Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (108 commits)
  bridge: ensure to unlock in error path in br_multicast_query().
  drivers/net/tulip/eeprom.c: fix bogus "(null)" in tulip init messages
  sky2: Avoid rtnl_unlock without rtnl_lock
  ipv6: Send netlink notification when DAD fails
  drivers/net/tg3.c: change the field used with the TG3_FLAG_10_100_ONLY constant
  ipconfig: Handle devices which take some time to come up.
  mac80211: Fix memory leak in ieee80211_if_write()
  mac80211: Fix (dynamic) power save entry
  ipw2200: use kmalloc for large local variables
  ath5k: read eeprom IQ calibration values correctly for G mode
  ath5k: fix I/Q calibration (for real)
  ath5k: fix TSF reset
  ath5k: use fixed antenna for tx descriptors
  libipw: split ieee->networks into small pieces
  mac80211: Fix sta_mtx unlocking on insert STA failure path
  rt2x00: remove KSEG1ADDR define from rt2x00soc.h
  net: add ColdFire support to the smc91x driver
  asix: fix setting mac address for AX88772
  ipv6 ip6_tunnel: eliminate unused recursion field from ip6_tnl{}.
  net: Fix dev_mc_add()
  ...
diff --git a/.gitignore b/.gitignore
index de6344e..a2939fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,13 +34,18 @@
 #
 # Top-level generic files
 #
-tags
-TAGS
-vmlinux
-vmlinuz
-System.map
-Module.markers
-Module.symvers
+/tags
+/TAGS
+/linux
+/vmlinux
+/vmlinuz
+/System.map
+/Module.markers
+/Module.symvers
+
+#
+# git files that we don't want to ignore even it they are dot-files
+#
 !.gitignore
 !.mailmap
 
diff --git a/Documentation/ABI/stable/sysfs-devices-node b/Documentation/ABI/stable/sysfs-devices-node
new file mode 100644
index 0000000..49b82ca
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-devices-node
@@ -0,0 +1,7 @@
+What:		/sys/devices/system/node/nodeX
+Date:		October 2002
+Contact:	Linux Memory Management list <linux-mm@kvack.org>
+Description:
+		When CONFIG_NUMA is enabled, this is a directory containing
+		information on node X such as what CPUs are local to the
+		node.
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index a07c0f3..a986e9b 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -159,3 +159,14 @@
 		device.  This is useful to ensure auto probing won't
 		match the driver to the device.  For example:
 		# echo "046d c315" > /sys/bus/usb/drivers/foo/remove_id
+
+What:		/sys/bus/usb/device/.../avoid_reset
+Date:		December 2009
+Contact:	Oliver Neukum <oliver@neukum.org>
+Description:
+		Writing 1 to this file tells the kernel that this
+		device will morph into another mode when it is reset.
+		Drivers will not use reset for error handling for
+		such devices.
+Users:
+		usb_modeswitch
diff --git a/Documentation/ABI/testing/sysfs-platform-asus-laptop b/Documentation/ABI/testing/sysfs-platform-asus-laptop
index a1cb660..1d77539 100644
--- a/Documentation/ABI/testing/sysfs-platform-asus-laptop
+++ b/Documentation/ABI/testing/sysfs-platform-asus-laptop
@@ -1,4 +1,4 @@
-What:		/sys/devices/platform/asus-laptop/display
+What:		/sys/devices/platform/asus_laptop/display
 Date:		January 2007
 KernelVersion:	2.6.20
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
@@ -13,7 +13,7 @@
 		Ex: - 0 (0000b) means no display
 		    - 3 (0011b) CRT+LCD.
 
-What:		/sys/devices/platform/asus-laptop/gps
+What:		/sys/devices/platform/asus_laptop/gps
 Date:		January 2007
 KernelVersion:	2.6.20
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
@@ -21,7 +21,7 @@
 		Control the gps device. 1 means on, 0 means off.
 Users:		Lapsus
 
-What:		/sys/devices/platform/asus-laptop/ledd
+What:		/sys/devices/platform/asus_laptop/ledd
 Date:		January 2007
 KernelVersion:	2.6.20
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
@@ -29,11 +29,11 @@
 		Some models like the W1N have a LED display that can be
 		used to display several informations.
 		To control the LED display, use the following :
-		    echo 0x0T000DDD > /sys/devices/platform/asus-laptop/
+		    echo 0x0T000DDD > /sys/devices/platform/asus_laptop/
 		where T control the 3 letters display, and DDD the 3 digits display.
 		The DDD table can be found in Documentation/laptops/asus-laptop.txt
 
-What:		/sys/devices/platform/asus-laptop/bluetooth
+What:		/sys/devices/platform/asus_laptop/bluetooth
 Date:		January 2007
 KernelVersion:	2.6.20
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
@@ -42,7 +42,7 @@
 		This may control the led, the device or both.
 Users:		Lapsus
 
-What:		/sys/devices/platform/asus-laptop/wlan
+What:		/sys/devices/platform/asus_laptop/wlan
 Date:		January 2007
 KernelVersion:	2.6.20
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
diff --git a/Documentation/ABI/testing/sysfs-platform-eeepc-laptop b/Documentation/ABI/testing/sysfs-platform-eeepc-laptop
index 7445dfb..5b026c6 100644
--- a/Documentation/ABI/testing/sysfs-platform-eeepc-laptop
+++ b/Documentation/ABI/testing/sysfs-platform-eeepc-laptop
@@ -1,4 +1,4 @@
-What:		/sys/devices/platform/eeepc-laptop/disp
+What:		/sys/devices/platform/eeepc/disp
 Date:		May 2008
 KernelVersion:	2.6.26
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
@@ -9,21 +9,21 @@
 		- 3 = LCD+CRT
 		If you run X11, you should use xrandr instead.
 
-What:		/sys/devices/platform/eeepc-laptop/camera
+What:		/sys/devices/platform/eeepc/camera
 Date:		May 2008
 KernelVersion:	2.6.26
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
 Description:
 		Control the camera. 1 means on, 0 means off.
 
-What:		/sys/devices/platform/eeepc-laptop/cardr
+What:		/sys/devices/platform/eeepc/cardr
 Date:		May 2008
 KernelVersion:	2.6.26
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
 Description:
 		Control the card reader. 1 means on, 0 means off.
 
-What:		/sys/devices/platform/eeepc-laptop/cpufv
+What:		/sys/devices/platform/eeepc/cpufv
 Date:		Jun 2009
 KernelVersion:	2.6.31
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
@@ -42,7 +42,7 @@
 		    `------------ Availables modes
 		For example, 0x301 means: mode 1 selected, 3 available modes.
 
-What:		/sys/devices/platform/eeepc-laptop/available_cpufv
+What:		/sys/devices/platform/eeepc/available_cpufv
 Date:		Jun 2009
 KernelVersion:	2.6.31
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 5aceb88..05e2ae2 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -4,20 +4,18 @@
         James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
 
 This document describes the DMA API.  For a more gentle introduction
-phrased in terms of the pci_ equivalents (and actual examples) see
-Documentation/PCI/PCI-DMA-mapping.txt.
+of the API (and actual examples) see
+Documentation/DMA-API-HOWTO.txt.
 
-This API is split into two pieces.  Part I describes the API and the
-corresponding pci_ API.  Part II describes the extensions to the API
-for supporting non-consistent memory machines.  Unless you know that
-your driver absolutely has to support non-consistent platforms (this
-is usually only legacy platforms) you should only use the API
-described in part I.
+This API is split into two pieces.  Part I describes the API.  Part II
+describes the extensions to the API for supporting non-consistent
+memory machines.  Unless you know that your driver absolutely has to
+support non-consistent platforms (this is usually only legacy
+platforms) you should only use the API described in part I.
 
-Part I - pci_ and dma_ Equivalent API 
+Part I - dma_ API
 -------------------------------------
 
-To get the pci_ API, you must #include <linux/pci.h>
 To get the dma_ API, you must #include <linux/dma-mapping.h>
 
 
@@ -27,9 +25,6 @@
 void *
 dma_alloc_coherent(struct device *dev, size_t size,
 			     dma_addr_t *dma_handle, gfp_t flag)
-void *
-pci_alloc_consistent(struct pci_dev *dev, size_t size,
-			     dma_addr_t *dma_handle)
 
 Consistent memory is memory for which a write by either the device or
 the processor can immediately be read by the processor or device
@@ -53,15 +48,11 @@
 The flag parameter (dma_alloc_coherent only) allows the caller to
 specify the GFP_ flags (see kmalloc) for the allocation (the
 implementation may choose to ignore flags that affect the location of
-the returned memory, like GFP_DMA).  For pci_alloc_consistent, you
-must assume GFP_ATOMIC behaviour.
+the returned memory, like GFP_DMA).
 
 void
 dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
 			   dma_addr_t dma_handle)
-void
-pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr,
-			   dma_addr_t dma_handle)
 
 Free the region of consistent memory you previously allocated.  dev,
 size and dma_handle must all be the same as those passed into the
@@ -89,10 +80,6 @@
 	dma_pool_create(const char *name, struct device *dev,
 			size_t size, size_t align, size_t alloc);
 
-	struct pci_pool *
-	pci_pool_create(const char *name, struct pci_device *dev,
-			size_t size, size_t align, size_t alloc);
-
 The pool create() routines initialize a pool of dma-coherent buffers
 for use with a given device.  It must be called in a context which
 can sleep.
@@ -108,9 +95,6 @@
 	void *dma_pool_alloc(struct dma_pool *pool, gfp_t gfp_flags,
 			dma_addr_t *dma_handle);
 
-	void *pci_pool_alloc(struct pci_pool *pool, gfp_t gfp_flags,
-			dma_addr_t *dma_handle);
-
 This allocates memory from the pool; the returned memory will meet the size
 and alignment requirements specified at creation time.  Pass GFP_ATOMIC to
 prevent blocking, or if it's permitted (not in_interrupt, not holding SMP locks),
@@ -122,9 +106,6 @@
 	void dma_pool_free(struct dma_pool *pool, void *vaddr,
 			dma_addr_t addr);
 
-	void pci_pool_free(struct pci_pool *pool, void *vaddr,
-			dma_addr_t addr);
-
 This puts memory back into the pool.  The pool is what was passed to
 the pool allocation routine; the cpu (vaddr) and dma addresses are what
 were returned when that routine allocated the memory being freed.
@@ -132,8 +113,6 @@
 
 	void dma_pool_destroy(struct dma_pool *pool);
 
-	void pci_pool_destroy(struct pci_pool *pool);
-
 The pool destroy() routines free the resources of the pool.  They must be
 called in a context which can sleep.  Make sure you've freed all allocated
 memory back to the pool before you destroy it.
@@ -144,8 +123,6 @@
 
 int
 dma_supported(struct device *dev, u64 mask)
-int
-pci_dma_supported(struct pci_dev *hwdev, u64 mask)
 
 Checks to see if the device can support DMA to the memory described by
 mask.
@@ -159,8 +136,14 @@
 
 int
 dma_set_mask(struct device *dev, u64 mask)
+
+Checks to see if the mask is possible and updates the device
+parameters if it is.
+
+Returns: 0 if successful and a negative error if not.
+
 int
-pci_set_dma_mask(struct pci_device *dev, u64 mask)
+dma_set_coherent_mask(struct device *dev, u64 mask)
 
 Checks to see if the mask is possible and updates the device
 parameters if it is.
@@ -187,9 +170,6 @@
 dma_addr_t
 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
 		      enum dma_data_direction direction)
-dma_addr_t
-pci_map_single(struct pci_dev *hwdev, void *cpu_addr, size_t size,
-		      int direction)
 
 Maps a piece of processor virtual memory so it can be accessed by the
 device and returns the physical handle of the memory.
@@ -198,14 +178,10 @@
 However the dma_ API uses a strongly typed enumerator for its
 direction:
 
-DMA_NONE		= PCI_DMA_NONE		no direction (used for
-						debugging)
-DMA_TO_DEVICE		= PCI_DMA_TODEVICE	data is going from the
-						memory to the device
-DMA_FROM_DEVICE		= PCI_DMA_FROMDEVICE	data is coming from
-						the device to the
-						memory
-DMA_BIDIRECTIONAL	= PCI_DMA_BIDIRECTIONAL	direction isn't known
+DMA_NONE		no direction (used for debugging)
+DMA_TO_DEVICE		data is going from the memory to the device
+DMA_FROM_DEVICE		data is coming from the device to the memory
+DMA_BIDIRECTIONAL	direction isn't known
 
 Notes:  Not all memory regions in a machine can be mapped by this
 API.  Further, regions that appear to be physically contiguous in
@@ -268,9 +244,6 @@
 void
 dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		 enum dma_data_direction direction)
-void
-pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
-		 size_t size, int direction)
 
 Unmaps the region previously mapped.  All the parameters passed in
 must be identical to those passed in (and returned) by the mapping
@@ -280,15 +253,9 @@
 dma_map_page(struct device *dev, struct page *page,
 		    unsigned long offset, size_t size,
 		    enum dma_data_direction direction)
-dma_addr_t
-pci_map_page(struct pci_dev *hwdev, struct page *page,
-		    unsigned long offset, size_t size, int direction)
 void
 dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
 	       enum dma_data_direction direction)
-void
-pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
-	       size_t size, int direction)
 
 API for mapping and unmapping for pages.  All the notes and warnings
 for the other mapping APIs apply here.  Also, although the <offset>
@@ -299,9 +266,6 @@
 int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 
-int
-pci_dma_mapping_error(struct pci_dev *hwdev, dma_addr_t dma_addr)
-
 In some circumstances dma_map_single and dma_map_page will fail to create
 a mapping. A driver can check for these errors by testing the returned
 dma address with dma_mapping_error(). A non-zero return value means the mapping
@@ -311,9 +275,6 @@
 	int
 	dma_map_sg(struct device *dev, struct scatterlist *sg,
 		int nents, enum dma_data_direction direction)
-	int
-	pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-		int nents, int direction)
 
 Returns: the number of physical segments mapped (this may be shorter
 than <nents> passed in if some elements of the scatter/gather list are
@@ -353,9 +314,6 @@
 	void
 	dma_unmap_sg(struct device *dev, struct scatterlist *sg,
 		int nhwentries, enum dma_data_direction direction)
-	void
-	pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-		int nents, int direction)
 
 Unmap the previously mapped scatter/gather list.  All the parameters
 must be the same as those and passed in to the scatter/gather mapping
@@ -365,21 +323,23 @@
 physical entries returned.
 
 void
-dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
-		enum dma_data_direction direction)
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+			enum dma_data_direction direction)
 void
-pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle,
-			   size_t size, int direction)
+dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
+			   enum dma_data_direction direction)
 void
-dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
-			  enum dma_data_direction direction)
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+		    enum dma_data_direction direction)
 void
-pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-		       int nelems, int direction)
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+		       enum dma_data_direction direction)
 
-Synchronise a single contiguous or scatter/gather mapping.  All the
-parameters must be the same as those passed into the single mapping
-API.
+Synchronise a single contiguous or scatter/gather mapping for the cpu
+and device. With the sync_sg API, all the parameters must be the same
+as those passed into the single mapping API. With the sync_single API,
+you can use dma_handle and size parameters that aren't identical to
+those passed into the single mapping API to do a partial sync.
 
 Notes:  You must do this:
 
@@ -461,9 +421,9 @@
 Part II - Advanced dma_ usage
 -----------------------------
 
-Warning: These pieces of the DMA API have no PCI equivalent.  They
-should also not be used in the majority of cases, since they cater for
-unlikely corner cases that don't belong in usual drivers.
+Warning: These pieces of the DMA API should not be used in the
+majority of cases, since they cater for unlikely corner cases that
+don't belong in usual drivers.
 
 If you don't understand how cache line coherency works between a
 processor and an I/O device, you should not be using this part of the
@@ -514,16 +474,6 @@
 of two for easy alignment.
 
 void
-dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
-		      unsigned long offset, size_t size,
-		      enum dma_data_direction direction)
-
-Does a partial sync, starting at offset and continuing for size.  You
-must be careful to observe the cache alignment and width when doing
-anything like this.  You must also be extra careful about accessing
-memory you intend to sync partially.
-
-void
 dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 	       enum dma_data_direction direction)
 
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index f9a6e2c..1b2dd4f 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -45,7 +45,7 @@
      </sect1>
 
      <sect1><title>Atomic and pointer manipulation</title>
-!Iarch/x86/include/asm/atomic_32.h
+!Iarch/x86/include/asm/atomic.h
 !Iarch/x86/include/asm/unaligned.h
      </sect1>
 
diff --git a/Documentation/DocBook/deviceiobook.tmpl b/Documentation/DocBook/deviceiobook.tmpl
index 3ed8812..c1ed6a4 100644
--- a/Documentation/DocBook/deviceiobook.tmpl
+++ b/Documentation/DocBook/deviceiobook.tmpl
@@ -316,7 +316,7 @@
 
   <chapter id="pubfunctions">
      <title>Public Functions Provided</title>
-!Iarch/x86/include/asm/io_32.h
+!Iarch/x86/include/asm/io.h
 !Elib/iomap.c
   </chapter>
 
diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl
index 5e7d84b..133cd6c 100644
--- a/Documentation/DocBook/mtdnand.tmpl
+++ b/Documentation/DocBook/mtdnand.tmpl
@@ -488,7 +488,7 @@
 				The ECC bytes must be placed immidiately after the data
 				bytes in order to make the syndrome generator work. This
 				is contrary to the usual layout used by software ECC. The
-				seperation of data and out of band area is not longer
+				separation of data and out of band area is not longer
 				possible. The nand driver code handles this layout and
 				the remaining free bytes in the oob area are managed by 
 				the autoplacement code. Provide a matching oob-layout
@@ -560,7 +560,7 @@
 				bad blocks. They have factory marked good blocks. The marker pattern
 				is erased when the block is erased to be reused. So in case of
 				powerloss before writing the pattern back to the chip this block 
-				would be lost and added to the bad blocks. Therefor we scan the 
+				would be lost and added to the bad blocks. Therefore we scan the 
 				chip(s) when we detect them the first time for good blocks and 
 				store this information in a bad block table before erasing any 
 				of the blocks.
@@ -1094,7 +1094,7 @@
 		manufacturers specifications. This applies similar to the spare area. 
 	</para>
 	<para>
-		Therefor NAND aware filesystems must either write in page size chunks
+		Therefore NAND aware filesystems must either write in page size chunks
 		or hold a writebuffer to collect smaller writes until they sum up to 
 		pagesize. Available NAND aware filesystems: JFFS2, YAFFS. 		
 	</para>
diff --git a/Documentation/DocBook/v4l/common.xml b/Documentation/DocBook/v4l/common.xml
index c65f0ac..cea23e1 100644
--- a/Documentation/DocBook/v4l/common.xml
+++ b/Documentation/DocBook/v4l/common.xml
@@ -1170,7 +1170,7 @@
 captured or output, applications can request frame skipping or
 duplicating on the driver side. This is especially useful when using
 the &func-read; or &func-write;, which are not augmented by timestamps
-or sequence counters, and to avoid unneccessary data copying.</para>
+or sequence counters, and to avoid unnecessary data copying.</para>
 
     <para>Finally these ioctls can be used to determine the number of
 buffers used internally by a driver in read/write mode. For
diff --git a/Documentation/DocBook/v4l/vidioc-g-parm.xml b/Documentation/DocBook/v4l/vidioc-g-parm.xml
index 78332d3..392aa9e 100644
--- a/Documentation/DocBook/v4l/vidioc-g-parm.xml
+++ b/Documentation/DocBook/v4l/vidioc-g-parm.xml
@@ -55,7 +55,7 @@
 duplicating on the driver side. This is especially useful when using
 the <function>read()</function> or <function>write()</function>, which
 are not augmented by timestamps or sequence counters, and to avoid
-unneccessary data copying.</para>
+unnecessary data copying.</para>
 
     <para>Further these ioctls can be used to determine the number of
 buffers used internally by a driver in read/write mode. For
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 8495fc9..f5395af 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -221,8 +221,8 @@
   - main 2.6.x kernel tree
   - 2.6.x.y -stable kernel tree
   - 2.6.x -git kernel patches
-  - 2.6.x -mm kernel patches
   - subsystem specific kernel trees and patches
+  - the 2.6.x -next kernel tree for integration tests
 
 2.6.x kernel tree
 -----------------
@@ -232,7 +232,7 @@
   - As soon as a new kernel is released a two weeks window is open,
     during this period of time maintainers can submit big diffs to
     Linus, usually the patches that have already been included in the
-    -mm kernel for a few weeks.  The preferred way to submit big changes
+    -next kernel for a few weeks.  The preferred way to submit big changes
     is using git (the kernel's source management tool, more information
     can be found at http://git.or.cz/) but plain patches are also just
     fine.
@@ -293,84 +293,43 @@
 experimental than -rc kernels since they are generated automatically
 without even a cursory glance to see if they are sane.
 
-2.6.x -mm kernel patches
-------------------------
-These are experimental kernel patches released by Andrew Morton.  Andrew
-takes all of the different subsystem kernel trees and patches and mushes
-them together, along with a lot of patches that have been plucked from
-the linux-kernel mailing list.  This tree serves as a proving ground for
-new features and patches.  Once a patch has proved its worth in -mm for
-a while Andrew or the subsystem maintainer pushes it on to Linus for
-inclusion in mainline.
-
-It is heavily encouraged that all new patches get tested in the -mm tree
-before they are sent to Linus for inclusion in the main kernel tree.  Code
-which does not make an appearance in -mm before the opening of the merge
-window will prove hard to merge into the mainline.
-
-These kernels are not appropriate for use on systems that are supposed
-to be stable and they are more risky to run than any of the other
-branches.
-
-If you wish to help out with the kernel development process, please test
-and use these kernel releases and provide feedback to the linux-kernel
-mailing list if you have any problems, and if everything works properly.
-
-In addition to all the other experimental patches, these kernels usually
-also contain any changes in the mainline -git kernels available at the
-time of release.
-
-The -mm kernels are not released on a fixed schedule, but usually a few
--mm kernels are released in between each -rc kernel (1 to 3 is common).
-
 Subsystem Specific kernel trees and patches
 -------------------------------------------
-A number of the different kernel subsystem developers expose their
-development trees so that others can see what is happening in the
-different areas of the kernel.  These trees are pulled into the -mm
-kernel releases as described above.
+The maintainers of the various kernel subsystems --- and also many
+kernel subsystem developers --- expose their current state of
+development in source repositories.  That way, others can see what is
+happening in the different areas of the kernel.  In areas where
+development is rapid, a developer may be asked to base his submissions
+onto such a subsystem kernel tree so that conflicts between the
+submission and other already ongoing work are avoided.
 
-Here is a list of some of the different kernel trees available:
-  git trees:
-    - Kbuild development tree, Sam Ravnborg <sam@ravnborg.org>
-	git.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
+Most of these repositories are git trees, but there are also other SCMs
+in use, or patch queues being published as quilt series.  Addresses of
+these subsystem repositories are listed in the MAINTAINERS file.  Many
+of them can be browsed at http://git.kernel.org/.
 
-    - ACPI development tree, Len Brown <len.brown@intel.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
+Before a proposed patch is committed to such a subsystem tree, it is
+subject to review which primarily happens on mailing lists (see the
+respective section below).  For several kernel subsystems, this review
+process is tracked with the tool patchwork.  Patchwork offers a web
+interface which shows patch postings, any comments on a patch or
+revisions to it, and maintainers can mark patches as under review,
+accepted, or rejected.  Most of these patchwork sites are listed at
+http://patchwork.kernel.org/ or http://patchwork.ozlabs.org/.
 
-    - Block development tree, Jens Axboe <jens.axboe@oracle.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
+2.6.x -next kernel tree for integration tests
+---------------------------------------------
+Before updates from subsystem trees are merged into the mainline 2.6.x
+tree, they need to be integration-tested.  For this purpose, a special
+testing repository exists into which virtually all subsystem trees are
+pulled on an almost daily basis:
+	http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
+	http://linux.f-seidel.de/linux-next/pmwiki/
 
-    - DRM development tree, Dave Airlie <airlied@linux.ie>
-	git.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
+This way, the -next kernel gives a summary outlook onto what will be
+expected to go into the mainline kernel at the next merge period.
+Adventurous testers are very welcome to runtime-test the -next kernel.
 
-    - ia64 development tree, Tony Luck <tony.luck@intel.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
-
-    - infiniband, Roland Dreier <rolandd@cisco.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
-
-    - libata, Jeff Garzik <jgarzik@pobox.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
-
-    - network drivers, Jeff Garzik <jgarzik@pobox.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
-
-    - pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
-	git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
-
-    - SCSI, James Bottomley <James.Bottomley@hansenpartnership.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
-
-    - x86, Ingo Molnar <mingo@elte.hu>
-	git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
-
-  quilt trees:
-    - USB, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
-	kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
-
-  Other kernel trees can be found listed at http://git.kernel.org/ and in
-  the MAINTAINERS file.
 
 Bug Reporting
 -------------
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
index bc38283..69dd29e 100644
--- a/Documentation/IPMI.txt
+++ b/Documentation/IPMI.txt
@@ -365,6 +365,7 @@
        regshifts=<shift1>,<shift2>,...
        slave_addrs=<addr1>,<addr2>,...
        force_kipmid=<enable1>,<enable2>,...
+       kipmid_max_busy_us=<ustime1>,<ustime2>,...
        unload_when_empty=[0|1]
 
 Each of these except si_trydefaults is a list, the first item for the
@@ -433,6 +434,7 @@
        ipmi_si.regshifts=<shift1>,<shift2>,...
        ipmi_si.slave_addrs=<addr1>,<addr2>,...
        ipmi_si.force_kipmid=<enable1>,<enable2>,...
+       ipmi_si.kipmid_max_busy_us=<ustime1>,<ustime2>,...
 
 It works the same as the module parameters of the same names.
 
@@ -450,6 +452,16 @@
 interrupts, the driver will run VERY slowly.  Don't blame me,
 these interfaces suck.
 
+Unfortunately, this thread can use a lot of CPU depending on the
+interface's performance.  This can waste a lot of CPU and cause
+various issues with detecting idle CPU and using extra power.  To
+avoid this, the kipmid_max_busy_us sets the maximum amount of time, in
+microseconds, that kipmid will spin before sleeping for a tick.  This
+value sets a balance between performance and CPU waste and needs to be
+tuned to your needs.  Maybe, someday, auto-tuning will be added, but
+that's not a simple thing and even the auto-tuning would need to be
+tuned to the user's desired performance.
+
 The driver supports a hot add and remove of interfaces.  This way,
 interfaces can be added or removed after the kernel is up and running.
 This is done using /sys/modules/ipmi_si/parameters/hotmod, which is a
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 94b9457..6fc7ea1 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -1,3 +1,3 @@
 obj-m := DocBook/ accounting/ auxdisplay/ connector/ \
-	filesystems/configfs/ ia64/ networking/ \
-	pcmcia/ spi/ video4linux/ vm/ watchdog/src/
+	filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \
+	pcmcia/ spi/ timers/ video4linux/ vm/ watchdog/src/
diff --git a/Documentation/PCI/PCI-DMA-mapping.txt b/Documentation/PCI/PCI-DMA-mapping.txt
index ecad88d..52618ab 100644
--- a/Documentation/PCI/PCI-DMA-mapping.txt
+++ b/Documentation/PCI/PCI-DMA-mapping.txt
@@ -1,12 +1,12 @@
-			Dynamic DMA mapping
-			===================
+		     Dynamic DMA mapping Guide
+		     =========================
 
 		 David S. Miller <davem@redhat.com>
 		 Richard Henderson <rth@cygnus.com>
 		  Jakub Jelinek <jakub@redhat.com>
 
-This document describes the DMA mapping system in terms of the pci_
-API.  For a similar API that works for generic devices, see
+This is a guide to device driver writers on how to use the DMA API
+with example pseudo-code.  For a concise description of the API, see
 DMA-API.txt.
 
 Most of the 64bit platforms have special hardware that translates bus
@@ -26,12 +26,15 @@
 transfer.
 
 The following API will work of course even on platforms where no such
-hardware exists, see e.g. arch/x86/include/asm/pci.h for how it is implemented on
-top of the virt_to_bus interface.
+hardware exists.
+
+Note that the DMA API works with any bus independent of the underlying
+microprocessor architecture. You should use the DMA API rather than
+the bus specific DMA API (e.g. pci_dma_*).
 
 First of all, you should make sure
 
-#include <linux/pci.h>
+#include <linux/dma-mapping.h>
 
 is in your driver. This file will obtain for you the definition of the
 dma_addr_t (which can hold any valid DMA address for the platform)
@@ -78,44 +81,43 @@
 			DMA addressing limitations
 
 Does your device have any DMA addressing limitations?  For example, is
-your device only capable of driving the low order 24-bits of address
-on the PCI bus for SAC DMA transfers?  If so, you need to inform the
-PCI layer of this fact.
+your device only capable of driving the low order 24-bits of address?
+If so, you need to inform the kernel of this fact.
 
 By default, the kernel assumes that your device can address the full
-32-bits in a SAC cycle.  For a 64-bit DAC capable device, this needs
-to be increased.  And for a device with limitations, as discussed in
-the previous paragraph, it needs to be decreased.
+32-bits.  For a 64-bit capable device, this needs to be increased.
+And for a device with limitations, as discussed in the previous
+paragraph, it needs to be decreased.
 
-pci_alloc_consistent() by default will return 32-bit DMA addresses.
-PCI-X specification requires PCI-X devices to support 64-bit
-addressing (DAC) for all transactions. And at least one platform (SGI
-SN2) requires 64-bit consistent allocations to operate correctly when
-the IO bus is in PCI-X mode. Therefore, like with pci_set_dma_mask(),
-it's good practice to call pci_set_consistent_dma_mask() to set the
-appropriate mask even if your device only supports 32-bit DMA
-(default) and especially if it's a PCI-X device.
+Special note about PCI: PCI-X specification requires PCI-X devices to
+support 64-bit addressing (DAC) for all transactions.  And at least
+one platform (SGI SN2) requires 64-bit consistent allocations to
+operate correctly when the IO bus is in PCI-X mode.
 
-For correct operation, you must interrogate the PCI layer in your
-device probe routine to see if the PCI controller on the machine can
-properly support the DMA addressing limitation your device has.  It is
-good style to do this even if your device holds the default setting,
+For correct operation, you must interrogate the kernel in your device
+probe routine to see if the DMA controller on the machine can properly
+support the DMA addressing limitation your device has.  It is good
+style to do this even if your device holds the default setting,
 because this shows that you did think about these issues wrt. your
 device.
 
-The query is performed via a call to pci_set_dma_mask():
+The query is performed via a call to dma_set_mask():
 
-	int pci_set_dma_mask(struct pci_dev *pdev, u64 device_mask);
+	int dma_set_mask(struct device *dev, u64 mask);
 
 The query for consistent allocations is performed via a call to
-pci_set_consistent_dma_mask():
+dma_set_coherent_mask():
 
-	int pci_set_consistent_dma_mask(struct pci_dev *pdev, u64 device_mask);
+	int dma_set_coherent_mask(struct device *dev, u64 mask);
 
-Here, pdev is a pointer to the PCI device struct of your device, and
-device_mask is a bit mask describing which bits of a PCI address your
-device supports.  It returns zero if your card can perform DMA
-properly on the machine given the address mask you provided.
+Here, dev is a pointer to the device struct of your device, and mask
+is a bit mask describing which bits of an address your device
+supports.  It returns zero if your card can perform DMA properly on
+the machine given the address mask you provided.  In general, the
+device struct of your device is embedded in the bus specific device
+struct of your device.  For example, a pointer to the device struct of
+your PCI device is pdev->dev (pdev is a pointer to the PCI device
+struct of your device).
 
 If it returns non-zero, your device cannot perform DMA properly on
 this platform, and attempting to do so will result in undefined
@@ -133,31 +135,30 @@
 even detected, you can ask them for the kernel messages to find out
 exactly why.
 
-The standard 32-bit addressing PCI device would do something like
-this:
+The standard 32-bit addressing device would do something like this:
 
-	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+	if (dma_set_mask(dev, DMA_BIT_MASK(32))) {
 		printk(KERN_WARNING
 		       "mydev: No suitable DMA available.\n");
 		goto ignore_this_device;
 	}
 
-Another common scenario is a 64-bit capable device.  The approach
-here is to try for 64-bit DAC addressing, but back down to a
-32-bit mask should that fail.  The PCI platform code may fail the
-64-bit mask not because the platform is not capable of 64-bit
-addressing.  Rather, it may fail in this case simply because
-32-bit SAC addressing is done more efficiently than DAC addressing.
-Sparc64 is one platform which behaves in this way.
+Another common scenario is a 64-bit capable device.  The approach here
+is to try for 64-bit addressing, but back down to a 32-bit mask that
+should not fail.  The kernel may fail the 64-bit mask not because the
+platform is not capable of 64-bit addressing.  Rather, it may fail in
+this case simply because 32-bit addressing is done more efficiently
+than 64-bit addressing.  For example, Sparc64 PCI SAC addressing is
+more efficient than DAC addressing.
 
 Here is how you would handle a 64-bit capable device which can drive
 all 64-bits when accessing streaming DMA:
 
 	int using_dac;
 
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+	if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
 		using_dac = 1;
-	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+	} else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
 		using_dac = 0;
 	} else {
 		printk(KERN_WARNING
@@ -170,36 +171,36 @@
 
 	int using_dac, consistent_using_dac;
 
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+	if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
 		using_dac = 1;
 	   	consistent_using_dac = 1;
-		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
-	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+		dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
+	} else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
 		using_dac = 0;
 		consistent_using_dac = 0;
-		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+		dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
 	} else {
 		printk(KERN_WARNING
 		       "mydev: No suitable DMA available.\n");
 		goto ignore_this_device;
 	}
 
-pci_set_consistent_dma_mask() will always be able to set the same or a
-smaller mask as pci_set_dma_mask(). However for the rare case that a
+dma_set_coherent_mask() will always be able to set the same or a
+smaller mask as dma_set_mask(). However for the rare case that a
 device driver only uses consistent allocations, one would have to
-check the return value from pci_set_consistent_dma_mask().
+check the return value from dma_set_coherent_mask().
 
 Finally, if your device can only drive the low 24-bits of
-address during PCI bus mastering you might do something like:
+address you might do something like:
 
-	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(24))) {
+	if (dma_set_mask(dev, DMA_BIT_MASK(24))) {
 		printk(KERN_WARNING
 		       "mydev: 24-bit DMA addressing not available.\n");
 		goto ignore_this_device;
 	}
 
-When pci_set_dma_mask() is successful, and returns zero, the PCI layer
-saves away this mask you have provided.  The PCI layer will use this
+When dma_set_mask() is successful, and returns zero, the kernel saves
+away this mask you have provided.  The kernel will use this
 information later when you make DMA mappings.
 
 There is a case which we are aware of at this time, which is worth
@@ -208,7 +209,7 @@
 functions) and the various different functions have _different_
 DMA addressing limitations, you may wish to probe each mask and
 only provide the functionality which the machine can handle.  It
-is important that the last call to pci_set_dma_mask() be for the
+is important that the last call to dma_set_mask() be for the
 most specific mask.
 
 Here is pseudo-code showing how this might be done:
@@ -217,17 +218,17 @@
 	#define RECORD_ADDRESS_BITS	DMA_BIT_MASK(24)
 
 	struct my_sound_card *card;
-	struct pci_dev *pdev;
+	struct device *dev;
 
 	...
-	if (!pci_set_dma_mask(pdev, PLAYBACK_ADDRESS_BITS)) {
+	if (!dma_set_mask(dev, PLAYBACK_ADDRESS_BITS)) {
 		card->playback_enabled = 1;
 	} else {
 		card->playback_enabled = 0;
 		printk(KERN_WARNING "%s: Playback disabled due to DMA limitations.\n",
 		       card->name);
 	}
-	if (!pci_set_dma_mask(pdev, RECORD_ADDRESS_BITS)) {
+	if (!dma_set_mask(dev, RECORD_ADDRESS_BITS)) {
 		card->record_enabled = 1;
 	} else {
 		card->record_enabled = 0;
@@ -252,8 +253,8 @@
   Think of "consistent" as "synchronous" or "coherent".
 
   The current default is to return consistent memory in the low 32
-  bits of the PCI bus space.  However, for future compatibility you
-  should set the consistent mask even if this default is fine for your
+  bits of the bus space.  However, for future compatibility you should
+  set the consistent mask even if this default is fine for your
   driver.
 
   Good examples of what to use consistent mappings for are:
@@ -285,9 +286,9 @@
 	     found in PCI bridges (such as by reading a register's value
 	     after writing it).
 
-- Streaming DMA mappings which are usually mapped for one DMA transfer,
-  unmapped right after it (unless you use pci_dma_sync_* below) and for which
-  hardware can optimize for sequential accesses.
+- Streaming DMA mappings which are usually mapped for one DMA
+  transfer, unmapped right after it (unless you use dma_sync_* below)
+  and for which hardware can optimize for sequential accesses.
 
   This of "streaming" as "asynchronous" or "outside the coherency
   domain".
@@ -302,8 +303,8 @@
   optimizations the hardware allows.  To this end, when using
   such mappings you must be explicit about what you want to happen.
 
-Neither type of DMA mapping has alignment restrictions that come
-from PCI, although some devices may have such restrictions.
+Neither type of DMA mapping has alignment restrictions that come from
+the underlying bus, although some devices may have such restrictions.
 Also, systems with caches that aren't DMA-coherent will work better
 when the underlying buffers don't share cache lines with other data.
 
@@ -315,33 +316,27 @@
 
 	dma_addr_t dma_handle;
 
-	cpu_addr = pci_alloc_consistent(pdev, size, &dma_handle);
+	cpu_addr = dma_alloc_coherent(dev, size, &dma_handle, gfp);
 
-where pdev is a struct pci_dev *. This may be called in interrupt context.
-You should use dma_alloc_coherent (see DMA-API.txt) for buses
-where devices don't have struct pci_dev (like ISA, EISA).
-
-This argument is needed because the DMA translations may be bus
-specific (and often is private to the bus which the device is attached
-to).
+where device is a struct device *. This may be called in interrupt
+context with the GFP_ATOMIC flag.
 
 Size is the length of the region you want to allocate, in bytes.
 
 This routine will allocate RAM for that region, so it acts similarly to
 __get_free_pages (but takes size instead of a page order).  If your
 driver needs regions sized smaller than a page, you may prefer using
-the pci_pool interface, described below.
+the dma_pool interface, described below.
 
-The consistent DMA mapping interfaces, for non-NULL pdev, will by
-default return a DMA address which is SAC (Single Address Cycle)
-addressable.  Even if the device indicates (via PCI dma mask) that it
-may address the upper 32-bits and thus perform DAC cycles, consistent
-allocation will only return > 32-bit PCI addresses for DMA if the
-consistent dma mask has been explicitly changed via
-pci_set_consistent_dma_mask().  This is true of the pci_pool interface
-as well.
+The consistent DMA mapping interfaces, for non-NULL dev, will by
+default return a DMA address which is 32-bit addressable.  Even if the
+device indicates (via DMA mask) that it may address the upper 32-bits,
+consistent allocation will only return > 32-bit addresses for DMA if
+the consistent DMA mask has been explicitly changed via
+dma_set_coherent_mask().  This is true of the dma_pool interface as
+well.
 
-pci_alloc_consistent returns two values: the virtual address which you
+dma_alloc_coherent returns two values: the virtual address which you
 can use to access it from the CPU and dma_handle which you pass to the
 card.
 
@@ -354,54 +349,54 @@
 
 To unmap and free such a DMA region, you call:
 
-	pci_free_consistent(pdev, size, cpu_addr, dma_handle);
+	dma_free_coherent(dev, size, cpu_addr, dma_handle);
 
-where pdev, size are the same as in the above call and cpu_addr and
-dma_handle are the values pci_alloc_consistent returned to you.
+where dev, size are the same as in the above call and cpu_addr and
+dma_handle are the values dma_alloc_coherent returned to you.
 This function may not be called in interrupt context.
 
 If your driver needs lots of smaller memory regions, you can write
-custom code to subdivide pages returned by pci_alloc_consistent,
-or you can use the pci_pool API to do that.  A pci_pool is like
-a kmem_cache, but it uses pci_alloc_consistent not __get_free_pages.
+custom code to subdivide pages returned by dma_alloc_coherent,
+or you can use the dma_pool API to do that.  A dma_pool is like
+a kmem_cache, but it uses dma_alloc_coherent not __get_free_pages.
 Also, it understands common hardware constraints for alignment,
 like queue heads needing to be aligned on N byte boundaries.
 
-Create a pci_pool like this:
+Create a dma_pool like this:
 
-	struct pci_pool *pool;
+	struct dma_pool *pool;
 
-	pool = pci_pool_create(name, pdev, size, align, alloc);
+	pool = dma_pool_create(name, dev, size, align, alloc);
 
-The "name" is for diagnostics (like a kmem_cache name); pdev and size
+The "name" is for diagnostics (like a kmem_cache name); dev and size
 are as above.  The device's hardware alignment requirement for this
 type of data is "align" (which is expressed in bytes, and must be a
 power of two).  If your device has no boundary crossing restrictions,
 pass 0 for alloc; passing 4096 says memory allocated from this pool
 must not cross 4KByte boundaries (but at that time it may be better to
-go for pci_alloc_consistent directly instead).
+go for dma_alloc_coherent directly instead).
 
-Allocate memory from a pci pool like this:
+Allocate memory from a dma pool like this:
 
-	cpu_addr = pci_pool_alloc(pool, flags, &dma_handle);
+	cpu_addr = dma_pool_alloc(pool, flags, &dma_handle);
 
 flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor
-holding SMP locks), SLAB_ATOMIC otherwise.  Like pci_alloc_consistent,
+holding SMP locks), SLAB_ATOMIC otherwise.  Like dma_alloc_coherent,
 this returns two values, cpu_addr and dma_handle.
 
-Free memory that was allocated from a pci_pool like this:
+Free memory that was allocated from a dma_pool like this:
 
-	pci_pool_free(pool, cpu_addr, dma_handle);
+	dma_pool_free(pool, cpu_addr, dma_handle);
 
-where pool is what you passed to pci_pool_alloc, and cpu_addr and
-dma_handle are the values pci_pool_alloc returned. This function
+where pool is what you passed to dma_pool_alloc, and cpu_addr and
+dma_handle are the values dma_pool_alloc returned. This function
 may be called in interrupt context.
 
-Destroy a pci_pool by calling:
+Destroy a dma_pool by calling:
 
-	pci_pool_destroy(pool);
+	dma_pool_destroy(pool);
 
-Make sure you've called pci_pool_free for all memory allocated
+Make sure you've called dma_pool_free for all memory allocated
 from a pool before you destroy the pool. This function may not
 be called in interrupt context.
 
@@ -411,15 +406,15 @@
 take a DMA direction argument, which is an integer and takes on
 one of the following values:
 
- PCI_DMA_BIDIRECTIONAL
- PCI_DMA_TODEVICE
- PCI_DMA_FROMDEVICE
- PCI_DMA_NONE
+ DMA_BIDIRECTIONAL
+ DMA_TO_DEVICE
+ DMA_FROM_DEVICE
+ DMA_NONE
 
 One should provide the exact DMA direction if you know it.
 
-PCI_DMA_TODEVICE means "from main memory to the PCI device"
-PCI_DMA_FROMDEVICE means "from the PCI device to main memory"
+DMA_TO_DEVICE means "from main memory to the device"
+DMA_FROM_DEVICE means "from the device to main memory"
 It is the direction in which the data moves during the DMA
 transfer.
 
@@ -427,12 +422,12 @@
 as you possibly can.
 
 If you absolutely cannot know the direction of the DMA transfer,
-specify PCI_DMA_BIDIRECTIONAL.  It means that the DMA can go in
+specify DMA_BIDIRECTIONAL.  It means that the DMA can go in
 either direction.  The platform guarantees that you may legally
 specify this, and that it will work, but this may be at the
 cost of performance for example.
 
-The value PCI_DMA_NONE is to be used for debugging.  One can
+The value DMA_NONE is to be used for debugging.  One can
 hold this in a data structure before you come to know the
 precise direction, and this will help catch cases where your
 direction tracking logic has failed to set things up properly.
@@ -442,21 +437,21 @@
 Some platforms actually have a write permission boolean which DMA
 mappings can be marked with, much like page protections in the user
 program address space.  Such platforms can and do report errors in the
-kernel logs when the PCI controller hardware detects violation of the
+kernel logs when the DMA controller hardware detects violation of the
 permission setting.
 
 Only streaming mappings specify a direction, consistent mappings
 implicitly have a direction attribute setting of
-PCI_DMA_BIDIRECTIONAL.
+DMA_BIDIRECTIONAL.
 
 The SCSI subsystem tells you the direction to use in the
 'sc_data_direction' member of the SCSI command your driver is
 working on.
 
 For Networking drivers, it's a rather simple affair.  For transmit
-packets, map/unmap them with the PCI_DMA_TODEVICE direction
+packets, map/unmap them with the DMA_TO_DEVICE direction
 specifier.  For receive packets, just the opposite, map/unmap them
-with the PCI_DMA_FROMDEVICE direction specifier.
+with the DMA_FROM_DEVICE direction specifier.
 
 		  Using Streaming DMA mappings
 
@@ -467,43 +462,43 @@
 
 To map a single region, you do:
 
-	struct pci_dev *pdev = mydev->pdev;
+	struct device *dev = &my_dev->dev;
 	dma_addr_t dma_handle;
 	void *addr = buffer->ptr;
 	size_t size = buffer->len;
 
-	dma_handle = pci_map_single(pdev, addr, size, direction);
+	dma_handle = dma_map_single(dev, addr, size, direction);
 
 and to unmap it:
 
-	pci_unmap_single(pdev, dma_handle, size, direction);
+	dma_unmap_single(dev, dma_handle, size, direction);
 
-You should call pci_unmap_single when the DMA activity is finished, e.g.
+You should call dma_unmap_single when the DMA activity is finished, e.g.
 from the interrupt which told you that the DMA transfer is done.
 
 Using cpu pointers like this for single mappings has a disadvantage,
 you cannot reference HIGHMEM memory in this way.  Thus, there is a
-map/unmap interface pair akin to pci_{map,unmap}_single.  These
+map/unmap interface pair akin to dma_{map,unmap}_single.  These
 interfaces deal with page/offset pairs instead of cpu pointers.
 Specifically:
 
-	struct pci_dev *pdev = mydev->pdev;
+	struct device *dev = &my_dev->dev;
 	dma_addr_t dma_handle;
 	struct page *page = buffer->page;
 	unsigned long offset = buffer->offset;
 	size_t size = buffer->len;
 
-	dma_handle = pci_map_page(pdev, page, offset, size, direction);
+	dma_handle = dma_map_page(dev, page, offset, size, direction);
 
 	...
 
-	pci_unmap_page(pdev, dma_handle, size, direction);
+	dma_unmap_page(dev, dma_handle, size, direction);
 
 Here, "offset" means byte offset within the given page.
 
 With scatterlists, you map a region gathered from several regions by:
 
-	int i, count = pci_map_sg(pdev, sglist, nents, direction);
+	int i, count = dma_map_sg(dev, sglist, nents, direction);
 	struct scatterlist *sg;
 
 	for_each_sg(sglist, sg, count, i) {
@@ -527,16 +522,16 @@
 
 To unmap a scatterlist, just call:
 
-	pci_unmap_sg(pdev, sglist, nents, direction);
+	dma_unmap_sg(dev, sglist, nents, direction);
 
 Again, make sure DMA activity has already finished.
 
-PLEASE NOTE:  The 'nents' argument to the pci_unmap_sg call must be
-              the _same_ one you passed into the pci_map_sg call,
+PLEASE NOTE:  The 'nents' argument to the dma_unmap_sg call must be
+              the _same_ one you passed into the dma_map_sg call,
 	      it should _NOT_ be the 'count' value _returned_ from the
-              pci_map_sg call.
+              dma_map_sg call.
 
-Every pci_map_{single,sg} call should have its pci_unmap_{single,sg}
+Every dma_map_{single,sg} call should have its dma_unmap_{single,sg}
 counterpart, because the bus address space is a shared resource (although
 in some ports the mapping is per each BUS so less devices contend for the
 same bus address space) and you could render the machine unusable by eating
@@ -547,14 +542,14 @@
 properly in order for the cpu and device to see the most uptodate and
 correct copy of the DMA buffer.
 
-So, firstly, just map it with pci_map_{single,sg}, and after each DMA
+So, firstly, just map it with dma_map_{single,sg}, and after each DMA
 transfer call either:
 
-	pci_dma_sync_single_for_cpu(pdev, dma_handle, size, direction);
+	dma_sync_single_for_cpu(dev, dma_handle, size, direction);
 
 or:
 
-	pci_dma_sync_sg_for_cpu(pdev, sglist, nents, direction);
+	dma_sync_sg_for_cpu(dev, sglist, nents, direction);
 
 as appropriate.
 
@@ -562,27 +557,27 @@
 finish accessing the data with the cpu, and then before actually
 giving the buffer to the hardware call either:
 
-	pci_dma_sync_single_for_device(pdev, dma_handle, size, direction);
+	dma_sync_single_for_device(dev, dma_handle, size, direction);
 
 or:
 
-	pci_dma_sync_sg_for_device(dev, sglist, nents, direction);
+	dma_sync_sg_for_device(dev, sglist, nents, direction);
 
 as appropriate.
 
 After the last DMA transfer call one of the DMA unmap routines
-pci_unmap_{single,sg}. If you don't touch the data from the first pci_map_*
-call till pci_unmap_*, then you don't have to call the pci_dma_sync_*
+dma_unmap_{single,sg}. If you don't touch the data from the first dma_map_*
+call till dma_unmap_*, then you don't have to call the dma_sync_*
 routines at all.
 
 Here is pseudo code which shows a situation in which you would need
-to use the pci_dma_sync_*() interfaces.
+to use the dma_sync_*() interfaces.
 
 	my_card_setup_receive_buffer(struct my_card *cp, char *buffer, int len)
 	{
 		dma_addr_t mapping;
 
-		mapping = pci_map_single(cp->pdev, buffer, len, PCI_DMA_FROMDEVICE);
+		mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE);
 
 		cp->rx_buf = buffer;
 		cp->rx_len = len;
@@ -606,25 +601,25 @@
 			 * the DMA transfer with the CPU first
 			 * so that we see updated contents.
 			 */
-			pci_dma_sync_single_for_cpu(cp->pdev, cp->rx_dma,
-						    cp->rx_len,
-						    PCI_DMA_FROMDEVICE);
+			dma_sync_single_for_cpu(&cp->dev, cp->rx_dma,
+						cp->rx_len,
+						DMA_FROM_DEVICE);
 
 			/* Now it is safe to examine the buffer. */
 			hp = (struct my_card_header *) cp->rx_buf;
 			if (header_is_ok(hp)) {
-				pci_unmap_single(cp->pdev, cp->rx_dma, cp->rx_len,
-						 PCI_DMA_FROMDEVICE);
+				dma_unmap_single(&cp->dev, cp->rx_dma, cp->rx_len,
+						 DMA_FROM_DEVICE);
 				pass_to_upper_layers(cp->rx_buf);
 				make_and_setup_new_rx_buf(cp);
 			} else {
 				/* Just sync the buffer and give it back
 				 * to the card.
 				 */
-				pci_dma_sync_single_for_device(cp->pdev,
-							       cp->rx_dma,
-							       cp->rx_len,
-							       PCI_DMA_FROMDEVICE);
+				dma_sync_single_for_device(&cp->dev,
+							   cp->rx_dma,
+							   cp->rx_len,
+							   DMA_FROM_DEVICE);
 				give_rx_buf_to_card(cp);
 			}
 		}
@@ -634,19 +629,19 @@
 longer, nor should they use bus_to_virt. Some drivers have to be changed a
 little bit, because there is no longer an equivalent to bus_to_virt in the
 dynamic DMA mapping scheme - you have to always store the DMA addresses
-returned by the pci_alloc_consistent, pci_pool_alloc, and pci_map_single
-calls (pci_map_sg stores them in the scatterlist itself if the platform
+returned by the dma_alloc_coherent, dma_pool_alloc, and dma_map_single
+calls (dma_map_sg stores them in the scatterlist itself if the platform
 supports dynamic DMA mapping in hardware) in your driver structures and/or
 in the card registers.
 
-All PCI drivers should be using these interfaces with no exceptions.
-It is planned to completely remove virt_to_bus() and bus_to_virt() as
+All drivers should be using these interfaces with no exceptions.  It
+is planned to completely remove virt_to_bus() and bus_to_virt() as
 they are entirely deprecated.  Some ports already do not provide these
 as it is impossible to correctly support them.
 
 		Optimizing Unmap State Space Consumption
 
-On many platforms, pci_unmap_{single,page}() is simply a nop.
+On many platforms, dma_unmap_{single,page}() is simply a nop.
 Therefore, keeping track of the mapping address and length is a waste
 of space.  Instead of filling your drivers up with ifdefs and the like
 to "work around" this (which would defeat the whole purpose of a
@@ -655,7 +650,7 @@
 Actually, instead of describing the macros one by one, we'll
 transform some example code.
 
-1) Use DECLARE_PCI_UNMAP_{ADDR,LEN} in state saving structures.
+1) Use DEFINE_DMA_UNMAP_{ADDR,LEN} in state saving structures.
    Example, before:
 
 	struct ring_state {
@@ -668,14 +663,11 @@
 
 	struct ring_state {
 		struct sk_buff *skb;
-		DECLARE_PCI_UNMAP_ADDR(mapping)
-		DECLARE_PCI_UNMAP_LEN(len)
+		DEFINE_DMA_UNMAP_ADDR(mapping);
+		DEFINE_DMA_UNMAP_LEN(len);
 	};
 
-   NOTE: DO NOT put a semicolon at the end of the DECLARE_*()
-         macro.
-
-2) Use pci_unmap_{addr,len}_set to set these values.
+2) Use dma_unmap_{addr,len}_set to set these values.
    Example, before:
 
 	ringp->mapping = FOO;
@@ -683,21 +675,21 @@
 
    after:
 
-	pci_unmap_addr_set(ringp, mapping, FOO);
-	pci_unmap_len_set(ringp, len, BAR);
+	dma_unmap_addr_set(ringp, mapping, FOO);
+	dma_unmap_len_set(ringp, len, BAR);
 
-3) Use pci_unmap_{addr,len} to access these values.
+3) Use dma_unmap_{addr,len} to access these values.
    Example, before:
 
-	pci_unmap_single(pdev, ringp->mapping, ringp->len,
-			 PCI_DMA_FROMDEVICE);
+	dma_unmap_single(dev, ringp->mapping, ringp->len,
+			 DMA_FROM_DEVICE);
 
    after:
 
-	pci_unmap_single(pdev,
-			 pci_unmap_addr(ringp, mapping),
-			 pci_unmap_len(ringp, len),
-			 PCI_DMA_FROMDEVICE);
+	dma_unmap_single(dev,
+			 dma_unmap_addr(ringp, mapping),
+			 dma_unmap_len(ringp, len),
+			 DMA_FROM_DEVICE);
 
 It really should be self-explanatory.  We treat the ADDR and LEN
 separately, because it is possible for an implementation to only
@@ -732,15 +724,15 @@
 DMA address space is limited on some architectures and an allocation
 failure can be determined by:
 
-- checking if pci_alloc_consistent returns NULL or pci_map_sg returns 0
+- checking if dma_alloc_coherent returns NULL or dma_map_sg returns 0
 
-- checking the returned dma_addr_t of pci_map_single and pci_map_page
-  by using pci_dma_mapping_error():
+- checking the returned dma_addr_t of dma_map_single and dma_map_page
+  by using dma_mapping_error():
 
 	dma_addr_t dma_handle;
 
-	dma_handle = pci_map_single(pdev, addr, size, direction);
-	if (pci_dma_mapping_error(pdev, dma_handle)) {
+	dma_handle = dma_map_single(dev, addr, size, direction);
+	if (dma_mapping_error(dev, dma_handle)) {
 		/*
 		 * reduce current DMA mapping usage,
 		 * delay and try again later or
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 1053a56..8916ca4 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -9,10 +9,14 @@
 kernel patches.
 
 
-1: Builds cleanly with applicable or modified CONFIG options =y, =m, and
+1: If you use a facility then #include the file that defines/declares
+   that facility.  Don't depend on other header files pulling in ones
+   that you use.
+
+2: Builds cleanly with applicable or modified CONFIG options =y, =m, and
    =n.  No gcc warnings/errors, no linker warnings/errors.
 
-2: Passes allnoconfig, allmodconfig
+2b: Passes allnoconfig, allmodconfig
 
 3: Builds on multiple CPU architectures by using local cross-compile tools
    or some other build farm.
diff --git a/Documentation/arm/Samsung-S3C24XX/CPUfreq.txt b/Documentation/arm/Samsung-S3C24XX/CPUfreq.txt
index 76b3a11..fa968aa 100644
--- a/Documentation/arm/Samsung-S3C24XX/CPUfreq.txt
+++ b/Documentation/arm/Samsung-S3C24XX/CPUfreq.txt
@@ -14,8 +14,8 @@
  how the clocks are arranged. The first implementation used as single
  PLL to feed the ARM, memory and peripherals via a series of dividers
  and muxes and this is the implementation that is documented here. A
- newer version where there is a seperate PLL and clock divider for the
- ARM core is available as a seperate driver.
+ newer version where there is a separate PLL and clock divider for the
+ ARM core is available as a separate driver.
 
 
 Layout
diff --git a/Documentation/arm/Samsung/Overview.txt b/Documentation/arm/Samsung/Overview.txt
new file mode 100644
index 0000000..7cced1f
--- /dev/null
+++ b/Documentation/arm/Samsung/Overview.txt
@@ -0,0 +1,86 @@
+		Samsung ARM Linux Overview
+		==========================
+
+Introduction
+------------
+
+  The Samsung range of ARM SoCs spans many similar devices, from the initial
+  ARM9 through to the newest ARM cores. This document shows an overview of
+  the current kernel support, how to use it and where to find the code
+  that supports this.
+
+  The currently supported SoCs are:
+
+  - S3C24XX: See Documentation/arm/Samsung-S3C24XX/Overview.txt for full list
+  - S3C64XX: S3C6400 and S3C6410
+  - S5PC6440
+
+  S5PC100 and S5PC110 support is currently being merged
+
+
+S3C24XX Systems
+---------------
+
+  There is still documentation in Documnetation/arm/Samsung-S3C24XX/ which
+  deals with the architecture and drivers specific to these devices.
+
+  See Documentation/arm/Samsung-S3C24XX/Overview.txt for more information
+  on the implementation details and specific support.
+
+
+Configuration
+-------------
+
+  A number of configurations are supplied, as there is no current way of
+  unifying all the SoCs into one kernel.
+
+  s5p6440_defconfig - S5P6440 specific default configuration
+  s5pc100_defconfig - S5PC100 specific default configuration
+
+
+Layout
+------
+
+  The directory layout is currently being restructured, and consists of
+  several platform directories and then the machine specific directories
+  of the CPUs being built for.
+
+  plat-samsung provides the base for all the implementations, and is the
+  last in the line of include directories that are processed for the build
+  specific information. It contains the base clock, GPIO and device definitions
+  to get the system running.
+
+  plat-s3c is the s3c24xx/s3c64xx platform directory, although it is currently
+  involved in other builds this will be phased out once the relevant code is
+  moved elsewhere.
+
+  plat-s3c24xx is for s3c24xx specific builds, see the S3C24XX docs.
+
+  plat-s3c64xx is for the s3c64xx specific bits, see the S3C24XX docs.
+
+  plat-s5p is for s5p specific builds, more to be added.
+
+
+  [ to finish ]
+
+
+Port Contributors
+-----------------
+
+  Ben Dooks (BJD)
+  Vincent Sanders
+  Herbert Potzl
+  Arnaud Patard (RTP)
+  Roc Wu
+  Klaus Fetscher
+  Dimitry Andric
+  Shannon Holland
+  Guillaume Gourat (NexVision)
+  Christer Weinigel (wingel) (Acer N30)
+  Lucas Correia Villa Real (S3C2400 port)
+
+
+Document Author
+---------------
+
+Copyright 2009-2010 Ben Dooks <ben-linux@fluff.org>
diff --git a/Documentation/arm/Samsung/clksrc-change-registers.awk b/Documentation/arm/Samsung/clksrc-change-registers.awk
new file mode 100755
index 0000000..0c50220
--- /dev/null
+++ b/Documentation/arm/Samsung/clksrc-change-registers.awk
@@ -0,0 +1,167 @@
+#!/usr/bin/awk -f
+#
+# Copyright 2010 Ben Dooks <ben-linux@fluff.org>
+#
+# Released under GPLv2
+
+# example usage
+# ./clksrc-change-registers.awk arch/arm/plat-s5pc1xx/include/plat/regs-clock.h < src > dst
+
+function extract_value(s)
+{
+    eqat = index(s, "=")
+    comat = index(s, ",")
+    return substr(s, eqat+2, (comat-eqat)-2)
+}
+
+function remove_brackets(b)
+{
+    return substr(b, 2, length(b)-2)
+}
+
+function splitdefine(l, p)
+{
+    r = split(l, tp)
+
+    p[0] = tp[2]
+    p[1] = remove_brackets(tp[3])
+}
+
+function find_length(f)
+{
+    if (0)
+	printf "find_length " f "\n" > "/dev/stderr"
+
+    if (f ~ /0x1/)
+	return 1
+    else if (f ~ /0x3/)
+	return 2
+    else if (f ~ /0x7/)
+	return 3
+    else if (f ~ /0xf/)
+	return 4
+
+    printf "unknown legnth " f "\n" > "/dev/stderr"
+    exit
+}
+
+function find_shift(s)
+{
+    id = index(s, "<")
+    if (id <= 0) {
+	printf "cannot find shift " s "\n" > "/dev/stderr"
+	exit
+    }
+
+    return substr(s, id+2)
+}
+
+
+BEGIN {
+    if (ARGC < 2) {
+	print "too few arguments" > "/dev/stderr"
+	exit
+    }
+
+# read the header file and find the mask values that we will need
+# to replace and create an associative array of values
+
+    while (getline line < ARGV[1] > 0) {
+	if (line ~ /\#define.*_MASK/ &&
+	    !(line ~ /S5PC100_EPLL_MASK/) &&
+	    !(line ~ /USB_SIG_MASK/)) {
+	    splitdefine(line, fields)
+	    name = fields[0]
+	    if (0)
+		printf "MASK " line "\n" > "/dev/stderr"
+	    dmask[name,0] = find_length(fields[1])
+	    dmask[name,1] = find_shift(fields[1])
+	    if (0)
+		printf "=> '" name "' LENGTH=" dmask[name,0] " SHIFT=" dmask[name,1] "\n" > "/dev/stderr"
+	} else {
+	}
+    }
+
+    delete ARGV[1]
+}
+
+/clksrc_clk.*=.*{/ {
+    shift=""
+    mask=""
+    divshift=""
+    reg_div=""
+    reg_src=""
+    indent=1
+
+    print $0
+
+    for(; indent >= 1;) {
+	if ((getline line) <= 0) {
+	    printf "unexpected end of file" > "/dev/stderr"
+	    exit 1;
+	}
+
+	if (line ~ /\.shift/) {
+	    shift = extract_value(line)
+	} else if (line ~ /\.mask/) {
+	    mask = extract_value(line)
+	} else if (line ~ /\.reg_divider/) {
+	    reg_div = extract_value(line)
+	} else if (line ~ /\.reg_source/) {
+	    reg_src = extract_value(line)
+	} else if (line ~ /\.divider_shift/) {
+	    divshift = extract_value(line)
+	} else if (line ~ /{/) {
+		indent++
+		print line
+	    } else if (line ~ /}/) {
+	    indent--
+
+	    if (indent == 0) {
+		if (0) {
+		    printf "shift '" shift   "' ='" dmask[shift,0] "'\n" > "/dev/stderr"
+		    printf "mask  '" mask    "'\n" > "/dev/stderr"
+		    printf "dshft '" divshift "'\n" > "/dev/stderr"
+		    printf "rdiv  '" reg_div "'\n" > "/dev/stderr"
+		    printf "rsrc  '" reg_src "'\n" > "/dev/stderr"
+		}
+
+		generated = mask
+		sub(reg_src, reg_div, generated)
+
+		if (0) {
+		    printf "/* rsrc " reg_src " */\n"
+		    printf "/* rdiv " reg_div " */\n"
+		    printf "/* shift " shift " */\n"
+		    printf "/* mask " mask " */\n"
+		    printf "/* generated " generated " */\n"
+		}
+
+		if (reg_div != "") {
+		    printf "\t.reg_div = { "
+		    printf ".reg = " reg_div ", "
+		    printf ".shift = " dmask[generated,1] ", "
+		    printf ".size = " dmask[generated,0] ", "
+		    printf "},\n"
+		}
+
+		printf "\t.reg_src = { "
+		printf ".reg = " reg_src ", "
+		printf ".shift = " dmask[mask,1] ", "
+		printf ".size = " dmask[mask,0] ", "
+
+		printf "},\n"
+
+	    }
+
+	    print line
+	} else {
+	    print line
+	}
+
+	if (0)
+	    printf indent ":" line "\n" > "/dev/stderr"
+    }
+}
+
+// && ! /clksrc_clk.*=.*{/ { print $0 }
diff --git a/Documentation/cdrom/ide-cd b/Documentation/cdrom/ide-cd
index 2c558cd..f4dc9de 100644
--- a/Documentation/cdrom/ide-cd
+++ b/Documentation/cdrom/ide-cd
@@ -159,42 +159,7 @@
 to change.  If the slot number is -1, the drive is unloaded.
 
 
-4. Compilation options
-----------------------
-
-There are a few additional options which can be set when compiling the
-driver.  Most people should not need to mess with any of these; they
-are listed here simply for completeness.  A compilation option can be
-enabled by adding a line of the form `#define <option> 1' to the top
-of ide-cd.c.  All these options are disabled by default.
-
-VERBOSE_IDE_CD_ERRORS
-  If this is set, ATAPI error codes will be translated into textual
-  descriptions.  In addition, a dump is made of the command which
-  provoked the error.  This is off by default to save the memory used
-  by the (somewhat long) table of error descriptions.  
-
-STANDARD_ATAPI
-  If this is set, the code needed to deal with certain drives which do
-  not properly implement the ATAPI spec will be disabled.  If you know
-  your drive implements ATAPI properly, you can turn this on to get a
-  slightly smaller kernel.
-
-NO_DOOR_LOCKING
-  If this is set, the driver will never attempt to lock the door of
-  the drive.
-
-CDROM_NBLOCKS_BUFFER
-  This sets the size of the buffer to be used for a CDROMREADAUDIO
-  ioctl.  The default is 8.
-
-TEST
-  This currently enables an additional ioctl which enables a user-mode
-  program to execute an arbitrary packet command.  See the source for
-  details.  This should be left off unless you know what you're doing.
-
-
-5. Common problems
+4. Common problems
 ------------------
 
 This section discusses some common problems encountered when trying to
@@ -371,7 +336,7 @@
     expense of low system performance.
 
 
-6. cdchange.c
+5. cdchange.c
 -------------
 
 /*
diff --git a/Documentation/cgroups/cgroup_event_listener.c b/Documentation/cgroups/cgroup_event_listener.c
new file mode 100644
index 0000000..8c2bfc4
--- /dev/null
+++ b/Documentation/cgroups/cgroup_event_listener.c
@@ -0,0 +1,110 @@
+/*
+ * cgroup_event_listener.c - Simple listener of cgroup events
+ *
+ * Copyright (C) Kirill A. Shutemov <kirill@shutemov.name>
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/eventfd.h>
+
+#define USAGE_STR "Usage: cgroup_event_listener <path-to-control-file> <args>\n"
+
+int main(int argc, char **argv)
+{
+	int efd = -1;
+	int cfd = -1;
+	int event_control = -1;
+	char event_control_path[PATH_MAX];
+	char line[LINE_MAX];
+	int ret;
+
+	if (argc != 3) {
+		fputs(USAGE_STR, stderr);
+		return 1;
+	}
+
+	cfd = open(argv[1], O_RDONLY);
+	if (cfd == -1) {
+		fprintf(stderr, "Cannot open %s: %s\n", argv[1],
+				strerror(errno));
+		goto out;
+	}
+
+	ret = snprintf(event_control_path, PATH_MAX, "%s/cgroup.event_control",
+			dirname(argv[1]));
+	if (ret >= PATH_MAX) {
+		fputs("Path to cgroup.event_control is too long\n", stderr);
+		goto out;
+	}
+
+	event_control = open(event_control_path, O_WRONLY);
+	if (event_control == -1) {
+		fprintf(stderr, "Cannot open %s: %s\n", event_control_path,
+				strerror(errno));
+		goto out;
+	}
+
+	efd = eventfd(0, 0);
+	if (efd == -1) {
+		perror("eventfd() failed");
+		goto out;
+	}
+
+	ret = snprintf(line, LINE_MAX, "%d %d %s", efd, cfd, argv[2]);
+	if (ret >= LINE_MAX) {
+		fputs("Arguments string is too long\n", stderr);
+		goto out;
+	}
+
+	ret = write(event_control, line, strlen(line) + 1);
+	if (ret == -1) {
+		perror("Cannot write to cgroup.event_control");
+		goto out;
+	}
+
+	while (1) {
+		uint64_t result;
+
+		ret = read(efd, &result, sizeof(result));
+		if (ret == -1) {
+			if (errno == EINTR)
+				continue;
+			perror("Cannot read from eventfd");
+			break;
+		}
+		assert(ret == sizeof(result));
+
+		ret = access(event_control_path, W_OK);
+		if ((ret == -1) && (errno == ENOENT)) {
+				puts("The cgroup seems to have removed.");
+				ret = 0;
+				break;
+		}
+
+		if (ret == -1) {
+			perror("cgroup.event_control "
+					"is not accessable any more");
+			break;
+		}
+
+		printf("%s %s: crossed\n", argv[1], argv[2]);
+	}
+
+out:
+	if (efd >= 0)
+		close(efd);
+	if (event_control >= 0)
+		close(event_control);
+	if (cfd >= 0)
+		close(cfd);
+
+	return (ret != 0);
+}
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index 0b33bfe..fd588ff0 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -22,6 +22,8 @@
 2. Usage Examples and Syntax
   2.1 Basic Usage
   2.2 Attaching processes
+  2.3 Mounting hierarchies by name
+  2.4 Notification API
 3. Kernel API
   3.1 Overview
   3.2 Synchronization
@@ -434,6 +436,25 @@
 The name of the subsystem appears as part of the hierarchy description
 in /proc/mounts and /proc/<pid>/cgroups.
 
+2.4 Notification API
+--------------------
+
+There is mechanism which allows to get notifications about changing
+status of a cgroup.
+
+To register new notification handler you need:
+ - create a file descriptor for event notification using eventfd(2);
+ - open a control file to be monitored (e.g. memory.usage_in_bytes);
+ - write "<event_fd> <control_fd> <args>" to cgroup.event_control.
+   Interpretation of args is defined by control file implementation;
+
+eventfd will be woken up by control file implementation or when the
+cgroup is removed.
+
+To unregister notification handler just close eventfd.
+
+NOTE: Support of notifications should be implemented for the control
+file. See documentation for the subsystem.
 
 3. Kernel API
 =============
@@ -488,6 +509,11 @@
 - add an entry in linux/cgroup_subsys.h
 - define a cgroup_subsys object called <name>_subsys
 
+If a subsystem can be compiled as a module, it should also have in its
+module initcall a call to cgroup_load_subsys(), and in its exitcall a
+call to cgroup_unload_subsys(). It should also set its_subsys.module =
+THIS_MODULE in its .c file.
+
 Each subsystem may export the following methods. The only mandatory
 methods are create/destroy. Any others that are null are presumed to
 be successful no-ops.
@@ -536,10 +562,21 @@
 task is passed, then a successful result indicates that *any*
 unspecified task can be moved into the cgroup. Note that this isn't
 called on a fork. If this method returns 0 (success) then this should
-remain valid while the caller holds cgroup_mutex. If threadgroup is
+remain valid while the caller holds cgroup_mutex and it is ensured that either
+attach() or cancel_attach() will be called in future. If threadgroup is
 true, then a successful result indicates that all threads in the given
 thread's threadgroup can be moved together.
 
+void cancel_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+	       struct task_struct *task, bool threadgroup)
+(cgroup_mutex held by caller)
+
+Called when a task attach operation has failed after can_attach() has succeeded.
+A subsystem whose can_attach() has some side-effects should provide this
+function, so that the subsytem can implement a rollback. If not, not necessary.
+This will be called only about subsystems whose can_attach() operation have
+succeeded.
+
 void attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
 	    struct cgroup *old_cgrp, struct task_struct *task,
 	    bool threadgroup)
diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt
index 1d7e978..4160df8 100644
--- a/Documentation/cgroups/cpusets.txt
+++ b/Documentation/cgroups/cpusets.txt
@@ -168,20 +168,20 @@
 containing (on top of the standard cgroup files) the following
 files describing that cpuset:
 
- - cpus: list of CPUs in that cpuset
- - mems: list of Memory Nodes in that cpuset
- - memory_migrate flag: if set, move pages to cpusets nodes
- - cpu_exclusive flag: is cpu placement exclusive?
- - mem_exclusive flag: is memory placement exclusive?
- - mem_hardwall flag:  is memory allocation hardwalled
- - memory_pressure: measure of how much paging pressure in cpuset
- - memory_spread_page flag: if set, spread page cache evenly on allowed nodes
- - memory_spread_slab flag: if set, spread slab cache evenly on allowed nodes
- - sched_load_balance flag: if set, load balance within CPUs on that cpuset
- - sched_relax_domain_level: the searching range when migrating tasks
+ - cpuset.cpus: list of CPUs in that cpuset
+ - cpuset.mems: list of Memory Nodes in that cpuset
+ - cpuset.memory_migrate flag: if set, move pages to cpusets nodes
+ - cpuset.cpu_exclusive flag: is cpu placement exclusive?
+ - cpuset.mem_exclusive flag: is memory placement exclusive?
+ - cpuset.mem_hardwall flag:  is memory allocation hardwalled
+ - cpuset.memory_pressure: measure of how much paging pressure in cpuset
+ - cpuset.memory_spread_page flag: if set, spread page cache evenly on allowed nodes
+ - cpuset.memory_spread_slab flag: if set, spread slab cache evenly on allowed nodes
+ - cpuset.sched_load_balance flag: if set, load balance within CPUs on that cpuset
+ - cpuset.sched_relax_domain_level: the searching range when migrating tasks
 
 In addition, the root cpuset only has the following file:
- - memory_pressure_enabled flag: compute memory_pressure?
+ - cpuset.memory_pressure_enabled flag: compute memory_pressure?
 
 New cpusets are created using the mkdir system call or shell
 command.  The properties of a cpuset, such as its flags, allowed
@@ -229,7 +229,7 @@
 a direct ancestor or descendant, may share any of the same CPUs or
 Memory Nodes.
 
-A cpuset that is mem_exclusive *or* mem_hardwall is "hardwalled",
+A cpuset that is cpuset.mem_exclusive *or* cpuset.mem_hardwall is "hardwalled",
 i.e. it restricts kernel allocations for page, buffer and other data
 commonly shared by the kernel across multiple users.  All cpusets,
 whether hardwalled or not, restrict allocations of memory for user
@@ -304,15 +304,15 @@
 ---------------------------
 There are two boolean flag files per cpuset that control where the
 kernel allocates pages for the file system buffers and related in
-kernel data structures.  They are called 'memory_spread_page' and
-'memory_spread_slab'.
+kernel data structures.  They are called 'cpuset.memory_spread_page' and
+'cpuset.memory_spread_slab'.
 
-If the per-cpuset boolean flag file 'memory_spread_page' is set, then
+If the per-cpuset boolean flag file 'cpuset.memory_spread_page' is set, then
 the kernel will spread the file system buffers (page cache) evenly
 over all the nodes that the faulting task is allowed to use, instead
 of preferring to put those pages on the node where the task is running.
 
-If the per-cpuset boolean flag file 'memory_spread_slab' is set,
+If the per-cpuset boolean flag file 'cpuset.memory_spread_slab' is set,
 then the kernel will spread some file system related slab caches,
 such as for inodes and dentries evenly over all the nodes that the
 faulting task is allowed to use, instead of preferring to put those
@@ -337,21 +337,21 @@
 is turned off, then the currently specified NUMA mempolicy once again
 applies to memory page allocations.
 
-Both 'memory_spread_page' and 'memory_spread_slab' are boolean flag
+Both 'cpuset.memory_spread_page' and 'cpuset.memory_spread_slab' are boolean flag
 files.  By default they contain "0", meaning that the feature is off
 for that cpuset.  If a "1" is written to that file, then that turns
 the named feature on.
 
 The implementation is simple.
 
-Setting the flag 'memory_spread_page' turns on a per-process flag
+Setting the flag 'cpuset.memory_spread_page' turns on a per-process flag
 PF_SPREAD_PAGE for each task that is in that cpuset or subsequently
 joins that cpuset.  The page allocation calls for the page cache
 is modified to perform an inline check for this PF_SPREAD_PAGE task
 flag, and if set, a call to a new routine cpuset_mem_spread_node()
 returns the node to prefer for the allocation.
 
-Similarly, setting 'memory_spread_slab' turns on the flag
+Similarly, setting 'cpuset.memory_spread_slab' turns on the flag
 PF_SPREAD_SLAB, and appropriately marked slab caches will allocate
 pages from the node returned by cpuset_mem_spread_node().
 
@@ -404,24 +404,24 @@
     system overhead on those CPUs, including avoiding task load
     balancing if that is not needed.
 
-When the per-cpuset flag "sched_load_balance" is enabled (the default
-setting), it requests that all the CPUs in that cpusets allowed 'cpus'
+When the per-cpuset flag "cpuset.sched_load_balance" is enabled (the default
+setting), it requests that all the CPUs in that cpusets allowed 'cpuset.cpus'
 be contained in a single sched domain, ensuring that load balancing
 can move a task (not otherwised pinned, as by sched_setaffinity)
 from any CPU in that cpuset to any other.
 
-When the per-cpuset flag "sched_load_balance" is disabled, then the
+When the per-cpuset flag "cpuset.sched_load_balance" is disabled, then the
 scheduler will avoid load balancing across the CPUs in that cpuset,
 --except-- in so far as is necessary because some overlapping cpuset
 has "sched_load_balance" enabled.
 
-So, for example, if the top cpuset has the flag "sched_load_balance"
+So, for example, if the top cpuset has the flag "cpuset.sched_load_balance"
 enabled, then the scheduler will have one sched domain covering all
-CPUs, and the setting of the "sched_load_balance" flag in any other
+CPUs, and the setting of the "cpuset.sched_load_balance" flag in any other
 cpusets won't matter, as we're already fully load balancing.
 
 Therefore in the above two situations, the top cpuset flag
-"sched_load_balance" should be disabled, and only some of the smaller,
+"cpuset.sched_load_balance" should be disabled, and only some of the smaller,
 child cpusets have this flag enabled.
 
 When doing this, you don't usually want to leave any unpinned tasks in
@@ -433,7 +433,7 @@
 task to that underused CPU.
 
 Of course, tasks pinned to a particular CPU can be left in a cpuset
-that disables "sched_load_balance" as those tasks aren't going anywhere
+that disables "cpuset.sched_load_balance" as those tasks aren't going anywhere
 else anyway.
 
 There is an impedance mismatch here, between cpusets and sched domains.
@@ -443,19 +443,19 @@
 It is necessary for sched domains to be flat because load balancing
 across partially overlapping sets of CPUs would risk unstable dynamics
 that would be beyond our understanding.  So if each of two partially
-overlapping cpusets enables the flag 'sched_load_balance', then we
+overlapping cpusets enables the flag 'cpuset.sched_load_balance', then we
 form a single sched domain that is a superset of both.  We won't move
 a task to a CPU outside it cpuset, but the scheduler load balancing
 code might waste some compute cycles considering that possibility.
 
 This mismatch is why there is not a simple one-to-one relation
-between which cpusets have the flag "sched_load_balance" enabled,
+between which cpusets have the flag "cpuset.sched_load_balance" enabled,
 and the sched domain configuration.  If a cpuset enables the flag, it
 will get balancing across all its CPUs, but if it disables the flag,
 it will only be assured of no load balancing if no other overlapping
 cpuset enables the flag.
 
-If two cpusets have partially overlapping 'cpus' allowed, and only
+If two cpusets have partially overlapping 'cpuset.cpus' allowed, and only
 one of them has this flag enabled, then the other may find its
 tasks only partially load balanced, just on the overlapping CPUs.
 This is just the general case of the top_cpuset example given a few
@@ -468,23 +468,23 @@
 1.7.1 sched_load_balance implementation details.
 ------------------------------------------------
 
-The per-cpuset flag 'sched_load_balance' defaults to enabled (contrary
+The per-cpuset flag 'cpuset.sched_load_balance' defaults to enabled (contrary
 to most cpuset flags.)  When enabled for a cpuset, the kernel will
 ensure that it can load balance across all the CPUs in that cpuset
 (makes sure that all the CPUs in the cpus_allowed of that cpuset are
 in the same sched domain.)
 
-If two overlapping cpusets both have 'sched_load_balance' enabled,
+If two overlapping cpusets both have 'cpuset.sched_load_balance' enabled,
 then they will be (must be) both in the same sched domain.
 
-If, as is the default, the top cpuset has 'sched_load_balance' enabled,
+If, as is the default, the top cpuset has 'cpuset.sched_load_balance' enabled,
 then by the above that means there is a single sched domain covering
 the whole system, regardless of any other cpuset settings.
 
 The kernel commits to user space that it will avoid load balancing
 where it can.  It will pick as fine a granularity partition of sched
 domains as it can while still providing load balancing for any set
-of CPUs allowed to a cpuset having 'sched_load_balance' enabled.
+of CPUs allowed to a cpuset having 'cpuset.sched_load_balance' enabled.
 
 The internal kernel cpuset to scheduler interface passes from the
 cpuset code to the scheduler code a partition of the load balanced
@@ -495,9 +495,9 @@
 The cpuset code builds a new such partition and passes it to the
 scheduler sched domain setup code, to have the sched domains rebuilt
 as necessary, whenever:
- - the 'sched_load_balance' flag of a cpuset with non-empty CPUs changes,
+ - the 'cpuset.sched_load_balance' flag of a cpuset with non-empty CPUs changes,
  - or CPUs come or go from a cpuset with this flag enabled,
- - or 'sched_relax_domain_level' value of a cpuset with non-empty CPUs
+ - or 'cpuset.sched_relax_domain_level' value of a cpuset with non-empty CPUs
    and with this flag enabled changes,
  - or a cpuset with non-empty CPUs and with this flag enabled is removed,
  - or a cpu is offlined/onlined.
@@ -542,7 +542,7 @@
 on the next tick.  For some applications in special situation, waiting
 1 tick may be too long.
 
-The 'sched_relax_domain_level' file allows you to request changing
+The 'cpuset.sched_relax_domain_level' file allows you to request changing
 this searching range as you like.  This file takes int value which
 indicates size of searching range in levels ideally as follows,
 otherwise initial value -1 that indicates the cpuset has no request.
@@ -559,8 +559,8 @@
 can be changed using the relax_domain_level= boot parameter.
 
 This file is per-cpuset and affect the sched domain where the cpuset
-belongs to.  Therefore if the flag 'sched_load_balance' of a cpuset
-is disabled, then 'sched_relax_domain_level' have no effect since
+belongs to.  Therefore if the flag 'cpuset.sched_load_balance' of a cpuset
+is disabled, then 'cpuset.sched_relax_domain_level' have no effect since
 there is no sched domain belonging the cpuset.
 
 If multiple cpusets are overlapping and hence they form a single sched
@@ -607,9 +607,9 @@
 memory placement, as above, the next time that the kernel attempts
 to allocate a page of memory for that task.
 
-If a cpuset has its 'cpus' modified, then each task in that cpuset
+If a cpuset has its 'cpuset.cpus' modified, then each task in that cpuset
 will have its allowed CPU placement changed immediately.  Similarly,
-if a tasks pid is written to another cpusets 'tasks' file, then its
+if a tasks pid is written to another cpusets 'cpuset.tasks' file, then its
 allowed CPU placement is changed immediately.  If such a task had been
 bound to some subset of its cpuset using the sched_setaffinity() call,
 the task will be allowed to run on any CPU allowed in its new cpuset,
@@ -622,8 +622,8 @@
 Normally, once a page is allocated (given a physical page
 of main memory) then that page stays on whatever node it
 was allocated, so long as it remains allocated, even if the
-cpusets memory placement policy 'mems' subsequently changes.
-If the cpuset flag file 'memory_migrate' is set true, then when
+cpusets memory placement policy 'cpuset.mems' subsequently changes.
+If the cpuset flag file 'cpuset.memory_migrate' is set true, then when
 tasks are attached to that cpuset, any pages that task had
 allocated to it on nodes in its previous cpuset are migrated
 to the tasks new cpuset. The relative placement of the page within
@@ -631,12 +631,12 @@
 For example if the page was on the second valid node of the prior cpuset
 then the page will be placed on the second valid node of the new cpuset.
 
-Also if 'memory_migrate' is set true, then if that cpusets
-'mems' file is modified, pages allocated to tasks in that
-cpuset, that were on nodes in the previous setting of 'mems',
+Also if 'cpuset.memory_migrate' is set true, then if that cpusets
+'cpuset.mems' file is modified, pages allocated to tasks in that
+cpuset, that were on nodes in the previous setting of 'cpuset.mems',
 will be moved to nodes in the new setting of 'mems.'
 Pages that were not in the tasks prior cpuset, or in the cpusets
-prior 'mems' setting, will not be moved.
+prior 'cpuset.mems' setting, will not be moved.
 
 There is an exception to the above.  If hotplug functionality is used
 to remove all the CPUs that are currently assigned to a cpuset,
@@ -678,8 +678,8 @@
   cd /dev/cpuset
   mkdir Charlie
   cd Charlie
-  /bin/echo 2-3 > cpus
-  /bin/echo 1 > mems
+  /bin/echo 2-3 > cpuset.cpus
+  /bin/echo 1 > cpuset.mems
   /bin/echo $$ > tasks
   sh
   # The subshell 'sh' is now running in cpuset Charlie
@@ -725,10 +725,13 @@
 
 In this directory you can find several files:
 # ls
-cpu_exclusive  memory_migrate      mems                      tasks
-cpus           memory_pressure     notify_on_release
-mem_exclusive  memory_spread_page  sched_load_balance
-mem_hardwall   memory_spread_slab  sched_relax_domain_level
+cpuset.cpu_exclusive       cpuset.memory_spread_slab
+cpuset.cpus                cpuset.mems
+cpuset.mem_exclusive       cpuset.sched_load_balance
+cpuset.mem_hardwall        cpuset.sched_relax_domain_level
+cpuset.memory_migrate      notify_on_release
+cpuset.memory_pressure     tasks
+cpuset.memory_spread_page
 
 Reading them will give you information about the state of this cpuset:
 the CPUs and Memory Nodes it can use, the processes that are using
@@ -736,13 +739,13 @@
 the cpuset.
 
 Set some flags:
-# /bin/echo 1 > cpu_exclusive
+# /bin/echo 1 > cpuset.cpu_exclusive
 
 Add some cpus:
-# /bin/echo 0-7 > cpus
+# /bin/echo 0-7 > cpuset.cpus
 
 Add some mems:
-# /bin/echo 0-7 > mems
+# /bin/echo 0-7 > cpuset.mems
 
 Now attach your shell to this cpuset:
 # /bin/echo $$ > tasks
@@ -774,28 +777,28 @@
 This is the syntax to use when writing in the cpus or mems files
 in cpuset directories:
 
-# /bin/echo 1-4 > cpus		-> set cpus list to cpus 1,2,3,4
-# /bin/echo 1,2,3,4 > cpus	-> set cpus list to cpus 1,2,3,4
+# /bin/echo 1-4 > cpuset.cpus		-> set cpus list to cpus 1,2,3,4
+# /bin/echo 1,2,3,4 > cpuset.cpus	-> set cpus list to cpus 1,2,3,4
 
 To add a CPU to a cpuset, write the new list of CPUs including the
 CPU to be added. To add 6 to the above cpuset:
 
-# /bin/echo 1-4,6 > cpus	-> set cpus list to cpus 1,2,3,4,6
+# /bin/echo 1-4,6 > cpuset.cpus	-> set cpus list to cpus 1,2,3,4,6
 
 Similarly to remove a CPU from a cpuset, write the new list of CPUs
 without the CPU to be removed.
 
 To remove all the CPUs:
 
-# /bin/echo "" > cpus		-> clear cpus list
+# /bin/echo "" > cpuset.cpus		-> clear cpus list
 
 2.3 Setting flags
 -----------------
 
 The syntax is very simple:
 
-# /bin/echo 1 > cpu_exclusive 	-> set flag 'cpu_exclusive'
-# /bin/echo 0 > cpu_exclusive 	-> unset flag 'cpu_exclusive'
+# /bin/echo 1 > cpuset.cpu_exclusive 	-> set flag 'cpuset.cpu_exclusive'
+# /bin/echo 0 > cpuset.cpu_exclusive 	-> unset flag 'cpuset.cpu_exclusive'
 
 2.4 Attaching processes
 -----------------------
diff --git a/Documentation/cgroups/memcg_test.txt b/Documentation/cgroups/memcg_test.txt
index 72db89e..f7f68b2 100644
--- a/Documentation/cgroups/memcg_test.txt
+++ b/Documentation/cgroups/memcg_test.txt
@@ -1,6 +1,6 @@
 Memory Resource Controller(Memcg)  Implementation Memo.
-Last Updated: 2009/1/20
-Base Kernel Version: based on 2.6.29-rc2.
+Last Updated: 2010/2
+Base Kernel Version: based on 2.6.33-rc7-mm(candidate for 34).
 
 Because VM is getting complex (one of reasons is memcg...), memcg's behavior
 is complex. This is a document for memcg's internal behavior.
@@ -337,7 +337,7 @@
 	race and lock dependency with other cgroup subsystems.
 
 	example)
-	# mount -t cgroup none /cgroup -t cpuset,memory,cpu,devices
+	# mount -t cgroup none /cgroup -o cpuset,memory,cpu,devices
 
 	and do task move, mkdir, rmdir etc...under this.
 
@@ -348,7 +348,7 @@
 
 	For example, test like following is good.
 	(Shell-A)
-	# mount -t cgroup none /cgroup -t memory
+	# mount -t cgroup none /cgroup -o memory
 	# mkdir /cgroup/test
 	# echo 40M > /cgroup/test/memory.limit_in_bytes
 	# echo 0 > /cgroup/test/tasks
@@ -378,3 +378,42 @@
 	#echo 50M > memory.limit_in_bytes
 	#echo 50M > memory.memsw.limit_in_bytes
 	run 51M of malloc
+
+ 9.9 Move charges at task migration
+	Charges associated with a task can be moved along with task migration.
+
+	(Shell-A)
+	#mkdir /cgroup/A
+	#echo $$ >/cgroup/A/tasks
+	run some programs which uses some amount of memory in /cgroup/A.
+
+	(Shell-B)
+	#mkdir /cgroup/B
+	#echo 1 >/cgroup/B/memory.move_charge_at_immigrate
+	#echo "pid of the program running in group A" >/cgroup/B/tasks
+
+	You can see charges have been moved by reading *.usage_in_bytes or
+	memory.stat of both A and B.
+	See 8.2 of Documentation/cgroups/memory.txt to see what value should be
+	written to move_charge_at_immigrate.
+
+ 9.10 Memory thresholds
+	Memory controler implements memory thresholds using cgroups notification
+	API. You can use Documentation/cgroups/cgroup_event_listener.c to test
+	it.
+
+	(Shell-A) Create cgroup and run event listener
+	# mkdir /cgroup/A
+	# ./cgroup_event_listener /cgroup/A/memory.usage_in_bytes 5M
+
+	(Shell-B) Add task to cgroup and try to allocate and free memory
+	# echo $$ >/cgroup/A/tasks
+	# a="$(dd if=/dev/zero bs=1M count=10)"
+	# a=
+
+	You will see message from cgroup_event_listener every time you cross
+	the thresholds.
+
+	Use /cgroup/A/memory.memsw.usage_in_bytes to test memsw thresholds.
+
+	It's good idea to test root cgroup as well.
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index b871f25..f8bc802 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -182,6 +182,8 @@
 NOTE: Reclaim does not work for the root cgroup, since we cannot set any
 limits on the root cgroup.
 
+Note2: When panic_on_oom is set to "2", the whole system will panic.
+
 2. Locking
 
 The memory controller uses the following hierarchy
@@ -262,10 +264,12 @@
 4.2 Task migration
 
 When a task migrates from one cgroup to another, it's charge is not
-carried forward. The pages allocated from the original cgroup still
+carried forward by default. The pages allocated from the original cgroup still
 remain charged to it, the charge is dropped when the page is freed or
 reclaimed.
 
+Note: You can move charges of a task along with task migration. See 8.
+
 4.3 Removing a cgroup
 
 A cgroup can be removed by rmdir, but as discussed in sections 4.1 and 4.2, a
@@ -377,7 +381,8 @@
 NOTE1: Enabling/disabling will fail if the cgroup already has other
 cgroups created below it.
 
-NOTE2: This feature can be enabled/disabled per subtree.
+NOTE2: When panic_on_oom is set to "2", the whole system will panic in
+case of an oom event in any cgroup.
 
 7. Soft limits
 
@@ -414,7 +419,76 @@
 NOTE2: It is recommended to set the soft limit always below the hard limit,
        otherwise the hard limit will take precedence.
 
-8. TODO
+8. Move charges at task migration
+
+Users can move charges associated with a task along with task migration, that
+is, uncharge task's pages from the old cgroup and charge them to the new cgroup.
+This feature is not supported in !CONFIG_MMU environments because of lack of
+page tables.
+
+8.1 Interface
+
+This feature is disabled by default. It can be enabled(and disabled again) by
+writing to memory.move_charge_at_immigrate of the destination cgroup.
+
+If you want to enable it:
+
+# echo (some positive value) > memory.move_charge_at_immigrate
+
+Note: Each bits of move_charge_at_immigrate has its own meaning about what type
+      of charges should be moved. See 8.2 for details.
+Note: Charges are moved only when you move mm->owner, IOW, a leader of a thread
+      group.
+Note: If we cannot find enough space for the task in the destination cgroup, we
+      try to make space by reclaiming memory. Task migration may fail if we
+      cannot make enough space.
+Note: It can take several seconds if you move charges in giga bytes order.
+
+And if you want disable it again:
+
+# echo 0 > memory.move_charge_at_immigrate
+
+8.2 Type of charges which can be move
+
+Each bits of move_charge_at_immigrate has its own meaning about what type of
+charges should be moved.
+
+  bit | what type of charges would be moved ?
+ -----+------------------------------------------------------------------------
+   0  | A charge of an anonymous page(or swap of it) used by the target task.
+      | Those pages and swaps must be used only by the target task. You must
+      | enable Swap Extension(see 2.4) to enable move of swap charges.
+
+Note: Those pages and swaps must be charged to the old cgroup.
+Note: More type of pages(e.g. file cache, shmem,) will be supported by other
+      bits in future.
+
+8.3 TODO
+
+- Add support for other types of pages(e.g. file cache, shmem, etc.).
+- Implement madvise(2) to let users decide the vma to be moved or not to be
+  moved.
+- All of moving charge operations are done under cgroup_mutex. It's not good
+  behavior to hold the mutex too long, so we may need some trick.
+
+9. Memory thresholds
+
+Memory controler implements memory thresholds using cgroups notification
+API (see cgroups.txt). It allows to register multiple memory and memsw
+thresholds and gets notifications when it crosses.
+
+To register a threshold application need:
+ - create an eventfd using eventfd(2);
+ - open memory.usage_in_bytes or memory.memsw.usage_in_bytes;
+ - write string like "<event_fd> <memory.usage_in_bytes> <threshold>" to
+   cgroup.event_control.
+
+Application will be notified through eventfd when memory usage crosses
+threshold in any direction.
+
+It's applicable for root and non-root cgroup.
+
+10. TODO
 
 1. Add support for accounting huge pages (as a separate controller)
 2. Make per-cgroup scanner reclaim not-shared pages first
diff --git a/Documentation/console/console.txt b/Documentation/console/console.txt
index 877a1b2..926cf1b 100644
--- a/Documentation/console/console.txt
+++ b/Documentation/console/console.txt
@@ -74,7 +74,7 @@
 hand, will bind the driver to the consoles that are currently occupied by a
 system driver.
 
-NOTE1: Binding and binding must be selected in Kconfig. It's under:
+NOTE1: Binding and unbinding must be selected in Kconfig. It's under:
 
 Device Drivers -> Character devices -> Support for binding and unbinding
 console drivers
diff --git a/Documentation/cpu-freq/pcc-cpufreq.txt b/Documentation/cpu-freq/pcc-cpufreq.txt
new file mode 100644
index 0000000..9e3c3b3
--- /dev/null
+++ b/Documentation/cpu-freq/pcc-cpufreq.txt
@@ -0,0 +1,207 @@
+/*
+ *  pcc-cpufreq.txt - PCC interface documentation
+ *
+ *  Copyright (C) 2009 Red Hat, Matthew Garrett <mjg@redhat.com>
+ *  Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ *      Nagananda Chumbalkar <nagananda.chumbalkar@hp.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; 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, GOOD TITLE or NON
+ *  INFRINGEMENT. See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+
+			Processor Clocking Control Driver
+			---------------------------------
+
+Contents:
+---------
+1.	Introduction
+1.1	PCC interface
+1.1.1   Get Average Frequency
+1.1.2	Set Desired Frequency
+1.2	Platforms affected
+2.	Driver and /sys details
+2.1	scaling_available_frequencies
+2.2	cpuinfo_transition_latency
+2.3	cpuinfo_cur_freq
+2.4	related_cpus
+3.	Caveats
+
+1. Introduction:
+----------------
+Processor Clocking Control (PCC) is an interface between the platform
+firmware and OSPM. It is a mechanism for coordinating processor
+performance (ie: frequency) between the platform firmware and the OS.
+
+The PCC driver (pcc-cpufreq) allows OSPM to take advantage of the PCC
+interface.
+
+OS utilizes the PCC interface to inform platform firmware what frequency the
+OS wants for a logical processor. The platform firmware attempts to achieve
+the requested frequency. If the request for the target frequency could not be
+satisfied by platform firmware, then it usually means that power budget
+conditions are in place, and "power capping" is taking place.
+
+1.1 PCC interface:
+------------------
+The complete PCC specification is available here:
+http://www.acpica.org/download/Processor-Clocking-Control-v1p0.pdf
+
+PCC relies on a shared memory region that provides a channel for communication
+between the OS and platform firmware. PCC also implements a "doorbell" that
+is used by the OS to inform the platform firmware that a command has been
+sent.
+
+The ACPI PCCH() method is used to discover the location of the PCC shared
+memory region. The shared memory region header contains the "command" and
+"status" interface. PCCH() also contains details on how to access the platform
+doorbell.
+
+The following commands are supported by the PCC interface:
+* Get Average Frequency
+* Set Desired Frequency
+
+The ACPI PCCP() method is implemented for each logical processor and is
+used to discover the offsets for the input and output buffers in the shared
+memory region.
+
+When PCC mode is enabled, the platform will not expose processor performance
+or throttle states (_PSS, _TSS and related ACPI objects) to OSPM. Therefore,
+the native P-state driver (such as acpi-cpufreq for Intel, powernow-k8 for
+AMD) will not load.
+
+However, OSPM remains in control of policy. The governor (eg: "ondemand")
+computes the required performance for each processor based on server workload.
+The PCC driver fills in the command interface, and the input buffer and
+communicates the request to the platform firmware. The platform firmware is
+responsible for delivering the requested performance.
+
+Each PCC command is "global" in scope and can affect all the logical CPUs in
+the system. Therefore, PCC is capable of performing "group" updates. With PCC
+the OS is capable of getting/setting the frequency of all the logical CPUs in
+the system with a single call to the BIOS.
+
+1.1.1 Get Average Frequency:
+----------------------------
+This command is used by the OSPM to query the running frequency of the
+processor since the last time this command was completed. The output buffer
+indicates the average unhalted frequency of the logical processor expressed as
+a percentage of the nominal (ie: maximum) CPU frequency. The output buffer
+also signifies if the CPU frequency is limited by a power budget condition.
+
+1.1.2 Set Desired Frequency:
+----------------------------
+This command is used by the OSPM to communicate to the platform firmware the
+desired frequency for a logical processor. The output buffer is currently
+ignored by OSPM. The next invocation of "Get Average Frequency" will inform
+OSPM if the desired frequency was achieved or not.
+
+1.2 Platforms affected:
+-----------------------
+The PCC driver will load on any system where the platform firmware:
+* supports the PCC interface, and the associated PCCH() and PCCP() methods
+* assumes responsibility for managing the hardware clocking controls in order
+to deliver the requested processor performance
+
+Currently, certain HP ProLiant platforms implement the PCC interface. On those
+platforms PCC is the "default" choice.
+
+However, it is possible to disable this interface via a BIOS setting. In
+such an instance, as is also the case on platforms where the PCC interface
+is not implemented, the PCC driver will fail to load silently.
+
+2. Driver and /sys details:
+---------------------------
+When the driver loads, it merely prints the lowest and the highest CPU
+frequencies supported by the platform firmware.
+
+The PCC driver loads with a message such as:
+pcc-cpufreq: (v1.00.00) driver loaded with frequency limits: 1600 MHz, 2933
+MHz
+
+This means that the OPSM can request the CPU to run at any frequency in
+between the limits (1600 MHz, and 2933 MHz) specified in the message.
+
+Internally, there is no need for the driver to convert the "target" frequency
+to a corresponding P-state.
+
+The VERSION number for the driver will be of the format v.xy.ab.
+eg: 1.00.02
+   ----- --
+    |    |
+    |    -- this will increase with bug fixes/enhancements to the driver
+    |-- this is the version of the PCC specification the driver adheres to
+
+
+The following is a brief discussion on some of the fields exported via the
+/sys filesystem and how their values are affected by the PCC driver:
+
+2.1 scaling_available_frequencies:
+----------------------------------
+scaling_available_frequencies is not created in /sys. No intermediate
+frequencies need to be listed because the BIOS will try to achieve any
+frequency, within limits, requested by the governor. A frequency does not have
+to be strictly associated with a P-state.
+
+2.2 cpuinfo_transition_latency:
+-------------------------------
+The cpuinfo_transition_latency field is 0. The PCC specification does
+not include a field to expose this value currently.
+
+2.3 cpuinfo_cur_freq:
+---------------------
+A) Often cpuinfo_cur_freq will show a value different than what is declared
+in the scaling_available_frequencies or scaling_cur_freq, or scaling_max_freq.
+This is due to "turbo boost" available on recent Intel processors. If certain
+conditions are met the BIOS can achieve a slightly higher speed than requested
+by OSPM. An example:
+
+scaling_cur_freq	: 2933000
+cpuinfo_cur_freq	: 3196000
+
+B) There is a round-off error associated with the cpuinfo_cur_freq value.
+Since the driver obtains the current frequency as a "percentage" (%) of the
+nominal frequency from the BIOS, sometimes, the values displayed by
+scaling_cur_freq and cpuinfo_cur_freq may not match. An example:
+
+scaling_cur_freq	: 1600000
+cpuinfo_cur_freq	: 1583000
+
+In this example, the nominal frequency is 2933 MHz. The driver obtains the
+current frequency, cpuinfo_cur_freq, as 54% of the nominal frequency:
+
+	54% of 2933 MHz = 1583 MHz
+
+Nominal frequency is the maximum frequency of the processor, and it usually
+corresponds to the frequency of the P0 P-state.
+
+2.4 related_cpus:
+-----------------
+The related_cpus field is identical to affected_cpus.
+
+affected_cpus	: 4
+related_cpus	: 4
+
+Currently, the PCC driver does not evaluate _PSD. The platforms that support
+PCC do not implement SW_ALL. So OSPM doesn't need to perform any coordination
+to ensure that the same frequency is requested of all dependent CPUs.
+
+3. Caveats:
+-----------
+The "cpufreq_stats" module in its present form cannot be loaded and
+expected to work with the PCC driver. Since the "cpufreq_stats" module
+provides information wrt each P-state, it is not applicable to the PCC driver.
diff --git a/Documentation/device-mapper/snapshot.txt b/Documentation/device-mapper/snapshot.txt
index e3a77b2..0d5bc46 100644
--- a/Documentation/device-mapper/snapshot.txt
+++ b/Documentation/device-mapper/snapshot.txt
@@ -122,3 +122,47 @@
 brw-------  1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
 brw-------  1 root root 254, 12 29 ago 18:16 /dev/mapper/volumeGroup-base-cow
 brw-------  1 root root 254, 10 29 ago 18:16 /dev/mapper/volumeGroup-base
+
+
+How to determine when a merging is complete
+===========================================
+The snapshot-merge and snapshot status lines end with:
+  <sectors_allocated>/<total_sectors> <metadata_sectors>
+
+Both <sectors_allocated> and <total_sectors> include both data and metadata.
+During merging, the number of sectors allocated gets smaller and
+smaller.  Merging has finished when the number of sectors holding data
+is zero, in other words <sectors_allocated> == <metadata_sectors>.
+
+Here is a practical example (using a hybrid of lvm and dmsetup commands):
+
+# lvs
+  LV      VG          Attr   LSize Origin  Snap%  Move Log Copy%  Convert
+  base    volumeGroup owi-a- 4.00g
+  snap    volumeGroup swi-a- 1.00g base  18.97
+
+# dmsetup status volumeGroup-snap
+0 8388608 snapshot 397896/2097152 1560
+                                  ^^^^ metadata sectors
+
+# lvconvert --merge -b volumeGroup/snap
+  Merging of volume snap started.
+
+# lvs volumeGroup/snap
+  LV      VG          Attr   LSize Origin  Snap%  Move Log Copy%  Convert
+  base    volumeGroup Owi-a- 4.00g          17.23
+
+# dmsetup status volumeGroup-base
+0 8388608 snapshot-merge 281688/2097152 1104
+
+# dmsetup status volumeGroup-base
+0 8388608 snapshot-merge 180480/2097152 712
+
+# dmsetup status volumeGroup-base
+0 8388608 snapshot-merge 16/2097152 16
+
+Merging has finished.
+
+# lvs
+  LV      VG          Attr   LSize Origin  Snap%  Move Log Copy%  Convert
+  base    volumeGroup owi-a- 4.00g
diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
index 2e2c2ea..41f4163 100644
--- a/Documentation/driver-model/platform.txt
+++ b/Documentation/driver-model/platform.txt
@@ -192,7 +192,7 @@
 User specified early platform devices will be registered at this point.
 For the early serial console case the user can specify port on the
 kernel command line as "earlyprintk=serial.0" where "earlyprintk" is
-the class string, "serial" is the name of the platfrom driver and
+the class string, "serial" is the name of the platform driver and
 0 is the platform device id. If the id is -1 then the dot and the
 id can be omitted.
 
diff --git a/Documentation/eisa.txt b/Documentation/eisa.txt
index 60e361b..f297fc1 100644
--- a/Documentation/eisa.txt
+++ b/Documentation/eisa.txt
@@ -171,7 +171,7 @@
 virtual_root.force_probe :
 
 Force the probing code to probe EISA slots even when it cannot find an
-EISA compliant mainboard (nothing appears on slot 0). Defaultd to 0
+EISA compliant mainboard (nothing appears on slot 0). Defaults to 0
 (don't force), and set to 1 (force probing) when either
 CONFIG_ALPHA_JENSEN or CONFIG_EISA_VLB_PRIMING are set.
 
diff --git a/Documentation/email-clients.txt b/Documentation/email-clients.txt
index a618efa..945ff3f 100644
--- a/Documentation/email-clients.txt
+++ b/Documentation/email-clients.txt
@@ -216,26 +216,14 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Gmail (Web GUI)
 
-If you just have to use Gmail to send patches, it CAN be made to work.  It
-requires a bit of external help, though.
+Does not work for sending patches.
 
-The first problem is that Gmail converts tabs to spaces.  This will
-totally break your patches.  To prevent this, you have to use a different
-editor.  There is a firefox extension called "ViewSourceWith"
-(https://addons.mozilla.org/en-US/firefox/addon/394) which allows you to
-edit any text box in the editor of your choice.  Configure it to launch
-your favorite editor.  When you want to send a patch, use this technique.
-Once you have crafted your messsage + patch, save and exit the editor,
-which should reload the Gmail edit box.  GMAIL WILL PRESERVE THE TABS.
-Hoorah.  Apparently you can cut-n-paste literal tabs, but Gmail will
-convert those to spaces upon sending!
+Gmail web client converts tabs to spaces automatically.
 
-The second problem is that Gmail converts tabs to spaces on replies.  If
-you reply to a patch, don't expect to be able to apply it as a patch.
+At the same time it wraps lines every 78 chars with CRLF style line breaks
+although tab2space problem can be solved with external editor.
 
-The last problem is that Gmail will base64-encode any message that has a
-non-ASCII character.  That includes things like European names.  Be aware.
-
-Gmail is not convenient for lkml patches, but CAN be made to work.
+Another problem is that Gmail will base64-encode any message that has a
+non-ASCII character. That includes things like European names.
 
                                 ###
diff --git a/Documentation/fault-injection/provoke-crashes.txt b/Documentation/fault-injection/provoke-crashes.txt
new file mode 100644
index 0000000..7a9d3d8
--- /dev/null
+++ b/Documentation/fault-injection/provoke-crashes.txt
@@ -0,0 +1,38 @@
+The lkdtm module provides an interface to crash or injure the kernel at
+predefined crashpoints to evaluate the reliability of crash dumps obtained
+using different dumping solutions. The module uses KPROBEs to instrument
+crashing points, but can also crash the kernel directly without KRPOBE
+support.
+
+
+You can provide the way either through module arguments when inserting
+the module, or through a debugfs interface.
+
+Usage: insmod lkdtm.ko [recur_count={>0}] cpoint_name=<> cpoint_type=<>
+				[cpoint_count={>0}]
+
+  recur_count : Recursion level for the stack overflow test. Default is 10.
+
+  cpoint_name : Crash point where the kernel is to be crashed. It can be
+	 one of INT_HARDWARE_ENTRY, INT_HW_IRQ_EN, INT_TASKLET_ENTRY,
+	 FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_DISPATCH_CMD,
+	 IDE_CORE_CP, DIRECT
+
+  cpoint_type : Indicates the action to be taken on hitting the crash point.
+     It can be one of PANIC, BUG, EXCEPTION, LOOP, OVERFLOW,
+     CORRUPT_STACK, UNALIGNED_LOAD_STORE_WRITE, OVERWRITE_ALLOCATION,
+     WRITE_AFTER_FREE,
+
+  cpoint_count : Indicates the number of times the crash point is to be hit
+    to trigger an action. The default is 10.
+
+You can also induce failures by mounting debugfs and writing the type to
+<mountpoint>/provoke-crash/<crashpoint>. E.g.,
+
+  mount -t debugfs debugfs /mnt
+  echo EXCEPTION > /mnt/provoke-crash/INT_HARDWARE_ENTRY
+
+
+A special file is `DIRECT' which will induce the crash directly without
+KPROBE instrumentation. This mode is the only one available when the module
+is built on a kernel without KPROBEs support.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 73ef30d..a5cc0db 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -117,19 +117,25 @@
 ---------------------------
 
 What:	PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
-When:	November 2005
+When:	2.6.35/2.6.36
 Files:	drivers/pcmcia/: pcmcia_ioctl.c
 Why:	With the 16-bit PCMCIA subsystem now behaving (almost) like a
 	normal hotpluggable bus, and with it using the default kernel
 	infrastructure (hotplug, driver core, sysfs) keeping the PCMCIA
 	control ioctl needed by cardmgr and cardctl from pcmcia-cs is
-	unnecessary, and makes further cleanups and integration of the
+	unnecessary and potentially harmful (it does not provide for
+	proper locking), and makes further cleanups and integration of the
 	PCMCIA subsystem into the Linux kernel device driver model more
 	difficult. The features provided by cardmgr and cardctl are either
 	handled by the kernel itself now or are available in the new
 	pcmciautils package available at
 	http://kernel.org/pub/linux/utils/kernel/pcmcia/
-Who:	Dominik Brodowski <linux@brodo.de>
+
+	For all architectures except ARM, the associated config symbol
+	has been removed from kernel 2.6.34; for ARM, it will be likely
+	be removed from kernel 2.6.35. The actual code will then likely
+	be removed from kernel 2.6.36.
+Who:	Dominik Brodowski <linux@dominikbrodowski.net>
 
 ---------------------------
 
@@ -443,12 +449,6 @@
 
 ----------------------------
 
-What:	adt7473 hardware monitoring driver
-When:	February 2010
-Why:	Obsoleted by the adt7475 driver.
-Who:	Jean Delvare <khali@linux-fr.org>
-
----------------------------
 What:	Support for lcd_switch and display_get in asus-laptop driver
 When:	March 2010
 Why:	These two features use non-standard interfaces. There are the
@@ -550,3 +550,35 @@
 	NCCI TTY device nodes. User space (pppdcapiplugin) works without
 	noticing the difference.
 Who:	Jan Kiszka <jan.kiszka@web.de>
+
+----------------------------
+
+What:	KVM memory aliases support
+When:	July 2010
+Why:	Memory aliasing support is used for speeding up guest vga access
+	through the vga windows.
+
+	Modern userspace no longer uses this feature, so it's just bitrotted
+	code and can be removed with no impact.
+Who:	Avi Kivity <avi@redhat.com>
+
+----------------------------
+
+What:	KVM kernel-allocated memory slots
+When:	July 2010
+Why:	Since 2.6.25, kvm supports user-allocated memory slots, which are
+	much more flexible than kernel-allocated slots.  All current userspace
+	supports the newer interface and this code can be removed with no
+	impact.
+Who:	Avi Kivity <avi@redhat.com>
+
+----------------------------
+
+What:	KVM paravirt mmu host support
+When:	January 2011
+Why:	The paravirt mmu host support is slower than non-paravirt mmu, both
+	on newer and older hardware.  It is already not exposed to the guest,
+	and kept only for live migration purposes.
+Who:	Avi Kivity <avi@redhat.com>
+
+----------------------------
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 875d496..3bae418 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -32,6 +32,8 @@
 	- info on the userspace interface to the OCFS2 DLM.
 dnotify.txt
 	- info about directory notification in Linux.
+dnotify_test.c
+	- example program for dnotify
 ecryptfs.txt
 	- docs on eCryptfs: stacked cryptographic filesystem for Linux.
 exofs.txt
@@ -62,6 +64,8 @@
 	- info and mount options for the JFS filesystem.
 locks.txt
 	- info on file locking implementations, flock() vs. fcntl(), etc.
+logfs.txt
+	- info on the LogFS flash filesystem.
 mandatory-locking.txt
 	- info on the Linux implementation of Sys V mandatory file locking.
 ncpfs.txt
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 18b9d0c..06bbbed 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -460,13 +460,6 @@
 
 --------------------------- dquot_operations -------------------------------
 prototypes:
-	int (*initialize) (struct inode *, int);
-	int (*drop) (struct inode *);
-	int (*alloc_space) (struct inode *, qsize_t, int);
-	int (*alloc_inode) (const struct inode *, unsigned long);
-	int (*free_space) (struct inode *, qsize_t);
-	int (*free_inode) (const struct inode *, unsigned long);
-	int (*transfer) (struct inode *, struct iattr *);
 	int (*write_dquot) (struct dquot *);
 	int (*acquire_dquot) (struct dquot *);
 	int (*release_dquot) (struct dquot *);
@@ -479,13 +472,6 @@
 What filesystem should expect from the generic quota functions:
 
 		FS recursion	Held locks when called
-initialize:	yes		maybe dqonoff_sem
-drop:		yes		-
-alloc_space:	->mark_dirty()	-
-alloc_inode:	->mark_dirty()	-
-free_space:	->mark_dirty()	-
-free_inode:	->mark_dirty()	-
-transfer:	yes		-
 write_dquot:	yes		dqonoff_sem or dqptr_sem
 acquire_dquot:	yes		dqonoff_sem or dqptr_sem
 release_dquot:	yes		dqonoff_sem or dqptr_sem
@@ -495,10 +481,6 @@
 FS recursion means calling ->quota_read() and ->quota_write() from superblock
 operations.
 
-->alloc_space(), ->alloc_inode(), ->free_space(), ->free_inode() are called
-only directly by the filesystem and do not call any fs functions only
-the ->mark_dirty() operation.
-
 More details about quota locking can be found in fs/dquot.c.
 
 --------------------------- vm_operations_struct -----------------------------
diff --git a/Documentation/filesystems/Makefile b/Documentation/filesystems/Makefile
new file mode 100644
index 0000000..a5dd114
--- /dev/null
+++ b/Documentation/filesystems/Makefile
@@ -0,0 +1,8 @@
+# kbuild trick to avoid linker error. Can be omitted if a module is built.
+obj- := dummy.o
+
+# List of programs to build
+hostprogs-y := dnotify_test
+
+# Tell kbuild to always build the programs
+always := $(hostprogs-y)
diff --git a/Documentation/filesystems/dnotify.txt b/Documentation/filesystems/dnotify.txt
index 9f5d338..6baf88f 100644
--- a/Documentation/filesystems/dnotify.txt
+++ b/Documentation/filesystems/dnotify.txt
@@ -62,38 +62,9 @@
 
 Example
 -------
+See Documentation/filesystems/dnotify_test.c for an example.
 
-	#define _GNU_SOURCE	/* needed to get the defines */
-	#include <fcntl.h>	/* in glibc 2.2 this has the needed
-					   values defined */
-	#include <signal.h>
-	#include <stdio.h>
-	#include <unistd.h>
-
-	static volatile int event_fd;
-
-	static void handler(int sig, siginfo_t *si, void *data)
-	{
-		event_fd = si->si_fd;
-	}
-
-	int main(void)
-	{
-		struct sigaction act;
-		int fd;
-
-		act.sa_sigaction = handler;
-		sigemptyset(&act.sa_mask);
-		act.sa_flags = SA_SIGINFO;
-		sigaction(SIGRTMIN + 1, &act, NULL);
-
-		fd = open(".", O_RDONLY);
-		fcntl(fd, F_SETSIG, SIGRTMIN + 1);
-		fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_MULTISHOT);
-		/* we will now be notified if any of the files
-		   in "." is modified or new files are created */
-		while (1) {
-			pause();
-			printf("Got event on fd=%d\n", event_fd);
-		}
-	}
+NOTE
+----
+Beginning with Linux 2.6.13, dnotify has been replaced by inotify.
+See Documentation/filesystems/inotify.txt for more information on it.
diff --git a/Documentation/filesystems/dnotify_test.c b/Documentation/filesystems/dnotify_test.c
new file mode 100644
index 0000000..8b37b4a
--- /dev/null
+++ b/Documentation/filesystems/dnotify_test.c
@@ -0,0 +1,34 @@
+#define _GNU_SOURCE	/* needed to get the defines */
+#include <fcntl.h>	/* in glibc 2.2 this has the needed
+				   values defined */
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static volatile int event_fd;
+
+static void handler(int sig, siginfo_t *si, void *data)
+{
+	event_fd = si->si_fd;
+}
+
+int main(void)
+{
+	struct sigaction act;
+	int fd;
+
+	act.sa_sigaction = handler;
+	sigemptyset(&act.sa_mask);
+	act.sa_flags = SA_SIGINFO;
+	sigaction(SIGRTMIN + 1, &act, NULL);
+
+	fd = open(".", O_RDONLY);
+	fcntl(fd, F_SETSIG, SIGRTMIN + 1);
+	fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_MULTISHOT);
+	/* we will now be notified if any of the files
+	   in "." is modified or new files are created */
+	while (1) {
+		pause();
+		printf("Got event on fd=%d\n", event_fd);
+	}
+}
diff --git a/Documentation/filesystems/logfs.txt b/Documentation/filesystems/logfs.txt
new file mode 100644
index 0000000..e64c94b
--- /dev/null
+++ b/Documentation/filesystems/logfs.txt
@@ -0,0 +1,241 @@
+
+The LogFS Flash Filesystem
+==========================
+
+Specification
+=============
+
+Superblocks
+-----------
+
+Two superblocks exist at the beginning and end of the filesystem.
+Each superblock is 256 Bytes large, with another 3840 Bytes reserved
+for future purposes, making a total of 4096 Bytes.
+
+Superblock locations may differ for MTD and block devices.  On MTD the
+first non-bad block contains a superblock in the first 4096 Bytes and
+the last non-bad block contains a superblock in the last 4096 Bytes.
+On block devices, the first 4096 Bytes of the device contain the first
+superblock and the last aligned 4096 Byte-block contains the second
+superblock.
+
+For the most part, the superblocks can be considered read-only.  They
+are written only to correct errors detected within the superblocks,
+move the journal and change the filesystem parameters through tunefs.
+As a result, the superblock does not contain any fields that require
+constant updates, like the amount of free space, etc.
+
+Segments
+--------
+
+The space in the device is split up into equal-sized segments.
+Segments are the primary write unit of LogFS.  Within each segments,
+writes happen from front (low addresses) to back (high addresses.  If
+only a partial segment has been written, the segment number, the
+current position within and optionally a write buffer are stored in
+the journal.
+
+Segments are erased as a whole.  Therefore Garbage Collection may be
+required to completely free a segment before doing so.
+
+Journal
+--------
+
+The journal contains all global information about the filesystem that
+is subject to frequent change.  At mount time, it has to be scanned
+for the most recent commit entry, which contains a list of pointers to
+all currently valid entries.
+
+Object Store
+------------
+
+All space except for the superblocks and journal is part of the object
+store.  Each segment contains a segment header and a number of
+objects, each consisting of the object header and the payload.
+Objects are either inodes, directory entries (dentries), file data
+blocks or indirect blocks.
+
+Levels
+------
+
+Garbage collection (GC) may fail if all data is written
+indiscriminately.  One requirement of GC is that data is seperated
+roughly according to the distance between the tree root and the data.
+Effectively that means all file data is on level 0, indirect blocks
+are on levels 1, 2, 3 4 or 5 for 1x, 2x, 3x, 4x or 5x indirect blocks,
+respectively.  Inode file data is on level 6 for the inodes and 7-11
+for indirect blocks.
+
+Each segment contains objects of a single level only.  As a result,
+each level requires its own seperate segment to be open for writing.
+
+Inode File
+----------
+
+All inodes are stored in a special file, the inode file.  Single
+exception is the inode file's inode (master inode) which for obvious
+reasons is stored in the journal instead.  Instead of data blocks, the
+leaf nodes of the inode files are inodes.
+
+Aliases
+-------
+
+Writes in LogFS are done by means of a wandering tree.  A naïve
+implementation would require that for each write or a block, all
+parent blocks are written as well, since the block pointers have
+changed.  Such an implementation would not be very efficient.
+
+In LogFS, the block pointer changes are cached in the journal by means
+of alias entries.  Each alias consists of its logical address - inode
+number, block index, level and child number (index into block) - and
+the changed data.  Any 8-byte word can be changes in this manner.
+
+Currently aliases are used for block pointers, file size, file used
+bytes and the height of an inodes indirect tree.
+
+Segment Aliases
+---------------
+
+Related to regular aliases, these are used to handle bad blocks.
+Initially, bad blocks are handled by moving the affected segment
+content to a spare segment and noting this move in the journal with a
+segment alias, a simple (to, from) tupel.  GC will later empty this
+segment and the alias can be removed again.  This is used on MTD only.
+
+Vim
+---
+
+By cleverly predicting the life time of data, it is possible to
+seperate long-living data from short-living data and thereby reduce
+the GC overhead later.  Each type of distinc life expectency (vim) can
+have a seperate segment open for writing.  Each (level, vim) tupel can
+be open just once.  If an open segment with unknown vim is encountered
+at mount time, it is closed and ignored henceforth.
+
+Indirect Tree
+-------------
+
+Inodes in LogFS are similar to FFS-style filesystems with direct and
+indirect block pointers.  One difference is that LogFS uses a single
+indirect pointer that can be either a 1x, 2x, etc. indirect pointer.
+A height field in the inode defines the height of the indirect tree
+and thereby the indirection of the pointer.
+
+Another difference is the addressing of indirect blocks.  In LogFS,
+the first 16 pointers in the first indirect block are left empty,
+corresponding to the 16 direct pointers in the inode.  In ext2 (maybe
+others as well) the first pointer in the first indirect block
+corresponds to logical block 12, skipping the 12 direct pointers.
+So where ext2 is using arithmetic to better utilize space, LogFS keeps
+arithmetic simple and uses compression to save space.
+
+Compression
+-----------
+
+Both file data and metadata can be compressed.  Compression for file
+data can be enabled with chattr +c and disabled with chattr -c.  Doing
+so has no effect on existing data, but new data will be stored
+accordingly.  New inodes will inherit the compression flag of the
+parent directory.
+
+Metadata is always compressed.  However, the space accounting ignores
+this and charges for the uncompressed size.  Failing to do so could
+result in GC failures when, after moving some data, indirect blocks
+compress worse than previously.  Even on a 100% full medium, GC may
+not consume any extra space, so the compression gains are lost space
+to the user.
+
+However, they are not lost space to the filesystem internals.  By
+cheating the user for those bytes, the filesystem gained some slack
+space and GC will run less often and faster.
+
+Garbage Collection and Wear Leveling
+------------------------------------
+
+Garbage collection is invoked whenever the number of free segments
+falls below a threshold.  The best (known) candidate is picked based
+on the least amount of valid data contained in the segment.  All
+remaining valid data is copied elsewhere, thereby invalidating it.
+
+The GC code also checks for aliases and writes then back if their
+number gets too large.
+
+Wear leveling is done by occasionally picking a suboptimal segment for
+garbage collection.  If a stale segments erase count is significantly
+lower than the active segments' erase counts, it will be picked.  Wear
+leveling is rate limited, so it will never monopolize the device for
+more than one segment worth at a time.
+
+Values for "occasionally", "significantly lower" are compile time
+constants.
+
+Hashed directories
+------------------
+
+To satisfy efficient lookup(), directory entries are hashed and
+located based on the hash.  In order to both support large directories
+and not be overly inefficient for small directories, several hash
+tables of increasing size are used.  For each table, the hash value
+modulo the table size gives the table index.
+
+Tables sizes are chosen to limit the number of indirect blocks with a
+fully populated table to 0, 1, 2 or 3 respectively.  So the first
+table contains 16 entries, the second 512-16, etc.
+
+The last table is special in several ways.  First its size depends on
+the effective 32bit limit on telldir/seekdir cookies.  Since logfs
+uses the upper half of the address space for indirect blocks, the size
+is limited to 2^31.  Secondly the table contains hash buckets with 16
+entries each.
+
+Using single-entry buckets would result in birthday "attacks".  At
+just 2^16 used entries, hash collisions would be likely (P >= 0.5).
+My math skills are insufficient to do the combinatorics for the 17x
+collisions necessary to overflow a bucket, but testing showed that in
+10,000 runs the lowest directory fill before a bucket overflow was
+188,057,130 entries with an average of 315,149,915 entries.  So for
+directory sizes of up to a million, bucket overflows should be
+virtually impossible under normal circumstances.
+
+With carefully chosen filenames, it is obviously possible to cause an
+overflow with just 21 entries (4 higher tables + 16 entries + 1).  So
+there may be a security concern if a malicious user has write access
+to a directory.
+
+Open For Discussion
+===================
+
+Device Address Space
+--------------------
+
+A device address space is used for caching.  Both block devices and
+MTD provide functions to either read a single page or write a segment.
+Partial segments may be written for data integrity, but where possible
+complete segments are written for performance on simple block device
+flash media.
+
+Meta Inodes
+-----------
+
+Inodes are stored in the inode file, which is just a regular file for
+most purposes.  At umount time, however, the inode file needs to
+remain open until all dirty inodes are written.  So
+generic_shutdown_super() may not close this inode, but shouldn't
+complain about remaining inodes due to the inode file either.  Same
+goes for mapping inode of the device address space.
+
+Currently logfs uses a hack that essentially copies part of fs/inode.c
+code over.  A general solution would be preferred.
+
+Indirect block mapping
+----------------------
+
+With compression, the block device (or mapping inode) cannot be used
+to cache indirect blocks.  Some other place is required.  Currently
+logfs uses the top half of each inode's address space.  The low 8TB
+(on 32bit) are filled with file data, the high 8TB are used for
+indirect blocks.
+
+One problem is that 16TB files created on 64bit systems actually have
+data in the top 8TB.  But files >16TB would cause problems anyway, so
+only the limit has changed.
diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
index 1bd0d0c..6a53a84 100644
--- a/Documentation/filesystems/nfs/nfs41-server.txt
+++ b/Documentation/filesystems/nfs/nfs41-server.txt
@@ -17,8 +17,7 @@
 on or off; rpc.nfsd does this correctly.)
 
 The NFSv4 minorversion 1 (NFSv4.1) implementation in nfsd is based
-on the latest NFSv4.1 Internet Draft:
-http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-29
+on RFC 5661.
 
 From the many new features in NFSv4.1 the current implementation
 focuses on the mandatory-to-implement NFSv4.1 Sessions, providing
@@ -44,7 +43,7 @@
 	  trunking, but this is a mandatory feature, and its use is
 	  recommended to clients in a number of places.  (E.g. to ensure
 	  timely renewal in case an existing connection's retry timeouts
-	  have gotten too long; see section 8.3 of the draft.)
+	  have gotten too long; see section 8.3 of the RFC.)
 	  Therefore, lack of this feature may cause future clients to
 	  fail.
 	- Incomplete backchannel support: incomplete backchannel gss
diff --git a/Documentation/filesystems/nilfs2.txt b/Documentation/filesystems/nilfs2.txt
index 839efd8..cf6d0d8 100644
--- a/Documentation/filesystems/nilfs2.txt
+++ b/Documentation/filesystems/nilfs2.txt
@@ -74,6 +74,9 @@
 			This disables every write access on the device for
 			read-only mounts or snapshots.  This option will fail
 			for r/w mounts on an unclean volume.
+discard			Issue discard/TRIM commands to the underlying block
+			device when blocks are freed.  This is useful for SSD
+			devices and sparse/thinly-provisioned LUNs.
 
 NILFS2 usage
 ============
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 0d07513..a4f30fa 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -164,6 +164,7 @@
   VmExe:        68 kB
   VmLib:      1412 kB
   VmPTE:        20 kb
+  VmSwap:        0 kB
   Threads:        1
   SigQ:   0/28578
   SigPnd: 0000000000000000
@@ -188,7 +189,13 @@
 contains details information about the process itself.  Its fields are
 explained in Table 1-4.
 
-Table 1-2: Contents of the statm files (as of 2.6.30-rc7)
+(for SMP CONFIG users)
+For making accounting scalable, RSS related information are handled in
+asynchronous manner and the vaule may not be very precise. To see a precise
+snapshot of a moment, you can see /proc/<pid>/smaps file and scan page table.
+It's slow but very precise.
+
+Table 1-2: Contents of the status files (as of 2.6.30-rc7)
 ..............................................................................
  Field                       Content
  Name                        filename of the executable
@@ -213,6 +220,7 @@
  VmExe                       size of text segment
  VmLib                       size of shared library code
  VmPTE                       size of page table entries
+ VmSwap                      size of swap usage (the number of referred swapents)
  Threads                     number of threads
  SigQ                        number of signals queued/max. number for queue
  SigPnd                      bitmap of pending signals for the thread
@@ -430,6 +438,7 @@
  modules     List of loaded modules                            
  mounts      Mounted filesystems                               
  net         Networking info (see text)                        
+ pagetypeinfo Additional page allocator information (see text)  (2.5)
  partitions  Table of partitions known to the system           
  pci	     Deprecated info of PCI bus (new way -> /proc/bus/pci/,
              decoupled by lspci					(2.4)
@@ -584,7 +593,7 @@
 Node 0, zone   Normal      1      0      0      1    101      8 ...
 Node 0, zone  HighMem      2      0      0      1      1      0 ...
 
-Memory fragmentation is a problem under some workloads, and buddyinfo is a 
+External fragmentation is a problem under some workloads, and buddyinfo is a
 useful tool for helping diagnose these problems.  Buddyinfo will give you a 
 clue as to how big an area you can safely allocate, or why a previous
 allocation failed.
@@ -594,6 +603,48 @@
 ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE 
 available in ZONE_NORMAL, etc... 
 
+More information relevant to external fragmentation can be found in
+pagetypeinfo.
+
+> cat /proc/pagetypeinfo
+Page block order: 9
+Pages per block:  512
+
+Free pages count per migrate type at order       0      1      2      3      4      5      6      7      8      9     10
+Node    0, zone      DMA, type    Unmovable      0      0      0      1      1      1      1      1      1      1      0
+Node    0, zone      DMA, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0
+Node    0, zone      DMA, type      Movable      1      1      2      1      2      1      1      0      1      0      2
+Node    0, zone      DMA, type      Reserve      0      0      0      0      0      0      0      0      0      1      0
+Node    0, zone      DMA, type      Isolate      0      0      0      0      0      0      0      0      0      0      0
+Node    0, zone    DMA32, type    Unmovable    103     54     77      1      1      1     11      8      7      1      9
+Node    0, zone    DMA32, type  Reclaimable      0      0      2      1      0      0      0      0      1      0      0
+Node    0, zone    DMA32, type      Movable    169    152    113     91     77     54     39     13      6      1    452
+Node    0, zone    DMA32, type      Reserve      1      2      2      2      2      0      1      1      1      1      0
+Node    0, zone    DMA32, type      Isolate      0      0      0      0      0      0      0      0      0      0      0
+
+Number of blocks type     Unmovable  Reclaimable      Movable      Reserve      Isolate
+Node 0, zone      DMA            2            0            5            1            0
+Node 0, zone    DMA32           41            6          967            2            0
+
+Fragmentation avoidance in the kernel works by grouping pages of different
+migrate types into the same contiguous regions of memory called page blocks.
+A page block is typically the size of the default hugepage size e.g. 2MB on
+X86-64. By keeping pages grouped based on their ability to move, the kernel
+can reclaim pages within a page block to satisfy a high-order allocation.
+
+The pagetypinfo begins with information on the size of a page block. It
+then gives the same type of information as buddyinfo except broken down
+by migrate-type and finishes with details on how many page blocks of each
+type exist.
+
+If min_free_kbytes has been tuned correctly (recommendations made by hugeadm
+from libhugetlbfs http://sourceforge.net/projects/libhugetlbfs/), one can
+make an estimate of the likely number of huge pages that can be allocated
+at a given point in time. All the "Movable" blocks should be allocatable
+unless memory has been mlock()'d. Some of the Reclaimable blocks should
+also be allocatable although a lot of filesystem metadata may have to be
+reclaimed to achieve this.
+
 ..............................................................................
 
 meminfo:
diff --git a/Documentation/filesystems/sharedsubtree.txt b/Documentation/filesystems/sharedsubtree.txt
index 23a1810..fc0e39a 100644
--- a/Documentation/filesystems/sharedsubtree.txt
+++ b/Documentation/filesystems/sharedsubtree.txt
@@ -837,6 +837,9 @@
 	 individual lists does not affect propagation or the way propagation
 	 tree is modified by operations.
 
+	All vfsmounts in a peer group have the same ->mnt_master.  If it is
+	non-NULL, they form a contiguous (ordered) segment of slave list.
+
 	A example propagation tree looks as shown in the figure below.
 	[ NOTE: Though it looks like a forest, if we consider all the shared
 	mounts as a conceptual entity called 'pnode', it becomes a tree]
@@ -874,8 +877,19 @@
 
 	NOTE: The propagation tree is orthogonal to the mount tree.
 
+8B Locking:
 
-8B Algorithm:
+	->mnt_share, ->mnt_slave, ->mnt_slave_list, ->mnt_master are protected
+	by namespace_sem (exclusive for modifications, shared for reading).
+
+	Normally we have ->mnt_flags modifications serialized by vfsmount_lock.
+	There are two exceptions: do_add_mount() and clone_mnt().
+	The former modifies a vfsmount that has not been visible in any shared
+	data structures yet.
+	The latter holds namespace_sem and the only references to vfsmount
+	are in lists that can't be traversed without namespace_sem.
+
+8C Algorithm:
 
 	The crux of the implementation resides in rbind/move operation.
 
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index 1866c27..c2c6e9b 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -253,6 +253,70 @@
 Also note that it's your responsibility to have stopped using a GPIO
 before you free it.
 
+Considering in most cases GPIOs are actually configured right after they
+are claimed, three additional calls are defined:
+
+	/* request a single GPIO, with initial configuration specified by
+	 * 'flags', identical to gpio_request() wrt other arguments and
+	 * return value
+	 */
+	int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
+
+	/* request multiple GPIOs in a single call
+	 */
+	int gpio_request_array(struct gpio *array, size_t num);
+
+	/* release multiple GPIOs in a single call
+	 */
+	void gpio_free_array(struct gpio *array, size_t num);
+
+where 'flags' is currently defined to specify the following properties:
+
+	* GPIOF_DIR_IN		- to configure direction as input
+	* GPIOF_DIR_OUT		- to configure direction as output
+
+	* GPIOF_INIT_LOW	- as output, set initial level to LOW
+	* GPIOF_INIT_HIGH	- as output, set initial level to HIGH
+
+since GPIOF_INIT_* are only valid when configured as output, so group valid
+combinations as:
+
+	* GPIOF_IN		- configure as input
+	* GPIOF_OUT_INIT_LOW	- configured as output, initial level LOW
+	* GPIOF_OUT_INIT_HIGH	- configured as output, initial level HIGH
+
+In the future, these flags can be extended to support more properties such
+as open-drain status.
+
+Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is
+introduced to encapsulate all three fields as:
+
+	struct gpio {
+		unsigned	gpio;
+		unsigned long	flags;
+		const char	*label;
+	};
+
+A typical example of usage:
+
+	static struct gpio leds_gpios[] = {
+		{ 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */
+		{ 33, GPIOF_OUT_INIT_LOW,  "Green LED" }, /* default to OFF */
+		{ 34, GPIOF_OUT_INIT_LOW,  "Red LED"   }, /* default to OFF */
+		{ 35, GPIOF_OUT_INIT_LOW,  "Blue LED"  }, /* default to OFF */
+		{ ... },
+	};
+
+	err = gpio_request_one(31, GPIOF_IN, "Reset Button");
+	if (err)
+		...
+
+	err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+	if (err)
+		...
+
+	gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+
 
 GPIOs mapped to IRQs
 --------------------
diff --git a/Documentation/hwmon/abituguru b/Documentation/hwmon/abituguru
index 87ffa0f..5eb3b9d 100644
--- a/Documentation/hwmon/abituguru
+++ b/Documentation/hwmon/abituguru
@@ -30,7 +30,7 @@
 	   bank1_types=1,1,0,0,0,0,0,2,0,0,0,0,2,0,0,1
 	   You may also need to specify the fan_sensors option for these boards
 	   fan_sensors=5
-	2) There is a seperate abituguru3 driver for these motherboards,
+	2) There is a separate abituguru3 driver for these motherboards,
 	   the abituguru (without the 3 !) driver will not work on these
 	   motherboards (and visa versa)!
 
diff --git a/Documentation/hwmon/adt7411 b/Documentation/hwmon/adt7411
new file mode 100644
index 0000000..1632960
--- /dev/null
+++ b/Documentation/hwmon/adt7411
@@ -0,0 +1,42 @@
+Kernel driver adt7411
+=====================
+
+Supported chips:
+  * Analog Devices ADT7411
+    Prefix: 'adt7411'
+    Addresses scanned: 0x48, 0x4a, 0x4b
+    Datasheet: Publicly available at the Analog Devices website
+
+Author: Wolfram Sang (based on adt7470 by Darrick J. Wong)
+
+Description
+-----------
+
+This driver implements support for the Analog Devices ADT7411 chip. There may
+be other chips that implement this interface.
+
+The ADT7411 can use an I2C/SMBus compatible 2-wire interface or an
+SPI-compatible 4-wire interface. It provides a 10-bit analog to digital
+converter which measures 1 temperature, vdd and 8 input voltages. It has an
+internal temperature sensor, but an external one can also be connected (one
+loses 2 inputs then). There are high- and low-limit registers for all inputs.
+
+Check the datasheet for details.
+
+sysfs-Interface
+---------------
+
+in0_input	- vdd voltage input
+in[1-8]_input	- analog 1-8 input
+temp1_input	- temperature input
+
+Besides standard interfaces, this driver adds (0 = off, 1 = on):
+
+  adc_ref_vdd	- Use vdd as reference instead of 2.25 V
+  fast_sampling	- Sample at 22.5 kHz instead of 1.4 kHz, but drop filters
+  no_average	- Turn off averaging over 16 samples
+
+Notes
+-----
+
+SPI, external temperature sensor and limit registers are not supported yet.
diff --git a/Documentation/hwmon/adt7473 b/Documentation/hwmon/adt7473
deleted file mode 100644
index 446612b..0000000
--- a/Documentation/hwmon/adt7473
+++ /dev/null
@@ -1,74 +0,0 @@
-Kernel driver adt7473
-======================
-
-Supported chips:
-  * Analog Devices ADT7473
-    Prefix: 'adt7473'
-    Addresses scanned: I2C 0x2C, 0x2D, 0x2E
-    Datasheet: Publicly available at the Analog Devices website
-
-Author: Darrick J. Wong
-
-This driver is depreacted, please use the adt7475 driver instead.
-
-Description
------------
-
-This driver implements support for the Analog Devices ADT7473 chip family.
-
-The ADT7473 uses the 2-wire interface compatible with the SMBUS 2.0
-specification. Using an analog to digital converter it measures three (3)
-temperatures and two (2) voltages. It has four (4) 16-bit counters for
-measuring fan speed. There are three (3) PWM outputs that can be used
-to control fan speed.
-
-A sophisticated control system for the PWM outputs is designed into the
-ADT7473 that allows fan speed to be adjusted automatically based on any of the
-three temperature sensors. Each PWM output is individually adjustable and
-programmable. Once configured, the ADT7473 will adjust the PWM outputs in
-response to the measured temperatures without further host intervention.
-This feature can also be disabled for manual control of the PWM's.
-
-Each of the measured inputs (voltage, temperature, fan speed) has
-corresponding high/low limit values. The ADT7473 will signal an ALARM if
-any measured value exceeds either limit.
-
-The ADT7473 samples all inputs continuously. The driver will not read
-the registers more often than once every other second. Further,
-configuration data is only read once per minute.
-
-Special Features
-----------------
-
-The ADT7473 have a 10-bit ADC and can therefore measure temperatures
-with 0.25 degC resolution. Temperature readings can be configured either
-for twos complement format or "Offset 64" format, wherein 63 is subtracted
-from the raw value to get the temperature value.
-
-The Analog Devices datasheet is very detailed and describes a procedure for
-determining an optimal configuration for the automatic PWM control.
-
-Configuration Notes
--------------------
-
-Besides standard interfaces driver adds the following:
-
-* PWM Control
-
-* pwm#_auto_point1_pwm and temp#_auto_point1_temp and
-* pwm#_auto_point2_pwm and temp#_auto_point2_temp -
-
-point1: Set the pwm speed at a lower temperature bound.
-point2: Set the pwm speed at a higher temperature bound.
-
-The ADT7473 will scale the pwm between the lower and higher pwm speed when
-the temperature is between the two temperature boundaries.  PWM values range
-from 0 (off) to 255 (full speed).  Fan speed will be set to maximum when the
-temperature sensor associated with the PWM control exceeds temp#_max.
-
-Notes
------
-
-The NVIDIA binary driver presents an ADT7473 chip via an on-card i2c bus.
-Unfortunately, they fail to set the i2c adapter class, so this driver may
-fail to find the chip until the nvidia driver is patched.
diff --git a/Documentation/hwmon/asc7621 b/Documentation/hwmon/asc7621
new file mode 100644
index 0000000..7287be7
--- /dev/null
+++ b/Documentation/hwmon/asc7621
@@ -0,0 +1,296 @@
+Kernel driver asc7621
+==================
+
+Supported chips:
+    Andigilog aSC7621 and aSC7621a
+    Prefix: 'asc7621'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.fairview5.com/linux/asc7621/asc7621.pdf
+
+Author:
+		George Joseph
+
+Description provided by Dave Pivin @ Andigilog:
+
+Andigilog has both the PECI and pre-PECI versions of the Heceta-6, as
+Intel calls them. Heceta-6e has high frequency PWM and Heceta-6p has
+added PECI and a 4th thermal zone. The Andigilog aSC7611 is the
+Heceta-6e part and aSC7621 is the Heceta-6p part. They are both in
+volume production, shipping to Intel and their subs.
+
+We have enhanced both parts relative to the governing Intel
+specification. First enhancement is temperature reading resolution. We
+have used registers below 20h for vendor-specific functions in addition
+to those in the Intel-specified vendor range.
+
+Our conversion process produces a result that is reported as two bytes.
+The fan speed control uses this finer value to produce a "step-less" fan
+PWM output. These two bytes are "read-locked" to guarantee that once a
+high or low byte is read, the other byte is locked-in until after the
+next read of any register. So to get an atomic reading, read high or low
+byte, then the very next read should be the opposite byte. Our data
+sheet says 10-bits of resolution, although you may find the lower bits
+are active, they are not necessarily reliable or useful externally. We
+chose not to mask them.
+
+We employ significant filtering that is user tunable as described in the
+data sheet. Our temperature reports and fan PWM outputs are very smooth
+when compared to the competition, in addition to the higher resolution
+temperature reports. The smoother PWM output does not require user
+intervention.
+
+We offer GPIO features on the former VID pins. These are open-drain
+outputs or inputs and may be used as general purpose I/O or as alarm
+outputs that are based on temperature limits. These are in 19h and 1Ah.
+
+We offer flexible mapping of temperature readings to thermal zones. Any
+temperature may be mapped to any zone, which has a default assignment
+that follows Intel's specs.
+
+Since there is a fan to zone assignment that allows for the "hotter" of
+a set of zones to control the PWM of an individual fan, but there is no
+indication to the user, we have added an indicator that shows which zone
+is currently controlling the PWM for a given fan. This is in register
+00h.
+
+Both remote diode temperature readings may be given an offset value such
+that the reported reading as well as the temperature used to determine
+PWM may be offset for system calibration purposes.
+
+PECI Extended configuration allows for having more than two domains per
+PECI address and also provides an enabling function for each PECI
+address. One could use our flexible zone assignment to have a zone
+assigned to up to 4 PECI addresses. This is not possible in the default
+Intel configuration. This would be useful in multi-CPU systems with
+individual fans on each that would benefit from individual fan control.
+This is in register 0Eh.
+
+The tachometer measurement system is flexible and able to adapt to many
+fan types. We can also support pulse-stretched PWM so that 3-wire fans
+may be used. These characteristics are in registers 04h to 07h.
+
+Finally, we have added a tach disable function that turns off the tach
+measurement system for individual tachs in order to save power. That is
+in register 75h.
+
+--
+aSC7621 Product Description
+
+The aSC7621 has a two wire digital interface compatible with SMBus 2.0.
+Using a 10-bit ADC, the aSC7621 measures the temperature of two remote diode
+connected transistors as well as its own die. Support for Platform
+Environmental Control Interface (PECI) is included.
+
+Using temperature information from these four zones, an automatic fan speed
+control algorithm is employed to minimize acoustic impact while achieving
+recommended CPU temperature under varying operational loads.
+
+To set fan speed, the aSC7621 has three independent pulse width modulation
+(PWM) outputs that are controlled by one, or a combination of three,
+temperature zones. Both high- and low-frequency PWM ranges are supported.
+
+The aSC7621 also includes a digital filter that can be invoked to smooth
+temperature readings for better control of fan speed and minimum acoustic
+impact.
+
+The aSC7621 has tachometer inputs to measure fan speed on up to four fans.
+Limit and status registers for all measured values are included to alert
+the system host that any measurements are outside of programmed limits
+via status registers.
+
+System voltages of VCCP, 2.5V, 3.3V, 5.0V, and 12V motherboard power are
+monitored efficiently with internal scaling resistors.
+
+Features
+- Supports PECI interface and monitors internal and remote thermal diodes
+- 2-wire, SMBus 2.0 compliant, serial interface
+- 10-bit ADC
+- Monitors VCCP, 2.5V, 3.3V, 5.0V, and 12V motherboard/processor supplies
+- Programmable autonomous fan control based on temperature readings
+- Noise filtering of temperature reading for fan speed control
+- 0.25C digital temperature sensor resolution
+- 3 PWM fan speed control outputs for 2-, 3- or 4-wire fans and up to 4 fan
+	tachometer inputs
+- Enhanced measured temperature to Temperature Zone assignment.
+- Provides high and low PWM frequency ranges
+- 3 GPIO pins for custom use
+- 24-Lead QSOP package
+
+Configuration Notes
+===================
+
+Except where noted below, the sysfs entries created by this driver follow
+the standards defined in "sysfs-interface".
+
+temp1_source
+	0 	(default) peci_legacy = 0, Remote 1 Temperature
+			peci_legacy = 1, PECI Processor Temperature 0
+	1 	Remote 1 Temperature
+	2 	Remote 2 Temperature
+	3 	Internal Temperature
+	4 	PECI Processor Temperature 0
+	5 	PECI Processor Temperature 1
+	6 	PECI Processor Temperature 2
+	7  PECI Processor Temperature 3
+
+temp2_source
+	0 	(default) Internal Temperature
+	1 	Remote 1 Temperature
+	2 	Remote 2 Temperature
+	3 	Internal Temperature
+	4 	PECI Processor Temperature 0
+	5 	PECI Processor Temperature 1
+	6 	PECI Processor Temperature 2
+	7 	PECI Processor Temperature 3
+
+temp3_source
+	0 	(default) Remote 2 Temperature
+	1 	Remote 1 Temperature
+	2 	Remote 2 Temperature
+	3 	Internal Temperature
+	4 	PECI Processor Temperature 0
+	5 	PECI Processor Temperature 1
+	6 	PECI Processor Temperature 2
+	7 	PECI Processor Temperature 3
+
+temp4_source
+	0 	(default) peci_legacy = 0, PECI Processor Temperature 0
+			peci_legacy = 1, Remote 1 Temperature
+	1 	Remote 1 Temperature
+	2 	Remote 2 Temperature
+	3 	Internal Temperature
+	4 	PECI Processor Temperature 0
+	5 	PECI Processor Temperature 1
+	6 	PECI Processor Temperature 2
+	7 	PECI Processor Temperature 3
+
+temp[1-4]_smoothing_enable
+temp[1-4]_smoothing_time
+	Smooths spikes in temp readings caused by noise.
+	Valid values in milliseconds are:
+	35000
+	17600
+	11800
+	 7000
+	 4400
+	 3000
+	 1600
+	  800
+
+temp[1-4]_crit
+	When the corresponding zone temperature reaches this value,
+	ALL pwm outputs will got to 100%.
+
+temp[5-8]_input
+temp[5-8]_enable
+	The aSC7621 can also read temperatures provided by the processor
+	via the PECI bus.  Usually these are "core" temps and are relative
+	to the point where the automatic thermal control circuit starts
+	throttling.  This means that these are usually negative numbers.
+
+pwm[1-3]_enable
+	0		Fan off.
+	1		Fan on manual control.
+	2		Fan on automatic control and will run at the minimum pwm
+				if the temperature for the zone is below the minimum.
+	3		Fan on automatic control but will be off if the temperature
+				for the zone is below the minimum.
+	4-254	Ignored.
+	255		Fan on full.
+
+pwm[1-3]_auto_channels
+	Bitmap as described in sysctl-interface with the following
+	exceptions...
+	Only the following combination of zones (and their corresponding masks)
+	are valid:
+	1
+	2
+	3
+	2,3
+	1,2,3
+	4
+	1,2,3,4
+
+	Special values:
+	0			Disabled.
+	16		Fan on manual control.
+	31		Fan on full.
+
+
+pwm[1-3]_invert
+	When set, inverts the meaning of pwm[1-3].
+	i.e.  when pwm = 0, the fan will be on full and
+	when pwm = 255 the fan will be off.
+
+pwm[1-3]_freq
+	PWM frequency in Hz
+	Valid values in Hz are:
+
+	10
+	15
+	23
+	30  (default)
+	38
+	47
+	62
+	94
+	23000
+	24000
+	25000
+	26000
+	27000
+	28000
+	29000
+	30000
+
+	Setting any other value will be ignored.
+
+peci_enable
+	Enables or disables PECI
+
+peci_avg
+	Input filter average time.
+
+	0 	0 Sec. (no Smoothing) (default)
+	1 	0.25 Sec.
+	2 	0.5 Sec.
+	3 	1.0 Sec.
+	4 	2.0 Sec.
+	5 	4.0 Sec.
+	6 	8.0 Sec.
+	7 	0.0 Sec.
+
+peci_legacy
+
+	0	Standard Mode (default)
+		Remote Diode 1 reading is associated with
+		Temperature Zone 1, PECI is associated with
+		Zone 4
+
+	1	Legacy Mode
+		PECI is associated with Temperature Zone 1,
+		Remote Diode 1 is associated with Zone 4
+
+peci_diode
+	Diode filter
+
+	0	0.25 Sec.
+	1 	1.1 Sec.
+	2 	2.4 Sec.  (default)
+	3 	3.4 Sec.
+	4 	5.0 Sec.
+	5 	6.8 Sec.
+	6 	10.2 Sec.
+	7 	16.4 Sec.
+
+peci_4domain
+	Four domain enable
+
+	0 	1 or 2 Domains for enabled processors (default)
+	1 	3 or 4 Domains for enabled processors
+
+peci_domain
+	Domain
+
+	0 	Processor contains a single domain (0) 	 (default)
+	1 	Processor contains two domains (0,1)
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index f9ba96c..8d08bf0 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -5,31 +5,23 @@
   * IT8705F
     Prefix: 'it87'
     Addresses scanned: from Super I/O config space (8 I/O ports)
-    Datasheet: Publicly available at the ITE website
-               http://www.ite.com.tw/product_info/file/pc/IT8705F_V.0.4.1.pdf
+    Datasheet: Once publicly available at the ITE website, but no longer
   * IT8712F
     Prefix: 'it8712'
     Addresses scanned: from Super I/O config space (8 I/O ports)
-    Datasheet: Publicly available at the ITE website
-               http://www.ite.com.tw/product_info/file/pc/IT8712F_V0.9.1.pdf
-               http://www.ite.com.tw/product_info/file/pc/Errata%20V0.1%20for%20IT8712F%20V0.9.1.pdf
-               http://www.ite.com.tw/product_info/file/pc/IT8712F_V0.9.3.pdf
+    Datasheet: Once publicly available at the ITE website, but no longer
   * IT8716F/IT8726F
     Prefix: 'it8716'
     Addresses scanned: from Super I/O config space (8 I/O ports)
-    Datasheet: Publicly available at the ITE website
-               http://www.ite.com.tw/product_info/file/pc/IT8716F_V0.3.ZIP
-               http://www.ite.com.tw/product_info/file/pc/IT8726F_V0.3.pdf
+    Datasheet: Once publicly available at the ITE website, but no longer
   * IT8718F
     Prefix: 'it8718'
     Addresses scanned: from Super I/O config space (8 I/O ports)
-    Datasheet: Publicly available at the ITE website
-               http://www.ite.com.tw/product_info/file/pc/IT8718F_V0.2.zip
-               http://www.ite.com.tw/product_info/file/pc/IT8718F_V0%203_(for%20C%20version).zip
+    Datasheet: Once publicly available at the ITE website, but no longer
   * IT8720F
     Prefix: 'it8720'
     Addresses scanned: from Super I/O config space (8 I/O ports)
-    Datasheet: Not yet publicly available.
+    Datasheet: Not publicly available
   * SiS950   [clone of IT8705F]
     Prefix: 'it87'
     Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -136,6 +128,10 @@
 seconds since the last update). This means that you can easily miss
 once-only alarms.
 
+Out-of-limit readings can also result in beeping, if the chip is properly
+wired and configured. Beeping can be enabled or disabled per sensor type
+(temperatures, voltages and fans.)
+
 The IT87xx only updates its values each 1.5 seconds; reading it more often
 will do no harm, but will return 'old' values.
 
@@ -150,11 +146,38 @@
 -----------------
 
 The fan speed control features are limited to manual PWM mode. Automatic
-"Smart Guardian" mode control handling is not implemented. However
-if you want to go for "manual mode" just write 1 to pwmN_enable.
+"Smart Guardian" mode control handling is only implemented for older chips
+(see below.) However if you want to go for "manual mode" just write 1 to
+pwmN_enable.
 
 If you are only able to control the fan speed with very small PWM values,
 try lowering the PWM base frequency (pwm1_freq). Depending on the fan,
 it may give you a somewhat greater control range. The same frequency is
 used to drive all fan outputs, which is why pwm2_freq and pwm3_freq are
 read-only.
+
+
+Automatic fan speed control (old interface)
+-------------------------------------------
+
+The driver supports the old interface to automatic fan speed control
+which is implemented by IT8705F chips up to revision F and IT8712F
+chips up to revision G.
+
+This interface implements 4 temperature vs. PWM output trip points.
+The PWM output of trip point 4 is always the maximum value (fan running
+at full speed) while the PWM output of the other 3 trip points can be
+freely chosen. The temperature of all 4 trip points can be freely chosen.
+Additionally, trip point 1 has an hysteresis temperature attached, to
+prevent fast switching between fan on and off.
+
+The chip automatically computes the PWM output value based on the input
+temperature, based on this simple rule: if the temperature value is
+between trip point N and trip point N+1 then the PWM output value is
+the one of trip point N. The automatic control mode is less flexible
+than the manual control mode, but it reacts faster, is more robust and
+doesn't use CPU cycles.
+
+Trip points must be set properly before switching to automatic fan speed
+control mode. The driver will perform basic integrity checks before
+actually switching to automatic control mode.
diff --git a/Documentation/hwmon/lm90 b/Documentation/hwmon/lm90
index 93d8e3d..6a03dd4 100644
--- a/Documentation/hwmon/lm90
+++ b/Documentation/hwmon/lm90
@@ -84,6 +84,10 @@
     Addresses scanned: I2C 0x4c
     Datasheet: Publicly available at the Maxim website
                http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3500
+  * Winbond/Nuvoton W83L771AWG/ASG
+    Prefix: 'w83l771'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Not publicly available, can be requested from Nuvoton
 
 
 Author: Jean Delvare <khali@linux-fr.org>
@@ -147,6 +151,12 @@
   * Selectable address
   * Remote sensor type selection
 
+W83L771AWG/ASG
+  * The AWG and ASG variants only differ in package format.
+  * Filter and alert configuration register at 0xBF
+  * Diode ideality factor configuration (remote sensor) at 0xE3
+  * Moving average (depending on conversion rate)
+
 All temperature values are given in degrees Celsius. Resolution
 is 1.0 degree for the local temperature, 0.125 degree for the remote
 temperature, except for the MAX6657, MAX6658 and MAX6659 which have a
@@ -163,6 +173,18 @@
 other second; reading them more often will do no harm, but will return
 'old' values.
 
+SMBus Alert Support
+-------------------
+
+This driver has basic support for SMBus alert. When an alert is received,
+the status register is read and the faulty temperature channel is logged.
+
+The Analog Devices chips (ADM1032 and ADT7461) do not implement the SMBus
+alert protocol properly so additional care is needed: the ALERT output is
+disabled when an alert is received, and is re-enabled only when the alarm
+is gone. Otherwise the chip would block alerts from other chips in the bus
+as long as the alarm is active.
+
 PEC Support
 -----------
 
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
index 81c0c59..e1bb5b2 100644
--- a/Documentation/i2c/busses/i2c-i801
+++ b/Documentation/i2c/busses/i2c-i801
@@ -15,7 +15,8 @@
   * Intel 82801I (ICH9)
   * Intel EP80579 (Tolapai)
   * Intel 82801JI (ICH10)
-  * Intel PCH
+  * Intel 3400/5 Series (PCH)
+  * Intel Cougar Point (PCH)
    Datasheets: Publicly available at the Intel website
 
 Authors: 
diff --git a/Documentation/i2c/busses/i2c-parport b/Documentation/i2c/busses/i2c-parport
index dceaba1..2461c7b 100644
--- a/Documentation/i2c/busses/i2c-parport
+++ b/Documentation/i2c/busses/i2c-parport
@@ -29,6 +29,9 @@
 Earlier kernels defaulted to type=0 (Philips).  But now, if the type
 parameter is missing, the driver will simply fail to initialize.
 
+SMBus alert support is available on adapters which have this line properly
+connected to the parallel port's interrupt pin.
+
 
 Building your own adapter
 -------------------------
diff --git a/Documentation/i2c/busses/i2c-parport-light b/Documentation/i2c/busses/i2c-parport-light
index 2874364..bdc9cbb 100644
--- a/Documentation/i2c/busses/i2c-parport-light
+++ b/Documentation/i2c/busses/i2c-parport-light
@@ -9,3 +9,14 @@
 and the impossibility to daisy-chain other parallel port devices.                 
   
 Please see i2c-parport for documentation.
+
+Module parameters:
+
+* type: type of adapter (see i2c-parport or modinfo)
+
+* base: base I/O address
+  Default is 0x378 which is fairly common for parallel ports, at least on PC.
+
+* irq: optional IRQ
+  This must be passed if you want SMBus alert support, assuming your adapter
+  actually supports this.
diff --git a/Documentation/i2c/smbus-protocol b/Documentation/i2c/smbus-protocol
index 9df4744..7c19d1a 100644
--- a/Documentation/i2c/smbus-protocol
+++ b/Documentation/i2c/smbus-protocol
@@ -185,6 +185,22 @@
 require PEC checksums.
 
 
+SMBus Alert
+===========
+
+SMBus Alert was introduced in Revision 1.0 of the specification.
+
+The SMBus alert protocol allows several SMBus slave devices to share a
+single interrupt pin on the SMBus master, while still allowing the master
+to know which slave triggered the interrupt.
+
+This is implemented the following way in the Linux kernel:
+* I2C bus drivers which support SMBus alert should call
+  i2c_setup_smbus_alert() to setup SMBus alert support.
+* I2C drivers for devices which can trigger SMBus alerts should implement
+  the optional alert() callback.
+
+
 I2C Block Transactions
 ======================
 
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 0a74603..3219ee0 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -318,8 +318,9 @@
 These routines read and write some bytes from/to a client. The client
 contains the i2c address, so you do not have to include it. The second
 parameter contains the bytes to read/write, the third the number of bytes
-to read/write (must be less than the length of the buffer.) Returned is
-the actual number of bytes read/written.
+to read/write (must be less than the length of the buffer, also should be
+less than 64k since msg.len is u16.) Returned is the actual number of bytes
+read/written.
 
 	int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 			 int num);
diff --git a/Documentation/init.txt b/Documentation/init.txt
new file mode 100644
index 0000000..535ad5e
--- /dev/null
+++ b/Documentation/init.txt
@@ -0,0 +1,49 @@
+Explaining the dreaded "No init found." boot hang message
+=========================================================
+
+OK, so you've got this pretty unintuitive message (currently located
+in init/main.c) and are wondering what the H*** went wrong.
+Some high-level reasons for failure (listed roughly in order of execution)
+to load the init binary are:
+A) Unable to mount root FS
+B) init binary doesn't exist on rootfs
+C) broken console device
+D) binary exists but dependencies not available
+E) binary cannot be loaded
+
+Detailed explanations:
+0) Set "debug" kernel parameter (in bootloader config file or CONFIG_CMDLINE)
+   to get more detailed kernel messages.
+A) make sure you have the correct root FS type
+   (and root= kernel parameter points to the correct partition),
+   required drivers such as storage hardware (such as SCSI or USB!)
+   and filesystem (ext3, jffs2 etc.) are builtin (alternatively as modules,
+   to be pre-loaded by an initrd)
+C) Possibly a conflict in console= setup --> initial console unavailable.
+   E.g. some serial consoles are unreliable due to serial IRQ issues (e.g.
+   missing interrupt-based configuration).
+   Try using a different console= device or e.g. netconsole= .
+D) e.g. required library dependencies of the init binary such as
+   /lib/ld-linux.so.2 missing or broken. Use readelf -d <INIT>|grep NEEDED
+   to find out which libraries are required.
+E) make sure the binary's architecture matches your hardware.
+   E.g. i386 vs. x86_64 mismatch, or trying to load x86 on ARM hardware.
+   In case you tried loading a non-binary file here (shell script?),
+   you should make sure that the script specifies an interpreter in its shebang
+   header line (#!/...) that is fully working (including its library
+   dependencies). And before tackling scripts, better first test a simple
+   non-script binary such as /bin/sh and confirm its successful execution.
+   To find out more, add code to init/main.c to display kernel_execve()s
+   return values.
+
+Please extend this explanation whenever you find new failure causes
+(after all loading the init binary is a CRITICAL and hard transition step
+which needs to be made as painless as possible), then submit patch to LKML.
+Further TODOs:
+- Implement the various run_init_process() invocations via a struct array
+  which can then store the kernel_execve() result value and on failure
+  log it all by iterating over _all_ results (very important usability fix).
+- try to make the implementation itself more helpful in general,
+  e.g. by providing additional error messages at affected places.
+
+Andreas Mohr <andi at lisas period de>
diff --git a/Documentation/input/rotary-encoder.txt b/Documentation/input/rotary-encoder.txt
index 3a6aec4..8b4129d 100644
--- a/Documentation/input/rotary-encoder.txt
+++ b/Documentation/input/rotary-encoder.txt
@@ -75,7 +75,7 @@
 the configuration.
 
 Because GPIO to IRQ mapping is platform specific, this information must
-be given in seperately to the driver. See the example below.
+be given in separately to the driver. See the example below.
 
 ---------<snip>---------
 
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 35cf64d..35c9b51 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -139,7 +139,6 @@
 'K'	all	linux/kd.h
 'L'	00-1F	linux/loop.h		conflict!
 'L'	10-1F	drivers/scsi/mpt2sas/mpt2sas_ctl.h	conflict!
-'L'	20-2F	linux/usb/vstusb.h
 'L'	E0-FF	linux/ppdd.h		encrypted disk device driver
 					<http://linux01.gwdg.de/~alatham/ppdd.html>
 'M'	all	linux/soundcard.h	conflict!
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index fbcddc5..3bc48b0 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1794,6 +1794,12 @@
 			purges which is reported from either PAL_VM_SUMMARY or
 			SAL PALO.
 
+	nr_cpus=	[SMP] Maximum number of processors that	an SMP kernel
+			could support.  nr_cpus=n : n >= 1 limits the kernel to
+			supporting 'n' processors. Later in runtime you can not
+			use hotplug cpu feature to put more cpu back to online.
+			just like you compile the kernel NR_CPUS=n
+
 	nr_uarts=	[SERIAL] maximum number of UARTs to be registered.
 
 	numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
@@ -2828,6 +2834,12 @@
 			default x2apic cluster mode on platforms
 			supporting x2apic.
 
+	x86_mrst_timer= [X86-32,APBT]
+			Choose timer option for x86 Moorestown MID platform.
+			Two valid options are apbt timer only and lapic timer
+			plus one apbt timer for broadcast timer.
+			x86_mrst_timer=apbt_only | lapic_and_apbt
+
 	xd=		[HW,XT] Original XT pre-IDE (RLL encoded) disks.
 	xd_geo=		See header of drivers/block/xd.c.
 
diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
index c79ab99..bdb1381 100644
--- a/Documentation/kobject.txt
+++ b/Documentation/kobject.txt
@@ -266,7 +266,7 @@
 
     struct kobj_type {
 	    void (*release)(struct kobject *);
-	    struct sysfs_ops	*sysfs_ops;
+	    const struct sysfs_ops *sysfs_ops;
 	    struct attribute	**default_attrs;
     };
 
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
index 053037a..2f9115c 100644
--- a/Documentation/kprobes.txt
+++ b/Documentation/kprobes.txt
@@ -1,6 +1,7 @@
 Title	: Kernel Probes (Kprobes)
 Authors	: Jim Keniston <jkenisto@us.ibm.com>
-	: Prasanna S Panchamukhi <prasanna@in.ibm.com>
+	: Prasanna S Panchamukhi <prasanna.panchamukhi@gmail.com>
+	: Masami Hiramatsu <mhiramat@redhat.com>
 
 CONTENTS
 
@@ -15,6 +16,7 @@
 9. Jprobes Example
 10. Kretprobes Example
 Appendix A: The kprobes debugfs interface
+Appendix B: The kprobes sysctl interface
 
 1. Concepts: Kprobes, Jprobes, Return Probes
 
@@ -42,13 +44,13 @@
 can speed up unregistration process when you have to unregister
 a lot of probes at once.
 
-The next three subsections explain how the different types of
-probes work.  They explain certain things that you'll need to
-know in order to make the best use of Kprobes -- e.g., the
-difference between a pre_handler and a post_handler, and how
-to use the maxactive and nmissed fields of a kretprobe.  But
-if you're in a hurry to start using Kprobes, you can skip ahead
-to section 2.
+The next four subsections explain how the different types of
+probes work and how jump optimization works.  They explain certain
+things that you'll need to know in order to make the best use of
+Kprobes -- e.g., the difference between a pre_handler and
+a post_handler, and how to use the maxactive and nmissed fields of
+a kretprobe.  But if you're in a hurry to start using Kprobes, you
+can skip ahead to section 2.
 
 1.1 How Does a Kprobe Work?
 
@@ -161,13 +163,125 @@
 object available, then in addition to incrementing the nmissed count,
 the user entry_handler invocation is also skipped.
 
+1.4 How Does Jump Optimization Work?
+
+If you configured your kernel with CONFIG_OPTPROBES=y (currently
+this option is supported on x86/x86-64, non-preemptive kernel) and
+the "debug.kprobes_optimization" kernel parameter is set to 1 (see
+sysctl(8)), Kprobes tries to reduce probe-hit overhead by using a jump
+instruction instead of a breakpoint instruction at each probepoint.
+
+1.4.1 Init a Kprobe
+
+When a probe is registered, before attempting this optimization,
+Kprobes inserts an ordinary, breakpoint-based kprobe at the specified
+address. So, even if it's not possible to optimize this particular
+probepoint, there'll be a probe there.
+
+1.4.2 Safety Check
+
+Before optimizing a probe, Kprobes performs the following safety checks:
+
+- Kprobes verifies that the region that will be replaced by the jump
+instruction (the "optimized region") lies entirely within one function.
+(A jump instruction is multiple bytes, and so may overlay multiple
+instructions.)
+
+- Kprobes analyzes the entire function and verifies that there is no
+jump into the optimized region.  Specifically:
+  - the function contains no indirect jump;
+  - the function contains no instruction that causes an exception (since
+  the fixup code triggered by the exception could jump back into the
+  optimized region -- Kprobes checks the exception tables to verify this);
+  and
+  - there is no near jump to the optimized region (other than to the first
+  byte).
+
+- For each instruction in the optimized region, Kprobes verifies that
+the instruction can be executed out of line.
+
+1.4.3 Preparing Detour Buffer
+
+Next, Kprobes prepares a "detour" buffer, which contains the following
+instruction sequence:
+- code to push the CPU's registers (emulating a breakpoint trap)
+- a call to the trampoline code which calls user's probe handlers.
+- code to restore registers
+- the instructions from the optimized region
+- a jump back to the original execution path.
+
+1.4.4 Pre-optimization
+
+After preparing the detour buffer, Kprobes verifies that none of the
+following situations exist:
+- The probe has either a break_handler (i.e., it's a jprobe) or a
+post_handler.
+- Other instructions in the optimized region are probed.
+- The probe is disabled.
+In any of the above cases, Kprobes won't start optimizing the probe.
+Since these are temporary situations, Kprobes tries to start
+optimizing it again if the situation is changed.
+
+If the kprobe can be optimized, Kprobes enqueues the kprobe to an
+optimizing list, and kicks the kprobe-optimizer workqueue to optimize
+it.  If the to-be-optimized probepoint is hit before being optimized,
+Kprobes returns control to the original instruction path by setting
+the CPU's instruction pointer to the copied code in the detour buffer
+-- thus at least avoiding the single-step.
+
+1.4.5 Optimization
+
+The Kprobe-optimizer doesn't insert the jump instruction immediately;
+rather, it calls synchronize_sched() for safety first, because it's
+possible for a CPU to be interrupted in the middle of executing the
+optimized region(*).  As you know, synchronize_sched() can ensure
+that all interruptions that were active when synchronize_sched()
+was called are done, but only if CONFIG_PREEMPT=n.  So, this version
+of kprobe optimization supports only kernels with CONFIG_PREEMPT=n.(**)
+
+After that, the Kprobe-optimizer calls stop_machine() to replace
+the optimized region with a jump instruction to the detour buffer,
+using text_poke_smp().
+
+1.4.6 Unoptimization
+
+When an optimized kprobe is unregistered, disabled, or blocked by
+another kprobe, it will be unoptimized.  If this happens before
+the optimization is complete, the kprobe is just dequeued from the
+optimized list.  If the optimization has been done, the jump is
+replaced with the original code (except for an int3 breakpoint in
+the first byte) by using text_poke_smp().
+
+(*)Please imagine that the 2nd instruction is interrupted and then
+the optimizer replaces the 2nd instruction with the jump *address*
+while the interrupt handler is running. When the interrupt
+returns to original address, there is no valid instruction,
+and it causes an unexpected result.
+
+(**)This optimization-safety checking may be replaced with the
+stop-machine method that ksplice uses for supporting a CONFIG_PREEMPT=y
+kernel.
+
+NOTE for geeks:
+The jump optimization changes the kprobe's pre_handler behavior.
+Without optimization, the pre_handler can change the kernel's execution
+path by changing regs->ip and returning 1.  However, when the probe
+is optimized, that modification is ignored.  Thus, if you want to
+tweak the kernel's execution path, you need to suppress optimization,
+using one of the following techniques:
+- Specify an empty function for the kprobe's post_handler or break_handler.
+ or
+- Config CONFIG_OPTPROBES=n.
+ or
+- Execute 'sysctl -w debug.kprobes_optimization=n'
+
 2. Architectures Supported
 
 Kprobes, jprobes, and return probes are implemented on the following
 architectures:
 
-- i386
-- x86_64 (AMD-64, EM64T)
+- i386 (Supports jump optimization)
+- x86_64 (AMD-64, EM64T) (Supports jump optimization)
 - ppc64
 - ia64 (Does not support probes on instruction slot1.)
 - sparc64 (Return probes not yet implemented.)
@@ -193,6 +307,10 @@
 so you can use "objdump -d -l vmlinux" to see the source-to-object
 code mapping.
 
+If you want to reduce probing overhead, set "Kprobes jump optimization
+support" (CONFIG_OPTPROBES) to "y". You can find this option under the
+"Kprobes" line.
+
 4. API Reference
 
 The Kprobes API includes a "register" function and an "unregister"
@@ -389,7 +507,10 @@
 
 Kprobes allows multiple probes at the same address.  Currently,
 however, there cannot be multiple jprobes on the same function at
-the same time.
+the same time.  Also, a probepoint for which there is a jprobe or
+a post_handler cannot be optimized.  So if you install a jprobe,
+or a kprobe with a post_handler, at an optimized probepoint, the
+probepoint will be unoptimized automatically.
 
 In general, you can install a probe anywhere in the kernel.
 In particular, you can probe interrupt handlers.  Known exceptions
@@ -453,6 +574,38 @@
 on the x86_64 version of __switch_to(); the registration functions
 return -EINVAL.
 
+On x86/x86-64, since the Jump Optimization of Kprobes modifies
+instructions widely, there are some limitations to optimization. To
+explain it, we introduce some terminology. Imagine a 3-instruction
+sequence consisting of a two 2-byte instructions and one 3-byte
+instruction.
+
+        IA
+         |
+[-2][-1][0][1][2][3][4][5][6][7]
+        [ins1][ins2][  ins3 ]
+	[<-     DCR       ->]
+	   [<- JTPR ->]
+
+ins1: 1st Instruction
+ins2: 2nd Instruction
+ins3: 3rd Instruction
+IA:  Insertion Address
+JTPR: Jump Target Prohibition Region
+DCR: Detoured Code Region
+
+The instructions in DCR are copied to the out-of-line buffer
+of the kprobe, because the bytes in DCR are replaced by
+a 5-byte jump instruction. So there are several limitations.
+
+a) The instructions in DCR must be relocatable.
+b) The instructions in DCR must not include a call instruction.
+c) JTPR must not be targeted by any jump or call instruction.
+d) DCR must not straddle the border betweeen functions.
+
+Anyway, these limitations are checked by the in-kernel instruction
+decoder, so you don't need to worry about that.
+
 6. Probe Overhead
 
 On a typical CPU in use in 2005, a kprobe hit takes 0.5 to 1.0
@@ -476,6 +629,19 @@
 ppc64: POWER5 (gr), 1656 MHz (SMT disabled, 1 virtual CPU per physical CPU)
 k = 0.77 usec; j = 1.31; r = 1.26; kr = 1.45; jr = 1.99
 
+6.1 Optimized Probe Overhead
+
+Typically, an optimized kprobe hit takes 0.07 to 0.1 microseconds to
+process. Here are sample overhead figures (in usec) for x86 architectures.
+k = unoptimized kprobe, b = boosted (single-step skipped), o = optimized kprobe,
+r = unoptimized kretprobe, rb = boosted kretprobe, ro = optimized kretprobe.
+
+i386: Intel(R) Xeon(R) E5410, 2.33GHz, 4656.90 bogomips
+k = 0.80 usec; b = 0.33; o = 0.05; r = 1.10; rb = 0.61; ro = 0.33
+
+x86-64: Intel(R) Xeon(R) E5410, 2.33GHz, 4656.90 bogomips
+k = 0.99 usec; b = 0.43; o = 0.06; r = 1.24; rb = 0.68; ro = 0.30
+
 7. TODO
 
 a. SystemTap (http://sourceware.org/systemtap): Provides a simplified
@@ -523,7 +689,8 @@
 a virtual address that is no longer valid (module init sections, module
 virtual addresses that correspond to modules that've been unloaded),
 such probes are marked with [GONE]. If the probe is temporarily disabled,
-such probes are marked with [DISABLED].
+such probes are marked with [DISABLED]. If the probe is optimized, it is
+marked with [OPTIMIZED].
 
 /sys/kernel/debug/kprobes/enabled: Turn kprobes ON/OFF forcibly.
 
@@ -533,3 +700,19 @@
 file. Note that this knob just disarms and arms all kprobes and doesn't
 change each probe's disabling state. This means that disabled kprobes (marked
 [DISABLED]) will be not enabled if you turn ON all kprobes by this knob.
+
+
+Appendix B: The kprobes sysctl interface
+
+/proc/sys/debug/kprobes-optimization: Turn kprobes optimization ON/OFF.
+
+When CONFIG_OPTPROBES=y, this sysctl interface appears and it provides
+a knob to globally and forcibly turn jump optimization (see section
+1.4) ON or OFF. By default, jump optimization is allowed (ON).
+If you echo "0" to this file or set "debug.kprobes_optimization" to
+0 via sysctl, all optimized probes will be unoptimized, and any new
+probes registered after that will not be optimized.  Note that this
+knob *changes* the optimized state. This means that optimized probes
+(marked [OPTIMIZED]) will be unoptimized ([OPTIMIZED] tag will be
+removed). If the knob is turned on, they will be optimized again.
+
diff --git a/Documentation/kvm/api.txt b/Documentation/kvm/api.txt
index 2811e45..c6416a3 100644
--- a/Documentation/kvm/api.txt
+++ b/Documentation/kvm/api.txt
@@ -23,12 +23,12 @@
    Only run vcpu ioctls from the same thread that was used to create the
    vcpu.
 
-2. File descritpors
+2. File descriptors
 
 The kvm API is centered around file descriptors.  An initial
 open("/dev/kvm") obtains a handle to the kvm subsystem; this handle
 can be used to issue system ioctls.  A KVM_CREATE_VM ioctl on this
-handle will create a VM file descripror which can be used to issue VM
+handle will create a VM file descriptor which can be used to issue VM
 ioctls.  A KVM_CREATE_VCPU ioctl on a VM fd will create a virtual cpu
 and return a file descriptor pointing to it.  Finally, ioctls on a vcpu
 fd can be used to control the vcpu, including the important task of
@@ -643,7 +643,7 @@
 Parameters: struct kvm_clock_data (in)
 Returns: 0 on success, -1 on error
 
-Sets the current timestamp of kvmclock to the valued specific in its parameter.
+Sets the current timestamp of kvmclock to the value specified in its parameter.
 In conjunction with KVM_GET_CLOCK, it is used to ensure monotonicity on scenarios
 such as migration.
 
@@ -795,11 +795,11 @@
 			__u64 data_offset; /* relative to kvm_run start */
 		} io;
 
-If exit_reason is KVM_EXIT_IO_IN or KVM_EXIT_IO_OUT, then the vcpu has
+If exit_reason is KVM_EXIT_IO, then the vcpu has
 executed a port I/O instruction which could not be satisfied by kvm.
 data_offset describes where the data is located (KVM_EXIT_IO_OUT) or
 where kvm expects application code to place the data for the next
-KVM_RUN invocation (KVM_EXIT_IO_IN).  Data format is a patcked array.
+KVM_RUN invocation (KVM_EXIT_IO_IN).  Data format is a packed array.
 
 		struct {
 			struct kvm_debug_exit_arch arch;
@@ -815,7 +815,7 @@
 			__u8  is_write;
 		} mmio;
 
-If exit_reason is KVM_EXIT_MMIO or KVM_EXIT_IO_OUT, then the vcpu has
+If exit_reason is KVM_EXIT_MMIO, then the vcpu has
 executed a memory-mapped I/O instruction which could not be satisfied
 by kvm.  The 'data' member contains the written data if 'is_write' is
 true, and should be filled by application code otherwise.
diff --git a/Documentation/laptops/00-INDEX b/Documentation/laptops/00-INDEX
index ee5692b..fa68853 100644
--- a/Documentation/laptops/00-INDEX
+++ b/Documentation/laptops/00-INDEX
@@ -2,6 +2,12 @@
 	- This file
 acer-wmi.txt
 	- information on the Acer Laptop WMI Extras driver.
+asus-laptop.txt
+	- information on the Asus Laptop Extras driver.
+disk-shock-protection.txt
+	- information on hard disk shock protection.
+dslm.c
+	- Simple Disk Sleep Monitor program
 laptop-mode.txt
 	- how to conserve battery power using laptop-mode.
 sony-laptop.txt
diff --git a/Documentation/laptops/Makefile b/Documentation/laptops/Makefile
new file mode 100644
index 0000000..5cb144a
--- /dev/null
+++ b/Documentation/laptops/Makefile
@@ -0,0 +1,8 @@
+# kbuild trick to avoid linker error. Can be omitted if a module is built.
+obj- := dummy.o
+
+# List of programs to build
+hostprogs-y := dslm
+
+# Tell kbuild to always build the programs
+always := $(hostprogs-y)
diff --git a/Documentation/laptops/dslm.c b/Documentation/laptops/dslm.c
new file mode 100644
index 0000000..72ff290
--- /dev/null
+++ b/Documentation/laptops/dslm.c
@@ -0,0 +1,166 @@
+/*
+ * dslm.c
+ * Simple Disk Sleep Monitor
+ *  by Bartek Kania
+ * Licenced under the GPL
+ */
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <linux/hdreg.h>
+
+#ifdef DEBUG
+#define D(x) x
+#else
+#define D(x)
+#endif
+
+int endit = 0;
+
+/* Check if the disk is in powersave-mode
+ * Most of the code is stolen from hdparm.
+ * 1 = active, 0 = standby/sleep, -1 = unknown */
+static int check_powermode(int fd)
+{
+    unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0};
+    int state;
+
+    if (ioctl(fd, HDIO_DRIVE_CMD, &args)
+	&& (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */
+	&& ioctl(fd, HDIO_DRIVE_CMD, &args)) {
+	if (errno != EIO || args[0] != 0 || args[1] != 0) {
+	    state = -1; /* "unknown"; */
+	} else
+	    state = 0; /* "sleeping"; */
+    } else {
+	state = (args[2] == 255) ? 1 : 0;
+    }
+    D(printf(" drive state is:  %d\n", state));
+
+    return state;
+}
+
+static char *state_name(int i)
+{
+    if (i == -1) return "unknown";
+    if (i == 0) return "sleeping";
+    if (i == 1) return "active";
+
+    return "internal error";
+}
+
+static char *myctime(time_t time)
+{
+    char *ts = ctime(&time);
+    ts[strlen(ts) - 1] = 0;
+
+    return ts;
+}
+
+static void measure(int fd)
+{
+    time_t start_time;
+    int last_state;
+    time_t last_time;
+    int curr_state;
+    time_t curr_time = 0;
+    time_t time_diff;
+    time_t active_time = 0;
+    time_t sleep_time = 0;
+    time_t unknown_time = 0;
+    time_t total_time = 0;
+    int changes = 0;
+    float tmp;
+
+    printf("Starting measurements\n");
+
+    last_state = check_powermode(fd);
+    start_time = last_time = time(0);
+    printf("  System is in state %s\n\n", state_name(last_state));
+
+    while(!endit) {
+	sleep(1);
+	curr_state = check_powermode(fd);
+
+	if (curr_state != last_state || endit) {
+	    changes++;
+	    curr_time = time(0);
+	    time_diff = curr_time - last_time;
+
+	    if (last_state == 1) active_time += time_diff;
+	    else if (last_state == 0) sleep_time += time_diff;
+	    else unknown_time += time_diff;
+
+	    last_state = curr_state;
+	    last_time = curr_time;
+
+	    printf("%s: State-change to %s\n", myctime(curr_time),
+		   state_name(curr_state));
+	}
+    }
+    changes--; /* Compensate for SIGINT */
+
+    total_time = time(0) - start_time;
+    printf("\nTotal running time:  %lus\n", curr_time - start_time);
+    printf(" State changed %d times\n", changes);
+
+    tmp = (float)sleep_time / (float)total_time * 100;
+    printf(" Time in sleep state:   %lus (%.2f%%)\n", sleep_time, tmp);
+    tmp = (float)active_time / (float)total_time * 100;
+    printf(" Time in active state:  %lus (%.2f%%)\n", active_time, tmp);
+    tmp = (float)unknown_time / (float)total_time * 100;
+    printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp);
+}
+
+static void ender(int s)
+{
+    endit = 1;
+}
+
+static void usage(void)
+{
+    puts("usage: dslm [-w <time>] <disk>");
+    exit(0);
+}
+
+int main(int argc, char **argv)
+{
+    int fd;
+    char *disk = 0;
+    int settle_time = 60;
+
+    /* Parse the simple command-line */
+    if (argc == 2)
+	disk = argv[1];
+    else if (argc == 4) {
+	settle_time = atoi(argv[2]);
+	disk = argv[3];
+    } else
+	usage();
+
+    if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) {
+	printf("Can't open %s, because: %s\n", disk, strerror(errno));
+	exit(-1);
+    }
+
+    if (settle_time) {
+	printf("Waiting %d seconds for the system to settle down to "
+	       "'normal'\n", settle_time);
+	sleep(settle_time);
+    } else
+	puts("Not waiting for system to settle down");
+
+    signal(SIGINT, ender);
+
+    measure(fd);
+
+    close(fd);
+
+    return 0;
+}
diff --git a/Documentation/laptops/laptop-mode.txt b/Documentation/laptops/laptop-mode.txt
index eeedee1..2c3c350 100644
--- a/Documentation/laptops/laptop-mode.txt
+++ b/Documentation/laptops/laptop-mode.txt
@@ -779,172 +779,4 @@
 ---------------
 
 Bartek Kania submitted this, it can be used to measure how much time your disk
-spends spun up/down.
-
----------------------------dslm.c BEGIN-----------------------------------------
-/*
- * Simple Disk Sleep Monitor
- *  by Bartek Kania
- * Licenced under the GPL
- */
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <time.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <linux/hdreg.h>
-
-#ifdef DEBUG
-#define D(x) x
-#else
-#define D(x)
-#endif
-
-int endit = 0;
-
-/* Check if the disk is in powersave-mode
- * Most of the code is stolen from hdparm.
- * 1 = active, 0 = standby/sleep, -1 = unknown */
-int check_powermode(int fd)
-{
-    unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0};
-    int state;
-
-    if (ioctl(fd, HDIO_DRIVE_CMD, &args)
-	&& (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */
-	&& ioctl(fd, HDIO_DRIVE_CMD, &args)) {
-	if (errno != EIO || args[0] != 0 || args[1] != 0) {
-	    state = -1; /* "unknown"; */
-	} else
-	    state = 0; /* "sleeping"; */
-    } else {
-	state = (args[2] == 255) ? 1 : 0;
-    }
-    D(printf(" drive state is:  %d\n", state));
-
-    return state;
-}
-
-char *state_name(int i)
-{
-    if (i == -1) return "unknown";
-    if (i == 0) return "sleeping";
-    if (i == 1) return "active";
-
-    return "internal error";
-}
-
-char *myctime(time_t time)
-{
-    char *ts = ctime(&time);
-    ts[strlen(ts) - 1] = 0;
-
-    return ts;
-}
-
-void measure(int fd)
-{
-    time_t start_time;
-    int last_state;
-    time_t last_time;
-    int curr_state;
-    time_t curr_time = 0;
-    time_t time_diff;
-    time_t active_time = 0;
-    time_t sleep_time = 0;
-    time_t unknown_time = 0;
-    time_t total_time = 0;
-    int changes = 0;
-    float tmp;
-
-    printf("Starting measurements\n");
-
-    last_state = check_powermode(fd);
-    start_time = last_time = time(0);
-    printf("  System is in state %s\n\n", state_name(last_state));
-
-    while(!endit) {
-	sleep(1);
-	curr_state = check_powermode(fd);
-
-	if (curr_state != last_state || endit) {
-	    changes++;
-	    curr_time = time(0);
-	    time_diff = curr_time - last_time;
-
-	    if (last_state == 1) active_time += time_diff;
-	    else if (last_state == 0) sleep_time += time_diff;
-	    else unknown_time += time_diff;
-
-	    last_state = curr_state;
-	    last_time = curr_time;
-
-	    printf("%s: State-change to %s\n", myctime(curr_time),
-		   state_name(curr_state));
-	}
-    }
-    changes--; /* Compensate for SIGINT */
-
-    total_time = time(0) - start_time;
-    printf("\nTotal running time:  %lus\n", curr_time - start_time);
-    printf(" State changed %d times\n", changes);
-
-    tmp = (float)sleep_time / (float)total_time * 100;
-    printf(" Time in sleep state:   %lus (%.2f%%)\n", sleep_time, tmp);
-    tmp = (float)active_time / (float)total_time * 100;
-    printf(" Time in active state:  %lus (%.2f%%)\n", active_time, tmp);
-    tmp = (float)unknown_time / (float)total_time * 100;
-    printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp);
-}
-
-void ender(int s)
-{
-    endit = 1;
-}
-
-void usage()
-{
-    puts("usage: dslm [-w <time>] <disk>");
-    exit(0);
-}
-
-int main(int argc, char **argv)
-{
-    int fd;
-    char *disk = 0;
-    int settle_time = 60;
-
-    /* Parse the simple command-line */
-    if (argc == 2)
-	disk = argv[1];
-    else if (argc == 4) {
-	settle_time = atoi(argv[2]);
-	disk = argv[3];
-    } else
-	usage();
-
-    if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) {
-	printf("Can't open %s, because: %s\n", disk, strerror(errno));
-	exit(-1);
-    }
-
-    if (settle_time) {
-	printf("Waiting %d seconds for the system to settle down to "
-	       "'normal'\n", settle_time);
-	sleep(settle_time);
-    } else
-	puts("Not waiting for system to settle down");
-
-    signal(SIGINT, ender);
-
-    measure(fd);
-
-    close(fd);
-
-    return 0;
-}
----------------------------dslm.c END-------------------------------------------
+spends spun up/down.  See Documentation/laptops/dslm.c
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index 75afa12..39c0a09 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -650,6 +650,10 @@
 	echo expand_toggle > /proc/acpi/ibm/video
 	echo video_switch > /proc/acpi/ibm/video
 
+NOTE: Access to this feature is restricted to processes owning the
+CAP_SYS_ADMIN capability for safety reasons, as it can interact badly
+enough with some versions of X.org to crash it.
+
 Each video output device can be enabled or disabled individually.
 Reading /proc/acpi/ibm/video shows the status of each device.
 
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 50189bf..fe5c099 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -32,6 +32,8 @@
 	- the Crystal LAN (CS8900/20-based) Ethernet ISA adapter driver
 cxacru.txt
 	- Conexant AccessRunner USB ADSL Modem
+cxacru-cf.py
+	- Conexant AccessRunner USB ADSL Modem configuration file parser
 de4x5.txt
 	- the Digital EtherWORKS DE4?? and DE5?? PCI Ethernet driver
 decnet.txt
diff --git a/Documentation/networking/cxacru-cf.py b/Documentation/networking/cxacru-cf.py
new file mode 100644
index 0000000..b41d298
--- /dev/null
+++ b/Documentation/networking/cxacru-cf.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+# Copyright 2009 Simon Arlott
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You 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.
+#
+# Usage: cxacru-cf.py < cxacru-cf.bin
+# Output: values string suitable for the sysfs adsl_config attribute
+#
+# Warning: cxacru-cf.bin with MD5 hash cdbac2689969d5ed5d4850f117702110
+# contains mis-aligned values which will stop the modem from being able
+# to make a connection. If the first and last two bytes are removed then
+# the values become valid, but the modulation will be forced to ANSI
+# T1.413 only which may not be appropriate.
+#
+# The original binary format is a packed list of le32 values.
+
+import sys
+import struct
+
+i = 0
+while True:
+	buf = sys.stdin.read(4)
+
+	if len(buf) == 0:
+		break
+	elif len(buf) != 4:
+		sys.stdout.write("\n")
+		sys.stderr.write("Error: read {0} not 4 bytes\n".format(len(buf)))
+		sys.exit(1)
+
+	if i > 0:
+		sys.stdout.write(" ")
+	sys.stdout.write("{0:x}={1}".format(i, struct.unpack("<I", buf)[0]))
+	i += 1
+
+sys.stdout.write("\n")
diff --git a/Documentation/networking/cxacru.txt b/Documentation/networking/cxacru.txt
index b074681..2cce044 100644
--- a/Documentation/networking/cxacru.txt
+++ b/Documentation/networking/cxacru.txt
@@ -4,6 +4,12 @@
 module loaded, the device will sometimes stop responding after unloading the
 driver and it is necessary to unplug/remove power to the device to fix this.
 
+Note: support for cxacru-cf.bin has been removed. It was not loaded correctly
+so it had no effect on the device configuration. Fixing it could have stopped
+existing devices working when an invalid configuration is supplied.
+
+There is a script cxacru-cf.py to convert an existing file to the sysfs form.
+
 Detected devices will appear as ATM devices named "cxacru". In /sys/class/atm/
 these are directories named cxacruN where N is the device number. A symlink
 named device points to the USB interface device's directory which contains
@@ -15,6 +21,15 @@
 * adsl_headend_environment
 	Information about the remote headend.
 
+* adsl_config
+	Configuration writing interface.
+	Write parameters in hexadecimal format <index>=<value>,
+	separated by whitespace, e.g.:
+		"1=0 a=5"
+	Up to 7 parameters at a time will be sent and the modem will restart
+	the ADSL connection when any value is set. These are logged for future
+	reference.
+
 * downstream_attenuation (dB)
 * downstream_bits_per_frame
 * downstream_rate (kbps)
@@ -61,6 +76,7 @@
 * mac_address
 
 * modulation
+	"" (when not connected)
 	"ANSI T1.413"
 	"ITU-T G.992.1 (G.DMT)"
 	"ITU-T G.992.2 (G.LITE)"
diff --git a/Documentation/networking/skfp.txt b/Documentation/networking/skfp.txt
index abfddf8..203ec66 100644
--- a/Documentation/networking/skfp.txt
+++ b/Documentation/networking/skfp.txt
@@ -68,7 +68,7 @@
 =======================
 
 From v2.01 on, the driver is integrated in the linux kernel sources.
-Therefor, the installation is the same as for any other adapter
+Therefore, the installation is the same as for any other adapter
 supported by the kernel.
 Refer to the manual of your distribution about the installation
 of network adapters.
diff --git a/Documentation/networking/timestamping/timestamping.c b/Documentation/networking/timestamping/timestamping.c
index a7936fe..bab619a 100644
--- a/Documentation/networking/timestamping/timestamping.c
+++ b/Documentation/networking/timestamping/timestamping.c
@@ -370,7 +370,7 @@
 	}
 
 	sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	if (socket < 0)
+	if (sock < 0)
 		bail("socket");
 
 	memset(&device, 0, sizeof(device));
diff --git a/Documentation/pnp.txt b/Documentation/pnp.txt
index a327db6..763e465 100644
--- a/Documentation/pnp.txt
+++ b/Documentation/pnp.txt
@@ -57,7 +57,7 @@
 # cat resources
 DISABLED
 
-- Notice the string "DISABLED".  THis means the device is not active.
+- Notice the string "DISABLED".  This means the device is not active.
 
 3.) check the device's possible configurations (optional)
 # cat options
@@ -139,7 +139,7 @@
 
 Requirements for a Linux PnP protocol:
 1.) the protocol must use EISA IDs
-2.) the protocol must inform the PnP Layer of a devices current configuration
+2.) the protocol must inform the PnP Layer of a device's current configuration
 - the ability to set resources is optional but preferred.
 
 The following are PnP protocol related functions:
@@ -158,7 +158,7 @@
 - automatically will free mem used by the device and related structures
 
 pnp_add_id
-- adds a EISA ID to the list of supported IDs for the specified device
+- adds an EISA ID to the list of supported IDs for the specified device
 
 For more information consult the source of a protocol such as
 /drivers/pnp/pnpbios/core.c.
@@ -167,7 +167,7 @@
 
 Linux Plug and Play Drivers
 ---------------------------
-	This section contains information for linux PnP driver developers.
+	This section contains information for Linux PnP driver developers.
 
 The New Way
 ...........
@@ -235,11 +235,10 @@
 The Old Way
 ...........
 
-a series of compatibility functions have been created to make it easy to convert 
-
+A series of compatibility functions have been created to make it easy to convert
 ISAPNP drivers.  They should serve as a temporary solution only.
 
-they are as follows:
+They are as follows:
 
 struct pnp_card *pnp_find_card(unsigned short vendor,
 				 unsigned short device,
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index 356fd86..55b859b 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -224,6 +224,12 @@
       RPM_SUSPENDED, which means that each device is initially regarded by the
       PM core as 'suspended', regardless of its real hardware status
 
+  unsigned int runtime_auto;
+    - if set, indicates that the user space has allowed the device driver to
+      power manage the device at run time via the /sys/devices/.../power/control
+      interface; it may only be modified with the help of the pm_runtime_allow()
+      and pm_runtime_forbid() helper functions
+
 All of the above fields are members of the 'power' member of 'struct device'.
 
 4. Run-time PM Device Helper Functions
@@ -250,7 +256,7 @@
       to suspend the device again in future
 
   int pm_runtime_resume(struct device *dev);
-    - execute the subsystem-leve resume callback for the device; returns 0 on
+    - execute the subsystem-level resume callback for the device; returns 0 on
       success, 1 if the device's run-time PM status was already 'active' or
       error code on failure, where -EAGAIN means it may be safe to attempt to
       resume the device again in future, but 'power.runtime_error' should be
@@ -329,6 +335,20 @@
       'power.runtime_error' is set or 'power.disable_depth' is greater than
       zero)
 
+  bool pm_runtime_suspended(struct device *dev);
+    - return true if the device's runtime PM status is 'suspended', or false
+      otherwise
+
+  void pm_runtime_allow(struct device *dev);
+    - set the power.runtime_auto flag for the device and decrease its usage
+      counter (used by the /sys/devices/.../power/control interface to
+      effectively allow the device to be power managed at run time)
+
+  void pm_runtime_forbid(struct device *dev);
+    - unset the power.runtime_auto flag for the device and increase its usage
+      counter (used by the /sys/devices/.../power/control interface to
+      effectively prevent the device from being power managed at run time)
+
 It is safe to execute the following helper functions from interrupt context:
 
 pm_request_idle()
@@ -382,6 +402,18 @@
 finished, so the PM core uses pm_runtime_idle_sync() to invoke the
 subsystem-level idle callback for the device at that time.
 
+The user space can effectively disallow the driver of the device to power manage
+it at run time by changing the value of its /sys/devices/.../power/control
+attribute to "on", which causes pm_runtime_forbid() to be called.  In principle,
+this mechanism may also be used by the driver to effectively turn off the
+run-time power management of the device until the user space turns it on.
+Namely, during the initialization the driver can make sure that the run-time PM
+status of the device is 'active' and call pm_runtime_forbid().  It should be
+noted, however, that if the user space has already intentionally changed the
+value of /sys/devices/.../power/control to "auto" to allow the driver to power
+manage the device at run time, the driver may confuse it by using
+pm_runtime_forbid() this way.
+
 6. Run-time PM and System Sleep
 
 Run-time PM and system sleep (i.e., system suspend and hibernation, also known
@@ -431,3 +463,64 @@
 ->prepare() callback and decrements it after calling the ->complete() callback.
 Hence disabling run-time PM temporarily like this will not cause any run-time
 suspend callbacks to be lost.
+
+7. Generic subsystem callbacks
+
+Subsystems may wish to conserve code space by using the set of generic power
+management callbacks provided by the PM core, defined in
+driver/base/power/generic_ops.c:
+
+  int pm_generic_runtime_idle(struct device *dev);
+    - invoke the ->runtime_idle() callback provided by the driver of this
+      device, if defined, and call pm_runtime_suspend() for this device if the
+      return value is 0 or the callback is not defined
+
+  int pm_generic_runtime_suspend(struct device *dev);
+    - invoke the ->runtime_suspend() callback provided by the driver of this
+      device and return its result, or return -EINVAL if not defined
+
+  int pm_generic_runtime_resume(struct device *dev);
+    - invoke the ->runtime_resume() callback provided by the driver of this
+      device and return its result, or return -EINVAL if not defined
+
+  int pm_generic_suspend(struct device *dev);
+    - if the device has not been suspended at run time, invoke the ->suspend()
+      callback provided by its driver and return its result, or return 0 if not
+      defined
+
+  int pm_generic_resume(struct device *dev);
+    - invoke the ->resume() callback provided by the driver of this device and,
+      if successful, change the device's runtime PM status to 'active'
+
+  int pm_generic_freeze(struct device *dev);
+    - if the device has not been suspended at run time, invoke the ->freeze()
+      callback provided by its driver and return its result, or return 0 if not
+      defined
+
+  int pm_generic_thaw(struct device *dev);
+    - if the device has not been suspended at run time, invoke the ->thaw()
+      callback provided by its driver and return its result, or return 0 if not
+      defined
+
+  int pm_generic_poweroff(struct device *dev);
+    - if the device has not been suspended at run time, invoke the ->poweroff()
+      callback provided by its driver and return its result, or return 0 if not
+      defined
+
+  int pm_generic_restore(struct device *dev);
+    - invoke the ->restore() callback provided by the driver of this device and,
+      if successful, change the device's runtime PM status to 'active'
+
+These functions can be assigned to the ->runtime_idle(), ->runtime_suspend(),
+->runtime_resume(), ->suspend(), ->resume(), ->freeze(), ->thaw(), ->poweroff(),
+or ->restore() callback pointers in the subsystem-level dev_pm_ops structures.
+
+If a subsystem wishes to use all of them at the same time, it can simply assign
+the GENERIC_SUBSYS_PM_OPS macro, defined in include/linux/pm.h, to its
+dev_pm_ops structure pointer.
+
+Device drivers that wish to use the same function as a system suspend, freeze,
+poweroff and run-time suspend callback, and similarly for system resume, thaw,
+restore, and run-time resume, can achieve this with the help of the
+UNIVERSAL_DEV_PM_OPS macro defined in include/linux/pm.h (possibly setting its
+last argument to NULL).
diff --git a/Documentation/powerpc/dts-bindings/fsl/dma.txt b/Documentation/powerpc/dts-bindings/fsl/dma.txt
index 0732cdd..2a4b4bc 100644
--- a/Documentation/powerpc/dts-bindings/fsl/dma.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/dma.txt
@@ -44,21 +44,29 @@
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <0>;
 			reg = <0 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
 		};
 		dma-channel@80 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <1>;
 			reg = <0x80 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
 		};
 		dma-channel@100 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <2>;
 			reg = <0x100 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
 		};
 		dma-channel@180 {
 			compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel";
 			cell-index = <3>;
 			reg = <0x180 0x80>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
 		};
 	};
 
diff --git a/Documentation/powerpc/dts-bindings/fsl/i2c.txt b/Documentation/powerpc/dts-bindings/fsl/i2c.txt
index b6d2e21..50da203 100644
--- a/Documentation/powerpc/dts-bindings/fsl/i2c.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/i2c.txt
@@ -2,15 +2,14 @@
 
 Required properties :
 
- - device_type : Should be "i2c"
  - reg : Offset and length of the register set for the device
+ - compatible : should be "fsl,CHIP-i2c" where CHIP is the name of a
+   compatible processor, e.g. mpc8313, mpc8543, mpc8544, mpc5121,
+   mpc5200 or mpc5200b. For the mpc5121, an additional node
+   "fsl,mpc5121-i2c-ctrl" is required as shown in the example below.
 
 Recommended properties :
 
- - compatible : compatibility list with 2 entries, the first should
-   be "fsl,CHIP-i2c" where CHIP is the name of a compatible processor,
-   e.g. mpc8313, mpc8543, mpc8544, mpc5200 or mpc5200b. The second one
-   should be "fsl-i2c".
  - interrupts : <a b> where a is the interrupt number and b is a
    field that represents an encoding of the sense and level
    information for the interrupt.  This should be encoded based on
@@ -24,25 +23,40 @@
 
 Examples :
 
+	/* MPC5121 based board */
+	i2c@1740 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc5121-i2c", "fsl-i2c";
+		reg = <0x1740 0x20>;
+		interrupts = <11 0x8>;
+		interrupt-parent = <&ipic>;
+		clock-frequency = <100000>;
+	};
+
+	i2ccontrol@1760 {
+		compatible = "fsl,mpc5121-i2c-ctrl";
+		reg = <0x1760 0x8>;
+	};
+
+	/* MPC5200B based board */
 	i2c@3d00 {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c";
-		cell-index = <0>;
 		reg = <0x3d00 0x40>;
 		interrupts = <2 15 0>;
 		interrupt-parent = <&mpc5200_pic>;
 		fsl,preserve-clocking;
 	};
 
+	/* MPC8544 base board */
 	i2c@3100 {
 		#address-cells = <1>;
 		#size-cells = <0>;
-		cell-index = <1>;
 		compatible = "fsl,mpc8544-i2c", "fsl-i2c";
 		reg = <0x3100 0x100>;
 		interrupts = <43 2>;
 		interrupt-parent = <&mpic>;
 		clock-frequency = <400000>;
 	};
-
diff --git a/Documentation/s390/kvm.txt b/Documentation/s390/kvm.txt
index 6f5ceb0..85f3280 100644
--- a/Documentation/s390/kvm.txt
+++ b/Documentation/s390/kvm.txt
@@ -102,7 +102,7 @@
 see also:	include/linux/kvm.h
 This ioctl stores the state of the cpu at the guest real address given as
 argument, unless one of the following values defined in include/linux/kvm.h
-is given as arguement:
+is given as argument:
 KVM_S390_STORE_STATUS_NOADDR - the CPU stores its status to the save area in
 absolute lowcore as defined by the principles of operation
 KVM_S390_STORE_STATUS_PREFIXED - the CPU stores its status to the save area in
diff --git a/Documentation/scsi/ChangeLog.lpfc b/Documentation/scsi/ChangeLog.lpfc
index ff19a52..2ffc114 100644
--- a/Documentation/scsi/ChangeLog.lpfc
+++ b/Documentation/scsi/ChangeLog.lpfc
@@ -989,8 +989,8 @@
 	* Remove redundant port_cmp != 2 check in if
 	  (!port_cmp) { .... if (port_cmp != 2).... }
 	* Clock changes: removed struct clk_data and timerList.
-	* Clock changes: seperate nodev_tmo and els_retry_delay into 2
-	  seperate timers and convert to 1 argument changed
+	* Clock changes: separate nodev_tmo and els_retry_delay into 2
+	  separate timers and convert to 1 argument changed
 	  LPFC_NODE_FARP_PEND_t to struct lpfc_node_farp_pend convert
 	  ipfarp_tmo to 1 argument convert target struct tmofunc and
 	  rtplunfunc to 1 argument * cr_count, cr_delay and
@@ -1514,7 +1514,7 @@
 	* Remove unused elxclock declaration in elx_sli.h.
 	* Since everywhere IOCB_ENTRY is used, the return value is cast,
 	  move the cast into the macro.
-	* Split ioctls out into seperate files
+	* Split ioctls out into separate files
 
 Changes from 20040326 to 20040402
 
@@ -1534,7 +1534,7 @@
 	* Unused variable cleanup
 	* Use Linux list macros for DMABUF_t
 	* Break up ioctls into 3 sections, dfc, util, hbaapi
-	  rearranged code so this could be easily seperated into a
+	  rearranged code so this could be easily separated into a
 	  differnet module later All 3 are currently turned on by
 	  defines in lpfc_ioctl.c LPFC_DFC_IOCTL, LPFC_UTIL_IOCTL,
 	  LPFC_HBAAPI_IOCTL
@@ -1551,7 +1551,7 @@
 	  started by lpfc_online().  lpfc_offline() only stopped
 	  els_timeout routine.  It now stops all timeout routines
 	  associated with that hba.
-	* Replace seperate next and prev pointers in struct
+	* Replace separate next and prev pointers in struct
 	  lpfc_bindlist with list_head type.  In elxHBA_t, replace
 	  fc_nlpbind_start and _end with fc_nlpbind_list and use
 	  list_head macros to access it.
diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt
index 5e5349a..7c90050 100644
--- a/Documentation/serial/tty.txt
+++ b/Documentation/serial/tty.txt
@@ -105,6 +105,10 @@
 			is permitted to call the driver write method from
 			this function. In such a situation defer it.
 
+dcd_change()	-	Report to the tty line the current DCD pin status
+			changes and the relative timestamp. The timestamp
+			can be NULL.
+
 
 Driver Access
 
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 33df82e..bfcbbf8 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -1812,7 +1812,7 @@
   Module snd-ua101
   ----------------
 
-    Module for the Edirol UA-101 audio/MIDI interface.
+    Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces.
 
     This module supports multiple devices, autoprobe and hotplugging.
 
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index fc5790d..6c7d18c 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -573,11 +573,14 @@
 may be not fatal yet.
 
 If this is set to 2, the kernel panics compulsorily even on the
-above-mentioned.
+above-mentioned. Even oom happens under memory cgroup, the whole
+system panics.
 
 The default value is 0.
 1 and 2 are for failover of clustering. Please select either
 according to your policy of failover.
+panic_on_oom=2+kdump gives you very strong tool to investigate
+why oom happens. You can get snapshot.
 
 =============================================================
 
diff --git a/Documentation/timers/00-INDEX b/Documentation/timers/00-INDEX
index 397dc35..a9248da 100644
--- a/Documentation/timers/00-INDEX
+++ b/Documentation/timers/00-INDEX
@@ -4,6 +4,8 @@
 	- High resolution timers and dynamic ticks design notes
 hpet.txt
 	- High Precision Event Timer Driver for Linux
+hpet_example.c
+	- sample hpet timer test program
 hrtimers.txt
 	- subsystem for high-resolution kernel timers
 timer_stats.txt
diff --git a/Documentation/timers/Makefile b/Documentation/timers/Makefile
new file mode 100644
index 0000000..c85625f
--- /dev/null
+++ b/Documentation/timers/Makefile
@@ -0,0 +1,8 @@
+# kbuild trick to avoid linker error. Can be omitted if a module is built.
+obj- := dummy.o
+
+# List of programs to build
+hostprogs-y := hpet_example
+
+# Tell kbuild to always build the programs
+always := $(hostprogs-y)
diff --git a/Documentation/timers/hpet.txt b/Documentation/timers/hpet.txt
index 16d25e6..767392f 100644
--- a/Documentation/timers/hpet.txt
+++ b/Documentation/timers/hpet.txt
@@ -26,274 +26,5 @@
 arch/x86/kernel/hpet.c.
 
 The driver provides a userspace API which resembles the API found in the
-RTC driver framework.  An example user space program is provided below.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <memory.h>
-#include <malloc.h>
-#include <time.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <linux/hpet.h>
-
-
-extern void hpet_open_close(int, const char **);
-extern void hpet_info(int, const char **);
-extern void hpet_poll(int, const char **);
-extern void hpet_fasync(int, const char **);
-extern void hpet_read(int, const char **);
-
-#include <sys/poll.h>
-#include <sys/ioctl.h>
-#include <signal.h>
-
-struct hpet_command {
-	char		*command;
-	void		(*func)(int argc, const char ** argv);
-} hpet_command[] = {
-	{
-		"open-close",
-		hpet_open_close
-	},
-	{
-		"info",
-		hpet_info
-	},
-	{
-		"poll",
-		hpet_poll
-	},
-	{
-		"fasync",
-		hpet_fasync
-	},
-};
-
-int
-main(int argc, const char ** argv)
-{
-	int	i;
-
-	argc--;
-	argv++;
-
-	if (!argc) {
-		fprintf(stderr, "-hpet: requires command\n");
-		return -1;
-	}
-
-
-	for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
-		if (!strcmp(argv[0], hpet_command[i].command)) {
-			argc--;
-			argv++;
-			fprintf(stderr, "-hpet: executing %s\n",
-				hpet_command[i].command);
-			hpet_command[i].func(argc, argv);
-			return 0;
-		}
-
-	fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
-
-	return -1;
-}
-
-void
-hpet_open_close(int argc, const char **argv)
-{
-	int	fd;
-
-	if (argc != 1) {
-		fprintf(stderr, "hpet_open_close: device-name\n");
-		return;
-	}
-
-	fd = open(argv[0], O_RDONLY);
-	if (fd < 0)
-		fprintf(stderr, "hpet_open_close: open failed\n");
-	else
-		close(fd);
-
-	return;
-}
-
-void
-hpet_info(int argc, const char **argv)
-{
-}
-
-void
-hpet_poll(int argc, const char **argv)
-{
-	unsigned long		freq;
-	int			iterations, i, fd;
-	struct pollfd		pfd;
-	struct hpet_info	info;
-	struct timeval		stv, etv;
-	struct timezone		tz;
-	long			usec;
-
-	if (argc != 3) {
-		fprintf(stderr, "hpet_poll: device-name freq iterations\n");
-		return;
-	}
-
-	freq = atoi(argv[1]);
-	iterations = atoi(argv[2]);
-
-	fd = open(argv[0], O_RDONLY);
-
-	if (fd < 0) {
-		fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
-		return;
-	}
-
-	if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
-		fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
-		goto out;
-	}
-
-	if (ioctl(fd, HPET_INFO, &info) < 0) {
-		fprintf(stderr, "hpet_poll: failed to get info\n");
-		goto out;
-	}
-
-	fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
-
-	if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
-		fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
-		goto out;
-	}
-
-	if (ioctl(fd, HPET_IE_ON, 0) < 0) {
-		fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
-		goto out;
-	}
-
-	pfd.fd = fd;
-	pfd.events = POLLIN;
-
-	for (i = 0; i < iterations; i++) {
-		pfd.revents = 0;
-		gettimeofday(&stv, &tz);
-		if (poll(&pfd, 1, -1) < 0)
-			fprintf(stderr, "hpet_poll: poll failed\n");
-		else {
-			long 	data;
-
-			gettimeofday(&etv, &tz);
-			usec = stv.tv_sec * 1000000 + stv.tv_usec;
-			usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
-
-			fprintf(stderr,
-				"hpet_poll: expired time = 0x%lx\n", usec);
-
-			fprintf(stderr, "hpet_poll: revents = 0x%x\n",
-				pfd.revents);
-
-			if (read(fd, &data, sizeof(data)) != sizeof(data)) {
-				fprintf(stderr, "hpet_poll: read failed\n");
-			}
-			else
-				fprintf(stderr, "hpet_poll: data 0x%lx\n",
-					data);
-		}
-	}
-
-out:
-	close(fd);
-	return;
-}
-
-static int hpet_sigio_count;
-
-static void
-hpet_sigio(int val)
-{
-	fprintf(stderr, "hpet_sigio: called\n");
-	hpet_sigio_count++;
-}
-
-void
-hpet_fasync(int argc, const char **argv)
-{
-	unsigned long		freq;
-	int			iterations, i, fd, value;
-	sig_t			oldsig;
-	struct hpet_info	info;
-
-	hpet_sigio_count = 0;
-	fd = -1;
-
-	if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
-		fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
-		return;
-	}
-
-	if (argc != 3) {
-		fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
-		goto out;
-	}
-
-	fd = open(argv[0], O_RDONLY);
-
-	if (fd < 0) {
-		fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
-		return;
-	}
-
-
-	if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
-		((value = fcntl(fd, F_GETFL)) == 1) ||
-		(fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
-		fprintf(stderr, "hpet_fasync: fcntl failed\n");
-		goto out;
-	}
-
-	freq = atoi(argv[1]);
-	iterations = atoi(argv[2]);
-
-	if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
-		fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
-		goto out;
-	}
-
-	if (ioctl(fd, HPET_INFO, &info) < 0) {
-		fprintf(stderr, "hpet_fasync: failed to get info\n");
-		goto out;
-	}
-
-	fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
-
-	if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
-		fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
-		goto out;
-	}
-
-	if (ioctl(fd, HPET_IE_ON, 0) < 0) {
-		fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
-		goto out;
-	}
-
-	for (i = 0; i < iterations; i++) {
-		(void) pause();
-		fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
-	}
-
-out:
-	signal(SIGIO, oldsig);
-
-	if (fd >= 0)
-		close(fd);
-
-	return;
-}
+RTC driver framework.  An example user space program is provided in
+file:Documentation/timers/hpet_example.c
diff --git a/Documentation/timers/hpet_example.c b/Documentation/timers/hpet_example.c
new file mode 100644
index 0000000..f9ce2d9
--- /dev/null
+++ b/Documentation/timers/hpet_example.c
@@ -0,0 +1,269 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <memory.h>
+#include <malloc.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <linux/hpet.h>
+
+
+extern void hpet_open_close(int, const char **);
+extern void hpet_info(int, const char **);
+extern void hpet_poll(int, const char **);
+extern void hpet_fasync(int, const char **);
+extern void hpet_read(int, const char **);
+
+#include <sys/poll.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+
+struct hpet_command {
+	char		*command;
+	void		(*func)(int argc, const char ** argv);
+} hpet_command[] = {
+	{
+		"open-close",
+		hpet_open_close
+	},
+	{
+		"info",
+		hpet_info
+	},
+	{
+		"poll",
+		hpet_poll
+	},
+	{
+		"fasync",
+		hpet_fasync
+	},
+};
+
+int
+main(int argc, const char ** argv)
+{
+	int	i;
+
+	argc--;
+	argv++;
+
+	if (!argc) {
+		fprintf(stderr, "-hpet: requires command\n");
+		return -1;
+	}
+
+
+	for (i = 0; i < (sizeof (hpet_command) / sizeof (hpet_command[0])); i++)
+		if (!strcmp(argv[0], hpet_command[i].command)) {
+			argc--;
+			argv++;
+			fprintf(stderr, "-hpet: executing %s\n",
+				hpet_command[i].command);
+			hpet_command[i].func(argc, argv);
+			return 0;
+		}
+
+	fprintf(stderr, "do_hpet: command %s not implemented\n", argv[0]);
+
+	return -1;
+}
+
+void
+hpet_open_close(int argc, const char **argv)
+{
+	int	fd;
+
+	if (argc != 1) {
+		fprintf(stderr, "hpet_open_close: device-name\n");
+		return;
+	}
+
+	fd = open(argv[0], O_RDONLY);
+	if (fd < 0)
+		fprintf(stderr, "hpet_open_close: open failed\n");
+	else
+		close(fd);
+
+	return;
+}
+
+void
+hpet_info(int argc, const char **argv)
+{
+}
+
+void
+hpet_poll(int argc, const char **argv)
+{
+	unsigned long		freq;
+	int			iterations, i, fd;
+	struct pollfd		pfd;
+	struct hpet_info	info;
+	struct timeval		stv, etv;
+	struct timezone		tz;
+	long			usec;
+
+	if (argc != 3) {
+		fprintf(stderr, "hpet_poll: device-name freq iterations\n");
+		return;
+	}
+
+	freq = atoi(argv[1]);
+	iterations = atoi(argv[2]);
+
+	fd = open(argv[0], O_RDONLY);
+
+	if (fd < 0) {
+		fprintf(stderr, "hpet_poll: open of %s failed\n", argv[0]);
+		return;
+	}
+
+	if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
+		fprintf(stderr, "hpet_poll: HPET_IRQFREQ failed\n");
+		goto out;
+	}
+
+	if (ioctl(fd, HPET_INFO, &info) < 0) {
+		fprintf(stderr, "hpet_poll: failed to get info\n");
+		goto out;
+	}
+
+	fprintf(stderr, "hpet_poll: info.hi_flags 0x%lx\n", info.hi_flags);
+
+	if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
+		fprintf(stderr, "hpet_poll: HPET_EPI failed\n");
+		goto out;
+	}
+
+	if (ioctl(fd, HPET_IE_ON, 0) < 0) {
+		fprintf(stderr, "hpet_poll, HPET_IE_ON failed\n");
+		goto out;
+	}
+
+	pfd.fd = fd;
+	pfd.events = POLLIN;
+
+	for (i = 0; i < iterations; i++) {
+		pfd.revents = 0;
+		gettimeofday(&stv, &tz);
+		if (poll(&pfd, 1, -1) < 0)
+			fprintf(stderr, "hpet_poll: poll failed\n");
+		else {
+			long 	data;
+
+			gettimeofday(&etv, &tz);
+			usec = stv.tv_sec * 1000000 + stv.tv_usec;
+			usec = (etv.tv_sec * 1000000 + etv.tv_usec) - usec;
+
+			fprintf(stderr,
+				"hpet_poll: expired time = 0x%lx\n", usec);
+
+			fprintf(stderr, "hpet_poll: revents = 0x%x\n",
+				pfd.revents);
+
+			if (read(fd, &data, sizeof(data)) != sizeof(data)) {
+				fprintf(stderr, "hpet_poll: read failed\n");
+			}
+			else
+				fprintf(stderr, "hpet_poll: data 0x%lx\n",
+					data);
+		}
+	}
+
+out:
+	close(fd);
+	return;
+}
+
+static int hpet_sigio_count;
+
+static void
+hpet_sigio(int val)
+{
+	fprintf(stderr, "hpet_sigio: called\n");
+	hpet_sigio_count++;
+}
+
+void
+hpet_fasync(int argc, const char **argv)
+{
+	unsigned long		freq;
+	int			iterations, i, fd, value;
+	sig_t			oldsig;
+	struct hpet_info	info;
+
+	hpet_sigio_count = 0;
+	fd = -1;
+
+	if ((oldsig = signal(SIGIO, hpet_sigio)) == SIG_ERR) {
+		fprintf(stderr, "hpet_fasync: failed to set signal handler\n");
+		return;
+	}
+
+	if (argc != 3) {
+		fprintf(stderr, "hpet_fasync: device-name freq iterations\n");
+		goto out;
+	}
+
+	fd = open(argv[0], O_RDONLY);
+
+	if (fd < 0) {
+		fprintf(stderr, "hpet_fasync: failed to open %s\n", argv[0]);
+		return;
+	}
+
+
+	if ((fcntl(fd, F_SETOWN, getpid()) == 1) ||
+		((value = fcntl(fd, F_GETFL)) == 1) ||
+		(fcntl(fd, F_SETFL, value | O_ASYNC) == 1)) {
+		fprintf(stderr, "hpet_fasync: fcntl failed\n");
+		goto out;
+	}
+
+	freq = atoi(argv[1]);
+	iterations = atoi(argv[2]);
+
+	if (ioctl(fd, HPET_IRQFREQ, freq) < 0) {
+		fprintf(stderr, "hpet_fasync: HPET_IRQFREQ failed\n");
+		goto out;
+	}
+
+	if (ioctl(fd, HPET_INFO, &info) < 0) {
+		fprintf(stderr, "hpet_fasync: failed to get info\n");
+		goto out;
+	}
+
+	fprintf(stderr, "hpet_fasync: info.hi_flags 0x%lx\n", info.hi_flags);
+
+	if (info.hi_flags && (ioctl(fd, HPET_EPI, 0) < 0)) {
+		fprintf(stderr, "hpet_fasync: HPET_EPI failed\n");
+		goto out;
+	}
+
+	if (ioctl(fd, HPET_IE_ON, 0) < 0) {
+		fprintf(stderr, "hpet_fasync, HPET_IE_ON failed\n");
+		goto out;
+	}
+
+	for (i = 0; i < iterations; i++) {
+		(void) pause();
+		fprintf(stderr, "hpet_fasync: count = %d\n", hpet_sigio_count);
+	}
+
+out:
+	signal(SIGIO, oldsig);
+
+	if (fd >= 0)
+		close(fd);
+
+	return;
+}
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index bab3040..03485bf 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -1588,7 +1588,7 @@
 
 When tracing is enabled, kstop_machine is called to prevent
 races with the CPUS executing code being modified (which can
-cause the CPU to do undesireable things), and the nops are
+cause the CPU to do undesirable things), and the nops are
 patched back to calls. But this time, they do not call mcount
 (which is just a function stub). They now call into the ftrace
 infrastructure.
diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
index 9cf83e8..d83703e 100644
--- a/Documentation/usb/error-codes.txt
+++ b/Documentation/usb/error-codes.txt
@@ -41,8 +41,8 @@
 
 -EFBIG		Host controller driver can't schedule that many ISO frames.
 
--EPIPE		Specified endpoint is stalled.  For non-control endpoints,
-		reset this status with usb_clear_halt().
+-EPIPE		The pipe type specified in the URB doesn't match the
+		endpoint's actual type.
 
 -EMSGSIZE	(a) endpoint maxpacket size is zero; it is not usable
 		    in the current interface altsetting.
@@ -60,6 +60,8 @@
 
 -EHOSTUNREACH	URB was rejected because the device is suspended.
 
+-ENOEXEC	A control URB doesn't contain a Setup packet.
+
 
 **************************************************************************
 *                   Error codes returned by in urb->status               *
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
index 3bf6818..2790ad4 100644
--- a/Documentation/usb/power-management.txt
+++ b/Documentation/usb/power-management.txt
@@ -2,7 +2,7 @@
 
 		 Alan Stern <stern@rowland.harvard.edu>
 
-			    November 10, 2009
+			    December 11, 2009
 
 
 
@@ -29,9 +29,9 @@
 information about system PM).
 
 Note: Dynamic PM support for USB is present only if the kernel was
-built with CONFIG_USB_SUSPEND enabled.  System PM support is present
-only if the kernel was built with CONFIG_SUSPEND or CONFIG_HIBERNATION
-enabled.
+built with CONFIG_USB_SUSPEND enabled (which depends on
+CONFIG_PM_RUNTIME).  System PM support is present only if the kernel
+was built with CONFIG_SUSPEND or CONFIG_HIBERNATION enabled.
 
 
 	What is Remote Wakeup?
@@ -229,6 +229,11 @@
 also change the idle-delay time; 2 seconds is not the best choice for
 every device.
 
+If a driver knows that its device has proper suspend/resume support,
+it can enable autosuspend all by itself.  For example, the video
+driver for a laptop's webcam might do this, since these devices are
+rarely used and so should normally be autosuspended.
+
 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,
@@ -321,69 +326,81 @@
 	void usb_autopm_get_interface_no_resume(struct usb_interface *intf);
 	void usb_autopm_put_interface_no_suspend(struct usb_interface *intf);
 
-The functions work by maintaining a counter in the usb_interface
-structure.  When intf->pm_usage_count is > 0 then the interface is
-deemed to be busy, and the kernel will not autosuspend the interface's
-device.  When intf->pm_usage_count is <= 0 then the interface is
-considered to be idle, and the kernel may autosuspend the device.
+The functions work by maintaining a usage counter in the
+usb_interface's embedded device structure.  When the counter is > 0
+then the interface is deemed to be busy, and the kernel will not
+autosuspend the interface's device.  When the usage counter is = 0
+then the interface is considered to be idle, and the kernel may
+autosuspend the device.
 
-(There is a similar pm_usage_count field in struct usb_device,
+(There is a similar usage counter field in struct usb_device,
 associated with the device itself rather than any of its interfaces.
-This field is used only by the USB core.)
+This counter is used only by the USB core.)
 
-Drivers must not modify intf->pm_usage_count directly; its value
-should be changed only be using the functions listed above.  Drivers
-are responsible for insuring that the overall change to pm_usage_count
-during their lifetime balances out to 0 (it may be necessary for the
-disconnect method to call usb_autopm_put_interface() one or more times
-to fulfill this requirement).  The first two routines use the PM mutex
-in struct usb_device for mutual exclusion; drivers using the async
-routines are responsible for their own synchronization and mutual
-exclusion.
+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
+any of the usb_autopm_* functions after their diconnect() routine has
+returned.
 
-	usb_autopm_get_interface() increments pm_usage_count and
-	attempts an autoresume if the new value is > 0 and the
-	device is suspended.
+Drivers using the async routines are responsible for their own
+synchronization and mutual exclusion.
 
-	usb_autopm_put_interface() decrements pm_usage_count and
-	attempts an autosuspend if the new value is <= 0 and the
-	device isn't suspended.
+	usb_autopm_get_interface() increments the usage counter and
+	does an autoresume if the device is suspended.  If the
+	autoresume fails, the counter is decremented back.
+
+	usb_autopm_put_interface() decrements the usage counter and
+	attempts an autosuspend if the new value is = 0.
 
 	usb_autopm_get_interface_async() and
 	usb_autopm_put_interface_async() do almost the same things as
-	their non-async counterparts.  The differences are: they do
-	not acquire the PM mutex, and they use a workqueue to do their
+	their non-async counterparts.  The big difference is that they
+	use a workqueue to do the resume or suspend part of their
 	jobs.  As a result they can be called in an atomic context,
 	such as an URB's completion handler, but when they return the
-	device will not generally not yet be in the desired state.
+	device will generally not yet be in the desired state.
 
 	usb_autopm_get_interface_no_resume() and
 	usb_autopm_put_interface_no_suspend() merely increment or
-	decrement the pm_usage_count value; they do not attempt to
-	carry out an autoresume or an autosuspend.  Hence they can be
-	called in an atomic context.
+	decrement the usage counter; they do not attempt to carry out
+	an autoresume or an autosuspend.  Hence they can be called in
+	an atomic context.
 
-The conventional usage pattern is that a driver calls
+The simplest usage pattern is that a driver calls
 usb_autopm_get_interface() in its open routine and
-usb_autopm_put_interface() in its close or release routine.  But
-other patterns are possible.
+usb_autopm_put_interface() in its close or release routine.  But other
+patterns are possible.
 
 The autosuspend attempts mentioned above will often fail for one
 reason or another.  For example, the power/level attribute might be
 set to "on", or another interface in the same device might not be
 idle.  This is perfectly normal.  If the reason for failure was that
-the device hasn't been idle for long enough, a delayed workqueue
-routine is automatically set up to carry out the operation when the
-autosuspend idle-delay has expired.
+the device hasn't been idle for long enough, a timer is scheduled to
+carry out the operation automatically when the autosuspend idle-delay
+has expired.
 
 Autoresume attempts also can fail, although failure would mean that
 the device is no longer present or operating properly.  Unlike
-autosuspend, there's no delay for an autoresume.
+autosuspend, there's no idle-delay for an autoresume.
 
 
 	Other parts of the driver interface
 	-----------------------------------
 
+Drivers can enable autosuspend for their devices by calling
+
+	usb_enable_autosuspend(struct usb_device *udev);
+
+in their probe() routine, if they know that the device is capable of
+suspending and resuming correctly.  This is exactly equivalent to
+writing "auto" to the device's power/level attribute.  Likewise,
+drivers can disable autosuspend by calling
+
+	usb_disable_autosuspend(struct usb_device *udev);
+
+This is exactly the same as writing "on" to the power/level attribute.
+
 Sometimes a driver needs to make sure that remote wakeup is enabled
 during autosuspend.  For example, there's not much point
 autosuspending a keyboard if the user can't cause the keyboard to do a
@@ -395,26 +412,27 @@
 Normally a driver would set this flag in its probe method, at which
 time the device is guaranteed not to be autosuspended.)
 
-The synchronous usb_autopm_* routines have to run in a sleepable
-process context; they must not be called from an interrupt handler or
-while holding a spinlock.  In fact, the entire autosuspend mechanism
-is not well geared toward interrupt-driven operation.  However there
-is one thing a driver can do in an interrupt handler:
+If a driver does its I/O asynchronously in interrupt context, it
+should call usb_autopm_get_interface_async() before starting output and
+usb_autopm_put_interface_async() when the output queue drains.  When
+it receives an input event, it should call
 
 	usb_mark_last_busy(struct usb_device *udev);
 
-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.  The usb_autopm_* routines will
-also set the last_busy field to the current time.
+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.
 
-Calling urb_mark_last_busy() from within an URB completion handler is
-subject to races: The kernel may have just finished deciding the
-device has been idle for long enough but not yet gotten around to
-calling the driver's suspend method.  The driver would have to be
-responsible for synchronizing its suspend method with its URB
-completion handler and causing the autosuspend to fail with -EBUSY if
-an URB had completed too recently.
+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.
 
 External suspend calls should never be allowed to fail in this way,
 only autosuspend calls.  The driver can tell them apart by checking
@@ -422,75 +440,23 @@
 method; this bit will be set for internal PM events (autosuspend) and
 clear for external PM events.
 
-Many of the ingredients in the autosuspend framework are oriented
-towards interfaces: The usb_interface structure contains the
-pm_usage_cnt field, and the usb_autopm_* routines take an interface
-pointer as their argument.  But somewhat confusingly, a few of the
-pieces (i.e., usb_mark_last_busy()) use the usb_device structure
-instead.  Drivers need to keep this straight; they can call
-interface_to_usbdev() to find the device structure for a given
-interface.
 
+	Mutual exclusion
+	----------------
 
-	Locking requirements
-	--------------------
-
-All three suspend/resume methods are always called while holding the
-usb_device's PM mutex.  For external events -- but not necessarily for
-autosuspend or autoresume -- the device semaphore (udev->dev.sem) will
-also be held.  This implies that external suspend/resume events are
-mutually exclusive with calls to probe, disconnect, pre_reset, and
-post_reset; the USB core guarantees that this is true of internal
-suspend/resume events as well.
+For external events -- but not necessarily for autosuspend or
+autoresume -- the device semaphore (udev->dev.sem) will be held when a
+suspend or resume method is called.  This implies that external
+suspend/resume events are mutually exclusive with calls to probe,
+disconnect, pre_reset, and post_reset; the USB core guarantees that
+this is true of autosuspend/autoresume events as well.
 
 If a driver wants to block all suspend/resume calls during some
-critical section, it can simply acquire udev->pm_mutex. Note that
-calls to resume may be triggered indirectly. Block IO due to memory
-allocations can make the vm subsystem resume a device. Thus while
-holding this lock you must not allocate memory with GFP_KERNEL or
-GFP_NOFS.
-
-Alternatively, if the critical section might call some of the
-usb_autopm_* routines, the driver can avoid deadlock by doing:
-
-	down(&udev->dev.sem);
-	rc = usb_autopm_get_interface(intf);
-
-and at the end of the critical section:
-
-	if (!rc)
-		usb_autopm_put_interface(intf);
-	up(&udev->dev.sem);
-
-Holding the device semaphore will block all external PM calls, and the
-usb_autopm_get_interface() will prevent any internal PM calls, even if
-it fails.  (Exercise: Why?)
-
-The rules for locking order are:
-
-	Never acquire any device semaphore while holding any PM mutex.
-
-	Never acquire udev->pm_mutex while holding the PM mutex for
-	a device that isn't a descendant of udev.
-
-In other words, PM mutexes should only be acquired going up the device
-tree, and they should be acquired only after locking all the device
-semaphores you need to hold.  These rules don't matter to drivers very
-much; they usually affect just the USB core.
-
-Still, drivers do need to be careful.  For example, many drivers use a
-private mutex to synchronize their normal I/O activities with their
-disconnect method.  Now if the driver supports autosuspend then it
-must call usb_autopm_put_interface() from somewhere -- maybe from its
-close method.  It should make the call while holding the private mutex,
-since a driver shouldn't call any of the usb_autopm_* functions for an
-interface from which it has been unbound.
-
-But the usb_autpm_* routines always acquire the device's PM mutex, and
-consequently the locking order has to be: private mutex first, PM
-mutex second.  Since the suspend method is always called with the PM
-mutex held, it mustn't try to acquire the private mutex.  It has to
-synchronize with the driver's I/O activities in some other way.
+critical section, the best way is to lock the device and call
+usb_autopm_get_interface() (and do the reverse at the end of the
+critical section).  Holding the device semaphore will block all
+external PM calls, and the usb_autopm_get_interface() will prevent any
+internal PM calls, even if it fails.  (Exercise: Why?)
 
 
 	Interaction between dynamic PM and system PM
@@ -499,22 +465,11 @@
 Dynamic power management and system power management can interact in
 a couple of ways.
 
-Firstly, a device may already be manually suspended or autosuspended
-when a system suspend occurs.  Since system suspends are supposed to
-be as transparent as possible, the device should remain suspended
-following the system resume.  The 2.6.23 kernel obeys this principle
-for manually suspended devices but not for autosuspended devices; they
-do get resumed when the system wakes up.  (Presumably they will be
-autosuspended again after their idle-delay time expires.)  In later
-kernels this behavior will be fixed.
-
-(There is an exception.  If a device would undergo a reset-resume
-instead of a normal resume, and the device is enabled for remote
-wakeup, then the reset-resume takes place even if the device was
-already suspended when the system suspend began.  The justification is
-that a reset-resume is a kind of remote-wakeup event.  Or to put it
-another way, a device which needs a reset won't be able to generate
-normal remote-wakeup signals, so it ought to be resumed immediately.)
+Firstly, a device may already be autosuspended when a system suspend
+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.
 
 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/vm/00-INDEX b/Documentation/vm/00-INDEX
index e57d6a9..dca82d7 100644
--- a/Documentation/vm/00-INDEX
+++ b/Documentation/vm/00-INDEX
@@ -4,23 +4,35 @@
 	- An explanation from Linus about tsk->active_mm vs tsk->mm.
 balance
 	- various information on memory balancing.
+hugepage-mmap.c
+	- Example app using huge page memory with the mmap system call.
+hugepage-shm.c
+	- Example app using huge page memory with Sys V shared memory system calls.
 hugetlbpage.txt
 	- a brief summary of hugetlbpage support in the Linux kernel.
+hwpoison.txt
+	- explains what hwpoison is
 ksm.txt
 	- how to use the Kernel Samepage Merging feature.
 locking
 	- info on how locking and synchronization is done in the Linux vm code.
+map_hugetlb.c
+	- an example program that uses the MAP_HUGETLB mmap flag.
 numa
 	- information about NUMA specific code in the Linux vm.
 numa_memory_policy.txt
 	- documentation of concepts and APIs of the 2.6 memory policy support.
 overcommit-accounting
 	- description of the Linux kernels overcommit handling modes.
+page-types.c
+	- Tool for querying page flags
 page_migration
 	- description of page migration in NUMA systems.
+pagemap.txt
+	- pagemap, from the userspace perspective
 slabinfo.c
 	- source code for a tool to get reports about slabs.
 slub.txt
 	- a short users guide for SLUB.
-map_hugetlb.c
-	- an example program that uses the MAP_HUGETLB mmap flag.
+unevictable-lru.txt
+	- Unevictable LRU infrastructure
diff --git a/Documentation/vm/Makefile b/Documentation/vm/Makefile
index 5bd269b..9dcff32 100644
--- a/Documentation/vm/Makefile
+++ b/Documentation/vm/Makefile
@@ -2,7 +2,7 @@
 obj- := dummy.o
 
 # List of programs to build
-hostprogs-y := slabinfo page-types
+hostprogs-y := slabinfo page-types hugepage-mmap hugepage-shm map_hugetlb
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
diff --git a/Documentation/vm/hugepage-mmap.c b/Documentation/vm/hugepage-mmap.c
new file mode 100644
index 0000000..db0dd9a
--- /dev/null
+++ b/Documentation/vm/hugepage-mmap.c
@@ -0,0 +1,91 @@
+/*
+ * hugepage-mmap:
+ *
+ * Example of using huge page memory in a user application using the mmap
+ * system call.  Before running this application, make sure that the
+ * administrator has mounted the hugetlbfs filesystem (on some directory
+ * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this
+ * example, the app is requesting memory of size 256MB that is backed by
+ * huge pages.
+ *
+ * For the ia64 architecture, the Linux kernel reserves Region number 4 for
+ * huge pages.  That means that if one requires a fixed address, a huge page
+ * aligned address starting with 0x800000... will be required.  If a fixed
+ * address is not required, the kernel will select an address in the proper
+ * range.
+ * Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#define FILE_NAME "/mnt/hugepagefile"
+#define LENGTH (256UL*1024*1024)
+#define PROTECTION (PROT_READ | PROT_WRITE)
+
+/* Only ia64 requires this */
+#ifdef __ia64__
+#define ADDR (void *)(0x8000000000000000UL)
+#define FLAGS (MAP_SHARED | MAP_FIXED)
+#else
+#define ADDR (void *)(0x0UL)
+#define FLAGS (MAP_SHARED)
+#endif
+
+static void check_bytes(char *addr)
+{
+	printf("First hex is %x\n", *((unsigned int *)addr));
+}
+
+static void write_bytes(char *addr)
+{
+	unsigned long i;
+
+	for (i = 0; i < LENGTH; i++)
+		*(addr + i) = (char)i;
+}
+
+static void read_bytes(char *addr)
+{
+	unsigned long i;
+
+	check_bytes(addr);
+	for (i = 0; i < LENGTH; i++)
+		if (*(addr + i) != (char)i) {
+			printf("Mismatch at %lu\n", i);
+			break;
+		}
+}
+
+int main(void)
+{
+	void *addr;
+	int fd;
+
+	fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);
+	if (fd < 0) {
+		perror("Open failed");
+		exit(1);
+	}
+
+	addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0);
+	if (addr == MAP_FAILED) {
+		perror("mmap");
+		unlink(FILE_NAME);
+		exit(1);
+	}
+
+	printf("Returned address is %p\n", addr);
+	check_bytes(addr);
+	write_bytes(addr);
+	read_bytes(addr);
+
+	munmap(addr, LENGTH);
+	close(fd);
+	unlink(FILE_NAME);
+
+	return 0;
+}
diff --git a/Documentation/vm/hugepage-shm.c b/Documentation/vm/hugepage-shm.c
new file mode 100644
index 0000000..07956d8
--- /dev/null
+++ b/Documentation/vm/hugepage-shm.c
@@ -0,0 +1,98 @@
+/*
+ * hugepage-shm:
+ *
+ * Example of using huge page memory in a user application using Sys V shared
+ * memory system calls.  In this example the app is requesting 256MB of
+ * memory that is backed by huge pages.  The application uses the flag
+ * SHM_HUGETLB in the shmget system call to inform the kernel that it is
+ * requesting huge pages.
+ *
+ * For the ia64 architecture, the Linux kernel reserves Region number 4 for
+ * huge pages.  That means that if one requires a fixed address, a huge page
+ * aligned address starting with 0x800000... will be required.  If a fixed
+ * address is not required, the kernel will select an address in the proper
+ * range.
+ * Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
+ *
+ * Note: The default shared memory limit is quite low on many kernels,
+ * you may need to increase it via:
+ *
+ * echo 268435456 > /proc/sys/kernel/shmmax
+ *
+ * This will increase the maximum size per shared memory segment to 256MB.
+ * The other limit that you will hit eventually is shmall which is the
+ * total amount of shared memory in pages. To set it to 16GB on a system
+ * with a 4kB pagesize do:
+ *
+ * echo 4194304 > /proc/sys/kernel/shmall
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
+
+#ifndef SHM_HUGETLB
+#define SHM_HUGETLB 04000
+#endif
+
+#define LENGTH (256UL*1024*1024)
+
+#define dprintf(x)  printf(x)
+
+/* Only ia64 requires this */
+#ifdef __ia64__
+#define ADDR (void *)(0x8000000000000000UL)
+#define SHMAT_FLAGS (SHM_RND)
+#else
+#define ADDR (void *)(0x0UL)
+#define SHMAT_FLAGS (0)
+#endif
+
+int main(void)
+{
+	int shmid;
+	unsigned long i;
+	char *shmaddr;
+
+	if ((shmid = shmget(2, LENGTH,
+			    SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
+		perror("shmget");
+		exit(1);
+	}
+	printf("shmid: 0x%x\n", shmid);
+
+	shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS);
+	if (shmaddr == (char *)-1) {
+		perror("Shared memory attach failure");
+		shmctl(shmid, IPC_RMID, NULL);
+		exit(2);
+	}
+	printf("shmaddr: %p\n", shmaddr);
+
+	dprintf("Starting the writes:\n");
+	for (i = 0; i < LENGTH; i++) {
+		shmaddr[i] = (char)(i);
+		if (!(i % (1024 * 1024)))
+			dprintf(".");
+	}
+	dprintf("\n");
+
+	dprintf("Starting the Check...");
+	for (i = 0; i < LENGTH; i++)
+		if (shmaddr[i] != (char)i)
+			printf("\nIndex %lu mismatched\n", i);
+	dprintf("Done.\n");
+
+	if (shmdt((const void *)shmaddr) != 0) {
+		perror("Detach failure");
+		shmctl(shmid, IPC_RMID, NULL);
+		exit(3);
+	}
+
+	shmctl(shmid, IPC_RMID, NULL);
+
+	return 0;
+}
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index bc31636..457634c 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -299,176 +299,11 @@
 *******************************************************************
 
 /*
- * Example of using huge page memory in a user application using Sys V shared
- * memory system calls.  In this example the app is requesting 256MB of
- * memory that is backed by huge pages.  The application uses the flag
- * SHM_HUGETLB in the shmget system call to inform the kernel that it is
- * requesting huge pages.
- *
- * For the ia64 architecture, the Linux kernel reserves Region number 4 for
- * huge pages.  That means that if one requires a fixed address, a huge page
- * aligned address starting with 0x800000... will be required.  If a fixed
- * address is not required, the kernel will select an address in the proper
- * range.
- * Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
- *
- * Note: The default shared memory limit is quite low on many kernels,
- * you may need to increase it via:
- *
- * echo 268435456 > /proc/sys/kernel/shmmax
- *
- * This will increase the maximum size per shared memory segment to 256MB.
- * The other limit that you will hit eventually is shmall which is the
- * total amount of shared memory in pages. To set it to 16GB on a system
- * with a 4kB pagesize do:
- *
- * echo 4194304 > /proc/sys/kernel/shmall
+ * hugepage-shm:  see Documentation/vm/hugepage-shm.c
  */
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/mman.h>
-
-#ifndef SHM_HUGETLB
-#define SHM_HUGETLB 04000
-#endif
-
-#define LENGTH (256UL*1024*1024)
-
-#define dprintf(x)  printf(x)
-
-#define ADDR (void *)(0x0UL)	/* let kernel choose address */
-#define SHMAT_FLAGS (0)
-
-int main(void)
-{
-	int shmid;
-	unsigned long i;
-	char *shmaddr;
-
-	if ((shmid = shmget(2, LENGTH,
-			    SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
-		perror("shmget");
-		exit(1);
-	}
-	printf("shmid: 0x%x\n", shmid);
-
-	shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS);
-	if (shmaddr == (char *)-1) {
-		perror("Shared memory attach failure");
-		shmctl(shmid, IPC_RMID, NULL);
-		exit(2);
-	}
-	printf("shmaddr: %p\n", shmaddr);
-
-	dprintf("Starting the writes:\n");
-	for (i = 0; i < LENGTH; i++) {
-		shmaddr[i] = (char)(i);
-		if (!(i % (1024 * 1024)))
-			dprintf(".");
-	}
-	dprintf("\n");
-
-	dprintf("Starting the Check...");
-	for (i = 0; i < LENGTH; i++)
-		if (shmaddr[i] != (char)i)
-			printf("\nIndex %lu mismatched\n", i);
-	dprintf("Done.\n");
-
-	if (shmdt((const void *)shmaddr) != 0) {
-		perror("Detach failure");
-		shmctl(shmid, IPC_RMID, NULL);
-		exit(3);
-	}
-
-	shmctl(shmid, IPC_RMID, NULL);
-
-	return 0;
-}
 
 *******************************************************************
 
 /*
- * Example of using huge page memory in a user application using the mmap
- * system call.  Before running this application, make sure that the
- * administrator has mounted the hugetlbfs filesystem (on some directory
- * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this
- * example, the app is requesting memory of size 256MB that is backed by
- * huge pages.
- *
- * For the ia64 architecture, the Linux kernel reserves Region number 4 for
- * huge pages.  That means that if one requires a fixed address, a huge page
- * aligned address starting with 0x800000... will be required.  If a fixed
- * address is not required, the kernel will select an address in the proper
- * range.
- * Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
+ * hugepage-mmap:  see Documentation/vm/hugepage-mmap.c
  */
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-
-#define FILE_NAME "/mnt/hugepagefile"
-#define LENGTH (256UL*1024*1024)
-#define PROTECTION (PROT_READ | PROT_WRITE)
-
-#define ADDR (void *)(0x0UL)	/* let kernel choose address */
-#define FLAGS (MAP_SHARED)
-
-void check_bytes(char *addr)
-{
-	printf("First hex is %x\n", *((unsigned int *)addr));
-}
-
-void write_bytes(char *addr)
-{
-	unsigned long i;
-
-	for (i = 0; i < LENGTH; i++)
-		*(addr + i) = (char)i;
-}
-
-void read_bytes(char *addr)
-{
-	unsigned long i;
-
-	check_bytes(addr);
-	for (i = 0; i < LENGTH; i++)
-		if (*(addr + i) != (char)i) {
-			printf("Mismatch at %lu\n", i);
-			break;
-		}
-}
-
-int main(void)
-{
-	void *addr;
-	int fd;
-
-	fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);
-	if (fd < 0) {
-		perror("Open failed");
-		exit(1);
-	}
-
-	addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0);
-	if (addr == MAP_FAILED) {
-		perror("mmap");
-		unlink(FILE_NAME);
-		exit(1);
-	}
-
-	printf("Returned address is %p\n", addr);
-	check_bytes(addr);
-	write_bytes(addr);
-	read_bytes(addr);
-
-	munmap(addr, LENGTH);
-	close(fd);
-	unlink(FILE_NAME);
-
-	return 0;
-}
diff --git a/Documentation/vm/map_hugetlb.c b/Documentation/vm/map_hugetlb.c
index e2bdae3..9969c7d 100644
--- a/Documentation/vm/map_hugetlb.c
+++ b/Documentation/vm/map_hugetlb.c
@@ -31,12 +31,12 @@
 #define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)
 #endif
 
-void check_bytes(char *addr)
+static void check_bytes(char *addr)
 {
 	printf("First hex is %x\n", *((unsigned int *)addr));
 }
 
-void write_bytes(char *addr)
+static void write_bytes(char *addr)
 {
 	unsigned long i;
 
@@ -44,7 +44,7 @@
 		*(addr + i) = (char)i;
 }
 
-void read_bytes(char *addr)
+static void read_bytes(char *addr)
 {
 	unsigned long i;
 
diff --git a/Documentation/vm/slub.txt b/Documentation/vm/slub.txt
index b37300e..07375e7 100644
--- a/Documentation/vm/slub.txt
+++ b/Documentation/vm/slub.txt
@@ -41,6 +41,7 @@
 	P		Poisoning (object and padding)
 	U		User tracking (free and alloc)
 	T		Trace (please only use on single slabs)
+	A		Toggle failslab filter mark for the cache
 	O		Switch debugging off for caches that would have
 			caused higher minimum slab orders
 	-		Switch all debugging off (useful if the kernel is
diff --git a/Documentation/voyager.txt b/Documentation/voyager.txt
deleted file mode 100644
index 2749af5..0000000
--- a/Documentation/voyager.txt
+++ /dev/null
@@ -1,95 +0,0 @@
-Running Linux on the Voyager Architecture
-=========================================
-
-For full details and current project status, see
-
-http://www.hansenpartnership.com/voyager
-
-The voyager architecture was designed by NCR in the mid 80s to be a
-fully SMP capable RAS computing architecture built around intel's 486
-chip set.  The voyager came in three levels of architectural
-sophistication: 3,4 and 5 --- 1 and 2 never made it out of prototype.
-The linux patches support only the Level 5 voyager architecture (any
-machine class 3435 and above).
-
-The Voyager Architecture
-------------------------
-
-Voyager machines consist of a Baseboard with a 386 diagnostic
-processor, a Power Supply Interface (PSI) a Primary and possibly
-Secondary Microchannel bus and between 2 and 20 voyager slots.  The
-voyager slots can be populated with memory and cpu cards (up to 4GB
-memory and from 1 486 to 32 Pentium Pro processors).  Internally, the
-voyager has a dual arbitrated system bus and a configuration and test
-bus (CAT).  The voyager bus speed is 40MHz.  Therefore (since all
-voyager cards are dual ported for each system bus) the maximum
-transfer rate is 320Mb/s but only if you have your slot configuration
-tuned (only memory cards can communicate with both busses at once, CPU
-cards utilise them one at a time).
-
-Voyager SMP
------------
-
-Since voyager was the first intel based SMP system, it is slightly
-more primitive than the Intel IO-APIC approach to SMP.  Voyager allows
-arbitrary interrupt routing (including processor affinity routing) of
-all 16 PC type interrupts.  However it does this by using a modified
-5259 master/slave chip set instead of an APIC bus.  Additionally,
-voyager supports Cross Processor Interrupts (CPI) equivalent to the
-APIC IPIs.  There are two routed voyager interrupt lines provided to
-each slot.
-
-Processor Cards
----------------
-
-These come in single, dyadic and quad configurations (the quads are
-problematic--see later).  The maximum configuration is 8 quad cards
-for 32 way SMP.
-
-Quad Processors
----------------
-
-Because voyager only supplies two interrupt lines to each Processor
-card, the Quad processors have to be configured (and Bootstrapped) in
-as a pair of Master/Slave processors.
-
-In fact, most Quad cards only accept one VIC interrupt line, so they
-have one interrupt handling processor (called the VIC extended
-processor) and three non-interrupt handling processors.
-
-Current Status
---------------
-
-The System will boot on Mono, Dyad and Quad cards.  There was
-originally a Quad boot problem which has been fixed by proper gdt
-alignment in the initial boot loader.  If you still cannot get your
-voyager system to boot, email me at:
-
-<J.E.J.Bottomley@HansenPartnership.com>
-
-
-The Quad cards now support using the separate Quad CPI vectors instead
-of going through the VIC mailbox system.
-
-The Level 4 architecture (3430 and 3360 Machines) should also work
-fine.
-
-Dump Switch
------------
-
-The voyager dump switch sends out a broadcast NMI which the voyager
-code intercepts and does a task dump.
-
-Power Switch
-------------
-
-The front panel power switch is intercepted by the kernel and should
-cause a system shutdown and power off.
-
-A Note About Mixed CPU Systems
-------------------------------
-
-Linux isn't designed to handle mixed CPU systems very well.  In order
-to get everything going you *must* make sure that your lowest
-capability CPU is used for booting.  Also, mixing CPU classes
-(e.g. 486 and 586) is really not going to work very well at all.
diff --git a/MAINTAINERS b/MAINTAINERS
index c685ee2..47cc449 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -71,6 +71,7 @@
 	M: Mail patches to: FullName <address@domain>
 	L: Mailing list that is relevant to this area
 	W: Web-page with status/info
+	Q: Patchwork web based patch tracking system site
 	T: SCM tree type and location.  Type is one of: git, hg, quilt, stgit.
 	S: Status, one of the following:
 	   Supported:	Someone is actually paid to look after this.
@@ -182,6 +183,7 @@
 M:	Latchesar Ionkov <lucho@ionkov.net>
 L:	v9fs-developer@lists.sourceforge.net
 W:	http://swik.net/v9fs
+Q:	http://patchwork.kernel.org/project/v9fs-devel/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git
 S:	Maintained
 F:	Documentation/filesystems/9p.txt
@@ -238,6 +240,7 @@
 M:	Len Brown <lenb@kernel.org>
 L:	linux-acpi@vger.kernel.org
 W:	http://www.lesswatts.org/projects/acpi/
+Q:	http://patchwork.kernel.org/project/linux-acpi/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
 S:	Supported
 F:	drivers/acpi/
@@ -428,7 +431,6 @@
 L:	linux-geode@lists.infradead.org (moderated for non-subscribers)
 W:	http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
 S:	Supported
-F:	arch/x86/kernel/geode_32.c
 F:	drivers/char/hw_random/geode-rng.c
 F:	drivers/crypto/geode*
 F:	drivers/video/geode/
@@ -664,6 +666,12 @@
 F:	arch/arm/mach-mx*/
 F:	arch/arm/plat-mxc/
 
+ARM/FREESCALE IMX51
+M:	Amit Kucheria <amit.kucheria@canonical.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm/mach-mx5/
+
 ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
 M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -937,6 +945,16 @@
 S:	Maintained
 F:	arch/arm/mach-s3c6410/
 
+ARM/SHMOBILE ARM ARCHITECTURE
+M:	Paul Mundt <lethal@linux-sh.org>
+M:	Magnus Damm <magnus.damm@gmail.com>
+L:	linux-sh@vger.kernel.org
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/genesis-2.6.git
+W:	http://oss.renesas.com
+S:	Supported
+F:	arch/arm/mach-shmobile/
+F:	drivers/sh/
+
 ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
 M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -966,6 +984,13 @@
 S:	Maintained
 F:	arch/arm/vfp/
 
+ASC7621 HARDWARE MONITOR DRIVER
+M:	George Joseph <george.joseph@fairview5.com>
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+F:	Documentation/hwmon/asc7621
+F:	drivers/hwmon/asc7621.c
+
 ASUS ACPI EXTRAS DRIVER
 M:	Corentin Chary <corentincj@iksaif.net>
 M:	Karol Kozimor <sziwan@users.sourceforge.net>
@@ -1226,6 +1251,13 @@
 S:	Supported
 F:	drivers/rtc/rtc-bfin.c
 
+BLACKFIN SDH DRIVER
+M:	Cliff Cai <cliff.cai@analog.com>
+L:	uclinux-dist-devel@blackfin.uclinux.org
+W:	http://blackfin.uclinux.org
+S:	Supported
+F:	drivers/mmc/host/bfin_sdh.c
+
 BLACKFIN SERIAL DRIVER
 M:	Sonic Zhang <sonic.zhang@analog.com>
 L:	uclinux-dist-devel@blackfin.uclinux.org
@@ -1332,6 +1364,7 @@
 M:	Chris Mason <chris.mason@oracle.com>
 L:	linux-btrfs@vger.kernel.org
 W:	http://btrfs.wiki.kernel.org/
+Q:	http://patchwork.kernel.org/project/linux-btrfs/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable.git
 S:	Maintained
 F:	Documentation/filesystems/btrfs.txt
@@ -1506,6 +1539,7 @@
 L:	linux-cifs-client@lists.samba.org (moderated for non-subscribers)
 L:	samba-technical@lists.samba.org (moderated for non-subscribers)
 W:	http://linux-cifs.samba.org/
+Q:	http://patchwork.ozlabs.org/project/linux-cifs-client/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git
 S:	Supported
 F:	Documentation/filesystems/cifs.txt
@@ -1792,6 +1826,7 @@
 P:	Alasdair Kergon
 L:	dm-devel@redhat.com
 W:	http://sources.redhat.com/dm
+Q:	http://patchwork.kernel.org/project/dm-devel/list/
 S:	Maintained
 F:	Documentation/device-mapper/
 F:	drivers/md/dm*
@@ -2137,6 +2172,7 @@
 M:	Andreas Dilger <adilger@sun.com>
 L:	linux-ext4@vger.kernel.org
 W:	http://ext4.wiki.kernel.org
+Q:	http://patchwork.ozlabs.org/project/linux-ext4/list/
 S:	Maintained
 F:	Documentation/filesystems/ext4.txt
 F:	fs/ext4/
@@ -2513,13 +2549,6 @@
 S:	Maintained
 F:	sound/parisc/harmony.*
 
-HAYES ESP SERIAL DRIVER
-M:	"Andrew J. Robinson" <arobinso@nyx.net>
-W:	http://www.nyx.net/~arobinso
-S:	Maintained
-F:	Documentation/serial/hayes-esp.txt
-F:	drivers/char/esp.c
-
 HEWLETT-PACKARD SMART2 RAID DRIVER
 M:	Chirag Kantharia <chirag.kantharia@hp.com>
 L:	iss_storagedev@hp.com
@@ -2728,6 +2757,7 @@
 IDE SUBSYSTEM
 M:	"David S. Miller" <davem@davemloft.net>
 L:	linux-ide@vger.kernel.org
+Q:	http://patchwork.ozlabs.org/project/linux-ide/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide-2.6.git
 S:	Maintained
 F:	Documentation/ide/
@@ -2782,6 +2812,7 @@
 M:	Hal Rosenstock <hal.rosenstock@gmail.com>
 L:	linux-rdma@vger.kernel.org
 W:	http://www.openib.org/
+Q:	http://patchwork.kernel.org/project/linux-rdma/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
 S:	Supported
 F:	Documentation/infiniband/
@@ -2801,12 +2832,13 @@
 M:	Dmitry Torokhov <dmitry.torokhov@gmail.com>
 M:	Dmitry Torokhov <dtor@mail.ru>
 L:	linux-input@vger.kernel.org
+Q:	http://patchwork.kernel.org/project/linux-input/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
 S:	Maintained
 F:	drivers/input/
 
 INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
-M:	Sylvain Meyer <sylvain.meyer@worldonline.fr>
+M:	Maik Broemme <mbroemme@plusserver.de>
 L:	linux-fbdev@vger.kernel.org
 S:	Maintained
 F:	Documentation/fb/intelfb.txt
@@ -3057,6 +3089,13 @@
 S:	Maintained
 F:	drivers/isdn/hardware/eicon/
 
+IT87 HARDWARE MONITORING DRIVER
+M:	Jean Delvare <khali@linux-fr.org>
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+F:	Documentation/hwmon/it87
+F:	drivers/hwmon/it87.c
+
 IVTV VIDEO4LINUX DRIVER
 M:	Andy Walls <awalls@radix.net>
 L:	ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
@@ -3110,6 +3149,7 @@
 KCONFIG
 M:	Roman Zippel <zippel@linux-m68k.org>
 L:	linux-kbuild@vger.kernel.org
+Q:	http://patchwork.kernel.org/project/linux-kbuild/list/
 S:	Maintained
 F:	Documentation/kbuild/kconfig-language.txt
 F:	scripts/kconfig/
@@ -3184,7 +3224,7 @@
 F:	arch/x86/kvm/svm.c
 
 KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC
-M:	Hollis Blanchard <hollisb@us.ibm.com>
+M:	Alexander Graf <agraf@suse.de>
 L:	kvm-ppc@vger.kernel.org
 W:	http://kvm.qumranet.com
 S:	Supported
@@ -3323,6 +3363,7 @@
 M:	Paul Mackerras <paulus@samba.org>
 W:	http://www.penguinppc.org/
 L:	linuxppc-dev@ozlabs.org
+Q:	http://patchwork.ozlabs.org/project/linuxppc-dev/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git
 S:	Supported
 F:	Documentation/powerpc/
@@ -3443,6 +3484,13 @@
 F:	Documentation/ldm.txt
 F:	fs/partitions/ldm.*
 
+LogFS
+M:	Joern Engel <joern@logfs.org>
+L:	logfs@logfs.org
+W:	logfs.org
+S:	Maintained
+F:	fs/logfs/
+
 LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
 M:	Eric Moore <Eric.Moore@lsi.com>
 M:	support@lsi.com
@@ -3579,6 +3627,7 @@
 P:	LinuxTV.org Project
 L:	linux-media@vger.kernel.org
 W:	http://linuxtv.org
+Q:	http://patchwork.kernel.org/project/linux-media/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:	Maintained
 F:	Documentation/dvb/
@@ -3606,7 +3655,7 @@
 
 MEMORY RESOURCE CONTROLLER
 M:	Balbir Singh <balbir@linux.vnet.ibm.com>
-M:	Pavel Emelyanov <xemul@openvz.org>
+M:	Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
 M:	KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
 L:	linux-mm@kvack.org
 S:	Maintained
@@ -3614,8 +3663,9 @@
 
 MEMORY TECHNOLOGY DEVICES (MTD)
 M:	David Woodhouse <dwmw2@infradead.org>
-W:	http://www.linux-mtd.infradead.org/
 L:	linux-mtd@lists.infradead.org
+W:	http://www.linux-mtd.infradead.org/
+Q:	http://patchwork.ozlabs.org/project/linux-mtd/list/
 T:	git git://git.infradead.org/mtd-2.6.git
 S:	Maintained
 F:	drivers/mtd/
@@ -3875,6 +3925,7 @@
 NETWORKING [WIRELESS]
 M:	"John W. Linville" <linville@tuxdriver.com>
 L:	linux-wireless@vger.kernel.org
+Q:	http://patchwork.kernel.org/project/linux-wireless/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
 S:	Maintained
 F:	net/mac80211/
@@ -3967,6 +4018,7 @@
 L:	linux-omap@vger.kernel.org
 W:	http://www.muru.com/linux/omap/
 W:	http://linux.omap.com/
+Q:	http://patchwork.kernel.org/project/linux-omap/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
 S:	Maintained
 F:	arch/arm/*omap*/
@@ -4193,6 +4245,7 @@
 M:	"James E.J. Bottomley" <jejb@parisc-linux.org>
 L:	linux-parisc@vger.kernel.org
 W:	http://www.parisc-linux.org/
+Q:	http://patchwork.kernel.org/project/linux-parisc/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
 S:	Maintained
 F:	arch/parisc/
@@ -4235,6 +4288,7 @@
 PCI SUBSYSTEM
 M:	Jesse Barnes <jbarnes@virtuousgeek.org>
 L:	linux-pci@vger.kernel.org
+Q:	http://patchwork.kernel.org/project/linux-pci/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
 S:	Supported
 F:	Documentation/PCI/
@@ -4273,10 +4327,13 @@
 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>
 S:	Supported
 F:	kernel/perf_event.c
 F:	include/linux/perf_event.h
-F:	arch/*/*/kernel/perf_event.c
+F:	arch/*/kernel/perf_event.c
+F:	arch/*/kernel/*/perf_event.c
+F:	arch/*/kernel/*/*/perf_event.c
 F:	arch/*/include/asm/perf_event.h
 F:	arch/*/lib/perf_event.c
 F:	arch/*/kernel/perf_callchain.c
@@ -4473,6 +4530,13 @@
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
 S:	Maintained
 
+MMP2 SUPPORT (aka ARMADA610)
+M:	Haojian Zhuang <haojian.zhuang@marvell.com>
+M:	Eric Miao <eric.y.miao@gmail.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
+S:	Maintained
+
 PXA MMCI DRIVER
 S:	Orphan
 
@@ -4610,6 +4674,7 @@
 REAL TIME CLOCK (RTC) SUBSYSTEM
 M:	Alessandro Zummo <a.zummo@towertech.it>
 L:	rtc-linux@googlegroups.com
+Q:	http://patchwork.ozlabs.org/project/rtc-linux/list/
 S:	Maintained
 F:	Documentation/rtc.txt
 F:	drivers/rtc/
@@ -4977,6 +5042,7 @@
 TI DAVINCI MACHINE SUPPORT
 P:	Kevin Hilman
 M:	davinci-linux-open-source@linux.davincidsp.com
+Q:	http://patchwork.kernel.org/project/linux-davinci/list/
 S:	Supported
 F:	arch/arm/mach-davinci
 
@@ -5142,6 +5208,7 @@
 SPARC + UltraSPARC (sparc/sparc64)
 M:	"David S. Miller" <davem@davemloft.net>
 L:	sparclinux@vger.kernel.org
+Q:	http://patchwork.ozlabs.org/project/sparclinux/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
 S:	Maintained
@@ -5157,6 +5224,7 @@
 M:	David Brownell <dbrownell@users.sourceforge.net>
 M:	Grant Likely <grant.likely@secretlab.ca>
 L:	spi-devel-general@lists.sourceforge.net
+Q:	http://patchwork.kernel.org/project/spi-devel-general/list/
 S:	Maintained
 F:	Documentation/spi/
 F:	drivers/spi/
@@ -5212,7 +5280,7 @@
 
 STARMODE RADIO IP (STRIP) PROTOCOL DRIVER
 S:	Orphan
-F:	drivers/net/wireless/strip.c
+F:	drivers/staging/strip/strip.c
 F:	include/linux/if_strip.h
 
 STRADIS MPEG-2 DECODER DRIVER
@@ -5233,6 +5301,7 @@
 M:	Paul Mundt <lethal@linux-sh.org>
 L:	linux-sh@vger.kernel.org
 W:	http://www.linux-sh.org
+Q:	http://patchwork.kernel.org/project/linux-sh/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git
 S:	Supported
 F:	Documentation/sh/
@@ -6000,7 +6069,7 @@
 W:	http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
 S:	Maintained
 F:	Documentation/networking/wavelan.txt
-F:	drivers/net/wireless/wavelan*
+F:	drivers/staging/wavelan/
 
 WD7000 SCSI DRIVER
 M:	Miroslav Zagorac <zaga@fly.cc.fer.hr>
@@ -6108,6 +6177,7 @@
 X86 PLATFORM DRIVERS
 M:	Matthew Garrett <mjg@redhat.com>
 L:	platform-driver-x86@vger.kernel.org
+T:      git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git
 S:	Maintained
 F:	drivers/platform/x86
 
@@ -6195,6 +6265,7 @@
 THE REST
 M:	Linus Torvalds <torvalds@linux-foundation.org>
 L:	linux-kernel@vger.kernel.org
+Q:	http://patchwork.kernel.org/project/LKML/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
 S:	Buried alive in reporters
 F:	*
diff --git a/Makefile b/Makefile
index 1b24895..08ff02d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 33
-EXTRAVERSION =
+SUBLEVEL = 34
+EXTRAVERSION = -rc1
 NAME = Man-Eating Seals of Antiquity
 
 # *DOCUMENTATION*
diff --git a/arch/Kconfig b/arch/Kconfig
index 215e460..e5eb133 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -41,6 +41,17 @@
 	  for kernel debugging, non-intrusive instrumentation and testing.
 	  If in doubt, say "N".
 
+config OPTPROBES
+	bool "Kprobes jump optimization support (EXPERIMENTAL)"
+	default y
+	depends on KPROBES
+	depends on !PREEMPT
+	depends on HAVE_OPTPROBES
+	select KALLSYMS_ALL
+	help
+	  This option will allow kprobes to optimize breakpoint to
+	  a jump for reducing its overhead.
+
 config HAVE_EFFICIENT_UNALIGNED_ACCESS
 	bool
 	help
@@ -83,6 +94,8 @@
 config HAVE_KRETPROBES
 	bool
 
+config HAVE_OPTPROBES
+	bool
 #
 # An arch should select this if it provides all these things:
 #
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index bd7261e..75291fd 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -10,6 +10,7 @@
 	select HAVE_OPROFILE
 	select HAVE_SYSCALL_WRAPPERS
 	select HAVE_PERF_EVENTS
+	select HAVE_DMA_ATTRS
 	help
 	  The Alpha is a 64-bit general-purpose processor designed and
 	  marketed by the Digital Equipment Corporation of blessed memory,
@@ -58,6 +59,9 @@
 	bool
 	default y
 
+config NEED_DMA_MAP_STATE
+       def_bool y
+
 config GENERIC_ISA_DMA
 	bool
 	default y
diff --git a/arch/alpha/include/asm/dma-mapping.h b/arch/alpha/include/asm/dma-mapping.h
index 04eb568..1bce816 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -1,71 +1,49 @@
 #ifndef _ALPHA_DMA_MAPPING_H
 #define _ALPHA_DMA_MAPPING_H
 
+#include <linux/dma-attrs.h>
 
-#ifdef CONFIG_PCI
+extern struct dma_map_ops *dma_ops;
 
-#include <linux/pci.h>
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+	return dma_ops;
+}
 
-#define dma_map_single(dev, va, size, dir)		\
-		pci_map_single(alpha_gendev_to_pci(dev), va, size, dir)
-#define dma_unmap_single(dev, addr, size, dir)		\
-		pci_unmap_single(alpha_gendev_to_pci(dev), addr, size, dir)
-#define dma_alloc_coherent(dev, size, addr, gfp)	\
-	      __pci_alloc_consistent(alpha_gendev_to_pci(dev), size, addr, gfp)
-#define dma_free_coherent(dev, size, va, addr)		\
-		pci_free_consistent(alpha_gendev_to_pci(dev), size, va, addr)
-#define dma_map_page(dev, page, off, size, dir)		\
-		pci_map_page(alpha_gendev_to_pci(dev), page, off, size, dir)
-#define dma_unmap_page(dev, addr, size, dir)		\
-		pci_unmap_page(alpha_gendev_to_pci(dev), addr, size, dir)
-#define dma_map_sg(dev, sg, nents, dir)			\
-		pci_map_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
-#define dma_unmap_sg(dev, sg, nents, dir)		\
-		pci_unmap_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
-#define dma_supported(dev, mask)			\
-		pci_dma_supported(alpha_gendev_to_pci(dev), mask)
-#define dma_mapping_error(dev, addr)				\
-		pci_dma_mapping_error(alpha_gendev_to_pci(dev), addr)
+#include <asm-generic/dma-mapping-common.h>
 
-#else	/* no PCI - no IOMMU. */
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t gfp)
+{
+	return get_dma_ops(dev)->alloc_coherent(dev, size, dma_handle, gfp);
+}
 
-#include <asm/io.h>	/* for virt_to_phys() */
+static inline void dma_free_coherent(struct device *dev, size_t size,
+				     void *vaddr, dma_addr_t dma_handle)
+{
+	get_dma_ops(dev)->free_coherent(dev, size, vaddr, dma_handle);
+}
 
-struct scatterlist;
-void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *dma_handle, gfp_t gfp);
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	       enum dma_data_direction direction);
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	return get_dma_ops(dev)->mapping_error(dev, dma_addr);
+}
 
-#define dma_free_coherent(dev, size, va, addr)		\
-		free_pages((unsigned long)va, get_order(size))
-#define dma_supported(dev, mask)		(mask < 0x00ffffffUL ? 0 : 1)
-#define dma_map_single(dev, va, size, dir)	virt_to_phys(va)
-#define dma_map_page(dev, page, off, size, dir)	(page_to_pa(page) + off)
+static inline int dma_supported(struct device *dev, u64 mask)
+{
+	return get_dma_ops(dev)->dma_supported(dev, mask);
+}
 
-#define dma_unmap_single(dev, addr, size, dir)	((void)0)
-#define dma_unmap_page(dev, addr, size, dir)	((void)0)
-#define dma_unmap_sg(dev, sg, nents, dir)	((void)0)
-
-#define dma_mapping_error(dev, addr)  (0)
-
-#endif	/* !CONFIG_PCI */
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+	return get_dma_ops(dev)->set_dma_mask(dev, mask);
+}
 
 #define dma_alloc_noncoherent(d, s, h, f)	dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h)	dma_free_coherent(d, s, v, h)
 #define dma_is_consistent(d, h)			(1)
 
-int dma_set_mask(struct device *dev, u64 mask);
-
-#define dma_sync_single_for_cpu(dev, addr, size, dir)	  ((void)0)
-#define dma_sync_single_for_device(dev, addr, size, dir)  ((void)0)
-#define dma_sync_single_range(dev, addr, off, size, dir)  ((void)0)
-#define dma_sync_sg_for_cpu(dev, sg, nents, dir)	  ((void)0)
-#define dma_sync_sg_for_device(dev, sg, nents, dir)	  ((void)0)
 #define dma_cache_sync(dev, va, size, dir)		  ((void)0)
-#define dma_sync_single_range_for_cpu(dev, addr, offset, size, dir)	((void)0)
-#define dma_sync_single_range_for_device(dev, addr, offset, size, dir)	((void)0)
-
 #define dma_get_cache_alignment()			  L1_CACHE_BYTES
 
 #endif	/* _ALPHA_DMA_MAPPING_H */
diff --git a/arch/alpha/include/asm/local.h b/arch/alpha/include/asm/local.h
index 6ad3ea6..b9e3e33 100644
--- a/arch/alpha/include/asm/local.h
+++ b/arch/alpha/include/asm/local.h
@@ -98,21 +98,4 @@
 #define __local_add(i,l)	((l)->a.counter+=(i))
 #define __local_sub(i,l)	((l)->a.counter-=(i))
 
-/* Use these for per-cpu local_t variables: on some archs they are
- * much more efficient than these naive implementations.  Note they take
- * a variable, not an address.
- */
-#define cpu_local_read(l)	local_read(&__get_cpu_var(l))
-#define cpu_local_set(l, i)	local_set(&__get_cpu_var(l), (i))
-
-#define cpu_local_inc(l)	local_inc(&__get_cpu_var(l))
-#define cpu_local_dec(l)	local_dec(&__get_cpu_var(l))
-#define cpu_local_add(i, l)	local_add((i), &__get_cpu_var(l))
-#define cpu_local_sub(i, l)	local_sub((i), &__get_cpu_var(l))
-
-#define __cpu_local_inc(l)	__local_inc(&__get_cpu_var(l))
-#define __cpu_local_dec(l)	__local_dec(&__get_cpu_var(l))
-#define __cpu_local_add(i, l)	__local_add((i), &__get_cpu_var(l))
-#define __cpu_local_sub(i, l)	__local_sub((i), &__get_cpu_var(l))
-
 #endif /* _ALPHA_LOCAL_H */
diff --git a/arch/alpha/include/asm/pci.h b/arch/alpha/include/asm/pci.h
index dd8dcab..28d0497 100644
--- a/arch/alpha/include/asm/pci.h
+++ b/arch/alpha/include/asm/pci.h
@@ -70,142 +70,11 @@
    decisions.  */
 #define PCI_DMA_BUS_IS_PHYS  0
 
-/* Allocate and map kernel buffer using consistent mode DMA for PCI
-   device.  Returns non-NULL cpu-view pointer to the buffer if
-   successful and sets *DMA_ADDRP to the pci side dma address as well,
-   else DMA_ADDRP is undefined.  */
-
-extern void *__pci_alloc_consistent(struct pci_dev *, size_t,
-				    dma_addr_t *, gfp_t);
-static inline void *
-pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma)
-{
-	return __pci_alloc_consistent(dev, size, dma, GFP_ATOMIC);
-}
-
-/* Free and unmap a consistent DMA buffer.  CPU_ADDR and DMA_ADDR must
-   be values that were returned from pci_alloc_consistent.  SIZE must
-   be the same as what as passed into pci_alloc_consistent.
-   References to the memory and mappings associated with CPU_ADDR or
-   DMA_ADDR past this call are illegal.  */
-
-extern void pci_free_consistent(struct pci_dev *, size_t, void *, dma_addr_t);
-
-/* Map a single buffer of the indicate size for PCI DMA in streaming mode.
-   The 32-bit PCI bus mastering address to use is returned.  Once the device
-   is given the dma address, the device owns this memory until either
-   pci_unmap_single or pci_dma_sync_single_for_cpu is performed.  */
-
-extern dma_addr_t pci_map_single(struct pci_dev *, void *, size_t, int);
-
-/* Likewise, but for a page instead of an address.  */
-extern dma_addr_t pci_map_page(struct pci_dev *, struct page *,
-			       unsigned long, size_t, int);
-
-/* Test for pci_map_single or pci_map_page having generated an error.  */
-
-static inline int
-pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr)
-{
-	return dma_addr == 0;
-}
-
-/* Unmap a single streaming mode DMA translation.  The DMA_ADDR and
-   SIZE must match what was provided for in a previous pci_map_single
-   call.  All other usages are undefined.  After this call, reads by
-   the cpu to the buffer are guaranteed to see whatever the device
-   wrote there.  */
-
-extern void pci_unmap_single(struct pci_dev *, dma_addr_t, size_t, int);
-extern void pci_unmap_page(struct pci_dev *, dma_addr_t, size_t, int);
-
-/* pci_unmap_{single,page} is not a nop, thus... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
-	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
-	__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)			\
-	((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
-	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)			\
-	((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
-	(((PTR)->LEN_NAME) = (VAL))
-
-/* Map a set of buffers described by scatterlist in streaming mode for
-   PCI DMA.  This is the scatter-gather version of the above
-   pci_map_single interface.  Here the scatter gather list elements
-   are each tagged with the appropriate PCI dma address and length.
-   They are obtained via sg_dma_{address,length}(SG).
-
-   NOTE: An implementation may be able to use a smaller number of DMA
-   address/length pairs than there are SG table elements.  (for
-   example via virtual mapping capabilities) The routine returns the
-   number of addr/length pairs actually used, at most nents.
-
-   Device ownership issues as mentioned above for pci_map_single are
-   the same here.  */
-
-extern int pci_map_sg(struct pci_dev *, struct scatterlist *, int, int);
-
-/* Unmap a set of streaming mode DMA translations.  Again, cpu read
-   rules concerning calls here are the same as for pci_unmap_single()
-   above.  */
-
-extern void pci_unmap_sg(struct pci_dev *, struct scatterlist *, int, int);
-
-/* Make physical memory consistent for a single streaming mode DMA
-   translation after a transfer and device currently has ownership
-   of the buffer.
-
-   If you perform a pci_map_single() but wish to interrogate the
-   buffer using the cpu, yet do not wish to teardown the PCI dma
-   mapping, you must call this function before doing so.  At the next
-   point you give the PCI dma address back to the card, you must first
-   perform a pci_dma_sync_for_device, and then the device again owns
-   the buffer.  */
-
-static inline void
-pci_dma_sync_single_for_cpu(struct pci_dev *dev, dma_addr_t dma_addr,
-			    long size, int direction)
-{
-	/* Nothing to do.  */
-}
-
-static inline void
-pci_dma_sync_single_for_device(struct pci_dev *dev, dma_addr_t dma_addr,
-			       size_t size, int direction)
-{
-	/* Nothing to do.  */
-}
-
-/* Make physical memory consistent for a set of streaming mode DMA
-   translations after a transfer.  The same as pci_dma_sync_single_*
-   but for a scatter-gather list, same rules and usage.  */
-
-static inline void
-pci_dma_sync_sg_for_cpu(struct pci_dev *dev, struct scatterlist *sg,
-			int nents, int direction)
-{
-	/* Nothing to do.  */
-}
-
-static inline void
-pci_dma_sync_sg_for_device(struct pci_dev *dev, struct scatterlist *sg,
-			   int nents, int direction)
-{
-	/* Nothing to do.  */
-}
-
-/* Return whether the given PCI device DMA address mask can
-   be supported properly.  For example, if your device can
-   only drive the low 24-bits during PCI bus mastering, then
-   you would pass 0x00ffffff as the mask to this function.  */
-
-extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
-
 #ifdef CONFIG_PCI
+
+/* implement the pci_ DMA API in terms of the generic device dma_ one */
+#include <asm-generic/pci-dma-compat.h>
+
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
 					unsigned long *strategy_parameter)
@@ -244,8 +113,6 @@
 	return hose->need_domain_info;
 }
 
-struct pci_dev *alpha_gendev_to_pci(struct device *dev);
-
 #endif /* __KERNEL__ */
 
 /* Values for the `which' argument to sys_pciconfig_iobase.  */
diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h
index 32c7a5c..65cf3e2 100644
--- a/arch/alpha/include/asm/ptrace.h
+++ b/arch/alpha/include/asm/ptrace.h
@@ -68,6 +68,7 @@
 
 #ifdef __KERNEL__
 
+#define arch_has_single_step()		(1)
 #define user_mode(regs) (((regs)->ps & 8) != 0)
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 62619f2..53c213f 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -361,7 +361,7 @@
 SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, char __user *, path,
 		int, flag, void __user *, data)
 {
-	int retval = -EINVAL;
+	int retval;
 	char *name;
 
 	name = getname(path);
@@ -379,6 +379,7 @@
 		retval = osf_procfs_mount(name, data, flag);
 		break;
 	default:
+		retval = -EINVAL;
 		printk("osf_mount(%ld, %x)\n", typenr, flag);
 	}
 	putname(name);
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index c19a376..823a540 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -106,58 +106,8 @@
 		return -ENODEV;
 }
 
-/* Stubs for the routines in pci_iommu.c: */
-
-void *
-__pci_alloc_consistent(struct pci_dev *pdev, size_t size,
-		       dma_addr_t *dma_addrp, gfp_t gfp)
-{
-	return NULL;
-}
-
-void
-pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
-		    dma_addr_t dma_addr)
-{
-}
-
-dma_addr_t
-pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size,
-	       int direction)
-{
-	return (dma_addr_t) 0;
-}
-
-void
-pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
-		 int direction)
-{
-}
-
-int
-pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
-	   int direction)
-{
-	return 0;
-}
-
-void
-pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
-	     int direction)
-{
-}
-
-int
-pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
-{
-	return 0;
-}
-
-/* Generic DMA mapping functions: */
-
-void *
-dma_alloc_coherent(struct device *dev, size_t size,
-		   dma_addr_t *dma_handle, gfp_t gfp)
+static void *alpha_noop_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t gfp)
 {
 	void *ret;
 
@@ -171,11 +121,22 @@
 	return ret;
 }
 
-EXPORT_SYMBOL(dma_alloc_coherent);
+static void alpha_noop_free_coherent(struct device *dev, size_t size,
+				     void *cpu_addr, dma_addr_t dma_addr)
+{
+	free_pages((unsigned long)cpu_addr, get_order(size));
+}
 
-int
-dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
-	   enum dma_data_direction direction)
+static dma_addr_t alpha_noop_map_page(struct device *dev, struct page *page,
+				      unsigned long offset, size_t size,
+				      enum dma_data_direction dir,
+				      struct dma_attrs *attrs)
+{
+	return page_to_pa(page) + offset;
+}
+
+static int alpha_noop_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
+			     enum dma_data_direction dir, struct dma_attrs *attrs)
 {
 	int i;
 	struct scatterlist *sg;
@@ -192,19 +153,37 @@
 	return nents;
 }
 
-EXPORT_SYMBOL(dma_map_sg);
+static int alpha_noop_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	return 0;
+}
 
-int
-dma_set_mask(struct device *dev, u64 mask)
+static int alpha_noop_supported(struct device *dev, u64 mask)
+{
+	return mask < 0x00ffffffUL ? 0 : 1;
+}
+
+static int alpha_noop_set_mask(struct device *dev, u64 mask)
 {
 	if (!dev->dma_mask || !dma_supported(dev, mask))
 		return -EIO;
 
 	*dev->dma_mask = mask;
-
 	return 0;
 }
-EXPORT_SYMBOL(dma_set_mask);
+
+struct dma_map_ops alpha_noop_ops = {
+	.alloc_coherent		= alpha_noop_alloc_coherent,
+	.free_coherent		= alpha_noop_free_coherent,
+	.map_page		= alpha_noop_map_page,
+	.map_sg			= alpha_noop_map_sg,
+	.mapping_error		= alpha_noop_mapping_error,
+	.dma_supported		= alpha_noop_supported,
+	.set_dma_mask		= alpha_noop_set_mask,
+};
+
+struct dma_map_ops *dma_ops = &alpha_noop_ops;
+EXPORT_SYMBOL(dma_ops);
 
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 8449504..ce9e54c 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -216,10 +216,30 @@
 	for (i = 0; i < n; ++i)
 		p[i] = 0;
 }
-
-/* True if the machine supports DAC addressing, and DEV can
-   make use of it given MASK.  */
-static int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask);
+
+/*
+ * True if the machine supports DAC addressing, and DEV can
+ * make use of it given MASK.
+ */
+static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
+{
+	dma64_addr_t dac_offset = alpha_mv.pci_dac_offset;
+	int ok = 1;
+
+	/* If this is not set, the machine doesn't support DAC at all.  */
+	if (dac_offset == 0)
+		ok = 0;
+
+	/* The device has to be able to address our DAC bit.  */
+	if ((dac_offset & dev->dma_mask) != dac_offset)
+		ok = 0;
+
+	/* If both conditions above are met, we are fine. */
+	DBGA("pci_dac_dma_supported %s from %p\n",
+	     ok ? "yes" : "no", __builtin_return_address(0));
+
+	return ok;
+}
 
 /* Map a single buffer of the indicated size for PCI DMA in streaming
    mode.  The 32-bit PCI bus mastering address to use is returned.
@@ -301,23 +321,36 @@
 	return ret;
 }
 
-dma_addr_t
-pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size, int dir)
+/* Helper for generic DMA-mapping functions. */
+static struct pci_dev *alpha_gendev_to_pci(struct device *dev)
 {
-	int dac_allowed; 
+	if (dev && dev->bus == &pci_bus_type)
+		return to_pci_dev(dev);
 
-	if (dir == PCI_DMA_NONE)
-		BUG();
+	/* Assume that non-PCI devices asking for DMA are either ISA or EISA,
+	   BUG() otherwise. */
+	BUG_ON(!isa_bridge);
 
-	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; 
-	return pci_map_single_1(pdev, cpu_addr, size, dac_allowed);
+	/* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA
+	   bridge is bus master then). */
+	if (!dev || !dev->dma_mask || !*dev->dma_mask)
+		return isa_bridge;
+
+	/* For EISA bus masters, return isa_bridge (it might have smaller
+	   dma_mask due to wiring limitations). */
+	if (*dev->dma_mask >= isa_bridge->dma_mask)
+		return isa_bridge;
+
+	/* This assumes ISA bus master with dma_mask 0xffffff. */
+	return NULL;
 }
-EXPORT_SYMBOL(pci_map_single);
 
-dma_addr_t
-pci_map_page(struct pci_dev *pdev, struct page *page, unsigned long offset,
-	     size_t size, int dir)
+static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
+				     unsigned long offset, size_t size,
+				     enum dma_data_direction dir,
+				     struct dma_attrs *attrs)
 {
+	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
 	int dac_allowed;
 
 	if (dir == PCI_DMA_NONE)
@@ -327,7 +360,6 @@
 	return pci_map_single_1(pdev, (char *)page_address(page) + offset, 
 				size, dac_allowed);
 }
-EXPORT_SYMBOL(pci_map_page);
 
 /* Unmap a single streaming mode DMA translation.  The DMA_ADDR and
    SIZE must match what was provided for in a previous pci_map_single
@@ -335,16 +367,17 @@
    the cpu to the buffer are guaranteed to see whatever the device
    wrote there.  */
 
-void
-pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
-		 int direction)
+static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
+				 size_t size, enum dma_data_direction dir,
+				 struct dma_attrs *attrs)
 {
 	unsigned long flags;
+	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
 	struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
 	struct pci_iommu_arena *arena;
 	long dma_ofs, npages;
 
-	if (direction == PCI_DMA_NONE)
+	if (dir == PCI_DMA_NONE)
 		BUG();
 
 	if (dma_addr >= __direct_map_base
@@ -393,25 +426,16 @@
 	DBGA2("pci_unmap_single: sg [%llx,%zx] np %ld from %p\n",
 	      dma_addr, size, npages, __builtin_return_address(0));
 }
-EXPORT_SYMBOL(pci_unmap_single);
-
-void
-pci_unmap_page(struct pci_dev *pdev, dma_addr_t dma_addr,
-	       size_t size, int direction)
-{
-	pci_unmap_single(pdev, dma_addr, size, direction);
-}
-EXPORT_SYMBOL(pci_unmap_page);
 
 /* Allocate and map kernel buffer using consistent mode DMA for PCI
    device.  Returns non-NULL cpu-view pointer to the buffer if
    successful and sets *DMA_ADDRP to the pci side dma address as well,
    else DMA_ADDRP is undefined.  */
 
-void *
-__pci_alloc_consistent(struct pci_dev *pdev, size_t size,
-		       dma_addr_t *dma_addrp, gfp_t gfp)
+static void *alpha_pci_alloc_coherent(struct device *dev, size_t size,
+				      dma_addr_t *dma_addrp, gfp_t gfp)
 {
+	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
 	void *cpu_addr;
 	long order = get_order(size);
 
@@ -439,13 +463,12 @@
 		gfp |= GFP_DMA;
 		goto try_again;
 	}
-		
+
 	DBGA2("pci_alloc_consistent: %zx -> [%p,%llx] from %p\n",
 	      size, cpu_addr, *dma_addrp, __builtin_return_address(0));
 
 	return cpu_addr;
 }
-EXPORT_SYMBOL(__pci_alloc_consistent);
 
 /* Free and unmap a consistent DMA buffer.  CPU_ADDR and DMA_ADDR must
    be values that were returned from pci_alloc_consistent.  SIZE must
@@ -453,17 +476,16 @@
    References to the memory and mappings associated with CPU_ADDR or
    DMA_ADDR past this call are illegal.  */
 
-void
-pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
-		    dma_addr_t dma_addr)
+static void alpha_pci_free_coherent(struct device *dev, size_t size,
+				    void *cpu_addr, dma_addr_t dma_addr)
 {
+	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
 	pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
 	free_pages((unsigned long)cpu_addr, get_order(size));
 
 	DBGA2("pci_free_consistent: [%llx,%zx] from %p\n",
 	      dma_addr, size, __builtin_return_address(0));
 }
-EXPORT_SYMBOL(pci_free_consistent);
 
 /* Classify the elements of the scatterlist.  Write dma_address
    of each element with:
@@ -626,23 +648,21 @@
 	return 1;
 }
 
-int
-pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
-	   int direction)
+static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
+			    int nents, enum dma_data_direction dir,
+			    struct dma_attrs *attrs)
 {
+	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
 	struct scatterlist *start, *end, *out;
 	struct pci_controller *hose;
 	struct pci_iommu_arena *arena;
 	dma_addr_t max_dma;
 	int dac_allowed;
-	struct device *dev;
 
-	if (direction == PCI_DMA_NONE)
+	if (dir == PCI_DMA_NONE)
 		BUG();
 
-	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
-
-	dev = pdev ? &pdev->dev : NULL;
+	dac_allowed = dev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
 
 	/* Fast path single entry scatterlists.  */
 	if (nents == 1) {
@@ -699,19 +719,19 @@
 	/* Some allocation failed while mapping the scatterlist
 	   entries.  Unmap them now.  */
 	if (out > start)
-		pci_unmap_sg(pdev, start, out - start, direction);
+		pci_unmap_sg(pdev, start, out - start, dir);
 	return 0;
 }
-EXPORT_SYMBOL(pci_map_sg);
 
 /* Unmap a set of streaming mode DMA translations.  Again, cpu read
    rules concerning calls here are the same as for pci_unmap_single()
    above.  */
 
-void
-pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
-	     int direction)
+static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg,
+			       int nents, enum dma_data_direction dir,
+			       struct dma_attrs *attrs)
 {
+	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
 	unsigned long flags;
 	struct pci_controller *hose;
 	struct pci_iommu_arena *arena;
@@ -719,7 +739,7 @@
 	dma_addr_t max_dma;
 	dma_addr_t fbeg, fend;
 
-	if (direction == PCI_DMA_NONE)
+	if (dir == PCI_DMA_NONE)
 		BUG();
 
 	if (! alpha_mv.mv_pci_tbi)
@@ -783,15 +803,13 @@
 
 	DBGA("pci_unmap_sg: %ld entries\n", nents - (end - sg));
 }
-EXPORT_SYMBOL(pci_unmap_sg);
-
 
 /* Return whether the given PCI device DMA address mask can be
    supported properly.  */
 
-int
-pci_dma_supported(struct pci_dev *pdev, u64 mask)
+static int alpha_pci_supported(struct device *dev, u64 mask)
 {
+	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
 	struct pci_controller *hose;
 	struct pci_iommu_arena *arena;
 
@@ -818,7 +836,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(pci_dma_supported);
 
 
 /*
@@ -918,66 +935,32 @@
 	return 0;
 }
 
-/* True if the machine supports DAC addressing, and DEV can
-   make use of it given MASK.  */
-
-static int
-pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
+static int alpha_pci_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
-	dma64_addr_t dac_offset = alpha_mv.pci_dac_offset;
-	int ok = 1;
-
-	/* If this is not set, the machine doesn't support DAC at all.  */
-	if (dac_offset == 0)
-		ok = 0;
-
-	/* The device has to be able to address our DAC bit.  */
-	if ((dac_offset & dev->dma_mask) != dac_offset)
-		ok = 0;
-
-	/* If both conditions above are met, we are fine. */
-	DBGA("pci_dac_dma_supported %s from %p\n",
-	     ok ? "yes" : "no", __builtin_return_address(0));
-
-	return ok;
+	return dma_addr == 0;
 }
 
-/* Helper for generic DMA-mapping functions. */
-
-struct pci_dev *
-alpha_gendev_to_pci(struct device *dev)
-{
-	if (dev && dev->bus == &pci_bus_type)
-		return to_pci_dev(dev);
-
-	/* Assume that non-PCI devices asking for DMA are either ISA or EISA,
-	   BUG() otherwise. */
-	BUG_ON(!isa_bridge);
-
-	/* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA
-	   bridge is bus master then). */
-	if (!dev || !dev->dma_mask || !*dev->dma_mask)
-		return isa_bridge;
-
-	/* For EISA bus masters, return isa_bridge (it might have smaller
-	   dma_mask due to wiring limitations). */
-	if (*dev->dma_mask >= isa_bridge->dma_mask)
-		return isa_bridge;
-
-	/* This assumes ISA bus master with dma_mask 0xffffff. */
-	return NULL;
-}
-EXPORT_SYMBOL(alpha_gendev_to_pci);
-
-int
-dma_set_mask(struct device *dev, u64 mask)
+static int alpha_pci_set_mask(struct device *dev, u64 mask)
 {
 	if (!dev->dma_mask ||
 	    !pci_dma_supported(alpha_gendev_to_pci(dev), mask))
 		return -EIO;
 
 	*dev->dma_mask = mask;
-
 	return 0;
 }
-EXPORT_SYMBOL(dma_set_mask);
+
+struct dma_map_ops alpha_pci_ops = {
+	.alloc_coherent		= alpha_pci_alloc_coherent,
+	.free_coherent		= alpha_pci_free_coherent,
+	.map_page		= alpha_pci_map_page,
+	.unmap_page		= alpha_pci_unmap_page,
+	.map_sg			= alpha_pci_map_sg,
+	.unmap_sg		= alpha_pci_unmap_sg,
+	.mapping_error		= alpha_pci_mapping_error,
+	.dma_supported		= alpha_pci_supported,
+	.set_dma_mask		= alpha_pci_set_mask,
+};
+
+struct dma_map_ops *dma_ops = &alpha_pci_ops;
+EXPORT_SYMBOL(dma_ops);
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index e072041d..9acadc6 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -249,6 +249,17 @@
 	return (nsaved != 0);
 }
 
+void user_enable_single_step(struct task_struct *child)
+{
+	/* Mark single stepping.  */
+	task_thread_info(child)->bpt_nsaved = -1;
+}
+
+void user_disable_single_step(struct task_struct *child)
+{
+	ptrace_cancel_bpt(child);
+}
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -256,7 +267,7 @@
  */
 void ptrace_disable(struct task_struct *child)
 { 
-	ptrace_cancel_bpt(child);
+	user_disable_single_step(child);
 }
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
@@ -295,52 +306,6 @@
 		DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
 		ret = put_reg(child, addr, data);
 		break;
-
-	case PTRACE_SYSCALL:
-		/* continue and stop at next (return from) syscall */
-	case PTRACE_CONT:    /* restart after signal. */
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		if (request == PTRACE_SYSCALL)
-			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		else
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->exit_code = data;
-		/* make sure single-step breakpoint is gone. */
-		ptrace_cancel_bpt(child);
-		wake_up_process(child);
-		ret = 0;
-		break;
-
-	/*
-	 * Make the child exit.  Best I can do is send it a sigkill.
-	 * perhaps it should be put in the status that it wants to
-	 * exit.
-	 */
-	case PTRACE_KILL:
-		ret = 0;
-		if (child->exit_state == EXIT_ZOMBIE)
-			break;
-		child->exit_code = SIGKILL;
-		/* make sure single-step breakpoint is gone. */
-		ptrace_cancel_bpt(child);
-		wake_up_process(child);
-		break;
-
-	case PTRACE_SINGLESTEP:  /* execute single instruction. */
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		/* Mark single stepping.  */
-		task_thread_info(child)->bpt_nsaved = -1;
-		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->exit_code = data;
-		wake_up_process(child);
-		/* give it a chance to run. */
-		ret = 0;
-		break;
-
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3b18128..cadfe2e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -155,6 +155,9 @@
 config ZONE_DMA
 	bool
 
+config NEED_DMA_MAP_STATE
+       def_bool y
+
 config GENERIC_ISA_DMA
 	bool
 
@@ -321,10 +324,9 @@
 	bool "Freescale MXC/iMX-based"
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
-	select ARCH_MTD_XIP
-	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	select HAVE_CLK
+	select COMMON_CLKDEV
 	help
 	  Support for Freescale MXC/iMX-based family of processors
 
@@ -508,7 +510,7 @@
 	  Orion-2 (5281), Orion-1-90 (6183).
 
 config ARCH_MMP
-	bool "Marvell PXA168/910"
+	bool "Marvell PXA168/910/MMP2"
 	depends on MMU
 	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
@@ -519,7 +521,7 @@
 	select TICK_ONESHOT
 	select PLAT_PXA
 	help
-	  Support for Marvell's PXA168/910 processor line.
+	  Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
 
 config ARCH_KS8695
 	bool "Micrel/Kendin KS8695"
@@ -605,6 +607,11 @@
 	  interface to the ARM9 modem processor which runs the baseband stack
 	  and controls some vital subsystems (clock and power control, etc).
 
+config ARCH_SHMOBILE
+	bool "Renesas SH-Mobile"
+	help
+	  Support for Renesas's SH-Mobile ARM platforms
+
 config ARCH_RPC
 	bool "RiscPC"
 	select ARCH_ACORN
@@ -648,12 +655,43 @@
 
 config ARCH_S3C64XX
 	bool "Samsung S3C64XX"
+	select PLAT_SAMSUNG
+	select CPU_V6
 	select GENERIC_GPIO
+	select ARM_VIC
 	select HAVE_CLK
+	select NO_IOPORT
 	select ARCH_HAS_CPUFREQ
+	select ARCH_REQUIRE_GPIOLIB
+	select SAMSUNG_CLKSRC
+	select SAMSUNG_IRQ_VIC_TIMER
+	select SAMSUNG_IRQ_UART
+	select S3C_GPIO_TRACK
+	select S3C_GPIO_PULL_UPDOWN
+	select S3C_GPIO_CFG_S3C24XX
+	select S3C_GPIO_CFG_S3C64XX
+	select S3C_DEV_NAND
+	select USB_ARCH_HAS_OHCI
+	select SAMSUNG_GPIOLIB_4BIT
 	help
 	  Samsung S3C64XX series based systems
 
+config ARCH_S5P6440
+	bool "Samsung S5P6440"
+	select CPU_V6
+	select GENERIC_GPIO
+	select HAVE_CLK
+	help
+	  Samsung S5P6440 CPU based systems
+
+config ARCH_S5P6442
+	bool "Samsung S5P6442"
+	select CPU_V6
+	select GENERIC_GPIO
+	select HAVE_CLK
+	help
+	  Samsung S5P6442 CPU based systems
+
 config ARCH_S5PC1XX
 	bool "Samsung S5PC1XX"
 	select GENERIC_GPIO
@@ -663,6 +701,15 @@
 	help
 	  Samsung S5PC1XX series based systems
 
+config ARCH_S5PV210
+	bool "Samsung S5PV210/S5PC110"
+	select CPU_V7
+	select GENERIC_GPIO
+	select HAVE_CLK
+	select ARM_L1_CACHE_SHIFT_6
+	help
+	  Samsung S5PV210/S5PC110 series based systems
+
 config ARCH_SHARK
 	bool "Shark"
 	select CPU_SA110
@@ -828,8 +875,7 @@
 
 source "arch/arm/plat-samsung/Kconfig"
 source "arch/arm/plat-s3c24xx/Kconfig"
-source "arch/arm/plat-s3c64xx/Kconfig"
-source "arch/arm/plat-s3c/Kconfig"
+source "arch/arm/plat-s5p/Kconfig"
 source "arch/arm/plat-s5pc1xx/Kconfig"
 
 if ARCH_S3C2410
@@ -837,21 +883,27 @@
 source "arch/arm/mach-s3c2410/Kconfig"
 source "arch/arm/mach-s3c2412/Kconfig"
 source "arch/arm/mach-s3c2440/Kconfig"
-source "arch/arm/mach-s3c2442/Kconfig"
 source "arch/arm/mach-s3c2443/Kconfig"
 endif
 
 if ARCH_S3C64XX
-source "arch/arm/mach-s3c6400/Kconfig"
-source "arch/arm/mach-s3c6410/Kconfig"
+source "arch/arm/mach-s3c64xx/Kconfig"
 endif
 
-source "arch/arm/plat-stmp3xxx/Kconfig"
+source "arch/arm/mach-s5p6440/Kconfig"
+
+source "arch/arm/mach-s5p6442/Kconfig"
 
 if ARCH_S5PC1XX
 source "arch/arm/mach-s5pc100/Kconfig"
 endif
 
+source "arch/arm/mach-s5pv210/Kconfig"
+
+source "arch/arm/mach-shmobile/Kconfig"
+
+source "arch/arm/plat-stmp3xxx/Kconfig"
+
 source "arch/arm/mach-u300/Kconfig"
 
 source "arch/arm/mach-ux500/Kconfig"
@@ -1117,7 +1169,7 @@
 config HZ
 	int
 	default 128 if ARCH_L7200
-	default 200 if ARCH_EBSA110 || ARCH_S3C2410
+	default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PV210
 	default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
 	default AT91_TIMER_HZ if ARCH_AT91
 	default 100
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 5cb9326..91344af 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -117,7 +117,7 @@
 	  cause the debug messages to appear on the first serial port.
 
 config DEBUG_S3C_UART
-	depends on PLAT_S3C
+	depends on PLAT_SAMSUNG
 	int "S3C UART to use for low-level debug"
 	default "0"
 	help
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 81f54ca..ed820e7 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -146,6 +146,7 @@
 machine-$(CONFIG_ARCH_MX2)		:= mx2
 machine-$(CONFIG_ARCH_MX25)		:= mx25
 machine-$(CONFIG_ARCH_MX3)		:= mx3
+machine-$(CONFIG_ARCH_MX5)		:= mx5
 machine-$(CONFIG_ARCH_MXC91231)		:= mxc91231
 machine-$(CONFIG_ARCH_NETX)		:= netx
 machine-$(CONFIG_ARCH_NOMADIK)		:= nomadik
@@ -159,12 +160,16 @@
 machine-$(CONFIG_ARCH_PXA)		:= pxa
 machine-$(CONFIG_ARCH_REALVIEW)		:= realview
 machine-$(CONFIG_ARCH_RPC)		:= rpc
-machine-$(CONFIG_ARCH_S3C2410)		:= s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443
+machine-$(CONFIG_ARCH_S3C2410)		:= s3c2410 s3c2400 s3c2412 s3c2440 s3c2443
 machine-$(CONFIG_ARCH_S3C24A0)		:= s3c24a0
-machine-$(CONFIG_ARCH_S3C64XX)		:= s3c6400 s3c6410
+machine-$(CONFIG_ARCH_S3C64XX)		:= s3c64xx
+machine-$(CONFIG_ARCH_S5P6440)		:= s5p6440
+machine-$(CONFIG_ARCH_S5P6442)		:= s5p6442
 machine-$(CONFIG_ARCH_S5PC1XX)		:= s5pc100
+machine-$(CONFIG_ARCH_S5PV210)		:= s5pv210
 machine-$(CONFIG_ARCH_SA1100)		:= sa1100
 machine-$(CONFIG_ARCH_SHARK)		:= shark
+machine-$(CONFIG_ARCH_SHMOBILE) 	:= shmobile
 machine-$(CONFIG_ARCH_STMP378X)		:= stmp378x
 machine-$(CONFIG_ARCH_STMP37XX)		:= stmp37xx
 machine-$(CONFIG_ARCH_U300)		:= u300
@@ -178,14 +183,15 @@
 # by CONFIG_* macro name.
 plat-$(CONFIG_ARCH_MXC)		:= mxc
 plat-$(CONFIG_ARCH_OMAP)	:= omap
+plat-$(CONFIG_ARCH_S3C64XX)	:= samsung
 plat-$(CONFIG_ARCH_STMP3XXX)	:= stmp3xxx
 plat-$(CONFIG_PLAT_IOP)		:= iop
 plat-$(CONFIG_PLAT_NOMADIK)	:= nomadik
 plat-$(CONFIG_PLAT_ORION)	:= orion
 plat-$(CONFIG_PLAT_PXA)		:= pxa
-plat-$(CONFIG_PLAT_S3C24XX)	:= s3c24xx s3c samsung
-plat-$(CONFIG_PLAT_S3C64XX)	:= s3c64xx s3c samsung
-plat-$(CONFIG_PLAT_S5PC1XX)	:= s5pc1xx s3c samsung
+plat-$(CONFIG_PLAT_S3C24XX)	:= s3c24xx samsung
+plat-$(CONFIG_PLAT_S5PC1XX)	:= s5pc1xx samsung
+plat-$(CONFIG_PLAT_S5P)		:= s5p samsung
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
diff --git a/arch/arm/boot/bootp/init.S b/arch/arm/boot/bootp/init.S
index df7bc70..8b0de41 100644
--- a/arch/arm/boot/bootp/init.S
+++ b/arch/arm/boot/bootp/init.S
@@ -49,7 +49,7 @@
 /*
  * find the end of the tag list, and then add an INITRD tag on the end.
  * If there is already an INITRD tag, then we ignore it; the last INITRD
- * tag takes precidence.
+ * tag takes precedence.
  */
 taglist:	ldr	r10, [r9, #0]		@ tag length
 		teq	r10, #0			@ last tag (zero length)?
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 99b75aa..535a91d 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -170,8 +170,8 @@
 
 		.text
 		adr	r0, LC0
- ARM(		ldmia	r0, {r1, r2, r3, r4, r5, r6, ip, sp}	)
- THUMB(		ldmia	r0, {r1, r2, r3, r4, r5, r6, ip}	)
+ ARM(		ldmia	r0, {r1, r2, r3, r4, r5, r6, r11, ip, sp})
+ THUMB(		ldmia	r0, {r1, r2, r3, r4, r5, r6, r11, ip}	)
  THUMB(		ldr	sp, [r0, #28]				)
 		subs	r0, r0, r1		@ calculate the delta offset
 
@@ -182,12 +182,13 @@
 		/*
 		 * We're running at a different address.  We need to fix
 		 * up various pointers:
-		 *   r5 - zImage base address
-		 *   r6 - GOT start
+		 *   r5 - zImage base address (_start)
+		 *   r6 - size of decompressed image
+		 *   r11 - GOT start
 		 *   ip - GOT end
 		 */
 		add	r5, r5, r0
-		add	r6, r6, r0
+		add	r11, r11, r0
 		add	ip, ip, r0
 
 #ifndef CONFIG_ZBOOT_ROM
@@ -205,10 +206,10 @@
 		/*
 		 * Relocate all entries in the GOT table.
 		 */
-1:		ldr	r1, [r6, #0]		@ relocate entries in the GOT
+1:		ldr	r1, [r11, #0]		@ relocate entries in the GOT
 		add	r1, r1, r0		@ table.  This fixes up the
-		str	r1, [r6], #4		@ C references.
-		cmp	r6, ip
+		str	r1, [r11], #4		@ C references.
+		cmp	r11, ip
 		blo	1b
 #else
 
@@ -216,12 +217,12 @@
 		 * Relocate entries in the GOT table.  We only relocate
 		 * the entries that are outside the (relocated) BSS region.
 		 */
-1:		ldr	r1, [r6, #0]		@ relocate entries in the GOT
+1:		ldr	r1, [r11, #0]		@ relocate entries in the GOT
 		cmp	r1, r2			@ entry < bss_start ||
 		cmphs	r3, r1			@ _end < entry
 		addlo	r1, r1, r0		@ table.  This fixes up the
-		str	r1, [r6], #4		@ C references.
-		cmp	r6, ip
+		str	r1, [r11], #4		@ C references.
+		cmp	r11, ip
 		blo	1b
 #endif
 
@@ -247,6 +248,7 @@
  * Check to see if we will overwrite ourselves.
  *   r4 = final kernel address
  *   r5 = start of this image
+ *   r6 = size of decompressed image
  *   r2 = end of malloc space (and therefore this image)
  * We basically want:
  *   r4 >= r2 -> OK
@@ -254,8 +256,7 @@
  */
 		cmp	r4, r2
 		bhs	wont_overwrite
-		sub	r3, sp, r5		@ > compressed kernel size
-		add	r0, r4, r3, lsl #2	@ allow for 4x expansion
+		add	r0, r4, r6
 		cmp	r0, r5
 		bls	wont_overwrite
 
@@ -271,7 +272,6 @@
  * r1-r3  = unused
  * r4     = kernel execution address
  * r5     = decompressed kernel start
- * r6     = processor ID
  * r7     = architecture ID
  * r8     = atags pointer
  * r9-r12,r14 = corrupted
@@ -312,7 +312,8 @@
 		.word	_end			@ r3
 		.word	zreladdr		@ r4
 		.word	_start			@ r5
-		.word	_got_start		@ r6
+		.word	_image_size		@ r6
+		.word	_got_start		@ r11
 		.word	_got_end		@ ip
 		.word	user_stack+4096		@ sp
 LC1:		.word	reloc_end - reloc_start
@@ -336,7 +337,6 @@
  *
  * On entry,
  *  r4 = kernel execution address
- *  r6 = processor ID
  *  r7 = architecture number
  *  r8 = atags pointer
  *  r9 = run-time address of "start"  (???)
@@ -542,7 +542,6 @@
  * r1-r3  = unused
  * r4     = kernel execution address
  * r5     = decompressed kernel start
- * r6     = processor ID
  * r7     = architecture ID
  * r8     = atags pointer
  * r9-r12,r14 = corrupted
@@ -581,19 +580,19 @@
  *  r1  = corrupted
  *  r2  = corrupted
  *  r3  = block offset
- *  r6  = corrupted
+ *  r9  = corrupted
  *  r12 = corrupted
  */
 
 call_cache_fn:	adr	r12, proc_types
 #ifdef CONFIG_CPU_CP15
-		mrc	p15, 0, r6, c0, c0	@ get processor ID
+		mrc	p15, 0, r9, c0, c0	@ get processor ID
 #else
-		ldr	r6, =CONFIG_PROCESSOR_ID
+		ldr	r9, =CONFIG_PROCESSOR_ID
 #endif
 1:		ldr	r1, [r12, #0]		@ get value
 		ldr	r2, [r12, #4]		@ get mask
-		eor	r1, r1, r6		@ (real ^ match)
+		eor	r1, r1, r9		@ (real ^ match)
 		tst	r1, r2			@       & mask
  ARM(		addeq	pc, r12, r3		) @ call cache function
  THUMB(		addeq	r12, r3			)
@@ -778,8 +777,7 @@
  * Turn off the Cache and MMU.  ARMv3 does not support
  * reading the control register, but ARMv4 does.
  *
- * On entry,  r6 = processor ID
- * On exit,   r0, r1, r2, r3, r12 corrupted
+ * On exit, r0, r1, r2, r3, r9, r12 corrupted
  * This routine must preserve: r4, r6, r7
  */
 		.align	5
@@ -852,10 +850,8 @@
 /*
  * Clean and flush the cache to maintain consistency.
  *
- * On entry,
- *  r6 = processor ID
  * On exit,
- *  r1, r2, r3, r11, r12 corrupted
+ *  r1, r2, r3, r9, r11, r12 corrupted
  * This routine must preserve:
  *  r0, r4, r5, r6, r7
  */
@@ -967,7 +963,7 @@
 		mov	r2, #64*1024		@ default: 32K dcache size (*2)
 		mov	r11, #32		@ default: 32 byte line size
 		mrc	p15, 0, r3, c0, c0, 1	@ read cache type
-		teq	r3, r6			@ cache ID register present?
+		teq	r3, r9			@ cache ID register present?
 		beq	no_cache_id
 		mov	r1, r3, lsr #18
 		and	r1, r1, #7
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index 7ca9ecf..d081689 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -43,6 +43,9 @@
 
   _etext = .;
 
+  /* Assume size of decompressed image is 4x the compressed image */
+  _image_size = (_etext - _text) * 4;
+
   _got_start = .;
   .got			: { *(.got) }
   _got_end = .;
diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c
index 446b696..6416d5b 100644
--- a/arch/arm/common/clkdev.c
+++ b/arch/arm/common/clkdev.c
@@ -32,7 +32,7 @@
  *  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 precidence: dev+con > dev only > con only.
+ * order of precedence: dev+con > dev only > con only.
  */
 static struct clk *clk_find(const char *dev_id, const char *con_id)
 {
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c
index 2793447..ee1d3b8 100644
--- a/arch/arm/common/it8152.c
+++ b/arch/arm/common/it8152.c
@@ -272,33 +272,6 @@
 		((dma_addr + size - PHYS_OFFSET) >= SZ_64M);
 }
 
-/*
- * We override these so we properly do dmabounce otherwise drivers
- * are able to set the dma_mask to 0xffffffff and we can no longer
- * trap bounces. :(
- *
- * We just return true on everyhing except for < 64MB in which case
- * we will fail miseralby and die since we can't handle that case.
- */
-int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	dev_dbg(&dev->dev, "%s: %llx\n", __func__, mask);
-	if (mask >= PHYS_OFFSET + SZ_64M - 1)
-		return 0;
-
-	return -EIO;
-}
-
-int
-pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	dev_dbg(&dev->dev, "%s: %llx\n", __func__, mask);
-	if (mask >= PHYS_OFFSET + SZ_64M - 1)
-		return 0;
-
-	return -EIO;
-}
-
 int __init it8152_pci_setup(int nr, struct pci_sys_data *sys)
 {
 	it8152_io.start = IT8152_IO_BASE + 0x12000;
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index bd36c77..90ae00b 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -32,6 +32,12 @@
 
 #include <asm/hardware/locomo.h>
 
+/* LoCoMo Interrupts */
+#define IRQ_LOCOMO_KEY		(0)
+#define IRQ_LOCOMO_GPIO		(1)
+#define IRQ_LOCOMO_LT		(2)
+#define IRQ_LOCOMO_SPI		(3)
+
 /* M62332 output channel selection */
 #define M62332_EVR_CH	1	/* M62332 volume channel number  */
 				/*   0 : CH.1 , 1 : CH. 2        */
@@ -58,6 +64,7 @@
 	struct device *dev;
 	unsigned long phys;
 	unsigned int irq;
+	int irq_base;
 	spinlock_t lock;
 	void __iomem *base;
 #ifdef CONFIG_PM
@@ -81,9 +88,7 @@
 static struct locomo_dev_info locomo_devices[] = {
 	{
 		.devid 		= LOCOMO_DEVID_KEYBOARD,
-		.irq = {
-			IRQ_LOCOMO_KEY,
-		},
+		.irq		= { IRQ_LOCOMO_KEY },
 		.name		= "locomo-keyboard",
 		.offset		= LOCOMO_KEYBOARD,
 		.length		= 16,
@@ -133,53 +138,20 @@
 	},
 };
 
-
-/** LoCoMo interrupt handling stuff.
- * NOTE: LoCoMo has a 1 to many mapping on all of its IRQs.
- * that is, there is only one real hardware interrupt
- * we determine which interrupt it is by reading some IO memory.
- * We have two levels of expansion, first in the handler for the
- * hardware interrupt we generate an interrupt
- * IRQ_LOCOMO_*_BASE and those handlers generate more interrupts
- *
- * hardware irq reads LOCOMO_ICR & 0x0f00
- *   IRQ_LOCOMO_KEY_BASE
- *   IRQ_LOCOMO_GPIO_BASE
- *   IRQ_LOCOMO_LT_BASE
- *   IRQ_LOCOMO_SPI_BASE
- * IRQ_LOCOMO_KEY_BASE reads LOCOMO_KIC & 0x0001
- *   IRQ_LOCOMO_KEY
- * IRQ_LOCOMO_GPIO_BASE reads LOCOMO_GIR & LOCOMO_GPD & 0xffff
- *   IRQ_LOCOMO_GPIO[0-15]
- * IRQ_LOCOMO_LT_BASE reads LOCOMO_LTINT & 0x0001
- *   IRQ_LOCOMO_LT
- * IRQ_LOCOMO_SPI_BASE reads LOCOMO_SPIIR & 0x000F
- *   IRQ_LOCOMO_SPI_RFR
- *   IRQ_LOCOMO_SPI_RFW
- *   IRQ_LOCOMO_SPI_OVRN
- *   IRQ_LOCOMO_SPI_TEND
- */
-
-#define LOCOMO_IRQ_START	(IRQ_LOCOMO_KEY_BASE)
-#define LOCOMO_IRQ_KEY_START	(IRQ_LOCOMO_KEY)
-#define	LOCOMO_IRQ_GPIO_START	(IRQ_LOCOMO_GPIO0)
-#define	LOCOMO_IRQ_LT_START	(IRQ_LOCOMO_LT)
-#define	LOCOMO_IRQ_SPI_START	(IRQ_LOCOMO_SPI_RFR)
-
 static void locomo_handler(unsigned int irq, struct irq_desc *desc)
 {
+	struct locomo *lchip = get_irq_chip_data(irq);
 	int req, i;
-	void __iomem *mapbase = get_irq_chip_data(irq);
 
 	/* Acknowledge the parent IRQ */
 	desc->chip->ack(irq);
 
 	/* check why this interrupt was generated */
-	req = locomo_readl(mapbase + LOCOMO_ICR) & 0x0f00;
+	req = locomo_readl(lchip->base + LOCOMO_ICR) & 0x0f00;
 
 	if (req) {
 		/* generate the next interrupt(s) */
-		irq = LOCOMO_IRQ_START;
+		irq = lchip->irq_base;
 		for (i = 0; i <= 3; i++, irq++) {
 			if (req & (0x0100 << i)) {
 				generic_handle_irq(irq);
@@ -195,20 +167,20 @@
 
 static void locomo_mask_irq(unsigned int irq)
 {
-	void __iomem *mapbase = get_irq_chip_data(irq);
+	struct locomo *lchip = get_irq_chip_data(irq);
 	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_ICR);
-	r &= ~(0x0010 << (irq - LOCOMO_IRQ_START));
-	locomo_writel(r, mapbase + LOCOMO_ICR);
+	r = locomo_readl(lchip->base + LOCOMO_ICR);
+	r &= ~(0x0010 << (irq - lchip->irq_base));
+	locomo_writel(r, lchip->base + LOCOMO_ICR);
 }
 
 static void locomo_unmask_irq(unsigned int irq)
 {
-	void __iomem *mapbase = get_irq_chip_data(irq);
+	struct locomo *lchip = get_irq_chip_data(irq);
 	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_ICR);
-	r |= (0x0010 << (irq - LOCOMO_IRQ_START));
-	locomo_writel(r, mapbase + LOCOMO_ICR);
+	r = locomo_readl(lchip->base + LOCOMO_ICR);
+	r |= (0x0010 << (irq - lchip->irq_base));
+	locomo_writel(r, lchip->base + LOCOMO_ICR);
 }
 
 static struct irq_chip locomo_chip = {
@@ -218,297 +190,22 @@
 	.unmask	= locomo_unmask_irq,
 };
 
-static void locomo_key_handler(unsigned int irq, struct irq_desc *desc)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-
-	if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
-		generic_handle_irq(LOCOMO_IRQ_KEY_START);
-	}
-}
-
-static void locomo_key_ack_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
-	r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START));
-	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
-}
-
-static void locomo_key_mask_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
-	r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START));
-	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
-}
-
-static void locomo_key_unmask_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
-	r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START));
-	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
-}
-
-static struct irq_chip locomo_key_chip = {
-	.name	= "LOCOMO-key",
-	.ack	= locomo_key_ack_irq,
-	.mask	= locomo_key_mask_irq,
-	.unmask	= locomo_key_unmask_irq,
-};
-
-static void locomo_gpio_handler(unsigned int irq, struct irq_desc *desc)
-{
-	int req, i;
-	void __iomem *mapbase = get_irq_chip_data(irq);
-
-	req = 	locomo_readl(mapbase + LOCOMO_GIR) &
-		locomo_readl(mapbase + LOCOMO_GPD) &
-		0xffff;
-
-	if (req) {
-		irq = LOCOMO_IRQ_GPIO_START;
-		for (i = 0; i <= 15; i++, irq++) {
-			if (req & (0x0001 << i)) {
-				generic_handle_irq(irq);
-			}
-		}
-	}
-}
-
-static void locomo_gpio_ack_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_GWE);
-	r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
-	locomo_writel(r, mapbase + LOCOMO_GWE);
-
-	r = locomo_readl(mapbase + LOCOMO_GIS);
-	r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
-	locomo_writel(r, mapbase + LOCOMO_GIS);
-
-	r = locomo_readl(mapbase + LOCOMO_GWE);
-	r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
-	locomo_writel(r, mapbase + LOCOMO_GWE);
-}
-
-static void locomo_gpio_mask_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_GIE);
-	r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
-	locomo_writel(r, mapbase + LOCOMO_GIE);
-}
-
-static void locomo_gpio_unmask_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_GIE);
-	r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START));
-	locomo_writel(r, mapbase + LOCOMO_GIE);
-}
-
-static int GPIO_IRQ_rising_edge;
-static int GPIO_IRQ_falling_edge;
-
-static int locomo_gpio_type(unsigned int irq, unsigned int type)
-{
-	unsigned int mask;
-	void __iomem *mapbase = get_irq_chip_data(irq);
-
-	mask = 1 << (irq - LOCOMO_IRQ_GPIO_START);
-
-	if (type == IRQ_TYPE_PROBE) {
-		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
-			return 0;
-		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
-	}
-
-	if (type & IRQ_TYPE_EDGE_RISING)
-		GPIO_IRQ_rising_edge |= mask;
-	else
-		GPIO_IRQ_rising_edge &= ~mask;
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		GPIO_IRQ_falling_edge |= mask;
-	else
-		GPIO_IRQ_falling_edge &= ~mask;
-	locomo_writel(GPIO_IRQ_rising_edge, mapbase + LOCOMO_GRIE);
-	locomo_writel(GPIO_IRQ_falling_edge, mapbase + LOCOMO_GFIE);
-
-	return 0;
-}
-
-static struct irq_chip locomo_gpio_chip = {
-	.name	  = "LOCOMO-gpio",
-	.ack	  = locomo_gpio_ack_irq,
-	.mask	  = locomo_gpio_mask_irq,
-	.unmask	  = locomo_gpio_unmask_irq,
-	.set_type = locomo_gpio_type,
-};
-
-static void locomo_lt_handler(unsigned int irq, struct irq_desc *desc)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-
-	if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
-		generic_handle_irq(LOCOMO_IRQ_LT_START);
-	}
-}
-
-static void locomo_lt_ack_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_LTINT);
-	r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START));
-	locomo_writel(r, mapbase + LOCOMO_LTINT);
-}
-
-static void locomo_lt_mask_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_LTINT);
-	r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START));
-	locomo_writel(r, mapbase + LOCOMO_LTINT);
-}
-
-static void locomo_lt_unmask_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_LTINT);
-	r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START));
-	locomo_writel(r, mapbase + LOCOMO_LTINT);
-}
-
-static struct irq_chip locomo_lt_chip = {
-	.name	= "LOCOMO-lt",
-	.ack	= locomo_lt_ack_irq,
-	.mask	= locomo_lt_mask_irq,
-	.unmask	= locomo_lt_unmask_irq,
-};
-
-static void locomo_spi_handler(unsigned int irq, struct irq_desc *desc)
-{
-	int req, i;
-	void __iomem *mapbase = get_irq_chip_data(irq);
-
-	req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F;
-	if (req) {
-		irq = LOCOMO_IRQ_SPI_START;
-
-		for (i = 0; i <= 3; i++, irq++) {
-			if (req & (0x0001 << i)) {
-				generic_handle_irq(irq);
-			}
-		}
-	}
-}
-
-static void locomo_spi_ack_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
-	r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
-
-	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIS);
-	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIS);
-
-	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
-	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE);
-}
-
-static void locomo_spi_mask_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
-	r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
-}
-
-static void locomo_spi_unmask_irq(unsigned int irq)
-{
-	void __iomem *mapbase = get_irq_chip_data(irq);
-	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
-	r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START));
-	locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE);
-}
-
-static struct irq_chip locomo_spi_chip = {
-	.name	= "LOCOMO-spi",
-	.ack	= locomo_spi_ack_irq,
-	.mask	= locomo_spi_mask_irq,
-	.unmask	= locomo_spi_unmask_irq,
-};
-
 static void locomo_setup_irq(struct locomo *lchip)
 {
-	int irq;
-	void __iomem *irqbase = lchip->base;
+	int irq = lchip->irq_base;
 
 	/*
 	 * Install handler for IRQ_LOCOMO_HW.
 	 */
 	set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING);
-	set_irq_chip_data(lchip->irq, irqbase);
+	set_irq_chip_data(lchip->irq, lchip);
 	set_irq_chained_handler(lchip->irq, locomo_handler);
 
-	/* Install handlers for IRQ_LOCOMO_*_BASE */
-	set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip);
-	set_irq_chip_data(IRQ_LOCOMO_KEY_BASE, irqbase);
-	set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler);
-
-	set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip);
-	set_irq_chip_data(IRQ_LOCOMO_GPIO_BASE, irqbase);
-	set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler);
-
-	set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip);
-	set_irq_chip_data(IRQ_LOCOMO_LT_BASE, irqbase);
-	set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler);
-
-	set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip);
-	set_irq_chip_data(IRQ_LOCOMO_SPI_BASE, irqbase);
-	set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler);
-
-	/* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */
-	set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip);
-	set_irq_chip_data(LOCOMO_IRQ_KEY_START, irqbase);
-	set_irq_handler(LOCOMO_IRQ_KEY_START, handle_edge_irq);
-	set_irq_flags(LOCOMO_IRQ_KEY_START, IRQF_VALID | IRQF_PROBE);
-
-	/* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */
-	for (irq = LOCOMO_IRQ_GPIO_START; irq < LOCOMO_IRQ_GPIO_START + 16; irq++) {
-		set_irq_chip(irq, &locomo_gpio_chip);
-		set_irq_chip_data(irq, irqbase);
-		set_irq_handler(irq, handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
-
-	/* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */
-	set_irq_chip(LOCOMO_IRQ_LT_START, &locomo_lt_chip);
-	set_irq_chip_data(LOCOMO_IRQ_LT_START, irqbase);
-	set_irq_handler(LOCOMO_IRQ_LT_START, handle_edge_irq);
-	set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE);
-
-	/* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */
-	for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 4; irq++) {
-		set_irq_chip(irq, &locomo_spi_chip);
-		set_irq_chip_data(irq, irqbase);
-		set_irq_handler(irq, handle_edge_irq);
+	/* Install handlers for IRQ_LOCOMO_* */
+	for ( ; irq <= lchip->irq_base + 3; irq++) {
+		set_irq_chip(irq, &locomo_chip);
+		set_irq_chip_data(irq, lchip);
+		set_irq_handler(irq, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 }
@@ -555,7 +252,8 @@
 		dev->mapbase = 0;
 	dev->length = info->length;
 
-	memmove(dev->irq, info->irq, sizeof(dev->irq));
+	dev->irq[0] = (lchip->irq_base == NO_IRQ) ?
+			NO_IRQ : lchip->irq_base + info->irq[0];
 
 	ret = device_register(&dev->dev);
 	if (ret) {
@@ -672,6 +370,7 @@
 static int
 __locomo_probe(struct device *me, struct resource *mem, int irq)
 {
+	struct locomo_platform_data *pdata = me->platform_data;
 	struct locomo *lchip;
 	unsigned long r;
 	int i, ret = -ENODEV;
@@ -687,6 +386,7 @@
 
 	lchip->phys = mem->start;
 	lchip->irq = irq;
+	lchip->irq_base = (pdata) ? pdata->irq_base : NO_IRQ;
 
 	/*
 	 * Map the whole region.  This also maps the
@@ -753,7 +453,7 @@
 	 * The interrupt controller must be initialised before any
 	 * other device to ensure that the interrupts are available.
 	 */
-	if (lchip->irq != NO_IRQ)
+	if (lchip->irq != NO_IRQ && lchip->irq_base != NO_IRQ)
 		locomo_setup_irq(lchip);
 
 	for (i = 0; i < ARRAY_SIZE(locomo_devices); i++)
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 8ba7044..a52a27c 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -35,6 +35,58 @@
 
 #include <asm/hardware/sa1111.h>
 
+/* SA1111 IRQs */
+#define IRQ_GPAIN0		(0)
+#define IRQ_GPAIN1		(1)
+#define IRQ_GPAIN2		(2)
+#define IRQ_GPAIN3		(3)
+#define IRQ_GPBIN0		(4)
+#define IRQ_GPBIN1		(5)
+#define IRQ_GPBIN2		(6)
+#define IRQ_GPBIN3		(7)
+#define IRQ_GPBIN4		(8)
+#define IRQ_GPBIN5		(9)
+#define IRQ_GPCIN0		(10)
+#define IRQ_GPCIN1		(11)
+#define IRQ_GPCIN2		(12)
+#define IRQ_GPCIN3		(13)
+#define IRQ_GPCIN4		(14)
+#define IRQ_GPCIN5		(15)
+#define IRQ_GPCIN6		(16)
+#define IRQ_GPCIN7		(17)
+#define IRQ_MSTXINT		(18)
+#define IRQ_MSRXINT		(19)
+#define IRQ_MSSTOPERRINT	(20)
+#define IRQ_TPTXINT		(21)
+#define IRQ_TPRXINT		(22)
+#define IRQ_TPSTOPERRINT	(23)
+#define SSPXMTINT		(24)
+#define SSPRCVINT		(25)
+#define SSPROR			(26)
+#define AUDXMTDMADONEA		(32)
+#define AUDRCVDMADONEA		(33)
+#define AUDXMTDMADONEB		(34)
+#define AUDRCVDMADONEB		(35)
+#define AUDTFSR			(36)
+#define AUDRFSR			(37)
+#define AUDTUR			(38)
+#define AUDROR			(39)
+#define AUDDTS			(40)
+#define AUDRDD			(41)
+#define AUDSTO			(42)
+#define IRQ_USBPWR		(43)
+#define IRQ_HCIM		(44)
+#define IRQ_HCIBUFFACC		(45)
+#define IRQ_HCIRMTWKP		(46)
+#define IRQ_NHCIMFCIR		(47)
+#define IRQ_USB_PORT_RESUME	(48)
+#define IRQ_S0_READY_NINT	(49)
+#define IRQ_S1_READY_NINT	(50)
+#define IRQ_S0_CD_VALID		(51)
+#define IRQ_S1_CD_VALID		(52)
+#define IRQ_S0_BVD1_STSCHG	(53)
+#define IRQ_S1_BVD1_STSCHG	(54)
+
 extern void __init sa1110_mb_enable(void);
 
 /*
@@ -49,6 +101,7 @@
 	struct clk	*clk;
 	unsigned long	phys;
 	int		irq;
+	int		irq_base;	/* base for cascaded on-chip IRQs */
 	spinlock_t	lock;
 	void __iomem	*base;
 #ifdef CONFIG_PM
@@ -152,36 +205,37 @@
 sa1111_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned int stat0, stat1, i;
-	void __iomem *base = get_irq_data(irq);
+	struct sa1111 *sachip = get_irq_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 
-	stat0 = sa1111_readl(base + SA1111_INTSTATCLR0);
-	stat1 = sa1111_readl(base + SA1111_INTSTATCLR1);
+	stat0 = sa1111_readl(mapbase + SA1111_INTSTATCLR0);
+	stat1 = sa1111_readl(mapbase + SA1111_INTSTATCLR1);
 
-	sa1111_writel(stat0, base + SA1111_INTSTATCLR0);
+	sa1111_writel(stat0, mapbase + SA1111_INTSTATCLR0);
 
 	desc->chip->ack(irq);
 
-	sa1111_writel(stat1, base + SA1111_INTSTATCLR1);
+	sa1111_writel(stat1, mapbase + SA1111_INTSTATCLR1);
 
 	if (stat0 == 0 && stat1 == 0) {
 		do_bad_IRQ(irq, desc);
 		return;
 	}
 
-	for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1)
+	for (i = 0; stat0; i++, stat0 >>= 1)
 		if (stat0 & 1)
-			handle_edge_irq(i, irq_desc + i);
+			generic_handle_irq(i + sachip->irq_base);
 
-	for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1)
+	for (i = 32; stat1; i++, stat1 >>= 1)
 		if (stat1 & 1)
-			handle_edge_irq(i, irq_desc + i);
+			generic_handle_irq(i + sachip->irq_base);
 
 	/* For level-based interrupts */
 	desc->chip->unmask(irq);
 }
 
-#define SA1111_IRQMASK_LO(x)	(1 << (x - IRQ_SA1111_START))
-#define SA1111_IRQMASK_HI(x)	(1 << (x - IRQ_SA1111_START - 32))
+#define SA1111_IRQMASK_LO(x)	(1 << (x - sachip->irq_base))
+#define SA1111_IRQMASK_HI(x)	(1 << (x - sachip->irq_base - 32))
 
 static void sa1111_ack_irq(unsigned int irq)
 {
@@ -189,7 +243,8 @@
 
 static void sa1111_mask_lowirq(unsigned int irq)
 {
-	void __iomem *mapbase = get_irq_chip_data(irq);
+	struct sa1111 *sachip = get_irq_chip_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned long ie0;
 
 	ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
@@ -199,7 +254,8 @@
 
 static void sa1111_unmask_lowirq(unsigned int irq)
 {
-	void __iomem *mapbase = get_irq_chip_data(irq);
+	struct sa1111 *sachip = get_irq_chip_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned long ie0;
 
 	ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
@@ -216,8 +272,9 @@
  */
 static int sa1111_retrigger_lowirq(unsigned int irq)
 {
+	struct sa1111 *sachip = get_irq_chip_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned int mask = SA1111_IRQMASK_LO(irq);
-	void __iomem *mapbase = get_irq_chip_data(irq);
 	unsigned long ip0;
 	int i;
 
@@ -237,8 +294,9 @@
 
 static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
 {
+	struct sa1111 *sachip = get_irq_chip_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned int mask = SA1111_IRQMASK_LO(irq);
-	void __iomem *mapbase = get_irq_chip_data(irq);
 	unsigned long ip0;
 
 	if (flags == IRQ_TYPE_PROBE)
@@ -260,8 +318,9 @@
 
 static int sa1111_wake_lowirq(unsigned int irq, unsigned int on)
 {
+	struct sa1111 *sachip = get_irq_chip_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned int mask = SA1111_IRQMASK_LO(irq);
-	void __iomem *mapbase = get_irq_chip_data(irq);
 	unsigned long we0;
 
 	we0 = sa1111_readl(mapbase + SA1111_WAKEEN0);
@@ -286,7 +345,8 @@
 
 static void sa1111_mask_highirq(unsigned int irq)
 {
-	void __iomem *mapbase = get_irq_chip_data(irq);
+	struct sa1111 *sachip = get_irq_chip_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned long ie1;
 
 	ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
@@ -296,7 +356,8 @@
 
 static void sa1111_unmask_highirq(unsigned int irq)
 {
-	void __iomem *mapbase = get_irq_chip_data(irq);
+	struct sa1111 *sachip = get_irq_chip_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned long ie1;
 
 	ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
@@ -313,8 +374,9 @@
  */
 static int sa1111_retrigger_highirq(unsigned int irq)
 {
+	struct sa1111 *sachip = get_irq_chip_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned int mask = SA1111_IRQMASK_HI(irq);
-	void __iomem *mapbase = get_irq_chip_data(irq);
 	unsigned long ip1;
 	int i;
 
@@ -334,8 +396,9 @@
 
 static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
 {
+	struct sa1111 *sachip = get_irq_chip_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned int mask = SA1111_IRQMASK_HI(irq);
-	void __iomem *mapbase = get_irq_chip_data(irq);
 	unsigned long ip1;
 
 	if (flags == IRQ_TYPE_PROBE)
@@ -357,8 +420,9 @@
 
 static int sa1111_wake_highirq(unsigned int irq, unsigned int on)
 {
+	struct sa1111 *sachip = get_irq_chip_data(irq);
+	void __iomem *mapbase = sachip->base + SA1111_INTC;
 	unsigned int mask = SA1111_IRQMASK_HI(irq);
-	void __iomem *mapbase = get_irq_chip_data(irq);
 	unsigned long we1;
 
 	we1 = sa1111_readl(mapbase + SA1111_WAKEEN1);
@@ -412,14 +476,14 @@
 
 	for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
 		set_irq_chip(irq, &sa1111_low_chip);
-		set_irq_chip_data(irq, irqbase);
+		set_irq_chip_data(irq, sachip);
 		set_irq_handler(irq, handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) {
 		set_irq_chip(irq, &sa1111_high_chip);
-		set_irq_chip_data(irq, irqbase);
+		set_irq_chip_data(irq, sachip);
 		set_irq_handler(irq, handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
@@ -428,7 +492,7 @@
 	 * Register SA1111 interrupt
 	 */
 	set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
-	set_irq_data(sachip->irq, irqbase);
+	set_irq_data(sachip->irq, sachip);
 	set_irq_chained_handler(sachip->irq, sa1111_irq_handler);
 }
 
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 37bda5f..9012004 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -140,6 +140,7 @@
 EXPORT_SYMBOL(read_scoop_reg);
 EXPORT_SYMBOL(write_scoop_reg);
 
+#ifdef CONFIG_PM
 static void check_scoop_reg(struct scoop_dev *sdev)
 {
 	unsigned short mcr;
@@ -149,7 +150,6 @@
 		iowrite16(0x0101, sdev->base + SCOOP_MCR);
 }
 
-#ifdef CONFIG_PM
 static int scoop_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct scoop_dev *sdev = platform_get_drvdata(dev);
diff --git a/arch/arm/configs/ap4evb_defconfig b/arch/arm/configs/ap4evb_defconfig
new file mode 100644
index 0000000..e14229b
--- /dev/null
+++ b/arch/arm/configs/ap4evb_defconfig
@@ -0,0 +1,779 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc7
+# Mon Feb  8 12:25:36 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+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_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+
+#
+# SH-Mobile System Type
+#
+# CONFIG_ARCH_SH7367 is not set
+# CONFIG_ARCH_SH7377 is not set
+CONFIG_ARCH_SH7372=y
+
+#
+# SH-Mobile Board Type
+#
+CONFIG_MACH_AP4EVB=y
+
+#
+# SH-Mobile System Configuration
+#
+
+#
+# Memory configuration
+#
+CONFIG_MEMORY_START=0x40000000
+CONFIG_MEMORY_SIZE=0x10000000
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TIMER_CMT=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=sh-sci.0,115200"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_APM_EMULATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=8
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_FSNOTIFY is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/g3evm_defconfig b/arch/arm/configs/g3evm_defconfig
new file mode 100644
index 0000000..3c19031
--- /dev/null
+++ b/arch/arm/configs/g3evm_defconfig
@@ -0,0 +1,774 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc7
+# Mon Feb  8 12:20:01 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+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_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+
+#
+# SH-Mobile System Type
+#
+CONFIG_ARCH_SH7367=y
+# CONFIG_ARCH_SH7377 is not set
+# CONFIG_ARCH_SH7372 is not set
+
+#
+# SH-Mobile Board Type
+#
+CONFIG_MACH_G3EVM=y
+
+#
+# SH-Mobile System Configuration
+#
+
+#
+# Memory configuration
+#
+CONFIG_MEMORY_START=0x50000000
+CONFIG_MEMORY_SIZE=0x08000000
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TIMER_CMT=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+# CONFIG_CPU_32v6K is not set
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+# CONFIG_ARM_ERRATA_411920 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySC1,115200 earlyprintk=sh-sci.1,115200"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_APM_EMULATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=8
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_FSNOTIFY is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/g4evm_defconfig b/arch/arm/configs/g4evm_defconfig
new file mode 100644
index 0000000..8ee79a5
--- /dev/null
+++ b/arch/arm/configs/g4evm_defconfig
@@ -0,0 +1,779 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc7
+# Mon Feb  8 12:21:35 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+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_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+CONFIG_ARCH_SHMOBILE=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+
+#
+# SH-Mobile System Type
+#
+# CONFIG_ARCH_SH7367 is not set
+CONFIG_ARCH_SH7377=y
+# CONFIG_ARCH_SH7372 is not set
+
+#
+# SH-Mobile Board Type
+#
+CONFIG_MACH_G4EVM=y
+
+#
+# SH-Mobile System Configuration
+#
+
+#
+# Memory configuration
+#
+CONFIG_MEMORY_START=0x40000000
+CONFIG_MEMORY_SIZE=0x08000000
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TIMER_CMT=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySC4,115200 earlyprintk=sh-sci.4,115200"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_APM_EMULATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=8
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_FSNOTIFY is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
new file mode 100644
index 0000000..95d2bec
--- /dev/null
+++ b/arch/arm/configs/imote2_defconfig
@@ -0,0 +1,2077 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc8
+# Sat Feb 13 21:48:53 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+# CONFIG_RD_LZO is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_SLOW_WORK=y
+# CONFIG_SLOW_WORK_DEBUG is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+
+#
+# Intel PXA2xx/PXA3xx Implementations
+#
+
+#
+# Intel/Marvell Dev Platforms (sorted by hardware release time)
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_MACH_ZYLONITE300 is not set
+# CONFIG_MACH_ZYLONITE320 is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_TAVOREVB is not set
+# CONFIG_MACH_SAAR is not set
+
+#
+# Third Party Dev Platforms (sorted by vendor name)
+#
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_ARCH_VIPER is not set
+# CONFIG_MACH_ARCOM_ZEUS is not set
+# CONFIG_MACH_BALLOON3 is not set
+# CONFIG_MACH_CSB726 is not set
+# CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_EXEDA is not set
+# CONFIG_MACH_CM_X300 is not set
+# CONFIG_ARCH_GUMSTIX is not set
+CONFIG_MACH_INTELMOTE2=y
+# CONFIG_MACH_STARGATE2 is not set
+# CONFIG_MACH_XCEP is not set
+# CONFIG_TRIZEPS_PXA is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_PCM027 is not set
+# CONFIG_MACH_COLIBRI is not set
+# CONFIG_MACH_COLIBRI300 is not set
+# CONFIG_MACH_COLIBRI320 is not set
+
+#
+# End-user Products (sorted by vendor name)
+#
+# CONFIG_MACH_H4700 is not set
+# CONFIG_MACH_H5000 is not set
+# CONFIG_MACH_HIMALAYA is not set
+# CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_MIOA701 is not set
+# CONFIG_PXA_EZX is not set
+# CONFIG_MACH_MP900C is not set
+# CONFIG_ARCH_PXA_PALM is not set
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_ARCH_PXA_ESERIES is not set
+CONFIG_PXA27x=y
+CONFIG_PXA_SSP=y
+CONFIG_PXA_HAVE_BOARD_IRQS=y
+CONFIG_PLAT_PXA=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_IWMMXT=y
+CONFIG_XSCALE_PMU=y
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty1 root=/dev/mmcblk0p2 rootfstype=ext2 rootdelay=3 ip=192.168.0.202:192.168.0.200:192.168.0.200:255.255.255.0 debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_APM_EMULATION=y
+CONFIG_PM_RUNTIME=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# 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_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_DCCP is not set
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+CONFIG_IEEE802154=y
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+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_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+# CONFIG_BT_HCIUART_BCSP is not set
+# CONFIG_BT_HCIUART_LL is not set
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+# CONFIG_BT_ATH3K is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_HAVE_MTD_OTP=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+# CONFIG_MTD_CFI_I2 is not set
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_OTP=y
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PXA2XX=y
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_IEEE802154_DRIVERS=y
+# CONFIG_IEEE802154_FAKEHARD is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_APMPOWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+CONFIG_KEYBOARD_PXA27x=y
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+CONFIG_TOUCHSCREEN_DA9034=y
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=8
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_PXA2XX=y
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_APM_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_DA9030 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+CONFIG_PMIC_DA903X=y
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13783 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_88PM8607 is not set
+# CONFIG_AB4500_CORE is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DEBUG=y
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+CONFIG_REGULATOR_DA903X=y
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+CONFIG_IR_CORE=y
+CONFIG_VIDEO_IR=y
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+CONFIG_MEDIA_TUNER_CUSTOMISE=y
+# CONFIG_MEDIA_TUNER_SIMPLE is not set
+# CONFIG_MEDIA_TUNER_TDA8290 is not set
+# CONFIG_MEDIA_TUNER_TDA827X is not set
+# CONFIG_MEDIA_TUNER_TDA18271 is not set
+# CONFIG_MEDIA_TUNER_TDA9887 is not set
+# CONFIG_MEDIA_TUNER_TEA5761 is not set
+# CONFIG_MEDIA_TUNER_TEA5767 is not set
+# CONFIG_MEDIA_TUNER_MT20XX is not set
+# CONFIG_MEDIA_TUNER_MT2060 is not set
+# CONFIG_MEDIA_TUNER_MT2266 is not set
+# CONFIG_MEDIA_TUNER_MT2131 is not set
+# CONFIG_MEDIA_TUNER_QT1010 is not set
+# CONFIG_MEDIA_TUNER_XC2028 is not set
+# CONFIG_MEDIA_TUNER_XC5000 is not set
+# CONFIG_MEDIA_TUNER_MXL5005S is not set
+# CONFIG_MEDIA_TUNER_MXL5007T is not set
+# CONFIG_MEDIA_TUNER_MC44S803 is not set
+CONFIG_MEDIA_TUNER_MAX2165=m
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_SG=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+CONFIG_VIDEO_IR_I2C=y
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TDA9875 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS5345 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_M52790 is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_VP27SMPX is not set
+
+#
+# RDS decoders
+#
+# CONFIG_VIDEO_SAA6588 is not set
+
+#
+# Video decoders
+#
+# CONFIG_VIDEO_ADV7180 is not set
+# CONFIG_VIDEO_BT819 is not set
+# CONFIG_VIDEO_BT856 is not set
+# CONFIG_VIDEO_BT866 is not set
+# CONFIG_VIDEO_KS0127 is not set
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_MT9V011 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_SAA7110 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_SAA7191 is not set
+# CONFIG_VIDEO_TVP514X is not set
+# CONFIG_VIDEO_TVP5150 is not set
+# CONFIG_VIDEO_VPX3220 is not set
+
+#
+# Video and audio decoders
+#
+# CONFIG_VIDEO_CX25840 is not set
+
+#
+# MPEG video encoders
+#
+# CONFIG_VIDEO_CX2341X is not set
+
+#
+# Video encoders
+#
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_SAA7185 is not set
+# CONFIG_VIDEO_ADV7170 is not set
+# CONFIG_VIDEO_ADV7175 is not set
+# CONFIG_VIDEO_THS7303 is not set
+# CONFIG_VIDEO_ADV7343 is not set
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+CONFIG_SOC_CAMERA=y
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+CONFIG_SOC_CAMERA_MT9M111=y
+# CONFIG_SOC_CAMERA_MT9T031 is not set
+# CONFIG_SOC_CAMERA_MT9T112 is not set
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_RJ54N1 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+# CONFIG_SOC_CAMERA_PLATFORM is not set
+# CONFIG_SOC_CAMERA_OV772X is not set
+# CONFIG_SOC_CAMERA_OV9640 is not set
+CONFIG_VIDEO_PXA27x=y
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
+# CONFIG_V4L_USB_DRIVERS is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_I2C_SI4713 is not set
+# CONFIG_RADIO_SI4713 is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_RADIO_SI470X is not set
+# CONFIG_USB_MR800 is not set
+CONFIG_RADIO_TEA5764=y
+CONFIG_RADIO_TEA5764_XTAL=y
+# CONFIG_RADIO_TEF6862 is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+CONFIG_FB_PXA_OVERLAY=y
+# CONFIG_FB_PXA_SMARTPANEL is not set
+CONFIG_FB_PXA_PARAMETERS=y
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_W100 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+# CONFIG_BACKLIGHT_DA903X is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_PXA2XX_LIB=y
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_PXA2XX_SOC=y
+# CONFIG_SND_PXA2XX_SOC_IMOTE2 is not set
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_APPLE=m
+# CONFIG_HID_WACOM is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=y
+# CONFIG_USB_ETH_RNDIS is not set
+# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_MULTI is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
+CONFIG_MMC_SPI=y
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+# CONFIG_LEDS_GPIO is not set
+CONFIG_LEDS_LP3944=y
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DA903X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_REGULATOR is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SA1100 is not set
+# CONFIG_RTC_DRV_PXA is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+# CONFIG_CIFS_STATS2 is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_LOCKDEP=y
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_LOCKDEP is not set
+CONFIG_TRACE_IRQFLAGS=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_WORKQUEUE=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_GHASH=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index 5fc44c9..4611d3c 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.32-rc6
-# Sat Nov  7 20:31:18 2009
+# Linux kernel version: 2.6.33-rc6
+# Thu Feb  4 23:08:54 2010
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -32,6 +32,12 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
@@ -45,6 +51,7 @@
 #
 CONFIG_TREE_RCU=y
 # CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
 # CONFIG_RCU_TRACE is not set
 CONFIG_RCU_FANOUT=32
 # CONFIG_RCU_FANOUT_EXACT is not set
@@ -127,14 +134,41 @@
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
 # CONFIG_DEFAULT_DEADLINE is not set
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -163,6 +197,7 @@
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
 CONFIG_ARCH_KIRKWOOD=y
 # CONFIG_ARCH_LOKI is not set
 # CONFIG_ARCH_MV78XX0 is not set
@@ -185,6 +220,7 @@
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
 
 #
 # Marvell Kirkwood Implementations
@@ -195,7 +231,11 @@
 CONFIG_MACH_MV88F6281GTW_GE=y
 CONFIG_MACH_SHEEVAPLUG=y
 CONFIG_MACH_TS219=y
+CONFIG_MACH_TS41X=y
+CONFIG_MACH_OPENRD=y
 CONFIG_MACH_OPENRD_BASE=y
+CONFIG_MACH_OPENRD_CLIENT=y
+CONFIG_MACH_NETSPACE_V2=y
 CONFIG_PLAT_ORION=y
 
 #
@@ -262,12 +302,10 @@
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_SPLIT_PTLOCK_CPUS=999999
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_HAVE_MLOCK=y
-CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 # CONFIG_KSM is not set
 CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ALIGNMENT_TRAP=y
@@ -398,15 +436,18 @@
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
 CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
 CONFIG_CFG80211=y
 # CONFIG_NL80211_TESTMODE is not set
 # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
 # CONFIG_CFG80211_REG_DEBUG is not set
 CONFIG_CFG80211_DEFAULT_PS=y
-CONFIG_CFG80211_DEFAULT_PS_VALUE=1
 # CONFIG_CFG80211_DEBUGFS is not set
 CONFIG_WIRELESS_OLD_REGULATORY=y
-CONFIG_WIRELESS_EXT=y
+CONFIG_CFG80211_WEXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 CONFIG_LIB80211=y
 # CONFIG_LIB80211_DEBUG is not set
@@ -556,6 +597,10 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
@@ -606,7 +651,9 @@
 # CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BE2ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_HPSA is not set
 # CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_3W_SAS is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
@@ -642,6 +689,7 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_PM8001 is not set
 # CONFIG_SCSI_SRP is not set
 # CONFIG_SCSI_BFA_FC is not set
 # CONFIG_SCSI_DH is not set
@@ -696,15 +744,16 @@
 # CONFIG_PATA_NS87415 is not set
 # CONFIG_PATA_OPTI is not set
 # CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC2027X is not set
 # CONFIG_PATA_PDC_OLD is not set
 # CONFIG_PATA_RADISYS is not set
 # CONFIG_PATA_RDC is not set
 # CONFIG_PATA_RZ1000 is not set
 # CONFIG_PATA_SC1200 is not set
 # CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_PDC2027X is not set
 # CONFIG_PATA_SIL680 is not set
 # CONFIG_PATA_SIS is not set
+# CONFIG_PATA_TOSHIBA is not set
 # CONFIG_PATA_VIA is not set
 # CONFIG_PATA_WINBOND is not set
 # CONFIG_PATA_SCH is not set
@@ -720,7 +769,7 @@
 #
 
 #
-# See the help texts for more information.
+# The newer stack is recommended.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
@@ -828,13 +877,6 @@
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
 CONFIG_WLAN=y
-# CONFIG_WLAN_PRE80211 is not set
-CONFIG_WLAN_80211=y
-CONFIG_LIBERTAS=y
-# CONFIG_LIBERTAS_USB is not set
-CONFIG_LIBERTAS_SDIO=y
-# CONFIG_LIBERTAS_SPI is not set
-# CONFIG_LIBERTAS_DEBUG is not set
 # CONFIG_LIBERTAS_THINFIRM is not set
 # CONFIG_ATMEL is not set
 # CONFIG_AT76C50X_USB is not set
@@ -846,19 +888,24 @@
 # CONFIG_ADM8211 is not set
 # CONFIG_MAC80211_HWSIM is not set
 # CONFIG_MWL8K is not set
-# CONFIG_P54_COMMON is not set
 # CONFIG_ATH_COMMON is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_HOSTAP is not set
 # CONFIG_IPW2100 is not set
 # CONFIG_IPW2200 is not set
 # CONFIG_IWLWIFI is not set
-# CONFIG_HOSTAP is not set
-# CONFIG_B43 is not set
-# CONFIG_B43LEGACY is not set
-# CONFIG_ZD1211RW is not set
-# CONFIG_RT2X00 is not set
-# CONFIG_HERMES is not set
-# CONFIG_WL12XX is not set
 # CONFIG_IWM is not set
+CONFIG_LIBERTAS=y
+# CONFIG_LIBERTAS_USB is not set
+CONFIG_LIBERTAS_SDIO=y
+# CONFIG_LIBERTAS_SPI is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_HERMES is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_WL12XX is not set
+# CONFIG_ZD1211RW is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -881,6 +928,7 @@
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_VMXNET3 is not set
 # CONFIG_ISDN is not set
 # CONFIG_PHONE is not set
 
@@ -890,6 +938,7 @@
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
 # CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
 
 #
 # Userland interfaces
@@ -933,6 +982,7 @@
 # CONFIG_SERIO_PCIPS2 is not set
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
 # CONFIG_GAMEPORT is not set
 
 #
@@ -1019,11 +1069,6 @@
 # CONFIG_I2C_TINY_USB is not set
 
 #
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
 # Other I2C/SMBus bus drivers
 #
 # CONFIG_I2C_PCA_PLATFORM is not set
@@ -1032,7 +1077,6 @@
 #
 # Miscellaneous I2C Chip support
 #
-# CONFIG_DS1682 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -1048,6 +1092,8 @@
 # CONFIG_SPI_BITBANG is not set
 # CONFIG_SPI_GPIO is not set
 CONFIG_SPI_ORION=y
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
 
 #
 # SPI Protocol Masters
@@ -1074,10 +1120,12 @@
 # CONFIG_GPIO_MAX732X is not set
 # CONFIG_GPIO_PCA953X is not set
 # CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
 
 #
 # PCI GPIO expanders:
 #
+# CONFIG_GPIO_CS5535 is not set
 # CONFIG_GPIO_BT8XX is not set
 # CONFIG_GPIO_LANGWELL is not set
 
@@ -1116,6 +1164,7 @@
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_TC6393XB is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
@@ -1123,6 +1172,8 @@
 # CONFIG_MFD_MC13783 is not set
 # CONFIG_AB3100_CORE is not set
 # CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_88PM8607 is not set
+# CONFIG_AB4500_CORE is not set
 # CONFIG_REGULATOR is not set
 # CONFIG_MEDIA_SUPPORT is not set
 
@@ -1305,6 +1356,7 @@
 # OTG and related infrastructure
 #
 # CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
 # CONFIG_NOP_USB_XCEIV is not set
 # CONFIG_UWB is not set
 CONFIG_MMC=y
@@ -1344,6 +1396,7 @@
 # CONFIG_LEDS_PCA955X is not set
 # CONFIG_LEDS_DAC124S085 is not set
 # CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
 
 #
 # LED Triggers
@@ -1388,6 +1441,7 @@
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
 CONFIG_RTC_DRV_S35390A=y
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
@@ -1417,7 +1471,9 @@
 # CONFIG_RTC_DRV_M48T86 is not set
 # CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
 # CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
@@ -1684,7 +1740,9 @@
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
+# CONFIG_EARLY_PRINTK is not set
 # CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
 
 #
 # Security options
@@ -1692,7 +1750,11 @@
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
 CONFIG_CRYPTO=y
 
 #
diff --git a/arch/arm/configs/mini2440_defconfig b/arch/arm/configs/mini2440_defconfig
index d2a90eb..ff44bd1 100644
--- a/arch/arm/configs/mini2440_defconfig
+++ b/arch/arm/configs/mini2440_defconfig
@@ -184,7 +184,7 @@
 CONFIG_S3C24XX_GPIO_EXTRA=0
 CONFIG_S3C2410_DMA=y
 # CONFIG_S3C2410_DMA_DEBUG is not set
-CONFIG_S3C24XX_ADC=y
+CONFIG_S3C_ADC=y
 CONFIG_PLAT_S3C=y
 CONFIG_CPU_LLSERIAL_S3C2440_ONLY=y
 CONFIG_CPU_LLSERIAL_S3C2440=y
@@ -199,8 +199,8 @@
 #
 # Power management
 #
-# CONFIG_S3C2410_PM_DEBUG is not set
-# CONFIG_S3C2410_PM_CHECK is not set
+# CONFIG_SAMSUNG_PM_DEBUG is not set
+# CONFIG_SAMSUNG_PM_CHECK is not set
 CONFIG_S3C_LOWLEVEL_UART_PORT=0
 CONFIG_S3C_GPIO_SPACE=0
 
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
new file mode 100644
index 0000000..03f76cf
--- /dev/null
+++ b/arch/arm/configs/mmp2_defconfig
@@ -0,0 +1,1194 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc2
+# Tue Jan  5 13:55:22 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+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_NET_NS is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+CONFIG_ARCH_MMP=y
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_MACH_TAVOREVB is not set
+
+#
+# Marvell PXA168/910/MMP2 Implmentations
+#
+# CONFIG_MACH_ASPENITE is not set
+# CONFIG_MACH_ZYLONITE2 is not set
+# CONFIG_MACH_TTC_DKB is not set
+CONFIG_MACH_FLINT=y
+CONFIG_CPU_MMP2=y
+CONFIG_PLAT_PXA=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+# CONFIG_ARM_ERRATA_411920 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on console=ttyS0,115200 mem=128M user_debug=255"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_PXA3xx is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+CONFIG_MTD_ONENAND=y
+# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
+CONFIG_MTD_ONENAND_GENERIC=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_WLAN=y
+# CONFIG_HOSTAP is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+CONFIG_MFD_88PM8607=y
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+CONFIG_REGULATOR_MAX8660=y
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+CONFIG_REGULATOR_88PM8607=y
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_EXT4_USE_FOR_EXT23=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/mv78xx0_defconfig b/arch/arm/configs/mv78xx0_defconfig
index 6afa2c1..da4710d 100644
--- a/arch/arm/configs/mv78xx0_defconfig
+++ b/arch/arm/configs/mv78xx0_defconfig
@@ -176,6 +176,7 @@
 #
 CONFIG_MACH_DB78X00_BP=y
 CONFIG_MACH_RD78X00_MASA=y
+CONFIG_MACH_TERASTATION_WXL=y
 CONFIG_PLAT_ORION=y
 
 #
diff --git a/arch/arm/configs/mx1ads_defconfig b/arch/arm/configs/mx1ads_defconfig
deleted file mode 100644
index 3cabbb6..0000000
--- a/arch/arm/configs/mx1ads_defconfig
+++ /dev/null
@@ -1,742 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 02:15:46 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-# CONFIG_KALLSYMS is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_IOP3XX is not set
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-CONFIG_ARCH_IMX=y
-# CONFIG_ARCH_H720X is not set
-
-#
-# IMX Implementations
-#
-CONFIG_ARCH_MX1ADS=y
-
-#
-# Processor Type
-#
-CONFIG_CPU_ARM920T=y
-CONFIG_CPU_32v4=y
-CONFIG_CPU_ABRT_EV4T=y
-CONFIG_CPU_CACHE_V4WT=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_COPY_V4WB=y
-CONFIG_CPU_TLB_V4WBI=y
-
-#
-# Processor Features
-#
-# CONFIG_ARM_THUMB is not set
-# CONFIG_CPU_ICACHE_DISABLE is not set
-# CONFIG_CPU_DCACHE_DISABLE is not set
-# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
-
-#
-# Bus support
-#
-CONFIG_ISA=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-CONFIG_PREEMPT=y
-# CONFIG_LEDS is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttySMX0,57600n8 ip=bootp root=/dev/nfs"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-CONFIG_FPE_NWFPE_XP=y
-CONFIG_FPE_FASTFPE=y
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_AOUT is not set
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_RAM is not set
-CONFIG_MTD_ROM=y
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=m
-CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_SMC91X is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=y
-# CONFIG_PPP_SYNC_TTY is not set
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=m
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=y
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_PREEMPT=y
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_KOBJECT is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-# CONFIG_DEBUG_LL is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_CRC_CCITT=y
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/mx27_defconfig b/arch/arm/configs/mx27_defconfig
index edfdd6f..b4c1366 100644
--- a/arch/arm/configs/mx27_defconfig
+++ b/arch/arm/configs/mx27_defconfig
@@ -200,7 +200,7 @@
 CONFIG_MACH_PCM038=y
 CONFIG_MACH_PCM970_BASEBOARD=y
 CONFIG_MACH_MX27_3DS=y
-CONFIG_MACH_MX27LITE=y
+CONFIG_MACH_IMX27LITE=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
 
diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx51_defconfig
new file mode 100644
index 0000000..c88e952
--- /dev/null
+++ b/arch/arm/configs/mx51_defconfig
@@ -0,0 +1,1286 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc6
+# Tue Feb  2 15:20:48 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=18
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_MXC=y
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+
+#
+# Freescale MXC Implementations
+#
+# CONFIG_ARCH_MX1 is not set
+# CONFIG_ARCH_MX2 is not set
+# CONFIG_ARCH_MX25 is not set
+# CONFIG_ARCH_MX3 is not set
+# CONFIG_ARCH_MXC91231 is not set
+CONFIG_ARCH_MX5=y
+CONFIG_ARCH_MX51=y
+
+#
+# MX5 platforms:
+#
+CONFIG_MACH_MX51_BABBAGE=y
+# CONFIG_MXC_IRQ_PRIOR is not set
+CONFIG_MXC_TZIC=y
+# CONFIG_MXC_PWM is not set
+CONFIG_ARCH_MXC_IOMUX_V3=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.0.101:/shared/nfs ip=dhcp"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# 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=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_ATA=m
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_SATA_PMP=y
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_MV is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_ICPLUS_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_NATIONAL_PHY=y
+CONFIG_STE10XP=y
+CONFIG_LSI_ET1011C_PHY=y
+CONFIG_FIXED_PHY=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_MDIO_GPIO=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+CONFIG_FEC=y
+# CONFIG_FEC2 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+CONFIG_MOUSE_PS2_ELANTECH=y
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=m
+# CONFIG_I2C_HELPER_AUTO is not set
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_IMX is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_MFD_88PM8607 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=m
+# CONFIG_MMC_SDHCI_PLTFM is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
+# CONFIG_MMC_MXC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+# CONFIG_LEDS_GPIO is not set
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+
+#
+# LED Triggers
+#
+# CONFIG_LEDS_TRIGGERS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_MXC is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_SECURITYFS=y
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/nuc950_defconfig b/arch/arm/configs/nuc950_defconfig
index 97300ec..51cc2a2 100644
--- a/arch/arm/configs/nuc950_defconfig
+++ b/arch/arm/configs/nuc950_defconfig
@@ -590,8 +590,40 @@
 #
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NUC900=y
+CONFIG_GPM1040A0_320X240=y
+CONFIG_FB_NUC900_DEBUG=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+
 
 #
 # Display device support
@@ -603,6 +635,25 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
 # CONFIG_SOUND is not set
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB_SUPPORT=y
diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig
index 85b05d3..ee1ebd8 100644
--- a/arch/arm/configs/orion5x_defconfig
+++ b/arch/arm/configs/orion5x_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.32-rc6
-# Sat Nov  7 20:52:21 2009
+# Linux kernel version: 2.6.33-rc6
+# Thu Feb  4 23:30:00 2010
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -32,6 +32,12 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
@@ -45,6 +51,7 @@
 #
 CONFIG_TREE_RCU=y
 # CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
 # CONFIG_RCU_TRACE is not set
 CONFIG_RCU_FANOUT=32
 # CONFIG_RCU_FANOUT_EXACT is not set
@@ -122,14 +129,41 @@
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
 # CONFIG_DEFAULT_DEADLINE is not set
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -158,6 +192,7 @@
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
 # CONFIG_ARCH_KIRKWOOD is not set
 # CONFIG_ARCH_LOKI is not set
 # CONFIG_ARCH_MV78XX0 is not set
@@ -180,6 +215,7 @@
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
 
 #
 # Orion Implementations
@@ -192,6 +228,7 @@
 CONFIG_MACH_TERASTATION_PRO2=y
 CONFIG_MACH_LINKSTATION_PRO=y
 CONFIG_MACH_LINKSTATION_MINI=y
+CONFIG_MACH_LINKSTATION_LS_HGL=y
 CONFIG_MACH_TS409=y
 CONFIG_MACH_WRT350N_V2=y
 CONFIG_MACH_TS78XX=y
@@ -268,12 +305,10 @@
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_SPLIT_PTLOCK_CPUS=999999
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_HAVE_MLOCK=y
-CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 # CONFIG_KSM is not set
 CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_LEDS=y
@@ -412,10 +447,6 @@
 # CONFIG_AF_RXRPC is not set
 CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
-CONFIG_CFG80211_DEFAULT_PS_VALUE=0
-# CONFIG_WIRELESS_OLD_REGULATORY is not set
-CONFIG_WIRELESS_EXT=y
-CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
 
 #
@@ -554,6 +585,10 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
@@ -562,6 +597,7 @@
 # CONFIG_ATA_OVER_ETH is not set
 # CONFIG_MG_DISK is not set
 CONFIG_MISC_DEVICES=y
+# CONFIG_AD525X_DPOT is not set
 # CONFIG_PHANTOM is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
@@ -569,6 +605,7 @@
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_HP_ILO is not set
 # CONFIG_ISL29003 is not set
+# CONFIG_DS1682 is not set
 # CONFIG_C2PORT is not set
 
 #
@@ -621,7 +658,9 @@
 # CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BE2ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_HPSA is not set
 # CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_3W_SAS is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
@@ -657,6 +696,7 @@
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_PM8001 is not set
 # CONFIG_SCSI_SRP is not set
 # CONFIG_SCSI_BFA_FC is not set
 # CONFIG_SCSI_DH is not set
@@ -711,15 +751,16 @@
 # CONFIG_PATA_NS87415 is not set
 # CONFIG_PATA_OPTI is not set
 # CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC2027X is not set
 # CONFIG_PATA_PDC_OLD is not set
 # CONFIG_PATA_RADISYS is not set
 # CONFIG_PATA_RDC is not set
 # CONFIG_PATA_RZ1000 is not set
 # CONFIG_PATA_SC1200 is not set
 # CONFIG_PATA_SERVERWORKS is not set
-# CONFIG_PATA_PDC2027X is not set
 # CONFIG_PATA_SIL680 is not set
 # CONFIG_PATA_SIS is not set
+# CONFIG_PATA_TOSHIBA is not set
 # CONFIG_PATA_VIA is not set
 # CONFIG_PATA_WINBOND is not set
 # CONFIG_PATA_PLATFORM is not set
@@ -736,7 +777,7 @@
 #
 
 #
-# See the help texts for more information.
+# The newer stack is recommended.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
@@ -842,8 +883,10 @@
 # CONFIG_NETDEV_10000 is not set
 # CONFIG_TR is not set
 CONFIG_WLAN=y
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
+# CONFIG_ATMEL is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -866,6 +909,7 @@
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_VMXNET3 is not set
 # CONFIG_ISDN is not set
 # CONFIG_PHONE is not set
 
@@ -875,6 +919,7 @@
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
 # CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
 
 #
 # Userland interfaces
@@ -993,11 +1038,6 @@
 # CONFIG_I2C_TINY_USB is not set
 
 #
-# Graphics adapter I2C/DDC channel drivers
-#
-# CONFIG_I2C_VOODOO3 is not set
-
-#
 # Other I2C/SMBus bus drivers
 #
 # CONFIG_I2C_PCA_PLATFORM is not set
@@ -1006,7 +1046,6 @@
 #
 # Miscellaneous I2C Chip support
 #
-# CONFIG_DS1682 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -1033,10 +1072,12 @@
 # CONFIG_GPIO_MAX732X is not set
 # CONFIG_GPIO_PCA953X is not set
 # CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
 
 #
 # PCI GPIO expanders:
 #
+# CONFIG_GPIO_CS5535 is not set
 # CONFIG_GPIO_BT8XX is not set
 # CONFIG_GPIO_LANGWELL is not set
 
@@ -1079,6 +1120,7 @@
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM73 is not set
 CONFIG_SENSORS_LM75=y
 # CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
@@ -1104,6 +1146,7 @@
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_AMC6821 is not set
 # CONFIG_SENSORS_THMC50 is not set
 # CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_TMP421 is not set
@@ -1118,6 +1161,7 @@
 # CONFIG_SENSORS_W83L786NG is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
 # CONFIG_THERMAL is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
@@ -1140,11 +1184,13 @@
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_TC6393XB is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_AB3100_CORE is not set
+# CONFIG_MFD_88PM8607 is not set
 # CONFIG_REGULATOR is not set
 # CONFIG_MEDIA_SUPPORT is not set
 
@@ -1316,6 +1362,7 @@
 # OTG and related infrastructure
 #
 # CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
 # CONFIG_NOP_USB_XCEIV is not set
 # CONFIG_UWB is not set
 # CONFIG_MMC is not set
@@ -1332,6 +1379,7 @@
 # CONFIG_LEDS_LP3944 is not set
 # CONFIG_LEDS_PCA955X is not set
 # CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
 
 #
 # LED Triggers
@@ -1377,6 +1425,7 @@
 # CONFIG_RTC_DRV_PCF8583 is not set
 CONFIG_RTC_DRV_M41T80=y
 # CONFIG_RTC_DRV_M41T80_WDT is not set
+# CONFIG_RTC_DRV_BQ32K is not set
 CONFIG_RTC_DRV_S35390A=y
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
@@ -1398,7 +1447,9 @@
 CONFIG_RTC_DRV_M48T86=y
 # CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
 # CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
@@ -1686,7 +1737,9 @@
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
+# CONFIG_EARLY_PRINTK is not set
 # CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
 
 #
 # Security options
@@ -1694,7 +1747,11 @@
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
 CONFIG_CRYPTO=y
 
 #
diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig
index 791b8c3..113511f 100644
--- a/arch/arm/configs/pxa168_defconfig
+++ b/arch/arm/configs/pxa168_defconfig
@@ -1,15 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc3
-# Fri Mar 20 13:43:13 2009
+# Linux kernel version: 2.6.33-rc3
+# Tue Jan 12 08:57:10 2010
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_MMU=y
-# CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -18,13 +16,12 @@
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -35,6 +32,12 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
@@ -46,11 +49,13 @@
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_GROUP_SCHED is not set
@@ -64,10 +69,10 @@
 # CONFIG_USER_NS is not set
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -78,17 +83,20 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -98,6 +106,11 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -109,8 +122,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -118,31 +130,62 @@
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
 # CONFIG_DEFAULT_DEADLINE is not set
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
 # CONFIG_FREEZER is not set
 
 #
 # System Type
 #
+CONFIG_MMU=y
 # CONFIG_ARCH_AAEC2000 is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
 # CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_NOMADIK is not set
 # CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
@@ -150,26 +193,30 @@
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
 # CONFIG_ARCH_KIRKWOOD is not set
-# CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
 # CONFIG_ARCH_LOKI is not set
 # CONFIG_ARCH_MV78XX0 is not set
-# CONFIG_ARCH_MXC is not set
 # CONFIG_ARCH_ORION5X is not set
+CONFIG_ARCH_MMP=y
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
 # CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
-CONFIG_ARCH_MMP=y
+# CONFIG_ARCH_MSM is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM is not set
-# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
 # CONFIG_MACH_TAVOREVB is not set
 
 #
@@ -177,6 +224,7 @@
 #
 CONFIG_MACH_ASPENITE=y
 CONFIG_MACH_ZYLONITE2=y
+CONFIG_MACH_AVENGERS_LITE=y
 # CONFIG_MACH_TTC_DKB is not set
 CONFIG_CPU_PXA168=y
 CONFIG_PLAT_PXA=y
@@ -187,7 +235,7 @@
 CONFIG_CPU_MOHAWK=y
 CONFIG_CPU_32v5=y
 CONFIG_CPU_ABRT_EV5T=y
-CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_PABRT_LEGACY=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_COPY_V4WB=y
 CONFIG_CPU_TLB_V4WBI=y
@@ -201,7 +249,7 @@
 # CONFIG_CPU_ICACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_BPREDICT_DISABLE is not set
-# CONFIG_OUTER_CACHE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
 CONFIG_IWMMXT=y
 CONFIG_COMMON_CLKDEV=y
 
@@ -223,13 +271,15 @@
 # CONFIG_VMSPLIT_2G is not set
 # CONFIG_VMSPLIT_1G is not set
 CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
 # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
 # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -237,12 +287,14 @@
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_SPLIT_PTLOCK_CPUS=999999
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
 
 #
 # Boot options
@@ -288,7 +340,6 @@
 #
 # Networking options
 #
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -330,6 +381,7 @@
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -343,6 +395,8 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -355,13 +409,13 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -374,6 +428,7 @@
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
@@ -412,8 +467,10 @@
 # CONFIG_AX88796 is not set
 CONFIG_SMC91X=y
 # CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
 # CONFIG_SMC911X is not set
 # CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -422,15 +479,12 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_WLAN=y
+# CONFIG_HOSTAP is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -442,6 +496,7 @@
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -449,6 +504,7 @@
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
 # CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
 
 #
 # Userland interfaces
@@ -510,6 +566,11 @@
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
 # CONFIG_DEBUG_GPIO is not set
@@ -530,11 +591,14 @@
 #
 # SPI GPIO expanders:
 #
+
+#
+# AC97 GPIO expanders:
+#
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
 
@@ -555,22 +619,8 @@
 # CONFIG_MFD_T7L66XB is not set
 # CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -595,13 +645,17 @@
 # CONFIG_USB_SUPPORT is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
-# CONFIG_ACCESSIBILITY is not set
 # CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
 CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
-# CONFIG_REGULATOR is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -613,10 +667,13 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -627,6 +684,11 @@
 CONFIG_GENERIC_ACL=y
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -673,6 +735,7 @@
 CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -681,7 +744,6 @@
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -706,6 +768,7 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -714,11 +777,15 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
 # CONFIG_DEBUG_PREEMPT is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -738,28 +805,33 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -768,7 +840,9 @@
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
+# CONFIG_EARLY_PRINTK is not set
 # CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
 
 #
 # Security options
@@ -776,13 +850,16 @@
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
 CONFIG_CRYPTO=y
 
 #
 # Crypto core or helper
 #
-# CONFIG_CRYPTO_FIPS is not set
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_ALGAPI2=y
 CONFIG_CRYPTO_AEAD2=y
@@ -791,10 +868,12 @@
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_HASH2=y
 CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 # CONFIG_CRYPTO_AUTHENC is not set
 # CONFIG_CRYPTO_TEST is not set
@@ -822,11 +901,13 @@
 #
 # CONFIG_CRYPTO_HMAC is not set
 # CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
 
 #
 # Digest
 #
 # CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
@@ -863,6 +944,7 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
 
 #
@@ -870,6 +952,7 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -884,7 +967,7 @@
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
new file mode 100644
index 0000000..acb1a8f
--- /dev/null
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -0,0 +1,1898 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32-rc5
+# Sun Nov  1 21:57:32 2009
+#
+CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_SLOW_WORK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+
+#
+# Intel PXA2xx/PXA3xx Implementations
+#
+
+#
+# Supported PXA3xx Processor Variants
+#
+CONFIG_CPU_PXA300=y
+# CONFIG_CPU_PXA310 is not set
+CONFIG_CPU_PXA320=y
+# CONFIG_CPU_PXA930 is not set
+# CONFIG_CPU_PXA935 is not set
+# CONFIG_CPU_PXA950 is not set
+
+#
+# Intel/Marvell Dev Platforms (sorted by hardware release time)
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_MACH_ZYLONITE is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_TAVOREVB is not set
+# CONFIG_MACH_SAAR is not set
+
+#
+# Third Party Dev Platforms (sorted by vendor name)
+#
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_ARCH_VIPER is not set
+# CONFIG_MACH_BALLOON3 is not set
+# CONFIG_MACH_CSB726 is not set
+# CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_EXEDA is not set
+# CONFIG_MACH_CM_X300 is not set
+# CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_MACH_INTELMOTE2 is not set
+# CONFIG_MACH_STARGATE2 is not set
+# CONFIG_MACH_XCEP is not set
+# CONFIG_TRIZEPS_PXA is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_PCM027 is not set
+# CONFIG_MACH_COLIBRI is not set
+# CONFIG_MACH_COLIBRI300 is not set
+# CONFIG_MACH_COLIBRI320 is not set
+
+#
+# End-user Products (sorted by vendor name)
+#
+# CONFIG_MACH_H4700 is not set
+# CONFIG_MACH_H5000 is not set
+# CONFIG_MACH_HIMALAYA is not set
+# CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_MIOA701 is not set
+# CONFIG_PXA_EZX is not set
+# CONFIG_MACH_MP900C is not set
+# CONFIG_ARCH_PXA_PALM is not set
+CONFIG_MACH_RAUMFELD_RC=y
+CONFIG_MACH_RAUMFELD_CONNECTOR=y
+CONFIG_MACH_RAUMFELD_PROTO=y
+CONFIG_MACH_RAUMFELD_SPEAKER=y
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_ARCH_PXA_ESERIES is not set
+CONFIG_PXA3xx=y
+CONFIG_PXA_SSP=y
+CONFIG_PLAT_PXA=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSC3=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_IO_36=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_CACHE_XSC3L2=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_IWMMXT=y
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="console=ttyS0,115200 rw"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_APM_EMULATION=y
+# CONFIG_PM_RUNTIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=y
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+CONFIG_CFG80211_REG_DEBUG=y
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEFAULT_PS_VALUE=1
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+CONFIG_MAC80211_RC_MINSTREL=y
+# CONFIG_MAC80211_RC_DEFAULT_PID is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+CONFIG_MTD_BLOCK2MTD=y
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_H1900 is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_SHARPSL is not set
+CONFIG_MTD_NAND_PXA3xx=y
+# CONFIG_MTD_NAND_PXA3xx_BUILTIN is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_ISL29003=y
+CONFIG_TI_DAC7512=y
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_WLAN=y
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+# CONFIG_LIBERTAS_USB is not set
+CONFIG_LIBERTAS_SDIO=m
+# CONFIG_LIBERTAS_SPI is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AT76C50X_USB is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_ATH_COMMON is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_WL12XX is not set
+# CONFIG_IWM is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=y
+# CONFIG_USB_NET_AX8817X is not set
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SMSC95XX is not set
+# CONFIG_USB_NET_GL620A is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_NET_PLUSB is not set
+CONFIG_USB_NET_MCS7830=y
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+# CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_POLLDEV=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_PXA27x is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+CONFIG_TOUCHSCREEN_EETI=m
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+# CONFIG_INPUT_UINPUT is not set
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_DEBUG=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+# CONFIG_SPI_PXA2XX is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+
+#
+# AC97 GPIO expanders:
+#
+CONFIG_W1=m
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+CONFIG_W1_MASTER_GPIO=m
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+CONFIG_W1_SLAVE_DS2760=m
+# CONFIG_W1_SLAVE_BQ27000 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_PDA_POWER=y
+# CONFIG_APM_POWER is not set
+CONFIG_BATTERY_DS2760=m
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+CONFIG_SENSORS_LIS3_SPI=y
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13783 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DEBUG=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+CONFIG_REGULATOR_MAX8660=y
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_OVERLAY is not set
+# CONFIG_FB_PXA_SMARTPANEL is not set
+# CONFIG_FB_PXA_PARAMETERS is not set
+CONFIG_PXA3XX_GCU=y
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_W100 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_RAUMFELD_CLUT224=y
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+# CONFIG_SND_DRIVERS is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_PXA2XX_LIB=y
+# CONFIG_SND_PXA2XX_AC97 is not set
+CONFIG_SND_SPI=y
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_PXA2XX_SOC=y
+CONFIG_SND_PXA_SOC_SSP=y
+CONFIG_SND_SOC_RAUMFELD=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_AK4104=y
+CONFIG_SND_SOC_CS4270=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+# CONFIG_DRAGONRISE_FF is not set
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_SMARTJOYPLUS=y
+# CONFIG_SMARTJOYPLUS_FF is not set
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+# CONFIG_THRUSTMASTER_FF is not set
+CONFIG_HID_ZEROPLUS=y
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_PXA=m
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_PWM is not set
+# CONFIG_LEDS_BD2802 is not set
+CONFIG_LEDS_LT3593=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SA1100 is not set
+CONFIG_RTC_DRV_PXA=y
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+CONFIG_FSCACHE=y
+CONFIG_FSCACHE_STATS=y
+# CONFIG_FSCACHE_HISTOGRAM is not set
+# CONFIG_FSCACHE_DEBUG is not set
+CONFIG_CACHEFILES=y
+# CONFIG_CACHEFILES_DEBUG is not set
+# CONFIG_CACHEFILES_HISTOGRAM is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFS_FSCACHE=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+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_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=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_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/arm/configs/rx51_defconfig b/arch/arm/configs/rx51_defconfig
index 426ae94..193bd33 100644
--- a/arch/arm/configs/rx51_defconfig
+++ b/arch/arm/configs/rx51_defconfig
@@ -445,6 +445,8 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+CONFIG_PHONET=y
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -1325,27 +1327,34 @@
 # CONFIG_USB_GADGET_LH7A40X is not set
 # CONFIG_USB_GADGET_OMAP is not set
 # CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
 # CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
 # CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
 # CONFIG_USB_GADGET_M66592 is not set
 # CONFIG_USB_GADGET_AMD5536UDC is not set
 # CONFIG_USB_GADGET_FSL_QE is not set
 # CONFIG_USB_GADGET_CI13XXX is not set
 # CONFIG_USB_GADGET_NET2280 is not set
 # CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 CONFIG_USB_GADGET_DUALSPEED=y
 CONFIG_USB_ZERO=m
 # CONFIG_USB_ZERO_HNPTEST is not set
+# CONFIG_USB_AUDIO is not set
 # CONFIG_USB_ETH is not set
 # CONFIG_USB_GADGETFS is not set
 CONFIG_USB_FILE_STORAGE=m
 # CONFIG_USB_FILE_STORAGE_TEST is not set
+# CONFIG_USB_MASS_STORAGE is not set
 # CONFIG_USB_G_SERIAL is not set
 # CONFIG_USB_MIDI_GADGET is not set
 # CONFIG_USB_G_PRINTER is not set
 # CONFIG_USB_CDC_COMPOSITE is not set
+CONFIG_USB_G_NOKIA=m
+# CONFIG_USB_G_MULTI is not set
 
 #
 # OTG and related infrastructure
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 2f10dae..8e94c3c 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -187,7 +187,7 @@
 CONFIG_PM_SIMTEC=y
 CONFIG_S3C2410_DMA=y
 # CONFIG_S3C2410_DMA_DEBUG is not set
-CONFIG_S3C24XX_ADC=y
+CONFIG_S3C_ADC=y
 CONFIG_MACH_SMDK=y
 CONFIG_PLAT_S3C=y
 CONFIG_CPU_LLSERIAL_S3C2410=y
@@ -203,8 +203,8 @@
 #
 # Power management
 #
-# CONFIG_S3C2410_PM_DEBUG is not set
-# CONFIG_S3C2410_PM_CHECK is not set
+# CONFIG_SAMSUNG_PM_DEBUG is not set
+# CONFIG_SAMSUNG_PM_CHECK is not set
 CONFIG_S3C_LOWLEVEL_UART_PORT=0
 CONFIG_S3C_GPIO_SPACE=0
 CONFIG_S3C_DEV_HSMMC=y
diff --git a/arch/arm/configs/s3c6400_defconfig b/arch/arm/configs/s3c6400_defconfig
index f56e50f..5e7d4c1 100644
--- a/arch/arm/configs/s3c6400_defconfig
+++ b/arch/arm/configs/s3c6400_defconfig
@@ -1,14 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Mon Nov  3 10:10:30 2008
+# Linux kernel version: 2.6.33-rc4
+# Tue Jan 19 13:12:40 2010
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_GENERIC_GPIO=y
-# CONFIG_GENERIC_TIME is not set
-# CONFIG_GENERIC_CLOCKEVENTS is not set
-CONFIG_MMU=y
 CONFIG_NO_IOPORT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
@@ -18,13 +15,13 @@
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_HAS_CPUFREQ=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -34,13 +31,30 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
 CONFIG_SWAP=y
 # CONFIG_SYSVIPC is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
@@ -50,8 +64,13 @@
 # CONFIG_PID_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
 CONFIG_SYSCTL_SYSCALL=y
@@ -62,32 +81,38 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -95,11 +120,8 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
-CONFIG_LBD=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
-CONFIG_LSF=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -107,33 +129,62 @@
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
 # CONFIG_DEFAULT_DEADLINE is not set
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
 # CONFIG_FREEZER is not set
 
 #
 # System Type
 #
+CONFIG_MMU=y
 # CONFIG_ARCH_AAEC2000 is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_NOMADIK is not set
 # CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
@@ -141,35 +192,62 @@
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
 # CONFIG_ARCH_KIRKWOOD is not set
-# CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
 # CONFIG_ARCH_LOKI is not set
 # CONFIG_ARCH_MV78XX0 is not set
-# CONFIG_ARCH_MXC is not set
 # CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
 # CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 CONFIG_ARCH_S3C64XX=y
+# CONFIG_ARCH_S5P6440 is not set
+# CONFIG_ARCH_S5PC1XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+CONFIG_PLAT_SAMSUNG=y
+CONFIG_SAMSUNG_CLKSRC=y
+CONFIG_SAMSUNG_IRQ_VIC_TIMER=y
+CONFIG_SAMSUNG_IRQ_UART=y
+CONFIG_S3C_GPIO_CFG_S3C24XX=y
+CONFIG_S3C_GPIO_CFG_S3C64XX=y
+CONFIG_S3C_GPIO_PULL_UPDOWN=y
+CONFIG_SAMSUNG_GPIO_EXTRA=0
+# CONFIG_S3C_ADC is not set
+CONFIG_S3C_DEV_HSMMC=y
+CONFIG_S3C_DEV_HSMMC1=y
+CONFIG_S3C_DEV_I2C1=y
+CONFIG_S3C_DEV_FB=y
+CONFIG_S3C_DEV_USB_HOST=y
+CONFIG_S3C_DEV_USB_HSOTG=y
+CONFIG_S3C_DEV_NAND=y
 CONFIG_PLAT_S3C64XX=y
 CONFIG_CPU_S3C6400_INIT=y
 CONFIG_CPU_S3C6400_CLOCK=y
+# CONFIG_S3C64XX_DMA is not set
 CONFIG_S3C64XX_SETUP_I2C0=y
 CONFIG_S3C64XX_SETUP_I2C1=y
+CONFIG_S3C64XX_SETUP_FB_24BPP=y
+CONFIG_S3C64XX_SETUP_SDHCI_GPIO=y
 CONFIG_PLAT_S3C=y
 
 #
 # Boot options
 #
 CONFIG_S3C_BOOT_ERROR_RESET=y
+CONFIG_S3C_BOOT_UART_FORCE_FIFO=y
 
 #
 # Power management
@@ -177,17 +255,16 @@
 CONFIG_S3C_LOWLEVEL_UART_PORT=0
 CONFIG_S3C_GPIO_SPACE=0
 CONFIG_S3C_GPIO_TRACK=y
-CONFIG_S3C_GPIO_PULL_UPDOWN=y
-CONFIG_S3C_GPIO_CFG_S3C24XX=y
-CONFIG_S3C_GPIO_CFG_S3C64XX=y
-CONFIG_S3C_DEV_HSMMC=y
-CONFIG_S3C_DEV_HSMMC1=y
-CONFIG_S3C_DEV_I2C1=y
+# CONFIG_MACH_SMDK6400 is not set
 CONFIG_CPU_S3C6410=y
 CONFIG_S3C6410_SETUP_SDHCI=y
+# CONFIG_MACH_ANW6410 is not set
 CONFIG_MACH_SMDK6410=y
 CONFIG_SMDK6410_SD_CH0=y
 # CONFIG_SMDK6410_SD_CH1 is not set
+# CONFIG_SMDK6410_WM1190_EV1 is not set
+# CONFIG_MACH_NCP is not set
+# CONFIG_MACH_HMT is not set
 
 #
 # Processor Type
@@ -196,7 +273,7 @@
 CONFIG_CPU_32v6K=y
 CONFIG_CPU_32v6=y
 CONFIG_CPU_ABRT_EV6=y
-CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_PABRT_V6=y
 CONFIG_CPU_CACHE_V6=y
 CONFIG_CPU_CACHE_VIPT=y
 CONFIG_CPU_COPY_V6=y
@@ -212,8 +289,10 @@
 # CONFIG_CPU_ICACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_BPREDICT_DISABLE is not set
-# CONFIG_OUTER_CACHE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+# CONFIG_ARM_ERRATA_411920 is not set
 CONFIG_ARM_VIC=y
+CONFIG_ARM_VIC_NR=2
 
 #
 # Bus support
@@ -229,13 +308,15 @@
 # CONFIG_VMSPLIT_2G is not set
 # CONFIG_VMSPLIT_1G is not set
 CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
 # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
 # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -243,26 +324,28 @@
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+CONFIG_SPLIT_PTLOCK_CPUS=999999
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
 
 #
 # Boot options
 #
 CONFIG_ZBOOT_ROM_TEXT=0
 CONFIG_ZBOOT_ROM_BSS=0
-CONFIG_CMDLINE="console=ttySAC0,115200 root=/dev/ram init=/bin/bash initrd=0x51000000,4M"
+CONFIG_CMDLINE="console=ttySAC0,115200 root=/dev/ram init=/linuxrc initrd=0x51000000,6M ramdisk_size=6144"
 # CONFIG_XIP_KERNEL is not set
 # CONFIG_KEXEC is not set
 
 #
 # CPU Power Management
 #
+# CONFIG_CPU_FREQ is not set
 # CONFIG_CPU_IDLE is not set
 
 #
@@ -300,6 +383,7 @@
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
@@ -314,14 +398,32 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_MG_DISK is not set
 CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IWMC3200TOP is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -334,6 +436,7 @@
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -341,6 +444,7 @@
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
 # CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
 
 #
 # Userland interfaces
@@ -357,27 +461,33 @@
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
 CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_QT2160 is not set
 # CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
 # CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
 CONFIG_MOUSE_PS2_LOGIPS2PP=y
 CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_LIFEBOOK=y
 CONFIG_MOUSE_PS2_TRACKPOINT=y
 # CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
 # CONFIG_MOUSE_PS2_TOUCHKIT is not set
 # CONFIG_MOUSE_SERIAL is not set
 # CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
@@ -390,6 +500,7 @@
 CONFIG_SERIO_SERPORT=y
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
 # CONFIG_GAMEPORT is not set
 
 #
@@ -423,16 +534,18 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_IPMI_HANDLER is not set
 CONFIG_HW_RANDOM=y
-# CONFIG_NVRAM is not set
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_HELPER_AUTO=y
 
@@ -443,6 +556,7 @@
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 # CONFIG_I2C_OCORES is not set
 CONFIG_I2C_S3C2410=y
@@ -463,32 +577,33 @@
 #
 # Miscellaneous I2C Chip support
 #
-# CONFIG_DS1682 is not set
-CONFIG_EEPROM_AT24=y
-# CONFIG_EEPROM_LEGACY is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
 # CONFIG_DEBUG_GPIO is not set
 # CONFIG_GPIO_SYSFS is not set
 
 #
+# Memory mapped GPIO expanders:
+#
+
+#
 # I2C GPIO expanders:
 #
 # CONFIG_GPIO_MAX732X is not set
 # CONFIG_GPIO_PCA953X is not set
 # CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
 
 #
 # PCI GPIO expanders:
@@ -497,10 +612,19 @@
 #
 # SPI GPIO expanders:
 #
+
+#
+# AC97 GPIO expanders:
+#
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
 # CONFIG_SENSORS_AD7414 is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
@@ -509,17 +633,21 @@
 # CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
 # CONFIG_SENSORS_ADT7470 is not set
 # CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM73 is not set
 # CONFIG_SENSORS_LM75 is not set
 # CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
@@ -530,16 +658,24 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
 # CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_AMC6821 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83791D is not set
@@ -549,15 +685,14 @@
 # CONFIG_SENSORS_W83L786NG is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
@@ -568,28 +703,22 @@
 # CONFIG_MFD_ASIC3 is not set
 # CONFIG_HTC_EGPIO is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_T7L66XB is not set
 # CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_MFD_88PM8607 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -612,17 +741,15 @@
 # CONFIG_SOUND is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
-CONFIG_HID_DEBUG=y
 # CONFIG_HIDRAW is not set
 # CONFIG_HID_PID is not set
 
 #
 # Special HID drivers
 #
-# CONFIG_HID_COMPAT is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB_ARCH_HAS_OHCI=y
 # CONFIG_USB_ARCH_HAS_EHCI is not set
 # CONFIG_USB is not set
 
@@ -631,9 +758,13 @@
 #
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
 CONFIG_MMC=y
 CONFIG_MMC_DEBUG=y
 CONFIG_MMC_UNSAFE_RESUME=y
@@ -650,22 +781,24 @@
 # MMC/SD/SDIO Host Controller Drivers
 #
 CONFIG_MMC_SDHCI=y
+# CONFIG_MMC_SDHCI_PLTFM is not set
 CONFIG_MMC_SDHCI_S3C=y
+# CONFIG_MMC_SDHCI_S3C_DMA is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
 # CONFIG_MEMSTICK is not set
-# CONFIG_ACCESSIBILITY is not set
 # CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
 CONFIG_RTC_LIB=y
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
 
 #
-# Voltage and Current regulators
+# TI VLYNQ
 #
-# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
-# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -674,6 +807,7 @@
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
@@ -683,9 +817,12 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -696,6 +833,11 @@
 CONFIG_GENERIC_ACL=y
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -719,10 +861,7 @@
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -731,12 +870,17 @@
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
 CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
 
@@ -755,6 +899,7 @@
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
@@ -763,12 +908,16 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_SLUB_DEBUG_ON is not set
 # CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
 CONFIG_DEBUG_RT_MUTEXES=y
 CONFIG_DEBUG_PI_LIST=y
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -787,34 +936,43 @@
 CONFIG_DEBUG_MEMORY_INIT=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
-
-#
-# Tracers
-#
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
+# CONFIG_EARLY_PRINTK is not set
 # CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
 CONFIG_DEBUG_S3C_UART=0
 
 #
@@ -823,13 +981,19 @@
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
 # CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
@@ -838,6 +1002,10 @@
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/s5p6440_defconfig b/arch/arm/configs/s5p6440_defconfig
new file mode 100644
index 0000000..279a15e
--- /dev/null
+++ b/arch/arm/configs/s5p6440_defconfig
@@ -0,0 +1,969 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc2
+# Sat Jan  9 16:33:55 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_NO_IOPORT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_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_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+CONFIG_ARCH_S5P6440=y
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+CONFIG_PLAT_SAMSUNG=y
+CONFIG_SAMSUNG_CLKSRC=y
+CONFIG_SAMSUNG_IRQ_VIC_TIMER=y
+CONFIG_SAMSUNG_IRQ_UART=y
+CONFIG_SAMSUNG_GPIO_EXTRA=0
+CONFIG_PLAT_S3C=y
+
+#
+# Boot options
+#
+CONFIG_S3C_BOOT_ERROR_RESET=y
+CONFIG_S3C_BOOT_UART_FORCE_FIFO=y
+
+#
+# Power management
+#
+CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_S3C_GPIO_SPACE=0
+CONFIG_S3C_GPIO_TRACK=y
+CONFIG_PLAT_S5P=y
+CONFIG_CPU_S5P6440_INIT=y
+CONFIG_CPU_S5P6440_CLOCK=y
+CONFIG_CPU_S5P6440=y
+CONFIG_MACH_SMDK6440=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+# CONFIG_ARM_ERRATA_411920 is not set
+CONFIG_ARM_VIC=y
+CONFIG_ARM_VIC_NR=2
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=200
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_NR_UARTS=3
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_UARTS=4
+# CONFIG_SERIAL_SAMSUNG_DEBUG is not set
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_SERIAL_S5P6440=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
+CONFIG_DEBUG_S3C_UART=1
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/s5p6442_defconfig b/arch/arm/configs/s5p6442_defconfig
new file mode 100644
index 0000000..74e20bf
--- /dev/null
+++ b/arch/arm/configs/s5p6442_defconfig
@@ -0,0 +1,883 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc4
+# Mon Jan 25 08:50:28 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_NO_IOPORT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_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_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P6440 is not set
+CONFIG_ARCH_S5P6442=y
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+CONFIG_PLAT_SAMSUNG=y
+CONFIG_SAMSUNG_CLKSRC=y
+CONFIG_SAMSUNG_IRQ_VIC_TIMER=y
+CONFIG_SAMSUNG_IRQ_UART=y
+CONFIG_SAMSUNG_GPIOLIB_4BIT=y
+CONFIG_S3C_GPIO_CFG_S3C24XX=y
+CONFIG_S3C_GPIO_CFG_S3C64XX=y
+CONFIG_S3C_GPIO_PULL_UPDOWN=y
+CONFIG_SAMSUNG_GPIO_EXTRA=0
+# CONFIG_S3C_ADC is not set
+
+#
+# Power management
+#
+CONFIG_PLAT_S3C=y
+
+#
+# Boot options
+#
+# CONFIG_S3C_BOOT_ERROR_RESET is not set
+CONFIG_S3C_BOOT_UART_FORCE_FIFO=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_S3C_GPIO_SPACE=0
+CONFIG_S3C_GPIO_TRACK=y
+CONFIG_PLAT_S5P=y
+CONFIG_CPU_S5P6442=y
+CONFIG_MACH_SMDK6442=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+# CONFIG_ARM_ERRATA_411920 is not set
+CONFIG_ARM_VIC=y
+CONFIG_ARM_VIC_NR=2
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=200
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_NR_UARTS=3
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_UARTS=3
+# CONFIG_SERIAL_SAMSUNG_DEBUG is not set
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_SERIAL_S5PV210=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
+CONFIG_DEBUG_S3C_UART=1
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/s5pc110_defconfig b/arch/arm/configs/s5pc110_defconfig
new file mode 100644
index 0000000..6ea6361
--- /dev/null
+++ b/arch/arm/configs/s5pc110_defconfig
@@ -0,0 +1,894 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc4
+# Wed Feb 24 15:36:54 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_NO_IOPORT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_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_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P6440 is not set
+# CONFIG_ARCH_S5P6442 is not set
+# CONFIG_ARCH_S5PC1XX is not set
+CONFIG_ARCH_S5PV210=y
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+CONFIG_PLAT_SAMSUNG=y
+
+#
+# Boot options
+#
+# CONFIG_S3C_BOOT_ERROR_RESET is not set
+CONFIG_S3C_BOOT_UART_FORCE_FIFO=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_SAMSUNG_CLKSRC=y
+CONFIG_SAMSUNG_IRQ_VIC_TIMER=y
+CONFIG_SAMSUNG_IRQ_UART=y
+CONFIG_SAMSUNG_GPIOLIB_4BIT=y
+CONFIG_S3C_GPIO_CFG_S3C24XX=y
+CONFIG_S3C_GPIO_CFG_S3C64XX=y
+CONFIG_S3C_GPIO_PULL_UPDOWN=y
+CONFIG_SAMSUNG_GPIO_EXTRA=0
+CONFIG_S3C_GPIO_SPACE=0
+CONFIG_S3C_GPIO_TRACK=y
+# CONFIG_S3C_ADC is not set
+
+#
+# Power management
+#
+CONFIG_PLAT_S5P=y
+CONFIG_CPU_S5PV210=y
+# CONFIG_MACH_SMDKV210 is not set
+CONFIG_MACH_SMDKC110=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_ARM_VIC=y
+CONFIG_ARM_VIC_NR=2
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_VMSPLIT_3G is not set
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0x80000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=200
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_UARTS_4=y
+CONFIG_SERIAL_SAMSUNG_UARTS=4
+# CONFIG_SERIAL_SAMSUNG_DEBUG is not set
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_SERIAL_S5PV210=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
+CONFIG_DEBUG_S3C_UART=1
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/configs/s5pv210_defconfig b/arch/arm/configs/s5pv210_defconfig
new file mode 100644
index 0000000..3f7d474
--- /dev/null
+++ b/arch/arm/configs/s5pv210_defconfig
@@ -0,0 +1,894 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc4
+# Wed Feb 24 15:36:16 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_NO_IOPORT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_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_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P6440 is not set
+# CONFIG_ARCH_S5P6442 is not set
+# CONFIG_ARCH_S5PC1XX is not set
+CONFIG_ARCH_S5PV210=y
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+CONFIG_PLAT_SAMSUNG=y
+
+#
+# Boot options
+#
+# CONFIG_S3C_BOOT_ERROR_RESET is not set
+CONFIG_S3C_BOOT_UART_FORCE_FIFO=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_SAMSUNG_CLKSRC=y
+CONFIG_SAMSUNG_IRQ_VIC_TIMER=y
+CONFIG_SAMSUNG_IRQ_UART=y
+CONFIG_SAMSUNG_GPIOLIB_4BIT=y
+CONFIG_S3C_GPIO_CFG_S3C24XX=y
+CONFIG_S3C_GPIO_CFG_S3C64XX=y
+CONFIG_S3C_GPIO_PULL_UPDOWN=y
+CONFIG_SAMSUNG_GPIO_EXTRA=0
+CONFIG_S3C_GPIO_SPACE=0
+CONFIG_S3C_GPIO_TRACK=y
+# CONFIG_S3C_ADC is not set
+
+#
+# Power management
+#
+CONFIG_PLAT_S5P=y
+CONFIG_CPU_S5PV210=y
+CONFIG_MACH_SMDKV210=y
+# CONFIG_MACH_SMDKC110 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+CONFIG_ARM_VIC=y
+CONFIG_ARM_VIC_NR=2
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_VMSPLIT_3G is not set
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0x80000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=200
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_UARTS_4=y
+CONFIG_SERIAL_SAMSUNG_UARTS=4
+# CONFIG_SERIAL_SAMSUNG_DEBUG is not set
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_SERIAL_S5PV210=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
+CONFIG_DEBUG_S3C_UART=1
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 256ee1c..69ce072 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -128,6 +128,14 @@
 
 static inline int dma_set_mask(struct device *dev, u64 dma_mask)
 {
+#ifdef CONFIG_DMABOUNCE
+	if (dev->archdata.dmabounce) {
+		if (dma_mask >= ISA_DMA_THRESHOLD)
+			return 0;
+		else
+			return -EIO;
+	}
+#endif
 	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
 		return -EIO;
 
diff --git a/arch/arm/include/asm/entry-macro-vic2.S b/arch/arm/include/asm/entry-macro-vic2.S
new file mode 100644
index 0000000..3ceb85e
--- /dev/null
+++ b/arch/arm/include/asm/entry-macro-vic2.S
@@ -0,0 +1,57 @@
+/* arch/arm/include/asm/entry-macro-vic2.S
+ *
+ * Originally arch/arm/mach-s3c6400/include/mach/entry-macro.S
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Low-level IRQ helper macros for a device with two VICs
+ *
+ * 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.
+*/
+
+/* This should be included from <mach/entry-macro.S> with the necessary
+ * defines for virtual addresses and IRQ bases for the two vics.
+ *
+ * The code needs the following defined:
+ *	IRQ_VIC0_BASE	IRQ number of VIC0's first IRQ
+ *	IRQ_VIC1_BASE	IRQ number of VIC1's first IRQ
+ *	VA_VIC0		Virtual address of VIC0
+ *	VA_VIC1		Virtual address of VIC1
+ *
+ * Note, code assumes VIC0's virtual address is an ARM immediate constant
+ * away from VIC1.
+*/
+
+#include <asm/hardware/vic.h>
+
+	.macro	disable_fiq
+	.endm
+
+	.macro	get_irqnr_preamble, base, tmp
+	ldr	\base, =VA_VIC0
+	.endm
+
+	.macro	arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+	@ check the vic0
+	mov	\irqnr, #IRQ_VIC0_BASE + 31
+	ldr	\irqstat, [ \base, # VIC_IRQ_STATUS ]
+	teq	\irqstat, #0
+
+	@ otherwise try vic1
+	addeq	\tmp, \base, #(VA_VIC1 - VA_VIC0)
+	addeq	\irqnr, \irqnr, #(IRQ_VIC1_BASE - IRQ_VIC0_BASE)
+	ldreq	\irqstat, [ \tmp, # VIC_IRQ_STATUS ]
+	teqeq	\irqstat, #0
+
+	clzne	\irqstat, \irqstat
+	subne	\irqnr, \irqnr, \irqstat
+	.endm
diff --git a/arch/arm/include/asm/hardware/iop3xx-adma.h b/arch/arm/include/asm/hardware/iop3xx-adma.h
index 1a8c727..9b28f12 100644
--- a/arch/arm/include/asm/hardware/iop3xx-adma.h
+++ b/arch/arm/include/asm/hardware/iop3xx-adma.h
@@ -366,8 +366,7 @@
 		slot_cnt += *slots_per_op;
 	}
 
-	if (len)
-		slot_cnt += *slots_per_op;
+	slot_cnt += *slots_per_op;
 
 	return slot_cnt;
 }
@@ -389,8 +388,7 @@
 		slot_cnt += *slots_per_op;
 	}
 
-	if (len)
-		slot_cnt += *slots_per_op;
+	slot_cnt += *slots_per_op;
 
 	return slot_cnt;
 }
@@ -737,10 +735,8 @@
 			i += slots_per_op;
 		} while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
 
-		if (len) {
-			iter = iop_hw_desc_slot_idx(hw_desc, i);
-			iter->byte_count = len;
-		}
+		iter = iop_hw_desc_slot_idx(hw_desc, i);
+		iter->byte_count = len;
 	}
 }
 
diff --git a/arch/arm/include/asm/hardware/it8152.h b/arch/arm/include/asm/hardware/it8152.h
index 74b5fff..6700c7f 100644
--- a/arch/arm/include/asm/hardware/it8152.h
+++ b/arch/arm/include/asm/hardware/it8152.h
@@ -75,6 +75,18 @@
   IT8152_PD_IRQ(1)  USB (USBR)
   IT8152_PD_IRQ(0)  Audio controller (ACR)
  */
+#define IT8152_IRQ(x)   (IRQ_BOARD_END + (x))
+
+/* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
+#define IT8152_LD_IRQ_COUNT     9
+#define IT8152_LP_IRQ_COUNT     16
+#define IT8152_PD_IRQ_COUNT     15
+
+/* Priorities: */
+#define IT8152_PD_IRQ(i)        IT8152_IRQ(i)
+#define IT8152_LP_IRQ(i)        (IT8152_IRQ(i) + IT8152_PD_IRQ_COUNT)
+#define IT8152_LD_IRQ(i)        (IT8152_IRQ(i) + IT8152_PD_IRQ_COUNT + IT8152_LP_IRQ_COUNT)
+
 /* frequently used interrupts */
 #define IT8152_PCISERR		IT8152_PD_IRQ(14)
 #define IT8152_H2PTADR		IT8152_PD_IRQ(13)
diff --git a/arch/arm/include/asm/hardware/locomo.h b/arch/arm/include/asm/hardware/locomo.h
index 954b1be..74e51d6b 100644
--- a/arch/arm/include/asm/hardware/locomo.h
+++ b/arch/arm/include/asm/hardware/locomo.h
@@ -214,4 +214,8 @@
 /* Frontlight control */
 void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf);
 
+struct locomo_platform_data {
+	int	irq_base;	/* IRQ base for cascaded on-chip IRQs */
+};
+
 #endif
diff --git a/arch/arm/include/asm/hardware/sa1111.h b/arch/arm/include/asm/hardware/sa1111.h
index 5da2595..92ed254 100644
--- a/arch/arm/include/asm/hardware/sa1111.h
+++ b/arch/arm/include/asm/hardware/sa1111.h
@@ -578,4 +578,8 @@
 void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v);
 void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v);
 
+struct sa1111_platform_data {
+	int	irq_base;	/* base for cascaded on-chip IRQs */
+};
+
 #endif  /* _ASM_ARCH_SA1111 */
diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h
index 226cddd..4798011 100644
--- a/arch/arm/include/asm/pci.h
+++ b/arch/arm/include/asm/pci.h
@@ -30,17 +30,6 @@
  */
 #define PCI_DMA_BUS_IS_PHYS     (1)
 
-/*
- * Whether pci_unmap_{single,page} is a nop depends upon the
- * configuration.
- */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)		((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)		((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	(((PTR)->LEN_NAME) = (VAL))
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index eec6e89..9dcb11e 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -128,6 +128,8 @@
 
 #ifdef __KERNEL__
 
+#define arch_has_single_step()	(1)
+
 #define user_mode(regs)	\
 	(((regs)->ARM_cpsr & 0xf) == 0)
 
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index cf9cdaa2..dd2bf53 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -443,9 +443,12 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_OLD_MMAP
+#define __ARCH_WANT_SYS_OLD_SELECT
 
 #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
 #define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_UTIME
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 9314a2d..37ae301 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -91,7 +91,7 @@
 		CALL(sys_settimeofday)
 /* 80 */	CALL(sys_getgroups16)
 		CALL(sys_setgroups16)
-		CALL(OBSOLETE(old_select))	/* used by libc4 */
+		CALL(OBSOLETE(sys_old_select))	/* used by libc4 */
 		CALL(sys_symlink)
 		CALL(sys_ni_syscall)		/* was sys_lstat */
 /* 85 */	CALL(sys_readlink)
@@ -99,7 +99,7 @@
 		CALL(sys_swapon)
 		CALL(sys_reboot)
 		CALL(OBSOLETE(sys_old_readdir))	/* used by libc4 */
-/* 90 */	CALL(OBSOLETE(old_mmap))	/* used by libc4 */
+/* 90 */	CALL(OBSOLETE(sys_old_mmap))	/* used by libc4 */
 		CALL(sys_munmap)
 		CALL(sys_truncate)
 		CALL(sys_ftruncate)
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index c54ceb3..3875d99 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -965,7 +965,7 @@
 	 */
 	armv6_pmcr_write(pmcr);
 
-	data.addr = 0;
+	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
 	for (idx = 0; idx <= armpmu->num_events; ++idx) {
@@ -1945,7 +1945,7 @@
 	 */
 	regs = get_irq_regs();
 
-	data.addr = 0;
+	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
 	for (idx = 0; idx <= armpmu->num_events; ++idx) {
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 08f899f..3f562a7 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -452,12 +452,23 @@
 		clear_breakpoint(child, &child->thread.debug.bp[i]);
 }
 
+void user_disable_single_step(struct task_struct *task)
+{
+	task->ptrace &= ~PT_SINGLESTEP;
+	ptrace_cancel_bpt(task);
+}
+
+void user_enable_single_step(struct task_struct *task)
+{
+	task->ptrace |= PT_SINGLESTEP;
+}
+
 /*
  * Called by kernel/ptrace.c when detaching..
  */
 void ptrace_disable(struct task_struct *child)
 {
-	single_step_disable(child);
+	user_disable_single_step(child);
 }
 
 /*
@@ -753,53 +764,6 @@
 			ret = ptrace_write_user(child, addr, data);
 			break;
 
-		/*
-		 * continue/restart and stop at next (return from) syscall
-		 */
-		case PTRACE_SYSCALL:
-		case PTRACE_CONT:
-			ret = -EIO;
-			if (!valid_signal(data))
-				break;
-			if (request == PTRACE_SYSCALL)
-				set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			else
-				clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			child->exit_code = data;
-			single_step_disable(child);
-			wake_up_process(child);
-			ret = 0;
-			break;
-
-		/*
-		 * make the child exit.  Best I can do is send it a sigkill.
-		 * perhaps it should be put in the status that it wants to
-		 * exit.
-		 */
-		case PTRACE_KILL:
-			single_step_disable(child);
-			if (child->exit_state != EXIT_ZOMBIE) {
-				child->exit_code = SIGKILL;
-				wake_up_process(child);
-			}
-			ret = 0;
-			break;
-
-		/*
-		 * execute single instruction.
-		 */
-		case PTRACE_SINGLESTEP:
-			ret = -EIO;
-			if (!valid_signal(data))
-				break;
-			single_step_enable(child);
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			child->exit_code = data;
-			/* give it a chance to run. */
-			wake_up_process(child);
-			ret = 0;
-			break;
-
 		case PTRACE_GETREGS:
 			ret = ptrace_getregs(child, (void __user *)data);
 			break;
diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h
index def3b61..3926605 100644
--- a/arch/arm/kernel/ptrace.h
+++ b/arch/arm/kernel/ptrace.h
@@ -14,20 +14,6 @@
 extern void ptrace_break(struct task_struct *, struct pt_regs *);
 
 /*
- * make sure single-step breakpoint is gone.
- */
-static inline void single_step_disable(struct task_struct *task)
-{
-	task->ptrace &= ~PT_SINGLESTEP;
-	ptrace_cancel_bpt(task);
-}
-
-static inline void single_step_enable(struct task_struct *task)
-{
-	task->ptrace |= PT_SINGLESTEP;
-}
-
-/*
  * Send SIGTRAP if we're single-stepping
  */
 static inline void single_step_trap(struct task_struct *task)
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index ae4027b..4350f75 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -28,135 +28,6 @@
 #include <linux/ipc.h>
 #include <linux/uaccess.h>
 
-struct mmap_arg_struct {
-	unsigned long addr;
-	unsigned long len;
-	unsigned long prot;
-	unsigned long flags;
-	unsigned long fd;
-	unsigned long offset;
-};
-
-asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
-{
-	int error = -EFAULT;
-	struct mmap_arg_struct a;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		goto out;
-
-	error = -EINVAL;
-	if (a.offset & ~PAGE_MASK)
-		goto out;
-
-	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
-out:
-	return error;
-}
-
-/*
- * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls.
- */
-
-struct sel_arg_struct {
-	unsigned long n;
-	fd_set __user *inp, *outp, *exp;
-	struct timeval __user *tvp;
-};
-
-asmlinkage int old_select(struct sel_arg_struct __user *arg)
-{
-	struct sel_arg_struct a;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-	/* sys_select() does the appropriate kernel locking */
-	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-}
-
-#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage int sys_ipc(uint call, int first, int second, int third,
-		       void __user *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL);
-	case SEMTIMEDOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
-					(const struct timespec __user *)fifth);
-
-	case SEMGET:
-		return sys_semget (first, second, third);
-	case SEMCTL: {
-		union semun fourth;
-		if (!ptr)
-			return -EINVAL;
-		if (get_user(fourth.__pad, (void __user * __user *) ptr))
-			return -EFAULT;
-		return sys_semctl (first, second, third, fourth);
-	}
-
-	case MSGSND:
-		return sys_msgsnd(first, (struct msgbuf __user *) ptr, 
-				  second, third);
-	case MSGRCV:
-		switch (version) {
-		case 0: {
-			struct ipc_kludge tmp;
-			if (!ptr)
-				return -EINVAL;
-			if (copy_from_user(&tmp,(struct ipc_kludge __user *)ptr,
-					   sizeof (tmp)))
-				return -EFAULT;
-			return sys_msgrcv (first, tmp.msgp, second,
-					   tmp.msgtyp, third);
-		}
-		default:
-			return sys_msgrcv (first,
-					   (struct msgbuf __user *) ptr,
-					   second, fifth, third);
-		}
-	case MSGGET:
-		return sys_msgget ((key_t) first, second);
-	case MSGCTL:
-		return sys_msgctl(first, second, (struct msqid_ds __user *)ptr);
-
-	case SHMAT:
-		switch (version) {
-		default: {
-			ulong raddr;
-			ret = do_shmat(first, (char __user *)ptr, second, &raddr);
-			if (ret)
-				return ret;
-			return put_user(raddr, (ulong __user *)third);
-		}
-		case 1: /* Of course, we don't support iBCS2! */
-			return -EINVAL;
-		}
-	case SHMDT: 
-		return sys_shmdt ((char __user *)ptr);
-	case SHMGET:
-		return sys_shmget (first, second, third);
-	case SHMCTL:
-		return sys_shmctl (first, second,
-				   (struct shmid_ds __user *) ptr);
-	default:
-		return -ENOSYS;
-	}
-}
-#endif
-
 /* Fork a new task - this creates a new program thread.
  * This is called indirectly via a small wrapper
  */
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index d59a0cd..33ff678 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -346,9 +346,6 @@
 	return sys_oabi_semtimedop(semid, tsops, nsops, NULL);
 }
 
-extern asmlinkage int sys_ipc(uint call, int first, int second, int third,
-			      void __user *ptr, long fifth);
-
 asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third,
 			    void __user *ptr, long fifth)
 {
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index 786ac2b..50292cd 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -359,7 +359,9 @@
 		frame.fp = regs->ARM_fp;
 		frame.sp = regs->ARM_sp;
 		frame.lr = regs->ARM_lr;
-		frame.pc = regs->ARM_pc;
+		/* PC might be corrupted, use LR in that case. */
+		frame.pc = kernel_text_address(regs->ARM_pc)
+			 ? regs->ARM_pc : regs->ARM_lr;
 	} else if (tsk == current) {
 		frame.fp = (unsigned long)__builtin_frame_address(0);
 		frame.sp = current_sp;
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index 309f351..2500f41 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -58,6 +58,12 @@
 {
 	u32	sr = at91_sys_read(AT91_ST_SR) & irqmask;
 
+	/*
+	 * irqs should be disabled here, but as the irq is shared they are only
+	 * guaranteed to be off if the timer irq is registered first.
+	 */
+	WARN_ON_ONCE(!irqs_disabled());
+
 	/* simulate "oneshot" timer with alarm */
 	if (sr & AT91_ST_ALMS) {
 		clkevt.event_handler(&clkevt);
@@ -132,24 +138,11 @@
 static int
 clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
 {
-	unsigned long	flags;
 	u32		alm;
 	int		status = 0;
 
 	BUG_ON(delta < 2);
 
-	/* Use "raw" primitives so we behave correctly on RT kernels. */
-	raw_local_irq_save(flags);
-
-	/*
-	 * According to Thomas Gleixner irqs are already disabled here.  Simply
-	 * removing raw_local_irq_save above (and the matching
-	 * raw_local_irq_restore) was not accepted.  See
-	 * http://thread.gmane.org/gmane.linux.ports.arm.kernel/41174
-	 * So for now (2008-11-20) just warn once if irqs were not disabled ...
-	 */
-	WARN_ON_ONCE(!raw_irqs_disabled_flags(flags));
-
 	/* The alarm IRQ uses absolute time (now+delta), not the relative
 	 * time (delta) in our calling convention.  Like all clockevents
 	 * using such "match" hardware, we have a race to defend against.
@@ -169,7 +162,6 @@
 	alm += delta;
 	at91_sys_write(AT91_ST_RTAR, alm);
 
-	raw_local_irq_restore(flags);
 	return status;
 }
 
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 4bd56ae..608a632 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -62,16 +62,12 @@
 static void
 pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 {
-	unsigned long	flags;
-
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		/* update clocksource counter, then enable the IRQ */
-		raw_local_irq_save(flags);
+		/* update clocksource counter */
 		pit_cnt += pit_cycle * PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
 		at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN
 				| AT91_PIT_PITIEN);
-		raw_local_irq_restore(flags);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		BUG();
@@ -100,6 +96,11 @@
  */
 static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
 {
+	/*
+	 * irqs should be disabled here, but as the irq is shared they are only
+	 * guaranteed to be off if the timer irq is registered first.
+	 */
+	WARN_ON_ONCE(!irqs_disabled());
 
 	/* The PIT interrupt may be disabled, and is shared */
 	if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC)
diff --git a/arch/arm/mach-at91/include/mach/at91_mci.h b/arch/arm/mach-at91/include/mach/at91_mci.h
index 550d503..57f8ee1 100644
--- a/arch/arm/mach-at91/include/mach/at91_mci.h
+++ b/arch/arm/mach-at91/include/mach/at91_mci.h
@@ -77,7 +77,7 @@
 
 #define AT91_MCI_BLKR		0x18		/* Block Register */
 #define		AT91_MCI_BLKR_BCNT(n)	((0xffff & (n)) << 0)	/* Block count */
-#define		AT91_MCI_BLKR_BLKLEN(n)	((0xffff & (n)) << 16)	/* Block lenght */
+#define		AT91_MCI_BLKR_BLKLEN(n)	((0xffff & (n)) << 16)	/* Block length */
 
 #define AT91_MCI_RSPR(n)	(0x20 + ((n) * 4))	/* Response Registers 0-3 */
 #define AT91_MCR_RDR		0x30		/* Receive Data Register */
diff --git a/arch/arm/mach-davinci/include/mach/i2c.h b/arch/arm/mach-davinci/include/mach/i2c.h
index 39fdcea..2312d19 100644
--- a/arch/arm/mach-davinci/include/mach/i2c.h
+++ b/arch/arm/mach-davinci/include/mach/i2c.h
@@ -1,5 +1,5 @@
 /*
- * DaVinci I2C controller platfrom_device info
+ * DaVinci I2C controller platform_device info
  *
  * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
  *
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 806972a..5da2cf4 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -605,7 +605,7 @@
 	.dev		= {
 		.dma_mask		= &dove_xor0_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(64),
-		.platform_data		= (void *)&dove_xor00_data,
+		.platform_data		= &dove_xor00_data,
 	},
 };
 
@@ -631,7 +631,7 @@
 	.dev		= {
 		.dma_mask		= &dove_xor0_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(64),
-		.platform_data		= (void *)&dove_xor01_data,
+		.platform_data		= &dove_xor01_data,
 	},
 };
 
@@ -704,7 +704,7 @@
 	.dev		= {
 		.dma_mask		= &dove_xor1_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(64),
-		.platform_data		= (void *)&dove_xor10_data,
+		.platform_data		= &dove_xor10_data,
 	},
 };
 
@@ -730,7 +730,7 @@
 	.dev		= {
 		.dma_mask		= &dove_xor1_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(64),
-		.platform_data		= (void *)&dove_xor11_data,
+		.platform_data		= &dove_xor11_data,
 	},
 };
 
diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
index 3bd934e..93107d8 100644
--- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h
+++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
@@ -65,6 +65,8 @@
 #define TS72XX_RTC_DATA_PHYS_BASE	0x11700000
 #define TS72XX_RTC_DATA_SIZE		0x00001000
 
+#define TS72XX_WDT_CONTROL_PHYS_BASE	0x23800000
+#define TS72XX_WDT_FEED_PHYS_BASE	0x23c00000
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c
index f3757a1..c33360e8 100644
--- a/arch/arm/mach-ep93xx/micro9.c
+++ b/arch/arm/mach-ep93xx/micro9.c
@@ -28,7 +28,7 @@
  *
  * Micro9-High has up to 64MB of 32-bit flash on CS1
  * Micro9-Mid has up to 64MB of either 32-bit or 16-bit flash on CS1
- * Micro9-Lite uses a seperate MTD map driver for flash support
+ * Micro9-Lite uses a separate MTD map driver for flash support
  * Micro9-Slim has up to 64MB of either 32-bit or 16-bit flash on CS1
  *************************************************************************/
 static struct physmap_flash_data micro9_flash_data;
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 259f782..fac1ec7 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -166,6 +166,26 @@
 	.num_resources	= 0,
 };
 
+static struct resource ts72xx_wdt_resources[] = {
+	{
+		.start	= TS72XX_WDT_CONTROL_PHYS_BASE,
+		.end	= TS72XX_WDT_CONTROL_PHYS_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= TS72XX_WDT_FEED_PHYS_BASE,
+		.end	= TS72XX_WDT_FEED_PHYS_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device ts72xx_wdt_device = {
+	.name		= "ts72xx-wdt",
+	.id		= -1,
+	.num_resources 	= ARRAY_SIZE(ts72xx_wdt_resources),
+	.resource	= ts72xx_wdt_resources,
+};
+
 static struct ep93xx_eth_data ts72xx_eth_data = {
 	.phy_id		= 1,
 };
@@ -175,6 +195,7 @@
 	ep93xx_init_devices();
 	ts72xx_register_flash();
 	platform_device_register(&ts72xx_rtc_device);
+	platform_device_register(&ts72xx_wdt_device);
 
 	ep93xx_register_eth(&ts72xx_eth_data, 1);
 }
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index c4a0159..e318153 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -502,32 +502,6 @@
 	return pci_scan_bus(sys->busnr, &ixp4xx_ops, sys);
 }
 
-/*
- * We override these so we properly do dmabounce otherwise drivers
- * are able to set the dma_mask to 0xffffffff and we can no longer
- * trap bounces. :(
- *
- * We just return true on everyhing except for < 64MB in which case 
- * we will fail miseralby and die since we can't handle that case.
- */
-int
-pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	if (mask >= SZ_64M - 1 )
-		return 0;
-
-	return -EIO;
-}
-    
-int
-pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	if (mask >= SZ_64M - 1 )
-		return 0;
-
-	return -EIO;
-}
-
 EXPORT_SYMBOL(ixp4xx_pci_read);
 EXPORT_SYMBOL(ixp4xx_pci_write);
 
diff --git a/arch/arm/mach-ixp4xx/include/mach/hardware.h b/arch/arm/mach-ixp4xx/include/mach/hardware.h
index f9d1c43..f91ca6d 100644
--- a/arch/arm/mach-ixp4xx/include/mach/hardware.h
+++ b/arch/arm/mach-ixp4xx/include/mach/hardware.h
@@ -26,11 +26,6 @@
 #define PCIBIOS_MAX_MEM		0x4BFFFFFF
 #endif
 
-/*
- * We override the standard dma-mask routines for bouncing.
- */
-#define	HAVE_ARCH_PCI_SET_DMA_MASK
-
 #define pcibios_assign_all_busses()	1
 
 /* Register locations and bits */
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index f6c6196..17879a8 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -32,6 +32,12 @@
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell SheevaPlug Reference Board.
 
+config MACH_ESATA_SHEEVAPLUG
+	bool "Marvell eSATA SheevaPlug Reference Board"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Marvell eSATA SheevaPlug Reference Board.
+
 config MACH_TS219
 	bool "QNAP TS-110, TS-119, TS-210, TS-219 and TS-219P Turbo NAS"
 	help
@@ -46,18 +52,35 @@
 	  QNAP TS-410, TS-410U, TS-419P and TS-419U Turbo NAS
 	  devices.
 
+config MACH_OPENRD
+        bool
+
 config MACH_OPENRD_BASE
 	bool "Marvell OpenRD Base Board"
+	select MACH_OPENRD
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell OpenRD Base Board.
 
+config MACH_OPENRD_CLIENT
+	bool "Marvell OpenRD Client Board"
+	select MACH_OPENRD
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Marvell OpenRD Client Board.
+
 config MACH_NETSPACE_V2
 	bool "LaCie Network Space v2 NAS Board"
 	help
 	  Say 'Y' here if you want your kernel to support the
 	  LaCie Network Space v2 NAS.
 
+config MACH_INETSPACE_V2
+	bool "LaCie Internet Space v2 NAS Board"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  LaCie Internet Space v2 NAS.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index d4d7f53..a5530e3 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -5,9 +5,11 @@
 obj-$(CONFIG_MACH_RD88F6281)		+= rd88f6281-setup.o
 obj-$(CONFIG_MACH_MV88F6281GTW_GE)	+= mv88f6281gtw_ge-setup.o
 obj-$(CONFIG_MACH_SHEEVAPLUG)		+= sheevaplug-setup.o
+obj-$(CONFIG_MACH_ESATA_SHEEVAPLUG)	+= sheevaplug-setup.o
 obj-$(CONFIG_MACH_TS219)		+= ts219-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_TS41X)		+= ts41x-setup.o tsx1x-common.o
-obj-$(CONFIG_MACH_OPENRD_BASE)		+= openrd_base-setup.o
+obj-$(CONFIG_MACH_OPENRD)		+= openrd-setup.o
 obj-$(CONFIG_MACH_NETSPACE_V2)		+= netspace_v2-setup.o
+obj-$(CONFIG_MACH_INETSPACE_V2)		+= netspace_v2-setup.o
 
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 242dd07..f759ca2 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -656,7 +656,7 @@
 	.dev		= {
 		.dma_mask		= &kirkwood_xor_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(64),
-		.platform_data		= (void *)&kirkwood_xor00_data,
+		.platform_data		= &kirkwood_xor00_data,
 	},
 };
 
@@ -682,7 +682,7 @@
 	.dev		= {
 		.dma_mask		= &kirkwood_xor_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(64),
-		.platform_data		= (void *)&kirkwood_xor01_data,
+		.platform_data		= &kirkwood_xor01_data,
 	},
 };
 
@@ -755,7 +755,7 @@
 	.dev		= {
 		.dma_mask		= &kirkwood_xor_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(64),
-		.platform_data		= (void *)&kirkwood_xor10_data,
+		.platform_data		= &kirkwood_xor10_data,
 	},
 };
 
@@ -781,7 +781,7 @@
 	.dev		= {
 		.dma_mask		= &kirkwood_xor_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(64),
-		.platform_data		= (void *)&kirkwood_xor11_data,
+		.platform_data		= &kirkwood_xor11_data,
 	},
 };
 
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
index 9a06406..3ae158d 100644
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -182,8 +182,14 @@
 
 static struct gpio_led netspace_v2_gpio_led_pins[] = {
 	{
-		.name	= "ns_v2:red:fail",
-		.gpio	= NETSPACE_V2_GPIO_RED_LED,
+		.name			= "ns_v2:blue:sata",
+		.default_trigger	= "default-on",
+		.gpio			= NETSPACE_V2_GPIO_BLUE_LED_CMD,
+		.active_low		= 1,
+	},
+	{
+		.name			= "ns_v2:red:fail",
+		.gpio			= NETSPACE_V2_GPIO_RED_LED,
 	},
 };
 
@@ -202,30 +208,19 @@
 
 static void __init netspace_v2_gpio_leds_init(void)
 {
+	int err;
+
+	/* Configure register slow_led to allow SATA activity LED blinking */
+	err = gpio_request(NETSPACE_V2_GPIO_BLUE_LED_SLOW, "blue LED slow");
+	if (err == 0) {
+		err = gpio_direction_output(NETSPACE_V2_GPIO_BLUE_LED_SLOW, 0);
+		if (err)
+			gpio_free(NETSPACE_V2_GPIO_BLUE_LED_SLOW);
+	}
+	if (err)
+		pr_err("netspace_v2: failed to configure blue LED slow GPIO\n");
+
 	platform_device_register(&netspace_v2_gpio_leds);
-
-	/*
-	 * Configure the front blue LED to blink in relation with the SATA
-	 * activity.
-	 */
-	if (gpio_request(NETSPACE_V2_GPIO_BLUE_LED_SLOW,
-			 "SATA blue LED slow") != 0)
-		return;
-	if (gpio_direction_output(NETSPACE_V2_GPIO_BLUE_LED_SLOW, 0) != 0)
-		goto err_free_1;
-	if (gpio_request(NETSPACE_V2_GPIO_BLUE_LED_CMD,
-			 "SATA blue LED command") != 0)
-		goto err_free_1;
-	if (gpio_direction_output(NETSPACE_V2_GPIO_BLUE_LED_CMD, 0) != 0)
-		goto err_free_2;
-
-	return;
-
-err_free_2:
-	gpio_free(NETSPACE_V2_GPIO_BLUE_LED_CMD);
-err_free_1:
-	gpio_free(NETSPACE_V2_GPIO_BLUE_LED_SLOW);
-	pr_err("netspace_v2: failed to configure SATA blue LED\n");
 }
 
 /*****************************************************************************
@@ -314,6 +309,7 @@
 		pr_err("netspace_v2: failed to configure power-off GPIO\n");
 }
 
+#ifdef CONFIG_MACH_NETSPACE_V2
 MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
 	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
 	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
@@ -323,3 +319,16 @@
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &netspace_v2_timer,
 MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_INETSPACE_V2
+MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
+	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
+	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= netspace_v2_init,
+	.map_io		= kirkwood_map_io,
+	.init_irq	= kirkwood_init_irq,
+	.timer		= &netspace_v2_timer,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
new file mode 100644
index 0000000..ad3f1ec
--- /dev/null
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -0,0 +1,118 @@
+/*
+ * arch/arm/mach-kirkwood/openrd-setup.c
+ *
+ * Marvell OpenRD (Base|Client) 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/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include <plat/mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mtd_partition openrd_nand_parts[] = {
+	{
+		.name		= "u-boot",
+		.offset		= 0,
+		.size		= SZ_1M,
+		.mask_flags	= MTD_WRITEABLE
+	}, {
+		.name		= "uImage",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= SZ_4M
+	}, {
+		.name		= "root",
+		.offset		= MTDPART_OFS_NXTBLK,
+		.size		= MTDPART_SIZ_FULL
+	},
+};
+
+static struct mv643xx_eth_platform_data openrd_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
+};
+
+static struct mv643xx_eth_platform_data openrd_ge01_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(24),
+};
+
+static struct mv_sata_platform_data openrd_sata_data = {
+	.n_ports	= 2,
+};
+
+static struct mvsdio_platform_data openrd_mvsdio_data = {
+	.gpio_card_detect = 29,	/* MPP29 used as SD card detect */
+};
+
+static unsigned int openrd_mpp_config[] __initdata = {
+	MPP29_GPIO,
+	0
+};
+
+static void __init openrd_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_init();
+	kirkwood_mpp_conf(openrd_mpp_config);
+
+	kirkwood_uart0_init();
+	kirkwood_nand_init(ARRAY_AND_SIZE(openrd_nand_parts), 25);
+
+	kirkwood_ehci_init();
+
+	kirkwood_ge00_init(&openrd_ge00_data);
+	if (machine_is_openrd_client())
+		kirkwood_ge01_init(&openrd_ge01_data);
+	kirkwood_sata_init(&openrd_sata_data);
+	kirkwood_sdio_init(&openrd_mvsdio_data);
+
+	kirkwood_i2c_init();
+}
+
+static int __init openrd_pci_init(void)
+{
+	if (machine_is_openrd_base() || machine_is_openrd_client())
+		kirkwood_pcie_init();
+
+	return 0;
+}
+subsys_initcall(openrd_pci_init);
+
+#ifdef CONFIG_MACH_OPENRD_BASE
+MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
+	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
+	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
+	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= openrd_init,
+	.map_io		= kirkwood_map_io,
+	.init_irq	= kirkwood_init_irq,
+	.timer		= &kirkwood_timer,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_OPENRD_CLIENT
+MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
+	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
+	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
+	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= openrd_init,
+	.map_io		= kirkwood_map_io,
+	.init_irq	= kirkwood_init_irq,
+	.timer		= &kirkwood_timer,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-kirkwood/openrd_base-setup.c b/arch/arm/mach-kirkwood/openrd_base-setup.c
deleted file mode 100644
index 77617c7..0000000
--- a/arch/arm/mach-kirkwood/openrd_base-setup.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/openrd_base-setup.c
- *
- * Marvell OpenRD Base 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/mtd/partitions.h>
-#include <linux/ata_platform.h>
-#include <linux/mv643xx_eth.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/kirkwood.h>
-#include <plat/mvsdio.h>
-#include "common.h"
-#include "mpp.h"
-
-static struct mtd_partition openrd_base_nand_parts[] = {
-	{
-		.name = "u-boot",
-		.offset = 0,
-		.size = SZ_1M
-	}, {
-		.name = "uImage",
-		.offset = MTDPART_OFS_NXTBLK,
-		.size = SZ_4M
-	}, {
-		.name = "root",
-		.offset = MTDPART_OFS_NXTBLK,
-		.size = MTDPART_SIZ_FULL
-	},
-};
-
-static struct mv643xx_eth_platform_data openrd_base_ge00_data = {
-	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
-};
-
-static struct mv_sata_platform_data openrd_base_sata_data = {
-	.n_ports	= 2,
-};
-
-static struct mvsdio_platform_data openrd_base_mvsdio_data = {
-	.gpio_card_detect = 29,	/* MPP29 used as SD card detect */
-};
-
-static unsigned int openrd_base_mpp_config[] __initdata = {
-	MPP29_GPIO,
-	0
-};
-
-static void __init openrd_base_init(void)
-{
-	/*
-	 * Basic setup. Needs to be called early.
-	 */
-	kirkwood_init();
-	kirkwood_mpp_conf(openrd_base_mpp_config);
-
-	kirkwood_uart0_init();
-	kirkwood_nand_init(ARRAY_AND_SIZE(openrd_base_nand_parts), 25);
-
-	kirkwood_ehci_init();
-
-	kirkwood_ge00_init(&openrd_base_ge00_data);
-	kirkwood_sata_init(&openrd_base_sata_data);
-	kirkwood_sdio_init(&openrd_base_mvsdio_data);
-
-	kirkwood_i2c_init();
-}
-
-static int __init openrd_base_pci_init(void)
-{
-	if (machine_is_openrd_base())
-		kirkwood_pcie_init();
-
-	return 0;
- }
-subsys_initcall(openrd_base_pci_init);
-
-
-MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
-	/* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */
-	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
-	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
-	.boot_params	= 0x00000100,
-	.init_machine	= openrd_base_init,
-	.map_io		= kirkwood_map_io,
-	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
-MACHINE_END
diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
index c7319ee..a00879d 100644
--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
+++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/ata_platform.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/gpio.h>
@@ -42,10 +43,19 @@
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
 };
 
+static struct mv_sata_platform_data sheeva_esata_sata_data = {
+	.n_ports	= 2,
+};
+
 static struct mvsdio_platform_data sheevaplug_mvsdio_data = {
 	/* unfortunately the CD signal has not been connected */
 };
 
+static struct mvsdio_platform_data sheeva_esata_mvsdio_data = {
+	.gpio_write_protect = 44, /* MPP44 used as SD write protect */
+	.gpio_card_detect = 47,	  /* MPP47 used as SD card detect */
+};
+
 static struct gpio_led sheevaplug_led_pins[] = {
 	{
 		.name			= "plug:green:health",
@@ -74,13 +84,26 @@
 	0
 };
 
+static unsigned int sheeva_esata_mpp_config[] __initdata = {
+	MPP29_GPIO,	/* USB Power Enable */
+	MPP44_GPIO,	/* SD Write Protect */
+	MPP47_GPIO,	/* SD Card Detect */
+	MPP49_GPIO,	/* LED Green */
+	0
+};
+
 static void __init sheevaplug_init(void)
 {
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
 	kirkwood_init();
-	kirkwood_mpp_conf(sheevaplug_mpp_config);
+
+	/* setup gpio pin select */
+	if (machine_is_sheeva_esata())
+		kirkwood_mpp_conf(sheeva_esata_mpp_config);
+	else
+		kirkwood_mpp_conf(sheevaplug_mpp_config);
 
 	kirkwood_uart0_init();
 	kirkwood_nand_init(ARRAY_AND_SIZE(sheevaplug_nand_parts), 25);
@@ -91,11 +114,21 @@
 	kirkwood_ehci_init();
 
 	kirkwood_ge00_init(&sheevaplug_ge00_data);
-	kirkwood_sdio_init(&sheevaplug_mvsdio_data);
+
+	/* honor lower power consumption for plugs with out eSATA */
+	if (machine_is_sheeva_esata())
+		kirkwood_sata_init(&sheeva_esata_sata_data);
+
+	/* enable sd wp and sd cd on plugs with esata */
+	if (machine_is_sheeva_esata())
+		kirkwood_sdio_init(&sheeva_esata_mvsdio_data);
+	else
+		kirkwood_sdio_init(&sheevaplug_mvsdio_data);
 
 	platform_device_register(&sheevaplug_leds);
 }
 
+#ifdef CONFIG_MACH_SHEEVAPLUG
 MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
 	/* Maintainer: shadi Ammouri <shadi@marvell.com> */
 	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
@@ -106,3 +139,16 @@
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_ESATA_SHEEVAPLUG
+MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
+	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
+	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= sheevaplug_init,
+	.map_io		= kirkwood_map_io,
+	.init_irq	= kirkwood_init_irq,
+	.timer		= &kirkwood_timer,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index c6a564f..6ab843e 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -1,6 +1,6 @@
 if ARCH_MMP
 
-menu "Marvell PXA168/910 Implmentations"
+menu "Marvell PXA168/910/MMP2 Implmentations"
 
 config MACH_ASPENITE
 	bool "Marvell's PXA168 Aspenite Development Board"
@@ -16,6 +16,13 @@
 	  Say 'Y' here if you want to support the Marvell PXA168-based
 	  Zylonite2 Development Board.
 
+config MACH_AVENGERS_LITE
+	bool "Marvell's PXA168 Avengers Lite Development Board"
+	select CPU_PXA168
+	help
+	  Say 'Y' here if you want to support the Marvell PXA168-based
+	  Avengers Lite Development Board.
+
 config MACH_TAVOREVB
 	bool "Marvell's PXA910 TavorEVB Development Board"
 	select CPU_PXA910
@@ -30,6 +37,26 @@
 	  Say 'Y' here if you want to support the Marvell PXA910-based
 	  TTC_DKB Development Board.
 
+config MACH_FLINT
+	bool "Marvell's Flint Development Platform"
+	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.
+
+config MACH_MARVELL_JASPER
+	bool "Marvell's Jasper Development Platform"
+	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.
+
 endmenu
 
 config CPU_PXA168
@@ -44,4 +71,10 @@
 	help
 	  Select code specific to PXA910
 
+config CPU_MMP2
+	bool
+	select CPU_V6
+	select CPU_32v6K
+	help
+	  Select code specific to MMP2. MMP2 is ARMv6 compatible.
 endif
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 6883e65..8b66d06 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -2,14 +2,18 @@
 # Makefile for Marvell's PXA168 processors line
 #
 
-obj-y				+= common.o clock.o devices.o irq.o time.o
+obj-y				+= common.o clock.o devices.o time.o
 
 # SoC support
-obj-$(CONFIG_CPU_PXA168)	+= pxa168.o
-obj-$(CONFIG_CPU_PXA910)	+= pxa910.o
+obj-$(CONFIG_CPU_PXA168)	+= pxa168.o irq-pxa168.o
+obj-$(CONFIG_CPU_PXA910)	+= pxa910.o irq-pxa168.o
+obj-$(CONFIG_CPU_MMP2)		+= mmp2.o irq-mmp2.o
 
 # board support
 obj-$(CONFIG_MACH_ASPENITE)	+= aspenite.o
 obj-$(CONFIG_MACH_ZYLONITE2)	+= aspenite.o
+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_FLINT)	+= flint.o
+obj-$(CONFIG_MACH_MARVELL_JASPER) += jasper.o
diff --git a/arch/arm/mach-mmp/avengers_lite.c b/arch/arm/mach-mmp/avengers_lite.c
new file mode 100644
index 0000000..8c3fa5d1
--- /dev/null
+++ b/arch/arm/mach-mmp/avengers_lite.c
@@ -0,0 +1,51 @@
+/*
+ *  linux/arch/arm/mach-mmp/avengers_lite.c
+ *
+ *  Support for the Marvell PXA168-based Avengers lite 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 <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/addr-map.h>
+#include <mach/mfp-pxa168.h>
+#include <mach/pxa168.h>
+#include <mach/irqs.h>
+
+
+#include "common.h"
+#include <linux/delay.h>
+
+/* Avengers lite MFP configurations */
+static unsigned long avengers_lite_pin_config_V16F[] __initdata = {
+	/* DEBUG_UART */
+	GPIO88_UART2_TXD,
+	GPIO89_UART2_RXD,
+};
+
+static void __init avengers_lite_init(void)
+{
+	mfp_config(ARRAY_AND_SIZE(avengers_lite_pin_config_V16F));
+
+	/* on-chip devices */
+	pxa168_add_uart(2);
+}
+
+MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform")
+	.phys_io        = APB_PHYS_BASE,
+	.boot_params    = 0x00000100,
+	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
+	.map_io		= pxa_map_io,
+	.init_irq       = pxa168_init_irq,
+	.timer          = &pxa168_timer,
+	.init_machine   = avengers_lite_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h
index c33fbbc..b4a0ba0 100644
--- a/arch/arm/mach-mmp/common.h
+++ b/arch/arm/mach-mmp/common.h
@@ -3,11 +3,15 @@
 struct sys_timer;
 
 extern void timer_init(int irq);
+extern void mmp2_clear_pmic_int(void);
 
 extern struct sys_timer pxa168_timer;
 extern struct sys_timer pxa910_timer;
+extern struct sys_timer mmp2_timer;
 extern void __init pxa168_init_irq(void);
 extern void __init pxa910_init_irq(void);
+extern void __init mmp2_init_icu(void);
+extern void __init mmp2_init_irq(void);
 
 extern void __init icu_init_irq(void);
 extern void __init pxa_map_io(void);
diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c
new file mode 100644
index 0000000..4ec7709
--- /dev/null
+++ b/arch/arm/mach-mmp/flint.c
@@ -0,0 +1,123 @@
+/*
+ *  linux/arch/arm/mach-mmp/flint.c
+ *
+ *  Support for the Marvell Flint Development Platform.
+ *
+ *  Copyright (C) 2009 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/smc91x.h>
+#include <linux/io.h>
+#include <linux/gpio.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 "common.h"
+
+static unsigned long flint_pin_config[] __initdata = {
+	/* UART1 */
+	GPIO45_UART1_RXD,
+	GPIO46_UART1_TXD,
+
+	/* UART2 */
+	GPIO47_UART2_RXD,
+	GPIO48_UART2_TXD,
+
+	/* SMC */
+	GPIO151_SMC_SCLK,
+	GPIO145_SMC_nCS0,
+	GPIO146_SMC_nCS1,
+	GPIO152_SMC_BE0,
+	GPIO153_SMC_BE1,
+	GPIO154_SMC_IRQ,
+	GPIO113_SMC_RDY,
+
+	/*Ethernet*/
+	GPIO155_GPIO155,
+
+	/* 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,
+};
+
+static struct smc91x_platdata flint_smc91x_info = {
+	.flags  = SMC91X_USE_16BIT | SMC91X_NOWAIT,
+};
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start  = SMC_CS1_PHYS_BASE + 0x300,
+		.end    = SMC_CS1_PHYS_BASE + 0xfffff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = gpio_to_irq(155),
+		.end    = gpio_to_irq(155),
+		.flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	}
+};
+
+static struct platform_device smc91x_device = {
+	.name           = "smc91x",
+	.id             = 0,
+	.dev            = {
+		.platform_data = &flint_smc91x_info,
+	},
+	.num_resources  = ARRAY_SIZE(smc91x_resources),
+	.resource       = smc91x_resources,
+};
+
+static void __init flint_init(void)
+{
+	mfp_config(ARRAY_AND_SIZE(flint_pin_config));
+
+	/* on-chip devices */
+	mmp2_add_uart(1);
+	mmp2_add_uart(2);
+
+	/* off-chip devices */
+	platform_device_register(&smc91x_device);
+}
+
+MACHINE_START(FLINT, "Flint Development Platform")
+	.phys_io        = APB_PHYS_BASE,
+	.boot_params    = 0x00000100,
+	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
+	.map_io		= pxa_map_io,
+	.init_irq       = mmp2_init_irq,
+	.timer          = &mmp2_timer,
+	.init_machine   = flint_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/include/mach/cputype.h b/arch/arm/mach-mmp/include/mach/cputype.h
index 25e797b..83b1872 100644
--- a/arch/arm/mach-mmp/include/mach/cputype.h
+++ b/arch/arm/mach-mmp/include/mach/cputype.h
@@ -8,6 +8,7 @@
  *
  * PXA168    A0    0x41159263   0x56158400   0x00A0A333
  * PXA910    Y0    0x41159262   0x56158000   0x00F0C910
+ * MMP2	     Z0			0x560f5811
  */
 
 #ifdef CONFIG_CPU_PXA168
@@ -24,7 +25,15 @@
 #  define __cpu_is_pxa910(id)	(0)
 #endif
 
+#ifdef CONFIG_CPU_MMP2
+#  define __cpu_is_mmp2(id)	\
+	({ unsigned int _id = ((id) >> 8) & 0xff; _id == 0x58; })
+#else
+#  define __cpu_is_mmp2(id)	(0)
+#endif
+
 #define cpu_is_pxa168()		({ __cpu_is_pxa168(read_cpuid_id()); })
 #define cpu_is_pxa910()		({ __cpu_is_pxa910(read_cpuid_id()); })
+#define cpu_is_mmp2()		({ __cpu_is_mmp2(read_cpuid_id()); })
 
 #endif /* __ASM_MACH_CPUTYPE_H */
diff --git a/arch/arm/mach-mmp/include/mach/devices.h b/arch/arm/mach-mmp/include/mach/devices.h
index 2458539..1fa0a49 100644
--- a/arch/arm/mach-mmp/include/mach/devices.h
+++ b/arch/arm/mach-mmp/include/mach/devices.h
@@ -34,4 +34,16 @@
 	.size		= _size,					\
 	.dma		= { _dma },					\
 };
+
+#define MMP2_DEVICE(_name, _drv, _id, _irq, _start, _size, _dma...)	\
+struct pxa_device_desc mmp2_device_##_name __initdata = {		\
+	.dev_name	= "mmp2-" #_name,				\
+	.drv_name	= _drv,						\
+	.id		= _id,						\
+	.irq		= IRQ_MMP2_##_irq,				\
+	.start		= _start,					\
+	.size		= _size,					\
+	.dma		= { _dma },					\
+}
+
 extern int pxa_register_device(struct pxa_device_desc *, void *, size_t);
diff --git a/arch/arm/mach-mmp/include/mach/entry-macro.S b/arch/arm/mach-mmp/include/mach/entry-macro.S
index 6d3cd35..c42d9d4 100644
--- a/arch/arm/mach-mmp/include/mach/entry-macro.S
+++ b/arch/arm/mach-mmp/include/mach/entry-macro.S
@@ -15,7 +15,12 @@
 	.endm
 
 	.macro	get_irqnr_preamble, base, tmp
-	ldr	\base, =ICU_AP_IRQ_SEL_INT_NUM
+	mrc	p15, 0, \tmp, c0, c0, 0		@ CPUID
+	and	\tmp, \tmp, #0xff00
+	cmp	\tmp, #0x5800
+	ldr	\base, =ICU_VIRT_BASE
+	addne	\base, \base, #0x10c		@ PJ1 AP INT SEL register
+	addeq	\base, \base, #0x104		@ PJ4 IRQ SEL register
 	.endm
 
 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h
index d68871b..0270119 100644
--- a/arch/arm/mach-mmp/include/mach/irqs.h
+++ b/arch/arm/mach-mmp/include/mach/irqs.h
@@ -113,10 +113,119 @@
 #define IRQ_PXA910_AP_PMU		60
 #define IRQ_PXA910_SM_INT		63	/* from PinMux */
 
-#define IRQ_GPIO_START			64
-#define IRQ_GPIO_NUM			128
+/*
+ * Interrupt numbers for MMP2
+ */
+#define IRQ_MMP2_NONE			(-1)
+#define IRQ_MMP2_SSP1			0
+#define IRQ_MMP2_SSP2			1
+#define IRQ_MMP2_SSPA1			2
+#define IRQ_MMP2_SSPA2			3
+#define IRQ_MMP2_PMIC_MUX		4	/* PMIC & Charger */
+#define IRQ_MMP2_RTC_MUX		5
+#define IRQ_MMP2_TWSI1			7
+#define IRQ_MMP2_GPU			8
+#define IRQ_MMP2_KEYPAD			9
+#define IRQ_MMP2_ROTARY			10
+#define IRQ_MMP2_TRACKBALL		11
+#define IRQ_MMP2_ONEWIRE		12
+#define IRQ_MMP2_TIMER1			13
+#define IRQ_MMP2_TIMER2			14
+#define IRQ_MMP2_TIMER3			15
+#define IRQ_MMP2_RIPC			16
+#define IRQ_MMP2_TWSI_MUX		17	/* TWSI2 ~ TWSI6 */
+#define IRQ_MMP2_HDMI			19
+#define IRQ_MMP2_SSP3			20
+#define IRQ_MMP2_SSP4			21
+#define IRQ_MMP2_USB_HS1		22
+#define IRQ_MMP2_USB_HS2		23
+#define IRQ_MMP2_UART3			24
+#define IRQ_MMP2_UART1			27
+#define IRQ_MMP2_UART2			28
+#define IRQ_MMP2_MIPI_DSI		29
+#define IRQ_MMP2_CI2			30
+#define IRQ_MMP2_PMU_TIMER1		31
+#define IRQ_MMP2_PMU_TIMER2		32
+#define IRQ_MMP2_PMU_TIMER3		33
+#define IRQ_MMP2_USB_FS			34
+#define IRQ_MMP2_MISC_MUX		35
+#define IRQ_MMP2_WDT1			36
+#define IRQ_MMP2_NAND_DMA		37
+#define IRQ_MMP2_USIM			38
+#define IRQ_MMP2_MMC			39
+#define IRQ_MMP2_WTM			40
+#define IRQ_MMP2_LCD			41
+#define IRQ_MMP2_CI			42
+#define IRQ_MMP2_IRE			43
+#define IRQ_MMP2_USB_OTG		44
+#define IRQ_MMP2_NAND			45
+#define IRQ_MMP2_UART4			46
+#define IRQ_MMP2_DMA_FIQ		47
+#define IRQ_MMP2_DMA_RIQ		48
+#define IRQ_MMP2_GPIO			49
+#define IRQ_MMP2_SSP_MUX		51
+#define IRQ_MMP2_MMC2			52
+#define IRQ_MMP2_MMC3			53
+#define IRQ_MMP2_MMC4			54
+#define IRQ_MMP2_MIPI_HSI		55
+#define IRQ_MMP2_MSP			58
+#define IRQ_MMP2_MIPI_SLIM_DMA		59
+#define IRQ_MMP2_PJ4_FREQ_CHG		60
+#define IRQ_MMP2_MIPI_SLIM		62
+#define IRQ_MMP2_SM			63
+
+#define IRQ_MMP2_MUX_BASE		64
+
+/* secondary interrupt of INT #4 */
+#define IRQ_MMP2_PMIC_BASE		(IRQ_MMP2_MUX_BASE)
+#define IRQ_MMP2_CHARGER		(IRQ_MMP2_PMIC_BASE + 0)
+#define IRQ_MMP2_PMIC			(IRQ_MMP2_PMIC_BASE + 1)
+
+/* secondary interrupt of INT #5 */
+#define IRQ_MMP2_RTC_BASE		(IRQ_MMP2_PMIC_BASE + 2)
+#define IRQ_MMP2_RTC_ALARM		(IRQ_MMP2_RTC_BASE + 0)
+#define IRQ_MMP2_RTC			(IRQ_MMP2_RTC_BASE + 1)
+
+/* secondary interrupt of INT #17 */
+#define IRQ_MMP2_TWSI_BASE		(IRQ_MMP2_RTC_BASE + 2)
+#define IRQ_MMP2_TWSI2			(IRQ_MMP2_TWSI_BASE + 0)
+#define IRQ_MMP2_TWSI3			(IRQ_MMP2_TWSI_BASE + 1)
+#define IRQ_MMP2_TWSI4			(IRQ_MMP2_TWSI_BASE + 2)
+#define IRQ_MMP2_TWSI5			(IRQ_MMP2_TWSI_BASE + 3)
+#define IRQ_MMP2_TWSI6			(IRQ_MMP2_TWSI_BASE + 4)
+
+/* secondary interrupt of INT #35 */
+#define IRQ_MMP2_MISC_BASE		(IRQ_MMP2_TWSI_BASE + 5)
+#define IRQ_MMP2_PERF			(IRQ_MMP2_MISC_BASE + 0)
+#define IRQ_MMP2_L2_PA_ECC		(IRQ_MMP2_MISC_BASE + 1)
+#define IRQ_MMP2_L2_ECC			(IRQ_MMP2_MISC_BASE + 2)
+#define IRQ_MMP2_L2_UECC		(IRQ_MMP2_MISC_BASE + 3)
+#define IRQ_MMP2_DDR			(IRQ_MMP2_MISC_BASE + 4)
+#define IRQ_MMP2_FAB0_TIMEOUT		(IRQ_MMP2_MISC_BASE + 5)
+#define IRQ_MMP2_FAB1_TIMEOUT		(IRQ_MMP2_MISC_BASE + 6)
+#define IRQ_MMP2_FAB2_TIMEOUT		(IRQ_MMP2_MISC_BASE + 7)
+#define IRQ_MMP2_THERMAL		(IRQ_MMP2_MISC_BASE + 9)
+#define IRQ_MMP2_MAIN_PMU		(IRQ_MMP2_MISC_BASE + 10)
+#define IRQ_MMP2_WDT2			(IRQ_MMP2_MISC_BASE + 11)
+#define IRQ_MMP2_CORESIGHT		(IRQ_MMP2_MISC_BASE + 12)
+#define IRQ_MMP2_COMMTX			(IRQ_MMP2_MISC_BASE + 13)
+#define IRQ_MMP2_COMMRX			(IRQ_MMP2_MISC_BASE + 14)
+
+/* secondary interrupt of INT #51 */
+#define IRQ_MMP2_SSP_BASE		(IRQ_MMP2_MISC_BASE + 15)
+#define IRQ_MMP2_SSP1_SRDY		(IRQ_MMP2_SSP_BASE + 0)
+#define IRQ_MMP2_SSP3_SRDY		(IRQ_MMP2_SSP_BASE + 1)
+
+#define IRQ_MMP2_MUX_END		(IRQ_MMP2_SSP_BASE + 2)
+
+#define IRQ_GPIO_START			128
+#define IRQ_GPIO_NUM			192
 #define IRQ_GPIO(x)			(IRQ_GPIO_START + (x))
 
-#define NR_IRQS		(IRQ_GPIO_START + IRQ_GPIO_NUM)
+/* Board IRQ - 64 by default, increase if not enough */
+#define IRQ_BOARD_START			(IRQ_GPIO_START + IRQ_GPIO_NUM)
+#define IRQ_BOARD_END			(IRQ_BOARD_START + 64)
+
+#define NR_IRQS				(IRQ_BOARD_END)
 
 #endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-mmp/include/mach/mfp-mmp2.h b/arch/arm/mach-mmp/include/mach/mfp-mmp2.h
new file mode 100644
index 0000000..9f9f814
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/mfp-mmp2.h
@@ -0,0 +1,240 @@
+#ifndef __ASM_MACH_MFP_MMP2_H
+#define __ASM_MACH_MFP_MMP2_H
+
+#include <mach/mfp.h>
+
+#define MFP_DRIVE_VERY_SLOW	(0x0 << 13)
+#define MFP_DRIVE_SLOW		(0x2 << 13)
+#define MFP_DRIVE_MEDIUM	(0x4 << 13)
+#define MFP_DRIVE_FAST		(0x8 << 13)
+
+/* GPIO */
+
+/* DFI */
+#define GPIO108_DFI_D15		MFP_CFG(GPIO108, AF0)
+#define GPIO109_DFI_D14		MFP_CFG(GPIO109, AF0)
+#define GPIO110_DFI_D13		MFP_CFG(GPIO110, AF0)
+#define GPIO161_DFI_D12		MFP_CFG(GPIO161, AF0)
+#define GPIO162_DFI_D11		MFP_CFG(GPIO162, AF0)
+#define GPIO163_DFI_D10		MFP_CFG(GPIO163, AF0)
+#define GPIO164_DFI_D9		MFP_CFG(GPIO164, AF0)
+#define GPIO111_DFI_D8		MFP_CFG(GPIO111, AF0)
+#define GPIO104_DFI_D7		MFP_CFG(GPIO104, AF0)
+#define GPIO105_DFI_D6		MFP_CFG(GPIO105, AF0)
+#define GPIO106_DFI_D5		MFP_CFG(GPIO106, AF0)
+#define GPIO107_DFI_D4		MFP_CFG(GPIO107, AF0)
+#define GPIO165_DFI_D3		MFP_CFG(GPIO165, AF0)
+#define GPIO166_DFI_D2		MFP_CFG(GPIO166, AF0)
+#define GPIO167_DFI_D1		MFP_CFG(GPIO167, AF0)
+#define GPIO168_DFI_D0		MFP_CFG(GPIO168, AF0)
+#define GPIO143_ND_nCS0		MFP_CFG(GPIO143, AF0)
+#define GPIO144_ND_nCS1		MFP_CFG(GPIO144, AF0)
+#define GPIO147_ND_nWE		MFP_CFG(GPIO147, AF0)
+#define GPIO148_ND_nRE		MFP_CFG(GPIO148, AF0)
+#define GPIO150_ND_ALE		MFP_CFG(GPIO150, AF0)
+#define GPIO149_ND_CLE		MFP_CFG(GPIO149, AF0)
+#define GPIO112_ND_RDY0		MFP_CFG(GPIO112, AF0)
+#define GPIO160_ND_RDY1		MFP_CFG(GPIO160, AF0)
+
+/* Static Memory Controller */
+#define GPIO145_SMC_nCS0	MFP_CFG(GPIO145, AF0)
+#define GPIO146_SMC_nCS1	MFP_CFG(GPIO146, AF0)
+#define GPIO152_SMC_BE0		MFP_CFG(GPIO152, AF0)
+#define GPIO153_SMC_BE1		MFP_CFG(GPIO153, AF0)
+#define GPIO154_SMC_IRQ		MFP_CFG(GPIO154, AF0)
+#define GPIO113_SMC_RDY		MFP_CFG(GPIO113, AF0)
+#define GPIO151_SMC_SCLK	MFP_CFG(GPIO151, AF0)
+
+/* Ethernet */
+#define GPIO155_SM_ADVMUX	MFP_CFG(GPIO155, AF2)
+#define GPIO155_GPIO155		MFP_CFG(GPIO155, AF1)
+
+/* UART1 */
+#define GPIO45_UART1_RXD	MFP_CFG(GPIO45, AF1)
+#define GPIO46_UART1_TXD	MFP_CFG(GPIO46, AF1)
+#define GPIO29_UART1_RXD	MFP_CFG(GPIO29, AF1)
+#define GPIO30_UART1_TXD	MFP_CFG(GPIO30, AF1)
+#define GPIO31_UART1_CTS	MFP_CFG(GPIO31, AF1)
+#define GPIO32_UART1_RTS	MFP_CFG(GPIO32, AF1)
+
+/* UART2 */
+#define GPIO47_UART2_RXD	MFP_CFG(GPIO47, AF1)
+#define GPIO48_UART2_TXD	MFP_CFG(GPIO48, AF1)
+#define GPIO49_UART2_CTS	MFP_CFG(GPIO49, AF1)
+#define GPIO50_UART2_RTS	MFP_CFG(GPIO50, AF1)
+
+/* UART3 */
+#define GPIO51_UART3_RXD	MFP_CFG(GPIO51, AF1)
+#define GPIO52_UART3_TXD	MFP_CFG(GPIO52, AF1)
+#define GPIO53_UART3_CTS	MFP_CFG(GPIO53, AF1)
+#define GPIO54_UART3_RTS	MFP_CFG(GPIO54, AF1)
+
+/* MMC1 */
+#define GPIO124_MMC1_DAT7	MFP_CFG_DRV(GPIO124, AF1, FAST)
+#define GPIO125_MMC1_DAT6	MFP_CFG_DRV(GPIO125, AF1, FAST)
+#define GPIO129_MMC1_DAT5	MFP_CFG_DRV(GPIO129, AF1, FAST)
+#define GPIO130_MMC1_DAT4	MFP_CFG_DRV(GPIO130, AF1, FAST)
+#define GPIO131_MMC1_DAT3	MFP_CFG_DRV(GPIO131, AF1, FAST)
+#define GPIO132_MMC1_DAT2	MFP_CFG_DRV(GPIO132, AF1, FAST)
+#define GPIO133_MMC1_DAT1	MFP_CFG_DRV(GPIO133, AF1, FAST)
+#define GPIO134_MMC1_DAT0	MFP_CFG_DRV(GPIO134, AF1, FAST)
+#define GPIO136_MMC1_CMD	MFP_CFG_DRV(GPIO136, AF1, FAST)
+#define GPIO139_MMC1_CLK	MFP_CFG_DRV(GPIO139, AF1, FAST)
+#define GPIO140_MMC1_CD		MFP_CFG_DRV(GPIO140, AF1, FAST)
+#define GPIO141_MMC1_WP		MFP_CFG_DRV(GPIO141, AF1, FAST)
+
+/*MMC2*/
+#define GPIO37_MMC2_DAT3	MFP_CFG_DRV(GPIO37, AF1, FAST)
+#define GPIO38_MMC2_DAT2	MFP_CFG_DRV(GPIO38, AF1, FAST)
+#define GPIO39_MMC2_DAT1	MFP_CFG_DRV(GPIO39, AF1, FAST)
+#define GPIO40_MMC2_DAT0	MFP_CFG_DRV(GPIO40, AF1, FAST)
+#define GPIO41_MMC2_CMD		MFP_CFG_DRV(GPIO41, AF1, FAST)
+#define GPIO42_MMC2_CLK		MFP_CFG_DRV(GPIO42, AF1, FAST)
+
+/*MMC3*/
+#define GPIO165_MMC3_DAT7	MFP_CFG_DRV(GPIO165, AF2, FAST)
+#define GPIO162_MMC3_DAT6	MFP_CFG_DRV(GPIO162, AF2, FAST)
+#define GPIO166_MMC3_DAT5	MFP_CFG_DRV(GPIO166, AF2, FAST)
+#define GPIO163_MMC3_DAT4	MFP_CFG_DRV(GPIO163, AF2, FAST)
+#define GPIO167_MMC3_DAT3	MFP_CFG_DRV(GPIO167, AF2, FAST)
+#define GPIO164_MMC3_DAT2	MFP_CFG_DRV(GPIO164, AF2, FAST)
+#define GPIO168_MMC3_DAT1	MFP_CFG_DRV(GPIO168, AF2, FAST)
+#define GPIO111_MMC3_DAT0	MFP_CFG_DRV(GPIO111, AF2, FAST)
+#define GPIO112_MMC3_CMD	MFP_CFG_DRV(GPIO112, AF2, FAST)
+#define GPIO151_MMC3_CLK	MFP_CFG_DRV(GPIO151, AF2, FAST)
+
+/* LCD */
+#define GPIO74_LCD_FCLK		MFP_CFG_DRV(GPIO74, AF1, FAST)
+#define GPIO75_LCD_LCLK		MFP_CFG_DRV(GPIO75, AF1, FAST)
+#define GPIO76_LCD_PCLK		MFP_CFG_DRV(GPIO76, AF1, FAST)
+#define GPIO77_LCD_DENA		MFP_CFG_DRV(GPIO77, AF1, FAST)
+#define GPIO78_LCD_DD0		MFP_CFG_DRV(GPIO78, AF1, FAST)
+#define GPIO79_LCD_DD1		MFP_CFG_DRV(GPIO79, AF1, FAST)
+#define GPIO80_LCD_DD2		MFP_CFG_DRV(GPIO80, AF1, FAST)
+#define GPIO81_LCD_DD3		MFP_CFG_DRV(GPIO81, AF1, FAST)
+#define GPIO82_LCD_DD4		MFP_CFG_DRV(GPIO82, AF1, FAST)
+#define GPIO83_LCD_DD5		MFP_CFG_DRV(GPIO83, AF1, FAST)
+#define GPIO84_LCD_DD6		MFP_CFG_DRV(GPIO84, AF1, FAST)
+#define GPIO85_LCD_DD7		MFP_CFG_DRV(GPIO85, AF1, FAST)
+#define GPIO86_LCD_DD8		MFP_CFG_DRV(GPIO86, AF1, FAST)
+#define GPIO87_LCD_DD9		MFP_CFG_DRV(GPIO87, AF1, FAST)
+#define GPIO88_LCD_DD10		MFP_CFG_DRV(GPIO88, AF1, FAST)
+#define GPIO89_LCD_DD11		MFP_CFG_DRV(GPIO89, AF1, FAST)
+#define GPIO90_LCD_DD12		MFP_CFG_DRV(GPIO90, AF1, FAST)
+#define GPIO91_LCD_DD13		MFP_CFG_DRV(GPIO91, AF1, FAST)
+#define GPIO92_LCD_DD14		MFP_CFG_DRV(GPIO92, AF1, FAST)
+#define GPIO93_LCD_DD15		MFP_CFG_DRV(GPIO93, AF1, FAST)
+#define GPIO94_LCD_DD16		MFP_CFG_DRV(GPIO94, AF1, FAST)
+#define GPIO95_LCD_DD17		MFP_CFG_DRV(GPIO95, AF1, FAST)
+#define GPIO96_LCD_DD18		MFP_CFG_DRV(GPIO96, AF1, FAST)
+#define GPIO97_LCD_DD19		MFP_CFG_DRV(GPIO97, AF1, FAST)
+#define GPIO98_LCD_DD20		MFP_CFG_DRV(GPIO98, AF1, FAST)
+#define GPIO99_LCD_DD21		MFP_CFG_DRV(GPIO99, AF1, FAST)
+#define GPIO100_LCD_DD22	MFP_CFG_DRV(GPIO100, AF1, FAST)
+#define GPIO101_LCD_DD23	MFP_CFG_DRV(GPIO101, AF1, FAST)
+#define GPIO94_SPI_DCLK		MFP_CFG_DRV(GPIO94, AF3, FAST)
+#define GPIO95_SPI_CS0		MFP_CFG_DRV(GPIO95, AF3, FAST)
+#define GPIO96_SPI_DIN		MFP_CFG_DRV(GPIO96, AF3, FAST)
+#define GPIO97_SPI_DOUT		MFP_CFG_DRV(GPIO97, AF3, FAST)
+#define GPIO98_LCD_RST		MFP_CFG_DRV(GPIO98, AF0, FAST)
+
+#define GPIO114_MN_CLK_OUT	MFP_CFG_DRV(GPIO114, AF1, FAST)
+
+/*LCD TV path*/
+#define GPIO124_LCD_DD24	MFP_CFG_DRV(GPIO124, AF2, FAST)
+#define GPIO125_LCD_DD25	MFP_CFG_DRV(GPIO125, AF2, FAST)
+#define GPIO126_LCD_DD33	MFP_CFG_DRV(GPIO126, AF2, FAST)
+#define GPIO127_LCD_DD26	MFP_CFG_DRV(GPIO127, AF2, FAST)
+#define GPIO128_LCD_DD27	MFP_CFG_DRV(GPIO128, AF2, FAST)
+#define GPIO129_LCD_DD28	MFP_CFG_DRV(GPIO129, AF2, FAST)
+#define GPIO130_LCD_DD29	MFP_CFG_DRV(GPIO130, AF2, FAST)
+#define GPIO135_LCD_DD30	MFP_CFG_DRV(GPIO135, AF2, FAST)
+#define GPIO137_LCD_DD31	MFP_CFG_DRV(GPIO137, AF2, FAST)
+#define GPIO138_LCD_DD32	MFP_CFG_DRV(GPIO138, AF2, FAST)
+#define GPIO140_LCD_DD34	MFP_CFG_DRV(GPIO140, AF2, FAST)
+#define GPIO141_LCD_DD35	MFP_CFG_DRV(GPIO141, AF2, FAST)
+
+/* I2C */
+#define GPIO43_TWSI2_SCL	MFP_CFG_DRV(GPIO43, AF1, SLOW)
+#define GPIO44_TWSI2_SDA	MFP_CFG_DRV(GPIO44, AF1, SLOW)
+#define GPIO71_TWSI3_SCL	MFP_CFG_DRV(GPIO71, AF1, SLOW)
+#define GPIO72_TWSI3_SDA	MFP_CFG_DRV(GPIO72, AF1, SLOW)
+#define GPIO99_TWSI5_SCL	MFP_CFG_DRV(GPIO99, AF4, SLOW)
+#define GPIO100_TWSI5_SDA	MFP_CFG_DRV(GPIO100, AF4, SLOW)
+#define GPIO97_TWSI6_SCL	MFP_CFG_DRV(GPIO97, AF2, SLOW)
+#define GPIO98_TWSI6_SDA	MFP_CFG_DRV(GPIO98, AF2, SLOW)
+
+/* SSPA1 */
+#define GPIO24_I2S_SYSCLK	MFP_CFG(GPIO24, AF1)
+#define GPIO25_I2S_BITCLK	MFP_CFG(GPIO25, AF1)
+#define GPIO26_I2S_SYNC		MFP_CFG(GPIO26, AF1)
+#define GPIO27_I2S_DATA_OUT	MFP_CFG(GPIO27, AF1)
+#define GPIO28_I2S_SDATA_IN	MFP_CFG(GPIO28, AF1)
+#define GPIO114_I2S_MCLK	MFP_CFG(GPIO114, AF1)
+
+/* SSPA2 */
+#define GPIO33_SSPA2_CLK	MFP_CFG(GPIO33, AF1)
+#define GPIO34_SSPA2_FRM	MFP_CFG(GPIO34, AF1)
+#define GPIO35_SSPA2_TXD	MFP_CFG(GPIO35, AF1)
+#define GPIO36_SSPA2_RXD	MFP_CFG(GPIO36, AF1)
+
+/* Keypad */
+#define GPIO00_KP_MKIN0		MFP_CFG(GPIO0, AF1)
+#define GPIO01_KP_MKOUT0	MFP_CFG(GPIO1, AF1)
+#define GPIO02_KP_MKIN1		MFP_CFG(GPIO2, AF1)
+#define GPIO03_KP_MKOUT1	MFP_CFG(GPIO3, AF1)
+#define GPIO04_KP_MKIN2		MFP_CFG(GPIO4, AF1)
+#define GPIO05_KP_MKOUT2	MFP_CFG(GPIO5, AF1)
+#define GPIO06_KP_MKIN3		MFP_CFG(GPIO6, AF1)
+#define GPIO07_KP_MKOUT3	MFP_CFG(GPIO7, AF1)
+#define GPIO08_KP_MKIN4		MFP_CFG(GPIO8, AF1)
+#define GPIO09_KP_MKOUT4	MFP_CFG(GPIO9, AF1)
+#define GPIO10_KP_MKIN5		MFP_CFG(GPIO10, AF1)
+#define GPIO11_KP_MKOUT5	MFP_CFG(GPIO11, AF1)
+#define GPIO12_KP_MKIN6		MFP_CFG(GPIO12, AF1)
+#define GPIO13_KP_MKOUT6	MFP_CFG(GPIO13, AF1)
+#define GPIO14_KP_MKIN7		MFP_CFG(GPIO14, AF1)
+#define GPIO15_KP_MKOUT7	MFP_CFG(GPIO15, AF1)
+#define GPIO16_KP_DKIN0		MFP_CFG(GPIO16, AF1)
+#define GPIO17_KP_DKIN1		MFP_CFG(GPIO17, AF1)
+#define GPIO18_KP_DKIN2		MFP_CFG(GPIO18, AF1)
+#define GPIO19_KP_DKIN3		MFP_CFG(GPIO19, AF1)
+#define GPIO20_KP_DKIN4		MFP_CFG(GPIO20, AF1)
+#define GPIO21_KP_DKIN5		MFP_CFG(GPIO21, AF1)
+#define GPIO22_KP_DKIN6		MFP_CFG(GPIO22, AF1)
+#define GPIO23_KP_DKIN7		MFP_CFG(GPIO23, AF1)
+
+/* CAMERA */
+#define GPIO59_CCIC_IN7		MFP_CFG_DRV(GPIO59, AF1, FAST)
+#define GPIO60_CCIC_IN6		MFP_CFG_DRV(GPIO60, AF1, FAST)
+#define GPIO61_CCIC_IN5		MFP_CFG_DRV(GPIO61, AF1, FAST)
+#define GPIO62_CCIC_IN4		MFP_CFG_DRV(GPIO62, AF1, FAST)
+#define GPIO63_CCIC_IN3		MFP_CFG_DRV(GPIO63, AF1, FAST)
+#define GPIO64_CCIC_IN2		MFP_CFG_DRV(GPIO64, AF1, FAST)
+#define GPIO65_CCIC_IN1		MFP_CFG_DRV(GPIO65, AF1, FAST)
+#define GPIO66_CCIC_IN0		MFP_CFG_DRV(GPIO66, AF1, FAST)
+#define GPIO67_CAM_HSYNC	MFP_CFG_DRV(GPIO67, AF1, FAST)
+#define GPIO68_CAM_VSYNC	MFP_CFG_DRV(GPIO68, AF1, FAST)
+#define GPIO69_CAM_MCLK		MFP_CFG_DRV(GPIO69, AF1, FAST)
+#define GPIO70_CAM_PCLK		MFP_CFG_DRV(GPIO70, AF1, FAST)
+
+/* Wifi */
+#define GPIO45_GPIO45		MFP_CFG(GPIO45, AF0)
+#define GPIO46_GPIO46		MFP_CFG(GPIO46, AF0)
+#define GPIO21_GPIO21		MFP_CFG(GPIO21, AF0)
+#define GPIO22_GPIO22		MFP_CFG(GPIO22, 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)
+
+/* Codec*/
+#define GPIO23_GPIO23		MFP_CFG(GPIO23, AF0)
+
+#define GPIO101_GPIO101		MFP_CFG(GPIO101, AF0)
+
+/* PMIC */
+#define PMIC_PMIC_INT		MFP_CFG(PMIC_INT, AF0)
+
+#endif /* __ASM_MACH_MFP_MMP2_H */
+
diff --git a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
index 3b216bf..ded43c4 100644
--- a/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
@@ -193,7 +193,9 @@
 #define GPIO32_CF_nCD1		MFP_CFG(GPIO32, AF3)
 #define GPIO33_CF_nCD2		MFP_CFG(GPIO33, AF3)
 
-/* UART1 */
+/* UART */
+#define GPIO88_UART2_TXD	MFP_CFG(GPIO88, AF2)
+#define GPIO89_UART2_RXD	MFP_CFG(GPIO89, AF2)
 #define GPIO107_UART1_TXD	MFP_CFG_DRV(GPIO107, AF1, FAST)
 #define GPIO107_UART1_RXD	MFP_CFG_DRV(GPIO107, AF2, FAST)
 #define GPIO108_UART1_RXD	MFP_CFG_DRV(GPIO108, AF1, FAST)
diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h
new file mode 100644
index 0000000..459f3be
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/mmp2.h
@@ -0,0 +1,60 @@
+#ifndef __ASM_MACH_MMP2_H
+#define __ASM_MACH_MMP2_H
+
+#include <linux/i2c.h>
+#include <mach/devices.h>
+#include <plat/i2c.h>
+
+extern struct pxa_device_desc mmp2_device_uart1;
+extern struct pxa_device_desc mmp2_device_uart2;
+extern struct pxa_device_desc mmp2_device_uart3;
+extern struct pxa_device_desc mmp2_device_uart4;
+extern struct pxa_device_desc mmp2_device_twsi1;
+extern struct pxa_device_desc mmp2_device_twsi2;
+extern struct pxa_device_desc mmp2_device_twsi3;
+extern struct pxa_device_desc mmp2_device_twsi4;
+extern struct pxa_device_desc mmp2_device_twsi5;
+extern struct pxa_device_desc mmp2_device_twsi6;
+
+static inline int mmp2_add_uart(int id)
+{
+	struct pxa_device_desc *d = NULL;
+
+	switch (id) {
+	case 1: d = &mmp2_device_uart1; break;
+	case 2: d = &mmp2_device_uart2; break;
+	case 3: d = &mmp2_device_uart3; break;
+	case 4: d = &mmp2_device_uart4; break;
+	default:
+		return -EINVAL;
+	}
+
+	return pxa_register_device(d, NULL, 0);
+}
+
+static inline int mmp2_add_twsi(int id, struct i2c_pxa_platform_data *data,
+				  struct i2c_board_info *info, unsigned size)
+{
+	struct pxa_device_desc *d = NULL;
+	int ret;
+
+	switch (id) {
+	case 0: d = &mmp2_device_twsi1; break;
+	case 1: d = &mmp2_device_twsi2; break;
+	case 2: d = &mmp2_device_twsi3; break;
+	case 3: d = &mmp2_device_twsi4; break;
+	case 4: d = &mmp2_device_twsi5; break;
+	case 5: d = &mmp2_device_twsi6; break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = i2c_register_board_info(id, info, size);
+	if (ret)
+		return ret;
+
+	return pxa_register_device(d, data, sizeof(*data));
+}
+
+#endif /* __ASM_MACH_MMP2_H */
+
diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h
index 98ccbee..712af03 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apbc.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h
@@ -69,6 +69,47 @@
 #define APBC_PXA910_ASFAR	APBC_REG(0x050)
 #define APBC_PXA910_ASSAR	APBC_REG(0x054)
 
+/*
+ * APB Clock register offsets for MMP2
+ */
+#define APBC_MMP2_RTC		APBC_REG(0x000)
+#define APBC_MMP2_TWSI1		APBC_REG(0x004)
+#define APBC_MMP2_TWSI2		APBC_REG(0x008)
+#define APBC_MMP2_TWSI3		APBC_REG(0x00c)
+#define APBC_MMP2_TWSI4		APBC_REG(0x010)
+#define APBC_MMP2_ONEWIRE	APBC_REG(0x014)
+#define APBC_MMP2_KPC		APBC_REG(0x018)
+#define APBC_MMP2_TB_ROTARY	APBC_REG(0x01c)
+#define APBC_MMP2_SW_JTAG	APBC_REG(0x020)
+#define APBC_MMP2_TIMERS	APBC_REG(0x024)
+#define APBC_MMP2_UART1		APBC_REG(0x02c)
+#define APBC_MMP2_UART2		APBC_REG(0x030)
+#define APBC_MMP2_UART3		APBC_REG(0x034)
+#define APBC_MMP2_GPIO		APBC_REG(0x038)
+#define APBC_MMP2_PWM0		APBC_REG(0x03c)
+#define APBC_MMP2_PWM1		APBC_REG(0x040)
+#define APBC_MMP2_PWM2		APBC_REG(0x044)
+#define APBC_MMP2_PWM3		APBC_REG(0x048)
+#define APBC_MMP2_SSP0		APBC_REG(0x04c)
+#define APBC_MMP2_SSP1		APBC_REG(0x050)
+#define APBC_MMP2_SSP2		APBC_REG(0x054)
+#define APBC_MMP2_SSP3		APBC_REG(0x058)
+#define APBC_MMP2_SSP4		APBC_REG(0x05c)
+#define APBC_MMP2_SSP5		APBC_REG(0x060)
+#define APBC_MMP2_AIB		APBC_REG(0x064)
+#define APBC_MMP2_ASFAR		APBC_REG(0x068)
+#define APBC_MMP2_ASSAR		APBC_REG(0x06c)
+#define APBC_MMP2_USIM		APBC_REG(0x070)
+#define APBC_MMP2_MPMU		APBC_REG(0x074)
+#define APBC_MMP2_IPC		APBC_REG(0x078)
+#define APBC_MMP2_TWSI5		APBC_REG(0x07c)
+#define APBC_MMP2_TWSI6		APBC_REG(0x080)
+#define APBC_MMP2_TWSI_INTSTS	APBC_REG(0x084)
+#define APBC_MMP2_UART4		APBC_REG(0x088)
+#define APBC_MMP2_RIPC		APBC_REG(0x08c)
+#define APBC_MMP2_THSENS1	APBC_REG(0x090)	/* Thermal Sensor */
+#define APBC_MMP2_THSENS_INTSTS	APBC_REG(0x0a4)
+
 /* Common APB clock register bit definitions */
 #define APBC_APBCLK	(1 << 0)  /* APB Bus Clock Enable */
 #define APBC_FNCLK	(1 << 1)  /* Functional Clock Enable */
diff --git a/arch/arm/mach-mmp/include/mach/regs-icu.h b/arch/arm/mach-mmp/include/mach/regs-icu.h
index e5f0872..f882d91 100644
--- a/arch/arm/mach-mmp/include/mach/regs-icu.h
+++ b/arch/arm/mach-mmp/include/mach/regs-icu.h
@@ -17,10 +17,12 @@
 #define ICU_REG(x)	(ICU_VIRT_BASE + (x))
 
 #define ICU_INT_CONF(n)		ICU_REG((n) << 2)
+#define ICU_INT_CONF_MASK	(0xf)
+
+/************ PXA168/PXA910 (MMP) *********************/
 #define ICU_INT_CONF_AP_INT	(1 << 6)
 #define ICU_INT_CONF_CP_INT	(1 << 5)
 #define ICU_INT_CONF_IRQ	(1 << 4)
-#define ICU_INT_CONF_MASK	(0xf)
 
 #define ICU_AP_FIQ_SEL_INT_NUM	ICU_REG(0x108)	/* AP FIQ Selected Interrupt */
 #define ICU_AP_IRQ_SEL_INT_NUM	ICU_REG(0x10C)	/* AP IRQ Selected Interrupt */
@@ -28,4 +30,42 @@
 #define ICU_INT_STATUS_0	ICU_REG(0x128)	/* Interrupt Stuats 0 */
 #define ICU_INT_STATUS_1	ICU_REG(0x12C)	/* Interrupt Status 1 */
 
+/************************** MMP2 ***********************/
+
+/*
+ * IRQ0/FIQ0 is routed to SP IRQ/FIQ.
+ * IRQ1 is routed to PJ4 IRQ, and IRQ2 is routes to PJ4 FIQ.
+ */
+#define ICU_INT_ROUTE_SP_IRQ		(1 << 4)
+#define ICU_INT_ROUTE_PJ4_IRQ		(1 << 5)
+#define ICU_INT_ROUTE_PJ4_FIQ		(1 << 6)
+
+#define MMP2_ICU_PJ4_IRQ_STATUS0	ICU_REG(0x138)
+#define MMP2_ICU_PJ4_IRQ_STATUS1	ICU_REG(0x13c)
+#define MMP2_ICU_PJ4_FIQ_STATUS0	ICU_REG(0x140)
+#define MMP2_ICU_PJ4_FIQ_STATUS1	ICU_REG(0x144)
+
+#define MMP2_ICU_INT4_STATUS		ICU_REG(0x150)
+#define MMP2_ICU_INT5_STATUS		ICU_REG(0x154)
+#define MMP2_ICU_INT17_STATUS		ICU_REG(0x158)
+#define MMP2_ICU_INT35_STATUS		ICU_REG(0x15c)
+#define MMP2_ICU_INT51_STATUS		ICU_REG(0x160)
+
+#define MMP2_ICU_INT4_MASK		ICU_REG(0x168)
+#define MMP2_ICU_INT5_MASK		ICU_REG(0x16C)
+#define MMP2_ICU_INT17_MASK		ICU_REG(0x170)
+#define MMP2_ICU_INT35_MASK		ICU_REG(0x174)
+#define MMP2_ICU_INT51_MASK		ICU_REG(0x178)
+
+#define MMP2_ICU_SP_IRQ_SEL		ICU_REG(0x100)
+#define MMP2_ICU_PJ4_IRQ_SEL		ICU_REG(0x104)
+#define MMP2_ICU_PJ4_FIQ_SEL		ICU_REG(0x108)
+
+#define MMP2_ICU_INVERT			ICU_REG(0x164)
+
+#define MMP2_ICU_INV_PMIC		(1 << 0)
+#define MMP2_ICU_INV_PERF		(1 << 1)
+#define MMP2_ICU_INV_COMMTX		(1 << 2)
+#define MMP2_ICU_INV_COMMRX		(1 << 3)
+
 #endif /* __ASM_MACH_ICU_H */
diff --git a/arch/arm/mach-mmp/include/mach/uncompress.h b/arch/arm/mach-mmp/include/mach/uncompress.h
index c93d5fa..a7dcc53 100644
--- a/arch/arm/mach-mmp/include/mach/uncompress.h
+++ b/arch/arm/mach-mmp/include/mach/uncompress.h
@@ -8,15 +8,16 @@
 
 #include <linux/serial_reg.h>
 #include <mach/addr-map.h>
+#include <asm/mach-types.h>
 
 #define UART1_BASE	(APB_PHYS_BASE + 0x36000)
 #define UART2_BASE	(APB_PHYS_BASE + 0x17000)
 #define UART3_BASE	(APB_PHYS_BASE + 0x18000)
 
+static volatile unsigned long *UART = (unsigned long *)UART2_BASE;
+
 static inline void putc(char c)
 {
-	volatile unsigned long *UART = (unsigned long *)UART2_BASE;
-
 	/* UART enabled? */
 	if (!(UART[UART_IER] & UART_IER_UUE))
 		return;
@@ -34,8 +35,14 @@
 {
 }
 
+static inline void arch_decomp_setup(void)
+{
+	if (machine_is_avengers_lite())
+		UART = (unsigned long *)UART3_BASE;
+}
+
 /*
  * nothing to do
  */
-#define arch_decomp_setup()
+
 #define arch_decomp_wdog()
diff --git a/arch/arm/mach-mmp/irq-mmp2.c b/arch/arm/mach-mmp/irq-mmp2.c
new file mode 100644
index 0000000..cb18221
--- /dev/null
+++ b/arch/arm/mach-mmp/irq-mmp2.c
@@ -0,0 +1,154 @@
+/*
+ *  linux/arch/arm/mach-mmp/irq-mmp2.c
+ *
+ *  Generic IRQ handling, GPIO IRQ demultiplexing, etc.
+ *
+ *  Author:	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *  Copyright:	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/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/regs-icu.h>
+
+#include "common.h"
+
+static void icu_mask_irq(unsigned int irq)
+{
+	uint32_t r = __raw_readl(ICU_INT_CONF(irq));
+
+	r &= ~ICU_INT_ROUTE_PJ4_IRQ;
+	__raw_writel(r, ICU_INT_CONF(irq));
+}
+
+static void icu_unmask_irq(unsigned int irq)
+{
+	uint32_t r = __raw_readl(ICU_INT_CONF(irq));
+
+	r |= ICU_INT_ROUTE_PJ4_IRQ;
+	__raw_writel(r, ICU_INT_CONF(irq));
+}
+
+static struct irq_chip icu_irq_chip = {
+	.name		= "icu_irq",
+	.mask		= icu_mask_irq,
+	.mask_ack	= icu_mask_irq,
+	.unmask		= icu_unmask_irq,
+};
+
+static void pmic_irq_ack(unsigned int irq)
+{
+	if (irq == IRQ_MMP2_PMIC)
+		mmp2_clear_pmic_int();
+}
+
+#define SECOND_IRQ_MASK(_name_, irq_base, prefix)			\
+static void _name_##_mask_irq(unsigned int irq)				\
+{									\
+	uint32_t r;							\
+	r = __raw_readl(prefix##_MASK) | (1 << (irq - irq_base));	\
+	__raw_writel(r, prefix##_MASK);					\
+}
+
+#define SECOND_IRQ_UNMASK(_name_, irq_base, prefix)			\
+static void _name_##_unmask_irq(unsigned int irq)			\
+{									\
+	uint32_t r;							\
+	r = __raw_readl(prefix##_MASK) & ~(1 << (irq - irq_base));	\
+	__raw_writel(r, prefix##_MASK);					\
+}
+
+#define SECOND_IRQ_DEMUX(_name_, irq_base, prefix)			\
+static void _name_##_irq_demux(unsigned int irq, struct irq_desc *desc)	\
+{									\
+	unsigned long status, mask, n;					\
+	mask = __raw_readl(prefix##_MASK);				\
+	while (1) {							\
+		status = __raw_readl(prefix##_STATUS) & ~mask;		\
+		if (status == 0)					\
+			break;						\
+		n = find_first_bit(&status, BITS_PER_LONG);		\
+		while (n < BITS_PER_LONG) {				\
+			generic_handle_irq(irq_base + n);		\
+			n = find_next_bit(&status, BITS_PER_LONG, n+1);	\
+		}							\
+	}								\
+}
+
+#define SECOND_IRQ_CHIP(_name_, irq_base, prefix)			\
+SECOND_IRQ_MASK(_name_, irq_base, prefix)				\
+SECOND_IRQ_UNMASK(_name_, irq_base, prefix)				\
+SECOND_IRQ_DEMUX(_name_, irq_base, prefix)				\
+static struct irq_chip _name_##_irq_chip = {				\
+	.name		= #_name_,					\
+	.mask		= _name_##_mask_irq,				\
+	.unmask		= _name_##_unmask_irq,				\
+}
+
+SECOND_IRQ_CHIP(pmic, IRQ_MMP2_PMIC_BASE, MMP2_ICU_INT4);
+SECOND_IRQ_CHIP(rtc,  IRQ_MMP2_RTC_BASE,  MMP2_ICU_INT5);
+SECOND_IRQ_CHIP(twsi, IRQ_MMP2_TWSI_BASE, MMP2_ICU_INT17);
+SECOND_IRQ_CHIP(misc, IRQ_MMP2_MISC_BASE, MMP2_ICU_INT35);
+SECOND_IRQ_CHIP(ssp,  IRQ_MMP2_SSP_BASE,  MMP2_ICU_INT51);
+
+static void init_mux_irq(struct irq_chip *chip, int start, int num)
+{
+	int irq;
+
+	for (irq = start; num > 0; irq++, num--) {
+		/* mask and clear the IRQ */
+		chip->mask(irq);
+		if (chip->ack)
+			chip->ack(irq);
+
+		set_irq_chip(irq, chip);
+		set_irq_flags(irq, IRQF_VALID);
+		set_irq_handler(irq, handle_level_irq);
+	}
+}
+
+void __init mmp2_init_icu(void)
+{
+	int irq;
+
+	for (irq = 0; irq < IRQ_MMP2_MUX_BASE; irq++) {
+		icu_mask_irq(irq);
+		set_irq_chip(irq, &icu_irq_chip);
+		set_irq_flags(irq, IRQF_VALID);
+
+		switch (irq) {
+		case IRQ_MMP2_PMIC_MUX:
+		case IRQ_MMP2_RTC_MUX:
+		case IRQ_MMP2_TWSI_MUX:
+		case IRQ_MMP2_MISC_MUX:
+		case IRQ_MMP2_SSP_MUX:
+			break;
+		default:
+			set_irq_handler(irq, handle_level_irq);
+			break;
+		}
+	}
+
+	/* NOTE: IRQ_MMP2_PMIC requires the PMIC MFPR register
+	 * to be written to clear the interrupt
+	 */
+	pmic_irq_chip.ack = pmic_irq_ack;
+
+	init_mux_irq(&pmic_irq_chip, IRQ_MMP2_PMIC_BASE, 2);
+	init_mux_irq(&rtc_irq_chip, IRQ_MMP2_RTC_BASE, 2);
+	init_mux_irq(&twsi_irq_chip, IRQ_MMP2_TWSI_BASE, 5);
+	init_mux_irq(&misc_irq_chip, IRQ_MMP2_MISC_BASE, 15);
+	init_mux_irq(&ssp_irq_chip, IRQ_MMP2_SSP_BASE, 2);
+
+	set_irq_chained_handler(IRQ_MMP2_PMIC_MUX, pmic_irq_demux);
+	set_irq_chained_handler(IRQ_MMP2_RTC_MUX, rtc_irq_demux);
+	set_irq_chained_handler(IRQ_MMP2_TWSI_MUX, twsi_irq_demux);
+	set_irq_chained_handler(IRQ_MMP2_MISC_MUX, misc_irq_demux);
+	set_irq_chained_handler(IRQ_MMP2_SSP_MUX, ssp_irq_demux);
+}
diff --git a/arch/arm/mach-mmp/irq.c b/arch/arm/mach-mmp/irq-pxa168.c
similarity index 100%
rename from arch/arm/mach-mmp/irq.c
rename to arch/arm/mach-mmp/irq-pxa168.c
diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
new file mode 100644
index 0000000..cfd4d66
--- /dev/null
+++ b/arch/arm/mach-mmp/jasper.c
@@ -0,0 +1,80 @@
+/*
+ *  linux/arch/arm/mach-mmp/jasper.c
+ *
+ *  Support for the Marvell Jasper 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 <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/addr-map.h>
+#include <mach/mfp-mmp2.h>
+#include <mach/mmp2.h>
+
+#include "common.h"
+
+static unsigned long jasper_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,
+};
+
+static void __init jasper_init(void)
+{
+	mfp_config(ARRAY_AND_SIZE(jasper_pin_config));
+
+	/* on-chip devices */
+	mmp2_add_uart(1);
+	mmp2_add_uart(3);
+}
+
+MACHINE_START(MARVELL_JASPER, "Jasper Development Platform")
+	.phys_io        = APB_PHYS_BASE,
+	.boot_params    = 0x00000100,
+	.io_pg_offst    = (APB_VIRT_BASE >> 18) & 0xfffc,
+	.map_io		= pxa_map_io,
+	.init_irq       = mmp2_init_irq,
+	.timer          = &mmp2_timer,
+	.init_machine   = jasper_init,
+MACHINE_END
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
new file mode 100644
index 0000000..72eb9da
--- /dev/null
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -0,0 +1,123 @@
+/*
+ * linux/arch/arm/mach-mmp/mmp2.c
+ *
+ * code name MMP2
+ *
+ * Copyright (C) 2009 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/io.h>
+
+#include <mach/addr-map.h>
+#include <mach/regs-apbc.h>
+#include <mach/regs-apmu.h>
+#include <mach/cputype.h>
+#include <mach/irqs.h>
+#include <mach/mfp.h>
+#include <mach/gpio.h>
+#include <mach/devices.h>
+
+#include "common.h"
+#include "clock.h"
+
+#define MFPR_VIRT_BASE	(APB_VIRT_BASE + 0x1e000)
+
+#define APMASK(i)	(GPIO_REGS_VIRT + BANK_OFF(i) + 0x9c)
+
+static struct mfp_addr_map mmp2_addr_map[] __initdata = {
+	MFP_ADDR(PMIC_INT, 0x2c4),
+
+	MFP_ADDR_END,
+};
+
+void mmp2_clear_pmic_int(void)
+{
+	unsigned long mfpr_pmic, data;
+
+	mfpr_pmic = APB_VIRT_BASE + 0x1e000 + 0x2c4;
+	data = __raw_readl(mfpr_pmic);
+	__raw_writel(data | (1 << 6), mfpr_pmic);
+	__raw_writel(data, mfpr_pmic);
+}
+
+static void __init mmp2_init_gpio(void)
+{
+	int i;
+
+	/* enable GPIO clock */
+	__raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_MMP2_GPIO);
+
+	/* unmask GPIO edge detection for all 6 banks -- APMASKx */
+	for (i = 0; i < 6; i++)
+		__raw_writel(0xffffffff, APMASK(i));
+
+	pxa_init_gpio(IRQ_MMP2_GPIO, 0, 167, NULL);
+}
+
+void __init mmp2_init_irq(void)
+{
+	mmp2_init_icu();
+	mmp2_init_gpio();
+}
+
+/* APB peripheral clocks */
+static APBC_CLK(uart1, MMP2_UART1, 1, 26000000);
+static APBC_CLK(uart2, MMP2_UART2, 1, 26000000);
+static APBC_CLK(uart3, MMP2_UART3, 1, 26000000);
+static APBC_CLK(uart4, MMP2_UART4, 1, 26000000);
+static APBC_CLK(twsi1, MMP2_TWSI1, 0, 26000000);
+static APBC_CLK(twsi2, MMP2_TWSI2, 0, 26000000);
+static APBC_CLK(twsi3, MMP2_TWSI3, 0, 26000000);
+static APBC_CLK(twsi4, MMP2_TWSI4, 0, 26000000);
+static APBC_CLK(twsi5, MMP2_TWSI5, 0, 26000000);
+static APBC_CLK(twsi6, MMP2_TWSI6, 0, 26000000);
+static APBC_CLK(rtc, MMP2_RTC, 0, 32768);
+
+static APMU_CLK(nand, NAND, 0xbf, 100000000);
+
+static struct clk_lookup mmp2_clkregs[] = {
+	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
+	INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+	INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
+	INIT_CLKREG(&clk_uart4, "pxa2xx-uart.3", NULL),
+	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.0", NULL),
+	INIT_CLKREG(&clk_twsi2, "pxa2xx-i2c.1", NULL),
+	INIT_CLKREG(&clk_twsi3, "pxa2xx-i2c.2", NULL),
+	INIT_CLKREG(&clk_twsi4, "pxa2xx-i2c.3", NULL),
+	INIT_CLKREG(&clk_twsi5, "pxa2xx-i2c.4", NULL),
+	INIT_CLKREG(&clk_twsi6, "pxa2xx-i2c.5", NULL),
+	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+};
+
+static int __init mmp2_init(void)
+{
+	if (cpu_is_mmp2()) {
+		mfp_init_base(MFPR_VIRT_BASE);
+		mfp_init_addr(mmp2_addr_map);
+		clks_register(ARRAY_AND_SIZE(mmp2_clkregs));
+	}
+
+	return 0;
+}
+postcore_initcall(mmp2_init);
+
+/* on-chip devices */
+MMP2_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4030000, 0x30, 4, 5);
+MMP2_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4017000, 0x30, 20, 21);
+MMP2_DEVICE(uart3, "pxa2xx-uart", 2, UART3, 0xd4018000, 0x30, 22, 23);
+MMP2_DEVICE(uart4, "pxa2xx-uart", 3, UART4, 0xd4016000, 0x30, 18, 19);
+MMP2_DEVICE(twsi1, "pxa2xx-i2c", 0, TWSI1, 0xd4011000, 0x70);
+MMP2_DEVICE(twsi2, "pxa2xx-i2c", 1, TWSI2, 0xd4031000, 0x70);
+MMP2_DEVICE(twsi3, "pxa2xx-i2c", 2, TWSI3, 0xd4032000, 0x70);
+MMP2_DEVICE(twsi4, "pxa2xx-i2c", 3, TWSI4, 0xd4033000, 0x70);
+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);
+
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c
index a8400bb..cf75694 100644
--- a/arch/arm/mach-mmp/time.c
+++ b/arch/arm/mach-mmp/time.c
@@ -30,7 +30,10 @@
 
 #include <mach/addr-map.h>
 #include <mach/regs-timers.h>
+#include <mach/regs-apbc.h>
 #include <mach/irqs.h>
+#include <mach/cputype.h>
+#include <asm/mach/time.h>
 
 #include "clock.h"
 
@@ -158,7 +161,7 @@
 
 	__raw_writel(cer & ~0x1, TIMERS_VIRT_BASE + TMR_CER); /* disable */
 
-	ccr &= TMR_CCR_CS_0(0x3);
+	ccr &= (cpu_is_mmp2()) ? TMR_CCR_CS_0(0) : TMR_CCR_CS_0(3);
 	__raw_writel(ccr, TIMERS_VIRT_BASE + TMR_CCR);
 
 	/* free-running mode */
@@ -197,3 +200,24 @@
 	clocksource_register(&cksrc);
 	clockevents_register_device(&ckevt);
 }
+
+static void __init mmp2_timer_init(void)
+{
+	unsigned long clk_rst;
+
+	__raw_writel(APBC_APBCLK | APBC_RST, APBC_MMP2_TIMERS);
+
+	/*
+	 * enable bus/functional clock, enable 6.5MHz (divider 4),
+	 * release reset
+	 */
+	clk_rst = APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(1);
+	__raw_writel(clk_rst, APBC_MMP2_TIMERS);
+
+	timer_init(IRQ_MMP2_TIMER1);
+}
+
+struct sys_timer mmp2_timer = {
+	.init	= mmp2_timer_init,
+};
+
diff --git a/arch/arm/mach-mv78xx0/Kconfig b/arch/arm/mach-mv78xx0/Kconfig
index 6fbe68f..f2d309d 100644
--- a/arch/arm/mach-mv78xx0/Kconfig
+++ b/arch/arm/mach-mv78xx0/Kconfig
@@ -14,6 +14,12 @@
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell RD-78x00-mASA Reference Design.
 
+config MACH_TERASTATION_WXL
+	bool "Buffalo WLX (Terastation Duo) NAS"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Buffalo WXL Nas.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-mv78xx0/Makefile b/arch/arm/mach-mv78xx0/Makefile
index da628b7..67a13f9 100644
--- a/arch/arm/mach-mv78xx0/Makefile
+++ b/arch/arm/mach-mv78xx0/Makefile
@@ -1,3 +1,4 @@
-obj-y				+= common.o addr-map.o irq.o pcie.o
+obj-y				+= common.o addr-map.o mpp.o irq.o pcie.o
 obj-$(CONFIG_MACH_DB78X00_BP)	+= db78x00-bp-setup.o
 obj-$(CONFIG_MACH_RD78X00_MASA)	+= rd78x00-masa-setup.o
+obj-$(CONFIG_MACH_TERASTATION_WXL) += buffalo-wxl-setup.o
diff --git a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
new file mode 100644
index 0000000..61e5e58
--- /dev/null
+++ b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
@@ -0,0 +1,155 @@
+/*
+ * arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
+ *
+ * Buffalo WXL (Terastation Duo) Setup routines
+ *
+ * sebastien requiem <sebastien@requiem.fr>
+ *
+ * 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/ethtool.h>
+#include <linux/i2c.h>
+#include <mach/mv78xx0.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include "common.h"
+#include "mpp.h"
+
+
+/* This arch has 2 Giga Ethernet */
+
+static struct mv643xx_eth_platform_data db78x00_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
+};
+
+static struct mv643xx_eth_platform_data db78x00_ge01_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
+};
+
+
+/* 2 SATA controller supporting HotPlug */
+
+static struct mv_sata_platform_data db78x00_sata_data = {
+	.n_ports	= 2,
+};
+
+static struct i2c_board_info __initdata db78x00_i2c_rtc = {
+	I2C_BOARD_INFO("ds1338", 0x68),
+};
+
+
+static unsigned int wxl_mpp_config[] __initdata = {
+	MPP0_GE1_TXCLK,
+	MPP1_GE1_TXCTL,
+	MPP2_GE1_RXCTL,
+	MPP3_GE1_RXCLK,
+	MPP4_GE1_TXD0,
+	MPP5_GE1_TXD1,
+	MPP6_GE1_TXD2,
+	MPP7_GE1_TXD3,
+	MPP8_GE1_RXD0,
+	MPP9_GE1_RXD1,
+	MPP10_GE1_RXD2,
+	MPP11_GE1_RXD3,
+	MPP12_GPIO,
+	MPP13_SYSRST_OUTn,
+	MPP14_SATA1_ACTn,
+	MPP15_SATA0_ACTn,
+	MPP16_GPIO,
+	MPP17_GPIO,
+	MPP18_GPIO,
+	MPP19_GPIO,
+	MPP20_GPIO,
+	MPP21_GPIO,
+	MPP22_GPIO,
+	MPP23_GPIO,
+	MPP24_UA2_TXD,
+	MPP25_UA2_RXD,
+	MPP26_UA2_CTSn,
+	MPP27_UA2_RTSn,
+	MPP28_GPIO,
+	MPP29_SYSRST_OUTn,
+	MPP30_GPIO,
+	MPP31_GPIO,
+	MPP32_GPIO,
+	MPP33_GPIO,
+	MPP34_GPIO,
+	MPP35_GPIO,
+	MPP36_GPIO,
+	MPP37_GPIO,
+	MPP38_GPIO,
+	MPP39_GPIO,
+	MPP40_UNUSED,
+	MPP41_UNUSED,
+	MPP42_UNUSED,
+	MPP43_UNUSED,
+	MPP44_UNUSED,
+	MPP45_UNUSED,
+	MPP46_UNUSED,
+	MPP47_UNUSED,
+	MPP48_SATA1_ACTn,
+	MPP49_SATA0_ACTn,
+	0
+};
+
+
+static void __init wxl_init(void)
+{
+	/*
+	 * Basic MV78xx0 setup. Needs to be called early.
+	 */
+	mv78xx0_init();
+	mv78xx0_mpp_conf(wxl_mpp_config);
+
+	/*
+	 * Partition on-chip peripherals between the two CPU cores.
+	 */
+	mv78xx0_ehci0_init();
+	mv78xx0_ehci1_init();
+	mv78xx0_ehci2_init();
+	mv78xx0_ge00_init(&db78x00_ge00_data);
+	mv78xx0_ge01_init(&db78x00_ge01_data);
+	mv78xx0_sata_init(&db78x00_sata_data);
+	mv78xx0_uart0_init();
+	mv78xx0_uart1_init();
+	mv78xx0_uart2_init();
+	mv78xx0_uart3_init();
+	mv78xx0_i2c_init();
+	i2c_register_board_info(0, &db78x00_i2c_rtc, 1);
+}
+
+static int __init wxl_pci_init(void)
+{
+	if (machine_is_terastation_wxl()) {
+		/*
+		 * Assign the x16 PCIe slot on the board to CPU core
+		 * #0, and let CPU core #1 have the four x1 slots.
+		 */
+		if (mv78xx0_core_index() == 0)
+			mv78xx0_pcie_init(0, 1);
+		else
+			mv78xx0_pcie_init(1, 0);
+	}
+
+	return 0;
+}
+subsys_initcall(wxl_pci_init);
+
+MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL")
+	/* Maintainer: Sebastien Requiem <sebastien@requiem.fr> */
+	.phys_io	= MV78XX0_REGS_PHYS_BASE,
+	.io_pg_offst	= ((MV78XX0_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= wxl_init,
+	.map_io		= mv78xx0_map_io,
+	.init_irq	= mv78xx0_init_irq,
+	.timer		= &mv78xx0_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mv78xx0/mpp.c b/arch/arm/mach-mv78xx0/mpp.c
new file mode 100644
index 0000000..354ac51
--- /dev/null
+++ b/arch/arm/mach-mv78xx0/mpp.c
@@ -0,0 +1,96 @@
+/*
+ * arch/arm/mach-mv78x00/mpp.c
+ *
+ * MPP functions for Marvell MV78x00 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/init.h>
+#include <linux/mbus.h>
+#include <linux/io.h>
+#include <asm/gpio.h>
+#include <mach/hardware.h>
+#include "common.h"
+#include "mpp.h"
+
+static unsigned int __init mv78xx0_variant(void)
+{
+	u32 dev, rev;
+
+	mv78xx0_pcie_id(&dev, &rev);
+
+	if (dev == MV78100_DEV_ID && rev >= MV78100_REV_A0)
+		return MPP_78100_A0_MASK;
+
+	printk(KERN_ERR "MPP setup: unknown mv78x00 variant "
+			"(dev %#x rev %#x)\n", dev, rev);
+	return 0;
+}
+
+#define MPP_CTRL(i)	(DEV_BUS_VIRT_BASE + (i) * 4)
+#define MPP_NR_REGS	(1 + MPP_MAX/8)
+
+void __init mv78xx0_mpp_conf(unsigned int *mpp_list)
+{
+	u32 mpp_ctrl[MPP_NR_REGS];
+	unsigned int variant_mask;
+	int i;
+
+	variant_mask = mv78xx0_variant();
+	if (!variant_mask)
+		return;
+
+	/* Initialize gpiolib. */
+	orion_gpio_init();
+
+	printk(KERN_DEBUG "initial MPP regs:");
+	for (i = 0; i < MPP_NR_REGS; i++) {
+		mpp_ctrl[i] = readl(MPP_CTRL(i));
+		printk(" %08x", mpp_ctrl[i]);
+	}
+	printk("\n");
+
+	while (*mpp_list) {
+		unsigned int num = MPP_NUM(*mpp_list);
+		unsigned int sel = MPP_SEL(*mpp_list);
+		int shift, gpio_mode;
+
+		if (num > MPP_MAX) {
+			printk(KERN_ERR "mv78xx0_mpp_conf: invalid MPP "
+					"number (%u)\n", num);
+			continue;
+		}
+		if (!(*mpp_list & variant_mask)) {
+			printk(KERN_WARNING
+					"mv78xx0_mpp_conf: requested MPP%u config "
+					"unavailable on this hardware\n", num);
+			continue;
+		}
+
+		shift = (num & 7) << 2;
+		mpp_ctrl[num / 8] &= ~(0xf << shift);
+		mpp_ctrl[num / 8] |= sel << shift;
+
+		gpio_mode = 0;
+		if (*mpp_list & MPP_INPUT_MASK)
+			gpio_mode |= GPIO_INPUT_OK;
+		if (*mpp_list & MPP_OUTPUT_MASK)
+			gpio_mode |= GPIO_OUTPUT_OK;
+		if (sel != 0)
+			gpio_mode = 0;
+		orion_gpio_set_valid(num, gpio_mode);
+
+		mpp_list++;
+	}
+
+	printk(KERN_DEBUG "  final MPP regs:");
+	for (i = 0; i < MPP_NR_REGS; i++) {
+		writel(mpp_ctrl[i], MPP_CTRL(i));
+		printk(" %08x", mpp_ctrl[i]);
+	}
+	printk("\n");
+}
diff --git a/arch/arm/mach-mv78xx0/mpp.h b/arch/arm/mach-mv78xx0/mpp.h
new file mode 100644
index 0000000..80840b7
--- /dev/null
+++ b/arch/arm/mach-mv78xx0/mpp.h
@@ -0,0 +1,347 @@
+/*
+ * linux/arch/arm/mach-mv78xx0/mpp.h -- Multi Purpose Pins
+ *
+ *
+ * sebastien requiem <sebastien@requiem.fr>
+ *
+ * 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 __MV78X00_MPP_H
+#define __MV78X00_MPP_H
+
+#define MPP(_num, _sel, _in, _out, _78100_A0) (\
+    /* MPP number */        ((_num) & 0xff) | \
+    /* MPP select value */        (((_sel) & 0xf) << 8) | \
+    /* may be input signal */    ((!!(_in)) << 12) | \
+    /* may be output signal */    ((!!(_out)) << 13) | \
+    /* available on A0 */    ((!!(_78100_A0)) << 14))
+
+#define MPP_NUM(x)    ((x) & 0xff)
+#define MPP_SEL(x)    (((x) >> 8) & 0xf)
+
+                /*   num sel  i  o  78100_A0  */
+
+#define MPP_INPUT_MASK        MPP(0, 0x0, 1, 0, 0)
+#define MPP_OUTPUT_MASK        MPP(0, 0x0, 0, 1, 0)
+
+#define MPP_78100_A0_MASK    MPP(0, 0x0, 0, 0, 1)
+
+#define MPP0_GPIO        MPP(0, 0x0, 1, 1, 1)
+#define MPP0_GE0_COL        MPP(0, 0x1, 1, 0, 1)
+#define MPP0_GE1_TXCLK        MPP(0, 0x2, 0, 1, 1)
+#define MPP0_UNUSED        MPP(0, 0x3, 0, 0, 1)
+
+#define MPP1_GPIO        MPP(1, 0x0, 1, 1, 1)
+#define MPP1_GE0_RXERR        MPP(1, 0x1, 1, 0, 1)
+#define MPP1_GE1_TXCTL        MPP(1, 0x2, 0, 1, 1)
+#define MPP1_UNUSED        MPP(1, 0x3, 0, 0, 1)
+
+#define MPP2_GPIO        MPP(2, 0x0, 1, 1, 1)
+#define MPP2_GE0_CRS        MPP(2, 0x1, 1, 0, 1)
+#define MPP2_GE1_RXCTL        MPP(2, 0x2, 1, 0, 1)
+#define MPP2_UNUSED        MPP(2, 0x3, 0, 0, 1)
+
+#define MPP3_GPIO        MPP(3, 0x0, 1, 1, 1)
+#define MPP3_GE0_TXERR        MPP(3, 0x1, 0, 1, 1)
+#define MPP3_GE1_RXCLK        MPP(3, 0x2, 1, 0, 1)
+#define MPP3_UNUSED        MPP(3, 0x3, 0, 0, 1)
+
+#define MPP4_GPIO        MPP(4, 0x0, 1, 1, 1)
+#define MPP4_GE0_TXD4        MPP(4, 0x1, 0, 1, 1)
+#define MPP4_GE1_TXD0        MPP(4, 0x2, 0, 1, 1)
+#define MPP4_UNUSED        MPP(4, 0x3, 0, 0, 1)
+
+#define MPP5_GPIO        MPP(5, 0x0, 1, 1, 1)
+#define MPP5_GE0_TXD5        MPP(5, 0x1, 0, 1, 1)
+#define MPP5_GE1_TXD1        MPP(5, 0x2, 0, 1, 1)
+#define MPP5_UNUSED        MPP(5, 0x3, 0, 0, 1)
+
+#define MPP6_GPIO        MPP(6, 0x0, 1, 1, 1)
+#define MPP6_GE0_TXD6        MPP(6, 0x1, 0, 1, 1)
+#define MPP6_GE1_TXD2        MPP(6, 0x2, 0, 1, 1)
+#define MPP6_UNUSED        MPP(6, 0x3, 0, 0, 1)
+
+#define MPP7_GPIO        MPP(7, 0x0, 1, 1, 1)
+#define MPP7_GE0_TXD7        MPP(7, 0x1, 0, 1, 1)
+#define MPP7_GE1_TXD3        MPP(7, 0x2, 0, 1, 1)
+#define MPP7_UNUSED        MPP(7, 0x3, 0, 0, 1)
+
+#define MPP8_GPIO        MPP(8, 0x0, 1, 1, 1)
+#define MPP8_GE0_RXD4        MPP(8, 0x1, 1, 0, 1)
+#define MPP8_GE1_RXD0        MPP(8, 0x2, 1, 0, 1)
+#define MPP8_UNUSED        MPP(8, 0x3, 0, 0, 1)
+
+#define MPP9_GPIO        MPP(9, 0x0, 1, 1, 1)
+#define MPP9_GE0_RXD5        MPP(9, 0x1, 1, 0, 1)
+#define MPP9_GE1_RXD1        MPP(9, 0x2, 1, 0, 1)
+#define MPP9_UNUSED        MPP(9, 0x3, 0, 0, 1)
+
+#define MPP10_GPIO        MPP(10, 0x0, 1, 1, 1)
+#define MPP10_GE0_RXD6        MPP(10, 0x1, 1, 0, 1)
+#define MPP10_GE1_RXD2        MPP(10, 0x2, 1, 0, 1)
+#define MPP10_UNUSED        MPP(10, 0x3, 0, 0, 1)
+
+#define MPP11_GPIO        MPP(11, 0x0, 1, 1, 1)
+#define MPP11_GE0_RXD7        MPP(11, 0x1, 1, 0, 1)
+#define MPP11_GE1_RXD3        MPP(11, 0x2, 1, 0, 1)
+#define MPP11_UNUSED        MPP(11, 0x3, 0, 0, 1)
+
+#define MPP12_GPIO        MPP(12, 0x0, 1, 1, 1)
+#define MPP12_M_BB        MPP(12, 0x3, 1, 0, 1)
+#define MPP12_UA0_CTSn        MPP(12, 0x4, 1, 0, 1)
+#define MPP12_NAND_FLASH_REn0    MPP(12, 0x5, 0, 1, 1)
+#define MPP12_TDM0_SCSn        MPP(12, 0X6, 0, 1, 1)
+#define MPP12_UNUSED        MPP(12, 0x1, 0, 0, 1)
+
+#define MPP13_GPIO        MPP(13, 0x0, 1, 1, 1)
+#define MPP13_SYSRST_OUTn    MPP(13, 0x3, 0, 1, 1)
+#define MPP13_UA0_RTSn        MPP(13, 0x4, 0, 1, 1)
+#define MPP13_NAN_FLASH_WEn0    MPP(13, 0x5, 0, 1, 1)
+#define MPP13_TDM_SCLK        MPP(13, 0x6, 0, 1, 1)
+#define MPP13_UNUSED        MPP(13, 0x1, 0, 0, 1)
+
+#define MPP14_GPIO        MPP(14, 0x0, 1, 1, 1)
+#define MPP14_SATA1_ACTn    MPP(14, 0x3, 0, 1, 1)
+#define MPP14_UA1_CTSn        MPP(14, 0x4, 1, 0, 1)
+#define MPP14_NAND_FLASH_REn1    MPP(14, 0x5, 0, 1, 1)
+#define MPP14_TDM_SMOSI        MPP(14, 0x6, 0, 1, 1)
+#define MPP14_UNUSED        MPP(14, 0x1, 0, 0, 1)
+
+#define MPP15_GPIO        MPP(15, 0x0, 1, 1, 1)
+#define MPP15_SATA0_ACTn    MPP(15, 0x3, 0, 1, 1)
+#define MPP15_UA1_RTSn        MPP(15, 0x4, 0, 1, 1)
+#define MPP15_NAND_FLASH_WEn1    MPP(15, 0x5, 0, 1, 1)
+#define MPP15_TDM_SMISO        MPP(15, 0x6, 1, 0, 1)
+#define MPP15_UNUSED        MPP(15, 0x1, 0, 0, 1)
+
+#define MPP16_GPIO        MPP(16, 0x0, 1, 1, 1)
+#define MPP16_SATA1_PRESENTn    MPP(16, 0x3, 0, 1, 1)
+#define MPP16_UA2_TXD        MPP(16, 0x4, 0, 1, 1)
+#define MPP16_NAND_FLASH_REn3    MPP(16, 0x5, 0, 1, 1)
+#define MPP16_TDM_INTn        MPP(16, 0x6, 1, 0, 1)
+#define MPP16_UNUSED        MPP(16, 0x1, 0, 0, 1)
+
+
+#define MPP17_GPIO        MPP(17, 0x0, 1, 1, 1)
+#define MPP17_SATA0_PRESENTn    MPP(17, 0x3, 0, 1, 1)
+#define MPP17_UA2_RXD        MPP(17, 0x4, 1, 0, 1)
+#define MPP17_NAND_FLASH_WEn3    MPP(17, 0x5, 0, 1, 1)
+#define MPP17_TDM_RSTn        MPP(17, 0x6, 0, 1, 1)
+#define MPP17_UNUSED        MPP(17, 0x1, 0, 0, 1)
+
+
+#define MPP18_GPIO        MPP(18, 0x0, 1, 1, 1)
+#define MPP18_UA0_CTSn        MPP(18, 0x4, 1, 0, 1)
+#define MPP18_BOOT_FLASH_REn    MPP(18, 0x5, 0, 1, 1)
+#define MPP18_UNUSED        MPP(18, 0x1, 0, 0, 1)
+
+
+
+#define MPP19_GPIO        MPP(19, 0x0, 1, 1, 1)
+#define MPP19_UA0_CTSn        MPP(19, 0x4, 0, 1, 1)
+#define MPP19_BOOT_FLASH_WEn    MPP(19, 0x5, 0, 1, 1)
+#define MPP19_UNUSED        MPP(19, 0x1, 0, 0, 1)
+
+
+#define MPP20_GPIO        MPP(20, 0x0, 1, 1, 1)
+#define MPP20_UA1_CTSs        MPP(20, 0x4, 1, 0, 1)
+#define MPP20_TDM_PCLK        MPP(20, 0x6, 1, 1, 0)
+#define MPP20_UNUSED        MPP(20, 0x1, 0, 0, 1)
+
+
+
+#define MPP21_GPIO        MPP(21, 0x0, 1, 1, 1)
+#define MPP21_UA1_CTSs        MPP(21, 0x4, 0, 1, 1)
+#define MPP21_TDM_FSYNC        MPP(21, 0x6, 1, 1, 0)
+#define MPP21_UNUSED        MPP(21, 0x1, 0, 0, 1)
+
+
+
+#define MPP22_GPIO        MPP(22, 0x0, 1, 1, 1)
+#define MPP22_UA3_TDX        MPP(22, 0x4, 0, 1, 1)
+#define MPP22_NAND_FLASH_REn2    MPP(22, 0x5, 0, 1, 1)
+#define MPP22_TDM_DRX        MPP(22, 0x6, 1, 0, 1)
+#define MPP22_UNUSED        MPP(22, 0x1, 0, 0, 1)
+
+
+
+#define MPP23_GPIO        MPP(23, 0x0, 1, 1, 1)
+#define MPP23_UA3_RDX        MPP(23, 0x4, 1, 0, 1)
+#define MPP23_NAND_FLASH_WEn2    MPP(23, 0x5, 0, 1, 1)
+#define MPP23_TDM_DTX        MPP(23, 0x6, 0, 1, 1)
+#define MPP23_UNUSED        MPP(23, 0x1, 0, 0, 1)
+
+
+#define MPP24_GPIO        MPP(24, 0x0, 1, 1, 1)
+#define MPP24_UA2_TXD        MPP(24, 0x4, 0, 1, 1)
+#define MPP24_TDM_INTn        MPP(24, 0x6, 1, 0, 1)
+#define MPP24_UNUSED        MPP(24, 0x1, 0, 0, 1)
+
+
+#define MPP25_GPIO        MPP(25, 0x0, 1, 1, 1)
+#define MPP25_UA2_RXD        MPP(25, 0x4, 1, 0, 1)
+#define MPP25_TDM_RSTn        MPP(25, 0x6, 0, 1, 1)
+#define MPP25_UNUSED        MPP(25, 0x1, 0, 0, 1)
+
+
+#define MPP26_GPIO        MPP(26, 0x0, 1, 1, 1)
+#define MPP26_UA2_CTSn        MPP(26, 0x4, 1, 0, 1)
+#define MPP26_TDM_PCLK        MPP(26, 0x6, 1, 1, 1)
+#define MPP26_UNUSED        MPP(26, 0x1, 0, 0, 1)
+
+
+#define MPP27_GPIO        MPP(27, 0x0, 1, 1, 1)
+#define MPP27_UA2_RTSn        MPP(27, 0x4, 0, 1, 1)
+#define MPP27_TDM_FSYNC        MPP(27, 0x6, 1, 1, 1)
+#define MPP27_UNUSED        MPP(27, 0x1, 0, 0, 1)
+
+
+#define MPP28_GPIO        MPP(28, 0x0, 1, 1, 1)
+#define MPP28_UA3_TXD        MPP(28, 0x4, 0, 1, 1)
+#define MPP28_TDM_DRX        MPP(28, 0x6, 1, 0, 1)
+#define MPP28_UNUSED        MPP(28, 0x1, 0, 0, 1)
+
+#define MPP29_GPIO        MPP(29, 0x0, 1, 1, 1)
+#define MPP29_UA3_RXD        MPP(29, 0x4, 1, 0, 1)
+#define MPP29_SYSRST_OUTn    MPP(29, 0x5, 0, 1, 1)
+#define MPP29_TDM_DTX        MPP(29, 0x6, 0, 1, 1)
+#define MPP29_UNUSED        MPP(29, 0x1, 0, 0, 1)
+
+#define MPP30_GPIO        MPP(30, 0x0, 1, 1, 1)
+#define MPP30_UA3_CTSn        MPP(30, 0x4, 1, 0, 1)
+#define MPP30_UNUSED        MPP(30, 0x1, 0, 0, 1)
+
+#define MPP31_GPIO        MPP(31, 0x0, 1, 1, 1)
+#define MPP31_UA3_RTSn        MPP(31, 0x4, 0, 1, 1)
+#define MPP31_TDM1_SCSn        MPP(31, 0x6, 0, 1, 1)
+#define MPP31_UNUSED        MPP(31, 0x1, 0, 0, 1)
+
+
+#define MPP32_GPIO        MPP(32, 0x1, 1, 1, 1)
+#define MPP32_UA3_TDX        MPP(32, 0x4, 0, 1, 1)
+#define MPP32_SYSRST_OUTn    MPP(32, 0x5, 0, 1, 1)
+#define MPP32_TDM0_RXQ        MPP(32, 0x6, 0, 1, 1)
+#define MPP32_UNUSED        MPP(32, 0x3, 0, 0, 1)
+
+
+#define MPP33_GPIO        MPP(33, 0x1, 1, 1, 1)
+#define MPP33_UA3_RDX        MPP(33, 0x4, 1, 0, 1)
+#define MPP33_TDM0_TXQ        MPP(33, 0x6, 0, 1, 1)
+#define MPP33_UNUSED        MPP(33, 0x3, 0, 0, 1)
+
+
+
+#define MPP34_GPIO        MPP(34, 0x1, 1, 1, 1)
+#define MPP34_UA2_TDX        MPP(34, 0x4, 0, 1, 1)
+#define MPP34_TDM1_RXQ        MPP(34, 0x6, 0, 1, 1)
+#define MPP34_UNUSED        MPP(34, 0x3, 0, 0, 1)
+
+
+
+#define MPP35_GPIO        MPP(35, 0x1, 1, 1, 1)
+#define MPP35_UA2_RDX        MPP(35, 0x4, 1, 0, 1)
+#define MPP35_TDM1_TXQ        MPP(35, 0x6, 0, 1, 1)
+#define MPP35_UNUSED        MPP(35, 0x3, 0, 0, 1)
+
+#define MPP36_GPIO        MPP(36, 0x1, 1, 1, 1)
+#define MPP36_UA0_CTSn        MPP(36, 0x2, 1, 0, 1)
+#define MPP36_UA2_TDX        MPP(36, 0x4, 0, 1, 1)
+#define MPP36_TDM0_SCSn        MPP(36, 0x6, 0, 1, 1)
+#define MPP36_UNUSED        MPP(36, 0x3, 0, 0, 1)
+
+
+#define MPP37_GPIO        MPP(37, 0x1, 1, 1, 1)
+#define MPP37_UA0_RTSn        MPP(37, 0x2, 0, 1, 1)
+#define MPP37_UA2_RXD        MPP(37, 0x4, 1, 0, 1)
+#define MPP37_SYSRST_OUTn    MPP(37, 0x5, 0, 1, 1)
+#define MPP37_TDM_SCLK        MPP(37, 0x6, 0, 1, 1)
+#define MPP37_UNUSED        MPP(37, 0x3, 0, 0, 1)
+
+
+
+
+#define MPP38_GPIO        MPP(38, 0x1, 1, 1, 1)
+#define MPP38_UA1_CTSn        MPP(38, 0x2, 1, 0, 1)
+#define MPP38_UA3_TXD        MPP(38, 0x4, 0, 1, 1)
+#define MPP38_SYSRST_OUTn    MPP(38, 0x5, 0, 1, 1)
+#define MPP38_TDM_SMOSI        MPP(38, 0x6, 0, 1, 1)
+#define MPP38_UNUSED        MPP(38, 0x3, 0, 0, 1)
+
+
+
+
+#define MPP39_GPIO        MPP(39, 0x1, 1, 1, 1)
+#define MPP39_UA1_RTSn        MPP(39, 0x2, 0, 1, 1)
+#define MPP39_UA3_RXD        MPP(39, 0x4, 1, 0, 1)
+#define MPP39_SYSRST_OUTn    MPP(39, 0x5, 0, 1, 1)
+#define MPP39_TDM_SMISO        MPP(39, 0x6, 1, 0, 1)
+#define MPP39_UNUSED        MPP(39, 0x3, 0, 0, 1)
+
+
+
+#define MPP40_GPIO        MPP(40, 0x1, 1, 1, 1)
+#define MPP40_TDM_INTn        MPP(40, 0x6, 1, 0, 1)
+#define MPP40_UNUSED        MPP(40, 0x0, 0, 0, 1)
+
+
+
+#define MPP41_GPIO        MPP(41, 0x1, 1, 1, 1)
+#define MPP41_TDM_RSTn        MPP(41, 0x6, 0, 1, 1)
+#define MPP41_UNUSED        MPP(41, 0x0, 0, 0, 1)
+
+
+
+#define MPP42_GPIO        MPP(42, 0x1, 1, 1, 1)
+#define MPP42_TDM_PCLK        MPP(42, 0x6, 1, 1, 1)
+#define MPP42_UNUSED        MPP(42, 0x0, 0, 0, 1)
+
+
+
+#define MPP43_GPIO        MPP(43, 0x1, 1, 1, 1)
+#define MPP43_TDM_FSYNC        MPP(43, 0x6, 1, 1, 1)
+#define MPP43_UNUSED        MPP(43, 0x0, 0, 0, 1)
+
+
+
+#define MPP44_GPIO        MPP(44, 0x1, 1, 1, 1)
+#define MPP44_TDM_DRX        MPP(44, 0x6, 1, 0, 1)
+#define MPP44_UNUSED        MPP(44, 0x0, 0, 0, 1)
+
+
+
+#define MPP45_GPIO        MPP(45, 0x1, 1, 1, 1)
+#define MPP45_SATA0_ACTn    MPP(45, 0x3, 0, 1, 1)
+#define MPP45_TDM_DRX        MPP(45, 0x6, 0, 1, 1)
+#define MPP45_UNUSED        MPP(45, 0x0, 0, 0, 1)
+
+
+#define MPP46_GPIO        MPP(46, 0x1, 1, 1, 1)
+#define MPP46_TDM_SCSn        MPP(46, 0x6, 0, 1, 1)
+#define MPP46_UNUSED        MPP(46, 0x0, 0, 0, 1)
+
+
+#define MPP47_GPIO        MPP(47, 0x1, 1, 1, 1)
+#define MPP47_UNUSED        MPP(47, 0x0, 0, 0, 1)
+
+
+
+#define MPP48_GPIO        MPP(48, 0x1, 1, 1, 1)
+#define MPP48_SATA1_ACTn    MPP(48, 0x3, 0, 1, 1)
+#define MPP48_UNUSED        MPP(48, 0x2, 0, 0, 1)
+
+
+
+#define MPP49_GPIO        MPP(49, 0x1, 1, 1, 1)
+#define MPP49_SATA0_ACTn    MPP(49, 0x3, 0, 1, 1)
+#define MPP49_M_BB        MPP(49, 0x4, 1, 0, 1)
+#define MPP49_UNUSED        MPP(49, 0x2, 0, 0, 1)
+
+
+#define MPP_MAX            49
+
+void mv78xx0_mpp_conf(unsigned int *mpp_list);
+
+#endif
diff --git a/arch/arm/mach-mx1/Makefile b/arch/arm/mach-mx1/Makefile
index 7f86fe0..fc2ddf8 100644
--- a/arch/arm/mach-mx1/Makefile
+++ b/arch/arm/mach-mx1/Makefile
@@ -4,11 +4,12 @@
 
 # Object file lists.
 
+EXTRA_CFLAGS += -DIMX_NEEDS_DEPRECATED_SYMBOLS
 obj-y			+= generic.o clock.o devices.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO)	+= ksym_mx1.o mx1_camera_fiq.o
 
 # Specific board support
-obj-$(CONFIG_ARCH_MX1ADS) += mx1ads.o
-obj-$(CONFIG_MACH_SCB9328) += scb9328.o
\ No newline at end of file
+obj-$(CONFIG_ARCH_MX1ADS) += mach-mx1ads.o
+obj-$(CONFIG_MACH_SCB9328) += mach-scb9328.o
diff --git a/arch/arm/mach-mx1/mach-mx1ads.c b/arch/arm/mach-mx1/mach-mx1ads.c
new file mode 100644
index 0000000..51f3cfd
--- /dev/null
+++ b/arch/arm/mach-mx1/mach-mx1ads.c
@@ -0,0 +1,165 @@
+/*
+ * arch/arm/mach-imx/mach-mx1ads.c
+ *
+ * Initially based on:
+ *	linux-2.6.7-imx/arch/arm/mach-imx/scb9328.c
+ *	Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
+ *
+ * 2004 (c) MontaVista Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/i2c.h>
+#include <linux/i2c/pcf857x.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/i2c.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx1.h>
+#include <mach/irqs.h>
+
+#include "devices.h"
+
+static int mx1ads_pins[] = {
+	/* UART1 */
+	PC9_PF_UART1_CTS,
+	PC10_PF_UART1_RTS,
+	PC11_PF_UART1_TXD,
+	PC12_PF_UART1_RXD,
+	/* UART2 */
+	PB28_PF_UART2_CTS,
+	PB29_PF_UART2_RTS,
+	PB30_PF_UART2_TXD,
+	PB31_PF_UART2_RXD,
+	/* I2C */
+	PA15_PF_I2C_SDA,
+	PA16_PF_I2C_SCL,
+	/* SPI */
+	PC13_PF_SPI1_SPI_RDY,
+	PC14_PF_SPI1_SCLK,
+	PC15_PF_SPI1_SS,
+	PC16_PF_SPI1_MISO,
+	PC17_PF_SPI1_MOSI,
+};
+
+/*
+ * UARTs platform data
+ */
+
+static struct imxuart_platform_data uart_pdata[] = {
+	{
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	},
+};
+
+/*
+ * Physmap flash
+ */
+
+static struct physmap_flash_data mx1ads_flash_data = {
+	.width		= 4,		/* bankwidth in bytes */
+};
+
+static struct resource flash_resource = {
+	.start	= IMX_CS0_PHYS,
+	.end	= IMX_CS0_PHYS + SZ_32M - 1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.resource = &flash_resource,
+	.num_resources = 1,
+};
+
+/*
+ * I2C
+ */
+static struct pcf857x_platform_data pcf857x_data[] = {
+	{
+		.gpio_base = 4 * 32,
+	}, {
+		.gpio_base = 4 * 32 + 16,
+	}
+};
+
+static struct imxi2c_platform_data mx1ads_i2c_data = {
+	.bitrate = 100000,
+};
+
+static struct i2c_board_info mx1ads_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("pcf8575", 0x22),
+		.platform_data = &pcf857x_data[0],
+	}, {
+		I2C_BOARD_INFO("pcf8575", 0x24),
+		.platform_data = &pcf857x_data[1],
+	},
+};
+
+/*
+ * Board init
+ */
+static void __init mx1ads_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mx1ads_pins,
+		ARRAY_SIZE(mx1ads_pins), "mx1ads");
+
+	/* UART */
+	mxc_register_device(&imx_uart1_device, &uart_pdata[0]);
+	mxc_register_device(&imx_uart2_device, &uart_pdata[1]);
+
+	/* Physmap flash */
+	mxc_register_device(&flash_device, &mx1ads_flash_data);
+
+	/* I2C */
+	i2c_register_board_info(0, mx1ads_i2c_devices,
+				ARRAY_SIZE(mx1ads_i2c_devices));
+
+	mxc_register_device(&imx_i2c_device, &mx1ads_i2c_data);
+}
+
+static void __init mx1ads_timer_init(void)
+{
+	mx1_clocks_init(32000);
+}
+
+struct sys_timer mx1ads_timer = {
+	.init	= mx1ads_timer_init,
+};
+
+MACHINE_START(MX1ADS, "Freescale MX1ADS")
+	/* Maintainer: Sascha Hauer, Pengutronix */
+	.phys_io	= IMX_IO_PHYS,
+	.io_pg_offst	= (IMX_IO_BASE >> 18) & 0xfffc,
+	.boot_params	= MX1_PHYS_OFFSET + 0x100,
+	.map_io		= mx1_map_io,
+	.init_irq	= mx1_init_irq,
+	.timer		= &mx1ads_timer,
+	.init_machine	= mx1ads_init,
+MACHINE_END
+
+MACHINE_START(MXLADS, "Freescale MXLADS")
+	.phys_io	= IMX_IO_PHYS,
+	.io_pg_offst	= (IMX_IO_BASE >> 18) & 0xfffc,
+	.boot_params	= MX1_PHYS_OFFSET + 0x100,
+	.map_io		= mx1_map_io,
+	.init_irq	= mx1_init_irq,
+	.timer		= &mx1ads_timer,
+	.init_machine	= mx1ads_init,
+MACHINE_END
diff --git a/arch/arm/mach-mx1/mach-scb9328.c b/arch/arm/mach-mx1/mach-scb9328.c
new file mode 100644
index 0000000..7587a7a
--- /dev/null
+++ b/arch/arm/mach-mx1/mach-scb9328.c
@@ -0,0 +1,158 @@
+/*
+ * linux/arch/arm/mach-mx1/mach-scb9328.c
+ *
+ * Copyright (c) 2004 Sascha Hauer <saschahauer@web.de>
+ * Copyright (c) 2006-2008 Juergen Beisert <jbeisert@netscape.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/interrupt.h>
+#include <linux/dm9000.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx1.h>
+
+#include "devices.h"
+
+/*
+ * This scb9328 has a 32MiB flash
+ */
+static struct resource flash_resource = {
+	.start	= IMX_CS0_PHYS,
+	.end	= IMX_CS0_PHYS + (32 * 1024 * 1024) - 1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct physmap_flash_data scb_flash_data = {
+	.width  = 2,
+};
+
+static struct platform_device scb_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev = {
+		.platform_data = &scb_flash_data,
+	},
+	.resource = &flash_resource,
+	.num_resources = 1,
+};
+
+/*
+ * scb9328 has a DM9000 network controller
+ * connected to CS5, with 16 bit data path
+ * and interrupt connected to GPIO 3
+ */
+
+/*
+ * internal datapath is fixed 16 bit
+ */
+static struct dm9000_plat_data dm9000_platdata = {
+	.flags	= DM9000_PLATF_16BITONLY,
+};
+
+/*
+ * the DM9000 drivers wants two defined address spaces
+ * to gain access to address latch registers and the data path.
+ */
+static struct resource dm9000x_resources[] = {
+	{
+		.name	= "address area",
+		.start	= IMX_CS5_PHYS,
+		.end	= IMX_CS5_PHYS + 1,
+		.flags	= IORESOURCE_MEM,	/* address access */
+	}, {
+		.name	= "data area",
+		.start	= IMX_CS5_PHYS + 4,
+		.end	= IMX_CS5_PHYS + 5,
+		.flags	= IORESOURCE_MEM,	/* data access */
+	}, {
+		.start	= IRQ_GPIOC(3),
+		.end	= IRQ_GPIOC(3),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+	},
+};
+
+static struct platform_device dm9000x_device = {
+	.name		= "dm9000",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(dm9000x_resources),
+	.resource	= dm9000x_resources,
+	.dev		= {
+		.platform_data = &dm9000_platdata,
+	}
+};
+
+static int mxc_uart1_pins[] = {
+	PC9_PF_UART1_CTS,
+	PC10_PF_UART1_RTS,
+	PC11_PF_UART1_TXD,
+	PC12_PF_UART1_RXD,
+};
+
+static int uart1_mxc_init(struct platform_device *pdev)
+{
+	return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
+			ARRAY_SIZE(mxc_uart1_pins), "UART1");
+}
+
+static int uart1_mxc_exit(struct platform_device *pdev)
+{
+	mxc_gpio_release_multiple_pins(mxc_uart1_pins,
+			ARRAY_SIZE(mxc_uart1_pins));
+	return 0;
+}
+
+static struct imxuart_platform_data uart_pdata = {
+	.init = uart1_mxc_init,
+	.exit = uart1_mxc_exit,
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&scb_flash_device,
+	&dm9000x_device,
+};
+
+/*
+ * scb9328_init - Init the CPU card itself
+ */
+static void __init scb9328_init(void)
+{
+	mxc_register_device(&imx_uart1_device, &uart_pdata);
+
+	printk(KERN_INFO"Scb9328: Adding devices\n");
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static void __init scb9328_timer_init(void)
+{
+	mx1_clocks_init(32000);
+}
+
+static struct sys_timer scb9328_timer = {
+	.init	= scb9328_timer_init,
+};
+
+MACHINE_START(SCB9328, "Synertronixx scb9328")
+    /* Sascha Hauer */
+	.phys_io	= 0x00200000,
+	.io_pg_offst	= ((0xe0200000) >> 18) & 0xfffc,
+	.boot_params	= 0x08000100,
+	.map_io		= mx1_map_io,
+	.init_irq	= mx1_init_irq,
+	.timer		= &scb9328_timer,
+	.init_machine	= scb9328_init,
+MACHINE_END
diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c
deleted file mode 100644
index 30f04e5..0000000
--- a/arch/arm/mach-mx1/mx1ads.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * arch/arm/mach-imx/mx1ads.c
- *
- * Initially based on:
- *	linux-2.6.7-imx/arch/arm/mach-imx/scb9328.c
- *	Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
- *
- * 2004 (c) MontaVista Software, Inc.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/i2c.h>
-#include <linux/i2c/pcf857x.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/i2c.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux.h>
-#include <mach/irqs.h>
-
-#include "devices.h"
-
-static int mx1ads_pins[] = {
-	/* UART1 */
-	PC9_PF_UART1_CTS,
-	PC10_PF_UART1_RTS,
-	PC11_PF_UART1_TXD,
-	PC12_PF_UART1_RXD,
-	/* UART2 */
-	PB28_PF_UART2_CTS,
-	PB29_PF_UART2_RTS,
-	PB30_PF_UART2_TXD,
-	PB31_PF_UART2_RXD,
-	/* I2C */
-	PA15_PF_I2C_SDA,
-	PA16_PF_I2C_SCL,
-	/* SPI */
-	PC13_PF_SPI1_SPI_RDY,
-	PC14_PF_SPI1_SCLK,
-	PC15_PF_SPI1_SS,
-	PC16_PF_SPI1_MISO,
-	PC17_PF_SPI1_MOSI,
-};
-
-/*
- * UARTs platform data
- */
-
-static struct imxuart_platform_data uart_pdata[] = {
-	{
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	},
-};
-
-/*
- * Physmap flash
- */
-
-static struct physmap_flash_data mx1ads_flash_data = {
-	.width		= 4,		/* bankwidth in bytes */
-};
-
-static struct resource flash_resource = {
-	.start	= IMX_CS0_PHYS,
-	.end	= IMX_CS0_PHYS + SZ_32M - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct platform_device flash_device = {
-	.name	= "physmap-flash",
-	.id	= 0,
-	.resource = &flash_resource,
-	.num_resources = 1,
-};
-
-/*
- * I2C
- */
-static struct pcf857x_platform_data pcf857x_data[] = {
-	{
-		.gpio_base = 4 * 32,
-	}, {
-		.gpio_base = 4 * 32 + 16,
-	}
-};
-
-static struct imxi2c_platform_data mx1ads_i2c_data = {
-	.bitrate = 100000,
-};
-
-static struct i2c_board_info mx1ads_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("pcf8575", 0x22),
-		.platform_data = &pcf857x_data[0],
-	}, {
-		I2C_BOARD_INFO("pcf8575", 0x24),
-		.platform_data = &pcf857x_data[1],
-	},
-};
-
-/*
- * Board init
- */
-static void __init mx1ads_init(void)
-{
-	mxc_gpio_setup_multiple_pins(mx1ads_pins,
-		ARRAY_SIZE(mx1ads_pins), "mx1ads");
-
-	/* UART */
-	mxc_register_device(&imx_uart1_device, &uart_pdata[0]);
-	mxc_register_device(&imx_uart2_device, &uart_pdata[1]);
-
-	/* Physmap flash */
-	mxc_register_device(&flash_device, &mx1ads_flash_data);
-
-	/* I2C */
-	i2c_register_board_info(0, mx1ads_i2c_devices,
-				ARRAY_SIZE(mx1ads_i2c_devices));
-
-	mxc_register_device(&imx_i2c_device, &mx1ads_i2c_data);
-}
-
-static void __init mx1ads_timer_init(void)
-{
-	mx1_clocks_init(32000);
-}
-
-struct sys_timer mx1ads_timer = {
-	.init	= mx1ads_timer_init,
-};
-
-MACHINE_START(MX1ADS, "Freescale MX1ADS")
-	/* Maintainer: Sascha Hauer, Pengutronix */
-	.phys_io	= IMX_IO_PHYS,
-	.io_pg_offst	= (IMX_IO_BASE >> 18) & 0xfffc,
-	.boot_params	= PHYS_OFFSET + 0x100,
-	.map_io		= mx1_map_io,
-	.init_irq	= mx1_init_irq,
-	.timer		= &mx1ads_timer,
-	.init_machine	= mx1ads_init,
-MACHINE_END
-
-MACHINE_START(MXLADS, "Freescale MXLADS")
-	.phys_io	= IMX_IO_PHYS,
-	.io_pg_offst	= (IMX_IO_BASE >> 18) & 0xfffc,
-	.boot_params	= PHYS_OFFSET + 0x100,
-	.map_io		= mx1_map_io,
-	.init_irq	= mx1_init_irq,
-	.timer		= &mx1ads_timer,
-	.init_machine	= mx1ads_init,
-MACHINE_END
diff --git a/arch/arm/mach-mx1/scb9328.c b/arch/arm/mach-mx1/scb9328.c
deleted file mode 100644
index 325d98d..0000000
--- a/arch/arm/mach-mx1/scb9328.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * linux/arch/arm/mach-mx1/scb9328.c
- *
- * Copyright (c) 2004 Sascha Hauer <saschahauer@web.de>
- * Copyright (c) 2006-2008 Juergen Beisert <jbeisert@netscape.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/interrupt.h>
-#include <linux/dm9000.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux.h>
-
-#include "devices.h"
-
-/*
- * This scb9328 has a 32MiB flash
- */
-static struct resource flash_resource = {
-	.start	= IMX_CS0_PHYS,
-	.end	= IMX_CS0_PHYS + (32 * 1024 * 1024) - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct physmap_flash_data scb_flash_data = {
-	.width  = 2,
-};
-
-static struct platform_device scb_flash_device = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev = {
-		.platform_data = &scb_flash_data,
-	},
-	.resource = &flash_resource,
-	.num_resources = 1,
-};
-
-/*
- * scb9328 has a DM9000 network controller
- * connected to CS5, with 16 bit data path
- * and interrupt connected to GPIO 3
- */
-
-/*
- * internal datapath is fixed 16 bit
- */
-static struct dm9000_plat_data dm9000_platdata = {
-	.flags	= DM9000_PLATF_16BITONLY,
-};
-
-/*
- * the DM9000 drivers wants two defined address spaces
- * to gain access to address latch registers and the data path.
- */
-static struct resource dm9000x_resources[] = {
-	{
-		.name	= "address area",
-		.start	= IMX_CS5_PHYS,
-		.end	= IMX_CS5_PHYS + 1,
-		.flags	= IORESOURCE_MEM,	/* address access */
-	}, {
-		.name	= "data area",
-		.start	= IMX_CS5_PHYS + 4,
-		.end	= IMX_CS5_PHYS + 5,
-		.flags	= IORESOURCE_MEM,	/* data access */
-	}, {
-		.start	= IRQ_GPIOC(3),
-		.end	= IRQ_GPIOC(3),
-		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},
-};
-
-static struct platform_device dm9000x_device = {
-	.name		= "dm9000",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(dm9000x_resources),
-	.resource	= dm9000x_resources,
-	.dev		= {
-		.platform_data = &dm9000_platdata,
-	}
-};
-
-static int mxc_uart1_pins[] = {
-	PC9_PF_UART1_CTS,
-	PC10_PF_UART1_RTS,
-	PC11_PF_UART1_TXD,
-	PC12_PF_UART1_RXD,
-};
-
-static int uart1_mxc_init(struct platform_device *pdev)
-{
-	return mxc_gpio_setup_multiple_pins(mxc_uart1_pins,
-			ARRAY_SIZE(mxc_uart1_pins), "UART1");
-}
-
-static int uart1_mxc_exit(struct platform_device *pdev)
-{
-	mxc_gpio_release_multiple_pins(mxc_uart1_pins,
-			ARRAY_SIZE(mxc_uart1_pins));
-	return 0;
-}
-
-static struct imxuart_platform_data uart_pdata = {
-	.init = uart1_mxc_init,
-	.exit = uart1_mxc_exit,
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct platform_device *devices[] __initdata = {
-	&scb_flash_device,
-	&dm9000x_device,
-};
-
-/*
- * scb9328_init - Init the CPU card itself
- */
-static void __init scb9328_init(void)
-{
-	mxc_register_device(&imx_uart1_device, &uart_pdata);
-
-	printk(KERN_INFO"Scb9328: Adding devices\n");
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-static void __init scb9328_timer_init(void)
-{
-	mx1_clocks_init(32000);
-}
-
-static struct sys_timer scb9328_timer = {
-	.init	= scb9328_timer_init,
-};
-
-MACHINE_START(SCB9328, "Synertronixx scb9328")
-    /* Sascha Hauer */
-	.phys_io	= 0x00200000,
-	.io_pg_offst	= ((0xe0200000) >> 18) & 0xfffc,
-	.boot_params	= 0x08000100,
-	.map_io		= mx1_map_io,
-	.init_irq	= mx1_init_irq,
-	.timer		= &scb9328_timer,
-	.init_machine	= scb9328_init,
-MACHINE_END
diff --git a/arch/arm/mach-mx2/Kconfig b/arch/arm/mach-mx2/Kconfig
index b96c6a3..742fd4e 100644
--- a/arch/arm/mach-mx2/Kconfig
+++ b/arch/arm/mach-mx2/Kconfig
@@ -37,6 +37,7 @@
 config MACH_PCM038
 	bool "Phytec phyCORE-i.MX27 CPU module (pcm038)"
 	depends on MACH_MX27
+	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for phyCORE-i.MX27 (aka pcm038) platform. This
 	  includes specific configurations for the module and its peripherals.
@@ -55,7 +56,7 @@
 
 endchoice
 
-config MACH_EUKREA_CPUIMX27
+config MACH_CPUIMX27
 	bool "Eukrea CPUIMX27 module"
 	depends on MACH_MX27
 	help
@@ -64,14 +65,14 @@
 
 config MACH_EUKREA_CPUIMX27_USESDHC2
 	bool "CPUIMX27 integrates SDHC2 module"
-	depends on MACH_EUKREA_CPUIMX27
+	depends on MACH_CPUIMX27
 	help
 	  This adds support for the internal SDHC2 used on CPUIMX27 used
 	  for wifi or eMMC.
 
 choice
 	prompt "Baseboard"
-	depends on MACH_EUKREA_CPUIMX27
+	depends on MACH_CPUIMX27
 	default MACH_EUKREA_MBIMX27_BASEBOARD
 
 config MACH_EUKREA_MBIMX27_BASEBOARD
@@ -90,7 +91,7 @@
 	  Include support for MX27PDK platform. This includes specific
 	  configurations for the board and its peripherals.
 
-config MACH_MX27LITE
+config MACH_IMX27LITE
 	bool "LogicPD MX27 LITEKIT platform"
 	depends on MACH_MX27
 	help
@@ -100,6 +101,7 @@
 config MACH_PCA100
 	bool "Phytec phyCARD-s (pca100)"
 	depends on MACH_MX27
+	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for phyCARD-s (aka pca100) platform. This
 	  includes specific configurations for the module and its peripherals.
diff --git a/arch/arm/mach-mx2/Makefile b/arch/arm/mach-mx2/Makefile
index 52aca0aa..e3254fa 100644
--- a/arch/arm/mach-mx2/Makefile
+++ b/arch/arm/mach-mx2/Makefile
@@ -4,21 +4,20 @@
 
 # Object file lists.
 
-obj-y	:=  generic.o devices.o serial.o
+obj-y	:=  devices.o serial.o
 
-obj-$(CONFIG_MACH_MX21) += clock_imx21.o
+obj-$(CONFIG_MACH_MX21) += clock_imx21.o mm-imx21.o
 
 obj-$(CONFIG_MACH_MX27) += cpu_imx27.o
-obj-$(CONFIG_MACH_MX27) += clock_imx27.o
+obj-$(CONFIG_MACH_MX27) += clock_imx27.o mm-imx27.o
 
-obj-$(CONFIG_MACH_MX21ADS) += mx21ads.o
-obj-$(CONFIG_MACH_MX27ADS) += mx27ads.o
-obj-$(CONFIG_MACH_PCM038) += pcm038.o
+obj-$(CONFIG_MACH_MX21ADS) += mach-mx21ads.o
+obj-$(CONFIG_MACH_MX27ADS) += mach-mx27ads.o
+obj-$(CONFIG_MACH_PCM038) += mach-pcm038.o
 obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o
-obj-$(CONFIG_MACH_MX27_3DS) += mx27pdk.o
-obj-$(CONFIG_MACH_MX27LITE) += mx27lite.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX27) += eukrea_cpuimx27.o
+obj-$(CONFIG_MACH_MX27_3DS) += mach-mx27_3ds.o
+obj-$(CONFIG_MACH_IMX27LITE) += mach-imx27lite.o
+obj-$(CONFIG_MACH_CPUIMX27) += mach-cpuimx27.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o
-obj-$(CONFIG_MACH_PCA100) += pca100.o
-obj-$(CONFIG_MACH_MXT_TD60) += mxt_td60.o
-
+obj-$(CONFIG_MACH_PCA100) += mach-pca100.o
+obj-$(CONFIG_MACH_MXT_TD60) += mach-mxt_td60.o
diff --git a/arch/arm/mach-mx2/clock_imx21.c b/arch/arm/mach-mx2/clock_imx21.c
index e82b489..bb419ef 100644
--- a/arch/arm/mach-mx2/clock_imx21.c
+++ b/arch/arm/mach-mx2/clock_imx21.c
@@ -23,11 +23,242 @@
 #include <linux/module.h>
 
 #include <mach/clock.h>
+#include <mach/hardware.h>
 #include <mach/common.h>
 #include <asm/clkdev.h>
 #include <asm/div64.h>
 
-#include "crm_regs.h"
+#define IO_ADDR_CCM(off)	(MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
+
+/* Register offsets */
+#define CCM_CSCR		IO_ADDR_CCM(0x0)
+#define CCM_MPCTL0		IO_ADDR_CCM(0x4)
+#define CCM_MPCTL1		IO_ADDR_CCM(0x8)
+#define CCM_SPCTL0		IO_ADDR_CCM(0xc)
+#define CCM_SPCTL1		IO_ADDR_CCM(0x10)
+#define CCM_OSC26MCTL		IO_ADDR_CCM(0x14)
+#define CCM_PCDR0		IO_ADDR_CCM(0x18)
+#define CCM_PCDR1		IO_ADDR_CCM(0x1c)
+#define CCM_PCCR0		IO_ADDR_CCM(0x20)
+#define CCM_PCCR1		IO_ADDR_CCM(0x24)
+#define CCM_CCSR		IO_ADDR_CCM(0x28)
+#define CCM_PMCTL		IO_ADDR_CCM(0x2c)
+#define CCM_PMCOUNT		IO_ADDR_CCM(0x30)
+#define CCM_WKGDCTL		IO_ADDR_CCM(0x34)
+
+#define CCM_CSCR_PRESC_OFFSET	29
+#define CCM_CSCR_PRESC_MASK	(0x7 << CCM_CSCR_PRESC_OFFSET)
+
+#define CCM_CSCR_USB_OFFSET	26
+#define CCM_CSCR_USB_MASK	(0x7 << CCM_CSCR_USB_OFFSET)
+#define CCM_CSCR_SD_OFFSET	24
+#define CCM_CSCR_SD_MASK	(0x3 << CCM_CSCR_SD_OFFSET)
+#define CCM_CSCR_SPLLRES	(1 << 22)
+#define CCM_CSCR_MPLLRES	(1 << 21)
+#define CCM_CSCR_SSI2_OFFSET	20
+#define CCM_CSCR_SSI2		(1 << CCM_CSCR_SSI2_OFFSET)
+#define CCM_CSCR_SSI1_OFFSET	19
+#define CCM_CSCR_SSI1		(1 << CCM_CSCR_SSI1_OFFSET)
+#define CCM_CSCR_FIR_OFFSET	18
+#define CCM_CSCR_FIR		(1 << CCM_CSCR_FIR_OFFSET)
+#define CCM_CSCR_SP		(1 << 17)
+#define CCM_CSCR_MCU		(1 << 16)
+#define CCM_CSCR_BCLK_OFFSET	10
+#define CCM_CSCR_BCLK_MASK	(0xf << CCM_CSCR_BCLK_OFFSET)
+#define CCM_CSCR_IPDIV_OFFSET	9
+#define CCM_CSCR_IPDIV		(1 << CCM_CSCR_IPDIV_OFFSET)
+
+#define CCM_CSCR_OSC26MDIV	(1 << 4)
+#define CCM_CSCR_OSC26M		(1 << 3)
+#define CCM_CSCR_FPM		(1 << 2)
+#define CCM_CSCR_SPEN		(1 << 1)
+#define CCM_CSCR_MPEN		1
+
+#define CCM_MPCTL0_CPLM		(1 << 31)
+#define CCM_MPCTL0_PD_OFFSET	26
+#define CCM_MPCTL0_PD_MASK	(0xf << 26)
+#define CCM_MPCTL0_MFD_OFFSET	16
+#define CCM_MPCTL0_MFD_MASK	(0x3ff << 16)
+#define CCM_MPCTL0_MFI_OFFSET	10
+#define CCM_MPCTL0_MFI_MASK	(0xf << 10)
+#define CCM_MPCTL0_MFN_OFFSET	0
+#define CCM_MPCTL0_MFN_MASK	0x3ff
+
+#define CCM_MPCTL1_LF		(1 << 15)
+#define CCM_MPCTL1_BRMO		(1 << 6)
+
+#define CCM_SPCTL0_CPLM		(1 << 31)
+#define CCM_SPCTL0_PD_OFFSET	26
+#define CCM_SPCTL0_PD_MASK	(0xf << 26)
+#define CCM_SPCTL0_MFD_OFFSET	16
+#define CCM_SPCTL0_MFD_MASK	(0x3ff << 16)
+#define CCM_SPCTL0_MFI_OFFSET	10
+#define CCM_SPCTL0_MFI_MASK	(0xf << 10)
+#define CCM_SPCTL0_MFN_OFFSET	0
+#define CCM_SPCTL0_MFN_MASK	0x3ff
+
+#define CCM_SPCTL1_LF		(1 << 15)
+#define CCM_SPCTL1_BRMO		(1 << 6)
+
+#define CCM_OSC26MCTL_PEAK_OFFSET	16
+#define CCM_OSC26MCTL_PEAK_MASK		(0x3 << 16)
+#define CCM_OSC26MCTL_AGC_OFFSET	8
+#define CCM_OSC26MCTL_AGC_MASK		(0x3f << 8)
+#define CCM_OSC26MCTL_ANATEST_OFFSET	0
+#define CCM_OSC26MCTL_ANATEST_MASK	0x3f
+
+#define CCM_PCDR0_SSI2BAUDDIV_OFFSET	26
+#define CCM_PCDR0_SSI2BAUDDIV_MASK	(0x3f << 26)
+#define CCM_PCDR0_SSI1BAUDDIV_OFFSET	16
+#define CCM_PCDR0_SSI1BAUDDIV_MASK	(0x3f << 16)
+#define CCM_PCDR0_NFCDIV_OFFSET		12
+#define CCM_PCDR0_NFCDIV_MASK		(0xf << 12)
+#define CCM_PCDR0_48MDIV_OFFSET		5
+#define CCM_PCDR0_48MDIV_MASK		(0x7 << CCM_PCDR0_48MDIV_OFFSET)
+#define CCM_PCDR0_FIRIDIV_OFFSET	0
+#define CCM_PCDR0_FIRIDIV_MASK		0x1f
+#define CCM_PCDR1_PERDIV4_OFFSET	24
+#define CCM_PCDR1_PERDIV4_MASK		(0x3f << 24)
+#define CCM_PCDR1_PERDIV3_OFFSET	16
+#define CCM_PCDR1_PERDIV3_MASK		(0x3f << 16)
+#define CCM_PCDR1_PERDIV2_OFFSET	8
+#define CCM_PCDR1_PERDIV2_MASK		(0x3f << 8)
+#define CCM_PCDR1_PERDIV1_OFFSET	0
+#define CCM_PCDR1_PERDIV1_MASK		0x3f
+
+#define CCM_PCCR_HCLK_CSI_OFFSET	31
+#define CCM_PCCR_HCLK_CSI_REG		CCM_PCCR0
+#define CCM_PCCR_HCLK_DMA_OFFSET	30
+#define CCM_PCCR_HCLK_DMA_REG		CCM_PCCR0
+#define CCM_PCCR_HCLK_BROM_OFFSET	28
+#define CCM_PCCR_HCLK_BROM_REG		CCM_PCCR0
+#define CCM_PCCR_HCLK_EMMA_OFFSET	27
+#define CCM_PCCR_HCLK_EMMA_REG		CCM_PCCR0
+#define CCM_PCCR_HCLK_LCDC_OFFSET	26
+#define CCM_PCCR_HCLK_LCDC_REG		CCM_PCCR0
+#define CCM_PCCR_HCLK_SLCDC_OFFSET	25
+#define CCM_PCCR_HCLK_SLCDC_REG		CCM_PCCR0
+#define CCM_PCCR_HCLK_USBOTG_OFFSET	24
+#define CCM_PCCR_HCLK_USBOTG_REG	CCM_PCCR0
+#define CCM_PCCR_HCLK_BMI_OFFSET	23
+#define CCM_PCCR_BMI_MASK		(1 << CCM_PCCR_BMI_MASK)
+#define CCM_PCCR_HCLK_BMI_REG		CCM_PCCR0
+#define CCM_PCCR_PERCLK4_OFFSET		22
+#define CCM_PCCR_PERCLK4_REG		CCM_PCCR0
+#define CCM_PCCR_SLCDC_OFFSET		21
+#define CCM_PCCR_SLCDC_REG		CCM_PCCR0
+#define CCM_PCCR_FIRI_BAUD_OFFSET	20
+#define CCM_PCCR_FIRI_BAUD_MASK		(1 << CCM_PCCR_FIRI_BAUD_MASK)
+#define CCM_PCCR_FIRI_BAUD_REG		CCM_PCCR0
+#define CCM_PCCR_NFC_OFFSET		19
+#define CCM_PCCR_NFC_REG		CCM_PCCR0
+#define CCM_PCCR_LCDC_OFFSET		18
+#define CCM_PCCR_LCDC_REG		CCM_PCCR0
+#define CCM_PCCR_SSI1_BAUD_OFFSET	17
+#define CCM_PCCR_SSI1_BAUD_REG		CCM_PCCR0
+#define CCM_PCCR_SSI2_BAUD_OFFSET	16
+#define CCM_PCCR_SSI2_BAUD_REG		CCM_PCCR0
+#define CCM_PCCR_EMMA_OFFSET		15
+#define CCM_PCCR_EMMA_REG		CCM_PCCR0
+#define CCM_PCCR_USBOTG_OFFSET		14
+#define CCM_PCCR_USBOTG_REG		CCM_PCCR0
+#define CCM_PCCR_DMA_OFFSET		13
+#define CCM_PCCR_DMA_REG		CCM_PCCR0
+#define CCM_PCCR_I2C1_OFFSET		12
+#define CCM_PCCR_I2C1_REG		CCM_PCCR0
+#define CCM_PCCR_GPIO_OFFSET		11
+#define CCM_PCCR_GPIO_REG		CCM_PCCR0
+#define CCM_PCCR_SDHC2_OFFSET		10
+#define CCM_PCCR_SDHC2_REG		CCM_PCCR0
+#define CCM_PCCR_SDHC1_OFFSET		9
+#define CCM_PCCR_SDHC1_REG		CCM_PCCR0
+#define CCM_PCCR_FIRI_OFFSET		8
+#define CCM_PCCR_FIRI_MASK		(1 << CCM_PCCR_BAUD_MASK)
+#define CCM_PCCR_FIRI_REG		CCM_PCCR0
+#define CCM_PCCR_SSI2_IPG_OFFSET	7
+#define CCM_PCCR_SSI2_REG		CCM_PCCR0
+#define CCM_PCCR_SSI1_IPG_OFFSET	6
+#define CCM_PCCR_SSI1_REG		CCM_PCCR0
+#define CCM_PCCR_CSPI2_OFFSET		5
+#define	CCM_PCCR_CSPI2_REG		CCM_PCCR0
+#define CCM_PCCR_CSPI1_OFFSET		4
+#define	CCM_PCCR_CSPI1_REG		CCM_PCCR0
+#define CCM_PCCR_UART4_OFFSET		3
+#define CCM_PCCR_UART4_REG		CCM_PCCR0
+#define CCM_PCCR_UART3_OFFSET		2
+#define CCM_PCCR_UART3_REG		CCM_PCCR0
+#define CCM_PCCR_UART2_OFFSET		1
+#define CCM_PCCR_UART2_REG		CCM_PCCR0
+#define CCM_PCCR_UART1_OFFSET		0
+#define CCM_PCCR_UART1_REG		CCM_PCCR0
+
+#define CCM_PCCR_OWIRE_OFFSET		31
+#define CCM_PCCR_OWIRE_REG		CCM_PCCR1
+#define CCM_PCCR_KPP_OFFSET		30
+#define CCM_PCCR_KPP_REG		CCM_PCCR1
+#define CCM_PCCR_RTC_OFFSET		29
+#define CCM_PCCR_RTC_REG		CCM_PCCR1
+#define CCM_PCCR_PWM_OFFSET		28
+#define CCM_PCCR_PWM_REG		CCM_PCCR1
+#define CCM_PCCR_GPT3_OFFSET		27
+#define CCM_PCCR_GPT3_REG		CCM_PCCR1
+#define CCM_PCCR_GPT2_OFFSET		26
+#define CCM_PCCR_GPT2_REG		CCM_PCCR1
+#define CCM_PCCR_GPT1_OFFSET		25
+#define CCM_PCCR_GPT1_REG		CCM_PCCR1
+#define CCM_PCCR_WDT_OFFSET		24
+#define CCM_PCCR_WDT_REG		CCM_PCCR1
+#define CCM_PCCR_CSPI3_OFFSET		23
+#define	CCM_PCCR_CSPI3_REG		CCM_PCCR1
+
+#define CCM_PCCR_CSPI1_MASK		(1 << CCM_PCCR_CSPI1_OFFSET)
+#define CCM_PCCR_CSPI2_MASK		(1 << CCM_PCCR_CSPI2_OFFSET)
+#define CCM_PCCR_CSPI3_MASK		(1 << CCM_PCCR_CSPI3_OFFSET)
+#define CCM_PCCR_DMA_MASK		(1 << CCM_PCCR_DMA_OFFSET)
+#define CCM_PCCR_EMMA_MASK		(1 << CCM_PCCR_EMMA_OFFSET)
+#define CCM_PCCR_GPIO_MASK		(1 << CCM_PCCR_GPIO_OFFSET)
+#define CCM_PCCR_GPT1_MASK		(1 << CCM_PCCR_GPT1_OFFSET)
+#define CCM_PCCR_GPT2_MASK		(1 << CCM_PCCR_GPT2_OFFSET)
+#define CCM_PCCR_GPT3_MASK		(1 << CCM_PCCR_GPT3_OFFSET)
+#define CCM_PCCR_HCLK_BROM_MASK		(1 << CCM_PCCR_HCLK_BROM_OFFSET)
+#define CCM_PCCR_HCLK_CSI_MASK		(1 << CCM_PCCR_HCLK_CSI_OFFSET)
+#define CCM_PCCR_HCLK_DMA_MASK		(1 << CCM_PCCR_HCLK_DMA_OFFSET)
+#define CCM_PCCR_HCLK_EMMA_MASK		(1 << CCM_PCCR_HCLK_EMMA_OFFSET)
+#define CCM_PCCR_HCLK_LCDC_MASK		(1 << CCM_PCCR_HCLK_LCDC_OFFSET)
+#define CCM_PCCR_HCLK_SLCDC_MASK	(1 << CCM_PCCR_HCLK_SLCDC_OFFSET)
+#define CCM_PCCR_HCLK_USBOTG_MASK	(1 << CCM_PCCR_HCLK_USBOTG_OFFSET)
+#define CCM_PCCR_I2C1_MASK		(1 << CCM_PCCR_I2C1_OFFSET)
+#define CCM_PCCR_KPP_MASK		(1 << CCM_PCCR_KPP_OFFSET)
+#define CCM_PCCR_LCDC_MASK		(1 << CCM_PCCR_LCDC_OFFSET)
+#define CCM_PCCR_NFC_MASK		(1 << CCM_PCCR_NFC_OFFSET)
+#define CCM_PCCR_OWIRE_MASK		(1 << CCM_PCCR_OWIRE_OFFSET)
+#define CCM_PCCR_PERCLK4_MASK		(1 << CCM_PCCR_PERCLK4_OFFSET)
+#define CCM_PCCR_PWM_MASK		(1 << CCM_PCCR_PWM_OFFSET)
+#define CCM_PCCR_RTC_MASK		(1 << CCM_PCCR_RTC_OFFSET)
+#define CCM_PCCR_SDHC1_MASK		(1 << CCM_PCCR_SDHC1_OFFSET)
+#define CCM_PCCR_SDHC2_MASK		(1 << CCM_PCCR_SDHC2_OFFSET)
+#define CCM_PCCR_SLCDC_MASK		(1 << CCM_PCCR_SLCDC_OFFSET)
+#define CCM_PCCR_SSI1_BAUD_MASK		(1 << CCM_PCCR_SSI1_BAUD_OFFSET)
+#define CCM_PCCR_SSI1_IPG_MASK		(1 << CCM_PCCR_SSI1_IPG_OFFSET)
+#define CCM_PCCR_SSI2_BAUD_MASK		(1 << CCM_PCCR_SSI2_BAUD_OFFSET)
+#define CCM_PCCR_SSI2_IPG_MASK		(1 << CCM_PCCR_SSI2_IPG_OFFSET)
+#define CCM_PCCR_UART1_MASK		(1 << CCM_PCCR_UART1_OFFSET)
+#define CCM_PCCR_UART2_MASK		(1 << CCM_PCCR_UART2_OFFSET)
+#define CCM_PCCR_UART3_MASK		(1 << CCM_PCCR_UART3_OFFSET)
+#define CCM_PCCR_UART4_MASK		(1 << CCM_PCCR_UART4_OFFSET)
+#define CCM_PCCR_USBOTG_MASK		(1 << CCM_PCCR_USBOTG_OFFSET)
+#define CCM_PCCR_WDT_MASK		(1 << CCM_PCCR_WDT_OFFSET)
+
+#define CCM_CCSR_32KSR		(1 << 15)
+
+#define CCM_CCSR_CLKMODE1	(1 << 9)
+#define CCM_CCSR_CLKMODE0	(1 << 8)
+
+#define CCM_CCSR_CLKOSEL_OFFSET 0
+#define CCM_CCSR_CLKOSEL_MASK	0x1f
+
+#define SYS_FMCR		0x14	/* Functional Muxing Control Reg */
+#define SYS_CHIP_ID		0x00	/* The offset of CHIP ID register */
 
 static int _clk_enable(struct clk *clk)
 {
@@ -1002,6 +1233,7 @@
 	clk_enable(&uart_clk[0]);
 #endif
 
-	mxc_timer_init(&gpt_clk[0], IO_ADDRESS(GPT1_BASE_ADDR), MXC_INT_GPT1);
+	mxc_timer_init(&gpt_clk[0], MX21_IO_ADDRESS(MX21_GPT1_BASE_ADDR),
+			MX21_INT_GPT1);
 	return 0;
 }
diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c
index 18c53a6..0f0823c 100644
--- a/arch/arm/mach-mx2/clock_imx27.c
+++ b/arch/arm/mach-mx2/clock_imx27.c
@@ -29,21 +29,23 @@
 #include <mach/common.h>
 #include <mach/hardware.h>
 
+#define IO_ADDR_CCM(off)	(MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off)))
+
 /* Register offsets */
-#define CCM_CSCR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x0)
-#define CCM_MPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0x4)
-#define CCM_MPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x8)
-#define CCM_SPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0xC)
-#define CCM_SPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x10)
-#define CCM_OSC26MCTL           (IO_ADDRESS(CCM_BASE_ADDR) + 0x14)
-#define CCM_PCDR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x18)
-#define CCM_PCDR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c)
-#define CCM_PCCR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x20)
-#define CCM_PCCR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x24)
-#define CCM_CCSR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x28)
-#define CCM_PMCTL               (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c)
-#define CCM_PMCOUNT             (IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
-#define CCM_WKGDCTL             (IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
+#define CCM_CSCR		IO_ADDR_CCM(0x0)
+#define CCM_MPCTL0		IO_ADDR_CCM(0x4)
+#define CCM_MPCTL1		IO_ADDR_CCM(0x8)
+#define CCM_SPCTL0		IO_ADDR_CCM(0xc)
+#define CCM_SPCTL1		IO_ADDR_CCM(0x10)
+#define CCM_OSC26MCTL		IO_ADDR_CCM(0x14)
+#define CCM_PCDR0		IO_ADDR_CCM(0x18)
+#define CCM_PCDR1		IO_ADDR_CCM(0x1c)
+#define CCM_PCCR0		IO_ADDR_CCM(0x20)
+#define CCM_PCCR1		IO_ADDR_CCM(0x24)
+#define CCM_CCSR		IO_ADDR_CCM(0x28)
+#define CCM_PMCTL		IO_ADDR_CCM(0x2c)
+#define CCM_PMCOUNT		IO_ADDR_CCM(0x30)
+#define CCM_WKGDCTL		IO_ADDR_CCM(0x34)
 
 #define CCM_CSCR_UPDATE_DIS	(1 << 31)
 #define CCM_CSCR_SSI2		(1 << 23)
@@ -753,7 +755,8 @@
 	clk_enable(&uart1_clk);
 #endif
 
-	mxc_timer_init(&gpt1_clk, IO_ADDRESS(GPT1_BASE_ADDR), MXC_INT_GPT1);
+	mxc_timer_init(&gpt1_clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
+			MX27_INT_GPT1);
 
 	return 0;
 }
diff --git a/arch/arm/mach-mx2/cpu_imx27.c b/arch/arm/mach-mx2/cpu_imx27.c
index d9e3bf9..d8d3b2d 100644
--- a/arch/arm/mach-mx2/cpu_imx27.c
+++ b/arch/arm/mach-mx2/cpu_imx27.c
@@ -39,7 +39,8 @@
 	 * the silicon revision very early we read it here to
 	 * avoid any further hooks
 	*/
-	val = __raw_readl(IO_ADDRESS(SYSCTRL_BASE_ADDR) + SYS_CHIP_ID);
+	val = __raw_readl(MX27_IO_ADDRESS(MX27_SYSCTRL_BASE_ADDR
+				+ SYS_CHIP_ID));
 
 	cpu_silicon_rev = (int)(val >> 28);
 	cpu_partnumber = (int)((val >> 12) & 0xFFFF);
diff --git a/arch/arm/mach-mx2/crm_regs.h b/arch/arm/mach-mx2/crm_regs.h
deleted file mode 100644
index 749de76..0000000
--- a/arch/arm/mach-mx2/crm_regs.h
+++ /dev/null
@@ -1,258 +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.
- */
-
-#ifndef __ARCH_ARM_MACH_MX2_CRM_REGS_H__
-#define __ARCH_ARM_MACH_MX2_CRM_REGS_H__
-
-#include <mach/hardware.h>
-
-/* Register offsets */
-#define CCM_CSCR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x0)
-#define CCM_MPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0x4)
-#define CCM_MPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x8)
-#define CCM_SPCTL0              (IO_ADDRESS(CCM_BASE_ADDR) + 0xC)
-#define CCM_SPCTL1              (IO_ADDRESS(CCM_BASE_ADDR) + 0x10)
-#define CCM_OSC26MCTL           (IO_ADDRESS(CCM_BASE_ADDR) + 0x14)
-#define CCM_PCDR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x18)
-#define CCM_PCDR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x1c)
-#define CCM_PCCR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x20)
-#define CCM_PCCR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x24)
-#define CCM_CCSR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x28)
-#define CCM_PMCTL               (IO_ADDRESS(CCM_BASE_ADDR) + 0x2c)
-#define CCM_PMCOUNT             (IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
-#define CCM_WKGDCTL             (IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
-
-#define CCM_CSCR_PRESC_OFFSET   29
-#define CCM_CSCR_PRESC_MASK     (0x7 << CCM_CSCR_PRESC_OFFSET)
-
-#define CCM_CSCR_USB_OFFSET     26
-#define CCM_CSCR_USB_MASK       (0x7 << CCM_CSCR_USB_OFFSET)
-#define CCM_CSCR_SD_OFFSET      24
-#define CCM_CSCR_SD_MASK        (0x3 << CCM_CSCR_SD_OFFSET)
-#define CCM_CSCR_SPLLRES        (1 << 22)
-#define CCM_CSCR_MPLLRES        (1 << 21)
-#define CCM_CSCR_SSI2_OFFSET    20
-#define CCM_CSCR_SSI2           (1 << CCM_CSCR_SSI2_OFFSET)
-#define CCM_CSCR_SSI1_OFFSET    19
-#define CCM_CSCR_SSI1           (1 << CCM_CSCR_SSI1_OFFSET)
-#define CCM_CSCR_FIR_OFFSET    	18
-#define CCM_CSCR_FIR		(1 << CCM_CSCR_FIR_OFFSET)
-#define CCM_CSCR_SP             (1 << 17)
-#define CCM_CSCR_MCU            (1 << 16)
-#define CCM_CSCR_BCLK_OFFSET	10
-#define CCM_CSCR_BCLK_MASK      (0xf << CCM_CSCR_BCLK_OFFSET)
-#define CCM_CSCR_IPDIV_OFFSET   9
-#define CCM_CSCR_IPDIV          (1 << CCM_CSCR_IPDIV_OFFSET)
-
-#define CCM_CSCR_OSC26MDIV      (1 << 4)
-#define CCM_CSCR_OSC26M         (1 << 3)
-#define CCM_CSCR_FPM            (1 << 2)
-#define CCM_CSCR_SPEN           (1 << 1)
-#define CCM_CSCR_MPEN           1
-
-
-
-#define CCM_MPCTL0_CPLM         (1 << 31)
-#define CCM_MPCTL0_PD_OFFSET    26
-#define CCM_MPCTL0_PD_MASK      (0xf << 26)
-#define CCM_MPCTL0_MFD_OFFSET   16
-#define CCM_MPCTL0_MFD_MASK     (0x3ff << 16)
-#define CCM_MPCTL0_MFI_OFFSET   10
-#define CCM_MPCTL0_MFI_MASK     (0xf << 10)
-#define CCM_MPCTL0_MFN_OFFSET   0
-#define CCM_MPCTL0_MFN_MASK     0x3ff
-
-#define CCM_MPCTL1_LF           (1 << 15)
-#define CCM_MPCTL1_BRMO         (1 << 6)
-
-#define CCM_SPCTL0_CPLM         (1 << 31)
-#define CCM_SPCTL0_PD_OFFSET    26
-#define CCM_SPCTL0_PD_MASK      (0xf << 26)
-#define CCM_SPCTL0_MFD_OFFSET   16
-#define CCM_SPCTL0_MFD_MASK     (0x3ff << 16)
-#define CCM_SPCTL0_MFI_OFFSET   10
-#define CCM_SPCTL0_MFI_MASK     (0xf << 10)
-#define CCM_SPCTL0_MFN_OFFSET   0
-#define CCM_SPCTL0_MFN_MASK     0x3ff
-
-#define CCM_SPCTL1_LF           (1 << 15)
-#define CCM_SPCTL1_BRMO         (1 << 6)
-
-#define CCM_OSC26MCTL_PEAK_OFFSET       16
-#define CCM_OSC26MCTL_PEAK_MASK         (0x3 << 16)
-#define CCM_OSC26MCTL_AGC_OFFSET        8
-#define CCM_OSC26MCTL_AGC_MASK          (0x3f << 8)
-#define CCM_OSC26MCTL_ANATEST_OFFSET    0
-#define CCM_OSC26MCTL_ANATEST_MASK      0x3f
-
-#define CCM_PCDR0_SSI2BAUDDIV_OFFSET    26
-#define CCM_PCDR0_SSI2BAUDDIV_MASK      (0x3f << 26)
-#define CCM_PCDR0_SSI1BAUDDIV_OFFSET    16
-#define CCM_PCDR0_SSI1BAUDDIV_MASK      (0x3f << 16)
-#define CCM_PCDR0_NFCDIV_OFFSET         12
-#define CCM_PCDR0_NFCDIV_MASK           (0xf << 12)
-#define CCM_PCDR0_48MDIV_OFFSET		5
-#define CCM_PCDR0_48MDIV_MASK		(0x7 << CCM_PCDR0_48MDIV_OFFSET)
-#define CCM_PCDR0_FIRIDIV_OFFSET	0
-#define CCM_PCDR0_FIRIDIV_MASK		0x1f
-#define CCM_PCDR1_PERDIV4_OFFSET        24
-#define CCM_PCDR1_PERDIV4_MASK          (0x3f << 24)
-#define CCM_PCDR1_PERDIV3_OFFSET        16
-#define CCM_PCDR1_PERDIV3_MASK          (0x3f << 16)
-#define CCM_PCDR1_PERDIV2_OFFSET        8
-#define CCM_PCDR1_PERDIV2_MASK          (0x3f << 8)
-#define CCM_PCDR1_PERDIV1_OFFSET        0
-#define CCM_PCDR1_PERDIV1_MASK          0x3f
-
-#define CCM_PCCR_HCLK_CSI_OFFSET       	31
-#define CCM_PCCR_HCLK_CSI_REG	        CCM_PCCR0
-#define CCM_PCCR_HCLK_DMA_OFFSET       	30
-#define CCM_PCCR_HCLK_DMA_REG	        CCM_PCCR0
-#define CCM_PCCR_HCLK_BROM_OFFSET      	28
-#define CCM_PCCR_HCLK_BROM_REG	        CCM_PCCR0
-#define CCM_PCCR_HCLK_EMMA_OFFSET      	27
-#define CCM_PCCR_HCLK_EMMA_REG	        CCM_PCCR0
-#define CCM_PCCR_HCLK_LCDC_OFFSET      	26
-#define CCM_PCCR_HCLK_LCDC_REG	        CCM_PCCR0
-#define CCM_PCCR_HCLK_SLCDC_OFFSET     	25
-#define CCM_PCCR_HCLK_SLCDC_REG	        CCM_PCCR0
-#define CCM_PCCR_HCLK_USBOTG_OFFSET    	24
-#define CCM_PCCR_HCLK_USBOTG_REG	CCM_PCCR0
-#define CCM_PCCR_HCLK_BMI_OFFSET    	23
-#define CCM_PCCR_BMI_MASK          	(1 << CCM_PCCR_BMI_MASK)
-#define CCM_PCCR_HCLK_BMI_REG	    	CCM_PCCR0
-#define CCM_PCCR_PERCLK4_OFFSET        	22
-#define CCM_PCCR_PERCLK4_REG	    	CCM_PCCR0
-#define CCM_PCCR_SLCDC_OFFSET          	21
-#define CCM_PCCR_SLCDC_REG		CCM_PCCR0
-#define CCM_PCCR_FIRI_BAUD_OFFSET       20
-#define CCM_PCCR_FIRI_BAUD_MASK         (1 << CCM_PCCR_FIRI_BAUD_MASK)
-#define CCM_PCCR_FIRI_BAUD_REG	        CCM_PCCR0
-#define CCM_PCCR_NFC_OFFSET		19
-#define CCM_PCCR_NFC_REG		CCM_PCCR0
-#define CCM_PCCR_LCDC_OFFSET           	18
-#define CCM_PCCR_LCDC_REG		CCM_PCCR0
-#define CCM_PCCR_SSI1_BAUD_OFFSET      	17
-#define CCM_PCCR_SSI1_BAUD_REG	    	CCM_PCCR0
-#define CCM_PCCR_SSI2_BAUD_OFFSET      	16
-#define CCM_PCCR_SSI2_BAUD_REG	    	CCM_PCCR0
-#define CCM_PCCR_EMMA_OFFSET           	15
-#define CCM_PCCR_EMMA_REG		CCM_PCCR0
-#define CCM_PCCR_USBOTG_OFFSET         	14
-#define CCM_PCCR_USBOTG_REG		CCM_PCCR0
-#define CCM_PCCR_DMA_OFFSET            	13
-#define CCM_PCCR_DMA_REG            	CCM_PCCR0
-#define CCM_PCCR_I2C1_OFFSET           	12
-#define CCM_PCCR_I2C1_REG		CCM_PCCR0
-#define CCM_PCCR_GPIO_OFFSET           	11
-#define CCM_PCCR_GPIO_REG		CCM_PCCR0
-#define CCM_PCCR_SDHC2_OFFSET          	10
-#define CCM_PCCR_SDHC2_REG		CCM_PCCR0
-#define CCM_PCCR_SDHC1_OFFSET          	9
-#define CCM_PCCR_SDHC1_REG		CCM_PCCR0
-#define CCM_PCCR_FIRI_OFFSET		8
-#define CCM_PCCR_FIRI_MASK		(1 << CCM_PCCR_BAUD_MASK)
-#define CCM_PCCR_FIRI_REG		CCM_PCCR0
-#define CCM_PCCR_SSI2_IPG_OFFSET       	7
-#define CCM_PCCR_SSI2_REG		CCM_PCCR0
-#define CCM_PCCR_SSI1_IPG_OFFSET       	6
-#define CCM_PCCR_SSI1_REG		CCM_PCCR0
-#define CCM_PCCR_CSPI2_OFFSET		5
-#define	CCM_PCCR_CSPI2_REG		CCM_PCCR0
-#define CCM_PCCR_CSPI1_OFFSET		4
-#define	CCM_PCCR_CSPI1_REG		CCM_PCCR0
-#define CCM_PCCR_UART4_OFFSET          	3
-#define CCM_PCCR_UART4_REG		CCM_PCCR0
-#define CCM_PCCR_UART3_OFFSET          	2
-#define CCM_PCCR_UART3_REG		CCM_PCCR0
-#define CCM_PCCR_UART2_OFFSET          	1
-#define CCM_PCCR_UART2_REG		CCM_PCCR0
-#define CCM_PCCR_UART1_OFFSET          	0
-#define CCM_PCCR_UART1_REG		CCM_PCCR0
-
-#define CCM_PCCR_OWIRE_OFFSET          	31
-#define CCM_PCCR_OWIRE_REG		CCM_PCCR1
-#define CCM_PCCR_KPP_OFFSET            	30
-#define CCM_PCCR_KPP_REG		CCM_PCCR1
-#define CCM_PCCR_RTC_OFFSET            	29
-#define CCM_PCCR_RTC_REG		CCM_PCCR1
-#define CCM_PCCR_PWM_OFFSET            	28
-#define CCM_PCCR_PWM_REG		CCM_PCCR1
-#define CCM_PCCR_GPT3_OFFSET           	27
-#define CCM_PCCR_GPT3_REG		CCM_PCCR1
-#define CCM_PCCR_GPT2_OFFSET           	26
-#define CCM_PCCR_GPT2_REG		CCM_PCCR1
-#define CCM_PCCR_GPT1_OFFSET           	25
-#define CCM_PCCR_GPT1_REG		CCM_PCCR1
-#define CCM_PCCR_WDT_OFFSET            	24
-#define CCM_PCCR_WDT_REG		CCM_PCCR1
-#define CCM_PCCR_CSPI3_OFFSET		23
-#define	CCM_PCCR_CSPI3_REG		CCM_PCCR1
-
-#define CCM_PCCR_CSPI1_MASK            	(1 << CCM_PCCR_CSPI1_OFFSET)
-#define CCM_PCCR_CSPI2_MASK            	(1 << CCM_PCCR_CSPI2_OFFSET)
-#define CCM_PCCR_CSPI3_MASK            	(1 << CCM_PCCR_CSPI3_OFFSET)
-#define CCM_PCCR_DMA_MASK              	(1 << CCM_PCCR_DMA_OFFSET)
-#define CCM_PCCR_EMMA_MASK             	(1 << CCM_PCCR_EMMA_OFFSET)
-#define CCM_PCCR_GPIO_MASK             	(1 << CCM_PCCR_GPIO_OFFSET)
-#define CCM_PCCR_GPT1_MASK             	(1 << CCM_PCCR_GPT1_OFFSET)
-#define CCM_PCCR_GPT2_MASK             	(1 << CCM_PCCR_GPT2_OFFSET)
-#define CCM_PCCR_GPT3_MASK             	(1 << CCM_PCCR_GPT3_OFFSET)
-#define CCM_PCCR_HCLK_BROM_MASK		(1 << CCM_PCCR_HCLK_BROM_OFFSET)
-#define CCM_PCCR_HCLK_CSI_MASK         	(1 << CCM_PCCR_HCLK_CSI_OFFSET)
-#define CCM_PCCR_HCLK_DMA_MASK         	(1 << CCM_PCCR_HCLK_DMA_OFFSET)
-#define CCM_PCCR_HCLK_EMMA_MASK        	(1 << CCM_PCCR_HCLK_EMMA_OFFSET)
-#define CCM_PCCR_HCLK_LCDC_MASK        	(1 << CCM_PCCR_HCLK_LCDC_OFFSET)
-#define CCM_PCCR_HCLK_SLCDC_MASK       	(1 << CCM_PCCR_HCLK_SLCDC_OFFSET)
-#define CCM_PCCR_HCLK_USBOTG_MASK      	(1 << CCM_PCCR_HCLK_USBOTG_OFFSET)
-#define CCM_PCCR_I2C1_MASK             	(1 << CCM_PCCR_I2C1_OFFSET)
-#define CCM_PCCR_KPP_MASK              	(1 << CCM_PCCR_KPP_OFFSET)
-#define CCM_PCCR_LCDC_MASK             	(1 << CCM_PCCR_LCDC_OFFSET)
-#define CCM_PCCR_NFC_MASK		(1 << CCM_PCCR_NFC_OFFSET)
-#define CCM_PCCR_OWIRE_MASK            	(1 << CCM_PCCR_OWIRE_OFFSET)
-#define CCM_PCCR_PERCLK4_MASK          	(1 << CCM_PCCR_PERCLK4_OFFSET)
-#define CCM_PCCR_PWM_MASK              	(1 << CCM_PCCR_PWM_OFFSET)
-#define CCM_PCCR_RTC_MASK              	(1 << CCM_PCCR_RTC_OFFSET)
-#define CCM_PCCR_SDHC1_MASK            	(1 << CCM_PCCR_SDHC1_OFFSET)
-#define CCM_PCCR_SDHC2_MASK            	(1 << CCM_PCCR_SDHC2_OFFSET)
-#define CCM_PCCR_SLCDC_MASK            	(1 << CCM_PCCR_SLCDC_OFFSET)
-#define CCM_PCCR_SSI1_BAUD_MASK        	(1 << CCM_PCCR_SSI1_BAUD_OFFSET)
-#define CCM_PCCR_SSI1_IPG_MASK         	(1 << CCM_PCCR_SSI1_IPG_OFFSET)
-#define CCM_PCCR_SSI2_BAUD_MASK        	(1 << CCM_PCCR_SSI2_BAUD_OFFSET)
-#define CCM_PCCR_SSI2_IPG_MASK         	(1 << CCM_PCCR_SSI2_IPG_OFFSET)
-#define CCM_PCCR_UART1_MASK            	(1 << CCM_PCCR_UART1_OFFSET)
-#define CCM_PCCR_UART2_MASK            	(1 << CCM_PCCR_UART2_OFFSET)
-#define CCM_PCCR_UART3_MASK            	(1 << CCM_PCCR_UART3_OFFSET)
-#define CCM_PCCR_UART4_MASK            	(1 << CCM_PCCR_UART4_OFFSET)
-#define CCM_PCCR_USBOTG_MASK           	(1 << CCM_PCCR_USBOTG_OFFSET)
-#define CCM_PCCR_WDT_MASK              	(1 << CCM_PCCR_WDT_OFFSET)
-
-
-#define CCM_CCSR_32KSR          (1 << 15)
-
-#define CCM_CCSR_CLKMODE1       (1 << 9)
-#define CCM_CCSR_CLKMODE0       (1 << 8)
-
-#define CCM_CCSR_CLKOSEL_OFFSET 0
-#define CCM_CCSR_CLKOSEL_MASK   0x1f
-
-#define SYS_FMCR                0x14	/*  Functional Muxing Control Reg */
-#define SYS_CHIP_ID             0x00	/* The offset of CHIP ID register */
-
-#endif /* __ARCH_ARM_MACH_MX2_CRM_REGS_H__ */
diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c
index 3d398ce..b91e412 100644
--- a/arch/arm/mach-mx2/devices.c
+++ b/arch/arm/mach-mx2/devices.c
@@ -31,6 +31,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/dma-mapping.h>
 
 #include <mach/irqs.h>
 #include <mach/hardware.h>
@@ -46,65 +47,31 @@
  * - i.MX21: 2 channel
  * - i.MX27: 3 channel
  */
-static struct resource mxc_spi_resources0[] = {
-	{
-	       .start = CSPI1_BASE_ADDR,
-	       .end = CSPI1_BASE_ADDR + SZ_4K - 1,
-	       .flags = IORESOURCE_MEM,
-	}, {
-	       .start = MXC_INT_CSPI1,
-	       .end = MXC_INT_CSPI1,
-	       .flags = IORESOURCE_IRQ,
-	},
-};
+#define DEFINE_IMX_SPI_DEVICE(n, baseaddr, irq)					\
+	static struct resource mxc_spi_resources ## n[] = {			\
+		{								\
+			.start = baseaddr,					\
+			.end = baseaddr + SZ_4K - 1,				\
+			.flags = IORESOURCE_MEM,				\
+		}, {								\
+			.start = irq,						\
+			.end = irq,						\
+			.flags = IORESOURCE_IRQ,				\
+		},								\
+	};									\
+										\
+	struct platform_device mxc_spi_device ## n = {				\
+		.name = "spi_imx",						\
+		.id = n,							\
+		.num_resources = ARRAY_SIZE(mxc_spi_resources ## n),		\
+		.resource = mxc_spi_resources ## n,				\
+	}
 
-static struct resource mxc_spi_resources1[] = {
-	{
-		.start = CSPI2_BASE_ADDR,
-		.end = CSPI2_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MXC_INT_CSPI2,
-		.end = MXC_INT_CSPI2,
-		.flags = IORESOURCE_IRQ,
-	},
-};
+DEFINE_IMX_SPI_DEVICE(0, MX2x_CSPI1_BASE_ADDR, MX2x_INT_CSPI1);
+DEFINE_IMX_SPI_DEVICE(1, MX2x_CSPI2_BASE_ADDR, MX2x_INT_CSPI2);
 
 #ifdef CONFIG_MACH_MX27
-static struct resource mxc_spi_resources2[] = {
-	{
-		.start = CSPI3_BASE_ADDR,
-		.end = CSPI3_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MXC_INT_CSPI3,
-		.end = MXC_INT_CSPI3,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-#endif
-
-struct platform_device mxc_spi_device0 = {
-	.name = "spi_imx",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_spi_resources0),
-	.resource = mxc_spi_resources0,
-};
-
-struct platform_device mxc_spi_device1 = {
-	.name = "spi_imx",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(mxc_spi_resources1),
-	.resource = mxc_spi_resources1,
-};
-
-#ifdef CONFIG_MACH_MX27
-struct platform_device mxc_spi_device2 = {
-	.name = "spi_imx",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(mxc_spi_resources2),
-	.resource = mxc_spi_resources2,
-};
+DEFINE_IMX_SPI_DEVICE(2, MX27_CSPI3_BASE_ADDR, MX27_INT_CSPI3);
 #endif
 
 /*
@@ -112,104 +79,34 @@
  * - i.MX21: 3 timers
  * - i.MX27: 6 timers
  */
-
-/* We use gpt0 as system timer, so do not add a device for this one */
-
-static struct resource timer1_resources[] = {
-	{
-		.start	= GPT2_BASE_ADDR,
-		.end	= GPT2_BASE_ADDR + 0x17,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start   = MXC_INT_GPT2,
-		.end     = MXC_INT_GPT2,
-		.flags   = IORESOURCE_IRQ,
+#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,			\
 	}
-};
 
-struct platform_device mxc_gpt1 = {
-	.name = "imx_gpt",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(timer1_resources),
-	.resource = timer1_resources,
-};
-
-static struct resource timer2_resources[] = {
-	{
-		.start	= GPT3_BASE_ADDR,
-		.end	= GPT3_BASE_ADDR + 0x17,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start   = MXC_INT_GPT3,
-		.end     = MXC_INT_GPT3,
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_gpt2 = {
-	.name = "imx_gpt",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(timer2_resources),
-	.resource = timer2_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
-static struct resource timer3_resources[] = {
-	{
-		.start	= GPT4_BASE_ADDR,
-		.end	= GPT4_BASE_ADDR + 0x17,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start   = MXC_INT_GPT4,
-		.end     = MXC_INT_GPT4,
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_gpt3 = {
-	.name = "imx_gpt",
-	.id = 3,
-	.num_resources = ARRAY_SIZE(timer3_resources),
-	.resource = timer3_resources,
-};
-
-static struct resource timer4_resources[] = {
-	{
-		.start	= GPT5_BASE_ADDR,
-		.end	= GPT5_BASE_ADDR + 0x17,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start   = MXC_INT_GPT5,
-		.end     = MXC_INT_GPT5,
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_gpt4 = {
-	.name = "imx_gpt",
-	.id = 4,
-	.num_resources = ARRAY_SIZE(timer4_resources),
-	.resource = timer4_resources,
-};
-
-static struct resource timer5_resources[] = {
-	{
-		.start	= GPT6_BASE_ADDR,
-		.end	= GPT6_BASE_ADDR + 0x17,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start   = MXC_INT_GPT6,
-		.end     = MXC_INT_GPT6,
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_gpt5 = {
-	.name = "imx_gpt",
-	.id = 5,
-	.num_resources = ARRAY_SIZE(timer5_resources),
-	.resource = timer5_resources,
-};
+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
 
 /*
@@ -220,9 +117,9 @@
  */
 static struct resource mxc_wdt_resources[] = {
 	{
-		.start	= WDOG_BASE_ADDR,
-		.end	= WDOG_BASE_ADDR + 0x30,
-		.flags	= IORESOURCE_MEM,
+		.start = MX2x_WDOG_BASE_ADDR,
+		.end = MX2x_WDOG_BASE_ADDR + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
 	},
 };
 
@@ -235,8 +132,8 @@
 
 static struct resource mxc_w1_master_resources[] = {
 	{
-		.start = OWIRE_BASE_ADDR,
-		.end   = OWIRE_BASE_ADDR + SZ_4K - 1,
+		.start = MX2x_OWIRE_BASE_ADDR,
+		.end = MX2x_OWIRE_BASE_ADDR + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 };
@@ -248,24 +145,33 @@
 	.resource = mxc_w1_master_resources,
 };
 
-static struct resource mxc_nand_resources[] = {
-	{
-		.start	= NFC_BASE_ADDR,
-		.end	= NFC_BASE_ADDR + 0xfff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MXC_INT_NANDFC,
-		.end	= MXC_INT_NANDFC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
+#define DEFINE_MXC_NAND_DEVICE(pfx, baseaddr, irq)			\
+	static struct resource pfx ## _nand_resources[] = {		\
+		{							\
+			.start = baseaddr,				\
+			.end = baseaddr + SZ_4K - 1,			\
+			.flags = IORESOURCE_MEM,			\
+		}, {							\
+			.start = irq,					\
+			.end = irq,					\
+			.flags = IORESOURCE_IRQ,			\
+		},							\
+	};								\
+									\
+	struct platform_device pfx ## _nand_device = {			\
+		.name = "mxc_nand",					\
+		.id = 0,						\
+		.num_resources = ARRAY_SIZE(pfx ## _nand_resources),	\
+		.resource = pfx ## _nand_resources,			\
+	}
 
-struct platform_device mxc_nand_device = {
-	.name = "mxc_nand",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_nand_resources),
-	.resource = mxc_nand_resources,
-};
+#ifdef CONFIG_MACH_MX21
+DEFINE_MXC_NAND_DEVICE(imx21, MX21_NFC_BASE_ADDR, MX21_INT_NANDFC);
+#endif
+
+#ifdef CONFIG_MACH_MX27
+DEFINE_MXC_NAND_DEVICE(imx27, MX27_NFC_BASE_ADDR, MX27_INT_NANDFC);
+#endif
 
 /*
  * lcdc:
@@ -275,12 +181,12 @@
  */
 static struct resource mxc_fb[] = {
 	{
-		.start = LCDC_BASE_ADDR,
-		.end   = LCDC_BASE_ADDR + 0xFFF,
+		.start = MX2x_LCDC_BASE_ADDR,
+		.end = MX2x_LCDC_BASE_ADDR + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = MXC_INT_LCDC,
-		.end   = MXC_INT_LCDC,
+		.start = MX2x_INT_LCDC,
+		.end = MX2x_INT_LCDC,
 		.flags = IORESOURCE_IRQ,
 	}
 };
@@ -292,20 +198,20 @@
 	.num_resources = ARRAY_SIZE(mxc_fb),
 	.resource = mxc_fb,
 	.dev = {
-		.coherent_dma_mask = 0xFFFFFFFF,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
 	},
 };
 
 #ifdef CONFIG_MACH_MX27
 static struct resource mxc_fec_resources[] = {
 	{
-		.start	= FEC_BASE_ADDR,
-		.end	= FEC_BASE_ADDR + 0xfff,
-		.flags	= IORESOURCE_MEM,
+		.start = MX27_FEC_BASE_ADDR,
+		.end = MX27_FEC_BASE_ADDR + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
 	}, {
-		.start	= MXC_INT_FEC,
-		.end	= MXC_INT_FEC,
-		.flags	= IORESOURCE_IRQ,
+		.start = MX27_INT_FEC,
+		.end = MX27_INT_FEC,
+		.flags = IORESOURCE_IRQ,
 	},
 };
 
@@ -317,55 +223,41 @@
 };
 #endif
 
-static struct resource mxc_i2c_1_resources[] = {
-	{
-		.start	= I2C_BASE_ADDR,
-		.end	= I2C_BASE_ADDR + 0x0fff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MXC_INT_I2C,
-		.end	= MXC_INT_I2C,
-		.flags	= IORESOURCE_IRQ,
+#define DEFINE_IMX_I2C_DEVICE(n, baseaddr, irq)				\
+	static struct resource mxc_i2c_resources ## n[] = {		\
+		{							\
+			.start = baseaddr,				\
+			.end = baseaddr + SZ_4K - 1,			\
+			.flags = IORESOURCE_MEM,			\
+		}, {							\
+			.start = irq,					\
+			.end = irq,					\
+			.flags = IORESOURCE_IRQ,			\
+		}							\
+	};								\
+									\
+	struct platform_device mxc_i2c_device ## n = {			\
+		.name = "imx-i2c",					\
+		.id = n,						\
+		.num_resources = ARRAY_SIZE(mxc_i2c_resources ## n),	\
+		.resource = mxc_i2c_resources ## n,			\
 	}
-};
 
-struct platform_device mxc_i2c_device0 = {
-	.name = "imx-i2c",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(mxc_i2c_1_resources),
-	.resource = mxc_i2c_1_resources,
-};
+DEFINE_IMX_I2C_DEVICE(0, MX2x_I2C_BASE_ADDR, MX2x_INT_I2C);
 
 #ifdef CONFIG_MACH_MX27
-static struct resource mxc_i2c_2_resources[] = {
-	{
-		.start	= I2C2_BASE_ADDR,
-		.end	= I2C2_BASE_ADDR + 0x0fff,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MXC_INT_I2C2,
-		.end	= MXC_INT_I2C2,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-struct platform_device mxc_i2c_device1 = {
-	.name = "imx-i2c",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(mxc_i2c_2_resources),
-	.resource = mxc_i2c_2_resources,
-};
+DEFINE_IMX_I2C_DEVICE(1, MX27_I2C2_BASE_ADDR, MX27_INT_I2C2);
 #endif
 
 static struct resource mxc_pwm_resources[] = {
 	{
-		.start	= PWM_BASE_ADDR,
-		.end	= PWM_BASE_ADDR + 0x0fff,
-		.flags	= IORESOURCE_MEM,
+		.start = MX2x_PWM_BASE_ADDR,
+		.end = MX2x_PWM_BASE_ADDR + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
 	}, {
-		.start   = MXC_INT_PWM,
-		.end     = MXC_INT_PWM,
-		.flags   = IORESOURCE_IRQ,
+		.start = MX2x_INT_PWM,
+		.end = MX2x_INT_PWM,
+		.flags = IORESOURCE_IRQ,
 	}
 };
 
@@ -376,81 +268,53 @@
 	.resource = mxc_pwm_resources,
 };
 
-/*
- * Resource definition for the MXC SDHC
- */
-static struct resource mxc_sdhc1_resources[] = {
-	{
-		.start = SDHC1_BASE_ADDR,
-		.end   = SDHC1_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MXC_INT_SDHC1,
-		.end   = MXC_INT_SDHC1,
-		.flags = IORESOURCE_IRQ,
-	}, {
-		.start  = DMA_REQ_SDHC1,
-		.end    = DMA_REQ_SDHC1,
-		.flags  = IORESOURCE_DMA,
-	},
-};
+#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,		\
+	}
 
-static u64 mxc_sdhc1_dmamask = 0xffffffffUL;
-
-struct platform_device mxc_sdhc_device0 = {
-       .name           = "mxc-mmc",
-       .id             = 0,
-       .dev            = {
-               .dma_mask = &mxc_sdhc1_dmamask,
-               .coherent_dma_mask = 0xffffffff,
-       },
-       .num_resources  = ARRAY_SIZE(mxc_sdhc1_resources),
-       .resource       = mxc_sdhc1_resources,
-};
-
-static struct resource mxc_sdhc2_resources[] = {
-	{
-		.start = SDHC2_BASE_ADDR,
-		.end   = SDHC2_BASE_ADDR + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = MXC_INT_SDHC2,
-		.end   = MXC_INT_SDHC2,
-		.flags = IORESOURCE_IRQ,
-	}, {
-		.start  = DMA_REQ_SDHC2,
-		.end    = DMA_REQ_SDHC2,
-		.flags  = IORESOURCE_DMA,
-	},
-};
-
-static u64 mxc_sdhc2_dmamask = 0xffffffffUL;
-
-struct platform_device mxc_sdhc_device1 = {
-       .name           = "mxc-mmc",
-       .id             = 1,
-       .dev            = {
-               .dma_mask = &mxc_sdhc2_dmamask,
-               .coherent_dma_mask = 0xffffffff,
-       },
-       .num_resources  = ARRAY_SIZE(mxc_sdhc2_resources),
-       .resource       = mxc_sdhc2_resources,
-};
+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	= OTG_BASE_ADDR,
-		.end	= OTG_BASE_ADDR + 0x1ff,
-		.flags	= IORESOURCE_MEM,
+		.start = MX27_USBOTG_BASE_ADDR,
+		.end = MX27_USBOTG_BASE_ADDR + 0x1ff,
+		.flags = IORESOURCE_MEM,
 	}, {
-		.start	= MXC_INT_USB3,
-		.end	= MXC_INT_USB3,
-		.flags	= IORESOURCE_IRQ,
+		.start = MX27_INT_USB3,
+		.end = MX27_INT_USB3,
+		.flags = IORESOURCE_IRQ,
 	},
 };
 
-static u64 otg_dmamask = 0xffffffffUL;
+static u64 otg_dmamask = DMA_BIT_MASK(32);
 
 /* OTG gadget device */
 struct platform_device mxc_otg_udc_device = {
@@ -458,7 +322,7 @@
 	.id		= -1,
 	.dev		= {
 		.dma_mask		= &otg_dmamask,
-		.coherent_dma_mask	= 0xffffffffUL,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
 	},
 	.resource	= otg_resources,
 	.num_resources	= ARRAY_SIZE(otg_resources),
@@ -469,7 +333,7 @@
 	.name = "mxc-ehci",
 	.id = 0,
 	.dev = {
-		.coherent_dma_mask = 0xffffffff,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.dma_mask = &otg_dmamask,
 	},
 	.resource = otg_resources,
@@ -478,16 +342,16 @@
 
 /* USB host 1 */
 
-static u64 usbh1_dmamask = 0xffffffffUL;
+static u64 usbh1_dmamask = DMA_BIT_MASK(32);
 
 static struct resource mxc_usbh1_resources[] = {
 	{
-		.start = OTG_BASE_ADDR + 0x200,
-		.end = OTG_BASE_ADDR + 0x3ff,
+		.start = MX27_USBOTG_BASE_ADDR + 0x200,
+		.end = MX27_USBOTG_BASE_ADDR + 0x3ff,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = MXC_INT_USB1,
-		.end = MXC_INT_USB1,
+		.start = MX27_INT_USB1,
+		.end = MX27_INT_USB1,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -496,7 +360,7 @@
 	.name = "mxc-ehci",
 	.id = 1,
 	.dev = {
-		.coherent_dma_mask = 0xffffffff,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.dma_mask = &usbh1_dmamask,
 	},
 	.resource = mxc_usbh1_resources,
@@ -504,16 +368,16 @@
 };
 
 /* USB host 2 */
-static u64 usbh2_dmamask = 0xffffffffUL;
+static u64 usbh2_dmamask = DMA_BIT_MASK(32);
 
 static struct resource mxc_usbh2_resources[] = {
 	{
-		.start = OTG_BASE_ADDR + 0x400,
-		.end = OTG_BASE_ADDR + 0x5ff,
+		.start = MX27_USBOTG_BASE_ADDR + 0x400,
+		.end = MX27_USBOTG_BASE_ADDR + 0x5ff,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = MXC_INT_USB2,
-		.end = MXC_INT_USB2,
+		.start = MX27_INT_USB2,
+		.end = MX27_INT_USB2,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -522,7 +386,7 @@
 	.name = "mxc-ehci",
 	.id = 2,
 	.dev = {
-		.coherent_dma_mask = 0xffffffff,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
 		.dma_mask = &usbh2_dmamask,
 	},
 	.resource = mxc_usbh2_resources,
@@ -530,115 +394,115 @@
 };
 #endif
 
-static struct resource imx_ssi_resources0[] = {
-	{
-		.start	= SSI1_BASE_ADDR,
-		.end	= SSI1_BASE_ADDR + 0x6F,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MXC_INT_SSI1,
-		.end	= MXC_INT_SSI1,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.name	= "tx0",
-		.start	= DMA_REQ_SSI1_TX0,
-		.end	= DMA_REQ_SSI1_TX0,
-		.flags	= IORESOURCE_DMA,
-	}, {
-		.name	= "rx0",
-		.start	= DMA_REQ_SSI1_RX0,
-		.end	= DMA_REQ_SSI1_RX0,
-		.flags	= IORESOURCE_DMA,
-	}, {
-		.name	= "tx1",
-		.start	= DMA_REQ_SSI1_TX1,
-		.end	= DMA_REQ_SSI1_TX1,
-		.flags	= IORESOURCE_DMA,
-	}, {
-		.name	= "rx1",
-		.start	= DMA_REQ_SSI1_RX1,
-		.end	= DMA_REQ_SSI1_RX1,
-		.flags	= IORESOURCE_DMA,
-	},
-};
+#define DEFINE_IMX_SSI_DMARES(_name, ssin, suffix)			\
+	{								\
+		.name = _name,						\
+		.start = MX2x_DMA_REQ_SSI ## ssin ## _ ## suffix,	\
+		.end = MX2x_DMA_REQ_SSI ## ssin ## _ ## suffix,		\
+		.flags = IORESOURCE_DMA,				\
+	}
 
-static struct resource imx_ssi_resources1[] = {
-	{
-		.start	= SSI2_BASE_ADDR,
-		.end	= SSI2_BASE_ADDR + 0x6F,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= MXC_INT_SSI2,
-		.end	= MXC_INT_SSI2,
-		.flags	= IORESOURCE_IRQ,
-	}, {
-		.name	= "tx0",
-		.start	= DMA_REQ_SSI2_TX0,
-		.end	= DMA_REQ_SSI2_TX0,
-		.flags	= IORESOURCE_DMA,
-	}, {
-		.name	= "rx0",
-		.start	= DMA_REQ_SSI2_RX0,
-		.end	= DMA_REQ_SSI2_RX0,
-		.flags	= IORESOURCE_DMA,
-	}, {
-		.name	= "tx1",
-		.start	= DMA_REQ_SSI2_TX1,
-		.end	= DMA_REQ_SSI2_TX1,
-		.flags	= IORESOURCE_DMA,
-	}, {
-		.name	= "rx1",
-		.start	= DMA_REQ_SSI2_RX1,
-		.end	= DMA_REQ_SSI2_RX1,
-		.flags	= IORESOURCE_DMA,
-	},
-};
+#define DEFINE_IMX_SSI_DEVICE(n, ssin, baseaddr, irq)			\
+	static struct resource imx_ssi_resources ## n[] = {		\
+		{							\
+			.start = MX2x_SSI ## ssin ## _BASE_ADDR,	\
+			.end = MX2x_SSI ## ssin ## _BASE_ADDR + 0x6f,	\
+			.flags = IORESOURCE_MEM,			\
+		}, {							\
+			.start = MX2x_INT_SSI1,				\
+			.end = MX2x_INT_SSI1,				\
+			.flags = IORESOURCE_IRQ,			\
+		},							\
+		DEFINE_IMX_SSI_DMARES("tx0", ssin, TX0),		\
+		DEFINE_IMX_SSI_DMARES("rx0", ssin, RX0),		\
+		DEFINE_IMX_SSI_DMARES("tx1", ssin, TX1),		\
+		DEFINE_IMX_SSI_DMARES("rx1", ssin, RX1),		\
+	};								\
+									\
+	struct platform_device imx_ssi_device ## n = {			\
+		.name = "imx-ssi",					\
+		.id = n,						\
+		.num_resources = ARRAY_SIZE(imx_ssi_resources ## n),	\
+		.resource = imx_ssi_resources ## n,			\
+	}
 
-struct platform_device imx_ssi_device0 = {
-	.name = "imx-ssi",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(imx_ssi_resources0),
-	.resource = imx_ssi_resources0,
-};
-
-struct platform_device imx_ssi_device1 = {
-	.name = "imx-ssi",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(imx_ssi_resources1),
-	.resource = imx_ssi_resources1,
-};
+DEFINE_IMX_SSI_DEVICE(0, 1, MX2x_SSI1_BASE_ADDR, MX2x_INT_SSI1);
+DEFINE_IMX_SSI_DEVICE(1, 2, MX2x_SSI1_BASE_ADDR, MX2x_INT_SSI1);
 
 /* GPIO port description */
-static struct mxc_gpio_port imx_gpio_ports[] = {
-	{
-		.chip.label = "gpio-0",
-		.irq = MXC_INT_GPIO,
-		.base = IO_ADDRESS(GPIO_BASE_ADDR),
-		.virtual_irq_start = MXC_GPIO_IRQ_START,
-	}, {
-		.chip.label = "gpio-1",
-		.base = IO_ADDRESS(GPIO_BASE_ADDR + 0x100),
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 32,
-	}, {
-		.chip.label = "gpio-2",
-		.base = IO_ADDRESS(GPIO_BASE_ADDR + 0x200),
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 64,
-	}, {
-		.chip.label = "gpio-3",
-		.base = IO_ADDRESS(GPIO_BASE_ADDR + 0x300),
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 96,
-	}, {
-		.chip.label = "gpio-4",
-		.base = IO_ADDRESS(GPIO_BASE_ADDR + 0x400),
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 128,
-	}, {
-		.chip.label = "gpio-5",
-		.base = IO_ADDRESS(GPIO_BASE_ADDR + 0x500),
-		.virtual_irq_start = MXC_GPIO_IRQ_START + 160,
+#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);
+#endif
+
+#ifdef CONFIG_MACH_MX27
+DEFINE_MXC_GPIO_PORTS(MX27, imx27);
+#endif
 
 int __init mxc_register_gpios(void)
 {
-	return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports));
+#ifdef CONFIG_MACH_MX21
+	if (cpu_is_mx21())
+		return mxc_gpio_init(imx21_gpio_ports, ARRAY_SIZE(imx21_gpio_ports));
+	else
+#endif
+#ifdef CONFIG_MACH_MX27
+	if (cpu_is_mx27())
+		return mxc_gpio_init(imx27_gpio_ports, ARRAY_SIZE(imx27_gpio_ports));
+	else
+#endif
+		return 0;
 }
+
+#ifdef CONFIG_MACH_MX21
+static struct resource mx21_usbhc_resources[] = {
+	{
+		.start	= MX21_BASE_ADDR,
+		.end	= MX21_BASE_ADDR + 0x1FFF,
+		.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
+
diff --git a/arch/arm/mach-mx2/devices.h b/arch/arm/mach-mx2/devices.h
index 97306aa..84ed513 100644
--- a/arch/arm/mach-mx2/devices.h
+++ b/arch/arm/mach-mx2/devices.h
@@ -1,8 +1,10 @@
 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_uart_device0;
 extern struct platform_device mxc_uart_device1;
@@ -11,12 +13,19 @@
 extern struct platform_device mxc_uart_device4;
 extern struct platform_device mxc_uart_device5;
 extern struct platform_device mxc_w1_master_device;
-extern struct platform_device mxc_nand_device;
+#ifdef CONFIG_MACH_MX21
+extern struct platform_device imx21_nand_device;
+#endif
+#ifdef CONFIG_MACH_MX27
+extern struct platform_device imx27_nand_device;
+#endif
 extern struct platform_device mxc_fb_device;
 extern struct platform_device mxc_fec_device;
 extern struct platform_device mxc_pwm_device;
 extern struct platform_device mxc_i2c_device0;
+#ifdef CONFIG_MACH_MX27
 extern struct platform_device mxc_i2c_device1;
+#endif
 extern struct platform_device mxc_sdhc_device0;
 extern struct platform_device mxc_sdhc_device1;
 extern struct platform_device mxc_otg_udc_device;
@@ -25,6 +34,9 @@
 extern struct platform_device mxc_usbh2;
 extern struct platform_device mxc_spi_device0;
 extern struct platform_device mxc_spi_device1;
+#ifdef CONFIG_MACH_MX27
 extern struct platform_device mxc_spi_device2;
+#endif
+extern struct platform_device mx21_usbhc_device;
 extern struct platform_device imx_ssi_device0;
 extern struct platform_device imx_ssi_device1;
diff --git a/arch/arm/mach-mx2/eukrea_cpuimx27.c b/arch/arm/mach-mx2/eukrea_cpuimx27.c
deleted file mode 100644
index 7b18760..0000000
--- a/arch/arm/mach-mx2/eukrea_cpuimx27.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2009 Eric Benard - eric@eukrea.com
- *
- * Based on pcm038.c which is :
- * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
- * 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/i2c.h>
-#include <linux/io.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include <mach/board-eukrea_cpuimx27.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/i2c.h>
-#include <mach/iomux.h>
-#include <mach/imx-uart.h>
-#include <mach/mxc_nand.h>
-
-#include "devices.h"
-
-static int eukrea_cpuimx27_pins[] = {
-	/* UART1 */
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS,
-	/* UART4 */
-	PB26_AF_UART4_RTS,
-	PB28_AF_UART4_TXD,
-	PB29_AF_UART4_CTS,
-	PB31_AF_UART4_RXD,
-	/* FEC */
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN,
-	/* I2C1 */
-	PD17_PF_I2C_DATA,
-	PD18_PF_I2C_CLK,
-	/* SDHC2 */
-	PB4_PF_SD2_D0,
-	PB5_PF_SD2_D1,
-	PB6_PF_SD2_D2,
-	PB7_PF_SD2_D3,
-	PB8_PF_SD2_CMD,
-	PB9_PF_SD2_CLK,
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
-	/* Quad UART's IRQ */
-	GPIO_PORTD | 22 | GPIO_GPIO | GPIO_IN,
-	GPIO_PORTD | 23 | GPIO_GPIO | GPIO_IN,
-	GPIO_PORTD | 27 | GPIO_GPIO | GPIO_IN,
-	GPIO_PORTD | 30 | GPIO_GPIO | GPIO_IN,
-#endif
-};
-
-static struct physmap_flash_data eukrea_cpuimx27_flash_data = {
-	.width = 2,
-};
-
-static struct resource eukrea_cpuimx27_flash_resource = {
-	.start = 0xc0000000,
-	.end   = 0xc3ffffff,
-	.flags = IORESOURCE_MEM,
-};
-
-static struct platform_device eukrea_cpuimx27_nor_mtd_device = {
-	.name = "physmap-flash",
-	.id = 0,
-	.dev = {
-		.platform_data = &eukrea_cpuimx27_flash_data,
-	},
-	.num_resources = 1,
-	.resource = &eukrea_cpuimx27_flash_resource,
-};
-
-static struct imxuart_platform_data uart_pdata[] = {
-	{
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	},
-};
-
-static struct mxc_nand_platform_data eukrea_cpuimx27_nand_board_info = {
-	.width = 1,
-	.hw_ecc = 1,
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-	&eukrea_cpuimx27_nor_mtd_device,
-	&mxc_fec_device,
-};
-
-static struct imxi2c_platform_data eukrea_cpuimx27_i2c_1_data = {
-	.bitrate = 100000,
-};
-
-static struct i2c_board_info eukrea_cpuimx27_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("pcf8563", 0x51),
-	},
-};
-
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
-static struct plat_serial8250_port serial_platform_data[] = {
-	{
-		.mapbase = (unsigned long)(CS3_BASE_ADDR + 0x200000),
-		.irq = IRQ_GPIOB(23),
-		.uartclk = 14745600,
-		.regshift = 1,
-		.iotype = UPIO_MEM,
-		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-	}, {
-		.mapbase = (unsigned long)(CS3_BASE_ADDR + 0x400000),
-		.irq = IRQ_GPIOB(22),
-		.uartclk = 14745600,
-		.regshift = 1,
-		.iotype = UPIO_MEM,
-		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-	}, {
-		.mapbase = (unsigned long)(CS3_BASE_ADDR + 0x800000),
-		.irq = IRQ_GPIOB(27),
-		.uartclk = 14745600,
-		.regshift = 1,
-		.iotype = UPIO_MEM,
-		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-	}, {
-		.mapbase = (unsigned long)(CS3_BASE_ADDR + 0x1000000),
-		.irq = IRQ_GPIOB(30),
-		.uartclk = 14745600,
-		.regshift = 1,
-		.iotype = UPIO_MEM,
-		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-	}, {
-	}
-};
-
-static struct platform_device serial_device = {
-	.name = "serial8250",
-	.id = 0,
-	.dev = {
-		.platform_data = serial_platform_data,
-	},
-};
-#endif
-
-static void __init eukrea_cpuimx27_init(void)
-{
-	mxc_gpio_setup_multiple_pins(eukrea_cpuimx27_pins,
-		ARRAY_SIZE(eukrea_cpuimx27_pins), "CPUIMX27");
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
-
-	mxc_register_device(&mxc_nand_device, &eukrea_cpuimx27_nand_board_info);
-
-	i2c_register_board_info(0, eukrea_cpuimx27_i2c_devices,
-				ARRAY_SIZE(eukrea_cpuimx27_i2c_devices));
-
-	mxc_register_device(&mxc_i2c_device0, &eukrea_cpuimx27_i2c_1_data);
-
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-
-#if defined(CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2)
-	/* SDHC2 can be used for Wifi */
-	mxc_register_device(&mxc_sdhc_device1, NULL);
-	/* in which case UART4 is also used for Bluetooth */
-	mxc_register_device(&mxc_uart_device3, &uart_pdata[1]);
-#endif
-
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
-	platform_device_register(&serial_device);
-#endif
-
-#ifdef CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD
-	eukrea_mbimx27_baseboard_init();
-#endif
-}
-
-static void __init eukrea_cpuimx27_timer_init(void)
-{
-	mx27_clocks_init(26000000);
-}
-
-static struct sys_timer eukrea_cpuimx27_timer = {
-	.init = eukrea_cpuimx27_timer_init,
-};
-
-MACHINE_START(CPUIMX27, "EUKREA CPUIMX27")
-	.phys_io        = AIPI_BASE_ADDR,
-	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = eukrea_cpuimx27_init,
-	.timer          = &eukrea_cpuimx27_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx2/eukrea_mbimx27-baseboard.c b/arch/arm/mach-mx2/eukrea_mbimx27-baseboard.c
index 7382b6d..f3b169d 100644
--- a/arch/arm/mach-mx2/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-mx2/eukrea_mbimx27-baseboard.c
@@ -28,7 +28,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/common.h>
-#include <mach/iomux.h>
+#include <mach/iomux-mx27.h>
 #include <mach/imxfb.h>
 #include <mach/hardware.h>
 #include <mach/mmc.h>
diff --git a/arch/arm/mach-mx2/generic.c b/arch/arm/mach-mx2/generic.c
deleted file mode 100644
index ae8f759..0000000
--- a/arch/arm/mach-mx2/generic.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * generic.c
- *
- * 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/mm.h>
-#include <linux/init.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-
-/* MX27 memory map definition */
-static struct map_desc mxc_io_desc[] __initdata = {
-	/*
-	 * this fixed mapping covers:
-	 * - AIPI1
-	 * - AIPI2
-	 * - AITC
-	 * - ROM Patch
-	 * - and some reserved space
-	 */
-	{
-		.virtual = AIPI_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(AIPI_BASE_ADDR),
-		.length = AIPI_SIZE,
-		.type = MT_DEVICE
-	},
-	/*
-	 * this fixed mapping covers:
-	 * - CSI
-	 * - ATA
-	 */
-	{
-		.virtual = SAHB1_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(SAHB1_BASE_ADDR),
-		.length = SAHB1_SIZE,
-		.type = MT_DEVICE
-	},
-	/*
-	 * this fixed mapping covers:
-	 * - EMI
-	 */
-	{
-		.virtual = X_MEMC_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(X_MEMC_BASE_ADDR),
-		.length = X_MEMC_SIZE,
-		.type = MT_DEVICE
-	}
-};
-
-/*
- * Initialize the memory map. It is called during the
- * system startup to create static physical to virtual
- * memory map for the IO modules.
- */
-void __init mx21_map_io(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX21);
-	mxc_arch_reset_init(IO_ADDRESS(WDOG_BASE_ADDR));
-
-	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
-}
-
-void __init mx27_map_io(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX27);
-	mxc_arch_reset_init(IO_ADDRESS(WDOG_BASE_ADDR));
-
-	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
-}
-
-void __init mx27_init_irq(void)
-{
-	mxc_init_irq(IO_ADDRESS(AVIC_BASE_ADDR));
-}
-
-void __init mx21_init_irq(void)
-{
-	mx27_init_irq();
-}
-
diff --git a/arch/arm/mach-mx2/mach-cpuimx27.c b/arch/arm/mach-mx2/mach-cpuimx27.c
new file mode 100644
index 0000000..1f616dca
--- /dev/null
+++ b/arch/arm/mach-mx2/mach-cpuimx27.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2009 Eric Benard - eric@eukrea.com
+ *
+ * Based on pcm038.c which is :
+ * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * 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/i2c.h>
+#include <linux/io.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/board-eukrea_cpuimx27.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/i2c.h>
+#include <mach/iomux-mx27.h>
+#include <mach/imx-uart.h>
+#include <mach/mxc_nand.h>
+
+#include "devices.h"
+
+static int eukrea_cpuimx27_pins[] = {
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* UART4 */
+	PB26_AF_UART4_RTS,
+	PB28_AF_UART4_TXD,
+	PB29_AF_UART4_CTS,
+	PB31_AF_UART4_RXD,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+	/* I2C1 */
+	PD17_PF_I2C_DATA,
+	PD18_PF_I2C_CLK,
+	/* SDHC2 */
+	PB4_PF_SD2_D0,
+	PB5_PF_SD2_D1,
+	PB6_PF_SD2_D2,
+	PB7_PF_SD2_D3,
+	PB8_PF_SD2_CMD,
+	PB9_PF_SD2_CLK,
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+	/* Quad UART's IRQ */
+	GPIO_PORTD | 22 | GPIO_GPIO | GPIO_IN,
+	GPIO_PORTD | 23 | GPIO_GPIO | GPIO_IN,
+	GPIO_PORTD | 27 | GPIO_GPIO | GPIO_IN,
+	GPIO_PORTD | 30 | GPIO_GPIO | GPIO_IN,
+#endif
+};
+
+static struct physmap_flash_data eukrea_cpuimx27_flash_data = {
+	.width = 2,
+};
+
+static struct resource eukrea_cpuimx27_flash_resource = {
+	.start = 0xc0000000,
+	.end   = 0xc3ffffff,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device eukrea_cpuimx27_nor_mtd_device = {
+	.name = "physmap-flash",
+	.id = 0,
+	.dev = {
+		.platform_data = &eukrea_cpuimx27_flash_data,
+	},
+	.num_resources = 1,
+	.resource = &eukrea_cpuimx27_flash_resource,
+};
+
+static struct imxuart_platform_data uart_pdata[] = {
+	{
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	},
+};
+
+static struct mxc_nand_platform_data eukrea_cpuimx27_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&eukrea_cpuimx27_nor_mtd_device,
+	&mxc_fec_device,
+};
+
+static struct imxi2c_platform_data eukrea_cpuimx27_i2c_1_data = {
+	.bitrate = 100000,
+};
+
+static struct i2c_board_info eukrea_cpuimx27_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	},
+};
+
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+static struct plat_serial8250_port serial_platform_data[] = {
+	{
+		.mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x200000),
+		.irq = IRQ_GPIOB(23),
+		.uartclk = 14745600,
+		.regshift = 1,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+	}, {
+		.mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x400000),
+		.irq = IRQ_GPIOB(22),
+		.uartclk = 14745600,
+		.regshift = 1,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+	}, {
+		.mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x800000),
+		.irq = IRQ_GPIOB(27),
+		.uartclk = 14745600,
+		.regshift = 1,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+	}, {
+		.mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x1000000),
+		.irq = IRQ_GPIOB(30),
+		.uartclk = 14745600,
+		.regshift = 1,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+	}, {
+	}
+};
+
+static struct platform_device serial_device = {
+	.name = "serial8250",
+	.id = 0,
+	.dev = {
+		.platform_data = serial_platform_data,
+	},
+};
+#endif
+
+static void __init eukrea_cpuimx27_init(void)
+{
+	mxc_gpio_setup_multiple_pins(eukrea_cpuimx27_pins,
+		ARRAY_SIZE(eukrea_cpuimx27_pins), "CPUIMX27");
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
+
+	mxc_register_device(&imx27_nand_device,
+			&eukrea_cpuimx27_nand_board_info);
+
+	i2c_register_board_info(0, eukrea_cpuimx27_i2c_devices,
+				ARRAY_SIZE(eukrea_cpuimx27_i2c_devices));
+
+	mxc_register_device(&mxc_i2c_device0, &eukrea_cpuimx27_i2c_1_data);
+
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+#if defined(CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2)
+	/* SDHC2 can be used for Wifi */
+	mxc_register_device(&mxc_sdhc_device1, NULL);
+	/* in which case UART4 is also used for Bluetooth */
+	mxc_register_device(&mxc_uart_device3, &uart_pdata[1]);
+#endif
+
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+	platform_device_register(&serial_device);
+#endif
+
+#ifdef CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD
+	eukrea_mbimx27_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx27_timer_init(void)
+{
+	mx27_clocks_init(26000000);
+}
+
+static struct sys_timer eukrea_cpuimx27_timer = {
+	.init = eukrea_cpuimx27_timer_init,
+};
+
+MACHINE_START(CPUIMX27, "EUKREA CPUIMX27")
+	.phys_io        = MX27_AIPI_BASE_ADDR,
+	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = MX27_PHYS_OFFSET + 0x100,
+	.map_io         = mx27_map_io,
+	.init_irq       = mx27_init_irq,
+	.init_machine   = eukrea_cpuimx27_init,
+	.timer          = &eukrea_cpuimx27_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx2/mach-imx27lite.c b/arch/arm/mach-mx2/mach-imx27lite.c
new file mode 100644
index 0000000..b5710bf
--- /dev/null
+++ b/arch/arm/mach-mx2/mach-imx27lite.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ * Copyright 2009 Daniel Schaeffer (daniel.schaeffer@timesys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx27.h>
+#include <mach/board-mx27lite.h>
+
+#include "devices.h"
+
+static unsigned int mx27lite_pins[] = {
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&mxc_fec_device,
+};
+
+static void __init mx27lite_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
+		"imx27lite");
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init mx27lite_timer_init(void)
+{
+	mx27_clocks_init(26000000);
+}
+
+static struct sys_timer mx27lite_timer = {
+	.init	= mx27lite_timer_init,
+};
+
+MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
+	.phys_io        = MX27_AIPI_BASE_ADDR,
+	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = MX27_PHYS_OFFSET + 0x100,
+	.map_io         = mx27_map_io,
+	.init_irq       = mx27_init_irq,
+	.init_machine   = mx27lite_init,
+	.timer          = &mx27lite_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx2/mach-mx21ads.c b/arch/arm/mach-mx2/mach-mx21ads.c
new file mode 100644
index 0000000..113e58d
--- /dev/null
+++ b/arch/arm/mach-mx2/mach-mx21ads.c
@@ -0,0 +1,294 @@
+/*
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2006-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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/physmap.h>
+#include <linux/gpio.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 <asm/mach/map.h>
+#include <mach/imx-uart.h>
+#include <mach/imxfb.h>
+#include <mach/iomux-mx21.h>
+#include <mach/mxc_nand.h>
+#include <mach/mmc.h>
+#include <mach/board-mx21ads.h>
+
+#include "devices.h"
+
+static unsigned int mx21ads_pins[] = {
+
+	/* CS8900A */
+	(GPIO_PORTE | GPIO_GPIO | GPIO_IN | 11),
+
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+
+	/* UART3 (IrDA) - only TXD and RXD */
+	PE8_PF_UART3_TXD,
+	PE9_PF_UART3_RXD,
+
+	/* UART4 */
+	PB26_AF_UART4_RTS,
+	PB28_AF_UART4_TXD,
+	PB29_AF_UART4_CTS,
+	PB31_AF_UART4_RXD,
+
+	/* LCDC */
+	PA5_PF_LSCLK,
+	PA6_PF_LD0,
+	PA7_PF_LD1,
+	PA8_PF_LD2,
+	PA9_PF_LD3,
+	PA10_PF_LD4,
+	PA11_PF_LD5,
+	PA12_PF_LD6,
+	PA13_PF_LD7,
+	PA14_PF_LD8,
+	PA15_PF_LD9,
+	PA16_PF_LD10,
+	PA17_PF_LD11,
+	PA18_PF_LD12,
+	PA19_PF_LD13,
+	PA20_PF_LD14,
+	PA21_PF_LD15,
+	PA22_PF_LD16,
+	PA24_PF_REV,     /* Sharp panel dedicated signal */
+	PA25_PF_CLS,     /* Sharp panel dedicated signal */
+	PA26_PF_PS,      /* Sharp panel dedicated signal */
+	PA27_PF_SPL_SPR, /* Sharp panel dedicated signal */
+	PA28_PF_HSYNC,
+	PA29_PF_VSYNC,
+	PA30_PF_CONTRAST,
+	PA31_PF_OE_ACD,
+
+	/* MMC/SDHC */
+	PE18_PF_SD1_D0,
+	PE19_PF_SD1_D1,
+	PE20_PF_SD1_D2,
+	PE21_PF_SD1_D3,
+	PE22_PF_SD1_CMD,
+	PE23_PF_SD1_CLK,
+
+	/* NFC */
+	PF0_PF_NRFB,
+	PF1_PF_NFCE,
+	PF2_PF_NFWP,
+	PF3_PF_NFCLE,
+	PF4_PF_NFALE,
+	PF5_PF_NFRE,
+	PF6_PF_NFWE,
+	PF7_PF_NFIO0,
+	PF8_PF_NFIO1,
+	PF9_PF_NFIO2,
+	PF10_PF_NFIO3,
+	PF11_PF_NFIO4,
+	PF12_PF_NFIO5,
+	PF13_PF_NFIO6,
+	PF14_PF_NFIO7,
+};
+
+/* ADS's NOR flash: 2x AM29BDS128HE9VKI on 32-bit bus */
+static struct physmap_flash_data mx21ads_flash_data = {
+	.width = 4,
+};
+
+static struct resource mx21ads_flash_resource = {
+	.start = MX21_CS0_BASE_ADDR,
+	.end = MX21_CS0_BASE_ADDR + 0x02000000 - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device mx21ads_nor_mtd_device = {
+	.name = "physmap-flash",
+	.id = 0,
+	.dev = {
+		.platform_data = &mx21ads_flash_data,
+	},
+	.num_resources = 1,
+	.resource = &mx21ads_flash_resource,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct imxuart_platform_data uart_norts_pdata = {
+};
+
+
+static int mx21ads_fb_init(struct platform_device *pdev)
+{
+	u16 tmp;
+
+	tmp = __raw_readw(MX21ADS_IO_REG);
+	tmp |= MX21ADS_IO_LCDON;
+	__raw_writew(tmp, MX21ADS_IO_REG);
+	return 0;
+}
+
+static void mx21ads_fb_exit(struct platform_device *pdev)
+{
+	u16 tmp;
+
+	tmp = __raw_readw(MX21ADS_IO_REG);
+	tmp &= ~MX21ADS_IO_LCDON;
+	__raw_writew(tmp, MX21ADS_IO_REG);
+}
+
+/*
+ * Connected is a portrait Sharp-QVGA display
+ * of type: LQ035Q7DB02
+ */
+static struct imx_fb_videomode mx21ads_modes[] = {
+	{
+		.mode = {
+			.name		= "Sharp-LQ035Q7",
+			.refresh	= 60,
+			.xres		= 240,
+			.yres		= 320,
+			.pixclock	= 188679, /* in ps (5.3MHz) */
+			.hsync_len	= 2,
+			.left_margin	= 6,
+			.right_margin	= 16,
+			.vsync_len	= 1,
+			.upper_margin	= 8,
+			.lower_margin	= 10,
+		},
+		.pcr		= 0xfb108bc7,
+		.bpp		= 16,
+	},
+};
+
+static struct imx_fb_platform_data mx21ads_fb_data = {
+	.mode = mx21ads_modes,
+	.num_modes = ARRAY_SIZE(mx21ads_modes),
+
+	.pwmr		= 0x00a903ff,
+	.lscr1		= 0x00120300,
+	.dmacr		= 0x00020008,
+
+	.init = mx21ads_fb_init,
+	.exit = mx21ads_fb_exit,
+};
+
+static int mx21ads_sdhc_get_ro(struct device *dev)
+{
+	return (__raw_readw(MX21ADS_IO_REG) & MX21ADS_IO_SD_WP) ? 1 : 0;
+}
+
+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,
+		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)
+{
+	free_irq(IRQ_GPIOD(25), data);
+}
+
+static struct imxmmc_platform_data mx21ads_sdhc_pdata = {
+	.ocr_avail = MMC_VDD_29_30 | MMC_VDD_30_31, /* 3.0V */
+	.get_ro = mx21ads_sdhc_get_ro,
+	.init = mx21ads_sdhc_init,
+	.exit = mx21ads_sdhc_exit,
+};
+
+static struct mxc_nand_platform_data mx21ads_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+static struct map_desc mx21ads_io_desc[] __initdata = {
+	/*
+	 * Memory-mapped I/O on MX21ADS Base board:
+	 *   - CS8900A Ethernet controller
+	 *   - ST16C2552CJ UART
+	 *   - CPU and Base board version
+	 *   - Base board I/O register
+	 */
+	{
+		.virtual = MX21ADS_MMIO_BASE_ADDR,
+		.pfn = __phys_to_pfn(MX21_CS1_BASE_ADDR),
+		.length = MX21ADS_MMIO_SIZE,
+		.type = MT_DEVICE,
+	},
+};
+
+static void __init mx21ads_map_io(void)
+{
+	mx21_map_io();
+	iotable_init(mx21ads_io_desc, ARRAY_SIZE(mx21ads_io_desc));
+}
+
+static struct platform_device *platform_devices[] __initdata = {
+	&mx21ads_nor_mtd_device,
+};
+
+static void __init mx21ads_board_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mx21ads_pins, ARRAY_SIZE(mx21ads_pins),
+			"mx21ads");
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	mxc_register_device(&mxc_uart_device2, &uart_norts_pdata);
+	mxc_register_device(&mxc_uart_device3, &uart_pdata);
+	mxc_register_device(&mxc_fb_device, &mx21ads_fb_data);
+	mxc_register_device(&mxc_sdhc_device0, &mx21ads_sdhc_pdata);
+	mxc_register_device(&imx21_nand_device, &mx21ads_nand_board_info);
+
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init mx21ads_timer_init(void)
+{
+	mx21_clocks_init(32768, 26000000);
+}
+
+static struct sys_timer mx21ads_timer = {
+	.init	= mx21ads_timer_init,
+};
+
+MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
+	/* maintainer: Freescale Semiconductor, Inc. */
+	.phys_io        = MX21_AIPI_BASE_ADDR,
+	.io_pg_offst    = ((MX21_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = MX21_PHYS_OFFSET + 0x100,
+	.map_io         = mx21ads_map_io,
+	.init_irq       = mx21_init_irq,
+	.init_machine   = mx21ads_board_init,
+	.timer          = &mx21ads_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx2/mach-mx27_3ds.c b/arch/arm/mach-mx2/mach-mx27_3ds.c
new file mode 100644
index 0000000..b2f4e0d
--- /dev/null
+++ b/arch/arm/mach-mx2/mach-mx27_3ds.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx27.h>
+#include <mach/board-mx27pdk.h>
+
+#include "devices.h"
+
+static unsigned int mx27pdk_pins[] = {
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&mxc_fec_device,
+};
+
+static void __init mx27pdk_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
+		"mx27pdk");
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init mx27pdk_timer_init(void)
+{
+	mx27_clocks_init(26000000);
+}
+
+static struct sys_timer mx27pdk_timer = {
+	.init	= mx27pdk_timer_init,
+};
+
+MACHINE_START(MX27_3DS, "Freescale MX27PDK")
+	/* maintainer: Freescale Semiconductor, Inc. */
+	.phys_io        = MX27_AIPI_BASE_ADDR,
+	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = MX27_PHYS_OFFSET + 0x100,
+	.map_io         = mx27_map_io,
+	.init_irq       = mx27_init_irq,
+	.init_machine   = mx27pdk_init,
+	.timer          = &mx27pdk_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx2/mach-mx27ads.c b/arch/arm/mach-mx2/mach-mx27ads.c
new file mode 100644
index 0000000..6ce3236
--- /dev/null
+++ b/arch/arm/mach-mx2/mach-mx27ads.c
@@ -0,0 +1,345 @@
+/*
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2006-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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+#include <linux/irq.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 <asm/mach/map.h>
+#include <mach/gpio.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx27.h>
+#include <mach/board-mx27ads.h>
+#include <mach/mxc_nand.h>
+#include <mach/i2c.h>
+#include <mach/imxfb.h>
+#include <mach/mmc.h>
+
+#include "devices.h"
+
+static unsigned int mx27ads_pins[] = {
+	/* UART0 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* UART1 */
+	PE3_PF_UART2_CTS,
+	PE4_PF_UART2_RTS,
+	PE6_PF_UART2_TXD,
+	PE7_PF_UART2_RXD,
+	/* UART2 */
+	PE8_PF_UART3_TXD,
+	PE9_PF_UART3_RXD,
+	PE10_PF_UART3_CTS,
+	PE11_PF_UART3_RTS,
+	/* UART3 */
+	PB26_AF_UART4_RTS,
+	PB28_AF_UART4_TXD,
+	PB29_AF_UART4_CTS,
+	PB31_AF_UART4_RXD,
+	/* UART4 */
+	PB18_AF_UART5_TXD,
+	PB19_AF_UART5_RXD,
+	PB20_AF_UART5_CTS,
+	PB21_AF_UART5_RTS,
+	/* UART5 */
+	PB10_AF_UART6_TXD,
+	PB12_AF_UART6_CTS,
+	PB11_AF_UART6_RXD,
+	PB13_AF_UART6_RTS,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+	/* I2C2 */
+	PC5_PF_I2C2_SDA,
+	PC6_PF_I2C2_SCL,
+	/* FB */
+	PA5_PF_LSCLK,
+	PA6_PF_LD0,
+	PA7_PF_LD1,
+	PA8_PF_LD2,
+	PA9_PF_LD3,
+	PA10_PF_LD4,
+	PA11_PF_LD5,
+	PA12_PF_LD6,
+	PA13_PF_LD7,
+	PA14_PF_LD8,
+	PA15_PF_LD9,
+	PA16_PF_LD10,
+	PA17_PF_LD11,
+	PA18_PF_LD12,
+	PA19_PF_LD13,
+	PA20_PF_LD14,
+	PA21_PF_LD15,
+	PA22_PF_LD16,
+	PA23_PF_LD17,
+	PA24_PF_REV,
+	PA25_PF_CLS,
+	PA26_PF_PS,
+	PA27_PF_SPL_SPR,
+	PA28_PF_HSYNC,
+	PA29_PF_VSYNC,
+	PA30_PF_CONTRAST,
+	PA31_PF_OE_ACD,
+	/* OWIRE */
+	PE16_AF_OWIRE,
+	/* SDHC1*/
+	PE18_PF_SD1_D0,
+	PE19_PF_SD1_D1,
+	PE20_PF_SD1_D2,
+	PE21_PF_SD1_D3,
+	PE22_PF_SD1_CMD,
+	PE23_PF_SD1_CLK,
+	/* SDHC2*/
+	PB4_PF_SD2_D0,
+	PB5_PF_SD2_D1,
+	PB6_PF_SD2_D2,
+	PB7_PF_SD2_D3,
+	PB8_PF_SD2_CMD,
+	PB9_PF_SD2_CLK,
+};
+
+static struct mxc_nand_platform_data mx27ads_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+/* ADS's NOR flash */
+static struct physmap_flash_data mx27ads_flash_data = {
+	.width = 2,
+};
+
+static struct resource mx27ads_flash_resource = {
+	.start = 0xc0000000,
+	.end = 0xc0000000 + 0x02000000 - 1,
+	.flags = IORESOURCE_MEM,
+
+};
+
+static struct platform_device mx27ads_nor_mtd_device = {
+	.name = "physmap-flash",
+	.id = 0,
+	.dev = {
+		.platform_data = &mx27ads_flash_data,
+	},
+	.num_resources = 1,
+	.resource = &mx27ads_flash_resource,
+};
+
+static struct imxi2c_platform_data mx27ads_i2c_data = {
+	.bitrate = 100000,
+};
+
+static struct i2c_board_info mx27ads_i2c_devices[] = {
+};
+
+void lcd_power(int on)
+{
+	if (on)
+		__raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_SET_REG);
+	else
+		__raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG);
+}
+
+static struct imx_fb_videomode mx27ads_modes[] = {
+	{
+		.mode = {
+			.name		= "Sharp-LQ035Q7",
+			.refresh	= 60,
+			.xres		= 240,
+			.yres		= 320,
+			.pixclock	= 188679, /* in ps (5.3MHz) */
+			.hsync_len	= 1,
+			.left_margin	= 9,
+			.right_margin	= 16,
+			.vsync_len	= 1,
+			.upper_margin	= 7,
+			.lower_margin	= 9,
+		},
+		.bpp		= 16,
+		.pcr		= 0xFB008BC0,
+	},
+};
+
+static struct imx_fb_platform_data mx27ads_fb_data = {
+	.mode = mx27ads_modes,
+	.num_modes = ARRAY_SIZE(mx27ads_modes),
+
+	/*
+	 * - HSYNC active high
+	 * - VSYNC active high
+	 * - clk notenabled while idle
+	 * - clock inverted
+	 * - data not inverted
+	 * - data enable low active
+	 * - enable sharp mode
+	 */
+	.pwmr		= 0x00A903FF,
+	.lscr1		= 0x00120300,
+	.dmacr		= 0x00020010,
+
+	.lcd_power	= lcd_power,
+};
+
+static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
+			      void *data)
+{
+	return request_irq(IRQ_GPIOE(21), detect_irq, IRQF_TRIGGER_RISING,
+			   "sdhc1-card-detect", data);
+}
+
+static int mx27ads_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
+			      void *data)
+{
+	return request_irq(IRQ_GPIOB(7), detect_irq, IRQF_TRIGGER_RISING,
+			   "sdhc2-card-detect", data);
+}
+
+static void mx27ads_sdhc1_exit(struct device *dev, void *data)
+{
+	free_irq(IRQ_GPIOE(21), data);
+}
+
+static void mx27ads_sdhc2_exit(struct device *dev, void *data)
+{
+	free_irq(IRQ_GPIOB(7), data);
+}
+
+static struct imxmmc_platform_data sdhc1_pdata = {
+	.init = mx27ads_sdhc1_init,
+	.exit = mx27ads_sdhc1_exit,
+};
+
+static struct imxmmc_platform_data sdhc2_pdata = {
+	.init = mx27ads_sdhc2_init,
+	.exit = mx27ads_sdhc2_exit,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&mx27ads_nor_mtd_device,
+	&mxc_fec_device,
+	&mxc_w1_master_device,
+};
+
+static struct imxuart_platform_data uart_pdata[] = {
+	{
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	},
+};
+
+static void __init mx27ads_board_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mx27ads_pins, ARRAY_SIZE(mx27ads_pins),
+			"mx27ads");
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
+	mxc_register_device(&mxc_uart_device1, &uart_pdata[1]);
+	mxc_register_device(&mxc_uart_device2, &uart_pdata[2]);
+	mxc_register_device(&mxc_uart_device3, &uart_pdata[3]);
+	mxc_register_device(&mxc_uart_device4, &uart_pdata[4]);
+	mxc_register_device(&mxc_uart_device5, &uart_pdata[5]);
+	mxc_register_device(&imx27_nand_device, &mx27ads_nand_board_info);
+
+	/* only the i2c master 1 is used on this CPU card */
+	i2c_register_board_info(1, mx27ads_i2c_devices,
+				ARRAY_SIZE(mx27ads_i2c_devices));
+	mxc_register_device(&mxc_i2c_device1, &mx27ads_i2c_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);
+
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init mx27ads_timer_init(void)
+{
+	unsigned long fref = 26000000;
+
+	if ((__raw_readw(PBC_VERSION_REG) & CKIH_27MHZ_BIT_SET) == 0)
+		fref = 27000000;
+
+	mx27_clocks_init(fref);
+}
+
+static struct sys_timer mx27ads_timer = {
+	.init	= mx27ads_timer_init,
+};
+
+static struct map_desc mx27ads_io_desc[] __initdata = {
+	{
+		.virtual = PBC_BASE_ADDRESS,
+		.pfn = __phys_to_pfn(MX27_CS4_BASE_ADDR),
+		.length = SZ_1M,
+		.type = MT_DEVICE,
+	},
+};
+
+static void __init mx27ads_map_io(void)
+{
+	mx27_map_io();
+	iotable_init(mx27ads_io_desc, ARRAY_SIZE(mx27ads_io_desc));
+}
+
+MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
+	/* maintainer: Freescale Semiconductor, Inc. */
+	.phys_io        = MX27_AIPI_BASE_ADDR,
+	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = MX27_PHYS_OFFSET + 0x100,
+	.map_io         = mx27ads_map_io,
+	.init_irq       = mx27_init_irq,
+	.init_machine   = mx27ads_board_init,
+	.timer          = &mx27ads_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-mx2/mach-mxt_td60.c b/arch/arm/mach-mx2/mach-mxt_td60.c
new file mode 100644
index 0000000..bc38559
--- /dev/null
+++ b/arch/arm/mach-mx2/mach-mxt_td60.c
@@ -0,0 +1,295 @@
+/*
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2006-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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+#include <linux/irq.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 <asm/mach/map.h>
+#include <linux/gpio.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx27.h>
+#include <mach/mxc_nand.h>
+#include <mach/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <mach/imxfb.h>
+#include <mach/mmc.h>
+
+#include "devices.h"
+
+static unsigned int mxt_td60_pins[] __initdata = {
+	/* UART0 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* UART1 */
+	PE3_PF_UART2_CTS,
+	PE4_PF_UART2_RTS,
+	PE6_PF_UART2_TXD,
+	PE7_PF_UART2_RXD,
+	/* UART2 */
+	PE8_PF_UART3_TXD,
+	PE9_PF_UART3_RXD,
+	PE10_PF_UART3_CTS,
+	PE11_PF_UART3_RTS,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+	/* I2C1 */
+	PD17_PF_I2C_DATA,
+	PD18_PF_I2C_CLK,
+	/* I2C2 */
+	PC5_PF_I2C2_SDA,
+	PC6_PF_I2C2_SCL,
+	/* FB */
+	PA5_PF_LSCLK,
+	PA6_PF_LD0,
+	PA7_PF_LD1,
+	PA8_PF_LD2,
+	PA9_PF_LD3,
+	PA10_PF_LD4,
+	PA11_PF_LD5,
+	PA12_PF_LD6,
+	PA13_PF_LD7,
+	PA14_PF_LD8,
+	PA15_PF_LD9,
+	PA16_PF_LD10,
+	PA17_PF_LD11,
+	PA18_PF_LD12,
+	PA19_PF_LD13,
+	PA20_PF_LD14,
+	PA21_PF_LD15,
+	PA22_PF_LD16,
+	PA23_PF_LD17,
+	PA25_PF_CLS,
+	PA27_PF_SPL_SPR,
+	PA28_PF_HSYNC,
+	PA29_PF_VSYNC,
+	PA30_PF_CONTRAST,
+	PA31_PF_OE_ACD,
+	/* OWIRE */
+	PE16_AF_OWIRE,
+	/* SDHC1*/
+	PE18_PF_SD1_D0,
+	PE19_PF_SD1_D1,
+	PE20_PF_SD1_D2,
+	PE21_PF_SD1_D3,
+	PE22_PF_SD1_CMD,
+	PE23_PF_SD1_CLK,
+	PF8_AF_ATA_IORDY,
+	/* SDHC2*/
+	PB4_PF_SD2_D0,
+	PB5_PF_SD2_D1,
+	PB6_PF_SD2_D2,
+	PB7_PF_SD2_D3,
+	PB8_PF_SD2_CMD,
+	PB9_PF_SD2_CLK,
+};
+
+static struct mxc_nand_platform_data mxt_td60_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+static struct imxi2c_platform_data mxt_td60_i2c_data = {
+	.bitrate = 100000,
+};
+
+/* PCA9557 */
+static int mxt_td60_pca9557_setup(struct i2c_client *client,
+				unsigned gpio_base, unsigned ngpio,
+				void *context)
+{
+	static int mxt_td60_gpio_value[] = {
+		-1, -1, -1, -1, -1, -1, -1, 1
+	};
+	int n;
+
+	for (n = 0; n < ARRAY_SIZE(mxt_td60_gpio_value); ++n) {
+		gpio_request(gpio_base + n, "MXT_TD60 GPIO Exp");
+		if (mxt_td60_gpio_value[n] < 0)
+			gpio_direction_input(gpio_base + n);
+		else
+			gpio_direction_output(gpio_base + n,
+						mxt_td60_gpio_value[n]);
+		gpio_export(gpio_base + n, 0);
+	}
+
+	return 0;
+}
+
+static struct pca953x_platform_data mxt_td60_pca9557_pdata = {
+	.gpio_base	= 240, /* place PCA9557 after all MX27 gpio pins */
+	.invert		= 0, /* Do not invert */
+	.setup		= mxt_td60_pca9557_setup,
+};
+
+static struct i2c_board_info mxt_td60_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("pca9557", 0x18),
+		.platform_data = &mxt_td60_pca9557_pdata,
+	},
+};
+
+static struct imxi2c_platform_data mxt_td60_i2c2_data = {
+	.bitrate = 100000,
+};
+
+static struct i2c_board_info mxt_td60_i2c2_devices[] = {
+};
+
+static struct imx_fb_videomode mxt_td60_modes[] = {
+	{
+		.mode = {
+			.name		= "Chimei LW700AT9003",
+			.refresh	= 60,
+			.xres		= 800,
+			.yres		= 480,
+			.pixclock	= 30303,
+			.hsync_len	= 64,
+			.left_margin	= 0x67,
+			.right_margin	= 0x68,
+			.vsync_len	= 16,
+			.upper_margin	= 0x0f,
+			.lower_margin	= 0x0f,
+		},
+		.bpp		= 16,
+		.pcr		= 0xFA208B83,
+	},
+};
+
+static struct imx_fb_platform_data mxt_td60_fb_data = {
+	.mode = mxt_td60_modes,
+	.num_modes = ARRAY_SIZE(mxt_td60_modes),
+
+	/*
+	 * - HSYNC active high
+	 * - VSYNC active high
+	 * - clk notenabled while idle
+	 * - clock inverted
+	 * - data not inverted
+	 * - data enable low active
+	 * - enable sharp mode
+	 */
+	.pwmr		= 0x00A903FF,
+	.lscr1		= 0x00120300,
+	.dmacr		= 0x00020010,
+};
+
+static int mxt_td60_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
+				void *data)
+{
+	return request_irq(IRQ_GPIOF(8), detect_irq, IRQF_TRIGGER_FALLING,
+				"sdhc1-card-detect", data);
+}
+
+static void mxt_td60_sdhc1_exit(struct device *dev, void *data)
+{
+	free_irq(IRQ_GPIOF(8), data);
+}
+
+static struct imxmmc_platform_data sdhc1_pdata = {
+	.init = mxt_td60_sdhc1_init,
+	.exit = mxt_td60_sdhc1_exit,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&mxc_fec_device,
+};
+
+static struct imxuart_platform_data uart_pdata[] = {
+	{
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	},
+};
+
+static void __init mxt_td60_board_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mxt_td60_pins, ARRAY_SIZE(mxt_td60_pins),
+			"MXT_TD60");
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
+	mxc_register_device(&mxc_uart_device1, &uart_pdata[1]);
+	mxc_register_device(&mxc_uart_device2, &uart_pdata[2]);
+	mxc_register_device(&imx27_nand_device, &mxt_td60_nand_board_info);
+
+	i2c_register_board_info(0, mxt_td60_i2c_devices,
+				ARRAY_SIZE(mxt_td60_i2c_devices));
+
+	i2c_register_board_info(1, mxt_td60_i2c2_devices,
+				ARRAY_SIZE(mxt_td60_i2c2_devices));
+
+	mxc_register_device(&mxc_i2c_device0, &mxt_td60_i2c_data);
+	mxc_register_device(&mxc_i2c_device1, &mxt_td60_i2c2_data);
+	mxc_register_device(&mxc_fb_device, &mxt_td60_fb_data);
+	mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
+
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init mxt_td60_timer_init(void)
+{
+	mx27_clocks_init(26000000);
+}
+
+static struct sys_timer mxt_td60_timer = {
+	.init	= mxt_td60_timer_init,
+};
+
+MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
+	/* maintainer: Maxtrack Industrial */
+	.phys_io	= MX27_AIPI_BASE_ADDR,
+	.io_pg_offst	= ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params	= MX27_PHYS_OFFSET + 0x100,
+	.map_io		= mx27_map_io,
+	.init_irq	= mx27_init_irq,
+	.init_machine	= mxt_td60_board_init,
+	.timer		= &mxt_td60_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-mx2/mach-pca100.c b/arch/arm/mach-mx2/mach-pca100.c
new file mode 100644
index 0000000..778fff2
--- /dev/null
+++ b/arch/arm/mach-mx2/mach-pca100.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * Copyright (C) 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/io.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#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>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx27.h>
+#include <mach/i2c.h>
+#include <asm/mach/time.h>
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+#include <mach/spi.h>
+#endif
+#include <mach/imx-uart.h>
+#include <mach/audmux.h>
+#include <mach/ssi.h>
+#include <mach/mxc_nand.h>
+#include <mach/irqs.h>
+#include <mach/mmc.h>
+#include <mach/mxc_ehci.h>
+#include <mach/ulpi.h>
+
+#include "devices.h"
+
+#define OTG_PHY_CS_GPIO (GPIO_PORTB + 23)
+#define USBH2_PHY_CS_GPIO (GPIO_PORTB + 24)
+
+static int pca100_pins[] = {
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* SDHC */
+	PB4_PF_SD2_D0,
+	PB5_PF_SD2_D1,
+	PB6_PF_SD2_D2,
+	PB7_PF_SD2_D3,
+	PB8_PF_SD2_CMD,
+	PB9_PF_SD2_CLK,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+	/* SSI1 */
+	PC20_PF_SSI1_FS,
+	PC21_PF_SSI1_RXD,
+	PC22_PF_SSI1_TXD,
+	PC23_PF_SSI1_CLK,
+	/* onboard I2C */
+	PC5_PF_I2C2_SDA,
+	PC6_PF_I2C2_SCL,
+	/* external I2C */
+	PD17_PF_I2C_DATA,
+	PD18_PF_I2C_CLK,
+	/* SPI1 */
+	PD25_PF_CSPI1_RDY,
+	PD29_PF_CSPI1_SCLK,
+	PD30_PF_CSPI1_MISO,
+	PD31_PF_CSPI1_MOSI,
+	/* OTG */
+	OTG_PHY_CS_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,
+	/* USBH2 */
+	USBH2_PHY_CS_GPIO | GPIO_GPIO | GPIO_OUT,
+	PA0_PF_USBH2_CLK,
+	PA1_PF_USBH2_DIR,
+	PA2_PF_USBH2_DATA7,
+	PA3_PF_USBH2_NXT,
+	PA4_PF_USBH2_STP,
+	PD19_AF_USBH2_DATA4,
+	PD20_AF_USBH2_DATA3,
+	PD21_AF_USBH2_DATA6,
+	PD22_AF_USBH2_DATA0,
+	PD23_AF_USBH2_DATA2,
+	PD24_AF_USBH2_DATA1,
+	PD26_AF_USBH2_DATA5,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct mxc_nand_platform_data pca100_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&mxc_w1_master_device,
+	&mxc_fec_device,
+};
+
+static struct imxi2c_platform_data pca100_i2c_1_data = {
+	.bitrate = 100000,
+};
+
+static struct at24_platform_data board_eeprom = {
+	.byte_len = 4096,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info pca100_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
+		.platform_data = &board_eeprom,
+	}, {
+		I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+		.type = "pcf8563"
+	}, {
+		I2C_BOARD_INFO("lm75", 0x4a),
+		.type = "lm75"
+	}
+};
+
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+static struct spi_eeprom at25320 = {
+	.name		= "at25320an",
+	.byte_len	= 4096,
+	.page_size	= 32,
+	.flags		= EE_ADDR2,
+};
+
+static struct spi_board_info pca100_spi_board_info[] __initdata = {
+	{
+		.modalias = "at25",
+		.max_speed_hz = 30000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.platform_data = &at25320,
+	},
+};
+
+static int pca100_spi_cs[] = {GPIO_PORTD + 28, GPIO_PORTD + 27};
+
+static struct spi_imx_master pca100_spi_0_data = {
+	.chipselect	= pca100_spi_cs,
+	.num_chipselect = ARRAY_SIZE(pca100_spi_cs),
+};
+#endif
+
+static void pca100_ac97_warm_reset(struct snd_ac97 *ac97)
+{
+	mxc_gpio_mode(GPIO_PORTC | 20 | GPIO_GPIO | GPIO_OUT);
+	gpio_set_value(GPIO_PORTC + 20, 1);
+	udelay(2);
+	gpio_set_value(GPIO_PORTC + 20, 0);
+	mxc_gpio_mode(PC20_PF_SSI1_FS);
+	msleep(2);
+}
+
+static void pca100_ac97_cold_reset(struct snd_ac97 *ac97)
+{
+	mxc_gpio_mode(GPIO_PORTC | 20 | GPIO_GPIO | GPIO_OUT);  /* FS */
+	gpio_set_value(GPIO_PORTC + 20, 0);
+	mxc_gpio_mode(GPIO_PORTC | 22 | GPIO_GPIO | GPIO_OUT);  /* TX */
+	gpio_set_value(GPIO_PORTC + 22, 0);
+	mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_OUT);  /* reset */
+	gpio_set_value(GPIO_PORTC + 28, 0);
+	udelay(10);
+	gpio_set_value(GPIO_PORTC + 28, 1);
+	mxc_gpio_mode(PC20_PF_SSI1_FS);
+	mxc_gpio_mode(PC22_PF_SSI1_TXD);
+	msleep(2);
+}
+
+static struct imx_ssi_platform_data pca100_ssi_pdata = {
+	.ac97_reset		= pca100_ac97_cold_reset,
+	.ac97_warm_reset	= pca100_ac97_warm_reset,
+	.flags			= IMX_SSI_USE_AC97,
+};
+
+static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
+		void *data)
+{
+	int ret;
+
+	ret = request_irq(IRQ_GPIOC(29), detect_irq,
+			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  "imx-mmc-detect", data);
+	if (ret)
+		printk(KERN_ERR
+			"pca100: Failed to reuest irq for sd/mmc detection\n");
+
+	return ret;
+}
+
+static void pca100_sdhc2_exit(struct device *dev, void *data)
+{
+	free_irq(IRQ_GPIOC(29), data);
+}
+
+static struct imxmmc_platform_data sdhc_pdata = {
+	.init = pca100_sdhc2_init,
+	.exit = pca100_sdhc2_exit,
+};
+
+static int otg_phy_init(struct platform_device *pdev)
+{
+	gpio_set_value(OTG_PHY_CS_GPIO, 0);
+	return 0;
+}
+
+static struct mxc_usbh_platform_data otg_pdata = {
+	.init	= otg_phy_init,
+	.portsc	= MXC_EHCI_MODE_ULPI,
+	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
+};
+
+static int usbh2_phy_init(struct platform_device *pdev)
+{
+	gpio_set_value(USBH2_PHY_CS_GPIO, 0);
+	return 0;
+}
+
+static struct mxc_usbh_platform_data usbh2_pdata = {
+	.init	= usbh2_phy_init,
+	.portsc	= MXC_EHCI_MODE_ULPI,
+	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
+};
+
+static struct fsl_usb2_platform_data otg_device_pdata = {
+	.operating_mode = FSL_USB2_DR_DEVICE,
+	.phy_mode       = FSL_USB2_PHY_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init pca100_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=", pca100_otg_mode);
+
+static void __init pca100_init(void)
+{
+	int ret;
+
+	/* SSI unit */
+	mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+				  MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */
+				  MXC_AUDMUX_V1_PCR_TFCSEL(3) |
+				  MXC_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */
+				  MXC_AUDMUX_V1_PCR_RXDSEL(3));
+	mxc_audmux_v1_configure_port(3,
+				  MXC_AUDMUX_V1_PCR_SYN | /* 4wire mode */
+				  MXC_AUDMUX_V1_PCR_TFCSEL(0) |
+				  MXC_AUDMUX_V1_PCR_TFSDIR |
+				  MXC_AUDMUX_V1_PCR_RXDSEL(0));
+
+	ret = mxc_gpio_setup_multiple_pins(pca100_pins,
+			ARRAY_SIZE(pca100_pins), "PCA100");
+	if (ret)
+		printk(KERN_ERR "pca100: Failed to setup pins (%d)\n", ret);
+
+	mxc_register_device(&imx_ssi_device0, &pca100_ssi_pdata);
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+
+	mxc_gpio_mode(GPIO_PORTC | 29 | GPIO_GPIO | GPIO_IN);
+	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
+
+	mxc_register_device(&imx27_nand_device, &pca100_nand_board_info);
+
+	/* only the i2c master 1 is used on this CPU card */
+	i2c_register_board_info(1, pca100_i2c_devices,
+				ARRAY_SIZE(pca100_i2c_devices));
+
+	mxc_register_device(&mxc_i2c_device1, &pca100_i2c_1_data);
+
+	mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT);
+	mxc_gpio_mode(GPIO_PORTD | 27 | GPIO_GPIO | GPIO_OUT);
+
+	/* GPIO0_IRQ */
+	mxc_gpio_mode(GPIO_PORTC | 31 | GPIO_GPIO | GPIO_IN);
+	/* GPIO1_IRQ */
+	mxc_gpio_mode(GPIO_PORTC | 25 | GPIO_GPIO | GPIO_IN);
+	/* GPIO2_IRQ */
+	mxc_gpio_mode(GPIO_PORTE | 5 | GPIO_GPIO | GPIO_IN);
+
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+	spi_register_board_info(pca100_spi_board_info,
+				ARRAY_SIZE(pca100_spi_board_info));
+	mxc_register_device(&mxc_spi_device0, &pca100_spi_0_data);
+#endif
+
+	gpio_request(OTG_PHY_CS_GPIO, "usb-otg-cs");
+	gpio_direction_output(OTG_PHY_CS_GPIO, 1);
+	gpio_request(USBH2_PHY_CS_GPIO, "usb-host2-cs");
+	gpio_direction_output(USBH2_PHY_CS_GPIO, 1);
+
+#if defined(CONFIG_USB_ULPI)
+	if (otg_mode_host) {
+		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+
+		mxc_register_device(&mxc_otg_host, &otg_pdata);
+	}
+
+	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+
+	mxc_register_device(&mxc_usbh2, &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);
+	}
+
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+}
+
+static void __init pca100_timer_init(void)
+{
+	mx27_clocks_init(26000000);
+}
+
+static struct sys_timer pca100_timer = {
+	.init = pca100_timer_init,
+};
+
+MACHINE_START(PCA100, "phyCARD-i.MX27")
+	.phys_io        = MX27_AIPI_BASE_ADDR,
+	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = MX27_PHYS_OFFSET + 0x100,
+	.map_io         = mx27_map_io,
+	.init_irq       = mx27_init_irq,
+	.init_machine   = pca100_init,
+	.timer          = &pca100_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-mx2/mach-pcm038.c b/arch/arm/mach-mx2/mach-pcm038.c
new file mode 100644
index 0000000..035fbe0
--- /dev/null
+++ b/arch/arm/mach-mx2/mach-pcm038.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ * 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/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/io.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/spi/spi.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/board-pcm038.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/i2c.h>
+#include <mach/iomux-mx27.h>
+#include <mach/imx-uart.h>
+#include <mach/mxc_nand.h>
+#include <mach/spi.h>
+#include <mach/mxc_ehci.h>
+#include <mach/ulpi.h>
+
+#include "devices.h"
+
+static int pcm038_pins[] = {
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	PE14_PF_UART1_CTS,
+	PE15_PF_UART1_RTS,
+	/* UART2 */
+	PE3_PF_UART2_CTS,
+	PE4_PF_UART2_RTS,
+	PE6_PF_UART2_TXD,
+	PE7_PF_UART2_RXD,
+	/* UART3 */
+	PE8_PF_UART3_TXD,
+	PE9_PF_UART3_RXD,
+	PE10_PF_UART3_CTS,
+	PE11_PF_UART3_RTS,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+	/* I2C2 */
+	PC5_PF_I2C2_SDA,
+	PC6_PF_I2C2_SCL,
+	/* SPI1 */
+	PD25_PF_CSPI1_RDY,
+	PD29_PF_CSPI1_SCLK,
+	PD30_PF_CSPI1_MISO,
+	PD31_PF_CSPI1_MOSI,
+	/* SSI1 */
+	PC20_PF_SSI1_FS,
+	PC21_PF_SSI1_RXD,
+	PC22_PF_SSI1_TXD,
+	PC23_PF_SSI1_CLK,
+	/* SSI4 */
+	PC16_PF_SSI4_FS,
+	PC17_PF_SSI4_RXD,
+	PC18_PF_SSI4_TXD,
+	PC19_PF_SSI4_CLK,
+	/* USB host */
+	PA0_PF_USBH2_CLK,
+	PA1_PF_USBH2_DIR,
+	PA2_PF_USBH2_DATA7,
+	PA3_PF_USBH2_NXT,
+	PA4_PF_USBH2_STP,
+	PD19_AF_USBH2_DATA4,
+	PD20_AF_USBH2_DATA3,
+	PD21_AF_USBH2_DATA6,
+	PD22_AF_USBH2_DATA0,
+	PD23_AF_USBH2_DATA2,
+	PD24_AF_USBH2_DATA1,
+	PD26_AF_USBH2_DATA5,
+};
+
+/*
+ * Phytec's PCM038 comes with 2MiB battery buffered SRAM,
+ * 16 bit width
+ */
+
+static struct platdata_mtd_ram pcm038_sram_data = {
+	.bankwidth = 2,
+};
+
+static struct resource pcm038_sram_resource = {
+	.start = MX27_CS1_BASE_ADDR,
+	.end   = MX27_CS1_BASE_ADDR + 512 * 1024 - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device pcm038_sram_mtd_device = {
+	.name = "mtd-ram",
+	.id = 0,
+	.dev = {
+		.platform_data = &pcm038_sram_data,
+	},
+	.num_resources = 1,
+	.resource = &pcm038_sram_resource,
+};
+
+/*
+ * Phytec's phyCORE-i.MX27 comes with 32MiB flash,
+ * 16 bit width
+ */
+static struct physmap_flash_data pcm038_flash_data = {
+	.width = 2,
+};
+
+static struct resource pcm038_flash_resource = {
+	.start = 0xc0000000,
+	.end   = 0xc1ffffff,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device pcm038_nor_mtd_device = {
+	.name = "physmap-flash",
+	.id = 0,
+	.dev = {
+		.platform_data = &pcm038_flash_data,
+	},
+	.num_resources = 1,
+	.resource = &pcm038_flash_resource,
+};
+
+static struct imxuart_platform_data uart_pdata[] = {
+	{
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.flags = IMXUART_HAVE_RTSCTS,
+	},
+};
+
+static struct mxc_nand_platform_data pcm038_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&pcm038_nor_mtd_device,
+	&mxc_w1_master_device,
+	&mxc_fec_device,
+	&pcm038_sram_mtd_device,
+};
+
+/* On pcm038 there's a sram attached to CS1, we enable the chipselect here and
+ * setup other stuffs to access the sram. */
+static void __init pcm038_init_sram(void)
+{
+	mx27_setup_weimcs(1, 0x0000d843, 0x22252521, 0x22220a00);
+}
+
+static struct imxi2c_platform_data pcm038_i2c_1_data = {
+	.bitrate = 100000,
+};
+
+static struct at24_platform_data board_eeprom = {
+	.byte_len = 4096,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info pcm038_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
+		.platform_data = &board_eeprom,
+	}, {
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	}, {
+		I2C_BOARD_INFO("lm75", 0x4a),
+	}
+};
+
+static int pcm038_spi_cs[] = {GPIO_PORTD + 28};
+
+static struct spi_imx_master pcm038_spi_0_data = {
+	.chipselect = pcm038_spi_cs,
+	.num_chipselect = ARRAY_SIZE(pcm038_spi_cs),
+};
+
+static struct regulator_consumer_supply sdhc1_consumers[] = {
+	{
+		.dev	= &mxc_sdhc_device1.dev,
+		.supply	= "sdhc_vcc",
+	},
+};
+
+static struct regulator_init_data sdhc1_data = {
+	.constraints = {
+		.min_uV = 3000000,
+		.max_uV = 3400000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+			REGULATOR_MODE_FAST,
+		.always_on = 0,
+		.boot_on = 0,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(sdhc1_consumers),
+	.consumer_supplies = sdhc1_consumers,
+};
+
+static struct regulator_consumer_supply cam_consumers[] = {
+	{
+		.dev	= NULL,
+		.supply	= "imx_cam_vcc",
+	},
+};
+
+static struct regulator_init_data cam_data = {
+	.constraints = {
+		.min_uV = 3000000,
+		.max_uV = 3400000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+			REGULATOR_MODE_FAST,
+		.always_on = 0,
+		.boot_on = 0,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(cam_consumers),
+	.consumer_supplies = cam_consumers,
+};
+
+struct mc13783_regulator_init_data pcm038_regulators[] = {
+	{
+		.id = MC13783_REGU_VCAM,
+		.init_data = &cam_data,
+	}, {
+		.id = MC13783_REGU_VMMC1,
+		.init_data = &sdhc1_data,
+	},
+};
+
+static struct mc13783_platform_data pcm038_pmic = {
+	.regulators = pcm038_regulators,
+	.num_regulators = ARRAY_SIZE(pcm038_regulators),
+	.flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
+		 MC13783_USE_TOUCHSCREEN,
+};
+
+static struct spi_board_info pcm038_spi_board_info[] __initdata = {
+	{
+		.modalias = "mc13783",
+		.irq = IRQ_GPIOB(23),
+		.max_speed_hz = 300000,
+		.bus_num = 0,
+		.chip_select = 0,
+		.platform_data = &pcm038_pmic,
+		.mode = SPI_CS_HIGH,
+	}
+};
+
+static struct mxc_usbh_platform_data usbh2_pdata = {
+	.portsc	= MXC_EHCI_MODE_ULPI,
+	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
+};
+
+static void __init pcm038_init(void)
+{
+	mxc_gpio_setup_multiple_pins(pcm038_pins, ARRAY_SIZE(pcm038_pins),
+			"PCM038");
+
+	pcm038_init_sram();
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
+	mxc_register_device(&mxc_uart_device1, &uart_pdata[1]);
+	mxc_register_device(&mxc_uart_device2, &uart_pdata[2]);
+
+	mxc_gpio_mode(PE16_AF_OWIRE);
+	mxc_register_device(&imx27_nand_device, &pcm038_nand_board_info);
+
+	/* only the i2c master 1 is used on this CPU card */
+	i2c_register_board_info(1, pcm038_i2c_devices,
+				ARRAY_SIZE(pcm038_i2c_devices));
+
+	mxc_register_device(&mxc_i2c_device1, &pcm038_i2c_1_data);
+
+	/* PE18 for user-LED D40 */
+	mxc_gpio_mode(GPIO_PORTE | 18 | GPIO_GPIO | GPIO_OUT);
+
+	mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT);
+
+	/* MC13783 IRQ */
+	mxc_gpio_mode(GPIO_PORTB | 23 | GPIO_GPIO | GPIO_IN);
+
+	mxc_register_device(&mxc_spi_device0, &pcm038_spi_0_data);
+	spi_register_board_info(pcm038_spi_board_info,
+				ARRAY_SIZE(pcm038_spi_board_info));
+
+	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+#ifdef CONFIG_MACH_PCM970_BASEBOARD
+	pcm970_baseboard_init();
+#endif
+}
+
+static void __init pcm038_timer_init(void)
+{
+	mx27_clocks_init(26000000);
+}
+
+static struct sys_timer pcm038_timer = {
+	.init = pcm038_timer_init,
+};
+
+MACHINE_START(PCM038, "phyCORE-i.MX27")
+	.phys_io        = MX27_AIPI_BASE_ADDR,
+	.io_pg_offst    = ((MX27_AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = MX27_PHYS_OFFSET + 0x100,
+	.map_io         = mx27_map_io,
+	.init_irq       = mx27_init_irq,
+	.init_machine   = pcm038_init,
+	.timer          = &pcm038_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx2/mm-imx21.c b/arch/arm/mach-mx2/mm-imx21.c
new file mode 100644
index 0000000..6413431
--- /dev/null
+++ b/arch/arm/mach-mx2/mm-imx21.c
@@ -0,0 +1,83 @@
+/*
+ * arch/arm/mach-mx2/mm-imx21.c
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <asm/pgtable.h>
+#include <asm/mach/map.h>
+
+/* MX21 memory map definition */
+static struct map_desc imx21_io_desc[] __initdata = {
+	/*
+	 * this fixed mapping covers:
+	 * - AIPI1
+	 * - AIPI2
+	 * - AITC
+	 * - 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
+	},
+	/*
+	 * 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
+	},
+	/*
+	 * 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
+	},
+};
+
+/*
+ * Initialize the memory map. It is called during the
+ * system startup to create static physical to virtual
+ * memory map for the IO modules.
+ */
+void __init mx21_map_io(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX21);
+	mxc_arch_reset_init(MX21_IO_ADDRESS(MX21_WDOG_BASE_ADDR));
+
+	iotable_init(imx21_io_desc, ARRAY_SIZE(imx21_io_desc));
+}
+
+void __init mx21_init_irq(void)
+{
+	mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR));
+}
diff --git a/arch/arm/mach-mx2/mm-imx27.c b/arch/arm/mach-mx2/mm-imx27.c
new file mode 100644
index 0000000..3366ed4
--- /dev/null
+++ b/arch/arm/mach-mx2/mm-imx27.c
@@ -0,0 +1,83 @@
+/*
+ * arch/arm/mach-mx2/mm-imx27.c
+ *
+ * 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/mm.h>
+#include <linux/init.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <asm/pgtable.h>
+#include <asm/mach/map.h>
+
+/* MX27 memory map definition */
+static struct map_desc imx27_io_desc[] __initdata = {
+	/*
+	 * this fixed mapping covers:
+	 * - AIPI1
+	 * - AIPI2
+	 * - AITC
+	 * - 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
+	},
+	/*
+	 * 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
+	},
+	/*
+	 * 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
+	},
+};
+
+/*
+ * Initialize the memory map. It is called during the
+ * system startup to create static physical to virtual
+ * memory map for the IO modules.
+ */
+void __init mx27_map_io(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX27);
+	mxc_arch_reset_init(MX27_IO_ADDRESS(MX27_WDOG_BASE_ADDR));
+
+	iotable_init(imx27_io_desc, ARRAY_SIZE(imx27_io_desc));
+}
+
+void __init mx27_init_irq(void)
+{
+	mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR));
+}
diff --git a/arch/arm/mach-mx2/mx21ads.c b/arch/arm/mach-mx2/mx21ads.c
deleted file mode 100644
index cf5f77c..0000000
--- a/arch/arm/mach-mx2/mx21ads.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2006-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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/physmap.h>
-#include <linux/gpio.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 <asm/mach/map.h>
-#include <mach/imx-uart.h>
-#include <mach/imxfb.h>
-#include <mach/iomux.h>
-#include <mach/mxc_nand.h>
-#include <mach/mmc.h>
-#include <mach/board-mx21ads.h>
-
-#include "devices.h"
-
-static unsigned int mx21ads_pins[] = {
-
-	/* CS8900A */
-	(GPIO_PORTE | GPIO_GPIO | GPIO_IN | 11),
-
-	/* UART1 */
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS,
-
-	/* UART3 (IrDA) - only TXD and RXD */
-	PE8_PF_UART3_TXD,
-	PE9_PF_UART3_RXD,
-
-	/* UART4 */
-	PB26_AF_UART4_RTS,
-	PB28_AF_UART4_TXD,
-	PB29_AF_UART4_CTS,
-	PB31_AF_UART4_RXD,
-
-	/* LCDC */
-	PA5_PF_LSCLK,
-	PA6_PF_LD0,
-	PA7_PF_LD1,
-	PA8_PF_LD2,
-	PA9_PF_LD3,
-	PA10_PF_LD4,
-	PA11_PF_LD5,
-	PA12_PF_LD6,
-	PA13_PF_LD7,
-	PA14_PF_LD8,
-	PA15_PF_LD9,
-	PA16_PF_LD10,
-	PA17_PF_LD11,
-	PA18_PF_LD12,
-	PA19_PF_LD13,
-	PA20_PF_LD14,
-	PA21_PF_LD15,
-	PA22_PF_LD16,
-	PA24_PF_REV,     /* Sharp panel dedicated signal */
-	PA25_PF_CLS,     /* Sharp panel dedicated signal */
-	PA26_PF_PS,      /* Sharp panel dedicated signal */
-	PA27_PF_SPL_SPR, /* Sharp panel dedicated signal */
-	PA28_PF_HSYNC,
-	PA29_PF_VSYNC,
-	PA30_PF_CONTRAST,
-	PA31_PF_OE_ACD,
-
-	/* MMC/SDHC */
-	PE18_PF_SD1_D0,
-	PE19_PF_SD1_D1,
-	PE20_PF_SD1_D2,
-	PE21_PF_SD1_D3,
-	PE22_PF_SD1_CMD,
-	PE23_PF_SD1_CLK,
-
-	/* NFC */
-	PF0_PF_NRFB,
-	PF1_PF_NFCE,
-	PF2_PF_NFWP,
-	PF3_PF_NFCLE,
-	PF4_PF_NFALE,
-	PF5_PF_NFRE,
-	PF6_PF_NFWE,
-	PF7_PF_NFIO0,
-	PF8_PF_NFIO1,
-	PF9_PF_NFIO2,
-	PF10_PF_NFIO3,
-	PF11_PF_NFIO4,
-	PF12_PF_NFIO5,
-	PF13_PF_NFIO6,
-	PF14_PF_NFIO7,
-};
-
-/* ADS's NOR flash: 2x AM29BDS128HE9VKI on 32-bit bus */
-static struct physmap_flash_data mx21ads_flash_data = {
-	.width = 4,
-};
-
-static struct resource mx21ads_flash_resource = {
-	.start = CS0_BASE_ADDR,
-	.end = CS0_BASE_ADDR + 0x02000000 - 1,
-	.flags = IORESOURCE_MEM,
-};
-
-static struct platform_device mx21ads_nor_mtd_device = {
-	.name = "physmap-flash",
-	.id = 0,
-	.dev = {
-		.platform_data = &mx21ads_flash_data,
-	},
-	.num_resources = 1,
-	.resource = &mx21ads_flash_resource,
-};
-
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct imxuart_platform_data uart_norts_pdata = {
-};
-
-
-static int mx21ads_fb_init(struct platform_device *pdev)
-{
-	u16 tmp;
-
-	tmp = __raw_readw(MX21ADS_IO_REG);
-	tmp |= MX21ADS_IO_LCDON;
-	__raw_writew(tmp, MX21ADS_IO_REG);
-	return 0;
-}
-
-static void mx21ads_fb_exit(struct platform_device *pdev)
-{
-	u16 tmp;
-
-	tmp = __raw_readw(MX21ADS_IO_REG);
-	tmp &= ~MX21ADS_IO_LCDON;
-	__raw_writew(tmp, MX21ADS_IO_REG);
-}
-
-/*
- * Connected is a portrait Sharp-QVGA display
- * of type: LQ035Q7DB02
- */
-static struct imx_fb_videomode mx21ads_modes[] = {
-	{
-		.mode = {
-			.name		= "Sharp-LQ035Q7",
-			.refresh	= 60,
-			.xres		= 240,
-			.yres		= 320,
-			.pixclock	= 188679, /* in ps (5.3MHz) */
-			.hsync_len	= 2,
-			.left_margin	= 6,
-			.right_margin	= 16,
-			.vsync_len	= 1,
-			.upper_margin	= 8,
-			.lower_margin	= 10,
-		},
-		.pcr		= 0xfb108bc7,
-		.bpp		= 16,
-	},
-};
-
-static struct imx_fb_platform_data mx21ads_fb_data = {
-	.mode = mx21ads_modes,
-	.num_modes = ARRAY_SIZE(mx21ads_modes),
-
-	.pwmr		= 0x00a903ff,
-	.lscr1		= 0x00120300,
-	.dmacr		= 0x00020008,
-
-	.init = mx21ads_fb_init,
-	.exit = mx21ads_fb_exit,
-};
-
-static int mx21ads_sdhc_get_ro(struct device *dev)
-{
-	return (__raw_readw(MX21ADS_IO_REG) & MX21ADS_IO_SD_WP) ? 1 : 0;
-}
-
-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,
-		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)
-{
-	free_irq(IRQ_GPIOD(25), data);
-}
-
-static struct imxmmc_platform_data mx21ads_sdhc_pdata = {
-	.ocr_avail = MMC_VDD_29_30 | MMC_VDD_30_31, /* 3.0V */
-	.get_ro = mx21ads_sdhc_get_ro,
-	.init = mx21ads_sdhc_init,
-	.exit = mx21ads_sdhc_exit,
-};
-
-static struct mxc_nand_platform_data mx21ads_nand_board_info = {
-	.width = 1,
-	.hw_ecc = 1,
-};
-
-static struct map_desc mx21ads_io_desc[] __initdata = {
-	/*
-	 * Memory-mapped I/O on MX21ADS Base board:
-	 *   - CS8900A Ethernet controller
-	 *   - ST16C2552CJ UART
-	 *   - CPU and Base board version
-	 *   - Base board I/O register
-	 */
-	{
-		.virtual = MX21ADS_MMIO_BASE_ADDR,
-		.pfn = __phys_to_pfn(CS1_BASE_ADDR),
-		.length = MX21ADS_MMIO_SIZE,
-		.type = MT_DEVICE,
-	},
-};
-
-static void __init mx21ads_map_io(void)
-{
-	mx21_map_io();
-	iotable_init(mx21ads_io_desc, ARRAY_SIZE(mx21ads_io_desc));
-}
-
-static struct platform_device *platform_devices[] __initdata = {
-	&mx21ads_nor_mtd_device,
-};
-
-static void __init mx21ads_board_init(void)
-{
-	mxc_gpio_setup_multiple_pins(mx21ads_pins, ARRAY_SIZE(mx21ads_pins),
-			"mx21ads");
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-	mxc_register_device(&mxc_uart_device2, &uart_norts_pdata);
-	mxc_register_device(&mxc_uart_device3, &uart_pdata);
-	mxc_register_device(&mxc_fb_device, &mx21ads_fb_data);
-	mxc_register_device(&mxc_sdhc_device0, &mx21ads_sdhc_pdata);
-	mxc_register_device(&mxc_nand_device, &mx21ads_nand_board_info);
-
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-}
-
-static void __init mx21ads_timer_init(void)
-{
-	mx21_clocks_init(32768, 26000000);
-}
-
-static struct sys_timer mx21ads_timer = {
-	.init	= mx21ads_timer_init,
-};
-
-MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
-	/* maintainer: Freescale Semiconductor, Inc. */
-	.phys_io        = AIPI_BASE_ADDR,
-	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx21ads_map_io,
-	.init_irq       = mx21_init_irq,
-	.init_machine   = mx21ads_board_init,
-	.timer          = &mx21ads_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c
deleted file mode 100644
index 83e412b..0000000
--- a/arch/arm/mach-mx2/mx27ads.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2006-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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/i2c.h>
-#include <linux/irq.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 <asm/mach/map.h>
-#include <mach/gpio.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux.h>
-#include <mach/board-mx27ads.h>
-#include <mach/mxc_nand.h>
-#include <mach/i2c.h>
-#include <mach/imxfb.h>
-#include <mach/mmc.h>
-
-#include "devices.h"
-
-static unsigned int mx27ads_pins[] = {
-	/* UART0 */
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS,
-	/* UART1 */
-	PE3_PF_UART2_CTS,
-	PE4_PF_UART2_RTS,
-	PE6_PF_UART2_TXD,
-	PE7_PF_UART2_RXD,
-	/* UART2 */
-	PE8_PF_UART3_TXD,
-	PE9_PF_UART3_RXD,
-	PE10_PF_UART3_CTS,
-	PE11_PF_UART3_RTS,
-	/* UART3 */
-	PB26_AF_UART4_RTS,
-	PB28_AF_UART4_TXD,
-	PB29_AF_UART4_CTS,
-	PB31_AF_UART4_RXD,
-	/* UART4 */
-	PB18_AF_UART5_TXD,
-	PB19_AF_UART5_RXD,
-	PB20_AF_UART5_CTS,
-	PB21_AF_UART5_RTS,
-	/* UART5 */
-	PB10_AF_UART6_TXD,
-	PB12_AF_UART6_CTS,
-	PB11_AF_UART6_RXD,
-	PB13_AF_UART6_RTS,
-	/* FEC */
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN,
-	/* I2C2 */
-	PC5_PF_I2C2_SDA,
-	PC6_PF_I2C2_SCL,
-	/* FB */
-	PA5_PF_LSCLK,
-	PA6_PF_LD0,
-	PA7_PF_LD1,
-	PA8_PF_LD2,
-	PA9_PF_LD3,
-	PA10_PF_LD4,
-	PA11_PF_LD5,
-	PA12_PF_LD6,
-	PA13_PF_LD7,
-	PA14_PF_LD8,
-	PA15_PF_LD9,
-	PA16_PF_LD10,
-	PA17_PF_LD11,
-	PA18_PF_LD12,
-	PA19_PF_LD13,
-	PA20_PF_LD14,
-	PA21_PF_LD15,
-	PA22_PF_LD16,
-	PA23_PF_LD17,
-	PA24_PF_REV,
-	PA25_PF_CLS,
-	PA26_PF_PS,
-	PA27_PF_SPL_SPR,
-	PA28_PF_HSYNC,
-	PA29_PF_VSYNC,
-	PA30_PF_CONTRAST,
-	PA31_PF_OE_ACD,
-	/* OWIRE */
-	PE16_AF_OWIRE,
-	/* SDHC1*/
-	PE18_PF_SD1_D0,
-	PE19_PF_SD1_D1,
-	PE20_PF_SD1_D2,
-	PE21_PF_SD1_D3,
-	PE22_PF_SD1_CMD,
-	PE23_PF_SD1_CLK,
-	/* SDHC2*/
-	PB4_PF_SD2_D0,
-	PB5_PF_SD2_D1,
-	PB6_PF_SD2_D2,
-	PB7_PF_SD2_D3,
-	PB8_PF_SD2_CMD,
-	PB9_PF_SD2_CLK,
-};
-
-static struct mxc_nand_platform_data mx27ads_nand_board_info = {
-	.width = 1,
-	.hw_ecc = 1,
-};
-
-/* ADS's NOR flash */
-static struct physmap_flash_data mx27ads_flash_data = {
-	.width = 2,
-};
-
-static struct resource mx27ads_flash_resource = {
-	.start = 0xc0000000,
-	.end = 0xc0000000 + 0x02000000 - 1,
-	.flags = IORESOURCE_MEM,
-
-};
-
-static struct platform_device mx27ads_nor_mtd_device = {
-	.name = "physmap-flash",
-	.id = 0,
-	.dev = {
-		.platform_data = &mx27ads_flash_data,
-	},
-	.num_resources = 1,
-	.resource = &mx27ads_flash_resource,
-};
-
-static struct imxi2c_platform_data mx27ads_i2c_data = {
-	.bitrate = 100000,
-};
-
-static struct i2c_board_info mx27ads_i2c_devices[] = {
-};
-
-void lcd_power(int on)
-{
-	if (on)
-		__raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_SET_REG);
-	else
-		__raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG);
-}
-
-static struct imx_fb_videomode mx27ads_modes[] = {
-	{
-		.mode = {
-			.name		= "Sharp-LQ035Q7",
-			.refresh	= 60,
-			.xres		= 240,
-			.yres		= 320,
-			.pixclock	= 188679, /* in ps (5.3MHz) */
-			.hsync_len	= 1,
-			.left_margin	= 9,
-			.right_margin	= 16,
-			.vsync_len	= 1,
-			.upper_margin	= 7,
-			.lower_margin	= 9,
-		},
-		.bpp		= 16,
-		.pcr		= 0xFB008BC0,
-	},
-};
-
-static struct imx_fb_platform_data mx27ads_fb_data = {
-	.mode = mx27ads_modes,
-	.num_modes = ARRAY_SIZE(mx27ads_modes),
-
-	/*
-	 * - HSYNC active high
-	 * - VSYNC active high
-	 * - clk notenabled while idle
-	 * - clock inverted
-	 * - data not inverted
-	 * - data enable low active
-	 * - enable sharp mode
-	 */
-	.pwmr		= 0x00A903FF,
-	.lscr1		= 0x00120300,
-	.dmacr		= 0x00020010,
-
-	.lcd_power	= lcd_power,
-};
-
-static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
-			      void *data)
-{
-	return request_irq(IRQ_GPIOE(21), detect_irq, IRQF_TRIGGER_RISING,
-			   "sdhc1-card-detect", data);
-}
-
-static int mx27ads_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
-			      void *data)
-{
-	return request_irq(IRQ_GPIOB(7), detect_irq, IRQF_TRIGGER_RISING,
-			   "sdhc2-card-detect", data);
-}
-
-static void mx27ads_sdhc1_exit(struct device *dev, void *data)
-{
-	free_irq(IRQ_GPIOE(21), data);
-}
-
-static void mx27ads_sdhc2_exit(struct device *dev, void *data)
-{
-	free_irq(IRQ_GPIOB(7), data);
-}
-
-static struct imxmmc_platform_data sdhc1_pdata = {
-	.init = mx27ads_sdhc1_init,
-	.exit = mx27ads_sdhc1_exit,
-};
-
-static struct imxmmc_platform_data sdhc2_pdata = {
-	.init = mx27ads_sdhc2_init,
-	.exit = mx27ads_sdhc2_exit,
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-	&mx27ads_nor_mtd_device,
-	&mxc_fec_device,
-	&mxc_w1_master_device,
-};
-
-static struct imxuart_platform_data uart_pdata[] = {
-	{
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	},
-};
-
-static void __init mx27ads_board_init(void)
-{
-	mxc_gpio_setup_multiple_pins(mx27ads_pins, ARRAY_SIZE(mx27ads_pins),
-			"mx27ads");
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
-	mxc_register_device(&mxc_uart_device1, &uart_pdata[1]);
-	mxc_register_device(&mxc_uart_device2, &uart_pdata[2]);
-	mxc_register_device(&mxc_uart_device3, &uart_pdata[3]);
-	mxc_register_device(&mxc_uart_device4, &uart_pdata[4]);
-	mxc_register_device(&mxc_uart_device5, &uart_pdata[5]);
-	mxc_register_device(&mxc_nand_device, &mx27ads_nand_board_info);
-
-	/* only the i2c master 1 is used on this CPU card */
-	i2c_register_board_info(1, mx27ads_i2c_devices,
-				ARRAY_SIZE(mx27ads_i2c_devices));
-	mxc_register_device(&mxc_i2c_device1, &mx27ads_i2c_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);
-
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-}
-
-static void __init mx27ads_timer_init(void)
-{
-	unsigned long fref = 26000000;
-
-	if ((__raw_readw(PBC_VERSION_REG) & CKIH_27MHZ_BIT_SET) == 0)
-		fref = 27000000;
-
-	mx27_clocks_init(fref);
-}
-
-static struct sys_timer mx27ads_timer = {
-	.init	= mx27ads_timer_init,
-};
-
-static struct map_desc mx27ads_io_desc[] __initdata = {
-	{
-		.virtual = PBC_BASE_ADDRESS,
-		.pfn = __phys_to_pfn(CS4_BASE_ADDR),
-		.length = SZ_1M,
-		.type = MT_DEVICE,
-	},
-};
-
-static void __init mx27ads_map_io(void)
-{
-	mx27_map_io();
-	iotable_init(mx27ads_io_desc, ARRAY_SIZE(mx27ads_io_desc));
-}
-
-MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
-	/* maintainer: Freescale Semiconductor, Inc. */
-	.phys_io        = AIPI_BASE_ADDR,
-	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx27ads_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = mx27ads_board_init,
-	.timer          = &mx27ads_timer,
-MACHINE_END
-
diff --git a/arch/arm/mach-mx2/mx27lite.c b/arch/arm/mach-mx2/mx27lite.c
deleted file mode 100644
index 82ea227..0000000
--- a/arch/arm/mach-mx2/mx27lite.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- * Copyright 2009 Daniel Schaeffer (daniel.schaeffer@timesys.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux.h>
-#include <mach/board-mx27lite.h>
-
-#include "devices.h"
-
-static unsigned int mx27lite_pins[] = {
-	/* UART1 */
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS,
-	/* FEC */
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN,
-};
-
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-	&mxc_fec_device,
-};
-
-static void __init mx27lite_init(void)
-{
-	mxc_gpio_setup_multiple_pins(mx27lite_pins, ARRAY_SIZE(mx27lite_pins),
-		"imx27lite");
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-}
-
-static void __init mx27lite_timer_init(void)
-{
-	mx27_clocks_init(26000000);
-}
-
-static struct sys_timer mx27lite_timer = {
-	.init	= mx27lite_timer_init,
-};
-
-MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
-	.phys_io        = AIPI_BASE_ADDR,
-	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = mx27lite_init,
-	.timer          = &mx27lite_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx2/mx27pdk.c b/arch/arm/mach-mx2/mx27pdk.c
deleted file mode 100644
index 6761d1b..0000000
--- a/arch/arm/mach-mx2/mx27pdk.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Author: Fabio Estevam <fabio.estevam@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux.h>
-#include <mach/board-mx27pdk.h>
-
-#include "devices.h"
-
-static unsigned int mx27pdk_pins[] = {
-	/* UART1 */
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS,
-	/* FEC */
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN,
-};
-
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-	&mxc_fec_device,
-};
-
-static void __init mx27pdk_init(void)
-{
-	mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins),
-		"mx27pdk");
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-}
-
-static void __init mx27pdk_timer_init(void)
-{
-	mx27_clocks_init(26000000);
-}
-
-static struct sys_timer mx27pdk_timer = {
-	.init	= mx27pdk_timer_init,
-};
-
-MACHINE_START(MX27_3DS, "Freescale MX27PDK")
-	/* maintainer: Freescale Semiconductor, Inc. */
-	.phys_io        = AIPI_BASE_ADDR,
-	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = mx27pdk_init,
-	.timer          = &mx27pdk_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx2/mxt_td60.c b/arch/arm/mach-mx2/mxt_td60.c
deleted file mode 100644
index 8bcc1a5..0000000
--- a/arch/arm/mach-mx2/mxt_td60.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2006-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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/i2c.h>
-#include <linux/irq.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 <asm/mach/map.h>
-#include <linux/gpio.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux.h>
-#include <mach/mxc_nand.h>
-#include <mach/i2c.h>
-#include <linux/i2c/pca953x.h>
-#include <mach/imxfb.h>
-#include <mach/mmc.h>
-
-#include "devices.h"
-
-static unsigned int mxt_td60_pins[] __initdata = {
-	/* UART0 */
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS,
-	/* UART1 */
-	PE3_PF_UART2_CTS,
-	PE4_PF_UART2_RTS,
-	PE6_PF_UART2_TXD,
-	PE7_PF_UART2_RXD,
-	/* UART2 */
-	PE8_PF_UART3_TXD,
-	PE9_PF_UART3_RXD,
-	PE10_PF_UART3_CTS,
-	PE11_PF_UART3_RTS,
-	/* FEC */
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN,
-	/* I2C1 */
-	PD17_PF_I2C_DATA,
-	PD18_PF_I2C_CLK,
-	/* I2C2 */
-	PC5_PF_I2C2_SDA,
-	PC6_PF_I2C2_SCL,
-	/* FB */
-	PA5_PF_LSCLK,
-	PA6_PF_LD0,
-	PA7_PF_LD1,
-	PA8_PF_LD2,
-	PA9_PF_LD3,
-	PA10_PF_LD4,
-	PA11_PF_LD5,
-	PA12_PF_LD6,
-	PA13_PF_LD7,
-	PA14_PF_LD8,
-	PA15_PF_LD9,
-	PA16_PF_LD10,
-	PA17_PF_LD11,
-	PA18_PF_LD12,
-	PA19_PF_LD13,
-	PA20_PF_LD14,
-	PA21_PF_LD15,
-	PA22_PF_LD16,
-	PA23_PF_LD17,
-	PA25_PF_CLS,
-	PA27_PF_SPL_SPR,
-	PA28_PF_HSYNC,
-	PA29_PF_VSYNC,
-	PA30_PF_CONTRAST,
-	PA31_PF_OE_ACD,
-	/* OWIRE */
-	PE16_AF_OWIRE,
-	/* SDHC1*/
-	PE18_PF_SD1_D0,
-	PE19_PF_SD1_D1,
-	PE20_PF_SD1_D2,
-	PE21_PF_SD1_D3,
-	PE22_PF_SD1_CMD,
-	PE23_PF_SD1_CLK,
-	PF8_AF_ATA_IORDY,
-	/* SDHC2*/
-	PB4_PF_SD2_D0,
-	PB5_PF_SD2_D1,
-	PB6_PF_SD2_D2,
-	PB7_PF_SD2_D3,
-	PB8_PF_SD2_CMD,
-	PB9_PF_SD2_CLK,
-};
-
-static struct mxc_nand_platform_data mxt_td60_nand_board_info = {
-	.width = 1,
-	.hw_ecc = 1,
-};
-
-static struct imxi2c_platform_data mxt_td60_i2c_data = {
-	.bitrate = 100000,
-};
-
-/* PCA9557 */
-static int mxt_td60_pca9557_setup(struct i2c_client *client,
-				unsigned gpio_base, unsigned ngpio,
-				void *context)
-{
-	static int mxt_td60_gpio_value[] = {
-		-1, -1, -1, -1, -1, -1, -1, 1
-	};
-	int n;
-
-	for (n = 0; n < ARRAY_SIZE(mxt_td60_gpio_value); ++n) {
-		gpio_request(gpio_base + n, "MXT_TD60 GPIO Exp");
-		if (mxt_td60_gpio_value[n] < 0)
-			gpio_direction_input(gpio_base + n);
-		else
-			gpio_direction_output(gpio_base + n,
-						mxt_td60_gpio_value[n]);
-		gpio_export(gpio_base + n, 0);
-	}
-
-	return 0;
-}
-
-static struct pca953x_platform_data mxt_td60_pca9557_pdata = {
-	.gpio_base	= 240, /* place PCA9557 after all MX27 gpio pins */
-	.invert		= 0, /* Do not invert */
-	.setup		= mxt_td60_pca9557_setup,
-};
-
-static struct i2c_board_info mxt_td60_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("pca9557", 0x18),
-		.platform_data = &mxt_td60_pca9557_pdata,
-	},
-};
-
-static struct imxi2c_platform_data mxt_td60_i2c2_data = {
-	.bitrate = 100000,
-};
-
-static struct i2c_board_info mxt_td60_i2c2_devices[] = {
-};
-
-static struct imx_fb_videomode mxt_td60_modes[] = {
-	{
-		.mode = {
-			.name		= "Chimei LW700AT9003",
-			.refresh	= 60,
-			.xres		= 800,
-			.yres		= 480,
-			.pixclock	= 30303,
-			.hsync_len	= 64,
-			.left_margin	= 0x67,
-			.right_margin	= 0x68,
-			.vsync_len	= 16,
-			.upper_margin	= 0x0f,
-			.lower_margin	= 0x0f,
-		},
-		.bpp		= 16,
-		.pcr		= 0xFA208B83,
-	},
-};
-
-static struct imx_fb_platform_data mxt_td60_fb_data = {
-	.mode = mxt_td60_modes,
-	.num_modes = ARRAY_SIZE(mxt_td60_modes),
-
-	/*
-	 * - HSYNC active high
-	 * - VSYNC active high
-	 * - clk notenabled while idle
-	 * - clock inverted
-	 * - data not inverted
-	 * - data enable low active
-	 * - enable sharp mode
-	 */
-	.pwmr		= 0x00A903FF,
-	.lscr1		= 0x00120300,
-	.dmacr		= 0x00020010,
-};
-
-static int mxt_td60_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
-				void *data)
-{
-	return request_irq(IRQ_GPIOF(8), detect_irq, IRQF_TRIGGER_FALLING,
-				"sdhc1-card-detect", data);
-}
-
-static void mxt_td60_sdhc1_exit(struct device *dev, void *data)
-{
-	free_irq(IRQ_GPIOF(8), data);
-}
-
-static struct imxmmc_platform_data sdhc1_pdata = {
-	.init = mxt_td60_sdhc1_init,
-	.exit = mxt_td60_sdhc1_exit,
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-	&mxc_fec_device,
-};
-
-static struct imxuart_platform_data uart_pdata[] = {
-	{
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	},
-};
-
-static void __init mxt_td60_board_init(void)
-{
-	mxc_gpio_setup_multiple_pins(mxt_td60_pins, ARRAY_SIZE(mxt_td60_pins),
-			"MXT_TD60");
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
-	mxc_register_device(&mxc_uart_device1, &uart_pdata[1]);
-	mxc_register_device(&mxc_uart_device2, &uart_pdata[2]);
-	mxc_register_device(&mxc_nand_device, &mxt_td60_nand_board_info);
-
-	i2c_register_board_info(0, mxt_td60_i2c_devices,
-				ARRAY_SIZE(mxt_td60_i2c_devices));
-
-	i2c_register_board_info(1, mxt_td60_i2c2_devices,
-				ARRAY_SIZE(mxt_td60_i2c2_devices));
-
-	mxc_register_device(&mxc_i2c_device0, &mxt_td60_i2c_data);
-	mxc_register_device(&mxc_i2c_device1, &mxt_td60_i2c2_data);
-	mxc_register_device(&mxc_fb_device, &mxt_td60_fb_data);
-	mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata);
-
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-}
-
-static void __init mxt_td60_timer_init(void)
-{
-	mx27_clocks_init(26000000);
-}
-
-static struct sys_timer mxt_td60_timer = {
-	.init	= mxt_td60_timer_init,
-};
-
-MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
-	/* maintainer: Maxtrack Industrial */
-	.phys_io	= AIPI_BASE_ADDR,
-	.io_pg_offst	= ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params	= PHYS_OFFSET + 0x100,
-	.map_io		= mx27_map_io,
-	.init_irq	= mx27_init_irq,
-	.init_machine	= mxt_td60_board_init,
-	.timer		= &mxt_td60_timer,
-MACHINE_END
-
diff --git a/arch/arm/mach-mx2/pca100.c b/arch/arm/mach-mx2/pca100.c
deleted file mode 100644
index aea3d34..0000000
--- a/arch/arm/mach-mx2/pca100.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
- * Copyright (C) 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/io.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
-#include <linux/dma-mapping.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/eeprom.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux.h>
-#include <mach/i2c.h>
-#include <asm/mach/time.h>
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
-#include <mach/spi.h>
-#endif
-#include <mach/imx-uart.h>
-#include <mach/mxc_nand.h>
-#include <mach/irqs.h>
-#include <mach/mmc.h>
-
-#include "devices.h"
-
-static int pca100_pins[] = {
-	/* UART1 */
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS,
-	/* SDHC */
-	PB4_PF_SD2_D0,
-	PB5_PF_SD2_D1,
-	PB6_PF_SD2_D2,
-	PB7_PF_SD2_D3,
-	PB8_PF_SD2_CMD,
-	PB9_PF_SD2_CLK,
-	/* FEC */
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN,
-	/* SSI1 */
-	PC20_PF_SSI1_FS,
-	PC21_PF_SSI1_RXD,
-	PC22_PF_SSI1_TXD,
-	PC23_PF_SSI1_CLK,
-	/* onboard I2C */
-	PC5_PF_I2C2_SDA,
-	PC6_PF_I2C2_SCL,
-	/* external I2C */
-	PD17_PF_I2C_DATA,
-	PD18_PF_I2C_CLK,
-	/* SPI1 */
-	PD25_PF_CSPI1_RDY,
-	PD29_PF_CSPI1_SCLK,
-	PD30_PF_CSPI1_MISO,
-	PD31_PF_CSPI1_MOSI,
-};
-
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct mxc_nand_platform_data pca100_nand_board_info = {
-	.width = 1,
-	.hw_ecc = 1,
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-	&mxc_w1_master_device,
-	&mxc_fec_device,
-};
-
-static struct imxi2c_platform_data pca100_i2c_1_data = {
-	.bitrate = 100000,
-};
-
-static struct at24_platform_data board_eeprom = {
-	.byte_len = 4096,
-	.page_size = 32,
-	.flags = AT24_FLAG_ADDR16,
-};
-
-static struct i2c_board_info pca100_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
-		.platform_data = &board_eeprom,
-	}, {
-		I2C_BOARD_INFO("rtc-pcf8563", 0x51),
-		.type = "pcf8563"
-	}, {
-		I2C_BOARD_INFO("lm75", 0x4a),
-		.type = "lm75"
-	}
-};
-
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
-static struct spi_eeprom at25320 = {
-	.name		= "at25320an",
-	.byte_len	= 4096,
-	.page_size	= 32,
-	.flags		= EE_ADDR2,
-};
-
-static struct spi_board_info pca100_spi_board_info[] __initdata = {
-	{
-		.modalias = "at25",
-		.max_speed_hz = 30000,
-		.bus_num = 0,
-		.chip_select = 1,
-		.platform_data = &at25320,
-	},
-};
-
-static int pca100_spi_cs[] = {GPIO_PORTD + 28, GPIO_PORTD + 27};
-
-static struct spi_imx_master pca100_spi_0_data = {
-	.chipselect	= pca100_spi_cs,
-	.num_chipselect = ARRAY_SIZE(pca100_spi_cs),
-};
-#endif
-
-static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
-		void *data)
-{
-	int ret;
-
-	ret = request_irq(IRQ_GPIOC(29), detect_irq,
-			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
-			  "imx-mmc-detect", data);
-	if (ret)
-		printk(KERN_ERR
-			"pca100: Failed to reuest irq for sd/mmc detection\n");
-
-	return ret;
-}
-
-static void pca100_sdhc2_exit(struct device *dev, void *data)
-{
-	free_irq(IRQ_GPIOC(29), data);
-}
-
-static struct imxmmc_platform_data sdhc_pdata = {
-	.init = pca100_sdhc2_init,
-	.exit = pca100_sdhc2_exit,
-};
-
-static void __init pca100_init(void)
-{
-	int ret;
-
-	ret = mxc_gpio_setup_multiple_pins(pca100_pins,
-			ARRAY_SIZE(pca100_pins), "PCA100");
-	if (ret)
-		printk(KERN_ERR "pca100: Failed to setup pins (%d)\n", ret);
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-
-	mxc_gpio_mode(GPIO_PORTC | 29 | GPIO_GPIO | GPIO_IN);
-	mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata);
-
-	mxc_register_device(&mxc_nand_device, &pca100_nand_board_info);
-
-	/* only the i2c master 1 is used on this CPU card */
-	i2c_register_board_info(1, pca100_i2c_devices,
-				ARRAY_SIZE(pca100_i2c_devices));
-
-	mxc_register_device(&mxc_i2c_device1, &pca100_i2c_1_data);
-
-	mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT);
-	mxc_gpio_mode(GPIO_PORTD | 27 | GPIO_GPIO | GPIO_OUT);
-
-	/* GPIO0_IRQ */
-	mxc_gpio_mode(GPIO_PORTC | 31 | GPIO_GPIO | GPIO_IN);
-	/* GPIO1_IRQ */
-	mxc_gpio_mode(GPIO_PORTC | 25 | GPIO_GPIO | GPIO_IN);
-	/* GPIO2_IRQ */
-	mxc_gpio_mode(GPIO_PORTE | 5 | GPIO_GPIO | GPIO_IN);
-
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
-	spi_register_board_info(pca100_spi_board_info,
-				ARRAY_SIZE(pca100_spi_board_info));
-	mxc_register_device(&mxc_spi_device0, &pca100_spi_0_data);
-#endif
-
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-}
-
-static void __init pca100_timer_init(void)
-{
-	mx27_clocks_init(26000000);
-}
-
-static struct sys_timer pca100_timer = {
-	.init = pca100_timer_init,
-};
-
-MACHINE_START(PCA100, "phyCARD-i.MX27")
-	.phys_io        = AIPI_BASE_ADDR,
-	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = pca100_init,
-	.timer          = &pca100_timer,
-MACHINE_END
-
diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c
deleted file mode 100644
index 906d59b..0000000
--- a/arch/arm/mach-mx2/pcm038.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
- * 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/i2c.h>
-#include <linux/i2c/at24.h>
-#include <linux/io.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/mtd/physmap.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/machine.h>
-#include <linux/mfd/mc13783.h>
-#include <linux/spi/spi.h>
-#include <linux/irq.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/board-pcm038.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/i2c.h>
-#include <mach/iomux.h>
-#include <mach/imx-uart.h>
-#include <mach/mxc_nand.h>
-#include <mach/spi.h>
-
-#include "devices.h"
-
-static int pcm038_pins[] = {
-	/* UART1 */
-	PE12_PF_UART1_TXD,
-	PE13_PF_UART1_RXD,
-	PE14_PF_UART1_CTS,
-	PE15_PF_UART1_RTS,
-	/* UART2 */
-	PE3_PF_UART2_CTS,
-	PE4_PF_UART2_RTS,
-	PE6_PF_UART2_TXD,
-	PE7_PF_UART2_RXD,
-	/* UART3 */
-	PE8_PF_UART3_TXD,
-	PE9_PF_UART3_RXD,
-	PE10_PF_UART3_CTS,
-	PE11_PF_UART3_RTS,
-	/* FEC */
-	PD0_AIN_FEC_TXD0,
-	PD1_AIN_FEC_TXD1,
-	PD2_AIN_FEC_TXD2,
-	PD3_AIN_FEC_TXD3,
-	PD4_AOUT_FEC_RX_ER,
-	PD5_AOUT_FEC_RXD1,
-	PD6_AOUT_FEC_RXD2,
-	PD7_AOUT_FEC_RXD3,
-	PD8_AF_FEC_MDIO,
-	PD9_AIN_FEC_MDC,
-	PD10_AOUT_FEC_CRS,
-	PD11_AOUT_FEC_TX_CLK,
-	PD12_AOUT_FEC_RXD0,
-	PD13_AOUT_FEC_RX_DV,
-	PD14_AOUT_FEC_RX_CLK,
-	PD15_AOUT_FEC_COL,
-	PD16_AIN_FEC_TX_ER,
-	PF23_AIN_FEC_TX_EN,
-	/* I2C2 */
-	PC5_PF_I2C2_SDA,
-	PC6_PF_I2C2_SCL,
-	/* SPI1 */
-	PD25_PF_CSPI1_RDY,
-	PD29_PF_CSPI1_SCLK,
-	PD30_PF_CSPI1_MISO,
-	PD31_PF_CSPI1_MOSI,
-	/* SSI1 */
-	PC20_PF_SSI1_FS,
-	PC21_PF_SSI1_RXD,
-	PC22_PF_SSI1_TXD,
-	PC23_PF_SSI1_CLK,
-	/* SSI4 */
-	PC16_PF_SSI4_FS,
-	PC17_PF_SSI4_RXD,
-	PC18_PF_SSI4_TXD,
-	PC19_PF_SSI4_CLK,
-};
-
-/*
- * Phytec's PCM038 comes with 2MiB battery buffered SRAM,
- * 16 bit width
- */
-
-static struct platdata_mtd_ram pcm038_sram_data = {
-	.bankwidth = 2,
-};
-
-static struct resource pcm038_sram_resource = {
-	.start = CS1_BASE_ADDR,
-	.end   = CS1_BASE_ADDR + 512 * 1024 - 1,
-	.flags = IORESOURCE_MEM,
-};
-
-static struct platform_device pcm038_sram_mtd_device = {
-	.name = "mtd-ram",
-	.id = 0,
-	.dev = {
-		.platform_data = &pcm038_sram_data,
-	},
-	.num_resources = 1,
-	.resource = &pcm038_sram_resource,
-};
-
-/*
- * Phytec's phyCORE-i.MX27 comes with 32MiB flash,
- * 16 bit width
- */
-static struct physmap_flash_data pcm038_flash_data = {
-	.width = 2,
-};
-
-static struct resource pcm038_flash_resource = {
-	.start = 0xc0000000,
-	.end   = 0xc1ffffff,
-	.flags = IORESOURCE_MEM,
-};
-
-static struct platform_device pcm038_nor_mtd_device = {
-	.name = "physmap-flash",
-	.id = 0,
-	.dev = {
-		.platform_data = &pcm038_flash_data,
-	},
-	.num_resources = 1,
-	.resource = &pcm038_flash_resource,
-};
-
-static struct imxuart_platform_data uart_pdata[] = {
-	{
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	}, {
-		.flags = IMXUART_HAVE_RTSCTS,
-	},
-};
-
-static struct mxc_nand_platform_data pcm038_nand_board_info = {
-	.width = 1,
-	.hw_ecc = 1,
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-	&pcm038_nor_mtd_device,
-	&mxc_w1_master_device,
-	&mxc_fec_device,
-	&pcm038_sram_mtd_device,
-};
-
-/* On pcm038 there's a sram attached to CS1, we enable the chipselect here and
- * setup other stuffs to access the sram. */
-static void __init pcm038_init_sram(void)
-{
-	__raw_writel(0x0000d843, CSCR_U(1));
-	__raw_writel(0x22252521, CSCR_L(1));
-	__raw_writel(0x22220a00, CSCR_A(1));
-}
-
-static struct imxi2c_platform_data pcm038_i2c_1_data = {
-	.bitrate = 100000,
-};
-
-static struct at24_platform_data board_eeprom = {
-	.byte_len = 4096,
-	.page_size = 32,
-	.flags = AT24_FLAG_ADDR16,
-};
-
-static struct i2c_board_info pcm038_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
-		.platform_data = &board_eeprom,
-	}, {
-		I2C_BOARD_INFO("pcf8563", 0x51),
-	}, {
-		I2C_BOARD_INFO("lm75", 0x4a),
-	}
-};
-
-static int pcm038_spi_cs[] = {GPIO_PORTD + 28};
-
-static struct spi_imx_master pcm038_spi_0_data = {
-	.chipselect = pcm038_spi_cs,
-	.num_chipselect = ARRAY_SIZE(pcm038_spi_cs),
-};
-
-static struct regulator_consumer_supply sdhc1_consumers[] = {
-	{
-		.dev	= &mxc_sdhc_device1.dev,
-		.supply	= "sdhc_vcc",
-	},
-};
-
-static struct regulator_init_data sdhc1_data = {
-	.constraints = {
-		.min_uV = 3000000,
-		.max_uV = 3400000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL |
-			REGULATOR_MODE_FAST,
-		.always_on = 0,
-		.boot_on = 0,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(sdhc1_consumers),
-	.consumer_supplies = sdhc1_consumers,
-};
-
-static struct regulator_consumer_supply cam_consumers[] = {
-	{
-		.dev	= NULL,
-		.supply	= "imx_cam_vcc",
-	},
-};
-
-static struct regulator_init_data cam_data = {
-	.constraints = {
-		.min_uV = 3000000,
-		.max_uV = 3400000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL |
-			REGULATOR_MODE_FAST,
-		.always_on = 0,
-		.boot_on = 0,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(cam_consumers),
-	.consumer_supplies = cam_consumers,
-};
-
-struct mc13783_regulator_init_data pcm038_regulators[] = {
-	{
-		.id = MC13783_REGU_VCAM,
-		.init_data = &cam_data,
-	}, {
-		.id = MC13783_REGU_VMMC1,
-		.init_data = &sdhc1_data,
-	},
-};
-
-static struct mc13783_platform_data pcm038_pmic = {
-	.regulators = pcm038_regulators,
-	.num_regulators = ARRAY_SIZE(pcm038_regulators),
-	.flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
-		 MC13783_USE_TOUCHSCREEN,
-};
-
-static struct spi_board_info pcm038_spi_board_info[] __initdata = {
-	{
-		.modalias = "mc13783",
-		.irq = IRQ_GPIOB(23),
-		.max_speed_hz = 300000,
-		.bus_num = 0,
-		.chip_select = 0,
-		.platform_data = &pcm038_pmic,
-		.mode = SPI_CS_HIGH,
-	}
-};
-
-static void __init pcm038_init(void)
-{
-	mxc_gpio_setup_multiple_pins(pcm038_pins, ARRAY_SIZE(pcm038_pins),
-			"PCM038");
-
-	pcm038_init_sram();
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata[0]);
-	mxc_register_device(&mxc_uart_device1, &uart_pdata[1]);
-	mxc_register_device(&mxc_uart_device2, &uart_pdata[2]);
-
-	mxc_gpio_mode(PE16_AF_OWIRE);
-	mxc_register_device(&mxc_nand_device, &pcm038_nand_board_info);
-
-	/* only the i2c master 1 is used on this CPU card */
-	i2c_register_board_info(1, pcm038_i2c_devices,
-				ARRAY_SIZE(pcm038_i2c_devices));
-
-	mxc_register_device(&mxc_i2c_device1, &pcm038_i2c_1_data);
-
-	/* PE18 for user-LED D40 */
-	mxc_gpio_mode(GPIO_PORTE | 18 | GPIO_GPIO | GPIO_OUT);
-
-	mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT);
-
-	/* MC13783 IRQ */
-	mxc_gpio_mode(GPIO_PORTB | 23 | GPIO_GPIO | GPIO_IN);
-
-	mxc_register_device(&mxc_spi_device0, &pcm038_spi_0_data);
-	spi_register_board_info(pcm038_spi_board_info,
-				ARRAY_SIZE(pcm038_spi_board_info));
-
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-
-#ifdef CONFIG_MACH_PCM970_BASEBOARD
-	pcm970_baseboard_init();
-#endif
-}
-
-static void __init pcm038_timer_init(void)
-{
-	mx27_clocks_init(26000000);
-}
-
-static struct sys_timer pcm038_timer = {
-	.init = pcm038_timer_init,
-};
-
-MACHINE_START(PCM038, "phyCORE-i.MX27")
-	.phys_io        = AIPI_BASE_ADDR,
-	.io_pg_offst    = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = pcm038_init,
-	.timer          = &pcm038_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx2/pcm970-baseboard.c b/arch/arm/mach-mx2/pcm970-baseboard.c
index 3cb7f45..4aafd5b 100644
--- a/arch/arm/mach-mx2/pcm970-baseboard.c
+++ b/arch/arm/mach-mx2/pcm970-baseboard.c
@@ -24,7 +24,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/common.h>
-#include <mach/iomux.h>
+#include <mach/iomux-mx27.h>
 #include <mach/imxfb.h>
 #include <mach/hardware.h>
 #include <mach/mmc.h>
@@ -190,8 +190,8 @@
 
 static struct resource pcm970_sja1000_resources[] = {
 	{
-		.start   = CS4_BASE_ADDR,
-		.end     = CS4_BASE_ADDR + 0x100 - 1,
+		.start   = MX27_CS4_BASE_ADDR,
+		.end     = MX27_CS4_BASE_ADDR + 0x100 - 1,
 		.flags   = IORESOURCE_MEM,
 	}, {
 		.start   = IRQ_GPIOE(19),
diff --git a/arch/arm/mach-mx2/serial.c b/arch/arm/mach-mx2/serial.c
index 40a485c..1c0c835 100644
--- a/arch/arm/mach-mx2/serial.c
+++ b/arch/arm/mach-mx2/serial.c
@@ -26,12 +26,12 @@
 
 static struct resource uart0[] = {
 	{
-		.start = UART1_BASE_ADDR,
-		.end = UART1_BASE_ADDR + 0x0B5,
+		.start = MX2x_UART1_BASE_ADDR,
+		.end = MX2x_UART1_BASE_ADDR + 0x0B5,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = MXC_INT_UART1,
-		.end = MXC_INT_UART1,
+		.start = MX2x_INT_UART1,
+		.end = MX2x_INT_UART1,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -45,12 +45,12 @@
 
 static struct resource uart1[] = {
 	{
-		.start = UART2_BASE_ADDR,
-		.end = UART2_BASE_ADDR + 0x0B5,
+		.start = MX2x_UART2_BASE_ADDR,
+		.end = MX2x_UART2_BASE_ADDR + 0x0B5,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = MXC_INT_UART2,
-		.end = MXC_INT_UART2,
+		.start = MX2x_INT_UART2,
+		.end = MX2x_INT_UART2,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -64,12 +64,12 @@
 
 static struct resource uart2[] = {
 	{
-		.start = UART3_BASE_ADDR,
-		.end = UART3_BASE_ADDR + 0x0B5,
+		.start = MX2x_UART3_BASE_ADDR,
+		.end = MX2x_UART3_BASE_ADDR + 0x0B5,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = MXC_INT_UART3,
-		.end = MXC_INT_UART3,
+		.start = MX2x_INT_UART3,
+		.end = MX2x_INT_UART3,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -83,12 +83,12 @@
 
 static struct resource uart3[] = {
 	{
-		.start = UART4_BASE_ADDR,
-		.end = UART4_BASE_ADDR + 0x0B5,
+		.start = MX2x_UART4_BASE_ADDR,
+		.end = MX2x_UART4_BASE_ADDR + 0x0B5,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = MXC_INT_UART4,
-		.end = MXC_INT_UART4,
+		.start = MX2x_INT_UART4,
+		.end = MX2x_INT_UART4,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -103,12 +103,12 @@
 #ifdef CONFIG_MACH_MX27
 static struct resource uart4[] = {
 	{
-		.start = UART5_BASE_ADDR,
-		.end = UART5_BASE_ADDR + 0x0B5,
+		.start = MX27_UART5_BASE_ADDR,
+		.end = MX27_UART5_BASE_ADDR + 0x0B5,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = MXC_INT_UART5,
-		.end = MXC_INT_UART5,
+		.start = MX27_INT_UART5,
+		.end = MX27_INT_UART5,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -122,12 +122,12 @@
 
 static struct resource uart5[] = {
 	{
-		.start = UART6_BASE_ADDR,
-		.end = UART6_BASE_ADDR + 0x0B5,
+		.start = MX27_UART6_BASE_ADDR,
+		.end = MX27_UART6_BASE_ADDR + 0x0B5,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = MXC_INT_UART6,
-		.end = MXC_INT_UART6,
+		.start = MX27_INT_UART6,
+		.end = MX27_INT_UART6,
 		.flags = IORESOURCE_IRQ,
 	},
 };
diff --git a/arch/arm/mach-mx25/Kconfig b/arch/arm/mach-mx25/Kconfig
index cc28f56..54d2173 100644
--- a/arch/arm/mach-mx25/Kconfig
+++ b/arch/arm/mach-mx25/Kconfig
@@ -3,7 +3,6 @@
 comment "MX25 platforms:"
 
 config MACH_MX25_3DS
-	select ARCH_MXC_IOMUX_V3
 	bool "Support MX25PDK (3DS) Platform"
 
 endif
diff --git a/arch/arm/mach-mx25/Makefile b/arch/arm/mach-mx25/Makefile
index fe23836..10cebc5 100644
--- a/arch/arm/mach-mx25/Makefile
+++ b/arch/arm/mach-mx25/Makefile
@@ -1,3 +1,3 @@
 obj-y				:= mm.o devices.o
 obj-$(CONFIG_ARCH_MX25)		+= clock.o
-obj-$(CONFIG_MACH_MX25_3DS)	+= mx25pdk.o
+obj-$(CONFIG_MACH_MX25_3DS)	+= mach-mx25pdk.o
diff --git a/arch/arm/mach-mx25/clock.c b/arch/arm/mach-mx25/clock.c
index 37e1359..1550149 100644
--- a/arch/arm/mach-mx25/clock.c
+++ b/arch/arm/mach-mx25/clock.c
@@ -124,6 +124,11 @@
 	return get_rate_per(5);
 }
 
+static unsigned long get_rate_lcdc(struct clk *clk)
+{
+	return get_rate_per(7);
+}
+
 static unsigned long get_rate_otg(struct clk *clk)
 {
 	return 48000000; /* FIXME */
@@ -167,6 +172,8 @@
 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(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(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);
@@ -182,6 +189,8 @@
 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 _REGISTER_CLOCK(d, n, c)	\
 	{				\
@@ -214,6 +223,8 @@
 	_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)
 };
 
 int __init mx25_clocks_init(void)
@@ -228,6 +239,9 @@
 	__raw_writel((0xf << 16) | (3 << 26), CRM_BASE + CCM_CGCR1);
 	__raw_writel((1 << 5), CRM_BASE + CCM_CGCR2);
 
+	/* Clock source for lcdc is upll */
+	__raw_writel(__raw_readl(CRM_BASE+0x64) | (1 << 7), 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.c b/arch/arm/mach-mx25/devices.c
index 9fdeea1..3f4b8a0 100644
--- a/arch/arm/mach-mx25/devices.c
+++ b/arch/arm/mach-mx25/devices.c
@@ -438,3 +438,65 @@
 	.num_resources	= ARRAY_SIZE(mx25_fec_resources),
 	.resource	= mx25_fec_resources,
 };
+
+static struct resource mxc_nand_resources[] = {
+	{
+		.start	= MX25_NFC_BASE_ADDR,
+		.end	= MX25_NFC_BASE_ADDR + 0x1fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MX25_INT_NANDFC,
+		.end	= MX25_INT_NANDFC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_nand_device = {
+	.name		= "mxc_nand",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(mxc_nand_resources),
+	.resource	= mxc_nand_resources,
+};
+
+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,
+	},
+};
diff --git a/arch/arm/mach-mx25/devices.h b/arch/arm/mach-mx25/devices.h
index fe5420f..39560e1 100644
--- a/arch/arm/mach-mx25/devices.h
+++ b/arch/arm/mach-mx25/devices.h
@@ -18,3 +18,6 @@
 extern struct platform_device mxc_i2c_device1;
 extern struct platform_device mxc_i2c_device2;
 extern struct platform_device mx25_fec_device;
+extern struct platform_device mxc_nand_device;
+extern struct platform_device mx25_rtc_device;
+extern struct platform_device mx25_fb_device;
diff --git a/arch/arm/mach-mx25/mach-mx25pdk.c b/arch/arm/mach-mx25/mach-mx25pdk.c
new file mode 100644
index 0000000..83d7410
--- /dev/null
+++ b/arch/arm/mach-mx25/mach-mx25pdk.c
@@ -0,0 +1,174 @@
+/*
+ * 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/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/fec.h>
+#include <linux/platform_device.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/imx-uart.h>
+#include <mach/mx25.h>
+#include <mach/mxc_nand.h>
+#include <mach/imxfb.h>
+#include "devices.h"
+#include <mach/iomux-mx25.h>
+
+static struct imxuart_platform_data uart_pdata = {
+	.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,
+};
+
+static struct fec_platform_data mx25_fec_pdata = {
+        .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 struct mxc_nand_platform_data mx25pdk_nand_board_info = {
+	.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 void __init mx25pdk_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
+			ARRAY_SIZE(mx25pdk_pads));
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	mxc_register_device(&mxc_usbh2, NULL);
+	mxc_register_device(&mxc_nand_device, &mx25pdk_nand_board_info);
+	mxc_register_device(&mx25_rtc_device, NULL);
+	mxc_register_device(&mx25_fb_device, &mx25pdk_fb_pdata);
+
+	mx25pdk_fec_reset();
+	mxc_register_device(&mx25_fec_device, &mx25_fec_pdata);
+}
+
+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. */
+	.phys_io	= MX25_AIPS1_BASE_ADDR,
+	.io_pg_offst	= ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.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/mx25pdk.c b/arch/arm/mach-mx25/mx25pdk.c
deleted file mode 100644
index 6f06089..0000000
--- a/arch/arm/mach-mx25/mx25pdk.c
+++ /dev/null
@@ -1,111 +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/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/fec.h>
-#include <linux/platform_device.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/imx-uart.h>
-#include <mach/mx25.h>
-#include <mach/mxc_nand.h>
-#include "devices.h"
-#include <mach/iomux.h>
-
-static struct imxuart_platform_data uart_pdata = {
-	.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 */
-};
-
-static struct fec_platform_data mx25_fec_pdata = {
-        .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 void __init mx25pdk_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
-			ARRAY_SIZE(mx25pdk_pads));
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-	mxc_register_device(&mxc_usbh2, NULL);
-
-	mx25pdk_fec_reset();
-	mxc_register_device(&mx25_fec_device, &mx25_fec_pdata);
-}
-
-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. */
-	.phys_io	= MX25_AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = 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-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index 2829441..3872af1 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -34,6 +34,7 @@
 config MACH_PCM037
 	bool "Support Phytec pcm037 (i.MX31) platforms"
 	select ARCH_MX31
+	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for Phytec pcm037 platform. This includes
 	  specific configurations for the board and its peripherals.
@@ -86,6 +87,7 @@
 config MACH_PCM043
 	bool "Support Phytec pcm043 (i.MX35) platforms"
 	select ARCH_MX35
+	select MXC_ULPI if USB_ULPI
 	help
 	  Include support for Phytec pcm043 platform. This includes
 	  specific configurations for the board and its peripherals.
diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile
index 93c7b29..5d650fd 100644
--- a/arch/arm/mach-mx3/Makefile
+++ b/arch/arm/mach-mx3/Makefile
@@ -5,18 +5,22 @@
 # Object file lists.
 
 obj-y				:= mm.o devices.o cpu.o
-obj-$(CONFIG_ARCH_MX31)		+= clock.o iomux.o
+CFLAGS_mm.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
+CFLAGS_devices.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
+CFLAGS_cpu.o = -DIMX_NEEDS_DEPRECATED_SYMBOLS
+obj-$(CONFIG_ARCH_MX31)		+= clock-imx31.o iomux-imx31.o
 obj-$(CONFIG_ARCH_MX35)		+= clock-imx35.o
-obj-$(CONFIG_MACH_MX31ADS)	+= mx31ads.o
-obj-$(CONFIG_MACH_MX31LILLY)	+= mx31lilly.o mx31lilly-db.o
-obj-$(CONFIG_MACH_MX31LITE)	+= mx31lite.o mx31lite-db.o
-obj-$(CONFIG_MACH_PCM037)	+= pcm037.o
-obj-$(CONFIG_MACH_PCM037_EET)	+= pcm037_eet.o
-obj-$(CONFIG_MACH_MX31_3DS)	+= mx31pdk.o
-obj-$(CONFIG_MACH_MX31MOBOARD)	+= mx31moboard.o mx31moboard-devboard.o \
-				   mx31moboard-marxbot.o
-obj-$(CONFIG_MACH_QONG)		+= qong.o
-obj-$(CONFIG_MACH_PCM043)	+= pcm043.o
-obj-$(CONFIG_MACH_ARMADILLO5X0) += armadillo5x0.o
-obj-$(CONFIG_MACH_MX35_3DS)	+= mx35pdk.o
-obj-$(CONFIG_MACH_KZM_ARM11_01)	+= kzmarm11.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
+obj-$(CONFIG_MACH_PCM043)	+= mach-pcm043.o
+obj-$(CONFIG_MACH_ARMADILLO5X0) += mach-armadillo5x0.o
+obj-$(CONFIG_MACH_MX35_3DS)	+= mach-mx35pdk.o
+obj-$(CONFIG_MACH_KZM_ARM11_01)	+= mach-kzm_arm11_01.o
diff --git a/arch/arm/mach-mx3/armadillo5x0.c b/arch/arm/mach-mx3/armadillo5x0.c
deleted file mode 100644
index 54aab40..0000000
--- a/arch/arm/mach-mx3/armadillo5x0.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * armadillo5x0.c
- *
- * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
- * updates in http://alberdroid.blogspot.com/
- *
- * Based on Atmark Techno, Inc. armadillo 500 BSP 2008
- * Based on mx31ads.c and pcm037.c Great Work!
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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/clk.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/smsc911x.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mtd/physmap.h>
-#include <linux/io.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
-#include <linux/i2c.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/imx-uart.h>
-#include <mach/iomux-mx3.h>
-#include <mach/board-armadillo5x0.h>
-#include <mach/mmc.h>
-#include <mach/ipu.h>
-#include <mach/mx3fb.h>
-#include <mach/mxc_nand.h>
-
-#include "devices.h"
-#include "crm_regs.h"
-
-static int armadillo5x0_pins[] = {
-	/* UART1 */
-	MX31_PIN_CTS1__CTS1,
-	MX31_PIN_RTS1__RTS1,
-	MX31_PIN_TXD1__TXD1,
-	MX31_PIN_RXD1__RXD1,
-	/* UART2 */
-	MX31_PIN_CTS2__CTS2,
-	MX31_PIN_RTS2__RTS2,
-	MX31_PIN_TXD2__TXD2,
-	MX31_PIN_RXD2__RXD2,
-	/* LAN9118_IRQ */
-	IOMUX_MODE(MX31_PIN_GPIO1_0, IOMUX_CONFIG_GPIO),
-	/* SDHC1 */
-	MX31_PIN_SD1_DATA3__SD1_DATA3,
-	MX31_PIN_SD1_DATA2__SD1_DATA2,
-	MX31_PIN_SD1_DATA1__SD1_DATA1,
-	MX31_PIN_SD1_DATA0__SD1_DATA0,
-	MX31_PIN_SD1_CLK__SD1_CLK,
-	MX31_PIN_SD1_CMD__SD1_CMD,
-	/* Framebuffer */
-	MX31_PIN_LD0__LD0,
-	MX31_PIN_LD1__LD1,
-	MX31_PIN_LD2__LD2,
-	MX31_PIN_LD3__LD3,
-	MX31_PIN_LD4__LD4,
-	MX31_PIN_LD5__LD5,
-	MX31_PIN_LD6__LD6,
-	MX31_PIN_LD7__LD7,
-	MX31_PIN_LD8__LD8,
-	MX31_PIN_LD9__LD9,
-	MX31_PIN_LD10__LD10,
-	MX31_PIN_LD11__LD11,
-	MX31_PIN_LD12__LD12,
-	MX31_PIN_LD13__LD13,
-	MX31_PIN_LD14__LD14,
-	MX31_PIN_LD15__LD15,
-	MX31_PIN_LD16__LD16,
-	MX31_PIN_LD17__LD17,
-	MX31_PIN_VSYNC3__VSYNC3,
-	MX31_PIN_HSYNC__HSYNC,
-	MX31_PIN_FPSHIFT__FPSHIFT,
-	MX31_PIN_DRDY0__DRDY0,
-	IOMUX_MODE(MX31_PIN_LCS1, IOMUX_CONFIG_GPIO), /*ADV7125_PSAVE*/
-	/* I2C2 */
-	MX31_PIN_CSPI2_MOSI__SCL,
-	MX31_PIN_CSPI2_MISO__SDA,
-};
-
-/* RTC over I2C*/
-#define ARMADILLO5X0_RTC_GPIO	IOMUX_TO_GPIO(MX31_PIN_SRXD4)
-
-static struct i2c_board_info armadillo5x0_i2c_rtc = {
-	I2C_BOARD_INFO("s35390a", 0x30),
-};
-
-/* GPIO BUTTONS */
-static struct gpio_keys_button armadillo5x0_buttons[] = {
-	{
-		.code		= KEY_ENTER, /*28*/
-		.gpio		= IOMUX_TO_GPIO(MX31_PIN_SCLK0),
-		.active_low	= 1,
-		.desc		= "menu",
-		.wakeup		= 1,
-	}, {
-		.code		= KEY_BACK, /*158*/
-		.gpio		= IOMUX_TO_GPIO(MX31_PIN_SRST0),
-		.active_low	= 1,
-		.desc		= "back",
-		.wakeup		= 1,
-	}
-};
-
-static struct gpio_keys_platform_data armadillo5x0_button_data = {
-	.buttons	= armadillo5x0_buttons,
-	.nbuttons	= ARRAY_SIZE(armadillo5x0_buttons),
-};
-
-static struct platform_device armadillo5x0_button_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &armadillo5x0_button_data,
-	}
-};
-
-/*
- * NAND Flash
- */
-static struct mxc_nand_platform_data armadillo5x0_nand_flash_pdata = {
-	.width		= 1,
-	.hw_ecc		= 1,
-};
-
-/*
- * MTD NOR Flash
- */
-static struct mtd_partition armadillo5x0_nor_flash_partitions[] = {
-	{
-		.name		= "nor.bootloader",
-		.offset		= 0x00000000,
-		.size		= 4*32*1024,
-	}, {
-		.name		= "nor.kernel",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 16*128*1024,
-	}, {
-		.name		= "nor.userland",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 110*128*1024,
-	}, {
-		.name		= "nor.config",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 1*128*1024,
-	},
-};
-
-static struct physmap_flash_data armadillo5x0_nor_flash_pdata = {
-	.width		= 2,
-	.parts		= armadillo5x0_nor_flash_partitions,
-	.nr_parts	= ARRAY_SIZE(armadillo5x0_nor_flash_partitions),
-};
-
-static struct resource armadillo5x0_nor_flash_resource = {
-	.flags		= IORESOURCE_MEM,
-	.start		= CS0_BASE_ADDR,
-	.end		= CS0_BASE_ADDR + SZ_64M - 1,
-};
-
-static struct platform_device armadillo5x0_nor_flash = {
-	.name			= "physmap-flash",
-	.id			= -1,
-	.num_resources		= 1,
-	.resource		= &armadillo5x0_nor_flash_resource,
-};
-
-/*
- * FB support
- */
-static const struct fb_videomode fb_modedb[] = {
-	{	/* 640x480 @ 60 Hz */
-		.name		= "CRT-VGA",
-		.refresh	= 60,
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= 39721,
-		.left_margin	= 35,
-		.right_margin	= 115,
-		.upper_margin	= 43,
-		.lower_margin	= 1,
-		.hsync_len	= 10,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_OE_ACT_HIGH,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	}, {/* 800x600 @ 56 Hz */
-		.name		= "CRT-SVGA",
-		.refresh	= 56,
-		.xres		= 800,
-		.yres		= 600,
-		.pixclock	= 30000,
-		.left_margin	= 30,
-		.right_margin	= 108,
-		.upper_margin	= 13,
-		.lower_margin	= 10,
-		.hsync_len	= 10,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_OE_ACT_HIGH | FB_SYNC_HOR_HIGH_ACT |
-				  FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	},
-};
-
-static struct ipu_platform_data mx3_ipu_data = {
-	.irq_base = MXC_IPU_IRQ_START,
-};
-
-static struct mx3fb_platform_data mx3fb_pdata = {
-	.dma_dev	= &mx3_ipu.dev,
-	.name		= "CRT-VGA",
-	.mode		= fb_modedb,
-	.num_modes	= ARRAY_SIZE(fb_modedb),
-};
-
-/*
- * SDHC 1
- * MMC support
- */
-static int armadillo5x0_sdhc1_get_ro(struct device *dev)
-{
-	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B));
-}
-
-static int armadillo5x0_sdhc1_init(struct device *dev,
-				   irq_handler_t detect_irq, void *data)
-{
-	int ret;
-	int gpio_det, gpio_wp;
-
-	gpio_det = IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK);
-	gpio_wp = IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B);
-
-	ret = gpio_request(gpio_det, "sdhc-card-detect");
-	if (ret)
-		return ret;
-
-	gpio_direction_input(gpio_det);
-
-	ret = gpio_request(gpio_wp, "sdhc-write-protect");
-	if (ret)
-		goto err_gpio_free;
-
-	gpio_direction_input(gpio_wp);
-
-	/* When supported the trigger type have to be BOTH */
-	ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), detect_irq,
-			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
-			  "sdhc-detect", data);
-
-	if (ret)
-		goto err_gpio_free_2;
-
-	return 0;
-
-err_gpio_free_2:
-	gpio_free(gpio_wp);
-
-err_gpio_free:
-	gpio_free(gpio_det);
-
-	return ret;
-
-}
-
-static void armadillo5x0_sdhc1_exit(struct device *dev, void *data)
-{
-	free_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), data);
-	gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK));
-	gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B));
-}
-
-static struct imxmmc_platform_data sdhc_pdata = {
-	.get_ro = armadillo5x0_sdhc1_get_ro,
-	.init = armadillo5x0_sdhc1_init,
-	.exit = armadillo5x0_sdhc1_exit,
-};
-
-/*
- * SMSC 9118
- * Network support
- */
-static struct resource armadillo5x0_smc911x_resources[] = {
-	{
-		.start	= CS3_BASE_ADDR,
-		.end	= CS3_BASE_ADDR + SZ_32M - 1,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
-		.end	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
-		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},
-};
-
-static struct smsc911x_platform_config smsc911x_info = {
-	.flags		= SMSC911X_USE_16BIT,
-	.irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
-};
-
-static struct platform_device armadillo5x0_smc911x_device = {
-	.name           = "smsc911x",
-	.id             = -1,
-	.num_resources  = ARRAY_SIZE(armadillo5x0_smc911x_resources),
-	.resource       = armadillo5x0_smc911x_resources,
-	.dev            = {
-		.platform_data = &smsc911x_info,
-	},
-};
-
-/* UART device data */
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct platform_device *devices[] __initdata = {
-	&armadillo5x0_smc911x_device,
-	&mxc_i2c_device1,
-	&armadillo5x0_button_device,
-};
-
-/*
- * Perform board specific initializations
- */
-static void __init armadillo5x0_init(void)
-{
-	mxc_iomux_setup_multiple_pins(armadillo5x0_pins,
-			ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0");
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-
-	/* Register UART */
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-	mxc_register_device(&mxc_uart_device1, &uart_pdata);
-
-	/* SMSC9118 IRQ pin */
-	gpio_direction_input(MX31_PIN_GPIO1_0);
-
-	/* Register SDHC */
-	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
-
-	/* Register FB */
-	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
-	mxc_register_device(&mx3_fb, &mx3fb_pdata);
-
-	/* Register NOR Flash */
-	mxc_register_device(&armadillo5x0_nor_flash,
-			    &armadillo5x0_nor_flash_pdata);
-
-	/* Register NAND Flash */
-	mxc_register_device(&mxc_nand_device, &armadillo5x0_nand_flash_pdata);
-
-	/* set NAND page size to 2k if not configured via boot mode pins */
-	__raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR);
-
-	/* RTC */
-	/* Get RTC IRQ and register the chip */
-	if (gpio_request(ARMADILLO5X0_RTC_GPIO, "rtc") == 0) {
-		if (gpio_direction_input(ARMADILLO5X0_RTC_GPIO) == 0)
-			armadillo5x0_i2c_rtc.irq = gpio_to_irq(ARMADILLO5X0_RTC_GPIO);
-		else
-			gpio_free(ARMADILLO5X0_RTC_GPIO);
-	}
-	if (armadillo5x0_i2c_rtc.irq == 0)
-		pr_warning("armadillo5x0_init: failed to get RTC IRQ\n");
-	i2c_register_board_info(1, &armadillo5x0_i2c_rtc, 1);
-}
-
-static void __init armadillo5x0_timer_init(void)
-{
-	mx31_clocks_init(26000000);
-}
-
-static struct sys_timer armadillo5x0_timer = {
-	.init	= armadillo5x0_timer_init,
-};
-
-MACHINE_START(ARMADILLO5X0, "Armadillo-500")
-	/* Maintainer: Alberto Panizzo  */
-	.phys_io	= AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params	= PHYS_OFFSET + 0x00000100,
-	.map_io		= mx31_map_io,
-	.init_irq	= mx31_init_irq,
-	.timer		= &armadillo5x0_timer,
-	.init_machine	= armadillo5x0_init,
-MACHINE_END
diff --git a/arch/arm/mach-mx3/clock-imx31.c b/arch/arm/mach-mx3/clock-imx31.c
new file mode 100644
index 0000000..80dba99
--- /dev/null
+++ b/arch/arm/mach-mx3/clock-imx31.c
@@ -0,0 +1,631 @@
+/*
+ * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by 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/module.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <asm/clkdev.h>
+#include <asm/div64.h>
+
+#include <mach/clock.h>
+#include <mach/hardware.h>
+#include <mach/mx31.h>
+#include <mach/common.h>
+
+#include "crm_regs.h"
+
+#define PRE_DIV_MIN_FREQ    10000000 /* Minimum Frequency after Predivider */
+
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
+{
+	u32 min_pre, temp_pre, old_err, err;
+
+	if (div >= 512) {
+		*pre = 8;
+		*post = 64;
+	} else if (div >= 64) {
+		min_pre = (div - 1) / 64 + 1;
+		old_err = 8;
+		for (temp_pre = 8; 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 + *pre - 1) / *pre;
+	} else if (div <= 8) {
+		*pre = div;
+		*post = 1;
+	} else {
+		*pre = 1;
+		*post = div;
+	}
+}
+
+static struct clk mcu_pll_clk;
+static struct clk serial_pll_clk;
+static struct clk ipg_clk;
+static struct clk ckih_clk;
+
+static int cgr_enable(struct clk *clk)
+{
+	u32 reg;
+
+	if (!clk->enable_reg)
+		return 0;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg |= 3 << clk->enable_shift;
+	__raw_writel(reg, clk->enable_reg);
+
+	return 0;
+}
+
+static void cgr_disable(struct clk *clk)
+{
+	u32 reg;
+
+	if (!clk->enable_reg)
+		return;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg &= ~(3 << clk->enable_shift);
+
+	/* special case for EMI clock */
+	if (clk->enable_reg == MXC_CCM_CGR2 && clk->enable_shift == 8)
+		reg |= (1 << clk->enable_shift);
+
+	__raw_writel(reg, clk->enable_reg);
+}
+
+static unsigned long pll_ref_get_rate(void)
+{
+	unsigned long ccmr;
+	unsigned int prcs;
+
+	ccmr = __raw_readl(MXC_CCM_CCMR);
+	prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
+	if (prcs == 0x1)
+		return CKIL_CLK_FREQ * 1024;
+	else
+		return clk_get_rate(&ckih_clk);
+}
+
+static unsigned long usb_pll_get_rate(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(MXC_CCM_UPCTL);
+
+	return mxc_decode_pll(reg, pll_ref_get_rate());
+}
+
+static unsigned long serial_pll_get_rate(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(MXC_CCM_SRPCTL);
+
+	return mxc_decode_pll(reg, pll_ref_get_rate());
+}
+
+static unsigned long mcu_pll_get_rate(struct clk *clk)
+{
+	unsigned long reg, ccmr;
+
+	ccmr = __raw_readl(MXC_CCM_CCMR);
+
+	if (!(ccmr & MXC_CCM_CCMR_MPE) || (ccmr & MXC_CCM_CCMR_MDS))
+		return clk_get_rate(&ckih_clk);
+
+	reg = __raw_readl(MXC_CCM_MPCTL);
+
+	return mxc_decode_pll(reg, pll_ref_get_rate());
+}
+
+static int usb_pll_enable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CCMR);
+	reg |= MXC_CCM_CCMR_UPE;
+	__raw_writel(reg, MXC_CCM_CCMR);
+
+	/* No lock bit on MX31, so using max time from spec */
+	udelay(80);
+
+	return 0;
+}
+
+static void usb_pll_disable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CCMR);
+	reg &= ~MXC_CCM_CCMR_UPE;
+	__raw_writel(reg, MXC_CCM_CCMR);
+}
+
+static int serial_pll_enable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CCMR);
+	reg |= MXC_CCM_CCMR_SPE;
+	__raw_writel(reg, MXC_CCM_CCMR);
+
+	/* No lock bit on MX31, so using max time from spec */
+	udelay(80);
+
+	return 0;
+}
+
+static void serial_pll_disable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CCMR);
+	reg &= ~MXC_CCM_CCMR_SPE;
+	__raw_writel(reg, MXC_CCM_CCMR);
+}
+
+#define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off)
+#define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
+#define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
+
+static unsigned long mcu_main_get_rate(struct clk *clk)
+{
+	u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
+
+	if ((pmcr0 & MXC_CCM_PMCR0_DFSUP1) == MXC_CCM_PMCR0_DFSUP1_SPLL)
+		return clk_get_rate(&serial_pll_clk);
+	else
+		return clk_get_rate(&mcu_pll_clk);
+}
+
+static unsigned long ahb_get_rate(struct clk *clk)
+{
+	unsigned long max_pdf;
+
+	max_pdf = PDR0(MXC_CCM_PDR0_MAX_PODF_MASK,
+		       MXC_CCM_PDR0_MAX_PODF_OFFSET);
+	return clk_get_rate(clk->parent) / (max_pdf + 1);
+}
+
+static unsigned long ipg_get_rate(struct clk *clk)
+{
+	unsigned long ipg_pdf;
+
+	ipg_pdf = PDR0(MXC_CCM_PDR0_IPG_PODF_MASK,
+		       MXC_CCM_PDR0_IPG_PODF_OFFSET);
+	return clk_get_rate(clk->parent) / (ipg_pdf + 1);
+}
+
+static unsigned long nfc_get_rate(struct clk *clk)
+{
+	unsigned long nfc_pdf;
+
+	nfc_pdf = PDR0(MXC_CCM_PDR0_NFC_PODF_MASK,
+		       MXC_CCM_PDR0_NFC_PODF_OFFSET);
+	return clk_get_rate(clk->parent) / (nfc_pdf + 1);
+}
+
+static unsigned long hsp_get_rate(struct clk *clk)
+{
+	unsigned long hsp_pdf;
+
+	hsp_pdf = PDR0(MXC_CCM_PDR0_HSP_PODF_MASK,
+		       MXC_CCM_PDR0_HSP_PODF_OFFSET);
+	return clk_get_rate(clk->parent) / (hsp_pdf + 1);
+}
+
+static unsigned long usb_get_rate(struct clk *clk)
+{
+	unsigned long usb_pdf, usb_prepdf;
+
+	usb_pdf = PDR1(MXC_CCM_PDR1_USB_PODF_MASK,
+		       MXC_CCM_PDR1_USB_PODF_OFFSET);
+	usb_prepdf = PDR1(MXC_CCM_PDR1_USB_PRDF_MASK,
+			  MXC_CCM_PDR1_USB_PRDF_OFFSET);
+	return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1);
+}
+
+static unsigned long csi_get_rate(struct clk *clk)
+{
+	u32 reg, pre, post;
+
+	reg = __raw_readl(MXC_CCM_PDR0);
+	pre = (reg & MXC_CCM_PDR0_CSI_PRDF_MASK) >>
+	    MXC_CCM_PDR0_CSI_PRDF_OFFSET;
+	pre++;
+	post = (reg & MXC_CCM_PDR0_CSI_PODF_MASK) >>
+	    MXC_CCM_PDR0_CSI_PODF_OFFSET;
+	post++;
+	return clk_get_rate(clk->parent) / (pre * post);
+}
+
+static unsigned long csi_round_rate(struct clk *clk, unsigned long rate)
+{
+	u32 pre, post, parent = clk_get_rate(clk->parent);
+	u32 div = parent / rate;
+
+	if (parent % rate)
+		div++;
+
+	__calc_pre_post_dividers(div, &pre, &post);
+
+	return parent / (pre * post);
+}
+
+static int csi_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
+
+	div = parent / rate;
+
+	if ((parent / div) != rate)
+		return -EINVAL;
+
+	__calc_pre_post_dividers(div, &pre, &post);
+
+	/* Set CSI clock divider */
+	reg = __raw_readl(MXC_CCM_PDR0) &
+	    ~(MXC_CCM_PDR0_CSI_PODF_MASK | MXC_CCM_PDR0_CSI_PRDF_MASK);
+	reg |= (post - 1) << MXC_CCM_PDR0_CSI_PODF_OFFSET;
+	reg |= (pre - 1) << MXC_CCM_PDR0_CSI_PRDF_OFFSET;
+	__raw_writel(reg, MXC_CCM_PDR0);
+
+	return 0;
+}
+
+static unsigned long ssi1_get_rate(struct clk *clk)
+{
+	unsigned long ssi1_pdf, ssi1_prepdf;
+
+	ssi1_pdf = PDR1(MXC_CCM_PDR1_SSI1_PODF_MASK,
+			MXC_CCM_PDR1_SSI1_PODF_OFFSET);
+	ssi1_prepdf = PDR1(MXC_CCM_PDR1_SSI1_PRE_PODF_MASK,
+			   MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET);
+	return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1);
+}
+
+static unsigned long ssi2_get_rate(struct clk *clk)
+{
+	unsigned long ssi2_pdf, ssi2_prepdf;
+
+	ssi2_pdf = PDR1(MXC_CCM_PDR1_SSI2_PODF_MASK,
+			MXC_CCM_PDR1_SSI2_PODF_OFFSET);
+	ssi2_prepdf = PDR1(MXC_CCM_PDR1_SSI2_PRE_PODF_MASK,
+			   MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET);
+	return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1);
+}
+
+static unsigned long firi_get_rate(struct clk *clk)
+{
+	unsigned long firi_pdf, firi_prepdf;
+
+	firi_pdf = PDR1(MXC_CCM_PDR1_FIRI_PODF_MASK,
+			MXC_CCM_PDR1_FIRI_PODF_OFFSET);
+	firi_prepdf = PDR1(MXC_CCM_PDR1_FIRI_PRE_PODF_MASK,
+			   MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET);
+	return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1);
+}
+
+static unsigned long firi_round_rate(struct clk *clk, unsigned long rate)
+{
+	u32 pre, post;
+	u32 parent = clk_get_rate(clk->parent);
+	u32 div = parent / rate;
+
+	if (parent % rate)
+		div++;
+
+	__calc_pre_post_dividers(div, &pre, &post);
+
+	return parent / (pre * post);
+
+}
+
+static int firi_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
+
+	div = parent / rate;
+
+	if ((parent / div) != rate)
+		return -EINVAL;
+
+	__calc_pre_post_dividers(div, &pre, &post);
+
+	/* Set FIRI clock divider */
+	reg = __raw_readl(MXC_CCM_PDR1) &
+	    ~(MXC_CCM_PDR1_FIRI_PODF_MASK | MXC_CCM_PDR1_FIRI_PRE_PODF_MASK);
+	reg |= (pre - 1) << MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET;
+	reg |= (post - 1) << MXC_CCM_PDR1_FIRI_PODF_OFFSET;
+	__raw_writel(reg, MXC_CCM_PDR1);
+
+	return 0;
+}
+
+static unsigned long mbx_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 2;
+}
+
+static unsigned long mstick1_get_rate(struct clk *clk)
+{
+	unsigned long msti_pdf;
+
+	msti_pdf = PDR2(MXC_CCM_PDR2_MST1_PDF_MASK,
+			MXC_CCM_PDR2_MST1_PDF_OFFSET);
+	return clk_get_rate(clk->parent) / (msti_pdf + 1);
+}
+
+static unsigned long mstick2_get_rate(struct clk *clk)
+{
+	unsigned long msti_pdf;
+
+	msti_pdf = PDR2(MXC_CCM_PDR2_MST2_PDF_MASK,
+			MXC_CCM_PDR2_MST2_PDF_OFFSET);
+	return clk_get_rate(clk->parent) / (msti_pdf + 1);
+}
+
+static unsigned long ckih_rate;
+
+static unsigned long clk_ckih_get_rate(struct clk *clk)
+{
+	return ckih_rate;
+}
+
+static unsigned long clk_ckil_get_rate(struct clk *clk)
+{
+	return CKIL_CLK_FREQ;
+}
+
+static struct clk ckih_clk = {
+	.get_rate = clk_ckih_get_rate,
+};
+
+static struct clk mcu_pll_clk = {
+	.parent = &ckih_clk,
+	.get_rate = mcu_pll_get_rate,
+};
+
+static struct clk mcu_main_clk = {
+	.parent = &mcu_pll_clk,
+	.get_rate = mcu_main_get_rate,
+};
+
+static struct clk serial_pll_clk = {
+	.parent = &ckih_clk,
+	.get_rate = serial_pll_get_rate,
+	.enable = serial_pll_enable,
+	.disable = serial_pll_disable,
+};
+
+static struct clk usb_pll_clk = {
+	.parent = &ckih_clk,
+	.get_rate = usb_pll_get_rate,
+	.enable = usb_pll_enable,
+	.disable = usb_pll_disable,
+};
+
+static struct clk ahb_clk = {
+	.parent = &mcu_main_clk,
+	.get_rate = ahb_get_rate,
+};
+
+#define DEFINE_CLOCK(name, i, er, es, gr, s, p)		\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.get_rate	= gr,			\
+		.enable		= cgr_enable,		\
+		.disable	= cgr_disable,		\
+		.secondary	= s,			\
+		.parent		= p,			\
+	}
+
+#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p)	\
+	static struct clk name = {				\
+		.id		= i,				\
+		.enable_reg	= er,				\
+		.enable_shift	= es,				\
+		.get_rate	= getsetround##_get_rate,	\
+		.set_rate	= getsetround##_set_rate,	\
+		.round_rate	= getsetround##_round_rate,	\
+		.enable		= cgr_enable,			\
+		.disable	= cgr_disable,			\
+		.secondary	= s,				\
+		.parent		= p,				\
+	}
+
+DEFINE_CLOCK(perclk_clk,  0, NULL,          0, NULL, NULL, &ipg_clk);
+
+DEFINE_CLOCK(sdhc1_clk,   0, MXC_CCM_CGR0,  0, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(sdhc2_clk,   1, MXC_CCM_CGR0,  2, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(gpt_clk,     0, MXC_CCM_CGR0,  4, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(epit1_clk,   0, MXC_CCM_CGR0,  6, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(epit2_clk,   1, MXC_CCM_CGR0,  8, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(iim_clk,     0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, &sdma_clk1, &ahb_clk);
+DEFINE_CLOCK(cspi3_clk,   2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(rng_clk,     0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(uart1_clk,   0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(uart2_clk,   1, MXC_CCM_CGR0, 22, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(ssi1_clk,    0, MXC_CCM_CGR0, 24, ssi1_get_rate, NULL, &serial_pll_clk);
+DEFINE_CLOCK(i2c1_clk,    0, MXC_CCM_CGR0, 26, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(i2c2_clk,    1, MXC_CCM_CGR0, 28, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(i2c3_clk,    2, MXC_CCM_CGR0, 30, NULL, NULL, &perclk_clk);
+
+DEFINE_CLOCK(mpeg4_clk,   0, MXC_CCM_CGR1,  0, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1,  2, mstick1_get_rate, NULL, &usb_pll_clk);
+DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1,  4, mstick2_get_rate, NULL, &usb_pll_clk);
+DEFINE_CLOCK1(csi_clk,    0, MXC_CCM_CGR1,  6, csi, NULL, &serial_pll_clk);
+DEFINE_CLOCK(rtc_clk,     0, MXC_CCM_CGR1,  8, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(wdog_clk,    0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(pwm_clk,     0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(usb_clk2,    0, MXC_CCM_CGR1, 18, usb_get_rate, NULL, &ahb_clk);
+DEFINE_CLOCK(kpp_clk,     0, MXC_CCM_CGR1, 20, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ipu_clk,     0, MXC_CCM_CGR1, 22, hsp_get_rate, NULL, &mcu_main_clk);
+DEFINE_CLOCK(uart3_clk,   2, MXC_CCM_CGR1, 24, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(uart4_clk,   3, MXC_CCM_CGR1, 26, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(uart5_clk,   4, MXC_CCM_CGR1, 28, NULL, NULL, &perclk_clk);
+DEFINE_CLOCK(owire_clk,   0, MXC_CCM_CGR1, 30, NULL, NULL, &perclk_clk);
+
+DEFINE_CLOCK(ssi2_clk,    1, MXC_CCM_CGR2,  0, ssi2_get_rate, NULL, &serial_pll_clk);
+DEFINE_CLOCK(cspi1_clk,   0, MXC_CCM_CGR2,  2, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(cspi2_clk,   1, MXC_CCM_CGR2,  4, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(mbx_clk,     0, MXC_CCM_CGR2,  6, mbx_get_rate, NULL, &ahb_clk);
+DEFINE_CLOCK(emi_clk,     0, MXC_CCM_CGR2,  8, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK(rtic_clk,    0, MXC_CCM_CGR2, 10, NULL, NULL, &ahb_clk);
+DEFINE_CLOCK1(firi_clk,   0, MXC_CCM_CGR2, 12, firi, NULL, &usb_pll_clk);
+
+DEFINE_CLOCK(sdma_clk2,   0, NULL,          0, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(usb_clk1,    0, NULL,          0, usb_get_rate, NULL, &usb_pll_clk);
+DEFINE_CLOCK(nfc_clk,     0, NULL,          0, nfc_get_rate, NULL, &ahb_clk);
+DEFINE_CLOCK(scc_clk,     0, NULL,          0, NULL, NULL, &ipg_clk);
+DEFINE_CLOCK(ipg_clk,     0, NULL,          0, ipg_get_rate, NULL, &ahb_clk);
+DEFINE_CLOCK(ckil_clk,    0, NULL,          0, clk_ckil_get_rate, NULL, NULL);
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
+	},
+
+static struct clk_lookup lookups[] = {
+	_REGISTER_CLOCK(NULL, "emi", emi_clk)
+	_REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
+	_REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
+	_REGISTER_CLOCK("spi_imx.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(NULL, "rtc", rtc_clk)
+	_REGISTER_CLOCK(NULL, "epit", epit1_clk)
+	_REGISTER_CLOCK(NULL, "epit", epit2_clk)
+	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
+	_REGISTER_CLOCK("ipu-core", NULL, ipu_clk)
+	_REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk)
+	_REGISTER_CLOCK(NULL, "kpp", kpp_clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb", usb_clk1)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_clk2)
+	_REGISTER_CLOCK("mxc-ehci.1", "usb", usb_clk1)
+	_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk2)
+	_REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk1)
+	_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk2)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2)
+	_REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk)
+	_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("imx-i2c.0", NULL, i2c1_clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
+	_REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
+	_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
+	_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
+	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+	_REGISTER_CLOCK(NULL, "firi", firi_clk)
+	_REGISTER_CLOCK(NULL, "ata", ata_clk)
+	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
+	_REGISTER_CLOCK(NULL, "rng", rng_clk)
+	_REGISTER_CLOCK(NULL, "sdma_ahb", sdma_clk1)
+	_REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
+	_REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
+	_REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
+	_REGISTER_CLOCK(NULL, "scc", scc_clk)
+	_REGISTER_CLOCK(NULL, "iim", iim_clk)
+	_REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk)
+	_REGISTER_CLOCK(NULL, "mbx", mbx_clk)
+	_REGISTER_CLOCK("mxc_rtc", NULL, ckil_clk)
+};
+
+int __init mx31_clocks_init(unsigned long fref)
+{
+	u32 reg;
+
+	ckih_rate = fref;
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	/* change the csi_clk parent if necessary */
+	reg = __raw_readl(MXC_CCM_CCMR);
+	if (!(reg & MXC_CCM_CCMR_CSCS))
+		if (clk_set_parent(&csi_clk, &usb_pll_clk))
+			pr_err("%s: error changing csi_clk parent\n", __func__);
+
+
+	/* Turn off all possible clocks */
+	__raw_writel((3 << 4), MXC_CCM_CGR0);
+	__raw_writel(0, MXC_CCM_CGR1);
+	__raw_writel((3 << 8) | (3 << 14) | (3 << 16)|
+		     1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
+					   MX32, but still required to be set */
+		     MXC_CCM_CGR2);
+
+	/*
+	 * Before turning off usb_pll make sure ipg_per_clk is generated
+	 * by ipg_clk and not usb_pll.
+	 */
+	__raw_writel(__raw_readl(MXC_CCM_CCMR) | (1 << 24), MXC_CCM_CCMR);
+
+	usb_pll_disable(&usb_pll_clk);
+
+	pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
+
+	clk_enable(&gpt_clk);
+	clk_enable(&emi_clk);
+	clk_enable(&iim_clk);
+
+	clk_enable(&serial_pll_clk);
+
+	mx31_read_cpu_rev();
+
+	if (mx31_revision() >= MX31_CHIP_REV_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;
+		__raw_writel(reg, MXC_CCM_PMCR1);
+	}
+
+	mxc_timer_init(&ipg_clk, MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR),
+			MX31_INT_GPT);
+
+	return 0;
+}
+
diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c
index f3f41fa..9f3e943e 100644
--- a/arch/arm/mach-mx3/clock-imx35.c
+++ b/arch/arm/mach-mx3/clock-imx35.c
@@ -28,7 +28,7 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 
-#define CCM_BASE	IO_ADDRESS(CCM_BASE_ADDR)
+#define CCM_BASE	MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR)
 
 #define CCM_CCMR        0x00
 #define CCM_PDR0        0x04
@@ -502,7 +502,8 @@
 	__raw_writel((3 << 26) | ll, CCM_BASE + CCM_CGR2);
 	__raw_writel(0, CCM_BASE + CCM_CGR3);
 
-	mxc_timer_init(&gpt_clk, IO_ADDRESS(GPT1_BASE_ADDR), MXC_INT_GPT);
+	mxc_timer_init(&gpt_clk,
+			MX35_IO_ADDRESS(MX35_GPT1_BASE_ADDR), MX35_INT_GPT);
 
 	return 0;
 }
diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c
deleted file mode 100644
index b5c39a0..0000000
--- a/arch/arm/mach-mx3/clock.c
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2008 by 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/module.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <asm/clkdev.h>
-#include <asm/div64.h>
-
-#include <mach/clock.h>
-#include <mach/hardware.h>
-#include <mach/mx31.h>
-#include <mach/common.h>
-
-#include "crm_regs.h"
-
-#define PRE_DIV_MIN_FREQ    10000000 /* Minimum Frequency after Predivider */
-
-static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
-{
-	u32 min_pre, temp_pre, old_err, err;
-
-	if (div >= 512) {
-		*pre = 8;
-		*post = 64;
-	} else if (div >= 64) {
-		min_pre = (div - 1) / 64 + 1;
-		old_err = 8;
-		for (temp_pre = 8; 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 + *pre - 1) / *pre;
-	} else if (div <= 8) {
-		*pre = div;
-		*post = 1;
-	} else {
-		*pre = 1;
-		*post = div;
-	}
-}
-
-static struct clk mcu_pll_clk;
-static struct clk serial_pll_clk;
-static struct clk ipg_clk;
-static struct clk ckih_clk;
-
-static int cgr_enable(struct clk *clk)
-{
-	u32 reg;
-
-	if (!clk->enable_reg)
-		return 0;
-
-	reg = __raw_readl(clk->enable_reg);
-	reg |= 3 << clk->enable_shift;
-	__raw_writel(reg, clk->enable_reg);
-
-	return 0;
-}
-
-static void cgr_disable(struct clk *clk)
-{
-	u32 reg;
-
-	if (!clk->enable_reg)
-		return;
-
-	reg = __raw_readl(clk->enable_reg);
-	reg &= ~(3 << clk->enable_shift);
-
-	/* special case for EMI clock */
-	if (clk->enable_reg == MXC_CCM_CGR2 && clk->enable_shift == 8)
-		reg |= (1 << clk->enable_shift);
-
-	__raw_writel(reg, clk->enable_reg);
-}
-
-static unsigned long pll_ref_get_rate(void)
-{
-	unsigned long ccmr;
-	unsigned int prcs;
-
-	ccmr = __raw_readl(MXC_CCM_CCMR);
-	prcs = (ccmr & MXC_CCM_CCMR_PRCS_MASK) >> MXC_CCM_CCMR_PRCS_OFFSET;
-	if (prcs == 0x1)
-		return CKIL_CLK_FREQ * 1024;
-	else
-		return clk_get_rate(&ckih_clk);
-}
-
-static unsigned long usb_pll_get_rate(struct clk *clk)
-{
-	unsigned long reg;
-
-	reg = __raw_readl(MXC_CCM_UPCTL);
-
-	return mxc_decode_pll(reg, pll_ref_get_rate());
-}
-
-static unsigned long serial_pll_get_rate(struct clk *clk)
-{
-	unsigned long reg;
-
-	reg = __raw_readl(MXC_CCM_SRPCTL);
-
-	return mxc_decode_pll(reg, pll_ref_get_rate());
-}
-
-static unsigned long mcu_pll_get_rate(struct clk *clk)
-{
-	unsigned long reg, ccmr;
-
-	ccmr = __raw_readl(MXC_CCM_CCMR);
-
-	if (!(ccmr & MXC_CCM_CCMR_MPE) || (ccmr & MXC_CCM_CCMR_MDS))
-		return clk_get_rate(&ckih_clk);
-
-	reg = __raw_readl(MXC_CCM_MPCTL);
-
-	return mxc_decode_pll(reg, pll_ref_get_rate());
-}
-
-static int usb_pll_enable(struct clk *clk)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CCMR);
-	reg |= MXC_CCM_CCMR_UPE;
-	__raw_writel(reg, MXC_CCM_CCMR);
-
-	/* No lock bit on MX31, so using max time from spec */
-	udelay(80);
-
-	return 0;
-}
-
-static void usb_pll_disable(struct clk *clk)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CCMR);
-	reg &= ~MXC_CCM_CCMR_UPE;
-	__raw_writel(reg, MXC_CCM_CCMR);
-}
-
-static int serial_pll_enable(struct clk *clk)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CCMR);
-	reg |= MXC_CCM_CCMR_SPE;
-	__raw_writel(reg, MXC_CCM_CCMR);
-
-	/* No lock bit on MX31, so using max time from spec */
-	udelay(80);
-
-	return 0;
-}
-
-static void serial_pll_disable(struct clk *clk)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CCMR);
-	reg &= ~MXC_CCM_CCMR_SPE;
-	__raw_writel(reg, MXC_CCM_CCMR);
-}
-
-#define PDR0(mask, off) ((__raw_readl(MXC_CCM_PDR0) & mask) >> off)
-#define PDR1(mask, off) ((__raw_readl(MXC_CCM_PDR1) & mask) >> off)
-#define PDR2(mask, off) ((__raw_readl(MXC_CCM_PDR2) & mask) >> off)
-
-static unsigned long mcu_main_get_rate(struct clk *clk)
-{
-	u32 pmcr0 = __raw_readl(MXC_CCM_PMCR0);
-
-	if ((pmcr0 & MXC_CCM_PMCR0_DFSUP1) == MXC_CCM_PMCR0_DFSUP1_SPLL)
-		return clk_get_rate(&serial_pll_clk);
-	else
-		return clk_get_rate(&mcu_pll_clk);
-}
-
-static unsigned long ahb_get_rate(struct clk *clk)
-{
-	unsigned long max_pdf;
-
-	max_pdf = PDR0(MXC_CCM_PDR0_MAX_PODF_MASK,
-		       MXC_CCM_PDR0_MAX_PODF_OFFSET);
-	return clk_get_rate(clk->parent) / (max_pdf + 1);
-}
-
-static unsigned long ipg_get_rate(struct clk *clk)
-{
-	unsigned long ipg_pdf;
-
-	ipg_pdf = PDR0(MXC_CCM_PDR0_IPG_PODF_MASK,
-		       MXC_CCM_PDR0_IPG_PODF_OFFSET);
-	return clk_get_rate(clk->parent) / (ipg_pdf + 1);
-}
-
-static unsigned long nfc_get_rate(struct clk *clk)
-{
-	unsigned long nfc_pdf;
-
-	nfc_pdf = PDR0(MXC_CCM_PDR0_NFC_PODF_MASK,
-		       MXC_CCM_PDR0_NFC_PODF_OFFSET);
-	return clk_get_rate(clk->parent) / (nfc_pdf + 1);
-}
-
-static unsigned long hsp_get_rate(struct clk *clk)
-{
-	unsigned long hsp_pdf;
-
-	hsp_pdf = PDR0(MXC_CCM_PDR0_HSP_PODF_MASK,
-		       MXC_CCM_PDR0_HSP_PODF_OFFSET);
-	return clk_get_rate(clk->parent) / (hsp_pdf + 1);
-}
-
-static unsigned long usb_get_rate(struct clk *clk)
-{
-	unsigned long usb_pdf, usb_prepdf;
-
-	usb_pdf = PDR1(MXC_CCM_PDR1_USB_PODF_MASK,
-		       MXC_CCM_PDR1_USB_PODF_OFFSET);
-	usb_prepdf = PDR1(MXC_CCM_PDR1_USB_PRDF_MASK,
-			  MXC_CCM_PDR1_USB_PRDF_OFFSET);
-	return clk_get_rate(clk->parent) / (usb_prepdf + 1) / (usb_pdf + 1);
-}
-
-static unsigned long csi_get_rate(struct clk *clk)
-{
-	u32 reg, pre, post;
-
-	reg = __raw_readl(MXC_CCM_PDR0);
-	pre = (reg & MXC_CCM_PDR0_CSI_PRDF_MASK) >>
-	    MXC_CCM_PDR0_CSI_PRDF_OFFSET;
-	pre++;
-	post = (reg & MXC_CCM_PDR0_CSI_PODF_MASK) >>
-	    MXC_CCM_PDR0_CSI_PODF_OFFSET;
-	post++;
-	return clk_get_rate(clk->parent) / (pre * post);
-}
-
-static unsigned long csi_round_rate(struct clk *clk, unsigned long rate)
-{
-	u32 pre, post, parent = clk_get_rate(clk->parent);
-	u32 div = parent / rate;
-
-	if (parent % rate)
-		div++;
-
-	__calc_pre_post_dividers(div, &pre, &post);
-
-	return parent / (pre * post);
-}
-
-static int csi_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
-
-	div = parent / rate;
-
-	if ((parent / div) != rate)
-		return -EINVAL;
-
-	__calc_pre_post_dividers(div, &pre, &post);
-
-	/* Set CSI clock divider */
-	reg = __raw_readl(MXC_CCM_PDR0) &
-	    ~(MXC_CCM_PDR0_CSI_PODF_MASK | MXC_CCM_PDR0_CSI_PRDF_MASK);
-	reg |= (post - 1) << MXC_CCM_PDR0_CSI_PODF_OFFSET;
-	reg |= (pre - 1) << MXC_CCM_PDR0_CSI_PRDF_OFFSET;
-	__raw_writel(reg, MXC_CCM_PDR0);
-
-	return 0;
-}
-
-static unsigned long ssi1_get_rate(struct clk *clk)
-{
-	unsigned long ssi1_pdf, ssi1_prepdf;
-
-	ssi1_pdf = PDR1(MXC_CCM_PDR1_SSI1_PODF_MASK,
-			MXC_CCM_PDR1_SSI1_PODF_OFFSET);
-	ssi1_prepdf = PDR1(MXC_CCM_PDR1_SSI1_PRE_PODF_MASK,
-			   MXC_CCM_PDR1_SSI1_PRE_PODF_OFFSET);
-	return clk_get_rate(clk->parent) / (ssi1_prepdf + 1) / (ssi1_pdf + 1);
-}
-
-static unsigned long ssi2_get_rate(struct clk *clk)
-{
-	unsigned long ssi2_pdf, ssi2_prepdf;
-
-	ssi2_pdf = PDR1(MXC_CCM_PDR1_SSI2_PODF_MASK,
-			MXC_CCM_PDR1_SSI2_PODF_OFFSET);
-	ssi2_prepdf = PDR1(MXC_CCM_PDR1_SSI2_PRE_PODF_MASK,
-			   MXC_CCM_PDR1_SSI2_PRE_PODF_OFFSET);
-	return clk_get_rate(clk->parent) / (ssi2_prepdf + 1) / (ssi2_pdf + 1);
-}
-
-static unsigned long firi_get_rate(struct clk *clk)
-{
-	unsigned long firi_pdf, firi_prepdf;
-
-	firi_pdf = PDR1(MXC_CCM_PDR1_FIRI_PODF_MASK,
-			MXC_CCM_PDR1_FIRI_PODF_OFFSET);
-	firi_prepdf = PDR1(MXC_CCM_PDR1_FIRI_PRE_PODF_MASK,
-			   MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET);
-	return clk_get_rate(clk->parent) / (firi_prepdf + 1) / (firi_pdf + 1);
-}
-
-static unsigned long firi_round_rate(struct clk *clk, unsigned long rate)
-{
-	u32 pre, post;
-	u32 parent = clk_get_rate(clk->parent);
-	u32 div = parent / rate;
-
-	if (parent % rate)
-		div++;
-
-	__calc_pre_post_dividers(div, &pre, &post);
-
-	return parent / (pre * post);
-
-}
-
-static int firi_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, div, pre, post, parent = clk_get_rate(clk->parent);
-
-	div = parent / rate;
-
-	if ((parent / div) != rate)
-		return -EINVAL;
-
-	__calc_pre_post_dividers(div, &pre, &post);
-
-	/* Set FIRI clock divider */
-	reg = __raw_readl(MXC_CCM_PDR1) &
-	    ~(MXC_CCM_PDR1_FIRI_PODF_MASK | MXC_CCM_PDR1_FIRI_PRE_PODF_MASK);
-	reg |= (pre - 1) << MXC_CCM_PDR1_FIRI_PRE_PODF_OFFSET;
-	reg |= (post - 1) << MXC_CCM_PDR1_FIRI_PODF_OFFSET;
-	__raw_writel(reg, MXC_CCM_PDR1);
-
-	return 0;
-}
-
-static unsigned long mbx_get_rate(struct clk *clk)
-{
-	return clk_get_rate(clk->parent) / 2;
-}
-
-static unsigned long mstick1_get_rate(struct clk *clk)
-{
-	unsigned long msti_pdf;
-
-	msti_pdf = PDR2(MXC_CCM_PDR2_MST1_PDF_MASK,
-			MXC_CCM_PDR2_MST1_PDF_OFFSET);
-	return clk_get_rate(clk->parent) / (msti_pdf + 1);
-}
-
-static unsigned long mstick2_get_rate(struct clk *clk)
-{
-	unsigned long msti_pdf;
-
-	msti_pdf = PDR2(MXC_CCM_PDR2_MST2_PDF_MASK,
-			MXC_CCM_PDR2_MST2_PDF_OFFSET);
-	return clk_get_rate(clk->parent) / (msti_pdf + 1);
-}
-
-static unsigned long ckih_rate;
-
-static unsigned long clk_ckih_get_rate(struct clk *clk)
-{
-	return ckih_rate;
-}
-
-static unsigned long clk_ckil_get_rate(struct clk *clk)
-{
-	return CKIL_CLK_FREQ;
-}
-
-static struct clk ckih_clk = {
-	.get_rate = clk_ckih_get_rate,
-};
-
-static struct clk mcu_pll_clk = {
-	.parent = &ckih_clk,
-	.get_rate = mcu_pll_get_rate,
-};
-
-static struct clk mcu_main_clk = {
-	.parent = &mcu_pll_clk,
-	.get_rate = mcu_main_get_rate,
-};
-
-static struct clk serial_pll_clk = {
-	.parent = &ckih_clk,
-	.get_rate = serial_pll_get_rate,
-	.enable = serial_pll_enable,
-	.disable = serial_pll_disable,
-};
-
-static struct clk usb_pll_clk = {
-	.parent = &ckih_clk,
-	.get_rate = usb_pll_get_rate,
-	.enable = usb_pll_enable,
-	.disable = usb_pll_disable,
-};
-
-static struct clk ahb_clk = {
-	.parent = &mcu_main_clk,
-	.get_rate = ahb_get_rate,
-};
-
-#define DEFINE_CLOCK(name, i, er, es, gr, s, p)		\
-	static struct clk name = {			\
-		.id		= i,			\
-		.enable_reg	= er,			\
-		.enable_shift	= es,			\
-		.get_rate	= gr,			\
-		.enable		= cgr_enable,		\
-		.disable	= cgr_disable,		\
-		.secondary	= s,			\
-		.parent		= p,			\
-	}
-
-#define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p)	\
-	static struct clk name = {				\
-		.id		= i,				\
-		.enable_reg	= er,				\
-		.enable_shift	= es,				\
-		.get_rate	= getsetround##_get_rate,	\
-		.set_rate	= getsetround##_set_rate,	\
-		.round_rate	= getsetround##_round_rate,	\
-		.enable		= cgr_enable,			\
-		.disable	= cgr_disable,			\
-		.secondary	= s,				\
-		.parent		= p,				\
-	}
-
-DEFINE_CLOCK(perclk_clk,  0, NULL,          0, NULL, NULL, &ipg_clk);
-
-DEFINE_CLOCK(sdhc1_clk,   0, MXC_CCM_CGR0,  0, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(sdhc2_clk,   1, MXC_CCM_CGR0,  2, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(gpt_clk,     0, MXC_CCM_CGR0,  4, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(epit1_clk,   0, MXC_CCM_CGR0,  6, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(epit2_clk,   1, MXC_CCM_CGR0,  8, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(iim_clk,     0, MXC_CCM_CGR0, 10, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(ata_clk,     0, MXC_CCM_CGR0, 12, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(sdma_clk1,   0, MXC_CCM_CGR0, 14, NULL, &sdma_clk1, &ahb_clk);
-DEFINE_CLOCK(cspi3_clk,   2, MXC_CCM_CGR0, 16, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(rng_clk,     0, MXC_CCM_CGR0, 18, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(uart1_clk,   0, MXC_CCM_CGR0, 20, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(uart2_clk,   1, MXC_CCM_CGR0, 22, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(ssi1_clk,    0, MXC_CCM_CGR0, 24, ssi1_get_rate, NULL, &serial_pll_clk);
-DEFINE_CLOCK(i2c1_clk,    0, MXC_CCM_CGR0, 26, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(i2c2_clk,    1, MXC_CCM_CGR0, 28, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(i2c3_clk,    2, MXC_CCM_CGR0, 30, NULL, NULL, &perclk_clk);
-
-DEFINE_CLOCK(mpeg4_clk,   0, MXC_CCM_CGR1,  0, NULL, NULL, &ahb_clk);
-DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1,  2, mstick1_get_rate, NULL, &usb_pll_clk);
-DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1,  4, mstick2_get_rate, NULL, &usb_pll_clk);
-DEFINE_CLOCK1(csi_clk,    0, MXC_CCM_CGR1,  6, csi, NULL, &serial_pll_clk);
-DEFINE_CLOCK(rtc_clk,     0, MXC_CCM_CGR1,  8, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(wdog_clk,    0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(pwm_clk,     0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(usb_clk2,    0, MXC_CCM_CGR1, 18, usb_get_rate, NULL, &ahb_clk);
-DEFINE_CLOCK(kpp_clk,     0, MXC_CCM_CGR1, 20, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(ipu_clk,     0, MXC_CCM_CGR1, 22, hsp_get_rate, NULL, &mcu_main_clk);
-DEFINE_CLOCK(uart3_clk,   2, MXC_CCM_CGR1, 24, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(uart4_clk,   3, MXC_CCM_CGR1, 26, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(uart5_clk,   4, MXC_CCM_CGR1, 28, NULL, NULL, &perclk_clk);
-DEFINE_CLOCK(owire_clk,   0, MXC_CCM_CGR1, 30, NULL, NULL, &perclk_clk);
-
-DEFINE_CLOCK(ssi2_clk,    1, MXC_CCM_CGR2,  0, ssi2_get_rate, NULL, &serial_pll_clk);
-DEFINE_CLOCK(cspi1_clk,   0, MXC_CCM_CGR2,  2, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(cspi2_clk,   1, MXC_CCM_CGR2,  4, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(mbx_clk,     0, MXC_CCM_CGR2,  6, mbx_get_rate, NULL, &ahb_clk);
-DEFINE_CLOCK(emi_clk,     0, MXC_CCM_CGR2,  8, NULL, NULL, &ahb_clk);
-DEFINE_CLOCK(rtic_clk,    0, MXC_CCM_CGR2, 10, NULL, NULL, &ahb_clk);
-DEFINE_CLOCK1(firi_clk,   0, MXC_CCM_CGR2, 12, firi, NULL, &usb_pll_clk);
-
-DEFINE_CLOCK(sdma_clk2,   0, NULL,          0, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(usb_clk1,    0, NULL,          0, usb_get_rate, NULL, &usb_pll_clk);
-DEFINE_CLOCK(nfc_clk,     0, NULL,          0, nfc_get_rate, NULL, &ahb_clk);
-DEFINE_CLOCK(scc_clk,     0, NULL,          0, NULL, NULL, &ipg_clk);
-DEFINE_CLOCK(ipg_clk,     0, NULL,          0, ipg_get_rate, NULL, &ahb_clk);
-DEFINE_CLOCK(ckil_clk,    0, NULL,          0, clk_ckil_get_rate, NULL, NULL);
-
-#define _REGISTER_CLOCK(d, n, c) \
-	{ \
-		.dev_id = d, \
-		.con_id = n, \
-		.clk = &c, \
-	},
-
-static struct clk_lookup lookups[] = {
-	_REGISTER_CLOCK(NULL, "emi", emi_clk)
-	_REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk)
-	_REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk)
-	_REGISTER_CLOCK("spi_imx.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(NULL, "rtc", rtc_clk)
-	_REGISTER_CLOCK(NULL, "epit", epit1_clk)
-	_REGISTER_CLOCK(NULL, "epit", epit2_clk)
-	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
-	_REGISTER_CLOCK("ipu-core", NULL, ipu_clk)
-	_REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk)
-	_REGISTER_CLOCK(NULL, "kpp", kpp_clk)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb", usb_clk1)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_clk2)
-	_REGISTER_CLOCK("mxc-ehci.1", "usb", usb_clk1)
-	_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk2)
-	_REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk1)
-	_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk2)
-	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1)
-	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2)
-	_REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk)
-	_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("imx-i2c.0", NULL, i2c1_clk)
-	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
-	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_clk)
-	_REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
-	_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc1_clk)
-	_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc2_clk)
-	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
-	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-	_REGISTER_CLOCK(NULL, "firi", firi_clk)
-	_REGISTER_CLOCK(NULL, "ata", ata_clk)
-	_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
-	_REGISTER_CLOCK(NULL, "rng", rng_clk)
-	_REGISTER_CLOCK(NULL, "sdma_ahb", sdma_clk1)
-	_REGISTER_CLOCK(NULL, "sdma_ipg", sdma_clk2)
-	_REGISTER_CLOCK(NULL, "mstick", mstick1_clk)
-	_REGISTER_CLOCK(NULL, "mstick", mstick2_clk)
-	_REGISTER_CLOCK(NULL, "scc", scc_clk)
-	_REGISTER_CLOCK(NULL, "iim", iim_clk)
-	_REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk)
-	_REGISTER_CLOCK(NULL, "mbx", mbx_clk)
-	_REGISTER_CLOCK("mxc_rtc", NULL, ckil_clk)
-};
-
-int __init mx31_clocks_init(unsigned long fref)
-{
-	u32 reg;
-
-	ckih_rate = fref;
-
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-	/* change the csi_clk parent if necessary */
-	reg = __raw_readl(MXC_CCM_CCMR);
-	if (!(reg & MXC_CCM_CCMR_CSCS))
-		if (clk_set_parent(&csi_clk, &usb_pll_clk))
-			pr_err("%s: error changing csi_clk parent\n", __func__);
-
-
-	/* Turn off all possible clocks */
-	__raw_writel((3 << 4), MXC_CCM_CGR0);
-	__raw_writel(0, MXC_CCM_CGR1);
-	__raw_writel((3 << 8) | (3 << 14) | (3 << 16)|
-		     1 << 27 | 1 << 28, /* Bit 27 and 28 are not defined for
-					   MX32, but still required to be set */
-		     MXC_CCM_CGR2);
-
-	/*
-	 * Before turning off usb_pll make sure ipg_per_clk is generated
-	 * by ipg_clk and not usb_pll.
-	 */
-	__raw_writel(__raw_readl(MXC_CCM_CCMR) | (1 << 24), MXC_CCM_CCMR);
-
-	usb_pll_disable(&usb_pll_clk);
-
-	pr_info("Clock input source is %ld\n", clk_get_rate(&ckih_clk));
-
-	clk_enable(&gpt_clk);
-	clk_enable(&emi_clk);
-	clk_enable(&iim_clk);
-
-	clk_enable(&serial_pll_clk);
-
-	mx31_read_cpu_rev();
-
-	if (mx31_revision() >= CHIP_REV_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;
-		__raw_writel(reg, MXC_CCM_PMCR1);
-	}
-
-	mxc_timer_init(&ipg_clk, IO_ADDRESS(GPT1_BASE_ADDR), MXC_INT_GPT);
-
-	return 0;
-}
-
diff --git a/arch/arm/mach-mx3/cpu.c b/arch/arm/mach-mx3/cpu.c
index db82880..861afe0 100644
--- a/arch/arm/mach-mx3/cpu.c
+++ b/arch/arm/mach-mx3/cpu.c
@@ -41,7 +41,7 @@
 	u32 i, srev;
 
 	/* read SREV register from IIM module */
-	srev = __raw_readl(IO_ADDRESS(IIM_BASE_ADDR) + MXC_IIMSREV);
+	srev = __raw_readl(IO_ADDRESS(IIM_BASE_ADDR + MXC_IIMSREV));
 
 	for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
 		if (srev == mx31_cpu_type[i].srev) {
diff --git a/arch/arm/mach-mx3/crm_regs.h b/arch/arm/mach-mx3/crm_regs.h
index adfa362..37a8a07 100644
--- a/arch/arm/mach-mx3/crm_regs.h
+++ b/arch/arm/mach-mx3/crm_regs.h
@@ -24,7 +24,7 @@
 #define CKIH_CLK_FREQ_27MHZ     27000000
 #define CKIL_CLK_FREQ           32768
 
-#define MXC_CCM_BASE		IO_ADDRESS(CCM_BASE_ADDR)
+#define MXC_CCM_BASE		MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR)
 
 /* Register addresses */
 #define MXC_CCM_CCMR		(MXC_CCM_BASE + 0x00)
diff --git a/arch/arm/mach-mx3/iomux-imx31.c b/arch/arm/mach-mx3/iomux-imx31.c
new file mode 100644
index 0000000..a1d7fa5
--- /dev/null
+++ b/arch/arm/mach-mx3/iomux-imx31.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Valentin Longchamp <valentin.longchamp@epfl.ch>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have 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/spinlock.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/iomux-mx3.h>
+
+/*
+ * IOMUX register (base) addresses
+ */
+#define IOMUX_BASE	MX31_IO_ADDRESS(MX31_IOMUXC_BASE_ADDR)
+#define IOMUXINT_OBS1	(IOMUX_BASE + 0x000)
+#define IOMUXINT_OBS2	(IOMUX_BASE + 0x004)
+#define IOMUXGPR	(IOMUX_BASE + 0x008)
+#define IOMUXSW_MUX_CTL	(IOMUX_BASE + 0x00C)
+#define IOMUXSW_PAD_CTL	(IOMUX_BASE + 0x154)
+
+static DEFINE_SPINLOCK(gpio_mux_lock);
+
+#define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
+
+unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
+/*
+ * set the mode for a IOMUX pin.
+ */
+int mxc_iomux_mode(unsigned int pin_mode)
+{
+	u32 field, l, mode, ret = 0;
+	void __iomem *reg;
+
+	reg = IOMUXSW_MUX_CTL + (pin_mode & IOMUX_REG_MASK);
+	field = pin_mode & 0x3;
+	mode = (pin_mode & IOMUX_MODE_MASK) >> IOMUX_MODE_SHIFT;
+
+	spin_lock(&gpio_mux_lock);
+
+	l = __raw_readl(reg);
+	l &= ~(0xff << (field * 8));
+	l |= mode << (field * 8);
+	__raw_writel(l, reg);
+
+	spin_unlock(&gpio_mux_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(mxc_iomux_mode);
+
+/*
+ * This function configures the pad value for a IOMUX pin.
+ */
+void mxc_iomux_set_pad(enum iomux_pins pin, u32 config)
+{
+	u32 field, l;
+	void __iomem *reg;
+
+	pin &= IOMUX_PADNUM_MASK;
+	reg = IOMUXSW_PAD_CTL + (pin + 2) / 3 * 4;
+	field = (pin + 2) % 3;
+
+	pr_debug("%s: reg offset = 0x%x, field = %d\n",
+			__func__, (pin + 2) / 3, field);
+
+	spin_lock(&gpio_mux_lock);
+
+	l = __raw_readl(reg);
+	l &= ~(0x1ff << (field * 10));
+	l |= config << (field * 10);
+	__raw_writel(l, reg);
+
+	spin_unlock(&gpio_mux_lock);
+}
+EXPORT_SYMBOL(mxc_iomux_set_pad);
+
+/*
+ * allocs a single pin:
+ * 	- reserves the pin so that it is not claimed by another driver
+ * 	- setups the iomux according to the configuration
+ */
+int mxc_iomux_alloc_pin(const unsigned int pin, const char *label)
+{
+	unsigned pad = pin & IOMUX_PADNUM_MASK;
+
+	if (pad >= (PIN_MAX + 1)) {
+		printk(KERN_ERR "mxc_iomux: Attempt to request nonexistant pin %u for \"%s\"\n",
+			pad, label ? label : "?");
+		return -EINVAL;
+	}
+
+	if (test_and_set_bit(pad, mxc_pin_alloc_map)) {
+		printk(KERN_ERR "mxc_iomux: pin %u already used. Allocation for \"%s\" failed\n",
+			pad, label ? label : "?");
+		return -EBUSY;
+	}
+	mxc_iomux_mode(pin);
+
+	return 0;
+}
+EXPORT_SYMBOL(mxc_iomux_alloc_pin);
+
+int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+		const char *label)
+{
+	unsigned int *p = pin_list;
+	int i;
+	int ret = -EINVAL;
+
+	for (i = 0; i < count; i++) {
+		ret = mxc_iomux_alloc_pin(*p, label);
+		if (ret)
+			goto setup_error;
+		p++;
+	}
+	return 0;
+
+setup_error:
+	mxc_iomux_release_multiple_pins(pin_list, i);
+	return ret;
+}
+EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins);
+
+void mxc_iomux_release_pin(const unsigned int pin)
+{
+	unsigned pad = pin & IOMUX_PADNUM_MASK;
+
+	if (pad < (PIN_MAX + 1))
+		clear_bit(pad, mxc_pin_alloc_map);
+}
+EXPORT_SYMBOL(mxc_iomux_release_pin);
+
+void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count)
+{
+	unsigned int *p = pin_list;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		mxc_iomux_release_pin(*p);
+		p++;
+	}
+}
+EXPORT_SYMBOL(mxc_iomux_release_multiple_pins);
+
+/*
+ * This function enables/disables the general purpose function for a particular
+ * signal.
+ */
+void mxc_iomux_set_gpr(enum iomux_gp_func gp, bool en)
+{
+	u32 l;
+
+	spin_lock(&gpio_mux_lock);
+	l = __raw_readl(IOMUXGPR);
+	if (en)
+		l |= gp;
+	else
+		l &= ~gp;
+
+	__raw_writel(l, IOMUXGPR);
+	spin_unlock(&gpio_mux_lock);
+}
+EXPORT_SYMBOL(mxc_iomux_set_gpr);
diff --git a/arch/arm/mach-mx3/iomux.c b/arch/arm/mach-mx3/iomux.c
deleted file mode 100644
index c66ccbc..0000000
--- a/arch/arm/mach-mx3/iomux.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
- * Copyright (C) 2009 by Valentin Longchamp <valentin.longchamp@epfl.ch>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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/spinlock.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-#include <mach/iomux-mx3.h>
-
-/*
- * IOMUX register (base) addresses
- */
-#define IOMUX_BASE	IO_ADDRESS(IOMUXC_BASE_ADDR)
-#define IOMUXINT_OBS1	(IOMUX_BASE + 0x000)
-#define IOMUXINT_OBS2	(IOMUX_BASE + 0x004)
-#define IOMUXGPR	(IOMUX_BASE + 0x008)
-#define IOMUXSW_MUX_CTL	(IOMUX_BASE + 0x00C)
-#define IOMUXSW_PAD_CTL	(IOMUX_BASE + 0x154)
-
-static DEFINE_SPINLOCK(gpio_mux_lock);
-
-#define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
-
-unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
-/*
- * set the mode for a IOMUX pin.
- */
-int mxc_iomux_mode(unsigned int pin_mode)
-{
-	u32 field, l, mode, ret = 0;
-	void __iomem *reg;
-
-	reg = IOMUXSW_MUX_CTL + (pin_mode & IOMUX_REG_MASK);
-	field = pin_mode & 0x3;
-	mode = (pin_mode & IOMUX_MODE_MASK) >> IOMUX_MODE_SHIFT;
-
-	spin_lock(&gpio_mux_lock);
-
-	l = __raw_readl(reg);
-	l &= ~(0xff << (field * 8));
-	l |= mode << (field * 8);
-	__raw_writel(l, reg);
-
-	spin_unlock(&gpio_mux_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL(mxc_iomux_mode);
-
-/*
- * This function configures the pad value for a IOMUX pin.
- */
-void mxc_iomux_set_pad(enum iomux_pins pin, u32 config)
-{
-	u32 field, l;
-	void __iomem *reg;
-
-	pin &= IOMUX_PADNUM_MASK;
-	reg = IOMUXSW_PAD_CTL + (pin + 2) / 3 * 4;
-	field = (pin + 2) % 3;
-
-	pr_debug("%s: reg offset = 0x%x, field = %d\n",
-			__func__, (pin + 2) / 3, field);
-
-	spin_lock(&gpio_mux_lock);
-
-	l = __raw_readl(reg);
-	l &= ~(0x1ff << (field * 10));
-	l |= config << (field * 10);
-	__raw_writel(l, reg);
-
-	spin_unlock(&gpio_mux_lock);
-}
-EXPORT_SYMBOL(mxc_iomux_set_pad);
-
-/*
- * allocs a single pin:
- * 	- reserves the pin so that it is not claimed by another driver
- * 	- setups the iomux according to the configuration
- */
-int mxc_iomux_alloc_pin(const unsigned int pin, const char *label)
-{
-	unsigned pad = pin & IOMUX_PADNUM_MASK;
-
-	if (pad >= (PIN_MAX + 1)) {
-		printk(KERN_ERR "mxc_iomux: Attempt to request nonexistant pin %u for \"%s\"\n",
-			pad, label ? label : "?");
-		return -EINVAL;
-	}
-
-	if (test_and_set_bit(pad, mxc_pin_alloc_map)) {
-		printk(KERN_ERR "mxc_iomux: pin %u already used. Allocation for \"%s\" failed\n",
-			pad, label ? label : "?");
-		return -EBUSY;
-	}
-	mxc_iomux_mode(pin);
-
-	return 0;
-}
-EXPORT_SYMBOL(mxc_iomux_alloc_pin);
-
-int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
-		const char *label)
-{
-	unsigned int *p = pin_list;
-	int i;
-	int ret = -EINVAL;
-
-	for (i = 0; i < count; i++) {
-		ret = mxc_iomux_alloc_pin(*p, label);
-		if (ret)
-			goto setup_error;
-		p++;
-	}
-	return 0;
-
-setup_error:
-	mxc_iomux_release_multiple_pins(pin_list, i);
-	return ret;
-}
-EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins);
-
-void mxc_iomux_release_pin(const unsigned int pin)
-{
-	unsigned pad = pin & IOMUX_PADNUM_MASK;
-
-	if (pad < (PIN_MAX + 1))
-		clear_bit(pad, mxc_pin_alloc_map);
-}
-EXPORT_SYMBOL(mxc_iomux_release_pin);
-
-void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count)
-{
-	unsigned int *p = pin_list;
-	int i;
-
-	for (i = 0; i < count; i++) {
-		mxc_iomux_release_pin(*p);
-		p++;
-	}
-}
-EXPORT_SYMBOL(mxc_iomux_release_multiple_pins);
-
-/*
- * This function enables/disables the general purpose function for a particular
- * signal.
- */
-void mxc_iomux_set_gpr(enum iomux_gp_func gp, bool en)
-{
-	u32 l;
-
-	spin_lock(&gpio_mux_lock);
-	l = __raw_readl(IOMUXGPR);
-	if (en)
-		l |= gp;
-	else
-		l &= ~gp;
-
-	__raw_writel(l, IOMUXGPR);
-	spin_unlock(&gpio_mux_lock);
-}
-EXPORT_SYMBOL(mxc_iomux_set_gpr);
diff --git a/arch/arm/mach-mx3/kzmarm11.c b/arch/arm/mach-mx3/kzmarm11.c
deleted file mode 100644
index 6fa99ce..0000000
--- a/arch/arm/mach-mx3/kzmarm11.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * KZM-ARM11-01 support
- *  Copyright (C) 2009  Yoichi Yuasa <yuasa@linux-mips.org>
- *
- * based on code for MX31ADS,
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2005-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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/smsc911x.h>
-#include <linux/types.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-#include <asm/setup.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-
-#include <mach/board-kzmarm11.h>
-#include <mach/clock.h>
-#include <mach/common.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux-mx3.h>
-#include <mach/memory.h>
-
-#include "devices.h"
-
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
-/*
- * KZM-ARM11-01 has an external UART on FPGA
- */
-static struct plat_serial8250_port serial_platform_data[] = {
-	{
-		.membase	= IO_ADDRESS(KZM_ARM11_16550),
-		.mapbase	= KZM_ARM11_16550,
-		.irq		= IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
-		.irqflags	= IRQ_TYPE_EDGE_RISING,
-		.uartclk	= 14745600,
-		.regshift	= 0,
-		.iotype		= UPIO_MEM,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
-				  UPF_BUGGY_UART,
-	},
-	{},
-};
-
-static struct resource serial8250_resources[] = {
-	{
-		.start	= KZM_ARM11_16550,
-		.end	= KZM_ARM11_16550 + 0x10,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
-		.end	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device serial_device = {
-	.name		= "serial8250",
-	.id		= PLAT8250_DEV_PLATFORM,
-	.dev		= {
-				.platform_data = serial_platform_data,
-			  },
-	.num_resources	= ARRAY_SIZE(serial8250_resources),
-	.resource	= serial8250_resources,
-};
-
-static int __init kzm_init_ext_uart(void)
-{
-	u8 tmp;
-
-	/*
-	 * GPIO 1-1: external UART interrupt line
-	 */
-	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO));
-	gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1), "ext-uart-int");
-	gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
-
-	/*
-	 * Unmask UART interrupt
-	 */
-	tmp = __raw_readb(IO_ADDRESS(KZM_ARM11_CTL1));
-	tmp |= 0x2;
-	__raw_writeb(tmp, IO_ADDRESS(KZM_ARM11_CTL1));
-
-	return platform_device_register(&serial_device);
-}
-#else
-static inline int kzm_init_ext_uart(void)
-{
-	return 0;
-}
-#endif
-
-/*
- * SMSC LAN9118
- */
-#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
-static struct smsc911x_platform_config kzm_smsc9118_config = {
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
-};
-
-static struct resource kzm_smsc9118_resources[] = {
-	{
-		.start	= CS5_BASE_ADDR,
-		.end	= CS5_BASE_ADDR + SZ_128K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_2),
-		.end	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_2),
-		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
-	},
-};
-
-static struct platform_device kzm_smsc9118_device = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(kzm_smsc9118_resources),
-	.resource	= kzm_smsc9118_resources,
-	.dev		= {
-				.platform_data = &kzm_smsc9118_config,
-			  },
-};
-
-static int __init kzm_init_smsc9118(void)
-{
-	/*
-	 * GPIO 1-2: SMSC9118 interrupt line
-	 */
-	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO1_2, IOMUX_CONFIG_GPIO));
-	gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2), "smsc9118-int");
-	gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2));
-
-	return platform_device_register(&kzm_smsc9118_device);
-}
-#else
-static inline int kzm_init_smsc9118(void)
-{
-	return 0;
-}
-#endif
-
-#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static void __init kzm_init_imx_uart(void)
-{
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-
-	mxc_register_device(&mxc_uart_device1, &uart_pdata);
-}
-#else
-static inline void kzm_init_imx_uart(void)
-{
-}
-#endif
-
-static int kzm_pins[] __initdata = {
-	MX31_PIN_CTS1__CTS1,
-	MX31_PIN_RTS1__RTS1,
-	MX31_PIN_TXD1__TXD1,
-	MX31_PIN_RXD1__RXD1,
-	MX31_PIN_DCD_DCE1__DCD_DCE1,
-	MX31_PIN_RI_DCE1__RI_DCE1,
-	MX31_PIN_DSR_DCE1__DSR_DCE1,
-	MX31_PIN_DTR_DCE1__DTR_DCE1,
-	MX31_PIN_CTS2__CTS2,
-	MX31_PIN_RTS2__RTS2,
-	MX31_PIN_TXD2__TXD2,
-	MX31_PIN_RXD2__RXD2,
-	MX31_PIN_DCD_DTE1__DCD_DTE2,
-	MX31_PIN_RI_DTE1__RI_DTE2,
-	MX31_PIN_DSR_DTE1__DSR_DTE2,
-	MX31_PIN_DTR_DTE1__DTR_DTE2,
-};
-
-/*
- * Board specific initialization.
- */
-static void __init kzm_board_init(void)
-{
-	mxc_iomux_setup_multiple_pins(kzm_pins,
-				      ARRAY_SIZE(kzm_pins), "kzm");
-	kzm_init_ext_uart();
-	kzm_init_smsc9118();
-	kzm_init_imx_uart();
-
-	pr_info("Clock input source is 26MHz\n");
-}
-
-/*
- * This structure defines static mappings for the kzm-arm11-01 board.
- */
-static struct map_desc kzm_io_desc[] __initdata = {
-	{
-		.virtual	= CS4_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(CS4_BASE_ADDR),
-		.length		= CS4_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CS5_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(CS5_BASE_ADDR),
-		.length		= CS5_SIZE,
-		.type		= MT_DEVICE
-	},
-};
-
-/*
- * Set up static virtual mappings.
- */
-static void __init kzm_map_io(void)
-{
-	mx31_map_io();
-	iotable_init(kzm_io_desc, ARRAY_SIZE(kzm_io_desc));
-}
-
-static void __init kzm_timer_init(void)
-{
-	mx31_clocks_init(26000000);
-}
-
-static struct sys_timer kzm_timer = {
-	.init   = kzm_timer_init,
-};
-
-/*
- * The following uses standard kernel macros define in arch.h in order to
- * initialize __mach_desc_KZM_ARM11_01 data structure.
- */
-MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
-	.phys_io        = AIPS1_BASE_ADDR,
-	.io_pg_offst    = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = kzm_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = kzm_board_init,
-	.timer          = &kzm_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-armadillo5x0.c b/arch/arm/mach-mx3/mach-armadillo5x0.c
new file mode 100644
index 0000000..3d72b0b
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-armadillo5x0.c
@@ -0,0 +1,416 @@
+/*
+ * armadillo5x0.c
+ *
+ * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
+ * updates in http://alberdroid.blogspot.com/
+ *
+ * Based on Atmark Techno, Inc. armadillo 500 BSP 2008
+ * Based on mx31ads.c and pcm037.c Great Work!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have 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/clk.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.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/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include <mach/board-armadillo5x0.h>
+#include <mach/mmc.h>
+#include <mach/ipu.h>
+#include <mach/mx3fb.h>
+#include <mach/mxc_nand.h>
+
+#include "devices.h"
+#include "crm_regs.h"
+
+static int armadillo5x0_pins[] = {
+	/* UART1 */
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+	/* UART2 */
+	MX31_PIN_CTS2__CTS2,
+	MX31_PIN_RTS2__RTS2,
+	MX31_PIN_TXD2__TXD2,
+	MX31_PIN_RXD2__RXD2,
+	/* LAN9118_IRQ */
+	IOMUX_MODE(MX31_PIN_GPIO1_0, IOMUX_CONFIG_GPIO),
+	/* SDHC1 */
+	MX31_PIN_SD1_DATA3__SD1_DATA3,
+	MX31_PIN_SD1_DATA2__SD1_DATA2,
+	MX31_PIN_SD1_DATA1__SD1_DATA1,
+	MX31_PIN_SD1_DATA0__SD1_DATA0,
+	MX31_PIN_SD1_CLK__SD1_CLK,
+	MX31_PIN_SD1_CMD__SD1_CMD,
+	/* Framebuffer */
+	MX31_PIN_LD0__LD0,
+	MX31_PIN_LD1__LD1,
+	MX31_PIN_LD2__LD2,
+	MX31_PIN_LD3__LD3,
+	MX31_PIN_LD4__LD4,
+	MX31_PIN_LD5__LD5,
+	MX31_PIN_LD6__LD6,
+	MX31_PIN_LD7__LD7,
+	MX31_PIN_LD8__LD8,
+	MX31_PIN_LD9__LD9,
+	MX31_PIN_LD10__LD10,
+	MX31_PIN_LD11__LD11,
+	MX31_PIN_LD12__LD12,
+	MX31_PIN_LD13__LD13,
+	MX31_PIN_LD14__LD14,
+	MX31_PIN_LD15__LD15,
+	MX31_PIN_LD16__LD16,
+	MX31_PIN_LD17__LD17,
+	MX31_PIN_VSYNC3__VSYNC3,
+	MX31_PIN_HSYNC__HSYNC,
+	MX31_PIN_FPSHIFT__FPSHIFT,
+	MX31_PIN_DRDY0__DRDY0,
+	IOMUX_MODE(MX31_PIN_LCS1, IOMUX_CONFIG_GPIO), /*ADV7125_PSAVE*/
+	/* I2C2 */
+	MX31_PIN_CSPI2_MOSI__SCL,
+	MX31_PIN_CSPI2_MISO__SDA,
+};
+
+/* RTC over I2C*/
+#define ARMADILLO5X0_RTC_GPIO	IOMUX_TO_GPIO(MX31_PIN_SRXD4)
+
+static struct i2c_board_info armadillo5x0_i2c_rtc = {
+	I2C_BOARD_INFO("s35390a", 0x30),
+};
+
+/* GPIO BUTTONS */
+static struct gpio_keys_button armadillo5x0_buttons[] = {
+	{
+		.code		= KEY_ENTER, /*28*/
+		.gpio		= IOMUX_TO_GPIO(MX31_PIN_SCLK0),
+		.active_low	= 1,
+		.desc		= "menu",
+		.wakeup		= 1,
+	}, {
+		.code		= KEY_BACK, /*158*/
+		.gpio		= IOMUX_TO_GPIO(MX31_PIN_SRST0),
+		.active_low	= 1,
+		.desc		= "back",
+		.wakeup		= 1,
+	}
+};
+
+static struct gpio_keys_platform_data armadillo5x0_button_data = {
+	.buttons	= armadillo5x0_buttons,
+	.nbuttons	= ARRAY_SIZE(armadillo5x0_buttons),
+};
+
+static struct platform_device armadillo5x0_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &armadillo5x0_button_data,
+	}
+};
+
+/*
+ * NAND Flash
+ */
+static struct mxc_nand_platform_data armadillo5x0_nand_flash_pdata = {
+	.width		= 1,
+	.hw_ecc		= 1,
+};
+
+/*
+ * MTD NOR Flash
+ */
+static struct mtd_partition armadillo5x0_nor_flash_partitions[] = {
+	{
+		.name		= "nor.bootloader",
+		.offset		= 0x00000000,
+		.size		= 4*32*1024,
+	}, {
+		.name		= "nor.kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 16*128*1024,
+	}, {
+		.name		= "nor.userland",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 110*128*1024,
+	}, {
+		.name		= "nor.config",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 1*128*1024,
+	},
+};
+
+static struct physmap_flash_data armadillo5x0_nor_flash_pdata = {
+	.width		= 2,
+	.parts		= armadillo5x0_nor_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(armadillo5x0_nor_flash_partitions),
+};
+
+static struct resource armadillo5x0_nor_flash_resource = {
+	.flags		= IORESOURCE_MEM,
+	.start		= MX31_CS0_BASE_ADDR,
+	.end		= MX31_CS0_BASE_ADDR + SZ_64M - 1,
+};
+
+static struct platform_device armadillo5x0_nor_flash = {
+	.name			= "physmap-flash",
+	.id			= -1,
+	.num_resources		= 1,
+	.resource		= &armadillo5x0_nor_flash_resource,
+};
+
+/*
+ * FB support
+ */
+static const struct fb_videomode fb_modedb[] = {
+	{	/* 640x480 @ 60 Hz */
+		.name		= "CRT-VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 39721,
+		.left_margin	= 35,
+		.right_margin	= 115,
+		.upper_margin	= 43,
+		.lower_margin	= 1,
+		.hsync_len	= 10,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_OE_ACT_HIGH,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {/* 800x600 @ 56 Hz */
+		.name		= "CRT-SVGA",
+		.refresh	= 56,
+		.xres		= 800,
+		.yres		= 600,
+		.pixclock	= 30000,
+		.left_margin	= 30,
+		.right_margin	= 108,
+		.upper_margin	= 13,
+		.lower_margin	= 10,
+		.hsync_len	= 10,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_OE_ACT_HIGH | FB_SYNC_HOR_HIGH_ACT |
+				  FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	},
+};
+
+static struct ipu_platform_data mx3_ipu_data = {
+	.irq_base = MXC_IPU_IRQ_START,
+};
+
+static struct mx3fb_platform_data mx3fb_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.name		= "CRT-VGA",
+	.mode		= fb_modedb,
+	.num_modes	= ARRAY_SIZE(fb_modedb),
+};
+
+/*
+ * SDHC 1
+ * MMC support
+ */
+static int armadillo5x0_sdhc1_get_ro(struct device *dev)
+{
+	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B));
+}
+
+static int armadillo5x0_sdhc1_init(struct device *dev,
+				   irq_handler_t detect_irq, void *data)
+{
+	int ret;
+	int gpio_det, gpio_wp;
+
+	gpio_det = IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK);
+	gpio_wp = IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B);
+
+	ret = gpio_request(gpio_det, "sdhc-card-detect");
+	if (ret)
+		return ret;
+
+	gpio_direction_input(gpio_det);
+
+	ret = gpio_request(gpio_wp, "sdhc-write-protect");
+	if (ret)
+		goto err_gpio_free;
+
+	gpio_direction_input(gpio_wp);
+
+	/* When supported the trigger type have to be BOTH */
+	ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), detect_irq,
+			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  "sdhc-detect", data);
+
+	if (ret)
+		goto err_gpio_free_2;
+
+	return 0;
+
+err_gpio_free_2:
+	gpio_free(gpio_wp);
+
+err_gpio_free:
+	gpio_free(gpio_det);
+
+	return ret;
+
+}
+
+static void armadillo5x0_sdhc1_exit(struct device *dev, void *data)
+{
+	free_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), data);
+	gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK));
+	gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B));
+}
+
+static struct imxmmc_platform_data sdhc_pdata = {
+	.get_ro = armadillo5x0_sdhc1_get_ro,
+	.init = armadillo5x0_sdhc1_init,
+	.exit = armadillo5x0_sdhc1_exit,
+};
+
+/*
+ * SMSC 9118
+ * Network support
+ */
+static struct resource armadillo5x0_smc911x_resources[] = {
+	{
+		.start	= MX31_CS3_BASE_ADDR,
+		.end	= MX31_CS3_BASE_ADDR + SZ_32M - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+		.end	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+	},
+};
+
+static struct smsc911x_platform_config smsc911x_info = {
+	.flags		= SMSC911X_USE_16BIT,
+	.irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct platform_device armadillo5x0_smc911x_device = {
+	.name           = "smsc911x",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(armadillo5x0_smc911x_resources),
+	.resource       = armadillo5x0_smc911x_resources,
+	.dev            = {
+		.platform_data = &smsc911x_info,
+	},
+};
+
+/* UART device data */
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&armadillo5x0_smc911x_device,
+	&mxc_i2c_device1,
+	&armadillo5x0_button_device,
+};
+
+/*
+ * Perform board specific initializations
+ */
+static void __init armadillo5x0_init(void)
+{
+	mxc_iomux_setup_multiple_pins(armadillo5x0_pins,
+			ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0");
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	/* Register UART */
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+
+	/* SMSC9118 IRQ pin */
+	gpio_direction_input(MX31_PIN_GPIO1_0);
+
+	/* Register SDHC */
+	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
+
+	/* Register FB */
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	mxc_register_device(&mx3_fb, &mx3fb_pdata);
+
+	/* Register NOR Flash */
+	mxc_register_device(&armadillo5x0_nor_flash,
+			    &armadillo5x0_nor_flash_pdata);
+
+	/* Register NAND Flash */
+	mxc_register_device(&mxc_nand_device, &armadillo5x0_nand_flash_pdata);
+
+	/* set NAND page size to 2k if not configured via boot mode pins */
+	__raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR);
+
+	/* RTC */
+	/* Get RTC IRQ and register the chip */
+	if (gpio_request(ARMADILLO5X0_RTC_GPIO, "rtc") == 0) {
+		if (gpio_direction_input(ARMADILLO5X0_RTC_GPIO) == 0)
+			armadillo5x0_i2c_rtc.irq = gpio_to_irq(ARMADILLO5X0_RTC_GPIO);
+		else
+			gpio_free(ARMADILLO5X0_RTC_GPIO);
+	}
+	if (armadillo5x0_i2c_rtc.irq == 0)
+		pr_warning("armadillo5x0_init: failed to get RTC IRQ\n");
+	i2c_register_board_info(1, &armadillo5x0_i2c_rtc, 1);
+}
+
+static void __init armadillo5x0_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer armadillo5x0_timer = {
+	.init	= armadillo5x0_timer_init,
+};
+
+MACHINE_START(ARMADILLO5X0, "Armadillo-500")
+	/* Maintainer: Alberto Panizzo  */
+	.phys_io	= MX31_AIPS1_BASE_ADDR,
+	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
+	.boot_params	= MX3x_PHYS_OFFSET + 0x100,
+	.map_io		= mx31_map_io,
+	.init_irq	= mx31_init_irq,
+	.timer		= &armadillo5x0_timer,
+	.init_machine	= armadillo5x0_init,
+MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-kzm_arm11_01.c b/arch/arm/mach-mx3/mach-kzm_arm11_01.c
new file mode 100644
index 0000000..f085d5d
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-kzm_arm11_01.c
@@ -0,0 +1,273 @@
+/*
+ * KZM-ARM11-01 support
+ *  Copyright (C) 2009  Yoichi Yuasa <yuasa@linux-mips.org>
+ *
+ * based on code for MX31ADS,
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2005-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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/smsc911x.h>
+#include <linux/types.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <mach/board-kzmarm11.h>
+#include <mach/clock.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include <mach/memory.h>
+
+#include "devices.h"
+
+#define KZM_ARM11_IO_ADDRESS(x) (					\
+	IMX_IO_ADDRESS(x, MX31_CS4) ?:					\
+	IMX_IO_ADDRESS(x, MX31_CS5) ?:					\
+	MX31_IO_ADDRESS(x))
+
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+/*
+ * KZM-ARM11-01 has an external UART on FPGA
+ */
+static struct plat_serial8250_port serial_platform_data[] = {
+	{
+		.membase	= KZM_ARM11_IO_ADDRESS(KZM_ARM11_16550),
+		.mapbase	= KZM_ARM11_16550,
+		.irq		= IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
+		.irqflags	= IRQ_TYPE_EDGE_RISING,
+		.uartclk	= 14745600,
+		.regshift	= 0,
+		.iotype		= UPIO_MEM,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+				  UPF_BUGGY_UART,
+	},
+	{},
+};
+
+static struct resource serial8250_resources[] = {
+	{
+		.start	= KZM_ARM11_16550,
+		.end	= KZM_ARM11_16550 + 0x10,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
+		.end	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device serial_device = {
+	.name		= "serial8250",
+	.id		= PLAT8250_DEV_PLATFORM,
+	.dev		= {
+				.platform_data = serial_platform_data,
+			  },
+	.num_resources	= ARRAY_SIZE(serial8250_resources),
+	.resource	= serial8250_resources,
+};
+
+static int __init kzm_init_ext_uart(void)
+{
+	u8 tmp;
+
+	/*
+	 * GPIO 1-1: external UART interrupt line
+	 */
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO));
+	gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1), "ext-uart-int");
+	gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
+
+	/*
+	 * Unmask UART interrupt
+	 */
+	tmp = __raw_readb(KZM_ARM11_IO_ADDRESS(KZM_ARM11_CTL1));
+	tmp |= 0x2;
+	__raw_writeb(tmp, KZM_ARM11_IO_ADDRESS(KZM_ARM11_CTL1));
+
+	return platform_device_register(&serial_device);
+}
+#else
+static inline int kzm_init_ext_uart(void)
+{
+	return 0;
+}
+#endif
+
+/*
+ * SMSC LAN9118
+ */
+#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
+static struct smsc911x_platform_config kzm_smsc9118_config = {
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
+};
+
+static struct resource kzm_smsc9118_resources[] = {
+	{
+		.start	= MX31_CS5_BASE_ADDR,
+		.end	= MX31_CS5_BASE_ADDR + SZ_128K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_2),
+		.end	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_2),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	},
+};
+
+static struct platform_device kzm_smsc9118_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(kzm_smsc9118_resources),
+	.resource	= kzm_smsc9118_resources,
+	.dev		= {
+				.platform_data = &kzm_smsc9118_config,
+			  },
+};
+
+static int __init kzm_init_smsc9118(void)
+{
+	/*
+	 * GPIO 1-2: SMSC9118 interrupt line
+	 */
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_GPIO1_2, IOMUX_CONFIG_GPIO));
+	gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2), "smsc9118-int");
+	gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2));
+
+	return platform_device_register(&kzm_smsc9118_device);
+}
+#else
+static inline int kzm_init_smsc9118(void)
+{
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static void __init kzm_init_imx_uart(void)
+{
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+}
+#else
+static inline void kzm_init_imx_uart(void)
+{
+}
+#endif
+
+static int kzm_pins[] __initdata = {
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+	MX31_PIN_DCD_DCE1__DCD_DCE1,
+	MX31_PIN_RI_DCE1__RI_DCE1,
+	MX31_PIN_DSR_DCE1__DSR_DCE1,
+	MX31_PIN_DTR_DCE1__DTR_DCE1,
+	MX31_PIN_CTS2__CTS2,
+	MX31_PIN_RTS2__RTS2,
+	MX31_PIN_TXD2__TXD2,
+	MX31_PIN_RXD2__RXD2,
+	MX31_PIN_DCD_DTE1__DCD_DTE2,
+	MX31_PIN_RI_DTE1__RI_DTE2,
+	MX31_PIN_DSR_DTE1__DSR_DTE2,
+	MX31_PIN_DTR_DTE1__DTR_DTE2,
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init kzm_board_init(void)
+{
+	mxc_iomux_setup_multiple_pins(kzm_pins,
+				      ARRAY_SIZE(kzm_pins), "kzm");
+	kzm_init_ext_uart();
+	kzm_init_smsc9118();
+	kzm_init_imx_uart();
+
+	pr_info("Clock input source is 26MHz\n");
+}
+
+/*
+ * This structure defines static mappings for the kzm-arm11-01 board.
+ */
+static struct map_desc kzm_io_desc[] __initdata = {
+	{
+		.virtual	= MX31_CS4_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(MX31_CS4_BASE_ADDR),
+		.length		= MX31_CS4_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= MX31_CS5_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(MX31_CS5_BASE_ADDR),
+		.length		= MX31_CS5_SIZE,
+		.type		= MT_DEVICE
+	},
+};
+
+/*
+ * Set up static virtual mappings.
+ */
+static void __init kzm_map_io(void)
+{
+	mx31_map_io();
+	iotable_init(kzm_io_desc, ARRAY_SIZE(kzm_io_desc));
+}
+
+static void __init kzm_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer kzm_timer = {
+	.init   = kzm_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros define in arch.h in order to
+ * initialize __mach_desc_KZM_ARM11_01 data structure.
+ */
+MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
+	.phys_io        = MX31_AIPS1_BASE_ADDR,
+	.io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
+	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
+	.map_io         = kzm_map_io,
+	.init_irq       = mx31_init_irq,
+	.init_machine   = kzm_board_init,
+	.timer          = &kzm_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
new file mode 100644
index 0000000..b88c18a
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
@@ -0,0 +1,266 @@
+/*
+ *  Copyright 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+#include <linux/platform_device.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/board-mx31pdk.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include "devices.h"
+
+/*!
+ * @file mx31pdk.c
+ *
+ * @brief This file contains the board-specific initialization routines.
+ *
+ * @ingroup System
+ */
+
+static int mx31pdk_pins[] = {
+	/* UART1 */
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+	IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO),
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+/*
+ * Support for the SMSC9217 on the Debug board.
+ */
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+};
+
+static struct resource smsc911x_resources[] = {
+	{
+		.start		= LAN9217_BASE_ADDR,
+		.end		= LAN9217_BASE_ADDR + 0xff,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= EXPIO_INT_ENET,
+		.end		= EXPIO_INT_ENET,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smsc911x_resources),
+	.resource	= smsc911x_resources,
+	.dev		= {
+		.platform_data = &smsc911x_config,
+	},
+};
+
+/*
+ * Routines for the CPLD on the debug board. It contains a CPLD handling
+ * LEDs, switches, interrupts for Ethernet.
+ */
+
+static void mx31pdk_expio_irq_handler(uint32_t irq, struct irq_desc *desc)
+{
+	uint32_t imr_val;
+	uint32_t int_valid;
+	uint32_t expio_irq;
+
+	imr_val = __raw_readw(CPLD_INT_MASK_REG);
+	int_valid = __raw_readw(CPLD_INT_STATUS_REG) & ~imr_val;
+
+	expio_irq = MXC_EXP_IO_BASE;
+	for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
+		if ((int_valid & 1) == 0)
+			continue;
+		generic_handle_irq(expio_irq);
+	}
+}
+
+/*
+ * Disable an expio pin's interrupt by setting the bit in the imr.
+ * @param irq           an expio virtual irq number
+ */
+static void expio_mask_irq(uint32_t irq)
+{
+	uint16_t reg;
+	uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
+
+	/* mask the interrupt */
+	reg = __raw_readw(CPLD_INT_MASK_REG);
+	reg |= 1 << expio;
+	__raw_writew(reg, CPLD_INT_MASK_REG);
+}
+
+/*
+ * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
+ * @param irq           an expanded io virtual irq number
+ */
+static void expio_ack_irq(uint32_t irq)
+{
+	uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
+
+	/* clear the interrupt status */
+	__raw_writew(1 << expio, CPLD_INT_RESET_REG);
+	__raw_writew(0, CPLD_INT_RESET_REG);
+	/* mask the interrupt */
+	expio_mask_irq(irq);
+}
+
+/*
+ * Enable a expio pin's interrupt by clearing the bit in the imr.
+ * @param irq           a expio virtual irq number
+ */
+static void expio_unmask_irq(uint32_t irq)
+{
+	uint16_t reg;
+	uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
+
+	/* unmask the interrupt */
+	reg = __raw_readw(CPLD_INT_MASK_REG);
+	reg &= ~(1 << expio);
+	__raw_writew(reg, CPLD_INT_MASK_REG);
+}
+
+static struct irq_chip expio_irq_chip = {
+	.ack = expio_ack_irq,
+	.mask = expio_mask_irq,
+	.unmask = expio_unmask_irq,
+};
+
+static int __init mx31pdk_init_expio(void)
+{
+	int i;
+	int ret;
+
+	/* Check if there's a debug board connected */
+	if ((__raw_readw(CPLD_MAGIC_NUMBER1_REG) != 0xAAAA) ||
+	    (__raw_readw(CPLD_MAGIC_NUMBER2_REG) != 0x5555) ||
+	    (__raw_readw(CPLD_MAGIC_NUMBER3_REG) != 0xCAFE)) {
+		/* No Debug board found */
+		return -ENODEV;
+	}
+
+	pr_info("i.MX31PDK Debug board detected, rev = 0x%04X\n",
+		__raw_readw(CPLD_CODE_VER_REG));
+
+	/*
+	 * Configure INT line as GPIO input
+	 */
+	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1), "sms9217-irq");
+	if (ret)
+		pr_warning("could not get LAN irq gpio\n");
+	else
+		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
+
+	/* Disable the interrupts and clear the status */
+	__raw_writew(0, CPLD_INT_MASK_REG);
+	__raw_writew(0xFFFF, CPLD_INT_RESET_REG);
+	__raw_writew(0, CPLD_INT_RESET_REG);
+	__raw_writew(0x1F, CPLD_INT_MASK_REG);
+	for (i = MXC_EXP_IO_BASE;
+	     i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES);
+	     i++) {
+		set_irq_chip(i, &expio_irq_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+	set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_LOW);
+	set_irq_chained_handler(EXPIO_PARENT_INT, mx31pdk_expio_irq_handler);
+
+	return 0;
+}
+
+/*
+ * This structure defines the MX31 memory map.
+ */
+static struct map_desc mx31pdk_io_desc[] __initdata = {
+	{
+		.virtual = MX31_CS5_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(MX31_CS5_BASE_ADDR),
+		.length = MX31_CS5_SIZE,
+		.type = MT_DEVICE,
+	},
+};
+
+/*
+ * Set up static virtual mappings.
+ */
+static void __init mx31pdk_map_io(void)
+{
+	mx31_map_io();
+	iotable_init(mx31pdk_io_desc, ARRAY_SIZE(mx31pdk_io_desc));
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	mxc_iomux_setup_multiple_pins(mx31pdk_pins, ARRAY_SIZE(mx31pdk_pins),
+				      "mx31pdk");
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+
+	if (!mx31pdk_init_expio())
+		platform_device_register(&smsc911x_device);
+}
+
+static void __init mx31pdk_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer mx31pdk_timer = {
+	.init	= mx31pdk_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros defined in arch.h in order to
+ * initialize __mach_desc_MX31PDK data structure.
+ */
+MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
+	/* Maintainer: Freescale Semiconductor, Inc. */
+	.phys_io	= MX31_AIPS1_BASE_ADDR,
+	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
+	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
+	.map_io         = mx31pdk_map_io,
+	.init_irq       = mx31_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &mx31pdk_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-mx31ads.c b/arch/arm/mach-mx3/mach-mx31ads.c
new file mode 100644
index 0000000..b3d1a18
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-mx31ads.c
@@ -0,0 +1,559 @@
+/*
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2005-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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/serial_8250.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/irq.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/board-mx31ads.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+#include <linux/mfd/wm8350/audio.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/pmic.h>
+#endif
+
+#include "devices.h"
+
+/*!
+ * @file mx31ads.c
+ *
+ * @brief This file contains the board-specific initialization routines.
+ *
+ * @ingroup System
+ */
+
+#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+/*!
+ * The serial port definition structure.
+ */
+static struct plat_serial8250_port serial_platform_data[] = {
+	{
+		.membase  = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTA),
+		.mapbase  = (unsigned long)(MX31_CS4_BASE_ADDR + PBC_SC16C652_UARTA),
+		.irq      = EXPIO_INT_XUART_INTA,
+		.uartclk  = 14745600,
+		.regshift = 0,
+		.iotype   = UPIO_MEM,
+		.flags    = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ,
+	}, {
+		.membase  = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTB),
+		.mapbase  = (unsigned long)(MX31_CS4_BASE_ADDR + PBC_SC16C652_UARTB),
+		.irq      = EXPIO_INT_XUART_INTB,
+		.uartclk  = 14745600,
+		.regshift = 0,
+		.iotype   = UPIO_MEM,
+		.flags    = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ,
+	},
+	{},
+};
+
+static struct platform_device serial_device = {
+	.name	= "serial8250",
+	.id	= 0,
+	.dev	= {
+		.platform_data = serial_platform_data,
+	},
+};
+
+static int __init mxc_init_extuart(void)
+{
+	return platform_device_register(&serial_device);
+}
+#else
+static inline int mxc_init_extuart(void)
+{
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static unsigned int uart_pins[] = {
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1
+};
+
+static inline void mxc_init_imx_uart(void)
+{
+	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0");
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+}
+#else /* !SERIAL_IMX */
+static inline void mxc_init_imx_uart(void)
+{
+}
+#endif /* !SERIAL_IMX */
+
+static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+	u32 imr_val;
+	u32 int_valid;
+	u32 expio_irq;
+
+	imr_val = __raw_readw(PBC_INTMASK_SET_REG);
+	int_valid = __raw_readw(PBC_INTSTATUS_REG) & imr_val;
+
+	expio_irq = MXC_EXP_IO_BASE;
+	for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
+		if ((int_valid & 1) == 0)
+			continue;
+
+		generic_handle_irq(expio_irq);
+	}
+}
+
+/*
+ * Disable an expio pin's interrupt by setting the bit in the imr.
+ * @param irq           an expio virtual irq number
+ */
+static void expio_mask_irq(u32 irq)
+{
+	u32 expio = MXC_IRQ_TO_EXPIO(irq);
+	/* mask the interrupt */
+	__raw_writew(1 << expio, PBC_INTMASK_CLEAR_REG);
+	__raw_readw(PBC_INTMASK_CLEAR_REG);
+}
+
+/*
+ * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
+ * @param irq           an expanded io virtual irq number
+ */
+static void expio_ack_irq(u32 irq)
+{
+	u32 expio = MXC_IRQ_TO_EXPIO(irq);
+	/* clear the interrupt status */
+	__raw_writew(1 << expio, PBC_INTSTATUS_REG);
+}
+
+/*
+ * Enable a expio pin's interrupt by clearing the bit in the imr.
+ * @param irq           a expio virtual irq number
+ */
+static void expio_unmask_irq(u32 irq)
+{
+	u32 expio = MXC_IRQ_TO_EXPIO(irq);
+	/* unmask the interrupt */
+	__raw_writew(1 << expio, PBC_INTMASK_SET_REG);
+}
+
+static struct irq_chip expio_irq_chip = {
+	.name = "EXPIO(CPLD)",
+	.ack = expio_ack_irq,
+	.mask = expio_mask_irq,
+	.unmask = expio_unmask_irq,
+};
+
+static void __init mx31ads_init_expio(void)
+{
+	int i;
+
+	printk(KERN_INFO "MX31ADS EXPIO(CPLD) hardware\n");
+
+	/*
+	 * Configure INT line as GPIO input
+	 */
+	mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO), "expio");
+
+	/* disable the interrupt and clear the status */
+	__raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG);
+	__raw_writew(0xFFFF, PBC_INTSTATUS_REG);
+	for (i = MXC_EXP_IO_BASE; i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES);
+	     i++) {
+		set_irq_chip(i, &expio_irq_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+	set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_HIGH);
+	set_irq_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
+}
+
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+/* This section defines setup for the Wolfson Microelectronics
+ * 1133-EV1 PMU/audio board.  When other PMU boards are supported the
+ * regulator definitions may be shared with them, but for now they can
+ * only be used with this board so would generate warnings about
+ * unused statics and some of the configuration is specific to this
+ * module.
+ */
+
+/* CPU */
+static struct regulator_consumer_supply sw1a_consumers[] = {
+	{
+		.supply = "cpu_vcc",
+	}
+};
+
+static struct regulator_init_data sw1a_data = {
+	.constraints = {
+		.name = "SW1A",
+		.min_uV = 1275000,
+		.max_uV = 1600000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_MODE,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+				    REGULATOR_MODE_FAST,
+		.state_mem = {
+			 .uV = 1400000,
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 1,
+		 },
+		.initial_state = PM_SUSPEND_MEM,
+		.always_on = 1,
+		.boot_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(sw1a_consumers),
+	.consumer_supplies = sw1a_consumers,
+};
+
+/* System IO - High */
+static struct regulator_init_data viohi_data = {
+	.constraints = {
+		.name = "VIOHO",
+		.min_uV = 2800000,
+		.max_uV = 2800000,
+		.state_mem = {
+			 .uV = 2800000,
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 1,
+		 },
+		.initial_state = PM_SUSPEND_MEM,
+		.always_on = 1,
+		.boot_on = 1,
+	},
+};
+
+/* System IO - Low */
+static struct regulator_init_data violo_data = {
+	.constraints = {
+		.name = "VIOLO",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.state_mem = {
+			 .uV = 1800000,
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 1,
+		 },
+		.initial_state = PM_SUSPEND_MEM,
+		.always_on = 1,
+		.boot_on = 1,
+	},
+};
+
+/* DDR RAM */
+static struct regulator_init_data sw2a_data = {
+	.constraints = {
+		.name = "SW2A",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.state_mem = {
+			 .uV = 1800000,
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 1,
+		 },
+		.state_disk = {
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 0,
+		 },
+		.always_on = 1,
+		.boot_on = 1,
+		.initial_state = PM_SUSPEND_MEM,
+	},
+};
+
+static struct regulator_init_data ldo1_data = {
+	.constraints = {
+		.name = "VCAM/VMMC1/VMMC2",
+		.min_uV = 2800000,
+		.max_uV = 2800000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.apply_uV = 1,
+	},
+};
+
+static struct regulator_consumer_supply ldo2_consumers[] = {
+	{ .supply = "AVDD", .dev_name = "1-001a" },
+	{ .supply = "HPVDD", .dev_name = "1-001a" },
+};
+
+/* CODEC and SIM */
+static struct regulator_init_data ldo2_data = {
+	.constraints = {
+		.name = "VESIM/VSIM/AVDD",
+		.min_uV = 3300000,
+		.max_uV = 3300000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.apply_uV = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(ldo2_consumers),
+	.consumer_supplies = ldo2_consumers,
+};
+
+/* General */
+static struct regulator_init_data vdig_data = {
+	.constraints = {
+		.name = "VDIG",
+		.min_uV = 1500000,
+		.max_uV = 1500000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.apply_uV = 1,
+		.always_on = 1,
+		.boot_on = 1,
+	},
+};
+
+/* Tranceivers */
+static struct regulator_init_data ldo4_data = {
+	.constraints = {
+		.name = "VRF1/CVDD_2.775",
+		.min_uV = 2500000,
+		.max_uV = 2500000,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL,
+		.apply_uV = 1,
+		.always_on = 1,
+		.boot_on = 1,
+	},
+};
+
+static struct wm8350_led_platform_data wm8350_led_data = {
+	.name            = "wm8350:white",
+	.default_trigger = "heartbeat",
+	.max_uA          = 27899,
+};
+
+static struct wm8350_audio_platform_data imx32ads_wm8350_setup = {
+	.vmid_discharge_msecs = 1000,
+	.drain_msecs = 30,
+	.cap_discharge_msecs = 700,
+	.vmid_charge_msecs = 700,
+	.vmid_s_curve = WM8350_S_CURVE_SLOW,
+	.dis_out4 = WM8350_DISCHARGE_SLOW,
+	.dis_out3 = WM8350_DISCHARGE_SLOW,
+	.dis_out2 = WM8350_DISCHARGE_SLOW,
+	.dis_out1 = WM8350_DISCHARGE_SLOW,
+	.vroi_out4 = WM8350_TIE_OFF_500R,
+	.vroi_out3 = WM8350_TIE_OFF_500R,
+	.vroi_out2 = WM8350_TIE_OFF_500R,
+	.vroi_out1 = WM8350_TIE_OFF_500R,
+	.vroi_enable = 0,
+	.codec_current_on = WM8350_CODEC_ISEL_1_0,
+	.codec_current_standby = WM8350_CODEC_ISEL_0_5,
+	.codec_current_charge = WM8350_CODEC_ISEL_1_5,
+};
+
+static int mx31_wm8350_init(struct wm8350 *wm8350)
+{
+	wm8350_gpio_config(wm8350, 0, WM8350_GPIO_DIR_IN,
+			   WM8350_GPIO0_PWR_ON_IN, WM8350_GPIO_ACTIVE_LOW,
+			   WM8350_GPIO_PULL_UP, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_ON);
+
+	wm8350_gpio_config(wm8350, 3, WM8350_GPIO_DIR_IN,
+			   WM8350_GPIO3_PWR_OFF_IN, WM8350_GPIO_ACTIVE_HIGH,
+			   WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_ON);
+
+	wm8350_gpio_config(wm8350, 4, WM8350_GPIO_DIR_IN,
+			   WM8350_GPIO4_MR_IN, WM8350_GPIO_ACTIVE_HIGH,
+			   WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_OFF);
+
+	wm8350_gpio_config(wm8350, 7, WM8350_GPIO_DIR_IN,
+			   WM8350_GPIO7_HIBERNATE_IN, WM8350_GPIO_ACTIVE_HIGH,
+			   WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_OFF);
+
+	wm8350_gpio_config(wm8350, 6, WM8350_GPIO_DIR_OUT,
+			   WM8350_GPIO6_SDOUT_OUT, WM8350_GPIO_ACTIVE_HIGH,
+			   WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_OFF);
+
+	wm8350_gpio_config(wm8350, 8, WM8350_GPIO_DIR_OUT,
+			   WM8350_GPIO8_VCC_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW,
+			   WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_OFF);
+
+	wm8350_gpio_config(wm8350, 9, WM8350_GPIO_DIR_OUT,
+			   WM8350_GPIO9_BATT_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW,
+			   WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
+			   WM8350_GPIO_DEBOUNCE_OFF);
+
+	wm8350_register_regulator(wm8350, WM8350_DCDC_1, &sw1a_data);
+	wm8350_register_regulator(wm8350, WM8350_DCDC_3, &viohi_data);
+	wm8350_register_regulator(wm8350, WM8350_DCDC_4, &violo_data);
+	wm8350_register_regulator(wm8350, WM8350_DCDC_6, &sw2a_data);
+	wm8350_register_regulator(wm8350, WM8350_LDO_1, &ldo1_data);
+	wm8350_register_regulator(wm8350, WM8350_LDO_2, &ldo2_data);
+	wm8350_register_regulator(wm8350, WM8350_LDO_3, &vdig_data);
+	wm8350_register_regulator(wm8350, WM8350_LDO_4, &ldo4_data);
+
+	/* LEDs */
+	wm8350_dcdc_set_slot(wm8350, WM8350_DCDC_5, 1, 1,
+			     WM8350_DC5_ERRACT_SHUTDOWN_CONV);
+	wm8350_isink_set_flash(wm8350, WM8350_ISINK_A,
+			       WM8350_ISINK_FLASH_DISABLE,
+			       WM8350_ISINK_FLASH_TRIG_BIT,
+			       WM8350_ISINK_FLASH_DUR_32MS,
+			       WM8350_ISINK_FLASH_ON_INSTANT,
+			       WM8350_ISINK_FLASH_OFF_INSTANT,
+			       WM8350_ISINK_FLASH_MODE_EN);
+	wm8350_dcdc25_set_mode(wm8350, WM8350_DCDC_5,
+			       WM8350_ISINK_MODE_BOOST,
+			       WM8350_ISINK_ILIM_NORMAL,
+			       WM8350_DC5_RMP_20V,
+			       WM8350_DC5_FBSRC_ISINKA);
+	wm8350_register_led(wm8350, 0, WM8350_DCDC_5, WM8350_ISINK_A,
+			    &wm8350_led_data);
+
+	wm8350->codec.platform_data = &imx32ads_wm8350_setup;
+
+	regulator_has_full_constraints();
+
+	return 0;
+}
+
+static struct wm8350_platform_data __initdata mx31_wm8350_pdata = {
+	.init = mx31_wm8350_init,
+	.irq_base = MXC_BOARD_IRQ_START + MXC_MAX_EXP_IO_LINES,
+};
+#endif
+
+#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
+static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = {
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+	{
+		I2C_BOARD_INFO("wm8350", 0x1a),
+		.platform_data = &mx31_wm8350_pdata,
+		.irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+	},
+#endif
+};
+
+static void mxc_init_i2c(void)
+{
+	i2c_register_board_info(1, mx31ads_i2c1_devices,
+				ARRAY_SIZE(mx31ads_i2c1_devices));
+
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_ALT1));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_ALT1));
+
+	mxc_register_device(&mxc_i2c_device1, NULL);
+}
+#else
+static void mxc_init_i2c(void)
+{
+}
+#endif
+
+static unsigned int ssi_pins[] = {
+	MX31_PIN_SFS5__SFS5,
+	MX31_PIN_SCK5__SCK5,
+	MX31_PIN_SRXD5__SRXD5,
+	MX31_PIN_STXD5__STXD5,
+};
+
+static void mxc_init_audio(void)
+{
+	mxc_register_device(&imx_ssi_device0, NULL);
+	mxc_iomux_setup_multiple_pins(ssi_pins, ARRAY_SIZE(ssi_pins), "ssi");
+}
+
+/*!
+ * This structure defines static mappings for the i.MX31ADS board.
+ */
+static struct map_desc mx31ads_io_desc[] __initdata = {
+	{
+		.virtual	= MX31_CS4_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(MX31_CS4_BASE_ADDR),
+		.length		= MX31_CS4_SIZE / 2,
+		.type		= MT_DEVICE
+	},
+};
+
+/*!
+ * Set up static virtual mappings.
+ */
+static void __init mx31ads_map_io(void)
+{
+	mx31_map_io();
+	iotable_init(mx31ads_io_desc, ARRAY_SIZE(mx31ads_io_desc));
+}
+
+static void __init mx31ads_init_irq(void)
+{
+	mx31_init_irq();
+	mx31ads_init_expio();
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	mxc_init_extuart();
+	mxc_init_imx_uart();
+	mxc_init_i2c();
+	mxc_init_audio();
+}
+
+static void __init mx31ads_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer mx31ads_timer = {
+	.init	= mx31ads_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros defined in arch.h in order to
+ * initialize __mach_desc_MX31ADS data structure.
+ */
+MACHINE_START(MX31ADS, "Freescale MX31ADS")
+	/* Maintainer: Freescale Semiconductor, Inc. */
+	.phys_io	= MX31_AIPS1_BASE_ADDR,
+	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
+	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
+	.map_io         = mx31ads_map_io,
+	.init_irq       = mx31ads_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &mx31ads_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-mx31lilly.c b/arch/arm/mach-mx3/mach-mx31lilly.c
new file mode 100644
index 0000000..80847b0
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-mx31lilly.c
@@ -0,0 +1,206 @@
+/*
+ *  LILLY-1131 module support
+ *
+ *    Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ *  based on code for other MX31 boards,
+ *
+ *    Copyright 2005-2007 Freescale Semiconductor
+ *    Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
+ *    Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/smsc911x.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13783.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx3.h>
+#include <mach/board-mx31lilly.h>
+#include <mach/spi.h>
+
+#include "devices.h"
+
+/*
+ * This file contains module-specific initialization routines for LILLY-1131.
+ * Initialization of peripherals found on the baseboard is implemented in the
+ * appropriate baseboard support code.
+ */
+
+/* SMSC ethernet support */
+
+static struct resource smsc91x_resources[] = {
+	{
+		.start	= MX31_CS4_BASE_ADDR,
+		.end	= MX31_CS4_BASE_ADDR + 0xffff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+		.end	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
+	}
+};
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags		= SMSC911X_USE_32BIT |
+			  SMSC911X_SAVE_MAC_ADDRESS |
+			  SMSC911X_FORCE_INTERNAL_PHY,
+};
+
+static struct platform_device smsc91x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smsc91x_resources),
+	.resource	= smsc91x_resources,
+	.dev		= {
+		.platform_data = &smsc911x_config,
+	}
+};
+
+/* NOR flash */
+static struct physmap_flash_data nor_flash_data = {
+	.width  = 2,
+};
+
+static struct resource nor_flash_resource = {
+	.start	= 0xa0000000,
+	.end	= 0xa1ffffff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device physmap_flash_device = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &nor_flash_data,
+	},
+	.resource = &nor_flash_resource,
+	.num_resources = 1,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&smsc91x_device,
+	&physmap_flash_device,
+};
+
+/* SPI */
+
+static int spi_internal_chipselect[] = {
+	MXC_SPI_CS(0),
+	MXC_SPI_CS(1),
+	MXC_SPI_CS(2),
+};
+
+static struct spi_imx_master spi0_pdata = {
+	.chipselect = spi_internal_chipselect,
+	.num_chipselect = ARRAY_SIZE(spi_internal_chipselect),
+};
+
+static struct spi_imx_master spi1_pdata = {
+	.chipselect = spi_internal_chipselect,
+	.num_chipselect = ARRAY_SIZE(spi_internal_chipselect),
+};
+
+static struct mc13783_platform_data mc13783_pdata __initdata = {
+	.flags = MC13783_USE_RTC | MC13783_USE_TOUCHSCREEN,
+};
+
+static struct spi_board_info mc13783_dev __initdata = {
+	.modalias	= "mc13783",
+	.max_speed_hz	= 1000000,
+	.bus_num	= 1,
+	.chip_select	= 0,
+	.platform_data	= &mc13783_pdata,
+};
+
+static int mx31lilly_baseboard;
+core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444);
+
+static void __init mx31lilly_board_init(void)
+{
+	switch (mx31lilly_baseboard) {
+	case MX31LILLY_NOBOARD:
+		break;
+	case MX31LILLY_DB:
+		mx31lilly_db_init();
+		break;
+	default:
+		printk(KERN_ERR "Illegal mx31lilly_baseboard type %d\n",
+			mx31lilly_baseboard);
+	}
+
+	mxc_iomux_alloc_pin(MX31_PIN_CS4__CS4, "Ethernet CS");
+
+	/* SPI */
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_SCLK__SCLK, "SPI1_CLK");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_MOSI__MOSI, "SPI1_TX");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_MISO__MISO, "SPI1_RX");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_SPI_RDY__SPI_RDY, "SPI1_RDY");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_SS0__SS0, "SPI1_SS0");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_SS1__SS1, "SPI1_SS1");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_SS2__SS2, "SPI1_SS2");
+
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SCLK__SCLK, "SPI2_CLK");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_MOSI__MOSI, "SPI2_TX");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_MISO__MISO, "SPI2_RX");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SPI_RDY__SPI_RDY, "SPI2_RDY");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SS0__SS0, "SPI2_SS0");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SS1__SS1, "SPI2_SS1");
+	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SS2__SS2, "SPI2_SS2");
+
+	mxc_register_device(&mxc_spi_device0, &spi0_pdata);
+	mxc_register_device(&mxc_spi_device1, &spi1_pdata);
+	spi_register_board_info(&mc13783_dev, 1);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static void __init mx31lilly_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer mx31lilly_timer = {
+	.init	= mx31lilly_timer_init,
+};
+
+MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
+	.phys_io	= MX31_AIPS1_BASE_ADDR,
+	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
+	.boot_params	= MX3x_PHYS_OFFSET + 0x100,
+	.map_io		= mx31_map_io,
+	.init_irq	= mx31_init_irq,
+	.init_machine	= mx31lilly_board_init,
+	.timer		= &mx31lilly_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-mx3/mach-mx31lite.c b/arch/arm/mach-mx3/mach-mx31lite.c
new file mode 100644
index 0000000..2b6d114
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-mx31lite.c
@@ -0,0 +1,297 @@
+/*
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *  Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/memory.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/spi/spi.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/board-mx31lite.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include <mach/irqs.h>
+#include <mach/mxc_nand.h>
+#include <mach/spi.h>
+#include <mach/mxc_ehci.h>
+#include <mach/ulpi.h>
+
+#include "devices.h"
+
+/*
+ * This file contains the module-specific initialization routines.
+ */
+
+static unsigned int mx31lite_pins[] = {
+	/* LAN9117 IRQ pin */
+	IOMUX_MODE(MX31_PIN_SFS6, IOMUX_CONFIG_GPIO),
+	/* SPI 1 */
+	MX31_PIN_CSPI2_SCLK__SCLK,
+	MX31_PIN_CSPI2_MOSI__MOSI,
+	MX31_PIN_CSPI2_MISO__MISO,
+	MX31_PIN_CSPI2_SPI_RDY__SPI_RDY,
+	MX31_PIN_CSPI2_SS0__SS0,
+	MX31_PIN_CSPI2_SS1__SS1,
+	MX31_PIN_CSPI2_SS2__SS2,
+};
+
+static struct mxc_nand_platform_data mx31lite_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_16BIT,
+};
+
+static struct resource smsc911x_resources[] = {
+	{
+		.start		= MX31_CS4_BASE_ADDR,
+		.end		= MX31_CS4_BASE_ADDR + 0x100,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= IOMUX_TO_IRQ(MX31_PIN_SFS6),
+		.end		= IOMUX_TO_IRQ(MX31_PIN_SFS6),
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smsc911x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smsc911x_resources),
+	.resource	= smsc911x_resources,
+	.dev		= {
+		.platform_data = &smsc911x_config,
+	},
+};
+
+/*
+ * SPI
+ *
+ * The MC13783 is the only hard-wired SPI device on the module.
+ */
+
+static int spi_internal_chipselect[] = {
+	MXC_SPI_CS(0),
+};
+
+static struct spi_imx_master spi1_pdata = {
+	.chipselect	= spi_internal_chipselect,
+	.num_chipselect	= ARRAY_SIZE(spi_internal_chipselect),
+};
+
+static struct mc13783_platform_data mc13783_pdata __initdata = {
+	.flags  = MC13783_USE_RTC |
+		  MC13783_USE_REGULATOR,
+};
+
+static struct spi_board_info mc13783_spi_dev __initdata = {
+	.modalias       = "mc13783",
+	.max_speed_hz   = 1000000,
+	.bus_num	= 1,
+	.chip_select    = 0,
+	.platform_data  = &mc13783_pdata,
+	.irq		= IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+};
+
+/*
+ * USB
+ */
+
+#if defined(CONFIG_USB_ULPI)
+#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
+			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
+
+static int usbh2_init(struct platform_device *pdev)
+{
+	int pins[] = {
+		MX31_PIN_USBH2_DATA0__USBH2_DATA0,
+		MX31_PIN_USBH2_DATA1__USBH2_DATA1,
+		MX31_PIN_USBH2_CLK__USBH2_CLK,
+		MX31_PIN_USBH2_DIR__USBH2_DIR,
+		MX31_PIN_USBH2_NXT__USBH2_NXT,
+		MX31_PIN_USBH2_STP__USBH2_STP,
+	};
+
+	mxc_iomux_setup_multiple_pins(pins, ARRAY_SIZE(pins), "USB H2");
+
+	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_SRXD6, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_STXD6, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SFS3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SCK3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SRXD3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_STXD3, USB_PAD_CFG);
+
+	mxc_iomux_set_gpr(MUX_PGP_UH2, true);
+
+	/* chip select */
+	mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_GPIO),
+				"USBH2_CS");
+	gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), "USBH2 CS");
+	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), 0);
+
+	return 0;
+}
+
+static struct mxc_usbh_platform_data usbh2_pdata = {
+	.init   = usbh2_init,
+	.portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
+	.flags  = MXC_EHCI_POWER_PINS_ENABLED,
+};
+#endif
+
+/*
+ * NOR flash
+ */
+
+static struct physmap_flash_data nor_flash_data = {
+	.width  = 2,
+};
+
+static struct resource nor_flash_resource = {
+	.start  = 0xa0000000,
+	.end    = 0xa1ffffff,
+	.flags  = IORESOURCE_MEM,
+};
+
+static struct platform_device physmap_flash_device = {
+	.name   = "physmap-flash",
+	.id     = 0,
+	.dev    = {
+		.platform_data  = &nor_flash_data,
+	},
+	.resource = &nor_flash_resource,
+	.num_resources = 1,
+};
+
+
+
+/*
+ * This structure defines the MX31 memory map.
+ */
+static struct map_desc mx31lite_io_desc[] __initdata = {
+	{
+		.virtual = MX31_CS4_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(MX31_CS4_BASE_ADDR),
+		.length = MX31_CS4_SIZE,
+		.type = MT_DEVICE
+	}
+};
+
+/*
+ * Set up static virtual mappings.
+ */
+void __init mx31lite_map_io(void)
+{
+	mx31_map_io();
+	iotable_init(mx31lite_io_desc, ARRAY_SIZE(mx31lite_io_desc));
+}
+
+static int mx31lite_baseboard;
+core_param(mx31lite_baseboard, mx31lite_baseboard, int, 0444);
+
+static void __init mxc_board_init(void)
+{
+	int ret;
+
+	switch (mx31lite_baseboard) {
+	case MX31LITE_NOBOARD:
+		break;
+	case MX31LITE_DB:
+		mx31lite_db_init();
+		break;
+	default:
+		printk(KERN_ERR "Illegal mx31lite_baseboard type %d\n",
+				mx31lite_baseboard);
+	}
+
+	mxc_iomux_setup_multiple_pins(mx31lite_pins, ARRAY_SIZE(mx31lite_pins),
+				      "mx31lite");
+
+	/* NOR and NAND flash */
+	platform_device_register(&physmap_flash_device);
+	mxc_register_device(&mxc_nand_device, &mx31lite_nand_board_info);
+
+	mxc_register_device(&mxc_spi_device1, &spi1_pdata);
+	spi_register_board_info(&mc13783_spi_dev, 1);
+
+#if defined(CONFIG_USB_ULPI)
+	/* USB */
+	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+
+	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+#endif
+
+	/* SMSC9117 IRQ pin */
+	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_SFS6), "sms9117-irq");
+	if (ret)
+		pr_warning("could not get LAN irq gpio\n");
+	else {
+		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_SFS6));
+		platform_device_register(&smsc911x_device);
+	}
+}
+
+static void __init mx31lite_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+struct sys_timer mx31lite_timer = {
+	.init	= mx31lite_timer_init,
+};
+
+MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
+	/* Maintainer: Freescale Semiconductor, Inc. */
+	.phys_io        = MX31_AIPS1_BASE_ADDR,
+	.io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
+	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
+	.map_io         = mx31lite_map_io,
+	.init_irq       = mx31_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &mx31lite_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c
new file mode 100644
index 0000000..a7dc519
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-mx31moboard.c
@@ -0,0 +1,551 @@
+/*
+ *  Copyright (C) 2008 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/dma-mapping.h>
+#include <linux/fsl_devices.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/leds.h>
+#include <linux/memory.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <mach/board-mx31moboard.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include <mach/ipu.h>
+#include <mach/i2c.h>
+#include <mach/mmc.h>
+#include <mach/mxc_ehci.h>
+#include <mach/mx3_camera.h>
+#include <mach/spi.h>
+#include <mach/ulpi.h>
+
+#include "devices.h"
+
+static unsigned int moboard_pins[] = {
+	/* UART0 */
+	MX31_PIN_TXD1__TXD1, MX31_PIN_RXD1__RXD1,
+	MX31_PIN_CTS1__GPIO2_7,
+	/* UART4 */
+	MX31_PIN_PC_RST__CTS5, MX31_PIN_PC_VS2__RTS5,
+	MX31_PIN_PC_BVD2__TXD5, MX31_PIN_PC_BVD1__RXD5,
+	/* I2C0 */
+	MX31_PIN_I2C_DAT__I2C1_SDA, MX31_PIN_I2C_CLK__I2C1_SCL,
+	/* I2C1 */
+	MX31_PIN_DCD_DTE1__I2C2_SDA, MX31_PIN_RI_DTE1__I2C2_SCL,
+	/* SDHC1 */
+	MX31_PIN_SD1_DATA3__SD1_DATA3, MX31_PIN_SD1_DATA2__SD1_DATA2,
+	MX31_PIN_SD1_DATA1__SD1_DATA1, MX31_PIN_SD1_DATA0__SD1_DATA0,
+	MX31_PIN_SD1_CLK__SD1_CLK, MX31_PIN_SD1_CMD__SD1_CMD,
+	MX31_PIN_ATA_CS0__GPIO3_26, MX31_PIN_ATA_CS1__GPIO3_27,
+	/* USB reset */
+	MX31_PIN_GPIO1_0__GPIO1_0,
+	/* USB OTG */
+	MX31_PIN_USBOTG_DATA0__USBOTG_DATA0,
+	MX31_PIN_USBOTG_DATA1__USBOTG_DATA1,
+	MX31_PIN_USBOTG_DATA2__USBOTG_DATA2,
+	MX31_PIN_USBOTG_DATA3__USBOTG_DATA3,
+	MX31_PIN_USBOTG_DATA4__USBOTG_DATA4,
+	MX31_PIN_USBOTG_DATA5__USBOTG_DATA5,
+	MX31_PIN_USBOTG_DATA6__USBOTG_DATA6,
+	MX31_PIN_USBOTG_DATA7__USBOTG_DATA7,
+	MX31_PIN_USBOTG_CLK__USBOTG_CLK, MX31_PIN_USBOTG_DIR__USBOTG_DIR,
+	MX31_PIN_USBOTG_NXT__USBOTG_NXT, MX31_PIN_USBOTG_STP__USBOTG_STP,
+	MX31_PIN_USB_OC__GPIO1_30,
+	/* USB H2 */
+	MX31_PIN_USBH2_DATA0__USBH2_DATA0,
+	MX31_PIN_USBH2_DATA1__USBH2_DATA1,
+	MX31_PIN_STXD3__USBH2_DATA2, MX31_PIN_SRXD3__USBH2_DATA3,
+	MX31_PIN_SCK3__USBH2_DATA4, MX31_PIN_SFS3__USBH2_DATA5,
+	MX31_PIN_STXD6__USBH2_DATA6, MX31_PIN_SRXD6__USBH2_DATA7,
+	MX31_PIN_USBH2_CLK__USBH2_CLK, MX31_PIN_USBH2_DIR__USBH2_DIR,
+	MX31_PIN_USBH2_NXT__USBH2_NXT, MX31_PIN_USBH2_STP__USBH2_STP,
+	MX31_PIN_SCK6__GPIO1_25,
+	/* LEDs */
+	MX31_PIN_SVEN0__GPIO2_0, MX31_PIN_STX0__GPIO2_1,
+	MX31_PIN_SRX0__GPIO2_2, MX31_PIN_SIMPD0__GPIO2_3,
+	/* SPI1 */
+	MX31_PIN_CSPI2_MOSI__MOSI, MX31_PIN_CSPI2_MISO__MISO,
+	MX31_PIN_CSPI2_SCLK__SCLK, MX31_PIN_CSPI2_SPI_RDY__SPI_RDY,
+	MX31_PIN_CSPI2_SS0__SS0, MX31_PIN_CSPI2_SS2__SS2,
+	/* Atlas IRQ */
+	MX31_PIN_GPIO1_3__GPIO1_3,
+	/* SPI2 */
+	MX31_PIN_CSPI3_MOSI__MOSI, MX31_PIN_CSPI3_MISO__MISO,
+	MX31_PIN_CSPI3_SCLK__SCLK, MX31_PIN_CSPI3_SPI_RDY__SPI_RDY,
+	MX31_PIN_CSPI2_SS1__CSPI3_SS1,
+};
+
+static struct physmap_flash_data mx31moboard_flash_data = {
+	.width  	= 2,
+};
+
+static struct resource mx31moboard_flash_resource = {
+	.start	= 0xa0000000,
+	.end	= 0xa1ffffff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device mx31moboard_flash = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &mx31moboard_flash_data,
+	},
+	.resource = &mx31moboard_flash_resource,
+	.num_resources = 1,
+};
+
+static int moboard_uart0_init(struct platform_device *pdev)
+{
+	gpio_request(IOMUX_TO_GPIO(MX31_PIN_CTS1), "uart0-cts-hack");
+	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CTS1), 0);
+	return 0;
+}
+
+static struct imxuart_platform_data uart0_pdata = {
+	.init = moboard_uart0_init,
+};
+
+static struct imxuart_platform_data uart4_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct imxi2c_platform_data moboard_i2c0_pdata = {
+	.bitrate = 400000,
+};
+
+static struct imxi2c_platform_data moboard_i2c1_pdata = {
+	.bitrate = 100000,
+};
+
+static int moboard_spi1_cs[] = {
+	MXC_SPI_CS(0),
+	MXC_SPI_CS(2),
+};
+
+static struct spi_imx_master moboard_spi1_master = {
+	.chipselect	= moboard_spi1_cs,
+	.num_chipselect	= ARRAY_SIZE(moboard_spi1_cs),
+};
+
+static struct regulator_consumer_supply sdhc_consumers[] = {
+	{
+		.dev	= &mxcsdhc_device0.dev,
+		.supply	= "sdhc0_vcc",
+	},
+	{
+		.dev	= &mxcsdhc_device1.dev,
+		.supply	= "sdhc1_vcc",
+	},
+};
+
+static struct regulator_init_data sdhc_vreg_data = {
+	.constraints = {
+		.min_uV = 2700000,
+		.max_uV = 3000000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+			REGULATOR_MODE_FAST,
+		.always_on = 0,
+		.boot_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(sdhc_consumers),
+	.consumer_supplies = sdhc_consumers,
+};
+
+static struct regulator_consumer_supply cam_consumers[] = {
+	{
+		.dev	= &mx3_camera.dev,
+		.supply	= "cam_vcc",
+	},
+};
+
+static struct regulator_init_data cam_vreg_data = {
+	.constraints = {
+		.min_uV = 2700000,
+		.max_uV = 3000000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+		.valid_modes_mask = REGULATOR_MODE_NORMAL |
+			REGULATOR_MODE_FAST,
+		.always_on = 0,
+		.boot_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(cam_consumers),
+	.consumer_supplies = cam_consumers,
+};
+
+static struct mc13783_regulator_init_data moboard_regulators[] = {
+	{
+		.id = MC13783_REGU_VMMC1,
+		.init_data = &sdhc_vreg_data,
+	},
+	{
+		.id = MC13783_REGU_VCAM,
+		.init_data = &cam_vreg_data,
+	},
+};
+
+static struct mc13783_platform_data moboard_pmic = {
+	.regulators = moboard_regulators,
+	.num_regulators = ARRAY_SIZE(moboard_regulators),
+	.flags = MC13783_USE_REGULATOR | MC13783_USE_RTC |
+		MC13783_USE_ADC,
+};
+
+static struct spi_board_info moboard_spi_board_info[] __initdata = {
+	{
+		.modalias = "mc13783",
+		.irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+		.max_speed_hz = 300000,
+		.bus_num = 1,
+		.chip_select = 0,
+		.platform_data = &moboard_pmic,
+		.mode = SPI_CS_HIGH,
+	},
+};
+
+static int moboard_spi2_cs[] = {
+	MXC_SPI_CS(1),
+};
+
+static struct spi_imx_master moboard_spi2_master = {
+	.chipselect	= moboard_spi2_cs,
+	.num_chipselect	= ARRAY_SIZE(moboard_spi2_cs),
+};
+
+#define SDHC1_CD IOMUX_TO_GPIO(MX31_PIN_ATA_CS0)
+#define SDHC1_WP IOMUX_TO_GPIO(MX31_PIN_ATA_CS1)
+
+static int moboard_sdhc1_get_ro(struct device *dev)
+{
+	return !gpio_get_value(SDHC1_WP);
+}
+
+static int moboard_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
+		void *data)
+{
+	int ret;
+
+	ret = gpio_request(SDHC1_CD, "sdhc-detect");
+	if (ret)
+		return ret;
+
+	gpio_direction_input(SDHC1_CD);
+
+	ret = gpio_request(SDHC1_WP, "sdhc-wp");
+	if (ret)
+		goto err_gpio_free;
+	gpio_direction_input(SDHC1_WP);
+
+	ret = request_irq(gpio_to_irq(SDHC1_CD), detect_irq,
+		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		"sdhc1-card-detect", data);
+	if (ret)
+		goto err_gpio_free_2;
+
+	return 0;
+
+err_gpio_free_2:
+	gpio_free(SDHC1_WP);
+err_gpio_free:
+	gpio_free(SDHC1_CD);
+
+	return ret;
+}
+
+static void moboard_sdhc1_exit(struct device *dev, void *data)
+{
+	free_irq(gpio_to_irq(SDHC1_CD), data);
+	gpio_free(SDHC1_WP);
+	gpio_free(SDHC1_CD);
+}
+
+static struct imxmmc_platform_data sdhc1_pdata = {
+	.get_ro	= moboard_sdhc1_get_ro,
+	.init	= moboard_sdhc1_init,
+	.exit	= moboard_sdhc1_exit,
+};
+
+/*
+ * this pin is dedicated for all mx31moboard systems, so we do it here
+ */
+#define USB_RESET_B	IOMUX_TO_GPIO(MX31_PIN_GPIO1_0)
+
+static void usb_xcvr_reset(void)
+{
+	gpio_request(USB_RESET_B, "usb-reset");
+	gpio_direction_output(USB_RESET_B, 0);
+	mdelay(1);
+	gpio_set_value(USB_RESET_B, 1);
+}
+
+#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
+			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
+
+#define OTG_EN_B IOMUX_TO_GPIO(MX31_PIN_USB_OC)
+
+static void moboard_usbotg_init(void)
+{
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, USB_PAD_CFG);
+
+	gpio_request(OTG_EN_B, "usb-udc-en");
+	gpio_direction_output(OTG_EN_B, 0);
+}
+
+static struct fsl_usb2_platform_data usb_pdata = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_ULPI,
+};
+
+#if defined(CONFIG_USB_ULPI)
+
+#define USBH2_EN_B IOMUX_TO_GPIO(MX31_PIN_SCK6)
+
+static int moboard_usbh2_hw_init(struct platform_device *pdev)
+{
+	int ret;
+
+	mxc_iomux_set_gpr(MUX_PGP_UH2, true);
+
+	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_SRXD6, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_STXD6, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SFS3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SCK3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SRXD3, USB_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_STXD3, USB_PAD_CFG);
+
+	ret = gpio_request(USBH2_EN_B, "usbh2-en");
+	if (ret)
+		return ret;
+	gpio_direction_output(USBH2_EN_B, 0);
+
+	return 0;
+}
+
+static int moboard_usbh2_hw_exit(struct platform_device *pdev)
+{
+	gpio_free(USBH2_EN_B);
+	return 0;
+}
+
+static struct mxc_usbh_platform_data usbh2_pdata = {
+	.init	= moboard_usbh2_hw_init,
+	.exit	= moboard_usbh2_hw_exit,
+	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
+	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
+};
+
+static int __init moboard_usbh2_init(void)
+{
+	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+			USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+
+	return mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+}
+#else
+static inline int moboard_usbh2_init(void) { return 0; }
+#endif
+
+
+static struct gpio_led mx31moboard_leds[] = {
+	{
+		.name 	= "coreboard-led-0:red:running",
+		.default_trigger = "heartbeat",
+		.gpio 	= IOMUX_TO_GPIO(MX31_PIN_SVEN0),
+	}, {
+		.name	= "coreboard-led-1:red",
+		.gpio	= IOMUX_TO_GPIO(MX31_PIN_STX0),
+	}, {
+		.name	= "coreboard-led-2:red",
+		.gpio	= IOMUX_TO_GPIO(MX31_PIN_SRX0),
+	}, {
+		.name	= "coreboard-led-3:red",
+		.gpio	= IOMUX_TO_GPIO(MX31_PIN_SIMPD0),
+	},
+};
+
+static struct gpio_led_platform_data mx31moboard_led_pdata = {
+	.num_leds 	= ARRAY_SIZE(mx31moboard_leds),
+	.leds		= mx31moboard_leds,
+};
+
+static struct platform_device mx31moboard_leds_device = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &mx31moboard_led_pdata,
+	},
+};
+
+static struct ipu_platform_data mx3_ipu_data = {
+	.irq_base = MXC_IPU_IRQ_START,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&mx31moboard_flash,
+	&mx31moboard_leds_device,
+};
+
+static struct mx3_camera_pdata camera_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.flags		= MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10,
+	.mclk_10khz	= 4800,
+};
+
+#define CAMERA_BUF_SIZE	(4*1024*1024)
+
+static int __init mx31moboard_cam_alloc_dma(const size_t buf_size)
+{
+	dma_addr_t dma_handle;
+	void *buf;
+	int dma;
+
+	if (buf_size < 2 * 1024 * 1024)
+		return -EINVAL;
+
+	buf = dma_alloc_coherent(NULL, buf_size, &dma_handle, GFP_KERNEL);
+	if (!buf) {
+		pr_err("%s: cannot allocate camera buffer-memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, buf_size);
+
+	dma = dma_declare_coherent_memory(&mx3_camera.dev,
+					dma_handle, dma_handle, buf_size,
+					DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+
+	/* The way we call dma_declare_coherent_memory only a malloc can fail */
+	return dma & DMA_MEMORY_MAP ? 0 : -ENOMEM;
+}
+
+static int mx31moboard_baseboard;
+core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
+
+/*
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	mxc_iomux_setup_multiple_pins(moboard_pins, ARRAY_SIZE(moboard_pins),
+		"moboard");
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	mxc_register_device(&mxc_uart_device0, &uart0_pdata);
+
+	mxc_register_device(&mxc_uart_device4, &uart4_pdata);
+
+	mxc_register_device(&mxc_i2c_device0, &moboard_i2c0_pdata);
+	mxc_register_device(&mxc_i2c_device1, &moboard_i2c1_pdata);
+
+	mxc_register_device(&mxc_spi_device1, &moboard_spi1_master);
+	mxc_register_device(&mxc_spi_device2, &moboard_spi2_master);
+
+	gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3), "pmic-irq");
+	gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
+	spi_register_board_info(moboard_spi_board_info,
+		ARRAY_SIZE(moboard_spi_board_info));
+
+	mxc_register_device(&mxcsdhc_device0, &sdhc1_pdata);
+
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	if (!mx31moboard_cam_alloc_dma(CAMERA_BUF_SIZE))
+		mxc_register_device(&mx3_camera, &camera_pdata);
+
+	usb_xcvr_reset();
+
+	moboard_usbotg_init();
+	mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+	moboard_usbh2_init();
+
+	switch (mx31moboard_baseboard) {
+	case MX31NOBOARD:
+		break;
+	case MX31DEVBOARD:
+		mx31moboard_devboard_init();
+		break;
+	case MX31MARXBOT:
+		mx31moboard_marxbot_init();
+		break;
+	case MX31SMARTBOT:
+		mx31moboard_smartbot_init();
+		break;
+	default:
+		printk(KERN_ERR "Illegal mx31moboard_baseboard type %d\n",
+			mx31moboard_baseboard);
+	}
+}
+
+static void __init mx31moboard_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+struct sys_timer mx31moboard_timer = {
+	.init	= mx31moboard_timer_init,
+};
+
+MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
+	/* Maintainer: Valentin Longchamp, EPFL Mobots group */
+	.phys_io	= MX31_AIPS1_BASE_ADDR,
+	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
+	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
+	.map_io         = mx31_map_io,
+	.init_irq       = mx31_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &mx31moboard_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-mx3/mach-mx35pdk.c b/arch/arm/mach-mx3/mach-mx35pdk.c
new file mode 100644
index 0000000..bcac84d
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-mx35pdk.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/memory.h>
+#include <linux/gpio.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx35.h>
+
+#include "devices.h"
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&mxc_fec_device,
+};
+
+static struct pad_desc mx35pdk_pads[] = {
+	/* UART1 */
+	MX35_PAD_CTS1__UART1_CTS,
+	MX35_PAD_RTS1__UART1_RTS,
+	MX35_PAD_TXD1__UART1_TXD_MUX,
+	MX35_PAD_RXD1__UART1_RXD_MUX,
+	/* FEC */
+	MX35_PAD_FEC_TX_CLK__FEC_TX_CLK,
+	MX35_PAD_FEC_RX_CLK__FEC_RX_CLK,
+	MX35_PAD_FEC_RX_DV__FEC_RX_DV,
+	MX35_PAD_FEC_COL__FEC_COL,
+	MX35_PAD_FEC_RDATA0__FEC_RDATA_0,
+	MX35_PAD_FEC_TDATA0__FEC_TDATA_0,
+	MX35_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX35_PAD_FEC_MDC__FEC_MDC,
+	MX35_PAD_FEC_MDIO__FEC_MDIO,
+	MX35_PAD_FEC_TX_ERR__FEC_TX_ERR,
+	MX35_PAD_FEC_RX_ERR__FEC_RX_ERR,
+	MX35_PAD_FEC_CRS__FEC_CRS,
+	MX35_PAD_FEC_RDATA1__FEC_RDATA_1,
+	MX35_PAD_FEC_TDATA1__FEC_TDATA_1,
+	MX35_PAD_FEC_RDATA2__FEC_RDATA_2,
+	MX35_PAD_FEC_TDATA2__FEC_TDATA_2,
+	MX35_PAD_FEC_RDATA3__FEC_RDATA_3,
+	MX35_PAD_FEC_TDATA3__FEC_TDATA_3,
+	/* USBOTG */
+	MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR,
+	MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC,
+};
+
+/* OTG config */
+static struct fsl_usb2_platform_data usb_pdata = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+
+	mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+}
+
+static void __init mx35pdk_timer_init(void)
+{
+	mx35_clocks_init();
+}
+
+struct sys_timer mx35pdk_timer = {
+	.init	= mx35pdk_timer_init,
+};
+
+MACHINE_START(MX35_3DS, "Freescale MX35PDK")
+	/* Maintainer: Freescale Semiconductor, Inc */
+	.phys_io	= MX35_AIPS1_BASE_ADDR,
+	.io_pg_offst	= ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
+	.map_io         = mx35_map_io,
+	.init_irq       = mx35_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &mx35pdk_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-pcm037.c b/arch/arm/mach-mx3/mach-pcm037.c
new file mode 100644
index 0000000..11f5315
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-pcm037.c
@@ -0,0 +1,693 @@
+/*
+ *  Copyright (C) 2008 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/memory.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#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>
+#include <linux/fsl_devices.h>
+
+#include <media/soc_camera.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <mach/board-pcm037.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/i2c.h>
+#include <mach/imx-uart.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_nand.h>
+#include <mach/mxc_ehci.h>
+#include <mach/ulpi.h>
+
+#include "devices.h"
+#include "pcm037.h"
+
+static enum pcm037_board_variant pcm037_instance = PCM037_PCM970;
+
+static int __init pcm037_variant_setup(char *str)
+{
+	if (!strcmp("eet", str))
+		pcm037_instance = PCM037_EET;
+	else if (strcmp("pcm970", str))
+		pr_warning("Unknown pcm037 baseboard variant %s\n", str);
+
+	return 1;
+}
+
+/* Supported values: "pcm970" (default) and "eet" */
+__setup("pcm037_variant=", pcm037_variant_setup);
+
+enum pcm037_board_variant pcm037_variant(void)
+{
+	return pcm037_instance;
+}
+
+/* UART1 with RTS/CTS handshake signals */
+static unsigned int pcm037_uart1_handshake_pins[] = {
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+};
+
+/* UART1 without RTS/CTS handshake signals */
+static unsigned int pcm037_uart1_pins[] = {
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1,
+};
+
+static unsigned int pcm037_pins[] = {
+	/* I2C */
+	MX31_PIN_CSPI2_MOSI__SCL,
+	MX31_PIN_CSPI2_MISO__SDA,
+	MX31_PIN_CSPI2_SS2__I2C3_SDA,
+	MX31_PIN_CSPI2_SCLK__I2C3_SCL,
+	/* SDHC1 */
+	MX31_PIN_SD1_DATA3__SD1_DATA3,
+	MX31_PIN_SD1_DATA2__SD1_DATA2,
+	MX31_PIN_SD1_DATA1__SD1_DATA1,
+	MX31_PIN_SD1_DATA0__SD1_DATA0,
+	MX31_PIN_SD1_CLK__SD1_CLK,
+	MX31_PIN_SD1_CMD__SD1_CMD,
+	IOMUX_MODE(MX31_PIN_SCK6, IOMUX_CONFIG_GPIO), /* card detect */
+	IOMUX_MODE(MX31_PIN_SFS6, IOMUX_CONFIG_GPIO), /* write protect */
+	/* SPI1 */
+	MX31_PIN_CSPI1_MOSI__MOSI,
+	MX31_PIN_CSPI1_MISO__MISO,
+	MX31_PIN_CSPI1_SCLK__SCLK,
+	MX31_PIN_CSPI1_SPI_RDY__SPI_RDY,
+	MX31_PIN_CSPI1_SS0__SS0,
+	MX31_PIN_CSPI1_SS1__SS1,
+	MX31_PIN_CSPI1_SS2__SS2,
+	/* UART2 */
+	MX31_PIN_TXD2__TXD2,
+	MX31_PIN_RXD2__RXD2,
+	MX31_PIN_CTS2__CTS2,
+	MX31_PIN_RTS2__RTS2,
+	/* UART3 */
+	MX31_PIN_CSPI3_MOSI__RXD3,
+	MX31_PIN_CSPI3_MISO__TXD3,
+	MX31_PIN_CSPI3_SCLK__RTS3,
+	MX31_PIN_CSPI3_SPI_RDY__CTS3,
+	/* LAN9217 irq pin */
+	IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO),
+	/* Onewire */
+	MX31_PIN_BATT_LINE__OWIRE,
+	/* Framebuffer */
+	MX31_PIN_LD0__LD0,
+	MX31_PIN_LD1__LD1,
+	MX31_PIN_LD2__LD2,
+	MX31_PIN_LD3__LD3,
+	MX31_PIN_LD4__LD4,
+	MX31_PIN_LD5__LD5,
+	MX31_PIN_LD6__LD6,
+	MX31_PIN_LD7__LD7,
+	MX31_PIN_LD8__LD8,
+	MX31_PIN_LD9__LD9,
+	MX31_PIN_LD10__LD10,
+	MX31_PIN_LD11__LD11,
+	MX31_PIN_LD12__LD12,
+	MX31_PIN_LD13__LD13,
+	MX31_PIN_LD14__LD14,
+	MX31_PIN_LD15__LD15,
+	MX31_PIN_LD16__LD16,
+	MX31_PIN_LD17__LD17,
+	MX31_PIN_VSYNC3__VSYNC3,
+	MX31_PIN_HSYNC__HSYNC,
+	MX31_PIN_FPSHIFT__FPSHIFT,
+	MX31_PIN_DRDY0__DRDY0,
+	MX31_PIN_D3_REV__D3_REV,
+	MX31_PIN_CONTRAST__CONTRAST,
+	MX31_PIN_D3_SPL__D3_SPL,
+	MX31_PIN_D3_CLS__D3_CLS,
+	MX31_PIN_LCS0__GPI03_23,
+	/* CSI */
+	IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_GPIO),
+	MX31_PIN_CSI_D6__CSI_D6,
+	MX31_PIN_CSI_D7__CSI_D7,
+	MX31_PIN_CSI_D8__CSI_D8,
+	MX31_PIN_CSI_D9__CSI_D9,
+	MX31_PIN_CSI_D10__CSI_D10,
+	MX31_PIN_CSI_D11__CSI_D11,
+	MX31_PIN_CSI_D12__CSI_D12,
+	MX31_PIN_CSI_D13__CSI_D13,
+	MX31_PIN_CSI_D14__CSI_D14,
+	MX31_PIN_CSI_D15__CSI_D15,
+	MX31_PIN_CSI_HSYNC__CSI_HSYNC,
+	MX31_PIN_CSI_MCLK__CSI_MCLK,
+	MX31_PIN_CSI_PIXCLK__CSI_PIXCLK,
+	MX31_PIN_CSI_VSYNC__CSI_VSYNC,
+	/* GPIO */
+	IOMUX_MODE(MX31_PIN_ATA_DMACK, IOMUX_CONFIG_GPIO),
+	/* OTG */
+	MX31_PIN_USBOTG_DATA0__USBOTG_DATA0,
+	MX31_PIN_USBOTG_DATA1__USBOTG_DATA1,
+	MX31_PIN_USBOTG_DATA2__USBOTG_DATA2,
+	MX31_PIN_USBOTG_DATA3__USBOTG_DATA3,
+	MX31_PIN_USBOTG_DATA4__USBOTG_DATA4,
+	MX31_PIN_USBOTG_DATA5__USBOTG_DATA5,
+	MX31_PIN_USBOTG_DATA6__USBOTG_DATA6,
+	MX31_PIN_USBOTG_DATA7__USBOTG_DATA7,
+	MX31_PIN_USBOTG_CLK__USBOTG_CLK,
+	MX31_PIN_USBOTG_DIR__USBOTG_DIR,
+	MX31_PIN_USBOTG_NXT__USBOTG_NXT,
+	MX31_PIN_USBOTG_STP__USBOTG_STP,
+	/* 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_STXD3, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_SRXD3, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_SCK3, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_SFS3, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_STXD6, IOMUX_CONFIG_FUNC),
+	IOMUX_MODE(MX31_PIN_SRXD6, IOMUX_CONFIG_FUNC),
+};
+
+static struct physmap_flash_data pcm037_flash_data = {
+	.width  = 2,
+};
+
+static struct resource pcm037_flash_resource = {
+	.start	= 0xa0000000,
+	.end	= 0xa1ffffff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device pcm037_flash = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &pcm037_flash_data,
+	},
+	.resource = &pcm037_flash_resource,
+	.num_resources = 1,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct resource smsc911x_resources[] = {
+	{
+		.start		= MX31_CS1_BASE_ADDR + 0x300,
+		.end		= MX31_CS1_BASE_ADDR + 0x300 + SZ_64K - 1,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
+		.end		= IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
+		.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+	},
+};
+
+static struct smsc911x_platform_config smsc911x_info = {
+	.flags		= SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY |
+			  SMSC911X_SAVE_MAC_ADDRESS,
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+};
+
+static struct platform_device pcm037_eth = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smsc911x_resources),
+	.resource	= smsc911x_resources,
+	.dev		= {
+		.platform_data = &smsc911x_info,
+	},
+};
+
+static struct platdata_mtd_ram pcm038_sram_data = {
+	.bankwidth = 2,
+};
+
+static struct resource pcm038_sram_resource = {
+	.start = MX31_CS4_BASE_ADDR,
+	.end   = MX31_CS4_BASE_ADDR + 512 * 1024 - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device pcm037_sram_device = {
+	.name = "mtd-ram",
+	.id = 0,
+	.dev = {
+		.platform_data = &pcm038_sram_data,
+	},
+	.num_resources = 1,
+	.resource = &pcm038_sram_resource,
+};
+
+static struct mxc_nand_platform_data pcm037_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+static struct imxi2c_platform_data pcm037_i2c_1_data = {
+	.bitrate = 100000,
+};
+
+static struct imxi2c_platform_data pcm037_i2c_2_data = {
+	.bitrate = 20000,
+};
+
+static struct at24_platform_data board_eeprom = {
+	.byte_len = 4096,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static int pcm037_camera_power(struct device *dev, int on)
+{
+	/* disable or enable the camera in X7 or X8 PCM970 connector */
+	gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), !on);
+	return 0;
+}
+
+static struct i2c_board_info pcm037_i2c_camera[] = {
+	{
+		I2C_BOARD_INFO("mt9t031", 0x5d),
+	}, {
+		I2C_BOARD_INFO("mt9v022", 0x48),
+	},
+};
+
+static struct soc_camera_link iclink_mt9v022 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.board_info	= &pcm037_i2c_camera[1],
+	.i2c_adapter_id	= 2,
+	.module_name	= "mt9v022",
+};
+
+static struct soc_camera_link iclink_mt9t031 = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.power		= pcm037_camera_power,
+	.board_info	= &pcm037_i2c_camera[0],
+	.i2c_adapter_id	= 2,
+	.module_name	= "mt9t031",
+};
+
+static struct i2c_board_info pcm037_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
+		.platform_data = &board_eeprom,
+	}, {
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	}
+};
+
+static struct platform_device pcm037_mt9t031 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &iclink_mt9t031,
+	},
+};
+
+static struct platform_device pcm037_mt9v022 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &iclink_mt9v022,
+	},
+};
+
+/* Not connected by default */
+#ifdef PCM970_SDHC_RW_SWITCH
+static int pcm970_sdhc1_get_ro(struct device *dev)
+{
+	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_SFS6));
+}
+#endif
+
+#define SDHC1_GPIO_WP	IOMUX_TO_GPIO(MX31_PIN_SFS6)
+#define SDHC1_GPIO_DET	IOMUX_TO_GPIO(MX31_PIN_SCK6)
+
+static int pcm970_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
+		void *data)
+{
+	int ret;
+
+	ret = gpio_request(SDHC1_GPIO_DET, "sdhc-detect");
+	if (ret)
+		return ret;
+
+	gpio_direction_input(SDHC1_GPIO_DET);
+
+#ifdef PCM970_SDHC_RW_SWITCH
+	ret = gpio_request(SDHC1_GPIO_WP, "sdhc-wp");
+	if (ret)
+		goto err_gpio_free;
+	gpio_direction_input(SDHC1_GPIO_WP);
+#endif
+
+	ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), detect_irq,
+			IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+				"sdhc-detect", data);
+	if (ret)
+		goto err_gpio_free_2;
+
+	return 0;
+
+err_gpio_free_2:
+#ifdef PCM970_SDHC_RW_SWITCH
+	gpio_free(SDHC1_GPIO_WP);
+err_gpio_free:
+#endif
+	gpio_free(SDHC1_GPIO_DET);
+
+	return ret;
+}
+
+static void pcm970_sdhc1_exit(struct device *dev, void *data)
+{
+	free_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), data);
+	gpio_free(SDHC1_GPIO_DET);
+	gpio_free(SDHC1_GPIO_WP);
+}
+
+static struct imxmmc_platform_data sdhc_pdata = {
+#ifdef PCM970_SDHC_RW_SWITCH
+	.get_ro = pcm970_sdhc1_get_ro,
+#endif
+	.init = pcm970_sdhc1_init,
+	.exit = pcm970_sdhc1_exit,
+};
+
+struct mx3_camera_pdata camera_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.flags		= MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10,
+	.mclk_10khz	= 2000,
+};
+
+static int __init pcm037_camera_alloc_dma(const size_t buf_size)
+{
+	dma_addr_t dma_handle;
+	void *buf;
+	int dma;
+
+	if (buf_size < 2 * 1024 * 1024)
+		return -EINVAL;
+
+	buf = dma_alloc_coherent(NULL, buf_size, &dma_handle, GFP_KERNEL);
+	if (!buf) {
+		pr_err("%s: cannot allocate camera buffer-memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	memset(buf, 0, buf_size);
+
+	dma = dma_declare_coherent_memory(&mx3_camera.dev,
+					dma_handle, dma_handle, buf_size,
+					DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+
+	/* The way we call dma_declare_coherent_memory only a malloc can fail */
+	return dma & DMA_MEMORY_MAP ? 0 : -ENOMEM;
+}
+
+static struct platform_device *devices[] __initdata = {
+	&pcm037_flash,
+	&pcm037_sram_device,
+	&pcm037_mt9t031,
+	&pcm037_mt9v022,
+};
+
+static struct ipu_platform_data mx3_ipu_data = {
+	.irq_base = MXC_IPU_IRQ_START,
+};
+
+static const struct fb_videomode fb_modedb[] = {
+	{
+		/* 240x320 @ 60 Hz Sharp */
+		.name		= "Sharp-LQ035Q7DH06-QVGA",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 185925,
+		.left_margin	= 9,
+		.right_margin	= 16,
+		.upper_margin	= 7,
+		.lower_margin	= 9,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE |
+				  FB_SYNC_CLK_INVERT | FB_SYNC_CLK_IDLE_EN,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* 240x320 @ 60 Hz */
+		.name		= "TX090",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 38255,
+		.left_margin	= 144,
+		.right_margin	= 0,
+		.upper_margin	= 7,
+		.lower_margin	= 40,
+		.hsync_len	= 96,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* 240x320 @ 60 Hz */
+		.name		= "CMEL-OLED",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 185925,
+		.left_margin	= 9,
+		.right_margin	= 16,
+		.upper_margin	= 7,
+		.lower_margin	= 9,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	},
+};
+
+static struct mx3fb_platform_data mx3fb_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.name		= "Sharp-LQ035Q7DH06-QVGA",
+	.mode		= fb_modedb,
+	.num_modes	= ARRAY_SIZE(fb_modedb),
+};
+
+static struct resource pcm970_sja1000_resources[] = {
+	{
+		.start   = MX31_CS5_BASE_ADDR,
+		.end     = MX31_CS5_BASE_ADDR + 0x100 - 1,
+		.flags   = IORESOURCE_MEM,
+	}, {
+		.start   = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)),
+		.end     = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)),
+		.flags   = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
+	},
+};
+
+struct sja1000_platform_data pcm970_sja1000_platform_data = {
+	.clock		= 16000000 / 2,
+	.ocr		= 0x40 | 0x18,
+	.cdr		= 0x40,
+};
+
+static struct platform_device pcm970_sja1000 = {
+	.name = "sja1000_platform",
+	.dev = {
+		.platform_data = &pcm970_sja1000_platform_data,
+	},
+	.resource = pcm970_sja1000_resources,
+	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
+};
+
+static struct mxc_usbh_platform_data otg_pdata = {
+	.portsc	= MXC_EHCI_MODE_ULPI,
+	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
+};
+
+static struct mxc_usbh_platform_data usbh2_pdata = {
+	.portsc	= MXC_EHCI_MODE_ULPI,
+	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
+};
+
+static struct fsl_usb2_platform_data otg_device_pdata = {
+	.operating_mode = FSL_USB2_DR_DEVICE,
+	.phy_mode       = FSL_USB2_PHY_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init pcm037_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=", pcm037_otg_mode);
+
+/*
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	int ret;
+	u32 tmp;
+
+	mxc_iomux_set_gpr(MUX_PGP_UH2, 1);
+
+	mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins),
+			"pcm037");
+
+#define H2_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS \
+		| PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
+
+	mxc_iomux_set_pad(MX31_PIN_USBH2_CLK, H2_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DIR, H2_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_NXT, H2_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_STP, H2_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DATA0, H2_PAD_CFG); /* USBH2_DATA0 */
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DATA1, H2_PAD_CFG); /* USBH2_DATA1 */
+	mxc_iomux_set_pad(MX31_PIN_SRXD6, H2_PAD_CFG);	/* USBH2_DATA2 */
+	mxc_iomux_set_pad(MX31_PIN_STXD6, H2_PAD_CFG);	/* USBH2_DATA3 */
+	mxc_iomux_set_pad(MX31_PIN_SFS3, H2_PAD_CFG);	/* USBH2_DATA4 */
+	mxc_iomux_set_pad(MX31_PIN_SCK3, H2_PAD_CFG);	/* USBH2_DATA5 */
+	mxc_iomux_set_pad(MX31_PIN_SRXD3, H2_PAD_CFG);	/* USBH2_DATA6 */
+	mxc_iomux_set_pad(MX31_PIN_STXD3, H2_PAD_CFG);	/* USBH2_DATA7 */
+
+	if (pcm037_variant() == PCM037_EET)
+		mxc_iomux_setup_multiple_pins(pcm037_uart1_pins,
+			ARRAY_SIZE(pcm037_uart1_pins), "pcm037_uart1");
+	else
+		mxc_iomux_setup_multiple_pins(pcm037_uart1_handshake_pins,
+			ARRAY_SIZE(pcm037_uart1_handshake_pins),
+			"pcm037_uart1");
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+	mxc_register_device(&mxc_uart_device2, &uart_pdata);
+
+	mxc_register_device(&mxc_w1_master_device, NULL);
+
+	/* LAN9217 IRQ pin */
+	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1), "lan9217-irq");
+	if (ret)
+		pr_warning("could not get LAN irq gpio\n");
+	else {
+		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
+		platform_device_register(&pcm037_eth);
+	}
+
+
+	/* I2C adapters and devices */
+	i2c_register_board_info(1, pcm037_i2c_devices,
+			ARRAY_SIZE(pcm037_i2c_devices));
+
+	mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
+	mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data);
+
+	mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
+	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	mxc_register_device(&mx3_fb, &mx3fb_pdata);
+
+	/* CSI */
+	/* Camera power: default - off */
+	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), "mt9t031-power");
+	if (!ret)
+		gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), 1);
+	else
+		iclink_mt9t031.power = NULL;
+
+	if (!pcm037_camera_alloc_dma(4 * 1024 * 1024))
+		mxc_register_device(&mx3_camera, &camera_pdata);
+
+	platform_device_register(&pcm970_sja1000);
+
+#if defined(CONFIG_USB_ULPI)
+	if (otg_mode_host) {
+		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+
+		mxc_register_device(&mxc_otg_host, &otg_pdata);
+	}
+
+	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+
+	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
+#endif
+	if (!otg_mode_host)
+		mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
+
+}
+
+static void __init pcm037_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+struct sys_timer pcm037_timer = {
+	.init	= pcm037_timer_init,
+};
+
+MACHINE_START(PCM037, "Phytec Phycore pcm037")
+	/* Maintainer: Pengutronix */
+	.phys_io	= MX31_AIPS1_BASE_ADDR,
+	.io_pg_offst	= (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
+	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
+	.map_io         = mx31_map_io,
+	.init_irq       = mx31_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &pcm037_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx3/pcm037_eet.c b/arch/arm/mach-mx3/mach-pcm037_eet.c
similarity index 100%
rename from arch/arm/mach-mx3/pcm037_eet.c
rename to arch/arm/mach-mx3/mach-pcm037_eet.c
diff --git a/arch/arm/mach-mx3/mach-pcm043.c b/arch/arm/mach-mx3/mach-pcm043.c
new file mode 100644
index 0000000..1bf1ec2
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-pcm043.c
@@ -0,0 +1,413 @@
+/*
+ *  Copyright (C) 2009 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/memory.h>
+#include <linux/gpio.h>
+#include <linux/smc911x.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#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>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/imx-uart.h>
+#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
+#include <mach/i2c.h>
+#endif
+#include <mach/iomux-mx35.h>
+#include <mach/ipu.h>
+#include <mach/mx3fb.h>
+#include <mach/mxc_nand.h>
+#include <mach/mxc_ehci.h>
+#include <mach/ulpi.h>
+#include <mach/audmux.h>
+#include <mach/ssi.h>
+
+#include "devices.h"
+
+static const struct fb_videomode fb_modedb[] = {
+	{
+		/* 240x320 @ 60 Hz */
+		.name		= "Sharp-LQ035Q7",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 185925,
+		.left_margin	= 9,
+		.right_margin	= 16,
+		.upper_margin	= 7,
+		.lower_margin	= 9,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE | FB_SYNC_CLK_INVERT | FB_SYNC_CLK_IDLE_EN,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* 240x320 @ 60 Hz */
+		.name		= "TX090",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 38255,
+		.left_margin	= 144,
+		.right_margin	= 0,
+		.upper_margin	= 7,
+		.lower_margin	= 40,
+		.hsync_len	= 96,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	},
+};
+
+static struct ipu_platform_data mx3_ipu_data = {
+	.irq_base = MXC_IPU_IRQ_START,
+};
+
+static struct mx3fb_platform_data mx3fb_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.name		= "Sharp-LQ035Q7",
+	.mode		= fb_modedb,
+	.num_modes	= ARRAY_SIZE(fb_modedb),
+};
+
+static struct physmap_flash_data pcm043_flash_data = {
+	.width  = 2,
+};
+
+static struct resource pcm043_flash_resource = {
+	.start	= 0xa0000000,
+	.end	= 0xa1ffffff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device pcm043_flash = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &pcm043_flash_data,
+	},
+	.resource = &pcm043_flash_resource,
+	.num_resources = 1,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
+static struct imxi2c_platform_data pcm043_i2c_1_data = {
+	.bitrate = 50000,
+};
+
+static struct at24_platform_data board_eeprom = {
+	.byte_len = 4096,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16,
+};
+
+static struct i2c_board_info pcm043_i2c_devices[] = {
+       {
+		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
+		.platform_data = &board_eeprom,
+	}, {
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	}
+};
+#endif
+
+static struct platform_device *devices[] __initdata = {
+	&pcm043_flash,
+	&mxc_fec_device,
+};
+
+static struct pad_desc pcm043_pads[] = {
+	/* UART1 */
+	MX35_PAD_CTS1__UART1_CTS,
+	MX35_PAD_RTS1__UART1_RTS,
+	MX35_PAD_TXD1__UART1_TXD_MUX,
+	MX35_PAD_RXD1__UART1_RXD_MUX,
+	/* UART2 */
+	MX35_PAD_CTS2__UART2_CTS,
+	MX35_PAD_RTS2__UART2_RTS,
+	MX35_PAD_TXD2__UART2_TXD_MUX,
+	MX35_PAD_RXD2__UART2_RXD_MUX,
+	/* FEC */
+	MX35_PAD_FEC_TX_CLK__FEC_TX_CLK,
+	MX35_PAD_FEC_RX_CLK__FEC_RX_CLK,
+	MX35_PAD_FEC_RX_DV__FEC_RX_DV,
+	MX35_PAD_FEC_COL__FEC_COL,
+	MX35_PAD_FEC_RDATA0__FEC_RDATA_0,
+	MX35_PAD_FEC_TDATA0__FEC_TDATA_0,
+	MX35_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX35_PAD_FEC_MDC__FEC_MDC,
+	MX35_PAD_FEC_MDIO__FEC_MDIO,
+	MX35_PAD_FEC_TX_ERR__FEC_TX_ERR,
+	MX35_PAD_FEC_RX_ERR__FEC_RX_ERR,
+	MX35_PAD_FEC_CRS__FEC_CRS,
+	MX35_PAD_FEC_RDATA1__FEC_RDATA_1,
+	MX35_PAD_FEC_TDATA1__FEC_TDATA_1,
+	MX35_PAD_FEC_RDATA2__FEC_RDATA_2,
+	MX35_PAD_FEC_TDATA2__FEC_TDATA_2,
+	MX35_PAD_FEC_RDATA3__FEC_RDATA_3,
+	MX35_PAD_FEC_TDATA3__FEC_TDATA_3,
+	/* I2C1 */
+	MX35_PAD_I2C1_CLK__I2C1_SCL,
+	MX35_PAD_I2C1_DAT__I2C1_SDA,
+	/* Display */
+	MX35_PAD_LD0__IPU_DISPB_DAT_0,
+	MX35_PAD_LD1__IPU_DISPB_DAT_1,
+	MX35_PAD_LD2__IPU_DISPB_DAT_2,
+	MX35_PAD_LD3__IPU_DISPB_DAT_3,
+	MX35_PAD_LD4__IPU_DISPB_DAT_4,
+	MX35_PAD_LD5__IPU_DISPB_DAT_5,
+	MX35_PAD_LD6__IPU_DISPB_DAT_6,
+	MX35_PAD_LD7__IPU_DISPB_DAT_7,
+	MX35_PAD_LD8__IPU_DISPB_DAT_8,
+	MX35_PAD_LD9__IPU_DISPB_DAT_9,
+	MX35_PAD_LD10__IPU_DISPB_DAT_10,
+	MX35_PAD_LD11__IPU_DISPB_DAT_11,
+	MX35_PAD_LD12__IPU_DISPB_DAT_12,
+	MX35_PAD_LD13__IPU_DISPB_DAT_13,
+	MX35_PAD_LD14__IPU_DISPB_DAT_14,
+	MX35_PAD_LD15__IPU_DISPB_DAT_15,
+	MX35_PAD_LD16__IPU_DISPB_DAT_16,
+	MX35_PAD_LD17__IPU_DISPB_DAT_17,
+	MX35_PAD_D3_HSYNC__IPU_DISPB_D3_HSYNC,
+	MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK,
+	MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY,
+	MX35_PAD_CONTRAST__IPU_DISPB_CONTR,
+	MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC,
+	MX35_PAD_D3_REV__IPU_DISPB_D3_REV,
+	MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS,
+	/* gpio */
+	MX35_PAD_ATA_CS0__GPIO2_6,
+	/* USB host */
+	MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR,
+	MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC,
+	/* SSI */
+	MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS,
+	MX35_PAD_STXD4__AUDMUX_AUD4_TXD,
+	MX35_PAD_SRXD4__AUDMUX_AUD4_RXD,
+	MX35_PAD_SCK4__AUDMUX_AUD4_TXC,
+};
+
+#define AC97_GPIO_TXFS	(1 * 32 + 31)
+#define AC97_GPIO_TXD	(1 * 32 + 28)
+#define AC97_GPIO_RESET	(1 * 32 + 0)
+
+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;
+	int ret;
+
+	ret = gpio_request(AC97_GPIO_TXFS, "SSI");
+	if (ret) {
+		printk("failed to get GPIO_TXFS: %d\n", ret);
+		return;
+	}
+
+	mxc_iomux_v3_setup_pad(&txfs_gpio);
+
+	/* warm reset */
+	gpio_direction_output(AC97_GPIO_TXFS, 1);
+	udelay(2);
+	gpio_set_value(AC97_GPIO_TXFS, 0);
+
+	gpio_free(AC97_GPIO_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;
+	int ret;
+
+	ret = gpio_request(AC97_GPIO_TXFS, "SSI");
+	if (ret)
+		goto err1;
+
+	ret = gpio_request(AC97_GPIO_TXD, "SSI");
+	if (ret)
+		goto err2;
+
+	ret = gpio_request(AC97_GPIO_RESET, "SSI");
+	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);
+
+	gpio_direction_output(AC97_GPIO_TXFS, 0);
+	gpio_direction_output(AC97_GPIO_TXD, 0);
+
+	/* cold reset */
+	gpio_direction_output(AC97_GPIO_RESET, 0);
+	udelay(10);
+	gpio_direction_output(AC97_GPIO_RESET, 1);
+
+	mxc_iomux_v3_setup_pad(&txd);
+	mxc_iomux_v3_setup_pad(&txfs);
+
+	gpio_free(AC97_GPIO_RESET);
+err3:
+	gpio_free(AC97_GPIO_TXD);
+err2:
+	gpio_free(AC97_GPIO_TXFS);
+err1:
+	if (ret)
+		printk("%s failed with %d\n", __func__, ret);
+	mdelay(1);
+}
+
+static struct imx_ssi_platform_data pcm043_ssi_pdata = {
+	.ac97_reset = pcm043_ac97_cold_reset,
+	.ac97_warm_reset = pcm043_ac97_warm_reset,
+	.flags = IMX_SSI_USE_AC97,
+};
+
+static struct mxc_nand_platform_data pcm037_nand_board_info = {
+	.width = 1,
+	.hw_ecc = 1,
+};
+
+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 usbh1_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 pcm043_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=", pcm043_otg_mode);
+
+/*
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
+
+	mxc_audmux_v2_configure_port(3,
+			MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
+			MXC_AUDMUX_V2_PTCR_TFSEL(0) |
+			MXC_AUDMUX_V2_PTCR_TFSDIR,
+			MXC_AUDMUX_V2_PDCR_RXDSEL(0));
+
+	mxc_audmux_v2_configure_port(0,
+			MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
+			MXC_AUDMUX_V2_PTCR_TCSEL(3) |
+			MXC_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */
+			MXC_AUDMUX_V2_PDCR_RXDSEL(3));
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
+	mxc_register_device(&imx_ssi_device0, &pcm043_ssi_pdata);
+
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+
+#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
+	i2c_register_board_info(0, pcm043_i2c_devices,
+			ARRAY_SIZE(pcm043_i2c_devices));
+
+	mxc_register_device(&mxc_i2c_device0, &pcm043_i2c_1_data);
+#endif
+
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	mxc_register_device(&mx3_fb, &mx3fb_pdata);
+
+#if defined(CONFIG_USB_ULPI)
+	if (otg_mode_host) {
+		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
+				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+
+		mxc_register_device(&mxc_otg_host, &otg_pdata);
+	}
+
+	mxc_register_device(&mxc_usbh1, &usbh1_pdata);
+#endif
+	if (!otg_mode_host)
+		mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata);
+
+}
+
+static void __init pcm043_timer_init(void)
+{
+	mx35_clocks_init();
+}
+
+struct sys_timer pcm043_timer = {
+	.init	= pcm043_timer_init,
+};
+
+MACHINE_START(PCM043, "Phytec Phycore pcm043")
+	/* Maintainer: Pengutronix */
+	.phys_io	= MX35_AIPS1_BASE_ADDR,
+	.io_pg_offst	= ((MX35_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
+	.map_io         = mx35_map_io,
+	.init_irq       = mx35_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &pcm043_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-mx3/mach-qong.c b/arch/arm/mach-mx3/mach-qong.c
new file mode 100644
index 0000000..e5b5b83
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-qong.c
@@ -0,0 +1,283 @@
+/*
+ *  Copyright (C) 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/memory.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/nand.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+#include <mach/common.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <mach/board-qong.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+#include "devices.h"
+
+/* FPGA defines */
+#define QONG_FPGA_VERSION(major, minor, rev)	\
+	(((major & 0xF) << 12) | ((minor & 0xF) << 8) | (rev & 0xFF))
+
+#define QONG_FPGA_BASEADDR 		MX31_CS1_BASE_ADDR
+#define QONG_FPGA_PERIPH_SIZE 		(1 << 24)
+
+#define QONG_FPGA_CTRL_BASEADDR		QONG_FPGA_BASEADDR
+#define QONG_FPGA_CTRL_SIZE 		0x10
+/* FPGA control registers */
+#define QONG_FPGA_CTRL_VERSION		0x00
+
+#define QONG_DNET_ID		1
+#define QONG_DNET_BASEADDR	\
+	(QONG_FPGA_BASEADDR + QONG_DNET_ID * QONG_FPGA_PERIPH_SIZE)
+#define QONG_DNET_SIZE 		0x00001000
+
+#define QONG_FPGA_IRQ		IOMUX_TO_IRQ(MX31_PIN_DTR_DCE1)
+
+/*
+ * This file contains the board-specific initialization routines.
+ */
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int uart_pins[] = {
+	MX31_PIN_CTS1__CTS1,
+	MX31_PIN_RTS1__RTS1,
+	MX31_PIN_TXD1__TXD1,
+	MX31_PIN_RXD1__RXD1
+};
+
+static inline void mxc_init_imx_uart(void)
+{
+	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins),
+			"uart-0");
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+}
+
+static struct resource dnet_resources[] = {
+	{
+		.name	= "dnet-memory",
+		.start	= QONG_DNET_BASEADDR,
+		.end	= QONG_DNET_BASEADDR + QONG_DNET_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= QONG_FPGA_IRQ,
+		.end	= QONG_FPGA_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device dnet_device = {
+	.name			= "dnet",
+	.id			= -1,
+	.num_resources		= ARRAY_SIZE(dnet_resources),
+	.resource		= dnet_resources,
+};
+
+static int __init qong_init_dnet(void)
+{
+	int ret;
+
+	ret = platform_device_register(&dnet_device);
+	return ret;
+}
+
+/* MTD NOR flash */
+
+static struct physmap_flash_data qong_flash_data = {
+	.width = 2,
+};
+
+static struct resource qong_flash_resource = {
+	.start = MX31_CS0_BASE_ADDR,
+	.end = MX31_CS0_BASE_ADDR + QONG_NOR_SIZE - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device qong_nor_mtd_device = {
+	.name = "physmap-flash",
+	.id = 0,
+	.dev = {
+		.platform_data = &qong_flash_data,
+		},
+	.resource = &qong_flash_resource,
+	.num_resources = 1,
+};
+
+static void qong_init_nor_mtd(void)
+{
+	(void)platform_device_register(&qong_nor_mtd_device);
+}
+
+/*
+ * Hardware specific access to control-lines
+ */
+static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+
+	if (cmd == NAND_CMD_NONE)
+		return;
+
+	if (ctrl & NAND_CLE)
+		writeb(cmd, nand_chip->IO_ADDR_W + (1 << 24));
+	else
+		writeb(cmd, nand_chip->IO_ADDR_W + (1 << 23));
+}
+
+/*
+ * Read the Device Ready pin.
+ */
+static int qong_nand_device_ready(struct mtd_info *mtd)
+{
+	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_NFRB));
+}
+
+static void qong_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+	if (chip >= 0)
+		gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
+	else
+		gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 1);
+}
+
+static struct platform_nand_data qong_nand_data = {
+	.chip = {
+		.chip_delay		= 20,
+		.options		= 0,
+	},
+	.ctrl = {
+		.cmd_ctrl 		= qong_nand_cmd_ctrl,
+		.dev_ready		= qong_nand_device_ready,
+		.select_chip		= qong_nand_select_chip,
+	}
+};
+
+static struct resource qong_nand_resource = {
+	.start  	= MX31_CS3_BASE_ADDR,
+	.end    	= MX31_CS3_BASE_ADDR + SZ_32M - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device qong_nand_device = {
+	.name		= "gen_nand",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &qong_nand_data,
+	},
+	.num_resources	= 1,
+	.resource	= &qong_nand_resource,
+};
+
+static void __init qong_init_nand_mtd(void)
+{
+	/* init CS */
+	mx31_setup_weimcs(3, 0x00004f00, 0x20013b31, 0x00020800);
+	mxc_iomux_set_gpr(MUX_SDCTL_CSD1_SEL, true);
+
+	/* enable pin */
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFCE_B, IOMUX_CONFIG_GPIO));
+	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), "nand_enable"))
+		gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
+
+	/* ready/busy pin */
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFRB, IOMUX_CONFIG_GPIO));
+	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFRB), "nand_rdy"))
+		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFRB));
+
+	/* write protect pin */
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFWP_B, IOMUX_CONFIG_GPIO));
+	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFWP_B), "nand_wp"))
+		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFWP_B));
+
+	platform_device_register(&qong_nand_device);
+}
+
+static void __init qong_init_fpga(void)
+{
+	void __iomem *regs;
+	u32 fpga_ver;
+
+	regs = ioremap(QONG_FPGA_CTRL_BASEADDR, QONG_FPGA_CTRL_SIZE);
+	if (!regs) {
+		printk(KERN_ERR "%s: failed to map registers, aborting.\n",
+				__func__);
+		return;
+	}
+
+	fpga_ver = readl(regs + QONG_FPGA_CTRL_VERSION);
+	iounmap(regs);
+	printk(KERN_INFO "Qong FPGA version %d.%d.%d\n",
+			(fpga_ver & 0xF000) >> 12,
+			(fpga_ver & 0x0F00) >> 8, fpga_ver & 0x00FF);
+	if (fpga_ver < QONG_FPGA_VERSION(0, 8, 7)) {
+		printk(KERN_ERR "qong: Unexpected FPGA version, FPGA-based "
+				"devices won't be registered!\n");
+		return;
+	}
+
+	/* register FPGA-based devices */
+	qong_init_nand_mtd();
+	qong_init_dnet();
+}
+
+/*
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	mxc_init_imx_uart();
+	qong_init_nor_mtd();
+	qong_init_fpga();
+}
+
+static void __init qong_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer qong_timer = {
+	.init	= qong_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros defined in arch.h in order to
+ * initialize __mach_desc_QONG data structure.
+ */
+
+MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
+	/* Maintainer: DENX Software Engineering GmbH */
+	.phys_io        = MX31_AIPS1_BASE_ADDR,
+	.io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
+	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
+	.map_io         = mx31_map_io,
+	.init_irq       = mx31_init_irq,
+	.init_machine   = mxc_board_init,
+	.timer          = &qong_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c
deleted file mode 100644
index 938c549..0000000
--- a/arch/arm/mach-mx3/mx31ads.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2005-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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/serial_8250.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/irq.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/board-mx31ads.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux-mx3.h>
-
-#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
-#include <linux/mfd/wm8350/audio.h>
-#include <linux/mfd/wm8350/core.h>
-#include <linux/mfd/wm8350/pmic.h>
-#endif
-
-#include "devices.h"
-
-/*!
- * @file mx31ads.c
- *
- * @brief This file contains the board-specific initialization routines.
- *
- * @ingroup System
- */
-
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
-/*!
- * The serial port definition structure.
- */
-static struct plat_serial8250_port serial_platform_data[] = {
-	{
-		.membase  = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTA),
-		.mapbase  = (unsigned long)(CS4_BASE_ADDR + PBC_SC16C652_UARTA),
-		.irq      = EXPIO_INT_XUART_INTA,
-		.uartclk  = 14745600,
-		.regshift = 0,
-		.iotype   = UPIO_MEM,
-		.flags    = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ,
-	}, {
-		.membase  = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTB),
-		.mapbase  = (unsigned long)(CS4_BASE_ADDR + PBC_SC16C652_UARTB),
-		.irq      = EXPIO_INT_XUART_INTB,
-		.uartclk  = 14745600,
-		.regshift = 0,
-		.iotype   = UPIO_MEM,
-		.flags    = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ,
-	},
-	{},
-};
-
-static struct platform_device serial_device = {
-	.name	= "serial8250",
-	.id	= 0,
-	.dev	= {
-		.platform_data = serial_platform_data,
-	},
-};
-
-static int __init mxc_init_extuart(void)
-{
-	return platform_device_register(&serial_device);
-}
-#else
-static inline int mxc_init_extuart(void)
-{
-	return 0;
-}
-#endif
-
-#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static unsigned int uart_pins[] = {
-	MX31_PIN_CTS1__CTS1,
-	MX31_PIN_RTS1__RTS1,
-	MX31_PIN_TXD1__TXD1,
-	MX31_PIN_RXD1__RXD1
-};
-
-static inline void mxc_init_imx_uart(void)
-{
-	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0");
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-}
-#else /* !SERIAL_IMX */
-static inline void mxc_init_imx_uart(void)
-{
-}
-#endif /* !SERIAL_IMX */
-
-static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
-{
-	u32 imr_val;
-	u32 int_valid;
-	u32 expio_irq;
-
-	imr_val = __raw_readw(PBC_INTMASK_SET_REG);
-	int_valid = __raw_readw(PBC_INTSTATUS_REG) & imr_val;
-
-	expio_irq = MXC_EXP_IO_BASE;
-	for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
-		if ((int_valid & 1) == 0)
-			continue;
-
-		generic_handle_irq(expio_irq);
-	}
-}
-
-/*
- * Disable an expio pin's interrupt by setting the bit in the imr.
- * @param irq           an expio virtual irq number
- */
-static void expio_mask_irq(u32 irq)
-{
-	u32 expio = MXC_IRQ_TO_EXPIO(irq);
-	/* mask the interrupt */
-	__raw_writew(1 << expio, PBC_INTMASK_CLEAR_REG);
-	__raw_readw(PBC_INTMASK_CLEAR_REG);
-}
-
-/*
- * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
- * @param irq           an expanded io virtual irq number
- */
-static void expio_ack_irq(u32 irq)
-{
-	u32 expio = MXC_IRQ_TO_EXPIO(irq);
-	/* clear the interrupt status */
-	__raw_writew(1 << expio, PBC_INTSTATUS_REG);
-}
-
-/*
- * Enable a expio pin's interrupt by clearing the bit in the imr.
- * @param irq           a expio virtual irq number
- */
-static void expio_unmask_irq(u32 irq)
-{
-	u32 expio = MXC_IRQ_TO_EXPIO(irq);
-	/* unmask the interrupt */
-	__raw_writew(1 << expio, PBC_INTMASK_SET_REG);
-}
-
-static struct irq_chip expio_irq_chip = {
-	.name = "EXPIO(CPLD)",
-	.ack = expio_ack_irq,
-	.mask = expio_mask_irq,
-	.unmask = expio_unmask_irq,
-};
-
-static void __init mx31ads_init_expio(void)
-{
-	int i;
-
-	printk(KERN_INFO "MX31ADS EXPIO(CPLD) hardware\n");
-
-	/*
-	 * Configure INT line as GPIO input
-	 */
-	mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_GPIO1_4, IOMUX_CONFIG_GPIO), "expio");
-
-	/* disable the interrupt and clear the status */
-	__raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG);
-	__raw_writew(0xFFFF, PBC_INTSTATUS_REG);
-	for (i = MXC_EXP_IO_BASE; i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES);
-	     i++) {
-		set_irq_chip(i, &expio_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
-	set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_HIGH);
-	set_irq_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
-}
-
-#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
-/* This section defines setup for the Wolfson Microelectronics
- * 1133-EV1 PMU/audio board.  When other PMU boards are supported the
- * regulator definitions may be shared with them, but for now they can
- * only be used with this board so would generate warnings about
- * unused statics and some of the configuration is specific to this
- * module.
- */
-
-/* CPU */
-static struct regulator_consumer_supply sw1a_consumers[] = {
-	{
-		.supply = "cpu_vcc",
-	}
-};
-
-static struct regulator_init_data sw1a_data = {
-	.constraints = {
-		.name = "SW1A",
-		.min_uV = 1275000,
-		.max_uV = 1600000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-				  REGULATOR_CHANGE_MODE,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL |
-				    REGULATOR_MODE_FAST,
-		.state_mem = {
-			 .uV = 1400000,
-			 .mode = REGULATOR_MODE_NORMAL,
-			 .enabled = 1,
-		 },
-		.initial_state = PM_SUSPEND_MEM,
-		.always_on = 1,
-		.boot_on = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(sw1a_consumers),
-	.consumer_supplies = sw1a_consumers,
-};
-
-/* System IO - High */
-static struct regulator_init_data viohi_data = {
-	.constraints = {
-		.name = "VIOHO",
-		.min_uV = 2800000,
-		.max_uV = 2800000,
-		.state_mem = {
-			 .uV = 2800000,
-			 .mode = REGULATOR_MODE_NORMAL,
-			 .enabled = 1,
-		 },
-		.initial_state = PM_SUSPEND_MEM,
-		.always_on = 1,
-		.boot_on = 1,
-	},
-};
-
-/* System IO - Low */
-static struct regulator_init_data violo_data = {
-	.constraints = {
-		.name = "VIOLO",
-		.min_uV = 1800000,
-		.max_uV = 1800000,
-		.state_mem = {
-			 .uV = 1800000,
-			 .mode = REGULATOR_MODE_NORMAL,
-			 .enabled = 1,
-		 },
-		.initial_state = PM_SUSPEND_MEM,
-		.always_on = 1,
-		.boot_on = 1,
-	},
-};
-
-/* DDR RAM */
-static struct regulator_init_data sw2a_data = {
-	.constraints = {
-		.name = "SW2A",
-		.min_uV = 1800000,
-		.max_uV = 1800000,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL,
-		.state_mem = {
-			 .uV = 1800000,
-			 .mode = REGULATOR_MODE_NORMAL,
-			 .enabled = 1,
-		 },
-		.state_disk = {
-			 .mode = REGULATOR_MODE_NORMAL,
-			 .enabled = 0,
-		 },
-		.always_on = 1,
-		.boot_on = 1,
-		.initial_state = PM_SUSPEND_MEM,
-	},
-};
-
-static struct regulator_init_data ldo1_data = {
-	.constraints = {
-		.name = "VCAM/VMMC1/VMMC2",
-		.min_uV = 2800000,
-		.max_uV = 2800000,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL,
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		.apply_uV = 1,
-	},
-};
-
-static struct regulator_consumer_supply ldo2_consumers[] = {
-	{
-		.supply = "AVDD",
-	},
-	{
-		.supply = "HPVDD",
-	},
-};
-
-/* CODEC and SIM */
-static struct regulator_init_data ldo2_data = {
-	.constraints = {
-		.name = "VESIM/VSIM/AVDD",
-		.min_uV = 3300000,
-		.max_uV = 3300000,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL,
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		.apply_uV = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(ldo2_consumers),
-	.consumer_supplies = ldo2_consumers,
-};
-
-/* General */
-static struct regulator_init_data vdig_data = {
-	.constraints = {
-		.name = "VDIG",
-		.min_uV = 1500000,
-		.max_uV = 1500000,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL,
-		.apply_uV = 1,
-		.always_on = 1,
-		.boot_on = 1,
-	},
-};
-
-/* Tranceivers */
-static struct regulator_init_data ldo4_data = {
-	.constraints = {
-		.name = "VRF1/CVDD_2.775",
-		.min_uV = 2500000,
-		.max_uV = 2500000,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL,
-		.apply_uV = 1,
-		.always_on = 1,
-		.boot_on = 1,
-	},
-};
-
-static struct wm8350_led_platform_data wm8350_led_data = {
-	.name            = "wm8350:white",
-	.default_trigger = "heartbeat",
-	.max_uA          = 27899,
-};
-
-static struct wm8350_audio_platform_data imx32ads_wm8350_setup = {
-	.vmid_discharge_msecs = 1000,
-	.drain_msecs = 30,
-	.cap_discharge_msecs = 700,
-	.vmid_charge_msecs = 700,
-	.vmid_s_curve = WM8350_S_CURVE_SLOW,
-	.dis_out4 = WM8350_DISCHARGE_SLOW,
-	.dis_out3 = WM8350_DISCHARGE_SLOW,
-	.dis_out2 = WM8350_DISCHARGE_SLOW,
-	.dis_out1 = WM8350_DISCHARGE_SLOW,
-	.vroi_out4 = WM8350_TIE_OFF_500R,
-	.vroi_out3 = WM8350_TIE_OFF_500R,
-	.vroi_out2 = WM8350_TIE_OFF_500R,
-	.vroi_out1 = WM8350_TIE_OFF_500R,
-	.vroi_enable = 0,
-	.codec_current_on = WM8350_CODEC_ISEL_1_0,
-	.codec_current_standby = WM8350_CODEC_ISEL_0_5,
-	.codec_current_charge = WM8350_CODEC_ISEL_1_5,
-};
-
-static int mx31_wm8350_init(struct wm8350 *wm8350)
-{
-	int i;
-
-	wm8350_gpio_config(wm8350, 0, WM8350_GPIO_DIR_IN,
-			   WM8350_GPIO0_PWR_ON_IN, WM8350_GPIO_ACTIVE_LOW,
-			   WM8350_GPIO_PULL_UP, WM8350_GPIO_INVERT_OFF,
-			   WM8350_GPIO_DEBOUNCE_ON);
-
-	wm8350_gpio_config(wm8350, 3, WM8350_GPIO_DIR_IN,
-			   WM8350_GPIO3_PWR_OFF_IN, WM8350_GPIO_ACTIVE_HIGH,
-			   WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
-			   WM8350_GPIO_DEBOUNCE_ON);
-
-	wm8350_gpio_config(wm8350, 4, WM8350_GPIO_DIR_IN,
-			   WM8350_GPIO4_MR_IN, WM8350_GPIO_ACTIVE_HIGH,
-			   WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
-			   WM8350_GPIO_DEBOUNCE_OFF);
-
-	wm8350_gpio_config(wm8350, 7, WM8350_GPIO_DIR_IN,
-			   WM8350_GPIO7_HIBERNATE_IN, WM8350_GPIO_ACTIVE_HIGH,
-			   WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
-			   WM8350_GPIO_DEBOUNCE_OFF);
-
-	wm8350_gpio_config(wm8350, 6, WM8350_GPIO_DIR_OUT,
-			   WM8350_GPIO6_SDOUT_OUT, WM8350_GPIO_ACTIVE_HIGH,
-			   WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
-			   WM8350_GPIO_DEBOUNCE_OFF);
-
-	wm8350_gpio_config(wm8350, 8, WM8350_GPIO_DIR_OUT,
-			   WM8350_GPIO8_VCC_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW,
-			   WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
-			   WM8350_GPIO_DEBOUNCE_OFF);
-
-	wm8350_gpio_config(wm8350, 9, WM8350_GPIO_DIR_OUT,
-			   WM8350_GPIO9_BATT_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW,
-			   WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
-			   WM8350_GPIO_DEBOUNCE_OFF);
-
-	/* Fix up for our own supplies. */
-	for (i = 0; i < ARRAY_SIZE(ldo2_consumers); i++)
-		ldo2_consumers[i].dev = wm8350->dev;
-
-	wm8350_register_regulator(wm8350, WM8350_DCDC_1, &sw1a_data);
-	wm8350_register_regulator(wm8350, WM8350_DCDC_3, &viohi_data);
-	wm8350_register_regulator(wm8350, WM8350_DCDC_4, &violo_data);
-	wm8350_register_regulator(wm8350, WM8350_DCDC_6, &sw2a_data);
-	wm8350_register_regulator(wm8350, WM8350_LDO_1, &ldo1_data);
-	wm8350_register_regulator(wm8350, WM8350_LDO_2, &ldo2_data);
-	wm8350_register_regulator(wm8350, WM8350_LDO_3, &vdig_data);
-	wm8350_register_regulator(wm8350, WM8350_LDO_4, &ldo4_data);
-
-	/* LEDs */
-	wm8350_dcdc_set_slot(wm8350, WM8350_DCDC_5, 1, 1,
-			     WM8350_DC5_ERRACT_SHUTDOWN_CONV);
-	wm8350_isink_set_flash(wm8350, WM8350_ISINK_A,
-			       WM8350_ISINK_FLASH_DISABLE,
-			       WM8350_ISINK_FLASH_TRIG_BIT,
-			       WM8350_ISINK_FLASH_DUR_32MS,
-			       WM8350_ISINK_FLASH_ON_INSTANT,
-			       WM8350_ISINK_FLASH_OFF_INSTANT,
-			       WM8350_ISINK_FLASH_MODE_EN);
-	wm8350_dcdc25_set_mode(wm8350, WM8350_DCDC_5,
-			       WM8350_ISINK_MODE_BOOST,
-			       WM8350_ISINK_ILIM_NORMAL,
-			       WM8350_DC5_RMP_20V,
-			       WM8350_DC5_FBSRC_ISINKA);
-	wm8350_register_led(wm8350, 0, WM8350_DCDC_5, WM8350_ISINK_A,
-			    &wm8350_led_data);
-
-	wm8350->codec.platform_data = &imx32ads_wm8350_setup;
-
-	regulator_has_full_constraints();
-
-	return 0;
-}
-
-static struct wm8350_platform_data __initdata mx31_wm8350_pdata = {
-	.init = mx31_wm8350_init,
-	.irq_base = MXC_BOARD_IRQ_START + MXC_MAX_EXP_IO_LINES,
-};
-#endif
-
-#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
-static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = {
-#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
-	{
-		I2C_BOARD_INFO("wm8350", 0x1a),
-		.platform_data = &mx31_wm8350_pdata,
-		.irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
-	},
-#endif
-};
-
-static void mxc_init_i2c(void)
-{
-	i2c_register_board_info(1, mx31ads_i2c1_devices,
-				ARRAY_SIZE(mx31ads_i2c1_devices));
-
-	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSPI2_MOSI, IOMUX_CONFIG_ALT1));
-	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_CSPI2_MISO, IOMUX_CONFIG_ALT1));
-
-	mxc_register_device(&mxc_i2c_device1, NULL);
-}
-#else
-static void mxc_init_i2c(void)
-{
-}
-#endif
-
-/*!
- * This structure defines static mappings for the i.MX31ADS board.
- */
-static struct map_desc mx31ads_io_desc[] __initdata = {
-	{
-		.virtual	= CS4_BASE_ADDR_VIRT,
-		.pfn		= __phys_to_pfn(CS4_BASE_ADDR),
-		.length		= CS4_SIZE / 2,
-		.type		= MT_DEVICE
-	},
-};
-
-/*!
- * Set up static virtual mappings.
- */
-static void __init mx31ads_map_io(void)
-{
-	mx31_map_io();
-	iotable_init(mx31ads_io_desc, ARRAY_SIZE(mx31ads_io_desc));
-}
-
-static void __init mx31ads_init_irq(void)
-{
-	mx31_init_irq();
-	mx31ads_init_expio();
-}
-
-/*!
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
-{
-	mxc_init_extuart();
-	mxc_init_imx_uart();
-	mxc_init_i2c();
-}
-
-static void __init mx31ads_timer_init(void)
-{
-	mx31_clocks_init(26000000);
-}
-
-static struct sys_timer mx31ads_timer = {
-	.init	= mx31ads_timer_init,
-};
-
-/*
- * The following uses standard kernel macros defined in arch.h in order to
- * initialize __mach_desc_MX31ADS data structure.
- */
-MACHINE_START(MX31ADS, "Freescale MX31ADS")
-	/* Maintainer: Freescale Semiconductor, Inc. */
-	.phys_io	= AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx31ads_map_io,
-	.init_irq       = mx31ads_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31ads_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx3/mx31lilly.c b/arch/arm/mach-mx3/mx31lilly.c
deleted file mode 100644
index 9ce029f..0000000
--- a/arch/arm/mach-mx3/mx31lilly.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- *  LILLY-1131 module support
- *
- *    Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- *
- *  based on code for other MX31 boards,
- *
- *    Copyright 2005-2007 Freescale Semiconductor
- *    Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
- *    Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/smsc911x.h>
-#include <linux/mtd/physmap.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13783.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx3.h>
-#include <mach/board-mx31lilly.h>
-#include <mach/spi.h>
-
-#include "devices.h"
-
-/*
- * This file contains module-specific initialization routines for LILLY-1131.
- * Initialization of peripherals found on the baseboard is implemented in the
- * appropriate baseboard support code.
- */
-
-/* SMSC ethernet support */
-
-static struct resource smsc91x_resources[] = {
-	{
-		.start	= CS4_BASE_ADDR,
-		.end	= CS4_BASE_ADDR + 0xffff,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
-		.end	= IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
-		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
-	}
-};
-
-static struct smsc911x_platform_config smsc911x_config = {
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
-	.flags		= SMSC911X_USE_32BIT |
-			  SMSC911X_SAVE_MAC_ADDRESS |
-			  SMSC911X_FORCE_INTERNAL_PHY,
-};
-
-static struct platform_device smsc91x_device = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smsc91x_resources),
-	.resource	= smsc91x_resources,
-	.dev		= {
-		.platform_data = &smsc911x_config,
-	}
-};
-
-/* NOR flash */
-static struct physmap_flash_data nor_flash_data = {
-	.width  = 2,
-};
-
-static struct resource nor_flash_resource = {
-	.start	= 0xa0000000,
-	.end	= 0xa1ffffff,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct platform_device physmap_flash_device = {
-	.name	= "physmap-flash",
-	.id	= 0,
-	.dev	= {
-		.platform_data  = &nor_flash_data,
-	},
-	.resource = &nor_flash_resource,
-	.num_resources = 1,
-};
-
-static struct platform_device *devices[] __initdata = {
-	&smsc91x_device,
-	&physmap_flash_device,
-};
-
-/* SPI */
-
-static int spi_internal_chipselect[] = {
-	MXC_SPI_CS(0),
-	MXC_SPI_CS(1),
-	MXC_SPI_CS(2),
-};
-
-static struct spi_imx_master spi0_pdata = {
-	.chipselect = spi_internal_chipselect,
-	.num_chipselect = ARRAY_SIZE(spi_internal_chipselect),
-};
-
-static struct spi_imx_master spi1_pdata = {
-	.chipselect = spi_internal_chipselect,
-	.num_chipselect = ARRAY_SIZE(spi_internal_chipselect),
-};
-
-static struct mc13783_platform_data mc13783_pdata __initdata = {
-	.flags = MC13783_USE_RTC | MC13783_USE_TOUCHSCREEN,
-};
-
-static struct spi_board_info mc13783_dev __initdata = {
-	.modalias	= "mc13783",
-	.max_speed_hz	= 1000000,
-	.bus_num	= 1,
-	.chip_select	= 0,
-	.platform_data	= &mc13783_pdata,
-};
-
-static int mx31lilly_baseboard;
-core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444);
-
-static void __init mx31lilly_board_init(void)
-{
-	switch (mx31lilly_baseboard) {
-	case MX31LILLY_NOBOARD:
-		break;
-	case MX31LILLY_DB:
-		mx31lilly_db_init();
-		break;
-	default:
-		printk(KERN_ERR "Illegal mx31lilly_baseboard type %d\n",
-			mx31lilly_baseboard);
-	}
-
-	mxc_iomux_alloc_pin(MX31_PIN_CS4__CS4, "Ethernet CS");
-
-	/* SPI */
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_SCLK__SCLK, "SPI1_CLK");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_MOSI__MOSI, "SPI1_TX");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_MISO__MISO, "SPI1_RX");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_SPI_RDY__SPI_RDY, "SPI1_RDY");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_SS0__SS0, "SPI1_SS0");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_SS1__SS1, "SPI1_SS1");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI1_SS2__SS2, "SPI1_SS2");
-
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SCLK__SCLK, "SPI2_CLK");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_MOSI__MOSI, "SPI2_TX");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_MISO__MISO, "SPI2_RX");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SPI_RDY__SPI_RDY, "SPI2_RDY");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SS0__SS0, "SPI2_SS0");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SS1__SS1, "SPI2_SS1");
-	mxc_iomux_alloc_pin(MX31_PIN_CSPI2_SS2__SS2, "SPI2_SS2");
-
-	mxc_register_device(&mxc_spi_device0, &spi0_pdata);
-	mxc_register_device(&mxc_spi_device1, &spi1_pdata);
-	spi_register_board_info(&mc13783_dev, 1);
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-static void __init mx31lilly_timer_init(void)
-{
-	mx31_clocks_init(26000000);
-}
-
-static struct sys_timer mx31lilly_timer = {
-	.init	= mx31lilly_timer_init,
-};
-
-MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
-	.phys_io	= AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params	= PHYS_OFFSET + 0x100,
-	.map_io		= mx31_map_io,
-	.init_irq	= mx31_init_irq,
-	.init_machine	= mx31lilly_board_init,
-	.timer		= &mx31lilly_timer,
-MACHINE_END
-
diff --git a/arch/arm/mach-mx3/mx31lite-db.c b/arch/arm/mach-mx3/mx31lite-db.c
index 694611d..ccd8742 100644
--- a/arch/arm/mach-mx3/mx31lite-db.c
+++ b/arch/arm/mach-mx3/mx31lite-db.c
@@ -67,6 +67,13 @@
 	MX31_PIN_CSPI1_SS0__SS0,
 	MX31_PIN_CSPI1_SS1__SS1,
 	MX31_PIN_CSPI1_SS2__SS2,
+	/* SDHC1 */
+	MX31_PIN_SD1_DATA0__SD1_DATA0,
+	MX31_PIN_SD1_DATA1__SD1_DATA1,
+	MX31_PIN_SD1_DATA2__SD1_DATA2,
+	MX31_PIN_SD1_DATA3__SD1_DATA3,
+	MX31_PIN_SD1_CLK__SD1_CLK,
+	MX31_PIN_SD1_CMD__SD1_CMD,
 };
 
 /* UART */
@@ -79,11 +86,11 @@
 static int gpio_det, gpio_wp;
 
 #define MMC_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
-			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
+		     PAD_CTL_ODE_CMOS)
 
 static int mxc_mmc1_get_ro(struct device *dev)
 {
-	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_LCS0));
+	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_GPIO1_6));
 }
 
 static int mxc_mmc1_init(struct device *dev,
@@ -94,12 +101,17 @@
 	gpio_det = IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1);
 	gpio_wp = IOMUX_TO_GPIO(MX31_PIN_GPIO1_6);
 
-	mxc_iomux_set_pad(MX31_PIN_SD1_DATA0, MMC_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_SD1_DATA1, MMC_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_SD1_DATA2, MMC_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_SD1_DATA3, MMC_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_SD1_DATA0,
+			  MMC_PAD_CFG | PAD_CTL_PUE_PUD | PAD_CTL_100K_PU);
+	mxc_iomux_set_pad(MX31_PIN_SD1_DATA1,
+			  MMC_PAD_CFG | PAD_CTL_PUE_PUD | PAD_CTL_100K_PU);
+	mxc_iomux_set_pad(MX31_PIN_SD1_DATA2,
+			  MMC_PAD_CFG | PAD_CTL_PUE_PUD | PAD_CTL_100K_PU);
+	mxc_iomux_set_pad(MX31_PIN_SD1_DATA3,
+			  MMC_PAD_CFG | PAD_CTL_PUE_PUD | PAD_CTL_100K_PU);
+	mxc_iomux_set_pad(MX31_PIN_SD1_CMD,
+			  MMC_PAD_CFG | PAD_CTL_PUE_PUD | PAD_CTL_100K_PU);
 	mxc_iomux_set_pad(MX31_PIN_SD1_CLK, MMC_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_SD1_CMD, MMC_PAD_CFG);
 
 	ret = gpio_request(gpio_det, "MMC detect");
 	if (ret)
@@ -113,7 +125,7 @@
 	gpio_direction_input(gpio_wp);
 
 	ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_DCD_DCE1), detect_irq,
-			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 			  "MMC detect", data);
 	if (ret)
 		goto exit_free_wp;
@@ -133,7 +145,7 @@
 {
 	gpio_free(gpio_det);
 	gpio_free(gpio_wp);
-	free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), data);
+	free_irq(IOMUX_TO_IRQ(MX31_PIN_DCD_DCE1), data);
 }
 
 static struct imxmmc_platform_data mmc_pdata = {
diff --git a/arch/arm/mach-mx3/mx31lite.c b/arch/arm/mach-mx3/mx31lite.c
deleted file mode 100644
index 789b20d..0000000
--- a/arch/arm/mach-mx3/mx31lite.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *  Copyright (C) 2009 Daniel Mack <daniel@caiaq.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/memory.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/smsc911x.h>
-#include <linux/mfd/mc13783.h>
-#include <linux/spi/spi.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <linux/mtd/physmap.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/board-mx31lite.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux-mx3.h>
-#include <mach/irqs.h>
-#include <mach/mxc_nand.h>
-#include <mach/spi.h>
-#include <mach/mxc_ehci.h>
-#include <mach/ulpi.h>
-
-#include "devices.h"
-
-/*
- * This file contains the module-specific initialization routines.
- */
-
-static unsigned int mx31lite_pins[] = {
-	/* LAN9117 IRQ pin */
-	IOMUX_MODE(MX31_PIN_SFS6, IOMUX_CONFIG_GPIO),
-	/* SPI 1 */
-	MX31_PIN_CSPI2_SCLK__SCLK,
-	MX31_PIN_CSPI2_MOSI__MOSI,
-	MX31_PIN_CSPI2_MISO__MISO,
-	MX31_PIN_CSPI2_SPI_RDY__SPI_RDY,
-	MX31_PIN_CSPI2_SS0__SS0,
-	MX31_PIN_CSPI2_SS1__SS1,
-	MX31_PIN_CSPI2_SS2__SS2,
-};
-
-static struct mxc_nand_platform_data mx31lite_nand_board_info = {
-	.width = 1,
-	.hw_ecc = 1,
-};
-
-static struct smsc911x_platform_config smsc911x_config = {
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_16BIT,
-};
-
-static struct resource smsc911x_resources[] = {
-	{
-		.start		= CS4_BASE_ADDR,
-		.end		= CS4_BASE_ADDR + 0x100,
-		.flags		= IORESOURCE_MEM,
-	}, {
-		.start		= IOMUX_TO_IRQ(MX31_PIN_SFS6),
-		.end		= IOMUX_TO_IRQ(MX31_PIN_SFS6),
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device smsc911x_device = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smsc911x_resources),
-	.resource	= smsc911x_resources,
-	.dev		= {
-		.platform_data = &smsc911x_config,
-	},
-};
-
-/*
- * SPI
- *
- * The MC13783 is the only hard-wired SPI device on the module.
- */
-
-static int spi_internal_chipselect[] = {
-	MXC_SPI_CS(0),
-};
-
-static struct spi_imx_master spi1_pdata = {
-	.chipselect	= spi_internal_chipselect,
-	.num_chipselect	= ARRAY_SIZE(spi_internal_chipselect),
-};
-
-static struct mc13783_platform_data mc13783_pdata __initdata = {
-	.flags  = MC13783_USE_RTC |
-		  MC13783_USE_REGULATOR,
-};
-
-static struct spi_board_info mc13783_spi_dev __initdata = {
-	.modalias       = "mc13783",
-	.max_speed_hz   = 1000000,
-	.bus_num	= 1,
-	.chip_select    = 0,
-	.platform_data  = &mc13783_pdata,
-	.irq		= IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
-};
-
-/*
- * USB
- */
-
-#if defined(CONFIG_USB_ULPI)
-#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
-			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
-
-static int usbh2_init(struct platform_device *pdev)
-{
-	int pins[] = {
-		MX31_PIN_USBH2_DATA0__USBH2_DATA0,
-		MX31_PIN_USBH2_DATA1__USBH2_DATA1,
-		MX31_PIN_USBH2_CLK__USBH2_CLK,
-		MX31_PIN_USBH2_DIR__USBH2_DIR,
-		MX31_PIN_USBH2_NXT__USBH2_NXT,
-		MX31_PIN_USBH2_STP__USBH2_STP,
-	};
-
-	mxc_iomux_setup_multiple_pins(pins, ARRAY_SIZE(pins), "USB H2");
-
-	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_SRXD6, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_STXD6, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_SFS3, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_SCK3, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_SRXD3, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_STXD3, USB_PAD_CFG);
-
-	mxc_iomux_set_gpr(MUX_PGP_UH2, true);
-
-	/* chip select */
-	mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_GPIO),
-				"USBH2_CS");
-	gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), "USBH2 CS");
-	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), 0);
-
-	return 0;
-}
-
-static struct mxc_usbh_platform_data usbh2_pdata = {
-	.init   = usbh2_init,
-	.portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags  = MXC_EHCI_POWER_PINS_ENABLED,
-};
-#endif
-
-/*
- * NOR flash
- */
-
-static struct physmap_flash_data nor_flash_data = {
-	.width  = 2,
-};
-
-static struct resource nor_flash_resource = {
-	.start  = 0xa0000000,
-	.end    = 0xa1ffffff,
-	.flags  = IORESOURCE_MEM,
-};
-
-static struct platform_device physmap_flash_device = {
-	.name   = "physmap-flash",
-	.id     = 0,
-	.dev    = {
-		.platform_data  = &nor_flash_data,
-	},
-	.resource = &nor_flash_resource,
-	.num_resources = 1,
-};
-
-
-
-/*
- * This structure defines the MX31 memory map.
- */
-static struct map_desc mx31lite_io_desc[] __initdata = {
-	{
-		.virtual = CS4_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(CS4_BASE_ADDR),
-		.length = CS4_SIZE,
-		.type = MT_DEVICE
-	}
-};
-
-/*
- * Set up static virtual mappings.
- */
-void __init mx31lite_map_io(void)
-{
-	mx31_map_io();
-	iotable_init(mx31lite_io_desc, ARRAY_SIZE(mx31lite_io_desc));
-}
-
-static int mx31lite_baseboard;
-core_param(mx31lite_baseboard, mx31lite_baseboard, int, 0444);
-
-static void __init mxc_board_init(void)
-{
-	int ret;
-
-	switch (mx31lite_baseboard) {
-	case MX31LITE_NOBOARD:
-		break;
-	case MX31LITE_DB:
-		mx31lite_db_init();
-		break;
-	default:
-		printk(KERN_ERR "Illegal mx31lite_baseboard type %d\n",
-				mx31lite_baseboard);
-	}
-
-	mxc_iomux_setup_multiple_pins(mx31lite_pins, ARRAY_SIZE(mx31lite_pins),
-				      "mx31lite");
-
-	/* NOR and NAND flash */
-	platform_device_register(&physmap_flash_device);
-	mxc_register_device(&mxc_nand_device, &mx31lite_nand_board_info);
-
-	mxc_register_device(&mxc_spi_device1, &spi1_pdata);
-	spi_register_board_info(&mc13783_spi_dev, 1);
-
-#if defined(CONFIG_USB_ULPI)
-	/* USB */
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
-
-	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
-#endif
-
-	/* SMSC9117 IRQ pin */
-	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_SFS6), "sms9117-irq");
-	if (ret)
-		pr_warning("could not get LAN irq gpio\n");
-	else {
-		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_SFS6));
-		platform_device_register(&smsc911x_device);
-	}
-}
-
-static void __init mx31lite_timer_init(void)
-{
-	mx31_clocks_init(26000000);
-}
-
-struct sys_timer mx31lite_timer = {
-	.init	= mx31lite_timer_init,
-};
-
-MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
-	/* Maintainer: Freescale Semiconductor, Inc. */
-	.phys_io        = AIPS1_BASE_ADDR,
-	.io_pg_offst    = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx31lite_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31lite_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx3/mx31moboard-devboard.c b/arch/arm/mach-mx3/mx31moboard-devboard.c
index 438428e..9fbad2e 100644
--- a/arch/arm/mach-mx3/mx31moboard-devboard.c
+++ b/arch/arm/mach-mx3/mx31moboard-devboard.c
@@ -49,6 +49,9 @@
 	MX31_PIN_CSPI1_SS2__USBH1_RCV, MX31_PIN_CSPI1_SCLK__USBH1_OEB,
 	MX31_PIN_CSPI1_SPI_RDY__USBH1_FS, MX31_PIN_SFS6__USBH1_SUSPEND,
 	MX31_PIN_NFRE_B__GPIO1_11, MX31_PIN_NFALE__GPIO1_12,
+	/* SEL */
+	MX31_PIN_DTR_DCE1__GPIO2_8, MX31_PIN_DSR_DCE1__GPIO2_9,
+	MX31_PIN_RI_DCE1__GPIO2_10, MX31_PIN_DCD_DCE1__GPIO2_11,
 };
 
 static struct imxuart_platform_data uart_pdata = {
@@ -108,6 +111,33 @@
 	.exit	= devboard_sdhc2_exit,
 };
 
+#define SEL0 IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1)
+#define SEL1 IOMUX_TO_GPIO(MX31_PIN_DSR_DCE1)
+#define SEL2 IOMUX_TO_GPIO(MX31_PIN_RI_DCE1)
+#define SEL3 IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)
+
+static void devboard_init_sel_gpios(void)
+{
+	if (!gpio_request(SEL0, "sel0")) {
+		gpio_direction_input(SEL0);
+		gpio_export(SEL0, true);
+	}
+
+	if (!gpio_request(SEL1, "sel1")) {
+		gpio_direction_input(SEL1);
+		gpio_export(SEL1, true);
+	}
+
+	if (!gpio_request(SEL2, "sel2")) {
+		gpio_direction_input(SEL2);
+		gpio_export(SEL2, true);
+	}
+
+	if (!gpio_request(SEL3, "sel3")) {
+		gpio_direction_input(SEL3);
+		gpio_export(SEL3, true);
+	}
+}
 #define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
 			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 
@@ -196,5 +226,7 @@
 
 	mxc_register_device(&mxcsdhc_device1, &sdhc2_pdata);
 
+	devboard_init_sel_gpios();
+
 	devboard_usbh1_init();
 }
diff --git a/arch/arm/mach-mx3/mx31moboard-marxbot.c b/arch/arm/mach-mx3/mx31moboard-marxbot.c
index 1f44b9c..3958515 100644
--- a/arch/arm/mach-mx3/mx31moboard-marxbot.c
+++ b/arch/arm/mach-mx3/mx31moboard-marxbot.c
@@ -66,6 +66,9 @@
 	MX31_PIN_CSPI1_SS2__USBH1_RCV, MX31_PIN_CSPI1_SCLK__USBH1_OEB,
 	MX31_PIN_CSPI1_SPI_RDY__USBH1_FS, MX31_PIN_SFS6__USBH1_SUSPEND,
 	MX31_PIN_NFRE_B__GPIO1_11, MX31_PIN_NFALE__GPIO1_12,
+	/* SEL */
+	MX31_PIN_DTR_DCE1__GPIO2_8, MX31_PIN_DSR_DCE1__GPIO2_9,
+	MX31_PIN_RI_DCE1__GPIO2_10, MX31_PIN_DCD_DCE1__GPIO2_11,
 };
 
 #define SDHC2_CD IOMUX_TO_GPIO(MX31_PIN_ATA_DIOR)
@@ -127,12 +130,12 @@
 static void dspics_resets_init(void)
 {
 	if (!gpio_request(TRSLAT_RST_B, "translator-rst")) {
-		gpio_direction_output(TRSLAT_RST_B, 1);
+		gpio_direction_output(TRSLAT_RST_B, 0);
 		gpio_export(TRSLAT_RST_B, false);
 	}
 
 	if (!gpio_request(DSPICS_RST_B, "dspics-rst")) {
-		gpio_direction_output(DSPICS_RST_B, 1);
+		gpio_direction_output(DSPICS_RST_B, 0);
 		gpio_export(DSPICS_RST_B, false);
 	}
 }
@@ -200,7 +203,7 @@
 	int ret = gpio_request(CAM_CHOICE, "cam-choice");
 	if (ret)
 		return ret;
-	gpio_direction_output(CAM_CHOICE, 1);
+	gpio_direction_output(CAM_CHOICE, 0);
 
 	ret = gpio_request(BASECAM_RST_B, "basecam-reset");
 	if (ret)
@@ -223,6 +226,34 @@
 	return 0;
 }
 
+#define SEL0 IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1)
+#define SEL1 IOMUX_TO_GPIO(MX31_PIN_DSR_DCE1)
+#define SEL2 IOMUX_TO_GPIO(MX31_PIN_RI_DCE1)
+#define SEL3 IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)
+
+static void marxbot_init_sel_gpios(void)
+{
+	if (!gpio_request(SEL0, "sel0")) {
+		gpio_direction_input(SEL0);
+		gpio_export(SEL0, true);
+	}
+
+	if (!gpio_request(SEL1, "sel1")) {
+		gpio_direction_input(SEL1);
+		gpio_export(SEL1, true);
+	}
+
+	if (!gpio_request(SEL2, "sel2")) {
+		gpio_direction_input(SEL2);
+		gpio_export(SEL2, true);
+	}
+
+	if (!gpio_request(SEL3, "sel3")) {
+		gpio_direction_input(SEL3);
+		gpio_export(SEL3, true);
+	}
+}
+
 #define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
 			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 
@@ -307,6 +338,8 @@
 	mxc_iomux_setup_multiple_pins(marxbot_pins, ARRAY_SIZE(marxbot_pins),
 		"marxbot");
 
+	marxbot_init_sel_gpios();
+
 	dspics_resets_init();
 
 	mxc_register_device(&mxcsdhc_device1, &sdhc2_pdata);
diff --git a/arch/arm/mach-mx3/mx31moboard-smartbot.c b/arch/arm/mach-mx3/mx31moboard-smartbot.c
new file mode 100644
index 0000000..52a69fc
--- /dev/null
+++ b/arch/arm/mach-mx3/mx31moboard-smartbot.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2009 Valentin Longchamp, EPFL Mobots group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx3.h>
+
+#include <media/soc_camera.h>
+
+#include "devices.h"
+
+static unsigned int smartbot_pins[] = {
+	/* UART1 */
+	MX31_PIN_CTS2__CTS2, MX31_PIN_RTS2__RTS2,
+	MX31_PIN_TXD2__TXD2, MX31_PIN_RXD2__RXD2,
+	/* CSI */
+	MX31_PIN_CSI_D4__CSI_D4, MX31_PIN_CSI_D5__CSI_D5,
+	MX31_PIN_CSI_D6__CSI_D6, MX31_PIN_CSI_D7__CSI_D7,
+	MX31_PIN_CSI_D8__CSI_D8, MX31_PIN_CSI_D9__CSI_D9,
+	MX31_PIN_CSI_D10__CSI_D10, MX31_PIN_CSI_D11__CSI_D11,
+	MX31_PIN_CSI_D12__CSI_D12, MX31_PIN_CSI_D13__CSI_D13,
+	MX31_PIN_CSI_D14__CSI_D14, MX31_PIN_CSI_D15__CSI_D15,
+	MX31_PIN_CSI_HSYNC__CSI_HSYNC, MX31_PIN_CSI_MCLK__CSI_MCLK,
+	MX31_PIN_CSI_PIXCLK__CSI_PIXCLK, MX31_PIN_CSI_VSYNC__CSI_VSYNC,
+	MX31_PIN_GPIO3_0__GPIO3_0, MX31_PIN_GPIO3_1__GPIO3_1,
+	/* ENABLES */
+	MX31_PIN_DTR_DCE1__GPIO2_8, MX31_PIN_DSR_DCE1__GPIO2_9,
+	MX31_PIN_RI_DCE1__GPIO2_10, MX31_PIN_DCD_DCE1__GPIO2_11,
+};
+
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+#define CAM_POWER	IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)
+#define CAM_RST_B	IOMUX_TO_GPIO(MX31_PIN_GPIO3_0)
+
+static int smartbot_cam_power(struct device *dev, int on)
+{
+	gpio_set_value(CAM_POWER, !on);
+	return 0;
+}
+
+static int smartbot_cam_reset(struct device *dev)
+{
+	gpio_set_value(CAM_RST_B, 0);
+	udelay(100);
+	gpio_set_value(CAM_RST_B, 1);
+	return 0;
+}
+
+static struct i2c_board_info smartbot_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("mt9t031", 0x5d),
+	},
+};
+
+static struct soc_camera_link base_iclink = {
+	.bus_id		= 0,		/* Must match with the camera ID */
+	.power		= smartbot_cam_power,
+	.reset		= smartbot_cam_reset,
+	.board_info	= &smartbot_i2c_devices[0],
+	.i2c_adapter_id	= 0,
+	.module_name	= "mt9t031",
+};
+
+static struct platform_device smartbot_camera[] = {
+	{
+		.name	= "soc-camera-pdrv",
+		.id	= 0,
+		.dev	= {
+			.platform_data = &base_iclink,
+		},
+	},
+};
+
+static struct platform_device *smartbot_cameras[] __initdata = {
+	&smartbot_camera[0],
+};
+
+static int __init smartbot_cam_init(void)
+{
+	int ret = gpio_request(CAM_RST_B, "cam-reset");
+	if (ret)
+		return ret;
+	gpio_direction_output(CAM_RST_B, 1);
+	ret = gpio_request(CAM_POWER, "cam-standby");
+	if (ret)
+		return ret;
+	gpio_direction_output(CAM_POWER, 0);
+
+	return 0;
+}
+
+#define POWER_EN IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1)
+#define DSPIC_RST_B IOMUX_TO_GPIO(MX31_PIN_DSR_DCE1)
+#define TRSLAT_RST_B IOMUX_TO_GPIO(MX31_PIN_RI_DCE1)
+#define SEL3 IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)
+
+static void smartbot_resets_init(void)
+{
+	if (!gpio_request(POWER_EN, "power-enable")) {
+		gpio_direction_output(POWER_EN, 0);
+		gpio_export(POWER_EN, false);
+	}
+
+	if (!gpio_request(DSPIC_RST_B, "dspic-rst")) {
+		gpio_direction_output(DSPIC_RST_B, 0);
+		gpio_export(DSPIC_RST_B, false);
+	}
+
+	if (!gpio_request(TRSLAT_RST_B, "translator-rst")) {
+		gpio_direction_output(TRSLAT_RST_B, 0);
+		gpio_export(TRSLAT_RST_B, false);
+	}
+
+	if (!gpio_request(SEL3, "sel3")) {
+		gpio_direction_input(SEL3);
+		gpio_export(SEL3, true);
+	}
+}
+/*
+ * system init for baseboard usage. Will be called by mx31moboard init.
+ */
+void __init mx31moboard_smartbot_init(void)
+{
+	printk(KERN_INFO "Initializing mx31smartbot peripherals\n");
+
+	mxc_iomux_setup_multiple_pins(smartbot_pins, ARRAY_SIZE(smartbot_pins),
+		"smartbot");
+
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+
+	smartbot_resets_init();
+
+	smartbot_cam_init();
+	platform_add_devices(smartbot_cameras, ARRAY_SIZE(smartbot_cameras));
+}
diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c
deleted file mode 100644
index cfd605d..0000000
--- a/arch/arm/mach-mx3/mx31moboard.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- *  Copyright (C) 2008 Valentin Longchamp, EPFL Mobots group
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/dma-mapping.h>
-#include <linux/fsl_devices.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/leds.h>
-#include <linux/memory.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/partitions.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/machine.h>
-#include <linux/mfd/mc13783.h>
-#include <linux/spi/spi.h>
-#include <linux/types.h>
-
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-#include <mach/board-mx31moboard.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux-mx3.h>
-#include <mach/ipu.h>
-#include <mach/i2c.h>
-#include <mach/mmc.h>
-#include <mach/mxc_ehci.h>
-#include <mach/mx3_camera.h>
-#include <mach/spi.h>
-#include <mach/ulpi.h>
-
-#include "devices.h"
-
-static unsigned int moboard_pins[] = {
-	/* UART0 */
-	MX31_PIN_TXD1__TXD1, MX31_PIN_RXD1__RXD1,
-	MX31_PIN_CTS1__GPIO2_7,
-	/* UART4 */
-	MX31_PIN_PC_RST__CTS5, MX31_PIN_PC_VS2__RTS5,
-	MX31_PIN_PC_BVD2__TXD5, MX31_PIN_PC_BVD1__RXD5,
-	/* I2C0 */
-	MX31_PIN_I2C_DAT__I2C1_SDA, MX31_PIN_I2C_CLK__I2C1_SCL,
-	/* I2C1 */
-	MX31_PIN_DCD_DTE1__I2C2_SDA, MX31_PIN_RI_DTE1__I2C2_SCL,
-	/* SDHC1 */
-	MX31_PIN_SD1_DATA3__SD1_DATA3, MX31_PIN_SD1_DATA2__SD1_DATA2,
-	MX31_PIN_SD1_DATA1__SD1_DATA1, MX31_PIN_SD1_DATA0__SD1_DATA0,
-	MX31_PIN_SD1_CLK__SD1_CLK, MX31_PIN_SD1_CMD__SD1_CMD,
-	MX31_PIN_ATA_CS0__GPIO3_26, MX31_PIN_ATA_CS1__GPIO3_27,
-	/* USB reset */
-	MX31_PIN_GPIO1_0__GPIO1_0,
-	/* USB OTG */
-	MX31_PIN_USBOTG_DATA0__USBOTG_DATA0,
-	MX31_PIN_USBOTG_DATA1__USBOTG_DATA1,
-	MX31_PIN_USBOTG_DATA2__USBOTG_DATA2,
-	MX31_PIN_USBOTG_DATA3__USBOTG_DATA3,
-	MX31_PIN_USBOTG_DATA4__USBOTG_DATA4,
-	MX31_PIN_USBOTG_DATA5__USBOTG_DATA5,
-	MX31_PIN_USBOTG_DATA6__USBOTG_DATA6,
-	MX31_PIN_USBOTG_DATA7__USBOTG_DATA7,
-	MX31_PIN_USBOTG_CLK__USBOTG_CLK, MX31_PIN_USBOTG_DIR__USBOTG_DIR,
-	MX31_PIN_USBOTG_NXT__USBOTG_NXT, MX31_PIN_USBOTG_STP__USBOTG_STP,
-	MX31_PIN_USB_OC__GPIO1_30,
-	/* USB H2 */
-	MX31_PIN_USBH2_DATA0__USBH2_DATA0,
-	MX31_PIN_USBH2_DATA1__USBH2_DATA1,
-	MX31_PIN_STXD3__USBH2_DATA2, MX31_PIN_SRXD3__USBH2_DATA3,
-	MX31_PIN_SCK3__USBH2_DATA4, MX31_PIN_SFS3__USBH2_DATA5,
-	MX31_PIN_STXD6__USBH2_DATA6, MX31_PIN_SRXD6__USBH2_DATA7,
-	MX31_PIN_USBH2_CLK__USBH2_CLK, MX31_PIN_USBH2_DIR__USBH2_DIR,
-	MX31_PIN_USBH2_NXT__USBH2_NXT, MX31_PIN_USBH2_STP__USBH2_STP,
-	MX31_PIN_SCK6__GPIO1_25,
-	/* LEDs */
-	MX31_PIN_SVEN0__GPIO2_0, MX31_PIN_STX0__GPIO2_1,
-	MX31_PIN_SRX0__GPIO2_2, MX31_PIN_SIMPD0__GPIO2_3,
-	/* SEL */
-	MX31_PIN_DTR_DCE1__GPIO2_8, MX31_PIN_DSR_DCE1__GPIO2_9,
-	MX31_PIN_RI_DCE1__GPIO2_10, MX31_PIN_DCD_DCE1__GPIO2_11,
-	/* SPI1 */
-	MX31_PIN_CSPI2_MOSI__MOSI, MX31_PIN_CSPI2_MISO__MISO,
-	MX31_PIN_CSPI2_SCLK__SCLK, MX31_PIN_CSPI2_SPI_RDY__SPI_RDY,
-	MX31_PIN_CSPI2_SS0__SS0, MX31_PIN_CSPI2_SS2__SS2,
-	/* Atlas IRQ */
-	MX31_PIN_GPIO1_3__GPIO1_3,
-	/* SPI2 */
-	MX31_PIN_CSPI3_MOSI__MOSI, MX31_PIN_CSPI3_MISO__MISO,
-	MX31_PIN_CSPI3_SCLK__SCLK, MX31_PIN_CSPI3_SPI_RDY__SPI_RDY,
-	MX31_PIN_CSPI2_SS1__CSPI3_SS1,
-};
-
-static struct physmap_flash_data mx31moboard_flash_data = {
-	.width  	= 2,
-};
-
-static struct resource mx31moboard_flash_resource = {
-	.start	= 0xa0000000,
-	.end	= 0xa1ffffff,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct platform_device mx31moboard_flash = {
-	.name	= "physmap-flash",
-	.id	= 0,
-	.dev	= {
-		.platform_data  = &mx31moboard_flash_data,
-	},
-	.resource = &mx31moboard_flash_resource,
-	.num_resources = 1,
-};
-
-static int moboard_uart0_init(struct platform_device *pdev)
-{
-	gpio_request(IOMUX_TO_GPIO(MX31_PIN_CTS1), "uart0-cts-hack");
-	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CTS1), 0);
-	return 0;
-}
-
-static struct imxuart_platform_data uart0_pdata = {
-	.init = moboard_uart0_init,
-};
-
-static struct imxuart_platform_data uart4_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct imxi2c_platform_data moboard_i2c0_pdata = {
-	.bitrate = 400000,
-};
-
-static struct imxi2c_platform_data moboard_i2c1_pdata = {
-	.bitrate = 100000,
-};
-
-static int moboard_spi1_cs[] = {
-	MXC_SPI_CS(0),
-	MXC_SPI_CS(2),
-};
-
-static struct spi_imx_master moboard_spi1_master = {
-	.chipselect	= moboard_spi1_cs,
-	.num_chipselect	= ARRAY_SIZE(moboard_spi1_cs),
-};
-
-static struct regulator_consumer_supply sdhc_consumers[] = {
-	{
-		.dev	= &mxcsdhc_device0.dev,
-		.supply	= "sdhc0_vcc",
-	},
-	{
-		.dev	= &mxcsdhc_device1.dev,
-		.supply	= "sdhc1_vcc",
-	},
-};
-
-static struct regulator_init_data sdhc_vreg_data = {
-	.constraints = {
-		.min_uV = 2700000,
-		.max_uV = 3000000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL |
-			REGULATOR_MODE_FAST,
-		.always_on = 0,
-		.boot_on = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(sdhc_consumers),
-	.consumer_supplies = sdhc_consumers,
-};
-
-static struct regulator_consumer_supply cam_consumers[] = {
-	{
-		.dev	= &mx3_camera.dev,
-		.supply	= "cam_vcc",
-	},
-};
-
-static struct regulator_init_data cam_vreg_data = {
-	.constraints = {
-		.min_uV = 2700000,
-		.max_uV = 3000000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
-			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL |
-			REGULATOR_MODE_FAST,
-		.always_on = 0,
-		.boot_on = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(cam_consumers),
-	.consumer_supplies = cam_consumers,
-};
-
-static struct mc13783_regulator_init_data moboard_regulators[] = {
-	{
-		.id = MC13783_REGU_VMMC1,
-		.init_data = &sdhc_vreg_data,
-	},
-	{
-		.id = MC13783_REGU_VCAM,
-		.init_data = &cam_vreg_data,
-	},
-};
-
-static struct mc13783_platform_data moboard_pmic = {
-	.regulators = moboard_regulators,
-	.num_regulators = ARRAY_SIZE(moboard_regulators),
-	.flags = MC13783_USE_REGULATOR | MC13783_USE_RTC |
-		MC13783_USE_ADC,
-};
-
-static struct spi_board_info moboard_spi_board_info[] __initdata = {
-	{
-		.modalias = "mc13783",
-		.irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
-		.max_speed_hz = 300000,
-		.bus_num = 1,
-		.chip_select = 0,
-		.platform_data = &moboard_pmic,
-		.mode = SPI_CS_HIGH,
-	},
-};
-
-static int moboard_spi2_cs[] = {
-	MXC_SPI_CS(1),
-};
-
-static struct spi_imx_master moboard_spi2_master = {
-	.chipselect	= moboard_spi2_cs,
-	.num_chipselect	= ARRAY_SIZE(moboard_spi2_cs),
-};
-
-#define SDHC1_CD IOMUX_TO_GPIO(MX31_PIN_ATA_CS0)
-#define SDHC1_WP IOMUX_TO_GPIO(MX31_PIN_ATA_CS1)
-
-static int moboard_sdhc1_get_ro(struct device *dev)
-{
-	return !gpio_get_value(SDHC1_WP);
-}
-
-static int moboard_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
-		void *data)
-{
-	int ret;
-
-	ret = gpio_request(SDHC1_CD, "sdhc-detect");
-	if (ret)
-		return ret;
-
-	gpio_direction_input(SDHC1_CD);
-
-	ret = gpio_request(SDHC1_WP, "sdhc-wp");
-	if (ret)
-		goto err_gpio_free;
-	gpio_direction_input(SDHC1_WP);
-
-	ret = request_irq(gpio_to_irq(SDHC1_CD), detect_irq,
-		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-		"sdhc1-card-detect", data);
-	if (ret)
-		goto err_gpio_free_2;
-
-	return 0;
-
-err_gpio_free_2:
-	gpio_free(SDHC1_WP);
-err_gpio_free:
-	gpio_free(SDHC1_CD);
-
-	return ret;
-}
-
-static void moboard_sdhc1_exit(struct device *dev, void *data)
-{
-	free_irq(gpio_to_irq(SDHC1_CD), data);
-	gpio_free(SDHC1_WP);
-	gpio_free(SDHC1_CD);
-}
-
-static struct imxmmc_platform_data sdhc1_pdata = {
-	.get_ro	= moboard_sdhc1_get_ro,
-	.init	= moboard_sdhc1_init,
-	.exit	= moboard_sdhc1_exit,
-};
-
-/*
- * this pin is dedicated for all mx31moboard systems, so we do it here
- */
-#define USB_RESET_B	IOMUX_TO_GPIO(MX31_PIN_GPIO1_0)
-
-static void usb_xcvr_reset(void)
-{
-	gpio_request(USB_RESET_B, "usb-reset");
-	gpio_direction_output(USB_RESET_B, 0);
-	mdelay(1);
-	gpio_set_value(USB_RESET_B, 1);
-}
-
-#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
-			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
-
-#define OTG_EN_B IOMUX_TO_GPIO(MX31_PIN_USB_OC)
-
-static void moboard_usbotg_init(void)
-{
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, USB_PAD_CFG);
-
-	gpio_request(OTG_EN_B, "usb-udc-en");
-	gpio_direction_output(OTG_EN_B, 0);
-}
-
-static struct fsl_usb2_platform_data usb_pdata = {
-	.operating_mode	= FSL_USB2_DR_DEVICE,
-	.phy_mode	= FSL_USB2_PHY_ULPI,
-};
-
-#if defined(CONFIG_USB_ULPI)
-
-#define USBH2_EN_B IOMUX_TO_GPIO(MX31_PIN_SCK6)
-
-static int moboard_usbh2_hw_init(struct platform_device *pdev)
-{
-	int ret = gpio_request(USBH2_EN_B, "usbh2-en");
-	if (ret)
-		return ret;
-
-	mxc_iomux_set_gpr(MUX_PGP_UH2, true);
-
-	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_SRXD6, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_STXD6, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_SFS3, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_SCK3, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_SRXD3, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_STXD3, USB_PAD_CFG);
-
-	gpio_direction_output(USBH2_EN_B, 0);
-
-	return 0;
-}
-
-static int moboard_usbh2_hw_exit(struct platform_device *pdev)
-{
-	gpio_free(USBH2_EN_B);
-	return 0;
-}
-
-static struct mxc_usbh_platform_data usbh2_pdata = {
-	.init	= moboard_usbh2_hw_init,
-	.exit	= moboard_usbh2_hw_exit,
-	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
-};
-
-static int __init moboard_usbh2_init(void)
-{
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
-
-	return mxc_register_device(&mxc_usbh2, &usbh2_pdata);
-}
-#else
-static inline int moboard_usbh2_init(void) { return 0; }
-#endif
-
-
-static struct gpio_led mx31moboard_leds[] = {
-	{
-		.name 	= "coreboard-led-0:red:running",
-		.default_trigger = "heartbeat",
-		.gpio 	= IOMUX_TO_GPIO(MX31_PIN_SVEN0),
-	}, {
-		.name	= "coreboard-led-1:red",
-		.gpio	= IOMUX_TO_GPIO(MX31_PIN_STX0),
-	}, {
-		.name	= "coreboard-led-2:red",
-		.gpio	= IOMUX_TO_GPIO(MX31_PIN_SRX0),
-	}, {
-		.name	= "coreboard-led-3:red",
-		.gpio	= IOMUX_TO_GPIO(MX31_PIN_SIMPD0),
-	},
-};
-
-static struct gpio_led_platform_data mx31moboard_led_pdata = {
-	.num_leds 	= ARRAY_SIZE(mx31moboard_leds),
-	.leds		= mx31moboard_leds,
-};
-
-static struct platform_device mx31moboard_leds_device = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &mx31moboard_led_pdata,
-	},
-};
-
-#define SEL0 IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1)
-#define SEL1 IOMUX_TO_GPIO(MX31_PIN_DSR_DCE1)
-#define SEL2 IOMUX_TO_GPIO(MX31_PIN_RI_DCE1)
-#define SEL3 IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)
-
-static void mx31moboard_init_sel_gpios(void)
-{
-	if (!gpio_request(SEL0, "sel0")) {
-		gpio_direction_input(SEL0);
-		gpio_export(SEL0, true);
-	}
-
-	if (!gpio_request(SEL1, "sel1")) {
-		gpio_direction_input(SEL1);
-		gpio_export(SEL1, true);
-	}
-
-	if (!gpio_request(SEL2, "sel2")) {
-		gpio_direction_input(SEL2);
-		gpio_export(SEL2, true);
-	}
-
-	if (!gpio_request(SEL3, "sel3")) {
-		gpio_direction_input(SEL3);
-		gpio_export(SEL3, true);
-	}
-}
-
-static struct ipu_platform_data mx3_ipu_data = {
-	.irq_base = MXC_IPU_IRQ_START,
-};
-
-static struct platform_device *devices[] __initdata = {
-	&mx31moboard_flash,
-	&mx31moboard_leds_device,
-};
-
-static struct mx3_camera_pdata camera_pdata = {
-	.dma_dev	= &mx3_ipu.dev,
-	.flags		= MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10,
-	.mclk_10khz	= 4800,
-};
-
-#define CAMERA_BUF_SIZE	(4*1024*1024)
-
-static int __init mx31moboard_cam_alloc_dma(const size_t buf_size)
-{
-	dma_addr_t dma_handle;
-	void *buf;
-	int dma;
-
-	if (buf_size < 2 * 1024 * 1024)
-		return -EINVAL;
-
-	buf = dma_alloc_coherent(NULL, buf_size, &dma_handle, GFP_KERNEL);
-	if (!buf) {
-		pr_err("%s: cannot allocate camera buffer-memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	memset(buf, 0, buf_size);
-
-	dma = dma_declare_coherent_memory(&mx3_camera.dev,
-					dma_handle, dma_handle, buf_size,
-					DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
-
-	/* The way we call dma_declare_coherent_memory only a malloc can fail */
-	return dma & DMA_MEMORY_MAP ? 0 : -ENOMEM;
-}
-
-static int mx31moboard_baseboard;
-core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
-
-/*
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
-{
-	mxc_iomux_setup_multiple_pins(moboard_pins, ARRAY_SIZE(moboard_pins),
-		"moboard");
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-
-	mxc_register_device(&mxc_uart_device0, &uart0_pdata);
-
-	mxc_register_device(&mxc_uart_device4, &uart4_pdata);
-
-	mx31moboard_init_sel_gpios();
-
-	mxc_register_device(&mxc_i2c_device0, &moboard_i2c0_pdata);
-	mxc_register_device(&mxc_i2c_device1, &moboard_i2c1_pdata);
-
-	mxc_register_device(&mxc_spi_device1, &moboard_spi1_master);
-	mxc_register_device(&mxc_spi_device2, &moboard_spi2_master);
-
-	gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3), "pmic-irq");
-	gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
-	spi_register_board_info(moboard_spi_board_info,
-		ARRAY_SIZE(moboard_spi_board_info));
-
-	mxc_register_device(&mxcsdhc_device0, &sdhc1_pdata);
-
-	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
-	if (!mx31moboard_cam_alloc_dma(CAMERA_BUF_SIZE))
-		mxc_register_device(&mx3_camera, &camera_pdata);
-
-	usb_xcvr_reset();
-
-	moboard_usbotg_init();
-	mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
-	moboard_usbh2_init();
-
-	switch (mx31moboard_baseboard) {
-	case MX31NOBOARD:
-		break;
-	case MX31DEVBOARD:
-		mx31moboard_devboard_init();
-		break;
-	case MX31MARXBOT:
-		mx31moboard_marxbot_init();
-		break;
-	default:
-		printk(KERN_ERR "Illegal mx31moboard_baseboard type %d\n",
-			mx31moboard_baseboard);
-	}
-}
-
-static void __init mx31moboard_timer_init(void)
-{
-	mx31_clocks_init(26000000);
-}
-
-struct sys_timer mx31moboard_timer = {
-	.init	= mx31moboard_timer_init,
-};
-
-MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
-	/* Maintainer: Valentin Longchamp, EPFL Mobots group */
-	.phys_io	= AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx31_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31moboard_timer,
-MACHINE_END
-
diff --git a/arch/arm/mach-mx3/mx31pdk.c b/arch/arm/mach-mx3/mx31pdk.c
deleted file mode 100644
index 18715f1..0000000
--- a/arch/arm/mach-mx3/mx31pdk.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- *  Copyright 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/smsc911x.h>
-#include <linux/platform_device.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/board-mx31pdk.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux-mx3.h>
-#include "devices.h"
-
-/*!
- * @file mx31pdk.c
- *
- * @brief This file contains the board-specific initialization routines.
- *
- * @ingroup System
- */
-
-static int mx31pdk_pins[] = {
-	/* UART1 */
-	MX31_PIN_CTS1__CTS1,
-	MX31_PIN_RTS1__RTS1,
-	MX31_PIN_TXD1__TXD1,
-	MX31_PIN_RXD1__RXD1,
-	IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO),
-};
-
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-/*
- * Support for the SMSC9217 on the Debug board.
- */
-
-static struct smsc911x_platform_config smsc911x_config = {
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-};
-
-static struct resource smsc911x_resources[] = {
-	{
-		.start		= LAN9217_BASE_ADDR,
-		.end		= LAN9217_BASE_ADDR + 0xff,
-		.flags		= IORESOURCE_MEM,
-	}, {
-		.start		= EXPIO_INT_ENET,
-		.end		= EXPIO_INT_ENET,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device smsc911x_device = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smsc911x_resources),
-	.resource	= smsc911x_resources,
-	.dev		= {
-		.platform_data = &smsc911x_config,
-	},
-};
-
-/*
- * Routines for the CPLD on the debug board. It contains a CPLD handling
- * LEDs, switches, interrupts for Ethernet.
- */
-
-static void mx31pdk_expio_irq_handler(uint32_t irq, struct irq_desc *desc)
-{
-	uint32_t imr_val;
-	uint32_t int_valid;
-	uint32_t expio_irq;
-
-	imr_val = __raw_readw(CPLD_INT_MASK_REG);
-	int_valid = __raw_readw(CPLD_INT_STATUS_REG) & ~imr_val;
-
-	expio_irq = MXC_EXP_IO_BASE;
-	for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
-		if ((int_valid & 1) == 0)
-			continue;
-		generic_handle_irq(expio_irq);
-	}
-}
-
-/*
- * Disable an expio pin's interrupt by setting the bit in the imr.
- * @param irq           an expio virtual irq number
- */
-static void expio_mask_irq(uint32_t irq)
-{
-	uint16_t reg;
-	uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
-
-	/* mask the interrupt */
-	reg = __raw_readw(CPLD_INT_MASK_REG);
-	reg |= 1 << expio;
-	__raw_writew(reg, CPLD_INT_MASK_REG);
-}
-
-/*
- * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
- * @param irq           an expanded io virtual irq number
- */
-static void expio_ack_irq(uint32_t irq)
-{
-	uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
-
-	/* clear the interrupt status */
-	__raw_writew(1 << expio, CPLD_INT_RESET_REG);
-	__raw_writew(0, CPLD_INT_RESET_REG);
-	/* mask the interrupt */
-	expio_mask_irq(irq);
-}
-
-/*
- * Enable a expio pin's interrupt by clearing the bit in the imr.
- * @param irq           a expio virtual irq number
- */
-static void expio_unmask_irq(uint32_t irq)
-{
-	uint16_t reg;
-	uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
-
-	/* unmask the interrupt */
-	reg = __raw_readw(CPLD_INT_MASK_REG);
-	reg &= ~(1 << expio);
-	__raw_writew(reg, CPLD_INT_MASK_REG);
-}
-
-static struct irq_chip expio_irq_chip = {
-	.ack = expio_ack_irq,
-	.mask = expio_mask_irq,
-	.unmask = expio_unmask_irq,
-};
-
-static int __init mx31pdk_init_expio(void)
-{
-	int i;
-	int ret;
-
-	/* Check if there's a debug board connected */
-	if ((__raw_readw(CPLD_MAGIC_NUMBER1_REG) != 0xAAAA) ||
-	    (__raw_readw(CPLD_MAGIC_NUMBER2_REG) != 0x5555) ||
-	    (__raw_readw(CPLD_MAGIC_NUMBER3_REG) != 0xCAFE)) {
-		/* No Debug board found */
-		return -ENODEV;
-	}
-
-	pr_info("i.MX31PDK Debug board detected, rev = 0x%04X\n",
-		__raw_readw(CPLD_CODE_VER_REG));
-
-	/*
-	 * Configure INT line as GPIO input
-	 */
-	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1), "sms9217-irq");
-	if (ret)
-		pr_warning("could not get LAN irq gpio\n");
-	else
-		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
-
-	/* Disable the interrupts and clear the status */
-	__raw_writew(0, CPLD_INT_MASK_REG);
-	__raw_writew(0xFFFF, CPLD_INT_RESET_REG);
-	__raw_writew(0, CPLD_INT_RESET_REG);
-	__raw_writew(0x1F, CPLD_INT_MASK_REG);
-	for (i = MXC_EXP_IO_BASE;
-	     i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES);
-	     i++) {
-		set_irq_chip(i, &expio_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
-	set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_LOW);
-	set_irq_chained_handler(EXPIO_PARENT_INT, mx31pdk_expio_irq_handler);
-
-	return 0;
-}
-
-/*
- * This structure defines the MX31 memory map.
- */
-static struct map_desc mx31pdk_io_desc[] __initdata = {
-	{
-		.virtual = CS5_BASE_ADDR_VIRT,
-		.pfn = __phys_to_pfn(CS5_BASE_ADDR),
-		.length = CS5_SIZE,
-		.type = MT_DEVICE,
-	},
-};
-
-/*
- * Set up static virtual mappings.
- */
-static void __init mx31pdk_map_io(void)
-{
-	mx31_map_io();
-	iotable_init(mx31pdk_io_desc, ARRAY_SIZE(mx31pdk_io_desc));
-}
-
-/*!
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
-{
-	mxc_iomux_setup_multiple_pins(mx31pdk_pins, ARRAY_SIZE(mx31pdk_pins),
-				      "mx31pdk");
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-
-	if (!mx31pdk_init_expio())
-		platform_device_register(&smsc911x_device);
-}
-
-static void __init mx31pdk_timer_init(void)
-{
-	mx31_clocks_init(26000000);
-}
-
-static struct sys_timer mx31pdk_timer = {
-	.init	= mx31pdk_timer_init,
-};
-
-/*
- * The following uses standard kernel macros defined in arch.h in order to
- * initialize __mach_desc_MX31PDK data structure.
- */
-MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
-	/* Maintainer: Freescale Semiconductor, Inc. */
-	.phys_io	= AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx31pdk_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31pdk_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx3/mx35pdk.c b/arch/arm/mach-mx3/mx35pdk.c
deleted file mode 100644
index 0bbc65e..0000000
--- a/arch/arm/mach-mx3/mx35pdk.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * Author: Fabio Estevam <fabio.estevam@freescale.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/memory.h>
-#include <linux/gpio.h>
-#include <linux/fsl_devices.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux-mx35.h>
-
-#include "devices.h"
-
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct platform_device *devices[] __initdata = {
-	&mxc_fec_device,
-};
-
-static struct pad_desc mx35pdk_pads[] = {
-	/* UART1 */
-	MX35_PAD_CTS1__UART1_CTS,
-	MX35_PAD_RTS1__UART1_RTS,
-	MX35_PAD_TXD1__UART1_TXD_MUX,
-	MX35_PAD_RXD1__UART1_RXD_MUX,
-	/* FEC */
-	MX35_PAD_FEC_TX_CLK__FEC_TX_CLK,
-	MX35_PAD_FEC_RX_CLK__FEC_RX_CLK,
-	MX35_PAD_FEC_RX_DV__FEC_RX_DV,
-	MX35_PAD_FEC_COL__FEC_COL,
-	MX35_PAD_FEC_RDATA0__FEC_RDATA_0,
-	MX35_PAD_FEC_TDATA0__FEC_TDATA_0,
-	MX35_PAD_FEC_TX_EN__FEC_TX_EN,
-	MX35_PAD_FEC_MDC__FEC_MDC,
-	MX35_PAD_FEC_MDIO__FEC_MDIO,
-	MX35_PAD_FEC_TX_ERR__FEC_TX_ERR,
-	MX35_PAD_FEC_RX_ERR__FEC_RX_ERR,
-	MX35_PAD_FEC_CRS__FEC_CRS,
-	MX35_PAD_FEC_RDATA1__FEC_RDATA_1,
-	MX35_PAD_FEC_TDATA1__FEC_TDATA_1,
-	MX35_PAD_FEC_RDATA2__FEC_RDATA_2,
-	MX35_PAD_FEC_TDATA2__FEC_TDATA_2,
-	MX35_PAD_FEC_RDATA3__FEC_RDATA_3,
-	MX35_PAD_FEC_TDATA3__FEC_TDATA_3,
-	/* USBOTG */
-	MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR,
-	MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC,
-};
-
-/* OTG config */
-static struct fsl_usb2_platform_data usb_pdata = {
-	.operating_mode	= FSL_USB2_DR_DEVICE,
-	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-
-	mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
-}
-
-static void __init mx35pdk_timer_init(void)
-{
-	mx35_clocks_init();
-}
-
-struct sys_timer mx35pdk_timer = {
-	.init	= mx35pdk_timer_init,
-};
-
-MACHINE_START(MX35_3DS, "Freescale MX35PDK")
-	/* Maintainer: Freescale Semiconductor, Inc */
-	.phys_io	= AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx35_map_io,
-	.init_irq       = mx35_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx35pdk_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
deleted file mode 100644
index 5be3969..0000000
--- a/arch/arm/mach-mx3/pcm037.c
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- *  Copyright (C) 2008 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/memory.h>
-#include <linux/gpio.h>
-#include <linux/smsc911x.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
-#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 <media/soc_camera.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-#include <mach/board-pcm037.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/i2c.h>
-#include <mach/imx-uart.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_nand.h>
-
-#include "devices.h"
-#include "pcm037.h"
-
-static enum pcm037_board_variant pcm037_instance = PCM037_PCM970;
-
-static int __init pcm037_variant_setup(char *str)
-{
-	if (!strcmp("eet", str))
-		pcm037_instance = PCM037_EET;
-	else if (strcmp("pcm970", str))
-		pr_warning("Unknown pcm037 baseboard variant %s\n", str);
-
-	return 1;
-}
-
-/* Supported values: "pcm970" (default) and "eet" */
-__setup("pcm037_variant=", pcm037_variant_setup);
-
-enum pcm037_board_variant pcm037_variant(void)
-{
-	return pcm037_instance;
-}
-
-/* UART1 with RTS/CTS handshake signals */
-static unsigned int pcm037_uart1_handshake_pins[] = {
-	MX31_PIN_CTS1__CTS1,
-	MX31_PIN_RTS1__RTS1,
-	MX31_PIN_TXD1__TXD1,
-	MX31_PIN_RXD1__RXD1,
-};
-
-/* UART1 without RTS/CTS handshake signals */
-static unsigned int pcm037_uart1_pins[] = {
-	MX31_PIN_TXD1__TXD1,
-	MX31_PIN_RXD1__RXD1,
-};
-
-static unsigned int pcm037_pins[] = {
-	/* I2C */
-	MX31_PIN_CSPI2_MOSI__SCL,
-	MX31_PIN_CSPI2_MISO__SDA,
-	MX31_PIN_CSPI2_SS2__I2C3_SDA,
-	MX31_PIN_CSPI2_SCLK__I2C3_SCL,
-	/* SDHC1 */
-	MX31_PIN_SD1_DATA3__SD1_DATA3,
-	MX31_PIN_SD1_DATA2__SD1_DATA2,
-	MX31_PIN_SD1_DATA1__SD1_DATA1,
-	MX31_PIN_SD1_DATA0__SD1_DATA0,
-	MX31_PIN_SD1_CLK__SD1_CLK,
-	MX31_PIN_SD1_CMD__SD1_CMD,
-	IOMUX_MODE(MX31_PIN_SCK6, IOMUX_CONFIG_GPIO), /* card detect */
-	IOMUX_MODE(MX31_PIN_SFS6, IOMUX_CONFIG_GPIO), /* write protect */
-	/* SPI1 */
-	MX31_PIN_CSPI1_MOSI__MOSI,
-	MX31_PIN_CSPI1_MISO__MISO,
-	MX31_PIN_CSPI1_SCLK__SCLK,
-	MX31_PIN_CSPI1_SPI_RDY__SPI_RDY,
-	MX31_PIN_CSPI1_SS0__SS0,
-	MX31_PIN_CSPI1_SS1__SS1,
-	MX31_PIN_CSPI1_SS2__SS2,
-	/* UART2 */
-	MX31_PIN_TXD2__TXD2,
-	MX31_PIN_RXD2__RXD2,
-	MX31_PIN_CTS2__CTS2,
-	MX31_PIN_RTS2__RTS2,
-	/* UART3 */
-	MX31_PIN_CSPI3_MOSI__RXD3,
-	MX31_PIN_CSPI3_MISO__TXD3,
-	MX31_PIN_CSPI3_SCLK__RTS3,
-	MX31_PIN_CSPI3_SPI_RDY__CTS3,
-	/* LAN9217 irq pin */
-	IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO),
-	/* Onewire */
-	MX31_PIN_BATT_LINE__OWIRE,
-	/* Framebuffer */
-	MX31_PIN_LD0__LD0,
-	MX31_PIN_LD1__LD1,
-	MX31_PIN_LD2__LD2,
-	MX31_PIN_LD3__LD3,
-	MX31_PIN_LD4__LD4,
-	MX31_PIN_LD5__LD5,
-	MX31_PIN_LD6__LD6,
-	MX31_PIN_LD7__LD7,
-	MX31_PIN_LD8__LD8,
-	MX31_PIN_LD9__LD9,
-	MX31_PIN_LD10__LD10,
-	MX31_PIN_LD11__LD11,
-	MX31_PIN_LD12__LD12,
-	MX31_PIN_LD13__LD13,
-	MX31_PIN_LD14__LD14,
-	MX31_PIN_LD15__LD15,
-	MX31_PIN_LD16__LD16,
-	MX31_PIN_LD17__LD17,
-	MX31_PIN_VSYNC3__VSYNC3,
-	MX31_PIN_HSYNC__HSYNC,
-	MX31_PIN_FPSHIFT__FPSHIFT,
-	MX31_PIN_DRDY0__DRDY0,
-	MX31_PIN_D3_REV__D3_REV,
-	MX31_PIN_CONTRAST__CONTRAST,
-	MX31_PIN_D3_SPL__D3_SPL,
-	MX31_PIN_D3_CLS__D3_CLS,
-	MX31_PIN_LCS0__GPI03_23,
-	/* CSI */
-	IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_GPIO),
-	MX31_PIN_CSI_D6__CSI_D6,
-	MX31_PIN_CSI_D7__CSI_D7,
-	MX31_PIN_CSI_D8__CSI_D8,
-	MX31_PIN_CSI_D9__CSI_D9,
-	MX31_PIN_CSI_D10__CSI_D10,
-	MX31_PIN_CSI_D11__CSI_D11,
-	MX31_PIN_CSI_D12__CSI_D12,
-	MX31_PIN_CSI_D13__CSI_D13,
-	MX31_PIN_CSI_D14__CSI_D14,
-	MX31_PIN_CSI_D15__CSI_D15,
-	MX31_PIN_CSI_HSYNC__CSI_HSYNC,
-	MX31_PIN_CSI_MCLK__CSI_MCLK,
-	MX31_PIN_CSI_PIXCLK__CSI_PIXCLK,
-	MX31_PIN_CSI_VSYNC__CSI_VSYNC,
-	/* GPIO */
-	IOMUX_MODE(MX31_PIN_ATA_DMACK, IOMUX_CONFIG_GPIO),
-};
-
-static struct physmap_flash_data pcm037_flash_data = {
-	.width  = 2,
-};
-
-static struct resource pcm037_flash_resource = {
-	.start	= 0xa0000000,
-	.end	= 0xa1ffffff,
-	.flags	= IORESOURCE_MEM,
-};
-
-static int usbotg_pins[] = {
-	MX31_PIN_USBOTG_DATA0__USBOTG_DATA0,
-	MX31_PIN_USBOTG_DATA1__USBOTG_DATA1,
-	MX31_PIN_USBOTG_DATA2__USBOTG_DATA2,
-	MX31_PIN_USBOTG_DATA3__USBOTG_DATA3,
-	MX31_PIN_USBOTG_DATA4__USBOTG_DATA4,
-	MX31_PIN_USBOTG_DATA5__USBOTG_DATA5,
-	MX31_PIN_USBOTG_DATA6__USBOTG_DATA6,
-	MX31_PIN_USBOTG_DATA7__USBOTG_DATA7,
-	MX31_PIN_USBOTG_CLK__USBOTG_CLK,
-	MX31_PIN_USBOTG_DIR__USBOTG_DIR,
-	MX31_PIN_USBOTG_NXT__USBOTG_NXT,
-	MX31_PIN_USBOTG_STP__USBOTG_STP,
-};
-
-/* USB OTG HS port */
-static int __init gpio_usbotg_hs_activate(void)
-{
-	int ret = mxc_iomux_setup_multiple_pins(usbotg_pins,
-					ARRAY_SIZE(usbotg_pins), "usbotg");
-
-	if (ret < 0) {
-		printk(KERN_ERR "Cannot set up OTG pins\n");
-		return ret;
-	}
-
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK,   PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR,   PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT,   PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_STP,   PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST);
-
-	return 0;
-}
-
-/* OTG config */
-static struct fsl_usb2_platform_data usb_pdata = {
-	.operating_mode	= FSL_USB2_DR_DEVICE,
-	.phy_mode	= FSL_USB2_PHY_ULPI,
-};
-
-static struct platform_device pcm037_flash = {
-	.name	= "physmap-flash",
-	.id	= 0,
-	.dev	= {
-		.platform_data  = &pcm037_flash_data,
-	},
-	.resource = &pcm037_flash_resource,
-	.num_resources = 1,
-};
-
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct resource smsc911x_resources[] = {
-	{
-		.start		= CS1_BASE_ADDR + 0x300,
-		.end		= CS1_BASE_ADDR + 0x300 + SZ_64K - 1,
-		.flags		= IORESOURCE_MEM,
-	}, {
-		.start		= IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
-		.end		= IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
-		.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},
-};
-
-static struct smsc911x_platform_config smsc911x_info = {
-	.flags		= SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY |
-			  SMSC911X_SAVE_MAC_ADDRESS,
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-};
-
-static struct platform_device pcm037_eth = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smsc911x_resources),
-	.resource	= smsc911x_resources,
-	.dev		= {
-		.platform_data = &smsc911x_info,
-	},
-};
-
-static struct platdata_mtd_ram pcm038_sram_data = {
-	.bankwidth = 2,
-};
-
-static struct resource pcm038_sram_resource = {
-	.start = CS4_BASE_ADDR,
-	.end   = CS4_BASE_ADDR + 512 * 1024 - 1,
-	.flags = IORESOURCE_MEM,
-};
-
-static struct platform_device pcm037_sram_device = {
-	.name = "mtd-ram",
-	.id = 0,
-	.dev = {
-		.platform_data = &pcm038_sram_data,
-	},
-	.num_resources = 1,
-	.resource = &pcm038_sram_resource,
-};
-
-static struct mxc_nand_platform_data pcm037_nand_board_info = {
-	.width = 1,
-	.hw_ecc = 1,
-};
-
-static struct imxi2c_platform_data pcm037_i2c_1_data = {
-	.bitrate = 100000,
-};
-
-static struct imxi2c_platform_data pcm037_i2c_2_data = {
-	.bitrate = 20000,
-};
-
-static struct at24_platform_data board_eeprom = {
-	.byte_len = 4096,
-	.page_size = 32,
-	.flags = AT24_FLAG_ADDR16,
-};
-
-static int pcm037_camera_power(struct device *dev, int on)
-{
-	/* disable or enable the camera in X7 or X8 PCM970 connector */
-	gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), !on);
-	return 0;
-}
-
-static struct i2c_board_info pcm037_i2c_camera[] = {
-	{
-		I2C_BOARD_INFO("mt9t031", 0x5d),
-	}, {
-		I2C_BOARD_INFO("mt9v022", 0x48),
-	},
-};
-
-static struct soc_camera_link iclink_mt9v022 = {
-	.bus_id		= 0,		/* Must match with the camera ID */
-	.board_info	= &pcm037_i2c_camera[1],
-	.i2c_adapter_id	= 2,
-	.module_name	= "mt9v022",
-};
-
-static struct soc_camera_link iclink_mt9t031 = {
-	.bus_id		= 0,		/* Must match with the camera ID */
-	.power		= pcm037_camera_power,
-	.board_info	= &pcm037_i2c_camera[0],
-	.i2c_adapter_id	= 2,
-	.module_name	= "mt9t031",
-};
-
-static struct i2c_board_info pcm037_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
-		.platform_data = &board_eeprom,
-	}, {
-		I2C_BOARD_INFO("pcf8563", 0x51),
-	}
-};
-
-static struct platform_device pcm037_mt9t031 = {
-	.name	= "soc-camera-pdrv",
-	.id	= 0,
-	.dev	= {
-		.platform_data = &iclink_mt9t031,
-	},
-};
-
-static struct platform_device pcm037_mt9v022 = {
-	.name	= "soc-camera-pdrv",
-	.id	= 1,
-	.dev	= {
-		.platform_data = &iclink_mt9v022,
-	},
-};
-
-/* Not connected by default */
-#ifdef PCM970_SDHC_RW_SWITCH
-static int pcm970_sdhc1_get_ro(struct device *dev)
-{
-	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_SFS6));
-}
-#endif
-
-#define SDHC1_GPIO_WP	IOMUX_TO_GPIO(MX31_PIN_SFS6)
-#define SDHC1_GPIO_DET	IOMUX_TO_GPIO(MX31_PIN_SCK6)
-
-static int pcm970_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
-		void *data)
-{
-	int ret;
-
-	ret = gpio_request(SDHC1_GPIO_DET, "sdhc-detect");
-	if (ret)
-		return ret;
-
-	gpio_direction_input(SDHC1_GPIO_DET);
-
-#ifdef PCM970_SDHC_RW_SWITCH
-	ret = gpio_request(SDHC1_GPIO_WP, "sdhc-wp");
-	if (ret)
-		goto err_gpio_free;
-	gpio_direction_input(SDHC1_GPIO_WP);
-#endif
-
-	ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), detect_irq,
-			IRQF_DISABLED | IRQF_TRIGGER_FALLING,
-				"sdhc-detect", data);
-	if (ret)
-		goto err_gpio_free_2;
-
-	return 0;
-
-err_gpio_free_2:
-#ifdef PCM970_SDHC_RW_SWITCH
-	gpio_free(SDHC1_GPIO_WP);
-err_gpio_free:
-#endif
-	gpio_free(SDHC1_GPIO_DET);
-
-	return ret;
-}
-
-static void pcm970_sdhc1_exit(struct device *dev, void *data)
-{
-	free_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), data);
-	gpio_free(SDHC1_GPIO_DET);
-	gpio_free(SDHC1_GPIO_WP);
-}
-
-static struct imxmmc_platform_data sdhc_pdata = {
-#ifdef PCM970_SDHC_RW_SWITCH
-	.get_ro = pcm970_sdhc1_get_ro,
-#endif
-	.init = pcm970_sdhc1_init,
-	.exit = pcm970_sdhc1_exit,
-};
-
-struct mx3_camera_pdata camera_pdata = {
-	.dma_dev	= &mx3_ipu.dev,
-	.flags		= MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10,
-	.mclk_10khz	= 2000,
-};
-
-static int __init pcm037_camera_alloc_dma(const size_t buf_size)
-{
-	dma_addr_t dma_handle;
-	void *buf;
-	int dma;
-
-	if (buf_size < 2 * 1024 * 1024)
-		return -EINVAL;
-
-	buf = dma_alloc_coherent(NULL, buf_size, &dma_handle, GFP_KERNEL);
-	if (!buf) {
-		pr_err("%s: cannot allocate camera buffer-memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	memset(buf, 0, buf_size);
-
-	dma = dma_declare_coherent_memory(&mx3_camera.dev,
-					dma_handle, dma_handle, buf_size,
-					DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
-
-	/* The way we call dma_declare_coherent_memory only a malloc can fail */
-	return dma & DMA_MEMORY_MAP ? 0 : -ENOMEM;
-}
-
-static struct platform_device *devices[] __initdata = {
-	&pcm037_flash,
-	&pcm037_sram_device,
-	&pcm037_mt9t031,
-	&pcm037_mt9v022,
-};
-
-static struct ipu_platform_data mx3_ipu_data = {
-	.irq_base = MXC_IPU_IRQ_START,
-};
-
-static const struct fb_videomode fb_modedb[] = {
-	{
-		/* 240x320 @ 60 Hz Sharp */
-		.name		= "Sharp-LQ035Q7DH06-QVGA",
-		.refresh	= 60,
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= 185925,
-		.left_margin	= 9,
-		.right_margin	= 16,
-		.upper_margin	= 7,
-		.lower_margin	= 9,
-		.hsync_len	= 1,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE |
-				  FB_SYNC_CLK_INVERT | FB_SYNC_CLK_IDLE_EN,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	}, {
-		/* 240x320 @ 60 Hz */
-		.name		= "TX090",
-		.refresh	= 60,
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= 38255,
-		.left_margin	= 144,
-		.right_margin	= 0,
-		.upper_margin	= 7,
-		.lower_margin	= 40,
-		.hsync_len	= 96,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	}, {
-		/* 240x320 @ 60 Hz */
-		.name		= "CMEL-OLED",
-		.refresh	= 60,
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= 185925,
-		.left_margin	= 9,
-		.right_margin	= 16,
-		.upper_margin	= 7,
-		.lower_margin	= 9,
-		.hsync_len	= 1,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	},
-};
-
-static struct mx3fb_platform_data mx3fb_pdata = {
-	.dma_dev	= &mx3_ipu.dev,
-	.name		= "Sharp-LQ035Q7DH06-QVGA",
-	.mode		= fb_modedb,
-	.num_modes	= ARRAY_SIZE(fb_modedb),
-};
-
-static struct resource pcm970_sja1000_resources[] = {
-	{
-		.start   = CS5_BASE_ADDR,
-		.end     = CS5_BASE_ADDR + 0x100 - 1,
-		.flags   = IORESOURCE_MEM,
-	}, {
-		.start   = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)),
-		.end     = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)),
-		.flags   = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
-	},
-};
-
-struct sja1000_platform_data pcm970_sja1000_platform_data = {
-	.clock		= 16000000 / 2,
-	.ocr		= 0x40 | 0x18,
-	.cdr		= 0x40,
-};
-
-static struct platform_device pcm970_sja1000 = {
-	.name = "sja1000_platform",
-	.dev = {
-		.platform_data = &pcm970_sja1000_platform_data,
-	},
-	.resource = pcm970_sja1000_resources,
-	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
-{
-	int ret;
-
-	mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins),
-			"pcm037");
-
-	if (pcm037_variant() == PCM037_EET)
-		mxc_iomux_setup_multiple_pins(pcm037_uart1_pins,
-			ARRAY_SIZE(pcm037_uart1_pins), "pcm037_uart1");
-	else
-		mxc_iomux_setup_multiple_pins(pcm037_uart1_handshake_pins,
-			ARRAY_SIZE(pcm037_uart1_handshake_pins),
-			"pcm037_uart1");
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-	mxc_register_device(&mxc_uart_device1, &uart_pdata);
-	mxc_register_device(&mxc_uart_device2, &uart_pdata);
-
-	mxc_register_device(&mxc_w1_master_device, NULL);
-
-	/* LAN9217 IRQ pin */
-	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1), "lan9217-irq");
-	if (ret)
-		pr_warning("could not get LAN irq gpio\n");
-	else {
-		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
-		platform_device_register(&pcm037_eth);
-	}
-
-
-	/* I2C adapters and devices */
-	i2c_register_board_info(1, pcm037_i2c_devices,
-			ARRAY_SIZE(pcm037_i2c_devices));
-
-	mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
-	mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data);
-
-	mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
-	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
-	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
-	mxc_register_device(&mx3_fb, &mx3fb_pdata);
-	if (!gpio_usbotg_hs_activate())
-		mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
-
-	/* CSI */
-	/* Camera power: default - off */
-	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), "mt9t031-power");
-	if (!ret)
-		gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), 1);
-	else
-		iclink_mt9t031.power = NULL;
-
-	if (!pcm037_camera_alloc_dma(4 * 1024 * 1024))
-		mxc_register_device(&mx3_camera, &camera_pdata);
-
-	platform_device_register(&pcm970_sja1000);
-}
-
-static void __init pcm037_timer_init(void)
-{
-	mx31_clocks_init(26000000);
-}
-
-struct sys_timer pcm037_timer = {
-	.init	= pcm037_timer_init,
-};
-
-MACHINE_START(PCM037, "Phytec Phycore pcm037")
-	/* Maintainer: Pengutronix */
-	.phys_io	= AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx31_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &pcm037_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx3/pcm043.c b/arch/arm/mach-mx3/pcm043.c
deleted file mode 100644
index e3aa829..0000000
--- a/arch/arm/mach-mx3/pcm043.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- *  Copyright (C) 2009 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/plat-ram.h>
-#include <linux/memory.h>
-#include <linux/gpio.h>
-#include <linux/smc911x.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/imx-uart.h>
-#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
-#include <mach/i2c.h>
-#endif
-#include <mach/iomux-mx35.h>
-#include <mach/ipu.h>
-#include <mach/mx3fb.h>
-#include <mach/mxc_nand.h>
-
-#include "devices.h"
-
-static const struct fb_videomode fb_modedb[] = {
-	{
-		/* 240x320 @ 60 Hz */
-		.name		= "Sharp-LQ035Q7",
-		.refresh	= 60,
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= 185925,
-		.left_margin	= 9,
-		.right_margin	= 16,
-		.upper_margin	= 7,
-		.lower_margin	= 9,
-		.hsync_len	= 1,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE | FB_SYNC_CLK_INVERT | FB_SYNC_CLK_IDLE_EN,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	}, {
-		/* 240x320 @ 60 Hz */
-		.name		= "TX090",
-		.refresh	= 60,
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= 38255,
-		.left_margin	= 144,
-		.right_margin	= 0,
-		.upper_margin	= 7,
-		.lower_margin	= 40,
-		.hsync_len	= 96,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
-		.vmode		= FB_VMODE_NONINTERLACED,
-		.flag		= 0,
-	},
-};
-
-static struct ipu_platform_data mx3_ipu_data = {
-	.irq_base = MXC_IPU_IRQ_START,
-};
-
-static struct mx3fb_platform_data mx3fb_pdata = {
-	.dma_dev	= &mx3_ipu.dev,
-	.name		= "Sharp-LQ035Q7",
-	.mode		= fb_modedb,
-	.num_modes	= ARRAY_SIZE(fb_modedb),
-};
-
-static struct physmap_flash_data pcm043_flash_data = {
-	.width  = 2,
-};
-
-static struct resource pcm043_flash_resource = {
-	.start	= 0xa0000000,
-	.end	= 0xa1ffffff,
-	.flags	= IORESOURCE_MEM,
-};
-
-static struct platform_device pcm043_flash = {
-	.name	= "physmap-flash",
-	.id	= 0,
-	.dev	= {
-		.platform_data  = &pcm043_flash_data,
-	},
-	.resource = &pcm043_flash_resource,
-	.num_resources = 1,
-};
-
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
-static struct imxi2c_platform_data pcm043_i2c_1_data = {
-	.bitrate = 50000,
-};
-
-static struct at24_platform_data board_eeprom = {
-	.byte_len = 4096,
-	.page_size = 32,
-	.flags = AT24_FLAG_ADDR16,
-};
-
-static struct i2c_board_info pcm043_i2c_devices[] = {
-       {
-		I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
-		.platform_data = &board_eeprom,
-	}, {
-		I2C_BOARD_INFO("pcf8563", 0x51),
-	}
-};
-#endif
-
-static struct platform_device *devices[] __initdata = {
-	&pcm043_flash,
-	&mxc_fec_device,
-};
-
-static struct pad_desc pcm043_pads[] = {
-	/* UART1 */
-	MX35_PAD_CTS1__UART1_CTS,
-	MX35_PAD_RTS1__UART1_RTS,
-	MX35_PAD_TXD1__UART1_TXD_MUX,
-	MX35_PAD_RXD1__UART1_RXD_MUX,
-	/* UART2 */
-	MX35_PAD_CTS2__UART2_CTS,
-	MX35_PAD_RTS2__UART2_RTS,
-	MX35_PAD_TXD2__UART2_TXD_MUX,
-	MX35_PAD_RXD2__UART2_RXD_MUX,
-	/* FEC */
-	MX35_PAD_FEC_TX_CLK__FEC_TX_CLK,
-	MX35_PAD_FEC_RX_CLK__FEC_RX_CLK,
-	MX35_PAD_FEC_RX_DV__FEC_RX_DV,
-	MX35_PAD_FEC_COL__FEC_COL,
-	MX35_PAD_FEC_RDATA0__FEC_RDATA_0,
-	MX35_PAD_FEC_TDATA0__FEC_TDATA_0,
-	MX35_PAD_FEC_TX_EN__FEC_TX_EN,
-	MX35_PAD_FEC_MDC__FEC_MDC,
-	MX35_PAD_FEC_MDIO__FEC_MDIO,
-	MX35_PAD_FEC_TX_ERR__FEC_TX_ERR,
-	MX35_PAD_FEC_RX_ERR__FEC_RX_ERR,
-	MX35_PAD_FEC_CRS__FEC_CRS,
-	MX35_PAD_FEC_RDATA1__FEC_RDATA_1,
-	MX35_PAD_FEC_TDATA1__FEC_TDATA_1,
-	MX35_PAD_FEC_RDATA2__FEC_RDATA_2,
-	MX35_PAD_FEC_TDATA2__FEC_TDATA_2,
-	MX35_PAD_FEC_RDATA3__FEC_RDATA_3,
-	MX35_PAD_FEC_TDATA3__FEC_TDATA_3,
-	/* I2C1 */
-	MX35_PAD_I2C1_CLK__I2C1_SCL,
-	MX35_PAD_I2C1_DAT__I2C1_SDA,
-	/* Display */
-	MX35_PAD_LD0__IPU_DISPB_DAT_0,
-	MX35_PAD_LD1__IPU_DISPB_DAT_1,
-	MX35_PAD_LD2__IPU_DISPB_DAT_2,
-	MX35_PAD_LD3__IPU_DISPB_DAT_3,
-	MX35_PAD_LD4__IPU_DISPB_DAT_4,
-	MX35_PAD_LD5__IPU_DISPB_DAT_5,
-	MX35_PAD_LD6__IPU_DISPB_DAT_6,
-	MX35_PAD_LD7__IPU_DISPB_DAT_7,
-	MX35_PAD_LD8__IPU_DISPB_DAT_8,
-	MX35_PAD_LD9__IPU_DISPB_DAT_9,
-	MX35_PAD_LD10__IPU_DISPB_DAT_10,
-	MX35_PAD_LD11__IPU_DISPB_DAT_11,
-	MX35_PAD_LD12__IPU_DISPB_DAT_12,
-	MX35_PAD_LD13__IPU_DISPB_DAT_13,
-	MX35_PAD_LD14__IPU_DISPB_DAT_14,
-	MX35_PAD_LD15__IPU_DISPB_DAT_15,
-	MX35_PAD_LD16__IPU_DISPB_DAT_16,
-	MX35_PAD_LD17__IPU_DISPB_DAT_17,
-	MX35_PAD_D3_HSYNC__IPU_DISPB_D3_HSYNC,
-	MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK,
-	MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY,
-	MX35_PAD_CONTRAST__IPU_DISPB_CONTR,
-	MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC,
-	MX35_PAD_D3_REV__IPU_DISPB_D3_REV,
-	MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS,
-	/* gpio */
-	MX35_PAD_ATA_CS0__GPIO2_6,
-};
-
-static struct mxc_nand_platform_data pcm037_nand_board_info = {
-	.width = 1,
-	.hw_ecc = 1,
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-	mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
-
-	mxc_register_device(&mxc_uart_device1, &uart_pdata);
-
-#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
-	i2c_register_board_info(0, pcm043_i2c_devices,
-			ARRAY_SIZE(pcm043_i2c_devices));
-
-	mxc_register_device(&mxc_i2c_device0, &pcm043_i2c_1_data);
-#endif
-
-	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
-	mxc_register_device(&mx3_fb, &mx3fb_pdata);
-}
-
-static void __init pcm043_timer_init(void)
-{
-	mx35_clocks_init();
-}
-
-struct sys_timer pcm043_timer = {
-	.init	= pcm043_timer_init,
-};
-
-MACHINE_START(PCM043, "Phytec Phycore pcm043")
-	/* Maintainer: Pengutronix */
-	.phys_io	= AIPS1_BASE_ADDR,
-	.io_pg_offst	= ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx35_map_io,
-	.init_irq       = mx35_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &pcm043_timer,
-MACHINE_END
-
diff --git a/arch/arm/mach-mx3/qong.c b/arch/arm/mach-mx3/qong.c
deleted file mode 100644
index 044511f..0000000
--- a/arch/arm/mach-mx3/qong.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- *  Copyright (C) 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/memory.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/nand.h>
-#include <linux/gpio.h>
-
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-#include <mach/common.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-#include <mach/board-qong.h>
-#include <mach/imx-uart.h>
-#include <mach/iomux-mx3.h>
-#include "devices.h"
-
-/* FPGA defines */
-#define QONG_FPGA_VERSION(major, minor, rev)	\
-	(((major & 0xF) << 12) | ((minor & 0xF) << 8) | (rev & 0xFF))
-
-#define QONG_FPGA_BASEADDR 		CS1_BASE_ADDR
-#define QONG_FPGA_PERIPH_SIZE 		(1 << 24)
-
-#define QONG_FPGA_CTRL_BASEADDR		QONG_FPGA_BASEADDR
-#define QONG_FPGA_CTRL_SIZE 		0x10
-/* FPGA control registers */
-#define QONG_FPGA_CTRL_VERSION		0x00
-
-#define QONG_DNET_ID		1
-#define QONG_DNET_BASEADDR	\
-	(QONG_FPGA_BASEADDR + QONG_DNET_ID * QONG_FPGA_PERIPH_SIZE)
-#define QONG_DNET_SIZE 		0x00001000
-
-#define QONG_FPGA_IRQ		IOMUX_TO_IRQ(MX31_PIN_DTR_DCE1)
-
-/*
- * This file contains the board-specific initialization routines.
- */
-
-static struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static int uart_pins[] = {
-	MX31_PIN_CTS1__CTS1,
-	MX31_PIN_RTS1__RTS1,
-	MX31_PIN_TXD1__TXD1,
-	MX31_PIN_RXD1__RXD1
-};
-
-static inline void mxc_init_imx_uart(void)
-{
-	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins),
-			"uart-0");
-	mxc_register_device(&mxc_uart_device0, &uart_pdata);
-}
-
-static struct resource dnet_resources[] = {
-	{
-		.name	= "dnet-memory",
-		.start	= QONG_DNET_BASEADDR,
-		.end	= QONG_DNET_BASEADDR + QONG_DNET_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	}, {
-		.start	= QONG_FPGA_IRQ,
-		.end	= QONG_FPGA_IRQ,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device dnet_device = {
-	.name			= "dnet",
-	.id			= -1,
-	.num_resources		= ARRAY_SIZE(dnet_resources),
-	.resource		= dnet_resources,
-};
-
-static int __init qong_init_dnet(void)
-{
-	int ret;
-
-	ret = platform_device_register(&dnet_device);
-	return ret;
-}
-
-/* MTD NOR flash */
-
-static struct physmap_flash_data qong_flash_data = {
-	.width = 2,
-};
-
-static struct resource qong_flash_resource = {
-	.start = CS0_BASE_ADDR,
-	.end = CS0_BASE_ADDR + QONG_NOR_SIZE - 1,
-	.flags = IORESOURCE_MEM,
-};
-
-static struct platform_device qong_nor_mtd_device = {
-	.name = "physmap-flash",
-	.id = 0,
-	.dev = {
-		.platform_data = &qong_flash_data,
-		},
-	.resource = &qong_flash_resource,
-	.num_resources = 1,
-};
-
-static void qong_init_nor_mtd(void)
-{
-	(void)platform_device_register(&qong_nor_mtd_device);
-}
-
-/*
- * Hardware specific access to control-lines
- */
-static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
-	struct nand_chip *nand_chip = mtd->priv;
-
-	if (cmd == NAND_CMD_NONE)
-		return;
-
-	if (ctrl & NAND_CLE)
-		writeb(cmd, nand_chip->IO_ADDR_W + (1 << 24));
-	else
-		writeb(cmd, nand_chip->IO_ADDR_W + (1 << 23));
-}
-
-/*
- * Read the Device Ready pin.
- */
-static int qong_nand_device_ready(struct mtd_info *mtd)
-{
-	return gpio_get_value(IOMUX_TO_GPIO(MX31_PIN_NFRB));
-}
-
-static void qong_nand_select_chip(struct mtd_info *mtd, int chip)
-{
-	if (chip >= 0)
-		gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
-	else
-		gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 1);
-}
-
-static struct platform_nand_data qong_nand_data = {
-	.chip = {
-		.chip_delay		= 20,
-		.options		= 0,
-	},
-	.ctrl = {
-		.cmd_ctrl 		= qong_nand_cmd_ctrl,
-		.dev_ready		= qong_nand_device_ready,
-		.select_chip		= qong_nand_select_chip,
-	}
-};
-
-static struct resource qong_nand_resource = {
-	.start  	= CS3_BASE_ADDR,
-	.end    	= CS3_BASE_ADDR + SZ_32M - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device qong_nand_device = {
-	.name		= "gen_nand",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &qong_nand_data,
-	},
-	.num_resources	= 1,
-	.resource	= &qong_nand_resource,
-};
-
-static void __init qong_init_nand_mtd(void)
-{
-	/* init CS */
-	__raw_writel(0x00004f00, CSCR_U(3));
-	__raw_writel(0x20013b31, CSCR_L(3));
-	__raw_writel(0x00020800, CSCR_A(3));
-	mxc_iomux_set_gpr(MUX_SDCTL_CSD1_SEL, true);
-
-	/* enable pin */
-	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFCE_B, IOMUX_CONFIG_GPIO));
-	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), "nand_enable"))
-		gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_NFCE_B), 0);
-
-	/* ready/busy pin */
-	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFRB, IOMUX_CONFIG_GPIO));
-	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFRB), "nand_rdy"))
-		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFRB));
-
-	/* write protect pin */
-	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_NFWP_B, IOMUX_CONFIG_GPIO));
-	if (!gpio_request(IOMUX_TO_GPIO(MX31_PIN_NFWP_B), "nand_wp"))
-		gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_NFWP_B));
-
-	platform_device_register(&qong_nand_device);
-}
-
-static void __init qong_init_fpga(void)
-{
-	void __iomem *regs;
-	u32 fpga_ver;
-
-	regs = ioremap(QONG_FPGA_CTRL_BASEADDR, QONG_FPGA_CTRL_SIZE);
-	if (!regs) {
-		printk(KERN_ERR "%s: failed to map registers, aborting.\n",
-				__func__);
-		return;
-	}
-
-	fpga_ver = readl(regs + QONG_FPGA_CTRL_VERSION);
-	iounmap(regs);
-	printk(KERN_INFO "Qong FPGA version %d.%d.%d\n",
-			(fpga_ver & 0xF000) >> 12,
-			(fpga_ver & 0x0F00) >> 8, fpga_ver & 0x00FF);
-	if (fpga_ver < QONG_FPGA_VERSION(0, 8, 7)) {
-		printk(KERN_ERR "qong: Unexpected FPGA version, FPGA-based "
-				"devices won't be registered!\n");
-		return;
-	}
-
-	/* register FPGA-based devices */
-	qong_init_nand_mtd();
-	qong_init_dnet();
-}
-
-/*
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
-{
-	mxc_init_imx_uart();
-	qong_init_nor_mtd();
-	qong_init_fpga();
-}
-
-static void __init qong_timer_init(void)
-{
-	mx31_clocks_init(26000000);
-}
-
-static struct sys_timer qong_timer = {
-	.init	= qong_timer_init,
-};
-
-/*
- * The following uses standard kernel macros defined in arch.h in order to
- * initialize __mach_desc_QONG data structure.
- */
-
-MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
-	/* Maintainer: DENX Software Engineering GmbH */
-	.phys_io        = AIPS1_BASE_ADDR,
-	.io_pg_offst    = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params    = PHYS_OFFSET + 0x100,
-	.map_io         = mx31_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &qong_timer,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
new file mode 100644
index 0000000..1576d51
--- /dev/null
+++ b/arch/arm/mach-mx5/Kconfig
@@ -0,0 +1,18 @@
+if ARCH_MX5
+
+config ARCH_MX51
+	bool
+	default y
+	select MXC_TZIC
+	select ARCH_MXC_IOMUX_V3
+
+comment "MX5 platforms:"
+
+config MACH_MX51_BABBAGE
+	bool "Support MX51 BABBAGE platforms"
+	help
+	  Include support for MX51 Babbage platform, also known as MX51EVK in
+	  u-boot. 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
new file mode 100644
index 0000000..bf23f86
--- /dev/null
+++ b/arch/arm/mach-mx5/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+obj-y   := cpu.o mm.o clock-mx51.o devices.o
+
+obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
+
diff --git a/arch/arm/mach-mx5/Makefile.boot b/arch/arm/mach-mx5/Makefile.boot
new file mode 100644
index 0000000..9939a19
--- /dev/null
+++ b/arch/arm/mach-mx5/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x90008000
+params_phys-y	:= 0x90000100
+initrd_phys-y	:= 0x90800000
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
new file mode 100644
index 0000000..ee67a71
--- /dev/null
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2009 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/init.h>
+#include <linux/platform_device.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/imx-uart.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices.h"
+
+static struct platform_device *devices[] __initdata = {
+	&mxc_fec_device,
+};
+
+static struct pad_desc mx51babbage_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,
+
+	/* UART2 */
+	MX51_PAD_UART2_RXD__UART2_RXD,
+	MX51_PAD_UART2_TXD__UART2_TXD,
+
+	/* UART3 */
+	MX51_PAD_EIM_D25__UART3_RXD,
+	MX51_PAD_EIM_D26__UART3_TXD,
+	MX51_PAD_EIM_D27__UART3_RTS,
+	MX51_PAD_EIM_D24__UART3_CTS,
+};
+
+/* Serial ports */
+#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
+static struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static inline void mxc_init_imx_uart(void)
+{
+	mxc_register_device(&mxc_uart_device0, &uart_pdata);
+	mxc_register_device(&mxc_uart_device1, &uart_pdata);
+	mxc_register_device(&mxc_uart_device2, &uart_pdata);
+}
+#else /* !SERIAL_IMX */
+static inline void mxc_init_imx_uart(void)
+{
+}
+#endif /* SERIAL_IMX */
+
+/*
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
+					ARRAY_SIZE(mx51babbage_pads));
+	mxc_init_imx_uart();
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static void __init mx51_babbage_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mxc_timer = {
+	.init	= mx51_babbage_timer_init,
+};
+
+MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
+	/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
+	.phys_io = MX51_AIPS1_BASE_ADDR,
+	.io_pg_offst = ((MX51_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+	.boot_params = PHYS_OFFSET + 0x100,
+	.map_io = mx51_map_io,
+	.init_irq = mx51_init_irq,
+	.init_machine = mxc_board_init,
+	.timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
new file mode 100644
index 0000000..be90c03
--- /dev/null
+++ b/arch/arm/mach-mx5/clock-mx51.c
@@ -0,0 +1,825 @@
+/*
+ * 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 <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;
+
+#define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
+
+static int _clk_ccgr_enable(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg |= MXC_CCM_CCGRx_MOD_ON << clk->enable_shift;
+	__raw_writel(reg, clk->enable_reg);
+
+	return 0;
+}
+
+static void _clk_ccgr_disable(struct clk *clk)
+{
+	u32 reg;
+	reg = __raw_readl(clk->enable_reg);
+	reg &= ~(MXC_CCM_CCGRx_MOD_OFF << clk->enable_shift);
+	__raw_writel(reg, clk->enable_reg);
+
+}
+
+static void _clk_ccgr_disable_inwait(struct clk *clk)
+{
+	u32 reg;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+	reg |= MXC_CCM_CCGRx_MOD_IDLE << clk->enable_shift;
+	__raw_writel(reg, clk->enable_reg);
+}
+
+/*
+ * 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_arm_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_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;
+}
+
+static unsigned long clk_uart_get_rate(struct clk *clk)
+{
+	u32 reg, prediv, podf;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(MXC_CCM_CSCDR1);
+	prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
+		  MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1;
+	podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
+		MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
+
+	return parent_rate / (prediv * podf);
+}
+
+static int _clk_uart_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_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK;
+	reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	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;
+}
+
+/* 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_arm_get_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 uart_root_clk = {
+	.parent = &pll2_sw_clk,
+	.get_rate = clk_uart_get_rate,
+	.set_parent = _clk_uart_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,
+};
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)	\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.get_rate	= gr,			\
+		.set_rate	= sr,			\
+		.enable		= _clk_ccgr_enable,	\
+		.disable	= _clk_ccgr_disable,	\
+		.parent		= p,			\
+		.secondary	= s,			\
+	}
+
+/* DEFINE_CLOCK(name, id, enable_reg, enable_shift,
+   get_rate, set_rate, parent, secondary); */
+
+/* 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_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
+	NULL,  NULL, &uart_root_clk, NULL);
+DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
+	NULL,  NULL, &uart_root_clk, NULL);
+DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
+	NULL,  NULL, &uart_root_clk, NULL);
+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);
+
+/* GPT */
+DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
+	NULL,  NULL, &ipg_perclk, NULL);
+DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_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);
+
+#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)
+};
+
+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);
+
+	/* 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
new file mode 100644
index 0000000..41c769f
--- /dev/null
+++ b/arch/arm/mach-mx5/cpu.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008-2009 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
+ *
+ * This file contains the CPU initialization code.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+
+static int __init post_cpu_init(void)
+{
+	unsigned int reg;
+	void __iomem *base;
+
+	if (!cpu_is_mx51())
+		return 0;
+
+	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);
+
+	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);
+
+	return 0;
+}
+
+postcore_initcall(post_cpu_init);
diff --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h
new file mode 100644
index 0000000..c776b9a
--- /dev/null
+++ b/arch/arm/mach-mx5/crm_regs.h
@@ -0,0 +1,583 @@
+/*
+ * Copyright 2008-2009 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
+ */
+#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
+#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
+
+#define MX51_CCM_BASE		MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)
+#define MX51_DPLL1_BASE		MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR)
+#define MX51_DPLL2_BASE		MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR)
+#define MX51_DPLL3_BASE		MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR)
+#define MX51_CORTEXA8_BASE	MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
+#define MX51_GPC_BASE		MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
+
+/* PLL Register Offsets */
+#define MXC_PLL_DP_CTL			0x00
+#define MXC_PLL_DP_CONFIG		0x04
+#define MXC_PLL_DP_OP			0x08
+#define MXC_PLL_DP_MFD			0x0C
+#define MXC_PLL_DP_MFN			0x10
+#define MXC_PLL_DP_MFNMINUS		0x14
+#define MXC_PLL_DP_MFNPLUS		0x18
+#define MXC_PLL_DP_HFS_OP		0x1C
+#define MXC_PLL_DP_HFS_MFD		0x20
+#define MXC_PLL_DP_HFS_MFN		0x24
+#define MXC_PLL_DP_MFN_TOGC		0x28
+#define MXC_PLL_DP_DESTAT		0x2c
+
+/* PLL Register Bit definitions */
+#define MXC_PLL_DP_CTL_MUL_CTRL		0x2000
+#define MXC_PLL_DP_CTL_DPDCK0_2_EN	0x1000
+#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET	12
+#define MXC_PLL_DP_CTL_ADE		0x800
+#define MXC_PLL_DP_CTL_REF_CLK_DIV	0x400
+#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK	(3 << 8)
+#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET	8
+#define MXC_PLL_DP_CTL_HFSM		0x80
+#define MXC_PLL_DP_CTL_PRE		0x40
+#define MXC_PLL_DP_CTL_UPEN		0x20
+#define MXC_PLL_DP_CTL_RST		0x10
+#define MXC_PLL_DP_CTL_RCP		0x8
+#define MXC_PLL_DP_CTL_PLM		0x4
+#define MXC_PLL_DP_CTL_BRM0		0x2
+#define MXC_PLL_DP_CTL_LRF		0x1
+
+#define MXC_PLL_DP_CONFIG_BIST		0x8
+#define MXC_PLL_DP_CONFIG_SJC_CE	0x4
+#define MXC_PLL_DP_CONFIG_AREN		0x2
+#define MXC_PLL_DP_CONFIG_LDREQ		0x1
+
+#define MXC_PLL_DP_OP_MFI_OFFSET	4
+#define MXC_PLL_DP_OP_MFI_MASK		(0xF << 4)
+#define MXC_PLL_DP_OP_PDF_OFFSET	0
+#define MXC_PLL_DP_OP_PDF_MASK		0xF
+
+#define MXC_PLL_DP_MFD_OFFSET		0
+#define MXC_PLL_DP_MFD_MASK		0x07FFFFFF
+
+#define MXC_PLL_DP_MFN_OFFSET		0x0
+#define MXC_PLL_DP_MFN_MASK		0x07FFFFFF
+
+#define MXC_PLL_DP_MFN_TOGC_TOG_DIS	(1 << 17)
+#define MXC_PLL_DP_MFN_TOGC_TOG_EN	(1 << 16)
+#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET	0x0
+#define MXC_PLL_DP_MFN_TOGC_CNT_MASK	0xFFFF
+
+#define MXC_PLL_DP_DESTAT_TOG_SEL	(1 << 31)
+#define MXC_PLL_DP_DESTAT_MFN		0x07FFFFFF
+
+/* Register addresses of CCM*/
+#define MXC_CCM_CCR		(MX51_CCM_BASE + 0x00)
+#define MXC_CCM_CCDR		(MX51_CCM_BASE + 0x04)
+#define MXC_CCM_CSR		(MX51_CCM_BASE + 0x08)
+#define MXC_CCM_CCSR		(MX51_CCM_BASE + 0x0C)
+#define MXC_CCM_CACRR		(MX51_CCM_BASE + 0x10)
+#define MXC_CCM_CBCDR		(MX51_CCM_BASE + 0x14)
+#define MXC_CCM_CBCMR		(MX51_CCM_BASE + 0x18)
+#define MXC_CCM_CSCMR1		(MX51_CCM_BASE + 0x1C)
+#define MXC_CCM_CSCMR2		(MX51_CCM_BASE + 0x20)
+#define MXC_CCM_CSCDR1		(MX51_CCM_BASE + 0x24)
+#define MXC_CCM_CS1CDR		(MX51_CCM_BASE + 0x28)
+#define MXC_CCM_CS2CDR		(MX51_CCM_BASE + 0x2C)
+#define MXC_CCM_CDCDR		(MX51_CCM_BASE + 0x30)
+#define MXC_CCM_CHSCDR		(MX51_CCM_BASE + 0x34)
+#define MXC_CCM_CSCDR2		(MX51_CCM_BASE + 0x38)
+#define MXC_CCM_CSCDR3		(MX51_CCM_BASE + 0x3C)
+#define MXC_CCM_CSCDR4		(MX51_CCM_BASE + 0x40)
+#define MXC_CCM_CWDR		(MX51_CCM_BASE + 0x44)
+#define MXC_CCM_CDHIPR		(MX51_CCM_BASE + 0x48)
+#define MXC_CCM_CDCR		(MX51_CCM_BASE + 0x4C)
+#define MXC_CCM_CTOR		(MX51_CCM_BASE + 0x50)
+#define MXC_CCM_CLPCR		(MX51_CCM_BASE + 0x54)
+#define MXC_CCM_CISR		(MX51_CCM_BASE + 0x58)
+#define MXC_CCM_CIMR		(MX51_CCM_BASE + 0x5C)
+#define MXC_CCM_CCOSR		(MX51_CCM_BASE + 0x60)
+#define MXC_CCM_CGPR		(MX51_CCM_BASE + 0x64)
+#define MXC_CCM_CCGR0		(MX51_CCM_BASE + 0x68)
+#define MXC_CCM_CCGR1		(MX51_CCM_BASE + 0x6C)
+#define MXC_CCM_CCGR2		(MX51_CCM_BASE + 0x70)
+#define MXC_CCM_CCGR3		(MX51_CCM_BASE + 0x74)
+#define MXC_CCM_CCGR4		(MX51_CCM_BASE + 0x78)
+#define MXC_CCM_CCGR5		(MX51_CCM_BASE + 0x7C)
+#define MXC_CCM_CCGR6		(MX51_CCM_BASE + 0x80)
+#define MXC_CCM_CMEOR		(MX51_CCM_BASE + 0x84)
+
+/* Define the bits in register CCR */
+#define MXC_CCM_CCR_COSC_EN		(1 << 12)
+#define MXC_CCM_CCR_FPM_MULT_MASK	(1 << 11)
+#define MXC_CCM_CCR_CAMP2_EN		(1 << 10)
+#define MXC_CCM_CCR_CAMP1_EN		(1 << 9)
+#define MXC_CCM_CCR_FPM_EN		(1 << 8)
+#define MXC_CCM_CCR_OSCNT_OFFSET	(0)
+#define MXC_CCM_CCR_OSCNT_MASK	(0xFF)
+
+/* Define the bits in register CCDR */
+#define MXC_CCM_CCDR_HSC_HS_MASK	(0x1 << 18)
+#define MXC_CCM_CCDR_IPU_HS_MASK	(0x1 << 17)
+#define MXC_CCM_CCDR_EMI_HS_MASK	(0x1 << 16)
+
+/* Define the bits in register CSR */
+#define MXC_CCM_CSR_COSR_READY	(1 << 5)
+#define MXC_CCM_CSR_LVS_VALUE	(1 << 4)
+#define MXC_CCM_CSR_CAMP2_READY	(1 << 3)
+#define MXC_CCM_CSR_CAMP1_READY	(1 << 2)
+#define MXC_CCM_CSR_FPM_READY	(1 << 1)
+#define MXC_CCM_CSR_REF_EN_B	(1 << 0)
+
+/* Define the bits in register CCSR */
+#define MXC_CCM_CCSR_LP_APM_SEL		(0x1 << 9)
+#define MXC_CCM_CCSR_STEP_SEL_OFFSET	(7)
+#define MXC_CCM_CCSR_STEP_SEL_MASK	(0x3 << 7)
+#define MXC_CCM_CCSR_STEP_SEL_LP_APM	   0
+#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS  1 /* Only when JTAG connected? */
+#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2
+#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3
+#define MXC_CCM_CCSR_PLL2_PODF_OFFSET	(5)
+#define MXC_CCM_CCSR_PLL2_PODF_MASK	(0x3 << 5)
+#define MXC_CCM_CCSR_PLL3_PODF_OFFSET	(3)
+#define MXC_CCM_CCSR_PLL3_PODF_MASK	(0x3 << 3)
+#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL	(1 << 2) /* 0: pll1_main_clk,
+						    1: step_clk */
+#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL	(1 << 1)
+#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL	(1 << 0)
+
+/* Define the bits in register CACRR */
+#define MXC_CCM_CACRR_ARM_PODF_OFFSET	(0)
+#define MXC_CCM_CACRR_ARM_PODF_MASK	(0x7)
+
+/* Define the bits in register CBCDR */
+#define MXC_CCM_CBCDR_EMI_CLK_SEL		(0x1 << 26)
+#define MXC_CCM_CBCDR_PERIPH_CLK_SEL		(0x1 << 25)
+#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET		(30)
+#define MXC_CCM_CBCDR_DDR_HF_SEL		(0x1 << 30)
+#define MXC_CCM_CBCDR_DDR_PODF_OFFSET		(27)
+#define MXC_CCM_CBCDR_DDR_PODF_MASK		(0x7 << 27)
+#define MXC_CCM_CBCDR_EMI_PODF_OFFSET		(22)
+#define MXC_CCM_CBCDR_EMI_PODF_MASK		(0x7 << 22)
+#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET		(19)
+#define MXC_CCM_CBCDR_AXI_B_PODF_MASK		(0x7 << 19)
+#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET		(16)
+#define MXC_CCM_CBCDR_AXI_A_PODF_MASK		(0x7 << 16)
+#define MXC_CCM_CBCDR_NFC_PODF_OFFSET		(13)
+#define MXC_CCM_CBCDR_NFC_PODF_MASK		(0x7 << 13)
+#define MXC_CCM_CBCDR_AHB_PODF_OFFSET		(10)
+#define MXC_CCM_CBCDR_AHB_PODF_MASK		(0x7 << 10)
+#define MXC_CCM_CBCDR_IPG_PODF_OFFSET		(8)
+#define MXC_CCM_CBCDR_IPG_PODF_MASK		(0x3 << 8)
+#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET	(6)
+#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK		(0x3 << 6)
+#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET	(3)
+#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK		(0x7 << 3)
+#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET	(0)
+#define MXC_CCM_CBCDR_PERCLK_PODF_MASK		(0x7)
+
+/* Define the bits in register CBCMR */
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET	(14)
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK	(0x3 << 14)
+#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET	(12)
+#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK	(0x3 << 12)
+#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET	(10)
+#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK		(0x3 << 10)
+#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET	(8)
+#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK	(0x3 << 8)
+#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET	(6)
+#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK	(0x3 << 6)
+#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET	(4)
+#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK		(0x3 << 4)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET	(14)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK	(0x3 << 14)
+#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL	(0x1 << 1)
+#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL	(0x1 << 0)
+
+/* Define the bits in register CSCMR1 */
+#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET		(30)
+#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK		(0x3 << 30)
+#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET		(28)
+#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK		(0x3 << 28)
+#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET		(26)
+#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL			(0x1 << 26)
+#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET		(24)
+#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK		(0x3 << 24)
+#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET		(22)
+#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK		(0x3 << 22)
+#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET	(20)
+#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK	(0x3 << 20)
+#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL			(0x1 << 19)
+#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL			(0x1 << 18)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET	(16)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK	(0x3 << 16)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET		(14)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK		(0x3 << 14)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET		(12)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK		(0x3 << 12)
+#define MXC_CCM_CSCMR1_SSI3_CLK_SEL			(0x1 << 11)
+#define MXC_CCM_CSCMR1_VPU_RCLK_SEL			(0x1 << 10)
+#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET		(8)
+#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK		(0x3 << 8)
+#define MXC_CCM_CSCMR1_TVE_CLK_SEL			(0x1 << 7)
+#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL			(0x1 << 6)
+#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET		(4)
+#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK		(0x3 << 4)
+#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET		(2)
+#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK		(0x3 << 2)
+#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL		(0x1 << 1)
+#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL		(0x1)
+
+/* Define the bits in register CSCMR2 */
+#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n)		(26+n*3)
+#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n)		(0x7 << (26+n*3))
+#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET		(24)
+#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK		(0x3 << 24)
+#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET		(22)
+#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK		(0x3 << 22)
+#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET		(20)
+#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK			(0x3 << 20)
+#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET		(18)
+#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK		(0x3 << 18)
+#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET		(16)
+#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK		(0x3 << 16)
+#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET		(14)
+#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK		(0x3 << 14)
+#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET		(12)
+#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK		(0x3 << 12)
+#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET		(10)
+#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK			(0x3 << 10)
+#define MXC_CCM_CSCMR2_SLIMBUS_COM			(0x1 << 9)
+#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET		(6)
+#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK		(0x7 << 6)
+#define MXC_CCM_CSCMR2_SPDIF1_COM			(1 << 5)
+#define MXC_CCM_CSCMR2_SPDIF0_COM			(1 << 4)
+#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET		(2)
+#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK		(0x3 << 2)
+#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET		(0)
+#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK		(0x3)
+
+/* Define the bits in register CSCDR1 */
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET	(22)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK	(0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET	(19)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK	(0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET	(16)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK	(0x7 << 16)
+#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET		(14)
+#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK		(0x3 << 14)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET	(11)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK	(0x7 << 11)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET		(8)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK		(0x7 << 8)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET		(6)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK		(0x3 << 6)
+#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET		(3)
+#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK		(0x7 << 3)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET		(0)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK		(0x7)
+
+/* Define the bits in register CS1CDR and CS2CDR */
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET		(22)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK		(0x7 << 22)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET		(16)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK		(0x3F << 16)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET		(6)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK		(0x7 << 6)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET		(0)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK		(0x3F)
+
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET		(22)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK		(0x7 << 22)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET		(16)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK		(0x3F << 16)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET		(6)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK		(0x7 << 6)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET		(0)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK		(0x3F)
+
+/* Define the bits in register CDCDR */
+#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET		(28)
+#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK			(0x7 << 28)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET		(25)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK		(0x7 << 25)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET		(19)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK		(0x3F << 19)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET		(16)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK		(0x7 << 16)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET		(9)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK		(0x3F << 9)
+#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET		(6)
+#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK			(0x7 << 6)
+#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET		(3)
+#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK			(0x7 << 3)
+#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET		(0)
+#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK			(0x7)
+
+/* Define the bits in register CHSCCDR */
+#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET		(12)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK		(0x7 << 12)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET		(6)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK		(0x3F << 6)
+#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET		(3)
+#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK		(0x7 << 3)
+#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET		(0)
+#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK		(0x7)
+
+/* Define the bits in register CSCDR2 */
+#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET		(25)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK		(0x7 << 25)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET		(19)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK		(0x3F << 19)
+#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET		(16)
+#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK		(0x7 << 16)
+#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET		(9)
+#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK		(0x3F << 9)
+#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET		(6)
+#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK		(0x7 << 6)
+#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET		(0)
+#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK		(0x3F)
+
+/* Define the bits in register CSCDR3 */
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET		(16)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK		(0x7 << 16)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET		(9)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK		(0x3F << 9)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET		(6)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK		(0x7 << 6)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET		(0)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK		(0x3F)
+
+/* Define the bits in register CSCDR4 */
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET	(16)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK		(0x7 << 16)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET	(9)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK		(0x3F << 9)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET	(6)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK		(0x7 << 6)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET	(0)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK		(0x3F)
+
+/* Define the bits in register CDHIPR */
+#define MXC_CCM_CDHIPR_ARM_PODF_BUSY			(1 << 16)
+#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY		(1 << 8)
+#define MXC_CCM_CDHIPR_DDR_PODF_BUSY			(1 << 7)
+#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY			(1 << 6)
+#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY		(1 << 5)
+#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY	(1 << 4)
+#define MXC_CCM_CDHIPR_AHB_PODF_BUSY			(1 << 3)
+#define MXC_CCM_CDHIPR_EMI_PODF_BUSY			(1 << 2)
+#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY			(1 << 1)
+#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY			(1 << 0)
+
+/* Define the bits in register CDCR */
+#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER		(0x1 << 2)
+#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET	(0)
+#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK		(0x3)
+
+/* 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 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)
+#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS	(0x1 << 17)
+#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS	(0x1 << 16)
+#define MXC_CCM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
+#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET		(9)
+#define MXC_CCM_CLPCR_STBY_COUNT_MASK		(0x3 << 9)
+#define MXC_CCM_CLPCR_VSTBY			(0x1 << 8)
+#define MXC_CCM_CLPCR_DIS_REF_OSC		(0x1 << 7)
+#define MXC_CCM_CLPCR_SBYOS			(0x1 << 6)
+#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET	(3)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK		(0x3 << 3)
+#define MXC_CCM_CLPCR_LPM_OFFSET		(0)
+#define MXC_CCM_CLPCR_LPM_MASK			(0x3)
+
+/* Define the bits in register CISR */
+#define MXC_CCM_CISR_ARM_PODF_LOADED			(0x1 << 25)
+#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED	(0x1 << 21)
+#define MXC_CCM_CISR_AHB_PODF_LOADED			(0x1 << 20)
+#define MXC_CCM_CISR_EMI_PODF_LOADED			(0x1 << 19)
+#define MXC_CCM_CISR_AXI_B_PODF_LOADED			(0x1 << 18)
+#define MXC_CCM_CISR_AXI_A_PODF_LOADED			(0x1 << 17)
+#define MXC_CCM_CISR_DIVIDER_LOADED			(0x1 << 16)
+#define MXC_CCM_CISR_COSC_READY				(0x1 << 6)
+#define MXC_CCM_CISR_CKIH2_READY			(0x1 << 5)
+#define MXC_CCM_CISR_CKIH_READY				(0x1 << 4)
+#define MXC_CCM_CISR_FPM_READY				(0x1 << 3)
+#define MXC_CCM_CISR_LRF_PLL3				(0x1 << 2)
+#define MXC_CCM_CISR_LRF_PLL2				(0x1 << 1)
+#define MXC_CCM_CISR_LRF_PLL1				(0x1)
+
+/* Define the bits in register CIMR */
+#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED		(0x1 << 25)
+#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED	(0x1 << 21)
+#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED		(0x1 << 20)
+#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED		(0x1 << 19)
+#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED		(0x1 << 18)
+#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED		(0x1 << 17)
+#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED		(0x1 << 16)
+#define MXC_CCM_CIMR_MASK_COSC_READY			(0x1 << 5)
+#define MXC_CCM_CIMR_MASK_CKIH_READY			(0x1 << 4)
+#define MXC_CCM_CIMR_MASK_FPM_READY			(0x1 << 3)
+#define MXC_CCM_CIMR_MASK_LRF_PLL3			(0x1 << 2)
+#define MXC_CCM_CIMR_MASK_LRF_PLL2			(0x1 << 1)
+#define MXC_CCM_CIMR_MASK_LRF_PLL1			(0x1)
+
+/* Define the bits in register CCOSR */
+#define MXC_CCM_CCOSR_CKO2_EN_OFFSET			(0x1 << 24)
+#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET			(21)
+#define MXC_CCM_CCOSR_CKO2_DIV_MASK			(0x7 << 21)
+#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET			(16)
+#define MXC_CCM_CCOSR_CKO2_SEL_MASK			(0x1F << 16)
+#define MXC_CCM_CCOSR_CKOL_EN				(0x1 << 7)
+#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET			(4)
+#define MXC_CCM_CCOSR_CKOL_DIV_MASK			(0x7 << 4)
+#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET			(0)
+#define MXC_CCM_CCOSR_CKOL_SEL_MASK			(0xF)
+
+/* Define the bits in registers CGPR */
+#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE		(0x1 << 4)
+#define MXC_CCM_CGPR_FPM_SEL				(0x1 << 3)
+#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET		(0)
+#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK		(0x7)
+
+/* Define the bits in registers CCGRx */
+#define MXC_CCM_CCGRx_CG_MASK				0x3
+#define MXC_CCM_CCGRx_MOD_OFF				0x0
+#define MXC_CCM_CCGRx_MOD_ON				0x3
+#define MXC_CCM_CCGRx_MOD_IDLE				0x1
+
+#define MXC_CCM_CCGRx_CG15_MASK				(0x3 << 30)
+#define MXC_CCM_CCGRx_CG14_MASK				(0x3 << 28)
+#define MXC_CCM_CCGRx_CG13_MASK				(0x3 << 26)
+#define MXC_CCM_CCGRx_CG12_MASK				(0x3 << 24)
+#define MXC_CCM_CCGRx_CG11_MASK				(0x3 << 22)
+#define MXC_CCM_CCGRx_CG10_MASK				(0x3 << 20)
+#define MXC_CCM_CCGRx_CG9_MASK				(0x3 << 18)
+#define MXC_CCM_CCGRx_CG8_MASK				(0x3 << 16)
+#define MXC_CCM_CCGRx_CG5_MASK				(0x3 << 10)
+#define MXC_CCM_CCGRx_CG4_MASK				(0x3 << 8)
+#define MXC_CCM_CCGRx_CG3_MASK				(0x3 << 6)
+#define MXC_CCM_CCGRx_CG2_MASK				(0x3 << 4)
+#define MXC_CCM_CCGRx_CG1_MASK				(0x3 << 2)
+#define MXC_CCM_CCGRx_CG0_MASK				(0x3 << 0)
+
+#define MXC_CCM_CCGRx_CG15_OFFSET			30
+#define MXC_CCM_CCGRx_CG14_OFFSET			28
+#define MXC_CCM_CCGRx_CG13_OFFSET			26
+#define MXC_CCM_CCGRx_CG12_OFFSET			24
+#define MXC_CCM_CCGRx_CG11_OFFSET			22
+#define MXC_CCM_CCGRx_CG10_OFFSET			20
+#define MXC_CCM_CCGRx_CG9_OFFSET			18
+#define MXC_CCM_CCGRx_CG8_OFFSET			16
+#define MXC_CCM_CCGRx_CG7_OFFSET			14
+#define MXC_CCM_CCGRx_CG6_OFFSET			12
+#define MXC_CCM_CCGRx_CG5_OFFSET			10
+#define MXC_CCM_CCGRx_CG4_OFFSET			8
+#define MXC_CCM_CCGRx_CG3_OFFSET			6
+#define MXC_CCM_CCGRx_CG2_OFFSET			4
+#define MXC_CCM_CCGRx_CG1_OFFSET			2
+#define MXC_CCM_CCGRx_CG0_OFFSET			0
+
+#define MXC_DPTC_LP_BASE	(MX51_GPC_BASE + 0x80)
+#define MXC_DPTC_GP_BASE	(MX51_GPC_BASE + 0x100)
+#define MXC_DVFS_CORE_BASE	(MX51_GPC_BASE + 0x180)
+#define MXC_DPTC_PER_BASE	(MX51_GPC_BASE + 0x1C0)
+#define MXC_PGC_IPU_BASE	(MX51_GPC_BASE + 0x220)
+#define MXC_PGC_VPU_BASE	(MX51_GPC_BASE + 0x240)
+#define MXC_PGC_GPU_BASE	(MX51_GPC_BASE + 0x260)
+#define MXC_SRPG_NEON_BASE	(MX51_GPC_BASE + 0x280)
+#define MXC_SRPG_ARM_BASE	(MX51_GPC_BASE + 0x2A0)
+#define MXC_SRPG_EMPGC0_BASE	(MX51_GPC_BASE + 0x2C0)
+#define MXC_SRPG_EMPGC1_BASE	(MX51_GPC_BASE + 0x2D0)
+#define MXC_SRPG_MEGAMIX_BASE	(MX51_GPC_BASE + 0x2E0)
+#define MXC_SRPG_EMI_BASE	(MX51_GPC_BASE + 0x300)
+
+/* CORTEXA8 platform */
+#define MXC_CORTEXA8_PLAT_PVID		(MX51_CORTEXA8_BASE + 0x0)
+#define MXC_CORTEXA8_PLAT_GPC		(MX51_CORTEXA8_BASE + 0x4)
+#define MXC_CORTEXA8_PLAT_PIC		(MX51_CORTEXA8_BASE + 0x8)
+#define MXC_CORTEXA8_PLAT_LPC		(MX51_CORTEXA8_BASE + 0xC)
+#define MXC_CORTEXA8_PLAT_NEON_LPC	(MX51_CORTEXA8_BASE + 0x10)
+#define MXC_CORTEXA8_PLAT_ICGC		(MX51_CORTEXA8_BASE + 0x14)
+#define MXC_CORTEXA8_PLAT_AMC		(MX51_CORTEXA8_BASE + 0x18)
+#define MXC_CORTEXA8_PLAT_NMC		(MX51_CORTEXA8_BASE + 0x20)
+#define MXC_CORTEXA8_PLAT_NMS		(MX51_CORTEXA8_BASE + 0x24)
+
+/* DVFS CORE */
+#define MXC_DVFSTHRS		(MXC_DVFS_CORE_BASE + 0x00)
+#define MXC_DVFSCOUN		(MXC_DVFS_CORE_BASE + 0x04)
+#define MXC_DVFSSIG1		(MXC_DVFS_CORE_BASE + 0x08)
+#define MXC_DVFSSIG0		(MXC_DVFS_CORE_BASE + 0x0C)
+#define MXC_DVFSGPC0		(MXC_DVFS_CORE_BASE + 0x10)
+#define MXC_DVFSGPC1		(MXC_DVFS_CORE_BASE + 0x14)
+#define MXC_DVFSGPBT		(MXC_DVFS_CORE_BASE + 0x18)
+#define MXC_DVFSEMAC		(MXC_DVFS_CORE_BASE + 0x1C)
+#define MXC_DVFSCNTR		(MXC_DVFS_CORE_BASE + 0x20)
+#define MXC_DVFSLTR0_0		(MXC_DVFS_CORE_BASE + 0x24)
+#define MXC_DVFSLTR0_1		(MXC_DVFS_CORE_BASE + 0x28)
+#define MXC_DVFSLTR1_0		(MXC_DVFS_CORE_BASE + 0x2C)
+#define MXC_DVFSLTR1_1		(MXC_DVFS_CORE_BASE + 0x30)
+#define MXC_DVFSPT0 		(MXC_DVFS_CORE_BASE + 0x34)
+#define MXC_DVFSPT1 		(MXC_DVFS_CORE_BASE + 0x38)
+#define MXC_DVFSPT2 		(MXC_DVFS_CORE_BASE + 0x3C)
+#define MXC_DVFSPT3 		(MXC_DVFS_CORE_BASE + 0x40)
+
+/* GPC */
+#define MXC_GPC_CNTR		(MX51_GPC_BASE + 0x0)
+#define MXC_GPC_PGR		(MX51_GPC_BASE + 0x4)
+#define MXC_GPC_VCR		(MX51_GPC_BASE + 0x8)
+#define MXC_GPC_ALL_PU		(MX51_GPC_BASE + 0xC)
+#define MXC_GPC_NEON		(MX51_GPC_BASE + 0x10)
+#define MXC_GPC_PGR_ARMPG_OFFSET	8
+#define MXC_GPC_PGR_ARMPG_MASK		(3 << 8)
+
+/* PGC */
+#define MXC_PGC_IPU_PGCR	(MXC_PGC_IPU_BASE + 0x0)
+#define MXC_PGC_IPU_PGSR	(MXC_PGC_IPU_BASE + 0xC)
+#define MXC_PGC_VPU_PGCR	(MXC_PGC_VPU_BASE + 0x0)
+#define MXC_PGC_VPU_PGSR	(MXC_PGC_VPU_BASE + 0xC)
+#define MXC_PGC_GPU_PGCR	(MXC_PGC_GPU_BASE + 0x0)
+#define MXC_PGC_GPU_PGSR	(MXC_PGC_GPU_BASE + 0xC)
+
+#define MXC_PGCR_PCR		1
+#define MXC_SRPGCR_PCR		1
+#define MXC_EMPGCR_PCR		1
+#define MXC_PGSR_PSR		1
+
+
+#define MXC_CORTEXA8_PLAT_LPC_DSM	(1 << 0)
+#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM	(1 << 1)
+
+/* SRPG */
+#define MXC_SRPG_NEON_SRPGCR	(MXC_SRPG_NEON_BASE + 0x0)
+#define MXC_SRPG_NEON_PUPSCR	(MXC_SRPG_NEON_BASE + 0x4)
+#define MXC_SRPG_NEON_PDNSCR	(MXC_SRPG_NEON_BASE + 0x8)
+
+#define MXC_SRPG_ARM_SRPGCR	(MXC_SRPG_ARM_BASE + 0x0)
+#define MXC_SRPG_ARM_PUPSCR	(MXC_SRPG_ARM_BASE + 0x4)
+#define MXC_SRPG_ARM_PDNSCR	(MXC_SRPG_ARM_BASE + 0x8)
+
+#define MXC_SRPG_EMPGC0_SRPGCR	(MXC_SRPG_EMPGC0_BASE + 0x0)
+#define MXC_SRPG_EMPGC0_PUPSCR	(MXC_SRPG_EMPGC0_BASE + 0x4)
+#define MXC_SRPG_EMPGC0_PDNSCR	(MXC_SRPG_EMPGC0_BASE + 0x8)
+
+#define MXC_SRPG_EMPGC1_SRPGCR	(MXC_SRPG_EMPGC1_BASE + 0x0)
+#define MXC_SRPG_EMPGC1_PUPSCR	(MXC_SRPG_EMPGC1_BASE + 0x4)
+#define MXC_SRPG_EMPGC1_PDNSCR	(MXC_SRPG_EMPGC1_BASE + 0x8)
+
+#define MXC_SRPG_MEGAMIX_SRPGCR		(MXC_SRPG_MEGAMIX_BASE + 0x0)
+#define MXC_SRPG_MEGAMIX_PUPSCR		(MXC_SRPG_MEGAMIX_BASE + 0x4)
+#define MXC_SRPG_MEGAMIX_PDNSCR		(MXC_SRPG_MEGAMIX_BASE + 0x8)
+
+#define MXC_SRPGC_EMI_SRPGCR	(MXC_SRPGC_EMI_BASE + 0x0)
+#define MXC_SRPGC_EMI_PUPSCR	(MXC_SRPGC_EMI_BASE + 0x4)
+#define MXC_SRPGC_EMI_PDNSCR	(MXC_SRPGC_EMI_BASE + 0x8)
+
+#endif				/* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
new file mode 100644
index 0000000..d6fd396
--- /dev/null
+++ b/arch/arm/mach-mx5/devices.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2009 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/platform_device.h>
+#include <mach/hardware.h>
+#include <mach/imx-uart.h>
+
+static struct resource uart0[] = {
+	{
+		.start = MX51_UART1_BASE_ADDR,
+		.end = MX51_UART1_BASE_ADDR + 0xfff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = MX51_MXC_INT_UART1,
+		.end = MX51_MXC_INT_UART1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_uart_device0 = {
+	.name = "imx-uart",
+	.id = 0,
+	.resource = uart0,
+	.num_resources = ARRAY_SIZE(uart0),
+};
+
+static struct resource uart1[] = {
+	{
+		.start = MX51_UART2_BASE_ADDR,
+		.end = MX51_UART2_BASE_ADDR + 0xfff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = MX51_MXC_INT_UART2,
+		.end = MX51_MXC_INT_UART2,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_uart_device1 = {
+	.name = "imx-uart",
+	.id = 1,
+	.resource = uart1,
+	.num_resources = ARRAY_SIZE(uart1),
+};
+
+static struct resource uart2[] = {
+	{
+		.start = MX51_UART3_BASE_ADDR,
+		.end = MX51_UART3_BASE_ADDR + 0xfff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = MX51_MXC_INT_UART3,
+		.end = MX51_MXC_INT_UART3,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_uart_device2 = {
+	.name = "imx-uart",
+	.id = 2,
+	.resource = uart2,
+	.num_resources = ARRAY_SIZE(uart2),
+};
+
+static struct resource mxc_fec_resources[] = {
+	{
+		.start	= MX51_MXC_FEC_BASE_ADDR,
+		.end	= MX51_MXC_FEC_BASE_ADDR + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= MX51_MXC_INT_FEC,
+		.end	= MX51_MXC_INT_FEC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device mxc_fec_device = {
+	.name = "fec",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_fec_resources),
+	.resource = mxc_fec_resources,
+};
+
+/* Dummy definition to allow compiling in AVIC and TZIC simultaneously */
+int __init mxc_register_gpios(void)
+{
+	return 0;
+}
diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h
new file mode 100644
index 0000000..f339ab8
--- /dev/null
+++ b/arch/arm/mach-mx5/devices.h
@@ -0,0 +1,4 @@
+extern struct platform_device mxc_uart_device0;
+extern struct platform_device mxc_uart_device1;
+extern struct platform_device mxc_uart_device2;
+extern struct platform_device mxc_fec_device;
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
new file mode 100644
index 0000000..c21e18b
--- /dev/null
+++ b/arch/arm/mach-mx5/mm.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008-2009 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/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-v3.h>
+
+/*
+ * 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_TZIC_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(MX51_TZIC_BASE_ADDR),
+		.length = MX51_TZIC_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
+	}, {
+		.virtual = MX51_NFC_AXI_BASE_ADDR_VIRT,
+		.pfn = __phys_to_pfn(MX51_NFC_AXI_BASE_ADDR),
+		.length = MX51_NFC_AXI_SIZE,
+		.type = 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 mx51_map_io(void)
+{
+	u32 tzic_addr;
+
+	if (mx51_revision() < MX51_CHIP_REV_2_0)
+		tzic_addr = 0x8FFFC000;
+	else
+		tzic_addr = 0xE0003000;
+	mxc_io_desc[2].pfn =  __phys_to_pfn(tzic_addr);
+
+	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));
+}
+
+void __init mx51_init_irq(void)
+{
+	tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
+}
diff --git a/arch/arm/mach-mxc91231/magx-zn5.c b/arch/arm/mach-mxc91231/magx-zn5.c
index 7dbe4ca..69816ba 100644
--- a/arch/arm/mach-mxc91231/magx-zn5.c
+++ b/arch/arm/mach-mxc91231/magx-zn5.c
@@ -55,7 +55,7 @@
 MACHINE_START(MAGX_ZN5, "Motorola Zn5")
 	.phys_io	= MXC91231_AIPS1_BASE_ADDR,
 	.io_pg_offst	= ((MXC91231_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= MXC91231_PHYS_OFFSET + 0x100,
 	.map_io		= mxc91231_map_io,
 	.init_irq	= mxc91231_init_irq,
 	.timer		= &zn5_timer,
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index 9438bf6..ab3712c 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -38,7 +38,7 @@
 #define SRC_CR_INIT_MASK	0x00007fff
 #define SRC_CR_INIT_VAL		0x2aaa8000
 
-/* These adresses span 16MB, so use three individual pages */
+/* These addresses span 16MB, so use three individual pages */
 static struct resource nhk8815_nand_resources[] = {
 	{
 		.name = "nand_addr",
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
index c3d513c..905719a 100644
--- a/arch/arm/mach-orion5x/Kconfig
+++ b/arch/arm/mach-orion5x/Kconfig
@@ -57,6 +57,13 @@
 	  Say 'Y' here if you want your kernel to support the
 	  Buffalo Linkstation Mini platform.
 
+config MACH_LINKSTATION_LS_HGL
+	bool "Buffalo Linkstation LS-HGL"
+	select I2C_BOARDINFO
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Buffalo Linkstation LS-HGL platform.
+
 config MACH_TS409
 	bool "QNAP TS-409"
 	help
diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile
index 89772fc..eb6eabc 100644
--- a/arch/arm/mach-orion5x/Makefile
+++ b/arch/arm/mach-orion5x/Makefile
@@ -5,6 +5,7 @@
 obj-$(CONFIG_MACH_TERASTATION_PRO2)	+= terastation_pro2-setup.o
 obj-$(CONFIG_MACH_LINKSTATION_PRO) += kurobox_pro-setup.o
 obj-$(CONFIG_MACH_LINKSTATION_MINI) += lsmini-setup.o
+obj-$(CONFIG_MACH_LINKSTATION_LS_HGL) += ls_hgl-setup.o
 obj-$(CONFIG_MACH_DNS323)	+= dns323-setup.o
 obj-$(CONFIG_MACH_TS209)	+= ts209-setup.o tsx09-common.o
 obj-$(CONFIG_MACH_TS409)	+= ts409-setup.o tsx09-common.o
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index f87fa12..8dc2c76 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -488,7 +488,7 @@
 	.dev		= {
 		.dma_mask		= &orion5x_xor_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(64),
-		.platform_data		= (void *)&orion5x_xor0_data,
+		.platform_data		= &orion5x_xor0_data,
 	},
 };
 
@@ -514,7 +514,7 @@
 	.dev		= {
 		.dma_mask		= &orion5x_xor_dmamask,
 		.coherent_dma_mask	= DMA_BIT_MASK(64),
-		.platform_data		= (void *)&orion5x_xor1_data,
+		.platform_data		= &orion5x_xor1_data,
 	},
 };
 
diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c
index 9d4bf76..7130904 100644
--- a/arch/arm/mach-orion5x/d2net-setup.c
+++ b/arch/arm/mach-orion5x/d2net-setup.c
@@ -149,10 +149,7 @@
 
 /*
  * The blue front LED is wired to the CPLD and can blink in relation with the
- * SATA activity. This feature is disabled to make this LED compatible with
- * the leds-gpio driver: MPP14 and MPP15 are configured to act like output
- * GPIO's and have to stay in an active state. This is needed to set the blue
- * LED in a "fix on" state regardless of the SATA activity.
+ * SATA activity.
  *
  * The following array detail the different LED registers and the combination
  * of their possible values:
@@ -171,12 +168,11 @@
 #define D2NET_GPIO_RED_LED		6
 #define D2NET_GPIO_BLUE_LED_BLINK_CTRL	16
 #define D2NET_GPIO_BLUE_LED_OFF		23
-#define D2NET_GPIO_SATA0_ACT		14
-#define D2NET_GPIO_SATA1_ACT		15
 
 static struct gpio_led d2net_leds[] = {
 	{
-		.name = "d2net:blue:power",
+		.name = "d2net:blue:sata",
+		.default_trigger = "default-on",
 		.gpio = D2NET_GPIO_BLUE_LED_OFF,
 		.active_low = 1,
 	},
@@ -201,25 +197,22 @@
 
 static void __init d2net_gpio_leds_init(void)
 {
+	int err;
+
 	/* Configure GPIO over MPP max number. */
 	orion_gpio_set_valid(D2NET_GPIO_BLUE_LED_OFF, 1);
 
-	if (gpio_request(D2NET_GPIO_SATA0_ACT, "LED SATA0 activity") != 0)
-		return;
-	if (gpio_direction_output(D2NET_GPIO_SATA0_ACT, 1) != 0)
-		goto err_free_1;
-	if (gpio_request(D2NET_GPIO_SATA1_ACT, "LED SATA1 activity") != 0)
-		goto err_free_1;
-	if (gpio_direction_output(D2NET_GPIO_SATA1_ACT, 1) != 0)
-		goto err_free_2;
-	platform_device_register(&d2net_gpio_leds);
-	return;
+	/* Configure register blink_ctrl to allow SATA activity LED blinking. */
+	err = gpio_request(D2NET_GPIO_BLUE_LED_BLINK_CTRL, "blue LED blink");
+	if (err == 0) {
+		err = gpio_direction_output(D2NET_GPIO_BLUE_LED_BLINK_CTRL, 1);
+		if (err)
+			gpio_free(D2NET_GPIO_BLUE_LED_BLINK_CTRL);
+	}
+	if (err)
+		pr_err("d2net: failed to configure blue LED blink GPIO\n");
 
-err_free_2:
-	gpio_free(D2NET_GPIO_SATA1_ACT);
-err_free_1:
-	gpio_free(D2NET_GPIO_SATA0_ACT);
-	return;
+	platform_device_register(&d2net_gpio_leds);
 }
 
 /****************************************************************************
@@ -289,8 +282,8 @@
 	{ 11, MPP_UNUSED },
 	{ 12, MPP_GPIO },	/* SATA 1 power */
 	{ 13, MPP_UNUSED },
-	{ 14, MPP_GPIO },	/* SATA 0 active */
-	{ 15, MPP_GPIO },	/* SATA 1 active */
+	{ 14, MPP_SATA_LED },	/* SATA 0 active */
+	{ 15, MPP_SATA_LED },	/* SATA 1 active */
 	{ 16, MPP_GPIO },	/* Blue front LED blink control */
 	{ 17, MPP_UNUSED },
 	{ 18, MPP_GPIO },	/* Front button (0 = Released, 1 = Pushed ) */
@@ -301,6 +294,8 @@
 	/* 24: Inhibit board power off (0 = Disabled, 1 = Enabled) */
 };
 
+#define D2NET_GPIO_INHIBIT_POWER_OFF    24
+
 static void __init d2net_init(void)
 {
 	/*
@@ -333,6 +328,8 @@
 
 	i2c_register_board_info(0, d2net_i2c_devices,
 				ARRAY_SIZE(d2net_i2c_devices));
+
+	orion_gpio_set_valid(D2NET_GPIO_INHIBIT_POWER_OFF, 1);
 }
 
 /* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index 8f159db..421b82f 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -34,7 +34,8 @@
 #define DNS323_GPIO_LED_RIGHT_AMBER	1
 #define DNS323_GPIO_LED_LEFT_AMBER	2
 #define DNS323_GPIO_SYSTEM_UP		3
-#define DNS323_GPIO_LED_POWER		5
+#define DNS323_GPIO_LED_POWER1		4
+#define DNS323_GPIO_LED_POWER2		5
 #define DNS323_GPIO_OVERTEMP		6
 #define DNS323_GPIO_RTC			7
 #define DNS323_GPIO_POWER_OFF		8
@@ -237,11 +238,31 @@
  * GPIO LEDs (simple - doesn't use hardware blinking support)
  */
 
+#define ORION_BLINK_HALF_PERIOD 100 /* ms */
+
+static int dns323_gpio_blink_set(unsigned gpio,
+	unsigned long *delay_on, unsigned long *delay_off)
+{
+	static int value = 0;
+
+	if (!*delay_on && !*delay_off)
+		*delay_on = *delay_off = ORION_BLINK_HALF_PERIOD;
+
+	if (ORION_BLINK_HALF_PERIOD == *delay_on
+	    && ORION_BLINK_HALF_PERIOD == *delay_off) {
+		value = !value;
+		orion_gpio_set_blink(gpio, value);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 static struct gpio_led dns323_leds[] = {
 	{
 		.name = "power:blue",
-		.gpio = DNS323_GPIO_LED_POWER,
-		.default_state = LEDS_GPIO_DEFSTATE_ON,
+		.gpio = DNS323_GPIO_LED_POWER2,
+		.default_trigger = "timer",
 	}, {
 		.name = "right:amber",
 		.gpio = DNS323_GPIO_LED_RIGHT_AMBER,
@@ -256,6 +277,7 @@
 static struct gpio_led_platform_data dns323_led_data = {
 	.num_leds	= ARRAY_SIZE(dns323_leds),
 	.leds		= dns323_leds,
+	.gpio_blink_set = dns323_gpio_blink_set,
 };
 
 static struct platform_device dns323_gpio_leds = {
@@ -412,6 +434,14 @@
 	orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE);
 	platform_device_register(&dns323_nor_flash);
 
+	/* The 5181 power LED is active low and requires
+	 * DNS323_GPIO_LED_POWER1 to also be low.
+	 */
+	if (dns323_dev_id() == MV88F5181_DEV_ID) {
+		dns323_leds[0].active_low = 1;
+		gpio_direction_output(DNS323_GPIO_LED_POWER1, 0);
+	}
+
 	platform_device_register(&dns323_gpio_leds);
 
 	platform_device_register(&dns323_button_device);
diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c
new file mode 100644
index 0000000..8e569be
--- /dev/null
+++ b/arch/arm/mach-orion5x/ls_hgl-setup.c
@@ -0,0 +1,276 @@
+/*
+ * arch/arm/mach-orion5x/ls_hgl-setup.c
+ *
+ * Maintainer: Zhu Qingsen <zhuqs@cn.fujitsu.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/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/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-HGL Info
+ ****************************************************************************/
+
+/*
+ * 256K NOR flash Device bus boot chip select
+ */
+
+#define LS_HGL_NOR_BOOT_BASE	0xf4000000
+#define LS_HGL_NOR_BOOT_SIZE	SZ_256K
+
+/*****************************************************************************
+ * 256KB NOR Flash on BOOT Device
+ ****************************************************************************/
+
+static struct physmap_flash_data ls_hgl_nor_flash_data = {
+	.width		= 1,
+};
+
+static struct resource ls_hgl_nor_flash_resource = {
+	.flags	= IORESOURCE_MEM,
+	.start	= LS_HGL_NOR_BOOT_BASE,
+	.end	= LS_HGL_NOR_BOOT_BASE + LS_HGL_NOR_BOOT_SIZE - 1,
+};
+
+static struct platform_device ls_hgl_nor_flash = {
+	.name			= "physmap-flash",
+	.id			= 0,
+	.dev		= {
+		.platform_data	= &ls_hgl_nor_flash_data,
+	},
+	.num_resources		= 1,
+	.resource		= &ls_hgl_nor_flash_resource,
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+
+static struct mv643xx_eth_platform_data ls_hgl_eth_data = {
+	.phy_addr	= 8,
+};
+
+/*****************************************************************************
+ * RTC 5C372a on I2C bus
+ ****************************************************************************/
+
+static struct i2c_board_info __initdata ls_hgl_i2c_rtc = {
+	I2C_BOARD_INFO("rs5c372a", 0x32),
+};
+
+/*****************************************************************************
+ * LEDs attached to GPIO
+ ****************************************************************************/
+
+#define LS_HGL_GPIO_LED_ALARM   2
+#define LS_HGL_GPIO_LED_INFO    3
+#define LS_HGL_GPIO_LED_FUNC    17
+#define LS_HGL_GPIO_LED_PWR     0
+
+
+static struct gpio_led ls_hgl_led_pins[] = {
+	{
+		.name	   = "alarm:red",
+		.gpio	   = LS_HGL_GPIO_LED_ALARM,
+		.active_low     = 1,
+	}, {
+		.name	   = "info:amber",
+		.gpio	   = LS_HGL_GPIO_LED_INFO,
+		.active_low     = 1,
+	}, {
+		.name	   = "func:blue:top",
+		.gpio	   = LS_HGL_GPIO_LED_FUNC,
+		.active_low     = 1,
+	}, {
+		.name	   = "power:blue:bottom",
+		.gpio	   = LS_HGL_GPIO_LED_PWR,
+	},
+};
+
+static struct gpio_led_platform_data ls_hgl_led_data = {
+	.leds	   = ls_hgl_led_pins,
+	.num_leds       = ARRAY_SIZE(ls_hgl_led_pins),
+};
+
+static struct platform_device ls_hgl_leds = {
+	.name   = "leds-gpio",
+	.id     = -1,
+	.dev    = {
+		.platform_data  = &ls_hgl_led_data,
+	},
+};
+
+/****************************************************************************
+ * GPIO Attached Keys
+ ****************************************************************************/
+#define LS_HGL_GPIO_KEY_FUNC       15
+#define LS_HGL_GPIO_KEY_POWER      8
+#define LS_HGL_GPIO_KEY_AUTOPOWER  10
+
+#define LS_HGL_SW_POWER     0x00
+#define LS_HGL_SW_AUTOPOWER 0x01
+
+static struct gpio_keys_button ls_hgl_buttons[] = {
+	{
+		.code	   = KEY_OPTION,
+		.gpio	   = LS_HGL_GPIO_KEY_FUNC,
+		.desc	   = "Function Button",
+		.active_low     = 1,
+	}, {
+		.type		= EV_SW,
+		.code	   = LS_HGL_SW_POWER,
+		.gpio	   = LS_HGL_GPIO_KEY_POWER,
+		.desc	   = "Power-on Switch",
+		.active_low     = 1,
+	}, {
+		.type		= EV_SW,
+		.code	   = LS_HGL_SW_AUTOPOWER,
+		.gpio	   = LS_HGL_GPIO_KEY_AUTOPOWER,
+		.desc	   = "Power-auto Switch",
+		.active_low     = 1,
+	},
+};
+
+static struct gpio_keys_platform_data ls_hgl_button_data = {
+	.buttons	= ls_hgl_buttons,
+	.nbuttons       = ARRAY_SIZE(ls_hgl_buttons),
+};
+
+static struct platform_device ls_hgl_button_device = {
+	.name	   = "gpio-keys",
+	.id	     = -1,
+	.num_resources  = 0,
+	.dev	    = {
+		.platform_data  = &ls_hgl_button_data,
+	},
+};
+
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+static struct mv_sata_platform_data ls_hgl_sata_data = {
+	.n_ports	= 2,
+};
+
+
+/*****************************************************************************
+ * Linkstation LS-HGL specific power off method: reboot
+ ****************************************************************************/
+/*
+ * On the Linkstation LS-HGL, 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 ls_hgl_power_off(void)
+{
+	arm_machine_restart('h', NULL);
+}
+
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+
+#define LS_HGL_GPIO_USB_POWER	9
+#define LS_HGL_GPIO_AUTO_POWER	10
+#define LS_HGL_GPIO_POWER	    8
+
+#define LS_HGL_GPIO_HDD_POWER	1
+
+static struct orion5x_mpp_mode ls_hgl_mpp_modes[] __initdata = {
+	{  0, MPP_GPIO }, /* LED_PWR */
+	{  1, MPP_GPIO }, /* HDD_PWR */
+	{  2, MPP_GPIO }, /* LED_ALARM */
+	{  3, MPP_GPIO }, /* LED_INFO */
+	{  4, MPP_UNUSED },
+	{  5, MPP_UNUSED },
+	{  6, MPP_GPIO }, /* FAN_LCK */
+	{  7, MPP_GPIO }, /* INIT */
+	{  8, MPP_GPIO }, /* POWER */
+	{  9, MPP_GPIO }, /* USB_PWR */
+	{ 10, MPP_GPIO }, /* AUTO_POWER */
+	{ 11, MPP_UNUSED }, /* LED_ETH (dummy) */
+	{ 12, MPP_UNUSED },
+	{ 13, MPP_UNUSED },
+	{ 14, MPP_UNUSED },
+	{ 15, MPP_GPIO }, /* FUNC */
+	{ 16, MPP_UNUSED },
+	{ 17, MPP_GPIO }, /* LED_FUNC */
+	{ 18, MPP_UNUSED },
+	{ 19, MPP_UNUSED },
+	{ -1 },
+};
+
+static void __init ls_hgl_init(void)
+{
+	/*
+	 * Setup basic Orion functions. Need to be called early.
+	 */
+	orion5x_init();
+
+	orion5x_mpp_conf(ls_hgl_mpp_modes);
+
+	/*
+	 * Configure peripherals.
+	 */
+	orion5x_ehci0_init();
+	orion5x_ehci1_init();
+	orion5x_eth_init(&ls_hgl_eth_data);
+	orion5x_i2c_init();
+	orion5x_sata_init(&ls_hgl_sata_data);
+	orion5x_uart0_init();
+	orion5x_xor_init();
+
+	orion5x_setup_dev_boot_win(LS_HGL_NOR_BOOT_BASE,
+				   LS_HGL_NOR_BOOT_SIZE);
+	platform_device_register(&ls_hgl_nor_flash);
+
+	platform_device_register(&ls_hgl_button_device);
+
+	platform_device_register(&ls_hgl_leds);
+
+	i2c_register_board_info(0, &ls_hgl_i2c_rtc, 1);
+
+	/* enable USB power */
+	gpio_set_value(LS_HGL_GPIO_USB_POWER, 1);
+
+	/* register power-off method */
+	pm_power_off = ls_hgl_power_off;
+
+	pr_info("%s: finished\n", __func__);
+}
+
+MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL")
+	/* Maintainer: Zhu Qingsen <zhuqs@cn.fujistu.com> */
+	.phys_io	= ORION5X_REGS_PHYS_BASE,
+	.io_pg_offst	= ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
+	.boot_params	= 0x00000100,
+	.init_machine	= ls_hgl_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-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c
index c9bf6b8..c704f05 100644
--- a/arch/arm/mach-orion5x/lsmini-setup.c
+++ b/arch/arm/mach-orion5x/lsmini-setup.c
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/pci.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/leds.h>
@@ -19,12 +18,13 @@
 #include <linux/input.h>
 #include <linux/i2c.h>
 #include <linux/ata_platform.h>
-#include <asm/mach-types.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"
-#include "include/mach/system.h"
 
 /*****************************************************************************
  * Linkstation Mini Info
@@ -186,7 +186,7 @@
 
 static void lsmini_power_off(void)
 {
-	arch_reset(0, NULL);
+	arm_machine_restart('h', NULL);
 }
 
 
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index dee9218..38fbd0a 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -115,6 +115,11 @@
 	select CPU_PXA310
 	select HAVE_PWM
 
+config MACH_CAPC7117
+	bool "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM"
+	select CPU_PXA320
+	select PXA3xx
+
 config ARCH_GUMSTIX
 	bool "Gumstix XScale 255 boards"
 	select PXA25x
@@ -417,6 +422,24 @@
 	  Say Y here if you intend to run this kernel on Palm Treo 680
 	  smartphone.
 
+config MACH_RAUMFELD_RC
+	bool "Raumfeld Controller"
+	select PXA3xx
+	select CPU_PXA300
+	select HAVE_PWM
+
+config MACH_RAUMFELD_CONNECTOR
+	bool "Raumfeld Connector"
+	select PXA3xx
+	select CPU_PXA300
+	select PXA_SSP
+
+config MACH_RAUMFELD_SPEAKER
+	bool "Raumfeld Speaker"
+	select PXA3xx
+	select CPU_PXA300
+	select PXA_SSP
+
 config PXA_SHARPSL
 	bool "SHARP Zaurus SL-5600, SL-C7xx and SL-Cxx00 Models"
 	select SHARP_SCOOP
@@ -435,6 +458,7 @@
 config CORGI_SSP_DEPRECATED
 	bool
 	select PXA_SSP
+	select PXA_SSP_LEGACY
 	help
 	  This option will include corgi_ssp.c and corgi_lcd.c
 	  that corgi_ts.c and other legacy drivers (corgi_bl.c
@@ -446,6 +470,7 @@
 	select PXA25x
 	select SHARP_LOCOMO
 	select PXA_SSP
+	select PXA_HAVE_BOARD_IRQS
 
 config MACH_CORGI
 	bool "Enable Sharp SL-C700 (Corgi) Support"
@@ -492,6 +517,11 @@
 	select PXA25x
 	select PXA_HAVE_BOARD_IRQS
 
+config MACH_ICONTROL
+	bool "TMT iControl/SafeTCam based on the MXM-8x10 CoM"
+	select CPU_PXA320
+	select PXA3xx
+
 config ARCH_PXA_ESERIES
 	bool "PXA based Toshiba e-series PDAs"
 	select PXA25x
@@ -629,6 +659,11 @@
 	help
 	  Enable support for PXA2xx SSP ports
 
+config PXA_SSP_LEGACY
+	bool
+	help
+	  Support of legacy SSP API
+
 config TOSA_BT
 	tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
 	depends on MACH_TOSA
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index f64afda..86bc87b 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -48,6 +48,7 @@
 endif
 obj-$(CONFIG_MACH_EM_X270)	+= em-x270.o
 obj-$(CONFIG_MACH_CM_X300)      += cm-x300.o
+obj-$(CONFIG_MACH_CAPC7117)     += capc7117.o mxm8x10.o
 obj-$(CONFIG_ARCH_GUMSTIX)	+= gumstix.o
 obj-$(CONFIG_GUMSTIX_AM200EPD)	+= am200epd.o
 obj-$(CONFIG_GUMSTIX_AM300EPD)	+= am300epd.o
@@ -82,6 +83,7 @@
 obj-$(CONFIG_CORGI_SSP_DEPRECATED)	+= corgi_ssp.o corgi_lcd.o
 obj-$(CONFIG_MACH_POODLE)	+= poodle.o
 obj-$(CONFIG_MACH_TOSA)		+= tosa.o
+obj-$(CONFIG_MACH_ICONTROL)     += icontrol.o mxm8x10.o
 obj-$(CONFIG_ARCH_PXA_ESERIES)	+= eseries.o
 obj-$(CONFIG_MACH_E330)		+= e330.o
 obj-$(CONFIG_MACH_E350)		+= e350.o
@@ -89,6 +91,9 @@
 obj-$(CONFIG_MACH_E750)		+= e750.o
 obj-$(CONFIG_MACH_E400)		+= e400.o
 obj-$(CONFIG_MACH_E800)		+= e800.o
+obj-$(CONFIG_MACH_RAUMFELD_RC)		+= raumfeld.o
+obj-$(CONFIG_MACH_RAUMFELD_CONNECTOR)	+= raumfeld.o
+obj-$(CONFIG_MACH_RAUMFELD_SPEAKER)	+= raumfeld.o
 
 # Support for blinky lights
 led-y := leds.o
diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c
index 4bd10a1..993d75e 100644
--- a/arch/arm/mach-pxa/am300epd.c
+++ b/arch/arm/mach-pxa/am300epd.c
@@ -288,7 +288,7 @@
 }
 
 module_param(panel_type, uint, 0);
-MODULE_PARM_DESC(panel_type, "Select the panel type: 6, 8, 97");
+MODULE_PARM_DESC(panel_type, "Select the panel type: 37, 6, 97");
 
 MODULE_DESCRIPTION("board driver for am300 epd kit");
 MODULE_AUTHOR("Jaya Kumar");
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index b8cd07c..f3b5ace 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -132,6 +132,14 @@
 		"enabled\n", __func__, BALLOON3_AUX_NIRQ);
 }
 
+static unsigned long balloon3_ac97_pin_config[] = {
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+	GPIO113_AC97_nRESET,
+};
+
 static void balloon3_backlight_power(int on)
 {
 	pr_debug("%s: power is %s\n", __func__, on ? "on" : "off");
@@ -140,26 +148,7 @@
 
 static unsigned long balloon3_lcd_pin_config[] = {
 	/* LCD - 16bpp Active TFT */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	GPIO99_GPIO,		/* Backlight */
 };
@@ -311,8 +300,10 @@
 	pxa_set_stuart_info(NULL);
 
 	pxa_set_i2c_info(NULL);
-	if (balloon3_has(BALLOON3_FEATURE_AUDIO))
+	if (balloon3_has(BALLOON3_FEATURE_AUDIO)) {
+		pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_ac97_pin_config));
 		pxa_set_ac97_info(NULL);
+	}
 
 	if (balloon3_has(BALLOON3_FEATURE_TOPPOLY)) {
 		pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_lcd_pin_config));
diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c
new file mode 100644
index 0000000..aae5446
--- /dev/null
+++ b/arch/arm/mach-pxa/capc7117.c
@@ -0,0 +1,158 @@
+/*
+ * linux/arch/arm/mach-pxa/capc7117.c
+ *
+ * Support for the Embedian CAPC-7117 Evaluation Kit
+ * based on the Embedian MXM-8x10 Computer on Module
+ *
+ * Copyright (C) 2009 Embedian Inc.
+ * Copyright (C) 2009 TMT Services & Supplies (Pty) Ltd.
+ *
+ * 2007-09-04: eric miao <eric.y.miao@gmail.com>
+ *             rewrite to align with latest kernel
+ *
+ * 2010-01-09: Edwin Peer <epeer@tmtservices.co.za>
+ *             Hennie van der Merwe <hvdmerwe@tmtservices.co.za>
+ *             rework for upstream merge
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/serial_8250.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pxa320.h>
+#include <mach/mxm8x10.h>
+
+#include "generic.h"
+
+/* IDE (PATA) Support */
+static struct pata_platform_info pata_platform_data = {
+	.ioport_shift = 1
+};
+
+static struct resource capc7117_ide_resources[] = {
+	[0] = {
+	       .start = 0x11000020,
+	       .end = 0x1100003f,
+	       .flags = IORESOURCE_MEM
+	},
+	[1] = {
+	       .start = 0x1100001c,
+	       .end = 0x1100001c,
+	       .flags = IORESOURCE_MEM
+	},
+	[2] = {
+	       .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO76)),
+	       .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO76)),
+	       .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING
+	}
+};
+
+static struct platform_device capc7117_ide_device = {
+	.name = "pata_platform",
+	.num_resources = ARRAY_SIZE(capc7117_ide_resources),
+	.resource = capc7117_ide_resources,
+	.dev = {
+		.platform_data = &pata_platform_data,
+		.coherent_dma_mask = ~0		/* grumble */
+	}
+};
+
+static void __init capc7117_ide_init(void)
+{
+	platform_device_register(&capc7117_ide_device);
+}
+
+/* TI16C752 UART support */
+#define	TI16C752_FLAGS		(UPF_BOOT_AUTOCONF | \
+					UPF_IOREMAP | \
+					UPF_BUGGY_UART | \
+					UPF_SKIP_TEST)
+#define	TI16C752_UARTCLK	(22118400)
+static struct plat_serial8250_port ti16c752_platform_data[] = {
+	[0] = {
+	       .mapbase = 0x14000000,
+	       .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO78)),
+	       .irqflags = IRQF_TRIGGER_RISING,
+	       .flags = TI16C752_FLAGS,
+	       .iotype = UPIO_MEM,
+	       .regshift = 1,
+	       .uartclk = TI16C752_UARTCLK
+	},
+	[1] = {
+	       .mapbase = 0x14000040,
+	       .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO79)),
+	       .irqflags = IRQF_TRIGGER_RISING,
+	       .flags = TI16C752_FLAGS,
+	       .iotype = UPIO_MEM,
+	       .regshift = 1,
+	       .uartclk = TI16C752_UARTCLK
+	},
+	[2] = {
+	       .mapbase = 0x14000080,
+	       .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO80)),
+	       .irqflags = IRQF_TRIGGER_RISING,
+	       .flags = TI16C752_FLAGS,
+	       .iotype = UPIO_MEM,
+	       .regshift = 1,
+	       .uartclk = TI16C752_UARTCLK
+	},
+	[3] = {
+	       .mapbase = 0x140000c0,
+	       .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO81)),
+	       .irqflags = IRQF_TRIGGER_RISING,
+	       .flags = TI16C752_FLAGS,
+	       .iotype = UPIO_MEM,
+	       .regshift = 1,
+	       .uartclk = TI16C752_UARTCLK
+	},
+	[4] = {
+	       /* end of array */
+	}
+};
+
+static struct platform_device ti16c752_device = {
+	.name = "serial8250",
+	.id = PLAT8250_DEV_PLATFORM,
+	.dev = {
+		.platform_data = ti16c752_platform_data
+	}
+};
+
+static void __init capc7117_uarts_init(void)
+{
+	platform_device_register(&ti16c752_device);
+}
+
+static void __init capc7117_init(void)
+{
+	/* Init CoM */
+	mxm_8x10_barebones_init();
+
+	/* Init evaluation board peripherals */
+	mxm_8x10_ac97_init();
+	mxm_8x10_usb_host_init();
+	mxm_8x10_mmc_init();
+
+	capc7117_uarts_init();
+	capc7117_ide_init();
+}
+
+MACHINE_START(CAPC7117,
+	      "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
+	.phys_io = 0x40000000,
+	.boot_params = 0xa0000100,
+	.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.map_io = pxa_map_io,
+	.init_irq = pxa3xx_init_irq,
+	.timer = &pxa_timer,
+	.init_machine = capc7117_init
+MACHINE_END
diff --git a/arch/arm/mach-pxa/cm-x255.c b/arch/arm/mach-pxa/cm-x255.c
index 253fd76..f1a7703 100644
--- a/arch/arm/mach-pxa/cm-x255.c
+++ b/arch/arm/mach-pxa/cm-x255.c
@@ -50,26 +50,7 @@
 	GPIO47_STUART_TXD,
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* SSP1 */
 	GPIO23_SSP1_SCLK,
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index eea78b6..a9926bb 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -71,26 +71,7 @@
 	GPIO111_MMC_DAT_3,
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* I2C */
 	GPIO117_I2C_SCL,
@@ -195,33 +176,57 @@
 	},
 };
 
-static unsigned long save_lcd_regs[10];
+static unsigned long cmx270_marathon_on[] = {
+	GPIO58_GPIO,
+	GPIO59_GPIO,
+	GPIO60_GPIO,
+	GPIO61_GPIO,
+	GPIO62_GPIO,
+	GPIO63_GPIO,
+	GPIO64_GPIO,
+	GPIO65_GPIO,
+	GPIO66_GPIO,
+	GPIO67_GPIO,
+	GPIO68_GPIO,
+	GPIO69_GPIO,
+	GPIO70_GPIO,
+	GPIO71_GPIO,
+	GPIO72_GPIO,
+	GPIO73_GPIO,
+	GPIO74_GPIO,
+	GPIO75_GPIO,
+	GPIO76_GPIO,
+	GPIO77_GPIO,
+};
+
+static unsigned long cmx270_marathon_off[] = {
+	GPIOxx_LCD_TFT_16BPP,
+};
 
 static int cmx270_marathon_probe(struct fb_info *fb)
 {
-	/* save PXA-270 pin settings before enabling 2700G */
-	save_lcd_regs[0] = GPDR1;
-	save_lcd_regs[1] = GPDR2;
-	save_lcd_regs[2] = GAFR1_U;
-	save_lcd_regs[3] = GAFR2_L;
-	save_lcd_regs[4] = GAFR2_U;
+	int gpio, err;
 
-	/* Disable PXA-270 on-chip controller driving pins */
-	GPDR1 &= ~(0xfc000000);
-	GPDR2 &= ~(0x00c03fff);
-	GAFR1_U &= ~(0xfff00000);
-	GAFR2_L &= ~(0x0fffffff);
-	GAFR2_U &= ~(0x0000f000);
+	for (gpio = 58; gpio <= 77; gpio++) {
+		err = gpio_request(gpio, "LCD");
+		if (err)
+			return err;
+		gpio_direction_input(gpio);
+	}
+
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_marathon_on));
 	return 0;
 }
 
 static int cmx270_marathon_remove(struct fb_info *fb)
 {
-	GPDR1 =   save_lcd_regs[0];
-	GPDR2 =   save_lcd_regs[1];
-	GAFR1_U = save_lcd_regs[2];
-	GAFR2_L = save_lcd_regs[3];
-	GAFR2_U = save_lcd_regs[4];
+	int gpio;
+
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_marathon_off));
+
+	for (gpio = 58; gpio <= 77; gpio++)
+		gpio_free(gpio);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-pxa/cm-x2xx-pci.c b/arch/arm/mach-pxa/cm-x2xx-pci.c
index 7873fa3..161fc2d 100644
--- a/arch/arm/mach-pxa/cm-x2xx-pci.c
+++ b/arch/arm/mach-pxa/cm-x2xx-pci.c
@@ -59,7 +59,7 @@
 static void cmx2xx_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
 	/* clear our parent irq */
-	GEDR(cmx2xx_it8152_irq_gpio) = GPIO_bit(cmx2xx_it8152_irq_gpio);
+	desc->chip->ack(irq);
 
 	it8152_irq_demux(irq, desc);
 }
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index a5ee707..1d9bc11 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -204,7 +204,7 @@
 	ssp_machinfo = machinfo;
 }
 
-static int __init corgi_ssp_probe(struct platform_device *dev)
+static int __devinit corgi_ssp_probe(struct platform_device *dev)
 {
 	int ret;
 
diff --git a/arch/arm/mach-pxa/e740.c b/arch/arm/mach-pxa/e740.c
index 94b23a9..d578021 100644
--- a/arch/arm/mach-pxa/e740.c
+++ b/arch/arm/mach-pxa/e740.c
@@ -134,6 +134,12 @@
 	/* IrDA */
 	GPIO38_GPIO | MFP_LPM_DRIVE_HIGH,
 
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+
 	/* Audio power control */
 	GPIO16_GPIO,  /* AC97 codec AVDD2 supply (analogue power) */
 	GPIO40_GPIO,  /* Mic amp power */
diff --git a/arch/arm/mach-pxa/e750.c b/arch/arm/mach-pxa/e750.c
index 5eccbce..af83caa 100644
--- a/arch/arm/mach-pxa/e750.c
+++ b/arch/arm/mach-pxa/e750.c
@@ -132,6 +132,12 @@
 	/* IrDA */
 	GPIO38_GPIO | MFP_LPM_DRIVE_HIGH,
 
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+
 	/* Audio power control */
 	GPIO4_GPIO,  /* Headphone amp power */
 	GPIO7_GPIO,  /* Speaker amp power */
diff --git a/arch/arm/mach-pxa/e800.c b/arch/arm/mach-pxa/e800.c
index aad129b..8ea97bf 100644
--- a/arch/arm/mach-pxa/e800.c
+++ b/arch/arm/mach-pxa/e800.c
@@ -35,6 +35,14 @@
 
 /* ------------------------ e800 LCD definitions ------------------------- */
 
+static unsigned long e800_pin_config[] __initdata = {
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+};
+
 static struct w100_gen_regs e800_lcd_regs = {
 	.lcd_format =            0x00008003,
 	.lcdd_cntl1 =            0x02a00000,
@@ -195,6 +203,7 @@
 
 static void __init e800_init(void)
 {
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(e800_pin_config));
 	pxa_set_ffuart_info(NULL);
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index c8a01bc..aab04f3 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -109,26 +109,7 @@
 	GPIO111_MMC_DAT_3,
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* QCI */
 	GPIO84_CIF_FV,
diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c
new file mode 100644
index 0000000..771137f
--- /dev/null
+++ b/arch/arm/mach-pxa/icontrol.c
@@ -0,0 +1,202 @@
+/*
+ * linux/arch/arm/mach-pxa/icontrol.c
+ *
+ * Support for the iControl and SafeTcam platforms from TMT Services
+ * using the Embedian MXM-8x10 Computer on Module
+ *
+ * Copyright (C) 2009 TMT Services & Supplies (Pty) Ltd.
+ *
+ * 2010-01-21 Hennie van der Merve <hvdmerwe@tmtservies.co.za>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/pxa320.h>
+#include <mach/mxm8x10.h>
+
+#include <linux/spi/spi.h>
+#include <mach/pxa2xx_spi.h>
+#include <linux/can/platform/mcp251x.h>
+
+#include "generic.h"
+
+#define ICONTROL_MCP251x_nCS1	(15)
+#define ICONTROL_MCP251x_nCS2	(16)
+#define ICONTROL_MCP251x_nCS3	(17)
+#define ICONTROL_MCP251x_nCS4	(24)
+
+#define ICONTROL_MCP251x_nIRQ1	(74)
+#define ICONTROL_MCP251x_nIRQ2	(75)
+#define ICONTROL_MCP251x_nIRQ3	(76)
+#define ICONTROL_MCP251x_nIRQ4	(77)
+
+static struct pxa2xx_spi_chip mcp251x_chip_info1 = {
+	.tx_threshold   = 8,
+	.rx_threshold   = 128,
+	.dma_burst_size = 8,
+	.timeout        = 235,
+	.gpio_cs        = ICONTROL_MCP251x_nCS1
+};
+
+static struct pxa2xx_spi_chip mcp251x_chip_info2 = {
+	.tx_threshold   = 8,
+	.rx_threshold   = 128,
+	.dma_burst_size = 8,
+	.timeout        = 235,
+	.gpio_cs        = ICONTROL_MCP251x_nCS2
+};
+
+static struct pxa2xx_spi_chip mcp251x_chip_info3 = {
+	.tx_threshold   = 8,
+	.rx_threshold   = 128,
+	.dma_burst_size = 8,
+	.timeout        = 235,
+	.gpio_cs        = ICONTROL_MCP251x_nCS3
+};
+
+static struct pxa2xx_spi_chip mcp251x_chip_info4 = {
+	.tx_threshold   = 8,
+	.rx_threshold   = 128,
+	.dma_burst_size = 8,
+	.timeout        = 235,
+	.gpio_cs        = ICONTROL_MCP251x_nCS4
+};
+
+static struct mcp251x_platform_data mcp251x_info = {
+	.oscillator_frequency = 16E6,
+	.model                = CAN_MCP251X_MCP2515,
+	.board_specific_setup = NULL,
+	.power_enable         = NULL,
+	.transceiver_enable   = NULL
+};
+
+static struct spi_board_info mcp251x_board_info[] = {
+	{
+		.modalias        = "mcp251x",
+		.max_speed_hz    = 6500000,
+		.bus_num         = 3,
+		.chip_select     = 0,
+		.platform_data   = &mcp251x_info,
+		.controller_data = &mcp251x_chip_info1,
+		.irq             = gpio_to_irq(ICONTROL_MCP251x_nIRQ1)
+	},
+	{
+		.modalias        = "mcp251x",
+		.max_speed_hz    = 6500000,
+		.bus_num         = 3,
+		.chip_select     = 1,
+		.platform_data   = &mcp251x_info,
+		.controller_data = &mcp251x_chip_info2,
+		.irq             = gpio_to_irq(ICONTROL_MCP251x_nIRQ2)
+	},
+	{
+		.modalias        = "mcp251x",
+		.max_speed_hz    = 6500000,
+		.bus_num         = 4,
+		.chip_select     = 0,
+		.platform_data   = &mcp251x_info,
+		.controller_data = &mcp251x_chip_info3,
+		.irq             = gpio_to_irq(ICONTROL_MCP251x_nIRQ3)
+	},
+	{
+		.modalias        = "mcp251x",
+		.max_speed_hz    = 6500000,
+		.bus_num         = 4,
+		.chip_select     = 1,
+		.platform_data   = &mcp251x_info,
+		.controller_data = &mcp251x_chip_info4,
+		.irq             = gpio_to_irq(ICONTROL_MCP251x_nIRQ4)
+	}
+};
+
+static struct pxa2xx_spi_master pxa_ssp3_spi_master_info = {
+	.clock_enable   = CKEN_SSP3,
+	.num_chipselect = 2,
+	.enable_dma     = 1
+};
+
+static struct pxa2xx_spi_master pxa_ssp4_spi_master_info = {
+	.clock_enable   = CKEN_SSP4,
+	.num_chipselect = 2,
+	.enable_dma     = 1
+};
+
+struct platform_device pxa_spi_ssp3 = {
+	.name          = "pxa2xx-spi",
+	.id            = 3,
+	.dev           = {
+		.platform_data = &pxa_ssp3_spi_master_info,
+	}
+};
+
+struct platform_device pxa_spi_ssp4 = {
+	.name          = "pxa2xx-spi",
+	.id            = 4,
+	.dev           = {
+		.platform_data = &pxa_ssp4_spi_master_info,
+	}
+};
+
+static struct platform_device *icontrol_spi_devices[] __initdata = {
+	&pxa_spi_ssp3,
+	&pxa_spi_ssp4,
+};
+
+static mfp_cfg_t mfp_can_cfg[] __initdata = {
+	/* CAN CS lines */
+	GPIO15_GPIO,
+	GPIO16_GPIO,
+	GPIO17_GPIO,
+	GPIO24_GPIO,
+
+	/* SPI (SSP3) lines */
+	GPIO89_SSP3_SCLK,
+	GPIO91_SSP3_TXD,
+	GPIO92_SSP3_RXD,
+
+	/* SPI (SSP4) lines */
+	GPIO93_SSP4_SCLK,
+	GPIO95_SSP4_TXD,
+	GPIO96_SSP4_RXD,
+
+	/* CAN nIRQ lines */
+	GPIO74_GPIO | MFP_LPM_EDGE_RISE,
+	GPIO75_GPIO | MFP_LPM_EDGE_RISE,
+	GPIO76_GPIO | MFP_LPM_EDGE_RISE,
+	GPIO77_GPIO | MFP_LPM_EDGE_RISE
+};
+
+static void __init icontrol_can_init(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(mfp_can_cfg));
+	platform_add_devices(ARRAY_AND_SIZE(icontrol_spi_devices));
+	spi_register_board_info(ARRAY_AND_SIZE(mcp251x_board_info));
+}
+
+static void __init icontrol_init(void)
+{
+	mxm_8x10_barebones_init();
+	mxm_8x10_usb_host_init();
+	mxm_8x10_mmc_init();
+
+	icontrol_can_init();
+}
+
+MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
+	.phys_io	= 0x40000000,
+	.boot_params	= 0xa0000100,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa3xx_init_irq,
+	.timer		= &pxa_timer,
+	.init_machine	= icontrol_init
+MACHINE_END
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 5c9e11d..bc78c4d 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -47,25 +47,7 @@
 
 static unsigned long idp_pin_config[] __initdata = {
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
+	GPIOxx_LCD_DSTN_16BPP,
 
 	/* BTUART */
 	GPIO42_BTUART_RXD,
diff --git a/arch/arm/mach-pxa/imote2.c b/arch/arm/mach-pxa/imote2.c
index 5b0862d..b2f878b 100644
--- a/arch/arm/mach-pxa/imote2.c
+++ b/arch/arm/mach-pxa/imote2.c
@@ -64,7 +64,6 @@
 	GPIO116_GPIO,			/* CC_CCA */
 	GPIO0_GPIO,			/* CC_FIFOP */
 	GPIO16_GPIO,			/* CCSFD */
-	GPIO39_GPIO,			/* CSn */
 	GPIO115_GPIO,			/* Power enable */
 
 	/* I2C */
@@ -72,7 +71,7 @@
 	GPIO118_I2C_SDA,
 
 	/* SSP 3 - 802.15.4 radio */
-	GPIO39_GPIO, 			/* Chip Select */
+	GPIO39_GPIO,			/* Chip Select */
 	GPIO34_SSP3_SCLK,
 	GPIO35_SSP3_TXD,
 	GPIO41_SSP3_RXD,
diff --git a/arch/arm/mach-pxa/include/mach/balloon3.h b/arch/arm/mach-pxa/include/mach/balloon3.h
index bfec09b..1a74106 100644
--- a/arch/arm/mach-pxa/include/mach/balloon3.h
+++ b/arch/arm/mach-pxa/include/mach/balloon3.h
@@ -129,6 +129,16 @@
 #define CPLD_AROUTING_LOONR2INT_BIT    6
 #define CPLD_AROUTING_LOONR2EXT_BIT    7
 
+/* Balloon3 Interrupts */
+#define BALLOON3_IRQ(x)		(IRQ_BOARD_START + (x))
+
+#define BALLOON3_BP_CF_NRDY_IRQ	BALLOON3_IRQ(0)
+#define BALLOON3_BP_NSTSCHG_IRQ	BALLOON3_IRQ(1)
+
+#define BALLOON3_AUX_NIRQ	IRQ_GPIO(BALLOON3_GPIO_AUX_NIRQ)
+#define BALLOON3_CODEC_IRQ	IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ)
+#define BALLOON3_S0_CD_IRQ	IRQ_GPIO(BALLOON3_GPIO_S0_CD)
+
 extern int balloon3_has(enum balloon3_features feature);
 
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h
index e741bf1..7515757 100644
--- a/arch/arm/mach-pxa/include/mach/hardware.h
+++ b/arch/arm/mach-pxa/include/mach/hardware.h
@@ -314,7 +314,6 @@
 #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
 
 
diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h
index 3677a9a..ffc8314 100644
--- a/arch/arm/mach-pxa/include/mach/irqs.h
+++ b/arch/arm/mach-pxa/include/mach/irqs.h
@@ -135,82 +135,6 @@
 #define IRQ_BOARD_END		(IRQ_BOARD_START + 16)
 #endif
 
-#define IRQ_SA1111_START	(IRQ_BOARD_END)
-#define IRQ_GPAIN0		(IRQ_BOARD_END + 0)
-#define IRQ_GPAIN1		(IRQ_BOARD_END + 1)
-#define IRQ_GPAIN2		(IRQ_BOARD_END + 2)
-#define IRQ_GPAIN3		(IRQ_BOARD_END + 3)
-#define IRQ_GPBIN0		(IRQ_BOARD_END + 4)
-#define IRQ_GPBIN1		(IRQ_BOARD_END + 5)
-#define IRQ_GPBIN2		(IRQ_BOARD_END + 6)
-#define IRQ_GPBIN3		(IRQ_BOARD_END + 7)
-#define IRQ_GPBIN4		(IRQ_BOARD_END + 8)
-#define IRQ_GPBIN5		(IRQ_BOARD_END + 9)
-#define IRQ_GPCIN0		(IRQ_BOARD_END + 10)
-#define IRQ_GPCIN1		(IRQ_BOARD_END + 11)
-#define IRQ_GPCIN2		(IRQ_BOARD_END + 12)
-#define IRQ_GPCIN3		(IRQ_BOARD_END + 13)
-#define IRQ_GPCIN4		(IRQ_BOARD_END + 14)
-#define IRQ_GPCIN5		(IRQ_BOARD_END + 15)
-#define IRQ_GPCIN6		(IRQ_BOARD_END + 16)
-#define IRQ_GPCIN7		(IRQ_BOARD_END + 17)
-#define IRQ_MSTXINT		(IRQ_BOARD_END + 18)
-#define IRQ_MSRXINT		(IRQ_BOARD_END + 19)
-#define IRQ_MSSTOPERRINT	(IRQ_BOARD_END + 20)
-#define IRQ_TPTXINT		(IRQ_BOARD_END + 21)
-#define IRQ_TPRXINT		(IRQ_BOARD_END + 22)
-#define IRQ_TPSTOPERRINT	(IRQ_BOARD_END + 23)
-#define SSPXMTINT		(IRQ_BOARD_END + 24)
-#define SSPRCVINT		(IRQ_BOARD_END + 25)
-#define SSPROR			(IRQ_BOARD_END + 26)
-#define AUDXMTDMADONEA		(IRQ_BOARD_END + 32)
-#define AUDRCVDMADONEA		(IRQ_BOARD_END + 33)
-#define AUDXMTDMADONEB		(IRQ_BOARD_END + 34)
-#define AUDRCVDMADONEB		(IRQ_BOARD_END + 35)
-#define AUDTFSR			(IRQ_BOARD_END + 36)
-#define AUDRFSR			(IRQ_BOARD_END + 37)
-#define AUDTUR			(IRQ_BOARD_END + 38)
-#define AUDROR			(IRQ_BOARD_END + 39)
-#define AUDDTS			(IRQ_BOARD_END + 40)
-#define AUDRDD			(IRQ_BOARD_END + 41)
-#define AUDSTO			(IRQ_BOARD_END + 42)
-#define IRQ_USBPWR		(IRQ_BOARD_END + 43)
-#define IRQ_HCIM		(IRQ_BOARD_END + 44)
-#define IRQ_HCIBUFFACC		(IRQ_BOARD_END + 45)
-#define IRQ_HCIRMTWKP		(IRQ_BOARD_END + 46)
-#define IRQ_NHCIMFCIR		(IRQ_BOARD_END + 47)
-#define IRQ_USB_PORT_RESUME	(IRQ_BOARD_END + 48)
-#define IRQ_S0_READY_NINT	(IRQ_BOARD_END + 49)
-#define IRQ_S1_READY_NINT	(IRQ_BOARD_END + 50)
-#define IRQ_S0_CD_VALID		(IRQ_BOARD_END + 51)
-#define IRQ_S1_CD_VALID		(IRQ_BOARD_END + 52)
-#define IRQ_S0_BVD1_STSCHG	(IRQ_BOARD_END + 53)
-#define IRQ_S1_BVD1_STSCHG	(IRQ_BOARD_END + 54)
-
-#define IRQ_LOCOMO_START	(IRQ_BOARD_END)
-#define IRQ_LOCOMO_KEY		(IRQ_BOARD_END + 0)
-#define IRQ_LOCOMO_GPIO0	(IRQ_BOARD_END + 1)
-#define IRQ_LOCOMO_GPIO1	(IRQ_BOARD_END + 2)
-#define IRQ_LOCOMO_GPIO2	(IRQ_BOARD_END + 3)
-#define IRQ_LOCOMO_GPIO3	(IRQ_BOARD_END + 4)
-#define IRQ_LOCOMO_GPIO4	(IRQ_BOARD_END + 5)
-#define IRQ_LOCOMO_GPIO5	(IRQ_BOARD_END + 6)
-#define IRQ_LOCOMO_GPIO6	(IRQ_BOARD_END + 7)
-#define IRQ_LOCOMO_GPIO7	(IRQ_BOARD_END + 8)
-#define IRQ_LOCOMO_GPIO8	(IRQ_BOARD_END + 9)
-#define IRQ_LOCOMO_GPIO9	(IRQ_BOARD_END + 10)
-#define IRQ_LOCOMO_GPIO10	(IRQ_BOARD_END + 11)
-#define IRQ_LOCOMO_GPIO11	(IRQ_BOARD_END + 12)
-#define IRQ_LOCOMO_GPIO12	(IRQ_BOARD_END + 13)
-#define IRQ_LOCOMO_GPIO13	(IRQ_BOARD_END + 14)
-#define IRQ_LOCOMO_GPIO14	(IRQ_BOARD_END + 15)
-#define IRQ_LOCOMO_GPIO15	(IRQ_BOARD_END + 16)
-#define IRQ_LOCOMO_LT		(IRQ_BOARD_END + 17)
-#define IRQ_LOCOMO_SPI_RFR	(IRQ_BOARD_END + 18)
-#define IRQ_LOCOMO_SPI_RFW	(IRQ_BOARD_END + 19)
-#define IRQ_LOCOMO_SPI_OVRN	(IRQ_BOARD_END + 20)
-#define IRQ_LOCOMO_SPI_TEND	(IRQ_BOARD_END + 21)
-
 /*
  * Figure out the MAX IRQ number.
  *
@@ -219,89 +143,16 @@
  * Otherwise, we have the standard IRQs only.
  */
 #ifdef CONFIG_SA1111
-#define NR_IRQS			(IRQ_S1_BVD1_STSCHG + 1)
-#elif defined(CONFIG_SHARP_LOCOMO)
-#define NR_IRQS			(IRQ_LOCOMO_SPI_TEND + 1)
+#define NR_IRQS			(IRQ_BOARD_END + 55)
 #elif defined(CONFIG_PXA_HAVE_BOARD_IRQS)
 #define NR_IRQS			(IRQ_BOARD_END)
 #else
 #define NR_IRQS			(IRQ_BOARD_START)
 #endif
 
-/*
- * Board specific IRQs.  Define them here.
- * Do not surround them with ifdefs.
- */
-#define LUBBOCK_IRQ(x)		(IRQ_BOARD_START + (x))
-#define LUBBOCK_SD_IRQ		LUBBOCK_IRQ(0)
-#define LUBBOCK_SA1111_IRQ	LUBBOCK_IRQ(1)
-#define LUBBOCK_USB_IRQ		LUBBOCK_IRQ(2)  /* usb connect */
-#define LUBBOCK_ETH_IRQ		LUBBOCK_IRQ(3)
-#define LUBBOCK_UCB1400_IRQ	LUBBOCK_IRQ(4)
-#define LUBBOCK_BB_IRQ		LUBBOCK_IRQ(5)
-#define LUBBOCK_USB_DISC_IRQ	LUBBOCK_IRQ(6)  /* usb disconnect */
-#define LUBBOCK_LAST_IRQ	LUBBOCK_IRQ(6)
-
-#define LPD270_IRQ(x)		(IRQ_BOARD_START + (x))
-#define LPD270_USBC_IRQ		LPD270_IRQ(2)
-#define LPD270_ETHERNET_IRQ	LPD270_IRQ(3)
-#define LPD270_AC97_IRQ		LPD270_IRQ(4)
-
-#define MAINSTONE_IRQ(x)	(IRQ_BOARD_START + (x))
-#define MAINSTONE_MMC_IRQ	MAINSTONE_IRQ(0)
-#define MAINSTONE_USIM_IRQ	MAINSTONE_IRQ(1)
-#define MAINSTONE_USBC_IRQ	MAINSTONE_IRQ(2)
-#define MAINSTONE_ETHERNET_IRQ	MAINSTONE_IRQ(3)
-#define MAINSTONE_AC97_IRQ	MAINSTONE_IRQ(4)
-#define MAINSTONE_PEN_IRQ	MAINSTONE_IRQ(5)
-#define MAINSTONE_MSINS_IRQ	MAINSTONE_IRQ(6)
-#define MAINSTONE_EXBRD_IRQ	MAINSTONE_IRQ(7)
-#define MAINSTONE_S0_CD_IRQ	MAINSTONE_IRQ(9)
-#define MAINSTONE_S0_STSCHG_IRQ	MAINSTONE_IRQ(10)
-#define MAINSTONE_S0_IRQ	MAINSTONE_IRQ(11)
-#define MAINSTONE_S1_CD_IRQ	MAINSTONE_IRQ(13)
-#define MAINSTONE_S1_STSCHG_IRQ	MAINSTONE_IRQ(14)
-#define MAINSTONE_S1_IRQ	MAINSTONE_IRQ(15)
-
-/* Balloon3 Interrupts */
-#define BALLOON3_IRQ(x)		(IRQ_BOARD_START + (x))
-
-#define BALLOON3_BP_CF_NRDY_IRQ	BALLOON3_IRQ(0)
-#define BALLOON3_BP_NSTSCHG_IRQ	BALLOON3_IRQ(1)
-
-#define BALLOON3_AUX_NIRQ	IRQ_GPIO(BALLOON3_GPIO_AUX_NIRQ)
-#define BALLOON3_CODEC_IRQ	IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ)
-#define BALLOON3_S0_CD_IRQ	IRQ_GPIO(BALLOON3_GPIO_S0_CD)
-
-/* LoCoMo Interrupts (CONFIG_SHARP_LOCOMO) */
-#define IRQ_LOCOMO_KEY_BASE	(IRQ_BOARD_START + 0)
-#define IRQ_LOCOMO_GPIO_BASE	(IRQ_BOARD_START + 1)
-#define IRQ_LOCOMO_LT_BASE	(IRQ_BOARD_START + 2)
-#define IRQ_LOCOMO_SPI_BASE	(IRQ_BOARD_START + 3)
-
-/* phyCORE-PXA270 (PCM027) Interrupts */
-#define PCM027_IRQ(x)          (IRQ_BOARD_START + (x))
-#define PCM027_BTDET_IRQ       PCM027_IRQ(0)
-#define PCM027_FF_RI_IRQ       PCM027_IRQ(1)
-#define PCM027_MMCDET_IRQ      PCM027_IRQ(2)
-#define PCM027_PM_5V_IRQ       PCM027_IRQ(3)
-
-/* ITE8152 irqs */
 /* add IT8152 IRQs beyond BOARD_END */
 #ifdef CONFIG_PCI_HOST_ITE8152
-#define IT8152_IRQ(x)   (IRQ_BOARD_END + (x))
-
-/* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
-#define IT8152_LD_IRQ_COUNT     9
-#define IT8152_LP_IRQ_COUNT     16
-#define IT8152_PD_IRQ_COUNT     15
-
-/* Priorities: */
-#define IT8152_PD_IRQ(i)        IT8152_IRQ(i)
-#define IT8152_LP_IRQ(i)        (IT8152_IRQ(i) + IT8152_PD_IRQ_COUNT)
-#define IT8152_LD_IRQ(i)        (IT8152_IRQ(i) + IT8152_PD_IRQ_COUNT + IT8152_LP_IRQ_COUNT)
-
-#define IT8152_LAST_IRQ         IT8152_LD_IRQ(IT8152_LD_IRQ_COUNT - 1)
+#define IT8152_LAST_IRQ         (IRQ_BOARD_END + 40)
 
 #if NR_IRQS < (IT8152_LAST_IRQ+1)
 #undef NR_IRQS
diff --git a/arch/arm/mach-pxa/include/mach/lpd270.h b/arch/arm/mach-pxa/include/mach/lpd270.h
index f89fb71..0e6440c 100644
--- a/arch/arm/mach-pxa/include/mach/lpd270.h
+++ b/arch/arm/mach-pxa/include/mach/lpd270.h
@@ -34,5 +34,9 @@
 #define LPD270_INT_ETHERNET	(1 << 3)  /* Ethernet controller IRQ */
 #define LPD270_INT_USBC		(1 << 2)  /* USB client cable detection IRQ */
 
+#define LPD270_IRQ(x)		(IRQ_BOARD_START + (x))
+#define LPD270_USBC_IRQ		LPD270_IRQ(2)
+#define LPD270_ETHERNET_IRQ	LPD270_IRQ(3)
+#define LPD270_AC97_IRQ		LPD270_IRQ(4)
 
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/lubbock.h b/arch/arm/mach-pxa/include/mach/lubbock.h
index 751b748..a0d4247 100644
--- a/arch/arm/mach-pxa/include/mach/lubbock.h
+++ b/arch/arm/mach-pxa/include/mach/lubbock.h
@@ -34,6 +34,17 @@
 #define LUB_IRQ_SET_CLR		__LUB_REG(LUBBOCK_FPGA_PHYS + 0x0d0)
 #define LUB_GP			__LUB_REG(LUBBOCK_FPGA_PHYS + 0x100)
 
+/* Board specific IRQs */
+#define LUBBOCK_IRQ(x)		(IRQ_BOARD_START + (x))
+#define LUBBOCK_SD_IRQ		LUBBOCK_IRQ(0)
+#define LUBBOCK_SA1111_IRQ	LUBBOCK_IRQ(1)
+#define LUBBOCK_USB_IRQ		LUBBOCK_IRQ(2)  /* usb connect */
+#define LUBBOCK_ETH_IRQ		LUBBOCK_IRQ(3)
+#define LUBBOCK_UCB1400_IRQ	LUBBOCK_IRQ(4)
+#define LUBBOCK_BB_IRQ		LUBBOCK_IRQ(5)
+#define LUBBOCK_USB_DISC_IRQ	LUBBOCK_IRQ(6)  /* usb disconnect */
+#define LUBBOCK_LAST_IRQ	LUBBOCK_IRQ(6)
+
 #ifndef __ASSEMBLY__
 extern void lubbock_set_misc_wr(unsigned int mask, unsigned int set);
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/mainstone.h b/arch/arm/mach-pxa/include/mach/mainstone.h
index 3461c43..86e623a 100644
--- a/arch/arm/mach-pxa/include/mach/mainstone.h
+++ b/arch/arm/mach-pxa/include/mach/mainstone.h
@@ -117,4 +117,21 @@
 #define MST_PCMCIA_PWR_VCC_33   0x8	   /* voltage VCC = 3.3V */
 #define MST_PCMCIA_PWR_VCC_50   0x4	   /* voltage VCC = 5.0V */
 
+/* board specific IRQs */
+#define MAINSTONE_IRQ(x)	(IRQ_BOARD_START + (x))
+#define MAINSTONE_MMC_IRQ	MAINSTONE_IRQ(0)
+#define MAINSTONE_USIM_IRQ	MAINSTONE_IRQ(1)
+#define MAINSTONE_USBC_IRQ	MAINSTONE_IRQ(2)
+#define MAINSTONE_ETHERNET_IRQ	MAINSTONE_IRQ(3)
+#define MAINSTONE_AC97_IRQ	MAINSTONE_IRQ(4)
+#define MAINSTONE_PEN_IRQ	MAINSTONE_IRQ(5)
+#define MAINSTONE_MSINS_IRQ	MAINSTONE_IRQ(6)
+#define MAINSTONE_EXBRD_IRQ	MAINSTONE_IRQ(7)
+#define MAINSTONE_S0_CD_IRQ	MAINSTONE_IRQ(9)
+#define MAINSTONE_S0_STSCHG_IRQ	MAINSTONE_IRQ(10)
+#define MAINSTONE_S0_IRQ	MAINSTONE_IRQ(11)
+#define MAINSTONE_S1_CD_IRQ	MAINSTONE_IRQ(13)
+#define MAINSTONE_S1_STSCHG_IRQ	MAINSTONE_IRQ(14)
+#define MAINSTONE_S1_IRQ	MAINSTONE_IRQ(15)
+
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h
index 9c78785..cafadc3 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa25x.h
@@ -190,4 +190,36 @@
 #define GPIO89_AC97_nRESET	MFP_CFG_OUT(GPIO89, AF0, DRIVE_HIGH)
 #endif	/* CONFIG_CPU_PXA26x */
 
+/* commonly used pin configurations */
+#define GPIOxx_LCD_16BPP	\
+	GPIO58_LCD_LDD_0,	\
+	GPIO59_LCD_LDD_1,	\
+	GPIO60_LCD_LDD_2,	\
+	GPIO61_LCD_LDD_3,	\
+	GPIO62_LCD_LDD_4,	\
+	GPIO63_LCD_LDD_5,	\
+	GPIO64_LCD_LDD_6,	\
+	GPIO65_LCD_LDD_7,	\
+	GPIO66_LCD_LDD_8,	\
+	GPIO67_LCD_LDD_9,	\
+	GPIO68_LCD_LDD_10,	\
+	GPIO69_LCD_LDD_11,	\
+	GPIO70_LCD_LDD_12,	\
+	GPIO71_LCD_LDD_13,	\
+	GPIO72_LCD_LDD_14,	\
+	GPIO73_LCD_LDD_15
+
+#define GPIOxx_LCD_DSTN_16BPP	\
+	GPIOxx_LCD_16BPP,	\
+	GPIO74_LCD_FCLK,	\
+	GPIO75_LCD_LCLK,	\
+	GPIO76_LCD_PCLK
+
+#define GPIOxx_LCD_TFT_16BPP	\
+	GPIOxx_LCD_16BPP,	\
+	GPIO74_LCD_FCLK,	\
+	GPIO75_LCD_LCLK,	\
+	GPIO76_LCD_PCLK,	\
+	GPIO77_LCD_BIAS
+
 #endif /* __ASM_ARCH_MFP_PXA25X_H */
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
index 6543c05..ec0f0b0 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
@@ -434,5 +434,32 @@
 #define GPIO112_nMSINS		MFP_CFG_IN(GPIO112, AF2)
 #define GPIO32_MSSCLK		MFP_CFG_OUT(GPIO32, AF1, DRIVE_LOW)
 
+/* commonly used pin configurations */
+#define GPIOxx_LCD_16BPP	\
+	GPIO58_LCD_LDD_0,	\
+	GPIO59_LCD_LDD_1,	\
+	GPIO60_LCD_LDD_2,	\
+	GPIO61_LCD_LDD_3,	\
+	GPIO62_LCD_LDD_4,	\
+	GPIO63_LCD_LDD_5,	\
+	GPIO64_LCD_LDD_6,	\
+	GPIO65_LCD_LDD_7,	\
+	GPIO66_LCD_LDD_8,	\
+	GPIO67_LCD_LDD_9,	\
+	GPIO68_LCD_LDD_10,	\
+	GPIO69_LCD_LDD_11,	\
+	GPIO70_LCD_LDD_12,	\
+	GPIO71_LCD_LDD_13,	\
+	GPIO72_LCD_LDD_14,	\
+	GPIO73_LCD_LDD_15
+
+#define GPIOxx_LCD_TFT_16BPP	\
+	GPIOxx_LCD_16BPP,	\
+	GPIO74_LCD_FCLK,	\
+	GPIO75_LCD_LCLK,	\
+	GPIO76_LCD_PCLK,	\
+	GPIO77_LCD_BIAS
+
+
 extern int keypad_set_wake(unsigned int on);
 #endif /* __ASM_ARCH_MFP_PXA27X_H */
diff --git a/arch/arm/mach-pxa/include/mach/mxm8x10.h b/arch/arm/mach-pxa/include/mach/mxm8x10.h
new file mode 100644
index 0000000..ffa1566
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/mxm8x10.h
@@ -0,0 +1,21 @@
+#ifndef __MACH_MXM_8X10_H
+#define __MACH_MXM_8X10_H
+
+#define MXM_8X10_ETH_PHYS	0x13000000
+
+#if defined(CONFIG_MMC)
+
+#define MXM_8X10_SD_nCD (72)
+#define MXM_8X10_SD_WP (84)
+
+extern void mxm_8x10_mmc_init(void);
+#else
+static inline void mxm_8x10_mmc_init(void) {}
+#endif
+
+extern void mxm_8x10_usb_host_init(void);
+extern void mxm_8x10_ac97_init(void);
+
+extern void mxm_8x10_barebones_init(void);
+
+#endif /* __MACH_MXM_8X10_H */
diff --git a/arch/arm/mach-pxa/include/mach/pcm027.h b/arch/arm/mach-pxa/include/mach/pcm027.h
index 4dcd2e8..0408326 100644
--- a/arch/arm/mach-pxa/include/mach/pcm027.h
+++ b/arch/arm/mach-pxa/include/mach/pcm027.h
@@ -23,6 +23,13 @@
  * Definitions of CPU card resources only
  */
 
+/* phyCORE-PXA270 (PCM027) Interrupts */
+#define PCM027_IRQ(x)          (IRQ_BOARD_START + (x))
+#define PCM027_BTDET_IRQ       PCM027_IRQ(0)
+#define PCM027_FF_RI_IRQ       PCM027_IRQ(1)
+#define PCM027_MMCDET_IRQ      PCM027_IRQ(2)
+#define PCM027_PM_5V_IRQ       PCM027_IRQ(3)
+
 /* I2C RTC */
 #define PCM027_RTC_IRQ_GPIO	0
 #define PCM027_RTC_IRQ		IRQ_GPIO(PCM027_RTC_IRQ_GPIO)
diff --git a/arch/arm/mach-pxa/include/mach/ssp.h b/arch/arm/mach-pxa/include/mach/ssp.h
index cb5cb76..be1be5b 100644
--- a/arch/arm/mach-pxa/include/mach/ssp.h
+++ b/arch/arm/mach-pxa/include/mach/ssp.h
@@ -46,6 +46,7 @@
 	int		drcmr_tx;
 };
 
+#ifdef CONFIG_PXA_SSP_LEGACY
 /*
  * SSP initialisation flags
  */
@@ -78,6 +79,7 @@
 int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags);
 int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed);
 void ssp_exit(struct ssp_dev *dev);
+#endif /* CONFIG_PXA_SSP_LEGACY */
 
 /**
  * ssp_write_reg - Write to a SSP register
diff --git a/arch/arm/mach-pxa/include/mach/uncompress.h b/arch/arm/mach-pxa/include/mach/uncompress.h
index 237734b..5ef91d9 100644
--- a/arch/arm/mach-pxa/include/mach/uncompress.h
+++ b/arch/arm/mach-pxa/include/mach/uncompress.h
@@ -10,20 +10,41 @@
  */
 
 #include <linux/serial_reg.h>
-#include <mach/regs-uart.h>
 #include <asm/mach-types.h>
 
-#define __REG(x)       ((volatile unsigned long *)x)
+#define FFUART_BASE	(0x40100000)
+#define BTUART_BASE	(0x40200000)
+#define STUART_BASE	(0x40700000)
 
-static volatile unsigned long *UART = FFUART;
+static unsigned long uart_base = FFUART_BASE;
+static unsigned int uart_shift = 2;
+static unsigned int uart_is_pxa = 1;
+
+static inline unsigned char uart_read(int offset)
+{
+	return *(volatile unsigned char *)(uart_base + (offset << uart_shift));
+}
+
+static inline void uart_write(unsigned char val, int offset)
+{
+	*(volatile unsigned char *)(uart_base + (offset << uart_shift)) = val;
+}
+
+static inline int uart_is_enabled(void)
+{
+	/* assume enabled by default for non-PXA uarts */
+	return uart_is_pxa ? uart_read(UART_IER) & UART_IER_UUE : 1;
+}
 
 static inline void putc(char c)
 {
-	if (!(UART[UART_IER] & IER_UUE))
+	if (!uart_is_enabled())
 		return;
-	while (!(UART[UART_LSR] & LSR_TDRQ))
+
+	while (!(uart_read(UART_LSR) & UART_LSR_THRE))
 		barrier();
-	UART[UART_TX] = c;
+
+	uart_write(c, UART_TX);
 }
 
 /*
@@ -38,7 +59,13 @@
 	if (machine_is_littleton() || machine_is_intelmote2()
 	    || machine_is_csb726() || machine_is_stargate2()
 	    || machine_is_cm_x300() || machine_is_balloon3())
-		UART = STUART;
+		uart_base = STUART_BASE;
+
+	if (machine_is_arcom_zeus()) {
+		uart_base = 0x10000000;	/* nCS4 */
+		uart_shift = 1;
+		uart_is_pxa = 0;
+	}
 }
 
 /*
diff --git a/arch/arm/mach-pxa/include/mach/zeus.h b/arch/arm/mach-pxa/include/mach/zeus.h
index c387046..6e11997 100644
--- a/arch/arm/mach-pxa/include/mach/zeus.h
+++ b/arch/arm/mach-pxa/include/mach/zeus.h
@@ -58,6 +58,8 @@
 #define ZEUS_EXT1_GPIO(x)	(ZEUS_EXT1_GPIO_BASE + (x))
 #define ZEUS_USER_GPIO(x)	(ZEUS_USER_GPIO_BASE + (x))
 
+#define	ZEUS_CAN_SHDN_GPIO	ZEUS_EXT1_GPIO(2)
+
 /*
  * CPLD registers:
  * Only 4 registers, but spreaded over a 32MB address space.
@@ -68,7 +70,6 @@
 #define ZEUS_CPLD_VERSION	(ZEUS_CPLD + 0x0000)
 #define ZEUS_CPLD_ISA_IRQ	(ZEUS_CPLD + 0x1000)
 #define ZEUS_CPLD_CONTROL	(ZEUS_CPLD + 0x2000)
-#define ZEUS_CPLD_EXTWDOG	(ZEUS_CPLD + 0x3000)
 
 /* CPLD register bits */
 #define ZEUS_CPLD_CONTROL_CF_RST        0x01
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 1373c22..d279507 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -83,6 +83,10 @@
 	GPIO89_USBH1_PEN,
 
 	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
 	GPIO45_AC97_SYSCLK,
 
 	GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
@@ -121,7 +125,7 @@
 
 	pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled;
 	do {
-		GEDR(0) = GPIO_bit(0);  /* clear useless edge notification */
+		desc->chip->ack(irq);	/* clear useless edge notification */
 		if (likely(pending)) {
 			irq = LPD270_IRQ(0) + __ffs(pending);
 			generic_handle_irq(irq);
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 98ee7e5..63d65a2 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -66,26 +66,14 @@
 	GPIO25_SSP1_TXD,
 	GPIO26_SSP1_RXD,
 
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+
 	/* LCD - 16bpp DSTN */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
+	GPIOxx_LCD_DSTN_16BPP,
 
 	/* BTUART */
 	GPIO42_BTUART_RXD,
@@ -158,7 +146,7 @@
 {
 	unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
 	do {
-		GEDR(0) = GPIO_bit(0);	/* clear our parent irq */
+		desc->chip->ack(irq);	/* clear our parent irq */
 		if (likely(pending)) {
 			irq = LUBBOCK_IRQ(0) + __ffs(pending);
 			generic_handle_irq(irq);
@@ -240,11 +228,18 @@
 	},
 };
 
+static struct sa1111_platform_data sa1111_info = {
+	.irq_base	= IRQ_BOARD_END,
+};
+
 static struct platform_device sa1111_device = {
 	.name		= "sa1111",
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(sa1111_resources),
 	.resource	= sa1111_resources,
+	.dev		= {
+		.platform_data	= &sa1111_info,
+	},
 };
 
 /* ADS7846 is connected through SSP ... and if your board has J5 populated,
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 189f330..e81dd0c 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -88,26 +88,7 @@
 	GPIO112_MMC_CMD,
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* QCI */
 	GPIO12_CIF_DD_7,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 851ee0f..5543c64 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -60,26 +60,7 @@
 	GPIO15_nCS_1,
 
 	/* LCD - 16bpp Active TFT */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 	GPIO16_PWM0_OUT,	/* Backlight */
 
 	/* MMC */
@@ -107,6 +88,10 @@
 	GPIO57_nIOIS16,
 
 	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
 	GPIO45_AC97_SYSCLK,
 
 	/* Keypad */
@@ -162,7 +147,7 @@
 {
 	unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled;
 	do {
-		GEDR(0) = GPIO_bit(0);  /* clear useless edge notification */
+		desc->chip->ack(irq);	/* clear useless edge notification */
 		if (likely(pending)) {
 			irq = MAINSTONE_IRQ(0) + __ffs(pending);
 			generic_handle_irq(irq);
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 2466a44..843fcca 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -86,25 +86,7 @@
 	MIO_CFG_OUT(GPIO22_USB_ENABLE, AF0, DRIVE_LOW),
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* QCI */
 	GPIO12_CIF_DD_7,
@@ -155,6 +137,10 @@
 	GPIO41_FFUART_RTS,
 
 	/* Sound */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
 	GPIO89_AC97_SYSCLK,
 	MIO_CFG_IN(GPIO12_HPJACK_INSERT, AF0),
 
diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c
new file mode 100644
index 0000000..8c9c6f0
--- /dev/null
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -0,0 +1,474 @@
+/*
+ * linux/arch/arm/mach-pxa/mxm8x10.c
+ *
+ * Support for the Embedian MXM-8x10 Computer on Module
+ *
+ * Copyright (C) 2006 Marvell International Ltd.
+ * Copyright (C) 2009 Embedian Inc.
+ * Copyright (C) 2009 TMT Services & Supplies (Pty) Ltd.
+ *
+ * 2007-09-04: eric miao <eric.y.miao@gmail.com>
+ *             rewrite to align with latest kernel
+ *
+ * 2010-01-09: Edwin Peer <epeer@tmtservices.co.za>
+ * 	       Hennie van der Merwe <hvdmerwe@tmtservices.co.za>
+ *             rework for upstream merge
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/serial_8250.h>
+#include <linux/dm9000.h>
+#include <linux/gpio.h>
+
+#include <plat/i2c.h>
+#include <plat/pxa3xx_nand.h>
+
+#include <mach/pxafb.h>
+#include <mach/mmc.h>
+#include <mach/ohci.h>
+#include <mach/pxa320.h>
+
+#include <mach/mxm8x10.h>
+
+#include "devices.h"
+#include "generic.h"
+
+/* GPIO pin definition
+
+External device stuff   - Leave unconfigured for now...
+---------------------
+GPIO0   -   DREQ    (External DMA Request)
+GPIO3   -   nGCS2   (External Chip Select) Where is nGCS0; nGCS1; nGCS4; nGCS5 ?
+GPIO4   -   nGCS3
+GPIO15  -   EXT_GPIO1
+GPIO16  -   EXT_GPIO2
+GPIO17  -   EXT_GPIO3
+GPIO24  -   EXT_GPIO4
+GPIO25  -   EXT_GPIO5
+GPIO26  -   EXT_GPIO6
+GPIO27  -   EXT_GPIO7
+GPIO28  -   EXT_GPIO8
+GPIO29  -   EXT_GPIO9
+GPIO30  -   EXT_GPIO10
+GPIO31  -   EXT_GPIO11
+GPIO57  -   EXT_GPIO12
+GPIO74  -   EXT_IRQ1
+GPIO75  -   EXT_IRQ2
+GPIO76  -   EXT_IRQ3
+GPIO77  -   EXT_IRQ4
+GPIO78  -   EXT_IRQ5
+GPIO79  -   EXT_IRQ6
+GPIO80  -   EXT_IRQ7
+GPIO81  -   EXT_IRQ8
+GPIO87  -   VCCIO_PWREN (External Device PWREN)
+
+Dallas 1-Wire   - Leave unconfigured for now...
+-------------
+GPIO0_2 -   DS - 1Wire
+
+Ethernet
+--------
+GPIO1   -   DM9000 PWR
+GPIO9   -   DM9K_nIRQ
+GPIO36  -   DM9K_RESET
+
+Keypad  - Leave unconfigured by for now...
+------
+GPIO1_2 -   KP_DKIN0
+GPIO5_2 -   KP_MKOUT7
+GPIO82  -   KP_DKIN1
+GPIO85  -   KP_DKIN2
+GPIO86  -   KP_DKIN3
+GPIO113 -   KP_MKIN0
+GPIO114 -   KP_MKIN1
+GPIO115 -   KP_MKIN2
+GPIO116 -   KP_MKIN3
+GPIO117 -   KP_MKIN4
+GPIO118 -   KP_MKIN5
+GPIO119 -   KP_MKIN6
+GPIO120 -   KP_MKIN7
+GPIO121 -   KP_MKOUT0
+GPIO122 -   KP_MKOUT1
+GPIO122 -   KP_MKOUT2
+GPIO123 -   KP_MKOUT3
+GPIO124 -   KP_MKOUT4
+GPIO125 -   KP_MKOUT5
+GPIO127 -   KP_MKOUT6
+
+Data Bus    - Leave unconfigured for now...
+--------
+GPIO2   -   nWait (Data Bus)
+
+USB Device
+----------
+GPIO4_2 -   USBD_PULLUP
+GPIO10  -   UTM_CLK (USB Device UTM Clk)
+GPIO49  -   USB 2.0 Device UTM_DATA0
+GPIO50  -   USB 2.0 Device UTM_DATA1
+GPIO51  -   USB 2.0 Device UTM_DATA2
+GPIO52  -   USB 2.0 Device UTM_DATA3
+GPIO53  -   USB 2.0 Device UTM_DATA4
+GPIO54  -   USB 2.0 Device UTM_DATA5
+GPIO55  -   USB 2.0 Device UTM_DATA6
+GPIO56  -   USB 2.0 Device UTM_DATA7
+GPIO58  -   UTM_RXVALID (USB 2.0 Device)
+GPIO59  -   UTM_RXACTIVE (USB 2.0 Device)
+GPIO60  -   UTM_RXERROR
+GPIO61  -   UTM_OPMODE0
+GPIO62  -   UTM_OPMODE1
+GPIO71  -   USBD_INT    (USB Device?)
+GPIO73  -   UTM_TXREADY (USB 2.0 Device)
+GPIO83  -   UTM_TXVALID (USB 2.0 Device)
+GPIO98  -   UTM_RESET   (USB 2.0 device)
+GPIO99  -   UTM_XCVR_SELECT
+GPIO100 -   UTM_TERM_SELECT
+GPIO101 -   UTM_SUSPENDM_X
+GPIO102 -   UTM_LINESTATE0
+GPIO103 -   UTM_LINESTATE1
+
+Card-Bus Interface  - Leave unconfigured for now...
+------------------
+GPIO5   -   nPIOR (I/O space output enable)
+GPIO6   -   nPIOW (I/O space write enable)
+GPIO7   -   nIOS16 (Input from I/O space telling size of data bus)
+GPIO8   -   nPWAIT (Input for inserting wait states)
+
+LCD
+---
+GPIO6_2     -   LDD0
+GPIO7_2     -   LDD1
+GPIO8_2     -   LDD2
+GPIO9_2     -   LDD3
+GPIO11_2    -   LDD5
+GPIO12_2    -   LDD6
+GPIO13_2    -   LDD7
+GPIO14_2    -   VSYNC
+GPIO15_2    -   HSYNC
+GPIO16_2    -   VCLK
+GPIO17_2    -   HCLK
+GPIO18_2    -   VDEN
+GPIO63      -   LDD8    (CPU LCD)
+GPIO64      -   LDD9    (CPU LCD)
+GPIO65      -   LDD10   (CPU LCD)
+GPIO66      -   LDD11   (CPU LCD)
+GPIO67      -   LDD12   (CPU LCD)
+GPIO68      -   LDD13   (CPU LCD)
+GPIO69      -   LDD14   (CPU LCD)
+GPIO70      -   LDD15   (CPU LCD)
+GPIO88      -   VCCLCD_PWREN (LCD Panel PWREN)
+GPIO97      -   BACKLIGHT_EN
+GPIO104     -   LCD_PWREN
+
+PWM   - Leave unconfigured for now...
+---
+GPIO11  -   PWM0
+GPIO12  -   PWM1
+GPIO13  -   PWM2
+GPIO14  -   PWM3
+
+SD-CARD
+-------
+GPIO18  -   SDDATA0
+GPIO19  -   SDDATA1
+GPIO20  -   SDDATA2
+GPIO21  -   SDDATA3
+GPIO22  -   SDCLK
+GPIO23  -   SDCMD
+GPIO72  -   SD_WP
+GPIO84  -   SD_nIRQ_CD  (SD-Card)
+
+I2C
+---
+GPIO32  -   I2CSCL
+GPIO33  -   I2CSDA
+
+AC97
+----
+GPIO35  -   AC97_SDATA_IN
+GPIO37  -   AC97_SDATA_OUT
+GPIO38  -   AC97_SYNC
+GPIO39  -   AC97_BITCLK
+GPIO40  -   AC97_nRESET
+
+UART1
+-----
+GPIO41  -   UART_RXD1
+GPIO42  -   UART_TXD1
+GPIO43  -   UART_CTS1
+GPIO44  -   UART_DCD1
+GPIO45  -   UART_DSR1
+GPIO46  -   UART_nRI1
+GPIO47  -   UART_DTR1
+GPIO48  -   UART_RTS1
+
+UART2
+-----
+GPIO109 -   RTS2
+GPIO110 -   RXD2
+GPIO111 -   TXD2
+GPIO112 -   nCTS2
+
+UART3
+-----
+GPIO105 -   nCTS3
+GPIO106 -   nRTS3
+GPIO107 -   TXD3
+GPIO108 -   RXD3
+
+SSP3    - Leave unconfigured for now...
+----
+GPIO89  -   SSP3_CLK
+GPIO90  -   SSP3_SFRM
+GPIO91  -   SSP3_TXD
+GPIO92  -   SSP3_RXD
+
+SSP4
+GPIO93  -   SSP4_CLK
+GPIO94  -   SSP4_SFRM
+GPIO95  -   SSP4_TXD
+GPIO96  -   SSP4_RXD
+*/
+
+static mfp_cfg_t mfp_cfg[] __initdata = {
+	/* USB */
+	GPIO10_UTM_CLK,
+	GPIO49_U2D_PHYDATA_0,
+	GPIO50_U2D_PHYDATA_1,
+	GPIO51_U2D_PHYDATA_2,
+	GPIO52_U2D_PHYDATA_3,
+	GPIO53_U2D_PHYDATA_4,
+	GPIO54_U2D_PHYDATA_5,
+	GPIO55_U2D_PHYDATA_6,
+	GPIO56_U2D_PHYDATA_7,
+	GPIO58_UTM_RXVALID,
+	GPIO59_UTM_RXACTIVE,
+	GPIO60_U2D_RXERROR,
+	GPIO61_U2D_OPMODE0,
+	GPIO62_U2D_OPMODE1,
+	GPIO71_GPIO, /* USBD_INT */
+	GPIO73_UTM_TXREADY,
+	GPIO83_U2D_TXVALID,
+	GPIO98_U2D_RESET,
+	GPIO99_U2D_XCVR_SEL,
+	GPIO100_U2D_TERM_SEL,
+	GPIO101_U2D_SUSPEND,
+	GPIO102_UTM_LINESTATE_0,
+	GPIO103_UTM_LINESTATE_1,
+	GPIO4_2_GPIO | MFP_PULL_HIGH, /* UTM_PULLUP */
+
+	/* DM9000 */
+	GPIO1_GPIO,
+	GPIO9_GPIO,
+	GPIO36_GPIO,
+
+	/* AC97 */
+	GPIO35_AC97_SDATA_IN_0,
+	GPIO37_AC97_SDATA_OUT,
+	GPIO38_AC97_SYNC,
+	GPIO39_AC97_BITCLK,
+	GPIO40_AC97_nACRESET,
+
+	/* UARTS */
+	GPIO41_UART1_RXD,
+	GPIO42_UART1_TXD,
+	GPIO43_UART1_CTS,
+	GPIO44_UART1_DCD,
+	GPIO45_UART1_DSR,
+	GPIO46_UART1_RI,
+	GPIO47_UART1_DTR,
+	GPIO48_UART1_RTS,
+
+	GPIO109_UART2_RTS,
+	GPIO110_UART2_RXD,
+	GPIO111_UART2_TXD,
+	GPIO112_UART2_CTS,
+
+	GPIO105_UART3_CTS,
+	GPIO106_UART3_RTS,
+	GPIO107_UART3_TXD,
+	GPIO108_UART3_RXD,
+
+	GPIO78_GPIO,
+	GPIO79_GPIO,
+	GPIO80_GPIO,
+	GPIO81_GPIO,
+
+	/* I2C */
+	GPIO32_I2C_SCL,
+	GPIO33_I2C_SDA,
+
+	/* MMC */
+	GPIO18_MMC1_DAT0,
+	GPIO19_MMC1_DAT1,
+	GPIO20_MMC1_DAT2,
+	GPIO21_MMC1_DAT3,
+	GPIO22_MMC1_CLK,
+	GPIO23_MMC1_CMD,
+	GPIO72_GPIO | MFP_PULL_HIGH, /* Card Detect */
+	GPIO84_GPIO | MFP_PULL_LOW, /* Write Protect */
+
+	/* IRQ */
+	GPIO74_GPIO | MFP_LPM_EDGE_RISE, /* EXT_IRQ1 */
+	GPIO75_GPIO | MFP_LPM_EDGE_RISE, /* EXT_IRQ2 */
+	GPIO76_GPIO | MFP_LPM_EDGE_RISE, /* EXT_IRQ3 */
+	GPIO77_GPIO | MFP_LPM_EDGE_RISE, /* EXT_IRQ4 */
+	GPIO78_GPIO | MFP_LPM_EDGE_RISE, /* EXT_IRQ5 */
+	GPIO79_GPIO | MFP_LPM_EDGE_RISE, /* EXT_IRQ6 */
+	GPIO80_GPIO | MFP_LPM_EDGE_RISE, /* EXT_IRQ7 */
+	GPIO81_GPIO | MFP_LPM_EDGE_RISE  /* EXT_IRQ8 */
+};
+
+/* MMC/MCI Support */
+#if defined(CONFIG_MMC)
+static struct pxamci_platform_data mxm_8x10_mci_platform_data = {
+	.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+	.detect_delay = 1,
+	.gpio_card_detect = MXM_8X10_SD_nCD,
+	.gpio_card_ro = MXM_8X10_SD_WP,
+	.gpio_power = -1
+};
+
+void __init mxm_8x10_mmc_init(void)
+{
+	pxa_set_mci_info(&mxm_8x10_mci_platform_data);
+}
+#endif
+
+/* USB Open Host Controler Interface */
+static struct pxaohci_platform_data mxm_8x10_ohci_platform_data = {
+	.port_mode = PMM_NPS_MODE,
+	.flags = ENABLE_PORT_ALL
+};
+
+void __init mxm_8x10_usb_host_init(void)
+{
+	pxa_set_ohci_info(&mxm_8x10_ohci_platform_data);
+}
+
+/* AC97 Sound Support */
+static struct platform_device mxm_8x10_ac97_device = {
+	.name = "pxa2xx-ac97"
+};
+
+void __init mxm_8x10_ac97_init(void)
+{
+	platform_device_register(&mxm_8x10_ac97_device);
+}
+
+/* NAND flash Support */
+#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+#define NAND_BLOCK_SIZE SZ_128K
+#define NB(x)           (NAND_BLOCK_SIZE * (x))
+static struct mtd_partition mxm_8x10_nand_partitions[] = {
+	[0] = {
+	       .name = "boot",
+	       .size = NB(0x002),
+	       .offset = NB(0x000),
+	       .mask_flags = MTD_WRITEABLE
+	},
+	[1] = {
+	       .name = "kernel",
+	       .size = NB(0x010),
+	       .offset = NB(0x002),
+	       .mask_flags = MTD_WRITEABLE
+	},
+	[2] = {
+	       .name = "root",
+	       .size = NB(0x36c),
+	       .offset = NB(0x012)
+	},
+	[3] = {
+	       .name = "bbt",
+	       .size = NB(0x082),
+	       .offset = NB(0x37e),
+	       .mask_flags = MTD_WRITEABLE
+	}
+};
+
+static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
+	.enable_arbiter = 1,
+	.keep_config = 1,
+	.parts = mxm_8x10_nand_partitions,
+	.nr_parts = ARRAY_SIZE(mxm_8x10_nand_partitions)
+};
+
+static void __init mxm_8x10_nand_init(void)
+{
+	pxa3xx_set_nand_info(&mxm_8x10_nand_info);
+}
+#else
+static inline void mxm_8x10_nand_init(void) {}
+#endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */
+
+/* Ethernet support: Davicom DM9000 */
+static struct resource dm9k_resources[] = {
+	[0] = {
+	       .start = MXM_8X10_ETH_PHYS + 0x300,
+	       .end = MXM_8X10_ETH_PHYS + 0x300,
+	       .flags = IORESOURCE_MEM
+	},
+	[1] = {
+	       .start = MXM_8X10_ETH_PHYS + 0x308,
+	       .end = MXM_8X10_ETH_PHYS + 0x308,
+	       .flags = IORESOURCE_MEM
+	},
+	[2] = {
+	       .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO9)),
+	       .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO9)),
+	       .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE
+	}
+};
+
+static struct dm9000_plat_data dm9k_plat_data = {
+	.flags = DM9000_PLATF_16BITONLY
+};
+
+static struct platform_device dm9k_device = {
+	.name = "dm9000",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(dm9k_resources),
+	.resource = dm9k_resources,
+	.dev = {
+		.platform_data = &dm9k_plat_data
+	}
+};
+
+static void __init mxm_8x10_ethernet_init(void)
+{
+	platform_device_register(&dm9k_device);
+}
+
+/* PXA UARTs */
+static void __init mxm_8x10_uarts_init(void)
+{
+	pxa_set_ffuart_info(NULL);
+	pxa_set_btuart_info(NULL);
+	pxa_set_stuart_info(NULL);
+}
+
+/* I2C and Real Time Clock */
+static struct i2c_board_info __initdata mxm_8x10_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("ds1337", 0x68)
+	}
+};
+
+static void __init mxm_8x10_i2c_init(void)
+{
+	i2c_register_board_info(0, mxm_8x10_i2c_devices,
+				ARRAY_SIZE(mxm_8x10_i2c_devices));
+	pxa_set_i2c_info(NULL);
+}
+
+void __init mxm_8x10_barebones_init(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(mfp_cfg));
+
+	mxm_8x10_uarts_init();
+	mxm_8x10_nand_init();
+	mxm_8x10_i2c_init();
+	mxm_8x10_ethernet_init();
+}
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index e100af7..f70c75b 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -83,26 +83,7 @@
 	GPIO105_KP_MKOUT_2,
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* PWM */
 	GPIO16_PWM0_OUT,
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index 8fe3ec2..d902a81 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -87,26 +87,7 @@
 	GPIO105_KP_MKOUT_2,
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* PWM */
 	GPIO16_PWM0_OUT,
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index b992f07..717d7a6 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -84,26 +84,7 @@
 	GPIO36_GPIO,	/* pullup */
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* MATRIX KEYPAD */
 	GPIO0_GPIO | WAKEUP_ON_EDGE_BOTH,	/* in 0 */
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index dc728d6..3d284ff 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -73,26 +73,7 @@
 	GPIO47_FICP_TXD,
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* GPIO KEYS */
 	GPIO5_GPIO,	/* notes */
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index b433bb4..d8b4469 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -99,25 +99,7 @@
 	GPIO93_KP_DKIN_0 | WAKEUP_ON_LEVEL_HIGH,	/* Hotsync button */
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* Quick Capture Interface */
 	GPIO84_CIF_FV,
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index b37a025..007b58c 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -110,26 +110,7 @@
 	GPIO105_KP_MKOUT_2,
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* FFUART */
 	GPIO34_FFUART_RXD,
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 1c5d68a..3a7925c 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -95,26 +95,8 @@
 	GPIO105_KP_MKOUT_2,
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
+
 	GPIO20_GPIO,	/* bl power */
 	GPIO21_GPIO,	/* LCD border switch */
 	GPIO22_GPIO,	/* LCD border color */
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index d5255ae..9d0ecea1 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -58,6 +58,12 @@
 	/* I2C */
 	GPIO117_I2C_SCL,
 	GPIO118_I2C_SDA,
+
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
 };
 
 /*
@@ -259,8 +265,7 @@
 	unsigned long pending = (~PCM990_INTSETCLR) & pcm990_irq_enabled;
 
 	do {
-		GEDR(PCM990_CTRL_INT_IRQ_GPIO) =
-					GPIO_bit(PCM990_CTRL_INT_IRQ_GPIO);
+		desc->chip->ack(irq);	/* clear our parent IRQ */
 		if (likely(pending)) {
 			irq = PCM027_IRQ(0) + __ffs(pending);
 			generic_handle_irq(irq);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index c2b938a..d58a524 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -91,26 +91,7 @@
 	GPIO35_FFUART_CTS,
 
 	/* LCD */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* PC Card */
 	GPIO48_nPOE,
@@ -193,11 +174,18 @@
 	},
 };
 
+static struct locomo_platform_data locomo_info = {
+	.irq_base	= IRQ_BOARD_START,
+};
+
 struct platform_device poodle_locomo_device = {
 	.name		= "locomo",
 	.id		= 0,
 	.num_resources	= ARRAY_SIZE(locomo_resources),
 	.resource	= locomo_resources,
+	.dev		= {
+		.platform_data	= &locomo_info,
+	},
 };
 
 EXPORT_SYMBOL(poodle_locomo_device);
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index d783123..0af3617 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -40,6 +40,25 @@
 }
 EXPORT_SYMBOL(pxa27x_clear_otgph);
 
+static unsigned long ac97_reset_config[] = {
+	GPIO95_AC97_nRESET,
+	GPIO95_GPIO,
+	GPIO113_AC97_nRESET,
+	GPIO113_GPIO,
+};
+
+void pxa27x_assert_ac97reset(int reset_gpio, int on)
+{
+	if (reset_gpio == 113)
+		pxa2xx_mfp_config(on ? &ac97_reset_config[0] :
+				       &ac97_reset_config[1], 1);
+
+	if (reset_gpio == 95)
+		pxa2xx_mfp_config(on ? &ac97_reset_config[2] :
+				       &ac97_reset_config[3], 1);
+}
+EXPORT_SYMBOL_GPL(pxa27x_assert_ac97reset);
+
 /* Crystal clock: 13MHz */
 #define BASE_CLK	13000000
 
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
new file mode 100644
index 0000000..3184bdc
--- /dev/null
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -0,0 +1,1108 @@
+/*
+ * arch/arm/mach-pxa/raumfeld.c
+ *
+ * Support for the following Raumfeld devices:
+ *
+ * 	* Controller
+ *  	* Connector
+ *  	* Speaker S/M
+ *
+ * See http://www.raumfeld.com for details.
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+#include <linux/input.h>
+#include <linux/rotary_encoder.h>
+#include <linux/gpio_keys.h>
+#include <linux/input/eeti_ts.h>
+#include <linux/leds.h>
+#include <linux/w1-gpio.h>
+#include <linux/sched.h>
+#include <linux/pwm_backlight.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/lis3lv02d.h>
+#include <linux/pda_power.h>
+#include <linux/power_supply.h>
+#include <linux/pda_power.h>
+#include <linux/power_supply.h>
+#include <linux/regulator/max8660.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/hardware.h>
+#include <mach/pxa3xx-regs.h>
+#include <mach/mfp-pxa3xx.h>
+#include <mach/mfp-pxa300.h>
+#include <mach/ohci.h>
+#include <mach/pxafb.h>
+#include <mach/mmc.h>
+#include <plat/i2c.h>
+#include <plat/pxa3xx_nand.h>
+
+#include "generic.h"
+#include "devices.h"
+#include "clock.h"
+
+/* common GPIO	definitions */
+
+/* inputs */
+#define GPIO_ON_OFF		(14)
+#define GPIO_VOLENC_A		(19)
+#define GPIO_VOLENC_B		(20)
+#define GPIO_CHARGE_DONE	(23)
+#define GPIO_CHARGE_IND		(27)
+#define GPIO_TOUCH_IRQ		(32)
+#define GPIO_ETH_IRQ		(40)
+#define GPIO_SPI_MISO		(98)
+#define GPIO_ACCEL_IRQ		(104)
+#define GPIO_RESCUE_BOOT	(115)
+#define GPIO_DOCK_DETECT	(116)
+#define GPIO_KEY1		(117)
+#define GPIO_KEY2		(118)
+#define GPIO_KEY3		(119)
+#define GPIO_CHARGE_USB_OK	(112)
+#define GPIO_CHARGE_DC_OK	(101)
+#define GPIO_CHARGE_USB_SUSP	(102)
+
+/* outputs */
+#define GPIO_SHUTDOWN_SUPPLY	(16)
+#define GPIO_SHUTDOWN_BATT	(18)
+#define GPIO_CHRG_PEN2		(31)
+#define GPIO_TFT_VA_EN		(33)
+#define GPIO_SPDIF_CS		(34)
+#define GPIO_LED2		(35)
+#define GPIO_LED1		(36)
+#define GPIO_SPDIF_RESET	(38)
+#define GPIO_SPI_CLK		(95)
+#define GPIO_MCLK_DAC_CS	(96)
+#define GPIO_SPI_MOSI		(97)
+#define GPIO_W1_PULLUP_ENABLE	(105)
+#define GPIO_DISPLAY_ENABLE	(106)
+#define GPIO_MCLK_RESET		(111)
+#define GPIO_W2W_RESET		(113)
+#define GPIO_W2W_PDN		(114)
+#define GPIO_CODEC_RESET	(120)
+#define GPIO_AUDIO_VA_ENABLE	(124)
+#define GPIO_ACCEL_CS		(125)
+#define GPIO_ONE_WIRE		(126)
+
+/*
+ * GPIO configurations
+ */
+static mfp_cfg_t raumfeld_controller_pin_config[] __initdata = {
+	/* UART1 */
+	GPIO77_UART1_RXD,
+	GPIO78_UART1_TXD,
+	GPIO79_UART1_CTS,
+	GPIO81_UART1_DSR,
+	GPIO83_UART1_DTR,
+	GPIO84_UART1_RTS,
+
+	/* UART3 */
+	GPIO110_UART3_RXD,
+
+	/* USB Host */
+	GPIO0_2_USBH_PEN,
+	GPIO1_2_USBH_PWR,
+
+	/* I2C */
+	GPIO21_I2C_SCL | MFP_LPM_FLOAT | MFP_PULL_FLOAT,
+	GPIO22_I2C_SDA | MFP_LPM_FLOAT | MFP_PULL_FLOAT,
+
+	/* SPI */
+	GPIO34_GPIO,	/* SPDIF_CS */
+	GPIO96_GPIO,	/* MCLK_CS */
+	GPIO125_GPIO,	/* ACCEL_CS */
+
+	/* MMC */
+	GPIO3_MMC1_DAT0,
+	GPIO4_MMC1_DAT1,
+	GPIO5_MMC1_DAT2,
+	GPIO6_MMC1_DAT3,
+	GPIO7_MMC1_CLK,
+	GPIO8_MMC1_CMD,
+
+	/* One-wire */
+	GPIO126_GPIO | MFP_LPM_FLOAT,
+	GPIO105_GPIO | MFP_PULL_LOW | MFP_LPM_PULL_LOW,
+
+	/* CHRG_USB_OK */
+	GPIO101_GPIO | MFP_PULL_HIGH,
+	/* CHRG_USB_OK */
+	GPIO112_GPIO | MFP_PULL_HIGH,
+	/* CHRG_USB_SUSP */
+	GPIO102_GPIO,
+	/* DISPLAY_ENABLE */
+	GPIO106_GPIO,
+	/* DOCK_DETECT */
+	GPIO116_GPIO | MFP_LPM_FLOAT | MFP_PULL_FLOAT,
+
+	/* LCD */
+	GPIO54_LCD_LDD_0,
+	GPIO55_LCD_LDD_1,
+	GPIO56_LCD_LDD_2,
+	GPIO57_LCD_LDD_3,
+	GPIO58_LCD_LDD_4,
+	GPIO59_LCD_LDD_5,
+	GPIO60_LCD_LDD_6,
+	GPIO61_LCD_LDD_7,
+	GPIO62_LCD_LDD_8,
+	GPIO63_LCD_LDD_9,
+	GPIO64_LCD_LDD_10,
+	GPIO65_LCD_LDD_11,
+	GPIO66_LCD_LDD_12,
+	GPIO67_LCD_LDD_13,
+	GPIO68_LCD_LDD_14,
+	GPIO69_LCD_LDD_15,
+	GPIO70_LCD_LDD_16,
+	GPIO71_LCD_LDD_17,
+	GPIO72_LCD_FCLK,
+	GPIO73_LCD_LCLK,
+	GPIO74_LCD_PCLK,
+	GPIO75_LCD_BIAS,
+};
+
+static mfp_cfg_t raumfeld_connector_pin_config[] __initdata = {
+	/* UART1 */
+	GPIO77_UART1_RXD,
+	GPIO78_UART1_TXD,
+	GPIO79_UART1_CTS,
+	GPIO81_UART1_DSR,
+	GPIO83_UART1_DTR,
+	GPIO84_UART1_RTS,
+
+	/* UART3 */
+	GPIO110_UART3_RXD,
+
+	/* USB Host */
+	GPIO0_2_USBH_PEN,
+	GPIO1_2_USBH_PWR,
+
+	/* I2C */
+	GPIO21_I2C_SCL | MFP_LPM_FLOAT | MFP_PULL_FLOAT,
+	GPIO22_I2C_SDA | MFP_LPM_FLOAT | MFP_PULL_FLOAT,
+
+	/* SPI */
+	GPIO34_GPIO,	/* SPDIF_CS */
+	GPIO96_GPIO,	/* MCLK_CS */
+	GPIO125_GPIO,	/* ACCEL_CS */
+
+	/* MMC */
+	GPIO3_MMC1_DAT0,
+	GPIO4_MMC1_DAT1,
+	GPIO5_MMC1_DAT2,
+	GPIO6_MMC1_DAT3,
+	GPIO7_MMC1_CLK,
+	GPIO8_MMC1_CMD,
+
+	/* Ethernet */
+	GPIO1_nCS2,			/* CS */
+	GPIO40_GPIO | MFP_PULL_HIGH,	/* IRQ */
+
+	/* SSP for I2S */
+	GPIO85_SSP1_SCLK,
+	GPIO89_SSP1_EXTCLK,
+	GPIO86_SSP1_FRM,
+	GPIO87_SSP1_TXD,
+	GPIO88_SSP1_RXD,
+	GPIO90_SSP1_SYSCLK,
+
+	/* SSP2 for S/PDIF */
+	GPIO25_SSP2_SCLK,
+	GPIO26_SSP2_FRM,
+	GPIO27_SSP2_TXD,
+	GPIO29_SSP2_EXTCLK,
+
+	/* LEDs */
+	GPIO35_GPIO | MFP_LPM_PULL_LOW,
+	GPIO36_GPIO | MFP_LPM_DRIVE_HIGH,
+};
+
+static mfp_cfg_t raumfeld_speaker_pin_config[] __initdata = {
+	/* UART1 */
+	GPIO77_UART1_RXD,
+	GPIO78_UART1_TXD,
+	GPIO79_UART1_CTS,
+	GPIO81_UART1_DSR,
+	GPIO83_UART1_DTR,
+	GPIO84_UART1_RTS,
+
+	/* UART3 */
+	GPIO110_UART3_RXD,
+
+	/* USB Host */
+	GPIO0_2_USBH_PEN,
+	GPIO1_2_USBH_PWR,
+
+	/* I2C */
+	GPIO21_I2C_SCL | MFP_LPM_FLOAT | MFP_PULL_FLOAT,
+	GPIO22_I2C_SDA | MFP_LPM_FLOAT | MFP_PULL_FLOAT,
+
+	/* SPI */
+	GPIO34_GPIO,	/* SPDIF_CS */
+	GPIO96_GPIO,	/* MCLK_CS */
+	GPIO125_GPIO,	/* ACCEL_CS */
+
+	/* MMC */
+	GPIO3_MMC1_DAT0,
+	GPIO4_MMC1_DAT1,
+	GPIO5_MMC1_DAT2,
+	GPIO6_MMC1_DAT3,
+	GPIO7_MMC1_CLK,
+	GPIO8_MMC1_CMD,
+
+	/* Ethernet */
+	GPIO1_nCS2,			/* CS */
+	GPIO40_GPIO | MFP_PULL_HIGH,	/* IRQ */
+
+	/* SSP for I2S */
+	GPIO85_SSP1_SCLK,
+	GPIO89_SSP1_EXTCLK,
+	GPIO86_SSP1_FRM,
+	GPIO87_SSP1_TXD,
+	GPIO88_SSP1_RXD,
+	GPIO90_SSP1_SYSCLK,
+
+	/* LEDs */
+	GPIO35_GPIO | MFP_LPM_PULL_LOW,
+	GPIO36_GPIO | MFP_LPM_DRIVE_HIGH,
+};
+
+/*
+ * SMSC LAN9220 Ethernet
+ */
+
+static struct resource smc91x_resources[] = {
+	{
+		.start	= PXA3xx_CS2_PHYS,
+		.end	= PXA3xx_CS2_PHYS + 0xfffff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= gpio_to_irq(GPIO_ETH_IRQ),
+		.end	= gpio_to_irq(GPIO_ETH_IRQ),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
+	}
+};
+
+static struct smsc911x_platform_config raumfeld_smsc911x_config = {
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags		= SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+	.dev		= {
+		.platform_data = &raumfeld_smsc911x_config,
+	}
+};
+
+/**
+ * NAND
+ */
+
+static struct mtd_partition raumfeld_nand_partitions[] = {
+	{
+		.name		= "Bootloader",
+		.offset		= 0,
+		.size		= 0xa0000,
+		.mask_flags	= MTD_WRITEABLE, /* force read-only */
+	},
+	{
+		.name		= "BootloaderEnvironment",
+		.offset		= 0xa0000,
+		.size		= 0x20000,
+	},
+	{
+		.name		= "BootloaderSplashScreen",
+		.offset		= 0xc0000,
+		.size		= 0x60000,
+	},
+	{
+		.name		= "UBI",
+		.offset		= 0x120000,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
+	.enable_arbiter	= 1,
+	.keep_config	= 1,
+	.parts		= raumfeld_nand_partitions,
+	.nr_parts	= ARRAY_SIZE(raumfeld_nand_partitions),
+};
+
+/**
+ * USB (OHCI) support
+ */
+
+static struct pxaohci_platform_data raumfeld_ohci_info = {
+	.port_mode      = PMM_GLOBAL_MODE,
+	.flags		= ENABLE_PORT1,
+};
+
+/**
+ * Rotary encoder input device
+ */
+
+static struct rotary_encoder_platform_data raumfeld_rotary_encoder_info = {
+	.steps		= 24,
+	.axis		= REL_X,
+	.relative_axis	= 1,
+	.gpio_a		= GPIO_VOLENC_A,
+	.gpio_b		= GPIO_VOLENC_B,
+	.inverted_a	= 1,
+	.inverted_b	= 0,
+};
+
+static struct platform_device rotary_encoder_device = {
+	.name		= "rotary-encoder",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &raumfeld_rotary_encoder_info,
+	}
+};
+
+/**
+ * GPIO buttons
+ */
+
+static struct gpio_keys_button gpio_keys_button[] = {
+	{
+		.code			= KEY_F1,
+		.type			= EV_KEY,
+		.gpio			= GPIO_KEY1,
+		.active_low		= 1,
+		.wakeup			= 0,
+		.debounce_interval	= 5, /* ms */
+		.desc			= "Button 1",
+	},
+	{
+		.code			= KEY_F2,
+		.type			= EV_KEY,
+		.gpio			= GPIO_KEY2,
+		.active_low		= 1,
+		.wakeup			= 0,
+		.debounce_interval	= 5, /* ms */
+		.desc			= "Button 2",
+	},
+	{
+		.code			= KEY_F3,
+		.type			= EV_KEY,
+		.gpio			= GPIO_KEY3,
+		.active_low		= 1,
+		.wakeup			= 0,
+		.debounce_interval	= 5, /* ms */
+		.desc			= "Button 3",
+	},
+	{
+		.code			= KEY_F4,
+		.type			= EV_KEY,
+		.gpio			= GPIO_RESCUE_BOOT,
+		.active_low		= 0,
+		.wakeup			= 0,
+		.debounce_interval	= 5, /* ms */
+		.desc			= "rescue boot button",
+	},
+	{
+		.code			= KEY_F5,
+		.type			= EV_KEY,
+		.gpio			= GPIO_DOCK_DETECT,
+		.active_low		= 1,
+		.wakeup			= 0,
+		.debounce_interval	= 5, /* ms */
+		.desc			= "dock detect",
+	},
+	{
+		.code			= KEY_F6,
+		.type			= EV_KEY,
+		.gpio			= GPIO_ON_OFF,
+		.active_low		= 0,
+		.wakeup			= 0,
+		.debounce_interval	= 5, /* ms */
+		.desc			= "on/off button",
+	},
+};
+
+static struct gpio_keys_platform_data gpio_keys_platform_data = {
+	.buttons	= gpio_keys_button,
+	.nbuttons	= ARRAY_SIZE(gpio_keys_button),
+	.rep		= 0,
+};
+
+static struct platform_device raumfeld_gpio_keys_device = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev 	= {
+		.platform_data	= &gpio_keys_platform_data,
+	}
+};
+
+/**
+ * GPIO LEDs
+ */
+
+static struct gpio_led raumfeld_leds[] = {
+	{
+		.name		= "raumfeld:1",
+		.gpio		= GPIO_LED1,
+		.active_low	= 1,
+		.default_state	= LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name		= "raumfeld:2",
+		.gpio		= GPIO_LED2,
+		.active_low	= 0,
+		.default_state	= LEDS_GPIO_DEFSTATE_OFF,
+	}
+};
+
+static struct gpio_led_platform_data raumfeld_led_platform_data = {
+	.leds		= raumfeld_leds,
+	.num_leds	= ARRAY_SIZE(raumfeld_leds),
+};
+
+static struct platform_device raumfeld_led_device = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &raumfeld_led_platform_data,
+	},
+};
+
+/**
+ * One-wire (W1 bus) support
+ */
+
+static void w1_enable_external_pullup(int enable)
+{
+	gpio_set_value(GPIO_W1_PULLUP_ENABLE, enable);
+	msleep(100);
+}
+
+static struct w1_gpio_platform_data w1_gpio_platform_data = {
+	.pin			= GPIO_ONE_WIRE,
+	.is_open_drain		= 0,
+	.enable_external_pullup	= w1_enable_external_pullup,
+};
+
+struct platform_device raumfeld_w1_gpio_device = {
+	.name	= "w1-gpio",
+	.dev	= {
+		.platform_data = &w1_gpio_platform_data
+	}
+};
+
+static void __init raumfeld_w1_init(void)
+{
+	int ret = gpio_request(GPIO_W1_PULLUP_ENABLE,
+				"W1 external pullup enable");
+
+	if (ret < 0)
+		pr_warning("Unable to request GPIO_W1_PULLUP_ENABLE\n");
+	else
+		gpio_direction_output(GPIO_W1_PULLUP_ENABLE, 0);
+
+	platform_device_register(&raumfeld_w1_gpio_device);
+}
+
+/**
+ * Framebuffer device
+ */
+
+/* PWM controlled backlight */
+static struct platform_pwm_backlight_data raumfeld_pwm_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= 100,
+	.dft_brightness	= 100,
+	/* 10000 ns = 10 ms ^= 100 kHz */
+	.pwm_period_ns	= 10000,
+};
+
+static struct platform_device raumfeld_pwm_backlight_device = {
+	.name	= "pwm-backlight",
+	.dev	= {
+		.parent		= &pxa27x_device_pwm0.dev,
+		.platform_data	= &raumfeld_pwm_backlight_data,
+	}
+};
+
+/* LT3593 controlled backlight */
+static struct gpio_led raumfeld_lt3593_led = {
+	.name		= "backlight",
+	.gpio		= mfp_to_gpio(MFP_PIN_GPIO17),
+	.default_state	= LEDS_GPIO_DEFSTATE_ON,
+};
+
+static struct gpio_led_platform_data raumfeld_lt3593_platform_data = {
+	.leds		= &raumfeld_lt3593_led,
+	.num_leds	= 1,
+};
+
+static struct platform_device raumfeld_lt3593_device = {
+	.name	= "leds-lt3593",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &raumfeld_lt3593_platform_data,
+	},
+};
+
+static struct pxafb_mode_info sharp_lq043t3dx02_mode = {
+	.pixclock	= 111000,
+	.xres		= 480,
+	.yres		= 272,
+	.bpp		= 16,
+	.hsync_len	= 4,
+	.left_margin	= 2,
+	.right_margin	= 1,
+	.vsync_len	= 1,
+	.upper_margin	= 3,
+	.lower_margin	= 1,
+	.sync		= 0,
+};
+
+static struct pxafb_mach_info raumfeld_sharp_lcd_info = {
+	.modes		= &sharp_lq043t3dx02_mode,
+	.num_modes	= 1,
+	.video_mem_size = 0x400000,
+	.lcd_conn	= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+};
+
+static void __init raumfeld_lcd_init(void)
+{
+	int ret;
+
+	set_pxa_fb_info(&raumfeld_sharp_lcd_info);
+
+	/* Earlier devices had the backlight regulator controlled
+	 * via PWM, later versions use another controller for that */
+	if ((system_rev & 0xff) < 2) {
+		mfp_cfg_t raumfeld_pwm_pin_config = GPIO17_PWM0_OUT;
+		pxa3xx_mfp_config(&raumfeld_pwm_pin_config, 1);
+		platform_device_register(&raumfeld_pwm_backlight_device);
+	} else
+		platform_device_register(&raumfeld_lt3593_device);
+
+	ret = gpio_request(GPIO_TFT_VA_EN, "display VA enable");
+	if (ret < 0)
+		pr_warning("Unable to request GPIO_TFT_VA_EN\n");
+	else
+		gpio_direction_output(GPIO_TFT_VA_EN, 1);
+
+	ret = gpio_request(GPIO_DISPLAY_ENABLE, "display enable");
+	if (ret < 0)
+		pr_warning("Unable to request GPIO_DISPLAY_ENABLE\n");
+	else
+		gpio_direction_output(GPIO_DISPLAY_ENABLE, 1);
+}
+
+/**
+ * SPI devices
+ */
+
+struct spi_gpio_platform_data raumfeld_spi_platform_data = {
+	.sck		= GPIO_SPI_CLK,
+	.mosi		= GPIO_SPI_MOSI,
+	.miso		= GPIO_SPI_MISO,
+	.num_chipselect	= 3,
+};
+
+static struct platform_device raumfeld_spi_device = {
+	.name	= "spi_gpio",
+	.id	= 0,
+	.dev 	= {
+		.platform_data	= &raumfeld_spi_platform_data,
+	}
+};
+
+static struct lis3lv02d_platform_data lis3_pdata = {
+	.click_flags 	= LIS3_CLICK_SINGLE_X |
+			  LIS3_CLICK_SINGLE_Y |
+			  LIS3_CLICK_SINGLE_Z,
+	.irq_cfg	= LIS3_IRQ1_CLICK | LIS3_IRQ2_CLICK,
+	.wakeup_flags	= LIS3_WAKEUP_X_LO | LIS3_WAKEUP_X_HI |
+			  LIS3_WAKEUP_Y_LO | LIS3_WAKEUP_Y_HI |
+			  LIS3_WAKEUP_Z_LO | LIS3_WAKEUP_Z_HI,
+	.wakeup_thresh	= 10,
+	.click_thresh_x = 10,
+	.click_thresh_y = 10,
+	.click_thresh_z = 10,
+};
+
+#define SPI_AK4104	\
+{			\
+	.modalias	= "ak4104",	\
+	.max_speed_hz	= 10000,	\
+	.bus_num	= 0,		\
+	.chip_select	= 0,		\
+	.controller_data = (void *) GPIO_SPDIF_CS,	\
+}
+
+#define SPI_LIS3	\
+{			\
+	.modalias	= "lis3lv02d_spi",	\
+	.max_speed_hz	= 1000000,		\
+	.bus_num	= 0,			\
+	.chip_select	= 1,			\
+	.controller_data = (void *) GPIO_ACCEL_CS,	\
+	.platform_data	= &lis3_pdata,		\
+	.irq		= gpio_to_irq(GPIO_ACCEL_IRQ),	\
+}
+
+#define SPI_DAC7512	\
+{	\
+	.modalias	= "dac7512",		\
+	.max_speed_hz	= 1000000,		\
+	.bus_num	= 0,			\
+	.chip_select	= 2,			\
+	.controller_data = (void *) GPIO_MCLK_DAC_CS,	\
+}
+
+static struct spi_board_info connector_spi_devices[] __initdata = {
+	SPI_AK4104,
+	SPI_DAC7512,
+};
+
+static struct spi_board_info speaker_spi_devices[] __initdata = {
+	SPI_DAC7512,
+};
+
+static struct spi_board_info controller_spi_devices[] __initdata = {
+	SPI_LIS3,
+};
+
+/**
+ * MMC for Marvell Libertas 8688 via SDIO
+ */
+
+static int raumfeld_mci_init(struct device *dev, irq_handler_t isr, void *data)
+{
+	gpio_set_value(GPIO_W2W_RESET, 1);
+	gpio_set_value(GPIO_W2W_PDN, 1);
+
+	return 0;
+}
+
+static void raumfeld_mci_exit(struct device *dev, void *data)
+{
+	gpio_set_value(GPIO_W2W_RESET, 0);
+	gpio_set_value(GPIO_W2W_PDN, 0);
+}
+
+static struct pxamci_platform_data raumfeld_mci_platform_data = {
+	.init			= raumfeld_mci_init,
+	.exit			= raumfeld_mci_exit,
+	.detect_delay		= 20,
+	.gpio_card_detect	= -1,
+	.gpio_card_ro		= -1,
+	.gpio_power		= -1,
+};
+
+/*
+ * External power / charge logic
+ */
+
+static int power_supply_init(struct device *dev)
+{
+	return 0;
+}
+
+static void power_supply_exit(struct device *dev)
+{
+}
+
+static int raumfeld_is_ac_online(void)
+{
+	return !gpio_get_value(GPIO_CHARGE_DC_OK);
+}
+
+static int raumfeld_is_usb_online(void)
+{
+	return 0;
+}
+
+static char *raumfeld_power_supplicants[] = { "ds2760-battery.0" };
+
+static struct pda_power_pdata power_supply_info = {
+	.init			= power_supply_init,
+	.is_ac_online		= raumfeld_is_ac_online,
+	.is_usb_online		= raumfeld_is_usb_online,
+	.exit			= power_supply_exit,
+	.supplied_to		= raumfeld_power_supplicants,
+	.num_supplicants	= ARRAY_SIZE(raumfeld_power_supplicants)
+};
+
+static struct resource power_supply_resources[] = {
+	{
+		.name  = "ac",
+		.flags = IORESOURCE_IRQ |
+			 IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE,
+		.start = GPIO_CHARGE_DC_OK,
+		.end   = GPIO_CHARGE_DC_OK,
+	},
+};
+
+static irqreturn_t charge_done_irq(int irq, void *dev_id)
+{
+	struct power_supply *psy;
+
+	psy = power_supply_get_by_name("ds2760-battery.0");
+
+	if (psy)
+		power_supply_set_battery_charged(psy);
+
+	return IRQ_HANDLED;
+}
+
+static struct platform_device raumfeld_power_supply = {
+	.name = "pda-power",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &power_supply_info,
+	},
+	.resource      = power_supply_resources,
+	.num_resources = ARRAY_SIZE(power_supply_resources),
+};
+
+static void __init raumfeld_power_init(void)
+{
+	int ret;
+
+	/* Set PEN2 high to enable maximum charge current */
+	ret = gpio_request(GPIO_CHRG_PEN2, "CHRG_PEN2");
+	if (ret < 0)
+		pr_warning("Unable to request GPIO_CHRG_PEN2\n");
+	else
+		gpio_direction_output(GPIO_CHRG_PEN2, 1);
+
+	ret = gpio_request(GPIO_CHARGE_DC_OK, "CABLE_DC_OK");
+	if (ret < 0)
+		pr_warning("Unable to request GPIO_CHARGE_DC_OK\n");
+
+	ret = gpio_request(GPIO_CHARGE_USB_SUSP, "CHARGE_USB_SUSP");
+	if (ret < 0)
+		pr_warning("Unable to request GPIO_CHARGE_USB_SUSP\n");
+	else
+		gpio_direction_output(GPIO_CHARGE_USB_SUSP, 0);
+
+	power_supply_resources[0].start = gpio_to_irq(GPIO_CHARGE_DC_OK);
+	power_supply_resources[0].end = gpio_to_irq(GPIO_CHARGE_DC_OK);
+
+	ret = request_irq(gpio_to_irq(GPIO_CHARGE_DONE),
+			&charge_done_irq, IORESOURCE_IRQ_LOWEDGE,
+			"charge_done", NULL);
+
+	if (ret < 0)
+		printk(KERN_ERR "%s: unable to register irq %d\n", __func__,
+			GPIO_CHARGE_DONE);
+	else
+		platform_device_register(&raumfeld_power_supply);
+}
+
+/* Fixed regulator for AUDIO_VA, 0-0048 maps to the cs4270 codec device */
+
+static struct regulator_consumer_supply audio_va_consumer_supply =
+	REGULATOR_SUPPLY("va", "0-0048");
+
+struct regulator_init_data audio_va_initdata = {
+	.consumer_supplies = &audio_va_consumer_supply,
+	.num_consumer_supplies = 1,
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct fixed_voltage_config audio_va_config = {
+	.supply_name		= "audio_va",
+	.microvolts		= 5000000,
+	.gpio			= GPIO_AUDIO_VA_ENABLE,
+	.enable_high		= 1,
+	.enabled_at_boot	= 0,
+	.init_data		= &audio_va_initdata,
+};
+
+static struct platform_device audio_va_device = {
+	.name	= "reg-fixed-voltage",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &audio_va_config,
+	},
+};
+
+/* Dummy supplies for Codec's VD/VLC */
+
+static struct regulator_consumer_supply audio_dummy_supplies[] = {
+	REGULATOR_SUPPLY("vd", "0-0048"),
+	REGULATOR_SUPPLY("vlc", "0-0048"),
+};
+
+struct regulator_init_data audio_dummy_initdata = {
+	.consumer_supplies = audio_dummy_supplies,
+	.num_consumer_supplies = ARRAY_SIZE(audio_dummy_supplies),
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct fixed_voltage_config audio_dummy_config = {
+	.supply_name		= "audio_vd",
+	.microvolts		= 3300000,
+	.gpio			= -1,
+	.init_data		= &audio_dummy_initdata,
+};
+
+static struct platform_device audio_supply_dummy_device = {
+	.name	= "reg-fixed-voltage",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &audio_dummy_config,
+	},
+};
+
+static struct platform_device *audio_regulator_devices[] = {
+	&audio_va_device,
+	&audio_supply_dummy_device,
+};
+
+/**
+ * Regulator support via MAX8660
+ */
+
+static struct regulator_consumer_supply vcc_mmc_supply =
+	REGULATOR_SUPPLY("vmmc", "pxa2xx-mci.0");
+
+static struct regulator_init_data vcc_mmc_init_data = {
+	.constraints = {
+		.min_uV			= 3300000,
+		.max_uV			= 3300000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
+		.valid_ops_mask		= REGULATOR_CHANGE_STATUS |
+					  REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_MODE,
+	},
+	.consumer_supplies = &vcc_mmc_supply,
+	.num_consumer_supplies = 1,
+};
+
+struct max8660_subdev_data max8660_v6_subdev_data = {
+	.id		= MAX8660_V6,
+	.name		= "vmmc",
+	.platform_data	= &vcc_mmc_init_data,
+};
+
+static struct max8660_platform_data max8660_pdata = {
+	.subdevs = &max8660_v6_subdev_data,
+	.num_subdevs = 1,
+};
+
+/**
+ * I2C devices
+ */
+
+static struct i2c_board_info raumfeld_pwri2c_board_info = {
+	.type		= "max8660",
+	.addr		= 0x34,
+	.platform_data	= &max8660_pdata,
+};
+
+static struct i2c_board_info raumfeld_connector_i2c_board_info __initdata = {
+	.type	= "cs4270",
+	.addr	= 0x48,
+};
+
+static struct eeti_ts_platform_data eeti_ts_pdata = {
+	.irq_active_high = 1,
+};
+
+static struct i2c_board_info raumfeld_controller_i2c_board_info __initdata = {
+	.type	= "eeti_ts",
+	.addr	= 0x0a,
+	.irq	= gpio_to_irq(GPIO_TOUCH_IRQ),
+	.platform_data = &eeti_ts_pdata,
+};
+
+static struct platform_device *raumfeld_common_devices[] = {
+	&raumfeld_gpio_keys_device,
+	&raumfeld_led_device,
+	&raumfeld_spi_device,
+};
+
+static void __init raumfeld_audio_init(void)
+{
+	int ret;
+
+	ret = gpio_request(GPIO_CODEC_RESET, "cs4270 reset");
+	if (ret < 0)
+		pr_warning("unable to request GPIO_CODEC_RESET\n");
+	else
+		gpio_direction_output(GPIO_CODEC_RESET, 1);
+
+	ret = gpio_request(GPIO_SPDIF_RESET, "ak4104 s/pdif reset");
+	if (ret < 0)
+		pr_warning("unable to request GPIO_SPDIF_RESET\n");
+	else
+		gpio_direction_output(GPIO_SPDIF_RESET, 1);
+
+	ret = gpio_request(GPIO_MCLK_RESET, "MCLK reset");
+	if (ret < 0)
+		pr_warning("unable to request GPIO_MCLK_RESET\n");
+	else
+		gpio_direction_output(GPIO_MCLK_RESET, 1);
+
+	platform_add_devices(ARRAY_AND_SIZE(audio_regulator_devices));
+}
+
+static void __init raumfeld_common_init(void)
+{
+	int ret;
+
+	/* The on/off button polarity has changed after revision 1 */
+	if ((system_rev & 0xff) > 1) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(gpio_keys_button); i++)
+			if (!strcmp(gpio_keys_button[i].desc, "on/off button"))
+				gpio_keys_button[i].active_low = 1;
+	}
+
+	enable_irq_wake(IRQ_WAKEUP0);
+
+	pxa3xx_set_nand_info(&raumfeld_nand_info);
+	pxa3xx_set_i2c_power_info(NULL);
+	pxa_set_ohci_info(&raumfeld_ohci_info);
+	pxa_set_mci_info(&raumfeld_mci_platform_data);
+	pxa_set_i2c_info(NULL);
+	pxa_set_ffuart_info(NULL);
+
+	ret = gpio_request(GPIO_W2W_RESET, "Wi2Wi reset");
+	if (ret < 0)
+		pr_warning("Unable to request GPIO_W2W_RESET\n");
+	else
+		gpio_direction_output(GPIO_W2W_RESET, 0);
+
+	ret = gpio_request(GPIO_W2W_PDN, "Wi2Wi powerup");
+	if (ret < 0)
+		pr_warning("Unable to request GPIO_W2W_PDN\n");
+	else
+		gpio_direction_output(GPIO_W2W_PDN, 0);
+
+	/* this can be used to switch off the device */
+	ret = gpio_request(GPIO_SHUTDOWN_SUPPLY,
+				"supply shutdown");
+	if (ret < 0)
+		pr_warning("Unable to request GPIO_SHUTDOWN_SUPPLY\n");
+	else
+		gpio_direction_output(GPIO_SHUTDOWN_SUPPLY, 0);
+
+	platform_add_devices(ARRAY_AND_SIZE(raumfeld_common_devices));
+	i2c_register_board_info(1, &raumfeld_pwri2c_board_info, 1);
+}
+
+static void __init raumfeld_controller_init(void)
+{
+	int ret;
+
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(raumfeld_controller_pin_config));
+	platform_device_register(&rotary_encoder_device);
+	spi_register_board_info(ARRAY_AND_SIZE(controller_spi_devices));
+	i2c_register_board_info(0, &raumfeld_controller_i2c_board_info, 1);
+
+	ret = gpio_request(GPIO_SHUTDOWN_BATT, "battery shutdown");
+	if (ret < 0)
+		pr_warning("Unable to request GPIO_SHUTDOWN_BATT\n");
+	else
+		gpio_direction_output(GPIO_SHUTDOWN_BATT, 0);
+
+	raumfeld_common_init();
+	raumfeld_power_init();
+	raumfeld_lcd_init();
+	raumfeld_w1_init();
+}
+
+static void __init raumfeld_connector_init(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(raumfeld_connector_pin_config));
+	spi_register_board_info(ARRAY_AND_SIZE(connector_spi_devices));
+	i2c_register_board_info(0, &raumfeld_connector_i2c_board_info, 1);
+
+	platform_device_register(&smc91x_device);
+
+	raumfeld_audio_init();
+	raumfeld_common_init();
+}
+
+static void __init raumfeld_speaker_init(void)
+{
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(raumfeld_speaker_pin_config));
+	spi_register_board_info(ARRAY_AND_SIZE(speaker_spi_devices));
+	i2c_register_board_info(0, &raumfeld_connector_i2c_board_info, 1);
+
+	platform_device_register(&smc91x_device);
+	platform_device_register(&rotary_encoder_device);
+
+	raumfeld_audio_init();
+	raumfeld_common_init();
+}
+
+/* physical memory regions */
+#define	RAUMFELD_SDRAM_BASE	0xa0000000	/* SDRAM region */
+
+#ifdef CONFIG_MACH_RAUMFELD_RC
+MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
+	.phys_io	= 0x40000000,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
+	.init_machine	= raumfeld_controller_init,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa3xx_init_irq,
+	.timer		= &pxa_timer,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_RAUMFELD_CONNECTOR
+MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
+	.phys_io	= 0x40000000,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
+	.init_machine	= raumfeld_connector_init,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa3xx_init_irq,
+	.timer		= &pxa_timer,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_RAUMFELD_SPEAKER
+MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
+	.phys_io	= 0x40000000,
+	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params	= RAUMFELD_SDRAM_BASE + 0x100,
+	.init_machine	= raumfeld_speaker_init,
+	.map_io		= pxa_map_io,
+	.init_irq	= pxa3xx_init_irq,
+	.timer		= &pxa_timer,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index 67229a1..463d874 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -900,7 +900,7 @@
 };
 #endif
 
-static int __init sharpsl_pm_probe(struct platform_device *pdev)
+static int __devinit sharpsl_pm_probe(struct platform_device *pdev)
 {
 	int ret;
 
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 28352c0..19b5109 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -56,25 +56,7 @@
 	GPIO80_nCS_4,	/* SCOOP #1 */
 
 	/* LCD - 16bpp Active TFT */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* PC Card */
 	GPIO48_nPOE,
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
index 9ebe658..a81d6db 100644
--- a/arch/arm/mach-pxa/ssp.c
+++ b/arch/arm/mach-pxa/ssp.c
@@ -35,6 +35,8 @@
 #include <mach/ssp.h>
 #include <mach/regs-ssp.h>
 
+#ifdef CONFIG_PXA_SSP_LEGACY
+
 #define TIMEOUT 100000
 
 static irqreturn_t ssp_interrupt(int irq, void *dev_id)
@@ -303,6 +305,7 @@
 	clk_disable(ssp->clk);
 	ssp_free(ssp);
 }
+#endif /* CONFIG_PXA_SSP_LEGACY */
 
 static DEFINE_MUTEX(ssp_lock);
 static LIST_HEAD(ssp_list);
@@ -488,6 +491,7 @@
 arch_initcall(pxa_ssp_init);
 module_exit(pxa_ssp_exit);
 
+#ifdef CONFIG_PXA_SSP_LEGACY
 EXPORT_SYMBOL(ssp_write_word);
 EXPORT_SYMBOL(ssp_read_word);
 EXPORT_SYMBOL(ssp_flush);
@@ -498,6 +502,7 @@
 EXPORT_SYMBOL(ssp_init);
 EXPORT_SYMBOL(ssp_exit);
 EXPORT_SYMBOL(ssp_config);
+#endif
 
 MODULE_DESCRIPTION("PXA SSP driver");
 MODULE_AUTHOR("Liam Girdwood");
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 750c448..293e40a 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -76,14 +76,12 @@
 static int
 pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev)
 {
-	unsigned long flags, next, oscr;
+	unsigned long next, oscr;
 
-	raw_local_irq_save(flags);
 	OIER |= OIER_E0;
 	next = OSCR + delta;
 	OSMR0 = next;
 	oscr = OSCR;
-	raw_local_irq_restore(flags);
 
 	return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
 }
@@ -91,23 +89,17 @@
 static void
 pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 {
-	unsigned long irqflags;
-
 	switch (mode) {
 	case CLOCK_EVT_MODE_ONESHOT:
-		raw_local_irq_save(irqflags);
 		OIER &= ~OIER_E0;
 		OSSR = OSSR_M0;
-		raw_local_irq_restore(irqflags);
 		break;
 
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
 		/* initializing, released, or preparing for suspend */
-		raw_local_irq_save(irqflags);
 		OIER &= ~OIER_E0;
 		OSSR = OSSR_M0;
-		raw_local_irq_restore(irqflags);
 		break;
 
 	case CLOCK_EVT_MODE_RESUME:
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index c854c16..ad552791 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/input/matrix_keypad.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -131,24 +132,24 @@
 	GPIO45_BTUART_RTS,
 
 	/* Keybd */
-	GPIO58_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO59_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO60_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO61_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO62_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO63_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO64_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO65_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO66_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO67_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO68_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO69_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO70_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO71_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO72_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO73_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO74_GPIO | MFP_LPM_DRIVE_LOW,
-	GPIO75_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO58_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 0 */
+	GPIO59_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 1 */
+	GPIO60_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 2 */
+	GPIO61_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 3 */
+	GPIO62_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 4 */
+	GPIO63_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 5 */
+	GPIO64_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 6 */
+	GPIO65_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 7 */
+	GPIO66_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 8 */
+	GPIO67_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 9 */
+	GPIO68_GPIO | MFP_LPM_DRIVE_LOW,	/* Column 10 */
+	GPIO69_GPIO | MFP_LPM_DRIVE_LOW,	/* Row 0 */
+	GPIO70_GPIO | MFP_LPM_DRIVE_LOW,	/* Row 1 */
+	GPIO71_GPIO | MFP_LPM_DRIVE_LOW,	/* Row 2 */
+	GPIO72_GPIO | MFP_LPM_DRIVE_LOW,	/* Row 3 */
+	GPIO73_GPIO | MFP_LPM_DRIVE_LOW,	/* Row 4 */
+	GPIO74_GPIO | MFP_LPM_DRIVE_LOW,	/* Row 5 */
+	GPIO75_GPIO | MFP_LPM_DRIVE_LOW,	/* Row 6 */
 
 	/* SPI */
 	GPIO81_SSP2_CLK_OUT,
@@ -411,9 +412,87 @@
 /*
  * Tosa Keyboard
  */
+static const uint32_t tosakbd_keymap[] = {
+	KEY(0, 2, KEY_W),
+	KEY(0, 6, KEY_K),
+	KEY(0, 7, KEY_BACKSPACE),
+	KEY(0, 8, KEY_P),
+	KEY(1, 1, KEY_Q),
+	KEY(1, 2, KEY_E),
+	KEY(1, 3, KEY_T),
+	KEY(1, 4, KEY_Y),
+	KEY(1, 6, KEY_O),
+	KEY(1, 7, KEY_I),
+	KEY(1, 8, KEY_COMMA),
+	KEY(2, 1, KEY_A),
+	KEY(2, 2, KEY_D),
+	KEY(2, 3, KEY_G),
+	KEY(2, 4, KEY_U),
+	KEY(2, 6, KEY_L),
+	KEY(2, 7, KEY_ENTER),
+	KEY(2, 8, KEY_DOT),
+	KEY(3, 1, KEY_Z),
+	KEY(3, 2, KEY_C),
+	KEY(3, 3, KEY_V),
+	KEY(3, 4, KEY_J),
+	KEY(3, 5, TOSA_KEY_ADDRESSBOOK),
+	KEY(3, 6, TOSA_KEY_CANCEL),
+	KEY(3, 7, TOSA_KEY_CENTER),
+	KEY(3, 8, TOSA_KEY_OK),
+	KEY(3, 9, KEY_LEFTSHIFT),
+	KEY(4, 1, KEY_S),
+	KEY(4, 2, KEY_R),
+	KEY(4, 3, KEY_B),
+	KEY(4, 4, KEY_N),
+	KEY(4, 5, TOSA_KEY_CALENDAR),
+	KEY(4, 6, TOSA_KEY_HOMEPAGE),
+	KEY(4, 7, KEY_LEFTCTRL),
+	KEY(4, 8, TOSA_KEY_LIGHT),
+	KEY(4, 10, KEY_RIGHTSHIFT),
+	KEY(5, 1, KEY_TAB),
+	KEY(5, 2, KEY_SLASH),
+	KEY(5, 3, KEY_H),
+	KEY(5, 4, KEY_M),
+	KEY(5, 5, TOSA_KEY_MENU),
+	KEY(5, 7, KEY_UP),
+	KEY(5, 11, TOSA_KEY_FN),
+	KEY(6, 1, KEY_X),
+	KEY(6, 2, KEY_F),
+	KEY(6, 3, KEY_SPACE),
+	KEY(6, 4, KEY_APOSTROPHE),
+	KEY(6, 5, TOSA_KEY_MAIL),
+	KEY(6, 6, KEY_LEFT),
+	KEY(6, 7, KEY_DOWN),
+	KEY(6, 8, KEY_RIGHT),
+};
+
+static struct matrix_keymap_data tosakbd_keymap_data = {
+	.keymap		= tosakbd_keymap,
+	.keymap_size	= ARRAY_SIZE(tosakbd_keymap),
+};
+
+static const int tosakbd_col_gpios[] =
+			{ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68 };
+static const int tosakbd_row_gpios[] =
+			{ 69, 70, 71, 72, 73, 74, 75 };
+
+static struct matrix_keypad_platform_data tosakbd_pdata = {
+	.keymap_data		= &tosakbd_keymap_data,
+	.row_gpios		= tosakbd_row_gpios,
+	.col_gpios		= tosakbd_col_gpios,
+	.num_row_gpios		= ARRAY_SIZE(tosakbd_row_gpios),
+	.num_col_gpios		= ARRAY_SIZE(tosakbd_col_gpios),
+	.col_scan_delay_us	= 10,
+	.debounce_ms		= 10,
+	.wakeup			= 1,
+};
+
 static struct platform_device tosakbd_device = {
-	.name		= "tosa-keyboard",
+	.name		= "matrix-keypad",
 	.id		= -1,
+	.dev		= {
+		.platform_data = &tosakbd_pdata,
+	},
 };
 
 static struct gpio_keys_button tosa_gpio_keys[] = {
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 0aa858e..797f254 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -72,27 +72,14 @@
 	GPIO79_nCS_3,		/* Logic CS */
 	GPIO0_GPIO | WAKEUP_ON_EDGE_RISE,	/* Logic irq */
 
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+
 	/* LCD - 16bpp Active TFT */
-	GPIO58_LCD_LDD_0,
-	GPIO59_LCD_LDD_1,
-	GPIO60_LCD_LDD_2,
-	GPIO61_LCD_LDD_3,
-	GPIO62_LCD_LDD_4,
-	GPIO63_LCD_LDD_5,
-	GPIO64_LCD_LDD_6,
-	GPIO65_LCD_LDD_7,
-	GPIO66_LCD_LDD_8,
-	GPIO67_LCD_LDD_9,
-	GPIO68_LCD_LDD_10,
-	GPIO69_LCD_LDD_11,
-	GPIO70_LCD_LDD_12,
-	GPIO71_LCD_LDD_13,
-	GPIO72_LCD_LDD_14,
-	GPIO73_LCD_LDD_15,
-	GPIO74_LCD_FCLK,
-	GPIO75_LCD_LCLK,
-	GPIO76_LCD_PCLK,
-	GPIO77_LCD_BIAS,
+	GPIOxx_LCD_TFT_16BPP,
 
 	/* UART */
 	GPIO9_FFUART_CTS,
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 89f258c..1dd1334 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -281,7 +281,7 @@
 	do {
 		/* we're in a chained irq handler,
 		 * so ack the interrupt by hand */
-		GEDR(VIPER_CPLD_GPIO) = GPIO_bit(VIPER_CPLD_GPIO);
+		desc->chip->ack(irq);
 
 		if (likely(pending)) {
 			irq = viper_bit_to_irq(__ffs(pending));
@@ -711,6 +711,12 @@
 	GPIO80_nCS_4,
 	GPIO33_nCS_5,
 
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+
 	/* FP Backlight */
 	GPIO9_GPIO, 				/* VIPER_BCKLIGHT_EN_GPIO */
 	GPIO10_GPIO,				/* VIPER_LCD_EN_GPIO */
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index 75f2a37..39896d8 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -26,6 +26,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/apm-emulation.h>
+#include <linux/can/platform/mcp251x.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -387,11 +388,47 @@
 	.enable_dma     = 1,
 };
 
-static struct platform_device pxa2xx_spi_ssp3_device = {
-	.name = "pxa2xx-spi",
-	.id = 3,
-	.dev = {
-		.platform_data = &pxa2xx_spi_ssp3_master_info,
+/* CAN bus on SPI */
+static int zeus_mcp2515_setup(struct spi_device *sdev)
+{
+	int err;
+
+	err = gpio_request(ZEUS_CAN_SHDN_GPIO, "CAN shutdown");
+	if (err)
+		return err;
+
+	err = gpio_direction_output(ZEUS_CAN_SHDN_GPIO, 1);
+	if (err) {
+		gpio_free(ZEUS_CAN_SHDN_GPIO);
+		return err;
+	}
+
+	return 0;
+}
+
+static int zeus_mcp2515_transceiver_enable(int enable)
+{
+	gpio_set_value(ZEUS_CAN_SHDN_GPIO, !enable);
+	return 0;
+}
+
+static struct mcp251x_platform_data zeus_mcp2515_pdata = {
+	.oscillator_frequency	= 16*1000*1000,
+	.model			= CAN_MCP251X_MCP2515,
+	.board_specific_setup	= zeus_mcp2515_setup,
+	.transceiver_enable	= zeus_mcp2515_transceiver_enable,
+	.power_enable		= zeus_mcp2515_transceiver_enable,
+};
+
+static struct spi_board_info zeus_spi_board_info[] = {
+	[0] = {
+		.modalias	= "mcp251x",
+		.platform_data	= &zeus_mcp2515_pdata,
+		.irq		= gpio_to_irq(ZEUS_CAN_GPIO),
+		.max_speed_hz	= 1*1000*1000,
+		.bus_num	= 3,
+		.mode		= SPI_MODE_0,
+		.chip_select	= 0,
 	},
 };
 
@@ -457,15 +494,28 @@
 	},
 };
 
+static struct resource zeus_max6369_resource = {
+	.start		= ZEUS_CPLD_EXTWDOG_PHYS,
+	.end		= ZEUS_CPLD_EXTWDOG_PHYS,
+	.flags		= IORESOURCE_MEM,
+};
+
+struct platform_device zeus_max6369_device = {
+	.name		= "max6369_wdt",
+	.id		= -1,
+	.resource	= &zeus_max6369_resource,
+	.num_resources	= 1,
+};
+
 static struct platform_device *zeus_devices[] __initdata = {
 	&zeus_serial_device,
 	&zeus_mtd_devices[0],
 	&zeus_dm9k0_device,
 	&zeus_dm9k1_device,
 	&zeus_sram_device,
-	&pxa2xx_spi_ssp3_device,
 	&zeus_leds_device,
 	&zeus_pcmcia_device,
+	&zeus_max6369_device,
 };
 
 /* AC'97 */
@@ -509,7 +559,9 @@
 
 static struct pxaohci_platform_data zeus_ohci_platform_data = {
 	.port_mode	= PMM_NPS_MODE,
-	.flags		= ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
+	/* Clear Power Control Polarity Low and set Power Sense
+	 * Polarity Low. Supply power to USB ports. */
+	.flags		= ENABLE_PORT_ALL | POWER_SENSE_LOW,
 	.init		= zeus_ohci_init,
 	.exit		= zeus_ohci_exit,
 };
@@ -621,11 +673,15 @@
 	.udc_command = zeus_udc_command,
 };
 
+#ifdef CONFIG_PM
 static void zeus_power_off(void)
 {
 	local_irq_disable();
 	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP);
 }
+#else
+#define zeus_power_off   NULL
+#endif
 
 #ifdef CONFIG_APM_EMULATION
 static void zeus_get_power_status(struct apm_power_info *info)
@@ -706,6 +762,12 @@
 };
 
 static mfp_cfg_t zeus_pin_config[] __initdata = {
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+
 	GPIO15_nCS_1,
 	GPIO78_nCS_2,
 	GPIO80_nCS_4,
@@ -731,6 +793,11 @@
 	GPIO104_CIF_DD_2,
 	GPIO105_CIF_DD_1,
 
+	GPIO81_SSP3_TXD,
+	GPIO82_SSP3_RXD,
+	GPIO83_SSP3_SFRM,
+	GPIO84_SSP3_SCLK,
+
 	GPIO48_nPOE,
 	GPIO49_nPWE,
 	GPIO50_nPIOR,
@@ -785,6 +852,8 @@
 	pxa_set_ac97_info(&zeus_ac97_info);
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(zeus_i2c_devices));
+	pxa2xx_set_spi_info(3, &pxa2xx_spi_ssp3_master_info);
+	spi_register_board_info(zeus_spi_board_info, ARRAY_SIZE(zeus_spi_board_info));
 }
 
 static struct map_desc zeus_io_desc[] __initdata = {
@@ -807,12 +876,6 @@
 		.type    = MT_DEVICE,
 	},
 	{
-		.virtual = ZEUS_CPLD_EXTWDOG,
-		.pfn     = __phys_to_pfn(ZEUS_CPLD_EXTWDOG_PHYS),
-		.length  = 0x1000,
-		.type    = MT_DEVICE,
-	},
-	{
 		.virtual = ZEUS_PC104IO,
 		.pfn     = __phys_to_pfn(ZEUS_PC104IO_PHYS),
 		.length  = 0x00800000,
@@ -837,7 +900,7 @@
 	PCFR = PCFR_OPDE | PCFR_DC_EN | PCFR_FS | PCFR_FP;
 }
 
-MACHINE_START(ARCOM_ZEUS, "Arcom ZEUS")
+MACHINE_START(ARCOM_ZEUS, "Arcom/Eurotech ZEUS")
 	/* Maintainer: Marc Zyngier <maz@misterjones.org> */
 	.phys_io	= 0x40000000,
 	.io_pg_offst	= ((io_p2v(0x40000000) >> 18) & 0xfffc),
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 63b753f..0d8e043 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -21,7 +21,7 @@
 #include <mach/dma.h>
 
 #include <plat/cpu.h>
-#include <plat/dma-plat.h>
+#include <plat/dma-s3c24xx.h>
 
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
diff --git a/arch/arm/mach-s3c2410/h1940-bluetooth.c b/arch/arm/mach-s3c2410/h1940-bluetooth.c
index b7d1f8d..a3f3c7b 100644
--- a/arch/arm/mach-s3c2410/h1940-bluetooth.c
+++ b/arch/arm/mach-s3c2410/h1940-bluetooth.c
@@ -56,7 +56,7 @@
 	.set_block = h1940bt_set_block,
 };
 
-static int __init h1940bt_probe(struct platform_device *pdev)
+static int __devinit h1940bt_probe(struct platform_device *pdev)
 {
 	struct rfkill *rfk;
 	int ret = 0;
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-core.h b/arch/arm/mach-s3c2410/include/mach/gpio-core.h
deleted file mode 100644
index f8b879a..0000000
--- a/arch/arm/mach-s3c2410/include/mach/gpio-core.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* arch/arm/mach-s3c24100/include/mach/gpio-core.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C2410 - GPIO core support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_GPIO_CORE_H
-#define __ASM_ARCH_GPIO_CORE_H __FILE__
-
-#include <plat/gpio-core.h>
-#include <mach/regs-gpio.h>
-
-extern struct s3c_gpio_chip s3c24xx_gpios[];
-
-static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
-{
-	struct s3c_gpio_chip *chip;
-
-	if (pin > S3C2410_GPG(10))
-		return NULL;
-
-	chip = &s3c24xx_gpios[pin/32];
-	return (S3C2410_GPIO_OFFSET(pin) < chip->chip.ngpio) ? chip : NULL;
-}
-
-#endif /* __ASM_ARCH_GPIO_CORE_H */
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-track.h b/arch/arm/mach-s3c2410/include/mach/gpio-track.h
new file mode 100644
index 0000000..acb2591
--- /dev/null
+++ b/arch/arm/mach-s3c2410/include/mach/gpio-track.h
@@ -0,0 +1,33 @@
+/* arch/arm/mach-s3c24100/include/mach/gpio-core.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C2410 - GPIO core support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_GPIO_CORE_H
+#define __ASM_ARCH_GPIO_CORE_H __FILE__
+
+#include <mach/regs-gpio.h>
+
+extern struct s3c_gpio_chip s3c24xx_gpios[];
+
+static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
+{
+	struct s3c_gpio_chip *chip;
+
+	if (pin > S3C2410_GPG(10))
+		return NULL;
+
+	chip = &s3c24xx_gpios[pin/32];
+	return (S3C2410_GPIO_OFFSET(pin) < chip->chip.ngpio) ? chip : NULL;
+}
+
+#endif /* __ASM_ARCH_GPIO_CORE_H */
diff --git a/arch/arm/mach-s3c2410/include/mach/pm-core.h b/arch/arm/mach-s3c2410/include/mach/pm-core.h
new file mode 100644
index 0000000..70a83b2
--- /dev/null
+++ b/arch/arm/mach-s3c2410/include/mach/pm-core.h
@@ -0,0 +1,64 @@
+/* linux/arch/arm/mach-s3c2410/include/pm-core.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C24xx - PM core support for arch/arm/plat-s3c/pm.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+	unsigned long tmp = __raw_readl(S3C2410_CLKCON);
+
+	/* re-start uart clocks */
+	tmp |= S3C2410_CLKCON_UART0;
+	tmp |= S3C2410_CLKCON_UART1;
+	tmp |= S3C2410_CLKCON_UART2;
+
+	__raw_writel(tmp, S3C2410_CLKCON);
+	udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+	__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
+	__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
+
+	/* ack any outstanding external interrupts before we go to sleep */
+
+	__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
+	__raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
+	__raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
+
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
+}
+
+static void s3c_pm_show_resume_irqs(int start, unsigned long which,
+				    unsigned long mask);
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+	S3C_PMDBG("post sleep: IRQs 0x%08x, 0x%08x\n",
+		  __raw_readl(S3C2410_SRCPND),
+		  __raw_readl(S3C2410_EINTPEND));
+
+	s3c_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
+				s3c_irqwake_intmask);
+
+	s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
+				s3c_irqwake_eintmask);
+}
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+					   struct pm_uart_save *save)
+{
+}
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
index ebc85c6..fd672f3 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
@@ -406,31 +406,31 @@
 #define S3C2443_GPE5_SD1_CLK   (0x02 << 10)
 #define S3C2400_GPE5_EINT5     (0x02 << 10)
 #define S3C2400_GPE5_TCLK1     (0x03 << 10)
+#define S3C2443_GPE5_AC_BITCLK (0x03 << 10)
 
 #define S3C2410_GPE6_SDCMD     (0x02 << 12)
 #define S3C2443_GPE6_SD1_CMD   (0x02 << 12)
-#define S3C2443_GPE6_AC_BITCLK (0x03 << 12)
+#define S3C2443_GPE6_AC_SDI    (0x03 << 12)
 #define S3C2400_GPE6_EINT6     (0x02 << 12)
 
 #define S3C2410_GPE7_SDDAT0    (0x02 << 14)
 #define S3C2443_GPE5_SD1_DAT0  (0x02 << 14)
-#define S3C2443_GPE7_AC_SDI    (0x03 << 14)
+#define S3C2443_GPE7_AC_SDO    (0x03 << 14)
 #define S3C2400_GPE7_EINT7     (0x02 << 14)
 
 #define S3C2410_GPE8_SDDAT1    (0x02 << 16)
 #define S3C2443_GPE8_SD1_DAT1  (0x02 << 16)
-#define S3C2443_GPE8_AC_SDO    (0x03 << 16)
+#define S3C2443_GPE8_AC_SYNC   (0x03 << 16)
 #define S3C2400_GPE8_nXDACK0   (0x02 << 16)
 
 #define S3C2410_GPE9_SDDAT2    (0x02 << 18)
 #define S3C2443_GPE9_SD1_DAT2  (0x02 << 18)
-#define S3C2443_GPE9_AC_SYNC   (0x03 << 18)
+#define S3C2443_GPE9_AC_nRESET (0x03 << 18)
 #define S3C2400_GPE9_nXDACK1   (0x02 << 18)
 #define S3C2400_GPE9_nXBACK    (0x03 << 18)
 
 #define S3C2410_GPE10_SDDAT3   (0x02 << 20)
 #define S3C2443_GPE10_SD1_DAT3 (0x02 << 20)
-#define S3C2443_GPE10_AC_nRESET (0x03 << 20)
 #define S3C2400_GPE10_nXDREQ0  (0x02 << 20)
 
 #define S3C2410_GPE11_SPIMISO0 (0x02 << 22)
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
index 6026d09..d87ebe0 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h
@@ -42,23 +42,14 @@
 
 #define S3C2443_PLLCON_OFF		(1<<24)
 
-#define S3C2443_CLKSRC_I2S_EXT		(1<<14)
-#define S3C2443_CLKSRC_I2S_EPLLDIV	(0<<14)
-#define S3C2443_CLKSRC_I2S_EPLLREF	(2<<14)
-#define S3C2443_CLKSRC_I2S_EPLLREF3	(3<<14)
-#define S3C2443_CLKSRC_I2S_MASK		(3<<14)
-
 #define S3C2443_CLKSRC_EPLLREF_XTAL	(2<<7)
 #define S3C2443_CLKSRC_EPLLREF_EXTCLK	(3<<7)
 #define S3C2443_CLKSRC_EPLLREF_MPLLREF	(0<<7)
 #define S3C2443_CLKSRC_EPLLREF_MPLLREF2	(1<<7)
 #define S3C2443_CLKSRC_EPLLREF_MASK	(3<<7)
 
-#define S3C2443_CLKSRC_ESYSCLK_EPLL	(1<<6)
-#define S3C2443_CLKSRC_MSYSCLK_MPLL	(1<<4)
 #define S3C2443_CLKSRC_EXTCLK_DIV	(1<<3)
 
-#define S3C2443_CLKDIV0_DVS		(1<<13)
 #define S3C2443_CLKDIV0_HALF_HCLK	(1<<3)
 #define S3C2443_CLKDIV0_HALF_PCLK	(1<<2)
 
@@ -81,28 +72,7 @@
 #define S3C2443_CLKDIV0_ARMDIV_12	(13<<9)
 #define S3C2443_CLKDIV0_ARMDIV_16	(15<<9)
 
-/* S3C2443_CLKDIV1 */
-
-#define S3C2443_CLKDIV1_CAMDIV_MASK	(15<<26)
-#define S3C2443_CLKDIV1_CAMDIV_SHIFT	(26)
-
-#define S3C2443_CLKDIV1_HSSPIDIV_MASK	(3<<24)
-#define S3C2443_CLKDIV1_HSSPIDIV_SHIFT	(24)
-
-#define S3C2443_CLKDIV1_DISPDIV_MASK	(0xff<<16)
-#define S3C2443_CLKDIV1_DISPDIV_SHIFT	(16)
-
-#define S3C2443_CLKDIV1_I2SDIV_MASK	(15<<12)
-#define S3C2443_CLKDIV1_I2SDIV_SHIFT	(12)
-
-#define S3C2443_CLKDIV1_UARTDIV_MASK	(15<<8)
-#define S3C2443_CLKDIV1_UARTDIV_SHIFT	(8)
-
-#define S3C2443_CLKDIV1_HSMMCDIV_MASK	(3<<6)
-#define S3C2443_CLKDIV1_HSMMCDIV_SHIFT	(6)
-
-#define S3C2443_CLKDIV1_USBHOSTDIV_MASK	(3<<4)
-#define S3C2443_CLKDIV1_USBHOSTDIV_SHIFT (4)
+/* S3C2443_CLKDIV1 removed, only used in clock.c code */
 
 #define S3C2443_CLKCON_NAND
 
diff --git a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h b/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
index 980a099..dcef228 100644
--- a/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
@@ -3,7 +3,7 @@
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C2410 - SPI Controller platfrom_device info
+ * S3C2410 - SPI Controller platform_device info
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-s3c2410/include/mach/timex.h b/arch/arm/mach-s3c2410/include/mach/timex.h
new file mode 100644
index 0000000..fe9ca1f
--- /dev/null
+++ b/arch/arm/mach-s3c2410/include/mach/timex.h
@@ -0,0 +1,24 @@
+/* arch/arm/mach-s3c2410/include/mach/timex.h
+ *
+ * Copyright (c) 2003-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - time parameters
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
+
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s3c2410/include/mach/vmalloc.h b/arch/arm/mach-s3c2410/include/mach/vmalloc.h
new file mode 100644
index 0000000..315b007
--- /dev/null
+++ b/arch/arm/mach-s3c2410/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/* arch/arm/mach-s3c2410/include/mach/vmalloc.h
+ *
+ * from arch/arm/mach-iop3xx/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
+ *		      http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S3C2410 vmalloc definition
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END	  (0xE0000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index 06a84ad..7047317 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -153,7 +153,7 @@
 	&s3c_device_adc,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
-	&s3c_device_usb,
+	&s3c_device_ohci,
  	&s3c_device_rtc,
 	&s3c_device_usbgadget,
         &s3c_device_sdi,
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 97162fd..02b1b622 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -584,7 +584,7 @@
 // cat /sys/devices/platform/s3c24xx-adc/s3c-hwmon/in_0
 
 static struct platform_device *bast_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 1e34abe..fbedd07 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -196,7 +196,7 @@
 	.id               = -1,
 };
 
-static struct s3c24xx_mci_pdata h1940_mmc_cfg = {
+static struct s3c24xx_mci_pdata h1940_mmc_cfg __initdata = {
 	.gpio_detect   = S3C2410_GPF(5),
 	.gpio_wprotect = S3C2410_GPH(8),
 	.set_power     = NULL,
@@ -272,7 +272,7 @@
 
 static struct platform_device *h1940_devices[] __initdata = {
 	&s3c_device_ts,
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
@@ -311,12 +311,11 @@
 	u32 tmp;
 
 	s3c24xx_fb_set_platdata(&h1940_fb_info);
+	s3c24xx_mci_set_platdata(&h1940_mmc_cfg);
  	s3c24xx_udc_set_platdata(&h1940_udc_cfg);
 	s3c24xx_ts_set_platdata(&h1940_ts_cfg);
 	s3c_i2c0_set_platdata(NULL);
 
-	s3c_device_sdi.dev.platform_data = &h1940_mmc_cfg;
-
 	/* Turn off suspend on both USB ports, and switch the
 	 * selectable USB port to USB device mode. */
 
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 0405712..684710f 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -322,7 +322,7 @@
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
 	&s3c_device_iis,
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_usbgadget,
 	&n30_button_device,
 	&n30_blue_led,
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index f6c7261..d8c7f2e 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -92,7 +92,7 @@
 /* Standard OTOM devices */
 
 static struct platform_device *otom11_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
index ab092bc..92a4ec3 100644
--- a/arch/arm/mach-s3c2410/mach-qt2410.c
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -246,7 +246,7 @@
 /* Board devices */
 
 static struct platform_device *qt2410_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index c49126c..4522230 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -87,7 +87,7 @@
 };
 
 static struct platform_device *smdk2410_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
diff --git a/arch/arm/mach-s3c2410/mach-tct_hammer.c b/arch/arm/mach-s3c2410/mach-tct_hammer.c
index 8fdb043..929164a 100644
--- a/arch/arm/mach-s3c2410/mach-tct_hammer.c
+++ b/arch/arm/mach-s3c2410/mach-tct_hammer.c
@@ -129,7 +129,7 @@
 	&s3c_device_adc,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_rtc,
 	&s3c_device_usbgadget,
 	&s3c_device_sdi,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 0d61fb5..9051f0d 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -334,7 +334,7 @@
 /* devices for this board */
 
 static struct platform_device *vr1000_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index 6b9d0d8..29bd3d9 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -91,7 +91,7 @@
 	}
 }
 
-static struct s3c2410_hcd_info usb_simtec_info = {
+static struct s3c2410_hcd_info usb_simtec_info __initdata = {
 	.port[0]	= {
 		.flags	= S3C_HCDFLG_USED
 	},
@@ -127,6 +127,6 @@
 	gpio_direction_output(S3C2410_GPB(4), 1);
 	gpio_direction_input(S3C2410_GPG(10));
 
-	s3c_device_usb.dev.platform_data = &usb_simtec_info;
+	s3c_ohci_set_platdata(&usb_simtec_info);
 	return 0;
 }
diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c
index a037df5..0c0505b 100644
--- a/arch/arm/mach-s3c2412/clock.c
+++ b/arch/arm/mach-s3c2412/clock.c
@@ -124,7 +124,9 @@
 	.name		= "usysclk",
 	.id		= -1,
 	.parent		= &clk_xtal,
-	.set_parent	= s3c2412_setparent_usysclk,
+	.ops		= &(struct clk_ops) {
+		.set_parent	= s3c2412_setparent_usysclk,
+	},
 };
 
 static struct clk clk_mrefclk = {
@@ -199,10 +201,12 @@
 static struct clk clk_usbsrc = {
 	.name		= "usbsrc",
 	.id		= -1,
-	.get_rate	= s3c2412_getrate_usbsrc,
-	.set_rate	= s3c2412_setrate_usbsrc,
-	.round_rate	= s3c2412_roundrate_usbsrc,
-	.set_parent	= s3c2412_setparent_usbsrc,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s3c2412_getrate_usbsrc,
+		.set_rate	= s3c2412_setrate_usbsrc,
+		.round_rate	= s3c2412_roundrate_usbsrc,
+		.set_parent	= s3c2412_setparent_usbsrc,
+	},
 };
 
 static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
@@ -225,7 +229,9 @@
 static struct clk clk_msysclk = {
 	.name		= "msysclk",
 	.id		= -1,
-	.set_parent	= s3c2412_setparent_msysclk,
+	.ops		= &(struct clk_ops) {
+		.set_parent	= s3c2412_setparent_msysclk,
+	},
 };
 
 static int s3c2412_setparent_armclk(struct clk *clk, struct clk *parent)
@@ -264,7 +270,9 @@
 	.name		= "armclk",
 	.id		= -1,
 	.parent		= &clk_msysclk,
-	.set_parent	= s3c2412_setparent_armclk,
+	.ops		= &(struct clk_ops) {
+		.set_parent	= s3c2412_setparent_armclk,
+	},
 };
 
 /* these next clocks have an divider immediately after them,
@@ -337,10 +345,12 @@
 static struct clk clk_uart = {
 	.name		= "uartclk",
 	.id		= -1,
-	.get_rate	= s3c2412_getrate_uart,
-	.set_rate	= s3c2412_setrate_uart,
-	.set_parent	= s3c2412_setparent_uart,
-	.round_rate	= s3c2412_roundrate_clksrc,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s3c2412_getrate_uart,
+		.set_rate	= s3c2412_setrate_uart,
+		.set_parent	= s3c2412_setparent_uart,
+		.round_rate	= s3c2412_roundrate_clksrc,
+	},
 };
 
 static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
@@ -388,10 +398,12 @@
 static struct clk clk_i2s = {
 	.name		= "i2sclk",
 	.id		= -1,
-	.get_rate	= s3c2412_getrate_i2s,
-	.set_rate	= s3c2412_setrate_i2s,
-	.set_parent	= s3c2412_setparent_i2s,
-	.round_rate	= s3c2412_roundrate_clksrc,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s3c2412_getrate_i2s,
+		.set_rate	= s3c2412_setrate_i2s,
+		.set_parent	= s3c2412_setparent_i2s,
+		.round_rate	= s3c2412_roundrate_clksrc,
+	},
 };
 
 static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
@@ -438,10 +450,12 @@
 static struct clk clk_cam = {
 	.name		= "camif-upll",	/* same as 2440 name */
 	.id		= -1,
-	.get_rate	= s3c2412_getrate_cam,
-	.set_rate	= s3c2412_setrate_cam,
-	.set_parent	= s3c2412_setparent_cam,
-	.round_rate	= s3c2412_roundrate_clksrc,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s3c2412_getrate_cam,
+		.set_rate	= s3c2412_setrate_cam,
+		.set_parent	= s3c2412_setparent_cam,
+		.round_rate	= s3c2412_roundrate_clksrc,
+	},
 };
 
 /* standard clock definitions */
diff --git a/arch/arm/mach-s3c2412/dma.c b/arch/arm/mach-s3c2412/dma.c
index f8d16fc..e880524 100644
--- a/arch/arm/mach-s3c2412/dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -20,7 +20,7 @@
 
 #include <mach/dma.h>
 
-#include <plat/dma-plat.h>
+#include <plat/dma-s3c24xx.h>
 #include <plat/cpu.h>
 
 #include <plat/regs-serial.h>
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index c9fa3fc..14f4798 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -468,7 +468,7 @@
 /* The platform devices being used. */
 
 static struct platform_device *jive_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_rtc,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c
index 9a5e4341..0392065 100644
--- a/arch/arm/mach-s3c2412/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2412/mach-smdk2413.c
@@ -104,8 +104,7 @@
 
 
 static struct platform_device *smdk2413_devices[] __initdata = {
-	&s3c_device_usb,
-	//&s3c_device_lcd,
+	&s3c_device_ohci,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
 	&s3c_device_iis,
diff --git a/arch/arm/mach-s3c2412/mach-vstms.c b/arch/arm/mach-s3c2412/mach-vstms.c
index a6ba591..3ca9265 100644
--- a/arch/arm/mach-s3c2412/mach-vstms.c
+++ b/arch/arm/mach-s3c2412/mach-vstms.c
@@ -121,7 +121,7 @@
 };
 
 static struct platform_device *vstms_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
 	&s3c_device_iis,
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index 8087935..7f46526 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -15,14 +15,67 @@
 	help
 	  Support for S3C2440 Samsung Mobile CPU based systems.
 
+config CPU_S3C2442
+	bool
+	depends on ARCH_S3C2410
+	select CPU_ARM920T
+	select S3C2410_CLOCK
+	select S3C2410_GPIO
+	select S3C2410_PM if PM
+	select CPU_S3C244X
+	select CPU_LLSERIAL_S3C2440
+	help
+	  Support for S3C2442 Samsung Mobile CPU based systems.
+
+config CPU_S3C244X
+	bool
+	depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
+	help
+	  Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
+
+
+
+config S3C2440_CPUFREQ
+	bool "S3C2440/S3C2442 CPU Frequency scaling support"
+	depends on CPU_FREQ_S3C24XX && (CPU_S3C2440 || CPU_S3C2442)
+	select S3C2410_CPUFREQ_UTILS
+	default y
+	help
+	  CPU Frequency scaling support for S3C2440 and S3C2442 SoC CPUs.
+
+config S3C2440_XTAL_12000000
+	bool
+	help
+	  Indicate that the build needs to support 12MHz system
+	  crystal.
+
+config S3C2440_XTAL_16934400
+	bool
+	help
+	  Indicate that the build needs to support 16.9344MHz system
+	  crystal.
+
+config S3C2440_PLL_12000000
+	bool
+	depends on S3C2440_CPUFREQ && S3C2440_XTAL_12000000
+	default y if CPU_FREQ_S3C24XX_PLL
+	help
+	  PLL tables for S3C2440 or S3C2442 CPUs with 12MHz crystals.
+
+config S3C2440_PLL_16934400
+	bool
+	depends on S3C2440_CPUFREQ && S3C2440_XTAL_16934400
+	default y if CPU_FREQ_S3C24XX_PLL
+	help
+	  PLL tables for S3C2440 or S3C2442 CPUs with 16.934MHz crystals.
+
 config S3C2440_DMA
 	bool
 	depends on ARCH_S3C2410 && CPU_S3C24405B
 	help
 	  Support for S3C2440 specific DMA code5A
 
-
-menu "S3C2440 Machines"
+menu "S3C2440 and S3C2442 Machines"
 
 config MACH_ANUBIS
 	bool "Simtec Electronics ANUBIS"
@@ -37,6 +90,18 @@
 	  Say Y here if you are using the Simtec Electronics ANUBIS
 	  development system
 
+config MACH_NEO1973_GTA02
+	bool "Openmoko GTA02 / Freerunner phone"
+	select CPU_S3C2442
+	select MFD_PCF50633
+	select PCF50633_GPIO
+	select I2C
+	select POWER_SUPPLY
+	select MACH_NEO1973
+	select S3C2410_PWM
+	help
+	   Say Y here if you are using the Openmoko GTA02 / Freerunner GSM Phone
+
 config MACH_OSIRIS
 	bool "Simtec IM2440D20 (OSIRIS) module"
 	select CPU_S3C2440
@@ -94,11 +159,14 @@
 
 config SMDK2440_CPU2440
 	bool "SMDK2440 with S3C2440 CPU module"
-	depends on ARCH_S3C2440
 	default y if ARCH_S3C2440
 	select S3C2440_XTAL_16934400
 	select CPU_S3C2440
 
+config SMDK2440_CPU2442
+	bool "SMDM2440 with S3C2442 CPU module"
+	select CPU_S3C2442
+
 config MACH_AT2440EVB
 	bool "Avantech AT2440EVB development board"
 	select CPU_S3C2440
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
index 5f32245..c85ba32 100644
--- a/arch/arm/mach-s3c2440/Makefile
+++ b/arch/arm/mach-s3c2440/Makefile
@@ -10,10 +10,20 @@
 obj-				:=
 
 obj-$(CONFIG_CPU_S3C2440)	+= s3c2440.o dsc.o
+obj-$(CONFIG_CPU_S3C2442)	+= s3c2442.o
+
 obj-$(CONFIG_CPU_S3C2440)	+= irq.o
 obj-$(CONFIG_CPU_S3C2440)	+= clock.o
 obj-$(CONFIG_S3C2440_DMA)	+= dma.o
 
+obj-$(CONFIG_CPU_S3C244X)	+= s3c244x.o
+obj-$(CONFIG_CPU_S3C244X)	+= s3c244x-irq.o
+obj-$(CONFIG_CPU_S3C244X)	+= s3c244x-clock.o
+obj-$(CONFIG_S3C2440_CPUFREQ)	+= s3c2440-cpufreq.o
+
+obj-$(CONFIG_S3C2440_PLL_12000000) += s3c2440-pll-12000000.o
+obj-$(CONFIG_S3C2440_PLL_16934400) += s3c2440-pll-16934400.o
+
 # Machine support
 
 obj-$(CONFIG_MACH_ANUBIS)	+= mach-anubis.o
@@ -23,6 +33,7 @@
 obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
 obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o
 obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o
+obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o
 
 # extra machine support
 
diff --git a/arch/arm/mach-s3c2440/clock.c b/arch/arm/mach-s3c2440/clock.c
index d1c29b2..3dc2426 100644
--- a/arch/arm/mach-s3c2440/clock.c
+++ b/arch/arm/mach-s3c2440/clock.c
@@ -98,8 +98,10 @@
 static struct clk s3c2440_clk_cam_upll = {
 	.name		= "camif-upll",
 	.id		= -1,
-	.set_rate	= s3c2440_camif_upll_setrate,
-	.round_rate	= s3c2440_camif_upll_round,
+	.ops		= &(struct clk_ops) {
+		.set_rate	= s3c2440_camif_upll_setrate,
+		.round_rate	= s3c2440_camif_upll_round,
+	},
 };
 
 static struct clk s3c2440_clk_ac97 = {
diff --git a/arch/arm/mach-s3c2440/dma.c b/arch/arm/mach-s3c2440/dma.c
index e08e081..3b0529f 100644
--- a/arch/arm/mach-s3c2440/dma.c
+++ b/arch/arm/mach-s3c2440/dma.c
@@ -20,7 +20,7 @@
 #include <mach/map.h>
 #include <mach/dma.h>
 
-#include <plat/dma-plat.h>
+#include <plat/dma-s3c24xx.h>
 #include <plat/cpu.h>
 
 #include <plat/regs-serial.h>
diff --git a/arch/arm/mach-s3c2440/dsc.c b/arch/arm/mach-s3c2440/dsc.c
index 5540442..9ea66e3 100644
--- a/arch/arm/mach-s3c2440/dsc.c
+++ b/arch/arm/mach-s3c2440/dsc.c
@@ -28,7 +28,7 @@
 #include <mach/regs-dsc.h>
 
 #include <plat/cpu.h>
-#include <plat/s3c2440.h>
+#include <plat/s3c244x.h>
 
 int s3c2440_set_dsc(unsigned int pin, unsigned int value)
 {
diff --git a/arch/arm/mach-s3c2442/include/mach/gta02.h b/arch/arm/mach-s3c2440/include/mach/gta02.h
similarity index 100%
rename from arch/arm/mach-s3c2442/include/mach/gta02.h
rename to arch/arm/mach-s3c2440/include/mach/gta02.h
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index 62a4c3e..b73f78a 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -409,7 +409,7 @@
 /* Standard Anubis devices */
 
 static struct platform_device *anubis_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_wdt,
 	&s3c_device_adc,
 	&s3c_device_i2c0,
diff --git a/arch/arm/mach-s3c2440/mach-at2440evb.c b/arch/arm/mach-s3c2440/mach-at2440evb.c
index aa69290..8472579 100644
--- a/arch/arm/mach-s3c2440/mach-at2440evb.c
+++ b/arch/arm/mach-s3c2440/mach-at2440evb.c
@@ -165,7 +165,7 @@
 	},
 };
 
-static struct s3c24xx_mci_pdata at2440evb_mci_pdata = {
+static struct s3c24xx_mci_pdata at2440evb_mci_pdata __initdata = {
 	.gpio_detect	= S3C2410_GPG(10),
 };
 
@@ -203,7 +203,7 @@
 };
 
 static struct platform_device *at2440evb_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_wdt,
 	&s3c_device_adc,
 	&s3c_device_i2c0,
@@ -216,8 +216,6 @@
 
 static void __init at2440evb_map_io(void)
 {
-	s3c_device_sdi.dev.platform_data = &at2440evb_mci_pdata;
-
 	s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc));
 	s3c24xx_init_clocks(16934400);
 	s3c24xx_init_uarts(at2440evb_uartcfgs, ARRAY_SIZE(at2440evb_uartcfgs));
@@ -226,6 +224,7 @@
 static void __init at2440evb_init(void)
 {
 	s3c24xx_fb_set_platdata(&at2440evb_fb_info);
+	s3c24xx_mci_set_platdata(&at2440evb_mci_pdata);
 	s3c_nand_set_platdata(&at2440evb_nand_info);
 	s3c_i2c0_set_platdata(NULL);
 
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
new file mode 100644
index 0000000..45799c6
--- /dev/null
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -0,0 +1,647 @@
+/*
+ * linux/arch/arm/mach-s3c2442/mach-gta02.c
+ *
+ * S3C2442 Machine Support for Openmoko GTA02 / FreeRunner.
+ *
+ * Copyright (C) 2006-2009 by Openmoko, Inc.
+ * Authors: Harald Welte <laforge@openmoko.org>
+ *          Andy Green <andy@openmoko.org>
+ *          Werner Almesberger <werner@openmoko.org>
+ * 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
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/spi/spi.h>
+
+#include <linux/mmc/host.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+
+#include <linux/i2c.h>
+#include <linux/backlight.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/pcf50633/core.h>
+#include <linux/mfd/pcf50633/mbc.h>
+#include <linux/mfd/pcf50633/adc.h>
+#include <linux/mfd/pcf50633/gpio.h>
+#include <linux/mfd/pcf50633/pmic.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-gpioj.h>
+#include <mach/fb.h>
+
+#include <mach/spi.h>
+#include <mach/spi-gpio.h>
+#include <plat/usb-control.h>
+#include <mach/regs-mem.h>
+#include <mach/hardware.h>
+
+#include <mach/gta02.h>
+
+#include <plat/regs-serial.h>
+#include <plat/nand.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/udc.h>
+#include <plat/gpio-cfg.h>
+#include <plat/iic.h>
+
+static struct pcf50633 *gta02_pcf;
+
+/*
+ * This gets called every 1ms when we paniced.
+ */
+
+static long gta02_panic_blink(long count)
+{
+	long delay = 0;
+	static long last_blink;
+	static char led;
+
+	/* Fast blink: 200ms period. */
+	if (count - last_blink < 100)
+		return 0;
+
+	led ^= 1;
+	gpio_direction_output(GTA02_GPIO_AUX_LED, led);
+
+	last_blink = count;
+
+	return delay;
+}
+
+
+static struct map_desc gta02_iodesc[] __initdata = {
+	{
+		.virtual	= 0xe0000000,
+		.pfn		= __phys_to_pfn(S3C2410_CS3 + 0x01000000),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE
+	},
+};
+
+#define UCON (S3C2410_UCON_DEFAULT | S3C2443_UCON_RXERR_IRQEN)
+#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
+#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
+
+static struct s3c2410_uartcfg gta02_uartcfgs[] = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= UCON,
+		.ulcon		= ULCON,
+		.ufcon		= UFCON,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= UCON,
+		.ulcon		= ULCON,
+		.ufcon		= UFCON,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= UCON,
+		.ulcon		= ULCON,
+		.ufcon		= UFCON,
+	},
+};
+
+#ifdef CONFIG_CHARGER_PCF50633
+/*
+ * On GTA02 the 1A charger features a 48K resistor to 0V on the ID pin.
+ * We use this to recognize that we can pull 1A from the USB socket.
+ *
+ * These constants are the measured pcf50633 ADC levels with the 1A
+ * charger / 48K resistor, and with no pulldown resistor.
+ */
+
+#define ADC_NOM_CHG_DETECT_1A 6
+#define ADC_NOM_CHG_DETECT_USB 43
+
+static void
+gta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res)
+{
+	int  ma;
+
+	/* Interpret charger type */
+	if (res < ((ADC_NOM_CHG_DETECT_USB + ADC_NOM_CHG_DETECT_1A) / 2)) {
+
+		/*
+		 * Sanity - stop GPO driving out now that we have a 1A charger
+		 * GPO controls USB Host power generation on GTA02
+		 */
+		pcf50633_gpio_set(pcf, PCF50633_GPO, 0);
+
+		ma = 1000;
+	} else
+		ma = 100;
+
+	pcf50633_mbc_usb_curlim_set(pcf, ma);
+}
+
+static struct delayed_work gta02_charger_work;
+static int gta02_usb_vbus_draw;
+
+static void gta02_charger_worker(struct work_struct *work)
+{
+	if (gta02_usb_vbus_draw) {
+		pcf50633_mbc_usb_curlim_set(gta02_pcf, gta02_usb_vbus_draw);
+		return;
+	}
+
+#ifdef CONFIG_PCF50633_ADC
+	pcf50633_adc_async_read(gta02_pcf,
+				PCF50633_ADCC1_MUX_ADCIN1,
+				PCF50633_ADCC1_AVERAGE_16,
+				gta02_configure_pmu_for_charger,
+				NULL);
+#else
+	/*
+	 * If the PCF50633 ADC is disabled we fallback to a
+	 * 100mA limit for safety.
+	 */
+	pcf50633_mbc_usb_curlim_set(pcf, 100);
+#endif
+}
+
+#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000)
+
+static void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq)
+{
+	if (irq == PCF50633_IRQ_USBINS) {
+		schedule_delayed_work(&gta02_charger_work,
+				      GTA02_CHARGER_CONFIGURE_TIMEOUT);
+
+		return;
+	}
+
+	if (irq == PCF50633_IRQ_USBREM) {
+		cancel_delayed_work_sync(&gta02_charger_work);
+		gta02_usb_vbus_draw = 0;
+	}
+}
+
+static void gta02_udc_vbus_draw(unsigned int ma)
+{
+	if (!gta02_pcf)
+		return;
+
+	gta02_usb_vbus_draw = ma;
+
+	schedule_delayed_work(&gta02_charger_work,
+			      GTA02_CHARGER_CONFIGURE_TIMEOUT);
+}
+#else /* !CONFIG_CHARGER_PCF50633 */
+#define gta02_pmu_event_callback	NULL
+#define gta02_udc_vbus_draw		NULL
+#endif
+
+/*
+ * This is called when pc50633 is probed, unfortunately quite late in the
+ * day since it is an I2C bus device. Here we can belatedly define some
+ * platform devices with the advantage that we can mark the pcf50633 as the
+ * parent. This makes them get suspended and resumed with their parent
+ * the pcf50633 still around.
+ */
+
+static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf);
+
+
+static char *gta02_batteries[] = {
+	"battery",
+};
+
+struct pcf50633_platform_data gta02_pcf_pdata = {
+	.resumers = {
+		[0] =	PCF50633_INT1_USBINS |
+			PCF50633_INT1_USBREM |
+			PCF50633_INT1_ALARM,
+		[1] =	PCF50633_INT2_ONKEYF,
+		[2] =	PCF50633_INT3_ONKEY1S,
+		[3] =	PCF50633_INT4_LOWSYS |
+			PCF50633_INT4_LOWBAT |
+			PCF50633_INT4_HIGHTMP,
+	},
+
+	.batteries = gta02_batteries,
+	.num_batteries = ARRAY_SIZE(gta02_batteries),
+
+	.charger_reference_current_ma = 1000,
+
+	.reg_init_data = {
+		[PCF50633_REGULATOR_AUTO] = {
+			.constraints = {
+				.min_uV = 3300000,
+				.max_uV = 3300000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.always_on = 1,
+				.apply_uV = 1,
+				.state_mem = {
+					.enabled = 1,
+				},
+			},
+		},
+		[PCF50633_REGULATOR_DOWN1] = {
+			.constraints = {
+				.min_uV = 1300000,
+				.max_uV = 1600000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.always_on = 1,
+				.apply_uV = 1,
+			},
+		},
+		[PCF50633_REGULATOR_DOWN2] = {
+			.constraints = {
+				.min_uV = 1800000,
+				.max_uV = 1800000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+				.always_on = 1,
+				.state_mem = {
+					.enabled = 1,
+				},
+			},
+		},
+		[PCF50633_REGULATOR_HCLDO] = {
+			.constraints = {
+				.min_uV = 2000000,
+				.max_uV = 3300000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+				.always_on = 1,
+			},
+		},
+		[PCF50633_REGULATOR_LDO1] = {
+			.constraints = {
+				.min_uV = 3300000,
+				.max_uV = 3300000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+				.state_mem = {
+					.enabled = 0,
+				},
+			},
+		},
+		[PCF50633_REGULATOR_LDO2] = {
+			.constraints = {
+				.min_uV = 3300000,
+				.max_uV = 3300000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+			},
+		},
+		[PCF50633_REGULATOR_LDO3] = {
+			.constraints = {
+				.min_uV = 3000000,
+				.max_uV = 3000000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+			},
+		},
+		[PCF50633_REGULATOR_LDO4] = {
+			.constraints = {
+				.min_uV = 3200000,
+				.max_uV = 3200000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+			},
+		},
+		[PCF50633_REGULATOR_LDO5] = {
+			.constraints = {
+				.min_uV = 3000000,
+				.max_uV = 3000000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.apply_uV = 1,
+				.state_mem = {
+					.enabled = 1,
+				},
+			},
+		},
+		[PCF50633_REGULATOR_LDO6] = {
+			.constraints = {
+				.min_uV = 3000000,
+				.max_uV = 3000000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+			},
+		},
+		[PCF50633_REGULATOR_MEMLDO] = {
+			.constraints = {
+				.min_uV = 1800000,
+				.max_uV = 1800000,
+				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.state_mem = {
+					.enabled = 1,
+				},
+			},
+		},
+
+	},
+	.probe_done = gta02_pmu_attach_child_devices,
+	.mbc_event_callback = gta02_pmu_event_callback,
+};
+
+
+/* NOR Flash. */
+
+#define GTA02_FLASH_BASE	0x18000000 /* GCS3 */
+#define GTA02_FLASH_SIZE	0x200000 /* 2MBytes */
+
+static struct physmap_flash_data gta02_nor_flash_data = {
+	.width		= 2,
+};
+
+static struct resource gta02_nor_flash_resource = {
+	.start		= GTA02_FLASH_BASE,
+	.end		= GTA02_FLASH_BASE + GTA02_FLASH_SIZE - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device gta02_nor_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &gta02_nor_flash_data,
+	},
+	.resource	= &gta02_nor_flash_resource,
+	.num_resources	= 1,
+};
+
+
+struct platform_device s3c24xx_pwm_device = {
+	.name		= "s3c24xx_pwm",
+	.num_resources	= 0,
+};
+
+static struct i2c_board_info gta02_i2c_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("pcf50633", 0x73),
+		.irq = GTA02_IRQ_PCF50633,
+		.platform_data = &gta02_pcf_pdata,
+	},
+	{
+		I2C_BOARD_INFO("wm8753", 0x1a),
+	},
+};
+
+static struct s3c2410_nand_set __initdata gta02_nand_sets[] = {
+	[0] = {
+		/*
+		 * This name is also hard-coded in the boot loaders, so
+		 * changing it would would require all users to upgrade
+		 * their boot loaders, some of which are stored in a NOR
+		 * that is considered to be immutable.
+		 */
+		.name		= "neo1973-nand",
+		.nr_chips	= 1,
+		.flash_bbt	= 1,
+	},
+};
+
+/*
+ * Choose a set of timings derived from S3C@2442B MCP54
+ * data sheet (K5D2G13ACM-D075 MCP Memory).
+ */
+
+static struct s3c2410_platform_nand __initdata gta02_nand_info = {
+	.tacls		= 0,
+	.twrph0		= 25,
+	.twrph1		= 15,
+	.nr_sets	= ARRAY_SIZE(gta02_nand_sets),
+	.sets		= gta02_nand_sets,
+};
+
+
+static void gta02_udc_command(enum s3c2410_udc_cmd_e cmd)
+{
+	switch (cmd) {
+	case S3C2410_UDC_P_ENABLE:
+		pr_debug("%s S3C2410_UDC_P_ENABLE\n", __func__);
+		gpio_direction_output(GTA02_GPIO_USB_PULLUP, 1);
+		break;
+	case S3C2410_UDC_P_DISABLE:
+		pr_debug("%s S3C2410_UDC_P_DISABLE\n", __func__);
+		gpio_direction_output(GTA02_GPIO_USB_PULLUP, 0);
+		break;
+	case S3C2410_UDC_P_RESET:
+		pr_debug("%s S3C2410_UDC_P_RESET\n", __func__);
+		/* FIXME: Do something here. */
+	}
+}
+
+/* Get PMU to set USB current limit accordingly. */
+static struct s3c2410_udc_mach_info gta02_udc_cfg = {
+	.vbus_draw	= gta02_udc_vbus_draw,
+	.udc_command	= gta02_udc_command,
+
+};
+
+
+
+static void gta02_bl_set_intensity(int intensity)
+{
+	struct pcf50633 *pcf = gta02_pcf;
+	int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
+
+	/* We map 8-bit intensity to 6-bit intensity in hardware. */
+	intensity >>= 2;
+
+	/*
+	 * This can happen during, eg, print of panic on blanked console,
+	 * but we can't service i2c without interrupts active, so abort.
+	 */
+	if (in_atomic()) {
+		printk(KERN_ERR "gta02_bl_set_intensity called while atomic\n");
+		return;
+	}
+
+	old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
+	if (intensity == old_intensity)
+		return;
+
+	/* We can't do this anywhere else. */
+	pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 5);
+
+	if (!(pcf50633_reg_read(pcf, PCF50633_REG_LEDENA) & 3))
+		old_intensity = 0;
+
+	/*
+	 * The PCF50633 cannot handle LEDOUT = 0 (datasheet p60)
+	 * if seen, you have to re-enable the LED unit.
+	 */
+	if (!intensity || !old_intensity)
+		pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0);
+
+	/* Illegal to set LEDOUT to 0. */
+	if (!intensity)
+		pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, 2);
+	else
+		pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
+					  intensity);
+
+	if (intensity)
+		pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 2);
+
+}
+
+static struct generic_bl_info gta02_bl_info = {
+	.name			= "gta02-bl",
+	.max_intensity		= 0xff,
+	.default_intensity	= 0xff,
+	.set_bl_intensity	= gta02_bl_set_intensity,
+};
+
+static struct platform_device gta02_bl_dev = {
+	.name			= "generic-bl",
+	.id			= 1,
+	.dev = {
+		.platform_data = &gta02_bl_info,
+	},
+};
+
+
+
+/* USB */
+static struct s3c2410_hcd_info gta02_usb_info __initdata = {
+	.port[0]	= {
+		.flags	= S3C_HCDFLG_USED,
+	},
+	.port[1]	= {
+		.flags	= 0,
+	},
+};
+
+
+static void __init gta02_map_io(void)
+{
+	s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
+}
+
+
+/* These are the guys that don't need to be children of PMU. */
+
+static struct platform_device *gta02_devices[] __initdata = {
+	&s3c_device_ohci,
+	&s3c_device_wdt,
+	&s3c_device_sdi,
+	&s3c_device_usbgadget,
+	&s3c_device_nand,
+	&gta02_nor_flash,
+	&s3c24xx_pwm_device,
+	&s3c_device_iis,
+	&s3c_device_i2c0,
+};
+
+/* These guys DO need to be children of PMU. */
+
+static struct platform_device *gta02_devices_pmu_children[] = {
+	&gta02_bl_dev,
+};
+
+
+/*
+ * This is called when pc50633 is probed, quite late in the day since it is an
+ * I2C bus device.  Here we can define platform devices with the advantage that
+ * we can mark the pcf50633 as the parent.  This makes them get suspended and
+ * resumed with their parent the pcf50633 still around.  All devices whose
+ * operation depends on something from pcf50633 must have this relationship
+ * made explicit like this, or suspend and resume will become an unreliable
+ * hellworld.
+ */
+
+static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf)
+{
+	int n;
+
+	/* Grab a copy of the now probed PMU pointer. */
+	gta02_pcf = pcf;
+
+	for (n = 0; n < ARRAY_SIZE(gta02_devices_pmu_children); n++)
+		gta02_devices_pmu_children[n]->dev.parent = pcf->dev;
+
+	platform_add_devices(gta02_devices_pmu_children,
+			     ARRAY_SIZE(gta02_devices_pmu_children));
+}
+
+static void gta02_poweroff(void)
+{
+	pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN, 1, 1);
+}
+
+static void __init gta02_machine_init(void)
+{
+	/* Set the panic callback to make AUX LED blink at ~5Hz. */
+	panic_blink = gta02_panic_blink;
+
+	s3c_pm_init();
+
+#ifdef CONFIG_CHARGER_PCF50633
+	INIT_DELAYED_WORK(&gta02_charger_work, gta02_charger_worker);
+#endif
+
+	s3c24xx_udc_set_platdata(&gta02_udc_cfg);
+	s3c_ohci_set_platdata(&gta02_usb_info);
+	s3c_nand_set_platdata(&gta02_nand_info);
+	s3c_i2c0_set_platdata(NULL);
+
+	i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));
+
+	platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
+	pm_power_off = gta02_poweroff;
+}
+
+
+MACHINE_START(NEO1973_GTA02, "GTA02")
+	/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+	.map_io		= gta02_map_io,
+	.init_irq	= s3c24xx_init_irq,
+	.init_machine	= gta02_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c
index 2068e90..571b176 100644
--- a/arch/arm/mach-s3c2440/mach-mini2440.c
+++ b/arch/arm/mach-s3c2440/mach-mini2440.c
@@ -506,9 +506,8 @@
 };
 
 static struct platform_device *mini2440_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_wdt,
-/*	&s3c_device_adc,*/ /* ADC doesn't like living with touchscreen ! */
 	&s3c_device_i2c0,
 	&s3c_device_rtc,
 	&s3c_device_usbgadget,
@@ -522,8 +521,6 @@
 	&s3c_device_sdi,
 	&s3c_device_iis,
 	&mini2440_audio,
-/*	&s3c_device_timer[0],*/	/* buzzer pwm, no API for it */
-	/* remaining devices are optional */
 };
 
 static void __init mini2440_map_io(void)
@@ -531,8 +528,6 @@
 	s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));
-
-	s3c_device_sdi.dev.platform_data = &mini2440_mmc_cfg;
 }
 
 /*
@@ -678,6 +673,7 @@
 	}
 
 	s3c24xx_udc_set_platdata(&mini2440_udc_cfg);
+	s3c24xx_mci_set_platdata(&mini2440_mmc_cfg);
 	s3c_nand_set_platdata(&mini2440_nand_info);
 	s3c_i2c0_set_platdata(NULL);
 
diff --git a/arch/arm/mach-s3c2440/mach-nexcoder.c b/arch/arm/mach-s3c2440/mach-nexcoder.c
index d43eded..3420415 100644
--- a/arch/arm/mach-s3c2440/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2440/mach-nexcoder.c
@@ -41,7 +41,7 @@
 #include <plat/iic.h>
 
 #include <plat/s3c2410.h>
-#include <plat/s3c2440.h>
+#include <plat/s3c244x.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -106,7 +106,7 @@
 /* Standard Nexcoder devices */
 
 static struct platform_device *nexcoder_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index a952a13a..1e836e5 100644
--- a/arch/arm/mach-s3c2440/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -176,7 +176,7 @@
 };
 
 static struct platform_device *rx3715_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c
index ec13e74..3ac3d63 100644
--- a/arch/arm/mach-s3c2440/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2440/mach-smdk2440.c
@@ -40,7 +40,7 @@
 #include <plat/iic.h>
 
 #include <plat/s3c2410.h>
-#include <plat/s3c2440.h>
+#include <plat/s3c244x.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -150,7 +150,7 @@
 };
 
 static struct platform_device *smdk2440_devices[] __initdata = {
-	&s3c_device_usb,
+	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
diff --git a/arch/arm/mach-s3c2440/s3c2440-pll-12000000.c b/arch/arm/mach-s3c2440/s3c2440-pll-12000000.c
new file mode 100644
index 0000000..f105d5e
--- /dev/null
+++ b/arch/arm/mach-s3c2440/s3c2440-pll-12000000.c
@@ -0,0 +1,97 @@
+/* arch/arm/mach-s3c2440/s3c2440-pll-12000000.c
+ *
+ * Copyright (c) 2006-2007 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	Vincent Sanders <vince@arm.linux.org.uk>
+ *
+ * S3C2440/S3C2442 CPU PLL tables (12MHz Crystal)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <plat/cpu.h>
+#include <plat/cpu-freq-core.h>
+
+static struct cpufreq_frequency_table s3c2440_plls_12[] __initdata = {
+	{ .frequency = 75000000,	.index = PLLVAL(0x75, 3, 3),  }, 	/* FVco 600.000000 */
+	{ .frequency = 80000000,	.index = PLLVAL(0x98, 4, 3),  }, 	/* FVco 640.000000 */
+	{ .frequency = 90000000,	.index = PLLVAL(0x70, 2, 3),  }, 	/* FVco 720.000000 */
+	{ .frequency = 100000000,	.index = PLLVAL(0x5c, 1, 3),  }, 	/* FVco 800.000000 */
+	{ .frequency = 110000000,	.index = PLLVAL(0x66, 1, 3),  }, 	/* FVco 880.000000 */
+	{ .frequency = 120000000,	.index = PLLVAL(0x70, 1, 3),  }, 	/* FVco 960.000000 */
+	{ .frequency = 150000000,	.index = PLLVAL(0x75, 3, 2),  }, 	/* FVco 600.000000 */
+	{ .frequency = 160000000,	.index = PLLVAL(0x98, 4, 2),  }, 	/* FVco 640.000000 */
+	{ .frequency = 170000000,	.index = PLLVAL(0x4d, 1, 2),  }, 	/* FVco 680.000000 */
+	{ .frequency = 180000000,	.index = PLLVAL(0x70, 2, 2),  }, 	/* FVco 720.000000 */
+	{ .frequency = 190000000,	.index = PLLVAL(0x57, 1, 2),  }, 	/* FVco 760.000000 */
+	{ .frequency = 200000000,	.index = PLLVAL(0x5c, 1, 2),  }, 	/* FVco 800.000000 */
+	{ .frequency = 210000000,	.index = PLLVAL(0x84, 2, 2),  }, 	/* FVco 840.000000 */
+	{ .frequency = 220000000,	.index = PLLVAL(0x66, 1, 2),  }, 	/* FVco 880.000000 */
+	{ .frequency = 230000000,	.index = PLLVAL(0x6b, 1, 2),  }, 	/* FVco 920.000000 */
+	{ .frequency = 240000000,	.index = PLLVAL(0x70, 1, 2),  }, 	/* FVco 960.000000 */
+	{ .frequency = 300000000,	.index = PLLVAL(0x75, 3, 1),  }, 	/* FVco 600.000000 */
+	{ .frequency = 310000000,	.index = PLLVAL(0x93, 4, 1),  }, 	/* FVco 620.000000 */
+	{ .frequency = 320000000,	.index = PLLVAL(0x98, 4, 1),  }, 	/* FVco 640.000000 */
+	{ .frequency = 330000000,	.index = PLLVAL(0x66, 2, 1),  }, 	/* FVco 660.000000 */
+	{ .frequency = 340000000,	.index = PLLVAL(0x4d, 1, 1),  }, 	/* FVco 680.000000 */
+	{ .frequency = 350000000,	.index = PLLVAL(0xa7, 4, 1),  }, 	/* FVco 700.000000 */
+	{ .frequency = 360000000,	.index = PLLVAL(0x70, 2, 1),  }, 	/* FVco 720.000000 */
+	{ .frequency = 370000000,	.index = PLLVAL(0xb1, 4, 1),  }, 	/* FVco 740.000000 */
+	{ .frequency = 380000000,	.index = PLLVAL(0x57, 1, 1),  }, 	/* FVco 760.000000 */
+	{ .frequency = 390000000,	.index = PLLVAL(0x7a, 2, 1),  }, 	/* FVco 780.000000 */
+	{ .frequency = 400000000,	.index = PLLVAL(0x5c, 1, 1),  }, 	/* FVco 800.000000 */
+};
+
+static int s3c2440_plls12_add(struct sys_device *dev)
+{
+	struct clk *xtal_clk;
+	unsigned long xtal;
+
+	xtal_clk = clk_get(NULL, "xtal");
+	if (IS_ERR(xtal_clk))
+		return PTR_ERR(xtal_clk);
+
+	xtal = clk_get_rate(xtal_clk);
+	clk_put(xtal_clk);
+
+	if (xtal == 12000000) {
+		printk(KERN_INFO "Using PLL table for 12MHz crystal\n");
+		return s3c_plltab_register(s3c2440_plls_12,
+					   ARRAY_SIZE(s3c2440_plls_12));
+	}
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2440_plls12_drv = {
+	.add	= s3c2440_plls12_add,
+};
+
+static int __init s3c2440_pll_12mhz(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_plls12_drv);
+
+}
+
+arch_initcall(s3c2440_pll_12mhz);
+
+static struct sysdev_driver s3c2442_plls12_drv = {
+	.add	= s3c2440_plls12_add,
+};
+
+static int __init s3c2442_pll_12mhz(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_plls12_drv);
+
+}
+
+arch_initcall(s3c2442_pll_12mhz);
diff --git a/arch/arm/mach-s3c2440/s3c2440-pll-16934400.c b/arch/arm/mach-s3c2440/s3c2440-pll-16934400.c
new file mode 100644
index 0000000..c8a8f90
--- /dev/null
+++ b/arch/arm/mach-s3c2440/s3c2440-pll-16934400.c
@@ -0,0 +1,127 @@
+/* arch/arm/mach-s3c2440/s3c2440-pll-16934400.c
+ *
+ * Copyright (c) 2006-2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	Vincent Sanders <vince@arm.linux.org.uk>
+ *
+ * S3C2440/S3C2442 CPU PLL tables (16.93444MHz Crystal)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <plat/cpu.h>
+#include <plat/cpu-freq-core.h>
+
+static struct cpufreq_frequency_table s3c2440_plls_169344[] __initdata = {
+	{ .frequency = 78019200,	.index = PLLVAL(121, 5, 3), 	}, 	/* FVco 624.153600 */
+	{ .frequency = 84067200,	.index = PLLVAL(131, 5, 3), 	}, 	/* FVco 672.537600 */
+	{ .frequency = 90115200,	.index = PLLVAL(141, 5, 3), 	}, 	/* FVco 720.921600 */
+	{ .frequency = 96163200,	.index = PLLVAL(151, 5, 3), 	}, 	/* FVco 769.305600 */
+	{ .frequency = 102135600,	.index = PLLVAL(185, 6, 3), 	}, 	/* FVco 817.084800 */
+	{ .frequency = 108259200,	.index = PLLVAL(171, 5, 3), 	}, 	/* FVco 866.073600 */
+	{ .frequency = 114307200,	.index = PLLVAL(127, 3, 3), 	}, 	/* FVco 914.457600 */
+	{ .frequency = 120234240,	.index = PLLVAL(134, 3, 3), 	}, 	/* FVco 961.873920 */
+	{ .frequency = 126161280,	.index = PLLVAL(141, 3, 3), 	}, 	/* FVco 1009.290240 */
+	{ .frequency = 132088320,	.index = PLLVAL(148, 3, 3), 	}, 	/* FVco 1056.706560 */
+	{ .frequency = 138015360,	.index = PLLVAL(155, 3, 3), 	}, 	/* FVco 1104.122880 */
+	{ .frequency = 144789120,	.index = PLLVAL(163, 3, 3), 	}, 	/* FVco 1158.312960 */
+	{ .frequency = 150100363,	.index = PLLVAL(187, 9, 2), 	}, 	/* FVco 600.401454 */
+	{ .frequency = 156038400,	.index = PLLVAL(121, 5, 2), 	}, 	/* FVco 624.153600 */
+	{ .frequency = 162086400,	.index = PLLVAL(126, 5, 2), 	}, 	/* FVco 648.345600 */
+	{ .frequency = 168134400,	.index = PLLVAL(131, 5, 2), 	}, 	/* FVco 672.537600 */
+	{ .frequency = 174048000,	.index = PLLVAL(177, 7, 2), 	}, 	/* FVco 696.192000 */
+	{ .frequency = 180230400,	.index = PLLVAL(141, 5, 2), 	}, 	/* FVco 720.921600 */
+	{ .frequency = 186278400,	.index = PLLVAL(124, 4, 2), 	}, 	/* FVco 745.113600 */
+	{ .frequency = 192326400,	.index = PLLVAL(151, 5, 2), 	}, 	/* FVco 769.305600 */
+	{ .frequency = 198132480,	.index = PLLVAL(109, 3, 2), 	}, 	/* FVco 792.529920 */
+	{ .frequency = 204271200,	.index = PLLVAL(185, 6, 2), 	}, 	/* FVco 817.084800 */
+	{ .frequency = 210268800,	.index = PLLVAL(141, 4, 2), 	}, 	/* FVco 841.075200 */
+	{ .frequency = 216518400,	.index = PLLVAL(171, 5, 2), 	}, 	/* FVco 866.073600 */
+	{ .frequency = 222264000,	.index = PLLVAL(97, 2, 2), 	}, 	/* FVco 889.056000 */
+	{ .frequency = 228614400,	.index = PLLVAL(127, 3, 2), 	}, 	/* FVco 914.457600 */
+	{ .frequency = 234259200,	.index = PLLVAL(158, 4, 2), 	}, 	/* FVco 937.036800 */
+	{ .frequency = 240468480,	.index = PLLVAL(134, 3, 2), 	}, 	/* FVco 961.873920 */
+	{ .frequency = 246960000,	.index = PLLVAL(167, 4, 2), 	}, 	/* FVco 987.840000 */
+	{ .frequency = 252322560,	.index = PLLVAL(141, 3, 2), 	}, 	/* FVco 1009.290240 */
+	{ .frequency = 258249600,	.index = PLLVAL(114, 2, 2), 	}, 	/* FVco 1032.998400 */
+	{ .frequency = 264176640,	.index = PLLVAL(148, 3, 2), 	}, 	/* FVco 1056.706560 */
+	{ .frequency = 270950400,	.index = PLLVAL(120, 2, 2), 	}, 	/* FVco 1083.801600 */
+	{ .frequency = 276030720,	.index = PLLVAL(155, 3, 2), 	}, 	/* FVco 1104.122880 */
+	{ .frequency = 282240000,	.index = PLLVAL(92, 1, 2), 	}, 	/* FVco 1128.960000 */
+	{ .frequency = 289578240,	.index = PLLVAL(163, 3, 2), 	}, 	/* FVco 1158.312960 */
+	{ .frequency = 294235200,	.index = PLLVAL(131, 2, 2), 	}, 	/* FVco 1176.940800 */
+	{ .frequency = 300200727,	.index = PLLVAL(187, 9, 1), 	}, 	/* FVco 600.401454 */
+	{ .frequency = 306358690,	.index = PLLVAL(191, 9, 1), 	}, 	/* FVco 612.717380 */
+	{ .frequency = 312076800,	.index = PLLVAL(121, 5, 1), 	}, 	/* FVco 624.153600 */
+	{ .frequency = 318366720,	.index = PLLVAL(86, 3, 1), 	}, 	/* FVco 636.733440 */
+	{ .frequency = 324172800,	.index = PLLVAL(126, 5, 1), 	}, 	/* FVco 648.345600 */
+	{ .frequency = 330220800,	.index = PLLVAL(109, 4, 1), 	}, 	/* FVco 660.441600 */
+	{ .frequency = 336268800,	.index = PLLVAL(131, 5, 1), 	}, 	/* FVco 672.537600 */
+	{ .frequency = 342074880,	.index = PLLVAL(93, 3, 1), 	}, 	/* FVco 684.149760 */
+	{ .frequency = 348096000,	.index = PLLVAL(177, 7, 1), 	}, 	/* FVco 696.192000 */
+	{ .frequency = 355622400,	.index = PLLVAL(118, 4, 1), 	}, 	/* FVco 711.244800 */
+	{ .frequency = 360460800,	.index = PLLVAL(141, 5, 1), 	}, 	/* FVco 720.921600 */
+	{ .frequency = 366206400,	.index = PLLVAL(165, 6, 1), 	}, 	/* FVco 732.412800 */
+	{ .frequency = 372556800,	.index = PLLVAL(124, 4, 1), 	}, 	/* FVco 745.113600 */
+	{ .frequency = 378201600,	.index = PLLVAL(126, 4, 1), 	}, 	/* FVco 756.403200 */
+	{ .frequency = 384652800,	.index = PLLVAL(151, 5, 1), 	}, 	/* FVco 769.305600 */
+	{ .frequency = 391608000,	.index = PLLVAL(177, 6, 1), 	}, 	/* FVco 783.216000 */
+	{ .frequency = 396264960,	.index = PLLVAL(109, 3, 1), 	}, 	/* FVco 792.529920 */
+	{ .frequency = 402192000,	.index = PLLVAL(87, 2, 1), 	}, 	/* FVco 804.384000 */
+};
+
+static int s3c2440_plls169344_add(struct sys_device *dev)
+{
+	struct clk *xtal_clk;
+	unsigned long xtal;
+
+	xtal_clk = clk_get(NULL, "xtal");
+	if (IS_ERR(xtal_clk))
+		return PTR_ERR(xtal_clk);
+
+	xtal = clk_get_rate(xtal_clk);
+	clk_put(xtal_clk);
+
+	if (xtal == 169344000) {
+		printk(KERN_INFO "Using PLL table for 16.9344MHz crystal\n");
+		return s3c_plltab_register(s3c2440_plls_169344,
+					   ARRAY_SIZE(s3c2440_plls_169344));
+	}
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2440_plls169344_drv = {
+	.add	= s3c2440_plls169344_add,
+};
+
+static int __init s3c2440_pll_16934400(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass,
+				      &s3c2440_plls169344_drv);
+
+}
+
+arch_initcall(s3c2440_pll_16934400);
+
+static struct sysdev_driver s3c2442_plls169344_drv = {
+	.add	= s3c2440_plls169344_add,
+};
+
+static int __init s3c2442_pll_16934400(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass,
+				      &s3c2442_plls169344_drv);
+
+}
+
+arch_initcall(s3c2442_pll_16934400);
diff --git a/arch/arm/mach-s3c2440/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c
index ac1f7ea..2b68f7e 100644
--- a/arch/arm/mach-s3c2440/s3c2440.c
+++ b/arch/arm/mach-s3c2440/s3c2440.c
@@ -29,9 +29,9 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 
-#include <plat/s3c2440.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/s3c244x.h>
 
 static struct sys_device s3c2440_sysdev = {
 	.cls		= &s3c2440_sysclass,
diff --git a/arch/arm/mach-s3c2440/s3c2442.c b/arch/arm/mach-s3c2440/s3c2442.c
new file mode 100644
index 0000000..188ad1e
--- /dev/null
+++ b/arch/arm/mach-s3c2440/s3c2442.c
@@ -0,0 +1,165 @@
+/* linux/arch/arm/mach-s3c2442/s3c2442.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2442 core and lock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+
+#include <mach/regs-clock.h>
+
+#include <plat/clock.h>
+#include <plat/cpu.h>
+
+/* S3C2442 extended clock support */
+
+static unsigned long s3c2442_camif_upll_round(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	div = parent_rate / rate;
+
+	if (div == 3)
+		return parent_rate / 3;
+
+	/* note, we remove the +/- 1 calculations for the divisor */
+
+	div /= 2;
+
+	if (div < 1)
+		div = 1;
+	else if (div > 16)
+		div = 16;
+
+	return parent_rate / (div * 2);
+}
+
+static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
+
+	rate = s3c2442_camif_upll_round(clk, rate);
+
+	camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
+
+	if (rate == parent_rate) {
+		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
+	} else if ((parent_rate / rate) == 3) {
+		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+		camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
+	} else {
+		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
+		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+		camdivn |= (((parent_rate / rate) / 2) - 1);
+	}
+
+	__raw_writel(camdivn, S3C2440_CAMDIVN);
+
+	return 0;
+}
+
+/* Extra S3C2442 clocks */
+
+static struct clk s3c2442_clk_cam = {
+	.name		= "camif",
+	.id		= -1,
+	.enable		= s3c2410_clkcon_enable,
+	.ctrlbit	= S3C2440_CLKCON_CAMERA,
+};
+
+static struct clk s3c2442_clk_cam_upll = {
+	.name		= "camif-upll",
+	.id		= -1,
+	.ops		= &(struct clk_ops) {
+		.set_rate	= s3c2442_camif_upll_setrate,
+		.round_rate	= s3c2442_camif_upll_round,
+	},
+};
+
+static int s3c2442_clk_add(struct sys_device *sysdev)
+{
+	struct clk *clock_upll;
+	struct clk *clock_h;
+	struct clk *clock_p;
+
+	clock_p = clk_get(NULL, "pclk");
+	clock_h = clk_get(NULL, "hclk");
+	clock_upll = clk_get(NULL, "upll");
+
+	if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
+		printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
+		return -EINVAL;
+	}
+
+	s3c2442_clk_cam.parent = clock_h;
+	s3c2442_clk_cam_upll.parent = clock_upll;
+
+	s3c24xx_register_clock(&s3c2442_clk_cam);
+	s3c24xx_register_clock(&s3c2442_clk_cam_upll);
+
+	clk_disable(&s3c2442_clk_cam);
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2442_clk_driver = {
+	.add	= s3c2442_clk_add,
+};
+
+static __init int s3c2442_clk_init(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver);
+}
+
+arch_initcall(s3c2442_clk_init);
+
+
+static struct sys_device s3c2442_sysdev = {
+	.cls		= &s3c2442_sysclass,
+};
+
+int __init s3c2442_init(void)
+{
+	printk("S3C2442: Initialising architecture\n");
+
+	return sysdev_register(&s3c2442_sysdev);
+}
diff --git a/arch/arm/mach-s3c2440/s3c244x-clock.c b/arch/arm/mach-s3c2440/s3c244x-clock.c
new file mode 100644
index 0000000..f8d9613
--- /dev/null
+++ b/arch/arm/mach-s3c2440/s3c244x-clock.c
@@ -0,0 +1,138 @@
+/* linux/arch/arm/plat-s3c24xx/s3c24xx-clock.c
+ *
+ * Copyright (c) 2004-2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2440/S3C2442 Common clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+
+#include <mach/regs-clock.h>
+
+#include <plat/clock.h>
+#include <plat/cpu.h>
+
+static int s3c2440_setparent_armclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long camdivn;
+	unsigned long dvs;
+
+	if (parent == &clk_f)
+		dvs = 0;
+	else if (parent == &clk_h)
+		dvs = S3C2440_CAMDIVN_DVSEN;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	camdivn  = __raw_readl(S3C2440_CAMDIVN);
+	camdivn &= ~S3C2440_CAMDIVN_DVSEN;
+	camdivn |= dvs;
+	__raw_writel(camdivn, S3C2440_CAMDIVN);
+
+	return 0;
+}
+
+static struct clk clk_arm = {
+	.name		= "armclk",
+	.id		= -1,
+	.ops		= &(struct clk_ops) {
+		.set_parent	= s3c2440_setparent_armclk,
+	},
+};
+
+static int s3c244x_clk_add(struct sys_device *sysdev)
+{
+	unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
+	unsigned long clkdivn;
+	struct clk *clock_upll;
+	int ret;
+
+	printk("S3C244X: Clock Support, DVS %s\n",
+	       (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
+
+	clk_arm.parent = (camdivn & S3C2440_CAMDIVN_DVSEN) ? &clk_h : &clk_f;
+
+	ret = s3c24xx_register_clock(&clk_arm);
+	if (ret < 0) {
+		printk(KERN_ERR "S3C24XX: Failed to add armclk (%d)\n", ret);
+		return ret;
+	}
+
+	clock_upll = clk_get(NULL, "upll");
+	if (IS_ERR(clock_upll)) {
+		printk(KERN_ERR "S3C244X: Failed to get upll clock\n");
+		return -ENOENT;
+	}
+
+	/* check rate of UPLL, and if it is near 96MHz, then change
+	 * to using half the UPLL rate for the system */
+
+	if (clk_get_rate(clock_upll) > (94 * MHZ)) {
+		clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
+
+		spin_lock(&clocks_lock);
+
+		clkdivn = __raw_readl(S3C2410_CLKDIVN);
+		clkdivn |= S3C2440_CLKDIVN_UCLK;
+		__raw_writel(clkdivn, S3C2410_CLKDIVN);
+
+		spin_unlock(&clocks_lock);
+	}
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2440_clk_driver = {
+	.add		= s3c244x_clk_add,
+};
+
+static int s3c2440_clk_init(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
+}
+
+arch_initcall(s3c2440_clk_init);
+
+static struct sysdev_driver s3c2442_clk_driver = {
+	.add		= s3c244x_clk_add,
+};
+
+static int s3c2442_clk_init(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver);
+}
+
+arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/plat-s3c24xx/s3c244x-irq.c b/arch/arm/mach-s3c2440/s3c244x-irq.c
similarity index 100%
rename from arch/arm/plat-s3c24xx/s3c244x-irq.c
rename to arch/arm/mach-s3c2440/s3c244x-irq.c
diff --git a/arch/arm/mach-s3c2440/s3c244x.c b/arch/arm/mach-s3c2440/s3c244x.c
new file mode 100644
index 0000000..5e4a97e
--- /dev/null
+++ b/arch/arm/mach-s3c2440/s3c244x.c
@@ -0,0 +1,195 @@
+/* linux/arch/arm/plat-s3c24xx/s3c244x.c
+ *
+ * Copyright (c) 2004-2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 and S3C2442 Mobile CPU support (not S3C2443)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+
+#include <plat/cpu-freq.h>
+
+#include <mach/regs-clock.h>
+#include <plat/regs-serial.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-gpioj.h>
+#include <mach/regs-dsc.h>
+
+#include <plat/s3c2410.h>
+#include <plat/s3c244x.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/pll.h>
+
+static struct map_desc s3c244x_iodesc[] __initdata = {
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(WATCHDOG),
+};
+
+/* uart initialisation */
+
+void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
+}
+
+void __init s3c244x_map_io(void)
+{
+	/* register our io-tables */
+
+	iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));
+
+	/* rename any peripherals used differing from the s3c2410 */
+
+	s3c_device_sdi.name  = "s3c2440-sdi";
+	s3c_device_i2c0.name  = "s3c2440-i2c";
+	s3c_device_nand.name = "s3c2440-nand";
+	s3c_device_ts.name = "s3c2440-ts";
+	s3c_device_usbgadget.name = "s3c2440-usbgadget";
+}
+
+void __init_or_cpufreq s3c244x_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+	unsigned long clkdiv;
+	unsigned long camdiv;
+	unsigned long xtal;
+	unsigned long hclk, fclk, pclk;
+	int hdiv = 1;
+
+	xtal_clk = clk_get(NULL, "xtal");
+	xtal = clk_get_rate(xtal_clk);
+	clk_put(xtal_clk);
+
+	fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
+
+	clkdiv = __raw_readl(S3C2410_CLKDIVN);
+	camdiv = __raw_readl(S3C2440_CAMDIVN);
+
+	/* work out clock scalings */
+
+	switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
+	case S3C2440_CLKDIVN_HDIVN_1:
+		hdiv = 1;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_2:
+		hdiv = 2;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_4_8:
+		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_3_6:
+		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
+		break;
+	}
+
+	hclk = fclk / hdiv;
+	pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1);
+
+	/* print brief summary of clocks, etc */
+
+	printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+	s3c24xx_setup_clocks(fclk, hclk, pclk);
+}
+
+void __init s3c244x_init_clocks(int xtal)
+{
+	/* initialise the clocks here, to allow other things like the
+	 * console to use them, and to add new ones after the initialisation
+	 */
+
+	s3c24xx_register_baseclocks(xtal);
+	s3c244x_setup_clocks();
+	s3c2410_baseclk_add();
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save s3c244x_sleep[] = {
+	SAVE_ITEM(S3C2440_DSC0),
+	SAVE_ITEM(S3C2440_DSC1),
+	SAVE_ITEM(S3C2440_GPJDAT),
+	SAVE_ITEM(S3C2440_GPJCON),
+	SAVE_ITEM(S3C2440_GPJUP)
+};
+
+static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
+{
+	s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+	return 0;
+}
+
+static int s3c244x_resume(struct sys_device *dev)
+{
+	s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+	return 0;
+}
+
+#else
+#define s3c244x_suspend NULL
+#define s3c244x_resume  NULL
+#endif
+
+/* Since the S3C2442 and S3C2440 share  items, put both sysclasses here */
+
+struct sysdev_class s3c2440_sysclass = {
+	.name		= "s3c2440-core",
+	.suspend	= s3c244x_suspend,
+	.resume		= s3c244x_resume
+};
+
+struct sysdev_class s3c2442_sysclass = {
+	.name		= "s3c2442-core",
+	.suspend	= s3c244x_suspend,
+	.resume		= s3c244x_resume
+};
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2440 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+static int __init s3c2440_core_init(void)
+{
+	return sysdev_class_register(&s3c2440_sysclass);
+}
+
+core_initcall(s3c2440_core_init);
+
+static int __init s3c2442_core_init(void)
+{
+	return sysdev_class_register(&s3c2442_sysclass);
+}
+
+core_initcall(s3c2442_core_init);
diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig
deleted file mode 100644
index 8d38118..0000000
--- a/arch/arm/mach-s3c2442/Kconfig
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2007 Simtec Electronics
-#
-# Licensed under GPLv2
-
-config CPU_S3C2442
-	bool
-	depends on ARCH_S3C2410
-	select CPU_ARM920T
-	select S3C2410_CLOCK
-	select S3C2410_GPIO
-	select S3C2410_PM if PM
-	select CPU_S3C244X
-	select CPU_LLSERIAL_S3C2440
-	help
-	  Support for S3C2442 Samsung Mobile CPU based systems.
-
-
-menu "S3C2442 Machines"
-
-config SMDK2440_CPU2442
-	bool "SMDM2440 with S3C2442 CPU module"
-	depends on ARCH_S3C2440
-	select CPU_S3C2442
-
-config MACH_NEO1973_GTA02
-	bool "Openmoko GTA02 / Freerunner phone"
-	select CPU_S3C2442
-	select MFD_PCF50633
-	select PCF50633_GPIO
-	select I2C
-	select POWER_SUPPLY
-	select MACH_NEO1973
-	select S3C2410_PWM
-	help
-	   Say Y here if you are using the Openmoko GTA02 / Freerunner GSM Phone
-
-endmenu
diff --git a/arch/arm/mach-s3c2442/Makefile b/arch/arm/mach-s3c2442/Makefile
deleted file mode 100644
index 2a19113..0000000
--- a/arch/arm/mach-s3c2442/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# arch/arm/mach-s3c2442/Makefile
-#
-# Copyright 2007 Simtec Electronics
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-obj-$(CONFIG_CPU_S3C2442)	+= s3c2442.o
-obj-$(CONFIG_CPU_S3C2442)	+= clock.o
-
-obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o
-
-# Machine support
-
diff --git a/arch/arm/mach-s3c2442/clock.c b/arch/arm/mach-s3c2442/clock.c
deleted file mode 100644
index ea1aa1f..0000000
--- a/arch/arm/mach-s3c2442/clock.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* linux/arch/arm/mach-s3c2442/clock.c
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2442 Clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/mutex.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-
-#include <mach/regs-clock.h>
-
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-/* S3C2442 extended clock support */
-
-static unsigned long s3c2442_camif_upll_round(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int div;
-
-	if (rate > parent_rate)
-		return parent_rate;
-
-	div = parent_rate / rate;
-
-	if (div == 3)
-		return parent_rate / 3;
-
-	/* note, we remove the +/- 1 calculations for the divisor */
-
-	div /= 2;
-
-	if (div < 1)
-		div = 1;
-	else if (div > 16)
-		div = 16;
-
-	return parent_rate / (div * 2);
-}
-
-static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
-
-	rate = s3c2442_camif_upll_round(clk, rate);
-
-	camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
-
-	if (rate == parent_rate) {
-		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
-	} else if ((parent_rate / rate) == 3) {
-		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
-		camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
-	} else {
-		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
-		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
-		camdivn |= (((parent_rate / rate) / 2) - 1);
-	}
-
-	__raw_writel(camdivn, S3C2440_CAMDIVN);
-
-	return 0;
-}
-
-/* Extra S3C2442 clocks */
-
-static struct clk s3c2442_clk_cam = {
-	.name		= "camif",
-	.id		= -1,
-	.enable		= s3c2410_clkcon_enable,
-	.ctrlbit	= S3C2440_CLKCON_CAMERA,
-};
-
-static struct clk s3c2442_clk_cam_upll = {
-	.name		= "camif-upll",
-	.id		= -1,
-	.set_rate	= s3c2442_camif_upll_setrate,
-	.round_rate	= s3c2442_camif_upll_round,
-};
-
-static int s3c2442_clk_add(struct sys_device *sysdev)
-{
-	struct clk *clock_upll;
-	struct clk *clock_h;
-	struct clk *clock_p;
-
-	clock_p = clk_get(NULL, "pclk");
-	clock_h = clk_get(NULL, "hclk");
-	clock_upll = clk_get(NULL, "upll");
-
-	if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
-		printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
-		return -EINVAL;
-	}
-
-	s3c2442_clk_cam.parent = clock_h;
-	s3c2442_clk_cam_upll.parent = clock_upll;
-
-	s3c24xx_register_clock(&s3c2442_clk_cam);
-	s3c24xx_register_clock(&s3c2442_clk_cam_upll);
-
-	clk_disable(&s3c2442_clk_cam);
-
-	return 0;
-}
-
-static struct sysdev_driver s3c2442_clk_driver = {
-	.add	= s3c2442_clk_add,
-};
-
-static __init int s3c2442_clk_init(void)
-{
-	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver);
-}
-
-arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c
deleted file mode 100644
index 0b4a3a0..0000000
--- a/arch/arm/mach-s3c2442/mach-gta02.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/*
- * linux/arch/arm/mach-s3c2442/mach-gta02.c
- *
- * S3C2442 Machine Support for Openmoko GTA02 / FreeRunner.
- *
- * Copyright (C) 2006-2009 by Openmoko, Inc.
- * Authors: Harald Welte <laforge@openmoko.org>
- *          Andy Green <andy@openmoko.org>
- *          Werner Almesberger <werner@openmoko.org>
- * 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
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-#include <linux/serial_core.h>
-#include <linux/spi/spi.h>
-
-#include <linux/mmc/host.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/io.h>
-
-#include <linux/i2c.h>
-#include <linux/backlight.h>
-#include <linux/regulator/machine.h>
-
-#include <linux/mfd/pcf50633/core.h>
-#include <linux/mfd/pcf50633/mbc.h>
-#include <linux/mfd/pcf50633/adc.h>
-#include <linux/mfd/pcf50633/gpio.h>
-#include <linux/mfd/pcf50633/pmic.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-#include <mach/regs-gpioj.h>
-#include <mach/fb.h>
-
-#include <mach/spi.h>
-#include <mach/spi-gpio.h>
-#include <plat/usb-control.h>
-#include <mach/regs-mem.h>
-#include <mach/hardware.h>
-
-#include <mach/gta02.h>
-
-#include <plat/regs-serial.h>
-#include <plat/nand.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/udc.h>
-#include <plat/gpio-cfg.h>
-#include <plat/iic.h>
-
-static struct pcf50633 *gta02_pcf;
-
-/*
- * This gets called every 1ms when we paniced.
- */
-
-static long gta02_panic_blink(long count)
-{
-	long delay = 0;
-	static long last_blink;
-	static char led;
-
-	/* Fast blink: 200ms period. */
-	if (count - last_blink < 100)
-		return 0;
-
-	led ^= 1;
-	gpio_direction_output(GTA02_GPIO_AUX_LED, led);
-
-	last_blink = count;
-
-	return delay;
-}
-
-
-static struct map_desc gta02_iodesc[] __initdata = {
-	{
-		.virtual	= 0xe0000000,
-		.pfn		= __phys_to_pfn(S3C2410_CS3 + 0x01000000),
-		.length		= SZ_1M,
-		.type		= MT_DEVICE
-	},
-};
-
-#define UCON (S3C2410_UCON_DEFAULT | S3C2443_UCON_RXERR_IRQEN)
-#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
-#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
-
-static struct s3c2410_uartcfg gta02_uartcfgs[] = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= UCON,
-		.ulcon		= ULCON,
-		.ufcon		= UFCON,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= UCON,
-		.ulcon		= ULCON,
-		.ufcon		= UFCON,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= UCON,
-		.ulcon		= ULCON,
-		.ufcon		= UFCON,
-	},
-};
-
-#ifdef CONFIG_CHARGER_PCF50633
-/*
- * On GTA02 the 1A charger features a 48K resistor to 0V on the ID pin.
- * We use this to recognize that we can pull 1A from the USB socket.
- *
- * These constants are the measured pcf50633 ADC levels with the 1A
- * charger / 48K resistor, and with no pulldown resistor.
- */
-
-#define ADC_NOM_CHG_DETECT_1A 6
-#define ADC_NOM_CHG_DETECT_USB 43
-
-static void
-gta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res)
-{
-	int  ma;
-
-	/* Interpret charger type */
-	if (res < ((ADC_NOM_CHG_DETECT_USB + ADC_NOM_CHG_DETECT_1A) / 2)) {
-
-		/*
-		 * Sanity - stop GPO driving out now that we have a 1A charger
-		 * GPO controls USB Host power generation on GTA02
-		 */
-		pcf50633_gpio_set(pcf, PCF50633_GPO, 0);
-
-		ma = 1000;
-	} else
-		ma = 100;
-
-	pcf50633_mbc_usb_curlim_set(pcf, ma);
-}
-
-static struct delayed_work gta02_charger_work;
-static int gta02_usb_vbus_draw;
-
-static void gta02_charger_worker(struct work_struct *work)
-{
-	if (gta02_usb_vbus_draw) {
-		pcf50633_mbc_usb_curlim_set(gta02_pcf, gta02_usb_vbus_draw);
-		return;
-	}
-
-#ifdef CONFIG_PCF50633_ADC
-	pcf50633_adc_async_read(gta02_pcf,
-				PCF50633_ADCC1_MUX_ADCIN1,
-				PCF50633_ADCC1_AVERAGE_16,
-				gta02_configure_pmu_for_charger,
-				NULL);
-#else
-	/*
-	 * If the PCF50633 ADC is disabled we fallback to a
-	 * 100mA limit for safety.
-	 */
-	pcf50633_mbc_usb_curlim_set(pcf, 100);
-#endif
-}
-
-#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000)
-
-static void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq)
-{
-	if (irq == PCF50633_IRQ_USBINS) {
-		schedule_delayed_work(&gta02_charger_work,
-				      GTA02_CHARGER_CONFIGURE_TIMEOUT);
-
-		return;
-	}
-
-	if (irq == PCF50633_IRQ_USBREM) {
-		cancel_delayed_work_sync(&gta02_charger_work);
-		gta02_usb_vbus_draw = 0;
-	}
-}
-
-static void gta02_udc_vbus_draw(unsigned int ma)
-{
-	if (!gta02_pcf)
-		return;
-
-	gta02_usb_vbus_draw = ma;
-
-	schedule_delayed_work(&gta02_charger_work,
-			      GTA02_CHARGER_CONFIGURE_TIMEOUT);
-}
-#else /* !CONFIG_CHARGER_PCF50633 */
-#define gta02_pmu_event_callback	NULL
-#define gta02_udc_vbus_draw		NULL
-#endif
-
-/*
- * This is called when pc50633 is probed, unfortunately quite late in the
- * day since it is an I2C bus device. Here we can belatedly define some
- * platform devices with the advantage that we can mark the pcf50633 as the
- * parent. This makes them get suspended and resumed with their parent
- * the pcf50633 still around.
- */
-
-static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf);
-
-
-static char *gta02_batteries[] = {
-	"battery",
-};
-
-struct pcf50633_platform_data gta02_pcf_pdata = {
-	.resumers = {
-		[0] =	PCF50633_INT1_USBINS |
-			PCF50633_INT1_USBREM |
-			PCF50633_INT1_ALARM,
-		[1] =	PCF50633_INT2_ONKEYF,
-		[2] =	PCF50633_INT3_ONKEY1S,
-		[3] =	PCF50633_INT4_LOWSYS |
-			PCF50633_INT4_LOWBAT |
-			PCF50633_INT4_HIGHTMP,
-	},
-
-	.batteries = gta02_batteries,
-	.num_batteries = ARRAY_SIZE(gta02_batteries),
-
-	.charger_reference_current_ma = 1000,
-
-	.reg_init_data = {
-		[PCF50633_REGULATOR_AUTO] = {
-			.constraints = {
-				.min_uV = 3300000,
-				.max_uV = 3300000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.always_on = 1,
-				.apply_uV = 1,
-				.state_mem = {
-					.enabled = 1,
-				},
-			},
-		},
-		[PCF50633_REGULATOR_DOWN1] = {
-			.constraints = {
-				.min_uV = 1300000,
-				.max_uV = 1600000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.always_on = 1,
-				.apply_uV = 1,
-			},
-		},
-		[PCF50633_REGULATOR_DOWN2] = {
-			.constraints = {
-				.min_uV = 1800000,
-				.max_uV = 1800000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.apply_uV = 1,
-				.always_on = 1,
-				.state_mem = {
-					.enabled = 1,
-				},
-			},
-		},
-		[PCF50633_REGULATOR_HCLDO] = {
-			.constraints = {
-				.min_uV = 2000000,
-				.max_uV = 3300000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-				.always_on = 1,
-			},
-		},
-		[PCF50633_REGULATOR_LDO1] = {
-			.constraints = {
-				.min_uV = 3300000,
-				.max_uV = 3300000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.apply_uV = 1,
-				.state_mem = {
-					.enabled = 0,
-				},
-			},
-		},
-		[PCF50633_REGULATOR_LDO2] = {
-			.constraints = {
-				.min_uV = 3300000,
-				.max_uV = 3300000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.apply_uV = 1,
-			},
-		},
-		[PCF50633_REGULATOR_LDO3] = {
-			.constraints = {
-				.min_uV = 3000000,
-				.max_uV = 3000000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.apply_uV = 1,
-			},
-		},
-		[PCF50633_REGULATOR_LDO4] = {
-			.constraints = {
-				.min_uV = 3200000,
-				.max_uV = 3200000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.apply_uV = 1,
-			},
-		},
-		[PCF50633_REGULATOR_LDO5] = {
-			.constraints = {
-				.min_uV = 3000000,
-				.max_uV = 3000000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.apply_uV = 1,
-				.state_mem = {
-					.enabled = 1,
-				},
-			},
-		},
-		[PCF50633_REGULATOR_LDO6] = {
-			.constraints = {
-				.min_uV = 3000000,
-				.max_uV = 3000000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-			},
-		},
-		[PCF50633_REGULATOR_MEMLDO] = {
-			.constraints = {
-				.min_uV = 1800000,
-				.max_uV = 1800000,
-				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.state_mem = {
-					.enabled = 1,
-				},
-			},
-		},
-
-	},
-	.probe_done = gta02_pmu_attach_child_devices,
-	.mbc_event_callback = gta02_pmu_event_callback,
-};
-
-
-/* NOR Flash. */
-
-#define GTA02_FLASH_BASE	0x18000000 /* GCS3 */
-#define GTA02_FLASH_SIZE	0x200000 /* 2MBytes */
-
-static struct physmap_flash_data gta02_nor_flash_data = {
-	.width		= 2,
-};
-
-static struct resource gta02_nor_flash_resource = {
-	.start		= GTA02_FLASH_BASE,
-	.end		= GTA02_FLASH_BASE + GTA02_FLASH_SIZE - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device gta02_nor_flash = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &gta02_nor_flash_data,
-	},
-	.resource	= &gta02_nor_flash_resource,
-	.num_resources	= 1,
-};
-
-
-struct platform_device s3c24xx_pwm_device = {
-	.name		= "s3c24xx_pwm",
-	.num_resources	= 0,
-};
-
-static struct i2c_board_info gta02_i2c_devs[] __initdata = {
-	{
-		I2C_BOARD_INFO("pcf50633", 0x73),
-		.irq = GTA02_IRQ_PCF50633,
-		.platform_data = &gta02_pcf_pdata,
-	},
-	{
-		I2C_BOARD_INFO("wm8753", 0x1a),
-	},
-};
-
-static struct s3c2410_nand_set __initdata gta02_nand_sets[] = {
-	[0] = {
-		/*
-		 * This name is also hard-coded in the boot loaders, so
-		 * changing it would would require all users to upgrade
-		 * their boot loaders, some of which are stored in a NOR
-		 * that is considered to be immutable.
-		 */
-		.name		= "neo1973-nand",
-		.nr_chips	= 1,
-		.flash_bbt	= 1,
-	},
-};
-
-/*
- * Choose a set of timings derived from S3C@2442B MCP54
- * data sheet (K5D2G13ACM-D075 MCP Memory).
- */
-
-static struct s3c2410_platform_nand __initdata gta02_nand_info = {
-	.tacls		= 0,
-	.twrph0		= 25,
-	.twrph1		= 15,
-	.nr_sets	= ARRAY_SIZE(gta02_nand_sets),
-	.sets		= gta02_nand_sets,
-};
-
-
-static void gta02_udc_command(enum s3c2410_udc_cmd_e cmd)
-{
-	switch (cmd) {
-	case S3C2410_UDC_P_ENABLE:
-		pr_debug("%s S3C2410_UDC_P_ENABLE\n", __func__);
-		gpio_direction_output(GTA02_GPIO_USB_PULLUP, 1);
-		break;
-	case S3C2410_UDC_P_DISABLE:
-		pr_debug("%s S3C2410_UDC_P_DISABLE\n", __func__);
-		gpio_direction_output(GTA02_GPIO_USB_PULLUP, 0);
-		break;
-	case S3C2410_UDC_P_RESET:
-		pr_debug("%s S3C2410_UDC_P_RESET\n", __func__);
-		/* FIXME: Do something here. */
-	}
-}
-
-/* Get PMU to set USB current limit accordingly. */
-static struct s3c2410_udc_mach_info gta02_udc_cfg = {
-	.vbus_draw	= gta02_udc_vbus_draw,
-	.udc_command	= gta02_udc_command,
-
-};
-
-
-
-static void gta02_bl_set_intensity(int intensity)
-{
-	struct pcf50633 *pcf = gta02_pcf;
-	int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
-
-	/* We map 8-bit intensity to 6-bit intensity in hardware. */
-	intensity >>= 2;
-
-	/*
-	 * This can happen during, eg, print of panic on blanked console,
-	 * but we can't service i2c without interrupts active, so abort.
-	 */
-	if (in_atomic()) {
-		printk(KERN_ERR "gta02_bl_set_intensity called while atomic\n");
-		return;
-	}
-
-	old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
-	if (intensity == old_intensity)
-		return;
-
-	/* We can't do this anywhere else. */
-	pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 5);
-
-	if (!(pcf50633_reg_read(pcf, PCF50633_REG_LEDENA) & 3))
-		old_intensity = 0;
-
-	/*
-	 * The PCF50633 cannot handle LEDOUT = 0 (datasheet p60)
-	 * if seen, you have to re-enable the LED unit.
-	 */
-	if (!intensity || !old_intensity)
-		pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0);
-
-	/* Illegal to set LEDOUT to 0. */
-	if (!intensity)
-		pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, 2);
-	else
-		pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
-					  intensity);
-
-	if (intensity)
-		pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 2);
-
-}
-
-static struct generic_bl_info gta02_bl_info = {
-	.name			= "gta02-bl",
-	.max_intensity		= 0xff,
-	.default_intensity	= 0xff,
-	.set_bl_intensity	= gta02_bl_set_intensity,
-};
-
-static struct platform_device gta02_bl_dev = {
-	.name			= "generic-bl",
-	.id			= 1,
-	.dev = {
-		.platform_data = &gta02_bl_info,
-	},
-};
-
-
-
-/* USB */
-static struct s3c2410_hcd_info gta02_usb_info = {
-	.port[0]	= {
-		.flags	= S3C_HCDFLG_USED,
-	},
-	.port[1]	= {
-		.flags	= 0,
-	},
-};
-
-
-static void __init gta02_map_io(void)
-{
-	s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc));
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
-}
-
-
-/* These are the guys that don't need to be children of PMU. */
-
-static struct platform_device *gta02_devices[] __initdata = {
-	&s3c_device_usb,
-	&s3c_device_wdt,
-	&s3c_device_sdi,
-	&s3c_device_usbgadget,
-	&s3c_device_nand,
-	&gta02_nor_flash,
-	&s3c24xx_pwm_device,
-	&s3c_device_iis,
-	&s3c_device_i2c0,
-};
-
-/* These guys DO need to be children of PMU. */
-
-static struct platform_device *gta02_devices_pmu_children[] = {
-	&gta02_bl_dev,
-};
-
-
-/*
- * This is called when pc50633 is probed, quite late in the day since it is an
- * I2C bus device.  Here we can define platform devices with the advantage that
- * we can mark the pcf50633 as the parent.  This makes them get suspended and
- * resumed with their parent the pcf50633 still around.  All devices whose
- * operation depends on something from pcf50633 must have this relationship
- * made explicit like this, or suspend and resume will become an unreliable
- * hellworld.
- */
-
-static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf)
-{
-	int n;
-
-	/* Grab a copy of the now probed PMU pointer. */
-	gta02_pcf = pcf;
-
-	for (n = 0; n < ARRAY_SIZE(gta02_devices_pmu_children); n++)
-		gta02_devices_pmu_children[n]->dev.parent = pcf->dev;
-
-	platform_add_devices(gta02_devices_pmu_children,
-			     ARRAY_SIZE(gta02_devices_pmu_children));
-}
-
-static void gta02_poweroff(void)
-{
-	pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN, 1, 1);
-}
-
-static void __init gta02_machine_init(void)
-{
-	/* Set the panic callback to make AUX LED blink at ~5Hz. */
-	panic_blink = gta02_panic_blink;
-
-	s3c_pm_init();
-
-#ifdef CONFIG_CHARGER_PCF50633
-	INIT_DELAYED_WORK(&gta02_charger_work, gta02_charger_worker);
-#endif
-
-	s3c_device_usb.dev.platform_data = &gta02_usb_info;
-
-	s3c24xx_udc_set_platdata(&gta02_udc_cfg);
-	s3c_nand_set_platdata(&gta02_nand_info);
-	s3c_i2c0_set_platdata(NULL);
-
-	i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));
-
-	platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
-	pm_power_off = gta02_poweroff;
-}
-
-
-MACHINE_START(NEO1973_GTA02, "GTA02")
-	/* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
-	.phys_io	= S3C2410_PA_UART,
-	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C2410_SDRAM_PA + 0x100,
-	.map_io		= gta02_map_io,
-	.init_irq	= s3c24xx_init_irq,
-	.init_machine	= gta02_machine_init,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c2442/s3c2442.c b/arch/arm/mach-s3c2442/s3c2442.c
deleted file mode 100644
index 4663bdc..0000000
--- a/arch/arm/mach-s3c2442/s3c2442.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* linux/arch/arm/mach-s3c2442/s3c2442.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *   Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C2442 Mobile CPU support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/sysdev.h>
-
-#include <plat/s3c2442.h>
-#include <plat/cpu.h>
-
-static struct sys_device s3c2442_sysdev = {
-	.cls		= &s3c2442_sysclass,
-};
-
-int __init s3c2442_init(void)
-{
-	printk("S3C2442: Initialising architecture\n");
-
-	return sysdev_register(&s3c2442_sysdev);
-}
diff --git a/arch/arm/mach-s3c2443/Kconfig b/arch/arm/mach-s3c2443/Kconfig
index 4314c44..698140a 100644
--- a/arch/arm/mach-s3c2443/Kconfig
+++ b/arch/arm/mach-s3c2443/Kconfig
@@ -7,6 +7,7 @@
 	depends on ARCH_S3C2410
 	select S3C2443_DMA if S3C2410_DMA
 	select CPU_LLSERIAL_S3C2440
+	select SAMSUNG_CLKSRC
 	help
 	  Support for the S3C2443 SoC from the S3C24XX line
 
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
index 2785d69..62cd4ea 100644
--- a/arch/arm/mach-s3c2443/clock.c
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2443/clock.c
  *
- * Copyright (c) 2007 Simtec Electronics
+ * Copyright (c) 2007, 2010 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
  * S3C2443 Clock control support
@@ -42,6 +42,7 @@
 
 #include <plat/s3c2443.h>
 #include <plat/clock.h>
+#include <plat/clock-clksrc.h>
 #include <plat/cpu.h>
 
 /* We currently have to assume that the system is running
@@ -53,141 +54,69 @@
  * set the correct muxing at initialisation
 */
 
-static int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
+static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable)
 {
-	unsigned int clocks = clk->ctrlbit;
-	unsigned long clkcon;
-
-	clkcon = __raw_readl(S3C2443_HCLKCON);
+	u32 ctrlbit = clk->ctrlbit;
+	u32 con = __raw_readl(reg);
 
 	if (enable)
-		clkcon |= clocks;
+		con |= ctrlbit;
 	else
-		clkcon &= ~clocks;
+		con &= ~ctrlbit;
 
-	__raw_writel(clkcon, S3C2443_HCLKCON);
-
+	__raw_writel(con, reg);
 	return 0;
 }
 
+static int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
+{
+	return s3c2443_gate(S3C2443_HCLKCON, clk, enable);
+}
+
 static int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
 {
-	unsigned int clocks = clk->ctrlbit;
-	unsigned long clkcon;
-
-	clkcon = __raw_readl(S3C2443_PCLKCON);
-
-	if (enable)
-		clkcon |= clocks;
-	else
-		clkcon &= ~clocks;
-
-	__raw_writel(clkcon, S3C2443_PCLKCON);
-
-	return 0;
+	return s3c2443_gate(S3C2443_PCLKCON, clk, enable);
 }
 
 static int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
 {
-	unsigned int clocks = clk->ctrlbit;
-	unsigned long clkcon;
-
-	clkcon = __raw_readl(S3C2443_SCLKCON);
-
-	if (enable)
-		clkcon |= clocks;
-	else
-		clkcon &= ~clocks;
-
-	__raw_writel(clkcon, S3C2443_SCLKCON);
-
-	return 0;
-}
-
-static unsigned long s3c2443_roundrate_clksrc(struct clk *clk,
-					      unsigned long rate,
-					      unsigned int max)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int div;
-
-	if (rate > parent_rate)
-		return parent_rate;
-
-	/* note, we remove the +/- 1 calculations as they cancel out */
-
-	div = (rate / parent_rate);
-
-	if (div < 1)
-		div = 1;
-	else if (div > max)
-		div = max;
-
-	return parent_rate / div;
-}
-
-static unsigned long s3c2443_roundrate_clksrc4(struct clk *clk,
-					       unsigned long rate)
-{
-	return s3c2443_roundrate_clksrc(clk, rate, 4);
-}
-
-static unsigned long s3c2443_roundrate_clksrc16(struct clk *clk,
-						unsigned long rate)
-{
-	return s3c2443_roundrate_clksrc(clk, rate, 16);
-}
-
-static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk,
-						 unsigned long rate)
-{
-	return s3c2443_roundrate_clksrc(clk, rate, 256);
+	return s3c2443_gate(S3C2443_SCLKCON, clk, enable);
 }
 
 /* clock selections */
 
+/* mpllref is a direct descendant of clk_xtal by default, but it is not
+ * elided as the EPLL can be either sourced by the XTAL or EXTCLK and as
+ * such directly equating the two source clocks is impossible.
+ */
 static struct clk clk_mpllref = {
 	.name		= "mpllref",
 	.parent		= &clk_xtal,
 	.id		= -1,
 };
 
-#if 0
-static struct clk clk_mpll = {
-	.name		= "mpll",
-	.parent		= &clk_mpllref,
-	.id		= -1,
-};
-#endif
-
 static struct clk clk_i2s_ext = {
 	.name		= "i2s-ext",
 	.id		= -1,
 };
 
-static int s3c2443_setparent_epllref(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+static struct clk *clk_epllref_sources[] = {
+	[0] = &clk_mpllref,
+	[1] = &clk_mpllref,
+	[2] = &clk_xtal,
+	[3] = &clk_ext,
+};
 
-	clksrc &= ~S3C2443_CLKSRC_EPLLREF_MASK;
-
-	if (parent == &clk_xtal)
-		clksrc |= S3C2443_CLKSRC_EPLLREF_XTAL;
-	else if (parent == &clk_ext)
-		clksrc |= S3C2443_CLKSRC_EPLLREF_EXTCLK;
-	else if (parent != &clk_mpllref)
-		return -EINVAL;
-
-	__raw_writel(clksrc, S3C2443_CLKSRC);
-	clk->parent = parent;
-
-	return 0;
-}
-
-static struct clk clk_epllref = {
-	.name		= "epllref",
-	.id		= -1,
-	.set_parent	= s3c2443_setparent_epllref,
+static struct clksrc_clk clk_epllref = {
+	.clk	= {
+		.name		= "epllref",
+		.id		= -1,
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = clk_epllref_sources,
+		.nr_sources = ARRAY_SIZE(clk_epllref_sources),
+	},
+	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 },
 };
 
 static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
@@ -205,34 +134,29 @@
 	.name		= "mdivclk",
 	.parent		= &clk_mpllref,
 	.id		= -1,
-	.get_rate	= s3c2443_getrate_mdivclk,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s3c2443_getrate_mdivclk,
+	},
 };
 
-static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+static struct clk *clk_msysclk_sources[] = {
+	[0] = &clk_mpllref,
+	[1] = &clk_mpll,
+	[2] = &clk_mdivclk,
+	[3] = &clk_mpllref,
+};
 
-	clksrc &= ~(S3C2443_CLKSRC_MSYSCLK_MPLL |
-		    S3C2443_CLKSRC_EXTCLK_DIV);
-
-	if (parent == &clk_mpll)
-		clksrc |= S3C2443_CLKSRC_MSYSCLK_MPLL;
-	else if (parent == &clk_mdivclk)
-		clksrc |= S3C2443_CLKSRC_EXTCLK_DIV;
-	else if (parent != &clk_mpllref)
-		return -EINVAL;
-
-	__raw_writel(clksrc, S3C2443_CLKSRC);
-	clk->parent = parent;
-
-	return 0;
-}
-
-static struct clk clk_msysclk = {
-	.name		= "msysclk",
-	.parent		= &clk_xtal,
-	.id		= -1,
-	.set_parent	= s3c2443_setparent_msysclk,
+static struct clksrc_clk clk_msysclk = {
+	.clk	= {
+		.name		= "msysclk",
+		.parent		= &clk_xtal,
+		.id		= -1,
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = clk_msysclk_sources,
+		.nr_sources = ARRAY_SIZE(clk_msysclk_sources),
+	},
+	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 },
 };
 
 /* armdiv
@@ -241,39 +165,105 @@
  * divider values applied to it to then be fed into armclk.
 */
 
+/* armdiv divisor table */
+
+static unsigned int armdiv[16] = {
+	[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 1,
+	[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 2,
+	[S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 3,
+	[S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 4,
+	[S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 6,
+	[S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 8,
+	[S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 12,
+	[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 16,
+};
+
+static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
+{
+	clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
+
+	return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
+}
+
+static unsigned long s3c2443_armclk_roundrate(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent = clk_get_rate(clk->parent);
+	unsigned long calc;
+	unsigned best = 256; /* bigger than any value */
+	unsigned div;
+	int ptr;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
+		div = armdiv[ptr];
+		calc = parent / div;
+		if (calc <= rate && div < best)
+			best = div;
+	}
+
+	return parent / best;
+}
+
+static int s3c2443_armclk_setrate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent = clk_get_rate(clk->parent);
+	unsigned long calc;
+	unsigned div;
+	unsigned best = 256; /* bigger than any value */
+	int ptr;
+	int val = -1;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(armdiv); ptr++) {
+		div = armdiv[ptr];
+		calc = parent / div;
+		if (calc <= rate && div < best) {
+			best = div;
+			val = ptr;
+		}
+	}
+
+	if (val >= 0) {
+		unsigned long clkcon0;
+
+		clkcon0 = __raw_readl(S3C2443_CLKDIV0);
+		clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
+		clkcon0 |= val << S3C2443_CLKDIV0_ARMDIV_SHIFT;
+		__raw_writel(clkcon0, S3C2443_CLKDIV0);
+	}
+
+	return (val == -1) ? -EINVAL : 0;
+}
+
 static struct clk clk_armdiv = {
 	.name		= "armdiv",
 	.id		= -1,
-	.parent		= &clk_msysclk,
+	.parent		= &clk_msysclk.clk,
+	.ops		= &(struct clk_ops) {
+		.round_rate = s3c2443_armclk_roundrate,
+		.set_rate = s3c2443_armclk_setrate,
+	},
 };
 
 /* armclk
  *
- * this is the clock fed into the ARM core itself, either from
- * armdiv or from hclk.
+ * this is the clock fed into the ARM core itself, from armdiv or from hclk.
  */
 
-static int s3c2443_setparent_armclk(struct clk *clk, struct clk *parent)
-{
-	unsigned long clkdiv0;
+static struct clk *clk_arm_sources[] = {
+	[0] = &clk_armdiv,
+	[1] = &clk_h,
+};
 
-	clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
-
-	if (parent == &clk_armdiv)
-		clkdiv0 &= ~S3C2443_CLKDIV0_DVS;
-	else if (parent == &clk_h)
-		clkdiv0 |= S3C2443_CLKDIV0_DVS;
-	else
-		return -EINVAL;
-
-	__raw_writel(clkdiv0, S3C2443_CLKDIV0);
-	return 0;
-}
-
-static struct clk clk_arm = {
-	.name		= "armclk",
-	.id		= -1,
-	.set_parent	= s3c2443_setparent_armclk,
+static struct clksrc_clk clk_arm = {
+	.clk	= {
+		.name		= "armclk",
+		.id		= -1,
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = clk_arm_sources,
+		.nr_sources = ARRAY_SIZE(clk_arm_sources),
+	},
+	.reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 },
 };
 
 /* esysclk
@@ -281,28 +271,22 @@
  * this is sourced from either the EPLL or the EPLLref clock
 */
 
-static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+static struct clk *clk_sysclk_sources[] = {
+	[0] = &clk_epllref.clk,
+	[1] = &clk_epll,
+};
 
-	if (parent == &clk_epll)
-		clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL;
-	else if (parent == &clk_epllref)
-		clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL;
-	else
-		return -EINVAL;
-
-	__raw_writel(clksrc, S3C2443_CLKSRC);
-	clk->parent = parent;
-
-	return 0;
-}
-
-static struct clk clk_esysclk = {
-	.name		= "esysclk",
-	.parent		= &clk_epll,
-	.id		= -1,
-	.set_parent	= s3c2443_setparent_esysclk,
+static struct clksrc_clk clk_esysclk = {
+	.clk	= {
+		.name		= "esysclk",
+		.parent		= &clk_epll,
+		.id		= -1,
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = clk_sysclk_sources,
+		.nr_sources = ARRAY_SIZE(clk_sysclk_sources),
+	},
+	.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 },
 };
 
 /* uartclk
@@ -310,83 +294,30 @@
  * UART baud-rate clock sourced from esysclk via a divisor
 */
 
-static unsigned long s3c2443_getrate_uart(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
-
-	div &= S3C2443_CLKDIV1_UARTDIV_MASK;
-	div >>= S3C2443_CLKDIV1_UARTDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-
-static int s3c2443_setrate_uart(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
-
-	rate = s3c2443_roundrate_clksrc16(clk, rate);
-	rate = parent_rate / rate;
-
-	clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
-	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2443_CLKDIV1);
-	return 0;
-}
-
-static struct clk clk_uart = {
-	.name		= "uartclk",
-	.id		= -1,
-	.parent		= &clk_esysclk,
-	.get_rate	= s3c2443_getrate_uart,
-	.set_rate	= s3c2443_setrate_uart,
-	.round_rate	= s3c2443_roundrate_clksrc16,
+static struct clksrc_clk clk_uart = {
+	.clk	= {
+		.name		= "uartclk",
+		.id		= -1,
+		.parent		= &clk_esysclk.clk,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
 };
 
+
 /* hsspi
  *
  * high-speed spi clock, sourced from esysclk
 */
 
-static unsigned long s3c2443_getrate_hsspi(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
-
-	div &= S3C2443_CLKDIV1_HSSPIDIV_MASK;
-	div >>= S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-
-static int s3c2443_setrate_hsspi(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
-
-	rate = s3c2443_roundrate_clksrc4(clk, rate);
-	rate = parent_rate / rate;
-
-	clkdivn &= ~S3C2443_CLKDIV1_HSSPIDIV_MASK;
-	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2443_CLKDIV1);
-	return 0;
-}
-
-static struct clk clk_hsspi = {
-	.name		= "hsspi",
-	.id		= -1,
-	.parent		= &clk_esysclk,
-	.ctrlbit	= S3C2443_SCLKCON_HSSPICLK,
-	.enable		= s3c2443_clkcon_enable_s,
-	.get_rate	= s3c2443_getrate_hsspi,
-	.set_rate	= s3c2443_setrate_hsspi,
-	.round_rate	= s3c2443_roundrate_clksrc4,
+static struct clksrc_clk clk_hsspi = {
+	.clk	= {
+		.name		= "hsspi",
+		.id		= -1,
+		.parent		= &clk_esysclk.clk,
+		.ctrlbit	= S3C2443_SCLKCON_HSSPICLK,
+		.enable		= s3c2443_clkcon_enable_s,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
 };
 
 /* usbhost
@@ -394,41 +325,15 @@
  * usb host bus-clock, usually 48MHz to provide USB bus clock timing
 */
 
-static unsigned long s3c2443_getrate_usbhost(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
-
-	div &= S3C2443_CLKDIV1_USBHOSTDIV_MASK;
-	div >>= S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2443_setrate_usbhost(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
-
-	rate = s3c2443_roundrate_clksrc4(clk, rate);
-	rate = parent_rate / rate;
-
-	clkdivn &= ~S3C2443_CLKDIV1_USBHOSTDIV_MASK;
-	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2443_CLKDIV1);
-	return 0;
-}
-
-static struct clk clk_usb_bus_host = {
-	.name		= "usb-bus-host-parent",
-	.id		= -1,
-	.parent		= &clk_esysclk,
-	.ctrlbit	= S3C2443_SCLKCON_USBHOST,
-	.enable		= s3c2443_clkcon_enable_s,
-	.get_rate	= s3c2443_getrate_usbhost,
-	.set_rate	= s3c2443_setrate_usbhost,
-	.round_rate	= s3c2443_roundrate_clksrc4,
+static struct clksrc_clk clk_usb_bus_host = {
+	.clk	= {
+		.name		= "usb-bus-host-parent",
+		.id		= -1,
+		.parent		= &clk_esysclk.clk,
+		.ctrlbit	= S3C2443_SCLKCON_USBHOST,
+		.enable		= s3c2443_clkcon_enable_s,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 },
 };
 
 /* clk_hsmcc_div
@@ -438,39 +343,13 @@
  * be fed to the hsmmc block
 */
 
-static unsigned long s3c2443_getrate_hsmmc_div(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
-
-	div &= S3C2443_CLKDIV1_HSMMCDIV_MASK;
-	div >>= S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2443_setrate_hsmmc_div(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
-
-	rate = s3c2443_roundrate_clksrc4(clk, rate);
-	rate = parent_rate / rate;
-
-	clkdivn &= ~S3C2443_CLKDIV1_HSMMCDIV_MASK;
-	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2443_CLKDIV1);
-	return 0;
-}
-
-static struct clk clk_hsmmc_div = {
-	.name		= "hsmmc-div",
-	.id		= -1,
-	.parent		= &clk_esysclk,
-	.get_rate	= s3c2443_getrate_hsmmc_div,
-	.set_rate	= s3c2443_setrate_hsmmc_div,
-	.round_rate	= s3c2443_roundrate_clksrc4,
+static struct clksrc_clk clk_hsmmc_div = {
+	.clk	= {
+		.name		= "hsmmc-div",
+		.id		= -1,
+		.parent		= &clk_esysclk.clk,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 },
 };
 
 static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
@@ -503,82 +382,55 @@
 static struct clk clk_hsmmc = {
 	.name		= "hsmmc-if",
 	.id		= -1,
-	.parent		= &clk_hsmmc_div,
+	.parent		= &clk_hsmmc_div.clk,
 	.enable		= s3c2443_enable_hsmmc,
-	.set_parent	= s3c2443_setparent_hsmmc,
+	.ops		= &(struct clk_ops) {
+		.set_parent	= s3c2443_setparent_hsmmc,
+	},
 };
 
 /* i2s_eplldiv
  *
- * this clock is the output from the i2s divisor of esysclk
+ * This clock is the output from the I2S divisor of ESYSCLK, and is seperate
+ * from the mux that comes after it (cannot merge into one single clock)
 */
 
-static unsigned long s3c2443_getrate_i2s_eplldiv(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
-
-	div &= S3C2443_CLKDIV1_I2SDIV_MASK;
-	div >>= S3C2443_CLKDIV1_I2SDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2443_setrate_i2s_eplldiv(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
-
-	rate = s3c2443_roundrate_clksrc16(clk, rate);
-	rate = parent_rate / rate;
-
-	clkdivn &= ~S3C2443_CLKDIV1_I2SDIV_MASK;
-	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_I2SDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2443_CLKDIV1);
-	return 0;
-}
-
-static struct clk clk_i2s_eplldiv = {
-	.name		= "i2s-eplldiv",
-	.id		= -1,
-	.parent		= &clk_esysclk,
-	.get_rate	= s3c2443_getrate_i2s_eplldiv,
-	.set_rate	= s3c2443_setrate_i2s_eplldiv,
-	.round_rate	= s3c2443_roundrate_clksrc16,
+static struct clksrc_clk clk_i2s_eplldiv = {
+	.clk	= {
+		.name		= "i2s-eplldiv",
+		.id		= -1,
+		.parent		= &clk_esysclk.clk,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 12, },
 };
 
 /* i2s-ref
  *
  * i2s bus reference clock, selectable from external, esysclk or epllref
+ *
+ * Note, this used to be two clocks, but was compressed into one.
 */
 
-static int s3c2443_setparent_i2s(struct clk *clk, struct clk *parent)
-{
-	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
+struct clk *clk_i2s_srclist[] = {
+	[0] = &clk_i2s_eplldiv.clk,
+	[1] = &clk_i2s_ext,
+	[2] = &clk_epllref.clk,
+	[3] = &clk_epllref.clk,
+};
 
-	clksrc &= ~S3C2443_CLKSRC_I2S_MASK;
+static struct clksrc_clk clk_i2s = {
+	.clk	= {
+		.name		= "i2s-if",
+		.id		= -1,
+		.ctrlbit	= S3C2443_SCLKCON_I2SCLK,
+		.enable		= s3c2443_clkcon_enable_s,
 
-	if (parent == &clk_epllref)
-		clksrc |= S3C2443_CLKSRC_I2S_EPLLREF;
-	else if (parent == &clk_i2s_ext)
-		clksrc |= S3C2443_CLKSRC_I2S_EXT;
-	else if (parent != &clk_i2s_eplldiv)
-		return -EINVAL;
-
-	clk->parent = parent;
-	__raw_writel(clksrc, S3C2443_CLKSRC);
-
-	return 0;
-}
-
-static struct clk clk_i2s = {
-	.name		= "i2s-if",
-	.id		= -1,
-	.parent		= &clk_i2s_eplldiv,
-	.ctrlbit	= S3C2443_SCLKCON_I2SCLK,
-	.enable		= s3c2443_clkcon_enable_s,
-	.set_parent	= s3c2443_setparent_i2s,
+	},
+	.sources = &(struct clksrc_sources) {
+		.sources = clk_i2s_srclist,
+		.nr_sources = ARRAY_SIZE(clk_i2s_srclist),
+	},
+	.reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 },
 };
 
 /* cam-if
@@ -586,41 +438,15 @@
  * camera interface bus-clock, divided down from esysclk
 */
 
-static unsigned long s3c2443_getrate_cam(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
-
-	div  &= S3C2443_CLKDIV1_CAMDIV_MASK;
-	div >>= S3C2443_CLKDIV1_CAMDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2443_setrate_cam(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdiv1 = __raw_readl(S3C2443_CLKDIV1);
-
-	rate = s3c2443_roundrate_clksrc16(clk, rate);
-	rate = parent_rate / rate;
-
-	clkdiv1 &= ~S3C2443_CLKDIV1_CAMDIV_MASK;
-	clkdiv1 |= (rate - 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT;
-
-	__raw_writel(clkdiv1, S3C2443_CLKDIV1);
-	return 0;
-}
-
-static struct clk clk_cam = {
-	.name		= "camif-upll",		/* same as 2440 name */
-	.id		= -1,
-	.parent		= &clk_esysclk,
-	.ctrlbit	= S3C2443_SCLKCON_CAMCLK,
-	.enable		= s3c2443_clkcon_enable_s,
-	.get_rate	= s3c2443_getrate_cam,
-	.set_rate	= s3c2443_setrate_cam,
-	.round_rate	= s3c2443_roundrate_clksrc16,
+static struct clksrc_clk clk_cam = {
+	.clk	= {
+		.name		= "camif-upll",	/* same as 2440 name */
+		.id		= -1,
+		.parent		= &clk_esysclk.clk,
+		.ctrlbit	= S3C2443_SCLKCON_CAMCLK,
+		.enable		= s3c2443_clkcon_enable_s,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 },
 };
 
 /* display-if
@@ -628,41 +454,15 @@
  * display interface clock, divided from esysclk
 */
 
-static unsigned long s3c2443_getrate_display(struct clk *clk)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long div = __raw_readl(S3C2443_CLKDIV1);
-
-	div &= S3C2443_CLKDIV1_DISPDIV_MASK;
-	div >>= S3C2443_CLKDIV1_DISPDIV_SHIFT;
-
-	return parent_rate / (div + 1);
-}
-
-static int s3c2443_setrate_display(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
-
-	rate = s3c2443_roundrate_clksrc256(clk, rate);
-	rate = parent_rate / rate;
-
-	clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
-	clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
-
-	__raw_writel(clkdivn, S3C2443_CLKDIV1);
-	return 0;
-}
-
-static struct clk clk_display = {
-	.name		= "display-if",
-	.id		= -1,
-	.parent		= &clk_esysclk,
-	.ctrlbit	= S3C2443_SCLKCON_DISPCLK,
-	.enable		= s3c2443_clkcon_enable_s,
-	.get_rate	= s3c2443_getrate_display,
-	.set_rate	= s3c2443_setrate_display,
-	.round_rate	= s3c2443_roundrate_clksrc256,
+static struct clksrc_clk clk_display = {
+	.clk	= {
+		.name		= "display-if",
+		.id		= -1,
+		.parent		= &clk_esysclk.clk,
+		.ctrlbit	= S3C2443_SCLKCON_DISPCLK,
+		.enable		= s3c2443_clkcon_enable_s,
+	},
+	.reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 },
 };
 
 /* prediv
@@ -684,8 +484,10 @@
 static struct clk clk_prediv = {
 	.name		= "prediv",
 	.id		= -1,
-	.parent		= &clk_msysclk,
-	.get_rate	= s3c2443_prediv_getrate,
+	.parent		= &clk_msysclk.clk,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s3c2443_prediv_getrate,
+	},
 };
 
 /* standard clock definitions */
@@ -857,7 +659,7 @@
 	}, {
 		.name		= "usb-bus-host",
 		.id		= -1,
-		.parent		= &clk_usb_bus_host,
+		.parent		= &clk_usb_bus_host.clk,
 	}, {
 		.name		= "ac97",
 		.id		= -1,
@@ -868,103 +670,26 @@
 
 /* clocks to add where we need to check their parentage */
 
-/* s3c2443_clk_initparents
- *
- * Initialise the parents for the clocks that we get at start-time
-*/
-
-static int __init clk_init_set_parent(struct clk *clk, struct clk *parent)
-{
-	printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name);
-	return clk_set_parent(clk, parent);
-}
+static struct clksrc_clk __initdata *init_list[] = {
+	&clk_epllref, /* should be first */
+	&clk_esysclk,
+	&clk_msysclk,
+	&clk_arm,
+	&clk_i2s_eplldiv,
+	&clk_i2s,
+	&clk_cam,
+	&clk_uart,
+	&clk_display,
+	&clk_hsmmc_div,
+	&clk_usb_bus_host,
+};
 
 static void __init s3c2443_clk_initparents(void)
 {
-	unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
-	struct clk *parent;
+	int ptr;
 
-	switch (clksrc & S3C2443_CLKSRC_EPLLREF_MASK) {
-	case S3C2443_CLKSRC_EPLLREF_EXTCLK:
-		parent = &clk_ext;
-		break;
-
-	case S3C2443_CLKSRC_EPLLREF_XTAL:
-	default:
-		parent = &clk_xtal;
-		break;
-
-	case S3C2443_CLKSRC_EPLLREF_MPLLREF:
-	case S3C2443_CLKSRC_EPLLREF_MPLLREF2:
-		parent = &clk_mpllref;
-		break;
-	}
-
-	clk_init_set_parent(&clk_epllref, parent);
-
-	switch (clksrc & S3C2443_CLKSRC_I2S_MASK) {
-	case S3C2443_CLKSRC_I2S_EXT:
-		parent = &clk_i2s_ext;
-		break;
-
-	case S3C2443_CLKSRC_I2S_EPLLDIV:
-	default:
-		parent = &clk_i2s_eplldiv;
-		break;
-
-	case S3C2443_CLKSRC_I2S_EPLLREF:
-	case S3C2443_CLKSRC_I2S_EPLLREF3:
-		parent = &clk_epllref;
-	}
-
-	clk_init_set_parent(&clk_i2s, &clk_epllref);
-
-	/* esysclk source */
-
-	parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?
-		&clk_epll : &clk_epllref;
-
-	clk_init_set_parent(&clk_esysclk, parent);
-
-	/* msysclk source */
-
-	if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) {
-		parent = &clk_mpll;
-	} else {
-		parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ?
-			&clk_mdivclk : &clk_mpllref;
-	}
-
-	clk_init_set_parent(&clk_msysclk, parent);
-
-	/* arm */
-
-	if (__raw_readl(S3C2443_CLKDIV0) & S3C2443_CLKDIV0_DVS)
-		parent = &clk_h;
-	else
-		parent = &clk_armdiv;
-
-	clk_init_set_parent(&clk_arm, parent);
-}
-
-/* armdiv divisor table */
-
-static unsigned int armdiv[16] = {
-	[S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 1,
-	[S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 2,
-	[S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 3,
-	[S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 4,
-	[S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 6,
-	[S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 8,
-	[S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 12,
-	[S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]	= 16,
-};
-
-static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
-{
-	clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
-
-	return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
+	for (ptr = 0; ptr < ARRAY_SIZE(init_list); ptr++)
+		s3c_set_clksrc(init_list[ptr], true);
 }
 
 static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0)
@@ -976,15 +701,12 @@
 
 /* clocks to add straight away */
 
-static struct clk *clks[] __initdata = {
-	&clk_ext,
-	&clk_epll,
+static struct clksrc_clk *clksrcs[] __initdata = {
 	&clk_usb_bus_host,
-	&clk_usb_bus,
-	&clk_esysclk,
 	&clk_epllref,
-	&clk_mpllref,
+	&clk_esysclk,
 	&clk_msysclk,
+	&clk_arm,
 	&clk_uart,
 	&clk_display,
 	&clk_cam,
@@ -992,9 +714,15 @@
 	&clk_i2s,
 	&clk_hsspi,
 	&clk_hsmmc_div,
+};
+
+static struct clk *clks[] __initdata = {
+	&clk_ext,
+	&clk_epll,
+	&clk_usb_bus,
+	&clk_mpllref,
 	&clk_hsmmc,
 	&clk_armdiv,
-	&clk_arm,
 	&clk_prediv,
 };
 
@@ -1014,7 +742,7 @@
 	clk_put(xtal_clk);
 
 	pll = s3c2443_get_mpll(mpllcon, xtal);
-	clk_msysclk.rate = pll;
+	clk_msysclk.clk.rate = pll;
 
 	fclk = pll / s3c2443_fclk_div(clkdiv0);
 	hclk = s3c2443_prediv_getrate(&clk_prediv);
@@ -1056,15 +784,18 @@
 		}
 	}
 
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+		s3c_register_clksrc(clksrcs[ptr], 1);
+
 	clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
-	clk_epll.parent = &clk_epllref;
-	clk_usb_bus.parent = &clk_usb_bus_host;
+	clk_epll.parent = &clk_epllref.clk;
+	clk_usb_bus.parent = &clk_usb_bus_host.clk;
 
 	/* ensure usb bus clock is within correct rate of 48MHz */
 
-	if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) {
+	if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) {
 		printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
-		clk_set_rate(&clk_usb_bus_host, 48*1000*1000);
+		clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000);
 	}
 
 	printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
@@ -1074,14 +805,7 @@
 
 	/* register clocks from clock array */
 
-	clkp = init_clocks;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
+	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
 	/* We must be careful disabling the clocks we are not intending to
 	 * be using at boot time, as subsystems such as the LCD which do
diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c
index 397f3b5..3f65868 100644
--- a/arch/arm/mach-s3c2443/dma.c
+++ b/arch/arm/mach-s3c2443/dma.c
@@ -20,7 +20,7 @@
 
 #include <mach/dma.h>
 
-#include <plat/dma-plat.h>
+#include <plat/dma-s3c24xx.h>
 #include <plat/cpu.h>
 
 #include <plat/regs-serial.h>
diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c
index 039a462..e2e362b 100644
--- a/arch/arm/mach-s3c2443/mach-smdk2443.c
+++ b/arch/arm/mach-s3c2443/mach-smdk2443.c
@@ -40,7 +40,7 @@
 #include <plat/iic.h>
 
 #include <plat/s3c2410.h>
-#include <plat/s3c2440.h>
+#include <plat/s3c2443.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -106,6 +106,9 @@
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
 	&s3c_device_hsmmc0,
+#ifdef CONFIG_SND_SOC_SMDK2443_WM9710
+	&s3c_device_ac97,
+#endif
 };
 
 static void __init smdk2443_map_io(void)
@@ -118,6 +121,11 @@
 static void __init smdk2443_machine_init(void)
 {
 	s3c_i2c0_set_platdata(NULL);
+
+#ifdef CONFIG_SND_SOC_SMDK2443_WM9710
+	s3c24xx_ac97_setup_gpio(S3C24XX_AC97_GPE0);
+#endif
+
 	platform_add_devices(smdk2443_devices, ARRAY_SIZE(smdk2443_devices));
 	smdk_machine_init();
 }
diff --git a/arch/arm/mach-s3c24a0/include/mach/io.h b/arch/arm/mach-s3c24a0/include/mach/io.h
new file mode 100644
index 0000000..4326c30
--- /dev/null
+++ b/arch/arm/mach-s3c24a0/include/mach/io.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s3c24a0/include/mach/io.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben-linux@fluff.org>
+ *
+ * Default IO routines for S3C24A0
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif
diff --git a/arch/arm/mach-s3c6400/Kconfig b/arch/arm/mach-s3c6400/Kconfig
deleted file mode 100644
index a250bf6..0000000
--- a/arch/arm/mach-s3c6400/Kconfig
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2008 Openmoko, Inc.
-#	Simtec Electronics, Ben Dooks <ben@simtec.co.uk>
-#
-# Licensed under GPLv2
-
-# Configuration options for the S3C6410 CPU
-
-config CPU_S3C6400
-	bool
-	select CPU_S3C6400_INIT
-	select CPU_S3C6400_CLOCK
-	help
-	  Enable S3C6400 CPU support
-
-config S3C6400_SETUP_SDHCI
-	bool
-	help
-	  Internal configuration for default SDHCI
-	  setup for S3C6400.
-
-# S36400 Macchine support
-
-config MACH_SMDK6400
-       bool "SMDK6400"
-	select CPU_S3C6400
-	select S3C_DEV_HSMMC
-	select S3C_DEV_NAND
-	select S3C6400_SETUP_SDHCI
-	help
-	  Machine support for the Samsung SMDK6400
diff --git a/arch/arm/mach-s3c6400/Makefile b/arch/arm/mach-s3c6400/Makefile
deleted file mode 100644
index df1ce4a..0000000
--- a/arch/arm/mach-s3c6400/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-# arch/arm/mach-s3c6400/Makefile
-#
-# Copyright 2008 Openmoko, Inc.
-# Copyright 2008 Simtec Electronics
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-# Core support for S3C6400 system
-
-obj-$(CONFIG_CPU_S3C6400)	+= s3c6400.o
-
-# setup support
-
-obj-$(CONFIG_S3C6400_SETUP_SDHCI) += setup-sdhci.o
-
-# Machine support
-
-obj-$(CONFIG_MACH_SMDK6400)	+= mach-smdk6400.o
diff --git a/arch/arm/mach-s3c6400/include/mach/debug-macro.S b/arch/arm/mach-s3c6400/include/mach/debug-macro.S
deleted file mode 100644
index 5c88875..0000000
--- a/arch/arm/mach-s3c6400/include/mach/debug-macro.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/* arch/arm/mach-s3c6400/include/mach/debug-macro.S
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <mach/map.h>
-#include <plat/regs-serial.h>
-
-	/* note, for the boot process to work we have to keep the UART
-	 * virtual address aligned to an 1MiB boundary for the L1
-	 * mapping the head code makes. We keep the UART virtual address
-	 * aligned and add in the offset when we load the value here.
-	 */
-
-	.macro addruart, rx, tmp
-		mrc	p15, 0, \rx, c1, c0
-		tst	\rx, #1
-		ldreq	\rx, = S3C_PA_UART
-		ldrne	\rx, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
-#if CONFIG_DEBUG_S3C_UART != 0
-		add	\rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
-#endif
-	.endm
-
-/* include the reset of the code which will do the work, we're only
- * compiling for a single cpu processor type so the default of s3c2440
- * will be fine with us.
- */
-
-#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s3c6400/include/mach/dma.h b/arch/arm/mach-s3c6400/include/mach/dma.h
deleted file mode 100644
index 6723860..0000000
--- a/arch/arm/mach-s3c6400/include/mach/dma.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* linux/arch/arm/mach-s3c6400/include/mach/dma.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C6400 - DMA support
- */
-
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H __FILE__
-
-#define S3C_DMA_CHANNELS	(16)
-
-/* see mach-s3c2410/dma.h for notes on dma channel numbers */
-
-/* Note, for the S3C64XX architecture we keep the DMACH_
- * defines in the order they are allocated to [S]DMA0/[S]DMA1
- * so that is easy to do DHACH_ -> DMA controller conversion
- */
-enum dma_ch {
-	/* DMA0/SDMA0 */
-	DMACH_UART0 = 0,
-	DMACH_UART0_SRC2,
-	DMACH_UART1,
-	DMACH_UART1_SRC2,
-	DMACH_UART2,
-	DMACH_UART2_SRC2,
-	DMACH_UART3,
-	DMACH_UART3_SRC2,
-	DMACH_PCM0_TX,
-	DMACH_PCM0_RX,
-	DMACH_I2S0_OUT,
-	DMACH_I2S0_IN,
-	DMACH_SPI0_TX,
-	DMACH_SPI0_RX,
-	DMACH_HSI_I2SV40_TX,
-	DMACH_HSI_I2SV40_RX,
-
-	/* DMA1/SDMA1 */
-	DMACH_PCM1_TX = 16,
-	DMACH_PCM1_RX,
-	DMACH_I2S1_OUT,
-	DMACH_I2S1_IN,
-	DMACH_SPI1_TX,
-	DMACH_SPI1_RX,
-	DMACH_AC97_PCMOUT,
-	DMACH_AC97_PCMIN,
-	DMACH_AC97_MICIN,
-	DMACH_PWM,
-	DMACH_IRDA,
-	DMACH_EXTERNAL,
-	DMACH_RES1,
-	DMACH_RES2,
-	DMACH_SECURITY_RX,	/* SDMA1 only */
-	DMACH_SECURITY_TX,	/* SDMA1 only */
-	DMACH_MAX		/* the end */
-};
-
-static __inline__ bool s3c_dma_has_circular(void)
-{
-	return true;
-}
-
-#define S3C2410_DMAF_CIRCULAR		(1 << 0)
-
-#include <plat/dma.h>
-
-#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/entry-macro.S b/arch/arm/mach-s3c6400/include/mach/entry-macro.S
deleted file mode 100644
index fbd90d2..0000000
--- a/arch/arm/mach-s3c6400/include/mach/entry-macro.S
+++ /dev/null
@@ -1,44 +0,0 @@
-/* arch/arm/mach-s3c6400/include/mach/entry-macro.S
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Low-level IRQ helper macros for the Samsung S3C64XX series
- *
- * 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/vic.h>
-#include <mach/map.h>
-#include <plat/irqs.h>
-
-	.macro	disable_fiq
-	.endm
-
-	.macro	get_irqnr_preamble, base, tmp
-	ldr	\base, =S3C_VA_VIC0
-	.endm
-
-	.macro	arch_ret_to_user, tmp1, tmp2
-	.endm
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-	@ check the vic0
-	mov	\irqnr, # S3C_IRQ_OFFSET + 31
-	ldr	\irqstat, [ \base, # VIC_IRQ_STATUS ]
-	teq	\irqstat, #0
-
-	@ otherwise try vic1
-	addeq	\tmp, \base, #(S3C_VA_VIC1 - S3C_VA_VIC0)
-	addeq	\irqnr, \irqnr, #32
-	ldreq	\irqstat, [ \tmp, # VIC_IRQ_STATUS ]
-	teqeq	\irqstat, #0
-
-	clzne	\irqstat, \irqstat
-	subne	\irqnr, \irqnr, \irqstat
-	.endm
diff --git a/arch/arm/mach-s3c6400/include/mach/gpio-core.h b/arch/arm/mach-s3c6400/include/mach/gpio-core.h
deleted file mode 100644
index d89aae6..0000000
--- a/arch/arm/mach-s3c6400/include/mach/gpio-core.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* arch/arm/mach-s3c6400/include/mach/gpio-core.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - GPIO core support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_GPIO_CORE_H
-#define __ASM_ARCH_GPIO_CORE_H __FILE__
-
-/* currently we just include the platform support */
-#include <plat/gpio-core.h>
-
-#endif /* __ASM_ARCH_GPIO_CORE_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/gpio.h b/arch/arm/mach-s3c6400/include/mach/gpio.h
deleted file mode 100644
index e8e35e8..0000000
--- a/arch/arm/mach-s3c6400/include/mach/gpio.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* arch/arm/mach-s3c6400/include/mach/gpio.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C6400 - GPIO lib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
-/* GPIO bank sizes */
-#define S3C64XX_GPIO_A_NR	(8)
-#define S3C64XX_GPIO_B_NR	(7)
-#define S3C64XX_GPIO_C_NR	(8)
-#define S3C64XX_GPIO_D_NR	(5)
-#define S3C64XX_GPIO_E_NR	(5)
-#define S3C64XX_GPIO_F_NR	(16)
-#define S3C64XX_GPIO_G_NR	(7)
-#define S3C64XX_GPIO_H_NR	(10)
-#define S3C64XX_GPIO_I_NR	(16)
-#define S3C64XX_GPIO_J_NR	(12)
-#define S3C64XX_GPIO_K_NR	(16)
-#define S3C64XX_GPIO_L_NR	(15)
-#define S3C64XX_GPIO_M_NR	(6)
-#define S3C64XX_GPIO_N_NR	(16)
-#define S3C64XX_GPIO_O_NR	(16)
-#define S3C64XX_GPIO_P_NR	(15)
-#define S3C64XX_GPIO_Q_NR	(9)
-
-/* GPIO bank numbes */
-
-/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
- * space for debugging purposes so that any accidental
- * change from one gpio bank to another can be caught.
-*/
-
-#define S3C64XX_GPIO_NEXT(__gpio) \
-	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s3c_gpio_number {
-	S3C64XX_GPIO_A_START = 0,
-	S3C64XX_GPIO_B_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_A),
-	S3C64XX_GPIO_C_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_B),
-	S3C64XX_GPIO_D_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_C),
-	S3C64XX_GPIO_E_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_D),
-	S3C64XX_GPIO_F_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_E),
-	S3C64XX_GPIO_G_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_F),
-	S3C64XX_GPIO_H_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_G),
-	S3C64XX_GPIO_I_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_H),
-	S3C64XX_GPIO_J_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_I),
-	S3C64XX_GPIO_K_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_J),
-	S3C64XX_GPIO_L_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_K),
-	S3C64XX_GPIO_M_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_L),
-	S3C64XX_GPIO_N_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_M),
-	S3C64XX_GPIO_O_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_N),
-	S3C64XX_GPIO_P_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_O),
-	S3C64XX_GPIO_Q_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_P),
-};
-
-/* S3C64XX GPIO number definitions. */
-
-#define S3C64XX_GPA(_nr)	(S3C64XX_GPIO_A_START + (_nr))
-#define S3C64XX_GPB(_nr)	(S3C64XX_GPIO_B_START + (_nr))
-#define S3C64XX_GPC(_nr)	(S3C64XX_GPIO_C_START + (_nr))
-#define S3C64XX_GPD(_nr)	(S3C64XX_GPIO_D_START + (_nr))
-#define S3C64XX_GPE(_nr)	(S3C64XX_GPIO_E_START + (_nr))
-#define S3C64XX_GPF(_nr)	(S3C64XX_GPIO_F_START + (_nr))
-#define S3C64XX_GPG(_nr)	(S3C64XX_GPIO_G_START + (_nr))
-#define S3C64XX_GPH(_nr)	(S3C64XX_GPIO_H_START + (_nr))
-#define S3C64XX_GPI(_nr)	(S3C64XX_GPIO_I_START + (_nr))
-#define S3C64XX_GPJ(_nr)	(S3C64XX_GPIO_J_START + (_nr))
-#define S3C64XX_GPK(_nr)	(S3C64XX_GPIO_K_START + (_nr))
-#define S3C64XX_GPL(_nr)	(S3C64XX_GPIO_L_START + (_nr))
-#define S3C64XX_GPM(_nr)	(S3C64XX_GPIO_M_START + (_nr))
-#define S3C64XX_GPN(_nr)	(S3C64XX_GPIO_N_START + (_nr))
-#define S3C64XX_GPO(_nr)	(S3C64XX_GPIO_O_START + (_nr))
-#define S3C64XX_GPP(_nr)	(S3C64XX_GPIO_P_START + (_nr))
-#define S3C64XX_GPQ(_nr)	(S3C64XX_GPIO_Q_START + (_nr))
-
-/* the end of the S3C64XX specific gpios */
-#define S3C64XX_GPIO_END	(S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)
-#define S3C_GPIO_END		S3C64XX_GPIO_END
-
-/* define the number of gpios we need to the one after the GPQ() range */
-#define ARCH_NR_GPIOS	(S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)
-
-#include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-s3c6400/include/mach/irqs.h b/arch/arm/mach-s3c6400/include/mach/irqs.h
deleted file mode 100644
index 4c97f9a..0000000
--- a/arch/arm/mach-s3c6400/include/mach/irqs.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* linux/arch/arm/mach-s3c6400/include/mach/irqs.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C6400 - IRQ definitions
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h
deleted file mode 100644
index 106ee13..0000000
--- a/arch/arm/mach-s3c6400/include/mach/map.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* linux/arch/arm/mach-s3c6400/include/mach/map.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C64XX - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-
-/* HSMMC units */
-#define S3C64XX_PA_HSMMC(x)	(0x7C200000 + ((x) * 0x100000))
-#define S3C64XX_PA_HSMMC0	S3C64XX_PA_HSMMC(0)
-#define S3C64XX_PA_HSMMC1	S3C64XX_PA_HSMMC(1)
-#define S3C64XX_PA_HSMMC2	S3C64XX_PA_HSMMC(2)
-
-#define S3C_PA_UART		(0x7F005000)
-#define S3C_PA_UART0		(S3C_PA_UART + 0x00)
-#define S3C_PA_UART1		(S3C_PA_UART + 0x400)
-#define S3C_PA_UART2		(S3C_PA_UART + 0x800)
-#define S3C_PA_UART3		(S3C_PA_UART + 0xC00)
-#define S3C_UART_OFFSET		(0x400)
-
-/* See notes on UART VA mapping in debug-macro.S */
-#define S3C_VA_UARTx(x)	(S3C_VA_UART + (S3C_PA_UART & 0xfffff) + ((x) * S3C_UART_OFFSET))
-
-#define S3C_VA_UART0		S3C_VA_UARTx(0)
-#define S3C_VA_UART1		S3C_VA_UARTx(1)
-#define S3C_VA_UART2		S3C_VA_UARTx(2)
-#define S3C_VA_UART3		S3C_VA_UARTx(3)
-
-#define S3C64XX_PA_NAND		(0x70200000)
-#define S3C64XX_PA_FB		(0x77100000)
-#define S3C64XX_PA_USB_HSOTG	(0x7C000000)
-#define S3C64XX_PA_WATCHDOG	(0x7E004000)
-#define S3C64XX_PA_SYSCON	(0x7E00F000)
-#define S3C64XX_PA_AC97		(0x7F001000)
-#define S3C64XX_PA_IIS0		(0x7F002000)
-#define S3C64XX_PA_IIS1		(0x7F003000)
-#define S3C64XX_PA_TIMER	(0x7F006000)
-#define S3C64XX_PA_IIC0		(0x7F004000)
-#define S3C64XX_PA_PCM0		(0x7F009000)
-#define S3C64XX_PA_PCM1		(0x7F00A000)
-#define S3C64XX_PA_IISV4	(0x7F00D000)
-#define S3C64XX_PA_IIC1		(0x7F00F000)
-
-#define S3C64XX_PA_GPIO		(0x7F008000)
-#define S3C64XX_VA_GPIO		S3C_ADDR_CPU(0x00000000)
-#define S3C64XX_SZ_GPIO		SZ_4K
-
-#define S3C64XX_PA_SDRAM	(0x50000000)
-#define S3C64XX_PA_VIC0		(0x71200000)
-#define S3C64XX_PA_VIC1		(0x71300000)
-
-#define S3C64XX_PA_MODEM	(0x74108000)
-#define S3C64XX_VA_MODEM	S3C_ADDR_CPU(0x00100000)
-
-#define S3C64XX_PA_USBHOST	(0x74300000)
-
-#define S3C64XX_PA_USB_HSPHY	(0x7C100000)
-#define S3C64XX_VA_USB_HSPHY	S3C_ADDR_CPU(0x00200000)
-
-/* place VICs close together */
-#define S3C_VA_VIC0		(S3C_VA_IRQ + 0x00)
-#define S3C_VA_VIC1		(S3C_VA_IRQ + 0x10000)
-
-/* compatibiltiy defines. */
-#define S3C_PA_TIMER		S3C64XX_PA_TIMER
-#define S3C_PA_HSMMC0		S3C64XX_PA_HSMMC0
-#define S3C_PA_HSMMC1		S3C64XX_PA_HSMMC1
-#define S3C_PA_HSMMC2		S3C64XX_PA_HSMMC2
-#define S3C_PA_IIC		S3C64XX_PA_IIC0
-#define S3C_PA_IIC1		S3C64XX_PA_IIC1
-#define S3C_PA_NAND		S3C64XX_PA_NAND
-#define S3C_PA_FB		S3C64XX_PA_FB
-#define S3C_PA_USBHOST		S3C64XX_PA_USBHOST
-#define S3C_PA_USB_HSOTG	S3C64XX_PA_USB_HSOTG
-#define S3C_VA_USB_HSPHY	S3C64XX_VA_USB_HSPHY
-
-#endif /* __ASM_ARCH_6400_MAP_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/regs-clock.h b/arch/arm/mach-s3c6400/include/mach/regs-clock.h
deleted file mode 100644
index a6c7f4e..0000000
--- a/arch/arm/mach-s3c6400/include/mach/regs-clock.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* linux/arch/arm/mach-s3c6400/include/mach/regs-clock.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C64XX - clock register compatibility with s3c24xx
- *
- * This program is free software; you can redistribute 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/regs-clock.h>
-
diff --git a/arch/arm/mach-s3c6400/include/mach/tick.h b/arch/arm/mach-s3c6400/include/mach/tick.h
deleted file mode 100644
index d9c0dc7..0000000
--- a/arch/arm/mach-s3c6400/include/mach/tick.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* linux/arch/arm/mach-s3c6400/include/mach/tick.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C64XX - Timer tick support definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_TICK_H
-#define __ASM_ARCH_TICK_H __FILE__
-
-/* note, the timer interrutps turn up in 2 places, the vic and then
- * the timer block. We take the VIC as the base at the moment.
- */
-static inline u32 s3c24xx_ostimer_pending(void)
-{
-	u32 pend = __raw_readl(S3C_VA_VIC0 + VIC_RAW_STATUS);
-	return pend & 1 << (IRQ_TIMER4_VIC - S3C64XX_IRQ_VIC0(0));
-}
-
-#define TICK_MAX	(0xffffffff)
-
-#endif /* __ASM_ARCH_6400_TICK_H */
diff --git a/arch/arm/mach-s3c6400/mach-smdk6400.c b/arch/arm/mach-s3c6400/mach-smdk6400.c
deleted file mode 100644
index ab19285..0000000
--- a/arch/arm/mach-s3c6400/mach-smdk6400.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* linux/arch/arm/mach-s3c6400/mach-smdk6400.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/io.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <plat/regs-serial.h>
-
-#include <plat/s3c6400.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/iic.h>
-
-#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
-#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
-#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
-
-static struct s3c2410_uartcfg smdk6400_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	},
-};
-
-static struct map_desc smdk6400_iodesc[] = {};
-
-static void __init smdk6400_map_io(void)
-{
-	s3c64xx_init_io(smdk6400_iodesc, ARRAY_SIZE(smdk6400_iodesc));
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(smdk6400_uartcfgs, ARRAY_SIZE(smdk6400_uartcfgs));
-}
-
-static struct platform_device *smdk6400_devices[] __initdata = {
-	&s3c_device_hsmmc1,
-	&s3c_device_i2c0,
-};
-
-static struct i2c_board_info i2c_devs[] __initdata = {
-	{ I2C_BOARD_INFO("wm8753", 0x1A), },
-	{ I2C_BOARD_INFO("24c08", 0x50), },
-};
-
-static void __init smdk6400_machine_init(void)
-{
-	i2c_register_board_info(0, i2c_devs, ARRAY_SIZE(i2c_devs));
-	platform_add_devices(smdk6400_devices, ARRAY_SIZE(smdk6400_devices));
-}
-
-MACHINE_START(SMDK6400, "SMDK6400")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
-
-	.init_irq	= s3c6400_init_irq,
-	.map_io		= smdk6400_map_io,
-	.init_machine	= smdk6400_machine_init,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c6400/s3c6400.c b/arch/arm/mach-s3c6400/s3c6400.c
deleted file mode 100644
index d876ee5..0000000
--- a/arch/arm/mach-s3c6400/s3c6400.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* linux/arch/arm/mach-s3c6410/cpu.c
- *
- * Copyright 2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/sysdev.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/regs-serial.h>
-#include <plat/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/clock.h>
-#include <plat/sdhci.h>
-#include <plat/iic-core.h>
-#include <plat/s3c6400.h>
-
-void __init s3c6400_map_io(void)
-{
-	/* setup SDHCI */
-
-	s3c6400_default_sdhci0();
-	s3c6400_default_sdhci1();
-	s3c6400_default_sdhci2();
-
-	/* the i2c devices are directly compatible with s3c2440 */
-	s3c_i2c0_setname("s3c2440-i2c");
-
-	s3c_device_nand.name = "s3c6400-nand";
-}
-
-void __init s3c6400_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
-	s3c24xx_register_baseclocks(xtal);
-	s3c64xx_register_clocks();
-	s3c6400_register_clocks(S3C6400_CLKDIV0_ARM_MASK);
-	s3c6400_setup_clocks();
-}
-
-void __init s3c6400_init_irq(void)
-{
-	/* VIC0 does not have IRQS 5..7,
-	 * VIC1 is fully populated. */
-	s3c64xx_init_irq(~0 & ~(0xf << 5), ~0);
-}
-
-struct sysdev_class s3c6400_sysclass = {
-	.name	= "s3c6400-core",
-};
-
-static struct sys_device s3c6400_sysdev = {
-	.cls	= &s3c6400_sysclass,
-};
-
-static int __init s3c6400_core_init(void)
-{
-	return sysdev_class_register(&s3c6400_sysclass);
-}
-
-core_initcall(s3c6400_core_init);
-
-int __init s3c6400_init(void)
-{
-	printk("S3C6400: Initialising architecture\n");
-
-	return sysdev_register(&s3c6400_sysdev);
-}
diff --git a/arch/arm/mach-s3c6400/setup-sdhci.c b/arch/arm/mach-s3c6400/setup-sdhci.c
deleted file mode 100644
index 1039937..0000000
--- a/arch/arm/mach-s3c6400/setup-sdhci.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* linux/arch/arm/mach-s3c6410/setup-sdhci.c
- *
- * Copyright 2008 Simtec Electronics
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C6410 - Helper functions for settign up SDHCI device(s) (HSMMC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
-
-/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
-
-char *s3c6400_hsmmc_clksrcs[4] = {
-	[0] = "hsmmc",
-	[1] = "hsmmc",
-	[2] = "mmc_bus",
-	/* [3] = "48m", - note not successfully used yet */
-};
-
-void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
-				  void __iomem *r,
-				  struct mmc_ios *ios,
-				  struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	printk(KERN_INFO "%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
-
diff --git a/arch/arm/mach-s3c6410/Kconfig b/arch/arm/mach-s3c6410/Kconfig
deleted file mode 100644
index 162f456..0000000
--- a/arch/arm/mach-s3c6410/Kconfig
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright 2008 Openmoko, Inc.
-# Copyright 2008 Simtec Electronics
-#
-# Licensed under GPLv2
-
-# Configuration options for the S3C6410 CPU
-
-config CPU_S3C6410
-	bool
-	select CPU_S3C6400_INIT
-	select CPU_S3C6400_CLOCK
-	help
-	  Enable S3C6410 CPU support
-
-config S3C6410_SETUP_SDHCI
-	bool
-	select S3C64XX_SETUP_SDHCI_GPIO
-	help
-	  Internal helper functions for S3C6410 based SDHCI systems
-
-config MACH_ANW6410
-	bool "A&W6410"
-	select CPU_S3C6410
-	select S3C_DEV_FB
-	select S3C64XX_SETUP_FB_24BPP
-	help
-	  Machine support for the A&W6410
-
-config MACH_SMDK6410
-	bool "SMDK6410"
-	select CPU_S3C6410
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_I2C1
-	select S3C_DEV_FB
-	select S3C_DEV_USB_HOST
-	select S3C_DEV_USB_HSOTG
-	select S3C6410_SETUP_SDHCI
-	select S3C64XX_SETUP_I2C1
-	select S3C64XX_SETUP_FB_24BPP
-	help
-	  Machine support for the Samsung SMDK6410
-
-# At least some of the SMDK6410s were shipped with the card detect
-# for the MMC/SD slots connected to the same input. This means that
-# either the boards need to be altered to have channel0 to an alternate
-# configuration or that only one slot can be used.
-
-choice
-	prompt "SMDK6410 MMC/SD slot setup"
-	depends on MACH_SMDK6410
-
-config SMDK6410_SD_CH0
-	bool "Use channel 0 only"
-	depends on MACH_SMDK6410
-	help
-          Select CON7 (channel 0) as the MMC/SD slot, as
-	  at least some SMDK6410 boards come with the
-	  resistors fitted so that the card detects for
-	  channels 0 and 1 are the same.
-       
-config SMDK6410_SD_CH1
-	bool "Use channel 1 only"
-	depends on MACH_SMDK6410
-	help
-          Select CON6 (channel 1) as the MMC/SD slot, as
-	  at least some SMDK6410 boards come with the
-	  resistors fitted so that the card detects for
-	  channels 0 and 1 are the same.
-
-endchoice
-
-config SMDK6410_WM1190_EV1
-	bool "Support Wolfson Microelectronics 1190-EV1 PMIC card"
-	depends on MACH_SMDK6410
-	select REGULATOR
-	select REGULATOR_WM8350
-	select S3C24XX_GPIO_EXTRA64
-	select MFD_WM8350_I2C
-	select MFD_WM8350_CONFIG_MODE_0
-	select MFD_WM8350_CONFIG_MODE_3
-	select MFD_WM8352_CONFIG_MODE_0
-	help
-	  The Wolfson Microelectronics 1190-EV1 is a WM835x based PMIC
-	  and audio daughtercard for the Samsung SMDK6410 reference
-	  platform.  Enabling this option will build support for this
-	  module into the kernel.  The presence of the module will be
-	  detected at runtime so the the resulting kernel can be used
-	  with or without the 1190-EV1 fitted.
-
-config MACH_NCP
-	bool "NCP"
-	select CPU_S3C6410
-	select S3C_DEV_I2C1
-	select S3C_DEV_HSMMC1
-	select S3C64XX_SETUP_I2C1
-	help
-          Machine support for the Samsung NCP
-
-config MACH_HMT
-	bool "Airgoo HMT"
-	select CPU_S3C6410
-	select S3C_DEV_FB
-	select S3C_DEV_NAND
-	select S3C_DEV_USB_HOST
-	select S3C64XX_SETUP_FB_24BPP
-	select HAVE_PWM
-	help
-	  Machine support for the Airgoo HMT
diff --git a/arch/arm/mach-s3c6410/Makefile b/arch/arm/mach-s3c6410/Makefile
deleted file mode 100644
index 3e48c3d..0000000
--- a/arch/arm/mach-s3c6410/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-# arch/arm/plat-s3c6410/Makefile
-#
-# Copyright 2008 Openmoko, Inc.
-# Copyright 2008 Simtec Electronics
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-# Core support for S3C6410 system
-
-obj-$(CONFIG_CPU_S3C6410)	+= cpu.o
-
-# Helper and device support
-
-obj-$(CONFIG_S3C6410_SETUP_SDHCI)	+= setup-sdhci.o
-
-# machine support
-
-obj-$(CONFIG_MACH_ANW6410)	+= mach-anw6410.o
-obj-$(CONFIG_MACH_SMDK6410)	+= mach-smdk6410.o
-obj-$(CONFIG_MACH_NCP)		+= mach-ncp.o
-obj-$(CONFIG_MACH_HMT)		+= mach-hmt.o
diff --git a/arch/arm/mach-s3c6410/cpu.c b/arch/arm/mach-s3c6410/cpu.c
deleted file mode 100644
index 522c086..0000000
--- a/arch/arm/mach-s3c6410/cpu.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* linux/arch/arm/mach-s3c6410/cpu.c
- *
- * Copyright 2008 Simtec Electronics
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/sysdev.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/regs-serial.h>
-#include <plat/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/clock.h>
-#include <plat/sdhci.h>
-#include <plat/iic-core.h>
-#include <plat/s3c6400.h>
-#include <plat/s3c6410.h>
-
-/* Initial IO mappings */
-
-static struct map_desc s3c6410_iodesc[] __initdata = {
-};
-
-/* s3c6410_map_io
- *
- * register the standard cpu IO areas
-*/
-
-void __init s3c6410_map_io(void)
-{
-	iotable_init(s3c6410_iodesc, ARRAY_SIZE(s3c6410_iodesc));
-
-	/* initialise device information early */
-	s3c6410_default_sdhci0();
-	s3c6410_default_sdhci1();
-	s3c6410_default_sdhci2();
-
-	/* the i2c devices are directly compatible with s3c2440 */
-	s3c_i2c0_setname("s3c2440-i2c");
-	s3c_i2c1_setname("s3c2440-i2c");
-
-	s3c_device_nand.name = "s3c6400-nand";
-}
-
-void __init s3c6410_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
-	s3c24xx_register_baseclocks(xtal);
-	s3c64xx_register_clocks();
-	s3c6400_register_clocks(S3C6410_CLKDIV0_ARM_MASK);
-	s3c6400_setup_clocks();
-}
-
-void __init s3c6410_init_irq(void)
-{
-	/* VIC0 is missing IRQ7, VIC1 is fully populated. */
-	s3c64xx_init_irq(~0 & ~(1 << 7), ~0);
-}
-
-struct sysdev_class s3c6410_sysclass = {
-	.name	= "s3c6410-core",
-};
-
-static struct sys_device s3c6410_sysdev = {
-	.cls	= &s3c6410_sysclass,
-};
-
-static int __init s3c6410_core_init(void)
-{
-	return sysdev_class_register(&s3c6410_sysclass);
-}
-
-core_initcall(s3c6410_core_init);
-
-int __init s3c6410_init(void)
-{
-	printk("S3C6410: Initialising architecture\n");
-
-	return sysdev_register(&s3c6410_sysdev);
-}
diff --git a/arch/arm/mach-s3c6410/mach-anw6410.c b/arch/arm/mach-s3c6410/mach-anw6410.c
deleted file mode 100644
index 661cca6..0000000
--- a/arch/arm/mach-s3c6410/mach-anw6410.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/* linux/arch/arm/mach-s3c6410/mach-anw6410.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- * Copyright 2009 Kwangwoo Lee
- * 	Kwangwoo Lee <kwangwoo.lee@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/dm9000.h>
-
-#include <video/platform_lcd.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-fb.h>
-#include <mach/map.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/iic.h>
-#include <plat/fb.h>
-
-#include <plat/s3c6410.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/regs-gpio.h>
-#include <plat/regs-modem.h>
-
-/* DM9000 */
-#define ANW6410_PA_DM9000	(0x18000000)
-
-/* A hardware buffer to control external devices is mapped at 0x30000000.
- * It can not be read. So current status must be kept in anw6410_extdev_status.
- */
-#define ANW6410_VA_EXTDEV	S3C_ADDR(0x02000000)
-#define ANW6410_PA_EXTDEV	(0x30000000)
-
-#define ANW6410_EN_DM9000	(1<<11)
-#define ANW6410_EN_LCD		(1<<14)
-
-static __u32 anw6410_extdev_status;
-
-static struct s3c2410_uartcfg anw6410_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = 0x3c5,
-		.ulcon	     = 0x03,
-		.ufcon	     = 0x51,
-	},
-};
-
-/* framebuffer and LCD setup. */
-static void __init anw6410_lcd_mode_set(void)
-{
-	u32 tmp;
-
-	/* set the LCD type */
-	tmp = __raw_readl(S3C64XX_SPCON);
-	tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
-	tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
-	__raw_writel(tmp, S3C64XX_SPCON);
-
-	/* remove the LCD bypass */
-	tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
-	tmp &= ~MIFPCON_LCD_BYPASS;
-	__raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
-}
-
-/* GPF1 = LCD panel power
- * GPF4 = LCD backlight control
- */
-static void anw6410_lcd_power_set(struct plat_lcd_data *pd,
-				   unsigned int power)
-{
-	if (power) {
-		anw6410_extdev_status |= (ANW6410_EN_LCD << 16);
-		__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
-
-		gpio_direction_output(S3C64XX_GPF(1), 1);
-		gpio_direction_output(S3C64XX_GPF(4), 1);
-	} else {
-		anw6410_extdev_status &= ~(ANW6410_EN_LCD << 16);
-		__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
-
-		gpio_direction_output(S3C64XX_GPF(1), 0);
-		gpio_direction_output(S3C64XX_GPF(4), 0);
-	}
-}
-
-static struct plat_lcd_data anw6410_lcd_power_data = {
-	.set_power	= anw6410_lcd_power_set,
-};
-
-static struct platform_device anw6410_lcd_powerdev = {
-	.name			= "platform-lcd",
-	.dev.parent		= &s3c_device_fb.dev,
-	.dev.platform_data	= &anw6410_lcd_power_data,
-};
-
-static struct s3c_fb_pd_win anw6410_fb_win0 = {
-	/* this is to ensure we use win0 */
-	.win_mode	= {
-		.pixclock	= 41094,
-		.left_margin	= 8,
-		.right_margin	= 13,
-		.upper_margin	= 7,
-		.lower_margin	= 5,
-		.hsync_len	= 3,
-		.vsync_len	= 1,
-		.xres		= 800,
-		.yres		= 480,
-	},
-	.max_bpp	= 32,
-	.default_bpp	= 16,
-};
-
-/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
-static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = {
-	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
-	.win[0]		= &anw6410_fb_win0,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-};
-
-/* DM9000AEP 10/100 ethernet controller */
-static void __init anw6410_dm9000_enable(void)
-{
-	anw6410_extdev_status |= (ANW6410_EN_DM9000 << 16);
-	__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
-}
-
-static struct resource anw6410_dm9000_resource[] = {
-	[0] = {
-		.start = ANW6410_PA_DM9000,
-		.end   = ANW6410_PA_DM9000 + 3,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = ANW6410_PA_DM9000 + 4,
-		.end   = ANW6410_PA_DM9000 + 4 + 500,
-		.flags = IORESOURCE_MEM,
-	},
-	[2] = {
-		.start = IRQ_EINT(15),
-		.end   = IRQ_EINT(15),
-		.flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
-	},
-};
-
-static struct dm9000_plat_data anw6410_dm9000_pdata = {
-	.flags	  = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
-	/* dev_addr can be set to provide hwaddr. */
-};
-
-static struct platform_device anw6410_device_eth = {
-	.name	= "dm9000",
-	.id	= -1,
-	.num_resources	= ARRAY_SIZE(anw6410_dm9000_resource),
-	.resource	= anw6410_dm9000_resource,
-	.dev	= {
-		.platform_data  = &anw6410_dm9000_pdata,
-	},
-};
-
-static struct map_desc anw6410_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)ANW6410_VA_EXTDEV,
-		.pfn		= __phys_to_pfn(ANW6410_PA_EXTDEV),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	},
-};
-
-static struct platform_device *anw6410_devices[] __initdata = {
-	&s3c_device_fb,
-	&anw6410_lcd_powerdev,
-	&anw6410_device_eth,
-};
-
-static void __init anw6410_map_io(void)
-{
-	s3c64xx_init_io(anw6410_iodesc, ARRAY_SIZE(anw6410_iodesc));
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(anw6410_uartcfgs, ARRAY_SIZE(anw6410_uartcfgs));
-
-	anw6410_lcd_mode_set();
-}
-
-static void __init anw6410_machine_init(void)
-{
-	s3c_fb_set_platdata(&anw6410_lcd_pdata);
-
-	gpio_request(S3C64XX_GPF(1), "panel power");
-	gpio_request(S3C64XX_GPF(4), "LCD backlight");
-
-	anw6410_dm9000_enable();
-
-	platform_add_devices(anw6410_devices, ARRAY_SIZE(anw6410_devices));
-}
-
-MACHINE_START(ANW6410, "A&W6410")
-	/* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
-
-	.init_irq	= s3c6410_init_irq,
-	.map_io		= anw6410_map_io,
-	.init_machine	= anw6410_machine_init,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c6410/mach-hmt.c b/arch/arm/mach-s3c6410/mach-hmt.c
deleted file mode 100644
index 7619456..0000000
--- a/arch/arm/mach-s3c6410/mach-hmt.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* mach-hmt.c - Platform code for Airgoo HMT
- *
- * Copyright 2009 Peter Korsgaard <jacmet@sunsite.dk>
- *
- * This program is free software; you can redistribute it 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/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/leds.h>
-#include <linux/pwm_backlight.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-fb.h>
-#include <mach/map.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/iic.h>
-#include <plat/fb.h>
-#include <plat/nand.h>
-
-#include <plat/s3c6410.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-#define UCON S3C2410_UCON_DEFAULT
-#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE)
-#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
-
-static struct s3c2410_uartcfg hmt_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-	[2] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-};
-
-static int hmt_bl_init(struct device *dev)
-{
-	int ret;
-
-	ret = gpio_request(S3C64XX_GPB(4), "lcd backlight enable");
-	if (!ret)
-		ret = gpio_direction_output(S3C64XX_GPB(4), 0);
-
-	return ret;
-}
-
-static int hmt_bl_notify(struct device *dev, int brightness)
-{
-	/*
-	 * translate from CIELUV/CIELAB L*->brightness, E.G. from
-	 * perceived luminance to light output. Assumes range 0..25600
-	 */
-	if (brightness < 0x800) {
-		/* Y = Yn * L / 903.3 */
-		brightness = (100*256 * brightness + 231245/2) / 231245;
-	} else {
-		/* Y = Yn * ((L + 16) / 116 )^3 */
-		int t = (brightness*4 + 16*1024 + 58)/116;
-		brightness = 25 * ((t * t * t + 0x100000/2) / 0x100000);
-	}
-
-	gpio_set_value(S3C64XX_GPB(4), brightness);
-
-	return brightness;
-}
-
-static void hmt_bl_exit(struct device *dev)
-{
-	gpio_free(S3C64XX_GPB(4));
-}
-
-static struct platform_pwm_backlight_data hmt_backlight_data = {
-	.pwm_id		= 1,
-	.max_brightness	= 100 * 256,
-	.dft_brightness	= 40 * 256,
-	.pwm_period_ns	= 1000000000 / (100 * 256 * 20),
-	.init		= hmt_bl_init,
-	.notify		= hmt_bl_notify,
-	.exit		= hmt_bl_exit,
-
-};
-
-static struct platform_device hmt_backlight_device = {
-	.name		= "pwm-backlight",
-	.dev		= {
-		.parent	= &s3c_device_timer[1].dev,
-		.platform_data = &hmt_backlight_data,
-	},
-};
-
-static struct s3c_fb_pd_win hmt_fb_win0 = {
-	.win_mode	= {
-		.pixclock	= 41094,
-		.left_margin	= 8,
-		.right_margin	= 13,
-		.upper_margin	= 7,
-		.lower_margin	= 5,
-		.hsync_len	= 3,
-		.vsync_len	= 1,
-		.xres		= 800,
-		.yres		= 480,
-	},
-	.max_bpp	= 32,
-	.default_bpp	= 16,
-};
-
-/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
-static struct s3c_fb_platdata hmt_lcd_pdata __initdata = {
-	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
-	.win[0]		= &hmt_fb_win0,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-};
-
-static struct mtd_partition hmt_nand_part[] = {
-	[0] = {
-		.name	= "uboot",
-		.size	= SZ_512K,
-		.offset	= 0,
-	},
-	[1] = {
-		.name	= "uboot-env1",
-		.size	= SZ_256K,
-		.offset	= SZ_512K,
-	},
-	[2] = {
-		.name	= "uboot-env2",
-		.size	= SZ_256K,
-		.offset	= SZ_512K + SZ_256K,
-	},
-	[3] = {
-		.name	= "kernel",
-		.size	= SZ_2M,
-		.offset	= SZ_1M,
-	},
-	[4] = {
-		.name	= "rootfs",
-		.size	= MTDPART_SIZ_FULL,
-		.offset	= SZ_1M + SZ_2M,
-	},
-};
-
-static struct s3c2410_nand_set hmt_nand_sets[] = {
-	[0] = {
-		.name		= "nand",
-		.nr_chips	= 1,
-		.nr_partitions	= ARRAY_SIZE(hmt_nand_part),
-		.partitions	= hmt_nand_part,
-	},
-};
-
-static struct s3c2410_platform_nand hmt_nand_info = {
-	.tacls		= 25,
-	.twrph0		= 55,
-	.twrph1		= 40,
-	.nr_sets	= ARRAY_SIZE(hmt_nand_sets),
-	.sets		= hmt_nand_sets,
-};
-
-static struct gpio_led hmt_leds[] = {
-	{ /* left function keys */
-		.name			= "left:blue",
-		.gpio			= S3C64XX_GPO(12),
-		.default_trigger	= "default-on",
-	},
-	{ /* right function keys - red */
-		.name			= "right:red",
-		.gpio			= S3C64XX_GPO(13),
-	},
-	{ /* right function keys - green */
-		.name			= "right:green",
-		.gpio			= S3C64XX_GPO(14),
-	},
-	{ /* right function keys - blue */
-		.name			= "right:blue",
-		.gpio			= S3C64XX_GPO(15),
-		.default_trigger	= "default-on",
-	},
-};
-
-static struct gpio_led_platform_data hmt_led_data = {
-	.num_leds = ARRAY_SIZE(hmt_leds),
-	.leds = hmt_leds,
-};
-
-static struct platform_device hmt_leds_device = {
-	.name			= "leds-gpio",
-	.id			= -1,
-	.dev.platform_data	= &hmt_led_data,
-};
-
-static struct map_desc hmt_iodesc[] = {};
-
-static struct platform_device *hmt_devices[] __initdata = {
-	&s3c_device_i2c0,
-	&s3c_device_nand,
-	&s3c_device_fb,
-	&s3c_device_usb,
-	&s3c_device_timer[1],
-	&hmt_backlight_device,
-	&hmt_leds_device,
-};
-
-static void __init hmt_map_io(void)
-{
-	s3c64xx_init_io(hmt_iodesc, ARRAY_SIZE(hmt_iodesc));
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(hmt_uartcfgs, ARRAY_SIZE(hmt_uartcfgs));
-}
-
-static void __init hmt_machine_init(void)
-{
-	s3c_i2c0_set_platdata(NULL);
-	s3c_fb_set_platdata(&hmt_lcd_pdata);
-	s3c_nand_set_platdata(&hmt_nand_info);
-
-	gpio_request(S3C64XX_GPC(7), "usb power");
-	gpio_direction_output(S3C64XX_GPC(7), 0);
-	gpio_request(S3C64XX_GPM(0), "usb power");
-	gpio_direction_output(S3C64XX_GPM(0), 1);
-	gpio_request(S3C64XX_GPK(7), "usb power");
-	gpio_direction_output(S3C64XX_GPK(7), 1);
-	gpio_request(S3C64XX_GPF(13), "usb power");
-	gpio_direction_output(S3C64XX_GPF(13), 1);
-
-	platform_add_devices(hmt_devices, ARRAY_SIZE(hmt_devices));
-}
-
-MACHINE_START(HMT, "Airgoo-HMT")
-	/* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
-	.init_irq	= s3c6410_init_irq,
-	.map_io		= hmt_map_io,
-	.init_machine	= hmt_machine_init,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c6410/mach-ncp.c b/arch/arm/mach-s3c6410/mach-ncp.c
deleted file mode 100644
index 55e9bbf..0000000
--- a/arch/arm/mach-s3c6410/mach-ncp.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * linux/arch/arm/mach-s3c6410/mach-ncp.c
- *
- * Copyright (C) 2008-2009 Samsung Electronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-
-#include <video/platform_lcd.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-fb.h>
-#include <mach/map.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/iic.h>
-#include <plat/fb.h>
-
-#include <plat/s3c6410.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-#define UCON S3C2410_UCON_DEFAULT
-#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE
-#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
-
-static struct s3c2410_uartcfg ncp_uartcfgs[] __initdata = {
-	/* REVISIT: NCP uses only serial 1, 2 */
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-	[2] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-};
-
-static struct platform_device *ncp_devices[] __initdata = {
-	&s3c_device_hsmmc1,
-	&s3c_device_i2c0,
-};
-
-static struct map_desc ncp_iodesc[] __initdata = {};
-
-static void __init ncp_map_io(void)
-{
-	s3c64xx_init_io(ncp_iodesc, ARRAY_SIZE(ncp_iodesc));
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(ncp_uartcfgs, ARRAY_SIZE(ncp_uartcfgs));
-}
-
-static void __init ncp_machine_init(void)
-{
-	s3c_i2c0_set_platdata(NULL);
-
-	platform_add_devices(ncp_devices, ARRAY_SIZE(ncp_devices));
-}
-
-MACHINE_START(NCP, "NCP")
-	/* Maintainer: Samsung Electronics */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
-	.init_irq	= s3c6410_init_irq,
-	.map_io		= ncp_map_io,
-	.init_machine	= ncp_machine_init,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c
deleted file mode 100644
index 8969fe7..0000000
--- a/arch/arm/mach-s3c6410/mach-smdk6410.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/* linux/arch/arm/mach-s3c6410/mach-smdk6410.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/smsc911x.h>
-#include <linux/regulator/fixed.h>
-
-#ifdef CONFIG_SMDK6410_WM1190_EV1
-#include <linux/mfd/wm8350/core.h>
-#include <linux/mfd/wm8350/pmic.h>
-#endif
-
-#include <video/platform_lcd.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-fb.h>
-#include <mach/map.h>
-
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-modem.h>
-#include <plat/regs-gpio.h>
-#include <plat/regs-sys.h>
-#include <plat/iic.h>
-#include <plat/fb.h>
-#include <plat/gpio-cfg.h>
-
-#include <plat/s3c6410.h>
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-
-#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
-#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
-#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
-
-static struct s3c2410_uartcfg smdk6410_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport	     = 0,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-	[1] = {
-		.hwport	     = 1,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-	[2] = {
-		.hwport	     = 2,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-	[3] = {
-		.hwport	     = 3,
-		.flags	     = 0,
-		.ucon	     = UCON,
-		.ulcon	     = ULCON,
-		.ufcon	     = UFCON,
-	},
-};
-
-/* framebuffer and LCD setup. */
-
-/* GPF15 = LCD backlight control
- * GPF13 => Panel power
- * GPN5 = LCD nRESET signal
- * PWM_TOUT1 => backlight brightness
- */
-
-static void smdk6410_lcd_power_set(struct plat_lcd_data *pd,
-				   unsigned int power)
-{
-	if (power) {
-		gpio_direction_output(S3C64XX_GPF(13), 1);
-		gpio_direction_output(S3C64XX_GPF(15), 1);
-
-		/* fire nRESET on power up */
-		gpio_direction_output(S3C64XX_GPN(5), 0);
-		msleep(10);
-		gpio_direction_output(S3C64XX_GPN(5), 1);
-		msleep(1);
-	} else {
-		gpio_direction_output(S3C64XX_GPF(15), 0);
-		gpio_direction_output(S3C64XX_GPF(13), 0);
-	}
-}
-
-static struct plat_lcd_data smdk6410_lcd_power_data = {
-	.set_power	= smdk6410_lcd_power_set,
-};
-
-static struct platform_device smdk6410_lcd_powerdev = {
-	.name			= "platform-lcd",
-	.dev.parent		= &s3c_device_fb.dev,
-	.dev.platform_data	= &smdk6410_lcd_power_data,
-};
-
-static struct s3c_fb_pd_win smdk6410_fb_win0 = {
-	/* this is to ensure we use win0 */
-	.win_mode	= {
-		.pixclock	= 41094,
-		.left_margin	= 8,
-		.right_margin	= 13,
-		.upper_margin	= 7,
-		.lower_margin	= 5,
-		.hsync_len	= 3,
-		.vsync_len	= 1,
-		.xres		= 800,
-		.yres		= 480,
-	},
-	.max_bpp	= 32,
-	.default_bpp	= 16,
-};
-
-/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
-static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = {
-	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
-	.win[0]		= &smdk6410_fb_win0,
-	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
-	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
-};
-
-static struct resource smdk6410_smsc911x_resources[] = {
-	[0] = {
-		.start = 0x18000000,
-		.end   = 0x18000000 + SZ_64K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = S3C_EINT(10),
-		.end   = S3C_EINT(10),
-		.flags = IORESOURCE_IRQ | IRQ_TYPE_LEVEL_LOW,
-	},
-};
-
-static struct smsc911x_platform_config smdk6410_smsc911x_pdata = {
-	.irq_polarity  = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type      = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
-	.flags         = SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.phy_interface = PHY_INTERFACE_MODE_MII,
-};
-
-
-static struct platform_device smdk6410_smsc911x = {
-	.name          = "smsc911x",
-	.id            = -1,
-	.num_resources = ARRAY_SIZE(smdk6410_smsc911x_resources),
-	.resource      = &smdk6410_smsc911x_resources[0],
-	.dev = {
-		.platform_data = &smdk6410_smsc911x_pdata,
-	},
-};
-
-#ifdef CONFIG_REGULATOR
-static struct regulator_consumer_supply smdk6410_b_pwr_5v_consumers[] = {
-	{
-		/* WM8580 */
-		.supply = "PVDD",
-		.dev_name = "0-001b",
-	},
-	{
-		/* WM8580 */
-		.supply = "AVDD",
-		.dev_name = "0-001b",
-	},
-};
-
-static struct regulator_init_data smdk6410_b_pwr_5v_data = {
-	.constraints = {
-		.always_on = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(smdk6410_b_pwr_5v_consumers),
-	.consumer_supplies = smdk6410_b_pwr_5v_consumers,
-};
-
-static struct fixed_voltage_config smdk6410_b_pwr_5v_pdata = {
-	.supply_name = "B_PWR_5V",
-	.microvolts = 5000000,
-	.init_data = &smdk6410_b_pwr_5v_data,
-	.gpio = -EINVAL,
-};
-
-static struct platform_device smdk6410_b_pwr_5v = {
-	.name          = "reg-fixed-voltage",
-	.id            = -1,
-	.dev = {
-		.platform_data = &smdk6410_b_pwr_5v_pdata,
-	},
-};
-#endif
-
-static struct map_desc smdk6410_iodesc[] = {};
-
-static struct platform_device *smdk6410_devices[] __initdata = {
-#ifdef CONFIG_SMDK6410_SD_CH0
-	&s3c_device_hsmmc0,
-#endif
-#ifdef CONFIG_SMDK6410_SD_CH1
-	&s3c_device_hsmmc1,
-#endif
-	&s3c_device_i2c0,
-	&s3c_device_i2c1,
-	&s3c_device_fb,
-	&s3c_device_usb,
-	&s3c_device_usb_hsotg,
-
-#ifdef CONFIG_REGULATOR
-	&smdk6410_b_pwr_5v,
-#endif
-	&smdk6410_lcd_powerdev,
-
-	&smdk6410_smsc911x,
-};
-
-#ifdef CONFIG_SMDK6410_WM1190_EV1
-/* S3C64xx internal logic & PLL */
-static struct regulator_init_data wm8350_dcdc1_data = {
-	.constraints = {
-		.name = "PVDD_INT/PVDD_PLL",
-		.min_uV = 1200000,
-		.max_uV = 1200000,
-		.always_on = 1,
-		.apply_uV = 1,
-	},
-};
-
-/* Memory */
-static struct regulator_init_data wm8350_dcdc3_data = {
-	.constraints = {
-		.name = "PVDD_MEM",
-		.min_uV = 1800000,
-		.max_uV = 1800000,
-		.always_on = 1,
-		.state_mem = {
-			 .uV = 1800000,
-			 .mode = REGULATOR_MODE_NORMAL,
-			 .enabled = 1,
-		 },
-		.initial_state = PM_SUSPEND_MEM,
-	},
-};
-
-/* USB, EXT, PCM, ADC/DAC, USB, MMC */
-static struct regulator_consumer_supply wm8350_dcdc4_consumers[] = {
-	{
-		/* WM8580 */
-		.supply = "DVDD",
-		.dev_name = "0-001b",
-	},
-};
-
-static struct regulator_init_data wm8350_dcdc4_data = {
-	.constraints = {
-		.name = "PVDD_HI/PVDD_EXT/PVDD_SYS/PVCCM2MTV",
-		.min_uV = 3000000,
-		.max_uV = 3000000,
-		.always_on = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(wm8350_dcdc4_consumers),
-	.consumer_supplies = wm8350_dcdc4_consumers,
-};
-
-/* ARM core */
-static struct regulator_consumer_supply dcdc6_consumers[] = {
-	{
-		.supply = "vddarm",
-	}
-};
-
-static struct regulator_init_data wm8350_dcdc6_data = {
-	.constraints = {
-		.name = "PVDD_ARM",
-		.min_uV = 1000000,
-		.max_uV = 1300000,
-		.always_on = 1,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(dcdc6_consumers),
-	.consumer_supplies = dcdc6_consumers,
-};
-
-/* Alive */
-static struct regulator_init_data wm8350_ldo1_data = {
-	.constraints = {
-		.name = "PVDD_ALIVE",
-		.min_uV = 1200000,
-		.max_uV = 1200000,
-		.always_on = 1,
-		.apply_uV = 1,
-	},
-};
-
-/* OTG */
-static struct regulator_init_data wm8350_ldo2_data = {
-	.constraints = {
-		.name = "PVDD_OTG",
-		.min_uV = 3300000,
-		.max_uV = 3300000,
-		.always_on = 1,
-	},
-};
-
-/* LCD */
-static struct regulator_init_data wm8350_ldo3_data = {
-	.constraints = {
-		.name = "PVDD_LCD",
-		.min_uV = 3000000,
-		.max_uV = 3000000,
-		.always_on = 1,
-	},
-};
-
-/* OTGi/1190-EV1 HPVDD & AVDD */
-static struct regulator_init_data wm8350_ldo4_data = {
-	.constraints = {
-		.name = "PVDD_OTGI/HPVDD/AVDD",
-		.min_uV = 1200000,
-		.max_uV = 1200000,
-		.apply_uV = 1,
-		.always_on = 1,
-	},
-};
-
-static struct {
-	int regulator;
-	struct regulator_init_data *initdata;
-} wm1190_regulators[] = {
-	{ WM8350_DCDC_1, &wm8350_dcdc1_data },
-	{ WM8350_DCDC_3, &wm8350_dcdc3_data },
-	{ WM8350_DCDC_4, &wm8350_dcdc4_data },
-	{ WM8350_DCDC_6, &wm8350_dcdc6_data },
-	{ WM8350_LDO_1, &wm8350_ldo1_data },
-	{ WM8350_LDO_2, &wm8350_ldo2_data },
-	{ WM8350_LDO_3, &wm8350_ldo3_data },
-	{ WM8350_LDO_4, &wm8350_ldo4_data },
-};
-
-static int __init smdk6410_wm8350_init(struct wm8350 *wm8350)
-{
-	int i;
-
-	/* Configure the IRQ line */
-	s3c_gpio_setpull(S3C64XX_GPN(12), S3C_GPIO_PULL_UP);
-
-	/* Instantiate the regulators */
-	for (i = 0; i < ARRAY_SIZE(wm1190_regulators); i++)
-		wm8350_register_regulator(wm8350,
-					  wm1190_regulators[i].regulator,
-					  wm1190_regulators[i].initdata);
-
-	return 0;
-}
-
-static struct wm8350_platform_data __initdata smdk6410_wm8350_pdata = {
-	.init = smdk6410_wm8350_init,
-	.irq_high = 1,
-};
-#endif
-
-static struct i2c_board_info i2c_devs0[] __initdata = {
-	{ I2C_BOARD_INFO("24c08", 0x50), },
-	{ I2C_BOARD_INFO("wm8580", 0x1b), },
-
-#ifdef CONFIG_SMDK6410_WM1190_EV1
-	{ I2C_BOARD_INFO("wm8350", 0x1a),
-	  .platform_data = &smdk6410_wm8350_pdata,
-	  .irq = S3C_EINT(12),
-	},
-#endif
-};
-
-static struct i2c_board_info i2c_devs1[] __initdata = {
-	{ I2C_BOARD_INFO("24c128", 0x57), },	/* Samsung S524AD0XD1 */
-};
-
-static void __init smdk6410_map_io(void)
-{
-	u32 tmp;
-
-	s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
-	s3c24xx_init_clocks(12000000);
-	s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
-
-	/* set the LCD type */
-
-	tmp = __raw_readl(S3C64XX_SPCON);
-	tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
-	tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
-	__raw_writel(tmp, S3C64XX_SPCON);
-
-	/* remove the lcd bypass */
-	tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
-	tmp &= ~MIFPCON_LCD_BYPASS;
-	__raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
-}
-
-static void __init smdk6410_machine_init(void)
-{
-	s3c_i2c0_set_platdata(NULL);
-	s3c_i2c1_set_platdata(NULL);
-	s3c_fb_set_platdata(&smdk6410_lcd_pdata);
-
-	gpio_request(S3C64XX_GPN(5), "LCD power");
-	gpio_request(S3C64XX_GPF(13), "LCD power");
-	gpio_request(S3C64XX_GPF(15), "LCD power");
-
-	i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
-	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
-	platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
-}
-
-MACHINE_START(SMDK6410, "SMDK6410")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
-	.phys_io	= S3C_PA_UART & 0xfff00000,
-	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
-	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
-
-	.init_irq	= s3c6410_init_irq,
-	.map_io		= smdk6410_map_io,
-	.init_machine	= smdk6410_machine_init,
-	.timer		= &s3c24xx_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s3c6410/setup-sdhci.c b/arch/arm/mach-s3c6410/setup-sdhci.c
deleted file mode 100644
index 816d2d9..0000000
--- a/arch/arm/mach-s3c6410/setup-sdhci.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/* linux/arch/arm/mach-s3c6410/setup-sdhci.c
- *
- * Copyright 2008 Simtec Electronics
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C6410 - Helper functions for settign up SDHCI device(s) (HSMMC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
-
-/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
-
-char *s3c6410_hsmmc_clksrcs[4] = {
-	[0] = "hsmmc",
-	[1] = "hsmmc",
-	[2] = "mmc_bus",
-	/* [3] = "48m", - note not successfully used yet */
-};
-
-
-void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
-				    void __iomem *r,
-				    struct mmc_ios *ios,
-				    struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	/* don't need to alter anything acording to card-type */
-
-	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	printk(KERN_INFO "%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
-
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
new file mode 100644
index 0000000..959df38
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -0,0 +1,180 @@
+# Copyright 2008 Openmoko, Inc.
+#	Simtec Electronics, Ben Dooks <ben@simtec.co.uk>
+#
+# Licensed under GPLv2
+
+# temporary until we can eliminate all drivers using it.
+config PLAT_S3C64XX
+	bool
+	depends on ARCH_S3C64XX
+	default y
+	help
+	  Base platform code for any Samsung S3C64XX device
+
+
+# Configuration options for the S3C6410 CPU
+
+config CPU_S3C6400
+	bool
+	help
+	  Enable S3C6400 CPU support
+
+config CPU_S3C6410
+	bool
+	help
+	  Enable S3C6410 CPU support
+
+config S3C64XX_DMA
+	bool "S3C64XX DMA"
+	select S3C_DMA
+
+config S3C64XX_SETUP_SDHCI
+	select S3C64XX_SETUP_SDHCI_GPIO
+	bool
+	help
+	  Internal configuration for default SDHCI setup for S3C6400 and
+	  S3C6410 SoCs.
+
+# platform specific device setup
+
+config S3C64XX_SETUP_I2C0
+	bool
+	default y
+	help
+	  Common setup code for i2c bus 0.
+
+	  Note, currently since i2c0 is always compiled, this setup helper
+	  is always compiled with it.
+
+config S3C64XX_SETUP_I2C1
+	bool
+	help
+	  Common setup code for i2c bus 1.
+
+config S3C64XX_SETUP_FB_24BPP
+	bool
+	help
+	  Common setup code for S3C64XX with an 24bpp RGB display helper.
+
+config S3C64XX_SETUP_SDHCI_GPIO
+	bool
+	help
+	  Common setup code for S3C64XX SDHCI GPIO configurations
+
+# S36400 Macchine support
+
+config MACH_SMDK6400
+       bool "SMDK6400"
+	select CPU_S3C6400
+	select S3C_DEV_HSMMC
+	select S3C_DEV_NAND
+	select S3C64XX_SETUP_SDHCI
+	help
+	  Machine support for the Samsung SMDK6400
+
+# S3C6410 machine support
+
+config MACH_ANW6410
+	bool "A&W6410"
+	select CPU_S3C6410
+	select S3C_DEV_FB
+	select S3C64XX_SETUP_FB_24BPP
+	help
+	  Machine support for the A&W6410
+
+config MACH_SMDK6410
+	bool "SMDK6410"
+	select CPU_S3C6410
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC1
+	select S3C_DEV_I2C1
+	select S3C_DEV_FB
+	select S3C_DEV_USB_HOST
+	select S3C_DEV_USB_HSOTG
+	select S3C64XX_SETUP_SDHCI
+	select S3C64XX_SETUP_I2C1
+	select S3C64XX_SETUP_FB_24BPP
+	help
+	  Machine support for the Samsung SMDK6410
+
+# At least some of the SMDK6410s were shipped with the card detect
+# for the MMC/SD slots connected to the same input. This means that
+# either the boards need to be altered to have channel0 to an alternate
+# configuration or that only one slot can be used.
+
+choice
+	prompt "SMDK6410 MMC/SD slot setup"
+	depends on MACH_SMDK6410
+
+config SMDK6410_SD_CH0
+	bool "Use channel 0 only"
+	depends on MACH_SMDK6410
+	help
+          Select CON7 (channel 0) as the MMC/SD slot, as
+	  at least some SMDK6410 boards come with the
+	  resistors fitted so that the card detects for
+	  channels 0 and 1 are the same.
+
+config SMDK6410_SD_CH1
+	bool "Use channel 1 only"
+	depends on MACH_SMDK6410
+	help
+          Select CON6 (channel 1) as the MMC/SD slot, as
+	  at least some SMDK6410 boards come with the
+	  resistors fitted so that the card detects for
+	  channels 0 and 1 are the same.
+
+endchoice
+
+config SMDK6410_WM1190_EV1
+	bool "Support Wolfson Microelectronics 1190-EV1 PMIC card"
+	depends on MACH_SMDK6410
+	select REGULATOR
+	select REGULATOR_WM8350
+	select S3C24XX_GPIO_EXTRA64
+	select MFD_WM8350_I2C
+	select MFD_WM8350_CONFIG_MODE_0
+	select MFD_WM8350_CONFIG_MODE_3
+	select MFD_WM8352_CONFIG_MODE_0
+	help
+	  The Wolfson Microelectronics 1190-EV1 is a WM835x based PMIC
+	  and audio daughtercard for the Samsung SMDK6410 reference
+	  platform.  Enabling this option will build support for this
+	  module into the kernel.  The presence of the module will be
+	  detected at runtime so the the resulting kernel can be used
+	  with or without the 1190-EV1 fitted.
+
+config SMDK6410_WM1192_EV1
+	bool "Support Wolfson Microelectronics 1192-EV1 PMIC card"
+	depends on MACH_SMDK6410
+	select REGULATOR
+	select REGULATOR_WM831X
+	select S3C24XX_GPIO_EXTRA64
+	select MFD_WM831X
+	help
+	  The Wolfson Microelectronics 1192-EV1 is a WM831x based PMIC
+	  daughtercard for the Samsung SMDK6410 reference platform.
+	  Enabling this option will build support for this module into
+	  the kernel.  The presence of the daughtercard will be
+	  detected at runtime so the the resulting kernel can be used
+	  with or without the 1192-EV1 fitted.
+
+config MACH_NCP
+	bool "NCP"
+	select CPU_S3C6410
+	select S3C_DEV_I2C1
+	select S3C_DEV_HSMMC1
+	select S3C64XX_SETUP_I2C1
+	help
+          Machine support for the Samsung NCP
+
+config MACH_HMT
+	bool "Airgoo HMT"
+	select CPU_S3C6410
+	select S3C_DEV_FB
+	select S3C_DEV_NAND
+	select S3C_DEV_USB_HOST
+	select S3C64XX_SETUP_FB_24BPP
+	select HAVE_PWM
+	help
+	  Machine support for the Airgoo HMT
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
new file mode 100644
index 0000000..3758e15
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -0,0 +1,62 @@
+# arch/arm/mach-s3c64xx/Makefile
+#
+# Copyright 2008 Openmoko, Inc.
+# Copyright 2008 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+# Core files
+obj-y				+= cpu.o
+obj-y				+= clock.o
+obj-y				+= gpiolib.o
+
+# Core support for S3C6400 system
+
+obj-$(CONFIG_CPU_S3C6400)	+= s3c6400.o
+obj-$(CONFIG_CPU_S3C6410)	+= s3c6410.o
+
+obj-y				+= irq.o
+obj-y				+= irq-eint.o
+
+# CPU frequency scaling
+
+obj-$(CONFIG_CPU_FREQ_S3C64XX)  += cpufreq.o
+
+# DMA support
+
+obj-$(CONFIG_S3C64XX_DMA)	+= dma.o
+
+# Device setup
+
+obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o
+obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
+obj-$(CONFIG_S3C64XX_SETUP_SDHCI) += setup-sdhci.o
+obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
+obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
+
+# PM
+
+obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_PM)		+= sleep.o
+obj-$(CONFIG_PM)		+= irq-pm.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_ANW6410)	+= mach-anw6410.o
+obj-$(CONFIG_MACH_SMDK6400)	+= mach-smdk6400.o
+obj-$(CONFIG_MACH_SMDK6410)	+= mach-smdk6410.o
+obj-$(CONFIG_MACH_NCP)		+= mach-ncp.o
+obj-$(CONFIG_MACH_HMT)		+= mach-hmt.o
+
+# device support
+
+obj-y				+= dev-uart.o
+obj-y				+= dev-rtc.o
+obj-y				+= dev-audio.o
+obj-$(CONFIG_S3C_ADC)		+= dev-adc.o
+obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
diff --git a/arch/arm/mach-s3c6400/Makefile.boot b/arch/arm/mach-s3c64xx/Makefile.boot
similarity index 100%
rename from arch/arm/mach-s3c6400/Makefile.boot
rename to arch/arm/mach-s3c64xx/Makefile.boot
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
new file mode 100644
index 0000000..2ac2e7d
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -0,0 +1,809 @@
+/* linux/arch/arm/plat-s3c64xx/clock.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX Base clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <mach/regs-sys.h>
+#include <mach/regs-clock.h>
+#include <mach/pll.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/clock-clksrc.h>
+
+/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
+ * ext_xtal_mux for want of an actual name from the manual.
+*/
+
+static struct clk clk_ext_xtal_mux = {
+	.name		= "ext_xtal",
+	.id		= -1,
+};
+
+#define clk_fin_apll clk_ext_xtal_mux
+#define clk_fin_mpll clk_ext_xtal_mux
+#define clk_fin_epll clk_ext_xtal_mux
+
+#define clk_fout_mpll	clk_mpll
+#define clk_fout_epll	clk_epll
+
+struct clk clk_h2 = {
+	.name		= "hclk2",
+	.id		= -1,
+	.rate		= 0,
+};
+
+struct clk clk_27m = {
+	.name		= "clk_27m",
+	.id		= -1,
+	.rate		= 27000000,
+};
+
+static int clk_48m_ctrl(struct clk *clk, int enable)
+{
+	unsigned long flags;
+	u32 val;
+
+	/* can't rely on clock lock, this register has other usages */
+	local_irq_save(flags);
+
+	val = __raw_readl(S3C64XX_OTHERS);
+	if (enable)
+		val |= S3C64XX_OTHERS_USBMASK;
+	else
+		val &= ~S3C64XX_OTHERS_USBMASK;
+
+	__raw_writel(val, S3C64XX_OTHERS);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+struct clk clk_48m = {
+	.name		= "clk_48m",
+	.id		= -1,
+	.rate		= 48000000,
+	.enable		= clk_48m_ctrl,
+};
+
+static int inline s3c64xx_gate(void __iomem *reg,
+				struct clk *clk,
+				int enable)
+{
+	unsigned int ctrlbit = clk->ctrlbit;
+	u32 con;
+
+	con = __raw_readl(reg);
+
+	if (enable)
+		con |= ctrlbit;
+	else
+		con &= ~ctrlbit;
+
+	__raw_writel(con, reg);
+	return 0;
+}
+
+static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
+{
+	return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
+}
+
+static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
+{
+	return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
+}
+
+int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
+{
+	return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
+}
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_TSADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_IIC,
+	}, {
+		.name		= "iis",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_IIS0,
+	}, {
+		.name		= "iis",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_IIS1,
+	}, {
+#ifdef CONFIG_CPU_S3C6410
+		.name		= "iis",
+		.id		= -1,  /* There's only one IISv4 port */
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C6410_CLKCON_PCLK_IIS2,
+	}, {
+#endif
+		.name		= "spi",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_SPI0,
+	}, {
+		.name		= "spi",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_SPI1,
+	}, {
+		.name		= "spi_48m",
+		.id		= 0,
+		.parent		= &clk_48m,
+		.enable		= s3c64xx_sclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_SCLK_SPI0_48,
+	}, {
+		.name		= "spi_48m",
+		.id		= 1,
+		.parent		= &clk_48m,
+		.enable		= s3c64xx_sclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_SCLK_SPI1_48,
+	}, {
+		.name		= "48m",
+		.id		= 0,
+		.parent		= &clk_48m,
+		.enable		= s3c64xx_sclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_SCLK_MMC0_48,
+	}, {
+		.name		= "48m",
+		.id		= 1,
+		.parent		= &clk_48m,
+		.enable		= s3c64xx_sclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_SCLK_MMC1_48,
+	}, {
+		.name		= "48m",
+		.id		= 2,
+		.parent		= &clk_48m,
+		.enable		= s3c64xx_sclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_SCLK_MMC2_48,
+	}, {
+		.name		= "dma0",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c64xx_hclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_HCLK_DMA0,
+	}, {
+		.name		= "dma1",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c64xx_hclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_HCLK_DMA1,
+	},
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c64xx_hclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_HCLK_LCD,
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_GPIO,
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c64xx_hclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_HCLK_UHOST,
+	}, {
+		.name		= "hsmmc",
+		.id		= 0,
+		.parent		= &clk_h,
+		.enable		= s3c64xx_hclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_HCLK_HSMMC0,
+	}, {
+		.name		= "hsmmc",
+		.id		= 1,
+		.parent		= &clk_h,
+		.enable		= s3c64xx_hclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_HCLK_HSMMC1,
+	}, {
+		.name		= "hsmmc",
+		.id		= 2,
+		.parent		= &clk_h,
+		.enable		= s3c64xx_hclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_HCLK_HSMMC2,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_PWM,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_UART2,
+	}, {
+		.name		= "uart",
+		.id		= 3,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_UART3,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c64xx_pclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_PCLK_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= S3C_CLKCON_PCLK_WDT,
+	}, {
+		.name		= "ac97",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= S3C_CLKCON_PCLK_AC97,
+	}
+};
+
+
+static struct clk clk_fout_apll = {
+	.name		= "fout_apll",
+	.id		= -1,
+};
+
+static struct clk *clk_src_apll_list[] = {
+	[0] = &clk_fin_apll,
+	[1] = &clk_fout_apll,
+};
+
+static struct clksrc_sources clk_src_apll = {
+	.sources	= clk_src_apll_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_apll_list),
+};
+
+static struct clksrc_clk clk_mout_apll = {
+	.clk	= {
+		.name		= "mout_apll",
+		.id		= -1,
+	},
+	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 0, .size = 1  },
+	.sources	= &clk_src_apll,
+};
+
+static struct clk *clk_src_epll_list[] = {
+	[0] = &clk_fin_epll,
+	[1] = &clk_fout_epll,
+};
+
+static struct clksrc_sources clk_src_epll = {
+	.sources	= clk_src_epll_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_epll_list),
+};
+
+static struct clksrc_clk clk_mout_epll = {
+	.clk	= {
+		.name		= "mout_epll",
+		.id		= -1,
+	},
+	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 2, .size = 1  },
+	.sources	= &clk_src_epll,
+};
+
+static struct clk *clk_src_mpll_list[] = {
+	[0] = &clk_fin_mpll,
+	[1] = &clk_fout_mpll,
+};
+
+static struct clksrc_sources clk_src_mpll = {
+	.sources	= clk_src_mpll_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_mpll_list),
+};
+
+static struct clksrc_clk clk_mout_mpll = {
+	.clk = {
+		.name		= "mout_mpll",
+		.id		= -1,
+	},
+	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 1, .size = 1  },
+	.sources	= &clk_src_mpll,
+};
+
+static unsigned int armclk_mask;
+
+static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk->parent);
+	u32 clkdiv;
+
+	/* divisor mask starts at bit0, so no need to shift */
+	clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
+
+	return rate / (clkdiv + 1);
+}
+
+static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
+						unsigned long rate)
+{
+	unsigned long parent = clk_get_rate(clk->parent);
+	u32 div;
+
+	if (parent < rate)
+		return parent;
+
+	div = (parent / rate) - 1;
+	if (div > armclk_mask)
+		div = armclk_mask;
+
+	return parent / (div + 1);
+}
+
+static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent = clk_get_rate(clk->parent);
+	u32 div;
+	u32 val;
+
+	if (rate < parent / (armclk_mask + 1))
+		return -EINVAL;
+
+	rate = clk_round_rate(clk, rate);
+	div = clk_get_rate(clk->parent) / rate;
+
+	val = __raw_readl(S3C_CLK_DIV0);
+	val &= ~armclk_mask;
+	val |= (div - 1);
+	__raw_writel(val, S3C_CLK_DIV0);
+
+	return 0;
+
+}
+
+static struct clk clk_arm = {
+	.name		= "armclk",
+	.id		= -1,
+	.parent		= &clk_mout_apll.clk,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s3c64xx_clk_arm_get_rate,
+		.set_rate	= s3c64xx_clk_arm_set_rate,
+		.round_rate	= s3c64xx_clk_arm_round_rate,
+	},
+};
+
+static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk->parent);
+
+	printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
+
+	if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK)
+		rate /= 2;
+
+	return rate;
+}
+
+static struct clk_ops clk_dout_ops = {
+	.get_rate	= s3c64xx_clk_doutmpll_get_rate,
+};
+
+static struct clk clk_dout_mpll = {
+	.name		= "dout_mpll",
+	.id		= -1,
+	.parent		= &clk_mout_mpll.clk,
+	.ops		= &clk_dout_ops,
+};
+
+static struct clk *clkset_spi_mmc_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll,
+	&clk_fin_epll,
+	&clk_27m,
+};
+
+static struct clksrc_sources clkset_spi_mmc = {
+	.sources	= clkset_spi_mmc_list,
+	.nr_sources	= ARRAY_SIZE(clkset_spi_mmc_list),
+};
+
+static struct clk *clkset_irda_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll,
+	NULL,
+	&clk_27m,
+};
+
+static struct clksrc_sources clkset_irda = {
+	.sources	= clkset_irda_list,
+	.nr_sources	= ARRAY_SIZE(clkset_irda_list),
+};
+
+static struct clk *clkset_uart_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll,
+	NULL,
+	NULL
+};
+
+static struct clksrc_sources clkset_uart = {
+	.sources	= clkset_uart_list,
+	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
+};
+
+static struct clk *clkset_uhost_list[] = {
+	&clk_48m,
+	&clk_mout_epll.clk,
+	&clk_dout_mpll,
+	&clk_fin_epll,
+};
+
+static struct clksrc_sources clkset_uhost = {
+	.sources	= clkset_uhost_list,
+	.nr_sources	= ARRAY_SIZE(clkset_uhost_list),
+};
+
+/* The peripheral clocks are all controlled via clocksource followed
+ * by an optional divider and gate stage. We currently roll this into
+ * one clock which hides the intermediate clock from the mux.
+ *
+ * Note, the JPEG clock can only be an even divider...
+ *
+ * The scaler and LCD clocks depend on the S3C64XX version, and also
+ * have a common parent divisor so are not included here.
+ */
+
+/* clocks that feed other parts of the clock source tree */
+
+static struct clk clk_iis_cd0 = {
+	.name		= "iis_cdclk0",
+	.id		= -1,
+};
+
+static struct clk clk_iis_cd1 = {
+	.name		= "iis_cdclk1",
+	.id		= -1,
+};
+
+static struct clk clk_pcm_cd = {
+	.name		= "pcm_cdclk",
+	.id		= -1,
+};
+
+static struct clk *clkset_audio0_list[] = {
+	[0] = &clk_mout_epll.clk,
+	[1] = &clk_dout_mpll,
+	[2] = &clk_fin_epll,
+	[3] = &clk_iis_cd0,
+	[4] = &clk_pcm_cd,
+};
+
+static struct clksrc_sources clkset_audio0 = {
+	.sources	= clkset_audio0_list,
+	.nr_sources	= ARRAY_SIZE(clkset_audio0_list),
+};
+
+static struct clk *clkset_audio1_list[] = {
+	[0] = &clk_mout_epll.clk,
+	[1] = &clk_dout_mpll,
+	[2] = &clk_fin_epll,
+	[3] = &clk_iis_cd1,
+	[4] = &clk_pcm_cd,
+};
+
+static struct clksrc_sources clkset_audio1 = {
+	.sources	= clkset_audio1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_audio1_list),
+};
+
+static struct clk *clkset_camif_list[] = {
+	&clk_h2,
+};
+
+static struct clksrc_sources clkset_camif = {
+	.sources	= clkset_camif_list,
+	.nr_sources	= ARRAY_SIZE(clkset_camif_list),
+};
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 0,
+			.ctrlbit        = S3C_CLKCON_SCLK_MMC0,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 18, .size = 2  },
+		.reg_div	= { .reg = S3C_CLK_DIV1, .shift = 0, .size = 4  },
+		.sources	= &clkset_spi_mmc,
+	}, {
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 1,
+			.ctrlbit        = S3C_CLKCON_SCLK_MMC1,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 20, .size = 2  },
+		.reg_div	= { .reg = S3C_CLK_DIV1, .shift = 4, .size = 4  },
+		.sources	= &clkset_spi_mmc,
+	}, {
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 2,
+			.ctrlbit        = S3C_CLKCON_SCLK_MMC2,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 22, .size = 2  },
+		.reg_div 	= { .reg = S3C_CLK_DIV1, .shift = 8, .size = 4  },
+		.sources	= &clkset_spi_mmc,
+	}, {
+		.clk	= {
+			.name		= "usb-bus-host",
+			.id		= -1,
+			.ctrlbit        = S3C_CLKCON_SCLK_UHOST,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src 	= { .reg = S3C_CLK_SRC, .shift = 5, .size = 2  },
+		.reg_div	= { .reg = S3C_CLK_DIV1, .shift = 20, .size = 4  },
+		.sources	= &clkset_uhost,
+	}, {
+		.clk	= {
+			.name		= "uclk1",
+			.id		= -1,
+			.ctrlbit        = S3C_CLKCON_SCLK_UART,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 13, .size = 1  },
+		.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4  },
+		.sources	= &clkset_uart,
+	}, {
+/* Where does UCLK0 come from? */
+		.clk	= {
+			.name		= "spi-bus",
+			.id		= 0,
+			.ctrlbit        = S3C_CLKCON_SCLK_SPI0,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 14, .size = 2  },
+		.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4  },
+		.sources	= &clkset_spi_mmc,
+	}, {
+		.clk	= {
+			.name		= "spi-bus",
+			.id		= 1,
+			.ctrlbit        = S3C_CLKCON_SCLK_SPI1,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 16, .size = 2  },
+		.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4  },
+		.sources	= &clkset_spi_mmc,
+	}, {
+		.clk	= {
+			.name		= "audio-bus",
+			.id		= 0,
+			.ctrlbit        = S3C_CLKCON_SCLK_AUDIO0,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 7, .size = 3  },
+		.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 8, .size = 4  },
+		.sources	= &clkset_audio0,
+	}, {
+		.clk	= {
+			.name		= "audio-bus",
+			.id		= 1,
+			.ctrlbit        = S3C_CLKCON_SCLK_AUDIO1,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 10, .size = 3  },
+		.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4  },
+		.sources	= &clkset_audio1,
+	}, {
+		.clk	= {
+			.name		= "irda-bus",
+			.id		= 0,
+			.ctrlbit        = S3C_CLKCON_SCLK_IRDA,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 24, .size = 2  },
+		.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 20, .size = 4  },
+		.sources	= &clkset_irda,
+	}, {
+		.clk	= {
+			.name		= "camera",
+			.id		= -1,
+			.ctrlbit        = S3C_CLKCON_SCLK_CAM,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_div	= { .reg = S3C_CLK_DIV0, .shift = 20, .size = 4  },
+		.reg_src	= { .reg = NULL, .shift = 0, .size = 0  },
+		.sources	= &clkset_camif,
+	},
+};
+
+/* Clock initialisation code */
+
+static struct clksrc_clk *init_parents[] = {
+	&clk_mout_apll,
+	&clk_mout_epll,
+	&clk_mout_mpll,
+};
+
+#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
+
+void __init_or_cpufreq s3c6400_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+	unsigned long xtal;
+	unsigned long fclk;
+	unsigned long hclk;
+	unsigned long hclk2;
+	unsigned long pclk;
+	unsigned long epll;
+	unsigned long apll;
+	unsigned long mpll;
+	unsigned int ptr;
+	u32 clkdiv0;
+
+	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
+
+	clkdiv0 = __raw_readl(S3C_CLK_DIV0);
+	printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0);
+
+	xtal_clk = clk_get(NULL, "xtal");
+	BUG_ON(IS_ERR(xtal_clk));
+
+	xtal = clk_get_rate(xtal_clk);
+	clk_put(xtal_clk);
+
+	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
+
+	/* For now assume the mux always selects the crystal */
+	clk_ext_xtal_mux.parent = xtal_clk;
+
+	epll = s3c6400_get_epll(xtal);
+	mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
+	apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
+
+	fclk = mpll;
+
+	printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
+	       apll, mpll, epll);
+
+	hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
+	hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
+	pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
+
+	printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n",
+	       hclk2, hclk, pclk);
+
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+	clk_fout_apll.rate = apll;
+
+	clk_h2.rate = hclk2;
+	clk_h.rate = hclk;
+	clk_p.rate = pclk;
+	clk_f.rate = fclk;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
+		s3c_set_clksrc(init_parents[ptr], true);
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+		s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks1[] __initdata = {
+	&clk_ext_xtal_mux,
+	&clk_iis_cd0,
+	&clk_iis_cd1,
+	&clk_pcm_cd,
+	&clk_mout_epll.clk,
+	&clk_mout_mpll.clk,
+	&clk_dout_mpll,
+	&clk_arm,
+};
+
+static struct clk *clks[] __initdata = {
+	&clk_ext,
+	&clk_epll,
+	&clk_27m,
+	&clk_48m,
+	&clk_h2,
+};
+
+/**
+ * s3c64xx_register_clocks - register clocks for s3c6400 and s3c6410
+ * @xtal: The rate for the clock crystal feeding the PLLs.
+ * @armclk_divlimit: Divisor mask for ARMCLK.
+ *
+ * Register the clocks for the S3C6400 and S3C6410 SoC range, such
+ * as ARMCLK as well as the necessary parent clocks.
+ *
+ * This call does not setup the clocks, which is left to the
+ * s3c6400_setup_clocks() call which may be needed by the cpufreq
+ * or resume code to re-set the clocks if the bootloader has changed
+ * them.
+ */
+void __init s3c64xx_register_clocks(unsigned long xtal, 
+				    unsigned armclk_divlimit)
+{
+	struct clk *clkp;
+	int ret;
+	int ptr;
+
+	armclk_mask = armclk_divlimit;
+
+	s3c24xx_register_baseclocks(xtal);
+	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+
+	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+
+		(clkp->enable)(clkp, 0);
+	}
+
+	s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+	s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-s3c64xx/cpu.c b/arch/arm/mach-s3c64xx/cpu.c
new file mode 100644
index 0000000..374e45e
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/cpu.c
@@ -0,0 +1,167 @@
+/* linux/arch/arm/plat-s3c64xx/cpu.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX CPU Support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/regs-serial.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+
+#include <mach/s3c6400.h>
+#include <mach/s3c6410.h>
+
+/* table of supported CPUs */
+
+static const char name_s3c6400[] = "S3C6400";
+static const char name_s3c6410[] = "S3C6410";
+
+static struct cpu_table cpu_ids[] __initdata = {
+	{
+		.idcode		= 0x36400000,
+		.idmask		= 0xfffff000,
+		.map_io		= s3c6400_map_io,
+		.init_clocks	= s3c6400_init_clocks,
+		.init_uarts	= s3c6400_init_uarts,
+		.init		= s3c6400_init,
+		.name		= name_s3c6400,
+	}, {
+		.idcode		= 0x36410100,
+		.idmask		= 0xffffff00,
+		.map_io		= s3c6410_map_io,
+		.init_clocks	= s3c6410_init_clocks,
+		.init_uarts	= s3c6410_init_uarts,
+		.init		= s3c6410_init,
+		.name		= name_s3c6410,
+	},
+};
+
+/* minimal IO mapping */
+
+/* see notes on uart map in arch/arm/mach-s3c6400/include/mach/debug-macro.S */
+#define UART_OFFS (S3C_PA_UART & 0xfffff)
+
+static struct map_desc s3c_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S3C_VA_SYS,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_SYSCON),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_MEM,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_SROM),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)(S3C_VA_UART + UART_OFFS),
+		.pfn		= __phys_to_pfn(S3C_PA_UART),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC0,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_VIC0),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC1,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_VIC1),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_TIMER,
+		.pfn		= __phys_to_pfn(S3C_PA_TIMER),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C64XX_VA_GPIO,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_GPIO),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C64XX_VA_MODEM,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_MODEM),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_WATCHDOG,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_WATCHDOG),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_USB_HSPHY,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_USB_HSPHY),
+		.length		= SZ_1K,
+		.type		= MT_DEVICE,
+	},
+};
+
+
+struct sysdev_class s3c64xx_sysclass = {
+	.name	= "s3c64xx-core",
+};
+
+static struct sys_device s3c64xx_sysdev = {
+	.cls	= &s3c64xx_sysclass,
+};
+
+/* uart registration process */
+
+void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no);
+}
+
+/* read cpu identification code */
+
+void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
+{
+	unsigned long idcode;
+
+	/* initialise the io descriptors we need for initialisation */
+	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
+	iotable_init(mach_desc, size);
+
+	idcode = __raw_readl(S3C_VA_SYS + 0x118);
+	if (!idcode) {
+		/* S3C6400 has the ID register in a different place,
+		 * and needs a write before it can be read. */
+
+		__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
+		idcode = __raw_readl(S3C_VA_SYS + 0xA1C);
+	}
+
+	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+}
+
+static __init int s3c64xx_sysdev_init(void)
+{
+	sysdev_class_register(&s3c64xx_sysclass);
+	return sysdev_register(&s3c64xx_sysdev);
+}
+
+core_initcall(s3c64xx_sysdev_init);
diff --git a/arch/arm/plat-s3c64xx/cpufreq.c b/arch/arm/mach-s3c64xx/cpufreq.c
similarity index 100%
rename from arch/arm/plat-s3c64xx/cpufreq.c
rename to arch/arm/mach-s3c64xx/cpufreq.c
diff --git a/arch/arm/mach-s3c64xx/dev-adc.c b/arch/arm/mach-s3c64xx/dev-adc.c
new file mode 100644
index 0000000..fafef9b
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/dev-adc.c
@@ -0,0 +1,46 @@
+/* linux/arch/arm/plat-s3c64xx/dev-adc.c
+ *
+ * Copyright 2010 Maurus Cuelenaere
+ *
+ * S3C64xx series device definition for ADC device
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/adc.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+static struct resource s3c_adc_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_ADC,
+		.end   = S3C64XX_PA_ADC + SZ_256 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TC,
+		.end   = IRQ_TC,
+		.flags = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start = IRQ_ADC,
+		.end   = IRQ_ADC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device s3c_device_adc = {
+	.name		= "s3c64xx-adc",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_adc_resource),
+	.resource	= s3c_adc_resource,
+};
diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c
new file mode 100644
index 0000000..c3e9e73
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/dev-audio.c
@@ -0,0 +1,335 @@
+/* linux/arch/arm/plat-s3c/dev-audio.c
+ *
+ * Copyright 2009 Wolfson Microelectronics
+ *      Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+#include <mach/dma.h>
+#include <mach/gpio.h>
+
+#include <plat/devs.h>
+#include <plat/audio.h>
+#include <plat/gpio-cfg.h>
+
+#include <mach/gpio-bank-c.h>
+#include <mach/gpio-bank-d.h>
+#include <mach/gpio-bank-e.h>
+#include <mach/gpio-bank-h.h>
+
+static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev)
+{
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK);
+		s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI);
+		s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0);
+		break;
+	case 1:
+		s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK);
+		s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI);
+		s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0);
+	default:
+		printk(KERN_DEBUG "Invalid I2S Controller number!");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int s3c64xx_i2sv4_cfg_gpio(struct platform_device *pdev)
+{
+	s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0);
+	s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1);
+	s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2);
+	s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK);
+	s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK);
+	s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK);
+	s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI);
+
+	return 0;
+}
+
+static struct resource s3c64xx_iis0_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_IIS0,
+		.end   = S3C64XX_PA_IIS0 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = DMACH_I2S0_OUT,
+		.end   = DMACH_I2S0_OUT,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = DMACH_I2S0_IN,
+		.end   = DMACH_I2S0_IN,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct s3c_audio_pdata s3c_i2s0_pdata = {
+	.cfg_gpio = s3c64xx_i2sv3_cfg_gpio,
+};
+
+struct platform_device s3c64xx_device_iis0 = {
+	.name		  = "s3c64xx-iis",
+	.id		  = 0,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_iis0_resource),
+	.resource	  = s3c64xx_iis0_resource,
+	.dev = {
+		.platform_data = &s3c_i2s0_pdata,
+	},
+};
+EXPORT_SYMBOL(s3c64xx_device_iis0);
+
+static struct resource s3c64xx_iis1_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_IIS1,
+		.end   = S3C64XX_PA_IIS1 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = DMACH_I2S1_OUT,
+		.end   = DMACH_I2S1_OUT,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = DMACH_I2S1_IN,
+		.end   = DMACH_I2S1_IN,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct s3c_audio_pdata s3c_i2s1_pdata = {
+	.cfg_gpio = s3c64xx_i2sv3_cfg_gpio,
+};
+
+struct platform_device s3c64xx_device_iis1 = {
+	.name		  = "s3c64xx-iis",
+	.id		  = 1,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_iis1_resource),
+	.resource	  = s3c64xx_iis1_resource,
+	.dev = {
+		.platform_data = &s3c_i2s1_pdata,
+	},
+};
+EXPORT_SYMBOL(s3c64xx_device_iis1);
+
+static struct resource s3c64xx_iisv4_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_IISV4,
+		.end   = S3C64XX_PA_IISV4 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = DMACH_HSI_I2SV40_TX,
+		.end   = DMACH_HSI_I2SV40_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = DMACH_HSI_I2SV40_RX,
+		.end   = DMACH_HSI_I2SV40_RX,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct s3c_audio_pdata s3c_i2sv4_pdata = {
+	.cfg_gpio = s3c64xx_i2sv4_cfg_gpio,
+};
+
+struct platform_device s3c64xx_device_iisv4 = {
+	.name		  = "s3c64xx-iis-v4",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_iisv4_resource),
+	.resource	  = s3c64xx_iisv4_resource,
+	.dev = {
+		.platform_data = &s3c_i2sv4_pdata,
+	},
+};
+EXPORT_SYMBOL(s3c64xx_device_iisv4);
+
+
+/* PCM Controller platform_devices */
+
+static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
+{
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_PCM0_SCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_PCM0_EXTCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_PCM0_FSYNC);
+		s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_PCM0_SIN);
+		s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_PCM0_SOUT);
+		break;
+	case 1:
+		s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_PCM1_SCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_PCM1_EXTCLK);
+		s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_PCM1_FSYNC);
+		s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_PCM1_SIN);
+		s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT);
+		break;
+	default:
+		printk(KERN_DEBUG "Invalid PCM Controller number!");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct resource s3c64xx_pcm0_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_PCM0,
+		.end   = S3C64XX_PA_PCM0 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = DMACH_PCM0_TX,
+		.end   = DMACH_PCM0_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = DMACH_PCM0_RX,
+		.end   = DMACH_PCM0_RX,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct s3c_audio_pdata s3c_pcm0_pdata = {
+	.cfg_gpio = s3c64xx_pcm_cfg_gpio,
+};
+
+struct platform_device s3c64xx_device_pcm0 = {
+	.name		  = "samsung-pcm",
+	.id		  = 0,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_pcm0_resource),
+	.resource	  = s3c64xx_pcm0_resource,
+	.dev = {
+		.platform_data = &s3c_pcm0_pdata,
+	},
+};
+EXPORT_SYMBOL(s3c64xx_device_pcm0);
+
+static struct resource s3c64xx_pcm1_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_PCM1,
+		.end   = S3C64XX_PA_PCM1 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = DMACH_PCM1_TX,
+		.end   = DMACH_PCM1_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = DMACH_PCM1_RX,
+		.end   = DMACH_PCM1_RX,
+		.flags = IORESOURCE_DMA,
+	},
+};
+
+static struct s3c_audio_pdata s3c_pcm1_pdata = {
+	.cfg_gpio = s3c64xx_pcm_cfg_gpio,
+};
+
+struct platform_device s3c64xx_device_pcm1 = {
+	.name		  = "samsung-pcm",
+	.id		  = 1,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_pcm1_resource),
+	.resource	  = s3c64xx_pcm1_resource,
+	.dev = {
+		.platform_data = &s3c_pcm1_pdata,
+	},
+};
+EXPORT_SYMBOL(s3c64xx_device_pcm1);
+
+/* AC97 Controller platform devices */
+
+static int s3c64xx_ac97_cfg_gpd(struct platform_device *pdev)
+{
+	s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_AC97_BITCLK);
+	s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_AC97_nRESET);
+	s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_AC97_SYNC);
+	s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_AC97_SDI);
+	s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_AC97_SDO);
+
+	return 0;
+}
+
+static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev)
+{
+	s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_AC97_BITCLK);
+	s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_AC97_nRESET);
+	s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_AC97_SYNC);
+	s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_AC97_SDI);
+	s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_AC97_SDO);
+
+	return 0;
+}
+
+static struct resource s3c64xx_ac97_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_AC97,
+		.end   = S3C64XX_PA_AC97 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = DMACH_AC97_PCMOUT,
+		.end   = DMACH_AC97_PCMOUT,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = DMACH_AC97_PCMIN,
+		.end   = DMACH_AC97_PCMIN,
+		.flags = IORESOURCE_DMA,
+	},
+	[3] = {
+		.start = DMACH_AC97_MICIN,
+		.end   = DMACH_AC97_MICIN,
+		.flags = IORESOURCE_DMA,
+	},
+	[4] = {
+		.start = IRQ_AC97,
+		.end   = IRQ_AC97,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_audio_pdata s3c_ac97_pdata;
+
+static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s3c64xx_device_ac97 = {
+	.name		  = "s3c-ac97",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_ac97_resource),
+	.resource	  = s3c64xx_ac97_resource,
+	.dev = {
+		.platform_data = &s3c_ac97_pdata,
+		.dma_mask = &s3c64xx_ac97_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+EXPORT_SYMBOL(s3c64xx_device_ac97);
+
+void __init s3c64xx_ac97_setup_gpio(int num)
+{
+	if (num == S3C64XX_AC97_GPD)
+		s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpd;
+	else
+		s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe;
+}
diff --git a/arch/arm/mach-s3c64xx/dev-rtc.c b/arch/arm/mach-s3c64xx/dev-rtc.c
new file mode 100644
index 0000000..b9e7a05
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/dev-rtc.c
@@ -0,0 +1,43 @@
+/* linux/arch/arm/plat-s3c64xx/dev-rtc.c
+ *
+ * Copyright 2009 by Maurus Cuelenaere <mcuelenaere@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+static struct resource s3c_rtc_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_RTC,
+		.end   = S3C64XX_PA_RTC + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_RTC_ALARM,
+		.end   = IRQ_RTC_ALARM,
+		.flags = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start = IRQ_RTC_TIC,
+		.end   = IRQ_RTC_TIC,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+struct platform_device s3c_device_rtc = {
+	.name		  = "s3c64xx-rtc",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_rtc_resource),
+	.resource	  = s3c_rtc_resource,
+};
+EXPORT_SYMBOL(s3c_device_rtc);
diff --git a/arch/arm/mach-s3c64xx/dev-spi.c b/arch/arm/mach-s3c64xx/dev-spi.c
new file mode 100644
index 0000000..29c32d0
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/dev-spi.c
@@ -0,0 +1,182 @@
+/* linux/arch/arm/plat-s3c64xx/dev-spi.c
+ *
+ * Copyright (C) 2009 Samsung Electronics Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/dma.h>
+#include <mach/map.h>
+#include <mach/gpio.h>
+#include <mach/gpio-bank-c.h>
+#include <mach/spi-clocks.h>
+
+#include <plat/s3c64xx-spi.h>
+#include <plat/gpio-cfg.h>
+#include <plat/irqs.h>
+
+static char *spi_src_clks[] = {
+	[S3C64XX_SPI_SRCCLK_PCLK] = "pclk",
+	[S3C64XX_SPI_SRCCLK_SPIBUS] = "spi-bus",
+	[S3C64XX_SPI_SRCCLK_48M] = "spi_48m",
+};
+
+/* SPI Controller platform_devices */
+
+/* Since we emulate multi-cs capability, we do not touch the GPC-3,7.
+ * The emulated CS is toggled by board specific mechanism, as it can
+ * be either some immediate GPIO or some signal out of some other
+ * chip in between ... or some yet another way.
+ * We simply do not assume anything about CS.
+ */
+static int s3c64xx_spi_cfg_gpio(struct platform_device *pdev)
+{
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin(S3C64XX_GPC(0), S3C64XX_GPC0_SPI_MISO0);
+		s3c_gpio_cfgpin(S3C64XX_GPC(1), S3C64XX_GPC1_SPI_CLKO);
+		s3c_gpio_cfgpin(S3C64XX_GPC(2), S3C64XX_GPC2_SPI_MOSIO);
+		s3c_gpio_setpull(S3C64XX_GPC(0), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S3C64XX_GPC(1), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S3C64XX_GPC(2), S3C_GPIO_PULL_UP);
+		break;
+
+	case 1:
+		s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_SPI_MISO1);
+		s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_SPI_CLK1);
+		s3c_gpio_cfgpin(S3C64XX_GPC(6), S3C64XX_GPC6_SPI_MOSI1);
+		s3c_gpio_setpull(S3C64XX_GPC(4), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S3C64XX_GPC(5), S3C_GPIO_PULL_UP);
+		s3c_gpio_setpull(S3C64XX_GPC(6), S3C_GPIO_PULL_UP);
+		break;
+
+	default:
+		dev_err(&pdev->dev, "Invalid SPI Controller number!");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct resource s3c64xx_spi0_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_SPI0,
+		.end   = S3C64XX_PA_SPI0 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = DMACH_SPI0_TX,
+		.end   = DMACH_SPI0_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = DMACH_SPI0_RX,
+		.end   = DMACH_SPI0_RX,
+		.flags = IORESOURCE_DMA,
+	},
+	[3] = {
+		.start = IRQ_SPI0,
+		.end   = IRQ_SPI0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c64xx_spi_info s3c64xx_spi0_pdata = {
+	.cfg_gpio = s3c64xx_spi_cfg_gpio,
+	.fifo_lvl_mask = 0x7f,
+	.rx_lvl_offset = 13,
+};
+
+static u64 spi_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s3c64xx_device_spi0 = {
+	.name		  = "s3c64xx-spi",
+	.id		  = 0,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_spi0_resource),
+	.resource	  = s3c64xx_spi0_resource,
+	.dev = {
+		.dma_mask		= &spi_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data = &s3c64xx_spi0_pdata,
+	},
+};
+EXPORT_SYMBOL(s3c64xx_device_spi0);
+
+static struct resource s3c64xx_spi1_resource[] = {
+	[0] = {
+		.start = S3C64XX_PA_SPI1,
+		.end   = S3C64XX_PA_SPI1 + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = DMACH_SPI1_TX,
+		.end   = DMACH_SPI1_TX,
+		.flags = IORESOURCE_DMA,
+	},
+	[2] = {
+		.start = DMACH_SPI1_RX,
+		.end   = DMACH_SPI1_RX,
+		.flags = IORESOURCE_DMA,
+	},
+	[3] = {
+		.start = IRQ_SPI1,
+		.end   = IRQ_SPI1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c64xx_spi_info s3c64xx_spi1_pdata = {
+	.cfg_gpio = s3c64xx_spi_cfg_gpio,
+	.fifo_lvl_mask = 0x7f,
+	.rx_lvl_offset = 13,
+};
+
+struct platform_device s3c64xx_device_spi1 = {
+	.name		  = "s3c64xx-spi",
+	.id		  = 1,
+	.num_resources	  = ARRAY_SIZE(s3c64xx_spi1_resource),
+	.resource	  = s3c64xx_spi1_resource,
+	.dev = {
+		.dma_mask		= &spi_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data = &s3c64xx_spi1_pdata,
+	},
+};
+EXPORT_SYMBOL(s3c64xx_device_spi1);
+
+void __init s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
+{
+	struct s3c64xx_spi_info *pd;
+
+	/* Reject invalid configuration */
+	if (!num_cs || src_clk_nr < 0
+			|| src_clk_nr > S3C64XX_SPI_SRCCLK_48M) {
+		printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
+		return;
+	}
+
+	switch (cntrlr) {
+	case 0:
+		pd = &s3c64xx_spi0_pdata;
+		break;
+	case 1:
+		pd = &s3c64xx_spi1_pdata;
+		break;
+	default:
+		printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
+							__func__, cntrlr);
+		return;
+	}
+
+	pd->num_cs = num_cs;
+	pd->src_clk_nr = src_clk_nr;
+	pd->src_clk_name = spi_src_clks[src_clk_nr];
+}
diff --git a/arch/arm/mach-s3c64xx/dev-uart.c b/arch/arm/mach-s3c64xx/dev-uart.c
new file mode 100644
index 0000000..f797f74
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/dev-uart.c
@@ -0,0 +1,147 @@
+/* linux/arch/arm/plat-s3c64xx/dev-uart.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Base S3C64XX UART resource and device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+/* Serial port registrations */
+
+/* 64xx uarts are closer together */
+
+static struct resource s3c64xx_uart0_resource[] = {
+	[0] = {
+		.start	= S3C_PA_UART0,
+		.end	= S3C_PA_UART0 + 0x100,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_S3CUART_RX0,
+		.end	= IRQ_S3CUART_RX0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_S3CUART_TX0,
+		.end	= IRQ_S3CUART_TX0,
+		.flags	= IORESOURCE_IRQ,
+
+	},
+	[3] = {
+		.start	= IRQ_S3CUART_ERR0,
+		.end	= IRQ_S3CUART_ERR0,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c64xx_uart1_resource[] = {
+	[0] = {
+		.start = S3C_PA_UART1,
+		.end   = S3C_PA_UART1 + 0x100,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_S3CUART_RX1,
+		.end	= IRQ_S3CUART_RX1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_S3CUART_TX1,
+		.end	= IRQ_S3CUART_TX1,
+		.flags	= IORESOURCE_IRQ,
+
+	},
+	[3] = {
+		.start	= IRQ_S3CUART_ERR1,
+		.end	= IRQ_S3CUART_ERR1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource s3c6xx_uart2_resource[] = {
+	[0] = {
+		.start = S3C_PA_UART2,
+		.end   = S3C_PA_UART2 + 0x100,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_S3CUART_RX2,
+		.end	= IRQ_S3CUART_RX2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_S3CUART_TX2,
+		.end	= IRQ_S3CUART_TX2,
+		.flags	= IORESOURCE_IRQ,
+
+	},
+	[3] = {
+		.start	= IRQ_S3CUART_ERR2,
+		.end	= IRQ_S3CUART_ERR2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource s3c64xx_uart3_resource[] = {
+	[0] = {
+		.start = S3C_PA_UART3,
+		.end   = S3C_PA_UART3 + 0x100,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_S3CUART_RX3,
+		.end	= IRQ_S3CUART_RX3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_S3CUART_TX3,
+		.end	= IRQ_S3CUART_TX3,
+		.flags	= IORESOURCE_IRQ,
+
+	},
+	[3] = {
+		.start	= IRQ_S3CUART_ERR3,
+		.end	= IRQ_S3CUART_ERR3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+
+struct s3c24xx_uart_resources s3c64xx_uart_resources[] __initdata = {
+	[0] = {
+		.resources	= s3c64xx_uart0_resource,
+		.nr_resources	= ARRAY_SIZE(s3c64xx_uart0_resource),
+	},
+	[1] = {
+		.resources	= s3c64xx_uart1_resource,
+		.nr_resources	= ARRAY_SIZE(s3c64xx_uart1_resource),
+	},
+	[2] = {
+		.resources	= s3c6xx_uart2_resource,
+		.nr_resources	= ARRAY_SIZE(s3c6xx_uart2_resource),
+	},
+	[3] = {
+		.resources	= s3c64xx_uart3_resource,
+		.nr_resources	= ARRAY_SIZE(s3c64xx_uart3_resource),
+	},
+};
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
new file mode 100644
index 0000000..b62bdf1
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/dma.c
@@ -0,0 +1,749 @@
+/* linux/arch/arm/plat-s3c64xx/dma.c
+ *
+ * Copyright 2009 Openmoko, Inc.
+ * Copyright 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX DMA core
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/dmapool.h>
+#include <linux/sysdev.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/dma.h>
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+#include <mach/regs-sys.h>
+
+#include <asm/hardware/pl080.h>
+
+/* dma channel state information */
+
+struct s3c64xx_dmac {
+	struct sys_device	 sysdev;
+	struct clk		*clk;
+	void __iomem		*regs;
+	struct s3c2410_dma_chan *channels;
+	enum dma_ch		 chanbase;
+};
+
+/* pool to provide LLI buffers */
+static struct dma_pool *dma_pool;
+
+/* Debug configuration and code */
+
+static unsigned char debug_show_buffs = 0;
+
+static void dbg_showchan(struct s3c2410_dma_chan *chan)
+{
+	pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n",
+		 chan->number,
+		 readl(chan->regs + PL080_CH_SRC_ADDR),
+		 readl(chan->regs + PL080_CH_DST_ADDR),
+		 readl(chan->regs + PL080_CH_LLI),
+		 readl(chan->regs + PL080_CH_CONTROL),
+		 readl(chan->regs + PL080S_CH_CONTROL2),
+		 readl(chan->regs + PL080S_CH_CONFIG));
+}
+
+static void show_lli(struct pl080s_lli *lli)
+{
+	pr_debug("LLI[%p] %08x->%08x, NL %08x C %08x,%08x\n",
+		 lli, lli->src_addr, lli->dst_addr, lli->next_lli,
+		 lli->control0, lli->control1);
+}
+
+static void dbg_showbuffs(struct s3c2410_dma_chan *chan)
+{
+	struct s3c64xx_dma_buff *ptr;
+	struct s3c64xx_dma_buff *end;
+
+	pr_debug("DMA%d: buffs next %p, curr %p, end %p\n",
+		 chan->number, chan->next, chan->curr, chan->end);
+
+	ptr = chan->next;
+	end = chan->end;
+
+	if (debug_show_buffs) {
+		for (; ptr != NULL; ptr = ptr->next) {
+			pr_debug("DMA%d: %08x ",
+				 chan->number, ptr->lli_dma);
+			show_lli(ptr->lli);
+		}
+	}
+}
+
+/* End of Debug */
+
+static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel)
+{
+	struct s3c2410_dma_chan *chan;
+	unsigned int start, offs;
+
+	start = 0;
+
+	if (channel >= DMACH_PCM1_TX)
+		start = 8;
+
+	for (offs = 0; offs < 8; offs++) {
+		chan = &s3c2410_chans[start + offs];
+		if (!chan->in_use)
+			goto found;
+	}
+
+	return NULL;
+
+found:
+	s3c_dma_chan_map[channel] = chan;
+	return chan;
+}
+
+int s3c2410_dma_config(unsigned int channel, int xferunit)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	switch (xferunit) {
+	case 1:
+		chan->hw_width = 0;
+		break;
+	case 2:
+		chan->hw_width = 1;
+		break;
+	case 4:
+		chan->hw_width = 2;
+		break;
+	default:
+		printk(KERN_ERR "%s: illegal width %d\n", __func__, xferunit);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_config);
+
+static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
+				 struct pl080s_lli *lli,
+				 dma_addr_t data, int size)
+{
+	dma_addr_t src, dst;
+	u32 control0, control1;
+
+	switch (chan->source) {
+	case S3C2410_DMASRC_HW:
+		src = chan->dev_addr;
+		dst = data;
+		control0 = PL080_CONTROL_SRC_AHB2;
+		control0 |= PL080_CONTROL_DST_INCR;
+		break;
+
+	case S3C2410_DMASRC_MEM:
+		src = data;
+		dst = chan->dev_addr;
+		control0 = PL080_CONTROL_DST_AHB2;
+		control0 |= PL080_CONTROL_SRC_INCR;
+		break;
+	default:
+		BUG();
+	}
+
+	/* note, we do not currently setup any of the burst controls */
+
+	control1 = size >> chan->hw_width;	/* size in no of xfers */
+	control0 |= PL080_CONTROL_PROT_SYS;	/* always in priv. mode */
+	control0 |= PL080_CONTROL_TC_IRQ_EN;	/* always fire IRQ */
+	control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT;
+	control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT;
+
+	lli->src_addr = src;
+	lli->dst_addr = dst;
+	lli->next_lli = 0;
+	lli->control0 = control0;
+	lli->control1 = control1;
+}
+
+static void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,
+				struct pl080s_lli *lli)
+{
+	void __iomem *regs = chan->regs;
+
+	pr_debug("%s: LLI %p => regs\n", __func__, lli);
+	show_lli(lli);
+
+	writel(lli->src_addr, regs + PL080_CH_SRC_ADDR);
+	writel(lli->dst_addr, regs + PL080_CH_DST_ADDR);
+	writel(lli->next_lli, regs + PL080_CH_LLI);
+	writel(lli->control0, regs + PL080_CH_CONTROL);
+	writel(lli->control1, regs + PL080S_CH_CONTROL2);
+}
+
+static int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)
+{
+	struct s3c64xx_dmac *dmac = chan->dmac;
+	u32 config;
+	u32 bit = chan->bit;
+
+	dbg_showchan(chan);
+
+	pr_debug("%s: clearing interrupts\n", __func__);
+
+	/* clear interrupts */
+	writel(bit, dmac->regs + PL080_TC_CLEAR);
+	writel(bit, dmac->regs + PL080_ERR_CLEAR);
+
+	pr_debug("%s: starting channel\n", __func__);
+
+	config = readl(chan->regs + PL080S_CH_CONFIG);
+	config |= PL080_CONFIG_ENABLE;
+
+	pr_debug("%s: writing config %08x\n", __func__, config);
+	writel(config, chan->regs + PL080S_CH_CONFIG);
+
+	return 0;
+}
+
+static int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)
+{
+	u32 config;
+	int timeout;
+
+	pr_debug("%s: stopping channel\n", __func__);
+
+	dbg_showchan(chan);
+
+	config = readl(chan->regs + PL080S_CH_CONFIG);
+	config |= PL080_CONFIG_HALT;
+	writel(config, chan->regs + PL080S_CH_CONFIG);
+
+	timeout = 1000;
+	do {
+		config = readl(chan->regs + PL080S_CH_CONFIG);
+		pr_debug("%s: %d - config %08x\n", __func__, timeout, config);
+		if (config & PL080_CONFIG_ACTIVE)
+			udelay(10);
+		else
+			break;
+		} while (--timeout > 0);
+
+	if (config & PL080_CONFIG_ACTIVE) {
+		printk(KERN_ERR "%s: channel still active\n", __func__);
+		return -EFAULT;
+	}
+
+	config = readl(chan->regs + PL080S_CH_CONFIG);
+	config &= ~PL080_CONFIG_ENABLE;
+	writel(config, chan->regs + PL080S_CH_CONFIG);
+
+	return 0;
+}
+
+static inline void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan,
+					 struct s3c64xx_dma_buff *buf,
+					 enum s3c2410_dma_buffresult result)
+{
+	if (chan->callback_fn != NULL)
+		(chan->callback_fn)(chan, buf->pw, 0, result);
+}
+
+static void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff)
+{
+	dma_pool_free(dma_pool, buff->lli, buff->lli_dma);
+	kfree(buff);
+}
+
+static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)
+{
+	struct s3c64xx_dma_buff *buff, *next;
+	u32 config;
+
+	dbg_showchan(chan);
+
+	pr_debug("%s: flushing channel\n", __func__);
+
+	config = readl(chan->regs + PL080S_CH_CONFIG);
+	config &= ~PL080_CONFIG_ENABLE;
+	writel(config, chan->regs + PL080S_CH_CONFIG);
+
+	/* dump all the buffers associated with this channel */
+
+	for (buff = chan->curr; buff != NULL; buff = next) {
+		next = buff->next;
+		pr_debug("%s: buff %p (next %p)\n", __func__, buff, buff->next);
+
+		s3c64xx_dma_bufffdone(chan, buff, S3C2410_RES_ABORT);
+		s3c64xx_dma_freebuff(buff);
+	}
+
+	chan->curr = chan->next = chan->end = NULL;
+
+	return 0;
+}
+
+int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	WARN_ON(!chan);
+	if (!chan)
+		return -EINVAL;
+
+	switch (op) {
+	case S3C2410_DMAOP_START:
+		return s3c64xx_dma_start(chan);
+
+	case S3C2410_DMAOP_STOP:
+		return s3c64xx_dma_stop(chan);
+
+	case S3C2410_DMAOP_FLUSH:
+		return s3c64xx_dma_flush(chan);
+
+	/* belive PAUSE/RESUME are no-ops */
+	case S3C2410_DMAOP_PAUSE:
+	case S3C2410_DMAOP_RESUME:
+	case S3C2410_DMAOP_STARTED:
+	case S3C2410_DMAOP_TIMEOUT:
+		return 0;
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(s3c2410_dma_ctrl);
+
+/* s3c2410_dma_enque
+ *
+ */
+
+int s3c2410_dma_enqueue(unsigned int channel, void *id,
+			dma_addr_t data, int size)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+	struct s3c64xx_dma_buff *next;
+	struct s3c64xx_dma_buff *buff;
+	struct pl080s_lli *lli;
+	unsigned long flags;
+	int ret;
+
+	WARN_ON(!chan);
+	if (!chan)
+		return -EINVAL;
+
+	buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_ATOMIC);
+	if (!buff) {
+		printk(KERN_ERR "%s: no memory for buffer\n", __func__);
+		return -ENOMEM;
+	}
+
+	lli = dma_pool_alloc(dma_pool, GFP_ATOMIC, &buff->lli_dma);
+	if (!lli) {
+		printk(KERN_ERR "%s: no memory for lli\n", __func__);
+		ret = -ENOMEM;
+		goto err_buff;
+	}
+
+	pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n",
+		 __func__, buff, data, lli, (u32)buff->lli_dma, size);
+
+	buff->lli = lli;
+	buff->pw = id;
+
+	s3c64xx_dma_fill_lli(chan, lli, data, size);
+
+	local_irq_save(flags);
+
+	if ((next = chan->next) != NULL) {
+		struct s3c64xx_dma_buff *end = chan->end;
+		struct pl080s_lli *endlli = end->lli;
+
+		pr_debug("enquing onto channel\n");
+
+		end->next = buff;
+		endlli->next_lli = buff->lli_dma;
+
+		if (chan->flags & S3C2410_DMAF_CIRCULAR) {
+			struct s3c64xx_dma_buff *curr = chan->curr;
+			lli->next_lli = curr->lli_dma;
+		}
+
+		if (next == chan->curr) {
+			writel(buff->lli_dma, chan->regs + PL080_CH_LLI);
+			chan->next = buff;
+		}
+
+		show_lli(endlli);
+		chan->end = buff;
+	} else {
+		pr_debug("enquing onto empty channel\n");
+
+		chan->curr = buff;
+		chan->next = buff;
+		chan->end = buff;
+
+		s3c64xx_lli_to_regs(chan, lli);
+	}
+
+	local_irq_restore(flags);
+
+	show_lli(lli);
+
+	dbg_showchan(chan);
+	dbg_showbuffs(chan);
+	return 0;
+
+err_buff:
+	kfree(buff);
+	return ret;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_enqueue);
+
+
+int s3c2410_dma_devconfig(int channel,
+			  enum s3c2410_dmasrc source,
+			  unsigned long devaddr)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+	u32 peripheral;
+	u32 config = 0;
+
+	pr_debug("%s: channel %d, source %d, dev %08lx, chan %p\n",
+		 __func__, channel, source, devaddr, chan);
+
+	WARN_ON(!chan);
+	if (!chan)
+		return -EINVAL;
+
+	peripheral = (chan->peripheral & 0xf);
+	chan->source = source;
+	chan->dev_addr = devaddr;
+
+	pr_debug("%s: peripheral %d\n", __func__, peripheral);
+
+	switch (source) {
+	case S3C2410_DMASRC_HW:
+		config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+		config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
+		break;
+	case S3C2410_DMASRC_MEM:
+		config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
+		config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
+		break;
+	default:
+		printk(KERN_ERR "%s: bad source\n", __func__);
+		return -EINVAL;
+	}
+
+	/* allow TC and ERR interrupts */
+	config |= PL080_CONFIG_TC_IRQ_MASK;
+	config |= PL080_CONFIG_ERR_IRQ_MASK;
+
+	pr_debug("%s: config %08x\n", __func__, config);
+
+	writel(config, chan->regs + PL080S_CH_CONFIG);
+
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_devconfig);
+
+
+int s3c2410_dma_getposition(unsigned int channel,
+			    dma_addr_t *src, dma_addr_t *dst)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	WARN_ON(!chan);
+	if (!chan)
+		return -EINVAL;
+
+	if (src != NULL)
+		*src = readl(chan->regs + PL080_CH_SRC_ADDR);
+
+	if (dst != NULL)
+		*dst = readl(chan->regs + PL080_CH_DST_ADDR);
+
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_getposition);
+
+/* s3c2410_request_dma
+ *
+ * get control of an dma channel
+*/
+
+int s3c2410_dma_request(unsigned int channel,
+			struct s3c2410_dma_client *client,
+			void *dev)
+{
+	struct s3c2410_dma_chan *chan;
+	unsigned long flags;
+
+	pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
+		 channel, client->name, dev);
+
+	local_irq_save(flags);
+
+	chan = s3c64xx_dma_map_channel(channel);
+	if (chan == NULL) {
+		local_irq_restore(flags);
+		return -EBUSY;
+	}
+
+	dbg_showchan(chan);
+
+	chan->client = client;
+	chan->in_use = 1;
+	chan->peripheral = channel;
+
+	local_irq_restore(flags);
+
+	/* need to setup */
+
+	pr_debug("%s: channel initialised, %p\n", __func__, chan);
+
+	return chan->number | DMACH_LOW_LEVEL;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_request);
+
+/* s3c2410_dma_free
+ *
+ * release the given channel back to the system, will stop and flush
+ * any outstanding transfers, and ensure the channel is ready for the
+ * next claimant.
+ *
+ * Note, although a warning is currently printed if the freeing client
+ * info is not the same as the registrant's client info, the free is still
+ * allowed to go through.
+*/
+
+int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+	unsigned long flags;
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	if (chan->client != client) {
+		printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
+		       channel, chan->client, client);
+	}
+
+	/* sort out stopping and freeing the channel */
+
+
+	chan->client = NULL;
+	chan->in_use = 0;
+
+	if (!(channel & DMACH_LOW_LEVEL))
+		s3c_dma_chan_map[channel] = NULL;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_free);
+
+static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
+{
+	struct s3c64xx_dmac *dmac = pw;
+	struct s3c2410_dma_chan *chan;
+	enum s3c2410_dma_buffresult res;
+	u32 tcstat, errstat;
+	u32 bit;
+	int offs;
+
+	tcstat = readl(dmac->regs + PL080_TC_STATUS);
+	errstat = readl(dmac->regs + PL080_ERR_STATUS);
+
+	for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) {
+		struct s3c64xx_dma_buff *buff;
+
+		if (!(errstat & bit) && !(tcstat & bit))
+			continue;
+
+		chan = dmac->channels + offs;
+		res = S3C2410_RES_ERR;
+
+		if (tcstat & bit) {
+			writel(bit, dmac->regs + PL080_TC_CLEAR);
+			res = S3C2410_RES_OK;
+		}
+
+		if (errstat & bit)
+			writel(bit, dmac->regs + PL080_ERR_CLEAR);
+
+		/* 'next' points to the buffer that is next to the
+		 * currently active buffer.
+		 * For CIRCULAR queues, 'next' will be same as 'curr'
+		 * when 'end' is the active buffer.
+		 */
+		buff = chan->curr;
+		while (buff && buff != chan->next
+				&& buff->next != chan->next)
+			buff = buff->next;
+
+		if (!buff)
+			BUG();
+
+		if (buff == chan->next)
+			buff = chan->end;
+
+		s3c64xx_dma_bufffdone(chan, buff, res);
+
+		/* Free the node and update curr, if non-circular queue */
+		if (!(chan->flags & S3C2410_DMAF_CIRCULAR)) {
+			chan->curr = buff->next;
+			s3c64xx_dma_freebuff(buff);
+		}
+
+		/* Update 'next' */
+		buff = chan->next;
+		if (chan->next == chan->end) {
+			chan->next = chan->curr;
+			if (!(chan->flags & S3C2410_DMAF_CIRCULAR))
+				chan->end = NULL;
+		} else {
+			chan->next = buff->next;
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct sysdev_class dma_sysclass = {
+	.name		= "s3c64xx-dma",
+};
+
+static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
+			     int irq, unsigned int base)
+{
+	struct s3c2410_dma_chan *chptr = &s3c2410_chans[chno];
+	struct s3c64xx_dmac *dmac;
+	char clkname[16];
+	void __iomem *regs;
+	void __iomem *regptr;
+	int err, ch;
+
+	dmac = kzalloc(sizeof(struct s3c64xx_dmac), GFP_KERNEL);
+	if (!dmac) {
+		printk(KERN_ERR "%s: failed to alloc mem\n", __func__);
+		return -ENOMEM;
+	}
+
+	dmac->sysdev.id = chno / 8;
+	dmac->sysdev.cls = &dma_sysclass;
+
+	err = sysdev_register(&dmac->sysdev);
+	if (err) {
+		printk(KERN_ERR "%s: failed to register sysdevice\n", __func__);
+		goto err_alloc;
+	}
+
+	regs = ioremap(base, 0x200);
+	if (!regs) {
+		printk(KERN_ERR "%s: failed to ioremap()\n", __func__);
+		err = -ENXIO;
+		goto err_dev;
+	}
+
+	snprintf(clkname, sizeof(clkname), "dma%d", dmac->sysdev.id);
+
+	dmac->clk = clk_get(NULL, clkname);
+	if (IS_ERR(dmac->clk)) {
+		printk(KERN_ERR "%s: failed to get clock %s\n", __func__, clkname);
+		err = PTR_ERR(dmac->clk);
+		goto err_map;
+	}
+
+	clk_enable(dmac->clk);
+
+	dmac->regs = regs;
+	dmac->chanbase = chbase;
+	dmac->channels = chptr;
+
+	err = request_irq(irq, s3c64xx_dma_irq, 0, "DMA", dmac);
+	if (err < 0) {
+		printk(KERN_ERR "%s: failed to get irq\n", __func__);
+		goto err_clk;
+	}
+
+	regptr = regs + PL080_Cx_BASE(0);
+
+	for (ch = 0; ch < 8; ch++, chno++, chptr++) {
+		printk(KERN_INFO "%s: registering DMA %d (%p)\n",
+		       __func__, chno, regptr);
+
+		chptr->bit = 1 << ch;
+		chptr->number = chno;
+		chptr->dmac = dmac;
+		chptr->regs = regptr;
+		regptr += PL008_Cx_STRIDE;
+	}
+
+	/* for the moment, permanently enable the controller */
+	writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG);
+
+	printk(KERN_INFO "PL080: IRQ %d, at %p\n", irq, regs);
+
+	return 0;
+
+err_clk:
+	clk_disable(dmac->clk);
+	clk_put(dmac->clk);
+err_map:
+	iounmap(regs);
+err_dev:
+	sysdev_unregister(&dmac->sysdev);
+err_alloc:
+	kfree(dmac);
+	return err;
+}
+
+static int __init s3c64xx_dma_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "%s: Registering DMA channels\n", __func__);
+
+	dma_pool = dma_pool_create("DMA-LLI", NULL, sizeof(struct pl080s_lli), 16, 0);
+	if (!dma_pool) {
+		printk(KERN_ERR "%s: failed to create pool\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = sysdev_class_register(&dma_sysclass);
+	if (ret) {
+		printk(KERN_ERR "%s: failed to create sysclass\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* Set all DMA configuration to be DMA, not SDMA */
+	writel(0xffffff, S3C_SYSREG(0x110));
+
+	/* Register standard DMA controlers */
+	s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
+	s3c64xx_dma_init1(8, DMACH_PCM1_TX, IRQ_DMA1, 0x75100000);
+
+	return 0;
+}
+
+arch_initcall(s3c64xx_dma_init);
diff --git a/arch/arm/mach-s3c64xx/gpiolib.c b/arch/arm/mach-s3c64xx/gpiolib.c
new file mode 100644
index 0000000..66e6794
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/gpiolib.c
@@ -0,0 +1,288 @@
+/* arch/arm/plat-s3c64xx/gpiolib.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - GPIOlib support 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+#include <mach/gpio.h>
+
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+#include <mach/regs-gpio.h>
+
+/* GPIO bank summary:
+ *
+ * Bank	GPIOs	Style	SlpCon	ExtInt Group
+ * A	8	4Bit	Yes	1
+ * B	7	4Bit	Yes	1
+ * C	8	4Bit	Yes	2
+ * D	5	4Bit	Yes	3
+ * E	5	4Bit	Yes	None
+ * F	16	2Bit	Yes	4 [1]
+ * G	7	4Bit	Yes	5
+ * H	10	4Bit[2]	Yes	6
+ * I	16	2Bit	Yes	None
+ * J	12	2Bit	Yes	None
+ * K	16	4Bit[2]	No	None
+ * L	15	4Bit[2] No	None
+ * M	6	4Bit	No	IRQ_EINT
+ * N	16	2Bit	No	IRQ_EINT
+ * O	16	2Bit	Yes	7
+ * P	15	2Bit	Yes	8
+ * Q	9	2Bit	Yes	9
+ *
+ * [1] BANKF pins 14,15 do not form part of the external interrupt sources
+ * [2] BANK has two control registers, GPxCON0 and GPxCON1
+ */
+
+static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
+	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
+	.cfg_eint	= 7,
+	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
+	.cfg_eint	= 3,
+	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
+{
+	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
+}
+
+static struct s3c_gpio_chip gpio_4bit[] = {
+	{
+		.base	= S3C64XX_GPA_BASE,
+		.config	= &gpio_4bit_cfg_eint0111,
+		.chip	= {
+			.base	= S3C64XX_GPA(0),
+			.ngpio	= S3C64XX_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.base	= S3C64XX_GPB_BASE,
+		.config	= &gpio_4bit_cfg_eint0111,
+		.chip	= {
+			.base	= S3C64XX_GPB(0),
+			.ngpio	= S3C64XX_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.base	= S3C64XX_GPC_BASE,
+		.config	= &gpio_4bit_cfg_eint0111,
+		.chip	= {
+			.base	= S3C64XX_GPC(0),
+			.ngpio	= S3C64XX_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.base	= S3C64XX_GPD_BASE,
+		.config	= &gpio_4bit_cfg_eint0111,
+		.chip	= {
+			.base	= S3C64XX_GPD(0),
+			.ngpio	= S3C64XX_GPIO_D_NR,
+			.label	= "GPD",
+		},
+	}, {
+		.base	= S3C64XX_GPE_BASE,
+		.config	= &gpio_4bit_cfg_noint,
+		.chip	= {
+			.base	= S3C64XX_GPE(0),
+			.ngpio	= S3C64XX_GPIO_E_NR,
+			.label	= "GPE",
+		},
+	}, {
+		.base	= S3C64XX_GPG_BASE,
+		.config	= &gpio_4bit_cfg_eint0111,
+		.chip	= {
+			.base	= S3C64XX_GPG(0),
+			.ngpio	= S3C64XX_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	}, {
+		.base	= S3C64XX_GPM_BASE,
+		.config	= &gpio_4bit_cfg_eint0011,
+		.chip	= {
+			.base	= S3C64XX_GPM(0),
+			.ngpio	= S3C64XX_GPIO_M_NR,
+			.label	= "GPM",
+			.to_irq = s3c64xx_gpio2int_gpm,
+		},
+	},
+};
+
+int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
+{
+	return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
+}
+
+static struct s3c_gpio_chip gpio_4bit2[] = {
+	{
+		.base	= S3C64XX_GPH_BASE + 0x4,
+		.config	= &gpio_4bit_cfg_eint0111,
+		.chip	= {
+			.base	= S3C64XX_GPH(0),
+			.ngpio	= S3C64XX_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	}, {
+		.base	= S3C64XX_GPK_BASE + 0x4,
+		.config	= &gpio_4bit_cfg_noint,
+		.chip	= {
+			.base	= S3C64XX_GPK(0),
+			.ngpio	= S3C64XX_GPIO_K_NR,
+			.label	= "GPK",
+		},
+	}, {
+		.base	= S3C64XX_GPL_BASE + 0x4,
+		.config	= &gpio_4bit_cfg_eint0011,
+		.chip	= {
+			.base	= S3C64XX_GPL(0),
+			.ngpio	= S3C64XX_GPIO_L_NR,
+			.label	= "GPL",
+			.to_irq = s3c64xx_gpio2int_gpl,
+		},
+	},
+};
+
+static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
+	.set_config	= s3c_gpio_setcfg_s3c24xx,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
+	.cfg_eint	= 2,
+	.set_config	= s3c_gpio_setcfg_s3c24xx,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
+	.cfg_eint	= 3,
+	.set_config	= s3c_gpio_setcfg_s3c24xx,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin)
+{
+	return IRQ_EINT(0) + pin;
+}
+
+static struct s3c_gpio_chip gpio_2bit[] = {
+	{
+		.base	= S3C64XX_GPF_BASE,
+		.config	= &gpio_2bit_cfg_eint11,
+		.chip	= {
+			.base	= S3C64XX_GPF(0),
+			.ngpio	= S3C64XX_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.base	= S3C64XX_GPI_BASE,
+		.config	= &gpio_2bit_cfg_noint,
+		.chip	= {
+			.base	= S3C64XX_GPI(0),
+			.ngpio	= S3C64XX_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.base	= S3C64XX_GPJ_BASE,
+		.config	= &gpio_2bit_cfg_noint,
+		.chip	= {
+			.base	= S3C64XX_GPJ(0),
+			.ngpio	= S3C64XX_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.base	= S3C64XX_GPN_BASE,
+		.config	= &gpio_2bit_cfg_eint10,
+		.chip	= {
+			.base	= S3C64XX_GPN(0),
+			.ngpio	= S3C64XX_GPIO_N_NR,
+			.label	= "GPN",
+			.to_irq = s3c64xx_gpio2int_gpn,
+		},
+	}, {
+		.base	= S3C64XX_GPO_BASE,
+		.config	= &gpio_2bit_cfg_eint11,
+		.chip	= {
+			.base	= S3C64XX_GPO(0),
+			.ngpio	= S3C64XX_GPIO_O_NR,
+			.label	= "GPO",
+		},
+	}, {
+		.base	= S3C64XX_GPP_BASE,
+		.config	= &gpio_2bit_cfg_eint11,
+		.chip	= {
+			.base	= S3C64XX_GPP(0),
+			.ngpio	= S3C64XX_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	}, {
+		.base	= S3C64XX_GPQ_BASE,
+		.config	= &gpio_2bit_cfg_eint11,
+		.chip	= {
+			.base	= S3C64XX_GPQ(0),
+			.ngpio	= S3C64XX_GPIO_Q_NR,
+			.label	= "GPQ",
+		},
+	},
+};
+
+static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
+{
+	chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
+}
+
+static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
+				       int nr_chips,
+				       void (*fn)(struct s3c_gpio_chip *))
+{
+	for (; nr_chips > 0; nr_chips--, chips++) {
+		if (fn)
+			(fn)(chips);
+		s3c_gpiolib_add(chips);
+	}
+}
+
+static __init int s3c64xx_gpiolib_init(void)
+{
+	s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
+			    samsung_gpiolib_add_4bit);
+
+	s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
+			    samsung_gpiolib_add_4bit2);
+
+	s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
+			    s3c64xx_gpiolib_add_2bit);
+
+	return 0;
+}
+
+core_initcall(s3c64xx_gpiolib_init);
diff --git a/arch/arm/mach-s3c64xx/include/mach/debug-macro.S b/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
new file mode 100644
index 0000000..b18ac52
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/debug-macro.S
@@ -0,0 +1,39 @@
+/* arch/arm/mach-s3c6400/include/mach/debug-macro.S
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <mach/map.h>
+#include <plat/regs-serial.h>
+
+	/* note, for the boot process to work we have to keep the UART
+	 * virtual address aligned to an 1MiB boundary for the L1
+	 * mapping the head code makes. We keep the UART virtual address
+	 * aligned and add in the offset when we load the value here.
+	 */
+
+	.macro addruart, rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1
+		ldreq	\rx, = S3C_PA_UART
+		ldrne	\rx, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
+#if CONFIG_DEBUG_S3C_UART != 0
+		add	\rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+#endif
+	.endm
+
+/* include the reset of the code which will do the work, we're only
+ * compiling for a single cpu processor type so the default of s3c2440
+ * will be fine with us.
+ */
+
+#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s3c64xx/include/mach/dma.h b/arch/arm/mach-s3c64xx/include/mach/dma.h
new file mode 100644
index 0000000..0a5d926
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/dma.h
@@ -0,0 +1,127 @@
+/* linux/arch/arm/mach-s3c6400/include/mach/dma.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C6400 - DMA support
+ */
+
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H __FILE__
+
+#define S3C_DMA_CHANNELS	(16)
+
+/* see mach-s3c2410/dma.h for notes on dma channel numbers */
+
+/* Note, for the S3C64XX architecture we keep the DMACH_
+ * defines in the order they are allocated to [S]DMA0/[S]DMA1
+ * so that is easy to do DHACH_ -> DMA controller conversion
+ */
+enum dma_ch {
+	/* DMA0/SDMA0 */
+	DMACH_UART0 = 0,
+	DMACH_UART0_SRC2,
+	DMACH_UART1,
+	DMACH_UART1_SRC2,
+	DMACH_UART2,
+	DMACH_UART2_SRC2,
+	DMACH_UART3,
+	DMACH_UART3_SRC2,
+	DMACH_PCM0_TX,
+	DMACH_PCM0_RX,
+	DMACH_I2S0_OUT,
+	DMACH_I2S0_IN,
+	DMACH_SPI0_TX,
+	DMACH_SPI0_RX,
+	DMACH_HSI_I2SV40_TX,
+	DMACH_HSI_I2SV40_RX,
+
+	/* DMA1/SDMA1 */
+	DMACH_PCM1_TX = 16,
+	DMACH_PCM1_RX,
+	DMACH_I2S1_OUT,
+	DMACH_I2S1_IN,
+	DMACH_SPI1_TX,
+	DMACH_SPI1_RX,
+	DMACH_AC97_PCMOUT,
+	DMACH_AC97_PCMIN,
+	DMACH_AC97_MICIN,
+	DMACH_PWM,
+	DMACH_IRDA,
+	DMACH_EXTERNAL,
+	DMACH_RES1,
+	DMACH_RES2,
+	DMACH_SECURITY_RX,	/* SDMA1 only */
+	DMACH_SECURITY_TX,	/* SDMA1 only */
+	DMACH_MAX		/* the end */
+};
+
+static __inline__ bool s3c_dma_has_circular(void)
+{
+	return true;
+}
+
+#define S3C2410_DMAF_CIRCULAR		(1 << 0)
+
+#include <plat/dma.h>
+
+#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
+
+struct s3c64xx_dma_buff;
+
+/** s3c64xx_dma_buff - S3C64XX DMA buffer descriptor
+ * @next: Pointer to next buffer in queue or ring.
+ * @pw: Client provided identifier
+ * @lli: Pointer to hardware descriptor this buffer is associated with.
+ * @lli_dma: Hardare address of the descriptor.
+ */
+struct s3c64xx_dma_buff {
+	struct s3c64xx_dma_buff *next;
+
+	void			*pw;
+	struct pl080s_lli	*lli;
+	dma_addr_t		 lli_dma;
+};
+
+struct s3c64xx_dmac;
+
+struct s3c2410_dma_chan {
+	unsigned char		 number;      /* number of this dma channel */
+	unsigned char		 in_use;      /* channel allocated */
+	unsigned char		 bit;	      /* bit for enable/disable/etc */
+	unsigned char		 hw_width;
+	unsigned char		 peripheral;
+
+	unsigned int		 flags;
+	enum s3c2410_dmasrc	 source;
+
+
+	dma_addr_t		dev_addr;
+
+	struct s3c2410_dma_client *client;
+	struct s3c64xx_dmac	*dmac;		/* pointer to controller */
+
+	void __iomem		*regs;
+
+	/* cdriver callbacks */
+	s3c2410_dma_cbfn_t	 callback_fn;	/* buffer done callback */
+	s3c2410_dma_opfn_t	 op_fn;		/* channel op callback */
+
+	/* buffer list and information */
+	struct s3c64xx_dma_buff	*curr;		/* current dma buffer */
+	struct s3c64xx_dma_buff	*next;		/* next buffer to load */
+	struct s3c64xx_dma_buff	*end;		/* end of queue */
+
+	/* note, when channel is running in circular mode, curr is the
+	 * first buffer enqueued, end is the last and curr is where the
+	 * last buffer-done event is set-at. The buffers are not freed
+	 * and the last buffer hardware descriptor points back to the
+	 * first.
+	 */
+};
+
+#include <plat/dma-core.h>
+
+#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/entry-macro.S b/arch/arm/mach-s3c64xx/include/mach/entry-macro.S
new file mode 100644
index 0000000..dd36260
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/entry-macro.S
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s3c6400/include/mach/entry-macro.S
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Low-level IRQ helper macros for the Samsung S3C64XX series
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+*/
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+#include <asm/entry-macro-vic2.S>
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-a.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-a.h
new file mode 100644
index 0000000..34212e1
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-a.h
@@ -0,0 +1,48 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-a.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank A register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPACON			(S3C64XX_GPA_BASE + 0x00)
+#define S3C64XX_GPADAT			(S3C64XX_GPA_BASE + 0x04)
+#define S3C64XX_GPAPUD			(S3C64XX_GPA_BASE + 0x08)
+#define S3C64XX_GPACONSLP		(S3C64XX_GPA_BASE + 0x0c)
+#define S3C64XX_GPAPUDSLP		(S3C64XX_GPA_BASE + 0x10)
+
+#define S3C64XX_GPA_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
+#define S3C64XX_GPA_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
+#define S3C64XX_GPA_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
+
+#define S3C64XX_GPA0_UART_RXD0		(0x02 << 0)
+#define S3C64XX_GPA0_EINT_G1_0		(0x07 << 0)
+
+#define S3C64XX_GPA1_UART_TXD0		(0x02 << 4)
+#define S3C64XX_GPA1_EINT_G1_1		(0x07 << 4)
+
+#define S3C64XX_GPA2_UART_nCTS0		(0x02 << 8)
+#define S3C64XX_GPA2_EINT_G1_2		(0x07 << 8)
+
+#define S3C64XX_GPA3_UART_nRTS0		(0x02 << 12)
+#define S3C64XX_GPA3_EINT_G1_3		(0x07 << 12)
+
+#define S3C64XX_GPA4_UART_RXD1		(0x02 << 16)
+#define S3C64XX_GPA4_EINT_G1_4		(0x07 << 16)
+
+#define S3C64XX_GPA5_UART_TXD1		(0x02 << 20)
+#define S3C64XX_GPA5_EINT_G1_5		(0x07 << 20)
+
+#define S3C64XX_GPA6_UART_nCTS1		(0x02 << 24)
+#define S3C64XX_GPA6_EINT_G1_6		(0x07 << 24)
+
+#define S3C64XX_GPA7_UART_nRTS1		(0x02 << 28)
+#define S3C64XX_GPA7_EINT_G1_7		(0x07 << 28)
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-b.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-b.h
new file mode 100644
index 0000000..7232c03
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-b.h
@@ -0,0 +1,60 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-b.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank B register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPBCON			(S3C64XX_GPB_BASE + 0x00)
+#define S3C64XX_GPBDAT			(S3C64XX_GPB_BASE + 0x04)
+#define S3C64XX_GPBPUD			(S3C64XX_GPB_BASE + 0x08)
+#define S3C64XX_GPBCONSLP		(S3C64XX_GPB_BASE + 0x0c)
+#define S3C64XX_GPBPUDSLP		(S3C64XX_GPB_BASE + 0x10)
+
+#define S3C64XX_GPB_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
+#define S3C64XX_GPB_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
+#define S3C64XX_GPB_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
+
+#define S3C64XX_GPB0_UART_RXD2		(0x02 << 0)
+#define S3C64XX_GPB0_EXTDMA_REQ		(0x03 << 0)
+#define S3C64XX_GPB0_IrDA_RXD		(0x04 << 0)
+#define S3C64XX_GPB0_ADDR_CF0		(0x05 << 0)
+#define S3C64XX_GPB0_EINT_G1_8		(0x07 << 0)
+
+#define S3C64XX_GPB1_UART_TXD2		(0x02 << 4)
+#define S3C64XX_GPB1_EXTDMA_ACK		(0x03 << 4)
+#define S3C64XX_GPB1_IrDA_TXD		(0x04 << 4)
+#define S3C64XX_GPB1_ADDR_CF1		(0x05 << 4)
+#define S3C64XX_GPB1_EINT_G1_9		(0x07 << 4)
+
+#define S3C64XX_GPB2_UART_RXD3		(0x02 << 8)
+#define S3C64XX_GPB2_IrDA_RXD		(0x03 << 8)
+#define S3C64XX_GPB2_EXTDMA_REQ		(0x04 << 8)
+#define S3C64XX_GPB2_ADDR_CF2		(0x05 << 8)
+#define S3C64XX_GPB2_I2C_SCL1		(0x06 << 8)
+#define S3C64XX_GPB2_EINT_G1_10		(0x07 << 8)
+
+#define S3C64XX_GPB3_UART_TXD3		(0x02 << 12)
+#define S3C64XX_GPB3_IrDA_TXD		(0x03 << 12)
+#define S3C64XX_GPB3_EXTDMA_ACK		(0x04 << 12)
+#define S3C64XX_GPB3_I2C_SDA1		(0x06 << 12)
+#define S3C64XX_GPB3_EINT_G1_11		(0x07 << 12)
+
+#define S3C64XX_GPB4_IrDA_SDBW		(0x02 << 16)
+#define S3C64XX_GPB4_CAM_FIELD		(0x03 << 16)
+#define S3C64XX_GPB4_CF_DATA_DIR	(0x04 << 16)
+#define S3C64XX_GPB4_EINT_G1_12		(0x07 << 16)
+
+#define S3C64XX_GPB5_I2C_SCL0		(0x02 << 20)
+#define S3C64XX_GPB5_EINT_G1_13		(0x07 << 20)
+
+#define S3C64XX_GPB6_I2C_SDA0		(0x02 << 24)
+#define S3C64XX_GPB6_EINT_G1_14		(0x07 << 24)
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-c.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-c.h
new file mode 100644
index 0000000..db189ab1
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-c.h
@@ -0,0 +1,53 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-c.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank C register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPCCON			(S3C64XX_GPC_BASE + 0x00)
+#define S3C64XX_GPCDAT			(S3C64XX_GPC_BASE + 0x04)
+#define S3C64XX_GPCPUD			(S3C64XX_GPC_BASE + 0x08)
+#define S3C64XX_GPCCONSLP		(S3C64XX_GPC_BASE + 0x0c)
+#define S3C64XX_GPCPUDSLP		(S3C64XX_GPC_BASE + 0x10)
+
+#define S3C64XX_GPC_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
+#define S3C64XX_GPC_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
+#define S3C64XX_GPC_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
+
+#define S3C64XX_GPC0_SPI_MISO0		(0x02 << 0)
+#define S3C64XX_GPC0_EINT_G2_0		(0x07 << 0)
+
+#define S3C64XX_GPC1_SPI_CLKO		(0x02 << 4)
+#define S3C64XX_GPC1_EINT_G2_1		(0x07 << 4)
+
+#define S3C64XX_GPC2_SPI_MOSIO		(0x02 << 8)
+#define S3C64XX_GPC2_EINT_G2_2		(0x07 << 8)
+
+#define S3C64XX_GPC3_SPI_nCSO		(0x02 << 12)
+#define S3C64XX_GPC3_EINT_G2_3		(0x07 << 12)
+
+#define S3C64XX_GPC4_SPI_MISO1		(0x02 << 16)
+#define S3C64XX_GPC4_MMC2_CMD		(0x03 << 16)
+#define S3C64XX_GPC4_I2S_V40_DO0	(0x05 << 16)
+#define S3C64XX_GPC4_EINT_G2_4		(0x07 << 16)
+
+#define S3C64XX_GPC5_SPI_CLK1		(0x02 << 20)
+#define S3C64XX_GPC5_MMC2_CLK		(0x03 << 20)
+#define S3C64XX_GPC5_I2S_V40_DO1	(0x05 << 20)
+#define S3C64XX_GPC5_EINT_G2_5		(0x07 << 20)
+
+#define S3C64XX_GPC6_SPI_MOSI1		(0x02 << 24)
+#define S3C64XX_GPC6_EINT_G2_6		(0x07 << 24)
+
+#define S3C64XX_GPC7_SPI_nCS1		(0x02 << 28)
+#define S3C64XX_GPC7_I2S_V40_DO2	(0x05 << 28)
+#define S3C64XX_GPC7_EINT_G2_7		(0x07 << 28)
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-d.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-d.h
new file mode 100644
index 0000000..1a01cee
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-d.h
@@ -0,0 +1,49 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-d.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank D register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPDCON			(S3C64XX_GPD_BASE + 0x00)
+#define S3C64XX_GPDDAT			(S3C64XX_GPD_BASE + 0x04)
+#define S3C64XX_GPDPUD			(S3C64XX_GPD_BASE + 0x08)
+#define S3C64XX_GPDCONSLP		(S3C64XX_GPD_BASE + 0x0c)
+#define S3C64XX_GPDPUDSLP		(S3C64XX_GPD_BASE + 0x10)
+
+#define S3C64XX_GPD_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
+#define S3C64XX_GPD_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
+#define S3C64XX_GPD_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
+
+#define S3C64XX_GPD0_PCM0_SCLK		(0x02 << 0)
+#define S3C64XX_GPD0_I2S0_CLK		(0x03 << 0)
+#define S3C64XX_GPD0_AC97_BITCLK	(0x04 << 0)
+#define S3C64XX_GPD0_EINT_G3_0		(0x07 << 0)
+
+#define S3C64XX_GPD1_PCM0_EXTCLK	(0x02 << 4)
+#define S3C64XX_GPD1_I2S0_CDCLK		(0x03 << 4)
+#define S3C64XX_GPD1_AC97_nRESET	(0x04 << 4)
+#define S3C64XX_GPD1_EINT_G3_1		(0x07 << 4)
+
+#define S3C64XX_GPD2_PCM0_FSYNC		(0x02 << 8)
+#define S3C64XX_GPD2_I2S0_LRCLK		(0x03 << 8)
+#define S3C64XX_GPD2_AC97_SYNC		(0x04 << 8)
+#define S3C64XX_GPD2_EINT_G3_2		(0x07 << 8)
+
+#define S3C64XX_GPD3_PCM0_SIN		(0x02 << 12)
+#define S3C64XX_GPD3_I2S0_DI		(0x03 << 12)
+#define S3C64XX_GPD3_AC97_SDI		(0x04 << 12)
+#define S3C64XX_GPD3_EINT_G3_3		(0x07 << 12)
+
+#define S3C64XX_GPD4_PCM0_SOUT		(0x02 << 16)
+#define S3C64XX_GPD4_I2S0_D0		(0x03 << 16)
+#define S3C64XX_GPD4_AC97_SDO		(0x04 << 16)
+#define S3C64XX_GPD4_EINT_G3_4		(0x07 << 16)
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-e.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-e.h
new file mode 100644
index 0000000..f057adb
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-e.h
@@ -0,0 +1,44 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-e.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank E register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPECON			(S3C64XX_GPE_BASE + 0x00)
+#define S3C64XX_GPEDAT			(S3C64XX_GPE_BASE + 0x04)
+#define S3C64XX_GPEPUD			(S3C64XX_GPE_BASE + 0x08)
+#define S3C64XX_GPECONSLP		(S3C64XX_GPE_BASE + 0x0c)
+#define S3C64XX_GPEPUDSLP		(S3C64XX_GPE_BASE + 0x10)
+
+#define S3C64XX_GPE_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
+#define S3C64XX_GPE_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
+#define S3C64XX_GPE_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
+
+#define S3C64XX_GPE0_PCM1_SCLK		(0x02 << 0)
+#define S3C64XX_GPE0_I2S1_CLK		(0x03 << 0)
+#define S3C64XX_GPE0_AC97_BITCLK	(0x04 << 0)
+
+#define S3C64XX_GPE1_PCM1_EXTCLK	(0x02 << 4)
+#define S3C64XX_GPE1_I2S1_CDCLK		(0x03 << 4)
+#define S3C64XX_GPE1_AC97_nRESET	(0x04 << 4)
+
+#define S3C64XX_GPE2_PCM1_FSYNC		(0x02 << 8)
+#define S3C64XX_GPE2_I2S1_LRCLK		(0x03 << 8)
+#define S3C64XX_GPE2_AC97_SYNC		(0x04 << 8)
+
+#define S3C64XX_GPE3_PCM1_SIN		(0x02 << 12)
+#define S3C64XX_GPE3_I2S1_DI		(0x03 << 12)
+#define S3C64XX_GPE3_AC97_SDI		(0x04 << 12)
+
+#define S3C64XX_GPE4_PCM1_SOUT		(0x02 << 16)
+#define S3C64XX_GPE4_I2S1_D0		(0x03 << 16)
+#define S3C64XX_GPE4_AC97_SDO		(0x04 << 16)
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-f.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-f.h
new file mode 100644
index 0000000..62ab8f5
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-f.h
@@ -0,0 +1,71 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-f.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank F register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPFCON			(S3C64XX_GPF_BASE + 0x00)
+#define S3C64XX_GPFDAT			(S3C64XX_GPF_BASE + 0x04)
+#define S3C64XX_GPFPUD			(S3C64XX_GPF_BASE + 0x08)
+#define S3C64XX_GPFCONSLP		(S3C64XX_GPF_BASE + 0x0c)
+#define S3C64XX_GPFPUDSLP		(S3C64XX_GPF_BASE + 0x10)
+
+#define S3C64XX_GPF_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
+#define S3C64XX_GPF_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
+#define S3C64XX_GPF_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
+
+#define S3C64XX_GPF0_CAMIF_CLK		(0x02 << 0)
+#define S3C64XX_GPF0_EINT_G4_0		(0x03 << 0)
+
+#define S3C64XX_GPF1_CAMIF_HREF		(0x02 << 2)
+#define S3C64XX_GPF1_EINT_G4_1		(0x03 << 2)
+
+#define S3C64XX_GPF2_CAMIF_PCLK		(0x02 << 4)
+#define S3C64XX_GPF2_EINT_G4_2		(0x03 << 4)
+
+#define S3C64XX_GPF3_CAMIF_nRST		(0x02 << 6)
+#define S3C64XX_GPF3_EINT_G4_3		(0x03 << 6)
+
+#define S3C64XX_GPF4_CAMIF_VSYNC	(0x02 << 8)
+#define S3C64XX_GPF4_EINT_G4_4		(0x03 << 8)
+
+#define S3C64XX_GPF5_CAMIF_YDATA0	(0x02 << 10)
+#define S3C64XX_GPF5_EINT_G4_5		(0x03 << 10)
+
+#define S3C64XX_GPF6_CAMIF_YDATA1	(0x02 << 12)
+#define S3C64XX_GPF6_EINT_G4_6		(0x03 << 12)
+
+#define S3C64XX_GPF7_CAMIF_YDATA2	(0x02 << 14)
+#define S3C64XX_GPF7_EINT_G4_7		(0x03 << 14)
+
+#define S3C64XX_GPF8_CAMIF_YDATA3	(0x02 << 16)
+#define S3C64XX_GPF8_EINT_G4_8		(0x03 << 16)
+
+#define S3C64XX_GPF9_CAMIF_YDATA4	(0x02 << 18)
+#define S3C64XX_GPF9_EINT_G4_9		(0x03 << 18)
+
+#define S3C64XX_GPF10_CAMIF_YDATA5	(0x02 << 20)
+#define S3C64XX_GPF10_EINT_G4_10	(0x03 << 20)
+
+#define S3C64XX_GPF11_CAMIF_YDATA6	(0x02 << 22)
+#define S3C64XX_GPF11_EINT_G4_11	(0x03 << 22)
+
+#define S3C64XX_GPF12_CAMIF_YDATA7	(0x02 << 24)
+#define S3C64XX_GPF12_EINT_G4_12	(0x03 << 24)
+
+#define S3C64XX_GPF13_PWM_ECLK		(0x02 << 26)
+#define S3C64XX_GPF13_EINT_G4_13	(0x03 << 26)
+
+#define S3C64XX_GPF14_PWM_TOUT0		(0x02 << 28)
+#define S3C64XX_GPF14_CLKOUT0		(0x03 << 28)
+
+#define S3C64XX_GPF15_PWM_TOUT1		(0x02 << 30)
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-g.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-g.h
new file mode 100644
index 0000000..b94954a
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-g.h
@@ -0,0 +1,42 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-g.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank G register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPGCON			(S3C64XX_GPG_BASE + 0x00)
+#define S3C64XX_GPGDAT			(S3C64XX_GPG_BASE + 0x04)
+#define S3C64XX_GPGPUD			(S3C64XX_GPG_BASE + 0x08)
+#define S3C64XX_GPGCONSLP		(S3C64XX_GPG_BASE + 0x0c)
+#define S3C64XX_GPGPUDSLP		(S3C64XX_GPG_BASE + 0x10)
+
+#define S3C64XX_GPG_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
+#define S3C64XX_GPG_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
+#define S3C64XX_GPG_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
+
+#define S3C64XX_GPG0_MMC0_CLK		(0x02 << 0)
+#define S3C64XX_GPG0_EINT_G5_0		(0x07 << 0)
+
+#define S3C64XX_GPG1_MMC0_CMD		(0x02 << 4)
+#define S3C64XX_GPG1_EINT_G5_1		(0x07 << 4)
+
+#define S3C64XX_GPG2_MMC0_DATA0		(0x02 << 8)
+#define S3C64XX_GPG2_EINT_G5_2		(0x07 << 8)
+
+#define S3C64XX_GPG3_MMC0_DATA1		(0x02 << 12)
+#define S3C64XX_GPG3_EINT_G5_3		(0x07 << 12)
+
+#define S3C64XX_GPG4_MMC0_DATA2		(0x02 << 16)
+#define S3C64XX_GPG4_EINT_G5_4		(0x07 << 16)
+
+#define S3C64XX_GPG5_MMC0_DATA3		(0x02 << 20)
+#define S3C64XX_GPG5_EINT_G5_5		(0x07 << 20)
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-h.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-h.h
new file mode 100644
index 0000000..5d75aaa
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-h.h
@@ -0,0 +1,74 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-h.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank H register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPHCON0			(S3C64XX_GPH_BASE + 0x00)
+#define S3C64XX_GPHCON1			(S3C64XX_GPH_BASE + 0x04)
+#define S3C64XX_GPHDAT			(S3C64XX_GPH_BASE + 0x08)
+#define S3C64XX_GPHPUD			(S3C64XX_GPH_BASE + 0x0c)
+#define S3C64XX_GPHCONSLP		(S3C64XX_GPH_BASE + 0x10)
+#define S3C64XX_GPHPUDSLP		(S3C64XX_GPH_BASE + 0x14)
+
+#define S3C64XX_GPH_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
+#define S3C64XX_GPH_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
+#define S3C64XX_GPH_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
+
+#define S3C64XX_GPH0_MMC1_CLK		(0x02 << 0)
+#define S3C64XX_GPH0_KP_COL0		(0x04 << 0)
+#define S3C64XX_GPH0_EINT_G6_0		(0x07 << 0)
+
+#define S3C64XX_GPH1_MMC1_CMD		(0x02 << 4)
+#define S3C64XX_GPH1_KP_COL1		(0x04 << 4)
+#define S3C64XX_GPH1_EINT_G6_1		(0x07 << 4)
+
+#define S3C64XX_GPH2_MMC1_DATA0		(0x02 << 8)
+#define S3C64XX_GPH2_KP_COL2		(0x04 << 8)
+#define S3C64XX_GPH2_EINT_G6_2		(0x07 << 8)
+
+#define S3C64XX_GPH3_MMC1_DATA1		(0x02 << 12)
+#define S3C64XX_GPH3_KP_COL3		(0x04 << 12)
+#define S3C64XX_GPH3_EINT_G6_3		(0x07 << 12)
+
+#define S3C64XX_GPH4_MMC1_DATA2		(0x02 << 16)
+#define S3C64XX_GPH4_KP_COL4		(0x04 << 16)
+#define S3C64XX_GPH4_EINT_G6_4		(0x07 << 16)
+
+#define S3C64XX_GPH5_MMC1_DATA3		(0x02 << 20)
+#define S3C64XX_GPH5_KP_COL5		(0x04 << 20)
+#define S3C64XX_GPH5_EINT_G6_5		(0x07 << 20)
+
+#define S3C64XX_GPH6_MMC1_DATA4		(0x02 << 24)
+#define S3C64XX_GPH6_MMC2_DATA0		(0x03 << 24)
+#define S3C64XX_GPH6_KP_COL6		(0x04 << 24)
+#define S3C64XX_GPH6_I2S_V40_BCLK	(0x05 << 24)
+#define S3C64XX_GPH6_ADDR_CF0		(0x06 << 24)
+#define S3C64XX_GPH6_EINT_G6_6		(0x07 << 24)
+
+#define S3C64XX_GPH7_MMC1_DATA5		(0x02 << 28)
+#define S3C64XX_GPH7_MMC2_DATA1		(0x03 << 28)
+#define S3C64XX_GPH7_KP_COL7		(0x04 << 28)
+#define S3C64XX_GPH7_I2S_V40_CDCLK	(0x05 << 28)
+#define S3C64XX_GPH7_ADDR_CF1		(0x06 << 28)
+#define S3C64XX_GPH7_EINT_G6_7		(0x07 << 28)
+
+#define S3C64XX_GPH8_MMC1_DATA6		(0x02 <<  0)
+#define S3C64XX_GPH8_MMC2_DATA2		(0x03 <<  0)
+#define S3C64XX_GPH8_I2S_V40_LRCLK	(0x05 <<  0)
+#define S3C64XX_GPH8_ADDR_CF2		(0x06 <<  0)
+#define S3C64XX_GPH8_EINT_G6_8		(0x07 <<  0)
+
+#define S3C64XX_GPH9_OUTPUT		(0x01 <<  4)
+#define S3C64XX_GPH9_MMC1_DATA7		(0x02 <<  4)
+#define S3C64XX_GPH9_MMC2_DATA3		(0x03 <<  4)
+#define S3C64XX_GPH9_I2S_V40_DI		(0x05 <<  4)
+#define S3C64XX_GPH9_EINT_G6_9		(0x07 <<  4)
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-i.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-i.h
new file mode 100644
index 0000000..4ceaa60
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-i.h
@@ -0,0 +1,40 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-i.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank I register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPICON			(S3C64XX_GPI_BASE + 0x00)
+#define S3C64XX_GPIDAT			(S3C64XX_GPI_BASE + 0x04)
+#define S3C64XX_GPIPUD			(S3C64XX_GPI_BASE + 0x08)
+#define S3C64XX_GPICONSLP		(S3C64XX_GPI_BASE + 0x0c)
+#define S3C64XX_GPIPUDSLP		(S3C64XX_GPI_BASE + 0x10)
+
+#define S3C64XX_GPI_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
+#define S3C64XX_GPI_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
+#define S3C64XX_GPI_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
+
+#define S3C64XX_GPI0_VD0		(0x02 << 0)
+#define S3C64XX_GPI1_VD1		(0x02 << 2)
+#define S3C64XX_GPI2_VD2		(0x02 << 4)
+#define S3C64XX_GPI3_VD3		(0x02 << 6)
+#define S3C64XX_GPI4_VD4		(0x02 << 8)
+#define S3C64XX_GPI5_VD5		(0x02 << 10)
+#define S3C64XX_GPI6_VD6		(0x02 << 12)
+#define S3C64XX_GPI7_VD7		(0x02 << 14)
+#define S3C64XX_GPI8_VD8		(0x02 << 16)
+#define S3C64XX_GPI9_VD9		(0x02 << 18)
+#define S3C64XX_GPI10_VD10		(0x02 << 20)
+#define S3C64XX_GPI11_VD11		(0x02 << 22)
+#define S3C64XX_GPI12_VD12		(0x02 << 24)
+#define S3C64XX_GPI13_VD13		(0x02 << 26)
+#define S3C64XX_GPI14_VD14		(0x02 << 28)
+#define S3C64XX_GPI15_VD15		(0x02 << 30)
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-j.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-j.h
new file mode 100644
index 0000000..6f25cd0
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-j.h
@@ -0,0 +1,36 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-j.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank J register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPJCON			(S3C64XX_GPJ_BASE + 0x00)
+#define S3C64XX_GPJDAT			(S3C64XX_GPJ_BASE + 0x04)
+#define S3C64XX_GPJPUD			(S3C64XX_GPJ_BASE + 0x08)
+#define S3C64XX_GPJCONSLP		(S3C64XX_GPJ_BASE + 0x0c)
+#define S3C64XX_GPJPUDSLP		(S3C64XX_GPJ_BASE + 0x10)
+
+#define S3C64XX_GPJ_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
+#define S3C64XX_GPJ_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
+#define S3C64XX_GPJ_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
+
+#define S3C64XX_GPJ0_VD16		(0x02 << 0)
+#define S3C64XX_GPJ1_VD17		(0x02 << 2)
+#define S3C64XX_GPJ2_VD18		(0x02 << 4)
+#define S3C64XX_GPJ3_VD19		(0x02 << 6)
+#define S3C64XX_GPJ4_VD20		(0x02 << 8)
+#define S3C64XX_GPJ5_VD21		(0x02 << 10)
+#define S3C64XX_GPJ6_VD22		(0x02 << 12)
+#define S3C64XX_GPJ7_VD23		(0x02 << 14)
+#define S3C64XX_GPJ8_LCD_HSYNC		(0x02 << 16)
+#define S3C64XX_GPJ9_LCD_VSYNC		(0x02 << 18)
+#define S3C64XX_GPJ10_LCD_VDEN		(0x02 << 20)
+#define S3C64XX_GPJ11_LCD_VCLK		(0x02 << 22)
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-n.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-n.h
new file mode 100644
index 0000000..d0aeda1
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-n.h
@@ -0,0 +1,54 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-n.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank N register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPNCON			(S3C64XX_GPN_BASE + 0x00)
+#define S3C64XX_GPNDAT			(S3C64XX_GPN_BASE + 0x04)
+#define S3C64XX_GPNPUD			(S3C64XX_GPN_BASE + 0x08)
+
+#define S3C64XX_GPN_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
+#define S3C64XX_GPN_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
+#define S3C64XX_GPN_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
+
+#define S3C64XX_GPN0_EINT0		(0x02 << 0)
+#define S3C64XX_GPN0_KP_ROW0		(0x03 << 0)
+
+#define S3C64XX_GPN1_EINT1		(0x02 << 2)
+#define S3C64XX_GPN1_KP_ROW1		(0x03 << 2)
+
+#define S3C64XX_GPN2_EINT2		(0x02 << 4)
+#define S3C64XX_GPN2_KP_ROW2		(0x03 << 4)
+
+#define S3C64XX_GPN3_EINT3		(0x02 << 6)
+#define S3C64XX_GPN3_KP_ROW3		(0x03 << 6)
+
+#define S3C64XX_GPN4_EINT4		(0x02 << 8)
+#define S3C64XX_GPN4_KP_ROW4		(0x03 << 8)
+
+#define S3C64XX_GPN5_EINT5		(0x02 << 10)
+#define S3C64XX_GPN5_KP_ROW5		(0x03 << 10)
+
+#define S3C64XX_GPN6_EINT6		(0x02 << 12)
+#define S3C64XX_GPN6_KP_ROW6		(0x03 << 12)
+
+#define S3C64XX_GPN7_EINT7		(0x02 << 14)
+#define S3C64XX_GPN7_KP_ROW7		(0x03 << 14)
+
+#define S3C64XX_GPN8_EINT8		(0x02 << 16)
+#define S3C64XX_GPN9_EINT9		(0x02 << 18)
+#define S3C64XX_GPN10_EINT10		(0x02 << 20)
+#define S3C64XX_GPN11_EINT11		(0x02 << 22)
+#define S3C64XX_GPN12_EINT12		(0x02 << 24)
+#define S3C64XX_GPN13_EINT13		(0x02 << 26)
+#define S3C64XX_GPN14_EINT14		(0x02 << 28)
+#define S3C64XX_GPN15_EINT15		(0x02 << 30)
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-o.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-o.h
new file mode 100644
index 0000000..21868fa
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-o.h
@@ -0,0 +1,70 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-o.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank O register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPOCON			(S3C64XX_GPO_BASE + 0x00)
+#define S3C64XX_GPODAT			(S3C64XX_GPO_BASE + 0x04)
+#define S3C64XX_GPOPUD			(S3C64XX_GPO_BASE + 0x08)
+#define S3C64XX_GPOCONSLP		(S3C64XX_GPO_BASE + 0x0c)
+#define S3C64XX_GPOPUDSLP		(S3C64XX_GPO_BASE + 0x10)
+
+#define S3C64XX_GPO_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
+#define S3C64XX_GPO_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
+#define S3C64XX_GPO_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
+
+#define S3C64XX_GPO0_MEM0_nCS2		(0x02 << 0)
+#define S3C64XX_GPO0_EINT_G7_0		(0x03 << 0)
+
+#define S3C64XX_GPO1_MEM0_nCS3		(0x02 << 2)
+#define S3C64XX_GPO1_EINT_G7_1		(0x03 << 2)
+
+#define S3C64XX_GPO2_MEM0_nCS4		(0x02 << 4)
+#define S3C64XX_GPO2_EINT_G7_2		(0x03 << 4)
+
+#define S3C64XX_GPO3_MEM0_nCS5		(0x02 << 6)
+#define S3C64XX_GPO3_EINT_G7_3		(0x03 << 6)
+
+#define S3C64XX_GPO4_EINT_G7_4		(0x03 << 8)
+
+#define S3C64XX_GPO5_EINT_G7_5		(0x03 << 10)
+
+#define S3C64XX_GPO6_MEM0_ADDR6		(0x02 << 12)
+#define S3C64XX_GPO6_EINT_G7_6		(0x03 << 12)
+
+#define S3C64XX_GPO7_MEM0_ADDR7		(0x02 << 14)
+#define S3C64XX_GPO7_EINT_G7_7		(0x03 << 14)
+
+#define S3C64XX_GPO8_MEM0_ADDR8		(0x02 << 16)
+#define S3C64XX_GPO8_EINT_G7_8		(0x03 << 16)
+
+#define S3C64XX_GPO9_MEM0_ADDR9		(0x02 << 18)
+#define S3C64XX_GPO9_EINT_G7_9		(0x03 << 18)
+
+#define S3C64XX_GPO10_MEM0_ADDR10	(0x02 << 20)
+#define S3C64XX_GPO10_EINT_G7_10	(0x03 << 20)
+
+#define S3C64XX_GPO11_MEM0_ADDR11	(0x02 << 22)
+#define S3C64XX_GPO11_EINT_G7_11	(0x03 << 22)
+
+#define S3C64XX_GPO12_MEM0_ADDR12	(0x02 << 24)
+#define S3C64XX_GPO12_EINT_G7_12	(0x03 << 24)
+
+#define S3C64XX_GPO13_MEM0_ADDR13	(0x02 << 26)
+#define S3C64XX_GPO13_EINT_G7_13	(0x03 << 26)
+
+#define S3C64XX_GPO14_MEM0_ADDR14	(0x02 << 28)
+#define S3C64XX_GPO14_EINT_G7_14	(0x03 << 28)
+
+#define S3C64XX_GPO15_MEM0_ADDR15	(0x02 << 30)
+#define S3C64XX_GPO15_EINT_G7_15	(0x03 << 30)
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-p.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-p.h
new file mode 100644
index 0000000..46bcfb6
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-p.h
@@ -0,0 +1,69 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-p.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank P register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPPCON			(S3C64XX_GPP_BASE + 0x00)
+#define S3C64XX_GPPDAT			(S3C64XX_GPP_BASE + 0x04)
+#define S3C64XX_GPPPUD			(S3C64XX_GPP_BASE + 0x08)
+#define S3C64XX_GPPCONSLP		(S3C64XX_GPP_BASE + 0x0c)
+#define S3C64XX_GPPPUDSLP		(S3C64XX_GPP_BASE + 0x10)
+
+#define S3C64XX_GPP_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
+#define S3C64XX_GPP_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
+#define S3C64XX_GPP_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
+
+#define S3C64XX_GPP0_MEM0_ADDRV		(0x02 << 0)
+#define S3C64XX_GPP0_EINT_G8_0		(0x03 << 0)
+
+#define S3C64XX_GPP1_MEM0_SMCLK		(0x02 << 2)
+#define S3C64XX_GPP1_EINT_G8_1		(0x03 << 2)
+
+#define S3C64XX_GPP2_MEM0_nWAIT		(0x02 << 4)
+#define S3C64XX_GPP2_EINT_G8_2		(0x03 << 4)
+
+#define S3C64XX_GPP3_MEM0_RDY0_ALE	(0x02 << 6)
+#define S3C64XX_GPP3_EINT_G8_3		(0x03 << 6)
+
+#define S3C64XX_GPP4_MEM0_RDY1_CLE	(0x02 << 8)
+#define S3C64XX_GPP4_EINT_G8_4		(0x03 << 8)
+
+#define S3C64XX_GPP5_MEM0_INTsm0_FWE	(0x02 << 10)
+#define S3C64XX_GPP5_EINT_G8_5		(0x03 << 10)
+
+#define S3C64XX_GPP6_MEM0_(null)	(0x02 << 12)
+#define S3C64XX_GPP6_EINT_G8_6		(0x03 << 12)
+
+#define S3C64XX_GPP7_MEM0_INTsm1_FRE	(0x02 << 14)
+#define S3C64XX_GPP7_EINT_G8_7		(0x03 << 14)
+
+#define S3C64XX_GPP8_MEM0_RPn_RnB	(0x02 << 16)
+#define S3C64XX_GPP8_EINT_G8_8		(0x03 << 16)
+
+#define S3C64XX_GPP9_MEM0_ATA_RESET	(0x02 << 18)
+#define S3C64XX_GPP9_EINT_G8_9		(0x03 << 18)
+
+#define S3C64XX_GPP10_MEM0_ATA_INPACK	(0x02 << 20)
+#define S3C64XX_GPP10_EINT_G8_10	(0x03 << 20)
+
+#define S3C64XX_GPP11_MEM0_ATA_REG	(0x02 << 22)
+#define S3C64XX_GPP11_EINT_G8_11	(0x03 << 22)
+
+#define S3C64XX_GPP12_MEM0_ATA_WE	(0x02 << 24)
+#define S3C64XX_GPP12_EINT_G8_12	(0x03 << 24)
+
+#define S3C64XX_GPP13_MEM0_ATA_OE	(0x02 << 26)
+#define S3C64XX_GPP13_EINT_G8_13	(0x03 << 26)
+
+#define S3C64XX_GPP14_MEM0_ATA_CD	(0x02 << 28)
+#define S3C64XX_GPP14_EINT_G8_14	(0x03 << 28)
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio-bank-q.h b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-q.h
new file mode 100644
index 0000000..1712223
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio-bank-q.h
@@ -0,0 +1,46 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/gpio-bank-q.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * 	Ben Dooks <ben@simtec.co.uk>
+ * 	http://armlinux.simtec.co.uk/
+ *
+ * GPIO Bank Q register and configuration definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define S3C64XX_GPQCON			(S3C64XX_GPQ_BASE + 0x00)
+#define S3C64XX_GPQDAT			(S3C64XX_GPQ_BASE + 0x04)
+#define S3C64XX_GPQPUD			(S3C64XX_GPQ_BASE + 0x08)
+#define S3C64XX_GPQCONSLP		(S3C64XX_GPQ_BASE + 0x0c)
+#define S3C64XX_GPQPUDSLP		(S3C64XX_GPQ_BASE + 0x10)
+
+#define S3C64XX_GPQ_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
+#define S3C64XX_GPQ_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
+#define S3C64XX_GPQ_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
+
+#define S3C64XX_GPQ0_MEM0_ADDR18_RAS	(0x02 << 0)
+#define S3C64XX_GPQ0_EINT_G9_0		(0x03 << 0)
+
+#define S3C64XX_GPQ1_MEM0_ADDR19_CAS	(0x02 << 2)
+#define S3C64XX_GPQ1_EINT_G9_1		(0x03 << 2)
+
+#define S3C64XX_GPQ2_EINT_G9_2		(0x03 << 4)
+
+#define S3C64XX_GPQ3_EINT_G9_3		(0x03 << 6)
+
+#define S3C64XX_GPQ4_EINT_G9_4		(0x03 << 8)
+
+#define S3C64XX_GPQ5_EINT_G9_5		(0x03 << 10)
+
+#define S3C64XX_GPQ6_EINT_G9_6		(0x03 << 12)
+
+#define S3C64XX_GPQ7_MEM0_ADDR17_WENDMC	(0x02 << 14)
+#define S3C64XX_GPQ7_EINT_G9_7		(0x03 << 14)
+
+#define S3C64XX_GPQ8_MEM0_ADDR16_APDMC	(0x02 << 16)
+#define S3C64XX_GPQ8_EINT_G9_8		(0x03 << 16)
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/gpio.h b/arch/arm/mach-s3c64xx/include/mach/gpio.h
new file mode 100644
index 0000000..0d46e99
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/gpio.h
@@ -0,0 +1,100 @@
+/* arch/arm/mach-s3c6400/include/mach/gpio.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C6400 - GPIO lib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define gpio_to_irq	__gpio_to_irq
+
+/* GPIO bank sizes */
+#define S3C64XX_GPIO_A_NR	(8)
+#define S3C64XX_GPIO_B_NR	(7)
+#define S3C64XX_GPIO_C_NR	(8)
+#define S3C64XX_GPIO_D_NR	(5)
+#define S3C64XX_GPIO_E_NR	(5)
+#define S3C64XX_GPIO_F_NR	(16)
+#define S3C64XX_GPIO_G_NR	(7)
+#define S3C64XX_GPIO_H_NR	(10)
+#define S3C64XX_GPIO_I_NR	(16)
+#define S3C64XX_GPIO_J_NR	(12)
+#define S3C64XX_GPIO_K_NR	(16)
+#define S3C64XX_GPIO_L_NR	(15)
+#define S3C64XX_GPIO_M_NR	(6)
+#define S3C64XX_GPIO_N_NR	(16)
+#define S3C64XX_GPIO_O_NR	(16)
+#define S3C64XX_GPIO_P_NR	(15)
+#define S3C64XX_GPIO_Q_NR	(9)
+
+/* GPIO bank numbes */
+
+/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
+ * space for debugging purposes so that any accidental
+ * change from one gpio bank to another can be caught.
+*/
+
+#define S3C64XX_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s3c_gpio_number {
+	S3C64XX_GPIO_A_START = 0,
+	S3C64XX_GPIO_B_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_A),
+	S3C64XX_GPIO_C_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_B),
+	S3C64XX_GPIO_D_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_C),
+	S3C64XX_GPIO_E_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_D),
+	S3C64XX_GPIO_F_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_E),
+	S3C64XX_GPIO_G_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_F),
+	S3C64XX_GPIO_H_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_G),
+	S3C64XX_GPIO_I_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_H),
+	S3C64XX_GPIO_J_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_I),
+	S3C64XX_GPIO_K_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_J),
+	S3C64XX_GPIO_L_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_K),
+	S3C64XX_GPIO_M_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_L),
+	S3C64XX_GPIO_N_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_M),
+	S3C64XX_GPIO_O_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_N),
+	S3C64XX_GPIO_P_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_O),
+	S3C64XX_GPIO_Q_START = S3C64XX_GPIO_NEXT(S3C64XX_GPIO_P),
+};
+
+/* S3C64XX GPIO number definitions. */
+
+#define S3C64XX_GPA(_nr)	(S3C64XX_GPIO_A_START + (_nr))
+#define S3C64XX_GPB(_nr)	(S3C64XX_GPIO_B_START + (_nr))
+#define S3C64XX_GPC(_nr)	(S3C64XX_GPIO_C_START + (_nr))
+#define S3C64XX_GPD(_nr)	(S3C64XX_GPIO_D_START + (_nr))
+#define S3C64XX_GPE(_nr)	(S3C64XX_GPIO_E_START + (_nr))
+#define S3C64XX_GPF(_nr)	(S3C64XX_GPIO_F_START + (_nr))
+#define S3C64XX_GPG(_nr)	(S3C64XX_GPIO_G_START + (_nr))
+#define S3C64XX_GPH(_nr)	(S3C64XX_GPIO_H_START + (_nr))
+#define S3C64XX_GPI(_nr)	(S3C64XX_GPIO_I_START + (_nr))
+#define S3C64XX_GPJ(_nr)	(S3C64XX_GPIO_J_START + (_nr))
+#define S3C64XX_GPK(_nr)	(S3C64XX_GPIO_K_START + (_nr))
+#define S3C64XX_GPL(_nr)	(S3C64XX_GPIO_L_START + (_nr))
+#define S3C64XX_GPM(_nr)	(S3C64XX_GPIO_M_START + (_nr))
+#define S3C64XX_GPN(_nr)	(S3C64XX_GPIO_N_START + (_nr))
+#define S3C64XX_GPO(_nr)	(S3C64XX_GPIO_O_START + (_nr))
+#define S3C64XX_GPP(_nr)	(S3C64XX_GPIO_P_START + (_nr))
+#define S3C64XX_GPQ(_nr)	(S3C64XX_GPIO_Q_START + (_nr))
+
+/* the end of the S3C64XX specific gpios */
+#define S3C64XX_GPIO_END	(S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)
+#define S3C_GPIO_END		S3C64XX_GPIO_END
+
+/* define the number of gpios we need to the one after the GPQ() range */
+#define GPIO_BOARD_START (S3C64XX_GPQ(S3C64XX_GPIO_Q_NR) + 1)
+
+#define BOARD_NR_GPIOS 16
+
+#define ARCH_NR_GPIOS	(GPIO_BOARD_START + BOARD_NR_GPIOS)
+
+#include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-s3c6400/include/mach/hardware.h b/arch/arm/mach-s3c64xx/include/mach/hardware.h
similarity index 100%
rename from arch/arm/mach-s3c6400/include/mach/hardware.h
rename to arch/arm/mach-s3c64xx/include/mach/hardware.h
diff --git a/arch/arm/mach-s3c64xx/include/mach/io.h b/arch/arm/mach-s3c64xx/include/mach/io.h
new file mode 100644
index 0000000..de5716db
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/io.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s3c64xxinclude/mach/io.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben-linux@fluff.org>
+ *
+ * Default IO routines for S3C64XX based
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif
diff --git a/arch/arm/mach-s3c64xx/include/mach/irqs.h b/arch/arm/mach-s3c64xx/include/mach/irqs.h
new file mode 100644
index 0000000..e9ab4ac
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/irqs.h
@@ -0,0 +1,216 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/irqs.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - IRQ support
+ */
+
+#ifndef __ASM_MACH_S3C64XX_IRQS_H
+#define __ASM_MACH_S3C64XX_IRQS_H __FILE__
+
+/* we keep the first set of CPU IRQs out of the range of
+ * the ISA space, so that the PC104 has them to itself
+ * and we don't end up having to do horrible things to the
+ * standard ISA drivers....
+ *
+ * note, since we're using the VICs, our start must be a
+ * mulitple of 32 to allow the common code to work
+ */
+
+#define S3C_IRQ_OFFSET	(32)
+
+#define S3C_IRQ(x)	((x) + S3C_IRQ_OFFSET)
+
+#define IRQ_VIC0_BASE	S3C_IRQ(0)
+#define IRQ_VIC1_BASE	S3C_IRQ(32)
+
+/* UART interrupts, each UART has 4 intterupts per channel so
+ * use the space between the ISA and S3C main interrupts. Note, these
+ * are not in the same order as the S3C24XX series! */
+
+#define IRQ_S3CUART_BASE0	(16)
+#define IRQ_S3CUART_BASE1	(20)
+#define IRQ_S3CUART_BASE2	(24)
+#define IRQ_S3CUART_BASE3	(28)
+
+#define UART_IRQ_RXD		(0)
+#define UART_IRQ_ERR		(1)
+#define UART_IRQ_TXD		(2)
+#define UART_IRQ_MODEM		(3)
+
+#define IRQ_S3CUART_RX0		(IRQ_S3CUART_BASE0 + UART_IRQ_RXD)
+#define IRQ_S3CUART_TX0		(IRQ_S3CUART_BASE0 + UART_IRQ_TXD)
+#define IRQ_S3CUART_ERR0	(IRQ_S3CUART_BASE0 + UART_IRQ_ERR)
+
+#define IRQ_S3CUART_RX1		(IRQ_S3CUART_BASE1 + UART_IRQ_RXD)
+#define IRQ_S3CUART_TX1		(IRQ_S3CUART_BASE1 + UART_IRQ_TXD)
+#define IRQ_S3CUART_ERR1	(IRQ_S3CUART_BASE1 + UART_IRQ_ERR)
+
+#define IRQ_S3CUART_RX2		(IRQ_S3CUART_BASE2 + UART_IRQ_RXD)
+#define IRQ_S3CUART_TX2		(IRQ_S3CUART_BASE2 + UART_IRQ_TXD)
+#define IRQ_S3CUART_ERR2	(IRQ_S3CUART_BASE2 + UART_IRQ_ERR)
+
+#define IRQ_S3CUART_RX3		(IRQ_S3CUART_BASE3 + UART_IRQ_RXD)
+#define IRQ_S3CUART_TX3		(IRQ_S3CUART_BASE3 + UART_IRQ_TXD)
+#define IRQ_S3CUART_ERR3	(IRQ_S3CUART_BASE3 + UART_IRQ_ERR)
+
+/* VIC based IRQs */
+
+#define S3C64XX_IRQ_VIC0(x)	(IRQ_VIC0_BASE + (x))
+#define S3C64XX_IRQ_VIC1(x)	(IRQ_VIC1_BASE + (x))
+
+/* VIC0 */
+
+#define IRQ_EINT0_3		S3C64XX_IRQ_VIC0(0)
+#define IRQ_EINT4_11		S3C64XX_IRQ_VIC0(1)
+#define IRQ_RTC_TIC		S3C64XX_IRQ_VIC0(2)
+#define IRQ_CAMIF_C		S3C64XX_IRQ_VIC0(3)
+#define IRQ_CAMIF_P		S3C64XX_IRQ_VIC0(4)
+#define IRQ_CAMIF_MC		S3C64XX_IRQ_VIC0(5)
+#define IRQ_S3C6410_IIC1	S3C64XX_IRQ_VIC0(5)
+#define IRQ_S3C6410_IIS		S3C64XX_IRQ_VIC0(6)
+#define IRQ_S3C6400_CAMIF_MP	S3C64XX_IRQ_VIC0(6)
+#define IRQ_CAMIF_WE_C		S3C64XX_IRQ_VIC0(7)
+#define IRQ_S3C6410_G3D		S3C64XX_IRQ_VIC0(8)
+#define IRQ_S3C6400_CAMIF_WE_P	S3C64XX_IRQ_VIC0(8)
+#define IRQ_POST0		S3C64XX_IRQ_VIC0(9)
+#define IRQ_ROTATOR		S3C64XX_IRQ_VIC0(10)
+#define IRQ_2D			S3C64XX_IRQ_VIC0(11)
+#define IRQ_TVENC		S3C64XX_IRQ_VIC0(12)
+#define IRQ_SCALER		S3C64XX_IRQ_VIC0(13)
+#define IRQ_BATF		S3C64XX_IRQ_VIC0(14)
+#define IRQ_JPEG		S3C64XX_IRQ_VIC0(15)
+#define IRQ_MFC			S3C64XX_IRQ_VIC0(16)
+#define IRQ_SDMA0		S3C64XX_IRQ_VIC0(17)
+#define IRQ_SDMA1		S3C64XX_IRQ_VIC0(18)
+#define IRQ_ARM_DMAERR		S3C64XX_IRQ_VIC0(19)
+#define IRQ_ARM_DMA		S3C64XX_IRQ_VIC0(20)
+#define IRQ_ARM_DMAS		S3C64XX_IRQ_VIC0(21)
+#define IRQ_KEYPAD		S3C64XX_IRQ_VIC0(22)
+#define IRQ_TIMER0_VIC		S3C64XX_IRQ_VIC0(23)
+#define IRQ_TIMER1_VIC		S3C64XX_IRQ_VIC0(24)
+#define IRQ_TIMER2_VIC		S3C64XX_IRQ_VIC0(25)
+#define IRQ_WDT			S3C64XX_IRQ_VIC0(26)
+#define IRQ_TIMER3_VIC		S3C64XX_IRQ_VIC0(27)
+#define IRQ_TIMER4_VIC		S3C64XX_IRQ_VIC0(28)
+#define IRQ_LCD_FIFO		S3C64XX_IRQ_VIC0(29)
+#define IRQ_LCD_VSYNC		S3C64XX_IRQ_VIC0(30)
+#define IRQ_LCD_SYSTEM		S3C64XX_IRQ_VIC0(31)
+
+/* VIC1 */
+
+#define IRQ_EINT12_19		S3C64XX_IRQ_VIC1(0)
+#define IRQ_EINT20_27		S3C64XX_IRQ_VIC1(1)
+#define IRQ_PCM0		S3C64XX_IRQ_VIC1(2)
+#define IRQ_PCM1		S3C64XX_IRQ_VIC1(3)
+#define IRQ_AC97		S3C64XX_IRQ_VIC1(4)
+#define IRQ_UART0		S3C64XX_IRQ_VIC1(5)
+#define IRQ_UART1		S3C64XX_IRQ_VIC1(6)
+#define IRQ_UART2		S3C64XX_IRQ_VIC1(7)
+#define IRQ_UART3		S3C64XX_IRQ_VIC1(8)
+#define IRQ_DMA0		S3C64XX_IRQ_VIC1(9)
+#define IRQ_DMA1		S3C64XX_IRQ_VIC1(10)
+#define IRQ_ONENAND0		S3C64XX_IRQ_VIC1(11)
+#define IRQ_ONENAND1		S3C64XX_IRQ_VIC1(12)
+#define IRQ_NFC			S3C64XX_IRQ_VIC1(13)
+#define IRQ_CFCON		S3C64XX_IRQ_VIC1(14)
+#define IRQ_USBH		S3C64XX_IRQ_VIC1(15)
+#define IRQ_SPI0		S3C64XX_IRQ_VIC1(16)
+#define IRQ_SPI1		S3C64XX_IRQ_VIC1(17)
+#define IRQ_IIC			S3C64XX_IRQ_VIC1(18)
+#define IRQ_HSItx		S3C64XX_IRQ_VIC1(19)
+#define IRQ_HSIrx		S3C64XX_IRQ_VIC1(20)
+#define IRQ_RESERVED		S3C64XX_IRQ_VIC1(21)
+#define IRQ_MSM			S3C64XX_IRQ_VIC1(22)
+#define IRQ_HOSTIF		S3C64XX_IRQ_VIC1(23)
+#define IRQ_HSMMC0		S3C64XX_IRQ_VIC1(24)
+#define IRQ_HSMMC1		S3C64XX_IRQ_VIC1(25)
+#define IRQ_HSMMC2		IRQ_SPI1	/* shared with SPI1 */
+#define IRQ_OTG			S3C64XX_IRQ_VIC1(26)
+#define IRQ_IRDA		S3C64XX_IRQ_VIC1(27)
+#define IRQ_RTC_ALARM		S3C64XX_IRQ_VIC1(28)
+#define IRQ_SEC			S3C64XX_IRQ_VIC1(29)
+#define IRQ_PENDN		S3C64XX_IRQ_VIC1(30)
+#define IRQ_TC			IRQ_PENDN
+#define IRQ_ADC			S3C64XX_IRQ_VIC1(31)
+
+#define S3C64XX_TIMER_IRQ(x)	S3C_IRQ(64 + (x))
+
+#define IRQ_TIMER0		S3C64XX_TIMER_IRQ(0)
+#define IRQ_TIMER1		S3C64XX_TIMER_IRQ(1)
+#define IRQ_TIMER2		S3C64XX_TIMER_IRQ(2)
+#define IRQ_TIMER3		S3C64XX_TIMER_IRQ(3)
+#define IRQ_TIMER4		S3C64XX_TIMER_IRQ(4)
+
+/* compatibility for device defines */
+
+#define IRQ_IIC1		IRQ_S3C6410_IIC1
+
+/* Since the IRQ_EINT(x) are a linear mapping on current s3c64xx series
+ * we just defined them as an IRQ_EINT(x) macro from S3C_IRQ_EINT_BASE
+ * which we place after the pair of VICs. */
+
+#define S3C_IRQ_EINT_BASE	S3C_IRQ(64+5)
+
+#define S3C_EINT(x)		((x) + S3C_IRQ_EINT_BASE)
+#define IRQ_EINT(x)		S3C_EINT(x)
+#define IRQ_EINT_BIT(x)		((x) - S3C_EINT(0))
+
+/* Next the external interrupt groups. These are similar to the IRQ_EINT(x)
+ * that they are sourced from the GPIO pins but with a different scheme for
+ * priority and source indication.
+ *
+ * The IRQ_EINT(x) can be thought of as 'group 0' of the available GPIO
+ * interrupts, but for historical reasons they are kept apart from these
+ * next interrupts.
+ *
+ * Use IRQ_EINT_GROUP(group, offset) to get the number for use in the
+ * machine specific support files.
+ */
+
+#define IRQ_EINT_GROUP1_NR	(15)
+#define IRQ_EINT_GROUP2_NR	(8)
+#define IRQ_EINT_GROUP3_NR	(5)
+#define IRQ_EINT_GROUP4_NR	(14)
+#define IRQ_EINT_GROUP5_NR	(7)
+#define IRQ_EINT_GROUP6_NR	(10)
+#define IRQ_EINT_GROUP7_NR	(16)
+#define IRQ_EINT_GROUP8_NR	(15)
+#define IRQ_EINT_GROUP9_NR	(9)
+
+#define IRQ_EINT_GROUP_BASE	S3C_EINT(28)
+#define IRQ_EINT_GROUP1_BASE	(IRQ_EINT_GROUP_BASE + 0x00)
+#define IRQ_EINT_GROUP2_BASE	(IRQ_EINT_GROUP1_BASE + IRQ_EINT_GROUP1_NR)
+#define IRQ_EINT_GROUP3_BASE	(IRQ_EINT_GROUP2_BASE + IRQ_EINT_GROUP2_NR)
+#define IRQ_EINT_GROUP4_BASE	(IRQ_EINT_GROUP3_BASE + IRQ_EINT_GROUP3_NR)
+#define IRQ_EINT_GROUP5_BASE	(IRQ_EINT_GROUP4_BASE + IRQ_EINT_GROUP4_NR)
+#define IRQ_EINT_GROUP6_BASE	(IRQ_EINT_GROUP5_BASE + IRQ_EINT_GROUP5_NR)
+#define IRQ_EINT_GROUP7_BASE	(IRQ_EINT_GROUP6_BASE + IRQ_EINT_GROUP6_NR)
+#define IRQ_EINT_GROUP8_BASE	(IRQ_EINT_GROUP7_BASE + IRQ_EINT_GROUP7_NR)
+#define IRQ_EINT_GROUP9_BASE	(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR)
+
+#define IRQ_EINT_GROUP(group, no)	(IRQ_EINT_GROUP##group##_BASE + (no))
+
+/* Define a group of interrupts for board-specific use (eg, for MFD
+ * interrupt controllers). */
+#define IRQ_BOARD_START (IRQ_EINT_GROUP9_BASE + IRQ_EINT_GROUP9_NR + 1)
+
+#ifdef CONFIG_SMDK6410_WM1190_EV1
+#define IRQ_BOARD_NR 64
+#elif defined(CONFIG_SMDK6410_WM1192_EV1)
+#define IRQ_BOARD_NR 64
+#else
+#define IRQ_BOARD_NR 16
+#endif
+
+#define IRQ_BOARD_END (IRQ_BOARD_START + IRQ_BOARD_NR)
+
+/* Set the default NR_IRQS */
+
+#define NR_IRQS	(IRQ_BOARD_END + 1)
+
+#endif /* __ASM_MACH_S3C64XX_IRQS_H */
+
diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h
new file mode 100644
index 0000000..801c1c0
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/map.h
@@ -0,0 +1,107 @@
+/* linux/arch/arm/mach-s3c6400/include/mach/map.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C64XX - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H __FILE__
+
+#include <plat/map-base.h>
+
+/*
+ * Post-mux Chip Select Regions Xm0CSn_
+ * These may be used by SROM, NAND or CF depending on settings
+ */
+
+#define S3C64XX_PA_XM0CSN0 (0x10000000)
+#define S3C64XX_PA_XM0CSN1 (0x18000000)
+#define S3C64XX_PA_XM0CSN2 (0x20000000)
+#define S3C64XX_PA_XM0CSN3 (0x28000000)
+#define S3C64XX_PA_XM0CSN4 (0x30000000)
+#define S3C64XX_PA_XM0CSN5 (0x38000000)
+
+/* HSMMC units */
+#define S3C64XX_PA_HSMMC(x)	(0x7C200000 + ((x) * 0x100000))
+#define S3C64XX_PA_HSMMC0	S3C64XX_PA_HSMMC(0)
+#define S3C64XX_PA_HSMMC1	S3C64XX_PA_HSMMC(1)
+#define S3C64XX_PA_HSMMC2	S3C64XX_PA_HSMMC(2)
+
+#define S3C_PA_UART		(0x7F005000)
+#define S3C_PA_UART0		(S3C_PA_UART + 0x00)
+#define S3C_PA_UART1		(S3C_PA_UART + 0x400)
+#define S3C_PA_UART2		(S3C_PA_UART + 0x800)
+#define S3C_PA_UART3		(S3C_PA_UART + 0xC00)
+#define S3C_UART_OFFSET		(0x400)
+
+/* See notes on UART VA mapping in debug-macro.S */
+#define S3C_VA_UARTx(x)	(S3C_VA_UART + (S3C_PA_UART & 0xfffff) + ((x) * S3C_UART_OFFSET))
+
+#define S3C_VA_UART0		S3C_VA_UARTx(0)
+#define S3C_VA_UART1		S3C_VA_UARTx(1)
+#define S3C_VA_UART2		S3C_VA_UARTx(2)
+#define S3C_VA_UART3		S3C_VA_UARTx(3)
+
+#define S3C64XX_PA_SROM		(0x70000000)
+
+#define S3C64XX_PA_NAND		(0x70200000)
+#define S3C64XX_PA_FB		(0x77100000)
+#define S3C64XX_PA_USB_HSOTG	(0x7C000000)
+#define S3C64XX_PA_WATCHDOG	(0x7E004000)
+#define S3C64XX_PA_RTC		(0x7E005000)
+#define S3C64XX_PA_ADC		(0x7E00B000)
+#define S3C64XX_PA_SYSCON	(0x7E00F000)
+#define S3C64XX_PA_AC97		(0x7F001000)
+#define S3C64XX_PA_IIS0		(0x7F002000)
+#define S3C64XX_PA_IIS1		(0x7F003000)
+#define S3C64XX_PA_TIMER	(0x7F006000)
+#define S3C64XX_PA_IIC0		(0x7F004000)
+#define S3C64XX_PA_SPI0		(0x7F00B000)
+#define S3C64XX_PA_SPI1		(0x7F00C000)
+#define S3C64XX_PA_PCM0		(0x7F009000)
+#define S3C64XX_PA_PCM1		(0x7F00A000)
+#define S3C64XX_PA_IISV4	(0x7F00D000)
+#define S3C64XX_PA_IIC1		(0x7F00F000)
+
+#define S3C64XX_PA_GPIO		(0x7F008000)
+#define S3C64XX_VA_GPIO		S3C_ADDR_CPU(0x00000000)
+#define S3C64XX_SZ_GPIO		SZ_4K
+
+#define S3C64XX_PA_SDRAM	(0x50000000)
+#define S3C64XX_PA_VIC0		(0x71200000)
+#define S3C64XX_PA_VIC1		(0x71300000)
+
+#define S3C64XX_PA_MODEM	(0x74108000)
+#define S3C64XX_VA_MODEM	S3C_ADDR_CPU(0x00100000)
+
+#define S3C64XX_PA_USBHOST	(0x74300000)
+
+#define S3C64XX_PA_USB_HSPHY	(0x7C100000)
+#define S3C64XX_VA_USB_HSPHY	S3C_ADDR_CPU(0x00200000)
+
+/* place VICs close together */
+#define VA_VIC0			(S3C_VA_IRQ + 0x00)
+#define VA_VIC1			(S3C_VA_IRQ + 0x10000)
+
+/* compatibiltiy defines. */
+#define S3C_PA_TIMER		S3C64XX_PA_TIMER
+#define S3C_PA_HSMMC0		S3C64XX_PA_HSMMC0
+#define S3C_PA_HSMMC1		S3C64XX_PA_HSMMC1
+#define S3C_PA_HSMMC2		S3C64XX_PA_HSMMC2
+#define S3C_PA_IIC		S3C64XX_PA_IIC0
+#define S3C_PA_IIC1		S3C64XX_PA_IIC1
+#define S3C_PA_NAND		S3C64XX_PA_NAND
+#define S3C_PA_FB		S3C64XX_PA_FB
+#define S3C_PA_USBHOST		S3C64XX_PA_USBHOST
+#define S3C_PA_USB_HSOTG	S3C64XX_PA_USB_HSOTG
+#define S3C_VA_USB_HSPHY	S3C64XX_VA_USB_HSPHY
+
+#endif /* __ASM_ARCH_6400_MAP_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/memory.h b/arch/arm/mach-s3c64xx/include/mach/memory.h
similarity index 100%
rename from arch/arm/mach-s3c6400/include/mach/memory.h
rename to arch/arm/mach-s3c64xx/include/mach/memory.h
diff --git a/arch/arm/plat-s3c64xx/include/plat/pll.h b/arch/arm/mach-s3c64xx/include/mach/pll.h
similarity index 100%
rename from arch/arm/plat-s3c64xx/include/plat/pll.h
rename to arch/arm/mach-s3c64xx/include/mach/pll.h
diff --git a/arch/arm/mach-s3c64xx/include/mach/pm-core.h b/arch/arm/mach-s3c64xx/include/mach/pm-core.h
new file mode 100644
index 0000000..1e9f20f
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/pm-core.h
@@ -0,0 +1,98 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/pm-core.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - PM core support for arch/arm/plat-s3c/pm.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <mach/regs-gpio.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+	u32 tmp = __raw_readl(S3C_PCLK_GATE);
+
+	/* As a note, since the S3C64XX UARTs generally have multiple
+	 * clock sources, we simply enable PCLK at the moment and hope
+	 * that the resume settings for the UART are suitable for the
+	 * use with PCLK.
+	 */
+
+	tmp |= S3C_CLKCON_PCLK_UART0;
+	tmp |= S3C_CLKCON_PCLK_UART1;
+	tmp |= S3C_CLKCON_PCLK_UART2;
+	tmp |= S3C_CLKCON_PCLK_UART3;
+
+	__raw_writel(tmp, S3C_PCLK_GATE);
+	udelay(10);
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+	/* VIC should have already been taken care of */
+
+	/* clear any pending EINT0 interrupts */
+	__raw_writel(__raw_readl(S3C64XX_EINT0PEND), S3C64XX_EINT0PEND);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+}
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+}
+
+/* make these defines, we currently do not have any need to change
+ * the IRQ wake controls depending on the CPU we are running on */
+
+#define s3c_irqwake_eintallow	((1 << 28) - 1)
+#define s3c_irqwake_intallow	(0)
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+					   struct pm_uart_save *save)
+{
+	u32 ucon = __raw_readl(regs + S3C2410_UCON);
+	u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
+	u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
+	u32 new_ucon;
+	u32 delta;
+
+	/* S3C64XX UART blocks only support level interrupts, so ensure that
+	 * when we restore unused UART blocks we force the level interrupt
+	 * settigs. */
+	save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
+
+	/* We have a constraint on changing the clock type of the UART
+	 * between UCLKx and PCLK, so ensure that when we restore UCON
+	 * that the CLK field is correctly modified if the bootloader
+	 * has changed anything.
+	 */
+	if (ucon_clk != save_clk) {
+		new_ucon = save->ucon;
+		delta = ucon_clk ^ save_clk;
+
+		/* change from UCLKx => wrong PCLK,
+		 * either UCLK can be tested for by a bit-test
+		 * with UCLK0 */
+		if (ucon_clk & S3C6400_UCON_UCLK0 &&
+		    !(save_clk & S3C6400_UCON_UCLK0) &&
+		    delta & S3C6400_UCON_PCLK2) {
+			new_ucon &= ~S3C6400_UCON_UCLK0;
+		} else if (delta == S3C6400_UCON_PCLK2) {
+			/* as an precaution, don't change from
+			 * PCLK2 => PCLK or vice-versa */
+			new_ucon ^= S3C6400_UCON_PCLK2;
+		}
+
+		S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
+			  ucon, new_ucon, save->ucon);
+		save->ucon = new_ucon;
+	}
+}
diff --git a/arch/arm/mach-s3c6400/include/mach/pwm-clock.h b/arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
similarity index 100%
rename from arch/arm/mach-s3c6400/include/mach/pwm-clock.h
rename to arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
new file mode 100644
index 0000000..3ef6274
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
@@ -0,0 +1,156 @@
+/* arch/arm/plat-s3c64xx/include/plat/regs-clock.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX clock register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_REGS_CLOCK_H
+#define __PLAT_REGS_CLOCK_H __FILE__
+
+#define S3C_CLKREG(x)		(S3C_VA_SYS + (x))
+
+#define S3C_APLL_LOCK		S3C_CLKREG(0x00)
+#define S3C_MPLL_LOCK		S3C_CLKREG(0x04)
+#define S3C_EPLL_LOCK		S3C_CLKREG(0x08)
+#define S3C_APLL_CON		S3C_CLKREG(0x0C)
+#define S3C_MPLL_CON		S3C_CLKREG(0x10)
+#define S3C_EPLL_CON0		S3C_CLKREG(0x14)
+#define S3C_EPLL_CON1		S3C_CLKREG(0x18)
+#define S3C_CLK_SRC		S3C_CLKREG(0x1C)
+#define S3C_CLK_DIV0		S3C_CLKREG(0x20)
+#define S3C_CLK_DIV1		S3C_CLKREG(0x24)
+#define S3C_CLK_DIV2		S3C_CLKREG(0x28)
+#define S3C_CLK_OUT		S3C_CLKREG(0x2C)
+#define S3C_HCLK_GATE		S3C_CLKREG(0x30)
+#define S3C_PCLK_GATE		S3C_CLKREG(0x34)
+#define S3C_SCLK_GATE		S3C_CLKREG(0x38)
+#define S3C_MEM0_GATE		S3C_CLKREG(0x3C)
+
+/* CLKDIV0 */
+#define S3C6400_CLKDIV0_PCLK_MASK	(0xf << 12)
+#define S3C6400_CLKDIV0_PCLK_SHIFT	(12)
+#define S3C6400_CLKDIV0_HCLK2_MASK	(0x7 << 9)
+#define S3C6400_CLKDIV0_HCLK2_SHIFT	(9)
+#define S3C6400_CLKDIV0_HCLK_MASK	(0x1 << 8)
+#define S3C6400_CLKDIV0_HCLK_SHIFT	(8)
+#define S3C6400_CLKDIV0_MPLL_MASK	(0x1 << 4)
+#define S3C6400_CLKDIV0_MPLL_SHIFT	(4)
+
+#define S3C6400_CLKDIV0_ARM_MASK	(0x7 << 0)
+#define S3C6410_CLKDIV0_ARM_MASK	(0xf << 0)
+#define S3C6400_CLKDIV0_ARM_SHIFT	(0)
+
+/* HCLK GATE Registers */
+#define S3C_CLKCON_HCLK_3DSE	(1<<31)
+#define S3C_CLKCON_HCLK_UHOST	(1<<29)
+#define S3C_CLKCON_HCLK_SECUR	(1<<28)
+#define S3C_CLKCON_HCLK_SDMA1	(1<<27)
+#define S3C_CLKCON_HCLK_SDMA0	(1<<26)
+#define S3C_CLKCON_HCLK_IROM	(1<<25)
+#define S3C_CLKCON_HCLK_DDR1	(1<<24)
+#define S3C_CLKCON_HCLK_DDR0	(1<<23)
+#define S3C_CLKCON_HCLK_MEM1	(1<<22)
+#define S3C_CLKCON_HCLK_MEM0	(1<<21)
+#define S3C_CLKCON_HCLK_USB	(1<<20)
+#define S3C_CLKCON_HCLK_HSMMC2	(1<<19)
+#define S3C_CLKCON_HCLK_HSMMC1	(1<<18)
+#define S3C_CLKCON_HCLK_HSMMC0	(1<<17)
+#define S3C_CLKCON_HCLK_MDP	(1<<16)
+#define S3C_CLKCON_HCLK_DHOST	(1<<15)
+#define S3C_CLKCON_HCLK_IHOST	(1<<14)
+#define S3C_CLKCON_HCLK_DMA1	(1<<13)
+#define S3C_CLKCON_HCLK_DMA0	(1<<12)
+#define S3C_CLKCON_HCLK_JPEG	(1<<11)
+#define S3C_CLKCON_HCLK_CAMIF	(1<<10)
+#define S3C_CLKCON_HCLK_SCALER	(1<<9)
+#define S3C_CLKCON_HCLK_2D	(1<<8)
+#define S3C_CLKCON_HCLK_TV	(1<<7)
+#define S3C_CLKCON_HCLK_POST0	(1<<5)
+#define S3C_CLKCON_HCLK_ROT	(1<<4)
+#define S3C_CLKCON_HCLK_LCD	(1<<3)
+#define S3C_CLKCON_HCLK_TZIC	(1<<2)
+#define S3C_CLKCON_HCLK_INTC	(1<<1)
+#define S3C_CLKCON_HCLK_MFC	(1<<0)
+
+/* PCLK GATE Registers */
+#define S3C6410_CLKCON_PCLK_I2C1	(1<<27)
+#define S3C6410_CLKCON_PCLK_IIS2	(1<<26)
+#define S3C_CLKCON_PCLK_SKEY		(1<<24)
+#define S3C_CLKCON_PCLK_CHIPID		(1<<23)
+#define S3C_CLKCON_PCLK_SPI1		(1<<22)
+#define S3C_CLKCON_PCLK_SPI0		(1<<21)
+#define S3C_CLKCON_PCLK_HSIRX		(1<<20)
+#define S3C_CLKCON_PCLK_HSITX		(1<<19)
+#define S3C_CLKCON_PCLK_GPIO		(1<<18)
+#define S3C_CLKCON_PCLK_IIC		(1<<17)
+#define S3C_CLKCON_PCLK_IIS1		(1<<16)
+#define S3C_CLKCON_PCLK_IIS0		(1<<15)
+#define S3C_CLKCON_PCLK_AC97		(1<<14)
+#define S3C_CLKCON_PCLK_TZPC		(1<<13)
+#define S3C_CLKCON_PCLK_TSADC		(1<<12)
+#define S3C_CLKCON_PCLK_KEYPAD		(1<<11)
+#define S3C_CLKCON_PCLK_IRDA		(1<<10)
+#define S3C_CLKCON_PCLK_PCM1		(1<<9)
+#define S3C_CLKCON_PCLK_PCM0		(1<<8)
+#define S3C_CLKCON_PCLK_PWM		(1<<7)
+#define S3C_CLKCON_PCLK_RTC		(1<<6)
+#define S3C_CLKCON_PCLK_WDT		(1<<5)
+#define S3C_CLKCON_PCLK_UART3		(1<<4)
+#define S3C_CLKCON_PCLK_UART2		(1<<3)
+#define S3C_CLKCON_PCLK_UART1		(1<<2)
+#define S3C_CLKCON_PCLK_UART0		(1<<1)
+#define S3C_CLKCON_PCLK_MFC		(1<<0)
+
+/* SCLK GATE Registers */
+#define S3C_CLKCON_SCLK_UHOST		(1<<30)
+#define S3C_CLKCON_SCLK_MMC2_48		(1<<29)
+#define S3C_CLKCON_SCLK_MMC1_48		(1<<28)
+#define S3C_CLKCON_SCLK_MMC0_48		(1<<27)
+#define S3C_CLKCON_SCLK_MMC2		(1<<26)
+#define S3C_CLKCON_SCLK_MMC1		(1<<25)
+#define S3C_CLKCON_SCLK_MMC0		(1<<24)
+#define S3C_CLKCON_SCLK_SPI1_48 	(1<<23)
+#define S3C_CLKCON_SCLK_SPI0_48 	(1<<22)
+#define S3C_CLKCON_SCLK_SPI1		(1<<21)
+#define S3C_CLKCON_SCLK_SPI0		(1<<20)
+#define S3C_CLKCON_SCLK_DAC27		(1<<19)
+#define S3C_CLKCON_SCLK_TV27		(1<<18)
+#define S3C_CLKCON_SCLK_SCALER27	(1<<17)
+#define S3C_CLKCON_SCLK_SCALER		(1<<16)
+#define S3C_CLKCON_SCLK_LCD27		(1<<15)
+#define S3C_CLKCON_SCLK_LCD		(1<<14)
+#define S3C6400_CLKCON_SCLK_POST1_27	(1<<13)
+#define S3C6410_CLKCON_FIMC		(1<<13)
+#define S3C_CLKCON_SCLK_POST0_27	(1<<12)
+#define S3C6400_CLKCON_SCLK_POST1	(1<<11)
+#define S3C6410_CLKCON_SCLK_AUDIO2	(1<<11)
+#define S3C_CLKCON_SCLK_POST0		(1<<10)
+#define S3C_CLKCON_SCLK_AUDIO1		(1<<9)
+#define S3C_CLKCON_SCLK_AUDIO0		(1<<8)
+#define S3C_CLKCON_SCLK_SECUR		(1<<7)
+#define S3C_CLKCON_SCLK_IRDA		(1<<6)
+#define S3C_CLKCON_SCLK_UART		(1<<5)
+#define S3C_CLKCON_SCLK_ONENAND 	(1<<4)
+#define S3C_CLKCON_SCLK_MFC		(1<<3)
+#define S3C_CLKCON_SCLK_CAM		(1<<2)
+#define S3C_CLKCON_SCLK_JPEG		(1<<1)
+
+/* CLKSRC */
+
+#define S3C6400_CLKSRC_APLL_MOUT	(1 << 0)
+#define S3C6400_CLKSRC_MPLL_MOUT	(1 << 1)
+#define S3C6400_CLKSRC_EPLL_MOUT	(1 << 2)
+#define S3C6400_CLKSRC_APLL_MOUT_SHIFT	(0)
+#define S3C6400_CLKSRC_MPLL_MOUT_SHIFT	(1)
+#define S3C6400_CLKSRC_EPLL_MOUT_SHIFT	(2)
+#define S3C6400_CLKSRC_MFC		(1 << 4)
+
+#endif /* _PLAT_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/regs-fb.h b/arch/arm/mach-s3c64xx/include/mach/regs-fb.h
similarity index 100%
rename from arch/arm/mach-s3c6400/include/mach/regs-fb.h
rename to arch/arm/mach-s3c64xx/include/mach/regs-fb.h
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h b/arch/arm/mach-s3c64xx/include/mach/regs-gpio-memport.h
similarity index 100%
rename from arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h
rename to arch/arm/mach-s3c64xx/include/mach/regs-gpio-memport.h
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h b/arch/arm/mach-s3c64xx/include/mach/regs-gpio.h
similarity index 100%
rename from arch/arm/plat-s3c64xx/include/plat/regs-gpio.h
rename to arch/arm/mach-s3c64xx/include/mach/regs-gpio.h
diff --git a/arch/arm/mach-s3c6400/include/mach/regs-irq.h b/arch/arm/mach-s3c64xx/include/mach/regs-irq.h
similarity index 100%
rename from arch/arm/mach-s3c6400/include/mach/regs-irq.h
rename to arch/arm/mach-s3c64xx/include/mach/regs-irq.h
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-modem.h b/arch/arm/mach-s3c64xx/include/mach/regs-modem.h
similarity index 100%
rename from arch/arm/plat-s3c64xx/include/plat/regs-modem.h
rename to arch/arm/mach-s3c64xx/include/mach/regs-modem.h
diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-srom.h b/arch/arm/mach-s3c64xx/include/mach/regs-srom.h
new file mode 100644
index 0000000..756731b
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/regs-srom.h
@@ -0,0 +1,59 @@
+/* arch/arm/plat-s3c64xx/include/plat/regs-srom.h
+ *
+ * Copyright 2009 Andy Green <andy@warmcat.com>
+ *
+ * S3C64XX SROM definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_REGS_SROM_H
+#define __PLAT_REGS_SROM_H __FILE__
+
+#define S3C64XX_SROMREG(x)	(S3C_VA_MEM + (x))
+
+#define S3C64XX_SROM_BW		S3C64XX_SROMREG(0)
+#define S3C64XX_SROM_BC0	S3C64XX_SROMREG(4)
+#define S3C64XX_SROM_BC1	S3C64XX_SROMREG(8)
+#define S3C64XX_SROM_BC2	S3C64XX_SROMREG(0xc)
+#define S3C64XX_SROM_BC3	S3C64XX_SROMREG(0x10)
+#define S3C64XX_SROM_BC4	S3C64XX_SROMREG(0x14)
+#define S3C64XX_SROM_BC5	S3C64XX_SROMREG(0x18)
+
+/*
+ * one register BW holds 5 x 4-bit packed settings for NCS0 - NCS4
+ */
+
+#define S3C64XX_SROM_BW__DATAWIDTH__SHIFT	0
+#define S3C64XX_SROM_BW__WAITENABLE__SHIFT	2
+#define S3C64XX_SROM_BW__BYTEENABLE__SHIFT	3
+#define S3C64XX_SROM_BW__CS_MASK 0xf
+
+#define S3C64XX_SROM_BW__NCS0__SHIFT	0
+#define S3C64XX_SROM_BW__NCS1__SHIFT	4
+#define S3C64XX_SROM_BW__NCS2__SHIFT	8
+#define S3C64XX_SROM_BW__NCS3__SHIFT	0xc
+#define S3C64XX_SROM_BW__NCS4__SHIFT	0x10
+
+/*
+ * applies to same to BCS0 - BCS4
+ */
+
+#define S3C64XX_SROM_BCX__PMC__SHIFT	0
+#define S3C64XX_SROM_BCX__PMC__MASK	3
+#define S3C64XX_SROM_BCX__TACP__SHIFT	4
+#define S3C64XX_SROM_BCX__TACP__MASK	0xf
+#define S3C64XX_SROM_BCX__TCAH__SHIFT	8
+#define S3C64XX_SROM_BCX__TCAH__MASK	0xf
+#define S3C64XX_SROM_BCX__TCOH__SHIFT	12
+#define S3C64XX_SROM_BCX__TCOH__MASK	0xf
+#define S3C64XX_SROM_BCX__TACC__SHIFT	16
+#define S3C64XX_SROM_BCX__TACC__MASK	0x1f
+#define S3C64XX_SROM_BCX__TCOS__SHIFT	24
+#define S3C64XX_SROM_BCX__TCOS__MASK	0xf
+#define S3C64XX_SROM_BCX__TACS__SHIFT	28
+#define S3C64XX_SROM_BCX__TACS__MASK	0xf
+
+#endif /* _PLAT_REGS_SROM_H */
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-sys.h b/arch/arm/mach-s3c64xx/include/mach/regs-sys.h
similarity index 100%
rename from arch/arm/plat-s3c64xx/include/plat/regs-sys.h
rename to arch/arm/mach-s3c64xx/include/mach/regs-sys.h
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h b/arch/arm/mach-s3c64xx/include/mach/regs-syscon-power.h
similarity index 100%
rename from arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h
rename to arch/arm/mach-s3c64xx/include/mach/regs-syscon-power.h
diff --git a/arch/arm/mach-s3c64xx/include/mach/s3c6400.h b/arch/arm/mach-s3c64xx/include/mach/s3c6400.h
new file mode 100644
index 0000000..f86958d
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/s3c6400.h
@@ -0,0 +1,36 @@
+/* arch/arm/mach-s3c64xx/include/macht/s3c6400.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Header file for s3c6400 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Common init code for S3C6400 related SoCs */
+
+extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s3c6400_setup_clocks(void);
+
+extern void s3c64xx_register_clocks(unsigned long xtal, unsigned armclk_limit);
+
+#ifdef CONFIG_CPU_S3C6400
+
+extern  int s3c6400_init(void);
+extern void s3c6400_init_irq(void);
+extern void s3c6400_map_io(void);
+extern void s3c6400_init_clocks(int xtal);
+
+#define s3c6400_init_uarts s3c6400_common_init_uarts
+
+#else
+#define s3c6400_init_clocks NULL
+#define s3c6400_init_uarts NULL
+#define s3c6400_map_io NULL
+#define s3c6400_init NULL
+#endif
diff --git a/arch/arm/mach-s3c64xx/include/mach/s3c6410.h b/arch/arm/mach-s3c64xx/include/mach/s3c6410.h
new file mode 100644
index 0000000..24f1141
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/s3c6410.h
@@ -0,0 +1,29 @@
+/* arch/arm/mach-s3c64xx/include/mach/s3c6410.h
+ *
+ * Copyright 2008 Openmoko,  Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Header file for s3c6410 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C6410
+
+extern  int s3c6410_init(void);
+extern void s3c6410_init_irq(void);
+extern void s3c6410_map_io(void);
+extern void s3c6410_init_clocks(int xtal);
+
+#define s3c6410_init_uarts s3c6400_common_init_uarts
+
+#else
+#define s3c6410_init_clocks NULL
+#define s3c6410_init_uarts NULL
+#define s3c6410_map_io NULL
+#define s3c6410_init NULL
+#endif
diff --git a/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h b/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h
new file mode 100644
index 0000000..9d0c43b
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h
@@ -0,0 +1,18 @@
+/* linux/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h
+ *
+ * Copyright (C) 2009 Samsung Electronics Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __S3C64XX_PLAT_SPI_CLKS_H
+#define __S3C64XX_PLAT_SPI_CLKS_H __FILE__
+
+#define S3C64XX_SPI_SRCCLK_PCLK		0
+#define S3C64XX_SPI_SRCCLK_SPIBUS	1
+#define S3C64XX_SPI_SRCCLK_48M		2
+
+#endif /* __S3C64XX_PLAT_SPI_CLKS_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/system.h b/arch/arm/mach-s3c64xx/include/mach/system.h
similarity index 100%
rename from arch/arm/mach-s3c6400/include/mach/system.h
rename to arch/arm/mach-s3c64xx/include/mach/system.h
diff --git a/arch/arm/mach-s3c64xx/include/mach/tick.h b/arch/arm/mach-s3c64xx/include/mach/tick.h
new file mode 100644
index 0000000..ebe18a9
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/tick.h
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-s3c6400/include/mach/tick.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C64XX - Timer tick support definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TICK_H
+#define __ASM_ARCH_TICK_H __FILE__
+
+/* note, the timer interrutps turn up in 2 places, the vic and then
+ * the timer block. We take the VIC as the base at the moment.
+ */
+static inline u32 s3c24xx_ostimer_pending(void)
+{
+	u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
+	return pend & 1 << (IRQ_TIMER4_VIC - S3C64XX_IRQ_VIC0(0));
+}
+
+#define TICK_MAX	(0xffffffff)
+
+#endif /* __ASM_ARCH_6400_TICK_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/timex.h b/arch/arm/mach-s3c64xx/include/mach/timex.h
new file mode 100644
index 0000000..fb2e8cd
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/timex.h
@@ -0,0 +1,24 @@
+/* arch/arm/mach-s3c64xx/include/mach/timex.h
+ *
+ * Copyright (c) 2003-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C6400 - time parameters
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
+
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s3c6400/include/mach/uncompress.h b/arch/arm/mach-s3c64xx/include/mach/uncompress.h
similarity index 100%
rename from arch/arm/mach-s3c6400/include/mach/uncompress.h
rename to arch/arm/mach-s3c64xx/include/mach/uncompress.h
diff --git a/arch/arm/mach-s3c64xx/include/mach/vmalloc.h b/arch/arm/mach-s3c64xx/include/mach/vmalloc.h
new file mode 100644
index 0000000..7411ef3
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/* arch/arm/mach-s3c64xx/include/mach/vmalloc.h
+ *
+ * from arch/arm/mach-iop3xx/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
+ *		      http://www.simtec.co.uk/products/SWLINUX/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S3C6400 vmalloc definition
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END	  (0xE0000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s3c64xx/irq-eint.c b/arch/arm/mach-s3c64xx/irq-eint.c
new file mode 100644
index 0000000..5682d6a
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/irq-eint.c
@@ -0,0 +1,213 @@
+/* arch/arm/plat-s3c64xx/irq-eint.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - Interrupt handling for IRQ_EINT(x)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/hardware/vic.h>
+
+#include <plat/regs-irqtype.h>
+#include <mach/regs-gpio.h>
+#include <plat/gpio-cfg.h>
+
+#include <mach/map.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+
+#define eint_offset(irq)	((irq) - IRQ_EINT(0))
+#define eint_irq_to_bit(irq)	(1 << eint_offset(irq))
+
+static inline void s3c_irq_eint_mask(unsigned int irq)
+{
+	u32 mask;
+
+	mask = __raw_readl(S3C64XX_EINT0MASK);
+	mask |= eint_irq_to_bit(irq);
+	__raw_writel(mask, S3C64XX_EINT0MASK);
+}
+
+static void s3c_irq_eint_unmask(unsigned int irq)
+{
+	u32 mask;
+
+	mask = __raw_readl(S3C64XX_EINT0MASK);
+	mask &= ~eint_irq_to_bit(irq);
+	__raw_writel(mask, S3C64XX_EINT0MASK);
+}
+
+static inline void s3c_irq_eint_ack(unsigned int irq)
+{
+	__raw_writel(eint_irq_to_bit(irq), S3C64XX_EINT0PEND);
+}
+
+static void s3c_irq_eint_maskack(unsigned int irq)
+{
+	/* compiler should in-line these */
+	s3c_irq_eint_mask(irq);
+	s3c_irq_eint_ack(irq);
+}
+
+static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
+{
+	int offs = eint_offset(irq);
+	int pin, pin_val;
+	int shift;
+	u32 ctrl, mask;
+	u32 newvalue = 0;
+	void __iomem *reg;
+
+	if (offs > 27)
+		return -EINVAL;
+
+	if (offs <= 15)
+		reg = S3C64XX_EINT0CON0;
+	else
+		reg = S3C64XX_EINT0CON1;
+
+	switch (type) {
+	case IRQ_TYPE_NONE:
+		printk(KERN_WARNING "No edge setting!\n");
+		break;
+
+	case IRQ_TYPE_EDGE_RISING:
+		newvalue = S3C2410_EXTINT_RISEEDGE;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		newvalue = S3C2410_EXTINT_FALLEDGE;
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		newvalue = S3C2410_EXTINT_BOTHEDGE;
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		newvalue = S3C2410_EXTINT_LOWLEV;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		newvalue = S3C2410_EXTINT_HILEV;
+		break;
+
+	default:
+		printk(KERN_ERR "No such irq type %d", type);
+		return -1;
+	}
+
+	if (offs <= 15)
+		shift = (offs / 2) * 4;
+	else
+		shift = ((offs - 16) / 2) * 4;
+	mask = 0x7 << shift;
+
+	ctrl = __raw_readl(reg);
+	ctrl &= ~mask;
+	ctrl |= newvalue << shift;
+	__raw_writel(ctrl, reg);
+
+	/* set the GPIO pin appropriately */
+
+	if (offs < 16) {
+		pin = S3C64XX_GPN(offs);
+		pin_val = S3C_GPIO_SFN(2);
+	} else if (offs < 23) {
+		pin = S3C64XX_GPL(offs + 8 - 16);
+		pin_val = S3C_GPIO_SFN(3);
+	} else {
+		pin = S3C64XX_GPM(offs - 23);
+		pin_val = S3C_GPIO_SFN(3);
+	}
+
+	s3c_gpio_cfgpin(pin, pin_val);
+
+	return 0;
+}
+
+static struct irq_chip s3c_irq_eint = {
+	.name		= "s3c-eint",
+	.mask		= s3c_irq_eint_mask,
+	.unmask		= s3c_irq_eint_unmask,
+	.mask_ack	= s3c_irq_eint_maskack,
+	.ack		= s3c_irq_eint_ack,
+	.set_type	= s3c_irq_eint_set_type,
+	.set_wake	= s3c_irqext_wake,
+};
+
+/* s3c_irq_demux_eint
+ *
+ * This function demuxes the IRQ from the group0 external interrupts,
+ * from IRQ_EINT(0) to IRQ_EINT(27). It is designed to be inlined into
+ * the specific handlers s3c_irq_demux_eintX_Y.
+ */
+static inline void s3c_irq_demux_eint(unsigned int start, unsigned int end)
+{
+	u32 status = __raw_readl(S3C64XX_EINT0PEND);
+	u32 mask = __raw_readl(S3C64XX_EINT0MASK);
+	unsigned int irq;
+
+	status &= ~mask;
+	status >>= start;
+	status &= (1 << (end - start + 1)) - 1;
+
+	for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
+		if (status & 1)
+			generic_handle_irq(irq);
+
+		status >>= 1;
+	}
+}
+
+static void s3c_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+{
+	s3c_irq_demux_eint(0, 3);
+}
+
+static void s3c_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
+{
+	s3c_irq_demux_eint(4, 11);
+}
+
+static void s3c_irq_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
+{
+	s3c_irq_demux_eint(12, 19);
+}
+
+static void s3c_irq_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
+{
+	s3c_irq_demux_eint(20, 27);
+}
+
+static int __init s3c64xx_init_irq_eint(void)
+{
+	int irq;
+
+	for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
+		set_irq_chip(irq, &s3c_irq_eint);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	set_irq_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
+	set_irq_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
+	set_irq_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
+	set_irq_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);
+
+	return 0;
+}
+
+arch_initcall(s3c64xx_init_irq_eint);
diff --git a/arch/arm/mach-s3c64xx/irq-pm.c b/arch/arm/mach-s3c64xx/irq-pm.c
new file mode 100644
index 0000000..da1bec6
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/irq-pm.c
@@ -0,0 +1,111 @@
+/* arch/arm/plat-s3c64xx/irq-pm.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - Interrupt handling Power Management
+ *
+ * This program is free software; you can redistribute it 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/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/serial_core.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-timer.h>
+#include <mach/regs-gpio.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+
+/* We handled all the IRQ types in this code, to save having to make several
+ * small files to handle each different type separately. Having the EINT_GRP
+ * code here shouldn't be as much bloat as the IRQ table space needed when
+ * they are enabled. The added benefit is we ensure that these registers are
+ * in the same state as we suspended.
+ */
+
+static struct sleep_save irq_save[] = {
+	SAVE_ITEM(S3C64XX_PRIORITY),
+	SAVE_ITEM(S3C64XX_EINT0CON0),
+	SAVE_ITEM(S3C64XX_EINT0CON1),
+	SAVE_ITEM(S3C64XX_EINT0FLTCON0),
+	SAVE_ITEM(S3C64XX_EINT0FLTCON1),
+	SAVE_ITEM(S3C64XX_EINT0FLTCON2),
+	SAVE_ITEM(S3C64XX_EINT0FLTCON3),
+	SAVE_ITEM(S3C64XX_EINT0MASK),
+	SAVE_ITEM(S3C64XX_TINT_CSTAT),
+};
+
+static struct irq_grp_save {
+	u32	fltcon;
+	u32	con;
+	u32	mask;
+} eint_grp_save[5];
+
+static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
+
+static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct irq_grp_save *grp = eint_grp_save;
+	int i;
+
+	S3C_PMDBG("%s: suspending IRQs\n", __func__);
+
+	s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+
+	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+		irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+		grp->con = __raw_readl(S3C64XX_EINT12CON + (i * 4));
+		grp->mask = __raw_readl(S3C64XX_EINT12MASK + (i * 4));
+		grp->fltcon = __raw_readl(S3C64XX_EINT12FLTCON + (i * 4));
+	}
+
+	return 0;
+}
+
+static int s3c64xx_irq_pm_resume(struct sys_device *dev)
+{
+	struct irq_grp_save *grp = eint_grp_save;
+	int i;
+
+	S3C_PMDBG("%s: resuming IRQs\n", __func__);
+
+	s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+
+	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
+		__raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
+
+	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
+		__raw_writel(grp->con, S3C64XX_EINT12CON + (i * 4));
+		__raw_writel(grp->mask, S3C64XX_EINT12MASK + (i * 4));
+		__raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4));
+	}
+
+	S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
+	return 0;
+}
+
+static struct sysdev_driver s3c64xx_irq_driver = {
+	.suspend = s3c64xx_irq_pm_suspend,
+	.resume	 = s3c64xx_irq_pm_resume,
+};
+
+static int __init s3c64xx_irq_pm_init(void)
+{
+	return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver);
+}
+
+arch_initcall(s3c64xx_irq_pm_init);
+
diff --git a/arch/arm/mach-s3c64xx/irq.c b/arch/arm/mach-s3c64xx/irq.c
new file mode 100644
index 0000000..67a145d
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/irq.c
@@ -0,0 +1,69 @@
+/* arch/arm/plat-s3c64xx/irq.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - Interrupt handling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/serial_core.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/hardware/vic.h>
+
+#include <mach/map.h>
+#include <plat/irq-vic-timer.h>
+#include <plat/irq-uart.h>
+#include <plat/cpu.h>
+
+static struct s3c_uart_irq uart_irqs[] = {
+	[0] = {
+		.regs		= S3C_VA_UART0,
+		.base_irq	= IRQ_S3CUART_BASE0,
+		.parent_irq	= IRQ_UART0,
+	},
+	[1] = {
+		.regs		= S3C_VA_UART1,
+		.base_irq	= IRQ_S3CUART_BASE1,
+		.parent_irq	= IRQ_UART1,
+	},
+	[2] = {
+		.regs		= S3C_VA_UART2,
+		.base_irq	= IRQ_S3CUART_BASE2,
+		.parent_irq	= IRQ_UART2,
+	},
+	[3] = {
+		.regs		= S3C_VA_UART3,
+		.base_irq	= IRQ_S3CUART_BASE3,
+		.parent_irq	= IRQ_UART3,
+	},
+};
+
+
+void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
+{
+	printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
+
+	/* initialise the pair of VICs */
+	vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, 0);
+	vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, 0);
+
+	/* add the timer sub-irqs */
+
+	s3c_init_vic_timer_irq(IRQ_TIMER0_VIC, IRQ_TIMER0);
+	s3c_init_vic_timer_irq(IRQ_TIMER1_VIC, IRQ_TIMER1);
+	s3c_init_vic_timer_irq(IRQ_TIMER2_VIC, IRQ_TIMER2);
+	s3c_init_vic_timer_irq(IRQ_TIMER3_VIC, IRQ_TIMER3);
+	s3c_init_vic_timer_irq(IRQ_TIMER4_VIC, IRQ_TIMER4);
+
+	s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
+}
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
new file mode 100644
index 0000000..4a0bb24
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -0,0 +1,245 @@
+/* linux/arch/arm/mach-s3c64xx/mach-anw6410.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ * Copyright 2009 Kwangwoo Lee
+ * 	Kwangwoo Lee <kwangwoo.lee@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/dm9000.h>
+
+#include <video/platform_lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-fb.h>
+#include <mach/map.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/iic.h>
+#include <plat/fb.h>
+
+#include <mach/s3c6410.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-modem.h>
+
+/* DM9000 */
+#define ANW6410_PA_DM9000	(0x18000000)
+
+/* A hardware buffer to control external devices is mapped at 0x30000000.
+ * It can not be read. So current status must be kept in anw6410_extdev_status.
+ */
+#define ANW6410_VA_EXTDEV	S3C_ADDR(0x02000000)
+#define ANW6410_PA_EXTDEV	(0x30000000)
+
+#define ANW6410_EN_DM9000	(1<<11)
+#define ANW6410_EN_LCD		(1<<14)
+
+static __u32 anw6410_extdev_status;
+
+static struct s3c2410_uartcfg anw6410_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+};
+
+/* framebuffer and LCD setup. */
+static void __init anw6410_lcd_mode_set(void)
+{
+	u32 tmp;
+
+	/* set the LCD type */
+	tmp = __raw_readl(S3C64XX_SPCON);
+	tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
+	tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
+	__raw_writel(tmp, S3C64XX_SPCON);
+
+	/* remove the LCD bypass */
+	tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
+	tmp &= ~MIFPCON_LCD_BYPASS;
+	__raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
+}
+
+/* GPF1 = LCD panel power
+ * GPF4 = LCD backlight control
+ */
+static void anw6410_lcd_power_set(struct plat_lcd_data *pd,
+				   unsigned int power)
+{
+	if (power) {
+		anw6410_extdev_status |= (ANW6410_EN_LCD << 16);
+		__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
+
+		gpio_direction_output(S3C64XX_GPF(1), 1);
+		gpio_direction_output(S3C64XX_GPF(4), 1);
+	} else {
+		anw6410_extdev_status &= ~(ANW6410_EN_LCD << 16);
+		__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
+
+		gpio_direction_output(S3C64XX_GPF(1), 0);
+		gpio_direction_output(S3C64XX_GPF(4), 0);
+	}
+}
+
+static struct plat_lcd_data anw6410_lcd_power_data = {
+	.set_power	= anw6410_lcd_power_set,
+};
+
+static struct platform_device anw6410_lcd_powerdev = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s3c_device_fb.dev,
+	.dev.platform_data	= &anw6410_lcd_power_data,
+};
+
+static struct s3c_fb_pd_win anw6410_fb_win0 = {
+	/* this is to ensure we use win0 */
+	.win_mode	= {
+		.pixclock	= 41094,
+		.left_margin	= 8,
+		.right_margin	= 13,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 16,
+};
+
+/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
+static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = {
+	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
+	.win[0]		= &anw6410_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+};
+
+/* DM9000AEP 10/100 ethernet controller */
+static void __init anw6410_dm9000_enable(void)
+{
+	anw6410_extdev_status |= (ANW6410_EN_DM9000 << 16);
+	__raw_writel(anw6410_extdev_status, ANW6410_VA_EXTDEV);
+}
+
+static struct resource anw6410_dm9000_resource[] = {
+	[0] = {
+		.start = ANW6410_PA_DM9000,
+		.end   = ANW6410_PA_DM9000 + 3,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = ANW6410_PA_DM9000 + 4,
+		.end   = ANW6410_PA_DM9000 + 4 + 500,
+		.flags = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start = IRQ_EINT(15),
+		.end   = IRQ_EINT(15),
+		.flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
+	},
+};
+
+static struct dm9000_plat_data anw6410_dm9000_pdata = {
+	.flags	  = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
+	/* dev_addr can be set to provide hwaddr. */
+};
+
+static struct platform_device anw6410_device_eth = {
+	.name	= "dm9000",
+	.id	= -1,
+	.num_resources	= ARRAY_SIZE(anw6410_dm9000_resource),
+	.resource	= anw6410_dm9000_resource,
+	.dev	= {
+		.platform_data  = &anw6410_dm9000_pdata,
+	},
+};
+
+static struct map_desc anw6410_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)ANW6410_VA_EXTDEV,
+		.pfn		= __phys_to_pfn(ANW6410_PA_EXTDEV),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static struct platform_device *anw6410_devices[] __initdata = {
+	&s3c_device_fb,
+	&anw6410_lcd_powerdev,
+	&anw6410_device_eth,
+};
+
+static void __init anw6410_map_io(void)
+{
+	s3c64xx_init_io(anw6410_iodesc, ARRAY_SIZE(anw6410_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(anw6410_uartcfgs, ARRAY_SIZE(anw6410_uartcfgs));
+
+	anw6410_lcd_mode_set();
+}
+
+static void __init anw6410_machine_init(void)
+{
+	s3c_fb_set_platdata(&anw6410_lcd_pdata);
+
+	gpio_request(S3C64XX_GPF(1), "panel power");
+	gpio_request(S3C64XX_GPF(4), "LCD backlight");
+
+	anw6410_dm9000_enable();
+
+	platform_add_devices(anw6410_devices, ARRAY_SIZE(anw6410_devices));
+}
+
+MACHINE_START(ANW6410, "A&W6410")
+	/* Maintainer: Kwangwoo Lee <kwangwoo.lee@gmail.com> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+
+	.init_irq	= s3c6410_init_irq,
+	.map_io		= anw6410_map_io,
+	.init_machine	= anw6410_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
new file mode 100644
index 0000000..187441a
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -0,0 +1,276 @@
+/* mach-hmt.c - Platform code for Airgoo HMT
+ *
+ * Copyright 2009 Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * This program is free software; you can redistribute it 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/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/leds.h>
+#include <linux/pwm_backlight.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-fb.h>
+#include <mach/map.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/iic.h>
+#include <plat/fb.h>
+#include <plat/nand.h>
+
+#include <mach/s3c6410.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE)
+#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
+
+static struct s3c2410_uartcfg hmt_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+};
+
+static int hmt_bl_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S3C64XX_GPB(4), "lcd backlight enable");
+	if (!ret)
+		ret = gpio_direction_output(S3C64XX_GPB(4), 0);
+
+	return ret;
+}
+
+static int hmt_bl_notify(struct device *dev, int brightness)
+{
+	/*
+	 * translate from CIELUV/CIELAB L*->brightness, E.G. from
+	 * perceived luminance to light output. Assumes range 0..25600
+	 */
+	if (brightness < 0x800) {
+		/* Y = Yn * L / 903.3 */
+		brightness = (100*256 * brightness + 231245/2) / 231245;
+	} else {
+		/* Y = Yn * ((L + 16) / 116 )^3 */
+		int t = (brightness*4 + 16*1024 + 58)/116;
+		brightness = 25 * ((t * t * t + 0x100000/2) / 0x100000);
+	}
+
+	gpio_set_value(S3C64XX_GPB(4), brightness);
+
+	return brightness;
+}
+
+static void hmt_bl_exit(struct device *dev)
+{
+	gpio_free(S3C64XX_GPB(4));
+}
+
+static struct platform_pwm_backlight_data hmt_backlight_data = {
+	.pwm_id		= 1,
+	.max_brightness	= 100 * 256,
+	.dft_brightness	= 40 * 256,
+	.pwm_period_ns	= 1000000000 / (100 * 256 * 20),
+	.init		= hmt_bl_init,
+	.notify		= hmt_bl_notify,
+	.exit		= hmt_bl_exit,
+
+};
+
+static struct platform_device hmt_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent	= &s3c_device_timer[1].dev,
+		.platform_data = &hmt_backlight_data,
+	},
+};
+
+static struct s3c_fb_pd_win hmt_fb_win0 = {
+	.win_mode	= {
+		.pixclock	= 41094,
+		.left_margin	= 8,
+		.right_margin	= 13,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 16,
+};
+
+/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
+static struct s3c_fb_platdata hmt_lcd_pdata __initdata = {
+	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
+	.win[0]		= &hmt_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+};
+
+static struct mtd_partition hmt_nand_part[] = {
+	[0] = {
+		.name	= "uboot",
+		.size	= SZ_512K,
+		.offset	= 0,
+	},
+	[1] = {
+		.name	= "uboot-env1",
+		.size	= SZ_256K,
+		.offset	= SZ_512K,
+	},
+	[2] = {
+		.name	= "uboot-env2",
+		.size	= SZ_256K,
+		.offset	= SZ_512K + SZ_256K,
+	},
+	[3] = {
+		.name	= "kernel",
+		.size	= SZ_2M,
+		.offset	= SZ_1M,
+	},
+	[4] = {
+		.name	= "rootfs",
+		.size	= MTDPART_SIZ_FULL,
+		.offset	= SZ_1M + SZ_2M,
+	},
+};
+
+static struct s3c2410_nand_set hmt_nand_sets[] = {
+	[0] = {
+		.name		= "nand",
+		.nr_chips	= 1,
+		.nr_partitions	= ARRAY_SIZE(hmt_nand_part),
+		.partitions	= hmt_nand_part,
+	},
+};
+
+static struct s3c2410_platform_nand hmt_nand_info = {
+	.tacls		= 25,
+	.twrph0		= 55,
+	.twrph1		= 40,
+	.nr_sets	= ARRAY_SIZE(hmt_nand_sets),
+	.sets		= hmt_nand_sets,
+};
+
+static struct gpio_led hmt_leds[] = {
+	{ /* left function keys */
+		.name			= "left:blue",
+		.gpio			= S3C64XX_GPO(12),
+		.default_trigger	= "default-on",
+	},
+	{ /* right function keys - red */
+		.name			= "right:red",
+		.gpio			= S3C64XX_GPO(13),
+	},
+	{ /* right function keys - green */
+		.name			= "right:green",
+		.gpio			= S3C64XX_GPO(14),
+	},
+	{ /* right function keys - blue */
+		.name			= "right:blue",
+		.gpio			= S3C64XX_GPO(15),
+		.default_trigger	= "default-on",
+	},
+};
+
+static struct gpio_led_platform_data hmt_led_data = {
+	.num_leds = ARRAY_SIZE(hmt_leds),
+	.leds = hmt_leds,
+};
+
+static struct platform_device hmt_leds_device = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &hmt_led_data,
+};
+
+static struct map_desc hmt_iodesc[] = {};
+
+static struct platform_device *hmt_devices[] __initdata = {
+	&s3c_device_i2c0,
+	&s3c_device_nand,
+	&s3c_device_fb,
+	&s3c_device_ohci,
+	&s3c_device_timer[1],
+	&hmt_backlight_device,
+	&hmt_leds_device,
+};
+
+static void __init hmt_map_io(void)
+{
+	s3c64xx_init_io(hmt_iodesc, ARRAY_SIZE(hmt_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(hmt_uartcfgs, ARRAY_SIZE(hmt_uartcfgs));
+}
+
+static void __init hmt_machine_init(void)
+{
+	s3c_i2c0_set_platdata(NULL);
+	s3c_fb_set_platdata(&hmt_lcd_pdata);
+	s3c_nand_set_platdata(&hmt_nand_info);
+
+	gpio_request(S3C64XX_GPC(7), "usb power");
+	gpio_direction_output(S3C64XX_GPC(7), 0);
+	gpio_request(S3C64XX_GPM(0), "usb power");
+	gpio_direction_output(S3C64XX_GPM(0), 1);
+	gpio_request(S3C64XX_GPK(7), "usb power");
+	gpio_direction_output(S3C64XX_GPK(7), 1);
+	gpio_request(S3C64XX_GPF(13), "usb power");
+	gpio_direction_output(S3C64XX_GPF(13), 1);
+
+	platform_add_devices(hmt_devices, ARRAY_SIZE(hmt_devices));
+}
+
+MACHINE_START(HMT, "Airgoo-HMT")
+	/* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.init_irq	= s3c6410_init_irq,
+	.map_io		= hmt_map_io,
+	.init_machine	= hmt_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
new file mode 100644
index 0000000..bf65747
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -0,0 +1,107 @@
+/*
+ * linux/arch/arm/mach-s3c64xx/mach-ncp.c
+ *
+ * Copyright (C) 2008-2009 Samsung Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include <video/platform_lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-fb.h>
+#include <mach/map.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/iic.h>
+#include <plat/fb.h>
+
+#include <mach/s3c6410.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg ncp_uartcfgs[] __initdata = {
+	/* REVISIT: NCP uses only serial 1, 2 */
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+};
+
+static struct platform_device *ncp_devices[] __initdata = {
+	&s3c_device_hsmmc1,
+	&s3c_device_i2c0,
+};
+
+static struct map_desc ncp_iodesc[] __initdata = {};
+
+static void __init ncp_map_io(void)
+{
+	s3c64xx_init_io(ncp_iodesc, ARRAY_SIZE(ncp_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(ncp_uartcfgs, ARRAY_SIZE(ncp_uartcfgs));
+}
+
+static void __init ncp_machine_init(void)
+{
+	s3c_i2c0_set_platdata(NULL);
+
+	platform_add_devices(ncp_devices, ARRAY_SIZE(ncp_devices));
+}
+
+MACHINE_START(NCP, "NCP")
+	/* Maintainer: Samsung Electronics */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+	.init_irq	= s3c6410_init_irq,
+	.map_io		= ncp_map_io,
+	.init_machine	= ncp_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
new file mode 100644
index 0000000..f7b1898
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -0,0 +1,96 @@
+/* linux/arch/arm/mach-s3c64xx/mach-smdk6400.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/regs-serial.h>
+
+#include <mach/s3c6400.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/iic.h>
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk6400_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+};
+
+static struct map_desc smdk6400_iodesc[] = {};
+
+static void __init smdk6400_map_io(void)
+{
+	s3c64xx_init_io(smdk6400_iodesc, ARRAY_SIZE(smdk6400_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(smdk6400_uartcfgs, ARRAY_SIZE(smdk6400_uartcfgs));
+}
+
+static struct platform_device *smdk6400_devices[] __initdata = {
+	&s3c_device_hsmmc1,
+	&s3c_device_i2c0,
+};
+
+static struct i2c_board_info i2c_devs[] __initdata = {
+	{ I2C_BOARD_INFO("wm8753", 0x1A), },
+	{ I2C_BOARD_INFO("24c08", 0x50), },
+};
+
+static void __init smdk6400_machine_init(void)
+{
+	i2c_register_board_info(0, i2c_devs, ARRAY_SIZE(i2c_devs));
+	platform_add_devices(smdk6400_devices, ARRAY_SIZE(smdk6400_devices));
+}
+
+MACHINE_START(SMDK6400, "SMDK6400")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+
+	.init_irq	= s3c6400_init_irq,
+	.map_io		= smdk6400_map_io,
+	.init_machine	= smdk6400_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
new file mode 100644
index 0000000..2d5afd2
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -0,0 +1,668 @@
+/* linux/arch/arm/mach-s3c64xx/mach-smdk6410.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/smsc911x.h>
+#include <linux/regulator/fixed.h>
+
+#ifdef CONFIG_SMDK6410_WM1190_EV1
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/pmic.h>
+#endif
+
+#ifdef CONFIG_SMDK6410_WM1192_EV1
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/pdata.h>
+#endif
+
+#include <video/platform_lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-fb.h>
+#include <mach/map.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <mach/regs-modem.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-sys.h>
+#include <mach/regs-srom.h>
+#include <plat/iic.h>
+#include <plat/fb.h>
+#include <plat/gpio-cfg.h>
+
+#include <mach/s3c6410.h>
+#include <plat/clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk6410_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+	[3] = {
+		.hwport	     = 3,
+		.flags	     = 0,
+		.ucon	     = UCON,
+		.ulcon	     = ULCON,
+		.ufcon	     = UFCON,
+	},
+};
+
+/* framebuffer and LCD setup. */
+
+/* GPF15 = LCD backlight control
+ * GPF13 => Panel power
+ * GPN5 = LCD nRESET signal
+ * PWM_TOUT1 => backlight brightness
+ */
+
+static void smdk6410_lcd_power_set(struct plat_lcd_data *pd,
+				   unsigned int power)
+{
+	if (power) {
+		gpio_direction_output(S3C64XX_GPF(13), 1);
+		gpio_direction_output(S3C64XX_GPF(15), 1);
+
+		/* fire nRESET on power up */
+		gpio_direction_output(S3C64XX_GPN(5), 0);
+		msleep(10);
+		gpio_direction_output(S3C64XX_GPN(5), 1);
+		msleep(1);
+	} else {
+		gpio_direction_output(S3C64XX_GPF(15), 0);
+		gpio_direction_output(S3C64XX_GPF(13), 0);
+	}
+}
+
+static struct plat_lcd_data smdk6410_lcd_power_data = {
+	.set_power	= smdk6410_lcd_power_set,
+};
+
+static struct platform_device smdk6410_lcd_powerdev = {
+	.name			= "platform-lcd",
+	.dev.parent		= &s3c_device_fb.dev,
+	.dev.platform_data	= &smdk6410_lcd_power_data,
+};
+
+static struct s3c_fb_pd_win smdk6410_fb_win0 = {
+	/* this is to ensure we use win0 */
+	.win_mode	= {
+		.pixclock	= 41094,
+		.left_margin	= 8,
+		.right_margin	= 13,
+		.upper_margin	= 7,
+		.lower_margin	= 5,
+		.hsync_len	= 3,
+		.vsync_len	= 1,
+		.xres		= 800,
+		.yres		= 480,
+	},
+	.max_bpp	= 32,
+	.default_bpp	= 16,
+};
+
+/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
+static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = {
+	.setup_gpio	= s3c64xx_fb_gpio_setup_24bpp,
+	.win[0]		= &smdk6410_fb_win0,
+	.vidcon0	= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+	.vidcon1	= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+};
+
+/*
+ * Configuring Ethernet on SMDK6410
+ *
+ * Both CS8900A and LAN9115 chips share one chip select mediated by CFG6.
+ * The constant address below corresponds to nCS1
+ *
+ *  1) Set CFGB2 p3 ON others off, no other CFGB selects "ethernet"
+ *  2) CFG6 needs to be switched to "LAN9115" side
+ */
+
+static struct resource smdk6410_smsc911x_resources[] = {
+	[0] = {
+		.start = S3C64XX_PA_XM0CSN1,
+		.end   = S3C64XX_PA_XM0CSN1 + SZ_64K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = S3C_EINT(10),
+		.end   = S3C_EINT(10),
+		.flags = IORESOURCE_IRQ | IRQ_TYPE_LEVEL_LOW,
+	},
+};
+
+static struct smsc911x_platform_config smdk6410_smsc911x_pdata = {
+	.irq_polarity  = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type      = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.flags         = SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
+
+static struct platform_device smdk6410_smsc911x = {
+	.name          = "smsc911x",
+	.id            = -1,
+	.num_resources = ARRAY_SIZE(smdk6410_smsc911x_resources),
+	.resource      = &smdk6410_smsc911x_resources[0],
+	.dev = {
+		.platform_data = &smdk6410_smsc911x_pdata,
+	},
+};
+
+#ifdef CONFIG_REGULATOR
+static struct regulator_consumer_supply smdk6410_b_pwr_5v_consumers[] = {
+	{
+		/* WM8580 */
+		.supply = "PVDD",
+		.dev_name = "0-001b",
+	},
+	{
+		/* WM8580 */
+		.supply = "AVDD",
+		.dev_name = "0-001b",
+	},
+};
+
+static struct regulator_init_data smdk6410_b_pwr_5v_data = {
+	.constraints = {
+		.always_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(smdk6410_b_pwr_5v_consumers),
+	.consumer_supplies = smdk6410_b_pwr_5v_consumers,
+};
+
+static struct fixed_voltage_config smdk6410_b_pwr_5v_pdata = {
+	.supply_name = "B_PWR_5V",
+	.microvolts = 5000000,
+	.init_data = &smdk6410_b_pwr_5v_data,
+	.gpio = -EINVAL,
+};
+
+static struct platform_device smdk6410_b_pwr_5v = {
+	.name          = "reg-fixed-voltage",
+	.id            = -1,
+	.dev = {
+		.platform_data = &smdk6410_b_pwr_5v_pdata,
+	},
+};
+#endif
+
+static struct map_desc smdk6410_iodesc[] = {};
+
+static struct platform_device *smdk6410_devices[] __initdata = {
+#ifdef CONFIG_SMDK6410_SD_CH0
+	&s3c_device_hsmmc0,
+#endif
+#ifdef CONFIG_SMDK6410_SD_CH1
+	&s3c_device_hsmmc1,
+#endif
+	&s3c_device_i2c0,
+	&s3c_device_i2c1,
+	&s3c_device_fb,
+	&s3c_device_ohci,
+	&s3c_device_usb_hsotg,
+	&s3c64xx_device_iisv4,
+
+#ifdef CONFIG_REGULATOR
+	&smdk6410_b_pwr_5v,
+#endif
+	&smdk6410_lcd_powerdev,
+
+	&smdk6410_smsc911x,
+};
+
+#ifdef CONFIG_REGULATOR
+/* ARM core */
+static struct regulator_consumer_supply smdk6410_vddarm_consumers[] = {
+	{
+		.supply = "vddarm",
+	}
+};
+
+/* VDDARM, BUCK1 on J5 */
+static struct regulator_init_data smdk6410_vddarm = {
+	.constraints = {
+		.name = "PVDD_ARM",
+		.min_uV = 1000000,
+		.max_uV = 1300000,
+		.always_on = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(smdk6410_vddarm_consumers),
+	.consumer_supplies = smdk6410_vddarm_consumers,
+};
+
+/* VDD_INT, BUCK2 on J5 */
+static struct regulator_init_data smdk6410_vddint = {
+	.constraints = {
+		.name = "PVDD_INT",
+		.min_uV = 1000000,
+		.max_uV = 1200000,
+		.always_on = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+	},
+};
+
+/* VDD_HI, LDO3 on J5 */
+static struct regulator_init_data smdk6410_vddhi = {
+	.constraints = {
+		.name = "PVDD_HI",
+		.always_on = 1,
+	},
+};
+
+/* VDD_PLL, LDO2 on J5 */
+static struct regulator_init_data smdk6410_vddpll = {
+	.constraints = {
+		.name = "PVDD_PLL",
+		.always_on = 1,
+	},
+};
+
+/* VDD_UH_MMC, LDO5 on J5 */
+static struct regulator_init_data smdk6410_vdduh_mmc = {
+	.constraints = {
+		.name = "PVDD_UH/PVDD_MMC",
+		.always_on = 1,
+	},
+};
+
+/* VCCM3BT, LDO8 on J5 */
+static struct regulator_init_data smdk6410_vccmc3bt = {
+	.constraints = {
+		.name = "PVCCM3BT",
+		.always_on = 1,
+	},
+};
+
+/* VCCM2MTV, LDO11 on J5 */
+static struct regulator_init_data smdk6410_vccm2mtv = {
+	.constraints = {
+		.name = "PVCCM2MTV",
+		.always_on = 1,
+	},
+};
+
+/* VDD_LCD, LDO12 on J5 */
+static struct regulator_init_data smdk6410_vddlcd = {
+	.constraints = {
+		.name = "PVDD_LCD",
+		.always_on = 1,
+	},
+};
+
+/* VDD_OTGI, LDO9 on J5 */
+static struct regulator_init_data smdk6410_vddotgi = {
+	.constraints = {
+		.name = "PVDD_OTGI",
+		.always_on = 1,
+	},
+};
+
+/* VDD_OTG, LDO14 on J5 */
+static struct regulator_init_data smdk6410_vddotg = {
+	.constraints = {
+		.name = "PVDD_OTG",
+		.always_on = 1,
+	},
+};
+
+/* VDD_ALIVE, LDO15 on J5 */
+static struct regulator_init_data smdk6410_vddalive = {
+	.constraints = {
+		.name = "PVDD_ALIVE",
+		.always_on = 1,
+	},
+};
+
+/* VDD_AUDIO, VLDO_AUDIO on J5 */
+static struct regulator_init_data smdk6410_vddaudio = {
+	.constraints = {
+		.name = "PVDD_AUDIO",
+		.always_on = 1,
+	},
+};
+#endif
+
+#ifdef CONFIG_SMDK6410_WM1190_EV1
+/* S3C64xx internal logic & PLL */
+static struct regulator_init_data wm8350_dcdc1_data = {
+	.constraints = {
+		.name = "PVDD_INT/PVDD_PLL",
+		.min_uV = 1200000,
+		.max_uV = 1200000,
+		.always_on = 1,
+		.apply_uV = 1,
+	},
+};
+
+/* Memory */
+static struct regulator_init_data wm8350_dcdc3_data = {
+	.constraints = {
+		.name = "PVDD_MEM",
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.always_on = 1,
+		.state_mem = {
+			 .uV = 1800000,
+			 .mode = REGULATOR_MODE_NORMAL,
+			 .enabled = 1,
+		},
+		.initial_state = PM_SUSPEND_MEM,
+	},
+};
+
+/* USB, EXT, PCM, ADC/DAC, USB, MMC */
+static struct regulator_consumer_supply wm8350_dcdc4_consumers[] = {
+	{
+		/* WM8580 */
+		.supply = "DVDD",
+		.dev_name = "0-001b",
+	},
+};
+
+static struct regulator_init_data wm8350_dcdc4_data = {
+	.constraints = {
+		.name = "PVDD_HI/PVDD_EXT/PVDD_SYS/PVCCM2MTV",
+		.min_uV = 3000000,
+		.max_uV = 3000000,
+		.always_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(wm8350_dcdc4_consumers),
+	.consumer_supplies = wm8350_dcdc4_consumers,
+};
+
+/* OTGi/1190-EV1 HPVDD & AVDD */
+static struct regulator_init_data wm8350_ldo4_data = {
+	.constraints = {
+		.name = "PVDD_OTGI/HPVDD/AVDD",
+		.min_uV = 1200000,
+		.max_uV = 1200000,
+		.apply_uV = 1,
+		.always_on = 1,
+	},
+};
+
+static struct {
+	int regulator;
+	struct regulator_init_data *initdata;
+} wm1190_regulators[] = {
+	{ WM8350_DCDC_1, &wm8350_dcdc1_data },
+	{ WM8350_DCDC_3, &wm8350_dcdc3_data },
+	{ WM8350_DCDC_4, &wm8350_dcdc4_data },
+	{ WM8350_DCDC_6, &smdk6410_vddarm },
+	{ WM8350_LDO_1, &smdk6410_vddalive },
+	{ WM8350_LDO_2, &smdk6410_vddotg },
+	{ WM8350_LDO_3, &smdk6410_vddlcd },
+	{ WM8350_LDO_4, &wm8350_ldo4_data },
+};
+
+static int __init smdk6410_wm8350_init(struct wm8350 *wm8350)
+{
+	int i;
+
+	/* Configure the IRQ line */
+	s3c_gpio_setpull(S3C64XX_GPN(12), S3C_GPIO_PULL_UP);
+
+	/* Instantiate the regulators */
+	for (i = 0; i < ARRAY_SIZE(wm1190_regulators); i++)
+		wm8350_register_regulator(wm8350,
+					  wm1190_regulators[i].regulator,
+					  wm1190_regulators[i].initdata);
+
+	return 0;
+}
+
+static struct wm8350_platform_data __initdata smdk6410_wm8350_pdata = {
+	.init = smdk6410_wm8350_init,
+	.irq_high = 1,
+	.irq_base = IRQ_BOARD_START,
+};
+#endif
+
+#ifdef CONFIG_SMDK6410_WM1192_EV1
+static struct gpio_led wm1192_pmic_leds[] = {
+	{
+		.name = "PMIC:red:power",
+		.gpio = GPIO_BOARD_START + 3,
+		.default_state = LEDS_GPIO_DEFSTATE_ON,
+	},
+};
+
+static struct gpio_led_platform_data wm1192_pmic_led = {
+	.num_leds = ARRAY_SIZE(wm1192_pmic_leds),
+	.leds = wm1192_pmic_leds,
+};
+
+static struct platform_device wm1192_pmic_led_dev = {
+	.name          = "leds-gpio",
+	.id            = -1,
+	.dev = {
+		.platform_data = &wm1192_pmic_led,
+	},
+};
+
+static int wm1192_pre_init(struct wm831x *wm831x)
+{
+	int ret;
+
+	/* Configure the IRQ line */
+	s3c_gpio_setpull(S3C64XX_GPN(12), S3C_GPIO_PULL_UP);
+
+	ret = platform_device_register(&wm1192_pmic_led_dev);
+	if (ret != 0)
+		dev_err(wm831x->dev, "Failed to add PMIC LED: %d\n", ret);
+
+	return 0;
+}
+
+static struct wm831x_backlight_pdata wm1192_backlight_pdata = {
+	.isink = 1,
+	.max_uA = 27554,
+};
+
+static struct regulator_init_data wm1192_dcdc3 = {
+	.constraints = {
+		.name = "PVDD_MEM/PVDD_GPS",
+		.always_on = 1,
+	},
+};
+
+static struct regulator_consumer_supply wm1192_ldo1_consumers[] = {
+	{ .supply = "DVDD", .dev_name = "0-001b", },   /* WM8580 */
+};
+
+static struct regulator_init_data wm1192_ldo1 = {
+	.constraints = {
+		.name = "PVDD_LCD/PVDD_EXT",
+		.always_on = 1,
+	},
+	.consumer_supplies = wm1192_ldo1_consumers,
+	.num_consumer_supplies = ARRAY_SIZE(wm1192_ldo1_consumers),
+};
+
+static struct wm831x_status_pdata wm1192_led7_pdata = {
+	.name = "LED7:green:",
+};
+
+static struct wm831x_status_pdata wm1192_led8_pdata = {
+	.name = "LED8:green:",
+};
+
+static struct wm831x_pdata smdk6410_wm1192_pdata = {
+	.pre_init = wm1192_pre_init,
+	.irq_base = IRQ_BOARD_START,
+
+	.backlight = &wm1192_backlight_pdata,
+	.dcdc = {
+		&smdk6410_vddarm,  /* DCDC1 */
+		&smdk6410_vddint,  /* DCDC2 */
+		&wm1192_dcdc3,
+	},
+	.gpio_base = GPIO_BOARD_START,
+	.ldo = {
+		 &wm1192_ldo1,        /* LDO1 */
+		 &smdk6410_vdduh_mmc, /* LDO2 */
+		 NULL,                /* LDO3 NC */
+		 &smdk6410_vddotgi,   /* LDO4 */
+		 &smdk6410_vddotg,    /* LDO5 */
+		 &smdk6410_vddhi,     /* LDO6 */
+		 &smdk6410_vddaudio,  /* LDO7 */
+		 &smdk6410_vccm2mtv,  /* LDO8 */
+		 &smdk6410_vddpll,    /* LDO9 */
+		 &smdk6410_vccmc3bt,  /* LDO10 */
+		 &smdk6410_vddalive,  /* LDO11 */
+	},
+	.status = {
+		&wm1192_led7_pdata,
+		&wm1192_led8_pdata,
+	},
+};
+#endif
+
+static struct i2c_board_info i2c_devs0[] __initdata = {
+	{ I2C_BOARD_INFO("24c08", 0x50), },
+	{ I2C_BOARD_INFO("wm8580", 0x1b), },
+
+#ifdef CONFIG_SMDK6410_WM1192_EV1
+	{ I2C_BOARD_INFO("wm8312", 0x34),
+	  .platform_data = &smdk6410_wm1192_pdata,
+	  .irq = S3C_EINT(12),
+	},
+#endif
+
+#ifdef CONFIG_SMDK6410_WM1190_EV1
+	{ I2C_BOARD_INFO("wm8350", 0x1a),
+	  .platform_data = &smdk6410_wm8350_pdata,
+	  .irq = S3C_EINT(12),
+	},
+#endif
+};
+
+static struct i2c_board_info i2c_devs1[] __initdata = {
+	{ I2C_BOARD_INFO("24c128", 0x57), },	/* Samsung S524AD0XD1 */
+};
+
+static void __init smdk6410_map_io(void)
+{
+	u32 tmp;
+
+	s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
+
+	/* set the LCD type */
+
+	tmp = __raw_readl(S3C64XX_SPCON);
+	tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
+	tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
+	__raw_writel(tmp, S3C64XX_SPCON);
+
+	/* remove the lcd bypass */
+	tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
+	tmp &= ~MIFPCON_LCD_BYPASS;
+	__raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
+}
+
+static void __init smdk6410_machine_init(void)
+{
+	u32 cs1;
+
+	s3c_i2c0_set_platdata(NULL);
+	s3c_i2c1_set_platdata(NULL);
+	s3c_fb_set_platdata(&smdk6410_lcd_pdata);
+
+	/* configure nCS1 width to 16 bits */
+
+	cs1 = __raw_readl(S3C64XX_SROM_BW) &
+		    ~(S3C64XX_SROM_BW__CS_MASK << S3C64XX_SROM_BW__NCS1__SHIFT);
+	cs1 |= ((1 << S3C64XX_SROM_BW__DATAWIDTH__SHIFT) |
+		(1 << S3C64XX_SROM_BW__WAITENABLE__SHIFT) |
+		(1 << S3C64XX_SROM_BW__BYTEENABLE__SHIFT)) <<
+						   S3C64XX_SROM_BW__NCS1__SHIFT;
+	__raw_writel(cs1, S3C64XX_SROM_BW);
+
+	/* set timing for nCS1 suitable for ethernet chip */
+
+	__raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) |
+		     (6 << S3C64XX_SROM_BCX__TACP__SHIFT) |
+		     (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) |
+		     (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) |
+		     (0xe << S3C64XX_SROM_BCX__TACC__SHIFT) |
+		     (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) |
+		     (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1);
+
+	gpio_request(S3C64XX_GPN(5), "LCD power");
+	gpio_request(S3C64XX_GPF(13), "LCD power");
+	gpio_request(S3C64XX_GPF(15), "LCD power");
+
+	i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
+	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+
+	platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
+}
+
+MACHINE_START(SMDK6410, "SMDK6410")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
+
+	.init_irq	= s3c6410_init_irq,
+	.map_io		= smdk6410_map_io,
+	.init_machine	= smdk6410_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c
new file mode 100644
index 0000000..b8ac459
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/pm.c
@@ -0,0 +1,173 @@
+/* linux/arch/arm/plat-s3c64xx/pm.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX CPU PM support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/pm.h>
+#include <mach/regs-sys.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-syscon-power.h>
+#include <mach/regs-gpio-memport.h>
+
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+#include <mach/gpio-bank-n.h>
+
+void s3c_pm_debug_smdkled(u32 set, u32 clear)
+{
+	unsigned long flags;
+	u32 reg;
+
+	local_irq_save(flags);
+	reg = __raw_readl(S3C64XX_GPNCON);
+	reg &= ~(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) |
+		 S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15));
+	reg |= S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) |
+	       S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15);
+	__raw_writel(reg, S3C64XX_GPNCON);
+
+	reg = __raw_readl(S3C64XX_GPNDAT);
+	reg &= ~(clear << 12);
+	reg |= set << 12;
+	__raw_writel(reg, S3C64XX_GPNDAT);
+
+	local_irq_restore(flags);
+}
+#endif
+
+static struct sleep_save core_save[] = {
+	SAVE_ITEM(S3C_APLL_LOCK),
+	SAVE_ITEM(S3C_MPLL_LOCK),
+	SAVE_ITEM(S3C_EPLL_LOCK),
+	SAVE_ITEM(S3C_CLK_SRC),
+	SAVE_ITEM(S3C_CLK_DIV0),
+	SAVE_ITEM(S3C_CLK_DIV1),
+	SAVE_ITEM(S3C_CLK_DIV2),
+	SAVE_ITEM(S3C_CLK_OUT),
+	SAVE_ITEM(S3C_HCLK_GATE),
+	SAVE_ITEM(S3C_PCLK_GATE),
+	SAVE_ITEM(S3C_SCLK_GATE),
+	SAVE_ITEM(S3C_MEM0_GATE),
+
+	SAVE_ITEM(S3C_EPLL_CON1),
+	SAVE_ITEM(S3C_EPLL_CON0),
+
+	SAVE_ITEM(S3C64XX_MEM0DRVCON),
+	SAVE_ITEM(S3C64XX_MEM1DRVCON),
+
+#ifndef CONFIG_CPU_FREQ
+	SAVE_ITEM(S3C_APLL_CON),
+	SAVE_ITEM(S3C_MPLL_CON),
+#endif
+};
+
+static struct sleep_save misc_save[] = {
+	SAVE_ITEM(S3C64XX_AHB_CON0),
+	SAVE_ITEM(S3C64XX_AHB_CON1),
+	SAVE_ITEM(S3C64XX_AHB_CON2),
+	
+	SAVE_ITEM(S3C64XX_SPCON),
+
+	SAVE_ITEM(S3C64XX_MEM0CONSTOP),
+	SAVE_ITEM(S3C64XX_MEM1CONSTOP),
+	SAVE_ITEM(S3C64XX_MEM0CONSLP0),
+	SAVE_ITEM(S3C64XX_MEM0CONSLP1),
+	SAVE_ITEM(S3C64XX_MEM1CONSLP),
+};
+
+void s3c_pm_configure_extint(void)
+{
+	__raw_writel(s3c_irqwake_eintmask, S3C64XX_EINT_MASK);
+}
+
+void s3c_pm_restore_core(void)
+{
+	__raw_writel(0, S3C64XX_EINT_MASK);
+
+	s3c_pm_debug_smdkled(1 << 2, 0);
+
+	s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+	s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
+}
+
+void s3c_pm_save_core(void)
+{
+	s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
+	s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
+}
+
+/* since both s3c6400 and s3c6410 share the same sleep pm calls, we
+ * put the per-cpu code in here until any new cpu comes along and changes
+ * this.
+ */
+
+static void s3c64xx_cpu_suspend(void)
+{
+	unsigned long tmp;
+
+	/* set our standby method to sleep */
+
+	tmp = __raw_readl(S3C64XX_PWR_CFG);
+	tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK;
+	tmp |= S3C64XX_PWRCFG_CFG_WFI_SLEEP;
+	__raw_writel(tmp, S3C64XX_PWR_CFG);
+
+	/* clear any old wakeup */
+
+	__raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT),
+		     S3C64XX_WAKEUP_STAT);
+
+	/* set the LED state to 0110 over sleep */
+	s3c_pm_debug_smdkled(3 << 1, 0xf);
+
+	/* issue the standby signal into the pm unit. Note, we
+	 * issue a write-buffer drain just in case */
+
+	tmp = 0;
+
+	asm("b 1f\n\t"
+	    ".align 5\n\t"
+	    "1:\n\t"
+	    "mcr p15, 0, %0, c7, c10, 5\n\t"
+	    "mcr p15, 0, %0, c7, c10, 4\n\t"
+	    "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
+
+	/* we should never get past here */
+
+	panic("sleep resumed to originator?");
+}
+
+static void s3c64xx_pm_prepare(void)
+{
+	/* store address of resume. */
+	__raw_writel(virt_to_phys(s3c_cpu_resume), S3C64XX_INFORM0);
+
+	/* ensure previous wakeup state is cleared before sleeping */
+	__raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT), S3C64XX_WAKEUP_STAT);
+}
+
+static int s3c64xx_pm_init(void)
+{
+	pm_cpu_prep = s3c64xx_pm_prepare;
+	pm_cpu_sleep = s3c64xx_cpu_suspend;
+	pm_uart_udivslot = 1;
+	return 0;
+}
+
+arch_initcall(s3c64xx_pm_init);
diff --git a/arch/arm/mach-s3c64xx/s3c6400.c b/arch/arm/mach-s3c64xx/s3c6400.c
new file mode 100644
index 0000000..707e34e
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/s3c6400.c
@@ -0,0 +1,89 @@
+/* linux/arch/arm/mach-s3c64xx/cpu.c
+ *
+ * Copyright 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/regs-serial.h>
+#include <mach/regs-clock.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/sdhci.h>
+#include <plat/iic-core.h>
+#include <mach/s3c6400.h>
+
+void __init s3c6400_map_io(void)
+{
+	/* setup SDHCI */
+
+	s3c6400_default_sdhci0();
+	s3c6400_default_sdhci1();
+	s3c6400_default_sdhci2();
+
+	/* the i2c devices are directly compatible with s3c2440 */
+	s3c_i2c0_setname("s3c2440-i2c");
+
+	s3c_device_nand.name = "s3c6400-nand";
+}
+
+void __init s3c6400_init_clocks(int xtal)
+{
+	s3c64xx_register_clocks(xtal, S3C6400_CLKDIV0_ARM_MASK);
+	s3c6400_setup_clocks();
+}
+
+void __init s3c6400_init_irq(void)
+{
+	/* VIC0 does not have IRQS 5..7,
+	 * VIC1 is fully populated. */
+	s3c64xx_init_irq(~0 & ~(0xf << 5), ~0);
+}
+
+struct sysdev_class s3c6400_sysclass = {
+	.name	= "s3c6400-core",
+};
+
+static struct sys_device s3c6400_sysdev = {
+	.cls	= &s3c6400_sysclass,
+};
+
+static int __init s3c6400_core_init(void)
+{
+	return sysdev_class_register(&s3c6400_sysclass);
+}
+
+core_initcall(s3c6400_core_init);
+
+int __init s3c6400_init(void)
+{
+	printk("S3C6400: Initialising architecture\n");
+
+	return sysdev_register(&s3c6400_sysdev);
+}
diff --git a/arch/arm/mach-s3c64xx/s3c6410.c b/arch/arm/mach-s3c64xx/s3c6410.c
new file mode 100644
index 0000000..59635d1
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/s3c6410.c
@@ -0,0 +1,91 @@
+/* linux/arch/arm/mach-s3c64xx/s3c6410.c
+ *
+ * Copyright 2008 Simtec Electronics
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/regs-serial.h>
+#include <mach/regs-clock.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/sdhci.h>
+#include <plat/iic-core.h>
+#include <mach/s3c6400.h>
+#include <mach/s3c6410.h>
+
+void __init s3c6410_map_io(void)
+{
+	/* initialise device information early */
+	s3c6410_default_sdhci0();
+	s3c6410_default_sdhci1();
+	s3c6410_default_sdhci2();
+
+	/* the i2c devices are directly compatible with s3c2440 */
+	s3c_i2c0_setname("s3c2440-i2c");
+	s3c_i2c1_setname("s3c2440-i2c");
+
+	s3c_device_nand.name = "s3c6400-nand";
+}
+
+void __init s3c6410_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
+	s3c64xx_register_clocks(xtal, S3C6410_CLKDIV0_ARM_MASK);
+	s3c6400_setup_clocks();
+}
+
+void __init s3c6410_init_irq(void)
+{
+	/* VIC0 is missing IRQ7, VIC1 is fully populated. */
+	s3c64xx_init_irq(~0 & ~(1 << 7), ~0);
+}
+
+struct sysdev_class s3c6410_sysclass = {
+	.name	= "s3c6410-core",
+};
+
+static struct sys_device s3c6410_sysdev = {
+	.cls	= &s3c6410_sysclass,
+};
+
+static int __init s3c6410_core_init(void)
+{
+	return sysdev_class_register(&s3c6410_sysclass);
+}
+
+core_initcall(s3c6410_core_init);
+
+int __init s3c6410_init(void)
+{
+	printk("S3C6410: Initialising architecture\n");
+
+	return sysdev_register(&s3c6410_sysdev);
+}
diff --git a/arch/arm/plat-s3c64xx/setup-fb-24bpp.c b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c
similarity index 100%
rename from arch/arm/plat-s3c64xx/setup-fb-24bpp.c
rename to arch/arm/mach-s3c64xx/setup-fb-24bpp.c
diff --git a/arch/arm/mach-s3c64xx/setup-i2c0.c b/arch/arm/mach-s3c64xx/setup-i2c0.c
new file mode 100644
index 0000000..d1b11e6
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/setup-i2c0.c
@@ -0,0 +1,31 @@
+/* linux/arch/arm/plat-s3c64xx/setup-i2c0.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Base S3C64XX I2C bus 0 gpio configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+struct platform_device; /* don't need the contents */
+
+#include <mach/gpio.h>
+#include <mach/gpio-bank-b.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c0_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgpin(S3C64XX_GPB(5), S3C64XX_GPB5_I2C_SCL0);
+	s3c_gpio_cfgpin(S3C64XX_GPB(6), S3C64XX_GPB6_I2C_SDA0);
+	s3c_gpio_setpull(S3C64XX_GPB(5), S3C_GPIO_PULL_UP);
+	s3c_gpio_setpull(S3C64XX_GPB(6), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-s3c64xx/setup-i2c1.c b/arch/arm/mach-s3c64xx/setup-i2c1.c
new file mode 100644
index 0000000..2dce57d
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/setup-i2c1.c
@@ -0,0 +1,31 @@
+/* linux/arch/arm/plat-s3c64xx/setup-i2c1.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Base S3C64XX I2C bus 1 gpio configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+struct platform_device; /* don't need the contents */
+
+#include <mach/gpio.h>
+#include <mach/gpio-bank-b.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c1_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgpin(S3C64XX_GPB(2), S3C64XX_GPB2_I2C_SCL1);
+	s3c_gpio_cfgpin(S3C64XX_GPB(3), S3C64XX_GPB3_I2C_SDA1);
+	s3c_gpio_setpull(S3C64XX_GPB(2), S3C_GPIO_PULL_UP);
+	s3c_gpio_setpull(S3C64XX_GPB(3), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/plat-s3c64xx/setup-sdhci-gpio.c b/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c
similarity index 100%
rename from arch/arm/plat-s3c64xx/setup-sdhci-gpio.c
rename to arch/arm/mach-s3c64xx/setup-sdhci-gpio.c
diff --git a/arch/arm/mach-s3c64xx/setup-sdhci.c b/arch/arm/mach-s3c64xx/setup-sdhci.c
new file mode 100644
index 0000000..1a94203
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/setup-sdhci.c
@@ -0,0 +1,72 @@
+/* linux/arch/arm/mach-s3c64xx/setup-sdhci.c
+ *
+ * Copyright 2008 Simtec Electronics
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C6400/S3C6410 - Helper functions for settign up SDHCI device(s) (HSMMC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include <plat/regs-sdhci.h>
+#include <plat/sdhci.h>
+
+/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
+
+char *s3c64xx_hsmmc_clksrcs[4] = {
+	[0] = "hsmmc",
+	[1] = "hsmmc",
+	[2] = "mmc_bus",
+	/* [3] = "48m", - note not successfully used yet */
+};
+
+void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
+				  void __iomem *r,
+				  struct mmc_ios *ios,
+				  struct mmc_card *card)
+{
+	u32 ctrl2, ctrl3;
+
+	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
+	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
+	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
+		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
+		  S3C_SDHCI_CTRL2_ENFBCLKRX |
+		  S3C_SDHCI_CTRL2_DFCNT_NONE |
+		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
+
+	if (ios->clock < 25 * 1000000)
+		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
+			 S3C_SDHCI_CTRL3_FCSEL2 |
+			 S3C_SDHCI_CTRL3_FCSEL1 |
+			 S3C_SDHCI_CTRL3_FCSEL0);
+	else
+		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
+
+	printk(KERN_INFO "%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
+	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
+	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
+}
+
+void s3c6410_setup_sdhci_cfg_card(struct platform_device *dev,
+				  void __iomem *r,
+				  struct mmc_ios *ios,
+				  struct mmc_card *card)
+{
+	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
+
+	s3c6400_setup_sdhci_cfg_card(dev, r, ios, card);
+}
diff --git a/arch/arm/mach-s3c64xx/sleep.S b/arch/arm/mach-s3c64xx/sleep.S
new file mode 100644
index 0000000..b2ef443
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/sleep.S
@@ -0,0 +1,144 @@
+/* linux/arch/arm/plat-s3c64xx/sleep.S
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX CPU sleep code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/map.h>
+
+#undef S3C64XX_VA_GPIO
+#define S3C64XX_VA_GPIO (0x0)
+
+#include <mach/regs-gpio.h>
+#include <mach/gpio-bank-n.h>
+
+#define LL_UART (S3C_PA_UART + (0x400 * CONFIG_S3C_LOWLEVEL_UART_PORT))
+
+	.text
+
+	/* s3c_cpu_save
+	 *
+	 * Save enough processor state to allow the restart of the pm.c
+	 * code after resume.
+	 *
+	 * entry:
+	 *	r0 = pointer to the save block
+	*/
+
+ENTRY(s3c_cpu_save)
+	stmfd	sp!, { r4 - r12, lr }
+
+	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ Translation Table BASE0
+	mrc	p15, 0, r7, c2, c0, 1	@ Translation Table BASE1
+	mrc	p15, 0, r8, c2, c0, 2	@ Translation Table Control
+	mrc	p15, 0, r9, c1, c0, 0	@ Control register
+	mrc	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
+	mrc	p15, 0, r11, c1, c0, 2	@ Co-processor access controls
+
+	stmia	r0, { r4 - r13 }	@ Save CP registers and SP
+
+	@@ save our state to ram
+	bl	s3c_pm_cb_flushcache
+
+	@@ call final suspend code
+	ldr	r0, =pm_cpu_sleep
+	ldr	pc, [r0]
+	
+	@@ return to the caller, after the MMU is turned on.
+	@@ restore the last bits of the stack and return.
+resume_with_mmu:
+	ldmfd	sp!, { r4 - r12, pc }	@ return, from sp from s3c_cpu_save
+
+	.data
+
+	/* the next bit is code, but it requires easy access to the
+	 * s3c_sleep_save_phys data before the MMU is switched on, so
+	 * we store the code that needs this variable in the .data where
+	 * the value can be written to (the .text segment is RO).
+	*/
+
+	.global	s3c_sleep_save_phys
+s3c_sleep_save_phys:
+	.word	0
+
+	/* Sleep magic, the word before the resume entry point so that the
+	 * bootloader can check for a resumeable image. */
+
+	.word	0x2bedf00d
+
+	/* s3c_cpu_reusme
+	 *
+	 * This is the entry point, stored by whatever method the bootloader
+	 * requires to get the kernel runnign again. This code expects to be
+	 * entered with no caches live and the MMU disabled. It will then
+	 * restore the MMU and other basic CP registers saved and restart
+	 * the kernel C code to finish the resume code.
+	*/
+
+ENTRY(s3c_cpu_resume)
+	msr	cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+	ldr	r2, =LL_UART		/* for debug */
+
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+	/* Initialise the GPIO state if we are debugging via the SMDK LEDs,
+	 * as the uboot version supplied resets these to inputs during the
+	 * resume checks.
+	*/
+
+	ldr	r3, =S3C64XX_PA_GPIO
+	ldr	r0, [ r3, #S3C64XX_GPNCON ]
+	bic	r0, r0, #(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) | \
+			  S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15))
+	orr	r0, r0, #(S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) | \
+			  S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15))
+	str	r0, [ r3, #S3C64XX_GPNCON ]
+
+	ldr	r0, [ r3, #S3C64XX_GPNDAT ]
+	bic	r0, r0, #0xf << 12			@ GPN12..15
+	orr	r0, r0, #1 << 15			@ GPN15
+	str	r0, [ r3, #S3C64XX_GPNDAT ]
+#endif
+
+	/* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
+	 * are thoroughly cleaned just in case the bootloader didn't do it
+	 * for us. */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c14, 0		@ clean+invalidate D cache
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r0, c7, c15, 0		@ clean+invalidate cache
+	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
+	@@mcr	p15, 0, r0, c8, c7, 0		@ invalidate I + D TLBs
+	@@mcr	p15, 0, r0, c7, c7, 0		@ Invalidate I + D caches
+
+	ldr	r0, s3c_sleep_save_phys
+	ldmia	r0, { r4 - r13 }
+
+	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ Translation Table BASE0
+	mcr	p15, 0, r7, c2, c0, 1	@ Translation Table BASE1
+	mcr	p15, 0, r8, c2, c0, 2	@ Translation Table Control
+	mcr	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
+
+	mov	r0, #0			@ restore copro access controls
+	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access controls
+	mcr 	p15, 0, r0, c7, c5, 4
+
+	ldr	r2, =resume_with_mmu
+	mcr	p15, 0, r9, c1, c0, 0		/* turn mmu back on */
+	nop
+	mov	pc, r2				/* jump back */
+
+	.end
diff --git a/arch/arm/mach-s5p6440/Kconfig b/arch/arm/mach-s5p6440/Kconfig
new file mode 100644
index 0000000..4c29ff8
--- /dev/null
+++ b/arch/arm/mach-s5p6440/Kconfig
@@ -0,0 +1,21 @@
+# arch/arm/mach-s5p6440/Kconfig
+#
+# Copyright (c) 2009 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+if ARCH_S5P6440
+
+config CPU_S5P6440
+	bool
+	help
+	  Enable S5P6440 CPU support
+
+config MACH_SMDK6440
+	bool "SMDK6440"
+	select CPU_S5P6440
+	help
+	  Machine support for the Samsung SMDK6440
+
+endif
diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile
new file mode 100644
index 0000000..1ad894b
--- /dev/null
+++ b/arch/arm/mach-s5p6440/Makefile
@@ -0,0 +1,19 @@
+# arch/arm/mach-s5p6440/Makefile
+#
+# Copyright (c) 2009 Samsung Electronics Co., Ltd.
+# 		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+# Core support for S5P6440 system
+
+obj-$(CONFIG_CPU_S5P6440)	+= cpu.o init.o clock.o gpio.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDK6440)	+= mach-smdk6440.o
diff --git a/arch/arm/mach-s5p6440/Makefile.boot b/arch/arm/mach-s5p6440/Makefile.boot
new file mode 100644
index 0000000..ff90aa1
--- /dev/null
+++ b/arch/arm/mach-s5p6440/Makefile.boot
@@ -0,0 +1,2 @@
+   zreladdr-y	:= 0x20008000
+params_phys-y	:= 0x20000100
diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c
new file mode 100644
index 0000000..b2672e1
--- /dev/null
+++ b/arch/arm/mach-s5p6440/clock.c
@@ -0,0 +1,698 @@
+/* linux/arch/arm/mach-s5p6440/clock.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/cpu-freq.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p-clock.h>
+#include <plat/pll.h>
+#include <plat/s5p6440.h>
+
+/* APLL Mux output clock */
+static struct clksrc_clk clk_mout_apll = {
+	.clk    = {
+		.name           = "mout_apll",
+		.id             = -1,
+	},
+	.sources        = &clk_src_apll,
+	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
+};
+
+static int s5p6440_epll_enable(struct clk *clk, int enable)
+{
+	unsigned int ctrlbit = clk->ctrlbit;
+	unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit;
+
+	if (enable)
+		__raw_writel(epll_con | ctrlbit, S5P_EPLL_CON);
+	else
+		__raw_writel(epll_con, S5P_EPLL_CON);
+
+	return 0;
+}
+
+static unsigned long s5p6440_epll_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+static u32 epll_div[][5] = {
+	{ 36000000,	0,	48, 1, 4 },
+	{ 48000000,	0,	32, 1, 3 },
+	{ 60000000,	0,	40, 1, 3 },
+	{ 72000000,	0,	48, 1, 3 },
+	{ 84000000,	0,	28, 1, 2 },
+	{ 96000000,	0,	32, 1, 2 },
+	{ 32768000,	45264,	43, 1, 4 },
+	{ 45158000,	6903,	30, 1, 3 },
+	{ 49152000,	50332,	32, 1, 3 },
+	{ 67738000,	10398,	45, 1, 3 },
+	{ 73728000,	9961,	49, 1, 3 }
+};
+
+static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned int epll_con, epll_con_k;
+	unsigned int i;
+
+	if (clk->rate == rate)	/* Return if nothing changed */
+		return 0;
+
+	epll_con = __raw_readl(S5P_EPLL_CON);
+	epll_con_k = __raw_readl(S5P_EPLL_CON_K);
+
+	epll_con_k &= ~(PLL90XX_KDIV_MASK);
+	epll_con &= ~(PLL90XX_MDIV_MASK | PLL90XX_PDIV_MASK | PLL90XX_SDIV_MASK);
+
+	for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
+		 if (epll_div[i][0] == rate) {
+			epll_con_k |= (epll_div[i][1] << PLL90XX_KDIV_SHIFT);
+			epll_con |= (epll_div[i][2] << PLL90XX_MDIV_SHIFT) |
+				    (epll_div[i][3] << PLL90XX_PDIV_SHIFT) |
+				    (epll_div[i][4] << PLL90XX_SDIV_SHIFT);
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(epll_div)) {
+		printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__);
+		return -EINVAL;
+	}
+
+	__raw_writel(epll_con, S5P_EPLL_CON);
+	__raw_writel(epll_con_k, S5P_EPLL_CON_K);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+static struct clk_ops s5p6440_epll_ops = {
+	.get_rate = s5p6440_epll_get_rate,
+	.set_rate = s5p6440_epll_set_rate,
+};
+
+static struct clksrc_clk clk_mout_epll = {
+	.clk    = {
+		.name           = "mout_epll",
+		.id             = -1,
+	},
+	.sources        = &clk_src_epll,
+	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 2, .size = 1 },
+};
+
+static struct clksrc_clk clk_mout_mpll = {
+	.clk = {
+		.name           = "mout_mpll",
+		.id             = -1,
+	},
+	.sources        = &clk_src_mpll,
+	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 },
+};
+
+static struct clk clk_h_low = {
+	.name		= "hclk_low",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+	.ops		= &clk_ops_def_setrate,
+};
+
+static struct clk clk_p_low = {
+	.name		= "pclk_low",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+	.ops		= &clk_ops_def_setrate,
+};
+
+enum perf_level {
+	L0 = 532*1000,
+	L1 = 266*1000,
+	L2 = 133*1000,
+};
+
+static const u32 clock_table[][3] = {
+	/*{ARM_CLK, DIVarm, DIVhclk}*/
+	{L0 * 1000, (0 << ARM_DIV_RATIO_SHIFT), (3 << S5P_CLKDIV0_HCLK_SHIFT)},
+	{L1 * 1000, (1 << ARM_DIV_RATIO_SHIFT), (1 << S5P_CLKDIV0_HCLK_SHIFT)},
+	{L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P_CLKDIV0_HCLK_SHIFT)},
+};
+
+static unsigned long s5p6440_armclk_get_rate(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk->parent);
+	u32 clkdiv;
+
+	/* divisor mask starts at bit0, so no need to shift */
+	clkdiv = __raw_readl(ARM_CLK_DIV) & ARM_DIV_MASK;
+
+	return rate / (clkdiv + 1);
+}
+
+static unsigned long s5p6440_armclk_round_rate(struct clk *clk,
+						unsigned long rate)
+{
+	u32 iter;
+
+	for (iter = 1 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
+		if (rate > clock_table[iter][0])
+			return clock_table[iter-1][0];
+	}
+
+	return clock_table[ARRAY_SIZE(clock_table) - 1][0];
+}
+
+static int s5p6440_armclk_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 round_tmp;
+	u32 iter;
+	u32 clk_div0_tmp;
+	u32 cur_rate = clk->ops->get_rate(clk);
+	unsigned long flags;
+
+	round_tmp = clk->ops->round_rate(clk, rate);
+	if (round_tmp == cur_rate)
+		return 0;
+
+
+	for (iter = 0 ; iter < ARRAY_SIZE(clock_table) ; iter++) {
+		if (round_tmp == clock_table[iter][0])
+			break;
+	}
+
+	if (iter >= ARRAY_SIZE(clock_table))
+		iter = ARRAY_SIZE(clock_table) - 1;
+
+	local_irq_save(flags);
+	if (cur_rate > round_tmp) {
+		/* Frequency Down */
+		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
+		clk_div0_tmp |= clock_table[iter][1];
+		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
+				~(S5P_CLKDIV0_HCLK_MASK);
+		clk_div0_tmp |= clock_table[iter][2];
+		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+
+	} else {
+		/* Frequency Up */
+		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) &
+				~(S5P_CLKDIV0_HCLK_MASK);
+		clk_div0_tmp |= clock_table[iter][2];
+		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+
+		clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
+		clk_div0_tmp |= clock_table[iter][1];
+		__raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+		}
+	local_irq_restore(flags);
+
+	clk->rate = clock_table[iter][0];
+
+	return 0;
+}
+
+static struct clk_ops s5p6440_clkarm_ops = {
+	.get_rate	= s5p6440_armclk_get_rate,
+	.set_rate	= s5p6440_armclk_set_rate,
+	.round_rate	= s5p6440_armclk_round_rate,
+};
+
+static unsigned long s5p6440_clk_doutmpll_get_rate(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk->parent);
+
+	if (__raw_readl(S5P_CLK_DIV0) & S5P_CLKDIV0_MPLL_MASK)
+		rate /= 2;
+
+	return rate;
+}
+
+static struct clk clk_dout_mpll = {
+	.name		= "dout_mpll",
+	.id		= -1,
+	.parent		= &clk_mout_mpll.clk,
+	.ops            = &(struct clk_ops) {
+		.get_rate	= s5p6440_clk_doutmpll_get_rate,
+	},
+};
+
+int s5p6440_clk48m_ctrl(struct clk *clk, int enable)
+{
+	unsigned long flags;
+	u32 val;
+
+	/* can't rely on clock lock, this register has other usages */
+	local_irq_save(flags);
+
+	val = __raw_readl(S5P_OTHERS);
+	if (enable)
+		val |= S5P_OTHERS_USB_SIG_MASK;
+	else
+		val &= ~S5P_OTHERS_USB_SIG_MASK;
+
+	__raw_writel(val, S5P_OTHERS);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static int s5p6440_pclk_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLK_GATE_PCLK, clk, enable);
+}
+
+static int s5p6440_hclk0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLK_GATE_HCLK0, clk, enable);
+}
+
+static int s5p6440_hclk1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLK_GATE_HCLK1, clk, enable);
+}
+
+static int s5p6440_sclk_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable);
+}
+
+static int s5p6440_mem_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable);
+}
+
+/*
+ * The following clocks will be disabled during clock initialization. It is
+ * recommended to keep the following clocks disabled until the driver requests
+ * for enabling the clock.
+ */
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s5p6440_mem_ctrl,
+		.ctrlbit	= S5P_CLKCON_MEM0_HCLK_NFCON,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_TSADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_IIC0,
+	}, {
+		.name		= "i2s_v40",
+		.id		= 0,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_IIS2,
+	}, {
+		.name		= "spi",
+		.id		= 0,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_SPI0,
+	}, {
+		.name		= "spi",
+		.id		= 1,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_SPI1,
+	}, {
+		.name		= "sclk_spi_48",
+		.id		= 0,
+		.parent		= &clk_48m,
+		.enable		= s5p6440_sclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_SCLK0_SPI0_48,
+	}, {
+		.name		= "sclk_spi_48",
+		.id		= 1,
+		.parent		= &clk_48m,
+		.enable		= s5p6440_sclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_SCLK0_SPI1_48,
+	}, {
+		.name		= "mmc_48m",
+		.id		= 0,
+		.parent		= &clk_48m,
+		.enable		= s5p6440_sclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_SCLK0_MMC0_48,
+	}, {
+		.name		= "mmc_48m",
+		.id		= 1,
+		.parent		= &clk_48m,
+		.enable		= s5p6440_sclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_SCLK0_MMC1_48,
+	}, {
+		.name		= "mmc_48m",
+		.id		= 2,
+		.parent		= &clk_48m,
+		.enable		= s5p6440_sclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_SCLK0_MMC2_48,
+	}, {
+		.name    	= "otg",
+		.id	   	= -1,
+		.parent  	= &clk_h_low,
+		.enable  	= s5p6440_hclk0_ctrl,
+		.ctrlbit 	= S5P_CLKCON_HCLK0_USB
+	}, {
+		.name    	= "post",
+		.id	   	= -1,
+		.parent  	= &clk_h_low,
+		.enable  	= s5p6440_hclk0_ctrl,
+		.ctrlbit 	= S5P_CLKCON_HCLK0_POST0
+	}, {
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h_low,
+		.enable		= s5p6440_hclk1_ctrl,
+		.ctrlbit	= S5P_CLKCON_HCLK1_DISPCON,
+	}, {
+		.name		= "hsmmc",
+		.id		= 0,
+		.parent		= &clk_h_low,
+		.enable		= s5p6440_hclk0_ctrl,
+		.ctrlbit	= S5P_CLKCON_HCLK0_HSMMC0,
+	}, {
+		.name		= "hsmmc",
+		.id		= 1,
+		.parent		= &clk_h_low,
+		.enable		= s5p6440_hclk0_ctrl,
+		.ctrlbit	= S5P_CLKCON_HCLK0_HSMMC1,
+	}, {
+		.name		= "hsmmc",
+		.id		= 2,
+		.parent		= &clk_h_low,
+		.enable		= s5p6440_hclk0_ctrl,
+		.ctrlbit	= S5P_CLKCON_HCLK0_HSMMC2,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_WDT,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_PWM,
+	}
+};
+
+/*
+ * The following clocks will be enabled during clock initialization.
+ */
+static struct clk init_clocks[] = {
+	{
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_GPIO,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_UART2,
+	}, {
+		.name		= "uart",
+		.id		= 3,
+		.parent		= &clk_p_low,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= S5P_CLKCON_PCLK_UART3,
+	}
+};
+
+static struct clk clk_iis_cd_v40 = {
+	.name		= "iis_cdclk_v40",
+	.id		= -1,
+};
+
+static struct clk clk_pcm_cd = {
+	.name		= "pcm_cdclk",
+	.id		= -1,
+};
+
+static struct clk *clkset_spi_mmc_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll,
+	&clk_fin_epll,
+};
+
+static struct clksrc_sources clkset_spi_mmc = {
+	.sources	= clkset_spi_mmc_list,
+	.nr_sources	= ARRAY_SIZE(clkset_spi_mmc_list),
+};
+
+static struct clk *clkset_uart_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll
+};
+
+static struct clksrc_sources clkset_uart = {
+	.sources	= clkset_uart_list,
+	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
+};
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 0,
+			.ctrlbit        = S5P_CLKCON_SCLK0_MMC0,
+			.enable		= s5p6440_sclk_ctrl,
+		},
+		.sources = &clkset_spi_mmc,
+		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 1,
+			.ctrlbit        = S5P_CLKCON_SCLK0_MMC1,
+			.enable		= s5p6440_sclk_ctrl,
+		},
+		.sources = &clkset_spi_mmc,
+		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 2,
+			.ctrlbit        = S5P_CLKCON_SCLK0_MMC2,
+			.enable		= s5p6440_sclk_ctrl,
+		},
+		.sources = &clkset_spi_mmc,
+		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "uclk1",
+			.id		= -1,
+			.ctrlbit        = S5P_CLKCON_SCLK0_UART,
+			.enable		= s5p6440_sclk_ctrl,
+		},
+		.sources = &clkset_uart,
+		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 13, .size = 1 },
+		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "spi_epll",
+			.id		= 0,
+			.ctrlbit        = S5P_CLKCON_SCLK0_SPI0,
+			.enable		= s5p6440_sclk_ctrl,
+		},
+		.sources = &clkset_spi_mmc,
+		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "spi_epll",
+			.id		= 1,
+			.ctrlbit        = S5P_CLKCON_SCLK0_SPI1,
+			.enable		= s5p6440_sclk_ctrl,
+		},
+		.sources = &clkset_spi_mmc,
+		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
+	}
+};
+
+/* Clock initialisation code */
+static struct clksrc_clk *init_parents[] = {
+	&clk_mout_apll,
+	&clk_mout_epll,
+	&clk_mout_mpll,
+};
+
+void __init_or_cpufreq s5p6440_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+	unsigned long xtal;
+	unsigned long fclk;
+	unsigned long hclk;
+	unsigned long hclk_low;
+	unsigned long pclk;
+	unsigned long pclk_low;
+	unsigned long epll;
+	unsigned long apll;
+	unsigned long mpll;
+	unsigned int ptr;
+	u32 clkdiv0;
+	u32 clkdiv3;
+
+	/* Set S5P6440 functions for clk_fout_epll */
+	clk_fout_epll.enable = s5p6440_epll_enable;
+	clk_fout_epll.ops = &s5p6440_epll_ops;
+
+	/* Set S5P6440 functions for arm clock */
+	clk_arm.parent = &clk_mout_apll.clk;
+	clk_arm.ops = &s5p6440_clkarm_ops;
+	clk_48m.enable = s5p6440_clk48m_ctrl;
+
+	clkdiv0 = __raw_readl(S5P_CLK_DIV0);
+	clkdiv3 = __raw_readl(S5P_CLK_DIV3);
+
+	xtal_clk = clk_get(NULL, "ext_xtal");
+	BUG_ON(IS_ERR(xtal_clk));
+
+	xtal = clk_get_rate(xtal_clk);
+	clk_put(xtal_clk);
+
+	epll = s5p_get_pll90xx(xtal, __raw_readl(S5P_EPLL_CON),
+				__raw_readl(S5P_EPLL_CON_K));
+	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
+	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502);
+
+	printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
+			" E=%ld.%ldMHz\n",
+			print_mhz(apll), print_mhz(mpll), print_mhz(epll));
+
+	fclk = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_ARM);
+	hclk = fclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK);
+	pclk = hclk / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK);
+
+	if (__raw_readl(S5P_OTHERS) & S5P_OTHERS_HCLK_LOW_SEL_MPLL) {
+		/* Asynchronous mode */
+		hclk_low = mpll / GET_DIV(clkdiv3, S5P_CLKDIV3_HCLK_LOW);
+	} else {
+		/* Synchronous mode */
+		hclk_low = apll / GET_DIV(clkdiv3, S5P_CLKDIV3_HCLK_LOW);
+	}
+
+	pclk_low = hclk_low / GET_DIV(clkdiv3, S5P_CLKDIV3_PCLK_LOW);
+
+	printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
+			" PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
+			print_mhz(hclk), print_mhz(hclk_low),
+			print_mhz(pclk), print_mhz(pclk_low));
+
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+	clk_fout_apll.rate = apll;
+
+	clk_f.rate = fclk;
+	clk_h.rate = hclk;
+	clk_p.rate = pclk;
+	clk_h_low.rate = hclk_low;
+	clk_p_low.rate = pclk_low;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
+		s3c_set_clksrc(init_parents[ptr], true);
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+		s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+	&clk_ext,
+	&clk_mout_epll.clk,
+	&clk_mout_mpll.clk,
+	&clk_dout_mpll,
+	&clk_iis_cd_v40,
+	&clk_pcm_cd,
+	&clk_p_low,
+	&clk_h_low,
+};
+
+void __init s5p6440_register_clocks(void)
+{
+	struct clk *clkp;
+	int ret;
+	int ptr;
+
+	ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+	if (ret > 0)
+		printk(KERN_ERR "Failed to register %u clocks\n", ret);
+
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+		(clkp->enable)(clkp, 0);
+	}
+
+	s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-s5p6440/cpu.c b/arch/arm/mach-s5p6440/cpu.c
new file mode 100644
index 0000000..1794131a
--- /dev/null
+++ b/arch/arm/mach-s5p6440/cpu.c
@@ -0,0 +1,114 @@
+/* linux/arch/arm/mach-s5p6440/cpu.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/proc-fns.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <asm/irq.h>
+
+#include <plat/regs-serial.h>
+#include <mach/regs-clock.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/s5p6440.h>
+
+static void s5p6440_idle(void)
+{
+	unsigned long val;
+
+	if (!need_resched()) {
+		val = __raw_readl(S5P_PWR_CFG);
+		val &= ~(0x3<<5);
+		val |= (0x1<<5);
+		__raw_writel(val, S5P_PWR_CFG);
+
+		cpu_do_idle();
+	}
+	local_irq_enable();
+}
+
+/* s5p6440_map_io
+ *
+ * register the standard cpu IO areas
+*/
+
+void __init s5p6440_map_io(void)
+{
+	/* initialize any device information early */
+}
+
+void __init s5p6440_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+	s3c24xx_register_baseclocks(xtal);
+	s5p_register_clocks(xtal);
+	s5p6440_register_clocks();
+	s5p6440_setup_clocks();
+}
+
+void __init s5p6440_init_irq(void)
+{
+	/* S5P6440 supports only 2 VIC */
+	u32 vic[2];
+
+	/*
+	 * VIC0 is missing IRQ_VIC0[3, 4, 8, 10, (12-22)]
+	 * VIC1 is missing IRQ VIC1[1, 3, 4, 10, 11, 12, 14, 15, 22]
+	 */
+	vic[0] = 0xff800ae7;
+	vic[1] = 0xffbf23e5;
+
+	s5p_init_irq(vic, ARRAY_SIZE(vic));
+}
+
+static struct sysdev_class s5p6440_sysclass = {
+	.name	= "s5p6440-core",
+};
+
+static struct sys_device s5p6440_sysdev = {
+	.cls	= &s5p6440_sysclass,
+};
+
+static int __init s5p6440_core_init(void)
+{
+	return sysdev_class_register(&s5p6440_sysclass);
+}
+
+core_initcall(s5p6440_core_init);
+
+int __init s5p6440_init(void)
+{
+	printk(KERN_INFO "S5P6440: Initializing architecture\n");
+
+	/* set idle function */
+	pm_idle = s5p6440_idle;
+
+	return sysdev_register(&s5p6440_sysdev);
+}
diff --git a/arch/arm/mach-s5p6440/gpio.c b/arch/arm/mach-s5p6440/gpio.c
new file mode 100644
index 0000000..b0ea741
--- /dev/null
+++ b/arch/arm/mach-s5p6440/gpio.c
@@ -0,0 +1,322 @@
+/* arch/arm/mach-s5p6440/gpio.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ * 		http://www.samsung.com/
+ *
+ * S5P6440 - GPIOlib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <mach/map.h>
+#include <mach/gpio.h>
+#include <mach/regs-gpio.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+/* GPIO bank summary:
+*
+* Bank	GPIOs	Style	SlpCon	ExtInt Group
+* A	6	4Bit	Yes	1
+* B	7	4Bit	Yes	1
+* C	8	4Bit	Yes	2
+* F	2	2Bit	Yes	4 [1]
+* G	7	4Bit	Yes	5
+* H	10	4Bit[2]	Yes	6
+* I	16	2Bit	Yes	None
+* J	12	2Bit	Yes	None
+* N	16	2Bit	No	IRQ_EINT
+* P	8	2Bit	Yes	8
+* R	15	4Bit[2]	Yes	8
+*
+* [1] BANKF pins 14,15 do not form part of the external interrupt sources
+* [2] BANK has two control registers, GPxCON0 and GPxCON1
+*/
+
+static int s5p6440_gpiolib_rbank_4bit2_input(struct gpio_chip *chip,
+					     unsigned int offset)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+
+	switch (offset) {
+	case 6:
+		offset += 1;
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		regcon -= 4;
+		break;
+	default:
+		offset -= 7;
+		break;
+	}
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, regcon);
+
+	return 0;
+}
+
+static int s5p6440_gpiolib_rbank_4bit2_output(struct gpio_chip *chip,
+					      unsigned int offset, int value)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+	unsigned long dat;
+	unsigned con_offset  = offset;
+
+	switch (con_offset) {
+	case 6:
+		con_offset += 1;
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		regcon -= 4;
+		break;
+	default:
+		con_offset -= 7;
+		break;
+	}
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(con_offset));
+	con |= 0x1 << con_4bit_shift(con_offset);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+	if (value)
+		dat |= 1 << offset;
+	else
+		dat &= ~(1 << offset);
+
+	__raw_writel(con, regcon);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	return 0;
+}
+
+int s5p6440_gpio_setcfg_4bit_rbank(struct s3c_gpio_chip *chip,
+				   unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift;
+	u32 con;
+
+	switch (off) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		shift = (off & 7) * 4;
+		reg -= 4;
+		break;
+	case 6:
+		shift = ((off + 1) & 7) * 4;
+		reg -= 4;
+	default:
+		shift = ((off + 1) & 7) * 4;
+		break;
+	}
+
+	if (s3c_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0xf << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+
+static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = {
+	{
+		.cfg_eint	= 0,
+	}, {
+		.cfg_eint	= 7,
+	}, {
+		.cfg_eint	= 3,
+		.set_config	= s5p6440_gpio_setcfg_4bit_rbank,
+	}, {
+		.cfg_eint	= 0,
+		.set_config	= s3c_gpio_setcfg_s3c24xx,
+	}, {
+		.cfg_eint	= 2,
+		.set_config	= s3c_gpio_setcfg_s3c24xx,
+	}, {
+		.cfg_eint	= 3,
+		.set_config	= s3c_gpio_setcfg_s3c24xx,
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_4bit[] = {
+	{
+		.base	= S5P6440_GPA_BASE,
+		.config	= &s5p6440_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPA(0),
+			.ngpio	= S5P6440_GPIO_A_NR,
+			.label	= "GPA",
+		},
+	}, {
+		.base	= S5P6440_GPB_BASE,
+		.config	= &s5p6440_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPB(0),
+			.ngpio	= S5P6440_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.base	= S5P6440_GPC_BASE,
+		.config	= &s5p6440_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPC(0),
+			.ngpio	= S5P6440_GPIO_C_NR,
+			.label	= "GPC",
+		},
+	}, {
+		.base	= S5P6440_GPG_BASE,
+		.config	= &s5p6440_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPG(0),
+			.ngpio	= S5P6440_GPIO_G_NR,
+			.label	= "GPG",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_4bit2[] = {
+	{
+		.base	= S5P6440_GPH_BASE + 0x4,
+		.config	= &s5p6440_gpio_cfgs[1],
+		.chip	= {
+			.base	= S5P6440_GPH(0),
+			.ngpio	= S5P6440_GPIO_H_NR,
+			.label	= "GPH",
+		},
+	},
+};
+
+static struct s3c_gpio_chip gpio_rbank_4bit2[] = {
+	{
+		.base	= S5P6440_GPR_BASE + 0x4,
+		.config	= &s5p6440_gpio_cfgs[2],
+		.chip	= {
+			.base	= S5P6440_GPR(0),
+			.ngpio	= S5P6440_GPIO_R_NR,
+			.label	= "GPR",
+		},
+	},
+};
+
+static struct s3c_gpio_chip s5p6440_gpio_2bit[] = {
+	{
+		.base	= S5P6440_GPF_BASE,
+		.config	= &s5p6440_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6440_GPF(0),
+			.ngpio	= S5P6440_GPIO_F_NR,
+			.label	= "GPF",
+		},
+	}, {
+		.base	= S5P6440_GPI_BASE,
+		.config	= &s5p6440_gpio_cfgs[3],
+		.chip	= {
+			.base	= S5P6440_GPI(0),
+			.ngpio	= S5P6440_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.base	= S5P6440_GPJ_BASE,
+		.config	= &s5p6440_gpio_cfgs[3],
+		.chip	= {
+			.base	= S5P6440_GPJ(0),
+			.ngpio	= S5P6440_GPIO_J_NR,
+			.label	= "GPJ",
+		},
+	}, {
+		.base	= S5P6440_GPN_BASE,
+		.config	= &s5p6440_gpio_cfgs[4],
+		.chip	= {
+			.base	= S5P6440_GPN(0),
+			.ngpio	= S5P6440_GPIO_N_NR,
+			.label	= "GPN",
+		},
+	}, {
+		.base	= S5P6440_GPP_BASE,
+		.config	= &s5p6440_gpio_cfgs[5],
+		.chip	= {
+			.base	= S5P6440_GPP(0),
+			.ngpio	= S5P6440_GPIO_P_NR,
+			.label	= "GPP",
+		},
+	},
+};
+
+void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chipcfg++) {
+		if (!chipcfg->set_config)
+			chipcfg->set_config	= s3c_gpio_setcfg_s3c64xx_4bit;
+		if (!chipcfg->set_pull)
+			chipcfg->set_pull	= s3c_gpio_setpull_updown;
+		if (!chipcfg->get_pull)
+			chipcfg->get_pull	= s3c_gpio_getpull_updown;
+	}
+}
+
+static void __init s5p6440_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
+						int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chip++) {
+		chip->chip.direction_input = s5p6440_gpiolib_rbank_4bit2_input;
+		chip->chip.direction_output =
+					s5p6440_gpiolib_rbank_4bit2_output;
+		s3c_gpiolib_add(chip);
+	}
+}
+
+static int __init s5p6440_gpiolib_init(void)
+{
+	struct s3c_gpio_chip *chips = s5p6440_gpio_2bit;
+	int nr_chips = ARRAY_SIZE(s5p6440_gpio_2bit);
+
+	s5p6440_gpiolib_set_cfg(s5p6440_gpio_cfgs,
+				ARRAY_SIZE(s5p6440_gpio_cfgs));
+
+	for (; nr_chips > 0; nr_chips--, chips++)
+		s3c_gpiolib_add(chips);
+
+	samsung_gpiolib_add_4bit_chips(s5p6440_gpio_4bit,
+				ARRAY_SIZE(s5p6440_gpio_4bit));
+
+	samsung_gpiolib_add_4bit2_chips(s5p6440_gpio_4bit2,
+				ARRAY_SIZE(s5p6440_gpio_4bit2));
+
+	s5p6440_gpio_add_rbank_4bit2(gpio_rbank_4bit2,
+				ARRAY_SIZE(gpio_rbank_4bit2));
+
+	return 0;
+}
+arch_initcall(s5p6440_gpiolib_init);
diff --git a/arch/arm/mach-s5p6440/include/mach/debug-macro.S b/arch/arm/mach-s5p6440/include/mach/debug-macro.S
new file mode 100644
index 0000000..48cdb0d
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/debug-macro.S
@@ -0,0 +1,37 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <mach/map.h>
+#include <plat/regs-serial.h>
+
+	/* note, for the boot process to work we have to keep the UART
+	 * virtual address aligned to an 1MiB boundary for the L1
+	 * mapping the head code makes. We keep the UART virtual address
+	 * aligned and add in the offset when we load the value here.
+	 */
+
+	.macro addruart, rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1
+		ldreq	\rx, = S3C_PA_UART
+		ldrne	\rx, = S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+		add	\rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+#endif
+	.endm
+
+/* include the reset of the code which will do the work, we're only
+ * compiling for a single cpu processor type so the default of s3c2440
+ * will be fine with us.
+ */
+
+#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s5p6440/include/mach/entry-macro.S b/arch/arm/mach-s5p6440/include/mach/entry-macro.S
new file mode 100644
index 0000000..e65f1b9
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/entry-macro.S
@@ -0,0 +1,16 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/entry-macro.S
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Low-level IRQ helper macros for the Samsung S5P6440
+ *
+ * This program is free software; you can redistribute 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/map.h>
+#include <plat/irqs.h>
+
+#include <asm/entry-macro-vic2.S>
diff --git a/arch/arm/mach-s5p6440/include/mach/gpio.h b/arch/arm/mach-s5p6440/include/mach/gpio.h
new file mode 100644
index 0000000..2178383
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/gpio.h
@@ -0,0 +1,80 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/gpio.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - GPIO lib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H __FILE__
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define gpio_to_irq	__gpio_to_irq
+
+/* GPIO bank sizes */
+#define S5P6440_GPIO_A_NR	(6)
+#define S5P6440_GPIO_B_NR	(7)
+#define S5P6440_GPIO_C_NR	(8)
+#define S5P6440_GPIO_F_NR	(2)
+#define S5P6440_GPIO_G_NR	(7)
+#define S5P6440_GPIO_H_NR	(10)
+#define S5P6440_GPIO_I_NR	(16)
+#define S5P6440_GPIO_J_NR	(12)
+#define S5P6440_GPIO_N_NR	(16)
+#define S5P6440_GPIO_P_NR	(8)
+#define S5P6440_GPIO_R_NR	(15)
+
+/* GPIO bank numbers */
+
+/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
+ * space for debugging purposes so that any accidental
+ * change from one gpio bank to another can be caught.
+*/
+#define S5P6440_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s5p_gpio_number {
+	S5P6440_GPIO_A_START = 0,
+	S5P6440_GPIO_B_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_A),
+	S5P6440_GPIO_C_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_B),
+	S5P6440_GPIO_F_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_C),
+	S5P6440_GPIO_G_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_F),
+	S5P6440_GPIO_H_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_G),
+	S5P6440_GPIO_I_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_H),
+	S5P6440_GPIO_J_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_I),
+	S5P6440_GPIO_N_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_J),
+	S5P6440_GPIO_P_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_N),
+	S5P6440_GPIO_R_START = S5P6440_GPIO_NEXT(S5P6440_GPIO_P),
+};
+
+/* S5P6440 GPIO number definitions. */
+#define S5P6440_GPA(_nr)	(S5P6440_GPIO_A_START + (_nr))
+#define S5P6440_GPB(_nr)	(S5P6440_GPIO_B_START + (_nr))
+#define S5P6440_GPC(_nr)	(S5P6440_GPIO_C_START + (_nr))
+#define S5P6440_GPF(_nr)	(S5P6440_GPIO_F_START + (_nr))
+#define S5P6440_GPG(_nr)	(S5P6440_GPIO_G_START + (_nr))
+#define S5P6440_GPH(_nr)	(S5P6440_GPIO_H_START + (_nr))
+#define S5P6440_GPI(_nr)	(S5P6440_GPIO_I_START + (_nr))
+#define S5P6440_GPJ(_nr)	(S5P6440_GPIO_J_START + (_nr))
+#define S5P6440_GPN(_nr)	(S5P6440_GPIO_N_START + (_nr))
+#define S5P6440_GPP(_nr)	(S5P6440_GPIO_P_START + (_nr))
+#define S5P6440_GPR(_nr)	(S5P6440_GPIO_R_START + (_nr))
+
+/* the end of the S5P6440 specific gpios */
+#define S5P6440_GPIO_END	(S5P6440_GPR(S5P6440_GPIO_R_NR) + 1)
+#define S3C_GPIO_END		S5P6440_GPIO_END
+
+/* define the number of gpios we need to the one after the GPR() range */
+#define ARCH_NR_GPIOS		(S5P6440_GPR(S5P6440_GPIO_R_NR) +	\
+				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/hardware.h b/arch/arm/mach-s5p6440/include/mach/hardware.h
new file mode 100644
index 0000000..be8b26e
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/hardware.h
@@ -0,0 +1,18 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/hardware.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - Hardware support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H __FILE__
+
+/* currently nothing here, placeholder */
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/io.h b/arch/arm/mach-s5p6440/include/mach/io.h
new file mode 100644
index 0000000..fa2d69c
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/io.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s5p6440/include/mach/io.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben-linux@fluff.org>
+ *
+ * Default IO routines for S3C64XX based
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif
diff --git a/arch/arm/mach-s5p6440/include/mach/irqs.h b/arch/arm/mach-s5p6440/include/mach/irqs.h
new file mode 100644
index 0000000..a4b9b40
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/irqs.h
@@ -0,0 +1,111 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/irqs.h
+ *
+ * Copyright 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - IRQ definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_S5P_IRQS_H
+#define __ASM_ARCH_S5P_IRQS_H __FILE__
+
+#include <plat/irqs.h>
+
+/* VIC0 */
+
+#define IRQ_EINT0_3		S5P_IRQ_VIC0(0)
+#define IRQ_EINT4_11		S5P_IRQ_VIC0(1)
+#define IRQ_RTC_TIC		S5P_IRQ_VIC0(2)
+#define IRQ_IIC1		S5P_IRQ_VIC0(5)
+#define IRQ_I2SV40		S5P_IRQ_VIC0(6)
+#define IRQ_GPS			S5P_IRQ_VIC0(7)
+#define IRQ_POST0		S5P_IRQ_VIC0(9)
+#define IRQ_2D			S5P_IRQ_VIC0(11)
+#define IRQ_TIMER0_VIC		S5P_IRQ_VIC0(23)
+#define IRQ_TIMER1_VIC		S5P_IRQ_VIC0(24)
+#define IRQ_TIMER2_VIC		S5P_IRQ_VIC0(25)
+#define IRQ_WDT			S5P_IRQ_VIC0(26)
+#define IRQ_TIMER3_VIC		S5P_IRQ_VIC0(27)
+#define IRQ_TIMER4_VIC		S5P_IRQ_VIC0(28)
+#define IRQ_DISPCON0		S5P_IRQ_VIC0(29)
+#define IRQ_DISPCON1		S5P_IRQ_VIC0(30)
+#define IRQ_DISPCON2		S5P_IRQ_VIC0(31)
+
+/* VIC1 */
+
+#define IRQ_EINT12_15		S5P_IRQ_VIC1(0)
+#define IRQ_PCM0		S5P_IRQ_VIC1(2)
+#define IRQ_UART0		S5P_IRQ_VIC1(5)
+#define IRQ_UART1		S5P_IRQ_VIC1(6)
+#define IRQ_UART2		S5P_IRQ_VIC1(7)
+#define IRQ_UART3		S5P_IRQ_VIC1(8)
+#define IRQ_DMA0		S5P_IRQ_VIC1(9)
+#define IRQ_NFC			S5P_IRQ_VIC1(13)
+#define IRQ_SPI0		S5P_IRQ_VIC1(16)
+#define IRQ_SPI1		S5P_IRQ_VIC1(17)
+#define IRQ_IIC			S5P_IRQ_VIC1(18)
+#define IRQ_DISPCON3		S5P_IRQ_VIC1(19)
+#define IRQ_FIMGVG		S5P_IRQ_VIC1(20)
+#define IRQ_EINT_GROUPS		S5P_IRQ_VIC1(21)
+#define IRQ_PMUIRQ		S5P_IRQ_VIC1(23)
+#define IRQ_HSMMC0		S5P_IRQ_VIC1(24)
+#define IRQ_HSMMC1		S5P_IRQ_VIC1(25)
+#define IRQ_HSMMC2		IRQ_SPI1	/* shared with SPI1 */
+#define IRQ_OTG			S5P_IRQ_VIC1(26)
+#define IRQ_DSI			S5P_IRQ_VIC1(27)
+#define IRQ_RTC_ALARM		S5P_IRQ_VIC1(28)
+#define IRQ_TSI			S5P_IRQ_VIC1(29)
+#define IRQ_PENDN		S5P_IRQ_VIC1(30)
+#define IRQ_TC			IRQ_PENDN
+#define IRQ_ADC			S5P_IRQ_VIC1(31)
+
+/*
+ * Since the IRQ_EINT(x) are a linear mapping on s5p6440 we just defined
+ * them as an IRQ_EINT(x) macro from S5P_IRQ_EINT_BASE which we place
+ * after the pair of VICs.
+ */
+
+#define S5P_IRQ_EINT_BASE	(S5P_IRQ_VIC1(31) + 6)
+
+#define S5P_EINT(x)		((x) + S5P_IRQ_EINT_BASE)
+#define IRQ_EINT(x)		S5P_EINT(x)
+
+/*
+ * Next the external interrupt groups. These are similar to the IRQ_EINT(x)
+ * that they are sourced from the GPIO pins but with a different scheme for
+ * priority and source indication.
+ *
+ * The IRQ_EINT(x) can be thought of as 'group 0' of the available GPIO
+ * interrupts, but for historical reasons they are kept apart from these
+ * next interrupts.
+ *
+ * Use IRQ_EINT_GROUP(group, offset) to get the number for use in the
+ * machine specific support files.
+ */
+
+/* Actually, #6 and #7 are missing in the EINT_GROUP1 */
+#define IRQ_EINT_GROUP1_NR	(15)
+#define IRQ_EINT_GROUP2_NR	(8)
+#define IRQ_EINT_GROUP5_NR	(7)
+#define IRQ_EINT_GROUP6_NR	(10)
+/* Actually, #0, #1 and #2 are missing in the EINT_GROUP8 */
+#define IRQ_EINT_GROUP8_NR	(11)
+
+#define IRQ_EINT_GROUP_BASE	S5P_EINT(16)
+#define IRQ_EINT_GROUP1_BASE	(IRQ_EINT_GROUP_BASE + 0)
+#define IRQ_EINT_GROUP2_BASE	(IRQ_EINT_GROUP1_BASE + IRQ_EINT_GROUP1_NR)
+#define IRQ_EINT_GROUP5_BASE	(IRQ_EINT_GROUP2_BASE + IRQ_EINT_GROUP2_NR)
+#define IRQ_EINT_GROUP6_BASE	(IRQ_EINT_GROUP5_BASE + IRQ_EINT_GROUP5_NR)
+#define IRQ_EINT_GROUP8_BASE	(IRQ_EINT_GROUP6_BASE + IRQ_EINT_GROUP6_NR)
+
+#define IRQ_EINT_GROUP(grp, x)	(IRQ_EINT_GROUP##grp##_BASE + (x))
+
+/* Set the default NR_IRQS */
+
+#define NR_IRQS			(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
+
+#endif /* __ASM_ARCH_S5P_IRQS_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/map.h b/arch/arm/mach-s5p6440/include/mach/map.h
new file mode 100644
index 0000000..8924e5a
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/map.h
@@ -0,0 +1,68 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/map.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H __FILE__
+
+#include <plat/map-base.h>
+#include <plat/map-s5p.h>
+
+#define S5P6440_PA_CHIPID	(0xE0000000)
+#define S5P_PA_CHIPID		S5P6440_PA_CHIPID
+
+#define S5P6440_PA_SYSCON	(0xE0100000)
+#define S5P6440_PA_CLK		(S5P6440_PA_SYSCON + 0x0)
+#define S5P_PA_SYSCON		S5P6440_PA_SYSCON
+
+#define S5P6440_PA_GPIO		(0xE0308000)
+#define S5P_PA_GPIO		S5P6440_PA_GPIO
+
+#define S5P6440_PA_VIC0		(0xE4000000)
+#define S5P_PA_VIC0		S5P6440_PA_VIC0
+
+#define S5P6440_PA_VIC1		(0xE4100000)
+#define S5P_PA_VIC1		S5P6440_PA_VIC1
+
+#define S5P6440_PA_TIMER	(0xEA000000)
+#define S5P_PA_TIMER		S5P6440_PA_TIMER
+
+#define S5P6440_PA_RTC		(0xEA100000)
+#define S5P_PA_RTC		S5P6440_PA_RTC
+
+#define S5P6440_PA_WDT		(0xEA200000)
+#define S5P_PA_WDT		S5P6440_PA_WDT
+
+#define S5P6440_PA_UART		(0xEC000000)
+
+#define S5P_PA_UART0		(S5P6440_PA_UART + 0x0)
+#define S5P_PA_UART1		(S5P6440_PA_UART + 0x400)
+#define S5P_PA_UART2		(S5P6440_PA_UART + 0x800)
+#define S5P_PA_UART3		(S5P6440_PA_UART + 0xC00)
+
+#define S5P_SZ_UART		SZ_256
+
+#define S5P6440_PA_IIC0		(0xEC104000)
+
+#define S5P6440_PA_HSOTG	(0xED100000)
+
+#define S5P6440_PA_HSMMC0	(0xED800000)
+#define S5P6440_PA_HSMMC1	(0xED900000)
+#define S5P6440_PA_HSMMC2	(0xEDA00000)
+
+#define S5P6440_PA_SDRAM	(0x20000000)
+#define S5P_PA_SDRAM		S5P6440_PA_SDRAM
+
+/* compatibiltiy defines. */
+#define S3C_PA_UART		S5P6440_PA_UART
+#define S3C_PA_IIC		S5P6440_PA_IIC0
+
+#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/memory.h b/arch/arm/mach-s5p6440/include/mach/memory.h
new file mode 100644
index 0000000..d62910c
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/memory.h
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/memory.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - Memory definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PHYS_OFFSET     	UL(0x20000000)
+#define CONSISTENT_DMA_SIZE	SZ_8M
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h b/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
new file mode 100644
index 0000000..c4bb7c5
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
@@ -0,0 +1,62 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * Copyright 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - pwm clock and timer support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/**
+ * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
+ * @cfg: The timer TCFG1 register bits shifted down to 0.
+ *
+ * Return true if the given configuration from TCFG1 is a TCLK instead
+ * any of the TDIV clocks.
+ */
+static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
+{
+	return tcfg == S3C2410_TCFG1_MUX_TCLK;
+}
+
+/**
+ * tcfg_to_divisor() - convert tcfg1 setting to a divisor
+ * @tcfg1: The tcfg1 setting, shifted down.
+ *
+ * Get the divisor value for the given tcfg1 setting. We assume the
+ * caller has already checked to see if this is not a TCLK source.
+ */
+static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
+{
+	return 1 << (1 + tcfg1);
+}
+
+/**
+ * pwm_tdiv_has_div1() - does the tdiv setting have a /1
+ *
+ * Return true if we have a /1 in the tdiv setting.
+ */
+static inline unsigned int pwm_tdiv_has_div1(void)
+{
+	return 0;
+}
+
+/**
+ * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
+ * @div: The divisor to calculate the bit information for.
+ *
+ * Turn a divisor into the necessary bit field for TCFG1.
+ */
+static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
+{
+	return ilog2(div) - 1;
+}
+
+#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
diff --git a/arch/arm/mach-s5p6440/include/mach/regs-clock.h b/arch/arm/mach-s5p6440/include/mach/regs-clock.h
new file mode 100644
index 0000000..c783ecc
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/regs-clock.h
@@ -0,0 +1,130 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - Clock register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_CLKREG(x)		(S3C_VA_SYS + (x))
+
+#define S5P_APLL_LOCK		S5P_CLKREG(0x00)
+#define S5P_MPLL_LOCK		S5P_CLKREG(0x04)
+#define S5P_EPLL_LOCK		S5P_CLKREG(0x08)
+#define S5P_APLL_CON		S5P_CLKREG(0x0C)
+#define S5P_MPLL_CON		S5P_CLKREG(0x10)
+#define S5P_EPLL_CON		S5P_CLKREG(0x14)
+#define S5P_EPLL_CON_K		S5P_CLKREG(0x18)
+#define S5P_CLK_SRC0		S5P_CLKREG(0x1C)
+#define S5P_CLK_DIV0		S5P_CLKREG(0x20)
+#define S5P_CLK_DIV1		S5P_CLKREG(0x24)
+#define S5P_CLK_DIV2		S5P_CLKREG(0x28)
+#define S5P_CLK_OUT		S5P_CLKREG(0x2C)
+#define S5P_CLK_GATE_HCLK0	S5P_CLKREG(0x30)
+#define S5P_CLK_GATE_PCLK	S5P_CLKREG(0x34)
+#define S5P_CLK_GATE_SCLK0	S5P_CLKREG(0x38)
+#define S5P_CLK_GATE_MEM0	S5P_CLKREG(0x3C)
+#define S5P_CLK_DIV3		S5P_CLKREG(0x40)
+#define S5P_CLK_GATE_HCLK1	S5P_CLKREG(0x44)
+#define S5P_CLK_GATE_SCLK1	S5P_CLKREG(0x48)
+#define S5P_AHB_CON0           	S5P_CLKREG(0x100)
+#define S5P_CLK_SRC1           	S5P_CLKREG(0x10C)
+#define S5P_SWRESET		S5P_CLKREG(0x114)
+#define S5P_SYS_ID		S5P_CLKREG(0x118)
+#define S5P_SYS_OTHERS		S5P_CLKREG(0x11C)
+#define S5P_MEM_CFG_STAT	S5P_CLKREG(0x12C)
+#define S5P_PWR_CFG		S5P_CLKREG(0x804)
+#define S5P_EINT_WAKEUP_MASK	S5P_CLKREG(0x808)
+#define S5P_NORMAL_CFG		S5P_CLKREG(0x810)
+#define S5P_STOP_CFG		S5P_CLKREG(0x814)
+#define S5P_SLEEP_CFG		S5P_CLKREG(0x818)
+#define S5P_OSC_FREQ		S5P_CLKREG(0x820)
+#define S5P_OSC_STABLE		S5P_CLKREG(0x824)
+#define S5P_PWR_STABLE		S5P_CLKREG(0x828)
+#define S5P_MTC_STABLE		S5P_CLKREG(0x830)
+#define S5P_OTHERS		S5P_CLKREG(0x900)
+#define S5P_RST_STAT		S5P_CLKREG(0x904)
+#define S5P_WAKEUP_STAT		S5P_CLKREG(0x908)
+#define S5P_SLPEN		S5P_CLKREG(0x930)
+#define S5P_INFORM0		S5P_CLKREG(0xA00)
+#define S5P_INFORM1		S5P_CLKREG(0xA04)
+#define S5P_INFORM2		S5P_CLKREG(0xA08)
+#define S5P_INFORM3		S5P_CLKREG(0xA0C)
+
+/* CLKDIV0 */
+#define S5P_CLKDIV0_PCLK_MASK		(0xf << 12)
+#define S5P_CLKDIV0_PCLK_SHIFT		(12)
+#define S5P_CLKDIV0_HCLK_MASK		(0xf << 8)
+#define S5P_CLKDIV0_HCLK_SHIFT		(8)
+#define S5P_CLKDIV0_MPLL_MASK		(0x1 << 4)
+#define S5P_CLKDIV0_ARM_MASK		(0xf << 0)
+#define S5P_CLKDIV0_ARM_SHIFT		(0)
+
+/* CLKDIV3 */
+#define S5P_CLKDIV3_PCLK_LOW_MASK	(0xf << 12)
+#define S5P_CLKDIV3_PCLK_LOW_SHIFT	(12)
+#define S5P_CLKDIV3_HCLK_LOW_MASK	(0xf << 8)
+#define S5P_CLKDIV3_HCLK_LOW_SHIFT	(8)
+
+/* HCLK0 GATE Registers */
+#define S5P_CLKCON_HCLK0_USB		(1<<20)
+#define S5P_CLKCON_HCLK0_HSMMC2		(1<<19)
+#define S5P_CLKCON_HCLK0_HSMMC1		(1<<18)
+#define S5P_CLKCON_HCLK0_HSMMC0		(1<<17)
+#define S5P_CLKCON_HCLK0_POST0		(1<<5)
+
+/* HCLK1 GATE Registers */
+#define S5P_CLKCON_HCLK1_DISPCON	(1<<1)
+
+/* PCLK GATE Registers */
+#define S5P_CLKCON_PCLK_IIS2		(1<<26)
+#define S5P_CLKCON_PCLK_SPI1		(1<<22)
+#define S5P_CLKCON_PCLK_SPI0		(1<<21)
+#define S5P_CLKCON_PCLK_GPIO		(1<<18)
+#define S5P_CLKCON_PCLK_IIC0		(1<<17)
+#define S5P_CLKCON_PCLK_TSADC		(1<<12)
+#define S5P_CLKCON_PCLK_PWM		(1<<7)
+#define S5P_CLKCON_PCLK_RTC		(1<<6)
+#define S5P_CLKCON_PCLK_WDT		(1<<5)
+#define S5P_CLKCON_PCLK_UART3		(1<<4)
+#define S5P_CLKCON_PCLK_UART2		(1<<3)
+#define S5P_CLKCON_PCLK_UART1		(1<<2)
+#define S5P_CLKCON_PCLK_UART0		(1<<1)
+
+/* SCLK0 GATE Registers */
+#define S5P_CLKCON_SCLK0_MMC2_48	(1<<29)
+#define S5P_CLKCON_SCLK0_MMC1_48	(1<<28)
+#define S5P_CLKCON_SCLK0_MMC0_48	(1<<27)
+#define S5P_CLKCON_SCLK0_MMC2		(1<<26)
+#define S5P_CLKCON_SCLK0_MMC1		(1<<25)
+#define S5P_CLKCON_SCLK0_MMC0		(1<<24)
+#define S5P_CLKCON_SCLK0_SPI1_48 	(1<<23)
+#define S5P_CLKCON_SCLK0_SPI0_48 	(1<<22)
+#define S5P_CLKCON_SCLK0_SPI1		(1<<21)
+#define S5P_CLKCON_SCLK0_SPI0		(1<<20)
+#define S5P_CLKCON_SCLK0_UART		(1<<5)
+
+/* SCLK1 GATE Registers */
+
+/* MEM0 GATE Registers */
+#define S5P_CLKCON_MEM0_HCLK_NFCON	(1<<2)
+
+/*OTHERS Resgister */
+#define S5P_OTHERS_USB_SIG_MASK		(1<<16)
+#define S5P_OTHERS_HCLK_LOW_SEL_MPLL	(1<<6)
+
+/* Compatibility defines */
+#define ARM_CLK_DIV			S5P_CLK_DIV0
+#define ARM_DIV_RATIO_SHIFT		0
+#define ARM_DIV_MASK			(0xf << ARM_DIV_RATIO_SHIFT)
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/regs-gpio.h b/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
new file mode 100644
index 0000000..82ff753
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
@@ -0,0 +1,54 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/regs-gpio.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - GPIO register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_REGS_GPIO_H
+#define __ASM_ARCH_REGS_GPIO_H __FILE__
+
+#include <mach/map.h>
+
+/* Base addresses for each of the banks */
+#define S5P6440_GPA_BASE		(S5P_VA_GPIO + 0x0000)
+#define S5P6440_GPB_BASE		(S5P_VA_GPIO + 0x0020)
+#define S5P6440_GPC_BASE		(S5P_VA_GPIO + 0x0040)
+#define S5P6440_GPF_BASE		(S5P_VA_GPIO + 0x00A0)
+#define S5P6440_GPG_BASE		(S5P_VA_GPIO + 0x00C0)
+#define S5P6440_GPH_BASE		(S5P_VA_GPIO + 0x00E0)
+#define S5P6440_GPI_BASE		(S5P_VA_GPIO + 0x0100)
+#define S5P6440_GPJ_BASE		(S5P_VA_GPIO + 0x0120)
+#define S5P6440_GPN_BASE		(S5P_VA_GPIO + 0x0830)
+#define S5P6440_GPP_BASE		(S5P_VA_GPIO + 0x0160)
+#define S5P6440_GPR_BASE		(S5P_VA_GPIO + 0x0290)
+#define S5P6440_EINT0CON0		(S5P_VA_GPIO + 0x900)
+#define S5P6440_EINT0FLTCON0		(S5P_VA_GPIO + 0x910)
+#define S5P6440_EINT0FLTCON1		(S5P_VA_GPIO + 0x914)
+#define S5P6440_EINT0MASK		(S5P_VA_GPIO + 0x920)
+#define S5P6440_EINT0PEND		(S5P_VA_GPIO + 0x924)
+
+/* for LCD */
+#define S5P6440_SPCON_LCD_SEL_RGB	(1 << 0)
+#define S5P6440_SPCON_LCD_SEL_MASK	(3 << 0)
+
+/* These set of macros are not really useful for the
+ * GPF/GPI/GPJ/GPN/GPP,
+ * useful for others set of GPIO's (4 bit)
+ */
+#define S5P6440_GPIO_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
+#define S5P6440_GPIO_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
+#define S5P6440_GPIO_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
+
+/* Use these macros for GPF/GPI/GPJ/GPN/GPP set of GPIO (2 bit)
+ * */
+#define S5P6440_GPIO2_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
+#define S5P6440_GPIO2_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
+#define S5P6440_GPIO2_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
+
+#endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/regs-irq.h b/arch/arm/mach-s5p6440/include/mach/regs-irq.h
new file mode 100644
index 0000000..a961f4b
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/regs-irq.h
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/regs-irq.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - IRQ register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_IRQ_H
+#define __ASM_ARCH_REGS_IRQ_H __FILE__
+
+#include <asm/hardware/vic.h>
+#include <mach/map.h>
+
+#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/system.h b/arch/arm/mach-s5p6440/include/mach/system.h
new file mode 100644
index 0000000..d2dd817
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/system.h
@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/system.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - system support header
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H __FILE__
+
+static void arch_idle(void)
+{
+	/* nothing here yet */
+}
+
+static void arch_reset(char mode, const char *cmd)
+{
+	/* nothing here yet */
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/tick.h b/arch/arm/mach-s5p6440/include/mach/tick.h
new file mode 100644
index 0000000..2f25c7f
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/tick.h
@@ -0,0 +1,24 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/tick.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - Timer tick support definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TICK_H
+#define __ASM_ARCH_TICK_H __FILE__
+
+static inline u32 s3c24xx_ostimer_pending(void)
+{
+	u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
+	return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));
+}
+
+#define TICK_MAX	(0xffffffff)
+
+#endif /* __ASM_ARCH_TICK_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/timex.h b/arch/arm/mach-s5p6440/include/mach/timex.h
new file mode 100644
index 0000000..fb2e8cd
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/timex.h
@@ -0,0 +1,24 @@
+/* arch/arm/mach-s3c64xx/include/mach/timex.h
+ *
+ * Copyright (c) 2003-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C6400 - time parameters
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
+
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/uncompress.h b/arch/arm/mach-s5p6440/include/mach/uncompress.h
new file mode 100644
index 0000000..7c1f600d
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/uncompress.h
@@ -0,0 +1,24 @@
+/* linux/arch/arm/mach-s5p6440/include/mach/uncompress.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - uncompress code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <mach/map.h>
+#include <plat/uncompress.h>
+
+static void arch_detect_cpu(void)
+{
+	/* we do not need to do any cpu detection here at the moment. */
+}
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-s5p6440/include/mach/vmalloc.h b/arch/arm/mach-s5p6440/include/mach/vmalloc.h
new file mode 100644
index 0000000..16df257
--- /dev/null
+++ b/arch/arm/mach-s5p6440/include/mach/vmalloc.h
@@ -0,0 +1,17 @@
+/* arch/arm/mach-s5p6440/include/mach/vmalloc.h
+ *
+ * Copyright 2010 Ben Dooks <ben-linux@fluff.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.
+ *
+ * S3C6400 vmalloc definition
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END	  (0xE0000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5p6440/init.c b/arch/arm/mach-s5p6440/init.c
new file mode 100644
index 0000000..a1f3727
--- /dev/null
+++ b/arch/arm/mach-s5p6440/init.c
@@ -0,0 +1,52 @@
+/* linux/arch/arm/mach-s5p6440/init.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6440 - Init support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/s5p6440.h>
+#include <plat/regs-serial.h>
+
+static struct s3c24xx_uart_clksrc s5p6440_serial_clocks[] = {
+	[0] = {
+		.name		= "pclk_low",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+	[1] = {
+		.name		= "uclk1",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+};
+
+/* uart registration process */
+void __init s5p6440_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	struct s3c2410_uartcfg *tcfg = cfg;
+	u32 ucnt;
+
+	for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
+		if (!tcfg->clocks) {
+			tcfg->clocks = s5p6440_serial_clocks;
+			tcfg->clocks_size = ARRAY_SIZE(s5p6440_serial_clocks);
+		}
+	}
+
+	s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
+}
diff --git a/arch/arm/mach-s5p6440/mach-smdk6440.c b/arch/arm/mach-s5p6440/mach-smdk6440.c
new file mode 100644
index 0000000..3ae88f2
--- /dev/null
+++ b/arch/arm/mach-s5p6440/mach-smdk6440.c
@@ -0,0 +1,111 @@
+/* linux/arch/arm/mach-s5p6440/mach-smdk6440.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+
+#include <plat/s5p6440.h>
+#include <plat/clock.h>
+#include <mach/regs-clock.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+
+#define S5P6440_UCON_DEFAULT    (S3C2410_UCON_TXILEVEL |	\
+				S3C2410_UCON_RXILEVEL |		\
+				S3C2410_UCON_TXIRQMODE |	\
+				S3C2410_UCON_RXIRQMODE |	\
+				S3C2410_UCON_RXFIFO_TOI |	\
+				S3C2443_UCON_RXERR_IRQEN)
+
+#define S5P6440_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define S5P6440_UFCON_DEFAULT   (S3C2410_UFCON_FIFOMODE |	\
+				S3C2440_UFCON_TXTRIG16 |	\
+				S3C2410_UFCON_RXTRIG8)
+
+static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = S5P6440_UCON_DEFAULT,
+		.ulcon	     = S5P6440_ULCON_DEFAULT,
+		.ufcon	     = S5P6440_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = S5P6440_UCON_DEFAULT,
+		.ulcon	     = S5P6440_ULCON_DEFAULT,
+		.ufcon	     = S5P6440_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = S5P6440_UCON_DEFAULT,
+		.ulcon	     = S5P6440_ULCON_DEFAULT,
+		.ufcon	     = S5P6440_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport	     = 3,
+		.flags	     = 0,
+		.ucon	     = S5P6440_UCON_DEFAULT,
+		.ulcon	     = S5P6440_ULCON_DEFAULT,
+		.ufcon	     = S5P6440_UFCON_DEFAULT,
+	},
+};
+
+static struct platform_device *smdk6440_devices[] __initdata = {
+};
+
+static void __init smdk6440_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_SYS_ID);
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs));
+}
+
+static void __init smdk6440_machine_init(void)
+{
+	platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices));
+}
+
+MACHINE_START(SMDK6440, "SMDK6440")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+
+	.init_irq	= s5p6440_init_irq,
+	.map_io		= smdk6440_map_io,
+	.init_machine	= smdk6440_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s5p6442/Kconfig b/arch/arm/mach-s5p6442/Kconfig
new file mode 100644
index 0000000..4f3f6de
--- /dev/null
+++ b/arch/arm/mach-s5p6442/Kconfig
@@ -0,0 +1,24 @@
+# arch/arm/mach-s5p6442/Kconfig
+#
+# Copyright (c) 2010 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+# Configuration options for the S5P6442
+
+if ARCH_S5P6442
+
+config CPU_S5P6442
+	bool
+	select PLAT_S5P
+	help
+	  Enable S5P6442 CPU support
+
+config MACH_SMDK6442
+	bool "SMDK6442"
+	select CPU_S5P6442
+	help
+	  Machine support for Samsung SMDK6442
+
+endif
diff --git a/arch/arm/mach-s5p6442/Makefile b/arch/arm/mach-s5p6442/Makefile
new file mode 100644
index 0000000..dde39a6
--- /dev/null
+++ b/arch/arm/mach-s5p6442/Makefile
@@ -0,0 +1,19 @@
+# arch/arm/mach-s5p6442/Makefile
+#
+# Copyright (c) 2010 Samsung Electronics Co., Ltd.
+# 		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+# Core support for S5P6442 system
+
+obj-$(CONFIG_CPU_S5P6442)	+= cpu.o init.o clock.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDK6442)	+= mach-smdk6442.o
diff --git a/arch/arm/mach-s5p6442/Makefile.boot b/arch/arm/mach-s5p6442/Makefile.boot
new file mode 100644
index 0000000..ff90aa1
--- /dev/null
+++ b/arch/arm/mach-s5p6442/Makefile.boot
@@ -0,0 +1,2 @@
+   zreladdr-y	:= 0x20008000
+params_phys-y	:= 0x20000100
diff --git a/arch/arm/mach-s5p6442/clock.c b/arch/arm/mach-s5p6442/clock.c
new file mode 100644
index 0000000..3aadbf4
--- /dev/null
+++ b/arch/arm/mach-s5p6442/clock.c
@@ -0,0 +1,396 @@
+/* linux/arch/arm/mach-s5p6442/clock.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6442 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/cpu-freq.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p6442.h>
+
+static struct clksrc_clk clk_mout_apll = {
+	.clk	= {
+		.name		= "mout_apll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_apll,
+	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
+};
+
+static struct clksrc_clk clk_mout_mpll = {
+	.clk = {
+		.name		= "mout_mpll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_mpll,
+	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk clk_mout_epll = {
+	.clk	= {
+		.name		= "mout_epll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_epll,
+	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
+};
+
+/* Possible clock sources for ARM Mux */
+static struct clk *clk_src_arm_list[] = {
+	[1] = &clk_mout_apll.clk,
+	[2] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clk_src_arm = {
+	.sources	= clk_src_arm_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_arm_list),
+};
+
+static struct clksrc_clk clk_mout_arm = {
+	.clk	= {
+		.name		= "mout_arm",
+		.id		= -1,
+	},
+	.sources	= &clk_src_arm,
+	.reg_src	= { .reg = S5P_CLK_MUX_STAT0, .shift = 16, .size = 3 },
+};
+
+static struct clk clk_dout_a2m = {
+	.name		= "dout_a2m",
+	.id		= -1,
+	.parent		= &clk_mout_apll.clk,
+};
+
+/* Possible clock sources for D0 Mux */
+static struct clk *clk_src_d0_list[] = {
+	[1] = &clk_mout_mpll.clk,
+	[2] = &clk_dout_a2m,
+};
+
+static struct clksrc_sources clk_src_d0 = {
+	.sources	= clk_src_d0_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_d0_list),
+};
+
+static struct clksrc_clk clk_mout_d0 = {
+	.clk = {
+		.name		= "mout_d0",
+		.id		= -1,
+	},
+	.sources	= &clk_src_d0,
+	.reg_src	= { .reg = S5P_CLK_MUX_STAT0, .shift = 20, .size = 3 },
+};
+
+static struct clk clk_dout_apll = {
+	.name		= "dout_apll",
+	.id		= -1,
+	.parent		= &clk_mout_arm.clk,
+};
+
+/* Possible clock sources for D0SYNC Mux */
+static struct clk *clk_src_d0sync_list[] = {
+	[1] = &clk_mout_d0.clk,
+	[2] = &clk_dout_apll,
+};
+
+static struct clksrc_sources clk_src_d0sync = {
+	.sources	= clk_src_d0sync_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_d0sync_list),
+};
+
+static struct clksrc_clk clk_mout_d0sync = {
+	.clk	= {
+		.name		= "mout_d0sync",
+		.id		= -1,
+	},
+	.sources	= &clk_src_d0sync,
+	.reg_src	= { .reg = S5P_CLK_MUX_STAT1, .shift = 28, .size = 3 },
+};
+
+/* Possible clock sources for D1 Mux */
+static struct clk *clk_src_d1_list[] = {
+	[1] = &clk_mout_mpll.clk,
+	[2] = &clk_dout_a2m,
+};
+
+static struct clksrc_sources clk_src_d1 = {
+	.sources	= clk_src_d1_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_d1_list),
+};
+
+static struct clksrc_clk clk_mout_d1 = {
+	.clk	= {
+		.name		= "mout_d1",
+		.id		= -1,
+	},
+	.sources	= &clk_src_d1,
+	.reg_src	= { .reg = S5P_CLK_MUX_STAT0, .shift = 24, .size = 3 },
+};
+
+/* Possible clock sources for D1SYNC Mux */
+static struct clk *clk_src_d1sync_list[] = {
+	[1] = &clk_mout_d1.clk,
+	[2] = &clk_dout_apll,
+};
+
+static struct clksrc_sources clk_src_d1sync = {
+	.sources	= clk_src_d1sync_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_d1sync_list),
+};
+
+static struct clksrc_clk clk_mout_d1sync = {
+	.clk	= {
+		.name		= "mout_d1sync",
+		.id		= -1,
+	},
+	.sources	= &clk_src_d1sync,
+	.reg_src	= { .reg = S5P_CLK_MUX_STAT1, .shift = 24, .size = 3 },
+};
+
+static struct clk clk_hclkd0 = {
+	.name		= "hclkd0",
+	.id		= -1,
+	.parent		= &clk_mout_d0sync.clk,
+};
+
+static struct clk clk_hclkd1 = {
+	.name		= "hclkd1",
+	.id		= -1,
+	.parent		= &clk_mout_d1sync.clk,
+};
+
+static struct clk clk_pclkd0 = {
+	.name		= "pclkd0",
+	.id		= -1,
+	.parent		= &clk_hclkd0,
+};
+
+static struct clk clk_pclkd1 = {
+	.name		= "pclkd1",
+	.id		= -1,
+	.parent		= &clk_hclkd1,
+};
+
+int s5p6442_clk_ip3_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
+}
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk	= {
+			.name		= "dout_a2m",
+			.id		= -1,
+			.parent		= &clk_mout_apll.clk,
+		},
+		.sources = &clk_src_apll,
+		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
+		.reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
+	}, {
+		.clk	= {
+			.name		= "dout_apll",
+			.id		= -1,
+			.parent		= &clk_mout_arm.clk,
+		},
+		.sources = &clk_src_arm,
+		.reg_src = { .reg = S5P_CLK_MUX_STAT0, .shift = 16, .size = 3 },
+		.reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 3 },
+	}, {
+		.clk	= {
+			.name		= "hclkd1",
+			.id		= -1,
+			.parent		= &clk_mout_d1sync.clk,
+		},
+		.sources = &clk_src_d1sync,
+		.reg_src = { .reg = S5P_CLK_MUX_STAT1, .shift = 24, .size = 3 },
+		.reg_div = { .reg = S5P_CLK_DIV0, .shift = 24, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "hclkd0",
+			.id		= -1,
+			.parent		= &clk_mout_d0sync.clk,
+		},
+		.sources = &clk_src_d0sync,
+		.reg_src = { .reg = S5P_CLK_MUX_STAT1, .shift = 28, .size = 3 },
+		.reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "pclkd0",
+			.id		= -1,
+			.parent		= &clk_hclkd0,
+		},
+		.sources = &clk_src_d0sync,
+		.reg_src = { .reg = S5P_CLK_MUX_STAT1, .shift = 28, .size = 3 },
+		.reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 },
+	}, {
+		.clk	= {
+			.name		= "pclkd1",
+			.id		= -1,
+			.parent		= &clk_hclkd1,
+		},
+		.sources = &clk_src_d1sync,
+		.reg_src = { .reg = S5P_CLK_MUX_STAT1, .shift = 24, .size = 3 },
+		.reg_div = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 },
+	}
+};
+
+/* Clock initialisation code */
+static struct clksrc_clk *init_parents[] = {
+	&clk_mout_apll,
+	&clk_mout_mpll,
+	&clk_mout_epll,
+	&clk_mout_arm,
+	&clk_mout_d0,
+	&clk_mout_d0sync,
+	&clk_mout_d1,
+	&clk_mout_d1sync,
+};
+
+void __init_or_cpufreq s5p6442_setup_clocks(void)
+{
+	struct clk *pclkd0_clk;
+	struct clk *pclkd1_clk;
+
+	unsigned long xtal;
+	unsigned long arm;
+	unsigned long hclkd0 = 0;
+	unsigned long hclkd1 = 0;
+	unsigned long pclkd0 = 0;
+	unsigned long pclkd1 = 0;
+
+	unsigned long apll;
+	unsigned long mpll;
+	unsigned long epll;
+	unsigned int ptr;
+
+	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
+
+	xtal = clk_get_rate(&clk_xtal);
+
+	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
+
+	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
+	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
+	epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500);
+
+	printk(KERN_INFO "S5P6440: PLL settings, A=%ld, M=%ld, E=%ld",
+			apll, mpll, epll);
+
+	clk_fout_apll.rate = apll;
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
+		s3c_set_clksrc(init_parents[ptr], true);
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+		s3c_set_clksrc(&clksrcs[ptr], true);
+
+	arm = clk_get_rate(&clk_dout_apll);
+	hclkd0 = clk_get_rate(&clk_hclkd0);
+	hclkd1 = clk_get_rate(&clk_hclkd1);
+
+	pclkd0_clk = clk_get(NULL, "pclkd0");
+	BUG_ON(IS_ERR(pclkd0_clk));
+
+	pclkd0 = clk_get_rate(pclkd0_clk);
+	clk_put(pclkd0_clk);
+
+	pclkd1_clk = clk_get(NULL, "pclkd1");
+	BUG_ON(IS_ERR(pclkd1_clk));
+
+	pclkd1 = clk_get_rate(pclkd1_clk);
+	clk_put(pclkd1_clk);
+
+	printk(KERN_INFO "S5P6442: HCLKD0=%ld, HCLKD1=%ld, PCLKD0=%ld, PCLKD1=%ld\n",
+			hclkd0, hclkd1, pclkd0, pclkd1);
+
+	/* For backward compatibility */
+	clk_f.rate = arm;
+	clk_h.rate = hclkd1;
+	clk_p.rate = pclkd1;
+
+	clk_pclkd0.rate = pclkd0;
+	clk_pclkd1.rate = pclkd1;
+}
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "systimer",
+		.id		= -1,
+		.parent		= &clk_pclkd1,
+		.enable		= s5p6442_clk_ip3_ctrl,
+		.ctrlbit	= (1<<16),
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_pclkd1,
+		.enable		= s5p6442_clk_ip3_ctrl,
+		.ctrlbit	= (1<<17),
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_pclkd1,
+		.enable		= s5p6442_clk_ip3_ctrl,
+		.ctrlbit	= (1<<18),
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_pclkd1,
+		.enable		= s5p6442_clk_ip3_ctrl,
+		.ctrlbit	= (1<<19),
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_pclkd1,
+		.enable		= s5p6442_clk_ip3_ctrl,
+		.ctrlbit	= (1<<23),
+	},
+};
+
+static struct clk *clks[] __initdata = {
+	&clk_ext,
+	&clk_epll,
+	&clk_mout_apll.clk,
+	&clk_mout_mpll.clk,
+	&clk_mout_epll.clk,
+	&clk_mout_d0.clk,
+	&clk_mout_d0sync.clk,
+	&clk_mout_d1.clk,
+	&clk_mout_d1sync.clk,
+	&clk_hclkd0,
+	&clk_pclkd0,
+	&clk_hclkd1,
+	&clk_pclkd1,
+};
+
+void __init s5p6442_register_clocks(void)
+{
+	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+	s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-s5p6442/cpu.c b/arch/arm/mach-s5p6442/cpu.c
new file mode 100644
index 0000000..bc2524d
--- /dev/null
+++ b/arch/arm/mach-s5p6442/cpu.c
@@ -0,0 +1,121 @@
+/* linux/arch/arm/mach-s5p6442/cpu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/proc-fns.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <asm/irq.h>
+
+#include <plat/regs-serial.h>
+#include <mach/regs-clock.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/s5p6442.h>
+
+/* Initial IO mappings */
+
+static struct map_desc s5p6442_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
+		.pfn		= __phys_to_pfn(S5P6442_PA_SYSTIMER),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC2,
+		.pfn		= __phys_to_pfn(S5P6442_PA_VIC2),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}
+};
+
+static void s5p6442_idle(void)
+{
+	if (!need_resched())
+		cpu_do_idle();
+
+	local_irq_enable();
+}
+
+/* s5p6442_map_io
+ *
+ * register the standard cpu IO areas
+*/
+
+void __init s5p6442_map_io(void)
+{
+	iotable_init(s5p6442_iodesc, ARRAY_SIZE(s5p6442_iodesc));
+}
+
+void __init s5p6442_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+	s3c24xx_register_baseclocks(xtal);
+	s5p_register_clocks(xtal);
+	s5p6442_register_clocks();
+	s5p6442_setup_clocks();
+}
+
+void __init s5p6442_init_irq(void)
+{
+	/* S5P6442 supports 3 VIC */
+	u32 vic[3];
+
+	/* VIC0, VIC1, and VIC2: some interrupt reserved */
+	vic[0] = 0x7fefffff;
+	vic[1] = 0X7f389c81;
+	vic[2] = 0X1bbbcfff;
+
+	s5p_init_irq(vic, ARRAY_SIZE(vic));
+}
+
+static struct sysdev_class s5p6442_sysclass = {
+	.name	= "s5p6442-core",
+};
+
+static struct sys_device s5p6442_sysdev = {
+	.cls	= &s5p6442_sysclass,
+};
+
+static int __init s5p6442_core_init(void)
+{
+	return sysdev_class_register(&s5p6442_sysclass);
+}
+
+core_initcall(s5p6442_core_init);
+
+int __init s5p6442_init(void)
+{
+	printk(KERN_INFO "S5P6442: Initializing architecture\n");
+
+	/* set idle function */
+	pm_idle = s5p6442_idle;
+
+	return sysdev_register(&s5p6442_sysdev);
+}
diff --git a/arch/arm/mach-s5p6442/include/mach/debug-macro.S b/arch/arm/mach-s5p6442/include/mach/debug-macro.S
new file mode 100644
index 0000000..1aae691
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/debug-macro.S
@@ -0,0 +1,36 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <mach/map.h>
+#include <plat/regs-serial.h>
+
+	.macro addruart, rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1
+		ldreq	\rx, = S3C_PA_UART
+		ldrne	\rx, = S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+		add	\rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+#endif
+	.endm
+
+#define fifo_full fifo_full_s5pv210
+#define fifo_level fifo_level_s5pv210
+
+/* include the reset of the code which will do the work, we're only
+ * compiling for a single cpu processor type so the default of s3c2440
+ * will be fine with us.
+ */
+
+#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s5p6442/include/mach/entry-macro.S b/arch/arm/mach-s5p6442/include/mach/entry-macro.S
new file mode 100644
index 0000000..6d574ed
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/entry-macro.S
@@ -0,0 +1,48 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/entry-macro.S
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Low-level IRQ helper macros for the Samsung S5P6442
+ *
+ * This program is free software; you can redistribute 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/hardware/vic.h>
+#include <mach/map.h>
+#include <plat/irqs.h>
+
+	.macro	disable_fiq
+	.endm
+
+	.macro	get_irqnr_preamble, base, tmp
+	ldr	\base, =VA_VIC0
+	.endm
+
+	.macro	arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+	@ check the vic0
+	mov	\irqnr, # S5P_IRQ_OFFSET + 31
+	ldr	\irqstat, [ \base, # VIC_IRQ_STATUS ]
+	teq	\irqstat, #0
+
+	@ otherwise try vic1
+	addeq	\tmp, \base, #(VA_VIC1 - VA_VIC0)
+	addeq	\irqnr, \irqnr, #32
+	ldreq	\irqstat, [ \tmp, # VIC_IRQ_STATUS ]
+	teqeq	\irqstat, #0
+
+	@ otherwise try vic2
+	addeq	\tmp, \base, #(VA_VIC2 - VA_VIC0)
+	addeq	\irqnr, \irqnr, #32
+	ldreq	\irqstat, [ \tmp, # VIC_IRQ_STATUS ]
+	teqeq	\irqstat, #0
+
+	clzne	\irqstat, \irqstat
+	subne	\irqnr, \irqnr, \irqstat
+	.endm
diff --git a/arch/arm/mach-s5p6442/include/mach/gpio.h b/arch/arm/mach-s5p6442/include/mach/gpio.h
new file mode 100644
index 0000000..b8715df
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/gpio.h
@@ -0,0 +1,123 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/gpio.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6442 - GPIO lib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H __FILE__
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define gpio_to_irq	__gpio_to_irq
+
+/* GPIO bank sizes */
+#define S5P6442_GPIO_A0_NR	(8)
+#define S5P6442_GPIO_A1_NR	(2)
+#define S5P6442_GPIO_B_NR	(4)
+#define S5P6442_GPIO_C0_NR	(5)
+#define S5P6442_GPIO_C1_NR	(5)
+#define S5P6442_GPIO_D0_NR	(2)
+#define S5P6442_GPIO_D1_NR	(6)
+#define S5P6442_GPIO_E0_NR	(8)
+#define S5P6442_GPIO_E1_NR	(5)
+#define S5P6442_GPIO_F0_NR	(8)
+#define S5P6442_GPIO_F1_NR	(8)
+#define S5P6442_GPIO_F2_NR	(8)
+#define S5P6442_GPIO_F3_NR	(6)
+#define S5P6442_GPIO_G0_NR	(7)
+#define S5P6442_GPIO_G1_NR	(7)
+#define S5P6442_GPIO_G2_NR	(7)
+#define S5P6442_GPIO_H0_NR	(8)
+#define S5P6442_GPIO_H1_NR	(8)
+#define S5P6442_GPIO_H2_NR	(8)
+#define S5P6442_GPIO_H3_NR	(8)
+#define S5P6442_GPIO_J0_NR	(8)
+#define S5P6442_GPIO_J1_NR	(6)
+#define S5P6442_GPIO_J2_NR	(8)
+#define S5P6442_GPIO_J3_NR	(8)
+#define S5P6442_GPIO_J4_NR	(5)
+
+/* GPIO bank numbers */
+
+/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
+ * space for debugging purposes so that any accidental
+ * change from one gpio bank to another can be caught.
+*/
+
+#define S5P6442_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s5p_gpio_number {
+	S5P6442_GPIO_A0_START	= 0,
+	S5P6442_GPIO_A1_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_A0),
+	S5P6442_GPIO_B_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_A1),
+	S5P6442_GPIO_C0_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_B),
+	S5P6442_GPIO_C1_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_C0),
+	S5P6442_GPIO_D0_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_C1),
+	S5P6442_GPIO_D1_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_D0),
+	S5P6442_GPIO_E0_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_D1),
+	S5P6442_GPIO_E1_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_E0),
+	S5P6442_GPIO_F0_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_E1),
+	S5P6442_GPIO_F1_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_F0),
+	S5P6442_GPIO_F2_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_F1),
+	S5P6442_GPIO_F3_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_F2),
+	S5P6442_GPIO_G0_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_F3),
+	S5P6442_GPIO_G1_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_G0),
+	S5P6442_GPIO_G2_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_G1),
+	S5P6442_GPIO_H0_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_G2),
+	S5P6442_GPIO_H1_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_H0),
+	S5P6442_GPIO_H2_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_H1),
+	S5P6442_GPIO_H3_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_H2),
+	S5P6442_GPIO_J0_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_H3),
+	S5P6442_GPIO_J1_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_J0),
+	S5P6442_GPIO_J2_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_J1),
+	S5P6442_GPIO_J3_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_J2),
+	S5P6442_GPIO_J4_START	= S5P6442_GPIO_NEXT(S5P6442_GPIO_J3),
+};
+
+/* S5P6442 GPIO number definitions. */
+#define S5P6442_GPA0(_nr)	(S5P6442_GPIO_A0_START + (_nr))
+#define S5P6442_GPA1(_nr)	(S5P6442_GPIO_A1_START + (_nr))
+#define S5P6442_GPB(_nr)	(S5P6442_GPIO_B_START + (_nr))
+#define S5P6442_GPC0(_nr)	(S5P6442_GPIO_C0_START + (_nr))
+#define S5P6442_GPC1(_nr)	(S5P6442_GPIO_C1_START + (_nr))
+#define S5P6442_GPD0(_nr)	(S5P6442_GPIO_D0_START + (_nr))
+#define S5P6442_GPD1(_nr)	(S5P6442_GPIO_D1_START + (_nr))
+#define S5P6442_GPE0(_nr)	(S5P6442_GPIO_E0_START + (_nr))
+#define S5P6442_GPE1(_nr)	(S5P6442_GPIO_E1_START + (_nr))
+#define S5P6442_GPF0(_nr)	(S5P6442_GPIO_F0_START + (_nr))
+#define S5P6442_GPF1(_nr)	(S5P6442_GPIO_F1_START + (_nr))
+#define S5P6442_GPF2(_nr)	(S5P6442_GPIO_F2_START + (_nr))
+#define S5P6442_GPF3(_nr)	(S5P6442_GPIO_F3_START + (_nr))
+#define S5P6442_GPG0(_nr)	(S5P6442_GPIO_G0_START + (_nr))
+#define S5P6442_GPG1(_nr)	(S5P6442_GPIO_G1_START + (_nr))
+#define S5P6442_GPG2(_nr)	(S5P6442_GPIO_G2_START + (_nr))
+#define S5P6442_GPH0(_nr)	(S5P6442_GPIO_H0_START + (_nr))
+#define S5P6442_GPH1(_nr)	(S5P6442_GPIO_H1_START + (_nr))
+#define S5P6442_GPH2(_nr)	(S5P6442_GPIO_H2_START + (_nr))
+#define S5P6442_GPH3(_nr)	(S5P6442_GPIO_H3_START + (_nr))
+#define S5P6442_GPJ0(_nr)	(S5P6442_GPIO_J0_START + (_nr))
+#define S5P6442_GPJ1(_nr)	(S5P6442_GPIO_J1_START + (_nr))
+#define S5P6442_GPJ2(_nr)	(S5P6442_GPIO_J2_START + (_nr))
+#define S5P6442_GPJ3(_nr)	(S5P6442_GPIO_J3_START + (_nr))
+#define S5P6442_GPJ4(_nr)	(S5P6442_GPIO_J4_START + (_nr))
+
+/* the end of the S5P6442 specific gpios */
+#define S5P6442_GPIO_END	(S5P6442_GPJ4(S5P6442_GPIO_J4_NR) + 1)
+#define S3C_GPIO_END		S5P6442_GPIO_END
+
+/* define the number of gpios we need to the one after the GPJ4() range */
+#define ARCH_NR_GPIOS		(S5P6442_GPJ4(S5P6442_GPIO_J4_NR) +	\
+				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/hardware.h b/arch/arm/mach-s5p6442/include/mach/hardware.h
new file mode 100644
index 0000000..8cd7b67
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/hardware.h
@@ -0,0 +1,18 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/hardware.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6442 - Hardware support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H __FILE__
+
+/* currently nothing here, placeholder */
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/io.h b/arch/arm/mach-s5p6442/include/mach/io.h
new file mode 100644
index 0000000..5d2195a
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/io.h
@@ -0,0 +1,17 @@
+/* arch/arm/mach-s5p6442/include/mach/io.h
+ *
+ * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Default IO routines for S5P6442
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif
diff --git a/arch/arm/mach-s5p6442/include/mach/irqs.h b/arch/arm/mach-s5p6442/include/mach/irqs.h
new file mode 100644
index 0000000..da66580
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/irqs.h
@@ -0,0 +1,86 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/irqs.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6442 - IRQ definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H __FILE__
+
+#include <plat/irqs.h>
+
+/* VIC0 */
+#define IRQ_EINT16_31 		S5P_IRQ_VIC0(16)
+#define IRQ_BATF 		S5P_IRQ_VIC0(17)
+#define IRQ_MDMA 		S5P_IRQ_VIC0(18)
+#define IRQ_PDMA 		S5P_IRQ_VIC0(19)
+#define IRQ_TIMER0_VIC		S5P_IRQ_VIC0(21)
+#define IRQ_TIMER1_VIC		S5P_IRQ_VIC0(22)
+#define IRQ_TIMER2_VIC		S5P_IRQ_VIC0(23)
+#define IRQ_TIMER3_VIC		S5P_IRQ_VIC0(24)
+#define IRQ_TIMER4_VIC		S5P_IRQ_VIC0(25)
+#define IRQ_SYSTIMER		S5P_IRQ_VIC0(26)
+#define IRQ_WDT			S5P_IRQ_VIC0(27)
+#define IRQ_RTC_ALARM		S5P_IRQ_VIC0(28)
+#define IRQ_RTC_TIC		S5P_IRQ_VIC0(29)
+#define IRQ_GPIOINT		S5P_IRQ_VIC0(30)
+
+/* VIC1 */
+#define IRQ_nPMUIRQ 		S5P_IRQ_VIC1(0)
+#define IRQ_ONENAND 		S5P_IRQ_VIC1(7)
+#define IRQ_UART0 		S5P_IRQ_VIC1(10)
+#define IRQ_UART1 		S5P_IRQ_VIC1(11)
+#define IRQ_UART2 		S5P_IRQ_VIC1(12)
+#define IRQ_SPI0 		S5P_IRQ_VIC1(15)
+#define IRQ_IIC 		S5P_IRQ_VIC1(19)
+#define IRQ_IIC1 		S5P_IRQ_VIC1(20)
+#define IRQ_IIC2 		S5P_IRQ_VIC1(21)
+#define IRQ_OTG 		S5P_IRQ_VIC1(24)
+#define IRQ_MSM 		S5P_IRQ_VIC1(25)
+#define IRQ_HSMMC0 		S5P_IRQ_VIC1(26)
+#define IRQ_HSMMC1 		S5P_IRQ_VIC1(27)
+#define IRQ_HSMMC2 		S5P_IRQ_VIC1(28)
+#define IRQ_COMMRX 		S5P_IRQ_VIC1(29)
+#define IRQ_COMMTX 		S5P_IRQ_VIC1(30)
+
+/* VIC2 */
+#define IRQ_LCD0 		S5P_IRQ_VIC2(0)
+#define IRQ_LCD1 		S5P_IRQ_VIC2(1)
+#define IRQ_LCD2 		S5P_IRQ_VIC2(2)
+#define IRQ_LCD3 		S5P_IRQ_VIC2(3)
+#define IRQ_ROTATOR 		S5P_IRQ_VIC2(4)
+#define IRQ_FIMC0 		S5P_IRQ_VIC2(5)
+#define IRQ_FIMC1 		S5P_IRQ_VIC2(6)
+#define IRQ_FIMC2 		S5P_IRQ_VIC2(7)
+#define IRQ_JPEG 		S5P_IRQ_VIC2(8)
+#define IRQ_3D 			S5P_IRQ_VIC2(10)
+#define IRQ_Mixer 		S5P_IRQ_VIC2(11)
+#define IRQ_MFC 		S5P_IRQ_VIC2(14)
+#define IRQ_TVENC 		S5P_IRQ_VIC2(15)
+#define IRQ_I2S0 		S5P_IRQ_VIC2(16)
+#define IRQ_I2S1 		S5P_IRQ_VIC2(17)
+#define IRQ_RP 			S5P_IRQ_VIC2(19)
+#define IRQ_PCM0 		S5P_IRQ_VIC2(20)
+#define IRQ_PCM1 		S5P_IRQ_VIC2(21)
+#define IRQ_ADC 		S5P_IRQ_VIC2(23)
+#define IRQ_PENDN 		S5P_IRQ_VIC2(24)
+#define IRQ_KEYPAD 		S5P_IRQ_VIC2(25)
+#define IRQ_SSS_INT 		S5P_IRQ_VIC2(27)
+#define IRQ_SSS_HASH 		S5P_IRQ_VIC2(28)
+#define IRQ_VIC_END 		S5P_IRQ_VIC2(31)
+
+#define S5P_IRQ_EINT_BASE	(IRQ_VIC_END + 1)
+
+#define IRQ_EINT(x)             ((x) < 16 ? S5P_IRQ_VIC0(x) : \
+					(S5P_IRQ_EINT_BASE + (x)-16))
+/* Set the default NR_IRQS */
+
+#define NR_IRQS 		(IRQ_EINT(31) + 1)
+
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/map.h b/arch/arm/mach-s5p6442/include/mach/map.h
new file mode 100644
index 0000000..685277d
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/map.h
@@ -0,0 +1,58 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/map.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6442 - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H __FILE__
+
+#include <plat/map-base.h>
+#include <plat/map-s5p.h>
+
+#define S5P6442_PA_CHIPID	(0xE0000000)
+#define S5P_PA_CHIPID		S5P6442_PA_CHIPID
+
+#define S5P6442_PA_SYSCON	(0xE0100000)
+#define S5P_PA_SYSCON		S5P6442_PA_SYSCON
+
+#define S5P6442_PA_GPIO		(0xE0200000)
+#define S5P_PA_GPIO		S5P6442_PA_GPIO
+
+#define S5P6442_PA_VIC0		(0xE4000000)
+#define S5P_PA_VIC0		S5P6442_PA_VIC0
+
+#define S5P6442_PA_VIC1		(0xE4100000)
+#define S5P_PA_VIC1		S5P6442_PA_VIC1
+
+#define S5P6442_PA_VIC2		(0xE4200000)
+#define S5P_PA_VIC2		S5P6442_PA_VIC2
+
+#define S5P6442_PA_TIMER	(0xEA000000)
+#define S5P_PA_TIMER		S5P6442_PA_TIMER
+
+#define S5P6442_PA_SYSTIMER   	(0xEA100000)
+
+#define S5P6442_PA_UART		(0xEC000000)
+
+#define S5P_PA_UART0		(S5P6442_PA_UART + 0x0)
+#define S5P_PA_UART1		(S5P6442_PA_UART + 0x400)
+#define S5P_PA_UART2		(S5P6442_PA_UART + 0x800)
+#define S5P_SZ_UART		SZ_256
+
+#define S5P6442_PA_IIC0		(0xEC100000)
+
+#define S5P6442_PA_SDRAM	(0x20000000)
+#define S5P_PA_SDRAM		S5P6442_PA_SDRAM
+
+/* compatibiltiy defines. */
+#define S3C_PA_UART		S5P6442_PA_UART
+#define S3C_PA_IIC		S5P6442_PA_IIC0
+
+#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/memory.h b/arch/arm/mach-s5p6442/include/mach/memory.h
new file mode 100644
index 0000000..9ddd877
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/memory.h
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/memory.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6442 - Memory definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PHYS_OFFSET		UL(0x20000000)
+#define CONSISTENT_DMA_SIZE	SZ_8M
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/pwm-clock.h b/arch/arm/mach-s5p6442/include/mach/pwm-clock.h
new file mode 100644
index 0000000..15e8525
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/pwm-clock.h
@@ -0,0 +1,69 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/pwm-clock.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * Copyright 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
+ *
+ * S5P6442 - pwm clock and timer support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_PWMCLK_H
+#define __ASM_ARCH_PWMCLK_H __FILE__
+
+/**
+ * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
+ * @cfg: The timer TCFG1 register bits shifted down to 0.
+ *
+ * Return true if the given configuration from TCFG1 is a TCLK instead
+ * any of the TDIV clocks.
+ */
+static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
+{
+	return tcfg == S3C2410_TCFG1_MUX_TCLK;
+}
+
+/**
+ * tcfg_to_divisor() - convert tcfg1 setting to a divisor
+ * @tcfg1: The tcfg1 setting, shifted down.
+ *
+ * Get the divisor value for the given tcfg1 setting. We assume the
+ * caller has already checked to see if this is not a TCLK source.
+ */
+static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
+{
+	return 1 << (1 + tcfg1);
+}
+
+/**
+ * pwm_tdiv_has_div1() - does the tdiv setting have a /1
+ *
+ * Return true if we have a /1 in the tdiv setting.
+ */
+static inline unsigned int pwm_tdiv_has_div1(void)
+{
+	return 0;
+}
+
+/**
+ * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
+ * @div: The divisor to calculate the bit information for.
+ *
+ * Turn a divisor into the necessary bit field for TCFG1.
+ */
+static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
+{
+	return ilog2(div) - 1;
+}
+
+#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
+
+#endif /* __ASM_ARCH_PWMCLK_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/regs-clock.h b/arch/arm/mach-s5p6442/include/mach/regs-clock.h
new file mode 100644
index 0000000..d8360b5
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/regs-clock.h
@@ -0,0 +1,103 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6442 - Clock register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_CLKREG(x)		(S3C_VA_SYS + (x))
+
+#define S5P_APLL_LOCK		S5P_CLKREG(0x00)
+#define S5P_MPLL_LOCK		S5P_CLKREG(0x08)
+#define S5P_EPLL_LOCK		S5P_CLKREG(0x10)
+#define S5P_VPLL_LOCK		S5P_CLKREG(0x20)
+
+#define S5P_APLL_CON		S5P_CLKREG(0x100)
+#define S5P_MPLL_CON		S5P_CLKREG(0x108)
+#define S5P_EPLL_CON		S5P_CLKREG(0x110)
+#define S5P_VPLL_CON		S5P_CLKREG(0x120)
+
+#define S5P_CLK_SRC0		S5P_CLKREG(0x200)
+#define S5P_CLK_SRC1		S5P_CLKREG(0x204)
+#define S5P_CLK_SRC2		S5P_CLKREG(0x208)
+#define S5P_CLK_SRC3		S5P_CLKREG(0x20C)
+#define S5P_CLK_SRC4		S5P_CLKREG(0x210)
+#define S5P_CLK_SRC5		S5P_CLKREG(0x214)
+#define S5P_CLK_SRC6		S5P_CLKREG(0x218)
+
+#define S5P_CLK_SRC_MASK0	S5P_CLKREG(0x280)
+#define S5P_CLK_SRC_MASK1	S5P_CLKREG(0x284)
+
+#define S5P_CLK_DIV0		S5P_CLKREG(0x300)
+#define S5P_CLK_DIV1		S5P_CLKREG(0x304)
+#define S5P_CLK_DIV2		S5P_CLKREG(0x308)
+#define S5P_CLK_DIV3		S5P_CLKREG(0x30C)
+#define S5P_CLK_DIV4		S5P_CLKREG(0x310)
+#define S5P_CLK_DIV5		S5P_CLKREG(0x314)
+#define S5P_CLK_DIV6		S5P_CLKREG(0x318)
+
+#define S5P_CLKGATE_IP3		S5P_CLKREG(0x46C)
+
+/* CLK_OUT */
+#define S5P_CLK_OUT_SHIFT	(12)
+#define S5P_CLK_OUT_MASK	(0x1F << S5P_CLK_OUT_SHIFT)
+#define S5P_CLK_OUT		S5P_CLKREG(0x500)
+
+#define S5P_CLK_DIV_STAT0	S5P_CLKREG(0x1000)
+#define S5P_CLK_DIV_STAT1	S5P_CLKREG(0x1004)
+
+#define S5P_CLK_MUX_STAT0	S5P_CLKREG(0x1100)
+#define S5P_CLK_MUX_STAT1	S5P_CLKREG(0x1104)
+
+#define S5P_MDNIE_SEL		S5P_CLKREG(0x7008)
+
+/* Register Bit definition */
+#define S5P_EPLL_EN     		(1<<31)
+#define S5P_EPLL_MASK   		0xffffffff
+#define S5P_EPLLVAL(_m, _p, _s)   	((_m) << 16 | ((_p) << 8) | ((_s)))
+
+/* CLKDIV0 */
+#define S5P_CLKDIV0_APLL_SHIFT		(0)
+#define S5P_CLKDIV0_APLL_MASK		(0x7 << S5P_CLKDIV0_APLL_SHIFT)
+#define S5P_CLKDIV0_A2M_SHIFT		(4)
+#define S5P_CLKDIV0_A2M_MASK		(0x7 << S5P_CLKDIV0_A2M_SHIFT)
+#define S5P_CLKDIV0_D0CLK_SHIFT		(16)
+#define S5P_CLKDIV0_D0CLK_MASK		(0xF << S5P_CLKDIV0_D0CLK_SHIFT)
+#define S5P_CLKDIV0_P0CLK_SHIFT		(20)
+#define S5P_CLKDIV0_P0CLK_MASK		(0x7 << S5P_CLKDIV0_P0CLK_SHIFT)
+#define S5P_CLKDIV0_D1CLK_SHIFT		(24)
+#define S5P_CLKDIV0_D1CLK_MASK		(0xF << S5P_CLKDIV0_D1CLK_SHIFT)
+#define S5P_CLKDIV0_P1CLK_SHIFT		(28)
+#define S5P_CLKDIV0_P1CLK_MASK		(0x7 << S5P_CLKDIV0_P1CLK_SHIFT)
+
+/* Clock MUX status Registers */
+#define S5P_CLK_MUX_STAT0_APLL_SHIFT	(0)
+#define S5P_CLK_MUX_STAT0_APLL_MASK	(0x7 << S5P_CLK_MUX_STAT0_APLL_SHIFT)
+#define S5P_CLK_MUX_STAT0_MPLL_SHIFT	(4)
+#define S5P_CLK_MUX_STAT0_MPLL_MASK	(0x7 << S5P_CLK_MUX_STAT0_MPLL_SHIFT)
+#define S5P_CLK_MUX_STAT0_EPLL_SHIFT	(8)
+#define S5P_CLK_MUX_STAT0_EPLL_MASK	(0x7 << S5P_CLK_MUX_STAT0_EPLL_SHIFT)
+#define S5P_CLK_MUX_STAT0_VPLL_SHIFT	(12)
+#define S5P_CLK_MUX_STAT0_VPLL_MASK	(0x7 << S5P_CLK_MUX_STAT0_VPLL_SHIFT)
+#define S5P_CLK_MUX_STAT0_MUXARM_SHIFT	(16)
+#define S5P_CLK_MUX_STAT0_MUXARM_MASK	(0x7 << S5P_CLK_MUX_STAT0_MUXARM_SHIFT)
+#define S5P_CLK_MUX_STAT0_MUXD0_SHIFT	(20)
+#define S5P_CLK_MUX_STAT0_MUXD0_MASK	(0x7 << S5P_CLK_MUX_STAT0_MUXD0_SHIFT)
+#define S5P_CLK_MUX_STAT0_MUXD1_SHIFT	(24)
+#define S5P_CLK_MUX_STAT0_MUXD1_MASK	(0x7 << S5P_CLK_MUX_STAT0_MUXD1_SHIFT)
+#define S5P_CLK_MUX_STAT1_D1SYNC_SHIFT	(24)
+#define S5P_CLK_MUX_STAT1_D1SYNC_MASK	(0x7 << S5P_CLK_MUX_STAT1_D1SYNC_SHIFT)
+#define S5P_CLK_MUX_STAT1_D0SYNC_SHIFT	(28)
+#define S5P_CLK_MUX_STAT1_D0SYNC_MASK	(0x7 << S5P_CLK_MUX_STAT1_D0SYNC_SHIFT)
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/regs-irq.h b/arch/arm/mach-s5p6442/include/mach/regs-irq.h
new file mode 100644
index 0000000..73782b5
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/regs-irq.h
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/regs-irq.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6442 - IRQ register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_IRQ_H
+#define __ASM_ARCH_REGS_IRQ_H __FILE__
+
+#include <asm/hardware/vic.h>
+#include <mach/map.h>
+
+#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/system.h b/arch/arm/mach-s5p6442/include/mach/system.h
new file mode 100644
index 0000000..8bcd8ed
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/system.h
@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/system.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6442 - system support header
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H __FILE__
+
+static void arch_idle(void)
+{
+	/* nothing here yet */
+}
+
+static void arch_reset(char mode, const char *cmd)
+{
+	/* nothing here yet */
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/tick.h b/arch/arm/mach-s5p6442/include/mach/tick.h
new file mode 100644
index 0000000..e1d4cab
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/tick.h
@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/tick.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/mach-s3c6400/include/mach/tick.h
+ *
+ * S5P6442 - Timer tick support definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TICK_H
+#define __ASM_ARCH_TICK_H __FILE__
+
+static inline u32 s3c24xx_ostimer_pending(void)
+{
+	u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
+	return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));
+}
+
+#define TICK_MAX	(0xffffffff)
+
+#endif /* __ASM_ARCH_TICK_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/timex.h b/arch/arm/mach-s5p6442/include/mach/timex.h
new file mode 100644
index 0000000..ff8f2fc
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/timex.h
@@ -0,0 +1,24 @@
+/* arch/arm/mach-s5p6442/include/mach/timex.h
+ *
+ * Copyright (c) 2003-2010 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S5P6442 - time parameters
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
+
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/uncompress.h b/arch/arm/mach-s5p6442/include/mach/uncompress.h
new file mode 100644
index 0000000..5ac7cbe
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/uncompress.h
@@ -0,0 +1,24 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/uncompress.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P6442 - uncompress code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <mach/map.h>
+#include <plat/uncompress.h>
+
+static void arch_detect_cpu(void)
+{
+	/* we do not need to do any cpu detection here at the moment. */
+}
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-s5p6442/include/mach/vmalloc.h b/arch/arm/mach-s5p6442/include/mach/vmalloc.h
new file mode 100644
index 0000000..be333368
--- /dev/null
+++ b/arch/arm/mach-s5p6442/include/mach/vmalloc.h
@@ -0,0 +1,17 @@
+/* arch/arm/mach-s5p6442/include/mach/vmalloc.h
+ *
+ * Copyright 2010 Ben Dooks <ben-linux@fluff.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.
+ *
+ * S5P6442 vmalloc definition
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END	  (0xE0000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5p6442/init.c b/arch/arm/mach-s5p6442/init.c
new file mode 100644
index 0000000..1874bdb
--- /dev/null
+++ b/arch/arm/mach-s5p6442/init.c
@@ -0,0 +1,44 @@
+/* linux/arch/arm/mach-s5p6442/s5p6442-init.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/s5p6442.h>
+#include <plat/regs-serial.h>
+
+static struct s3c24xx_uart_clksrc s5p6442_serial_clocks[] = {
+	[0] = {
+		.name		= "pclk",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+};
+
+/* uart registration process */
+void __init s5p6442_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	struct s3c2410_uartcfg *tcfg = cfg;
+	u32 ucnt;
+
+	for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
+		if (!tcfg->clocks) {
+			tcfg->clocks = s5p6442_serial_clocks;
+			tcfg->clocks_size = ARRAY_SIZE(s5p6442_serial_clocks);
+		}
+	}
+
+	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
+}
diff --git a/arch/arm/mach-s5p6442/mach-smdk6442.c b/arch/arm/mach-s5p6442/mach-smdk6442.c
new file mode 100644
index 0000000..0d63371
--- /dev/null
+++ b/arch/arm/mach-s5p6442/mach-smdk6442.c
@@ -0,0 +1,91 @@
+/* linux/arch/arm/mach-s5p6442/mach-smdk6442.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/regs-serial.h>
+#include <plat/s5p6442.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define S5P6442_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define S5P6442_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define S5P6442_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdk6442_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= S5P6442_UCON_DEFAULT,
+		.ulcon		= S5P6442_ULCON_DEFAULT,
+		.ufcon		= S5P6442_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= S5P6442_UCON_DEFAULT,
+		.ulcon		= S5P6442_ULCON_DEFAULT,
+		.ufcon		= S5P6442_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= S5P6442_UCON_DEFAULT,
+		.ulcon		= S5P6442_ULCON_DEFAULT,
+		.ufcon		= S5P6442_UFCON_DEFAULT,
+	},
+};
+
+static struct platform_device *smdk6442_devices[] __initdata = {
+};
+
+static void __init smdk6442_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(smdk6442_uartcfgs, ARRAY_SIZE(smdk6442_uartcfgs));
+}
+
+static void __init smdk6442_machine_init(void)
+{
+	platform_add_devices(smdk6442_devices, ARRAY_SIZE(smdk6442_devices));
+}
+
+MACHINE_START(SMDK6442, "SMDK6442")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= s5p6442_init_irq,
+	.map_io		= smdk6442_map_io,
+	.init_machine	= smdk6442_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s5pc100/include/mach/gpio-core.h b/arch/arm/mach-s5pc100/include/mach/gpio-core.h
deleted file mode 100644
index ad28d8e..0000000
--- a/arch/arm/mach-s5pc100/include/mach/gpio-core.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* arch/arm/mach-s5pc100/include/mach/gpio-core.h
- *
- * Copyright 2009 Samsung Electronics Co.
- *      Byungho Min <bhmin@samsung.com>
- *
- * S5PC100 - GPIO core support
- *
- * Based on mach-s3c6400/include/mach/gpio-core.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_GPIO_CORE_H
-#define __ASM_ARCH_GPIO_CORE_H __FILE__
-
-/* currently we just include the platform support */
-#include <plat/gpio-core.h>
-
-#endif /* __ASM_ARCH_GPIO_CORE_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/io.h b/arch/arm/mach-s5pc100/include/mach/io.h
new file mode 100644
index 0000000..819acf5
--- /dev/null
+++ b/arch/arm/mach-s5pc100/include/mach/io.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-s5pc100/include/mach/io.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben-linux@fluff.org>
+ *
+ * Default IO routines for S5PC100 systems
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif
diff --git a/arch/arm/mach-s5pc100/include/mach/tick.h b/arch/arm/mach-s5pc100/include/mach/tick.h
index d3de0f3..f338c9e 100644
--- a/arch/arm/mach-s5pc100/include/mach/tick.h
+++ b/arch/arm/mach-s5pc100/include/mach/tick.h
@@ -21,7 +21,7 @@
 static inline u32 s3c24xx_ostimer_pending(void)
 {
 	u32 pend = __raw_readl(S3C_VA_VIC0 + VIC_RAW_STATUS);
-	return pend & 1 << (IRQ_TIMER4 - S5PC1XX_IRQ_VIC0(0));
+	return pend & 1 << (IRQ_TIMER4_VIC - S5PC1XX_IRQ_VIC0(0));
 }
 
 #define TICK_MAX	(0xffffffff)
diff --git a/arch/arm/mach-s5pc100/include/mach/timex.h b/arch/arm/mach-s5pc100/include/mach/timex.h
new file mode 100644
index 0000000..47ffb17
--- /dev/null
+++ b/arch/arm/mach-s5pc100/include/mach/timex.h
@@ -0,0 +1,24 @@
+/* arch/arm/mach-s5pc100/include/mach/timex.h
+ *
+ * Copyright (c) 2003-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C6400 - time parameters
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
+
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/vmalloc.h b/arch/arm/mach-s5pc100/include/mach/vmalloc.h
new file mode 100644
index 0000000..be9df79
--- /dev/null
+++ b/arch/arm/mach-s5pc100/include/mach/vmalloc.h
@@ -0,0 +1,17 @@
+/* arch/arm/mach-s5pc100/include/mach/vmalloc.h
+ *
+ * Copyright 2010 Ben Dooks <ben-linux@fluff.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.
+ *
+ * S3C6400 vmalloc definition
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END	  (0xe0000000UL)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5pc100/setup-sdhci.c b/arch/arm/mach-s5pc100/setup-sdhci.c
index 4385986..ea7ff19 100644
--- a/arch/arm/mach-s5pc100/setup-sdhci.c
+++ b/arch/arm/mach-s5pc100/setup-sdhci.c
@@ -28,8 +28,8 @@
 char *s5pc100_hsmmc_clksrcs[4] = {
 	[0] = "hsmmc",
 	[1] = "hsmmc",
-	/* [2] = "mmc_bus", not yet succesfuuly used yet */
-	/* [3] = "48m", - note not succesfully used yet */
+	/* [2] = "mmc_bus", not yet successfully used yet */
+	/* [3] = "48m", - note not successfully used yet */
 };
 
 
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
new file mode 100644
index 0000000..af33a1a
--- /dev/null
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -0,0 +1,40 @@
+# arch/arm/mach-s5pv210/Kconfig
+#
+# Copyright (c) 2010 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+# Configuration options for the S5PV210/S5PC110
+
+if ARCH_S5PV210
+
+config CPU_S5PV210
+	bool
+	select PLAT_S5P
+	help
+	  Enable S5PV210 CPU support
+
+choice
+	prompt "Select machine type"
+	depends on ARCH_S5PV210
+	default MACH_SMDKV210
+
+config MACH_SMDKV210
+	bool "SMDKV210"
+	select CPU_S5PV210
+	select ARCH_SPARSEMEM_ENABLE
+	help
+	  Machine support for Samsung SMDKV210
+
+config MACH_SMDKC110
+	bool "SMDKC110"
+	select CPU_S5PV210
+	select ARCH_SPARSEMEM_ENABLE
+	help
+	  Machine support for Samsung SMDKC110
+	  S5PC110(MCP) is one of package option of S5PV210
+
+endchoice
+
+endif
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
new file mode 100644
index 0000000..8ebf51c
--- /dev/null
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -0,0 +1,20 @@
+# arch/arm/mach-s5pv210/Makefile
+#
+# Copyright (c) 2010 Samsung Electronics Co., Ltd.
+# 		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+# Core support for S5PV210 system
+
+obj-$(CONFIG_CPU_S5PV210)	+= cpu.o init.o clock.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDKV210)	+= mach-smdkv210.o
+obj-$(CONFIG_MACH_SMDKC110)	+= mach-smdkc110.o
diff --git a/arch/arm/mach-s5pv210/Makefile.boot b/arch/arm/mach-s5pv210/Makefile.boot
new file mode 100644
index 0000000..ff90aa1
--- /dev/null
+++ b/arch/arm/mach-s5pv210/Makefile.boot
@@ -0,0 +1,2 @@
+   zreladdr-y	:= 0x20008000
+params_phys-y	:= 0x20000100
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
new file mode 100644
index 0000000..ccccae2
--- /dev/null
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -0,0 +1,454 @@
+/* linux/arch/arm/mach-s5pv210/clock.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+
+#include <plat/cpu-freq.h>
+#include <mach/regs-clock.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5pv210.h>
+
+static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
+}
+
+static int s5pv210_clk_ip1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP1, clk, enable);
+}
+
+static int s5pv210_clk_ip2_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP2, clk, enable);
+}
+
+static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
+}
+
+static struct clk clk_h200 = {
+	.name		= "hclk200",
+	.id		= -1,
+};
+
+static struct clk clk_h100 = {
+	.name		= "hclk100",
+	.id		= -1,
+};
+
+static struct clk clk_h166 = {
+	.name		= "hclk166",
+	.id		= -1,
+};
+
+static struct clk clk_h133 = {
+	.name		= "hclk133",
+	.id		= -1,
+};
+
+static struct clk clk_p100 = {
+	.name		= "pclk100",
+	.id		= -1,
+};
+
+static struct clk clk_p83 = {
+	.name		= "pclk83",
+	.id		= -1,
+};
+
+static struct clk clk_p66 = {
+	.name		= "pclk66",
+	.id		= -1,
+};
+
+static struct clk *sys_clks[] = {
+	&clk_h200,
+	&clk_h100,
+	&clk_h166,
+	&clk_h133,
+	&clk_p100,
+	&clk_p83,
+	&clk_p66
+};
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "rot",
+		.id		= -1,
+		.parent		= &clk_h166,
+		.enable		= s5pv210_clk_ip0_ctrl,
+		.ctrlbit	= (1<<29),
+	}, {
+		.name		= "otg",
+		.id		= -1,
+		.parent		= &clk_h133,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1<<16),
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h133,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1<<17),
+	}, {
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h166,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1<<0),
+	}, {
+		.name		= "cfcon",
+		.id		= 0,
+		.parent		= &clk_h133,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1<<25),
+	}, {
+		.name		= "hsmmc",
+		.id		= 0,
+		.parent		= &clk_h133,
+		.enable		= s5pv210_clk_ip2_ctrl,
+		.ctrlbit	= (1<<16),
+	}, {
+		.name		= "hsmmc",
+		.id		= 1,
+		.parent		= &clk_h133,
+		.enable		= s5pv210_clk_ip2_ctrl,
+		.ctrlbit	= (1<<17),
+	}, {
+		.name		= "hsmmc",
+		.id		= 2,
+		.parent		= &clk_h133,
+		.enable		= s5pv210_clk_ip2_ctrl,
+		.ctrlbit	= (1<<18),
+	}, {
+		.name		= "hsmmc",
+		.id		= 3,
+		.parent		= &clk_h133,
+		.enable		= s5pv210_clk_ip2_ctrl,
+		.ctrlbit	= (1<<19),
+	}, {
+		.name		= "systimer",
+		.id		= -1,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<16),
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<22),
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<15),
+	}, {
+		.name		= "i2c",
+		.id		= 0,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<7),
+	}, {
+		.name		= "i2c",
+		.id		= 1,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<8),
+	}, {
+		.name		= "i2c",
+		.id		= 2,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<9),
+	}, {
+		.name		= "spi",
+		.id		= 0,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<12),
+	}, {
+		.name		= "spi",
+		.id		= 1,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<13),
+	}, {
+		.name		= "spi",
+		.id		= 2,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<14),
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<23),
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<24),
+	}, {
+		.name		= "keypad",
+		.id		= -1,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<21),
+	}, {
+		.name		= "i2s_v50",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<4),
+	}, {
+		.name		= "i2s_v32",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<4),
+	}, {
+		.name		= "i2s_v32",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<4),
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<7),
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<8),
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<9),
+	}, {
+		.name		= "uart",
+		.id		= 3,
+		.parent		= &clk_p66,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<10),
+	},
+};
+
+static struct clksrc_clk clk_mout_apll = {
+	.clk	= {
+		.name		= "mout_apll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_apll,
+	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
+};
+
+static struct clksrc_clk clk_mout_epll = {
+	.clk	= {
+		.name		= "mout_epll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_epll,
+	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk clk_mout_mpll = {
+	.clk = {
+		.name		= "mout_mpll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_mpll,
+	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_uart_list[] = {
+	[6] = &clk_mout_mpll.clk,
+	[7] = &clk_mout_epll.clk,
+};
+
+static struct clksrc_sources clkset_uart = {
+	.sources	= clkset_uart_list,
+	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
+};
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk	= {
+			.name		= "uclk1",
+			.id		= -1,
+			.ctrlbit	= (1<<17),
+			.enable		= s5pv210_clk_ip3_ctrl,
+		},
+		.sources = &clkset_uart,
+		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
+	}
+};
+
+/* Clock initialisation code */
+static struct clksrc_clk *init_parents[] = {
+	&clk_mout_apll,
+	&clk_mout_epll,
+	&clk_mout_mpll,
+};
+
+#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
+
+void __init_or_cpufreq s5pv210_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+	unsigned long xtal;
+	unsigned long armclk;
+	unsigned long hclk200;
+	unsigned long hclk166;
+	unsigned long hclk133;
+	unsigned long pclk100;
+	unsigned long pclk83;
+	unsigned long pclk66;
+	unsigned long apll;
+	unsigned long mpll;
+	unsigned long epll;
+	unsigned int ptr;
+	u32 clkdiv0, clkdiv1;
+
+	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
+
+	clkdiv0 = __raw_readl(S5P_CLK_DIV0);
+	clkdiv1 = __raw_readl(S5P_CLK_DIV1);
+
+	printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n",
+				__func__, clkdiv0, clkdiv1);
+
+	xtal_clk = clk_get(NULL, "xtal");
+	BUG_ON(IS_ERR(xtal_clk));
+
+	xtal = clk_get_rate(xtal_clk);
+	clk_put(xtal_clk);
+
+	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
+
+	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
+	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
+	epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500);
+
+	printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld",
+			apll, mpll, epll);
+
+	armclk = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_APLL);
+	if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX200_MASK)
+		hclk200 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200);
+	else
+		hclk200 = armclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200);
+
+	if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX166_MASK) {
+		hclk166 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M);
+		hclk166 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166);
+	} else
+		hclk166 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166);
+
+	if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX133_MASK) {
+		hclk133 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M);
+		hclk133 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133);
+	} else
+		hclk133 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133);
+
+	pclk100 = hclk200 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK100);
+	pclk83 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83);
+	pclk66 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66);
+
+	printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld, \
+			HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
+	       armclk, hclk200, hclk166, hclk133, pclk100, pclk83, pclk66);
+
+	clk_fout_apll.rate = apll;
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+
+	clk_f.rate = armclk;
+	clk_h.rate = hclk133;
+	clk_p.rate = pclk66;
+	clk_p66.rate = pclk66;
+	clk_p83.rate = pclk83;
+	clk_h133.rate = hclk133;
+	clk_h166.rate = hclk166;
+	clk_h200.rate = hclk200;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
+		s3c_set_clksrc(init_parents[ptr], true);
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+		s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+	&clk_mout_epll.clk,
+	&clk_mout_mpll.clk,
+};
+
+void __init s5pv210_register_clocks(void)
+{
+	struct clk *clkp;
+	int ret;
+	int ptr;
+
+	ret = s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+	if (ret > 0)
+		printk(KERN_ERR "Failed to register %u clocks\n", ret);
+
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+	ret = s3c24xx_register_clocks(sys_clks, ARRAY_SIZE(sys_clks));
+	if (ret > 0)
+		printk(KERN_ERR "Failed to register system clocks\n");
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+		(clkp->enable)(clkp, 0);
+	}
+
+	s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
new file mode 100644
index 0000000..0e0f8fd
--- /dev/null
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -0,0 +1,126 @@
+/* linux/arch/arm/mach-s5pv210/cpu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/proc-fns.h>
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/clock.h>
+#include <plat/s5pv210.h>
+
+/* Initial IO mappings */
+
+static struct map_desc s5pv210_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
+		.pfn		= __phys_to_pfn(S5PV210_PA_SYSTIMER),
+		.length		= SZ_1M,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC2,
+		.pfn		= __phys_to_pfn(S5PV210_PA_VIC2),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC3,
+		.pfn		= __phys_to_pfn(S5PV210_PA_VIC3),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_SROMC,
+		.pfn		= __phys_to_pfn(S5PV210_PA_SROMC),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}
+};
+
+static void s5pv210_idle(void)
+{
+	if (!need_resched())
+		cpu_do_idle();
+
+	local_irq_enable();
+}
+
+/* s5pv210_map_io
+ *
+ * register the standard cpu IO areas
+*/
+
+void __init s5pv210_map_io(void)
+{
+	iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
+}
+
+void __init s5pv210_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+	s3c24xx_register_baseclocks(xtal);
+	s5p_register_clocks(xtal);
+	s5pv210_register_clocks();
+	s5pv210_setup_clocks();
+}
+
+void __init s5pv210_init_irq(void)
+{
+	u32 vic[4];	/* S5PV210 supports 4 VIC */
+
+	/* All the VICs are fully populated. */
+	vic[0] = ~0;
+	vic[1] = ~0;
+	vic[2] = ~0;
+	vic[3] = ~0;
+
+	s5p_init_irq(vic, ARRAY_SIZE(vic));
+}
+
+static struct sysdev_class s5pv210_sysclass = {
+	.name	= "s5pv210-core",
+};
+
+static struct sys_device s5pv210_sysdev = {
+	.cls	= &s5pv210_sysclass,
+};
+
+static int __init s5pv210_core_init(void)
+{
+	return sysdev_class_register(&s5pv210_sysclass);
+}
+
+core_initcall(s5pv210_core_init);
+
+int __init s5pv210_init(void)
+{
+	printk(KERN_INFO "S5PV210: Initializing architecture\n");
+
+	/* set idle function */
+	pm_idle = s5pv210_idle;
+
+	return sysdev_register(&s5pv210_sysdev);
+}
diff --git a/arch/arm/mach-s5pv210/include/mach/debug-macro.S b/arch/arm/mach-s5pv210/include/mach/debug-macro.S
new file mode 100644
index 0000000..7872f5c
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/debug-macro.S
@@ -0,0 +1,42 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <mach/map.h>
+#include <plat/regs-serial.h>
+
+	/* note, for the boot process to work we have to keep the UART
+	 * virtual address aligned to an 1MiB boundary for the L1
+	 * mapping the head code makes. We keep the UART virtual address
+	 * aligned and add in the offset when we load the value here.
+	 */
+
+	.macro addruart, rx, tmp
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1
+		ldreq	\rx, = S3C_PA_UART
+		ldrne	\rx, = S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+		add	\rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART)
+#endif
+	.endm
+
+#define fifo_full fifo_full_s5pv210
+#define fifo_level fifo_level_s5pv210
+
+/* include the reset of the code which will do the work, we're only
+ * compiling for a single cpu processor type so the default of s3c2440
+ * will be fine with us.
+ */
+
+#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s5pv210/include/mach/entry-macro.S b/arch/arm/mach-s5pv210/include/mach/entry-macro.S
new file mode 100644
index 0000000..3aa41ac
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/entry-macro.S
@@ -0,0 +1,54 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/entry-macro.S
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Low-level IRQ helper macros for the Samsung S5PV210
+ *
+ * This program is free software; you can redistribute 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/hardware/vic.h>
+#include <mach/map.h>
+#include <plat/irqs.h>
+
+	.macro	disable_fiq
+	.endm
+
+	.macro	get_irqnr_preamble, base, tmp
+	ldr	\base, =VA_VIC0
+	.endm
+
+	.macro	arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+	@ check the vic0
+	mov	\irqnr, # S5P_IRQ_OFFSET + 31
+	ldr	\irqstat, [ \base, # VIC_IRQ_STATUS ]
+	teq	\irqstat, #0
+
+	@ otherwise try vic1
+	addeq	\tmp, \base, #(VA_VIC1 - VA_VIC0)
+	addeq	\irqnr, \irqnr, #32
+	ldreq	\irqstat, [ \tmp, # VIC_IRQ_STATUS ]
+	teqeq	\irqstat, #0
+
+	@ otherwise try vic2
+	addeq	\tmp, \base, #(VA_VIC2 - VA_VIC0)
+	addeq	\irqnr, \irqnr, #32
+	ldreq	\irqstat, [ \tmp, # VIC_IRQ_STATUS ]
+	teqeq	\irqstat, #0
+
+	@ otherwise try vic3
+	addeq	\tmp, \base, #(VA_VIC3 - VA_VIC0)
+	addeq	\irqnr, \irqnr, #32
+	ldreq	\irqstat, [ \tmp, # VIC_IRQ_STATUS ]
+	teqeq	\irqstat, #0
+
+	clzne	\irqstat, \irqstat
+	subne	\irqnr, \irqnr, \irqstat
+	.endm
diff --git a/arch/arm/mach-s5pv210/include/mach/gpio.h b/arch/arm/mach-s5pv210/include/mach/gpio.h
new file mode 100644
index 0000000..533b020
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/gpio.h
@@ -0,0 +1,129 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/gpio.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - GPIO lib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H __FILE__
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define gpio_to_irq	__gpio_to_irq
+
+/* GPIO bank sizes */
+#define S5PV210_GPIO_A0_NR	(8)
+#define S5PV210_GPIO_A1_NR	(4)
+#define S5PV210_GPIO_B_NR	(8)
+#define S5PV210_GPIO_C0_NR	(5)
+#define S5PV210_GPIO_C1_NR	(5)
+#define S5PV210_GPIO_D0_NR	(4)
+#define S5PV210_GPIO_D1_NR	(6)
+#define S5PV210_GPIO_E0_NR	(8)
+#define S5PV210_GPIO_E1_NR	(5)
+#define S5PV210_GPIO_F0_NR	(8)
+#define S5PV210_GPIO_F1_NR	(8)
+#define S5PV210_GPIO_F2_NR	(8)
+#define S5PV210_GPIO_F3_NR	(6)
+#define S5PV210_GPIO_G0_NR	(7)
+#define S5PV210_GPIO_G1_NR	(7)
+#define S5PV210_GPIO_G2_NR	(7)
+#define S5PV210_GPIO_G3_NR	(7)
+#define S5PV210_GPIO_H0_NR	(8)
+#define S5PV210_GPIO_H1_NR	(8)
+#define S5PV210_GPIO_H2_NR	(8)
+#define S5PV210_GPIO_H3_NR	(8)
+#define S5PV210_GPIO_I_NR	(7)
+#define S5PV210_GPIO_J0_NR	(8)
+#define S5PV210_GPIO_J1_NR	(6)
+#define S5PV210_GPIO_J2_NR	(8)
+#define S5PV210_GPIO_J3_NR	(8)
+#define S5PV210_GPIO_J4_NR	(5)
+
+/* GPIO bank numbers */
+
+/* CONFIG_S3C_GPIO_SPACE allows the user to select extra
+ * space for debugging purposes so that any accidental
+ * change from one gpio bank to another can be caught.
+*/
+
+#define S5PV210_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s5p_gpio_number {
+	S5PV210_GPIO_A0_START	= 0,
+	S5PV210_GPIO_A1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_A0),
+	S5PV210_GPIO_B_START 	= S5PV210_GPIO_NEXT(S5PV210_GPIO_A1),
+	S5PV210_GPIO_C0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_B),
+	S5PV210_GPIO_C1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_C0),
+	S5PV210_GPIO_D0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_C1),
+	S5PV210_GPIO_D1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_D0),
+	S5PV210_GPIO_E0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_D1),
+	S5PV210_GPIO_E1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_E0),
+	S5PV210_GPIO_F0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_E1),
+	S5PV210_GPIO_F1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_F0),
+	S5PV210_GPIO_F2_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_F1),
+	S5PV210_GPIO_F3_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_F2),
+	S5PV210_GPIO_G0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_F3),
+	S5PV210_GPIO_G1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_G0),
+	S5PV210_GPIO_G2_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_G1),
+	S5PV210_GPIO_G3_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_G2),
+	S5PV210_GPIO_H0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_G3),
+	S5PV210_GPIO_H1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_H0),
+	S5PV210_GPIO_H2_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_H1),
+	S5PV210_GPIO_H3_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_H2),
+	S5PV210_GPIO_I_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_H3),
+	S5PV210_GPIO_J0_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_I),
+	S5PV210_GPIO_J1_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J0),
+	S5PV210_GPIO_J2_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J1),
+	S5PV210_GPIO_J3_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J2),
+	S5PV210_GPIO_J4_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J3),
+};
+
+/* S5PV210 GPIO number definitions */
+#define S5PV210_GPA0(_nr)	(S5PV210_GPIO_A0_START + (_nr))
+#define S5PV210_GPA1(_nr)	(S5PV210_GPIO_A1_START + (_nr))
+#define S5PV210_GPB(_nr)	(S5PV210_GPIO_B_START + (_nr))
+#define S5PV210_GPC0(_nr)	(S5PV210_GPIO_C0_START + (_nr))
+#define S5PV210_GPC1(_nr)	(S5PV210_GPIO_C1_START + (_nr))
+#define S5PV210_GPD0(_nr)	(S5PV210_GPIO_D0_START + (_nr))
+#define S5PV210_GPD1(_nr)	(S5PV210_GPIO_D1_START + (_nr))
+#define S5PV210_GPE0(_nr)	(S5PV210_GPIO_E0_START + (_nr))
+#define S5PV210_GPE1(_nr)	(S5PV210_GPIO_E1_START + (_nr))
+#define S5PV210_GPF0(_nr)	(S5PV210_GPIO_F0_START + (_nr))
+#define S5PV210_GPF1(_nr)	(S5PV210_GPIO_F1_START + (_nr))
+#define S5PV210_GPF2(_nr)	(S5PV210_GPIO_F2_START + (_nr))
+#define S5PV210_GPF3(_nr)	(S5PV210_GPIO_F3_START + (_nr))
+#define S5PV210_GPG0(_nr)	(S5PV210_GPIO_G0_START + (_nr))
+#define S5PV210_GPG1(_nr)	(S5PV210_GPIO_G1_START + (_nr))
+#define S5PV210_GPG2(_nr)	(S5PV210_GPIO_G2_START + (_nr))
+#define S5PV210_GPG3(_nr)	(S5PV210_GPIO_G3_START + (_nr))
+#define S5PV210_GPH0(_nr)	(S5PV210_GPIO_H0_START + (_nr))
+#define S5PV210_GPH1(_nr)	(S5PV210_GPIO_H1_START + (_nr))
+#define S5PV210_GPH2(_nr)	(S5PV210_GPIO_H2_START + (_nr))
+#define S5PV210_GPH3(_nr)	(S5PV210_GPIO_H3_START + (_nr))
+#define S5PV210_GPI(_nr)	(S5PV210_GPIO_I_START + (_nr))
+#define S5PV210_GPJ0(_nr)	(S5PV210_GPIO_J0_START + (_nr))
+#define S5PV210_GPJ1(_nr)	(S5PV210_GPIO_J1_START + (_nr))
+#define S5PV210_GPJ2(_nr)	(S5PV210_GPIO_J2_START + (_nr))
+#define S5PV210_GPJ3(_nr)	(S5PV210_GPIO_J3_START + (_nr))
+#define S5PV210_GPJ4(_nr)	(S5PV210_GPIO_J4_START + (_nr))
+
+/* the end of the S5PV210 specific gpios */
+#define S5PV210_GPIO_END	(S5PV210_GPJ4(S5PV210_GPIO_J4_NR) + 1)
+#define S3C_GPIO_END		S5PV210_GPIO_END
+
+/* define the number of gpios we need to the one after the GPJ4() range */
+#define ARCH_NR_GPIOS		(S5PV210_GPJ4(S5PV210_GPIO_J4_NR) +	\
+				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/hardware.h b/arch/arm/mach-s5pv210/include/mach/hardware.h
new file mode 100644
index 0000000..fada7a3
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/hardware.h
@@ -0,0 +1,18 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/hardware.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - Hardware support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H __FILE__
+
+/* currently nothing here, placeholder */
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/io.h b/arch/arm/mach-s5pv210/include/mach/io.h
new file mode 100644
index 0000000..5ab9d56
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/io.h
@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/io.h
+ *
+ * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/io.h
+ *
+ * Default IO routines for S5PV210
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H __FILE__
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
new file mode 100644
index 0000000..62c5175
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -0,0 +1,146 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/irqs.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - IRQ definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H __FILE__
+
+#include <plat/irqs.h>
+
+/* VIC0: System, DMA, Timer */
+
+#define IRQ_EINT0		S5P_IRQ_VIC0(0)
+#define IRQ_EINT1		S5P_IRQ_VIC0(1)
+#define IRQ_EINT2		S5P_IRQ_VIC0(2)
+#define IRQ_EINT3		S5P_IRQ_VIC0(3)
+#define IRQ_EINT4		S5P_IRQ_VIC0(4)
+#define IRQ_EINT5		S5P_IRQ_VIC0(5)
+#define IRQ_EINT6		S5P_IRQ_VIC0(6)
+#define IRQ_EINT7		S5P_IRQ_VIC0(7)
+#define IRQ_EINT8		S5P_IRQ_VIC0(8)
+#define IRQ_EINT9		S5P_IRQ_VIC0(9)
+#define IRQ_EINT10		S5P_IRQ_VIC0(10)
+#define IRQ_EINT11		S5P_IRQ_VIC0(11)
+#define IRQ_EINT12		S5P_IRQ_VIC0(12)
+#define IRQ_EINT13		S5P_IRQ_VIC0(13)
+#define IRQ_EINT14		S5P_IRQ_VIC0(14)
+#define IRQ_EINT15		S5P_IRQ_VIC0(15)
+#define IRQ_EINT16_31		S5P_IRQ_VIC0(16)
+#define IRQ_BATF		S5P_IRQ_VIC0(17)
+#define IRQ_MDMA		S5P_IRQ_VIC0(18)
+#define IRQ_PDMA0		S5P_IRQ_VIC0(19)
+#define IRQ_PDMA1		S5P_IRQ_VIC0(20)
+#define IRQ_TIMER0_VIC		S5P_IRQ_VIC0(21)
+#define IRQ_TIMER1_VIC		S5P_IRQ_VIC0(22)
+#define IRQ_TIMER2_VIC		S5P_IRQ_VIC0(23)
+#define IRQ_TIMER3_VIC		S5P_IRQ_VIC0(24)
+#define IRQ_TIMER4_VIC		S5P_IRQ_VIC0(25)
+#define IRQ_SYSTIMER		S5P_IRQ_VIC0(26)
+#define IRQ_WDT			S5P_IRQ_VIC0(27)
+#define IRQ_RTC_ALARM		S5P_IRQ_VIC0(28)
+#define IRQ_RTC_TIC		S5P_IRQ_VIC0(29)
+#define IRQ_GPIOINT		S5P_IRQ_VIC0(30)
+#define IRQ_FIMC3		S5P_IRQ_VIC0(31)
+
+/* VIC1: ARM, Power, Memory, Connectivity, Storage */
+
+#define IRQ_CORTEX0		S5P_IRQ_VIC1(0)
+#define IRQ_CORTEX1		S5P_IRQ_VIC1(1)
+#define IRQ_CORTEX2		S5P_IRQ_VIC1(2)
+#define IRQ_CORTEX3		S5P_IRQ_VIC1(3)
+#define IRQ_CORTEX4		S5P_IRQ_VIC1(4)
+#define IRQ_IEMAPC		S5P_IRQ_VIC1(5)
+#define IRQ_IEMIEC		S5P_IRQ_VIC1(6)
+#define IRQ_ONENAND		S5P_IRQ_VIC1(7)
+#define IRQ_NFC			S5P_IRQ_VIC1(8)
+#define IRQ_CFC			S5P_IRQ_VIC1(9)
+#define IRQ_UART0		S5P_IRQ_VIC1(10)
+#define IRQ_UART1		S5P_IRQ_VIC1(11)
+#define IRQ_UART2		S5P_IRQ_VIC1(12)
+#define IRQ_UART3		S5P_IRQ_VIC1(13)
+#define IRQ_IIC			S5P_IRQ_VIC1(14)
+#define IRQ_SPI0		S5P_IRQ_VIC1(15)
+#define IRQ_SPI1		S5P_IRQ_VIC1(16)
+#define IRQ_SPI2		S5P_IRQ_VIC1(17)
+#define IRQ_IRDA		S5P_IRQ_VIC1(18)
+#define IRQ_CAN0		S5P_IRQ_VIC1(19)
+#define IRQ_CAN1		S5P_IRQ_VIC1(20)
+#define IRQ_HSIRX		S5P_IRQ_VIC1(21)
+#define IRQ_HSITX		S5P_IRQ_VIC1(22)
+#define IRQ_UHOST		S5P_IRQ_VIC1(23)
+#define IRQ_OTG			S5P_IRQ_VIC1(24)
+#define IRQ_MSM			S5P_IRQ_VIC1(25)
+#define IRQ_HSMMC0		S5P_IRQ_VIC1(26)
+#define IRQ_HSMMC1		S5P_IRQ_VIC1(27)
+#define IRQ_HSMMC2		S5P_IRQ_VIC1(28)
+#define IRQ_MIPICSI		S5P_IRQ_VIC1(29)
+#define IRQ_MIPIDSI		S5P_IRQ_VIC1(30)
+#define IRQ_ONENAND_AUDI	S5P_IRQ_VIC1(31)
+
+/* VIC2: Multimedia, Audio, Security */
+
+#define IRQ_LCD0		S5P_IRQ_VIC2(0)
+#define IRQ_LCD1		S5P_IRQ_VIC2(1)
+#define IRQ_LCD2		S5P_IRQ_VIC2(2)
+#define IRQ_LCD3		S5P_IRQ_VIC2(3)
+#define IRQ_ROTATOR		S5P_IRQ_VIC2(4)
+#define IRQ_FIMC0		S5P_IRQ_VIC2(5)
+#define IRQ_FIMC1		S5P_IRQ_VIC2(6)
+#define IRQ_FIMC2		S5P_IRQ_VIC2(7)
+#define IRQ_JPEG		S5P_IRQ_VIC2(8)
+#define IRQ_2D			S5P_IRQ_VIC2(9)
+#define IRQ_3D			S5P_IRQ_VIC2(10)
+#define IRQ_MIXER		S5P_IRQ_VIC2(11)
+#define IRQ_HDMI		S5P_IRQ_VIC2(12)
+#define IRQ_IIC1		S5P_IRQ_VIC2(13)
+#define IRQ_MFC			S5P_IRQ_VIC2(14)
+#define IRQ_TVENC		S5P_IRQ_VIC2(15)
+#define IRQ_I2S0		S5P_IRQ_VIC2(16)
+#define IRQ_I2S1		S5P_IRQ_VIC2(17)
+#define IRQ_I2S2		S5P_IRQ_VIC2(18)
+#define IRQ_AC97		S5P_IRQ_VIC2(19)
+#define IRQ_PCM0		S5P_IRQ_VIC2(20)
+#define IRQ_PCM1		S5P_IRQ_VIC2(21)
+#define IRQ_SPDIF		S5P_IRQ_VIC2(22)
+#define IRQ_ADC			S5P_IRQ_VIC2(23)
+#define IRQ_PENDN		S5P_IRQ_VIC2(24)
+#define IRQ_TC			IRQ_PENDN
+#define IRQ_KEYPAD		S5P_IRQ_VIC2(25)
+#define IRQ_CG			S5P_IRQ_VIC2(26)
+#define IRQ_SEC			S5P_IRQ_VIC2(27)
+#define IRQ_SECRX		S5P_IRQ_VIC2(28)
+#define IRQ_SECTX		S5P_IRQ_VIC2(29)
+#define IRQ_SDMIRQ		S5P_IRQ_VIC2(30)
+#define IRQ_SDMFIQ		S5P_IRQ_VIC2(31)
+
+/* VIC3: Etc */
+
+#define IRQ_IPC			S5P_IRQ_VIC3(0)
+#define IRQ_HOSTIF		S5P_IRQ_VIC3(1)
+#define IRQ_MMC3		S5P_IRQ_VIC3(2)
+#define IRQ_CEC			S5P_IRQ_VIC3(3)
+#define IRQ_TSI			S5P_IRQ_VIC3(4)
+#define IRQ_MDNIE0		S5P_IRQ_VIC3(5)
+#define IRQ_MDNIE1		S5P_IRQ_VIC3(6)
+#define IRQ_MDNIE2		S5P_IRQ_VIC3(7)
+#define IRQ_MDNIE3		S5P_IRQ_VIC3(8)
+#define IRQ_VIC_END		S5P_IRQ_VIC3(31)
+
+#define S5P_IRQ_EINT_BASE	(IRQ_VIC_END + 1)
+
+#define S5P_EINT(x)		((x) + S5P_IRQ_EINT_BASE)
+#define IRQ_EINT(x)		S5P_EINT(x)
+
+/* Set the default NR_IRQS */
+
+#define NR_IRQS 		(IRQ_EINT(31) + 1)
+
+#endif /* ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
new file mode 100644
index 0000000..c22694c
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -0,0 +1,65 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/map.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H __FILE__
+
+#include <plat/map-base.h>
+#include <plat/map-s5p.h>
+
+#define S5PV210_PA_CHIPID	(0xE0000000)
+#define S5P_PA_CHIPID		S5PV210_PA_CHIPID
+
+#define S5PV210_PA_SYSCON	(0xE0100000)
+#define S5P_PA_SYSCON		S5PV210_PA_SYSCON
+
+#define S5PV210_PA_GPIO		(0xE0200000)
+#define S5P_PA_GPIO		S5PV210_PA_GPIO
+
+#define S5PV210_PA_IIC0		(0xE1800000)
+
+#define S5PV210_PA_TIMER	(0xE2500000)
+#define S5P_PA_TIMER		S5PV210_PA_TIMER
+
+#define S5PV210_PA_SYSTIMER	(0xE2600000)
+
+#define S5PV210_PA_UART		(0xE2900000)
+
+#define S5P_PA_UART0		(S5PV210_PA_UART + 0x0)
+#define S5P_PA_UART1		(S5PV210_PA_UART + 0x400)
+#define S5P_PA_UART2		(S5PV210_PA_UART + 0x800)
+#define S5P_PA_UART3		(S5PV210_PA_UART + 0xC00)
+
+#define S5P_SZ_UART		SZ_256
+
+#define S5PV210_PA_SROMC	(0xE8000000)
+
+#define S5PV210_PA_VIC0		(0xF2000000)
+#define S5P_PA_VIC0		S5PV210_PA_VIC0
+
+#define S5PV210_PA_VIC1		(0xF2100000)
+#define S5P_PA_VIC1		S5PV210_PA_VIC1
+
+#define S5PV210_PA_VIC2		(0xF2200000)
+#define S5P_PA_VIC2		S5PV210_PA_VIC2
+
+#define S5PV210_PA_VIC3		(0xF2300000)
+#define S5P_PA_VIC3		S5PV210_PA_VIC3
+
+#define S5PV210_PA_SDRAM	(0x20000000)
+#define S5P_PA_SDRAM		S5PV210_PA_SDRAM
+
+/* compatibiltiy defines. */
+#define S3C_PA_UART		S5PV210_PA_UART
+#define S3C_PA_IIC		S5PV210_PA_IIC0
+
+#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/memory.h b/arch/arm/mach-s5pv210/include/mach/memory.h
new file mode 100644
index 0000000..379117e
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/memory.h
@@ -0,0 +1,23 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/memory.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - Memory definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PHYS_OFFSET		UL(0x20000000)
+#define CONSISTENT_DMA_SIZE	(SZ_8M + SZ_4M + SZ_2M)
+
+/* Maximum of 256MiB in one bank */
+#define MAX_PHYSMEM_BITS	32
+#define SECTION_SIZE_BITS	28
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/pwm-clock.h b/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
new file mode 100644
index 0000000..69027fe
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
@@ -0,0 +1,69 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
+ *
+ * S5PV210 - pwm clock and timer support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_PWMCLK_H
+#define __ASM_ARCH_PWMCLK_H __FILE__
+
+/**
+ * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
+ * @cfg: The timer TCFG1 register bits shifted down to 0.
+ *
+ * Return true if the given configuration from TCFG1 is a TCLK instead
+ * any of the TDIV clocks.
+ */
+static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
+{
+	return tcfg == S3C2410_TCFG1_MUX_TCLK;
+}
+
+/**
+ * tcfg_to_divisor() - convert tcfg1 setting to a divisor
+ * @tcfg1: The tcfg1 setting, shifted down.
+ *
+ * Get the divisor value for the given tcfg1 setting. We assume the
+ * caller has already checked to see if this is not a TCLK source.
+ */
+static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
+{
+	return 1 << (1 + tcfg1);
+}
+
+/**
+ * pwm_tdiv_has_div1() - does the tdiv setting have a /1
+ *
+ * Return true if we have a /1 in the tdiv setting.
+ */
+static inline unsigned int pwm_tdiv_has_div1(void)
+{
+	return 0;
+}
+
+/**
+ * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
+ * @div: The divisor to calculate the bit information for.
+ *
+ * Turn a divisor into the necessary bit field for TCFG1.
+ */
+static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
+{
+	return ilog2(div) - 1;
+}
+
+#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
+
+#endif /* __ASM_ARCH_PWMCLK_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
new file mode 100644
index 0000000..e56e0e4
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
@@ -0,0 +1,169 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - Clock register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_CLKREG(x)		(S3C_VA_SYS + (x))
+
+#define S5P_APLL_LOCK		S5P_CLKREG(0x00)
+#define S5P_MPLL_LOCK		S5P_CLKREG(0x08)
+#define S5P_EPLL_LOCK		S5P_CLKREG(0x10)
+#define S5P_VPLL_LOCK		S5P_CLKREG(0x20)
+
+#define S5P_APLL_CON		S5P_CLKREG(0x100)
+#define S5P_MPLL_CON		S5P_CLKREG(0x108)
+#define S5P_EPLL_CON		S5P_CLKREG(0x110)
+#define S5P_VPLL_CON		S5P_CLKREG(0x120)
+
+#define S5P_CLK_SRC0		S5P_CLKREG(0x200)
+#define S5P_CLK_SRC1		S5P_CLKREG(0x204)
+#define S5P_CLK_SRC2		S5P_CLKREG(0x208)
+#define S5P_CLK_SRC3		S5P_CLKREG(0x20C)
+#define S5P_CLK_SRC4		S5P_CLKREG(0x210)
+#define S5P_CLK_SRC5		S5P_CLKREG(0x214)
+#define S5P_CLK_SRC6		S5P_CLKREG(0x218)
+
+#define S5P_CLK_SRC_MASK0	S5P_CLKREG(0x280)
+#define S5P_CLK_SRC_MASK1	S5P_CLKREG(0x284)
+
+#define S5P_CLK_DIV0		S5P_CLKREG(0x300)
+#define S5P_CLK_DIV1		S5P_CLKREG(0x304)
+#define S5P_CLK_DIV2		S5P_CLKREG(0x308)
+#define S5P_CLK_DIV3		S5P_CLKREG(0x30C)
+#define S5P_CLK_DIV4		S5P_CLKREG(0x310)
+#define S5P_CLK_DIV5		S5P_CLKREG(0x314)
+#define S5P_CLK_DIV6		S5P_CLKREG(0x318)
+#define S5P_CLK_DIV7		S5P_CLKREG(0x31C)
+
+#define S5P_CLKGATE_MAIN0	S5P_CLKREG(0x400)
+#define S5P_CLKGATE_MAIN1	S5P_CLKREG(0x404)
+#define S5P_CLKGATE_MAIN2	S5P_CLKREG(0x408)
+
+#define S5P_CLKGATE_PERI0	S5P_CLKREG(0x420)
+#define S5P_CLKGATE_PERI1	S5P_CLKREG(0x424)
+
+#define S5P_CLKGATE_SCLK0	S5P_CLKREG(0x440)
+#define S5P_CLKGATE_SCLK1	S5P_CLKREG(0x444)
+#define S5P_CLKGATE_IP0		S5P_CLKREG(0x460)
+#define S5P_CLKGATE_IP1		S5P_CLKREG(0x464)
+#define S5P_CLKGATE_IP2		S5P_CLKREG(0x468)
+#define S5P_CLKGATE_IP3		S5P_CLKREG(0x46C)
+#define S5P_CLKGATE_IP4		S5P_CLKREG(0x470)
+
+#define S5P_CLKGATE_BLOCK	S5P_CLKREG(0x480)
+#define S5P_CLKGATE_BUS0	S5P_CLKREG(0x484)
+#define S5P_CLKGATE_BUS1	S5P_CLKREG(0x488)
+#define S5P_CLK_OUT		S5P_CLKREG(0x500)
+
+/* CLKSRC0 */
+#define S5P_CLKSRC0_MUX200_MASK		(0x1<<16)
+#define S5P_CLKSRC0_MUX166_MASK		(0x1<<20)
+#define S5P_CLKSRC0_MUX133_MASK		(0x1<<24)
+
+/* CLKDIV0 */
+#define S5P_CLKDIV0_APLL_SHIFT		(0)
+#define S5P_CLKDIV0_APLL_MASK		(0x7 << S5P_CLKDIV0_APLL_SHIFT)
+#define S5P_CLKDIV0_A2M_SHIFT		(4)
+#define S5P_CLKDIV0_A2M_MASK		(0x7 << S5P_CLKDIV0_A2M_SHIFT)
+#define S5P_CLKDIV0_HCLK200_SHIFT	(8)
+#define S5P_CLKDIV0_HCLK200_MASK	(0x7 << S5P_CLKDIV0_HCLK200_SHIFT)
+#define S5P_CLKDIV0_PCLK100_SHIFT	(12)
+#define S5P_CLKDIV0_PCLK100_MASK	(0x7 << S5P_CLKDIV0_PCLK100_SHIFT)
+#define S5P_CLKDIV0_HCLK166_SHIFT	(16)
+#define S5P_CLKDIV0_HCLK166_MASK	(0xF << S5P_CLKDIV0_HCLK166_SHIFT)
+#define S5P_CLKDIV0_PCLK83_SHIFT	(20)
+#define S5P_CLKDIV0_PCLK83_MASK		(0x7 << S5P_CLKDIV0_PCLK83_SHIFT)
+#define S5P_CLKDIV0_HCLK133_SHIFT	(24)
+#define S5P_CLKDIV0_HCLK133_MASK	(0xF << S5P_CLKDIV0_HCLK133_SHIFT)
+#define S5P_CLKDIV0_PCLK66_SHIFT	(28)
+#define S5P_CLKDIV0_PCLK66_MASK		(0x7 << S5P_CLKDIV0_PCLK66_SHIFT)
+
+/* Registers related to power management */
+#define S5P_PWR_CFG		S5P_CLKREG(0xC000)
+#define S5P_EINT_WAKEUP_MASK	S5P_CLKREG(0xC004)
+#define S5P_WAKEUP_MASK 	S5P_CLKREG(0xC008)
+#define S5P_PWR_MODE		S5P_CLKREG(0xC00C)
+#define S5P_NORMAL_CFG		S5P_CLKREG(0xC010)
+#define S5P_IDLE_CFG		S5P_CLKREG(0xC020)
+#define S5P_STOP_CFG		S5P_CLKREG(0xC030)
+#define S5P_STOP_MEM_CFG	S5P_CLKREG(0xC034)
+#define S5P_SLEEP_CFG		S5P_CLKREG(0xC040)
+
+#define S5P_OSC_FREQ		S5P_CLKREG(0xC100)
+#define S5P_OSC_STABLE		S5P_CLKREG(0xC104)
+#define S5P_PWR_STABLE		S5P_CLKREG(0xC108)
+#define S5P_MTC_STABLE		S5P_CLKREG(0xC110)
+#define S5P_CLAMP_STABLE	S5P_CLKREG(0xC114)
+
+#define S5P_WAKEUP_STAT		S5P_CLKREG(0xC200)
+#define S5P_BLK_PWR_STAT	S5P_CLKREG(0xC204)
+
+#define S5P_OTHERS		S5P_CLKREG(0xE000)
+#define S5P_OM_STAT		S5P_CLKREG(0xE100)
+#define S5P_USB_PHY_CONTROL	S5P_CLKREG(0xE80C)
+#define S5P_DAC_CONTROL		S5P_CLKREG(0xE810)
+
+#define S5P_INFORM0		S5P_CLKREG(0xF000)
+#define S5P_INFORM1		S5P_CLKREG(0xF004)
+#define S5P_INFORM2		S5P_CLKREG(0xF008)
+#define S5P_INFORM3		S5P_CLKREG(0xF00C)
+#define S5P_INFORM4		S5P_CLKREG(0xF010)
+#define S5P_INFORM5		S5P_CLKREG(0xF014)
+#define S5P_INFORM6		S5P_CLKREG(0xF018)
+#define S5P_INFORM7		S5P_CLKREG(0xF01C)
+
+#define S5P_RST_STAT		S5P_CLKREG(0xA000)
+#define S5P_OSC_CON		S5P_CLKREG(0x8000)
+#define S5P_MIPI_PHY_CON0	S5P_CLKREG(0x7200)
+#define S5P_MIPI_PHY_CON1	S5P_CLKREG(0x7204)
+#define S5P_MIPI_CONTROL	S5P_CLKREG(0xE814)
+
+#define S5P_IDLE_CFG_TL_MASK	(3 << 30)
+#define S5P_IDLE_CFG_TM_MASK	(3 << 28)
+#define S5P_IDLE_CFG_TL_ON	(2 << 30)
+#define S5P_IDLE_CFG_TM_ON	(2 << 28)
+#define S5P_IDLE_CFG_DIDLE	(1 << 0)
+
+#define S5P_CFG_WFI_CLEAN		(~(3 << 8))
+#define S5P_CFG_WFI_IDLE		(1 << 8)
+#define S5P_CFG_WFI_STOP		(2 << 8)
+#define S5P_CFG_WFI_SLEEP		(3 << 8)
+
+#define S5P_OTHER_SYS_INT		24
+#define S5P_OTHER_STA_TYPE		23
+#define S5P_OTHER_SYSC_INTOFF		(1 << 0)
+#define STA_TYPE_EXPON			0
+#define STA_TYPE_SFR			1
+
+#define S5P_PWR_STA_EXP_SCALE		0
+#define S5P_PWR_STA_CNT			4
+
+#define S5P_PWR_STABLE_COUNT		85500
+
+#define S5P_SLEEP_CFG_OSC_EN		(1 << 0)
+#define S5P_SLEEP_CFG_USBOSC_EN		(1 << 1)
+
+/* OTHERS Resgister */
+#define S5P_OTHERS_USB_SIG_MASK		(1 << 16)
+#define S5P_OTHERS_MIPI_DPHY_EN		(1 << 28)
+
+/* MIPI */
+#define S5P_MIPI_DPHY_EN		(3)
+
+/* S5P_DAC_CONTROL */
+#define S5P_DAC_ENABLE			(1)
+#define S5P_DAC_DISABLE			(0)
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-irq.h b/arch/arm/mach-s5pv210/include/mach/regs-irq.h
new file mode 100644
index 0000000..5c3b104
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/regs-irq.h
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/regs-irq.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - IRQ register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_IRQ_H
+#define __ASM_ARCH_REGS_IRQ_H __FILE__
+
+#include <asm/hardware/vic.h>
+#include <mach/map.h>
+
+#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/system.h b/arch/arm/mach-s5pv210/include/mach/system.h
new file mode 100644
index 0000000..1ca04d5
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/system.h
@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/system.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - system support header
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H __FILE__
+
+static void arch_idle(void)
+{
+	/* nothing here yet */
+}
+
+static void arch_reset(char mode, const char *cmd)
+{
+	/* nothing here yet */
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/tick.h b/arch/arm/mach-s5pv210/include/mach/tick.h
new file mode 100644
index 0000000..7993b36
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/tick.h
@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/tick.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/mach-s3c6400/include/mach/tick.h
+ *
+ * S5PV210 - Timer tick support definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TICK_H
+#define __ASM_ARCH_TICK_H __FILE__
+
+static inline u32 s3c24xx_ostimer_pending(void)
+{
+	u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
+	return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));
+}
+
+#define TICK_MAX	(0xffffffff)
+
+#endif /* __ASM_ARCH_TICK_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/timex.h b/arch/arm/mach-s5pv210/include/mach/timex.h
new file mode 100644
index 0000000..73dc854
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/timex.h
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/timex.h
+ *
+ * Copyright (c) 2003-2010 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/timex.h
+ *
+ * S5PV210 - time parameters
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H __FILE__
+
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
+
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/uncompress.h b/arch/arm/mach-s5pv210/include/mach/uncompress.h
new file mode 100644
index 0000000..08ff2fd
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/uncompress.h
@@ -0,0 +1,24 @@
+/* linux/arch/arm/mach-s5pv210/include/mach/uncompress.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - uncompress code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <mach/map.h>
+#include <plat/uncompress.h>
+
+static void arch_detect_cpu(void)
+{
+	/* we do not need to do any cpu detection here at the moment. */
+}
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/vmalloc.h b/arch/arm/mach-s5pv210/include/mach/vmalloc.h
new file mode 100644
index 0000000..58f515e
--- /dev/null
+++ b/arch/arm/mach-s5pv210/include/mach/vmalloc.h
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-s5p6442/include/mach/vmalloc.h
+ *
+ * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/vmalloc.h
+ *
+ * S5PV210 vmalloc definition
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H __FILE__
+
+#define VMALLOC_END	  (0xE0000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5pv210/init.c b/arch/arm/mach-s5pv210/init.c
new file mode 100644
index 0000000..4865ae2
--- /dev/null
+++ b/arch/arm/mach-s5pv210/init.c
@@ -0,0 +1,44 @@
+/* linux/arch/arm/mach-s5pv210/init.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/s5pv210.h>
+#include <plat/regs-serial.h>
+
+static struct s3c24xx_uart_clksrc s5pv210_serial_clocks[] = {
+	[0] = {
+		.name		= "pclk",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+};
+
+/* uart registration process */
+void __init s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	struct s3c2410_uartcfg *tcfg = cfg;
+	u32 ucnt;
+
+	for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
+		if (!tcfg->clocks) {
+			tcfg->clocks = s5pv210_serial_clocks;
+			tcfg->clocks_size = ARRAY_SIZE(s5pv210_serial_clocks);
+		}
+	}
+
+	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
+}
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
new file mode 100644
index 0000000..ab4869d
--- /dev/null
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -0,0 +1,98 @@
+/* linux/arch/arm/mach-s5pv210/mach-smdkc110.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/regs-serial.h>
+#include <plat/s5pv210.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define S5PV210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define S5PV210_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define S5PV210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= S5PV210_UCON_DEFAULT,
+		.ulcon		= S5PV210_ULCON_DEFAULT,
+		.ufcon		= S5PV210_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= S5PV210_UCON_DEFAULT,
+		.ulcon		= S5PV210_ULCON_DEFAULT,
+		.ufcon		= S5PV210_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= S5PV210_UCON_DEFAULT,
+		.ulcon		= S5PV210_ULCON_DEFAULT,
+		.ufcon		= S5PV210_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= S5PV210_UCON_DEFAULT,
+		.ulcon		= S5PV210_ULCON_DEFAULT,
+		.ufcon		= S5PV210_UFCON_DEFAULT,
+	},
+};
+
+static struct platform_device *smdkc110_devices[] __initdata = {
+};
+
+static void __init smdkc110_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
+}
+
+static void __init smdkc110_machine_init(void)
+{
+	platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices));
+}
+
+MACHINE_START(SMDKC110, "SMDKC110")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= s5pv210_init_irq,
+	.map_io		= smdkc110_map_io,
+	.init_machine	= smdkc110_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
new file mode 100644
index 0000000..a278832
--- /dev/null
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -0,0 +1,98 @@
+/* linux/arch/arm/mach-s5pv210/mach-smdkv210.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include <plat/regs-serial.h>
+#include <plat/s5pv210.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define S5PV210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define S5PV210_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define S5PV210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= S5PV210_UCON_DEFAULT,
+		.ulcon		= S5PV210_ULCON_DEFAULT,
+		.ufcon		= S5PV210_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= S5PV210_UCON_DEFAULT,
+		.ulcon		= S5PV210_ULCON_DEFAULT,
+		.ufcon		= S5PV210_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= S5PV210_UCON_DEFAULT,
+		.ulcon		= S5PV210_ULCON_DEFAULT,
+		.ufcon		= S5PV210_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= S5PV210_UCON_DEFAULT,
+		.ulcon		= S5PV210_ULCON_DEFAULT,
+		.ufcon		= S5PV210_UFCON_DEFAULT,
+	},
+};
+
+static struct platform_device *smdkv210_devices[] __initdata = {
+};
+
+static void __init smdkv210_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
+}
+
+static void __init smdkv210_machine_init(void)
+{
+	platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));
+}
+
+MACHINE_START(SMDKV210, "SMDKV210")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.phys_io	= S3C_PA_UART & 0xfff00000,
+	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= s5pv210_init_irq,
+	.map_io		= smdkv210_map_io,
+	.init_machine	= smdkv210_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index 051ec0f..259cb2c 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -51,6 +51,10 @@
 	},
 };
 
+static struct sa1111_platform_data sa1111_info = {
+	.irq_base	= IRQ_BOARD_END,
+};
+
 static u64 sa1111_dmamask = 0xffffffffUL;
 
 static struct platform_device sa1111_device = {
@@ -59,6 +63,7 @@
 	.dev		= {
 		.dma_mask = &sa1111_dmamask,
 		.coherent_dma_mask = 0xffffffff,
+		.platform_data = &sa1111_info,
 	},
 	.num_resources	= ARRAY_SIZE(sa1111_resources),
 	.resource	= sa1111_resources,
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 9982c5c..5d5f330 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -234,6 +234,10 @@
 	},
 };
 
+static struct locomo_platform_data locomo_info = {
+	.irq_base	= IRQ_BOARD_START,
+};
+
 struct platform_device collie_locomo_device = {
 	.name		= "locomo",
 	.id		= 0,
diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h
index 71a0b3f..52acda7 100644
--- a/arch/arm/mach-sa1100/include/mach/collie.h
+++ b/arch/arm/mach-sa1100/include/mach/collie.h
@@ -72,13 +72,6 @@
 #define COLLIE_IRQ_GPIO_GA_INT		IRQ_GPIO25
 #define COLLIE_IRQ_GPIO_MAIN_BAT_LOW	IRQ_GPIO26
 
-#define COLLIE_LCM_IRQ_GPIO_RTS		IRQ_LOCOMO_GPIO0
-#define COLLIE_LCM_IRQ_GPIO_CTS		IRQ_LOCOMO_GPIO1
-#define COLLIE_LCM_IRQ_GPIO_DSR		IRQ_LOCOMO_GPIO2
-#define COLLIE_LCM_IRQ_GPIO_DTR		IRQ_LOCOMO_GPIO3
-#define COLLIE_LCM_IRQ_GPIO_nSD_DETECT	IRQ_LOCOMO_GPIO13
-#define COLLIE_LCM_IRQ_GPIO_nSD_WP	IRQ_LOCOMO_GPIO14
-
 /* GPIO's on the TC35143AF (Toshiba Analog Frontend) */
 #define COLLIE_TC35143_GPIO_BASE	(GPIO_MAX + 13)
 #define COLLIE_TC35143_GPIO_VERSION0    UCB_IO_0
diff --git a/arch/arm/mach-sa1100/include/mach/irqs.h b/arch/arm/mach-sa1100/include/mach/irqs.h
index ae81f80..8c8845b 100644
--- a/arch/arm/mach-sa1100/include/mach/irqs.h
+++ b/arch/arm/mach-sa1100/include/mach/irqs.h
@@ -68,93 +68,17 @@
 #define IRQ_BOARD_START		49
 #define IRQ_BOARD_END		65
 
-#define IRQ_SA1111_START	(IRQ_BOARD_END)
-#define IRQ_GPAIN0		(IRQ_BOARD_END + 0)
-#define IRQ_GPAIN1		(IRQ_BOARD_END + 1)
-#define IRQ_GPAIN2		(IRQ_BOARD_END + 2)
-#define IRQ_GPAIN3		(IRQ_BOARD_END + 3)
-#define IRQ_GPBIN0		(IRQ_BOARD_END + 4)
-#define IRQ_GPBIN1		(IRQ_BOARD_END + 5)
-#define IRQ_GPBIN2		(IRQ_BOARD_END + 6)
-#define IRQ_GPBIN3		(IRQ_BOARD_END + 7)
-#define IRQ_GPBIN4		(IRQ_BOARD_END + 8)
-#define IRQ_GPBIN5		(IRQ_BOARD_END + 9)
-#define IRQ_GPCIN0		(IRQ_BOARD_END + 10)
-#define IRQ_GPCIN1		(IRQ_BOARD_END + 11)
-#define IRQ_GPCIN2		(IRQ_BOARD_END + 12)
-#define IRQ_GPCIN3		(IRQ_BOARD_END + 13)
-#define IRQ_GPCIN4		(IRQ_BOARD_END + 14)
-#define IRQ_GPCIN5		(IRQ_BOARD_END + 15)
-#define IRQ_GPCIN6		(IRQ_BOARD_END + 16)
-#define IRQ_GPCIN7		(IRQ_BOARD_END + 17)
-#define IRQ_MSTXINT		(IRQ_BOARD_END + 18)
-#define IRQ_MSRXINT		(IRQ_BOARD_END + 19)
-#define IRQ_MSSTOPERRINT	(IRQ_BOARD_END + 20)
-#define IRQ_TPTXINT		(IRQ_BOARD_END + 21)
-#define IRQ_TPRXINT		(IRQ_BOARD_END + 22)
-#define IRQ_TPSTOPERRINT	(IRQ_BOARD_END + 23)
-#define SSPXMTINT		(IRQ_BOARD_END + 24)
-#define SSPRCVINT		(IRQ_BOARD_END + 25)
-#define SSPROR			(IRQ_BOARD_END + 26)
-#define AUDXMTDMADONEA		(IRQ_BOARD_END + 32)
-#define AUDRCVDMADONEA		(IRQ_BOARD_END + 33)
-#define AUDXMTDMADONEB		(IRQ_BOARD_END + 34)
-#define AUDRCVDMADONEB		(IRQ_BOARD_END + 35)
-#define AUDTFSR			(IRQ_BOARD_END + 36)
-#define AUDRFSR			(IRQ_BOARD_END + 37)
-#define AUDTUR			(IRQ_BOARD_END + 38)
-#define AUDROR			(IRQ_BOARD_END + 39)
-#define AUDDTS			(IRQ_BOARD_END + 40)
-#define AUDRDD			(IRQ_BOARD_END + 41)
-#define AUDSTO			(IRQ_BOARD_END + 42)
-#define IRQ_USBPWR		(IRQ_BOARD_END + 43)
-#define IRQ_HCIM		(IRQ_BOARD_END + 44)
-#define IRQ_HCIBUFFACC		(IRQ_BOARD_END + 45)
-#define IRQ_HCIRMTWKP		(IRQ_BOARD_END + 46)
-#define IRQ_NHCIMFCIR		(IRQ_BOARD_END + 47)
-#define IRQ_USB_PORT_RESUME	(IRQ_BOARD_END + 48)
-#define IRQ_S0_READY_NINT	(IRQ_BOARD_END + 49)
-#define IRQ_S1_READY_NINT	(IRQ_BOARD_END + 50)
-#define IRQ_S0_CD_VALID		(IRQ_BOARD_END + 51)
-#define IRQ_S1_CD_VALID		(IRQ_BOARD_END + 52)
-#define IRQ_S0_BVD1_STSCHG	(IRQ_BOARD_END + 53)
-#define IRQ_S1_BVD1_STSCHG	(IRQ_BOARD_END + 54)
-
-#define IRQ_LOCOMO_START	(IRQ_BOARD_END)
-#define IRQ_LOCOMO_KEY		(IRQ_BOARD_END + 0)
-#define IRQ_LOCOMO_GPIO0	(IRQ_BOARD_END + 1)
-#define IRQ_LOCOMO_GPIO1	(IRQ_BOARD_END + 2)
-#define IRQ_LOCOMO_GPIO2	(IRQ_BOARD_END + 3)
-#define IRQ_LOCOMO_GPIO3	(IRQ_BOARD_END + 4)
-#define IRQ_LOCOMO_GPIO4	(IRQ_BOARD_END + 5)
-#define IRQ_LOCOMO_GPIO5	(IRQ_BOARD_END + 6)
-#define IRQ_LOCOMO_GPIO6	(IRQ_BOARD_END + 7)
-#define IRQ_LOCOMO_GPIO7	(IRQ_BOARD_END + 8)
-#define IRQ_LOCOMO_GPIO8	(IRQ_BOARD_END + 9)
-#define IRQ_LOCOMO_GPIO9	(IRQ_BOARD_END + 10)
-#define IRQ_LOCOMO_GPIO10	(IRQ_BOARD_END + 11)
-#define IRQ_LOCOMO_GPIO11	(IRQ_BOARD_END + 12)
-#define IRQ_LOCOMO_GPIO12	(IRQ_BOARD_END + 13)
-#define IRQ_LOCOMO_GPIO13	(IRQ_BOARD_END + 14)
-#define IRQ_LOCOMO_GPIO14	(IRQ_BOARD_END + 15)
-#define IRQ_LOCOMO_GPIO15	(IRQ_BOARD_END + 16)
-#define IRQ_LOCOMO_LT		(IRQ_BOARD_END + 17)
-#define IRQ_LOCOMO_SPI_RFR	(IRQ_BOARD_END + 18)
-#define IRQ_LOCOMO_SPI_RFW	(IRQ_BOARD_END + 19)
-#define IRQ_LOCOMO_SPI_REND	(IRQ_BOARD_END + 20)
-#define IRQ_LOCOMO_SPI_TEND	(IRQ_BOARD_END + 21)
-
 /*
  * Figure out the MAX IRQ number.
  *
  * If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1.
- * If we have an LoCoMo, the max IRQ is IRQ_LOCOMO_SPI_TEND+1
+ * If we have an LoCoMo, the max IRQ is IRQ_BOARD_START + 4
  * Otherwise, we have the standard IRQs only.
  */
 #ifdef CONFIG_SA1111
-#define NR_IRQS			(IRQ_S1_BVD1_STSCHG + 1)
-#elif defined(CONFIG_SHARP_LOCOMO)
-#define NR_IRQS			(IRQ_LOCOMO_SPI_TEND + 1)
+#define NR_IRQS			(IRQ_BOARD_END + 55)
+#elif defined(CONFIG_SHARPSL_LOCOMO)
+#define NR_IRQS			(IRQ_BOARD_START + 4)
 #else
 #define NR_IRQS			(IRQ_BOARD_START)
 #endif
@@ -166,10 +90,3 @@
 #define IRQ_NEPONSET_SMC9196	(IRQ_BOARD_START + 0)
 #define IRQ_NEPONSET_USAR	(IRQ_BOARD_START + 1)
 #define IRQ_NEPONSET_SA1111	(IRQ_BOARD_START + 2)
-
-/* LoCoMo Interrupts (CONFIG_SHARP_LOCOMO) */
-#define IRQ_LOCOMO_KEY_BASE	(IRQ_BOARD_START + 0)
-#define IRQ_LOCOMO_GPIO_BASE	(IRQ_BOARD_START + 1)
-#define IRQ_LOCOMO_LT_BASE	(IRQ_BOARD_START + 2)
-#define IRQ_LOCOMO_SPI_BASE	(IRQ_BOARD_START + 3)
-
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 13ebd2d..d3ec620 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -208,6 +208,10 @@
 	},
 };
 
+static struct sa1111_platform_data sa1111_info = {
+	.irq_base	= IRQ_BOARD_END,
+};
+
 static u64 sa1111_dmamask = 0xffffffffUL;
 
 static struct platform_device sa1111_device = {
@@ -216,6 +220,7 @@
 	.dev		= {
 		.dma_mask = &sa1111_dmamask,
 		.coherent_dma_mask = 0xffffffff,
+		.platform_data = &sa1111_info,
 	},
 	.num_resources	= ARRAY_SIZE(sa1111_resources),
 	.resource	= sa1111_resources,
diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c
index 506a5e5..9b6dee5d 100644
--- a/arch/arm/mach-sa1100/jornada720_ssp.c
+++ b/arch/arm/mach-sa1100/jornada720_ssp.c
@@ -130,7 +130,7 @@
 };
 EXPORT_SYMBOL(jornada_ssp_end);
 
-static int __init jornada_ssp_probe(struct platform_device *dev)
+static int __devinit jornada_ssp_probe(struct platform_device *dev)
 {
 	int ret;
 
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index 6ccd175..0b505d9 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -241,6 +241,10 @@
 	},
 };
 
+static struct sa1111_platform_data sa1111_info = {
+	.irq_base	= IRQ_BOARD_END,
+};
+
 static u64 sa1111_dmamask = 0xffffffffUL;
 
 static struct platform_device sa1111_device = {
@@ -249,6 +253,7 @@
 	.dev		= {
 		.dma_mask = &sa1111_dmamask,
 		.coherent_dma_mask = 0xffffffff,
+		.platform_data = &sa1111_info,
 	},
 	.num_resources	= ARRAY_SIZE(sa1111_resources),
 	.resource	= sa1111_resources,
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index b9cbb56..74b6e0e 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -35,14 +35,12 @@
 static int
 sa1100_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c)
 {
-	unsigned long flags, next, oscr;
+	unsigned long next, oscr;
 
-	raw_local_irq_save(flags);
 	OIER |= OIER_E0;
 	next = OSCR + delta;
 	OSMR0 = next;
 	oscr = OSCR;
-	raw_local_irq_restore(flags);
 
 	return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
 }
@@ -50,16 +48,12 @@
 static void
 sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
 {
-	unsigned long flags;
-
 	switch (mode) {
 	case CLOCK_EVT_MODE_ONESHOT:
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
-		raw_local_irq_save(flags);
 		OIER &= ~OIER_E0;
 		OSSR = OSSR_M0;
-		raw_local_irq_restore(flags);
 		break;
 
 	case CLOCK_EVT_MODE_RESUME:
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
new file mode 100644
index 0000000..aeceb9b
--- /dev/null
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -0,0 +1,84 @@
+if ARCH_SHMOBILE
+
+comment "SH-Mobile System Type"
+
+config ARCH_SH7367
+	bool "SH-Mobile G3 (SH7367)"
+	select CPU_V6
+	select HAVE_CLK
+	select COMMON_CLKDEV
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+
+config ARCH_SH7377
+	bool "SH-Mobile G4 (SH7377)"
+	select CPU_V7
+	select HAVE_CLK
+	select COMMON_CLKDEV
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+
+config ARCH_SH7372
+	bool "SH-Mobile AP4 (SH7372)"
+	select CPU_V7
+	select HAVE_CLK
+	select COMMON_CLKDEV
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+
+comment "SH-Mobile Board Type"
+
+config MACH_G3EVM
+	bool "G3EVM board"
+	depends on ARCH_SH7367
+	select ARCH_REQUIRE_GPIOLIB
+
+config MACH_G4EVM
+	bool "G4EVM board"
+	depends on ARCH_SH7377
+	select ARCH_REQUIRE_GPIOLIB
+
+config MACH_AP4EVB
+	bool "AP4EVB board"
+	depends on ARCH_SH7372
+	select ARCH_REQUIRE_GPIOLIB
+
+comment "SH-Mobile System Configuration"
+
+menu "Memory configuration"
+
+config MEMORY_START
+	hex "Physical memory start address"
+	default "0x50000000" if MACH_G3EVM
+	default "0x40000000" if MACH_G4EVM
+	default "0x40000000" if MACH_AP4EVB
+	default "0x00000000"
+	---help---
+	  Tweak this only when porting to a new machine which does not
+	  already have a defconfig. Changing it from the known correct
+	  value on any of the known systems will only lead to disaster.
+
+config MEMORY_SIZE
+	hex "Physical memory size"
+	default "0x08000000" if MACH_G3EVM
+	default "0x08000000" if MACH_G4EVM
+	default "0x10000000" if MACH_AP4EVB
+	default "0x04000000"
+	help
+	  This sets the default memory size assumed by your kernel. It can
+	  be overridden as normal by the 'mem=' argument on the kernel command
+	  line.
+
+endmenu
+
+menu "Timer and clock configuration"
+
+config SH_TIMER_CMT
+	bool "CMT timer driver"
+	default y
+	help
+	  This enables build of the CMT timer driver.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
new file mode 100644
index 0000000..6d385d3
--- /dev/null
+++ b/arch/arm/mach-shmobile/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common objects
+obj-y				:= timer.o console.o
+
+# CPU objects
+obj-$(CONFIG_ARCH_SH7367)	+= setup-sh7367.o clock-sh7367.o intc-sh7367.o
+obj-$(CONFIG_ARCH_SH7377)	+= setup-sh7377.o clock-sh7367.o intc-sh7377.o
+obj-$(CONFIG_ARCH_SH7372)	+= setup-sh7372.o clock-sh7367.o intc-sh7372.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)
+
+# Board objects
+obj-$(CONFIG_MACH_G3EVM)	+= board-g3evm.o
+obj-$(CONFIG_MACH_G4EVM)	+= board-g4evm.o
+obj-$(CONFIG_MACH_AP4EVB)	+= board-ap4evb.o
diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot
new file mode 100644
index 0000000..1c08ee9
--- /dev/null
+++ b/arch/arm/mach-shmobile/Makefile.boot
@@ -0,0 +1,9 @@
+__ZRELADDR	:= $(shell /bin/bash -c 'printf "0x%08x" \
+		     $$[$(CONFIG_MEMORY_START) + 0x8000]')
+
+   zreladdr-y   := $(__ZRELADDR)
+
+# Unsupported legacy stuff
+#
+#params_phys-y (Instead: Pass atags pointer in r2)
+#initrd_phys-y (Instead: Use compiled-in initramfs)
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
new file mode 100644
index 0000000..a0463d9
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -0,0 +1,301 @@
+/*
+ * AP4EVB board support
+ *
+ * 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/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+#include <linux/smsc911x.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/input/sh_keysc.h>
+#include <mach/common.h>
+#include <mach/sh7372.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.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
+ */
+
+/*
+ * 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
+ */
+
+/*
+ * 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
+ */
+
+/*
+ * SMSC 9220
+ *
+ *  SW1		SMSC 9220
+ * -----------------------
+ *  ON		access disable
+ *  OFF		access enable
+ */
+
+/*
+ * KEYSC
+ *
+ * SW43		KEYSC
+ * -------------------------
+ * ON		enable
+ * OFF		disable
+ */
+
+/* MTD */
+static struct mtd_partition nor_flash_partitions[] = {
+	{
+		.name		= "loader",
+		.offset		= 0x00000000,
+		.size		= 512 * 1024,
+	},
+	{
+		.name		= "bootenv",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 512 * 1024,
+	},
+	{
+		.name		= "kernel_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 9220 */
+static struct resource smc911x_resources[] = {
+	{
+		.start	= 0x14000000,
+		.end	= 0x16000000 - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= 6,
+		.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,
+	},
+};
+
+/* KEYSC (Needs SW43 set to ON) */
+static struct sh_keysc_info keysc_info = {
+	.mode		= SH_KEYSC_MODE_1,
+	.scan_timing	= 3,
+	.delay		= 2500,
+	.keycodes = {
+		KEY_0, KEY_1, KEY_2, KEY_3, KEY_4,
+		KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,
+		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,
+	},
+};
+
+static struct resource keysc_resources[] = {
+	[0] = {
+		.name	= "KEYSC",
+		.start  = 0xe61b0000,
+		.end    = 0xe61b0063,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 79,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device keysc_device = {
+	.name           = "sh_keysc",
+	.id             = 0, /* "keysc0" clock */
+	.num_resources  = ARRAY_SIZE(keysc_resources),
+	.resource       = keysc_resources,
+	.dev	= {
+		.platform_data	= &keysc_info,
+	},
+};
+
+static struct platform_device *ap4evb_devices[] __initdata = {
+	&nor_flash_device,
+	&smc911x_device,
+	&keysc_device,
+};
+
+static struct map_desc ap4evb_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 ap4evb_map_io(void)
+{
+	iotable_init(ap4evb_io_desc, ARRAY_SIZE(ap4evb_io_desc));
+
+	/* setup early devices, clocks and console here as well */
+	sh7372_add_early_devices();
+	sh7367_clock_init(); /* use g3 clocks for now */
+	shmobile_setup_console();
+}
+
+static void __init ap4evb_init(void)
+{
+	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);
+
+	/* enable LED 1 - 4 */
+	gpio_request(GPIO_PORT185, NULL);
+	gpio_request(GPIO_PORT186, NULL);
+	gpio_request(GPIO_PORT187, NULL);
+	gpio_request(GPIO_PORT188, NULL);
+	gpio_direction_output(GPIO_PORT185, 1);
+	gpio_direction_output(GPIO_PORT186, 1);
+	gpio_direction_output(GPIO_PORT187, 1);
+	gpio_direction_output(GPIO_PORT188, 1);
+	gpio_export(GPIO_PORT185, 0);
+	gpio_export(GPIO_PORT186, 0);
+	gpio_export(GPIO_PORT187, 0);
+	gpio_export(GPIO_PORT188, 0);
+
+	/* enable Debug switch (S6) */
+	gpio_request(GPIO_PORT32, NULL);
+	gpio_request(GPIO_PORT33, NULL);
+	gpio_request(GPIO_PORT34, NULL);
+	gpio_request(GPIO_PORT35, NULL);
+	gpio_direction_input(GPIO_PORT32);
+	gpio_direction_input(GPIO_PORT33);
+	gpio_direction_input(GPIO_PORT34);
+	gpio_direction_input(GPIO_PORT35);
+	gpio_export(GPIO_PORT32, 0);
+	gpio_export(GPIO_PORT33, 0);
+	gpio_export(GPIO_PORT34, 0);
+	gpio_export(GPIO_PORT35, 0);
+
+	/* enable KEYSC */
+	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_KEYIN0_136, NULL);
+	gpio_request(GPIO_FN_KEYIN1_135, NULL);
+	gpio_request(GPIO_FN_KEYIN2_134, NULL);
+	gpio_request(GPIO_FN_KEYIN3_133, NULL);
+	gpio_request(GPIO_FN_KEYIN4,     NULL);
+
+	sh7372_add_standard_devices();
+
+	platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
+}
+
+MACHINE_START(AP4EVB, "ap4evb")
+	.phys_io	= 0xe6000000,
+	.io_pg_offst	= ((0xe6000000) >> 18) & 0xfffc,
+	.map_io		= ap4evb_map_io,
+	.init_irq	= sh7372_init_irq,
+	.init_machine	= ap4evb_init,
+	.timer		= &shmobile_timer,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
new file mode 100644
index 0000000..f36c9a9
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-g3evm.c
@@ -0,0 +1,211 @@
+/*
+ * G3EVM board support
+ *
+ * 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/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/usb/r8a66597.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <mach/sh7367.h>
+#include <mach/common.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+static struct mtd_partition nor_flash_partitions[] = {
+	{
+		.name		= "loader",
+		.offset		= 0x00000000,
+		.size		= 512 * 1024,
+	},
+	{
+		.name		= "bootenv",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 512 * 1024,
+	},
+	{
+		.name		= "kernel_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,
+};
+
+/* USBHS */
+void usb_host_port_power(int port, int power)
+{
+	if (!power) /* only power-on supported for now */
+		return;
+
+	/* set VBOUT/PWEN and EXTLP0 in DVSTCTR */
+	__raw_writew(__raw_readw(0xe6890008) | 0x600, 0xe6890008);
+}
+
+static struct r8a66597_platdata usb_host_data = {
+	.on_chip = 1,
+	.port_power = usb_host_port_power,
+};
+
+static struct resource usb_host_resources[] = {
+	[0] = {
+		.name	= "USBHS",
+		.start	= 0xe6890000,
+		.end	= 0xe68900e5,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 65,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device usb_host_device = {
+	.name		= "r8a66597_hcd",
+	.id		= 0,
+	.dev = {
+		.platform_data		= &usb_host_data,
+		.dma_mask		= NULL,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(usb_host_resources),
+	.resource	= usb_host_resources,
+};
+
+static struct platform_device *g3evm_devices[] __initdata = {
+	&nor_flash_device,
+	&usb_host_device,
+};
+
+static struct map_desc g3evm_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 g3evm_map_io(void)
+{
+	iotable_init(g3evm_io_desc, ARRAY_SIZE(g3evm_io_desc));
+
+	/* setup early devices, clocks and console here as well */
+	sh7367_add_early_devices();
+	sh7367_clock_init();
+	shmobile_setup_console();
+}
+
+static void __init g3evm_init(void)
+{
+	sh7367_pinmux_init();
+
+	/* Lit DS4 LED */
+	gpio_request(GPIO_PORT22, NULL);
+	gpio_direction_output(GPIO_PORT22, 1);
+	gpio_export(GPIO_PORT22, 0);
+
+	/* Lit DS8 LED */
+	gpio_request(GPIO_PORT23, NULL);
+	gpio_direction_output(GPIO_PORT23, 1);
+	gpio_export(GPIO_PORT23, 0);
+
+	/* Lit DS3 LED */
+	gpio_request(GPIO_PORT24, NULL);
+	gpio_direction_output(GPIO_PORT24, 1);
+	gpio_export(GPIO_PORT24, 0);
+
+	/* SCIFA1 */
+	gpio_request(GPIO_FN_SCIFA1_TXD, NULL);
+	gpio_request(GPIO_FN_SCIFA1_RXD, NULL);
+	gpio_request(GPIO_FN_SCIFA1_CTS, NULL);
+	gpio_request(GPIO_FN_SCIFA1_RTS, NULL);
+
+	/* USBHS */
+	gpio_request(GPIO_FN_VBUS0, NULL);
+	gpio_request(GPIO_FN_PWEN, NULL);
+	gpio_request(GPIO_FN_OVCN, NULL);
+	gpio_request(GPIO_FN_OVCN2, NULL);
+	gpio_request(GPIO_FN_EXTLP, NULL);
+	gpio_request(GPIO_FN_IDIN, NULL);
+
+	/* enable clock in SYMSTPCR2 */
+	__raw_writel(__raw_readl(0xe6158048) & ~(1 << 22), 0xe6158048);
+
+	/* setup USB phy */
+	__raw_writew(0x0300, 0xe605810a);	/* USBCR1 */
+	__raw_writew(0x00e0, 0xe60581c0);	/* CPFCH */
+	__raw_writew(0x6010, 0xe60581c6);	/* CGPOSR */
+	__raw_writew(0x8a0a, 0xe605810c);	/* USBCR2 */
+
+	sh7367_add_standard_devices();
+
+	platform_add_devices(g3evm_devices, ARRAY_SIZE(g3evm_devices));
+}
+
+MACHINE_START(G3EVM, "g3evm")
+	.phys_io	= 0xe6000000,
+	.io_pg_offst	= ((0xe6000000) >> 18) & 0xfffc,
+	.map_io		= g3evm_map_io,
+	.init_irq	= sh7367_init_irq,
+	.init_machine	= g3evm_init,
+	.timer		= &shmobile_timer,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
new file mode 100644
index 0000000..5acd623
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-g4evm.c
@@ -0,0 +1,211 @@
+/*
+ * G4EVM board support
+ *
+ * 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/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/usb/r8a66597.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <mach/sh7377.h>
+#include <mach/common.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+static struct mtd_partition nor_flash_partitions[] = {
+	{
+		.name		= "loader",
+		.offset		= 0x00000000,
+		.size		= 512 * 1024,
+	},
+	{
+		.name		= "bootenv",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= 512 * 1024,
+	},
+	{
+		.name		= "kernel_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,
+};
+
+/* USBHS */
+void usb_host_port_power(int port, int power)
+{
+	if (!power) /* only power-on supported for now */
+		return;
+
+	/* set VBOUT/PWEN and EXTLP0 in DVSTCTR */
+	__raw_writew(__raw_readw(0xe6890008) | 0x600, 0xe6890008);
+}
+
+static struct r8a66597_platdata usb_host_data = {
+	.on_chip = 1,
+	.port_power = usb_host_port_power,
+};
+
+static struct resource usb_host_resources[] = {
+	[0] = {
+		.name	= "USBHS",
+		.start	= 0xe6890000,
+		.end	= 0xe68900e5,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 65,
+		.end	= 65,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device usb_host_device = {
+	.name		= "r8a66597_hcd",
+	.id		= 0,
+	.dev = {
+		.platform_data		= &usb_host_data,
+		.dma_mask		= NULL,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(usb_host_resources),
+	.resource	= usb_host_resources,
+};
+
+static struct platform_device *g4evm_devices[] __initdata = {
+	&nor_flash_device,
+	&usb_host_device,
+};
+
+static struct map_desc g4evm_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 g4evm_map_io(void)
+{
+	iotable_init(g4evm_io_desc, ARRAY_SIZE(g4evm_io_desc));
+
+	/* setup early devices, clocks and console here as well */
+	sh7377_add_early_devices();
+	sh7367_clock_init(); /* use g3 clocks for now */
+	shmobile_setup_console();
+}
+
+static void __init g4evm_init(void)
+{
+	sh7377_pinmux_init();
+
+	/* Lit DS14 LED */
+	gpio_request(GPIO_PORT109, NULL);
+	gpio_direction_output(GPIO_PORT109, 1);
+	gpio_export(GPIO_PORT109, 1);
+
+	/* Lit DS15 LED */
+	gpio_request(GPIO_PORT110, NULL);
+	gpio_direction_output(GPIO_PORT110, 1);
+	gpio_export(GPIO_PORT110, 1);
+
+	/* Lit DS16 LED */
+	gpio_request(GPIO_PORT112, NULL);
+	gpio_direction_output(GPIO_PORT112, 1);
+	gpio_export(GPIO_PORT112, 1);
+
+	/* Lit DS17 LED */
+	gpio_request(GPIO_PORT113, NULL);
+	gpio_direction_output(GPIO_PORT113, 1);
+	gpio_export(GPIO_PORT113, 1);
+
+	/* USBHS */
+	gpio_request(GPIO_FN_VBUS_0, NULL);
+	gpio_request(GPIO_FN_PWEN, NULL);
+	gpio_request(GPIO_FN_OVCN, NULL);
+	gpio_request(GPIO_FN_OVCN2, NULL);
+	gpio_request(GPIO_FN_EXTLP, NULL);
+	gpio_request(GPIO_FN_IDIN, NULL);
+
+	/* enable clock in SMSTPCR3 */
+	__raw_writel(__raw_readl(0xe615013c) & ~(1 << 22), 0xe615013c);
+
+	/* setup USB phy */
+	__raw_writew(0x0200, 0xe605810a);       /* USBCR1 */
+	__raw_writew(0x00e0, 0xe60581c0);       /* CPFCH */
+	__raw_writew(0x6010, 0xe60581c6);       /* CGPOSR */
+	__raw_writew(0x8a0a, 0xe605810c);       /* USBCR2 */
+
+	sh7377_add_standard_devices();
+
+	platform_add_devices(g4evm_devices, ARRAY_SIZE(g4evm_devices));
+}
+
+MACHINE_START(G4EVM, "g4evm")
+	.phys_io	= 0xe6000000,
+	.io_pg_offst	= ((0xe6000000) >> 18) & 0xfffc,
+	.map_io		= g4evm_map_io,
+	.init_irq	= sh7377_init_irq,
+	.init_machine	= g4evm_init,
+	.timer		= &shmobile_timer,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c
new file mode 100644
index 0000000..58bd54e
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-sh7367.c
@@ -0,0 +1,96 @@
+/*
+ * Preliminary clock framework support for sh7367
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+
+struct clk {
+	const char *name;
+	unsigned long rate;
+};
+
+#include <asm/clkdev.h>
+
+int __clk_get(struct clk *clk)
+{
+	return 1;
+}
+EXPORT_SYMBOL(__clk_get);
+
+void __clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(__clk_put);
+
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk ? clk->rate : 0;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+/* a static peripheral clock for now - enough to get sh-sci working */
+static struct clk peripheral_clk = {
+	.name	    = "peripheral_clk",
+	.rate	    = 48000000,
+};
+
+/* a static rclk for now - enough to get sh_cmt working */
+static struct clk r_clk = {
+	.name	    = "r_clk",
+	.rate	    = 32768,
+};
+
+/* a static usb0 for now - enough to get r8a66597 working */
+static struct clk usb0_clk = {
+	.name	    = "usb0",
+};
+
+static struct clk_lookup lookups[] = {
+	{
+		.clk = &peripheral_clk,
+	}, {
+		.clk = &r_clk,
+	}, {
+		.clk = &usb0_clk,
+	}
+};
+
+void __init sh7367_clock_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+		lookups[i].con_id = lookups[i].clk->name;
+		clkdev_add(&lookups[i]);
+	}
+}
diff --git a/arch/arm/mach-shmobile/console.c b/arch/arm/mach-shmobile/console.c
new file mode 100644
index 0000000..9411a5b
--- /dev/null
+++ b/arch/arm/mach-shmobile/console.c
@@ -0,0 +1,31 @@
+/*
+ * SH-Mobile Console
+ *
+ * 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/platform_device.h>
+#include <mach/common.h>
+#include <asm/mach/map.h>
+
+void __init shmobile_setup_console(void)
+{
+	parse_early_param();
+
+	/* Let earlyprintk output early console messages */
+	early_platform_driver_probe("earlyprintk", 1, 1);
+}
diff --git a/arch/arm/mach-shmobile/include/mach/clkdev.h b/arch/arm/mach-shmobile/include/mach/clkdev.h
new file mode 100644
index 0000000..36d0163
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+int __clk_get(struct clk *clk);
+void __clk_put(struct clk *clk);
+
+#endif /* __ASM_MACH_CLKDEV_H */
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
new file mode 100644
index 0000000..5790360
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -0,0 +1,23 @@
+#ifndef __ARCH_MACH_COMMON_H
+#define __ARCH_MACH_COMMON_H
+
+extern struct sys_timer shmobile_timer;
+extern void shmobile_setup_console(void);
+
+extern void sh7367_init_irq(void);
+extern void sh7367_add_early_devices(void);
+extern void sh7367_add_standard_devices(void);
+extern void sh7367_clock_init(void);
+extern void sh7367_pinmux_init(void);
+
+extern void sh7377_init_irq(void);
+extern void sh7377_add_early_devices(void);
+extern void sh7377_add_standard_devices(void);
+extern void sh7377_pinmux_init(void);
+
+extern void sh7372_init_irq(void);
+extern void sh7372_add_early_devices(void);
+extern void sh7372_add_standard_devices(void);
+extern void sh7372_pinmux_init(void);
+
+#endif /* __ARCH_MACH_COMMON_H */
diff --git a/arch/arm/mach-shmobile/include/mach/dma.h b/arch/arm/mach-shmobile/include/mach/dma.h
new file mode 100644
index 0000000..40a8c178
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/dma.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-shmobile/include/mach/entry-macro.S b/arch/arm/mach-shmobile/include/mach/entry-macro.S
new file mode 100644
index 0000000..a285d13
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/entry-macro.S
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 <mach/hardware.h>
+#include <mach/irqs.h>
+
+	.macro  disable_fiq
+	.endm
+
+	.macro  get_irqnr_preamble, base, tmp
+	ldr     \base, =INTFLGA
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr     \irqnr, [\base]
+	cmp	\irqnr, #0
+	beq	1000f
+	/* intevt to irq number */
+	lsr	\irqnr, \irqnr, #0x5
+	subs	\irqnr, \irqnr, #16
+
+1000:
+	.endm
diff --git a/arch/arm/mach-shmobile/include/mach/gpio.h b/arch/arm/mach-shmobile/include/mach/gpio.h
new file mode 100644
index 0000000..5bc6bd4
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/gpio.h
@@ -0,0 +1,48 @@
+/*
+ * Generic GPIO API and pinmux table support
+ *
+ * Copyright (c) 2008  Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#define ARCH_NR_GPIOS 1024
+#include <linux/sh_pfc.h>
+
+#ifdef CONFIG_GPIOLIB
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	__gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+	return __gpio_cansleep(gpio);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return -ENOSYS;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+	return -EINVAL;
+}
+
+#endif /* CONFIG_GPIOLIB */
+
+#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-shmobile/include/mach/hardware.h b/arch/arm/mach-shmobile/include/mach/hardware.h
new file mode 100644
index 0000000..3f0ef19
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/hardware.h
@@ -0,0 +1,7 @@
+#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/io.h b/arch/arm/mach-shmobile/include/mach/io.h
new file mode 100644
index 0000000..7339fe4
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/io.h
@@ -0,0 +1,9 @@
+#ifndef __ASM_MACH_IO_H
+#define __ASM_MACH_IO_H
+
+#define IO_SPACE_LIMIT		0xffffffff
+
+#define __io(a)			((void __iomem *)(a))
+#define __mem_pci(a)		(a)
+
+#endif /* __ASM_MACH_IO_H */
diff --git a/arch/arm/mach-shmobile/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
new file mode 100644
index 0000000..5179b72
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_MACH_IRQS_H
+#define __ASM_MACH_IRQS_H
+
+#define NR_IRQS         512
+#define NR_IRQS_LEGACY  8
+
+#define evt2irq(evt)		(((evt) >> 5) - 16)
+#define irq2evt(irq)		(((irq) + 16) << 5)
+
+#endif /* __ASM_MACH_IRQS_H */
diff --git a/arch/arm/mach-shmobile/include/mach/memory.h b/arch/arm/mach-shmobile/include/mach/memory.h
new file mode 100644
index 0000000..e188183
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/memory.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_MEMORY_H
+#define __ASM_MACH_MEMORY_H
+
+#define PHYS_OFFSET	UL(CONFIG_MEMORY_START)
+#define MEM_SIZE	UL(CONFIG_MEMORY_SIZE)
+
+#endif /* __ASM_MACH_MEMORY_H */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7367.h b/arch/arm/mach-shmobile/include/mach/sh7367.h
new file mode 100644
index 0000000..52d0de6
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/sh7367.h
@@ -0,0 +1,332 @@
+#ifndef __ASM_SH7367_H__
+#define __ASM_SH7367_H__
+
+/* Pin Function Controller:
+ * GPIO_FN_xx - GPIO used to select pin function
+ * GPIO_PORTxx - GPIO mapped to real I/O pin on CPU
+ */
+enum {
+	/* 49-1 -> 49-6 (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_PORT119,
+
+	GPIO_PORT120, GPIO_PORT121, GPIO_PORT122, GPIO_PORT123, GPIO_PORT124,
+	GPIO_PORT125, GPIO_PORT126, GPIO_PORT127, 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_PORT165, GPIO_PORT166, GPIO_PORT167, GPIO_PORT168, GPIO_PORT169,
+
+	GPIO_PORT170, GPIO_PORT171, GPIO_PORT172, GPIO_PORT173, GPIO_PORT174,
+	GPIO_PORT175, GPIO_PORT176, GPIO_PORT177, GPIO_PORT178, GPIO_PORT179,
+
+	GPIO_PORT180, GPIO_PORT181, GPIO_PORT182, GPIO_PORT183, GPIO_PORT184,
+	GPIO_PORT185, GPIO_PORT186, GPIO_PORT187, GPIO_PORT188, GPIO_PORT189,
+
+	GPIO_PORT190, GPIO_PORT191, 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,
+
+	/* Special Pull-up / Pull-down Functions */
+	GPIO_FN_PORT48_KEYIN0_PU, GPIO_FN_PORT49_KEYIN1_PU,
+	GPIO_FN_PORT50_KEYIN2_PU, GPIO_FN_PORT55_KEYIN3_PU,
+	GPIO_FN_PORT56_KEYIN4_PU, GPIO_FN_PORT57_KEYIN5_PU,
+	GPIO_FN_PORT58_KEYIN6_PU,
+
+	/* 49-1 (FN) */
+	GPIO_FN_VBUS0, GPIO_FN_CPORT0, GPIO_FN_CPORT1, GPIO_FN_CPORT2,
+	GPIO_FN_CPORT3, GPIO_FN_CPORT4, GPIO_FN_CPORT5, GPIO_FN_CPORT6,
+	GPIO_FN_CPORT7, GPIO_FN_CPORT8, GPIO_FN_CPORT9, GPIO_FN_CPORT10,
+	GPIO_FN_CPORT11, GPIO_FN_SIN2, GPIO_FN_CPORT12, GPIO_FN_XCTS2,
+	GPIO_FN_CPORT13, GPIO_FN_RFSPO4, GPIO_FN_CPORT14, GPIO_FN_RFSPO5,
+	GPIO_FN_CPORT15, GPIO_FN_CPORT16, GPIO_FN_CPORT17, GPIO_FN_SOUT2,
+	GPIO_FN_CPORT18, GPIO_FN_XRTS2, GPIO_FN_CPORT19, GPIO_FN_CPORT20,
+	GPIO_FN_RFSPO6, GPIO_FN_CPORT21, GPIO_FN_STATUS0, GPIO_FN_CPORT22,
+	GPIO_FN_STATUS1, GPIO_FN_CPORT23, GPIO_FN_STATUS2, GPIO_FN_RFSPO7,
+	GPIO_FN_MPORT0, GPIO_FN_MPORT1, GPIO_FN_B_SYNLD1, GPIO_FN_B_SYNLD2,
+	GPIO_FN_XMAINPS, GPIO_FN_XDIVPS, GPIO_FN_XIDRST, GPIO_FN_IDCLK,
+	GPIO_FN_IDIO, GPIO_FN_SOUT1, GPIO_FN_SCIFA4_TXD,
+	GPIO_FN_M02_BERDAT, GPIO_FN_SIN1, GPIO_FN_SCIFA4_RXD, GPIO_FN_XWUP,
+	GPIO_FN_XRTS1, GPIO_FN_SCIFA4_RTS, GPIO_FN_M03_BERCLK,
+	GPIO_FN_XCTS1, GPIO_FN_SCIFA4_CTS,
+
+	/* 49-2 (FN) */
+	GPIO_FN_HSU_IQ_AGC6, GPIO_FN_MFG2_IN2, GPIO_FN_MSIOF2_MCK0,
+	GPIO_FN_HSU_IQ_AGC5, GPIO_FN_MFG2_IN1, GPIO_FN_MSIOF2_MCK1,
+	GPIO_FN_HSU_IQ_AGC4, GPIO_FN_MSIOF2_RSYNC,
+	GPIO_FN_HSU_IQ_AGC3, GPIO_FN_MFG2_OUT1, GPIO_FN_MSIOF2_RSCK,
+	GPIO_FN_HSU_IQ_AGC2, GPIO_FN_PORT42_KEYOUT0,
+	GPIO_FN_HSU_IQ_AGC1, GPIO_FN_PORT43_KEYOUT1,
+	GPIO_FN_HSU_IQ_AGC0, GPIO_FN_PORT44_KEYOUT2,
+	GPIO_FN_HSU_IQ_AGC_ST, GPIO_FN_PORT45_KEYOUT3,
+	GPIO_FN_HSU_IQ_PDO, GPIO_FN_PORT46_KEYOUT4,
+	GPIO_FN_HSU_IQ_PYO, GPIO_FN_PORT47_KEYOUT5,
+	GPIO_FN_HSU_EN_TXMUX_G3MO, GPIO_FN_PORT48_KEYIN0,
+	GPIO_FN_HSU_I_TXMUX_G3MO, GPIO_FN_PORT49_KEYIN1,
+	GPIO_FN_HSU_Q_TXMUX_G3MO, GPIO_FN_PORT50_KEYIN2,
+	GPIO_FN_HSU_SYO, GPIO_FN_PORT51_MSIOF2_TSYNC,
+	GPIO_FN_HSU_SDO, GPIO_FN_PORT52_MSIOF2_TSCK,
+	GPIO_FN_HSU_TGTTI_G3MO, GPIO_FN_PORT53_MSIOF2_TXD,
+	GPIO_FN_B_TIME_STAMP, GPIO_FN_PORT54_MSIOF2_RXD,
+	GPIO_FN_HSU_SDI, GPIO_FN_PORT55_KEYIN3,
+	GPIO_FN_HSU_SCO, GPIO_FN_PORT56_KEYIN4,
+	GPIO_FN_HSU_DREQ, GPIO_FN_PORT57_KEYIN5,
+	GPIO_FN_HSU_DACK, GPIO_FN_PORT58_KEYIN6,
+	GPIO_FN_HSU_CLK61M, GPIO_FN_PORT59_MSIOF2_SS1,
+	GPIO_FN_HSU_XRST, GPIO_FN_PORT60_MSIOF2_SS2,
+	GPIO_FN_PCMCLKO, GPIO_FN_SYNC8KO, GPIO_FN_DNPCM_A, GPIO_FN_UPPCM_A,
+	GPIO_FN_XTALB1L,
+	GPIO_FN_GPS_AGC1, GPIO_FN_SCIFA0_RTS,
+	GPIO_FN_GPS_AGC2, GPIO_FN_SCIFA0_SCK,
+	GPIO_FN_GPS_AGC3, GPIO_FN_SCIFA0_TXD,
+	GPIO_FN_GPS_AGC4, GPIO_FN_SCIFA0_RXD,
+	GPIO_FN_GPS_PWRD, GPIO_FN_SCIFA0_CTS,
+	GPIO_FN_GPS_IM, GPIO_FN_GPS_IS, GPIO_FN_GPS_QM, GPIO_FN_GPS_QS,
+	GPIO_FN_SIUBOMC, GPIO_FN_TPU2TO0,
+	GPIO_FN_SIUCKB, GPIO_FN_TPU2TO1,
+	GPIO_FN_SIUBOLR, GPIO_FN_BBIF2_TSYNC, GPIO_FN_TPU2TO2,
+	GPIO_FN_SIUBOBT, GPIO_FN_BBIF2_TSCK, GPIO_FN_TPU2TO3,
+	GPIO_FN_SIUBOSLD, GPIO_FN_BBIF2_TXD, GPIO_FN_TPU3TO0,
+	GPIO_FN_SIUBILR, GPIO_FN_TPU3TO1,
+	GPIO_FN_SIUBIBT, GPIO_FN_TPU3TO2,
+	GPIO_FN_SIUBISLD, GPIO_FN_TPU3TO3,
+	GPIO_FN_NMI, GPIO_FN_TPU4TO0,
+	GPIO_FN_DNPCM_M, GPIO_FN_TPU4TO1, GPIO_FN_TPU4TO2, GPIO_FN_TPU4TO3,
+	GPIO_FN_IRQ_TMPB,
+	GPIO_FN_PWEN, GPIO_FN_MFG1_OUT1,
+	GPIO_FN_OVCN, GPIO_FN_MFG1_IN1,
+	GPIO_FN_OVCN2, GPIO_FN_MFG1_IN2,
+
+	/* 49-3 (FN) */
+	GPIO_FN_RFSPO1, GPIO_FN_RFSPO2, GPIO_FN_RFSPO3, GPIO_FN_PORT93_VIO_CKO2,
+	GPIO_FN_USBTERM, GPIO_FN_EXTLP, GPIO_FN_IDIN,
+	GPIO_FN_SCIFA5_CTS, GPIO_FN_MFG0_IN1,
+	GPIO_FN_SCIFA5_RTS, GPIO_FN_MFG0_IN2,
+	GPIO_FN_SCIFA5_RXD,
+	GPIO_FN_SCIFA5_TXD,
+	GPIO_FN_SCIFA5_SCK, GPIO_FN_MFG0_OUT1,
+	GPIO_FN_A0_EA0, GPIO_FN_BS,
+	GPIO_FN_A14_EA14, GPIO_FN_PORT102_KEYOUT0,
+	GPIO_FN_A15_EA15, GPIO_FN_PORT103_KEYOUT1, GPIO_FN_DV_CLKOL,
+	GPIO_FN_A16_EA16, GPIO_FN_PORT104_KEYOUT2,
+	GPIO_FN_DV_VSYNCL, GPIO_FN_MSIOF0_SS1,
+	GPIO_FN_A17_EA17, GPIO_FN_PORT105_KEYOUT3,
+	GPIO_FN_DV_HSYNCL, GPIO_FN_MSIOF0_TSYNC,
+	GPIO_FN_A18_EA18, GPIO_FN_PORT106_KEYOUT4,
+	GPIO_FN_DV_DL0, GPIO_FN_MSIOF0_TSCK,
+	GPIO_FN_A19_EA19, GPIO_FN_PORT107_KEYOUT5,
+	GPIO_FN_DV_DL1, GPIO_FN_MSIOF0_TXD,
+	GPIO_FN_A20_EA20, GPIO_FN_PORT108_KEYIN0,
+	GPIO_FN_DV_DL2, GPIO_FN_MSIOF0_RSCK,
+	GPIO_FN_A21_EA21, GPIO_FN_PORT109_KEYIN1,
+	GPIO_FN_DV_DL3, GPIO_FN_MSIOF0_RSYNC,
+	GPIO_FN_A22_EA22, GPIO_FN_PORT110_KEYIN2,
+	GPIO_FN_DV_DL4, GPIO_FN_MSIOF0_MCK0,
+	GPIO_FN_A23_EA23, GPIO_FN_PORT111_KEYIN3,
+	GPIO_FN_DV_DL5, GPIO_FN_MSIOF0_MCK1,
+	GPIO_FN_A24_EA24, GPIO_FN_PORT112_KEYIN4,
+	GPIO_FN_DV_DL6, GPIO_FN_MSIOF0_RXD,
+	GPIO_FN_A25_EA25, GPIO_FN_PORT113_KEYIN5,
+	GPIO_FN_DV_DL7, GPIO_FN_MSIOF0_SS2,
+	GPIO_FN_A26, GPIO_FN_PORT113_KEYIN6, GPIO_FN_DV_CLKIL,
+	GPIO_FN_D0_ED0_NAF0, GPIO_FN_D1_ED1_NAF1, GPIO_FN_D2_ED2_NAF2,
+	GPIO_FN_D3_ED3_NAF3, GPIO_FN_D4_ED4_NAF4, GPIO_FN_D5_ED5_NAF5,
+	GPIO_FN_D6_ED6_NAF6, GPIO_FN_D7_ED7_NAF7, GPIO_FN_D8_ED8_NAF8,
+	GPIO_FN_D9_ED9_NAF9, GPIO_FN_D10_ED10_NAF10, GPIO_FN_D11_ED11_NAF11,
+	GPIO_FN_D12_ED12_NAF12, GPIO_FN_D13_ED13_NAF13,
+	GPIO_FN_D14_ED14_NAF14, GPIO_FN_D15_ED15_NAF15,
+	GPIO_FN_CS4, GPIO_FN_CS5A, GPIO_FN_CS5B, GPIO_FN_FCE1,
+	GPIO_FN_CS6B, GPIO_FN_XCS2, GPIO_FN_FCE0, GPIO_FN_CS6A,
+	GPIO_FN_DACK0, GPIO_FN_WAIT, GPIO_FN_DREQ0, GPIO_FN_RD_XRD,
+	GPIO_FN_A27, GPIO_FN_RDWR_XWE, GPIO_FN_WE0_XWR0_FWE,
+	GPIO_FN_WE1_XWR1, GPIO_FN_FRB, GPIO_FN_CKO,
+	GPIO_FN_NBRSTOUT, GPIO_FN_NBRST,
+
+	/* 49-4 (FN) */
+	GPIO_FN_RFSPO0, GPIO_FN_PORT146_VIO_CKO2, GPIO_FN_TSTMD,
+	GPIO_FN_VIO_VD, GPIO_FN_VIO_HD,
+	GPIO_FN_VIO_D0, GPIO_FN_VIO_D1, GPIO_FN_VIO_D2,
+	GPIO_FN_VIO_D3, GPIO_FN_VIO_D4, GPIO_FN_VIO_D5,
+	GPIO_FN_VIO_D6, GPIO_FN_VIO_D7, GPIO_FN_VIO_D8,
+	GPIO_FN_VIO_D9, GPIO_FN_VIO_D10, GPIO_FN_VIO_D11,
+	GPIO_FN_VIO_D12, GPIO_FN_VIO_D13, GPIO_FN_VIO_D14,
+	GPIO_FN_VIO_D15, GPIO_FN_VIO_CLK, GPIO_FN_VIO_FIELD,
+	GPIO_FN_VIO_CKO,
+	GPIO_FN_MFG3_IN1, GPIO_FN_MFG3_IN2,
+	GPIO_FN_M9_SLCD_A01, GPIO_FN_MFG3_OUT1, GPIO_FN_TPU0TO0,
+	GPIO_FN_M10_SLCD_CK1, GPIO_FN_MFG4_IN1, GPIO_FN_TPU0TO1,
+	GPIO_FN_M11_SLCD_SO1, GPIO_FN_MFG4_IN2, GPIO_FN_TPU0TO2,
+	GPIO_FN_M12_SLCD_CE1, GPIO_FN_MFG4_OUT1, GPIO_FN_TPU0TO3,
+	GPIO_FN_LCDD0, GPIO_FN_PORT175_KEYOUT0, GPIO_FN_DV_D0,
+	GPIO_FN_SIUCKA, GPIO_FN_MFG0_OUT2,
+	GPIO_FN_LCDD1, GPIO_FN_PORT176_KEYOUT1, GPIO_FN_DV_D1,
+	GPIO_FN_SIUAOLR, GPIO_FN_BBIF2_TSYNC1,
+	GPIO_FN_LCDD2, GPIO_FN_PORT177_KEYOUT2, GPIO_FN_DV_D2,
+	GPIO_FN_SIUAOBT, GPIO_FN_BBIF2_TSCK1,
+	GPIO_FN_LCDD3, GPIO_FN_PORT178_KEYOUT3, GPIO_FN_DV_D3,
+	GPIO_FN_SIUAOSLD, GPIO_FN_BBIF2_TXD1,
+	GPIO_FN_LCDD4, GPIO_FN_PORT179_KEYOUT4, GPIO_FN_DV_D4,
+	GPIO_FN_SIUAISPD, GPIO_FN_MFG1_OUT2,
+	GPIO_FN_LCDD5, GPIO_FN_PORT180_KEYOUT5, GPIO_FN_DV_D5,
+	GPIO_FN_SIUAILR, GPIO_FN_MFG2_OUT2,
+	GPIO_FN_LCDD6, GPIO_FN_DV_D6,
+	GPIO_FN_SIUAIBT, GPIO_FN_MFG3_OUT2, GPIO_FN_XWR2,
+	GPIO_FN_LCDD7, GPIO_FN_DV_D7,
+	GPIO_FN_SIUAISLD, GPIO_FN_MFG4_OUT2, GPIO_FN_XWR3,
+	GPIO_FN_LCDD8, GPIO_FN_DV_D8, GPIO_FN_D16, GPIO_FN_ED16,
+	GPIO_FN_LCDD9, GPIO_FN_DV_D9, GPIO_FN_D17, GPIO_FN_ED17,
+	GPIO_FN_LCDD10, GPIO_FN_DV_D10, GPIO_FN_D18, GPIO_FN_ED18,
+	GPIO_FN_LCDD11, GPIO_FN_DV_D11, GPIO_FN_D19, GPIO_FN_ED19,
+	GPIO_FN_LCDD12, GPIO_FN_DV_D12, GPIO_FN_D20, GPIO_FN_ED20,
+	GPIO_FN_LCDD13, GPIO_FN_DV_D13, GPIO_FN_D21, GPIO_FN_ED21,
+	GPIO_FN_LCDD14, GPIO_FN_DV_D14, GPIO_FN_D22, GPIO_FN_ED22,
+	GPIO_FN_LCDD15, GPIO_FN_DV_D15, GPIO_FN_D23, GPIO_FN_ED23,
+	GPIO_FN_LCDD16, GPIO_FN_DV_HSYNC, GPIO_FN_D24, GPIO_FN_ED24,
+	GPIO_FN_LCDD17, GPIO_FN_DV_VSYNC, GPIO_FN_D25, GPIO_FN_ED25,
+	GPIO_FN_LCDD18, GPIO_FN_DREQ2, GPIO_FN_MSIOF0L_TSCK,
+	GPIO_FN_D26, GPIO_FN_ED26,
+	GPIO_FN_LCDD19, GPIO_FN_MSIOF0L_TSYNC,
+	GPIO_FN_D27, GPIO_FN_ED27,
+	GPIO_FN_LCDD20, GPIO_FN_TS_SPSYNC1, GPIO_FN_MSIOF0L_MCK0,
+	GPIO_FN_D28, GPIO_FN_ED28,
+	GPIO_FN_LCDD21, GPIO_FN_TS_SDAT1, GPIO_FN_MSIOF0L_MCK1,
+	GPIO_FN_D29, GPIO_FN_ED29,
+	GPIO_FN_LCDD22, GPIO_FN_TS_SDEN1, GPIO_FN_MSIOF0L_SS1,
+	GPIO_FN_D30, GPIO_FN_ED30,
+	GPIO_FN_LCDD23, GPIO_FN_TS_SCK1, GPIO_FN_MSIOF0L_SS2,
+	GPIO_FN_D31, GPIO_FN_ED31,
+	GPIO_FN_LCDDCK, GPIO_FN_LCDWR, GPIO_FN_DV_CKO, GPIO_FN_SIUAOSPD,
+	GPIO_FN_LCDRD, GPIO_FN_DACK2, GPIO_FN_MSIOF0L_RSYNC,
+
+
+	/* 49-5 (FN) */
+	GPIO_FN_LCDHSYN, GPIO_FN_LCDCS, GPIO_FN_LCDCS2, GPIO_FN_DACK3,
+	GPIO_FN_LCDDISP, GPIO_FN_LCDRS, GPIO_FN_DREQ3, GPIO_FN_MSIOF0L_RSCK,
+	GPIO_FN_LCDCSYN, GPIO_FN_LCDCSYN2, GPIO_FN_DV_CKI,
+	GPIO_FN_LCDLCLK, GPIO_FN_DREQ1, GPIO_FN_MSIOF0L_RXD,
+	GPIO_FN_LCDDON, GPIO_FN_LCDDON2, GPIO_FN_DACK1, GPIO_FN_MSIOF0L_TXD,
+	GPIO_FN_VIO_DR0, GPIO_FN_VIO_DR1, GPIO_FN_VIO_DR2, GPIO_FN_VIO_DR3,
+	GPIO_FN_VIO_DR4, GPIO_FN_VIO_DR5, GPIO_FN_VIO_DR6, GPIO_FN_VIO_DR7,
+	GPIO_FN_VIO_VDR, GPIO_FN_VIO_HDR,
+	GPIO_FN_VIO_CLKR, GPIO_FN_VIO_CKOR,
+	GPIO_FN_SCIFA1_TXD, GPIO_FN_GPS_PGFA0,
+	GPIO_FN_SCIFA1_SCK, GPIO_FN_GPS_PGFA1,
+	GPIO_FN_SCIFA1_RTS, GPIO_FN_GPS_EPPSINMON,
+	GPIO_FN_SCIFA1_RXD, GPIO_FN_SCIFA1_CTS,
+	GPIO_FN_MSIOF1_TXD, GPIO_FN_SCIFA1_TXD2, GPIO_FN_GPS_TXD,
+	GPIO_FN_MSIOF1_TSYNC, GPIO_FN_SCIFA1_CTS2, GPIO_FN_I2C_SDA2,
+	GPIO_FN_MSIOF1_TSCK, GPIO_FN_SCIFA1_SCK2,
+	GPIO_FN_MSIOF1_RXD, GPIO_FN_SCIFA1_RXD2, GPIO_FN_GPS_RXD,
+	GPIO_FN_MSIOF1_RSCK, GPIO_FN_SCIFA1_RTS2,
+	GPIO_FN_MSIOF1_RSYNC, GPIO_FN_I2C_SCL2,
+	GPIO_FN_MSIOF1_MCK0, GPIO_FN_MSIOF1_MCK1,
+	GPIO_FN_MSIOF1_SS1, GPIO_FN_EDBGREQ3,
+	GPIO_FN_MSIOF1_SS2,
+	GPIO_FN_PORT236_IROUT, GPIO_FN_IRDA_OUT,
+	GPIO_FN_IRDA_IN, GPIO_FN_IRDA_FIRSEL,
+	GPIO_FN_TPU1TO0, GPIO_FN_TS_SPSYNC3,
+	GPIO_FN_TPU1TO1, GPIO_FN_TS_SDAT3,
+	GPIO_FN_TPU1TO2, GPIO_FN_TS_SDEN3, GPIO_FN_PORT241_MSIOF2_SS1,
+	GPIO_FN_TPU1TO3, GPIO_FN_PORT242_MSIOF2_TSCK,
+	GPIO_FN_M13_BSW, GPIO_FN_PORT243_MSIOF2_TSYNC,
+	GPIO_FN_M14_GSW, GPIO_FN_PORT244_MSIOF2_TXD,
+	GPIO_FN_PORT245_IROUT, GPIO_FN_M15_RSW,
+	GPIO_FN_SOUT3, GPIO_FN_SCIFA2_TXD1,
+	GPIO_FN_SIN3, GPIO_FN_SCIFA2_RXD1,
+	GPIO_FN_XRTS3, GPIO_FN_SCIFA2_RTS1, GPIO_FN_PORT248_MSIOF2_SS2,
+	GPIO_FN_XCTS3, GPIO_FN_SCIFA2_CTS1, GPIO_FN_PORT249_MSIOF2_RXD,
+	GPIO_FN_DINT, GPIO_FN_SCIFA2_SCK1, GPIO_FN_TS_SCK3,
+	GPIO_FN_SDHICLK0, GPIO_FN_TCK2,
+	GPIO_FN_SDHICD0,
+	GPIO_FN_SDHID0_0, GPIO_FN_TMS2,
+	GPIO_FN_SDHID0_1, GPIO_FN_TDO2,
+	GPIO_FN_SDHID0_2, GPIO_FN_TDI2,
+	GPIO_FN_SDHID0_3, GPIO_FN_RTCK2,
+
+	/* 49-6 (FN) */
+	GPIO_FN_SDHICMD0, GPIO_FN_TRST2,
+	GPIO_FN_SDHIWP0, GPIO_FN_EDBGREQ2,
+	GPIO_FN_SDHICLK1, GPIO_FN_TCK3,
+	GPIO_FN_SDHID1_0, GPIO_FN_M11_SLCD_SO2,
+	GPIO_FN_TS_SPSYNC2, GPIO_FN_TMS3,
+	GPIO_FN_SDHID1_1, GPIO_FN_M9_SLCD_AO2,
+	GPIO_FN_TS_SDAT2, GPIO_FN_TDO3,
+	GPIO_FN_SDHID1_2, GPIO_FN_M10_SLCD_CK2,
+	GPIO_FN_TS_SDEN2, GPIO_FN_TDI3,
+	GPIO_FN_SDHID1_3, GPIO_FN_M12_SLCD_CE2,
+	GPIO_FN_TS_SCK2, GPIO_FN_RTCK3,
+	GPIO_FN_SDHICMD1, GPIO_FN_TRST3,
+	GPIO_FN_SDHICLK2, GPIO_FN_SCIFB_SCK,
+	GPIO_FN_SDHID2_0, GPIO_FN_SCIFB_TXD,
+	GPIO_FN_SDHID2_1, GPIO_FN_SCIFB_CTS,
+	GPIO_FN_SDHID2_2, GPIO_FN_SCIFB_RXD,
+	GPIO_FN_SDHID2_3, GPIO_FN_SCIFB_RTS,
+	GPIO_FN_SDHICMD2,
+	GPIO_FN_RESETOUTS,
+	GPIO_FN_DIVLOCK,
+};
+
+#endif /* __ASM_SH7367_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
new file mode 100644
index 0000000..dc34f00
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2010 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef __ASM_SH7372_H__
+#define __ASM_SH7372_H__
+
+/*
+ * Pin Function Controller:
+ *	GPIO_FN_xx - GPIO used to select pin function
+ *	GPIO_PORTxx - GPIO mapped to real I/O pin on CPU
+ */
+enum {
+	/* PORT */
+	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_PORT119,
+
+	GPIO_PORT120, GPIO_PORT121, GPIO_PORT122, GPIO_PORT123, GPIO_PORT124,
+	GPIO_PORT125, GPIO_PORT126, GPIO_PORT127, 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_PORT165, GPIO_PORT166, GPIO_PORT167, GPIO_PORT168, GPIO_PORT169,
+
+	GPIO_PORT170, GPIO_PORT171, GPIO_PORT172, GPIO_PORT173, GPIO_PORT174,
+	GPIO_PORT175, GPIO_PORT176, GPIO_PORT177, GPIO_PORT178, GPIO_PORT179,
+
+	GPIO_PORT180, GPIO_PORT181, GPIO_PORT182, GPIO_PORT183, GPIO_PORT184,
+	GPIO_PORT185, GPIO_PORT186, GPIO_PORT187, GPIO_PORT188, GPIO_PORT189,
+
+	GPIO_PORT190,
+
+	/* IRQ */
+	GPIO_FN_IRQ0_6,		/* PORT   6 */
+	GPIO_FN_IRQ0_162,	/* PORT 162 */
+	GPIO_FN_IRQ1,		/* PORT  12 */
+	GPIO_FN_IRQ2_4,		/* PORT   4 */
+	GPIO_FN_IRQ2_5,		/* PORT   5 */
+	GPIO_FN_IRQ3_8,		/* PORT   8 */
+	GPIO_FN_IRQ3_16,	/* PORT  16 */
+	GPIO_FN_IRQ4_17,	/* PORT  17 */
+	GPIO_FN_IRQ4_163,	/* PORT 163 */
+	GPIO_FN_IRQ5,		/* PORT  18 */
+	GPIO_FN_IRQ6_39,	/* PORT  39 */
+	GPIO_FN_IRQ6_164,	/* PORT 164 */
+	GPIO_FN_IRQ7_40,	/* PORT  40 */
+	GPIO_FN_IRQ7_167,	/* PORT 167 */
+	GPIO_FN_IRQ8_41,	/* PORT  41 */
+	GPIO_FN_IRQ8_168,	/* PORT 168 */
+	GPIO_FN_IRQ9_42,	/* PORT  42 */
+	GPIO_FN_IRQ9_169,	/* PORT 169 */
+	GPIO_FN_IRQ10,		/* PORT  65 */
+	GPIO_FN_IRQ11,		/* PORT  67 */
+	GPIO_FN_IRQ12_80,	/* PORT  80 */
+	GPIO_FN_IRQ12_137,	/* PORT 137 */
+	GPIO_FN_IRQ13_81,	/* PORT  81 */
+	GPIO_FN_IRQ13_145,	/* PORT 145 */
+	GPIO_FN_IRQ14_82,	/* PORT  82 */
+	GPIO_FN_IRQ14_146,	/* PORT 146 */
+	GPIO_FN_IRQ15_83,	/* PORT  83 */
+	GPIO_FN_IRQ15_147,	/* PORT 147 */
+	GPIO_FN_IRQ16_84,	/* PORT  84 */
+	GPIO_FN_IRQ16_170,	/* PORT 170 */
+	GPIO_FN_IRQ17,		/* PORT  85 */
+	GPIO_FN_IRQ18,		/* PORT  86 */
+	GPIO_FN_IRQ19,		/* PORT  87 */
+	GPIO_FN_IRQ20,		/* PORT  92 */
+	GPIO_FN_IRQ21,		/* PORT  93 */
+	GPIO_FN_IRQ22,		/* PORT  94 */
+	GPIO_FN_IRQ23,		/* PORT  95 */
+	GPIO_FN_IRQ24,		/* PORT 112 */
+	GPIO_FN_IRQ25,		/* PORT 119 */
+	GPIO_FN_IRQ26_121,	/* PORT 121 */
+	GPIO_FN_IRQ26_172,	/* PORT 172 */
+	GPIO_FN_IRQ27_122,	/* PORT 122 */
+	GPIO_FN_IRQ27_180,	/* PORT 180 */
+	GPIO_FN_IRQ28_123,	/* PORT 123 */
+	GPIO_FN_IRQ28_181,	/* PORT 181 */
+	GPIO_FN_IRQ29_129,	/* PORT 129 */
+	GPIO_FN_IRQ29_182,	/* PORT 182 */
+	GPIO_FN_IRQ30_130,	/* PORT 130 */
+	GPIO_FN_IRQ30_183,	/* PORT 183 */
+	GPIO_FN_IRQ31_138,	/* PORT 138 */
+	GPIO_FN_IRQ31_184,	/* PORT 184 */
+
+	/*
+	 * MSIOF0	(PORT 36, 37, 38, 39
+	 * 		      40, 41, 42, 43, 44, 45)
+	 */
+	GPIO_FN_MSIOF0_TSYNC,	GPIO_FN_MSIOF0_TSCK,
+	GPIO_FN_MSIOF0_RXD,	GPIO_FN_MSIOF0_RSCK,
+	GPIO_FN_MSIOF0_RSYNC,	GPIO_FN_MSIOF0_MCK0,
+	GPIO_FN_MSIOF0_MCK1,	GPIO_FN_MSIOF0_SS1,
+	GPIO_FN_MSIOF0_SS2,	GPIO_FN_MSIOF0_TXD,
+
+	/*
+	 * MSIOF1	(PORT 39, 40, 41, 42, 43, 44
+	 * 		      84, 85, 86, 87, 88, 89, 90, 91, 92, 93)
+	 */
+	GPIO_FN_MSIOF1_TSCK_39,	GPIO_FN_MSIOF1_TSYNC_40,
+	GPIO_FN_MSIOF1_TSCK_88,	GPIO_FN_MSIOF1_TSYNC_89,
+	GPIO_FN_MSIOF1_TXD_41,	GPIO_FN_MSIOF1_RXD_42,
+	GPIO_FN_MSIOF1_TXD_90,	GPIO_FN_MSIOF1_RXD_91,
+	GPIO_FN_MSIOF1_SS1_43,	GPIO_FN_MSIOF1_SS2_44,
+	GPIO_FN_MSIOF1_SS1_92,	GPIO_FN_MSIOF1_SS2_93,
+	GPIO_FN_MSIOF1_RSCK,	GPIO_FN_MSIOF1_RSYNC,
+	GPIO_FN_MSIOF1_MCK0,	GPIO_FN_MSIOF1_MCK1,
+
+	/*
+	 * MSIOF2	(PORT 134, 135, 136, 137, 138, 139
+	 *		      148, 149, 150, 151)
+	 */
+	GPIO_FN_MSIOF2_RSCK,	GPIO_FN_MSIOF2_RSYNC,
+	GPIO_FN_MSIOF2_MCK0,	GPIO_FN_MSIOF2_MCK1,
+	GPIO_FN_MSIOF2_SS1,	GPIO_FN_MSIOF2_SS2,
+	GPIO_FN_MSIOF2_TSYNC,	GPIO_FN_MSIOF2_TSCK,
+	GPIO_FN_MSIOF2_RXD,	GPIO_FN_MSIOF2_TXD,
+
+	/* MSIOF3	(PORT 76, 77, 78, 79, 80, 81, 82, 83) */
+	GPIO_FN_BBIF1_RXD,	GPIO_FN_BBIF1_TSYNC,
+	GPIO_FN_BBIF1_TSCK,	GPIO_FN_BBIF1_TXD,
+	GPIO_FN_BBIF1_RSCK,	GPIO_FN_BBIF1_RSYNC,
+	GPIO_FN_BBIF1_FLOW,	GPIO_FN_BB_RX_FLOW_N,
+
+	/* MSIOF4	(PORT 0, 1, 2, 3) */
+	GPIO_FN_BBIF2_TSCK1,	GPIO_FN_BBIF2_TSYNC1,
+	GPIO_FN_BBIF2_TXD1,	GPIO_FN_BBIF2_RXD,
+
+	/* FSI		(PORT 4, 5, 6, 7, 8, 9, 10, 11, 15) */
+	GPIO_FN_FSIACK,		GPIO_FN_FSIBCK,
+	GPIO_FN_FSIAILR,	GPIO_FN_FSIAIBT,
+	GPIO_FN_FSIAISLD,	GPIO_FN_FSIAOMC,
+	GPIO_FN_FSIAOLR,	GPIO_FN_FSIAOBT,
+	GPIO_FN_FSIAOSLD,	GPIO_FN_FSIASPDIF_11,
+	GPIO_FN_FSIASPDIF_15,
+
+	/* FMSI		(PORT 12, 13, 14, 15, 16, 17, 18, 65) */
+	GPIO_FN_FMSOCK,		GPIO_FN_FMSOOLR,
+	GPIO_FN_FMSIOLR,	GPIO_FN_FMSOOBT,
+	GPIO_FN_FMSIOBT,	GPIO_FN_FMSOSLD,
+	GPIO_FN_FMSOILR,	GPIO_FN_FMSIILR,
+	GPIO_FN_FMSOIBT,	GPIO_FN_FMSIIBT,
+	GPIO_FN_FMSISLD,	GPIO_FN_FMSICK,
+
+	/* SCIFA0	(PORT 152, 153, 156, 157, 158) */
+	GPIO_FN_SCIFA0_TXD,	GPIO_FN_SCIFA0_RXD,
+	GPIO_FN_SCIFA0_SCK,	GPIO_FN_SCIFA0_RTS,
+	GPIO_FN_SCIFA0_CTS,
+
+	/* SCIFA1	(PORT 154, 155, 159, 160, 161) */
+	GPIO_FN_SCIFA1_TXD,	GPIO_FN_SCIFA1_RXD,
+	GPIO_FN_SCIFA1_SCK,	GPIO_FN_SCIFA1_RTS,
+	GPIO_FN_SCIFA1_CTS,
+
+	/* SCIFA2	(PORT 94, 95, 96, 97, 98) */
+	GPIO_FN_SCIFA2_CTS1,	GPIO_FN_SCIFA2_RTS1,
+	GPIO_FN_SCIFA2_TXD1,	GPIO_FN_SCIFA2_RXD1,
+	GPIO_FN_SCIFA2_SCK1,
+
+	/* SCIFA3	(PORT 43, 44,
+			     140, 141, 142, 143, 144) */
+	GPIO_FN_SCIFA3_CTS_43,	GPIO_FN_SCIFA3_CTS_140,
+	GPIO_FN_SCIFA3_RTS_44,	GPIO_FN_SCIFA3_RTS_141,
+	GPIO_FN_SCIFA3_SCK,	GPIO_FN_SCIFA3_TXD,
+	GPIO_FN_SCIFA3_RXD,
+
+	/* SCIFA4	(PORT 5, 6) */
+	GPIO_FN_SCIFA4_RXD,	GPIO_FN_SCIFA4_TXD,
+
+	/* SCIFA5	(PORT 8, 12) */
+	GPIO_FN_SCIFA5_RXD,	GPIO_FN_SCIFA5_TXD,
+
+	/* SCIFB	(PORT 162, 163, 164, 165, 166) */
+	GPIO_FN_SCIFB_SCK,	GPIO_FN_SCIFB_RTS,
+	GPIO_FN_SCIFB_CTS,	GPIO_FN_SCIFB_TXD,
+	GPIO_FN_SCIFB_RXD,
+
+	/*
+	 * CEU		(PORT 16, 17,
+	 *		      100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+	 *		      110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+	 *		      120)
+	 */
+	GPIO_FN_VIO_HD,		GPIO_FN_VIO_CKO1,	GPIO_FN_VIO_CKO2,
+	GPIO_FN_VIO_VD,		GPIO_FN_VIO_CLK,	GPIO_FN_VIO_FIELD,
+	GPIO_FN_VIO_CKO,
+	GPIO_FN_VIO_D0,		GPIO_FN_VIO_D1,		GPIO_FN_VIO_D2,
+	GPIO_FN_VIO_D3,		GPIO_FN_VIO_D4,		GPIO_FN_VIO_D5,
+	GPIO_FN_VIO_D6,		GPIO_FN_VIO_D7,		GPIO_FN_VIO_D8,
+	GPIO_FN_VIO_D9,		GPIO_FN_VIO_D10,	GPIO_FN_VIO_D11,
+	GPIO_FN_VIO_D12,	GPIO_FN_VIO_D13,	GPIO_FN_VIO_D14,
+	GPIO_FN_VIO_D15,
+
+	/* USB0		(PORT 113, 114, 115, 116, 117, 167) */
+	GPIO_FN_IDIN_0,		GPIO_FN_EXTLP_0,
+	GPIO_FN_OVCN2_0,	GPIO_FN_PWEN_0,
+	GPIO_FN_OVCN_0,		GPIO_FN_VBUS0_0,
+
+	/* USB1		(PORT 18, 113, 114, 115, 116, 117, 138, 162, 168) */
+	GPIO_FN_IDIN_1_18,	GPIO_FN_IDIN_1_113,
+	GPIO_FN_PWEN_1_115,	GPIO_FN_PWEN_1_138,
+	GPIO_FN_OVCN_1_114,	GPIO_FN_OVCN_1_162,
+	GPIO_FN_EXTLP_1,	GPIO_FN_OVCN2_1,
+	GPIO_FN_VBUS0_1,
+
+	/* GPIO		(PORT 41, 42, 43, 44) */
+	GPIO_FN_GPI0,	GPIO_FN_GPI1,	GPIO_FN_GPO0,	GPIO_FN_GPO1,
+
+	/*
+	 * BSC		(PORT 19,
+	 *		      20, 21, 22, 25, 26, 27, 28, 29,
+	 *		      30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+	 *		      40, 41, 42, 43, 44, 45,
+	 *		      62, 63, 64, 65, 66, 67,
+	 *		      71, 72, 74, 75)
+	 */
+	GPIO_FN_BS,	GPIO_FN_WE1,
+	GPIO_FN_CKO,	GPIO_FN_WAIT,	GPIO_FN_RDWR,
+
+	GPIO_FN_A0,	GPIO_FN_A1,	GPIO_FN_A2,	GPIO_FN_A3,
+	GPIO_FN_A6,	GPIO_FN_A7,	GPIO_FN_A8,	GPIO_FN_A9,
+	GPIO_FN_A10,	GPIO_FN_A11,	GPIO_FN_A12,	GPIO_FN_A13,
+	GPIO_FN_A14,	GPIO_FN_A15,	GPIO_FN_A16,	GPIO_FN_A17,
+	GPIO_FN_A18,	GPIO_FN_A19,	GPIO_FN_A20,	GPIO_FN_A21,
+	GPIO_FN_A22,	GPIO_FN_A23,	GPIO_FN_A24,	GPIO_FN_A25,
+	GPIO_FN_A26,
+
+	GPIO_FN_CS0,	GPIO_FN_CS2,	GPIO_FN_CS4,
+	GPIO_FN_CS5A,	GPIO_FN_CS5B,	GPIO_FN_CS6A,
+
+	/*
+	 * BSC/FLCTL		(PORT 23, 24,
+	 *			      46, 47, 48, 49,
+	 *			      50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+	 *			      60, 61, 69, 70)
+	 */
+	GPIO_FN_RD_FSC,		GPIO_FN_WE0_FWE,
+	GPIO_FN_A4_FOE,		GPIO_FN_A5_FCDE,
+	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,
+
+	/*
+	 * MMCIF(1)		(PORT 84, 85, 86, 87, 88, 89,
+	 *			      90, 91, 92, 99)
+	 */
+	GPIO_FN_MMCD0_0,	GPIO_FN_MMCD0_1,	GPIO_FN_MMCD0_2,
+	GPIO_FN_MMCD0_3,	GPIO_FN_MMCD0_4,	GPIO_FN_MMCD0_5,
+	GPIO_FN_MMCD0_6,	GPIO_FN_MMCD0_7,
+	GPIO_FN_MMCCMD0,	GPIO_FN_MMCCLK0,
+
+	/* MMCIF(2)		(PORT 54, 55, 56, 57, 58, 59, 60, 61, 66, 67) */
+	GPIO_FN_MMCD1_0,	GPIO_FN_MMCD1_1,	GPIO_FN_MMCD1_2,
+	GPIO_FN_MMCD1_3,	GPIO_FN_MMCD1_4,	GPIO_FN_MMCD1_5,
+	GPIO_FN_MMCD1_6,	GPIO_FN_MMCD1_7,
+	GPIO_FN_MMCCLK1,	GPIO_FN_MMCCMD1,
+
+	/* SPU2		(PORT 65) */
+	GPIO_FN_VINT_I,
+
+	/* FLCTL	(PORT 66, 68, 73) */
+	GPIO_FN_FCE1,	GPIO_FN_FCE0,	GPIO_FN_FRB,
+
+	/* HSI		(PORT 76, 77, 78, 79, 80, 81, 82, 83) */
+	GPIO_FN_GP_RX_FLAG,	GPIO_FN_GP_RX_DATA,	GPIO_FN_GP_TX_READY,
+	GPIO_FN_GP_RX_WAKE,	GPIO_FN_MP_TX_FLAG,	GPIO_FN_MP_TX_DATA,
+	GPIO_FN_MP_RX_READY,	GPIO_FN_MP_TX_WAKE,
+
+	/*
+	 * MFI		(PORT 76, 77, 78, 79,
+	 *		      80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+	 *		      90, 91, 92, 93, 94, 95, 96, 97, 98, 99)
+	 */
+	GPIO_FN_MFIv6,	/* see MSEL4CR 6 */
+	GPIO_FN_MFIv4,	/* see MSEL4CR 6 */
+
+	GPIO_FN_MEMC_CS0,		GPIO_FN_MEMC_BUSCLK_MEMC_A0,
+	GPIO_FN_MEMC_CS1_MEMC_A1,	GPIO_FN_MEMC_ADV_MEMC_DREQ0,
+	GPIO_FN_MEMC_WAIT_MEMC_DREQ1,	GPIO_FN_MEMC_NOE,
+	GPIO_FN_MEMC_NWE,		GPIO_FN_MEMC_INT,
+
+	GPIO_FN_MEMC_AD0,	GPIO_FN_MEMC_AD1,	GPIO_FN_MEMC_AD2,
+	GPIO_FN_MEMC_AD3,	GPIO_FN_MEMC_AD4,	GPIO_FN_MEMC_AD5,
+	GPIO_FN_MEMC_AD6,	GPIO_FN_MEMC_AD7,	GPIO_FN_MEMC_AD8,
+	GPIO_FN_MEMC_AD9,	GPIO_FN_MEMC_AD10,	GPIO_FN_MEMC_AD11,
+	GPIO_FN_MEMC_AD12,	GPIO_FN_MEMC_AD13,	GPIO_FN_MEMC_AD14,
+	GPIO_FN_MEMC_AD15,
+
+	/* SIM		(PORT 94, 95, 98) */
+	GPIO_FN_SIM_RST,	GPIO_FN_SIM_CLK,	GPIO_FN_SIM_D,
+
+	/* TPU		(PORT 93, 99, 112, 160, 161) */
+	GPIO_FN_TPU0TO0,	GPIO_FN_TPU0TO1,
+	GPIO_FN_TPU0TO2_93,	GPIO_FN_TPU0TO2_99,
+	GPIO_FN_TPU0TO3,
+
+	/* I2C2		(PORT 110, 111) */
+	GPIO_FN_I2C_SCL2,	GPIO_FN_I2C_SDA2,
+
+	/* I2C3(1)	(PORT 114, 115) */
+	GPIO_FN_I2C_SCL3,	GPIO_FN_I2C_SDA3,
+
+	/* I2C3(2)	(PORT 137, 145) */
+	GPIO_FN_I2C_SCL3S,	GPIO_FN_I2C_SDA3S,
+
+	/* I2C4(2)	(PORT 116, 117) */
+	GPIO_FN_I2C_SCL4,	GPIO_FN_I2C_SDA4,
+
+	/* I2C4(2)	(PORT 146, 147) */
+	GPIO_FN_I2C_SCL4S,	GPIO_FN_I2C_SDA4S,
+
+	/*
+	 * KEYSC	(PORT 121, 122, 123, 124, 125, 126, 127, 128, 129,
+	 *		      130, 131, 132, 133, 134, 135, 136)
+	 */
+	GPIO_FN_KEYOUT0,	GPIO_FN_KEYIN0_121,	GPIO_FN_KEYIN0_136,
+	GPIO_FN_KEYOUT1,	GPIO_FN_KEYIN1_122,	GPIO_FN_KEYIN1_135,
+	GPIO_FN_KEYOUT2,	GPIO_FN_KEYIN2_123,	GPIO_FN_KEYIN2_134,
+	GPIO_FN_KEYOUT3,	GPIO_FN_KEYIN3_124,	GPIO_FN_KEYIN3_133,
+	GPIO_FN_KEYOUT4,	GPIO_FN_KEYIN4,
+	GPIO_FN_KEYOUT5,	GPIO_FN_KEYIN5,
+	GPIO_FN_KEYOUT6,	GPIO_FN_KEYIN6,
+	GPIO_FN_KEYOUT7,	GPIO_FN_KEYIN7,
+
+	/*
+	 * LCDC		(PORT      121, 122, 123, 124, 125, 126, 127, 128, 129,
+	 *		      130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+	 *		      140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+	 *		      150, 151)
+	 */
+	GPIO_FN_LCDC0_SELECT, /* LCDC 0 */
+	GPIO_FN_LCDC1_SELECT, /* LCDC 1 */
+	GPIO_FN_LCDHSYN,	GPIO_FN_LCDCS,	GPIO_FN_LCDVSYN,
+	GPIO_FN_LCDDCK,		GPIO_FN_LCDWR,	GPIO_FN_LCDRD,
+	GPIO_FN_LCDDISP,	GPIO_FN_LCDRS,	GPIO_FN_LCDLCLK,
+	GPIO_FN_LCDDON,
+
+	GPIO_FN_LCDD0,	GPIO_FN_LCDD1,	GPIO_FN_LCDD2,	GPIO_FN_LCDD3,
+	GPIO_FN_LCDD4,	GPIO_FN_LCDD5,	GPIO_FN_LCDD6,	GPIO_FN_LCDD7,
+	GPIO_FN_LCDD8,	GPIO_FN_LCDD9,	GPIO_FN_LCDD10,	GPIO_FN_LCDD11,
+	GPIO_FN_LCDD12,	GPIO_FN_LCDD13,	GPIO_FN_LCDD14,	GPIO_FN_LCDD15,
+	GPIO_FN_LCDD16,	GPIO_FN_LCDD17,	GPIO_FN_LCDD18,	GPIO_FN_LCDD19,
+	GPIO_FN_LCDD20,	GPIO_FN_LCDD21,	GPIO_FN_LCDD22,	GPIO_FN_LCDD23,
+
+	/* IRDA		(PORT 139, 140, 141, 142) */
+	GPIO_FN_IRDA_OUT,	GPIO_FN_IRDA_IN,	GPIO_FN_IRDA_FIRSEL,
+	GPIO_FN_IROUT_139,	GPIO_FN_IROUT_140,
+
+	/* TSIF1	(PORT 156, 157, 158, 159) */
+	GPIO_FN_TS0_1SELECT, /* TSIF0 - 1 select */
+	GPIO_FN_TS0_2SELECT, /* TSIF0 - 2 select */
+	GPIO_FN_TS1_1SELECT, /* TSIF1 - 1 select */
+	GPIO_FN_TS1_2SELECT, /* TSIF1 - 2 select */
+
+	GPIO_FN_TS_SPSYNC1,	GPIO_FN_TS_SDAT1,
+	GPIO_FN_TS_SDEN1,	GPIO_FN_TS_SCK1,
+
+	/* TSIF2	(PORT 137, 145, 146, 147) */
+	GPIO_FN_TS_SPSYNC2,	GPIO_FN_TS_SDAT2,
+	GPIO_FN_TS_SDEN2,	GPIO_FN_TS_SCK2,
+
+	/* HDMI		(PORT 169, 170) */
+	GPIO_FN_HDMI_HPD,	GPIO_FN_HDMI_CEC,
+
+	/* SDHI0	(PORT 171, 172, 173, 174, 175, 176, 177, 178) */
+	GPIO_FN_SDHICLK0,	GPIO_FN_SDHICD0,
+	GPIO_FN_SDHICMD0,	GPIO_FN_SDHIWP0,
+	GPIO_FN_SDHID0_0,	GPIO_FN_SDHID0_1,
+	GPIO_FN_SDHID0_2,	GPIO_FN_SDHID0_3,
+
+	/* SDHI1	(PORT 179, 180, 181, 182, 183, 184) */
+	GPIO_FN_SDHICLK1,	GPIO_FN_SDHICMD1,	GPIO_FN_SDHID1_0,
+	GPIO_FN_SDHID1_1,	GPIO_FN_SDHID1_2,	GPIO_FN_SDHID1_3,
+
+	/* SDHI2	(PORT 185, 186, 187, 188, 189, 190) */
+	GPIO_FN_SDHICLK2,	GPIO_FN_SDHICMD2,	GPIO_FN_SDHID2_0,
+	GPIO_FN_SDHID2_1,	GPIO_FN_SDHID2_2,	GPIO_FN_SDHID2_3,
+
+	/* SDENC	see MSEL4CR 19 */
+	GPIO_FN_SDENC_CPG,
+	GPIO_FN_SDENC_DV_CLKI,
+};
+
+#endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7377.h b/arch/arm/mach-shmobile/include/mach/sh7377.h
new file mode 100644
index 0000000..f580e22
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/sh7377.h
@@ -0,0 +1,360 @@
+#ifndef __ASM_SH7377_H__
+#define __ASM_SH7377_H__
+
+/* Pin Function Controller:
+ * GPIO_FN_xx - GPIO used to select pin function
+ * GPIO_PORTxx - GPIO mapped to real I/O pin on CPU
+ */
+enum {
+	/* 55-1 -> 55-5 (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,
+
+	/* Special Pull-up / Pull-down Functions */
+	GPIO_FN_PORT66_KEYIN0_PU, GPIO_FN_PORT67_KEYIN1_PU,
+	GPIO_FN_PORT68_KEYIN2_PU, GPIO_FN_PORT69_KEYIN3_PU,
+	GPIO_FN_PORT70_KEYIN4_PU, GPIO_FN_PORT71_KEYIN5_PU,
+	GPIO_FN_PORT72_KEYIN6_PU,
+
+	/* 55-1 (FN) */
+	GPIO_FN_VBUS_0,
+	GPIO_FN_CPORT0,
+	GPIO_FN_CPORT1,
+	GPIO_FN_CPORT2,
+	GPIO_FN_CPORT3,
+	GPIO_FN_CPORT4,
+	GPIO_FN_CPORT5,
+	GPIO_FN_CPORT6,
+	GPIO_FN_CPORT7,
+	GPIO_FN_CPORT8,
+	GPIO_FN_CPORT9,
+	GPIO_FN_CPORT10,
+	GPIO_FN_CPORT11, GPIO_FN_SIN2,
+	GPIO_FN_CPORT12, GPIO_FN_XCTS2,
+	GPIO_FN_CPORT13, GPIO_FN_RFSPO4,
+	GPIO_FN_CPORT14, GPIO_FN_RFSPO5,
+	GPIO_FN_CPORT15, GPIO_FN_SCIFA0_SCK, GPIO_FN_GPS_AGC2,
+	GPIO_FN_CPORT16, GPIO_FN_SCIFA0_TXD, GPIO_FN_GPS_AGC3,
+	GPIO_FN_CPORT17_IC_OE, GPIO_FN_SOUT2,
+	GPIO_FN_CPORT18, GPIO_FN_XRTS2, GPIO_FN_PORT19_VIO_CKO2,
+	GPIO_FN_CPORT19_MPORT1,
+	GPIO_FN_CPORT20, GPIO_FN_RFSPO6,
+	GPIO_FN_CPORT21, GPIO_FN_STATUS0,
+	GPIO_FN_CPORT22, GPIO_FN_STATUS1,
+	GPIO_FN_CPORT23, GPIO_FN_STATUS2, GPIO_FN_RFSPO7,
+	GPIO_FN_B_SYNLD1,
+	GPIO_FN_B_SYNLD2, GPIO_FN_SYSENMSK,
+	GPIO_FN_XMAINPS,
+	GPIO_FN_XDIVPS,
+	GPIO_FN_XIDRST,
+	GPIO_FN_IDCLK, GPIO_FN_IC_DP,
+	GPIO_FN_IDIO, GPIO_FN_IC_DM,
+	GPIO_FN_SOUT1, GPIO_FN_SCIFA4_TXD, GPIO_FN_M02_BERDAT,
+	GPIO_FN_SIN1, GPIO_FN_SCIFA4_RXD, GPIO_FN_XWUP,
+	GPIO_FN_XRTS1, GPIO_FN_SCIFA4_RTS, GPIO_FN_M03_BERCLK,
+	GPIO_FN_XCTS1, GPIO_FN_SCIFA4_CTS,
+	GPIO_FN_PCMCLKO,
+	GPIO_FN_SYNC8KO,
+
+	/* 55-2 (FN) */
+	GPIO_FN_DNPCM_A,
+	GPIO_FN_UPPCM_A,
+	GPIO_FN_VACK,
+	GPIO_FN_XTALB1L,
+	GPIO_FN_GPS_AGC1, GPIO_FN_SCIFA0_RTS,
+	GPIO_FN_GPS_AGC4, GPIO_FN_SCIFA0_RXD,
+	GPIO_FN_GPS_PWRDOWN, GPIO_FN_SCIFA0_CTS,
+	GPIO_FN_GPS_IM,
+	GPIO_FN_GPS_IS,
+	GPIO_FN_GPS_QM,
+	GPIO_FN_GPS_QS,
+	GPIO_FN_FMSOCK, GPIO_FN_PORT49_IRDA_OUT, GPIO_FN_PORT49_IROUT,
+	GPIO_FN_FMSOOLR, GPIO_FN_BBIF2_TSYNC2, GPIO_FN_TPU2TO2, GPIO_FN_IPORT3,
+	GPIO_FN_FMSIOLR,
+	GPIO_FN_FMSOOBT, GPIO_FN_BBIF2_TSCK2, GPIO_FN_TPU2TO3, GPIO_FN_OPORT1,
+	GPIO_FN_FMSIOBT,
+	GPIO_FN_FMSOSLD, GPIO_FN_BBIF2_TXD2, GPIO_FN_OPORT2,
+	GPIO_FN_FMSOILR, GPIO_FN_PORT53_IRDA_IN, GPIO_FN_TPU3TO3,
+	GPIO_FN_OPORT3, GPIO_FN_FMSIILR,
+	GPIO_FN_FMSOIBT, GPIO_FN_PORT54_IRDA_FIRSEL, GPIO_FN_TPU3TO2,
+	GPIO_FN_FMSIIBT,
+	GPIO_FN_FMSISLD, GPIO_FN_MFG0_OUT1, GPIO_FN_TPU0TO0,
+	GPIO_FN_A0_EA0, GPIO_FN_BS,
+	GPIO_FN_A12_EA12, GPIO_FN_PORT58_VIO_CKOR, GPIO_FN_TPU4TO2,
+	GPIO_FN_A13_EA13, GPIO_FN_PORT59_IROUT, GPIO_FN_MFG0_OUT2,
+	GPIO_FN_TPU0TO1,
+	GPIO_FN_A14_EA14, GPIO_FN_PORT60_KEYOUT5,
+	GPIO_FN_A15_EA15, GPIO_FN_PORT61_KEYOUT4,
+	GPIO_FN_A16_EA16, GPIO_FN_PORT62_KEYOUT3, GPIO_FN_MSIOF0_SS1,
+	GPIO_FN_A17_EA17, GPIO_FN_PORT63_KEYOUT2, GPIO_FN_MSIOF0_TSYNC,
+	GPIO_FN_A18_EA18, GPIO_FN_PORT64_KEYOUT1, GPIO_FN_MSIOF0_TSCK,
+	GPIO_FN_A19_EA19, GPIO_FN_PORT65_KEYOUT0, GPIO_FN_MSIOF0_TXD,
+	GPIO_FN_A20_EA20, GPIO_FN_PORT66_KEYIN0, GPIO_FN_MSIOF0_RSCK,
+	GPIO_FN_A21_EA21, GPIO_FN_PORT67_KEYIN1, GPIO_FN_MSIOF0_RSYNC,
+	GPIO_FN_A22_EA22, GPIO_FN_PORT68_KEYIN2, GPIO_FN_MSIOF0_MCK0,
+	GPIO_FN_A23_EA23, GPIO_FN_PORT69_KEYIN3, GPIO_FN_MSIOF0_MCK1,
+	GPIO_FN_A24_EA24, GPIO_FN_PORT70_KEYIN4, GPIO_FN_MSIOF0_RXD,
+	GPIO_FN_A25_EA25, GPIO_FN_PORT71_KEYIN5, GPIO_FN_MSIOF0_SS2,
+	GPIO_FN_A26, GPIO_FN_PORT72_KEYIN6,
+	GPIO_FN_D0_ED0_NAF0,
+	GPIO_FN_D1_ED1_NAF1,
+	GPIO_FN_D2_ED2_NAF2,
+	GPIO_FN_D3_ED3_NAF3,
+	GPIO_FN_D4_ED4_NAF4,
+	GPIO_FN_D5_ED5_NAF5,
+	GPIO_FN_D6_ED6_NAF6,
+	GPIO_FN_D7_ED7_NAF7,
+	GPIO_FN_D8_ED8_NAF8,
+	GPIO_FN_D9_ED9_NAF9,
+	GPIO_FN_D10_ED10_NAF10,
+	GPIO_FN_D11_ED11_NAF11,
+	GPIO_FN_D12_ED12_NAF12,
+	GPIO_FN_D13_ED13_NAF13,
+	GPIO_FN_D14_ED14_NAF14,
+	GPIO_FN_D15_ED15_NAF15,
+	GPIO_FN_CS4,
+	GPIO_FN_CS5A, GPIO_FN_FMSICK,
+	GPIO_FN_CS5B, GPIO_FN_FCE1,
+
+	/* 55-3 (FN) */
+	GPIO_FN_CS6B, GPIO_FN_XCS2, GPIO_FN_CS6A, GPIO_FN_DACK0,
+	GPIO_FN_FCE0,
+	GPIO_FN_WAIT, GPIO_FN_DREQ0,
+	GPIO_FN_RD_XRD,
+	GPIO_FN_WE0_XWR0_FWE,
+	GPIO_FN_WE1_XWR1,
+	GPIO_FN_FRB,
+	GPIO_FN_CKO,
+	GPIO_FN_NBRSTOUT,
+	GPIO_FN_NBRST,
+	GPIO_FN_GPS_EPPSIN,
+	GPIO_FN_LATCHPULSE,
+	GPIO_FN_LTESIGNAL,
+	GPIO_FN_LEGACYSTATE,
+	GPIO_FN_TCKON,
+	GPIO_FN_VIO_VD, GPIO_FN_PORT128_KEYOUT0, GPIO_FN_IPORT0,
+	GPIO_FN_VIO_HD, GPIO_FN_PORT129_KEYOUT1, GPIO_FN_IPORT1,
+	GPIO_FN_VIO_D0, GPIO_FN_PORT130_KEYOUT2, GPIO_FN_PORT130_MSIOF2_RXD,
+	GPIO_FN_VIO_D1, GPIO_FN_PORT131_KEYOUT3, GPIO_FN_PORT131_MSIOF2_SS1,
+	GPIO_FN_VIO_D2, GPIO_FN_PORT132_KEYOUT4, GPIO_FN_PORT132_MSIOF2_SS2,
+	GPIO_FN_VIO_D3, GPIO_FN_PORT133_KEYOUT5, GPIO_FN_PORT133_MSIOF2_TSYNC,
+	GPIO_FN_VIO_D4, GPIO_FN_PORT134_KEYIN0, GPIO_FN_PORT134_MSIOF2_TXD,
+	GPIO_FN_VIO_D5, GPIO_FN_PORT135_KEYIN1, GPIO_FN_PORT135_MSIOF2_TSCK,
+	GPIO_FN_VIO_D6, GPIO_FN_PORT136_KEYIN2,
+	GPIO_FN_VIO_D7, GPIO_FN_PORT137_KEYIN3,
+	GPIO_FN_VIO_D8, GPIO_FN_M9_SLCD_A01, GPIO_FN_PORT138_FSIAOMC,
+	GPIO_FN_VIO_D9, GPIO_FN_M10_SLCD_CK1, GPIO_FN_PORT139_FSIAOLR,
+	GPIO_FN_VIO_D10, GPIO_FN_M11_SLCD_SO1, GPIO_FN_TPU0TO2,
+	GPIO_FN_PORT140_FSIAOBT,
+	GPIO_FN_VIO_D11, GPIO_FN_M12_SLCD_CE1, GPIO_FN_TPU0TO3,
+	GPIO_FN_PORT141_FSIAOSLD,
+	GPIO_FN_VIO_D12, GPIO_FN_M13_BSW, GPIO_FN_PORT142_FSIACK,
+	GPIO_FN_VIO_D13, GPIO_FN_M14_GSW, GPIO_FN_PORT143_FSIAILR,
+	GPIO_FN_VIO_D14, GPIO_FN_M15_RSW, GPIO_FN_PORT144_FSIAIBT,
+	GPIO_FN_VIO_D15, GPIO_FN_TPU1TO3, GPIO_FN_PORT145_FSIAISLD,
+	GPIO_FN_VIO_CLK, GPIO_FN_PORT146_KEYIN4, GPIO_FN_IPORT2,
+	GPIO_FN_VIO_FIELD, GPIO_FN_PORT147_KEYIN5,
+	GPIO_FN_VIO_CKO, GPIO_FN_PORT148_KEYIN6,
+	GPIO_FN_A27, GPIO_FN_RDWR_XWE, GPIO_FN_MFG0_IN1,
+	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_SOUT3, GPIO_FN_SCIFA2_TXD1, GPIO_FN_MSIOF2_MCK0,
+	GPIO_FN_SIN3, GPIO_FN_SCIFA2_RXD1, GPIO_FN_MSIOF2_MCK1,
+	GPIO_FN_XRTS3, GPIO_FN_SCIFA2_RTS1, GPIO_FN_PORT156_MSIOF2_SS2,
+	GPIO_FN_XCTS3, GPIO_FN_SCIFA2_CTS1, GPIO_FN_PORT157_MSIOF2_RXD,
+
+	/* 55-4 (FN) */
+	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_SOUT0,
+	GPIO_FN_PORT161_SCIFB_CTS, GPIO_FN_PORT161_SCIFA5_CTS, GPIO_FN_XCTS0,
+	GPIO_FN_MFG3_IN2,
+	GPIO_FN_PORT162_SCIFB_RXD, GPIO_FN_PORT162_SCIFA5_RXD, GPIO_FN_SIN0,
+	GPIO_FN_MFG3_IN1,
+	GPIO_FN_PORT163_SCIFB_RTS, GPIO_FN_PORT163_SCIFA5_RTS, GPIO_FN_XRTS0,
+	GPIO_FN_MFG3_OUT1,
+	GPIO_FN_TPU3TO0,
+	GPIO_FN_LCDD0, GPIO_FN_PORT192_KEYOUT0, GPIO_FN_EXT_CKI,
+	GPIO_FN_LCDD1, GPIO_FN_PORT193_KEYOUT1, GPIO_FN_PORT193_SCIFA5_CTS,
+	GPIO_FN_BBIF2_TSYNC1,
+	GPIO_FN_LCDD2, GPIO_FN_PORT194_KEYOUT2, GPIO_FN_PORT194_SCIFA5_RTS,
+	GPIO_FN_BBIF2_TSCK1,
+	GPIO_FN_LCDD3, GPIO_FN_PORT195_KEYOUT3, GPIO_FN_PORT195_SCIFA5_RXD,
+	GPIO_FN_BBIF2_TXD1,
+	GPIO_FN_LCDD4, GPIO_FN_PORT196_KEYOUT4, GPIO_FN_PORT196_SCIFA5_TXD,
+	GPIO_FN_LCDD5, GPIO_FN_PORT197_KEYOUT5, GPIO_FN_PORT197_SCIFA5_SCK,
+	GPIO_FN_MFG2_OUT2, GPIO_FN_TPU2TO1,
+	GPIO_FN_LCDD6, GPIO_FN_XWR2,
+	GPIO_FN_LCDD7, GPIO_FN_TPU4TO1, GPIO_FN_MFG4_OUT2, GPIO_FN_XWR3,
+	GPIO_FN_LCDD8, GPIO_FN_PORT200_KEYIN0, GPIO_FN_VIO_DR0, GPIO_FN_D16,
+	GPIO_FN_ED16,
+	GPIO_FN_LCDD9, GPIO_FN_PORT201_KEYIN1, GPIO_FN_VIO_DR1, GPIO_FN_D17,
+	GPIO_FN_ED17,
+	GPIO_FN_LCDD10, GPIO_FN_PORT202_KEYIN2, GPIO_FN_VIO_DR2, GPIO_FN_D18,
+	GPIO_FN_ED18,
+	GPIO_FN_LCDD11, GPIO_FN_PORT203_KEYIN3, GPIO_FN_VIO_DR3, GPIO_FN_D19,
+	GPIO_FN_ED19,
+	GPIO_FN_LCDD12, GPIO_FN_PORT204_KEYIN4, GPIO_FN_VIO_DR4, GPIO_FN_D20,
+	GPIO_FN_ED20,
+	GPIO_FN_LCDD13, GPIO_FN_PORT205_KEYIN5, GPIO_FN_VIO_DR5, GPIO_FN_D21,
+	GPIO_FN_ED21,
+	GPIO_FN_LCDD14, GPIO_FN_PORT206_KEYIN6, GPIO_FN_VIO_DR6, GPIO_FN_D22,
+	GPIO_FN_ED22,
+	GPIO_FN_LCDD15, GPIO_FN_PORT207_MSIOF0L_SS1, GPIO_FN_PORT207_KEYOUT0,
+	GPIO_FN_VIO_DR7,
+	GPIO_FN_D23, GPIO_FN_ED23,
+	GPIO_FN_LCDD16, GPIO_FN_PORT208_MSIOF0L_SS2, GPIO_FN_PORT208_KEYOUT1,
+	GPIO_FN_VIO_VDR,
+	GPIO_FN_D24, GPIO_FN_ED24,
+	GPIO_FN_LCDD17, GPIO_FN_PORT209_KEYOUT2, GPIO_FN_VIO_HDR, GPIO_FN_D25,
+	GPIO_FN_ED25,
+	GPIO_FN_LCDD18, GPIO_FN_DREQ2, GPIO_FN_PORT210_MSIOF0L_SS1, GPIO_FN_D26,
+	GPIO_FN_ED26,
+	GPIO_FN_LCDD19, GPIO_FN_PORT211_MSIOF0L_SS2, GPIO_FN_D27, GPIO_FN_ED27,
+	GPIO_FN_LCDD20, GPIO_FN_TS_SPSYNC1, GPIO_FN_MSIOF0L_MCK0, GPIO_FN_D28,
+	GPIO_FN_ED28,
+	GPIO_FN_LCDD21, GPIO_FN_TS_SDAT1, GPIO_FN_MSIOF0L_MCK1, GPIO_FN_D29,
+	GPIO_FN_ED29,
+	GPIO_FN_LCDD22, GPIO_FN_TS_SDEN1, GPIO_FN_MSIOF0L_RSCK, GPIO_FN_D30,
+	GPIO_FN_ED30,
+	GPIO_FN_LCDD23, GPIO_FN_TS_SCK1, GPIO_FN_MSIOF0L_RSYNC, GPIO_FN_D31,
+	GPIO_FN_ED31,
+	GPIO_FN_LCDDCK, GPIO_FN_LCDWR, GPIO_FN_PORT216_KEYOUT3,
+	GPIO_FN_VIO_CLKR,
+	GPIO_FN_LCDRD, GPIO_FN_DACK2, GPIO_FN_MSIOF0L_TSYNC,
+	GPIO_FN_LCDHSYN, GPIO_FN_LCDCS, GPIO_FN_LCDCS2, GPIO_FN_DACK3,
+	GPIO_FN_PORT218_VIO_CKOR, GPIO_FN_PORT218_KEYOUT4,
+	GPIO_FN_LCDDISP, GPIO_FN_LCDRS, GPIO_FN_DREQ3, GPIO_FN_MSIOF0L_TSCK,
+	GPIO_FN_LCDVSYN, GPIO_FN_LCDVSYN2, GPIO_FN_PORT220_KEYOUT5,
+	GPIO_FN_LCDLCLK, GPIO_FN_DREQ1, GPIO_FN_PWEN, GPIO_FN_MSIOF0L_RXD,
+	GPIO_FN_LCDDON, GPIO_FN_LCDDON2, GPIO_FN_DACK1, GPIO_FN_OVCN,
+	GPIO_FN_MSIOF0L_TXD,
+	GPIO_FN_SCIFA1_TXD, GPIO_FN_OVCN2,
+	GPIO_FN_EXTLP, GPIO_FN_SCIFA1_SCK, GPIO_FN_USBTERM,
+	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_PORT230_FSIAOMC,
+	GPIO_FN_MSIOF1_TSYNC, GPIO_FN_SCIFA2_CTS2, GPIO_FN_PORT231_FSIAOLR,
+	GPIO_FN_MSIOF1_TSCK, GPIO_FN_SCIFA2_SCK2, GPIO_FN_PORT232_FSIAOBT,
+	GPIO_FN_MSIOF1_RXD, GPIO_FN_SCIFA2_RXD2, GPIO_FN_GPS_VCOTRIG,
+	GPIO_FN_PORT233_FSIACK,
+	GPIO_FN_MSIOF1_RSCK, GPIO_FN_SCIFA2_RTS2, GPIO_FN_PORT234_FSIAOSLD,
+	GPIO_FN_MSIOF1_RSYNC, GPIO_FN_OPORT0, GPIO_FN_MFG1_IN2,
+	GPIO_FN_PORT235_FSIAILR,
+	GPIO_FN_MSIOF1_MCK0, GPIO_FN_I2C_SDA2, GPIO_FN_PORT236_FSIAIBT,
+	GPIO_FN_MSIOF1_MCK1, GPIO_FN_I2C_SCL2, GPIO_FN_PORT237_FSIAISLD,
+	GPIO_FN_MSIOF1_SS1, GPIO_FN_EDBGREQ3,
+
+	/* 55-5 (FN) */
+	GPIO_FN_MSIOF1_SS2,
+	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_PORT244_MSIOF2_RXD,
+	GPIO_FN_PORT245_SCIFA5_RTS, GPIO_FN_MFG2_IN2, GPIO_FN_PORT245_SCIFB_RTS,
+	GPIO_FN_PORT245_MSIOF2_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_MSIOF2_TSCK,
+	GPIO_FN_PORT249_IROUT, GPIO_FN_MFG4_IN1, GPIO_FN_PORT249_MSIOF2_TSYNC,
+	GPIO_FN_SDHICLK0, GPIO_FN_TCK2_SWCLK_MC0,
+	GPIO_FN_SDHICD0,
+	GPIO_FN_SDHID0_0, GPIO_FN_TMS2_SWDIO_MC0,
+	GPIO_FN_SDHID0_1, GPIO_FN_TDO2_SWO0_MC0,
+	GPIO_FN_SDHID0_2, GPIO_FN_TDI2,
+	GPIO_FN_SDHID0_3, GPIO_FN_RTCK2_SWO1_MC0,
+	GPIO_FN_SDHICMD0, GPIO_FN_TRST2,
+	GPIO_FN_SDHIWP0, GPIO_FN_EDBGREQ2,
+	GPIO_FN_SDHICLK1, GPIO_FN_TCK3_SWCLK_MC1,
+	GPIO_FN_SDHID1_0, GPIO_FN_M11_SLCD_SO2, GPIO_FN_TS_SPSYNC2,
+	GPIO_FN_TMS3_SWDIO_MC1,
+	GPIO_FN_SDHID1_1, GPIO_FN_M9_SLCD_A02, GPIO_FN_TS_SDAT2,
+	GPIO_FN_TDO3_SWO0_MC1,
+	GPIO_FN_SDHID1_2, GPIO_FN_M10_SLCD_CK2, GPIO_FN_TS_SDEN2, GPIO_FN_TDI3,
+	GPIO_FN_SDHID1_3, GPIO_FN_M12_SLCD_CE2, GPIO_FN_TS_SCK2,
+	GPIO_FN_RTCK3_SWO1_MC1,
+	GPIO_FN_SDHICMD1, GPIO_FN_TRST3,
+	GPIO_FN_RESETOUTS,
+};
+
+#endif /* __ASM_SH7377_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/system.h b/arch/arm/mach-shmobile/include/mach/system.h
new file mode 100644
index 0000000..76a687e
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/system.h
@@ -0,0 +1,14 @@
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	cpu_reset(0);
+}
+
+#endif
diff --git a/arch/arm/mach-shmobile/include/mach/timex.h b/arch/arm/mach-shmobile/include/mach/timex.h
new file mode 100644
index 0000000..ae0d8d8
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/timex.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_MACH_TIMEX_H
+#define __ASM_MACH_TIMEX_H
+
+#define CLOCK_TICK_RATE		1193180 /* unused i8253 PIT value */
+
+#endif /* __ASM_MACH_TIMEX_H */
diff --git a/arch/arm/mach-shmobile/include/mach/uncompress.h b/arch/arm/mach-shmobile/include/mach/uncompress.h
new file mode 100644
index 0000000..0bd7556
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/uncompress.h
@@ -0,0 +1,21 @@
+#ifndef __ASM_MACH_UNCOMPRESS_H
+#define __ASM_MACH_UNCOMPRESS_H
+
+/*
+ * This does not append a newline
+ */
+static void putc(int c)
+{
+}
+
+static inline void flush(void)
+{
+}
+
+static void arch_decomp_setup(void)
+{
+}
+
+#define arch_decomp_wdog()
+
+#endif /* __ASM_MACH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-shmobile/include/mach/vmalloc.h b/arch/arm/mach-shmobile/include/mach/vmalloc.h
new file mode 100644
index 0000000..fb3c4f1
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/vmalloc.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_MACH_VMALLOC_H
+#define __ASM_MACH_VMALLOC_H
+
+#define VMALLOC_END       (PAGE_OFFSET + 0x24000000)
+
+#endif /* __ASM_MACH_VMALLOC_H */
diff --git a/arch/arm/mach-shmobile/intc-sh7367.c b/arch/arm/mach-shmobile/intc-sh7367.c
new file mode 100644
index 0000000..6a547b4
--- /dev/null
+++ b/arch/arm/mach-shmobile/intc-sh7367.c
@@ -0,0 +1,270 @@
+/*
+ * sh7367 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/mach-types.h>
+#include <asm/mach/arch.h>
+
+enum {
+	UNUSED_INTCA = 0,
+
+	/* interrupt sources INTCA */
+	IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A,
+	IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A,
+	DIRC,
+	CRYPT1_ERR, CRYPT2_STD,
+	IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1,
+	ARM11_IRQPMU, ARM11_COMMTX, ARM11_COMMRX,
+	ETM11_ACQCMP, ETM11_FULL,
+	MFI_MFIM, MFI_MFIS,
+	BBIF1, BBIF2,
+	USBDMAC_USHDMI,
+	USBHS_USHI0, USBHS_USHI1,
+	CMT1_CMT10, CMT1_CMT11, CMT1_CMT12, CMT1_CMT13, CMT2, CMT3,
+	KEYSC_KEY,
+	SCIFA0, SCIFA1, SCIFA2, SCIFA3,
+	MSIOF2, MSIOF1,
+	SCIFA4, SCIFA5, SCIFB,
+	FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
+	SDHI0_SDHI0I0, SDHI0_SDHI0I1, SDHI0_SDHI0I2, SDHI0_SDHI0I3,
+	SDHI1_SDHI1I0, SDHI1_SDHI1I1, SDHI1_SDHI1I2, SDHI1_SDHI1I3,
+	MSU_MSU, MSU_MSU2,
+	IREM,
+	SIU,
+	SPU,
+	IRDA,
+	TPU0, TPU1, TPU2, TPU3, TPU4,
+	LCRC,
+	PINT1, PINT2,
+	TTI20,
+	MISTY,
+	DDM,
+	SDHI2_SDHI2I0, SDHI2_SDHI2I1, SDHI2_SDHI2I2, SDHI2_SDHI2I3,
+	RWDT0, RWDT1,
+	DMAC_1_DEI0, DMAC_1_DEI1, DMAC_1_DEI2, DMAC_1_DEI3,
+	DMAC_2_DEI4, DMAC_2_DEI5, DMAC_2_DADERR,
+	DMAC2_1_DEI0, DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3,
+	DMAC2_2_DEI4, DMAC2_2_DEI5, DMAC2_2_DADERR,
+	DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3,
+	DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR,
+
+	/* interrupt groups INTCA */
+	DMAC_1, DMAC_2,	DMAC2_1, DMAC2_2, DMAC3_1, DMAC3_2,
+	ETM11, ARM11, USBHS, FLCTL, IIC1, SDHI0, SDHI1, SDHI2,
+};
+
+static struct intc_vect intca_vectors[] = {
+	INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
+	INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
+	INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
+	INTC_VECT(IRQ6A, 0x02c0), INTC_VECT(IRQ7A, 0x02e0),
+	INTC_VECT(IRQ8A, 0x0300), INTC_VECT(IRQ9A, 0x0320),
+	INTC_VECT(IRQ10A, 0x0340), INTC_VECT(IRQ11A, 0x0360),
+	INTC_VECT(IRQ12A, 0x0380), INTC_VECT(IRQ13A, 0x03a0),
+	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
+	INTC_VECT(DIRC, 0x0560),
+	INTC_VECT(CRYPT1_ERR, 0x05e0),
+	INTC_VECT(CRYPT2_STD, 0x0700),
+	INTC_VECT(IIC1_ALI1, 0x0780), INTC_VECT(IIC1_TACKI1, 0x07a0),
+	INTC_VECT(IIC1_WAITI1, 0x07c0), INTC_VECT(IIC1_DTEI1, 0x07e0),
+	INTC_VECT(ARM11_IRQPMU, 0x0800), INTC_VECT(ARM11_COMMTX, 0x0840),
+	INTC_VECT(ARM11_COMMRX, 0x0860),
+	INTC_VECT(ETM11_ACQCMP, 0x0880), INTC_VECT(ETM11_FULL, 0x08a0),
+	INTC_VECT(MFI_MFIM, 0x0900), INTC_VECT(MFI_MFIS, 0x0920),
+	INTC_VECT(BBIF1, 0x0940), INTC_VECT(BBIF2, 0x0960),
+	INTC_VECT(USBDMAC_USHDMI, 0x0a00),
+	INTC_VECT(USBHS_USHI0, 0x0a20), INTC_VECT(USBHS_USHI1, 0x0a40),
+	INTC_VECT(CMT1_CMT10, 0x0b00), INTC_VECT(CMT1_CMT11, 0x0b20),
+	INTC_VECT(CMT1_CMT12, 0x0b40), INTC_VECT(CMT1_CMT13, 0x0b60),
+	INTC_VECT(CMT2, 0x0b80), INTC_VECT(CMT3, 0x0ba0),
+	INTC_VECT(KEYSC_KEY, 0x0be0),
+	INTC_VECT(SCIFA0, 0x0c00), INTC_VECT(SCIFA1, 0x0c20),
+	INTC_VECT(SCIFA2, 0x0c40), INTC_VECT(SCIFA3, 0x0c60),
+	INTC_VECT(MSIOF2, 0x0c80), INTC_VECT(MSIOF1, 0x0d00),
+	INTC_VECT(SCIFA4, 0x0d20), INTC_VECT(SCIFA5, 0x0d40),
+	INTC_VECT(SCIFB, 0x0d60),
+	INTC_VECT(FLCTL_FLSTEI, 0x0d80), INTC_VECT(FLCTL_FLTENDI, 0x0da0),
+	INTC_VECT(FLCTL_FLTREQ0I, 0x0dc0), INTC_VECT(FLCTL_FLTREQ1I, 0x0de0),
+	INTC_VECT(SDHI0_SDHI0I0, 0x0e00), INTC_VECT(SDHI0_SDHI0I1, 0x0e20),
+	INTC_VECT(SDHI0_SDHI0I2, 0x0e40), INTC_VECT(SDHI0_SDHI0I3, 0x0e60),
+	INTC_VECT(SDHI1_SDHI1I0, 0x0e80), INTC_VECT(SDHI1_SDHI1I1, 0x0ea0),
+	INTC_VECT(SDHI1_SDHI1I2, 0x0ec0), INTC_VECT(SDHI1_SDHI1I3, 0x0ee0),
+	INTC_VECT(MSU_MSU, 0x0f20), INTC_VECT(MSU_MSU2, 0x0f40),
+	INTC_VECT(IREM, 0x0f60),
+	INTC_VECT(SIU, 0x0fa0),
+	INTC_VECT(SPU, 0x0fc0),
+	INTC_VECT(IRDA, 0x0480),
+	INTC_VECT(TPU0, 0x04a0), INTC_VECT(TPU1, 0x04c0),
+	INTC_VECT(TPU2, 0x04e0), INTC_VECT(TPU3, 0x0500),
+	INTC_VECT(TPU4, 0x0520),
+	INTC_VECT(LCRC, 0x0540),
+	INTC_VECT(PINT1, 0x1000), INTC_VECT(PINT2, 0x1020),
+	INTC_VECT(TTI20, 0x1100),
+	INTC_VECT(MISTY, 0x1120),
+	INTC_VECT(DDM, 0x1140),
+	INTC_VECT(SDHI2_SDHI2I0, 0x1200), INTC_VECT(SDHI2_SDHI2I1, 0x1220),
+	INTC_VECT(SDHI2_SDHI2I2, 0x1240), INTC_VECT(SDHI2_SDHI2I3, 0x1260),
+	INTC_VECT(RWDT0, 0x1280), INTC_VECT(RWDT1, 0x12a0),
+	INTC_VECT(DMAC_1_DEI0, 0x2000), INTC_VECT(DMAC_1_DEI1, 0x2020),
+	INTC_VECT(DMAC_1_DEI2, 0x2040), INTC_VECT(DMAC_1_DEI3, 0x2060),
+	INTC_VECT(DMAC_2_DEI4, 0x2080), INTC_VECT(DMAC_2_DEI5, 0x20a0),
+	INTC_VECT(DMAC_2_DADERR, 0x20c0),
+	INTC_VECT(DMAC2_1_DEI0, 0x2100), INTC_VECT(DMAC2_1_DEI1, 0x2120),
+	INTC_VECT(DMAC2_1_DEI2, 0x2140), INTC_VECT(DMAC2_1_DEI3, 0x2160),
+	INTC_VECT(DMAC2_2_DEI4, 0x2180), INTC_VECT(DMAC2_2_DEI5, 0x21a0),
+	INTC_VECT(DMAC2_2_DADERR, 0x21c0),
+	INTC_VECT(DMAC3_1_DEI0, 0x2200), INTC_VECT(DMAC3_1_DEI1, 0x2220),
+	INTC_VECT(DMAC3_1_DEI2, 0x2240), INTC_VECT(DMAC3_1_DEI3, 0x2260),
+	INTC_VECT(DMAC3_2_DEI4, 0x2280), INTC_VECT(DMAC3_2_DEI5, 0x22a0),
+	INTC_VECT(DMAC3_2_DADERR, 0x22c0),
+};
+
+static struct intc_group intca_groups[] __initdata = {
+	INTC_GROUP(DMAC_1, DMAC_1_DEI0,
+		   DMAC_1_DEI1, DMAC_1_DEI2, DMAC_1_DEI3),
+	INTC_GROUP(DMAC_2, DMAC_2_DEI4,
+		   DMAC_2_DEI5, DMAC_2_DADERR),
+	INTC_GROUP(DMAC2_1, DMAC2_1_DEI0,
+		   DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3),
+	INTC_GROUP(DMAC2_2, DMAC2_2_DEI4,
+		   DMAC2_2_DEI5, DMAC2_2_DADERR),
+	INTC_GROUP(DMAC3_1, DMAC3_1_DEI0,
+		   DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3),
+	INTC_GROUP(DMAC3_2, DMAC3_2_DEI4,
+		   DMAC3_2_DEI5, DMAC3_2_DADERR),
+	INTC_GROUP(ETM11, ETM11_ACQCMP, ETM11_FULL),
+	INTC_GROUP(ARM11, ARM11_IRQPMU, ARM11_COMMTX, ARM11_COMMTX),
+	INTC_GROUP(USBHS, USBHS_USHI0, USBHS_USHI1),
+	INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI,
+		   FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
+	INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1),
+	INTC_GROUP(SDHI0, SDHI0_SDHI0I0, SDHI0_SDHI0I1,
+		   SDHI0_SDHI0I2, SDHI0_SDHI0I3),
+	INTC_GROUP(SDHI1, SDHI1_SDHI1I0, SDHI1_SDHI1I1,
+		   SDHI1_SDHI1I2, SDHI1_SDHI1I3),
+	INTC_GROUP(SDHI2, SDHI2_SDHI2I0, SDHI2_SDHI2I1,
+		   SDHI2_SDHI2I2, SDHI2_SDHI2I3),
+};
+
+static struct intc_mask_reg intca_mask_registers[] = {
+	{ 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
+	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
+	    ARM11_IRQPMU, 0, ARM11_COMMTX, ARM11_COMMRX } },
+	{ 0xe6940084, 0xe69400c4, 8, /* IMR1A / IMCR1A */
+	  { CRYPT1_ERR, CRYPT2_STD, DIRC, 0,
+	    DMAC_1_DEI3, DMAC_1_DEI2, DMAC_1_DEI1, DMAC_1_DEI0 } },
+	{ 0xe6940088, 0xe69400c8, 8, /* IMR2A / IMCR2A */
+	  { PINT1, PINT2, 0, 0,
+	    BBIF1, BBIF2, MFI_MFIS, MFI_MFIM } },
+	{ 0xe694008c, 0xe69400cc, 8, /* IMR3A / IMCR3A */
+	  { DMAC3_1_DEI3, DMAC3_1_DEI2, DMAC3_1_DEI1, DMAC3_1_DEI0,
+	    DMAC3_2_DADERR, DMAC3_2_DEI5, DMAC3_2_DEI4, IRDA } },
+	{ 0xe6940090, 0xe69400d0, 8, /* IMR4A / IMCR4A */
+	  { DDM, 0, 0, 0,
+	    0, 0, ETM11_FULL, ETM11_ACQCMP } },
+	{ 0xe6940094, 0xe69400d4, 8, /* IMR5A / IMCR5A */
+	  { KEYSC_KEY, DMAC_2_DADERR, DMAC_2_DEI5, DMAC_2_DEI4,
+	    SCIFA3, SCIFA2, SCIFA1, SCIFA0 } },
+	{ 0xe6940098, 0xe69400d8, 8, /* IMR6A / IMCR6A */
+	  { SCIFB, SCIFA5, SCIFA4, MSIOF1,
+	    0, 0, MSIOF2, 0 } },
+	{ 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */
+	  { SDHI0_SDHI0I3, SDHI0_SDHI0I2, SDHI0_SDHI0I1, SDHI0_SDHI0I0,
+	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
+	{ 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */
+	  { SDHI1_SDHI1I3, SDHI1_SDHI1I2, SDHI1_SDHI1I1, SDHI1_SDHI1I0,
+	    TTI20, USBDMAC_USHDMI, SPU, SIU } },
+	{ 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */
+	  { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10,
+	    CMT2, USBHS_USHI1, USBHS_USHI0, 0 } },
+	{ 0xe69400a8, 0xe69400e8, 8, /* IMR10A / IMCR10A */
+	  { 0, DMAC2_2_DADERR, DMAC2_2_DEI5, DMAC2_2_DEI4,
+	    0, 0, 0, 0 } },
+	{ 0xe69400ac, 0xe69400ec, 8, /* IMR11A / IMCR11A */
+	  { IIC1_DTEI1, IIC1_WAITI1, IIC1_TACKI1, IIC1_ALI1,
+	    LCRC, MSU_MSU2, IREM, MSU_MSU } },
+	{ 0xe69400b0, 0xe69400f0, 8, /* IMR12A / IMCR12A */
+	  { 0, 0, TPU0, TPU1,
+	    TPU2, TPU3, TPU4, 0 } },
+	{ 0xe69400b4, 0xe69400f4, 8, /* IMR13A / IMCR13A */
+	  { SDHI2_SDHI2I3, SDHI2_SDHI2I2, SDHI2_SDHI2I1, SDHI2_SDHI2I0,
+	    MISTY, CMT3, RWDT1, RWDT0 } },
+};
+
+static struct intc_prio_reg intca_prio_registers[] = {
+	{ 0xe6900010, 0, 32, 4, /* INTPRI00A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900014, 0, 32, 4, /* INTPRI10A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+
+	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, LCRC } },
+	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, ETM11, BBIF1, BBIF2 } },
+	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { CRYPT1_ERR, CRYPT2_STD,
+					      CMT1_CMT11, ARM11 } },
+	{ 0xe694000c, 0, 16, 4, /* IPRDA */ { PINT1, PINT2,
+					      CMT1_CMT12, TPU4 } },
+	{ 0xe6940010, 0, 16, 4, /* IPREA */ { DMAC_1, MFI_MFIS,
+					      MFI_MFIM, USBHS } },
+	{ 0xe6940014, 0, 16, 4, /* IPRFA */ { KEYSC_KEY, DMAC_2,
+					      0, CMT1_CMT10 } },
+	{ 0xe6940018, 0, 16, 4, /* IPRGA */ { SCIFA0, SCIFA1,
+					      SCIFA2, SCIFA3 } },
+	{ 0xe694001c, 0, 16, 4, /* IPRGH */ { MSIOF2, USBDMAC_USHDMI,
+					      FLCTL, SDHI0 } },
+	{ 0xe6940020, 0, 16, 4, /* IPRIA */ { MSIOF1, SCIFA4, MSU_MSU, IIC1 } },
+	{ 0xe6940024, 0, 16, 4, /* IPRJA */ { DMAC2_1, DMAC2_2, SIU, TTI20 } },
+	{ 0xe6940028, 0, 16, 4, /* IPRKA */ { 0, CMT1_CMT13, IREM, SDHI1 } },
+	{ 0xe694002c, 0, 16, 4, /* IPRLA */ { TPU0, TPU1, TPU2, TPU3 } },
+	{ 0xe6940030, 0, 16, 4, /* IPRMA */ { MISTY, CMT3, RWDT1, RWDT0 } },
+	{ 0xe6940034, 0, 16, 4, /* IPRNA */ { SCIFB, SCIFA5, SPU, DDM } },
+	{ 0xe6940038, 0, 16, 4, /* IPROA */ { 0, 0, DIRC, SDHI2 } },
+};
+
+static struct intc_sense_reg intca_sense_registers[] __initdata = {
+	{ 0xe6900000, 16, 2, /* ICR1A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900004, 16, 2, /* ICR2A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+};
+
+static struct intc_mask_reg intca_ack_registers[] __initdata = {
+	{ 0xe6900020, 0, 8, /* INTREQ00A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900024, 0, 8, /* INTREQ10A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+};
+
+static DECLARE_INTC_DESC_ACK(intca_desc, "sh7367-intca",
+			     intca_vectors, intca_groups,
+			     intca_mask_registers, intca_prio_registers,
+			     intca_sense_registers, intca_ack_registers);
+
+void __init sh7367_init_irq(void)
+{
+	/* INTCA */
+	register_intc_controller(&intca_desc);
+}
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
new file mode 100644
index 0000000..c57a923
--- /dev/null
+++ b/arch/arm/mach-shmobile/intc-sh7372.c
@@ -0,0 +1,369 @@
+/*
+ * sh7372 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/mach-types.h>
+#include <asm/mach/arch.h>
+
+enum {
+	UNUSED_INTCA = 0,
+
+	/* interrupt sources INTCA */
+	IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A,
+	IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A,
+	IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A,
+	IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A,
+	DIRC,
+	CRYPT_STD,
+	IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1,
+	AP_ARM_IRQPMU, AP_ARM_COMMTX, AP_ARM_COMMRX,
+	MFI_MFIM, MFI_MFIS,
+	BBIF1, BBIF2,
+	USBHSDMAC0_USHDMI,
+	_3DG_SGX540,
+	CMT1_CMT10, CMT1_CMT11, CMT1_CMT12, CMT1_CMT13, CMT2, CMT3,
+	KEYSC_KEY,
+	SCIFA0, SCIFA1, SCIFA2, SCIFA3,
+	MSIOF2, MSIOF1,
+	SCIFA4, SCIFA5, SCIFB,
+	FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
+	SDHI0_SDHI0I0, SDHI0_SDHI0I1, SDHI0_SDHI0I2, SDHI0_SDHI0I3,
+	SDHI1_SDHI1I0, SDHI1_SDHI1I1, SDHI1_SDHI1I2,
+	IRREM,
+	IRDA,
+	TPU0,
+	TTI20,
+	DDM,
+	SDHI2_SDHI2I0, SDHI2_SDHI2I1, SDHI2_SDHI2I2, SDHI2_SDHI2I3,
+	RWDT0,
+	DMAC1_1_DEI0, DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3,
+	DMAC1_2_DEI4, DMAC1_2_DEI5, DMAC1_2_DADERR,
+	DMAC2_1_DEI0, DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3,
+	DMAC2_2_DEI4, DMAC2_2_DEI5, DMAC2_2_DADERR,
+	DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3,
+	DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR,
+	SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM,
+	HDMI,
+	SPU2_SPU0, SPU2_SPU1,
+	FSI, FMSI,
+	MIPI_HSI,
+	IPMMU_IPMMUD,
+	CEC_1, CEC_2,
+	AP_ARM_CTIIRQ, AP_ARM_DMAEXTERRIRQ, AP_ARM_DMAIRQ, AP_ARM_DMASIRQ,
+	MFIS2,
+	CPORTR2S,
+	CMT14, CMT15,
+	MMC_MMC_ERR, MMC_MMC_NOR,
+	IIC4_ALI4, IIC4_TACKI4, IIC4_WAITI4, IIC4_DTEI4,
+	IIC3_ALI3, IIC3_TACKI3, IIC3_WAITI3, IIC3_DTEI3,
+	USB0_USB0I1, USB0_USB0I0,
+	USB1_USB1I1, USB1_USB1I0,
+	USBHSDMAC1_USHDMI,
+
+	/* interrupt groups INTCA */
+	DMAC1_1, DMAC1_2, DMAC2_1, DMAC2_2, DMAC3_1, DMAC3_2, SHWYSTAT,
+	AP_ARM1, AP_ARM2, SPU2, FLCTL, IIC1, SDHI0, SDHI1, SDHI2
+};
+
+static struct intc_vect intca_vectors[] __initdata = {
+	INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
+	INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
+	INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
+	INTC_VECT(IRQ6A, 0x02c0), INTC_VECT(IRQ7A, 0x02e0),
+	INTC_VECT(IRQ8A, 0x0300), INTC_VECT(IRQ9A, 0x0320),
+	INTC_VECT(IRQ10A, 0x0340), INTC_VECT(IRQ11A, 0x0360),
+	INTC_VECT(IRQ12A, 0x0380), INTC_VECT(IRQ13A, 0x03a0),
+	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
+	INTC_VECT(IRQ16A, 0x3200), INTC_VECT(IRQ17A, 0x3220),
+	INTC_VECT(IRQ18A, 0x3240), INTC_VECT(IRQ19A, 0x3260),
+	INTC_VECT(IRQ20A, 0x3280), INTC_VECT(IRQ31A, 0x32a0),
+	INTC_VECT(IRQ22A, 0x32c0), INTC_VECT(IRQ23A, 0x32e0),
+	INTC_VECT(IRQ24A, 0x3300), INTC_VECT(IRQ25A, 0x3320),
+	INTC_VECT(IRQ26A, 0x3340), INTC_VECT(IRQ27A, 0x3360),
+	INTC_VECT(IRQ28A, 0x3380), INTC_VECT(IRQ29A, 0x33a0),
+	INTC_VECT(IRQ30A, 0x33c0), INTC_VECT(IRQ31A, 0x33e0),
+	INTC_VECT(DIRC, 0x0560),
+	INTC_VECT(CRYPT_STD, 0x0700),
+	INTC_VECT(IIC1_ALI1, 0x0780), INTC_VECT(IIC1_TACKI1, 0x07a0),
+	INTC_VECT(IIC1_WAITI1, 0x07c0), INTC_VECT(IIC1_DTEI1, 0x07e0),
+	INTC_VECT(AP_ARM_IRQPMU, 0x0800), INTC_VECT(AP_ARM_COMMTX, 0x0840),
+	INTC_VECT(AP_ARM_COMMRX, 0x0860),
+	INTC_VECT(MFI_MFIM, 0x0900), INTC_VECT(MFI_MFIS, 0x0920),
+	INTC_VECT(BBIF1, 0x0940), INTC_VECT(BBIF2, 0x0960),
+	INTC_VECT(USBHSDMAC0_USHDMI, 0x0a00),
+	INTC_VECT(_3DG_SGX540, 0x0a60),
+	INTC_VECT(CMT1_CMT10, 0x0b00), INTC_VECT(CMT1_CMT11, 0x0b20),
+	INTC_VECT(CMT1_CMT12, 0x0b40), INTC_VECT(CMT1_CMT13, 0x0b60),
+	INTC_VECT(CMT2, 0x0b80), INTC_VECT(CMT3, 0x0ba0),
+	INTC_VECT(KEYSC_KEY, 0x0be0),
+	INTC_VECT(SCIFA0, 0x0c00), INTC_VECT(SCIFA1, 0x0c20),
+	INTC_VECT(SCIFA2, 0x0c40), INTC_VECT(SCIFA3, 0x0c60),
+	INTC_VECT(MSIOF2, 0x0c80), INTC_VECT(MSIOF1, 0x0d00),
+	INTC_VECT(SCIFA4, 0x0d20), INTC_VECT(SCIFA5, 0x0d40),
+	INTC_VECT(SCIFB, 0x0d60),
+	INTC_VECT(FLCTL_FLSTEI, 0x0d80), INTC_VECT(FLCTL_FLTENDI, 0x0da0),
+	INTC_VECT(FLCTL_FLTREQ0I, 0x0dc0), INTC_VECT(FLCTL_FLTREQ1I, 0x0de0),
+	INTC_VECT(SDHI0_SDHI0I0, 0x0e00), INTC_VECT(SDHI0_SDHI0I1, 0x0e20),
+	INTC_VECT(SDHI0_SDHI0I2, 0x0e40), INTC_VECT(SDHI0_SDHI0I3, 0x0e60),
+	INTC_VECT(SDHI1_SDHI1I0, 0x0e80), INTC_VECT(SDHI1_SDHI1I1, 0x0ea0),
+	INTC_VECT(SDHI1_SDHI1I2, 0x0ec0),
+	INTC_VECT(IRREM, 0x0f60),
+	INTC_VECT(IRDA, 0x0480),
+	INTC_VECT(TPU0, 0x04a0),
+	INTC_VECT(TTI20, 0x1100),
+	INTC_VECT(DDM, 0x1140),
+	INTC_VECT(SDHI2_SDHI2I0, 0x1200), INTC_VECT(SDHI2_SDHI2I1, 0x1220),
+	INTC_VECT(SDHI2_SDHI2I2, 0x1240), INTC_VECT(SDHI2_SDHI2I3, 0x1260),
+	INTC_VECT(RWDT0, 0x1280),
+	INTC_VECT(DMAC1_1_DEI0, 0x2000), INTC_VECT(DMAC1_1_DEI1, 0x2020),
+	INTC_VECT(DMAC1_1_DEI2, 0x2040), INTC_VECT(DMAC1_1_DEI3, 0x2060),
+	INTC_VECT(DMAC1_2_DEI4, 0x2080), INTC_VECT(DMAC1_2_DEI5, 0x20a0),
+	INTC_VECT(DMAC1_2_DADERR, 0x20c0),
+	INTC_VECT(DMAC2_1_DEI0, 0x2100), INTC_VECT(DMAC2_1_DEI1, 0x2120),
+	INTC_VECT(DMAC2_1_DEI2, 0x2140), INTC_VECT(DMAC2_1_DEI3, 0x2160),
+	INTC_VECT(DMAC2_2_DEI4, 0x2180), INTC_VECT(DMAC2_2_DEI5, 0x21a0),
+	INTC_VECT(DMAC2_2_DADERR, 0x21c0),
+	INTC_VECT(DMAC3_1_DEI0, 0x2200), INTC_VECT(DMAC3_1_DEI1, 0x2220),
+	INTC_VECT(DMAC3_1_DEI2, 0x2240), INTC_VECT(DMAC3_1_DEI3, 0x2260),
+	INTC_VECT(DMAC3_2_DEI4, 0x2280), INTC_VECT(DMAC3_2_DEI5, 0x22a0),
+	INTC_VECT(DMAC3_2_DADERR, 0x22c0),
+	INTC_VECT(SHWYSTAT_RT, 0x1300), INTC_VECT(SHWYSTAT_HS, 0x1320),
+	INTC_VECT(SHWYSTAT_COM, 0x1340),
+	INTC_VECT(HDMI, 0x17e0),
+	INTC_VECT(SPU2_SPU0, 0x1800), INTC_VECT(SPU2_SPU1, 0x1820),
+	INTC_VECT(FSI, 0x1840),
+	INTC_VECT(FMSI, 0x1860),
+	INTC_VECT(MIPI_HSI, 0x18e0),
+	INTC_VECT(IPMMU_IPMMUD, 0x1920),
+	INTC_VECT(CEC_1, 0x1940), INTC_VECT(CEC_2, 0x1960),
+	INTC_VECT(AP_ARM_CTIIRQ, 0x1980),
+	INTC_VECT(AP_ARM_DMAEXTERRIRQ, 0x19a0),
+	INTC_VECT(AP_ARM_DMAIRQ, 0x19c0),
+	INTC_VECT(AP_ARM_DMASIRQ, 0x19e0),
+	INTC_VECT(MFIS2, 0x1a00),
+	INTC_VECT(CPORTR2S, 0x1a20),
+	INTC_VECT(CMT14, 0x1a40), INTC_VECT(CMT15, 0x1a60),
+	INTC_VECT(MMC_MMC_ERR, 0x1ac0), INTC_VECT(MMC_MMC_NOR, 0x1ae0),
+	INTC_VECT(IIC4_ALI4, 0x1b00), INTC_VECT(IIC4_TACKI4, 0x1b20),
+	INTC_VECT(IIC4_WAITI4, 0x1b40), INTC_VECT(IIC4_DTEI4, 0x1b60),
+	INTC_VECT(IIC3_ALI3, 0x1b80), INTC_VECT(IIC3_TACKI3, 0x1ba0),
+	INTC_VECT(IIC3_WAITI3, 0x1bc0), INTC_VECT(IIC3_DTEI3, 0x1be0),
+	INTC_VECT(USB0_USB0I1, 0x1c80), INTC_VECT(USB0_USB0I0, 0x1ca0),
+	INTC_VECT(USB1_USB1I1, 0x1cc0), INTC_VECT(USB1_USB1I0, 0x1ce0),
+	INTC_VECT(USBHSDMAC1_USHDMI, 0x1d00),
+};
+
+static struct intc_group intca_groups[] __initdata = {
+	INTC_GROUP(DMAC1_1, DMAC1_1_DEI0,
+		   DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3),
+	INTC_GROUP(DMAC1_2, DMAC1_2_DEI4,
+		   DMAC1_2_DEI5, DMAC1_2_DADERR),
+	INTC_GROUP(DMAC2_1, DMAC2_1_DEI0,
+		   DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3),
+	INTC_GROUP(DMAC2_2, DMAC2_2_DEI4,
+		   DMAC2_2_DEI5, DMAC2_2_DADERR),
+	INTC_GROUP(DMAC3_1, DMAC3_1_DEI0,
+		   DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3),
+	INTC_GROUP(DMAC3_2, DMAC3_2_DEI4,
+		   DMAC3_2_DEI5, DMAC3_2_DADERR),
+	INTC_GROUP(AP_ARM1, AP_ARM_IRQPMU, AP_ARM_COMMTX, AP_ARM_COMMRX),
+	INTC_GROUP(AP_ARM2, AP_ARM_CTIIRQ, AP_ARM_DMAEXTERRIRQ,
+		   AP_ARM_DMAIRQ, AP_ARM_DMASIRQ),
+	INTC_GROUP(SPU2, SPU2_SPU0, SPU2_SPU1),
+	INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI,
+		   FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
+	INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1),
+	INTC_GROUP(SDHI0, SDHI0_SDHI0I0, SDHI0_SDHI0I1,
+		   SDHI0_SDHI0I2, SDHI0_SDHI0I3),
+	INTC_GROUP(SDHI1, SDHI1_SDHI1I0, SDHI1_SDHI1I1,
+		   SDHI1_SDHI1I2),
+	INTC_GROUP(SDHI2, SDHI2_SDHI2I0, SDHI2_SDHI2I1,
+		   SDHI2_SDHI2I2, SDHI2_SDHI2I3),
+	INTC_GROUP(SHWYSTAT, SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM),
+};
+
+static struct intc_mask_reg intca_mask_registers[] __initdata = {
+	{ 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+	{ 0xe6900048, 0xe6900068, 8, /* INTMSK20A / INTMSKCLR20A */
+	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
+	{ 0xe690004c, 0xe690006c, 8, /* INTMSK30A / INTMSKCLR30A */
+	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
+
+	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
+	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
+	    AP_ARM_IRQPMU, 0, AP_ARM_COMMTX, AP_ARM_COMMRX } },
+	{ 0xe6940084, 0xe69400c4, 8, /* IMR1A / IMCR1A */
+	  { 0, CRYPT_STD, DIRC, 0,
+	    DMAC1_1_DEI3, DMAC1_1_DEI2, DMAC1_1_DEI1, DMAC1_1_DEI0 } },
+	{ 0xe6940088, 0xe69400c8, 8, /* IMR2A / IMCR2A */
+	  { 0, 0, 0, 0,
+	    BBIF1, BBIF2, MFI_MFIS, MFI_MFIM } },
+	{ 0xe694008c, 0xe69400cc, 8, /* IMR3A / IMCR3A */
+	  { DMAC3_1_DEI3, DMAC3_1_DEI2, DMAC3_1_DEI1, DMAC3_1_DEI0,
+	    DMAC3_2_DADERR, DMAC3_2_DEI5, DMAC3_2_DEI4, IRDA } },
+	{ 0xe6940090, 0xe69400d0, 8, /* IMR4A / IMCR4A */
+	  { DDM, 0, 0, 0,
+	    0, 0, 0, 0 } },
+	{ 0xe6940094, 0xe69400d4, 8, /* IMR5A / IMCR5A */
+	  { KEYSC_KEY, DMAC1_2_DADERR, DMAC1_2_DEI5, DMAC1_2_DEI4,
+	    SCIFA3, SCIFA2, SCIFA1, SCIFA0 } },
+	{ 0xe6940098, 0xe69400d8, 8, /* IMR6A / IMCR6A */
+	  { SCIFB, SCIFA5, SCIFA4, MSIOF1,
+	    0, 0, MSIOF2, 0 } },
+	{ 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */
+	  { SDHI0_SDHI0I3, SDHI0_SDHI0I2, SDHI0_SDHI0I1, SDHI0_SDHI0I0,
+	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
+	{ 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */
+	  { 0, SDHI1_SDHI1I2, SDHI1_SDHI1I1, SDHI1_SDHI1I0,
+	    TTI20, USBHSDMAC0_USHDMI, 0, 0 } },
+	{ 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */
+	  { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10,
+	    CMT2, 0, 0, _3DG_SGX540 } },
+	{ 0xe69400a8, 0xe69400e8, 8, /* IMR10A / IMCR10A */
+	  { 0, DMAC2_2_DADERR, DMAC2_2_DEI5, DMAC2_2_DEI4,
+	    0, 0, 0, 0 } },
+	{ 0xe69400ac, 0xe69400ec, 8, /* IMR11A / IMCR11A */
+	  { IIC1_DTEI1, IIC1_WAITI1, IIC1_TACKI1, IIC1_ALI1,
+	    0, 0, IRREM, 0 } },
+	{ 0xe69400b0, 0xe69400f0, 8, /* IMR12A / IMCR12A */
+	  { 0, 0, TPU0, 0,
+	    0, 0, 0, 0 } },
+	{ 0xe69400b4, 0xe69400f4, 8, /* IMR13A / IMCR13A */
+	  { SDHI2_SDHI2I3, SDHI2_SDHI2I2, SDHI2_SDHI2I1, SDHI2_SDHI2I0,
+	    0, CMT3, 0, RWDT0 } },
+	{ 0xe6950080, 0xe69500c0, 8, /* IMR0A3 / IMCR0A3 */
+	  { SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, 0,
+	    0, 0, 0, 0 } },
+	{ 0xe6950090, 0xe69500d0, 8, /* IMR4A3 / IMCR4A3 */
+	  { 0, 0, 0, 0,
+	    0, 0, 0, HDMI } },
+	{ 0xe6950094, 0xe69500d4, 8, /* IMR5A3 / IMCR5A3 */
+	  { SPU2_SPU0, SPU2_SPU1, FSI, FMSI,
+	    0, 0, 0, MIPI_HSI } },
+	{ 0xe6950098, 0xe69500d8, 8, /* IMR6A3 / IMCR6A3 */
+	  { 0, IPMMU_IPMMUD, CEC_1, CEC_2,
+	    AP_ARM_CTIIRQ, AP_ARM_DMAEXTERRIRQ,
+	    AP_ARM_DMAIRQ, AP_ARM_DMASIRQ } },
+	{ 0xe695009c, 0xe69500dc, 8, /* IMR7A3 / IMCR7A3 */
+	  { MFIS2, CPORTR2S, CMT14, CMT15,
+	    0, 0, MMC_MMC_ERR, MMC_MMC_NOR } },
+	{ 0xe69500a0, 0xe69500e0, 8, /* IMR8A3 / IMCR8A3 */
+	  { IIC4_ALI4, IIC4_TACKI4, IIC4_WAITI4, IIC4_DTEI4,
+	    IIC3_ALI3, IIC3_TACKI3, IIC3_WAITI3, IIC3_DTEI3 } },
+	{ 0xe69500a4, 0xe69500e4, 8, /* IMR9A3 / IMCR9A3 */
+	  { 0, 0, 0, 0,
+	    USB0_USB0I1, USB0_USB0I0, USB1_USB1I1, USB1_USB1I0 } },
+	{ 0xe69500a8, 0xe69500e8, 8, /* IMR10A3 / IMCR10A3 */
+	  { USBHSDMAC1_USHDMI, 0, 0, 0,
+	    0, 0, 0, 0 } },
+};
+
+static struct intc_prio_reg intca_prio_registers[] __initdata = {
+	{ 0xe6900010, 0, 32, 4, /* INTPRI00A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900014, 0, 32, 4, /* INTPRI10A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+	{ 0xe6900018, 0, 32, 4, /* INTPRI20A */
+	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
+	{ 0xe690001c, 0, 32, 4, /* INTPRI30A */
+	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
+
+	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, 0 } },
+	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, 0, BBIF1, BBIF2 } },
+	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { 0, CRYPT_STD,
+					      CMT1_CMT11, AP_ARM1 } },
+	{ 0xe694000c, 0, 16, 4, /* IPRDA */ { 0, 0,
+					      CMT1_CMT12, 0 } },
+	{ 0xe6940010, 0, 16, 4, /* IPREA */ { DMAC1_1, MFI_MFIS,
+					      MFI_MFIM, 0 } },
+	{ 0xe6940014, 0, 16, 4, /* IPRFA */ { KEYSC_KEY, DMAC1_2,
+					      _3DG_SGX540, CMT1_CMT10 } },
+	{ 0xe6940018, 0, 16, 4, /* IPRGA */ { SCIFA0, SCIFA1,
+					      SCIFA2, SCIFA3 } },
+	{ 0xe694001c, 0, 16, 4, /* IPRGH */ { MSIOF2, USBHSDMAC0_USHDMI,
+					      FLCTL, SDHI0 } },
+	{ 0xe6940020, 0, 16, 4, /* IPRIA */ { MSIOF1, SCIFA4,
+					      0/* MSU */, IIC1 } },
+	{ 0xe6940024, 0, 16, 4, /* IPRJA */ { DMAC2_1, DMAC2_2,
+					      0/* MSUG */, TTI20 } },
+	{ 0xe6940028, 0, 16, 4, /* IPRKA */ { 0, CMT1_CMT13, IRREM, SDHI1 } },
+	{ 0xe694002c, 0, 16, 4, /* IPRLA */ { TPU0, 0, 0, 0 } },
+	{ 0xe6940030, 0, 16, 4, /* IPRMA */ { 0, CMT3, 0, RWDT0 } },
+	{ 0xe6940034, 0, 16, 4, /* IPRNA */ { SCIFB, SCIFA5, 0, DDM } },
+	{ 0xe6940038, 0, 16, 4, /* IPROA */ { 0, 0, DIRC, SDHI2 } },
+	{ 0xe6950000, 0, 16, 4, /* IPRAA3 */ { SHWYSTAT, 0, 0, 0 } },
+	{ 0xe6950024, 0, 16, 4, /* IPRJA3 */ { 0, 0, 0, HDMI } },
+	{ 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } },
+	{ 0xe695002c, 0, 16, 4, /* IPRLA3 */ { 0, 0, 0, MIPI_HSI } },
+	{ 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU_IPMMUD, 0,
+					       CEC_1, CEC_2 } },
+	{ 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } },
+	{ 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S,
+					       CMT14, CMT15 } },
+	{ 0xe694003c, 0, 16, 4, /* IPRPA3 */ { 0, 0,
+					       MMC_MMC_ERR, MMC_MMC_NOR } },
+	{ 0xe6940040, 0, 16, 4, /* IPRQA3 */ { IIC4_ALI4, IIC4_TACKI4,
+					       IIC4_WAITI4, IIC4_DTEI4 } },
+	{ 0xe6940044, 0, 16, 4, /* IPRRA3 */ { IIC3_ALI3, IIC3_TACKI3,
+					       IIC3_WAITI3, IIC3_DTEI3 } },
+	{ 0xe6940048, 0, 16, 4, /* IPRSA3 */ { 0/*ERI*/, 0/*RXI*/,
+					       0/*TXI*/, 0/*TEI*/} },
+	{ 0xe694004c, 0, 16, 4, /* IPRTA3 */ { USB0_USB0I1, USB0_USB0I0,
+					       USB1_USB1I1, USB1_USB1I0 } },
+	{ 0xe6940050, 0, 16, 4, /* IPRUA3 */ { USBHSDMAC1_USHDMI, 0, 0, 0 } },
+};
+
+static struct intc_sense_reg intca_sense_registers[] __initdata = {
+	{ 0xe6900000, 32, 4, /* ICR1A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900004, 32, 4, /* ICR2A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+	{ 0xe6900008, 32, 4, /* ICR3A */
+	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
+	{ 0xe690000c, 32, 4, /* ICR4A */
+	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
+};
+
+static struct intc_mask_reg intca_ack_registers[] __initdata = {
+	{ 0xe6900020, 0, 8, /* INTREQ00A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900024, 0, 8, /* INTREQ10A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+	{ 0xe6900028, 0, 8, /* INTREQ20A */
+	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
+	{ 0xe690002c, 0, 8, /* INTREQ30A */
+	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
+};
+
+static DECLARE_INTC_DESC_ACK(intca_desc, "sh7372-intca",
+			     intca_vectors, intca_groups,
+			     intca_mask_registers, intca_prio_registers,
+			     intca_sense_registers, intca_ack_registers);
+
+void __init sh7372_init_irq(void)
+{
+	register_intc_controller(&intca_desc);
+}
diff --git a/arch/arm/mach-shmobile/intc-sh7377.c b/arch/arm/mach-shmobile/intc-sh7377.c
new file mode 100644
index 0000000..125021c
--- /dev/null
+++ b/arch/arm/mach-shmobile/intc-sh7377.c
@@ -0,0 +1,350 @@
+/*
+ * sh7377 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/mach-types.h>
+#include <asm/mach/arch.h>
+
+enum {
+	UNUSED_INTCA = 0,
+
+	/* interrupt sources INTCA */
+	IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A,
+	IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A,
+	IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A,
+	IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A,
+	DIRC,
+	_2DG,
+	CRYPT_STD,
+	IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1,
+	AP_ARM_IRQPMU, AP_ARM_COMMTX, AP_ARM_COMMRX,
+	MFI_MFIM, MFI_MFIS,
+	BBIF1, BBIF2,
+	USBDMAC_USHDMI,
+	USBHS_USHI0, USBHS_USHI1,
+	_3DG_SGX540,
+	CMT1_CMT10, CMT1_CMT11, CMT1_CMT12, CMT1_CMT13, CMT2, CMT3,
+	KEYSC_KEY,
+	SCIFA0, SCIFA1, SCIFA2, SCIFA3,
+	MSIOF2, MSIOF1,
+	SCIFA4, SCIFA5, SCIFB,
+	FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
+	SDHI0_SDHI0I0, SDHI0_SDHI0I1, SDHI0_SDHI0I2, SDHI0_SDHI0I3,
+	SDHI1_SDHI1I0, SDHI1_SDHI1I1, SDHI1_SDHI1I2, SDHI1_SDHI1I3,
+	MSU_MSU, MSU_MSU2,
+	IRREM,
+	MSUG,
+	IRDA,
+	TPU0, TPU1, TPU2, TPU3, TPU4,
+	LCRC,
+	PINTCA_PINT1, PINTCA_PINT2,
+	TTI20,
+	MISTY,
+	DDM,
+	RWDT0, RWDT1,
+	DMAC_1_DEI0, DMAC_1_DEI1, DMAC_1_DEI2, DMAC_1_DEI3,
+	DMAC_2_DEI4, DMAC_2_DEI5, DMAC_2_DADERR,
+	DMAC2_1_DEI0, DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3,
+	DMAC2_2_DEI4, DMAC2_2_DEI5, DMAC2_2_DADERR,
+	DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3,
+	DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR,
+	SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM,
+	ICUSB_ICUSB0, ICUSB_ICUSB1,
+	ICUDMC_ICUDMC1, ICUDMC_ICUDMC2,
+	SPU2_SPU0, SPU2_SPU1,
+	FSI,
+	FMSI,
+	SCUV,
+	IPMMU_IPMMUB,
+	AP_ARM_CTIIRQ, AP_ARM_DMAEXTERRIRQ, AP_ARM_DMAIRQ, AP_ARM_DMASIRQ,
+	MFIS2,
+	CPORTR2S,
+	CMT14, CMT15,
+	SCIFA6,
+
+	/* interrupt groups INTCA */
+	DMAC_1, DMAC_2,	DMAC2_1, DMAC2_2, DMAC3_1, DMAC3_2, SHWYSTAT,
+	AP_ARM1, AP_ARM2, USBHS, SPU2, FLCTL, IIC1, SDHI0, SDHI1,
+	ICUSB, ICUDMC
+};
+
+static struct intc_vect intca_vectors[] = {
+	INTC_VECT(IRQ0A, 0x0200), INTC_VECT(IRQ1A, 0x0220),
+	INTC_VECT(IRQ2A, 0x0240), INTC_VECT(IRQ3A, 0x0260),
+	INTC_VECT(IRQ4A, 0x0280), INTC_VECT(IRQ5A, 0x02a0),
+	INTC_VECT(IRQ6A, 0x02c0), INTC_VECT(IRQ7A, 0x02e0),
+	INTC_VECT(IRQ8A, 0x0300), INTC_VECT(IRQ9A, 0x0320),
+	INTC_VECT(IRQ10A, 0x0340), INTC_VECT(IRQ11A, 0x0360),
+	INTC_VECT(IRQ12A, 0x0380), INTC_VECT(IRQ13A, 0x03a0),
+	INTC_VECT(IRQ14A, 0x03c0), INTC_VECT(IRQ15A, 0x03e0),
+	INTC_VECT(IRQ16A, 0x3200), INTC_VECT(IRQ17A, 0x3220),
+	INTC_VECT(IRQ18A, 0x3240), INTC_VECT(IRQ19A, 0x3260),
+	INTC_VECT(IRQ20A, 0x3280), INTC_VECT(IRQ31A, 0x32a0),
+	INTC_VECT(IRQ22A, 0x32c0), INTC_VECT(IRQ23A, 0x32e0),
+	INTC_VECT(IRQ24A, 0x3300), INTC_VECT(IRQ25A, 0x3320),
+	INTC_VECT(IRQ26A, 0x3340), INTC_VECT(IRQ27A, 0x3360),
+	INTC_VECT(IRQ28A, 0x3380), INTC_VECT(IRQ29A, 0x33a0),
+	INTC_VECT(IRQ30A, 0x33c0), INTC_VECT(IRQ31A, 0x33e0),
+	INTC_VECT(DIRC, 0x0560),
+	INTC_VECT(_2DG, 0x05e0),
+	INTC_VECT(CRYPT_STD, 0x0700),
+	INTC_VECT(IIC1_ALI1, 0x0780), INTC_VECT(IIC1_TACKI1, 0x07a0),
+	INTC_VECT(IIC1_WAITI1, 0x07c0), INTC_VECT(IIC1_DTEI1, 0x07e0),
+	INTC_VECT(AP_ARM_IRQPMU, 0x0800), INTC_VECT(AP_ARM_COMMTX, 0x0840),
+	INTC_VECT(AP_ARM_COMMRX, 0x0860),
+	INTC_VECT(MFI_MFIM, 0x0900), INTC_VECT(MFI_MFIS, 0x0920),
+	INTC_VECT(BBIF1, 0x0940), INTC_VECT(BBIF2, 0x0960),
+	INTC_VECT(USBDMAC_USHDMI, 0x0a00),
+	INTC_VECT(USBHS_USHI0, 0x0a20), INTC_VECT(USBHS_USHI1, 0x0a40),
+	INTC_VECT(_3DG_SGX540, 0x0a60),
+	INTC_VECT(CMT1_CMT10, 0x0b00), INTC_VECT(CMT1_CMT11, 0x0b20),
+	INTC_VECT(CMT1_CMT12, 0x0b40), INTC_VECT(CMT1_CMT13, 0x0b60),
+	INTC_VECT(CMT2, 0x0b80), INTC_VECT(CMT3, 0x0ba0),
+	INTC_VECT(KEYSC_KEY, 0x0be0),
+	INTC_VECT(SCIFA0, 0x0c00), INTC_VECT(SCIFA1, 0x0c20),
+	INTC_VECT(SCIFA2, 0x0c40), INTC_VECT(SCIFA3, 0x0c60),
+	INTC_VECT(MSIOF2, 0x0c80), INTC_VECT(MSIOF1, 0x0d00),
+	INTC_VECT(SCIFA4, 0x0d20), INTC_VECT(SCIFA5, 0x0d40),
+	INTC_VECT(SCIFB, 0x0d60),
+	INTC_VECT(FLCTL_FLSTEI, 0x0d80), INTC_VECT(FLCTL_FLTENDI, 0x0da0),
+	INTC_VECT(FLCTL_FLTREQ0I, 0x0dc0), INTC_VECT(FLCTL_FLTREQ1I, 0x0de0),
+	INTC_VECT(SDHI0_SDHI0I0, 0x0e00), INTC_VECT(SDHI0_SDHI0I1, 0x0e20),
+	INTC_VECT(SDHI0_SDHI0I2, 0x0e40), INTC_VECT(SDHI0_SDHI0I3, 0x0e60),
+	INTC_VECT(SDHI1_SDHI1I0, 0x0e80), INTC_VECT(SDHI1_SDHI1I1, 0x0ea0),
+	INTC_VECT(SDHI1_SDHI1I2, 0x0ec0), INTC_VECT(SDHI1_SDHI1I3, 0x0ee0),
+	INTC_VECT(MSU_MSU, 0x0f20), INTC_VECT(MSU_MSU2, 0x0f40),
+	INTC_VECT(IRREM, 0x0f60),
+	INTC_VECT(MSUG, 0x0fa0),
+	INTC_VECT(IRDA, 0x0480),
+	INTC_VECT(TPU0, 0x04a0), INTC_VECT(TPU1, 0x04c0),
+	INTC_VECT(TPU2, 0x04e0), INTC_VECT(TPU3, 0x0500),
+	INTC_VECT(TPU4, 0x0520),
+	INTC_VECT(LCRC, 0x0540),
+	INTC_VECT(PINTCA_PINT1, 0x1000), INTC_VECT(PINTCA_PINT2, 0x1020),
+	INTC_VECT(TTI20, 0x1100),
+	INTC_VECT(MISTY, 0x1120),
+	INTC_VECT(DDM, 0x1140),
+	INTC_VECT(RWDT0, 0x1280), INTC_VECT(RWDT1, 0x12a0),
+	INTC_VECT(DMAC_1_DEI0, 0x2000), INTC_VECT(DMAC_1_DEI1, 0x2020),
+	INTC_VECT(DMAC_1_DEI2, 0x2040), INTC_VECT(DMAC_1_DEI3, 0x2060),
+	INTC_VECT(DMAC_2_DEI4, 0x2080), INTC_VECT(DMAC_2_DEI5, 0x20a0),
+	INTC_VECT(DMAC_2_DADERR, 0x20c0),
+	INTC_VECT(DMAC2_1_DEI0, 0x2100), INTC_VECT(DMAC2_1_DEI1, 0x2120),
+	INTC_VECT(DMAC2_1_DEI2, 0x2140), INTC_VECT(DMAC2_1_DEI3, 0x2160),
+	INTC_VECT(DMAC2_2_DEI4, 0x2180), INTC_VECT(DMAC2_2_DEI5, 0x21a0),
+	INTC_VECT(DMAC2_2_DADERR, 0x21c0),
+	INTC_VECT(DMAC3_1_DEI0, 0x2200), INTC_VECT(DMAC3_1_DEI1, 0x2220),
+	INTC_VECT(DMAC3_1_DEI2, 0x2240), INTC_VECT(DMAC3_1_DEI3, 0x2260),
+	INTC_VECT(DMAC3_2_DEI4, 0x2280), INTC_VECT(DMAC3_2_DEI5, 0x22a0),
+	INTC_VECT(DMAC3_2_DADERR, 0x22c0),
+	INTC_VECT(SHWYSTAT_RT, 0x1300), INTC_VECT(SHWYSTAT_HS, 0x1d20),
+	INTC_VECT(SHWYSTAT_COM, 0x1340),
+	INTC_VECT(ICUSB_ICUSB0, 0x1700), INTC_VECT(ICUSB_ICUSB1, 0x1720),
+	INTC_VECT(ICUDMC_ICUDMC1, 0x1780), INTC_VECT(ICUDMC_ICUDMC2, 0x17a0),
+	INTC_VECT(SPU2_SPU0, 0x1800), INTC_VECT(SPU2_SPU1, 0x1820),
+	INTC_VECT(FSI, 0x1840),
+	INTC_VECT(FMSI, 0x1860),
+	INTC_VECT(SCUV, 0x1880),
+	INTC_VECT(IPMMU_IPMMUB, 0x1900),
+	INTC_VECT(AP_ARM_CTIIRQ, 0x1980),
+	INTC_VECT(AP_ARM_DMAEXTERRIRQ, 0x19a0),
+	INTC_VECT(AP_ARM_DMAIRQ, 0x19c0),
+	INTC_VECT(AP_ARM_DMASIRQ, 0x19e0),
+	INTC_VECT(MFIS2, 0x1a00),
+	INTC_VECT(CPORTR2S, 0x1a20),
+	INTC_VECT(CMT14, 0x1a40), INTC_VECT(CMT15, 0x1a60),
+	INTC_VECT(SCIFA6, 0x1a80),
+};
+
+static struct intc_group intca_groups[] __initdata = {
+	INTC_GROUP(DMAC_1, DMAC_1_DEI0,
+		   DMAC_1_DEI1, DMAC_1_DEI2, DMAC_1_DEI3),
+	INTC_GROUP(DMAC_2, DMAC_2_DEI4,
+		   DMAC_2_DEI5, DMAC_2_DADERR),
+	INTC_GROUP(DMAC2_1, DMAC2_1_DEI0,
+		   DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3),
+	INTC_GROUP(DMAC2_2, DMAC2_2_DEI4,
+		   DMAC2_2_DEI5, DMAC2_2_DADERR),
+	INTC_GROUP(DMAC3_1, DMAC3_1_DEI0,
+		   DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3),
+	INTC_GROUP(DMAC3_2, DMAC3_2_DEI4,
+		   DMAC3_2_DEI5, DMAC3_2_DADERR),
+	INTC_GROUP(AP_ARM1, AP_ARM_IRQPMU, AP_ARM_COMMTX, AP_ARM_COMMTX),
+	INTC_GROUP(USBHS, USBHS_USHI0, USBHS_USHI1),
+	INTC_GROUP(SPU2, SPU2_SPU0, SPU2_SPU1),
+	INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI,
+		   FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
+	INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1),
+	INTC_GROUP(SDHI0, SDHI0_SDHI0I0, SDHI0_SDHI0I1,
+		   SDHI0_SDHI0I2, SDHI0_SDHI0I3),
+	INTC_GROUP(SDHI1, SDHI1_SDHI1I0, SDHI1_SDHI1I1,
+		   SDHI1_SDHI1I2, SDHI1_SDHI1I3),
+	INTC_GROUP(SHWYSTAT, SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM),
+	INTC_GROUP(ICUSB, ICUSB_ICUSB0, ICUSB_ICUSB1),
+	INTC_GROUP(ICUDMC, ICUDMC_ICUDMC1, ICUDMC_ICUDMC2),
+};
+
+static struct intc_mask_reg intca_mask_registers[] = {
+	{ 0xe6900040, 0xe6900060, 8, /* INTMSK00A / INTMSKCLR00A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900044, 0xe6900064, 8, /* INTMSK10A / INTMSKCLR10A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+	{ 0xe6900048, 0xe6900068, 8, /* INTMSK20A / INTMSKCLR20A */
+	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
+	{ 0xe690004c, 0xe690006c, 8, /* INTMSK30A / INTMSKCLR30A */
+	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
+
+	{ 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
+	  { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
+	    AP_ARM_IRQPMU, 0, AP_ARM_COMMTX, AP_ARM_COMMRX } },
+	{ 0xe6940084, 0xe69400c4, 8, /* IMR1A / IMCR1A */
+	  { _2DG, CRYPT_STD, DIRC, 0,
+	    DMAC_1_DEI3, DMAC_1_DEI2, DMAC_1_DEI1, DMAC_1_DEI0 } },
+	{ 0xe6940088, 0xe69400c8, 8, /* IMR2A / IMCR2A */
+	  { PINTCA_PINT1, PINTCA_PINT2, 0, 0,
+	    BBIF1, BBIF2, MFI_MFIS, MFI_MFIM } },
+	{ 0xe694008c, 0xe69400cc, 8, /* IMR3A / IMCR3A */
+	  { DMAC3_1_DEI3, DMAC3_1_DEI2, DMAC3_1_DEI1, DMAC3_1_DEI0,
+	    DMAC3_2_DADERR, DMAC3_2_DEI5, DMAC3_2_DEI4, IRDA } },
+	{ 0xe6940090, 0xe69400d0, 8, /* IMR4A / IMCR4A */
+	  { DDM, 0, 0, 0,
+	    0, 0, 0, 0 } },
+	{ 0xe6940094, 0xe69400d4, 8, /* IMR5A / IMCR5A */
+	  { KEYSC_KEY, DMAC_2_DADERR, DMAC_2_DEI5, DMAC_2_DEI4,
+	    SCIFA3, SCIFA2, SCIFA1, SCIFA0 } },
+	{ 0xe6940098, 0xe69400d8, 8, /* IMR6A / IMCR6A */
+	  { SCIFB, SCIFA5, SCIFA4, MSIOF1,
+	    0, 0, MSIOF2, 0 } },
+	{ 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */
+	  { SDHI0_SDHI0I3, SDHI0_SDHI0I2, SDHI0_SDHI0I1, SDHI0_SDHI0I0,
+	    FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
+	{ 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */
+	  { SDHI1_SDHI1I3, SDHI1_SDHI1I2, SDHI1_SDHI1I1, SDHI1_SDHI1I0,
+	    TTI20, USBDMAC_USHDMI, 0, MSUG } },
+	{ 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */
+	  { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10,
+	    CMT2, USBHS_USHI1, USBHS_USHI0, _3DG_SGX540 } },
+	{ 0xe69400a8, 0xe69400e8, 8, /* IMR10A / IMCR10A */
+	  { 0, DMAC2_2_DADERR, DMAC2_2_DEI5, DMAC2_2_DEI4,
+	    0, 0, 0, 0 } },
+	{ 0xe69400ac, 0xe69400ec, 8, /* IMR11A / IMCR11A */
+	  { IIC1_DTEI1, IIC1_WAITI1, IIC1_TACKI1, IIC1_ALI1,
+	    LCRC, MSU_MSU2, IRREM, MSU_MSU } },
+	{ 0xe69400b0, 0xe69400f0, 8, /* IMR12A / IMCR12A */
+	  { 0, 0, TPU0, TPU1,
+	    TPU2, TPU3, TPU4, 0 } },
+	{ 0xe69400b4, 0xe69400f4, 8, /* IMR13A / IMCR13A */
+	  { 0, 0, 0, 0,
+	    MISTY, CMT3, RWDT1, RWDT0 } },
+	{ 0xe6950080, 0xe69500c0, 8, /* IMR0A3 / IMCR0A3 */
+	  { SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, 0,
+	    0, 0, 0, 0 } },
+	{ 0xe6950090, 0xe69500d0, 8, /* IMR4A3 / IMCR4A3 */
+	  { ICUSB_ICUSB0, ICUSB_ICUSB1, 0, 0,
+	    ICUDMC_ICUDMC1, ICUDMC_ICUDMC2, 0, 0 } },
+	{ 0xe6950094, 0xe69500d4, 8, /* IMR5A3 / IMCR5A3 */
+	  { SPU2_SPU0, SPU2_SPU1, FSI, FMSI,
+	    SCUV, 0, 0, 0 } },
+	{ 0xe6950098, 0xe69500d8, 8, /* IMR6A3 / IMCR6A3 */
+	  { IPMMU_IPMMUB, 0, 0, 0,
+	    AP_ARM_CTIIRQ, AP_ARM_DMAEXTERRIRQ,
+	    AP_ARM_DMAIRQ, AP_ARM_DMASIRQ } },
+	{ 0xe695009c, 0xe69500dc, 8, /* IMR7A3 / IMCR7A3 */
+	  { MFIS2, CPORTR2S, CMT14, CMT15,
+	    SCIFA6, 0, 0, 0 } },
+};
+
+static struct intc_prio_reg intca_prio_registers[] = {
+	{ 0xe6900010, 0, 32, 4, /* INTPRI00A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900014, 0, 32, 4, /* INTPRI10A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+	{ 0xe6900018, 0, 32, 4, /* INTPRI10A */
+	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
+	{ 0xe690001c, 0, 32, 4, /* INTPRI30A */
+	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
+
+	{ 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, LCRC } },
+	{ 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, 0, BBIF1, BBIF2 } },
+	{ 0xe6940008, 0, 16, 4, /* IPRCA */ { _2DG, CRYPT_STD,
+					      CMT1_CMT11, AP_ARM1 } },
+	{ 0xe694000c, 0, 16, 4, /* IPRDA */ { PINTCA_PINT1, PINTCA_PINT2,
+					      CMT1_CMT12, TPU4 } },
+	{ 0xe6940010, 0, 16, 4, /* IPREA */ { DMAC_1, MFI_MFIS,
+					      MFI_MFIM, USBHS } },
+	{ 0xe6940014, 0, 16, 4, /* IPRFA */ { KEYSC_KEY, DMAC_2,
+					      _3DG_SGX540, CMT1_CMT10 } },
+	{ 0xe6940018, 0, 16, 4, /* IPRGA */ { SCIFA0, SCIFA1,
+					      SCIFA2, SCIFA3 } },
+	{ 0xe694001c, 0, 16, 4, /* IPRGH */ { MSIOF2, USBDMAC_USHDMI,
+					      FLCTL, SDHI0 } },
+	{ 0xe6940020, 0, 16, 4, /* IPRIA */ { MSIOF1, SCIFA4, MSU_MSU, IIC1 } },
+	{ 0xe6940024, 0, 16, 4, /* IPRJA */ { DMAC2_1, DMAC2_2, MSUG, TTI20 } },
+	{ 0xe6940028, 0, 16, 4, /* IPRKA */ { 0, CMT1_CMT13, IRREM, SDHI1 } },
+	{ 0xe694002c, 0, 16, 4, /* IPRLA */ { TPU0, TPU1, TPU2, TPU3 } },
+	{ 0xe6940030, 0, 16, 4, /* IPRMA */ { MISTY, CMT3, RWDT1, RWDT0 } },
+	{ 0xe6940034, 0, 16, 4, /* IPRNA */ { SCIFB, SCIFA5, 0, DDM } },
+	{ 0xe6940038, 0, 16, 4, /* IPROA */ { 0, 0, DIRC, 0 } },
+	{ 0xe6950000, 0, 16, 4, /* IPRAA3 */ { SHWYSTAT, 0, 0, 0 } },
+	{ 0xe6950020, 0, 16, 4, /* IPRIA3 */ { ICUSB, 0, 0, 0 } },
+	{ 0xe6950024, 0, 16, 4, /* IPRJA3 */ { ICUDMC, 0, 0, 0 } },
+	{ 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } },
+	{ 0xe695002c, 0, 16, 4, /* IPRLA3 */ { SCUV, 0, 0, 0 } },
+	{ 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU_IPMMUB, 0, 0, 0 } },
+	{ 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } },
+	{ 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S,
+					       CMT14, CMT15 } },
+	{ 0xe694003c, 0, 16, 4, /* IPRPA3 */ { SCIFA6, 0, 0, 0 } },
+};
+
+static struct intc_sense_reg intca_sense_registers[] __initdata = {
+	{ 0xe6900000, 16, 2, /* ICR1A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900004, 16, 2, /* ICR2A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+	{ 0xe6900008, 16, 2, /* ICR3A */
+	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
+	{ 0xe690000c, 16, 2, /* ICR4A */
+	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
+};
+
+static struct intc_mask_reg intca_ack_registers[] __initdata = {
+	{ 0xe6900020, 0, 8, /* INTREQ00A */
+	  { IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A } },
+	{ 0xe6900024, 0, 8, /* INTREQ10A */
+	  { IRQ8A, IRQ9A, IRQ10A, IRQ11A, IRQ12A, IRQ13A, IRQ14A, IRQ15A } },
+	{ 0xe6900028, 0, 8, /* INTREQ20A */
+	  { IRQ16A, IRQ17A, IRQ18A, IRQ19A, IRQ20A, IRQ21A, IRQ22A, IRQ23A } },
+	{ 0xe690002c, 0, 8, /* INTREQ30A */
+	  { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
+};
+
+static DECLARE_INTC_DESC_ACK(intca_desc, "sh7377-intca",
+			     intca_vectors, intca_groups,
+			     intca_mask_registers, intca_prio_registers,
+			     intca_sense_registers, intca_ack_registers);
+
+void __init sh7377_init_irq(void)
+{
+	register_intc_controller(&intca_desc);
+}
diff --git a/arch/arm/mach-shmobile/pfc-sh7367.c b/arch/arm/mach-shmobile/pfc-sh7367.c
new file mode 100644
index 0000000..128555e
--- /dev/null
+++ b/arch/arm/mach-shmobile/pfc-sh7367.c
@@ -0,0 +1,1801 @@
+/*
+ * sh7367 processor support - PFC 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/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <mach/sh7367.h>
+
+#define _1(fn, pfx, sfx) fn(pfx, sfx)
+
+#define _10(fn, pfx, sfx)				\
+	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
+	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
+	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
+	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
+	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
+
+#define _90(fn, pfx, sfx)				\
+	_10(fn, pfx##1, sfx), _10(fn, pfx##2, sfx),	\
+	_10(fn, pfx##3, sfx), _10(fn, pfx##4, sfx),	\
+	_10(fn, pfx##5, sfx), _10(fn, pfx##6, sfx),	\
+	_10(fn, pfx##7, sfx), _10(fn, pfx##8, sfx),	\
+	_10(fn, pfx##9, sfx)
+
+#define _273(fn, pfx, sfx)		\
+	_10(fn, pfx, sfx), _90(fn, pfx, sfx),		\
+	_10(fn, pfx##10, sfx), _90(fn, pfx##1, sfx),	\
+	_10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),	\
+	_10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),	\
+	_10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),	\
+	_10(fn, pfx##26, sfx), _1(fn, pfx##270, sfx),	\
+	_1(fn, pfx##271, sfx), _1(fn, pfx##272, sfx)
+
+#define _PORT(pfx, sfx) pfx##_##sfx
+#define PORT_273(str) _273(_PORT, PORT, str)
+
+enum {
+	PINMUX_RESERVED = 0,
+
+	PINMUX_DATA_BEGIN,
+	PORT_273(DATA), /* PORT0_DATA -> PORT272_DATA */
+	PINMUX_DATA_END,
+
+	PINMUX_INPUT_BEGIN,
+	PORT_273(IN), /* PORT0_IN -> PORT272_IN */
+	PINMUX_INPUT_END,
+
+	PINMUX_INPUT_PULLUP_BEGIN,
+	PORT_273(IN_PU), /* PORT0_IN_PU -> PORT272_IN_PU */
+	PINMUX_INPUT_PULLUP_END,
+
+	PINMUX_INPUT_PULLDOWN_BEGIN,
+	PORT_273(IN_PD), /* PORT0_IN_PD -> PORT272_IN_PD */
+	PINMUX_INPUT_PULLDOWN_END,
+
+	PINMUX_OUTPUT_BEGIN,
+	PORT_273(OUT), /* PORT0_OUT -> PORT272_OUT */
+	PINMUX_OUTPUT_END,
+
+	PINMUX_FUNCTION_BEGIN,
+	PORT_273(FN_IN), /* PORT0_FN_IN -> PORT272_FN_IN */
+	PORT_273(FN_OUT), /* PORT0_FN_OUT -> PORT272_FN_OUT */
+	PORT_273(FN0), /* PORT0_FN0 -> PORT272_FN0 */
+	PORT_273(FN1), /* PORT0_FN1 -> PORT272_FN1 */
+	PORT_273(FN2), /* PORT0_FN2 -> PORT272_FN2 */
+	PORT_273(FN3), /* PORT0_FN3 -> PORT272_FN3 */
+	PORT_273(FN4), /* PORT0_FN4 -> PORT272_FN4 */
+	PORT_273(FN5), /* PORT0_FN5 -> PORT272_FN5 */
+	PORT_273(FN6), /* PORT0_FN6 -> PORT272_FN6 */
+	PORT_273(FN7), /* PORT0_FN7 -> PORT272_FN7 */
+
+	MSELBCR_MSEL2_1, MSELBCR_MSEL2_0,
+	PINMUX_FUNCTION_END,
+
+	PINMUX_MARK_BEGIN,
+	/* Special Pull-up / Pull-down Functions */
+	PORT48_KEYIN0_PU_MARK, PORT49_KEYIN1_PU_MARK,
+	PORT50_KEYIN2_PU_MARK, PORT55_KEYIN3_PU_MARK,
+	PORT56_KEYIN4_PU_MARK, PORT57_KEYIN5_PU_MARK,
+	PORT58_KEYIN6_PU_MARK,
+
+	/* 49-1 */
+	VBUS0_MARK, CPORT0_MARK, CPORT1_MARK, CPORT2_MARK,
+	CPORT3_MARK, CPORT4_MARK, CPORT5_MARK, CPORT6_MARK,
+	CPORT7_MARK, CPORT8_MARK, CPORT9_MARK, CPORT10_MARK,
+	CPORT11_MARK, SIN2_MARK, CPORT12_MARK, XCTS2_MARK,
+	CPORT13_MARK, RFSPO4_MARK, CPORT14_MARK, RFSPO5_MARK,
+	CPORT15_MARK, CPORT16_MARK, CPORT17_MARK, SOUT2_MARK,
+	CPORT18_MARK, XRTS2_MARK, CPORT19_MARK, CPORT20_MARK,
+	RFSPO6_MARK, CPORT21_MARK, STATUS0_MARK, CPORT22_MARK,
+	STATUS1_MARK, CPORT23_MARK, STATUS2_MARK, RFSPO7_MARK,
+	MPORT0_MARK, MPORT1_MARK, B_SYNLD1_MARK, B_SYNLD2_MARK,
+	XMAINPS_MARK, XDIVPS_MARK, XIDRST_MARK, IDCLK_MARK,
+	IDIO_MARK, SOUT1_MARK, SCIFA4_TXD_MARK,
+	M02_BERDAT_MARK, SIN1_MARK, SCIFA4_RXD_MARK, XWUP_MARK,
+	XRTS1_MARK, SCIFA4_RTS_MARK, M03_BERCLK_MARK,
+	XCTS1_MARK, SCIFA4_CTS_MARK,
+
+	/* 49-2 */
+	HSU_IQ_AGC6_MARK, MFG2_IN2_MARK, MSIOF2_MCK0_MARK,
+	HSU_IQ_AGC5_MARK, MFG2_IN1_MARK, MSIOF2_MCK1_MARK,
+	HSU_IQ_AGC4_MARK, MSIOF2_RSYNC_MARK,
+	HSU_IQ_AGC3_MARK, MFG2_OUT1_MARK, MSIOF2_RSCK_MARK,
+	HSU_IQ_AGC2_MARK, PORT42_KEYOUT0_MARK,
+	HSU_IQ_AGC1_MARK, PORT43_KEYOUT1_MARK,
+	HSU_IQ_AGC0_MARK, PORT44_KEYOUT2_MARK,
+	HSU_IQ_AGC_ST_MARK, PORT45_KEYOUT3_MARK,
+	HSU_IQ_PDO_MARK, PORT46_KEYOUT4_MARK,
+	HSU_IQ_PYO_MARK, PORT47_KEYOUT5_MARK,
+	HSU_EN_TXMUX_G3MO_MARK, PORT48_KEYIN0_MARK,
+	HSU_I_TXMUX_G3MO_MARK, PORT49_KEYIN1_MARK,
+	HSU_Q_TXMUX_G3MO_MARK, PORT50_KEYIN2_MARK,
+	HSU_SYO_MARK, PORT51_MSIOF2_TSYNC_MARK,
+	HSU_SDO_MARK, PORT52_MSIOF2_TSCK_MARK,
+	HSU_TGTTI_G3MO_MARK, PORT53_MSIOF2_TXD_MARK,
+	B_TIME_STAMP_MARK, PORT54_MSIOF2_RXD_MARK,
+	HSU_SDI_MARK, PORT55_KEYIN3_MARK,
+	HSU_SCO_MARK, PORT56_KEYIN4_MARK,
+	HSU_DREQ_MARK, PORT57_KEYIN5_MARK,
+	HSU_DACK_MARK, PORT58_KEYIN6_MARK,
+	HSU_CLK61M_MARK, PORT59_MSIOF2_SS1_MARK,
+	HSU_XRST_MARK, PORT60_MSIOF2_SS2_MARK,
+	PCMCLKO_MARK, SYNC8KO_MARK, DNPCM_A_MARK, UPPCM_A_MARK,
+	XTALB1L_MARK,
+	GPS_AGC1_MARK, SCIFA0_RTS_MARK,
+	GPS_AGC2_MARK, SCIFA0_SCK_MARK,
+	GPS_AGC3_MARK, SCIFA0_TXD_MARK,
+	GPS_AGC4_MARK, SCIFA0_RXD_MARK,
+	GPS_PWRD_MARK, SCIFA0_CTS_MARK,
+	GPS_IM_MARK, GPS_IS_MARK, GPS_QM_MARK, GPS_QS_MARK,
+	SIUBOMC_MARK, TPU2TO0_MARK,
+	SIUCKB_MARK, TPU2TO1_MARK,
+	SIUBOLR_MARK, BBIF2_TSYNC_MARK, TPU2TO2_MARK,
+	SIUBOBT_MARK, BBIF2_TSCK_MARK, TPU2TO3_MARK,
+	SIUBOSLD_MARK, BBIF2_TXD_MARK, TPU3TO0_MARK,
+	SIUBILR_MARK, TPU3TO1_MARK,
+	SIUBIBT_MARK, TPU3TO2_MARK,
+	SIUBISLD_MARK, TPU3TO3_MARK,
+	NMI_MARK, TPU4TO0_MARK,
+	DNPCM_M_MARK, TPU4TO1_MARK, TPU4TO2_MARK, TPU4TO3_MARK,
+	IRQ_TMPB_MARK,
+	PWEN_MARK, MFG1_OUT1_MARK,
+	OVCN_MARK, MFG1_IN1_MARK,
+	OVCN2_MARK, MFG1_IN2_MARK,
+
+	/* 49-3 */
+	RFSPO1_MARK, RFSPO2_MARK, RFSPO3_MARK, PORT93_VIO_CKO2_MARK,
+	USBTERM_MARK, EXTLP_MARK, IDIN_MARK,
+	SCIFA5_CTS_MARK, MFG0_IN1_MARK,
+	SCIFA5_RTS_MARK, MFG0_IN2_MARK,
+	SCIFA5_RXD_MARK,
+	SCIFA5_TXD_MARK,
+	SCIFA5_SCK_MARK, MFG0_OUT1_MARK,
+	A0_EA0_MARK, BS_MARK,
+	A14_EA14_MARK, PORT102_KEYOUT0_MARK,
+	A15_EA15_MARK, PORT103_KEYOUT1_MARK, DV_CLKOL_MARK,
+	A16_EA16_MARK, PORT104_KEYOUT2_MARK,
+	DV_VSYNCL_MARK, MSIOF0_SS1_MARK,
+	A17_EA17_MARK, PORT105_KEYOUT3_MARK,
+	DV_HSYNCL_MARK, MSIOF0_TSYNC_MARK,
+	A18_EA18_MARK, PORT106_KEYOUT4_MARK,
+	DV_DL0_MARK, MSIOF0_TSCK_MARK,
+	A19_EA19_MARK, PORT107_KEYOUT5_MARK,
+	DV_DL1_MARK, MSIOF0_TXD_MARK,
+	A20_EA20_MARK, PORT108_KEYIN0_MARK,
+	DV_DL2_MARK, MSIOF0_RSCK_MARK,
+	A21_EA21_MARK, PORT109_KEYIN1_MARK,
+	DV_DL3_MARK, MSIOF0_RSYNC_MARK,
+	A22_EA22_MARK, PORT110_KEYIN2_MARK,
+	DV_DL4_MARK, MSIOF0_MCK0_MARK,
+	A23_EA23_MARK, PORT111_KEYIN3_MARK,
+	DV_DL5_MARK, MSIOF0_MCK1_MARK,
+	A24_EA24_MARK, PORT112_KEYIN4_MARK,
+	DV_DL6_MARK, MSIOF0_RXD_MARK,
+	A25_EA25_MARK, PORT113_KEYIN5_MARK,
+	DV_DL7_MARK, MSIOF0_SS2_MARK,
+	A26_MARK, PORT113_KEYIN6_MARK, DV_CLKIL_MARK,
+	D0_ED0_NAF0_MARK, D1_ED1_NAF1_MARK, D2_ED2_NAF2_MARK,
+	D3_ED3_NAF3_MARK, D4_ED4_NAF4_MARK, D5_ED5_NAF5_MARK,
+	D6_ED6_NAF6_MARK, D7_ED7_NAF7_MARK, D8_ED8_NAF8_MARK,
+	D9_ED9_NAF9_MARK, D10_ED10_NAF10_MARK, D11_ED11_NAF11_MARK,
+	D12_ED12_NAF12_MARK, D13_ED13_NAF13_MARK,
+	D14_ED14_NAF14_MARK, D15_ED15_NAF15_MARK,
+	CS4_MARK, CS5A_MARK, CS5B_MARK, FCE1_MARK,
+	CS6B_MARK, XCS2_MARK, FCE0_MARK, CS6A_MARK,
+	DACK0_MARK, WAIT_MARK, DREQ0_MARK, RD_XRD_MARK,
+	A27_MARK, RDWR_XWE_MARK, WE0_XWR0_FWE_MARK,
+	WE1_XWR1_MARK, FRB_MARK, CKO_MARK,
+	NBRSTOUT_MARK, NBRST_MARK,
+
+	/* 49-4 */
+	RFSPO0_MARK, PORT146_VIO_CKO2_MARK, TSTMD_MARK,
+	VIO_VD_MARK, VIO_HD_MARK,
+	VIO_D0_MARK, VIO_D1_MARK, VIO_D2_MARK,
+	VIO_D3_MARK, VIO_D4_MARK, VIO_D5_MARK,
+	VIO_D6_MARK, VIO_D7_MARK, VIO_D8_MARK,
+	VIO_D9_MARK, VIO_D10_MARK, VIO_D11_MARK,
+	VIO_D12_MARK, VIO_D13_MARK, VIO_D14_MARK,
+	VIO_D15_MARK, VIO_CLK_MARK, VIO_FIELD_MARK,
+	VIO_CKO_MARK,
+	MFG3_IN1_MARK, MFG3_IN2_MARK,
+	M9_SLCD_A01_MARK, MFG3_OUT1_MARK, TPU0TO0_MARK,
+	M10_SLCD_CK1_MARK, MFG4_IN1_MARK, TPU0TO1_MARK,
+	M11_SLCD_SO1_MARK, MFG4_IN2_MARK, TPU0TO2_MARK,
+	M12_SLCD_CE1_MARK, MFG4_OUT1_MARK, TPU0TO3_MARK,
+	LCDD0_MARK, PORT175_KEYOUT0_MARK, DV_D0_MARK,
+	SIUCKA_MARK, MFG0_OUT2_MARK,
+	LCDD1_MARK, PORT176_KEYOUT1_MARK, DV_D1_MARK,
+	SIUAOLR_MARK, BBIF2_TSYNC1_MARK,
+	LCDD2_MARK, PORT177_KEYOUT2_MARK, DV_D2_MARK,
+	SIUAOBT_MARK, BBIF2_TSCK1_MARK,
+	LCDD3_MARK, PORT178_KEYOUT3_MARK, DV_D3_MARK,
+	SIUAOSLD_MARK, BBIF2_TXD1_MARK,
+	LCDD4_MARK, PORT179_KEYOUT4_MARK, DV_D4_MARK,
+	SIUAISPD_MARK, MFG1_OUT2_MARK,
+	LCDD5_MARK, PORT180_KEYOUT5_MARK, DV_D5_MARK,
+	SIUAILR_MARK, MFG2_OUT2_MARK,
+	LCDD6_MARK, DV_D6_MARK,
+	SIUAIBT_MARK, MFG3_OUT2_MARK, XWR2_MARK,
+	LCDD7_MARK, DV_D7_MARK,
+	SIUAISLD_MARK, MFG4_OUT2_MARK, XWR3_MARK,
+	LCDD8_MARK, DV_D8_MARK, D16_MARK, ED16_MARK,
+	LCDD9_MARK, DV_D9_MARK, D17_MARK, ED17_MARK,
+	LCDD10_MARK, DV_D10_MARK, D18_MARK, ED18_MARK,
+	LCDD11_MARK, DV_D11_MARK, D19_MARK, ED19_MARK,
+	LCDD12_MARK, DV_D12_MARK, D20_MARK, ED20_MARK,
+	LCDD13_MARK, DV_D13_MARK, D21_MARK, ED21_MARK,
+	LCDD14_MARK, DV_D14_MARK, D22_MARK, ED22_MARK,
+	LCDD15_MARK, DV_D15_MARK, D23_MARK, ED23_MARK,
+	LCDD16_MARK, DV_HSYNC_MARK, D24_MARK, ED24_MARK,
+	LCDD17_MARK, DV_VSYNC_MARK, D25_MARK, ED25_MARK,
+	LCDD18_MARK, DREQ2_MARK, MSIOF0L_TSCK_MARK,
+	D26_MARK, ED26_MARK,
+	LCDD19_MARK, MSIOF0L_TSYNC_MARK,
+	D27_MARK, ED27_MARK,
+	LCDD20_MARK, TS_SPSYNC1_MARK, MSIOF0L_MCK0_MARK,
+	D28_MARK, ED28_MARK,
+	LCDD21_MARK, TS_SDAT1_MARK, MSIOF0L_MCK1_MARK,
+	D29_MARK, ED29_MARK,
+	LCDD22_MARK, TS_SDEN1_MARK, MSIOF0L_SS1_MARK,
+	D30_MARK, ED30_MARK,
+	LCDD23_MARK, TS_SCK1_MARK, MSIOF0L_SS2_MARK,
+	D31_MARK, ED31_MARK,
+	LCDDCK_MARK, LCDWR_MARK, DV_CKO_MARK, SIUAOSPD_MARK,
+	LCDRD_MARK, DACK2_MARK, MSIOF0L_RSYNC_MARK,
+
+	/* 49-5 */
+	LCDHSYN_MARK, LCDCS_MARK, LCDCS2_MARK, DACK3_MARK,
+	LCDDISP_MARK, LCDRS_MARK, DREQ3_MARK, MSIOF0L_RSCK_MARK,
+	LCDCSYN_MARK, LCDCSYN2_MARK, DV_CKI_MARK,
+	LCDLCLK_MARK, DREQ1_MARK, MSIOF0L_RXD_MARK,
+	LCDDON_MARK, LCDDON2_MARK, DACK1_MARK, MSIOF0L_TXD_MARK,
+	VIO_DR0_MARK, VIO_DR1_MARK, VIO_DR2_MARK, VIO_DR3_MARK,
+	VIO_DR4_MARK, VIO_DR5_MARK, VIO_DR6_MARK, VIO_DR7_MARK,
+	VIO_VDR_MARK, VIO_HDR_MARK,
+	VIO_CLKR_MARK, VIO_CKOR_MARK,
+	SCIFA1_TXD_MARK, GPS_PGFA0_MARK,
+	SCIFA1_SCK_MARK, GPS_PGFA1_MARK,
+	SCIFA1_RTS_MARK, GPS_EPPSINMON_MARK,
+	SCIFA1_RXD_MARK, SCIFA1_CTS_MARK,
+	MSIOF1_TXD_MARK, SCIFA1_TXD2_MARK, GPS_TXD_MARK,
+	MSIOF1_TSYNC_MARK, SCIFA1_CTS2_MARK, I2C_SDA2_MARK,
+	MSIOF1_TSCK_MARK, SCIFA1_SCK2_MARK,
+	MSIOF1_RXD_MARK, SCIFA1_RXD2_MARK, GPS_RXD_MARK,
+	MSIOF1_RSCK_MARK, SCIFA1_RTS2_MARK,
+	MSIOF1_RSYNC_MARK, I2C_SCL2_MARK,
+	MSIOF1_MCK0_MARK, MSIOF1_MCK1_MARK,
+	MSIOF1_SS1_MARK, EDBGREQ3_MARK,
+	MSIOF1_SS2_MARK,
+	PORT236_IROUT_MARK, IRDA_OUT_MARK,
+	IRDA_IN_MARK, IRDA_FIRSEL_MARK,
+	TPU1TO0_MARK, TS_SPSYNC3_MARK,
+	TPU1TO1_MARK, TS_SDAT3_MARK,
+	TPU1TO2_MARK, TS_SDEN3_MARK, PORT241_MSIOF2_SS1_MARK,
+	TPU1TO3_MARK, PORT242_MSIOF2_TSCK_MARK,
+	M13_BSW_MARK, PORT243_MSIOF2_TSYNC_MARK,
+	M14_GSW_MARK, PORT244_MSIOF2_TXD_MARK,
+	PORT245_IROUT_MARK, M15_RSW_MARK,
+	SOUT3_MARK, SCIFA2_TXD1_MARK,
+	SIN3_MARK, SCIFA2_RXD1_MARK,
+	XRTS3_MARK, SCIFA2_RTS1_MARK, PORT248_MSIOF2_SS2_MARK,
+	XCTS3_MARK, SCIFA2_CTS1_MARK, PORT249_MSIOF2_RXD_MARK,
+	DINT_MARK, SCIFA2_SCK1_MARK, TS_SCK3_MARK,
+	SDHICLK0_MARK, TCK2_MARK,
+	SDHICD0_MARK,
+	SDHID0_0_MARK, TMS2_MARK,
+	SDHID0_1_MARK, TDO2_MARK,
+	SDHID0_2_MARK, TDI2_MARK,
+	SDHID0_3_MARK, RTCK2_MARK,
+
+	/* 49-6 */
+	SDHICMD0_MARK, TRST2_MARK,
+	SDHIWP0_MARK, EDBGREQ2_MARK,
+	SDHICLK1_MARK, TCK3_MARK,
+	SDHID1_0_MARK, M11_SLCD_SO2_MARK,
+	TS_SPSYNC2_MARK, TMS3_MARK,
+	SDHID1_1_MARK, M9_SLCD_AO2_MARK,
+	TS_SDAT2_MARK, TDO3_MARK,
+	SDHID1_2_MARK, M10_SLCD_CK2_MARK,
+	TS_SDEN2_MARK, TDI3_MARK,
+	SDHID1_3_MARK, M12_SLCD_CE2_MARK,
+	TS_SCK2_MARK, RTCK3_MARK,
+	SDHICMD1_MARK, TRST3_MARK,
+	SDHICLK2_MARK, SCIFB_SCK_MARK,
+	SDHID2_0_MARK, SCIFB_TXD_MARK,
+	SDHID2_1_MARK, SCIFB_CTS_MARK,
+	SDHID2_2_MARK, SCIFB_RXD_MARK,
+	SDHID2_3_MARK, SCIFB_RTS_MARK,
+	SDHICMD2_MARK,
+	RESETOUTS_MARK,
+	DIVLOCK_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 */
+
+	/* 49-1 (GPIO) */
+	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_PU(9),
+	PORT_DATA_I_PU(10), PORT_DATA_I_PU(11), PORT_DATA_I_PU(12),
+	PORT_DATA_I_PU(13),
+	PORT_DATA_IO_PU_PD(14), PORT_DATA_IO_PU_PD(15),
+	PORT_DATA_O(16), PORT_DATA_O(17), PORT_DATA_O(18), PORT_DATA_O(19),
+	PORT_DATA_O(20), PORT_DATA_O(21), PORT_DATA_O(22), PORT_DATA_O(23),
+	PORT_DATA_O(24), PORT_DATA_O(25), PORT_DATA_O(26),
+	PORT_DATA_I_PD(27), PORT_DATA_I_PD(28),
+	PORT_DATA_O(29), PORT_DATA_O(30), PORT_DATA_O(31), PORT_DATA_O(32),
+	PORT_DATA_IO_PU(33),
+	PORT_DATA_O(34),
+	PORT_DATA_I_PU(35),
+	PORT_DATA_O(36),
+	PORT_DATA_I_PU_PD(37),
+
+	/* 49-2 (GPIO) */
+	PORT_DATA_IO_PU_PD(38),
+	PORT_DATA_IO_PD(39), PORT_DATA_IO_PD(40), PORT_DATA_IO_PD(41),
+	PORT_DATA_O(42), PORT_DATA_O(43), PORT_DATA_O(44), PORT_DATA_O(45),
+	PORT_DATA_O(46), PORT_DATA_O(47),
+	PORT_DATA_I_PU_PD(48), PORT_DATA_I_PU_PD(49), PORT_DATA_I_PU_PD(50),
+	PORT_DATA_IO_PD(51), PORT_DATA_IO_PD(52),
+	PORT_DATA_O(53),
+	PORT_DATA_IO_PD(54),
+	PORT_DATA_I_PU_PD(55),
+	PORT_DATA_IO_PU_PD(56),
+	PORT_DATA_I_PU_PD(57),
+	PORT_DATA_IO_PU_PD(58),
+	PORT_DATA_O(59), PORT_DATA_O(60), PORT_DATA_O(61), PORT_DATA_O(62),
+	PORT_DATA_O(63),
+	PORT_DATA_I_PU(64),
+	PORT_DATA_O(65), PORT_DATA_O(66), PORT_DATA_O(67), PORT_DATA_O(68),
+	PORT_DATA_IO_PD(69), PORT_DATA_IO_PD(70),
+	PORT_DATA_I_PD(71), PORT_DATA_I_PD(72), PORT_DATA_I_PD(73),
+	PORT_DATA_I_PD(74),
+	PORT_DATA_IO_PU_PD(75), PORT_DATA_IO_PU_PD(76),
+	PORT_DATA_IO_PD(77), PORT_DATA_IO_PD(78),
+	PORT_DATA_O(79),
+	PORT_DATA_IO_PD(80), PORT_DATA_IO_PD(81), PORT_DATA_IO_PD(82),
+	PORT_DATA_IO_PU_PD(83), PORT_DATA_IO_PU_PD(84),
+	PORT_DATA_IO_PU_PD(85), PORT_DATA_IO_PU_PD(86),
+	PORT_DATA_I_PD(87),
+	PORT_DATA_IO_PU_PD(88),
+	PORT_DATA_I_PU_PD(89), PORT_DATA_I_PU_PD(90),
+
+	/* 49-3 (GPIO) */
+	PORT_DATA_O(91), PORT_DATA_O(92), PORT_DATA_O(93), PORT_DATA_O(94),
+	PORT_DATA_I_PU_PD(95),
+	PORT_DATA_IO_PU_PD(96), PORT_DATA_IO_PU_PD(97), PORT_DATA_IO_PU_PD(98),
+	PORT_DATA_IO_PU_PD(99),	PORT_DATA_IO_PU_PD(100),
+	PORT_DATA_IO(101), PORT_DATA_IO(102), PORT_DATA_IO(103),
+	PORT_DATA_IO_PD(104), PORT_DATA_IO_PD(105), PORT_DATA_IO_PD(106),
+	PORT_DATA_IO_PD(107),
+	PORT_DATA_IO_PU_PD(108), PORT_DATA_IO_PU_PD(109),
+	PORT_DATA_IO_PU_PD(110), PORT_DATA_IO_PU_PD(111),
+	PORT_DATA_IO_PU_PD(112), PORT_DATA_IO_PU_PD(113),
+	PORT_DATA_IO_PU_PD(114),
+	PORT_DATA_IO_PU(115), PORT_DATA_IO_PU(116), PORT_DATA_IO_PU(117),
+	PORT_DATA_IO_PU(118), PORT_DATA_IO_PU(119), PORT_DATA_IO_PU(120),
+	PORT_DATA_IO_PU(121), PORT_DATA_IO_PU(122), PORT_DATA_IO_PU(123),
+	PORT_DATA_IO_PU(124), PORT_DATA_IO_PU(125), PORT_DATA_IO_PU(126),
+	PORT_DATA_IO_PU(127), PORT_DATA_IO_PU(128), PORT_DATA_IO_PU(129),
+	PORT_DATA_IO_PU(130),
+	PORT_DATA_O(131), PORT_DATA_O(132), PORT_DATA_O(133),
+	PORT_DATA_IO_PU(134),
+	PORT_DATA_O(135), PORT_DATA_O(136),
+	PORT_DATA_I_PU_PD(137),
+	PORT_DATA_IO(138),
+	PORT_DATA_IO_PU_PD(139),
+	PORT_DATA_IO(140), PORT_DATA_IO(141),
+	PORT_DATA_I_PU(142),
+	PORT_DATA_O(143), PORT_DATA_O(144),
+	PORT_DATA_I_PU(145),
+
+	/* 49-4 (GPIO) */
+	PORT_DATA_O(146),
+	PORT_DATA_I_PU_PD(147),
+	PORT_DATA_I_PD(148), PORT_DATA_I_PD(149),
+	PORT_DATA_IO_PD(150), PORT_DATA_IO_PD(151), PORT_DATA_IO_PD(152),
+	PORT_DATA_IO_PD(153), PORT_DATA_IO_PD(154), PORT_DATA_IO_PD(155),
+	PORT_DATA_IO_PD(156), PORT_DATA_IO_PD(157), PORT_DATA_IO_PD(158),
+	PORT_DATA_IO_PD(159), PORT_DATA_IO_PD(160), PORT_DATA_IO_PD(161),
+	PORT_DATA_IO_PD(162), PORT_DATA_IO_PD(163), PORT_DATA_IO_PD(164),
+	PORT_DATA_IO_PD(165), PORT_DATA_IO_PD(166),
+	PORT_DATA_IO_PU_PD(167),
+	PORT_DATA_O(168),
+	PORT_DATA_I_PD(169), PORT_DATA_I_PD(170),
+	PORT_DATA_O(171),
+	PORT_DATA_IO_PD(172), PORT_DATA_IO_PD(173),
+	PORT_DATA_O(174),
+	PORT_DATA_IO_PD(175), PORT_DATA_IO_PD(176), PORT_DATA_IO_PD(177),
+	PORT_DATA_IO_PD(178), PORT_DATA_IO_PD(179), PORT_DATA_IO_PD(180),
+	PORT_DATA_IO_PD(181), PORT_DATA_IO_PD(182), PORT_DATA_IO_PD(183),
+	PORT_DATA_IO_PD(184), PORT_DATA_IO_PD(185), PORT_DATA_IO_PD(186),
+	PORT_DATA_IO_PD(187), PORT_DATA_IO_PD(188), PORT_DATA_IO_PD(189),
+	PORT_DATA_IO_PD(190), PORT_DATA_IO_PD(191), PORT_DATA_IO_PD(192),
+	PORT_DATA_IO_PD(193), PORT_DATA_IO_PD(194), PORT_DATA_IO_PD(195),
+	PORT_DATA_IO_PD(196), PORT_DATA_IO_PD(197), PORT_DATA_IO_PD(198),
+	PORT_DATA_O(199),
+	PORT_DATA_IO_PD(200),
+
+	/* 49-5 (GPIO) */
+	PORT_DATA_O(201),
+	PORT_DATA_IO_PD(202), PORT_DATA_IO_PD(203),
+	PORT_DATA_I(204),
+	PORT_DATA_O(205),
+	PORT_DATA_IO_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_PD(214),
+	PORT_DATA_IO_PD(215), PORT_DATA_IO_PD(216),
+	PORT_DATA_O(217),
+	PORT_DATA_I_PU_PD(218), PORT_DATA_I_PU_PD(219),
+	PORT_DATA_O(220), PORT_DATA_O(221), PORT_DATA_O(222),
+	PORT_DATA_I_PD(223),
+	PORT_DATA_I_PU_PD(224),
+	PORT_DATA_O(225),
+	PORT_DATA_IO_PD(226),
+	PORT_DATA_IO_PU_PD(227),
+	PORT_DATA_I_PD(228),
+	PORT_DATA_IO_PD(229), PORT_DATA_IO_PD(230),
+	PORT_DATA_I_PU_PD(231), PORT_DATA_I_PU_PD(232),
+	PORT_DATA_IO_PU_PD(233), PORT_DATA_IO_PU_PD(234),
+	PORT_DATA_I_PU_PD(235),
+	PORT_DATA_O(236),
+	PORT_DATA_I_PD(237),
+	PORT_DATA_IO_PU_PD(238), PORT_DATA_IO_PU_PD(239),
+	PORT_DATA_IO_PD(240), PORT_DATA_IO_PD(241),
+	PORT_DATA_IO_PD(242), PORT_DATA_IO_PD(243),
+	PORT_DATA_O(244),
+	PORT_DATA_IO_PU_PD(245),
+	PORT_DATA_O(246),
+	PORT_DATA_I_PD(247),
+	PORT_DATA_IO_PU_PD(248),
+	PORT_DATA_I_PU_PD(249),
+	PORT_DATA_IO_PD(250), PORT_DATA_IO_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),
+
+	/* 49-6 (GPIO) */
+	PORT_DATA_IO_PU_PD(257), PORT_DATA_IO_PU_PD(258),
+	PORT_DATA_IO_PD(259),
+	PORT_DATA_IO_PU(260), PORT_DATA_IO_PU(261), PORT_DATA_IO_PU(262),
+	PORT_DATA_IO_PU(263), PORT_DATA_IO_PU(264),
+	PORT_DATA_O(265),
+	PORT_DATA_IO_PU(266), PORT_DATA_IO_PU(267), PORT_DATA_IO_PU(268),
+	PORT_DATA_IO_PU(269), PORT_DATA_IO_PU(270),
+	PORT_DATA_O(271),
+	PORT_DATA_I_PD(272),
+
+	/* Special Pull-up / Pull-down Functions */
+	PINMUX_DATA(PORT48_KEYIN0_PU_MARK, MSELBCR_MSEL2_1,
+		    PORT48_FN2, PORT48_IN_PU),
+	PINMUX_DATA(PORT49_KEYIN1_PU_MARK, MSELBCR_MSEL2_1,
+		    PORT49_FN2, PORT49_IN_PU),
+	PINMUX_DATA(PORT50_KEYIN2_PU_MARK, MSELBCR_MSEL2_1,
+		    PORT50_FN2, PORT50_IN_PU),
+	PINMUX_DATA(PORT55_KEYIN3_PU_MARK, MSELBCR_MSEL2_1,
+		    PORT55_FN2, PORT55_IN_PU),
+	PINMUX_DATA(PORT56_KEYIN4_PU_MARK, MSELBCR_MSEL2_1,
+		    PORT56_FN2, PORT56_IN_PU),
+	PINMUX_DATA(PORT57_KEYIN5_PU_MARK, MSELBCR_MSEL2_1,
+		    PORT57_FN2, PORT57_IN_PU),
+	PINMUX_DATA(PORT58_KEYIN6_PU_MARK, MSELBCR_MSEL2_1,
+		    PORT58_FN2, PORT58_IN_PU),
+
+	/* 49-1 (FN) */
+	PINMUX_DATA(VBUS0_MARK, PORT0_FN1),
+	PINMUX_DATA(CPORT0_MARK, PORT1_FN1),
+	PINMUX_DATA(CPORT1_MARK, PORT2_FN1),
+	PINMUX_DATA(CPORT2_MARK, PORT3_FN1),
+	PINMUX_DATA(CPORT3_MARK, PORT4_FN1),
+	PINMUX_DATA(CPORT4_MARK, PORT5_FN1),
+	PINMUX_DATA(CPORT5_MARK, PORT6_FN1),
+	PINMUX_DATA(CPORT6_MARK, PORT7_FN1),
+	PINMUX_DATA(CPORT7_MARK, PORT8_FN1),
+	PINMUX_DATA(CPORT8_MARK, PORT9_FN1),
+	PINMUX_DATA(CPORT9_MARK, PORT10_FN1),
+	PINMUX_DATA(CPORT10_MARK, PORT11_FN1),
+	PINMUX_DATA(CPORT11_MARK, PORT12_FN1),
+	PINMUX_DATA(SIN2_MARK, PORT12_FN2),
+	PINMUX_DATA(CPORT12_MARK, PORT13_FN1),
+	PINMUX_DATA(XCTS2_MARK, PORT13_FN2),
+	PINMUX_DATA(CPORT13_MARK, PORT14_FN1),
+	PINMUX_DATA(RFSPO4_MARK, PORT14_FN2),
+	PINMUX_DATA(CPORT14_MARK, PORT15_FN1),
+	PINMUX_DATA(RFSPO5_MARK, PORT15_FN2),
+	PINMUX_DATA(CPORT15_MARK, PORT16_FN1),
+	PINMUX_DATA(CPORT16_MARK, PORT17_FN1),
+	PINMUX_DATA(CPORT17_MARK, PORT18_FN1),
+	PINMUX_DATA(SOUT2_MARK, PORT18_FN2),
+	PINMUX_DATA(CPORT18_MARK, PORT19_FN1),
+	PINMUX_DATA(XRTS2_MARK, PORT19_FN1),
+	PINMUX_DATA(CPORT19_MARK, PORT20_FN1),
+	PINMUX_DATA(CPORT20_MARK, PORT21_FN1),
+	PINMUX_DATA(RFSPO6_MARK, PORT21_FN2),
+	PINMUX_DATA(CPORT21_MARK, PORT22_FN1),
+	PINMUX_DATA(STATUS0_MARK, PORT22_FN2),
+	PINMUX_DATA(CPORT22_MARK, PORT23_FN1),
+	PINMUX_DATA(STATUS1_MARK, PORT23_FN2),
+	PINMUX_DATA(CPORT23_MARK, PORT24_FN1),
+	PINMUX_DATA(STATUS2_MARK, PORT24_FN2),
+	PINMUX_DATA(RFSPO7_MARK, PORT24_FN3),
+	PINMUX_DATA(MPORT0_MARK, PORT25_FN1),
+	PINMUX_DATA(MPORT1_MARK, PORT26_FN1),
+	PINMUX_DATA(B_SYNLD1_MARK, PORT27_FN1),
+	PINMUX_DATA(B_SYNLD2_MARK, PORT28_FN1),
+	PINMUX_DATA(XMAINPS_MARK, PORT29_FN1),
+	PINMUX_DATA(XDIVPS_MARK, PORT30_FN1),
+	PINMUX_DATA(XIDRST_MARK, PORT31_FN1),
+	PINMUX_DATA(IDCLK_MARK, PORT32_FN1),
+	PINMUX_DATA(IDIO_MARK, PORT33_FN1),
+	PINMUX_DATA(SOUT1_MARK, PORT34_FN1),
+	PINMUX_DATA(SCIFA4_TXD_MARK, PORT34_FN2),
+	PINMUX_DATA(M02_BERDAT_MARK, PORT34_FN3),
+	PINMUX_DATA(SIN1_MARK, PORT35_FN1),
+	PINMUX_DATA(SCIFA4_RXD_MARK, PORT35_FN2),
+	PINMUX_DATA(XWUP_MARK, PORT35_FN3),
+	PINMUX_DATA(XRTS1_MARK, PORT36_FN1),
+	PINMUX_DATA(SCIFA4_RTS_MARK, PORT36_FN2),
+	PINMUX_DATA(M03_BERCLK_MARK, PORT36_FN3),
+	PINMUX_DATA(XCTS1_MARK, PORT37_FN1),
+	PINMUX_DATA(SCIFA4_CTS_MARK, PORT37_FN2),
+
+	/* 49-2 (FN) */
+	PINMUX_DATA(HSU_IQ_AGC6_MARK, PORT38_FN1),
+	PINMUX_DATA(MFG2_IN2_MARK, PORT38_FN2),
+	PINMUX_DATA(MSIOF2_MCK0_MARK, PORT38_FN3),
+	PINMUX_DATA(HSU_IQ_AGC5_MARK, PORT39_FN1),
+	PINMUX_DATA(MFG2_IN1_MARK, PORT39_FN2),
+	PINMUX_DATA(MSIOF2_MCK1_MARK, PORT39_FN3),
+	PINMUX_DATA(HSU_IQ_AGC4_MARK, PORT40_FN1),
+	PINMUX_DATA(MSIOF2_RSYNC_MARK, PORT40_FN3),
+	PINMUX_DATA(HSU_IQ_AGC3_MARK, PORT41_FN1),
+	PINMUX_DATA(MFG2_OUT1_MARK, PORT41_FN2),
+	PINMUX_DATA(MSIOF2_RSCK_MARK, PORT41_FN3),
+	PINMUX_DATA(HSU_IQ_AGC2_MARK, PORT42_FN1),
+	PINMUX_DATA(PORT42_KEYOUT0_MARK, MSELBCR_MSEL2_1, PORT42_FN2),
+	PINMUX_DATA(HSU_IQ_AGC1_MARK, PORT43_FN1),
+	PINMUX_DATA(PORT43_KEYOUT1_MARK, MSELBCR_MSEL2_1, PORT43_FN2),
+	PINMUX_DATA(HSU_IQ_AGC0_MARK, PORT44_FN1),
+	PINMUX_DATA(PORT44_KEYOUT2_MARK, MSELBCR_MSEL2_1, PORT44_FN2),
+	PINMUX_DATA(HSU_IQ_AGC_ST_MARK, PORT45_FN1),
+	PINMUX_DATA(PORT45_KEYOUT3_MARK, MSELBCR_MSEL2_1, PORT45_FN2),
+	PINMUX_DATA(HSU_IQ_PDO_MARK, PORT46_FN1),
+	PINMUX_DATA(PORT46_KEYOUT4_MARK, MSELBCR_MSEL2_1, PORT46_FN2),
+	PINMUX_DATA(HSU_IQ_PYO_MARK, PORT47_FN1),
+	PINMUX_DATA(PORT47_KEYOUT5_MARK, MSELBCR_MSEL2_1, PORT47_FN2),
+	PINMUX_DATA(HSU_EN_TXMUX_G3MO_MARK, PORT48_FN1),
+	PINMUX_DATA(PORT48_KEYIN0_MARK, MSELBCR_MSEL2_1, PORT48_FN2),
+	PINMUX_DATA(HSU_I_TXMUX_G3MO_MARK, PORT49_FN1),
+	PINMUX_DATA(PORT49_KEYIN1_MARK, MSELBCR_MSEL2_1, PORT49_FN2),
+	PINMUX_DATA(HSU_Q_TXMUX_G3MO_MARK, PORT50_FN1),
+	PINMUX_DATA(PORT50_KEYIN2_MARK, MSELBCR_MSEL2_1, PORT50_FN2),
+	PINMUX_DATA(HSU_SYO_MARK, PORT51_FN1),
+	PINMUX_DATA(PORT51_MSIOF2_TSYNC_MARK, PORT51_FN2),
+	PINMUX_DATA(HSU_SDO_MARK, PORT52_FN1),
+	PINMUX_DATA(PORT52_MSIOF2_TSCK_MARK, PORT52_FN2),
+	PINMUX_DATA(HSU_TGTTI_G3MO_MARK, PORT53_FN1),
+	PINMUX_DATA(PORT53_MSIOF2_TXD_MARK, PORT53_FN2),
+	PINMUX_DATA(B_TIME_STAMP_MARK, PORT54_FN1),
+	PINMUX_DATA(PORT54_MSIOF2_RXD_MARK, PORT54_FN2),
+	PINMUX_DATA(HSU_SDI_MARK, PORT55_FN1),
+	PINMUX_DATA(PORT55_KEYIN3_MARK, MSELBCR_MSEL2_1, PORT55_FN2),
+	PINMUX_DATA(HSU_SCO_MARK, PORT56_FN1),
+	PINMUX_DATA(PORT56_KEYIN4_MARK, MSELBCR_MSEL2_1, PORT56_FN2),
+	PINMUX_DATA(HSU_DREQ_MARK, PORT57_FN1),
+	PINMUX_DATA(PORT57_KEYIN5_MARK, MSELBCR_MSEL2_1, PORT57_FN2),
+	PINMUX_DATA(HSU_DACK_MARK, PORT58_FN1),
+	PINMUX_DATA(PORT58_KEYIN6_MARK, MSELBCR_MSEL2_1, PORT58_FN2),
+	PINMUX_DATA(HSU_CLK61M_MARK, PORT59_FN1),
+	PINMUX_DATA(PORT59_MSIOF2_SS1_MARK, PORT59_FN2),
+	PINMUX_DATA(HSU_XRST_MARK, PORT60_FN1),
+	PINMUX_DATA(PORT60_MSIOF2_SS2_MARK, PORT60_FN2),
+	PINMUX_DATA(PCMCLKO_MARK, PORT61_FN1),
+	PINMUX_DATA(SYNC8KO_MARK, PORT62_FN1),
+	PINMUX_DATA(DNPCM_A_MARK, PORT63_FN1),
+	PINMUX_DATA(UPPCM_A_MARK, PORT64_FN1),
+	PINMUX_DATA(XTALB1L_MARK, PORT65_FN1),
+	PINMUX_DATA(GPS_AGC1_MARK, PORT66_FN1),
+	PINMUX_DATA(SCIFA0_RTS_MARK, PORT66_FN2),
+	PINMUX_DATA(GPS_AGC2_MARK, PORT67_FN1),
+	PINMUX_DATA(SCIFA0_SCK_MARK, PORT67_FN2),
+	PINMUX_DATA(GPS_AGC3_MARK, PORT68_FN1),
+	PINMUX_DATA(SCIFA0_TXD_MARK, PORT68_FN2),
+	PINMUX_DATA(GPS_AGC4_MARK, PORT69_FN1),
+	PINMUX_DATA(SCIFA0_RXD_MARK, PORT69_FN2),
+	PINMUX_DATA(GPS_PWRD_MARK, PORT70_FN1),
+	PINMUX_DATA(SCIFA0_CTS_MARK, PORT70_FN2),
+	PINMUX_DATA(GPS_IM_MARK, PORT71_FN1),
+	PINMUX_DATA(GPS_IS_MARK, PORT72_FN1),
+	PINMUX_DATA(GPS_QM_MARK, PORT73_FN1),
+	PINMUX_DATA(GPS_QS_MARK, PORT74_FN1),
+	PINMUX_DATA(SIUBOMC_MARK, PORT75_FN1),
+	PINMUX_DATA(TPU2TO0_MARK, PORT75_FN3),
+	PINMUX_DATA(SIUCKB_MARK, PORT76_FN1),
+	PINMUX_DATA(TPU2TO1_MARK, PORT76_FN3),
+	PINMUX_DATA(SIUBOLR_MARK, PORT77_FN1),
+	PINMUX_DATA(BBIF2_TSYNC_MARK, PORT77_FN2),
+	PINMUX_DATA(TPU2TO2_MARK, PORT77_FN3),
+	PINMUX_DATA(SIUBOBT_MARK, PORT78_FN1),
+	PINMUX_DATA(BBIF2_TSCK_MARK, PORT78_FN2),
+	PINMUX_DATA(TPU2TO3_MARK, PORT78_FN3),
+	PINMUX_DATA(SIUBOSLD_MARK, PORT79_FN1),
+	PINMUX_DATA(BBIF2_TXD_MARK, PORT79_FN2),
+	PINMUX_DATA(TPU3TO0_MARK, PORT79_FN3),
+	PINMUX_DATA(SIUBILR_MARK, PORT80_FN1),
+	PINMUX_DATA(TPU3TO1_MARK, PORT80_FN3),
+	PINMUX_DATA(SIUBIBT_MARK, PORT81_FN1),
+	PINMUX_DATA(TPU3TO2_MARK, PORT81_FN3),
+	PINMUX_DATA(SIUBISLD_MARK, PORT82_FN1),
+	PINMUX_DATA(TPU3TO3_MARK, PORT82_FN3),
+	PINMUX_DATA(NMI_MARK, PORT83_FN1),
+	PINMUX_DATA(TPU4TO0_MARK, PORT83_FN3),
+	PINMUX_DATA(DNPCM_M_MARK, PORT84_FN1),
+	PINMUX_DATA(TPU4TO1_MARK, PORT84_FN3),
+	PINMUX_DATA(TPU4TO2_MARK, PORT85_FN3),
+	PINMUX_DATA(TPU4TO3_MARK, PORT86_FN3),
+	PINMUX_DATA(IRQ_TMPB_MARK, PORT87_FN1),
+	PINMUX_DATA(PWEN_MARK, PORT88_FN1),
+	PINMUX_DATA(MFG1_OUT1_MARK, PORT88_FN2),
+	PINMUX_DATA(OVCN_MARK, PORT89_FN1),
+	PINMUX_DATA(MFG1_IN1_MARK, PORT89_FN2),
+	PINMUX_DATA(OVCN2_MARK, PORT90_FN1),
+	PINMUX_DATA(MFG1_IN2_MARK, PORT90_FN2),
+
+	/* 49-3 (FN) */
+	PINMUX_DATA(RFSPO1_MARK, PORT91_FN1),
+	PINMUX_DATA(RFSPO2_MARK, PORT92_FN1),
+	PINMUX_DATA(RFSPO3_MARK, PORT93_FN1),
+	PINMUX_DATA(PORT93_VIO_CKO2_MARK, PORT93_FN2),
+	PINMUX_DATA(USBTERM_MARK, PORT94_FN1),
+	PINMUX_DATA(EXTLP_MARK, PORT94_FN2),
+	PINMUX_DATA(IDIN_MARK, PORT95_FN1),
+	PINMUX_DATA(SCIFA5_CTS_MARK, PORT96_FN1),
+	PINMUX_DATA(MFG0_IN1_MARK, PORT96_FN2),
+	PINMUX_DATA(SCIFA5_RTS_MARK, PORT97_FN1),
+	PINMUX_DATA(MFG0_IN2_MARK, PORT97_FN2),
+	PINMUX_DATA(SCIFA5_RXD_MARK, PORT98_FN1),
+	PINMUX_DATA(SCIFA5_TXD_MARK, PORT99_FN1),
+	PINMUX_DATA(SCIFA5_SCK_MARK, PORT100_FN1),
+	PINMUX_DATA(MFG0_OUT1_MARK, PORT100_FN2),
+	PINMUX_DATA(A0_EA0_MARK, PORT101_FN1),
+	PINMUX_DATA(BS_MARK, PORT101_FN2),
+	PINMUX_DATA(A14_EA14_MARK, PORT102_FN1),
+	PINMUX_DATA(PORT102_KEYOUT0_MARK, MSELBCR_MSEL2_0, PORT102_FN2),
+	PINMUX_DATA(A15_EA15_MARK, PORT103_FN1),
+	PINMUX_DATA(PORT103_KEYOUT1_MARK, MSELBCR_MSEL2_0, PORT103_FN2),
+	PINMUX_DATA(DV_CLKOL_MARK, PORT103_FN3),
+	PINMUX_DATA(A16_EA16_MARK, PORT104_FN1),
+	PINMUX_DATA(PORT104_KEYOUT2_MARK, MSELBCR_MSEL2_0, PORT104_FN2),
+	PINMUX_DATA(DV_VSYNCL_MARK, PORT104_FN3),
+	PINMUX_DATA(MSIOF0_SS1_MARK, PORT104_FN4),
+	PINMUX_DATA(A17_EA17_MARK, PORT105_FN1),
+	PINMUX_DATA(PORT105_KEYOUT3_MARK, MSELBCR_MSEL2_0, PORT105_FN2),
+	PINMUX_DATA(DV_HSYNCL_MARK, PORT105_FN3),
+	PINMUX_DATA(MSIOF0_TSYNC_MARK, PORT105_FN4),
+	PINMUX_DATA(A18_EA18_MARK, PORT106_FN1),
+	PINMUX_DATA(PORT106_KEYOUT4_MARK, MSELBCR_MSEL2_0, PORT106_FN2),
+	PINMUX_DATA(DV_DL0_MARK, PORT106_FN3),
+	PINMUX_DATA(MSIOF0_TSCK_MARK, PORT106_FN4),
+	PINMUX_DATA(A19_EA19_MARK, PORT107_FN1),
+	PINMUX_DATA(PORT107_KEYOUT5_MARK, MSELBCR_MSEL2_0, PORT107_FN2),
+	PINMUX_DATA(DV_DL1_MARK, PORT107_FN3),
+	PINMUX_DATA(MSIOF0_TXD_MARK, PORT107_FN4),
+	PINMUX_DATA(A20_EA20_MARK, PORT108_FN1),
+	PINMUX_DATA(PORT108_KEYIN0_MARK, MSELBCR_MSEL2_0, PORT108_FN2),
+	PINMUX_DATA(DV_DL2_MARK, PORT108_FN3),
+	PINMUX_DATA(MSIOF0_RSCK_MARK, PORT108_FN4),
+	PINMUX_DATA(A21_EA21_MARK, PORT109_FN1),
+	PINMUX_DATA(PORT109_KEYIN1_MARK, MSELBCR_MSEL2_0, PORT109_FN2),
+	PINMUX_DATA(DV_DL3_MARK, PORT109_FN3),
+	PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT109_FN4),
+	PINMUX_DATA(A22_EA22_MARK, PORT110_FN1),
+	PINMUX_DATA(PORT110_KEYIN2_MARK, MSELBCR_MSEL2_0, PORT110_FN2),
+	PINMUX_DATA(DV_DL4_MARK, PORT110_FN3),
+	PINMUX_DATA(MSIOF0_MCK0_MARK, PORT110_FN4),
+	PINMUX_DATA(A23_EA23_MARK, PORT111_FN1),
+	PINMUX_DATA(PORT111_KEYIN3_MARK, MSELBCR_MSEL2_0, PORT111_FN2),
+	PINMUX_DATA(DV_DL5_MARK, PORT111_FN3),
+	PINMUX_DATA(MSIOF0_MCK1_MARK, PORT111_FN4),
+	PINMUX_DATA(A24_EA24_MARK, PORT112_FN1),
+	PINMUX_DATA(PORT112_KEYIN4_MARK, MSELBCR_MSEL2_0, PORT112_FN2),
+	PINMUX_DATA(DV_DL6_MARK, PORT112_FN3),
+	PINMUX_DATA(MSIOF0_RXD_MARK, PORT112_FN4),
+	PINMUX_DATA(A25_EA25_MARK, PORT113_FN1),
+	PINMUX_DATA(PORT113_KEYIN5_MARK, MSELBCR_MSEL2_0, PORT113_FN2),
+	PINMUX_DATA(DV_DL7_MARK, PORT113_FN3),
+	PINMUX_DATA(MSIOF0_SS2_MARK, PORT113_FN4),
+	PINMUX_DATA(A26_MARK, PORT114_FN1),
+	PINMUX_DATA(PORT113_KEYIN6_MARK, MSELBCR_MSEL2_0, PORT114_FN2),
+	PINMUX_DATA(DV_CLKIL_MARK, PORT114_FN3),
+	PINMUX_DATA(D0_ED0_NAF0_MARK, PORT115_FN1),
+	PINMUX_DATA(D1_ED1_NAF1_MARK, PORT116_FN1),
+	PINMUX_DATA(D2_ED2_NAF2_MARK, PORT117_FN1),
+	PINMUX_DATA(D3_ED3_NAF3_MARK, PORT118_FN1),
+	PINMUX_DATA(D4_ED4_NAF4_MARK, PORT119_FN1),
+	PINMUX_DATA(D5_ED5_NAF5_MARK, PORT120_FN1),
+	PINMUX_DATA(D6_ED6_NAF6_MARK, PORT121_FN1),
+	PINMUX_DATA(D7_ED7_NAF7_MARK, PORT122_FN1),
+	PINMUX_DATA(D8_ED8_NAF8_MARK, PORT123_FN1),
+	PINMUX_DATA(D9_ED9_NAF9_MARK, PORT124_FN1),
+	PINMUX_DATA(D10_ED10_NAF10_MARK, PORT125_FN1),
+	PINMUX_DATA(D11_ED11_NAF11_MARK, PORT126_FN1),
+	PINMUX_DATA(D12_ED12_NAF12_MARK, PORT127_FN1),
+	PINMUX_DATA(D13_ED13_NAF13_MARK, PORT128_FN1),
+	PINMUX_DATA(D14_ED14_NAF14_MARK, PORT129_FN1),
+	PINMUX_DATA(D15_ED15_NAF15_MARK, PORT130_FN1),
+	PINMUX_DATA(CS4_MARK, PORT131_FN1),
+	PINMUX_DATA(CS5A_MARK, PORT132_FN1),
+	PINMUX_DATA(CS5B_MARK, PORT133_FN1),
+	PINMUX_DATA(FCE1_MARK, PORT133_FN2),
+	PINMUX_DATA(CS6B_MARK, PORT134_FN1),
+	PINMUX_DATA(XCS2_MARK, PORT134_FN2),
+	PINMUX_DATA(FCE0_MARK, PORT135_FN1),
+	PINMUX_DATA(CS6A_MARK, PORT136_FN1),
+	PINMUX_DATA(DACK0_MARK, PORT136_FN2),
+	PINMUX_DATA(WAIT_MARK, PORT137_FN1),
+	PINMUX_DATA(DREQ0_MARK, PORT137_FN2),
+	PINMUX_DATA(RD_XRD_MARK, PORT138_FN1),
+	PINMUX_DATA(A27_MARK, PORT139_FN1),
+	PINMUX_DATA(RDWR_XWE_MARK, PORT139_FN2),
+	PINMUX_DATA(WE0_XWR0_FWE_MARK, PORT140_FN1),
+	PINMUX_DATA(WE1_XWR1_MARK, PORT141_FN1),
+	PINMUX_DATA(FRB_MARK, PORT142_FN1),
+	PINMUX_DATA(CKO_MARK, PORT143_FN1),
+	PINMUX_DATA(NBRSTOUT_MARK, PORT144_FN1),
+	PINMUX_DATA(NBRST_MARK, PORT145_FN1),
+
+	/* 49-4 (FN) */
+	PINMUX_DATA(RFSPO0_MARK, PORT146_FN1),
+	PINMUX_DATA(PORT146_VIO_CKO2_MARK, PORT146_FN2),
+	PINMUX_DATA(TSTMD_MARK, PORT147_FN1),
+	PINMUX_DATA(VIO_VD_MARK, PORT148_FN1),
+	PINMUX_DATA(VIO_HD_MARK, PORT149_FN1),
+	PINMUX_DATA(VIO_D0_MARK, PORT150_FN1),
+	PINMUX_DATA(VIO_D1_MARK, PORT151_FN1),
+	PINMUX_DATA(VIO_D2_MARK, PORT152_FN1),
+	PINMUX_DATA(VIO_D3_MARK, PORT153_FN1),
+	PINMUX_DATA(VIO_D4_MARK, PORT154_FN1),
+	PINMUX_DATA(VIO_D5_MARK, PORT155_FN1),
+	PINMUX_DATA(VIO_D6_MARK, PORT156_FN1),
+	PINMUX_DATA(VIO_D7_MARK, PORT157_FN1),
+	PINMUX_DATA(VIO_D8_MARK, PORT158_FN1),
+	PINMUX_DATA(VIO_D9_MARK, PORT159_FN1),
+	PINMUX_DATA(VIO_D10_MARK, PORT160_FN1),
+	PINMUX_DATA(VIO_D11_MARK, PORT161_FN1),
+	PINMUX_DATA(VIO_D12_MARK, PORT162_FN1),
+	PINMUX_DATA(VIO_D13_MARK, PORT163_FN1),
+	PINMUX_DATA(VIO_D14_MARK, PORT164_FN1),
+	PINMUX_DATA(VIO_D15_MARK, PORT165_FN1),
+	PINMUX_DATA(VIO_CLK_MARK, PORT166_FN1),
+	PINMUX_DATA(VIO_FIELD_MARK, PORT167_FN1),
+	PINMUX_DATA(VIO_CKO_MARK, PORT168_FN1),
+	PINMUX_DATA(MFG3_IN1_MARK, PORT169_FN2),
+	PINMUX_DATA(MFG3_IN2_MARK, PORT170_FN2),
+	PINMUX_DATA(M9_SLCD_A01_MARK, PORT171_FN1),
+	PINMUX_DATA(MFG3_OUT1_MARK, PORT171_FN2),
+	PINMUX_DATA(TPU0TO0_MARK, PORT171_FN3),
+	PINMUX_DATA(M10_SLCD_CK1_MARK, PORT172_FN1),
+	PINMUX_DATA(MFG4_IN1_MARK, PORT172_FN2),
+	PINMUX_DATA(TPU0TO1_MARK, PORT172_FN3),
+	PINMUX_DATA(M11_SLCD_SO1_MARK, PORT173_FN1),
+	PINMUX_DATA(MFG4_IN2_MARK, PORT173_FN2),
+	PINMUX_DATA(TPU0TO2_MARK, PORT173_FN3),
+	PINMUX_DATA(M12_SLCD_CE1_MARK, PORT174_FN1),
+	PINMUX_DATA(MFG4_OUT1_MARK, PORT174_FN2),
+	PINMUX_DATA(TPU0TO3_MARK, PORT174_FN3),
+	PINMUX_DATA(LCDD0_MARK, PORT175_FN1),
+	PINMUX_DATA(PORT175_KEYOUT0_MARK, PORT175_FN2),
+	PINMUX_DATA(DV_D0_MARK, PORT175_FN3),
+	PINMUX_DATA(SIUCKA_MARK, PORT175_FN4),
+	PINMUX_DATA(MFG0_OUT2_MARK, PORT175_FN5),
+	PINMUX_DATA(LCDD1_MARK, PORT176_FN1),
+	PINMUX_DATA(PORT176_KEYOUT1_MARK, PORT176_FN2),
+	PINMUX_DATA(DV_D1_MARK, PORT176_FN3),
+	PINMUX_DATA(SIUAOLR_MARK, PORT176_FN4),
+	PINMUX_DATA(BBIF2_TSYNC1_MARK, PORT176_FN5),
+	PINMUX_DATA(LCDD2_MARK, PORT177_FN1),
+	PINMUX_DATA(PORT177_KEYOUT2_MARK, PORT177_FN2),
+	PINMUX_DATA(DV_D2_MARK, PORT177_FN3),
+	PINMUX_DATA(SIUAOBT_MARK, PORT177_FN4),
+	PINMUX_DATA(BBIF2_TSCK1_MARK, PORT177_FN5),
+	PINMUX_DATA(LCDD3_MARK, PORT178_FN1),
+	PINMUX_DATA(PORT178_KEYOUT3_MARK, PORT178_FN2),
+	PINMUX_DATA(DV_D3_MARK, PORT178_FN3),
+	PINMUX_DATA(SIUAOSLD_MARK, PORT178_FN4),
+	PINMUX_DATA(BBIF2_TXD1_MARK, PORT178_FN5),
+	PINMUX_DATA(LCDD4_MARK, PORT179_FN1),
+	PINMUX_DATA(PORT179_KEYOUT4_MARK, PORT179_FN2),
+	PINMUX_DATA(DV_D4_MARK, PORT179_FN3),
+	PINMUX_DATA(SIUAISPD_MARK, PORT179_FN4),
+	PINMUX_DATA(MFG1_OUT2_MARK, PORT179_FN5),
+	PINMUX_DATA(LCDD5_MARK, PORT180_FN1),
+	PINMUX_DATA(PORT180_KEYOUT5_MARK, PORT180_FN2),
+	PINMUX_DATA(DV_D5_MARK, PORT180_FN3),
+	PINMUX_DATA(SIUAILR_MARK, PORT180_FN4),
+	PINMUX_DATA(MFG2_OUT2_MARK, PORT180_FN5),
+	PINMUX_DATA(LCDD6_MARK, PORT181_FN1),
+	PINMUX_DATA(DV_D6_MARK, PORT181_FN3),
+	PINMUX_DATA(SIUAIBT_MARK, PORT181_FN4),
+	PINMUX_DATA(MFG3_OUT2_MARK, PORT181_FN5),
+	PINMUX_DATA(XWR2_MARK, PORT181_FN7),
+	PINMUX_DATA(LCDD7_MARK, PORT182_FN1),
+	PINMUX_DATA(DV_D7_MARK, PORT182_FN3),
+	PINMUX_DATA(SIUAISLD_MARK, PORT182_FN4),
+	PINMUX_DATA(MFG4_OUT2_MARK, PORT182_FN5),
+	PINMUX_DATA(XWR3_MARK, PORT182_FN7),
+	PINMUX_DATA(LCDD8_MARK, PORT183_FN1),
+	PINMUX_DATA(DV_D8_MARK, PORT183_FN3),
+	PINMUX_DATA(D16_MARK, PORT183_FN6),
+	PINMUX_DATA(ED16_MARK, PORT183_FN7),
+	PINMUX_DATA(LCDD9_MARK, PORT184_FN1),
+	PINMUX_DATA(DV_D9_MARK, PORT184_FN3),
+	PINMUX_DATA(D17_MARK, PORT184_FN6),
+	PINMUX_DATA(ED17_MARK, PORT184_FN7),
+	PINMUX_DATA(LCDD10_MARK, PORT185_FN1),
+	PINMUX_DATA(DV_D10_MARK, PORT185_FN3),
+	PINMUX_DATA(D18_MARK, PORT185_FN6),
+	PINMUX_DATA(ED18_MARK, PORT185_FN7),
+	PINMUX_DATA(LCDD11_MARK, PORT186_FN1),
+	PINMUX_DATA(DV_D11_MARK, PORT186_FN3),
+	PINMUX_DATA(D19_MARK, PORT186_FN6),
+	PINMUX_DATA(ED19_MARK, PORT186_FN7),
+	PINMUX_DATA(LCDD12_MARK, PORT187_FN1),
+	PINMUX_DATA(DV_D12_MARK, PORT187_FN3),
+	PINMUX_DATA(D20_MARK, PORT187_FN6),
+	PINMUX_DATA(ED20_MARK, PORT187_FN7),
+	PINMUX_DATA(LCDD13_MARK, PORT188_FN1),
+	PINMUX_DATA(DV_D13_MARK, PORT188_FN3),
+	PINMUX_DATA(D21_MARK, PORT188_FN6),
+	PINMUX_DATA(ED21_MARK, PORT188_FN7),
+	PINMUX_DATA(LCDD14_MARK, PORT189_FN1),
+	PINMUX_DATA(DV_D14_MARK, PORT189_FN3),
+	PINMUX_DATA(D22_MARK, PORT189_FN6),
+	PINMUX_DATA(ED22_MARK, PORT189_FN7),
+	PINMUX_DATA(LCDD15_MARK, PORT190_FN1),
+	PINMUX_DATA(DV_D15_MARK, PORT190_FN3),
+	PINMUX_DATA(D23_MARK, PORT190_FN6),
+	PINMUX_DATA(ED23_MARK, PORT190_FN7),
+	PINMUX_DATA(LCDD16_MARK, PORT191_FN1),
+	PINMUX_DATA(DV_HSYNC_MARK, PORT191_FN3),
+	PINMUX_DATA(D24_MARK, PORT191_FN6),
+	PINMUX_DATA(ED24_MARK, PORT191_FN7),
+	PINMUX_DATA(LCDD17_MARK, PORT192_FN1),
+	PINMUX_DATA(DV_VSYNC_MARK, PORT192_FN3),
+	PINMUX_DATA(D25_MARK, PORT192_FN6),
+	PINMUX_DATA(ED25_MARK, PORT192_FN7),
+	PINMUX_DATA(LCDD18_MARK, PORT193_FN1),
+	PINMUX_DATA(DREQ2_MARK, PORT193_FN2),
+	PINMUX_DATA(MSIOF0L_TSCK_MARK, PORT193_FN5),
+	PINMUX_DATA(D26_MARK, PORT193_FN6),
+	PINMUX_DATA(ED26_MARK, PORT193_FN7),
+	PINMUX_DATA(LCDD19_MARK, PORT194_FN1),
+	PINMUX_DATA(MSIOF0L_TSYNC_MARK, PORT194_FN5),
+	PINMUX_DATA(D27_MARK, PORT194_FN6),
+	PINMUX_DATA(ED27_MARK, PORT194_FN7),
+	PINMUX_DATA(LCDD20_MARK, PORT195_FN1),
+	PINMUX_DATA(TS_SPSYNC1_MARK, PORT195_FN2),
+	PINMUX_DATA(MSIOF0L_MCK0_MARK, PORT195_FN5),
+	PINMUX_DATA(D28_MARK, PORT195_FN6),
+	PINMUX_DATA(ED28_MARK, PORT195_FN7),
+	PINMUX_DATA(LCDD21_MARK, PORT196_FN1),
+	PINMUX_DATA(TS_SDAT1_MARK, PORT196_FN2),
+	PINMUX_DATA(MSIOF0L_MCK1_MARK, PORT196_FN5),
+	PINMUX_DATA(D29_MARK, PORT196_FN6),
+	PINMUX_DATA(ED29_MARK, PORT196_FN7),
+	PINMUX_DATA(LCDD22_MARK, PORT197_FN1),
+	PINMUX_DATA(TS_SDEN1_MARK, PORT197_FN2),
+	PINMUX_DATA(MSIOF0L_SS1_MARK, PORT197_FN5),
+	PINMUX_DATA(D30_MARK, PORT197_FN6),
+	PINMUX_DATA(ED30_MARK, PORT197_FN7),
+	PINMUX_DATA(LCDD23_MARK, PORT198_FN1),
+	PINMUX_DATA(TS_SCK1_MARK, PORT198_FN2),
+	PINMUX_DATA(MSIOF0L_SS2_MARK, PORT198_FN5),
+	PINMUX_DATA(D31_MARK, PORT198_FN6),
+	PINMUX_DATA(ED31_MARK, PORT198_FN7),
+	PINMUX_DATA(LCDDCK_MARK, PORT199_FN1),
+	PINMUX_DATA(LCDWR_MARK, PORT199_FN2),
+	PINMUX_DATA(DV_CKO_MARK, PORT199_FN3),
+	PINMUX_DATA(SIUAOSPD_MARK, PORT199_FN4),
+	PINMUX_DATA(LCDRD_MARK, PORT200_FN1),
+	PINMUX_DATA(DACK2_MARK, PORT200_FN2),
+	PINMUX_DATA(MSIOF0L_RSYNC_MARK, PORT200_FN5),
+
+	/* 49-5 (FN) */
+	PINMUX_DATA(LCDHSYN_MARK, PORT201_FN1),
+	PINMUX_DATA(LCDCS_MARK, PORT201_FN2),
+	PINMUX_DATA(LCDCS2_MARK, PORT201_FN3),
+	PINMUX_DATA(DACK3_MARK, PORT201_FN4),
+	PINMUX_DATA(LCDDISP_MARK, PORT202_FN1),
+	PINMUX_DATA(LCDRS_MARK, PORT202_FN2),
+	PINMUX_DATA(DREQ3_MARK, PORT202_FN4),
+	PINMUX_DATA(MSIOF0L_RSCK_MARK, PORT202_FN5),
+	PINMUX_DATA(LCDCSYN_MARK, PORT203_FN1),
+	PINMUX_DATA(LCDCSYN2_MARK, PORT203_FN2),
+	PINMUX_DATA(DV_CKI_MARK, PORT203_FN3),
+	PINMUX_DATA(LCDLCLK_MARK, PORT204_FN1),
+	PINMUX_DATA(DREQ1_MARK, PORT204_FN3),
+	PINMUX_DATA(MSIOF0L_RXD_MARK, PORT204_FN5),
+	PINMUX_DATA(LCDDON_MARK, PORT205_FN1),
+	PINMUX_DATA(LCDDON2_MARK, PORT205_FN2),
+	PINMUX_DATA(DACK1_MARK, PORT205_FN3),
+	PINMUX_DATA(MSIOF0L_TXD_MARK, PORT205_FN5),
+	PINMUX_DATA(VIO_DR0_MARK, PORT206_FN1),
+	PINMUX_DATA(VIO_DR1_MARK, PORT207_FN1),
+	PINMUX_DATA(VIO_DR2_MARK, PORT208_FN1),
+	PINMUX_DATA(VIO_DR3_MARK, PORT209_FN1),
+	PINMUX_DATA(VIO_DR4_MARK, PORT210_FN1),
+	PINMUX_DATA(VIO_DR5_MARK, PORT211_FN1),
+	PINMUX_DATA(VIO_DR6_MARK, PORT212_FN1),
+	PINMUX_DATA(VIO_DR7_MARK, PORT213_FN1),
+	PINMUX_DATA(VIO_VDR_MARK, PORT214_FN1),
+	PINMUX_DATA(VIO_HDR_MARK, PORT215_FN1),
+	PINMUX_DATA(VIO_CLKR_MARK, PORT216_FN1),
+	PINMUX_DATA(VIO_CKOR_MARK, PORT217_FN1),
+	PINMUX_DATA(SCIFA1_TXD_MARK, PORT220_FN2),
+	PINMUX_DATA(GPS_PGFA0_MARK, PORT220_FN3),
+	PINMUX_DATA(SCIFA1_SCK_MARK, PORT221_FN2),
+	PINMUX_DATA(GPS_PGFA1_MARK, PORT221_FN3),
+	PINMUX_DATA(SCIFA1_RTS_MARK, PORT222_FN2),
+	PINMUX_DATA(GPS_EPPSINMON_MARK, PORT222_FN3),
+	PINMUX_DATA(SCIFA1_RXD_MARK, PORT223_FN2),
+	PINMUX_DATA(SCIFA1_CTS_MARK, PORT224_FN2),
+	PINMUX_DATA(MSIOF1_TXD_MARK, PORT225_FN1),
+	PINMUX_DATA(SCIFA1_TXD2_MARK, PORT225_FN2),
+	PINMUX_DATA(GPS_TXD_MARK, PORT225_FN3),
+	PINMUX_DATA(MSIOF1_TSYNC_MARK, PORT226_FN1),
+	PINMUX_DATA(SCIFA1_CTS2_MARK, PORT226_FN2),
+	PINMUX_DATA(I2C_SDA2_MARK, PORT226_FN3),
+	PINMUX_DATA(MSIOF1_TSCK_MARK, PORT227_FN1),
+	PINMUX_DATA(SCIFA1_SCK2_MARK, PORT227_FN2),
+	PINMUX_DATA(MSIOF1_RXD_MARK, PORT228_FN1),
+	PINMUX_DATA(SCIFA1_RXD2_MARK, PORT228_FN2),
+	PINMUX_DATA(GPS_RXD_MARK, PORT228_FN3),
+	PINMUX_DATA(MSIOF1_RSCK_MARK, PORT229_FN1),
+	PINMUX_DATA(SCIFA1_RTS2_MARK, PORT229_FN2),
+	PINMUX_DATA(MSIOF1_RSYNC_MARK, PORT230_FN1),
+	PINMUX_DATA(I2C_SCL2_MARK, PORT230_FN3),
+	PINMUX_DATA(MSIOF1_MCK0_MARK, PORT231_FN1),
+	PINMUX_DATA(MSIOF1_MCK1_MARK, PORT232_FN1),
+	PINMUX_DATA(MSIOF1_SS1_MARK, PORT233_FN1),
+	PINMUX_DATA(EDBGREQ3_MARK, PORT233_FN2),
+	PINMUX_DATA(MSIOF1_SS2_MARK, PORT234_FN1),
+	PINMUX_DATA(PORT236_IROUT_MARK, PORT236_FN1),
+	PINMUX_DATA(IRDA_OUT_MARK, PORT236_FN2),
+	PINMUX_DATA(IRDA_IN_MARK, PORT237_FN2),
+	PINMUX_DATA(IRDA_FIRSEL_MARK, PORT238_FN1),
+	PINMUX_DATA(TPU1TO0_MARK, PORT239_FN3),
+	PINMUX_DATA(TS_SPSYNC3_MARK, PORT239_FN4),
+	PINMUX_DATA(TPU1TO1_MARK, PORT240_FN3),
+	PINMUX_DATA(TS_SDAT3_MARK, PORT240_FN4),
+	PINMUX_DATA(TPU1TO2_MARK, PORT241_FN3),
+	PINMUX_DATA(TS_SDEN3_MARK, PORT241_FN4),
+	PINMUX_DATA(PORT241_MSIOF2_SS1_MARK, PORT241_FN5),
+	PINMUX_DATA(TPU1TO3_MARK, PORT242_FN3),
+	PINMUX_DATA(PORT242_MSIOF2_TSCK_MARK, PORT242_FN5),
+	PINMUX_DATA(M13_BSW_MARK, PORT243_FN2),
+	PINMUX_DATA(PORT243_MSIOF2_TSYNC_MARK, PORT243_FN5),
+	PINMUX_DATA(M14_GSW_MARK, PORT244_FN2),
+	PINMUX_DATA(PORT244_MSIOF2_TXD_MARK, PORT244_FN5),
+	PINMUX_DATA(PORT245_IROUT_MARK, PORT245_FN1),
+	PINMUX_DATA(M15_RSW_MARK, PORT245_FN2),
+	PINMUX_DATA(SOUT3_MARK, PORT246_FN1),
+	PINMUX_DATA(SCIFA2_TXD1_MARK, PORT246_FN2),
+	PINMUX_DATA(SIN3_MARK, PORT247_FN1),
+	PINMUX_DATA(SCIFA2_RXD1_MARK, PORT247_FN2),
+	PINMUX_DATA(XRTS3_MARK, PORT248_FN1),
+	PINMUX_DATA(SCIFA2_RTS1_MARK, PORT248_FN2),
+	PINMUX_DATA(PORT248_MSIOF2_SS2_MARK, PORT248_FN5),
+	PINMUX_DATA(XCTS3_MARK, PORT249_FN1),
+	PINMUX_DATA(SCIFA2_CTS1_MARK, PORT249_FN2),
+	PINMUX_DATA(PORT249_MSIOF2_RXD_MARK, PORT249_FN5),
+	PINMUX_DATA(DINT_MARK, PORT250_FN1),
+	PINMUX_DATA(SCIFA2_SCK1_MARK, PORT250_FN2),
+	PINMUX_DATA(TS_SCK3_MARK, PORT250_FN4),
+	PINMUX_DATA(SDHICLK0_MARK, PORT251_FN1),
+	PINMUX_DATA(TCK2_MARK, PORT251_FN2),
+	PINMUX_DATA(SDHICD0_MARK, PORT252_FN1),
+	PINMUX_DATA(SDHID0_0_MARK, PORT253_FN1),
+	PINMUX_DATA(TMS2_MARK, PORT253_FN2),
+	PINMUX_DATA(SDHID0_1_MARK, PORT254_FN1),
+	PINMUX_DATA(TDO2_MARK, PORT254_FN2),
+	PINMUX_DATA(SDHID0_2_MARK, PORT255_FN1),
+	PINMUX_DATA(TDI2_MARK, PORT255_FN2),
+	PINMUX_DATA(SDHID0_3_MARK, PORT256_FN1),
+	PINMUX_DATA(RTCK2_MARK, PORT256_FN2),
+
+	/* 49-6 (FN) */
+	PINMUX_DATA(SDHICMD0_MARK, PORT257_FN1),
+	PINMUX_DATA(TRST2_MARK, PORT257_FN2),
+	PINMUX_DATA(SDHIWP0_MARK, PORT258_FN1),
+	PINMUX_DATA(EDBGREQ2_MARK, PORT258_FN2),
+	PINMUX_DATA(SDHICLK1_MARK, PORT259_FN1),
+	PINMUX_DATA(TCK3_MARK, PORT259_FN4),
+	PINMUX_DATA(SDHID1_0_MARK, PORT260_FN1),
+	PINMUX_DATA(M11_SLCD_SO2_MARK, PORT260_FN2),
+	PINMUX_DATA(TS_SPSYNC2_MARK, PORT260_FN3),
+	PINMUX_DATA(TMS3_MARK, PORT260_FN4),
+	PINMUX_DATA(SDHID1_1_MARK, PORT261_FN1),
+	PINMUX_DATA(M9_SLCD_AO2_MARK, PORT261_FN2),
+	PINMUX_DATA(TS_SDAT2_MARK, PORT261_FN3),
+	PINMUX_DATA(TDO3_MARK, PORT261_FN4),
+	PINMUX_DATA(SDHID1_2_MARK, PORT262_FN1),
+	PINMUX_DATA(M10_SLCD_CK2_MARK, PORT262_FN2),
+	PINMUX_DATA(TS_SDEN2_MARK, PORT262_FN3),
+	PINMUX_DATA(TDI3_MARK, PORT262_FN4),
+	PINMUX_DATA(SDHID1_3_MARK, PORT263_FN1),
+	PINMUX_DATA(M12_SLCD_CE2_MARK, PORT263_FN2),
+	PINMUX_DATA(TS_SCK2_MARK, PORT263_FN3),
+	PINMUX_DATA(RTCK3_MARK, PORT263_FN4),
+	PINMUX_DATA(SDHICMD1_MARK, PORT264_FN1),
+	PINMUX_DATA(TRST3_MARK, PORT264_FN4),
+	PINMUX_DATA(SDHICLK2_MARK, PORT265_FN1),
+	PINMUX_DATA(SCIFB_SCK_MARK, PORT265_FN2),
+	PINMUX_DATA(SDHID2_0_MARK, PORT266_FN1),
+	PINMUX_DATA(SCIFB_TXD_MARK, PORT266_FN2),
+	PINMUX_DATA(SDHID2_1_MARK, PORT267_FN1),
+	PINMUX_DATA(SCIFB_CTS_MARK, PORT267_FN2),
+	PINMUX_DATA(SDHID2_2_MARK, PORT268_FN1),
+	PINMUX_DATA(SCIFB_RXD_MARK, PORT268_FN2),
+	PINMUX_DATA(SDHID2_3_MARK, PORT269_FN1),
+	PINMUX_DATA(SCIFB_RTS_MARK, PORT269_FN2),
+	PINMUX_DATA(SDHICMD2_MARK, PORT270_FN1),
+	PINMUX_DATA(RESETOUTS_MARK, PORT271_FN1),
+	PINMUX_DATA(DIVLOCK_MARK, PORT272_FN1),
+};
+
+#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
+#define GPIO_PORT_273() _273(_GPIO_PORT, , unused)
+#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
+
+static struct pinmux_gpio pinmux_gpios[] = {
+	/* 49-1 -> 49-6 (GPIO) */
+	GPIO_PORT_273(),
+
+	/* Special Pull-up / Pull-down Functions */
+	GPIO_FN(PORT48_KEYIN0_PU), GPIO_FN(PORT49_KEYIN1_PU),
+	GPIO_FN(PORT50_KEYIN2_PU), GPIO_FN(PORT55_KEYIN3_PU),
+	GPIO_FN(PORT56_KEYIN4_PU), GPIO_FN(PORT57_KEYIN5_PU),
+	GPIO_FN(PORT58_KEYIN6_PU),
+
+	/* 49-1 (FN) */
+	GPIO_FN(VBUS0), GPIO_FN(CPORT0), GPIO_FN(CPORT1), GPIO_FN(CPORT2),
+	GPIO_FN(CPORT3), GPIO_FN(CPORT4), GPIO_FN(CPORT5), GPIO_FN(CPORT6),
+	GPIO_FN(CPORT7), GPIO_FN(CPORT8), GPIO_FN(CPORT9), GPIO_FN(CPORT10),
+	GPIO_FN(CPORT11), GPIO_FN(SIN2), GPIO_FN(CPORT12), GPIO_FN(XCTS2),
+	GPIO_FN(CPORT13), GPIO_FN(RFSPO4), GPIO_FN(CPORT14), GPIO_FN(RFSPO5),
+	GPIO_FN(CPORT15), GPIO_FN(CPORT16), GPIO_FN(CPORT17), GPIO_FN(SOUT2),
+	GPIO_FN(CPORT18), GPIO_FN(XRTS2), GPIO_FN(CPORT19), GPIO_FN(CPORT20),
+	GPIO_FN(RFSPO6), GPIO_FN(CPORT21), GPIO_FN(STATUS0), GPIO_FN(CPORT22),
+	GPIO_FN(STATUS1), GPIO_FN(CPORT23), GPIO_FN(STATUS2), GPIO_FN(RFSPO7),
+	GPIO_FN(MPORT0), GPIO_FN(MPORT1), GPIO_FN(B_SYNLD1), GPIO_FN(B_SYNLD2),
+	GPIO_FN(XMAINPS), GPIO_FN(XDIVPS), GPIO_FN(XIDRST), GPIO_FN(IDCLK),
+	GPIO_FN(IDIO), GPIO_FN(SOUT1), GPIO_FN(SCIFA4_TXD),
+	GPIO_FN(M02_BERDAT), GPIO_FN(SIN1), GPIO_FN(SCIFA4_RXD), GPIO_FN(XWUP),
+	GPIO_FN(XRTS1), GPIO_FN(SCIFA4_RTS), GPIO_FN(M03_BERCLK),
+	GPIO_FN(XCTS1), GPIO_FN(SCIFA4_CTS),
+
+	/* 49-2 (FN) */
+	GPIO_FN(HSU_IQ_AGC6), GPIO_FN(MFG2_IN2), GPIO_FN(MSIOF2_MCK0),
+	GPIO_FN(HSU_IQ_AGC5), GPIO_FN(MFG2_IN1), GPIO_FN(MSIOF2_MCK1),
+	GPIO_FN(HSU_IQ_AGC4), GPIO_FN(MSIOF2_RSYNC),
+	GPIO_FN(HSU_IQ_AGC3), GPIO_FN(MFG2_OUT1), GPIO_FN(MSIOF2_RSCK),
+	GPIO_FN(HSU_IQ_AGC2), GPIO_FN(PORT42_KEYOUT0),
+	GPIO_FN(HSU_IQ_AGC1), GPIO_FN(PORT43_KEYOUT1),
+	GPIO_FN(HSU_IQ_AGC0), GPIO_FN(PORT44_KEYOUT2),
+	GPIO_FN(HSU_IQ_AGC_ST), GPIO_FN(PORT45_KEYOUT3),
+	GPIO_FN(HSU_IQ_PDO), GPIO_FN(PORT46_KEYOUT4),
+	GPIO_FN(HSU_IQ_PYO), GPIO_FN(PORT47_KEYOUT5),
+	GPIO_FN(HSU_EN_TXMUX_G3MO), GPIO_FN(PORT48_KEYIN0),
+	GPIO_FN(HSU_I_TXMUX_G3MO), GPIO_FN(PORT49_KEYIN1),
+	GPIO_FN(HSU_Q_TXMUX_G3MO), GPIO_FN(PORT50_KEYIN2),
+	GPIO_FN(HSU_SYO), GPIO_FN(PORT51_MSIOF2_TSYNC),
+	GPIO_FN(HSU_SDO), GPIO_FN(PORT52_MSIOF2_TSCK),
+	GPIO_FN(HSU_TGTTI_G3MO), GPIO_FN(PORT53_MSIOF2_TXD),
+	GPIO_FN(B_TIME_STAMP), GPIO_FN(PORT54_MSIOF2_RXD),
+	GPIO_FN(HSU_SDI), GPIO_FN(PORT55_KEYIN3),
+	GPIO_FN(HSU_SCO), GPIO_FN(PORT56_KEYIN4),
+	GPIO_FN(HSU_DREQ), GPIO_FN(PORT57_KEYIN5),
+	GPIO_FN(HSU_DACK), GPIO_FN(PORT58_KEYIN6),
+	GPIO_FN(HSU_CLK61M), GPIO_FN(PORT59_MSIOF2_SS1),
+	GPIO_FN(HSU_XRST), GPIO_FN(PORT60_MSIOF2_SS2),
+	GPIO_FN(PCMCLKO), GPIO_FN(SYNC8KO), GPIO_FN(DNPCM_A), GPIO_FN(UPPCM_A),
+	GPIO_FN(XTALB1L),
+	GPIO_FN(GPS_AGC1), GPIO_FN(SCIFA0_RTS),
+	GPIO_FN(GPS_AGC2), GPIO_FN(SCIFA0_SCK),
+	GPIO_FN(GPS_AGC3), GPIO_FN(SCIFA0_TXD),
+	GPIO_FN(GPS_AGC4), GPIO_FN(SCIFA0_RXD),
+	GPIO_FN(GPS_PWRD), GPIO_FN(SCIFA0_CTS),
+	GPIO_FN(GPS_IM), GPIO_FN(GPS_IS), GPIO_FN(GPS_QM), GPIO_FN(GPS_QS),
+	GPIO_FN(SIUBOMC), GPIO_FN(TPU2TO0),
+	GPIO_FN(SIUCKB), GPIO_FN(TPU2TO1),
+	GPIO_FN(SIUBOLR), GPIO_FN(BBIF2_TSYNC), GPIO_FN(TPU2TO2),
+	GPIO_FN(SIUBOBT), GPIO_FN(BBIF2_TSCK), GPIO_FN(TPU2TO3),
+	GPIO_FN(SIUBOSLD), GPIO_FN(BBIF2_TXD), GPIO_FN(TPU3TO0),
+	GPIO_FN(SIUBILR), GPIO_FN(TPU3TO1),
+	GPIO_FN(SIUBIBT), GPIO_FN(TPU3TO2),
+	GPIO_FN(SIUBISLD), GPIO_FN(TPU3TO3),
+	GPIO_FN(NMI), GPIO_FN(TPU4TO0),
+	GPIO_FN(DNPCM_M), GPIO_FN(TPU4TO1), GPIO_FN(TPU4TO2), GPIO_FN(TPU4TO3),
+	GPIO_FN(IRQ_TMPB),
+	GPIO_FN(PWEN), GPIO_FN(MFG1_OUT1),
+	GPIO_FN(OVCN), GPIO_FN(MFG1_IN1),
+	GPIO_FN(OVCN2), GPIO_FN(MFG1_IN2),
+
+	/* 49-3 (FN) */
+	GPIO_FN(RFSPO1), GPIO_FN(RFSPO2), GPIO_FN(RFSPO3),
+	GPIO_FN(PORT93_VIO_CKO2),
+	GPIO_FN(USBTERM), GPIO_FN(EXTLP), GPIO_FN(IDIN),
+	GPIO_FN(SCIFA5_CTS), GPIO_FN(MFG0_IN1),
+	GPIO_FN(SCIFA5_RTS), GPIO_FN(MFG0_IN2),
+	GPIO_FN(SCIFA5_RXD),
+	GPIO_FN(SCIFA5_TXD),
+	GPIO_FN(SCIFA5_SCK), GPIO_FN(MFG0_OUT1),
+	GPIO_FN(A0_EA0), GPIO_FN(BS),
+	GPIO_FN(A14_EA14), GPIO_FN(PORT102_KEYOUT0),
+	GPIO_FN(A15_EA15), GPIO_FN(PORT103_KEYOUT1), GPIO_FN(DV_CLKOL),
+	GPIO_FN(A16_EA16), GPIO_FN(PORT104_KEYOUT2),
+	GPIO_FN(DV_VSYNCL), GPIO_FN(MSIOF0_SS1),
+	GPIO_FN(A17_EA17), GPIO_FN(PORT105_KEYOUT3),
+	GPIO_FN(DV_HSYNCL), GPIO_FN(MSIOF0_TSYNC),
+	GPIO_FN(A18_EA18), GPIO_FN(PORT106_KEYOUT4),
+	GPIO_FN(DV_DL0), GPIO_FN(MSIOF0_TSCK),
+	GPIO_FN(A19_EA19), GPIO_FN(PORT107_KEYOUT5),
+	GPIO_FN(DV_DL1), GPIO_FN(MSIOF0_TXD),
+	GPIO_FN(A20_EA20), GPIO_FN(PORT108_KEYIN0),
+	GPIO_FN(DV_DL2), GPIO_FN(MSIOF0_RSCK),
+	GPIO_FN(A21_EA21), GPIO_FN(PORT109_KEYIN1),
+	GPIO_FN(DV_DL3), GPIO_FN(MSIOF0_RSYNC),
+	GPIO_FN(A22_EA22), GPIO_FN(PORT110_KEYIN2),
+	GPIO_FN(DV_DL4), GPIO_FN(MSIOF0_MCK0),
+	GPIO_FN(A23_EA23), GPIO_FN(PORT111_KEYIN3),
+	GPIO_FN(DV_DL5), GPIO_FN(MSIOF0_MCK1),
+	GPIO_FN(A24_EA24), GPIO_FN(PORT112_KEYIN4),
+	GPIO_FN(DV_DL6), GPIO_FN(MSIOF0_RXD),
+	GPIO_FN(A25_EA25), GPIO_FN(PORT113_KEYIN5),
+	GPIO_FN(DV_DL7), GPIO_FN(MSIOF0_SS2),
+	GPIO_FN(A26), GPIO_FN(PORT113_KEYIN6), GPIO_FN(DV_CLKIL),
+	GPIO_FN(D0_ED0_NAF0), GPIO_FN(D1_ED1_NAF1), GPIO_FN(D2_ED2_NAF2),
+	GPIO_FN(D3_ED3_NAF3), GPIO_FN(D4_ED4_NAF4), GPIO_FN(D5_ED5_NAF5),
+	GPIO_FN(D6_ED6_NAF6), GPIO_FN(D7_ED7_NAF7), GPIO_FN(D8_ED8_NAF8),
+	GPIO_FN(D9_ED9_NAF9), GPIO_FN(D10_ED10_NAF10), GPIO_FN(D11_ED11_NAF11),
+	GPIO_FN(D12_ED12_NAF12), GPIO_FN(D13_ED13_NAF13),
+	GPIO_FN(D14_ED14_NAF14), GPIO_FN(D15_ED15_NAF15),
+	GPIO_FN(CS4), GPIO_FN(CS5A), GPIO_FN(CS5B), GPIO_FN(FCE1),
+	GPIO_FN(CS6B), GPIO_FN(XCS2), GPIO_FN(FCE0), GPIO_FN(CS6A),
+	GPIO_FN(DACK0), GPIO_FN(WAIT), GPIO_FN(DREQ0), GPIO_FN(RD_XRD),
+	GPIO_FN(A27), GPIO_FN(RDWR_XWE), GPIO_FN(WE0_XWR0_FWE),
+	GPIO_FN(WE1_XWR1), GPIO_FN(FRB), GPIO_FN(CKO),
+	GPIO_FN(NBRSTOUT), GPIO_FN(NBRST),
+
+	/* 49-4 (FN) */
+	GPIO_FN(RFSPO0), GPIO_FN(PORT146_VIO_CKO2), GPIO_FN(TSTMD),
+	GPIO_FN(VIO_VD), GPIO_FN(VIO_HD),
+	GPIO_FN(VIO_D0), GPIO_FN(VIO_D1), GPIO_FN(VIO_D2),
+	GPIO_FN(VIO_D3), GPIO_FN(VIO_D4), GPIO_FN(VIO_D5),
+	GPIO_FN(VIO_D6), GPIO_FN(VIO_D7), GPIO_FN(VIO_D8),
+	GPIO_FN(VIO_D9), GPIO_FN(VIO_D10), GPIO_FN(VIO_D11),
+	GPIO_FN(VIO_D12), GPIO_FN(VIO_D13), GPIO_FN(VIO_D14),
+	GPIO_FN(VIO_D15), GPIO_FN(VIO_CLK), GPIO_FN(VIO_FIELD),
+	GPIO_FN(VIO_CKO),
+	GPIO_FN(MFG3_IN1), GPIO_FN(MFG3_IN2),
+	GPIO_FN(M9_SLCD_A01), GPIO_FN(MFG3_OUT1), GPIO_FN(TPU0TO0),
+	GPIO_FN(M10_SLCD_CK1), GPIO_FN(MFG4_IN1), GPIO_FN(TPU0TO1),
+	GPIO_FN(M11_SLCD_SO1), GPIO_FN(MFG4_IN2), GPIO_FN(TPU0TO2),
+	GPIO_FN(M12_SLCD_CE1), GPIO_FN(MFG4_OUT1), GPIO_FN(TPU0TO3),
+	GPIO_FN(LCDD0), GPIO_FN(PORT175_KEYOUT0), GPIO_FN(DV_D0),
+	GPIO_FN(SIUCKA), GPIO_FN(MFG0_OUT2),
+	GPIO_FN(LCDD1), GPIO_FN(PORT176_KEYOUT1), GPIO_FN(DV_D1),
+	GPIO_FN(SIUAOLR), GPIO_FN(BBIF2_TSYNC1),
+	GPIO_FN(LCDD2), GPIO_FN(PORT177_KEYOUT2), GPIO_FN(DV_D2),
+	GPIO_FN(SIUAOBT), GPIO_FN(BBIF2_TSCK1),
+	GPIO_FN(LCDD3), GPIO_FN(PORT178_KEYOUT3), GPIO_FN(DV_D3),
+	GPIO_FN(SIUAOSLD), GPIO_FN(BBIF2_TXD1),
+	GPIO_FN(LCDD4), GPIO_FN(PORT179_KEYOUT4), GPIO_FN(DV_D4),
+	GPIO_FN(SIUAISPD), GPIO_FN(MFG1_OUT2),
+	GPIO_FN(LCDD5), GPIO_FN(PORT180_KEYOUT5), GPIO_FN(DV_D5),
+	GPIO_FN(SIUAILR), GPIO_FN(MFG2_OUT2),
+	GPIO_FN(LCDD6), GPIO_FN(DV_D6),
+	GPIO_FN(SIUAIBT), GPIO_FN(MFG3_OUT2), GPIO_FN(XWR2),
+	GPIO_FN(LCDD7), GPIO_FN(DV_D7),
+	GPIO_FN(SIUAISLD), GPIO_FN(MFG4_OUT2), GPIO_FN(XWR3),
+	GPIO_FN(LCDD8), GPIO_FN(DV_D8), GPIO_FN(D16), GPIO_FN(ED16),
+	GPIO_FN(LCDD9), GPIO_FN(DV_D9), GPIO_FN(D17), GPIO_FN(ED17),
+	GPIO_FN(LCDD10), GPIO_FN(DV_D10), GPIO_FN(D18), GPIO_FN(ED18),
+	GPIO_FN(LCDD11), GPIO_FN(DV_D11), GPIO_FN(D19), GPIO_FN(ED19),
+	GPIO_FN(LCDD12), GPIO_FN(DV_D12), GPIO_FN(D20), GPIO_FN(ED20),
+	GPIO_FN(LCDD13), GPIO_FN(DV_D13), GPIO_FN(D21), GPIO_FN(ED21),
+	GPIO_FN(LCDD14), GPIO_FN(DV_D14), GPIO_FN(D22), GPIO_FN(ED22),
+	GPIO_FN(LCDD15), GPIO_FN(DV_D15), GPIO_FN(D23), GPIO_FN(ED23),
+	GPIO_FN(LCDD16), GPIO_FN(DV_HSYNC), GPIO_FN(D24), GPIO_FN(ED24),
+	GPIO_FN(LCDD17), GPIO_FN(DV_VSYNC), GPIO_FN(D25), GPIO_FN(ED25),
+	GPIO_FN(LCDD18), GPIO_FN(DREQ2), GPIO_FN(MSIOF0L_TSCK),
+	GPIO_FN(D26), GPIO_FN(ED26),
+	GPIO_FN(LCDD19), GPIO_FN(MSIOF0L_TSYNC),
+	GPIO_FN(D27), GPIO_FN(ED27),
+	GPIO_FN(LCDD20), GPIO_FN(TS_SPSYNC1), GPIO_FN(MSIOF0L_MCK0),
+	GPIO_FN(D28), GPIO_FN(ED28),
+	GPIO_FN(LCDD21), GPIO_FN(TS_SDAT1), GPIO_FN(MSIOF0L_MCK1),
+	GPIO_FN(D29), GPIO_FN(ED29),
+	GPIO_FN(LCDD22), GPIO_FN(TS_SDEN1), GPIO_FN(MSIOF0L_SS1),
+	GPIO_FN(D30), GPIO_FN(ED30),
+	GPIO_FN(LCDD23), GPIO_FN(TS_SCK1), GPIO_FN(MSIOF0L_SS2),
+	GPIO_FN(D31), GPIO_FN(ED31),
+	GPIO_FN(LCDDCK), GPIO_FN(LCDWR), GPIO_FN(DV_CKO), GPIO_FN(SIUAOSPD),
+	GPIO_FN(LCDRD), GPIO_FN(DACK2), GPIO_FN(MSIOF0L_RSYNC),
+
+	/* 49-5 (FN) */
+	GPIO_FN(LCDHSYN), GPIO_FN(LCDCS), GPIO_FN(LCDCS2), GPIO_FN(DACK3),
+	GPIO_FN(LCDDISP), GPIO_FN(LCDRS), GPIO_FN(DREQ3), GPIO_FN(MSIOF0L_RSCK),
+	GPIO_FN(LCDCSYN), GPIO_FN(LCDCSYN2), GPIO_FN(DV_CKI),
+	GPIO_FN(LCDLCLK), GPIO_FN(DREQ1), GPIO_FN(MSIOF0L_RXD),
+	GPIO_FN(LCDDON), GPIO_FN(LCDDON2), GPIO_FN(DACK1), GPIO_FN(MSIOF0L_TXD),
+	GPIO_FN(VIO_DR0), GPIO_FN(VIO_DR1), GPIO_FN(VIO_DR2), GPIO_FN(VIO_DR3),
+	GPIO_FN(VIO_DR4), GPIO_FN(VIO_DR5), GPIO_FN(VIO_DR6), GPIO_FN(VIO_DR7),
+	GPIO_FN(VIO_VDR), GPIO_FN(VIO_HDR),
+	GPIO_FN(VIO_CLKR), GPIO_FN(VIO_CKOR),
+	GPIO_FN(SCIFA1_TXD), GPIO_FN(GPS_PGFA0),
+	GPIO_FN(SCIFA1_SCK), GPIO_FN(GPS_PGFA1),
+	GPIO_FN(SCIFA1_RTS), GPIO_FN(GPS_EPPSINMON),
+	GPIO_FN(SCIFA1_RXD), GPIO_FN(SCIFA1_CTS),
+	GPIO_FN(MSIOF1_TXD), GPIO_FN(SCIFA1_TXD2), GPIO_FN(GPS_TXD),
+	GPIO_FN(MSIOF1_TSYNC), GPIO_FN(SCIFA1_CTS2), GPIO_FN(I2C_SDA2),
+	GPIO_FN(MSIOF1_TSCK), GPIO_FN(SCIFA1_SCK2),
+	GPIO_FN(MSIOF1_RXD), GPIO_FN(SCIFA1_RXD2), GPIO_FN(GPS_RXD),
+	GPIO_FN(MSIOF1_RSCK), GPIO_FN(SCIFA1_RTS2),
+	GPIO_FN(MSIOF1_RSYNC), GPIO_FN(I2C_SCL2),
+	GPIO_FN(MSIOF1_MCK0), GPIO_FN(MSIOF1_MCK1),
+	GPIO_FN(MSIOF1_SS1), GPIO_FN(EDBGREQ3),
+	GPIO_FN(MSIOF1_SS2),
+	GPIO_FN(PORT236_IROUT), GPIO_FN(IRDA_OUT),
+	GPIO_FN(IRDA_IN), GPIO_FN(IRDA_FIRSEL),
+	GPIO_FN(TPU1TO0), GPIO_FN(TS_SPSYNC3),
+	GPIO_FN(TPU1TO1), GPIO_FN(TS_SDAT3),
+	GPIO_FN(TPU1TO2), GPIO_FN(TS_SDEN3), GPIO_FN(PORT241_MSIOF2_SS1),
+	GPIO_FN(TPU1TO3), GPIO_FN(PORT242_MSIOF2_TSCK),
+	GPIO_FN(M13_BSW), GPIO_FN(PORT243_MSIOF2_TSYNC),
+	GPIO_FN(M14_GSW), GPIO_FN(PORT244_MSIOF2_TXD),
+	GPIO_FN(PORT245_IROUT), GPIO_FN(M15_RSW),
+	GPIO_FN(SOUT3), GPIO_FN(SCIFA2_TXD1),
+	GPIO_FN(SIN3), GPIO_FN(SCIFA2_RXD1),
+	GPIO_FN(XRTS3), GPIO_FN(SCIFA2_RTS1), GPIO_FN(PORT248_MSIOF2_SS2),
+	GPIO_FN(XCTS3), GPIO_FN(SCIFA2_CTS1), GPIO_FN(PORT249_MSIOF2_RXD),
+	GPIO_FN(DINT), GPIO_FN(SCIFA2_SCK1), GPIO_FN(TS_SCK3),
+	GPIO_FN(SDHICLK0), GPIO_FN(TCK2),
+	GPIO_FN(SDHICD0),
+	GPIO_FN(SDHID0_0), GPIO_FN(TMS2),
+	GPIO_FN(SDHID0_1), GPIO_FN(TDO2),
+	GPIO_FN(SDHID0_2), GPIO_FN(TDI2),
+	GPIO_FN(SDHID0_3), GPIO_FN(RTCK2),
+
+	/* 49-6 (FN) */
+	GPIO_FN(SDHICMD0), GPIO_FN(TRST2),
+	GPIO_FN(SDHIWP0), GPIO_FN(EDBGREQ2),
+	GPIO_FN(SDHICLK1), GPIO_FN(TCK3),
+	GPIO_FN(SDHID1_0), GPIO_FN(M11_SLCD_SO2),
+	GPIO_FN(TS_SPSYNC2), GPIO_FN(TMS3),
+	GPIO_FN(SDHID1_1), GPIO_FN(M9_SLCD_AO2),
+	GPIO_FN(TS_SDAT2), GPIO_FN(TDO3),
+	GPIO_FN(SDHID1_2), GPIO_FN(M10_SLCD_CK2),
+	GPIO_FN(TS_SDEN2), GPIO_FN(TDI3),
+	GPIO_FN(SDHID1_3), GPIO_FN(M12_SLCD_CE2),
+	GPIO_FN(TS_SCK2), GPIO_FN(RTCK3),
+	GPIO_FN(SDHICMD1), GPIO_FN(TRST3),
+	GPIO_FN(SDHICLK2), GPIO_FN(SCIFB_SCK),
+	GPIO_FN(SDHID2_0), GPIO_FN(SCIFB_TXD),
+	GPIO_FN(SDHID2_1), GPIO_FN(SCIFB_CTS),
+	GPIO_FN(SDHID2_2), GPIO_FN(SCIFB_RXD),
+	GPIO_FN(SDHID2_3), GPIO_FN(SCIFB_RTS),
+	GPIO_FN(SDHICMD2),
+	GPIO_FN(RESETOUTS),
+	GPIO_FN(DIVLOCK),
+};
+
+/* helper for top 4 bits in PORTnCR */
+#define PCRH(in, in_pd, in_pu, out)		\
+	0, (out), (in), 0,			\
+	0, 0, 0, 0,				\
+	0, 0, (in_pd), 0,			\
+	0, 0, (in_pu), 0
+
+#define PORTCR(nr, reg)						\
+	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {		\
+		PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,		\
+		     PORT##nr##_IN_PU, PORT##nr##_OUT),		\
+		PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2,	\
+		PORT##nr##_FN3,	PORT##nr##_FN4, PORT##nr##_FN5,	\
+		PORT##nr##_FN6, PORT##nr##_FN7 }		\
+	}
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+	PORTCR(0, 0xe6050000), /* PORT0CR */
+	PORTCR(1, 0xe6050001), /* PORT1CR */
+	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, 0xe6050020), /* PORT32CR */
+	PORTCR(33, 0xe6050021), /* PORT33CR */
+	PORTCR(34, 0xe6050022), /* PORT34CR */
+	PORTCR(35, 0xe6050023), /* PORT35CR */
+	PORTCR(36, 0xe6050024), /* PORT36CR */
+	PORTCR(37, 0xe6050025), /* PORT37CR */
+	PORTCR(38, 0xe6050026), /* PORT38CR */
+	PORTCR(39, 0xe6050027), /* PORT39CR */
+
+	PORTCR(40, 0xe6050028), /* PORT40CR */
+	PORTCR(41, 0xe6050029), /* PORT41CR */
+	PORTCR(42, 0xe605002a), /* PORT42CR */
+	PORTCR(43, 0xe605002b), /* PORT43CR */
+	PORTCR(44, 0xe605002c), /* PORT44CR */
+	PORTCR(45, 0xe605002d), /* PORT45CR */
+	PORTCR(46, 0xe605002e), /* PORT46CR */
+	PORTCR(47, 0xe605002f), /* PORT47CR */
+	PORTCR(48, 0xe6050030), /* PORT48CR */
+	PORTCR(49, 0xe6050031), /* PORT49CR */
+
+	PORTCR(50, 0xe6050032), /* PORT50CR */
+	PORTCR(51, 0xe6050033), /* PORT51CR */
+	PORTCR(52, 0xe6050034), /* PORT52CR */
+	PORTCR(53, 0xe6050035), /* PORT53CR */
+	PORTCR(54, 0xe6050036), /* PORT54CR */
+	PORTCR(55, 0xe6050037), /* PORT55CR */
+	PORTCR(56, 0xe6050038), /* PORT56CR */
+	PORTCR(57, 0xe6050039), /* PORT57CR */
+	PORTCR(58, 0xe605003a), /* PORT58CR */
+	PORTCR(59, 0xe605003b), /* PORT59CR */
+
+	PORTCR(60, 0xe605003c), /* PORT60CR */
+	PORTCR(61, 0xe605003d), /* PORT61CR */
+	PORTCR(62, 0xe605003e), /* PORT62CR */
+	PORTCR(63, 0xe605003f), /* PORT63CR */
+	PORTCR(64, 0xe6050040), /* PORT64CR */
+	PORTCR(65, 0xe6050041), /* PORT65CR */
+	PORTCR(66, 0xe6050042), /* PORT66CR */
+	PORTCR(67, 0xe6050043), /* PORT67CR */
+	PORTCR(68, 0xe6050044), /* PORT68CR */
+	PORTCR(69, 0xe6050045), /* PORT69CR */
+
+	PORTCR(70, 0xe6050046), /* PORT70CR */
+	PORTCR(71, 0xe6050047), /* PORT71CR */
+	PORTCR(72, 0xe6050048), /* PORT72CR */
+	PORTCR(73, 0xe6050049), /* PORT73CR */
+	PORTCR(74, 0xe605004a), /* PORT74CR */
+	PORTCR(75, 0xe605004b), /* PORT75CR */
+	PORTCR(76, 0xe605004c), /* PORT76CR */
+	PORTCR(77, 0xe605004d), /* PORT77CR */
+	PORTCR(78, 0xe605004e), /* PORT78CR */
+	PORTCR(79, 0xe605004f), /* PORT79CR */
+
+	PORTCR(80, 0xe6050050), /* PORT80CR */
+	PORTCR(81, 0xe6050051), /* PORT81CR */
+	PORTCR(82, 0xe6050052), /* PORT82CR */
+	PORTCR(83, 0xe6050053), /* PORT83CR */
+	PORTCR(84, 0xe6050054), /* PORT84CR */
+	PORTCR(85, 0xe6050055), /* PORT85CR */
+	PORTCR(86, 0xe6050056), /* PORT86CR */
+	PORTCR(87, 0xe6050057), /* 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, 0xe6051060), /* PORT96CR */
+	PORTCR(97, 0xe6051061), /* PORT97CR */
+	PORTCR(98, 0xe6051062), /* PORT98CR */
+	PORTCR(99, 0xe6051063), /* PORT99CR */
+
+	PORTCR(100, 0xe6051064), /* PORT100CR */
+	PORTCR(101, 0xe6051065), /* PORT101CR */
+	PORTCR(102, 0xe6051066), /* PORT102CR */
+	PORTCR(103, 0xe6051067), /* PORT103CR */
+	PORTCR(104, 0xe6051068), /* PORT104CR */
+	PORTCR(105, 0xe6051069), /* PORT105CR */
+	PORTCR(106, 0xe605106a), /* PORT106CR */
+	PORTCR(107, 0xe605106b), /* PORT107CR */
+	PORTCR(108, 0xe605106c), /* PORT108CR */
+	PORTCR(109, 0xe605106d), /* PORT109CR */
+
+	PORTCR(110, 0xe605106e), /* PORT110CR */
+	PORTCR(111, 0xe605106f), /* PORT111CR */
+	PORTCR(112, 0xe6051070), /* PORT112CR */
+	PORTCR(113, 0xe6051071), /* PORT113CR */
+	PORTCR(114, 0xe6051072), /* PORT114CR */
+	PORTCR(115, 0xe6051073), /* PORT115CR */
+	PORTCR(116, 0xe6051074), /* PORT116CR */
+	PORTCR(117, 0xe6051075), /* PORT117CR */
+	PORTCR(118, 0xe6051076), /* PORT118CR */
+	PORTCR(119, 0xe6051077), /* PORT119CR */
+
+	PORTCR(120, 0xe6051078), /* PORT120CR */
+	PORTCR(121, 0xe6051079), /* PORT121CR */
+	PORTCR(122, 0xe605107a), /* PORT122CR */
+	PORTCR(123, 0xe605107b), /* PORT123CR */
+	PORTCR(124, 0xe605107c), /* PORT124CR */
+	PORTCR(125, 0xe605107d), /* PORT125CR */
+	PORTCR(126, 0xe605107e), /* PORT126CR */
+	PORTCR(127, 0xe605107f), /* PORT127CR */
+	PORTCR(128, 0xe6051080), /* PORT128CR */
+	PORTCR(129, 0xe6051081), /* PORT129CR */
+
+	PORTCR(130, 0xe6051082), /* PORT130CR */
+	PORTCR(131, 0xe6051083), /* PORT131CR */
+	PORTCR(132, 0xe6051084), /* PORT132CR */
+	PORTCR(133, 0xe6051085), /* PORT133CR */
+	PORTCR(134, 0xe6051086), /* PORT134CR */
+	PORTCR(135, 0xe6051087), /* PORT135CR */
+	PORTCR(136, 0xe6051088), /* PORT136CR */
+	PORTCR(137, 0xe6051089), /* PORT137CR */
+	PORTCR(138, 0xe605108a), /* PORT138CR */
+	PORTCR(139, 0xe605108b), /* PORT139CR */
+
+	PORTCR(140, 0xe605108c), /* PORT140CR */
+	PORTCR(141, 0xe605108d), /* PORT141CR */
+	PORTCR(142, 0xe605108e), /* PORT142CR */
+	PORTCR(143, 0xe605108f), /* PORT143CR */
+	PORTCR(144, 0xe6051090), /* PORT144CR */
+	PORTCR(145, 0xe6051091), /* PORT145CR */
+	PORTCR(146, 0xe6051092), /* PORT146CR */
+	PORTCR(147, 0xe6051093), /* PORT147CR */
+	PORTCR(148, 0xe6051094), /* PORT148CR */
+	PORTCR(149, 0xe6051095), /* PORT149CR */
+
+	PORTCR(150, 0xe6051096), /* PORT150CR */
+	PORTCR(151, 0xe6051097), /* PORT151CR */
+	PORTCR(152, 0xe6051098), /* PORT152CR */
+	PORTCR(153, 0xe6051099), /* PORT153CR */
+	PORTCR(154, 0xe605109a), /* PORT154CR */
+	PORTCR(155, 0xe605109b), /* PORT155CR */
+	PORTCR(156, 0xe605109c), /* PORT156CR */
+	PORTCR(157, 0xe605109d), /* PORT157CR */
+	PORTCR(158, 0xe605109e), /* PORT158CR */
+	PORTCR(159, 0xe605109f), /* PORT159CR */
+
+	PORTCR(160, 0xe60510a0), /* PORT160CR */
+	PORTCR(161, 0xe60510a1), /* PORT161CR */
+	PORTCR(162, 0xe60510a2), /* PORT162CR */
+	PORTCR(163, 0xe60510a3), /* PORT163CR */
+	PORTCR(164, 0xe60510a4), /* PORT164CR */
+	PORTCR(165, 0xe60510a5), /* PORT165CR */
+	PORTCR(166, 0xe60510a6), /* PORT166CR */
+	PORTCR(167, 0xe60510a7), /* PORT167CR */
+	PORTCR(168, 0xe60510a8), /* PORT168CR */
+	PORTCR(169, 0xe60510a9), /* PORT169CR */
+
+	PORTCR(170, 0xe60510aa), /* PORT170CR */
+	PORTCR(171, 0xe60510ab), /* PORT171CR */
+	PORTCR(172, 0xe60510ac), /* PORT172CR */
+	PORTCR(173, 0xe60510ad), /* PORT173CR */
+	PORTCR(174, 0xe60510ae), /* PORT174CR */
+	PORTCR(175, 0xe60520af), /* PORT175CR */
+	PORTCR(176, 0xe60520b0), /* PORT176CR */
+	PORTCR(177, 0xe60520b1), /* PORT177CR */
+	PORTCR(178, 0xe60520b2), /* PORT178CR */
+	PORTCR(179, 0xe60520b3), /* PORT179CR */
+
+	PORTCR(180, 0xe60520b4), /* PORT180CR */
+	PORTCR(181, 0xe60520b5), /* PORT181CR */
+	PORTCR(182, 0xe60520b6), /* PORT182CR */
+	PORTCR(183, 0xe60520b7), /* PORT183CR */
+	PORTCR(184, 0xe60520b8), /* PORT184CR */
+	PORTCR(185, 0xe60520b9), /* PORT185CR */
+	PORTCR(186, 0xe60520ba), /* PORT186CR */
+	PORTCR(187, 0xe60520bb), /* PORT187CR */
+	PORTCR(188, 0xe60520bc), /* PORT188CR */
+	PORTCR(189, 0xe60520bd), /* PORT189CR */
+
+	PORTCR(190, 0xe60520be), /* PORT190CR */
+	PORTCR(191, 0xe60520bf), /* PORT191CR */
+	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, 0xe60520e0), /* PORT224CR */
+	PORTCR(225, 0xe60520e1), /* PORT225CR */
+	PORTCR(226, 0xe60520e2), /* PORT226CR */
+	PORTCR(227, 0xe60520e3), /* PORT227CR */
+	PORTCR(228, 0xe60520e4), /* PORT228CR */
+	PORTCR(229, 0xe60520e5), /* PORT229CR */
+
+	PORTCR(230, 0xe60520e6), /* PORT230CR */
+	PORTCR(231, 0xe60520e7), /* PORT231CR */
+	PORTCR(232, 0xe60520e8), /* PORT232CR */
+	PORTCR(233, 0xe60520e9), /* PORT233CR */
+	PORTCR(234, 0xe60520ea), /* PORT234CR */
+	PORTCR(235, 0xe60520eb), /* 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 */
+
+	{ PINMUX_CFG_REG("MSELBCR", 0xe6058024, 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, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0,
+		0, 0,
+		0, 0,
+		0, 0,
+		0, 0,
+		MSELBCR_MSEL2_0, MSELBCR_MSEL2_1,
+		0, 0,
+		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("PORTL063_032DR", 0xe6054004, 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("PORTL095_064DR", 0xe6054008, 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("PORTD127_096DR", 0xe6055004, 32) {
+		PORT127_DATA, PORT126_DATA, PORT125_DATA, PORT124_DATA,
+		PORT123_DATA, PORT122_DATA, PORT121_DATA, PORT120_DATA,
+		PORT119_DATA, 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("PORTD159_128DR", 0xe6055008, 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", 0xe6056000, 32) {
+		PORT191_DATA, PORT190_DATA, PORT189_DATA, PORT188_DATA,
+		PORT187_DATA, PORT186_DATA, PORT185_DATA, PORT184_DATA,
+		PORT183_DATA, PORT182_DATA, PORT181_DATA, PORT180_DATA,
+		PORT179_DATA, PORT178_DATA, PORT177_DATA, PORT176_DATA,
+		PORT175_DATA, PORT174_DATA, PORT173_DATA, PORT172_DATA,
+		PORT171_DATA, PORT170_DATA, PORT169_DATA, PORT168_DATA,
+		PORT167_DATA, PORT166_DATA, PORT165_DATA, PORT164_DATA,
+		PORT163_DATA, PORT162_DATA, PORT161_DATA, PORT160_DATA }
+	},
+	{ PINMUX_DATA_REG("PORTR223_192DR", 0xe6056004, 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, 0, 0, 0,
+		0, 0, 0, 0,
+		0, 0, 0, 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 }
+	},
+	{ },
+};
+
+static struct pinmux_info sh7367_pinmux_info = {
+	.name = "sh7367_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_DIVLOCK,
+
+	.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 sh7367_pinmux_init(void)
+{
+	register_pinmux(&sh7367_pinmux_info);
+}
diff --git a/arch/arm/mach-shmobile/pfc-sh7372.c b/arch/arm/mach-shmobile/pfc-sh7372.c
new file mode 100644
index 0000000..9557d09
--- /dev/null
+++ b/arch/arm/mach-shmobile/pfc-sh7372.c
@@ -0,0 +1,1637 @@
+/*
+ * sh7372 processor support - PFC hardware block
+ *
+ * Copyright (C) 2010  Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on
+ * sh7367 processor support - PFC 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/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <mach/sh7372.h>
+
+#define _1(fn, pfx, sfx) fn(pfx, sfx)
+
+#define _10(fn, pfx, sfx)				\
+	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
+	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
+	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
+	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
+	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
+
+#define _80(fn, pfx, sfx)				\
+	_10(fn, pfx##1, sfx),	_10(fn, pfx##2, sfx),	\
+	_10(fn, pfx##3, sfx),	_10(fn, pfx##4, sfx),	\
+	_10(fn, pfx##5, sfx),	_10(fn, pfx##6, sfx),	\
+	_10(fn, pfx##7, sfx),	_10(fn, pfx##8, sfx)
+
+#define _190(fn, pfx, sfx) \
+	_10(fn, pfx, sfx), _80(fn, pfx, sfx), _10(fn, pfx##9, sfx), \
+	_10(fn, pfx##10, sfx), _80(fn, pfx##1, sfx), _1(fn, pfx##190, sfx)
+
+#define _PORT(pfx, sfx) pfx##_##sfx
+#define PORT_ALL(str) _190(_PORT, PORT, str)
+
+enum {
+	PINMUX_RESERVED = 0,
+
+	/* PORT0_DATA -> PORT190_DATA */
+	PINMUX_DATA_BEGIN,
+	PORT_ALL(DATA),
+	PINMUX_DATA_END,
+
+	/* PORT0_IN -> PORT190_IN */
+	PINMUX_INPUT_BEGIN,
+	PORT_ALL(IN),
+	PINMUX_INPUT_END,
+
+	/* PORT0_IN_PU -> PORT190_IN_PU */
+	PINMUX_INPUT_PULLUP_BEGIN,
+	PORT_ALL(IN_PU),
+	PINMUX_INPUT_PULLUP_END,
+
+	/* PORT0_IN_PD -> PORT190_IN_PD */
+	PINMUX_INPUT_PULLDOWN_BEGIN,
+	PORT_ALL(IN_PD),
+	PINMUX_INPUT_PULLDOWN_END,
+
+	/* PORT0_OUT -> PORT190_OUT */
+	PINMUX_OUTPUT_BEGIN,
+	PORT_ALL(OUT),
+	PINMUX_OUTPUT_END,
+
+	PINMUX_FUNCTION_BEGIN,
+	PORT_ALL(FN_IN),	/* PORT0_FN_IN	-> PORT190_FN_IN */
+	PORT_ALL(FN_OUT),	/* PORT0_FN_OUT	-> PORT190_FN_OUT */
+	PORT_ALL(FN0),		/* PORT0_FN0	-> PORT190_FN0 */
+	PORT_ALL(FN1),		/* PORT0_FN1	-> PORT190_FN1 */
+	PORT_ALL(FN2),		/* PORT0_FN2	-> PORT190_FN2 */
+	PORT_ALL(FN3),		/* PORT0_FN3	-> PORT190_FN3 */
+	PORT_ALL(FN4),		/* PORT0_FN4	-> PORT190_FN4 */
+	PORT_ALL(FN5),		/* PORT0_FN5	-> PORT190_FN5 */
+	PORT_ALL(FN6),		/* PORT0_FN6	-> PORT190_FN6 */
+	PORT_ALL(FN7),		/* PORT0_FN7	-> PORT190_FN7 */
+
+	MSEL1CR_31_0,	MSEL1CR_31_1,
+	MSEL1CR_30_0,	MSEL1CR_30_1,
+	MSEL1CR_29_0,	MSEL1CR_29_1,
+	MSEL1CR_28_0,	MSEL1CR_28_1,
+	MSEL1CR_27_0,	MSEL1CR_27_1,
+	MSEL1CR_26_0,	MSEL1CR_26_1,
+	MSEL1CR_16_0,	MSEL1CR_16_1,
+	MSEL1CR_15_0,	MSEL1CR_15_1,
+	MSEL1CR_14_0,	MSEL1CR_14_1,
+	MSEL1CR_13_0,	MSEL1CR_13_1,
+	MSEL1CR_12_0,	MSEL1CR_12_1,
+	MSEL1CR_9_0,	MSEL1CR_9_1,
+	MSEL1CR_8_0,	MSEL1CR_8_1,
+	MSEL1CR_7_0,	MSEL1CR_7_1,
+	MSEL1CR_6_0,	MSEL1CR_6_1,
+	MSEL1CR_4_0,	MSEL1CR_4_1,
+	MSEL1CR_3_0,	MSEL1CR_3_1,
+	MSEL1CR_2_0,	MSEL1CR_2_1,
+	MSEL1CR_0_0,	MSEL1CR_0_1,
+
+	MSEL3CR_27_0,	MSEL3CR_27_1,
+	MSEL3CR_26_0,	MSEL3CR_26_1,
+	MSEL3CR_21_0,	MSEL3CR_21_1,
+	MSEL3CR_20_0,	MSEL3CR_20_1,
+	MSEL3CR_15_0,	MSEL3CR_15_1,
+	MSEL3CR_9_0,	MSEL3CR_9_1,
+	MSEL3CR_6_0,	MSEL3CR_6_1,
+
+	MSEL4CR_19_0,	MSEL4CR_19_1,
+	MSEL4CR_18_0,	MSEL4CR_18_1,
+	MSEL4CR_17_0,	MSEL4CR_17_1,
+	MSEL4CR_16_0,	MSEL4CR_16_1,
+	MSEL4CR_15_0,	MSEL4CR_15_1,
+	MSEL4CR_14_0,	MSEL4CR_14_1,
+	MSEL4CR_10_0,	MSEL4CR_10_1,
+	MSEL4CR_6_0,	MSEL4CR_6_1,
+	MSEL4CR_4_0,	MSEL4CR_4_1,
+	MSEL4CR_1_0,	MSEL4CR_1_1,
+	PINMUX_FUNCTION_END,
+
+	PINMUX_MARK_BEGIN,
+
+	/* IRQ */
+	IRQ0_6_MARK,	IRQ0_162_MARK,	IRQ1_MARK,	IRQ2_4_MARK,
+	IRQ2_5_MARK,	IRQ3_8_MARK,	IRQ3_16_MARK,	IRQ4_17_MARK,
+	IRQ4_163_MARK,	IRQ5_MARK,	IRQ6_39_MARK,	IRQ6_164_MARK,
+	IRQ7_40_MARK,	IRQ7_167_MARK,	IRQ8_41_MARK,	IRQ8_168_MARK,
+	IRQ9_42_MARK,	IRQ9_169_MARK,	IRQ10_MARK,	IRQ11_MARK,
+	IRQ12_80_MARK,	IRQ12_137_MARK,	IRQ13_81_MARK,	IRQ13_145_MARK,
+	IRQ14_82_MARK,	IRQ14_146_MARK,	IRQ15_83_MARK,	IRQ15_147_MARK,
+	IRQ16_84_MARK,	IRQ16_170_MARK,	IRQ17_MARK,	IRQ18_MARK,
+	IRQ19_MARK,	IRQ20_MARK,	IRQ21_MARK,	IRQ22_MARK,
+	IRQ23_MARK,	IRQ24_MARK,	IRQ25_MARK,	IRQ26_121_MARK,
+	IRQ26_172_MARK,	IRQ27_122_MARK,	IRQ27_180_MARK,	IRQ28_123_MARK,
+	IRQ28_181_MARK,	IRQ29_129_MARK,	IRQ29_182_MARK,	IRQ30_130_MARK,
+	IRQ30_183_MARK,	IRQ31_138_MARK,	IRQ31_184_MARK,
+
+	/* MSIOF0 */
+	MSIOF0_TSYNC_MARK,	MSIOF0_TSCK_MARK,	MSIOF0_RXD_MARK,
+	MSIOF0_RSCK_MARK,	MSIOF0_RSYNC_MARK,	MSIOF0_MCK0_MARK,
+	MSIOF0_MCK1_MARK,	MSIOF0_SS1_MARK,	MSIOF0_SS2_MARK,
+	MSIOF0_TXD_MARK,
+
+	/* MSIOF1 */
+	MSIOF1_TSCK_39_MARK,	MSIOF1_TSYNC_40_MARK,
+	MSIOF1_TSCK_88_MARK,	MSIOF1_TSYNC_89_MARK,
+	MSIOF1_TXD_41_MARK,	MSIOF1_RXD_42_MARK,
+	MSIOF1_TXD_90_MARK,	MSIOF1_RXD_91_MARK,
+	MSIOF1_SS1_43_MARK,	MSIOF1_SS2_44_MARK,
+	MSIOF1_SS1_92_MARK,	MSIOF1_SS2_93_MARK,
+	MSIOF1_RSCK_MARK,	MSIOF1_RSYNC_MARK,
+	MSIOF1_MCK0_MARK,	MSIOF1_MCK1_MARK,
+
+	/* MSIOF2 */
+	MSIOF2_RSCK_MARK,	MSIOF2_RSYNC_MARK,	MSIOF2_MCK0_MARK,
+	MSIOF2_MCK1_MARK,	MSIOF2_SS1_MARK,	MSIOF2_SS2_MARK,
+	MSIOF2_TSYNC_MARK,	MSIOF2_TSCK_MARK,	MSIOF2_RXD_MARK,
+	MSIOF2_TXD_MARK,
+
+	/* MSIOF3 */
+	BBIF1_RXD_MARK,		BBIF1_TSYNC_MARK,	BBIF1_TSCK_MARK,
+	BBIF1_TXD_MARK,		BBIF1_RSCK_MARK,	BBIF1_RSYNC_MARK,
+	BBIF1_FLOW_MARK,	BB_RX_FLOW_N_MARK,
+
+	/* MSIOF4 */
+	BBIF2_TSCK1_MARK,	BBIF2_TSYNC1_MARK,
+	BBIF2_TXD1_MARK,	BBIF2_RXD_MARK,
+
+	/* FSI */
+	FSIACK_MARK,	FSIBCK_MARK,		FSIAILR_MARK,	FSIAIBT_MARK,
+	FSIAISLD_MARK,	FSIAOMC_MARK,		FSIAOLR_MARK,	FSIAOBT_MARK,
+	FSIAOSLD_MARK,	FSIASPDIF_11_MARK,	FSIASPDIF_15_MARK,
+
+	/* FMSI */
+	FMSOCK_MARK,	FMSOOLR_MARK,	FMSIOLR_MARK,	FMSOOBT_MARK,
+	FMSIOBT_MARK,	FMSOSLD_MARK,	FMSOILR_MARK,	FMSIILR_MARK,
+	FMSOIBT_MARK,	FMSIIBT_MARK,	FMSISLD_MARK,	FMSICK_MARK,
+
+	/* SCIFA0 */
+	SCIFA0_TXD_MARK,	SCIFA0_RXD_MARK,	SCIFA0_SCK_MARK,
+	SCIFA0_RTS_MARK,	SCIFA0_CTS_MARK,
+
+	/* SCIFA1 */
+	SCIFA1_TXD_MARK,	SCIFA1_RXD_MARK,	SCIFA1_SCK_MARK,
+	SCIFA1_RTS_MARK,	SCIFA1_CTS_MARK,
+
+	/* SCIFA2 */
+	SCIFA2_CTS1_MARK,	SCIFA2_RTS1_MARK,	SCIFA2_TXD1_MARK,
+	SCIFA2_RXD1_MARK,	SCIFA2_SCK1_MARK,
+
+	/* SCIFA3 */
+	SCIFA3_CTS_43_MARK,	SCIFA3_CTS_140_MARK,	SCIFA3_RTS_44_MARK,
+	SCIFA3_RTS_141_MARK,	SCIFA3_SCK_MARK,	SCIFA3_TXD_MARK,
+	SCIFA3_RXD_MARK,
+
+	/* SCIFA4 */
+	SCIFA4_RXD_MARK,	SCIFA4_TXD_MARK,
+
+	/* SCIFA5 */
+	SCIFA5_RXD_MARK,	SCIFA5_TXD_MARK,
+
+	/* SCIFB */
+	SCIFB_SCK_MARK,	SCIFB_RTS_MARK,	SCIFB_CTS_MARK,
+	SCIFB_TXD_MARK,	SCIFB_RXD_MARK,
+
+	/* CEU */
+	VIO_HD_MARK,	VIO_CKO1_MARK,	VIO_CKO2_MARK,	VIO_VD_MARK,
+	VIO_CLK_MARK,	VIO_FIELD_MARK,	VIO_CKO_MARK,
+	VIO_D0_MARK,	VIO_D1_MARK,	VIO_D2_MARK,	VIO_D3_MARK,
+	VIO_D4_MARK,	VIO_D5_MARK,	VIO_D6_MARK,	VIO_D7_MARK,
+	VIO_D8_MARK,	VIO_D9_MARK,	VIO_D10_MARK,	VIO_D11_MARK,
+	VIO_D12_MARK,	VIO_D13_MARK,	VIO_D14_MARK,	VIO_D15_MARK,
+
+	/* USB0 */
+	IDIN_0_MARK,	EXTLP_0_MARK,	OVCN2_0_MARK,	PWEN_0_MARK,
+	OVCN_0_MARK,	VBUS0_0_MARK,
+
+	/* USB1 */
+	IDIN_1_18_MARK,		IDIN_1_113_MARK,
+	PWEN_1_115_MARK,	PWEN_1_138_MARK,
+	OVCN_1_114_MARK,	OVCN_1_162_MARK,
+	EXTLP_1_MARK,		OVCN2_1_MARK,
+	VBUS0_1_MARK,
+
+	/* GPIO */
+	GPI0_MARK,	GPI1_MARK,	GPO0_MARK,	GPO1_MARK,
+
+	/* BSC */
+	BS_MARK,	WE1_MARK,
+	CKO_MARK,	WAIT_MARK,	RDWR_MARK,
+
+	A0_MARK,	A1_MARK,	A2_MARK,	A3_MARK,
+	A6_MARK,	A7_MARK,	A8_MARK,	A9_MARK,
+	A10_MARK,	A11_MARK,	A12_MARK,	A13_MARK,
+	A14_MARK,	A15_MARK,	A16_MARK,	A17_MARK,
+	A18_MARK,	A19_MARK,	A20_MARK,	A21_MARK,
+	A22_MARK,	A23_MARK,	A24_MARK,	A25_MARK,
+	A26_MARK,
+
+	CS0_MARK,	CS2_MARK,	CS4_MARK,
+	CS5A_MARK,	CS5B_MARK,	CS6A_MARK,
+
+	/* BSC/FLCTL */
+	RD_FSC_MARK,	WE0_FWE_MARK,	A4_FOE_MARK,	A5_FCDE_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,
+
+	/* MMCIF(1) */
+	MMCD0_0_MARK,	MMCD0_1_MARK,	MMCD0_2_MARK,	MMCD0_3_MARK,
+	MMCD0_4_MARK,	MMCD0_5_MARK,	MMCD0_6_MARK,	MMCD0_7_MARK,
+	MMCCMD0_MARK,	MMCCLK0_MARK,
+
+	/* MMCIF(2) */
+	MMCD1_0_MARK,	MMCD1_1_MARK,	MMCD1_2_MARK,	MMCD1_3_MARK,
+	MMCD1_4_MARK,	MMCD1_5_MARK,	MMCD1_6_MARK,	MMCD1_7_MARK,
+	MMCCLK1_MARK,	MMCCMD1_MARK,
+
+	/* SPU2 */
+	VINT_I_MARK,
+
+	/* FLCTL */
+	FCE1_MARK,	FCE0_MARK,	FRB_MARK,
+
+	/* HSI */
+	GP_RX_FLAG_MARK,	GP_RX_DATA_MARK,	GP_TX_READY_MARK,
+	GP_RX_WAKE_MARK,	MP_TX_FLAG_MARK,	MP_TX_DATA_MARK,
+	MP_RX_READY_MARK,	MP_TX_WAKE_MARK,
+
+	/* MFI */
+	MFIv6_MARK,
+	MFIv4_MARK,
+
+	MEMC_CS0_MARK,			MEMC_BUSCLK_MEMC_A0_MARK,
+	MEMC_CS1_MEMC_A1_MARK,		MEMC_ADV_MEMC_DREQ0_MARK,
+	MEMC_WAIT_MEMC_DREQ1_MARK,	MEMC_NOE_MARK,
+	MEMC_NWE_MARK,			MEMC_INT_MARK,
+
+	MEMC_AD0_MARK,	MEMC_AD1_MARK,	MEMC_AD2_MARK,
+	MEMC_AD3_MARK,	MEMC_AD4_MARK,	MEMC_AD5_MARK,
+	MEMC_AD6_MARK,	MEMC_AD7_MARK,	MEMC_AD8_MARK,
+	MEMC_AD9_MARK,	MEMC_AD10_MARK,	MEMC_AD11_MARK,
+	MEMC_AD12_MARK,	MEMC_AD13_MARK,	MEMC_AD14_MARK,
+	MEMC_AD15_MARK,
+
+	/* SIM */
+	SIM_RST_MARK,	SIM_CLK_MARK,	SIM_D_MARK,
+
+	/* TPU */
+	TPU0TO0_MARK,		TPU0TO1_MARK,
+	TPU0TO2_93_MARK,	TPU0TO2_99_MARK,
+	TPU0TO3_MARK,
+
+	/* I2C2 */
+	I2C_SCL2_MARK,	I2C_SDA2_MARK,
+
+	/* I2C3(1) */
+	I2C_SCL3_MARK,	I2C_SDA3_MARK,
+
+	/* I2C3(2) */
+	I2C_SCL3S_MARK,	I2C_SDA3S_MARK,
+
+	/* I2C4(2) */
+	I2C_SCL4_MARK,	I2C_SDA4_MARK,
+
+	/* I2C4(2) */
+	I2C_SCL4S_MARK,	I2C_SDA4S_MARK,
+
+	/* KEYSC */
+	KEYOUT0_MARK,	KEYIN0_121_MARK,	KEYIN0_136_MARK,
+	KEYOUT1_MARK,	KEYIN1_122_MARK,	KEYIN1_135_MARK,
+	KEYOUT2_MARK,	KEYIN2_123_MARK,	KEYIN2_134_MARK,
+	KEYOUT3_MARK,	KEYIN3_124_MARK,	KEYIN3_133_MARK,
+	KEYOUT4_MARK,	KEYIN4_MARK,
+	KEYOUT5_MARK,	KEYIN5_MARK,
+	KEYOUT6_MARK,	KEYIN6_MARK,
+	KEYOUT7_MARK,	KEYIN7_MARK,
+
+	/* LCDC */
+	LCDC0_SELECT_MARK,
+	LCDC1_SELECT_MARK,
+	LCDHSYN_MARK,	LCDCS_MARK,	LCDVSYN_MARK,	LCDDCK_MARK,
+	LCDWR_MARK,	LCDRD_MARK,	LCDDISP_MARK,	LCDRS_MARK,
+	LCDLCLK_MARK,	LCDDON_MARK,
+
+	LCDD0_MARK,	LCDD1_MARK,	LCDD2_MARK,	LCDD3_MARK,
+	LCDD4_MARK,	LCDD5_MARK,	LCDD6_MARK,	LCDD7_MARK,
+	LCDD8_MARK,	LCDD9_MARK,	LCDD10_MARK,	LCDD11_MARK,
+	LCDD12_MARK,	LCDD13_MARK,	LCDD14_MARK,	LCDD15_MARK,
+	LCDD16_MARK,	LCDD17_MARK,	LCDD18_MARK,	LCDD19_MARK,
+	LCDD20_MARK,	LCDD21_MARK,	LCDD22_MARK,	LCDD23_MARK,
+
+	/* IRDA */
+	IRDA_OUT_MARK,	IRDA_IN_MARK,	IRDA_FIRSEL_MARK,
+	IROUT_139_MARK,	IROUT_140_MARK,
+
+	/* TSIF1 */
+	TS0_1SELECT_MARK,
+	TS0_2SELECT_MARK,
+	TS1_1SELECT_MARK,
+	TS1_2SELECT_MARK,
+
+	TS_SPSYNC1_MARK,	TS_SDAT1_MARK,
+	TS_SDEN1_MARK,		TS_SCK1_MARK,
+
+	/* TSIF2 */
+	TS_SPSYNC2_MARK,	TS_SDAT2_MARK,
+	TS_SDEN2_MARK,		TS_SCK2_MARK,
+
+	/* HDMI */
+	HDMI_HPD_MARK,	HDMI_CEC_MARK,
+
+	/* SDHI0 */
+	SDHICLK0_MARK,	SDHICD0_MARK,
+	SDHICMD0_MARK,	SDHIWP0_MARK,
+	SDHID0_0_MARK,	SDHID0_1_MARK,
+	SDHID0_2_MARK,	SDHID0_3_MARK,
+
+	/* SDHI1 */
+	SDHICLK1_MARK,	SDHICMD1_MARK,	SDHID1_0_MARK,
+	SDHID1_1_MARK,	SDHID1_2_MARK,	SDHID1_3_MARK,
+
+	/* SDHI2 */
+	SDHICLK2_MARK,	SDHICMD2_MARK,	SDHID2_0_MARK,
+	SDHID2_1_MARK,	SDHID2_2_MARK,	SDHID2_3_MARK,
+
+	/* SDENC */
+	SDENC_CPG_MARK,
+	SDENC_DV_CLKI_MARK,
+
+	PINMUX_MARK_END,
+};
+
+/* PORT_DATA_I_PD(nr) */
+#define _I___D(nr)			     \
+	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
+		    PORT##nr##_IN, PORT##nr##_IN_PD)
+
+/* PORT_DATA_I_PU(nr) */
+#define _I__U_(nr)			     \
+	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
+		    PORT##nr##_IN, PORT##nr##_IN_PU)
+
+/* PORT_DATA_I_PU_PD(nr) */
+#define _I__UD(nr)			     \
+	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
+		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
+
+/* PORT_DATA_O(nr) */
+#define __O___(nr)							\
+	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
+
+/* PORT_DATA_IO(nr) */
+#define _IO___(nr)				     \
+	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
+		    PORT##nr##_IN)
+
+/* PORT_DATA_IO_PD(nr) */
+#define _IO__D(nr)					     \
+	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
+		    PORT##nr##_IN, PORT##nr##_IN_PD)
+
+/* PORT_DATA_IO_PU(nr) */
+#define _IO_U_(nr)					     \
+	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
+		    PORT##nr##_IN, PORT##nr##_IN_PU)
+
+/* PORT_DATA_IO_PU_PD(nr) */
+#define _IO_UD(nr)					     \
+	PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
+		    PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
+
+
+static pinmux_enum_t pinmux_data[] = {
+
+	/* specify valid pin states for each pin in GPIO mode */
+
+	_IO__D(0), _IO__D(1), __O___(2), _I___D(3), _I___D(4),
+	_I___D(5), _IO_UD(6), _I___D(7), _IO__D(8), __O___(9),
+
+	__O___(10), __O___(11), _IO_UD(12), _IO__D(13), _IO__D(14),
+	__O___(15), _IO__D(16), _IO__D(17), _I___D(18), _IO___(19),
+
+	_IO___(20), _IO___(21), _IO___(22), _IO___(23), _IO___(24),
+	_IO___(25), _IO___(26), _IO___(27), _IO___(28), _IO___(29),
+
+	_IO___(30), _IO___(31), _IO___(32), _IO___(33), _IO___(34),
+	_IO___(35), _IO___(36), _IO___(37), _IO___(38), _IO___(39),
+
+	_IO___(40), _IO___(41), _IO___(42), _IO___(43), _IO___(44),
+	_IO___(45), _IO_U_(46), _IO_U_(47), _IO_U_(48), _IO_U_(49),
+
+	_IO_U_(50), _IO_U_(51), _IO_U_(52), _IO_U_(53), _IO_U_(54),
+	_IO_U_(55), _IO_U_(56), _IO_U_(57), _IO_U_(58), _IO_U_(59),
+
+	_IO_U_(60), _IO_U_(61), _IO___(62), __O___(63), __O___(64),
+	_IO_U_(65), __O___(66), _IO_U_(67), __O___(68), _IO___(69), /*66?*/
+
+	_IO___(70), _IO___(71), __O___(72), _I__U_(73), _I__UD(74),
+	_IO_UD(75), _IO_UD(76), _IO_UD(77), _IO_UD(78), _IO_UD(79),
+
+	_IO_UD(80), _IO_UD(81), _IO_UD(82), _IO_UD(83), _IO_UD(84),
+	_IO_UD(85), _IO_UD(86), _IO_UD(87), _IO_UD(88), _IO_UD(89),
+
+	_IO_UD(90), _IO_UD(91), _IO_UD(92), _IO_UD(93), _IO_UD(94),
+	_IO_UD(95), _IO_U_(96), _IO_UD(97), _IO_UD(98), __O___(99), /*99?*/
+
+	_IO__D(100), _IO__D(101), _IO__D(102), _IO__D(103), _IO__D(104),
+	_IO__D(105), _IO_U_(106), _IO_U_(107), _IO_U_(108), _IO_U_(109),
+
+	_IO_U_(110), _IO_U_(111), _IO__D(112), _IO__D(113), _IO_U_(114),
+	_IO_U_(115), _IO_U_(116), _IO_U_(117), _IO_U_(118), _IO_U_(119),
+
+	_IO_U_(120), _IO__D(121), _IO__D(122), _IO__D(123), _IO__D(124),
+	_IO__D(125), _IO__D(126), _IO__D(127), _IO__D(128), _IO_UD(129),
+
+	_IO_UD(130), _IO_UD(131), _IO_UD(132), _IO_UD(133), _IO_UD(134),
+	_IO_UD(135), _IO__D(136), _IO__D(137), _IO__D(138), _IO__D(139),
+
+	_IO__D(140), _IO__D(141), _IO__D(142), _IO_UD(143), _IO__D(144),
+	_IO__D(145), _IO__D(146), _IO__D(147), _IO__D(148), _IO__D(149),
+
+	_IO__D(150), _IO__D(151), _IO_UD(152), _I___D(153), _IO_UD(154),
+	_I___D(155), _IO__D(156), _IO__D(157), _I___D(158), _IO__D(159),
+
+	__O___(160), _IO__D(161), _IO__D(162), _IO__D(163), _I___D(164),
+	_IO__D(165), _I___D(166), _I___D(167), _I___D(168), _I___D(169),
+
+	_I___D(170), __O___(171), _IO_UD(172), _IO_UD(173), _IO_UD(174),
+	_IO_UD(175), _IO_UD(176), _IO_UD(177), _IO_UD(178), __O___(179),
+
+	_IO_UD(180), _IO_UD(181), _IO_UD(182), _IO_UD(183), _IO_UD(184),
+	__O___(185), _IO_UD(186), _IO_UD(187), _IO_UD(188), _IO_UD(189),
+
+	_IO_UD(190),
+
+	/* IRQ */
+	PINMUX_DATA(IRQ0_6_MARK,	PORT6_FN0, 	MSEL1CR_0_0),
+	PINMUX_DATA(IRQ0_162_MARK,	PORT162_FN0,	MSEL1CR_0_1),
+	PINMUX_DATA(IRQ1_MARK,		PORT12_FN0),
+	PINMUX_DATA(IRQ2_4_MARK,	PORT4_FN0,	MSEL1CR_2_0),
+	PINMUX_DATA(IRQ2_5_MARK,	PORT5_FN0,	MSEL1CR_2_1),
+	PINMUX_DATA(IRQ3_8_MARK,	PORT8_FN0,	MSEL1CR_3_0),
+	PINMUX_DATA(IRQ3_16_MARK,	PORT16_FN0,	MSEL1CR_3_1),
+	PINMUX_DATA(IRQ4_17_MARK,	PORT17_FN0,	MSEL1CR_4_0),
+	PINMUX_DATA(IRQ4_163_MARK,	PORT163_FN0,	MSEL1CR_4_1),
+	PINMUX_DATA(IRQ5_MARK,		PORT18_FN0),
+	PINMUX_DATA(IRQ6_39_MARK,	PORT39_FN0,	MSEL1CR_6_0),
+	PINMUX_DATA(IRQ6_164_MARK,	PORT164_FN0,	MSEL1CR_6_1),
+	PINMUX_DATA(IRQ7_40_MARK,	PORT40_FN0,	MSEL1CR_7_1),
+	PINMUX_DATA(IRQ7_167_MARK,	PORT167_FN0,	MSEL1CR_7_0),
+	PINMUX_DATA(IRQ8_41_MARK,	PORT41_FN0,	MSEL1CR_8_1),
+	PINMUX_DATA(IRQ8_168_MARK,	PORT168_FN0,	MSEL1CR_8_0),
+	PINMUX_DATA(IRQ9_42_MARK,	PORT42_FN0,	MSEL1CR_9_0),
+	PINMUX_DATA(IRQ9_169_MARK,	PORT169_FN0,	MSEL1CR_9_1),
+	PINMUX_DATA(IRQ10_MARK,		PORT65_FN0,	MSEL1CR_9_1),
+	PINMUX_DATA(IRQ11_MARK,		PORT67_FN0),
+	PINMUX_DATA(IRQ12_80_MARK,	PORT80_FN0,	MSEL1CR_12_0),
+	PINMUX_DATA(IRQ12_137_MARK,	PORT137_FN0,	MSEL1CR_12_1),
+	PINMUX_DATA(IRQ13_81_MARK,	PORT81_FN0,	MSEL1CR_13_0),
+	PINMUX_DATA(IRQ13_145_MARK,	PORT145_FN0,	MSEL1CR_13_1),
+	PINMUX_DATA(IRQ14_82_MARK,	PORT82_FN0,	MSEL1CR_14_0),
+	PINMUX_DATA(IRQ14_146_MARK,	PORT146_FN0,	MSEL1CR_14_1),
+	PINMUX_DATA(IRQ15_83_MARK,	PORT83_FN0,	MSEL1CR_15_0),
+	PINMUX_DATA(IRQ15_147_MARK,	PORT147_FN0,	MSEL1CR_15_1),
+	PINMUX_DATA(IRQ16_84_MARK,	PORT84_FN0,	MSEL1CR_16_0),
+	PINMUX_DATA(IRQ16_170_MARK,	PORT170_FN0,	MSEL1CR_16_1),
+	PINMUX_DATA(IRQ17_MARK,		PORT85_FN0),
+	PINMUX_DATA(IRQ18_MARK,		PORT86_FN0),
+	PINMUX_DATA(IRQ19_MARK,		PORT87_FN0),
+	PINMUX_DATA(IRQ20_MARK,		PORT92_FN0),
+	PINMUX_DATA(IRQ21_MARK,		PORT93_FN0),
+	PINMUX_DATA(IRQ22_MARK,		PORT94_FN0),
+	PINMUX_DATA(IRQ23_MARK,		PORT95_FN0),
+	PINMUX_DATA(IRQ24_MARK,		PORT112_FN0),
+	PINMUX_DATA(IRQ25_MARK,		PORT119_FN0),
+	PINMUX_DATA(IRQ26_121_MARK,	PORT121_FN0,	MSEL1CR_26_1),
+	PINMUX_DATA(IRQ26_172_MARK,	PORT172_FN0,	MSEL1CR_26_0),
+	PINMUX_DATA(IRQ27_122_MARK,	PORT122_FN0,	MSEL1CR_27_1),
+	PINMUX_DATA(IRQ27_180_MARK,	PORT180_FN0,	MSEL1CR_27_0),
+	PINMUX_DATA(IRQ28_123_MARK,	PORT123_FN0,	MSEL1CR_28_1),
+	PINMUX_DATA(IRQ28_181_MARK,	PORT181_FN0,	MSEL1CR_28_0),
+	PINMUX_DATA(IRQ29_129_MARK,	PORT129_FN0,	MSEL1CR_29_1),
+	PINMUX_DATA(IRQ29_182_MARK,	PORT182_FN0,	MSEL1CR_29_0),
+	PINMUX_DATA(IRQ30_130_MARK,	PORT130_FN0,	MSEL1CR_30_1),
+	PINMUX_DATA(IRQ30_183_MARK,	PORT183_FN0,	MSEL1CR_30_0),
+	PINMUX_DATA(IRQ31_138_MARK,	PORT138_FN0,	MSEL1CR_31_1),
+	PINMUX_DATA(IRQ31_184_MARK,	PORT184_FN0,	MSEL1CR_31_0),
+
+	/* Function 1 */
+	PINMUX_DATA(BBIF2_TSCK1_MARK,		PORT0_FN1),
+	PINMUX_DATA(BBIF2_TSYNC1_MARK,		PORT1_FN1),
+	PINMUX_DATA(BBIF2_TXD1_MARK,		PORT2_FN1),
+	PINMUX_DATA(BBIF2_RXD_MARK,		PORT3_FN1),
+	PINMUX_DATA(FSIACK_MARK,		PORT4_FN1),
+	PINMUX_DATA(FSIAILR_MARK,		PORT5_FN1),
+	PINMUX_DATA(FSIAIBT_MARK,		PORT6_FN1),
+	PINMUX_DATA(FSIAISLD_MARK,		PORT7_FN1),
+	PINMUX_DATA(FSIAOMC_MARK,		PORT8_FN1),
+	PINMUX_DATA(FSIAOLR_MARK,		PORT9_FN1),
+	PINMUX_DATA(FSIAOBT_MARK,		PORT10_FN1),
+	PINMUX_DATA(FSIAOSLD_MARK,		PORT11_FN1),
+	PINMUX_DATA(FMSOCK_MARK,		PORT12_FN1),
+	PINMUX_DATA(FMSOOLR_MARK,		PORT13_FN1),
+	PINMUX_DATA(FMSOOBT_MARK,		PORT14_FN1),
+	PINMUX_DATA(FMSOSLD_MARK,		PORT15_FN1),
+	PINMUX_DATA(FMSOILR_MARK,		PORT16_FN1),
+	PINMUX_DATA(FMSOIBT_MARK,		PORT17_FN1),
+	PINMUX_DATA(FMSISLD_MARK,		PORT18_FN1),
+	PINMUX_DATA(A0_MARK,			PORT19_FN1),
+	PINMUX_DATA(A1_MARK,			PORT20_FN1),
+	PINMUX_DATA(A2_MARK,			PORT21_FN1),
+	PINMUX_DATA(A3_MARK,			PORT22_FN1),
+	PINMUX_DATA(A4_FOE_MARK,		PORT23_FN1),
+	PINMUX_DATA(A5_FCDE_MARK,		PORT24_FN1),
+	PINMUX_DATA(A6_MARK,			PORT25_FN1),
+	PINMUX_DATA(A7_MARK,			PORT26_FN1),
+	PINMUX_DATA(A8_MARK,			PORT27_FN1),
+	PINMUX_DATA(A9_MARK,			PORT28_FN1),
+	PINMUX_DATA(A10_MARK,			PORT29_FN1),
+	PINMUX_DATA(A11_MARK,			PORT30_FN1),
+	PINMUX_DATA(A12_MARK,			PORT31_FN1),
+	PINMUX_DATA(A13_MARK,			PORT32_FN1),
+	PINMUX_DATA(A14_MARK,			PORT33_FN1),
+	PINMUX_DATA(A15_MARK,			PORT34_FN1),
+	PINMUX_DATA(A16_MARK,			PORT35_FN1),
+	PINMUX_DATA(A17_MARK,			PORT36_FN1),
+	PINMUX_DATA(A18_MARK,			PORT37_FN1),
+	PINMUX_DATA(A19_MARK,			PORT38_FN1),
+	PINMUX_DATA(A20_MARK,			PORT39_FN1),
+	PINMUX_DATA(A21_MARK,			PORT40_FN1),
+	PINMUX_DATA(A22_MARK,			PORT41_FN1),
+	PINMUX_DATA(A23_MARK,			PORT42_FN1),
+	PINMUX_DATA(A24_MARK,			PORT43_FN1),
+	PINMUX_DATA(A25_MARK,			PORT44_FN1),
+	PINMUX_DATA(A26_MARK,			PORT45_FN1),
+	PINMUX_DATA(D0_NAF0_MARK,		PORT46_FN1),
+	PINMUX_DATA(D1_NAF1_MARK,		PORT47_FN1),
+	PINMUX_DATA(D2_NAF2_MARK,		PORT48_FN1),
+	PINMUX_DATA(D3_NAF3_MARK,		PORT49_FN1),
+	PINMUX_DATA(D4_NAF4_MARK,		PORT50_FN1),
+	PINMUX_DATA(D5_NAF5_MARK,		PORT51_FN1),
+	PINMUX_DATA(D6_NAF6_MARK,		PORT52_FN1),
+	PINMUX_DATA(D7_NAF7_MARK,		PORT53_FN1),
+	PINMUX_DATA(D8_NAF8_MARK,		PORT54_FN1),
+	PINMUX_DATA(D9_NAF9_MARK,		PORT55_FN1),
+	PINMUX_DATA(D10_NAF10_MARK,		PORT56_FN1),
+	PINMUX_DATA(D11_NAF11_MARK,		PORT57_FN1),
+	PINMUX_DATA(D12_NAF12_MARK,		PORT58_FN1),
+	PINMUX_DATA(D13_NAF13_MARK,		PORT59_FN1),
+	PINMUX_DATA(D14_NAF14_MARK,		PORT60_FN1),
+	PINMUX_DATA(D15_NAF15_MARK,		PORT61_FN1),
+	PINMUX_DATA(CS0_MARK,			PORT62_FN1),
+	PINMUX_DATA(CS2_MARK,			PORT63_FN1),
+	PINMUX_DATA(CS4_MARK,			PORT64_FN1),
+	PINMUX_DATA(CS5A_MARK,			PORT65_FN1),
+	PINMUX_DATA(CS5B_MARK,			PORT66_FN1),
+	PINMUX_DATA(CS6A_MARK,			PORT67_FN1),
+	PINMUX_DATA(FCE0_MARK,			PORT68_FN1),
+	PINMUX_DATA(RD_FSC_MARK,		PORT69_FN1),
+	PINMUX_DATA(WE0_FWE_MARK,		PORT70_FN1),
+	PINMUX_DATA(WE1_MARK,			PORT71_FN1),
+	PINMUX_DATA(CKO_MARK,			PORT72_FN1),
+	PINMUX_DATA(FRB_MARK,			PORT73_FN1),
+	PINMUX_DATA(WAIT_MARK,			PORT74_FN1),
+	PINMUX_DATA(RDWR_MARK,			PORT75_FN1),
+	PINMUX_DATA(MEMC_AD0_MARK,		PORT76_FN1),
+	PINMUX_DATA(MEMC_AD1_MARK,		PORT77_FN1),
+	PINMUX_DATA(MEMC_AD2_MARK,		PORT78_FN1),
+	PINMUX_DATA(MEMC_AD3_MARK,		PORT79_FN1),
+	PINMUX_DATA(MEMC_AD4_MARK,		PORT80_FN1),
+	PINMUX_DATA(MEMC_AD5_MARK,		PORT81_FN1),
+	PINMUX_DATA(MEMC_AD6_MARK,		PORT82_FN1),
+	PINMUX_DATA(MEMC_AD7_MARK,		PORT83_FN1),
+	PINMUX_DATA(MEMC_AD8_MARK,		PORT84_FN1),
+	PINMUX_DATA(MEMC_AD9_MARK,		PORT85_FN1),
+	PINMUX_DATA(MEMC_AD10_MARK,		PORT86_FN1),
+	PINMUX_DATA(MEMC_AD11_MARK,		PORT87_FN1),
+	PINMUX_DATA(MEMC_AD12_MARK,		PORT88_FN1),
+	PINMUX_DATA(MEMC_AD13_MARK,		PORT89_FN1),
+	PINMUX_DATA(MEMC_AD14_MARK,		PORT90_FN1),
+	PINMUX_DATA(MEMC_AD15_MARK,		PORT91_FN1),
+	PINMUX_DATA(MEMC_CS0_MARK,		PORT92_FN1),
+	PINMUX_DATA(MEMC_BUSCLK_MEMC_A0_MARK,	PORT93_FN1),
+	PINMUX_DATA(MEMC_CS1_MEMC_A1_MARK,	PORT94_FN1),
+	PINMUX_DATA(MEMC_ADV_MEMC_DREQ0_MARK,	PORT95_FN1),
+	PINMUX_DATA(MEMC_WAIT_MEMC_DREQ1_MARK,	PORT96_FN1),
+	PINMUX_DATA(MEMC_NOE_MARK,		PORT97_FN1),
+	PINMUX_DATA(MEMC_NWE_MARK,		PORT98_FN1),
+	PINMUX_DATA(MEMC_INT_MARK,		PORT99_FN1),
+	PINMUX_DATA(VIO_VD_MARK,		PORT100_FN1),
+	PINMUX_DATA(VIO_HD_MARK,		PORT101_FN1),
+	PINMUX_DATA(VIO_D0_MARK,		PORT102_FN1),
+	PINMUX_DATA(VIO_D1_MARK,		PORT103_FN1),
+	PINMUX_DATA(VIO_D2_MARK,		PORT104_FN1),
+	PINMUX_DATA(VIO_D3_MARK,		PORT105_FN1),
+	PINMUX_DATA(VIO_D4_MARK,		PORT106_FN1),
+	PINMUX_DATA(VIO_D5_MARK,		PORT107_FN1),
+	PINMUX_DATA(VIO_D6_MARK,		PORT108_FN1),
+	PINMUX_DATA(VIO_D7_MARK,		PORT109_FN1),
+	PINMUX_DATA(VIO_D8_MARK,		PORT110_FN1),
+	PINMUX_DATA(VIO_D9_MARK,		PORT111_FN1),
+	PINMUX_DATA(VIO_D10_MARK,		PORT112_FN1),
+	PINMUX_DATA(VIO_D11_MARK,		PORT113_FN1),
+	PINMUX_DATA(VIO_D12_MARK,		PORT114_FN1),
+	PINMUX_DATA(VIO_D13_MARK,		PORT115_FN1),
+	PINMUX_DATA(VIO_D14_MARK,		PORT116_FN1),
+	PINMUX_DATA(VIO_D15_MARK,		PORT117_FN1),
+	PINMUX_DATA(VIO_CLK_MARK,		PORT118_FN1),
+	PINMUX_DATA(VIO_FIELD_MARK,		PORT119_FN1),
+	PINMUX_DATA(VIO_CKO_MARK,		PORT120_FN1),
+	PINMUX_DATA(LCDD0_MARK,			PORT121_FN1),
+	PINMUX_DATA(LCDD1_MARK,			PORT122_FN1),
+	PINMUX_DATA(LCDD2_MARK,			PORT123_FN1),
+	PINMUX_DATA(LCDD3_MARK,			PORT124_FN1),
+	PINMUX_DATA(LCDD4_MARK,			PORT125_FN1),
+	PINMUX_DATA(LCDD5_MARK,			PORT126_FN1),
+	PINMUX_DATA(LCDD6_MARK,			PORT127_FN1),
+	PINMUX_DATA(LCDD7_MARK,			PORT128_FN1),
+	PINMUX_DATA(LCDD8_MARK,			PORT129_FN1),
+	PINMUX_DATA(LCDD9_MARK,			PORT130_FN1),
+	PINMUX_DATA(LCDD10_MARK,		PORT131_FN1),
+	PINMUX_DATA(LCDD11_MARK,		PORT132_FN1),
+	PINMUX_DATA(LCDD12_MARK,		PORT133_FN1),
+	PINMUX_DATA(LCDD13_MARK,		PORT134_FN1),
+	PINMUX_DATA(LCDD14_MARK,		PORT135_FN1),
+	PINMUX_DATA(LCDD15_MARK,		PORT136_FN1),
+	PINMUX_DATA(LCDD16_MARK,		PORT137_FN1),
+	PINMUX_DATA(LCDD17_MARK,		PORT138_FN1),
+	PINMUX_DATA(LCDD18_MARK,		PORT139_FN1),
+	PINMUX_DATA(LCDD19_MARK,		PORT140_FN1),
+	PINMUX_DATA(LCDD20_MARK,		PORT141_FN1),
+	PINMUX_DATA(LCDD21_MARK,		PORT142_FN1),
+	PINMUX_DATA(LCDD22_MARK,		PORT143_FN1),
+	PINMUX_DATA(LCDD23_MARK,		PORT144_FN1),
+	PINMUX_DATA(LCDHSYN_MARK,		PORT145_FN1),
+	PINMUX_DATA(LCDVSYN_MARK,		PORT146_FN1),
+	PINMUX_DATA(LCDDCK_MARK,		PORT147_FN1),
+	PINMUX_DATA(LCDRD_MARK,			PORT148_FN1),
+	PINMUX_DATA(LCDDISP_MARK,		PORT149_FN1),
+	PINMUX_DATA(LCDLCLK_MARK,		PORT150_FN1),
+	PINMUX_DATA(LCDDON_MARK,		PORT151_FN1),
+	PINMUX_DATA(SCIFA0_TXD_MARK,		PORT152_FN1),
+	PINMUX_DATA(SCIFA0_RXD_MARK,		PORT153_FN1),
+	PINMUX_DATA(SCIFA1_TXD_MARK,		PORT154_FN1),
+	PINMUX_DATA(SCIFA1_RXD_MARK,		PORT155_FN1),
+	PINMUX_DATA(TS_SPSYNC1_MARK,		PORT156_FN1),
+	PINMUX_DATA(TS_SDAT1_MARK,		PORT157_FN1),
+	PINMUX_DATA(TS_SDEN1_MARK,		PORT158_FN1),
+	PINMUX_DATA(TS_SCK1_MARK,		PORT159_FN1),
+	PINMUX_DATA(TPU0TO0_MARK,		PORT160_FN1),
+	PINMUX_DATA(TPU0TO1_MARK,		PORT161_FN1),
+	PINMUX_DATA(SCIFB_SCK_MARK,		PORT162_FN1),
+	PINMUX_DATA(SCIFB_RTS_MARK,		PORT163_FN1),
+	PINMUX_DATA(SCIFB_CTS_MARK,		PORT164_FN1),
+	PINMUX_DATA(SCIFB_TXD_MARK,		PORT165_FN1),
+	PINMUX_DATA(SCIFB_RXD_MARK,		PORT166_FN1),
+	PINMUX_DATA(VBUS0_0_MARK,		PORT167_FN1),
+	PINMUX_DATA(VBUS0_1_MARK,		PORT168_FN1),
+	PINMUX_DATA(HDMI_HPD_MARK,		PORT169_FN1),
+	PINMUX_DATA(HDMI_CEC_MARK,		PORT170_FN1),
+	PINMUX_DATA(SDHICLK0_MARK,		PORT171_FN1),
+	PINMUX_DATA(SDHICD0_MARK,		PORT172_FN1),
+	PINMUX_DATA(SDHID0_0_MARK,		PORT173_FN1),
+	PINMUX_DATA(SDHID0_1_MARK,		PORT174_FN1),
+	PINMUX_DATA(SDHID0_2_MARK,		PORT175_FN1),
+	PINMUX_DATA(SDHID0_3_MARK,		PORT176_FN1),
+	PINMUX_DATA(SDHICMD0_MARK,		PORT177_FN1),
+	PINMUX_DATA(SDHIWP0_MARK,		PORT178_FN1),
+	PINMUX_DATA(SDHICLK1_MARK,		PORT179_FN1),
+	PINMUX_DATA(SDHID1_0_MARK,		PORT180_FN1),
+	PINMUX_DATA(SDHID1_1_MARK,		PORT181_FN1),
+	PINMUX_DATA(SDHID1_2_MARK,		PORT182_FN1),
+	PINMUX_DATA(SDHID1_3_MARK,		PORT183_FN1),
+	PINMUX_DATA(SDHICMD1_MARK,		PORT184_FN1),
+	PINMUX_DATA(SDHICLK2_MARK,		PORT185_FN1),
+	PINMUX_DATA(SDHID2_0_MARK,		PORT186_FN1),
+	PINMUX_DATA(SDHID2_1_MARK,		PORT187_FN1),
+	PINMUX_DATA(SDHID2_2_MARK,		PORT188_FN1),
+	PINMUX_DATA(SDHID2_3_MARK,		PORT189_FN1),
+	PINMUX_DATA(SDHICMD2_MARK,		PORT190_FN1),
+
+	/* Function 2 */
+	PINMUX_DATA(FSIBCK_MARK,		PORT4_FN2),
+	PINMUX_DATA(SCIFA4_RXD_MARK,		PORT5_FN2),
+	PINMUX_DATA(SCIFA4_TXD_MARK,		PORT6_FN2),
+	PINMUX_DATA(SCIFA5_RXD_MARK,		PORT8_FN2),
+	PINMUX_DATA(FSIASPDIF_11_MARK,		PORT11_FN2),
+	PINMUX_DATA(SCIFA5_TXD_MARK,		PORT12_FN2),
+	PINMUX_DATA(FMSIOLR_MARK,		PORT13_FN2),
+	PINMUX_DATA(FMSIOBT_MARK,		PORT14_FN2),
+	PINMUX_DATA(FSIASPDIF_15_MARK,		PORT15_FN2),
+	PINMUX_DATA(FMSIILR_MARK,		PORT16_FN2),
+	PINMUX_DATA(FMSIIBT_MARK,		PORT17_FN2),
+	PINMUX_DATA(BS_MARK,			PORT19_FN2),
+	PINMUX_DATA(MSIOF0_TSYNC_MARK,		PORT36_FN2),
+	PINMUX_DATA(MSIOF0_TSCK_MARK,		PORT37_FN2),
+	PINMUX_DATA(MSIOF0_RXD_MARK,		PORT38_FN2),
+	PINMUX_DATA(MSIOF0_RSCK_MARK,		PORT39_FN2),
+	PINMUX_DATA(MSIOF0_RSYNC_MARK,		PORT40_FN2),
+	PINMUX_DATA(MSIOF0_MCK0_MARK,		PORT41_FN2),
+	PINMUX_DATA(MSIOF0_MCK1_MARK,		PORT42_FN2),
+	PINMUX_DATA(MSIOF0_SS1_MARK,		PORT43_FN2),
+	PINMUX_DATA(MSIOF0_SS2_MARK,		PORT44_FN2),
+	PINMUX_DATA(MSIOF0_TXD_MARK,		PORT45_FN2),
+	PINMUX_DATA(FMSICK_MARK,		PORT65_FN2),
+	PINMUX_DATA(FCE1_MARK,			PORT66_FN2),
+	PINMUX_DATA(BBIF1_RXD_MARK,		PORT76_FN2),
+	PINMUX_DATA(BBIF1_TSYNC_MARK,		PORT77_FN2),
+	PINMUX_DATA(BBIF1_TSCK_MARK,		PORT78_FN2),
+	PINMUX_DATA(BBIF1_TXD_MARK,		PORT79_FN2),
+	PINMUX_DATA(BBIF1_RSCK_MARK,		PORT80_FN2),
+	PINMUX_DATA(BBIF1_RSYNC_MARK,		PORT81_FN2),
+	PINMUX_DATA(BBIF1_FLOW_MARK,		PORT82_FN2),
+	PINMUX_DATA(BB_RX_FLOW_N_MARK,		PORT83_FN2),
+	PINMUX_DATA(MSIOF1_RSCK_MARK,		PORT84_FN2),
+	PINMUX_DATA(MSIOF1_RSYNC_MARK,		PORT85_FN2),
+	PINMUX_DATA(MSIOF1_MCK0_MARK,		PORT86_FN2),
+	PINMUX_DATA(MSIOF1_MCK1_MARK,		PORT87_FN2),
+	PINMUX_DATA(MSIOF1_TSCK_88_MARK,	PORT88_FN2, MSEL4CR_10_1),
+	PINMUX_DATA(MSIOF1_TSYNC_89_MARK,	PORT89_FN2, MSEL4CR_10_1),
+	PINMUX_DATA(MSIOF1_TXD_90_MARK,		PORT90_FN2, MSEL4CR_10_1),
+	PINMUX_DATA(MSIOF1_RXD_91_MARK,		PORT91_FN2, MSEL4CR_10_1),
+	PINMUX_DATA(MSIOF1_SS1_92_MARK,		PORT92_FN2, MSEL4CR_10_1),
+	PINMUX_DATA(MSIOF1_SS2_93_MARK,		PORT93_FN2, MSEL4CR_10_1),
+	PINMUX_DATA(SCIFA2_CTS1_MARK,		PORT94_FN2),
+	PINMUX_DATA(SCIFA2_RTS1_MARK,		PORT95_FN2),
+	PINMUX_DATA(SCIFA2_TXD1_MARK,		PORT96_FN2),
+	PINMUX_DATA(SCIFA2_RXD1_MARK,		PORT97_FN2),
+	PINMUX_DATA(SCIFA2_SCK1_MARK,		PORT98_FN2),
+	PINMUX_DATA(I2C_SCL2_MARK,		PORT110_FN2),
+	PINMUX_DATA(I2C_SDA2_MARK,		PORT111_FN2),
+	PINMUX_DATA(I2C_SCL3_MARK,		PORT114_FN2, MSEL4CR_16_1),
+	PINMUX_DATA(I2C_SDA3_MARK,		PORT115_FN2, MSEL4CR_16_1),
+	PINMUX_DATA(I2C_SCL4_MARK,		PORT116_FN2, MSEL4CR_17_1),
+	PINMUX_DATA(I2C_SDA4_MARK,		PORT117_FN2, MSEL4CR_17_1),
+	PINMUX_DATA(MSIOF2_RSCK_MARK,		PORT134_FN2),
+	PINMUX_DATA(MSIOF2_RSYNC_MARK,		PORT135_FN2),
+	PINMUX_DATA(MSIOF2_MCK0_MARK,		PORT136_FN2),
+	PINMUX_DATA(MSIOF2_MCK1_MARK,		PORT137_FN2),
+	PINMUX_DATA(MSIOF2_SS1_MARK,		PORT138_FN2),
+	PINMUX_DATA(MSIOF2_SS2_MARK,		PORT139_FN2),
+	PINMUX_DATA(SCIFA3_CTS_140_MARK,	PORT140_FN2, MSEL3CR_9_1),
+	PINMUX_DATA(SCIFA3_RTS_141_MARK,	PORT141_FN2),
+	PINMUX_DATA(SCIFA3_SCK_MARK,		PORT142_FN2),
+	PINMUX_DATA(SCIFA3_TXD_MARK,		PORT143_FN2),
+	PINMUX_DATA(SCIFA3_RXD_MARK,		PORT144_FN2),
+	PINMUX_DATA(MSIOF2_TSYNC_MARK,		PORT148_FN2),
+	PINMUX_DATA(MSIOF2_TSCK_MARK,		PORT149_FN2),
+	PINMUX_DATA(MSIOF2_RXD_MARK,		PORT150_FN2),
+	PINMUX_DATA(MSIOF2_TXD_MARK,		PORT151_FN2),
+	PINMUX_DATA(SCIFA0_SCK_MARK,		PORT156_FN2),
+	PINMUX_DATA(SCIFA0_RTS_MARK,		PORT157_FN2),
+	PINMUX_DATA(SCIFA0_CTS_MARK,		PORT158_FN2),
+	PINMUX_DATA(SCIFA1_SCK_MARK,		PORT159_FN2),
+	PINMUX_DATA(SCIFA1_RTS_MARK,		PORT160_FN2),
+	PINMUX_DATA(SCIFA1_CTS_MARK,		PORT161_FN2),
+
+	/* Function 3 */
+	PINMUX_DATA(VIO_CKO1_MARK,		PORT16_FN3),
+	PINMUX_DATA(VIO_CKO2_MARK,		PORT17_FN3),
+	PINMUX_DATA(IDIN_1_18_MARK,		PORT18_FN3, MSEL4CR_14_1),
+	PINMUX_DATA(MSIOF1_TSCK_39_MARK,	PORT39_FN3, MSEL4CR_10_0),
+	PINMUX_DATA(MSIOF1_TSYNC_40_MARK,	PORT40_FN3, MSEL4CR_10_0),
+	PINMUX_DATA(MSIOF1_TXD_41_MARK,		PORT41_FN3, MSEL4CR_10_0),
+	PINMUX_DATA(MSIOF1_RXD_42_MARK,		PORT42_FN3, MSEL4CR_10_0),
+	PINMUX_DATA(MSIOF1_SS1_43_MARK,		PORT43_FN3, MSEL4CR_10_0),
+	PINMUX_DATA(MSIOF1_SS2_44_MARK,		PORT44_FN3, MSEL4CR_10_0),
+	PINMUX_DATA(MMCD1_0_MARK,		PORT54_FN3, MSEL4CR_15_1),
+	PINMUX_DATA(MMCD1_1_MARK,		PORT55_FN3, MSEL4CR_15_1),
+	PINMUX_DATA(MMCD1_2_MARK,		PORT56_FN3, MSEL4CR_15_1),
+	PINMUX_DATA(MMCD1_3_MARK,		PORT57_FN3, MSEL4CR_15_1),
+	PINMUX_DATA(MMCD1_4_MARK,		PORT58_FN3, MSEL4CR_15_1),
+	PINMUX_DATA(MMCD1_5_MARK,		PORT59_FN3, MSEL4CR_15_1),
+	PINMUX_DATA(MMCD1_6_MARK,		PORT60_FN3, MSEL4CR_15_1),
+	PINMUX_DATA(MMCD1_7_MARK,		PORT61_FN3, MSEL4CR_15_1),
+	PINMUX_DATA(VINT_I_MARK,		PORT65_FN3),
+	PINMUX_DATA(MMCCLK1_MARK,		PORT66_FN3, MSEL4CR_15_1),
+	PINMUX_DATA(MMCCMD1_MARK,		PORT67_FN3, MSEL4CR_15_1),
+	PINMUX_DATA(TPU0TO2_93_MARK,		PORT93_FN3),
+	PINMUX_DATA(TPU0TO2_99_MARK,		PORT99_FN3),
+	PINMUX_DATA(TPU0TO3_MARK,		PORT112_FN3),
+	PINMUX_DATA(IDIN_0_MARK,		PORT113_FN3),
+	PINMUX_DATA(EXTLP_0_MARK,		PORT114_FN3),
+	PINMUX_DATA(OVCN2_0_MARK,		PORT115_FN3),
+	PINMUX_DATA(PWEN_0_MARK,		PORT116_FN3),
+	PINMUX_DATA(OVCN_0_MARK,		PORT117_FN3),
+	PINMUX_DATA(KEYOUT7_MARK,		PORT121_FN3),
+	PINMUX_DATA(KEYOUT6_MARK,		PORT122_FN3),
+	PINMUX_DATA(KEYOUT5_MARK,		PORT123_FN3),
+	PINMUX_DATA(KEYOUT4_MARK,		PORT124_FN3),
+	PINMUX_DATA(KEYOUT3_MARK,		PORT125_FN3),
+	PINMUX_DATA(KEYOUT2_MARK,		PORT126_FN3),
+	PINMUX_DATA(KEYOUT1_MARK,		PORT127_FN3),
+	PINMUX_DATA(KEYOUT0_MARK,		PORT128_FN3),
+	PINMUX_DATA(KEYIN7_MARK,		PORT129_FN3),
+	PINMUX_DATA(KEYIN6_MARK,		PORT130_FN3),
+	PINMUX_DATA(KEYIN5_MARK,		PORT131_FN3),
+	PINMUX_DATA(KEYIN4_MARK,		PORT132_FN3),
+	PINMUX_DATA(KEYIN3_133_MARK,		PORT133_FN3, MSEL4CR_18_0),
+	PINMUX_DATA(KEYIN2_134_MARK,		PORT134_FN3, MSEL4CR_18_0),
+	PINMUX_DATA(KEYIN1_135_MARK,		PORT135_FN3, MSEL4CR_18_0),
+	PINMUX_DATA(KEYIN0_136_MARK,		PORT136_FN3, MSEL4CR_18_0),
+	PINMUX_DATA(TS_SPSYNC2_MARK,		PORT137_FN3),
+	PINMUX_DATA(IROUT_139_MARK,		PORT139_FN3),
+	PINMUX_DATA(IRDA_OUT_MARK,		PORT140_FN3),
+	PINMUX_DATA(IRDA_IN_MARK,		PORT141_FN3),
+	PINMUX_DATA(IRDA_FIRSEL_MARK,		PORT142_FN3),
+	PINMUX_DATA(TS_SDAT2_MARK,		PORT145_FN3),
+	PINMUX_DATA(TS_SDEN2_MARK,		PORT146_FN3),
+	PINMUX_DATA(TS_SCK2_MARK,		PORT147_FN3),
+
+	/* Function 4 */
+	PINMUX_DATA(SCIFA3_CTS_43_MARK,	PORT43_FN4, MSEL3CR_9_0),
+	PINMUX_DATA(SCIFA3_RTS_44_MARK,	PORT44_FN4),
+	PINMUX_DATA(GP_RX_FLAG_MARK,	PORT76_FN4),
+	PINMUX_DATA(GP_RX_DATA_MARK,	PORT77_FN4),
+	PINMUX_DATA(GP_TX_READY_MARK,	PORT78_FN4),
+	PINMUX_DATA(GP_RX_WAKE_MARK,	PORT79_FN4),
+	PINMUX_DATA(MP_TX_FLAG_MARK,	PORT80_FN4),
+	PINMUX_DATA(MP_TX_DATA_MARK,	PORT81_FN4),
+	PINMUX_DATA(MP_RX_READY_MARK,	PORT82_FN4),
+	PINMUX_DATA(MP_TX_WAKE_MARK,	PORT83_FN4),
+	PINMUX_DATA(MMCD0_0_MARK,	PORT84_FN4, MSEL4CR_15_0),
+	PINMUX_DATA(MMCD0_1_MARK,	PORT85_FN4, MSEL4CR_15_0),
+	PINMUX_DATA(MMCD0_2_MARK,	PORT86_FN4, MSEL4CR_15_0),
+	PINMUX_DATA(MMCD0_3_MARK,	PORT87_FN4, MSEL4CR_15_0),
+	PINMUX_DATA(MMCD0_4_MARK,	PORT88_FN4, MSEL4CR_15_0),
+	PINMUX_DATA(MMCD0_5_MARK,	PORT89_FN4, MSEL4CR_15_0),
+	PINMUX_DATA(MMCD0_6_MARK,	PORT90_FN4, MSEL4CR_15_0),
+	PINMUX_DATA(MMCD0_7_MARK,	PORT91_FN4, MSEL4CR_15_0),
+	PINMUX_DATA(MMCCMD0_MARK,	PORT92_FN4, MSEL4CR_15_0),
+	PINMUX_DATA(SIM_RST_MARK,	PORT94_FN4),
+	PINMUX_DATA(SIM_CLK_MARK,	PORT95_FN4),
+	PINMUX_DATA(SIM_D_MARK,		PORT98_FN4),
+	PINMUX_DATA(MMCCLK0_MARK,	PORT99_FN4, MSEL4CR_15_0),
+	PINMUX_DATA(IDIN_1_113_MARK,	PORT113_FN4, MSEL4CR_14_0),
+	PINMUX_DATA(OVCN_1_114_MARK,	PORT114_FN4, MSEL4CR_14_0),
+	PINMUX_DATA(PWEN_1_115_MARK,	PORT115_FN4),
+	PINMUX_DATA(EXTLP_1_MARK,	PORT116_FN4),
+	PINMUX_DATA(OVCN2_1_MARK,	PORT117_FN4),
+	PINMUX_DATA(KEYIN0_121_MARK,	PORT121_FN4, MSEL4CR_18_1),
+	PINMUX_DATA(KEYIN1_122_MARK,	PORT122_FN4, MSEL4CR_18_1),
+	PINMUX_DATA(KEYIN2_123_MARK,	PORT123_FN4, MSEL4CR_18_1),
+	PINMUX_DATA(KEYIN3_124_MARK,	PORT124_FN4, MSEL4CR_18_1),
+	PINMUX_DATA(PWEN_1_138_MARK,	PORT138_FN4),
+	PINMUX_DATA(IROUT_140_MARK,	PORT140_FN4),
+	PINMUX_DATA(LCDCS_MARK,		PORT145_FN4),
+	PINMUX_DATA(LCDWR_MARK,		PORT147_FN4),
+	PINMUX_DATA(LCDRS_MARK,		PORT149_FN4),
+	PINMUX_DATA(OVCN_1_162_MARK,	PORT162_FN4, MSEL4CR_14_1),
+
+	/* Function 5 */
+	PINMUX_DATA(GPI0_MARK,		PORT41_FN5),
+	PINMUX_DATA(GPI1_MARK,		PORT42_FN5),
+	PINMUX_DATA(GPO0_MARK,		PORT43_FN5),
+	PINMUX_DATA(GPO1_MARK,		PORT44_FN5),
+	PINMUX_DATA(I2C_SCL3S_MARK,	PORT137_FN5, MSEL4CR_16_0),
+	PINMUX_DATA(I2C_SDA3S_MARK,	PORT145_FN5, MSEL4CR_16_0),
+	PINMUX_DATA(I2C_SCL4S_MARK,	PORT146_FN5, MSEL4CR_17_0),
+	PINMUX_DATA(I2C_SDA4S_MARK,	PORT147_FN5, MSEL4CR_17_0),
+
+	/* Function select */
+	PINMUX_DATA(LCDC0_SELECT_MARK,	MSEL3CR_6_0),
+	PINMUX_DATA(LCDC1_SELECT_MARK,	MSEL3CR_6_1),
+
+	PINMUX_DATA(TS0_1SELECT_MARK,	MSEL3CR_21_0, MSEL3CR_20_0),
+	PINMUX_DATA(TS0_2SELECT_MARK,	MSEL3CR_21_0, MSEL3CR_20_1),
+	PINMUX_DATA(TS1_1SELECT_MARK,	MSEL3CR_27_0, MSEL3CR_26_0),
+	PINMUX_DATA(TS1_2SELECT_MARK,	MSEL3CR_27_0, MSEL3CR_26_1),
+
+	PINMUX_DATA(SDENC_CPG_MARK,	MSEL4CR_19_0),
+	PINMUX_DATA(SDENC_DV_CLKI_MARK,	MSEL4CR_19_1),
+
+	PINMUX_DATA(MFIv6_MARK,		MSEL4CR_6_0),
+	PINMUX_DATA(MFIv4_MARK,		MSEL4CR_6_1),
+};
+
+#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
+#define GPIO_PORT_ALL() _190(_GPIO_PORT, , unused)
+#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
+
+static struct pinmux_gpio pinmux_gpios[] = {
+
+	/* PORT */
+	GPIO_PORT_ALL(),
+
+	/* IRQ */
+	GPIO_FN(IRQ0_6),	GPIO_FN(IRQ0_162),	GPIO_FN(IRQ1),
+	GPIO_FN(IRQ2_4),	GPIO_FN(IRQ2_5),	GPIO_FN(IRQ3_8),
+	GPIO_FN(IRQ3_16),	GPIO_FN(IRQ4_17),	GPIO_FN(IRQ4_163),
+	GPIO_FN(IRQ5),		GPIO_FN(IRQ6_39),	GPIO_FN(IRQ6_164),
+	GPIO_FN(IRQ7_40),	GPIO_FN(IRQ7_167),	GPIO_FN(IRQ8_41),
+	GPIO_FN(IRQ8_168),	GPIO_FN(IRQ9_42),	GPIO_FN(IRQ9_169),
+	GPIO_FN(IRQ10),		GPIO_FN(IRQ11),		GPIO_FN(IRQ12_80),
+	GPIO_FN(IRQ12_137),	GPIO_FN(IRQ13_81),	GPIO_FN(IRQ13_145),
+	GPIO_FN(IRQ14_82),	GPIO_FN(IRQ14_146),	GPIO_FN(IRQ15_83),
+	GPIO_FN(IRQ15_147),	GPIO_FN(IRQ16_84),	GPIO_FN(IRQ16_170),
+	GPIO_FN(IRQ17),		GPIO_FN(IRQ18),		GPIO_FN(IRQ19),
+	GPIO_FN(IRQ20),		GPIO_FN(IRQ21),		GPIO_FN(IRQ22),
+	GPIO_FN(IRQ23),		GPIO_FN(IRQ24),		GPIO_FN(IRQ25),
+	GPIO_FN(IRQ26_121),	GPIO_FN(IRQ26_172),	GPIO_FN(IRQ27_122),
+	GPIO_FN(IRQ27_180),	GPIO_FN(IRQ28_123),	GPIO_FN(IRQ28_181),
+	GPIO_FN(IRQ29_129),	GPIO_FN(IRQ29_182),	GPIO_FN(IRQ30_130),
+	GPIO_FN(IRQ30_183),	GPIO_FN(IRQ31_138),	GPIO_FN(IRQ31_184),
+
+	/* MSIOF0 */
+	GPIO_FN(MSIOF0_TSYNC),	GPIO_FN(MSIOF0_TSCK),	GPIO_FN(MSIOF0_RXD),
+	GPIO_FN(MSIOF0_RSCK),	GPIO_FN(MSIOF0_RSYNC),	GPIO_FN(MSIOF0_MCK0),
+	GPIO_FN(MSIOF0_MCK1),	GPIO_FN(MSIOF0_SS1),	GPIO_FN(MSIOF0_SS2),
+	GPIO_FN(MSIOF0_TXD),
+
+	/* MSIOF1 */
+	GPIO_FN(MSIOF1_TSCK_39),	GPIO_FN(MSIOF1_TSCK_88),
+	GPIO_FN(MSIOF1_TSYNC_40),	GPIO_FN(MSIOF1_TSYNC_89),
+	GPIO_FN(MSIOF1_TXD_41),		GPIO_FN(MSIOF1_TXD_90),
+	GPIO_FN(MSIOF1_RXD_42),		GPIO_FN(MSIOF1_RXD_91),
+	GPIO_FN(MSIOF1_SS1_43),		GPIO_FN(MSIOF1_SS1_92),
+	GPIO_FN(MSIOF1_SS2_44),		GPIO_FN(MSIOF1_SS2_93),
+	GPIO_FN(MSIOF1_RSCK),		GPIO_FN(MSIOF1_RSYNC),
+	GPIO_FN(MSIOF1_MCK0),		GPIO_FN(MSIOF1_MCK1),
+
+	/* MSIOF2 */
+	GPIO_FN(MSIOF2_RSCK),	GPIO_FN(MSIOF2_RSYNC),	GPIO_FN(MSIOF2_MCK0),
+	GPIO_FN(MSIOF2_MCK1),	GPIO_FN(MSIOF2_SS1),	GPIO_FN(MSIOF2_SS2),
+	GPIO_FN(MSIOF2_TSYNC),	GPIO_FN(MSIOF2_TSCK),	GPIO_FN(MSIOF2_RXD),
+	GPIO_FN(MSIOF2_TXD),
+
+	/* MSIOF3 */
+	GPIO_FN(BBIF1_RXD),	GPIO_FN(BBIF1_TSYNC),	GPIO_FN(BBIF1_TSCK),
+	GPIO_FN(BBIF1_TXD),	GPIO_FN(BBIF1_RSCK),	GPIO_FN(BBIF1_RSYNC),
+	GPIO_FN(BBIF1_FLOW),	GPIO_FN(BB_RX_FLOW_N),
+
+	/* MSIOF4 */
+	GPIO_FN(BBIF2_TSCK1),	GPIO_FN(BBIF2_TSYNC1),
+	GPIO_FN(BBIF2_TXD1),	GPIO_FN(BBIF2_RXD),
+
+	/* FSI */
+	GPIO_FN(FSIACK),	GPIO_FN(FSIBCK),	GPIO_FN(FSIAILR),
+	GPIO_FN(FSIAIBT),	GPIO_FN(FSIAISLD),	GPIO_FN(FSIAOMC),
+	GPIO_FN(FSIAOLR),	GPIO_FN(FSIAOBT),	GPIO_FN(FSIAOSLD),
+	GPIO_FN(FSIASPDIF_11),	GPIO_FN(FSIASPDIF_15),
+
+	/* FMSI */
+	GPIO_FN(FMSOCK),	GPIO_FN(FMSOOLR),	GPIO_FN(FMSIOLR),
+	GPIO_FN(FMSOOBT),	GPIO_FN(FMSIOBT),	GPIO_FN(FMSOSLD),
+	GPIO_FN(FMSOILR),	GPIO_FN(FMSIILR),	GPIO_FN(FMSOIBT),
+	GPIO_FN(FMSIIBT),	GPIO_FN(FMSISLD),	GPIO_FN(FMSICK),
+
+	/* SCIFA0 */
+	GPIO_FN(SCIFA0_TXD),	GPIO_FN(SCIFA0_RXD),	GPIO_FN(SCIFA0_SCK),
+	GPIO_FN(SCIFA0_RTS),	GPIO_FN(SCIFA0_CTS),
+
+	/* SCIFA1 */
+	GPIO_FN(SCIFA1_TXD),	GPIO_FN(SCIFA1_RXD),	GPIO_FN(SCIFA1_SCK),
+	GPIO_FN(SCIFA1_RTS),	GPIO_FN(SCIFA1_CTS),
+
+	/* SCIFA2 */
+	GPIO_FN(SCIFA2_CTS1),	GPIO_FN(SCIFA2_RTS1),	GPIO_FN(SCIFA2_TXD1),
+	GPIO_FN(SCIFA2_RXD1),	GPIO_FN(SCIFA2_SCK1),
+
+	/* SCIFA3 */
+	GPIO_FN(SCIFA3_CTS_43),		GPIO_FN(SCIFA3_CTS_140),
+	GPIO_FN(SCIFA3_RTS_44),		GPIO_FN(SCIFA3_RTS_141),
+	GPIO_FN(SCIFA3_SCK),		GPIO_FN(SCIFA3_TXD),
+	GPIO_FN(SCIFA3_RXD),
+
+	/* SCIFA4 */
+	GPIO_FN(SCIFA4_RXD),	GPIO_FN(SCIFA4_TXD),
+
+	/* SCIFA5 */
+	GPIO_FN(SCIFA5_RXD),	GPIO_FN(SCIFA5_TXD),
+
+	/* SCIFB */
+	GPIO_FN(SCIFB_SCK),	GPIO_FN(SCIFB_RTS),	GPIO_FN(SCIFB_CTS),
+	GPIO_FN(SCIFB_TXD),	GPIO_FN(SCIFB_RXD),
+
+	/* CEU */
+	GPIO_FN(VIO_HD),	GPIO_FN(VIO_CKO1),	GPIO_FN(VIO_CKO2),
+	GPIO_FN(VIO_VD),	GPIO_FN(VIO_CLK),	GPIO_FN(VIO_FIELD),
+	GPIO_FN(VIO_CKO),	GPIO_FN(VIO_D0),	GPIO_FN(VIO_D1),
+	GPIO_FN(VIO_D2),	GPIO_FN(VIO_D3),	GPIO_FN(VIO_D4),
+	GPIO_FN(VIO_D5),	GPIO_FN(VIO_D6),	GPIO_FN(VIO_D7),
+	GPIO_FN(VIO_D8),	GPIO_FN(VIO_D9),	GPIO_FN(VIO_D10),
+	GPIO_FN(VIO_D11),	GPIO_FN(VIO_D12),	GPIO_FN(VIO_D13),
+	GPIO_FN(VIO_D14),	GPIO_FN(VIO_D15),
+
+	/* USB0 */
+	GPIO_FN(IDIN_0),	GPIO_FN(EXTLP_0),	GPIO_FN(OVCN2_0),
+	GPIO_FN(PWEN_0),	GPIO_FN(OVCN_0),	GPIO_FN(VBUS0_0),
+
+	/* USB1 */
+	GPIO_FN(IDIN_1_18),	GPIO_FN(IDIN_1_113),
+	GPIO_FN(OVCN_1_114),	GPIO_FN(OVCN_1_162),
+	GPIO_FN(PWEN_1_115),	GPIO_FN(PWEN_1_138),
+	GPIO_FN(EXTLP_1),	GPIO_FN(OVCN2_1),
+	GPIO_FN(VBUS0_1),
+
+	/* GPIO */
+	GPIO_FN(GPI0),	GPIO_FN(GPI1),	GPIO_FN(GPO0),	GPIO_FN(GPO1),
+
+	/* BSC */
+	GPIO_FN(BS),	GPIO_FN(WE1),	GPIO_FN(CKO),
+	GPIO_FN(WAIT),	GPIO_FN(RDWR),
+
+	GPIO_FN(A0),	GPIO_FN(A1),	GPIO_FN(A2),
+	GPIO_FN(A3),	GPIO_FN(A6),	GPIO_FN(A7),
+	GPIO_FN(A8),	GPIO_FN(A9),	GPIO_FN(A10),
+	GPIO_FN(A11),	GPIO_FN(A12),	GPIO_FN(A13),
+	GPIO_FN(A14),	GPIO_FN(A15),	GPIO_FN(A16),
+	GPIO_FN(A17),	GPIO_FN(A18),	GPIO_FN(A19),
+	GPIO_FN(A20),	GPIO_FN(A21),	GPIO_FN(A22),
+	GPIO_FN(A23),	GPIO_FN(A24),	GPIO_FN(A25),
+	GPIO_FN(A26),
+
+	GPIO_FN(CS0),	GPIO_FN(CS2),	GPIO_FN(CS4),
+	GPIO_FN(CS5A),	GPIO_FN(CS5B),	GPIO_FN(CS6A),
+
+	/* BSC/FLCTL */
+	GPIO_FN(RD_FSC),	GPIO_FN(WE0_FWE),	GPIO_FN(A4_FOE),
+	GPIO_FN(A5_FCDE),	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),
+
+	/* MMCIF(1) */
+	GPIO_FN(MMCD0_0),	GPIO_FN(MMCD0_1),	GPIO_FN(MMCD0_2),
+	GPIO_FN(MMCD0_3),	GPIO_FN(MMCD0_4),	GPIO_FN(MMCD0_5),
+	GPIO_FN(MMCD0_6),	GPIO_FN(MMCD0_7),	GPIO_FN(MMCCMD0),
+	GPIO_FN(MMCCLK0),
+
+	/* MMCIF(2) */
+	GPIO_FN(MMCD1_0),	GPIO_FN(MMCD1_1),	GPIO_FN(MMCD1_2),
+	GPIO_FN(MMCD1_3),	GPIO_FN(MMCD1_4),	GPIO_FN(MMCD1_5),
+	GPIO_FN(MMCD1_6),	GPIO_FN(MMCD1_7),	GPIO_FN(MMCCLK1),
+	GPIO_FN(MMCCMD1),
+
+	/* SPU2 */
+	GPIO_FN(VINT_I),
+
+	/* FLCTL */
+	GPIO_FN(FCE1),	GPIO_FN(FCE0),	GPIO_FN(FRB),
+
+	/* HSI */
+	GPIO_FN(GP_RX_FLAG),	GPIO_FN(GP_RX_DATA),	GPIO_FN(GP_TX_READY),
+	GPIO_FN(GP_RX_WAKE),	GPIO_FN(MP_TX_FLAG),	GPIO_FN(MP_TX_DATA),
+	GPIO_FN(MP_RX_READY),	GPIO_FN(MP_TX_WAKE),
+
+	/* MFI */
+	GPIO_FN(MFIv6),
+	GPIO_FN(MFIv4),
+
+	GPIO_FN(MEMC_BUSCLK_MEMC_A0),	GPIO_FN(MEMC_ADV_MEMC_DREQ0),
+	GPIO_FN(MEMC_WAIT_MEMC_DREQ1),	GPIO_FN(MEMC_CS1_MEMC_A1),
+	GPIO_FN(MEMC_CS0),	GPIO_FN(MEMC_NOE),
+	GPIO_FN(MEMC_NWE),	GPIO_FN(MEMC_INT),
+
+	GPIO_FN(MEMC_AD0),	GPIO_FN(MEMC_AD1),	GPIO_FN(MEMC_AD2),
+	GPIO_FN(MEMC_AD3),	GPIO_FN(MEMC_AD4),	GPIO_FN(MEMC_AD5),
+	GPIO_FN(MEMC_AD6),	GPIO_FN(MEMC_AD7),	GPIO_FN(MEMC_AD8),
+	GPIO_FN(MEMC_AD9),	GPIO_FN(MEMC_AD10),	GPIO_FN(MEMC_AD11),
+	GPIO_FN(MEMC_AD12),	GPIO_FN(MEMC_AD13),	GPIO_FN(MEMC_AD14),
+	GPIO_FN(MEMC_AD15),
+
+	/* SIM */
+	GPIO_FN(SIM_RST),	GPIO_FN(SIM_CLK),	GPIO_FN(SIM_D),
+
+	/* TPU */
+	GPIO_FN(TPU0TO0),	GPIO_FN(TPU0TO1),	GPIO_FN(TPU0TO2_93),
+	GPIO_FN(TPU0TO2_99),	GPIO_FN(TPU0TO3),
+
+	/* I2C2 */
+	GPIO_FN(I2C_SCL2),	GPIO_FN(I2C_SDA2),
+
+	/* I2C3(1) */
+	GPIO_FN(I2C_SCL3),	GPIO_FN(I2C_SDA3),
+
+	/* I2C3(2) */
+	GPIO_FN(I2C_SCL3S),	GPIO_FN(I2C_SDA3S),
+
+	/* I2C4(2) */
+	GPIO_FN(I2C_SCL4),	GPIO_FN(I2C_SDA4),
+
+	/* I2C4(2) */
+	GPIO_FN(I2C_SCL4S),	GPIO_FN(I2C_SDA4S),
+
+	/* KEYSC */
+	GPIO_FN(KEYOUT0),	GPIO_FN(KEYIN0_121),	GPIO_FN(KEYIN0_136),
+	GPIO_FN(KEYOUT1),	GPIO_FN(KEYIN1_122),	GPIO_FN(KEYIN1_135),
+	GPIO_FN(KEYOUT2),	GPIO_FN(KEYIN2_123),	GPIO_FN(KEYIN2_134),
+	GPIO_FN(KEYOUT3),	GPIO_FN(KEYIN3_124),	GPIO_FN(KEYIN3_133),
+	GPIO_FN(KEYOUT4),	GPIO_FN(KEYIN4),	GPIO_FN(KEYOUT5),
+	GPIO_FN(KEYIN5),	GPIO_FN(KEYOUT6),	GPIO_FN(KEYIN6),
+	GPIO_FN(KEYOUT7),	GPIO_FN(KEYIN7),
+
+	/* LCDC */
+	GPIO_FN(LCDHSYN),	GPIO_FN(LCDCS),	GPIO_FN(LCDVSYN),
+	GPIO_FN(LCDDCK),	GPIO_FN(LCDWR),	GPIO_FN(LCDRD),
+	GPIO_FN(LCDDISP),	GPIO_FN(LCDRS),	GPIO_FN(LCDLCLK),
+	GPIO_FN(LCDDON),
+
+	GPIO_FN(LCDD0),		GPIO_FN(LCDD1),		GPIO_FN(LCDD2),
+	GPIO_FN(LCDD3),		GPIO_FN(LCDD4),		GPIO_FN(LCDD5),
+	GPIO_FN(LCDD6),		GPIO_FN(LCDD7),		GPIO_FN(LCDD8),
+	GPIO_FN(LCDD9),		GPIO_FN(LCDD10),	GPIO_FN(LCDD11),
+	GPIO_FN(LCDD12),	GPIO_FN(LCDD13),	GPIO_FN(LCDD14),
+	GPIO_FN(LCDD15),	GPIO_FN(LCDD16),	GPIO_FN(LCDD17),
+	GPIO_FN(LCDD18),	GPIO_FN(LCDD19),	GPIO_FN(LCDD20),
+	GPIO_FN(LCDD21),	GPIO_FN(LCDD22),	GPIO_FN(LCDD23),
+
+	/* IRDA */
+	GPIO_FN(IRDA_OUT),	GPIO_FN(IRDA_IN),	GPIO_FN(IRDA_FIRSEL),
+	GPIO_FN(IROUT_139),	GPIO_FN(IROUT_140),
+
+	/* TSIF1 */
+	GPIO_FN(TS0_1SELECT),
+	GPIO_FN(TS0_2SELECT),
+	GPIO_FN(TS1_1SELECT),
+	GPIO_FN(TS1_2SELECT),
+
+	GPIO_FN(TS_SPSYNC1),	GPIO_FN(TS_SDAT1),
+	GPIO_FN(TS_SDEN1),	GPIO_FN(TS_SCK1),
+
+	/* TSIF2 */
+	GPIO_FN(TS_SPSYNC2),	GPIO_FN(TS_SDAT2),
+	GPIO_FN(TS_SDEN2),	GPIO_FN(TS_SCK2),
+
+	/* HDMI */
+	GPIO_FN(HDMI_HPD),	GPIO_FN(HDMI_CEC),
+
+	/* SDHI0 */
+	GPIO_FN(SDHICLK0),	GPIO_FN(SDHICD0),	GPIO_FN(SDHICMD0),
+	GPIO_FN(SDHIWP0),	GPIO_FN(SDHID0_0),	GPIO_FN(SDHID0_1),
+	GPIO_FN(SDHID0_2),	GPIO_FN(SDHID0_3),
+
+	/* SDHI1 */
+	GPIO_FN(SDHICLK1),	GPIO_FN(SDHICMD1),	GPIO_FN(SDHID1_0),
+	GPIO_FN(SDHID1_1),	GPIO_FN(SDHID1_2),	GPIO_FN(SDHID1_3),
+
+	/* SDHI2 */
+	GPIO_FN(SDHICLK2),	GPIO_FN(SDHICMD2),	GPIO_FN(SDHID2_0),
+	GPIO_FN(SDHID2_1),	GPIO_FN(SDHID2_2),	GPIO_FN(SDHID2_3),
+
+	/* SDENC */
+	GPIO_FN(SDENC_CPG),
+	GPIO_FN(SDENC_DV_CLKI),
+};
+
+/* helper for top 4 bits in PORTnCR */
+#define PCRH(in, in_pd, in_pu, out)		\
+	0, (out), (in), 0,			\
+	0, 0, 0, 0,				\
+	0, 0, (in_pd), 0,			\
+	0, 0, (in_pu), 0
+
+#define PORTCR(nr, reg)						\
+	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {		\
+		PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,		\
+		     PORT##nr##_IN_PU, PORT##nr##_OUT),		\
+		PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2,	\
+		PORT##nr##_FN3,	PORT##nr##_FN4, PORT##nr##_FN5,	\
+		PORT##nr##_FN6, PORT##nr##_FN7 }		\
+	}
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+	PORTCR(0,	0xE6051000), /* PORT0CR */
+	PORTCR(1,	0xE6051001), /* PORT1CR */
+	PORTCR(2,	0xE6051002), /* PORT2CR */
+	PORTCR(3,	0xE6051003), /* PORT3CR */
+	PORTCR(4,	0xE6051004), /* PORT4CR */
+	PORTCR(5,	0xE6051005), /* PORT5CR */
+	PORTCR(6,	0xE6051006), /* PORT6CR */
+	PORTCR(7,	0xE6051007), /* PORT7CR */
+	PORTCR(8,	0xE6051008), /* PORT8CR */
+	PORTCR(9,	0xE6051009), /* PORT9CR */
+	PORTCR(10,	0xE605100A), /* PORT10CR */
+	PORTCR(11,	0xE605100B), /* PORT11CR */
+	PORTCR(12,	0xE605100C), /* PORT12CR */
+	PORTCR(13,	0xE605100D), /* PORT13CR */
+	PORTCR(14,	0xE605100E), /* PORT14CR */
+	PORTCR(15,	0xE605100F), /* PORT15CR */
+	PORTCR(16,	0xE6051010), /* PORT16CR */
+	PORTCR(17,	0xE6051011), /* PORT17CR */
+	PORTCR(18,	0xE6051012), /* PORT18CR */
+	PORTCR(19,	0xE6051013), /* PORT19CR */
+	PORTCR(20,	0xE6051014), /* PORT20CR */
+	PORTCR(21,	0xE6051015), /* PORT21CR */
+	PORTCR(22,	0xE6051016), /* PORT22CR */
+	PORTCR(23,	0xE6051017), /* PORT23CR */
+	PORTCR(24,	0xE6051018), /* PORT24CR */
+	PORTCR(25,	0xE6051019), /* PORT25CR */
+	PORTCR(26,	0xE605101A), /* PORT26CR */
+	PORTCR(27,	0xE605101B), /* PORT27CR */
+	PORTCR(28,	0xE605101C), /* PORT28CR */
+	PORTCR(29,	0xE605101D), /* PORT29CR */
+	PORTCR(30,	0xE605101E), /* PORT30CR */
+	PORTCR(31,	0xE605101F), /* 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,	0xE605202E), /* PORT46CR */
+	PORTCR(47,	0xE605202F), /* PORT47CR */
+	PORTCR(48,	0xE6052030), /* PORT48CR */
+	PORTCR(49,	0xE6052031), /* PORT49CR */
+	PORTCR(50,	0xE6052032), /* PORT50CR */
+	PORTCR(51,	0xE6052033), /* PORT51CR */
+	PORTCR(52,	0xE6052034), /* PORT52CR */
+	PORTCR(53,	0xE6052035), /* PORT53CR */
+	PORTCR(54,	0xE6052036), /* PORT54CR */
+	PORTCR(55,	0xE6052037), /* PORT55CR */
+	PORTCR(56,	0xE6052038), /* PORT56CR */
+	PORTCR(57,	0xE6052039), /* PORT57CR */
+	PORTCR(58,	0xE605203A), /* PORT58CR */
+	PORTCR(59,	0xE605203B), /* PORT59CR */
+	PORTCR(60,	0xE605203C), /* PORT60CR */
+	PORTCR(61,	0xE605203D), /* PORT61CR */
+	PORTCR(62,	0xE605203E), /* PORT62CR */
+	PORTCR(63,	0xE605203F), /* PORT63CR */
+	PORTCR(64,	0xE6052040), /* PORT64CR */
+	PORTCR(65,	0xE6052041), /* PORT65CR */
+	PORTCR(66,	0xE6052042), /* PORT66CR */
+	PORTCR(67,	0xE6052043), /* PORT67CR */
+	PORTCR(68,	0xE6052044), /* PORT68CR */
+	PORTCR(69,	0xE6052045), /* PORT69CR */
+	PORTCR(70,	0xE6052046), /* PORT70CR */
+	PORTCR(71,	0xE6052047), /* PORT71CR */
+	PORTCR(72,	0xE6052048), /* PORT72CR */
+	PORTCR(73,	0xE6052049), /* PORT73CR */
+	PORTCR(74,	0xE605204A), /* PORT74CR */
+	PORTCR(75,	0xE605204B), /* PORT75CR */
+	PORTCR(76,	0xE605004C), /* PORT76CR */
+	PORTCR(77,	0xE605004D), /* PORT77CR */
+	PORTCR(78,	0xE605004E), /* PORT78CR */
+	PORTCR(79,	0xE605004F), /* PORT79CR */
+	PORTCR(80,	0xE6050050), /* PORT80CR */
+	PORTCR(81,	0xE6050051), /* PORT81CR */
+	PORTCR(82,	0xE6050052), /* PORT82CR */
+	PORTCR(83,	0xE6050053), /* PORT83CR */
+	PORTCR(84,	0xE6050054), /* PORT84CR */
+	PORTCR(85,	0xE6050055), /* PORT85CR */
+	PORTCR(86,	0xE6050056), /* PORT86CR */
+	PORTCR(87,	0xE6050057), /* PORT87CR */
+	PORTCR(88,	0xE6050058), /* PORT88CR */
+	PORTCR(89,	0xE6050059), /* PORT89CR */
+	PORTCR(90,	0xE605005A), /* PORT90CR */
+	PORTCR(91,	0xE605005B), /* PORT91CR */
+	PORTCR(92,	0xE605005C), /* PORT92CR */
+	PORTCR(93,	0xE605005D), /* PORT93CR */
+	PORTCR(94,	0xE605005E), /* PORT94CR */
+	PORTCR(95,	0xE605005F), /* PORT95CR */
+	PORTCR(96,	0xE6050060), /* PORT96CR */
+	PORTCR(97,	0xE6050061), /* PORT97CR */
+	PORTCR(98,	0xE6050062), /* PORT98CR */
+	PORTCR(99,	0xE6050063), /* PORT99CR */
+	PORTCR(100,	0xE6053064), /* PORT100CR */
+	PORTCR(101,	0xE6053065), /* PORT101CR */
+	PORTCR(102,	0xE6053066), /* PORT102CR */
+	PORTCR(103,	0xE6053067), /* PORT103CR */
+	PORTCR(104,	0xE6053068), /* PORT104CR */
+	PORTCR(105,	0xE6053069), /* PORT105CR */
+	PORTCR(106,	0xE605306A), /* PORT106CR */
+	PORTCR(107,	0xE605306B), /* PORT107CR */
+	PORTCR(108,	0xE605306C), /* PORT108CR */
+	PORTCR(109,	0xE605306D), /* PORT109CR */
+	PORTCR(110,	0xE605306E), /* PORT110CR */
+	PORTCR(111,	0xE605306F), /* PORT111CR */
+	PORTCR(112,	0xE6053070), /* PORT112CR */
+	PORTCR(113,	0xE6053071), /* PORT113CR */
+	PORTCR(114,	0xE6053072), /* PORT114CR */
+	PORTCR(115,	0xE6053073), /* PORT115CR */
+	PORTCR(116,	0xE6053074), /* PORT116CR */
+	PORTCR(117,	0xE6053075), /* PORT117CR */
+	PORTCR(118,	0xE6053076), /* PORT118CR */
+	PORTCR(119,	0xE6053077), /* PORT119CR */
+	PORTCR(120,	0xE6053078), /* PORT120CR */
+	PORTCR(121,	0xE6050079), /* PORT121CR */
+	PORTCR(122,	0xE605007A), /* PORT122CR */
+	PORTCR(123,	0xE605007B), /* PORT123CR */
+	PORTCR(124,	0xE605007C), /* PORT124CR */
+	PORTCR(125,	0xE605007D), /* PORT125CR */
+	PORTCR(126,	0xE605007E), /* PORT126CR */
+	PORTCR(127,	0xE605007F), /* PORT127CR */
+	PORTCR(128,	0xE6050080), /* PORT128CR */
+	PORTCR(129,	0xE6050081), /* PORT129CR */
+	PORTCR(130,	0xE6050082), /* PORT130CR */
+	PORTCR(131,	0xE6050083), /* PORT131CR */
+	PORTCR(132,	0xE6050084), /* PORT132CR */
+	PORTCR(133,	0xE6050085), /* PORT133CR */
+	PORTCR(134,	0xE6050086), /* PORT134CR */
+	PORTCR(135,	0xE6050087), /* PORT135CR */
+	PORTCR(136,	0xE6050088), /* PORT136CR */
+	PORTCR(137,	0xE6050089), /* PORT137CR */
+	PORTCR(138,	0xE605008A), /* PORT138CR */
+	PORTCR(139,	0xE605008B), /* PORT139CR */
+	PORTCR(140,	0xE605008C), /* PORT140CR */
+	PORTCR(141,	0xE605008D), /* PORT141CR */
+	PORTCR(142,	0xE605008E), /* PORT142CR */
+	PORTCR(143,	0xE605008F), /* PORT143CR */
+	PORTCR(144,	0xE6050090), /* PORT144CR */
+	PORTCR(145,	0xE6050091), /* PORT145CR */
+	PORTCR(146,	0xE6050092), /* PORT146CR */
+	PORTCR(147,	0xE6050093), /* PORT147CR */
+	PORTCR(148,	0xE6050094), /* PORT148CR */
+	PORTCR(149,	0xE6050095), /* PORT149CR */
+	PORTCR(150,	0xE6050096), /* PORT150CR */
+	PORTCR(151,	0xE6050097), /* PORT151CR */
+	PORTCR(152,	0xE6053098), /* PORT152CR */
+	PORTCR(153,	0xE6053099), /* PORT153CR */
+	PORTCR(154,	0xE605309A), /* PORT154CR */
+	PORTCR(155,	0xE605309B), /* PORT155CR */
+	PORTCR(156,	0xE605009C), /* PORT156CR */
+	PORTCR(157,	0xE605009D), /* PORT157CR */
+	PORTCR(158,	0xE605009E), /* PORT158CR */
+	PORTCR(159,	0xE605009F), /* PORT159CR */
+	PORTCR(160,	0xE60500A0), /* PORT160CR */
+	PORTCR(161,	0xE60500A1), /* PORT161CR */
+	PORTCR(162,	0xE60500A2), /* PORT162CR */
+	PORTCR(163,	0xE60500A3), /* PORT163CR */
+	PORTCR(164,	0xE60500A4), /* PORT164CR */
+	PORTCR(165,	0xE60500A5), /* PORT165CR */
+	PORTCR(166,	0xE60500A6), /* PORT166CR */
+	PORTCR(167,	0xE60520A7), /* PORT167CR */
+	PORTCR(168,	0xE60520A8), /* PORT168CR */
+	PORTCR(169,	0xE60520A9), /* PORT169CR */
+	PORTCR(170,	0xE60520AA), /* PORT170CR */
+	PORTCR(171,	0xE60520AB), /* PORT171CR */
+	PORTCR(172,	0xE60520AC), /* PORT172CR */
+	PORTCR(173,	0xE60520AD), /* PORT173CR */
+	PORTCR(174,	0xE60520AE), /* PORT174CR */
+	PORTCR(175,	0xE60520AF), /* PORT175CR */
+	PORTCR(176,	0xE60520B0), /* PORT176CR */
+	PORTCR(177,	0xE60520B1), /* PORT177CR */
+	PORTCR(178,	0xE60520B2), /* PORT178CR */
+	PORTCR(179,	0xE60520B3), /* PORT179CR */
+	PORTCR(180,	0xE60520B4), /* PORT180CR */
+	PORTCR(181,	0xE60520B5), /* PORT181CR */
+	PORTCR(182,	0xE60520B6), /* PORT182CR */
+	PORTCR(183,	0xE60520B7), /* PORT183CR */
+	PORTCR(184,	0xE60520B8), /* PORT184CR */
+	PORTCR(185,	0xE60520B9), /* PORT185CR */
+	PORTCR(186,	0xE60520BA), /* PORT186CR */
+	PORTCR(187,	0xE60520BB), /* PORT187CR */
+	PORTCR(188,	0xE60520BC), /* PORT188CR */
+	PORTCR(189,	0xE60520BD), /* PORT189CR */
+	PORTCR(190,	0xE60520BE), /* PORT190CR */
+
+	{ PINMUX_CFG_REG("MSEL1CR", 0xE605800C, 32, 1) {
+			MSEL1CR_31_0,	MSEL1CR_31_1,
+			MSEL1CR_30_0,	MSEL1CR_30_1,
+			MSEL1CR_29_0,	MSEL1CR_29_1,
+			MSEL1CR_28_0,	MSEL1CR_28_1,
+			MSEL1CR_27_0,	MSEL1CR_27_1,
+			MSEL1CR_26_0,	MSEL1CR_26_1,
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+			0, 0, 0, 0, 0, 0, 0, 0,
+			MSEL1CR_16_0,	MSEL1CR_16_1,
+			MSEL1CR_15_0,	MSEL1CR_15_1,
+			MSEL1CR_14_0,	MSEL1CR_14_1,
+			MSEL1CR_13_0,	MSEL1CR_13_1,
+			MSEL1CR_12_0,	MSEL1CR_12_1,
+			0, 0, 0, 0,
+			MSEL1CR_9_0,	MSEL1CR_9_1,
+			MSEL1CR_8_0,	MSEL1CR_8_1,
+			MSEL1CR_7_0,	MSEL1CR_7_1,
+			MSEL1CR_6_0,	MSEL1CR_6_1,
+			0, 0,
+			MSEL1CR_4_0,	MSEL1CR_4_1,
+			MSEL1CR_3_0,	MSEL1CR_3_1,
+			MSEL1CR_2_0,	MSEL1CR_2_1,
+			0, 0,
+			MSEL1CR_0_0,	MSEL1CR_0_1,
+		}
+	},
+	{ PINMUX_CFG_REG("MSEL3CR", 0xE6058020, 32, 1) {
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			MSEL3CR_27_0,	MSEL3CR_27_1,
+			MSEL3CR_26_0,	MSEL3CR_26_1,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			MSEL3CR_21_0,	MSEL3CR_21_1,
+			MSEL3CR_20_0,	MSEL3CR_20_1,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			MSEL3CR_15_0,	MSEL3CR_15_1,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0,
+			MSEL3CR_9_0,	MSEL3CR_9_1,
+			0, 0, 0, 0,
+			MSEL3CR_6_0,	MSEL3CR_6_1,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			}
+	},
+	{ PINMUX_CFG_REG("MSEL4CR", 0xE6058024, 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,
+			MSEL4CR_19_0,	MSEL4CR_19_1,
+			MSEL4CR_18_0,	MSEL4CR_18_1,
+			MSEL4CR_17_0,	MSEL4CR_17_1,
+			MSEL4CR_16_0,	MSEL4CR_16_1,
+			MSEL4CR_15_0,	MSEL4CR_15_1,
+			MSEL4CR_14_0,	MSEL4CR_14_1,
+			0, 0, 0, 0,
+			0, 0,
+			MSEL4CR_10_0,	MSEL4CR_10_1,
+			0, 0, 0, 0,
+			0, 0,
+			MSEL4CR_6_0,	MSEL4CR_6_1,
+			0, 0,
+			MSEL4CR_4_0,	MSEL4CR_4_1,
+			0, 0, 0, 0,
+			MSEL4CR_1_0,	MSEL4CR_1_1,
+			0, 0,
+		}
+	},
+	{ },
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+	{ PINMUX_DATA_REG("PORTL095_064DR", 0xE6054008, 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,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTL127_096DR", 0xE605400C, 32) {
+			PORT127_DATA, PORT126_DATA, PORT125_DATA, PORT124_DATA,
+			PORT123_DATA, PORT122_DATA, PORT121_DATA, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			PORT99_DATA,  PORT98_DATA,  PORT97_DATA,  PORT96_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTL159_128DR", 0xE6054010, 32) {
+			PORT159_DATA, PORT158_DATA, PORT157_DATA, PORT156_DATA,
+			0, 0, 0, 0,
+			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("PORTL191_160DR", 0xE6054014, 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,	      PORT166_DATA, PORT165_DATA, PORT164_DATA,
+			PORT163_DATA, PORT162_DATA, PORT161_DATA, PORT160_DATA,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTD031_000DR", 0xE6055000, 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", 0xE6055004, 32) {
+			0, 0, 0, 0, 0, 0, 0, 0,
+			0, 0, 0, 0, 0, 0, 0, 0,
+			0,           0,           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("PORTR063_032DR", 0xE6056004, 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, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTR095_064DR", 0xE6056008, 32) {
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			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("PORTR191_160DR", 0xE6056014, 32) {
+			0,	      PORT190_DATA, PORT189_DATA, PORT188_DATA,
+			PORT187_DATA, PORT186_DATA, PORT185_DATA, PORT184_DATA,
+			PORT183_DATA, PORT182_DATA, PORT181_DATA, PORT180_DATA,
+			PORT179_DATA, PORT178_DATA, PORT177_DATA, PORT176_DATA,
+			PORT175_DATA, PORT174_DATA, PORT173_DATA, PORT172_DATA,
+			PORT171_DATA, PORT170_DATA, PORT169_DATA, PORT168_DATA,
+			PORT167_DATA, 0, 0, 0,
+			0, 0, 0, 0,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTU127_096DR", 0xE605700C, 32) {
+			0, 0, 0, 0,
+			0, 0, 0, PORT120_DATA,
+			PORT119_DATA, 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,
+			0, 0, 0, 0,
+		}
+	},
+	{ PINMUX_DATA_REG("PORTU159_128DR", 0xE6057010, 32) {
+			0, 0, 0, 0,
+			PORT155_DATA, PORT154_DATA, PORT153_DATA, PORT152_DATA,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+		}
+	},
+	{ },
+};
+
+static struct pinmux_info sh7372_pinmux_info = {
+	.name = "sh7372_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_SDENC_DV_CLKI,
+
+	.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 sh7372_pinmux_init(void)
+{
+	register_pinmux(&sh7372_pinmux_info);
+}
diff --git a/arch/arm/mach-shmobile/pfc-sh7377.c b/arch/arm/mach-shmobile/pfc-sh7377.c
new file mode 100644
index 0000000..613e684
--- /dev/null
+++ b/arch/arm/mach-shmobile/pfc-sh7377.c
@@ -0,0 +1,1767 @@
+/*
+ * sh7377 processor support - PFC hardware block
+ *
+ * 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/sh7377.h>
+
+#define _1(fn, pfx, sfx) fn(pfx, sfx)
+
+#define _10(fn, pfx, sfx)				\
+	_1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),	\
+	_1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),	\
+	_1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),	\
+	_1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),	\
+	_1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
+
+#define _90(fn, pfx, sfx)				\
+	_10(fn, pfx##1, sfx), _10(fn, pfx##2, sfx),	\
+	_10(fn, pfx##3, sfx), _10(fn, pfx##4, sfx),	\
+	_10(fn, pfx##5, sfx), _10(fn, pfx##6, sfx),	\
+	_10(fn, pfx##7, sfx), _10(fn, pfx##8, sfx),	\
+	_10(fn, pfx##9, sfx)
+
+#define _265(fn, pfx, sfx)				\
+	_10(fn, pfx, sfx), _90(fn, pfx, sfx),		\
+	_10(fn, pfx##10, sfx),				\
+	_1(fn, pfx##110, sfx), _1(fn, pfx##111, sfx),	\
+	_1(fn, pfx##112, sfx), _1(fn, pfx##113, sfx),	\
+	_1(fn, pfx##114, sfx), _1(fn, pfx##115, sfx),	\
+	_1(fn, pfx##116, sfx), _1(fn, pfx##117, sfx),	\
+	_1(fn, pfx##118, sfx),				\
+	_1(fn, pfx##128, sfx), _1(fn, pfx##129, sfx),	\
+	_10(fn, pfx##13, sfx), _10(fn, pfx##14, sfx),	\
+	_10(fn, pfx##15, sfx),				\
+	_1(fn, pfx##160, sfx), _1(fn, pfx##161, sfx),	\
+	_1(fn, pfx##162, sfx), _1(fn, pfx##163, sfx),	\
+	_1(fn, pfx##164, sfx),				\
+	_1(fn, pfx##192, sfx), _1(fn, pfx##193, sfx),	\
+	_1(fn, pfx##194, sfx), _1(fn, pfx##195, sfx),	\
+	_1(fn, pfx##196, sfx), _1(fn, pfx##197, sfx),	\
+	_1(fn, pfx##198, sfx), _1(fn, pfx##199, sfx),	\
+	_10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),	\
+	_10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),	\
+	_10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),	\
+	_1(fn, pfx##260, sfx), _1(fn, pfx##261, sfx),	\
+	_1(fn, pfx##262, sfx), _1(fn, pfx##263, sfx),	\
+	_1(fn, pfx##264, sfx)
+
+#define _PORT(pfx, sfx) pfx##_##sfx
+#define PORT_265(str) _265(_PORT, PORT, str)
+
+enum {
+	PINMUX_RESERVED = 0,
+
+	PINMUX_DATA_BEGIN,
+	PORT_265(DATA), /* PORT0_DATA -> PORT264_DATA */
+	PINMUX_DATA_END,
+
+	PINMUX_INPUT_BEGIN,
+	PORT_265(IN), /* PORT0_IN -> PORT264_IN */
+	PINMUX_INPUT_END,
+
+	PINMUX_INPUT_PULLUP_BEGIN,
+	PORT_265(IN_PU), /* PORT0_IN_PU -> PORT264_IN_PU */
+	PINMUX_INPUT_PULLUP_END,
+
+	PINMUX_INPUT_PULLDOWN_BEGIN,
+	PORT_265(IN_PD), /* PORT0_IN_PD -> PORT264_IN_PD */
+	PINMUX_INPUT_PULLDOWN_END,
+
+	PINMUX_OUTPUT_BEGIN,
+	PORT_265(OUT), /* PORT0_OUT -> PORT264_OUT */
+	PINMUX_OUTPUT_END,
+
+	PINMUX_FUNCTION_BEGIN,
+	PORT_265(FN_IN), /* PORT0_FN_IN -> PORT264_FN_IN */
+	PORT_265(FN_OUT), /* PORT0_FN_OUT -> PORT264_FN_OUT */
+	PORT_265(FN0), /* PORT0_FN0 -> PORT264_FN0 */
+	PORT_265(FN1), /* PORT0_FN1 -> PORT264_FN1 */
+	PORT_265(FN2), /* PORT0_FN2 -> PORT264_FN2 */
+	PORT_265(FN3), /* PORT0_FN3 -> PORT264_FN3 */
+	PORT_265(FN4), /* PORT0_FN4 -> PORT264_FN4 */
+	PORT_265(FN5), /* PORT0_FN5 -> PORT264_FN5 */
+	PORT_265(FN6), /* PORT0_FN6 -> PORT264_FN6 */
+	PORT_265(FN7), /* PORT0_FN7 -> PORT264_FN7 */
+
+	MSELBCR_MSEL17_1, MSELBCR_MSEL17_0,
+	MSELBCR_MSEL16_1, MSELBCR_MSEL16_0,
+	PINMUX_FUNCTION_END,
+
+	PINMUX_MARK_BEGIN,
+	/* Special Pull-up / Pull-down Functions */
+	PORT66_KEYIN0_PU_MARK, PORT67_KEYIN1_PU_MARK,
+	PORT68_KEYIN2_PU_MARK, PORT69_KEYIN3_PU_MARK,
+	PORT70_KEYIN4_PU_MARK, PORT71_KEYIN5_PU_MARK,
+	PORT72_KEYIN6_PU_MARK,
+
+	/* 55-1 */
+	VBUS_0_MARK,
+	CPORT0_MARK,
+	CPORT1_MARK,
+	CPORT2_MARK,
+	CPORT3_MARK,
+	CPORT4_MARK,
+	CPORT5_MARK,
+	CPORT6_MARK,
+	CPORT7_MARK,
+	CPORT8_MARK,
+	CPORT9_MARK,
+	CPORT10_MARK,
+	CPORT11_MARK, SIN2_MARK,
+	CPORT12_MARK, XCTS2_MARK,
+	CPORT13_MARK, RFSPO4_MARK,
+	CPORT14_MARK, RFSPO5_MARK,
+	CPORT15_MARK, SCIFA0_SCK_MARK, GPS_AGC2_MARK,
+	CPORT16_MARK, SCIFA0_TXD_MARK, GPS_AGC3_MARK,
+	CPORT17_IC_OE_MARK, SOUT2_MARK,
+	CPORT18_MARK, XRTS2_MARK, PORT19_VIO_CKO2_MARK,
+	CPORT19_MPORT1_MARK,
+	CPORT20_MARK, RFSPO6_MARK,
+	CPORT21_MARK, STATUS0_MARK,
+	CPORT22_MARK, STATUS1_MARK,
+	CPORT23_MARK, STATUS2_MARK, RFSPO7_MARK,
+	B_SYNLD1_MARK,
+	B_SYNLD2_MARK, SYSENMSK_MARK,
+	XMAINPS_MARK,
+	XDIVPS_MARK,
+	XIDRST_MARK,
+	IDCLK_MARK, IC_DP_MARK,
+	IDIO_MARK, IC_DM_MARK,
+	SOUT1_MARK, SCIFA4_TXD_MARK, M02_BERDAT_MARK,
+	SIN1_MARK, SCIFA4_RXD_MARK, XWUP_MARK,
+	XRTS1_MARK, SCIFA4_RTS_MARK, M03_BERCLK_MARK,
+	XCTS1_MARK, SCIFA4_CTS_MARK,
+	PCMCLKO_MARK,
+	SYNC8KO_MARK,
+
+	/* 55-2 */
+	DNPCM_A_MARK,
+	UPPCM_A_MARK,
+	VACK_MARK,
+	XTALB1L_MARK,
+	GPS_AGC1_MARK, SCIFA0_RTS_MARK,
+	GPS_AGC4_MARK, SCIFA0_RXD_MARK,
+	GPS_PWRDOWN_MARK, SCIFA0_CTS_MARK,
+	GPS_IM_MARK,
+	GPS_IS_MARK,
+	GPS_QM_MARK,
+	GPS_QS_MARK,
+	FMSOCK_MARK, PORT49_IRDA_OUT_MARK, PORT49_IROUT_MARK,
+	FMSOOLR_MARK, BBIF2_TSYNC2_MARK, TPU2TO2_MARK, IPORT3_MARK,
+	FMSIOLR_MARK,
+	FMSOOBT_MARK, BBIF2_TSCK2_MARK, TPU2TO3_MARK, OPORT1_MARK,
+	FMSIOBT_MARK,
+	FMSOSLD_MARK, BBIF2_TXD2_MARK, OPORT2_MARK,
+	FMSOILR_MARK, PORT53_IRDA_IN_MARK, TPU3TO3_MARK, OPORT3_MARK,
+	FMSIILR_MARK,
+	FMSOIBT_MARK, PORT54_IRDA_FIRSEL_MARK, TPU3TO2_MARK, FMSIIBT_MARK,
+	FMSISLD_MARK, MFG0_OUT1_MARK, TPU0TO0_MARK,
+	A0_EA0_MARK, BS_MARK,
+	A12_EA12_MARK, PORT58_VIO_CKOR_MARK, TPU4TO2_MARK,
+	A13_EA13_MARK, PORT59_IROUT_MARK, MFG0_OUT2_MARK, TPU0TO1_MARK,
+	A14_EA14_MARK, PORT60_KEYOUT5_MARK,
+	A15_EA15_MARK, PORT61_KEYOUT4_MARK,
+	A16_EA16_MARK, PORT62_KEYOUT3_MARK, MSIOF0_SS1_MARK,
+	A17_EA17_MARK, PORT63_KEYOUT2_MARK, MSIOF0_TSYNC_MARK,
+	A18_EA18_MARK, PORT64_KEYOUT1_MARK, MSIOF0_TSCK_MARK,
+	A19_EA19_MARK, PORT65_KEYOUT0_MARK, MSIOF0_TXD_MARK,
+	A20_EA20_MARK, PORT66_KEYIN0_MARK, MSIOF0_RSCK_MARK,
+	A21_EA21_MARK, PORT67_KEYIN1_MARK, MSIOF0_RSYNC_MARK,
+	A22_EA22_MARK, PORT68_KEYIN2_MARK, MSIOF0_MCK0_MARK,
+	A23_EA23_MARK, PORT69_KEYIN3_MARK, MSIOF0_MCK1_MARK,
+	A24_EA24_MARK, PORT70_KEYIN4_MARK, MSIOF0_RXD_MARK,
+	A25_EA25_MARK, PORT71_KEYIN5_MARK, MSIOF0_SS2_MARK,
+	A26_MARK, PORT72_KEYIN6_MARK,
+	D0_ED0_NAF0_MARK,
+	D1_ED1_NAF1_MARK,
+	D2_ED2_NAF2_MARK,
+	D3_ED3_NAF3_MARK,
+	D4_ED4_NAF4_MARK,
+	D5_ED5_NAF5_MARK,
+	D6_ED6_NAF6_MARK,
+	D7_ED7_NAF7_MARK,
+	D8_ED8_NAF8_MARK,
+	D9_ED9_NAF9_MARK,
+	D10_ED10_NAF10_MARK,
+	D11_ED11_NAF11_MARK,
+	D12_ED12_NAF12_MARK,
+	D13_ED13_NAF13_MARK,
+	D14_ED14_NAF14_MARK,
+	D15_ED15_NAF15_MARK,
+	CS4_MARK,
+	CS5A_MARK, FMSICK_MARK,
+	CS5B_MARK, FCE1_MARK,
+
+	/* 55-3 */
+	CS6B_MARK, XCS2_MARK, CS6A_MARK, DACK0_MARK,
+	FCE0_MARK,
+	WAIT_MARK, DREQ0_MARK,
+	RD_XRD_MARK,
+	WE0_XWR0_FWE_MARK,
+	WE1_XWR1_MARK,
+	FRB_MARK,
+	CKO_MARK,
+	NBRSTOUT_MARK,
+	NBRST_MARK,
+	GPS_EPPSIN_MARK,
+	LATCHPULSE_MARK,
+	LTESIGNAL_MARK,
+	LEGACYSTATE_MARK,
+	TCKON_MARK,
+	VIO_VD_MARK, PORT128_KEYOUT0_MARK, IPORT0_MARK,
+	VIO_HD_MARK, PORT129_KEYOUT1_MARK, IPORT1_MARK,
+	VIO_D0_MARK, PORT130_KEYOUT2_MARK, PORT130_MSIOF2_RXD_MARK,
+	VIO_D1_MARK, PORT131_KEYOUT3_MARK, PORT131_MSIOF2_SS1_MARK,
+	VIO_D2_MARK, PORT132_KEYOUT4_MARK, PORT132_MSIOF2_SS2_MARK,
+	VIO_D3_MARK, PORT133_KEYOUT5_MARK, PORT133_MSIOF2_TSYNC_MARK,
+	VIO_D4_MARK, PORT134_KEYIN0_MARK, PORT134_MSIOF2_TXD_MARK,
+	VIO_D5_MARK, PORT135_KEYIN1_MARK, PORT135_MSIOF2_TSCK_MARK,
+	VIO_D6_MARK, PORT136_KEYIN2_MARK,
+	VIO_D7_MARK, PORT137_KEYIN3_MARK,
+	VIO_D8_MARK, M9_SLCD_A01_MARK, PORT138_FSIAOMC_MARK,
+	VIO_D9_MARK, M10_SLCD_CK1_MARK, PORT139_FSIAOLR_MARK,
+	VIO_D10_MARK, M11_SLCD_SO1_MARK, TPU0TO2_MARK, PORT140_FSIAOBT_MARK,
+	VIO_D11_MARK, M12_SLCD_CE1_MARK, TPU0TO3_MARK, PORT141_FSIAOSLD_MARK,
+	VIO_D12_MARK, M13_BSW_MARK, PORT142_FSIACK_MARK,
+	VIO_D13_MARK, M14_GSW_MARK, PORT143_FSIAILR_MARK,
+	VIO_D14_MARK, M15_RSW_MARK, PORT144_FSIAIBT_MARK,
+	VIO_D15_MARK, TPU1TO3_MARK, PORT145_FSIAISLD_MARK,
+	VIO_CLK_MARK, PORT146_KEYIN4_MARK, IPORT2_MARK,
+	VIO_FIELD_MARK, PORT147_KEYIN5_MARK,
+	VIO_CKO_MARK, PORT148_KEYIN6_MARK,
+	A27_MARK, RDWR_XWE_MARK, MFG0_IN1_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,
+	SOUT3_MARK, SCIFA2_TXD1_MARK, MSIOF2_MCK0_MARK,
+	SIN3_MARK, SCIFA2_RXD1_MARK, MSIOF2_MCK1_MARK,
+	XRTS3_MARK, SCIFA2_RTS1_MARK, PORT156_MSIOF2_SS2_MARK,
+	XCTS3_MARK, SCIFA2_CTS1_MARK, PORT157_MSIOF2_RXD_MARK,
+
+	/* 55-4 */
+	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, SOUT0_MARK,
+	PORT161_SCIFB_CTS_MARK, PORT161_SCIFA5_CTS_MARK, XCTS0_MARK,
+	MFG3_IN2_MARK,
+	PORT162_SCIFB_RXD_MARK, PORT162_SCIFA5_RXD_MARK, SIN0_MARK,
+	MFG3_IN1_MARK,
+	PORT163_SCIFB_RTS_MARK, PORT163_SCIFA5_RTS_MARK, XRTS0_MARK,
+	MFG3_OUT1_MARK, TPU3TO0_MARK,
+	LCDD0_MARK, PORT192_KEYOUT0_MARK, EXT_CKI_MARK,
+	LCDD1_MARK, PORT193_KEYOUT1_MARK, PORT193_SCIFA5_CTS_MARK,
+	BBIF2_TSYNC1_MARK,
+	LCDD2_MARK, PORT194_KEYOUT2_MARK, PORT194_SCIFA5_RTS_MARK,
+	BBIF2_TSCK1_MARK,
+	LCDD3_MARK, PORT195_KEYOUT3_MARK, PORT195_SCIFA5_RXD_MARK,
+	BBIF2_TXD1_MARK,
+	LCDD4_MARK, PORT196_KEYOUT4_MARK, PORT196_SCIFA5_TXD_MARK,
+	LCDD5_MARK, PORT197_KEYOUT5_MARK, PORT197_SCIFA5_SCK_MARK,
+	MFG2_OUT2_MARK,
+	TPU2TO1_MARK,
+	LCDD6_MARK, XWR2_MARK,
+	LCDD7_MARK, TPU4TO1_MARK, MFG4_OUT2_MARK, XWR3_MARK,
+	LCDD8_MARK, PORT200_KEYIN0_MARK, VIO_DR0_MARK, D16_MARK, ED16_MARK,
+	LCDD9_MARK, PORT201_KEYIN1_MARK, VIO_DR1_MARK, D17_MARK, ED17_MARK,
+	LCDD10_MARK, PORT202_KEYIN2_MARK, VIO_DR2_MARK, D18_MARK, ED18_MARK,
+	LCDD11_MARK, PORT203_KEYIN3_MARK, VIO_DR3_MARK, D19_MARK, ED19_MARK,
+	LCDD12_MARK, PORT204_KEYIN4_MARK, VIO_DR4_MARK, D20_MARK, ED20_MARK,
+	LCDD13_MARK, PORT205_KEYIN5_MARK, VIO_DR5_MARK, D21_MARK, ED21_MARK,
+	LCDD14_MARK, PORT206_KEYIN6_MARK, VIO_DR6_MARK, D22_MARK, ED22_MARK,
+	LCDD15_MARK, PORT207_MSIOF0L_SS1_MARK, PORT207_KEYOUT0_MARK,
+	VIO_DR7_MARK, D23_MARK, ED23_MARK,
+	LCDD16_MARK, PORT208_MSIOF0L_SS2_MARK, PORT208_KEYOUT1_MARK,
+	VIO_VDR_MARK, D24_MARK, ED24_MARK,
+	LCDD17_MARK, PORT209_KEYOUT2_MARK, VIO_HDR_MARK, D25_MARK, ED25_MARK,
+	LCDD18_MARK, DREQ2_MARK, PORT210_MSIOF0L_SS1_MARK, D26_MARK, ED26_MARK,
+	LCDD19_MARK, PORT211_MSIOF0L_SS2_MARK, D27_MARK, ED27_MARK,
+	LCDD20_MARK, TS_SPSYNC1_MARK, MSIOF0L_MCK0_MARK, D28_MARK, ED28_MARK,
+	LCDD21_MARK, TS_SDAT1_MARK, MSIOF0L_MCK1_MARK, D29_MARK, ED29_MARK,
+	LCDD22_MARK, TS_SDEN1_MARK, MSIOF0L_RSCK_MARK, D30_MARK, ED30_MARK,
+	LCDD23_MARK, TS_SCK1_MARK, MSIOF0L_RSYNC_MARK, D31_MARK, ED31_MARK,
+	LCDDCK_MARK, LCDWR_MARK, PORT216_KEYOUT3_MARK, VIO_CLKR_MARK,
+	LCDRD_MARK, DACK2_MARK, MSIOF0L_TSYNC_MARK,
+	LCDHSYN_MARK, LCDCS_MARK, LCDCS2_MARK, DACK3_MARK,
+	PORT218_VIO_CKOR_MARK, PORT218_KEYOUT4_MARK,
+	LCDDISP_MARK, LCDRS_MARK, DREQ3_MARK, MSIOF0L_TSCK_MARK,
+	LCDVSYN_MARK, LCDVSYN2_MARK, PORT220_KEYOUT5_MARK,
+	LCDLCLK_MARK, DREQ1_MARK, PWEN_MARK, MSIOF0L_RXD_MARK,
+	LCDDON_MARK, LCDDON2_MARK, DACK1_MARK, OVCN_MARK, MSIOF0L_TXD_MARK,
+	SCIFA1_TXD_MARK, OVCN2_MARK,
+	EXTLP_MARK, SCIFA1_SCK_MARK, USBTERM_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, PORT230_FSIAOMC_MARK,
+	MSIOF1_TSYNC_MARK, SCIFA2_CTS2_MARK, PORT231_FSIAOLR_MARK,
+	MSIOF1_TSCK_MARK, SCIFA2_SCK2_MARK, PORT232_FSIAOBT_MARK,
+	MSIOF1_RXD_MARK, SCIFA2_RXD2_MARK, GPS_VCOTRIG_MARK,
+	PORT233_FSIACK_MARK,
+	MSIOF1_RSCK_MARK, SCIFA2_RTS2_MARK, PORT234_FSIAOSLD_MARK,
+	MSIOF1_RSYNC_MARK, OPORT0_MARK, MFG1_IN2_MARK, PORT235_FSIAILR_MARK,
+	MSIOF1_MCK0_MARK, I2C_SDA2_MARK, PORT236_FSIAIBT_MARK,
+	MSIOF1_MCK1_MARK, I2C_SCL2_MARK, PORT237_FSIAISLD_MARK,
+	MSIOF1_SS1_MARK, EDBGREQ3_MARK,
+
+	/* 55-5 */
+	MSIOF1_SS2_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,
+	PORT244_MSIOF2_RXD_MARK,
+	PORT245_SCIFA5_RTS_MARK, MFG2_IN2_MARK, PORT245_SCIFB_RTS_MARK,
+	PORT245_MSIOF2_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_MSIOF2_TSCK_MARK,
+	PORT249_IROUT_MARK, MFG4_IN1_MARK, PORT249_MSIOF2_TSYNC_MARK,
+	SDHICLK0_MARK, TCK2_SWCLK_MC0_MARK,
+	SDHICD0_MARK,
+	SDHID0_0_MARK, TMS2_SWDIO_MC0_MARK,
+	SDHID0_1_MARK, TDO2_SWO0_MC0_MARK,
+	SDHID0_2_MARK, TDI2_MARK,
+	SDHID0_3_MARK, RTCK2_SWO1_MC0_MARK,
+	SDHICMD0_MARK, TRST2_MARK,
+	SDHIWP0_MARK, EDBGREQ2_MARK,
+	SDHICLK1_MARK, TCK3_SWCLK_MC1_MARK,
+	SDHID1_0_MARK, M11_SLCD_SO2_MARK, TS_SPSYNC2_MARK,
+	TMS3_SWDIO_MC1_MARK,
+	SDHID1_1_MARK, M9_SLCD_A02_MARK, TS_SDAT2_MARK, TDO3_SWO0_MC1_MARK,
+	SDHID1_2_MARK, M10_SLCD_CK2_MARK, TS_SDEN2_MARK, TDI3_MARK,
+	SDHID1_3_MARK, M12_SLCD_CE2_MARK, TS_SCK2_MARK, RTCK3_SWO1_MC1_MARK,
+	SDHICMD1_MARK, TRST3_MARK,
+	RESETOUTS_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 */
+	/* 55-1 (GPIO) */
+	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_PU(9),
+	PORT_DATA_I_PU(10), PORT_DATA_I_PU(11),
+	PORT_DATA_IO_PU(12), PORT_DATA_IO_PU(13),
+	PORT_DATA_IO_PU_PD(14), PORT_DATA_IO_PU_PD(15),
+	PORT_DATA_O(16), PORT_DATA_IO(17),
+	PORT_DATA_O(18), PORT_DATA_O(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_O(27),
+	PORT_DATA_O(28), PORT_DATA_O(29),
+	PORT_DATA_IO(30), PORT_DATA_IO_PU(31),
+	PORT_DATA_IO_PD(32), PORT_DATA_I_PU(33),
+	PORT_DATA_IO_PD(34), PORT_DATA_I_PU_PD(35),
+	PORT_DATA_O(36), PORT_DATA_IO(37),
+
+	/* 55-2 (GPIO) */
+	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_PD(43),
+	PORT_DATA_IO_PD(44), PORT_DATA_I_PD(45),
+	PORT_DATA_I_PD(46), PORT_DATA_I_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_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),
+
+	/* 55-3 (GPIO) */
+	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_PD(104), PORT_DATA_I_PD(105),
+	PORT_DATA_I_PD(106), PORT_DATA_I_PD(107),
+	PORT_DATA_I_PD(108), PORT_DATA_IO_PD(109),
+	PORT_DATA_IO_PD(110), PORT_DATA_I_PD(111),
+	PORT_DATA_IO_PD(112), PORT_DATA_IO_PD(113),
+	PORT_DATA_IO_PD(114), PORT_DATA_I_PD(115),
+	PORT_DATA_I_PD(116), PORT_DATA_IO_PD(117),
+	PORT_DATA_I_PD(118), PORT_DATA_IO_PD(128),
+	PORT_DATA_IO_PD(129), PORT_DATA_IO_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_PD(150),
+	PORT_DATA_IO_PU_PD(151), PORT_DATA_IO_PD(152),
+	PORT_DATA_IO_PD(153), PORT_DATA_IO_PD(154),
+	PORT_DATA_I_PD(155), PORT_DATA_IO_PU_PD(156),
+	PORT_DATA_I_PD(157), PORT_DATA_IO_PD(158),
+
+	/* 55-4 (GPIO) */
+	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_PD(193),
+	PORT_DATA_IO_PD(194), PORT_DATA_IO_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_PD(214), PORT_DATA_IO_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_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_PD(228),
+	PORT_DATA_I_PD(229), PORT_DATA_IO(230),
+	PORT_DATA_IO_PD(231), PORT_DATA_IO_PU_PD(232),
+	PORT_DATA_I_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),
+
+	/* 55-5 (GPIO) */
+	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_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_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),
+
+	/* Special Pull-up / Pull-down Functions */
+	PINMUX_DATA(PORT66_KEYIN0_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
+				PORT66_FN2, PORT66_IN_PU),
+	PINMUX_DATA(PORT67_KEYIN1_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
+				PORT67_FN2, PORT67_IN_PU),
+	PINMUX_DATA(PORT68_KEYIN2_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
+				PORT68_FN2, PORT68_IN_PU),
+	PINMUX_DATA(PORT69_KEYIN3_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
+				PORT69_FN2, PORT69_IN_PU),
+	PINMUX_DATA(PORT70_KEYIN4_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
+				PORT70_FN2, PORT70_IN_PU),
+	PINMUX_DATA(PORT71_KEYIN5_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
+				PORT71_FN2, PORT71_IN_PU),
+	PINMUX_DATA(PORT72_KEYIN6_PU_MARK, MSELBCR_MSEL17_0, MSELBCR_MSEL16_0,
+				PORT72_FN2, PORT72_IN_PU),
+
+
+	/* 55-1 (FN) */
+	PINMUX_DATA(VBUS_0_MARK, PORT0_FN1),
+	PINMUX_DATA(CPORT0_MARK, PORT1_FN1),
+	PINMUX_DATA(CPORT1_MARK, PORT2_FN1),
+	PINMUX_DATA(CPORT2_MARK, PORT3_FN1),
+	PINMUX_DATA(CPORT3_MARK, PORT4_FN1),
+	PINMUX_DATA(CPORT4_MARK, PORT5_FN1),
+	PINMUX_DATA(CPORT5_MARK, PORT6_FN1),
+	PINMUX_DATA(CPORT6_MARK, PORT7_FN1),
+	PINMUX_DATA(CPORT7_MARK, PORT8_FN1),
+	PINMUX_DATA(CPORT8_MARK, PORT9_FN1),
+	PINMUX_DATA(CPORT9_MARK, PORT10_FN1),
+	PINMUX_DATA(CPORT10_MARK, PORT11_FN1),
+	PINMUX_DATA(CPORT11_MARK, PORT12_FN1),
+	PINMUX_DATA(SIN2_MARK, PORT12_FN2),
+	PINMUX_DATA(CPORT12_MARK, PORT13_FN1),
+	PINMUX_DATA(XCTS2_MARK, PORT13_FN2),
+	PINMUX_DATA(CPORT13_MARK, PORT14_FN1),
+	PINMUX_DATA(RFSPO4_MARK, PORT14_FN2),
+	PINMUX_DATA(CPORT14_MARK, PORT15_FN1),
+	PINMUX_DATA(RFSPO5_MARK, PORT15_FN2),
+	PINMUX_DATA(CPORT15_MARK, PORT16_FN1),
+	PINMUX_DATA(SCIFA0_SCK_MARK, PORT16_FN2),
+	PINMUX_DATA(GPS_AGC2_MARK, PORT16_FN3),
+	PINMUX_DATA(CPORT16_MARK, PORT17_FN1),
+	PINMUX_DATA(SCIFA0_TXD_MARK, PORT17_FN2),
+	PINMUX_DATA(GPS_AGC3_MARK, PORT17_FN3),
+	PINMUX_DATA(CPORT17_IC_OE_MARK, PORT18_FN1),
+	PINMUX_DATA(SOUT2_MARK, PORT18_FN2),
+	PINMUX_DATA(CPORT18_MARK, PORT19_FN1),
+	PINMUX_DATA(XRTS2_MARK, PORT19_FN2),
+	PINMUX_DATA(PORT19_VIO_CKO2_MARK, PORT19_FN3),
+	PINMUX_DATA(CPORT19_MPORT1_MARK, PORT20_FN1),
+	PINMUX_DATA(CPORT20_MARK, PORT21_FN1),
+	PINMUX_DATA(RFSPO6_MARK, PORT21_FN2),
+	PINMUX_DATA(CPORT21_MARK, PORT22_FN1),
+	PINMUX_DATA(STATUS0_MARK, PORT22_FN2),
+	PINMUX_DATA(CPORT22_MARK, PORT23_FN1),
+	PINMUX_DATA(STATUS1_MARK, PORT23_FN2),
+	PINMUX_DATA(CPORT23_MARK, PORT24_FN1),
+	PINMUX_DATA(STATUS2_MARK, PORT24_FN2),
+	PINMUX_DATA(RFSPO7_MARK, PORT24_FN3),
+	PINMUX_DATA(B_SYNLD1_MARK, PORT25_FN1),
+	PINMUX_DATA(B_SYNLD2_MARK, PORT26_FN1),
+	PINMUX_DATA(SYSENMSK_MARK, PORT26_FN2),
+	PINMUX_DATA(XMAINPS_MARK, PORT27_FN1),
+	PINMUX_DATA(XDIVPS_MARK, PORT28_FN1),
+	PINMUX_DATA(XIDRST_MARK, PORT29_FN1),
+	PINMUX_DATA(IDCLK_MARK, PORT30_FN1),
+	PINMUX_DATA(IC_DP_MARK, PORT30_FN2),
+	PINMUX_DATA(IDIO_MARK, PORT31_FN1),
+	PINMUX_DATA(IC_DM_MARK, PORT31_FN2),
+	PINMUX_DATA(SOUT1_MARK, PORT32_FN1),
+	PINMUX_DATA(SCIFA4_TXD_MARK, PORT32_FN2),
+	PINMUX_DATA(M02_BERDAT_MARK, PORT32_FN3),
+	PINMUX_DATA(SIN1_MARK, PORT33_FN1),
+	PINMUX_DATA(SCIFA4_RXD_MARK, PORT33_FN2),
+	PINMUX_DATA(XWUP_MARK, PORT33_FN3),
+	PINMUX_DATA(XRTS1_MARK, PORT34_FN1),
+	PINMUX_DATA(SCIFA4_RTS_MARK, PORT34_FN2),
+	PINMUX_DATA(M03_BERCLK_MARK, PORT34_FN3),
+	PINMUX_DATA(XCTS1_MARK, PORT35_FN1),
+	PINMUX_DATA(SCIFA4_CTS_MARK, PORT35_FN2),
+	PINMUX_DATA(PCMCLKO_MARK, PORT36_FN1),
+	PINMUX_DATA(SYNC8KO_MARK, PORT37_FN1),
+
+	/* 55-2 (FN) */
+	PINMUX_DATA(DNPCM_A_MARK, PORT38_FN1),
+	PINMUX_DATA(UPPCM_A_MARK, PORT39_FN1),
+	PINMUX_DATA(VACK_MARK, PORT40_FN1),
+	PINMUX_DATA(XTALB1L_MARK, PORT41_FN1),
+	PINMUX_DATA(GPS_AGC1_MARK, PORT42_FN1),
+	PINMUX_DATA(SCIFA0_RTS_MARK, PORT42_FN2),
+	PINMUX_DATA(GPS_AGC4_MARK, PORT43_FN1),
+	PINMUX_DATA(SCIFA0_RXD_MARK, PORT43_FN2),
+	PINMUX_DATA(GPS_PWRDOWN_MARK, PORT44_FN1),
+	PINMUX_DATA(SCIFA0_CTS_MARK, PORT44_FN2),
+	PINMUX_DATA(GPS_IM_MARK, PORT45_FN1),
+	PINMUX_DATA(GPS_IS_MARK, PORT46_FN1),
+	PINMUX_DATA(GPS_QM_MARK, PORT47_FN1),
+	PINMUX_DATA(GPS_QS_MARK, PORT48_FN1),
+	PINMUX_DATA(FMSOCK_MARK, PORT49_FN1),
+	PINMUX_DATA(PORT49_IRDA_OUT_MARK, PORT49_FN2),
+	PINMUX_DATA(PORT49_IROUT_MARK, PORT49_FN3),
+	PINMUX_DATA(FMSOOLR_MARK, PORT50_FN1),
+	PINMUX_DATA(BBIF2_TSYNC2_MARK, PORT50_FN2),
+	PINMUX_DATA(TPU2TO2_MARK, PORT50_FN3),
+	PINMUX_DATA(IPORT3_MARK, PORT50_FN4),
+	PINMUX_DATA(FMSIOLR_MARK, PORT50_FN5),
+	PINMUX_DATA(FMSOOBT_MARK, PORT51_FN1),
+	PINMUX_DATA(BBIF2_TSCK2_MARK, PORT51_FN2),
+	PINMUX_DATA(TPU2TO3_MARK, PORT51_FN3),
+	PINMUX_DATA(OPORT1_MARK, PORT51_FN4),
+	PINMUX_DATA(FMSIOBT_MARK, PORT51_FN5),
+	PINMUX_DATA(FMSOSLD_MARK, PORT52_FN1),
+	PINMUX_DATA(BBIF2_TXD2_MARK, PORT52_FN2),
+	PINMUX_DATA(OPORT2_MARK, PORT52_FN3),
+	PINMUX_DATA(FMSOILR_MARK, PORT53_FN1),
+	PINMUX_DATA(PORT53_IRDA_IN_MARK, PORT53_FN2),
+	PINMUX_DATA(TPU3TO3_MARK, PORT53_FN3),
+	PINMUX_DATA(OPORT3_MARK, PORT53_FN4),
+	PINMUX_DATA(FMSIILR_MARK, PORT53_FN5),
+	PINMUX_DATA(FMSOIBT_MARK, PORT54_FN1),
+	PINMUX_DATA(PORT54_IRDA_FIRSEL_MARK, PORT54_FN2),
+	PINMUX_DATA(TPU3TO2_MARK, PORT54_FN3),
+	PINMUX_DATA(FMSIIBT_MARK, PORT54_FN4),
+	PINMUX_DATA(FMSISLD_MARK, PORT55_FN1),
+	PINMUX_DATA(MFG0_OUT1_MARK, PORT55_FN2),
+	PINMUX_DATA(TPU0TO0_MARK, PORT55_FN3),
+	PINMUX_DATA(A0_EA0_MARK, PORT57_FN1),
+	PINMUX_DATA(BS_MARK, PORT57_FN2),
+	PINMUX_DATA(A12_EA12_MARK, PORT58_FN1),
+	PINMUX_DATA(PORT58_VIO_CKOR_MARK, PORT58_FN2),
+	PINMUX_DATA(TPU4TO2_MARK, PORT58_FN3),
+	PINMUX_DATA(A13_EA13_MARK, PORT59_FN1),
+	PINMUX_DATA(PORT59_IROUT_MARK, PORT59_FN2),
+	PINMUX_DATA(MFG0_OUT2_MARK, PORT59_FN3),
+	PINMUX_DATA(TPU0TO1_MARK, PORT59_FN4),
+	PINMUX_DATA(A14_EA14_MARK, PORT60_FN1),
+	PINMUX_DATA(PORT60_KEYOUT5_MARK, PORT60_FN2),
+	PINMUX_DATA(A15_EA15_MARK, PORT61_FN1),
+	PINMUX_DATA(PORT61_KEYOUT4_MARK, PORT61_FN2),
+	PINMUX_DATA(A16_EA16_MARK, PORT62_FN1),
+	PINMUX_DATA(PORT62_KEYOUT3_MARK, PORT62_FN2),
+	PINMUX_DATA(MSIOF0_SS1_MARK, PORT62_FN3),
+	PINMUX_DATA(A17_EA17_MARK, PORT63_FN1),
+	PINMUX_DATA(PORT63_KEYOUT2_MARK, PORT63_FN2),
+	PINMUX_DATA(MSIOF0_TSYNC_MARK, PORT63_FN3),
+	PINMUX_DATA(A18_EA18_MARK, PORT64_FN1),
+	PINMUX_DATA(PORT64_KEYOUT1_MARK, PORT64_FN2),
+	PINMUX_DATA(MSIOF0_TSCK_MARK, PORT64_FN3),
+	PINMUX_DATA(A19_EA19_MARK, PORT65_FN1),
+	PINMUX_DATA(PORT65_KEYOUT0_MARK, PORT65_FN2),
+	PINMUX_DATA(MSIOF0_TXD_MARK, PORT65_FN3),
+	PINMUX_DATA(A20_EA20_MARK, PORT66_FN1),
+	PINMUX_DATA(PORT66_KEYIN0_MARK, PORT66_FN2),
+	PINMUX_DATA(MSIOF0_RSCK_MARK, PORT66_FN3),
+	PINMUX_DATA(A21_EA21_MARK, PORT67_FN1),
+	PINMUX_DATA(PORT67_KEYIN1_MARK, PORT67_FN2),
+	PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT67_FN3),
+	PINMUX_DATA(A22_EA22_MARK, PORT68_FN1),
+	PINMUX_DATA(PORT68_KEYIN2_MARK, PORT68_FN2),
+	PINMUX_DATA(MSIOF0_MCK0_MARK, PORT68_FN3),
+	PINMUX_DATA(A23_EA23_MARK, PORT69_FN1),
+	PINMUX_DATA(PORT69_KEYIN3_MARK, PORT69_FN2),
+	PINMUX_DATA(MSIOF0_MCK1_MARK, PORT69_FN3),
+	PINMUX_DATA(A24_EA24_MARK, PORT70_FN1),
+	PINMUX_DATA(PORT70_KEYIN4_MARK, PORT70_FN2),
+	PINMUX_DATA(MSIOF0_RXD_MARK, PORT70_FN3),
+	PINMUX_DATA(A25_EA25_MARK, PORT71_FN1),
+	PINMUX_DATA(PORT71_KEYIN5_MARK, PORT71_FN2),
+	PINMUX_DATA(MSIOF0_SS2_MARK, PORT71_FN3),
+	PINMUX_DATA(A26_MARK, PORT72_FN1),
+	PINMUX_DATA(PORT72_KEYIN6_MARK, PORT72_FN2),
+	PINMUX_DATA(D0_ED0_NAF0_MARK, PORT74_FN1),
+	PINMUX_DATA(D1_ED1_NAF1_MARK, PORT75_FN1),
+	PINMUX_DATA(D2_ED2_NAF2_MARK, PORT76_FN1),
+	PINMUX_DATA(D3_ED3_NAF3_MARK, PORT77_FN1),
+	PINMUX_DATA(D4_ED4_NAF4_MARK, PORT78_FN1),
+	PINMUX_DATA(D5_ED5_NAF5_MARK, PORT79_FN1),
+	PINMUX_DATA(D6_ED6_NAF6_MARK, PORT80_FN1),
+	PINMUX_DATA(D7_ED7_NAF7_MARK, PORT81_FN1),
+	PINMUX_DATA(D8_ED8_NAF8_MARK, PORT82_FN1),
+	PINMUX_DATA(D9_ED9_NAF9_MARK, PORT83_FN1),
+	PINMUX_DATA(D10_ED10_NAF10_MARK, PORT84_FN1),
+	PINMUX_DATA(D11_ED11_NAF11_MARK, PORT85_FN1),
+	PINMUX_DATA(D12_ED12_NAF12_MARK, PORT86_FN1),
+	PINMUX_DATA(D13_ED13_NAF13_MARK, PORT87_FN1),
+	PINMUX_DATA(D14_ED14_NAF14_MARK, PORT88_FN1),
+	PINMUX_DATA(D15_ED15_NAF15_MARK, PORT89_FN1),
+	PINMUX_DATA(CS4_MARK, PORT90_FN1),
+	PINMUX_DATA(CS5A_MARK, PORT91_FN1),
+	PINMUX_DATA(FMSICK_MARK, PORT91_FN2),
+	PINMUX_DATA(CS5B_MARK, PORT92_FN1),
+	PINMUX_DATA(FCE1_MARK, PORT92_FN2),
+
+	/* 55-3 (FN) */
+	PINMUX_DATA(CS6B_MARK, PORT93_FN1),
+	PINMUX_DATA(XCS2_MARK, PORT93_FN2),
+	PINMUX_DATA(CS6A_MARK, PORT93_FN3),
+	PINMUX_DATA(DACK0_MARK, PORT93_FN4),
+	PINMUX_DATA(FCE0_MARK, PORT94_FN1),
+	PINMUX_DATA(WAIT_MARK, PORT95_FN1),
+	PINMUX_DATA(DREQ0_MARK, PORT95_FN2),
+	PINMUX_DATA(RD_XRD_MARK, PORT96_FN1),
+	PINMUX_DATA(WE0_XWR0_FWE_MARK, PORT97_FN1),
+	PINMUX_DATA(WE1_XWR1_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(GPS_EPPSIN_MARK, PORT106_FN1),
+	PINMUX_DATA(LATCHPULSE_MARK, PORT110_FN1),
+	PINMUX_DATA(LTESIGNAL_MARK, PORT111_FN1),
+	PINMUX_DATA(LEGACYSTATE_MARK, PORT112_FN1),
+	PINMUX_DATA(TCKON_MARK, PORT118_FN1),
+	PINMUX_DATA(VIO_VD_MARK, PORT128_FN1),
+	PINMUX_DATA(PORT128_KEYOUT0_MARK, PORT128_FN2),
+	PINMUX_DATA(IPORT0_MARK, PORT128_FN3),
+	PINMUX_DATA(VIO_HD_MARK, PORT129_FN1),
+	PINMUX_DATA(PORT129_KEYOUT1_MARK, PORT129_FN2),
+	PINMUX_DATA(IPORT1_MARK, PORT129_FN3),
+	PINMUX_DATA(VIO_D0_MARK, PORT130_FN1),
+	PINMUX_DATA(PORT130_KEYOUT2_MARK, PORT130_FN2),
+	PINMUX_DATA(PORT130_MSIOF2_RXD_MARK, PORT130_FN3),
+	PINMUX_DATA(VIO_D1_MARK, PORT131_FN1),
+	PINMUX_DATA(PORT131_KEYOUT3_MARK, PORT131_FN2),
+	PINMUX_DATA(PORT131_MSIOF2_SS1_MARK, PORT131_FN3),
+	PINMUX_DATA(VIO_D2_MARK, PORT132_FN1),
+	PINMUX_DATA(PORT132_KEYOUT4_MARK, PORT132_FN2),
+	PINMUX_DATA(PORT132_MSIOF2_SS2_MARK, PORT132_FN3),
+	PINMUX_DATA(VIO_D3_MARK, PORT133_FN1),
+	PINMUX_DATA(PORT133_KEYOUT5_MARK, PORT133_FN2),
+	PINMUX_DATA(PORT133_MSIOF2_TSYNC_MARK, PORT133_FN3),
+	PINMUX_DATA(VIO_D4_MARK, PORT134_FN1),
+	PINMUX_DATA(PORT134_KEYIN0_MARK, PORT134_FN2),
+	PINMUX_DATA(PORT134_MSIOF2_TXD_MARK, PORT134_FN3),
+	PINMUX_DATA(VIO_D5_MARK, PORT135_FN1),
+	PINMUX_DATA(PORT135_KEYIN1_MARK, PORT135_FN2),
+	PINMUX_DATA(PORT135_MSIOF2_TSCK_MARK, PORT135_FN3),
+	PINMUX_DATA(VIO_D6_MARK, PORT136_FN1),
+	PINMUX_DATA(PORT136_KEYIN2_MARK, PORT136_FN2),
+	PINMUX_DATA(VIO_D7_MARK, PORT137_FN1),
+	PINMUX_DATA(PORT137_KEYIN3_MARK, PORT137_FN2),
+	PINMUX_DATA(VIO_D8_MARK, PORT138_FN1),
+	PINMUX_DATA(M9_SLCD_A01_MARK, PORT138_FN2),
+	PINMUX_DATA(PORT138_FSIAOMC_MARK, PORT138_FN3),
+	PINMUX_DATA(VIO_D9_MARK, PORT139_FN1),
+	PINMUX_DATA(M10_SLCD_CK1_MARK, PORT139_FN2),
+	PINMUX_DATA(PORT139_FSIAOLR_MARK, PORT139_FN3),
+	PINMUX_DATA(VIO_D10_MARK, PORT140_FN1),
+	PINMUX_DATA(M11_SLCD_SO1_MARK, PORT140_FN2),
+	PINMUX_DATA(TPU0TO2_MARK, PORT140_FN3),
+	PINMUX_DATA(PORT140_FSIAOBT_MARK, PORT140_FN4),
+	PINMUX_DATA(VIO_D11_MARK, PORT141_FN1),
+	PINMUX_DATA(M12_SLCD_CE1_MARK, PORT141_FN2),
+	PINMUX_DATA(TPU0TO3_MARK, PORT141_FN3),
+	PINMUX_DATA(PORT141_FSIAOSLD_MARK, PORT141_FN4),
+	PINMUX_DATA(VIO_D12_MARK, PORT142_FN1),
+	PINMUX_DATA(M13_BSW_MARK, PORT142_FN2),
+	PINMUX_DATA(PORT142_FSIACK_MARK, PORT142_FN3),
+	PINMUX_DATA(VIO_D13_MARK, PORT143_FN1),
+	PINMUX_DATA(M14_GSW_MARK, PORT143_FN2),
+	PINMUX_DATA(PORT143_FSIAILR_MARK, PORT143_FN3),
+	PINMUX_DATA(VIO_D14_MARK, PORT144_FN1),
+	PINMUX_DATA(M15_RSW_MARK, PORT144_FN2),
+	PINMUX_DATA(PORT144_FSIAIBT_MARK, PORT144_FN3),
+	PINMUX_DATA(VIO_D15_MARK, PORT145_FN1),
+	PINMUX_DATA(TPU1TO3_MARK, PORT145_FN2),
+	PINMUX_DATA(PORT145_FSIAISLD_MARK, PORT145_FN3),
+	PINMUX_DATA(VIO_CLK_MARK, PORT146_FN1),
+	PINMUX_DATA(PORT146_KEYIN4_MARK, PORT146_FN2),
+	PINMUX_DATA(IPORT2_MARK, PORT146_FN3),
+	PINMUX_DATA(VIO_FIELD_MARK, PORT147_FN1),
+	PINMUX_DATA(PORT147_KEYIN5_MARK, PORT147_FN2),
+	PINMUX_DATA(VIO_CKO_MARK, PORT148_FN1),
+	PINMUX_DATA(PORT148_KEYIN6_MARK, PORT148_FN2),
+	PINMUX_DATA(A27_MARK, PORT149_FN1),
+	PINMUX_DATA(RDWR_XWE_MARK, PORT149_FN2),
+	PINMUX_DATA(MFG0_IN1_MARK, PORT149_FN3),
+	PINMUX_DATA(MFG0_IN2_MARK, PORT150_FN1),
+	PINMUX_DATA(TS_SPSYNC3_MARK, PORT151_FN1),
+	PINMUX_DATA(MSIOF2_RSCK_MARK, PORT151_FN2),
+	PINMUX_DATA(TS_SDAT3_MARK, PORT152_FN1),
+	PINMUX_DATA(MSIOF2_RSYNC_MARK, PORT152_FN2),
+	PINMUX_DATA(TPU1TO2_MARK, PORT153_FN1),
+	PINMUX_DATA(TS_SDEN3_MARK, PORT153_FN2),
+	PINMUX_DATA(PORT153_MSIOF2_SS1_MARK, PORT153_FN3),
+	PINMUX_DATA(SOUT3_MARK, PORT154_FN1),
+	PINMUX_DATA(SCIFA2_TXD1_MARK, PORT154_FN2),
+	PINMUX_DATA(MSIOF2_MCK0_MARK, PORT154_FN3),
+	PINMUX_DATA(SIN3_MARK, PORT155_FN1),
+	PINMUX_DATA(SCIFA2_RXD1_MARK, PORT155_FN2),
+	PINMUX_DATA(MSIOF2_MCK1_MARK, PORT155_FN3),
+	PINMUX_DATA(XRTS3_MARK, PORT156_FN1),
+	PINMUX_DATA(SCIFA2_RTS1_MARK, PORT156_FN2),
+	PINMUX_DATA(PORT156_MSIOF2_SS2_MARK, PORT156_FN3),
+	PINMUX_DATA(XCTS3_MARK, PORT157_FN1),
+	PINMUX_DATA(SCIFA2_CTS1_MARK, PORT157_FN2),
+	PINMUX_DATA(PORT157_MSIOF2_RXD_MARK, PORT157_FN3),
+
+	/* 55-4 (FN) */
+	PINMUX_DATA(DINT_MARK, PORT158_FN1),
+	PINMUX_DATA(SCIFA2_SCK1_MARK, PORT158_FN2),
+	PINMUX_DATA(TS_SCK3_MARK, PORT158_FN3),
+	PINMUX_DATA(PORT159_SCIFB_SCK_MARK, PORT159_FN1),
+	PINMUX_DATA(PORT159_SCIFA5_SCK_MARK, PORT159_FN2),
+	PINMUX_DATA(NMI_MARK, PORT159_FN3),
+	PINMUX_DATA(PORT160_SCIFB_TXD_MARK, PORT160_FN1),
+	PINMUX_DATA(PORT160_SCIFA5_TXD_MARK, PORT160_FN2),
+	PINMUX_DATA(SOUT0_MARK, PORT160_FN3),
+	PINMUX_DATA(PORT161_SCIFB_CTS_MARK, PORT161_FN1),
+	PINMUX_DATA(PORT161_SCIFA5_CTS_MARK, PORT161_FN2),
+	PINMUX_DATA(XCTS0_MARK, PORT161_FN3),
+	PINMUX_DATA(MFG3_IN2_MARK, PORT161_FN4),
+	PINMUX_DATA(PORT162_SCIFB_RXD_MARK, PORT162_FN1),
+	PINMUX_DATA(PORT162_SCIFA5_RXD_MARK, PORT162_FN2),
+	PINMUX_DATA(SIN0_MARK, PORT162_FN3),
+	PINMUX_DATA(MFG3_IN1_MARK, PORT162_FN4),
+	PINMUX_DATA(PORT163_SCIFB_RTS_MARK, PORT163_FN1),
+	PINMUX_DATA(PORT163_SCIFA5_RTS_MARK, PORT163_FN2),
+	PINMUX_DATA(XRTS0_MARK, PORT163_FN3),
+	PINMUX_DATA(MFG3_OUT1_MARK, PORT163_FN4),
+	PINMUX_DATA(TPU3TO0_MARK, PORT163_FN5),
+	PINMUX_DATA(LCDD0_MARK, PORT192_FN1),
+	PINMUX_DATA(PORT192_KEYOUT0_MARK, PORT192_FN2),
+	PINMUX_DATA(EXT_CKI_MARK, PORT192_FN3),
+	PINMUX_DATA(LCDD1_MARK, PORT193_FN1),
+	PINMUX_DATA(PORT193_KEYOUT1_MARK, PORT193_FN2),
+	PINMUX_DATA(PORT193_SCIFA5_CTS_MARK, PORT193_FN3),
+	PINMUX_DATA(BBIF2_TSYNC1_MARK, PORT193_FN4),
+	PINMUX_DATA(LCDD2_MARK, PORT194_FN1),
+	PINMUX_DATA(PORT194_KEYOUT2_MARK, PORT194_FN2),
+	PINMUX_DATA(PORT194_SCIFA5_RTS_MARK, PORT194_FN3),
+	PINMUX_DATA(BBIF2_TSCK1_MARK, PORT194_FN4),
+	PINMUX_DATA(LCDD3_MARK, PORT195_FN1),
+	PINMUX_DATA(PORT195_KEYOUT3_MARK, PORT195_FN2),
+	PINMUX_DATA(PORT195_SCIFA5_RXD_MARK, PORT195_FN3),
+	PINMUX_DATA(BBIF2_TXD1_MARK, PORT195_FN4),
+	PINMUX_DATA(LCDD4_MARK, PORT196_FN1),
+	PINMUX_DATA(PORT196_KEYOUT4_MARK, PORT196_FN2),
+	PINMUX_DATA(PORT196_SCIFA5_TXD_MARK, PORT196_FN3),
+	PINMUX_DATA(LCDD5_MARK, PORT197_FN1),
+	PINMUX_DATA(PORT197_KEYOUT5_MARK, PORT197_FN2),
+	PINMUX_DATA(PORT197_SCIFA5_SCK_MARK, PORT197_FN3),
+	PINMUX_DATA(MFG2_OUT2_MARK, PORT197_FN4),
+	PINMUX_DATA(LCDD6_MARK, PORT198_FN1),
+	PINMUX_DATA(LCDD7_MARK, PORT199_FN1),
+	PINMUX_DATA(TPU4TO1_MARK, PORT199_FN2),
+	PINMUX_DATA(MFG4_OUT2_MARK, PORT199_FN3),
+	PINMUX_DATA(LCDD8_MARK, PORT200_FN1),
+	PINMUX_DATA(PORT200_KEYIN0_MARK, PORT200_FN2),
+	PINMUX_DATA(VIO_DR0_MARK, PORT200_FN3),
+	PINMUX_DATA(D16_MARK, PORT200_FN4),
+	PINMUX_DATA(LCDD9_MARK, PORT201_FN1),
+	PINMUX_DATA(PORT201_KEYIN1_MARK, PORT201_FN2),
+	PINMUX_DATA(VIO_DR1_MARK, PORT201_FN3),
+	PINMUX_DATA(D17_MARK, PORT201_FN4),
+	PINMUX_DATA(LCDD10_MARK, PORT202_FN1),
+	PINMUX_DATA(PORT202_KEYIN2_MARK, PORT202_FN2),
+	PINMUX_DATA(VIO_DR2_MARK, PORT202_FN3),
+	PINMUX_DATA(D18_MARK, PORT202_FN4),
+	PINMUX_DATA(LCDD11_MARK, PORT203_FN1),
+	PINMUX_DATA(PORT203_KEYIN3_MARK, PORT203_FN2),
+	PINMUX_DATA(VIO_DR3_MARK, PORT203_FN3),
+	PINMUX_DATA(D19_MARK, PORT203_FN4),
+	PINMUX_DATA(LCDD12_MARK, PORT204_FN1),
+	PINMUX_DATA(PORT204_KEYIN4_MARK, PORT204_FN2),
+	PINMUX_DATA(VIO_DR4_MARK, PORT204_FN3),
+	PINMUX_DATA(D20_MARK, PORT204_FN4),
+	PINMUX_DATA(LCDD13_MARK, PORT205_FN1),
+	PINMUX_DATA(PORT205_KEYIN5_MARK, PORT205_FN2),
+	PINMUX_DATA(VIO_DR5_MARK, PORT205_FN3),
+	PINMUX_DATA(D21_MARK, PORT205_FN4),
+	PINMUX_DATA(LCDD14_MARK, PORT206_FN1),
+	PINMUX_DATA(PORT206_KEYIN6_MARK, PORT206_FN2),
+	PINMUX_DATA(VIO_DR6_MARK, PORT206_FN3),
+	PINMUX_DATA(D22_MARK, PORT206_FN4),
+	PINMUX_DATA(LCDD15_MARK, PORT207_FN1),
+	PINMUX_DATA(PORT207_MSIOF0L_SS1_MARK, PORT207_FN2),
+	PINMUX_DATA(PORT207_KEYOUT0_MARK, PORT207_FN3),
+	PINMUX_DATA(VIO_DR7_MARK, PORT207_FN4),
+	PINMUX_DATA(D23_MARK, PORT207_FN5),
+	PINMUX_DATA(LCDD16_MARK, PORT208_FN1),
+	PINMUX_DATA(PORT208_MSIOF0L_SS2_MARK, PORT208_FN2),
+	PINMUX_DATA(PORT208_KEYOUT1_MARK, PORT208_FN3),
+	PINMUX_DATA(VIO_VDR_MARK, PORT208_FN4),
+	PINMUX_DATA(D24_MARK, PORT208_FN5),
+	PINMUX_DATA(LCDD17_MARK, PORT209_FN1),
+	PINMUX_DATA(PORT209_KEYOUT2_MARK, PORT209_FN2),
+	PINMUX_DATA(VIO_HDR_MARK, PORT209_FN3),
+	PINMUX_DATA(D25_MARK, PORT209_FN4),
+	PINMUX_DATA(LCDD18_MARK, PORT210_FN1),
+	PINMUX_DATA(DREQ2_MARK, PORT210_FN2),
+	PINMUX_DATA(PORT210_MSIOF0L_SS1_MARK, PORT210_FN3),
+	PINMUX_DATA(D26_MARK, PORT210_FN4),
+	PINMUX_DATA(LCDD19_MARK, PORT211_FN1),
+	PINMUX_DATA(PORT211_MSIOF0L_SS2_MARK, PORT211_FN2),
+	PINMUX_DATA(D27_MARK, PORT211_FN3),
+	PINMUX_DATA(LCDD20_MARK, PORT212_FN1),
+	PINMUX_DATA(TS_SPSYNC1_MARK, PORT212_FN2),
+	PINMUX_DATA(MSIOF0L_MCK0_MARK, PORT212_FN3),
+	PINMUX_DATA(D28_MARK, PORT212_FN4),
+	PINMUX_DATA(LCDD21_MARK, PORT213_FN1),
+	PINMUX_DATA(TS_SDAT1_MARK, PORT213_FN2),
+	PINMUX_DATA(MSIOF0L_MCK1_MARK, PORT213_FN3),
+	PINMUX_DATA(D29_MARK, PORT213_FN4),
+	PINMUX_DATA(LCDD22_MARK, PORT214_FN1),
+	PINMUX_DATA(TS_SDEN1_MARK, PORT214_FN2),
+	PINMUX_DATA(MSIOF0L_RSCK_MARK, PORT214_FN3),
+	PINMUX_DATA(D30_MARK, PORT214_FN4),
+	PINMUX_DATA(LCDD23_MARK, PORT215_FN1),
+	PINMUX_DATA(TS_SCK1_MARK, PORT215_FN2),
+	PINMUX_DATA(MSIOF0L_RSYNC_MARK, PORT215_FN3),
+	PINMUX_DATA(D31_MARK, PORT215_FN4),
+	PINMUX_DATA(LCDDCK_MARK, PORT216_FN1),
+	PINMUX_DATA(LCDWR_MARK, PORT216_FN2),
+	PINMUX_DATA(PORT216_KEYOUT3_MARK, PORT216_FN3),
+	PINMUX_DATA(VIO_CLKR_MARK, PORT216_FN4),
+	PINMUX_DATA(LCDRD_MARK, PORT217_FN1),
+	PINMUX_DATA(DACK2_MARK, PORT217_FN2),
+	PINMUX_DATA(MSIOF0L_TSYNC_MARK, PORT217_FN3),
+	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(PORT218_KEYOUT4_MARK, PORT218_FN6),
+	PINMUX_DATA(LCDDISP_MARK, PORT219_FN1),
+	PINMUX_DATA(LCDRS_MARK, PORT219_FN2),
+	PINMUX_DATA(DREQ3_MARK, PORT219_FN3),
+	PINMUX_DATA(MSIOF0L_TSCK_MARK, PORT219_FN4),
+	PINMUX_DATA(LCDVSYN_MARK, PORT220_FN1),
+	PINMUX_DATA(LCDVSYN2_MARK, PORT220_FN2),
+	PINMUX_DATA(PORT220_KEYOUT5_MARK, PORT220_FN3),
+	PINMUX_DATA(LCDLCLK_MARK, PORT221_FN1),
+	PINMUX_DATA(DREQ1_MARK, PORT221_FN2),
+	PINMUX_DATA(PWEN_MARK, PORT221_FN3),
+	PINMUX_DATA(MSIOF0L_RXD_MARK, PORT221_FN4),
+	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),
+	PINMUX_DATA(SCIFA1_TXD_MARK, PORT225_FN1),
+	PINMUX_DATA(OVCN2_MARK, PORT225_FN2),
+	PINMUX_DATA(EXTLP_MARK, PORT226_FN1),
+	PINMUX_DATA(SCIFA1_SCK_MARK, PORT226_FN2),
+	PINMUX_DATA(USBTERM_MARK, PORT226_FN3),
+	PINMUX_DATA(PORT226_VIO_CKO2_MARK, PORT226_FN4),
+	PINMUX_DATA(SCIFA1_RTS_MARK, PORT227_FN1),
+	PINMUX_DATA(IDIN_MARK, PORT227_FN2),
+	PINMUX_DATA(SCIFA1_RXD_MARK, PORT228_FN1),
+	PINMUX_DATA(SCIFA1_CTS_MARK, PORT229_FN1),
+	PINMUX_DATA(MFG1_IN1_MARK, PORT229_FN2),
+	PINMUX_DATA(MSIOF1_TXD_MARK, PORT230_FN1),
+	PINMUX_DATA(SCIFA2_TXD2_MARK, PORT230_FN2),
+	PINMUX_DATA(PORT230_FSIAOMC_MARK, PORT230_FN3),
+	PINMUX_DATA(MSIOF1_TSYNC_MARK, PORT231_FN1),
+	PINMUX_DATA(SCIFA2_CTS2_MARK, PORT231_FN2),
+	PINMUX_DATA(PORT231_FSIAOLR_MARK, PORT231_FN3),
+	PINMUX_DATA(MSIOF1_TSCK_MARK, PORT232_FN1),
+	PINMUX_DATA(SCIFA2_SCK2_MARK, PORT232_FN2),
+	PINMUX_DATA(PORT232_FSIAOBT_MARK, PORT232_FN3),
+	PINMUX_DATA(MSIOF1_RXD_MARK, PORT233_FN1),
+	PINMUX_DATA(SCIFA2_RXD2_MARK, PORT233_FN2),
+	PINMUX_DATA(GPS_VCOTRIG_MARK, PORT233_FN3),
+	PINMUX_DATA(PORT233_FSIACK_MARK, PORT233_FN4),
+	PINMUX_DATA(MSIOF1_RSCK_MARK, PORT234_FN1),
+	PINMUX_DATA(SCIFA2_RTS2_MARK, PORT234_FN2),
+	PINMUX_DATA(PORT234_FSIAOSLD_MARK, PORT234_FN3),
+	PINMUX_DATA(MSIOF1_RSYNC_MARK, PORT235_FN1),
+	PINMUX_DATA(OPORT0_MARK, PORT235_FN2),
+	PINMUX_DATA(MFG1_IN2_MARK, PORT235_FN3),
+	PINMUX_DATA(PORT235_FSIAILR_MARK, PORT235_FN4),
+	PINMUX_DATA(MSIOF1_MCK0_MARK, PORT236_FN1),
+	PINMUX_DATA(I2C_SDA2_MARK, PORT236_FN2),
+	PINMUX_DATA(PORT236_FSIAIBT_MARK, PORT236_FN3),
+	PINMUX_DATA(MSIOF1_MCK1_MARK, PORT237_FN1),
+	PINMUX_DATA(I2C_SCL2_MARK, PORT237_FN2),
+	PINMUX_DATA(PORT237_FSIAISLD_MARK, PORT237_FN3),
+	PINMUX_DATA(MSIOF1_SS1_MARK, PORT238_FN1),
+	PINMUX_DATA(EDBGREQ3_MARK, PORT238_FN2),
+
+	/* 55-5 (FN) */
+	PINMUX_DATA(MSIOF1_SS2_MARK, PORT239_FN1),
+	PINMUX_DATA(SCIFA6_TXD_MARK, PORT240_FN1),
+	PINMUX_DATA(PORT241_IRDA_OUT_MARK, PORT241_FN1),
+	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),
+	PINMUX_DATA(MFG4_IN2_MARK, PORT242_FN2),
+	PINMUX_DATA(PORT243_IRDA_FIRSEL_MARK, PORT243_FN1),
+	PINMUX_DATA(PORT243_VIO_CKO2_MARK, PORT243_FN2),
+	PINMUX_DATA(PORT244_SCIFA5_CTS_MARK, PORT244_FN1),
+	PINMUX_DATA(MFG2_IN1_MARK, PORT244_FN2),
+	PINMUX_DATA(PORT244_SCIFB_CTS_MARK, PORT244_FN3),
+	PINMUX_DATA(PORT245_SCIFA5_RTS_MARK, PORT245_FN1),
+	PINMUX_DATA(MFG2_IN2_MARK, PORT245_FN2),
+	PINMUX_DATA(PORT245_SCIFB_RTS_MARK, PORT245_FN3),
+	PINMUX_DATA(PORT246_SCIFA5_RXD_MARK, PORT246_FN1),
+	PINMUX_DATA(MFG1_OUT1_MARK, PORT246_FN2),
+	PINMUX_DATA(PORT246_SCIFB_RXD_MARK, PORT246_FN3),
+	PINMUX_DATA(TPU1TO0_MARK, PORT246_FN4),
+	PINMUX_DATA(PORT247_SCIFA5_TXD_MARK, PORT247_FN1),
+	PINMUX_DATA(MFG3_OUT2_MARK, PORT247_FN2),
+	PINMUX_DATA(PORT247_SCIFB_TXD_MARK, PORT247_FN3),
+	PINMUX_DATA(TPU3TO1_MARK, PORT247_FN4),
+	PINMUX_DATA(PORT248_SCIFA5_SCK_MARK, PORT248_FN1),
+	PINMUX_DATA(MFG2_OUT1_MARK, PORT248_FN2),
+	PINMUX_DATA(PORT248_SCIFB_SCK_MARK, PORT248_FN3),
+	PINMUX_DATA(TPU2TO0_MARK, PORT248_FN4),
+	PINMUX_DATA(PORT249_IROUT_MARK, PORT249_FN1),
+	PINMUX_DATA(MFG4_IN1_MARK, PORT249_FN2),
+	PINMUX_DATA(SDHICLK0_MARK, PORT250_FN1),
+	PINMUX_DATA(TCK2_SWCLK_MC0_MARK, PORT250_FN2),
+	PINMUX_DATA(SDHICD0_MARK, PORT251_FN1),
+	PINMUX_DATA(SDHID0_0_MARK, PORT252_FN1),
+	PINMUX_DATA(TMS2_SWDIO_MC0_MARK, PORT252_FN2),
+	PINMUX_DATA(SDHID0_1_MARK, PORT253_FN1),
+	PINMUX_DATA(TDO2_SWO0_MC0_MARK, PORT253_FN2),
+	PINMUX_DATA(SDHID0_2_MARK, PORT254_FN1),
+	PINMUX_DATA(TDI2_MARK, PORT254_FN2),
+	PINMUX_DATA(SDHID0_3_MARK, PORT255_FN1),
+	PINMUX_DATA(RTCK2_SWO1_MC0_MARK, PORT255_FN2),
+	PINMUX_DATA(SDHICMD0_MARK, PORT256_FN1),
+	PINMUX_DATA(TRST2_MARK, PORT256_FN2),
+	PINMUX_DATA(SDHIWP0_MARK, PORT257_FN1),
+	PINMUX_DATA(EDBGREQ2_MARK, PORT257_FN2),
+	PINMUX_DATA(SDHICLK1_MARK, PORT258_FN1),
+	PINMUX_DATA(TCK3_SWCLK_MC1_MARK, PORT258_FN2),
+	PINMUX_DATA(SDHID1_0_MARK, PORT259_FN1),
+	PINMUX_DATA(M11_SLCD_SO2_MARK, PORT259_FN2),
+	PINMUX_DATA(TS_SPSYNC2_MARK, PORT259_FN3),
+	PINMUX_DATA(TMS3_SWDIO_MC1_MARK, PORT259_FN4),
+	PINMUX_DATA(SDHID1_1_MARK, PORT260_FN1),
+	PINMUX_DATA(M9_SLCD_A02_MARK, PORT260_FN2),
+	PINMUX_DATA(TS_SDAT2_MARK, PORT260_FN3),
+	PINMUX_DATA(TDO3_SWO0_MC1_MARK, PORT260_FN4),
+	PINMUX_DATA(SDHID1_2_MARK, PORT261_FN1),
+	PINMUX_DATA(M10_SLCD_CK2_MARK, PORT261_FN2),
+	PINMUX_DATA(TS_SDEN2_MARK, PORT261_FN3),
+	PINMUX_DATA(TDI3_MARK, PORT261_FN4),
+	PINMUX_DATA(SDHID1_3_MARK, PORT262_FN1),
+	PINMUX_DATA(M12_SLCD_CE2_MARK, PORT262_FN2),
+	PINMUX_DATA(TS_SCK2_MARK, PORT262_FN3),
+	PINMUX_DATA(RTCK3_SWO1_MC1_MARK, PORT262_FN4),
+	PINMUX_DATA(SDHICMD1_MARK, PORT263_FN1),
+	PINMUX_DATA(TRST3_MARK, PORT263_FN2),
+	PINMUX_DATA(RESETOUTS_MARK, PORT264_FN1),
+};
+
+#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
+#define GPIO_PORT_265() _265(_GPIO_PORT, , unused)
+#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
+
+static struct pinmux_gpio pinmux_gpios[] = {
+	/* 55-1 -> 55-5 (GPIO) */
+	GPIO_PORT_265(),
+
+	/* Special Pull-up / Pull-down Functions */
+	GPIO_FN(PORT66_KEYIN0_PU), GPIO_FN(PORT67_KEYIN1_PU),
+	GPIO_FN(PORT68_KEYIN2_PU), GPIO_FN(PORT69_KEYIN3_PU),
+	GPIO_FN(PORT70_KEYIN4_PU), GPIO_FN(PORT71_KEYIN5_PU),
+	GPIO_FN(PORT72_KEYIN6_PU),
+
+	/* 55-1 (FN) */
+	GPIO_FN(VBUS_0),
+	GPIO_FN(CPORT0),
+	GPIO_FN(CPORT1),
+	GPIO_FN(CPORT2),
+	GPIO_FN(CPORT3),
+	GPIO_FN(CPORT4),
+	GPIO_FN(CPORT5),
+	GPIO_FN(CPORT6),
+	GPIO_FN(CPORT7),
+	GPIO_FN(CPORT8),
+	GPIO_FN(CPORT9),
+	GPIO_FN(CPORT10),
+	GPIO_FN(CPORT11), GPIO_FN(SIN2),
+	GPIO_FN(CPORT12), GPIO_FN(XCTS2),
+	GPIO_FN(CPORT13), GPIO_FN(RFSPO4),
+	GPIO_FN(CPORT14), GPIO_FN(RFSPO5),
+	GPIO_FN(CPORT15), GPIO_FN(SCIFA0_SCK), GPIO_FN(GPS_AGC2),
+	GPIO_FN(CPORT16), GPIO_FN(SCIFA0_TXD), GPIO_FN(GPS_AGC3),
+	GPIO_FN(CPORT17_IC_OE), GPIO_FN(SOUT2),
+	GPIO_FN(CPORT18), GPIO_FN(XRTS2), GPIO_FN(PORT19_VIO_CKO2),
+	GPIO_FN(CPORT19_MPORT1),
+	GPIO_FN(CPORT20), GPIO_FN(RFSPO6),
+	GPIO_FN(CPORT21), GPIO_FN(STATUS0),
+	GPIO_FN(CPORT22), GPIO_FN(STATUS1),
+	GPIO_FN(CPORT23), GPIO_FN(STATUS2), GPIO_FN(RFSPO7),
+	GPIO_FN(B_SYNLD1),
+	GPIO_FN(B_SYNLD2), GPIO_FN(SYSENMSK),
+	GPIO_FN(XMAINPS),
+	GPIO_FN(XDIVPS),
+	GPIO_FN(XIDRST),
+	GPIO_FN(IDCLK), GPIO_FN(IC_DP),
+	GPIO_FN(IDIO), GPIO_FN(IC_DM),
+	GPIO_FN(SOUT1), GPIO_FN(SCIFA4_TXD), GPIO_FN(M02_BERDAT),
+	GPIO_FN(SIN1), GPIO_FN(SCIFA4_RXD), GPIO_FN(XWUP),
+	GPIO_FN(XRTS1), GPIO_FN(SCIFA4_RTS), GPIO_FN(M03_BERCLK),
+	GPIO_FN(XCTS1), GPIO_FN(SCIFA4_CTS),
+	GPIO_FN(PCMCLKO),
+	GPIO_FN(SYNC8KO),
+
+	/* 55-2 (FN) */
+	GPIO_FN(DNPCM_A),
+	GPIO_FN(UPPCM_A),
+	GPIO_FN(VACK),
+	GPIO_FN(XTALB1L),
+	GPIO_FN(GPS_AGC1), GPIO_FN(SCIFA0_RTS),
+	GPIO_FN(GPS_AGC4), GPIO_FN(SCIFA0_RXD),
+	GPIO_FN(GPS_PWRDOWN), GPIO_FN(SCIFA0_CTS),
+	GPIO_FN(GPS_IM),
+	GPIO_FN(GPS_IS),
+	GPIO_FN(GPS_QM),
+	GPIO_FN(GPS_QS),
+	GPIO_FN(FMSOCK), GPIO_FN(PORT49_IRDA_OUT), GPIO_FN(PORT49_IROUT),
+	GPIO_FN(FMSOOLR), GPIO_FN(BBIF2_TSYNC2), GPIO_FN(TPU2TO2),
+	GPIO_FN(IPORT3), GPIO_FN(FMSIOLR),
+	GPIO_FN(FMSOOBT), GPIO_FN(BBIF2_TSCK2), GPIO_FN(TPU2TO3),
+	GPIO_FN(OPORT1), GPIO_FN(FMSIOBT),
+	GPIO_FN(FMSOSLD), GPIO_FN(BBIF2_TXD2), GPIO_FN(OPORT2),
+	GPIO_FN(FMSOILR), GPIO_FN(PORT53_IRDA_IN), GPIO_FN(TPU3TO3),
+	GPIO_FN(OPORT3), GPIO_FN(FMSIILR),
+	GPIO_FN(FMSOIBT), GPIO_FN(PORT54_IRDA_FIRSEL), GPIO_FN(TPU3TO2),
+	GPIO_FN(FMSIIBT),
+	GPIO_FN(FMSISLD), GPIO_FN(MFG0_OUT1), GPIO_FN(TPU0TO0),
+	GPIO_FN(A0_EA0), GPIO_FN(BS),
+	GPIO_FN(A12_EA12), GPIO_FN(PORT58_VIO_CKOR), GPIO_FN(TPU4TO2),
+	GPIO_FN(A13_EA13), GPIO_FN(PORT59_IROUT), GPIO_FN(MFG0_OUT2),
+	GPIO_FN(TPU0TO1),
+	GPIO_FN(A14_EA14), GPIO_FN(PORT60_KEYOUT5),
+	GPIO_FN(A15_EA15), GPIO_FN(PORT61_KEYOUT4),
+	GPIO_FN(A16_EA16), GPIO_FN(PORT62_KEYOUT3), GPIO_FN(MSIOF0_SS1),
+	GPIO_FN(A17_EA17), GPIO_FN(PORT63_KEYOUT2), GPIO_FN(MSIOF0_TSYNC),
+	GPIO_FN(A18_EA18), GPIO_FN(PORT64_KEYOUT1), GPIO_FN(MSIOF0_TSCK),
+	GPIO_FN(A19_EA19), GPIO_FN(PORT65_KEYOUT0), GPIO_FN(MSIOF0_TXD),
+	GPIO_FN(A20_EA20), GPIO_FN(PORT66_KEYIN0), GPIO_FN(MSIOF0_RSCK),
+	GPIO_FN(A21_EA21), GPIO_FN(PORT67_KEYIN1), GPIO_FN(MSIOF0_RSYNC),
+	GPIO_FN(A22_EA22), GPIO_FN(PORT68_KEYIN2), GPIO_FN(MSIOF0_MCK0),
+	GPIO_FN(A23_EA23), GPIO_FN(PORT69_KEYIN3), GPIO_FN(MSIOF0_MCK1),
+	GPIO_FN(A24_EA24), GPIO_FN(PORT70_KEYIN4), GPIO_FN(MSIOF0_RXD),
+	GPIO_FN(A25_EA25), GPIO_FN(PORT71_KEYIN5), GPIO_FN(MSIOF0_SS2),
+	GPIO_FN(A26), GPIO_FN(PORT72_KEYIN6),
+	GPIO_FN(D0_ED0_NAF0),
+	GPIO_FN(D1_ED1_NAF1),
+	GPIO_FN(D2_ED2_NAF2),
+	GPIO_FN(D3_ED3_NAF3),
+	GPIO_FN(D4_ED4_NAF4),
+	GPIO_FN(D5_ED5_NAF5),
+	GPIO_FN(D6_ED6_NAF6),
+	GPIO_FN(D7_ED7_NAF7),
+	GPIO_FN(D8_ED8_NAF8),
+	GPIO_FN(D9_ED9_NAF9),
+	GPIO_FN(D10_ED10_NAF10),
+	GPIO_FN(D11_ED11_NAF11),
+	GPIO_FN(D12_ED12_NAF12),
+	GPIO_FN(D13_ED13_NAF13),
+	GPIO_FN(D14_ED14_NAF14),
+	GPIO_FN(D15_ED15_NAF15),
+	GPIO_FN(CS4),
+	GPIO_FN(CS5A), GPIO_FN(FMSICK),
+
+	/* 55-3 (FN) */
+	GPIO_FN(CS5B), GPIO_FN(FCE1),
+	GPIO_FN(CS6B), GPIO_FN(XCS2), GPIO_FN(CS6A), GPIO_FN(DACK0),
+	GPIO_FN(FCE0),
+	GPIO_FN(WAIT), GPIO_FN(DREQ0),
+	GPIO_FN(RD_XRD),
+	GPIO_FN(WE0_XWR0_FWE),
+	GPIO_FN(WE1_XWR1),
+	GPIO_FN(FRB),
+	GPIO_FN(CKO),
+	GPIO_FN(NBRSTOUT),
+	GPIO_FN(NBRST),
+	GPIO_FN(GPS_EPPSIN),
+	GPIO_FN(LATCHPULSE),
+	GPIO_FN(LTESIGNAL),
+	GPIO_FN(LEGACYSTATE),
+	GPIO_FN(TCKON),
+	GPIO_FN(VIO_VD), GPIO_FN(PORT128_KEYOUT0), GPIO_FN(IPORT0),
+	GPIO_FN(VIO_HD), GPIO_FN(PORT129_KEYOUT1), GPIO_FN(IPORT1),
+	GPIO_FN(VIO_D0), GPIO_FN(PORT130_KEYOUT2), GPIO_FN(PORT130_MSIOF2_RXD),
+	GPIO_FN(VIO_D1), GPIO_FN(PORT131_KEYOUT3), GPIO_FN(PORT131_MSIOF2_SS1),
+	GPIO_FN(VIO_D2), GPIO_FN(PORT132_KEYOUT4), GPIO_FN(PORT132_MSIOF2_SS2),
+	GPIO_FN(VIO_D3), GPIO_FN(PORT133_KEYOUT5),
+	GPIO_FN(PORT133_MSIOF2_TSYNC),
+	GPIO_FN(VIO_D4), GPIO_FN(PORT134_KEYIN0), GPIO_FN(PORT134_MSIOF2_TXD),
+	GPIO_FN(VIO_D5), GPIO_FN(PORT135_KEYIN1), GPIO_FN(PORT135_MSIOF2_TSCK),
+	GPIO_FN(VIO_D6), GPIO_FN(PORT136_KEYIN2),
+	GPIO_FN(VIO_D7), GPIO_FN(PORT137_KEYIN3),
+	GPIO_FN(VIO_D8), GPIO_FN(M9_SLCD_A01), GPIO_FN(PORT138_FSIAOMC),
+	GPIO_FN(VIO_D9), GPIO_FN(M10_SLCD_CK1), GPIO_FN(PORT139_FSIAOLR),
+	GPIO_FN(VIO_D10), GPIO_FN(M11_SLCD_SO1), GPIO_FN(TPU0TO2),
+	GPIO_FN(PORT140_FSIAOBT),
+	GPIO_FN(VIO_D11), GPIO_FN(M12_SLCD_CE1), GPIO_FN(TPU0TO3),
+	GPIO_FN(PORT141_FSIAOSLD),
+	GPIO_FN(VIO_D12), GPIO_FN(M13_BSW), GPIO_FN(PORT142_FSIACK),
+	GPIO_FN(VIO_D13), GPIO_FN(M14_GSW), GPIO_FN(PORT143_FSIAILR),
+	GPIO_FN(VIO_D14), GPIO_FN(M15_RSW), GPIO_FN(PORT144_FSIAIBT),
+	GPIO_FN(VIO_D15), GPIO_FN(TPU1TO3), GPIO_FN(PORT145_FSIAISLD),
+	GPIO_FN(VIO_CLK), GPIO_FN(PORT146_KEYIN4), GPIO_FN(IPORT2),
+	GPIO_FN(VIO_FIELD), GPIO_FN(PORT147_KEYIN5),
+	GPIO_FN(VIO_CKO), GPIO_FN(PORT148_KEYIN6),
+	GPIO_FN(A27), GPIO_FN(RDWR_XWE), GPIO_FN(MFG0_IN1),
+	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(SOUT3), GPIO_FN(SCIFA2_TXD1), GPIO_FN(MSIOF2_MCK0),
+	GPIO_FN(SIN3), GPIO_FN(SCIFA2_RXD1), GPIO_FN(MSIOF2_MCK1),
+	GPIO_FN(XRTS3), GPIO_FN(SCIFA2_RTS1), GPIO_FN(PORT156_MSIOF2_SS2),
+	GPIO_FN(XCTS3), GPIO_FN(SCIFA2_CTS1), GPIO_FN(PORT157_MSIOF2_RXD),
+
+	/* 55-4 (FN) */
+	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(SOUT0),
+	GPIO_FN(PORT161_SCIFB_CTS), GPIO_FN(PORT161_SCIFA5_CTS), GPIO_FN(XCTS0),
+	GPIO_FN(MFG3_IN2),
+	GPIO_FN(PORT162_SCIFB_RXD), GPIO_FN(PORT162_SCIFA5_RXD), GPIO_FN(SIN0),
+	GPIO_FN(MFG3_IN1),
+	GPIO_FN(PORT163_SCIFB_RTS), GPIO_FN(PORT163_SCIFA5_RTS), GPIO_FN(XRTS0),
+	GPIO_FN(MFG3_OUT1), GPIO_FN(TPU3TO0),
+	GPIO_FN(LCDD0), GPIO_FN(PORT192_KEYOUT0), GPIO_FN(EXT_CKI),
+	GPIO_FN(LCDD1), GPIO_FN(PORT193_KEYOUT1), GPIO_FN(PORT193_SCIFA5_CTS),
+	GPIO_FN(BBIF2_TSYNC1),
+	GPIO_FN(LCDD2), GPIO_FN(PORT194_KEYOUT2), GPIO_FN(PORT194_SCIFA5_RTS),
+	GPIO_FN(BBIF2_TSCK1),
+	GPIO_FN(LCDD3), GPIO_FN(PORT195_KEYOUT3), GPIO_FN(PORT195_SCIFA5_RXD),
+	GPIO_FN(BBIF2_TXD1),
+	GPIO_FN(LCDD4), GPIO_FN(PORT196_KEYOUT4), GPIO_FN(PORT196_SCIFA5_TXD),
+	GPIO_FN(LCDD5), GPIO_FN(PORT197_KEYOUT5), GPIO_FN(PORT197_SCIFA5_SCK),
+	GPIO_FN(MFG2_OUT2),
+	GPIO_FN(LCDD6),
+	GPIO_FN(LCDD7), GPIO_FN(TPU4TO1), GPIO_FN(MFG4_OUT2),
+	GPIO_FN(LCDD8), GPIO_FN(PORT200_KEYIN0), GPIO_FN(VIO_DR0),
+	GPIO_FN(D16),
+	GPIO_FN(LCDD9), GPIO_FN(PORT201_KEYIN1), GPIO_FN(VIO_DR1),
+	GPIO_FN(D17),
+	GPIO_FN(LCDD10), GPIO_FN(PORT202_KEYIN2), GPIO_FN(VIO_DR2),
+	GPIO_FN(D18),
+	GPIO_FN(LCDD11), GPIO_FN(PORT203_KEYIN3), GPIO_FN(VIO_DR3),
+	GPIO_FN(D19),
+	GPIO_FN(LCDD12), GPIO_FN(PORT204_KEYIN4), GPIO_FN(VIO_DR4),
+	GPIO_FN(D20),
+	GPIO_FN(LCDD13), GPIO_FN(PORT205_KEYIN5), GPIO_FN(VIO_DR5),
+	GPIO_FN(D21),
+	GPIO_FN(LCDD14), GPIO_FN(PORT206_KEYIN6), GPIO_FN(VIO_DR6),
+	GPIO_FN(D22),
+	GPIO_FN(LCDD15), GPIO_FN(PORT207_MSIOF0L_SS1), GPIO_FN(PORT207_KEYOUT0),
+	GPIO_FN(VIO_DR7), GPIO_FN(D23),
+	GPIO_FN(LCDD16), GPIO_FN(PORT208_MSIOF0L_SS2), GPIO_FN(PORT208_KEYOUT1),
+	GPIO_FN(VIO_VDR), GPIO_FN(D24),
+	GPIO_FN(LCDD17), GPIO_FN(PORT209_KEYOUT2), GPIO_FN(VIO_HDR),
+	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(PORT216_KEYOUT3),
+	GPIO_FN(VIO_CLKR),
+	GPIO_FN(LCDRD), GPIO_FN(DACK2), GPIO_FN(MSIOF0L_TSYNC),
+	GPIO_FN(LCDHSYN), GPIO_FN(LCDCS), GPIO_FN(LCDCS2), GPIO_FN(DACK3),
+	GPIO_FN(PORT218_VIO_CKOR), GPIO_FN(PORT218_KEYOUT4),
+	GPIO_FN(LCDDISP), GPIO_FN(LCDRS), GPIO_FN(DREQ3), GPIO_FN(MSIOF0L_TSCK),
+	GPIO_FN(LCDVSYN), GPIO_FN(LCDVSYN2), GPIO_FN(PORT220_KEYOUT5),
+	GPIO_FN(LCDLCLK), GPIO_FN(DREQ1), GPIO_FN(PWEN), GPIO_FN(MSIOF0L_RXD),
+	GPIO_FN(LCDDON), GPIO_FN(LCDDON2), GPIO_FN(DACK1), GPIO_FN(OVCN),
+	GPIO_FN(MSIOF0L_TXD),
+	GPIO_FN(SCIFA1_TXD), GPIO_FN(OVCN2),
+	GPIO_FN(EXTLP), GPIO_FN(SCIFA1_SCK), GPIO_FN(USBTERM),
+	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(PORT230_FSIAOMC),
+	GPIO_FN(MSIOF1_TSYNC), GPIO_FN(SCIFA2_CTS2), GPIO_FN(PORT231_FSIAOLR),
+	GPIO_FN(MSIOF1_TSCK), GPIO_FN(SCIFA2_SCK2), GPIO_FN(PORT232_FSIAOBT),
+	GPIO_FN(MSIOF1_RXD), GPIO_FN(SCIFA2_RXD2), GPIO_FN(GPS_VCOTRIG),
+	GPIO_FN(PORT233_FSIACK),
+	GPIO_FN(MSIOF1_RSCK), GPIO_FN(SCIFA2_RTS2), GPIO_FN(PORT234_FSIAOSLD),
+	GPIO_FN(MSIOF1_RSYNC), GPIO_FN(OPORT0), GPIO_FN(MFG1_IN2),
+	GPIO_FN(PORT235_FSIAILR),
+	GPIO_FN(MSIOF1_MCK0), GPIO_FN(I2C_SDA2), GPIO_FN(PORT236_FSIAIBT),
+	GPIO_FN(MSIOF1_MCK1), GPIO_FN(I2C_SCL2), GPIO_FN(PORT237_FSIAISLD),
+	GPIO_FN(MSIOF1_SS1), GPIO_FN(EDBGREQ3),
+
+	/* 55-5 (FN) */
+	GPIO_FN(MSIOF1_SS2),
+	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(PORT245_SCIFA5_RTS), GPIO_FN(MFG2_IN2),
+	GPIO_FN(PORT245_SCIFB_RTS),
+	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(PORT249_IROUT), GPIO_FN(MFG4_IN1),
+	GPIO_FN(SDHICLK0), GPIO_FN(TCK2_SWCLK_MC0),
+	GPIO_FN(SDHICD0),
+	GPIO_FN(SDHID0_0), GPIO_FN(TMS2_SWDIO_MC0),
+	GPIO_FN(SDHID0_1), GPIO_FN(TDO2_SWO0_MC0),
+	GPIO_FN(SDHID0_2), GPIO_FN(TDI2),
+	GPIO_FN(SDHID0_3), GPIO_FN(RTCK2_SWO1_MC0),
+	GPIO_FN(SDHICMD0), GPIO_FN(TRST2),
+	GPIO_FN(SDHIWP0), GPIO_FN(EDBGREQ2),
+	GPIO_FN(SDHICLK1), GPIO_FN(TCK3_SWCLK_MC1),
+	GPIO_FN(SDHID1_0), GPIO_FN(M11_SLCD_SO2), GPIO_FN(TS_SPSYNC2),
+	GPIO_FN(TMS3_SWDIO_MC1),
+	GPIO_FN(SDHID1_1), GPIO_FN(M9_SLCD_A02), GPIO_FN(TS_SDAT2),
+	GPIO_FN(TDO3_SWO0_MC1),
+	GPIO_FN(SDHID1_2), GPIO_FN(M10_SLCD_CK2), GPIO_FN(TS_SDEN2),
+	GPIO_FN(TDI3),
+	GPIO_FN(SDHID1_3), GPIO_FN(M12_SLCD_CE2), GPIO_FN(TS_SCK2),
+	GPIO_FN(RTCK3_SWO1_MC1),
+	GPIO_FN(SDHICMD1), GPIO_FN(TRST3),
+	GPIO_FN(RESETOUTS),
+};
+
+/* helper for top 4 bits in PORTnCR */
+#define PCRH(in, in_pd, in_pu, out)	\
+	0, (out), (in), 0,	\
+		0, 0, 0, 0,	\
+		0, 0, (in_pd), 0,	\
+		0, 0, (in_pu), 0
+
+#define PORTCR(nr, reg)	\
+	{ PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {	\
+			PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,	\
+				 PORT##nr##_IN_PU, PORT##nr##_OUT),	\
+				PORT##nr##_FN0, PORT##nr##_FN1,	\
+				PORT##nr##_FN2, PORT##nr##_FN3,	\
+				PORT##nr##_FN4, PORT##nr##_FN5,	\
+				PORT##nr##_FN6, PORT##nr##_FN7 }	\
+	}
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+	PORTCR(0, 0xe6050000), /* PORT0CR */
+	PORTCR(1, 0xe6050001), /* PORT1CR */
+	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, 0xe6050020), /* PORT32CR */
+	PORTCR(33, 0xe6050021), /* PORT33CR */
+	PORTCR(34, 0xe6050022), /* PORT34CR */
+	PORTCR(35, 0xe6050023), /* PORT35CR */
+	PORTCR(36, 0xe6050024), /* PORT36CR */
+	PORTCR(37, 0xe6050025), /* PORT37CR */
+	PORTCR(38, 0xe6050026), /* PORT38CR */
+	PORTCR(39, 0xe6050027), /* PORT39CR */
+
+	PORTCR(40, 0xe6050028), /* PORT40CR */
+	PORTCR(41, 0xe6050029), /* PORT41CR */
+	PORTCR(42, 0xe605002a), /* PORT42CR */
+	PORTCR(43, 0xe605002b), /* PORT43CR */
+	PORTCR(44, 0xe605002c), /* PORT44CR */
+	PORTCR(45, 0xe605002d), /* PORT45CR */
+	PORTCR(46, 0xe605002e), /* PORT46CR */
+	PORTCR(47, 0xe605002f), /* PORT47CR */
+	PORTCR(48, 0xe6050030), /* PORT48CR */
+	PORTCR(49, 0xe6050031), /* PORT49CR */
+
+	PORTCR(50, 0xe6050032), /* PORT50CR */
+	PORTCR(51, 0xe6050033), /* PORT51CR */
+	PORTCR(52, 0xe6050034), /* PORT52CR */
+	PORTCR(53, 0xe6050035), /* PORT53CR */
+	PORTCR(54, 0xe6050036), /* PORT54CR */
+	PORTCR(55, 0xe6050037), /* PORT55CR */
+	PORTCR(56, 0xe6050038), /* PORT56CR */
+	PORTCR(57, 0xe6050039), /* PORT57CR */
+	PORTCR(58, 0xe605003a), /* PORT58CR */
+	PORTCR(59, 0xe605003b), /* PORT59CR */
+
+	PORTCR(60, 0xe605003c), /* PORT60CR */
+	PORTCR(61, 0xe605003d), /* PORT61CR */
+	PORTCR(62, 0xe605003e), /* PORT62CR */
+	PORTCR(63, 0xe605003f), /* PORT63CR */
+	PORTCR(64, 0xe6050040), /* PORT64CR */
+	PORTCR(65, 0xe6050041), /* PORT65CR */
+	PORTCR(66, 0xe6050042), /* PORT66CR */
+	PORTCR(67, 0xe6050043), /* PORT67CR */
+	PORTCR(68, 0xe6050044), /* PORT68CR */
+	PORTCR(69, 0xe6050045), /* PORT69CR */
+
+	PORTCR(70, 0xe6050046), /* PORT70CR */
+	PORTCR(71, 0xe6050047), /* PORT71CR */
+	PORTCR(72, 0xe6050048), /* PORT72CR */
+	PORTCR(73, 0xe6050049), /* PORT73CR */
+	PORTCR(74, 0xe605004a), /* PORT74CR */
+	PORTCR(75, 0xe605004b), /* PORT75CR */
+	PORTCR(76, 0xe605004c), /* PORT76CR */
+	PORTCR(77, 0xe605004d), /* PORT77CR */
+	PORTCR(78, 0xe605004e), /* PORT78CR */
+	PORTCR(79, 0xe605004f), /* PORT79CR */
+
+	PORTCR(80, 0xe6050050), /* PORT80CR */
+	PORTCR(81, 0xe6050051), /* PORT81CR */
+	PORTCR(82, 0xe6050052), /* PORT82CR */
+	PORTCR(83, 0xe6050053), /* PORT83CR */
+	PORTCR(84, 0xe6050054), /* PORT84CR */
+	PORTCR(85, 0xe6050055), /* PORT85CR */
+	PORTCR(86, 0xe6050056), /* PORT86CR */
+	PORTCR(87, 0xe6050057), /* PORT87CR */
+	PORTCR(88, 0xe6050058), /* PORT88CR */
+	PORTCR(89, 0xe6050059), /* PORT89CR */
+
+	PORTCR(90, 0xe605005a), /* PORT90CR */
+	PORTCR(91, 0xe605005b), /* PORT91CR */
+	PORTCR(92, 0xe605005c), /* PORT92CR */
+	PORTCR(93, 0xe605005d), /* PORT93CR */
+	PORTCR(94, 0xe605005e), /* PORT94CR */
+	PORTCR(95, 0xe605005f), /* PORT95CR */
+	PORTCR(96, 0xe6050060), /* PORT96CR */
+	PORTCR(97, 0xe6050061), /* PORT97CR */
+	PORTCR(98, 0xe6050062), /* PORT98CR */
+	PORTCR(99, 0xe6050063), /* PORT99CR */
+
+	PORTCR(100, 0xe6050064), /* PORT100CR */
+	PORTCR(101, 0xe6050065), /* PORT101CR */
+	PORTCR(102, 0xe6050066), /* PORT102CR */
+	PORTCR(103, 0xe6050067), /* PORT103CR */
+	PORTCR(104, 0xe6050068), /* PORT104CR */
+	PORTCR(105, 0xe6050069), /* PORT105CR */
+	PORTCR(106, 0xe605006a), /* PORT106CR */
+	PORTCR(107, 0xe605006b), /* PORT107CR */
+	PORTCR(108, 0xe605006c), /* PORT108CR */
+	PORTCR(109, 0xe605006d), /* PORT109CR */
+
+	PORTCR(110, 0xe605006e), /* PORT110CR */
+	PORTCR(111, 0xe605006f), /* PORT111CR */
+	PORTCR(112, 0xe6050070), /* PORT112CR */
+	PORTCR(113, 0xe6050071), /* PORT113CR */
+	PORTCR(114, 0xe6050072), /* PORT114CR */
+	PORTCR(115, 0xe6050073), /* PORT115CR */
+	PORTCR(116, 0xe6050074), /* PORT116CR */
+	PORTCR(117, 0xe6050075), /* PORT117CR */
+	PORTCR(118, 0xe6050076), /* PORT118CR */
+
+	PORTCR(128, 0xe6051080), /* PORT128CR */
+	PORTCR(129, 0xe6051081), /* PORT129CR */
+
+	PORTCR(130, 0xe6051082), /* PORT130CR */
+	PORTCR(131, 0xe6051083), /* PORT131CR */
+	PORTCR(132, 0xe6051084), /* PORT132CR */
+	PORTCR(133, 0xe6051085), /* PORT133CR */
+	PORTCR(134, 0xe6051086), /* PORT134CR */
+	PORTCR(135, 0xe6051087), /* PORT135CR */
+	PORTCR(136, 0xe6051088), /* PORT136CR */
+	PORTCR(137, 0xe6051089), /* PORT137CR */
+	PORTCR(138, 0xe605108a), /* PORT138CR */
+	PORTCR(139, 0xe605108b), /* PORT139CR */
+
+	PORTCR(140, 0xe605108c), /* PORT140CR */
+	PORTCR(141, 0xe605108d), /* PORT141CR */
+	PORTCR(142, 0xe605108e), /* PORT142CR */
+	PORTCR(143, 0xe605108f), /* PORT143CR */
+	PORTCR(144, 0xe6051090), /* PORT144CR */
+	PORTCR(145, 0xe6051091), /* PORT145CR */
+	PORTCR(146, 0xe6051092), /* PORT146CR */
+	PORTCR(147, 0xe6051093), /* PORT147CR */
+	PORTCR(148, 0xe6051094), /* PORT148CR */
+	PORTCR(149, 0xe6051095), /* PORT149CR */
+
+	PORTCR(150, 0xe6051096), /* PORT150CR */
+	PORTCR(151, 0xe6051097), /* PORT151CR */
+	PORTCR(152, 0xe6051098), /* PORT152CR */
+	PORTCR(153, 0xe6051099), /* PORT153CR */
+	PORTCR(154, 0xe605109a), /* PORT154CR */
+	PORTCR(155, 0xe605109b), /* PORT155CR */
+	PORTCR(156, 0xe605109c), /* PORT156CR */
+	PORTCR(157, 0xe605109d), /* PORT157CR */
+	PORTCR(158, 0xe605109e), /* PORT158CR */
+	PORTCR(159, 0xe605109f), /* PORT159CR */
+
+	PORTCR(160, 0xe60510a0), /* PORT160CR */
+	PORTCR(161, 0xe60510a1), /* PORT161CR */
+	PORTCR(162, 0xe60510a2), /* PORT162CR */
+	PORTCR(163, 0xe60510a3), /* PORT163CR */
+	PORTCR(164, 0xe60510a4), /* 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, 0xe60520e0), /* PORT224CR */
+	PORTCR(225, 0xe60520e1), /* PORT225CR */
+	PORTCR(226, 0xe60520e2), /* PORT226CR */
+	PORTCR(227, 0xe60520e3), /* PORT227CR */
+	PORTCR(228, 0xe60520e4), /* PORT228CR */
+	PORTCR(229, 0xe60520e5), /* PORT229CR */
+
+	PORTCR(230, 0xe60520e6), /* PORT230CR */
+	PORTCR(231, 0xe60520e7), /* PORT231CR */
+	PORTCR(232, 0xe60520e8), /* PORT232CR */
+	PORTCR(233, 0xe60520e9), /* PORT233CR */
+	PORTCR(234, 0xe60520ea), /* PORT234CR */
+	PORTCR(235, 0xe60520eb), /* PORT235CR */
+	PORTCR(236, 0xe60520ec), /* PORT236CR */
+	PORTCR(237, 0xe60520ed), /* PORT237CR */
+	PORTCR(238, 0xe60520ee), /* PORT238CR */
+	PORTCR(239, 0xe60520ef), /* PORT239CR */
+
+	PORTCR(240, 0xe60520f0), /* PORT240CR */
+	PORTCR(241, 0xe60520f1), /* PORT241CR */
+	PORTCR(242, 0xe60520f2), /* PORT242CR */
+	PORTCR(243, 0xe60520f3), /* PORT243CR */
+	PORTCR(244, 0xe60520f4), /* PORT244CR */
+	PORTCR(245, 0xe60520f5), /* PORT245CR */
+	PORTCR(246, 0xe60520f6), /* PORT246CR */
+	PORTCR(247, 0xe60520f7), /* PORT247CR */
+	PORTCR(248, 0xe60520f8), /* PORT248CR */
+	PORTCR(249, 0xe60520f9), /* PORT249CR */
+
+	PORTCR(250, 0xe60520fa), /* PORT250CR */
+	PORTCR(251, 0xe60520fb), /* PORT251CR */
+	PORTCR(252, 0xe60520fc), /* PORT252CR */
+	PORTCR(253, 0xe60520fd), /* PORT253CR */
+	PORTCR(254, 0xe60520fe), /* PORT254CR */
+	PORTCR(255, 0xe60520ff), /* PORT255CR */
+	PORTCR(256, 0xe6052100), /* PORT256CR */
+	PORTCR(257, 0xe6052101), /* PORT257CR */
+	PORTCR(258, 0xe6052102), /* PORT258CR */
+	PORTCR(259, 0xe6052103), /* PORT259CR */
+
+	PORTCR(260, 0xe6052104), /* PORT260CR */
+	PORTCR(261, 0xe6052105), /* PORT261CR */
+	PORTCR(262, 0xe6052106), /* PORT262CR */
+	PORTCR(263, 0xe6052107), /* PORT263CR */
+	PORTCR(264, 0xe6052108), /* PORT264CR */
+
+	{ PINMUX_CFG_REG("MSELBCR", 0xe6058024, 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, 0, 0, 0, 0,
+			MSELBCR_MSEL17_0, MSELBCR_MSEL17_1,
+			MSELBCR_MSEL16_0, MSELBCR_MSEL16_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, 0, 0, 0, 0, 0, 0, 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("PORTL063_032DR", 0xe6054004, 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("PORTL095_064DR", 0xe6054008, 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("PORTD127_096DR", 0xe605400C, 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("PORTD159_128DR", 0xe6055000, 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", 0xe6055004, 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", 0xe6056000, 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", 0xe6056004, 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", 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, PORT264_DATA,
+			PORT263_DATA, PORT262_DATA, PORT261_DATA, PORT260_DATA,
+			PORT259_DATA, PORT258_DATA, PORT257_DATA, PORT256_DATA }
+	},
+	{ },
+};
+
+static struct pinmux_info sh7377_pinmux_info = {
+	.name = "sh7377_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_RESETOUTS,
+
+	.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 sh7377_pinmux_init(void)
+{
+	register_pinmux(&sh7377_pinmux_info);
+}
diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c
new file mode 100644
index 0000000..eca9071
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-sh7367.c
@@ -0,0 +1,198 @@
+/*
+ * sh7367 processor support
+ *
+ * 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_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_SCIF,
+	.irqs		= { 80, 80, 80, 80 },
+};
+
+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_SCIF,
+	.irqs           = { 81, 81, 81, 81 },
+};
+
+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_SCIF,
+	.irqs           = { 82, 82, 82, 82 },
+};
+
+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_SCIF,
+	.irqs           = { 83, 83, 83, 83 },
+};
+
+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_SCIF,
+	.irqs           = { 89, 89, 89, 89 },
+};
+
+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_SCIF,
+	.irqs           = { 90, 90, 90, 90 },
+};
+
+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	= 0xe6c30000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs           = { 91, 91, 91, 91 },
+};
+
+static struct platform_device scif6_device = {
+	.name		= "sh-sci",
+	.id		= 6,
+	.dev		= {
+		.platform_data	= &scif6_platform_data,
+	},
+};
+
+static struct sh_timer_config cmt10_platform_data = {
+	.name = "CMT10",
+	.channel_offset = 0x10,
+	.timer_bit = 0,
+	.clk = "r_clk",
+	.clockevent_rating = 125,
+	.clocksource_rating = 125,
+};
+
+static struct resource cmt10_resources[] = {
+	[0] = {
+		.name	= "CMT10",
+		.start	= 0xe6138010,
+		.end	= 0xe613801b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 72,
+		.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),
+};
+
+static struct platform_device *sh7367_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
+	&scif6_device,
+	&cmt10_device,
+};
+
+void __init sh7367_add_standard_devices(void)
+{
+	platform_add_devices(sh7367_early_devices,
+			     ARRAY_SIZE(sh7367_early_devices));
+}
+
+#define SYMSTPCR2 0xe6158048
+#define SYMSTPCR2_CMT1 (1 << 29)
+
+void __init sh7367_add_early_devices(void)
+{
+	/* enable clock to CMT1 */
+	__raw_writel(__raw_readl(SYMSTPCR2) & ~SYMSTPCR2_CMT1, SYMSTPCR2);
+
+	early_platform_add_devices(sh7367_early_devices,
+				   ARRAY_SIZE(sh7367_early_devices));
+}
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
new file mode 100644
index 0000000..1d11532
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -0,0 +1,199 @@
+/*
+ * sh7372 processor support
+ *
+ * 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_SCIF,
+	.irqs		= { 80, 80, 80, 80 },
+};
+
+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_SCIF,
+	.irqs           = { 81, 81, 81, 81 },
+};
+
+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_SCIF,
+	.irqs           = { 82, 82, 82, 82 },
+};
+
+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_SCIF,
+	.irqs           = { 83, 83, 83, 83 },
+};
+
+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_SCIF,
+	.irqs           = { 89, 89, 89, 89 },
+};
+
+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_SCIF,
+	.irqs           = { 90, 90, 90, 90 },
+};
+
+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	= 0xe6c30000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs           = { 91, 91, 91, 91 },
+};
+
+static struct platform_device scif6_device = {
+	.name		= "sh-sci",
+	.id		= 6,
+	.dev		= {
+		.platform_data	= &scif6_platform_data,
+	},
+};
+
+static struct sh_timer_config cmt10_platform_data = {
+	.name = "CMT10",
+	.channel_offset = 0x10,
+	.timer_bit = 0,
+	.clk = "r_clk",
+	.clockevent_rating = 125,
+	.clocksource_rating = 125,
+};
+
+static struct resource cmt10_resources[] = {
+	[0] = {
+		.name	= "CMT10",
+		.start	= 0xe6138010,
+		.end	= 0xe613801b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 72,
+		.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),
+};
+
+static struct platform_device *sh7372_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
+	&scif6_device,
+	&cmt10_device,
+};
+
+void __init sh7372_add_standard_devices(void)
+{
+	platform_add_devices(sh7372_early_devices,
+			    ARRAY_SIZE(sh7372_early_devices));
+}
+
+#define SMSTPCR3 0xe615013c
+#define SMSTPCR3_CMT1 (1 << 29)
+
+void __init sh7372_add_early_devices(void)
+{
+	/* enable clock to CMT1 */
+	__raw_writel(__raw_readl(SMSTPCR3) & ~SMSTPCR3_CMT1, SMSTPCR3);
+
+	early_platform_add_devices(sh7372_early_devices,
+				   ARRAY_SIZE(sh7372_early_devices));
+}
diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c
new file mode 100644
index 0000000..60e3777
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-sh7377.c
@@ -0,0 +1,215 @@
+/*
+ * sh7377 processor support
+ *
+ * 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_SCIF,
+	.irqs		= { 80, 80, 80, 80 },
+};
+
+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_SCIF,
+	.irqs           = { 81, 81, 81, 81 },
+};
+
+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_SCIF,
+	.irqs           = { 82, 82, 82, 82 },
+};
+
+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_SCIF,
+	.irqs           = { 83, 83, 83, 83 },
+};
+
+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_SCIF,
+	.irqs           = { 89, 89, 89, 89 },
+};
+
+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_SCIF,
+	.irqs           = { 90, 90, 90, 90 },
+};
+
+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_SCIF,
+	.irqs           = { 196, 196, 196, 196 },
+};
+
+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	= 0xe6c30000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs           = { 91, 91, 91, 91 },
+};
+
+static struct platform_device scif7_device = {
+	.name		= "sh-sci",
+	.id		= 7,
+	.dev		= {
+		.platform_data	= &scif7_platform_data,
+	},
+};
+
+static struct sh_timer_config cmt10_platform_data = {
+	.name = "CMT10",
+	.channel_offset = 0x10,
+	.timer_bit = 0,
+	.clk = "r_clk",
+	.clockevent_rating = 125,
+	.clocksource_rating = 125,
+};
+
+static struct resource cmt10_resources[] = {
+	[0] = {
+		.name	= "CMT10",
+		.start	= 0xe6138010,
+		.end	= 0xe613801b,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 72,
+		.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),
+};
+
+static struct platform_device *sh7377_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
+	&scif6_device,
+	&scif7_device,
+	&cmt10_device,
+};
+
+void __init sh7377_add_standard_devices(void)
+{
+	platform_add_devices(sh7377_early_devices,
+			    ARRAY_SIZE(sh7377_early_devices));
+}
+
+#define SMSTPCR3 0xe615013c
+#define SMSTPCR3_CMT1 (1 << 29)
+
+void __init sh7377_add_early_devices(void)
+{
+	/* enable clock to CMT1 */
+	__raw_writel(__raw_readl(SMSTPCR3) & ~SMSTPCR3_CMT1, SMSTPCR3);
+
+	early_platform_add_devices(sh7377_early_devices,
+				   ARRAY_SIZE(sh7377_early_devices));
+}
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
new file mode 100644
index 0000000..895794b
--- /dev/null
+++ b/arch/arm/mach-shmobile/timer.c
@@ -0,0 +1,46 @@
+/*
+ * SH-Mobile Timer
+ *
+ * Copyright (C) 2010  Magnus Damm
+ * Copyright (C) 2002 - 2009  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
+ * 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/platform_device.h>
+#include <asm/mach/time.h>
+
+static void __init shmobile_late_time_init(void)
+{
+	/*
+	 * Make sure all compiled-in early timers register themselves.
+	 *
+	 * Run probe() for two "earlytimer" devices, these will be the
+	 * clockevents and clocksource devices respectively. In the event
+	 * that only a clockevents device is available, we -ENODEV on the
+	 * clocksource and the jiffies clocksource is used transparently
+	 * instead. No error handling is necessary here.
+	 */
+	early_platform_driver_register_all("earlytimer");
+	early_platform_driver_probe("earlytimer", 2, 0);
+}
+
+static void __init shmobile_timer_init(void)
+{
+	late_time_init = shmobile_late_time_init;
+}
+
+struct sys_timer shmobile_timer = {
+	.init		= shmobile_timer_init,
+};
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 01b5031..5f34eb6 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -358,7 +358,7 @@
 	/*
 	 * The AVE3e requires two regions of 256MB that it considers
 	 * "invisible". The hardware will not be able to access these
-	 * adresses, so they should never point to system RAM.
+	 * addresses, so they should never point to system RAM.
 	 */
 	{
 		.name  = "AVE3e Reserved 0",
@@ -1596,7 +1596,7 @@
 /*
  * Some devices and their resources require reserved physical memory from
  * the end of the available RAM. This function traverses the list of devices
- * and assigns actual adresses to these.
+ * and assigns actual addresses to these.
  */
 static void __init u300_assign_physmem(void)
 {
diff --git a/arch/arm/mach-u300/include/mach/coh901318.h b/arch/arm/mach-u300/include/mach/coh901318.h
index f4cfee9..b8155b4 100644
--- a/arch/arm/mach-u300/include/mach/coh901318.h
+++ b/arch/arm/mach-u300/include/mach/coh901318.h
@@ -53,7 +53,7 @@
  * struct coh_dma_channel - dma channel base
  * @name: ascii name of dma channel
  * @number: channel id number
- * @desc_nbr_max: number of preallocated descriptortors
+ * @desc_nbr_max: number of preallocated descriptors
  * @priority_high: prio of channel, 0 low otherwise high.
  * @param: configuration parameters
  * @dev_addr: physical address of periphal connected to channel
diff --git a/arch/arm/mach-u300/include/mach/debug-macro.S b/arch/arm/mach-u300/include/mach/debug-macro.S
index ca4a028..92c1242 100644
--- a/arch/arm/mach-u300/include/mach/debug-macro.S
+++ b/arch/arm/mach-u300/include/mach/debug-macro.S
@@ -11,7 +11,7 @@
 #include <mach/hardware.h>
 
 	.macro	addruart, rx, tmp
-	/* If we move the adress using MMU, use this. */
+	/* If we move the address using MMU, use this. */
 	mrc	p15, 0, \rx, c1, c0
 	tst	\rx, #1			@ MMU enabled?
 	ldreq	\rx,	  = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address
diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h
index 6da6502..04ea836 100644
--- a/arch/arm/mach-ux500/include/mach/hardware.h
+++ b/arch/arm/mach-ux500/include/mach/hardware.h
@@ -68,12 +68,12 @@
 #define U8500_PKAM_BASE		(U8500_PER6_BASE + 0x2000)
 #define U8500_CRYPTO0_BASE	(U8500_PER6_BASE + 0xa000)
 #define U8500_CRYPTO1_BASE	(U8500_PER6_BASE + 0xb000)
-#define U8500_CLKRST6_BASE	(U8500_PER7_BASE + 0xf000)
+#define U8500_CLKRST6_BASE	(U8500_PER6_BASE + 0xf000)
 
 /* per5 base addressess */
 #define U8500_USBOTG_BASE	(U8500_PER5_BASE + 0x00000)
 #define U8500_GPIO5_BASE	(U8500_PER5_BASE + 0x1e000)
-#define U8500_CLKRST5_BASE	(U8500_PER7_BASE + 0x1f000)
+#define U8500_CLKRST5_BASE	(U8500_PER5_BASE + 0x1f000)
 
 /* per4 base addressess */
 #define U8500_BACKUPRAM0_BASE	(U8500_PER4_BASE + 0x0000)
@@ -95,7 +95,7 @@
 #define U8500_UART2_BASE	(U8500_PER3_BASE + 0x7000)
 #define U8500_SDI5_BASE		(U8500_PER3_BASE + 0x8000)
 #define U8500_GPIO3_BASE	(U8500_PER3_BASE + 0xe000)
-#define U8500_CLKRST3_BASE	(U8500_PER7_BASE + 0xf000)
+#define U8500_CLKRST3_BASE	(U8500_PER3_BASE + 0xf000)
 
 /* per2 base addressess */
 #define U8500_I2C3_BASE		(U8500_PER2_BASE + 0x0000)
@@ -123,7 +123,7 @@
 #define U8500_SPI3_BASE		(U8500_PER1_BASE + 0x9000)
 #define U8500_SLIM0_BASE	(U8500_PER1_BASE + 0xa000)
 #define U8500_GPIO1_BASE	(U8500_PER1_BASE + 0xe000)
-#define U8500_CLKRST1_BASE	(U8500_PER2_BASE + 0xf000)
+#define U8500_CLKRST1_BASE	(U8500_PER1_BASE + 0xf000)
 
 /* ST-Ericsson modified pl022 id */
 #define SSP_PER_ID		0x01080022
diff --git a/arch/arm/mach-w90x900/cpu.h b/arch/arm/mach-w90x900/cpu.h
index 4d58ba1..f8730b6 100644
--- a/arch/arm/mach-w90x900/cpu.h
+++ b/arch/arm/mach-w90x900/cpu.h
@@ -57,3 +57,4 @@
 extern struct platform_device nuc900_device_kpi;
 extern struct platform_device nuc900_device_rtc;
 extern struct platform_device nuc900_device_ts;
+extern struct platform_device nuc900_device_lcd;
diff --git a/arch/arm/mach-w90x900/dev.c b/arch/arm/mach-w90x900/dev.c
index ec711f4..4887612 100644
--- a/arch/arm/mach-w90x900/dev.c
+++ b/arch/arm/mach-w90x900/dev.c
@@ -34,6 +34,7 @@
 #include <mach/regs-serial.h>
 #include <mach/nuc900_spi.h>
 #include <mach/map.h>
+#include <mach/fb.h>
 
 #include "cpu.h"
 
@@ -380,6 +381,47 @@
 	.resource	= nuc900_kpi_resource,
 };
 
+#ifdef CONFIG_FB_NUC900
+
+static struct resource nuc900_lcd_resource[] = {
+	[0] = {
+		.start = W90X900_PA_LCD,
+		.end   = W90X900_PA_LCD + W90X900_SZ_LCD - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_LCD,
+		.end   = IRQ_LCD,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static u64 nuc900_device_lcd_dmamask = -1;
+struct platform_device nuc900_device_lcd = {
+	.name             = "nuc900-lcd",
+	.id               = -1,
+	.num_resources    = ARRAY_SIZE(nuc900_lcd_resource),
+	.resource         = nuc900_lcd_resource,
+	.dev              = {
+		.dma_mask               = &nuc900_device_lcd_dmamask,
+		.coherent_dma_mask      = -1,
+	}
+};
+
+void  nuc900_fb_set_platdata(struct nuc900fb_mach_info *pd)
+{
+	struct nuc900fb_mach_info *npd;
+
+	npd = kmalloc(sizeof(*npd), GFP_KERNEL);
+	if (npd) {
+		memcpy(npd, pd, sizeof(*npd));
+		nuc900_device_lcd.dev.platform_data = npd;
+	} else {
+		printk(KERN_ERR "no memory for LCD platform data\n");
+	}
+}
+#endif
+
 /*Here should be your evb resourse,such as LCD*/
 
 static struct platform_device *nuc900_public_dev[] __initdata = {
diff --git a/arch/arm/mach-w90x900/include/mach/fb.h b/arch/arm/mach-w90x900/include/mach/fb.h
new file mode 100644
index 0000000..cec5ece
--- /dev/null
+++ b/arch/arm/mach-w90x900/include/mach/fb.h
@@ -0,0 +1,83 @@
+/* linux/include/asm/arch-nuc900/fb.h
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Changelog:
+ *
+ *   2008/08/26     vincen.zswan modify this file for LCD.
+ */
+
+#ifndef __ASM_ARM_FB_H
+#define __ASM_ARM_FB_H
+
+
+
+/* LCD Controller Hardware Desc */
+struct nuc900fb_hw {
+	unsigned int lcd_dccs;
+	unsigned int lcd_device_ctrl;
+	unsigned int lcd_mpulcd_cmd;
+	unsigned int lcd_int_cs;
+	unsigned int lcd_crtc_size;
+	unsigned int lcd_crtc_dend;
+	unsigned int lcd_crtc_hr;
+	unsigned int lcd_crtc_hsync;
+	unsigned int lcd_crtc_vr;
+	unsigned int lcd_va_baddr0;
+	unsigned int lcd_va_baddr1;
+	unsigned int lcd_va_fbctrl;
+	unsigned int lcd_va_scale;
+	unsigned int lcd_va_test;
+	unsigned int lcd_va_win;
+	unsigned int lcd_va_stuff;
+};
+
+/* LCD Display Description */
+struct nuc900fb_display {
+	/* LCD Image type */
+	unsigned type;
+
+	/* LCD Screen Size */
+	unsigned short width;
+	unsigned short height;
+
+	/* LCD Screen Info */
+	unsigned short xres;
+	unsigned short yres;
+	unsigned short bpp;
+
+	unsigned long pixclock;
+	unsigned short left_margin;
+	unsigned short right_margin;
+	unsigned short hsync_len;
+	unsigned short upper_margin;
+	unsigned short lower_margin;
+	unsigned short vsync_len;
+
+	/* hardware special register value */
+	unsigned int dccs;
+	unsigned int devctl;
+	unsigned int fbctrl;
+	unsigned int scale;
+};
+
+struct nuc900fb_mach_info {
+	struct nuc900fb_display *displays;
+	unsigned num_displays;
+	unsigned default_display;
+	/* GPIO Setting  Info */
+	unsigned gpio_dir;
+	unsigned gpio_dir_mask;
+	unsigned gpio_data;
+	unsigned gpio_data_mask;
+};
+
+extern void __init nuc900_fb_set_platdata(struct nuc900fb_mach_info *);
+
+#endif /* __ASM_ARM_FB_H */
diff --git a/arch/arm/mach-w90x900/include/mach/regs-ldm.h b/arch/arm/mach-w90x900/include/mach/regs-ldm.h
new file mode 100644
index 0000000..e9d480a
--- /dev/null
+++ b/arch/arm/mach-w90x900/include/mach/regs-ldm.h
@@ -0,0 +1,253 @@
+/*
+ * arch/arm/mach-w90x900/include/mach/regs-serial.h
+ *
+ * Copyright (c) 2009 Nuvoton technology corporation
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *  Description:
+ *     Nuvoton Display, LCM Register list
+ *  Author:  Wang Qiang (rurality.linux@gmail.com) 2009/12/11
+ *
+ */
+
+
+#ifndef __ASM_ARM_W90X900_REGS_LDM_H
+#define __ASM_ARM_W90X900_REGS_LDM_H
+
+#include <mach/map.h>
+
+/* Display Controller Control/Status Register */
+#define REG_LCM_DCCS			(0x00)
+
+#define LCM_DCCS_ENG_RST		(1 << 0)
+#define LCM_DCCS_VA_EN			(1 << 1)
+#define LCM_DCCS_OSD_EN			(1 << 2)
+#define LCM_DCCS_DISP_OUT_EN		(1 << 3)
+#define LCM_DCCS_DISP_INT_EN		(1 << 4)
+#define LCM_DCCS_CMD_ON			(1 << 5)
+#define LCM_DCCS_FIELD_INTR		(1 << 6)
+#define LCM_DCCS_SINGLE			(1 << 7)
+
+enum LCM_DCCS_VA_SRC {
+	LCM_DCCS_VA_SRC_YUV422		= (0 << 8),
+	LCM_DCCS_VA_SRC_YCBCR422	= (1 << 8),
+	LCM_DCCS_VA_SRC_RGB888		= (2 << 8),
+	LCM_DCCS_VA_SRC_RGB666		= (3 << 8),
+	LCM_DCCS_VA_SRC_RGB565		= (4 << 8),
+	LCM_DCCS_VA_SRC_RGB444LOW	= (5 << 8),
+	LCM_DCCS_VA_SRC_RGB444HIGH 	= (7 << 8)
+};
+
+
+/* Display Device Control Register */
+#define REG_LCM_DEV_CTRL		(0x04)
+
+enum LCM_DEV_CTRL_SWAP_YCbCr {
+	LCM_DEV_CTRL_SWAP_UYVY		= (0 << 1),
+	LCM_DEV_CTRL_SWAP_YUYV		= (1 << 1),
+	LCM_DEV_CTRL_SWAP_VYUY		= (2 << 1),
+	LCM_DEV_CTRL_SWAP_YVYU		= (3 << 1)
+};
+
+enum LCM_DEV_CTRL_RGB_SHIFT {
+	LCM_DEV_CTRL_RGB_SHIFT_NOT 	= (0 << 3),
+	LCM_DEV_CTRL_RGB_SHIFT_ONECYCLE = (1 << 3),
+	LCM_DEV_CTRL_RGB_SHIFT_TWOCYCLE = (2 << 3),
+	LCM_DEV_CTRL_RGB_SHIFT_NOT_DEF	= (3 << 3)
+};
+
+enum LCM_DEV_CTRL_DEVICE {
+	LCM_DEV_CTRL_DEVICE_YUV422	= (0 << 5),
+	LCM_DEV_CTRL_DEVICE_YUV444	= (1 << 5),
+	LCM_DEV_CTRL_DEVICE_UNIPAC	= (4 << 5),
+	LCM_DEV_CTRL_DEVICE_SEIKO_EPSON	= (5 << 5),
+	LCM_DEV_CTRL_DEVICE_HIGH_COLOR	= (6 << 5),
+	LCM_DEV_CTRL_DEVICE_MPU		= (7 << 5)
+};
+
+#define LCM_DEV_CTRL_LCD_DDA		(8)
+#define LCM_DEV_CTRL_YUV2CCIR		(16)
+
+enum LCM_DEV_CTRL_LCD_SEL {
+	LCM_DEV_CTRL_LCD_SEL_RGB_GBR	= (0 << 17),
+	LCM_DEV_CTRL_LCD_SEL_BGR_RBG	= (1 << 17),
+	LCM_DEV_CTRL_LCD_SEL_GBR_RGB	= (2 << 17),
+	LCM_DEV_CTRL_LCD_SEL_RBG_BGR	= (3 << 17)
+};
+
+enum LCM_DEV_CTRL_FAL_D {
+	LCM_DEV_CTRL_FAL_D_FALLING	= (0 << 19),
+	LCM_DEV_CTRL_FAL_D_RISING	= (1 << 19),
+};
+
+enum LCM_DEV_CTRL_H_POL {
+	LCM_DEV_CTRL_H_POL_LOW		= (0 << 20),
+	LCM_DEV_CTRL_H_POL_HIGH		= (1 << 20),
+};
+
+enum LCM_DEV_CTRL_V_POL {
+	LCM_DEV_CTRL_V_POL_LOW		= (0 << 21),
+	LCM_DEV_CTRL_V_POL_HIGH		= (1 << 21),
+};
+
+enum LCM_DEV_CTRL_VR_LACE {
+	LCM_DEV_CTRL_VR_LACE_NINTERLACE	= (0 << 22),
+	LCM_DEV_CTRL_VR_LACE_INTERLACE	= (1 << 22),
+};
+
+enum LCM_DEV_CTRL_LACE {
+	LCM_DEV_CTRL_LACE_NINTERLACE	= (0 << 23),
+	LCM_DEV_CTRL_LACE_INTERLACE	= (1 << 23),
+};
+
+enum LCM_DEV_CTRL_RGB_SCALE {
+	LCM_DEV_CTRL_RGB_SCALE_4096 	= (0 << 24),
+	LCM_DEV_CTRL_RGB_SCALE_65536 	= (1 << 24),
+	LCM_DEV_CTRL_RGB_SCALE_262144 	= (2 << 24),
+	LCM_DEV_CTRL_RGB_SCALE_16777216 = (3 << 24),
+};
+
+enum LCM_DEV_CTRL_DBWORD {
+	LCM_DEV_CTRL_DBWORD_HALFWORD	= (0 << 26),
+	LCM_DEV_CTRL_DBWORD_FULLWORD	= (1 << 26),
+};
+
+enum LCM_DEV_CTRL_MPU68 {
+	LCM_DEV_CTRL_MPU68_80_SERIES	= (0 << 27),
+	LCM_DEV_CTRL_MPU68_68_SERIES	= (1 << 27),
+};
+
+enum LCM_DEV_CTRL_DE_POL {
+	LCM_DEV_CTRL_DE_POL_HIGH	= (0 << 28),
+	LCM_DEV_CTRL_DE_POL_LOW		= (1 << 28),
+};
+
+#define LCM_DEV_CTRL_CMD16		(29)
+#define LCM_DEV_CTRL_CM16t18		(30)
+#define LCM_DEV_CTRL_CMD_LOW		(31)
+
+/* MPU-Interface LCD Write Command */
+#define REG_LCM_MPU_CMD			(0x08)
+
+/* Interrupt Control/Status Register */
+#define REG_LCM_INT_CS			(0x0c)
+#define LCM_INT_CS_DISP_F_EN		(1 << 0)
+#define LCM_INT_CS_UNDERRUN_EN   	(1 << 1)
+#define LCM_INT_CS_BUS_ERROR_INT 	(1 << 28)
+#define LCM_INT_CS_UNDERRUN_INT  	(1 << 29)
+#define LCM_INT_CS_DISP_F_STATUS 	(1 << 30)
+#define LCM_INT_CS_DISP_F_INT		(1 << 31)
+
+/* CRTC Display Size Control Register */
+#define REG_LCM_CRTC_SIZE		(0x10)
+#define LCM_CRTC_SIZE_VTTVAL(x)		((x) << 16)
+#define LCM_CRTC_SIZE_HTTVAL(x)		((x) << 0)
+
+/* CRTC Display Enable End */
+#define REG_LCM_CRTC_DEND		(0x14)
+#define LCM_CRTC_DEND_VDENDVAL(x)	((x) << 16)
+#define LCM_CRTC_DEND_HDENDVAL(x)	((x) << 0)
+
+/* CRTC Internal Horizontal Retrace Control Register */
+#define REG_LCM_CRTC_HR			(0x18)
+#define LCM_CRTC_HR_EVAL(x)		((x) << 16)
+#define LCM_CRTC_HR_SVAL(x)		((x) << 0)
+
+/* CRTC Horizontal Sync Control Register */
+#define REG_LCM_CRTC_HSYNC		(0x1C)
+#define LCM_CRTC_HSYNC_SHIFTVAL(x)	((x) << 30)
+#define LCM_CRTC_HSYNC_EVAL(x)		((x) << 16)
+#define LCM_CRTC_HSYNC_SVAL(x)		((x) << 0)
+
+/* CRTC Internal Vertical Retrace Control Register */
+#define REG_LCM_CRTC_VR			(0x20)
+#define LCM_CRTC_VR_EVAL(x)		((x) << 16)
+#define LCM_CRTC_VR_SVAL(x)		((x) << 0)
+
+/* Video Stream Frame Buffer-0 Starting Address */
+#define REG_LCM_VA_BADDR0		(0x24)
+
+/* Video Stream Frame Buffer-1 Starting Address */
+#define REG_LCM_VA_BADDR1		(0x28)
+
+/* Video Stream Frame Buffer Control Register */
+#define REG_LCM_VA_FBCTRL		(0x2C)
+#define LCM_VA_FBCTRL_IO_REGION_HALF	(1 << 28)
+#define LCM_VA_FBCTRL_FIELD_DUAL  	(1 << 29)
+#define LCM_VA_FBCTRL_START_BUF 	(1 << 30)
+#define LCM_VA_FBCTRL_DB_EN		(1 << 31)
+
+/* Video Stream Scaling Control Register */
+#define REG_LCM_VA_SCALE		(0x30)
+#define LCM_VA_SCALE_XCOPY_INTERPOLATION (0 << 15)
+#define LCM_VA_SCALE_XCOPY_DUPLICATION	 (1 << 15)
+
+/* Image Stream Active Window Coordinates */
+#define REG_LCM_VA_WIN			(0x38)
+
+/* Image Stream Stuff Pixel */
+#define REG_LCM_VA_STUFF		(0x3C)
+
+/* OSD Window Starting Coordinates */
+#define REG_LCM_OSD_WINS		(0x40)
+
+/* OSD Window Ending Coordinates */
+#define REG_LCM_OSD_WINE		(0x44)
+
+/* OSD Stream Frame Buffer Starting Address */
+#define REG_LCM_OSD_BADDR		(0x48)
+
+/* OSD Stream Frame Buffer Control Register */
+#define REG_LCM_OSD_FBCTRL		(0x4c)
+
+/* OSD Overlay Control Register */
+#define REG_LCM_OSD_OVERLAY		(0x50)
+
+/* OSD Overlay Color-Key Pattern Register */
+#define REG_LCM_OSD_CKEY		(0x54)
+
+/* OSD Overlay Color-Key Mask Register */
+#define REG_LCM_OSD_CMASK		(0x58)
+
+/* OSD Window Skip1 Register */
+#define REG_LCM_OSD_SKIP1		(0x5C)
+
+/* OSD Window Skip2 Register */
+#define REG_LCM_OSD_SKIP2		(0x60)
+
+/* OSD horizontal up scaling control register */
+#define REG_LCM_OSD_SCALE		(0x64)
+
+/* MPU Vsync control register */
+#define REG_LCM_MPU_VSYNC		(0x68)
+
+/* Hardware cursor control Register */
+#define REG_LCM_HC_CTRL			(0x6C)
+
+/* Hardware cursot tip point potison on va picture */
+#define REG_LCM_HC_POS			(0x70)
+
+/* Hardware Cursor Window Buffer Control Register */
+#define REG_LCM_HC_WBCTRL		(0x74)
+
+/* Hardware cursor memory base address register */
+#define REG_LCM_HC_BADDR		(0x78)
+
+/* Hardware cursor color ram register mapped to bpp = 0 */
+#define REG_LCM_HC_COLOR0		(0x7C)
+
+/* Hardware cursor color ram register mapped to bpp = 1 */
+#define REG_LCM_HC_COLOR1		(0x80)
+
+/* Hardware cursor color ram register mapped to bpp = 2 */
+#define REG_LCM_HC_COLOR2		(0x84)
+
+/* Hardware cursor color ram register mapped to bpp = 3 */
+#define REG_LCM_HC_COLOR3		(0x88)
+
+#endif /* __ASM_ARM_W90X900_REGS_LDM_H */
diff --git a/arch/arm/mach-w90x900/mach-nuc950evb.c b/arch/arm/mach-w90x900/mach-nuc950evb.c
index cef903b..b3edc3c 100644
--- a/arch/arm/mach-w90x900/mach-nuc950evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc950evb.c
@@ -10,6 +10,8 @@
  * This program is free software; 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.
+ *   history:
+ *     Wang Qiang (rurality.linux@gmail.com) add LCD support
  *
  */
 
@@ -18,9 +20,51 @@
 #include <asm/mach/map.h>
 #include <asm/mach-types.h>
 #include <mach/map.h>
+#include <mach/regs-ldm.h>
+#include <mach/fb.h>
 
 #include "nuc950.h"
 
+#ifdef CONFIG_FB_NUC900
+/* LCD Controller */
+static struct nuc900fb_display __initdata nuc950_lcd_info[] = {
+	/* Giantplus Technology GPM1040A0 320x240 Color TFT LCD */
+	[0] = {
+		.type		= LCM_DCCS_VA_SRC_RGB565,
+		.width 		= 320,
+		.height		= 240,
+		.xres		= 320,
+		.yres		= 240,
+		.bpp		= 16,
+		.pixclock	= 200000,
+		.left_margin	= 34,
+		.right_margin   = 54,
+		.hsync_len	= 10,
+		.upper_margin	= 18,
+		.lower_margin	= 4,
+		.vsync_len	= 1,
+		.dccs		= 0x8e00041a,
+		.devctl		= 0x060800c0,
+		.fbctrl		= 0x00a000a0,
+		.scale		= 0x04000400,
+	},
+};
+
+static struct nuc900fb_mach_info nuc950_fb_info __initdata = {
+#if defined(CONFIG_GPM1040A0_320X240)
+	.displays		= &nuc950_lcd_info[0],
+#else
+	.displays		= nuc950_lcd_info,
+#endif
+	.num_displays 		= ARRAY_SIZE(nuc950_lcd_info),
+	.default_display	= 0,
+	.gpio_dir		= 0x00000004,
+	.gpio_dir_mask		= 0xFFFFFFFD,
+	.gpio_data		= 0x00000004,
+	.gpio_data_mask		= 0xFFFFFFFD,
+};
+#endif
+
 static void __init nuc950evb_map_io(void)
 {
 	nuc950_map_io();
@@ -30,6 +74,9 @@
 static void __init nuc950evb_init(void)
 {
 	nuc950_board_init();
+#ifdef CONFIG_FB_NUC900
+	nuc900_fb_set_platdata(&nuc950_fb_info);
+#endif
 }
 
 MACHINE_START(W90P950EVB, "W90P950EVB")
diff --git a/arch/arm/mach-w90x900/nuc950.c b/arch/arm/mach-w90x900/nuc950.c
index 1495081..4d1f1ab 100644
--- a/arch/arm/mach-w90x900/nuc950.c
+++ b/arch/arm/mach-w90x900/nuc950.c
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
+
 #include "cpu.h"
 
 /* define specific CPU platform device */
@@ -25,6 +26,9 @@
 static struct platform_device *nuc950_dev[] __initdata = {
 	&nuc900_device_kpi,
 	&nuc900_device_fmi,
+#ifdef CONFIG_FB_NUC900
+	&nuc900_device_lcd,
+#endif
 };
 
 /* define specific CPU platform io map */
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 8b0a1ee..7f7ad6f 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -9,38 +9,43 @@
 config ARCH_MX1
 	bool "MX1-based"
 	select CPU_ARM920T
-	select COMMON_CLKDEV
+	select IMX_HAVE_IOMUX_V1
 	help
 	  This enables support for systems based on the Freescale i.MX1 family
 
 config ARCH_MX2
 	bool "MX2-based"
 	select CPU_ARM926T
-	select COMMON_CLKDEV
+	select IMX_HAVE_IOMUX_V1
 	help
 	  This enables support for systems based on the Freescale i.MX2 family
 
 config ARCH_MX25
 	bool "MX25-based"
 	select CPU_ARM926T
-	select COMMON_CLKDEV
+	select ARCH_MXC_IOMUX_V3
+	select HAVE_FB_IMX
 	help
 	  This enables support for systems based on the Freescale i.MX25 family
 
 config ARCH_MX3
 	bool "MX3-based"
 	select CPU_V6
-	select COMMON_CLKDEV
 	help
 	  This enables support for systems based on the Freescale i.MX3 family
 
 config ARCH_MXC91231
 	bool "MXC91231-based"
 	select CPU_V6
-	select COMMON_CLKDEV
 	help
 	  This enables support for systems based on the Freescale MXC91231 family
 
+config ARCH_MX5
+	bool "MX5-based"
+	select CPU_V7
+	help
+	  This enables support for systems based on the Freescale i.MX51 family
+
 endchoice
 
 source "arch/arm/mach-mx1/Kconfig"
@@ -48,12 +53,12 @@
 source "arch/arm/mach-mx3/Kconfig"
 source "arch/arm/mach-mx25/Kconfig"
 source "arch/arm/mach-mxc91231/Kconfig"
+source "arch/arm/mach-mx5/Kconfig"
 
 endmenu
 
 config MXC_IRQ_PRIOR
 	bool "Use IRQ priority"
-	depends on ARCH_MXC
 	help
 	  Select this if you want to use prioritized IRQ handling.
 	  This feature prevents higher priority ISR to be interrupted
@@ -62,9 +67,16 @@
 	  requirements for timing.
 	  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.
+
 config MXC_PWM
 	tristate "Enable PWM driver"
-	depends on ARCH_MXC
 	select HAVE_PWM
 	help
 	  Enable support for the i.MX PWM controller(s).
@@ -74,7 +86,9 @@
 
 config ARCH_HAS_RNGA
 	bool
-	depends on ARCH_MXC
+
+config IMX_HAVE_IOMUX_V1
+	bool
 
 config ARCH_MXC_IOMUX_V3
 	bool
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 6cee38d..895bc3c 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -5,8 +5,12 @@
 # Common support
 obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o system.o
 
-obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o
-obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o
+# MX51 uses the TZIC interrupt controller, older platforms use AVIC (irq.o)
+obj-$(CONFIG_MXC_TZIC) += tzic.o
+
+obj-$(CONFIG_ARCH_MX1) += dma-mx1-mx2.o
+obj-$(CONFIG_ARCH_MX2) += dma-mx1-mx2.o
+obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
 obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
 obj-$(CONFIG_MXC_PWM)  += pwm.o
 obj-$(CONFIG_USB_EHCI_MXC) += ehci.o
diff --git a/arch/arm/plat-mxc/audmux-v1.c b/arch/arm/plat-mxc/audmux-v1.c
index da6387d..b62917c 100644
--- a/arch/arm/plat-mxc/audmux-v1.c
+++ b/arch/arm/plat-mxc/audmux-v1.c
@@ -50,8 +50,18 @@
 
 static int mxc_audmux_v1_init(void)
 {
-	if (cpu_is_mx27() || cpu_is_mx21())
-		audmux_base = IO_ADDRESS(AUDMUX_BASE_ADDR);
+#ifdef CONFIG_MACH_MX21
+	if (cpu_is_mx21())
+		audmux_base = MX21_IO_ADDRESS(MX21_AUDMUX_BASE_ADDR);
+	else
+#endif
+#ifdef CONFIG_MACH_MX27
+	if (cpu_is_mx27())
+		audmux_base = MX27_IO_ADDRESS(MX27_AUDMUX_BASE_ADDR);
+	else
+#endif
+		(void)0;
+	
 	return 0;
 }
 
diff --git a/arch/arm/plat-mxc/audmux-v2.c b/arch/arm/plat-mxc/audmux-v2.c
index b06954a..d983cd6 100644
--- a/arch/arm/plat-mxc/audmux-v2.c
+++ b/arch/arm/plat-mxc/audmux-v2.c
@@ -190,7 +190,10 @@
 {
 	int ret;
 
-	if (cpu_is_mx35()) {
+	if (cpu_is_mx31())
+		audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
+
+	else if (cpu_is_mx35()) {
 		audmux_clk = clk_get(NULL, "audmux");
 		if (IS_ERR(audmux_clk)) {
 			ret = PTR_ERR(audmux_clk);
@@ -198,11 +201,9 @@
 					ret);
 			return ret;
 		}
+		audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR);
 	}
 
-	if (cpu_is_mx31() || cpu_is_mx35())
-		audmux_base = IO_ADDRESS(AUDMUX_BASE_ADDR);
-
 	audmux_debugfs_init();
 
 	return 0;
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 9e8fbd5..323ff8c 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -56,6 +56,7 @@
 	__clk_disable(clk->parent);
 	__clk_disable(clk->secondary);
 
+	WARN_ON(!clk->usecount);
 	if (!(--clk->usecount) && clk->disable)
 		clk->disable(clk);
 }
diff --git a/arch/arm/plat-mxc/dma-mx1-mx2.c b/arch/arm/plat-mxc/dma-mx1-mx2.c
index 9c1b3f9..e16014b 100644
--- a/arch/arm/plat-mxc/dma-mx1-mx2.c
+++ b/arch/arm/plat-mxc/dma-mx1-mx2.c
@@ -128,6 +128,18 @@
 	int hw_chaining;
 };
 
+static void __iomem *imx_dmav1_baseaddr;
+
+static void imx_dmav1_writel(unsigned val, unsigned offset)
+{
+	__raw_writel(val, imx_dmav1_baseaddr + offset);
+}
+
+static unsigned imx_dmav1_readl(unsigned offset)
+{
+	return __raw_readl(imx_dmav1_baseaddr + offset);
+}
+
 static struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
 
 static struct clk *dma_clk;
@@ -140,7 +152,6 @@
 		return 0;
 }
 
-
 /*
  * imx_dma_sg_next - prepare next chunk for scatter-gather DMA emulation
  */
@@ -160,17 +171,17 @@
 		imxdma->resbytes -= now;
 
 	if ((imxdma->dma_mode & DMA_MODE_MASK) == DMA_MODE_READ)
-		__raw_writel(sg->dma_address, DMA_BASE + DMA_DAR(channel));
+		imx_dmav1_writel(sg->dma_address, DMA_DAR(channel));
 	else
-		__raw_writel(sg->dma_address, DMA_BASE + DMA_SAR(channel));
+		imx_dmav1_writel(sg->dma_address, DMA_SAR(channel));
 
-	__raw_writel(now, DMA_BASE + DMA_CNTR(channel));
+	imx_dmav1_writel(now, DMA_CNTR(channel));
 
 	pr_debug("imxdma%d: next sg chunk dst 0x%08x, src 0x%08x, "
 		"size 0x%08x\n", channel,
-		 __raw_readl(DMA_BASE + DMA_DAR(channel)),
-		 __raw_readl(DMA_BASE + DMA_SAR(channel)),
-		 __raw_readl(DMA_BASE + DMA_CNTR(channel)));
+		 imx_dmav1_readl(DMA_DAR(channel)),
+		 imx_dmav1_readl(DMA_SAR(channel)),
+		 imx_dmav1_readl(DMA_CNTR(channel)));
 
 	return now;
 }
@@ -218,27 +229,26 @@
 			channel, __func__, (unsigned int)dma_address,
 			dma_length, dev_addr);
 
-		__raw_writel(dev_addr, DMA_BASE + DMA_SAR(channel));
-		__raw_writel(dma_address, DMA_BASE + DMA_DAR(channel));
-		__raw_writel(imxdma->ccr_from_device,
-				DMA_BASE + DMA_CCR(channel));
+		imx_dmav1_writel(dev_addr, DMA_SAR(channel));
+		imx_dmav1_writel(dma_address, DMA_DAR(channel));
+		imx_dmav1_writel(imxdma->ccr_from_device, DMA_CCR(channel));
 	} else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
 		pr_debug("imxdma%d: %s dma_addressg=0x%08x dma_length=%d "
 			"dev_addr=0x%08x for write\n",
 			channel, __func__, (unsigned int)dma_address,
 			dma_length, dev_addr);
 
-		__raw_writel(dma_address, DMA_BASE + DMA_SAR(channel));
-		__raw_writel(dev_addr, DMA_BASE + DMA_DAR(channel));
-		__raw_writel(imxdma->ccr_to_device,
-				DMA_BASE + DMA_CCR(channel));
+		imx_dmav1_writel(dma_address, DMA_SAR(channel));
+		imx_dmav1_writel(dev_addr, DMA_DAR(channel));
+		imx_dmav1_writel(imxdma->ccr_to_device,
+				DMA_CCR(channel));
 	} else {
 		printk(KERN_ERR "imxdma%d: imx_dma_setup_single bad dmamode\n",
 		       channel);
 		return -EINVAL;
 	}
 
-	__raw_writel(dma_length, DMA_BASE + DMA_CNTR(channel));
+	imx_dmav1_writel(dma_length, DMA_CNTR(channel));
 
 	return 0;
 }
@@ -316,17 +326,15 @@
 			"dev_addr=0x%08x for read\n",
 			channel, __func__, sg, sgcount, dma_length, dev_addr);
 
-		__raw_writel(dev_addr, DMA_BASE + DMA_SAR(channel));
-		__raw_writel(imxdma->ccr_from_device,
-				DMA_BASE + DMA_CCR(channel));
+		imx_dmav1_writel(dev_addr, DMA_SAR(channel));
+		imx_dmav1_writel(imxdma->ccr_from_device, DMA_CCR(channel));
 	} else if ((dmamode & DMA_MODE_MASK) == DMA_MODE_WRITE) {
 		pr_debug("imxdma%d: %s sg=%p sgcount=%d total length=%d "
 			"dev_addr=0x%08x for write\n",
 			channel, __func__, sg, sgcount, dma_length, dev_addr);
 
-		__raw_writel(dev_addr, DMA_BASE + DMA_DAR(channel));
-		__raw_writel(imxdma->ccr_to_device,
-				DMA_BASE + DMA_CCR(channel));
+		imx_dmav1_writel(dev_addr, DMA_DAR(channel));
+		imx_dmav1_writel(imxdma->ccr_to_device, DMA_CCR(channel));
 	} else {
 		printk(KERN_ERR "imxdma%d: imx_dma_setup_sg bad dmamode\n",
 		       channel);
@@ -360,7 +368,7 @@
 	imxdma->ccr_from_device = config_port | (config_mem << 2) | dreq;
 	imxdma->ccr_to_device = config_mem | (config_port << 2) | dreq;
 
-	__raw_writel(dmareq, DMA_BASE + DMA_RSSR(channel));
+	imx_dmav1_writel(dmareq, DMA_RSSR(channel));
 
 	return 0;
 }
@@ -368,7 +376,7 @@
 
 void imx_dma_config_burstlen(int channel, unsigned int burstlen)
 {
-	__raw_writel(burstlen, DMA_BASE + DMA_BLR(channel));
+	imx_dmav1_writel(burstlen, DMA_BLR(channel));
 }
 EXPORT_SYMBOL(imx_dma_config_burstlen);
 
@@ -398,7 +406,7 @@
 	}
 
 	local_irq_save(flags);
-	__raw_writel(1 << channel, DMA_BASE + DMA_DISR);
+	imx_dmav1_writel(1 << channel, DMA_DISR);
 	imxdma->irq_handler = irq_handler;
 	imxdma->err_handler = err_handler;
 	imxdma->data = data;
@@ -462,22 +470,21 @@
 
 	local_irq_save(flags);
 
-	__raw_writel(1 << channel, DMA_BASE + DMA_DISR);
-	__raw_writel(__raw_readl(DMA_BASE + DMA_DIMR) & ~(1 << channel),
-		DMA_BASE + DMA_DIMR);
-	__raw_writel(__raw_readl(DMA_BASE + DMA_CCR(channel)) | CCR_CEN |
-		CCR_ACRPT,
-		DMA_BASE + DMA_CCR(channel));
+	imx_dmav1_writel(1 << channel, DMA_DISR);
+	imx_dmav1_writel(imx_dmav1_readl(DMA_DIMR) & ~(1 << channel), DMA_DIMR);
+	imx_dmav1_writel(imx_dmav1_readl(DMA_CCR(channel)) | CCR_CEN |
+		CCR_ACRPT, DMA_CCR(channel));
 
 #ifdef CONFIG_ARCH_MX2
-	if (imxdma->sg && imx_dma_hw_chain(imxdma)) {
+	if ((cpu_is_mx21() || cpu_is_mx27()) &&
+			imxdma->sg && imx_dma_hw_chain(imxdma)) {
 		imxdma->sg = sg_next(imxdma->sg);
 		if (imxdma->sg) {
 			u32 tmp;
 			imx_dma_sg_next(channel, imxdma->sg);
-			tmp = __raw_readl(DMA_BASE + DMA_CCR(channel));
-			__raw_writel(tmp | CCR_RPT | CCR_ACRPT,
-				DMA_BASE + DMA_CCR(channel));
+			tmp = imx_dmav1_readl(DMA_CCR(channel));
+			imx_dmav1_writel(tmp | CCR_RPT | CCR_ACRPT,
+				DMA_CCR(channel));
 		}
 	}
 #endif
@@ -502,11 +509,10 @@
 		del_timer(&imxdma->watchdog);
 
 	local_irq_save(flags);
-	__raw_writel(__raw_readl(DMA_BASE + DMA_DIMR) | (1 << channel),
-		DMA_BASE + DMA_DIMR);
-	__raw_writel(__raw_readl(DMA_BASE + DMA_CCR(channel)) & ~CCR_CEN,
-		DMA_BASE + DMA_CCR(channel));
-	__raw_writel(1 << channel, DMA_BASE + DMA_DISR);
+	imx_dmav1_writel(imx_dmav1_readl(DMA_DIMR) | (1 << channel), DMA_DIMR);
+	imx_dmav1_writel(imx_dmav1_readl(DMA_CCR(channel)) & ~CCR_CEN,
+			DMA_CCR(channel));
+	imx_dmav1_writel(1 << channel, DMA_DISR);
 	imxdma->in_use = 0;
 	local_irq_restore(flags);
 }
@@ -517,7 +523,7 @@
 {
 	struct imx_dma_channel *imxdma = &imx_dma_channels[chno];
 
-	__raw_writel(0, DMA_BASE + DMA_CCR(chno));
+	imx_dmav1_writel(0, DMA_CCR(chno));
 	imxdma->in_use = 0;
 	imxdma->sg = NULL;
 
@@ -533,17 +539,17 @@
 	unsigned int err_mask;
 	int errcode;
 
-	disr = __raw_readl(DMA_BASE + DMA_DISR);
+	disr = imx_dmav1_readl(DMA_DISR);
 
-	err_mask = __raw_readl(DMA_BASE + DMA_DBTOSR) |
-		   __raw_readl(DMA_BASE + DMA_DRTOSR) |
-		   __raw_readl(DMA_BASE + DMA_DSESR)  |
-		   __raw_readl(DMA_BASE + DMA_DBOSR);
+	err_mask = imx_dmav1_readl(DMA_DBTOSR) |
+		   imx_dmav1_readl(DMA_DRTOSR) |
+		   imx_dmav1_readl(DMA_DSESR)  |
+		   imx_dmav1_readl(DMA_DBOSR);
 
 	if (!err_mask)
 		return IRQ_HANDLED;
 
-	__raw_writel(disr & err_mask, DMA_BASE + DMA_DISR);
+	imx_dmav1_writel(disr & err_mask, DMA_DISR);
 
 	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
 		if (!(err_mask & (1 << i)))
@@ -551,20 +557,20 @@
 		imxdma = &imx_dma_channels[i];
 		errcode = 0;
 
-		if (__raw_readl(DMA_BASE + DMA_DBTOSR) & (1 << i)) {
-			__raw_writel(1 << i, DMA_BASE + DMA_DBTOSR);
+		if (imx_dmav1_readl(DMA_DBTOSR) & (1 << i)) {
+			imx_dmav1_writel(1 << i, DMA_DBTOSR);
 			errcode |= IMX_DMA_ERR_BURST;
 		}
-		if (__raw_readl(DMA_BASE + DMA_DRTOSR) & (1 << i)) {
-			__raw_writel(1 << i, DMA_BASE + DMA_DRTOSR);
+		if (imx_dmav1_readl(DMA_DRTOSR) & (1 << i)) {
+			imx_dmav1_writel(1 << i, DMA_DRTOSR);
 			errcode |= IMX_DMA_ERR_REQUEST;
 		}
-		if (__raw_readl(DMA_BASE + DMA_DSESR) & (1 << i)) {
-			__raw_writel(1 << i, DMA_BASE + DMA_DSESR);
+		if (imx_dmav1_readl(DMA_DSESR) & (1 << i)) {
+			imx_dmav1_writel(1 << i, DMA_DSESR);
 			errcode |= IMX_DMA_ERR_TRANSFER;
 		}
-		if (__raw_readl(DMA_BASE + DMA_DBOSR) & (1 << i)) {
-			__raw_writel(1 << i, DMA_BASE + DMA_DBOSR);
+		if (imx_dmav1_readl(DMA_DBOSR) & (1 << i)) {
+			imx_dmav1_writel(1 << i, DMA_DBOSR);
 			errcode |= IMX_DMA_ERR_BUFFER;
 		}
 		if (imxdma->name && imxdma->err_handler) {
@@ -607,7 +613,7 @@
 		if (imxdma->sg) {
 			imx_dma_sg_next(chno, imxdma->sg);
 
-			tmp = __raw_readl(DMA_BASE + DMA_CCR(chno));
+			tmp = imx_dmav1_readl(DMA_CCR(chno));
 
 			if (imx_dma_hw_chain(imxdma)) {
 				/* FIXME: The timeout should probably be
@@ -617,15 +623,13 @@
 					jiffies + msecs_to_jiffies(500));
 
 				tmp |= CCR_CEN | CCR_RPT | CCR_ACRPT;
-				__raw_writel(tmp, DMA_BASE +
-						DMA_CCR(chno));
+				imx_dmav1_writel(tmp, DMA_CCR(chno));
 			} else {
-				__raw_writel(tmp & ~CCR_CEN, DMA_BASE +
-						DMA_CCR(chno));
+				imx_dmav1_writel(tmp & ~CCR_CEN, DMA_CCR(chno));
 				tmp |= CCR_CEN;
 			}
 
-			__raw_writel(tmp, DMA_BASE + DMA_CCR(chno));
+			imx_dmav1_writel(tmp, DMA_CCR(chno));
 
 			if (imxdma->prog_handler)
 				imxdma->prog_handler(chno, imxdma->data,
@@ -640,7 +644,7 @@
 		}
 	}
 
-	__raw_writel(0, DMA_BASE + DMA_CCR(chno));
+	imx_dmav1_writel(0, DMA_CCR(chno));
 	imxdma->in_use = 0;
 	if (imxdma->irq_handler)
 		imxdma->irq_handler(chno, imxdma->data);
@@ -651,15 +655,16 @@
 	int i, disr;
 
 #ifdef CONFIG_ARCH_MX2
-	dma_err_handler(irq, dev_id);
+	if (cpu_is_mx21() || cpu_is_mx27())
+		dma_err_handler(irq, dev_id);
 #endif
 
-	disr = __raw_readl(DMA_BASE + DMA_DISR);
+	disr = imx_dmav1_readl(DMA_DISR);
 
 	pr_debug("imxdma: dma_irq_handler called, disr=0x%08x\n",
 		     disr);
 
-	__raw_writel(disr, DMA_BASE + DMA_DISR);
+	imx_dmav1_writel(disr, DMA_DISR);
 	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
 		if (disr & (1 << i))
 			dma_irq_handle_channel(i);
@@ -699,17 +704,19 @@
 	local_irq_restore(flags); /* request_irq() can block */
 
 #ifdef CONFIG_ARCH_MX2
-	ret = request_irq(MXC_INT_DMACH0 + channel, dma_irq_handler, 0, "DMA",
-			NULL);
-	if (ret) {
-		imxdma->name = NULL;
-		printk(KERN_CRIT "Can't register IRQ %d for DMA channel %d\n",
-				MXC_INT_DMACH0 + channel, channel);
-		return ret;
+	if (cpu_is_mx21() || cpu_is_mx27()) {
+		ret = request_irq(MX2x_INT_DMACH0 + channel,
+				dma_irq_handler, 0, "DMA", NULL);
+		if (ret) {
+			imxdma->name = NULL;
+			pr_crit("Can't register IRQ %d for DMA channel %d\n",
+					MX2x_INT_DMACH0 + channel, channel);
+			return ret;
+		}
+		init_timer(&imxdma->watchdog);
+		imxdma->watchdog.function = &imx_dma_watchdog;
+		imxdma->watchdog.data = channel;
 	}
-	init_timer(&imxdma->watchdog);
-	imxdma->watchdog.function = &imx_dma_watchdog;
-	imxdma->watchdog.data = channel;
 #endif
 
 	return ret;
@@ -738,7 +745,8 @@
 	imxdma->name = NULL;
 
 #ifdef CONFIG_ARCH_MX2
-	free_irq(MXC_INT_DMACH0 + channel, NULL);
+	if (cpu_is_mx21() || cpu_is_mx27())
+		free_irq(MX2x_INT_DMACH0 + channel, NULL);
 #endif
 
 	local_irq_restore(flags);
@@ -796,34 +804,53 @@
 	int ret = 0;
 	int i;
 
+#ifdef CONFIG_ARCH_MX1
+	if (cpu_is_mx1())
+		imx_dmav1_baseaddr = MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR);
+	else
+#endif
+#ifdef CONFIG_MACH_MX21
+	if (cpu_is_mx21())
+		imx_dmav1_baseaddr = MX21_IO_ADDRESS(MX21_DMA_BASE_ADDR);
+	else
+#endif
+#ifdef CONFIG_MACH_MX27
+	if (cpu_is_mx27())
+		imx_dmav1_baseaddr = MX27_IO_ADDRESS(MX27_DMA_BASE_ADDR);
+	else
+#endif
+		BUG();
+
 	dma_clk = clk_get(NULL, "dma");
 	clk_enable(dma_clk);
 
 	/* reset DMA module */
-	__raw_writel(DCR_DRST, DMA_BASE + DMA_DCR);
+	imx_dmav1_writel(DCR_DRST, DMA_DCR);
 
 #ifdef CONFIG_ARCH_MX1
-	ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
-	if (ret) {
-		printk(KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
-		return ret;
-	}
+	if (cpu_is_mx1()) {
+		ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", NULL);
+		if (ret) {
+			pr_crit("Wow!  Can't register IRQ for DMA\n");
+			return ret;
+		}
 
-	ret = request_irq(DMA_ERR, dma_err_handler, 0, "DMA", NULL);
-	if (ret) {
-		printk(KERN_CRIT "Wow!  Can't register ERRIRQ for DMA\n");
-		free_irq(DMA_INT, NULL);
-		return ret;
+		ret = request_irq(MX1_DMA_ERR, dma_err_handler, 0, "DMA", NULL);
+		if (ret) {
+			pr_crit("Wow!  Can't register ERRIRQ for DMA\n");
+			free_irq(MX1_DMA_INT, NULL);
+			return ret;
+		}
 	}
 #endif
 	/* enable DMA module */
-	__raw_writel(DCR_DEN, DMA_BASE + DMA_DCR);
+	imx_dmav1_writel(DCR_DEN, DMA_DCR);
 
 	/* clear all interrupts */
-	__raw_writel((1 << IMX_DMA_CHANNELS) - 1, DMA_BASE + DMA_DISR);
+	imx_dmav1_writel((1 << IMX_DMA_CHANNELS) - 1, DMA_DISR);
 
 	/* disable interrupts */
-	__raw_writel((1 << IMX_DMA_CHANNELS) - 1, DMA_BASE + DMA_DIMR);
+	imx_dmav1_writel((1 << IMX_DMA_CHANNELS) - 1, DMA_DIMR);
 
 	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
 		imx_dma_channels[i].sg = NULL;
diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c
index 41599be..cb0b63874 100644
--- a/arch/arm/plat-mxc/ehci.c
+++ b/arch/arm/plat-mxc/ehci.c
@@ -25,25 +25,37 @@
 #define USBCTRL_OTGBASE_OFFSET	0x600
 
 #define MX31_OTG_SIC_SHIFT	29
-#define MX31_OTG_SIC_MASK	(0xf << MX31_OTG_SIC_SHIFT)
+#define MX31_OTG_SIC_MASK	(0x3 << MX31_OTG_SIC_SHIFT)
 #define MX31_OTG_PM_BIT		(1 << 24)
 
 #define MX31_H2_SIC_SHIFT	21
-#define MX31_H2_SIC_MASK	(0xf << MX31_H2_SIC_SHIFT)
+#define MX31_H2_SIC_MASK	(0x3 << MX31_H2_SIC_SHIFT)
 #define MX31_H2_PM_BIT		(1 << 16)
 #define MX31_H2_DT_BIT		(1 << 5)
 
 #define MX31_H1_SIC_SHIFT	13
-#define MX31_H1_SIC_MASK	(0xf << MX31_H1_SIC_SHIFT)
+#define MX31_H1_SIC_MASK	(0x3 << MX31_H1_SIC_SHIFT)
 #define MX31_H1_PM_BIT		(1 << 8)
 #define MX31_H1_DT_BIT		(1 << 4)
 
+#define MX35_OTG_SIC_SHIFT	29
+#define MX35_OTG_SIC_MASK	(0x3 << MX35_OTG_SIC_SHIFT)
+#define MX35_OTG_PM_BIT		(1 << 24)
+
+#define MX35_H1_SIC_SHIFT	21
+#define MX35_H1_SIC_MASK	(0x3 << MX35_H1_SIC_SHIFT)
+#define MX35_H1_PM_BIT		(1 << 8)
+#define MX35_H1_IPPUE_UP_BIT	(1 << 7)
+#define MX35_H1_IPPUE_DOWN_BIT	(1 << 6)
+#define MX35_H1_TLL_BIT		(1 << 5)
+#define MX35_H1_USBTE_BIT	(1 << 4)
+
 int mxc_set_usbcontrol(int port, unsigned int flags)
 {
 	unsigned int v;
-
+#ifdef CONFIG_ARCH_MX3
 	if (cpu_is_mx31()) {
-		v = readl(IO_ADDRESS(MX31_OTG_BASE_ADDR +
+		v = readl(MX31_IO_ADDRESS(MX31_OTG_BASE_ADDR +
 				     USBCTRL_OTGBASE_OFFSET));
 
 		switch (port) {
@@ -51,15 +63,15 @@
 			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
 			v |= (flags & MXC_EHCI_INTERFACE_MASK)
 					<< MX31_OTG_SIC_SHIFT;
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
 				v |= MX31_OTG_PM_BIT;
 
 			break;
 		case 1: /* H1 port */
-			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT);
+			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
 			v |= (flags & MXC_EHCI_INTERFACE_MASK)
 						<< MX31_H1_SIC_SHIFT;
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
 				v |= MX31_H1_PM_BIT;
 
 			if (!(flags & MXC_EHCI_TTL_ENABLED))
@@ -67,7 +79,7 @@
 
 			break;
 		case 2:	/* H2 port */
-			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT);
+			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
 			v |= (flags & MXC_EHCI_INTERFACE_MASK)
 						<< MX31_H2_SIC_SHIFT;
 			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
@@ -77,13 +89,103 @@
 				v |= MX31_H2_DT_BIT;
 
 			break;
+		default:
+			return -EINVAL;
 		}
 
-		writel(v, IO_ADDRESS(MX31_OTG_BASE_ADDR +
+		writel(v, MX31_IO_ADDRESS(MX31_OTG_BASE_ADDR +
 				     USBCTRL_OTGBASE_OFFSET));
 		return 0;
 	}
 
+	if (cpu_is_mx35()) {
+		v = readl(MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+				     USBCTRL_OTGBASE_OFFSET));
+
+		switch (port) {
+		case 0:	/* OTG port */
+			v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
+			v |= (flags & MXC_EHCI_INTERFACE_MASK)
+					<< MX35_OTG_SIC_SHIFT;
+			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+				v |= MX35_OTG_PM_BIT;
+
+			break;
+		case 1: /* H1 port */
+			v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
+				MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
+			v |= (flags & MXC_EHCI_INTERFACE_MASK)
+						<< MX35_H1_SIC_SHIFT;
+			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+				v |= MX35_H1_PM_BIT;
+
+			if (!(flags & MXC_EHCI_TTL_ENABLED))
+				v |= MX35_H1_TLL_BIT;
+
+			if (flags & MXC_EHCI_INTERNAL_PHY)
+				v |= MX35_H1_USBTE_BIT;
+
+			if (flags & MXC_EHCI_IPPUE_DOWN)
+				v |= MX35_H1_IPPUE_DOWN_BIT;
+
+			if (flags & MXC_EHCI_IPPUE_UP)
+				v |= MX35_H1_IPPUE_UP_BIT;
+
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		writel(v, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
+				     USBCTRL_OTGBASE_OFFSET));
+		return 0;
+	}
+#endif /* CONFIG_ARCH_MX3 */
+#ifdef CONFIG_MACH_MX27
+	if (cpu_is_mx27()) {
+		/* On i.MX27 we can use the i.MX31 USBCTRL bits, they
+		 * are identical
+		 */
+		v = readl(MX27_IO_ADDRESS(MX27_OTG_BASE_ADDR +
+				     USBCTRL_OTGBASE_OFFSET));
+		switch (port) {
+		case 0:	/* OTG port */
+			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
+			v |= (flags & MXC_EHCI_INTERFACE_MASK)
+					<< MX31_OTG_SIC_SHIFT;
+			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+				v |= MX31_OTG_PM_BIT;
+			break;
+		case 1: /* H1 port */
+			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
+			v |= (flags & MXC_EHCI_INTERFACE_MASK)
+						<< MX31_H1_SIC_SHIFT;
+			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+				v |= MX31_H1_PM_BIT;
+
+			if (!(flags & MXC_EHCI_TTL_ENABLED))
+				v |= MX31_H1_DT_BIT;
+
+			break;
+		case 2:	/* H2 port */
+			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
+			v |= (flags & MXC_EHCI_INTERFACE_MASK)
+						<< MX31_H2_SIC_SHIFT;
+			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+				v |= MX31_H2_PM_BIT;
+
+			if (!(flags & MXC_EHCI_TTL_ENABLED))
+				v |= MX31_H2_DT_BIT;
+
+			break;
+		default:
+			return -EINVAL;
+		}
+		writel(v, MX27_IO_ADDRESS(MX27_OTG_BASE_ADDR +
+				     USBCTRL_OTGBASE_OFFSET));
+		return 0;
+	}
+#endif /* CONFIG_MACH_MX27 */
 	printk(KERN_WARNING
 		"%s() unable to setup USBCONTROL for this CPU\n", __func__);
 	return -EINVAL;
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index d65ebe3..70b2389 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -140,16 +140,13 @@
 	val = __raw_readl(reg);
 	edge = (val >> (bit << 1)) & 3;
 	val &= ~(0x3 << (bit << 1));
-	switch (edge) {
-	case GPIO_INT_HIGH_LEV:
+	if (edge == GPIO_INT_HIGH_LEV) {
 		edge = GPIO_INT_LOW_LEV;
 		pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
-		break;
-	case GPIO_INT_LOW_LEV:
+	} else if (edge == GPIO_INT_LOW_LEV) {
 		edge = GPIO_INT_HIGH_LEV;
 		pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
-		break;
-	default:
+	} else {
 		pr_err("mxc: invalid configuration for GPIO %d: %x\n",
 		       gpio, edge);
 		return;
@@ -157,25 +154,20 @@
 	__raw_writel(val | (edge << (bit << 1)), reg);
 }
 
-/* handle n interrupts in one status register */
+/* handle 32 interrupts in one status register */
 static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
 {
-	u32 gpio_irq_no;
+	u32 gpio_irq_no_base = port->virtual_irq_start;
 
-	gpio_irq_no = port->virtual_irq_start;
-	for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) {
-		u32 gpio = irq_to_gpio(gpio_irq_no);
+	while (irq_stat != 0) {
+		int irqoffset = fls(irq_stat) - 1;
 
-		if ((irq_stat & 1) == 0)
-			continue;
+		if (port->both_edges & (1 << irqoffset))
+			mxc_flip_edge(port, irqoffset);
 
-		BUG_ON(!(irq_desc[gpio_irq_no].handle_irq));
+		generic_handle_irq(gpio_irq_no_base + irqoffset);
 
-		if (port->both_edges & (1 << (gpio & 31)))
-			mxc_flip_edge(port, gpio);
-
-		irq_desc[gpio_irq_no].handle_irq(gpio_irq_no,
-				&irq_desc[gpio_irq_no]);
+		irq_stat &= ~(1 << irqoffset);
 	}
 }
 
diff --git a/arch/arm/plat-mxc/include/mach/board-kzmarm11.h b/arch/arm/plat-mxc/include/mach/board-kzmarm11.h
index 05ff2f3..93cc66f 100644
--- a/arch/arm/plat-mxc/include/mach/board-kzmarm11.h
+++ b/arch/arm/plat-mxc/include/mach/board-kzmarm11.h
@@ -21,19 +21,19 @@
 /*
  *  KZM-ARM11-01 Board Control Registers on FPGA
  */
-#define KZM_ARM11_CTL1		(CS4_BASE_ADDR + 0x1000)
-#define KZM_ARM11_CTL2		(CS4_BASE_ADDR + 0x1001)
-#define KZM_ARM11_RSW1		(CS4_BASE_ADDR + 0x1002)
-#define KZM_ARM11_BACK_LIGHT	(CS4_BASE_ADDR + 0x1004)
-#define KZM_ARM11_FPGA_REV	(CS4_BASE_ADDR + 0x1008)
-#define KZM_ARM11_7SEG_LED	(CS4_BASE_ADDR + 0x1010)
-#define KZM_ARM11_LEDS		(CS4_BASE_ADDR + 0x1020)
-#define KZM_ARM11_DIPSW2	(CS4_BASE_ADDR + 0x1003)
+#define KZM_ARM11_CTL1		(MX31_CS4_BASE_ADDR + 0x1000)
+#define KZM_ARM11_CTL2		(MX31_CS4_BASE_ADDR + 0x1001)
+#define KZM_ARM11_RSW1		(MX31_CS4_BASE_ADDR + 0x1002)
+#define KZM_ARM11_BACK_LIGHT	(MX31_CS4_BASE_ADDR + 0x1004)
+#define KZM_ARM11_FPGA_REV	(MX31_CS4_BASE_ADDR + 0x1008)
+#define KZM_ARM11_7SEG_LED	(MX31_CS4_BASE_ADDR + 0x1010)
+#define KZM_ARM11_LEDS		(MX31_CS4_BASE_ADDR + 0x1020)
+#define KZM_ARM11_DIPSW2	(MX31_CS4_BASE_ADDR + 0x1003)
 
 /*
  * External UART for touch panel on FPGA
  */
-#define KZM_ARM11_16550		(CS4_BASE_ADDR + 0x1050)
+#define KZM_ARM11_16550		(MX31_CS4_BASE_ADDR + 0x1050)
 
 #endif /* __ARM_ARCH_BOARD_KZM_ARM11_H */
 
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31ads.h b/arch/arm/plat-mxc/include/mach/board-mx31ads.h
index 2cbfa35..095a199 100644
--- a/arch/arm/plat-mxc/include/mach/board-mx31ads.h
+++ b/arch/arm/plat-mxc/include/mach/board-mx31ads.h
@@ -14,7 +14,7 @@
 #include <mach/hardware.h>
 
 /* Base address of PBC controller */
-#define PBC_BASE_ADDRESS        IO_ADDRESS(CS4_BASE_ADDR)
+#define PBC_BASE_ADDRESS        MX31_CS4_BASE_ADDR_VIRT
 /* Offsets for the PBC Controller register */
 
 /* PBC Board status register offset */
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31moboard.h b/arch/arm/plat-mxc/include/mach/board-mx31moboard.h
index d5be6b5..fc5fec9 100644
--- a/arch/arm/plat-mxc/include/mach/board-mx31moboard.h
+++ b/arch/arm/plat-mxc/include/mach/board-mx31moboard.h
@@ -25,6 +25,7 @@
 	MX31NOBOARD	= 0,
 	MX31DEVBOARD	= 1,
 	MX31MARXBOT	= 2,
+	MX31SMARTBOT	= 3,
 };
 
 /*
@@ -34,6 +35,7 @@
 
 extern void mx31moboard_devboard_init(void);
 extern void mx31moboard_marxbot_init(void);
+extern void mx31moboard_smartbot_init(void);
 
 #endif
 
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 43a82d0..753a598 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -26,13 +26,6 @@
 struct module;
 
 struct clk {
-#ifndef CONFIG_COMMON_CLKDEV
-	/* As soon as i.MX1 and i.MX31 switched to clkdev, this
-	 * block can go away */
-	struct list_head node;
-	struct module *owner;
-	const char *name;
-#endif
 	int id;
 	/* Source clock this clk depends on */
 	struct clk *parent;
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 4bf1068..2941472 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -20,14 +20,17 @@
 extern void mx27_map_io(void);
 extern void mx31_map_io(void);
 extern void mx35_map_io(void);
+extern void mx51_map_io(void);
 extern void mxc91231_map_io(void);
 extern void mxc_init_irq(void __iomem *);
+extern void tzic_init_irq(void __iomem *);
 extern void mx1_init_irq(void);
 extern void mx21_init_irq(void);
 extern void mx25_init_irq(void);
 extern void mx27_init_irq(void);
 extern void mx31_init_irq(void);
 extern void mx35_init_irq(void);
+extern void mx51_init_irq(void);
 extern void mxc91231_init_irq(void);
 extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int);
 extern int mx1_clocks_init(unsigned long fref);
@@ -36,6 +39,8 @@
 extern int mx27_clocks_init(unsigned long fref);
 extern int mx31_clocks_init(unsigned long fref);
 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 mxc91231_clocks_init(unsigned long fref);
 extern int mxc_register_gpios(void);
 extern int mxc_register_device(struct platform_device *pdev, void *data);
diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S
index 5a6ae1b..0b6e11e 100644
--- a/arch/arm/plat-mxc/include/mach/debug-macro.S
+++ b/arch/arm/plat-mxc/include/mach/debug-macro.S
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  *
  */
+#define IMX_NEEDS_DEPRECATED_SYMBOLS
 
 #ifdef CONFIG_ARCH_MX1
 #include <mach/mx1.h>
@@ -44,13 +45,22 @@
 #define UART_VADDR	AIPS1_IO_ADDRESS(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_AIPS1_IO_ADDRESS(MXC91231_UART2_BASE_ADDR)
+#define UART_VADDR	MXC91231_IO_ADDRESS(MXC91231_UART2_BASE_ADDR)
 #endif
 		.macro	addruart, rx, tmp
 		mrc	p15, 0, \rx, c1, c0
diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S
index 7cf290e..aeb0869 100644
--- a/arch/arm/plat-mxc/include/mach/entry-macro.S
+++ b/arch/arm/plat-mxc/include/mach/entry-macro.S
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org>
- *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *  Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -18,11 +18,16 @@
 	.endm
 
 	.macro  get_irqnr_preamble, base, tmp
+#ifndef CONFIG_MXC_TZIC
 	ldr	\base, =avic_base
 	ldr	\base, [\base]
 #ifdef CONFIG_MXC_IRQ_PRIOR
 	ldr	r4, [\base, #AVIC_NIMASK]
 #endif
+#elif defined CONFIG_MXC_TZIC
+	ldr	\base, =tzic_base
+	ldr	\base, [\base]
+#endif /* CONFIG_MXC_TZIC */
 	.endm
 
 	.macro  arch_ret_to_user, tmp1, tmp2
@@ -32,6 +37,7 @@
 	@ and returns its number in irqnr
 	@ and returns if an interrupt occured in irqstat
 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+#ifndef CONFIG_MXC_TZIC
 	@ Load offset & priority of the highest priority
 	@ interrupt pending from AVIC_NIVECSR
 	ldr	\irqstat, [\base, #0x40]
@@ -45,6 +51,32 @@
 	strne	\tmp, [\base, #AVIC_NIMASK]
 	streq	r4, [\base, #AVIC_NIMASK]
 #endif
+#elif defined CONFIG_MXC_TZIC
+	@ Load offset & priority of the highest priority
+	@ interrupt pending.
+	@ 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
+	cmp     \irqnr, #128
+	blo     1000b
+	b       2001f
+1001:	mov     \irqstat, #1
+1002:	tst     \tmp, \irqstat
+	bne     2002f
+	movs    \tmp, \tmp, lsr #1
+	addne   \irqnr, \irqnr, #1
+	bne     1002b
+2001:
+	mov  \irqnr, #0
+2002:
+	movs \irqnr, \irqnr
+#endif
 	.endm
 
 	@ irq priority table (not used)
diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h
index 78db754..ebadf4a 100644
--- a/arch/arm/plat-mxc/include/mach/hardware.h
+++ b/arch/arm/plat-mxc/include/mach/hardware.h
@@ -22,6 +22,15 @@
 
 #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 CONFIG_ARCH_MX5
+#include <mach/mx51.h>
+#endif
+
 #ifdef CONFIG_ARCH_MX3
 #include <mach/mx3x.h>
 #include <mach/mx31.h>
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx1.h b/arch/arm/plat-mxc/include/mach/iomux-mx1.h
index bf23305..6b1507c 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx1.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx1.h
@@ -1,166 +1,155 @@
 /*
-* Copyright (C) 2008 by 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.
-*/
+ * Copyright (C) 2008 by 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.
+ */
+#ifndef __MACH_IOMUX_MX1_H__
+#define __MACH_IOMUX_MX1_H__
 
-#ifndef _MXC_IOMUX_MX1_H
-#define _MXC_IOMUX_MX1_H
+#include <mach/iomux-v1.h>
 
-#ifndef GPIO_PORTA
-#error Please include mach/iomux.h
-#endif
+#define PA0_AIN_SPI2_CLK	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
+#define PA0_AF_ETMTRACESYNC	(GPIO_PORTA | GPIO_AF | 0)
+#define PA1_AOUT_SPI2_RXD	(GPIO_PORTA | GPIO_AOUT | GPIO_IN | 1)
+#define PA1_PF_TIN		(GPIO_PORTA | GPIO_PF | 1)
+#define PA2_PF_PWM0		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 2)
+#define PA3_PF_CSI_MCLK		(GPIO_PORTA | GPIO_PF | 3)
+#define PA4_PF_CSI_D0		(GPIO_PORTA | GPIO_PF | 4)
+#define PA5_PF_CSI_D1		(GPIO_PORTA | GPIO_PF | 5)
+#define PA6_PF_CSI_D2		(GPIO_PORTA | GPIO_PF | 6)
+#define PA7_PF_CSI_D3		(GPIO_PORTA | GPIO_PF | 7)
+#define PA8_PF_CSI_D4		(GPIO_PORTA | GPIO_PF | 8)
+#define PA9_PF_CSI_D5		(GPIO_PORTA | GPIO_PF | 9)
+#define PA10_PF_CSI_D6		(GPIO_PORTA | GPIO_PF | 10)
+#define PA11_PF_CSI_D7		(GPIO_PORTA | GPIO_PF | 11)
+#define PA12_PF_CSI_VSYNC	(GPIO_PORTA | GPIO_PF | 12)
+#define PA13_PF_CSI_HSYNC	(GPIO_PORTA | GPIO_PF | 13)
+#define PA14_PF_CSI_PIXCLK	(GPIO_PORTA | GPIO_PF | 14)
+#define PA15_PF_I2C_SDA		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 15)
+#define PA16_PF_I2C_SCL		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 16)
+#define PA17_AF_ETMTRACEPKT4	(GPIO_PORTA | GPIO_AF | 17)
+#define PA17_AIN_SPI2_SS	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17)
+#define PA18_AF_ETMTRACEPKT5	(GPIO_PORTA | GPIO_AF | 18)
+#define PA19_AF_ETMTRACEPKT6	(GPIO_PORTA | GPIO_AF | 19)
+#define PA20_AF_ETMTRACEPKT7	(GPIO_PORTA | GPIO_AF | 20)
+#define PA21_PF_A0		(GPIO_PORTA | GPIO_PF | 21)
+#define PA22_PF_CS4		(GPIO_PORTA | GPIO_PF | 22)
+#define PA23_PF_CS5		(GPIO_PORTA | GPIO_PF | 23)
+#define PA24_PF_A16		(GPIO_PORTA | GPIO_PF | 24)
+#define PA24_AF_ETMTRACEPKT0	(GPIO_PORTA | GPIO_AF | 24)
+#define PA25_PF_A17		(GPIO_PORTA | GPIO_PF | 25)
+#define PA25_AF_ETMTRACEPKT1	(GPIO_PORTA | GPIO_AF | 25)
+#define PA26_PF_A18		(GPIO_PORTA | GPIO_PF | 26)
+#define PA26_AF_ETMTRACEPKT2	(GPIO_PORTA | GPIO_AF | 26)
+#define PA27_PF_A19		(GPIO_PORTA | GPIO_PF | 27)
+#define PA27_AF_ETMTRACEPKT3	(GPIO_PORTA | GPIO_AF | 27)
+#define PA28_PF_A20		(GPIO_PORTA | GPIO_PF | 28)
+#define PA28_AF_ETMPIPESTAT0	(GPIO_PORTA | GPIO_AF | 28)
+#define PA29_PF_A21		(GPIO_PORTA | GPIO_PF | 29)
+#define PA29_AF_ETMPIPESTAT1	(GPIO_PORTA | GPIO_AF | 29)
+#define PA30_PF_A22		(GPIO_PORTA | GPIO_PF | 30)
+#define PA30_AF_ETMPIPESTAT2	(GPIO_PORTA | GPIO_AF | 30)
+#define PA31_PF_A23		(GPIO_PORTA | GPIO_PF | 31)
+#define PA31_AF_ETMTRACECLK	(GPIO_PORTA | GPIO_AF | 31)
+#define PB8_PF_SD_DAT0		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8)
+#define PB8_AF_MS_PIO		(GPIO_PORTB | GPIO_AF | 8)
+#define PB9_PF_SD_DAT1		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 9)
+#define PB9_AF_MS_PI1		(GPIO_PORTB | GPIO_AF | 9)
+#define PB10_PF_SD_DAT2		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 10)
+#define PB10_AF_MS_SCLKI	(GPIO_PORTB | GPIO_AF | 10)
+#define PB11_PF_SD_DAT3		(GPIO_PORTB | GPIO_PF | 11)
+#define PB11_AF_MS_SDIO		(GPIO_PORTB | GPIO_AF | 11)
+#define PB12_PF_SD_CLK		(GPIO_PORTB | GPIO_PF | 12)
+#define PB12_AF_MS_SCLK0	(GPIO_PORTB | GPIO_AF | 12)
+#define PB13_PF_SD_CMD		(GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13)
+#define PB13_AF_MS_BS		(GPIO_PORTB | GPIO_AF | 13)
+#define PB14_AF_SSI_RXFS	(GPIO_PORTB | GPIO_AF | 14)
+#define PB15_AF_SSI_RXCLK	(GPIO_PORTB | GPIO_AF | 15)
+#define PB16_AF_SSI_RXDAT	(GPIO_PORTB | GPIO_AF | GPIO_IN | 16)
+#define PB17_AF_SSI_TXDAT	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 17)
+#define PB18_AF_SSI_TXFS	(GPIO_PORTB | GPIO_AF | 18)
+#define PB19_AF_SSI_TXCLK	(GPIO_PORTB | GPIO_AF | 19)
+#define PB20_PF_USBD_AFE	(GPIO_PORTB | GPIO_PF | 20)
+#define PB21_PF_USBD_OE		(GPIO_PORTB | GPIO_PF | 21)
+#define PB22_PF_USBD_RCV	(GPIO_PORTB | GPIO_PF | 22)
+#define PB23_PF_USBD_SUSPND	(GPIO_PORTB | GPIO_PF | 23)
+#define PB24_PF_USBD_VP		(GPIO_PORTB | GPIO_PF | 24)
+#define PB25_PF_USBD_VM		(GPIO_PORTB | GPIO_PF | 25)
+#define PB26_PF_USBD_VPO	(GPIO_PORTB | GPIO_PF | 26)
+#define PB27_PF_USBD_VMO	(GPIO_PORTB | GPIO_PF | 27)
+#define PB28_PF_UART2_CTS	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 28)
+#define PB29_PF_UART2_RTS	(GPIO_PORTB | GPIO_PF | GPIO_IN | 29)
+#define PB30_PF_UART2_TXD	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 30)
+#define PB31_PF_UART2_RXD	(GPIO_PORTB | GPIO_PF | GPIO_IN | 31)
+#define PC3_PF_SSI_RXFS		(GPIO_PORTC | GPIO_PF | 3)
+#define PC4_PF_SSI_RXCLK	(GPIO_PORTC | GPIO_PF | 4)
+#define PC5_PF_SSI_RXDAT	(GPIO_PORTC | GPIO_PF | GPIO_IN | 5)
+#define PC6_PF_SSI_TXDAT	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 6)
+#define PC7_PF_SSI_TXFS		(GPIO_PORTC | GPIO_PF | 7)
+#define PC8_PF_SSI_TXCLK	(GPIO_PORTC | GPIO_PF | 8)
+#define PC9_PF_UART1_CTS	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
+#define PC10_PF_UART1_RTS	(GPIO_PORTC | GPIO_PF | GPIO_IN | 10)
+#define PC11_PF_UART1_TXD	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 11)
+#define PC12_PF_UART1_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 12)
+#define PC13_PF_SPI1_SPI_RDY	(GPIO_PORTC | GPIO_PF | 13)
+#define PC14_PF_SPI1_SCLK	(GPIO_PORTC | GPIO_PF | 14)
+#define PC15_PF_SPI1_SS		(GPIO_PORTC | GPIO_PF | 15)
+#define PC16_PF_SPI1_MISO	(GPIO_PORTC | GPIO_PF | 16)
+#define PC17_PF_SPI1_MOSI	(GPIO_PORTC | GPIO_PF | 17)
+#define PC24_BIN_UART3_RI	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 24)
+#define PC25_BIN_UART3_DSR	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 25)
+#define PC26_AOUT_UART3_DTR	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 26)
+#define PC27_BIN_UART3_DCD	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 27)
+#define PC28_BIN_UART3_CTS	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 28)
+#define PC29_AOUT_UART3_RTS	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 29)
+#define PC30_BIN_UART3_TX	(GPIO_PORTC | GPIO_BIN | 30)
+#define PC31_AOUT_UART3_RX	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 31)
+#define PD6_PF_LSCLK		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 6)
+#define PD7_PF_REV		(GPIO_PORTD | GPIO_PF | 7)
+#define PD7_AF_UART2_DTR	(GPIO_PORTD | GPIO_AF | GPIO_IN | 7)
+#define PD7_AIN_SPI2_SCLK	(GPIO_PORTD | GPIO_AIN | 7)
+#define PD8_PF_CLS		(GPIO_PORTD | GPIO_PF | 8)
+#define PD8_AF_UART2_DCD	(GPIO_PORTD | GPIO_AF | GPIO_OUT | 8)
+#define PD8_AIN_SPI2_SS		(GPIO_PORTD | GPIO_AIN | 8)
+#define PD9_PF_PS		(GPIO_PORTD | GPIO_PF | 9)
+#define PD9_AF_UART2_RI		(GPIO_PORTD | GPIO_AF | GPIO_OUT | 9)
+#define PD9_AOUT_SPI2_RXD	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 9)
+#define PD10_PF_SPL_SPR		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 10)
+#define PD10_AF_UART2_DSR	(GPIO_PORTD | GPIO_AF | GPIO_OUT | 10)
+#define PD10_AIN_SPI2_TXD	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 10)
+#define PD11_PF_CONTRAST	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 11)
+#define PD12_PF_ACD_OE		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 12)
+#define PD13_PF_LP_HSYNC	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 13)
+#define PD14_PF_FLM_VSYNC	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 14)
+#define PD15_PF_LD0		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 15)
+#define PD16_PF_LD1		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 16)
+#define PD17_PF_LD2		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
+#define PD18_PF_LD3		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
+#define PD19_PF_LD4		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 19)
+#define PD20_PF_LD5		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 20)
+#define PD21_PF_LD6		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 21)
+#define PD22_PF_LD7		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 22)
+#define PD23_PF_LD8		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 23)
+#define PD24_PF_LD9		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 24)
+#define PD25_PF_LD10		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
+#define PD26_PF_LD11		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
+#define PD27_PF_LD12		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
+#define PD28_PF_LD13		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 28)
+#define PD29_PF_LD14		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 29)
+#define PD30_PF_LD15		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 30)
+#define PD31_PF_TMR2OUT		(GPIO_PORTD | GPIO_PF | 31)
+#define PD31_BIN_SPI2_TXD	(GPIO_PORTD | GPIO_BIN | 31)
 
-/* FIXME: This list is not completed. The correct directions are
-* missing on some (many) pins
-*/
-
-
-/* Primary GPIO pin functions */
-
-#define PA0_AIN_SPI2_CLK        (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
-#define PA0_AF_ETMTRACESYNC     (GPIO_PORTA | GPIO_AF | 0)
-#define PA1_AOUT_SPI2_RXD       (GPIO_PORTA | GPIO_AOUT | GPIO_IN | 1)
-#define PA1_PF_TIN              (GPIO_PORTA | GPIO_PF | 1)
-#define PA2_PF_PWM0             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 2)
-#define PA3_PF_CSI_MCLK         (GPIO_PORTA | GPIO_PF | 3)
-#define PA4_PF_CSI_D0           (GPIO_PORTA | GPIO_PF | 4)
-#define PA5_PF_CSI_D1           (GPIO_PORTA | GPIO_PF | 5)
-#define PA6_PF_CSI_D2           (GPIO_PORTA | GPIO_PF | 6)
-#define PA7_PF_CSI_D3           (GPIO_PORTA | GPIO_PF | 7)
-#define PA8_PF_CSI_D4           (GPIO_PORTA | GPIO_PF | 8)
-#define PA9_PF_CSI_D5           (GPIO_PORTA | GPIO_PF | 9)
-#define PA10_PF_CSI_D6          (GPIO_PORTA | GPIO_PF | 10)
-#define PA11_PF_CSI_D7          (GPIO_PORTA | GPIO_PF | 11)
-#define PA12_PF_CSI_VSYNC       (GPIO_PORTA | GPIO_PF | 12)
-#define PA13_PF_CSI_HSYNC       (GPIO_PORTA | GPIO_PF | 13)
-#define PA14_PF_CSI_PIXCLK      (GPIO_PORTA | GPIO_PF | 14)
-#define PA15_PF_I2C_SDA         (GPIO_PORTA | GPIO_PF | GPIO_OUT | 15)
-#define PA16_PF_I2C_SCL         (GPIO_PORTA | GPIO_PF | GPIO_OUT | 16)
-#define PA17_AF_ETMTRACEPKT4    (GPIO_PORTA | GPIO_AF | 17)
-#define PA17_AIN_SPI2_SS        (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17)
-#define PA18_AF_ETMTRACEPKT5    (GPIO_PORTA | GPIO_AF | 18)
-#define PA19_AF_ETMTRACEPKT6    (GPIO_PORTA | GPIO_AF | 19)
-#define PA20_AF_ETMTRACEPKT7    (GPIO_PORTA | GPIO_AF | 20)
-#define PA21_PF_A0              (GPIO_PORTA | GPIO_PF | 21)
-#define PA22_PF_CS4             (GPIO_PORTA | GPIO_PF | 22)
-#define PA23_PF_CS5             (GPIO_PORTA | GPIO_PF | 23)
-#define PA24_PF_A16             (GPIO_PORTA | GPIO_PF | 24)
-#define PA24_AF_ETMTRACEPKT0    (GPIO_PORTA | GPIO_AF | 24)
-#define PA25_PF_A17             (GPIO_PORTA | GPIO_PF | 25)
-#define PA25_AF_ETMTRACEPKT1    (GPIO_PORTA | GPIO_AF | 25)
-#define PA26_PF_A18             (GPIO_PORTA | GPIO_PF | 26)
-#define PA26_AF_ETMTRACEPKT2    (GPIO_PORTA | GPIO_AF | 26)
-#define PA27_PF_A19             (GPIO_PORTA | GPIO_PF | 27)
-#define PA27_AF_ETMTRACEPKT3    (GPIO_PORTA | GPIO_AF | 27)
-#define PA28_PF_A20             (GPIO_PORTA | GPIO_PF | 28)
-#define PA28_AF_ETMPIPESTAT0    (GPIO_PORTA | GPIO_AF | 28)
-#define PA29_PF_A21             (GPIO_PORTA | GPIO_PF | 29)
-#define PA29_AF_ETMPIPESTAT1    (GPIO_PORTA | GPIO_AF | 29)
-#define PA30_PF_A22             (GPIO_PORTA | GPIO_PF | 30)
-#define PA30_AF_ETMPIPESTAT2    (GPIO_PORTA | GPIO_AF | 30)
-#define PA31_PF_A23             (GPIO_PORTA | GPIO_PF | 31)
-#define PA31_AF_ETMTRACECLK     (GPIO_PORTA | GPIO_AF | 31)
-#define PB8_PF_SD_DAT0          (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 8)
-#define PB8_AF_MS_PIO           (GPIO_PORTB | GPIO_AF | 8)
-#define PB9_PF_SD_DAT1          (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 9)
-#define PB9_AF_MS_PI1           (GPIO_PORTB | GPIO_AF | 9)
-#define PB10_PF_SD_DAT2         (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 10)
-#define PB10_AF_MS_SCLKI        (GPIO_PORTB | GPIO_AF | 10)
-#define PB11_PF_SD_DAT3         (GPIO_PORTB | GPIO_PF | 11)
-#define PB11_AF_MS_SDIO         (GPIO_PORTB | GPIO_AF | 11)
-#define PB12_PF_SD_CLK          (GPIO_PORTB | GPIO_PF | 12)
-#define PB12_AF_MS_SCLK0        (GPIO_PORTB | GPIO_AF | 12)
-#define PB13_PF_SD_CMD          (GPIO_PORTB | GPIO_PF | GPIO_PUEN | 13)
-#define PB13_AF_MS_BS           (GPIO_PORTB | GPIO_AF | 13)
-#define PB14_AF_SSI_RXFS        (GPIO_PORTB | GPIO_AF | 14)
-#define PB15_AF_SSI_RXCLK       (GPIO_PORTB | GPIO_AF | 15)
-#define PB16_AF_SSI_RXDAT       (GPIO_PORTB | GPIO_AF | GPIO_IN | 16)
-#define PB17_AF_SSI_TXDAT       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 17)
-#define PB18_AF_SSI_TXFS        (GPIO_PORTB | GPIO_AF | 18)
-#define PB19_AF_SSI_TXCLK       (GPIO_PORTB | GPIO_AF | 19)
-#define PB20_PF_USBD_AFE        (GPIO_PORTB | GPIO_PF | 20)
-#define PB21_PF_USBD_OE         (GPIO_PORTB | GPIO_PF | 21)
-#define PB22_PF_USBD_RCV        (GPIO_PORTB | GPIO_PF | 22)
-#define PB23_PF_USBD_SUSPND     (GPIO_PORTB | GPIO_PF | 23)
-#define PB24_PF_USBD_VP         (GPIO_PORTB | GPIO_PF | 24)
-#define PB25_PF_USBD_VM         (GPIO_PORTB | GPIO_PF | 25)
-#define PB26_PF_USBD_VPO        (GPIO_PORTB | GPIO_PF | 26)
-#define PB27_PF_USBD_VMO        (GPIO_PORTB | GPIO_PF | 27)
-#define PB28_PF_UART2_CTS       (GPIO_PORTB | GPIO_PF | GPIO_OUT | 28)
-#define PB29_PF_UART2_RTS       (GPIO_PORTB | GPIO_PF | GPIO_IN | 29)
-#define PB30_PF_UART2_TXD       (GPIO_PORTB | GPIO_PF | GPIO_OUT | 30)
-#define PB31_PF_UART2_RXD       (GPIO_PORTB | GPIO_PF | GPIO_IN | 31)
-#define PC3_PF_SSI_RXFS         (GPIO_PORTC | GPIO_PF | 3)
-#define PC4_PF_SSI_RXCLK        (GPIO_PORTC | GPIO_PF | 4)
-#define PC5_PF_SSI_RXDAT        (GPIO_PORTC | GPIO_PF | GPIO_IN | 5)
-#define PC6_PF_SSI_TXDAT        (GPIO_PORTC | GPIO_PF | GPIO_OUT | 6)
-#define PC7_PF_SSI_TXFS         (GPIO_PORTC | GPIO_PF | 7)
-#define PC8_PF_SSI_TXCLK        (GPIO_PORTC | GPIO_PF | 8)
-#define PC9_PF_UART1_CTS        (GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
-#define PC10_PF_UART1_RTS       (GPIO_PORTC | GPIO_PF | GPIO_IN | 10)
-#define PC11_PF_UART1_TXD       (GPIO_PORTC | GPIO_PF | GPIO_OUT | 11)
-#define PC12_PF_UART1_RXD       (GPIO_PORTC | GPIO_PF | GPIO_IN | 12)
-#define PC13_PF_SPI1_SPI_RDY    (GPIO_PORTC | GPIO_PF | 13)
-#define PC14_PF_SPI1_SCLK       (GPIO_PORTC | GPIO_PF | 14)
-#define PC15_PF_SPI1_SS         (GPIO_PORTC | GPIO_PF | 15)
-#define PC16_PF_SPI1_MISO       (GPIO_PORTC | GPIO_PF | 16)
-#define PC17_PF_SPI1_MOSI       (GPIO_PORTC | GPIO_PF | 17)
-#define PC24_BIN_UART3_RI       (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 24)
-#define PC25_BIN_UART3_DSR      (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 25)
-#define PC26_AOUT_UART3_DTR     (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 26)
-#define PC27_BIN_UART3_DCD      (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 27)
-#define PC28_BIN_UART3_CTS      (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 28)
-#define PC29_AOUT_UART3_RTS     (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 29)
-#define PC30_BIN_UART3_TX       (GPIO_PORTC | GPIO_BIN | 30)
-#define PC31_AOUT_UART3_RX      (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 31)
-#define PD6_PF_LSCLK            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 6)
-#define PD7_PF_REV              (GPIO_PORTD | GPIO_PF | 7)
-#define PD7_AF_UART2_DTR        (GPIO_PORTD | GPIO_AF | GPIO_IN | 7)
-#define PD7_AIN_SPI2_SCLK       (GPIO_PORTD | GPIO_AIN | 7)
-#define PD8_PF_CLS              (GPIO_PORTD | GPIO_PF | 8)
-#define PD8_AF_UART2_DCD        (GPIO_PORTD | GPIO_AF | GPIO_OUT | 8)
-#define PD8_AIN_SPI2_SS         (GPIO_PORTD | GPIO_AIN | 8)
-#define PD9_PF_PS               (GPIO_PORTD | GPIO_PF | 9)
-#define PD9_AF_UART2_RI         (GPIO_PORTD | GPIO_AF | GPIO_OUT | 9)
-#define PD9_AOUT_SPI2_RXD       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 9)
-#define PD10_PF_SPL_SPR         (GPIO_PORTD | GPIO_PF | GPIO_OUT | 10)
-#define PD10_AF_UART2_DSR       (GPIO_PORTD | GPIO_AF | GPIO_OUT | 10)
-#define PD10_AIN_SPI2_TXD       (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 10)
-#define PD11_PF_CONTRAST        (GPIO_PORTD | GPIO_PF | GPIO_OUT | 11)
-#define PD12_PF_ACD_OE          (GPIO_PORTD | GPIO_PF | GPIO_OUT | 12)
-#define PD13_PF_LP_HSYNC        (GPIO_PORTD | GPIO_PF | GPIO_OUT | 13)
-#define PD14_PF_FLM_VSYNC       (GPIO_PORTD | GPIO_PF | GPIO_OUT | 14)
-#define PD15_PF_LD0             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 15)
-#define PD16_PF_LD1             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 16)
-#define PD17_PF_LD2             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
-#define PD18_PF_LD3             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
-#define PD19_PF_LD4             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 19)
-#define PD20_PF_LD5             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 20)
-#define PD21_PF_LD6             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 21)
-#define PD22_PF_LD7             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 22)
-#define PD23_PF_LD8             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 23)
-#define PD24_PF_LD9             (GPIO_PORTD | GPIO_PF | GPIO_OUT | 24)
-#define PD25_PF_LD10            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
-#define PD26_PF_LD11            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
-#define PD27_PF_LD12            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
-#define PD28_PF_LD13            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 28)
-#define PD29_PF_LD14            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 29)
-#define PD30_PF_LD15            (GPIO_PORTD | GPIO_PF | GPIO_OUT | 30)
-#define PD31_PF_TMR2OUT         (GPIO_PORTD | GPIO_PF | 31)
-#define PD31_BIN_SPI2_TXD       (GPIO_PORTD | GPIO_BIN | 31)
-
-
-#endif
+#endif /* ifndef __MACH_IOMUX_MX1_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx21.h b/arch/arm/plat-mxc/include/mach/iomux-mx21.h
index 63aaa97..1495dfd 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx21.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx21.h
@@ -1,126 +1,122 @@
 /*
-* Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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.
-*/
+ * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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_IOMUX_MX21_H__
+#define __MACH_IOMUX_MX21_H__
 
-#ifndef _MXC_IOMUX_MX21_H
-#define _MXC_IOMUX_MX21_H
-
-#ifndef GPIO_PORTA
-#error Please include mach/iomux.h
-#endif
-
+#include <mach/iomux-mx2x.h>
+#include <mach/iomux-v1.h>
 
 /* Primary GPIO pin functions */
 
-#define PB22_PF_USBH1_BYP       (GPIO_PORTB | GPIO_PF | 22)
-#define PB25_PF_USBH1_ON        (GPIO_PORTB | GPIO_PF | 25)
-#define PC5_PF_USBOTG_SDA       (GPIO_PORTC | GPIO_PF | 5)
-#define PC6_PF_USBOTG_SCL       (GPIO_PORTC | GPIO_PF | 6)
-#define PC7_PF_USBOTG_ON        (GPIO_PORTC | GPIO_PF | 7)
-#define PC8_PF_USBOTG_FS        (GPIO_PORTC | GPIO_PF | 8)
-#define PC9_PF_USBOTG_OE        (GPIO_PORTC | GPIO_PF | 9)
-#define PC10_PF_USBOTG_TXDM     (GPIO_PORTC | GPIO_PF | 10)
-#define PC11_PF_USBOTG_TXDP     (GPIO_PORTC | GPIO_PF | 11)
-#define PC12_PF_USBOTG_RXDM     (GPIO_PORTC | GPIO_PF | 12)
-#define PC13_PF_USBOTG_RXDP     (GPIO_PORTC | GPIO_PF | 13)
-#define PC16_PF_SAP_FS          (GPIO_PORTC | GPIO_PF | 16)
-#define PC17_PF_SAP_RXD         (GPIO_PORTC | GPIO_PF | 17)
-#define PC18_PF_SAP_TXD         (GPIO_PORTC | GPIO_PF | 18)
-#define PC19_PF_SAP_CLK         (GPIO_PORTC | GPIO_PF | 19)
-#define PE0_PF_TEST_WB2         (GPIO_PORTE | GPIO_PF | 0)
-#define PE1_PF_TEST_WB1         (GPIO_PORTE | GPIO_PF | 1)
-#define PE2_PF_TEST_WB0         (GPIO_PORTE | GPIO_PF | 2)
-#define PF1_PF_NFCE             (GPIO_PORTF | GPIO_PF | 1)
-#define PF3_PF_NFCLE            (GPIO_PORTF | GPIO_PF | 3)
-#define PF7_PF_NFIO0            (GPIO_PORTF | GPIO_PF | 7)
-#define PF8_PF_NFIO1            (GPIO_PORTF | GPIO_PF | 8)
-#define PF9_PF_NFIO2            (GPIO_PORTF | GPIO_PF | 9)
-#define PF10_PF_NFIO3           (GPIO_PORTF | GPIO_PF | 10)
-#define PF11_PF_NFIO4           (GPIO_PORTF | GPIO_PF | 11)
-#define PF12_PF_NFIO5           (GPIO_PORTF | GPIO_PF | 12)
-#define PF13_PF_NFIO6           (GPIO_PORTF | GPIO_PF | 13)
-#define PF14_PF_NFIO7           (GPIO_PORTF | GPIO_PF | 14)
-#define PF16_PF_RES             (GPIO_PORTF | GPIO_PF | 16)
+#define PB22_PF_USBH1_BYP	(GPIO_PORTB | GPIO_PF | 22)
+#define PB25_PF_USBH1_ON	(GPIO_PORTB | GPIO_PF | 25)
+#define PC5_PF_USBOTG_SDA	(GPIO_PORTC | GPIO_PF | 5)
+#define PC6_PF_USBOTG_SCL	(GPIO_PORTC | GPIO_PF | 6)
+#define PC7_PF_USBOTG_ON	(GPIO_PORTC | GPIO_PF | 7)
+#define PC8_PF_USBOTG_FS	(GPIO_PORTC | GPIO_PF | 8)
+#define PC9_PF_USBOTG_OE	(GPIO_PORTC | GPIO_PF | 9)
+#define PC10_PF_USBOTG_TXDM	(GPIO_PORTC | GPIO_PF | 10)
+#define PC11_PF_USBOTG_TXDP	(GPIO_PORTC | GPIO_PF | 11)
+#define PC12_PF_USBOTG_RXDM	(GPIO_PORTC | GPIO_PF | 12)
+#define PC13_PF_USBOTG_RXDP	(GPIO_PORTC | GPIO_PF | 13)
+#define PC16_PF_SAP_FS		(GPIO_PORTC | GPIO_PF | 16)
+#define PC17_PF_SAP_RXD		(GPIO_PORTC | GPIO_PF | 17)
+#define PC18_PF_SAP_TXD		(GPIO_PORTC | GPIO_PF | 18)
+#define PC19_PF_SAP_CLK		(GPIO_PORTC | GPIO_PF | 19)
+#define PE0_PF_TEST_WB2		(GPIO_PORTE | GPIO_PF | 0)
+#define PE1_PF_TEST_WB1		(GPIO_PORTE | GPIO_PF | 1)
+#define PE2_PF_TEST_WB0		(GPIO_PORTE | GPIO_PF | 2)
+#define PF1_PF_NFCE		(GPIO_PORTF | GPIO_PF | 1)
+#define PF3_PF_NFCLE		(GPIO_PORTF | GPIO_PF | 3)
+#define PF7_PF_NFIO0		(GPIO_PORTF | GPIO_PF | 7)
+#define PF8_PF_NFIO1		(GPIO_PORTF | GPIO_PF | 8)
+#define PF9_PF_NFIO2		(GPIO_PORTF | GPIO_PF | 9)
+#define PF10_PF_NFIO3		(GPIO_PORTF | GPIO_PF | 10)
+#define PF11_PF_NFIO4		(GPIO_PORTF | GPIO_PF | 11)
+#define PF12_PF_NFIO5		(GPIO_PORTF | GPIO_PF | 12)
+#define PF13_PF_NFIO6		(GPIO_PORTF | GPIO_PF | 13)
+#define PF14_PF_NFIO7		(GPIO_PORTF | GPIO_PF | 14)
+#define PF16_PF_RES		(GPIO_PORTF | GPIO_PF | 16)
 
 /* Alternate GPIO pin functions */
 
-#define PA5_AF_BMI_CLK_CS       (GPIO_PORTA | GPIO_AF | 5)
-#define PA6_AF_BMI_D0           (GPIO_PORTA | GPIO_AF | 6)
-#define PA7_AF_BMI_D1           (GPIO_PORTA | GPIO_AF | 7)
-#define PA8_AF_BMI_D2           (GPIO_PORTA | GPIO_AF | 8)
-#define PA9_AF_BMI_D3           (GPIO_PORTA | GPIO_AF | 9)
-#define PA10_AF_BMI_D4          (GPIO_PORTA | GPIO_AF | 10)
-#define PA11_AF_BMI_D5          (GPIO_PORTA | GPIO_AF | 11)
-#define PA12_AF_BMI_D6          (GPIO_PORTA | GPIO_AF | 12)
-#define PA13_AF_BMI_D7          (GPIO_PORTA | GPIO_AF | 13)
-#define PA14_AF_BMI_D8          (GPIO_PORTA | GPIO_AF | 14)
-#define PA15_AF_BMI_D9          (GPIO_PORTA | GPIO_AF | 15)
-#define PA16_AF_BMI_D10         (GPIO_PORTA | GPIO_AF | 16)
-#define PA17_AF_BMI_D11         (GPIO_PORTA | GPIO_AF | 17)
-#define PA18_AF_BMI_D12         (GPIO_PORTA | GPIO_AF | 18)
-#define PA19_AF_BMI_D13         (GPIO_PORTA | GPIO_AF | 19)
-#define PA20_AF_BMI_D14         (GPIO_PORTA | GPIO_AF | 20)
-#define PA21_AF_BMI_D15         (GPIO_PORTA | GPIO_AF | 21)
-#define PA22_AF_BMI_READ_REQ    (GPIO_PORTA | GPIO_AF | 22)
-#define PA23_AF_BMI_WRITE       (GPIO_PORTA | GPIO_AF | 23)
-#define PA29_AF_BMI_RX_FULL     (GPIO_PORTA | GPIO_AF | 29)
-#define PA30_AF_BMI_READ        (GPIO_PORTA | GPIO_AF | 30)
+#define PA5_AF_BMI_CLK_CS	(GPIO_PORTA | GPIO_AF | 5)
+#define PA6_AF_BMI_D0		(GPIO_PORTA | GPIO_AF | 6)
+#define PA7_AF_BMI_D1		(GPIO_PORTA | GPIO_AF | 7)
+#define PA8_AF_BMI_D2		(GPIO_PORTA | GPIO_AF | 8)
+#define PA9_AF_BMI_D3		(GPIO_PORTA | GPIO_AF | 9)
+#define PA10_AF_BMI_D4		(GPIO_PORTA | GPIO_AF | 10)
+#define PA11_AF_BMI_D5		(GPIO_PORTA | GPIO_AF | 11)
+#define PA12_AF_BMI_D6		(GPIO_PORTA | GPIO_AF | 12)
+#define PA13_AF_BMI_D7		(GPIO_PORTA | GPIO_AF | 13)
+#define PA14_AF_BMI_D8		(GPIO_PORTA | GPIO_AF | 14)
+#define PA15_AF_BMI_D9		(GPIO_PORTA | GPIO_AF | 15)
+#define PA16_AF_BMI_D10		(GPIO_PORTA | GPIO_AF | 16)
+#define PA17_AF_BMI_D11		(GPIO_PORTA | GPIO_AF | 17)
+#define PA18_AF_BMI_D12		(GPIO_PORTA | GPIO_AF | 18)
+#define PA19_AF_BMI_D13		(GPIO_PORTA | GPIO_AF | 19)
+#define PA20_AF_BMI_D14		(GPIO_PORTA | GPIO_AF | 20)
+#define PA21_AF_BMI_D15		(GPIO_PORTA | GPIO_AF | 21)
+#define PA22_AF_BMI_READ_REQ	(GPIO_PORTA | GPIO_AF | 22)
+#define PA23_AF_BMI_WRITE	(GPIO_PORTA | GPIO_AF | 23)
+#define PA29_AF_BMI_RX_FULL	(GPIO_PORTA | GPIO_AF | 29)
+#define PA30_AF_BMI_READ	(GPIO_PORTA | GPIO_AF | 30)
 
 /* AIN GPIO pin functions */
 
-#define PC14_AIN_SYS_CLK        (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14)
-#define PD21_AIN_USBH2_FS       (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 21)
-#define PD22_AIN_USBH2_OE       (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 22)
-#define PD23_AIN_USBH2_TXDM     (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 23)
-#define PD24_AIN_USBH2_TXDP     (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 24)
-#define PE8_AIN_IR_TXD          (GPIO_PORTE | GPIO_AIN | GPIO_OUT | 8)
-#define PF0_AIN_PC_RST          (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 0)
-#define PF1_AIN_PC_CE1          (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 1)
-#define PF2_AIN_PC_CE2          (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 2)
-#define PF3_AIN_PC_POE          (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 3)
-#define PF4_AIN_PC_OE           (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 4)
-#define PF5_AIN_PC_RW           (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 5)
+#define PC14_AIN_SYS_CLK	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14)
+#define PD21_AIN_USBH2_FS	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 21)
+#define PD22_AIN_USBH2_OE	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 22)
+#define PD23_AIN_USBH2_TXDM	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 23)
+#define PD24_AIN_USBH2_TXDP	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 24)
+#define PE8_AIN_IR_TXD		(GPIO_PORTE | GPIO_AIN | GPIO_OUT | 8)
+#define PF0_AIN_PC_RST		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 0)
+#define PF1_AIN_PC_CE1		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 1)
+#define PF2_AIN_PC_CE2		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 2)
+#define PF3_AIN_PC_POE		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 3)
+#define PF4_AIN_PC_OE		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 4)
+#define PF5_AIN_PC_RW		(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 5)
 
 /* BIN GPIO pin functions */
 
-#define PC14_BIN_SYS_CLK        (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14)
-#define PD27_BIN_EXT_DMA_GRANT  (GPIO_PORTD | GPIO_BIN | GPIO_OUT | 27)
+#define PC14_BIN_SYS_CLK	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14)
+#define PD27_BIN_EXT_DMA_GRANT	(GPIO_PORTD | GPIO_BIN | GPIO_OUT | 27)
 
 /* CIN GPIO pin functions */
 
-#define PB26_CIN_USBH1_RXDAT    (GPIO_PORTB | GPIO_CIN | GPIO_OUT | 26)
+#define PB26_CIN_USBH1_RXDAT	(GPIO_PORTB | GPIO_CIN | GPIO_OUT | 26)
 
 /* AOUT GPIO pin functions */
 
-#define PA29_AOUT_BMI_WAIT      (GPIO_PORTA | GPIO_AOUT | GPIO_IN | 29)
-#define PD19_AOUT_USBH2_RXDM    (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 19)
-#define PD20_AOUT_USBH2_RXDP    (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 20)
-#define PD25_AOUT_EXT_DMAREQ    (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 25)
-#define PD26_AOUT_USBOTG_RXDAT  (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 26)
-#define PE9_AOUT_IR_RXD         (GPIO_PORTE | GPIO_AOUT | GPIO_IN | 9)
-#define PF6_AOUT_PC_BVD2        (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 6)
-#define PF7_AOUT_PC_BVD1        (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 7)
-#define PF8_AOUT_PC_VS2         (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 8)
-#define PF9_AOUT_PC_VS1         (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 9)
-#define PF10_AOUT_PC_WP         (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 10)
-#define PF11_AOUT_PC_READY      (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 11)
-#define PF12_AOUT_PC_WAIT       (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 12)
-#define PF13_AOUT_PC_CD2        (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 13)
-#define PF14_AOUT_PC_CD1        (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 14)
+#define PA29_AOUT_BMI_WAIT	(GPIO_PORTA | GPIO_AOUT | GPIO_IN | 29)
+#define PD19_AOUT_USBH2_RXDM	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 19)
+#define PD20_AOUT_USBH2_RXDP	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 20)
+#define PD25_AOUT_EXT_DMAREQ	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 25)
+#define PD26_AOUT_USBOTG_RXDAT	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 26)
+#define PE9_AOUT_IR_RXD		(GPIO_PORTE | GPIO_AOUT | GPIO_IN | 9)
+#define PF6_AOUT_PC_BVD2	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 6)
+#define PF7_AOUT_PC_BVD1	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 7)
+#define PF8_AOUT_PC_VS2		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 8)
+#define PF9_AOUT_PC_VS1		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 9)
+#define PF10_AOUT_PC_WP		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 10)
+#define PF11_AOUT_PC_READY	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 11)
+#define PF12_AOUT_PC_WAIT	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 12)
+#define PF13_AOUT_PC_CD2	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 13)
+#define PF14_AOUT_PC_CD1	(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 14)
 
-
-#endif
+#endif /* ifndef __MACH_IOMUX_MX21_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx25.h b/arch/arm/plat-mxc/include/mach/iomux-mx25.h
index 9af494f..f39220d 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx25.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx25.h
@@ -7,7 +7,7 @@
  *    Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
  * and
  * arch/arm/plat-mxc/include/mach/iomux-mx35.h
- *    Copyright (C, NO_PAD_CTRL) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.de>
+ *    Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.de>
  *
  * The code contained herein is licensed under the GNU General Public
  * License. You may obtain a copy of the GNU General Public License
@@ -16,24 +16,11 @@
  * http://www.opensource.org/licenses/gpl-license.html
  * http://www.gnu.org/copyleft/gpl.html
  */
-#ifndef __IOMUX_MX25_H__
-#define __IOMUX_MX25_H__
+#ifndef __MACH_IOMUX_MX25_H__
+#define __MACH_IOMUX_MX25_H__
 
 #include <mach/iomux-v3.h>
 
-#ifndef GPIO_PORTA
-#error Please include mach/iomux.h
-#endif
-
-/*
- *
- * @brief MX25 I/O Pin List
- *
- * @ingroup GPIO_MX25
- */
-
-#ifndef __ASSEMBLY__
-
 /*
  * IOMUX/PAD Bit field definitions
  */
@@ -462,9 +449,11 @@
 #define MX25_PAD_GPIO_C__CAN2_TX	IOMUX_PAD(0x3f8, 0x1fc, 0x16, 0, 0, PAD_CTL_PUS_22K_UP)
 
 #define MX25_PAD_GPIO_D__GPIO_D		IOMUX_PAD(0x3fc, 0x200, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_GPIO_E__LD16		IOMUX_PAD(0x400, 0x204, 0x02, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_GPIO_D__CAN2_RX	IOMUX_PAD(0x3fc, 0x200, 0x16, 0x484, 1, PAD_CTL_PUS_22K_UP)
 
 #define MX25_PAD_GPIO_E__GPIO_E		IOMUX_PAD(0x400, 0x204, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_GPIO_F__LD17		IOMUX_PAD(0x404, 0x208, 0x02, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_GPIO_E__AUD7_TXD	IOMUX_PAD(0x400, 0x204, 0x14, 0, 0, NO_PAD_CTRL)
 
 #define MX25_PAD_GPIO_F__GPIO_F		IOMUX_PAD(0x404, 0x208, 0x10, 0, 0, NO_PAD_CTRL)
@@ -513,5 +502,4 @@
 #define MX25_PAD_CTL_GRP_DVS_SDHC1	IOMUX_PAD(0x458, 0x000, 0, 0, 0, NO_PAD_CTRL)
 #define MX25_PAD_CTL_GRP_DVS_LCD	IOMUX_PAD(0x45c, 0x000, 0, 0, 0, NO_PAD_CTRL)
 
-#endif // __ASSEMBLY__
-#endif // __IOMUX_MX25_H__
+#endif /* __MACH_IOMUX_MX25_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx27.h b/arch/arm/plat-mxc/include/mach/iomux-mx27.h
index 5ac158b..d9f9a6e 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx27.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx27.h
@@ -1,207 +1,205 @@
 /*
-* Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
-* Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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.
-*/
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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_IOMUX_MX27_H__
+#define __MACH_IOMUX_MX27_H__
 
-#ifndef _MXC_IOMUX_MX27_H
-#define _MXC_IOMUX_MX27_H
-
-#ifndef GPIO_PORTA
-#error Please include mach/iomux.h
-#endif
-
+#include <mach/iomux-mx2x.h>
+#include <mach/iomux-v1.h>
 
 /* Primary GPIO pin functions */
 
-#define PA0_PF_USBH2_CLK        (GPIO_PORTA | GPIO_PF | 0)
-#define PA1_PF_USBH2_DIR        (GPIO_PORTA | GPIO_PF | 1)
-#define PA2_PF_USBH2_DATA7      (GPIO_PORTA | GPIO_PF | 2)
-#define PA3_PF_USBH2_NXT        (GPIO_PORTA | GPIO_PF | 3)
-#define PA4_PF_USBH2_STP        (GPIO_PORTA | GPIO_PF | 4)
-#define PB22_PF_USBH1_SUSP      (GPIO_PORTB | GPIO_PF | 22)
-#define PB25_PF_USBH1_RCV       (GPIO_PORTB | GPIO_PF | 25)
-#define PC5_PF_I2C2_SDA         (GPIO_PORTC | GPIO_PF | GPIO_IN | 5)
-#define PC6_PF_I2C2_SCL         (GPIO_PORTC | GPIO_PF | GPIO_IN | 6)
-#define PC7_PF_USBOTG_DATA5     (GPIO_PORTC | GPIO_PF | GPIO_OUT | 7)
-#define PC8_PF_USBOTG_DATA6     (GPIO_PORTC | GPIO_PF | GPIO_OUT | 8)
-#define PC9_PF_USBOTG_DATA0     (GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
-#define PC10_PF_USBOTG_DATA2    (GPIO_PORTC | GPIO_PF | GPIO_OUT | 10)
-#define PC11_PF_USBOTG_DATA1    (GPIO_PORTC | GPIO_PF | GPIO_OUT | 11)
-#define PC12_PF_USBOTG_DATA4    (GPIO_PORTC | GPIO_PF | GPIO_OUT | 12)
-#define PC13_PF_USBOTG_DATA3    (GPIO_PORTC | GPIO_PF | GPIO_OUT | 13)
-#define PC16_PF_SSI4_FS         (GPIO_PORTC | GPIO_PF | GPIO_IN | 16)
-#define PC17_PF_SSI4_RXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 17)
-#define PC18_PF_SSI4_TXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 18)
-#define PC19_PF_SSI4_CLK        (GPIO_PORTC | GPIO_PF | GPIO_IN | 19)
-#define PC25_AF_GPT5_TIN        (GPIO_PORTC | GPIO_AF | 25)
-#define PC27_AF_GPT4_TIN        (GPIO_PORTC | GPIO_AF | 27)
-#define PD0_PF_SD3_CMD          (GPIO_PORTD | GPIO_PF | 0)
-#define PD1_PF_SD3_CLK          (GPIO_PORTD | GPIO_PF | 1)
-#define PD2_PF_ATA_DATA0        (GPIO_PORTD | GPIO_PF | 2)
-#define PD3_PF_ATA_DATA1        (GPIO_PORTD | GPIO_PF | 3)
-#define PD4_PF_ATA_DATA2        (GPIO_PORTD | GPIO_PF | 4)
-#define PD5_PF_ATA_DATA3        (GPIO_PORTD | GPIO_PF | 5)
-#define PD6_PF_ATA_DATA4        (GPIO_PORTD | GPIO_PF | 6)
-#define PD7_PF_ATA_DATA5        (GPIO_PORTD | GPIO_PF | 7)
-#define PD8_PF_ATA_DATA6        (GPIO_PORTD | GPIO_PF | 8)
-#define PD9_PF_ATA_DATA7        (GPIO_PORTD | GPIO_PF | 9)
-#define PD10_PF_ATA_DATA8       (GPIO_PORTD | GPIO_PF | 10)
-#define PD11_PF_ATA_DATA9       (GPIO_PORTD | GPIO_PF | 11)
-#define PD12_PF_ATA_DATA10      (GPIO_PORTD | GPIO_PF | 12)
-#define PD13_PF_ATA_DATA11      (GPIO_PORTD | GPIO_PF | 13)
-#define PD14_PF_ATA_DATA12      (GPIO_PORTD | GPIO_PF | 14)
-#define PD15_PF_ATA_DATA13      (GPIO_PORTD | GPIO_PF | 15)
-#define PD16_PF_ATA_DATA14      (GPIO_PORTD | GPIO_PF | 16)
-#define PE0_PF_USBOTG_NXT       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 0)
-#define PE1_PF_USBOTG_STP       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 1)
-#define PE2_PF_USBOTG_DIR       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 2)
-#define PE24_PF_USBOTG_CLK      (GPIO_PORTE | GPIO_PF | GPIO_OUT | 24)
-#define PE25_PF_USBOTG_DATA7    (GPIO_PORTE | GPIO_PF | GPIO_OUT | 25)
-#define PF1_PF_NFCLE            (GPIO_PORTF | GPIO_PF | 1)
-#define PF3_PF_NFCE             (GPIO_PORTF | GPIO_PF | 3)
-#define PF7_PF_PC_POE           (GPIO_PORTF | GPIO_PF | 7)
-#define PF8_PF_PC_RW            (GPIO_PORTF | GPIO_PF | 8)
-#define PF9_PF_PC_IOIS16        (GPIO_PORTF | GPIO_PF | 9)
-#define PF10_PF_PC_RST          (GPIO_PORTF | GPIO_PF | 10)
-#define PF11_PF_PC_BVD2         (GPIO_PORTF | GPIO_PF | 11)
-#define PF12_PF_PC_BVD1         (GPIO_PORTF | GPIO_PF | 12)
-#define PF13_PF_PC_VS2          (GPIO_PORTF | GPIO_PF | 13)
-#define PF14_PF_PC_VS1          (GPIO_PORTF | GPIO_PF | 14)
-#define PF16_PF_PC_PWRON        (GPIO_PORTF | GPIO_PF | 16)
-#define PF17_PF_PC_READY        (GPIO_PORTF | GPIO_PF | 17)
-#define PF18_PF_PC_WAIT         (GPIO_PORTF | GPIO_PF | 18)
-#define PF19_PF_PC_CD2          (GPIO_PORTF | GPIO_PF | 19)
-#define PF20_PF_PC_CD1          (GPIO_PORTF | GPIO_PF | 20)
-#define PF23_PF_ATA_DATA15      (GPIO_PORTF | GPIO_PF | 23)
+#define PA0_PF_USBH2_CLK	(GPIO_PORTA | GPIO_PF | 0)
+#define PA1_PF_USBH2_DIR	(GPIO_PORTA | GPIO_PF | 1)
+#define PA2_PF_USBH2_DATA7	(GPIO_PORTA | GPIO_PF | 2)
+#define PA3_PF_USBH2_NXT	(GPIO_PORTA | GPIO_PF | 3)
+#define PA4_PF_USBH2_STP	(GPIO_PORTA | GPIO_PF | 4)
+#define PB22_PF_USBH1_SUSP	(GPIO_PORTB | GPIO_PF | 22)
+#define PB25_PF_USBH1_RCV	(GPIO_PORTB | GPIO_PF | 25)
+#define PC5_PF_I2C2_SDA		(GPIO_PORTC | GPIO_PF | GPIO_IN | 5)
+#define PC6_PF_I2C2_SCL		(GPIO_PORTC | GPIO_PF | GPIO_IN | 6)
+#define PC7_PF_USBOTG_DATA5	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 7)
+#define PC8_PF_USBOTG_DATA6	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 8)
+#define PC9_PF_USBOTG_DATA0	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 9)
+#define PC10_PF_USBOTG_DATA2	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 10)
+#define PC11_PF_USBOTG_DATA1	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 11)
+#define PC12_PF_USBOTG_DATA4	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 12)
+#define PC13_PF_USBOTG_DATA3	(GPIO_PORTC | GPIO_PF | GPIO_OUT | 13)
+#define PC16_PF_SSI4_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 16)
+#define PC17_PF_SSI4_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 17)
+#define PC18_PF_SSI4_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 18)
+#define PC19_PF_SSI4_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 19)
+#define PD0_PF_SD3_CMD		(GPIO_PORTD | GPIO_PF | 0)
+#define PD1_PF_SD3_CLK		(GPIO_PORTD | GPIO_PF | 1)
+#define PD2_PF_ATA_DATA0	(GPIO_PORTD | GPIO_PF | 2)
+#define PD3_PF_ATA_DATA1	(GPIO_PORTD | GPIO_PF | 3)
+#define PD4_PF_ATA_DATA2	(GPIO_PORTD | GPIO_PF | 4)
+#define PD5_PF_ATA_DATA3	(GPIO_PORTD | GPIO_PF | 5)
+#define PD6_PF_ATA_DATA4	(GPIO_PORTD | GPIO_PF | 6)
+#define PD7_PF_ATA_DATA5	(GPIO_PORTD | GPIO_PF | 7)
+#define PD8_PF_ATA_DATA6	(GPIO_PORTD | GPIO_PF | 8)
+#define PD9_PF_ATA_DATA7	(GPIO_PORTD | GPIO_PF | 9)
+#define PD10_PF_ATA_DATA8	(GPIO_PORTD | GPIO_PF | 10)
+#define PD11_PF_ATA_DATA9	(GPIO_PORTD | GPIO_PF | 11)
+#define PD12_PF_ATA_DATA10	(GPIO_PORTD | GPIO_PF | 12)
+#define PD13_PF_ATA_DATA11	(GPIO_PORTD | GPIO_PF | 13)
+#define PD14_PF_ATA_DATA12	(GPIO_PORTD | GPIO_PF | 14)
+#define PD15_PF_ATA_DATA13	(GPIO_PORTD | GPIO_PF | 15)
+#define PD16_PF_ATA_DATA14	(GPIO_PORTD | GPIO_PF | 16)
+#define PE0_PF_USBOTG_NXT	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 0)
+#define PE1_PF_USBOTG_STP	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 1)
+#define PE2_PF_USBOTG_DIR	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 2)
+#define PE24_PF_USBOTG_CLK	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 24)
+#define PE25_PF_USBOTG_DATA7	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 25)
+#define PF1_PF_NFCLE		(GPIO_PORTF | GPIO_PF | 1)
+#define PF3_PF_NFCE		(GPIO_PORTF | GPIO_PF | 3)
+#define PF7_PF_PC_POE		(GPIO_PORTF | GPIO_PF | 7)
+#define PF8_PF_PC_RW		(GPIO_PORTF | GPIO_PF | 8)
+#define PF9_PF_PC_IOIS16	(GPIO_PORTF | GPIO_PF | 9)
+#define PF10_PF_PC_RST		(GPIO_PORTF | GPIO_PF | 10)
+#define PF11_PF_PC_BVD2		(GPIO_PORTF | GPIO_PF | 11)
+#define PF12_PF_PC_BVD1		(GPIO_PORTF | GPIO_PF | 12)
+#define PF13_PF_PC_VS2		(GPIO_PORTF | GPIO_PF | 13)
+#define PF14_PF_PC_VS1		(GPIO_PORTF | GPIO_PF | 14)
+#define PF16_PF_PC_PWRON	(GPIO_PORTF | GPIO_PF | 16)
+#define PF17_PF_PC_READY	(GPIO_PORTF | GPIO_PF | 17)
+#define PF18_PF_PC_WAIT		(GPIO_PORTF | GPIO_PF | 18)
+#define PF19_PF_PC_CD2		(GPIO_PORTF | GPIO_PF | 19)
+#define PF20_PF_PC_CD1		(GPIO_PORTF | GPIO_PF | 20)
+#define PF23_PF_ATA_DATA15	(GPIO_PORTF | GPIO_PF | 23)
 
 /* Alternate GPIO pin functions */
 
-#define PB4_AF_MSHC_DATA0       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 4)
-#define PB5_AF_MSHC_DATA1       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 5)
-#define PB6_AF_MSHC_DATA2       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 6)
-#define PB7_AF_MSHC_DATA4       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 7)
-#define PB8_AF_MSHC_BS          (GPIO_PORTB | GPIO_AF | GPIO_OUT | 8)
-#define PB9_AF_MSHC_SCLK        (GPIO_PORTB | GPIO_AF | GPIO_OUT | 9)
-#define PB10_AF_UART6_TXD       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 10)
-#define PB11_AF_UART6_RXD       (GPIO_PORTB | GPIO_AF | GPIO_IN | 11)
-#define PB12_AF_UART6_CTS       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 12)
-#define PB13_AF_UART6_RTS       (GPIO_PORTB | GPIO_AF | GPIO_IN | 13)
-#define PB18_AF_UART5_TXD       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 18)
-#define PB19_AF_UART5_RXD       (GPIO_PORTB | GPIO_AF | GPIO_IN | 19)
-#define PB20_AF_UART5_CTS       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 20)
-#define PB21_AF_UART5_RTS       (GPIO_PORTB | GPIO_AF | GPIO_IN | 21)
-#define PC8_AF_FEC_MDIO         (GPIO_PORTC | GPIO_AF | GPIO_IN | 8)
-#define PC24_AF_GPT5_TOUT       (GPIO_PORTC | GPIO_AF | 24)
-#define PC26_AF_GPT4_TOUT       (GPIO_PORTC | GPIO_AF | 26)
-#define PD1_AF_ETMTRACE_PKT15   (GPIO_PORTD | GPIO_AF | 1)
-#define PD6_AF_ETMTRACE_PKT14   (GPIO_PORTD | GPIO_AF | 6)
-#define PD7_AF_ETMTRACE_PKT13   (GPIO_PORTD | GPIO_AF | 7)
-#define PD9_AF_ETMTRACE_PKT12   (GPIO_PORTD | GPIO_AF | 9)
-#define PD2_AF_SD3_D0           (GPIO_PORTD | GPIO_AF | 2)
-#define PD3_AF_SD3_D1           (GPIO_PORTD | GPIO_AF | 3)
-#define PD4_AF_SD3_D2           (GPIO_PORTD | GPIO_AF | 4)
-#define PD5_AF_SD3_D3           (GPIO_PORTD | GPIO_AF | 5)
-#define PD8_AF_FEC_MDIO         (GPIO_PORTD | GPIO_AF | GPIO_IN | 8)
-#define PD10_AF_ETMTRACE_PKT11  (GPIO_PORTD | GPIO_AF | 10)
-#define PD11_AF_ETMTRACE_PKT10  (GPIO_PORTD | GPIO_AF | 11)
-#define PD12_AF_ETMTRACE_PKT9   (GPIO_PORTD | GPIO_AF | 12)
-#define PD13_AF_ETMTRACE_PKT8   (GPIO_PORTD | GPIO_AF | 13)
-#define PD14_AF_ETMTRACE_PKT7   (GPIO_PORTD | GPIO_AF | 14)
-#define PD15_AF_ETMTRACE_PKT6   (GPIO_PORTD | GPIO_AF | 15)
-#define PD16_AF_ETMTRACE_PKT5   (GPIO_PORTD | GPIO_AF | 16)
-#define PF1_AF_ETMTRACE_PKT0    (GPIO_PORTF | GPIO_AF | 1)
-#define PF3_AF_ETMTRACE_PKT2    (GPIO_PORTF | GPIO_AF | 3)
-#define PF5_AF_ETMPIPESTAT11    (GPIO_PORTF | GPIO_AF | 5)
-#define PF7_AF_ATA_BUFFER_EN    (GPIO_PORTF | GPIO_AF | 7)
-#define PF8_AF_ATA_IORDY        (GPIO_PORTF | GPIO_AF | 8)
-#define PF9_AF_ATA_INTRQ        (GPIO_PORTF | GPIO_AF | 9)
-#define PF10_AF_ATA_RESET       (GPIO_PORTF | GPIO_AF | 10)
-#define PF11_AF_ATA_DMACK       (GPIO_PORTF | GPIO_AF | 11)
-#define PF12_AF_ATA_DMAREQ      (GPIO_PORTF | GPIO_AF | 12)
-#define PF13_AF_ATA_DA0         (GPIO_PORTF | GPIO_AF | 13)
-#define PF14_AF_ATA_DA1         (GPIO_PORTF | GPIO_AF | 14)
-#define PF15_AF_ETMTRACE_SYNC   (GPIO_PORTF | GPIO_AF | 15)
-#define PF16_AF_ATA_DA2         (GPIO_PORTF | GPIO_AF | 16)
-#define PF17_AF_ATA_CS0         (GPIO_PORTF | GPIO_AF | 17)
-#define PF18_AF_ATA_CS1         (GPIO_PORTF | GPIO_AF | 18)
-#define PF19_AF_ATA_DIOW        (GPIO_PORTF | GPIO_AF | 19)
-#define PF20_AF_ATA_DIOR        (GPIO_PORTF | GPIO_AF | 20)
-#define PF22_AF_ETMTRACE_CLK    (GPIO_PORTF | GPIO_AF | 22)
-#define PF23_AF_ETMTRACE_PKT4   (GPIO_PORTF | GPIO_AF | 23)
+#define PB4_AF_MSHC_DATA0	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 4)
+#define PB5_AF_MSHC_DATA1	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 5)
+#define PB6_AF_MSHC_DATA2	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 6)
+#define PB7_AF_MSHC_DATA4	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 7)
+#define PB8_AF_MSHC_BS		(GPIO_PORTB | GPIO_AF | GPIO_OUT | 8)
+#define PB9_AF_MSHC_SCLK	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 9)
+#define PB10_AF_UART6_TXD	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 10)
+#define PB11_AF_UART6_RXD	(GPIO_PORTB | GPIO_AF | GPIO_IN | 11)
+#define PB12_AF_UART6_CTS	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 12)
+#define PB13_AF_UART6_RTS	(GPIO_PORTB | GPIO_AF | GPIO_IN | 13)
+#define PB18_AF_UART5_TXD	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 18)
+#define PB19_AF_UART5_RXD	(GPIO_PORTB | GPIO_AF | GPIO_IN | 19)
+#define PB20_AF_UART5_CTS	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 20)
+#define PB21_AF_UART5_RTS	(GPIO_PORTB | GPIO_AF | GPIO_IN | 21)
+#define PC8_AF_FEC_MDIO		(GPIO_PORTC | GPIO_AF | GPIO_IN | 8)
+#define PC24_AF_GPT5_TOUT	(GPIO_PORTC | GPIO_AF | 24)
+#define PC25_AF_GPT5_TIN	(GPIO_PORTC | GPIO_AF | 25)
+#define PC26_AF_GPT4_TOUT	(GPIO_PORTC | GPIO_AF | 26)
+#define PC27_AF_GPT4_TIN	(GPIO_PORTC | GPIO_AF | 27)
+#define PD1_AF_ETMTRACE_PKT15	(GPIO_PORTD | GPIO_AF | 1)
+#define PD6_AF_ETMTRACE_PKT14	(GPIO_PORTD | GPIO_AF | 6)
+#define PD7_AF_ETMTRACE_PKT13	(GPIO_PORTD | GPIO_AF | 7)
+#define PD9_AF_ETMTRACE_PKT12	(GPIO_PORTD | GPIO_AF | 9)
+#define PD2_AF_SD3_D0		(GPIO_PORTD | GPIO_AF | 2)
+#define PD3_AF_SD3_D1		(GPIO_PORTD | GPIO_AF | 3)
+#define PD4_AF_SD3_D2		(GPIO_PORTD | GPIO_AF | 4)
+#define PD5_AF_SD3_D3		(GPIO_PORTD | GPIO_AF | 5)
+#define PD8_AF_FEC_MDIO		(GPIO_PORTD | GPIO_AF | GPIO_IN | 8)
+#define PD10_AF_ETMTRACE_PKT11	(GPIO_PORTD | GPIO_AF | 10)
+#define PD11_AF_ETMTRACE_PKT10	(GPIO_PORTD | GPIO_AF | 11)
+#define PD12_AF_ETMTRACE_PKT9	(GPIO_PORTD | GPIO_AF | 12)
+#define PD13_AF_ETMTRACE_PKT8	(GPIO_PORTD | GPIO_AF | 13)
+#define PD14_AF_ETMTRACE_PKT7	(GPIO_PORTD | GPIO_AF | 14)
+#define PD15_AF_ETMTRACE_PKT6	(GPIO_PORTD | GPIO_AF | 15)
+#define PD16_AF_ETMTRACE_PKT5	(GPIO_PORTD | GPIO_AF | 16)
+#define PF1_AF_ETMTRACE_PKT0	(GPIO_PORTF | GPIO_AF | 1)
+#define PF3_AF_ETMTRACE_PKT2	(GPIO_PORTF | GPIO_AF | 3)
+#define PF5_AF_ETMPIPESTAT11	(GPIO_PORTF | GPIO_AF | 5)
+#define PF7_AF_ATA_BUFFER_EN	(GPIO_PORTF | GPIO_AF | 7)
+#define PF8_AF_ATA_IORDY	(GPIO_PORTF | GPIO_AF | 8)
+#define PF9_AF_ATA_INTRQ	(GPIO_PORTF | GPIO_AF | 9)
+#define PF10_AF_ATA_RESET	(GPIO_PORTF | GPIO_AF | 10)
+#define PF11_AF_ATA_DMACK	(GPIO_PORTF | GPIO_AF | 11)
+#define PF12_AF_ATA_DMAREQ	(GPIO_PORTF | GPIO_AF | 12)
+#define PF13_AF_ATA_DA0		(GPIO_PORTF | GPIO_AF | 13)
+#define PF14_AF_ATA_DA1		(GPIO_PORTF | GPIO_AF | 14)
+#define PF15_AF_ETMTRACE_SYNC	(GPIO_PORTF | GPIO_AF | 15)
+#define PF16_AF_ATA_DA2		(GPIO_PORTF | GPIO_AF | 16)
+#define PF17_AF_ATA_CS0		(GPIO_PORTF | GPIO_AF | 17)
+#define PF18_AF_ATA_CS1		(GPIO_PORTF | GPIO_AF | 18)
+#define PF19_AF_ATA_DIOW	(GPIO_PORTF | GPIO_AF | 19)
+#define PF20_AF_ATA_DIOR	(GPIO_PORTF | GPIO_AF | 20)
+#define PF22_AF_ETMTRACE_CLK	(GPIO_PORTF | GPIO_AF | 22)
+#define PF23_AF_ETMTRACE_PKT4	(GPIO_PORTF | GPIO_AF | 23)
 
 /* AIN GPIO pin functions */
 
-#define PC14_AIN_SSI1_MCLK      (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14)
-#define PC15_AIN_GPT6_TOUT      (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 15)
-#define PD0_AIN_FEC_TXD0        (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 0)
-#define PD1_AIN_FEC_TXD1        (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 1)
-#define PD2_AIN_FEC_TXD2        (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 2)
-#define PD3_AIN_FEC_TXD3        (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 3)
-#define PD9_AIN_FEC_MDC         (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 9)
-#define PD16_AIN_FEC_TX_ER      (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 16)
-#define PD27_AIN_EXT_DMA_GRANT  (GPIO_PORTD | GPIO_AIN | GPIO_OUT | 27)
-#define PF23_AIN_FEC_TX_EN      (GPIO_PORTF | GPIO_AIN | GPIO_OUT | 23)
+#define PC14_AIN_SSI1_MCLK	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 14)
+#define PC15_AIN_GPT6_TOUT	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 15)
+#define PD0_AIN_FEC_TXD0	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 0)
+#define PD1_AIN_FEC_TXD1	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 1)
+#define PD2_AIN_FEC_TXD2	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 2)
+#define PD3_AIN_FEC_TXD3	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 3)
+#define PD9_AIN_FEC_MDC		(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 9)
+#define PD16_AIN_FEC_TX_ER	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 16)
+#define PD27_AIN_EXT_DMA_GRANT	(GPIO_PORTD | GPIO_AIN | GPIO_OUT | 27)
+#define PF23_AIN_FEC_TX_EN	(GPIO_PORTF | GPIO_AIN | GPIO_OUT | 23)
 
 /* BIN GPIO pin functions */
 
-#define PC14_BIN_SSI2_MCLK      (GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14)
+#define PC14_BIN_SSI2_MCLK	(GPIO_PORTC | GPIO_BIN | GPIO_OUT | 14)
 
 /* CIN GPIO pin functions */
 
-#define PD2_CIN_SLCDC1_DAT0     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 2)
-#define PD3_CIN_SLCDC1_DAT1     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 3)
-#define PD4_CIN_SLCDC1_DAT2     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 4)
-#define PD5_CIN_SLCDC1_DAT3     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 5)
-#define PD6_CIN_SLCDC1_DAT4     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 6)
-#define PD7_CIN_SLCDC1_DAT5     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 7)
-#define PD8_CIN_SLCDC1_DAT6     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 8)
-#define PD9_CIN_SLCDC1_DAT7     (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 9)
-#define PD10_CIN_SLCDC1_DAT8    (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 10)
-#define PD11_CIN_SLCDC1_DAT9    (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 11)
-#define PD12_CIN_SLCDC1_DAT10   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 12)
-#define PD13_CIN_SLCDC1_DAT11   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 13)
-#define PD14_CIN_SLCDC1_DAT12   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 14)
-#define PD15_CIN_SLCDC1_DAT13   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 15)
-#define PD16_CIN_SLCDC1_DAT14   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 16)
-#define PD23_CIN_SLCDC1_DAT15   (GPIO_PORTD | GPIO_CIN | GPIO_OUT | 23)
-#define PF27_CIN_EXT_DMA_GRANT  (GPIO_PORTF | GPIO_CIN | GPIO_OUT | 27)
+#define PD2_CIN_SLCDC1_DAT0	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 2)
+#define PD3_CIN_SLCDC1_DAT1	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 3)
+#define PD4_CIN_SLCDC1_DAT2	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 4)
+#define PD5_CIN_SLCDC1_DAT3	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 5)
+#define PD6_CIN_SLCDC1_DAT4	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 6)
+#define PD7_CIN_SLCDC1_DAT5	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 7)
+#define PD8_CIN_SLCDC1_DAT6	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 8)
+#define PD9_CIN_SLCDC1_DAT7	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 9)
+#define PD10_CIN_SLCDC1_DAT8	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 10)
+#define PD11_CIN_SLCDC1_DAT9	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 11)
+#define PD12_CIN_SLCDC1_DAT10	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 12)
+#define PD13_CIN_SLCDC1_DAT11	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 13)
+#define PD14_CIN_SLCDC1_DAT12	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 14)
+#define PD15_CIN_SLCDC1_DAT13	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 15)
+#define PD16_CIN_SLCDC1_DAT14	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 16)
+#define PD23_CIN_SLCDC1_DAT15	(GPIO_PORTD | GPIO_CIN | GPIO_OUT | 23)
+#define PF27_CIN_EXT_DMA_GRANT	(GPIO_PORTF | GPIO_CIN | GPIO_OUT | 27)
 /* LCDC_TESTx on PBxx omitted, because it's not clear what they do */
 
 /* AOUT GPIO pin functions */
 
-#define PC14_AOUT_GPT6_TIN      (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 14)
-#define PD4_AOUT_FEC_RX_ER      (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 4)
-#define PD5_AOUT_FEC_RXD1       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 5)
-#define PD6_AOUT_FEC_RXD2       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 6)
-#define PD7_AOUT_FEC_RXD3       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 7)
-#define PD10_AOUT_FEC_CRS       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 10)
-#define PD11_AOUT_FEC_TX_CLK    (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 11)
-#define PD12_AOUT_FEC_RXD0      (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 12)
-#define PD13_AOUT_FEC_RX_DV     (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 13)
-#define PD14_AOUT_FEC_RX_CLK    (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 14)
-#define PD15_AOUT_FEC_COL       (GPIO_PORTD | GPIO_AOUT | GPIO_IN | 15)
+#define PC14_AOUT_GPT6_TIN	(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 14)
+#define PD4_AOUT_FEC_RX_ER	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 4)
+#define PD5_AOUT_FEC_RXD1	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 5)
+#define PD6_AOUT_FEC_RXD2	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 6)
+#define PD7_AOUT_FEC_RXD3	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 7)
+#define PD10_AOUT_FEC_CRS	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 10)
+#define PD11_AOUT_FEC_TX_CLK	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 11)
+#define PD12_AOUT_FEC_RXD0	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 12)
+#define PD13_AOUT_FEC_RX_DV	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 13)
+#define PD14_AOUT_FEC_RX_CLK	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 14)
+#define PD15_AOUT_FEC_COL	(GPIO_PORTD | GPIO_AOUT | GPIO_IN | 15)
 
-#define PC17_BOUT_PC_IOIS16     (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 17)
-#define PC18_BOUT_PC_BVD2       (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 18)
-#define PC19_BOUT_PC_BVD1       (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 19)
-#define PC28_BOUT_PC_BVD2       (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 28)
-#define PC29_BOUT_PC_VS1        (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 29)
-#define PC30_BOUT_PC_READY      (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 30)
-#define PC31_BOUT_PC_WAIT       (GPIO_PORTC | GPIO_BOUT | GPIO_IN | 31)
+/* BOUT GPIO pin functions */
 
+#define PC17_BOUT_PC_IOIS16	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 17)
+#define PC18_BOUT_PC_BVD2	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 18)
+#define PC19_BOUT_PC_BVD1	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 19)
+#define PC28_BOUT_PC_BVD2	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 28)
+#define PC29_BOUT_PC_VS1	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 29)
+#define PC30_BOUT_PC_READY	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 30)
+#define PC31_BOUT_PC_WAIT	(GPIO_PORTC | GPIO_BOUT | GPIO_IN | 31)
 
-#endif /* _MXC_GPIO_MX1_MX2_H */
+#endif /* __MACH_IOMUX_MX27_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx2x.h b/arch/arm/plat-mxc/include/mach/iomux-mx2x.h
index fb5ae63..c4f116d 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx2x.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx2x.h
@@ -1,237 +1,230 @@
 /*
-* Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
-* Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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 _MXC_IOMUX_MX2x_H
-#define _MXC_IOMUX_MX2x_H
-
-#ifndef GPIO_PORTA
-#error Please include mach/iomux.h
-#endif
-
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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_IOMUX_MX2x_H__
+#define __MACH_IOMUX_MX2x_H__
 
 /* Primary GPIO pin functions */
 
-#define PA5_PF_LSCLK            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 5)
-#define PA6_PF_LD0              (GPIO_PORTA | GPIO_PF | GPIO_OUT | 6)
-#define PA7_PF_LD1              (GPIO_PORTA | GPIO_PF | GPIO_OUT | 7)
-#define PA8_PF_LD2              (GPIO_PORTA | GPIO_PF | GPIO_OUT | 8)
-#define PA9_PF_LD3              (GPIO_PORTA | GPIO_PF | GPIO_OUT | 9)
-#define PA10_PF_LD4             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 10)
-#define PA11_PF_LD5             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 11)
-#define PA12_PF_LD6             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 12)
-#define PA13_PF_LD7             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 13)
-#define PA14_PF_LD8             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 14)
-#define PA15_PF_LD9             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 15)
-#define PA16_PF_LD10            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 16)
-#define PA17_PF_LD11            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 17)
-#define PA18_PF_LD12            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 18)
-#define PA19_PF_LD13            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 19)
-#define PA20_PF_LD14            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 20)
-#define PA21_PF_LD15            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 21)
-#define PA22_PF_LD16            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 22)
-#define PA23_PF_LD17            (GPIO_PORTA | GPIO_PF | GPIO_OUT | 23)
-#define PA24_PF_REV             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 24)
-#define PA25_PF_CLS             (GPIO_PORTA | GPIO_PF | GPIO_OUT | 25)
-#define PA26_PF_PS              (GPIO_PORTA | GPIO_PF | GPIO_OUT | 26)
-#define PA27_PF_SPL_SPR         (GPIO_PORTA | GPIO_PF | GPIO_OUT | 27)
-#define PA28_PF_HSYNC           (GPIO_PORTA | GPIO_PF | GPIO_OUT | 28)
-#define PA29_PF_VSYNC           (GPIO_PORTA | GPIO_PF | GPIO_OUT | 29)
-#define PA30_PF_CONTRAST        (GPIO_PORTA | GPIO_PF | GPIO_OUT | 30)
-#define PA31_PF_OE_ACD          (GPIO_PORTA | GPIO_PF | GPIO_OUT | 31)
-#define PB4_PF_SD2_D0           (GPIO_PORTB | GPIO_PF | 4)
-#define PB5_PF_SD2_D1           (GPIO_PORTB | GPIO_PF | 5)
-#define PB6_PF_SD2_D2           (GPIO_PORTB | GPIO_PF | 6)
-#define PB7_PF_SD2_D3           (GPIO_PORTB | GPIO_PF | 7)
-#define PB8_PF_SD2_CMD          (GPIO_PORTB | GPIO_PF | 8)
-#define PB9_PF_SD2_CLK          (GPIO_PORTB | GPIO_PF | 9)
-#define PB10_PF_CSI_D0          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 10)
-#define PB11_PF_CSI_D1          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 11)
-#define PB12_PF_CSI_D2          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 12)
-#define PB13_PF_CSI_D3          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 13)
-#define PB14_PF_CSI_D4          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 14)
-#define PB15_PF_CSI_MCLK        (GPIO_PORTB | GPIO_PF | GPIO_OUT | 15)
-#define PB16_PF_CSI_PIXCLK      (GPIO_PORTB | GPIO_PF | GPIO_OUT | 16)
-#define PB17_PF_CSI_D5          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 17)
-#define PB18_PF_CSI_D6          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 18)
-#define PB19_PF_CSI_D7          (GPIO_PORTB | GPIO_PF | GPIO_OUT | 19)
-#define PB20_PF_CSI_VSYNC       (GPIO_PORTB | GPIO_PF | GPIO_OUT | 20)
-#define PB21_PF_CSI_HSYNC       (GPIO_PORTB | GPIO_PF | GPIO_OUT | 21)
-#define PB23_PF_USB_PWR         (GPIO_PORTB | GPIO_PF | 23)
-#define PB24_PF_USB_OC          (GPIO_PORTB | GPIO_PF | 24)
-#define PB26_PF_USBH1_FS        (GPIO_PORTB | GPIO_PF | 26)
-#define PB27_PF_USBH1_OE        (GPIO_PORTB | GPIO_PF | 27)
-#define PB28_PF_USBH1_TXDM      (GPIO_PORTB | GPIO_PF | 28)
-#define PB29_PF_USBH1_TXDP      (GPIO_PORTB | GPIO_PF | 29)
-#define PB30_PF_USBH1_RXDM      (GPIO_PORTB | GPIO_PF | 30)
-#define PB31_PF_USBH1_RXDP      (GPIO_PORTB | GPIO_PF | 31)
-#define PC14_PF_TOUT            (GPIO_PORTC | GPIO_PF | 14)
-#define PC15_PF_TIN             (GPIO_PORTC | GPIO_PF | 15)
-#define PC20_PF_SSI1_FS         (GPIO_PORTC | GPIO_PF | GPIO_IN | 20)
-#define PC21_PF_SSI1_RXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 21)
-#define PC22_PF_SSI1_TXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 22)
-#define PC23_PF_SSI1_CLK        (GPIO_PORTC | GPIO_PF | GPIO_IN | 23)
-#define PC24_PF_SSI2_FS         (GPIO_PORTC | GPIO_PF | GPIO_IN | 24)
-#define PC25_PF_SSI2_RXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 25)
-#define PC26_PF_SSI2_TXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 26)
-#define PC27_PF_SSI2_CLK        (GPIO_PORTC | GPIO_PF | GPIO_IN | 27)
-#define PC28_PF_SSI3_FS         (GPIO_PORTC | GPIO_PF | GPIO_IN | 28)
-#define PC29_PF_SSI3_RXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 29)
-#define PC30_PF_SSI3_TXD        (GPIO_PORTC | GPIO_PF | GPIO_IN | 30)
-#define PC31_PF_SSI3_CLK        (GPIO_PORTC | GPIO_PF | GPIO_IN | 31)
-#define PD17_PF_I2C_DATA        (GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
-#define PD18_PF_I2C_CLK         (GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
-#define PD19_PF_CSPI2_SS2       (GPIO_PORTD | GPIO_PF | 19)
-#define PD20_PF_CSPI2_SS1       (GPIO_PORTD | GPIO_PF | 20)
-#define PD21_PF_CSPI2_SS0       (GPIO_PORTD | GPIO_PF | 21)
-#define PD22_PF_CSPI2_SCLK      (GPIO_PORTD | GPIO_PF | 22)
-#define PD23_PF_CSPI2_MISO      (GPIO_PORTD | GPIO_PF | 23)
-#define PD24_PF_CSPI2_MOSI      (GPIO_PORTD | GPIO_PF | 24)
-#define PD25_PF_CSPI1_RDY       (GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
-#define PD26_PF_CSPI1_SS2       (GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
-#define PD27_PF_CSPI1_SS1       (GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
-#define PD28_PF_CSPI1_SS0       (GPIO_PORTD | GPIO_PF | GPIO_OUT | 28)
-#define PD29_PF_CSPI1_SCLK      (GPIO_PORTD | GPIO_PF | GPIO_OUT | 29)
-#define PD30_PF_CSPI1_MISO      (GPIO_PORTD | GPIO_PF | GPIO_IN | 30)
-#define PD31_PF_CSPI1_MOSI      (GPIO_PORTD | GPIO_PF | GPIO_OUT | 31)
-#define PE3_PF_UART2_CTS        (GPIO_PORTE | GPIO_PF | GPIO_OUT | 3)
-#define PE4_PF_UART2_RTS        (GPIO_PORTE | GPIO_PF | GPIO_IN | 4)
-#define PE5_PF_PWMO             (GPIO_PORTE | GPIO_PF | 5)
-#define PE6_PF_UART2_TXD        (GPIO_PORTE | GPIO_PF | GPIO_OUT | 6)
-#define PE7_PF_UART2_RXD        (GPIO_PORTE | GPIO_PF | GPIO_IN | 7)
-#define PE8_PF_UART3_TXD        (GPIO_PORTE | GPIO_PF | GPIO_OUT | 8)
-#define PE9_PF_UART3_RXD        (GPIO_PORTE | GPIO_PF | GPIO_IN | 9)
-#define PE10_PF_UART3_CTS       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 10)
-#define PE11_PF_UART3_RTS       (GPIO_PORTE | GPIO_PF | GPIO_IN | 11)
-#define PE12_PF_UART1_TXD       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 12)
-#define PE13_PF_UART1_RXD       (GPIO_PORTE | GPIO_PF | GPIO_IN | 13)
-#define PE14_PF_UART1_CTS       (GPIO_PORTE | GPIO_PF | GPIO_OUT | 14)
-#define PE15_PF_UART1_RTS       (GPIO_PORTE | GPIO_PF | GPIO_IN | 15)
-#define PE16_PF_RTCK            (GPIO_PORTE | GPIO_PF | GPIO_OUT | 16)
-#define PE17_PF_RESET_OUT       (GPIO_PORTE | GPIO_PF | 17)
-#define PE18_PF_SD1_D0          (GPIO_PORTE | GPIO_PF | 18)
-#define PE19_PF_SD1_D1          (GPIO_PORTE | GPIO_PF | 19)
-#define PE20_PF_SD1_D2          (GPIO_PORTE | GPIO_PF | 20)
-#define PE21_PF_SD1_D3          (GPIO_PORTE | GPIO_PF | 21)
-#define PE22_PF_SD1_CMD         (GPIO_PORTE | GPIO_PF | 22)
-#define PE23_PF_SD1_CLK         (GPIO_PORTE | GPIO_PF | 23)
-#define PF0_PF_NRFB             (GPIO_PORTF | GPIO_PF | 0)
-#define PF2_PF_NFWP             (GPIO_PORTF | GPIO_PF | 2)
-#define PF4_PF_NFALE            (GPIO_PORTF | GPIO_PF | 4)
-#define PF5_PF_NFRE             (GPIO_PORTF | GPIO_PF | 5)
-#define PF6_PF_NFWE             (GPIO_PORTF | GPIO_PF | 6)
-#define PF15_PF_CLKO            (GPIO_PORTF | GPIO_PF | 15)
-#define PF21_PF_CS4             (GPIO_PORTF | GPIO_PF | 21)
-#define PF22_PF_CS5             (GPIO_PORTF | GPIO_PF | 22)
+#define PA5_PF_LSCLK		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 5)
+#define PA6_PF_LD0		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 6)
+#define PA7_PF_LD1		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 7)
+#define PA8_PF_LD2		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 8)
+#define PA9_PF_LD3		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 9)
+#define PA10_PF_LD4		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 10)
+#define PA11_PF_LD5		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 11)
+#define PA12_PF_LD6		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 12)
+#define PA13_PF_LD7		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 13)
+#define PA14_PF_LD8		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 14)
+#define PA15_PF_LD9		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 15)
+#define PA16_PF_LD10		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 16)
+#define PA17_PF_LD11		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 17)
+#define PA18_PF_LD12		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 18)
+#define PA19_PF_LD13		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 19)
+#define PA20_PF_LD14		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 20)
+#define PA21_PF_LD15		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 21)
+#define PA22_PF_LD16		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 22)
+#define PA23_PF_LD17		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 23)
+#define PA24_PF_REV		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 24)
+#define PA25_PF_CLS		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 25)
+#define PA26_PF_PS		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 26)
+#define PA27_PF_SPL_SPR		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 27)
+#define PA28_PF_HSYNC		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 28)
+#define PA29_PF_VSYNC		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 29)
+#define PA30_PF_CONTRAST	(GPIO_PORTA | GPIO_PF | GPIO_OUT | 30)
+#define PA31_PF_OE_ACD		(GPIO_PORTA | GPIO_PF | GPIO_OUT | 31)
+#define PB4_PF_SD2_D0		(GPIO_PORTB | GPIO_PF | 4)
+#define PB5_PF_SD2_D1		(GPIO_PORTB | GPIO_PF | 5)
+#define PB6_PF_SD2_D2		(GPIO_PORTB | GPIO_PF | 6)
+#define PB7_PF_SD2_D3		(GPIO_PORTB | GPIO_PF | 7)
+#define PB8_PF_SD2_CMD		(GPIO_PORTB | GPIO_PF | 8)
+#define PB9_PF_SD2_CLK		(GPIO_PORTB | GPIO_PF | 9)
+#define PB10_PF_CSI_D0		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 10)
+#define PB11_PF_CSI_D1		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 11)
+#define PB12_PF_CSI_D2		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 12)
+#define PB13_PF_CSI_D3		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 13)
+#define PB14_PF_CSI_D4		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 14)
+#define PB15_PF_CSI_MCLK	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 15)
+#define PB16_PF_CSI_PIXCLK	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 16)
+#define PB17_PF_CSI_D5		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 17)
+#define PB18_PF_CSI_D6		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 18)
+#define PB19_PF_CSI_D7		(GPIO_PORTB | GPIO_PF | GPIO_OUT | 19)
+#define PB20_PF_CSI_VSYNC	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 20)
+#define PB21_PF_CSI_HSYNC	(GPIO_PORTB | GPIO_PF | GPIO_OUT | 21)
+#define PB23_PF_USB_PWR		(GPIO_PORTB | GPIO_PF | 23)
+#define PB24_PF_USB_OC		(GPIO_PORTB | GPIO_PF | 24)
+#define PB26_PF_USBH1_FS	(GPIO_PORTB | GPIO_PF | 26)
+#define PB27_PF_USBH1_OE	(GPIO_PORTB | GPIO_PF | 27)
+#define PB28_PF_USBH1_TXDM	(GPIO_PORTB | GPIO_PF | 28)
+#define PB29_PF_USBH1_TXDP	(GPIO_PORTB | GPIO_PF | 29)
+#define PB30_PF_USBH1_RXDM	(GPIO_PORTB | GPIO_PF | 30)
+#define PB31_PF_USBH1_RXDP	(GPIO_PORTB | GPIO_PF | 31)
+#define PC14_PF_TOUT		(GPIO_PORTC | GPIO_PF | 14)
+#define PC15_PF_TIN		(GPIO_PORTC | GPIO_PF | 15)
+#define PC20_PF_SSI1_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 20)
+#define PC21_PF_SSI1_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 21)
+#define PC22_PF_SSI1_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 22)
+#define PC23_PF_SSI1_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 23)
+#define PC24_PF_SSI2_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 24)
+#define PC25_PF_SSI2_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 25)
+#define PC26_PF_SSI2_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 26)
+#define PC27_PF_SSI2_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 27)
+#define PC28_PF_SSI3_FS		(GPIO_PORTC | GPIO_PF | GPIO_IN | 28)
+#define PC29_PF_SSI3_RXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 29)
+#define PC30_PF_SSI3_TXD	(GPIO_PORTC | GPIO_PF | GPIO_IN | 30)
+#define PC31_PF_SSI3_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 31)
+#define PD17_PF_I2C_DATA	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
+#define PD18_PF_I2C_CLK		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
+#define PD19_PF_CSPI2_SS2	(GPIO_PORTD | GPIO_PF | 19)
+#define PD20_PF_CSPI2_SS1	(GPIO_PORTD | GPIO_PF | 20)
+#define PD21_PF_CSPI2_SS0	(GPIO_PORTD | GPIO_PF | 21)
+#define PD22_PF_CSPI2_SCLK	(GPIO_PORTD | GPIO_PF | 22)
+#define PD23_PF_CSPI2_MISO	(GPIO_PORTD | GPIO_PF | 23)
+#define PD24_PF_CSPI2_MOSI	(GPIO_PORTD | GPIO_PF | 24)
+#define PD25_PF_CSPI1_RDY	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
+#define PD26_PF_CSPI1_SS2	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
+#define PD27_PF_CSPI1_SS1	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
+#define PD28_PF_CSPI1_SS0	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 28)
+#define PD29_PF_CSPI1_SCLK	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 29)
+#define PD30_PF_CSPI1_MISO	(GPIO_PORTD | GPIO_PF | GPIO_IN | 30)
+#define PD31_PF_CSPI1_MOSI	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 31)
+#define PE3_PF_UART2_CTS	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 3)
+#define PE4_PF_UART2_RTS	(GPIO_PORTE | GPIO_PF | GPIO_IN | 4)
+#define PE5_PF_PWMO		(GPIO_PORTE | GPIO_PF | 5)
+#define PE6_PF_UART2_TXD	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 6)
+#define PE7_PF_UART2_RXD	(GPIO_PORTE | GPIO_PF | GPIO_IN | 7)
+#define PE8_PF_UART3_TXD	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 8)
+#define PE9_PF_UART3_RXD	(GPIO_PORTE | GPIO_PF | GPIO_IN | 9)
+#define PE10_PF_UART3_CTS	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 10)
+#define PE11_PF_UART3_RTS	(GPIO_PORTE | GPIO_PF | GPIO_IN | 11)
+#define PE12_PF_UART1_TXD	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 12)
+#define PE13_PF_UART1_RXD	(GPIO_PORTE | GPIO_PF | GPIO_IN | 13)
+#define PE14_PF_UART1_CTS	(GPIO_PORTE | GPIO_PF | GPIO_OUT | 14)
+#define PE15_PF_UART1_RTS	(GPIO_PORTE | GPIO_PF | GPIO_IN | 15)
+#define PE16_PF_RTCK		(GPIO_PORTE | GPIO_PF | GPIO_OUT | 16)
+#define PE17_PF_RESET_OUT	(GPIO_PORTE | GPIO_PF | 17)
+#define PE18_PF_SD1_D0		(GPIO_PORTE | GPIO_PF | 18)
+#define PE19_PF_SD1_D1		(GPIO_PORTE | GPIO_PF | 19)
+#define PE20_PF_SD1_D2		(GPIO_PORTE | GPIO_PF | 20)
+#define PE21_PF_SD1_D3		(GPIO_PORTE | GPIO_PF | 21)
+#define PE22_PF_SD1_CMD		(GPIO_PORTE | GPIO_PF | 22)
+#define PE23_PF_SD1_CLK		(GPIO_PORTE | GPIO_PF | 23)
+#define PF0_PF_NRFB		(GPIO_PORTF | GPIO_PF | 0)
+#define PF2_PF_NFWP		(GPIO_PORTF | GPIO_PF | 2)
+#define PF4_PF_NFALE		(GPIO_PORTF | GPIO_PF | 4)
+#define PF5_PF_NFRE		(GPIO_PORTF | GPIO_PF | 5)
+#define PF6_PF_NFWE		(GPIO_PORTF | GPIO_PF | 6)
+#define PF15_PF_CLKO		(GPIO_PORTF | GPIO_PF | 15)
+#define PF21_PF_CS4		(GPIO_PORTF | GPIO_PF | 21)
+#define PF22_PF_CS5		(GPIO_PORTF | GPIO_PF | 22)
 
 /* Alternate GPIO pin functions */
 
-#define PB26_AF_UART4_RTS       (GPIO_PORTB | GPIO_AF | GPIO_IN | 26)
-#define PB28_AF_UART4_TXD       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 28)
-#define PB29_AF_UART4_CTS       (GPIO_PORTB | GPIO_AF | GPIO_OUT | 29)
-#define PB31_AF_UART4_RXD       (GPIO_PORTB | GPIO_AF | GPIO_IN | 31)
-#define PC28_AF_SLCDC2_D0       (GPIO_PORTC | GPIO_AF | 28)
-#define PC29_AF_SLCDC2_RS       (GPIO_PORTC | GPIO_AF | 29)
-#define PC30_AF_SLCDC2_CS       (GPIO_PORTC | GPIO_AF | 30)
-#define PC31_AF_SLCDC2_CLK      (GPIO_PORTC | GPIO_AF | 31)
-#define PD19_AF_USBH2_DATA4     (GPIO_PORTD | GPIO_AF | 19)
-#define PD20_AF_USBH2_DATA3     (GPIO_PORTD | GPIO_AF | 20)
-#define PD21_AF_USBH2_DATA6     (GPIO_PORTD | GPIO_AF | 21)
-#define PD22_AF_USBH2_DATA0     (GPIO_PORTD | GPIO_AF | 22)
-#define PD23_AF_USBH2_DATA2     (GPIO_PORTD | GPIO_AF | 23)
-#define PD24_AF_USBH2_DATA1     (GPIO_PORTD | GPIO_AF | 24)
-#define PD26_AF_USBH2_DATA5     (GPIO_PORTD | GPIO_AF | 26)
-#define PE0_AF_KP_COL6          (GPIO_PORTE | GPIO_AF | 0)
-#define PE1_AF_KP_ROW6          (GPIO_PORTE | GPIO_AF | 1)
-#define PE2_AF_KP_ROW7          (GPIO_PORTE | GPIO_AF | 2)
-#define PE3_AF_KP_COL7          (GPIO_PORTE | GPIO_AF | 3)
-#define PE4_AF_KP_ROW7          (GPIO_PORTE | GPIO_AF | 4)
-#define PE6_AF_KP_COL6          (GPIO_PORTE | GPIO_AF | 6)
-#define PE7_AF_KP_ROW6          (GPIO_PORTE | GPIO_AF | 7)
-#define PE16_AF_OWIRE           (GPIO_PORTE | GPIO_AF | 16)
-#define PE18_AF_CSPI3_MISO      (GPIO_PORTE | GPIO_AF | GPIO_IN | 18)
-#define PE21_AF_CSPI3_SS        (GPIO_PORTE | GPIO_AF | GPIO_OUT | 21)
-#define PE22_AF_CSPI3_MOSI      (GPIO_PORTE | GPIO_AF | GPIO_OUT | 22)
-#define PE23_AF_CSPI3_SCLK      (GPIO_PORTE | GPIO_AF | GPIO_OUT | 23)
+#define PB26_AF_UART4_RTS	(GPIO_PORTB | GPIO_AF | GPIO_IN | 26)
+#define PB28_AF_UART4_TXD	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 28)
+#define PB29_AF_UART4_CTS	(GPIO_PORTB | GPIO_AF | GPIO_OUT | 29)
+#define PB31_AF_UART4_RXD	(GPIO_PORTB | GPIO_AF | GPIO_IN | 31)
+#define PC28_AF_SLCDC2_D0	(GPIO_PORTC | GPIO_AF | 28)
+#define PC29_AF_SLCDC2_RS	(GPIO_PORTC | GPIO_AF | 29)
+#define PC30_AF_SLCDC2_CS	(GPIO_PORTC | GPIO_AF | 30)
+#define PC31_AF_SLCDC2_CLK	(GPIO_PORTC | GPIO_AF | 31)
+#define PD19_AF_USBH2_DATA4	(GPIO_PORTD | GPIO_AF | 19)
+#define PD20_AF_USBH2_DATA3	(GPIO_PORTD | GPIO_AF | 20)
+#define PD21_AF_USBH2_DATA6	(GPIO_PORTD | GPIO_AF | 21)
+#define PD22_AF_USBH2_DATA0	(GPIO_PORTD | GPIO_AF | 22)
+#define PD23_AF_USBH2_DATA2	(GPIO_PORTD | GPIO_AF | 23)
+#define PD24_AF_USBH2_DATA1	(GPIO_PORTD | GPIO_AF | 24)
+#define PD26_AF_USBH2_DATA5	(GPIO_PORTD | GPIO_AF | 26)
+#define PE0_AF_KP_COL6		(GPIO_PORTE | GPIO_AF | 0)
+#define PE1_AF_KP_ROW6		(GPIO_PORTE | GPIO_AF | 1)
+#define PE2_AF_KP_ROW7		(GPIO_PORTE | GPIO_AF | 2)
+#define PE3_AF_KP_COL7		(GPIO_PORTE | GPIO_AF | 3)
+#define PE4_AF_KP_ROW7		(GPIO_PORTE | GPIO_AF | 4)
+#define PE6_AF_KP_COL6		(GPIO_PORTE | GPIO_AF | 6)
+#define PE7_AF_KP_ROW6		(GPIO_PORTE | GPIO_AF | 7)
+#define PE16_AF_OWIRE		(GPIO_PORTE | GPIO_AF | 16)
+#define PE18_AF_CSPI3_MISO	(GPIO_PORTE | GPIO_AF | GPIO_IN | 18)
+#define PE21_AF_CSPI3_SS	(GPIO_PORTE | GPIO_AF | GPIO_OUT | 21)
+#define PE22_AF_CSPI3_MOSI	(GPIO_PORTE | GPIO_AF | GPIO_OUT | 22)
+#define PE23_AF_CSPI3_SCLK	(GPIO_PORTE | GPIO_AF | GPIO_OUT | 23)
 
 /* AIN GPIO pin functions */
 
-#define PA6_AIN_SLCDC1_DAT0     (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 6)
-#define PA7_AIN_SLCDC1_DAT1     (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 7)
-#define PA8_AIN_SLCDC1_DAT2     (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 8)
-#define PA0_AIN_SLCDC1_DAT3     (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
-#define PA11_AIN_SLCDC1_DAT5    (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 11)
-#define PA13_AIN_SLCDC1_DAT7    (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 13)
-#define PA15_AIN_SLCDC1_DAT9    (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 15)
-#define PA17_AIN_SLCDC1_DAT11   (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17)
-#define PA19_AIN_SLCDC1_DAT13   (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 19)
-#define PA21_AIN_SLCDC1_DAT15   (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 21)
-#define PA22_AIN_EXT_DMAGRANT   (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 22)
-#define PA24_AIN_SLCDC1_D0      (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 24)
-#define PA25_AIN_SLCDC1_RS      (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 25)
-#define PA26_AIN_SLCDC1_CS      (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 26)
-#define PA27_AIN_SLCDC1_CLK     (GPIO_PORTA | GPIO_AIN | GPIO_OUT | 27)
-#define PB6_AIN_SLCDC1_D0       (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 6)
-#define PB7_AIN_SLCDC1_RS       (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 7)
-#define PB8_AIN_SLCDC1_CS       (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 8)
-#define PB9_AIN_SLCDC1_CLK      (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 9)
-#define PB25_AIN_SLCDC1_DAT0    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 25)
-#define PB26_AIN_SLCDC1_DAT1    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 26)
-#define PB27_AIN_SLCDC1_DAT2    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 27)
-#define PB28_AIN_SLCDC1_DAT3    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 28)
-#define PB29_AIN_SLCDC1_DAT4    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 29)
-#define PB30_AIN_SLCDC1_DAT5    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 30)
-#define PB31_AIN_SLCDC1_DAT6    (GPIO_PORTB | GPIO_AIN | GPIO_OUT | 31)
-#define PC5_AIN_SLCDC1_DAT7     (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 5)
-#define PC6_AIN_SLCDC1_DAT8     (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 6)
-#define PC7_AIN_SLCDC1_DAT9     (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 7)
-#define PC8_AIN_SLCDC1_DAT10    (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 8)
-#define PC9_AIN_SLCDC1_DAT11    (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 9)
-#define PC10_AIN_SLCDC1_DAT12   (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 10)
-#define PC11_AIN_SLCDC1_DAT13   (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 11)
-#define PC12_AIN_SLCDC1_DAT14   (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 12)
-#define PC13_AIN_SLCDC1_DAT15   (GPIO_PORTC | GPIO_AIN | GPIO_OUT | 13)
-#define PE5_AIN_PC_SPKOUT       (GPIO_PORTE | GPIO_AIN | GPIO_OUT | 5)
+#define PA6_AIN_SLCDC1_DAT0	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 6)
+#define PA7_AIN_SLCDC1_DAT1	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 7)
+#define PA8_AIN_SLCDC1_DAT2	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 8)
+#define PA0_AIN_SLCDC1_DAT3	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 0)
+#define PA11_AIN_SLCDC1_DAT5	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 11)
+#define PA13_AIN_SLCDC1_DAT7	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 13)
+#define PA15_AIN_SLCDC1_DAT9	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 15)
+#define PA17_AIN_SLCDC1_DAT11	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 17)
+#define PA19_AIN_SLCDC1_DAT13	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 19)
+#define PA21_AIN_SLCDC1_DAT15	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 21)
+#define PA22_AIN_EXT_DMAGRANT	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 22)
+#define PA24_AIN_SLCDC1_D0	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 24)
+#define PA25_AIN_SLCDC1_RS	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 25)
+#define PA26_AIN_SLCDC1_CS	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 26)
+#define PA27_AIN_SLCDC1_CLK	(GPIO_PORTA | GPIO_AIN | GPIO_OUT | 27)
+#define PB6_AIN_SLCDC1_D0	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 6)
+#define PB7_AIN_SLCDC1_RS	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 7)
+#define PB8_AIN_SLCDC1_CS	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 8)
+#define PB9_AIN_SLCDC1_CLK	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 9)
+#define PB25_AIN_SLCDC1_DAT0	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 25)
+#define PB26_AIN_SLCDC1_DAT1	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 26)
+#define PB27_AIN_SLCDC1_DAT2	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 27)
+#define PB28_AIN_SLCDC1_DAT3	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 28)
+#define PB29_AIN_SLCDC1_DAT4	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 29)
+#define PB30_AIN_SLCDC1_DAT5	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 30)
+#define PB31_AIN_SLCDC1_DAT6	(GPIO_PORTB | GPIO_AIN | GPIO_OUT | 31)
+#define PC5_AIN_SLCDC1_DAT7	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 5)
+#define PC6_AIN_SLCDC1_DAT8	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 6)
+#define PC7_AIN_SLCDC1_DAT9	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 7)
+#define PC8_AIN_SLCDC1_DAT10	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 8)
+#define PC9_AIN_SLCDC1_DAT11	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 9)
+#define PC10_AIN_SLCDC1_DAT12	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 10)
+#define PC11_AIN_SLCDC1_DAT13	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 11)
+#define PC12_AIN_SLCDC1_DAT14	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 12)
+#define PC13_AIN_SLCDC1_DAT15	(GPIO_PORTC | GPIO_AIN | GPIO_OUT | 13)
+#define PE5_AIN_PC_SPKOUT	(GPIO_PORTE | GPIO_AIN | GPIO_OUT | 5)
 
 /* BIN GPIO pin functions */
 
-#define PE5_BIN_TOUT2           (GPIO_PORTE | GPIO_BIN | GPIO_OUT | 5)
+#define PE5_BIN_TOUT2		(GPIO_PORTE | GPIO_BIN | GPIO_OUT | 5)
 
 /* CIN GPIO pin functions */
 
-#define PA14_CIN_SLCDC1_DAT0    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 14)
-#define PA15_CIN_SLCDC1_DAT1    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 15)
-#define PA16_CIN_SLCDC1_DAT2    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 16)
-#define PA17_CIN_SLCDC1_DAT3    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 17)
-#define PA18_CIN_SLCDC1_DAT4    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 18)
-#define PA19_CIN_SLCDC1_DAT5    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 19)
-#define PA20_CIN_SLCDC1_DAT6    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 20)
-#define PA21_CIN_SLCDC1_DAT7    (GPIO_PORTA | GPIO_CIN | GPIO_OUT | 21)
-#define PB30_CIN_UART4_CTS      (GPIO_PORTB | GPIO_CIN | GPIO_OUT | 30)
-#define PE5_CIN_TOUT3           (GPIO_PORTE | GPIO_CIN | GPIO_OUT | 5)
+#define PA14_CIN_SLCDC1_DAT0	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 14)
+#define PA15_CIN_SLCDC1_DAT1	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 15)
+#define PA16_CIN_SLCDC1_DAT2	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 16)
+#define PA17_CIN_SLCDC1_DAT3	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 17)
+#define PA18_CIN_SLCDC1_DAT4	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 18)
+#define PA19_CIN_SLCDC1_DAT5	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 19)
+#define PA20_CIN_SLCDC1_DAT6	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 20)
+#define PA21_CIN_SLCDC1_DAT7	(GPIO_PORTA | GPIO_CIN | GPIO_OUT | 21)
+#define PB30_CIN_UART4_CTS	(GPIO_PORTB | GPIO_CIN | GPIO_OUT | 30)
+#define PE5_CIN_TOUT3		(GPIO_PORTE | GPIO_CIN | GPIO_OUT | 5)
 
 /* AOUT GPIO pin functions */
 
-#define PB29_AOUT_UART4_RXD     (GPIO_PORTB | GPIO_AOUT | GPIO_IN | 29)
-#define PB31_AOUT_UART4_RTS     (GPIO_PORTB | GPIO_AOUT | GPIO_IN | 31)
+#define PB29_AOUT_UART4_RXD	(GPIO_PORTB | GPIO_AOUT | GPIO_IN | 29)
+#define PB31_AOUT_UART4_RTS	(GPIO_PORTB | GPIO_AOUT | GPIO_IN | 31)
 #define PC8_AOUT_USBOTG_TXR_INT (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 8)
-#define PC15_AOUT_WKGD          (GPIO_PORTC | GPIO_AOUT | GPIO_IN | 15)
-#define PF21_AOUT_DTACK         (GPIO_PORTF | GPIO_AOUT | GPIO_IN | 21)
+#define PC15_AOUT_WKGD		(GPIO_PORTC | GPIO_AOUT | GPIO_IN | 15)
+#define PF21_AOUT_DTACK		(GPIO_PORTF | GPIO_AOUT | GPIO_IN | 21)
 
-
-#endif
+#endif /* ifndef __MACH_IOMUX_MX2x_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
index e1fc6da..e51465d 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
@@ -16,12 +16,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA 02110-1301, USA.
  */
-
-#ifndef __MACH_MX31_IOMUX_H__
-#define __MACH_MX31_IOMUX_H__
+#ifndef __MACH_IOMUX_MX3_H__
+#define __MACH_IOMUX_MX3_H__
 
 #include <linux/types.h>
-
 /*
  * various IOMUX output functions
  */
@@ -34,7 +32,7 @@
 #define	IOMUX_OCONFIG_ALT4 (5 << 4)	/* used as alternate function 4 */
 #define	IOMUX_OCONFIG_ALT5 (6 << 4)	/* used as alternate function 5 */
 #define	IOMUX_OCONFIG_ALT6 (7 << 4)	/* used as alternate function 6 */
-#define	IOMUX_ICONFIG_NONE  0	 	/* not configured for input */
+#define	IOMUX_ICONFIG_NONE  0		/* not configured for input */
 #define	IOMUX_ICONFIG_GPIO  1		/* used as GPIO */
 #define	IOMUX_ICONFIG_FUNC  2		/* used as function */
 #define	IOMUX_ICONFIG_ALT1  4		/* used as alternate function 1 */
@@ -167,11 +165,6 @@
 	MXC_GPIO_IRQ_START)
 
 /*
- * The number of gpio devices among the pads
- */
-#define GPIO_PORT_MAX 3
-
-/*
  * This enumeration is constructed based on the Section
  * "sw_pad_ctl & sw_mux_ctl details" of the MX31 IC Spec. Each enumerated
  * value is constructed based on the rules described above.
@@ -633,40 +626,40 @@
 #define MX31_PIN_TXD2__GPIO1_28		IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_GPIO)
 #define MX31_PIN_CSI_D4__GPIO3_4	IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_GPIO)
 #define MX31_PIN_CSI_D5__GPIO3_5	IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_USBOTG_DATA0__USBOTG_DATA0    IOMUX_MODE(MX31_PIN_USBOTG_DATA0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA1__USBOTG_DATA1    IOMUX_MODE(MX31_PIN_USBOTG_DATA1, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA2__USBOTG_DATA2    IOMUX_MODE(MX31_PIN_USBOTG_DATA2, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA3__USBOTG_DATA3    IOMUX_MODE(MX31_PIN_USBOTG_DATA3, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA4__USBOTG_DATA4    IOMUX_MODE(MX31_PIN_USBOTG_DATA4, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA5__USBOTG_DATA5    IOMUX_MODE(MX31_PIN_USBOTG_DATA5, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA6__USBOTG_DATA6    IOMUX_MODE(MX31_PIN_USBOTG_DATA6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DATA7__USBOTG_DATA7    IOMUX_MODE(MX31_PIN_USBOTG_DATA7, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_CLK__USBOTG_CLK        IOMUX_MODE(MX31_PIN_USBOTG_CLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_DIR__USBOTG_DIR        IOMUX_MODE(MX31_PIN_USBOTG_DIR, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_NXT__USBOTG_NXT        IOMUX_MODE(MX31_PIN_USBOTG_NXT, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBOTG_STP__USBOTG_STP        IOMUX_MODE(MX31_PIN_USBOTG_STP, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_CSPI1_MOSI__USBH1_RXDM        IOMUX_MODE(MX31_PIN_CSPI1_MOSI, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_MISO__USBH1_RXDP        IOMUX_MODE(MX31_PIN_CSPI1_MISO, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_SS0__USBH1_TXDM         IOMUX_MODE(MX31_PIN_CSPI1_SS0,  IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_SS1__USBH1_TXDP         IOMUX_MODE(MX31_PIN_CSPI1_SS1,  IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_SS2__USBH1_RCV          IOMUX_MODE(MX31_PIN_CSPI1_SS2,  IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_SCLK__USBH1_OEB         IOMUX_MODE(MX31_PIN_CSPI1_SCLK, IOMUX_CONFIG_ALT1)
-#define MX31_PIN_CSPI1_SPI_RDY__USBH1_FS       IOMUX_MODE(MX31_PIN_CSPI1_SPI_RDY, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_USBOTG_DATA0__USBOTG_DATA0	IOMUX_MODE(MX31_PIN_USBOTG_DATA0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA1__USBOTG_DATA1	IOMUX_MODE(MX31_PIN_USBOTG_DATA1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA2__USBOTG_DATA2	IOMUX_MODE(MX31_PIN_USBOTG_DATA2, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA3__USBOTG_DATA3	IOMUX_MODE(MX31_PIN_USBOTG_DATA3, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA4__USBOTG_DATA4	IOMUX_MODE(MX31_PIN_USBOTG_DATA4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA5__USBOTG_DATA5	IOMUX_MODE(MX31_PIN_USBOTG_DATA5, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA6__USBOTG_DATA6	IOMUX_MODE(MX31_PIN_USBOTG_DATA6, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DATA7__USBOTG_DATA7	IOMUX_MODE(MX31_PIN_USBOTG_DATA7, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_CLK__USBOTG_CLK		IOMUX_MODE(MX31_PIN_USBOTG_CLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_DIR__USBOTG_DIR		IOMUX_MODE(MX31_PIN_USBOTG_DIR, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_NXT__USBOTG_NXT		IOMUX_MODE(MX31_PIN_USBOTG_NXT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBOTG_STP__USBOTG_STP		IOMUX_MODE(MX31_PIN_USBOTG_STP, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_CSPI1_MOSI__USBH1_RXDM		IOMUX_MODE(MX31_PIN_CSPI1_MOSI, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_MISO__USBH1_RXDP		IOMUX_MODE(MX31_PIN_CSPI1_MISO, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_SS0__USBH1_TXDM		IOMUX_MODE(MX31_PIN_CSPI1_SS0, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_SS1__USBH1_TXDP		IOMUX_MODE(MX31_PIN_CSPI1_SS1, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_SS2__USBH1_RCV		IOMUX_MODE(MX31_PIN_CSPI1_SS2, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_SCLK__USBH1_OEB		IOMUX_MODE(MX31_PIN_CSPI1_SCLK, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI1_SPI_RDY__USBH1_FS	IOMUX_MODE(MX31_PIN_CSPI1_SPI_RDY, IOMUX_CONFIG_ALT1)
 #define MX31_PIN_SFS6__USBH1_SUSPEND	IOMUX_MODE(MX31_PIN_SFS6, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_NFRE_B__GPIO1_11	IOMUX_MODE(MX31_PIN_NFRE_B, IOMUX_CONFIG_GPIO)
 #define MX31_PIN_NFALE__GPIO1_12	IOMUX_MODE(MX31_PIN_NFALE, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_USBH2_DATA0__USBH2_DATA0      IOMUX_MODE(MX31_PIN_USBH2_DATA0, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBH2_DATA1__USBH2_DATA1      IOMUX_MODE(MX31_PIN_USBH2_DATA1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_DATA0__USBH2_DATA0	IOMUX_MODE(MX31_PIN_USBH2_DATA0, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_DATA1__USBH2_DATA1	IOMUX_MODE(MX31_PIN_USBH2_DATA1, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_STXD3__USBH2_DATA2	IOMUX_MODE(MX31_PIN_STXD3, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_SRXD3__USBH2_DATA3	IOMUX_MODE(MX31_PIN_SRXD3, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_SCK3__USBH2_DATA4	IOMUX_MODE(MX31_PIN_SCK3, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_SFS3__USBH2_DATA5	IOMUX_MODE(MX31_PIN_SFS3, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_STXD6__USBH2_DATA6	IOMUX_MODE(MX31_PIN_STXD6, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_SRXD6__USBH2_DATA7	IOMUX_MODE(MX31_PIN_SRXD6, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBH2_CLK__USBH2_CLK          IOMUX_MODE(MX31_PIN_USBH2_CLK, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBH2_DIR__USBH2_DIR          IOMUX_MODE(MX31_PIN_USBH2_DIR, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBH2_NXT__USBH2_NXT          IOMUX_MODE(MX31_PIN_USBH2_NXT, IOMUX_CONFIG_FUNC)
-#define MX31_PIN_USBH2_STP__USBH2_STP          IOMUX_MODE(MX31_PIN_USBH2_STP, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_CLK__USBH2_CLK		IOMUX_MODE(MX31_PIN_USBH2_CLK, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_DIR__USBH2_DIR		IOMUX_MODE(MX31_PIN_USBH2_DIR, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_NXT__USBH2_NXT		IOMUX_MODE(MX31_PIN_USBH2_NXT, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_USBH2_STP__USBH2_STP		IOMUX_MODE(MX31_PIN_USBH2_STP, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_SCK6__GPIO1_25		IOMUX_MODE(MX31_PIN_SCK6, IOMUX_CONFIG_GPIO)
 #define MX31_PIN_USB_OC__GPIO1_30	IOMUX_MODE(MX31_PIN_USB_OC, IOMUX_CONFIG_GPIO)
 #define MX31_PIN_I2C_DAT__I2C1_SDA	IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC)
@@ -711,8 +704,8 @@
 #define MX31_PIN_DSR_DCE1__GPIO2_9	IOMUX_MODE(MX31_PIN_DSR_DCE1, IOMUX_CONFIG_GPIO)
 #define MX31_PIN_RI_DCE1__GPIO2_10	IOMUX_MODE(MX31_PIN_RI_DCE1, IOMUX_CONFIG_GPIO)
 #define MX31_PIN_DCD_DCE1__GPIO2_11	IOMUX_MODE(MX31_PIN_DCD_DCE1, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_STXD5__GPIO1_21       IOMUX_MODE(MX31_PIN_STXD5, IOMUX_CONFIG_GPIO)
-#define MX31_PIN_SRXD5__GPIO1_22       IOMUX_MODE(MX31_PIN_SRXD5, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_STXD5__GPIO1_21	IOMUX_MODE(MX31_PIN_STXD5, IOMUX_CONFIG_GPIO)
+#define MX31_PIN_SRXD5__GPIO1_22	IOMUX_MODE(MX31_PIN_SRXD5, IOMUX_CONFIG_GPIO)
 #define MX31_PIN_GPIO1_3__GPIO1_3	IOMUX_MODE(MX31_PIN_GPIO1_3, IOMUX_CONFIG_GPIO)
 #define MX31_PIN_CSPI2_SS1__CSPI3_SS1	IOMUX_MODE(MX31_PIN_CSPI2_SS1, IOMUX_CONFIG_ALT1)
 #define MX31_PIN_RTS1__GPIO2_6		IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_GPIO)
@@ -727,13 +720,14 @@
 #define MX31_PIN_SCK5__SCK5		IOMUX_MODE(MX31_PIN_SCK5, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_SFS5__SFS5		IOMUX_MODE(MX31_PIN_SFS5, IOMUX_CONFIG_FUNC)
 
-/*XXX: The SS0, SS1, SS2, SS3 lines of spi3 are multiplexed by cspi2_ss0, cspi2_ss1, cspi1_ss0
- * cspi1_ss1*/
+/*
+ * XXX: The SS0, SS1, SS2, SS3 lines of spi3 are multiplexed with cspi2_ss0,
+ * cspi2_ss1, cspi1_ss0 cspi1_ss1
+ */
 
 /*
  * This function configures the pad value for a IOMUX pin.
  */
 void mxc_iomux_set_pad(enum iomux_pins, u32);
 
-#endif
-
+#endif /* ifndef __MACH_IOMUX_MX3_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx35.h b/arch/arm/plat-mxc/include/mach/iomux-mx35.h
index c88d407..2a24bae 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx35.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx35.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C, NO_PAD_CTRL) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.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
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
new file mode 100644
index 0000000..b4f975e
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -0,0 +1,326 @@
+/*
+ * 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
+ */
+
+#ifndef __MACH_IOMUX_MX51_H__
+#define __MACH_IOMUX_MX51_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;
+
+/* 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)
+
+/*
+ * 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> see also iomux-v3.h
+ */
+
+/*
+ * FIXME: This was converted using scripts from existing Freescale code to
+ * this form used upstream. Need to verify the name format.
+ */
+
+/*						PAD      MUX   ALT INPSE PATH PADCTRL */
+
+#define MX51_PAD_GPIO_2_0__EIM_D16	IOMUX_PAD(0x3f0, 0x05c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_1__EIM_D17	IOMUX_PAD(0x3f4, 0x060, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_2__EIM_D18	IOMUX_PAD(0x3f8, 0x064, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_3__EIM_D19	IOMUX_PAD(0x3fc, 0x068, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_4__EIM_D20	IOMUX_PAD(0x400, 0x06c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_5__EIM_D21	IOMUX_PAD(0x404, 0x070, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_6__EIM_D22	IOMUX_PAD(0x408, 0x074, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_7__EIM_D23	IOMUX_PAD(0x40c, 0x078, 1, 0x0,   0, NO_PAD_CTRL)
+
+/* Babbage UART3 */
+#define MX51_PAD_EIM_D24__UART3_CTS	IOMUX_PAD(0x410, 0x07c, IOMUX_CONFIG_ALT3, 0x0, 0, MX51_UART3_PAD_CTRL)
+#define MX51_PAD_EIM_D25__UART3_RXD	IOMUX_PAD(0x414, 0x080, IOMUX_CONFIG_ALT3, 0x9f4, 0, MX51_UART3_PAD_CTRL)
+#define MX51_PAD_EIM_D26__UART3_TXD	IOMUX_PAD(0x418, 0x084, IOMUX_CONFIG_ALT3, 0x0, 0, MX51_UART3_PAD_CTRL)
+#define MX51_PAD_EIM_D27__UART3_RTS	IOMUX_PAD(0x41c, 0x088, IOMUX_CONFIG_ALT3, 0x9f0, 0, 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_GPIO_2_10__EIM_A16	IOMUX_PAD(0x430, 0x09c, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_11__EIM_A17	IOMUX_PAD(0x434, 0x0a0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_12__EIM_A18	IOMUX_PAD(0x438, 0x0a4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_13__EIM_A19	IOMUX_PAD(0x43c, 0x0a8, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_14__EIM_A20	IOMUX_PAD(0x440, 0x0ac, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_15__EIM_A21	IOMUX_PAD(0x444, 0x0b0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_16__EIM_A22	IOMUX_PAD(0x448, 0x0b4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_17__EIM_A23	IOMUX_PAD(0x44c, 0x0b8, 1, 0x0,   0, NO_PAD_CTRL)
+
+#define MX51_PAD_GPIO_2_18__EIM_A24	IOMUX_PAD(0x450, 0x0bc, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_19__EIM_A25	IOMUX_PAD(0x454, 0x0c0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_20__EIM_A26	IOMUX_PAD(0x458, 0x0c4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_21__EIM_A27	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_GPIO_2_22__EIM_EB2	IOMUX_PAD(0x468, 0x0d4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_23__EIM_EB3	IOMUX_PAD(0x46c, 0x0d8, 1, 0x0,   0, NO_PAD_CTRL)
+
+#define MX51_PAD_GPIO_2_24__EIM_OE	IOMUX_PAD(0x470, 0x0dc, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_25__EIM_CS0	IOMUX_PAD(0x474, 0x0e0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_26__EIM_CS1	IOMUX_PAD(0x478, 0x0e4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_27__EIM_CS2	IOMUX_PAD(0x47c, 0x0e8, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_28__EIM_CS3	IOMUX_PAD(0x480, 0x0ec, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_29__EIM_CS4	IOMUX_PAD(0x484, 0x0f0, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_30__EIM_CS5	IOMUX_PAD(0x488, 0x0f4, 1, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_2_31__EIM_DTACK	IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, NO_PAD_CTRL)
+
+#define MX51_PAD_GPIO_3_1__EIM_LBA	IOMUX_PAD(0x494, 0xFC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_2__EIM_CRE	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_GPIO_3_3__NANDF_WE_B	IOMUX_PAD(0x4E4, 0x108, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_4__NANDF_RE_B	IOMUX_PAD(0x4E8, 0x10C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_5__NANDF_ALE	IOMUX_PAD(0x4EC, 0x110, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_6__NANDF_CLE	IOMUX_PAD(0x4F0, 0x114, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_7__NANDF_WP_B	IOMUX_PAD(0x4F4, 0x118, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_8__NANDF_RB0	IOMUX_PAD(0x4F8, 0x11C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_9__NANDF_RB1	IOMUX_PAD(0x4FC, 0x120, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_10__NANDF_RB2	IOMUX_PAD(0x500, 0x124, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_11__NANDF_RB3	IOMUX_PAD(0x504, 0x128, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_12__GPIO_NAND	IOMUX_PAD(0x514, 0x12C, 3, 0x0, 0, NO_PAD_CTRL)
+/* REVISIT: Not sure of these values
+
+  #define MX51_PAD_GPIO_1___NANDF_RB4	IOMUX_PAD(, , , 0x0, 0, NO_PAD_CTRL)
+  #define MX51_PAD_GPIO_3_13__NANDF_RB5	IOMUX_PAD(0x5D8, 0x130, 3, 0x0, 0, NO_PAD_CTRL)
+  #define MX51_PAD_GPIO_3_15__NANDF_RB7	IOMUX_PAD(0x5E0, 0x138, 3, 0x0, 0, NO_PAD_CTRL)
+*/
+#define MX51_PAD_GPIO_3_14__NANDF_RB6	IOMUX_PAD(0x5DC, 0x134, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_16__NANDF_CS0	IOMUX_PAD(0x518, 0x130, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_17__NANDF_CS1	IOMUX_PAD(0x51C, 0x134, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_18__NANDF_CS2	IOMUX_PAD(0x520, 0x138, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_19__NANDF_CS3	IOMUX_PAD(0x524, 0x13C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_20__NANDF_CS4	IOMUX_PAD(0x528, 0x140, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_21__NANDF_CS5	IOMUX_PAD(0x52C, 0x144, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_22__NANDF_CS6	IOMUX_PAD(0x530, 0x148, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_23__NANDF_CS7	IOMUX_PAD(0x534, 0x14C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_24__NANDF_RDY_INT	IOMUX_PAD(0x538, 0x150, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_25__NANDF_D15	IOMUX_PAD(0x53C, 0x154, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_26__NANDF_D14	IOMUX_PAD(0x540, 0x158, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_27__NANDF_D13	IOMUX_PAD(0x544, 0x15C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_28__NANDF_D12	IOMUX_PAD(0x548, 0x160, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_29__NANDF_D11	IOMUX_PAD(0x54C, 0x164, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_30__NANDF_D10	IOMUX_PAD(0x550, 0x168, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_31__NANDF_D9	IOMUX_PAD(0x554, 0x16C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_0__NANDF_D8	IOMUX_PAD(0x558, 0x170, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_1__NANDF_D7	IOMUX_PAD(0x55C, 0x174, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_2__NANDF_D6	IOMUX_PAD(0x560, 0x178, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_3__NANDF_D5	IOMUX_PAD(0x564, 0x17C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_4__NANDF_D4	IOMUX_PAD(0x568, 0x180, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_5__NANDF_D3	IOMUX_PAD(0x56C, 0x184, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_6__NANDF_D2	IOMUX_PAD(0x570, 0x188, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_7__NANDF_D1	IOMUX_PAD(0x574, 0x18C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_8__NANDF_D0	IOMUX_PAD(0x578, 0x190, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_12__CSI1_D8	IOMUX_PAD(0x57C, 0x194, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_13__CSI1_D9	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, 0x0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_MCLK__CSI1_MCLK	IOMUX_PAD(0x5B8, 0x0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI1_PKE0__CSI1_PKE0	IOMUX_PAD(0x860, 0x0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_9__CSI2_D12	IOMUX_PAD(0x5BC, 0x1CC, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_10__CSI2_D13	IOMUX_PAD(0x5C0, 0x1D0, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_11__CSI2_D14	IOMUX_PAD(0x5C4, 0x1D4, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_12__CSI2_D15	IOMUX_PAD(0x5C8, 0x1D8, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_11__CSI2_D16	IOMUX_PAD(0x5CC, 0x1DC, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_12__CSI2_D17	IOMUX_PAD(0x5D0, 0x1E0, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_11__CSI2_D18	IOMUX_PAD(0x5D4, 0x1E4, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_12__CSI2_D19	IOMUX_PAD(0x5D8, 0x1E8, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_13__CSI2_VSYNC	IOMUX_PAD(0x5DC, 0x1EC, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_14__CSI2_HSYNC	IOMUX_PAD(0x5E0, 0x1F0, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_15__CSI2_PIXCLK	IOMUX_PAD(0x5E4, 0x1F4, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_CSI2_PKE0__CSI2_PKE0	IOMUX_PAD(0x81C, 0x0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_16__I2C1_CLK	IOMUX_PAD(0x5E8, 0x1F8, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_17__I2C1_DAT	IOMUX_PAD(0x5EC, 0x1FC, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_18__AUD3_BB_TXD	IOMUX_PAD(0x5F0, 0x200, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_19__AUD3_BB_RXD	IOMUX_PAD(0x5F4, 0x204, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_20__AUD3_BB_CK	IOMUX_PAD(0x5F8, 0x208, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_21__AUD3_BB_FS	IOMUX_PAD(0x5FC, 0x20C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_22__CSPI1_MOSI	IOMUX_PAD(0x600, 0x210, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_23__CSPI1_MISO	IOMUX_PAD(0x604, 0x214, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_24__CSPI1_SS0	IOMUX_PAD(0x608, 0x218, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_25__CSPI1_SS1	IOMUX_PAD(0x60C, 0x21C, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_26__CSPI1_RDY	IOMUX_PAD(0x610, 0x220, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_4_27__CSPI1_SCLK	IOMUX_PAD(0x614, 0x224, 3, 0x0, 0, NO_PAD_CTRL)
+
+/* Babbage UART1 */
+#define MX51_PAD_UART1_RXD__UART1_RXD	IOMUX_PAD(0x618, 0x228,	IOMUX_CONFIG_ALT0, 0x9e4, 0, MX51_UART1_PAD_CTRL | PAD_CTL_SRE_FAST)
+#define MX51_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x61C, 0x22C, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_UART1_PAD_CTRL | PAD_CTL_SRE_FAST)
+#define MX51_PAD_UART1_RTS__UART1_RTS	IOMUX_PAD(0x620, 0x230, IOMUX_CONFIG_ALT0, 0x9e0, 0, MX51_UART1_PAD_CTRL)
+#define MX51_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x624, 0x234, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_UART1_PAD_CTRL)
+
+/* Babbage UART2 */
+#define MX51_PAD_UART2_RXD__UART2_RXD	IOMUX_PAD(0x628, 0x238, IOMUX_CONFIG_ALT0, 0x9ec, 2, MX51_UART2_PAD_CTRL)
+#define MX51_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x62C, 0x23C, IOMUX_CONFIG_ALT0, 0x0, 0, MX51_UART2_PAD_CTRL)
+
+#define MX51_PAD_GPIO_1_22__UART3_RXD	IOMUX_PAD(0x630, 0x240, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_23__UART3_TXD	IOMUX_PAD(0x634, 0x244, 3, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_24__OWIRE_LINE	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_COL5__KEY_COL5	IOMUX_PAD(0x660, 0x270, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_25__USBH1_CLK	IOMUX_PAD(0x678, 0x278, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_26__USBH1_DIR	IOMUX_PAD(0x67C, 0x27C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_27__USBH1_STP	IOMUX_PAD(0x680, 0x280, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_28__USBH1_NXT	IOMUX_PAD(0x684, 0x284, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_11__USBH1_DATA0	IOMUX_PAD(0x688, 0x288, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_12__USBH1_DATA1	IOMUX_PAD(0x68C, 0x28C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_13__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_14__USBH1_DATA3	IOMUX_PAD(0x694, 0x294, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_15__USBH1_DATA4	IOMUX_PAD(0x698, 0x298, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_16__USBH1_DATA5	IOMUX_PAD(0x69C, 0x29C, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_17__USBH1_DATA6	IOMUX_PAD(0x6A0, 0x2A0, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_18__USBH1_DATA7	IOMUX_PAD(0x6A4, 0x2A4, 2, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_0__DI1_PIN11	IOMUX_PAD(0x6A8, 0x2A8, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_1__DI1_PIN12	IOMUX_PAD(0x6AC, 0x2AC, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_2__DI1_PIN13	IOMUX_PAD(0x6B0, 0x2B0, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_3__DI1_D0_CS	IOMUX_PAD(0x6B4, 0x2B4, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_4__DI1_D1_CS	IOMUX_PAD(0x6B8, 0x2B8, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_5__DISPB2_SER_DIN	IOMUX_PAD(0x6BC, 0x2BC, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_6__DISPB2_SER_DIO	IOMUX_PAD(0x6C0, 0x2C0, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_7__DISPB2_SER_CLK	IOMUX_PAD(0x6C4, 0x2C4, 4, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_3_8__DISPB2_SER_RS	IOMUX_PAD(0x6C8, 0x2C8, 4, 0x0, 0, 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_GPIO_1_19__DISP2_DAT6	IOMUX_PAD(0x774, 0x36C, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_29__DISP2_DAT7	IOMUX_PAD(0x778, 0x370, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_30__DISP2_DAT8	IOMUX_PAD(0x77C, 0x374, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_31__DISP2_DAT9	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, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK	IOMUX_PAD(0x7A0, 0x398, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0	IOMUX_PAD(0x7A4, 0x39C, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1	IOMUX_PAD(0x7A8, 0x3A0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2	IOMUX_PAD(0x7AC, 0x3A4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3	IOMUX_PAD(0x7B0, 0x3A8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_0__GPIO1_0	IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_1__GPIO1_1	IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD	IOMUX_PAD(0x7BC, 0x3B4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK	IOMUX_PAD(0x7C0, 0x3B8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0	IOMUX_PAD(0x7C4, 0x3BC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1	IOMUX_PAD(0x7C8, 0x3C0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2	IOMUX_PAD(0x7CC, 0x3C4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3	IOMUX_PAD(0x7D0, 0x3C8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_2__GPIO1_2	IOMUX_PAD(0x7D4, 0x3CC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_3__GPIO1_3	IOMUX_PAD(0x7D8, 0x3D0, 0, 0x0, 0, NO_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__GPIO1_4	IOMUX_PAD(0x804, 0x3D8, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_5__GPIO1_5	IOMUX_PAD(0x808, 0x3DC, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_6__GPIO1_6	IOMUX_PAD(0x80C, 0x3E0, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_7__GPIO1_7	IOMUX_PAD(0x810, 0x3E4, 0, 0x0, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_8__GPIO1_8	IOMUX_PAD(0x814, 0x3E8, 0, 0x0, 1, \
+						(PAD_CTL_SRE_SLOW | PAD_CTL_DSE_MED | PAD_CTL_PUS_100K_UP |  PAD_CTL_HYS))
+#define MX51_PAD_GPIO_1_9__GPIO1_9	IOMUX_PAD(0x818, 0x3EC, 0, 0x0, 0, NO_PAD_CTRL)
+
+/* EIM */
+#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)
+
+#endif /* __MACH_IOMUX_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v1.h b/arch/arm/plat-mxc/include/mach/iomux-v1.h
new file mode 100644
index 0000000..884f575
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/iomux-v1.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
+ * Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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_IOMUX_V1_H__
+#define __MACH_IOMUX_V1_H__
+
+/*
+*  GPIO Module and I/O Multiplexer
+*  x = 0..3 for reg_A, reg_B, reg_C, reg_D
+*/
+#define MXC_DDIR(x)	(0x00 + ((x) << 8))
+#define MXC_OCR1(x)	(0x04 + ((x) << 8))
+#define MXC_OCR2(x)	(0x08 + ((x) << 8))
+#define MXC_ICONFA1(x)	(0x0c + ((x) << 8))
+#define MXC_ICONFA2(x)	(0x10 + ((x) << 8))
+#define MXC_ICONFB1(x)	(0x14 + ((x) << 8))
+#define MXC_ICONFB2(x)	(0x18 + ((x) << 8))
+#define MXC_DR(x)	(0x1c + ((x) << 8))
+#define MXC_GIUS(x)	(0x20 + ((x) << 8))
+#define MXC_SSR(x)	(0x24 + ((x) << 8))
+#define MXC_ICR1(x)	(0x28 + ((x) << 8))
+#define MXC_ICR2(x)	(0x2c + ((x) << 8))
+#define MXC_IMR(x)	(0x30 + ((x) << 8))
+#define MXC_ISR(x)	(0x34 + ((x) << 8))
+#define MXC_GPR(x)	(0x38 + ((x) << 8))
+#define MXC_SWR(x)	(0x3c + ((x) << 8))
+#define MXC_PUEN(x)	(0x40 + ((x) << 8))
+
+#define MX1_NUM_GPIO_PORT	4
+#define MX21_NUM_GPIO_PORT	6
+#define MX27_NUM_GPIO_PORT	6
+
+#define GPIO_PIN_MASK 0x1f
+
+#define GPIO_PORT_SHIFT 5
+#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT)
+
+#define GPIO_PORTA	(0 << GPIO_PORT_SHIFT)
+#define GPIO_PORTB	(1 << GPIO_PORT_SHIFT)
+#define GPIO_PORTC	(2 << GPIO_PORT_SHIFT)
+#define GPIO_PORTD	(3 << GPIO_PORT_SHIFT)
+#define GPIO_PORTE	(4 << GPIO_PORT_SHIFT)
+#define GPIO_PORTF	(5 << GPIO_PORT_SHIFT)
+
+#define GPIO_OUT	(1 << 8)
+#define GPIO_IN		(0 << 8)
+#define GPIO_PUEN	(1 << 9)
+
+#define GPIO_PF		(1 << 10)
+#define GPIO_AF		(1 << 11)
+
+#define GPIO_OCR_SHIFT 12
+#define GPIO_OCR_MASK	(3 << GPIO_OCR_SHIFT)
+#define GPIO_AIN	(0 << GPIO_OCR_SHIFT)
+#define GPIO_BIN	(1 << GPIO_OCR_SHIFT)
+#define GPIO_CIN	(2 << GPIO_OCR_SHIFT)
+#define GPIO_GPIO	(3 << GPIO_OCR_SHIFT)
+
+#define GPIO_AOUT_SHIFT	14
+#define GPIO_AOUT_MASK	(3 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT	(0 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_ISR	(1 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_0	(2 << GPIO_AOUT_SHIFT)
+#define GPIO_AOUT_1	(3 << GPIO_AOUT_SHIFT)
+
+#define GPIO_BOUT_SHIFT	16
+#define GPIO_BOUT_MASK	(3 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT	(0 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_ISR	(1 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_0	(2 << GPIO_BOUT_SHIFT)
+#define GPIO_BOUT_1	(3 << GPIO_BOUT_SHIFT)
+
+/* decode irq number to use with IMR(x), ISR(x) and friends */
+#define IRQ_TO_REG(irq) ((irq - MXC_INTERNAL_IRQS) >> 5)
+
+#define IRQ_GPIOA(x)  (MXC_GPIO_IRQ_START + x)
+#define IRQ_GPIOB(x)  (IRQ_GPIOA(32) + x)
+#define IRQ_GPIOC(x)  (IRQ_GPIOB(32) + x)
+#define IRQ_GPIOD(x)  (IRQ_GPIOC(32) + x)
+#define IRQ_GPIOE(x)  (IRQ_GPIOD(32) + x)
+#define IRQ_GPIOF(x)  (IRQ_GPIOE(32) + x)
+
+extern int mxc_gpio_mode(int gpio_mode);
+extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+		const char *label);
+extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count);
+
+#endif /* __MACH_IOMUX_V1_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h
index 1deda01..f2f73d3 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h
@@ -81,11 +81,13 @@
 
 #define PAD_CTL_ODE			(1 << 3)
 
-#define PAD_CTL_DSE_STANDARD		(0 << 1)
-#define PAD_CTL_DSE_HIGH		(1 << 1)
-#define PAD_CTL_DSE_MAX			(2 << 1)
+#define PAD_CTL_DSE_LOW			(0 << 1)
+#define PAD_CTL_DSE_MED			(1 << 1)
+#define PAD_CTL_DSE_HIGH		(2 << 1)
+#define PAD_CTL_DSE_MAX			(3 << 1)
 
 #define PAD_CTL_SRE_FAST		(1 << 0)
+#define PAD_CTL_SRE_SLOW		(0 << 0)
 
 /*
  * setups a single pad in the iomuxer
diff --git a/arch/arm/plat-mxc/include/mach/iomux.h b/arch/arm/plat-mxc/include/mach/iomux.h
index 011cfcd..3d226d7 100644
--- a/arch/arm/plat-mxc/include/mach/iomux.h
+++ b/arch/arm/plat-mxc/include/mach/iomux.h
@@ -1,102 +1,14 @@
 /*
-* Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
-* Copyright (C) 2009 by Holger Schurig <hs4233@mail.mn-solutions.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.
-*/
+ * Copyright (C) 2010 Uwe Kleine-Koenig, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __MACH_IOMUX_H__
+#define __MACH_IOMUX_H__
 
-#ifndef _MXC_IOMUX_H
-#define _MXC_IOMUX_H
-
-/*
-*  GPIO Module and I/O Multiplexer
-*  x = 0..3 for reg_A, reg_B, reg_C, reg_D
-*/
-#define VA_GPIO_BASE	IO_ADDRESS(GPIO_BASE_ADDR)
-#define MXC_DDIR(x)    (0x00 + ((x) << 8))
-#define MXC_OCR1(x)    (0x04 + ((x) << 8))
-#define MXC_OCR2(x)    (0x08 + ((x) << 8))
-#define MXC_ICONFA1(x) (0x0c + ((x) << 8))
-#define MXC_ICONFA2(x) (0x10 + ((x) << 8))
-#define MXC_ICONFB1(x) (0x14 + ((x) << 8))
-#define MXC_ICONFB2(x) (0x18 + ((x) << 8))
-#define MXC_DR(x)      (0x1c + ((x) << 8))
-#define MXC_GIUS(x)    (0x20 + ((x) << 8))
-#define MXC_SSR(x)     (0x24 + ((x) << 8))
-#define MXC_ICR1(x)    (0x28 + ((x) << 8))
-#define MXC_ICR2(x)    (0x2c + ((x) << 8))
-#define MXC_IMR(x)     (0x30 + ((x) << 8))
-#define MXC_ISR(x)     (0x34 + ((x) << 8))
-#define MXC_GPR(x)     (0x38 + ((x) << 8))
-#define MXC_SWR(x)     (0x3c + ((x) << 8))
-#define MXC_PUEN(x)    (0x40 + ((x) << 8))
-
-#ifdef CONFIG_ARCH_MX1
-# define GPIO_PORT_MAX  3
-#endif
-#ifdef CONFIG_ARCH_MX2
-# define GPIO_PORT_MAX  5
-#endif
-#ifdef CONFIG_ARCH_MX25
-# define GPIO_PORT_MAX  3
-#endif
-
-#ifndef GPIO_PORT_MAX
-# error "GPIO config port count unknown!"
-#endif
-
-#define GPIO_PIN_MASK 0x1f
-
-#define GPIO_PORT_SHIFT 5
-#define GPIO_PORT_MASK (0x7 << GPIO_PORT_SHIFT)
-
-#define GPIO_PORTA (0 << GPIO_PORT_SHIFT)
-#define GPIO_PORTB (1 << GPIO_PORT_SHIFT)
-#define GPIO_PORTC (2 << GPIO_PORT_SHIFT)
-#define GPIO_PORTD (3 << GPIO_PORT_SHIFT)
-#define GPIO_PORTE (4 << GPIO_PORT_SHIFT)
-#define GPIO_PORTF (5 << GPIO_PORT_SHIFT)
-
-#define GPIO_OUT   (1 << 8)
-#define GPIO_IN    (0 << 8)
-#define GPIO_PUEN  (1 << 9)
-
-#define GPIO_PF    (1 << 10)
-#define GPIO_AF    (1 << 11)
-
-#define GPIO_OCR_SHIFT 12
-#define GPIO_OCR_MASK (3 << GPIO_OCR_SHIFT)
-#define GPIO_AIN   (0 << GPIO_OCR_SHIFT)
-#define GPIO_BIN   (1 << GPIO_OCR_SHIFT)
-#define GPIO_CIN   (2 << GPIO_OCR_SHIFT)
-#define GPIO_GPIO  (3 << GPIO_OCR_SHIFT)
-
-#define GPIO_AOUT_SHIFT 14
-#define GPIO_AOUT_MASK (3 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT     (0 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT_ISR (1 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT_0   (2 << GPIO_AOUT_SHIFT)
-#define GPIO_AOUT_1   (3 << GPIO_AOUT_SHIFT)
-
-#define GPIO_BOUT_SHIFT 16
-#define GPIO_BOUT_MASK (3 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT      (0 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT_ISR  (1 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT_0    (2 << GPIO_BOUT_SHIFT)
-#define GPIO_BOUT_1    (3 << GPIO_BOUT_SHIFT)
-
+/* This file will go away, please include mach/iomux-mx... directly */
 
 #ifdef CONFIG_ARCH_MX1
 #include <mach/iomux-mx1.h>
@@ -110,25 +22,5 @@
 #include <mach/iomux-mx27.h>
 #endif
 #endif
-#ifdef CONFIG_ARCH_MX25
-#include <mach/iomux-mx25.h>
-#endif
 
-
-/* decode irq number to use with IMR(x), ISR(x) and friends */
-#define IRQ_TO_REG(irq) ((irq - MXC_INTERNAL_IRQS) >> 5)
-
-#define IRQ_GPIOA(x)  (MXC_GPIO_IRQ_START + x)
-#define IRQ_GPIOB(x)  (IRQ_GPIOA(32) + x)
-#define IRQ_GPIOC(x)  (IRQ_GPIOB(32) + x)
-#define IRQ_GPIOD(x)  (IRQ_GPIOC(32) + x)
-#define IRQ_GPIOE(x)  (IRQ_GPIOD(32) + x)
-#define IRQ_GPIOF(x)  (IRQ_GPIOE(32) + x)
-
-
-extern void mxc_gpio_mode(int gpio_mode);
-extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
-	const char *label);
-extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count);
-
-#endif
+#endif /* __MACH_IOMUX_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index 0cb3476..86781f7 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -12,22 +12,29 @@
 #define __ASM_ARCH_MXC_IRQS_H__
 
 /*
- * So far all i.MX SoCs have 64 internal interrupts
+ * SoCs with TZIC interrupt controller have 128 IRQs, those with AVIC have 64
  */
+#ifdef CONFIG_MXC_TZIC
+#define MXC_INTERNAL_IRQS	128
+#else
 #define MXC_INTERNAL_IRQS	64
+#endif
 
 #define MXC_GPIO_IRQ_START	MXC_INTERNAL_IRQS
 
-#if defined CONFIG_ARCH_MX1
-#define MXC_GPIO_IRQS		(32 * 4)
-#elif defined CONFIG_ARCH_MX2
+/* these are ordered by size to support multi-SoC kernels */
+#if defined CONFIG_ARCH_MX2
 #define MXC_GPIO_IRQS		(32 * 6)
-#elif defined CONFIG_ARCH_MX3
-#define MXC_GPIO_IRQS		(32 * 3)
+#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
+#define MXC_GPIO_IRQS		(32 * 4)
 #elif defined CONFIG_ARCH_MXC91231
 #define MXC_GPIO_IRQS		(32 * 4)
+#elif defined CONFIG_ARCH_MX3
+#define MXC_GPIO_IRQS		(32 * 3)
 #endif
 
 /*
@@ -51,6 +58,7 @@
 #else
 #define MX3_IPU_IRQS 0
 #endif
+/* REVISIT: Add IPU irqs on IMX51 */
 
 #define NR_IRQS			(MXC_IPU_IRQ_START + MX3_IPU_IRQS)
 
diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h
index d3afafd..c4b40c3 100644
--- a/arch/arm/plat-mxc/include/mach/memory.h
+++ b/arch/arm/plat-mxc/include/mach/memory.h
@@ -11,30 +11,31 @@
 #ifndef __ASM_ARCH_MXC_MEMORY_H__
 #define __ASM_ARCH_MXC_MEMORY_H__
 
-#if defined CONFIG_ARCH_MX1
-#define PHYS_OFFSET		UL(0x08000000)
-#elif defined CONFIG_ARCH_MX2
-#ifdef CONFIG_MACH_MX21
-#define PHYS_OFFSET		UL(0xC0000000)
-#endif
-#ifdef CONFIG_MACH_MX27
-#define PHYS_OFFSET		UL(0xA0000000)
-#endif
-#elif defined CONFIG_ARCH_MX3
-#define PHYS_OFFSET		UL(0x80000000)
-#elif defined CONFIG_ARCH_MX25
-#define PHYS_OFFSET		UL(0x80000000)
-#elif defined CONFIG_ARCH_MXC91231
-#define PHYS_OFFSET		UL(0x90000000)
-#endif
+#define MX1_PHYS_OFFSET		UL(0x08000000)
+#define MX21_PHYS_OFFSET	UL(0xc0000000)
+#define MX25_PHYS_OFFSET	UL(0x80000000)
+#define MX27_PHYS_OFFSET	UL(0xa0000000)
+#define MX3x_PHYS_OFFSET	UL(0x80000000)
+#define MX51_PHYS_OFFSET	UL(0x90000000)
+#define MXC91231_PHYS_OFFSET	UL(0x90000000)
 
-#if defined(CONFIG_MX1_VIDEO)
-/*
- * Increase size of DMA-consistent memory region.
- * This is required for i.MX camera driver to capture at least four VGA frames.
- */
-#define CONSISTENT_DMA_SIZE SZ_4M
-#endif /* CONFIG_MX1_VIDEO */
+#if !defined(CONFIG_RUNTIME_PHYS_OFFSET)
+# if defined CONFIG_ARCH_MX1
+#  define PHYS_OFFSET		MX1_PHYS_OFFSET
+# elif defined CONFIG_MACH_MX21
+#  define PHYS_OFFSET		MX21_PHYS_OFFSET
+# elif defined CONFIG_ARCH_MX25
+#  define PHYS_OFFSET		MX25_PHYS_OFFSET
+# elif defined CONFIG_MACH_MX27
+#  define PHYS_OFFSET		MX27_PHYS_OFFSET
+# elif defined CONFIG_ARCH_MX3
+#  define PHYS_OFFSET		MX3x_PHYS_OFFSET
+# elif defined CONFIG_ARCH_MXC91231
+#  define PHYS_OFFSET		MXC91231_PHYS_OFFSET
+# elif defined CONFIG_ARCH_MX5
+#  define PHYS_OFFSET		MX51_PHYS_OFFSET
+# endif
+#endif
 
 #if defined(CONFIG_MX3_VIDEO)
 /*
@@ -42,6 +43,13 @@
  * This is required for mx3 camera driver to capture at least two QXGA frames.
  */
 #define CONSISTENT_DMA_SIZE SZ_8M
-#endif /* CONFIG_MX3_VIDEO */
+
+#elif defined(CONFIG_MX1_VIDEO)
+/*
+ * Increase size of DMA-consistent memory region.
+ * This is required for i.MX camera driver to capture at least four VGA frames.
+ */
+#define CONSISTENT_DMA_SIZE SZ_4M
+#endif /* CONFIG_MX1_VIDEO */
 
 #endif /* __ASM_ARCH_MXC_MEMORY_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mtd-xip.h b/arch/arm/plat-mxc/include/mach/mtd-xip.h
deleted file mode 100644
index 1ab1bba..0000000
--- a/arch/arm/plat-mxc/include/mach/mtd-xip.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * MTD primitives for XIP support. Architecture specific functions
- *
- * Do not include this file directly. It's included from linux/mtd/xip.h
- *
- * Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com>, Teltonika, 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 <mach/mxc_timer.h>
-
-#ifndef __ARCH_IMX_MTD_XIP_H__
-#define __ARCH_IMX_MTD_XIP_H__
-
-#ifdef CONFIG_ARCH_MX1
-/* AITC registers */
-#define AITC_BASE	IO_ADDRESS(AVIC_BASE_ADDR)
-#define NIPNDH		(AITC_BASE + 0x58)
-#define NIPNDL		(AITC_BASE + 0x5C)
-#define INTENABLEH	(AITC_BASE + 0x10)
-#define INTENABLEL	(AITC_BASE + 0x14)
-/* MTD macros */
-#define xip_irqpending() ((__raw_readl(INTENABLEH) &  __raw_readl(NIPNDH)) \
-			|| (__raw_readl(INTENABLEL) &  __raw_readl(NIPNDL)))
-#define xip_currtime()		(__raw_readl(TIMER_BASE + MXC_TCN))
-#define xip_elapsed_since(x)	(signed)((__raw_readl(TIMER_BASE + MXC_TCN) - (x)) / 96)
-#define xip_cpu_idle()		asm volatile ("mcr p15, 0, %0, c7, c0, 4" :: "r" (0))
-#endif /* CONFIG_ARCH_MX1 */
-
-#endif /* __ARCH_IMX_MTD_XIP_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx1.h b/arch/arm/plat-mxc/include/mach/mx1.h
index 1b2890a..5eba7e6 100644
--- a/arch/arm/plat-mxc/include/mach/mx1.h
+++ b/arch/arm/plat-mxc/include/mach/mx1.h
@@ -9,156 +9,289 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef __ASM_ARCH_MXC_MX1_H__
-#define __ASM_ARCH_MXC_MX1_H__
+#ifndef __MACH_MX1_H__
+#define __MACH_MX1_H__
 
 #include <mach/vmalloc.h>
 
 /*
  * Memory map
  */
-#define IMX_IO_PHYS	0x00200000
-#define IMX_IO_SIZE	0x00100000
-#define IMX_IO_BASE	VMALLOC_END
+#define MX1_IO_BASE_ADDR	0x00200000
+#define MX1_IO_SIZE		SZ_1M
+#define MX1_IO_BASE_ADDR_VIRT	VMALLOC_END
 
-#define IMX_CS0_PHYS	0x10000000
-#define IMX_CS0_SIZE	0x02000000
+#define MX1_CS0_PHYS		0x10000000
+#define MX1_CS0_SIZE		0x02000000
 
-#define IMX_CS1_PHYS	0x12000000
-#define IMX_CS1_SIZE	0x01000000
+#define MX1_CS1_PHYS		0x12000000
+#define MX1_CS1_SIZE		0x01000000
 
-#define IMX_CS2_PHYS	0x13000000
-#define IMX_CS2_SIZE	0x01000000
+#define MX1_CS2_PHYS		0x13000000
+#define MX1_CS2_SIZE		0x01000000
 
-#define IMX_CS3_PHYS	0x14000000
-#define IMX_CS3_SIZE	0x01000000
+#define MX1_CS3_PHYS		0x14000000
+#define MX1_CS3_SIZE		0x01000000
 
-#define IMX_CS4_PHYS	0x15000000
-#define IMX_CS4_SIZE	0x01000000
+#define MX1_CS4_PHYS		0x15000000
+#define MX1_CS4_SIZE		0x01000000
 
-#define IMX_CS5_PHYS	0x16000000
-#define IMX_CS5_SIZE	0x01000000
+#define MX1_CS5_PHYS		0x16000000
+#define MX1_CS5_SIZE		0x01000000
 
 /*
  *  Register BASEs, based on OFFSETs
  */
-#define AIPI1_BASE_ADDR		(0x00000 + IMX_IO_PHYS)
-#define WDT_BASE_ADDR		(0x01000 + IMX_IO_PHYS)
-#define TIM1_BASE_ADDR		(0x02000 + IMX_IO_PHYS)
-#define TIM2_BASE_ADDR		(0x03000 + IMX_IO_PHYS)
-#define RTC_BASE_ADDR		(0x04000 + IMX_IO_PHYS)
-#define LCDC_BASE_ADDR		(0x05000 + IMX_IO_PHYS)
-#define UART1_BASE_ADDR		(0x06000 + IMX_IO_PHYS)
-#define UART2_BASE_ADDR		(0x07000 + IMX_IO_PHYS)
-#define PWM_BASE_ADDR		(0x08000 + IMX_IO_PHYS)
-#define DMA_BASE_ADDR		(0x09000 + IMX_IO_PHYS)
-#define AIPI2_BASE_ADDR		(0x10000 + IMX_IO_PHYS)
-#define SIM_BASE_ADDR		(0x11000 + IMX_IO_PHYS)
-#define USBD_BASE_ADDR		(0x12000 + IMX_IO_PHYS)
-#define SPI1_BASE_ADDR		(0x13000 + IMX_IO_PHYS)
-#define MMC_BASE_ADDR		(0x14000 + IMX_IO_PHYS)
-#define ASP_BASE_ADDR		(0x15000 + IMX_IO_PHYS)
-#define BTA_BASE_ADDR		(0x16000 + IMX_IO_PHYS)
-#define I2C_BASE_ADDR		(0x17000 + IMX_IO_PHYS)
-#define SSI_BASE_ADDR		(0x18000 + IMX_IO_PHYS)
-#define SPI2_BASE_ADDR		(0x19000 + IMX_IO_PHYS)
-#define MSHC_BASE_ADDR		(0x1A000 + IMX_IO_PHYS)
-#define CCM_BASE_ADDR		(0x1B000 + IMX_IO_PHYS)
-#define SCM_BASE_ADDR		(0x1B804 + IMX_IO_PHYS)
-#define GPIO_BASE_ADDR		(0x1C000 + IMX_IO_PHYS)
-#define EIM_BASE_ADDR		(0x20000 + IMX_IO_PHYS)
-#define SDRAMC_BASE_ADDR	(0x21000 + IMX_IO_PHYS)
-#define MMA_BASE_ADDR		(0x22000 + IMX_IO_PHYS)
-#define AVIC_BASE_ADDR		(0x23000 + IMX_IO_PHYS)
-#define CSI_BASE_ADDR		(0x24000 + IMX_IO_PHYS)
+#define MX1_AIPI1_BASE_ADDR		(0x00000 + MX1_IO_BASE_ADDR)
+#define MX1_WDT_BASE_ADDR		(0x01000 + MX1_IO_BASE_ADDR)
+#define MX1_TIM1_BASE_ADDR		(0x02000 + MX1_IO_BASE_ADDR)
+#define MX1_TIM2_BASE_ADDR		(0x03000 + MX1_IO_BASE_ADDR)
+#define MX1_RTC_BASE_ADDR		(0x04000 + MX1_IO_BASE_ADDR)
+#define MX1_LCDC_BASE_ADDR		(0x05000 + MX1_IO_BASE_ADDR)
+#define MX1_UART1_BASE_ADDR		(0x06000 + MX1_IO_BASE_ADDR)
+#define MX1_UART2_BASE_ADDR		(0x07000 + MX1_IO_BASE_ADDR)
+#define MX1_PWM_BASE_ADDR		(0x08000 + MX1_IO_BASE_ADDR)
+#define MX1_DMA_BASE_ADDR		(0x09000 + MX1_IO_BASE_ADDR)
+#define MX1_AIPI2_BASE_ADDR		(0x10000 + MX1_IO_BASE_ADDR)
+#define MX1_SIM_BASE_ADDR		(0x11000 + MX1_IO_BASE_ADDR)
+#define MX1_USBD_BASE_ADDR		(0x12000 + MX1_IO_BASE_ADDR)
+#define MX1_SPI1_BASE_ADDR		(0x13000 + MX1_IO_BASE_ADDR)
+#define MX1_MMC_BASE_ADDR		(0x14000 + MX1_IO_BASE_ADDR)
+#define MX1_ASP_BASE_ADDR		(0x15000 + MX1_IO_BASE_ADDR)
+#define MX1_BTA_BASE_ADDR		(0x16000 + MX1_IO_BASE_ADDR)
+#define MX1_I2C_BASE_ADDR		(0x17000 + MX1_IO_BASE_ADDR)
+#define MX1_SSI_BASE_ADDR		(0x18000 + MX1_IO_BASE_ADDR)
+#define MX1_SPI2_BASE_ADDR		(0x19000 + MX1_IO_BASE_ADDR)
+#define MX1_MSHC_BASE_ADDR		(0x1A000 + MX1_IO_BASE_ADDR)
+#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_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)
+#define MX1_AVIC_BASE_ADDR		(0x23000 + MX1_IO_BASE_ADDR)
+#define MX1_CSI_BASE_ADDR		(0x24000 + MX1_IO_BASE_ADDR)
 
 /* macro to get at IO space when running virtually */
-#define IO_ADDRESS(x)	((x) - IMX_IO_PHYS + IMX_IO_BASE)
-
-/* define macros needed for entry-macro.S */
-#define AVIC_IO_ADDRESS(x)	IO_ADDRESS(x)
+#define MX1_IO_ADDRESS(x) (						\
+	IMX_IO_ADDRESS(x, MX1_IO))
 
 /* fixed interrput numbers */
-#define INT_SOFTINT		0
-#define CSI_INT			6
-#define DSPA_MAC_INT		7
-#define DSPA_INT		8
-#define COMP_INT		9
-#define MSHC_XINT		10
-#define GPIO_INT_PORTA		11
-#define GPIO_INT_PORTB		12
-#define GPIO_INT_PORTC		13
-#define LCDC_INT		14
-#define SIM_INT			15
-#define SIM_DATA_INT		16
-#define RTC_INT			17
-#define RTC_SAMINT		18
-#define UART2_MINT_PFERR	19
-#define UART2_MINT_RTS		20
-#define UART2_MINT_DTR		21
-#define UART2_MINT_UARTC	22
-#define UART2_MINT_TX		23
-#define UART2_MINT_RX		24
-#define UART1_MINT_PFERR	25
-#define UART1_MINT_RTS		26
-#define UART1_MINT_DTR		27
-#define UART1_MINT_UARTC	28
-#define UART1_MINT_TX		29
-#define UART1_MINT_RX		30
-#define VOICE_DAC_INT		31
-#define VOICE_ADC_INT		32
-#define PEN_DATA_INT		33
-#define PWM_INT			34
-#define SDHC_INT		35
-#define I2C_INT			39
-#define CSPI_INT		41
-#define SSI_TX_INT		42
-#define SSI_TX_ERR_INT		43
-#define SSI_RX_INT		44
-#define SSI_RX_ERR_INT		45
-#define TOUCH_INT		46
-#define USBD_INT0		47
-#define USBD_INT1		48
-#define USBD_INT2		49
-#define USBD_INT3		50
-#define USBD_INT4		51
-#define USBD_INT5		52
-#define USBD_INT6		53
-#define BTSYS_INT		55
-#define BTTIM_INT		56
-#define BTWUI_INT		57
-#define TIM2_INT		58
-#define TIM1_INT		59
-#define DMA_ERR			60
-#define DMA_INT			61
-#define GPIO_INT_PORTD		62
-#define WDT_INT			63
+#define MX1_INT_SOFTINT		0
+#define MX1_CSI_INT		6
+#define MX1_DSPA_MAC_INT	7
+#define MX1_DSPA_INT		8
+#define MX1_COMP_INT		9
+#define MX1_MSHC_XINT		10
+#define MX1_GPIO_INT_PORTA	11
+#define MX1_GPIO_INT_PORTB	12
+#define MX1_GPIO_INT_PORTC	13
+#define MX1_LCDC_INT		14
+#define MX1_SIM_INT		15
+#define MX1_SIM_DATA_INT	16
+#define MX1_RTC_INT		17
+#define MX1_RTC_SAMINT		18
+#define MX1_UART2_MINT_PFERR	19
+#define MX1_UART2_MINT_RTS	20
+#define MX1_UART2_MINT_DTR	21
+#define MX1_UART2_MINT_UARTC	22
+#define MX1_UART2_MINT_TX	23
+#define MX1_UART2_MINT_RX	24
+#define MX1_UART1_MINT_PFERR	25
+#define MX1_UART1_MINT_RTS	26
+#define MX1_UART1_MINT_DTR	27
+#define MX1_UART1_MINT_UARTC	28
+#define MX1_UART1_MINT_TX	29
+#define MX1_UART1_MINT_RX	30
+#define MX1_VOICE_DAC_INT	31
+#define MX1_VOICE_ADC_INT	32
+#define MX1_PEN_DATA_INT	33
+#define MX1_PWM_INT		34
+#define MX1_SDHC_INT		35
+#define MX1_I2C_INT		39
+#define MX1_CSPI_INT		41
+#define MX1_SSI_TX_INT		42
+#define MX1_SSI_TX_ERR_INT	43
+#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_BTSYS_INT		55
+#define MX1_BTTIM_INT		56
+#define MX1_BTWUI_INT		57
+#define MX1_TIM2_INT		58
+#define MX1_TIM1_INT		59
+#define MX1_DMA_ERR		60
+#define MX1_DMA_INT		61
+#define MX1_GPIO_INT_PORTD	62
+#define MX1_WDT_INT		63
 
 /* DMA */
-#define DMA_REQ_UART3_T		2
-#define DMA_REQ_UART3_R		3
-#define DMA_REQ_SSI2_T		4
-#define DMA_REQ_SSI2_R		5
-#define DMA_REQ_CSI_STAT	6
-#define DMA_REQ_CSI_R		7
-#define DMA_REQ_MSHC		8
-#define DMA_REQ_DSPA_DCT_DOUT	9
-#define DMA_REQ_DSPA_DCT_DIN	10
-#define DMA_REQ_DSPA_MAC	11
-#define DMA_REQ_EXT		12
-#define DMA_REQ_SDHC		13
-#define DMA_REQ_SPI1_R		14
-#define DMA_REQ_SPI1_T		15
-#define DMA_REQ_SSI_T		16
-#define DMA_REQ_SSI_R		17
-#define DMA_REQ_ASP_DAC		18
-#define DMA_REQ_ASP_ADC		19
-#define DMA_REQ_USP_EP(x)	(20 + (x))
-#define DMA_REQ_SPI2_R		26
-#define DMA_REQ_SPI2_T		27
-#define DMA_REQ_UART2_T		28
-#define DMA_REQ_UART2_R		29
-#define DMA_REQ_UART1_T		30
-#define DMA_REQ_UART1_R		31
+#define MX1_DMA_REQ_UART3_T		2
+#define MX1_DMA_REQ_UART3_R		3
+#define MX1_DMA_REQ_SSI2_T		4
+#define MX1_DMA_REQ_SSI2_R		5
+#define MX1_DMA_REQ_CSI_STAT		6
+#define MX1_DMA_REQ_CSI_R		7
+#define MX1_DMA_REQ_MSHC		8
+#define MX1_DMA_REQ_DSPA_DCT_DOUT	9
+#define MX1_DMA_REQ_DSPA_DCT_DIN	10
+#define MX1_DMA_REQ_DSPA_MAC		11
+#define MX1_DMA_REQ_EXT			12
+#define MX1_DMA_REQ_SDHC		13
+#define MX1_DMA_REQ_SPI1_R		14
+#define MX1_DMA_REQ_SPI1_T		15
+#define MX1_DMA_REQ_SSI_T		16
+#define MX1_DMA_REQ_SSI_R		17
+#define MX1_DMA_REQ_ASP_DAC		18
+#define MX1_DMA_REQ_ASP_ADC		19
+#define MX1_DMA_REQ_USP_EP(x)		(20 + (x))
+#define MX1_DMA_REQ_SPI2_R		26
+#define MX1_DMA_REQ_SPI2_T		27
+#define MX1_DMA_REQ_UART2_T		28
+#define MX1_DMA_REQ_UART2_R		29
+#define MX1_DMA_REQ_UART1_T		30
+#define MX1_DMA_REQ_UART1_R		31
 
-#endif /*  __ASM_ARCH_MXC_MX1_H__ */
+/*
+ * This doesn't depend on IMX_NEEDS_DEPRECATED_SYMBOLS
+ * 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_I2C_INT
+#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 */
+
+#endif /* ifndef __MACH_MX1_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx21-usbhost.h b/arch/arm/plat-mxc/include/mach/mx21-usbhost.h
new file mode 100644
index 0000000..22d0b59
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx21-usbhost.h
@@ -0,0 +1,38 @@
+/*
+ *	Copyright (C) 2009 Martin Fuzzey <mfuzzey@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.
+ */
+
+#ifndef __ASM_ARCH_MX21_USBH
+#define __ASM_ARCH_MX21_USBH
+
+enum mx21_usbh_xcvr {
+	/* Values below as used by hardware (HWMODE register) */
+	MX21_USBXCVR_TXDIF_RXDIF = 0,
+	MX21_USBXCVR_TXDIF_RXSE = 1,
+	MX21_USBXCVR_TXSE_RXDIF = 2,
+	MX21_USBXCVR_TXSE_RXSE = 3,
+};
+
+struct mx21_usbh_platform_data {
+	enum mx21_usbh_xcvr host_xcvr; /* tranceiver mode host 1,2 ports */
+	enum mx21_usbh_xcvr otg_xcvr; /* tranceiver mode otg (as host) port */
+	u16 	enable_host1:1,
+		enable_host2:1,
+		enable_otg_host:1, /* enable "OTG" port (as host) */
+		host1_xcverless:1, /* traceiverless host1 port */
+		host1_txenoe:1, /* output enable host1 transmit enable */
+		otg_ext_xcvr:1, /* external tranceiver for OTG port */
+		unused:10;
+};
+
+#endif /* __ASM_ARCH_MX21_USBH */
diff --git a/arch/arm/plat-mxc/include/mach/mx21.h b/arch/arm/plat-mxc/include/mach/mx21.h
index bb297d8..ed98b9c 100644
--- a/arch/arm/plat-mxc/include/mach/mx21.h
+++ b/arch/arm/plat-mxc/include/mach/mx21.h
@@ -22,8 +22,8 @@
  * MA  02110-1301, USA.
  */
 
-#ifndef __ASM_ARCH_MXC_MX21_H__
-#define __ASM_ARCH_MXC_MX21_H__
+#ifndef __MACH_MX21_H__
+#define __MACH_MX21_H__
 
 #define MX21_AIPI_BASE_ADDR		0x10000000
 #define MX21_AIPI_BASE_ADDR_VIRT	0xf4000000
@@ -92,6 +92,11 @@
 
 #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))
+
 /* fixed interrupt numbers */
 #define MX21_INT_CSPI3		6
 #define MX21_INT_GPIO		8
@@ -179,6 +184,7 @@
 #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
@@ -211,5 +217,6 @@
 #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 /* __ASM_ARCH_MXC_MX21_H__ */
+#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 854e2dc..4eb6e33 100644
--- a/arch/arm/plat-mxc/include/mach/mx25.h
+++ b/arch/arm/plat-mxc/include/mach/mx25.h
@@ -22,27 +22,27 @@
 #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_AIPS1_IO_ADDRESS(x)  \
-	(((x) - MX25_AIPS1_BASE_ADDR) + MX25_AIPS1_BASE_ADDR_VIRT)
-#define MX25_AIPS2_IO_ADDRESS(x)  \
-	(((x) - MX25_AIPS2_BASE_ADDR) + MX25_AIPS2_BASE_ADDR_VIRT)
-#define MX25_AVIC_IO_ADDRESS(x)  \
-	(((x) - MX25_AVIC_BASE_ADDR) + MX25_AVIC_BASE_ADDR_VIRT)
+#define MX25_IO_ADDRESS(x) (					\
+	IMX_IO_ADDRESS(x, MX25_AIPS1) ?:			\
+	IMX_IO_ADDRESS(x, MX25_AIPS2) ?:			\
+	IMX_IO_ADDRESS(x, MX25_AVIC))
 
-#define __in_range(addr, name)	((addr) >= name##_BASE_ADDR && (addr) < name##_BASE_ADDR + name##_SIZE)
-
-#define MX25_IO_ADDRESS(x)					\
-	(void __force __iomem *)				\
-	(__in_range(x, MX25_AIPS1) ? MX25_AIPS1_IO_ADDRESS(x) :	\
-	__in_range(x, MX25_AIPS2) ? MX25_AIPS2_IO_ADDRESS(x) :	\
-	__in_range(x, MX25_AVIC) ? MX25_AVIC_IO_ADDRESS(x) :	\
-	0xDEADBEEF)
-
-#define UART1_BASE_ADDR			0x43f90000
-#define UART2_BASE_ADDR			0x43f94000
+#define MX25_UART1_BASE_ADDR		0x43f90000
+#define MX25_UART2_BASE_ADDR		0x43f94000
 
 #define MX25_FEC_BASE_ADDR		0x50038000
+#define MX25_NFC_BASE_ADDR		0xbb000000
+#define MX25_DRYICE_BASE_ADDR		0x53ffc000
+#define MX25_LCDC_BASE_ADDR		0x53fbc000
 
+#define MX25_INT_DRYICE	25
 #define MX25_INT_FEC	57
+#define MX25_INT_NANDFC	33
+#define MX25_INT_LCDC	39
 
-#endif /* __MACH_MX25_H__ */
+#if defined(IMX_NEEDS_DEPRECATED_SYMBOLS)
+#define UART1_BASE_ADDR			MX25_UART1_BASE_ADDR
+#define UART2_BASE_ADDR			MX25_UART2_BASE_ADDR
+#endif
+
+#endif /* ifndef __MACH_MX25_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h
index e2ae19f..bae9cd7 100644
--- a/arch/arm/plat-mxc/include/mach/mx27.h
+++ b/arch/arm/plat-mxc/include/mach/mx27.h
@@ -21,8 +21,12 @@
  * MA  02110-1301, USA.
  */
 
-#ifndef __ASM_ARCH_MXC_MX27_H__
-#define __ASM_ARCH_MXC_MX27_H__
+#ifndef __MACH_MX27_H__
+#define __MACH_MX27_H__
+
+#ifndef __ASSEMBLER__
+#include <linux/io.h>
+#endif
 
 #define MX27_AIPI_BASE_ADDR		0x10000000
 #define MX27_AIPI_BASE_ADDR_VIRT	0xf4000000
@@ -109,11 +113,31 @@
 #define MX27_M3IF_BASE_ADDR			(MX27_X_MEMC_BASE_ADDR + 0x3000)
 #define MX27_PCMCIA_CTL_BASE_ADDR		(MX27_X_MEMC_BASE_ADDR + 0x4000)
 
+#define MX27_WEIM_CSCRx_BASE_ADDR(cs)	(MX27_WEIM_BASE_ADDR + (cs) * 0x10)
+#define MX27_WEIM_CSCRxU(cs)			(MX27_WEIM_CSCRx_BASE_ADDR(cs))
+#define MX27_WEIM_CSCRxL(cs)			(MX27_WEIM_CSCRx_BASE_ADDR(cs) + 0x4)
+#define MX27_WEIM_CSCRxA(cs)			(MX27_WEIM_CSCRx_BASE_ADDR(cs) + 0x8)
+
 #define MX27_PCMCIA_MEM_BASE_ADDR	0xdc000000
 
 /* 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))
+
+#ifndef __ASSEMBLER__
+static inline void mx27_setup_weimcs(size_t cs,
+		unsigned upper, unsigned lower, unsigned addional)
+{
+	__raw_writel(upper, MX27_IO_ADDRESS(MX27_WEIM_CSCRxU(cs)));
+	__raw_writel(lower, MX27_IO_ADDRESS(MX27_WEIM_CSCRxL(cs)));
+	__raw_writel(addional, MX27_IO_ADDRESS(MX27_WEIM_CSCRxA(cs)));
+}
+#endif
+
 /* fixed interrupt numbers */
 #define MX27_INT_I2C2		1
 #define MX27_INT_GPT6		2
@@ -225,6 +249,7 @@
 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
@@ -292,5 +317,6 @@
 #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 /* __ASM_ARCH_MXC_MX27_H__ */
+#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 f2eaf14..afb895a 100644
--- a/arch/arm/plat-mxc/include/mach/mx2x.h
+++ b/arch/arm/plat-mxc/include/mach/mx2x.h
@@ -20,8 +20,8 @@
  * MA  02110-1301, USA.
  */
 
-#ifndef __ASM_ARCH_MXC_MX2x_H__
-#define __ASM_ARCH_MXC_MX2x_H__
+#ifndef __MACH_MX2x_H__
+#define __MACH_MX2x_H__
 
 /* The following addresses are common between i.MX21 and i.MX27 */
 
@@ -176,6 +176,7 @@
 #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
@@ -287,5 +288,6 @@
 #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 /* __ASM_ARCH_MXC_MX2x_H__ */
+#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 b8b47d1..fb90e11 100644
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ b/arch/arm/plat-mxc/include/mach/mx31.h
@@ -1,3 +1,10 @@
+#ifndef __MACH_MX31_H__
+#define __MACH_MX31_H__
+
+#ifndef __ASSEMBLER__
+#include <linux/io.h>
+#endif
+
 /*
  * IRAM
  */
@@ -107,8 +114,30 @@
 #define MX31_EMI_CTL_BASE_ADDR			(MX31_X_MEMC_BASE_ADDR + 0x4000)
 #define MX31_PCMCIA_CTL_BASE_ADDR		MX31_EMI_CTL_BASE_ADDR
 
+#define MX31_WEIM_CSCRx_BASE_ADDR(cs)	(MX31_WEIM_BASE_ADDR + (cs) * 0x10)
+#define MX31_WEIM_CSCRxU(cs)			(MX31_WEIM_CSCRx_BASE_ADDR(cs))
+#define MX31_WEIM_CSCRxL(cs)			(MX31_WEIM_CSCRx_BASE_ADDR(cs) + 0x4)
+#define MX31_WEIM_CSCRxA(cs)			(MX31_WEIM_CSCRx_BASE_ADDR(cs) + 0x8)
+
 #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))
+
+#ifndef __ASSEMBLER__
+static inline void mx31_setup_weimcs(size_t cs,
+		unsigned upper, unsigned lower, unsigned addional)
+{
+	__raw_writel(upper, MX31_IO_ADDRESS(MX31_WEIM_CSCRxU(cs)));
+	__raw_writel(lower, MX31_IO_ADDRESS(MX31_WEIM_CSCRxL(cs)));
+	__raw_writel(addional, MX31_IO_ADDRESS(MX31_WEIM_CSCRxA(cs)));
+}
+#endif
+
 #define MX31_INT_I2C3		3
 #define MX31_INT_I2C2		4
 #define MX31_INT_MPEG4_ENCODER	5
@@ -186,6 +215,7 @@
 #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
@@ -216,3 +246,6 @@
 #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 af871bc..526a558 100644
--- a/arch/arm/plat-mxc/include/mach/mx35.h
+++ b/arch/arm/plat-mxc/include/mach/mx35.h
@@ -1,3 +1,5 @@
+#ifndef __MACH_MX35_H__
+#define __MACH_MX35_H__
 /*
  * IRAM
  */
@@ -104,6 +106,13 @@
 #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))
+
 /*
  * Interrupt numbers
  */
@@ -180,6 +189,7 @@
 #define MX35_SYSTEM_REV_MIN		MX35_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
@@ -195,3 +205,6 @@
 #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 be69272..7a356de3 100644
--- a/arch/arm/plat-mxc/include/mach/mx3x.h
+++ b/arch/arm/plat-mxc/include/mach/mx3x.h
@@ -8,8 +8,8 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef __ASM_ARCH_MXC_MX31_H__
-#define __ASM_ARCH_MXC_MX31_H__
+#ifndef __MACH_MX3x_H__
+#define __MACH_MX3x_H__
 
 /*
  * MX31 memory map:
@@ -269,6 +269,7 @@
 }
 #endif
 
+#ifdef IMX_NEEDS_DEPRECATED_SYMBOLS
 /* these should go away */
 #define L2CC_BASE_ADDR MX3x_L2CC_BASE_ADDR
 #define L2CC_SIZE MX3x_L2CC_SIZE
@@ -401,5 +402,6 @@
 #define CHIP_REV_3_2 MX3x_CHIP_REV_3_2
 #define SYSTEM_REV_MIN MX3x_SYSTEM_REV_MIN
 #define SYSTEM_REV_NUM MX3x_SYSTEM_REV_NUM
+#endif
 
-#endif /*  __ASM_ARCH_MXC_MX31_H__ */
+#endif /* ifndef __MACH_MX3x_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx51.h b/arch/arm/plat-mxc/include/mach/mx51.h
new file mode 100644
index 0000000..771532b
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx51.h
@@ -0,0 +1,454 @@
+#ifndef __ASM_ARCH_MXC_MX51_H__
+#define __ASM_ARCH_MXC_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
+ * FA100000	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
+ * F9000000	CFFF0000	64K	NFC (NAND Flash AXI)
+ *
+ */
+
+/*
+ * IRAM
+ */
+#define MX51_IRAM_BASE_ADDR		0x1FFE0000	/* internal ram */
+#define MX51_IRAM_BASE_ADDR_VIRT	0xFA3E0000
+#define MX51_IRAM_PARTITIONS		16
+#define MX51_IRAM_PARTITIONS_TO1	12
+#define MX51_IRAM_SIZE		(MX51_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
+
+/*
+ * NFC
+ */
+#define MX51_NFC_AXI_BASE_ADDR		0xCFFF0000	/* NAND flash AXI */
+#define MX51_NFC_AXI_BASE_ADDR_VIRT	0xF9000000
+#define MX51_NFC_AXI_SIZE		SZ_64K
+
+/*
+ * Graphics Memory of GPU
+ */
+#define MX51_GPU_BASE_ADDR		0x20000000
+#define MX51_GPU2D_BASE_ADDR		0xD0000000
+
+#define MX51_TZIC_BASE_ADDR		0x8FFFC000
+#define MX51_TZIC_BASE_ADDR_VIRT	0xFA100000
+#define MX51_TZIC_SIZE			SZ_16K
+
+#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 + 0x00001000)
+#define MX51_ETM_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00002000)
+#define MX51_TPIU_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00003000)
+#define MX51_CTI0_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00004000)
+#define MX51_CTI1_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00005000)
+#define MX51_CTI2_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00006000)
+#define MX51_CTI3_BASE_ADDR		(MX51_DEBUG_BASE_ADDR + 0x00007000)
+#define MX51_CORTEX_DBG_BASE_ADDR	(MX51_DEBUG_BASE_ADDR + 0x00008000)
+
+/*
+ * 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_MMC_SDHC1_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00004000)
+#define MX51_MMC_SDHC2_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00008000)
+#define MX51_UART3_BASE_ADDR 		(MX51_SPBA0_BASE_ADDR + 0x0000C000)
+#define MX51_CSPI1_BASE_ADDR 		(MX51_SPBA0_BASE_ADDR + 0x00010000)
+#define MX51_SSI2_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x00014000)
+#define MX51_MMC_SDHC3_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00020000)
+#define MX51_MMC_SDHC4_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00024000)
+#define MX51_SPDIF_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x00028000)
+#define MX51_ATA_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x00030000)
+#define MX51_SLIM_DMA_BASE_ADDR		(MX51_SPBA0_BASE_ADDR + 0x00034000)
+#define MX51_HSI2C_DMA_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00038000)
+#define MX51_SPBA_CTRL_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x0003C000)
+
+/*
+ * defines for SPBA modules
+ */
+#define MX51_SPBA_SDHC1	0x04
+#define MX51_SPBA_SDHC2	0x08
+#define MX51_SPBA_UART3	0x0C
+#define MX51_SPBA_CSPI1	0x10
+#define MX51_SPBA_SSI2	0x14
+#define MX51_SPBA_SDHC3	0x20
+#define MX51_SPBA_SDHC4	0x24
+#define MX51_SPBA_SPDIF	0x28
+#define MX51_SPBA_ATA	0x30
+#define MX51_SPBA_SLIM	0x34
+#define MX51_SPBA_HSI2C	0x38
+#define MX51_SPBA_CTRL	0x3C
+
+/*
+ * 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 + 0x00080000)
+#define MX51_GPIO1_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00084000)
+#define MX51_GPIO2_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00088000)
+#define MX51_GPIO3_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x0008C000)
+#define MX51_GPIO4_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00090000)
+#define MX51_KPP_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00094000)
+#define MX51_WDOG_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x00098000)
+#define MX51_WDOG2_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x0009C000)
+#define MX51_GPT1_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000A0000)
+#define MX51_SRTC_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000A4000)
+#define MX51_IOMUXC_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000A8000)
+#define MX51_EPIT1_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000AC000)
+#define MX51_EPIT2_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000B0000)
+#define MX51_PWM1_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000B4000)
+#define MX51_PWM2_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000B8000)
+#define MX51_UART1_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000BC000)
+#define MX51_UART2_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000C0000)
+#define MX51_SRC_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000D0000)
+#define MX51_CCM_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000D4000)
+#define MX51_GPC_BASE_ADDR	(MX51_AIPS1_BASE_ADDR + 0x000D8000)
+
+/*
+ * Defines for modules using static and dynamic DMA channels
+ */
+#define MX51_MXC_DMA_CHANNEL_IRAM	30
+#define MX51_MXC_DMA_CHANNEL_SPDIF_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART1_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART1_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART2_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART2_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART3_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_UART3_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_MMC1	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_MMC2	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_SSI1_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_SSI1_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_SSI2_RX	MXC_DMA_DYNAMIC_CHANNEL
+#ifdef CONFIG_SDMA_IRAM
+#define MX51_MXC_DMA_CHANNEL_SSI2_TX	(MX51_MXC_DMA_CHANNEL_IRAM + 1)
+#else				/*CONFIG_SDMA_IRAM */
+#define MX51_MXC_DMA_CHANNEL_SSI2_TX	MXC_DMA_DYNAMIC_CHANNEL
+#endif				/*CONFIG_SDMA_IRAM */
+#define MX51_MXC_DMA_CHANNEL_CSPI1_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_CSPI1_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_CSPI2_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_CSPI2_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_CSPI3_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_CSPI3_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_ATA_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_ATA_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MX51_MXC_DMA_CHANNEL_MEMORY	MXC_DMA_DYNAMIC_CHANNEL
+
+/*
+ * 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 + 0x00080000)
+#define MX51_PLL2_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x00084000)
+#define MX51_PLL3_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x00088000)
+#define MX51_AHBMAX_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x00094000)
+#define MX51_IIM_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x00098000)
+#define MX51_CSU_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x0009C000)
+#define MX51_ARM_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000A0000)
+#define MX51_OWIRE_BASE_ADDR 	(MX51_AIPS2_BASE_ADDR + 0x000A4000)
+#define MX51_FIRI_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000A8000)
+#define MX51_CSPI2_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000AC000)
+#define MX51_SDMA_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000B0000)
+#define MX51_SCC_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000B4000)
+#define MX51_ROMCP_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000B8000)
+#define MX51_RTIC_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000BC000)
+#define MX51_CSPI3_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000C0000)
+#define MX51_I2C2_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000C4000)
+#define MX51_I2C1_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000C8000)
+#define MX51_SSI1_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000CC000)
+#define MX51_AUDMUX_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000D0000)
+#define MX51_M4IF_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000D8000)
+#define MX51_ESDCTL_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000D9000)
+#define MX51_WEIM_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000DA000)
+#define MX51_NFC_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000DB000)
+#define MX51_EMI_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000DBF00)
+#define MX51_MIPI_HSC_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000DC000)
+#define MX51_ATA_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000E0000)
+#define MX51_SIM_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000E4000)
+#define MX51_SSI3BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000E8000)
+#define MX51_MXC_FEC_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000EC000)
+#define MX51_TVE_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000F0000)
+#define MX51_VPU_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000F4000)
+#define MX51_SAHARA_BASE_ADDR	(MX51_AIPS2_BASE_ADDR + 0x000F8000)
+
+/*
+ * Memory regions and CS
+ */
+#define MX51_GPU_CTRL_BASE_ADDR		0x30000000
+#define MX51_IPU_CTRL_BASE_ADDR		0x40000000
+#define MX51_CSD0_BASE_ADDR		0x90000000
+#define MX51_CSD1_BASE_ADDR		0xA0000000
+#define MX51_CS0_BASE_ADDR		0xB0000000
+#define MX51_CS1_BASE_ADDR		0xB8000000
+#define MX51_CS2_BASE_ADDR		0xC0000000
+#define MX51_CS3_BASE_ADDR		0xC8000000
+#define MX51_CS4_BASE_ADDR		0xCC000000
+#define MX51_CS5_BASE_ADDR		0xCE000000
+
+/* Does given address belongs to the specified memory region? */
+#define ADDRESS_IN_REGION(addr, start, size)			\
+	(((addr) >= (start)) && ((addr) < (start)+(size)))
+
+/* Does given address belongs to the specified named `module'? */
+#define MX51_IS_MODULE(addr, module)			       \
+	ADDRESS_IN_REGION(addr, MX51_ ## module ## _BASE_ADDR, \
+				MX51_ ## module ## _SIZE)
+/*
+ * 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 MX51_IO_ADDRESS(x)					\
+	(void __iomem *)					\
+	(MX51_IS_MODULE(x, IRAM) ? MX51_IRAM_IO_ADDRESS(x) :	\
+	MX51_IS_MODULE(x, TZIC) ? MX51_TZIC_IO_ADDRESS(x) :	\
+	MX51_IS_MODULE(x, DEBUG) ? MX51_DEBUG_IO_ADDRESS(x) :	\
+	MX51_IS_MODULE(x, SPBA0) ? MX51_SPBA0_IO_ADDRESS(x) :	\
+	MX51_IS_MODULE(x, AIPS1) ? MX51_AIPS1_IO_ADDRESS(x) :	\
+	MX51_IS_MODULE(x, AIPS2) ? MX51_AIPS2_IO_ADDRESS(x) :	\
+	MX51_IS_MODULE(x, NFC_AXI) ? MX51_NFC_AXI_IO_ADDRESS(x) : \
+	0xDEADBEEF)
+
+/*
+ * define the address mapping macros: in physical address order
+ */
+#define MX51_IRAM_IO_ADDRESS(x)  \
+	(((x) - MX51_IRAM_BASE_ADDR) + MX51_IRAM_BASE_ADDR_VIRT)
+
+#define MX51_TZIC_IO_ADDRESS(x)  \
+	(((x) - MX51_TZIC_BASE_ADDR) + MX51_TZIC_BASE_ADDR_VIRT)
+
+#define MX51_DEBUG_IO_ADDRESS(x)  \
+	(((x) - MX51_DEBUG_BASE_ADDR) + MX51_DEBUG_BASE_ADDR_VIRT)
+
+#define MX51_SPBA0_IO_ADDRESS(x)  \
+	(((x) - MX51_SPBA0_BASE_ADDR) + MX51_SPBA0_BASE_ADDR_VIRT)
+
+#define MX51_AIPS1_IO_ADDRESS(x)  \
+	(((x) - MX51_AIPS1_BASE_ADDR) + MX51_AIPS1_BASE_ADDR_VIRT)
+
+#define MX51_AIPS2_IO_ADDRESS(x)  \
+	(((x) - MX51_AIPS2_BASE_ADDR) + MX51_AIPS2_BASE_ADDR_VIRT)
+
+#define MX51_NFC_AXI_IO_ADDRESS(x) \
+	(((x) - MX51_NFC_AXI_BASE_ADDR) + MX51_NFC_AXI_BASE_ADDR_VIRT)
+
+#define MX51_IS_MEM_DEVICE_NONSHARED(x)		0
+
+/*
+ * DMA request assignments
+ */
+#define MX51_DMA_REQ_SSI3_TX1	47
+#define MX51_DMA_REQ_SSI3_RX1	46
+#define MX51_DMA_REQ_SPDIF	45
+#define MX51_DMA_REQ_UART3_TX	44
+#define MX51_DMA_REQ_UART3_RX	43
+#define MX51_DMA_REQ_SLIM_B_TX	42
+#define MX51_DMA_REQ_SDHC4	41
+#define MX51_DMA_REQ_SDHC3	40
+#define MX51_DMA_REQ_CSPI_TX	39
+#define MX51_DMA_REQ_CSPI_RX	38
+#define MX51_DMA_REQ_SSI3_TX2	37
+#define MX51_DMA_REQ_IPU	36
+#define MX51_DMA_REQ_SSI3_RX2	35
+#define MX51_DMA_REQ_EPIT2	34
+#define MX51_DMA_REQ_CTI2_1	33
+#define MX51_DMA_REQ_EMI_WR	32
+#define MX51_DMA_REQ_CTI2_0	31
+#define MX51_DMA_REQ_EMI_RD	30
+#define MX51_DMA_REQ_SSI1_TX1	29
+#define MX51_DMA_REQ_SSI1_RX1	28
+#define MX51_DMA_REQ_SSI1_TX2	27
+#define MX51_DMA_REQ_SSI1_RX2	26
+#define MX51_DMA_REQ_SSI2_TX1	25
+#define MX51_DMA_REQ_SSI2_RX1	24
+#define MX51_DMA_REQ_SSI2_TX2	23
+#define MX51_DMA_REQ_SSI2_RX2	22
+#define MX51_DMA_REQ_SDHC2	21
+#define MX51_DMA_REQ_SDHC1	20
+#define MX51_DMA_REQ_UART1_TX	19
+#define MX51_DMA_REQ_UART1_RX	18
+#define MX51_DMA_REQ_UART2_TX	17
+#define MX51_DMA_REQ_UART2_RX	16
+#define MX51_DMA_REQ_GPU	15
+#define MX51_DMA_REQ_EXTREQ1	14
+#define MX51_DMA_REQ_FIRI_TX	13
+#define MX51_DMA_REQ_FIRI_RX	12
+#define MX51_DMA_REQ_HS_I2C_RX	11
+#define MX51_DMA_REQ_HS_I2C_TX	10
+#define MX51_DMA_REQ_CSPI2_TX	9
+#define MX51_DMA_REQ_CSPI2_RX	8
+#define MX51_DMA_REQ_CSPI1_TX	7
+#define MX51_DMA_REQ_CSPI1_RX	6
+#define MX51_DMA_REQ_SLIM_B	5
+#define MX51_DMA_REQ_ATA_TX_END	4
+#define MX51_DMA_REQ_ATA_TX	3
+#define MX51_DMA_REQ_ATA_RX	2
+#define MX51_DMA_REQ_GPC	1
+#define MX51_DMA_REQ_VPU	0
+
+/*
+ * Interrupt numbers
+ */
+#define MX51_MXC_INT_BASE	0
+#define MX51_MXC_INT_RESV0	0
+#define MX51_MXC_INT_MMC_SDHC1	1
+#define MX51_MXC_INT_MMC_SDHC2	2
+#define MX51_MXC_INT_MMC_SDHC3	3
+#define MX51_MXC_INT_MMC_SDHC4	4
+#define MX51_MXC_INT_RESV5	5
+#define MX51_MXC_INT_SDMA	6
+#define MX51_MXC_INT_IOMUX	7
+#define MX51_MXC_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_MXC_INT_GPU	12
+#define MX51_MXC_INT_RESV13	13
+#define MX51_MXC_INT_USB_H1	14
+#define MX51_MXC_INT_EMI	15
+#define MX51_MXC_INT_USB_H2	16
+#define MX51_MXC_INT_USB_H3	17
+#define MX51_MXC_INT_USB_OTG	18
+#define MX51_MXC_INT_SAHARA_H0	19
+#define MX51_MXC_INT_SAHARA_H1	20
+#define MX51_MXC_INT_SCC_SMN	21
+#define MX51_MXC_INT_SCC_STZ	22
+#define MX51_MXC_INT_SCC_SCM	23
+#define MX51_MXC_INT_SRTC_NTZ	24
+#define MX51_MXC_INT_SRTC_TZ	25
+#define MX51_MXC_INT_RTIC	26
+#define MX51_MXC_INT_CSU	27
+#define MX51_MXC_INT_SLIM_B	28
+#define MX51_MXC_INT_SSI1	29
+#define MX51_MXC_INT_SSI2	30
+#define MX51_MXC_INT_UART1	31
+#define MX51_MXC_INT_UART2	32
+#define MX51_MXC_INT_UART3	33
+#define MX51_MXC_INT_RESV34	34
+#define MX51_MXC_INT_RESV35	35
+#define MX51_MXC_INT_CSPI1	36
+#define MX51_MXC_INT_CSPI2	37
+#define MX51_MXC_INT_CSPI	38
+#define MX51_MXC_INT_GPT	39
+#define MX51_MXC_INT_EPIT1	40
+#define MX51_MXC_INT_EPIT2	41
+#define MX51_MXC_INT_GPIO1_INT7	42
+#define MX51_MXC_INT_GPIO1_INT6	43
+#define MX51_MXC_INT_GPIO1_INT5	44
+#define MX51_MXC_INT_GPIO1_INT4	45
+#define MX51_MXC_INT_GPIO1_INT3	46
+#define MX51_MXC_INT_GPIO1_INT2	47
+#define MX51_MXC_INT_GPIO1_INT1	48
+#define MX51_MXC_INT_GPIO1_INT0	49
+#define MX51_MXC_INT_GPIO1_LOW	50
+#define MX51_MXC_INT_GPIO1_HIGH	51
+#define MX51_MXC_INT_GPIO2_LOW	52
+#define MX51_MXC_INT_GPIO2_HIGH	53
+#define MX51_MXC_INT_GPIO3_LOW	54
+#define MX51_MXC_INT_GPIO3_HIGH	55
+#define MX51_MXC_INT_GPIO4_LOW	56
+#define MX51_MXC_INT_GPIO4_HIGH	57
+#define MX51_MXC_INT_WDOG1	58
+#define MX51_MXC_INT_WDOG2	59
+#define MX51_MXC_INT_KPP	60
+#define MX51_MXC_INT_PWM1	61
+#define MX51_MXC_INT_I2C1	62
+#define MX51_MXC_INT_I2C2	63
+#define MX51_MXC_INT_HS_I2C	64
+#define MX51_MXC_INT_RESV65	65
+#define MX51_MXC_INT_RESV66	66
+#define MX51_MXC_INT_SIM_IPB	67
+#define MX51_MXC_INT_SIM_DAT	68
+#define MX51_MXC_INT_IIM	69
+#define MX51_MXC_INT_ATA	70
+#define MX51_MXC_INT_CCM1	71
+#define MX51_MXC_INT_CCM2	72
+#define MX51_MXC_INT_GPC1	73
+#define MX51_MXC_INT_GPC2	74
+#define MX51_MXC_INT_SRC	75
+#define MX51_MXC_INT_NM		76
+#define MX51_MXC_INT_PMU	77
+#define MX51_MXC_INT_CTI_IRQ	78
+#define MX51_MXC_INT_CTI1_TG0	79
+#define MX51_MXC_INT_CTI1_TG1	80
+#define MX51_MXC_INT_MCG_ERR	81
+#define MX51_MXC_INT_MCG_TMR	82
+#define MX51_MXC_INT_MCG_FUNC	83
+#define MX51_MXC_INT_GPU2_IRQ	84
+#define MX51_MXC_INT_GPU2_BUSY	85
+#define MX51_MXC_INT_RESV86	86
+#define MX51_MXC_INT_FEC	87
+#define MX51_MXC_INT_OWIRE	88
+#define MX51_MXC_INT_CTI1_TG2	89
+#define MX51_MXC_INT_SJC	90
+#define MX51_MXC_INT_SPDIF	91
+#define MX51_MXC_INT_TVE	92
+#define MX51_MXC_INT_FIRI	93
+#define MX51_MXC_INT_PWM2	94
+#define MX51_MXC_INT_SLIM_EXP	95
+#define MX51_MXC_INT_SSI3	96
+#define MX51_MXC_INT_EMI_BOOT	97
+#define MX51_MXC_INT_CTI1_TG3	98
+#define MX51_MXC_INT_SMC_RX	99
+#define MX51_MXC_INT_VPU_IDLE	100
+#define MX51_MXC_INT_EMI_NFC	101
+#define MX51_MXC_INT_GPU_IDLE	102
+
+/* 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
+
+/* Mandatory defines used globally */
+
+#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
+
+extern unsigned int system_rev;
+
+static inline unsigned int mx51_revision(void)
+{
+	return system_rev;
+}
+#endif
+
+#endif	/*  __ASM_ARCH_MXC_MX51_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 5199053..a790bf2 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -30,6 +30,7 @@
 #define MXC_CPU_MX27		27
 #define MXC_CPU_MX31		31
 #define MXC_CPU_MX35		35
+#define MXC_CPU_MX51		51
 #define MXC_CPU_MXC91231	91231
 
 #ifndef __ASSEMBLY__
@@ -108,6 +109,18 @@
 # define cpu_is_mx35()		(0)
 #endif
 
+#ifdef CONFIG_ARCH_MX5
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX51
+# endif
+# define cpu_is_mx51()		(mxc_cpu_type == MXC_CPU_MX51)
+#else
+# define cpu_is_mx51()		(0)
+#endif
+
 #ifdef CONFIG_ARCH_MXC91231
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
@@ -121,9 +134,10 @@
 #endif
 
 #if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2)
-#define CSCR_U(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10)
-#define CSCR_L(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10 + 0x4)
-#define CSCR_A(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10 + 0x8)
+/* These are deprecated, use mx[23][157]_setup_weimcs instead. */
+#define CSCR_U(n) (IO_ADDRESS(WEIM_BASE_ADDR + n * 0x10))
+#define CSCR_L(n) (IO_ADDRESS(WEIM_BASE_ADDR + n * 0x10 + 0x4))
+#define CSCR_A(n) (IO_ADDRESS(WEIM_BASE_ADDR + n * 0x10 + 0x8))
 #endif
 
 #define cpu_is_mx3()	(cpu_is_mx31() || cpu_is_mx35() || cpu_is_mxc91231())
diff --git a/arch/arm/plat-mxc/include/mach/mxc91231.h b/arch/arm/plat-mxc/include/mach/mxc91231.h
index 81484d1..5182b98 100644
--- a/arch/arm/plat-mxc/include/mach/mxc91231.h
+++ b/arch/arm/plat-mxc/include/mach/mxc91231.h
@@ -184,60 +184,22 @@
 #define MXC91231_CS4_BASE_ADDR		0xB4000000
 #define MXC91231_CS5_BASE_ADDR		0xB6000000
 
-/* Is given address belongs to the specified memory region? */
-#define ADDRESS_IN_REGION(addr, start, size) \
-	(((addr) >= (start)) && ((addr) < (start)+(size)))
-
-/* Is given address belongs to the specified named `module'? */
-#define MXC91231_IS_MODULE(addr, module) \
-	ADDRESS_IN_REGION(addr, MXC91231_ ## module ## _BASE_ADDR, \
-	                        MXC91231_ ## module ## _SIZE)
 /*
  * 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
+ * it returns 0.
  */
 
-#define MXC91231_IO_ADDRESS(x) \
-	(void __iomem *) \
-	(MXC91231_IS_MODULE(x, L2CC) ? MXC91231_L2CC_IO_ADDRESS(x) : \
-	 MXC91231_IS_MODULE(x, AIPS1) ? MXC91231_AIPS1_IO_ADDRESS(x) : \
-	 MXC91231_IS_MODULE(x, AIPS2) ? MXC91231_AIPS2_IO_ADDRESS(x) : \
-	 MXC91231_IS_MODULE(x, SPBA0) ? MXC91231_SPBA0_IO_ADDRESS(x) : \
-	 MXC91231_IS_MODULE(x, SPBA1) ? MXC91231_SPBA1_IO_ADDRESS(x) : \
-	 MXC91231_IS_MODULE(x, ROMP) ? MXC91231_ROMP_IO_ADDRESS(x) : \
-	 MXC91231_IS_MODULE(x, AVIC) ? MXC91231_AVIC_IO_ADDRESS(x) : \
-	 MXC91231_IS_MODULE(x, X_MEMC) ? MXC91231_X_MEMC_IO_ADDRESS(x) : \
-	 0xDEADBEEF)
-
-
-/*
- * define the address mapping macros: in physical address order
- */
-#define MXC91231_L2CC_IO_ADDRESS(x)  \
-	(((x) - MXC91231_L2CC_BASE_ADDR) + MXC91231_L2CC_BASE_ADDR_VIRT)
-
-#define MXC91231_AIPS1_IO_ADDRESS(x)  \
-	(((x) - MXC91231_AIPS1_BASE_ADDR) + MXC91231_AIPS1_BASE_ADDR_VIRT)
-
-#define MXC91231_SPBA0_IO_ADDRESS(x)  \
-	(((x) - MXC91231_SPBA0_BASE_ADDR) + MXC91231_SPBA0_BASE_ADDR_VIRT)
-
-#define MXC91231_SPBA1_IO_ADDRESS(x)  \
-	(((x) - MXC91231_SPBA1_BASE_ADDR) + MXC91231_SPBA1_BASE_ADDR_VIRT)
-
-#define MXC91231_AIPS2_IO_ADDRESS(x)  \
-	(((x) - MXC91231_AIPS2_BASE_ADDR) + MXC91231_AIPS2_BASE_ADDR_VIRT)
-
-#define MXC91231_ROMP_IO_ADDRESS(x)  \
-	(((x) - MXC91231_ROMP_BASE_ADDR) + MXC91231_ROMP_BASE_ADDR_VIRT)
-
-#define MXC91231_AVIC_IO_ADDRESS(x)  \
-	(((x) - MXC91231_AVIC_BASE_ADDR) + MXC91231_AVIC_BASE_ADDR_VIRT)
-
-#define MXC91231_X_MEMC_IO_ADDRESS(x)  \
-	(((x) - MXC91231_X_MEMC_BASE_ADDR) + MXC91231_X_MEMC_BASE_ADDR_VIRT)
+#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))
 
 /*
  * 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 8f79623..4b9b836 100644
--- a/arch/arm/plat-mxc/include/mach/mxc_ehci.h
+++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
@@ -22,6 +22,10 @@
 #define MXC_EHCI_POWER_PINS_ENABLED	(1 << 5)
 #define MXC_EHCI_TTL_ENABLED		(1 << 6)
 
+#define MXC_EHCI_INTERNAL_PHY		(1 << 7)
+#define MXC_EHCI_IPPUE_DOWN		(1 << 8)
+#define MXC_EHCI_IPPUE_UP		(1 << 9)
+
 struct mxc_usbh_platform_data {
 	int (*init)(struct platform_device *pdev);
 	int (*exit)(struct platform_device *pdev);
diff --git a/arch/arm/plat-mxc/include/mach/ssi.h b/arch/arm/plat-mxc/include/mach/ssi.h
new file mode 100644
index 0000000..c34ded5
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/ssi.h
@@ -0,0 +1,18 @@
+#ifndef __MACH_SSI_H
+#define __MACH_SSI_H
+
+struct snd_ac97;
+
+extern unsigned char imx_ssi_fiq_start, imx_ssi_fiq_end;
+extern unsigned long imx_ssi_fiq_base, imx_ssi_fiq_tx_buffer, imx_ssi_fiq_rx_buffer;
+
+struct imx_ssi_platform_data {
+	unsigned int flags;
+#define IMX_SSI_DMA            (1 << 0)
+#define IMX_SSI_USE_AC97       (1 << 1)
+	void (*ac97_reset) (struct snd_ac97 *ac97);
+	void (*ac97_warm_reset)(struct snd_ac97 *ac97);
+};
+
+#endif /* __MACH_SSI_H */
+
diff --git a/arch/arm/plat-mxc/include/mach/timex.h b/arch/arm/plat-mxc/include/mach/timex.h
index 527a6c2..024416e 100644
--- a/arch/arm/plat-mxc/include/mach/timex.h
+++ b/arch/arm/plat-mxc/include/mach/timex.h
@@ -28,6 +28,8 @@
 #define CLOCK_TICK_RATE		16625000
 #elif defined CONFIG_ARCH_MX25
 #define CLOCK_TICK_RATE		16000000
+#elif defined CONFIG_ARCH_MX5
+#define CLOCK_TICK_RATE		8000000
 #elif defined CONFIG_ARCH_MXC91231
 #define CLOCK_TICK_RATE		13000000
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
index d49384c..52e476a 100644
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ b/arch/arm/plat-mxc/include/mach/uncompress.h
@@ -1,8 +1,6 @@
 /*
  *  arch/arm/plat-mxc/include/mach/uncompress.h
  *
- *
- *
  *  Copyright (C) 1999 ARM Limited
  *  Copyright (C) Shane Nay (shane@minirl.com)
  *
@@ -25,7 +23,6 @@
 
 #define __MXC_BOOT_UNCOMPRESS
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 
 static unsigned long uart_base;
diff --git a/arch/arm/plat-mxc/iomux-mx1-mx2.c b/arch/arm/plat-mxc/iomux-mx1-mx2.c
deleted file mode 100644
index a37163c..0000000
--- a/arch/arm/plat-mxc/iomux-mx1-mx2.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- *  arch/arm/mach-mxc/generic.c
- *
- *  author: Sascha Hauer
- *  Created: april 20th, 2004
- *  Copyright: Synertronixx GmbH
- *
- *  Common code for i.MX machines
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/gpio.h>
-
-#include <mach/hardware.h>
-#include <asm/mach/map.h>
-#include <mach/iomux.h>
-
-void mxc_gpio_mode(int gpio_mode)
-{
-	unsigned int pin = gpio_mode & GPIO_PIN_MASK;
-	unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
-	unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
-	unsigned int tmp;
-
-	/* Pullup enable */
-	tmp = __raw_readl(VA_GPIO_BASE + MXC_PUEN(port));
-	if (gpio_mode & GPIO_PUEN)
-		tmp |= (1 << pin);
-	else
-		tmp &= ~(1 << pin);
-	__raw_writel(tmp, VA_GPIO_BASE + MXC_PUEN(port));
-
-	/* Data direction */
-	tmp = __raw_readl(VA_GPIO_BASE + MXC_DDIR(port));
-	if (gpio_mode & GPIO_OUT)
-		tmp |= 1 << pin;
-	else
-		tmp &= ~(1 << pin);
-	__raw_writel(tmp, VA_GPIO_BASE + MXC_DDIR(port));
-
-	/* Primary / alternate function */
-	tmp = __raw_readl(VA_GPIO_BASE + MXC_GPR(port));
-	if (gpio_mode & GPIO_AF)
-		tmp |= (1 << pin);
-	else
-		tmp &= ~(1 << pin);
-	__raw_writel(tmp, VA_GPIO_BASE + MXC_GPR(port));
-
-	/* use as gpio? */
-	tmp = __raw_readl(VA_GPIO_BASE + MXC_GIUS(port));
-	if (gpio_mode & (GPIO_PF | GPIO_AF))
-		tmp &= ~(1 << pin);
-	else
-		tmp |= (1 << pin);
-	__raw_writel(tmp, VA_GPIO_BASE + MXC_GIUS(port));
-
-	if (pin < 16) {
-		tmp = __raw_readl(VA_GPIO_BASE + MXC_OCR1(port));
-		tmp &= ~(3 << (pin * 2));
-		tmp |= (ocr << (pin * 2));
-		__raw_writel(tmp, VA_GPIO_BASE + MXC_OCR1(port));
-
-		tmp = __raw_readl(VA_GPIO_BASE + MXC_ICONFA1(port));
-		tmp &= ~(3 << (pin * 2));
-		tmp |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << (pin * 2);
-		__raw_writel(tmp, VA_GPIO_BASE + MXC_ICONFA1(port));
-
-		tmp = __raw_readl(VA_GPIO_BASE + MXC_ICONFB1(port));
-		tmp &= ~(3 << (pin * 2));
-		tmp |= ((gpio_mode >> GPIO_BOUT_SHIFT) & 3) << (pin * 2);
-		__raw_writel(tmp, VA_GPIO_BASE + MXC_ICONFB1(port));
-	} else {
-		pin -= 16;
-
-		tmp = __raw_readl(VA_GPIO_BASE + MXC_OCR2(port));
-		tmp &= ~(3 << (pin * 2));
-		tmp |= (ocr << (pin * 2));
-		__raw_writel(tmp, VA_GPIO_BASE + MXC_OCR2(port));
-
-		tmp = __raw_readl(VA_GPIO_BASE + MXC_ICONFA2(port));
-		tmp &= ~(3 << (pin * 2));
-		tmp |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << (pin * 2);
-		__raw_writel(tmp, VA_GPIO_BASE + MXC_ICONFA2(port));
-
-		tmp = __raw_readl(VA_GPIO_BASE + MXC_ICONFB2(port));
-		tmp &= ~(3 << (pin * 2));
-		tmp |= ((gpio_mode >> GPIO_BOUT_SHIFT) & 3) << (pin * 2);
-		__raw_writel(tmp, VA_GPIO_BASE + MXC_ICONFB2(port));
-	}
-}
-EXPORT_SYMBOL(mxc_gpio_mode);
-
-int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
-		const char *label)
-{
-	const int *p = pin_list;
-	int i;
-	unsigned gpio;
-	unsigned mode;
-	int ret = -EINVAL;
-
-	for (i = 0; i < count; i++) {
-		gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
-		mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
-
-		if (gpio >= (GPIO_PORT_MAX + 1) * 32)
-			goto setup_error;
-
-		ret = gpio_request(gpio, label);
-		if (ret)
-			goto setup_error;
-
-		mxc_gpio_mode(gpio | mode);
-
-		p++;
-	}
-	return 0;
-
-setup_error:
-	mxc_gpio_release_multiple_pins(pin_list, i);
-	return ret;
-}
-EXPORT_SYMBOL(mxc_gpio_setup_multiple_pins);
-
-void mxc_gpio_release_multiple_pins(const int *pin_list, int count)
-{
-	const int *p = pin_list;
-	int i;
-
-	for (i = 0; i < count; i++) {
-		unsigned gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
-		gpio_free(gpio);
-		p++;
-	}
-
-}
-EXPORT_SYMBOL(mxc_gpio_release_multiple_pins);
-
diff --git a/arch/arm/plat-mxc/iomux-v1.c b/arch/arm/plat-mxc/iomux-v1.c
new file mode 100644
index 0000000..960a02c
--- /dev/null
+++ b/arch/arm/plat-mxc/iomux-v1.c
@@ -0,0 +1,238 @@
+/*
+ * arch/arm/plat-mxc/iomux-v1.c
+ *
+ * Copyright (C) 2004 Sascha Hauer, Synertronixx GmbH
+ * Copyright (C) 2009 Uwe Kleine-Koenig, Pengutronix
+ *
+ * Common code for i.MX1, i.MX21 and i.MX27
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have 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/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <asm/mach/map.h>
+#include <mach/iomux-v1.h>
+
+static void __iomem *imx_iomuxv1_baseaddr;
+static unsigned imx_iomuxv1_numports;
+
+static inline unsigned long imx_iomuxv1_readl(unsigned offset)
+{
+	return __raw_readl(imx_iomuxv1_baseaddr + offset);
+}
+
+static inline void imx_iomuxv1_writel(unsigned long val, unsigned offset)
+{
+	__raw_writel(val, imx_iomuxv1_baseaddr + offset);
+}
+
+static inline void imx_iomuxv1_rmwl(unsigned offset,
+		unsigned long mask, unsigned long value)
+{
+	unsigned long reg = imx_iomuxv1_readl(offset);
+
+	reg &= ~mask;
+	reg |= value;
+
+	imx_iomuxv1_writel(reg, offset);
+}
+
+static inline void imx_iomuxv1_set_puen(
+		unsigned int port, unsigned int pin, int on)
+{
+	unsigned long mask = 1 << pin;
+
+	imx_iomuxv1_rmwl(MXC_PUEN(port), mask, on ? mask : 0);
+}
+
+static inline void imx_iomuxv1_set_ddir(
+		unsigned int port, unsigned int pin, int out)
+{
+	unsigned long mask = 1 << pin;
+
+	imx_iomuxv1_rmwl(MXC_DDIR(port), mask, out ? mask : 0);
+}
+
+static inline void imx_iomuxv1_set_gpr(
+		unsigned int port, unsigned int pin, int af)
+{
+	unsigned long mask = 1 << pin;
+
+	imx_iomuxv1_rmwl(MXC_GPR(port), mask, af ? mask : 0);
+}
+
+static inline void imx_iomuxv1_set_gius(
+		unsigned int port, unsigned int pin, int inuse)
+{
+	unsigned long mask = 1 << pin;
+
+	imx_iomuxv1_rmwl(MXC_GIUS(port), mask, inuse ? mask : 0);
+}
+
+static inline void imx_iomuxv1_set_ocr(
+		unsigned int port, unsigned int pin, unsigned int ocr)
+{
+	unsigned long shift = (pin & 0xf) << 1;
+	unsigned long mask = 3 << shift;
+	unsigned long value = ocr << shift;
+	unsigned long offset = pin < 16 ? MXC_OCR1(port) : MXC_OCR2(port);
+
+	imx_iomuxv1_rmwl(offset, mask, value);
+}
+
+static inline void imx_iomuxv1_set_iconfa(
+		unsigned int port, unsigned int pin, unsigned int aout)
+{
+	unsigned long shift = (pin & 0xf) << 1;
+	unsigned long mask = 3 << shift;
+	unsigned long value = aout << shift;
+	unsigned long offset = pin < 16 ? MXC_ICONFA1(port) : MXC_ICONFA2(port);
+
+	imx_iomuxv1_rmwl(offset, mask, value);
+}
+
+static inline void imx_iomuxv1_set_iconfb(
+		unsigned int port, unsigned int pin, unsigned int bout)
+{
+	unsigned long shift = (pin & 0xf) << 1;
+	unsigned long mask = 3 << shift;
+	unsigned long value = bout << shift;
+	unsigned long offset = pin < 16 ? MXC_ICONFB1(port) : MXC_ICONFB2(port);
+
+	imx_iomuxv1_rmwl(offset, mask, value);
+}
+
+int mxc_gpio_mode(int gpio_mode)
+{
+	unsigned int pin = gpio_mode & GPIO_PIN_MASK;
+	unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+	unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
+	unsigned int aout = (gpio_mode >> GPIO_AOUT_SHIFT) & 3;
+	unsigned int bout = (gpio_mode >> GPIO_BOUT_SHIFT) & 3;
+
+	if (port >= imx_iomuxv1_numports)
+		return -EINVAL;
+
+	/* Pullup enable */
+	imx_iomuxv1_set_puen(port, pin, gpio_mode & GPIO_PUEN);
+
+	/* Data direction */
+	imx_iomuxv1_set_ddir(port, pin, gpio_mode & GPIO_OUT);
+
+	/* Primary / alternate function */
+	imx_iomuxv1_set_gpr(port, pin, gpio_mode & GPIO_AF);
+
+	/* use as gpio? */
+	imx_iomuxv1_set_gius(port, pin, !(gpio_mode & (GPIO_PF | GPIO_AF)));
+
+	imx_iomuxv1_set_ocr(port, pin, ocr);
+
+	imx_iomuxv1_set_iconfa(port, pin, aout);
+
+	imx_iomuxv1_set_iconfb(port, pin, bout);
+
+	return 0;
+}
+EXPORT_SYMBOL(mxc_gpio_mode);
+
+static int imx_iomuxv1_setup_multiple(const int *list, unsigned count)
+{
+	size_t i;
+	int ret;
+
+	for (i = 0; i < count; ++i) {
+		ret = mxc_gpio_mode(list[i]);
+
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+		const char *label)
+{
+	size_t i;
+	int ret;
+
+	for (i = 0; i < count; ++i) {
+		unsigned gpio = pin_list[i] & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+
+		ret = gpio_request(gpio, label);
+		if (ret)
+			goto err_gpio_request;
+	}
+
+	ret = imx_iomuxv1_setup_multiple(pin_list, count);
+	if (ret)
+		goto err_setup;
+
+	return 0;
+
+err_setup:
+	BUG_ON(i != count);
+
+err_gpio_request:
+	mxc_gpio_release_multiple_pins(pin_list, i);
+
+	return ret;
+}
+EXPORT_SYMBOL(mxc_gpio_setup_multiple_pins);
+
+void mxc_gpio_release_multiple_pins(const int *pin_list, int count)
+{
+	size_t i;
+
+	for (i = 0; i < count; ++i) {
+		unsigned gpio = pin_list[i] & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+
+		gpio_free(gpio);
+	}
+}
+EXPORT_SYMBOL(mxc_gpio_release_multiple_pins);
+
+static int imx_iomuxv1_init(void)
+{
+#ifdef CONFIG_ARCH_MX1
+	if (cpu_is_mx1()) {
+		imx_iomuxv1_baseaddr = MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR);
+		imx_iomuxv1_numports = MX1_NUM_GPIO_PORT;
+	} else
+#endif
+#ifdef CONFIG_MACH_MX21
+	if (cpu_is_mx21()) {
+		imx_iomuxv1_baseaddr = MX21_IO_ADDRESS(MX21_GPIO_BASE_ADDR);
+		imx_iomuxv1_numports = MX21_NUM_GPIO_PORT;
+	} else
+#endif
+#ifdef CONFIG_MACH_MX27
+	if (cpu_is_mx27()) {
+		imx_iomuxv1_baseaddr = MX27_IO_ADDRESS(MX27_GPIO_BASE_ADDR);
+		imx_iomuxv1_numports = MX27_NUM_GPIO_PORT;
+	} else
+#endif
+		return -ENODEV;
+
+	return 0;
+}
+pure_initcall(imx_iomuxv1_init);
diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c
index 844567ee..c1ce51a 100644
--- a/arch/arm/plat-mxc/time.c
+++ b/arch/arm/plat-mxc/time.c
@@ -30,9 +30,15 @@
 #include <asm/mach/time.h>
 #include <mach/common.h>
 
+/*
+ * There are 2 versions of the timer hardware on Freescale MXC hardware.
+ * Version 1: MX1/MXL, MX21, MX27.
+ * Version 2: MX25, MX31, MX35, MX37, MX51
+ */
+
 /* defines common for all i.MX */
 #define MXC_TCTL		0x00
-#define MXC_TCTL_TEN		(1 << 0)
+#define MXC_TCTL_TEN		(1 << 0) /* Enable module */
 #define MXC_TPRER		0x04
 
 /* MX1, MX21, MX27 */
@@ -47,8 +53,8 @@
 #define MX2_TSTAT_CAPT		(1 << 1)
 #define MX2_TSTAT_COMP		(1 << 0)
 
-/* MX31, MX35, MX25, MXC91231 */
-#define MX3_TCTL_WAITEN		(1 << 3)
+/* MX31, MX35, MX25, MXC91231, MX5 */
+#define MX3_TCTL_WAITEN		(1 << 3) /* Wait enable mode */
 #define MX3_TCTL_CLK_IPG	(1 << 6)
 #define MX3_TCTL_FRR		(1 << 9)
 #define MX3_IR			0x0c
@@ -57,6 +63,9 @@
 #define MX3_TCN			0x24
 #define MX3_TCMP		0x10
 
+#define timer_is_v1()	(cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
+#define timer_is_v2()	(!timer_is_v1())
+
 static struct clock_event_device clockevent_mxc;
 static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
 
@@ -66,7 +75,7 @@
 {
 	unsigned int tmp;
 
-	if (cpu_is_mx3() || cpu_is_mx25())
+	if (timer_is_v2())
 		__raw_writel(0, timer_base + MX3_IR);
 	else {
 		tmp = __raw_readl(timer_base + MXC_TCTL);
@@ -76,7 +85,7 @@
 
 static inline void gpt_irq_enable(void)
 {
-	if (cpu_is_mx3() || cpu_is_mx25())
+	if (timer_is_v2())
 		__raw_writel(1<<0, timer_base + MX3_IR);
 	else {
 		__raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
@@ -86,11 +95,13 @@
 
 static void gpt_irq_acknowledge(void)
 {
-	if (cpu_is_mx1())
-		__raw_writel(0, timer_base + MX1_2_TSTAT);
-	if (cpu_is_mx2())
-		__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, timer_base + MX1_2_TSTAT);
-	if (cpu_is_mx3() || cpu_is_mx25())
+	if (timer_is_v1()) {
+		if (cpu_is_mx1())
+			__raw_writel(0, timer_base + MX1_2_TSTAT);
+		else
+			__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP,
+				timer_base + MX1_2_TSTAT);
+	} else if (timer_is_v2())
 		__raw_writel(MX3_TSTAT_OF1, timer_base + MX3_TSTAT);
 }
 
@@ -117,7 +128,7 @@
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
-	if (cpu_is_mx3() || cpu_is_mx25())
+	if (timer_is_v2())
 		clocksource_mxc.read = mx3_get_cycles;
 
 	clocksource_mxc.mult = clocksource_hz2mult(c,
@@ -180,7 +191,7 @@
 
 	if (mode != clockevent_mode) {
 		/* Set event time into far-far future */
-		if (cpu_is_mx3() || cpu_is_mx25())
+		if (timer_is_v2())
 			__raw_writel(__raw_readl(timer_base + MX3_TCN) - 3,
 					timer_base + MX3_TCMP);
 		else
@@ -233,7 +244,7 @@
 	struct clock_event_device *evt = &clockevent_mxc;
 	uint32_t tstat;
 
-	if (cpu_is_mx3() || cpu_is_mx25())
+	if (timer_is_v2())
 		tstat = __raw_readl(timer_base + MX3_TSTAT);
 	else
 		tstat = __raw_readl(timer_base + MX1_2_TSTAT);
@@ -264,7 +275,7 @@
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
-	if (cpu_is_mx3() || cpu_is_mx25())
+	if (timer_is_v2())
 		clockevent_mxc.set_next_event = mx3_set_next_event;
 
 	clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
@@ -296,7 +307,7 @@
 	__raw_writel(0, timer_base + MXC_TCTL);
 	__raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
 
-	if (cpu_is_mx3() || cpu_is_mx25())
+	if (timer_is_v2())
 		tctl_val = MX3_TCTL_CLK_IPG | MX3_TCTL_FRR | MX3_TCTL_WAITEN | MXC_TCTL_TEN;
 	else
 		tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
new file mode 100644
index 0000000..afa6709
--- /dev/null
+++ b/arch/arm/plat-mxc/tzic.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2004-2009 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
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <mach/hardware.h>
+
+/*
+ *****************************************
+ * TZIC Registers                        *
+ *****************************************
+ */
+
+#define TZIC_INTCNTL	0x0000	/* Control register */
+#define TZIC_INTTYPE	0x0004	/* Controller Type register */
+#define TZIC_IMPID	0x0008	/* Distributor Implementer Identification */
+#define TZIC_PRIOMASK	0x000C	/* Priority Mask Reg */
+#define TZIC_SYNCCTRL	0x0010	/* Synchronizer Control register */
+#define TZIC_DSMINT	0x0014	/* DSM interrupt Holdoffregister */
+#define TZIC_INTSEC0(i)	(0x0080 + ((i) << 2)) /* Interrupt Security Reg 0 */
+#define TZIC_ENSET0(i)	(0x0100 + ((i) << 2)) /* Enable Set Reg 0 */
+#define TZIC_ENCLEAR0(i) (0x0180 + ((i) << 2)) /* Enable Clear Reg 0 */
+#define TZIC_SRCSET0	0x0200	/* Source Set Register 0 */
+#define TZIC_SRCCLAR0	0x0280	/* Source Clear Register 0 */
+#define TZIC_PRIORITY0	0x0400	/* Priority Register 0 */
+#define TZIC_PND0	0x0D00	/* Pending Register 0 */
+#define TZIC_HIPND0	0x0D80	/* High Priority Pending Register */
+#define TZIC_WAKEUP0(i)	(0x0E00 + ((i) << 2))	/* Wakeup Config Register */
+#define TZIC_SWINT	0x0F00	/* Software Interrupt Rigger Register */
+#define TZIC_ID0	0x0FD0	/* Indentification Register 0 */
+
+void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
+
+/**
+ * tzic_mask_irq() - Disable interrupt number "irq" in the TZIC
+ *
+ * @param  irq          interrupt source number
+ */
+static void tzic_mask_irq(unsigned int irq)
+{
+	int index, off;
+
+	index = irq >> 5;
+	off = irq & 0x1F;
+	__raw_writel(1 << off, tzic_base + TZIC_ENCLEAR0(index));
+}
+
+/**
+ * tzic_unmask_irq() - Enable interrupt number "irq" in the TZIC
+ *
+ * @param  irq          interrupt source number
+ */
+static void tzic_unmask_irq(unsigned int irq)
+{
+	int index, off;
+
+	index = irq >> 5;
+	off = irq & 0x1F;
+	__raw_writel(1 << off, tzic_base + TZIC_ENSET0(index));
+}
+
+static unsigned int wakeup_intr[4];
+
+/**
+ * tzic_set_wake_irq() - Set interrupt number "irq" in the TZIC as a wake-up source.
+ *
+ * @param  irq          interrupt source number
+ * @param  enable       enable as wake-up if equal to non-zero
+ * 			disble as wake-up if equal to zero
+ *
+ * @return       This function returns 0 on success.
+ */
+static int tzic_set_wake_irq(unsigned int irq, unsigned int enable)
+{
+	unsigned int index, off;
+
+	index = irq >> 5;
+	off = irq & 0x1F;
+
+	if (index > 3)
+		return -EINVAL;
+
+	if (enable)
+		wakeup_intr[index] |= (1 << off);
+	else
+		wakeup_intr[index] &= ~(1 << off);
+
+	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,
+};
+
+/*
+ * This function initializes the TZIC hardware and disables all the
+ * interrupts. It registers the interrupt enable and disable functions
+ * to the kernel for each interrupt source.
+ */
+void __init tzic_init_irq(void __iomem *irqbase)
+{
+	int i;
+
+	tzic_base = irqbase;
+	/* put the TZIC into the reset value with
+	 * all interrupts disabled
+	 */
+	i = __raw_readl(tzic_base + TZIC_INTCNTL);
+
+	__raw_writel(0x80010001, tzic_base + TZIC_INTCNTL);
+	__raw_writel(0x1f, tzic_base + TZIC_PRIOMASK);
+	__raw_writel(0x02, tzic_base + TZIC_SYNCCTRL);
+
+	for (i = 0; i < 4; i++)
+		__raw_writel(0xFFFFFFFF, tzic_base + TZIC_INTSEC0(i));
+
+	/* disable all interrupts */
+	for (i = 0; i < 4; i++)
+		__raw_writel(0xFFFFFFFF, tzic_base + TZIC_ENCLEAR0(i));
+
+	/* all IRQ no FIQ Warning :: No selection */
+
+	for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
+		set_irq_chip(i, &mxc_tzic_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	pr_info("TrustZone Interrupt Controller (TZIC) initialized\n");
+}
+
+/**
+ * tzic_enable_wake() - enable wakeup interrupt
+ *
+ * @param is_idle		1 if called in idle loop (ENSET0 register);
+ *				0 to be used when called from low power entry
+ * @return			0 if successful; non-zero otherwise
+ */
+int tzic_enable_wake(int is_idle)
+{
+	unsigned int i, v;
+
+	__raw_writel(1, tzic_base + TZIC_DSMINT);
+	if (unlikely(__raw_readl(tzic_base + TZIC_DSMINT) == 0))
+		return -EAGAIN;
+
+	for (i = 0; i < 4; i++) {
+		v = is_idle ? __raw_readl(TZIC_ENSET0(i)) : wakeup_intr[i];
+		__raw_writel(v, TZIC_WAKEUP0(i));
+	}
+
+	return 0;
+}
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c
index 62f18ad..fa7cb3a 100644
--- a/arch/arm/plat-nomadik/timer.c
+++ b/arch/arm/plat-nomadik/timer.c
@@ -49,24 +49,17 @@
 static void nmdk_clkevt_mode(enum clock_event_mode mode,
 			     struct clock_event_device *dev)
 {
-	unsigned long flags;
-
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		/* enable interrupts -- and count current value? */
-		raw_local_irq_save(flags);
+		/* count current value? */
 		writel(readl(mtu_base + MTU_IMSC) | 1, mtu_base + MTU_IMSC);
-		raw_local_irq_restore(flags);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
 		BUG(); /* Not supported, yet */
 		/* FALLTHROUGH */
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_UNUSED:
-		/* disable irq */
-		raw_local_irq_save(flags);
 		writel(readl(mtu_base + MTU_IMSC) & ~1, mtu_base + MTU_IMSC);
-		raw_local_irq_restore(flags);
 		break;
 	case CLOCK_EVT_MODE_RESUME:
 		break;
diff --git a/arch/arm/plat-s3c/Kconfig b/arch/arm/plat-s3c/Kconfig
deleted file mode 100644
index 9e9d028..0000000
--- a/arch/arm/plat-s3c/Kconfig
+++ /dev/null
@@ -1,215 +0,0 @@
-# Copyright 2007 Simtec Electronics
-#
-# Licensed under GPLv2
-
-config PLAT_S3C
-	bool
-	depends on ARCH_S3C2410 || ARCH_S3C24A0 || ARCH_S3C64XX
-	default y
-	select NO_IOPORT
-	help
-	  Base platform code for any Samsung S3C device
-
-# low-level serial option nodes
-
-if PLAT_S3C
-
-config CPU_LLSERIAL_S3C2410_ONLY
-	bool
-	default y if CPU_LLSERIAL_S3C2410 && !CPU_LLSERIAL_S3C2440
-
-config CPU_LLSERIAL_S3C2440_ONLY
-	bool
-	default y if CPU_LLSERIAL_S3C2440 && !CPU_LLSERIAL_S3C2410
-
-config CPU_LLSERIAL_S3C2410
-	bool
-	help
-	  Selected if there is an S3C2410 (or register compatible) serial
-	  low-level implementation needed
-
-config CPU_LLSERIAL_S3C2440
-	bool
-	help
-	  Selected if there is an S3C2440 (or register compatible) serial
-	  low-level implementation needed
-
-# boot configurations
-
-comment "Boot options"
-
-config S3C_BOOT_WATCHDOG
-	bool "S3C Initialisation watchdog"
-	depends on S3C2410_WATCHDOG
-	help
-	  Say y to enable the watchdog during the kernel decompression
-	  stage. If the kernel fails to uncompress, then the watchdog
-	  will trigger a reset and the system should restart.
-
-config S3C_BOOT_ERROR_RESET
-	bool "S3C Reboot on decompression error"
-	help
-	  Say y here to use the watchdog to reset the system if the
-	  kernel decompressor detects an error during decompression.
-
-config S3C_BOOT_UART_FORCE_FIFO
-       bool "Force UART FIFO on during boot process"
-       default y
-       help
-         Say Y here to force the UART FIFOs on during the kernel
-	 uncompressor
-
-comment "Power management"
-
-config S3C2410_PM_DEBUG
-	bool "S3C2410 PM Suspend debug"
-	depends on PM
-	help
-	  Say Y here if you want verbose debugging from the PM Suspend and
-	  Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
-	  for more information.
-
-config S3C_PM_DEBUG_LED_SMDK
-       bool "SMDK LED suspend/resume debugging"
-       depends on PM && (MACH_SMDK6410)
-       help
-         Say Y here to enable the use of the SMDK LEDs on the baseboard
-	 for debugging of the state of the suspend and resume process.
-
-	 Note, this currently only works for S3C64XX based SMDK boards.
-
-config S3C2410_PM_CHECK
-	bool "S3C2410 PM Suspend Memory CRC"
-	depends on PM && CRC32
-	help
- 	  Enable the PM code's memory area checksum over sleep. This option
-	  will generate CRCs of all blocks of memory, and store them before
-	  going to sleep. The blocks are then checked on resume for any
-	  errors.
-
-	  Note, this can take several seconds depending on memory size
-	  and CPU speed.
-
-	  See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
-
-config S3C2410_PM_CHECK_CHUNKSIZE
-	int "S3C2410 PM Suspend CRC Chunksize (KiB)"
-	depends on PM && S3C2410_PM_CHECK
-	default 64
-	help
-	  Set the chunksize in Kilobytes of the CRC for checking memory
-	  corruption over suspend and resume. A smaller value will mean that
-	  the CRC data block will take more memory, but wil identify any
-	  faults with better precision.
-
-	  See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
-
-config S3C_LOWLEVEL_UART_PORT
-	int "S3C UART to use for low-level messages"
-	default 0
-	help
-	  Choice of which UART port to use for the low-level messages,
-	  such as the `Uncompressing...` at start time. The value of
-	  this configuration should be between zero and two. The port
-	  must have been initialised by the boot-loader before use.
-
-# options for gpiolib support
-
-config S3C_GPIO_SPACE
-	int "Space between gpio banks"
-	default 0
-	help
-	  Add a number of spare GPIO entries between each bank for debugging
-	  purposes. This allows any problems where an counter overflows from
-	  one bank to another to be caught, at the expense of using a little
-	  more memory.
-
-config S3C_GPIO_TRACK
-	bool
-	help
-	  Internal configuration option to enable the s3c specific gpio
-	  chip tracking if the platform requires it.
-
-config S3C_GPIO_PULL_UPDOWN
-	bool
-	help
-	  Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_PULL_DOWN
-	bool
-	help
-	  Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_PULL_UP
-	bool
-	help
-	  Internal configuration to enable the correct GPIO pull helper
-
-config S3C_GPIO_CFG_S3C24XX
-	bool
-	help
-	  Internal configuration to enable S3C24XX style GPIO configuration
-	  functions.
-
-config S3C_GPIO_CFG_S3C64XX
-	bool
-	help
-	  Internal configuration to enable S3C64XX style GPIO configuration
-	  functions.
-
-config S5P_GPIO_CFG_S5PC1XX
-	bool
-	help
-	  Internal configuration to enable S5PC1XX style GPIO configuration
-	  functions.
-
-# DMA
-
-config S3C_DMA
-	bool
-	help
-	  Internal configuration for S3C DMA core
-
-# device definitions to compile in
-
-config S3C_DEV_HSMMC
-	bool
-	help
-	  Compile in platform device definitions for HSMMC code
-
-config S3C_DEV_HSMMC1
-	bool
-	help
-	  Compile in platform device definitions for HSMMC channel 1
-
-config S3C_DEV_HSMMC2
-	bool
-	help
-	  Compile in platform device definitions for HSMMC channel 2
-
-config S3C_DEV_I2C1
-	bool
-	help
-	  Compile in platform device definitions for I2C channel 1
-
-config S3C_DEV_FB
-	bool
-	help
-	  Compile in platform device definition for framebuffer
-
-config S3C_DEV_USB_HOST
-	bool
-	help
-	  Compile in platform device definition for USB host.
-
-config S3C_DEV_USB_HSOTG
-	bool
-	help
-	  Compile in platform device definition for USB high-speed OtG
-
-config S3C_DEV_NAND
-	bool
-	help
-	  Compile in platform device definition for NAND controller
-
-endif
diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile
deleted file mode 100644
index 50444da..0000000
--- a/arch/arm/plat-s3c/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-# arch/arm/plat-s3c/Makefile
-#
-# Copyright 2008 Simtec Electronics
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-# Core support for all Samsung SoCs
-
-obj-y				+=  init.o
-obj-y				+= time.o
-obj-y				+= clock.o
-obj-y				+= pwm-clock.o
-obj-y				+= gpio.o
-obj-y				+= gpio-config.o
-
-# DMA support
-
-obj-$(CONFIG_S3C_DMA)		+= dma.o
-
-# PM support
-
-obj-$(CONFIG_PM)		+= pm.o
-obj-$(CONFIG_PM)		+= pm-gpio.o
-obj-$(CONFIG_S3C2410_PM_CHECK)	+= pm-check.o
-
-# PWM support
-
-obj-$(CONFIG_HAVE_PWM)		+= pwm.o
-
-# devices
-
-obj-$(CONFIG_S3C_DEV_HSMMC)	+= dev-hsmmc.o
-obj-$(CONFIG_S3C_DEV_HSMMC1)	+= dev-hsmmc1.o
-obj-$(CONFIG_S3C_DEV_HSMMC2)	+= dev-hsmmc2.o
-obj-y				+= dev-i2c0.o
-obj-$(CONFIG_S3C_DEV_I2C1)	+= dev-i2c1.o
-obj-$(CONFIG_S3C_DEV_FB)	+= dev-fb.o
-obj-$(CONFIG_S3C_DEV_USB_HOST)	+= dev-usb.o
-obj-$(CONFIG_S3C_DEV_USB_HSOTG)	+= dev-usb-hsotg.o
-obj-$(CONFIG_S3C_DEV_NAND)	+= dev-nand.o
diff --git a/arch/arm/plat-s3c/clock.c b/arch/arm/plat-s3c/clock.c
deleted file mode 100644
index 619cfa8..0000000
--- a/arch/arm/plat-s3c/clock.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/clock.c
- *
- * Copyright 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX Core clock control support
- *
- * Based on, and code from linux/arch/arm/mach-versatile/clock.c
- **
- **  Copyright (C) 2004 ARM Limited.
- **  Written by Deep Blue Solutions Limited.
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <plat/cpu-freq.h>
-
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-/* clock information */
-
-static LIST_HEAD(clocks);
-
-/* We originally used an mutex here, but some contexts (see resume)
- * are calling functions such as clk_set_parent() with IRQs disabled
- * causing an BUG to be triggered.
- */
-DEFINE_SPINLOCK(clocks_lock);
-
-/* enable and disable calls for use with the clk struct */
-
-static int clk_null_enable(struct clk *clk, int enable)
-{
-	return 0;
-}
-
-/* Clock API calls */
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *p;
-	struct clk *clk = ERR_PTR(-ENOENT);
-	int idno;
-
-	if (dev == NULL || dev->bus != &platform_bus_type)
-		idno = -1;
-	else
-		idno = to_platform_device(dev)->id;
-
-	spin_lock(&clocks_lock);
-
-	list_for_each_entry(p, &clocks, list) {
-		if (p->id == idno &&
-		    strcmp(id, p->name) == 0 &&
-		    try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-
-	/* check for the case where a device was supplied, but the
-	 * clock that was being searched for is not device specific */
-
-	if (IS_ERR(clk)) {
-		list_for_each_entry(p, &clocks, list) {
-			if (p->id == -1 && strcmp(id, p->name) == 0 &&
-			    try_module_get(p->owner)) {
-				clk = p;
-				break;
-			}
-		}
-	}
-
-	spin_unlock(&clocks_lock);
-	return clk;
-}
-
-void clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-int clk_enable(struct clk *clk)
-{
-	if (IS_ERR(clk) || clk == NULL)
-		return -EINVAL;
-
-	clk_enable(clk->parent);
-
-	spin_lock(&clocks_lock);
-
-	if ((clk->usage++) == 0)
-		(clk->enable)(clk, 1);
-
-	spin_unlock(&clocks_lock);
-	return 0;
-}
-
-void clk_disable(struct clk *clk)
-{
-	if (IS_ERR(clk) || clk == NULL)
-		return;
-
-	spin_lock(&clocks_lock);
-
-	if ((--clk->usage) == 0)
-		(clk->enable)(clk, 0);
-
-	spin_unlock(&clocks_lock);
-	clk_disable(clk->parent);
-}
-
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	if (IS_ERR(clk))
-		return 0;
-
-	if (clk->rate != 0)
-		return clk->rate;
-
-	if (clk->get_rate != NULL)
-		return (clk->get_rate)(clk);
-
-	if (clk->parent != NULL)
-		return clk_get_rate(clk->parent);
-
-	return clk->rate;
-}
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	if (!IS_ERR(clk) && clk->round_rate)
-		return (clk->round_rate)(clk, rate);
-
-	return rate;
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	int ret;
-
-	if (IS_ERR(clk))
-		return -EINVAL;
-
-	/* We do not default just do a clk->rate = rate as
-	 * the clock may have been made this way by choice.
-	 */
-
-	WARN_ON(clk->set_rate == NULL);
-
-	if (clk->set_rate == NULL)
-		return -EINVAL;
-
-	spin_lock(&clocks_lock);
-	ret = (clk->set_rate)(clk, rate);
-	spin_unlock(&clocks_lock);
-
-	return ret;
-}
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-	return clk->parent;
-}
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	int ret = 0;
-
-	if (IS_ERR(clk))
-		return -EINVAL;
-
-	spin_lock(&clocks_lock);
-
-	if (clk->set_parent)
-		ret = (clk->set_parent)(clk, parent);
-
-	spin_unlock(&clocks_lock);
-
-	return ret;
-}
-
-EXPORT_SYMBOL(clk_get);
-EXPORT_SYMBOL(clk_put);
-EXPORT_SYMBOL(clk_enable);
-EXPORT_SYMBOL(clk_disable);
-EXPORT_SYMBOL(clk_get_rate);
-EXPORT_SYMBOL(clk_round_rate);
-EXPORT_SYMBOL(clk_set_rate);
-EXPORT_SYMBOL(clk_get_parent);
-EXPORT_SYMBOL(clk_set_parent);
-
-/* base clocks */
-
-static int clk_default_setrate(struct clk *clk, unsigned long rate)
-{
-	clk->rate = rate;
-	return 0;
-}
-
-struct clk clk_xtal = {
-	.name		= "xtal",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_ext = {
-	.name		= "ext",
-	.id		= -1,
-};
-
-struct clk clk_epll = {
-	.name		= "epll",
-	.id		= -1,
-};
-
-struct clk clk_mpll = {
-	.name		= "mpll",
-	.id		= -1,
-	.set_rate	= clk_default_setrate,
-};
-
-struct clk clk_upll = {
-	.name		= "upll",
-	.id		= -1,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_f = {
-	.name		= "fclk",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= &clk_mpll,
-	.ctrlbit	= 0,
-	.set_rate	= clk_default_setrate,
-};
-
-struct clk clk_h = {
-	.name		= "hclk",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-	.set_rate	= clk_default_setrate,
-};
-
-struct clk clk_p = {
-	.name		= "pclk",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-	.set_rate	= clk_default_setrate,
-};
-
-struct clk clk_usb_bus = {
-	.name		= "usb-bus",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= &clk_upll,
-};
-
-
-
-struct clk s3c24xx_uclk = {
-	.name		= "uclk",
-	.id		= -1,
-};
-
-/* initialise the clock system */
-
-int s3c24xx_register_clock(struct clk *clk)
-{
-	if (clk->enable == NULL)
-		clk->enable = clk_null_enable;
-
-	/* add to the list of available clocks */
-
-	/* Quick check to see if this clock has already been registered. */
-	BUG_ON(clk->list.prev != clk->list.next);
-
-	spin_lock(&clocks_lock);
-	list_add(&clk->list, &clocks);
-	spin_unlock(&clocks_lock);
-
-	return 0;
-}
-
-int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
-{
-	int fails = 0;
-
-	for (; nr_clks > 0; nr_clks--, clks++) {
-		if (s3c24xx_register_clock(*clks) < 0)
-			fails++;
-	}
-
-	return fails;
-}
-
-/* initalise all the clocks */
-
-int __init s3c24xx_register_baseclocks(unsigned long xtal)
-{
-	printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n");
-
-	clk_xtal.rate = xtal;
-
-	/* register our clocks */
-
-	if (s3c24xx_register_clock(&clk_xtal) < 0)
-		printk(KERN_ERR "failed to register master xtal\n");
-
-	if (s3c24xx_register_clock(&clk_mpll) < 0)
-		printk(KERN_ERR "failed to register mpll clock\n");
-
-	if (s3c24xx_register_clock(&clk_upll) < 0)
-		printk(KERN_ERR "failed to register upll clock\n");
-
-	if (s3c24xx_register_clock(&clk_f) < 0)
-		printk(KERN_ERR "failed to register cpu fclk\n");
-
-	if (s3c24xx_register_clock(&clk_h) < 0)
-		printk(KERN_ERR "failed to register cpu hclk\n");
-
-	if (s3c24xx_register_clock(&clk_p) < 0)
-		printk(KERN_ERR "failed to register cpu pclk\n");
-
-	return 0;
-}
-
diff --git a/arch/arm/plat-s3c/dev-usb-hsotg.c b/arch/arm/plat-s3c/dev-usb-hsotg.c
deleted file mode 100644
index e2f604b..0000000
--- a/arch/arm/plat-s3c/dev-usb-hsotg.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-usb-hsotg.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for USB high-speed UDC/OtG block
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-static struct resource s3c_usb_hsotg_resources[] = {
-	[0] = {
-		.start	= S3C_PA_USB_HSOTG,
-		.end	= S3C_PA_USB_HSOTG + 0x10000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_OTG,
-		.end	= IRQ_OTG,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s3c_device_usb_hsotg = {
-	.name		= "s3c-hsotg",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s3c_usb_hsotg_resources),
-	.resource	= s3c_usb_hsotg_resources,
-};
diff --git a/arch/arm/plat-s3c/dev-usb.c b/arch/arm/plat-s3c/dev-usb.c
deleted file mode 100644
index 2ee85ab..0000000
--- a/arch/arm/plat-s3c/dev-usb.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-usb.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series device definition for USB host
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-
-static struct resource s3c_usb_resource[] = {
-	[0] = {
-		.start = S3C_PA_USBHOST,
-		.end   = S3C_PA_USBHOST + 0x100 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_USBH,
-		.end   = IRQ_USBH,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static u64 s3c_device_usb_dmamask = 0xffffffffUL;
-
-struct platform_device s3c_device_usb = {
-	.name		  = "s3c2410-ohci",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c_usb_resource),
-	.resource	  = s3c_usb_resource,
-	.dev              = {
-		.dma_mask = &s3c_device_usb_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
-	}
-};
-
-EXPORT_SYMBOL(s3c_device_usb);
diff --git a/arch/arm/plat-s3c/dma.c b/arch/arm/plat-s3c/dma.c
deleted file mode 100644
index a995850..0000000
--- a/arch/arm/plat-s3c/dma.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* linux/arch/arm/plat-s3c/dma.c
- *
- * Copyright (c) 2003-2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C DMA core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-struct s3c2410_dma_buf;
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-#include <plat/dma-plat.h>
-
-/* dma channel state information */
-struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
-struct s3c2410_dma_chan *s3c_dma_chan_map[DMACH_MAX];
-
-/* s3c_dma_lookup_channel
- *
- * change the dma channel number given into a real dma channel id
-*/
-
-struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel)
-{
-	if (channel & DMACH_LOW_LEVEL)
-		return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
-	else
-		return s3c_dma_chan_map[channel];
-}
-
-/* do we need to protect the settings of the fields from
- * irq?
-*/
-
-int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)
-{
-	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
-
-	chan->op_fn = rtn;
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_set_opfn);
-
-int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
-{
-	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
-
-	chan->callback_fn = rtn;
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
-{
-	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	chan->flags = flags;
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_setflags);
diff --git a/arch/arm/plat-s3c/gpio-config.c b/arch/arm/plat-s3c/gpio-config.c
deleted file mode 100644
index 456969b..0000000
--- a/arch/arm/plat-s3c/gpio-config.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio-config.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO configuration core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-
-#include <mach/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long flags;
-	int offset;
-	int ret;
-
-	if (!chip)
-		return -EINVAL;
-
-	offset = pin - chip->chip.base;
-
-	local_irq_save(flags);
-	ret = s3c_gpio_do_setcfg(chip, offset, config);
-	local_irq_restore(flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_cfgpin);
-
-int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
-{
-	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
-	unsigned long flags;
-	int offset, ret;
-
-	if (!chip)
-		return -EINVAL;
-
-	offset = pin - chip->chip.base;
-
-	local_irq_save(flags);
-	ret = s3c_gpio_do_setpull(chip, offset, pull);
-	local_irq_restore(flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(s3c_gpio_setpull);
-
-#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
-int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip,
-				  unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = off;
-	u32 con;
-
-	if (s3c_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-
-		/* Map output to 0, and SFN2 to 1 */
-		cfg -= 1;
-		if (cfg > 1)
-			return -EINVAL;
-
-		cfg <<= shift;
-	}
-
-	con = __raw_readl(reg);
-	con &= ~(0x1 << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	return 0;
-}
-
-int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
-			    unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = off * 2;
-	u32 con;
-
-	if (s3c_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-		if (cfg > 3)
-			return -EINVAL;
-
-		cfg <<= shift;
-	}
-
-	con = __raw_readl(reg);
-	con &= ~(0x3 << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
-int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-				 unsigned int off, unsigned int cfg)
-{
-	void __iomem *reg = chip->base;
-	unsigned int shift = (off & 7) * 4;
-	u32 con;
-
-	if (off < 8 && chip->chip.ngpio > 8)
-		reg -= 4;
-
-	if (s3c_gpio_is_cfg_special(cfg)) {
-		cfg &= 0xf;
-		cfg <<= shift;
-	}
-
-	con = __raw_readl(reg);
-	con &= ~(0xf << shift);
-	con |= cfg;
-	__raw_writel(con, reg);
-
-	return 0;
-}
-#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
-
-#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
-int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
-			    unsigned int off, s3c_gpio_pull_t pull)
-{
-	void __iomem *reg = chip->base + 0x08;
-	int shift = off * 2;
-	u32 pup;
-
-	pup = __raw_readl(reg);
-	pup &= ~(3 << shift);
-	pup |= pull << shift;
-	__raw_writel(pup, reg);
-
-	return 0;
-}
-
-s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
-					unsigned int off)
-{
-	void __iomem *reg = chip->base + 0x08;
-	int shift = off * 2;
-	u32 pup = __raw_readl(reg);
-
-	pup >>= shift;
-	pup &= 0x3;
-	return (__force s3c_gpio_pull_t)pup;
-}
-#endif
diff --git a/arch/arm/plat-s3c/gpio.c b/arch/arm/plat-s3c/gpio.c
deleted file mode 100644
index 5ff24e0..0000000
--- a/arch/arm/plat-s3c/gpio.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/gpio-core.h>
-
-#ifdef CONFIG_S3C_GPIO_TRACK
-struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
-
-static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
-{
-	unsigned int gpn;
-	int i;
-
-	gpn = chip->chip.base;
-	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
-		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
-		s3c_gpios[gpn] = chip;
-	}
-}
-#endif /* CONFIG_S3C_GPIO_TRACK */
-
-/* Default routines for controlling GPIO, based on the original S3C24XX
- * GPIO functions which deal with the case where each gpio bank of the
- * chip is as following:
- *
- * base + 0x00: Control register, 2 bits per gpio
- *	        gpio n: 2 bits starting at (2*n)
- *		00 = input, 01 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *		bit n: data bit n
-*/
-
-static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long con;
-
-	local_irq_save(flags);
-
-	con = __raw_readl(base + 0x00);
-	con &= ~(3 << (offset * 2));
-
-	__raw_writel(con, base + 0x00);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int s3c_gpiolib_output(struct gpio_chip *chip,
-			      unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long dat;
-	unsigned long con;
-
-	local_irq_save(flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offset);
-	if (value)
-		dat |= 1 << offset;
-	__raw_writel(dat, base + 0x04);
-
-	con = __raw_readl(base + 0x00);
-	con &= ~(3 << (offset * 2));
-	con |= 1 << (offset * 2);
-
-	__raw_writel(con, base + 0x00);
-	__raw_writel(dat, base + 0x04);
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static void s3c_gpiolib_set(struct gpio_chip *chip,
-			    unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long dat;
-
-	local_irq_save(flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offset);
-	if (value)
-		dat |= 1 << offset;
-	__raw_writel(dat, base + 0x04);
-
-	local_irq_restore(flags);
-}
-
-static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	unsigned long val;
-
-	val = __raw_readl(ourchip->base + 0x04);
-	val >>= offset;
-	val &= 1;
-
-	return val;
-}
-
-__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
-{
-	struct gpio_chip *gc = &chip->chip;
-	int ret;
-
-	BUG_ON(!chip->base);
-	BUG_ON(!gc->label);
-	BUG_ON(!gc->ngpio);
-
-	if (!gc->direction_input)
-		gc->direction_input = s3c_gpiolib_input;
-	if (!gc->direction_output)
-		gc->direction_output = s3c_gpiolib_output;
-	if (!gc->set)
-		gc->set = s3c_gpiolib_set;
-	if (!gc->get)
-		gc->get = s3c_gpiolib_get;
-
-#ifdef CONFIG_PM
-	if (chip->pm != NULL) {
-		if (!chip->pm->save || !chip->pm->resume)
-			printk(KERN_ERR "gpio: %s has missing PM functions\n",
-			       gc->label);
-	} else
-		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
-#endif
-
-	/* gpiochip_add() prints own failure message on error. */
-	ret = gpiochip_add(gc);
-	if (ret >= 0)
-		s3c_gpiolib_track(chip);
-}
diff --git a/arch/arm/plat-s3c/include/mach/io.h b/arch/arm/plat-s3c/include/mach/io.h
deleted file mode 100644
index f6a5363..0000000
--- a/arch/arm/plat-s3c/include/mach/io.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/plat-s3c/include/mach/io.h
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben-linux@fluff.org>
- *
- * Default IO routines for plat-s3c based systems, such as S3C24A0
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/* No current ISA/PCI bus support. */
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif
diff --git a/arch/arm/plat-s3c/include/mach/timex.h b/arch/arm/plat-s3c/include/mach/timex.h
deleted file mode 100644
index 2a425ed..0000000
--- a/arch/arm/plat-s3c/include/mach/timex.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/timex.h
- *
- * Copyright (c) 2003-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - time parameters
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
- * a variable is useless. It seems as long as we make our timers an
- * exact multiple of HZ, any value that makes a 1->1 correspondence
- * for the time conversion functions to/from jiffies is acceptable.
-*/
-
-
-#define CLOCK_TICK_RATE 12000000
-
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/plat-s3c/include/mach/vmalloc.h b/arch/arm/plat-s3c/include/mach/vmalloc.h
deleted file mode 100644
index 299d95f..0000000
--- a/arch/arm/plat-s3c/include/mach/vmalloc.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* arch/arm/plat-s3c/include/mach/vmalloc.h
- *
- * from arch/arm/mach-iop3xx/include/mach/vmalloc.h
- *
- * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
- *		      http://www.simtec.co.uk/products/SWLINUX/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2410 vmalloc definition
-*/
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END	  (0xe0000000UL)
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/plat-s3c/include/plat/adc.h b/arch/arm/plat-s3c/include/plat/adc.h
deleted file mode 100644
index 5f3b1cd..0000000
--- a/arch/arm/plat-s3c/include/plat/adc.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/adc.h
- *
- * Copyright (c) 2008 Simtec Electronics
- *	http://armlinux.simnte.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX ADC driver information
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_ADC_H
-#define __ASM_PLAT_ADC_H __FILE__
-
-struct s3c_adc_client;
-
-extern int s3c_adc_start(struct s3c_adc_client *client,
-			 unsigned int channel, unsigned int nr_samples);
-
-extern int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch);
-
-extern struct s3c_adc_client *
-	s3c_adc_register(struct platform_device *pdev,
-			 void (*select)(struct s3c_adc_client *client,
-					unsigned selected),
-			 void (*conv)(struct s3c_adc_client *client,
-				      unsigned d0, unsigned d1,
-				      unsigned *samples_left),
-			 unsigned int is_ts);
-
-extern void s3c_adc_release(struct s3c_adc_client *client);
-
-#endif /* __ASM_PLAT_ADC_H */
diff --git a/arch/arm/plat-s3c/include/plat/audio-simtec.h b/arch/arm/plat-s3c/include/plat/audio-simtec.h
deleted file mode 100644
index 53a9365..0000000
--- a/arch/arm/plat-s3c/include/plat/audio-simtec.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/audio-simtec.h
- *
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Simtec Audio support.
-*/
-
-/**
- * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio
- * @use_mpllin: Select codec clock from MPLLin
- * @output_cdclk: Need to output CDCLK to the codec
- * @have_mic: Set if we have a MIC socket
- * @have_lout: Set if we have a LineOut socket
- * @amp_gpio: GPIO pin to enable the AMP
- * @amp_gain: Option GPIO to control AMP gain
- */
-struct s3c24xx_audio_simtec_pdata {
-	unsigned int	use_mpllin:1;
-	unsigned int	output_cdclk:1;
-
-	unsigned int	have_mic:1;
-	unsigned int	have_lout:1;
-
-	int		amp_gpio;
-	int		amp_gain[2];
-
-	void	(*startup)(void);
-};
-
-extern int simtec_audio_add(const char *codec_name, bool has_lr_routing,
-			    struct s3c24xx_audio_simtec_pdata *pdata);
diff --git a/arch/arm/plat-s3c/include/plat/audio.h b/arch/arm/plat-s3c/include/plat/audio.h
deleted file mode 100644
index f22d23b..0000000
--- a/arch/arm/plat-s3c/include/plat/audio.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/audio.h
- *
- * Copyright (c) 2009 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/**
- * struct s3c_audio_pdata - common platform data for audio device drivers
- * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode
- */
-struct s3c_audio_pdata {
-	int (*cfg_gpio)(struct platform_device *);
-};
diff --git a/arch/arm/plat-s3c/include/plat/clock.h b/arch/arm/plat-s3c/include/plat/clock.h
deleted file mode 100644
index d86af84..0000000
--- a/arch/arm/plat-s3c/include/plat/clock.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* linux/arch/arm/plat-s3c/include/plat/clock.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	http://www.simtec.co.uk/products/SWLINUX/
- *	Written by Ben Dooks, <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/spinlock.h>
-
-struct clk {
-	struct list_head      list;
-	struct module        *owner;
-	struct clk           *parent;
-	const char           *name;
-	int		      id;
-	int		      usage;
-	unsigned long         rate;
-	unsigned long         ctrlbit;
-
-	int		    (*enable)(struct clk *, int enable);
-	int		    (*set_rate)(struct clk *c, unsigned long rate);
-	unsigned long	    (*get_rate)(struct clk *c);
-	unsigned long	    (*round_rate)(struct clk *c, unsigned long rate);
-	int		    (*set_parent)(struct clk *c, struct clk *parent);
-};
-
-/* other clocks which may be registered by board support */
-
-extern struct clk s3c24xx_dclk0;
-extern struct clk s3c24xx_dclk1;
-extern struct clk s3c24xx_clkout0;
-extern struct clk s3c24xx_clkout1;
-extern struct clk s3c24xx_uclk;
-
-extern struct clk clk_usb_bus;
-
-/* core clock support */
-
-extern struct clk clk_f;
-extern struct clk clk_h;
-extern struct clk clk_p;
-extern struct clk clk_mpll;
-extern struct clk clk_upll;
-extern struct clk clk_epll;
-extern struct clk clk_xtal;
-extern struct clk clk_ext;
-
-/* S3C64XX specific clocks */
-extern struct clk clk_h2;
-extern struct clk clk_27m;
-extern struct clk clk_48m;
-
-/* exports for arch/arm/mach-s3c2410
- *
- * Please DO NOT use these outside of arch/arm/mach-s3c2410
-*/
-
-extern spinlock_t clocks_lock;
-
-extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
-
-extern int s3c24xx_register_clock(struct clk *clk);
-extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks);
-
-extern int s3c24xx_register_baseclocks(unsigned long xtal);
-
-extern void s3c64xx_register_clocks(void);
-
-extern void s3c24xx_setup_clocks(unsigned long fclk,
-				 unsigned long hclk,
-				 unsigned long pclk);
-
-extern void s3c2410_setup_clocks(void);
-extern void s3c2412_setup_clocks(void);
-extern void s3c244x_setup_clocks(void);
-extern void s3c2443_setup_clocks(void);
-
-/* S3C64XX specific functions and clocks */
-
-extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable);
-
-/* Init for pwm clock code */
-
-extern void s3c_pwmclk_init(void);
-
diff --git a/arch/arm/plat-s3c/include/plat/cpu-freq.h b/arch/arm/plat-s3c/include/plat/cpu-freq.h
deleted file mode 100644
index 94eb06a..0000000
--- a/arch/arm/plat-s3c/include/plat/cpu-freq.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/cpu-freq.h
- *
- * Copyright (c) 2006-2007 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C CPU frequency scaling support - driver and board
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/cpufreq.h>
-
-struct s3c_cpufreq_info;
-struct s3c_cpufreq_board;
-struct s3c_iotimings;
-
-/**
- * struct s3c_freq - frequency information (mainly for core drivers)
- * @fclk: The FCLK frequency in Hz.
- * @armclk: The ARMCLK frequency in Hz.
- * @hclk_tns: HCLK cycle time in 10ths of nano-seconds.
- * @hclk: The HCLK frequency in Hz.
- * @pclk: The PCLK frequency in Hz.
- *
- * This contains the frequency information about the current configuration
- * mainly for the core drivers to ensure we do not end up passing about
- * a large number of parameters.
- *
- * The @hclk_tns field is a useful cache for the parts of the drivers that
- * need to calculate IO timings and suchlike.
- */
-struct s3c_freq {
-	unsigned long	fclk;
-	unsigned long	armclk;
-	unsigned long	hclk_tns;	/* in 10ths of ns */
-	unsigned long	hclk;
-	unsigned long	pclk;
-};
-
-/**
- * struct s3c_cpufreq_freqs - s3c cpufreq notification information.
- * @freqs: The cpufreq setting information.
- * @old: The old clock settings.
- * @new: The new clock settings.
- * @pll_changing: Set if the PLL is changing.
- *
- * Wrapper 'struct cpufreq_freqs' so that any drivers receiving the
- * notification can use this information that is not provided by just
- * having the core frequency alone.
- *
- * The pll_changing flag is used to indicate if the PLL itself is
- * being set during this change. This is important as the clocks
- * will temporarily be set to the XTAL clock during this time, so
- * drivers may want to close down their output during this time.
- *
- * Note, this is not being used by any current drivers and therefore
- * may be removed in the future.
- */
-struct s3c_cpufreq_freqs {
-	struct cpufreq_freqs	freqs;
-	struct s3c_freq		old;
-	struct s3c_freq		new;
-
-	unsigned int		pll_changing:1;
-};
-
-#define to_s3c_cpufreq(_cf) container_of(_cf, struct s3c_cpufreq_freqs, freqs)
-
-/**
- * struct s3c_clkdivs - clock divisor information
- * @p_divisor: Divisor from FCLK to PCLK.
- * @h_divisor: Divisor from FCLK to HCLK.
- * @arm_divisor: Divisor from FCLK to ARMCLK (not all CPUs).
- * @dvs: Non-zero if using DVS mode for ARMCLK.
- *
- * Divisor settings for the core clocks.
- */
-struct s3c_clkdivs {
-	int		p_divisor;
-	int		h_divisor;
-	int		arm_divisor;
-	unsigned char	dvs;
-};
-
-#define PLLVAL(_m, _p, _s) (((_m) << 12) | ((_p) << 4) | (_s))
-
-/**
- * struct s3c_pllval - PLL value entry.
- * @freq: The frequency for this entry in Hz.
- * @pll_reg: The PLL register setting for this PLL value.
- */
-struct s3c_pllval {
-	unsigned long		freq;
-	unsigned long		pll_reg;
-};
-
-/**
- * struct s3c_cpufreq_board - per-board cpu frequency informatin
- * @refresh: The SDRAM refresh period in nanoseconds.
- * @auto_io: Set if the IO timing settings should be generated from the
- *	initialisation time hardware registers.
- * @need_io: Set if the board has external IO on any of the chipselect
- *	lines that will require the hardware timing registers to be
- *	updated on a clock change.
- * @max: The maxium frequency limits for the system. Any field that
- *	is left at zero will use the CPU's settings.
- *
- * This contains the board specific settings that affect how the CPU
- * drivers chose settings. These include the memory refresh and IO
- * timing information.
- *
- * Registration depends on the driver being used, the ARMCLK only
- * implementation does not currently need this but the older style
- * driver requires this to be available.
- */
-struct s3c_cpufreq_board {
-	unsigned int	refresh;
-	unsigned int	auto_io:1;	/* automatically init io timings. */
-	unsigned int	need_io:1;	/* set if needs io timing support. */
-
-	/* any non-zero field in here is taken as an upper limit. */
-	struct s3c_freq	max;	/* frequency limits */
-};
-
-/* Things depending on frequency scaling. */
-#ifdef CONFIG_CPU_FREQ_S3C
-#define __init_or_cpufreq
-#else
-#define __init_or_cpufreq __init
-#endif
-
-/* Board functions */
-
-#ifdef CONFIG_CPU_FREQ_S3C
-extern int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board);
-#else
-
-static inline int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board)
-{
-	return 0;
-}
-#endif  /* CONFIG_CPU_FREQ_S3C */
diff --git a/arch/arm/plat-s3c/include/plat/cpu.h b/arch/arm/plat-s3c/include/plat/cpu.h
deleted file mode 100644
index d1131ca..0000000
--- a/arch/arm/plat-s3c/include/plat/cpu.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* linux/arch/arm/plat-s3c/include/plat/cpu.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C24XX CPU support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* todo - fix when rmk changes iodescs to use `void __iomem *` */
-
-#ifndef __SAMSUNG_PLAT_CPU_H
-#define __SAMSUNG_PLAT_CPU_H
-
-#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
-
-#ifndef MHZ
-#define MHZ (1000*1000)
-#endif
-
-#define print_mhz(m) ((m) / MHZ), (((m) / 1000) % 1000)
-
-/* forward declaration */
-struct s3c24xx_uart_resources;
-struct platform_device;
-struct s3c2410_uartcfg;
-struct map_desc;
-
-/* per-cpu initialisation function table. */
-
-struct cpu_table {
-	unsigned long	idcode;
-	unsigned long	idmask;
-	void		(*map_io)(void);
-	void		(*init_uarts)(struct s3c2410_uartcfg *cfg, int no);
-	void		(*init_clocks)(int xtal);
-	int		(*init)(void);
-	const char	*name;
-};
-
-extern void s3c_init_cpu(unsigned long idcode,
-			 struct cpu_table *cpus, unsigned int cputab_size);
-
-/* core initialisation functions */
-
-extern void s3c24xx_init_irq(void);
-extern void s3c64xx_init_irq(u32 vic0, u32 vic1);
-
-extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
-extern void s3c64xx_init_io(struct map_desc *mach_desc, int size);
-
-extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c24xx_init_clocks(int xtal);
-
-extern void s3c24xx_init_uartdevs(char *name,
-				  struct s3c24xx_uart_resources *res,
-				  struct s3c2410_uartcfg *cfg, int no);
-
-/* timer for 2410/2440 */
-
-struct sys_timer;
-extern struct sys_timer s3c24xx_timer;
-
-/* system device classes */
-
-extern struct sysdev_class s3c2410_sysclass;
-extern struct sysdev_class s3c2410a_sysclass;
-extern struct sysdev_class s3c2412_sysclass;
-extern struct sysdev_class s3c2440_sysclass;
-extern struct sysdev_class s3c2442_sysclass;
-extern struct sysdev_class s3c2443_sysclass;
-extern struct sysdev_class s3c6410_sysclass;
-extern struct sysdev_class s3c64xx_sysclass;
-
-extern void (*s5pc1xx_idle)(void);
-
-#endif
diff --git a/arch/arm/plat-s3c/include/plat/debug-macro.S b/arch/arm/plat-s3c/include/plat/debug-macro.S
deleted file mode 100644
index 3634d4e..0000000
--- a/arch/arm/plat-s3c/include/plat/debug-macro.S
+++ /dev/null
@@ -1,75 +0,0 @@
-/* linux/include/asm-arm/plat-s3c/debug-macro.S
- *
- * Copyright 2005, 2007 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <plat/regs-serial.h>
-
-/* The S3C2440 implementations are used by default as they are the
- * most widely re-used */
-
-	.macro fifo_level_s3c2440 rd, rx
-		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
-		and	\rd, \rd, #S3C2440_UFSTAT_TXMASK
-	.endm
-
-#ifndef fifo_level
-#define fifo_level fifo_level_s3c2440
-#endif
-
-	.macro  fifo_full_s3c2440 rd, rx
-		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
-		tst	\rd, #S3C2440_UFSTAT_TXFULL
-	.endm
-
-#ifndef fifo_full
-#define fifo_full fifo_full_s3c2440
-#endif
-
-	.macro	senduart,rd,rx
-		strb 	\rd, [\rx, # S3C2410_UTXH ]
-	.endm
-
-	.macro	busyuart, rd, rx
-		ldr	\rd, [ \rx, # S3C2410_UFCON ]
-		tst	\rd, #S3C2410_UFCON_FIFOMODE	@ fifo enabled?
-		beq	1001f				@
-		@ FIFO enabled...
-1003:
-		fifo_full \rd, \rx
-		bne	1003b
-		b	1002f
-
-1001:
-		@ busy waiting for non fifo
-		ldr	\rd, [ \rx, # S3C2410_UTRSTAT ]
-		tst	\rd, #S3C2410_UTRSTAT_TXFE
-		beq	1001b
-
-1002:		@ exit busyuart
-	.endm
-
-	.macro	waituart,rd,rx
-		ldr	\rd, [ \rx, # S3C2410_UFCON ]
-		tst	\rd, #S3C2410_UFCON_FIFOMODE	@ fifo enabled?
-		beq	1001f				@
-		@ FIFO enabled...
-1003:
-		fifo_level \rd, \rx
-		teq	\rd, #0
-		bne	1003b
-		b	1002f
-1001:
-		@ idle waiting for non fifo
-		ldr	\rd, [ \rx, # S3C2410_UTRSTAT ]
-		tst	\rd, #S3C2410_UTRSTAT_TXFE
-		beq	1001b
-
-1002:		@ exit busyuart
-	.endm
diff --git a/arch/arm/plat-s3c/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h
deleted file mode 100644
index c1c20b0..0000000
--- a/arch/arm/plat-s3c/include/plat/devs.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/devs.h
- *
- * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2410 standard platform devices
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-#include <linux/platform_device.h>
-
-struct s3c24xx_uart_resources {
-	struct resource		*resources;
-	unsigned long		 nr_resources;
-};
-
-extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
-extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
-
-extern struct platform_device *s3c24xx_uart_devs[];
-extern struct platform_device *s3c24xx_uart_src[];
-
-extern struct platform_device s3c_device_timer[];
-
-extern struct platform_device s3c64xx_device_iis0;
-extern struct platform_device s3c64xx_device_iis1;
-extern struct platform_device s3c64xx_device_iisv4;
-
-extern struct platform_device s3c64xx_device_pcm0;
-extern struct platform_device s3c64xx_device_pcm1;
-
-extern struct platform_device s3c_device_ts;
-extern struct platform_device s3c_device_fb;
-extern struct platform_device s3c_device_usb;
-extern struct platform_device s3c_device_lcd;
-extern struct platform_device s3c_device_wdt;
-extern struct platform_device s3c_device_i2c0;
-extern struct platform_device s3c_device_i2c1;
-extern struct platform_device s3c_device_rtc;
-extern struct platform_device s3c_device_adc;
-extern struct platform_device s3c_device_sdi;
-extern struct platform_device s3c_device_iis;
-extern struct platform_device s3c_device_hwmon;
-extern struct platform_device s3c_device_hsmmc0;
-extern struct platform_device s3c_device_hsmmc1;
-extern struct platform_device s3c_device_hsmmc2;
-
-extern struct platform_device s3c_device_spi0;
-extern struct platform_device s3c_device_spi1;
-
-extern struct platform_device s3c_device_hwmon;
-
-extern struct platform_device s3c_device_nand;
-
-extern struct platform_device s3c_device_usbgadget;
-extern struct platform_device s3c_device_usb_hsotg;
-
-/* s3c2440 specific devices */
-
-#ifdef CONFIG_CPU_S3C2440
-
-extern struct platform_device s3c_device_camif;
-extern struct platform_device s3c_device_ac97;
-
-#endif
diff --git a/arch/arm/plat-s3c/include/plat/dma.h b/arch/arm/plat-s3c/include/plat/dma.h
deleted file mode 100644
index e429d10..0000000
--- a/arch/arm/plat-s3c/include/plat/dma.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/dma.h
- *
- * Copyright (C) 2003-2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C DMA support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-enum s3c2410_dma_buffresult {
-	S3C2410_RES_OK,
-	S3C2410_RES_ERR,
-	S3C2410_RES_ABORT
-};
-
-enum s3c2410_dmasrc {
-	S3C2410_DMASRC_HW,		/* source is memory */
-	S3C2410_DMASRC_MEM		/* source is hardware */
-};
-
-/* enum s3c2410_chan_op
- *
- * operation codes passed to the DMA code by the user, and also used
- * to inform the current channel owner of any changes to the system state
-*/
-
-enum s3c2410_chan_op {
-	S3C2410_DMAOP_START,
-	S3C2410_DMAOP_STOP,
-	S3C2410_DMAOP_PAUSE,
-	S3C2410_DMAOP_RESUME,
-	S3C2410_DMAOP_FLUSH,
-	S3C2410_DMAOP_TIMEOUT,		/* internal signal to handler */
-	S3C2410_DMAOP_STARTED,		/* indicate channel started */
-};
-
-struct s3c2410_dma_client {
-	char                *name;
-};
-
-struct s3c2410_dma_chan;
-
-/* s3c2410_dma_cbfn_t
- *
- * buffer callback routine type
-*/
-
-typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
-				   void *buf, int size,
-				   enum s3c2410_dma_buffresult result);
-
-typedef int  (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
-				   enum s3c2410_chan_op );
-
-
-
-/* s3c2410_dma_request
- *
- * request a dma channel exclusivley
-*/
-
-extern int s3c2410_dma_request(unsigned int channel,
-			       struct s3c2410_dma_client *, void *dev);
-
-
-/* s3c2410_dma_ctrl
- *
- * change the state of the dma channel
-*/
-
-extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op);
-
-/* s3c2410_dma_setflags
- *
- * set the channel's flags to a given state
-*/
-
-extern int s3c2410_dma_setflags(unsigned int channel,
-				unsigned int flags);
-
-/* s3c2410_dma_free
- *
- * free the dma channel (will also abort any outstanding operations)
-*/
-
-extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);
-
-/* s3c2410_dma_enqueue
- *
- * place the given buffer onto the queue of operations for the channel.
- * The buffer must be allocated from dma coherent memory, or the Dcache/WB
- * drained before the buffer is given to the DMA system.
-*/
-
-extern int s3c2410_dma_enqueue(unsigned int channel, void *id,
-			       dma_addr_t data, int size);
-
-/* s3c2410_dma_config
- *
- * configure the dma channel
-*/
-
-extern int s3c2410_dma_config(unsigned int channel, int xferunit);
-
-/* s3c2410_dma_devconfig
- *
- * configure the device we're talking to
-*/
-
-extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
-				 unsigned long devaddr);
-
-/* s3c2410_dma_getposition
- *
- * get the position that the dma transfer is currently at
-*/
-
-extern int s3c2410_dma_getposition(unsigned int channel,
-				   dma_addr_t *src, dma_addr_t *dest);
-
-extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
-extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
-
-
diff --git a/arch/arm/plat-s3c/include/plat/fb.h b/arch/arm/plat-s3c/include/plat/fb.h
deleted file mode 100644
index f8db879..0000000
--- a/arch/arm/plat-s3c/include/plat/fb.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* linux/arch/arm/plat-s3c/include/plat/fb.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C - FB platform data definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __PLAT_S3C_FB_H
-#define __PLAT_S3C_FB_H __FILE__
-
-/**
- * struct s3c_fb_pd_win - per window setup data
- * @win_mode: The display parameters to initialise (not for window 0)
- * @virtual_x: The virtual X size.
- * @virtual_y: The virtual Y size.
- */
-struct s3c_fb_pd_win {
-	struct fb_videomode	win_mode;
-
-	unsigned short		default_bpp;
-	unsigned short		max_bpp;
-	unsigned short		virtual_x;
-	unsigned short		virtual_y;
-};
-
-/**
- * struct s3c_fb_platdata -  S3C driver platform specific information
- * @setup_gpio: Setup the external GPIO pins to the right state to transfer
- *		the data from the display system to the connected display
- *		device.
- * @vidcon0: The base vidcon0 values to control the panel data format.
- * @vidcon1: The base vidcon1 values to control the panel data output.
- * @win: The setup data for each hardware window, or NULL for unused.
- * @display_mode: The LCD output display mode.
- *
- * The platform data supplies the video driver with all the information
- * it requires to work with the display(s) attached to the machine. It
- * controls the initial mode, the number of display windows (0 is always
- * the base framebuffer) that are initialised etc.
- *
- */
-struct s3c_fb_platdata {
-	void	(*setup_gpio)(void);
-
-	struct s3c_fb_pd_win	*win[S3C_FB_MAX_WIN];
-
-	u32			 vidcon0;
-	u32			 vidcon1;
-};
-
-/**
- * s3c_fb_set_platdata() - Setup the FB device with platform data.
- * @pd: The platform data to set. The data is copied from the passed structure
- *      so the machine data can mark the data __initdata so that any unused
- *      machines will end up dumping their data at runtime.
- */
-extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
-
-/**
- * s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
- *
- * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
- */
-extern void s3c64xx_fb_gpio_setup_24bpp(void);
-
-/**
- * s5pc100_fb_gpio_setup_24bpp() - S5PC100 setup function for 24bpp LCD
- *
- * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
- */
-extern void s5pc100_fb_gpio_setup_24bpp(void);
-
-#endif /* __PLAT_S3C_FB_H */
diff --git a/arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h
deleted file mode 100644
index 652e2bb..0000000
--- a/arch/arm/plat-s3c/include/plat/gpio-cfg-helpers.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C Platform - GPIO pin configuration helper definitions
- *
- * This program is free software; you can 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 meant for core cpu support, machine or other driver files
- * should not be including this header.
- */
-
-#ifndef __PLAT_GPIO_CFG_HELPERS_H
-#define __PLAT_GPIO_CFG_HELPERS_H __FILE__
-
-/* As a note, all gpio configuration functions are entered exclusively, either
- * with the relevant lock held or the system prevented from doing anything else
- * by disabling interrupts.
-*/
-
-static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip,
-				     unsigned int off, unsigned int config)
-{
-	return (chip->config->set_config)(chip, off, config);
-}
-
-static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
-				      unsigned int off, s3c_gpio_pull_t pull)
-{
-	return (chip->config->set_pull)(chip, off, pull);
-}
-
-/**
- * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register
- * has two bits of configuration per gpio, which have the following
- * functions:
- *	00 = input
- *	01 = output
- *	1x = special function
-*/
-extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
-				   unsigned int off, unsigned int cfg);
-
-/**
- * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A)
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register
- * has one bit of configuration for the gpio, where setting the bit
- * means the pin is in special function mode and unset means output.
-*/
-extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
-				     unsigned int off, unsigned int cfg);
-
-/**
- * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @cfg: The configuration value to set.
- *
- * This helper deal with the GPIO cases where the control register has 4 bits
- * of control per GPIO, generally in the form of:
- *	0000 = Input
- *	0001 = Output
- *	others = Special functions (dependant on bank)
- *
- * Note, since the code to deal with the case where there are two control
- * registers instead of one, we do not have a seperate set of functions for
- * each case.
-*/
-extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
-					unsigned int off, unsigned int cfg);
-
-
-/* Pull-{up,down} resistor controls.
- *
- * S3C2410,S3C2440,S3C24A0 = Pull-UP,
- * S3C2412,S3C2413 = Pull-Down
- * S3C6400,S3C6410 = Pull-Both [None,Down,Up,Undef]
- * S3C2443 = Pull-Both [not same as S3C6400]
- */
-
-/**
- * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @param: pull: The pull mode being requested.
- *
- * This is a helper function for the case where we have GPIOs with one
- * bit configuring the presence of a pull-up resistor.
- */
-extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
-				unsigned int off, s3c_gpio_pull_t pull);
-
-/**
- * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none
- * @chip: The gpio chip that is being configured
- * @off: The offset for the GPIO being configured
- * @param: pull: The pull mode being requested
- *
- * This is a helper function for the case where we have GPIOs with one
- * bit configuring the presence of a pull-down resistor.
- */
-extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
-				  unsigned int off, s3c_gpio_pull_t pull);
-
-/**
- * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @param: pull: The pull mode being requested.
- *
- * This is a helper function for the case where we have GPIOs with two
- * bits configuring the presence of a pull resistor, in the following
- * order:
- *	00 = No pull resistor connected
- *	01 = Pull-up resistor connected
- *	10 = Pull-down resistor connected
- */
-extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
-				   unsigned int off, s3c_gpio_pull_t pull);
-
-
-/**
- * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none
- * @chip: The gpio chip that the GPIO pin belongs to
- * @off: The offset to the pin to get the configuration of.
- *
- * This helper function reads the state of the pull-{up,down} resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_upown.
-*/
-extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
-					       unsigned int off);
-
-/**
- * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
- * @chip: The gpio chip that is being configured.
- * @off: The offset for the GPIO being configured.
- * @param: pull: The pull mode being requested.
- *
- * This is a helper function for the case where we have GPIOs with two
- * bits configuring the presence of a pull resistor, in the following
- * order:
- *	00 = Pull-up resistor connected
- *	10 = Pull-down resistor connected
- *	x1 = No pull up resistor
- */
-extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
-				    unsigned int off, s3c_gpio_pull_t pull);
-
-/**
- * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors
- * @chip: The gpio chip that the GPIO pin belongs to.
- * @off: The offset to the pin to get the configuration of.
- *
- * This helper function reads the state of the pull-{up,down} resistor for the
- * given GPIO in the same case as s3c_gpio_setpull_upown.
-*/
-extern s3c_gpio_pull_t s3c_gpio_getpull_s3c24xx(struct s3c_gpio_chip *chip,
-						unsigned int off);
-
-#endif /* __PLAT_GPIO_CFG_HELPERS_H */
-
diff --git a/arch/arm/plat-s3c/include/plat/gpio-core.h b/arch/arm/plat-s3c/include/plat/gpio-core.h
deleted file mode 100644
index 32af612..0000000
--- a/arch/arm/plat-s3c/include/plat/gpio-core.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* linux/arch/arm/plat-s3c/include/plat/gpio-core.h
- *
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C Platform - GPIO core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* Define the core gpiolib support functions that the s3c platforms may
- * need to extend or change depending on the hardware and the s3c chip
- * selected at build or found at run time.
- *
- * These definitions are not intended for driver inclusion, there is
- * nothing here that should not live outside the platform and core
- * specific code.
-*/
-
-struct s3c_gpio_chip;
-
-/**
- * struct s3c_gpio_pm - power management (suspend/resume) information
- * @save: Routine to save the state of the GPIO block
- * @resume: Routine to resume the GPIO block.
- */
-struct s3c_gpio_pm {
-	void (*save)(struct s3c_gpio_chip *chip);
-	void (*resume)(struct s3c_gpio_chip *chip);
-};
-
-struct s3c_gpio_cfg;
-
-/**
- * struct s3c_gpio_chip - wrapper for specific implementation of gpio
- * @chip: The chip structure to be exported via gpiolib.
- * @base: The base pointer to the gpio configuration registers.
- * @config: special function and pull-resistor control information.
- * @pm_save: Save information for suspend/resume support.
- *
- * This wrapper provides the necessary information for the Samsung
- * specific gpios being registered with gpiolib.
- */
-struct s3c_gpio_chip {
-	struct gpio_chip	chip;
-	struct s3c_gpio_cfg	*config;
-	struct s3c_gpio_pm	*pm;
-	void __iomem		*base;
-#ifdef CONFIG_PM
-	u32			pm_save[4];
-#endif
-};
-
-static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
-{
-	return container_of(gpc, struct s3c_gpio_chip, chip);
-}
-
-/** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip.
- * @chip: The chip to register
- *
- * This is a wrapper to gpiochip_add() that takes our specific gpio chip
- * information and makes the necessary alterations for the platform and
- * notes the information for use with the configuration systems and any
- * other parts of the system.
- */
-extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
-
-/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
- * for use with the configuration calls, and other parts of the s3c gpiolib
- * support code.
- *
- * Not all s3c support code will need this, as some configurations of cpu
- * may only support one or two different configuration options and have an
- * easy gpio to s3c_gpio_chip mapping function. If this is the case, then
- * the machine support file should provide its own s3c_gpiolib_getchip()
- * and any other necessary functions.
- */
-
-#ifdef CONFIG_S3C_GPIO_TRACK
-extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
-
-static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
-{
-	return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL;
-}
-#else
-/* machine specific code should provide s3c_gpiolib_getchip */
-
-static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
-#endif
-
-#ifdef CONFIG_PM
-extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
-extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
-extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
-#define __gpio_pm(x) x
-#else
-#define s3c_gpio_pm_1bit NULL
-#define s3c_gpio_pm_2bit NULL
-#define s3c_gpio_pm_4bit NULL
-#define __gpio_pm(x) NULL
-
-#endif /* CONFIG_PM */
diff --git a/arch/arm/plat-s3c/include/plat/nand.h b/arch/arm/plat-s3c/include/plat/nand.h
deleted file mode 100644
index 226147b..0000000
--- a/arch/arm/plat-s3c/include/plat/nand.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/nand.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - NAND device controller platfrom_device info
- *
- * This program is free software; you can 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 s3c2410_nand_set - define a set of one or more nand chips
- * @disable_ecc:	Entirely disable ECC - Dangerous
- * @flash_bbt: 		Openmoko u-boot can create a Bad Block Table
- *			Setting this flag will allow the kernel to
- *			look for it at boot time and also skip the NAND
- *			scan.
- * @options:		Default value to set into 'struct nand_chip' options.
- * @nr_chips:		Number of chips in this set
- * @nr_partitions:	Number of partitions pointed to by @partitions
- * @name:		Name of set (optional)
- * @nr_map:		Map for low-layer logical to physical chip numbers (option)
- * @partitions:		The mtd partition list
- *
- * define a set of one or more nand chips registered with an unique mtd. Also
- * allows to pass flag to the underlying NAND layer. 'disable_ecc' will trigger
- * a warning at boot time.
- */
-struct s3c2410_nand_set {
-	unsigned int		disable_ecc:1;
-	unsigned int		flash_bbt:1;
-
-	unsigned int		options;
-	int			nr_chips;
-	int			nr_partitions;
-	char			*name;
-	int			*nr_map;
-	struct mtd_partition	*partitions;
-	struct nand_ecclayout	*ecc_layout;
-};
-
-struct s3c2410_platform_nand {
-	/* timing information for controller, all times in nanoseconds */
-
-	int	tacls;	/* time for active CLE/ALE to nWE/nOE */
-	int	twrph0;	/* active time for nWE/nOE */
-	int	twrph1;	/* time for release CLE/ALE from nWE/nOE inactive */
-
-	unsigned int	ignore_unset_ecc:1;
-
-	int			nr_sets;
-	struct s3c2410_nand_set *sets;
-
-	void			(*select_chip)(struct s3c2410_nand_set *,
-					       int chip);
-};
-
-/**
- * s3c_nand_set_platdata() - register NAND platform data.
- * @nand: The NAND platform data to register with s3c_device_nand.
- *
- * This function copies the given NAND platform data, @nand and registers
- * it with the s3c_device_nand. This allows @nand to be __initdata.
-*/
-extern void s3c_nand_set_platdata(struct s3c2410_platform_nand *nand);
diff --git a/arch/arm/plat-s3c/include/plat/pm.h b/arch/arm/plat-s3c/include/plat/pm.h
deleted file mode 100644
index 7a79719..0000000
--- a/arch/arm/plat-s3c/include/plat/pm.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/pm.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Written by Ben Dooks, <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* s3c_pm_init
- *
- * called from board at initialisation time to setup the power
- * management
-*/
-
-#ifdef CONFIG_PM
-
-extern __init int s3c_pm_init(void);
-
-#else
-
-static inline int s3c_pm_init(void)
-{
-	return 0;
-}
-#endif
-
-/* configuration for the IRQ mask over sleep */
-extern unsigned long s3c_irqwake_intmask;
-extern unsigned long s3c_irqwake_eintmask;
-
-/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
-extern unsigned long s3c_irqwake_intallow;
-extern unsigned long s3c_irqwake_eintallow;
-
-/* per-cpu sleep functions */
-
-extern void (*pm_cpu_prep)(void);
-extern void (*pm_cpu_sleep)(void);
-
-/* Flags for PM Control */
-
-extern unsigned long s3c_pm_flags;
-
-extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */
-
-/* from sleep.S */
-
-extern int  s3c_cpu_save(unsigned long *saveblk);
-extern void s3c_cpu_resume(void);
-
-extern void s3c2410_cpu_suspend(void);
-
-extern unsigned long s3c_sleep_save_phys;
-
-/* sleep save info */
-
-/**
- * struct sleep_save - save information for shared peripherals.
- * @reg: Pointer to the register to save.
- * @val: Holder for the value saved from reg.
- *
- * This describes a list of registers which is used by the pm core and
- * other subsystem to save and restore register values over suspend.
- */
-struct sleep_save {
-	void __iomem	*reg;
-	unsigned long	val;
-};
-
-#define SAVE_ITEM(x) \
-	{ .reg = (x) }
-
-/**
- * struct pm_uart_save - save block for core UART
- * @ulcon: Save value for S3C2410_ULCON
- * @ucon: Save value for S3C2410_UCON
- * @ufcon: Save value for S3C2410_UFCON
- * @umcon: Save value for S3C2410_UMCON
- * @ubrdiv: Save value for S3C2410_UBRDIV
- *
- * Save block for UART registers to be held over sleep and restored if they
- * are needed (say by debug).
-*/
-struct pm_uart_save {
-	u32	ulcon;
-	u32	ucon;
-	u32	ufcon;
-	u32	umcon;
-	u32	ubrdiv;
-	u32	udivslot;
-};
-
-/* helper functions to save/restore lists of registers. */
-
-extern void s3c_pm_do_save(struct sleep_save *ptr, int count);
-extern void s3c_pm_do_restore(struct sleep_save *ptr, int count);
-extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
-
-#ifdef CONFIG_PM
-extern int s3c_irqext_wake(unsigned int irqno, unsigned int state);
-extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
-extern int s3c24xx_irq_resume(struct sys_device *dev);
-#else
-#define s3c_irqext_wake NULL
-#define s3c24xx_irq_suspend NULL
-#define s3c24xx_irq_resume  NULL
-#endif
-
-/* PM debug functions */
-
-#ifdef CONFIG_S3C2410_PM_DEBUG
-/**
- * s3c_pm_dbg() - low level debug function for use in suspend/resume.
- * @msg: The message to print.
- *
- * This function is used mainly to debug the resume process before the system
- * can rely on printk/console output. It uses the low-level debugging output
- * routine printascii() to do its work.
- */
-extern void s3c_pm_dbg(const char *msg, ...);
-
-#define S3C_PMDBG(fmt...) s3c_pm_dbg(fmt)
-#else
-#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
-#endif
-
-#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
-/**
- * s3c_pm_debug_smdkled() - Debug PM suspend/resume via SMDK Board LEDs
- * @set: set bits for the state of the LEDs
- * @clear: clear bits for the state of the LEDs.
- */
-extern void s3c_pm_debug_smdkled(u32 set, u32 clear);
-
-#else
-static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { }
-#endif /* CONFIG_S3C_PM_DEBUG_LED_SMDK */
-
-/* suspend memory checking */
-
-#ifdef CONFIG_S3C2410_PM_CHECK
-extern void s3c_pm_check_prepare(void);
-extern void s3c_pm_check_restore(void);
-extern void s3c_pm_check_cleanup(void);
-extern void s3c_pm_check_store(void);
-#else
-#define s3c_pm_check_prepare() do { } while(0)
-#define s3c_pm_check_restore() do { } while(0)
-#define s3c_pm_check_cleanup() do { } while(0)
-#define s3c_pm_check_store()   do { } while(0)
-#endif
-
-/**
- * s3c_pm_configure_extint() - ensure pins are correctly set for IRQ
- *
- * Setup all the necessary GPIO pins for waking the system on external
- * interrupt.
- */
-extern void s3c_pm_configure_extint(void);
-
-/**
- * s3c_pm_restore_gpios() - restore the state of the gpios after sleep.
- *
- * Restore the state of the GPIO pins after sleep, which may involve ensuring
- * that we do not glitch the state of the pins from that the bootloader's
- * resume code has done.
-*/
-extern void s3c_pm_restore_gpios(void);
-
-/**
- * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
- *
- * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios().
- */
-extern void s3c_pm_save_gpios(void);
-
-/**
- * s3c_pm_cb_flushcache - callback for assembly code
- *
- * Callback to issue flush_cache_all() as this call is
- * not a directly callable object.
- */
-extern void s3c_pm_cb_flushcache(void);
-
-extern void s3c_pm_save_core(void);
-extern void s3c_pm_restore_core(void);
diff --git a/arch/arm/plat-s3c/include/plat/regs-adc.h b/arch/arm/plat-s3c/include/plat/regs-adc.h
deleted file mode 100644
index 4323ccc..0000000
--- a/arch/arm/plat-s3c/include/plat/regs-adc.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-adc.h
- *
- * Copyright (c) 2004 Shannon Holland <holland@loser.net>
- *
- * This program is free software; yosu can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2410 ADC registers
-*/
-
-#ifndef __ASM_ARCH_REGS_ADC_H
-#define __ASM_ARCH_REGS_ADC_H "regs-adc.h"
-
-#define S3C2410_ADCREG(x) (x)
-
-#define S3C2410_ADCCON	   S3C2410_ADCREG(0x00)
-#define S3C2410_ADCTSC	   S3C2410_ADCREG(0x04)
-#define S3C2410_ADCDLY	   S3C2410_ADCREG(0x08)
-#define S3C2410_ADCDAT0	   S3C2410_ADCREG(0x0C)
-#define S3C2410_ADCDAT1	   S3C2410_ADCREG(0x10)
-
-
-/* ADCCON Register Bits */
-#define S3C2410_ADCCON_ECFLG		(1<<15)
-#define S3C2410_ADCCON_PRSCEN		(1<<14)
-#define S3C2410_ADCCON_PRSCVL(x)	(((x)&0xFF)<<6)
-#define S3C2410_ADCCON_PRSCVLMASK	(0xFF<<6)
-#define S3C2410_ADCCON_SELMUX(x)	(((x)&0x7)<<3)
-#define S3C2410_ADCCON_MUXMASK		(0x7<<3)
-#define S3C2410_ADCCON_STDBM		(1<<2)
-#define S3C2410_ADCCON_READ_START	(1<<1)
-#define S3C2410_ADCCON_ENABLE_START	(1<<0)
-#define S3C2410_ADCCON_STARTMASK	(0x3<<0)
-
-
-/* ADCTSC Register Bits */
-#define S3C2410_ADCTSC_YM_SEN		(1<<7)
-#define S3C2410_ADCTSC_YP_SEN		(1<<6)
-#define S3C2410_ADCTSC_XM_SEN		(1<<5)
-#define S3C2410_ADCTSC_XP_SEN		(1<<4)
-#define S3C2410_ADCTSC_PULL_UP_DISABLE	(1<<3)
-#define S3C2410_ADCTSC_AUTO_PST		(1<<2)
-#define S3C2410_ADCTSC_XY_PST(x)	(((x)&0x3)<<0)
-
-/* ADCDAT0 Bits */
-#define S3C2410_ADCDAT0_UPDOWN		(1<<15)
-#define S3C2410_ADCDAT0_AUTO_PST	(1<<14)
-#define S3C2410_ADCDAT0_XY_PST		(0x3<<12)
-#define S3C2410_ADCDAT0_XPDATA_MASK	(0x03FF)
-
-/* ADCDAT1 Bits */
-#define S3C2410_ADCDAT1_UPDOWN		(1<<15)
-#define S3C2410_ADCDAT1_AUTO_PST	(1<<14)
-#define S3C2410_ADCDAT1_XY_PST		(0x3<<12)
-#define S3C2410_ADCDAT1_YPDATA_MASK	(0x03FF)
-
-#endif /* __ASM_ARCH_REGS_ADC_H */
-
-
diff --git a/arch/arm/plat-s3c/include/plat/regs-fb-v4.h b/arch/arm/plat-s3c/include/plat/regs-fb-v4.h
deleted file mode 100644
index a60ed0d..0000000
--- a/arch/arm/plat-s3c/include/plat/regs-fb-v4.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/regs-fb-v4.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      http://armlinux.simtec.co.uk/
- *      Ben Dooks <ben@simtec.co.uk>
- *
- * S3C64XX - new-style framebuffer register definitions
- *
- * This is the register set for the new style framebuffer interface
- * found from the S3C2443 onwards and specifically the S3C64XX series
- * S3C6400 and S3C6410.
- *
- * The file contains the cpu specific items which change between whichever
- * architecture is selected. See <plat/regs-fb.h> for the core definitions
- * that are the same.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* include the core definitions here, in case we really do need to
- * override them at a later date.
-*/
-
-#include <plat/regs-fb.h>
-
-#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
-#define VIDCON1_FSTATUS_EVEN	(1 << 15)
-
-/* Video timing controls */
-#define VIDTCON0				(0x10)
-#define VIDTCON1				(0x14)
-#define VIDTCON2				(0x18)
-
-/* Window position controls */
-
-#define WINCON(_win)				(0x20 + ((_win) * 4))
-
-/* OSD1 and OSD4 do not have register D */
-
-#define VIDOSD_A(_win)				(0x40 + ((_win) * 16))
-#define VIDOSD_B(_win)				(0x44 + ((_win) * 16))
-#define VIDOSD_C(_win)				(0x48 + ((_win) * 16))
-#define VIDOSD_D(_win)				(0x4C + ((_win) * 16))
-
-
-#define VIDINTCON0				(0x130)
-
-#define WxKEYCONy(_win, _con)			((0x140 + ((_win) * 8)) + ((_con) * 4))
-
-/* WINCONx */
-
-#define WINCONx_CSCWIDTH_MASK			(0x3 << 26)
-#define WINCONx_CSCWIDTH_SHIFT			(26)
-#define WINCONx_CSCWIDTH_WIDE			(0x0 << 26)
-#define WINCONx_CSCWIDTH_NARROW			(0x3 << 26)
-
-#define WINCONx_ENLOCAL				(1 << 22)
-#define WINCONx_BUFSTATUS			(1 << 21)
-#define WINCONx_BUFSEL				(1 << 20)
-#define WINCONx_BUFAUTOEN			(1 << 19)
-#define WINCONx_YCbCr				(1 << 13)
-
-#define WINCON1_LOCALSEL_CAMIF			(1 << 23)
-
-#define WINCON2_LOCALSEL_CAMIF			(1 << 23)
-#define WINCON2_BLD_PIX				(1 << 6)
-
-#define WINCON2_ALPHA_SEL			(1 << 1)
-#define WINCON2_BPPMODE_MASK			(0xf << 2)
-#define WINCON2_BPPMODE_SHIFT			(2)
-#define WINCON2_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON2_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON2_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON2_BPPMODE_8BPP_1232		(0x4 << 2)
-#define WINCON2_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON2_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON2_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON2_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON2_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON2_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON2_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON2_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON2_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON2_BPPMODE_28BPP_A4888		(0xd << 2)
-
-#define WINCON3_BLD_PIX				(1 << 6)
-
-#define WINCON3_ALPHA_SEL			(1 << 1)
-#define WINCON3_BPPMODE_MASK			(0xf << 2)
-#define WINCON3_BPPMODE_SHIFT			(2)
-#define WINCON3_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON3_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON3_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON3_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON3_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON3_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON3_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON3_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON3_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON3_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON3_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON3_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON3_BPPMODE_28BPP_A4888		(0xd << 2)
-
-#define VIDINTCON0_FIFIOSEL_WINDOW2		(0x10 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW3		(0x20 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW4		(0x40 << 5)
-
-#define DITHMODE				(0x170)
-#define WINxMAP(_win)				(0x180 + ((_win) * 4))
-
-
-#define DITHMODE_R_POS_MASK			(0x3 << 5)
-#define DITHMODE_R_POS_SHIFT			(5)
-#define DITHMODE_R_POS_8BIT			(0x0 << 5)
-#define DITHMODE_R_POS_6BIT			(0x1 << 5)
-#define DITHMODE_R_POS_5BIT			(0x2 << 5)
-
-#define DITHMODE_G_POS_MASK			(0x3 << 3)
-#define DITHMODE_G_POS_SHIFT			(3)
-#define DITHMODE_G_POS_8BIT			(0x0 << 3)
-#define DITHMODE_G_POS_6BIT			(0x1 << 3)
-#define DITHMODE_G_POS_5BIT			(0x2 << 3)
-
-#define DITHMODE_B_POS_MASK			(0x3 << 1)
-#define DITHMODE_B_POS_SHIFT			(1)
-#define DITHMODE_B_POS_8BIT			(0x0 << 1)
-#define DITHMODE_B_POS_6BIT			(0x1 << 1)
-#define DITHMODE_B_POS_5BIT			(0x2 << 1)
-
-#define DITHMODE_DITH_EN			(1 << 0)
-
-#define WPALCON					(0x1A0)
-
-/* Palette control */
-/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
- * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
-#define WPALCON_W4PAL_16BPP_A555		(1 << 8)
-#define WPALCON_W3PAL_16BPP_A555		(1 << 7)
-#define WPALCON_W2PAL_16BPP_A555		(1 << 6)
-
-
-/* system specific implementation code for palette sizes, and other
- * information that changes depending on which architecture is being
- * compiled.
-*/
-
-/* return true if window _win has OSD register D */
-#define s3c_fb_has_osd_d(_win) ((_win) != 4 && (_win) != 0)
-
-static inline unsigned int s3c_fb_win_pal_size(unsigned int win)
-{
-	if (win < 2)
-		return 256;
-	if (win < 4)
-		return 16;
-	if (win == 4)
-		return 4;
-
-	BUG();	/* shouldn't get here */
-}
-
-static inline int s3c_fb_validate_win_bpp(unsigned int win, unsigned int bpp)
-{
-	/* all windows can do 1/2 bpp */
-
-	if ((bpp == 25 || bpp == 19) && win == 0)
-		return 0;	/* win 0 does not have 19 or 25bpp modes */
-
-	if (bpp == 4 && win == 4)
-		return 0;
-
-	if (bpp == 8 && (win >= 3))
-		return 0;	/* win 3/4 cannot do 8bpp in any mode */
-
-	return 1;
-}
-
-static inline int s3c_fb_pal_is16(unsigned int window)
-{
-	return window > 1;
-}
-
-struct s3c_fb_palette {
-	struct fb_bitfield	r;
-	struct fb_bitfield	g;
-	struct fb_bitfield	b;
-	struct fb_bitfield	a;
-};
-
-static inline void s3c_fb_init_palette(unsigned int window,
-				       struct s3c_fb_palette *palette)
-{
-	if (window < 2) {
-		/* Windows 0/1 are 8/8/8 or A/8/8/8 */
-		palette->r.offset = 16;
-		palette->r.length = 8;
-		palette->g.offset = 8;
-		palette->g.length = 8;
-		palette->b.offset = 0;
-		palette->b.length = 8;
-	} else {
-		/* currently we assume RGB 5/6/5 */
-		palette->r.offset = 11;
-		palette->r.length = 5;
-		palette->g.offset = 5;
-		palette->g.length = 6;
-		palette->b.offset = 0;
-		palette->b.length = 5;
-	}
-}
-
-/* Notes on per-window bpp settings
- *
- * Value	Win0	 Win1	  Win2	   Win3	    Win 4
- * 0000		1(P)	 1(P)	  1(P)	   1(P)	    1(P)
- * 0001		2(P)	 2(P)     2(P)	   2(P)	    2(P)
- * 0010		4(P)	 4(P)     4(P)	   4(P)     -none-
- * 0011		8(P)	 8(P)     -none-   -none-   -none-
- * 0100		-none-	 8(A232)  8(A232)  -none-   -none-
- * 0101		16(565)	 16(565)  16(565)  16(565)   16(565)
- * 0110		-none-	 16(A555) 16(A555) 16(A555)  16(A555)
- * 0111		16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
- * 1000		18(666)	 18(666)  18(666)  18(666)   18(666)
- * 1001		-none-	 18(A665) 18(A665) 18(A665)  16(A665)
- * 1010		-none-	 19(A666) 19(A666) 19(A666)  19(A666)
- * 1011		24(888)	 24(888)  24(888)  24(888)   24(888)
- * 1100		-none-	 24(A887) 24(A887) 24(A887)  24(A887)
- * 1101		-none-	 25(A888) 25(A888) 25(A888)  25(A888)
- * 1110		-none-	 -none-	  -none-   -none-    -none-
- * 1111		-none-	 -none-   -none-   -none-    -none-
-*/
diff --git a/arch/arm/plat-s3c/include/plat/regs-fb.h b/arch/arm/plat-s3c/include/plat/regs-fb.h
deleted file mode 100644
index e9ee599..0000000
--- a/arch/arm/plat-s3c/include/plat/regs-fb.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/regs-fb.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      http://armlinux.simtec.co.uk/
- *      Ben Dooks <ben@simtec.co.uk>
- *
- * S3C Platform - new-style framebuffer register definitions
- *
- * This is the register set for the new style framebuffer interface
- * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
- * S3C64XX series such as the S3C6400 and S3C6410.
- *
- * The file does not contain the cpu specific items which are based on
- * whichever architecture is selected, it only contains the core of the
- * register set. See <mach/regs-fb.h> to get the specifics.
- *
- * Note, we changed to using regs-fb.h as it avoids any clashes with
- * the original regs-lcd.h so out of the way of regs-lcd.h as well as
- * indicating the newer block is much more than just an LCD interface.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* Please do not include this file directly, use <mach/regs-fb.h> to
- * ensure all the localised SoC support is included as necessary.
-*/
-
-/* VIDCON0 */
-
-#define VIDCON0					(0x00)
-#define VIDCON0_INTERLACE			(1 << 29)
-#define VIDCON0_VIDOUT_MASK			(0x3 << 26)
-#define VIDCON0_VIDOUT_SHIFT			(26)
-#define VIDCON0_VIDOUT_RGB			(0x0 << 26)
-#define VIDCON0_VIDOUT_TV			(0x1 << 26)
-#define VIDCON0_VIDOUT_I80_LDI0			(0x2 << 26)
-#define VIDCON0_VIDOUT_I80_LDI1			(0x3 << 26)
-
-#define VIDCON0_L1_DATA_MASK			(0x7 << 23)
-#define VIDCON0_L1_DATA_SHIFT			(23)
-#define VIDCON0_L1_DATA_16BPP			(0x0 << 23)
-#define VIDCON0_L1_DATA_18BPP16			(0x1 << 23)
-#define VIDCON0_L1_DATA_18BPP9			(0x2 << 23)
-#define VIDCON0_L1_DATA_24BPP			(0x3 << 23)
-#define VIDCON0_L1_DATA_18BPP			(0x4 << 23)
-#define VIDCON0_L1_DATA_16BPP8			(0x5 << 23)
-
-#define VIDCON0_L0_DATA_MASK			(0x7 << 20)
-#define VIDCON0_L0_DATA_SHIFT			(20)
-#define VIDCON0_L0_DATA_16BPP			(0x0 << 20)
-#define VIDCON0_L0_DATA_18BPP16			(0x1 << 20)
-#define VIDCON0_L0_DATA_18BPP9			(0x2 << 20)
-#define VIDCON0_L0_DATA_24BPP			(0x3 << 20)
-#define VIDCON0_L0_DATA_18BPP			(0x4 << 20)
-#define VIDCON0_L0_DATA_16BPP8			(0x5 << 20)
-
-#define VIDCON0_PNRMODE_MASK			(0x3 << 17)
-#define VIDCON0_PNRMODE_SHIFT			(17)
-#define VIDCON0_PNRMODE_RGB			(0x0 << 17)
-#define VIDCON0_PNRMODE_BGR			(0x1 << 17)
-#define VIDCON0_PNRMODE_SERIAL_RGB		(0x2 << 17)
-#define VIDCON0_PNRMODE_SERIAL_BGR		(0x3 << 17)
-
-#define VIDCON0_CLKVALUP			(1 << 16)
-#define VIDCON0_CLKVAL_F_MASK			(0xff << 6)
-#define VIDCON0_CLKVAL_F_SHIFT			(6)
-#define VIDCON0_CLKVAL_F_LIMIT			(0xff)
-#define VIDCON0_CLKVAL_F(_x)			((_x) << 6)
-#define VIDCON0_VLCKFREE			(1 << 5)
-#define VIDCON0_CLKDIR				(1 << 4)
-
-#define VIDCON0_CLKSEL_MASK			(0x3 << 2)
-#define VIDCON0_CLKSEL_SHIFT			(2)
-#define VIDCON0_CLKSEL_HCLK			(0x0 << 2)
-#define VIDCON0_CLKSEL_LCD			(0x1 << 2)
-#define VIDCON0_CLKSEL_27M			(0x3 << 2)
-
-#define VIDCON0_ENVID				(1 << 1)
-#define VIDCON0_ENVID_F				(1 << 0)
-
-#define VIDCON1					(0x04)
-#define VIDCON1_LINECNT_MASK			(0x7ff << 16)
-#define VIDCON1_LINECNT_SHIFT			(16)
-#define VIDCON1_LINECNT_GET(_v)			(((_v) >> 16) & 0x7ff)
-#define VIDCON1_VSTATUS_MASK			(0x3 << 13)
-#define VIDCON1_VSTATUS_SHIFT			(13)
-#define VIDCON1_VSTATUS_VSYNC			(0x0 << 13)
-#define VIDCON1_VSTATUS_BACKPORCH		(0x1 << 13)
-#define VIDCON1_VSTATUS_ACTIVE			(0x2 << 13)
-#define VIDCON1_VSTATUS_FRONTPORCH		(0x0 << 13)
-
-#define VIDCON1_INV_VCLK			(1 << 7)
-#define VIDCON1_INV_HSYNC			(1 << 6)
-#define VIDCON1_INV_VSYNC			(1 << 5)
-#define VIDCON1_INV_VDEN			(1 << 4)
-
-/* VIDCON2 */
-
-#define VIDCON2					(0x08)
-#define VIDCON2_EN601				(1 << 23)
-#define VIDCON2_TVFMTSEL_SW			(1 << 14)
-
-#define VIDCON2_TVFMTSEL1_MASK			(0x3 << 12)
-#define VIDCON2_TVFMTSEL1_SHIFT			(12)
-#define VIDCON2_TVFMTSEL1_RGB			(0x0 << 12)
-#define VIDCON2_TVFMTSEL1_YUV422		(0x1 << 12)
-#define VIDCON2_TVFMTSEL1_YUV444		(0x2 << 12)
-
-#define VIDCON2_ORGYCbCr			(1 << 8)
-#define VIDCON2_YUVORDCrCb			(1 << 7)
-
-/* VIDTCON0 */
-
-#define VIDTCON0_VBPDE_MASK			(0xff << 24)
-#define VIDTCON0_VBPDE_SHIFT			(24)
-#define VIDTCON0_VBPDE_LIMIT			(0xff)
-#define VIDTCON0_VBPDE(_x)			((_x) << 24)
-
-#define VIDTCON0_VBPD_MASK			(0xff << 16)
-#define VIDTCON0_VBPD_SHIFT			(16)
-#define VIDTCON0_VBPD_LIMIT			(0xff)
-#define VIDTCON0_VBPD(_x)			((_x) << 16)
-
-#define VIDTCON0_VFPD_MASK			(0xff << 8)
-#define VIDTCON0_VFPD_SHIFT			(8)
-#define VIDTCON0_VFPD_LIMIT			(0xff)
-#define VIDTCON0_VFPD(_x)			((_x) << 8)
-
-#define VIDTCON0_VSPW_MASK			(0xff << 0)
-#define VIDTCON0_VSPW_SHIFT			(0)
-#define VIDTCON0_VSPW_LIMIT			(0xff)
-#define VIDTCON0_VSPW(_x)			((_x) << 0)
-
-/* VIDTCON1 */
-
-#define VIDTCON1_VFPDE_MASK			(0xff << 24)
-#define VIDTCON1_VFPDE_SHIFT			(24)
-#define VIDTCON1_VFPDE_LIMIT			(0xff)
-#define VIDTCON1_VFPDE(_x)			((_x) << 24)
-
-#define VIDTCON1_HBPD_MASK			(0xff << 16)
-#define VIDTCON1_HBPD_SHIFT			(16)
-#define VIDTCON1_HBPD_LIMIT			(0xff)
-#define VIDTCON1_HBPD(_x)			((_x) << 16)
-
-#define VIDTCON1_HFPD_MASK			(0xff << 8)
-#define VIDTCON1_HFPD_SHIFT			(8)
-#define VIDTCON1_HFPD_LIMIT			(0xff)
-#define VIDTCON1_HFPD(_x)			((_x) << 8)
-
-#define VIDTCON1_HSPW_MASK			(0xff << 0)
-#define VIDTCON1_HSPW_SHIFT			(0)
-#define VIDTCON1_HSPW_LIMIT			(0xff)
-#define VIDTCON1_HSPW(_x)			((_x) << 0)
-
-#define VIDTCON2				(0x18)
-#define VIDTCON2_LINEVAL_MASK			(0x7ff << 11)
-#define VIDTCON2_LINEVAL_SHIFT			(11)
-#define VIDTCON2_LINEVAL_LIMIT			(0x7ff)
-#define VIDTCON2_LINEVAL(_x)			((_x) << 11)
-
-#define VIDTCON2_HOZVAL_MASK			(0x7ff << 0)
-#define VIDTCON2_HOZVAL_SHIFT			(0)
-#define VIDTCON2_HOZVAL_LIMIT			(0x7ff)
-#define VIDTCON2_HOZVAL(_x)			((_x) << 0)
-
-/* WINCONx */
-
-
-#define WINCONx_BITSWP				(1 << 18)
-#define WINCONx_BYTSWP				(1 << 17)
-#define WINCONx_HAWSWP				(1 << 16)
-#define WINCONx_BURSTLEN_MASK			(0x3 << 9)
-#define WINCONx_BURSTLEN_SHIFT			(9)
-#define WINCONx_BURSTLEN_16WORD			(0x0 << 9)
-#define WINCONx_BURSTLEN_8WORD			(0x1 << 9)
-#define WINCONx_BURSTLEN_4WORD			(0x2 << 9)
-
-#define WINCONx_ENWIN				(1 << 0)
-#define WINCON0_BPPMODE_MASK			(0xf << 2)
-#define WINCON0_BPPMODE_SHIFT			(2)
-#define WINCON0_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON0_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON0_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON0_BPPMODE_8BPP_PALETTE		(0x3 << 2)
-#define WINCON0_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON0_BPPMODE_16BPP_1555		(0x7 << 2)
-#define WINCON0_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON0_BPPMODE_24BPP_888		(0xb << 2)
-
-#define WINCON1_BLD_PIX				(1 << 6)
-
-#define WINCON1_ALPHA_SEL			(1 << 1)
-#define WINCON1_BPPMODE_MASK			(0xf << 2)
-#define WINCON1_BPPMODE_SHIFT			(2)
-#define WINCON1_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON1_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON1_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON1_BPPMODE_8BPP_PALETTE		(0x3 << 2)
-#define WINCON1_BPPMODE_8BPP_1232		(0x4 << 2)
-#define WINCON1_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON1_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON1_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON1_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON1_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON1_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON1_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON1_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON1_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON1_BPPMODE_28BPP_A4888		(0xd << 2)
-
-
-#define VIDOSDxA_TOPLEFT_X_MASK			(0x7ff << 11)
-#define VIDOSDxA_TOPLEFT_X_SHIFT		(11)
-#define VIDOSDxA_TOPLEFT_X_LIMIT		(0x7ff)
-#define VIDOSDxA_TOPLEFT_X(_x)			((_x) << 11)
-
-#define VIDOSDxA_TOPLEFT_Y_MASK			(0x7ff << 0)
-#define VIDOSDxA_TOPLEFT_Y_SHIFT		(0)
-#define VIDOSDxA_TOPLEFT_Y_LIMIT		(0x7ff)
-#define VIDOSDxA_TOPLEFT_Y(_x)			((_x) << 0)
-
-#define VIDOSDxB_BOTRIGHT_X_MASK		(0x7ff << 11)
-#define VIDOSDxB_BOTRIGHT_X_SHIFT		(11)
-#define VIDOSDxB_BOTRIGHT_X_LIMIT		(0x7ff)
-#define VIDOSDxB_BOTRIGHT_X(_x)			((_x) << 11)
-
-#define VIDOSDxB_BOTRIGHT_Y_MASK		(0x7ff << 0)
-#define VIDOSDxB_BOTRIGHT_Y_SHIFT		(0)
-#define VIDOSDxB_BOTRIGHT_Y_LIMIT		(0x7ff)
-#define VIDOSDxB_BOTRIGHT_Y(_x)			((_x) << 0)
-
-/* For VIDOSD[1..4]C */
-#define VIDISD14C_ALPHA0_R(_x)			((_x) << 20)
-#define VIDISD14C_ALPHA0_G_MASK			(0xf << 16)
-#define VIDISD14C_ALPHA0_G_SHIFT		(16)
-#define VIDISD14C_ALPHA0_G_LIMIT		(0xf)
-#define VIDISD14C_ALPHA0_G(_x)			((_x) << 16)
-#define VIDISD14C_ALPHA0_B_MASK			(0xf << 12)
-#define VIDISD14C_ALPHA0_B_SHIFT		(12)
-#define VIDISD14C_ALPHA0_B_LIMIT		(0xf)
-#define VIDISD14C_ALPHA0_B(_x)			((_x) << 12)
-#define VIDISD14C_ALPHA1_R_MASK			(0xf << 8)
-#define VIDISD14C_ALPHA1_R_SHIFT		(8)
-#define VIDISD14C_ALPHA1_R_LIMIT		(0xf)
-#define VIDISD14C_ALPHA1_R(_x)			((_x) << 8)
-#define VIDISD14C_ALPHA1_G_MASK			(0xf << 4)
-#define VIDISD14C_ALPHA1_G_SHIFT		(4)
-#define VIDISD14C_ALPHA1_G_LIMIT		(0xf)
-#define VIDISD14C_ALPHA1_G(_x)			((_x) << 4)
-#define VIDISD14C_ALPHA1_B_MASK			(0xf << 0)
-#define VIDISD14C_ALPHA1_B_SHIFT		(0)
-#define VIDISD14C_ALPHA1_B_LIMIT		(0xf)
-#define VIDISD14C_ALPHA1_B(_x)			((_x) << 0)
-
-/* Video buffer addresses */
-#define VIDW_BUF_START(_buff)			(0xA0 + ((_buff) * 8))
-#define VIDW_BUF_START1(_buff)			(0xA4 + ((_buff) * 8))
-#define VIDW_BUF_END(_buff)			(0xD0 + ((_buff) * 8))
-#define VIDW_BUF_END1(_buff)			(0xD4 + ((_buff) * 8))
-#define VIDW_BUF_SIZE(_buff)			(0x100 + ((_buff) * 4))
-
-#define VIDW_BUF_SIZE_OFFSET_MASK		(0x1fff << 13)
-#define VIDW_BUF_SIZE_OFFSET_SHIFT		(13)
-#define VIDW_BUF_SIZE_OFFSET_LIMIT		(0x1fff)
-#define VIDW_BUF_SIZE_OFFSET(_x)		((_x) << 13)
-
-#define VIDW_BUF_SIZE_PAGEWIDTH_MASK		(0x1fff << 0)
-#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT		(0)
-#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT		(0x1fff)
-#define VIDW_BUF_SIZE_PAGEWIDTH(_x)		((_x) << 0)
-
-/* Interrupt controls and status */
-
-#define VIDINTCON0_FIFOINTERVAL_MASK		(0x3f << 20)
-#define VIDINTCON0_FIFOINTERVAL_SHIFT		(20)
-#define VIDINTCON0_FIFOINTERVAL_LIMIT		(0x3f)
-#define VIDINTCON0_FIFOINTERVAL(_x)		((_x) << 20)
-
-#define VIDINTCON0_INT_SYSMAINCON		(1 << 19)
-#define VIDINTCON0_INT_SYSSUBCON		(1 << 18)
-#define VIDINTCON0_INT_I80IFDONE		(1 << 17)
-
-#define VIDINTCON0_FRAMESEL0_MASK		(0x3 << 15)
-#define VIDINTCON0_FRAMESEL0_SHIFT		(15)
-#define VIDINTCON0_FRAMESEL0_BACKPORCH		(0x0 << 15)
-#define VIDINTCON0_FRAMESEL0_VSYNC		(0x1 << 15)
-#define VIDINTCON0_FRAMESEL0_ACTIVE		(0x2 << 15)
-#define VIDINTCON0_FRAMESEL0_FRONTPORCH		(0x3 << 15)
-
-#define VIDINTCON0_FRAMESEL1			(1 << 14)
-#define VIDINTCON0_FRAMESEL1_NONE		(0x0 << 14)
-#define VIDINTCON0_FRAMESEL1_BACKPORCH		(0x1 << 14)
-#define VIDINTCON0_FRAMESEL1_VSYNC		(0x2 << 14)
-#define VIDINTCON0_FRAMESEL1_FRONTPORCH		(0x3 << 14)
-
-#define VIDINTCON0_INT_FRAME			(1 << 12)
-#define VIDINTCON0_FIFIOSEL_MASK		(0x7f << 5)
-#define VIDINTCON0_FIFIOSEL_SHIFT		(5)
-#define VIDINTCON0_FIFIOSEL_WINDOW0		(0x1 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW1		(0x2 << 5)
-
-#define VIDINTCON0_FIFOLEVEL_MASK		(0x7 << 2)
-#define VIDINTCON0_FIFOLEVEL_SHIFT		(2)
-#define VIDINTCON0_FIFOLEVEL_TO25PC		(0x0 << 2)
-#define VIDINTCON0_FIFOLEVEL_TO50PC		(0x1 << 2)
-#define VIDINTCON0_FIFOLEVEL_TO75PC		(0x2 << 2)
-#define VIDINTCON0_FIFOLEVEL_EMPTY		(0x3 << 2)
-#define VIDINTCON0_FIFOLEVEL_FULL		(0x4 << 2)
-
-#define VIDINTCON0_INT_FIFO_MASK		(0x3 << 0)
-#define VIDINTCON0_INT_FIFO_SHIFT		(0)
-#define VIDINTCON0_INT_ENABLE			(1 << 0)
-
-#define VIDINTCON1				(0x134)
-#define VIDINTCON1_INT_I180			(1 << 2)
-#define VIDINTCON1_INT_FRAME			(1 << 1)
-#define VIDINTCON1_INT_FIFO			(1 << 0)
-
-/* Window colour-key control registers */
-
-#define WxKEYCON0_KEYBL_EN			(1 << 26)
-#define WxKEYCON0_KEYEN_F			(1 << 25)
-#define WxKEYCON0_DIRCON			(1 << 24)
-#define WxKEYCON0_COMPKEY_MASK			(0xffffff << 0)
-#define WxKEYCON0_COMPKEY_SHIFT			(0)
-#define WxKEYCON0_COMPKEY_LIMIT			(0xffffff)
-#define WxKEYCON0_COMPKEY(_x)			((_x) << 0)
-#define WxKEYCON1_COLVAL_MASK			(0xffffff << 0)
-#define WxKEYCON1_COLVAL_SHIFT			(0)
-#define WxKEYCON1_COLVAL_LIMIT			(0xffffff)
-#define WxKEYCON1_COLVAL(_x)			((_x) << 0)
-
-
-/* Window blanking (MAP) */
-
-#define WINxMAP_MAP				(1 << 24)
-#define WINxMAP_MAP_COLOUR_MASK			(0xffffff << 0)
-#define WINxMAP_MAP_COLOUR_SHIFT		(0)
-#define WINxMAP_MAP_COLOUR_LIMIT		(0xffffff)
-#define WINxMAP_MAP_COLOUR(_x)			((_x) << 0)
-
-#define WPALCON_PAL_UPDATE			(1 << 9)
-#define WPALCON_W1PAL_MASK			(0x7 << 3)
-#define WPALCON_W1PAL_SHIFT			(3)
-#define WPALCON_W1PAL_25BPP_A888		(0x0 << 3)
-#define WPALCON_W1PAL_24BPP			(0x1 << 3)
-#define WPALCON_W1PAL_19BPP_A666		(0x2 << 3)
-#define WPALCON_W1PAL_18BPP_A665		(0x3 << 3)
-#define WPALCON_W1PAL_18BPP			(0x4 << 3)
-#define WPALCON_W1PAL_16BPP_A555		(0x5 << 3)
-#define WPALCON_W1PAL_16BPP_565			(0x6 << 3)
-
-#define WPALCON_W0PAL_MASK			(0x7 << 0)
-#define WPALCON_W0PAL_SHIFT			(0)
-#define WPALCON_W0PAL_25BPP_A888		(0x0 << 0)
-#define WPALCON_W0PAL_24BPP			(0x1 << 0)
-#define WPALCON_W0PAL_19BPP_A666		(0x2 << 0)
-#define WPALCON_W0PAL_18BPP_A665		(0x3 << 0)
-#define WPALCON_W0PAL_18BPP			(0x4 << 0)
-#define WPALCON_W0PAL_16BPP_A555		(0x5 << 0)
-#define WPALCON_W0PAL_16BPP_565			(0x6 << 0)
-
diff --git a/arch/arm/plat-s3c/include/plat/regs-serial.h b/arch/arm/plat-s3c/include/plat/regs-serial.h
deleted file mode 100644
index 85d8904..0000000
--- a/arch/arm/plat-s3c/include/plat/regs-serial.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-serial.h
- *
- *  From linux/include/asm-arm/hardware/serial_s3c2410.h
- *
- *  Internal header file for Samsung S3C2410 serial ports (UART0-2)
- *
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *
- *  Additional defines, Copyright 2003 Simtec Electronics (linux@simtec.co.uk)
- *
- *  Adapted from:
- *
- *  Internal header file for MX1ADS serial ports (UART1 & 2)
- *
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef __ASM_ARM_REGS_SERIAL_H
-#define __ASM_ARM_REGS_SERIAL_H
-
-#define S3C24XX_VA_UART0      (S3C_VA_UART)
-#define S3C24XX_VA_UART1      (S3C_VA_UART + 0x4000 )
-#define S3C24XX_VA_UART2      (S3C_VA_UART + 0x8000 )
-#define S3C24XX_VA_UART3      (S3C_VA_UART + 0xC000 )
-
-#define S3C2410_PA_UART0      (S3C24XX_PA_UART)
-#define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
-#define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
-#define S3C2443_PA_UART3      (S3C24XX_PA_UART + 0xC000 )
-
-#define S3C2410_URXH	  (0x24)
-#define S3C2410_UTXH	  (0x20)
-#define S3C2410_ULCON	  (0x00)
-#define S3C2410_UCON	  (0x04)
-#define S3C2410_UFCON	  (0x08)
-#define S3C2410_UMCON	  (0x0C)
-#define S3C2410_UBRDIV	  (0x28)
-#define S3C2410_UTRSTAT	  (0x10)
-#define S3C2410_UERSTAT	  (0x14)
-#define S3C2410_UFSTAT	  (0x18)
-#define S3C2410_UMSTAT	  (0x1C)
-
-#define S3C2410_LCON_CFGMASK	  ((0xF<<3)|(0x3))
-
-#define S3C2410_LCON_CS5	  (0x0)
-#define S3C2410_LCON_CS6	  (0x1)
-#define S3C2410_LCON_CS7	  (0x2)
-#define S3C2410_LCON_CS8	  (0x3)
-#define S3C2410_LCON_CSMASK	  (0x3)
-
-#define S3C2410_LCON_PNONE	  (0x0)
-#define S3C2410_LCON_PEVEN	  (0x5 << 3)
-#define S3C2410_LCON_PODD	  (0x4 << 3)
-#define S3C2410_LCON_PMASK	  (0x7 << 3)
-
-#define S3C2410_LCON_STOPB	  (1<<2)
-#define S3C2410_LCON_IRM          (1<<6)
-
-#define S3C2440_UCON_CLKMASK	  (3<<10)
-#define S3C2440_UCON_PCLK	  (0<<10)
-#define S3C2440_UCON_UCLK	  (1<<10)
-#define S3C2440_UCON_PCLK2	  (2<<10)
-#define S3C2440_UCON_FCLK	  (3<<10)
-#define S3C2443_UCON_EPLL	  (3<<10)
-
-#define S3C6400_UCON_CLKMASK	(3<<10)
-#define S3C6400_UCON_PCLK	(0<<10)
-#define S3C6400_UCON_PCLK2	(2<<10)
-#define S3C6400_UCON_UCLK0	(1<<10)
-#define S3C6400_UCON_UCLK1	(3<<10)
-
-#define S3C2440_UCON2_FCLK_EN	  (1<<15)
-#define S3C2440_UCON0_DIVMASK	  (15 << 12)
-#define S3C2440_UCON1_DIVMASK	  (15 << 12)
-#define S3C2440_UCON2_DIVMASK	  (7 << 12)
-#define S3C2440_UCON_DIVSHIFT	  (12)
-
-#define S3C2412_UCON_CLKMASK	(3<<10)
-#define S3C2412_UCON_UCLK	(1<<10)
-#define S3C2412_UCON_USYSCLK	(3<<10)
-#define S3C2412_UCON_PCLK	(0<<10)
-#define S3C2412_UCON_PCLK2	(2<<10)
-
-#define S3C2410_UCON_UCLK	  (1<<10)
-#define S3C2410_UCON_SBREAK	  (1<<4)
-
-#define S3C2410_UCON_TXILEVEL	  (1<<9)
-#define S3C2410_UCON_RXILEVEL	  (1<<8)
-#define S3C2410_UCON_TXIRQMODE	  (1<<2)
-#define S3C2410_UCON_RXIRQMODE	  (1<<0)
-#define S3C2410_UCON_RXFIFO_TOI	  (1<<7)
-#define S3C2443_UCON_RXERR_IRQEN  (1<<6)
-#define S3C2443_UCON_LOOPBACK	  (1<<5)
-
-#define S3C2410_UCON_DEFAULT	  (S3C2410_UCON_TXILEVEL  | \
-				   S3C2410_UCON_RXILEVEL  | \
-				   S3C2410_UCON_TXIRQMODE | \
-				   S3C2410_UCON_RXIRQMODE | \
-				   S3C2410_UCON_RXFIFO_TOI)
-
-#define S3C2410_UFCON_FIFOMODE	  (1<<0)
-#define S3C2410_UFCON_TXTRIG0	  (0<<6)
-#define S3C2410_UFCON_RXTRIG8	  (1<<4)
-#define S3C2410_UFCON_RXTRIG12	  (2<<4)
-
-/* S3C2440 FIFO trigger levels */
-#define S3C2440_UFCON_RXTRIG1	  (0<<4)
-#define S3C2440_UFCON_RXTRIG8	  (1<<4)
-#define S3C2440_UFCON_RXTRIG16	  (2<<4)
-#define S3C2440_UFCON_RXTRIG32	  (3<<4)
-
-#define S3C2440_UFCON_TXTRIG0	  (0<<6)
-#define S3C2440_UFCON_TXTRIG16	  (1<<6)
-#define S3C2440_UFCON_TXTRIG32	  (2<<6)
-#define S3C2440_UFCON_TXTRIG48	  (3<<6)
-
-#define S3C2410_UFCON_RESETBOTH	  (3<<1)
-#define S3C2410_UFCON_RESETTX	  (1<<2)
-#define S3C2410_UFCON_RESETRX	  (1<<1)
-
-#define S3C2410_UFCON_DEFAULT	  (S3C2410_UFCON_FIFOMODE | \
-				   S3C2410_UFCON_TXTRIG0  | \
-				   S3C2410_UFCON_RXTRIG8 )
-
-#define	S3C2410_UMCOM_AFC	  (1<<4)
-#define	S3C2410_UMCOM_RTS_LOW	  (1<<0)
-
-#define S3C2412_UMCON_AFC_63	(0<<5)		/* same as s3c2443 */
-#define S3C2412_UMCON_AFC_56	(1<<5)
-#define S3C2412_UMCON_AFC_48	(2<<5)
-#define S3C2412_UMCON_AFC_40	(3<<5)
-#define S3C2412_UMCON_AFC_32	(4<<5)
-#define S3C2412_UMCON_AFC_24	(5<<5)
-#define S3C2412_UMCON_AFC_16	(6<<5)
-#define S3C2412_UMCON_AFC_8	(7<<5)
-
-#define S3C2410_UFSTAT_TXFULL	  (1<<9)
-#define S3C2410_UFSTAT_RXFULL	  (1<<8)
-#define S3C2410_UFSTAT_TXMASK	  (15<<4)
-#define S3C2410_UFSTAT_TXSHIFT	  (4)
-#define S3C2410_UFSTAT_RXMASK	  (15<<0)
-#define S3C2410_UFSTAT_RXSHIFT	  (0)
-
-/* UFSTAT S3C24A0 */
-#define S3C24A0_UFSTAT_TXFULL	  (1 << 14)
-#define S3C24A0_UFSTAT_RXFULL	  (1 << 6)
-#define S3C24A0_UFSTAT_TXMASK	  (63 << 8)
-#define S3C24A0_UFSTAT_TXSHIFT	  (8)
-#define S3C24A0_UFSTAT_RXMASK	  (63)
-#define S3C24A0_UFSTAT_RXSHIFT	  (0)
-
-/* UFSTAT S3C2443 same as S3C2440 */
-#define S3C2440_UFSTAT_TXFULL	  (1<<14)
-#define S3C2440_UFSTAT_RXFULL	  (1<<6)
-#define S3C2440_UFSTAT_TXSHIFT	  (8)
-#define S3C2440_UFSTAT_RXSHIFT	  (0)
-#define S3C2440_UFSTAT_TXMASK	  (63<<8)
-#define S3C2440_UFSTAT_RXMASK	  (63)
-
-#define S3C2410_UTRSTAT_TXE	  (1<<2)
-#define S3C2410_UTRSTAT_TXFE	  (1<<1)
-#define S3C2410_UTRSTAT_RXDR	  (1<<0)
-
-#define S3C2410_UERSTAT_OVERRUN	  (1<<0)
-#define S3C2410_UERSTAT_FRAME	  (1<<2)
-#define S3C2410_UERSTAT_BREAK	  (1<<3)
-#define S3C2443_UERSTAT_PARITY	  (1<<1)
-
-#define S3C2410_UERSTAT_ANY	  (S3C2410_UERSTAT_OVERRUN | \
-				   S3C2410_UERSTAT_FRAME | \
-				   S3C2410_UERSTAT_BREAK)
-
-#define S3C2410_UMSTAT_CTS	  (1<<0)
-#define S3C2410_UMSTAT_DeltaCTS	  (1<<2)
-
-#define S3C2443_DIVSLOT		  (0x2C)
-
-/* S3C64XX interrupt registers. */
-#define S3C64XX_UINTP		0x30
-#define S3C64XX_UINTSP		0x34
-#define S3C64XX_UINTM		0x38
-
-#ifndef __ASSEMBLY__
-
-/* struct s3c24xx_uart_clksrc
- *
- * this structure defines a named clock source that can be used for the
- * uart, so that the best clock can be selected for the requested baud
- * rate.
- *
- * min_baud and max_baud define the range of baud-rates this clock is
- * acceptable for, if they are both zero, it is assumed any baud rate that
- * can be generated from this clock will be used.
- *
- * divisor gives the divisor from the clock to the one seen by the uart
-*/
-
-struct s3c24xx_uart_clksrc {
-	const char	*name;
-	unsigned int	 divisor;
-	unsigned int	 min_baud;
-	unsigned int	 max_baud;
-};
-
-/* configuration structure for per-machine configurations for the
- * serial port
- *
- * the pointer is setup by the machine specific initialisation from the
- * arch/arm/mach-s3c2410/ directory.
-*/
-
-struct s3c2410_uartcfg {
-	unsigned char	   hwport;	 /* hardware port number */
-	unsigned char	   unused;
-	unsigned short	   flags;
-	upf_t		   uart_flags;	 /* default uart flags */
-
-	unsigned long	   ucon;	 /* value of ucon for port */
-	unsigned long	   ulcon;	 /* value of ulcon for port */
-	unsigned long	   ufcon;	 /* value of ufcon for port */
-
-	struct s3c24xx_uart_clksrc *clocks;
-	unsigned int		    clocks_size;
-};
-
-/* s3c24xx_uart_devs
- *
- * this is exported from the core as we cannot use driver_register(),
- * or platform_add_device() before the console_initcall()
-*/
-
-extern struct platform_device *s3c24xx_uart_devs[4];
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_ARM_REGS_SERIAL_H */
-
diff --git a/arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h b/arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h
deleted file mode 100644
index 36a85f5..0000000
--- a/arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      http://armlinux.simtec.co.uk/
- *      Ben Dooks <ben@simtec.co.uk>
- *
- * S3C - USB2.0 Highspeed/OtG device PHY registers
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* Note, this is a seperate header file as some of the clock framework
- * needs to touch this if the clk_48m is used as the USB OHCI or other
- * peripheral source.
-*/
-
-#ifndef __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H
-#define __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H __FILE__
-
-/* S3C64XX_PA_USB_HSPHY */
-
-#define S3C_HSOTG_PHYREG(x)	((x) + S3C_VA_USB_HSPHY)
-
-#define S3C_PHYPWR				S3C_HSOTG_PHYREG(0x00)
-#define SRC_PHYPWR_OTG_DISABLE			(1 << 4)
-#define SRC_PHYPWR_ANALOG_POWERDOWN		(1 << 3)
-#define SRC_PHYPWR_FORCE_SUSPEND		(1 << 1)
-
-#define S3C_PHYCLK				S3C_HSOTG_PHYREG(0x04)
-#define S3C_PHYCLK_MODE_USB11			(1 << 6)
-#define S3C_PHYCLK_EXT_OSC			(1 << 5)
-#define S3C_PHYCLK_CLK_FORCE			(1 << 4)
-#define S3C_PHYCLK_ID_PULL			(1 << 2)
-#define S3C_PHYCLK_CLKSEL_MASK			(0x3 << 0)
-#define S3C_PHYCLK_CLKSEL_SHIFT			(0)
-#define S3C_PHYCLK_CLKSEL_48M			(0x0 << 0)
-#define S3C_PHYCLK_CLKSEL_12M			(0x2 << 0)
-#define S3C_PHYCLK_CLKSEL_24M			(0x3 << 0)
-
-#define S3C_RSTCON				S3C_HSOTG_PHYREG(0x08)
-#define S3C_RSTCON_PHYCLK			(1 << 2)
-#define S3C_RSTCON_HCLK				(1 << 2)
-#define S3C_RSTCON_PHY				(1 << 0)
-
-#define S3C_PHYTUNE				S3C_HSOTG_PHYREG(0x20)
-
-#endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H */
diff --git a/arch/arm/plat-s3c/include/plat/sdhci.h b/arch/arm/plat-s3c/include/plat/sdhci.h
deleted file mode 100644
index 5319867..0000000
--- a/arch/arm/plat-s3c/include/plat/sdhci.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/* linux/arch/arm/plat-s3c/include/plat/sdhci.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C Platform - SDHCI (HSMMC) platform data definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __PLAT_S3C_SDHCI_H
-#define __PLAT_S3C_SDHCI_H __FILE__
-
-struct platform_device;
-struct mmc_host;
-struct mmc_card;
-struct mmc_ios;
-
-/**
- * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI
- * @max_width: The maximum number of data bits supported.
- * @host_caps: Standard MMC host capabilities bit field.
- * @cfg_gpio: Configure the GPIO for a specific card bit-width
- * @cfg_card: Configure the interface for a specific card and speed. This
- *            is necessary the controllers and/or GPIO blocks require the
- *	      changing of driver-strength and other controls dependant on
- *	      the card and speed of operation.
- *
- * Initialisation data specific to either the machine or the platform
- * for the device driver to use or call-back when configuring gpio or
- * card speed information.
-*/
-struct s3c_sdhci_platdata {
-	unsigned int	max_width;
-	unsigned int	host_caps;
-
-	char		**clocks;	/* set of clock sources */
-
-	void	(*cfg_gpio)(struct platform_device *dev, int width);
-	void	(*cfg_card)(struct platform_device *dev,
-			    void __iomem *regbase,
-			    struct mmc_ios *ios,
-			    struct mmc_card *card);
-};
-
-/**
- * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
- * @pd: Platform data to register to device.
- *
- * Register the given platform data for use withe S3C SDHCI device.
- * The call will copy the platform data, so the board definitions can
- * make the structure itself __initdata.
- */
-extern void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd);
-extern void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd);
-extern void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd);
-
-/* Default platform data, exported so that per-cpu initialisation can
- * set the correct one when there are more than one cpu type selected.
-*/
-
-extern struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata;
-extern struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata;
-extern struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata;
-
-/* Helper function availablity */
-
-extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-
-/* S3C6400 SDHCI setup */
-
-#ifdef CONFIG_S3C6400_SETUP_SDHCI
-extern char *s3c6400_hsmmc_clksrcs[4];
-
-#ifdef CONFIG_S3C_DEV_HSMMC
-extern void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
-					 void __iomem *r,
-					 struct mmc_ios *ios,
-					 struct mmc_card *card);
-
-static inline void s3c6400_default_sdhci0(void)
-{
-	s3c_hsmmc0_def_platdata.clocks = s3c6400_hsmmc_clksrcs;
-	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
-}
-
-#else
-static inline void s3c6400_default_sdhci0(void) { }
-#endif  /* CONFIG_S3C_DEV_HSMMC */
-
-#ifdef CONFIG_S3C_DEV_HSMMC1
-static inline void s3c6400_default_sdhci1(void)
-{
-	s3c_hsmmc1_def_platdata.clocks = s3c6400_hsmmc_clksrcs;
-	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
-}
-#else
-static inline void s3c6400_default_sdhci1(void) { }
-#endif /* CONFIG_S3C_DEV_HSMMC1 */
-
-#ifdef CONFIG_S3C_DEV_HSMMC2
-static inline void s3c6400_default_sdhci2(void)
-{
-	s3c_hsmmc2_def_platdata.clocks = s3c6400_hsmmc_clksrcs;
-	s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
-}
-#else
-static inline void s3c6400_default_sdhci2(void) { }
-#endif /* CONFIG_S3C_DEV_HSMMC2 */
-
-#else
-static inline void s3c6400_default_sdhci0(void) { }
-static inline void s3c6400_default_sdhci1(void) { }
-#endif /* CONFIG_S3C6400_SETUP_SDHCI */
-
-/* S3C6410 SDHCI setup */
-
-#ifdef CONFIG_S3C6410_SETUP_SDHCI
-extern char *s3c6410_hsmmc_clksrcs[4];
-
-extern void s3c6410_setup_sdhci0_cfg_card(struct platform_device *dev,
-					   void __iomem *r,
-					   struct mmc_ios *ios,
-					   struct mmc_card *card);
-
-#ifdef CONFIG_S3C_DEV_HSMMC
-static inline void s3c6410_default_sdhci0(void)
-{
-	s3c_hsmmc0_def_platdata.clocks = s3c6410_hsmmc_clksrcs;
-	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card;
-}
-#else
-static inline void s3c6410_default_sdhci0(void) { }
-#endif /* CONFIG_S3C_DEV_HSMMC */
-
-#ifdef CONFIG_S3C_DEV_HSMMC1
-static inline void s3c6410_default_sdhci1(void)
-{
-	s3c_hsmmc1_def_platdata.clocks = s3c6410_hsmmc_clksrcs;
-	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card;
-}
-#else
-static inline void s3c6410_default_sdhci1(void) { }
-#endif /* CONFIG_S3C_DEV_HSMMC1 */
-
-#ifdef CONFIG_S3C_DEV_HSMMC2
-static inline void s3c6410_default_sdhci2(void)
-{
-	s3c_hsmmc2_def_platdata.clocks = s3c6410_hsmmc_clksrcs;
-	s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s3c6410_setup_sdhci0_cfg_card;
-}
-#else
-static inline void s3c6410_default_sdhci2(void) { }
-#endif /* CONFIG_S3C_DEV_HSMMC2 */
-
-#else
-static inline void s3c6410_default_sdhci0(void) { }
-static inline void s3c6410_default_sdhci1(void) { }
-#endif /* CONFIG_S3C6410_SETUP_SDHCI */
-
-/* S5PC100 SDHCI setup */
-
-#ifdef CONFIG_S5PC100_SETUP_SDHCI
-extern char *s5pc100_hsmmc_clksrcs[4];
-
-extern void s5pc100_setup_sdhci0_cfg_card(struct platform_device *dev,
-					   void __iomem *r,
-					   struct mmc_ios *ios,
-					   struct mmc_card *card);
-
-#ifdef CONFIG_S3C_DEV_HSMMC
-static inline void s5pc100_default_sdhci0(void)
-{
-	s3c_hsmmc0_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
-	s3c_hsmmc0_def_platdata.cfg_gpio = s5pc100_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
-}
-#else
-static inline void s5pc100_default_sdhci0(void) { }
-#endif /* CONFIG_S3C_DEV_HSMMC */
-
-#ifdef CONFIG_S3C_DEV_HSMMC1
-static inline void s5pc100_default_sdhci1(void)
-{
-	s3c_hsmmc1_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
-	s3c_hsmmc1_def_platdata.cfg_gpio = s5pc100_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
-}
-#else
-static inline void s5pc100_default_sdhci1(void) { }
-#endif /* CONFIG_S3C_DEV_HSMMC1 */
-
-#ifdef CONFIG_S3C_DEV_HSMMC2
-static inline void s5pc100_default_sdhci2(void)
-{
-	s3c_hsmmc2_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
-	s3c_hsmmc2_def_platdata.cfg_gpio = s5pc100_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
-}
-#else
-static inline void s5pc100_default_sdhci2(void) { }
-#endif /* CONFIG_S3C_DEV_HSMMC1 */
-
-
-#else
-static inline void s5pc100_default_sdhci0(void) { }
-static inline void s5pc100_default_sdhci1(void) { }
-static inline void s5pc100_default_sdhci2(void) { }
-#endif /* CONFIG_S5PC100_SETUP_SDHCI */
-
-#endif /* __PLAT_S3C_SDHCI_H */
diff --git a/arch/arm/plat-s3c/include/plat/udc-hs.h b/arch/arm/plat-s3c/include/plat/udc-hs.h
deleted file mode 100644
index dd04db0..0000000
--- a/arch/arm/plat-s3c/include/plat/udc-hs.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/udc-hs.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C USB2.0 High-speed / OtG platform information
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-enum s3c_hostg_dmamode {
-	S3C_HSOTG_DMA_NONE,	/* do not use DMA at-all */
-	S3C_HSOTG_DMA_ONLY,	/* always use DMA */
-	S3C_HSOTG_DMA_DRV,	/* DMA is chosen by driver */
-};
-
-/**
- * struct s3c_hsotg_plat - platform data for high-speed otg/udc
- * @dma: Whether to use DMA or not.
- * @is_osc: The clock source is an oscillator, not a crystal
- */
-struct s3c_hsotg_plat {
-	enum s3c_hostg_dmamode	dma;
-	unsigned int		is_osc : 1;
-};
diff --git a/arch/arm/plat-s3c/include/plat/uncompress.h b/arch/arm/plat-s3c/include/plat/uncompress.h
deleted file mode 100644
index dc66a47..0000000
--- a/arch/arm/plat-s3c/include/plat/uncompress.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/* linux/include/asm-arm/plat-s3c/uncompress.h
- *
- * Copyright 2003, 2007 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C - uncompress code
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_UNCOMPRESS_H
-#define __ASM_PLAT_UNCOMPRESS_H
-
-typedef unsigned int upf_t;	/* cannot include linux/serial_core.h */
-
-/* uart setup */
-
-static unsigned int fifo_mask;
-static unsigned int fifo_max;
-
-/* forward declerations */
-
-static void arch_detect_cpu(void);
-
-/* defines for UART registers */
-
-#include <plat/regs-serial.h>
-#include <plat/regs-watchdog.h>
-
-/* working in physical space... */
-#undef S3C2410_WDOGREG
-#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x)))
-
-/* how many bytes we allow into the FIFO at a time in FIFO mode */
-#define FIFO_MAX	 (14)
-
-#define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT)
-
-static __inline__ void
-uart_wr(unsigned int reg, unsigned int val)
-{
-	volatile unsigned int *ptr;
-
-	ptr = (volatile unsigned int *)(reg + uart_base);
-	*ptr = val;
-}
-
-static __inline__ unsigned int
-uart_rd(unsigned int reg)
-{
-	volatile unsigned int *ptr;
-
-	ptr = (volatile unsigned int *)(reg + uart_base);
-	return *ptr;
-}
-
-/* we can deal with the case the UARTs are being run
- * in FIFO mode, so that we don't hold up our execution
- * waiting for tx to happen...
-*/
-
-static void putc(int ch)
-{
-	if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
-		int level;
-
-		while (1) {
-			level = uart_rd(S3C2410_UFSTAT);
-			level &= fifo_mask;
-
-			if (level < fifo_max)
-				break;
-		}
-
-	} else {
-		/* not using fifos */
-
-		while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
-			barrier();
-	}
-
-	/* write byte to transmission register */
-	uart_wr(S3C2410_UTXH, ch);
-}
-
-static inline void flush(void)
-{
-}
-
-#define __raw_writel(d, ad)			\
-	do {							\
-		*((volatile unsigned int __force *)(ad)) = (d); \
-	} while (0)
-
-/* CONFIG_S3C_BOOT_WATCHDOG
- *
- * Simple boot-time watchdog setup, to reboot the system if there is
- * any problem with the boot process
-*/
-
-#ifdef CONFIG_S3C_BOOT_WATCHDOG
-
-#define WDOG_COUNT (0xff00)
-
-static inline void arch_decomp_wdog(void)
-{
-	__raw_writel(WDOG_COUNT, S3C2410_WTCNT);
-}
-
-static void arch_decomp_wdog_start(void)
-{
-	__raw_writel(WDOG_COUNT, S3C2410_WTDAT);
-	__raw_writel(WDOG_COUNT, S3C2410_WTCNT);
-	__raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON);
-}
-
-#else
-#define arch_decomp_wdog_start()
-#define arch_decomp_wdog()
-#endif
-
-#ifdef CONFIG_S3C_BOOT_ERROR_RESET
-
-static void arch_decomp_error(const char *x)
-{
-	putstr("\n\n");
-	putstr(x);
-	putstr("\n\n -- System resetting\n");
-
-	__raw_writel(0x4000, S3C2410_WTDAT);
-	__raw_writel(0x4000, S3C2410_WTCNT);
-	__raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
-
-	while(1);
-}
-
-#define arch_error arch_decomp_error
-#endif
-
-static void error(char *err);
-
-#ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO
-static inline void arch_enable_uart_fifo(void)
-{
-	u32 fifocon = uart_rd(S3C2410_UFCON);
-
-	if (!(fifocon & S3C2410_UFCON_FIFOMODE)) {
-		fifocon |= S3C2410_UFCON_RESETBOTH;
-		uart_wr(S3C2410_UFCON, fifocon);
-
-		/* wait for fifo reset to complete */
-		while (1) {
-			fifocon = uart_rd(S3C2410_UFCON);
-			if (!(fifocon & S3C2410_UFCON_RESETBOTH))
-				break;
-		}
-	}
-}
-#else
-#define arch_enable_uart_fifo() do { } while(0)
-#endif
-
-
-static void
-arch_decomp_setup(void)
-{
-	/* we may need to setup the uart(s) here if we are not running
-	 * on an BAST... the BAST will have left the uarts configured
-	 * after calling linux.
-	 */
-
-	arch_detect_cpu();
-	arch_decomp_wdog_start();
-
-	/* Enable the UART FIFOs if they where not enabled and our
-	 * configuration says we should turn them on.
-	 */
-
-	arch_enable_uart_fifo();
-}
-
-
-#endif /* __ASM_PLAT_UNCOMPRESS_H */
diff --git a/arch/arm/plat-s3c/include/plat/usb-control.h b/arch/arm/plat-s3c/include/plat/usb-control.h
deleted file mode 100644
index 822c87f..0000000
--- a/arch/arm/plat-s3c/include/plat/usb-control.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/usb-control.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C - USB host port information
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_USBCONTROL_H
-#define __ASM_ARCH_USBCONTROL_H
-
-#define S3C_HCDFLG_USED	(1)
-
-struct s3c2410_hcd_port {
-	unsigned char	flags;
-	unsigned char	power;
-	unsigned char	oc_status;
-	unsigned char	oc_changed;
-};
-
-struct s3c2410_hcd_info {
-	struct usb_hcd		*hcd;
-	struct s3c2410_hcd_port	port[2];
-
-	void		(*power_control)(int port, int to);
-	void		(*enable_oc)(struct s3c2410_hcd_info *, int on);
-	void		(*report_oc)(struct s3c2410_hcd_info *, int ports);
-};
-
-static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports)
-{
-	if (info->report_oc != NULL) {
-		(info->report_oc)(info, ports);
-	}
-}
-
-#endif /*__ASM_ARCH_USBCONTROL_H */
diff --git a/arch/arm/plat-s3c/pm-check.c b/arch/arm/plat-s3c/pm-check.c
deleted file mode 100644
index 8eb1f43..0000000
--- a/arch/arm/plat-s3c/pm-check.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/* linux/arch/arm/plat-s3c/pm-check.c
- *  originally in linux/arch/arm/plat-s3c24xx/pm.c
- *
- * Copyright (c) 2004-2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C Power Mangament - suspend/resume memory corruptiuon check.
- *
- * This program is free software; you can redistribute it 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/suspend.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-#include <linux/ioport.h>
-
-#include <plat/pm.h>
-
-#if CONFIG_S3C2410_PM_CHECK_CHUNKSIZE < 1
-#error CONFIG_S3C2410_PM_CHECK_CHUNKSIZE must be a positive non-zero value
-#endif
-
-/* suspend checking code...
- *
- * this next area does a set of crc checks over all the installed
- * memory, so the system can verify if the resume was ok.
- *
- * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
- * increasing it will mean that the area corrupted will be less easy to spot,
- * and reducing the size will cause the CRC save area to grow
-*/
-
-#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
-
-static u32 crc_size;	/* size needed for the crc block */
-static u32 *crcs;	/* allocated over suspend/resume */
-
-typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
-
-/* s3c_pm_run_res
- *
- * go through the given resource list, and look for system ram
-*/
-
-static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
-{
-	while (ptr != NULL) {
-		if (ptr->child != NULL)
-			s3c_pm_run_res(ptr->child, fn, arg);
-
-		if ((ptr->flags & IORESOURCE_MEM) &&
-		    strcmp(ptr->name, "System RAM") == 0) {
-			S3C_PMDBG("Found system RAM at %08lx..%08lx\n",
-				  (unsigned long)ptr->start,
-				  (unsigned long)ptr->end);
-			arg = (fn)(ptr, arg);
-		}
-
-		ptr = ptr->sibling;
-	}
-}
-
-static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg)
-{
-	s3c_pm_run_res(&iomem_resource, fn, arg);
-}
-
-static u32 *s3c_pm_countram(struct resource *res, u32 *val)
-{
-	u32 size = (u32)(res->end - res->start)+1;
-
-	size += CHECK_CHUNKSIZE-1;
-	size /= CHECK_CHUNKSIZE;
-
-	S3C_PMDBG("Area %08lx..%08lx, %d blocks\n",
-		  (unsigned long)res->start, (unsigned long)res->end, size);
-
-	*val += size * sizeof(u32);
-	return val;
-}
-
-/* s3c_pm_prepare_check
- *
- * prepare the necessary information for creating the CRCs. This
- * must be done before the final save, as it will require memory
- * allocating, and thus touching bits of the kernel we do not
- * know about.
-*/
-
-void s3c_pm_check_prepare(void)
-{
-	crc_size = 0;
-
-	s3c_pm_run_sysram(s3c_pm_countram, &crc_size);
-
-	S3C_PMDBG("s3c_pm_prepare_check: %u checks needed\n", crc_size);
-
-	crcs = kmalloc(crc_size+4, GFP_KERNEL);
-	if (crcs == NULL)
-		printk(KERN_ERR "Cannot allocated CRC save area\n");
-}
-
-static u32 *s3c_pm_makecheck(struct resource *res, u32 *val)
-{
-	unsigned long addr, left;
-
-	for (addr = res->start; addr < res->end;
-	     addr += CHECK_CHUNKSIZE) {
-		left = res->end - addr;
-
-		if (left > CHECK_CHUNKSIZE)
-			left = CHECK_CHUNKSIZE;
-
-		*val = crc32_le(~0, phys_to_virt(addr), left);
-		val++;
-	}
-
-	return val;
-}
-
-/* s3c_pm_check_store
- *
- * compute the CRC values for the memory blocks before the final
- * sleep.
-*/
-
-void s3c_pm_check_store(void)
-{
-	if (crcs != NULL)
-		s3c_pm_run_sysram(s3c_pm_makecheck, crcs);
-}
-
-/* in_region
- *
- * return TRUE if the area defined by ptr..ptr+size contains the
- * what..what+whatsz
-*/
-
-static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
-{
-	if ((what+whatsz) < ptr)
-		return 0;
-
-	if (what > (ptr+size))
-		return 0;
-
-	return 1;
-}
-
-/**
- * s3c_pm_runcheck() - helper to check a resource on restore.
- * @res: The resource to check
- * @vak: Pointer to list of CRC32 values to check.
- *
- * Called from the s3c_pm_check_restore() via s3c_pm_run_sysram(), this
- * function runs the given memory resource checking it against the stored
- * CRC to ensure that memory is restored. The function tries to skip as
- * many of the areas used during the suspend process.
- */
-static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
-{
-	void *save_at = phys_to_virt(s3c_sleep_save_phys);
-	unsigned long addr;
-	unsigned long left;
-	void *stkpage;
-	void *ptr;
-	u32 calc;
-
-	stkpage = (void *)((u32)&calc & ~PAGE_MASK);
-
-	for (addr = res->start; addr < res->end;
-	     addr += CHECK_CHUNKSIZE) {
-		left = res->end - addr;
-
-		if (left > CHECK_CHUNKSIZE)
-			left = CHECK_CHUNKSIZE;
-
-		ptr = phys_to_virt(addr);
-
-		if (in_region(ptr, left, stkpage, 4096)) {
-			S3C_PMDBG("skipping %08lx, has stack in\n", addr);
-			goto skip_check;
-		}
-
-		if (in_region(ptr, left, crcs, crc_size)) {
-			S3C_PMDBG("skipping %08lx, has crc block in\n", addr);
-			goto skip_check;
-		}
-
-		if (in_region(ptr, left, save_at, 32*4 )) {
-			S3C_PMDBG("skipping %08lx, has save block in\n", addr);
-			goto skip_check;
-		}
-
-		/* calculate and check the checksum */
-
-		calc = crc32_le(~0, ptr, left);
-		if (calc != *val) {
-			printk(KERN_ERR "Restore CRC error at "
-			       "%08lx (%08x vs %08x)\n", addr, calc, *val);
-
-			S3C_PMDBG("Restore CRC error at %08lx (%08x vs %08x)\n",
-			    addr, calc, *val);
-		}
-
-	skip_check:
-		val++;
-	}
-
-	return val;
-}
-
-/**
- * s3c_pm_check_restore() - memory check called on resume
- *
- * check the CRCs after the restore event and free the memory used
- * to hold them
-*/
-void s3c_pm_check_restore(void)
-{
-	if (crcs != NULL)
-		s3c_pm_run_sysram(s3c_pm_runcheck, crcs);
-}
-
-/**
- * s3c_pm_check_cleanup() - free memory resources
- *
- * Free the resources that where allocated by the suspend
- * memory check code. We do this separately from the
- * s3c_pm_check_restore() function as we cannot call any
- * functions that might sleep during that resume.
- */
-void s3c_pm_check_cleanup(void)
-{
-	kfree(crcs);
-	crcs = NULL;
-}
-
diff --git a/arch/arm/plat-s3c/pm-gpio.c b/arch/arm/plat-s3c/pm-gpio.c
deleted file mode 100644
index cfd326a..0000000
--- a/arch/arm/plat-s3c/pm-gpio.c
+++ /dev/null
@@ -1,380 +0,0 @@
-
-/* linux/arch/arm/plat-s3c/pm-gpio.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO PM code
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/sysdev.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/gpio-core.h>
-#include <plat/pm.h>
-
-/* PM GPIO helpers */
-
-#define OFFS_CON	(0x00)
-#define OFFS_DAT	(0x04)
-#define OFFS_UP		(0x08)
-
-static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
-{
-	chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
-	chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
-}
-
-static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
-{
-	void __iomem *base = chip->base;
-	u32 old_gpcon = __raw_readl(base + OFFS_CON);
-	u32 old_gpdat = __raw_readl(base + OFFS_DAT);
-	u32 gps_gpcon = chip->pm_save[0];
-	u32 gps_gpdat = chip->pm_save[1];
-	u32 gpcon;
-
-	/* GPACON only has one bit per control / data and no PULLUPs.
-	 * GPACON[x] = 0 => Output, 1 => SFN */
-
-	/* first set all SFN bits to SFN */
-
-	gpcon = old_gpcon | gps_gpcon;
-	__raw_writel(gpcon, base + OFFS_CON);
-
-	/* now set all the other bits */
-
-	__raw_writel(gps_gpdat, base + OFFS_DAT);
-	__raw_writel(gps_gpcon, base + OFFS_CON);
-
-	S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
-		  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
-}
-
-struct s3c_gpio_pm s3c_gpio_pm_1bit = {
-	.save	= s3c_gpio_pm_1bit_save,
-	.resume = s3c_gpio_pm_1bit_resume,
-};
-
-static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
-{
-	chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
-	chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
-	chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
-}
-
-/* Test whether the given masked+shifted bits of an GPIO configuration
- * are one of the SFN (special function) modes. */
-
-static inline int is_sfn(unsigned long con)
-{
-	return con >= 2;
-}
-
-/* Test if the given masked+shifted GPIO configuration is an input */
-
-static inline int is_in(unsigned long con)
-{
-	return con == 0;
-}
-
-/* Test if the given masked+shifted GPIO configuration is an output */
-
-static inline int is_out(unsigned long con)
-{
-	return con == 1;
-}
-
-/**
- * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
- * @chip: The chip information to resume.
- *
- * Restore one of the GPIO banks that was saved during suspend. This is
- * not as simple as once thought, due to the possibility of glitches
- * from the order that the CON and DAT registers are set in.
- *
- * The three states the pin can be are {IN,OUT,SFN} which gives us 9
- * combinations of changes to check. Three of these, if the pin stays
- * in the same configuration can be discounted. This leaves us with
- * the following:
- *
- * { IN => OUT }  Change DAT first
- * { IN => SFN }  Change CON first
- * { OUT => SFN } Change CON first, so new data will not glitch
- * { OUT => IN }  Change CON first, so new data will not glitch
- * { SFN => IN }  Change CON first
- * { SFN => OUT } Change DAT first, so new data will not glitch [1]
- *
- * We do not currently deal with the UP registers as these control
- * weak resistors, so a small delay in change should not need to bring
- * these into the calculations.
- *
- * [1] this assumes that writing to a pin DAT whilst in SFN will set the
- *     state for when it is next output.
- */
-static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
-{
-	void __iomem *base = chip->base;
-	u32 old_gpcon = __raw_readl(base + OFFS_CON);
-	u32 old_gpdat = __raw_readl(base + OFFS_DAT);
-	u32 gps_gpcon = chip->pm_save[0];
-	u32 gps_gpdat = chip->pm_save[1];
-	u32 gpcon, old, new, mask;
-	u32 change_mask = 0x0;
-	int nr;
-
-	/* restore GPIO pull-up settings */
-	__raw_writel(chip->pm_save[2], base + OFFS_UP);
-
-	/* Create a change_mask of all the items that need to have
-	 * their CON value changed before their DAT value, so that
-	 * we minimise the work between the two settings.
-	 */
-
-	for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
-		old = (old_gpcon & mask) >> nr;
-		new = (gps_gpcon & mask) >> nr;
-
-		/* If there is no change, then skip */
-
-		if (old == new)
-			continue;
-
-		/* If both are special function, then skip */
-
-		if (is_sfn(old) && is_sfn(new))
-			continue;
-
-		/* Change is IN => OUT, do not change now */
-
-		if (is_in(old) && is_out(new))
-			continue;
-
-		/* Change is SFN => OUT, do not change now */
-
-		if (is_sfn(old) && is_out(new))
-			continue;
-
-		/* We should now be at the case of IN=>SFN,
-		 * OUT=>SFN, OUT=>IN, SFN=>IN. */
-
-		change_mask |= mask;
-	}
-
-
-	/* Write the new CON settings */
-
-	gpcon = old_gpcon & ~change_mask;
-	gpcon |= gps_gpcon & change_mask;
-
-	__raw_writel(gpcon, base + OFFS_CON);
-
-	/* Now change any items that require DAT,CON */
-
-	__raw_writel(gps_gpdat, base + OFFS_DAT);
-	__raw_writel(gps_gpcon, base + OFFS_CON);
-
-	S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
-		  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
-}
-
-struct s3c_gpio_pm s3c_gpio_pm_2bit = {
-	.save	= s3c_gpio_pm_2bit_save,
-	.resume = s3c_gpio_pm_2bit_resume,
-};
-
-#ifdef CONFIG_ARCH_S3C64XX
-static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
-{
-	chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
-	chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
-	chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
-
-	if (chip->chip.ngpio > 8)
-		chip->pm_save[0] = __raw_readl(chip->base - 4);
-}
-
-static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
-{
-	u32 old, new, mask;
-	u32 change_mask = 0x0;
-	int nr;
-
-	for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
-		old = (old_gpcon & mask) >> nr;
-		new = (gps_gpcon & mask) >> nr;
-
-		/* If there is no change, then skip */
-
-		if (old == new)
-			continue;
-
-		/* If both are special function, then skip */
-
-		if (is_sfn(old) && is_sfn(new))
-			continue;
-
-		/* Change is IN => OUT, do not change now */
-
-		if (is_in(old) && is_out(new))
-			continue;
-
-		/* Change is SFN => OUT, do not change now */
-
-		if (is_sfn(old) && is_out(new))
-			continue;
-
-		/* We should now be at the case of IN=>SFN,
-		 * OUT=>SFN, OUT=>IN, SFN=>IN. */
-
-		change_mask |= mask;
-	}
-
-	return change_mask;
-}
-
-static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
-{
-	void __iomem *con = chip->base + (index * 4);
-	u32 old_gpcon = __raw_readl(con);
-	u32 gps_gpcon = chip->pm_save[index + 1];
-	u32 gpcon, mask;
-
-	mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
-
-	gpcon = old_gpcon & ~mask;
-	gpcon |= gps_gpcon & mask;
-
-	__raw_writel(gpcon, con);
-}
-
-static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
-{
-	void __iomem *base = chip->base;
-	u32 old_gpcon[2];
-	u32 old_gpdat = __raw_readl(base + OFFS_DAT);
-	u32 gps_gpdat = chip->pm_save[2];
-
-	/* First, modify the CON settings */
-
-	old_gpcon[0] = 0;
-	old_gpcon[1] = __raw_readl(base + OFFS_CON);
-
-	s3c_gpio_pm_4bit_con(chip, 0);
-	if (chip->chip.ngpio > 8) {
-		old_gpcon[0] = __raw_readl(base - 4);
-		s3c_gpio_pm_4bit_con(chip, -1);
-	}
-
-	/* Now change the configurations that require DAT,CON */
-
-	__raw_writel(chip->pm_save[2], base + OFFS_DAT);
-	__raw_writel(chip->pm_save[1], base + OFFS_CON);
-	if (chip->chip.ngpio > 8)
-		__raw_writel(chip->pm_save[0], base - 4);
-
-	__raw_writel(chip->pm_save[2], base + OFFS_DAT);
-	__raw_writel(chip->pm_save[3], base + OFFS_UP);
-
-	if (chip->chip.ngpio > 8) {
-		S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
-			  chip->chip.label, old_gpcon[0], old_gpcon[1],
-			  __raw_readl(base - 4),
-			  __raw_readl(base + OFFS_CON),
-			  old_gpdat, gps_gpdat);
-	} else
-		S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
-			  chip->chip.label, old_gpcon[1],
-			  __raw_readl(base + OFFS_CON),
-			  old_gpdat, gps_gpdat);
-}
-
-struct s3c_gpio_pm s3c_gpio_pm_4bit = {
-	.save	= s3c_gpio_pm_4bit_save,
-	.resume = s3c_gpio_pm_4bit_resume,
-};
-#endif /* CONFIG_ARCH_S3C64XX */
-
-/**
- * s3c_pm_save_gpio() - save gpio chip data for suspend
- * @ourchip: The chip for suspend.
- */
-static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
-{
-	struct s3c_gpio_pm *pm = ourchip->pm;
-
-	if (pm == NULL || pm->save == NULL)
-		S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
-	else
-		pm->save(ourchip);
-}
-
-/**
- * s3c_pm_save_gpios() - Save the state of the GPIO banks.
- *
- * For all the GPIO banks, save the state of each one ready for going
- * into a suspend mode.
- */
-void s3c_pm_save_gpios(void)
-{
-	struct s3c_gpio_chip *ourchip;
-	unsigned int gpio_nr;
-
-	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
-		ourchip = s3c_gpiolib_getchip(gpio_nr);
-		if (!ourchip)
-			continue;
-
-		s3c_pm_save_gpio(ourchip);
-
-		S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
-			  ourchip->chip.label,
-			  ourchip->pm_save[0],
-			  ourchip->pm_save[1],
-			  ourchip->pm_save[2],
-			  ourchip->pm_save[3]);
-
-		gpio_nr += ourchip->chip.ngpio;
-		gpio_nr += CONFIG_S3C_GPIO_SPACE;
-	}
-}
-
-/**
- * s3c_pm_resume_gpio() - restore gpio chip data after suspend
- * @ourchip: The suspended chip.
- */
-static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
-{
-	struct s3c_gpio_pm *pm = ourchip->pm;
-
-	if (pm == NULL || pm->resume == NULL)
-		S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
-	else
-		pm->resume(ourchip);
-}
-
-void s3c_pm_restore_gpios(void)
-{
-	struct s3c_gpio_chip *ourchip;
-	unsigned int gpio_nr;
-
-	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
-		ourchip = s3c_gpiolib_getchip(gpio_nr);
-		if (!ourchip)
-			continue;
-
-		s3c_pm_resume_gpio(ourchip);
-
-		gpio_nr += ourchip->chip.ngpio;
-		gpio_nr += CONFIG_S3C_GPIO_SPACE;
-	}
-}
diff --git a/arch/arm/plat-s3c/pm.c b/arch/arm/plat-s3c/pm.c
deleted file mode 100644
index 7674706..0000000
--- a/arch/arm/plat-s3c/pm.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/* linux/arch/arm/plat-s3c/pm.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2004-2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C common power management (suspend to ram) support.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/suspend.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
-#include <linux/io.h>
-
-#include <asm/cacheflush.h>
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-irq.h>
-#include <asm/irq.h>
-
-#include <plat/pm.h>
-#include <plat/pm-core.h>
-
-/* for external use */
-
-unsigned long s3c_pm_flags;
-
-/* Debug code:
- *
- * This code supports debug output to the low level UARTs for use on
- * resume before the console layer is available.
-*/
-
-#ifdef CONFIG_S3C2410_PM_DEBUG
-extern void printascii(const char *);
-
-void s3c_pm_dbg(const char *fmt, ...)
-{
-	va_list va;
-	char buff[256];
-
-	va_start(va, fmt);
-	vsprintf(buff, fmt, va);
-	va_end(va);
-
-	printascii(buff);
-}
-
-static inline void s3c_pm_debug_init(void)
-{
-	/* restart uart clocks so we can use them to output */
-	s3c_pm_debug_init_uart();
-}
-
-#else
-#define s3c_pm_debug_init() do { } while(0)
-
-#endif /* CONFIG_S3C2410_PM_DEBUG */
-
-/* Save the UART configurations if we are configured for debug. */
-
-unsigned char pm_uart_udivslot;
-
-#ifdef CONFIG_S3C2410_PM_DEBUG
-
-struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
-
-static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
-{
-	void __iomem *regs = S3C_VA_UARTx(uart);
-
-	save->ulcon = __raw_readl(regs + S3C2410_ULCON);
-	save->ucon = __raw_readl(regs + S3C2410_UCON);
-	save->ufcon = __raw_readl(regs + S3C2410_UFCON);
-	save->umcon = __raw_readl(regs + S3C2410_UMCON);
-	save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
-
-	if (pm_uart_udivslot)
-		save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
-
-	S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
-		  uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
-}
-
-static void s3c_pm_save_uarts(void)
-{
-	struct pm_uart_save *save = uart_save;
-	unsigned int uart;
-
-	for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
-		s3c_pm_save_uart(uart, save);
-}
-
-static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
-{
-	void __iomem *regs = S3C_VA_UARTx(uart);
-
-	s3c_pm_arch_update_uart(regs, save);
-
-	__raw_writel(save->ulcon, regs + S3C2410_ULCON);
-	__raw_writel(save->ucon,  regs + S3C2410_UCON);
-	__raw_writel(save->ufcon, regs + S3C2410_UFCON);
-	__raw_writel(save->umcon, regs + S3C2410_UMCON);
-	__raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
-
-	if (pm_uart_udivslot)
-		__raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
-}
-
-static void s3c_pm_restore_uarts(void)
-{
-	struct pm_uart_save *save = uart_save;
-	unsigned int uart;
-
-	for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
-		s3c_pm_restore_uart(uart, save);
-}
-#else
-static void s3c_pm_save_uarts(void) { }
-static void s3c_pm_restore_uarts(void) { }
-#endif
-
-/* The IRQ ext-int code goes here, it is too small to currently bother
- * with its own file. */
-
-unsigned long s3c_irqwake_intmask	= 0xffffffffL;
-unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
-
-int s3c_irqext_wake(unsigned int irqno, unsigned int state)
-{
-	unsigned long bit = 1L << IRQ_EINT_BIT(irqno);
-
-	if (!(s3c_irqwake_eintallow & bit))
-		return -ENOENT;
-
-	printk(KERN_INFO "wake %s for irq %d\n",
-	       state ? "enabled" : "disabled", irqno);
-
-	if (!state)
-		s3c_irqwake_eintmask |= bit;
-	else
-		s3c_irqwake_eintmask &= ~bit;
-
-	return 0;
-}
-
-/* helper functions to save and restore register state */
-
-/**
- * s3c_pm_do_save() - save a set of registers for restoration on resume.
- * @ptr: Pointer to an array of registers.
- * @count: Size of the ptr array.
- *
- * Run through the list of registers given, saving their contents in the
- * array for later restoration when we wakeup.
- */
-void s3c_pm_do_save(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		ptr->val = __raw_readl(ptr->reg);
-		S3C_PMDBG("saved %p value %08lx\n", ptr->reg, ptr->val);
-	}
-}
-
-/**
- * s3c_pm_do_restore() - restore register values from the save list.
- * @ptr: Pointer to an array of registers.
- * @count: Size of the ptr array.
- *
- * Restore the register values saved from s3c_pm_do_save().
- *
- * Note, we do not use S3C_PMDBG() in here, as the system may not have
- * restore the UARTs state yet
-*/
-
-void s3c_pm_do_restore(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
-		       ptr->reg, ptr->val, __raw_readl(ptr->reg));
-
-		__raw_writel(ptr->val, ptr->reg);
-	}
-}
-
-/**
- * s3c_pm_do_restore_core() - early restore register values from save list.
- *
- * This is similar to s3c_pm_do_restore() except we try and minimise the
- * side effects of the function in case registers that hardware might need
- * to work has been restored.
- *
- * WARNING: Do not put any debug in here that may effect memory or use
- * peripherals, as things may be changing!
-*/
-
-void s3c_pm_do_restore_core(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++)
-		__raw_writel(ptr->val, ptr->reg);
-}
-
-/* s3c2410_pm_show_resume_irqs
- *
- * print any IRQs asserted at resume time (ie, we woke from)
-*/
-static void s3c_pm_show_resume_irqs(int start, unsigned long which,
-				    unsigned long mask)
-{
-	int i;
-
-	which &= ~mask;
-
-	for (i = 0; i <= 31; i++) {
-		if (which & (1L<<i)) {
-			S3C_PMDBG("IRQ %d asserted at resume\n", start+i);
-		}
-	}
-}
-
-
-void (*pm_cpu_prep)(void);
-void (*pm_cpu_sleep)(void);
-
-#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
-
-/* s3c_pm_enter
- *
- * central control for sleep/resume process
-*/
-
-static int s3c_pm_enter(suspend_state_t state)
-{
-	static unsigned long regs_save[16];
-
-	/* ensure the debug is initialised (if enabled) */
-
-	s3c_pm_debug_init();
-
-	S3C_PMDBG("%s(%d)\n", __func__, state);
-
-	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
-		printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__);
-		return -EINVAL;
-	}
-
-	/* check if we have anything to wake-up with... bad things seem
-	 * to happen if you suspend with no wakeup (system will often
-	 * require a full power-cycle)
-	*/
-
-	if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
-	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
-		printk(KERN_ERR "%s: No wake-up sources!\n", __func__);
-		printk(KERN_ERR "%s: Aborting sleep\n", __func__);
-		return -EINVAL;
-	}
-
-	/* store the physical address of the register recovery block */
-
-	s3c_sleep_save_phys = virt_to_phys(regs_save);
-
-	S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys);
-
-	/* save all necessary core registers not covered by the drivers */
-
-	s3c_pm_save_gpios();
-	s3c_pm_save_uarts();
-	s3c_pm_save_core();
-
-	/* set the irq configuration for wake */
-
-	s3c_pm_configure_extint();
-
-	S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n",
-	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
-
-	s3c_pm_arch_prepare_irqs();
-
-	/* call cpu specific preparation */
-
-	pm_cpu_prep();
-
-	/* flush cache back to ram */
-
-	flush_cache_all();
-
-	s3c_pm_check_store();
-
-	/* send the cpu to sleep... */
-
-	s3c_pm_arch_stop_clocks();
-
-	/* s3c_cpu_save will also act as our return point from when
-	 * we resume as it saves its own register state and restores it
-	 * during the resume.  */
-
-	s3c_cpu_save(regs_save);
-
-	/* restore the cpu state using the kernel's cpu init code. */
-
-	cpu_init();
-
-	/* restore the system state */
-
-	s3c_pm_restore_core();
-	s3c_pm_restore_uarts();
-	s3c_pm_restore_gpios();
-
-	s3c_pm_debug_init();
-
-	/* check what irq (if any) restored the system */
-
-	s3c_pm_arch_show_resume_irqs();
-
-	S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
-
-	/* LEDs should now be 1110 */
-	s3c_pm_debug_smdkled(1 << 1, 0);
-
-	s3c_pm_check_restore();
-
-	/* ok, let's return from sleep */
-
-	S3C_PMDBG("S3C PM Resume (post-restore)\n");
-	return 0;
-}
-
-/* callback from assembly code */
-void s3c_pm_cb_flushcache(void)
-{
-	flush_cache_all();
-}
-
-static int s3c_pm_prepare(void)
-{
-	/* prepare check area if configured */
-
-	s3c_pm_check_prepare();
-	return 0;
-}
-
-static void s3c_pm_finish(void)
-{
-	s3c_pm_check_cleanup();
-}
-
-static struct platform_suspend_ops s3c_pm_ops = {
-	.enter		= s3c_pm_enter,
-	.prepare	= s3c_pm_prepare,
-	.finish		= s3c_pm_finish,
-	.valid		= suspend_valid_only_mem,
-};
-
-/* s3c_pm_init
- *
- * Attach the power management functions. This should be called
- * from the board specific initialisation if the board supports
- * it.
-*/
-
-int __init s3c_pm_init(void)
-{
-	printk("S3C Power Management, Copyright 2004 Simtec Electronics\n");
-
-	suspend_set_ops(&s3c_pm_ops);
-	return 0;
-}
diff --git a/arch/arm/plat-s3c/pwm-clock.c b/arch/arm/plat-s3c/pwm-clock.c
deleted file mode 100644
index a318215..0000000
--- a/arch/arm/plat-s3c/pwm-clock.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/pwm-clock.c
- *
- * Copyright (c) 2007 Simtec Electronics
- * Copyright (c) 2007, 2008 Ben Dooks
- *	Ben Dooks <ben-linux@fluff.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.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/log2.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <asm/irq.h>
-
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-#include <plat/regs-timer.h>
-#include <mach/pwm-clock.h>
-
-/* Each of the timers 0 through 5 go through the following
- * clock tree, with the inputs depending on the timers.
- *
- * pclk ---- [ prescaler 0 ] -+---> timer 0
- *			      +---> timer 1
- *
- * pclk ---- [ prescaler 1 ] -+---> timer 2
- *			      +---> timer 3
- *			      \---> timer 4
- *
- * Which are fed into the timers as so:
- *
- * prescaled 0 ---- [ div 2,4,8,16 ] ---\
- *				       [mux] -> timer 0
- * tclk 0 ------------------------------/
- *
- * prescaled 0 ---- [ div 2,4,8,16 ] ---\
- *				       [mux] -> timer 1
- * tclk 0 ------------------------------/
- *
- *
- * prescaled 1 ---- [ div 2,4,8,16 ] ---\
- *				       [mux] -> timer 2
- * tclk 1 ------------------------------/
- *
- * prescaled 1 ---- [ div 2,4,8,16 ] ---\
- *				       [mux] -> timer 3
- * tclk 1 ------------------------------/
- *
- * prescaled 1 ---- [ div 2,4,8, 16 ] --\
- *				       [mux] -> timer 4
- * tclk 1 ------------------------------/
- *
- * Since the mux and the divider are tied together in the
- * same register space, it is impossible to set the parent
- * and the rate at the same time. To avoid this, we add an
- * intermediate 'prescaled-and-divided' clock to select
- * as the parent for the timer input clock called tdiv.
- *
- * prescaled clk --> pwm-tdiv ---\
- *                             [ mux ] --> timer X
- * tclk -------------------------/
-*/
-
-static struct clk clk_timer_scaler[];
-
-static unsigned long clk_pwm_scaler_get_rate(struct clk *clk)
-{
-	unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0);
-
-	if (clk == &clk_timer_scaler[1]) {
-		tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK;
-		tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT;
-	} else {
-		tcfg0 &= S3C2410_TCFG_PRESCALER0_MASK;
-	}
-
-	return clk_get_rate(clk->parent) / (tcfg0 + 1);
-}
-
-static unsigned long clk_pwm_scaler_round_rate(struct clk *clk,
-					       unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long divisor = parent_rate / rate;
-
-	if (divisor > 256)
-		divisor = 256;
-	else if (divisor < 2)
-		divisor = 2;
-
-	return parent_rate / divisor;
-}
-
-static int clk_pwm_scaler_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long round = clk_pwm_scaler_round_rate(clk, rate);
-	unsigned long tcfg0;
-	unsigned long divisor;
-	unsigned long flags;
-
-	divisor = clk_get_rate(clk->parent) / round;
-	divisor--;
-
-	local_irq_save(flags);
-	tcfg0 = __raw_readl(S3C2410_TCFG0);
-
-	if (clk == &clk_timer_scaler[1]) {
-		tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
-		tcfg0 |= divisor << S3C2410_TCFG_PRESCALER1_SHIFT;
-	} else {
-		tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
-		tcfg0 |= divisor;
-	}
-
-	__raw_writel(tcfg0, S3C2410_TCFG0);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static struct clk clk_timer_scaler[] = {
-	[0]	= {
-		.name		= "pwm-scaler0",
-		.id		= -1,
-		.get_rate	= clk_pwm_scaler_get_rate,
-		.set_rate	= clk_pwm_scaler_set_rate,
-		.round_rate	= clk_pwm_scaler_round_rate,
-	},
-	[1]	= {
-		.name		= "pwm-scaler1",
-		.id		= -1,
-		.get_rate	= clk_pwm_scaler_get_rate,
-		.set_rate	= clk_pwm_scaler_set_rate,
-		.round_rate	= clk_pwm_scaler_round_rate,
-	},
-};
-
-static struct clk clk_timer_tclk[] = {
-	[0]	= {
-		.name		= "pwm-tclk0",
-		.id		= -1,
-	},
-	[1]	= {
-		.name		= "pwm-tclk1",
-		.id		= -1,
-	},
-};
-
-struct pwm_tdiv_clk {
-	struct clk	clk;
-	unsigned int	divisor;
-};
-
-static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk)
-{
-	return container_of(clk, struct pwm_tdiv_clk, clk);
-}
-
-static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk)
-{
-	unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
-	unsigned int divisor;
-
-	tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
-	tcfg1 &= S3C2410_TCFG1_MUX_MASK;
-
-	if (pwm_cfg_src_is_tclk(tcfg1))
-		divisor = to_tdiv(clk)->divisor;
-	else
-		divisor = tcfg_to_divisor(tcfg1);
-
-	return clk_get_rate(clk->parent) / divisor;
-}
-
-static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk,
-					     unsigned long rate)
-{
-	unsigned long parent_rate;
-	unsigned long divisor;
-
-	parent_rate = clk_get_rate(clk->parent);
-	divisor = parent_rate / rate;
-
-	if (divisor <= 1 && pwm_tdiv_has_div1())
-		divisor = 1;
-	else if (divisor <= 2)
-		divisor = 2;
-	else if (divisor <= 4)
-		divisor = 4;
-	else if (divisor <= 8)
-		divisor = 8;
-	else
-		divisor = 16;
-
-	return parent_rate / divisor;
-}
-
-static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk)
-{
-	return pwm_tdiv_div_bits(divclk->divisor);
-}
-
-static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk)
-{
-	unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
-	unsigned long bits = clk_pwm_tdiv_bits(divclk);
-	unsigned long flags;
-	unsigned long shift =  S3C2410_TCFG1_SHIFT(divclk->clk.id);
-
-	local_irq_save(flags);
-
-	tcfg1 = __raw_readl(S3C2410_TCFG1);
-	tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
-	tcfg1 |= bits << shift;
-	__raw_writel(tcfg1, S3C2410_TCFG1);
-
-	local_irq_restore(flags);
-}
-
-static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate)
-{
-	struct pwm_tdiv_clk *divclk = to_tdiv(clk);
-	unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	unsigned long divisor;
-
-	tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
-	tcfg1 &= S3C2410_TCFG1_MUX_MASK;
-
-	rate = clk_round_rate(clk, rate);
-	divisor = parent_rate / rate;
-
-	if (divisor > 16)
-		return -EINVAL;
-
-	divclk->divisor = divisor;
-
-	/* Update the current MUX settings if we are currently
-	 * selected as the clock source for this clock. */
-
-	if (!pwm_cfg_src_is_tclk(tcfg1))
-		clk_pwm_tdiv_update(divclk);
-
-	return 0;
-}
-
-static struct pwm_tdiv_clk clk_timer_tdiv[] = {
-	[0]	= {
-		.clk	= {
-			.name		= "pwm-tdiv",
-			.parent		= &clk_timer_scaler[0],
-			.get_rate	= clk_pwm_tdiv_get_rate,
-			.set_rate	= clk_pwm_tdiv_set_rate,
-			.round_rate	= clk_pwm_tdiv_round_rate,
-		},
-	},
-	[1]	= {
-		.clk	= {
-			.name		= "pwm-tdiv",
-			.parent		= &clk_timer_scaler[0],
-			.get_rate	= clk_pwm_tdiv_get_rate,
-			.set_rate	= clk_pwm_tdiv_set_rate,
-			.round_rate	= clk_pwm_tdiv_round_rate,
-		}
-	},
-	[2]	= {
-		.clk	= {
-			.name		= "pwm-tdiv",
-			.parent		= &clk_timer_scaler[1],
-			.get_rate	= clk_pwm_tdiv_get_rate,
-			.set_rate	= clk_pwm_tdiv_set_rate,
-			.round_rate	= clk_pwm_tdiv_round_rate,
-		},
-	},
-	[3]	= {
-		.clk	= {
-			.name		= "pwm-tdiv",
-			.parent		= &clk_timer_scaler[1],
-			.get_rate	= clk_pwm_tdiv_get_rate,
-			.set_rate	= clk_pwm_tdiv_set_rate,
-			.round_rate	= clk_pwm_tdiv_round_rate,
-		},
-	},
-	[4]	= {
-		.clk	= {
-			.name		= "pwm-tdiv",
-			.parent		= &clk_timer_scaler[1],
-			.get_rate	= clk_pwm_tdiv_get_rate,
-			.set_rate	= clk_pwm_tdiv_set_rate,
-			.round_rate	= clk_pwm_tdiv_round_rate,
-		},
-	},
-};
-
-static int __init clk_pwm_tdiv_register(unsigned int id)
-{
-	struct pwm_tdiv_clk *divclk = &clk_timer_tdiv[id];
-	unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
-
-	tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
-	tcfg1 &= S3C2410_TCFG1_MUX_MASK;
-
-	divclk->clk.id = id;
-	divclk->divisor = tcfg_to_divisor(tcfg1);
-
-	return s3c24xx_register_clock(&divclk->clk);
-}
-
-static inline struct clk *s3c24xx_pwmclk_tclk(unsigned int id)
-{
-	return (id >= 2) ? &clk_timer_tclk[1] : &clk_timer_tclk[0];
-}
-
-static inline struct clk *s3c24xx_pwmclk_tdiv(unsigned int id)
-{
-	return &clk_timer_tdiv[id].clk;
-}
-
-static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent)
-{
-	unsigned int id = clk->id;
-	unsigned long tcfg1;
-	unsigned long flags;
-	unsigned long bits;
-	unsigned long shift = S3C2410_TCFG1_SHIFT(id);
-
-	if (parent == s3c24xx_pwmclk_tclk(id))
-		bits = S3C_TCFG1_MUX_TCLK << shift;
-	else if (parent == s3c24xx_pwmclk_tdiv(id))
-		bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	local_irq_save(flags);
-
-	tcfg1 = __raw_readl(S3C2410_TCFG1);
-	tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
-	__raw_writel(tcfg1 | bits, S3C2410_TCFG1);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-static struct clk clk_tin[] = {
-	[0]	= {
-		.name		= "pwm-tin",
-		.id		= 0,
-		.set_parent	= clk_pwm_tin_set_parent,
-	},
-	[1]	= {
-		.name		= "pwm-tin",
-		.id		= 1,
-		.set_parent	= clk_pwm_tin_set_parent,
-	},
-	[2]	= {
-		.name		= "pwm-tin",
-		.id		= 2,
-		.set_parent	= clk_pwm_tin_set_parent,
-	},
-	[3]	= {
-		.name		= "pwm-tin",
-		.id		= 3,
-		.set_parent	= clk_pwm_tin_set_parent,
-	},
-	[4]	= {
-		.name		= "pwm-tin",
-		.id		= 4,
-		.set_parent	= clk_pwm_tin_set_parent,
-	},
-};
-
-static __init int clk_pwm_tin_register(struct clk *pwm)
-{
-	unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
-	unsigned int id = pwm->id;
-
-	struct clk *parent;
-	int ret;
-
-	ret = s3c24xx_register_clock(pwm);
-	if (ret < 0)
-		return ret;
-
-	tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
-	tcfg1 &= S3C2410_TCFG1_MUX_MASK;
-
-	if (pwm_cfg_src_is_tclk(tcfg1))
-		parent = s3c24xx_pwmclk_tclk(id);
-	else
-		parent = s3c24xx_pwmclk_tdiv(id);
-
-	return clk_set_parent(pwm, parent);
-}
-
-/**
- * s3c_pwmclk_init() - initialise pwm clocks
- *
- * Initialise and register the clocks which provide the inputs for the
- * pwm timer blocks.
- *
- * Note, this call is required by the time core, so must be called after
- * the base clocks are added and before any of the initcalls are run.
- */
-__init void s3c_pwmclk_init(void)
-{
-	struct clk *clk_timers;
-	unsigned int clk;
-	int ret;
-
-	clk_timers = clk_get(NULL, "timers");
-	if (IS_ERR(clk_timers)) {
-		printk(KERN_ERR "%s: no parent clock\n", __func__);
-		return;
-	}
-
-	for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) {
-		clk_timer_scaler[clk].parent = clk_timers;
-		ret = s3c24xx_register_clock(&clk_timer_scaler[clk]);
-		if (ret < 0) {
-			printk(KERN_ERR "error adding pwm scaler%d clock\n", clk);
-			return;
-		}
-	}
-
-	for (clk = 0; clk < ARRAY_SIZE(clk_timer_tclk); clk++) {
-		ret = s3c24xx_register_clock(&clk_timer_tclk[clk]);
-		if (ret < 0) {
-			printk(KERN_ERR "error adding pww tclk%d\n", clk);
-			return;
-		}
-	}
-
-	for (clk = 0; clk < ARRAY_SIZE(clk_timer_tdiv); clk++) {
-		ret = clk_pwm_tdiv_register(clk);
-		if (ret < 0) {
-			printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk);
-			return;
-		}
-	}
-
-	for (clk = 0; clk < ARRAY_SIZE(clk_tin); clk++) {
-		ret = clk_pwm_tin_register(&clk_tin[clk]);
-		if (ret < 0) {
-			printk(KERN_ERR "error adding pwm%d tin clock\n", clk);
-			return;
-		}
-	}
-}
diff --git a/arch/arm/plat-s3c/time.c b/arch/arm/plat-s3c/time.c
deleted file mode 100644
index 3b27b29..0000000
--- a/arch/arm/plat-s3c/time.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/time.c
- *
- * Copyright (C) 2003-2005 Simtec Electronics
- *	Ben Dooks, <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-
-#include <asm/system.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-#include <asm/irq.h>
-#include <mach/map.h>
-#include <plat/regs-timer.h>
-#include <mach/regs-irq.h>
-#include <asm/mach/time.h>
-#include <mach/tick.h>
-
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-static unsigned long timer_startval;
-static unsigned long timer_usec_ticks;
-
-#ifndef TICK_MAX
-#define TICK_MAX (0xffff)
-#endif
-
-#define TIMER_USEC_SHIFT 16
-
-/* we use the shifted arithmetic to work out the ratio of timer ticks
- * to usecs, as often the peripheral clock is not a nice even multiple
- * of 1MHz.
- *
- * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok
- * for the current HZ value of 200 without producing overflows.
- *
- * Original patch by Dimitry Andric, updated by Ben Dooks
-*/
-
-
-/* timer_mask_usec_ticks
- *
- * given a clock and divisor, make the value to pass into timer_ticks_to_usec
- * to scale the ticks into usecs
-*/
-
-static inline unsigned long
-timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk)
-{
-	unsigned long den = pclk / 1000;
-
-	return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den;
-}
-
-/* timer_ticks_to_usec
- *
- * convert timer ticks to usec.
-*/
-
-static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
-{
-	unsigned long res;
-
-	res = ticks * timer_usec_ticks;
-	res += 1 << (TIMER_USEC_SHIFT - 4);	/* round up slightly */
-
-	return res >> TIMER_USEC_SHIFT;
-}
-
-/***
- * Returns microsecond  since last clock interrupt.  Note that interrupts
- * will have been disabled by do_gettimeoffset()
- * IRQs are disabled before entering here from do_gettimeofday()
- */
-
-static unsigned long s3c2410_gettimeoffset (void)
-{
-	unsigned long tdone;
-	unsigned long tval;
-
-	/* work out how many ticks have gone since last timer interrupt */
-
-	tval =  __raw_readl(S3C2410_TCNTO(4));
-	tdone = timer_startval - tval;
-
-	/* check to see if there is an interrupt pending */
-
-	if (s3c24xx_ostimer_pending()) {
-		/* re-read the timer, and try and fix up for the missed
-		 * interrupt. Note, the interrupt may go off before the
-		 * timer has re-loaded from wrapping.
-		 */
-
-		tval =  __raw_readl(S3C2410_TCNTO(4));
-		tdone = timer_startval - tval;
-
-		if (tval != 0)
-			tdone += timer_startval;
-	}
-
-	return timer_ticks_to_usec(tdone);
-}
-
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-s3c2410_timer_interrupt(int irq, void *dev_id)
-{
-	timer_tick();
-	return IRQ_HANDLED;
-}
-
-static struct irqaction s3c2410_timer_irq = {
-	.name		= "S3C2410 Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= s3c2410_timer_interrupt,
-};
-
-#define use_tclk1_12() ( \
-	machine_is_bast()	|| \
-	machine_is_vr1000()	|| \
-	machine_is_anubis()	|| \
-	machine_is_osiris())
-
-static struct clk *tin;
-static struct clk *tdiv;
-static struct clk *timerclk;
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- *
- * Currently we only use timer4, as it is the only timer which has no
- * other function that can be exploited externally
- */
-static void s3c2410_timer_setup (void)
-{
-	unsigned long tcon;
-	unsigned long tcnt;
-	unsigned long tcfg1;
-	unsigned long tcfg0;
-
-	tcnt = TICK_MAX;  /* default value for tcnt */
-
-	/* configure the system for whichever machine is in use */
-
-	if (use_tclk1_12()) {
-		/* timer is at 12MHz, scaler is 1 */
-		timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
-		tcnt = 12000000 / HZ;
-
-		tcfg1 = __raw_readl(S3C2410_TCFG1);
-		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
-		tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
-		__raw_writel(tcfg1, S3C2410_TCFG1);
-	} else {
-		unsigned long pclk;
-		struct clk *tscaler;
-
-		/* for the h1940 (and others), we use the pclk from the core
-		 * to generate the timer values. since values around 50 to
-		 * 70MHz are not values we can directly generate the timer
-		 * value from, we need to pre-scale and divide before using it.
-		 *
-		 * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz
-		 * (8.45 ticks per usec)
-		 */
-
-		pclk = clk_get_rate(timerclk);
-
-		/* configure clock tick */
-
-		timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
-
-		tscaler = clk_get_parent(tdiv);
-
-		clk_set_rate(tscaler, pclk / 3);
-		clk_set_rate(tdiv, pclk / 6);
-		clk_set_parent(tin, tdiv);
-
-		tcnt = clk_get_rate(tin) / HZ;
-	}
-
-	tcon = __raw_readl(S3C2410_TCON);
-	tcfg0 = __raw_readl(S3C2410_TCFG0);
-	tcfg1 = __raw_readl(S3C2410_TCFG1);
-
-	/* timers reload after counting zero, so reduce the count by 1 */
-
-	tcnt--;
-
-	printk(KERN_DEBUG "timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n",
-	       tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks);
-
-	/* check to see if timer is within 16bit range... */
-	if (tcnt > TICK_MAX) {
-		panic("setup_timer: HZ is too small, cannot configure timer!");
-		return;
-	}
-
-	__raw_writel(tcfg1, S3C2410_TCFG1);
-	__raw_writel(tcfg0, S3C2410_TCFG0);
-
-	timer_startval = tcnt;
-	__raw_writel(tcnt, S3C2410_TCNTB(4));
-
-	/* ensure timer is stopped... */
-
-	tcon &= ~(7<<20);
-	tcon |= S3C2410_TCON_T4RELOAD;
-	tcon |= S3C2410_TCON_T4MANUALUPD;
-
-	__raw_writel(tcon, S3C2410_TCON);
-	__raw_writel(tcnt, S3C2410_TCNTB(4));
-	__raw_writel(tcnt, S3C2410_TCMPB(4));
-
-	/* start the timer running */
-	tcon |= S3C2410_TCON_T4START;
-	tcon &= ~S3C2410_TCON_T4MANUALUPD;
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void __init s3c2410_timer_resources(void)
-{
-	struct platform_device tmpdev;
-
-	tmpdev.dev.bus = &platform_bus_type;
-	tmpdev.id = 4;
-
-	timerclk = clk_get(NULL, "timers");
-	if (IS_ERR(timerclk))
-		panic("failed to get clock for system timer");
-
-	clk_enable(timerclk);
-
-	if (!use_tclk1_12()) {
-		tin = clk_get(&tmpdev.dev, "pwm-tin");
-		if (IS_ERR(tin))
-			panic("failed to get pwm-tin clock for system timer");
-
-		tdiv = clk_get(&tmpdev.dev, "pwm-tdiv");
-		if (IS_ERR(tdiv))
-			panic("failed to get pwm-tdiv clock for system timer");
-	}
-
-	clk_enable(tin);
-}
-
-static void __init s3c2410_timer_init(void)
-{
-	s3c2410_timer_resources();
-	s3c2410_timer_setup();
-	setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
-}
-
-struct sys_timer s3c24xx_timer = {
-	.init		= s3c2410_timer_init,
-	.offset		= s3c2410_gettimeoffset,
-	.resume		= s3c2410_timer_setup
-};
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
index 342647e..6e93ef8 100644
--- a/arch/arm/plat-s3c24xx/Kconfig
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -14,6 +14,28 @@
 
 if PLAT_S3C24XX
 
+# low-level serial option nodes
+
+config CPU_LLSERIAL_S3C2410_ONLY
+	bool
+	default y if CPU_LLSERIAL_S3C2410 && !CPU_LLSERIAL_S3C2440
+
+config CPU_LLSERIAL_S3C2440_ONLY
+	bool
+	default y if CPU_LLSERIAL_S3C2440 && !CPU_LLSERIAL_S3C2410
+
+config CPU_LLSERIAL_S3C2410
+	bool
+	help
+	  Selected if there is an S3C2410 (or register compatible) serial
+	  low-level implementation needed
+
+config CPU_LLSERIAL_S3C2440
+	bool
+	help
+	  Selected if there is an S3C2440 (or register compatible) serial
+	  low-level implementation needed
+
 # code that is shared between a number of the s3c24xx implementations
 
 config S3C2410_CLOCK
@@ -27,46 +49,6 @@
 	help
 	  Clock code for supporting DCLK/CLKOUT on S3C24XX architectures
 
-config CPU_S3C244X
-	bool
-	depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
-	help
-	  Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
-
-config S3C2440_CPUFREQ
-	bool "S3C2440/S3C2442 CPU Frequency scaling support"
-	depends on CPU_FREQ_S3C24XX && (CPU_S3C2440 || CPU_S3C2442)
-	select S3C2410_CPUFREQ_UTILS
-	default y
-	help
-	  CPU Frequency scaling support for S3C2440 and S3C2442 SoC CPUs.
-
-config S3C2440_XTAL_12000000
-	bool
-	help
-	  Indicate that the build needs to support 12MHz system
-	  crystal.
-
-config S3C2440_XTAL_16934400
-	bool
-	help
-	  Indicate that the build needs to support 16.9344MHz system
-	  crystal.
-
-config S3C2440_PLL_12000000
-	bool
-	depends on S3C2440_CPUFREQ && S3C2440_XTAL_12000000
-	default y if CPU_FREQ_S3C24XX_PLL
-	help
-	  PLL tables for S3C2440 or S3C2442 CPUs with 12MHz crystals.
-
-config S3C2440_PLL_16934400
-	bool
-	depends on S3C2440_CPUFREQ && S3C2440_XTAL_16934400
-	default y if CPU_FREQ_S3C24XX_PLL
-	help
-	  PLL tables for S3C2440 or S3C2442 CPUs with 16.934MHz crystals.
-
 config S3C24XX_PWM
 	bool "PWM device support"
 	select HAVE_PWM
@@ -74,7 +56,6 @@
 	  Support for exporting the PWM timer blocks via the pwm device
 	  system.
 
-
 # gpio configurations
 
 config S3C24XX_GPIO_EXTRA
@@ -117,13 +98,6 @@
 	  Enable debugging output for the DMA code. This option sends info
 	  to the kernel log, at priority KERN_DEBUG.
 
-config S3C24XX_ADC
-	bool "ADC common driver support"
-	help
-	  Core support for the ADC block found in the S3C24XX SoC systems
-	  for drivers such as the touchscreen and hwmon to use to share
-	  this resource.
-
 # SPI default pin configuration code
 
 config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
index 5dee8c1..c2237c4 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -25,20 +25,12 @@
 
 # Architecture dependant builds
 
-obj-$(CONFIG_CPU_S3C244X)	+= s3c244x.o
-obj-$(CONFIG_CPU_S3C244X)	+= s3c244x-irq.o
-obj-$(CONFIG_CPU_S3C244X)	+= s3c244x-clock.o
-obj-$(CONFIG_S3C2440_CPUFREQ)	+= s3c2440-cpufreq.o
-obj-$(CONFIG_S3C2440_PLL_12000000) += s3c2440-pll-12000000.o
-obj-$(CONFIG_S3C2440_PLL_16934400) += s3c2440-pll-16934400.o
-
 obj-$(CONFIG_PM_SIMTEC)		+= pm-simtec.o
 obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_PM)		+= irq-pm.o
 obj-$(CONFIG_PM)		+= sleep.o
 obj-$(CONFIG_S3C2410_CLOCK)	+= s3c2410-clock.o
 obj-$(CONFIG_S3C2410_DMA)	+= dma.o
-obj-$(CONFIG_S3C24XX_ADC)	+= adc.o
 obj-$(CONFIG_S3C2410_IOTIMING)	+= s3c2410-iotiming.o
 obj-$(CONFIG_S3C2412_IOTIMING)	+= s3c2412-iotiming.o
 obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += s3c2410-cpufreq-utils.o
diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c
deleted file mode 100644
index ce47627..0000000
--- a/arch/arm/plat-s3c24xx/adc.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/* arch/arm/plat-s3c24xx/adc.c
- *
- * Copyright (c) 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
- *
- * S3C24XX ADC device core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#include <plat/regs-adc.h>
-#include <plat/adc.h>
-
-/* This driver is designed to control the usage of the ADC block between
- * the touchscreen and any other drivers that may need to use it, such as
- * the hwmon driver.
- *
- * Priority will be given to the touchscreen driver, but as this itself is
- * rate limited it should not starve other requests which are processed in
- * order that they are received.
- *
- * Each user registers to get a client block which uniquely identifies it
- * and stores information such as the necessary functions to callback when
- * action is required.
- */
-
-struct s3c_adc_client {
-	struct platform_device	*pdev;
-	struct list_head	 pend;
-	wait_queue_head_t	*wait;
-
-	unsigned int		 nr_samples;
-	int			 result;
-	unsigned char		 is_ts;
-	unsigned char		 channel;
-
-	void	(*select_cb)(struct s3c_adc_client *c, unsigned selected);
-	void	(*convert_cb)(struct s3c_adc_client *c,
-			      unsigned val1, unsigned val2,
-			      unsigned *samples_left);
-};
-
-struct adc_device {
-	struct platform_device	*pdev;
-	struct platform_device	*owner;
-	struct clk		*clk;
-	struct s3c_adc_client	*cur;
-	struct s3c_adc_client	*ts_pend;
-	void __iomem		*regs;
-
-	unsigned int		 prescale;
-
-	int			 irq;
-};
-
-static struct adc_device *adc_dev;
-
-static LIST_HEAD(adc_pending);
-
-#define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg)
-
-static inline void s3c_adc_convert(struct adc_device *adc)
-{
-	unsigned con = readl(adc->regs + S3C2410_ADCCON);
-
-	con |= S3C2410_ADCCON_ENABLE_START;
-	writel(con, adc->regs + S3C2410_ADCCON);
-}
-
-static inline void s3c_adc_select(struct adc_device *adc,
-				  struct s3c_adc_client *client)
-{
-	unsigned con = readl(adc->regs + S3C2410_ADCCON);
-
-	client->select_cb(client, 1);
-
-	con &= ~S3C2410_ADCCON_MUXMASK;
-	con &= ~S3C2410_ADCCON_STDBM;
-	con &= ~S3C2410_ADCCON_STARTMASK;
-
-	if (!client->is_ts)
-		con |= S3C2410_ADCCON_SELMUX(client->channel);
-
-	writel(con, adc->regs + S3C2410_ADCCON);
-}
-
-static void s3c_adc_dbgshow(struct adc_device *adc)
-{
-	adc_dbg(adc, "CON=%08x, TSC=%08x, DLY=%08x\n",
-		readl(adc->regs + S3C2410_ADCCON),
-		readl(adc->regs + S3C2410_ADCTSC),
-		readl(adc->regs + S3C2410_ADCDLY));
-}
-
-static void s3c_adc_try(struct adc_device *adc)
-{
-	struct s3c_adc_client *next = adc->ts_pend;
-
-	if (!next && !list_empty(&adc_pending)) {
-		next = list_first_entry(&adc_pending,
-					struct s3c_adc_client, pend);
-		list_del(&next->pend);
-	} else
-		adc->ts_pend = NULL;
-
-	if (next) {
-		adc_dbg(adc, "new client is %p\n", next);
-		adc->cur = next;
-		s3c_adc_select(adc, next);
-		s3c_adc_convert(adc);
-		s3c_adc_dbgshow(adc);
-	}
-}
-
-int s3c_adc_start(struct s3c_adc_client *client,
-		  unsigned int channel, unsigned int nr_samples)
-{
-	struct adc_device *adc = adc_dev;
-	unsigned long flags;
-
-	if (!adc) {
-		printk(KERN_ERR "%s: failed to find adc\n", __func__);
-		return -EINVAL;
-	}
-
-	if (client->is_ts && adc->ts_pend)
-		return -EAGAIN;
-
-	local_irq_save(flags);
-
-	client->channel = channel;
-	client->nr_samples = nr_samples;
-
-	if (client->is_ts)
-		adc->ts_pend = client;
-	else
-		list_add_tail(&client->pend, &adc_pending);
-
-	if (!adc->cur)
-		s3c_adc_try(adc);
-	local_irq_restore(flags);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(s3c_adc_start);
-
-static void s3c_convert_done(struct s3c_adc_client *client,
-			     unsigned v, unsigned u, unsigned *left)
-{
-	client->result = v;
-	wake_up(client->wait);
-}
-
-int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch)
-{
-	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
-	int ret;
-
-	client->convert_cb = s3c_convert_done;
-	client->wait = &wake;
-	client->result = -1;
-
-	ret = s3c_adc_start(client, ch, 1);
-	if (ret < 0)
-		goto err;
-
-	ret = wait_event_timeout(wake, client->result >= 0, HZ / 2);
-	if (client->result < 0) {
-		ret = -ETIMEDOUT;
-		goto err;
-	}
-
-	client->convert_cb = NULL;
-	return client->result;
-
-err:
-	return ret;
-}
-EXPORT_SYMBOL_GPL(s3c_adc_read);
-
-static void s3c_adc_default_select(struct s3c_adc_client *client,
-				   unsigned select)
-{
-}
-
-struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
-					void (*select)(struct s3c_adc_client *client,
-						       unsigned int selected),
-					void (*conv)(struct s3c_adc_client *client,
-						     unsigned d0, unsigned d1,
-						     unsigned *samples_left),
-					unsigned int is_ts)
-{
-	struct s3c_adc_client *client;
-
-	WARN_ON(!pdev);
-
-	if (!select)
-		select = s3c_adc_default_select;
-
-	if (!pdev)
-		return ERR_PTR(-EINVAL);
-
-	client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL);
-	if (!client) {
-		dev_err(&pdev->dev, "no memory for adc client\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	client->pdev = pdev;
-	client->is_ts = is_ts;
-	client->select_cb = select;
-	client->convert_cb = conv;
-
-	return client;
-}
-EXPORT_SYMBOL_GPL(s3c_adc_register);
-
-void s3c_adc_release(struct s3c_adc_client *client)
-{
-	/* We should really check that nothing is in progress. */
-	if (adc_dev->cur == client)
-		adc_dev->cur = NULL;
-	if (adc_dev->ts_pend == client)
-		adc_dev->ts_pend = NULL;
-	else {
-		struct list_head *p, *n;
-		struct s3c_adc_client *tmp;
-
-		list_for_each_safe(p, n, &adc_pending) {
-			tmp = list_entry(p, struct s3c_adc_client, pend);
-			if (tmp == client)
-				list_del(&tmp->pend);
-		}
-	}
-
-	if (adc_dev->cur == NULL)
-		s3c_adc_try(adc_dev);
-	kfree(client);
-}
-EXPORT_SYMBOL_GPL(s3c_adc_release);
-
-static irqreturn_t s3c_adc_irq(int irq, void *pw)
-{
-	struct adc_device *adc = pw;
-	struct s3c_adc_client *client = adc->cur;
-	unsigned long flags;
-	unsigned data0, data1;
-
-	if (!client) {
-		dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__);
-		return IRQ_HANDLED;
-	}
-
-	data0 = readl(adc->regs + S3C2410_ADCDAT0);
-	data1 = readl(adc->regs + S3C2410_ADCDAT1);
-	adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1);
-
-	client->nr_samples--;
-
-	if (client->convert_cb)
-		(client->convert_cb)(client, data0 & 0x3ff, data1 & 0x3ff,
-				     &client->nr_samples);
-
-	if (client->nr_samples > 0) {
-		/* fire another conversion for this */
-
-		client->select_cb(client, 1);
-		s3c_adc_convert(adc);
-	} else {
-		local_irq_save(flags);
-		(client->select_cb)(client, 0);
-		adc->cur = NULL;
-
-		s3c_adc_try(adc);
-		local_irq_restore(flags);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static int s3c_adc_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct adc_device *adc;
-	struct resource *regs;
-	int ret;
-
-	adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL);
-	if (adc == NULL) {
-		dev_err(dev, "failed to allocate adc_device\n");
-		return -ENOMEM;
-	}
-
-	adc->pdev = pdev;
-	adc->prescale = S3C2410_ADCCON_PRSCVL(49);
-
-	adc->irq = platform_get_irq(pdev, 1);
-	if (adc->irq <= 0) {
-		dev_err(dev, "failed to get adc irq\n");
-		ret = -ENOENT;
-		goto err_alloc;
-	}
-
-	ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc);
-	if (ret < 0) {
-		dev_err(dev, "failed to attach adc irq\n");
-		goto err_alloc;
-	}
-
-	adc->clk = clk_get(dev, "adc");
-	if (IS_ERR(adc->clk)) {
-		dev_err(dev, "failed to get adc clock\n");
-		ret = PTR_ERR(adc->clk);
-		goto err_irq;
-	}
-
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!regs) {
-		dev_err(dev, "failed to find registers\n");
-		ret = -ENXIO;
-		goto err_clk;
-	}
-
-	adc->regs = ioremap(regs->start, resource_size(regs));
-	if (!adc->regs) {
-		dev_err(dev, "failed to map registers\n");
-		ret = -ENXIO;
-		goto err_clk;
-	}
-
-	clk_enable(adc->clk);
-
-	writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
-	       adc->regs + S3C2410_ADCCON);
-
-	dev_info(dev, "attached adc driver\n");
-
-	platform_set_drvdata(pdev, adc);
-	adc_dev = adc;
-
-	return 0;
-
- err_clk:
-	clk_put(adc->clk);
-
- err_irq:
-	free_irq(adc->irq, adc);
-
- err_alloc:
-	kfree(adc);
-	return ret;
-}
-
-static int __devexit s3c_adc_remove(struct platform_device *pdev)
-{
-	struct adc_device *adc = platform_get_drvdata(pdev);
-
-	iounmap(adc->regs);
-	free_irq(adc->irq, adc);
-	clk_disable(adc->clk);
-	clk_put(adc->clk);
-	kfree(adc);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct adc_device *adc = platform_get_drvdata(pdev);
-	u32 con;
-
-	con = readl(adc->regs + S3C2410_ADCCON);
-	con |= S3C2410_ADCCON_STDBM;
-	writel(con, adc->regs + S3C2410_ADCCON);
-
-	clk_disable(adc->clk);
-
-	return 0;
-}
-
-static int s3c_adc_resume(struct platform_device *pdev)
-{
-	struct adc_device *adc = platform_get_drvdata(pdev);
-
-	clk_enable(adc->clk);
-
-	writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
-	       adc->regs + S3C2410_ADCCON);
-
-	return 0;
-}
-
-#else
-#define s3c_adc_suspend NULL
-#define s3c_adc_resume NULL
-#endif
-
-static struct platform_driver s3c_adc_driver = {
-	.driver		= {
-		.name	= "s3c24xx-adc",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= s3c_adc_probe,
-	.remove		= __devexit_p(s3c_adc_remove),
-	.suspend	= s3c_adc_suspend,
-	.resume		= s3c_adc_resume,
-};
-
-static int __init adc_init(void)
-{
-	int ret;
-
-	ret = platform_driver_register(&s3c_adc_driver);
-	if (ret)
-		printk(KERN_ERR "%s: failed to add adc driver\n", __func__);
-
-	return ret;
-}
-
-arch_initcall(adc_init);
diff --git a/arch/arm/plat-s3c24xx/clock-dclk.c b/arch/arm/plat-s3c24xx/clock-dclk.c
index ac061a1..cf97caa 100644
--- a/arch/arm/plat-s3c24xx/clock-dclk.c
+++ b/arch/arm/plat-s3c24xx/clock-dclk.c
@@ -161,14 +161,18 @@
 
 /* external clock definitions */
 
+static struct clk_ops dclk_ops = {
+	.set_parent	= s3c24xx_dclk_setparent,
+	.set_rate	= s3c24xx_set_dclk_rate,
+	.round_rate	= s3c24xx_round_dclk_rate,
+};
+
 struct clk s3c24xx_dclk0 = {
 	.name		= "dclk0",
 	.id		= -1,
 	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
 	.enable	        = s3c24xx_dclk_enable,
-	.set_parent	= s3c24xx_dclk_setparent,
-	.set_rate	= s3c24xx_set_dclk_rate,
-	.round_rate	= s3c24xx_round_dclk_rate,
+	.ops		= &dclk_ops,
 };
 
 struct clk s3c24xx_dclk1 = {
@@ -176,19 +180,21 @@
 	.id		= -1,
 	.ctrlbit	= S3C2410_DCLKCON_DCLK1EN,
 	.enable		= s3c24xx_dclk_enable,
-	.set_parent	= s3c24xx_dclk_setparent,
-	.set_rate	= s3c24xx_set_dclk_rate,
-	.round_rate	= s3c24xx_round_dclk_rate,
+	.ops		= &dclk_ops,
+};
+
+static struct clk_ops clkout_ops = {
+	.set_parent	= s3c24xx_clkout_setparent,
 };
 
 struct clk s3c24xx_clkout0 = {
 	.name		= "clkout0",
 	.id		= -1,
-	.set_parent	= s3c24xx_clkout_setparent,
+	.ops		= &clkout_ops,
 };
 
 struct clk s3c24xx_clkout1 = {
 	.name		= "clkout1",
 	.id		= -1,
-	.set_parent	= s3c24xx_clkout_setparent,
+	.ops		= &clkout_ops,
 };
diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
index 4af9dd9..9ca64df 100644
--- a/arch/arm/plat-s3c24xx/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -49,9 +49,7 @@
 #include <plat/s3c2400.h>
 #include <plat/s3c2410.h>
 #include <plat/s3c2412.h>
-#include "s3c244x.h"
-#include <plat/s3c2440.h>
-#include <plat/s3c2442.h>
+#include <plat/s3c244x.h>
 #include <plat/s3c2443.h>
 
 /* table of supported CPUs */
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
index 7f686a3..8c6de1c 100644
--- a/arch/arm/plat-s3c24xx/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -32,6 +32,7 @@
 
 #include <plat/regs-serial.h>
 #include <plat/udc.h>
+#include <plat/mci.h>
 
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -112,34 +113,6 @@
 	},
 };
 
-/* yart devices */
-
-static struct platform_device s3c24xx_uart_device0 = {
-	.id		= 0,
-};
-
-static struct platform_device s3c24xx_uart_device1 = {
-	.id		= 1,
-};
-
-static struct platform_device s3c24xx_uart_device2 = {
-	.id		= 2,
-};
-
-static struct platform_device s3c24xx_uart_device3 = {
-	.id		= 3,
-};
-
-struct platform_device *s3c24xx_uart_src[4] = {
-	&s3c24xx_uart_device0,
-	&s3c24xx_uart_device1,
-	&s3c24xx_uart_device2,
-	&s3c24xx_uart_device3,
-};
-
-struct platform_device *s3c24xx_uart_devs[4] = {
-};
-
 /* LCD Controller */
 
 static struct resource s3c_lcd_resource[] = {
@@ -185,9 +158,27 @@
 }
 
 /* Touchscreen */
+
+static struct resource s3c_ts_resource[] = {
+	[0] = {
+		.start = S3C24XX_PA_ADC,
+		.end   = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_TC,
+		.end   = IRQ_TC,
+		.flags = IORESOURCE_IRQ,
+	},
+
+};
+
 struct platform_device s3c_device_ts = {
 	.name		  = "s3c2410-ts",
 	.id		  = -1,
+	.dev.parent	= &s3c_device_adc.dev,
+	.num_resources	  = ARRAY_SIZE(s3c_ts_resource),
+	.resource	  = s3c_ts_resource,
 };
 EXPORT_SYMBOL(s3c_device_ts);
 
@@ -379,6 +370,18 @@
 
 EXPORT_SYMBOL(s3c_device_sdi);
 
+void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
+{
+	struct s3c24xx_mci_pdata *npd;
+
+	npd = kmemdup(pdata, sizeof(struct s3c24xx_mci_pdata), GFP_KERNEL);
+	if (!npd)
+		printk(KERN_ERR "%s: no memory to copy pdata", __func__);
+
+	s3c_device_sdi.dev.platform_data = npd;
+}
+
+
 /* SPI (0) */
 
 static struct resource s3c_spi0_resource[] = {
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index f0ea794..93827b3 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -33,7 +33,7 @@
 #include <mach/dma.h>
 #include <mach/map.h>
 
-#include <plat/dma-plat.h>
+#include <plat/dma-s3c24xx.h>
 #include <plat/regs-dma.h>
 
 /* io map for dma */
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
index 6d7a961..4f0f11a 100644
--- a/arch/arm/plat-s3c24xx/gpiolib.c
+++ b/arch/arm/plat-s3c24xx/gpiolib.c
@@ -20,7 +20,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-#include <mach/gpio-core.h>
+#include <plat/gpio-core.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <plat/pm.h>
diff --git a/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h b/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h
new file mode 100644
index 0000000..de5e88f
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/include/plat/audio-simtec.h
@@ -0,0 +1,37 @@
+/* arch/arm/plat-s3c24xx/include/plat/audio-simtec.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Simtec Audio support.
+*/
+
+/**
+ * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio
+ * @use_mpllin: Select codec clock from MPLLin
+ * @output_cdclk: Need to output CDCLK to the codec
+ * @have_mic: Set if we have a MIC socket
+ * @have_lout: Set if we have a LineOut socket
+ * @amp_gpio: GPIO pin to enable the AMP
+ * @amp_gain: Option GPIO to control AMP gain
+ */
+struct s3c24xx_audio_simtec_pdata {
+	unsigned int	use_mpllin:1;
+	unsigned int	output_cdclk:1;
+
+	unsigned int	have_mic:1;
+	unsigned int	have_lout:1;
+
+	int		amp_gpio;
+	int		amp_gain[2];
+
+	void	(*startup)(void);
+};
+
+extern int simtec_audio_add(const char *codec_name, bool has_lr_routing,
+			    struct s3c24xx_audio_simtec_pdata *pdata);
diff --git a/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h b/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h
index 33d421d..d623235 100644
--- a/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h
+++ b/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h
@@ -135,7 +135,7 @@
  * @locktime_m: The lock-time in uS for the MPLL.
  * @locktime_u: The lock-time in uS for the UPLL.
  * @locttime_bits: The number of bits each LOCKTIME field.
- * @need_pll: Set if this driver needs to change the PLL values to acheive
+ * @need_pll: Set if this driver needs to change the PLL values to achieve
  *	any frequency changes. This is really only need by devices like the
  *	S3C2410 where there is no or limited divider between the PLL and the
  *	ARMCLK.
diff --git a/arch/arm/plat-s3c24xx/include/plat/dma-plat.h b/arch/arm/plat-s3c24xx/include/plat/dma-plat.h
deleted file mode 100644
index 9565ead..0000000
--- a/arch/arm/plat-s3c24xx/include/plat/dma-plat.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/include/plat/dma-plat.h
- *
- * Copyright (C) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C24XX DMA support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <plat/dma-core.h>
-
-extern struct sysdev_class dma_sysclass;
-extern struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
-
-#define DMA_CH_VALID		(1<<31)
-#define DMA_CH_NEVER		(1<<30)
-
-struct s3c24xx_dma_addr {
-	unsigned long		from;
-	unsigned long		to;
-};
-
-/* struct s3c24xx_dma_map
- *
- * this holds the mapping information for the channel selected
- * to be connected to the specified device
-*/
-
-struct s3c24xx_dma_map {
-	const char		*name;
-	struct s3c24xx_dma_addr  hw_addr;
-
-	unsigned long		 channels[S3C_DMA_CHANNELS];
-	unsigned long		 channels_rx[S3C_DMA_CHANNELS];
-};
-
-struct s3c24xx_dma_selection {
-	struct s3c24xx_dma_map	*map;
-	unsigned long		 map_size;
-	unsigned long		 dcon_mask;
-
-	void	(*select)(struct s3c2410_dma_chan *chan,
-			  struct s3c24xx_dma_map *map);
-
-	void	(*direction)(struct s3c2410_dma_chan *chan,
-			     struct s3c24xx_dma_map *map,
-			     enum s3c2410_dmasrc dir);
-};
-
-extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
-
-/* struct s3c24xx_dma_order_ch
- *
- * channel map for one of the `enum dma_ch` dma channels. the list
- * entry contains a set of low-level channel numbers, orred with
- * DMA_CH_VALID, which are checked in the order in the array.
-*/
-
-struct s3c24xx_dma_order_ch {
-	unsigned int	list[S3C_DMA_CHANNELS];	/* list of channels */
-	unsigned int	flags;				/* flags */
-};
-
-/* struct s3c24xx_dma_order
- *
- * information provided by either the core or the board to give the
- * dma system a hint on how to allocate channels
-*/
-
-struct s3c24xx_dma_order {
-	struct s3c24xx_dma_order_ch	channels[DMACH_MAX];
-};
-
-extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
-
-/* DMA init code, called from the cpu support code */
-
-extern int s3c2410_dma_init(void);
-
-extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
-			    unsigned int stride);
diff --git a/arch/arm/plat-s3c24xx/include/plat/mci.h b/arch/arm/plat-s3c24xx/include/plat/mci.h
index 36aaa10..2ac2b21 100644
--- a/arch/arm/plat-s3c24xx/include/plat/mci.h
+++ b/arch/arm/plat-s3c24xx/include/plat/mci.h
@@ -40,4 +40,13 @@
 				     unsigned short vdd);
 };
 
+/**
+ * s3c24xx_mci_set_platdata - set platform data for mmc/sdi device
+ * @pdata: The platform data
+ *
+ * Copy the platform data supplied by @pdata so that this can be marked
+ * __initdata.
+ */
+extern void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata);
+
 #endif /* _ARCH_NCI_H */
diff --git a/arch/arm/plat-s3c24xx/include/plat/pm-core.h b/arch/arm/plat-s3c24xx/include/plat/pm-core.h
deleted file mode 100644
index fb45dd9..0000000
--- a/arch/arm/plat-s3c24xx/include/plat/pm-core.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/include/plat/pll.h
- *
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C24xx - PM core support for arch/arm/plat-s3c/pm.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-static inline void s3c_pm_debug_init_uart(void)
-{
-	unsigned long tmp = __raw_readl(S3C2410_CLKCON);
-
-	/* re-start uart clocks */
-	tmp |= S3C2410_CLKCON_UART0;
-	tmp |= S3C2410_CLKCON_UART1;
-	tmp |= S3C2410_CLKCON_UART2;
-
-	__raw_writel(tmp, S3C2410_CLKCON);
-	udelay(10);
-}
-
-static inline void s3c_pm_arch_prepare_irqs(void)
-{
-	__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
-	__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
-
-	/* ack any outstanding external interrupts before we go to sleep */
-
-	__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
-	__raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
-	__raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
-
-}
-
-static inline void s3c_pm_arch_stop_clocks(void)
-{
-	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
-}
-
-static void s3c_pm_show_resume_irqs(int start, unsigned long which,
-				    unsigned long mask);
-
-static inline void s3c_pm_arch_show_resume_irqs(void)
-{
-	S3C_PMDBG("post sleep: IRQs 0x%08x, 0x%08x\n",
-		  __raw_readl(S3C2410_SRCPND),
-		  __raw_readl(S3C2410_EINTPEND));
-
-	s3c_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
-				s3c_irqwake_intmask);
-
-	s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
-				s3c_irqwake_eintmask);
-}
-
-static inline void s3c_pm_arch_update_uart(void __iomem *regs,
-					   struct pm_uart_save *save)
-{
-}
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2440.h b/arch/arm/plat-s3c24xx/include/plat/s3c2440.h
deleted file mode 100644
index 107853b..0000000
--- a/arch/arm/plat-s3c24xx/include/plat/s3c2440.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2440.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2440 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifdef CONFIG_CPU_S3C2440
-extern  int s3c2440_init(void);
-#else
-#define s3c2440_init NULL
-#endif
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2442.h b/arch/arm/plat-s3c24xx/include/plat/s3c2442.h
deleted file mode 100644
index 451a23a..0000000
--- a/arch/arm/plat-s3c24xx/include/plat/s3c2442.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/include/asm-arm/plat-s3c24xx/s3c2442.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for s3c2442 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifdef CONFIG_CPU_S3C2442
-extern  int s3c2442_init(void);
-#else
-#define s3c2442_init NULL
-#endif
diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c244x.h b/arch/arm/plat-s3c24xx/include/plat/s3c244x.h
new file mode 100644
index 0000000..307248d
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/include/plat/s3c244x.h
@@ -0,0 +1,37 @@
+/* linux/arch/arm/plat-s3c24xx/include/plat/s3c244x.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2440 and S3C2442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+
+extern void s3c244x_map_io(void);
+
+extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c244x_init_clocks(int xtal);
+
+#else
+#define s3c244x_init_clocks NULL
+#define s3c244x_init_uarts NULL
+#define s3c244x_map_io NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2440
+extern  int s3c2440_init(void);
+#else
+#define s3c2440_init NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2442
+extern  int s3c2442_init(void);
+#else
+#define s3c2442_init NULL
+#endif
diff --git a/arch/arm/plat-s3c24xx/s3c2440-pll-12000000.c b/arch/arm/plat-s3c24xx/s3c2440-pll-12000000.c
deleted file mode 100644
index 49f6503..0000000
--- a/arch/arm/plat-s3c24xx/s3c2440-pll-12000000.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* arch/arm/plat-s3c24xx/s3c2440-pll-12000000.c
- *
- * Copyright (c) 2006-2007 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *	Vincent Sanders <vince@arm.linux.org.uk>
- *
- * S3C2440/S3C2442 CPU PLL tables (12MHz Crystal)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sysdev.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <plat/cpu.h>
-#include <plat/cpu-freq-core.h>
-
-static struct cpufreq_frequency_table s3c2440_plls_12[] __initdata = {
-	{ .frequency = 75000000,	.index = PLLVAL(0x75, 3, 3),  }, 	/* FVco 600.000000 */
-	{ .frequency = 80000000,	.index = PLLVAL(0x98, 4, 3),  }, 	/* FVco 640.000000 */
-	{ .frequency = 90000000,	.index = PLLVAL(0x70, 2, 3),  }, 	/* FVco 720.000000 */
-	{ .frequency = 100000000,	.index = PLLVAL(0x5c, 1, 3),  }, 	/* FVco 800.000000 */
-	{ .frequency = 110000000,	.index = PLLVAL(0x66, 1, 3),  }, 	/* FVco 880.000000 */
-	{ .frequency = 120000000,	.index = PLLVAL(0x70, 1, 3),  }, 	/* FVco 960.000000 */
-	{ .frequency = 150000000,	.index = PLLVAL(0x75, 3, 2),  }, 	/* FVco 600.000000 */
-	{ .frequency = 160000000,	.index = PLLVAL(0x98, 4, 2),  }, 	/* FVco 640.000000 */
-	{ .frequency = 170000000,	.index = PLLVAL(0x4d, 1, 2),  }, 	/* FVco 680.000000 */
-	{ .frequency = 180000000,	.index = PLLVAL(0x70, 2, 2),  }, 	/* FVco 720.000000 */
-	{ .frequency = 190000000,	.index = PLLVAL(0x57, 1, 2),  }, 	/* FVco 760.000000 */
-	{ .frequency = 200000000,	.index = PLLVAL(0x5c, 1, 2),  }, 	/* FVco 800.000000 */
-	{ .frequency = 210000000,	.index = PLLVAL(0x84, 2, 2),  }, 	/* FVco 840.000000 */
-	{ .frequency = 220000000,	.index = PLLVAL(0x66, 1, 2),  }, 	/* FVco 880.000000 */
-	{ .frequency = 230000000,	.index = PLLVAL(0x6b, 1, 2),  }, 	/* FVco 920.000000 */
-	{ .frequency = 240000000,	.index = PLLVAL(0x70, 1, 2),  }, 	/* FVco 960.000000 */
-	{ .frequency = 300000000,	.index = PLLVAL(0x75, 3, 1),  }, 	/* FVco 600.000000 */
-	{ .frequency = 310000000,	.index = PLLVAL(0x93, 4, 1),  }, 	/* FVco 620.000000 */
-	{ .frequency = 320000000,	.index = PLLVAL(0x98, 4, 1),  }, 	/* FVco 640.000000 */
-	{ .frequency = 330000000,	.index = PLLVAL(0x66, 2, 1),  }, 	/* FVco 660.000000 */
-	{ .frequency = 340000000,	.index = PLLVAL(0x4d, 1, 1),  }, 	/* FVco 680.000000 */
-	{ .frequency = 350000000,	.index = PLLVAL(0xa7, 4, 1),  }, 	/* FVco 700.000000 */
-	{ .frequency = 360000000,	.index = PLLVAL(0x70, 2, 1),  }, 	/* FVco 720.000000 */
-	{ .frequency = 370000000,	.index = PLLVAL(0xb1, 4, 1),  }, 	/* FVco 740.000000 */
-	{ .frequency = 380000000,	.index = PLLVAL(0x57, 1, 1),  }, 	/* FVco 760.000000 */
-	{ .frequency = 390000000,	.index = PLLVAL(0x7a, 2, 1),  }, 	/* FVco 780.000000 */
-	{ .frequency = 400000000,	.index = PLLVAL(0x5c, 1, 1),  }, 	/* FVco 800.000000 */
-};
-
-static int s3c2440_plls12_add(struct sys_device *dev)
-{
-	struct clk *xtal_clk;
-	unsigned long xtal;
-
-	xtal_clk = clk_get(NULL, "xtal");
-	if (IS_ERR(xtal_clk))
-		return PTR_ERR(xtal_clk);
-
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	if (xtal == 12000000) {
-		printk(KERN_INFO "Using PLL table for 12MHz crystal\n");
-		return s3c_plltab_register(s3c2440_plls_12,
-					   ARRAY_SIZE(s3c2440_plls_12));
-	}
-
-	return 0;
-}
-
-static struct sysdev_driver s3c2440_plls12_drv = {
-	.add	= s3c2440_plls12_add,
-};
-
-static int __init s3c2440_pll_12mhz(void)
-{
-	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_plls12_drv);
-
-}
-
-arch_initcall(s3c2440_pll_12mhz);
-
-static struct sysdev_driver s3c2442_plls12_drv = {
-	.add	= s3c2440_plls12_add,
-};
-
-static int __init s3c2442_pll_12mhz(void)
-{
-	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_plls12_drv);
-
-}
-
-arch_initcall(s3c2442_pll_12mhz);
diff --git a/arch/arm/plat-s3c24xx/s3c2440-pll-16934400.c b/arch/arm/plat-s3c24xx/s3c2440-pll-16934400.c
deleted file mode 100644
index 7679af1..0000000
--- a/arch/arm/plat-s3c24xx/s3c2440-pll-16934400.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* arch/arm/plat-s3c24xx/s3c2440-pll-16934400.c
- *
- * Copyright (c) 2006-2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *	Vincent Sanders <vince@arm.linux.org.uk>
- *
- * S3C2440/S3C2442 CPU PLL tables (16.93444MHz Crystal)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sysdev.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <plat/cpu.h>
-#include <plat/cpu-freq-core.h>
-
-static struct cpufreq_frequency_table s3c2440_plls_169344[] __initdata = {
-	{ .frequency = 78019200,	.index = PLLVAL(121, 5, 3), 	}, 	/* FVco 624.153600 */
-	{ .frequency = 84067200,	.index = PLLVAL(131, 5, 3), 	}, 	/* FVco 672.537600 */
-	{ .frequency = 90115200,	.index = PLLVAL(141, 5, 3), 	}, 	/* FVco 720.921600 */
-	{ .frequency = 96163200,	.index = PLLVAL(151, 5, 3), 	}, 	/* FVco 769.305600 */
-	{ .frequency = 102135600,	.index = PLLVAL(185, 6, 3), 	}, 	/* FVco 817.084800 */
-	{ .frequency = 108259200,	.index = PLLVAL(171, 5, 3), 	}, 	/* FVco 866.073600 */
-	{ .frequency = 114307200,	.index = PLLVAL(127, 3, 3), 	}, 	/* FVco 914.457600 */
-	{ .frequency = 120234240,	.index = PLLVAL(134, 3, 3), 	}, 	/* FVco 961.873920 */
-	{ .frequency = 126161280,	.index = PLLVAL(141, 3, 3), 	}, 	/* FVco 1009.290240 */
-	{ .frequency = 132088320,	.index = PLLVAL(148, 3, 3), 	}, 	/* FVco 1056.706560 */
-	{ .frequency = 138015360,	.index = PLLVAL(155, 3, 3), 	}, 	/* FVco 1104.122880 */
-	{ .frequency = 144789120,	.index = PLLVAL(163, 3, 3), 	}, 	/* FVco 1158.312960 */
-	{ .frequency = 150100363,	.index = PLLVAL(187, 9, 2), 	}, 	/* FVco 600.401454 */
-	{ .frequency = 156038400,	.index = PLLVAL(121, 5, 2), 	}, 	/* FVco 624.153600 */
-	{ .frequency = 162086400,	.index = PLLVAL(126, 5, 2), 	}, 	/* FVco 648.345600 */
-	{ .frequency = 168134400,	.index = PLLVAL(131, 5, 2), 	}, 	/* FVco 672.537600 */
-	{ .frequency = 174048000,	.index = PLLVAL(177, 7, 2), 	}, 	/* FVco 696.192000 */
-	{ .frequency = 180230400,	.index = PLLVAL(141, 5, 2), 	}, 	/* FVco 720.921600 */
-	{ .frequency = 186278400,	.index = PLLVAL(124, 4, 2), 	}, 	/* FVco 745.113600 */
-	{ .frequency = 192326400,	.index = PLLVAL(151, 5, 2), 	}, 	/* FVco 769.305600 */
-	{ .frequency = 198132480,	.index = PLLVAL(109, 3, 2), 	}, 	/* FVco 792.529920 */
-	{ .frequency = 204271200,	.index = PLLVAL(185, 6, 2), 	}, 	/* FVco 817.084800 */
-	{ .frequency = 210268800,	.index = PLLVAL(141, 4, 2), 	}, 	/* FVco 841.075200 */
-	{ .frequency = 216518400,	.index = PLLVAL(171, 5, 2), 	}, 	/* FVco 866.073600 */
-	{ .frequency = 222264000,	.index = PLLVAL(97, 2, 2), 	}, 	/* FVco 889.056000 */
-	{ .frequency = 228614400,	.index = PLLVAL(127, 3, 2), 	}, 	/* FVco 914.457600 */
-	{ .frequency = 234259200,	.index = PLLVAL(158, 4, 2), 	}, 	/* FVco 937.036800 */
-	{ .frequency = 240468480,	.index = PLLVAL(134, 3, 2), 	}, 	/* FVco 961.873920 */
-	{ .frequency = 246960000,	.index = PLLVAL(167, 4, 2), 	}, 	/* FVco 987.840000 */
-	{ .frequency = 252322560,	.index = PLLVAL(141, 3, 2), 	}, 	/* FVco 1009.290240 */
-	{ .frequency = 258249600,	.index = PLLVAL(114, 2, 2), 	}, 	/* FVco 1032.998400 */
-	{ .frequency = 264176640,	.index = PLLVAL(148, 3, 2), 	}, 	/* FVco 1056.706560 */
-	{ .frequency = 270950400,	.index = PLLVAL(120, 2, 2), 	}, 	/* FVco 1083.801600 */
-	{ .frequency = 276030720,	.index = PLLVAL(155, 3, 2), 	}, 	/* FVco 1104.122880 */
-	{ .frequency = 282240000,	.index = PLLVAL(92, 1, 2), 	}, 	/* FVco 1128.960000 */
-	{ .frequency = 289578240,	.index = PLLVAL(163, 3, 2), 	}, 	/* FVco 1158.312960 */
-	{ .frequency = 294235200,	.index = PLLVAL(131, 2, 2), 	}, 	/* FVco 1176.940800 */
-	{ .frequency = 300200727,	.index = PLLVAL(187, 9, 1), 	}, 	/* FVco 600.401454 */
-	{ .frequency = 306358690,	.index = PLLVAL(191, 9, 1), 	}, 	/* FVco 612.717380 */
-	{ .frequency = 312076800,	.index = PLLVAL(121, 5, 1), 	}, 	/* FVco 624.153600 */
-	{ .frequency = 318366720,	.index = PLLVAL(86, 3, 1), 	}, 	/* FVco 636.733440 */
-	{ .frequency = 324172800,	.index = PLLVAL(126, 5, 1), 	}, 	/* FVco 648.345600 */
-	{ .frequency = 330220800,	.index = PLLVAL(109, 4, 1), 	}, 	/* FVco 660.441600 */
-	{ .frequency = 336268800,	.index = PLLVAL(131, 5, 1), 	}, 	/* FVco 672.537600 */
-	{ .frequency = 342074880,	.index = PLLVAL(93, 3, 1), 	}, 	/* FVco 684.149760 */
-	{ .frequency = 348096000,	.index = PLLVAL(177, 7, 1), 	}, 	/* FVco 696.192000 */
-	{ .frequency = 355622400,	.index = PLLVAL(118, 4, 1), 	}, 	/* FVco 711.244800 */
-	{ .frequency = 360460800,	.index = PLLVAL(141, 5, 1), 	}, 	/* FVco 720.921600 */
-	{ .frequency = 366206400,	.index = PLLVAL(165, 6, 1), 	}, 	/* FVco 732.412800 */
-	{ .frequency = 372556800,	.index = PLLVAL(124, 4, 1), 	}, 	/* FVco 745.113600 */
-	{ .frequency = 378201600,	.index = PLLVAL(126, 4, 1), 	}, 	/* FVco 756.403200 */
-	{ .frequency = 384652800,	.index = PLLVAL(151, 5, 1), 	}, 	/* FVco 769.305600 */
-	{ .frequency = 391608000,	.index = PLLVAL(177, 6, 1), 	}, 	/* FVco 783.216000 */
-	{ .frequency = 396264960,	.index = PLLVAL(109, 3, 1), 	}, 	/* FVco 792.529920 */
-	{ .frequency = 402192000,	.index = PLLVAL(87, 2, 1), 	}, 	/* FVco 804.384000 */
-};
-
-static int s3c2440_plls169344_add(struct sys_device *dev)
-{
-	struct clk *xtal_clk;
-	unsigned long xtal;
-
-	xtal_clk = clk_get(NULL, "xtal");
-	if (IS_ERR(xtal_clk))
-		return PTR_ERR(xtal_clk);
-
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	if (xtal == 169344000) {
-		printk(KERN_INFO "Using PLL table for 16.9344MHz crystal\n");
-		return s3c_plltab_register(s3c2440_plls_169344,
-					   ARRAY_SIZE(s3c2440_plls_169344));
-	}
-
-	return 0;
-}
-
-static struct sysdev_driver s3c2440_plls169344_drv = {
-	.add	= s3c2440_plls169344_add,
-};
-
-static int __init s3c2440_pll_16934400(void)
-{
-	return sysdev_driver_register(&s3c2440_sysclass,
-				      &s3c2440_plls169344_drv);
-
-}
-
-arch_initcall(s3c2440_pll_16934400);
-
-static struct sysdev_driver s3c2442_plls169344_drv = {
-	.add	= s3c2440_plls169344_add,
-};
-
-static int __init s3c2442_pll_16934400(void)
-{
-	return sysdev_driver_register(&s3c2442_sysclass,
-				      &s3c2442_plls169344_drv);
-
-}
-
-arch_initcall(s3c2442_pll_16934400);
diff --git a/arch/arm/plat-s3c24xx/s3c244x-clock.c b/arch/arm/plat-s3c24xx/s3c244x-clock.c
deleted file mode 100644
index 7937109..0000000
--- a/arch/arm/plat-s3c24xx/s3c244x-clock.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/s3c24xx-clock.c
- *
- * Copyright (c) 2004-2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2440/S3C2442 Common clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-
-#include <mach/regs-clock.h>
-
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-static int s3c2440_setparent_armclk(struct clk *clk, struct clk *parent)
-{
-	unsigned long camdivn;
-	unsigned long dvs;
-
-	if (parent == &clk_f)
-		dvs = 0;
-	else if (parent == &clk_h)
-		dvs = S3C2440_CAMDIVN_DVSEN;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	camdivn  = __raw_readl(S3C2440_CAMDIVN);
-	camdivn &= ~S3C2440_CAMDIVN_DVSEN;
-	camdivn |= dvs;
-	__raw_writel(camdivn, S3C2440_CAMDIVN);
-
-	return 0;
-}
-
-static struct clk clk_arm = {
-	.name		= "armclk",
-	.id		= -1,
-	.set_parent	= s3c2440_setparent_armclk,
-};
-
-static int s3c244x_clk_add(struct sys_device *sysdev)
-{
-	unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
-	unsigned long clkdivn;
-	struct clk *clock_upll;
-	int ret;
-
-	printk("S3C244X: Clock Support, DVS %s\n",
-	       (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
-
-	clk_arm.parent = (camdivn & S3C2440_CAMDIVN_DVSEN) ? &clk_h : &clk_f;
-
-	ret = s3c24xx_register_clock(&clk_arm);
-	if (ret < 0) {
-		printk(KERN_ERR "S3C24XX: Failed to add armclk (%d)\n", ret);
-		return ret;
-	}
-
-	clock_upll = clk_get(NULL, "upll");
-	if (IS_ERR(clock_upll)) {
-		printk(KERN_ERR "S3C244X: Failed to get upll clock\n");
-		return -ENOENT;
-	}
-
-	/* check rate of UPLL, and if it is near 96MHz, then change
-	 * to using half the UPLL rate for the system */
-
-	if (clk_get_rate(clock_upll) > (94 * MHZ)) {
-		clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
-
-		spin_lock(&clocks_lock);
-
-		clkdivn = __raw_readl(S3C2410_CLKDIVN);
-		clkdivn |= S3C2440_CLKDIVN_UCLK;
-		__raw_writel(clkdivn, S3C2410_CLKDIVN);
-
-		spin_unlock(&clocks_lock);
-	}
-
-	return 0;
-}
-
-static struct sysdev_driver s3c2440_clk_driver = {
-	.add		= s3c244x_clk_add,
-};
-
-static int s3c2440_clk_init(void)
-{
-	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
-}
-
-arch_initcall(s3c2440_clk_init);
-
-static struct sysdev_driver s3c2442_clk_driver = {
-	.add		= s3c244x_clk_add,
-};
-
-static int s3c2442_clk_init(void)
-{
-	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver);
-}
-
-arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/plat-s3c24xx/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c
deleted file mode 100644
index 12623a4..0000000
--- a/arch/arm/plat-s3c24xx/s3c244x.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/s3c244x.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- *   Ben Dooks <ben@simtec.co.uk>
- *
- * Samsung S3C2440 and S3C2442 Mobile CPU support (not S3C2443)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/sysdev.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <plat/cpu-freq.h>
-
-#include <mach/regs-clock.h>
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-#include <mach/regs-gpioj.h>
-#include <mach/regs-dsc.h>
-
-#include <plat/s3c2410.h>
-#include <plat/s3c2440.h>
-#include "s3c244x.h"
-#include <plat/clock.h>
-#include <plat/devs.h>
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/pll.h>
-
-static struct map_desc s3c244x_iodesc[] __initdata = {
-	IODESC_ENT(CLKPWR),
-	IODESC_ENT(TIMER),
-	IODESC_ENT(WATCHDOG),
-};
-
-/* uart initialisation */
-
-void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
-}
-
-void __init s3c244x_map_io(void)
-{
-	/* register our io-tables */
-
-	iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));
-
-	/* rename any peripherals used differing from the s3c2410 */
-
-	s3c_device_sdi.name  = "s3c2440-sdi";
-	s3c_device_i2c0.name  = "s3c2440-i2c";
-	s3c_device_nand.name = "s3c2440-nand";
-	s3c_device_ts.name = "s3c2440-ts";
-	s3c_device_usbgadget.name = "s3c2440-usbgadget";
-}
-
-void __init_or_cpufreq s3c244x_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long clkdiv;
-	unsigned long camdiv;
-	unsigned long xtal;
-	unsigned long hclk, fclk, pclk;
-	int hdiv = 1;
-
-	xtal_clk = clk_get(NULL, "xtal");
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
-
-	clkdiv = __raw_readl(S3C2410_CLKDIVN);
-	camdiv = __raw_readl(S3C2440_CAMDIVN);
-
-	/* work out clock scalings */
-
-	switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
-	case S3C2440_CLKDIVN_HDIVN_1:
-		hdiv = 1;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_2:
-		hdiv = 2;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_4_8:
-		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_3_6:
-		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
-		break;
-	}
-
-	hclk = fclk / hdiv;
-	pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1);
-
-	/* print brief summary of clocks, etc */
-
-	printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
-	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
-
-	s3c24xx_setup_clocks(fclk, hclk, pclk);
-}
-
-void __init s3c244x_init_clocks(int xtal)
-{
-	/* initialise the clocks here, to allow other things like the
-	 * console to use them, and to add new ones after the initialisation
-	 */
-
-	s3c24xx_register_baseclocks(xtal);
-	s3c244x_setup_clocks();
-	s3c2410_baseclk_add();
-}
-
-#ifdef CONFIG_PM
-
-static struct sleep_save s3c244x_sleep[] = {
-	SAVE_ITEM(S3C2440_DSC0),
-	SAVE_ITEM(S3C2440_DSC1),
-	SAVE_ITEM(S3C2440_GPJDAT),
-	SAVE_ITEM(S3C2440_GPJCON),
-	SAVE_ITEM(S3C2440_GPJUP)
-};
-
-static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
-{
-	s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
-	return 0;
-}
-
-static int s3c244x_resume(struct sys_device *dev)
-{
-	s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
-	return 0;
-}
-
-#else
-#define s3c244x_suspend NULL
-#define s3c244x_resume  NULL
-#endif
-
-/* Since the S3C2442 and S3C2440 share  items, put both sysclasses here */
-
-struct sysdev_class s3c2440_sysclass = {
-	.name		= "s3c2440-core",
-	.suspend	= s3c244x_suspend,
-	.resume		= s3c244x_resume
-};
-
-struct sysdev_class s3c2442_sysclass = {
-	.name		= "s3c2442-core",
-	.suspend	= s3c244x_suspend,
-	.resume		= s3c244x_resume
-};
-
-/* need to register class before we actually register the device, and
- * we also need to ensure that it has been initialised before any of the
- * drivers even try to use it (even if not on an s3c2440 based system)
- * as a driver which may support both 2410 and 2440 may try and use it.
-*/
-
-static int __init s3c2440_core_init(void)
-{
-	return sysdev_class_register(&s3c2440_sysclass);
-}
-
-core_initcall(s3c2440_core_init);
-
-static int __init s3c2442_core_init(void)
-{
-	return sysdev_class_register(&s3c2442_sysclass);
-}
-
-core_initcall(s3c2442_core_init);
diff --git a/arch/arm/plat-s3c24xx/s3c244x.h b/arch/arm/plat-s3c24xx/s3c244x.h
deleted file mode 100644
index 6aab5ea..0000000
--- a/arch/arm/plat-s3c24xx/s3c244x.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/s3c244x.h
- *
- * Copyright (c) 2004-2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Header file for S3C2440 and S3C2442 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
-
-extern void s3c244x_map_io(void);
-
-extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-
-extern void s3c244x_init_clocks(int xtal);
-
-#else
-#define s3c244x_init_clocks NULL
-#define s3c244x_init_uarts NULL
-#define s3c244x_map_io NULL
-#endif
diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig
deleted file mode 100644
index e6da87a..0000000
--- a/arch/arm/plat-s3c64xx/Kconfig
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright 2008 Openmoko, Inc.
-# Copyright 2008 Simtec Electronics
-#	Ben Dooks <ben@simtec.co.uk>
-#
-# Licensed under GPLv2
-
-config PLAT_S3C64XX
-	bool
-	depends on ARCH_S3C64XX
-	default y
-	select CPU_V6
-	select PLAT_S3C
-	select ARM_VIC
-	select NO_IOPORT
-	select ARCH_REQUIRE_GPIOLIB
-	select S3C_GPIO_TRACK
-	select S3C_GPIO_PULL_UPDOWN
-	select S3C_GPIO_CFG_S3C24XX
-	select S3C_GPIO_CFG_S3C64XX
-	select S3C_DEV_NAND
-	select USB_ARCH_HAS_OHCI
-	help
-	  Base platform code for any Samsung S3C64XX device
-
-if PLAT_S3C64XX
-
-# Configuration options shared by all S3C64XX implementations
-
-config CPU_S3C6400_INIT
-	bool
-	help
-	  Common initialisation code for the S3C6400 that is shared
-	  by other CPUs in the series, such as the S3C6410.
-
-config CPU_S3C6400_CLOCK
-	bool
-	help
-	  Common clock support code for the S3C6400 that is shared
-	  by other CPUs in the series, such as the S3C6410.
-
-config S3C64XX_DMA
-	bool "S3C64XX DMA"
-	select S3C_DMA
-
-# platform specific device setup
-
-config S3C64XX_SETUP_I2C0
-	bool
-	default y
-	help
-	  Common setup code for i2c bus 0.
-
-	  Note, currently since i2c0 is always compiled, this setup helper
-	  is always compiled with it.
-
-config S3C64XX_SETUP_I2C1
-	bool
-	help
-	  Common setup code for i2c bus 1.
-
-config S3C64XX_SETUP_FB_24BPP
-	bool
-	help
-	  Common setup code for S3C64XX with an 24bpp RGB display helper.
-
-config S3C64XX_SETUP_SDHCI_GPIO
-	bool
-	help
-	  Common setup code for S3C64XX SDHCI GPIO configurations
-
-endif
diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile
deleted file mode 100644
index b85b435..0000000
--- a/arch/arm/plat-s3c64xx/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-# arch/arm/plat-s3c64xx/Makefile
-#
-# Copyright 2008 Openmoko, Inc.
-# Copyright 2008 Simtec Electronics
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:= dummy.o
-obj-				:=
-
-# Core files
-
-obj-y				+= dev-uart.o
-obj-y				+= cpu.o
-obj-y				+= irq.o
-obj-y				+= irq-eint.o
-obj-y				+= clock.o
-obj-y				+= gpiolib.o
-
-# CPU support
-
-obj-$(CONFIG_CPU_S3C6400_INIT)	+= s3c6400-init.o
-obj-$(CONFIG_CPU_S3C6400_CLOCK)	+= s3c6400-clock.o
-obj-$(CONFIG_CPU_FREQ_S3C64XX)  += cpufreq.o
-
-# PM support
-
-obj-$(CONFIG_PM)		+= pm.o
-obj-$(CONFIG_PM)		+= sleep.o
-obj-$(CONFIG_PM)		+= irq-pm.o
-
-# DMA support
-
-obj-$(CONFIG_S3C64XX_DMA)	+= dma.o
-
-# Device setup
-
-obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o
-obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
-obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
-obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
-obj-$(CONFIG_SND_S3C24XX_SOC) += dev-audio.o
diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c
deleted file mode 100644
index 7a36e89..0000000
--- a/arch/arm/plat-s3c64xx/clock.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/clock.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C64XX Base clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <plat/regs-sys.h>
-#include <plat/regs-clock.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/clock.h>
-
-struct clk clk_h2 = {
-	.name		= "hclk2",
-	.id		= -1,
-	.rate		= 0,
-};
-
-struct clk clk_27m = {
-	.name		= "clk_27m",
-	.id		= -1,
-	.rate		= 27000000,
-};
-
-static int clk_48m_ctrl(struct clk *clk, int enable)
-{
-	unsigned long flags;
-	u32 val;
-
-	/* can't rely on clock lock, this register has other usages */
-	local_irq_save(flags);
-
-	val = __raw_readl(S3C64XX_OTHERS);
-	if (enable)
-		val |= S3C64XX_OTHERS_USBMASK;
-	else
-		val &= ~S3C64XX_OTHERS_USBMASK;
-
-	__raw_writel(val, S3C64XX_OTHERS);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-struct clk clk_48m = {
-	.name		= "clk_48m",
-	.id		= -1,
-	.rate		= 48000000,
-	.enable		= clk_48m_ctrl,
-};
-
-static int inline s3c64xx_gate(void __iomem *reg,
-				struct clk *clk,
-				int enable)
-{
-	unsigned int ctrlbit = clk->ctrlbit;
-	u32 con;
-
-	con = __raw_readl(reg);
-
-	if (enable)
-		con |= ctrlbit;
-	else
-		con &= ~ctrlbit;
-
-	__raw_writel(con, reg);
-	return 0;
-}
-
-static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
-{
-	return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
-}
-
-static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
-{
-	return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
-}
-
-int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
-{
-	return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
-}
-
-static struct clk init_clocks_disable[] = {
-	{
-		.name		= "nand",
-		.id		= -1,
-		.parent		= &clk_h,
-	}, {
-		.name		= "adc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_TSADC,
-	}, {
-		.name		= "i2c",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_IIC,
-	}, {
-		.name		= "iis",
-		.id		= 0,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_IIS0,
-	}, {
-		.name		= "iis",
-		.id		= 1,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_IIS1,
-	}, {
-		.name		= "spi",
-		.id		= 0,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_SPI0,
-	}, {
-		.name		= "spi",
-		.id		= 1,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_SPI1,
-	}, {
-		.name		= "48m",
-		.id		= 0,
-		.parent		= &clk_48m,
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_MMC0_48,
-	}, {
-		.name		= "48m",
-		.id		= 1,
-		.parent		= &clk_48m,
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_MMC1_48,
-	}, {
-		.name		= "48m",
-		.id		= 2,
-		.parent		= &clk_48m,
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_MMC2_48,
-	}, {
-		.name		= "dma0",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_DMA0,
-	}, {
-		.name		= "dma1",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_DMA1,
-	},
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "lcd",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_LCD,
-	}, {
-		.name		= "gpio",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_GPIO,
-	}, {
-		.name		= "usb-host",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_UHOST,
-	}, {
-		.name		= "hsmmc",
-		.id		= 0,
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_HSMMC0,
-	}, {
-		.name		= "hsmmc",
-		.id		= 1,
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_HSMMC1,
-	}, {
-		.name		= "hsmmc",
-		.id		= 2,
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_HSMMC2,
-	}, {
-		.name		= "timers",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_PWM,
-	}, {
-		.name		= "uart",
-		.id		= 0,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_UART0,
-	}, {
-		.name		= "uart",
-		.id		= 1,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_UART1,
-	}, {
-		.name		= "uart",
-		.id		= 2,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_UART2,
-	}, {
-		.name		= "uart",
-		.id		= 3,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_UART3,
-	}, {
-		.name		= "rtc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_RTC,
-	}, {
-		.name		= "watchdog",
-		.id		= -1,
-		.parent		= &clk_p,
-		.ctrlbit	= S3C_CLKCON_PCLK_WDT,
-	}, {
-		.name		= "ac97",
-		.id		= -1,
-		.parent		= &clk_p,
-		.ctrlbit	= S3C_CLKCON_PCLK_AC97,
-	}
-};
-
-static struct clk *clks[] __initdata = {
-	&clk_ext,
-	&clk_epll,
-	&clk_27m,
-	&clk_48m,
-	&clk_h2,
-};
-
-void __init s3c64xx_register_clocks(void)
-{
-	struct clk *clkp;
-	int ret;
-	int ptr;
-
-	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
-	clkp = init_clocks;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-
-		(clkp->enable)(clkp, 0);
-	}
-
-	s3c_pwmclk_init();
-}
diff --git a/arch/arm/plat-s3c64xx/cpu.c b/arch/arm/plat-s3c64xx/cpu.c
deleted file mode 100644
index 49796d2..0000000
--- a/arch/arm/plat-s3c64xx/cpu.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/cpu.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C64XX CPU Support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/sysdev.h>
-#include <linux/serial_core.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <plat/regs-serial.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/clock.h>
-
-#include <plat/s3c6400.h>
-#include <plat/s3c6410.h>
-
-/* table of supported CPUs */
-
-static const char name_s3c6400[] = "S3C6400";
-static const char name_s3c6410[] = "S3C6410";
-
-static struct cpu_table cpu_ids[] __initdata = {
-	{
-		.idcode		= 0x36400000,
-		.idmask		= 0xfffff000,
-		.map_io		= s3c6400_map_io,
-		.init_clocks	= s3c6400_init_clocks,
-		.init_uarts	= s3c6400_init_uarts,
-		.init		= s3c6400_init,
-		.name		= name_s3c6400,
-	}, {
-		.idcode		= 0x36410100,
-		.idmask		= 0xffffff00,
-		.map_io		= s3c6410_map_io,
-		.init_clocks	= s3c6410_init_clocks,
-		.init_uarts	= s3c6410_init_uarts,
-		.init		= s3c6410_init,
-		.name		= name_s3c6410,
-	},
-};
-
-/* minimal IO mapping */
-
-/* see notes on uart map in arch/arm/mach-s3c6400/include/mach/debug-macro.S */
-#define UART_OFFS (S3C_PA_UART & 0xfffff)
-
-static struct map_desc s3c_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S3C_VA_SYS,
-		.pfn		= __phys_to_pfn(S3C64XX_PA_SYSCON),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)(S3C_VA_UART + UART_OFFS),
-		.pfn		= __phys_to_pfn(S3C_PA_UART),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_VIC0,
-		.pfn		= __phys_to_pfn(S3C64XX_PA_VIC0),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_VIC1,
-		.pfn		= __phys_to_pfn(S3C64XX_PA_VIC1),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_TIMER,
-		.pfn		= __phys_to_pfn(S3C_PA_TIMER),
-		.length		= SZ_16K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C64XX_VA_GPIO,
-		.pfn		= __phys_to_pfn(S3C64XX_PA_GPIO),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C64XX_VA_MODEM,
-		.pfn		= __phys_to_pfn(S3C64XX_PA_MODEM),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_WATCHDOG,
-		.pfn		= __phys_to_pfn(S3C64XX_PA_WATCHDOG),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_USB_HSPHY,
-		.pfn		= __phys_to_pfn(S3C64XX_PA_USB_HSPHY),
-		.length		= SZ_1K,
-		.type		= MT_DEVICE,
-	},
-};
-
-
-struct sysdev_class s3c64xx_sysclass = {
-	.name	= "s3c64xx-core",
-};
-
-static struct sys_device s3c64xx_sysdev = {
-	.cls	= &s3c64xx_sysclass,
-};
-
-
-/* read cpu identification code */
-
-void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
-{
-	unsigned long idcode;
-
-	/* initialise the io descriptors we need for initialisation */
-	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
-	iotable_init(mach_desc, size);
-
-	idcode = __raw_readl(S3C_VA_SYS + 0x118);
-	if (!idcode) {
-		/* S3C6400 has the ID register in a different place,
-		 * and needs a write before it can be read. */
-
-		__raw_writel(0x0, S3C_VA_SYS + 0xA1C);
-		idcode = __raw_readl(S3C_VA_SYS + 0xA1C);
-	}
-
-	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
-}
-
-static __init int s3c64xx_sysdev_init(void)
-{
-	sysdev_class_register(&s3c64xx_sysclass);
-	return sysdev_register(&s3c64xx_sysdev);
-}
-
-core_initcall(s3c64xx_sysdev_init);
diff --git a/arch/arm/plat-s3c64xx/dev-audio.c b/arch/arm/plat-s3c64xx/dev-audio.c
deleted file mode 100644
index a21a88f..0000000
--- a/arch/arm/plat-s3c64xx/dev-audio.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/* linux/arch/arm/plat-s3c/dev-audio.c
- *
- * Copyright 2009 Wolfson Microelectronics
- *      Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/platform_device.h>
-
-#include <mach/irqs.h>
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/gpio.h>
-
-#include <plat/devs.h>
-#include <plat/audio.h>
-#include <plat/gpio-bank-d.h>
-#include <plat/gpio-bank-e.h>
-#include <plat/gpio-cfg.h>
-
-static struct resource s3c64xx_iis0_resource[] = {
-	[0] = {
-		.start = S3C64XX_PA_IIS0,
-		.end   = S3C64XX_PA_IIS0 + 0x100 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device s3c64xx_device_iis0 = {
-	.name		  = "s3c64xx-iis",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s3c64xx_iis0_resource),
-	.resource	  = s3c64xx_iis0_resource,
-};
-EXPORT_SYMBOL(s3c64xx_device_iis0);
-
-static struct resource s3c64xx_iis1_resource[] = {
-	[0] = {
-		.start = S3C64XX_PA_IIS1,
-		.end   = S3C64XX_PA_IIS1 + 0x100 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device s3c64xx_device_iis1 = {
-	.name		  = "s3c64xx-iis",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c64xx_iis1_resource),
-	.resource	  = s3c64xx_iis1_resource,
-};
-EXPORT_SYMBOL(s3c64xx_device_iis1);
-
-static struct resource s3c64xx_iisv4_resource[] = {
-	[0] = {
-		.start = S3C64XX_PA_IISV4,
-		.end   = S3C64XX_PA_IISV4 + 0x100 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device s3c64xx_device_iisv4 = {
-	.name		  = "s3c64xx-iis-v4",
-	.id		  = -1,
-	.num_resources	  = ARRAY_SIZE(s3c64xx_iisv4_resource),
-	.resource	  = s3c64xx_iisv4_resource,
-};
-EXPORT_SYMBOL(s3c64xx_device_iisv4);
-
-
-/* PCM Controller platform_devices */
-
-static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_PCM0_SCLK);
-		s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_PCM0_EXTCLK);
-		s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_PCM0_FSYNC);
-		s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_PCM0_SIN);
-		s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_PCM0_SOUT);
-		break;
-	case 1:
-		s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_PCM1_SCLK);
-		s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_PCM1_EXTCLK);
-		s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_PCM1_FSYNC);
-		s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_PCM1_SIN);
-		s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT);
-		break;
-	default:
-		printk(KERN_DEBUG "Invalid PCM Controller number!");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct resource s3c64xx_pcm0_resource[] = {
-	[0] = {
-		.start = S3C64XX_PA_PCM0,
-		.end   = S3C64XX_PA_PCM0 + 0x100 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = DMACH_PCM0_TX,
-		.end   = DMACH_PCM0_TX,
-		.flags = IORESOURCE_DMA,
-	},
-	[2] = {
-		.start = DMACH_PCM0_RX,
-		.end   = DMACH_PCM0_RX,
-		.flags = IORESOURCE_DMA,
-	},
-};
-
-static struct s3c_audio_pdata s3c_pcm0_pdata = {
-	.cfg_gpio = s3c64xx_pcm_cfg_gpio,
-};
-
-struct platform_device s3c64xx_device_pcm0 = {
-	.name		  = "samsung-pcm",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s3c64xx_pcm0_resource),
-	.resource	  = s3c64xx_pcm0_resource,
-	.dev = {
-		.platform_data = &s3c_pcm0_pdata,
-	},
-};
-EXPORT_SYMBOL(s3c64xx_device_pcm0);
-
-static struct resource s3c64xx_pcm1_resource[] = {
-	[0] = {
-		.start = S3C64XX_PA_PCM1,
-		.end   = S3C64XX_PA_PCM1 + 0x100 - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = DMACH_PCM1_TX,
-		.end   = DMACH_PCM1_TX,
-		.flags = IORESOURCE_DMA,
-	},
-	[2] = {
-		.start = DMACH_PCM1_RX,
-		.end   = DMACH_PCM1_RX,
-		.flags = IORESOURCE_DMA,
-	},
-};
-
-static struct s3c_audio_pdata s3c_pcm1_pdata = {
-	.cfg_gpio = s3c64xx_pcm_cfg_gpio,
-};
-
-struct platform_device s3c64xx_device_pcm1 = {
-	.name		  = "samsung-pcm",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c64xx_pcm1_resource),
-	.resource	  = s3c64xx_pcm1_resource,
-	.dev = {
-		.platform_data = &s3c_pcm1_pdata,
-	},
-};
-EXPORT_SYMBOL(s3c64xx_device_pcm1);
diff --git a/arch/arm/plat-s3c64xx/dev-uart.c b/arch/arm/plat-s3c64xx/dev-uart.c
deleted file mode 100644
index 62c11a6..0000000
--- a/arch/arm/plat-s3c64xx/dev-uart.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/dev-uart.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Base S3C64XX UART resource and device definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/platform_device.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/irq.h>
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <plat/devs.h>
-
-/* Serial port registrations */
-
-/* 64xx uarts are closer together */
-
-static struct resource s3c64xx_uart0_resource[] = {
-	[0] = {
-		.start	= S3C_PA_UART0,
-		.end	= S3C_PA_UART0 + 0x100,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_S3CUART_RX0,
-		.end	= IRQ_S3CUART_RX0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX0,
-		.end	= IRQ_S3CUART_TX0,
-		.flags	= IORESOURCE_IRQ,
-
-	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR0,
-		.end	= IRQ_S3CUART_ERR0,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c64xx_uart1_resource[] = {
-	[0] = {
-		.start = S3C_PA_UART1,
-		.end   = S3C_PA_UART1 + 0x100,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_S3CUART_RX1,
-		.end	= IRQ_S3CUART_RX1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX1,
-		.end	= IRQ_S3CUART_TX1,
-		.flags	= IORESOURCE_IRQ,
-
-	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR1,
-		.end	= IRQ_S3CUART_ERR1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource s3c6xx_uart2_resource[] = {
-	[0] = {
-		.start = S3C_PA_UART2,
-		.end   = S3C_PA_UART2 + 0x100,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_S3CUART_RX2,
-		.end	= IRQ_S3CUART_RX2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX2,
-		.end	= IRQ_S3CUART_TX2,
-		.flags	= IORESOURCE_IRQ,
-
-	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR2,
-		.end	= IRQ_S3CUART_ERR2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource s3c64xx_uart3_resource[] = {
-	[0] = {
-		.start = S3C_PA_UART3,
-		.end   = S3C_PA_UART3 + 0x100,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_S3CUART_RX3,
-		.end	= IRQ_S3CUART_RX3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_S3CUART_TX3,
-		.end	= IRQ_S3CUART_TX3,
-		.flags	= IORESOURCE_IRQ,
-
-	},
-	[3] = {
-		.start	= IRQ_S3CUART_ERR3,
-		.end	= IRQ_S3CUART_ERR3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-
-struct s3c24xx_uart_resources s3c64xx_uart_resources[] __initdata = {
-	[0] = {
-		.resources	= s3c64xx_uart0_resource,
-		.nr_resources	= ARRAY_SIZE(s3c64xx_uart0_resource),
-	},
-	[1] = {
-		.resources	= s3c64xx_uart1_resource,
-		.nr_resources	= ARRAY_SIZE(s3c64xx_uart1_resource),
-	},
-	[2] = {
-		.resources	= s3c6xx_uart2_resource,
-		.nr_resources	= ARRAY_SIZE(s3c6xx_uart2_resource),
-	},
-	[3] = {
-		.resources	= s3c64xx_uart3_resource,
-		.nr_resources	= ARRAY_SIZE(s3c64xx_uart3_resource),
-	},
-};
-
-/* uart devices */
-
-static struct platform_device s3c24xx_uart_device0 = {
-	.id		= 0,
-};
-
-static struct platform_device s3c24xx_uart_device1 = {
-	.id		= 1,
-};
-
-static struct platform_device s3c24xx_uart_device2 = {
-	.id		= 2,
-};
-
-static struct platform_device s3c24xx_uart_device3 = {
-	.id		= 3,
-};
-
-struct platform_device *s3c24xx_uart_src[4] = {
-	&s3c24xx_uart_device0,
-	&s3c24xx_uart_device1,
-	&s3c24xx_uart_device2,
-	&s3c24xx_uart_device3,
-};
-
-struct platform_device *s3c24xx_uart_devs[4] = {
-};
-
diff --git a/arch/arm/plat-s3c64xx/dma.c b/arch/arm/plat-s3c64xx/dma.c
deleted file mode 100644
index d554b93..0000000
--- a/arch/arm/plat-s3c64xx/dma.c
+++ /dev/null
@@ -1,750 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/dma.c
- *
- * Copyright 2009 Openmoko, Inc.
- * Copyright 2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C64XX DMA core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/dmapool.h>
-#include <linux/sysdev.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <mach/dma.h>
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-#include <plat/dma-plat.h>
-#include <plat/regs-sys.h>
-
-#include <asm/hardware/pl080.h>
-
-/* dma channel state information */
-
-struct s3c64xx_dmac {
-	struct sys_device	 sysdev;
-	struct clk		*clk;
-	void __iomem		*regs;
-	struct s3c2410_dma_chan *channels;
-	enum dma_ch		 chanbase;
-};
-
-/* pool to provide LLI buffers */
-static struct dma_pool *dma_pool;
-
-/* Debug configuration and code */
-
-static unsigned char debug_show_buffs = 0;
-
-static void dbg_showchan(struct s3c2410_dma_chan *chan)
-{
-	pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n",
-		 chan->number,
-		 readl(chan->regs + PL080_CH_SRC_ADDR),
-		 readl(chan->regs + PL080_CH_DST_ADDR),
-		 readl(chan->regs + PL080_CH_LLI),
-		 readl(chan->regs + PL080_CH_CONTROL),
-		 readl(chan->regs + PL080S_CH_CONTROL2),
-		 readl(chan->regs + PL080S_CH_CONFIG));
-}
-
-static void show_lli(struct pl080s_lli *lli)
-{
-	pr_debug("LLI[%p] %08x->%08x, NL %08x C %08x,%08x\n",
-		 lli, lli->src_addr, lli->dst_addr, lli->next_lli,
-		 lli->control0, lli->control1);
-}
-
-static void dbg_showbuffs(struct s3c2410_dma_chan *chan)
-{
-	struct s3c64xx_dma_buff *ptr;
-	struct s3c64xx_dma_buff *end;
-
-	pr_debug("DMA%d: buffs next %p, curr %p, end %p\n",
-		 chan->number, chan->next, chan->curr, chan->end);
-
-	ptr = chan->next;
-	end = chan->end;
-
-	if (debug_show_buffs) {
-		for (; ptr != NULL; ptr = ptr->next) {
-			pr_debug("DMA%d: %08x ",
-				 chan->number, ptr->lli_dma);
-			show_lli(ptr->lli);
-		}
-	}
-}
-
-/* End of Debug */
-
-static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel)
-{
-	struct s3c2410_dma_chan *chan;
-	unsigned int start, offs;
-
-	start = 0;
-
-	if (channel >= DMACH_PCM1_TX)
-		start = 8;
-
-	for (offs = 0; offs < 8; offs++) {
-		chan = &s3c2410_chans[start + offs];
-		if (!chan->in_use)
-			goto found;
-	}
-
-	return NULL;
-
-found:
-	s3c_dma_chan_map[channel] = chan;
-	return chan;
-}
-
-int s3c2410_dma_config(unsigned int channel, int xferunit)
-{
-	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	switch (xferunit) {
-	case 1:
-		chan->hw_width = 0;
-		break;
-	case 2:
-		chan->hw_width = 1;
-		break;
-	case 4:
-		chan->hw_width = 2;
-		break;
-	default:
-		printk(KERN_ERR "%s: illegal width %d\n", __func__, xferunit);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
-				 struct pl080s_lli *lli,
-				 dma_addr_t data, int size)
-{
-	dma_addr_t src, dst;
-	u32 control0, control1;
-
-	switch (chan->source) {
-	case S3C2410_DMASRC_HW:
-		src = chan->dev_addr;
-		dst = data;
-		control0 = PL080_CONTROL_SRC_AHB2;
-		control0 |= PL080_CONTROL_DST_INCR;
-		break;
-
-	case S3C2410_DMASRC_MEM:
-		src = data;
-		dst = chan->dev_addr;
-		control0 = PL080_CONTROL_DST_AHB2;
-		control0 |= PL080_CONTROL_SRC_INCR;
-		break;
-	default:
-		BUG();
-	}
-
-	/* note, we do not currently setup any of the burst controls */
-
-	control1 = size >> chan->hw_width;	/* size in no of xfers */
-	control0 |= PL080_CONTROL_PROT_SYS;	/* always in priv. mode */
-	control0 |= PL080_CONTROL_TC_IRQ_EN;	/* always fire IRQ */
-	control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT;
-	control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT;
-
-	lli->src_addr = src;
-	lli->dst_addr = dst;
-	lli->next_lli = 0;
-	lli->control0 = control0;
-	lli->control1 = control1;
-}
-
-static void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,
-				struct pl080s_lli *lli)
-{
-	void __iomem *regs = chan->regs;
-
-	pr_debug("%s: LLI %p => regs\n", __func__, lli);
-	show_lli(lli);
-
-	writel(lli->src_addr, regs + PL080_CH_SRC_ADDR);
-	writel(lli->dst_addr, regs + PL080_CH_DST_ADDR);
-	writel(lli->next_lli, regs + PL080_CH_LLI);
-	writel(lli->control0, regs + PL080_CH_CONTROL);
-	writel(lli->control1, regs + PL080S_CH_CONTROL2);
-}
-
-static int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)
-{
-	struct s3c64xx_dmac *dmac = chan->dmac;
-	u32 config;
-	u32 bit = chan->bit;
-
-	dbg_showchan(chan);
-
-	pr_debug("%s: clearing interrupts\n", __func__);
-
-	/* clear interrupts */
-	writel(bit, dmac->regs + PL080_TC_CLEAR);
-	writel(bit, dmac->regs + PL080_ERR_CLEAR);
-
-	pr_debug("%s: starting channel\n", __func__);
-
-	config = readl(chan->regs + PL080S_CH_CONFIG);
-	config |= PL080_CONFIG_ENABLE;
-
-	pr_debug("%s: writing config %08x\n", __func__, config);
-	writel(config, chan->regs + PL080S_CH_CONFIG);
-
-	return 0;
-}
-
-static int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)
-{
-	u32 config;
-	int timeout;
-
-	pr_debug("%s: stopping channel\n", __func__);
-
-	dbg_showchan(chan);
-
-	config = readl(chan->regs + PL080S_CH_CONFIG);
-	config |= PL080_CONFIG_HALT;
-	writel(config, chan->regs + PL080S_CH_CONFIG);
-
-	timeout = 1000;
-	do {
-		config = readl(chan->regs + PL080S_CH_CONFIG);
-		pr_debug("%s: %d - config %08x\n", __func__, timeout, config);
-		if (config & PL080_CONFIG_ACTIVE)
-			udelay(10);
-		else
-			break;
-		} while (--timeout > 0);
-
-	if (config & PL080_CONFIG_ACTIVE) {
-		printk(KERN_ERR "%s: channel still active\n", __func__);
-		return -EFAULT;
-	}
-
-	config = readl(chan->regs + PL080S_CH_CONFIG);
-	config &= ~PL080_CONFIG_ENABLE;
-	writel(config, chan->regs + PL080S_CH_CONFIG);
-
-	return 0;
-}
-
-static inline void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan,
-					 struct s3c64xx_dma_buff *buf,
-					 enum s3c2410_dma_buffresult result)
-{
-	if (chan->callback_fn != NULL)
-		(chan->callback_fn)(chan, buf->pw, 0, result);
-}
-
-static void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff)
-{
-	dma_pool_free(dma_pool, buff->lli, buff->lli_dma);
-	kfree(buff);
-}
-
-static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)
-{
-	struct s3c64xx_dma_buff *buff, *next;
-	u32 config;
-
-	dbg_showchan(chan);
-
-	pr_debug("%s: flushing channel\n", __func__);
-
-	config = readl(chan->regs + PL080S_CH_CONFIG);
-	config &= ~PL080_CONFIG_ENABLE;
-	writel(config, chan->regs + PL080S_CH_CONFIG);
-
-	/* dump all the buffers associated with this channel */
-
-	for (buff = chan->curr; buff != NULL; buff = next) {
-		next = buff->next;
-		pr_debug("%s: buff %p (next %p)\n", __func__, buff, buff->next);
-
-		s3c64xx_dma_bufffdone(chan, buff, S3C2410_RES_ABORT);
-		s3c64xx_dma_freebuff(buff);
-	}
-
-	chan->curr = chan->next = chan->end = NULL;
-
-	return 0;
-}
-
-int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
-{
-	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-	WARN_ON(!chan);
-	if (!chan)
-		return -EINVAL;
-
-	switch (op) {
-	case S3C2410_DMAOP_START:
-		return s3c64xx_dma_start(chan);
-
-	case S3C2410_DMAOP_STOP:
-		return s3c64xx_dma_stop(chan);
-
-	case S3C2410_DMAOP_FLUSH:
-		return s3c64xx_dma_flush(chan);
-
-	/* belive PAUSE/RESUME are no-ops */
-	case S3C2410_DMAOP_PAUSE:
-	case S3C2410_DMAOP_RESUME:
-	case S3C2410_DMAOP_STARTED:
-	case S3C2410_DMAOP_TIMEOUT:
-		return 0;
-	}
-
-	return -ENOENT;
-}
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-/* s3c2410_dma_enque
- *
- */
-
-int s3c2410_dma_enqueue(unsigned int channel, void *id,
-			dma_addr_t data, int size)
-{
-	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-	struct s3c64xx_dma_buff *next;
-	struct s3c64xx_dma_buff *buff;
-	struct pl080s_lli *lli;
-	unsigned long flags;
-	int ret;
-
-	WARN_ON(!chan);
-	if (!chan)
-		return -EINVAL;
-
-	buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_ATOMIC);
-	if (!buff) {
-		printk(KERN_ERR "%s: no memory for buffer\n", __func__);
-		return -ENOMEM;
-	}
-
-	lli = dma_pool_alloc(dma_pool, GFP_ATOMIC, &buff->lli_dma);
-	if (!lli) {
-		printk(KERN_ERR "%s: no memory for lli\n", __func__);
-		ret = -ENOMEM;
-		goto err_buff;
-	}
-
-	pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n",
-		 __func__, buff, data, lli, (u32)buff->lli_dma, size);
-
-	buff->lli = lli;
-	buff->pw = id;
-
-	s3c64xx_dma_fill_lli(chan, lli, data, size);
-
-	local_irq_save(flags);
-
-	if ((next = chan->next) != NULL) {
-		struct s3c64xx_dma_buff *end = chan->end;
-		struct pl080s_lli *endlli = end->lli;
-
-		pr_debug("enquing onto channel\n");
-
-		end->next = buff;
-		endlli->next_lli = buff->lli_dma;
-
-		if (chan->flags & S3C2410_DMAF_CIRCULAR) {
-			struct s3c64xx_dma_buff *curr = chan->curr;
-			lli->next_lli = curr->lli_dma;
-		}
-
-		if (next == chan->curr) {
-			writel(buff->lli_dma, chan->regs + PL080_CH_LLI);
-			chan->next = buff;
-		}
-
-		show_lli(endlli);
-		chan->end = buff;
-	} else {
-		pr_debug("enquing onto empty channel\n");
-
-		chan->curr = buff;
-		chan->next = buff;
-		chan->end = buff;
-
-		s3c64xx_lli_to_regs(chan, lli);
-	}
-
-	local_irq_restore(flags);
-
-	show_lli(lli);
-
-	dbg_showchan(chan);
-	dbg_showbuffs(chan);
-	return 0;
-
-err_buff:
-	kfree(buff);
-	return ret;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-
-int s3c2410_dma_devconfig(int channel,
-			  enum s3c2410_dmasrc source,
-			  unsigned long devaddr)
-{
-	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-	u32 peripheral;
-	u32 config = 0;
-
-	pr_debug("%s: channel %d, source %d, dev %08lx, chan %p\n",
-		 __func__, channel, source, devaddr, chan);
-
-	WARN_ON(!chan);
-	if (!chan)
-		return -EINVAL;
-
-	peripheral = (chan->peripheral & 0xf);
-	chan->source = source;
-	chan->dev_addr = devaddr;
-
-	pr_debug("%s: peripheral %d\n", __func__, peripheral);
-
-	switch (source) {
-	case S3C2410_DMASRC_HW:
-		config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
-		config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
-		break;
-	case S3C2410_DMASRC_MEM:
-		config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
-		config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
-		break;
-	default:
-		printk(KERN_ERR "%s: bad source\n", __func__);
-		return -EINVAL;
-	}
-
-	/* allow TC and ERR interrupts */
-	config |= PL080_CONFIG_TC_IRQ_MASK;
-	config |= PL080_CONFIG_ERR_IRQ_MASK;
-
-	pr_debug("%s: config %08x\n", __func__, config);
-
-	writel(config, chan->regs + PL080S_CH_CONFIG);
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-
-int s3c2410_dma_getposition(unsigned int channel,
-			    dma_addr_t *src, dma_addr_t *dst)
-{
-	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-
-	WARN_ON(!chan);
-	if (!chan)
-		return -EINVAL;
-
-	if (src != NULL)
-		*src = readl(chan->regs + PL080_CH_SRC_ADDR);
-
-	if (dst != NULL)
-		*dst = readl(chan->regs + PL080_CH_DST_ADDR);
-
-	return 0;
-}
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-/* s3c2410_request_dma
- *
- * get control of an dma channel
-*/
-
-int s3c2410_dma_request(unsigned int channel,
-			struct s3c2410_dma_client *client,
-			void *dev)
-{
-	struct s3c2410_dma_chan *chan;
-	unsigned long flags;
-
-	pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
-		 channel, client->name, dev);
-
-	local_irq_save(flags);
-
-	chan = s3c64xx_dma_map_channel(channel);
-	if (chan == NULL) {
-		local_irq_restore(flags);
-		return -EBUSY;
-	}
-
-	dbg_showchan(chan);
-
-	chan->client = client;
-	chan->in_use = 1;
-	chan->peripheral = channel;
-
-	local_irq_restore(flags);
-
-	/* need to setup */
-
-	pr_debug("%s: channel initialised, %p\n", __func__, chan);
-
-	return chan->number | DMACH_LOW_LEVEL;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-/* s3c2410_dma_free
- *
- * release the given channel back to the system, will stop and flush
- * any outstanding transfers, and ensure the channel is ready for the
- * next claimant.
- *
- * Note, although a warning is currently printed if the freeing client
- * info is not the same as the registrant's client info, the free is still
- * allowed to go through.
-*/
-
-int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
-{
-	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
-	unsigned long flags;
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	local_irq_save(flags);
-
-	if (chan->client != client) {
-		printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
-		       channel, chan->client, client);
-	}
-
-	/* sort out stopping and freeing the channel */
-
-
-	chan->client = NULL;
-	chan->in_use = 0;
-
-	if (!(channel & DMACH_LOW_LEVEL))
-		s3c_dma_chan_map[channel] = NULL;
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
-{
-	struct s3c64xx_dmac *dmac = pw;
-	struct s3c2410_dma_chan *chan;
-	enum s3c2410_dma_buffresult res;
-	u32 tcstat, errstat;
-	u32 bit;
-	int offs;
-
-	tcstat = readl(dmac->regs + PL080_TC_STATUS);
-	errstat = readl(dmac->regs + PL080_ERR_STATUS);
-
-	for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) {
-		struct s3c64xx_dma_buff *buff;
-
-		if (!(errstat & bit) && !(tcstat & bit))
-			continue;
-
-		chan = dmac->channels + offs;
-		res = S3C2410_RES_ERR;
-
-		if (tcstat & bit) {
-			writel(bit, dmac->regs + PL080_TC_CLEAR);
-			res = S3C2410_RES_OK;
-		}
-
-		if (errstat & bit)
-			writel(bit, dmac->regs + PL080_ERR_CLEAR);
-
-		/* 'next' points to the buffer that is next to the
-		 * currently active buffer.
-		 * For CIRCULAR queues, 'next' will be same as 'curr'
-		 * when 'end' is the active buffer.
-		 */
-		buff = chan->curr;
-		while (buff && buff != chan->next
-				&& buff->next != chan->next)
-			buff = buff->next;
-
-		if (!buff)
-			BUG();
-
-		if (buff == chan->next)
-			buff = chan->end;
-
-		s3c64xx_dma_bufffdone(chan, buff, res);
-
-		/* Free the node and update curr, if non-circular queue */
-		if (!(chan->flags & S3C2410_DMAF_CIRCULAR)) {
-			chan->curr = buff->next;
-			s3c64xx_dma_freebuff(buff);
-		}
-
-		/* Update 'next' */
-		buff = chan->next;
-		if (chan->next == chan->end) {
-			chan->next = chan->curr;
-			if (!(chan->flags & S3C2410_DMAF_CIRCULAR))
-				chan->end = NULL;
-		} else {
-			chan->next = buff->next;
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-static struct sysdev_class dma_sysclass = {
-	.name		= "s3c64xx-dma",
-};
-
-static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
-			     int irq, unsigned int base)
-{
-	struct s3c2410_dma_chan *chptr = &s3c2410_chans[chno];
-	struct s3c64xx_dmac *dmac;
-	char clkname[16];
-	void __iomem *regs;
-	void __iomem *regptr;
-	int err, ch;
-
-	dmac = kzalloc(sizeof(struct s3c64xx_dmac), GFP_KERNEL);
-	if (!dmac) {
-		printk(KERN_ERR "%s: failed to alloc mem\n", __func__);
-		return -ENOMEM;
-	}
-
-	dmac->sysdev.id = chno / 8;
-	dmac->sysdev.cls = &dma_sysclass;
-
-	err = sysdev_register(&dmac->sysdev);
-	if (err) {
-		printk(KERN_ERR "%s: failed to register sysdevice\n", __func__);
-		goto err_alloc;
-	}
-
-	regs = ioremap(base, 0x200);
-	if (!regs) {
-		printk(KERN_ERR "%s: failed to ioremap()\n", __func__);
-		err = -ENXIO;
-		goto err_dev;
-	}
-
-	snprintf(clkname, sizeof(clkname), "dma%d", dmac->sysdev.id);
-
-	dmac->clk = clk_get(NULL, clkname);
-	if (IS_ERR(dmac->clk)) {
-		printk(KERN_ERR "%s: failed to get clock %s\n", __func__, clkname);
-		err = PTR_ERR(dmac->clk);
-		goto err_map;
-	}
-
-	clk_enable(dmac->clk);
-
-	dmac->regs = regs;
-	dmac->chanbase = chbase;
-	dmac->channels = chptr;
-
-	err = request_irq(irq, s3c64xx_dma_irq, 0, "DMA", dmac);
-	if (err < 0) {
-		printk(KERN_ERR "%s: failed to get irq\n", __func__);
-		goto err_clk;
-	}
-
-	regptr = regs + PL080_Cx_BASE(0);
-
-	for (ch = 0; ch < 8; ch++, chno++, chptr++) {
-		printk(KERN_INFO "%s: registering DMA %d (%p)\n",
-		       __func__, chno, regptr);
-
-		chptr->bit = 1 << ch;
-		chptr->number = chno;
-		chptr->dmac = dmac;
-		chptr->regs = regptr;
-		regptr += PL008_Cx_STRIDE;
-	}
-
-	/* for the moment, permanently enable the controller */
-	writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG);
-
-	printk(KERN_INFO "PL080: IRQ %d, at %p\n", irq, regs);
-
-	return 0;
-
-err_clk:
-	clk_disable(dmac->clk);
-	clk_put(dmac->clk);
-err_map:
-	iounmap(regs);
-err_dev:
-	sysdev_unregister(&dmac->sysdev);
-err_alloc:
-	kfree(dmac);
-	return err;
-}
-
-static int __init s3c64xx_dma_init(void)
-{
-	int ret;
-
-	printk(KERN_INFO "%s: Registering DMA channels\n", __func__);
-
-	dma_pool = dma_pool_create("DMA-LLI", NULL, sizeof(struct pl080s_lli), 16, 0);
-	if (!dma_pool) {
-		printk(KERN_ERR "%s: failed to create pool\n", __func__);
-		return -ENOMEM;
-	}
-
-	ret = sysdev_class_register(&dma_sysclass);
-	if (ret) {
-		printk(KERN_ERR "%s: failed to create sysclass\n", __func__);
-		return -ENOMEM;
-	}
-
-	/* Set all DMA configuration to be DMA, not SDMA */
-	writel(0xffffff, S3C_SYSREG(0x110));
-
-	/* Register standard DMA controlers */
-	s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
-	s3c64xx_dma_init1(8, DMACH_PCM1_TX, IRQ_DMA1, 0x75100000);
-
-	return 0;
-}
-
-arch_initcall(s3c64xx_dma_init);
diff --git a/arch/arm/plat-s3c64xx/gpiolib.c b/arch/arm/plat-s3c64xx/gpiolib.c
deleted file mode 100644
index 7785604..0000000
--- a/arch/arm/plat-s3c64xx/gpiolib.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/* arch/arm/plat-s3c64xx/gpiolib.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - GPIOlib support 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <mach/map.h>
-#include <mach/gpio.h>
-#include <mach/gpio-core.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <plat/regs-gpio.h>
-
-/* GPIO bank summary:
- *
- * Bank	GPIOs	Style	SlpCon	ExtInt Group
- * A	8	4Bit	Yes	1
- * B	7	4Bit	Yes	1
- * C	8	4Bit	Yes	2
- * D	5	4Bit	Yes	3
- * E	5	4Bit	Yes	None
- * F	16	2Bit	Yes	4 [1]
- * G	7	4Bit	Yes	5
- * H	10	4Bit[2]	Yes	6
- * I	16	2Bit	Yes	None
- * J	12	2Bit	Yes	None
- * K	16	4Bit[2]	No	None
- * L	15	4Bit[2] No	None
- * M	6	4Bit	No	IRQ_EINT
- * N	16	2Bit	No	IRQ_EINT
- * O	16	2Bit	Yes	7
- * P	15	2Bit	Yes	8
- * Q	9	2Bit	Yes	9
- *
- * [1] BANKF pins 14,15 do not form part of the external interrupt sources
- * [2] BANK has two control registers, GPxCON0 and GPxCON1
- */
-
-#define OFF_GPCON	(0x00)
-#define OFF_GPDAT	(0x04)
-
-#define con_4bit_shift(__off) ((__off) * 4)
-
-#if 1
-#define gpio_dbg(x...) do { } while(0)
-#else
-#define gpio_dbg(x...) printk(KERN_DEBUG x)
-#endif
-
-/* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where
- * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
- * following example:
- *
- * base + 0x00: Control register, 4 bits per gpio
- *	        gpio n: 4 bits starting at (4*n)
- *		0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *		bit n: data bit n
- *
- * Note, since the data register is one bit per gpio and is at base + 0x4
- * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
- * the output.
-*/
-
-static int s3c64xx_gpiolib_4bit_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long con;
-
-	con = __raw_readl(base + OFF_GPCON);
-	con &= ~(0xf << con_4bit_shift(offset));
-	__raw_writel(con, base + OFF_GPCON);
-
-	gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
-
-	return 0;
-}
-
-static int s3c64xx_gpiolib_4bit_output(struct gpio_chip *chip,
-				       unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long con;
-	unsigned long dat;
-
-	con = __raw_readl(base + OFF_GPCON);
-	con &= ~(0xf << con_4bit_shift(offset));
-	con |= 0x1 << con_4bit_shift(offset);
-
-	dat = __raw_readl(base + OFF_GPDAT);
-	if (value)
-		dat |= 1 << offset;
-	else
-		dat &= ~(1 << offset);
-
-	__raw_writel(dat, base + OFF_GPDAT);
-	__raw_writel(con, base + OFF_GPCON);
-	__raw_writel(dat, base + OFF_GPDAT);
-
-	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-	return 0;
-}
-
-/* The next set of routines are for the case where the GPIO configuration
- * registers are 4 bits per GPIO but there is more than one register (the
- * bank has more than 8 GPIOs.
- *
- * This case is the similar to the 4 bit case, but the registers are as
- * follows:
- *
- * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
- *	        gpio n: 4 bits starting at (4*n)
- *		0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
- *	        gpio n: 4 bits starting at (4*n)
- *		0000 = input, 0001 = output, others mean special-function
- * base + 0x08: Data register, 1 bit per gpio
- *		bit n: data bit n
- *
- * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
- * store the 'base + 0x4' address so that these routines see the data
- * register at ourchip->base + 0x04.
-*/
-
-static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	void __iomem *regcon = base;
-	unsigned long con;
-
-	if (offset > 7)
-		offset -= 8;
-	else
-		regcon -= 4;
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(offset));
-	__raw_writel(con, regcon);
-
-	gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
-
-	return 0;
-
-}
-
-static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip *chip,
-				       unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	void __iomem *regcon = base;
-	unsigned long con;
-	unsigned long dat;
-
-	if (offset > 7)
-		offset -= 8;
-	else
-		regcon -= 4;
-
-	con = __raw_readl(regcon);
-	con &= ~(0xf << con_4bit_shift(offset));
-	con |= 0x1 << con_4bit_shift(offset);
-
-	dat = __raw_readl(base + OFF_GPDAT);
-	if (value)
-		dat |= 1 << offset;
-	else
-		dat &= ~(1 << offset);
-
-	__raw_writel(dat, base + OFF_GPDAT);
-	__raw_writel(con, regcon);
-	__raw_writel(dat, base + OFF_GPDAT);
-
-	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-	return 0;
-}
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
-	.cfg_eint	= 7,
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
-	.cfg_eint	= 3,
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin)
-{
-	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
-}
-
-static struct s3c_gpio_chip gpio_4bit[] = {
-	{
-		.base	= S3C64XX_GPA_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPA(0),
-			.ngpio	= S3C64XX_GPIO_A_NR,
-			.label	= "GPA",
-		},
-	}, {
-		.base	= S3C64XX_GPB_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPB(0),
-			.ngpio	= S3C64XX_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.base	= S3C64XX_GPC_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPC(0),
-			.ngpio	= S3C64XX_GPIO_C_NR,
-			.label	= "GPC",
-		},
-	}, {
-		.base	= S3C64XX_GPD_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPD(0),
-			.ngpio	= S3C64XX_GPIO_D_NR,
-			.label	= "GPD",
-		},
-	}, {
-		.base	= S3C64XX_GPE_BASE,
-		.config	= &gpio_4bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPE(0),
-			.ngpio	= S3C64XX_GPIO_E_NR,
-			.label	= "GPE",
-		},
-	}, {
-		.base	= S3C64XX_GPG_BASE,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPG(0),
-			.ngpio	= S3C64XX_GPIO_G_NR,
-			.label	= "GPG",
-		},
-	}, {
-		.base	= S3C64XX_GPM_BASE,
-		.config	= &gpio_4bit_cfg_eint0011,
-		.chip	= {
-			.base	= S3C64XX_GPM(0),
-			.ngpio	= S3C64XX_GPIO_M_NR,
-			.label	= "GPM",
-			.to_irq = s3c64xx_gpio2int_gpm,
-		},
-	},
-};
-
-int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin)
-{
-	return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
-}
-
-static struct s3c_gpio_chip gpio_4bit2[] = {
-	{
-		.base	= S3C64XX_GPH_BASE + 0x4,
-		.config	= &gpio_4bit_cfg_eint0111,
-		.chip	= {
-			.base	= S3C64XX_GPH(0),
-			.ngpio	= S3C64XX_GPIO_H_NR,
-			.label	= "GPH",
-		},
-	}, {
-		.base	= S3C64XX_GPK_BASE + 0x4,
-		.config	= &gpio_4bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPK(0),
-			.ngpio	= S3C64XX_GPIO_K_NR,
-			.label	= "GPK",
-		},
-	}, {
-		.base	= S3C64XX_GPL_BASE + 0x4,
-		.config	= &gpio_4bit_cfg_eint0011,
-		.chip	= {
-			.base	= S3C64XX_GPL(0),
-			.ngpio	= S3C64XX_GPIO_L_NR,
-			.label	= "GPL",
-			.to_irq = s3c64xx_gpio2int_gpl,
-		},
-	},
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
-	.cfg_eint	= 2,
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
-	.cfg_eint	= 3,
-	.set_config	= s3c_gpio_setcfg_s3c24xx,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin)
-{
-	return IRQ_EINT(0) + pin;
-}
-
-static struct s3c_gpio_chip gpio_2bit[] = {
-	{
-		.base	= S3C64XX_GPF_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPF(0),
-			.ngpio	= S3C64XX_GPIO_F_NR,
-			.label	= "GPF",
-		},
-	}, {
-		.base	= S3C64XX_GPI_BASE,
-		.config	= &gpio_2bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPI(0),
-			.ngpio	= S3C64XX_GPIO_I_NR,
-			.label	= "GPI",
-		},
-	}, {
-		.base	= S3C64XX_GPJ_BASE,
-		.config	= &gpio_2bit_cfg_noint,
-		.chip	= {
-			.base	= S3C64XX_GPJ(0),
-			.ngpio	= S3C64XX_GPIO_J_NR,
-			.label	= "GPJ",
-		},
-	}, {
-		.base	= S3C64XX_GPN_BASE,
-		.config	= &gpio_2bit_cfg_eint10,
-		.chip	= {
-			.base	= S3C64XX_GPN(0),
-			.ngpio	= S3C64XX_GPIO_N_NR,
-			.label	= "GPN",
-			.to_irq = s3c64xx_gpio2int_gpn,
-		},
-	}, {
-		.base	= S3C64XX_GPO_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPO(0),
-			.ngpio	= S3C64XX_GPIO_O_NR,
-			.label	= "GPO",
-		},
-	}, {
-		.base	= S3C64XX_GPP_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPP(0),
-			.ngpio	= S3C64XX_GPIO_P_NR,
-			.label	= "GPP",
-		},
-	}, {
-		.base	= S3C64XX_GPQ_BASE,
-		.config	= &gpio_2bit_cfg_eint11,
-		.chip	= {
-			.base	= S3C64XX_GPQ(0),
-			.ngpio	= S3C64XX_GPIO_Q_NR,
-			.label	= "GPQ",
-		},
-	},
-};
-
-static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
-{
-	chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
-	chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
-	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
-{
-	chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
-	chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
-	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
-{
-	chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
-}
-
-static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
-				       int nr_chips,
-				       void (*fn)(struct s3c_gpio_chip *))
-{
-	for (; nr_chips > 0; nr_chips--, chips++) {
-		if (fn)
-			(fn)(chips);
-		s3c_gpiolib_add(chips);
-	}
-}
-
-static __init int s3c64xx_gpiolib_init(void)
-{
-	s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
-			    s3c64xx_gpiolib_add_4bit);
-
-	s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
-			    s3c64xx_gpiolib_add_4bit2);
-
-	s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
-			    s3c64xx_gpiolib_add_2bit);
-
-	return 0;
-}
-
-core_initcall(s3c64xx_gpiolib_init);
diff --git a/arch/arm/plat-s3c64xx/include/plat/dma-plat.h b/arch/arm/plat-s3c64xx/include/plat/dma-plat.h
deleted file mode 100644
index 8f76a1e..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/dma-plat.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/dma-plat.h
- *
- * Copyright 2009 Openmoko, Inc.
- * Copyright 2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C64XX DMA core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
-
-struct s3c64xx_dma_buff;
-
-/** s3c64xx_dma_buff - S3C64XX DMA buffer descriptor
- * @next: Pointer to next buffer in queue or ring.
- * @pw: Client provided identifier
- * @lli: Pointer to hardware descriptor this buffer is associated with.
- * @lli_dma: Hardare address of the descriptor.
- */
-struct s3c64xx_dma_buff {
-	struct s3c64xx_dma_buff *next;
-
-	void			*pw;
-	struct pl080s_lli	*lli;
-	dma_addr_t		 lli_dma;
-};
-
-struct s3c64xx_dmac;
-
-struct s3c2410_dma_chan {
-	unsigned char		 number;      /* number of this dma channel */
-	unsigned char		 in_use;      /* channel allocated */
-	unsigned char		 bit;	      /* bit for enable/disable/etc */
-	unsigned char		 hw_width;
-	unsigned char		 peripheral;
-
-	unsigned int		 flags;
-	enum s3c2410_dmasrc	 source;
-
-
-	dma_addr_t		dev_addr;
-
-	struct s3c2410_dma_client *client;
-	struct s3c64xx_dmac	*dmac;		/* pointer to controller */
-
-	void __iomem		*regs;
-
-	/* cdriver callbacks */
-	s3c2410_dma_cbfn_t	 callback_fn;	/* buffer done callback */
-	s3c2410_dma_opfn_t	 op_fn;		/* channel op callback */
-
-	/* buffer list and information */
-	struct s3c64xx_dma_buff	*curr;		/* current dma buffer */
-	struct s3c64xx_dma_buff	*next;		/* next buffer to load */
-	struct s3c64xx_dma_buff	*end;		/* end of queue */
-
-	/* note, when channel is running in circular mode, curr is the
-	 * first buffer enqueued, end is the last and curr is where the
-	 * last buffer-done event is set-at. The buffers are not freed
-	 * and the last buffer hardware descriptor points back to the
-	 * first.
-	 */
-};
-
-#include <plat/dma-core.h>
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-a.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-a.h
deleted file mode 100644
index 9aa0e42..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-a.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-a.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank A register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPACON			(S3C64XX_GPA_BASE + 0x00)
-#define S3C64XX_GPADAT			(S3C64XX_GPA_BASE + 0x04)
-#define S3C64XX_GPAPUD			(S3C64XX_GPA_BASE + 0x08)
-#define S3C64XX_GPACONSLP		(S3C64XX_GPA_BASE + 0x0c)
-#define S3C64XX_GPAPUDSLP		(S3C64XX_GPA_BASE + 0x10)
-
-#define S3C64XX_GPA_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
-#define S3C64XX_GPA_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
-#define S3C64XX_GPA_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
-
-#define S3C64XX_GPA0_UART_RXD0		(0x02 << 0)
-#define S3C64XX_GPA0_EINT_G1_0		(0x07 << 0)
-
-#define S3C64XX_GPA1_UART_TXD0		(0x02 << 4)
-#define S3C64XX_GPA1_EINT_G1_1		(0x07 << 4)
-
-#define S3C64XX_GPA2_UART_nCTS0		(0x02 << 8)
-#define S3C64XX_GPA2_EINT_G1_2		(0x07 << 8)
-
-#define S3C64XX_GPA3_UART_nRTS0		(0x02 << 12)
-#define S3C64XX_GPA3_EINT_G1_3		(0x07 << 12)
-
-#define S3C64XX_GPA4_UART_RXD1		(0x02 << 16)
-#define S3C64XX_GPA4_EINT_G1_4		(0x07 << 16)
-
-#define S3C64XX_GPA5_UART_TXD1		(0x02 << 20)
-#define S3C64XX_GPA5_EINT_G1_5		(0x07 << 20)
-
-#define S3C64XX_GPA6_UART_nCTS1		(0x02 << 24)
-#define S3C64XX_GPA6_EINT_G1_6		(0x07 << 24)
-
-#define S3C64XX_GPA7_UART_nRTS1		(0x02 << 28)
-#define S3C64XX_GPA7_EINT_G1_7		(0x07 << 28)
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-b.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-b.h
deleted file mode 100644
index 3933adb..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-b.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-b.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank B register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPBCON			(S3C64XX_GPB_BASE + 0x00)
-#define S3C64XX_GPBDAT			(S3C64XX_GPB_BASE + 0x04)
-#define S3C64XX_GPBPUD			(S3C64XX_GPB_BASE + 0x08)
-#define S3C64XX_GPBCONSLP		(S3C64XX_GPB_BASE + 0x0c)
-#define S3C64XX_GPBPUDSLP		(S3C64XX_GPB_BASE + 0x10)
-
-#define S3C64XX_GPB_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
-#define S3C64XX_GPB_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
-#define S3C64XX_GPB_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
-
-#define S3C64XX_GPB0_UART_RXD2		(0x02 << 0)
-#define S3C64XX_GPB0_EXTDMA_REQ		(0x03 << 0)
-#define S3C64XX_GPB0_IrDA_RXD		(0x04 << 0)
-#define S3C64XX_GPB0_ADDR_CF0		(0x05 << 0)
-#define S3C64XX_GPB0_EINT_G1_8		(0x07 << 0)
-
-#define S3C64XX_GPB1_UART_TXD2		(0x02 << 4)
-#define S3C64XX_GPB1_EXTDMA_ACK		(0x03 << 4)
-#define S3C64XX_GPB1_IrDA_TXD		(0x04 << 4)
-#define S3C64XX_GPB1_ADDR_CF1		(0x05 << 4)
-#define S3C64XX_GPB1_EINT_G1_9		(0x07 << 4)
-
-#define S3C64XX_GPB2_UART_RXD3		(0x02 << 8)
-#define S3C64XX_GPB2_IrDA_RXD		(0x03 << 8)
-#define S3C64XX_GPB2_EXTDMA_REQ		(0x04 << 8)
-#define S3C64XX_GPB2_ADDR_CF2		(0x05 << 8)
-#define S3C64XX_GPB2_I2C_SCL1		(0x06 << 8)
-#define S3C64XX_GPB2_EINT_G1_10		(0x07 << 8)
-
-#define S3C64XX_GPB3_UART_TXD3		(0x02 << 12)
-#define S3C64XX_GPB3_IrDA_TXD		(0x03 << 12)
-#define S3C64XX_GPB3_EXTDMA_ACK		(0x04 << 12)
-#define S3C64XX_GPB3_I2C_SDA1		(0x06 << 12)
-#define S3C64XX_GPB3_EINT_G1_11		(0x07 << 12)
-
-#define S3C64XX_GPB4_IrDA_SDBW		(0x02 << 16)
-#define S3C64XX_GPB4_CAM_FIELD		(0x03 << 16)
-#define S3C64XX_GPB4_CF_DATA_DIR	(0x04 << 16)
-#define S3C64XX_GPB4_EINT_G1_12		(0x07 << 16)
-
-#define S3C64XX_GPB5_I2C_SCL0		(0x02 << 20)
-#define S3C64XX_GPB5_EINT_G1_13		(0x07 << 20)
-
-#define S3C64XX_GPB6_I2C_SDA0		(0x02 << 24)
-#define S3C64XX_GPB6_EINT_G1_14		(0x07 << 24)
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-c.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-c.h
deleted file mode 100644
index e22b49f..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-c.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-c.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank C register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPCCON			(S3C64XX_GPC_BASE + 0x00)
-#define S3C64XX_GPCDAT			(S3C64XX_GPC_BASE + 0x04)
-#define S3C64XX_GPCPUD			(S3C64XX_GPC_BASE + 0x08)
-#define S3C64XX_GPCCONSLP		(S3C64XX_GPC_BASE + 0x0c)
-#define S3C64XX_GPCPUDSLP		(S3C64XX_GPC_BASE + 0x10)
-
-#define S3C64XX_GPC_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
-#define S3C64XX_GPC_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
-#define S3C64XX_GPC_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
-
-#define S3C64XX_GPC0_SPI_MISO0		(0x02 << 0)
-#define S3C64XX_GPC0_EINT_G2_0		(0x07 << 0)
-
-#define S3C64XX_GPC1_SPI_CLKO		(0x02 << 4)
-#define S3C64XX_GPC1_EINT_G2_1		(0x07 << 4)
-
-#define S3C64XX_GPC2_SPI_MOSIO		(0x02 << 8)
-#define S3C64XX_GPC2_EINT_G2_2		(0x07 << 8)
-
-#define S3C64XX_GPC3_SPI_nCSO		(0x02 << 12)
-#define S3C64XX_GPC3_EINT_G2_3		(0x07 << 12)
-
-#define S3C64XX_GPC4_SPI_MISO1		(0x02 << 16)
-#define S3C64XX_GPC4_MMC2_CMD		(0x03 << 16)
-#define S3C64XX_GPC4_I2S_V40_DO0	(0x05 << 16)
-#define S3C64XX_GPC4_EINT_G2_4		(0x07 << 16)
-
-#define S3C64XX_GPC5_SPI_CLK1		(0x02 << 20)
-#define S3C64XX_GPC5_MMC2_CLK		(0x03 << 20)
-#define S3C64XX_GPC5_I2S_V40_DO1	(0x05 << 20)
-#define S3C64XX_GPC5_EINT_G2_5		(0x07 << 20)
-
-#define S3C64XX_GPC6_SPI_MOSI1		(0x02 << 24)
-#define S3C64XX_GPC6_EINT_G2_6		(0x07 << 24)
-
-#define S3C64XX_GPC7_SPI_nCS1		(0x02 << 28)
-#define S3C64XX_GPC7_I2S_V40_DO2	(0x05 << 28)
-#define S3C64XX_GPC7_EINT_G2_7		(0x07 << 28)
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-d.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-d.h
deleted file mode 100644
index 6fe4a49..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-d.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-d.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank D register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPDCON			(S3C64XX_GPD_BASE + 0x00)
-#define S3C64XX_GPDDAT			(S3C64XX_GPD_BASE + 0x04)
-#define S3C64XX_GPDPUD			(S3C64XX_GPD_BASE + 0x08)
-#define S3C64XX_GPDCONSLP		(S3C64XX_GPD_BASE + 0x0c)
-#define S3C64XX_GPDPUDSLP		(S3C64XX_GPD_BASE + 0x10)
-
-#define S3C64XX_GPD_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
-#define S3C64XX_GPD_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
-#define S3C64XX_GPD_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
-
-#define S3C64XX_GPD0_PCM0_SCLK		(0x02 << 0)
-#define S3C64XX_GPD0_I2S0_CLK		(0x03 << 0)
-#define S3C64XX_GPD0_AC97_BITCLK	(0x04 << 0)
-#define S3C64XX_GPD0_EINT_G3_0		(0x07 << 0)
-
-#define S3C64XX_GPD1_PCM0_EXTCLK	(0x02 << 4)
-#define S3C64XX_GPD1_I2S0_CDCLK		(0x03 << 4)
-#define S3C64XX_GPD1_AC97_nRESET	(0x04 << 4)
-#define S3C64XX_GPD1_EINT_G3_1		(0x07 << 4)
-
-#define S3C64XX_GPD2_PCM0_FSYNC		(0x02 << 8)
-#define S3C64XX_GPD2_I2S0_LRCLK		(0x03 << 8)
-#define S3C64XX_GPD2_AC97_SYNC		(0x04 << 8)
-#define S3C64XX_GPD2_EINT_G3_2		(0x07 << 8)
-
-#define S3C64XX_GPD3_PCM0_SIN		(0x02 << 12)
-#define S3C64XX_GPD3_I2S0_DI		(0x03 << 12)
-#define S3C64XX_GPD3_AC97_SDI		(0x04 << 12)
-#define S3C64XX_GPD3_EINT_G3_3		(0x07 << 12)
-
-#define S3C64XX_GPD4_PCM0_SOUT		(0x02 << 16)
-#define S3C64XX_GPD4_I2S0_D0		(0x03 << 16)
-#define S3C64XX_GPD4_AC97_SDO		(0x04 << 16)
-#define S3C64XX_GPD4_EINT_G3_4		(0x07 << 16)
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-e.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-e.h
deleted file mode 100644
index 7fcf3d8..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-e.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-e.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank E register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPECON			(S3C64XX_GPE_BASE + 0x00)
-#define S3C64XX_GPEDAT			(S3C64XX_GPE_BASE + 0x04)
-#define S3C64XX_GPEPUD			(S3C64XX_GPE_BASE + 0x08)
-#define S3C64XX_GPECONSLP		(S3C64XX_GPE_BASE + 0x0c)
-#define S3C64XX_GPEPUDSLP		(S3C64XX_GPE_BASE + 0x10)
-
-#define S3C64XX_GPE_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
-#define S3C64XX_GPE_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
-#define S3C64XX_GPE_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
-
-#define S3C64XX_GPE0_PCM1_SCLK		(0x02 << 0)
-#define S3C64XX_GPE0_I2S1_CLK		(0x03 << 0)
-#define S3C64XX_GPE0_AC97_BITCLK	(0x04 << 0)
-
-#define S3C64XX_GPE1_PCM1_EXTCLK	(0x02 << 4)
-#define S3C64XX_GPE1_I2S1_CDCLK		(0x03 << 4)
-#define S3C64XX_GPE1_AC97_nRESET	(0x04 << 4)
-
-#define S3C64XX_GPE2_PCM1_FSYNC		(0x02 << 8)
-#define S3C64XX_GPE2_I2S1_LRCLK		(0x03 << 8)
-#define S3C64XX_GPE2_AC97_SYNC		(0x04 << 8)
-
-#define S3C64XX_GPE3_PCM1_SIN		(0x02 << 12)
-#define S3C64XX_GPE3_I2S1_DI		(0x03 << 12)
-#define S3C64XX_GPE3_AC97_SDI		(0x04 << 12)
-
-#define S3C64XX_GPE4_PCM1_SOUT		(0x02 << 16)
-#define S3C64XX_GPE4_I2S1_D0		(0x03 << 16)
-#define S3C64XX_GPE4_AC97_SDO		(0x04 << 16)
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-f.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-f.h
deleted file mode 100644
index f3faff9..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-f.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-f.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank F register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPFCON			(S3C64XX_GPF_BASE + 0x00)
-#define S3C64XX_GPFDAT			(S3C64XX_GPF_BASE + 0x04)
-#define S3C64XX_GPFPUD			(S3C64XX_GPF_BASE + 0x08)
-#define S3C64XX_GPFCONSLP		(S3C64XX_GPF_BASE + 0x0c)
-#define S3C64XX_GPFPUDSLP		(S3C64XX_GPF_BASE + 0x10)
-
-#define S3C64XX_GPF_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
-#define S3C64XX_GPF_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
-#define S3C64XX_GPF_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
-
-#define S3C64XX_GPF0_CAMIF_CLK		(0x02 << 0)
-#define S3C64XX_GPF0_EINT_G4_0		(0x03 << 0)
-
-#define S3C64XX_GPF1_CAMIF_HREF		(0x02 << 2)
-#define S3C64XX_GPF1_EINT_G4_1		(0x03 << 2)
-
-#define S3C64XX_GPF2_CAMIF_PCLK		(0x02 << 4)
-#define S3C64XX_GPF2_EINT_G4_2		(0x03 << 4)
-
-#define S3C64XX_GPF3_CAMIF_nRST		(0x02 << 6)
-#define S3C64XX_GPF3_EINT_G4_3		(0x03 << 6)
-
-#define S3C64XX_GPF4_CAMIF_VSYNC	(0x02 << 8)
-#define S3C64XX_GPF4_EINT_G4_4		(0x03 << 8)
-
-#define S3C64XX_GPF5_CAMIF_YDATA0	(0x02 << 10)
-#define S3C64XX_GPF5_EINT_G4_5		(0x03 << 10)
-
-#define S3C64XX_GPF6_CAMIF_YDATA1	(0x02 << 12)
-#define S3C64XX_GPF6_EINT_G4_6		(0x03 << 12)
-
-#define S3C64XX_GPF7_CAMIF_YDATA2	(0x02 << 14)
-#define S3C64XX_GPF7_EINT_G4_7		(0x03 << 14)
-
-#define S3C64XX_GPF8_CAMIF_YDATA3	(0x02 << 16)
-#define S3C64XX_GPF8_EINT_G4_8		(0x03 << 16)
-
-#define S3C64XX_GPF9_CAMIF_YDATA4	(0x02 << 18)
-#define S3C64XX_GPF9_EINT_G4_9		(0x03 << 18)
-
-#define S3C64XX_GPF10_CAMIF_YDATA5	(0x02 << 20)
-#define S3C64XX_GPF10_EINT_G4_10	(0x03 << 20)
-
-#define S3C64XX_GPF11_CAMIF_YDATA6	(0x02 << 22)
-#define S3C64XX_GPF11_EINT_G4_11	(0x03 << 22)
-
-#define S3C64XX_GPF12_CAMIF_YDATA7	(0x02 << 24)
-#define S3C64XX_GPF12_EINT_G4_12	(0x03 << 24)
-
-#define S3C64XX_GPF13_PWM_ECLK		(0x02 << 26)
-#define S3C64XX_GPF13_EINT_G4_13	(0x03 << 26)
-
-#define S3C64XX_GPF14_PWM_TOUT0		(0x02 << 28)
-#define S3C64XX_GPF14_CLKOUT0		(0x03 << 28)
-
-#define S3C64XX_GPF15_PWM_TOUT1		(0x02 << 30)
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-g.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-g.h
deleted file mode 100644
index 35bbd23..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-g.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-g.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank G register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPGCON			(S3C64XX_GPG_BASE + 0x00)
-#define S3C64XX_GPGDAT			(S3C64XX_GPG_BASE + 0x04)
-#define S3C64XX_GPGPUD			(S3C64XX_GPG_BASE + 0x08)
-#define S3C64XX_GPGCONSLP		(S3C64XX_GPG_BASE + 0x0c)
-#define S3C64XX_GPGPUDSLP		(S3C64XX_GPG_BASE + 0x10)
-
-#define S3C64XX_GPG_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
-#define S3C64XX_GPG_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
-#define S3C64XX_GPG_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
-
-#define S3C64XX_GPG0_MMC0_CLK		(0x02 << 0)
-#define S3C64XX_GPG0_EINT_G5_0		(0x07 << 0)
-
-#define S3C64XX_GPG1_MMC0_CMD		(0x02 << 4)
-#define S3C64XX_GPG1_EINT_G5_1		(0x07 << 4)
-
-#define S3C64XX_GPG2_MMC0_DATA0		(0x02 << 8)
-#define S3C64XX_GPG2_EINT_G5_2		(0x07 << 8)
-
-#define S3C64XX_GPG3_MMC0_DATA1		(0x02 << 12)
-#define S3C64XX_GPG3_EINT_G5_3		(0x07 << 12)
-
-#define S3C64XX_GPG4_MMC0_DATA2		(0x02 << 16)
-#define S3C64XX_GPG4_EINT_G5_4		(0x07 << 16)
-
-#define S3C64XX_GPG5_MMC0_DATA3		(0x02 << 20)
-#define S3C64XX_GPG5_EINT_G5_5		(0x07 << 20)
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-h.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-h.h
deleted file mode 100644
index 2ba1767..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-h.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-h.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank H register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPHCON0			(S3C64XX_GPH_BASE + 0x00)
-#define S3C64XX_GPHCON1			(S3C64XX_GPH_BASE + 0x04)
-#define S3C64XX_GPHDAT			(S3C64XX_GPH_BASE + 0x08)
-#define S3C64XX_GPHPUD			(S3C64XX_GPH_BASE + 0x0c)
-#define S3C64XX_GPHCONSLP		(S3C64XX_GPH_BASE + 0x10)
-#define S3C64XX_GPHPUDSLP		(S3C64XX_GPH_BASE + 0x14)
-
-#define S3C64XX_GPH_CONMASK(__gpio)	(0xf << ((__gpio) * 4))
-#define S3C64XX_GPH_INPUT(__gpio)	(0x0 << ((__gpio) * 4))
-#define S3C64XX_GPH_OUTPUT(__gpio)	(0x1 << ((__gpio) * 4))
-
-#define S3C64XX_GPH0_MMC1_CLK		(0x02 << 0)
-#define S3C64XX_GPH0_KP_COL0		(0x04 << 0)
-#define S3C64XX_GPH0_EINT_G6_0		(0x07 << 0)
-
-#define S3C64XX_GPH1_MMC1_CMD		(0x02 << 4)
-#define S3C64XX_GPH1_KP_COL1		(0x04 << 4)
-#define S3C64XX_GPH1_EINT_G6_1		(0x07 << 4)
-
-#define S3C64XX_GPH2_MMC1_DATA0		(0x02 << 8)
-#define S3C64XX_GPH2_KP_COL2		(0x04 << 8)
-#define S3C64XX_GPH2_EINT_G6_2		(0x07 << 8)
-
-#define S3C64XX_GPH3_MMC1_DATA1		(0x02 << 12)
-#define S3C64XX_GPH3_KP_COL3		(0x04 << 12)
-#define S3C64XX_GPH3_EINT_G6_3		(0x07 << 12)
-
-#define S3C64XX_GPH4_MMC1_DATA2		(0x02 << 16)
-#define S3C64XX_GPH4_KP_COL4		(0x04 << 16)
-#define S3C64XX_GPH4_EINT_G6_4		(0x07 << 16)
-
-#define S3C64XX_GPH5_MMC1_DATA3		(0x02 << 20)
-#define S3C64XX_GPH5_KP_COL5		(0x04 << 20)
-#define S3C64XX_GPH5_EINT_G6_5		(0x07 << 20)
-
-#define S3C64XX_GPH6_MMC1_DATA4		(0x02 << 24)
-#define S3C64XX_GPH6_MMC2_DATA0		(0x03 << 24)
-#define S3C64XX_GPH6_KP_COL6		(0x04 << 24)
-#define S3C64XX_GPH6_I2S_V40_BCLK	(0x05 << 24)
-#define S3C64XX_GPH6_ADDR_CF0		(0x06 << 24)
-#define S3C64XX_GPH6_EINT_G6_6		(0x07 << 24)
-
-#define S3C64XX_GPH7_MMC1_DATA5		(0x02 << 28)
-#define S3C64XX_GPH7_MMC2_DATA1		(0x03 << 28)
-#define S3C64XX_GPH7_KP_COL7		(0x04 << 28)
-#define S3C64XX_GPH7_I2S_V40_CDCLK	(0x05 << 28)
-#define S3C64XX_GPH7_ADDR_CF1		(0x06 << 28)
-#define S3C64XX_GPH7_EINT_G6_7		(0x07 << 28)
-
-#define S3C64XX_GPH8_MMC1_DATA6		(0x02 <<  0)
-#define S3C64XX_GPH8_MMC2_DATA2		(0x03 <<  0)
-#define S3C64XX_GPH8_I2S_V40_LRCLK	(0x05 <<  0)
-#define S3C64XX_GPH8_ADDR_CF2		(0x06 <<  0)
-#define S3C64XX_GPH8_EINT_G6_8		(0x07 <<  0)
-
-#define S3C64XX_GPH9_OUTPUT		(0x01 <<  4)
-#define S3C64XX_GPH9_MMC1_DATA7		(0x02 <<  4)
-#define S3C64XX_GPH9_MMC2_DATA3		(0x03 <<  4)
-#define S3C64XX_GPH9_I2S_V40_DI		(0x05 <<  4)
-#define S3C64XX_GPH9_EINT_G6_9		(0x07 <<  4)
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-i.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-i.h
deleted file mode 100644
index ce9ebe3..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-i.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-i.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank I register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPICON			(S3C64XX_GPI_BASE + 0x00)
-#define S3C64XX_GPIDAT			(S3C64XX_GPI_BASE + 0x04)
-#define S3C64XX_GPIPUD			(S3C64XX_GPI_BASE + 0x08)
-#define S3C64XX_GPICONSLP		(S3C64XX_GPI_BASE + 0x0c)
-#define S3C64XX_GPIPUDSLP		(S3C64XX_GPI_BASE + 0x10)
-
-#define S3C64XX_GPI_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
-#define S3C64XX_GPI_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
-#define S3C64XX_GPI_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
-
-#define S3C64XX_GPI0_VD0		(0x02 << 0)
-#define S3C64XX_GPI1_VD1		(0x02 << 2)
-#define S3C64XX_GPI2_VD2		(0x02 << 4)
-#define S3C64XX_GPI3_VD3		(0x02 << 6)
-#define S3C64XX_GPI4_VD4		(0x02 << 8)
-#define S3C64XX_GPI5_VD5		(0x02 << 10)
-#define S3C64XX_GPI6_VD6		(0x02 << 12)
-#define S3C64XX_GPI7_VD7		(0x02 << 14)
-#define S3C64XX_GPI8_VD8		(0x02 << 16)
-#define S3C64XX_GPI9_VD9		(0x02 << 18)
-#define S3C64XX_GPI10_VD10		(0x02 << 20)
-#define S3C64XX_GPI11_VD11		(0x02 << 22)
-#define S3C64XX_GPI12_VD12		(0x02 << 24)
-#define S3C64XX_GPI13_VD13		(0x02 << 26)
-#define S3C64XX_GPI14_VD14		(0x02 << 28)
-#define S3C64XX_GPI15_VD15		(0x02 << 30)
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-j.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-j.h
deleted file mode 100644
index 21a9062..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-j.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-j.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank J register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPJCON			(S3C64XX_GPJ_BASE + 0x00)
-#define S3C64XX_GPJDAT			(S3C64XX_GPJ_BASE + 0x04)
-#define S3C64XX_GPJPUD			(S3C64XX_GPJ_BASE + 0x08)
-#define S3C64XX_GPJCONSLP		(S3C64XX_GPJ_BASE + 0x0c)
-#define S3C64XX_GPJPUDSLP		(S3C64XX_GPJ_BASE + 0x10)
-
-#define S3C64XX_GPJ_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
-#define S3C64XX_GPJ_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
-#define S3C64XX_GPJ_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
-
-#define S3C64XX_GPJ0_VD16		(0x02 << 0)
-#define S3C64XX_GPJ1_VD17		(0x02 << 2)
-#define S3C64XX_GPJ2_VD18		(0x02 << 4)
-#define S3C64XX_GPJ3_VD19		(0x02 << 6)
-#define S3C64XX_GPJ4_VD20		(0x02 << 8)
-#define S3C64XX_GPJ5_VD21		(0x02 << 10)
-#define S3C64XX_GPJ6_VD22		(0x02 << 12)
-#define S3C64XX_GPJ7_VD23		(0x02 << 14)
-#define S3C64XX_GPJ8_LCD_HSYNC		(0x02 << 16)
-#define S3C64XX_GPJ9_LCD_VSYNC		(0x02 << 18)
-#define S3C64XX_GPJ10_LCD_VDEN		(0x02 << 20)
-#define S3C64XX_GPJ11_LCD_VCLK		(0x02 << 22)
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-n.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-n.h
deleted file mode 100644
index 569e761..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-n.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-n.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank N register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPNCON			(S3C64XX_GPN_BASE + 0x00)
-#define S3C64XX_GPNDAT			(S3C64XX_GPN_BASE + 0x04)
-#define S3C64XX_GPNPUD			(S3C64XX_GPN_BASE + 0x08)
-
-#define S3C64XX_GPN_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
-#define S3C64XX_GPN_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
-#define S3C64XX_GPN_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
-
-#define S3C64XX_GPN0_EINT0		(0x02 << 0)
-#define S3C64XX_GPN0_KP_ROW0		(0x03 << 0)
-
-#define S3C64XX_GPN1_EINT1		(0x02 << 2)
-#define S3C64XX_GPN1_KP_ROW1		(0x03 << 2)
-
-#define S3C64XX_GPN2_EINT2		(0x02 << 4)
-#define S3C64XX_GPN2_KP_ROW2		(0x03 << 4)
-
-#define S3C64XX_GPN3_EINT3		(0x02 << 6)
-#define S3C64XX_GPN3_KP_ROW3		(0x03 << 6)
-
-#define S3C64XX_GPN4_EINT4		(0x02 << 8)
-#define S3C64XX_GPN4_KP_ROW4		(0x03 << 8)
-
-#define S3C64XX_GPN5_EINT5		(0x02 << 10)
-#define S3C64XX_GPN5_KP_ROW5		(0x03 << 10)
-
-#define S3C64XX_GPN6_EINT6		(0x02 << 12)
-#define S3C64XX_GPN6_KP_ROW6		(0x03 << 12)
-
-#define S3C64XX_GPN7_EINT7		(0x02 << 14)
-#define S3C64XX_GPN7_KP_ROW7		(0x03 << 14)
-
-#define S3C64XX_GPN8_EINT8		(0x02 << 16)
-#define S3C64XX_GPN9_EINT9		(0x02 << 18)
-#define S3C64XX_GPN10_EINT10		(0x02 << 20)
-#define S3C64XX_GPN11_EINT11		(0x02 << 22)
-#define S3C64XX_GPN12_EINT12		(0x02 << 24)
-#define S3C64XX_GPN13_EINT13		(0x02 << 26)
-#define S3C64XX_GPN14_EINT14		(0x02 << 28)
-#define S3C64XX_GPN15_EINT15		(0x02 << 30)
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-o.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-o.h
deleted file mode 100644
index b09e129..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-o.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-o.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank O register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPOCON			(S3C64XX_GPO_BASE + 0x00)
-#define S3C64XX_GPODAT			(S3C64XX_GPO_BASE + 0x04)
-#define S3C64XX_GPOPUD			(S3C64XX_GPO_BASE + 0x08)
-#define S3C64XX_GPOCONSLP		(S3C64XX_GPO_BASE + 0x0c)
-#define S3C64XX_GPOPUDSLP		(S3C64XX_GPO_BASE + 0x10)
-
-#define S3C64XX_GPO_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
-#define S3C64XX_GPO_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
-#define S3C64XX_GPO_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
-
-#define S3C64XX_GPO0_MEM0_nCS2		(0x02 << 0)
-#define S3C64XX_GPO0_EINT_G7_0		(0x03 << 0)
-
-#define S3C64XX_GPO1_MEM0_nCS3		(0x02 << 2)
-#define S3C64XX_GPO1_EINT_G7_1		(0x03 << 2)
-
-#define S3C64XX_GPO2_MEM0_nCS4		(0x02 << 4)
-#define S3C64XX_GPO2_EINT_G7_2		(0x03 << 4)
-
-#define S3C64XX_GPO3_MEM0_nCS5		(0x02 << 6)
-#define S3C64XX_GPO3_EINT_G7_3		(0x03 << 6)
-
-#define S3C64XX_GPO4_EINT_G7_4		(0x03 << 8)
-
-#define S3C64XX_GPO5_EINT_G7_5		(0x03 << 10)
-
-#define S3C64XX_GPO6_MEM0_ADDR6		(0x02 << 12)
-#define S3C64XX_GPO6_EINT_G7_6		(0x03 << 12)
-
-#define S3C64XX_GPO7_MEM0_ADDR7		(0x02 << 14)
-#define S3C64XX_GPO7_EINT_G7_7		(0x03 << 14)
-
-#define S3C64XX_GPO8_MEM0_ADDR8		(0x02 << 16)
-#define S3C64XX_GPO8_EINT_G7_8		(0x03 << 16)
-
-#define S3C64XX_GPO9_MEM0_ADDR9		(0x02 << 18)
-#define S3C64XX_GPO9_EINT_G7_9		(0x03 << 18)
-
-#define S3C64XX_GPO10_MEM0_ADDR10	(0x02 << 20)
-#define S3C64XX_GPO10_EINT_G7_10	(0x03 << 20)
-
-#define S3C64XX_GPO11_MEM0_ADDR11	(0x02 << 22)
-#define S3C64XX_GPO11_EINT_G7_11	(0x03 << 22)
-
-#define S3C64XX_GPO12_MEM0_ADDR12	(0x02 << 24)
-#define S3C64XX_GPO12_EINT_G7_12	(0x03 << 24)
-
-#define S3C64XX_GPO13_MEM0_ADDR13	(0x02 << 26)
-#define S3C64XX_GPO13_EINT_G7_13	(0x03 << 26)
-
-#define S3C64XX_GPO14_MEM0_ADDR14	(0x02 << 28)
-#define S3C64XX_GPO14_EINT_G7_14	(0x03 << 28)
-
-#define S3C64XX_GPO15_MEM0_ADDR15	(0x02 << 30)
-#define S3C64XX_GPO15_EINT_G7_15	(0x03 << 30)
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-p.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-p.h
deleted file mode 100644
index 92f0051..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-p.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-p.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank P register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPPCON			(S3C64XX_GPP_BASE + 0x00)
-#define S3C64XX_GPPDAT			(S3C64XX_GPP_BASE + 0x04)
-#define S3C64XX_GPPPUD			(S3C64XX_GPP_BASE + 0x08)
-#define S3C64XX_GPPCONSLP		(S3C64XX_GPP_BASE + 0x0c)
-#define S3C64XX_GPPPUDSLP		(S3C64XX_GPP_BASE + 0x10)
-
-#define S3C64XX_GPP_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
-#define S3C64XX_GPP_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
-#define S3C64XX_GPP_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
-
-#define S3C64XX_GPP0_MEM0_ADDRV		(0x02 << 0)
-#define S3C64XX_GPP0_EINT_G8_0		(0x03 << 0)
-
-#define S3C64XX_GPP1_MEM0_SMCLK		(0x02 << 2)
-#define S3C64XX_GPP1_EINT_G8_1		(0x03 << 2)
-
-#define S3C64XX_GPP2_MEM0_nWAIT		(0x02 << 4)
-#define S3C64XX_GPP2_EINT_G8_2		(0x03 << 4)
-
-#define S3C64XX_GPP3_MEM0_RDY0_ALE	(0x02 << 6)
-#define S3C64XX_GPP3_EINT_G8_3		(0x03 << 6)
-
-#define S3C64XX_GPP4_MEM0_RDY1_CLE	(0x02 << 8)
-#define S3C64XX_GPP4_EINT_G8_4		(0x03 << 8)
-
-#define S3C64XX_GPP5_MEM0_INTsm0_FWE	(0x02 << 10)
-#define S3C64XX_GPP5_EINT_G8_5		(0x03 << 10)
-
-#define S3C64XX_GPP6_MEM0_(null)	(0x02 << 12)
-#define S3C64XX_GPP6_EINT_G8_6		(0x03 << 12)
-
-#define S3C64XX_GPP7_MEM0_INTsm1_FRE	(0x02 << 14)
-#define S3C64XX_GPP7_EINT_G8_7		(0x03 << 14)
-
-#define S3C64XX_GPP8_MEM0_RPn_RnB	(0x02 << 16)
-#define S3C64XX_GPP8_EINT_G8_8		(0x03 << 16)
-
-#define S3C64XX_GPP9_MEM0_ATA_RESET	(0x02 << 18)
-#define S3C64XX_GPP9_EINT_G8_9		(0x03 << 18)
-
-#define S3C64XX_GPP10_MEM0_ATA_INPACK	(0x02 << 20)
-#define S3C64XX_GPP10_EINT_G8_10	(0x03 << 20)
-
-#define S3C64XX_GPP11_MEM0_ATA_REG	(0x02 << 22)
-#define S3C64XX_GPP11_EINT_G8_11	(0x03 << 22)
-
-#define S3C64XX_GPP12_MEM0_ATA_WE	(0x02 << 24)
-#define S3C64XX_GPP12_EINT_G8_12	(0x03 << 24)
-
-#define S3C64XX_GPP13_MEM0_ATA_OE	(0x02 << 26)
-#define S3C64XX_GPP13_EINT_G8_13	(0x03 << 26)
-
-#define S3C64XX_GPP14_MEM0_ATA_CD	(0x02 << 28)
-#define S3C64XX_GPP14_EINT_G8_14	(0x03 << 28)
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-q.h b/arch/arm/plat-s3c64xx/include/plat/gpio-bank-q.h
deleted file mode 100644
index 565e60a..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/gpio-bank-q.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/gpio-bank-q.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * 	Ben Dooks <ben@simtec.co.uk>
- * 	http://armlinux.simtec.co.uk/
- *
- * GPIO Bank Q register and configuration definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#define S3C64XX_GPQCON			(S3C64XX_GPQ_BASE + 0x00)
-#define S3C64XX_GPQDAT			(S3C64XX_GPQ_BASE + 0x04)
-#define S3C64XX_GPQPUD			(S3C64XX_GPQ_BASE + 0x08)
-#define S3C64XX_GPQCONSLP		(S3C64XX_GPQ_BASE + 0x0c)
-#define S3C64XX_GPQPUDSLP		(S3C64XX_GPQ_BASE + 0x10)
-
-#define S3C64XX_GPQ_CONMASK(__gpio)	(0x3 << ((__gpio) * 2))
-#define S3C64XX_GPQ_INPUT(__gpio)	(0x0 << ((__gpio) * 2))
-#define S3C64XX_GPQ_OUTPUT(__gpio)	(0x1 << ((__gpio) * 2))
-
-#define S3C64XX_GPQ0_MEM0_ADDR18_RAS	(0x02 << 0)
-#define S3C64XX_GPQ0_EINT_G9_0		(0x03 << 0)
-
-#define S3C64XX_GPQ1_MEM0_ADDR19_CAS	(0x02 << 2)
-#define S3C64XX_GPQ1_EINT_G9_1		(0x03 << 2)
-
-#define S3C64XX_GPQ2_EINT_G9_2		(0x03 << 4)
-
-#define S3C64XX_GPQ3_EINT_G9_3		(0x03 << 6)
-
-#define S3C64XX_GPQ4_EINT_G9_4		(0x03 << 8)
-
-#define S3C64XX_GPQ5_EINT_G9_5		(0x03 << 10)
-
-#define S3C64XX_GPQ6_EINT_G9_6		(0x03 << 12)
-
-#define S3C64XX_GPQ7_MEM0_ADDR17_WENDMC	(0x02 << 14)
-#define S3C64XX_GPQ7_EINT_G9_7		(0x03 << 14)
-
-#define S3C64XX_GPQ8_MEM0_ADDR16_APDMC	(0x02 << 16)
-#define S3C64XX_GPQ8_EINT_G9_8		(0x03 << 16)
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h
deleted file mode 100644
index 7956fd3..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/irqs.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/mach/irqs.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - Common IRQ support
- */
-
-#ifndef __ASM_PLAT_S3C64XX_IRQS_H
-#define __ASM_PLAT_S3C64XX_IRQS_H __FILE__
-
-/* we keep the first set of CPU IRQs out of the range of
- * the ISA space, so that the PC104 has them to itself
- * and we don't end up having to do horrible things to the
- * standard ISA drivers....
- *
- * note, since we're using the VICs, our start must be a
- * mulitple of 32 to allow the common code to work
- */
-
-#define S3C_IRQ_OFFSET	(32)
-
-#define S3C_IRQ(x)	((x) + S3C_IRQ_OFFSET)
-
-#define S3C_VIC0_BASE	S3C_IRQ(0)
-#define S3C_VIC1_BASE	S3C_IRQ(32)
-
-/* UART interrupts, each UART has 4 intterupts per channel so
- * use the space between the ISA and S3C main interrupts. Note, these
- * are not in the same order as the S3C24XX series! */
-
-#define IRQ_S3CUART_BASE0	(16)
-#define IRQ_S3CUART_BASE1	(20)
-#define IRQ_S3CUART_BASE2	(24)
-#define IRQ_S3CUART_BASE3	(28)
-
-#define UART_IRQ_RXD		(0)
-#define UART_IRQ_ERR		(1)
-#define UART_IRQ_TXD		(2)
-#define UART_IRQ_MODEM		(3)
-
-#define IRQ_S3CUART_RX0		(IRQ_S3CUART_BASE0 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX0		(IRQ_S3CUART_BASE0 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR0	(IRQ_S3CUART_BASE0 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX1		(IRQ_S3CUART_BASE1 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX1		(IRQ_S3CUART_BASE1 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR1	(IRQ_S3CUART_BASE1 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX2		(IRQ_S3CUART_BASE2 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX2		(IRQ_S3CUART_BASE2 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR2	(IRQ_S3CUART_BASE2 + UART_IRQ_ERR)
-
-#define IRQ_S3CUART_RX3		(IRQ_S3CUART_BASE3 + UART_IRQ_RXD)
-#define IRQ_S3CUART_TX3		(IRQ_S3CUART_BASE3 + UART_IRQ_TXD)
-#define IRQ_S3CUART_ERR3	(IRQ_S3CUART_BASE3 + UART_IRQ_ERR)
-
-/* VIC based IRQs */
-
-#define S3C64XX_IRQ_VIC0(x)	(S3C_VIC0_BASE + (x))
-#define S3C64XX_IRQ_VIC1(x)	(S3C_VIC1_BASE + (x))
-
-/* VIC0 */
-
-#define IRQ_EINT0_3		S3C64XX_IRQ_VIC0(0)
-#define IRQ_EINT4_11		S3C64XX_IRQ_VIC0(1)
-#define IRQ_RTC_TIC		S3C64XX_IRQ_VIC0(2)
-#define IRQ_CAMIF_C		S3C64XX_IRQ_VIC0(3)
-#define IRQ_CAMIF_P		S3C64XX_IRQ_VIC0(4)
-#define IRQ_CAMIF_MC		S3C64XX_IRQ_VIC0(5)
-#define IRQ_S3C6410_IIC1	S3C64XX_IRQ_VIC0(5)
-#define IRQ_S3C6410_IIS		S3C64XX_IRQ_VIC0(6)
-#define IRQ_S3C6400_CAMIF_MP	S3C64XX_IRQ_VIC0(6)
-#define IRQ_CAMIF_WE_C		S3C64XX_IRQ_VIC0(7)
-#define IRQ_S3C6410_G3D		S3C64XX_IRQ_VIC0(8)
-#define IRQ_S3C6400_CAMIF_WE_P	S3C64XX_IRQ_VIC0(8)
-#define IRQ_POST0		S3C64XX_IRQ_VIC0(9)
-#define IRQ_ROTATOR		S3C64XX_IRQ_VIC0(10)
-#define IRQ_2D			S3C64XX_IRQ_VIC0(11)
-#define IRQ_TVENC		S3C64XX_IRQ_VIC0(12)
-#define IRQ_SCALER		S3C64XX_IRQ_VIC0(13)
-#define IRQ_BATF		S3C64XX_IRQ_VIC0(14)
-#define IRQ_JPEG		S3C64XX_IRQ_VIC0(15)
-#define IRQ_MFC			S3C64XX_IRQ_VIC0(16)
-#define IRQ_SDMA0		S3C64XX_IRQ_VIC0(17)
-#define IRQ_SDMA1		S3C64XX_IRQ_VIC0(18)
-#define IRQ_ARM_DMAERR		S3C64XX_IRQ_VIC0(19)
-#define IRQ_ARM_DMA		S3C64XX_IRQ_VIC0(20)
-#define IRQ_ARM_DMAS		S3C64XX_IRQ_VIC0(21)
-#define IRQ_KEYPAD		S3C64XX_IRQ_VIC0(22)
-#define IRQ_TIMER0_VIC		S3C64XX_IRQ_VIC0(23)
-#define IRQ_TIMER1_VIC		S3C64XX_IRQ_VIC0(24)
-#define IRQ_TIMER2_VIC		S3C64XX_IRQ_VIC0(25)
-#define IRQ_WDT			S3C64XX_IRQ_VIC0(26)
-#define IRQ_TIMER3_VIC		S3C64XX_IRQ_VIC0(27)
-#define IRQ_TIMER4_VIC		S3C64XX_IRQ_VIC0(28)
-#define IRQ_LCD_FIFO		S3C64XX_IRQ_VIC0(29)
-#define IRQ_LCD_VSYNC		S3C64XX_IRQ_VIC0(30)
-#define IRQ_LCD_SYSTEM		S3C64XX_IRQ_VIC0(31)
-
-/* VIC1 */
-
-#define IRQ_EINT12_19		S3C64XX_IRQ_VIC1(0)
-#define IRQ_EINT20_27		S3C64XX_IRQ_VIC1(1)
-#define IRQ_PCM0		S3C64XX_IRQ_VIC1(2)
-#define IRQ_PCM1		S3C64XX_IRQ_VIC1(3)
-#define IRQ_AC97		S3C64XX_IRQ_VIC1(4)
-#define IRQ_UART0		S3C64XX_IRQ_VIC1(5)
-#define IRQ_UART1		S3C64XX_IRQ_VIC1(6)
-#define IRQ_UART2		S3C64XX_IRQ_VIC1(7)
-#define IRQ_UART3		S3C64XX_IRQ_VIC1(8)
-#define IRQ_DMA0		S3C64XX_IRQ_VIC1(9)
-#define IRQ_DMA1		S3C64XX_IRQ_VIC1(10)
-#define IRQ_ONENAND0		S3C64XX_IRQ_VIC1(11)
-#define IRQ_ONENAND1		S3C64XX_IRQ_VIC1(12)
-#define IRQ_NFC			S3C64XX_IRQ_VIC1(13)
-#define IRQ_CFCON		S3C64XX_IRQ_VIC1(14)
-#define IRQ_USBH		S3C64XX_IRQ_VIC1(15)
-#define IRQ_SPI0		S3C64XX_IRQ_VIC1(16)
-#define IRQ_SPI1		S3C64XX_IRQ_VIC1(17)
-#define IRQ_IIC			S3C64XX_IRQ_VIC1(18)
-#define IRQ_HSItx		S3C64XX_IRQ_VIC1(19)
-#define IRQ_HSIrx		S3C64XX_IRQ_VIC1(20)
-#define IRQ_RESERVED		S3C64XX_IRQ_VIC1(21)
-#define IRQ_MSM			S3C64XX_IRQ_VIC1(22)
-#define IRQ_HOSTIF		S3C64XX_IRQ_VIC1(23)
-#define IRQ_HSMMC0		S3C64XX_IRQ_VIC1(24)
-#define IRQ_HSMMC1		S3C64XX_IRQ_VIC1(25)
-#define IRQ_HSMMC2		IRQ_SPI1	/* shared with SPI1 */
-#define IRQ_OTG			S3C64XX_IRQ_VIC1(26)
-#define IRQ_IRDA		S3C64XX_IRQ_VIC1(27)
-#define IRQ_RTC_ALARM		S3C64XX_IRQ_VIC1(28)
-#define IRQ_SEC			S3C64XX_IRQ_VIC1(29)
-#define IRQ_PENDN		S3C64XX_IRQ_VIC1(30)
-#define IRQ_TC			IRQ_PENDN
-#define IRQ_ADC			S3C64XX_IRQ_VIC1(31)
-
-#define S3C64XX_TIMER_IRQ(x)	S3C_IRQ(64 + (x))
-
-#define IRQ_TIMER0		S3C64XX_TIMER_IRQ(0)
-#define IRQ_TIMER1		S3C64XX_TIMER_IRQ(1)
-#define IRQ_TIMER2		S3C64XX_TIMER_IRQ(2)
-#define IRQ_TIMER3		S3C64XX_TIMER_IRQ(3)
-#define IRQ_TIMER4		S3C64XX_TIMER_IRQ(4)
-
-/* compatibility for device defines */
-
-#define IRQ_IIC1		IRQ_S3C6410_IIC1
-
-/* Since the IRQ_EINT(x) are a linear mapping on current s3c64xx series
- * we just defined them as an IRQ_EINT(x) macro from S3C_IRQ_EINT_BASE
- * which we place after the pair of VICs. */
-
-#define S3C_IRQ_EINT_BASE	S3C_IRQ(64+5)
-
-#define S3C_EINT(x)		((x) + S3C_IRQ_EINT_BASE)
-#define IRQ_EINT(x)		S3C_EINT(x)
-#define IRQ_EINT_BIT(x)		((x) - S3C_EINT(0))
-
-/* Next the external interrupt groups. These are similar to the IRQ_EINT(x)
- * that they are sourced from the GPIO pins but with a different scheme for
- * priority and source indication.
- *
- * The IRQ_EINT(x) can be thought of as 'group 0' of the available GPIO
- * interrupts, but for historical reasons they are kept apart from these
- * next interrupts.
- *
- * Use IRQ_EINT_GROUP(group, offset) to get the number for use in the
- * machine specific support files.
- */
-
-#define IRQ_EINT_GROUP1_NR	(15)
-#define IRQ_EINT_GROUP2_NR	(8)
-#define IRQ_EINT_GROUP3_NR	(5)
-#define IRQ_EINT_GROUP4_NR	(14)
-#define IRQ_EINT_GROUP5_NR	(7)
-#define IRQ_EINT_GROUP6_NR	(10)
-#define IRQ_EINT_GROUP7_NR	(16)
-#define IRQ_EINT_GROUP8_NR	(15)
-#define IRQ_EINT_GROUP9_NR	(9)
-
-#define IRQ_EINT_GROUP_BASE	S3C_EINT(28)
-#define IRQ_EINT_GROUP1_BASE	(IRQ_EINT_GROUP_BASE + 0x00)
-#define IRQ_EINT_GROUP2_BASE	(IRQ_EINT_GROUP1_BASE + IRQ_EINT_GROUP1_NR)
-#define IRQ_EINT_GROUP3_BASE	(IRQ_EINT_GROUP2_BASE + IRQ_EINT_GROUP2_NR)
-#define IRQ_EINT_GROUP4_BASE	(IRQ_EINT_GROUP3_BASE + IRQ_EINT_GROUP3_NR)
-#define IRQ_EINT_GROUP5_BASE	(IRQ_EINT_GROUP4_BASE + IRQ_EINT_GROUP4_NR)
-#define IRQ_EINT_GROUP6_BASE	(IRQ_EINT_GROUP5_BASE + IRQ_EINT_GROUP5_NR)
-#define IRQ_EINT_GROUP7_BASE	(IRQ_EINT_GROUP6_BASE + IRQ_EINT_GROUP6_NR)
-#define IRQ_EINT_GROUP8_BASE	(IRQ_EINT_GROUP7_BASE + IRQ_EINT_GROUP7_NR)
-#define IRQ_EINT_GROUP9_BASE	(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR)
-
-#define IRQ_EINT_GROUP(group, no)	(IRQ_EINT_GROUP##group##_BASE + (no))
-
-/* Define a group of interrupts for board-specific use (eg, for MFD
- * interrupt controllers). */
-#define IRQ_BOARD_START (IRQ_EINT_GROUP9_BASE + IRQ_EINT_GROUP9_NR + 1)
-
-#define IRQ_BOARD_NR 16
-
-#define IRQ_BOARD_END (IRQ_BOARD_START + IRQ_BOARD_NR)
-
-/* Set the default NR_IRQS */
-
-#define NR_IRQS	(IRQ_BOARD_END + 1)
-
-#endif /* __ASM_PLAT_S3C64XX_IRQS_H */
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/pm-core.h b/arch/arm/plat-s3c64xx/include/plat/pm-core.h
deleted file mode 100644
index d347de3..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/pm-core.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/include/plat/pm-core.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - PM core support for arch/arm/plat-s3c/pm.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <plat/regs-gpio.h>
-
-static inline void s3c_pm_debug_init_uart(void)
-{
-	u32 tmp = __raw_readl(S3C_PCLK_GATE);
-
-	/* As a note, since the S3C64XX UARTs generally have multiple
-	 * clock sources, we simply enable PCLK at the moment and hope
-	 * that the resume settings for the UART are suitable for the
-	 * use with PCLK.
-	 */
-
-	tmp |= S3C_CLKCON_PCLK_UART0;
-	tmp |= S3C_CLKCON_PCLK_UART1;
-	tmp |= S3C_CLKCON_PCLK_UART2;
-	tmp |= S3C_CLKCON_PCLK_UART3;
-
-	__raw_writel(tmp, S3C_PCLK_GATE);
-	udelay(10);
-}
-
-static inline void s3c_pm_arch_prepare_irqs(void)
-{
-	/* VIC should have already been taken care of */
-
-	/* clear any pending EINT0 interrupts */
-	__raw_writel(__raw_readl(S3C64XX_EINT0PEND), S3C64XX_EINT0PEND);
-}
-
-static inline void s3c_pm_arch_stop_clocks(void)
-{
-}
-
-static inline void s3c_pm_arch_show_resume_irqs(void)
-{
-}
-
-/* make these defines, we currently do not have any need to change
- * the IRQ wake controls depending on the CPU we are running on */
-
-#define s3c_irqwake_eintallow	((1 << 28) - 1)
-#define s3c_irqwake_intallow	(0)
-
-static inline void s3c_pm_arch_update_uart(void __iomem *regs,
-					   struct pm_uart_save *save)
-{
-	u32 ucon = __raw_readl(regs + S3C2410_UCON);
-	u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
-	u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
-	u32 new_ucon;
-	u32 delta;
-
-	/* S3C64XX UART blocks only support level interrupts, so ensure that
-	 * when we restore unused UART blocks we force the level interrupt
-	 * settigs. */
-	save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
-
-	/* We have a constraint on changing the clock type of the UART
-	 * between UCLKx and PCLK, so ensure that when we restore UCON
-	 * that the CLK field is correctly modified if the bootloader
-	 * has changed anything.
-	 */
-	if (ucon_clk != save_clk) {
-		new_ucon = save->ucon;
-		delta = ucon_clk ^ save_clk;
-
-		/* change from UCLKx => wrong PCLK,
-		 * either UCLK can be tested for by a bit-test
-		 * with UCLK0 */
-		if (ucon_clk & S3C6400_UCON_UCLK0 &&
-		    !(save_clk & S3C6400_UCON_UCLK0) &&
-		    delta & S3C6400_UCON_PCLK2) {
-			new_ucon &= ~S3C6400_UCON_UCLK0;
-		} else if (delta == S3C6400_UCON_PCLK2) {
-			/* as an precaution, don't change from
-			 * PCLK2 => PCLK or vice-versa */
-			new_ucon ^= S3C6400_UCON_PCLK2;
-		}
-
-		S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
-			  ucon, new_ucon, save->ucon);
-		save->ucon = new_ucon;
-	}
-}
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h
deleted file mode 100644
index ff46e7f..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/* arch/arm/plat-s3c64xx/include/plat/regs-clock.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C64XX clock register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __PLAT_REGS_CLOCK_H
-#define __PLAT_REGS_CLOCK_H __FILE__
-
-#define S3C_CLKREG(x)		(S3C_VA_SYS + (x))
-
-#define S3C_APLL_LOCK		S3C_CLKREG(0x00)
-#define S3C_MPLL_LOCK		S3C_CLKREG(0x04)
-#define S3C_EPLL_LOCK		S3C_CLKREG(0x08)
-#define S3C_APLL_CON		S3C_CLKREG(0x0C)
-#define S3C_MPLL_CON		S3C_CLKREG(0x10)
-#define S3C_EPLL_CON0		S3C_CLKREG(0x14)
-#define S3C_EPLL_CON1		S3C_CLKREG(0x18)
-#define S3C_CLK_SRC		S3C_CLKREG(0x1C)
-#define S3C_CLK_DIV0		S3C_CLKREG(0x20)
-#define S3C_CLK_DIV1		S3C_CLKREG(0x24)
-#define S3C_CLK_DIV2		S3C_CLKREG(0x28)
-#define S3C_CLK_OUT		S3C_CLKREG(0x2C)
-#define S3C_HCLK_GATE		S3C_CLKREG(0x30)
-#define S3C_PCLK_GATE		S3C_CLKREG(0x34)
-#define S3C_SCLK_GATE		S3C_CLKREG(0x38)
-#define S3C_MEM0_GATE		S3C_CLKREG(0x3C)
-
-/* CLKDIV0 */
-#define S3C6400_CLKDIV0_MFC_MASK	(0xf << 28)
-#define S3C6400_CLKDIV0_MFC_SHIFT	(28)
-#define S3C6400_CLKDIV0_JPEG_MASK	(0xf << 24)
-#define S3C6400_CLKDIV0_JPEG_SHIFT	(24)
-#define S3C6400_CLKDIV0_CAM_MASK	(0xf << 20)
-#define S3C6400_CLKDIV0_CAM_SHIFT	(20)
-#define S3C6400_CLKDIV0_SECURITY_MASK	(0x3 << 18)
-#define S3C6400_CLKDIV0_SECURITY_SHIFT	(18)
-#define S3C6400_CLKDIV0_PCLK_MASK	(0xf << 12)
-#define S3C6400_CLKDIV0_PCLK_SHIFT	(12)
-#define S3C6400_CLKDIV0_HCLK2_MASK	(0x7 << 9)
-#define S3C6400_CLKDIV0_HCLK2_SHIFT	(9)
-#define S3C6400_CLKDIV0_HCLK_MASK	(0x1 << 8)
-#define S3C6400_CLKDIV0_HCLK_SHIFT	(8)
-#define S3C6400_CLKDIV0_MPLL_MASK	(0x1 << 4)
-#define S3C6400_CLKDIV0_MPLL_SHIFT	(4)
-#define S3C6400_CLKDIV0_ARM_MASK	(0x7 << 0)
-#define S3C6410_CLKDIV0_ARM_MASK	(0xf << 0)
-#define S3C6400_CLKDIV0_ARM_SHIFT	(0)
-
-/* CLKDIV1 */
-#define S3C6410_CLKDIV1_FIMC_MASK	(0xf << 24)
-#define S3C6410_CLKDIV1_FIMC_SHIFT	(24)
-#define S3C6400_CLKDIV1_UHOST_MASK	(0xf << 20)
-#define S3C6400_CLKDIV1_UHOST_SHIFT	(20)
-#define S3C6400_CLKDIV1_SCALER_MASK	(0xf << 16)
-#define S3C6400_CLKDIV1_SCALER_SHIFT	(16)
-#define S3C6400_CLKDIV1_LCD_MASK	(0xf << 12)
-#define S3C6400_CLKDIV1_LCD_SHIFT	(12)
-#define S3C6400_CLKDIV1_MMC2_MASK	(0xf << 8)
-#define S3C6400_CLKDIV1_MMC2_SHIFT	(8)
-#define S3C6400_CLKDIV1_MMC1_MASK	(0xf << 4)
-#define S3C6400_CLKDIV1_MMC1_SHIFT	(4)
-#define S3C6400_CLKDIV1_MMC0_MASK	(0xf << 0)
-#define S3C6400_CLKDIV1_MMC0_SHIFT	(0)
-
-/* CLKDIV2 */
-#define S3C6410_CLKDIV2_AUDIO2_MASK	(0xf << 24)
-#define S3C6410_CLKDIV2_AUDIO2_SHIFT	(24)
-#define S3C6400_CLKDIV2_IRDA_MASK	(0xf << 20)
-#define S3C6400_CLKDIV2_IRDA_SHIFT	(20)
-#define S3C6400_CLKDIV2_UART_MASK	(0xf << 16)
-#define S3C6400_CLKDIV2_UART_SHIFT	(16)
-#define S3C6400_CLKDIV2_AUDIO1_MASK	(0xf << 12)
-#define S3C6400_CLKDIV2_AUDIO1_SHIFT	(12)
-#define S3C6400_CLKDIV2_AUDIO0_MASK	(0xf << 8)
-#define S3C6400_CLKDIV2_AUDIO0_SHIFT	(8)
-#define S3C6400_CLKDIV2_SPI1_MASK	(0xf << 4)
-#define S3C6400_CLKDIV2_SPI1_SHIFT	(4)
-#define S3C6400_CLKDIV2_SPI0_MASK	(0xf << 0)
-#define S3C6400_CLKDIV2_SPI0_SHIFT	(0)
-
-/* HCLK GATE Registers */
-#define S3C_CLKCON_HCLK_3DSE	(1<<31)
-#define S3C_CLKCON_HCLK_UHOST	(1<<29)
-#define S3C_CLKCON_HCLK_SECUR	(1<<28)
-#define S3C_CLKCON_HCLK_SDMA1	(1<<27)
-#define S3C_CLKCON_HCLK_SDMA0	(1<<26)
-#define S3C_CLKCON_HCLK_IROM	(1<<25)
-#define S3C_CLKCON_HCLK_DDR1	(1<<24)
-#define S3C_CLKCON_HCLK_DDR0	(1<<23)
-#define S3C_CLKCON_HCLK_MEM1	(1<<22)
-#define S3C_CLKCON_HCLK_MEM0	(1<<21)
-#define S3C_CLKCON_HCLK_USB	(1<<20)
-#define S3C_CLKCON_HCLK_HSMMC2	(1<<19)
-#define S3C_CLKCON_HCLK_HSMMC1	(1<<18)
-#define S3C_CLKCON_HCLK_HSMMC0	(1<<17)
-#define S3C_CLKCON_HCLK_MDP	(1<<16)
-#define S3C_CLKCON_HCLK_DHOST	(1<<15)
-#define S3C_CLKCON_HCLK_IHOST	(1<<14)
-#define S3C_CLKCON_HCLK_DMA1	(1<<13)
-#define S3C_CLKCON_HCLK_DMA0	(1<<12)
-#define S3C_CLKCON_HCLK_JPEG	(1<<11)
-#define S3C_CLKCON_HCLK_CAMIF	(1<<10)
-#define S3C_CLKCON_HCLK_SCALER	(1<<9)
-#define S3C_CLKCON_HCLK_2D	(1<<8)
-#define S3C_CLKCON_HCLK_TV	(1<<7)
-#define S3C_CLKCON_HCLK_POST0	(1<<5)
-#define S3C_CLKCON_HCLK_ROT	(1<<4)
-#define S3C_CLKCON_HCLK_LCD	(1<<3)
-#define S3C_CLKCON_HCLK_TZIC	(1<<2)
-#define S3C_CLKCON_HCLK_INTC	(1<<1)
-#define S3C_CLKCON_HCLK_MFC	(1<<0)
-
-/* PCLK GATE Registers */
-#define S3C6410_CLKCON_PCLK_I2C1	(1<<27)
-#define S3C6410_CLKCON_PCLK_IIS2	(1<<26)
-#define S3C_CLKCON_PCLK_SKEY		(1<<24)
-#define S3C_CLKCON_PCLK_CHIPID		(1<<23)
-#define S3C_CLKCON_PCLK_SPI1		(1<<22)
-#define S3C_CLKCON_PCLK_SPI0		(1<<21)
-#define S3C_CLKCON_PCLK_HSIRX		(1<<20)
-#define S3C_CLKCON_PCLK_HSITX		(1<<19)
-#define S3C_CLKCON_PCLK_GPIO		(1<<18)
-#define S3C_CLKCON_PCLK_IIC		(1<<17)
-#define S3C_CLKCON_PCLK_IIS1		(1<<16)
-#define S3C_CLKCON_PCLK_IIS0		(1<<15)
-#define S3C_CLKCON_PCLK_AC97		(1<<14)
-#define S3C_CLKCON_PCLK_TZPC		(1<<13)
-#define S3C_CLKCON_PCLK_TSADC		(1<<12)
-#define S3C_CLKCON_PCLK_KEYPAD		(1<<11)
-#define S3C_CLKCON_PCLK_IRDA		(1<<10)
-#define S3C_CLKCON_PCLK_PCM1		(1<<9)
-#define S3C_CLKCON_PCLK_PCM0		(1<<8)
-#define S3C_CLKCON_PCLK_PWM		(1<<7)
-#define S3C_CLKCON_PCLK_RTC		(1<<6)
-#define S3C_CLKCON_PCLK_WDT		(1<<5)
-#define S3C_CLKCON_PCLK_UART3		(1<<4)
-#define S3C_CLKCON_PCLK_UART2		(1<<3)
-#define S3C_CLKCON_PCLK_UART1		(1<<2)
-#define S3C_CLKCON_PCLK_UART0		(1<<1)
-#define S3C_CLKCON_PCLK_MFC		(1<<0)
-
-/* SCLK GATE Registers */
-#define S3C_CLKCON_SCLK_UHOST		(1<<30)
-#define S3C_CLKCON_SCLK_MMC2_48		(1<<29)
-#define S3C_CLKCON_SCLK_MMC1_48		(1<<28)
-#define S3C_CLKCON_SCLK_MMC0_48		(1<<27)
-#define S3C_CLKCON_SCLK_MMC2		(1<<26)
-#define S3C_CLKCON_SCLK_MMC1		(1<<25)
-#define S3C_CLKCON_SCLK_MMC0		(1<<24)
-#define S3C_CLKCON_SCLK_SPI1_48 	(1<<23)
-#define S3C_CLKCON_SCLK_SPI0_48 	(1<<22)
-#define S3C_CLKCON_SCLK_SPI1		(1<<21)
-#define S3C_CLKCON_SCLK_SPI0		(1<<20)
-#define S3C_CLKCON_SCLK_DAC27		(1<<19)
-#define S3C_CLKCON_SCLK_TV27		(1<<18)
-#define S3C_CLKCON_SCLK_SCALER27	(1<<17)
-#define S3C_CLKCON_SCLK_SCALER		(1<<16)
-#define S3C_CLKCON_SCLK_LCD27		(1<<15)
-#define S3C_CLKCON_SCLK_LCD		(1<<14)
-#define S3C6400_CLKCON_SCLK_POST1_27	(1<<13)
-#define S3C6410_CLKCON_FIMC		(1<<13)
-#define S3C_CLKCON_SCLK_POST0_27	(1<<12)
-#define S3C6400_CLKCON_SCLK_POST1	(1<<11)
-#define S3C6410_CLKCON_SCLK_AUDIO2	(1<<11)
-#define S3C_CLKCON_SCLK_POST0		(1<<10)
-#define S3C_CLKCON_SCLK_AUDIO1		(1<<9)
-#define S3C_CLKCON_SCLK_AUDIO0		(1<<8)
-#define S3C_CLKCON_SCLK_SECUR		(1<<7)
-#define S3C_CLKCON_SCLK_IRDA		(1<<6)
-#define S3C_CLKCON_SCLK_UART		(1<<5)
-#define S3C_CLKCON_SCLK_ONENAND 	(1<<4)
-#define S3C_CLKCON_SCLK_MFC		(1<<3)
-#define S3C_CLKCON_SCLK_CAM		(1<<2)
-#define S3C_CLKCON_SCLK_JPEG		(1<<1)
-
-/* CLKSRC */
-
-#define S3C6400_CLKSRC_APLL_MOUT	(1 << 0)
-#define S3C6400_CLKSRC_MPLL_MOUT	(1 << 1)
-#define S3C6400_CLKSRC_EPLL_MOUT	(1 << 2)
-#define S3C6400_CLKSRC_APLL_MOUT_SHIFT	(0)
-#define S3C6400_CLKSRC_MPLL_MOUT_SHIFT	(1)
-#define S3C6400_CLKSRC_EPLL_MOUT_SHIFT	(2)
-#define S3C6400_CLKSRC_MFC		(1 << 4)
-
-#define S3C6410_CLKSRC_TV27_MASK	(0x1 << 31)
-#define S3C6410_CLKSRC_TV27_SHIFT	(31)
-#define S3C6410_CLKSRC_DAC27_MASK	(0x1 << 30)
-#define S3C6410_CLKSRC_DAC27_SHIFT	(30)
-#define S3C6400_CLKSRC_SCALER_MASK	(0x3 << 28)
-#define S3C6400_CLKSRC_SCALER_SHIFT	(28)
-#define S3C6400_CLKSRC_LCD_MASK		(0x3 << 26)
-#define S3C6400_CLKSRC_LCD_SHIFT	(26)
-#define S3C6400_CLKSRC_IRDA_MASK	(0x3 << 24)
-#define S3C6400_CLKSRC_IRDA_SHIFT	(24)
-#define S3C6400_CLKSRC_MMC2_MASK	(0x3 << 22)
-#define S3C6400_CLKSRC_MMC2_SHIFT	(22)
-#define S3C6400_CLKSRC_MMC1_MASK	(0x3 << 20)
-#define S3C6400_CLKSRC_MMC1_SHIFT	(20)
-#define S3C6400_CLKSRC_MMC0_MASK	(0x3 << 18)
-#define S3C6400_CLKSRC_MMC0_SHIFT	(18)
-#define S3C6400_CLKSRC_SPI1_MASK	(0x3 << 16)
-#define S3C6400_CLKSRC_SPI1_SHIFT	(16)
-#define S3C6400_CLKSRC_SPI0_MASK	(0x3 << 14)
-#define S3C6400_CLKSRC_SPI0_SHIFT	(14)
-#define S3C6400_CLKSRC_UART_MASK	(0x1 << 13)
-#define S3C6400_CLKSRC_UART_SHIFT	(13)
-#define S3C6400_CLKSRC_AUDIO1_MASK	(0x7 << 10)
-#define S3C6400_CLKSRC_AUDIO1_SHIFT	(10)
-#define S3C6400_CLKSRC_AUDIO0_MASK	(0x7 << 7)
-#define S3C6400_CLKSRC_AUDIO0_SHIFT	(7)
-#define S3C6400_CLKSRC_UHOST_MASK	(0x3 << 5)
-#define S3C6400_CLKSRC_UHOST_SHIFT	(5)
-
-
-#endif /* _PLAT_REGS_CLOCK_H */
diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6400.h b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h
deleted file mode 100644
index 11f2e1e..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/s3c6400.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* arch/arm/plat-s3c64xx/include/plat/s3c6400.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Header file for s3c6400 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* Common init code for S3C6400 related SoCs */
-
-extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s3c6400_register_clocks(unsigned armclk_divlimit);
-extern void s3c6400_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S3C6400
-
-extern  int s3c6400_init(void);
-extern void s3c6400_init_irq(void);
-extern void s3c6400_map_io(void);
-extern void s3c6400_init_clocks(int xtal);
-
-#define s3c6400_init_uarts s3c6400_common_init_uarts
-
-#else
-#define s3c6400_init_clocks NULL
-#define s3c6400_init_uarts NULL
-#define s3c6400_map_io NULL
-#define s3c6400_init NULL
-#endif
-
diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6410.h b/arch/arm/plat-s3c64xx/include/plat/s3c6410.h
deleted file mode 100644
index 50dcdd6..0000000
--- a/arch/arm/plat-s3c64xx/include/plat/s3c6410.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* arch/arm/plat-s3c64xx/include/plat/s3c6410.h
- *
- * Copyright 2008 Openmoko,  Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Header file for s3c6410 cpu support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifdef CONFIG_CPU_S3C6410
-
-extern  int s3c6410_init(void);
-extern void s3c6410_init_irq(void);
-extern void s3c6410_map_io(void);
-extern void s3c6410_init_clocks(int xtal);
-
-#define s3c6410_init_uarts s3c6400_common_init_uarts
-
-#else
-#define s3c6410_init_clocks NULL
-#define s3c6410_init_uarts NULL
-#define s3c6410_map_io NULL
-#define s3c6410_init NULL
-#endif
diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c
deleted file mode 100644
index ebdf183..0000000
--- a/arch/arm/plat-s3c64xx/irq-eint.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/* arch/arm/plat-s3c64xx/irq-eint.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - Interrupt handling for IRQ_EINT(x)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/sysdev.h>
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/hardware/vic.h>
-
-#include <plat/regs-irqtype.h>
-#include <plat/regs-gpio.h>
-#include <plat/gpio-cfg.h>
-
-#include <mach/map.h>
-#include <plat/cpu.h>
-#include <plat/pm.h>
-
-#define eint_offset(irq)	((irq) - IRQ_EINT(0))
-#define eint_irq_to_bit(irq)	(1 << eint_offset(irq))
-
-static inline void s3c_irq_eint_mask(unsigned int irq)
-{
-	u32 mask;
-
-	mask = __raw_readl(S3C64XX_EINT0MASK);
-	mask |= eint_irq_to_bit(irq);
-	__raw_writel(mask, S3C64XX_EINT0MASK);
-}
-
-static void s3c_irq_eint_unmask(unsigned int irq)
-{
-	u32 mask;
-
-	mask = __raw_readl(S3C64XX_EINT0MASK);
-	mask &= ~eint_irq_to_bit(irq);
-	__raw_writel(mask, S3C64XX_EINT0MASK);
-}
-
-static inline void s3c_irq_eint_ack(unsigned int irq)
-{
-	__raw_writel(eint_irq_to_bit(irq), S3C64XX_EINT0PEND);
-}
-
-static void s3c_irq_eint_maskack(unsigned int irq)
-{
-	/* compiler should in-line these */
-	s3c_irq_eint_mask(irq);
-	s3c_irq_eint_ack(irq);
-}
-
-static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
-{
-	int offs = eint_offset(irq);
-	int pin, pin_val;
-	int shift;
-	u32 ctrl, mask;
-	u32 newvalue = 0;
-	void __iomem *reg;
-
-	if (offs > 27)
-		return -EINVAL;
-
-	if (offs <= 15)
-		reg = S3C64XX_EINT0CON0;
-	else
-		reg = S3C64XX_EINT0CON1;
-
-	switch (type) {
-	case IRQ_TYPE_NONE:
-		printk(KERN_WARNING "No edge setting!\n");
-		break;
-
-	case IRQ_TYPE_EDGE_RISING:
-		newvalue = S3C2410_EXTINT_RISEEDGE;
-		break;
-
-	case IRQ_TYPE_EDGE_FALLING:
-		newvalue = S3C2410_EXTINT_FALLEDGE;
-		break;
-
-	case IRQ_TYPE_EDGE_BOTH:
-		newvalue = S3C2410_EXTINT_BOTHEDGE;
-		break;
-
-	case IRQ_TYPE_LEVEL_LOW:
-		newvalue = S3C2410_EXTINT_LOWLEV;
-		break;
-
-	case IRQ_TYPE_LEVEL_HIGH:
-		newvalue = S3C2410_EXTINT_HILEV;
-		break;
-
-	default:
-		printk(KERN_ERR "No such irq type %d", type);
-		return -1;
-	}
-
-	if (offs <= 15)
-		shift = (offs / 2) * 4;
-	else
-		shift = ((offs - 16) / 2) * 4;
-	mask = 0x7 << shift;
-
-	ctrl = __raw_readl(reg);
-	ctrl &= ~mask;
-	ctrl |= newvalue << shift;
-	__raw_writel(ctrl, reg);
-
-	/* set the GPIO pin appropriately */
-
-	if (offs < 16) {
-		pin = S3C64XX_GPN(offs);
-		pin_val = S3C_GPIO_SFN(2);
-	} else if (offs < 23) {
-		pin = S3C64XX_GPL(offs + 8 - 16);
-		pin_val = S3C_GPIO_SFN(3);
-	} else {
-		pin = S3C64XX_GPM(offs - 23);
-		pin_val = S3C_GPIO_SFN(3);
-	}
-
-	s3c_gpio_cfgpin(pin, pin_val);
-
-	return 0;
-}
-
-static struct irq_chip s3c_irq_eint = {
-	.name		= "s3c-eint",
-	.mask		= s3c_irq_eint_mask,
-	.unmask		= s3c_irq_eint_unmask,
-	.mask_ack	= s3c_irq_eint_maskack,
-	.ack		= s3c_irq_eint_ack,
-	.set_type	= s3c_irq_eint_set_type,
-	.set_wake	= s3c_irqext_wake,
-};
-
-/* s3c_irq_demux_eint
- *
- * This function demuxes the IRQ from the group0 external interrupts,
- * from IRQ_EINT(0) to IRQ_EINT(27). It is designed to be inlined into
- * the specific handlers s3c_irq_demux_eintX_Y.
- */
-static inline void s3c_irq_demux_eint(unsigned int start, unsigned int end)
-{
-	u32 status = __raw_readl(S3C64XX_EINT0PEND);
-	u32 mask = __raw_readl(S3C64XX_EINT0MASK);
-	unsigned int irq;
-
-	status &= ~mask;
-	status >>= start;
-	status &= (1 << (end - start + 1)) - 1;
-
-	for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) {
-		if (status & 1)
-			generic_handle_irq(irq);
-
-		status >>= 1;
-	}
-}
-
-static void s3c_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_eint(0, 3);
-}
-
-static void s3c_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_eint(4, 11);
-}
-
-static void s3c_irq_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_eint(12, 19);
-}
-
-static void s3c_irq_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_eint(20, 27);
-}
-
-static int __init s3c64xx_init_irq_eint(void)
-{
-	int irq;
-
-	for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
-		set_irq_chip(irq, &s3c_irq_eint);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-	set_irq_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
-	set_irq_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
-	set_irq_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
-	set_irq_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);
-
-	return 0;
-}
-
-arch_initcall(s3c64xx_init_irq_eint);
diff --git a/arch/arm/plat-s3c64xx/irq-pm.c b/arch/arm/plat-s3c64xx/irq-pm.c
deleted file mode 100644
index ca523b5..0000000
--- a/arch/arm/plat-s3c64xx/irq-pm.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/* arch/arm/plat-s3c64xx/irq-pm.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - Interrupt handling Power Management
- *
- * This program is free software; you can redistribute it 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/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/serial_core.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <mach/map.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-timer.h>
-#include <plat/regs-gpio.h>
-#include <plat/cpu.h>
-#include <plat/pm.h>
-
-/* We handled all the IRQ types in this code, to save having to make several
- * small files to handle each different type separately. Having the EINT_GRP
- * code here shouldn't be as much bloat as the IRQ table space needed when
- * they are enabled. The added benefit is we ensure that these registers are
- * in the same state as we suspended.
- */
-
-static struct sleep_save irq_save[] = {
-	SAVE_ITEM(S3C64XX_PRIORITY),
-	SAVE_ITEM(S3C64XX_EINT0CON0),
-	SAVE_ITEM(S3C64XX_EINT0CON1),
-	SAVE_ITEM(S3C64XX_EINT0FLTCON0),
-	SAVE_ITEM(S3C64XX_EINT0FLTCON1),
-	SAVE_ITEM(S3C64XX_EINT0FLTCON2),
-	SAVE_ITEM(S3C64XX_EINT0FLTCON3),
-	SAVE_ITEM(S3C64XX_EINT0MASK),
-	SAVE_ITEM(S3C64XX_TINT_CSTAT),
-};
-
-static struct irq_grp_save {
-	u32	fltcon;
-	u32	con;
-	u32	mask;
-} eint_grp_save[5];
-
-static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
-
-static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
-{
-	struct irq_grp_save *grp = eint_grp_save;
-	int i;
-
-	S3C_PMDBG("%s: suspending IRQs\n", __func__);
-
-	s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
-
-	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
-		irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
-
-	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
-		grp->con = __raw_readl(S3C64XX_EINT12CON + (i * 4));
-		grp->mask = __raw_readl(S3C64XX_EINT12MASK + (i * 4));
-		grp->fltcon = __raw_readl(S3C64XX_EINT12FLTCON + (i * 4));
-	}
-
-	return 0;
-}
-
-static int s3c64xx_irq_pm_resume(struct sys_device *dev)
-{
-	struct irq_grp_save *grp = eint_grp_save;
-	int i;
-
-	S3C_PMDBG("%s: resuming IRQs\n", __func__);
-
-	s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
-
-	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
-		__raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
-
-	for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
-		__raw_writel(grp->con, S3C64XX_EINT12CON + (i * 4));
-		__raw_writel(grp->mask, S3C64XX_EINT12MASK + (i * 4));
-		__raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4));
-	}
-
-	S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
-	return 0;
-}
-
-static struct sysdev_driver s3c64xx_irq_driver = {
-	.suspend = s3c64xx_irq_pm_suspend,
-	.resume	 = s3c64xx_irq_pm_resume,
-};
-
-static int __init s3c64xx_irq_pm_init(void)
-{
-	return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver);
-}
-
-arch_initcall(s3c64xx_irq_pm_init);
-
diff --git a/arch/arm/plat-s3c64xx/irq.c b/arch/arm/plat-s3c64xx/irq.c
deleted file mode 100644
index 8dc5b6d..0000000
--- a/arch/arm/plat-s3c64xx/irq.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/* arch/arm/plat-s3c64xx/irq.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C64XX - Interrupt handling
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/serial_core.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/hardware/vic.h>
-
-#include <mach/map.h>
-#include <plat/regs-serial.h>
-#include <plat/regs-timer.h>
-#include <plat/cpu.h>
-
-/* Timer interrupt handling */
-
-static void s3c_irq_demux_timer(unsigned int base_irq, unsigned int sub_irq)
-{
-	generic_handle_irq(sub_irq);
-}
-
-static void s3c_irq_demux_timer0(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_timer(irq, IRQ_TIMER0);
-}
-
-static void s3c_irq_demux_timer1(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_timer(irq, IRQ_TIMER1);
-}
-
-static void s3c_irq_demux_timer2(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_timer(irq, IRQ_TIMER2);
-}
-
-static void s3c_irq_demux_timer3(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_timer(irq, IRQ_TIMER3);
-}
-
-static void s3c_irq_demux_timer4(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_timer(irq, IRQ_TIMER4);
-}
-
-/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
-
-static void s3c_irq_timer_mask(unsigned int irq)
-{
-	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
-
-	reg &= 0x1f;  /* mask out pending interrupts */
-	reg &= ~(1 << (irq - IRQ_TIMER0));
-	__raw_writel(reg, S3C64XX_TINT_CSTAT);
-}
-
-static void s3c_irq_timer_unmask(unsigned int irq)
-{
-	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
-
-	reg &= 0x1f;  /* mask out pending interrupts */
-	reg |= 1 << (irq - IRQ_TIMER0);
-	__raw_writel(reg, S3C64XX_TINT_CSTAT);
-}
-
-static void s3c_irq_timer_ack(unsigned int irq)
-{
-	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
-
-	reg &= 0x1f;
-	reg |= (1 << 5) << (irq - IRQ_TIMER0);
-	__raw_writel(reg, S3C64XX_TINT_CSTAT);
-}
-
-static struct irq_chip s3c_irq_timer = {
-	.name		= "s3c-timer",
-	.mask		= s3c_irq_timer_mask,
-	.unmask		= s3c_irq_timer_unmask,
-	.ack		= s3c_irq_timer_ack,
-};
-
-struct uart_irq {
-	void __iomem	*regs;
-	unsigned int	 base_irq;
-	unsigned int	 parent_irq;
-};
-
-/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
- * are consecutive when looking up the interrupt in the demux routines.
- */
-static struct uart_irq uart_irqs[] = {
-	[0] = {
-		.regs		= S3C_VA_UART0,
-		.base_irq	= IRQ_S3CUART_BASE0,
-		.parent_irq	= IRQ_UART0,
-	},
-	[1] = {
-		.regs		= S3C_VA_UART1,
-		.base_irq	= IRQ_S3CUART_BASE1,
-		.parent_irq	= IRQ_UART1,
-	},
-	[2] = {
-		.regs		= S3C_VA_UART2,
-		.base_irq	= IRQ_S3CUART_BASE2,
-		.parent_irq	= IRQ_UART2,
-	},
-	[3] = {
-		.regs		= S3C_VA_UART3,
-		.base_irq	= IRQ_S3CUART_BASE3,
-		.parent_irq	= IRQ_UART3,
-	},
-};
-
-static inline void __iomem *s3c_irq_uart_base(unsigned int irq)
-{
-	struct uart_irq *uirq = get_irq_chip_data(irq);
-	return uirq->regs;
-}
-
-static inline unsigned int s3c_irq_uart_bit(unsigned int irq)
-{
-	return irq & 3;
-}
-
-/* UART interrupt registers, not worth adding to seperate include header */
-
-static void s3c_irq_uart_mask(unsigned int irq)
-{
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
-	u32 reg;
-
-	reg = __raw_readl(regs + S3C64XX_UINTM);
-	reg |= (1 << bit);
-	__raw_writel(reg, regs + S3C64XX_UINTM);
-}
-
-static void s3c_irq_uart_maskack(unsigned int irq)
-{
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
-	u32 reg;
-
-	reg = __raw_readl(regs + S3C64XX_UINTM);
-	reg |= (1 << bit);
-	__raw_writel(reg, regs + S3C64XX_UINTM);
-	__raw_writel(1 << bit, regs + S3C64XX_UINTP);
-}
-
-static void s3c_irq_uart_unmask(unsigned int irq)
-{
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
-	u32 reg;
-
-	reg = __raw_readl(regs + S3C64XX_UINTM);
-	reg &= ~(1 << bit);
-	__raw_writel(reg, regs + S3C64XX_UINTM);
-}
-
-static void s3c_irq_uart_ack(unsigned int irq)
-{
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
-
-	__raw_writel(1 << bit, regs + S3C64XX_UINTP);
-}
-
-static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
-{
-	struct uart_irq *uirq = &uart_irqs[irq - IRQ_UART0];
-	u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
-	int base = uirq->base_irq;
-
-	if (pend & (1 << 0))
-		generic_handle_irq(base);
-	if (pend & (1 << 1))
-		generic_handle_irq(base + 1);
-	if (pend & (1 << 2))
-		generic_handle_irq(base + 2);
-	if (pend & (1 << 3))
-		generic_handle_irq(base + 3);
-}
-
-static struct irq_chip s3c_irq_uart = {
-	.name		= "s3c-uart",
-	.mask		= s3c_irq_uart_mask,
-	.unmask		= s3c_irq_uart_unmask,
-	.mask_ack	= s3c_irq_uart_maskack,
-	.ack		= s3c_irq_uart_ack,
-};
-
-static void __init s3c64xx_uart_irq(struct uart_irq *uirq)
-{
-	void __iomem *reg_base = uirq->regs;
-	unsigned int irq;
-	int offs;
-
-	/* mask all interrupts at the start. */
-	__raw_writel(0xf, reg_base + S3C64XX_UINTM);
-
-	for (offs = 0; offs < 3; offs++) {
-		irq = uirq->base_irq + offs;
-
-		set_irq_chip(irq, &s3c_irq_uart);
-		set_irq_chip_data(irq, uirq);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-	set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
-}
-
-void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
-{
-	int uart, irq;
-
-	printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
-
-	/* initialise the pair of VICs */
-	vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid, 0);
-	vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid, 0);
-
-	/* add the timer sub-irqs */
-
-	set_irq_chained_handler(IRQ_TIMER0_VIC, s3c_irq_demux_timer0);
-	set_irq_chained_handler(IRQ_TIMER1_VIC, s3c_irq_demux_timer1);
-	set_irq_chained_handler(IRQ_TIMER2_VIC, s3c_irq_demux_timer2);
-	set_irq_chained_handler(IRQ_TIMER3_VIC, s3c_irq_demux_timer3);
-	set_irq_chained_handler(IRQ_TIMER4_VIC, s3c_irq_demux_timer4);
-
-	for (irq = IRQ_TIMER0; irq <= IRQ_TIMER4; irq++) {
-		set_irq_chip(irq, &s3c_irq_timer);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-	for (uart = 0; uart < ARRAY_SIZE(uart_irqs); uart++)
-		s3c64xx_uart_irq(&uart_irqs[uart]);
-}
-
-
diff --git a/arch/arm/plat-s3c64xx/pm.c b/arch/arm/plat-s3c64xx/pm.c
deleted file mode 100644
index 47632fc..0000000
--- a/arch/arm/plat-s3c64xx/pm.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/pm.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C64XX CPU PM support.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/suspend.h>
-#include <linux/serial_core.h>
-#include <linux/io.h>
-
-#include <mach/map.h>
-
-#include <plat/pm.h>
-#include <plat/regs-sys.h>
-#include <plat/regs-gpio.h>
-#include <plat/regs-clock.h>
-#include <plat/regs-syscon-power.h>
-#include <plat/regs-gpio-memport.h>
-
-#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
-#include <plat/gpio-bank-n.h>
-
-void s3c_pm_debug_smdkled(u32 set, u32 clear)
-{
-	unsigned long flags;
-	u32 reg;
-
-	local_irq_save(flags);
-	reg = __raw_readl(S3C64XX_GPNCON);
-	reg &= ~(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) |
-		 S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15));
-	reg |= S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) |
-	       S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15);
-	__raw_writel(reg, S3C64XX_GPNCON);
-
-	reg = __raw_readl(S3C64XX_GPNDAT);
-	reg &= ~(clear << 12);
-	reg |= set << 12;
-	__raw_writel(reg, S3C64XX_GPNDAT);
-
-	local_irq_restore(flags);
-}
-#endif
-
-static struct sleep_save core_save[] = {
-	SAVE_ITEM(S3C_APLL_LOCK),
-	SAVE_ITEM(S3C_MPLL_LOCK),
-	SAVE_ITEM(S3C_EPLL_LOCK),
-	SAVE_ITEM(S3C_CLK_SRC),
-	SAVE_ITEM(S3C_CLK_DIV0),
-	SAVE_ITEM(S3C_CLK_DIV1),
-	SAVE_ITEM(S3C_CLK_DIV2),
-	SAVE_ITEM(S3C_CLK_OUT),
-	SAVE_ITEM(S3C_HCLK_GATE),
-	SAVE_ITEM(S3C_PCLK_GATE),
-	SAVE_ITEM(S3C_SCLK_GATE),
-	SAVE_ITEM(S3C_MEM0_GATE),
-
-	SAVE_ITEM(S3C_EPLL_CON1),
-	SAVE_ITEM(S3C_EPLL_CON0),
-
-	SAVE_ITEM(S3C64XX_MEM0DRVCON),
-	SAVE_ITEM(S3C64XX_MEM1DRVCON),
-
-#ifndef CONFIG_CPU_FREQ
-	SAVE_ITEM(S3C_APLL_CON),
-	SAVE_ITEM(S3C_MPLL_CON),
-#endif
-};
-
-static struct sleep_save misc_save[] = {
-	SAVE_ITEM(S3C64XX_AHB_CON0),
-	SAVE_ITEM(S3C64XX_AHB_CON1),
-	SAVE_ITEM(S3C64XX_AHB_CON2),
-	
-	SAVE_ITEM(S3C64XX_SPCON),
-
-	SAVE_ITEM(S3C64XX_MEM0CONSTOP),
-	SAVE_ITEM(S3C64XX_MEM1CONSTOP),
-	SAVE_ITEM(S3C64XX_MEM0CONSLP0),
-	SAVE_ITEM(S3C64XX_MEM0CONSLP1),
-	SAVE_ITEM(S3C64XX_MEM1CONSLP),
-};
-
-void s3c_pm_configure_extint(void)
-{
-	__raw_writel(s3c_irqwake_eintmask, S3C64XX_EINT_MASK);
-}
-
-void s3c_pm_restore_core(void)
-{
-	__raw_writel(0, S3C64XX_EINT_MASK);
-
-	s3c_pm_debug_smdkled(1 << 2, 0);
-
-	s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
-	s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
-}
-
-void s3c_pm_save_core(void)
-{
-	s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
-	s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
-}
-
-/* since both s3c6400 and s3c6410 share the same sleep pm calls, we
- * put the per-cpu code in here until any new cpu comes along and changes
- * this.
- */
-
-static void s3c64xx_cpu_suspend(void)
-{
-	unsigned long tmp;
-
-	/* set our standby method to sleep */
-
-	tmp = __raw_readl(S3C64XX_PWR_CFG);
-	tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK;
-	tmp |= S3C64XX_PWRCFG_CFG_WFI_SLEEP;
-	__raw_writel(tmp, S3C64XX_PWR_CFG);
-
-	/* clear any old wakeup */
-
-	__raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT),
-		     S3C64XX_WAKEUP_STAT);
-
-	/* set the LED state to 0110 over sleep */
-	s3c_pm_debug_smdkled(3 << 1, 0xf);
-
-	/* issue the standby signal into the pm unit. Note, we
-	 * issue a write-buffer drain just in case */
-
-	tmp = 0;
-
-	asm("b 1f\n\t"
-	    ".align 5\n\t"
-	    "1:\n\t"
-	    "mcr p15, 0, %0, c7, c10, 5\n\t"
-	    "mcr p15, 0, %0, c7, c10, 4\n\t"
-	    "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
-
-	/* we should never get past here */
-
-	panic("sleep resumed to originator?");
-}
-
-static void s3c64xx_pm_prepare(void)
-{
-	/* store address of resume. */
-	__raw_writel(virt_to_phys(s3c_cpu_resume), S3C64XX_INFORM0);
-
-	/* ensure previous wakeup state is cleared before sleeping */
-	__raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT), S3C64XX_WAKEUP_STAT);
-}
-
-static int s3c64xx_pm_init(void)
-{
-	pm_cpu_prep = s3c64xx_pm_prepare;
-	pm_cpu_sleep = s3c64xx_cpu_suspend;
-	pm_uart_udivslot = 1;
-	return 0;
-}
-
-arch_initcall(s3c64xx_pm_init);
diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c
deleted file mode 100644
index ffd56de..0000000
--- a/arch/arm/plat-s3c64xx/s3c6400-clock.c
+++ /dev/null
@@ -1,758 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/s3c6400-clock.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C6400 based common clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/sysdev.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <plat/cpu-freq.h>
-
-#include <plat/regs-clock.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-
-/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
- * ext_xtal_mux for want of an actual name from the manual.
-*/
-
-static struct clk clk_ext_xtal_mux = {
-	.name		= "ext_xtal",
-	.id		= -1,
-};
-
-#define clk_fin_apll clk_ext_xtal_mux
-#define clk_fin_mpll clk_ext_xtal_mux
-#define clk_fin_epll clk_ext_xtal_mux
-
-#define clk_fout_mpll	clk_mpll
-#define clk_fout_epll	clk_epll
-
-struct clk_sources {
-	unsigned int	nr_sources;
-	struct clk	**sources;
-};
-
-struct clksrc_clk {
-	struct clk		clk;
-	unsigned int		mask;
-	unsigned int		shift;
-
-	struct clk_sources	*sources;
-
-	unsigned int		divider_shift;
-	void __iomem		*reg_divider;
-};
-
-static struct clk clk_fout_apll = {
-	.name		= "fout_apll",
-	.id		= -1,
-};
-
-static struct clk *clk_src_apll_list[] = {
-	[0] = &clk_fin_apll,
-	[1] = &clk_fout_apll,
-};
-
-static struct clk_sources clk_src_apll = {
-	.sources	= clk_src_apll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_apll_list),
-};
-
-static struct clksrc_clk clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-		.id		= -1,
-	},
-	.shift		= S3C6400_CLKSRC_APLL_MOUT_SHIFT,
-	.mask		= S3C6400_CLKSRC_APLL_MOUT,
-	.sources	= &clk_src_apll,
-};
-
-static struct clk *clk_src_epll_list[] = {
-	[0] = &clk_fin_epll,
-	[1] = &clk_fout_epll,
-};
-
-static struct clk_sources clk_src_epll = {
-	.sources	= clk_src_epll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_epll_list),
-};
-
-static struct clksrc_clk clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-		.id		= -1,
-	},
-	.shift		= S3C6400_CLKSRC_EPLL_MOUT_SHIFT,
-	.mask		= S3C6400_CLKSRC_EPLL_MOUT,
-	.sources	= &clk_src_epll,
-};
-
-static struct clk *clk_src_mpll_list[] = {
-	[0] = &clk_fin_mpll,
-	[1] = &clk_fout_mpll,
-};
-
-static struct clk_sources clk_src_mpll = {
-	.sources	= clk_src_mpll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mpll_list),
-};
-
-static struct clksrc_clk clk_mout_mpll = {
-	.clk = {
-		.name		= "mout_mpll",
-		.id		= -1,
-	},
-	.shift		= S3C6400_CLKSRC_MPLL_MOUT_SHIFT,
-	.mask		= S3C6400_CLKSRC_MPLL_MOUT,
-	.sources	= &clk_src_mpll,
-};
-
-static unsigned int armclk_mask;
-
-static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-	u32 clkdiv;
-
-	/* divisor mask starts at bit0, so no need to shift */
-	clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
-
-	return rate / (clkdiv + 1);
-}
-
-static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
-						unsigned long rate)
-{
-	unsigned long parent = clk_get_rate(clk->parent);
-	u32 div;
-
-	if (parent < rate)
-		return parent;
-
-	div = (parent / rate) - 1;
-	if (div > armclk_mask)
-		div = armclk_mask;
-
-	return parent / (div + 1);
-}
-
-static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent = clk_get_rate(clk->parent);
-	u32 div;
-	u32 val;
-
-	if (rate < parent / (armclk_mask + 1))
-		return -EINVAL;
-
-	rate = clk_round_rate(clk, rate);
-	div = clk_get_rate(clk->parent) / rate;
-
-	val = __raw_readl(S3C_CLK_DIV0);
-	val &= ~armclk_mask;
-	val |= (div - 1);
-	__raw_writel(val, S3C_CLK_DIV0);
-
-	return 0;
-
-}
-
-static struct clk clk_arm = {
-	.name		= "armclk",
-	.id		= -1,
-	.parent		= &clk_mout_apll.clk,
-	.get_rate	= s3c64xx_clk_arm_get_rate,
-	.set_rate	= s3c64xx_clk_arm_set_rate,
-	.round_rate	= s3c64xx_clk_arm_round_rate,
-};
-
-static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-
-	printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
-
-	if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK)
-		rate /= 2;
-
-	return rate;
-}
-
-static struct clk clk_dout_mpll = {
-	.name		= "dout_mpll",
-	.id		= -1,
-	.parent		= &clk_mout_mpll.clk,
-	.get_rate	= s3c64xx_clk_doutmpll_get_rate,
-};
-
-static struct clk *clkset_spi_mmc_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll,
-	&clk_fin_epll,
-	&clk_27m,
-};
-
-static struct clk_sources clkset_spi_mmc = {
-	.sources	= clkset_spi_mmc_list,
-	.nr_sources	= ARRAY_SIZE(clkset_spi_mmc_list),
-};
-
-static struct clk *clkset_irda_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll,
-	NULL,
-	&clk_27m,
-};
-
-static struct clk_sources clkset_irda = {
-	.sources	= clkset_irda_list,
-	.nr_sources	= ARRAY_SIZE(clkset_irda_list),
-};
-
-static struct clk *clkset_uart_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll,
-	NULL,
-	NULL
-};
-
-static struct clk_sources clkset_uart = {
-	.sources	= clkset_uart_list,
-	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_uhost_list[] = {
-	&clk_48m,
-	&clk_mout_epll.clk,
-	&clk_dout_mpll,
-	&clk_fin_epll,
-};
-
-static struct clk_sources clkset_uhost = {
-	.sources	= clkset_uhost_list,
-	.nr_sources	= ARRAY_SIZE(clkset_uhost_list),
-};
-
-
-/* The peripheral clocks are all controlled via clocksource followed
- * by an optional divider and gate stage. We currently roll this into
- * one clock which hides the intermediate clock from the mux.
- *
- * Note, the JPEG clock can only be an even divider...
- *
- * The scaler and LCD clocks depend on the S3C64XX version, and also
- * have a common parent divisor so are not included here.
- */
-
-static inline struct clksrc_clk *to_clksrc(struct clk *clk)
-{
-	return container_of(clk, struct clksrc_clk, clk);
-}
-
-static unsigned long s3c64xx_getrate_clksrc(struct clk *clk)
-{
-	struct clksrc_clk *sclk = to_clksrc(clk);
-	unsigned long rate = clk_get_rate(clk->parent);
-	u32 clkdiv = __raw_readl(sclk->reg_divider);
-
-	clkdiv >>= sclk->divider_shift;
-	clkdiv &= 0xf;
-	clkdiv++;
-
-	rate /= clkdiv;
-	return rate;
-}
-
-static int s3c64xx_setrate_clksrc(struct clk *clk, unsigned long rate)
-{
-	struct clksrc_clk *sclk = to_clksrc(clk);
-	void __iomem *reg = sclk->reg_divider;
-	unsigned int div;
-	u32 val;
-
-	rate = clk_round_rate(clk, rate);
-	div = clk_get_rate(clk->parent) / rate;
-	if (div > 16)
-		return -EINVAL;
-
-	val = __raw_readl(reg);
-	val &= ~(0xf << sclk->divider_shift);
-	val |= (div - 1) << sclk->divider_shift;
-	__raw_writel(val, reg);
-
-	return 0;
-}
-
-static int s3c64xx_setparent_clksrc(struct clk *clk, struct clk *parent)
-{
-	struct clksrc_clk *sclk = to_clksrc(clk);
-	struct clk_sources *srcs = sclk->sources;
-	u32 clksrc = __raw_readl(S3C_CLK_SRC);
-	int src_nr = -1;
-	int ptr;
-
-	for (ptr = 0; ptr < srcs->nr_sources; ptr++)
-		if (srcs->sources[ptr] == parent) {
-			src_nr = ptr;
-			break;
-		}
-
-	if (src_nr >= 0) {
-		clksrc &= ~sclk->mask;
-		clksrc |= src_nr << sclk->shift;
-
-		__raw_writel(clksrc, S3C_CLK_SRC);
-
-		clk->parent = parent;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static unsigned long s3c64xx_roundrate_clksrc(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int div;
-
-	if (rate > parent_rate)
-		rate = parent_rate;
-	else {
-		div = parent_rate / rate;
-
-		if (div == 0)
-			div = 1;
-		if (div > 16)
-			div = 16;
-
-		rate = parent_rate / div;
-	}
-
-	return rate;
-}
-
-static struct clksrc_clk clk_mmc0 = {
-	.clk	= {
-		.name		= "mmc_bus",
-		.id		= 0,
-		.ctrlbit        = S3C_CLKCON_SCLK_MMC0,
-		.enable		= s3c64xx_sclk_ctrl,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= S3C6400_CLKSRC_MMC0_SHIFT,
-	.mask		= S3C6400_CLKSRC_MMC0_MASK,
-	.sources	= &clkset_spi_mmc,
-	.divider_shift	= S3C6400_CLKDIV1_MMC0_SHIFT,
-	.reg_divider	= S3C_CLK_DIV1,
-};
-
-static struct clksrc_clk clk_mmc1 = {
-	.clk	= {
-		.name		= "mmc_bus",
-		.id		= 1,
-		.ctrlbit        = S3C_CLKCON_SCLK_MMC1,
-		.enable		= s3c64xx_sclk_ctrl,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= S3C6400_CLKSRC_MMC1_SHIFT,
-	.mask		= S3C6400_CLKSRC_MMC1_MASK,
-	.sources	= &clkset_spi_mmc,
-	.divider_shift	= S3C6400_CLKDIV1_MMC1_SHIFT,
-	.reg_divider	= S3C_CLK_DIV1,
-};
-
-static struct clksrc_clk clk_mmc2 = {
-	.clk	= {
-		.name		= "mmc_bus",
-		.id		= 2,
-		.ctrlbit        = S3C_CLKCON_SCLK_MMC2,
-		.enable		= s3c64xx_sclk_ctrl,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= S3C6400_CLKSRC_MMC2_SHIFT,
-	.mask		= S3C6400_CLKSRC_MMC2_MASK,
-	.sources	= &clkset_spi_mmc,
-	.divider_shift	= S3C6400_CLKDIV1_MMC2_SHIFT,
-	.reg_divider	= S3C_CLK_DIV1,
-};
-
-static struct clksrc_clk clk_usbhost = {
-	.clk	= {
-		.name		= "usb-bus-host",
-		.id		= -1,
-		.ctrlbit        = S3C_CLKCON_SCLK_UHOST,
-		.enable		= s3c64xx_sclk_ctrl,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= S3C6400_CLKSRC_UHOST_SHIFT,
-	.mask		= S3C6400_CLKSRC_UHOST_MASK,
-	.sources	= &clkset_uhost,
-	.divider_shift	= S3C6400_CLKDIV1_UHOST_SHIFT,
-	.reg_divider	= S3C_CLK_DIV1,
-};
-
-static struct clksrc_clk clk_uart_uclk1 = {
-	.clk	= {
-		.name		= "uclk1",
-		.id		= -1,
-		.ctrlbit        = S3C_CLKCON_SCLK_UART,
-		.enable		= s3c64xx_sclk_ctrl,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= S3C6400_CLKSRC_UART_SHIFT,
-	.mask		= S3C6400_CLKSRC_UART_MASK,
-	.sources	= &clkset_uart,
-	.divider_shift	= S3C6400_CLKDIV2_UART_SHIFT,
-	.reg_divider	= S3C_CLK_DIV2,
-};
-
-/* Where does UCLK0 come from? */
-
-static struct clksrc_clk clk_spi0 = {
-	.clk	= {
-		.name		= "spi-bus",
-		.id		= 0,
-		.ctrlbit        = S3C_CLKCON_SCLK_SPI0,
-		.enable		= s3c64xx_sclk_ctrl,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= S3C6400_CLKSRC_SPI0_SHIFT,
-	.mask		= S3C6400_CLKSRC_SPI0_MASK,
-	.sources	= &clkset_spi_mmc,
-	.divider_shift	= S3C6400_CLKDIV2_SPI0_SHIFT,
-	.reg_divider	= S3C_CLK_DIV2,
-};
-
-static struct clksrc_clk clk_spi1 = {
-	.clk	= {
-		.name		= "spi-bus",
-		.id		= 1,
-		.ctrlbit        = S3C_CLKCON_SCLK_SPI1,
-		.enable		= s3c64xx_sclk_ctrl,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= S3C6400_CLKSRC_SPI1_SHIFT,
-	.mask		= S3C6400_CLKSRC_SPI1_MASK,
-	.sources	= &clkset_spi_mmc,
-	.divider_shift	= S3C6400_CLKDIV2_SPI1_SHIFT,
-	.reg_divider	= S3C_CLK_DIV2,
-};
-
-static struct clk clk_iis_cd0 = {
-	.name		= "iis_cdclk0",
-	.id		= -1,
-};
-
-static struct clk clk_iis_cd1 = {
-	.name		= "iis_cdclk1",
-	.id		= -1,
-};
-
-static struct clk clk_pcm_cd = {
-	.name		= "pcm_cdclk",
-	.id		= -1,
-};
-
-static struct clk *clkset_audio0_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_dout_mpll,
-	[2] = &clk_fin_epll,
-	[3] = &clk_iis_cd0,
-	[4] = &clk_pcm_cd,
-};
-
-static struct clk_sources clkset_audio0 = {
-	.sources	= clkset_audio0_list,
-	.nr_sources	= ARRAY_SIZE(clkset_audio0_list),
-};
-
-static struct clksrc_clk clk_audio0 = {
-	.clk	= {
-		.name		= "audio-bus",
-		.id		= 0,
-		.ctrlbit        = S3C_CLKCON_SCLK_AUDIO0,
-		.enable		= s3c64xx_sclk_ctrl,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= S3C6400_CLKSRC_AUDIO0_SHIFT,
-	.mask		= S3C6400_CLKSRC_AUDIO0_MASK,
-	.sources	= &clkset_audio0,
-	.divider_shift	= S3C6400_CLKDIV2_AUDIO0_SHIFT,
-	.reg_divider	= S3C_CLK_DIV2,
-};
-
-static struct clk *clkset_audio1_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_dout_mpll,
-	[2] = &clk_fin_epll,
-	[3] = &clk_iis_cd1,
-	[4] = &clk_pcm_cd,
-};
-
-static struct clk_sources clkset_audio1 = {
-	.sources	= clkset_audio1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_audio1_list),
-};
-
-static struct clksrc_clk clk_audio1 = {
-	.clk	= {
-		.name		= "audio-bus",
-		.id		= 1,
-		.ctrlbit        = S3C_CLKCON_SCLK_AUDIO1,
-		.enable		= s3c64xx_sclk_ctrl,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= S3C6400_CLKSRC_AUDIO1_SHIFT,
-	.mask		= S3C6400_CLKSRC_AUDIO1_MASK,
-	.sources	= &clkset_audio1,
-	.divider_shift	= S3C6400_CLKDIV2_AUDIO1_SHIFT,
-	.reg_divider	= S3C_CLK_DIV2,
-};
-
-static struct clksrc_clk clk_irda = {
-	.clk	= {
-		.name		= "irda-bus",
-		.id		= 0,
-		.ctrlbit        = S3C_CLKCON_SCLK_IRDA,
-		.enable		= s3c64xx_sclk_ctrl,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= S3C6400_CLKSRC_IRDA_SHIFT,
-	.mask		= S3C6400_CLKSRC_IRDA_MASK,
-	.sources	= &clkset_irda,
-	.divider_shift	= S3C6400_CLKDIV2_IRDA_SHIFT,
-	.reg_divider	= S3C_CLK_DIV2,
-};
-
-static struct clk *clkset_camif_list[] = {
-	&clk_h2,
-};
-
-static struct clk_sources clkset_camif = {
-	.sources	= clkset_camif_list,
-	.nr_sources	= ARRAY_SIZE(clkset_camif_list),
-};
-
-static struct clksrc_clk clk_camif = {
-	.clk	= {
-		.name		= "camera",
-		.id		= -1,
-		.ctrlbit        = S3C_CLKCON_SCLK_CAM,
-		.enable		= s3c64xx_sclk_ctrl,
-		.set_parent	= s3c64xx_setparent_clksrc,
-		.get_rate	= s3c64xx_getrate_clksrc,
-		.set_rate	= s3c64xx_setrate_clksrc,
-		.round_rate	= s3c64xx_roundrate_clksrc,
-	},
-	.shift		= 0,
-	.mask		= 0,
-	.sources	= &clkset_camif,
-	.divider_shift	= S3C6400_CLKDIV0_CAM_SHIFT,
-	.reg_divider	= S3C_CLK_DIV0,
-};
-
-/* Clock initialisation code */
-
-static struct clksrc_clk *init_parents[] = {
-	&clk_mout_apll,
-	&clk_mout_epll,
-	&clk_mout_mpll,
-	&clk_mmc0,
-	&clk_mmc1,
-	&clk_mmc2,
-	&clk_usbhost,
-	&clk_uart_uclk1,
-	&clk_spi0,
-	&clk_spi1,
-	&clk_audio0,
-	&clk_audio1,
-	&clk_irda,
-	&clk_camif,
-};
-
-static void __init_or_cpufreq s3c6400_set_clksrc(struct clksrc_clk *clk)
-{
-	struct clk_sources *srcs = clk->sources;
-	u32 clksrc = __raw_readl(S3C_CLK_SRC);
-
-	clksrc &= clk->mask;
-	clksrc >>= clk->shift;
-
-	if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
-		printk(KERN_ERR "%s: bad source %d\n",
-		       clk->clk.name, clksrc);
-		return;
-	}
-
-	clk->clk.parent = srcs->sources[clksrc];
-
-	printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n",
-	       clk->clk.name, clk->clk.parent->name, clksrc,
-	       clk_get_rate(&clk->clk));
-}
-
-#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
-
-void __init_or_cpufreq s3c6400_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long xtal;
-	unsigned long fclk;
-	unsigned long hclk;
-	unsigned long hclk2;
-	unsigned long pclk;
-	unsigned long epll;
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned int ptr;
-	u32 clkdiv0;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	clkdiv0 = __raw_readl(S3C_CLK_DIV0);
-	printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0);
-
-	xtal_clk = clk_get(NULL, "xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	/* For now assume the mux always selects the crystal */
-	clk_ext_xtal_mux.parent = xtal_clk;
-
-	epll = s3c6400_get_epll(xtal);
-	mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
-	apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
-
-	fclk = mpll;
-
-	printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
-	       apll, mpll, epll);
-
-	hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
-	hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
-	pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
-
-	printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n",
-	       hclk2, hclk, pclk);
-
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_apll.rate = apll;
-
-	clk_h2.rate = hclk2;
-	clk_h.rate = hclk;
-	clk_p.rate = pclk;
-	clk_f.rate = fclk;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
-		s3c6400_set_clksrc(init_parents[ptr]);
-}
-
-static struct clk *clks[] __initdata = {
-	&clk_ext_xtal_mux,
-	&clk_iis_cd0,
-	&clk_iis_cd1,
-	&clk_pcm_cd,
-	&clk_mout_epll.clk,
-	&clk_mout_mpll.clk,
-	&clk_dout_mpll,
-	&clk_mmc0.clk,
-	&clk_mmc1.clk,
-	&clk_mmc2.clk,
-	&clk_usbhost.clk,
-	&clk_uart_uclk1.clk,
-	&clk_spi0.clk,
-	&clk_spi1.clk,
-	&clk_audio0.clk,
-	&clk_audio1.clk,
-	&clk_irda.clk,
-	&clk_camif.clk,
-	&clk_arm,
-};
-
-/**
- * s3c6400_register_clocks - register clocks for s3c6400 and above
- * @armclk_divlimit: Divisor mask for ARMCLK
- *
- * Register the clocks for the S3C6400 and above SoC range, such
- * as ARMCLK and the clocks which have divider chains attached.
- *
- * This call does not setup the clocks, which is left to the
- * s3c6400_setup_clocks() call which may be needed by the cpufreq
- * or resume code to re-set the clocks if the bootloader has changed
- * them.
- */
-void __init s3c6400_register_clocks(unsigned armclk_divlimit)
-{
-	struct clk *clkp;
-	int ret;
-	int ptr;
-
-	armclk_mask = armclk_divlimit;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
-		clkp = clks[ptr];
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-}
diff --git a/arch/arm/plat-s3c64xx/s3c6400-init.c b/arch/arm/plat-s3c64xx/s3c6400-init.c
deleted file mode 100644
index 6c28f39..0000000
--- a/arch/arm/plat-s3c64xx/s3c6400-init.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/s3c6400-init.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * S3C6400 - CPU initialisation (common with other S3C64XX chips)
- *
- * This program is free software; you can redistribute it 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/init.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/s3c6400.h>
-#include <plat/s3c6410.h>
-
-/* uart registration process */
-
-void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no);
-}
diff --git a/arch/arm/plat-s3c64xx/setup-i2c0.c b/arch/arm/plat-s3c64xx/setup-i2c0.c
deleted file mode 100644
index 3644807..0000000
--- a/arch/arm/plat-s3c64xx/setup-i2c0.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/setup-i2c0.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Base S3C64XX I2C bus 0 gpio configuration
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <mach/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-bank-b.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgpin(S3C64XX_GPB(5), S3C64XX_GPB5_I2C_SCL0);
-	s3c_gpio_cfgpin(S3C64XX_GPB(6), S3C64XX_GPB6_I2C_SDA0);
-	s3c_gpio_setpull(S3C64XX_GPB(5), S3C_GPIO_PULL_UP);
-	s3c_gpio_setpull(S3C64XX_GPB(6), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/plat-s3c64xx/setup-i2c1.c b/arch/arm/plat-s3c64xx/setup-i2c1.c
deleted file mode 100644
index bbe229b..0000000
--- a/arch/arm/plat-s3c64xx/setup-i2c1.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/setup-i2c1.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * Base S3C64XX I2C bus 1 gpio configuration
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-struct platform_device; /* don't need the contents */
-
-#include <mach/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-bank-b.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgpin(S3C64XX_GPB(2), S3C64XX_GPB2_I2C_SCL1);
-	s3c_gpio_cfgpin(S3C64XX_GPB(3), S3C64XX_GPB3_I2C_SDA1);
-	s3c_gpio_setpull(S3C64XX_GPB(2), S3C_GPIO_PULL_UP);
-	s3c_gpio_setpull(S3C64XX_GPB(3), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/plat-s3c64xx/sleep.S b/arch/arm/plat-s3c64xx/sleep.S
deleted file mode 100644
index 8e71fe9..0000000
--- a/arch/arm/plat-s3c64xx/sleep.S
+++ /dev/null
@@ -1,144 +0,0 @@
-/* linux/0arch/arm/plat-s3c64xx/sleep.S
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C64XX CPU sleep code
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <mach/map.h>
-
-#undef S3C64XX_VA_GPIO
-#define S3C64XX_VA_GPIO (0x0)
-
-#include <plat/regs-gpio.h>
-#include <plat/gpio-bank-n.h>
-
-#define LL_UART (S3C_PA_UART + (0x400 * CONFIG_S3C_LOWLEVEL_UART_PORT))
-
-	.text
-
-	/* s3c_cpu_save
-	 *
-	 * Save enough processor state to allow the restart of the pm.c
-	 * code after resume.
-	 *
-	 * entry:
-	 *	r0 = pointer to the save block
-	*/
-
-ENTRY(s3c_cpu_save)
-	stmfd	sp!, { r4 - r12, lr }
-
-	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r6, c2, c0, 0	@ Translation Table BASE0
-	mrc	p15, 0, r7, c2, c0, 1	@ Translation Table BASE1
-	mrc	p15, 0, r8, c2, c0, 2	@ Translation Table Control
-	mrc	p15, 0, r9, c1, c0, 0	@ Control register
-	mrc	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
-	mrc	p15, 0, r11, c1, c0, 2	@ Co-processor access controls
-
-	stmia	r0, { r4 - r13 }	@ Save CP registers and SP
-
-	@@ save our state to ram
-	bl	s3c_pm_cb_flushcache
-
-	@@ call final suspend code
-	ldr	r0, =pm_cpu_sleep
-	ldr	pc, [r0]
-	
-	@@ return to the caller, after the MMU is turned on.
-	@@ restore the last bits of the stack and return.
-resume_with_mmu:
-	ldmfd	sp!, { r4 - r12, pc }	@ return, from sp from s3c_cpu_save
-
-	.data
-
-	/* the next bit is code, but it requires easy access to the
-	 * s3c_sleep_save_phys data before the MMU is switched on, so
-	 * we store the code that needs this variable in the .data where
-	 * the value can be written to (the .text segment is RO).
-	*/
-
-	.global	s3c_sleep_save_phys
-s3c_sleep_save_phys:
-	.word	0
-
-	/* Sleep magic, the word before the resume entry point so that the
-	 * bootloader can check for a resumeable image. */
-
-	.word	0x2bedf00d
-
-	/* s3c_cpu_reusme
-	 *
-	 * This is the entry point, stored by whatever method the bootloader
-	 * requires to get the kernel runnign again. This code expects to be
-	 * entered with no caches live and the MMU disabled. It will then
-	 * restore the MMU and other basic CP registers saved and restart
-	 * the kernel C code to finish the resume code.
-	*/
-
-ENTRY(s3c_cpu_resume)
-	msr	cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
-	ldr	r2, =LL_UART		/* for debug */
-
-#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
-	/* Initialise the GPIO state if we are debugging via the SMDK LEDs,
-	 * as the uboot version supplied resets these to inputs during the
-	 * resume checks.
-	*/
-
-	ldr	r3, =S3C64XX_PA_GPIO
-	ldr	r0, [ r3, #S3C64XX_GPNCON ]
-	bic	r0, r0, #(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) | \
-			  S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15))
-	orr	r0, r0, #(S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) | \
-			  S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15))
-	str	r0, [ r3, #S3C64XX_GPNCON ]
-
-	ldr	r0, [ r3, #S3C64XX_GPNDAT ]
-	bic	r0, r0, #0xf << 12			@ GPN12..15
-	orr	r0, r0, #1 << 15			@ GPN15
-	str	r0, [ r3, #S3C64XX_GPNDAT ]
-#endif
-
-	/* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
-	 * are thoroughly cleaned just in case the bootloader didn't do it
-	 * for us. */
-	mov	r0, #0
-	mcr	p15, 0, r0, c7, c14, 0		@ clean+invalidate D cache
-	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mcr	p15, 0, r0, c7, c15, 0		@ clean+invalidate cache
-	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	@@mcr	p15, 0, r0, c8, c7, 0		@ invalidate I + D TLBs
-	@@mcr	p15, 0, r0, c7, c7, 0		@ Invalidate I + D caches
-
-	ldr	r0, s3c_sleep_save_phys
-	ldmia	r0, { r4 - r13 }
-
-	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mcr	p15, 0, r6, c2, c0, 0	@ Translation Table BASE0
-	mcr	p15, 0, r7, c2, c0, 1	@ Translation Table BASE1
-	mcr	p15, 0, r8, c2, c0, 2	@ Translation Table Control
-	mcr	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
-
-	mov	r0, #0			@ restore copro access controls
-	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access controls
-	mcr 	p15, 0, r0, c7, c5, 4
-
-	ldr	r2, =resume_with_mmu
-	mcr	p15, 0, r9, c1, c0, 0		/* turn mmu back on */
-	nop
-	mov	pc, r2				/* jump back */
-
-	.end
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
new file mode 100644
index 0000000..d400a6a
--- /dev/null
+++ b/arch/arm/plat-s5p/Kconfig
@@ -0,0 +1,25 @@
+# arch/arm/plat-s5p/Kconfig
+#
+# Copyright (c) 2009 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+config PLAT_S5P
+	bool
+	depends on (ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PV210)
+	default y
+	select ARM_VIC
+	select NO_IOPORT
+	select ARCH_REQUIRE_GPIOLIB
+	select S3C_GPIO_TRACK
+	select SAMSUNG_GPIOLIB_4BIT
+	select S3C_GPIO_CFG_S3C64XX
+	select S3C_GPIO_PULL_UPDOWN
+	select S3C_GPIO_CFG_S3C24XX
+	select PLAT_SAMSUNG
+	select SAMSUNG_CLKSRC
+	select SAMSUNG_IRQ_VIC_TIMER
+	select SAMSUNG_IRQ_UART
+	help
+	  Base platform code for Samsung's S5P series SoC.
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
new file mode 100644
index 0000000..a7c54b3
--- /dev/null
+++ b/arch/arm/plat-s5p/Makefile
@@ -0,0 +1,19 @@
+# arch/arm/plat-s5p/Makefile
+#
+# Copyright (c) 2009 Samsung Electronics Co., Ltd.
+# 		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:= dummy.o
+obj-				:=
+
+# Core files
+
+obj-y				+= dev-uart.o
+obj-y				+= cpu.o
+obj-y				+= clock.o
+obj-y				+= irq.o
+obj-y				+= setup-i2c0.o
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c
new file mode 100644
index 0000000..aa96e33
--- /dev/null
+++ b/arch/arm/plat-s5p/clock.c
@@ -0,0 +1,149 @@
+/* linux/arch/arm/plat-s5p/clock.c
+ *
+ * Copyright 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P - Common clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+#include <asm/div64.h>
+
+#include <plat/clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/s5p-clock.h>
+
+/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
+ * clk_ext_xtal_mux.
+*/
+struct clk clk_ext_xtal_mux = {
+	.name		= "ext_xtal",
+	.id		= -1,
+};
+
+static struct clk s5p_clk_27m = {
+	.name		= "clk_27m",
+	.id		= -1,
+	.rate		= 27000000,
+};
+
+/* 48MHz USB Phy clock output */
+struct clk clk_48m = {
+	.name		= "clk_48m",
+	.id		= -1,
+	.rate		= 48000000,
+};
+
+/* APLL clock output
+ * No need .ctrlbit, this is always on
+*/
+struct clk clk_fout_apll = {
+	.name		= "fout_apll",
+	.id		= -1,
+};
+
+/* MPLL clock output
+ * No need .ctrlbit, this is always on
+*/
+struct clk clk_fout_mpll = {
+	.name		= "fout_mpll",
+	.id		= -1,
+};
+
+/* EPLL clock output */
+struct clk clk_fout_epll = {
+	.name		= "fout_epll",
+	.id		= -1,
+	.ctrlbit	= (1 << 31),
+};
+
+/* ARM clock */
+struct clk clk_arm = {
+	.name		= "armclk",
+	.id		= -1,
+	.rate		= 0,
+	.ctrlbit	= 0,
+};
+
+/* Possible clock sources for APLL Mux */
+static struct clk *clk_src_apll_list[] = {
+	[0] = &clk_fin_apll,
+	[1] = &clk_fout_apll,
+};
+
+struct clksrc_sources clk_src_apll = {
+	.sources	= clk_src_apll_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_apll_list),
+};
+
+/* Possible clock sources for MPLL Mux */
+static struct clk *clk_src_mpll_list[] = {
+	[0] = &clk_fin_mpll,
+	[1] = &clk_fout_mpll,
+};
+
+struct clksrc_sources clk_src_mpll = {
+	.sources	= clk_src_mpll_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_mpll_list),
+};
+
+/* Possible clock sources for EPLL Mux */
+static struct clk *clk_src_epll_list[] = {
+	[0] = &clk_fin_epll,
+	[1] = &clk_fout_epll,
+};
+
+struct clksrc_sources clk_src_epll = {
+	.sources	= clk_src_epll_list,
+	.nr_sources	= ARRAY_SIZE(clk_src_epll_list),
+};
+
+struct clk clk_vpll = {
+	.name		= "vpll",
+	.id		= -1,
+};
+
+int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable)
+{
+	unsigned int ctrlbit = clk->ctrlbit;
+	u32 con;
+
+	con = __raw_readl(reg);
+	con = enable ? (con | ctrlbit) : (con & ~ctrlbit);
+	__raw_writel(con, reg);
+	return 0;
+}
+
+static struct clk *s5p_clks[] __initdata = {
+	&clk_ext_xtal_mux,
+	&clk_48m,
+	&s5p_clk_27m,
+	&clk_fout_apll,
+	&clk_fout_mpll,
+	&clk_fout_epll,
+	&clk_arm,
+	&clk_vpll,
+};
+
+void __init s5p_register_clocks(unsigned long xtal_freq)
+{
+	int ret;
+
+	clk_ext_xtal_mux.rate = xtal_freq;
+
+	ret = s3c24xx_register_clocks(s5p_clks, ARRAY_SIZE(s5p_clks));
+	if (ret > 0)
+		printk(KERN_ERR "Failed to register s5p clocks\n");
+}
diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
new file mode 100644
index 0000000..f92e5de
--- /dev/null
+++ b/arch/arm/plat-s5p/cpu.c
@@ -0,0 +1,113 @@
+/* linux/arch/arm/plat-s5p/cpu.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P CPU Support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <mach/map.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/regs-clock.h>
+#include <plat/cpu.h>
+#include <plat/s5p6440.h>
+#include <plat/s5p6442.h>
+#include <plat/s5pv210.h>
+
+/* table of supported CPUs */
+
+static const char name_s5p6440[] = "S5P6440";
+static const char name_s5p6442[] = "S5P6442";
+static const char name_s5pv210[] = "S5PV210/S5PC110";
+
+static struct cpu_table cpu_ids[] __initdata = {
+	{
+		.idcode		= 0x56440100,
+		.idmask		= 0xffffff00,
+		.map_io		= s5p6440_map_io,
+		.init_clocks	= s5p6440_init_clocks,
+		.init_uarts	= s5p6440_init_uarts,
+		.init		= s5p6440_init,
+		.name		= name_s5p6440,
+	}, {
+		.idcode		= 0x36442000,
+		.idmask		= 0xffffff00,
+		.map_io		= s5p6442_map_io,
+		.init_clocks	= s5p6442_init_clocks,
+		.init_uarts	= s5p6442_init_uarts,
+		.init		= s5p6442_init,
+		.name		= name_s5p6442,
+	}, {
+		.idcode		= 0x43110000,
+		.idmask		= 0xfffff000,
+		.map_io		= s5pv210_map_io,
+		.init_clocks	= s5pv210_init_clocks,
+		.init_uarts	= s5pv210_init_uarts,
+		.init		= s5pv210_init,
+		.name		= name_s5pv210,
+	},
+};
+
+/* minimal IO mapping */
+
+static struct map_desc s5p_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_CHIPID,
+		.pfn		= __phys_to_pfn(S5P_PA_CHIPID),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_SYS,
+		.pfn		= __phys_to_pfn(S5P_PA_SYSCON),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_UART,
+		.pfn		= __phys_to_pfn(S3C_PA_UART),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC0,
+		.pfn		= __phys_to_pfn(S5P_PA_VIC0),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)VA_VIC1,
+		.pfn		= __phys_to_pfn(S5P_PA_VIC1),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_TIMER,
+		.pfn		= __phys_to_pfn(S5P_PA_TIMER),
+		.length		= SZ_16K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO,
+		.pfn		= __phys_to_pfn(S5P_PA_GPIO),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+/* read cpu identification code */
+
+void __init s5p_init_io(struct map_desc *mach_desc,
+			int size, void __iomem *cpuid_addr)
+{
+	unsigned long idcode;
+
+	/* initialize the io descriptors we need for initialization */
+	iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
+	if (mach_desc)
+		iotable_init(mach_desc, size);
+
+	idcode = __raw_readl(cpuid_addr);
+	s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
+}
diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c
new file mode 100644
index 0000000..a89331e
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-uart.c
@@ -0,0 +1,139 @@
+/* linux/arch/arm/plat-s5p/dev-uart.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Base S5P UART resource and device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+ /* Serial port registrations */
+
+static struct resource s5p_uart0_resource[] = {
+	[0] = {
+		.start	= S5P_PA_UART0,
+		.end	= S5P_PA_UART0 + S5P_SZ_UART,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_S5P_UART_RX0,
+		.end	= IRQ_S5P_UART_RX0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_S5P_UART_TX0,
+		.end	= IRQ_S5P_UART_TX0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= IRQ_S5P_UART_ERR0,
+		.end	= IRQ_S5P_UART_ERR0,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s5p_uart1_resource[] = {
+	[0] = {
+		.start	= S5P_PA_UART1,
+		.end	= S5P_PA_UART1 + S5P_SZ_UART,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_S5P_UART_RX1,
+		.end	= IRQ_S5P_UART_RX1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_S5P_UART_TX1,
+		.end	= IRQ_S5P_UART_TX1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= IRQ_S5P_UART_ERR1,
+		.end	= IRQ_S5P_UART_ERR1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource s5p_uart2_resource[] = {
+	[0] = {
+		.start	= S5P_PA_UART2,
+		.end	= S5P_PA_UART2 + S5P_SZ_UART,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_S5P_UART_RX2,
+		.end	= IRQ_S5P_UART_RX2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_S5P_UART_TX2,
+		.end	= IRQ_S5P_UART_TX2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= IRQ_S5P_UART_ERR2,
+		.end	= IRQ_S5P_UART_ERR2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource s5p_uart3_resource[] = {
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
+	[0] = {
+		.start	= S5P_PA_UART3,
+		.end	= S5P_PA_UART3 + S5P_SZ_UART,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_S5P_UART_RX3,
+		.end	= IRQ_S5P_UART_RX3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_S5P_UART_TX3,
+		.end	= IRQ_S5P_UART_TX3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start	= IRQ_S5P_UART_ERR3,
+		.end	= IRQ_S5P_UART_ERR3,
+		.flags	= IORESOURCE_IRQ,
+	},
+#endif
+};
+
+struct s3c24xx_uart_resources s5p_uart_resources[] __initdata = {
+	[0] = {
+		.resources	= s5p_uart0_resource,
+		.nr_resources	= ARRAY_SIZE(s5p_uart0_resource),
+	},
+	[1] = {
+		.resources	= s5p_uart1_resource,
+		.nr_resources	= ARRAY_SIZE(s5p_uart1_resource),
+	},
+	[2] = {
+		.resources	= s5p_uart2_resource,
+		.nr_resources	= ARRAY_SIZE(s5p_uart2_resource),
+	},
+	[3] = {
+		.resources	= s5p_uart3_resource,
+		.nr_resources	= ARRAY_SIZE(s5p_uart3_resource),
+	},
+};
diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h
new file mode 100644
index 0000000..42e757f
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/irqs.h
@@ -0,0 +1,90 @@
+/* linux/arch/arm/plat-s5p/include/plat/irqs.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P Common IRQ support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_S5P_IRQS_H
+#define __ASM_PLAT_S5P_IRQS_H __FILE__
+
+/* we keep the first set of CPU IRQs out of the range of
+ * the ISA space, so that the PC104 has them to itself
+ * and we don't end up having to do horrible things to the
+ * standard ISA drivers....
+ *
+ * note, since we're using the VICs, our start must be a
+ * mulitple of 32 to allow the common code to work
+ */
+
+#define S5P_IRQ_OFFSET		(32)
+
+#define S5P_IRQ(x)		((x) + S5P_IRQ_OFFSET)
+
+#define S5P_VIC0_BASE		S5P_IRQ(0)
+#define S5P_VIC1_BASE		S5P_IRQ(32)
+#define S5P_VIC2_BASE		S5P_IRQ(64)
+#define S5P_VIC3_BASE		S5P_IRQ(96)
+
+#define VIC_BASE(x)		(S5P_VIC0_BASE + ((x)*32))
+
+#define IRQ_VIC0_BASE		S5P_VIC0_BASE
+#define IRQ_VIC1_BASE		S5P_VIC1_BASE
+#define IRQ_VIC2_BASE		S5P_VIC2_BASE
+
+/* UART interrupts, each UART has 4 intterupts per channel so
+ * use the space between the ISA and S3C main interrupts. Note, these
+ * are not in the same order as the S3C24XX series! */
+
+#define IRQ_S5P_UART_BASE0	(16)
+#define IRQ_S5P_UART_BASE1	(20)
+#define IRQ_S5P_UART_BASE2	(24)
+#define IRQ_S5P_UART_BASE3	(28)
+
+#define UART_IRQ_RXD		(0)
+#define UART_IRQ_ERR		(1)
+#define UART_IRQ_TXD		(2)
+
+#define IRQ_S5P_UART_RX0	(IRQ_S5P_UART_BASE0 + UART_IRQ_RXD)
+#define IRQ_S5P_UART_TX0	(IRQ_S5P_UART_BASE0 + UART_IRQ_TXD)
+#define IRQ_S5P_UART_ERR0	(IRQ_S5P_UART_BASE0 + UART_IRQ_ERR)
+
+#define IRQ_S5P_UART_RX1	(IRQ_S5P_UART_BASE1 + UART_IRQ_RXD)
+#define IRQ_S5P_UART_TX1	(IRQ_S5P_UART_BASE1 + UART_IRQ_TXD)
+#define IRQ_S5P_UART_ERR1	(IRQ_S5P_UART_BASE1 + UART_IRQ_ERR)
+
+#define IRQ_S5P_UART_RX2	(IRQ_S5P_UART_BASE2 + UART_IRQ_RXD)
+#define IRQ_S5P_UART_TX2	(IRQ_S5P_UART_BASE2 + UART_IRQ_TXD)
+#define IRQ_S5P_UART_ERR2	(IRQ_S5P_UART_BASE2 + UART_IRQ_ERR)
+
+#define IRQ_S5P_UART_RX3	(IRQ_S5P_UART_BASE3 + UART_IRQ_RXD)
+#define IRQ_S5P_UART_TX3	(IRQ_S5P_UART_BASE3 + UART_IRQ_TXD)
+#define IRQ_S5P_UART_ERR3	(IRQ_S5P_UART_BASE3 + UART_IRQ_ERR)
+
+/* S3C compatibilty defines */
+#define IRQ_S3CUART_RX0		IRQ_S5P_UART_RX0
+#define IRQ_S3CUART_RX1		IRQ_S5P_UART_RX1
+#define IRQ_S3CUART_RX2		IRQ_S5P_UART_RX2
+#define IRQ_S3CUART_RX3		IRQ_S5P_UART_RX3
+
+/* VIC based IRQs */
+
+#define S5P_IRQ_VIC0(x)		(S5P_VIC0_BASE + (x))
+#define S5P_IRQ_VIC1(x)		(S5P_VIC1_BASE + (x))
+#define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
+#define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
+
+#define S5P_TIMER_IRQ(x)	S5P_IRQ(11 + (x))
+
+#define IRQ_TIMER0		S5P_TIMER_IRQ(0)
+#define IRQ_TIMER1		S5P_TIMER_IRQ(1)
+#define IRQ_TIMER2		S5P_TIMER_IRQ(2)
+#define IRQ_TIMER3		S5P_TIMER_IRQ(3)
+#define IRQ_TIMER4		S5P_TIMER_IRQ(4)
+
+#endif /* __ASM_PLAT_S5P_IRQS_H */
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h
new file mode 100644
index 0000000..1482852
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/map-s5p.h
@@ -0,0 +1,34 @@
+/* linux/arch/arm/plat-s5p/include/plat/map-s5p.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_MAP_S5P_H
+#define __ASM_PLAT_MAP_S5P_H __FILE__
+
+#define S5P_VA_CHIPID		S3C_ADDR(0x00700000)
+#define S5P_VA_GPIO		S3C_ADDR(0x00500000)
+#define S5P_VA_SYSTIMER		S3C_ADDR(0x01200000)
+#define S5P_VA_SROMC		S3C_ADDR(0x01100000)
+
+#define S5P_VA_UART0		(S3C_VA_UART + 0x0)
+#define S5P_VA_UART1		(S3C_VA_UART + 0x400)
+#define S5P_VA_UART2		(S3C_VA_UART + 0x800)
+#define S5P_VA_UART3		(S3C_VA_UART + 0xC00)
+
+#define S3C_UART_OFFSET		(0x400)
+
+#define VA_VIC(x)		(S3C_VA_IRQ + ((x) * 0x10000))
+#define VA_VIC0			VA_VIC(0)
+#define VA_VIC1			VA_VIC(1)
+#define VA_VIC2			VA_VIC(2)
+#define VA_VIC3			VA_VIC(3)
+
+#endif /* __ASM_PLAT_MAP_S5P_H */
diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h
new file mode 100644
index 0000000..d48325b
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/pll.h
@@ -0,0 +1,83 @@
+/* arch/arm/plat-s5p/include/plat/pll.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P PLL code
+ *
+ * Based on arch/arm/plat-s3c64xx/include/plat/pll.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define PLL45XX_MDIV_MASK	(0x3FF)
+#define PLL45XX_PDIV_MASK	(0x3F)
+#define PLL45XX_SDIV_MASK	(0x7)
+#define PLL45XX_MDIV_SHIFT	(16)
+#define PLL45XX_PDIV_SHIFT	(8)
+#define PLL45XX_SDIV_SHIFT	(0)
+
+#include <asm/div64.h>
+
+enum pll45xx_type_t {
+	pll_4500,
+	pll_4502,
+	pll_4508
+};
+
+static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
+					    enum pll45xx_type_t pll_type)
+{
+	u32 mdiv, pdiv, sdiv;
+	u64 fvco = baseclk;
+
+	mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
+
+	if (pll_type == pll_4508)
+		sdiv = sdiv - 1;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+#define PLL90XX_MDIV_MASK	(0xFF)
+#define PLL90XX_PDIV_MASK	(0x3F)
+#define PLL90XX_SDIV_MASK	(0x7)
+#define PLL90XX_KDIV_MASK	(0xffff)
+#define PLL90XX_MDIV_SHIFT	(16)
+#define PLL90XX_PDIV_SHIFT	(8)
+#define PLL90XX_SDIV_SHIFT	(0)
+#define PLL90XX_KDIV_SHIFT	(0)
+
+static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
+					    u32 pll_con, u32 pll_conk)
+{
+	unsigned long result;
+	u32 mdiv, pdiv, sdiv, kdiv;
+	u64 tmp;
+
+	mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
+	pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
+	sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
+	kdiv = pll_conk & PLL90XX_KDIV_MASK;
+
+	/* We need to multiple baseclk by mdiv (the integer part) and kdiv
+	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
+	 * add kdiv before multiplying. The use of tmp is to avoid any
+	 * overflows before shifting bac down into result when multipling
+	 * by the mdiv and kdiv pair.
+	 */
+
+	tmp = baseclk;
+	tmp *= (mdiv << 16) + kdiv;
+	do_div(tmp, (pdiv << sdiv));
+	result = tmp >> 16;
+
+	return result;
+}
diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h
new file mode 100644
index 0000000..56fb8b4
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h
@@ -0,0 +1,40 @@
+/* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h
+ *
+ * Copyright 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5p clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_S5P_CLOCK_H
+#define __ASM_PLAT_S5P_CLOCK_H __FILE__
+
+#include <linux/clk.h>
+
+#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
+
+#define clk_fin_apll clk_ext_xtal_mux
+#define clk_fin_mpll clk_ext_xtal_mux
+#define clk_fin_epll clk_ext_xtal_mux
+#define clk_fin_vpll clk_ext_xtal_mux
+
+extern struct clk clk_ext_xtal_mux;
+extern struct clk clk_48m;
+extern struct clk clk_fout_apll;
+extern struct clk clk_fout_mpll;
+extern struct clk clk_fout_epll;
+extern struct clk clk_arm;
+extern struct clk clk_vpll;
+
+extern struct clksrc_sources clk_src_apll;
+extern struct clksrc_sources clk_src_mpll;
+extern struct clksrc_sources clk_src_epll;
+
+extern int s5p6440_clk48m_ctrl(struct clk *clk, int enable);
+extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);
+
+#endif /* __ASM_PLAT_S5P_CLOCK_H */
diff --git a/arch/arm/plat-s5p/include/plat/s5p6440.h b/arch/arm/plat-s5p/include/plat/s5p6440.h
new file mode 100644
index 0000000..a4cd75a
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/s5p6440.h
@@ -0,0 +1,37 @@
+/* arch/arm/plat-s5p/include/plat/s5p6440.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5p6440 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+ /* Common init code for S5P6440 related SoCs */
+
+extern void s5p6440_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s5p6440_register_clocks(void);
+extern void s5p6440_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6440
+
+extern  int s5p6440_init(void);
+extern void s5p6440_init_irq(void);
+extern void s5p6440_map_io(void);
+extern void s5p6440_init_clocks(int xtal);
+
+#define s5p6440_init_uarts s5p6440_common_init_uarts
+
+#else
+#define s5p6440_init_clocks NULL
+#define s5p6440_init_uarts NULL
+#define s5p6440_map_io NULL
+#define s5p6440_init NULL
+#endif
+
+/* S5P6440 timer */
+
+extern struct sys_timer s5p6440_timer;
diff --git a/arch/arm/plat-s5p/include/plat/s5p6442.h b/arch/arm/plat-s5p/include/plat/s5p6442.h
new file mode 100644
index 0000000..7b88013
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/s5p6442.h
@@ -0,0 +1,33 @@
+/* arch/arm/plat-s5p/include/plat/s5p6442.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5p6442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Common init code for S5P6442 related SoCs */
+
+extern void s5p6442_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s5p6442_register_clocks(void);
+extern void s5p6442_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5P6442
+
+extern  int s5p6442_init(void);
+extern void s5p6442_init_irq(void);
+extern void s5p6442_map_io(void);
+extern void s5p6442_init_clocks(int xtal);
+
+#define s5p6442_init_uarts s5p6442_common_init_uarts
+
+#else
+#define s5p6442_init_clocks NULL
+#define s5p6442_init_uarts NULL
+#define s5p6442_map_io NULL
+#define s5p6442_init NULL
+#endif
diff --git a/arch/arm/plat-s5p/include/plat/s5pv210.h b/arch/arm/plat-s5p/include/plat/s5pv210.h
new file mode 100644
index 0000000..6c93a0c
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/s5pv210.h
@@ -0,0 +1,33 @@
+/* linux/arch/arm/plat-s5p/include/plat/s5pv210.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5pv210 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Common init code for S5PV210 related SoCs */
+
+extern void s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void s5pv210_register_clocks(void);
+extern void s5pv210_setup_clocks(void);
+
+#ifdef CONFIG_CPU_S5PV210
+
+extern  int s5pv210_init(void);
+extern void s5pv210_init_irq(void);
+extern void s5pv210_map_io(void);
+extern void s5pv210_init_clocks(int xtal);
+
+#define s5pv210_init_uarts s5pv210_common_init_uarts
+
+#else
+#define s5pv210_init_clocks NULL
+#define s5pv210_init_uarts NULL
+#define s5pv210_map_io NULL
+#define s5pv210_init NULL
+#endif
diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c
new file mode 100644
index 0000000..25e1eb6
--- /dev/null
+++ b/arch/arm/plat-s5p/irq.c
@@ -0,0 +1,72 @@
+/* arch/arm/plat-s5p/irq.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P - Interrupt handling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/hardware/vic.h>
+
+#include <linux/serial_core.h>
+#include <mach/map.h>
+#include <plat/regs-timer.h>
+#include <plat/regs-serial.h>
+#include <plat/cpu.h>
+#include <plat/irq-vic-timer.h>
+#include <plat/irq-uart.h>
+
+/*
+ * Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
+ * are consecutive when looking up the interrupt in the demux routines.
+ */
+static struct s3c_uart_irq uart_irqs[] = {
+	[0] = {
+		.regs		= S5P_VA_UART0,
+		.base_irq	= IRQ_S5P_UART_BASE0,
+		.parent_irq	= IRQ_UART0,
+	},
+	[1] = {
+		.regs		= S5P_VA_UART1,
+		.base_irq	= IRQ_S5P_UART_BASE1,
+		.parent_irq	= IRQ_UART1,
+	},
+	[2] = {
+		.regs		= S5P_VA_UART2,
+		.base_irq	= IRQ_S5P_UART_BASE2,
+		.parent_irq	= IRQ_UART2,
+	},
+#if CONFIG_SERIAL_SAMSUNG_UARTS > 3
+	[3] = {
+		.regs		= S5P_VA_UART3,
+		.base_irq	= IRQ_S5P_UART_BASE3,
+		.parent_irq	= IRQ_UART3,
+	},
+#endif
+};
+
+void __init s5p_init_irq(u32 *vic, u32 num_vic)
+{
+	int irq;
+
+	/* initialize the VICs */
+	for (irq = 0; irq < num_vic; irq++)
+		vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
+
+	s3c_init_vic_timer_irq(IRQ_TIMER0_VIC, IRQ_TIMER0);
+	s3c_init_vic_timer_irq(IRQ_TIMER1_VIC, IRQ_TIMER1);
+	s3c_init_vic_timer_irq(IRQ_TIMER2_VIC, IRQ_TIMER2);
+	s3c_init_vic_timer_irq(IRQ_TIMER3_VIC, IRQ_TIMER3);
+	s3c_init_vic_timer_irq(IRQ_TIMER4_VIC, IRQ_TIMER4);
+
+	s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
+}
diff --git a/arch/arm/plat-s5p/setup-i2c0.c b/arch/arm/plat-s5p/setup-i2c0.c
new file mode 100644
index 0000000..67a66e0
--- /dev/null
+++ b/arch/arm/plat-s5p/setup-i2c0.c
@@ -0,0 +1,25 @@
+/* linux/arch/arm/plat-s5p/setup-i2c0.c
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * I2C0 GPIO configuration.
+ *
+ * Based on plat-s3c64xx/setup-i2c0.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+struct platform_device; /* don't need the contents */
+
+#include <plat/iic.h>
+
+void s3c_i2c0_cfg_gpio(struct platform_device *dev)
+{
+	/* Will be populated later */
+}
diff --git a/arch/arm/plat-s5pc1xx/Kconfig b/arch/arm/plat-s5pc1xx/Kconfig
index b7b9e91..c7ccdf2 100644
--- a/arch/arm/plat-s5pc1xx/Kconfig
+++ b/arch/arm/plat-s5pc1xx/Kconfig
@@ -11,6 +11,9 @@
 	select ARM_VIC
 	select NO_IOPORT
 	select ARCH_REQUIRE_GPIOLIB
+	select SAMSUNG_CLKSRC
+	select SAMSUNG_IRQ_UART
+	select SAMSUNG_IRQ_VIC_TIMER
 	select S3C_GPIO_TRACK
 	select S3C_GPIO_PULL_UPDOWN
 	select S3C_GPIO_CFG_S3C24XX
diff --git a/arch/arm/plat-s5pc1xx/clock.c b/arch/arm/plat-s5pc1xx/clock.c
index 26c21d8..387f231 100644
--- a/arch/arm/plat-s5pc1xx/clock.c
+++ b/arch/arm/plat-s5pc1xx/clock.c
@@ -64,25 +64,13 @@
 	.rate		= 54000000,
 };
 
-static int clk_default_setrate(struct clk *clk, unsigned long rate)
-{
-	clk->rate = rate;
-	return 0;
-}
-
-static int clk_dummy_enable(struct clk *clk, int enable)
-{
-	return 0;
-}
-
 struct clk clk_hd0 = {
 	.name		= "hclkd0",
 	.id		= -1,
 	.rate		= 0,
 	.parent		= NULL,
 	.ctrlbit	= 0,
-	.set_rate	= clk_default_setrate,
-	.enable		= clk_dummy_enable,
+	.ops		= &clk_ops_def_setrate,
 };
 
 struct clk clk_pd0 = {
@@ -91,8 +79,7 @@
 	.rate		= 0,
 	.parent		= NULL,
 	.ctrlbit	= 0,
-	.set_rate	= clk_default_setrate,
-	.enable		= clk_dummy_enable,
+	.ops		= &clk_ops_def_setrate,
 };
 
 static int s5pc1xx_clk_gate(void __iomem *reg, struct clk *clk, int enable)
@@ -686,6 +673,8 @@
 static struct clk *clks[] __initdata = {
 	&clk_ext,
 	&clk_epll,
+	&clk_pd0,
+	&clk_hd0,
 	&clk_27m,
 	&clk_48m,
 	&clk_54m,
@@ -700,16 +689,8 @@
 
 	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
 
-	clkp = s5pc100_init_clocks;
-	size = ARRAY_SIZE(s5pc100_init_clocks);
-
-	for (ptr = 0; ptr < size; ptr++, clkp++) {
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
+	s3c_register_clocks(s5pc100_init_clocks,
+			    ARRAY_SIZE(s5pc100_init_clocks));
 
 	clkp = s5pc100_init_clocks_disable;
 	size = ARRAY_SIZE(s5pc100_init_clocks_disable);
diff --git a/arch/arm/plat-s5pc1xx/dev-uart.c b/arch/arm/plat-s5pc1xx/dev-uart.c
index f749bc5..586c95c 100644
--- a/arch/arm/plat-s5pc1xx/dev-uart.c
+++ b/arch/arm/plat-s5pc1xx/dev-uart.c
@@ -143,32 +143,3 @@
 		.nr_resources	= ARRAY_SIZE(s5pc1xx_uart3_resource),
 	},
 };
-
-/* uart devices */
-
-static struct platform_device s3c24xx_uart_device0 = {
-	.id		= 0,
-};
-
-static struct platform_device s3c24xx_uart_device1 = {
-	.id		= 1,
-};
-
-static struct platform_device s3c24xx_uart_device2 = {
-	.id		= 2,
-};
-
-static struct platform_device s3c24xx_uart_device3 = {
-	.id		= 3,
-};
-
-struct platform_device *s3c24xx_uart_src[4] = {
-	&s3c24xx_uart_device0,
-	&s3c24xx_uart_device1,
-	&s3c24xx_uart_device2,
-	&s3c24xx_uart_device3,
-};
-
-struct platform_device *s3c24xx_uart_devs[4] = {
-};
-
diff --git a/arch/arm/plat-s5pc1xx/gpio-config.c b/arch/arm/plat-s5pc1xx/gpio-config.c
index bba675d..a4f67e8 100644
--- a/arch/arm/plat-s5pc1xx/gpio-config.c
+++ b/arch/arm/plat-s5pc1xx/gpio-config.c
@@ -16,7 +16,7 @@
 #include <linux/gpio.h>
 #include <linux/io.h>
 
-#include <mach/gpio-core.h>
+#include <plat/gpio-core.h>
 #include <plat/gpio-cfg-s5pc1xx.h>
 
 s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin, unsigned int off)
diff --git a/arch/arm/plat-s5pc1xx/gpiolib.c b/arch/arm/plat-s5pc1xx/gpiolib.c
index facb410..1ffc57a 100644
--- a/arch/arm/plat-s5pc1xx/gpiolib.c
+++ b/arch/arm/plat-s5pc1xx/gpiolib.c
@@ -17,8 +17,8 @@
 #include <linux/gpio.h>
 
 #include <mach/map.h>
-#include <mach/gpio-core.h>
 
+#include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
 #include <plat/regs-gpio.h>
diff --git a/arch/arm/plat-s5pc1xx/include/plat/irqs.h b/arch/arm/plat-s5pc1xx/include/plat/irqs.h
index ef87363..409c8043 100644
--- a/arch/arm/plat-s5pc1xx/include/plat/irqs.h
+++ b/arch/arm/plat-s5pc1xx/include/plat/irqs.h
@@ -88,11 +88,11 @@
 #define IRQ_MDMA		S5PC1XX_IRQ_VIC0(18)
 #define IRQ_PDMA0		S5PC1XX_IRQ_VIC0(19)
 #define IRQ_PDMA1		S5PC1XX_IRQ_VIC0(20)
-#define IRQ_TIMER0		S5PC1XX_IRQ_VIC0(21)
-#define IRQ_TIMER1		S5PC1XX_IRQ_VIC0(22)
-#define IRQ_TIMER2		S5PC1XX_IRQ_VIC0(23)
-#define IRQ_TIMER3		S5PC1XX_IRQ_VIC0(24)
-#define IRQ_TIMER4		S5PC1XX_IRQ_VIC0(25)
+#define IRQ_TIMER0_VIC		S5PC1XX_IRQ_VIC0(21)
+#define IRQ_TIMER1_VIC		S5PC1XX_IRQ_VIC0(22)
+#define IRQ_TIMER2_VIC		S5PC1XX_IRQ_VIC0(23)
+#define IRQ_TIMER3_VIC		S5PC1XX_IRQ_VIC0(24)
+#define IRQ_TIMER4_VIC		S5PC1XX_IRQ_VIC0(25)
 #define IRQ_SYSTIMER		S5PC1XX_IRQ_VIC0(26)
 #define IRQ_WDT			S5PC1XX_IRQ_VIC0(27)
 #define IRQ_RTC_ALARM		S5PC1XX_IRQ_VIC0(28)
@@ -171,8 +171,15 @@
 #define IRQ_SDMIRQ		S5PC1XX_IRQ_VIC2(30)
 #define IRQ_SDMFIQ		S5PC1XX_IRQ_VIC2(31)
 
+#define IRQ_TIMER(x)		(IRQ_SDMFIQ + 1 + (x))
+#define IRQ_TIMER0		IRQ_TIMER(0)
+#define IRQ_TIMER1		IRQ_TIMER(1)
+#define IRQ_TIMER2		IRQ_TIMER(2)
+#define IRQ_TIMER3		IRQ_TIMER(3)
+#define IRQ_TIMER4		IRQ_TIMER(4)
+
 /* External interrupt */
-#define S3C_IRQ_EINT_BASE	(IRQ_SDMFIQ + 1)
+#define S3C_IRQ_EINT_BASE	(IRQ_SDMFIQ + 6)
 
 #define S3C_EINT(x)		(S3C_IRQ_EINT_BASE + (x - 16))
 #define IRQ_EINT(x)		(x < 16 ? IRQ_EINT0 + x : S3C_EINT(x))
diff --git a/arch/arm/plat-s5pc1xx/include/plat/regs-clock.h b/arch/arm/plat-s5pc1xx/include/plat/regs-clock.h
index c5cc86e..24dec4e 100644
--- a/arch/arm/plat-s5pc1xx/include/plat/regs-clock.h
+++ b/arch/arm/plat-s5pc1xx/include/plat/regs-clock.h
@@ -61,73 +61,10 @@
 #define S5PC100_EPLL_MASK		0xffffffff
 #define S5PC100_EPLLVAL(_m, _p, _s)	((_m) << 16 | ((_p) << 8) | ((_s)))
 
-/* CLKSRC0 */
-#define S5PC100_CLKSRC0_APLL_MASK		(0x1<<0)
-#define S5PC100_CLKSRC0_APLL_SHIFT		(0)
-#define S5PC100_CLKSRC0_MPLL_MASK		(0x1<<4)
-#define S5PC100_CLKSRC0_MPLL_SHIFT		(4)
-#define S5PC100_CLKSRC0_EPLL_MASK		(0x1<<8)
-#define S5PC100_CLKSRC0_EPLL_SHIFT		(8)
-#define S5PC100_CLKSRC0_HPLL_MASK		(0x1<<12)
-#define S5PC100_CLKSRC0_HPLL_SHIFT		(12)
-#define S5PC100_CLKSRC0_AMMUX_MASK		(0x1<<16)
-#define S5PC100_CLKSRC0_AMMUX_SHIFT		(16)
-#define S5PC100_CLKSRC0_HREF_MASK		(0x1<<20)
-#define S5PC100_CLKSRC0_HREF_SHIFT		(20)
-#define S5PC100_CLKSRC0_ONENAND_MASK	(0x1<<24)
-#define S5PC100_CLKSRC0_ONENAND_SHIFT	(24)
-
-
-/* CLKSRC1 */
-#define S5PC100_CLKSRC1_UART_MASK		(0x1<<0)
-#define S5PC100_CLKSRC1_UART_SHIFT		(0)
-#define S5PC100_CLKSRC1_SPI0_MASK		(0x3<<4)
-#define S5PC100_CLKSRC1_SPI0_SHIFT		(4)
-#define S5PC100_CLKSRC1_SPI1_MASK		(0x3<<8)
-#define S5PC100_CLKSRC1_SPI1_SHIFT		(8)
-#define S5PC100_CLKSRC1_SPI2_MASK		(0x3<<12)
-#define S5PC100_CLKSRC1_SPI2_SHIFT		(12)
-#define S5PC100_CLKSRC1_IRDA_MASK		(0x3<<16)
-#define S5PC100_CLKSRC1_IRDA_SHIFT		(16)
-#define S5PC100_CLKSRC1_UHOST_MASK		(0x3<<20)
-#define S5PC100_CLKSRC1_UHOST_SHIFT		(20)
-#define S5PC100_CLKSRC1_CLK48M_MASK		(0x1<<24)
+/* CLKSRC0..CLKSRC3 -> mostly removed due to clksrc updates */
+#define S5PC100_CLKSRC1_CLK48M_MASK	(0x1<<24)
 #define S5PC100_CLKSRC1_CLK48M_SHIFT	(24)
 
-/* CLKSRC2 */
-#define S5PC100_CLKSRC2_MMC0_MASK		(0x3<<0)
-#define S5PC100_CLKSRC2_MMC0_SHIFT		(0)
-#define S5PC100_CLKSRC2_MMC1_MASK		(0x3<<4)
-#define S5PC100_CLKSRC2_MMC1_SHIFT		(4)
-#define S5PC100_CLKSRC2_MMC2_MASK		(0x3<<8)
-#define S5PC100_CLKSRC2_MMC2_SHIFT		(8)
-#define S5PC100_CLKSRC2_LCD_MASK		(0x3<<12)
-#define S5PC100_CLKSRC2_LCD_SHIFT		(12)
-#define S5PC100_CLKSRC2_FIMC0_MASK		(0x3<<16)
-#define S5PC100_CLKSRC2_FIMC0_SHIFT		(16)
-#define S5PC100_CLKSRC2_FIMC1_MASK		(0x3<<20)
-#define S5PC100_CLKSRC2_FIMC1_SHIFT		(20)
-#define S5PC100_CLKSRC2_FIMC2_MASK		(0x3<<24)
-#define S5PC100_CLKSRC2_FIMC2_SHIFT		(24)
-#define S5PC100_CLKSRC2_MIXER_MASK		(0x3<<28)
-#define S5PC100_CLKSRC2_MIXER_SHIFT		(28)
-
-/* CLKSRC3 */
-#define S5PC100_CLKSRC3_PWI_MASK		(0x3<<0)
-#define S5PC100_CLKSRC3_PWI_SHIFT		(0)
-#define S5PC100_CLKSRC3_HCLKD2_MASK		(0x1<<4)
-#define S5PC100_CLKSRC3_HCLKD2_SHIFT	(4)
-#define S5PC100_CLKSRC3_I2SD2_MASK		(0x3<<8)
-#define S5PC100_CLKSRC3_I2SD2_SHIFT		(8)
-#define S5PC100_CLKSRC3_AUDIO0_MASK		(0x7<<12)
-#define S5PC100_CLKSRC3_AUDIO0_SHIFT	(12)
-#define S5PC100_CLKSRC3_AUDIO1_MASK		(0x7<<16)
-#define S5PC100_CLKSRC3_AUDIO1_SHIFT	(16)
-#define S5PC100_CLKSRC3_AUDIO2_MASK		(0x7<<20)
-#define S5PC100_CLKSRC3_AUDIO2_SHIFT	(20)
-#define S5PC100_CLKSRC3_SPDIF_MASK		(0x3<<24)
-#define S5PC100_CLKSRC3_SPDIF_SHIFT		(24)
-
 /* CLKDIV0 */
 #define S5PC100_CLKDIV0_APLL_MASK		(0x1<<0)
 #define S5PC100_CLKDIV0_APLL_SHIFT		(0)
@@ -140,7 +77,7 @@
 #define S5PC100_CLKDIV0_SECSS_MASK		(0x7<<16)
 #define S5PC100_CLKDIV0_SECSS_SHIFT		(16)
 
-/* CLKDIV1 */
+/* CLKDIV1 (OneNAND clock only used in one place, removed) */
 #define S5PC100_CLKDIV1_APLL2_MASK		(0x7<<0)
 #define S5PC100_CLKDIV1_APLL2_SHIFT		(0)
 #define S5PC100_CLKDIV1_MPLL_MASK		(0x3<<4)
@@ -151,56 +88,12 @@
 #define S5PC100_CLKDIV1_D1_SHIFT		(12)
 #define S5PC100_CLKDIV1_PCLKD1_MASK		(0x7<<16)
 #define S5PC100_CLKDIV1_PCLKD1_SHIFT	(16)
-#define S5PC100_CLKDIV1_ONENAND_MASK	(0x3<<20)
-#define S5PC100_CLKDIV1_ONENAND_SHIFT	(20)
 #define S5PC100_CLKDIV1_CAM_MASK		(0x1F<<24)
 #define S5PC100_CLKDIV1_CAM_SHIFT		(24)
 
-/* CLKDIV2 */
-#define S5PC100_CLKDIV2_UART_MASK		(0x7<<0)
-#define S5PC100_CLKDIV2_UART_SHIFT		(0)
-#define S5PC100_CLKDIV2_SPI0_MASK		(0xf<<4)
-#define S5PC100_CLKDIV2_SPI0_SHIFT		(4)
-#define S5PC100_CLKDIV2_SPI1_MASK		(0xf<<8)
-#define S5PC100_CLKDIV2_SPI1_SHIFT		(8)
-#define S5PC100_CLKDIV2_SPI2_MASK		(0xf<<12)
-#define S5PC100_CLKDIV2_SPI2_SHIFT		(12)
-#define S5PC100_CLKDIV2_IRDA_MASK		(0xf<<16)
-#define S5PC100_CLKDIV2_IRDA_SHIFT		(16)
-#define S5PC100_CLKDIV2_UHOST_MASK		(0xf<<20)
-#define S5PC100_CLKDIV2_UHOST_SHIFT		(20)
-
-/* CLKDIV3 */
-#define S5PC100_CLKDIV3_MMC0_MASK		(0xf<<0)
-#define S5PC100_CLKDIV3_MMC0_SHIFT		(0)
-#define S5PC100_CLKDIV3_MMC1_MASK		(0xf<<4)
-#define S5PC100_CLKDIV3_MMC1_SHIFT		(4)
-#define S5PC100_CLKDIV3_MMC2_MASK		(0xf<<8)
-#define S5PC100_CLKDIV3_MMC2_SHIFT		(8)
-#define S5PC100_CLKDIV3_LCD_MASK		(0xf<<12)
-#define S5PC100_CLKDIV3_LCD_SHIFT		(12)
-#define S5PC100_CLKDIV3_FIMC0_MASK		(0xf<<16)
-#define S5PC100_CLKDIV3_FIMC0_SHIFT		(16)
-#define S5PC100_CLKDIV3_FIMC1_MASK		(0xf<<20)
-#define S5PC100_CLKDIV3_FIMC1_SHIFT		(20)
-#define S5PC100_CLKDIV3_FIMC2_MASK		(0xf<<24)
-#define S5PC100_CLKDIV3_FIMC2_SHIFT		(24)
-#define S5PC100_CLKDIV3_HDMI_MASK		(0xf<<28)
-#define S5PC100_CLKDIV3_HDMI_SHIFT		(28)
-
-/* CLKDIV4 */
-#define S5PC100_CLKDIV4_PWI_MASK		(0x7<<0)
-#define S5PC100_CLKDIV4_PWI_SHIFT		(0)
-#define S5PC100_CLKDIV4_HCLKD2_MASK		(0x7<<4)
-#define S5PC100_CLKDIV4_HCLKD2_SHIFT	(4)
-#define S5PC100_CLKDIV4_I2SD2_MASK		(0xf<<8)
-#define S5PC100_CLKDIV4_I2SD2_SHIFT		(8)
-#define S5PC100_CLKDIV4_AUDIO0_MASK		(0xf<<12)
-#define S5PC100_CLKDIV4_AUDIO0_SHIFT	(12)
-#define S5PC100_CLKDIV4_AUDIO1_MASK		(0xf<<16)
-#define S5PC100_CLKDIV4_AUDIO1_SHIFT	(16)
-#define S5PC100_CLKDIV4_AUDIO2_MASK		(0xf<<20)
-#define S5PC100_CLKDIV4_AUDIO2_SHIFT	(20)
+/* CLKDIV2 => removed in clksrc update */
+/* CLKDIV3 => removed in clksrc update, or not needed */
+/* CLKDIV4 => removed in clksrc update, or not needed */
 
 /* HCLKD0/PCLKD0 Clock Gate 0 Registers */
 #define S5PC100_CLKGATE_D00_INTC		(1<<0)
diff --git a/arch/arm/plat-s5pc1xx/irq.c b/arch/arm/plat-s5pc1xx/irq.c
index e44fd04..bfc5248 100644
--- a/arch/arm/plat-s5pc1xx/irq.c
+++ b/arch/arm/plat-s5pc1xx/irq.c
@@ -20,87 +20,14 @@
 #include <asm/hardware/vic.h>
 
 #include <mach/map.h>
-#include <plat/regs-timer.h>
+#include <plat/irq-vic-timer.h>
+#include <plat/irq-uart.h>
 #include <plat/cpu.h>
 
-/* Timer interrupt handling */
-
-static void s3c_irq_demux_timer(unsigned int base_irq, unsigned int sub_irq)
-{
-	generic_handle_irq(sub_irq);
-}
-
-static void s3c_irq_demux_timer0(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_timer(irq, IRQ_TIMER0);
-}
-
-static void s3c_irq_demux_timer1(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_timer(irq, IRQ_TIMER1);
-}
-
-static void s3c_irq_demux_timer2(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_timer(irq, IRQ_TIMER2);
-}
-
-static void s3c_irq_demux_timer3(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_timer(irq, IRQ_TIMER3);
-}
-
-static void s3c_irq_demux_timer4(unsigned int irq, struct irq_desc *desc)
-{
-	s3c_irq_demux_timer(irq, IRQ_TIMER4);
-}
-
-/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
-
-static void s3c_irq_timer_mask(unsigned int irq)
-{
-	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
-
-	reg &= 0x1f;  /* mask out pending interrupts */
-	reg &= ~(1 << (irq - IRQ_TIMER0));
-	__raw_writel(reg, S3C64XX_TINT_CSTAT);
-}
-
-static void s3c_irq_timer_unmask(unsigned int irq)
-{
-	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
-
-	reg &= 0x1f;  /* mask out pending interrupts */
-	reg |= 1 << (irq - IRQ_TIMER0);
-	__raw_writel(reg, S3C64XX_TINT_CSTAT);
-}
-
-static void s3c_irq_timer_ack(unsigned int irq)
-{
-	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
-
-	reg &= 0x1f;  /* mask out pending interrupts */
-	reg |= (1 << 5) << (irq - IRQ_TIMER0);
-	__raw_writel(reg, S3C64XX_TINT_CSTAT);
-}
-
-static struct irq_chip s3c_irq_timer = {
-	.name		= "s3c-timer",
-	.mask		= s3c_irq_timer_mask,
-	.unmask		= s3c_irq_timer_unmask,
-	.ack		= s3c_irq_timer_ack,
-};
-
-struct uart_irq {
-	void __iomem	*regs;
-	unsigned int	 base_irq;
-	unsigned int	 parent_irq;
-};
-
 /* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
  * are consecutive when looking up the interrupt in the demux routines.
  */
-static struct uart_irq uart_irqs[] = {
+static struct s3c_uart_irq uart_irqs[] = {
 	[0] = {
 		.regs		= (void *)S3C_VA_UART0,
 		.base_irq	= IRQ_S3CUART_BASE0,
@@ -123,113 +50,9 @@
 	},
 };
 
-static inline void __iomem *s3c_irq_uart_base(unsigned int irq)
-{
-	struct uart_irq *uirq = get_irq_chip_data(irq);
-	return uirq->regs;
-}
-
-static inline unsigned int s3c_irq_uart_bit(unsigned int irq)
-{
-	return irq & 3;
-}
-
-/* UART interrupt registers, not worth adding to seperate include header */
-#define S3C64XX_UINTP	0x30
-#define S3C64XX_UINTSP	0x34
-#define S3C64XX_UINTM	0x38
-
-static void s3c_irq_uart_mask(unsigned int irq)
-{
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
-	u32 reg;
-
-	reg = __raw_readl(regs + S3C64XX_UINTM);
-	reg |= (1 << bit);
-	__raw_writel(reg, regs + S3C64XX_UINTM);
-}
-
-static void s3c_irq_uart_maskack(unsigned int irq)
-{
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
-	u32 reg;
-
-	reg = __raw_readl(regs + S3C64XX_UINTM);
-	reg |= (1 << bit);
-	__raw_writel(reg, regs + S3C64XX_UINTM);
-	__raw_writel(1 << bit, regs + S3C64XX_UINTP);
-}
-
-static void s3c_irq_uart_unmask(unsigned int irq)
-{
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
-	u32 reg;
-
-	reg = __raw_readl(regs + S3C64XX_UINTM);
-	reg &= ~(1 << bit);
-	__raw_writel(reg, regs + S3C64XX_UINTM);
-}
-
-static void s3c_irq_uart_ack(unsigned int irq)
-{
-	void __iomem *regs = s3c_irq_uart_base(irq);
-	unsigned int bit = s3c_irq_uart_bit(irq);
-
-	__raw_writel(1 << bit, regs + S3C64XX_UINTP);
-}
-
-static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
-{
-	struct uart_irq *uirq = &uart_irqs[irq - IRQ_UART0];
-	u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
-	int base = uirq->base_irq;
-
-	if (pend & (1 << 0))
-		generic_handle_irq(base);
-	if (pend & (1 << 1))
-		generic_handle_irq(base + 1);
-	if (pend & (1 << 2))
-		generic_handle_irq(base + 2);
-	if (pend & (1 << 3))
-		generic_handle_irq(base + 3);
-}
-
-static struct irq_chip s3c_irq_uart = {
-	.name		= "s3c-uart",
-	.mask		= s3c_irq_uart_mask,
-	.unmask		= s3c_irq_uart_unmask,
-	.mask_ack	= s3c_irq_uart_maskack,
-	.ack		= s3c_irq_uart_ack,
-};
-
-static void __init s5pc1xx_uart_irq(struct uart_irq *uirq)
-{
-	void __iomem *reg_base = uirq->regs;
-	unsigned int irq;
-	int offs;
-
-	/* mask all interrupts at the start. */
-	__raw_writel(0xf, reg_base + S3C64XX_UINTM);
-
-	for (offs = 0; offs < 3; offs++) {
-		irq = uirq->base_irq + offs;
-
-		set_irq_chip(irq, &s3c_irq_uart);
-		set_irq_chip_data(irq, uirq);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-	set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
-}
-
 void __init s5pc1xx_init_irq(u32 *vic_valid, int num)
 {
 	int i;
-	int uart, irq;
 
 	printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
 
@@ -240,20 +63,13 @@
 
 	/* add the timer sub-irqs */
 
-	set_irq_chained_handler(IRQ_TIMER0, s3c_irq_demux_timer0);
-	set_irq_chained_handler(IRQ_TIMER1, s3c_irq_demux_timer1);
-	set_irq_chained_handler(IRQ_TIMER2, s3c_irq_demux_timer2);
-	set_irq_chained_handler(IRQ_TIMER3, s3c_irq_demux_timer3);
-	set_irq_chained_handler(IRQ_TIMER4, s3c_irq_demux_timer4);
+	s3c_init_vic_timer_irq(IRQ_TIMER0_VIC, IRQ_TIMER0);
+	s3c_init_vic_timer_irq(IRQ_TIMER1_VIC, IRQ_TIMER1);
+	s3c_init_vic_timer_irq(IRQ_TIMER2_VIC, IRQ_TIMER2);
+	s3c_init_vic_timer_irq(IRQ_TIMER3_VIC, IRQ_TIMER3);
+	s3c_init_vic_timer_irq(IRQ_TIMER4_VIC, IRQ_TIMER4);
 
-	for (irq = IRQ_TIMER0; irq <= IRQ_TIMER4; irq++) {
-		set_irq_chip(irq, &s3c_irq_timer);
-		set_irq_handler(irq, handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-
-	for (uart = 0; uart < ARRAY_SIZE(uart_irqs); uart++)
-		s5pc1xx_uart_irq(&uart_irqs[uart]);
+	s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
 }
 
 
diff --git a/arch/arm/plat-s5pc1xx/s5pc100-clock.c b/arch/arm/plat-s5pc1xx/s5pc100-clock.c
index b436d44..2bf6c57 100644
--- a/arch/arm/plat-s5pc1xx/s5pc100-clock.c
+++ b/arch/arm/plat-s5pc1xx/s5pc100-clock.c
@@ -29,6 +29,7 @@
 
 #include <plat/regs-clock.h>
 #include <plat/clock.h>
+#include <plat/clock-clksrc.h>
 #include <plat/cpu.h>
 #include <plat/pll.h>
 #include <plat/devs.h>
@@ -51,23 +52,6 @@
 #define clk_fout_mpll	clk_mpll
 #define clk_vclk_54m	clk_54m
 
-struct clk_sources {
-	unsigned int	nr_sources;
-	struct clk	**sources;
-};
-
-struct clksrc_clk {
-	struct clk		clk;
-	unsigned int		mask;
-	unsigned int		shift;
-
-	struct clk_sources	*sources;
-
-	unsigned int		divider_shift;
-	void __iomem		*reg_divider;
-	void __iomem		*reg_source;
-};
-
 /* APLL */
 static struct clk clk_fout_apll = {
 	.name		= "fout_apll",
@@ -80,7 +64,7 @@
 	[1] = &clk_fout_apll,
 };
 
-static struct clk_sources clk_src_apll = {
+static struct clksrc_sources clk_src_apll = {
 	.sources	= clk_src_apll_list,
 	.nr_sources	= ARRAY_SIZE(clk_src_apll_list),
 };
@@ -90,10 +74,8 @@
 		.name		= "mout_apll",
 		.id		= -1,
 	},
-	.shift		= S5PC100_CLKSRC0_APLL_SHIFT,
-	.mask		= S5PC100_CLKSRC0_APLL_MASK,
 	.sources	= &clk_src_apll,
-	.reg_source	= S5PC100_CLKSRC0,
+	.reg_src = { .reg = S5PC100_CLKSRC0, .shift = 0, .size = 1, },
 };
 
 static unsigned long s5pc100_clk_dout_apll_get_rate(struct clk *clk)
@@ -111,7 +93,9 @@
 	.name		= "dout_apll",
 	.id		= -1,
 	.parent		= &clk_mout_apll.clk,
-	.get_rate	= s5pc100_clk_dout_apll_get_rate,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s5pc100_clk_dout_apll_get_rate,
+	},
 };
 
 static unsigned long s5pc100_clk_arm_get_rate(struct clk *clk)
@@ -165,9 +149,11 @@
 	.name		= "armclk",
 	.id		= -1,
 	.parent		= &clk_dout_apll,
-	.get_rate	= s5pc100_clk_arm_get_rate,
-	.set_rate	= s5pc100_clk_arm_set_rate,
-	.round_rate	= s5pc100_clk_arm_round_rate,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s5pc100_clk_arm_get_rate,
+		.set_rate	= s5pc100_clk_arm_set_rate,
+		.round_rate	= s5pc100_clk_arm_round_rate,
+	},
 };
 
 static unsigned long s5pc100_clk_dout_d0_bus_get_rate(struct clk *clk)
@@ -185,7 +171,9 @@
 	.name		= "dout_d0_bus",
 	.id		= -1,
 	.parent		= &clk_arm,
-	.get_rate	= s5pc100_clk_dout_d0_bus_get_rate,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s5pc100_clk_dout_d0_bus_get_rate,
+	},
 };
 
 static unsigned long s5pc100_clk_dout_pclkd0_get_rate(struct clk *clk)
@@ -203,7 +191,9 @@
 	.name		= "dout_pclkd0",
 	.id		= -1,
 	.parent		= &clk_dout_d0_bus,
-	.get_rate	= s5pc100_clk_dout_pclkd0_get_rate,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s5pc100_clk_dout_pclkd0_get_rate,
+	},
 };
 
 static unsigned long s5pc100_clk_dout_apll2_get_rate(struct clk *clk)
@@ -221,7 +211,9 @@
 	.name		= "dout_apll2",
 	.id		= -1,
 	.parent		= &clk_mout_apll.clk,
-	.get_rate	= s5pc100_clk_dout_apll2_get_rate,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s5pc100_clk_dout_apll2_get_rate,
+	},
 };
 
 /* MPLL */
@@ -230,7 +222,7 @@
 	[1] = &clk_fout_mpll,
 };
 
-static struct clk_sources clk_src_mpll = {
+static struct clksrc_sources clk_src_mpll = {
 	.sources	= clk_src_mpll_list,
 	.nr_sources	= ARRAY_SIZE(clk_src_mpll_list),
 };
@@ -240,10 +232,8 @@
 		.name		= "mout_mpll",
 		.id		= -1,
 	},
-	.shift		= S5PC100_CLKSRC0_MPLL_SHIFT,
-	.mask		= S5PC100_CLKSRC0_MPLL_MASK,
 	.sources	= &clk_src_mpll,
-	.reg_source	= S5PC100_CLKSRC0,
+	.reg_src = { .reg = S5PC100_CLKSRC0, .shift = 4, .size = 1, },
 };
 
 static struct clk *clkset_am_list[] = {
@@ -251,7 +241,7 @@
 	[1] = &clk_dout_apll2,
 };
 
-static struct clk_sources clk_src_am = {
+static struct clksrc_sources clk_src_am = {
 	.sources	= clkset_am_list,
 	.nr_sources	= ARRAY_SIZE(clkset_am_list),
 };
@@ -261,10 +251,8 @@
 		.name		= "mout_am",
 		.id		= -1,
 	},
-	.shift		= S5PC100_CLKSRC0_AMMUX_SHIFT,
-	.mask		= S5PC100_CLKSRC0_AMMUX_MASK,
 	.sources	= &clk_src_am,
-	.reg_source	= S5PC100_CLKSRC0,
+	.reg_src = { .reg = S5PC100_CLKSRC0, .shift = 16, .size = 1, },
 };
 
 static unsigned long s5pc100_clk_dout_d1_bus_get_rate(struct clk *clk)
@@ -284,7 +272,9 @@
 	.name		= "dout_d1_bus",
 	.id		= -1,
 	.parent		= &clk_mout_am.clk,
-	.get_rate	= s5pc100_clk_dout_d1_bus_get_rate,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s5pc100_clk_dout_d1_bus_get_rate,
+	},
 };
 
 static struct clk *clkset_onenand_list[] = {
@@ -292,7 +282,7 @@
 	[1] = &clk_dout_d1_bus,
 };
 
-static struct clk_sources clk_src_onenand = {
+static struct clksrc_sources clk_src_onenand = {
 	.sources	= clkset_onenand_list,
 	.nr_sources	= ARRAY_SIZE(clkset_onenand_list),
 };
@@ -302,10 +292,8 @@
 		.name		= "mout_onenand",
 		.id		= -1,
 	},
-	.shift		= S5PC100_CLKSRC0_ONENAND_SHIFT,
-	.mask		= S5PC100_CLKSRC0_ONENAND_MASK,
 	.sources	= &clk_src_onenand,
-	.reg_source	= S5PC100_CLKSRC0,
+	.reg_src = { .reg = S5PC100_CLKSRC0, .shift = 24, .size = 1, },
 };
 
 static unsigned long s5pc100_clk_dout_pclkd1_get_rate(struct clk *clk)
@@ -325,7 +313,9 @@
 	.name		= "dout_pclkd1",
 	.id		= -1,
 	.parent		= &clk_dout_d1_bus,
-	.get_rate	= s5pc100_clk_dout_pclkd1_get_rate,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s5pc100_clk_dout_pclkd1_get_rate,
+	},
 };
 
 static unsigned long s5pc100_clk_dout_mpll2_get_rate(struct clk *clk)
@@ -345,7 +335,9 @@
 	.name		= "dout_mpll2",
 	.id		= -1,
 	.parent		= &clk_mout_am.clk,
-	.get_rate	= s5pc100_clk_dout_mpll2_get_rate,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s5pc100_clk_dout_mpll2_get_rate,
+	},
 };
 
 static unsigned long s5pc100_clk_dout_cam_get_rate(struct clk *clk)
@@ -365,7 +357,9 @@
 	.name		= "dout_cam",
 	.id		= -1,
 	.parent		= &clk_dout_mpll2,
-	.get_rate	= s5pc100_clk_dout_cam_get_rate,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s5pc100_clk_dout_cam_get_rate,
+	},
 };
 
 static unsigned long s5pc100_clk_dout_mpll_get_rate(struct clk *clk)
@@ -385,7 +379,9 @@
 	.name		= "dout_mpll",
 	.id		= -1,
 	.parent		= &clk_mout_am.clk,
-	.get_rate	= s5pc100_clk_dout_mpll_get_rate,
+	.ops		= &(struct clk_ops) {
+		.get_rate	= s5pc100_clk_dout_mpll_get_rate,
+	},
 };
 
 /* EPLL */
@@ -399,7 +395,7 @@
 	[1] = &clk_fout_epll,
 };
 
-static struct clk_sources clk_src_epll = {
+static struct clksrc_sources clk_src_epll = {
 	.sources	= clk_src_epll_list,
 	.nr_sources	= ARRAY_SIZE(clk_src_epll_list),
 };
@@ -409,10 +405,8 @@
 		.name		= "mout_epll",
 		.id		= -1,
 	},
-	.shift		= S5PC100_CLKSRC0_EPLL_SHIFT,
-	.mask		= S5PC100_CLKSRC0_EPLL_MASK,
-	.sources	= &clk_src_epll,
-	.reg_source	= S5PC100_CLKSRC0,
+	.sources = &clk_src_epll,
+	.reg_src = { .reg = S5PC100_CLKSRC0, .shift = 8, .size = 1, },
 };
 
 /* HPLL */
@@ -426,7 +420,7 @@
 	[1] = &clk_fout_hpll,
 };
 
-static struct clk_sources clk_src_hpll = {
+static struct clksrc_sources clk_src_hpll = {
 	.sources	= clk_src_hpll_list,
 	.nr_sources	= ARRAY_SIZE(clk_src_hpll_list),
 };
@@ -436,10 +430,8 @@
 		.name		= "mout_hpll",
 		.id		= -1,
 	},
-	.shift		= S5PC100_CLKSRC0_HPLL_SHIFT,
-	.mask		= S5PC100_CLKSRC0_HPLL_MASK,
-	.sources	= &clk_src_hpll,
-	.reg_source	= S5PC100_CLKSRC0,
+	.sources = &clk_src_hpll,
+	.reg_src = { .reg = S5PC100_CLKSRC0, .shift = 12, .size = 1, },
 };
 
 /* Peripherals */
@@ -454,190 +446,6 @@
  * have a common parent divisor so are not included here.
  */
 
-static inline struct clksrc_clk *to_clksrc(struct clk *clk)
-{
-	return container_of(clk, struct clksrc_clk, clk);
-}
-
-static unsigned long s5pc100_getrate_clksrc(struct clk *clk)
-{
-	struct clksrc_clk *sclk = to_clksrc(clk);
-	unsigned long rate = clk_get_rate(clk->parent);
-	u32 clkdiv = __raw_readl(sclk->reg_divider);
-
-	clkdiv >>= sclk->divider_shift;
-	clkdiv &= 0xf;
-	clkdiv++;
-
-	rate /= clkdiv;
-	return rate;
-}
-
-static int s5pc100_setrate_clksrc(struct clk *clk, unsigned long rate)
-{
-	struct clksrc_clk *sclk = to_clksrc(clk);
-	void __iomem *reg = sclk->reg_divider;
-	unsigned int div;
-	u32 val;
-
-	rate = clk_round_rate(clk, rate);
-	div = clk_get_rate(clk->parent) / rate;
-	if (div > 16)
-		return -EINVAL;
-
-	val = __raw_readl(reg);
-	val &= ~(0xf << sclk->divider_shift);
-	val |= (div - 1) << sclk->divider_shift;
-	__raw_writel(val, reg);
-
-	return 0;
-}
-
-static int s5pc100_setparent_clksrc(struct clk *clk, struct clk *parent)
-{
-	struct clksrc_clk *sclk = to_clksrc(clk);
-	struct clk_sources *srcs = sclk->sources;
-	u32 clksrc = __raw_readl(sclk->reg_source);
-	int src_nr = -1;
-	int ptr;
-
-	for (ptr = 0; ptr < srcs->nr_sources; ptr++)
-		if (srcs->sources[ptr] == parent) {
-			src_nr = ptr;
-			break;
-		}
-
-	if (src_nr >= 0) {
-		clksrc &= ~sclk->mask;
-		clksrc |= src_nr << sclk->shift;
-
-		__raw_writel(clksrc, sclk->reg_source);
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static unsigned long s5pc100_roundrate_clksrc(struct clk *clk,
-					      unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-	int div;
-
-	if (rate > parent_rate)
-		rate = parent_rate;
-	else {
-		div = rate / parent_rate;
-
-		if (div == 0)
-			div = 1;
-		if (div > 16)
-			div = 16;
-
-		rate = parent_rate / div;
-	}
-
-	return rate;
-}
-
-static struct clk *clkset_spi_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll2,
-	&clk_fin_epll,
-	&clk_mout_hpll.clk,
-};
-
-static struct clk_sources clkset_spi = {
-	.sources	= clkset_spi_list,
-	.nr_sources	= ARRAY_SIZE(clkset_spi_list),
-};
-
-static struct clksrc_clk clk_spi0 = {
-	.clk	= {
-		.name		= "spi_bus",
-		.id		= 0,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK0_SPI0,
-		.enable		= s5pc100_sclk0_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC1_SPI0_SHIFT,
-	.mask		= S5PC100_CLKSRC1_SPI0_MASK,
-	.sources	= &clkset_spi,
-	.divider_shift	= S5PC100_CLKDIV2_SPI0_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV2,
-	.reg_source	= S5PC100_CLKSRC1,
-};
-
-static struct clksrc_clk clk_spi1 = {
-	.clk	= {
-		.name		= "spi_bus",
-		.id		= 1,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK0_SPI1,
-		.enable		= s5pc100_sclk0_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC1_SPI1_SHIFT,
-	.mask		= S5PC100_CLKSRC1_SPI1_MASK,
-	.sources	= &clkset_spi,
-	.divider_shift	= S5PC100_CLKDIV2_SPI1_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV2,
-	.reg_source	= S5PC100_CLKSRC1,
-};
-
-static struct clksrc_clk clk_spi2 = {
-	.clk	= {
-		.name		= "spi_bus",
-		.id		= 2,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK0_SPI2,
-		.enable		= s5pc100_sclk0_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC1_SPI2_SHIFT,
-	.mask		= S5PC100_CLKSRC1_SPI2_MASK,
-	.sources	= &clkset_spi,
-	.divider_shift	= S5PC100_CLKDIV2_SPI2_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV2,
-	.reg_source	= S5PC100_CLKSRC1,
-};
-
-static struct clk *clkset_uart_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll,
-};
-
-static struct clk_sources clkset_uart = {
-	.sources	= clkset_uart_list,
-	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clksrc_clk clk_uart_uclk1 = {
-	.clk	= {
-		.name		= "uclk1",
-		.id		= -1,
-		.ctrlbit        = S5PC100_CLKGATE_SCLK0_UART,
-		.enable		= s5pc100_sclk0_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC1_UART_SHIFT,
-	.mask		= S5PC100_CLKSRC1_UART_MASK,
-	.sources	= &clkset_uart,
-	.divider_shift	= S5PC100_CLKDIV2_UART_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV2,
-	.reg_source	= S5PC100_CLKSRC1,
-};
-
 static struct clk clk_iis_cd0 = {
 	.name		= "iis_cdclk0",
 	.id		= -1,
@@ -672,28 +480,31 @@
 	&clk_mout_hpll.clk,
 };
 
-static struct clk_sources clkset_audio0 = {
+static struct clksrc_sources clkset_audio0 = {
 	.sources	= clkset_audio0_list,
 	.nr_sources	= ARRAY_SIZE(clkset_audio0_list),
 };
 
-static struct clksrc_clk clk_audio0 = {
-	.clk	= {
-		.name		= "audio-bus",
-		.id		= 0,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK1_AUDIO0,
-		.enable		= s5pc100_sclk1_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC3_AUDIO0_SHIFT,
-	.mask		= S5PC100_CLKSRC3_AUDIO0_MASK,
-	.sources	= &clkset_audio0,
-	.divider_shift	= S5PC100_CLKDIV4_AUDIO0_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV4,
-	.reg_source	= S5PC100_CLKSRC3,
+static struct clk *clkset_spi_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll2,
+	&clk_fin_epll,
+	&clk_mout_hpll.clk,
+};
+
+static struct clksrc_sources clkset_spi = {
+	.sources	= clkset_spi_list,
+	.nr_sources	= ARRAY_SIZE(clkset_spi_list),
+};
+
+static struct clk *clkset_uart_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll,
+};
+
+static struct clksrc_sources clkset_uart = {
+	.sources	= clkset_uart_list,
+	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
 };
 
 static struct clk *clkset_audio1_list[] = {
@@ -705,30 +516,11 @@
 	&clk_mout_hpll.clk,
 };
 
-static struct clk_sources clkset_audio1 = {
+static struct clksrc_sources clkset_audio1 = {
 	.sources	= clkset_audio1_list,
 	.nr_sources	= ARRAY_SIZE(clkset_audio1_list),
 };
 
-static struct clksrc_clk clk_audio1 = {
-	.clk	= {
-		.name		= "audio-bus",
-		.id		= 1,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK1_AUDIO1,
-		.enable		= s5pc100_sclk1_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC3_AUDIO1_SHIFT,
-	.mask		= S5PC100_CLKSRC3_AUDIO1_MASK,
-	.sources	= &clkset_audio1,
-	.divider_shift	= S5PC100_CLKDIV4_AUDIO1_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV4,
-	.reg_source	= S5PC100_CLKSRC3,
-};
-
 static struct clk *clkset_audio2_list[] = {
 	&clk_mout_epll.clk,
 	&clk_dout_mpll,
@@ -737,52 +529,56 @@
 	&clk_mout_hpll.clk,
 };
 
-static struct clk_sources clkset_audio2 = {
+static struct clksrc_sources clkset_audio2 = {
 	.sources	= clkset_audio2_list,
 	.nr_sources	= ARRAY_SIZE(clkset_audio2_list),
 };
 
-static struct clksrc_clk clk_audio2 = {
-	.clk	= {
-		.name		= "audio-bus",
-		.id		= 2,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK1_AUDIO2,
-		.enable		= s5pc100_sclk1_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
+static struct clksrc_clk clksrc_audio[] = {
+	{
+		.clk	= {
+			.name		= "audio-bus",
+			.id		= 0,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK1_AUDIO0,
+			.enable		= s5pc100_sclk1_ctrl,
+		},
+		.sources = &clkset_audio0,
+		.reg_div = { .reg = S5PC100_CLKDIV4, .shift = 12, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC3, .shift = 12, .size = 3, },
+	}, {
+		.clk	= {
+			.name		= "audio-bus",
+			.id		= 1,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK1_AUDIO1,
+			.enable		= s5pc100_sclk1_ctrl,
+		},
+		.sources = &clkset_audio1,
+		.reg_div = { .reg = S5PC100_CLKDIV4, .shift = 16, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC3, .shift = 16, .size = 3, },
+	}, {
+		.clk	= {
+			.name		= "audio-bus",
+			.id		= 2,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK1_AUDIO2,
+			.enable		= s5pc100_sclk1_ctrl,
+		},
+		.sources = &clkset_audio2,
+		.reg_div = { .reg = S5PC100_CLKDIV4, .shift = 20, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC3, .shift = 20, .size = 3, },
 	},
-	.shift		= S5PC100_CLKSRC3_AUDIO2_SHIFT,
-	.mask		= S5PC100_CLKSRC3_AUDIO2_MASK,
-	.sources	= &clkset_audio2,
-	.divider_shift	= S5PC100_CLKDIV4_AUDIO2_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV4,
-	.reg_source	= S5PC100_CLKSRC3,
 };
 
 static struct clk *clkset_spdif_list[] = {
-	&clk_audio0.clk,
-	&clk_audio1.clk,
-	&clk_audio2.clk,
+	&clksrc_audio[0].clk,
+	&clksrc_audio[1].clk,
+	&clksrc_audio[2].clk,
 };
 
-static struct clk_sources clkset_spdif = {
+static struct clksrc_sources clkset_spdif = {
 	.sources	= clkset_spdif_list,
 	.nr_sources	= ARRAY_SIZE(clkset_spdif_list),
 };
 
-static struct clksrc_clk clk_spdif = {
-	.clk	= {
-		.name		= "spdif",
-		.id		= -1,
-	},
-	.shift		= S5PC100_CLKSRC3_SPDIF_SHIFT,
-	.mask		= S5PC100_CLKSRC3_SPDIF_MASK,
-	.sources	= &clkset_spdif,
-	.reg_source	= S5PC100_CLKSRC3,
-};
-
 static struct clk *clkset_lcd_fimc_list[] = {
 	&clk_mout_epll.clk,
 	&clk_dout_mpll,
@@ -790,87 +586,11 @@
 	&clk_vclk_54m,
 };
 
-static struct clk_sources clkset_lcd_fimc = {
+static struct clksrc_sources clkset_lcd_fimc = {
 	.sources	= clkset_lcd_fimc_list,
 	.nr_sources	= ARRAY_SIZE(clkset_lcd_fimc_list),
 };
 
-static struct clksrc_clk clk_lcd = {
-	.clk	= {
-		.name		= "lcd",
-		.id		= -1,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK1_LCD,
-		.enable		= s5pc100_sclk1_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC2_LCD_SHIFT,
-	.mask		= S5PC100_CLKSRC2_LCD_MASK,
-	.sources	= &clkset_lcd_fimc,
-	.divider_shift	= S5PC100_CLKDIV3_LCD_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV3,
-	.reg_source	= S5PC100_CLKSRC2,
-};
-
-static struct clksrc_clk clk_fimc0 = {
-	.clk	= {
-		.name		= "fimc",
-		.id		= 0,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK1_FIMC0,
-		.enable		= s5pc100_sclk1_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC2_FIMC0_SHIFT,
-	.mask		= S5PC100_CLKSRC2_FIMC0_MASK,
-	.sources	= &clkset_lcd_fimc,
-	.divider_shift	= S5PC100_CLKDIV3_FIMC0_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV3,
-	.reg_source	= S5PC100_CLKSRC2,
-};
-
-static struct clksrc_clk clk_fimc1 = {
-	.clk	= {
-		.name		= "fimc",
-		.id		= 1,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK1_FIMC1,
-		.enable		= s5pc100_sclk1_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC2_FIMC1_SHIFT,
-	.mask		= S5PC100_CLKSRC2_FIMC1_MASK,
-	.sources	= &clkset_lcd_fimc,
-	.divider_shift	= S5PC100_CLKDIV3_FIMC1_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV3,
-	.reg_source	= S5PC100_CLKSRC2,
-};
-
-static struct clksrc_clk clk_fimc2 = {
-	.clk	= {
-		.name		= "fimc",
-		.id		= 2,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK1_FIMC2,
-		.enable		= s5pc100_sclk1_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC2_FIMC2_SHIFT,
-	.mask		= S5PC100_CLKSRC2_FIMC2_MASK,
-	.sources	= &clkset_lcd_fimc,
-	.divider_shift	= S5PC100_CLKDIV3_FIMC2_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV3,
-	.reg_source	= S5PC100_CLKSRC2,
-};
-
 static struct clk *clkset_mmc_list[] = {
 	&clk_mout_epll.clk,
 	&clk_dout_mpll,
@@ -878,69 +598,11 @@
 	&clk_mout_hpll.clk ,
 };
 
-static struct clk_sources clkset_mmc = {
+static struct clksrc_sources clkset_mmc = {
 	.sources	= clkset_mmc_list,
 	.nr_sources	= ARRAY_SIZE(clkset_mmc_list),
 };
 
-static struct clksrc_clk clk_mmc0 = {
-	.clk	= {
-		.name		= "mmc_bus",
-		.id		= 0,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK0_MMC0,
-		.enable		= s5pc100_sclk0_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC2_MMC0_SHIFT,
-	.mask		= S5PC100_CLKSRC2_MMC0_MASK,
-	.sources	= &clkset_mmc,
-	.divider_shift	= S5PC100_CLKDIV3_MMC0_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV3,
-	.reg_source	= S5PC100_CLKSRC2,
-};
-
-static struct clksrc_clk clk_mmc1 = {
-	.clk	= {
-		.name		= "mmc_bus",
-		.id		= 1,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK0_MMC1,
-		.enable		= s5pc100_sclk0_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC2_MMC1_SHIFT,
-	.mask		= S5PC100_CLKSRC2_MMC1_MASK,
-	.sources	= &clkset_mmc,
-	.divider_shift	= S5PC100_CLKDIV3_MMC1_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV3,
-	.reg_source	= S5PC100_CLKSRC2,
-};
-
-static struct clksrc_clk clk_mmc2 = {
-	.clk	= {
-		.name		= "mmc_bus",
-		.id		= 2,
-		.ctrlbit	= S5PC100_CLKGATE_SCLK0_MMC2,
-		.enable		= s5pc100_sclk0_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC2_MMC2_SHIFT,
-	.mask		= S5PC100_CLKSRC2_MMC2_MASK,
-	.sources	= &clkset_mmc,
-	.divider_shift	= S5PC100_CLKDIV3_MMC2_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV3,
-	.reg_source	= S5PC100_CLKSRC2,
-};
-
-
 static struct clk *clkset_usbhost_list[] = {
 	&clk_mout_epll.clk,
 	&clk_dout_mpll,
@@ -948,28 +610,141 @@
 	&clk_48m,
 };
 
-static struct clk_sources clkset_usbhost = {
+static struct clksrc_sources clkset_usbhost = {
 	.sources	= clkset_usbhost_list,
 	.nr_sources	= ARRAY_SIZE(clkset_usbhost_list),
 };
 
-static struct clksrc_clk clk_usbhost = {
-	.clk	= {
-		.name		= "usbhost",
-		.id		= -1,
-		.ctrlbit        = S5PC100_CLKGATE_SCLK0_USBHOST,
-		.enable		= s5pc100_sclk0_ctrl,
-		.set_parent	= s5pc100_setparent_clksrc,
-		.get_rate	= s5pc100_getrate_clksrc,
-		.set_rate	= s5pc100_setrate_clksrc,
-		.round_rate	= s5pc100_roundrate_clksrc,
-	},
-	.shift		= S5PC100_CLKSRC1_UHOST_SHIFT,
-	.mask		= S5PC100_CLKSRC1_UHOST_MASK,
-	.sources	= &clkset_usbhost,
-	.divider_shift	= S5PC100_CLKDIV2_UHOST_SHIFT,
-	.reg_divider	= S5PC100_CLKDIV2,
-	.reg_source	= S5PC100_CLKSRC1,
+static struct clksrc_clk clksrc_clks[] = {
+	{
+		.clk	= {
+			.name		= "spi_bus",
+			.id		= 0,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK0_SPI0,
+			.enable		= s5pc100_sclk0_ctrl,
+
+		},
+		.sources = &clkset_spi,
+		.reg_div = { .reg = S5PC100_CLKDIV2, .shift = 4, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC1, .shift = 4, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "spi_bus",
+			.id		= 1,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK0_SPI1,
+			.enable		= s5pc100_sclk0_ctrl,
+		},
+		.sources = &clkset_spi,
+		.reg_div = { .reg = S5PC100_CLKDIV2, .shift = 8, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC1, .shift = 8, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "spi_bus",
+			.id		= 2,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK0_SPI2,
+			.enable		= s5pc100_sclk0_ctrl,
+		},
+		.sources = &clkset_spi,
+		.reg_div = { .reg = S5PC100_CLKDIV2, .shift = 12, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC1, .shift = 12, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "uclk1",
+			.id		= -1,
+			.ctrlbit        = S5PC100_CLKGATE_SCLK0_UART,
+			.enable		= s5pc100_sclk0_ctrl,
+		},
+		.sources = &clkset_uart,
+		.reg_div = { .reg = S5PC100_CLKDIV2, .shift = 0, .size = 3, },
+		.reg_src = { .reg = S5PC100_CLKSRC1, .shift = 0, .size = 1, },
+	}, {
+		.clk	= {
+			.name		= "spdif",
+			.id		= -1,
+		},
+		.sources	= &clkset_spdif,
+		.reg_src = { .reg = S5PC100_CLKSRC3, .shift = 24, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "lcd",
+			.id		= -1,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK1_LCD,
+			.enable		= s5pc100_sclk1_ctrl,
+		},
+		.sources = &clkset_lcd_fimc,
+		.reg_div = { .reg = S5PC100_CLKDIV3, .shift = 12, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC2, .shift = 12, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "fimc",
+			.id		= 0,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK1_FIMC0,
+			.enable		= s5pc100_sclk1_ctrl,
+		},
+		.sources = &clkset_lcd_fimc,
+		.reg_div = { .reg = S5PC100_CLKDIV3, .shift = 16, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC2, .shift = 16, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "fimc",
+			.id		= 1,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK1_FIMC1,
+			.enable		= s5pc100_sclk1_ctrl,
+		},
+		.sources	= &clkset_lcd_fimc,
+		.reg_div = { .reg = S5PC100_CLKDIV3, .shift = 20, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC2, .shift = 20, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "fimc",
+			.id		= 2,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK1_FIMC2,
+			.enable		= s5pc100_sclk1_ctrl,
+		},
+		.sources = &clkset_lcd_fimc,
+		.reg_div = { .reg = S5PC100_CLKDIV3, .shift = 24, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC2, .shift = 24, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 0,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK0_MMC0,
+			.enable		= s5pc100_sclk0_ctrl,
+		},
+		.sources = &clkset_mmc,
+		.reg_div = { .reg = S5PC100_CLKDIV3, .shift = 0, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC2, .shift = 0, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 1,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK0_MMC1,
+			.enable		= s5pc100_sclk0_ctrl,
+		},
+		.sources = &clkset_mmc,
+		.reg_div = { .reg = S5PC100_CLKDIV3, .shift = 4, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC2, .shift = 4, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "mmc_bus",
+			.id		= 2,
+			.ctrlbit	= S5PC100_CLKGATE_SCLK0_MMC2,
+			.enable		= s5pc100_sclk0_ctrl,
+		},
+		.sources	= &clkset_mmc,
+		.reg_div = { .reg = S5PC100_CLKDIV3, .shift = 8, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC2, .shift = 8, .size = 2, },
+	}, {
+		.clk	= {
+			.name		= "usbhost",
+			.id		= -1,
+			.ctrlbit        = S5PC100_CLKGATE_SCLK0_USBHOST,
+			.enable		= s5pc100_sclk0_ctrl,
+		},
+		.sources = &clkset_usbhost,
+		.reg_div = { .reg = S5PC100_CLKDIV2, .shift = 20, .size = 4, },
+		.reg_src = { .reg = S5PC100_CLKSRC1, .shift = 20, .size = 2, },
+	}
 };
 
 /* Clock initialisation code */
@@ -981,45 +756,8 @@
 	&clk_mout_onenand,
 	&clk_mout_epll,
 	&clk_mout_hpll,
-	&clk_spi0,
-	&clk_spi1,
-	&clk_spi2,
-	&clk_uart_uclk1,
-	&clk_audio0,
-	&clk_audio1,
-	&clk_audio2,
-	&clk_spdif,
-	&clk_lcd,
-	&clk_fimc0,
-	&clk_fimc1,
-	&clk_fimc2,
-	&clk_mmc0,
-	&clk_mmc1,
-	&clk_mmc2,
-	&clk_usbhost,
 };
 
-static void __init_or_cpufreq s5pc100_set_clksrc(struct clksrc_clk *clk)
-{
-	struct clk_sources *srcs = clk->sources;
-	u32 clksrc = __raw_readl(clk->reg_source);
-
-	clksrc &= clk->mask;
-	clksrc >>= clk->shift;
-
-	if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
-		printk(KERN_ERR "%s: bad source %d\n",
-		       clk->clk.name, clksrc);
-		return;
-	}
-
-	clk->clk.parent = srcs->sources[clksrc];
-
-	printk(KERN_INFO "%s: source is %s (%d), rate is %ld.%03ld MHz\n",
-		clk->clk.name, clk->clk.parent->name, clksrc,
-		print_mhz(clk_get_rate(&clk->clk)));
-}
-
 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
 
 void __init_or_cpufreq s5pc100_setup_clocks(void)
@@ -1083,17 +821,25 @@
 	clk_f.rate = armclk;
 
 	for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
-		s5pc100_set_clksrc(init_parents[ptr]);
+		s3c_set_clksrc(init_parents[ptr], true);
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrc_audio); ptr++)
+		s3c_set_clksrc(clksrc_audio + ptr, true);
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrc_clks); ptr++)
+		s3c_set_clksrc(clksrc_clks + ptr, true);
 }
 
 static struct clk *clks[] __initdata = {
 	&clk_ext_xtal_mux,
-	&clk_mout_apll.clk,
 	&clk_dout_apll,
 	&clk_dout_d0_bus,
 	&clk_dout_pclkd0,
 	&clk_dout_apll2,
+	&clk_mout_apll.clk,
 	&clk_mout_mpll.clk,
+	&clk_mout_epll.clk,
+	&clk_mout_hpll.clk,
 	&clk_mout_am.clk,
 	&clk_dout_d1_bus,
 	&clk_mout_onenand.clk,
@@ -1101,29 +847,12 @@
 	&clk_dout_mpll2,
 	&clk_dout_cam,
 	&clk_dout_mpll,
-	&clk_mout_epll.clk,
 	&clk_fout_epll,
 	&clk_iis_cd0,
 	&clk_iis_cd1,
 	&clk_iis_cd2,
 	&clk_pcm_cd0,
 	&clk_pcm_cd1,
-	&clk_spi0.clk,
-	&clk_spi1.clk,
-	&clk_spi2.clk,
-	&clk_uart_uclk1.clk,
-	&clk_audio0.clk,
-	&clk_audio1.clk,
-	&clk_audio2.clk,
-	&clk_spdif.clk,
-	&clk_lcd.clk,
-	&clk_fimc0.clk,
-	&clk_fimc1.clk,
-	&clk_fimc2.clk,
-	&clk_mmc0.clk,
-	&clk_mmc1.clk,
-	&clk_mmc2.clk,
-	&clk_usbhost.clk,
 	&clk_arm,
 };
 
@@ -1141,4 +870,7 @@
 			       clkp->name, ret);
 		}
 	}
+
+	s3c_register_clksrc(clksrc_audio, ARRAY_SIZE(clksrc_audio));
+	s3c_register_clksrc(clksrc_clks, ARRAY_SIZE(clksrc_clks));
 }
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 486a0d6..d552c65 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -7,11 +7,240 @@
 config PLAT_SAMSUNG
 	bool
 	depends on ARCH_S3C2410 || ARCH_S3C24A0 || ARCH_S3C64XX || ARCH_S5PC1XX
+	select NO_IOPORT
 	default y
 	help
 	  Base platform code for all Samsung SoC based systems
 
 if PLAT_SAMSUNG
 
+# boot configurations
+
+comment "Boot options"
+
+config S3C_BOOT_WATCHDOG
+	bool "S3C Initialisation watchdog"
+	depends on S3C2410_WATCHDOG
+	help
+	  Say y to enable the watchdog during the kernel decompression
+	  stage. If the kernel fails to uncompress, then the watchdog
+	  will trigger a reset and the system should restart.
+
+config S3C_BOOT_ERROR_RESET
+	bool "S3C Reboot on decompression error"
+	help
+	  Say y here to use the watchdog to reset the system if the
+	  kernel decompressor detects an error during decompression.
+
+config S3C_BOOT_UART_FORCE_FIFO
+       bool "Force UART FIFO on during boot process"
+       default y
+       help
+         Say Y here to force the UART FIFOs on during the kernel
+	 uncompressor
+
+
+config S3C_LOWLEVEL_UART_PORT
+	int "S3C UART to use for low-level messages"
+	default 0
+	help
+	  Choice of which UART port to use for the low-level messages,
+	  such as the `Uncompressing...` at start time. The value of
+	  this configuration should be between zero and two. The port
+	  must have been initialised by the boot-loader before use.
+
+# clock options
+
+config SAMSUNG_CLKSRC
+	bool
+	help
+	  Select the clock code for the clksrc implementation
+	  used by newer systems such as the S3C64XX.
+
+# options for IRQ support
+
+config SAMSUNG_IRQ_VIC_TIMER
+       bool
+       help
+         Internal configuration to build the VIC timer interrupt code.
+
+config SAMSUNG_IRQ_UART
+       bool
+       help
+         Internal configuration to build the IRQ UART demux code.
+
+# options for gpio configuration support
+
+config SAMSUNG_GPIOLIB_4BIT
+	bool
+	help
+	  GPIOlib file contains the 4 bit modification functions for gpio
+	  configuration. GPIOlib shall be compiled only for S3C64XX and S5P
+	  series of processors.
+
+config S3C_GPIO_CFG_S3C24XX
+	bool
+	help
+	  Internal configuration to enable S3C24XX style GPIO configuration
+	  functions.
+
+config S3C_GPIO_CFG_S3C64XX
+	bool
+	help
+	  Internal configuration to enable S3C64XX style GPIO configuration
+	  functions.
+
+config S5P_GPIO_CFG_S5PC1XX
+	bool
+	help
+	  Internal configuration to enable S5PC1XX style GPIO configuration
+	  functions.
+
+config S3C_GPIO_PULL_UPDOWN
+	bool
+	help
+	  Internal configuration to enable the correct GPIO pull helper
+
+config S3C_GPIO_PULL_DOWN
+	bool
+	help
+	  Internal configuration to enable the correct GPIO pull helper
+
+config S3C_GPIO_PULL_UP
+	bool
+	help
+	  Internal configuration to enable the correct GPIO pull helper
+
+config SAMSUNG_GPIO_EXTRA
+	int "Number of additional GPIO pins"
+	default 0
+	help
+	  Use additional GPIO space in addition to the GPIO's the SOC
+	  provides. This allows expanding the GPIO space for use with
+	  GPIO expanders.
+
+config S3C_GPIO_SPACE
+	int "Space between gpio banks"
+	default 0
+	help
+	  Add a number of spare GPIO entries between each bank for debugging
+	  purposes. This allows any problems where an counter overflows from
+	  one bank to another to be caught, at the expense of using a little
+	  more memory.
+
+config S3C_GPIO_TRACK
+	bool
+	help
+	  Internal configuration option to enable the s3c specific gpio
+	  chip tracking if the platform requires it.
+
+# ADC driver
+
+config S3C_ADC
+	bool "ADC common driver support"
+	help
+	  Core support for the ADC block found in the Samsung SoC systems
+	  for drivers such as the touchscreen and hwmon to use to share
+	  this resource.
+
+# device definitions to compile in
+
+config S3C_DEV_HSMMC
+	bool
+	help
+	  Compile in platform device definitions for HSMMC code
+
+config S3C_DEV_HSMMC1
+	bool
+	help
+	  Compile in platform device definitions for HSMMC channel 1
+
+config S3C_DEV_HSMMC2
+	bool
+	help
+	  Compile in platform device definitions for HSMMC channel 2
+
+config S3C_DEV_I2C1
+	bool
+	help
+	  Compile in platform device definitions for I2C channel 1
+
+config S3C_DEV_FB
+	bool
+	help
+	  Compile in platform device definition for framebuffer
+
+config S3C_DEV_USB_HOST
+	bool
+	help
+	  Compile in platform device definition for USB host.
+
+config S3C_DEV_USB_HSOTG
+	bool
+	help
+	  Compile in platform device definition for USB high-speed OtG
+
+config S3C_DEV_NAND
+	bool
+	help
+	  Compile in platform device definition for NAND controller
+
+config S3C64XX_DEV_SPI
+	bool
+	help
+	  Compile in platform device definitions for S3C64XX's type
+	  SPI controllers.
+
+# DMA
+
+config S3C_DMA
+	bool
+	help
+	  Internal configuration for S3C DMA core
+
+comment "Power management"
+
+config SAMSUNG_PM_DEBUG
+	bool "S3C2410 PM Suspend debug"
+	depends on PM
+	help
+	  Say Y here if you want verbose debugging from the PM Suspend and
+	  Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
+	  for more information.
+
+config S3C_PM_DEBUG_LED_SMDK
+       bool "SMDK LED suspend/resume debugging"
+       depends on PM && (MACH_SMDK6410)
+       help
+         Say Y here to enable the use of the SMDK LEDs on the baseboard
+	 for debugging of the state of the suspend and resume process.
+
+	 Note, this currently only works for S3C64XX based SMDK boards.
+
+config SAMSUNG_PM_CHECK
+	bool "S3C2410 PM Suspend Memory CRC"
+	depends on PM && CRC32
+	help
+	  Enable the PM code's memory area checksum over sleep. This option
+	  will generate CRCs of all blocks of memory, and store them before
+	  going to sleep. The blocks are then checked on resume for any
+	  errors.
+
+	  Note, this can take several seconds depending on memory size
+	  and CPU speed.
+
+	  See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
+
+config SAMSUNG_PM_CHECK_CHUNKSIZE
+	int "S3C2410 PM Suspend CRC Chunksize (KiB)"
+	depends on PM && SAMSUNG_PM_CHECK
+	default 64
+	help
+	  Set the chunksize in Kilobytes of the CRC for checking memory
+	  corruption over suspend and resume. A smaller value will mean that
+	  the CRC data block will take more memory, but wil identify any
+	  faults with better precision.
+
+	  See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
 
 endif
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 4478b9f..22c89d0 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -9,3 +9,48 @@
 obj-n				:= dummy.o
 obj-				:=
 
+# Objects we always build independent of SoC choice
+
+obj-y				+= init.o
+obj-y				+= time.o
+obj-y				+= clock.o
+obj-y				+= pwm-clock.o
+obj-y				+= gpio.o
+obj-y				+= gpio-config.o
+
+obj-$(CONFIG_SAMSUNG_GPIOLIB_4BIT)	+= gpiolib.o
+obj-$(CONFIG_SAMSUNG_CLKSRC)	+= clock-clksrc.o
+
+obj-$(CONFIG_SAMSUNG_IRQ_UART)	+= irq-uart.o
+obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o
+
+# ADC
+
+obj-$(CONFIG_S3C_ADC)	+= adc.o
+
+# devices
+
+obj-$(CONFIG_S3C_DEV_HSMMC)	+= dev-hsmmc.o
+obj-$(CONFIG_S3C_DEV_HSMMC1)	+= dev-hsmmc1.o
+obj-$(CONFIG_S3C_DEV_HSMMC2)	+= dev-hsmmc2.o
+obj-y				+= dev-i2c0.o
+obj-$(CONFIG_S3C_DEV_I2C1)	+= dev-i2c1.o
+obj-$(CONFIG_S3C_DEV_FB)	+= dev-fb.o
+obj-y				+= dev-uart.o
+obj-$(CONFIG_S3C_DEV_USB_HOST)	+= dev-usb.o
+obj-$(CONFIG_S3C_DEV_USB_HSOTG)	+= dev-usb-hsotg.o
+obj-$(CONFIG_S3C_DEV_NAND)	+= dev-nand.o
+
+# DMA support
+
+obj-$(CONFIG_S3C_DMA)		+= dma.o
+
+# PM support
+
+obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_PM)		+= pm-gpio.o
+obj-$(CONFIG_SAMSUNG_PM_CHECK)	+= pm-check.o
+
+# PWM support
+
+obj-$(CONFIG_HAVE_PWM)		+= pwm.o
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
new file mode 100644
index 0000000..0b5833b
--- /dev/null
+++ b/arch/arm/plat-samsung/adc.c
@@ -0,0 +1,474 @@
+/* arch/arm/plat-samsung/adc.c
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
+ *
+ * Samsung ADC device core
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <plat/regs-adc.h>
+#include <plat/adc.h>
+
+/* This driver is designed to control the usage of the ADC block between
+ * the touchscreen and any other drivers that may need to use it, such as
+ * the hwmon driver.
+ *
+ * Priority will be given to the touchscreen driver, but as this itself is
+ * rate limited it should not starve other requests which are processed in
+ * order that they are received.
+ *
+ * Each user registers to get a client block which uniquely identifies it
+ * and stores information such as the necessary functions to callback when
+ * action is required.
+ */
+
+enum s3c_cpu_type {
+	TYPE_S3C24XX,
+	TYPE_S3C64XX
+};
+
+struct s3c_adc_client {
+	struct platform_device	*pdev;
+	struct list_head	 pend;
+	wait_queue_head_t	*wait;
+
+	unsigned int		 nr_samples;
+	int			 result;
+	unsigned char		 is_ts;
+	unsigned char		 channel;
+
+	void	(*select_cb)(struct s3c_adc_client *c, unsigned selected);
+	void	(*convert_cb)(struct s3c_adc_client *c,
+			      unsigned val1, unsigned val2,
+			      unsigned *samples_left);
+};
+
+struct adc_device {
+	struct platform_device	*pdev;
+	struct platform_device	*owner;
+	struct clk		*clk;
+	struct s3c_adc_client	*cur;
+	struct s3c_adc_client	*ts_pend;
+	void __iomem		*regs;
+
+	unsigned int		 prescale;
+
+	int			 irq;
+};
+
+static struct adc_device *adc_dev;
+
+static LIST_HEAD(adc_pending);
+
+#define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg)
+
+static inline void s3c_adc_convert(struct adc_device *adc)
+{
+	unsigned con = readl(adc->regs + S3C2410_ADCCON);
+
+	con |= S3C2410_ADCCON_ENABLE_START;
+	writel(con, adc->regs + S3C2410_ADCCON);
+}
+
+static inline void s3c_adc_select(struct adc_device *adc,
+				  struct s3c_adc_client *client)
+{
+	unsigned con = readl(adc->regs + S3C2410_ADCCON);
+
+	client->select_cb(client, 1);
+
+	con &= ~S3C2410_ADCCON_MUXMASK;
+	con &= ~S3C2410_ADCCON_STDBM;
+	con &= ~S3C2410_ADCCON_STARTMASK;
+
+	if (!client->is_ts)
+		con |= S3C2410_ADCCON_SELMUX(client->channel);
+
+	writel(con, adc->regs + S3C2410_ADCCON);
+}
+
+static void s3c_adc_dbgshow(struct adc_device *adc)
+{
+	adc_dbg(adc, "CON=%08x, TSC=%08x, DLY=%08x\n",
+		readl(adc->regs + S3C2410_ADCCON),
+		readl(adc->regs + S3C2410_ADCTSC),
+		readl(adc->regs + S3C2410_ADCDLY));
+}
+
+static void s3c_adc_try(struct adc_device *adc)
+{
+	struct s3c_adc_client *next = adc->ts_pend;
+
+	if (!next && !list_empty(&adc_pending)) {
+		next = list_first_entry(&adc_pending,
+					struct s3c_adc_client, pend);
+		list_del(&next->pend);
+	} else
+		adc->ts_pend = NULL;
+
+	if (next) {
+		adc_dbg(adc, "new client is %p\n", next);
+		adc->cur = next;
+		s3c_adc_select(adc, next);
+		s3c_adc_convert(adc);
+		s3c_adc_dbgshow(adc);
+	}
+}
+
+int s3c_adc_start(struct s3c_adc_client *client,
+		  unsigned int channel, unsigned int nr_samples)
+{
+	struct adc_device *adc = adc_dev;
+	unsigned long flags;
+
+	if (!adc) {
+		printk(KERN_ERR "%s: failed to find adc\n", __func__);
+		return -EINVAL;
+	}
+
+	if (client->is_ts && adc->ts_pend)
+		return -EAGAIN;
+
+	local_irq_save(flags);
+
+	client->channel = channel;
+	client->nr_samples = nr_samples;
+
+	if (client->is_ts)
+		adc->ts_pend = client;
+	else
+		list_add_tail(&client->pend, &adc_pending);
+
+	if (!adc->cur)
+		s3c_adc_try(adc);
+	local_irq_restore(flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(s3c_adc_start);
+
+static void s3c_convert_done(struct s3c_adc_client *client,
+			     unsigned v, unsigned u, unsigned *left)
+{
+	client->result = v;
+	wake_up(client->wait);
+}
+
+int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch)
+{
+	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
+	int ret;
+
+	client->convert_cb = s3c_convert_done;
+	client->wait = &wake;
+	client->result = -1;
+
+	ret = s3c_adc_start(client, ch, 1);
+	if (ret < 0)
+		goto err;
+
+	ret = wait_event_timeout(wake, client->result >= 0, HZ / 2);
+	if (client->result < 0) {
+		ret = -ETIMEDOUT;
+		goto err;
+	}
+
+	client->convert_cb = NULL;
+	return client->result;
+
+err:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(s3c_adc_read);
+
+static void s3c_adc_default_select(struct s3c_adc_client *client,
+				   unsigned select)
+{
+}
+
+struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
+					void (*select)(struct s3c_adc_client *client,
+						       unsigned int selected),
+					void (*conv)(struct s3c_adc_client *client,
+						     unsigned d0, unsigned d1,
+						     unsigned *samples_left),
+					unsigned int is_ts)
+{
+	struct s3c_adc_client *client;
+
+	WARN_ON(!pdev);
+
+	if (!select)
+		select = s3c_adc_default_select;
+
+	if (!pdev)
+		return ERR_PTR(-EINVAL);
+
+	client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL);
+	if (!client) {
+		dev_err(&pdev->dev, "no memory for adc client\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	client->pdev = pdev;
+	client->is_ts = is_ts;
+	client->select_cb = select;
+	client->convert_cb = conv;
+
+	return client;
+}
+EXPORT_SYMBOL_GPL(s3c_adc_register);
+
+void s3c_adc_release(struct s3c_adc_client *client)
+{
+	/* We should really check that nothing is in progress. */
+	if (adc_dev->cur == client)
+		adc_dev->cur = NULL;
+	if (adc_dev->ts_pend == client)
+		adc_dev->ts_pend = NULL;
+	else {
+		struct list_head *p, *n;
+		struct s3c_adc_client *tmp;
+
+		list_for_each_safe(p, n, &adc_pending) {
+			tmp = list_entry(p, struct s3c_adc_client, pend);
+			if (tmp == client)
+				list_del(&tmp->pend);
+		}
+	}
+
+	if (adc_dev->cur == NULL)
+		s3c_adc_try(adc_dev);
+	kfree(client);
+}
+EXPORT_SYMBOL_GPL(s3c_adc_release);
+
+static irqreturn_t s3c_adc_irq(int irq, void *pw)
+{
+	struct adc_device *adc = pw;
+	struct s3c_adc_client *client = adc->cur;
+	enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
+	unsigned long flags;
+	unsigned data0, data1;
+
+	if (!client) {
+		dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__);
+		goto exit;
+	}
+
+	data0 = readl(adc->regs + S3C2410_ADCDAT0);
+	data1 = readl(adc->regs + S3C2410_ADCDAT1);
+	adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1);
+
+	client->nr_samples--;
+
+	if (cpu == TYPE_S3C64XX) {
+		/* S3C64XX ADC resolution is 12-bit */
+		data0 &= 0xfff;
+		data1 &= 0xfff;
+	} else {
+		data0 &= 0x3ff;
+		data1 &= 0x3ff;
+	}
+
+	if (client->convert_cb)
+		(client->convert_cb)(client, data0, data1, &client->nr_samples);
+
+	if (client->nr_samples > 0) {
+		/* fire another conversion for this */
+
+		client->select_cb(client, 1);
+		s3c_adc_convert(adc);
+	} else {
+		local_irq_save(flags);
+		(client->select_cb)(client, 0);
+		adc->cur = NULL;
+
+		s3c_adc_try(adc);
+		local_irq_restore(flags);
+	}
+
+exit:
+	if (cpu == TYPE_S3C64XX) {
+		/* Clear ADC interrupt */
+		writel(0, adc->regs + S3C64XX_ADCCLRINT);
+	}
+	return IRQ_HANDLED;
+}
+
+static int s3c_adc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct adc_device *adc;
+	struct resource *regs;
+	int ret;
+	unsigned tmp;
+
+	adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL);
+	if (adc == NULL) {
+		dev_err(dev, "failed to allocate adc_device\n");
+		return -ENOMEM;
+	}
+
+	adc->pdev = pdev;
+	adc->prescale = S3C2410_ADCCON_PRSCVL(49);
+
+	adc->irq = platform_get_irq(pdev, 1);
+	if (adc->irq <= 0) {
+		dev_err(dev, "failed to get adc irq\n");
+		ret = -ENOENT;
+		goto err_alloc;
+	}
+
+	ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc);
+	if (ret < 0) {
+		dev_err(dev, "failed to attach adc irq\n");
+		goto err_alloc;
+	}
+
+	adc->clk = clk_get(dev, "adc");
+	if (IS_ERR(adc->clk)) {
+		dev_err(dev, "failed to get adc clock\n");
+		ret = PTR_ERR(adc->clk);
+		goto err_irq;
+	}
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_err(dev, "failed to find registers\n");
+		ret = -ENXIO;
+		goto err_clk;
+	}
+
+	adc->regs = ioremap(regs->start, resource_size(regs));
+	if (!adc->regs) {
+		dev_err(dev, "failed to map registers\n");
+		ret = -ENXIO;
+		goto err_clk;
+	}
+
+	clk_enable(adc->clk);
+
+	tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
+	if (platform_get_device_id(pdev)->driver_data == TYPE_S3C64XX) {
+		/* Enable 12-bit ADC resolution */
+		tmp |= S3C64XX_ADCCON_RESSEL;
+	}
+	writel(tmp, adc->regs + S3C2410_ADCCON);
+
+	dev_info(dev, "attached adc driver\n");
+
+	platform_set_drvdata(pdev, adc);
+	adc_dev = adc;
+
+	return 0;
+
+ err_clk:
+	clk_put(adc->clk);
+
+ err_irq:
+	free_irq(adc->irq, adc);
+
+ err_alloc:
+	kfree(adc);
+	return ret;
+}
+
+static int __devexit s3c_adc_remove(struct platform_device *pdev)
+{
+	struct adc_device *adc = platform_get_drvdata(pdev);
+
+	iounmap(adc->regs);
+	free_irq(adc->irq, adc);
+	clk_disable(adc->clk);
+	clk_put(adc->clk);
+	kfree(adc);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct adc_device *adc = platform_get_drvdata(pdev);
+	u32 con;
+
+	con = readl(adc->regs + S3C2410_ADCCON);
+	con |= S3C2410_ADCCON_STDBM;
+	writel(con, adc->regs + S3C2410_ADCCON);
+
+	disable_irq(adc->irq);
+	clk_disable(adc->clk);
+
+	return 0;
+}
+
+static int s3c_adc_resume(struct platform_device *pdev)
+{
+	struct adc_device *adc = platform_get_drvdata(pdev);
+
+	clk_enable(adc->clk);
+	enable_irq(adc->irq);
+
+	writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
+	       adc->regs + S3C2410_ADCCON);
+
+	return 0;
+}
+
+#else
+#define s3c_adc_suspend NULL
+#define s3c_adc_resume NULL
+#endif
+
+static struct platform_device_id s3c_adc_driver_ids[] = {
+	{
+		.name           = "s3c24xx-adc",
+		.driver_data    = TYPE_S3C24XX,
+	}, {
+		.name           = "s3c64xx-adc",
+		.driver_data    = TYPE_S3C64XX,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, s3c_adc_driver_ids);
+
+static struct platform_driver s3c_adc_driver = {
+	.id_table	= s3c_adc_driver_ids,
+	.driver		= {
+		.name	= "s3c-adc",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= s3c_adc_probe,
+	.remove		= __devexit_p(s3c_adc_remove),
+	.suspend	= s3c_adc_suspend,
+	.resume		= s3c_adc_resume,
+};
+
+static int __init adc_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&s3c_adc_driver);
+	if (ret)
+		printk(KERN_ERR "%s: failed to add adc driver\n", __func__);
+
+	return ret;
+}
+
+arch_initcall(adc_init);
diff --git a/arch/arm/plat-samsung/clock-clksrc.c b/arch/arm/plat-samsung/clock-clksrc.c
new file mode 100644
index 0000000..ae8b850
--- /dev/null
+++ b/arch/arm/plat-samsung/clock-clksrc.c
@@ -0,0 +1,212 @@
+/* linux/arch/arm/plat-samsung/clock-clksrc.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/sysdev.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+#include <plat/clock-clksrc.h>
+#include <plat/cpu-freq.h>
+
+static inline struct clksrc_clk *to_clksrc(struct clk *clk)
+{
+	return container_of(clk, struct clksrc_clk, clk);
+}
+
+static inline u32 bit_mask(u32 shift, u32 nr_bits)
+{
+	u32 mask = 0xffffffff >> (32 - nr_bits);
+
+	return mask << shift;
+}
+
+static unsigned long s3c_getrate_clksrc(struct clk *clk)
+{
+	struct clksrc_clk *sclk = to_clksrc(clk);
+	unsigned long rate = clk_get_rate(clk->parent);
+	u32 clkdiv = __raw_readl(sclk->reg_div.reg);
+	u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size);
+
+	clkdiv &= mask;
+	clkdiv >>= sclk->reg_div.shift;
+	clkdiv++;
+
+	rate /= clkdiv;
+	return rate;
+}
+
+static int s3c_setrate_clksrc(struct clk *clk, unsigned long rate)
+{
+	struct clksrc_clk *sclk = to_clksrc(clk);
+	void __iomem *reg = sclk->reg_div.reg;
+	unsigned int div;
+	u32 mask = bit_mask(sclk->reg_div.shift, sclk->reg_div.size);
+	u32 val;
+
+	rate = clk_round_rate(clk, rate);
+	div = clk_get_rate(clk->parent) / rate;
+	if (div > (1 << sclk->reg_div.size))
+		return -EINVAL;
+
+	val = __raw_readl(reg);
+	val &= ~mask;
+	val |= (div - 1) << sclk->reg_div.shift;
+	__raw_writel(val, reg);
+
+	return 0;
+}
+
+static int s3c_setparent_clksrc(struct clk *clk, struct clk *parent)
+{
+	struct clksrc_clk *sclk = to_clksrc(clk);
+	struct clksrc_sources *srcs = sclk->sources;
+	u32 clksrc = __raw_readl(sclk->reg_src.reg);
+	u32 mask = bit_mask(sclk->reg_src.shift, sclk->reg_src.size);
+	int src_nr = -1;
+	int ptr;
+
+	for (ptr = 0; ptr < srcs->nr_sources; ptr++)
+		if (srcs->sources[ptr] == parent) {
+			src_nr = ptr;
+			break;
+		}
+
+	if (src_nr >= 0) {
+		clk->parent = parent;
+
+		clksrc &= ~mask;
+		clksrc |= src_nr << sclk->reg_src.shift;
+
+		__raw_writel(clksrc, sclk->reg_src.reg);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static unsigned long s3c_roundrate_clksrc(struct clk *clk,
+					      unsigned long rate)
+{
+	struct clksrc_clk *sclk = to_clksrc(clk);
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int max_div = 1 << sclk->reg_div.size;
+	int div;
+
+	if (rate >= parent_rate)
+		rate = parent_rate;
+	else {
+		div = parent_rate / rate;
+		if (parent_rate % rate)
+			div++;
+
+		if (div == 0)
+			div = 1;
+		if (div > max_div)
+			div = max_div;
+
+		rate = parent_rate / div;
+	}
+
+	return rate;
+}
+
+/* Clock initialisation code */
+
+void __init_or_cpufreq s3c_set_clksrc(struct clksrc_clk *clk, bool announce)
+{
+	struct clksrc_sources *srcs = clk->sources;
+	u32 mask = bit_mask(clk->reg_src.shift, clk->reg_src.size);
+	u32 clksrc;
+
+	if (!clk->reg_src.reg) {
+		if (!clk->clk.parent)
+			printk(KERN_ERR "%s: no parent clock specified\n",
+				clk->clk.name);
+		return;
+	}
+
+	clksrc = __raw_readl(clk->reg_src.reg);
+	clksrc &= mask;
+	clksrc >>= clk->reg_src.shift;
+
+	if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) {
+		printk(KERN_ERR "%s: bad source %d\n",
+		       clk->clk.name, clksrc);
+		return;
+	}
+
+	clk->clk.parent = srcs->sources[clksrc];
+
+	if (announce)
+		printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n",
+		       clk->clk.name, clk->clk.parent->name, clksrc,
+		       clk_get_rate(&clk->clk));
+}
+
+static struct clk_ops clksrc_ops = {
+	.set_parent	= s3c_setparent_clksrc,
+	.get_rate	= s3c_getrate_clksrc,
+	.set_rate	= s3c_setrate_clksrc,
+	.round_rate	= s3c_roundrate_clksrc,
+};
+
+static struct clk_ops clksrc_ops_nodiv = {
+	.set_parent	= s3c_setparent_clksrc,
+};
+
+static struct clk_ops clksrc_ops_nosrc = {
+	.get_rate	= s3c_getrate_clksrc,
+	.set_rate	= s3c_setrate_clksrc,
+	.round_rate	= s3c_roundrate_clksrc,
+};
+
+void __init s3c_register_clksrc(struct clksrc_clk *clksrc, int size)
+{
+	int ret;
+
+	for (; size > 0; size--, clksrc++) {
+		if (!clksrc->reg_div.reg && !clksrc->reg_src.reg)
+			printk(KERN_ERR "%s: clock %s has no registers set\n",
+			       __func__, clksrc->clk.name);
+
+		/* fill in the default functions */
+
+		if (!clksrc->clk.ops) {
+			if (!clksrc->reg_div.reg)
+				clksrc->clk.ops = &clksrc_ops_nodiv;
+			else if (!clksrc->reg_src.reg)
+				clksrc->clk.ops = &clksrc_ops_nosrc;
+			else
+				clksrc->clk.ops = &clksrc_ops;
+		}
+
+		/* setup the clocksource, but do not announce it
+		 * as it may be re-set by the setup routines
+		 * called after the rest of the clocks have been
+		 * registered
+		 */
+		s3c_set_clksrc(clksrc, false);
+
+		ret = s3c24xx_register_clock(&clksrc->clk);
+
+		if (ret < 0) {
+			printk(KERN_ERR "%s: failed to register %s (%d)\n",
+			       __func__, clksrc->clk.name, ret);
+		}
+	}
+}
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
new file mode 100644
index 0000000..1b25c9d
--- /dev/null
+++ b/arch/arm/plat-samsung/clock.c
@@ -0,0 +1,409 @@
+/* linux/arch/arm/plat-s3c24xx/clock.c
+ *
+ * Copyright 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX Core clock control support
+ *
+ * Based on, and code from linux/arch/arm/mach-versatile/clock.c
+ **
+ **  Copyright (C) 2004 ARM Limited.
+ **  Written by Deep Blue Solutions Limited.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+
+#include <plat/cpu-freq.h>
+
+#include <plat/clock.h>
+#include <plat/cpu.h>
+
+/* clock information */
+
+static LIST_HEAD(clocks);
+
+/* We originally used an mutex here, but some contexts (see resume)
+ * are calling functions such as clk_set_parent() with IRQs disabled
+ * causing an BUG to be triggered.
+ */
+DEFINE_SPINLOCK(clocks_lock);
+
+/* enable and disable calls for use with the clk struct */
+
+static int clk_null_enable(struct clk *clk, int enable)
+{
+	return 0;
+}
+
+/* Clock API calls */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p;
+	struct clk *clk = ERR_PTR(-ENOENT);
+	int idno;
+
+	if (dev == NULL || dev->bus != &platform_bus_type)
+		idno = -1;
+	else
+		idno = to_platform_device(dev)->id;
+
+	spin_lock(&clocks_lock);
+
+	list_for_each_entry(p, &clocks, list) {
+		if (p->id == idno &&
+		    strcmp(id, p->name) == 0 &&
+		    try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+
+	/* check for the case where a device was supplied, but the
+	 * clock that was being searched for is not device specific */
+
+	if (IS_ERR(clk)) {
+		list_for_each_entry(p, &clocks, list) {
+			if (p->id == -1 && strcmp(id, p->name) == 0 &&
+			    try_module_get(p->owner)) {
+				clk = p;
+				break;
+			}
+		}
+	}
+
+	spin_unlock(&clocks_lock);
+	return clk;
+}
+
+void clk_put(struct clk *clk)
+{
+	module_put(clk->owner);
+}
+
+int clk_enable(struct clk *clk)
+{
+	if (IS_ERR(clk) || clk == NULL)
+		return -EINVAL;
+
+	clk_enable(clk->parent);
+
+	spin_lock(&clocks_lock);
+
+	if ((clk->usage++) == 0)
+		(clk->enable)(clk, 1);
+
+	spin_unlock(&clocks_lock);
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+	if (IS_ERR(clk) || clk == NULL)
+		return;
+
+	spin_lock(&clocks_lock);
+
+	if ((--clk->usage) == 0)
+		(clk->enable)(clk, 0);
+
+	spin_unlock(&clocks_lock);
+	clk_disable(clk->parent);
+}
+
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (IS_ERR(clk))
+		return 0;
+
+	if (clk->rate != 0)
+		return clk->rate;
+
+	if (clk->ops != NULL && clk->ops->get_rate != NULL)
+		return (clk->ops->get_rate)(clk);
+
+	if (clk->parent != NULL)
+		return clk_get_rate(clk->parent);
+
+	return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (!IS_ERR(clk) && clk->ops && clk->ops->round_rate)
+		return (clk->ops->round_rate)(clk, rate);
+
+	return rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret;
+
+	if (IS_ERR(clk))
+		return -EINVAL;
+
+	/* We do not default just do a clk->rate = rate as
+	 * the clock may have been made this way by choice.
+	 */
+
+	WARN_ON(clk->ops == NULL);
+	WARN_ON(clk->ops && clk->ops->set_rate == NULL);
+
+	if (clk->ops == NULL || clk->ops->set_rate == NULL)
+		return -EINVAL;
+
+	spin_lock(&clocks_lock);
+	ret = (clk->ops->set_rate)(clk, rate);
+	spin_unlock(&clocks_lock);
+
+	return ret;
+}
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return clk->parent;
+}
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = 0;
+
+	if (IS_ERR(clk))
+		return -EINVAL;
+
+	spin_lock(&clocks_lock);
+
+	if (clk->ops && clk->ops->set_parent)
+		ret = (clk->ops->set_parent)(clk, parent);
+
+	spin_unlock(&clocks_lock);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_get);
+EXPORT_SYMBOL(clk_put);
+EXPORT_SYMBOL(clk_enable);
+EXPORT_SYMBOL(clk_disable);
+EXPORT_SYMBOL(clk_get_rate);
+EXPORT_SYMBOL(clk_round_rate);
+EXPORT_SYMBOL(clk_set_rate);
+EXPORT_SYMBOL(clk_get_parent);
+EXPORT_SYMBOL(clk_set_parent);
+
+/* base clocks */
+
+int clk_default_setrate(struct clk *clk, unsigned long rate)
+{
+	clk->rate = rate;
+	return 0;
+}
+
+struct clk_ops clk_ops_def_setrate = {
+	.set_rate	= clk_default_setrate,
+};
+
+struct clk clk_xtal = {
+	.name		= "xtal",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_ext = {
+	.name		= "ext",
+	.id		= -1,
+};
+
+struct clk clk_epll = {
+	.name		= "epll",
+	.id		= -1,
+};
+
+struct clk clk_mpll = {
+	.name		= "mpll",
+	.id		= -1,
+	.ops		= &clk_ops_def_setrate,
+};
+
+struct clk clk_upll = {
+	.name		= "upll",
+	.id		= -1,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_f = {
+	.name		= "fclk",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= &clk_mpll,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_h = {
+	.name		= "hclk",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+	.ops		= &clk_ops_def_setrate,
+};
+
+struct clk clk_p = {
+	.name		= "pclk",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+	.ops		= &clk_ops_def_setrate,
+};
+
+struct clk clk_usb_bus = {
+	.name		= "usb-bus",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= &clk_upll,
+};
+
+
+struct clk s3c24xx_uclk = {
+	.name		= "uclk",
+	.id		= -1,
+};
+
+/* initialise the clock system */
+
+/**
+ * s3c24xx_register_clock() - register a clock
+ * @clk: The clock to register
+ *
+ * Add the specified clock to the list of clocks known by the system.
+ */
+int s3c24xx_register_clock(struct clk *clk)
+{
+	if (clk->enable == NULL)
+		clk->enable = clk_null_enable;
+
+	/* add to the list of available clocks */
+
+	/* Quick check to see if this clock has already been registered. */
+	BUG_ON(clk->list.prev != clk->list.next);
+
+	spin_lock(&clocks_lock);
+	list_add(&clk->list, &clocks);
+	spin_unlock(&clocks_lock);
+
+	return 0;
+}
+
+/**
+ * s3c24xx_register_clocks() - register an array of clock pointers
+ * @clks: Pointer to an array of struct clk pointers
+ * @nr_clks: The number of clocks in the @clks array.
+ *
+ * Call s3c24xx_register_clock() for all the clock pointers contained
+ * in the @clks list. Returns the number of failures.
+ */
+int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
+{
+	int fails = 0;
+
+	for (; nr_clks > 0; nr_clks--, clks++) {
+		if (s3c24xx_register_clock(*clks) < 0) {
+			struct clk *clk = *clks;
+			printk(KERN_ERR "%s: failed to register %p: %s\n",
+			       __func__, clk, clk->name);
+			fails++;
+		}
+	}
+
+	return fails;
+}
+
+/**
+ * s3c_register_clocks() - register an array of clocks
+ * @clkp: Pointer to the first clock in the array.
+ * @nr_clks: Number of clocks to register.
+ *
+ * Call s3c24xx_register_clock() on the @clkp array given, printing an
+ * error if it fails to register the clock (unlikely).
+ */
+void __init s3c_register_clocks(struct clk *clkp, int nr_clks)
+{
+	int ret;
+
+	for (; nr_clks > 0; nr_clks--, clkp++) {
+		ret = s3c24xx_register_clock(clkp);
+
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+}
+
+/* initalise all the clocks */
+
+int __init s3c24xx_register_baseclocks(unsigned long xtal)
+{
+	printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n");
+
+	clk_xtal.rate = xtal;
+
+	/* register our clocks */
+
+	if (s3c24xx_register_clock(&clk_xtal) < 0)
+		printk(KERN_ERR "failed to register master xtal\n");
+
+	if (s3c24xx_register_clock(&clk_mpll) < 0)
+		printk(KERN_ERR "failed to register mpll clock\n");
+
+	if (s3c24xx_register_clock(&clk_upll) < 0)
+		printk(KERN_ERR "failed to register upll clock\n");
+
+	if (s3c24xx_register_clock(&clk_f) < 0)
+		printk(KERN_ERR "failed to register cpu fclk\n");
+
+	if (s3c24xx_register_clock(&clk_h) < 0)
+		printk(KERN_ERR "failed to register cpu hclk\n");
+
+	if (s3c24xx_register_clock(&clk_p) < 0)
+		printk(KERN_ERR "failed to register cpu pclk\n");
+
+	return 0;
+}
+
diff --git a/arch/arm/plat-s3c/dev-fb.c b/arch/arm/plat-samsung/dev-fb.c
similarity index 100%
rename from arch/arm/plat-s3c/dev-fb.c
rename to arch/arm/plat-samsung/dev-fb.c
diff --git a/arch/arm/plat-s3c/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c
similarity index 100%
rename from arch/arm/plat-s3c/dev-hsmmc.c
rename to arch/arm/plat-samsung/dev-hsmmc.c
diff --git a/arch/arm/plat-s3c/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c
similarity index 100%
rename from arch/arm/plat-s3c/dev-hsmmc1.c
rename to arch/arm/plat-samsung/dev-hsmmc1.c
diff --git a/arch/arm/plat-s3c/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c
similarity index 100%
rename from arch/arm/plat-s3c/dev-hsmmc2.c
rename to arch/arm/plat-samsung/dev-hsmmc2.c
diff --git a/arch/arm/plat-s3c/dev-i2c0.c b/arch/arm/plat-samsung/dev-i2c0.c
similarity index 100%
rename from arch/arm/plat-s3c/dev-i2c0.c
rename to arch/arm/plat-samsung/dev-i2c0.c
diff --git a/arch/arm/plat-s3c/dev-i2c1.c b/arch/arm/plat-samsung/dev-i2c1.c
similarity index 100%
rename from arch/arm/plat-s3c/dev-i2c1.c
rename to arch/arm/plat-samsung/dev-i2c1.c
diff --git a/arch/arm/plat-s3c/dev-nand.c b/arch/arm/plat-samsung/dev-nand.c
similarity index 100%
rename from arch/arm/plat-s3c/dev-nand.c
rename to arch/arm/plat-samsung/dev-nand.c
diff --git a/arch/arm/plat-samsung/dev-uart.c b/arch/arm/plat-samsung/dev-uart.c
new file mode 100644
index 0000000..3776cd9
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-uart.c
@@ -0,0 +1,44 @@
+/* linux/arch/arm/plat-samsung/dev-uart.c
+ *	originally from arch/arm/plat-s3c24xx/devs.c
+ *x
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Base S3C24XX platform device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+/* uart devices */
+
+static struct platform_device s3c24xx_uart_device0 = {
+	.id		= 0,
+};
+
+static struct platform_device s3c24xx_uart_device1 = {
+	.id		= 1,
+};
+
+static struct platform_device s3c24xx_uart_device2 = {
+	.id		= 2,
+};
+
+static struct platform_device s3c24xx_uart_device3 = {
+	.id		= 3,
+};
+
+struct platform_device *s3c24xx_uart_src[4] = {
+	&s3c24xx_uart_device0,
+	&s3c24xx_uart_device1,
+	&s3c24xx_uart_device2,
+	&s3c24xx_uart_device3,
+};
+
+struct platform_device *s3c24xx_uart_devs[4] = {
+};
diff --git a/arch/arm/plat-samsung/dev-usb-hsotg.c b/arch/arm/plat-samsung/dev-usb-hsotg.c
new file mode 100644
index 0000000..33a844a
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-usb-hsotg.c
@@ -0,0 +1,48 @@
+/* linux/arch/arm/plat-s3c/dev-usb-hsotg.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C series device definition for USB high-speed UDC/OtG block
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+
+static struct resource s3c_usb_hsotg_resources[] = {
+	[0] = {
+		.start	= S3C_PA_USB_HSOTG,
+		.end	= S3C_PA_USB_HSOTG + 0x10000 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_OTG,
+		.end	= IRQ_OTG,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 s3c_hsotg_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device s3c_device_usb_hsotg = {
+	.name		= "s3c-hsotg",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(s3c_usb_hsotg_resources),
+	.resource	= s3c_usb_hsotg_resources,
+	.dev		= {
+		.dma_mask		= &s3c_hsotg_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
diff --git a/arch/arm/plat-samsung/dev-usb.c b/arch/arm/plat-samsung/dev-usb.c
new file mode 100644
index 0000000..8816565
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-usb.c
@@ -0,0 +1,69 @@
+/* linux/arch/arm/plat-s3c/dev-usb.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C series device definition for USB host
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+#include <plat/usb-control.h>
+
+static struct resource s3c_usb_resource[] = {
+	[0] = {
+		.start = S3C_PA_USBHOST,
+		.end   = S3C_PA_USBHOST + 0x100 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBH,
+		.end   = IRQ_USBH,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static u64 s3c_device_usb_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_ohci = {
+	.name		  = "s3c2410-ohci",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_usb_resource),
+	.resource	  = s3c_usb_resource,
+	.dev              = {
+		.dma_mask = &s3c_device_usb_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+
+EXPORT_SYMBOL(s3c_device_ohci);
+
+/**
+ * s3c_ohci_set_platdata - initialise OHCI device platform data
+ * @info: The platform data.
+ *
+ * This call copies the @info passed in and sets the device .platform_data
+ * field to that copy. The @info is copied so that the original can be marked
+ * __initdata.
+ */
+void __init s3c_ohci_set_platdata(struct s3c2410_hcd_info *info)
+{
+	struct s3c2410_hcd_info *npd;
+
+	npd = kmemdup(info, sizeof(struct s3c2410_hcd_info), GFP_KERNEL);
+	if (!npd)
+		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+
+	s3c_device_ohci.dev.platform_data = npd;
+}
diff --git a/arch/arm/plat-samsung/dma.c b/arch/arm/plat-samsung/dma.c
new file mode 100644
index 0000000..cb459dd
--- /dev/null
+++ b/arch/arm/plat-samsung/dma.c
@@ -0,0 +1,84 @@
+/* linux/arch/arm/plat-samsung/dma.c
+ *
+ * Copyright (c) 2003-2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C DMA core
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct s3c2410_dma_buf;
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+
+#include <mach/dma.h>
+#include <mach/irqs.h>
+
+/* dma channel state information */
+struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
+struct s3c2410_dma_chan *s3c_dma_chan_map[DMACH_MAX];
+
+/* s3c_dma_lookup_channel
+ *
+ * change the dma channel number given into a real dma channel id
+*/
+
+struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel)
+{
+	if (channel & DMACH_LOW_LEVEL)
+		return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
+	else
+		return s3c_dma_chan_map[channel];
+}
+
+/* do we need to protect the settings of the fields from
+ * irq?
+*/
+
+int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
+
+	chan->op_fn = rtn;
+
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_set_opfn);
+
+int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
+
+	chan->callback_fn = rtn;
+
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
+
+int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
+{
+	struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	chan->flags = flags;
+	return 0;
+}
+EXPORT_SYMBOL(s3c2410_dma_setflags);
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c
new file mode 100644
index 0000000..44a84e8
--- /dev/null
+++ b/arch/arm/plat-samsung/gpio-config.c
@@ -0,0 +1,166 @@
+/* linux/arch/arm/plat-s3c/gpio-config.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C series GPIO configuration core
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
+{
+	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+	unsigned long flags;
+	int offset;
+	int ret;
+
+	if (!chip)
+		return -EINVAL;
+
+	offset = pin - chip->chip.base;
+
+	local_irq_save(flags);
+	ret = s3c_gpio_do_setcfg(chip, offset, config);
+	local_irq_restore(flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_cfgpin);
+
+int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
+{
+	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+	unsigned long flags;
+	int offset, ret;
+
+	if (!chip)
+		return -EINVAL;
+
+	offset = pin - chip->chip.base;
+
+	local_irq_save(flags);
+	ret = s3c_gpio_do_setpull(chip, offset, pull);
+	local_irq_restore(flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_setpull);
+
+#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
+int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip,
+				  unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = off;
+	u32 con;
+
+	if (s3c_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+
+		/* Map output to 0, and SFN2 to 1 */
+		cfg -= 1;
+		if (cfg > 1)
+			return -EINVAL;
+
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0x1 << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+
+int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
+			    unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = off * 2;
+	u32 con;
+
+	if (s3c_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+		if (cfg > 3)
+			return -EINVAL;
+
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0x3 << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
+int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
+				 unsigned int off, unsigned int cfg)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = (off & 7) * 4;
+	u32 con;
+
+	if (off < 8 && chip->chip.ngpio > 8)
+		reg -= 4;
+
+	if (s3c_gpio_is_cfg_special(cfg)) {
+		cfg &= 0xf;
+		cfg <<= shift;
+	}
+
+	con = __raw_readl(reg);
+	con &= ~(0xf << shift);
+	con |= cfg;
+	__raw_writel(con, reg);
+
+	return 0;
+}
+#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
+
+#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
+int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
+			    unsigned int off, s3c_gpio_pull_t pull)
+{
+	void __iomem *reg = chip->base + 0x08;
+	int shift = off * 2;
+	u32 pup;
+
+	pup = __raw_readl(reg);
+	pup &= ~(3 << shift);
+	pup |= pull << shift;
+	__raw_writel(pup, reg);
+
+	return 0;
+}
+
+s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
+					unsigned int off)
+{
+	void __iomem *reg = chip->base + 0x08;
+	int shift = off * 2;
+	u32 pup = __raw_readl(reg);
+
+	pup >>= shift;
+	pup &= 0x3;
+	return (__force s3c_gpio_pull_t)pup;
+}
+#endif
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c
new file mode 100644
index 0000000..28d2ab8
--- /dev/null
+++ b/arch/arm/plat-samsung/gpio.c
@@ -0,0 +1,156 @@
+/* linux/arch/arm/plat-s3c/gpio.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C series GPIO core
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-core.h>
+
+#ifdef CONFIG_S3C_GPIO_TRACK
+struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
+
+static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
+{
+	unsigned int gpn;
+	int i;
+
+	gpn = chip->chip.base;
+	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
+		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
+		s3c_gpios[gpn] = chip;
+	}
+}
+#endif /* CONFIG_S3C_GPIO_TRACK */
+
+/* Default routines for controlling GPIO, based on the original S3C24XX
+ * GPIO functions which deal with the case where each gpio bank of the
+ * chip is as following:
+ *
+ * base + 0x00: Control register, 2 bits per gpio
+ *	        gpio n: 2 bits starting at (2*n)
+ *		00 = input, 01 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *		bit n: data bit n
+*/
+
+static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long con;
+
+	local_irq_save(flags);
+
+	con = __raw_readl(base + 0x00);
+	con &= ~(3 << (offset * 2));
+
+	__raw_writel(con, base + 0x00);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+static int s3c_gpiolib_output(struct gpio_chip *chip,
+			      unsigned offset, int value)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long dat;
+	unsigned long con;
+
+	local_irq_save(flags);
+
+	dat = __raw_readl(base + 0x04);
+	dat &= ~(1 << offset);
+	if (value)
+		dat |= 1 << offset;
+	__raw_writel(dat, base + 0x04);
+
+	con = __raw_readl(base + 0x00);
+	con &= ~(3 << (offset * 2));
+	con |= 1 << (offset * 2);
+
+	__raw_writel(con, base + 0x00);
+	__raw_writel(dat, base + 0x04);
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+static void s3c_gpiolib_set(struct gpio_chip *chip,
+			    unsigned offset, int value)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long dat;
+
+	local_irq_save(flags);
+
+	dat = __raw_readl(base + 0x04);
+	dat &= ~(1 << offset);
+	if (value)
+		dat |= 1 << offset;
+	__raw_writel(dat, base + 0x04);
+
+	local_irq_restore(flags);
+}
+
+static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	unsigned long val;
+
+	val = __raw_readl(ourchip->base + 0x04);
+	val >>= offset;
+	val &= 1;
+
+	return val;
+}
+
+__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
+{
+	struct gpio_chip *gc = &chip->chip;
+	int ret;
+
+	BUG_ON(!chip->base);
+	BUG_ON(!gc->label);
+	BUG_ON(!gc->ngpio);
+
+	if (!gc->direction_input)
+		gc->direction_input = s3c_gpiolib_input;
+	if (!gc->direction_output)
+		gc->direction_output = s3c_gpiolib_output;
+	if (!gc->set)
+		gc->set = s3c_gpiolib_set;
+	if (!gc->get)
+		gc->get = s3c_gpiolib_get;
+
+#ifdef CONFIG_PM
+	if (chip->pm != NULL) {
+		if (!chip->pm->save || !chip->pm->resume)
+			printk(KERN_ERR "gpio: %s has missing PM functions\n",
+			       gc->label);
+	} else
+		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+#endif
+
+	/* gpiochip_add() prints own failure message on error. */
+	ret = gpiochip_add(gc);
+	if (ret >= 0)
+		s3c_gpiolib_track(chip);
+}
diff --git a/arch/arm/plat-samsung/gpiolib.c b/arch/arm/plat-samsung/gpiolib.c
new file mode 100644
index 0000000..8a8ba8b
--- /dev/null
+++ b/arch/arm/plat-samsung/gpiolib.c
@@ -0,0 +1,199 @@
+/* arch/arm/plat-samsung/gpiolib.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * SAMSUNG - GPIOlib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <mach/gpio.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+#ifndef DEBUG_GPIO
+#define gpio_dbg(x...) do { } while (0)
+#else
+#define gpio_dbg(x...) printk(KERN_DEBUG x)
+#endif
+
+/* The samsung_gpiolib_4bit routines are to control the gpio banks where
+ * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
+ * following example:
+ *
+ * base + 0x00: Control register, 4 bits per gpio
+ *		gpio n: 4 bits starting at (4*n)
+ *		0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *		bit n: data bit n
+ *
+ * Note, since the data register is one bit per gpio and is at base + 0x4
+ * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
+ * the output.
+*/
+
+static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
+				      unsigned int offset)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long con;
+
+	con = __raw_readl(base + GPIOCON_OFF);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, base + GPIOCON_OFF);
+
+	gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+
+	return 0;
+}
+
+static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
+				       unsigned int offset, int value)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long con;
+	unsigned long dat;
+
+	con = __raw_readl(base + GPIOCON_OFF);
+	con &= ~(0xf << con_4bit_shift(offset));
+	con |= 0x1 << con_4bit_shift(offset);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+
+	if (value)
+		dat |= 1 << offset;
+	else
+		dat &= ~(1 << offset);
+
+	__raw_writel(dat, base + GPIODAT_OFF);
+	__raw_writel(con, base + GPIOCON_OFF);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+	return 0;
+}
+
+/* The next set of routines are for the case where the GPIO configuration
+ * registers are 4 bits per GPIO but there is more than one register (the
+ * bank has more than 8 GPIOs.
+ *
+ * This case is the similar to the 4 bit case, but the registers are as
+ * follows:
+ *
+ * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
+ *		gpio n: 4 bits starting at (4*n)
+ *		0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
+ *		gpio n: 4 bits starting at (4*n)
+ *		0000 = input, 0001 = output, others mean special-function
+ * base + 0x08: Data register, 1 bit per gpio
+ *		bit n: data bit n
+ *
+ * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
+ * store the 'base + 0x4' address so that these routines see the data
+ * register at ourchip->base + 0x04.
+ */
+
+static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
+				       unsigned int offset)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+
+	if (offset > 7)
+		offset -= 8;
+	else
+		regcon -= 4;
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(offset));
+	__raw_writel(con, regcon);
+
+	gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+
+	return 0;
+}
+
+static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
+					unsigned int offset, int value)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	void __iomem *regcon = base;
+	unsigned long con;
+	unsigned long dat;
+	unsigned con_offset = offset;
+
+	if (con_offset > 7)
+		con_offset -= 8;
+	else
+		regcon -= 4;
+
+	con = __raw_readl(regcon);
+	con &= ~(0xf << con_4bit_shift(con_offset));
+	con |= 0x1 << con_4bit_shift(con_offset);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+
+	if (value)
+		dat |= 1 << offset;
+	else
+		dat &= ~(1 << offset);
+
+	__raw_writel(dat, base + GPIODAT_OFF);
+	__raw_writel(con, regcon);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+	return 0;
+}
+
+void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
+{
+	chip->chip.direction_input = samsung_gpiolib_4bit_input;
+	chip->chip.direction_output = samsung_gpiolib_4bit_output;
+	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
+}
+
+void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
+{
+	chip->chip.direction_input = samsung_gpiolib_4bit2_input;
+	chip->chip.direction_output = samsung_gpiolib_4bit2_output;
+	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
+}
+
+void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
+					   int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chip++) {
+		samsung_gpiolib_add_4bit(chip);
+		s3c_gpiolib_add(chip);
+	}
+}
+
+void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
+					    int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chip++) {
+		samsung_gpiolib_add_4bit2(chip);
+		s3c_gpiolib_add(chip);
+	}
+}
diff --git a/arch/arm/plat-samsung/include/plat/adc.h b/arch/arm/plat-samsung/include/plat/adc.h
new file mode 100644
index 0000000..e8382c7
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/adc.h
@@ -0,0 +1,35 @@
+/* arch/arm/plat-samsung/include/plat/adc.h
+ *
+ * Copyright (c) 2008 Simtec Electronics
+ *	http://armlinux.simnte.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C ADC driver information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_ADC_H
+#define __ASM_PLAT_ADC_H __FILE__
+
+struct s3c_adc_client;
+
+extern int s3c_adc_start(struct s3c_adc_client *client,
+			 unsigned int channel, unsigned int nr_samples);
+
+extern int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch);
+
+extern struct s3c_adc_client *
+	s3c_adc_register(struct platform_device *pdev,
+			 void (*select)(struct s3c_adc_client *client,
+					unsigned selected),
+			 void (*conv)(struct s3c_adc_client *client,
+				      unsigned d0, unsigned d1,
+				      unsigned *samples_left),
+			 unsigned int is_ts);
+
+extern void s3c_adc_release(struct s3c_adc_client *client);
+
+#endif /* __ASM_PLAT_ADC_H */
diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h
new file mode 100644
index 0000000..e32f9ed
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/audio.h
@@ -0,0 +1,25 @@
+/* arch/arm/plat-samsung/include/plat/audio.h
+ *
+ * Copyright (c) 2009 Samsung Electronics Co. Ltd
+ * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* The machine init code calls s3c*_ac97_setup_gpio with
+ * one of these defines in order to select appropriate bank
+ * of GPIO for AC97 pins
+ */
+#define S3C64XX_AC97_GPD  0
+#define S3C64XX_AC97_GPE  1
+extern void s3c64xx_ac97_setup_gpio(int);
+
+/**
+ * struct s3c_audio_pdata - common platform data for audio device drivers
+ * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode
+ */
+struct s3c_audio_pdata {
+	int (*cfg_gpio)(struct platform_device *);
+};
diff --git a/arch/arm/plat-samsung/include/plat/clock-clksrc.h b/arch/arm/plat-samsung/include/plat/clock-clksrc.h
new file mode 100644
index 0000000..50a8ca7
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/clock-clksrc.h
@@ -0,0 +1,83 @@
+/* linux/arch/arm/plat-samsung/include/plat/clock-clksrc.h
+ *
+ * Parts taken from arch/arm/plat-s3c64xx/clock.c
+ *	Copyright 2008 Openmoko, Inc.
+ *	Copyright 2008 Simtec Electronics
+ *		Ben Dooks <ben@simtec.co.uk>
+ *		http://armlinux.simtec.co.uk/
+ *
+ * Copyright 2009 Ben Dooks <ben-linux@fluff.org>
+ * Copyright 2009 Harald Welte
+ *
+ * This program is free software; you can 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 clksrc_sources - list of sources for a given clock
+ * @sources: array of pointers to clocks
+ * @nr_sources: The size of @sources
+ */
+struct clksrc_sources {
+	unsigned int	nr_sources;
+	struct clk	**sources;
+};
+
+/**
+ * struct clksrc_reg - register definition for clock control bits
+ * @reg: pointer to the register in virtual memory.
+ * @shift: the shift in bits to where the bitfield is.
+ * @size: the size in bits of the bitfield.
+ *
+ * This specifies the size and position of the bits we are interested
+ * in within the register specified by @reg.
+ */
+struct clksrc_reg {
+	void __iomem		*reg;
+	unsigned short		shift;
+	unsigned short		size;
+};
+
+/**
+ * struct clksrc_clk - class of clock for newer style samsung devices.
+ * @clk: the standard clock representation
+ * @sources: the sources for this clock
+ * @reg_src: the register definition for selecting the clock's source
+ * @reg_div: the register definition for the clock's output divisor
+ *
+ * This clock implements the features required by the newer SoCs where
+ * the standard clock block provides an input mux and a post-mux divisor
+ * to provide the periperhal's clock.
+ *
+ * The array of @sources provides the mapping of mux position to the
+ * clock, and @reg_src shows the code where to modify to change the mux
+ * position. The @reg_div defines how to change the divider settings on
+ * the output.
+ */
+struct clksrc_clk {
+	struct clk		clk;
+	struct clksrc_sources	*sources;
+
+	struct clksrc_reg	reg_src;
+	struct clksrc_reg	reg_div;
+};
+
+/**
+ * s3c_set_clksrc() - setup the clock from the register settings
+ * @clk: The clock to setup.
+ * @announce: true to announce the setting to printk().
+ *
+ * Setup the clock from the current register settings, for when the
+ * kernel boots or if it is resuming from a possibly unknown state.
+ */
+extern void s3c_set_clksrc(struct clksrc_clk *clk, bool announce);
+
+/**
+ * s3c_register_clksrc() register clocks from an array of clksrc clocks
+ * @srcs: The array of clocks to register
+ * @size: The size of the @srcs array.
+ *
+ * Initialise and register the array of clocks described by @srcs.
+ */
+extern void s3c_register_clksrc(struct clksrc_clk *srcs, int size);
diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h
new file mode 100644
index 0000000..60b6269
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/clock.h
@@ -0,0 +1,115 @@
+/* linux/arch/arm/plat-s3c/include/plat/clock.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	http://www.simtec.co.uk/products/SWLINUX/
+ *	Written by Ben Dooks, <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/spinlock.h>
+
+struct clk;
+
+/**
+ * struct clk_ops - standard clock operations
+ * @set_rate: set the clock rate, see clk_set_rate().
+ * @get_rate: get the clock rate, see clk_get_rate().
+ * @round_rate: round a given clock rate, see clk_round_rate().
+ * @set_parent: set the clock's parent, see clk_set_parent().
+ *
+ * Group the common clock implementations together so that we
+ * don't have to keep setting the same fiels again. We leave
+ * enable in struct clk.
+ *
+ * Adding an extra layer of indirection into the process should
+ * not be a problem as it is unlikely these operations are going
+ * to need to be called quickly.
+ */
+struct clk_ops {
+	int		    (*set_rate)(struct clk *c, unsigned long rate);
+	unsigned long	    (*get_rate)(struct clk *c);
+	unsigned long	    (*round_rate)(struct clk *c, unsigned long rate);
+	int		    (*set_parent)(struct clk *c, struct clk *parent);
+};
+
+struct clk {
+	struct list_head      list;
+	struct module        *owner;
+	struct clk           *parent;
+	const char           *name;
+	int		      id;
+	int		      usage;
+	unsigned long         rate;
+	unsigned long         ctrlbit;
+
+	struct clk_ops		*ops;
+	int		    (*enable)(struct clk *, int enable);
+};
+
+/* other clocks which may be registered by board support */
+
+extern struct clk s3c24xx_dclk0;
+extern struct clk s3c24xx_dclk1;
+extern struct clk s3c24xx_clkout0;
+extern struct clk s3c24xx_clkout1;
+extern struct clk s3c24xx_uclk;
+
+extern struct clk clk_usb_bus;
+
+/* core clock support */
+
+extern struct clk clk_f;
+extern struct clk clk_h;
+extern struct clk clk_p;
+extern struct clk clk_mpll;
+extern struct clk clk_upll;
+extern struct clk clk_epll;
+extern struct clk clk_xtal;
+extern struct clk clk_ext;
+
+/* S3C64XX specific clocks */
+extern struct clk clk_h2;
+extern struct clk clk_27m;
+extern struct clk clk_48m;
+
+extern int clk_default_setrate(struct clk *clk, unsigned long rate);
+extern struct clk_ops clk_ops_def_setrate;
+
+/* exports for arch/arm/mach-s3c2410
+ *
+ * Please DO NOT use these outside of arch/arm/mach-s3c2410
+*/
+
+extern spinlock_t clocks_lock;
+
+extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
+
+extern int s3c24xx_register_clock(struct clk *clk);
+extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks);
+
+extern void s3c_register_clocks(struct clk *clk, int nr_clks);
+
+extern int s3c24xx_register_baseclocks(unsigned long xtal);
+
+extern void s5p_register_clocks(unsigned long xtal_freq);
+
+extern void s3c24xx_setup_clocks(unsigned long fclk,
+				 unsigned long hclk,
+				 unsigned long pclk);
+
+extern void s3c2410_setup_clocks(void);
+extern void s3c2412_setup_clocks(void);
+extern void s3c244x_setup_clocks(void);
+extern void s3c2443_setup_clocks(void);
+
+/* S3C64XX specific functions and clocks */
+
+extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable);
+
+/* Init for pwm clock code */
+
+extern void s3c_pwmclk_init(void);
+
diff --git a/arch/arm/plat-samsung/include/plat/cpu-freq.h b/arch/arm/plat-samsung/include/plat/cpu-freq.h
new file mode 100644
index 0000000..80c4a80
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/cpu-freq.h
@@ -0,0 +1,145 @@
+/* arch/arm/plat-samsung/include/plat/cpu-freq.h
+ *
+ * Copyright (c) 2006-2007 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C CPU frequency scaling support - driver and board
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/cpufreq.h>
+
+struct s3c_cpufreq_info;
+struct s3c_cpufreq_board;
+struct s3c_iotimings;
+
+/**
+ * struct s3c_freq - frequency information (mainly for core drivers)
+ * @fclk: The FCLK frequency in Hz.
+ * @armclk: The ARMCLK frequency in Hz.
+ * @hclk_tns: HCLK cycle time in 10ths of nano-seconds.
+ * @hclk: The HCLK frequency in Hz.
+ * @pclk: The PCLK frequency in Hz.
+ *
+ * This contains the frequency information about the current configuration
+ * mainly for the core drivers to ensure we do not end up passing about
+ * a large number of parameters.
+ *
+ * The @hclk_tns field is a useful cache for the parts of the drivers that
+ * need to calculate IO timings and suchlike.
+ */
+struct s3c_freq {
+	unsigned long	fclk;
+	unsigned long	armclk;
+	unsigned long	hclk_tns;	/* in 10ths of ns */
+	unsigned long	hclk;
+	unsigned long	pclk;
+};
+
+/**
+ * struct s3c_cpufreq_freqs - s3c cpufreq notification information.
+ * @freqs: The cpufreq setting information.
+ * @old: The old clock settings.
+ * @new: The new clock settings.
+ * @pll_changing: Set if the PLL is changing.
+ *
+ * Wrapper 'struct cpufreq_freqs' so that any drivers receiving the
+ * notification can use this information that is not provided by just
+ * having the core frequency alone.
+ *
+ * The pll_changing flag is used to indicate if the PLL itself is
+ * being set during this change. This is important as the clocks
+ * will temporarily be set to the XTAL clock during this time, so
+ * drivers may want to close down their output during this time.
+ *
+ * Note, this is not being used by any current drivers and therefore
+ * may be removed in the future.
+ */
+struct s3c_cpufreq_freqs {
+	struct cpufreq_freqs	freqs;
+	struct s3c_freq		old;
+	struct s3c_freq		new;
+
+	unsigned int		pll_changing:1;
+};
+
+#define to_s3c_cpufreq(_cf) container_of(_cf, struct s3c_cpufreq_freqs, freqs)
+
+/**
+ * struct s3c_clkdivs - clock divisor information
+ * @p_divisor: Divisor from FCLK to PCLK.
+ * @h_divisor: Divisor from FCLK to HCLK.
+ * @arm_divisor: Divisor from FCLK to ARMCLK (not all CPUs).
+ * @dvs: Non-zero if using DVS mode for ARMCLK.
+ *
+ * Divisor settings for the core clocks.
+ */
+struct s3c_clkdivs {
+	int		p_divisor;
+	int		h_divisor;
+	int		arm_divisor;
+	unsigned char	dvs;
+};
+
+#define PLLVAL(_m, _p, _s) (((_m) << 12) | ((_p) << 4) | (_s))
+
+/**
+ * struct s3c_pllval - PLL value entry.
+ * @freq: The frequency for this entry in Hz.
+ * @pll_reg: The PLL register setting for this PLL value.
+ */
+struct s3c_pllval {
+	unsigned long		freq;
+	unsigned long		pll_reg;
+};
+
+/**
+ * struct s3c_cpufreq_board - per-board cpu frequency informatin
+ * @refresh: The SDRAM refresh period in nanoseconds.
+ * @auto_io: Set if the IO timing settings should be generated from the
+ *	initialisation time hardware registers.
+ * @need_io: Set if the board has external IO on any of the chipselect
+ *	lines that will require the hardware timing registers to be
+ *	updated on a clock change.
+ * @max: The maxium frequency limits for the system. Any field that
+ *	is left at zero will use the CPU's settings.
+ *
+ * This contains the board specific settings that affect how the CPU
+ * drivers chose settings. These include the memory refresh and IO
+ * timing information.
+ *
+ * Registration depends on the driver being used, the ARMCLK only
+ * implementation does not currently need this but the older style
+ * driver requires this to be available.
+ */
+struct s3c_cpufreq_board {
+	unsigned int	refresh;
+	unsigned int	auto_io:1;	/* automatically init io timings. */
+	unsigned int	need_io:1;	/* set if needs io timing support. */
+
+	/* any non-zero field in here is taken as an upper limit. */
+	struct s3c_freq	max;	/* frequency limits */
+};
+
+/* Things depending on frequency scaling. */
+#ifdef CONFIG_CPU_FREQ_S3C
+#define __init_or_cpufreq
+#else
+#define __init_or_cpufreq __init
+#endif
+
+/* Board functions */
+
+#ifdef CONFIG_CPU_FREQ_S3C
+extern int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board);
+#else
+
+static inline int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board)
+{
+	return 0;
+}
+#endif  /* CONFIG_CPU_FREQ_S3C */
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
new file mode 100644
index 0000000..d316b4a
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -0,0 +1,84 @@
+/* linux/arch/arm/plat-samsung/include/plat/cpu.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C24XX CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* todo - fix when rmk changes iodescs to use `void __iomem *` */
+
+#ifndef __SAMSUNG_PLAT_CPU_H
+#define __SAMSUNG_PLAT_CPU_H
+
+#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#define print_mhz(m) ((m) / MHZ), (((m) / 1000) % 1000)
+
+/* forward declaration */
+struct s3c24xx_uart_resources;
+struct platform_device;
+struct s3c2410_uartcfg;
+struct map_desc;
+
+/* per-cpu initialisation function table. */
+
+struct cpu_table {
+	unsigned long	idcode;
+	unsigned long	idmask;
+	void		(*map_io)(void);
+	void		(*init_uarts)(struct s3c2410_uartcfg *cfg, int no);
+	void		(*init_clocks)(int xtal);
+	int		(*init)(void);
+	const char	*name;
+};
+
+extern void s3c_init_cpu(unsigned long idcode,
+			 struct cpu_table *cpus, unsigned int cputab_size);
+
+/* core initialisation functions */
+
+extern void s3c24xx_init_irq(void);
+extern void s3c64xx_init_irq(u32 vic0, u32 vic1);
+extern void s5p_init_irq(u32 *vic, u32 num_vic);
+
+extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
+extern void s3c64xx_init_io(struct map_desc *mach_desc, int size);
+extern void s5p_init_io(struct map_desc *mach_desc,
+			int size, void __iomem *cpuid_addr);
+
+extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c24xx_init_clocks(int xtal);
+
+extern void s3c24xx_init_uartdevs(char *name,
+				  struct s3c24xx_uart_resources *res,
+				  struct s3c2410_uartcfg *cfg, int no);
+
+/* timer for 2410/2440 */
+
+struct sys_timer;
+extern struct sys_timer s3c24xx_timer;
+
+/* system device classes */
+
+extern struct sysdev_class s3c2410_sysclass;
+extern struct sysdev_class s3c2410a_sysclass;
+extern struct sysdev_class s3c2412_sysclass;
+extern struct sysdev_class s3c2440_sysclass;
+extern struct sysdev_class s3c2442_sysclass;
+extern struct sysdev_class s3c2443_sysclass;
+extern struct sysdev_class s3c6410_sysclass;
+extern struct sysdev_class s3c64xx_sysclass;
+
+extern void (*s5pc1xx_idle)(void);
+
+#endif
diff --git a/arch/arm/plat-samsung/include/plat/debug-macro.S b/arch/arm/plat-samsung/include/plat/debug-macro.S
new file mode 100644
index 0000000..dc6efd9
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/debug-macro.S
@@ -0,0 +1,87 @@
+/* arch/arm/plat-samsung/include/plat/debug-macro.S
+ *
+ * Copyright 2005, 2007 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <plat/regs-serial.h>
+
+/* The S5PV210/S5PC110 and S5P6442 implementations are as belows. */
+
+	.macro fifo_level_s5pv210 rd, rx
+		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		and	\rd, \rd, #S5PV210_UFSTAT_TXMASK
+	.endm
+
+	.macro  fifo_full_s5pv210 rd, rx
+		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		tst	\rd, #S5PV210_UFSTAT_TXFULL
+	.endm
+
+/* The S3C2440 implementations are used by default as they are the
+ * most widely re-used */
+
+	.macro fifo_level_s3c2440 rd, rx
+		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		and	\rd, \rd, #S3C2440_UFSTAT_TXMASK
+	.endm
+
+#ifndef fifo_level
+#define fifo_level fifo_level_s3c2440
+#endif
+
+	.macro  fifo_full_s3c2440 rd, rx
+		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		tst	\rd, #S3C2440_UFSTAT_TXFULL
+	.endm
+
+#ifndef fifo_full
+#define fifo_full fifo_full_s3c2440
+#endif
+
+	.macro	senduart,rd,rx
+		strb 	\rd, [\rx, # S3C2410_UTXH ]
+	.endm
+
+	.macro	busyuart, rd, rx
+		ldr	\rd, [ \rx, # S3C2410_UFCON ]
+		tst	\rd, #S3C2410_UFCON_FIFOMODE	@ fifo enabled?
+		beq	1001f				@
+		@ FIFO enabled...
+1003:
+		fifo_full \rd, \rx
+		bne	1003b
+		b	1002f
+
+1001:
+		@ busy waiting for non fifo
+		ldr	\rd, [ \rx, # S3C2410_UTRSTAT ]
+		tst	\rd, #S3C2410_UTRSTAT_TXFE
+		beq	1001b
+
+1002:		@ exit busyuart
+	.endm
+
+	.macro	waituart,rd,rx
+		ldr	\rd, [ \rx, # S3C2410_UFCON ]
+		tst	\rd, #S3C2410_UFCON_FIFOMODE	@ fifo enabled?
+		beq	1001f				@
+		@ FIFO enabled...
+1003:
+		fifo_level \rd, \rx
+		teq	\rd, #0
+		bne	1003b
+		b	1002f
+1001:
+		@ idle waiting for non fifo
+		ldr	\rd, [ \rx, # S3C2410_UTRSTAT ]
+		tst	\rd, #S3C2410_UTRSTAT_TXFE
+		beq	1001b
+
+1002:		@ exit busyuart
+	.endm
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
new file mode 100644
index 0000000..796d242
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -0,0 +1,74 @@
+/* arch/arm/plat-samsung/include/plat/devs.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 standard platform devices
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/platform_device.h>
+
+struct s3c24xx_uart_resources {
+	struct resource		*resources;
+	unsigned long		 nr_resources;
+};
+
+extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
+extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
+extern struct s3c24xx_uart_resources s5p_uart_resources[];
+
+extern struct platform_device *s3c24xx_uart_devs[];
+extern struct platform_device *s3c24xx_uart_src[];
+
+extern struct platform_device s3c_device_timer[];
+
+extern struct platform_device s3c64xx_device_iis0;
+extern struct platform_device s3c64xx_device_iis1;
+extern struct platform_device s3c64xx_device_iisv4;
+
+extern struct platform_device s3c64xx_device_spi0;
+extern struct platform_device s3c64xx_device_spi1;
+
+extern struct platform_device s3c64xx_device_pcm0;
+extern struct platform_device s3c64xx_device_pcm1;
+
+extern struct platform_device s3c64xx_device_ac97;
+
+extern struct platform_device s3c_device_ts;
+
+extern struct platform_device s3c_device_fb;
+extern struct platform_device s3c_device_ohci;
+extern struct platform_device s3c_device_lcd;
+extern struct platform_device s3c_device_wdt;
+extern struct platform_device s3c_device_i2c0;
+extern struct platform_device s3c_device_i2c1;
+extern struct platform_device s3c_device_rtc;
+extern struct platform_device s3c_device_adc;
+extern struct platform_device s3c_device_sdi;
+extern struct platform_device s3c_device_iis;
+extern struct platform_device s3c_device_hwmon;
+extern struct platform_device s3c_device_hsmmc0;
+extern struct platform_device s3c_device_hsmmc1;
+extern struct platform_device s3c_device_hsmmc2;
+
+extern struct platform_device s3c_device_spi0;
+extern struct platform_device s3c_device_spi1;
+
+extern struct platform_device s3c_device_hwmon;
+
+extern struct platform_device s3c_device_nand;
+
+extern struct platform_device s3c_device_usbgadget;
+extern struct platform_device s3c_device_usb_hsotg;
+
+/* s3c2440 specific devices */
+
+#ifdef CONFIG_CPU_S3C2440
+
+extern struct platform_device s3c_device_camif;
+extern struct platform_device s3c_device_ac97;
+
+#endif
diff --git a/arch/arm/plat-s3c/include/plat/dma-core.h b/arch/arm/plat-samsung/include/plat/dma-core.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/dma-core.h
rename to arch/arm/plat-samsung/include/plat/dma-core.h
diff --git a/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
new file mode 100644
index 0000000..336d5ac
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
@@ -0,0 +1,84 @@
+/* linux/arch/arm/plat-samsung/include/plat/dma-s3c24xx.h
+ *
+ * Copyright (C) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C24XX DMA support - per SoC functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <plat/dma-core.h>
+
+extern struct sysdev_class dma_sysclass;
+extern struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
+
+#define DMA_CH_VALID		(1<<31)
+#define DMA_CH_NEVER		(1<<30)
+
+struct s3c24xx_dma_addr {
+	unsigned long		from;
+	unsigned long		to;
+};
+
+/* struct s3c24xx_dma_map
+ *
+ * this holds the mapping information for the channel selected
+ * to be connected to the specified device
+*/
+
+struct s3c24xx_dma_map {
+	const char		*name;
+	struct s3c24xx_dma_addr  hw_addr;
+
+	unsigned long		 channels[S3C_DMA_CHANNELS];
+	unsigned long		 channels_rx[S3C_DMA_CHANNELS];
+};
+
+struct s3c24xx_dma_selection {
+	struct s3c24xx_dma_map	*map;
+	unsigned long		 map_size;
+	unsigned long		 dcon_mask;
+
+	void	(*select)(struct s3c2410_dma_chan *chan,
+			  struct s3c24xx_dma_map *map);
+
+	void	(*direction)(struct s3c2410_dma_chan *chan,
+			     struct s3c24xx_dma_map *map,
+			     enum s3c2410_dmasrc dir);
+};
+
+extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
+
+/* struct s3c24xx_dma_order_ch
+ *
+ * channel map for one of the `enum dma_ch` dma channels. the list
+ * entry contains a set of low-level channel numbers, orred with
+ * DMA_CH_VALID, which are checked in the order in the array.
+*/
+
+struct s3c24xx_dma_order_ch {
+	unsigned int	list[S3C_DMA_CHANNELS];	/* list of channels */
+	unsigned int	flags;				/* flags */
+};
+
+/* struct s3c24xx_dma_order
+ *
+ * information provided by either the core or the board to give the
+ * dma system a hint on how to allocate channels
+*/
+
+struct s3c24xx_dma_order {
+	struct s3c24xx_dma_order_ch	channels[DMACH_MAX];
+};
+
+extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
+
+/* DMA init code, called from the cpu support code */
+
+extern int s3c2410_dma_init(void);
+
+extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
+			    unsigned int stride);
diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h
new file mode 100644
index 0000000..7584d75
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/dma.h
@@ -0,0 +1,127 @@
+/* arch/arm/plat-samsung/include/plat/dma.h
+ *
+ * Copyright (C) 2003-2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C DMA support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+enum s3c2410_dma_buffresult {
+	S3C2410_RES_OK,
+	S3C2410_RES_ERR,
+	S3C2410_RES_ABORT
+};
+
+enum s3c2410_dmasrc {
+	S3C2410_DMASRC_HW,		/* source is memory */
+	S3C2410_DMASRC_MEM		/* source is hardware */
+};
+
+/* enum s3c2410_chan_op
+ *
+ * operation codes passed to the DMA code by the user, and also used
+ * to inform the current channel owner of any changes to the system state
+*/
+
+enum s3c2410_chan_op {
+	S3C2410_DMAOP_START,
+	S3C2410_DMAOP_STOP,
+	S3C2410_DMAOP_PAUSE,
+	S3C2410_DMAOP_RESUME,
+	S3C2410_DMAOP_FLUSH,
+	S3C2410_DMAOP_TIMEOUT,		/* internal signal to handler */
+	S3C2410_DMAOP_STARTED,		/* indicate channel started */
+};
+
+struct s3c2410_dma_client {
+	char                *name;
+};
+
+struct s3c2410_dma_chan;
+
+/* s3c2410_dma_cbfn_t
+ *
+ * buffer callback routine type
+*/
+
+typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
+				   void *buf, int size,
+				   enum s3c2410_dma_buffresult result);
+
+typedef int  (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
+				   enum s3c2410_chan_op );
+
+
+
+/* s3c2410_dma_request
+ *
+ * request a dma channel exclusivley
+*/
+
+extern int s3c2410_dma_request(unsigned int channel,
+			       struct s3c2410_dma_client *, void *dev);
+
+
+/* s3c2410_dma_ctrl
+ *
+ * change the state of the dma channel
+*/
+
+extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op);
+
+/* s3c2410_dma_setflags
+ *
+ * set the channel's flags to a given state
+*/
+
+extern int s3c2410_dma_setflags(unsigned int channel,
+				unsigned int flags);
+
+/* s3c2410_dma_free
+ *
+ * free the dma channel (will also abort any outstanding operations)
+*/
+
+extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);
+
+/* s3c2410_dma_enqueue
+ *
+ * place the given buffer onto the queue of operations for the channel.
+ * The buffer must be allocated from dma coherent memory, or the Dcache/WB
+ * drained before the buffer is given to the DMA system.
+*/
+
+extern int s3c2410_dma_enqueue(unsigned int channel, void *id,
+			       dma_addr_t data, int size);
+
+/* s3c2410_dma_config
+ *
+ * configure the dma channel
+*/
+
+extern int s3c2410_dma_config(unsigned int channel, int xferunit);
+
+/* s3c2410_dma_devconfig
+ *
+ * configure the device we're talking to
+*/
+
+extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
+				 unsigned long devaddr);
+
+/* s3c2410_dma_getposition
+ *
+ * get the position that the dma transfer is currently at
+*/
+
+extern int s3c2410_dma_getposition(unsigned int channel,
+				   dma_addr_t *src, dma_addr_t *dest);
+
+extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
+extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
+
+
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h
new file mode 100644
index 0000000..ffc01a7
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/fb.h
@@ -0,0 +1,80 @@
+/* arch/arm/plat-samsung/include/plat/fb.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C - FB platform data definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_S3C_FB_H
+#define __PLAT_S3C_FB_H __FILE__
+
+/**
+ * struct s3c_fb_pd_win - per window setup data
+ * @win_mode: The display parameters to initialise (not for window 0)
+ * @virtual_x: The virtual X size.
+ * @virtual_y: The virtual Y size.
+ */
+struct s3c_fb_pd_win {
+	struct fb_videomode	win_mode;
+
+	unsigned short		default_bpp;
+	unsigned short		max_bpp;
+	unsigned short		virtual_x;
+	unsigned short		virtual_y;
+};
+
+/**
+ * struct s3c_fb_platdata -  S3C driver platform specific information
+ * @setup_gpio: Setup the external GPIO pins to the right state to transfer
+ *		the data from the display system to the connected display
+ *		device.
+ * @vidcon0: The base vidcon0 values to control the panel data format.
+ * @vidcon1: The base vidcon1 values to control the panel data output.
+ * @win: The setup data for each hardware window, or NULL for unused.
+ * @display_mode: The LCD output display mode.
+ *
+ * The platform data supplies the video driver with all the information
+ * it requires to work with the display(s) attached to the machine. It
+ * controls the initial mode, the number of display windows (0 is always
+ * the base framebuffer) that are initialised etc.
+ *
+ */
+struct s3c_fb_platdata {
+	void	(*setup_gpio)(void);
+
+	struct s3c_fb_pd_win	*win[S3C_FB_MAX_WIN];
+
+	u32			 vidcon0;
+	u32			 vidcon1;
+};
+
+/**
+ * s3c_fb_set_platdata() - Setup the FB device with platform data.
+ * @pd: The platform data to set. The data is copied from the passed structure
+ *      so the machine data can mark the data __initdata so that any unused
+ *      machines will end up dumping their data at runtime.
+ */
+extern void s3c_fb_set_platdata(struct s3c_fb_platdata *pd);
+
+/**
+ * s3c64xx_fb_gpio_setup_24bpp() - S3C64XX setup function for 24bpp LCD
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
+ */
+extern void s3c64xx_fb_gpio_setup_24bpp(void);
+
+/**
+ * s5pc100_fb_gpio_setup_24bpp() - S5PC100 setup function for 24bpp LCD
+ *
+ * Initialise the GPIO for an 24bpp LCD display on the RGB interface.
+ */
+extern void s5pc100_fb_gpio_setup_24bpp(void);
+
+#endif /* __PLAT_S3C_FB_H */
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
new file mode 100644
index 0000000..dda19da
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
@@ -0,0 +1,176 @@
+/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg-helper.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C Platform - GPIO pin configuration helper definitions
+ *
+ * This program is free software; you can 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 meant for core cpu support, machine or other driver files
+ * should not be including this header.
+ */
+
+#ifndef __PLAT_GPIO_CFG_HELPERS_H
+#define __PLAT_GPIO_CFG_HELPERS_H __FILE__
+
+/* As a note, all gpio configuration functions are entered exclusively, either
+ * with the relevant lock held or the system prevented from doing anything else
+ * by disabling interrupts.
+*/
+
+static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip,
+				     unsigned int off, unsigned int config)
+{
+	return (chip->config->set_config)(chip, off, config);
+}
+
+static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
+				      unsigned int off, s3c_gpio_pull_t pull)
+{
+	return (chip->config->set_pull)(chip, off, pull);
+}
+
+/**
+ * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has two bits of configuration per gpio, which have the following
+ * functions:
+ *	00 = input
+ *	01 = output
+ *	1x = special function
+*/
+extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
+				   unsigned int off, unsigned int cfg);
+
+/**
+ * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register
+ * has one bit of configuration for the gpio, where setting the bit
+ * means the pin is in special function mode and unset means output.
+*/
+extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
+				     unsigned int off, unsigned int cfg);
+
+/**
+ * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @cfg: The configuration value to set.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ *	0000 = Input
+ *	0001 = Output
+ *	others = Special functions (dependant on bank)
+ *
+ * Note, since the code to deal with the case where there are two control
+ * registers instead of one, we do not have a separate set of functions for
+ * each case.
+*/
+extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
+					unsigned int off, unsigned int cfg);
+
+
+/* Pull-{up,down} resistor controls.
+ *
+ * S3C2410,S3C2440,S3C24A0 = Pull-UP,
+ * S3C2412,S3C2413 = Pull-Down
+ * S3C6400,S3C6410 = Pull-Both [None,Down,Up,Undef]
+ * S3C2443 = Pull-Both [not same as S3C6400]
+ */
+
+/**
+ * s3c_gpio_setpull_1up() - Pull configuration for choice of up or none.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @param: pull: The pull mode being requested.
+ *
+ * This is a helper function for the case where we have GPIOs with one
+ * bit configuring the presence of a pull-up resistor.
+ */
+extern int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
+				unsigned int off, s3c_gpio_pull_t pull);
+
+/**
+ * s3c_gpio_setpull_1down() - Pull configuration for choice of down or none
+ * @chip: The gpio chip that is being configured
+ * @off: The offset for the GPIO being configured
+ * @param: pull: The pull mode being requested
+ *
+ * This is a helper function for the case where we have GPIOs with one
+ * bit configuring the presence of a pull-down resistor.
+ */
+extern int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
+				  unsigned int off, s3c_gpio_pull_t pull);
+
+/**
+ * s3c_gpio_setpull_upown() - Pull configuration for choice of up, down or none
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @param: pull: The pull mode being requested.
+ *
+ * This is a helper function for the case where we have GPIOs with two
+ * bits configuring the presence of a pull resistor, in the following
+ * order:
+ *	00 = No pull resistor connected
+ *	01 = Pull-up resistor connected
+ *	10 = Pull-down resistor connected
+ */
+extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
+				   unsigned int off, s3c_gpio_pull_t pull);
+
+
+/**
+ * s3c_gpio_getpull_updown() - Get configuration for choice of up, down or none
+ * @chip: The gpio chip that the GPIO pin belongs to
+ * @off: The offset to the pin to get the configuration of.
+ *
+ * This helper function reads the state of the pull-{up,down} resistor for the
+ * given GPIO in the same case as s3c_gpio_setpull_upown.
+*/
+extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
+					       unsigned int off);
+
+/**
+ * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ * @param: pull: The pull mode being requested.
+ *
+ * This is a helper function for the case where we have GPIOs with two
+ * bits configuring the presence of a pull resistor, in the following
+ * order:
+ *	00 = Pull-up resistor connected
+ *	10 = Pull-down resistor connected
+ *	x1 = No pull up resistor
+ */
+extern int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
+				    unsigned int off, s3c_gpio_pull_t pull);
+
+/**
+ * s3c_gpio_getpull_s3c2443() - Get configuration for s3c2443 pull resistors
+ * @chip: The gpio chip that the GPIO pin belongs to.
+ * @off: The offset to the pin to get the configuration of.
+ *
+ * This helper function reads the state of the pull-{up,down} resistor for the
+ * given GPIO in the same case as s3c_gpio_setpull_upown.
+*/
+extern s3c_gpio_pull_t s3c_gpio_getpull_s3c24xx(struct s3c_gpio_chip *chip,
+						unsigned int off);
+
+#endif /* __PLAT_GPIO_CFG_HELPERS_H */
+
diff --git a/arch/arm/plat-s3c/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/gpio-cfg.h
rename to arch/arm/plat-samsung/include/plat/gpio-cfg.h
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
new file mode 100644
index 0000000..49ff406
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -0,0 +1,137 @@
+/* linux/arch/arm/plat-s3c/include/plat/gpio-core.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C Platform - GPIO core
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define GPIOCON_OFF	(0x00)
+#define GPIODAT_OFF	(0x04)
+
+#define con_4bit_shift(__off) ((__off) * 4)
+
+/* Define the core gpiolib support functions that the s3c platforms may
+ * need to extend or change depending on the hardware and the s3c chip
+ * selected at build or found at run time.
+ *
+ * These definitions are not intended for driver inclusion, there is
+ * nothing here that should not live outside the platform and core
+ * specific code.
+*/
+
+struct s3c_gpio_chip;
+
+/**
+ * struct s3c_gpio_pm - power management (suspend/resume) information
+ * @save: Routine to save the state of the GPIO block
+ * @resume: Routine to resume the GPIO block.
+ */
+struct s3c_gpio_pm {
+	void (*save)(struct s3c_gpio_chip *chip);
+	void (*resume)(struct s3c_gpio_chip *chip);
+};
+
+struct s3c_gpio_cfg;
+
+/**
+ * struct s3c_gpio_chip - wrapper for specific implementation of gpio
+ * @chip: The chip structure to be exported via gpiolib.
+ * @base: The base pointer to the gpio configuration registers.
+ * @config: special function and pull-resistor control information.
+ * @pm_save: Save information for suspend/resume support.
+ *
+ * This wrapper provides the necessary information for the Samsung
+ * specific gpios being registered with gpiolib.
+ */
+struct s3c_gpio_chip {
+	struct gpio_chip	chip;
+	struct s3c_gpio_cfg	*config;
+	struct s3c_gpio_pm	*pm;
+	void __iomem		*base;
+#ifdef CONFIG_PM
+	u32			pm_save[4];
+#endif
+};
+
+static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
+{
+	return container_of(gpc, struct s3c_gpio_chip, chip);
+}
+
+/** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip.
+ * @chip: The chip to register
+ *
+ * This is a wrapper to gpiochip_add() that takes our specific gpio chip
+ * information and makes the necessary alterations for the platform and
+ * notes the information for use with the configuration systems and any
+ * other parts of the system.
+ */
+extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
+
+/* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
+ * for use with the configuration calls, and other parts of the s3c gpiolib
+ * support code.
+ *
+ * Not all s3c support code will need this, as some configurations of cpu
+ * may only support one or two different configuration options and have an
+ * easy gpio to s3c_gpio_chip mapping function. If this is the case, then
+ * the machine support file should provide its own s3c_gpiolib_getchip()
+ * and any other necessary functions.
+ */
+
+/**
+ * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
+ * @chip: The gpio chip that is being configured.
+ * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
+ *
+ * This helper deal with the GPIO cases where the control register has 4 bits
+ * of control per GPIO, generally in the form of:
+ * 0000 = Input
+ * 0001 = Output
+ * others = Special functions (dependant on bank)
+ *
+ * Note, since the code to deal with the case where there are two control
+ * registers instead of one, we do not have a seperate set of function
+ * (samsung_gpiolib_add_4bit2_chips)for each case.
+ */
+extern void samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
+					   int nr_chips);
+extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
+					    int nr_chips);
+
+extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip);
+extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
+
+#ifdef CONFIG_S3C_GPIO_TRACK
+extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
+
+static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
+{
+	return (chip < S3C_GPIO_END) ? s3c_gpios[chip] : NULL;
+}
+#else
+/* machine specific code should provide s3c_gpiolib_getchip */
+
+#include <mach/gpio-track.h>
+
+static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
+#endif
+
+#ifdef CONFIG_PM
+extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
+extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
+extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
+#define __gpio_pm(x) x
+#else
+#define s3c_gpio_pm_1bit NULL
+#define s3c_gpio_pm_2bit NULL
+#define s3c_gpio_pm_4bit NULL
+#define __gpio_pm(x) NULL
+
+#endif /* CONFIG_PM */
diff --git a/arch/arm/plat-s3c/include/plat/hwmon.h b/arch/arm/plat-samsung/include/plat/hwmon.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/hwmon.h
rename to arch/arm/plat-samsung/include/plat/hwmon.h
diff --git a/arch/arm/plat-s3c/include/plat/iic-core.h b/arch/arm/plat-samsung/include/plat/iic-core.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/iic-core.h
rename to arch/arm/plat-samsung/include/plat/iic-core.h
diff --git a/arch/arm/plat-s3c/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/iic.h
rename to arch/arm/plat-samsung/include/plat/iic.h
diff --git a/arch/arm/plat-samsung/include/plat/irq-uart.h b/arch/arm/plat-samsung/include/plat/irq-uart.h
new file mode 100644
index 0000000..a9331e4
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/irq-uart.h
@@ -0,0 +1,20 @@
+/* arch/arm/plat-samsung/include/plat/irq-uart.h
+ *
+ * Copyright (c) 2010 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for Samsung SoC UART IRQ demux for S3C64XX and later
+ *
+ * This program is free software; you can 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 s3c_uart_irq {
+	void __iomem	*regs;
+	unsigned int	 base_irq;
+	unsigned int	 parent_irq;
+};
+
+extern void s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs);
+
diff --git a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h
new file mode 100644
index 0000000..a90b534
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h
@@ -0,0 +1,13 @@
+/* arch/arm/plat-samsung/include/plat/irq-vic-timer.h
+ *
+ * Copyright (c) 2010 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for Samsung SoC IRQ VIC timer
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+extern void s3c_init_vic_timer_irq(unsigned int vic, unsigned int timer);
diff --git a/arch/arm/plat-s3c/include/plat/map-base.h b/arch/arm/plat-samsung/include/plat/map-base.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/map-base.h
rename to arch/arm/plat-samsung/include/plat/map-base.h
diff --git a/arch/arm/plat-samsung/include/plat/nand.h b/arch/arm/plat-samsung/include/plat/nand.h
new file mode 100644
index 0000000..b64115f
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/nand.h
@@ -0,0 +1,67 @@
+/* arch/arm/mach-s3c2410/include/mach/nand.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - NAND device controller platform_device info
+ *
+ * This program is free software; you can 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 s3c2410_nand_set - define a set of one or more nand chips
+ * @disable_ecc:	Entirely disable ECC - Dangerous
+ * @flash_bbt: 		Openmoko u-boot can create a Bad Block Table
+ *			Setting this flag will allow the kernel to
+ *			look for it at boot time and also skip the NAND
+ *			scan.
+ * @options:		Default value to set into 'struct nand_chip' options.
+ * @nr_chips:		Number of chips in this set
+ * @nr_partitions:	Number of partitions pointed to by @partitions
+ * @name:		Name of set (optional)
+ * @nr_map:		Map for low-layer logical to physical chip numbers (option)
+ * @partitions:		The mtd partition list
+ *
+ * define a set of one or more nand chips registered with an unique mtd. Also
+ * allows to pass flag to the underlying NAND layer. 'disable_ecc' will trigger
+ * a warning at boot time.
+ */
+struct s3c2410_nand_set {
+	unsigned int		disable_ecc:1;
+	unsigned int		flash_bbt:1;
+
+	unsigned int		options;
+	int			nr_chips;
+	int			nr_partitions;
+	char			*name;
+	int			*nr_map;
+	struct mtd_partition	*partitions;
+	struct nand_ecclayout	*ecc_layout;
+};
+
+struct s3c2410_platform_nand {
+	/* timing information for controller, all times in nanoseconds */
+
+	int	tacls;	/* time for active CLE/ALE to nWE/nOE */
+	int	twrph0;	/* active time for nWE/nOE */
+	int	twrph1;	/* time for release CLE/ALE from nWE/nOE inactive */
+
+	unsigned int	ignore_unset_ecc:1;
+
+	int			nr_sets;
+	struct s3c2410_nand_set *sets;
+
+	void			(*select_chip)(struct s3c2410_nand_set *,
+					       int chip);
+};
+
+/**
+ * s3c_nand_set_platdata() - register NAND platform data.
+ * @nand: The NAND platform data to register with s3c_device_nand.
+ *
+ * This function copies the given NAND platform data, @nand and registers
+ * it with the s3c_device_nand. This allows @nand to be __initdata.
+*/
+extern void s3c_nand_set_platdata(struct s3c2410_platform_nand *nand);
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
new file mode 100644
index 0000000..245836d
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -0,0 +1,189 @@
+/* arch/arm/plat-samsung/include/plat/pm.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Written by Ben Dooks, <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* s3c_pm_init
+ *
+ * called from board at initialisation time to setup the power
+ * management
+*/
+
+#ifdef CONFIG_PM
+
+extern __init int s3c_pm_init(void);
+
+#else
+
+static inline int s3c_pm_init(void)
+{
+	return 0;
+}
+#endif
+
+/* configuration for the IRQ mask over sleep */
+extern unsigned long s3c_irqwake_intmask;
+extern unsigned long s3c_irqwake_eintmask;
+
+/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
+extern unsigned long s3c_irqwake_intallow;
+extern unsigned long s3c_irqwake_eintallow;
+
+/* per-cpu sleep functions */
+
+extern void (*pm_cpu_prep)(void);
+extern void (*pm_cpu_sleep)(void);
+
+/* Flags for PM Control */
+
+extern unsigned long s3c_pm_flags;
+
+extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */
+
+/* from sleep.S */
+
+extern int  s3c_cpu_save(unsigned long *saveblk);
+extern void s3c_cpu_resume(void);
+
+extern void s3c2410_cpu_suspend(void);
+
+extern unsigned long s3c_sleep_save_phys;
+
+/* sleep save info */
+
+/**
+ * struct sleep_save - save information for shared peripherals.
+ * @reg: Pointer to the register to save.
+ * @val: Holder for the value saved from reg.
+ *
+ * This describes a list of registers which is used by the pm core and
+ * other subsystem to save and restore register values over suspend.
+ */
+struct sleep_save {
+	void __iomem	*reg;
+	unsigned long	val;
+};
+
+#define SAVE_ITEM(x) \
+	{ .reg = (x) }
+
+/**
+ * struct pm_uart_save - save block for core UART
+ * @ulcon: Save value for S3C2410_ULCON
+ * @ucon: Save value for S3C2410_UCON
+ * @ufcon: Save value for S3C2410_UFCON
+ * @umcon: Save value for S3C2410_UMCON
+ * @ubrdiv: Save value for S3C2410_UBRDIV
+ *
+ * Save block for UART registers to be held over sleep and restored if they
+ * are needed (say by debug).
+*/
+struct pm_uart_save {
+	u32	ulcon;
+	u32	ucon;
+	u32	ufcon;
+	u32	umcon;
+	u32	ubrdiv;
+	u32	udivslot;
+};
+
+/* helper functions to save/restore lists of registers. */
+
+extern void s3c_pm_do_save(struct sleep_save *ptr, int count);
+extern void s3c_pm_do_restore(struct sleep_save *ptr, int count);
+extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
+
+#ifdef CONFIG_PM
+extern int s3c_irqext_wake(unsigned int irqno, unsigned int state);
+extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
+extern int s3c24xx_irq_resume(struct sys_device *dev);
+#else
+#define s3c_irqext_wake NULL
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
+
+/* PM debug functions */
+
+#ifdef CONFIG_SAMSUNG_PM_DEBUG
+/**
+ * s3c_pm_dbg() - low level debug function for use in suspend/resume.
+ * @msg: The message to print.
+ *
+ * This function is used mainly to debug the resume process before the system
+ * can rely on printk/console output. It uses the low-level debugging output
+ * routine printascii() to do its work.
+ */
+extern void s3c_pm_dbg(const char *msg, ...);
+
+#define S3C_PMDBG(fmt...) s3c_pm_dbg(fmt)
+#else
+#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
+#endif
+
+#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
+/**
+ * s3c_pm_debug_smdkled() - Debug PM suspend/resume via SMDK Board LEDs
+ * @set: set bits for the state of the LEDs
+ * @clear: clear bits for the state of the LEDs.
+ */
+extern void s3c_pm_debug_smdkled(u32 set, u32 clear);
+
+#else
+static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { }
+#endif /* CONFIG_S3C_PM_DEBUG_LED_SMDK */
+
+/* suspend memory checking */
+
+#ifdef CONFIG_SAMSUNG_PM_CHECK
+extern void s3c_pm_check_prepare(void);
+extern void s3c_pm_check_restore(void);
+extern void s3c_pm_check_cleanup(void);
+extern void s3c_pm_check_store(void);
+#else
+#define s3c_pm_check_prepare() do { } while(0)
+#define s3c_pm_check_restore() do { } while(0)
+#define s3c_pm_check_cleanup() do { } while(0)
+#define s3c_pm_check_store()   do { } while(0)
+#endif
+
+/**
+ * s3c_pm_configure_extint() - ensure pins are correctly set for IRQ
+ *
+ * Setup all the necessary GPIO pins for waking the system on external
+ * interrupt.
+ */
+extern void s3c_pm_configure_extint(void);
+
+/**
+ * s3c_pm_restore_gpios() - restore the state of the gpios after sleep.
+ *
+ * Restore the state of the GPIO pins after sleep, which may involve ensuring
+ * that we do not glitch the state of the pins from that the bootloader's
+ * resume code has done.
+*/
+extern void s3c_pm_restore_gpios(void);
+
+/**
+ * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
+ *
+ * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios().
+ */
+extern void s3c_pm_save_gpios(void);
+
+/**
+ * s3c_pm_cb_flushcache - callback for assembly code
+ *
+ * Callback to issue flush_cache_all() as this call is
+ * not a directly callable object.
+ */
+extern void s3c_pm_cb_flushcache(void);
+
+extern void s3c_pm_save_core(void);
+extern void s3c_pm_restore_core(void);
diff --git a/arch/arm/plat-s3c/include/plat/regs-ac97.h b/arch/arm/plat-samsung/include/plat/regs-ac97.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/regs-ac97.h
rename to arch/arm/plat-samsung/include/plat/regs-ac97.h
diff --git a/arch/arm/plat-samsung/include/plat/regs-adc.h b/arch/arm/plat-samsung/include/plat/regs-adc.h
new file mode 100644
index 0000000..7554c4f
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-adc.h
@@ -0,0 +1,64 @@
+/* arch/arm/mach-s3c2410/include/mach/regs-adc.h
+ *
+ * Copyright (c) 2004 Shannon Holland <holland@loser.net>
+ *
+ * This program is free software; yosu can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * S3C2410 ADC registers
+*/
+
+#ifndef __ASM_ARCH_REGS_ADC_H
+#define __ASM_ARCH_REGS_ADC_H "regs-adc.h"
+
+#define S3C2410_ADCREG(x) (x)
+
+#define S3C2410_ADCCON	   S3C2410_ADCREG(0x00)
+#define S3C2410_ADCTSC	   S3C2410_ADCREG(0x04)
+#define S3C2410_ADCDLY	   S3C2410_ADCREG(0x08)
+#define S3C2410_ADCDAT0	   S3C2410_ADCREG(0x0C)
+#define S3C2410_ADCDAT1	   S3C2410_ADCREG(0x10)
+#define S3C64XX_ADCUPDN		S3C2410_ADCREG(0x14)
+#define S3C64XX_ADCCLRINT	S3C2410_ADCREG(0x18)
+#define S3C64XX_ADCCLRINTPNDNUP	S3C2410_ADCREG(0x20)
+
+
+/* ADCCON Register Bits */
+#define S3C64XX_ADCCON_RESSEL		(1<<16)
+#define S3C2410_ADCCON_ECFLG		(1<<15)
+#define S3C2410_ADCCON_PRSCEN		(1<<14)
+#define S3C2410_ADCCON_PRSCVL(x)	(((x)&0xFF)<<6)
+#define S3C2410_ADCCON_PRSCVLMASK	(0xFF<<6)
+#define S3C2410_ADCCON_SELMUX(x)	(((x)&0x7)<<3)
+#define S3C2410_ADCCON_MUXMASK		(0x7<<3)
+#define S3C2410_ADCCON_STDBM		(1<<2)
+#define S3C2410_ADCCON_READ_START	(1<<1)
+#define S3C2410_ADCCON_ENABLE_START	(1<<0)
+#define S3C2410_ADCCON_STARTMASK	(0x3<<0)
+
+
+/* ADCTSC Register Bits */
+#define S3C2410_ADCTSC_YM_SEN		(1<<7)
+#define S3C2410_ADCTSC_YP_SEN		(1<<6)
+#define S3C2410_ADCTSC_XM_SEN		(1<<5)
+#define S3C2410_ADCTSC_XP_SEN		(1<<4)
+#define S3C2410_ADCTSC_PULL_UP_DISABLE	(1<<3)
+#define S3C2410_ADCTSC_AUTO_PST		(1<<2)
+#define S3C2410_ADCTSC_XY_PST(x)	(((x)&0x3)<<0)
+
+/* ADCDAT0 Bits */
+#define S3C2410_ADCDAT0_UPDOWN		(1<<15)
+#define S3C2410_ADCDAT0_AUTO_PST	(1<<14)
+#define S3C2410_ADCDAT0_XY_PST		(0x3<<12)
+#define S3C2410_ADCDAT0_XPDATA_MASK	(0x03FF)
+
+/* ADCDAT1 Bits */
+#define S3C2410_ADCDAT1_UPDOWN		(1<<15)
+#define S3C2410_ADCDAT1_AUTO_PST	(1<<14)
+#define S3C2410_ADCDAT1_XY_PST		(0x3<<12)
+#define S3C2410_ADCDAT1_YPDATA_MASK	(0x03FF)
+
+#endif /* __ASM_ARCH_REGS_ADC_H */
+
+
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
new file mode 100644
index 0000000..0f43599
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
@@ -0,0 +1,235 @@
+/* arch/arm/plat-samsung/include/plat/regs-fb-v4.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C64XX - new-style framebuffer register definitions
+ *
+ * This is the register set for the new style framebuffer interface
+ * found from the S3C2443 onwards and specifically the S3C64XX series
+ * S3C6400 and S3C6410.
+ *
+ * The file contains the cpu specific items which change between whichever
+ * architecture is selected. See <plat/regs-fb.h> for the core definitions
+ * that are the same.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* include the core definitions here, in case we really do need to
+ * override them at a later date.
+*/
+
+#include <plat/regs-fb.h>
+
+#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
+#define VIDCON1_FSTATUS_EVEN	(1 << 15)
+
+/* Video timing controls */
+#define VIDTCON0				(0x10)
+#define VIDTCON1				(0x14)
+#define VIDTCON2				(0x18)
+
+/* Window position controls */
+
+#define WINCON(_win)				(0x20 + ((_win) * 4))
+
+/* OSD1 and OSD4 do not have register D */
+
+#define VIDOSD_A(_win)				(0x40 + ((_win) * 16))
+#define VIDOSD_B(_win)				(0x44 + ((_win) * 16))
+#define VIDOSD_C(_win)				(0x48 + ((_win) * 16))
+#define VIDOSD_D(_win)				(0x4C + ((_win) * 16))
+
+
+#define VIDINTCON0				(0x130)
+
+#define WxKEYCONy(_win, _con)			((0x140 + ((_win) * 8)) + ((_con) * 4))
+
+/* WINCONx */
+
+#define WINCONx_CSCWIDTH_MASK			(0x3 << 26)
+#define WINCONx_CSCWIDTH_SHIFT			(26)
+#define WINCONx_CSCWIDTH_WIDE			(0x0 << 26)
+#define WINCONx_CSCWIDTH_NARROW			(0x3 << 26)
+
+#define WINCONx_ENLOCAL				(1 << 22)
+#define WINCONx_BUFSTATUS			(1 << 21)
+#define WINCONx_BUFSEL				(1 << 20)
+#define WINCONx_BUFAUTOEN			(1 << 19)
+#define WINCONx_YCbCr				(1 << 13)
+
+#define WINCON1_LOCALSEL_CAMIF			(1 << 23)
+
+#define WINCON2_LOCALSEL_CAMIF			(1 << 23)
+#define WINCON2_BLD_PIX				(1 << 6)
+
+#define WINCON2_ALPHA_SEL			(1 << 1)
+#define WINCON2_BPPMODE_MASK			(0xf << 2)
+#define WINCON2_BPPMODE_SHIFT			(2)
+#define WINCON2_BPPMODE_1BPP			(0x0 << 2)
+#define WINCON2_BPPMODE_2BPP			(0x1 << 2)
+#define WINCON2_BPPMODE_4BPP			(0x2 << 2)
+#define WINCON2_BPPMODE_8BPP_1232		(0x4 << 2)
+#define WINCON2_BPPMODE_16BPP_565		(0x5 << 2)
+#define WINCON2_BPPMODE_16BPP_A1555		(0x6 << 2)
+#define WINCON2_BPPMODE_16BPP_I1555		(0x7 << 2)
+#define WINCON2_BPPMODE_18BPP_666		(0x8 << 2)
+#define WINCON2_BPPMODE_18BPP_A1665		(0x9 << 2)
+#define WINCON2_BPPMODE_19BPP_A1666		(0xa << 2)
+#define WINCON2_BPPMODE_24BPP_888		(0xb << 2)
+#define WINCON2_BPPMODE_24BPP_A1887		(0xc << 2)
+#define WINCON2_BPPMODE_25BPP_A1888		(0xd << 2)
+#define WINCON2_BPPMODE_28BPP_A4888		(0xd << 2)
+
+#define WINCON3_BLD_PIX				(1 << 6)
+
+#define WINCON3_ALPHA_SEL			(1 << 1)
+#define WINCON3_BPPMODE_MASK			(0xf << 2)
+#define WINCON3_BPPMODE_SHIFT			(2)
+#define WINCON3_BPPMODE_1BPP			(0x0 << 2)
+#define WINCON3_BPPMODE_2BPP			(0x1 << 2)
+#define WINCON3_BPPMODE_4BPP			(0x2 << 2)
+#define WINCON3_BPPMODE_16BPP_565		(0x5 << 2)
+#define WINCON3_BPPMODE_16BPP_A1555		(0x6 << 2)
+#define WINCON3_BPPMODE_16BPP_I1555		(0x7 << 2)
+#define WINCON3_BPPMODE_18BPP_666		(0x8 << 2)
+#define WINCON3_BPPMODE_18BPP_A1665		(0x9 << 2)
+#define WINCON3_BPPMODE_19BPP_A1666		(0xa << 2)
+#define WINCON3_BPPMODE_24BPP_888		(0xb << 2)
+#define WINCON3_BPPMODE_24BPP_A1887		(0xc << 2)
+#define WINCON3_BPPMODE_25BPP_A1888		(0xd << 2)
+#define WINCON3_BPPMODE_28BPP_A4888		(0xd << 2)
+
+#define VIDINTCON0_FIFIOSEL_WINDOW2		(0x10 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW3		(0x20 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW4		(0x40 << 5)
+
+#define DITHMODE				(0x170)
+#define WINxMAP(_win)				(0x180 + ((_win) * 4))
+
+
+#define DITHMODE_R_POS_MASK			(0x3 << 5)
+#define DITHMODE_R_POS_SHIFT			(5)
+#define DITHMODE_R_POS_8BIT			(0x0 << 5)
+#define DITHMODE_R_POS_6BIT			(0x1 << 5)
+#define DITHMODE_R_POS_5BIT			(0x2 << 5)
+
+#define DITHMODE_G_POS_MASK			(0x3 << 3)
+#define DITHMODE_G_POS_SHIFT			(3)
+#define DITHMODE_G_POS_8BIT			(0x0 << 3)
+#define DITHMODE_G_POS_6BIT			(0x1 << 3)
+#define DITHMODE_G_POS_5BIT			(0x2 << 3)
+
+#define DITHMODE_B_POS_MASK			(0x3 << 1)
+#define DITHMODE_B_POS_SHIFT			(1)
+#define DITHMODE_B_POS_8BIT			(0x0 << 1)
+#define DITHMODE_B_POS_6BIT			(0x1 << 1)
+#define DITHMODE_B_POS_5BIT			(0x2 << 1)
+
+#define DITHMODE_DITH_EN			(1 << 0)
+
+#define WPALCON					(0x1A0)
+
+/* Palette control */
+/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
+ * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
+#define WPALCON_W4PAL_16BPP_A555		(1 << 8)
+#define WPALCON_W3PAL_16BPP_A555		(1 << 7)
+#define WPALCON_W2PAL_16BPP_A555		(1 << 6)
+
+
+/* system specific implementation code for palette sizes, and other
+ * information that changes depending on which architecture is being
+ * compiled.
+*/
+
+/* return true if window _win has OSD register D */
+#define s3c_fb_has_osd_d(_win) ((_win) != 4 && (_win) != 0)
+
+static inline unsigned int s3c_fb_win_pal_size(unsigned int win)
+{
+	if (win < 2)
+		return 256;
+	if (win < 4)
+		return 16;
+	if (win == 4)
+		return 4;
+
+	BUG();	/* shouldn't get here */
+}
+
+static inline int s3c_fb_validate_win_bpp(unsigned int win, unsigned int bpp)
+{
+	/* all windows can do 1/2 bpp */
+
+	if ((bpp == 25 || bpp == 19) && win == 0)
+		return 0;	/* win 0 does not have 19 or 25bpp modes */
+
+	if (bpp == 4 && win == 4)
+		return 0;
+
+	if (bpp == 8 && (win >= 3))
+		return 0;	/* win 3/4 cannot do 8bpp in any mode */
+
+	return 1;
+}
+
+static inline int s3c_fb_pal_is16(unsigned int window)
+{
+	return window > 1;
+}
+
+struct s3c_fb_palette {
+	struct fb_bitfield	r;
+	struct fb_bitfield	g;
+	struct fb_bitfield	b;
+	struct fb_bitfield	a;
+};
+
+static inline void s3c_fb_init_palette(unsigned int window,
+				       struct s3c_fb_palette *palette)
+{
+	if (window < 2) {
+		/* Windows 0/1 are 8/8/8 or A/8/8/8 */
+		palette->r.offset = 16;
+		palette->r.length = 8;
+		palette->g.offset = 8;
+		palette->g.length = 8;
+		palette->b.offset = 0;
+		palette->b.length = 8;
+	} else {
+		/* currently we assume RGB 5/6/5 */
+		palette->r.offset = 11;
+		palette->r.length = 5;
+		palette->g.offset = 5;
+		palette->g.length = 6;
+		palette->b.offset = 0;
+		palette->b.length = 5;
+	}
+}
+
+/* Notes on per-window bpp settings
+ *
+ * Value	Win0	 Win1	  Win2	   Win3	    Win 4
+ * 0000		1(P)	 1(P)	  1(P)	   1(P)	    1(P)
+ * 0001		2(P)	 2(P)     2(P)	   2(P)	    2(P)
+ * 0010		4(P)	 4(P)     4(P)	   4(P)     -none-
+ * 0011		8(P)	 8(P)     -none-   -none-   -none-
+ * 0100		-none-	 8(A232)  8(A232)  -none-   -none-
+ * 0101		16(565)	 16(565)  16(565)  16(565)   16(565)
+ * 0110		-none-	 16(A555) 16(A555) 16(A555)  16(A555)
+ * 0111		16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
+ * 1000		18(666)	 18(666)  18(666)  18(666)   18(666)
+ * 1001		-none-	 18(A665) 18(A665) 18(A665)  16(A665)
+ * 1010		-none-	 19(A666) 19(A666) 19(A666)  19(A666)
+ * 1011		24(888)	 24(888)  24(888)  24(888)   24(888)
+ * 1100		-none-	 24(A887) 24(A887) 24(A887)  24(A887)
+ * 1101		-none-	 25(A888) 25(A888) 25(A888)  25(A888)
+ * 1110		-none-	 -none-	  -none-   -none-    -none-
+ * 1111		-none-	 -none-   -none-   -none-    -none-
+*/
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
new file mode 100644
index 0000000..0ef806e
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-fb.h
@@ -0,0 +1,366 @@
+/* arch/arm/plat-samsung/include/plat/regs-fb.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C Platform - new-style framebuffer register definitions
+ *
+ * This is the register set for the new style framebuffer interface
+ * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
+ * S3C64XX series such as the S3C6400 and S3C6410.
+ *
+ * The file does not contain the cpu specific items which are based on
+ * whichever architecture is selected, it only contains the core of the
+ * register set. See <mach/regs-fb.h> to get the specifics.
+ *
+ * Note, we changed to using regs-fb.h as it avoids any clashes with
+ * the original regs-lcd.h so out of the way of regs-lcd.h as well as
+ * indicating the newer block is much more than just an LCD interface.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Please do not include this file directly, use <mach/regs-fb.h> to
+ * ensure all the localised SoC support is included as necessary.
+*/
+
+/* VIDCON0 */
+
+#define VIDCON0					(0x00)
+#define VIDCON0_INTERLACE			(1 << 29)
+#define VIDCON0_VIDOUT_MASK			(0x3 << 26)
+#define VIDCON0_VIDOUT_SHIFT			(26)
+#define VIDCON0_VIDOUT_RGB			(0x0 << 26)
+#define VIDCON0_VIDOUT_TV			(0x1 << 26)
+#define VIDCON0_VIDOUT_I80_LDI0			(0x2 << 26)
+#define VIDCON0_VIDOUT_I80_LDI1			(0x3 << 26)
+
+#define VIDCON0_L1_DATA_MASK			(0x7 << 23)
+#define VIDCON0_L1_DATA_SHIFT			(23)
+#define VIDCON0_L1_DATA_16BPP			(0x0 << 23)
+#define VIDCON0_L1_DATA_18BPP16			(0x1 << 23)
+#define VIDCON0_L1_DATA_18BPP9			(0x2 << 23)
+#define VIDCON0_L1_DATA_24BPP			(0x3 << 23)
+#define VIDCON0_L1_DATA_18BPP			(0x4 << 23)
+#define VIDCON0_L1_DATA_16BPP8			(0x5 << 23)
+
+#define VIDCON0_L0_DATA_MASK			(0x7 << 20)
+#define VIDCON0_L0_DATA_SHIFT			(20)
+#define VIDCON0_L0_DATA_16BPP			(0x0 << 20)
+#define VIDCON0_L0_DATA_18BPP16			(0x1 << 20)
+#define VIDCON0_L0_DATA_18BPP9			(0x2 << 20)
+#define VIDCON0_L0_DATA_24BPP			(0x3 << 20)
+#define VIDCON0_L0_DATA_18BPP			(0x4 << 20)
+#define VIDCON0_L0_DATA_16BPP8			(0x5 << 20)
+
+#define VIDCON0_PNRMODE_MASK			(0x3 << 17)
+#define VIDCON0_PNRMODE_SHIFT			(17)
+#define VIDCON0_PNRMODE_RGB			(0x0 << 17)
+#define VIDCON0_PNRMODE_BGR			(0x1 << 17)
+#define VIDCON0_PNRMODE_SERIAL_RGB		(0x2 << 17)
+#define VIDCON0_PNRMODE_SERIAL_BGR		(0x3 << 17)
+
+#define VIDCON0_CLKVALUP			(1 << 16)
+#define VIDCON0_CLKVAL_F_MASK			(0xff << 6)
+#define VIDCON0_CLKVAL_F_SHIFT			(6)
+#define VIDCON0_CLKVAL_F_LIMIT			(0xff)
+#define VIDCON0_CLKVAL_F(_x)			((_x) << 6)
+#define VIDCON0_VLCKFREE			(1 << 5)
+#define VIDCON0_CLKDIR				(1 << 4)
+
+#define VIDCON0_CLKSEL_MASK			(0x3 << 2)
+#define VIDCON0_CLKSEL_SHIFT			(2)
+#define VIDCON0_CLKSEL_HCLK			(0x0 << 2)
+#define VIDCON0_CLKSEL_LCD			(0x1 << 2)
+#define VIDCON0_CLKSEL_27M			(0x3 << 2)
+
+#define VIDCON0_ENVID				(1 << 1)
+#define VIDCON0_ENVID_F				(1 << 0)
+
+#define VIDCON1					(0x04)
+#define VIDCON1_LINECNT_MASK			(0x7ff << 16)
+#define VIDCON1_LINECNT_SHIFT			(16)
+#define VIDCON1_LINECNT_GET(_v)			(((_v) >> 16) & 0x7ff)
+#define VIDCON1_VSTATUS_MASK			(0x3 << 13)
+#define VIDCON1_VSTATUS_SHIFT			(13)
+#define VIDCON1_VSTATUS_VSYNC			(0x0 << 13)
+#define VIDCON1_VSTATUS_BACKPORCH		(0x1 << 13)
+#define VIDCON1_VSTATUS_ACTIVE			(0x2 << 13)
+#define VIDCON1_VSTATUS_FRONTPORCH		(0x0 << 13)
+
+#define VIDCON1_INV_VCLK			(1 << 7)
+#define VIDCON1_INV_HSYNC			(1 << 6)
+#define VIDCON1_INV_VSYNC			(1 << 5)
+#define VIDCON1_INV_VDEN			(1 << 4)
+
+/* VIDCON2 */
+
+#define VIDCON2					(0x08)
+#define VIDCON2_EN601				(1 << 23)
+#define VIDCON2_TVFMTSEL_SW			(1 << 14)
+
+#define VIDCON2_TVFMTSEL1_MASK			(0x3 << 12)
+#define VIDCON2_TVFMTSEL1_SHIFT			(12)
+#define VIDCON2_TVFMTSEL1_RGB			(0x0 << 12)
+#define VIDCON2_TVFMTSEL1_YUV422		(0x1 << 12)
+#define VIDCON2_TVFMTSEL1_YUV444		(0x2 << 12)
+
+#define VIDCON2_ORGYCbCr			(1 << 8)
+#define VIDCON2_YUVORDCrCb			(1 << 7)
+
+/* VIDTCON0 */
+
+#define VIDTCON0_VBPDE_MASK			(0xff << 24)
+#define VIDTCON0_VBPDE_SHIFT			(24)
+#define VIDTCON0_VBPDE_LIMIT			(0xff)
+#define VIDTCON0_VBPDE(_x)			((_x) << 24)
+
+#define VIDTCON0_VBPD_MASK			(0xff << 16)
+#define VIDTCON0_VBPD_SHIFT			(16)
+#define VIDTCON0_VBPD_LIMIT			(0xff)
+#define VIDTCON0_VBPD(_x)			((_x) << 16)
+
+#define VIDTCON0_VFPD_MASK			(0xff << 8)
+#define VIDTCON0_VFPD_SHIFT			(8)
+#define VIDTCON0_VFPD_LIMIT			(0xff)
+#define VIDTCON0_VFPD(_x)			((_x) << 8)
+
+#define VIDTCON0_VSPW_MASK			(0xff << 0)
+#define VIDTCON0_VSPW_SHIFT			(0)
+#define VIDTCON0_VSPW_LIMIT			(0xff)
+#define VIDTCON0_VSPW(_x)			((_x) << 0)
+
+/* VIDTCON1 */
+
+#define VIDTCON1_VFPDE_MASK			(0xff << 24)
+#define VIDTCON1_VFPDE_SHIFT			(24)
+#define VIDTCON1_VFPDE_LIMIT			(0xff)
+#define VIDTCON1_VFPDE(_x)			((_x) << 24)
+
+#define VIDTCON1_HBPD_MASK			(0xff << 16)
+#define VIDTCON1_HBPD_SHIFT			(16)
+#define VIDTCON1_HBPD_LIMIT			(0xff)
+#define VIDTCON1_HBPD(_x)			((_x) << 16)
+
+#define VIDTCON1_HFPD_MASK			(0xff << 8)
+#define VIDTCON1_HFPD_SHIFT			(8)
+#define VIDTCON1_HFPD_LIMIT			(0xff)
+#define VIDTCON1_HFPD(_x)			((_x) << 8)
+
+#define VIDTCON1_HSPW_MASK			(0xff << 0)
+#define VIDTCON1_HSPW_SHIFT			(0)
+#define VIDTCON1_HSPW_LIMIT			(0xff)
+#define VIDTCON1_HSPW(_x)			((_x) << 0)
+
+#define VIDTCON2				(0x18)
+#define VIDTCON2_LINEVAL_MASK			(0x7ff << 11)
+#define VIDTCON2_LINEVAL_SHIFT			(11)
+#define VIDTCON2_LINEVAL_LIMIT			(0x7ff)
+#define VIDTCON2_LINEVAL(_x)			((_x) << 11)
+
+#define VIDTCON2_HOZVAL_MASK			(0x7ff << 0)
+#define VIDTCON2_HOZVAL_SHIFT			(0)
+#define VIDTCON2_HOZVAL_LIMIT			(0x7ff)
+#define VIDTCON2_HOZVAL(_x)			((_x) << 0)
+
+/* WINCONx */
+
+
+#define WINCONx_BITSWP				(1 << 18)
+#define WINCONx_BYTSWP				(1 << 17)
+#define WINCONx_HAWSWP				(1 << 16)
+#define WINCONx_BURSTLEN_MASK			(0x3 << 9)
+#define WINCONx_BURSTLEN_SHIFT			(9)
+#define WINCONx_BURSTLEN_16WORD			(0x0 << 9)
+#define WINCONx_BURSTLEN_8WORD			(0x1 << 9)
+#define WINCONx_BURSTLEN_4WORD			(0x2 << 9)
+
+#define WINCONx_ENWIN				(1 << 0)
+#define WINCON0_BPPMODE_MASK			(0xf << 2)
+#define WINCON0_BPPMODE_SHIFT			(2)
+#define WINCON0_BPPMODE_1BPP			(0x0 << 2)
+#define WINCON0_BPPMODE_2BPP			(0x1 << 2)
+#define WINCON0_BPPMODE_4BPP			(0x2 << 2)
+#define WINCON0_BPPMODE_8BPP_PALETTE		(0x3 << 2)
+#define WINCON0_BPPMODE_16BPP_565		(0x5 << 2)
+#define WINCON0_BPPMODE_16BPP_1555		(0x7 << 2)
+#define WINCON0_BPPMODE_18BPP_666		(0x8 << 2)
+#define WINCON0_BPPMODE_24BPP_888		(0xb << 2)
+
+#define WINCON1_BLD_PIX				(1 << 6)
+
+#define WINCON1_ALPHA_SEL			(1 << 1)
+#define WINCON1_BPPMODE_MASK			(0xf << 2)
+#define WINCON1_BPPMODE_SHIFT			(2)
+#define WINCON1_BPPMODE_1BPP			(0x0 << 2)
+#define WINCON1_BPPMODE_2BPP			(0x1 << 2)
+#define WINCON1_BPPMODE_4BPP			(0x2 << 2)
+#define WINCON1_BPPMODE_8BPP_PALETTE		(0x3 << 2)
+#define WINCON1_BPPMODE_8BPP_1232		(0x4 << 2)
+#define WINCON1_BPPMODE_16BPP_565		(0x5 << 2)
+#define WINCON1_BPPMODE_16BPP_A1555		(0x6 << 2)
+#define WINCON1_BPPMODE_16BPP_I1555		(0x7 << 2)
+#define WINCON1_BPPMODE_18BPP_666		(0x8 << 2)
+#define WINCON1_BPPMODE_18BPP_A1665		(0x9 << 2)
+#define WINCON1_BPPMODE_19BPP_A1666		(0xa << 2)
+#define WINCON1_BPPMODE_24BPP_888		(0xb << 2)
+#define WINCON1_BPPMODE_24BPP_A1887		(0xc << 2)
+#define WINCON1_BPPMODE_25BPP_A1888		(0xd << 2)
+#define WINCON1_BPPMODE_28BPP_A4888		(0xd << 2)
+
+
+#define VIDOSDxA_TOPLEFT_X_MASK			(0x7ff << 11)
+#define VIDOSDxA_TOPLEFT_X_SHIFT		(11)
+#define VIDOSDxA_TOPLEFT_X_LIMIT		(0x7ff)
+#define VIDOSDxA_TOPLEFT_X(_x)			((_x) << 11)
+
+#define VIDOSDxA_TOPLEFT_Y_MASK			(0x7ff << 0)
+#define VIDOSDxA_TOPLEFT_Y_SHIFT		(0)
+#define VIDOSDxA_TOPLEFT_Y_LIMIT		(0x7ff)
+#define VIDOSDxA_TOPLEFT_Y(_x)			((_x) << 0)
+
+#define VIDOSDxB_BOTRIGHT_X_MASK		(0x7ff << 11)
+#define VIDOSDxB_BOTRIGHT_X_SHIFT		(11)
+#define VIDOSDxB_BOTRIGHT_X_LIMIT		(0x7ff)
+#define VIDOSDxB_BOTRIGHT_X(_x)			((_x) << 11)
+
+#define VIDOSDxB_BOTRIGHT_Y_MASK		(0x7ff << 0)
+#define VIDOSDxB_BOTRIGHT_Y_SHIFT		(0)
+#define VIDOSDxB_BOTRIGHT_Y_LIMIT		(0x7ff)
+#define VIDOSDxB_BOTRIGHT_Y(_x)			((_x) << 0)
+
+/* For VIDOSD[1..4]C */
+#define VIDISD14C_ALPHA0_R(_x)			((_x) << 20)
+#define VIDISD14C_ALPHA0_G_MASK			(0xf << 16)
+#define VIDISD14C_ALPHA0_G_SHIFT		(16)
+#define VIDISD14C_ALPHA0_G_LIMIT		(0xf)
+#define VIDISD14C_ALPHA0_G(_x)			((_x) << 16)
+#define VIDISD14C_ALPHA0_B_MASK			(0xf << 12)
+#define VIDISD14C_ALPHA0_B_SHIFT		(12)
+#define VIDISD14C_ALPHA0_B_LIMIT		(0xf)
+#define VIDISD14C_ALPHA0_B(_x)			((_x) << 12)
+#define VIDISD14C_ALPHA1_R_MASK			(0xf << 8)
+#define VIDISD14C_ALPHA1_R_SHIFT		(8)
+#define VIDISD14C_ALPHA1_R_LIMIT		(0xf)
+#define VIDISD14C_ALPHA1_R(_x)			((_x) << 8)
+#define VIDISD14C_ALPHA1_G_MASK			(0xf << 4)
+#define VIDISD14C_ALPHA1_G_SHIFT		(4)
+#define VIDISD14C_ALPHA1_G_LIMIT		(0xf)
+#define VIDISD14C_ALPHA1_G(_x)			((_x) << 4)
+#define VIDISD14C_ALPHA1_B_MASK			(0xf << 0)
+#define VIDISD14C_ALPHA1_B_SHIFT		(0)
+#define VIDISD14C_ALPHA1_B_LIMIT		(0xf)
+#define VIDISD14C_ALPHA1_B(_x)			((_x) << 0)
+
+/* Video buffer addresses */
+#define VIDW_BUF_START(_buff)			(0xA0 + ((_buff) * 8))
+#define VIDW_BUF_START1(_buff)			(0xA4 + ((_buff) * 8))
+#define VIDW_BUF_END(_buff)			(0xD0 + ((_buff) * 8))
+#define VIDW_BUF_END1(_buff)			(0xD4 + ((_buff) * 8))
+#define VIDW_BUF_SIZE(_buff)			(0x100 + ((_buff) * 4))
+
+#define VIDW_BUF_SIZE_OFFSET_MASK		(0x1fff << 13)
+#define VIDW_BUF_SIZE_OFFSET_SHIFT		(13)
+#define VIDW_BUF_SIZE_OFFSET_LIMIT		(0x1fff)
+#define VIDW_BUF_SIZE_OFFSET(_x)		((_x) << 13)
+
+#define VIDW_BUF_SIZE_PAGEWIDTH_MASK		(0x1fff << 0)
+#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT		(0)
+#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT		(0x1fff)
+#define VIDW_BUF_SIZE_PAGEWIDTH(_x)		((_x) << 0)
+
+/* Interrupt controls and status */
+
+#define VIDINTCON0_FIFOINTERVAL_MASK		(0x3f << 20)
+#define VIDINTCON0_FIFOINTERVAL_SHIFT		(20)
+#define VIDINTCON0_FIFOINTERVAL_LIMIT		(0x3f)
+#define VIDINTCON0_FIFOINTERVAL(_x)		((_x) << 20)
+
+#define VIDINTCON0_INT_SYSMAINCON		(1 << 19)
+#define VIDINTCON0_INT_SYSSUBCON		(1 << 18)
+#define VIDINTCON0_INT_I80IFDONE		(1 << 17)
+
+#define VIDINTCON0_FRAMESEL0_MASK		(0x3 << 15)
+#define VIDINTCON0_FRAMESEL0_SHIFT		(15)
+#define VIDINTCON0_FRAMESEL0_BACKPORCH		(0x0 << 15)
+#define VIDINTCON0_FRAMESEL0_VSYNC		(0x1 << 15)
+#define VIDINTCON0_FRAMESEL0_ACTIVE		(0x2 << 15)
+#define VIDINTCON0_FRAMESEL0_FRONTPORCH		(0x3 << 15)
+
+#define VIDINTCON0_FRAMESEL1			(1 << 14)
+#define VIDINTCON0_FRAMESEL1_NONE		(0x0 << 14)
+#define VIDINTCON0_FRAMESEL1_BACKPORCH		(0x1 << 14)
+#define VIDINTCON0_FRAMESEL1_VSYNC		(0x2 << 14)
+#define VIDINTCON0_FRAMESEL1_FRONTPORCH		(0x3 << 14)
+
+#define VIDINTCON0_INT_FRAME			(1 << 12)
+#define VIDINTCON0_FIFIOSEL_MASK		(0x7f << 5)
+#define VIDINTCON0_FIFIOSEL_SHIFT		(5)
+#define VIDINTCON0_FIFIOSEL_WINDOW0		(0x1 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW1		(0x2 << 5)
+
+#define VIDINTCON0_FIFOLEVEL_MASK		(0x7 << 2)
+#define VIDINTCON0_FIFOLEVEL_SHIFT		(2)
+#define VIDINTCON0_FIFOLEVEL_TO25PC		(0x0 << 2)
+#define VIDINTCON0_FIFOLEVEL_TO50PC		(0x1 << 2)
+#define VIDINTCON0_FIFOLEVEL_TO75PC		(0x2 << 2)
+#define VIDINTCON0_FIFOLEVEL_EMPTY		(0x3 << 2)
+#define VIDINTCON0_FIFOLEVEL_FULL		(0x4 << 2)
+
+#define VIDINTCON0_INT_FIFO_MASK		(0x3 << 0)
+#define VIDINTCON0_INT_FIFO_SHIFT		(0)
+#define VIDINTCON0_INT_ENABLE			(1 << 0)
+
+#define VIDINTCON1				(0x134)
+#define VIDINTCON1_INT_I180			(1 << 2)
+#define VIDINTCON1_INT_FRAME			(1 << 1)
+#define VIDINTCON1_INT_FIFO			(1 << 0)
+
+/* Window colour-key control registers */
+
+#define WxKEYCON0_KEYBL_EN			(1 << 26)
+#define WxKEYCON0_KEYEN_F			(1 << 25)
+#define WxKEYCON0_DIRCON			(1 << 24)
+#define WxKEYCON0_COMPKEY_MASK			(0xffffff << 0)
+#define WxKEYCON0_COMPKEY_SHIFT			(0)
+#define WxKEYCON0_COMPKEY_LIMIT			(0xffffff)
+#define WxKEYCON0_COMPKEY(_x)			((_x) << 0)
+#define WxKEYCON1_COLVAL_MASK			(0xffffff << 0)
+#define WxKEYCON1_COLVAL_SHIFT			(0)
+#define WxKEYCON1_COLVAL_LIMIT			(0xffffff)
+#define WxKEYCON1_COLVAL(_x)			((_x) << 0)
+
+
+/* Window blanking (MAP) */
+
+#define WINxMAP_MAP				(1 << 24)
+#define WINxMAP_MAP_COLOUR_MASK			(0xffffff << 0)
+#define WINxMAP_MAP_COLOUR_SHIFT		(0)
+#define WINxMAP_MAP_COLOUR_LIMIT		(0xffffff)
+#define WINxMAP_MAP_COLOUR(_x)			((_x) << 0)
+
+#define WPALCON_PAL_UPDATE			(1 << 9)
+#define WPALCON_W1PAL_MASK			(0x7 << 3)
+#define WPALCON_W1PAL_SHIFT			(3)
+#define WPALCON_W1PAL_25BPP_A888		(0x0 << 3)
+#define WPALCON_W1PAL_24BPP			(0x1 << 3)
+#define WPALCON_W1PAL_19BPP_A666		(0x2 << 3)
+#define WPALCON_W1PAL_18BPP_A665		(0x3 << 3)
+#define WPALCON_W1PAL_18BPP			(0x4 << 3)
+#define WPALCON_W1PAL_16BPP_A555		(0x5 << 3)
+#define WPALCON_W1PAL_16BPP_565			(0x6 << 3)
+
+#define WPALCON_W0PAL_MASK			(0x7 << 0)
+#define WPALCON_W0PAL_SHIFT			(0)
+#define WPALCON_W0PAL_25BPP_A888		(0x0 << 0)
+#define WPALCON_W0PAL_24BPP			(0x1 << 0)
+#define WPALCON_W0PAL_19BPP_A666		(0x2 << 0)
+#define WPALCON_W0PAL_18BPP_A665		(0x3 << 0)
+#define WPALCON_W0PAL_18BPP			(0x4 << 0)
+#define WPALCON_W0PAL_16BPP_A555		(0x5 << 0)
+#define WPALCON_W0PAL_16BPP_565			(0x6 << 0)
+
diff --git a/arch/arm/plat-s3c/include/plat/regs-iic.h b/arch/arm/plat-samsung/include/plat/regs-iic.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/regs-iic.h
rename to arch/arm/plat-samsung/include/plat/regs-iic.h
diff --git a/arch/arm/plat-s3c/include/plat/regs-irqtype.h b/arch/arm/plat-samsung/include/plat/regs-irqtype.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/regs-irqtype.h
rename to arch/arm/plat-samsung/include/plat/regs-irqtype.h
diff --git a/arch/arm/plat-s3c/include/plat/regs-nand.h b/arch/arm/plat-samsung/include/plat/regs-nand.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/regs-nand.h
rename to arch/arm/plat-samsung/include/plat/regs-nand.h
diff --git a/arch/arm/plat-s3c/include/plat/regs-rtc.h b/arch/arm/plat-samsung/include/plat/regs-rtc.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/regs-rtc.h
rename to arch/arm/plat-samsung/include/plat/regs-rtc.h
diff --git a/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h b/arch/arm/plat-samsung/include/plat/regs-s3c2412-iis.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h
rename to arch/arm/plat-samsung/include/plat/regs-s3c2412-iis.h
diff --git a/arch/arm/plat-s3c/include/plat/regs-sdhci.h b/arch/arm/plat-samsung/include/plat/regs-sdhci.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/regs-sdhci.h
rename to arch/arm/plat-samsung/include/plat/regs-sdhci.h
diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h
new file mode 100644
index 0000000..a6eba84
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-serial.h
@@ -0,0 +1,281 @@
+/* arch/arm/plat-samsung/include/plat/regs-serial.h
+ *
+ *  From linux/include/asm-arm/hardware/serial_s3c2410.h
+ *
+ *  Internal header file for Samsung S3C2410 serial ports (UART0-2)
+ *
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *
+ *  Additional defines, Copyright 2003 Simtec Electronics (linux@simtec.co.uk)
+ *
+ *  Adapted from:
+ *
+ *  Internal header file for MX1ADS serial ports (UART1 & 2)
+ *
+ *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __ASM_ARM_REGS_SERIAL_H
+#define __ASM_ARM_REGS_SERIAL_H
+
+#define S3C24XX_VA_UART0      (S3C_VA_UART)
+#define S3C24XX_VA_UART1      (S3C_VA_UART + 0x4000 )
+#define S3C24XX_VA_UART2      (S3C_VA_UART + 0x8000 )
+#define S3C24XX_VA_UART3      (S3C_VA_UART + 0xC000 )
+
+#define S3C2410_PA_UART0      (S3C24XX_PA_UART)
+#define S3C2410_PA_UART1      (S3C24XX_PA_UART + 0x4000 )
+#define S3C2410_PA_UART2      (S3C24XX_PA_UART + 0x8000 )
+#define S3C2443_PA_UART3      (S3C24XX_PA_UART + 0xC000 )
+
+#define S3C2410_URXH	  (0x24)
+#define S3C2410_UTXH	  (0x20)
+#define S3C2410_ULCON	  (0x00)
+#define S3C2410_UCON	  (0x04)
+#define S3C2410_UFCON	  (0x08)
+#define S3C2410_UMCON	  (0x0C)
+#define S3C2410_UBRDIV	  (0x28)
+#define S3C2410_UTRSTAT	  (0x10)
+#define S3C2410_UERSTAT	  (0x14)
+#define S3C2410_UFSTAT	  (0x18)
+#define S3C2410_UMSTAT	  (0x1C)
+
+#define S3C2410_LCON_CFGMASK	  ((0xF<<3)|(0x3))
+
+#define S3C2410_LCON_CS5	  (0x0)
+#define S3C2410_LCON_CS6	  (0x1)
+#define S3C2410_LCON_CS7	  (0x2)
+#define S3C2410_LCON_CS8	  (0x3)
+#define S3C2410_LCON_CSMASK	  (0x3)
+
+#define S3C2410_LCON_PNONE	  (0x0)
+#define S3C2410_LCON_PEVEN	  (0x5 << 3)
+#define S3C2410_LCON_PODD	  (0x4 << 3)
+#define S3C2410_LCON_PMASK	  (0x7 << 3)
+
+#define S3C2410_LCON_STOPB	  (1<<2)
+#define S3C2410_LCON_IRM          (1<<6)
+
+#define S3C2440_UCON_CLKMASK	  (3<<10)
+#define S3C2440_UCON_PCLK	  (0<<10)
+#define S3C2440_UCON_UCLK	  (1<<10)
+#define S3C2440_UCON_PCLK2	  (2<<10)
+#define S3C2440_UCON_FCLK	  (3<<10)
+#define S3C2443_UCON_EPLL	  (3<<10)
+
+#define S3C6400_UCON_CLKMASK	(3<<10)
+#define S3C6400_UCON_PCLK	(0<<10)
+#define S3C6400_UCON_PCLK2	(2<<10)
+#define S3C6400_UCON_UCLK0	(1<<10)
+#define S3C6400_UCON_UCLK1	(3<<10)
+
+#define S3C2440_UCON2_FCLK_EN	  (1<<15)
+#define S3C2440_UCON0_DIVMASK	  (15 << 12)
+#define S3C2440_UCON1_DIVMASK	  (15 << 12)
+#define S3C2440_UCON2_DIVMASK	  (7 << 12)
+#define S3C2440_UCON_DIVSHIFT	  (12)
+
+#define S3C2412_UCON_CLKMASK	(3<<10)
+#define S3C2412_UCON_UCLK	(1<<10)
+#define S3C2412_UCON_USYSCLK	(3<<10)
+#define S3C2412_UCON_PCLK	(0<<10)
+#define S3C2412_UCON_PCLK2	(2<<10)
+
+#define S3C2410_UCON_UCLK	  (1<<10)
+#define S3C2410_UCON_SBREAK	  (1<<4)
+
+#define S3C2410_UCON_TXILEVEL	  (1<<9)
+#define S3C2410_UCON_RXILEVEL	  (1<<8)
+#define S3C2410_UCON_TXIRQMODE	  (1<<2)
+#define S3C2410_UCON_RXIRQMODE	  (1<<0)
+#define S3C2410_UCON_RXFIFO_TOI	  (1<<7)
+#define S3C2443_UCON_RXERR_IRQEN  (1<<6)
+#define S3C2443_UCON_LOOPBACK	  (1<<5)
+
+#define S3C2410_UCON_DEFAULT	  (S3C2410_UCON_TXILEVEL  | \
+				   S3C2410_UCON_RXILEVEL  | \
+				   S3C2410_UCON_TXIRQMODE | \
+				   S3C2410_UCON_RXIRQMODE | \
+				   S3C2410_UCON_RXFIFO_TOI)
+
+#define S3C2410_UFCON_FIFOMODE	  (1<<0)
+#define S3C2410_UFCON_TXTRIG0	  (0<<6)
+#define S3C2410_UFCON_RXTRIG8	  (1<<4)
+#define S3C2410_UFCON_RXTRIG12	  (2<<4)
+
+/* S3C2440 FIFO trigger levels */
+#define S3C2440_UFCON_RXTRIG1	  (0<<4)
+#define S3C2440_UFCON_RXTRIG8	  (1<<4)
+#define S3C2440_UFCON_RXTRIG16	  (2<<4)
+#define S3C2440_UFCON_RXTRIG32	  (3<<4)
+
+#define S3C2440_UFCON_TXTRIG0	  (0<<6)
+#define S3C2440_UFCON_TXTRIG16	  (1<<6)
+#define S3C2440_UFCON_TXTRIG32	  (2<<6)
+#define S3C2440_UFCON_TXTRIG48	  (3<<6)
+
+#define S3C2410_UFCON_RESETBOTH	  (3<<1)
+#define S3C2410_UFCON_RESETTX	  (1<<2)
+#define S3C2410_UFCON_RESETRX	  (1<<1)
+
+#define S3C2410_UFCON_DEFAULT	  (S3C2410_UFCON_FIFOMODE | \
+				   S3C2410_UFCON_TXTRIG0  | \
+				   S3C2410_UFCON_RXTRIG8 )
+
+#define	S3C2410_UMCOM_AFC	  (1<<4)
+#define	S3C2410_UMCOM_RTS_LOW	  (1<<0)
+
+#define S3C2412_UMCON_AFC_63	(0<<5)		/* same as s3c2443 */
+#define S3C2412_UMCON_AFC_56	(1<<5)
+#define S3C2412_UMCON_AFC_48	(2<<5)
+#define S3C2412_UMCON_AFC_40	(3<<5)
+#define S3C2412_UMCON_AFC_32	(4<<5)
+#define S3C2412_UMCON_AFC_24	(5<<5)
+#define S3C2412_UMCON_AFC_16	(6<<5)
+#define S3C2412_UMCON_AFC_8	(7<<5)
+
+#define S3C2410_UFSTAT_TXFULL	  (1<<9)
+#define S3C2410_UFSTAT_RXFULL	  (1<<8)
+#define S3C2410_UFSTAT_TXMASK	  (15<<4)
+#define S3C2410_UFSTAT_TXSHIFT	  (4)
+#define S3C2410_UFSTAT_RXMASK	  (15<<0)
+#define S3C2410_UFSTAT_RXSHIFT	  (0)
+
+/* UFSTAT S3C24A0 */
+#define S3C24A0_UFSTAT_TXFULL	  (1 << 14)
+#define S3C24A0_UFSTAT_RXFULL	  (1 << 6)
+#define S3C24A0_UFSTAT_TXMASK	  (63 << 8)
+#define S3C24A0_UFSTAT_TXSHIFT	  (8)
+#define S3C24A0_UFSTAT_RXMASK	  (63)
+#define S3C24A0_UFSTAT_RXSHIFT	  (0)
+
+/* UFSTAT S3C2443 same as S3C2440 */
+#define S3C2440_UFSTAT_TXFULL	  (1<<14)
+#define S3C2440_UFSTAT_RXFULL	  (1<<6)
+#define S3C2440_UFSTAT_TXSHIFT	  (8)
+#define S3C2440_UFSTAT_RXSHIFT	  (0)
+#define S3C2440_UFSTAT_TXMASK	  (63<<8)
+#define S3C2440_UFSTAT_RXMASK	  (63)
+
+#define S3C2410_UTRSTAT_TXE	  (1<<2)
+#define S3C2410_UTRSTAT_TXFE	  (1<<1)
+#define S3C2410_UTRSTAT_RXDR	  (1<<0)
+
+#define S3C2410_UERSTAT_OVERRUN	  (1<<0)
+#define S3C2410_UERSTAT_FRAME	  (1<<2)
+#define S3C2410_UERSTAT_BREAK	  (1<<3)
+#define S3C2443_UERSTAT_PARITY	  (1<<1)
+
+#define S3C2410_UERSTAT_ANY	  (S3C2410_UERSTAT_OVERRUN | \
+				   S3C2410_UERSTAT_FRAME | \
+				   S3C2410_UERSTAT_BREAK)
+
+#define S3C2410_UMSTAT_CTS	  (1<<0)
+#define S3C2410_UMSTAT_DeltaCTS	  (1<<2)
+
+#define S3C2443_DIVSLOT		  (0x2C)
+
+/* S3C64XX interrupt registers. */
+#define S3C64XX_UINTP		0x30
+#define S3C64XX_UINTSP		0x34
+#define S3C64XX_UINTM		0x38
+
+/* Following are specific to S5PV210 and S5P6442 */
+#define S5PV210_UCON_CLKMASK	(1<<10)
+#define S5PV210_UCON_PCLK	(0<<10)
+#define S5PV210_UCON_UCLK	(1<<10)
+
+#define S5PV210_UFCON_TXTRIG0	(0<<8)
+#define S5PV210_UFCON_TXTRIG4	(1<<8)
+#define S5PV210_UFCON_TXTRIG8	(2<<8)
+#define S5PV210_UFCON_TXTRIG16	(3<<8)
+#define S5PV210_UFCON_TXTRIG32	(4<<8)
+#define S5PV210_UFCON_TXTRIG64	(5<<8)
+#define S5PV210_UFCON_TXTRIG128 (6<<8)
+#define S5PV210_UFCON_TXTRIG256 (7<<8)
+
+#define S5PV210_UFCON_RXTRIG1	(0<<4)
+#define S5PV210_UFCON_RXTRIG4	(1<<4)
+#define S5PV210_UFCON_RXTRIG8	(2<<4)
+#define S5PV210_UFCON_RXTRIG16	(3<<4)
+#define S5PV210_UFCON_RXTRIG32	(4<<4)
+#define S5PV210_UFCON_RXTRIG64	(5<<4)
+#define S5PV210_UFCON_RXTRIG128	(6<<4)
+#define S5PV210_UFCON_RXTRIG256	(7<<4)
+
+#define S5PV210_UFSTAT_TXFULL	(1<<24)
+#define S5PV210_UFSTAT_RXFULL	(1<<8)
+#define S5PV210_UFSTAT_TXMASK	(255<<16)
+#define S5PV210_UFSTAT_TXSHIFT	(16)
+#define S5PV210_UFSTAT_RXMASK	(255<<0)
+#define S5PV210_UFSTAT_RXSHIFT	(0)
+
+#ifndef __ASSEMBLY__
+
+/* struct s3c24xx_uart_clksrc
+ *
+ * this structure defines a named clock source that can be used for the
+ * uart, so that the best clock can be selected for the requested baud
+ * rate.
+ *
+ * min_baud and max_baud define the range of baud-rates this clock is
+ * acceptable for, if they are both zero, it is assumed any baud rate that
+ * can be generated from this clock will be used.
+ *
+ * divisor gives the divisor from the clock to the one seen by the uart
+*/
+
+struct s3c24xx_uart_clksrc {
+	const char	*name;
+	unsigned int	 divisor;
+	unsigned int	 min_baud;
+	unsigned int	 max_baud;
+};
+
+/* configuration structure for per-machine configurations for the
+ * serial port
+ *
+ * the pointer is setup by the machine specific initialisation from the
+ * arch/arm/mach-s3c2410/ directory.
+*/
+
+struct s3c2410_uartcfg {
+	unsigned char	   hwport;	 /* hardware port number */
+	unsigned char	   unused;
+	unsigned short	   flags;
+	upf_t		   uart_flags;	 /* default uart flags */
+
+	unsigned long	   ucon;	 /* value of ucon for port */
+	unsigned long	   ulcon;	 /* value of ulcon for port */
+	unsigned long	   ufcon;	 /* value of ufcon for port */
+
+	struct s3c24xx_uart_clksrc *clocks;
+	unsigned int		    clocks_size;
+};
+
+/* s3c24xx_uart_devs
+ *
+ * this is exported from the core as we cannot use driver_register(),
+ * or platform_add_device() before the console_initcall()
+*/
+
+extern struct platform_device *s3c24xx_uart_devs[4];
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_ARM_REGS_SERIAL_H */
+
diff --git a/arch/arm/plat-s3c/include/plat/regs-timer.h b/arch/arm/plat-samsung/include/plat/regs-timer.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/regs-timer.h
rename to arch/arm/plat-samsung/include/plat/regs-timer.h
diff --git a/arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h
new file mode 100644
index 0000000..a111ad8
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg-phy.h
@@ -0,0 +1,50 @@
+/* arch/arm/plat-s3c/include/plat/regs-usb-hsotg-phy.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      http://armlinux.simtec.co.uk/
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C - USB2.0 Highspeed/OtG device PHY registers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Note, this is a separate header file as some of the clock framework
+ * needs to touch this if the clk_48m is used as the USB OHCI or other
+ * peripheral source.
+*/
+
+#ifndef __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H
+#define __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H __FILE__
+
+/* S3C64XX_PA_USB_HSPHY */
+
+#define S3C_HSOTG_PHYREG(x)	((x) + S3C_VA_USB_HSPHY)
+
+#define S3C_PHYPWR				S3C_HSOTG_PHYREG(0x00)
+#define SRC_PHYPWR_OTG_DISABLE			(1 << 4)
+#define SRC_PHYPWR_ANALOG_POWERDOWN		(1 << 3)
+#define SRC_PHYPWR_FORCE_SUSPEND		(1 << 1)
+
+#define S3C_PHYCLK				S3C_HSOTG_PHYREG(0x04)
+#define S3C_PHYCLK_MODE_USB11			(1 << 6)
+#define S3C_PHYCLK_EXT_OSC			(1 << 5)
+#define S3C_PHYCLK_CLK_FORCE			(1 << 4)
+#define S3C_PHYCLK_ID_PULL			(1 << 2)
+#define S3C_PHYCLK_CLKSEL_MASK			(0x3 << 0)
+#define S3C_PHYCLK_CLKSEL_SHIFT			(0)
+#define S3C_PHYCLK_CLKSEL_48M			(0x0 << 0)
+#define S3C_PHYCLK_CLKSEL_12M			(0x2 << 0)
+#define S3C_PHYCLK_CLKSEL_24M			(0x3 << 0)
+
+#define S3C_RSTCON				S3C_HSOTG_PHYREG(0x08)
+#define S3C_RSTCON_PHYCLK			(1 << 2)
+#define S3C_RSTCON_HCLK				(1 << 2)
+#define S3C_RSTCON_PHY				(1 << 0)
+
+#define S3C_PHYTUNE				S3C_HSOTG_PHYREG(0x20)
+
+#endif /* __PLAT_S3C64XX_REGS_USB_HSOTG_PHY_H */
diff --git a/arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h b/arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/regs-usb-hsotg.h
rename to arch/arm/plat-samsung/include/plat/regs-usb-hsotg.h
diff --git a/arch/arm/plat-s3c/include/plat/regs-watchdog.h b/arch/arm/plat-samsung/include/plat/regs-watchdog.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/regs-watchdog.h
rename to arch/arm/plat-samsung/include/plat/regs-watchdog.h
diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
new file mode 100644
index 0000000..d177241
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
@@ -0,0 +1,67 @@
+/* linux/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
+ *
+ * Copyright (C) 2009 Samsung Electronics Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __S3C64XX_PLAT_SPI_H
+#define __S3C64XX_PLAT_SPI_H
+
+/**
+ * struct s3c64xx_spi_csinfo - ChipSelect description
+ * @fb_delay: Slave specific feedback delay.
+ *            Refer to FB_CLK_SEL register definition in SPI chapter.
+ * @line: Custom 'identity' of the CS line.
+ * @set_level: CS line control.
+ *
+ * This is per SPI-Slave Chipselect information.
+ * Allocate and initialize one in machine init code and make the
+ * spi_board_info.controller_data point to it.
+ */
+struct s3c64xx_spi_csinfo {
+	u8 fb_delay;
+	unsigned line;
+	void (*set_level)(unsigned line_id, int lvl);
+};
+
+/**
+ * struct s3c64xx_spi_info - SPI Controller defining structure
+ * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
+ * @src_clk_name: Platform name of the corresponding clock.
+ * @num_cs: Number of CS this controller emulates.
+ * @cfg_gpio: Configure pins for this SPI controller.
+ * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6
+ * @rx_lvl_offset: Depends on tx fifo_lvl field and bus number
+ * @high_speed: If the controller supports HIGH_SPEED_EN bit
+ */
+struct s3c64xx_spi_info {
+	int src_clk_nr;
+	char *src_clk_name;
+
+	int num_cs;
+
+	int (*cfg_gpio)(struct platform_device *pdev);
+
+	/* Following two fields are for future compatibility */
+	int fifo_lvl_mask;
+	int rx_lvl_offset;
+	int high_speed;
+};
+
+/**
+ * s3c64xx_spi_set_info - SPI Controller configure callback by the board
+ *				initialization code.
+ * @cntrlr: SPI controller number the configuration is for.
+ * @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks.
+ * @num_cs: Number of elements in the 'cs' array.
+ *
+ * Call this from machine init code for each SPI Controller that
+ * has some chips attached to it.
+ */
+extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
+
+#endif /* __S3C64XX_PLAT_SPI_H */
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
new file mode 100644
index 0000000..7d07cd7
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -0,0 +1,221 @@
+/* linux/arch/arm/plat-s3c/include/plat/sdhci.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C Platform - SDHCI (HSMMC) platform data definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __PLAT_S3C_SDHCI_H
+#define __PLAT_S3C_SDHCI_H __FILE__
+
+struct platform_device;
+struct mmc_host;
+struct mmc_card;
+struct mmc_ios;
+
+/**
+ * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI
+ * @max_width: The maximum number of data bits supported.
+ * @host_caps: Standard MMC host capabilities bit field.
+ * @cfg_gpio: Configure the GPIO for a specific card bit-width
+ * @cfg_card: Configure the interface for a specific card and speed. This
+ *            is necessary the controllers and/or GPIO blocks require the
+ *	      changing of driver-strength and other controls dependant on
+ *	      the card and speed of operation.
+ *
+ * Initialisation data specific to either the machine or the platform
+ * for the device driver to use or call-back when configuring gpio or
+ * card speed information.
+*/
+struct s3c_sdhci_platdata {
+	unsigned int	max_width;
+	unsigned int	host_caps;
+
+	char		**clocks;	/* set of clock sources */
+
+	void	(*cfg_gpio)(struct platform_device *dev, int width);
+	void	(*cfg_card)(struct platform_device *dev,
+			    void __iomem *regbase,
+			    struct mmc_ios *ios,
+			    struct mmc_card *card);
+};
+
+/**
+ * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
+ * @pd: Platform data to register to device.
+ *
+ * Register the given platform data for use withe S3C SDHCI device.
+ * The call will copy the platform data, so the board definitions can
+ * make the structure itself __initdata.
+ */
+extern void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd);
+extern void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd);
+extern void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd);
+
+/* Default platform data, exported so that per-cpu initialisation can
+ * set the correct one when there are more than one cpu type selected.
+*/
+
+extern struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata;
+extern struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata;
+extern struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata;
+
+/* Helper function availablity */
+
+extern void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
+extern void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
+extern void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
+extern void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
+extern void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
+extern void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
+
+/* S3C6400 SDHCI setup */
+
+#ifdef CONFIG_S3C64XX_SETUP_SDHCI
+extern char *s3c64xx_hsmmc_clksrcs[4];
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+extern void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev,
+					 void __iomem *r,
+					 struct mmc_ios *ios,
+					 struct mmc_card *card);
+
+static inline void s3c6400_default_sdhci0(void)
+{
+	s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
+	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
+	s3c_hsmmc0_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
+}
+
+#else
+static inline void s3c6400_default_sdhci0(void) { }
+#endif  /* CONFIG_S3C_DEV_HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC1
+static inline void s3c6400_default_sdhci1(void)
+{
+	s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
+	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
+	s3c_hsmmc1_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
+}
+#else
+static inline void s3c6400_default_sdhci1(void) { }
+#endif /* CONFIG_S3C_DEV_HSMMC1 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC2
+static inline void s3c6400_default_sdhci2(void)
+{
+	s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
+	s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
+	s3c_hsmmc2_def_platdata.cfg_card = s3c6400_setup_sdhci_cfg_card;
+}
+#else
+static inline void s3c6400_default_sdhci2(void) { }
+#endif /* CONFIG_S3C_DEV_HSMMC2 */
+
+/* S3C6410 SDHCI setup */
+
+extern void s3c6410_setup_sdhci_cfg_card(struct platform_device *dev,
+					 void __iomem *r,
+					 struct mmc_ios *ios,
+					 struct mmc_card *card);
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+static inline void s3c6410_default_sdhci0(void)
+{
+	s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
+	s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
+	s3c_hsmmc0_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
+}
+#else
+static inline void s3c6410_default_sdhci0(void) { }
+#endif /* CONFIG_S3C_DEV_HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC1
+static inline void s3c6410_default_sdhci1(void)
+{
+	s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
+	s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
+	s3c_hsmmc1_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
+}
+#else
+static inline void s3c6410_default_sdhci1(void) { }
+#endif /* CONFIG_S3C_DEV_HSMMC1 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC2
+static inline void s3c6410_default_sdhci2(void)
+{
+	s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
+	s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
+	s3c_hsmmc2_def_platdata.cfg_card = s3c6410_setup_sdhci_cfg_card;
+}
+#else
+static inline void s3c6410_default_sdhci2(void) { }
+#endif /* CONFIG_S3C_DEV_HSMMC2 */
+
+#else
+static inline void s3c6410_default_sdhci0(void) { }
+static inline void s3c6410_default_sdhci1(void) { }
+static inline void s3c6400_default_sdhci0(void) { }
+static inline void s3c6400_default_sdhci1(void) { }
+
+#endif /* CONFIG_S3C64XX_SETUP_SDHCI */
+
+/* S5PC100 SDHCI setup */
+
+#ifdef CONFIG_S5PC100_SETUP_SDHCI
+extern char *s5pc100_hsmmc_clksrcs[4];
+
+extern void s5pc100_setup_sdhci0_cfg_card(struct platform_device *dev,
+					   void __iomem *r,
+					   struct mmc_ios *ios,
+					   struct mmc_card *card);
+
+#ifdef CONFIG_S3C_DEV_HSMMC
+static inline void s5pc100_default_sdhci0(void)
+{
+	s3c_hsmmc0_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
+	s3c_hsmmc0_def_platdata.cfg_gpio = s5pc100_setup_sdhci0_cfg_gpio;
+	s3c_hsmmc0_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
+}
+#else
+static inline void s5pc100_default_sdhci0(void) { }
+#endif /* CONFIG_S3C_DEV_HSMMC */
+
+#ifdef CONFIG_S3C_DEV_HSMMC1
+static inline void s5pc100_default_sdhci1(void)
+{
+	s3c_hsmmc1_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
+	s3c_hsmmc1_def_platdata.cfg_gpio = s5pc100_setup_sdhci1_cfg_gpio;
+	s3c_hsmmc1_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
+}
+#else
+static inline void s5pc100_default_sdhci1(void) { }
+#endif /* CONFIG_S3C_DEV_HSMMC1 */
+
+#ifdef CONFIG_S3C_DEV_HSMMC2
+static inline void s5pc100_default_sdhci2(void)
+{
+	s3c_hsmmc2_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
+	s3c_hsmmc2_def_platdata.cfg_gpio = s5pc100_setup_sdhci2_cfg_gpio;
+	s3c_hsmmc2_def_platdata.cfg_card = s5pc100_setup_sdhci0_cfg_card;
+}
+#else
+static inline void s5pc100_default_sdhci2(void) { }
+#endif /* CONFIG_S3C_DEV_HSMMC1 */
+
+
+#else
+static inline void s5pc100_default_sdhci0(void) { }
+static inline void s5pc100_default_sdhci1(void) { }
+static inline void s5pc100_default_sdhci2(void) { }
+#endif /* CONFIG_S5PC100_SETUP_SDHCI */
+
+#endif /* __PLAT_S3C_SDHCI_H */
diff --git a/arch/arm/plat-samsung/include/plat/udc-hs.h b/arch/arm/plat-samsung/include/plat/udc-hs.h
new file mode 100644
index 0000000..a22a4f2
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/udc-hs.h
@@ -0,0 +1,29 @@
+/* arch/arm/plat-s3c/include/plat/udc-hs.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C USB2.0 High-speed / OtG platform information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+enum s3c_hsotg_dmamode {
+	S3C_HSOTG_DMA_NONE,	/* do not use DMA at-all */
+	S3C_HSOTG_DMA_ONLY,	/* always use DMA */
+	S3C_HSOTG_DMA_DRV,	/* DMA is chosen by driver */
+};
+
+/**
+ * struct s3c_hsotg_plat - platform data for high-speed otg/udc
+ * @dma: Whether to use DMA or not.
+ * @is_osc: The clock source is an oscillator, not a crystal
+ */
+struct s3c_hsotg_plat {
+	enum s3c_hsotg_dmamode	dma;
+	unsigned int		is_osc : 1;
+};
diff --git a/arch/arm/plat-samsung/include/plat/uncompress.h b/arch/arm/plat-samsung/include/plat/uncompress.h
new file mode 100644
index 0000000..e87ce8f
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/uncompress.h
@@ -0,0 +1,186 @@
+/* arch/arm/plat-samsung/include/plat/uncompress.h
+ *
+ * Copyright 2003, 2007 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C - uncompress code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_UNCOMPRESS_H
+#define __ASM_PLAT_UNCOMPRESS_H
+
+typedef unsigned int upf_t;	/* cannot include linux/serial_core.h */
+
+/* uart setup */
+
+static unsigned int fifo_mask;
+static unsigned int fifo_max;
+
+/* forward declerations */
+
+static void arch_detect_cpu(void);
+
+/* defines for UART registers */
+
+#include <plat/regs-serial.h>
+#include <plat/regs-watchdog.h>
+
+/* working in physical space... */
+#undef S3C2410_WDOGREG
+#define S3C2410_WDOGREG(x) ((S3C24XX_PA_WATCHDOG + (x)))
+
+/* how many bytes we allow into the FIFO at a time in FIFO mode */
+#define FIFO_MAX	 (14)
+
+#define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT)
+
+static __inline__ void
+uart_wr(unsigned int reg, unsigned int val)
+{
+	volatile unsigned int *ptr;
+
+	ptr = (volatile unsigned int *)(reg + uart_base);
+	*ptr = val;
+}
+
+static __inline__ unsigned int
+uart_rd(unsigned int reg)
+{
+	volatile unsigned int *ptr;
+
+	ptr = (volatile unsigned int *)(reg + uart_base);
+	return *ptr;
+}
+
+/* we can deal with the case the UARTs are being run
+ * in FIFO mode, so that we don't hold up our execution
+ * waiting for tx to happen...
+*/
+
+static void putc(int ch)
+{
+	if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
+		int level;
+
+		while (1) {
+			level = uart_rd(S3C2410_UFSTAT);
+			level &= fifo_mask;
+
+			if (level < fifo_max)
+				break;
+		}
+
+	} else {
+		/* not using fifos */
+
+		while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)
+			barrier();
+	}
+
+	/* write byte to transmission register */
+	uart_wr(S3C2410_UTXH, ch);
+}
+
+static inline void flush(void)
+{
+}
+
+#define __raw_writel(d, ad)			\
+	do {							\
+		*((volatile unsigned int __force *)(ad)) = (d); \
+	} while (0)
+
+/* CONFIG_S3C_BOOT_WATCHDOG
+ *
+ * Simple boot-time watchdog setup, to reboot the system if there is
+ * any problem with the boot process
+*/
+
+#ifdef CONFIG_S3C_BOOT_WATCHDOG
+
+#define WDOG_COUNT (0xff00)
+
+static inline void arch_decomp_wdog(void)
+{
+	__raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+}
+
+static void arch_decomp_wdog_start(void)
+{
+	__raw_writel(WDOG_COUNT, S3C2410_WTDAT);
+	__raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+	__raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON);
+}
+
+#else
+#define arch_decomp_wdog_start()
+#define arch_decomp_wdog()
+#endif
+
+#ifdef CONFIG_S3C_BOOT_ERROR_RESET
+
+static void arch_decomp_error(const char *x)
+{
+	putstr("\n\n");
+	putstr(x);
+	putstr("\n\n -- System resetting\n");
+
+	__raw_writel(0x4000, S3C2410_WTDAT);
+	__raw_writel(0x4000, S3C2410_WTCNT);
+	__raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
+
+	while(1);
+}
+
+#define arch_error arch_decomp_error
+#endif
+
+static void error(char *err);
+
+#ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO
+static inline void arch_enable_uart_fifo(void)
+{
+	u32 fifocon = uart_rd(S3C2410_UFCON);
+
+	if (!(fifocon & S3C2410_UFCON_FIFOMODE)) {
+		fifocon |= S3C2410_UFCON_RESETBOTH;
+		uart_wr(S3C2410_UFCON, fifocon);
+
+		/* wait for fifo reset to complete */
+		while (1) {
+			fifocon = uart_rd(S3C2410_UFCON);
+			if (!(fifocon & S3C2410_UFCON_RESETBOTH))
+				break;
+		}
+	}
+}
+#else
+#define arch_enable_uart_fifo() do { } while(0)
+#endif
+
+
+static void
+arch_decomp_setup(void)
+{
+	/* we may need to setup the uart(s) here if we are not running
+	 * on an BAST... the BAST will have left the uarts configured
+	 * after calling linux.
+	 */
+
+	arch_detect_cpu();
+	arch_decomp_wdog_start();
+
+	/* Enable the UART FIFOs if they where not enabled and our
+	 * configuration says we should turn them on.
+	 */
+
+	arch_enable_uart_fifo();
+}
+
+
+#endif /* __ASM_PLAT_UNCOMPRESS_H */
diff --git a/arch/arm/plat-samsung/include/plat/usb-control.h b/arch/arm/plat-samsung/include/plat/usb-control.h
new file mode 100644
index 0000000..7fa1fbe
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/usb-control.h
@@ -0,0 +1,43 @@
+/* arch/arm/plat-samsung/include/plat/usb-control.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C - USB host port information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_USBCONTROL_H
+#define __ASM_ARCH_USBCONTROL_H
+
+#define S3C_HCDFLG_USED	(1)
+
+struct s3c2410_hcd_port {
+	unsigned char	flags;
+	unsigned char	power;
+	unsigned char	oc_status;
+	unsigned char	oc_changed;
+};
+
+struct s3c2410_hcd_info {
+	struct usb_hcd		*hcd;
+	struct s3c2410_hcd_port	port[2];
+
+	void		(*power_control)(int port, int to);
+	void		(*enable_oc)(struct s3c2410_hcd_info *, int on);
+	void		(*report_oc)(struct s3c2410_hcd_info *, int ports);
+};
+
+static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports)
+{
+	if (info->report_oc != NULL) {
+		(info->report_oc)(info, ports);
+	}
+}
+
+extern void s3c_ohci_set_platdata(struct s3c2410_hcd_info *info);
+
+#endif /*__ASM_ARCH_USBCONTROL_H */
diff --git a/arch/arm/plat-s3c/include/plat/watchdog-reset.h b/arch/arm/plat-samsung/include/plat/watchdog-reset.h
similarity index 100%
rename from arch/arm/plat-s3c/include/plat/watchdog-reset.h
rename to arch/arm/plat-samsung/include/plat/watchdog-reset.h
diff --git a/arch/arm/plat-s3c/init.c b/arch/arm/plat-samsung/init.c
similarity index 100%
rename from arch/arm/plat-s3c/init.c
rename to arch/arm/plat-samsung/init.c
diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c
new file mode 100644
index 0000000..4f8c102
--- /dev/null
+++ b/arch/arm/plat-samsung/irq-uart.c
@@ -0,0 +1,143 @@
+/* arch/arm/plat-samsung/irq-uart.c
+ *	originally part of arch/arm/plat-s3c64xx/irq.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * Samsung- UART Interrupt handling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/serial_core.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+#include <plat/irq-uart.h>
+#include <plat/regs-serial.h>
+#include <plat/cpu.h>
+
+/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
+ * are consecutive when looking up the interrupt in the demux routines.
+ */
+
+static inline void __iomem *s3c_irq_uart_base(unsigned int irq)
+{
+	struct s3c_uart_irq *uirq = get_irq_chip_data(irq);
+	return uirq->regs;
+}
+
+static inline unsigned int s3c_irq_uart_bit(unsigned int irq)
+{
+	return irq & 3;
+}
+
+static void s3c_irq_uart_mask(unsigned int irq)
+{
+	void __iomem *regs = s3c_irq_uart_base(irq);
+	unsigned int bit = s3c_irq_uart_bit(irq);
+	u32 reg;
+
+	reg = __raw_readl(regs + S3C64XX_UINTM);
+	reg |= (1 << bit);
+	__raw_writel(reg, regs + S3C64XX_UINTM);
+}
+
+static void s3c_irq_uart_maskack(unsigned int irq)
+{
+	void __iomem *regs = s3c_irq_uart_base(irq);
+	unsigned int bit = s3c_irq_uart_bit(irq);
+	u32 reg;
+
+	reg = __raw_readl(regs + S3C64XX_UINTM);
+	reg |= (1 << bit);
+	__raw_writel(reg, regs + S3C64XX_UINTM);
+	__raw_writel(1 << bit, regs + S3C64XX_UINTP);
+}
+
+static void s3c_irq_uart_unmask(unsigned int irq)
+{
+	void __iomem *regs = s3c_irq_uart_base(irq);
+	unsigned int bit = s3c_irq_uart_bit(irq);
+	u32 reg;
+
+	reg = __raw_readl(regs + S3C64XX_UINTM);
+	reg &= ~(1 << bit);
+	__raw_writel(reg, regs + S3C64XX_UINTM);
+}
+
+static void s3c_irq_uart_ack(unsigned int irq)
+{
+	void __iomem *regs = s3c_irq_uart_base(irq);
+	unsigned int bit = s3c_irq_uart_bit(irq);
+
+	__raw_writel(1 << bit, regs + S3C64XX_UINTP);
+}
+
+static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
+{
+	struct s3c_uart_irq *uirq = desc->handler_data;
+	u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP);
+	int base = uirq->base_irq;
+
+	if (pend & (1 << 0))
+		generic_handle_irq(base);
+	if (pend & (1 << 1))
+		generic_handle_irq(base + 1);
+	if (pend & (1 << 2))
+		generic_handle_irq(base + 2);
+	if (pend & (1 << 3))
+		generic_handle_irq(base + 3);
+}
+
+static struct irq_chip s3c_irq_uart = {
+	.name		= "s3c-uart",
+	.mask		= s3c_irq_uart_mask,
+	.unmask		= s3c_irq_uart_unmask,
+	.mask_ack	= s3c_irq_uart_maskack,
+	.ack		= s3c_irq_uart_ack,
+};
+
+static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
+{
+	struct irq_desc *desc = irq_to_desc(uirq->parent_irq);
+	void __iomem *reg_base = uirq->regs;
+	unsigned int irq;
+	int offs;
+
+	/* mask all interrupts at the start. */
+	__raw_writel(0xf, reg_base + S3C64XX_UINTM);
+
+	for (offs = 0; offs < 3; offs++) {
+		irq = uirq->base_irq + offs;
+
+		set_irq_chip(irq, &s3c_irq_uart);
+		set_irq_chip_data(irq, uirq);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	desc->handler_data = uirq;
+	set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
+}
+
+/**
+ * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing
+ * @irq: The interrupt data for registering
+ * @nr_irqs: The number of interrupt descriptions in @irq.
+ *
+ * Register the UART interrupts specified by @irq including the demuxing
+ * routines. This supports the S3C6400 and newer style of devices.
+ */
+void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs)
+{
+	for (; nr_irqs > 0; nr_irqs--, irq++)
+		s3c_init_uart_irq(irq);
+}
diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c
new file mode 100644
index 0000000..0270519
--- /dev/null
+++ b/arch/arm/plat-samsung/irq-vic-timer.c
@@ -0,0 +1,86 @@
+/* arch/arm/plat-samsung/irq-vic-timer.c
+ *	originally part of arch/arm/plat-s3c64xx/irq.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * S3C64XX - Interrupt handling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+#include <plat/irq-vic-timer.h>
+#include <plat/regs-timer.h>
+
+static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc)
+{
+	generic_handle_irq((int)desc->handler_data);
+}
+
+/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
+
+static void s3c_irq_timer_mask(unsigned int irq)
+{
+	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
+
+	reg &= 0x1f;  /* mask out pending interrupts */
+	reg &= ~(1 << (irq - IRQ_TIMER0));
+	__raw_writel(reg, S3C64XX_TINT_CSTAT);
+}
+
+static void s3c_irq_timer_unmask(unsigned int irq)
+{
+	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
+
+	reg &= 0x1f;  /* mask out pending interrupts */
+	reg |= 1 << (irq - IRQ_TIMER0);
+	__raw_writel(reg, S3C64XX_TINT_CSTAT);
+}
+
+static void s3c_irq_timer_ack(unsigned int irq)
+{
+	u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
+
+	reg &= 0x1f;
+	reg |= (1 << 5) << (irq - IRQ_TIMER0);
+	__raw_writel(reg, S3C64XX_TINT_CSTAT);
+}
+
+static struct irq_chip s3c_irq_timer = {
+	.name		= "s3c-timer",
+	.mask		= s3c_irq_timer_mask,
+	.unmask		= s3c_irq_timer_unmask,
+	.ack		= s3c_irq_timer_ack,
+};
+
+/**
+ * s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\
+ * @parent_irq: The parent IRQ on the VIC for the timer.
+ * @timer_irq: The IRQ to be used for the timer.
+ *
+ * Register the necessary IRQ chaining and support for the timer IRQs
+ * chained of the VIC.
+ */
+void __init s3c_init_vic_timer_irq(unsigned int parent_irq,
+				   unsigned int timer_irq)
+{
+	struct irq_desc *desc = irq_to_desc(parent_irq);
+
+	set_irq_chained_handler(parent_irq, s3c_irq_demux_vic_timer);
+
+	set_irq_chip(timer_irq, &s3c_irq_timer);
+	set_irq_handler(timer_irq, handle_level_irq);
+	set_irq_flags(timer_irq, IRQF_VALID);
+
+	desc->handler_data = (void *)timer_irq;
+}
diff --git a/arch/arm/plat-samsung/pm-check.c b/arch/arm/plat-samsung/pm-check.c
new file mode 100644
index 0000000..0b5bb77
--- /dev/null
+++ b/arch/arm/plat-samsung/pm-check.c
@@ -0,0 +1,242 @@
+/* linux/arch/arm/plat-s3c/pm-check.c
+ *  originally in linux/arch/arm/plat-s3c24xx/pm.c
+ *
+ * Copyright (c) 2004-2008 Simtec Electronics
+ *	http://armlinux.simtec.co.uk
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C Power Mangament - suspend/resume memory corruptiuon check.
+ *
+ * This program is free software; you can redistribute it 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/suspend.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/ioport.h>
+
+#include <plat/pm.h>
+
+#if CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE < 1
+#error CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE must be a positive non-zero value
+#endif
+
+/* suspend checking code...
+ *
+ * this next area does a set of crc checks over all the installed
+ * memory, so the system can verify if the resume was ok.
+ *
+ * CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
+ * increasing it will mean that the area corrupted will be less easy to spot,
+ * and reducing the size will cause the CRC save area to grow
+*/
+
+#define CHECK_CHUNKSIZE (CONFIG_SAMSUNG_PM_CHECK_CHUNKSIZE * 1024)
+
+static u32 crc_size;	/* size needed for the crc block */
+static u32 *crcs;	/* allocated over suspend/resume */
+
+typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
+
+/* s3c_pm_run_res
+ *
+ * go through the given resource list, and look for system ram
+*/
+
+static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
+{
+	while (ptr != NULL) {
+		if (ptr->child != NULL)
+			s3c_pm_run_res(ptr->child, fn, arg);
+
+		if ((ptr->flags & IORESOURCE_MEM) &&
+		    strcmp(ptr->name, "System RAM") == 0) {
+			S3C_PMDBG("Found system RAM at %08lx..%08lx\n",
+				  (unsigned long)ptr->start,
+				  (unsigned long)ptr->end);
+			arg = (fn)(ptr, arg);
+		}
+
+		ptr = ptr->sibling;
+	}
+}
+
+static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg)
+{
+	s3c_pm_run_res(&iomem_resource, fn, arg);
+}
+
+static u32 *s3c_pm_countram(struct resource *res, u32 *val)
+{
+	u32 size = (u32)(res->end - res->start)+1;
+
+	size += CHECK_CHUNKSIZE-1;
+	size /= CHECK_CHUNKSIZE;
+
+	S3C_PMDBG("Area %08lx..%08lx, %d blocks\n",
+		  (unsigned long)res->start, (unsigned long)res->end, size);
+
+	*val += size * sizeof(u32);
+	return val;
+}
+
+/* s3c_pm_prepare_check
+ *
+ * prepare the necessary information for creating the CRCs. This
+ * must be done before the final save, as it will require memory
+ * allocating, and thus touching bits of the kernel we do not
+ * know about.
+*/
+
+void s3c_pm_check_prepare(void)
+{
+	crc_size = 0;
+
+	s3c_pm_run_sysram(s3c_pm_countram, &crc_size);
+
+	S3C_PMDBG("s3c_pm_prepare_check: %u checks needed\n", crc_size);
+
+	crcs = kmalloc(crc_size+4, GFP_KERNEL);
+	if (crcs == NULL)
+		printk(KERN_ERR "Cannot allocated CRC save area\n");
+}
+
+static u32 *s3c_pm_makecheck(struct resource *res, u32 *val)
+{
+	unsigned long addr, left;
+
+	for (addr = res->start; addr < res->end;
+	     addr += CHECK_CHUNKSIZE) {
+		left = res->end - addr;
+
+		if (left > CHECK_CHUNKSIZE)
+			left = CHECK_CHUNKSIZE;
+
+		*val = crc32_le(~0, phys_to_virt(addr), left);
+		val++;
+	}
+
+	return val;
+}
+
+/* s3c_pm_check_store
+ *
+ * compute the CRC values for the memory blocks before the final
+ * sleep.
+*/
+
+void s3c_pm_check_store(void)
+{
+	if (crcs != NULL)
+		s3c_pm_run_sysram(s3c_pm_makecheck, crcs);
+}
+
+/* in_region
+ *
+ * return TRUE if the area defined by ptr..ptr+size contains the
+ * what..what+whatsz
+*/
+
+static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
+{
+	if ((what+whatsz) < ptr)
+		return 0;
+
+	if (what > (ptr+size))
+		return 0;
+
+	return 1;
+}
+
+/**
+ * s3c_pm_runcheck() - helper to check a resource on restore.
+ * @res: The resource to check
+ * @vak: Pointer to list of CRC32 values to check.
+ *
+ * Called from the s3c_pm_check_restore() via s3c_pm_run_sysram(), this
+ * function runs the given memory resource checking it against the stored
+ * CRC to ensure that memory is restored. The function tries to skip as
+ * many of the areas used during the suspend process.
+ */
+static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
+{
+	void *save_at = phys_to_virt(s3c_sleep_save_phys);
+	unsigned long addr;
+	unsigned long left;
+	void *stkpage;
+	void *ptr;
+	u32 calc;
+
+	stkpage = (void *)((u32)&calc & ~PAGE_MASK);
+
+	for (addr = res->start; addr < res->end;
+	     addr += CHECK_CHUNKSIZE) {
+		left = res->end - addr;
+
+		if (left > CHECK_CHUNKSIZE)
+			left = CHECK_CHUNKSIZE;
+
+		ptr = phys_to_virt(addr);
+
+		if (in_region(ptr, left, stkpage, 4096)) {
+			S3C_PMDBG("skipping %08lx, has stack in\n", addr);
+			goto skip_check;
+		}
+
+		if (in_region(ptr, left, crcs, crc_size)) {
+			S3C_PMDBG("skipping %08lx, has crc block in\n", addr);
+			goto skip_check;
+		}
+
+		if (in_region(ptr, left, save_at, 32*4 )) {
+			S3C_PMDBG("skipping %08lx, has save block in\n", addr);
+			goto skip_check;
+		}
+
+		/* calculate and check the checksum */
+
+		calc = crc32_le(~0, ptr, left);
+		if (calc != *val) {
+			printk(KERN_ERR "Restore CRC error at "
+			       "%08lx (%08x vs %08x)\n", addr, calc, *val);
+
+			S3C_PMDBG("Restore CRC error at %08lx (%08x vs %08x)\n",
+			    addr, calc, *val);
+		}
+
+	skip_check:
+		val++;
+	}
+
+	return val;
+}
+
+/**
+ * s3c_pm_check_restore() - memory check called on resume
+ *
+ * check the CRCs after the restore event and free the memory used
+ * to hold them
+*/
+void s3c_pm_check_restore(void)
+{
+	if (crcs != NULL)
+		s3c_pm_run_sysram(s3c_pm_runcheck, crcs);
+}
+
+/**
+ * s3c_pm_check_cleanup() - free memory resources
+ *
+ * Free the resources that where allocated by the suspend
+ * memory check code. We do this separately from the
+ * s3c_pm_check_restore() function as we cannot call any
+ * functions that might sleep during that resume.
+ */
+void s3c_pm_check_cleanup(void)
+{
+	kfree(crcs);
+	crcs = NULL;
+}
+
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c
new file mode 100644
index 0000000..69a4c7f
--- /dev/null
+++ b/arch/arm/plat-samsung/pm-gpio.c
@@ -0,0 +1,380 @@
+
+/* linux/arch/arm/plat-s3c/pm-gpio.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C series GPIO PM code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/sysdev.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-core.h>
+#include <plat/pm.h>
+
+/* PM GPIO helpers */
+
+#define OFFS_CON	(0x00)
+#define OFFS_DAT	(0x04)
+#define OFFS_UP		(0x08)
+
+static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
+{
+	chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
+	chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
+}
+
+static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
+{
+	void __iomem *base = chip->base;
+	u32 old_gpcon = __raw_readl(base + OFFS_CON);
+	u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+	u32 gps_gpcon = chip->pm_save[0];
+	u32 gps_gpdat = chip->pm_save[1];
+	u32 gpcon;
+
+	/* GPACON only has one bit per control / data and no PULLUPs.
+	 * GPACON[x] = 0 => Output, 1 => SFN */
+
+	/* first set all SFN bits to SFN */
+
+	gpcon = old_gpcon | gps_gpcon;
+	__raw_writel(gpcon, base + OFFS_CON);
+
+	/* now set all the other bits */
+
+	__raw_writel(gps_gpdat, base + OFFS_DAT);
+	__raw_writel(gps_gpcon, base + OFFS_CON);
+
+	S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
+		  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
+}
+
+struct s3c_gpio_pm s3c_gpio_pm_1bit = {
+	.save	= s3c_gpio_pm_1bit_save,
+	.resume = s3c_gpio_pm_1bit_resume,
+};
+
+static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
+{
+	chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
+	chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
+	chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
+}
+
+/* Test whether the given masked+shifted bits of an GPIO configuration
+ * are one of the SFN (special function) modes. */
+
+static inline int is_sfn(unsigned long con)
+{
+	return con >= 2;
+}
+
+/* Test if the given masked+shifted GPIO configuration is an input */
+
+static inline int is_in(unsigned long con)
+{
+	return con == 0;
+}
+
+/* Test if the given masked+shifted GPIO configuration is an output */
+
+static inline int is_out(unsigned long con)
+{
+	return con == 1;
+}
+
+/**
+ * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
+ * @chip: The chip information to resume.
+ *
+ * Restore one of the GPIO banks that was saved during suspend. This is
+ * not as simple as once thought, due to the possibility of glitches
+ * from the order that the CON and DAT registers are set in.
+ *
+ * The three states the pin can be are {IN,OUT,SFN} which gives us 9
+ * combinations of changes to check. Three of these, if the pin stays
+ * in the same configuration can be discounted. This leaves us with
+ * the following:
+ *
+ * { IN => OUT }  Change DAT first
+ * { IN => SFN }  Change CON first
+ * { OUT => SFN } Change CON first, so new data will not glitch
+ * { OUT => IN }  Change CON first, so new data will not glitch
+ * { SFN => IN }  Change CON first
+ * { SFN => OUT } Change DAT first, so new data will not glitch [1]
+ *
+ * We do not currently deal with the UP registers as these control
+ * weak resistors, so a small delay in change should not need to bring
+ * these into the calculations.
+ *
+ * [1] this assumes that writing to a pin DAT whilst in SFN will set the
+ *     state for when it is next output.
+ */
+static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
+{
+	void __iomem *base = chip->base;
+	u32 old_gpcon = __raw_readl(base + OFFS_CON);
+	u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+	u32 gps_gpcon = chip->pm_save[0];
+	u32 gps_gpdat = chip->pm_save[1];
+	u32 gpcon, old, new, mask;
+	u32 change_mask = 0x0;
+	int nr;
+
+	/* restore GPIO pull-up settings */
+	__raw_writel(chip->pm_save[2], base + OFFS_UP);
+
+	/* Create a change_mask of all the items that need to have
+	 * their CON value changed before their DAT value, so that
+	 * we minimise the work between the two settings.
+	 */
+
+	for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
+		old = (old_gpcon & mask) >> nr;
+		new = (gps_gpcon & mask) >> nr;
+
+		/* If there is no change, then skip */
+
+		if (old == new)
+			continue;
+
+		/* If both are special function, then skip */
+
+		if (is_sfn(old) && is_sfn(new))
+			continue;
+
+		/* Change is IN => OUT, do not change now */
+
+		if (is_in(old) && is_out(new))
+			continue;
+
+		/* Change is SFN => OUT, do not change now */
+
+		if (is_sfn(old) && is_out(new))
+			continue;
+
+		/* We should now be at the case of IN=>SFN,
+		 * OUT=>SFN, OUT=>IN, SFN=>IN. */
+
+		change_mask |= mask;
+	}
+
+
+	/* Write the new CON settings */
+
+	gpcon = old_gpcon & ~change_mask;
+	gpcon |= gps_gpcon & change_mask;
+
+	__raw_writel(gpcon, base + OFFS_CON);
+
+	/* Now change any items that require DAT,CON */
+
+	__raw_writel(gps_gpdat, base + OFFS_DAT);
+	__raw_writel(gps_gpcon, base + OFFS_CON);
+
+	S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
+		  chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
+}
+
+struct s3c_gpio_pm s3c_gpio_pm_2bit = {
+	.save	= s3c_gpio_pm_2bit_save,
+	.resume = s3c_gpio_pm_2bit_resume,
+};
+
+#ifdef CONFIG_ARCH_S3C64XX
+static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
+{
+	chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
+	chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
+	chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
+
+	if (chip->chip.ngpio > 8)
+		chip->pm_save[0] = __raw_readl(chip->base - 4);
+}
+
+static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
+{
+	u32 old, new, mask;
+	u32 change_mask = 0x0;
+	int nr;
+
+	for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
+		old = (old_gpcon & mask) >> nr;
+		new = (gps_gpcon & mask) >> nr;
+
+		/* If there is no change, then skip */
+
+		if (old == new)
+			continue;
+
+		/* If both are special function, then skip */
+
+		if (is_sfn(old) && is_sfn(new))
+			continue;
+
+		/* Change is IN => OUT, do not change now */
+
+		if (is_in(old) && is_out(new))
+			continue;
+
+		/* Change is SFN => OUT, do not change now */
+
+		if (is_sfn(old) && is_out(new))
+			continue;
+
+		/* We should now be at the case of IN=>SFN,
+		 * OUT=>SFN, OUT=>IN, SFN=>IN. */
+
+		change_mask |= mask;
+	}
+
+	return change_mask;
+}
+
+static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
+{
+	void __iomem *con = chip->base + (index * 4);
+	u32 old_gpcon = __raw_readl(con);
+	u32 gps_gpcon = chip->pm_save[index + 1];
+	u32 gpcon, mask;
+
+	mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
+
+	gpcon = old_gpcon & ~mask;
+	gpcon |= gps_gpcon & mask;
+
+	__raw_writel(gpcon, con);
+}
+
+static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
+{
+	void __iomem *base = chip->base;
+	u32 old_gpcon[2];
+	u32 old_gpdat = __raw_readl(base + OFFS_DAT);
+	u32 gps_gpdat = chip->pm_save[2];
+
+	/* First, modify the CON settings */
+
+	old_gpcon[0] = 0;
+	old_gpcon[1] = __raw_readl(base + OFFS_CON);
+
+	s3c_gpio_pm_4bit_con(chip, 0);
+	if (chip->chip.ngpio > 8) {
+		old_gpcon[0] = __raw_readl(base - 4);
+		s3c_gpio_pm_4bit_con(chip, -1);
+	}
+
+	/* Now change the configurations that require DAT,CON */
+
+	__raw_writel(chip->pm_save[2], base + OFFS_DAT);
+	__raw_writel(chip->pm_save[1], base + OFFS_CON);
+	if (chip->chip.ngpio > 8)
+		__raw_writel(chip->pm_save[0], base - 4);
+
+	__raw_writel(chip->pm_save[2], base + OFFS_DAT);
+	__raw_writel(chip->pm_save[3], base + OFFS_UP);
+
+	if (chip->chip.ngpio > 8) {
+		S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
+			  chip->chip.label, old_gpcon[0], old_gpcon[1],
+			  __raw_readl(base - 4),
+			  __raw_readl(base + OFFS_CON),
+			  old_gpdat, gps_gpdat);
+	} else
+		S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
+			  chip->chip.label, old_gpcon[1],
+			  __raw_readl(base + OFFS_CON),
+			  old_gpdat, gps_gpdat);
+}
+
+struct s3c_gpio_pm s3c_gpio_pm_4bit = {
+	.save	= s3c_gpio_pm_4bit_save,
+	.resume = s3c_gpio_pm_4bit_resume,
+};
+#endif /* CONFIG_ARCH_S3C64XX */
+
+/**
+ * s3c_pm_save_gpio() - save gpio chip data for suspend
+ * @ourchip: The chip for suspend.
+ */
+static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
+{
+	struct s3c_gpio_pm *pm = ourchip->pm;
+
+	if (pm == NULL || pm->save == NULL)
+		S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
+	else
+		pm->save(ourchip);
+}
+
+/**
+ * s3c_pm_save_gpios() - Save the state of the GPIO banks.
+ *
+ * For all the GPIO banks, save the state of each one ready for going
+ * into a suspend mode.
+ */
+void s3c_pm_save_gpios(void)
+{
+	struct s3c_gpio_chip *ourchip;
+	unsigned int gpio_nr;
+
+	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+		ourchip = s3c_gpiolib_getchip(gpio_nr);
+		if (!ourchip)
+			continue;
+
+		s3c_pm_save_gpio(ourchip);
+
+		S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
+			  ourchip->chip.label,
+			  ourchip->pm_save[0],
+			  ourchip->pm_save[1],
+			  ourchip->pm_save[2],
+			  ourchip->pm_save[3]);
+
+		gpio_nr += ourchip->chip.ngpio;
+		gpio_nr += CONFIG_S3C_GPIO_SPACE;
+	}
+}
+
+/**
+ * s3c_pm_resume_gpio() - restore gpio chip data after suspend
+ * @ourchip: The suspended chip.
+ */
+static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
+{
+	struct s3c_gpio_pm *pm = ourchip->pm;
+
+	if (pm == NULL || pm->resume == NULL)
+		S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
+	else
+		pm->resume(ourchip);
+}
+
+void s3c_pm_restore_gpios(void)
+{
+	struct s3c_gpio_chip *ourchip;
+	unsigned int gpio_nr;
+
+	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+		ourchip = s3c_gpiolib_getchip(gpio_nr);
+		if (!ourchip)
+			continue;
+
+		s3c_pm_resume_gpio(ourchip);
+
+		gpio_nr += ourchip->chip.ngpio;
+		gpio_nr += CONFIG_S3C_GPIO_SPACE;
+	}
+}
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
new file mode 100644
index 0000000..27cfca5
--- /dev/null
+++ b/arch/arm/plat-samsung/pm.c
@@ -0,0 +1,378 @@
+/* linux/arch/arm/plat-s3c/pm.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2004-2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * S3C common power management (suspend to ram) support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <mach/hardware.h>
+#include <mach/map.h>
+
+#include <plat/regs-serial.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-irq.h>
+#include <asm/irq.h>
+
+#include <plat/pm.h>
+#include <mach/pm-core.h>
+
+/* for external use */
+
+unsigned long s3c_pm_flags;
+
+/* Debug code:
+ *
+ * This code supports debug output to the low level UARTs for use on
+ * resume before the console layer is available.
+*/
+
+#ifdef CONFIG_SAMSUNG_PM_DEBUG
+extern void printascii(const char *);
+
+void s3c_pm_dbg(const char *fmt, ...)
+{
+	va_list va;
+	char buff[256];
+
+	va_start(va, fmt);
+	vsprintf(buff, fmt, va);
+	va_end(va);
+
+	printascii(buff);
+}
+
+static inline void s3c_pm_debug_init(void)
+{
+	/* restart uart clocks so we can use them to output */
+	s3c_pm_debug_init_uart();
+}
+
+#else
+#define s3c_pm_debug_init() do { } while(0)
+
+#endif /* CONFIG_SAMSUNG_PM_DEBUG */
+
+/* Save the UART configurations if we are configured for debug. */
+
+unsigned char pm_uart_udivslot;
+
+#ifdef CONFIG_SAMSUNG_PM_DEBUG
+
+struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
+
+static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
+{
+	void __iomem *regs = S3C_VA_UARTx(uart);
+
+	save->ulcon = __raw_readl(regs + S3C2410_ULCON);
+	save->ucon = __raw_readl(regs + S3C2410_UCON);
+	save->ufcon = __raw_readl(regs + S3C2410_UFCON);
+	save->umcon = __raw_readl(regs + S3C2410_UMCON);
+	save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
+
+	if (pm_uart_udivslot)
+		save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
+
+	S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
+		  uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
+}
+
+static void s3c_pm_save_uarts(void)
+{
+	struct pm_uart_save *save = uart_save;
+	unsigned int uart;
+
+	for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
+		s3c_pm_save_uart(uart, save);
+}
+
+static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
+{
+	void __iomem *regs = S3C_VA_UARTx(uart);
+
+	s3c_pm_arch_update_uart(regs, save);
+
+	__raw_writel(save->ulcon, regs + S3C2410_ULCON);
+	__raw_writel(save->ucon,  regs + S3C2410_UCON);
+	__raw_writel(save->ufcon, regs + S3C2410_UFCON);
+	__raw_writel(save->umcon, regs + S3C2410_UMCON);
+	__raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
+
+	if (pm_uart_udivslot)
+		__raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
+}
+
+static void s3c_pm_restore_uarts(void)
+{
+	struct pm_uart_save *save = uart_save;
+	unsigned int uart;
+
+	for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
+		s3c_pm_restore_uart(uart, save);
+}
+#else
+static void s3c_pm_save_uarts(void) { }
+static void s3c_pm_restore_uarts(void) { }
+#endif
+
+/* The IRQ ext-int code goes here, it is too small to currently bother
+ * with its own file. */
+
+unsigned long s3c_irqwake_intmask	= 0xffffffffL;
+unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
+
+int s3c_irqext_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long bit = 1L << IRQ_EINT_BIT(irqno);
+
+	if (!(s3c_irqwake_eintallow & bit))
+		return -ENOENT;
+
+	printk(KERN_INFO "wake %s for irq %d\n",
+	       state ? "enabled" : "disabled", irqno);
+
+	if (!state)
+		s3c_irqwake_eintmask |= bit;
+	else
+		s3c_irqwake_eintmask &= ~bit;
+
+	return 0;
+}
+
+/* helper functions to save and restore register state */
+
+/**
+ * s3c_pm_do_save() - save a set of registers for restoration on resume.
+ * @ptr: Pointer to an array of registers.
+ * @count: Size of the ptr array.
+ *
+ * Run through the list of registers given, saving their contents in the
+ * array for later restoration when we wakeup.
+ */
+void s3c_pm_do_save(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		ptr->val = __raw_readl(ptr->reg);
+		S3C_PMDBG("saved %p value %08lx\n", ptr->reg, ptr->val);
+	}
+}
+
+/**
+ * s3c_pm_do_restore() - restore register values from the save list.
+ * @ptr: Pointer to an array of registers.
+ * @count: Size of the ptr array.
+ *
+ * Restore the register values saved from s3c_pm_do_save().
+ *
+ * Note, we do not use S3C_PMDBG() in here, as the system may not have
+ * restore the UARTs state yet
+*/
+
+void s3c_pm_do_restore(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
+		       ptr->reg, ptr->val, __raw_readl(ptr->reg));
+
+		__raw_writel(ptr->val, ptr->reg);
+	}
+}
+
+/**
+ * s3c_pm_do_restore_core() - early restore register values from save list.
+ *
+ * This is similar to s3c_pm_do_restore() except we try and minimise the
+ * side effects of the function in case registers that hardware might need
+ * to work has been restored.
+ *
+ * WARNING: Do not put any debug in here that may effect memory or use
+ * peripherals, as things may be changing!
+*/
+
+void s3c_pm_do_restore_core(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++)
+		__raw_writel(ptr->val, ptr->reg);
+}
+
+/* s3c2410_pm_show_resume_irqs
+ *
+ * print any IRQs asserted at resume time (ie, we woke from)
+*/
+static void s3c_pm_show_resume_irqs(int start, unsigned long which,
+				    unsigned long mask)
+{
+	int i;
+
+	which &= ~mask;
+
+	for (i = 0; i <= 31; i++) {
+		if (which & (1L<<i)) {
+			S3C_PMDBG("IRQ %d asserted at resume\n", start+i);
+		}
+	}
+}
+
+
+void (*pm_cpu_prep)(void);
+void (*pm_cpu_sleep)(void);
+
+#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
+
+/* s3c_pm_enter
+ *
+ * central control for sleep/resume process
+*/
+
+static int s3c_pm_enter(suspend_state_t state)
+{
+	static unsigned long regs_save[16];
+
+	/* ensure the debug is initialised (if enabled) */
+
+	s3c_pm_debug_init();
+
+	S3C_PMDBG("%s(%d)\n", __func__, state);
+
+	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
+		printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__);
+		return -EINVAL;
+	}
+
+	/* check if we have anything to wake-up with... bad things seem
+	 * to happen if you suspend with no wakeup (system will often
+	 * require a full power-cycle)
+	*/
+
+	if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
+	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
+		printk(KERN_ERR "%s: No wake-up sources!\n", __func__);
+		printk(KERN_ERR "%s: Aborting sleep\n", __func__);
+		return -EINVAL;
+	}
+
+	/* store the physical address of the register recovery block */
+
+	s3c_sleep_save_phys = virt_to_phys(regs_save);
+
+	S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys);
+
+	/* save all necessary core registers not covered by the drivers */
+
+	s3c_pm_save_gpios();
+	s3c_pm_save_uarts();
+	s3c_pm_save_core();
+
+	/* set the irq configuration for wake */
+
+	s3c_pm_configure_extint();
+
+	S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n",
+	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
+
+	s3c_pm_arch_prepare_irqs();
+
+	/* call cpu specific preparation */
+
+	pm_cpu_prep();
+
+	/* flush cache back to ram */
+
+	flush_cache_all();
+
+	s3c_pm_check_store();
+
+	/* send the cpu to sleep... */
+
+	s3c_pm_arch_stop_clocks();
+
+	/* s3c_cpu_save will also act as our return point from when
+	 * we resume as it saves its own register state and restores it
+	 * during the resume.  */
+
+	s3c_cpu_save(regs_save);
+
+	/* restore the cpu state using the kernel's cpu init code. */
+
+	cpu_init();
+
+	/* restore the system state */
+
+	s3c_pm_restore_core();
+	s3c_pm_restore_uarts();
+	s3c_pm_restore_gpios();
+
+	s3c_pm_debug_init();
+
+	/* check what irq (if any) restored the system */
+
+	s3c_pm_arch_show_resume_irqs();
+
+	S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
+
+	/* LEDs should now be 1110 */
+	s3c_pm_debug_smdkled(1 << 1, 0);
+
+	s3c_pm_check_restore();
+
+	/* ok, let's return from sleep */
+
+	S3C_PMDBG("S3C PM Resume (post-restore)\n");
+	return 0;
+}
+
+/* callback from assembly code */
+void s3c_pm_cb_flushcache(void)
+{
+	flush_cache_all();
+}
+
+static int s3c_pm_prepare(void)
+{
+	/* prepare check area if configured */
+
+	s3c_pm_check_prepare();
+	return 0;
+}
+
+static void s3c_pm_finish(void)
+{
+	s3c_pm_check_cleanup();
+}
+
+static struct platform_suspend_ops s3c_pm_ops = {
+	.enter		= s3c_pm_enter,
+	.prepare	= s3c_pm_prepare,
+	.finish		= s3c_pm_finish,
+	.valid		= suspend_valid_only_mem,
+};
+
+/* s3c_pm_init
+ *
+ * Attach the power management functions. This should be called
+ * from the board specific initialisation if the board supports
+ * it.
+*/
+
+int __init s3c_pm_init(void)
+{
+	printk("S3C Power Management, Copyright 2004 Simtec Electronics\n");
+
+	suspend_set_ops(&s3c_pm_ops);
+	return 0;
+}
diff --git a/arch/arm/plat-samsung/pwm-clock.c b/arch/arm/plat-samsung/pwm-clock.c
new file mode 100644
index 0000000..46c9381
--- /dev/null
+++ b/arch/arm/plat-samsung/pwm-clock.c
@@ -0,0 +1,455 @@
+/* linux/arch/arm/plat-s3c24xx/pwm-clock.c
+ *
+ * Copyright (c) 2007 Simtec Electronics
+ * Copyright (c) 2007, 2008 Ben Dooks
+ *	Ben Dooks <ben-linux@fluff.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.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/log2.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/map.h>
+#include <asm/irq.h>
+
+#include <plat/clock.h>
+#include <plat/cpu.h>
+
+#include <plat/regs-timer.h>
+#include <mach/pwm-clock.h>
+
+/* Each of the timers 0 through 5 go through the following
+ * clock tree, with the inputs depending on the timers.
+ *
+ * pclk ---- [ prescaler 0 ] -+---> timer 0
+ *			      +---> timer 1
+ *
+ * pclk ---- [ prescaler 1 ] -+---> timer 2
+ *			      +---> timer 3
+ *			      \---> timer 4
+ *
+ * Which are fed into the timers as so:
+ *
+ * prescaled 0 ---- [ div 2,4,8,16 ] ---\
+ *				       [mux] -> timer 0
+ * tclk 0 ------------------------------/
+ *
+ * prescaled 0 ---- [ div 2,4,8,16 ] ---\
+ *				       [mux] -> timer 1
+ * tclk 0 ------------------------------/
+ *
+ *
+ * prescaled 1 ---- [ div 2,4,8,16 ] ---\
+ *				       [mux] -> timer 2
+ * tclk 1 ------------------------------/
+ *
+ * prescaled 1 ---- [ div 2,4,8,16 ] ---\
+ *				       [mux] -> timer 3
+ * tclk 1 ------------------------------/
+ *
+ * prescaled 1 ---- [ div 2,4,8, 16 ] --\
+ *				       [mux] -> timer 4
+ * tclk 1 ------------------------------/
+ *
+ * Since the mux and the divider are tied together in the
+ * same register space, it is impossible to set the parent
+ * and the rate at the same time. To avoid this, we add an
+ * intermediate 'prescaled-and-divided' clock to select
+ * as the parent for the timer input clock called tdiv.
+ *
+ * prescaled clk --> pwm-tdiv ---\
+ *                             [ mux ] --> timer X
+ * tclk -------------------------/
+*/
+
+static struct clk clk_timer_scaler[];
+
+static unsigned long clk_pwm_scaler_get_rate(struct clk *clk)
+{
+	unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0);
+
+	if (clk == &clk_timer_scaler[1]) {
+		tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK;
+		tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT;
+	} else {
+		tcfg0 &= S3C2410_TCFG_PRESCALER0_MASK;
+	}
+
+	return clk_get_rate(clk->parent) / (tcfg0 + 1);
+}
+
+static unsigned long clk_pwm_scaler_round_rate(struct clk *clk,
+					       unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long divisor = parent_rate / rate;
+
+	if (divisor > 256)
+		divisor = 256;
+	else if (divisor < 2)
+		divisor = 2;
+
+	return parent_rate / divisor;
+}
+
+static int clk_pwm_scaler_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long round = clk_pwm_scaler_round_rate(clk, rate);
+	unsigned long tcfg0;
+	unsigned long divisor;
+	unsigned long flags;
+
+	divisor = clk_get_rate(clk->parent) / round;
+	divisor--;
+
+	local_irq_save(flags);
+	tcfg0 = __raw_readl(S3C2410_TCFG0);
+
+	if (clk == &clk_timer_scaler[1]) {
+		tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
+		tcfg0 |= divisor << S3C2410_TCFG_PRESCALER1_SHIFT;
+	} else {
+		tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
+		tcfg0 |= divisor;
+	}
+
+	__raw_writel(tcfg0, S3C2410_TCFG0);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static struct clk_ops clk_pwm_scaler_ops = {
+	.get_rate	= clk_pwm_scaler_get_rate,
+	.set_rate	= clk_pwm_scaler_set_rate,
+	.round_rate	= clk_pwm_scaler_round_rate,
+};
+
+static struct clk clk_timer_scaler[] = {
+	[0]	= {
+		.name		= "pwm-scaler0",
+		.id		= -1,
+		.ops		= &clk_pwm_scaler_ops,
+	},
+	[1]	= {
+		.name		= "pwm-scaler1",
+		.id		= -1,
+		.ops		= &clk_pwm_scaler_ops,
+	},
+};
+
+static struct clk clk_timer_tclk[] = {
+	[0]	= {
+		.name		= "pwm-tclk0",
+		.id		= -1,
+	},
+	[1]	= {
+		.name		= "pwm-tclk1",
+		.id		= -1,
+	},
+};
+
+struct pwm_tdiv_clk {
+	struct clk	clk;
+	unsigned int	divisor;
+};
+
+static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk)
+{
+	return container_of(clk, struct pwm_tdiv_clk, clk);
+}
+
+static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk)
+{
+	unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
+	unsigned int divisor;
+
+	tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
+	tcfg1 &= S3C2410_TCFG1_MUX_MASK;
+
+	if (pwm_cfg_src_is_tclk(tcfg1))
+		divisor = to_tdiv(clk)->divisor;
+	else
+		divisor = tcfg_to_divisor(tcfg1);
+
+	return clk_get_rate(clk->parent) / divisor;
+}
+
+static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk,
+					     unsigned long rate)
+{
+	unsigned long parent_rate;
+	unsigned long divisor;
+
+	parent_rate = clk_get_rate(clk->parent);
+	divisor = parent_rate / rate;
+
+	if (divisor <= 1 && pwm_tdiv_has_div1())
+		divisor = 1;
+	else if (divisor <= 2)
+		divisor = 2;
+	else if (divisor <= 4)
+		divisor = 4;
+	else if (divisor <= 8)
+		divisor = 8;
+	else
+		divisor = 16;
+
+	return parent_rate / divisor;
+}
+
+static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk)
+{
+	return pwm_tdiv_div_bits(divclk->divisor);
+}
+
+static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk)
+{
+	unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
+	unsigned long bits = clk_pwm_tdiv_bits(divclk);
+	unsigned long flags;
+	unsigned long shift =  S3C2410_TCFG1_SHIFT(divclk->clk.id);
+
+	local_irq_save(flags);
+
+	tcfg1 = __raw_readl(S3C2410_TCFG1);
+	tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
+	tcfg1 |= bits << shift;
+	__raw_writel(tcfg1, S3C2410_TCFG1);
+
+	local_irq_restore(flags);
+}
+
+static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct pwm_tdiv_clk *divclk = to_tdiv(clk);
+	unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long divisor;
+
+	tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
+	tcfg1 &= S3C2410_TCFG1_MUX_MASK;
+
+	rate = clk_round_rate(clk, rate);
+	divisor = parent_rate / rate;
+
+	if (divisor > 16)
+		return -EINVAL;
+
+	divclk->divisor = divisor;
+
+	/* Update the current MUX settings if we are currently
+	 * selected as the clock source for this clock. */
+
+	if (!pwm_cfg_src_is_tclk(tcfg1))
+		clk_pwm_tdiv_update(divclk);
+
+	return 0;
+}
+
+static struct clk_ops clk_tdiv_ops = {
+	.get_rate	= clk_pwm_tdiv_get_rate,
+	.set_rate	= clk_pwm_tdiv_set_rate,
+	.round_rate	= clk_pwm_tdiv_round_rate,
+};
+
+static struct pwm_tdiv_clk clk_timer_tdiv[] = {
+	[0]	= {
+		.clk	= {
+			.name	= "pwm-tdiv",
+			.ops	= &clk_tdiv_ops,
+			.parent	= &clk_timer_scaler[0],
+		},
+	},
+	[1]	= {
+		.clk	= {
+			.name	= "pwm-tdiv",
+			.ops	= &clk_tdiv_ops,
+			.parent	= &clk_timer_scaler[0],
+		}
+	},
+	[2]	= {
+		.clk	= {
+			.name	= "pwm-tdiv",
+			.ops	= &clk_tdiv_ops,
+			.parent	= &clk_timer_scaler[1],
+		},
+	},
+	[3]	= {
+		.clk	= {
+			.name	= "pwm-tdiv",
+			.ops	= &clk_tdiv_ops,
+			.parent	= &clk_timer_scaler[1],
+		},
+	},
+	[4]	= {
+		.clk	= {
+			.name	= "pwm-tdiv",
+			.ops	= &clk_tdiv_ops,
+			.parent	= &clk_timer_scaler[1],
+		},
+	},
+};
+
+static int __init clk_pwm_tdiv_register(unsigned int id)
+{
+	struct pwm_tdiv_clk *divclk = &clk_timer_tdiv[id];
+	unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
+
+	tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
+	tcfg1 &= S3C2410_TCFG1_MUX_MASK;
+
+	divclk->clk.id = id;
+	divclk->divisor = tcfg_to_divisor(tcfg1);
+
+	return s3c24xx_register_clock(&divclk->clk);
+}
+
+static inline struct clk *s3c24xx_pwmclk_tclk(unsigned int id)
+{
+	return (id >= 2) ? &clk_timer_tclk[1] : &clk_timer_tclk[0];
+}
+
+static inline struct clk *s3c24xx_pwmclk_tdiv(unsigned int id)
+{
+	return &clk_timer_tdiv[id].clk;
+}
+
+static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent)
+{
+	unsigned int id = clk->id;
+	unsigned long tcfg1;
+	unsigned long flags;
+	unsigned long bits;
+	unsigned long shift = S3C2410_TCFG1_SHIFT(id);
+
+	if (parent == s3c24xx_pwmclk_tclk(id))
+		bits = S3C_TCFG1_MUX_TCLK << shift;
+	else if (parent == s3c24xx_pwmclk_tdiv(id))
+		bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	local_irq_save(flags);
+
+	tcfg1 = __raw_readl(S3C2410_TCFG1);
+	tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
+	__raw_writel(tcfg1 | bits, S3C2410_TCFG1);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+static struct clk_ops clk_tin_ops = {
+	.set_parent	= clk_pwm_tin_set_parent,
+};
+
+static struct clk clk_tin[] = {
+	[0]	= {
+		.name	= "pwm-tin",
+		.id	= 0,
+		.ops	= &clk_tin_ops,
+	},
+	[1]	= {
+		.name	= "pwm-tin",
+		.id	= 1,
+		.ops	= &clk_tin_ops,
+	},
+	[2]	= {
+		.name	= "pwm-tin",
+		.id	= 2,
+		.ops	= &clk_tin_ops,
+	},
+	[3]	= {
+		.name	= "pwm-tin",
+		.id	= 3,
+		.ops	= &clk_tin_ops,
+	},
+	[4]	= {
+		.name	= "pwm-tin",
+		.id	= 4,
+		.ops	= &clk_tin_ops,
+	},
+};
+
+static __init int clk_pwm_tin_register(struct clk *pwm)
+{
+	unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
+	unsigned int id = pwm->id;
+
+	struct clk *parent;
+	int ret;
+
+	ret = s3c24xx_register_clock(pwm);
+	if (ret < 0)
+		return ret;
+
+	tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
+	tcfg1 &= S3C2410_TCFG1_MUX_MASK;
+
+	if (pwm_cfg_src_is_tclk(tcfg1))
+		parent = s3c24xx_pwmclk_tclk(id);
+	else
+		parent = s3c24xx_pwmclk_tdiv(id);
+
+	return clk_set_parent(pwm, parent);
+}
+
+/**
+ * s3c_pwmclk_init() - initialise pwm clocks
+ *
+ * Initialise and register the clocks which provide the inputs for the
+ * pwm timer blocks.
+ *
+ * Note, this call is required by the time core, so must be called after
+ * the base clocks are added and before any of the initcalls are run.
+ */
+__init void s3c_pwmclk_init(void)
+{
+	struct clk *clk_timers;
+	unsigned int clk;
+	int ret;
+
+	clk_timers = clk_get(NULL, "timers");
+	if (IS_ERR(clk_timers)) {
+		printk(KERN_ERR "%s: no parent clock\n", __func__);
+		return;
+	}
+
+	for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++)
+		clk_timer_scaler[clk].parent = clk_timers;
+
+	s3c_register_clocks(clk_timer_scaler, ARRAY_SIZE(clk_timer_scaler));
+	s3c_register_clocks(clk_timer_tclk, ARRAY_SIZE(clk_timer_tclk));
+
+	for (clk = 0; clk < ARRAY_SIZE(clk_timer_tdiv); clk++) {
+		ret = clk_pwm_tdiv_register(clk);
+
+		if (ret < 0) {
+			printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk);
+			return;
+		}
+	}
+
+	for (clk = 0; clk < ARRAY_SIZE(clk_tin); clk++) {
+		ret = clk_pwm_tin_register(&clk_tin[clk]);
+		if (ret < 0) {
+			printk(KERN_ERR "error adding pwm%d tin clock\n", clk);
+			return;
+		}
+	}
+}
diff --git a/arch/arm/plat-s3c/pwm.c b/arch/arm/plat-samsung/pwm.c
similarity index 100%
rename from arch/arm/plat-s3c/pwm.c
rename to arch/arm/plat-samsung/pwm.c
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c
new file mode 100644
index 0000000..2231d80
--- /dev/null
+++ b/arch/arm/plat-samsung/time.c
@@ -0,0 +1,285 @@
+/* linux/arch/arm/plat-samsung/time.c
+ *
+ * Copyright (C) 2003-2005 Simtec Electronics
+ *	Ben Dooks, <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include <asm/system.h>
+#include <asm/leds.h>
+#include <asm/mach-types.h>
+
+#include <asm/irq.h>
+#include <mach/map.h>
+#include <plat/regs-timer.h>
+#include <mach/regs-irq.h>
+#include <asm/mach/time.h>
+#include <mach/tick.h>
+
+#include <plat/clock.h>
+#include <plat/cpu.h>
+
+static unsigned long timer_startval;
+static unsigned long timer_usec_ticks;
+
+#ifndef TICK_MAX
+#define TICK_MAX (0xffff)
+#endif
+
+#define TIMER_USEC_SHIFT 16
+
+/* we use the shifted arithmetic to work out the ratio of timer ticks
+ * to usecs, as often the peripheral clock is not a nice even multiple
+ * of 1MHz.
+ *
+ * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok
+ * for the current HZ value of 200 without producing overflows.
+ *
+ * Original patch by Dimitry Andric, updated by Ben Dooks
+*/
+
+
+/* timer_mask_usec_ticks
+ *
+ * given a clock and divisor, make the value to pass into timer_ticks_to_usec
+ * to scale the ticks into usecs
+*/
+
+static inline unsigned long
+timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk)
+{
+	unsigned long den = pclk / 1000;
+
+	return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den;
+}
+
+/* timer_ticks_to_usec
+ *
+ * convert timer ticks to usec.
+*/
+
+static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
+{
+	unsigned long res;
+
+	res = ticks * timer_usec_ticks;
+	res += 1 << (TIMER_USEC_SHIFT - 4);	/* round up slightly */
+
+	return res >> TIMER_USEC_SHIFT;
+}
+
+/***
+ * Returns microsecond  since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ * IRQs are disabled before entering here from do_gettimeofday()
+ */
+
+static unsigned long s3c2410_gettimeoffset (void)
+{
+	unsigned long tdone;
+	unsigned long tval;
+
+	/* work out how many ticks have gone since last timer interrupt */
+
+	tval =  __raw_readl(S3C2410_TCNTO(4));
+	tdone = timer_startval - tval;
+
+	/* check to see if there is an interrupt pending */
+
+	if (s3c24xx_ostimer_pending()) {
+		/* re-read the timer, and try and fix up for the missed
+		 * interrupt. Note, the interrupt may go off before the
+		 * timer has re-loaded from wrapping.
+		 */
+
+		tval =  __raw_readl(S3C2410_TCNTO(4));
+		tdone = timer_startval - tval;
+
+		if (tval != 0)
+			tdone += timer_startval;
+	}
+
+	return timer_ticks_to_usec(tdone);
+}
+
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+s3c2410_timer_interrupt(int irq, void *dev_id)
+{
+	timer_tick();
+	return IRQ_HANDLED;
+}
+
+static struct irqaction s3c2410_timer_irq = {
+	.name		= "S3C2410 Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= s3c2410_timer_interrupt,
+};
+
+#define use_tclk1_12() ( \
+	machine_is_bast()	|| \
+	machine_is_vr1000()	|| \
+	machine_is_anubis()	|| \
+	machine_is_osiris())
+
+static struct clk *tin;
+static struct clk *tdiv;
+static struct clk *timerclk;
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ *
+ * Currently we only use timer4, as it is the only timer which has no
+ * other function that can be exploited externally
+ */
+static void s3c2410_timer_setup (void)
+{
+	unsigned long tcon;
+	unsigned long tcnt;
+	unsigned long tcfg1;
+	unsigned long tcfg0;
+
+	tcnt = TICK_MAX;  /* default value for tcnt */
+
+	/* configure the system for whichever machine is in use */
+
+	if (use_tclk1_12()) {
+		/* timer is at 12MHz, scaler is 1 */
+		timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
+		tcnt = 12000000 / HZ;
+
+		tcfg1 = __raw_readl(S3C2410_TCFG1);
+		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
+		tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
+		__raw_writel(tcfg1, S3C2410_TCFG1);
+	} else {
+		unsigned long pclk;
+		struct clk *tscaler;
+
+		/* for the h1940 (and others), we use the pclk from the core
+		 * to generate the timer values. since values around 50 to
+		 * 70MHz are not values we can directly generate the timer
+		 * value from, we need to pre-scale and divide before using it.
+		 *
+		 * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz
+		 * (8.45 ticks per usec)
+		 */
+
+		pclk = clk_get_rate(timerclk);
+
+		/* configure clock tick */
+
+		timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
+
+		tscaler = clk_get_parent(tdiv);
+
+		clk_set_rate(tscaler, pclk / 3);
+		clk_set_rate(tdiv, pclk / 6);
+		clk_set_parent(tin, tdiv);
+
+		tcnt = clk_get_rate(tin) / HZ;
+	}
+
+	tcon = __raw_readl(S3C2410_TCON);
+	tcfg0 = __raw_readl(S3C2410_TCFG0);
+	tcfg1 = __raw_readl(S3C2410_TCFG1);
+
+	/* timers reload after counting zero, so reduce the count by 1 */
+
+	tcnt--;
+
+	printk(KERN_DEBUG "timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n",
+	       tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks);
+
+	/* check to see if timer is within 16bit range... */
+	if (tcnt > TICK_MAX) {
+		panic("setup_timer: HZ is too small, cannot configure timer!");
+		return;
+	}
+
+	__raw_writel(tcfg1, S3C2410_TCFG1);
+	__raw_writel(tcfg0, S3C2410_TCFG0);
+
+	timer_startval = tcnt;
+	__raw_writel(tcnt, S3C2410_TCNTB(4));
+
+	/* ensure timer is stopped... */
+
+	tcon &= ~(7<<20);
+	tcon |= S3C2410_TCON_T4RELOAD;
+	tcon |= S3C2410_TCON_T4MANUALUPD;
+
+	__raw_writel(tcon, S3C2410_TCON);
+	__raw_writel(tcnt, S3C2410_TCNTB(4));
+	__raw_writel(tcnt, S3C2410_TCMPB(4));
+
+	/* start the timer running */
+	tcon |= S3C2410_TCON_T4START;
+	tcon &= ~S3C2410_TCON_T4MANUALUPD;
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void __init s3c2410_timer_resources(void)
+{
+	struct platform_device tmpdev;
+
+	tmpdev.dev.bus = &platform_bus_type;
+	tmpdev.id = 4;
+
+	timerclk = clk_get(NULL, "timers");
+	if (IS_ERR(timerclk))
+		panic("failed to get clock for system timer");
+
+	clk_enable(timerclk);
+
+	if (!use_tclk1_12()) {
+		tin = clk_get(&tmpdev.dev, "pwm-tin");
+		if (IS_ERR(tin))
+			panic("failed to get pwm-tin clock for system timer");
+
+		tdiv = clk_get(&tmpdev.dev, "pwm-tdiv");
+		if (IS_ERR(tdiv))
+			panic("failed to get pwm-tdiv clock for system timer");
+	}
+
+	clk_enable(tin);
+}
+
+static void __init s3c2410_timer_init(void)
+{
+	s3c2410_timer_resources();
+	s3c2410_timer_setup();
+	setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
+}
+
+struct sys_timer s3c24xx_timer = {
+	.init		= s3c2410_timer_init,
+	.offset		= s3c2410_gettimeoffset,
+	.resume		= s3c2410_timer_setup
+};
diff --git a/arch/avr32/include/asm/ptrace.h b/arch/avr32/include/asm/ptrace.h
index 9e2d44f..e53dd0d 100644
--- a/arch/avr32/include/asm/ptrace.h
+++ b/arch/avr32/include/asm/ptrace.h
@@ -124,6 +124,8 @@
 
 #include <asm/ocd.h>
 
+#define arch_has_single_step()		(1)
+
 #define arch_ptrace_attach(child)       ocd_enable(child)
 
 #define user_mode(regs)                 (((regs)->sr & MODE_MASK) == MODE_USER)
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c
index 1fed38f..dd5b882 100644
--- a/arch/avr32/kernel/ptrace.c
+++ b/arch/avr32/kernel/ptrace.c
@@ -28,9 +28,9 @@
 				  THREAD_SIZE - sizeof(struct pt_regs));
 }
 
-static void ptrace_single_step(struct task_struct *tsk)
+static void user_enable_single_step(struct task_struct *tsk)
 {
-	pr_debug("ptrace_single_step: pid=%u, PC=0x%08lx, SR=0x%08lx\n",
+	pr_debug("user_enable_single_step: pid=%u, PC=0x%08lx, SR=0x%08lx\n",
 		 tsk->pid, task_pt_regs(tsk)->pc, task_pt_regs(tsk)->sr);
 
 	/*
@@ -49,6 +49,11 @@
 	set_tsk_thread_flag(tsk, TIF_SINGLE_STEP);
 }
 
+void user_disable_single_step(struct task_struct *child)
+{
+	/* XXX(hch): a no-op here seems wrong.. */
+}
+
 /*
  * Called by kernel/ptrace.c when detaching
  *
@@ -167,50 +172,6 @@
 		ret = ptrace_write_user(child, addr, data);
 		break;
 
-	/* continue and stop at next (return from) syscall */
-	case PTRACE_SYSCALL:
-	/* restart after signal */
-	case PTRACE_CONT:
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		if (request == PTRACE_SYSCALL)
-			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		else
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->exit_code = data;
-		/* XXX: Are we sure no breakpoints are active here? */
-		wake_up_process(child);
-		ret = 0;
-		break;
-
-	/*
-	 * Make the child exit. Best I can do is send it a
-	 * SIGKILL. Perhaps it should be put in the status that it
-	 * wants to exit.
-	 */
-	case PTRACE_KILL:
-		ret = 0;
-		if (child->exit_state == EXIT_ZOMBIE)
-			break;
-		child->exit_code = SIGKILL;
-		wake_up_process(child);
-		break;
-
-	/*
-	 * execute single instruction.
-	 */
-	case PTRACE_SINGLESTEP:
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		ptrace_single_step(child);
-		child->exit_code = data;
-		wake_up_process(child);
-		ret = 0;
-		break;
-
 	case PTRACE_GETREGS:
 		ret = ptrace_getregs(child, (void __user *)data);
 		break;
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index b13d187..3a4bc1a 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -1770,10 +1770,13 @@
 					  ARRAY_SIZE(usba0_resource)))
 		goto out_free_pdev;
 
-	if (data)
+	if (data) {
 		usba_data.pdata.vbus_pin = data->vbus_pin;
-	else
+		usba_data.pdata.vbus_pin_inverted = data->vbus_pin_inverted;
+	} else {
 		usba_data.pdata.vbus_pin = -EINVAL;
+		usba_data.pdata.vbus_pin_inverted = -EINVAL;
+	}
 
 	data = &usba_data.pdata;
 	data->num_ep = ARRAY_SIZE(at32_usba_ep);
diff --git a/arch/blackfin/include/asm/dma-mapping.h b/arch/blackfin/include/asm/dma-mapping.h
index f9172ff..413a303 100644
--- a/arch/blackfin/include/asm/dma-mapping.h
+++ b/arch/blackfin/include/asm/dma-mapping.h
@@ -65,13 +65,6 @@
 	}
 }
 
-/*
- * Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
- *
- * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single is performed.
- */
 static inline dma_addr_t
 dma_map_single(struct device *dev, void *ptr, size_t size,
 	       enum dma_data_direction dir)
@@ -88,14 +81,6 @@
 	return dma_map_single(dev, page_address(page) + offset, size, dir);
 }
 
-/*
- * Unmap a single streaming mode DMA translation.  The dma_addr and size
- * must match what was provided for in a previous pci_map_single call.  All
- * other usages are undefined.
- *
- * After this call, reads by the cpu to the buffer are guarenteed to see
- * whatever the device wrote there.
- */
 static inline void
 dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		 enum dma_data_direction dir)
@@ -110,30 +95,9 @@
 	dma_unmap_single(dev, dma_addr, size, dir);
 }
 
-/*
- * Map a set of buffers described by scatterlist in streaming
- * mode for DMA.  This is the scather-gather version of the
- * above pci_map_single interface.  Here the scatter gather list
- * elements are each tagged with the appropriate dma address
- * and length.  They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of
- *       DMA address/length pairs than there are SG table elements.
- *       (for example via virtual mapping capabilities)
- *       The routine returns the number of addr/length pairs actually
- *       used, at most nents.
- *
- * Device ownership issues as mentioned above for pci_map_single are
- * the same here.
- */
 extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 		      enum dma_data_direction dir);
 
-/*
- * Unmap a set of streaming mode DMA translations.
- * Again, cpu read rules concerning calls here are the same as for
- * pci_unmap_single() above.
- */
 static inline void
 dma_unmap_sg(struct device *dev, struct scatterlist *sg,
 	     int nhwentries, enum dma_data_direction dir)
diff --git a/arch/blackfin/include/asm/nand.h b/arch/blackfin/include/asm/nand.h
index 3ae8b56..3a1e79d 100644
--- a/arch/blackfin/include/asm/nand.h
+++ b/arch/blackfin/include/asm/nand.h
@@ -1,5 +1,5 @@
 /*
- * BF5XX - NAND flash controller platfrom_device info
+ * BF5XX - NAND flash controller platform_device info
  *
  * Copyright 2007-2008 Analog Devices, Inc.
  *
@@ -8,7 +8,7 @@
 
 /* struct bf5xx_nand_platform
  *
- * define a interface between platfrom board specific code and
+ * define a interface between platform board specific code and
  * bf54x NFC driver.
  *
  * nr_partitions = number of partitions pointed to be partitoons (or zero)
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index b0ed0b4..01b2f58 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -816,8 +816,8 @@
 
 ENTRY(_ret_from_exception)
 #ifdef CONFIG_IPIPE
-	p2.l = _per_cpu__ipipe_percpu_domain;
-	p2.h = _per_cpu__ipipe_percpu_domain;
+	p2.l = _ipipe_percpu_domain;
+	p2.h = _ipipe_percpu_domain;
 	r0.l = _ipipe_root;
 	r0.h = _ipipe_root;
 	r2 = [p2];
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 7adac38..059eac6 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -20,6 +20,12 @@
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_TIME
+	def_bool y
+
+config ARCH_USES_GETTIMEOFFSET
+	def_bool y
+
 config GENERIC_IOMAP
        bool
        default y
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index 2c18d08..0d6420d 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -358,7 +358,7 @@
 1:	btstq	12, $r1		   ; Refill?
 	bpl	2f
 	lsrq	24, $r1     ; Get PGD index (bit 24-31)
-	move.d  [per_cpu__current_pgd], $r0 ; PGD for the current process
+	move.d  [current_pgd], $r0 ; PGD for the current process
 	move.d	[$r0+$r1.d], $r0   ; Get PMD
 	beq	2f
 	nop
@@ -692,7 +692,7 @@
 	.long sys_swapon
 	.long sys_reboot
 	.long sys_old_readdir
-	.long old_mmap		/* 90 */
+	.long sys_old_mmap	/* 90 */
 	.long sys_munmap
 	.long sys_truncate
 	.long sys_ftruncate
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index ee505b2..e70c804 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -127,57 +127,6 @@
 			ret = 0;
 			break;
 
-		case PTRACE_SYSCALL:
-		case PTRACE_CONT:
-			ret = -EIO;
-			
-			if (!valid_signal(data))
-				break;
-                        
-			if (request == PTRACE_SYSCALL) {
-				set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			}
-			else {
-				clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			}
-			
-			child->exit_code = data;
-			
-			/* TODO: make sure any pending breakpoint is killed */
-			wake_up_process(child);
-			ret = 0;
-			
-			break;
-		
- 		/* Make the child exit by sending it a sigkill. */
-		case PTRACE_KILL:
-			ret = 0;
-			
-			if (child->exit_state == EXIT_ZOMBIE)
-				break;
-			
-			child->exit_code = SIGKILL;
-			
-			/* TODO: make sure any pending breakpoint is killed */
-			wake_up_process(child);
-			break;
-
-		/* Set the trap flag. */
-		case PTRACE_SINGLESTEP:
-			ret = -EIO;
-			
-			if (!valid_signal(data))
-				break;
-			
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
-			/* TODO: set some clever breakpoint mechanism... */
-
-			child->exit_code = data;
-			wake_up_process(child);
-			ret = 0;
-			break;
-
 		/* Get all GP registers from the child. */
 		case PTRACE_GETREGS: {
 		  	int i;
diff --git a/arch/cris/arch-v10/lib/old_checksum.c b/arch/cris/arch-v10/lib/old_checksum.c
index 1734b46..8f79163 100644
--- a/arch/cris/arch-v10/lib/old_checksum.c
+++ b/arch/cris/arch-v10/lib/old_checksum.c
@@ -77,7 +77,7 @@
 		sum += *buff++;
 
 	if (endMarker > buff)
-		sum += *(const u8 *)buff;	/* add extra byte seperately */
+		sum += *(const u8 *)buff;	/* add extra byte separately */
 
 	BITOFF;
 	return (__force __wsum)sum;
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index fd529a0..b70fb34 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -628,9 +628,9 @@
 		cdesc->dma_descr->buf = (char*)virt_to_phys(operation->tfrm_op.indata[*iniov_ix].iov_base + *iniov_offset);
 		cdesc->dma_descr->after = cdesc->dma_descr->buf + dlength;
 
+		assert(desc_len >= dlength);
 		desc_len -= dlength;
 		*iniov_offset += dlength;
-		assert(desc_len >= 0);
 		if (*iniov_offset >= operation->tfrm_op.indata[*iniov_ix].iov_len) {
 			*iniov_offset = 0;
 			++(*iniov_ix);
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S
index 435b967..1f39861 100644
--- a/arch/cris/arch-v32/kernel/entry.S
+++ b/arch/cris/arch-v32/kernel/entry.S
@@ -615,7 +615,7 @@
 	.long sys_swapon
 	.long sys_reboot
 	.long sys_old_readdir
-	.long old_mmap		/* 90 */
+	.long sys_old_mmap	/* 90 */
 	.long sys_munmap
 	.long sys_truncate
 	.long sys_ftruncate
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index dd40147..f4ebd1e 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -78,6 +78,35 @@
 	return 0;
 }
 
+void user_enable_single_step(struct task_struct *child)
+{
+	unsigned long tmp;
+
+	/*
+	 * Set up SPC if not set already (in which case we have no other
+	 * choice but to trust it).
+	 */
+	if (!get_reg(child, PT_SPC)) {
+		/* In case we're stopped in a delay slot. */
+		tmp = get_reg(child, PT_ERP) & ~1;
+		put_reg(child, PT_SPC, tmp);
+	}
+	tmp = get_reg(child, PT_CCS) | SBIT_USER;
+	put_reg(child, PT_CCS, tmp);
+}
+
+void user_disable_single_step(struct task_struct *child)
+{
+	put_reg(child, PT_SPC, 0);
+
+	if (!get_debugreg(child->pid, PT_BP_CTRL)) {
+		unsigned long tmp;
+		/* If no h/w bp configured, disable S bit. */
+		tmp = get_reg(child, PT_CCS) & ~SBIT_USER;
+		put_reg(child, PT_CCS, tmp);
+	}
+}
+
 /*
  * Called by kernel/ptrace.c when detaching.
  *
@@ -89,8 +118,7 @@
 	unsigned long tmp;
 
 	/* Deconfigure SPC and S-bit. */
-	tmp = get_reg(child, PT_CCS) & ~SBIT_USER;
-	put_reg(child, PT_CCS, tmp);
+	user_disable_single_step(child);
 	put_reg(child, PT_SPC, 0);
 
 	/* Deconfigure any watchpoints associated with the child. */
@@ -169,83 +197,6 @@
 			ret = 0;
 			break;
 
-		case PTRACE_SYSCALL:
-		case PTRACE_CONT:
-			ret = -EIO;
-
-			if (!valid_signal(data))
-				break;
-
-			/* Continue means no single-step. */
-			put_reg(child, PT_SPC, 0);
-
-			if (!get_debugreg(child->pid, PT_BP_CTRL)) {
-				unsigned long tmp;
-				/* If no h/w bp configured, disable S bit. */
-				tmp = get_reg(child, PT_CCS) & ~SBIT_USER;
-				put_reg(child, PT_CCS, tmp);
-			}
-
-			if (request == PTRACE_SYSCALL) {
-				set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			}
-			else {
-				clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			}
-
-			child->exit_code = data;
-
-			/* TODO: make sure any pending breakpoint is killed */
-			wake_up_process(child);
-			ret = 0;
-
-			break;
-
-		/* Make the child exit by sending it a sigkill. */
-		case PTRACE_KILL:
-			ret = 0;
-
-			if (child->exit_state == EXIT_ZOMBIE)
-				break;
-
-			child->exit_code = SIGKILL;
-
-			/* Deconfigure single-step and h/w bp. */
-			ptrace_disable(child);
-
-			/* TODO: make sure any pending breakpoint is killed */
-			wake_up_process(child);
-			break;
-
-		/* Set the trap flag. */
-		case PTRACE_SINGLESTEP:	{
-			unsigned long tmp;
-			ret = -EIO;
-
-			/* Set up SPC if not set already (in which case we have
-			   no other choice but to trust it). */
-			if (!get_reg(child, PT_SPC)) {
-				/* In case we're stopped in a delay slot. */
-				tmp = get_reg(child, PT_ERP) & ~1;
-				put_reg(child, PT_SPC, tmp);
-			}
-			tmp = get_reg(child, PT_CCS) | SBIT_USER;
-			put_reg(child, PT_CCS, tmp);
-
-			if (!valid_signal(data))
-				break;
-
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
-			/* TODO: set some clever breakpoint mechanism... */
-
-			child->exit_code = data;
-			wake_up_process(child);
-			ret = 0;
-			break;
-
-		}
-
 		/* Get all GP registers from the child. */
 		case PTRACE_GETREGS: {
 			int i;
diff --git a/arch/cris/arch-v32/mach-fs/arbiter.c b/arch/cris/arch-v32/mach-fs/arbiter.c
index 84d31bd..82ef293 100644
--- a/arch/cris/arch-v32/mach-fs/arbiter.c
+++ b/arch/cris/arch-v32/mach-fs/arbiter.c
@@ -332,7 +332,7 @@
 	if (id == 0)
 		intr_mask.bp0 = regk_marb_no;
 	else if (id == 1)
-		intr_mask.bp2 = regk_marb_no;
+		intr_mask.bp1 = regk_marb_no;
 	else if (id == 2)
 		intr_mask.bp2 = regk_marb_no;
 	else if (id == 3)
diff --git a/arch/cris/arch-v32/mm/mmu.S b/arch/cris/arch-v32/mm/mmu.S
index 2238d15..f125d91 100644
--- a/arch/cris/arch-v32/mm/mmu.S
+++ b/arch/cris/arch-v32/mm/mmu.S
@@ -115,7 +115,7 @@
 #ifdef CONFIG_SMP
 	move    $s7, $acr	; PGD
 #else
-	move.d  per_cpu__current_pgd, $acr ; PGD
+	move.d  current_pgd, $acr ; PGD
 #endif
 	; Look up PMD in PGD
 	lsrq	24, $r0	; Get PMD index into PGD (bit 24-31)
diff --git a/arch/cris/arch-v32/mm/tlb.c b/arch/cris/arch-v32/mm/tlb.c
index 6779bcb..c030d02 100644
--- a/arch/cris/arch-v32/mm/tlb.c
+++ b/arch/cris/arch-v32/mm/tlb.c
@@ -189,7 +189,7 @@
 		spin_unlock(&mmu_context_lock);
 
 		/*
-		 * Remember the pgd for the fault handlers. Keep a seperate
+		 * Remember the pgd for the fault handlers. Keep a separate
 		 * copy of it because current and active_mm might be invalid
 		 * at points where * there's still a need to derefer the pgd.
 		 */
diff --git a/arch/cris/include/arch-v32/arch/ptrace.h b/arch/cris/include/arch-v32/arch/ptrace.h
index 41f4e86..ffca8d0 100644
--- a/arch/cris/include/arch-v32/arch/ptrace.h
+++ b/arch/cris/include/arch-v32/arch/ptrace.h
@@ -108,6 +108,7 @@
 
 #ifdef __KERNEL__
 
+#define arch_has_single_step() (1)
 #define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0)
 #define instruction_pointer(regs) ((regs)->erp)
 extern void show_regs(struct pt_regs *);
diff --git a/arch/cris/include/asm/pci.h b/arch/cris/include/asm/pci.h
index 730ce40..9f1cd56 100644
--- a/arch/cris/include/asm/pci.h
+++ b/arch/cris/include/asm/pci.h
@@ -44,14 +44,6 @@
  */
 #define PCI_DMA_BUS_IS_PHYS	(1)
 
-/* pci_unmap_{page,single} is a nop so... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME)		(0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
-
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 			       enum pci_mmap_state mmap_state, int write_combine);
diff --git a/arch/cris/include/asm/unistd.h b/arch/cris/include/asm/unistd.h
index c170793..f6fad83 100644
--- a/arch/cris/include/asm/unistd.h
+++ b/arch/cris/include/asm/unistd.h
@@ -352,6 +352,7 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
@@ -364,6 +365,7 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_MMAP
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c
index c2bbb1a..7aa036e 100644
--- a/arch/cris/kernel/sys_cris.c
+++ b/arch/cris/kernel/sys_cris.c
@@ -26,24 +26,6 @@
 #include <asm/uaccess.h>
 #include <asm/segment.h>
 
-asmlinkage unsigned long old_mmap(unsigned long __user *args)
-{        
-	unsigned long buffer[6];
-	int err = -EFAULT;
-
-	if (copy_from_user(&buffer, args, sizeof(buffer)))
-		goto out;
-
-	err = -EINVAL;
-	if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */
-		goto out;
-
-	err = sys_mmap_pgoff(buffer[0], buffer[1], buffer[2], buffer[3],
-                       buffer[4], buffer[5] >> PAGE_SHIFT);
-out:
-	return err;
-}
-
 asmlinkage long
 sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
           unsigned long flags, unsigned long fd, unsigned long pgoff)
@@ -51,81 +33,3 @@
 	/* bug(?): 8Kb pages here */
         return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
 }
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly. (same as arch/i386)
- */
-
-asmlinkage int sys_ipc (uint call, int first, int second,
-			int third, void __user *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL);
-	case SEMTIMEDOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
-					(const struct timespec __user *)fifth);
-
-	case SEMGET:
-		return sys_semget (first, second, third);
-	case SEMCTL: {
-		union semun fourth;
-		if (!ptr)
-			return -EINVAL;
-		if (get_user(fourth.__pad, (void * __user *) ptr))
-			return -EFAULT;
-		return sys_semctl (first, second, third, fourth);
-	}
-
-	case MSGSND:
-		return sys_msgsnd (first, (struct msgbuf __user *) ptr, 
-				   second, third);
-	case MSGRCV:
-		switch (version) {
-		case 0: {
-			struct ipc_kludge tmp;
-			if (!ptr)
-				return -EINVAL;
-			
-			if (copy_from_user(&tmp,
-					   (struct ipc_kludge __user *) ptr, 
-					   sizeof (tmp)))
-				return -EFAULT;
-			return sys_msgrcv (first, tmp.msgp, second,
-					   tmp.msgtyp, third);
-		}
-		default:
-			return sys_msgrcv (first,
-					   (struct msgbuf __user *) ptr,
-					   second, fifth, third);
-		}
-	case MSGGET:
-		return sys_msgget ((key_t) first, second);
-	case MSGCTL:
-		return sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
-
-	case SHMAT: {
-                ulong raddr;
-                ret = do_shmat (first, (char __user *) ptr, second, &raddr);
-                if (ret)
-                        return ret;
-                return put_user (raddr, (ulong __user *) third);
-        }
-	case SHMDT: 
-		return sys_shmdt ((char __user *)ptr);
-	case SHMGET:
-		return sys_shmget (first, second, third);
-	case SHMCTL:
-		return sys_shmctl (first, second,
-				   (struct shmid_ds __user *) ptr);
-	default:
-		return -ENOSYS;
-	}
-}
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index 074fe7d..a05dd31 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -42,75 +42,11 @@
 extern unsigned long do_slow_gettimeoffset(void);
 static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
 
-/*
- * This version of gettimeofday has near microsecond resolution.
- *
- * Note: Division is quite slow on CRIS and do_gettimeofday is called
- *       rather often. Maybe we should do some kind of approximation here
- *       (a naive approximation would be to divide by 1024).
- */
-void do_gettimeofday(struct timeval *tv)
+u32 arch_gettimeoffset(void)
 {
-	unsigned long flags;
-	signed long usec, sec;
-	local_irq_save(flags);
-	usec = do_gettimeoffset();
-
-        /*
-	 * If time_adjust is negative then NTP is slowing the clock
-	 * so make sure not to go into next possible interval.
-	 * Better to lose some accuracy than have time go backwards..
-	 */
-	if (unlikely(time_adjust < 0) && usec > tickadj)
-		usec = tickadj;
-
-	sec = xtime.tv_sec;
-	usec += xtime.tv_nsec / 1000;
-	local_irq_restore(flags);
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
+	return do_gettimeoffset() * 1000;
 }
 
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irq(&xtime_lock);
-	/*
-	 * This is revolting. We need to set "xtime" correctly. However, the
-	 * value in this location is the value at the most recent update of
-	 * wall time.  Discover what correction gettimeofday() would have
-	 * made, and then undo it!
-	 */
-	nsec -= do_gettimeoffset() * NSEC_PER_USEC;
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-	set_normalized_timespec(&xtime, sec, nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	ntp_clear();
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-
 /*
  * BUG: This routine does not handle hour overflow properly; it just
  *      sets the minutes. Usually you'll only notice that after reboot!
diff --git a/arch/frv/include/asm/dma-mapping.h b/arch/frv/include/asm/dma-mapping.h
index b289887..6af5d83 100644
--- a/arch/frv/include/asm/dma-mapping.h
+++ b/arch/frv/include/asm/dma-mapping.h
@@ -7,6 +7,11 @@
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 
+/*
+ * See Documentation/DMA-API.txt for the description of how the
+ * following DMA API should work.
+ */
+
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
@@ -16,24 +21,9 @@
 void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp);
 void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle);
 
-/*
- * Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
- *
- * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single is performed.
- */
 extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 				 enum dma_data_direction direction);
 
-/*
- * Unmap a single streaming mode DMA translation.  The dma_addr and size
- * must match what was provided for in a previous pci_map_single call.  All
- * other usages are undefined.
- *
- * After this call, reads by the cpu to the buffer are guarenteed to see
- * whatever the device wrote there.
- */
 static inline
 void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		      enum dma_data_direction direction)
@@ -41,30 +31,9 @@
 	BUG_ON(direction == DMA_NONE);
 }
 
-/*
- * Map a set of buffers described by scatterlist in streaming
- * mode for DMA.  This is the scather-gather version of the
- * above pci_map_single interface.  Here the scatter gather list
- * elements are each tagged with the appropriate dma address
- * and length.  They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of
- *       DMA address/length pairs than there are SG table elements.
- *       (for example via virtual mapping capabilities)
- *       The routine returns the number of addr/length pairs actually
- *       used, at most nents.
- *
- * Device ownership issues as mentioned above for pci_map_single are
- * the same here.
- */
 extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 		      enum dma_data_direction direction);
 
-/*
- * Unmap a set of streaming mode DMA translations.
- * Again, cpu read rules concerning calls here are the same as for
- * pci_unmap_single() above.
- */
 static inline
 void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 	     enum dma_data_direction direction)
diff --git a/arch/frv/include/asm/pci.h b/arch/frv/include/asm/pci.h
index 492b5c4..0d59979 100644
--- a/arch/frv/include/asm/pci.h
+++ b/arch/frv/include/asm/pci.h
@@ -43,14 +43,6 @@
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_controller_num(PDEV)	(0)
 
-/* pci_unmap_{page,single} is a nop so... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME)		(0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
@@ -68,41 +60,4 @@
 #define PCIBIOS_MIN_IO		0x100
 #define PCIBIOS_MIN_MEM		0x00010000
 
-/* Make physical memory consistent for a single
- * streaming mode DMA translation after a transfer.
- *
- * If you perform a pci_map_single() but wish to interrogate the
- * buffer using the cpu, yet do not wish to teardown the PCI dma
- * mapping, you must call this function before doing so.  At the
- * next point you give the PCI dma address back to the card, the
- * device again owns the buffer.
- */
-static inline void pci_dma_sync_single(struct pci_dev *hwdev,
-				       dma_addr_t dma_handle,
-				       size_t size, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-
-	frv_cache_wback_inv((unsigned long)bus_to_virt(dma_handle),
-			    (unsigned long)bus_to_virt(dma_handle) + size);
-}
-
-/* Make physical memory consistent for a set of streaming
- * mode DMA translations after a transfer.
- *
- * The same as pci_dma_sync_single but for a scatter-gather list,
- * same rules and usage.
- */
-static inline void pci_dma_sync_sg(struct pci_dev *hwdev,
-				   struct scatterlist *sg,
-				   int nelems, int direction)
-{
-	int i;
-	BUG_ON(direction == PCI_DMA_NONE);
-
-	for (i = 0; i < nelems; i++)
-		frv_cache_wback_inv(sg_dma_address(&sg[i]),
-				    sg_dma_address(&sg[i])+sg_dma_len(&sg[i]));
-}
-
 #endif /* _ASM_FRV_PCI_H */
diff --git a/arch/frv/include/asm/ptrace.h b/arch/frv/include/asm/ptrace.h
index a54b535..6bfad4c 100644
--- a/arch/frv/include/asm/ptrace.h
+++ b/arch/frv/include/asm/ptrace.h
@@ -84,8 +84,6 @@
 #define task_pt_regs(task) ((task)->thread.frame0)
 
 #define arch_has_single_step()	(1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
 
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h
index be6ef0f..b28da49 100644
--- a/arch/frv/include/asm/unistd.h
+++ b/arch/frv/include/asm/unistd.h
@@ -354,6 +354,7 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 /* #define __ARCH_WANT_SYS_GETHOSTNAME */
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 /* #define __ARCH_WANT_SYS_SGETMASK */
 /* #define __ARCH_WANT_SYS_SIGNAL */
diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c
index 1d3d4c9..9c49808 100644
--- a/arch/frv/kernel/sys_frv.c
+++ b/arch/frv/kernel/sys_frv.c
@@ -42,92 +42,3 @@
 	return sys_mmap_pgoff(addr, len, prot, flags, fd,
 			      pgoff >> (PAGE_SHIFT - 12));
 }
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage long sys_ipc(unsigned long call,
-			unsigned long first,
-			unsigned long second,
-			unsigned long third,
-			void __user *ptr,
-			unsigned long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr, second, NULL);
-	case SEMTIMEDOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
-				      (const struct timespec __user *)fifth);
-
-	case SEMGET:
-		return sys_semget (first, second, third);
-	case SEMCTL: {
-		union semun fourth;
-		if (!ptr)
-			return -EINVAL;
-		if (get_user(fourth.__pad, (void * __user *) ptr))
-			return -EFAULT;
-		return sys_semctl (first, second, third, fourth);
-	}
-
-	case MSGSND:
-		return sys_msgsnd (first, (struct msgbuf __user *) ptr,
-				   second, third);
-	case MSGRCV:
-		switch (version) {
-		case 0: {
-			struct ipc_kludge tmp;
-			if (!ptr)
-				return -EINVAL;
-
-			if (copy_from_user(&tmp,
-					   (struct ipc_kludge __user *) ptr,
-					   sizeof (tmp)))
-				return -EFAULT;
-			return sys_msgrcv (first, tmp.msgp, second,
-					   tmp.msgtyp, third);
-		}
-		default:
-			return sys_msgrcv (first,
-					   (struct msgbuf __user *) ptr,
-					   second, fifth, third);
-		}
-	case MSGGET:
-		return sys_msgget ((key_t) first, second);
-	case MSGCTL:
-		return sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
-
-	case SHMAT:
-		switch (version) {
-		default: {
-			ulong raddr;
-			ret = do_shmat (first, (char __user *) ptr, second, &raddr);
-			if (ret)
-				return ret;
-			return put_user (raddr, (ulong __user *) third);
-		}
-		case 1:	/* iBCS2 emulator entry point */
-			if (!segment_eq(get_fs(), get_ds()))
-				return -EINVAL;
-			/* The "(ulong *) third" is valid _only_ because of the kernel segment thing */
-			return do_shmat (first, (char __user *) ptr, second, (ulong *) third);
-		}
-	case SHMDT:
-		return sys_shmdt ((char __user *)ptr);
-	case SHMGET:
-		return sys_shmget (first, second, third);
-	case SHMCTL:
-		return sys_shmctl (first, second,
-				   (struct shmid_ds __user *) ptr);
-	default:
-		return -ENOSYS;
-	}
-}
diff --git a/arch/frv/mb93090-mb00/pci-dma-nommu.c b/arch/frv/mb93090-mb00/pci-dma-nommu.c
index 4e1ba0b..e47857f 100644
--- a/arch/frv/mb93090-mb00/pci-dma-nommu.c
+++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c
@@ -106,13 +106,6 @@
 
 EXPORT_SYMBOL(dma_free_coherent);
 
-/*
- * Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
- *
- * Once the device is given the dma address, the device owns this memory
- * until either dma_unmap_single or pci_dma_sync_single is performed.
- */
 dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 			  enum dma_data_direction direction)
 {
@@ -125,22 +118,6 @@
 
 EXPORT_SYMBOL(dma_map_single);
 
-/*
- * Map a set of buffers described by scatterlist in streaming
- * mode for DMA.  This is the scather-gather version of the
- * above dma_map_single interface.  Here the scatter gather list
- * elements are each tagged with the appropriate dma address
- * and length.  They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of
- *       DMA address/length pairs than there are SG table elements.
- *       (for example via virtual mapping capabilities)
- *       The routine returns the number of addr/length pairs actually
- *       used, at most nents.
- *
- * Device ownership issues as mentioned above for dma_map_single are
- * the same here.
- */
 int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 	       enum dma_data_direction direction)
 {
@@ -157,13 +134,6 @@
 
 EXPORT_SYMBOL(dma_map_sg);
 
-/*
- * Map a single page of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
- *
- * Device ownership issues as mentioned above for dma_map_single are
- * the same here.
- */
 dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset,
 			size_t size, enum dma_data_direction direction)
 {
diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c
index 45954f0..2c912e8 100644
--- a/arch/frv/mb93090-mb00/pci-dma.c
+++ b/arch/frv/mb93090-mb00/pci-dma.c
@@ -38,13 +38,6 @@
 
 EXPORT_SYMBOL(dma_free_coherent);
 
-/*
- * Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
- *
- * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single is performed.
- */
 dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 			  enum dma_data_direction direction)
 {
@@ -57,22 +50,6 @@
 
 EXPORT_SYMBOL(dma_map_single);
 
-/*
- * Map a set of buffers described by scatterlist in streaming
- * mode for DMA.  This is the scather-gather version of the
- * above dma_map_single interface.  Here the scatter gather list
- * elements are each tagged with the appropriate dma address
- * and length.  They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of
- *       DMA address/length pairs than there are SG table elements.
- *       (for example via virtual mapping capabilities)
- *       The routine returns the number of addr/length pairs actually
- *       used, at most nents.
- *
- * Device ownership issues as mentioned above for dma_map_single are
- * the same here.
- */
 int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 	       enum dma_data_direction direction)
 {
@@ -103,13 +80,6 @@
 
 EXPORT_SYMBOL(dma_map_sg);
 
-/*
- * Map a single page of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
- *
- * Device ownership issues as mentioned above for dma_map_single are
- * the same here.
- */
 dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset,
 			size_t size, enum dma_data_direction direction)
 {
diff --git a/arch/h8300/include/asm/io.h b/arch/h8300/include/asm/io.h
index 33e842f..c1a8df2 100644
--- a/arch/h8300/include/asm/io.h
+++ b/arch/h8300/include/asm/io.h
@@ -25,7 +25,7 @@
  * memory location directly.
  */
 /* ++roman: The assignments to temp. vars avoid that gcc sometimes generates
- * two accesses to memory, which may be undesireable for some devices.
+ * two accesses to memory, which may be undesirable for some devices.
  */
 
 /*
diff --git a/arch/h8300/include/asm/ptrace.h b/arch/h8300/include/asm/ptrace.h
index c2e05e4..d866c0e 100644
--- a/arch/h8300/include/asm/ptrace.h
+++ b/arch/h8300/include/asm/ptrace.h
@@ -55,6 +55,8 @@
 /* Find the stack offset for a register, relative to thread.esp0. */
 #define PT_REG(reg)	((long)&((struct pt_regs *)0)->reg)
 
+#define arch_has_single_step()	(1)
+
 #define user_mode(regs) (!((regs)->ccr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h
index 99f3c35..50f2c5a3 100644
--- a/arch/h8300/include/asm/unistd.h
+++ b/arch/h8300/include/asm/unistd.h
@@ -336,6 +336,7 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
@@ -348,6 +349,8 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_MMAP
+#define __ARCH_WANT_SYS_OLD_SELECT
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index d32bbf0..df11412 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -34,25 +34,20 @@
 /* cpu depend functions */
 extern long h8300_get_reg(struct task_struct *task, int regno);
 extern int  h8300_put_reg(struct task_struct *task, int regno, unsigned long data);
-extern void h8300_disable_trace(struct task_struct *child);
-extern void h8300_enable_trace(struct task_struct *child);
+
+
+void user_disable_single_step(struct task_struct *child)
+{
+}
 
 /*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
  */
 
-inline
-static int read_long(struct task_struct * tsk, unsigned long addr,
-	unsigned long * result)
-{
-	*result = *(unsigned long *)addr;
-	return 0;
-}
-
 void ptrace_disable(struct task_struct *child)
 {
-	h8300_disable_trace(child);
+	user_disable_single_step(child);
 }
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
@@ -60,17 +55,6 @@
 	int ret;
 
 	switch (request) {
-		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
-		case PTRACE_PEEKDATA: {
-			unsigned long tmp;
-
-			ret = read_long(child, addr, &tmp);
-			if (ret < 0)
-				break ;
-			ret = put_user(tmp, (unsigned long *) data);
-			break ;
-		}
-
 	/* read the word at location addr in the USER area. */
 		case PTRACE_PEEKUSR: {
 			unsigned long tmp = 0;
@@ -109,11 +93,6 @@
 		}
 
       /* when I and D space are separate, this will have to be fixed. */
-		case PTRACE_POKETEXT: /* write the word at location addr. */
-		case PTRACE_POKEDATA:
-			ret = generic_ptrace_pokedata(child, addr, data);
-			break;
-
 		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
 			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) {
 				ret = -EIO;
@@ -131,53 +110,6 @@
 			}
 			ret = -EIO;
 			break ;
-		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-		case PTRACE_CONT: { /* restart after signal. */
-			ret = -EIO;
-			if (!valid_signal(data))
-				break ;
-			if (request == PTRACE_SYSCALL)
-				set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			else
-				clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			child->exit_code = data;
-			wake_up_process(child);
-			/* make sure the single step bit is not set. */
-			h8300_disable_trace(child);
-			ret = 0;
-		}
-
-/*
- * make the child exit.  Best I can do is send it a sigkill. 
- * perhaps it should be put in the status that it wants to 
- * exit.
- */
-		case PTRACE_KILL: {
-
-			ret = 0;
-			if (child->exit_state == EXIT_ZOMBIE) /* already dead */
-				break;
-			child->exit_code = SIGKILL;
-			h8300_disable_trace(child);
-			wake_up_process(child);
-			break;
-		}
-
-		case PTRACE_SINGLESTEP: {  /* set the trap flag. */
-			ret = -EIO;
-			if (!valid_signal(data))
-				break;
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			child->exit_code = data;
-			h8300_enable_trace(child);
-			wake_up_process(child);
-			ret = 0;
-			break;
-		}
-
-		case PTRACE_DETACH:	/* detach a process that was attached. */
-			ret = ptrace_detach(child, data);
-			break;
 
 		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
 		  	int i;
@@ -210,7 +142,7 @@
 		}
 
 		default:
-			ret = -EIO;
+			ret = ptrace_request(child, request, addr, data);
 			break;
 	}
 	return ret;
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c
index b5969db..f9b3f44 100644
--- a/arch/h8300/kernel/sys_h8300.c
+++ b/arch/h8300/kernel/sys_h8300.c
@@ -26,144 +26,6 @@
 #include <asm/traps.h>
 #include <asm/unistd.h>
 
-/*
- * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
- * handle more than 4 system call parameters, so these system calls
- * used a memory block for parameter passing..
- */
-
-struct mmap_arg_struct {
-	unsigned long addr;
-	unsigned long len;
-	unsigned long prot;
-	unsigned long flags;
-	unsigned long fd;
-	unsigned long offset;
-};
-
-asmlinkage int old_mmap(struct mmap_arg_struct *arg)
-{
-	struct mmap_arg_struct a;
-	int error = -EFAULT;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		goto out;
-
-	error = -EINVAL;
-	if (a.offset & ~PAGE_MASK)
-		goto out;
-
-	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
-			       a.offset >> PAGE_SHIFT);
-out:
-	return error;
-}
-
-struct sel_arg_struct {
-	unsigned long n;
-	fd_set *inp, *outp, *exp;
-	struct timeval *tvp;
-};
-
-asmlinkage int old_select(struct sel_arg_struct *arg)
-{
-	struct sel_arg_struct a;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-	/* sys_select() does the appropriate kernel locking */
-	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-}
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage int sys_ipc (uint call, int first, int second,
-			int third, void *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	if (call <= SEMCTL)
-		switch (call) {
-		case SEMOP:
-			return sys_semop (first, (struct sembuf *)ptr, second);
-		case SEMGET:
-			return sys_semget (first, second, third);
-		case SEMCTL: {
-			union semun fourth;
-			if (!ptr)
-				return -EINVAL;
-			if (get_user(fourth.__pad, (void **) ptr))
-				return -EFAULT;
-			return sys_semctl (first, second, third, fourth);
-			}
-		default:
-			return -EINVAL;
-		}
-	if (call <= MSGCTL) 
-		switch (call) {
-		case MSGSND:
-			return sys_msgsnd (first, (struct msgbuf *) ptr, 
-					  second, third);
-		case MSGRCV:
-			switch (version) {
-			case 0: {
-				struct ipc_kludge tmp;
-				if (!ptr)
-					return -EINVAL;
-				if (copy_from_user (&tmp,
-						    (struct ipc_kludge *)ptr,
-						    sizeof (tmp)))
-					return -EFAULT;
-				return sys_msgrcv (first, tmp.msgp, second,
-						   tmp.msgtyp, third);
-				}
-			default:
-				return sys_msgrcv (first,
-						   (struct msgbuf *) ptr,
-						   second, fifth, third);
-			}
-		case MSGGET:
-			return sys_msgget ((key_t) first, second);
-		case MSGCTL:
-			return sys_msgctl (first, second,
-					   (struct msqid_ds *) ptr);
-		default:
-			return -EINVAL;
-		}
-	if (call <= SHMCTL) 
-		switch (call) {
-		case SHMAT:
-			switch (version) {
-			default: {
-				ulong raddr;
-				ret = do_shmat (first, (char *) ptr,
-						 second, &raddr);
-				if (ret)
-					return ret;
-				return put_user (raddr, (ulong *) third);
-			}
-			}
-		case SHMDT: 
-			return sys_shmdt ((char *)ptr);
-		case SHMGET:
-			return sys_shmget (first, second, third);
-		case SHMCTL:
-			return sys_shmctl (first, second,
-					   (struct shmid_ds *) ptr);
-		default:
-			return -EINVAL;
-		}
-
-	return -EINVAL;
-}
-
 /* sys_cacheflush -- no support.  */
 asmlinkage int
 sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S
index 2d69881..faefaff 100644
--- a/arch/h8300/kernel/syscalls.S
+++ b/arch/h8300/kernel/syscalls.S
@@ -96,7 +96,7 @@
 	.long SYMBOL_NAME(sys_settimeofday)
 	.long SYMBOL_NAME(sys_getgroups16)	/* 80 */
 	.long SYMBOL_NAME(sys_setgroups16)
-	.long SYMBOL_NAME(old_select)
+	.long SYMBOL_NAME(sys_old_select)
 	.long SYMBOL_NAME(sys_symlink)
 	.long SYMBOL_NAME(sys_lstat)
 	.long SYMBOL_NAME(sys_readlink)		/* 85 */
@@ -104,7 +104,7 @@
 	.long SYMBOL_NAME(sys_swapon)
 	.long SYMBOL_NAME(sys_reboot)
 	.long SYMBOL_NAME(sys_old_readdir)
-	.long SYMBOL_NAME(old_mmap)		/* 90 */
+	.long SYMBOL_NAME(sys_old_mmap)		/* 90 */
 	.long SYMBOL_NAME(sys_munmap)
 	.long SYMBOL_NAME(sys_truncate)
 	.long SYMBOL_NAME(sys_ftruncate)
diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c
index 746b1ae..4f1ed02 100644
--- a/arch/h8300/platform/h8300h/ptrace_h8300h.c
+++ b/arch/h8300/platform/h8300h/ptrace_h8300h.c
@@ -60,7 +60,7 @@
 }
 
 /* disable singlestep */
-void h8300_disable_trace(struct task_struct *child)
+void user_disable_single_step(struct task_struct *child)
 {
 	if((long)child->thread.breakinfo.addr != -1L) {
 		*child->thread.breakinfo.addr = child->thread.breakinfo.inst;
@@ -264,7 +264,7 @@
 
 /* Set breakpoint(s) to simulate a single step from the current PC.  */
 
-void h8300_enable_trace(struct task_struct *child)
+void user_enable_single_step(struct task_struct *child)
 {
 	unsigned short *nextpc;
 	nextpc = getnextpc(child,(unsigned short *)h8300_get_reg(child, PT_PC));
@@ -276,7 +276,7 @@
 asmlinkage void trace_trap(unsigned long bp)
 {
 	if ((unsigned long)current->thread.breakinfo.addr == bp) {
-		h8300_disable_trace(current);
+		user_disable_single_step(current);
 		force_sig(SIGTRAP,current);
 	} else
 	        force_sig(SIGILL,current);
diff --git a/arch/h8300/platform/h8s/ptrace_h8s.c b/arch/h8300/platform/h8s/ptrace_h8s.c
index e8cd46f..c058ab1 100644
--- a/arch/h8300/platform/h8s/ptrace_h8s.c
+++ b/arch/h8300/platform/h8s/ptrace_h8s.c
@@ -65,13 +65,13 @@
 }
 
 /* disable singlestep */
-void h8300_disable_trace(struct task_struct *child)
+void user_disable_single_step(struct task_struct *child)
 {
 	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE;
 }
 
 /* enable singlestep */
-void h8300_enable_trace(struct task_struct *child)
+void user_enable_single_step(struct task_struct *child)
 {
 	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE;
 }
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 9a50d7d..4d4f418 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -53,6 +53,9 @@
 	bool
 	default y
 
+config NEED_DMA_MAP_STATE
+	def_bool y
+
 config SWIOTLB
        bool
 
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h
index dfcf75b..f90edc8 100644
--- a/arch/ia64/include/asm/compat.h
+++ b/arch/ia64/include/asm/compat.h
@@ -5,7 +5,8 @@
  */
 #include <linux/types.h>
 
-#define COMPAT_USER_HZ	100
+#define COMPAT_USER_HZ		100
+#define COMPAT_UTS_MACHINE	"i686\0\0\0"
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
diff --git a/arch/ia64/include/asm/elf.h b/arch/ia64/include/asm/elf.h
index 4c41656..b5298eb 100644
--- a/arch/ia64/include/asm/elf.h
+++ b/arch/ia64/include/asm/elf.h
@@ -219,54 +219,6 @@
 	NEW_AUX_ENT(AT_SYSINFO_EHDR, (unsigned long) GATE_EHDR);		\
 } while (0)
 
-
-/*
- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
- * extra segments containing the gate DSO contents.  Dumping its
- * contents makes post-mortem fully interpretable later without matching up
- * the same kernel and hardware config to see what PC values meant.
- * Dumping its extra ELF program headers includes all the other information
- * a debugger needs to easily find how the gate DSO was being used.
- */
-#define ELF_CORE_EXTRA_PHDRS		(GATE_EHDR->e_phnum)
-#define ELF_CORE_WRITE_EXTRA_PHDRS						\
-do {										\
-	const struct elf_phdr *const gate_phdrs =			      \
-		(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);   \
-	int i;									\
-	Elf64_Off ofs = 0;						      \
-	for (i = 0; i < GATE_EHDR->e_phnum; ++i) {				\
-		struct elf_phdr phdr = gate_phdrs[i];			      \
-		if (phdr.p_type == PT_LOAD) {					\
-			phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz);	      \
-			phdr.p_filesz = phdr.p_memsz;			      \
-			if (ofs == 0) {					      \
-				ofs = phdr.p_offset = offset;		      \
-			offset += phdr.p_filesz;				\
-		}							      \
-		else							      \
-				phdr.p_offset = ofs;			      \
-		}							      \
-		else							      \
-			phdr.p_offset += ofs;					\
-		phdr.p_paddr = 0; /* match other core phdrs */			\
-		DUMP_WRITE(&phdr, sizeof(phdr));				\
-	}									\
-} while (0)
-#define ELF_CORE_WRITE_EXTRA_DATA					\
-do {									\
-	const struct elf_phdr *const gate_phdrs =			      \
-		(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);   \
-	int i;								\
-	for (i = 0; i < GATE_EHDR->e_phnum; ++i) {			\
-		if (gate_phdrs[i].p_type == PT_LOAD) {			      \
-			DUMP_WRITE((void *) gate_phdrs[i].p_vaddr,	      \
-				   PAGE_ALIGN(gate_phdrs[i].p_memsz));	      \
-			break;						      \
-		}							      \
-	}								\
-} while (0)
-
 /*
  * format for entries in the Global Offset Table
  */
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index 55281aa..73b5f78 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -56,20 +56,6 @@
 
 #include <asm-generic/pci-dma-compat.h>
 
-/* pci_unmap_{single,page} is not a nop, thus... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
-	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
-	__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)			\
-	((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
-	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)			\
-	((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
-	(((PTR)->LEN_NAME) = (VAL))
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
diff --git a/arch/ia64/include/asm/percpu.h b/arch/ia64/include/asm/percpu.h
index 30cf465..f7c00a5 100644
--- a/arch/ia64/include/asm/percpu.h
+++ b/arch/ia64/include/asm/percpu.h
@@ -9,7 +9,7 @@
 #define PERCPU_ENOUGH_ROOM PERCPU_PAGE_SIZE
 
 #ifdef __ASSEMBLY__
-# define THIS_CPU(var)	(per_cpu__##var)  /* use this to mark accesses to per-CPU variables... */
+# define THIS_CPU(var)	(var)  /* use this to mark accesses to per-CPU variables... */
 #else /* !__ASSEMBLY__ */
 
 
@@ -39,7 +39,7 @@
  * On the positive side, using __ia64_per_cpu_var() instead of __get_cpu_var() is slightly
  * more efficient.
  */
-#define __ia64_per_cpu_var(var)	per_cpu__##var
+#define __ia64_per_cpu_var(var)	var
 
 #include <asm-generic/percpu.h>
 
diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h
index 14055c6..7ae9c3f 100644
--- a/arch/ia64/include/asm/ptrace.h
+++ b/arch/ia64/include/asm/ptrace.h
@@ -319,11 +319,7 @@
 	ptrace_attach_sync_user_rbs(child)
 
   #define arch_has_single_step()  (1)
-  extern void user_enable_single_step(struct task_struct *);
-  extern void user_disable_single_step(struct task_struct *);
-
   #define arch_has_block_step()   (1)
-  extern void user_enable_block_step(struct task_struct *);
 
 #endif /* !__KERNEL__ */
 
diff --git a/arch/ia64/include/asm/xen/events.h b/arch/ia64/include/asm/xen/events.h
index b8370c8..baa74c8 100644
--- a/arch/ia64/include/asm/xen/events.h
+++ b/arch/ia64/include/asm/xen/events.h
@@ -36,10 +36,6 @@
 	return !(ia64_psr(regs)->i);
 }
 
-static inline void handle_irq(int irq, struct pt_regs *regs)
-{
-	__do_IRQ(irq);
-}
 #define irq_ctx_init(cpu)	do { } while (0)
 
 #endif /* _ASM_IA64_XEN_EVENTS_H */
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 4138282..db10b1e 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -45,6 +45,8 @@
 obj-$(CONFIG_DMAR)		+= pci-dma.o
 obj-$(CONFIG_SWIOTLB)		+= pci-swiotlb.o
 
+obj-$(CONFIG_BINFMT_ELF)	+= elfcore.o
+
 # fp_emulate() expects f2-f5,f16-f31 to contain the user-level state.
 CFLAGS_traps.o  += -mfixed-range=f2-f5,f16-f31
 
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index c16fb03..a7ca07f 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -852,8 +852,8 @@
 
 	possible = available_cpus + additional_cpus;
 
-	if (possible > NR_CPUS)
-		possible = NR_CPUS;
+	if (possible > nr_cpu_ids)
+		possible = nr_cpu_ids;
 
 	printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
 		possible, max((possible - available_cpus), 0));
diff --git a/arch/ia64/kernel/elfcore.c b/arch/ia64/kernel/elfcore.c
new file mode 100644
index 0000000..bac1639
--- /dev/null
+++ b/arch/ia64/kernel/elfcore.c
@@ -0,0 +1,80 @@
+#include <linux/elf.h>
+#include <linux/coredump.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/elf.h>
+
+
+Elf64_Half elf_core_extra_phdrs(void)
+{
+	return GATE_EHDR->e_phnum;
+}
+
+int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
+			       unsigned long limit)
+{
+	const struct elf_phdr *const gate_phdrs =
+		(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
+	int i;
+	Elf64_Off ofs = 0;
+
+	for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
+		struct elf_phdr phdr = gate_phdrs[i];
+
+		if (phdr.p_type == PT_LOAD) {
+			phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz);
+			phdr.p_filesz = phdr.p_memsz;
+			if (ofs == 0) {
+				ofs = phdr.p_offset = offset;
+				offset += phdr.p_filesz;
+			} else {
+				phdr.p_offset = ofs;
+			}
+		} else {
+			phdr.p_offset += ofs;
+		}
+		phdr.p_paddr = 0; /* match other core phdrs */
+		*size += sizeof(phdr);
+		if (*size > limit || !dump_write(file, &phdr, sizeof(phdr)))
+			return 0;
+	}
+	return 1;
+}
+
+int elf_core_write_extra_data(struct file *file, size_t *size,
+			      unsigned long limit)
+{
+	const struct elf_phdr *const gate_phdrs =
+		(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
+	int i;
+
+	for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
+		if (gate_phdrs[i].p_type == PT_LOAD) {
+			void *addr = (void *)gate_phdrs[i].p_vaddr;
+			size_t memsz = PAGE_ALIGN(gate_phdrs[i].p_memsz);
+
+			*size += memsz;
+			if (*size > limit || !dump_write(file, addr, memsz))
+				return 0;
+			break;
+		}
+	}
+	return 1;
+}
+
+size_t elf_core_extra_data_size(void)
+{
+	const struct elf_phdr *const gate_phdrs =
+		(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
+	int i;
+	size_t size = 0;
+
+	for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
+		if (gate_phdrs[i].p_type == PT_LOAD) {
+			size += PAGE_ALIGN(gate_phdrs[i].p_memsz);
+			break;
+		}
+	}
+	return size;
+}
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
index 461b999..7f4a0ed 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -30,9 +30,9 @@
 #endif
 
 #include <asm/processor.h>
-EXPORT_SYMBOL(per_cpu__ia64_cpu_info);
+EXPORT_SYMBOL(ia64_cpu_info);
 #ifdef CONFIG_SMP
-EXPORT_SYMBOL(per_cpu__local_per_cpu_offset);
+EXPORT_SYMBOL(local_per_cpu_offset);
 #endif
 
 #include <asm/uaccess.h>
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index b81e46b..703062c 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2315,6 +2315,7 @@
 		DPRINT(("Cannot allocate vma\n"));
 		goto error_kmem;
 	}
+	INIT_LIST_HEAD(&vma->anon_vma_chain);
 
 	/*
 	 * partially initialize the vma for the sampling buffer
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index 8f06035..b3a5818 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -282,7 +282,7 @@
 	return ret;
 }
 
-static struct sysfs_ops cache_sysfs_ops = {
+static const struct sysfs_ops cache_sysfs_ops = {
 	.show   = cache_show
 };
 
diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig
index 01c7579..fa4d1e5 100644
--- a/arch/ia64/kvm/Kconfig
+++ b/arch/ia64/kvm/Kconfig
@@ -26,6 +26,7 @@
 	select ANON_INODES
 	select HAVE_KVM_IRQCHIP
 	select KVM_APIC_ARCHITECTURE
+	select KVM_MMIO
 	---help---
 	  Support hosting fully virtualized guest machines using hardware
 	  virtualization extensions.  You will need a fairly recent
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 5fdeec5..26e0e08 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -241,10 +241,10 @@
 	return 0;
 mmio:
 	if (p->dir)
-		r = kvm_io_bus_read(&vcpu->kvm->mmio_bus, p->addr,
+		r = kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, p->addr,
 				    p->size, &p->data);
 	else
-		r = kvm_io_bus_write(&vcpu->kvm->mmio_bus, p->addr,
+		r = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, p->addr,
 				     p->size, &p->data);
 	if (r)
 		printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr);
@@ -636,12 +636,9 @@
 static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	union context *host_ctx, *guest_ctx;
-	int r;
+	int r, idx;
 
-	/*
-	 * down_read() may sleep and return with interrupts enabled
-	 */
-	down_read(&vcpu->kvm->slots_lock);
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
 
 again:
 	if (signal_pending(current)) {
@@ -663,7 +660,7 @@
 	if (r < 0)
 		goto vcpu_run_fail;
 
-	up_read(&vcpu->kvm->slots_lock);
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 	kvm_guest_enter();
 
 	/*
@@ -687,7 +684,7 @@
 	kvm_guest_exit();
 	preempt_enable();
 
-	down_read(&vcpu->kvm->slots_lock);
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
 
 	r = kvm_handle_exit(kvm_run, vcpu);
 
@@ -697,10 +694,10 @@
 	}
 
 out:
-	up_read(&vcpu->kvm->slots_lock);
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 	if (r > 0) {
 		kvm_resched(vcpu);
-		down_read(&vcpu->kvm->slots_lock);
+		idx = srcu_read_lock(&vcpu->kvm->srcu);
 		goto again;
 	}
 
@@ -971,7 +968,7 @@
 			goto out;
 		r = kvm_setup_default_irq_routing(kvm);
 		if (r) {
-			kfree(kvm->arch.vioapic);
+			kvm_ioapic_destroy(kvm);
 			goto out;
 		}
 		break;
@@ -1377,12 +1374,14 @@
 
 static void kvm_release_vm_pages(struct kvm *kvm)
 {
+	struct kvm_memslots *slots;
 	struct kvm_memory_slot *memslot;
 	int i, j;
 	unsigned long base_gfn;
 
-	for (i = 0; i < kvm->nmemslots; i++) {
-		memslot = &kvm->memslots[i];
+	slots = rcu_dereference(kvm->memslots);
+	for (i = 0; i < slots->nmemslots; i++) {
+		memslot = &slots->memslots[i];
 		base_gfn = memslot->base_gfn;
 
 		for (j = 0; j < memslot->npages; j++) {
@@ -1405,6 +1404,7 @@
 	kfree(kvm->arch.vioapic);
 	kvm_release_vm_pages(kvm);
 	kvm_free_physmem(kvm);
+	cleanup_srcu_struct(&kvm->srcu);
 	free_kvm(kvm);
 }
 
@@ -1576,15 +1576,15 @@
 	return r;
 }
 
-int kvm_arch_set_memory_region(struct kvm *kvm,
-		struct kvm_userspace_memory_region *mem,
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+		struct kvm_memory_slot *memslot,
 		struct kvm_memory_slot old,
+		struct kvm_userspace_memory_region *mem,
 		int user_alloc)
 {
 	unsigned long i;
 	unsigned long pfn;
-	int npages = mem->memory_size >> PAGE_SHIFT;
-	struct kvm_memory_slot *memslot = &kvm->memslots[mem->slot];
+	int npages = memslot->npages;
 	unsigned long base_gfn = memslot->base_gfn;
 
 	if (base_gfn + npages > (KVM_MAX_MEM_SIZE >> PAGE_SHIFT))
@@ -1608,6 +1608,14 @@
 	return 0;
 }
 
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+		struct kvm_userspace_memory_region *mem,
+		struct kvm_memory_slot old,
+		int user_alloc)
+{
+	return;
+}
+
 void kvm_arch_flush_shadow(struct kvm *kvm)
 {
 	kvm_flush_remote_tlbs(kvm);
@@ -1802,7 +1810,7 @@
 	if (log->slot >= KVM_MEMORY_SLOTS)
 		goto out;
 
-	memslot = &kvm->memslots[log->slot];
+	memslot = &kvm->memslots->memslots[log->slot];
 	r = -ENOENT;
 	if (!memslot->dirty_bitmap)
 		goto out;
@@ -1827,6 +1835,7 @@
 	struct kvm_memory_slot *memslot;
 	int is_dirty = 0;
 
+	mutex_lock(&kvm->slots_lock);
 	spin_lock(&kvm->arch.dirty_log_lock);
 
 	r = kvm_ia64_sync_dirty_log(kvm, log);
@@ -1840,12 +1849,13 @@
 	/* If nothing is dirty, don't bother messing with page tables. */
 	if (is_dirty) {
 		kvm_flush_remote_tlbs(kvm);
-		memslot = &kvm->memslots[log->slot];
+		memslot = &kvm->memslots->memslots[log->slot];
 		n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
 		memset(memslot->dirty_bitmap, 0, n);
 	}
 	r = 0;
 out:
+	mutex_unlock(&kvm->slots_lock);
 	spin_unlock(&kvm->arch.dirty_log_lock);
 	return r;
 }
diff --git a/arch/ia64/kvm/kvm_fw.c b/arch/ia64/kvm/kvm_fw.c
index e4b8231..cb548ee 100644
--- a/arch/ia64/kvm/kvm_fw.c
+++ b/arch/ia64/kvm/kvm_fw.c
@@ -75,7 +75,7 @@
 	struct exit_ctl_data *p;
 
 	p = kvm_get_exit_data(vcpu);
-	if (p && p->exit_reason == EXIT_REASON_PAL_CALL) {
+	if (p->exit_reason == EXIT_REASON_PAL_CALL) {
 		p->u.pal_data.ret = result;
 		return ;
 	}
@@ -87,7 +87,7 @@
 	struct exit_ctl_data *p;
 
 	p = kvm_get_exit_data(vcpu);
-	if (p && p->exit_reason == EXIT_REASON_SAL_CALL) {
+	if (p->exit_reason == EXIT_REASON_SAL_CALL) {
 		p->u.sal_data.ret = result;
 		return ;
 	}
@@ -322,7 +322,7 @@
 	struct exit_ctl_data *p;
 
 	p = kvm_get_exit_data(vcpu);
-	if (p && (p->exit_reason == EXIT_REASON_PAL_CALL))
+	if (p->exit_reason == EXIT_REASON_PAL_CALL)
 		index = p->u.pal_data.gr28;
 
 	return index;
@@ -646,18 +646,16 @@
 
 	p = kvm_get_exit_data(vcpu);
 
-	if (p) {
-		if (p->exit_reason == EXIT_REASON_SAL_CALL) {
-			*in0 = p->u.sal_data.in0;
-			*in1 = p->u.sal_data.in1;
-			*in2 = p->u.sal_data.in2;
-			*in3 = p->u.sal_data.in3;
-			*in4 = p->u.sal_data.in4;
-			*in5 = p->u.sal_data.in5;
-			*in6 = p->u.sal_data.in6;
-			*in7 = p->u.sal_data.in7;
-			return ;
-		}
+	if (p->exit_reason == EXIT_REASON_SAL_CALL) {
+		*in0 = p->u.sal_data.in0;
+		*in1 = p->u.sal_data.in1;
+		*in2 = p->u.sal_data.in2;
+		*in3 = p->u.sal_data.in3;
+		*in4 = p->u.sal_data.in4;
+		*in5 = p->u.sal_data.in5;
+		*in6 = p->u.sal_data.in6;
+		*in7 = p->u.sal_data.in7;
+		return ;
 	}
 	*in0 = 0;
 }
diff --git a/arch/ia64/kvm/mmio.c b/arch/ia64/kvm/mmio.c
index 9bf55af..fb8f9f5 100644
--- a/arch/ia64/kvm/mmio.c
+++ b/arch/ia64/kvm/mmio.c
@@ -316,8 +316,8 @@
 		return;
 	} else {
 		inst_type = -1;
-		panic_vm(vcpu, "Unsupported MMIO access instruction! \
-				Bunld[0]=0x%lx, Bundle[1]=0x%lx\n",
+		panic_vm(vcpu, "Unsupported MMIO access instruction! "
+				"Bunld[0]=0x%lx, Bundle[1]=0x%lx\n",
 				bundle.i64[0], bundle.i64[1]);
 	}
 
diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c
index dce75b70..958815c 100644
--- a/arch/ia64/kvm/vcpu.c
+++ b/arch/ia64/kvm/vcpu.c
@@ -1639,8 +1639,8 @@
 	 * Otherwise panic
 	 */
 	if (val & (IA64_PSR_PK | IA64_PSR_IS | IA64_PSR_VM))
-		panic_vm(vcpu, "Only support guests with vpsr.pk =0 \
-				& vpsr.is=0\n");
+		panic_vm(vcpu, "Only support guests with vpsr.pk =0 "
+				"& vpsr.is=0\n");
 
 	/*
 	 * For those IA64_PSR bits: id/da/dd/ss/ed/ia
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 19c4b21..8d586d1 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -459,7 +459,7 @@
 		cpu = 0;
 		node = node_cpuid[cpu].nid;
 		cpu0_cpu_info = (struct cpuinfo_ia64 *)(__phys_per_cpu_start +
-			((char *)&per_cpu__ia64_cpu_info - __per_cpu_start));
+			((char *)&ia64_cpu_info - __per_cpu_start));
 		cpu0_cpu_info->node_data = mem_data[node].node_data;
 	}
 #endif /* CONFIG_SMP */
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index ca3335e..ed41759 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -117,6 +117,7 @@
 	 */
 	vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 	if (vma) {
+		INIT_LIST_HEAD(&vma->anon_vma_chain);
 		vma->vm_mm = current->mm;
 		vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
 		vma->vm_end = vma->vm_start + PAGE_SIZE;
@@ -135,6 +136,7 @@
 	if (!(current->personality & MMAP_PAGE_ZERO)) {
 		vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
 		if (vma) {
+			INIT_LIST_HEAD(&vma->anon_vma_chain);
 			vma->vm_mm = current->mm;
 			vma->vm_end = PAGE_SIZE;
 			vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT);
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index e456f06..d00dfc1 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -241,7 +241,7 @@
  * Note:  This stuff is duped here because Altix requires the PCDP to
  * locate a usable VGA device due to lack of proper ACPI support.  Structures
  * could be used from drivers/firmware/pcdp.h, but it was decided that moving
- * this file to a more public location just for Altix use was undesireable.
+ * this file to a more public location just for Altix use was undesirable.
  */
 
 struct hcdp_uart_desc {
diff --git a/arch/m32r/include/asm/local.h b/arch/m32r/include/asm/local.h
index 22256d1..734bca8 100644
--- a/arch/m32r/include/asm/local.h
+++ b/arch/m32r/include/asm/local.h
@@ -338,29 +338,4 @@
  * a variable, not an address.
  */
 
-/* Need to disable preemption for the cpu local counters otherwise we could
-   still access a variable of a previous CPU in a non local way. */
-#define cpu_local_wrap_v(l)	 	\
-	({ local_t res__;		\
-	   preempt_disable(); 		\
-	   res__ = (l);			\
-	   preempt_enable();		\
-	   res__; })
-#define cpu_local_wrap(l)		\
-	({ preempt_disable();		\
-	   l;				\
-	   preempt_enable(); })		\
-
-#define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
-#define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
-#define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var(l)))
-#define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var(l)))
-#define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
-#define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
-
-#define __cpu_local_inc(l)	cpu_local_inc(l)
-#define __cpu_local_dec(l)	cpu_local_dec(l)
-#define __cpu_local_add(i, l)	cpu_local_add((i), (l))
-#define __cpu_local_sub(i, l)	cpu_local_sub((i), (l))
-
 #endif /* __M32R_LOCAL_H */
diff --git a/arch/m32r/include/asm/ptrace.h b/arch/m32r/include/asm/ptrace.h
index a0755b9..840a123 100644
--- a/arch/m32r/include/asm/ptrace.h
+++ b/arch/m32r/include/asm/ptrace.h
@@ -120,6 +120,8 @@
 
 #include <asm/m32r.h>		/* M32R_PSW_BSM, M32R_PSW_BPM */
 
+#define arch_has_single_step() (1)
+
 struct task_struct;
 extern void init_debug_traps(struct task_struct *);
 #define arch_ptrace_attach(child) \
diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h
index cf701c9..7612577 100644
--- a/arch/m32r/include/asm/unistd.h
+++ b/arch/m32r/include/asm/unistd.h
@@ -339,6 +339,7 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_TIME
 #define __ARCH_WANT_SYS_UTIME
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index 98682bb..e555091 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -580,6 +580,35 @@
 	}
 }
 
+void user_enable_single_step(struct task_struct *child)
+{
+	unsigned long next_pc;
+	unsigned long pc, insn;
+
+	clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
+	/* Compute next pc.  */
+	pc = get_stack_long(child, PT_BPC);
+
+	if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
+	    != sizeof(insn))
+		break;
+
+	compute_next_pc(insn, pc, &next_pc, child);
+	if (next_pc & 0x80000000)
+		break;
+
+	if (embed_debug_trap(child, next_pc))
+		break;
+
+	invalidate_cache();
+}
+
+void user_disable_single_step(struct task_struct *child)
+{
+	unregister_all_debug_traps(child);
+	invalidate_cache();
+}
 
 /*
  * Called by kernel/ptrace.c when detaching..
@@ -630,74 +659,6 @@
 		ret = ptrace_write_user(child, addr, data);
 		break;
 
-	/*
-	 * continue/restart and stop at next (return from) syscall
-	 */
-	case PTRACE_SYSCALL:
-	case PTRACE_CONT:
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		if (request == PTRACE_SYSCALL)
-			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		else
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->exit_code = data;
-		wake_up_process(child);
-		ret = 0;
-		break;
-
-	/*
-	 * make the child exit.  Best I can do is send it a sigkill.
-	 * perhaps it should be put in the status that it wants to
-	 * exit.
-	 */
-	case PTRACE_KILL: {
-		ret = 0;
-		unregister_all_debug_traps(child);
-		invalidate_cache();
-		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
-			break;
-		child->exit_code = SIGKILL;
-		wake_up_process(child);
-		break;
-	}
-
-	/*
-	 * execute single instruction.
-	 */
-	case PTRACE_SINGLESTEP: {
-		unsigned long next_pc;
-		unsigned long pc, insn;
-
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
-		/* Compute next pc.  */
-		pc = get_stack_long(child, PT_BPC);
-
-		if (access_process_vm(child, pc&~3, &insn, sizeof(insn), 0)
-		    != sizeof(insn))
-			break;
-
-		compute_next_pc(insn, pc, &next_pc, child);
-		if (next_pc & 0x80000000)
-			break;
-
-		if (embed_debug_trap(child, next_pc))
-			break;
-
-		invalidate_cache();
-		child->exit_code = data;
-
-		/* give it a chance to run. */
-		wake_up_process(child);
-		ret = 0;
-		break;
-	}
-
 	case PTRACE_GETREGS:
 		ret = ptrace_getregs(child, (void __user *)data);
 		break;
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c
index d3c865c..0a00f46 100644
--- a/arch/m32r/kernel/sys_m32r.c
+++ b/arch/m32r/kernel/sys_m32r.c
@@ -76,98 +76,6 @@
 	return oldval;
 }
 
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage int sys_ipc(uint call, int first, int second,
-		       int third, void __user *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr,
-				      second, NULL);
-	case SEMTIMEDOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr,
-				      second, (const struct timespec __user *)fifth);
-	case SEMGET:
-		return sys_semget (first, second, third);
-	case SEMCTL: {
-		union semun fourth;
-		if (!ptr)
-			return -EINVAL;
-		if (get_user(fourth.__pad, (void __user * __user *) ptr))
-			return -EFAULT;
-		return sys_semctl (first, second, third, fourth);
-		}
-
-	case MSGSND:
-		return sys_msgsnd (first, (struct msgbuf __user *) ptr,
-				   second, third);
-	case MSGRCV:
-		switch (version) {
-		case 0: {
-			struct ipc_kludge tmp;
-			if (!ptr)
-				return -EINVAL;
-
-			if (copy_from_user(&tmp,
-					   (struct ipc_kludge __user *) ptr,
-					   sizeof (tmp)))
-				return -EFAULT;
-			return sys_msgrcv (first, tmp.msgp, second,
-					   tmp.msgtyp, third);
-			}
-		default:
-			return sys_msgrcv (first,
-					   (struct msgbuf __user *) ptr,
-					   second, fifth, third);
-		}
-	case MSGGET:
-		return sys_msgget ((key_t) first, second);
-	case MSGCTL:
-		return sys_msgctl (first, second,
-				   (struct msqid_ds __user *) ptr);
-	case SHMAT: {
-		ulong raddr;
-
-		if (!access_ok(VERIFY_WRITE, (ulong __user *) third,
-				      sizeof(ulong)))
-			return -EFAULT;
-		ret = do_shmat (first, (char __user *) ptr, second, &raddr);
-		if (ret)
-			return ret;
-		return put_user (raddr, (ulong __user *) third);
-		}
-	case SHMDT:
-		return sys_shmdt ((char __user *)ptr);
-	case SHMGET:
-		return sys_shmget (first, second, third);
-	case SHMCTL:
-		return sys_shmctl (first, second,
-				   (struct shmid_ds __user *) ptr);
-	default:
-		return -ENOSYS;
-	}
-}
-
-asmlinkage int sys_uname(struct old_utsname __user * name)
-{
-	int err;
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err = copy_to_user(name, utsname(), sizeof (*name));
-	up_read(&uts_sem);
-	return err?-EFAULT:0;
-}
-
 asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
 {
 	/* This should flush more selectively ...  */
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index 4add96d..5890897 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -121,7 +121,7 @@
  * bytes have been lost and in which state of the packet structure we are now.
  * This usually causes keyboards bytes to be interpreted as mouse movements
  * and vice versa, which is very annoying. It seems better to throw away some
- * bytes (that are usually mouse bytes) than to misinterpret them. Therefor I
+ * bytes (that are usually mouse bytes) than to misinterpret them. Therefore I
  * introduced the RESYNC state for IKBD data. In this state, the bytes up to
  * one that really looks like a key event (0x04..0xf2) or the start of a mouse
  * packet (0xf8..0xfb) are thrown away, but at most 2 bytes. This at least
diff --git a/arch/m68k/include/asm/fbio.h b/arch/m68k/include/asm/fbio.h
index b9215a0..0a21da8 100644
--- a/arch/m68k/include/asm/fbio.h
+++ b/arch/m68k/include/asm/fbio.h
@@ -173,7 +173,7 @@
 	int     mdi_ncluts;     /* Number of implemented CLUTs in this MDI */
         int     mdi_type;       /* FBTYPE name */
         int     mdi_height;     /* height */
-        int     mdi_width;      /* widht */
+        int     mdi_width;      /* width */
         int     mdi_size;       /* available ram */
         int     mdi_mode;       /* 8bpp, 16bpp or 32bpp */
         int     mdi_pixfreq;    /* pixel clock (from PROM) */
diff --git a/arch/m68k/include/asm/io_no.h b/arch/m68k/include/asm/io_no.h
index 359065d5..6e2413e 100644
--- a/arch/m68k/include/asm/io_no.h
+++ b/arch/m68k/include/asm/io_no.h
@@ -16,7 +16,7 @@
  * memory location directly.
  */
 /* ++roman: The assignments to temp. vars avoid that gcc sometimes generates
- * two accesses to memory, which may be undesireable for some devices.
+ * two accesses to memory, which may be undesirable for some devices.
  */
 
 /*
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h
index 21605c7..6e6e3ac 100644
--- a/arch/m68k/include/asm/ptrace.h
+++ b/arch/m68k/include/asm/ptrace.h
@@ -87,18 +87,10 @@
 #define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
-/*
- * These are defined as per linux/ptrace.h.
- */
-struct task_struct;
-
 #define arch_has_single_step()	(1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
 
 #ifdef CONFIG_MMU
 #define arch_has_block_step()	(1)
-extern void user_enable_block_step(struct task_struct *);
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index d72a71d..60b15d0 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -351,6 +351,7 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
@@ -363,6 +364,8 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_MMAP
+#define __ARCH_WANT_SYS_OLD_SELECT
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index e136b8c..2391bdf 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -510,7 +510,7 @@
 	.long sys_settimeofday
 	.long sys_getgroups16	/* 80 */
 	.long sys_setgroups16
-	.long old_select
+	.long sys_old_select
 	.long sys_symlink
 	.long sys_lstat
 	.long sys_readlink	/* 85 */
@@ -518,7 +518,7 @@
 	.long sys_swapon
 	.long sys_reboot
 	.long sys_old_readdir
-	.long old_mmap		/* 90 */
+	.long sys_old_mmap	/* 90 */
 	.long sys_munmap
 	.long sys_truncate
 	.long sys_ftruncate
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index e3ad2d6..7789669 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -46,137 +46,6 @@
 	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
 }
 
-/*
- * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
- * handle more than 4 system call parameters, so these system calls
- * used a memory block for parameter passing..
- */
-
-struct mmap_arg_struct {
-	unsigned long addr;
-	unsigned long len;
-	unsigned long prot;
-	unsigned long flags;
-	unsigned long fd;
-	unsigned long offset;
-};
-
-asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
-{
-	struct mmap_arg_struct a;
-	int error = -EFAULT;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		goto out;
-
-	error = -EINVAL;
-	if (a.offset & ~PAGE_MASK)
-		goto out;
-
-	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
-			       a.offset >> PAGE_SHIFT);
-out:
-	return error;
-}
-
-struct sel_arg_struct {
-	unsigned long n;
-	fd_set __user *inp, *outp, *exp;
-	struct timeval __user *tvp;
-};
-
-asmlinkage int old_select(struct sel_arg_struct __user *arg)
-{
-	struct sel_arg_struct a;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-	/* sys_select() does the appropriate kernel locking */
-	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-}
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage int sys_ipc (uint call, int first, int second,
-			int third, void __user *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	if (call <= SEMCTL)
-		switch (call) {
-		case SEMOP:
-			return sys_semop (first, ptr, second);
-		case SEMGET:
-			return sys_semget (first, second, third);
-		case SEMCTL: {
-			union semun fourth;
-			if (!ptr)
-				return -EINVAL;
-			if (get_user(fourth.__pad, (void __user *__user *) ptr))
-				return -EFAULT;
-			return sys_semctl (first, second, third, fourth);
-			}
-		default:
-			return -ENOSYS;
-		}
-	if (call <= MSGCTL)
-		switch (call) {
-		case MSGSND:
-			return sys_msgsnd (first, ptr, second, third);
-		case MSGRCV:
-			switch (version) {
-			case 0: {
-				struct ipc_kludge tmp;
-				if (!ptr)
-					return -EINVAL;
-				if (copy_from_user (&tmp, ptr, sizeof (tmp)))
-					return -EFAULT;
-				return sys_msgrcv (first, tmp.msgp, second,
-						   tmp.msgtyp, third);
-				}
-			default:
-				return sys_msgrcv (first, ptr,
-						   second, fifth, third);
-			}
-		case MSGGET:
-			return sys_msgget ((key_t) first, second);
-		case MSGCTL:
-			return sys_msgctl (first, second, ptr);
-		default:
-			return -ENOSYS;
-		}
-	if (call <= SHMCTL)
-		switch (call) {
-		case SHMAT:
-			switch (version) {
-			default: {
-				ulong raddr;
-				ret = do_shmat (first, ptr, second, &raddr);
-				if (ret)
-					return ret;
-				return put_user (raddr, (ulong __user *) third);
-			}
-			}
-		case SHMDT:
-			return sys_shmdt (ptr);
-		case SHMGET:
-			return sys_shmget (first, second, third);
-		case SHMCTL:
-			return sys_shmctl (first, second, ptr);
-		default:
-			return -ENOSYS;
-		}
-
-	return -EINVAL;
-}
-
 /* Convert virtual (user) address VADDR to physical address PADDR */
 #define virt_to_phys_040(vaddr)						\
 ({									\
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index 85ed2f9..f6be124 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -116,12 +116,6 @@
 	int ret;
 
 	switch (request) {
-		/* when I and D space are separate, these will need to be fixed. */
-		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
-		case PTRACE_PEEKDATA:
-			ret = generic_ptrace_peekdata(child, addr, data);
-			break;
-
 		/* read the word at location addr in the USER area. */
 		case PTRACE_PEEKUSR: {
 			unsigned long tmp;
@@ -160,12 +154,6 @@
 			break;
 		}
 
-		/* when I and D space are separate, this will have to be fixed. */
-		case PTRACE_POKETEXT: /* write the word at location addr. */
-		case PTRACE_POKEDATA:
-			ret = generic_ptrace_pokedata(child, addr, data);
-			break;
-
 		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
 			ret = -EIO;
 			if ((addr & 3) || addr < 0 ||
@@ -202,66 +190,6 @@
 			}
 			break;
 
-		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-		case PTRACE_CONT: { /* restart after signal. */
-			long tmp;
-
-			ret = -EIO;
-			if (!valid_signal(data))
-				break;
-			if (request == PTRACE_SYSCALL)
-				set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			else
-				clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			child->exit_code = data;
-			/* make sure the single step bit is not set. */
-			tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
-			put_reg(child, PT_SR, tmp);
-			wake_up_process(child);
-			ret = 0;
-			break;
-		}
-
-		/*
-		 * make the child exit.  Best I can do is send it a sigkill. 
-		 * perhaps it should be put in the status that it wants to 
-		 * exit.
-		 */
-		case PTRACE_KILL: {
-			long tmp;
-
-			ret = 0;
-			if (child->exit_state == EXIT_ZOMBIE) /* already dead */
-				break;
-			child->exit_code = SIGKILL;
-			/* make sure the single step bit is not set. */
-			tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
-			put_reg(child, PT_SR, tmp);
-			wake_up_process(child);
-			break;
-		}
-
-		case PTRACE_SINGLESTEP: {  /* set the trap flag. */
-			long tmp;
-
-			ret = -EIO;
-			if (!valid_signal(data))
-				break;
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-			tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
-			put_reg(child, PT_SR, tmp);
-
-			child->exit_code = data;
-			/* give it a chance to run. */
-			wake_up_process(child);
-			ret = 0;
-			break;
-		}
-
-		case PTRACE_DETACH:	/* detach a process that was attached. */
-			ret = ptrace_detach(child, data);
-			break;
-
 		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
 		  	int i;
 			unsigned long tmp;
@@ -325,7 +253,7 @@
 		break;
 
 		default:
-			ret = -EIO;
+			ret = ptrace_request(child, request, addr, data);
 			break;
 	}
 	return ret;
diff --git a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c
index 923dd4a..d65e9c4 100644
--- a/arch/m68knommu/kernel/sys_m68k.c
+++ b/arch/m68knommu/kernel/sys_m68k.c
@@ -27,142 +27,6 @@
 #include <asm/cacheflush.h>
 #include <asm/unistd.h>
 
-/*
- * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
- * handle more than 4 system call parameters, so these system calls
- * used a memory block for parameter passing..
- */
-
-struct mmap_arg_struct {
-	unsigned long addr;
-	unsigned long len;
-	unsigned long prot;
-	unsigned long flags;
-	unsigned long fd;
-	unsigned long offset;
-};
-
-asmlinkage int old_mmap(struct mmap_arg_struct *arg)
-{
-	struct mmap_arg_struct a;
-	int error = -EFAULT;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		goto out;
-
-	error = -EINVAL;
-	if (a.offset & ~PAGE_MASK)
-		goto out;
-
-	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
-				a.offset >> PAGE_SHIFT);
-out:
-	return error;
-}
-
-struct sel_arg_struct {
-	unsigned long n;
-	fd_set *inp, *outp, *exp;
-	struct timeval *tvp;
-};
-
-asmlinkage int old_select(struct sel_arg_struct *arg)
-{
-	struct sel_arg_struct a;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-	/* sys_select() does the appropriate kernel locking */
-	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-}
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage int sys_ipc (uint call, int first, int second,
-			int third, void *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	if (call <= SEMCTL)
-		switch (call) {
-		case SEMOP:
-			return sys_semop (first, (struct sembuf *)ptr, second);
-		case SEMGET:
-			return sys_semget (first, second, third);
-		case SEMCTL: {
-			union semun fourth;
-			if (!ptr)
-				return -EINVAL;
-			if (get_user(fourth.__pad, (void **) ptr))
-				return -EFAULT;
-			return sys_semctl (first, second, third, fourth);
-			}
-		default:
-			return -EINVAL;
-		}
-	if (call <= MSGCTL) 
-		switch (call) {
-		case MSGSND:
-			return sys_msgsnd (first, (struct msgbuf *) ptr, 
-					  second, third);
-		case MSGRCV:
-			switch (version) {
-			case 0: {
-				struct ipc_kludge tmp;
-				if (!ptr)
-					return -EINVAL;
-				if (copy_from_user (&tmp,
-						    (struct ipc_kludge *)ptr,
-						    sizeof (tmp)))
-					return -EFAULT;
-				return sys_msgrcv (first, tmp.msgp, second,
-						   tmp.msgtyp, third);
-				}
-			default:
-				return sys_msgrcv (first,
-						   (struct msgbuf *) ptr,
-						   second, fifth, third);
-			}
-		case MSGGET:
-			return sys_msgget ((key_t) first, second);
-		case MSGCTL:
-			return sys_msgctl (first, second,
-					   (struct msqid_ds *) ptr);
-		default:
-			return -EINVAL;
-		}
-	if (call <= SHMCTL)
-		switch (call) {
-		case SHMAT:
-			switch (version) {
-			default: {
-				ulong raddr;
-				ret = do_shmat (first, ptr, second, &raddr);
-				if (ret)
-					return ret;
-				return put_user (raddr, (ulong __user *) third);
-			}
-			}
-		case SHMDT:
-			return sys_shmdt (ptr);
-		case SHMGET:
-			return sys_shmget (first, second, third);
-		case SHMCTL:
-			return sys_shmctl (first, second, ptr);
-		default:
-			return -ENOSYS;
-		}
-
-	return -EINVAL;
-}
-
 /* sys_cacheflush -- flush (part of) the processor cache.  */
 asmlinkage int
 sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
index 56dd01d..b30b3eb 100644
--- a/arch/m68knommu/kernel/syscalltable.S
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -100,7 +100,7 @@
 	.long sys_settimeofday
 	.long sys_getgroups16	/* 80 */
 	.long sys_setgroups16
-	.long old_select
+	.long sys_old_select
 	.long sys_symlink
 	.long sys_lstat
 	.long sys_readlink	/* 85 */
@@ -108,7 +108,7 @@
 	.long sys_ni_syscall	/* sys_swapon */
 	.long sys_reboot
 	.long sys_old_readdir
-	.long old_mmap		/* 90 */
+	.long sys_old_mmap	/* 90 */
 	.long sys_munmap
 	.long sys_truncate
 	.long sys_ftruncate
diff --git a/arch/microblaze/include/asm/entry.h b/arch/microblaze/include/asm/entry.h
index 61abbd2..ec89f2a 100644
--- a/arch/microblaze/include/asm/entry.h
+++ b/arch/microblaze/include/asm/entry.h
@@ -21,7 +21,7 @@
  * places
  */
 
-#define PER_CPU(var) per_cpu__##var
+#define PER_CPU(var) var
 
 # ifndef __ASSEMBLY__
 DECLARE_PER_CPU(unsigned int, KSP); /* Saved kernel stack pointer */
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index 4b3ac32..6d6349a 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -78,26 +78,6 @@
 	unsigned long copied;
 
 	switch (request) {
-	case PTRACE_PEEKTEXT: /* read word at location addr. */
-	case PTRACE_PEEKDATA:
-		pr_debug("PEEKTEXT/PEEKDATA at %08lX\n", addr);
-		copied = access_process_vm(child, addr, &val, sizeof(val), 0);
-		rval = -EIO;
-		if (copied != sizeof(val))
-			break;
-		rval = put_user(val, (unsigned long *)data);
-		break;
-
-	case PTRACE_POKETEXT: /* write the word at location addr. */
-	case PTRACE_POKEDATA:
-		pr_debug("POKETEXT/POKEDATA to %08lX\n", addr);
-		rval = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1)
-		    == sizeof(data))
-			break;
-		rval = -EIO;
-		break;
-
 	/* Read/write the word at location ADDR in the registers. */
 	case PTRACE_PEEKUSR:
 	case PTRACE_POKEUSR:
@@ -130,50 +110,8 @@
 		if (rval == 0 && request == PTRACE_PEEKUSR)
 			rval = put_user(val, (unsigned long *)data);
 		break;
-	/* Continue and stop at next (return from) syscall */
-	case PTRACE_SYSCALL:
-		pr_debug("PTRACE_SYSCALL\n");
-	case PTRACE_SINGLESTEP:
-		pr_debug("PTRACE_SINGLESTEP\n");
-	/* Restart after a signal.  */
-	case PTRACE_CONT:
-		pr_debug("PTRACE_CONT\n");
-		rval = -EIO;
-		if (!valid_signal(data))
-			break;
-
-		if (request == PTRACE_SYSCALL)
-			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		else
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-
-		child->exit_code = data;
-		pr_debug("wakeup_process\n");
-		wake_up_process(child);
-		rval = 0;
-		break;
-
-	/*
-	 * make the child exit.  Best I can do is send it a sigkill.
-	 * perhaps it should be put in the status that it wants to
-	 * exit.
-	 */
-	case PTRACE_KILL:
-		pr_debug("PTRACE_KILL\n");
-		rval = 0;
-		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
-			break;
-		child->exit_code = SIGKILL;
-		wake_up_process(child);
-		break;
-
-	case PTRACE_DETACH: /* detach a process that was attached. */
-		pr_debug("PTRACE_DETACH\n");
-		rval = ptrace_detach(child, data);
-		break;
 	default:
-		/* rval = ptrace_request(child, request, addr, data); noMMU */
-		rval = -EIO;
+		rval = ptrace_request(child, request, addr, data);
 	}
 	return rval;
 }
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 591ca0c..29e8692 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -812,9 +812,9 @@
 
 config DMA_NONCOHERENT
 	bool
-	select DMA_NEED_PCI_MAP_STATE
+	select NEED_DMA_MAP_STATE
 
-config DMA_NEED_PCI_MAP_STATE
+config NEED_DMA_MAP_STATE
 	bool
 
 config SYS_HAS_EARLY_PRINTK
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index f58aed3..613f691 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -8,7 +8,8 @@
 #include <asm/page.h>
 #include <asm/ptrace.h>
 
-#define COMPAT_USER_HZ	100
+#define COMPAT_USER_HZ		100
+#define COMPAT_UTS_MACHINE	"mips\0\0\0"
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
diff --git a/arch/mips/include/asm/local.h b/arch/mips/include/asm/local.h
index 361f4f16..bdcdef0 100644
--- a/arch/mips/include/asm/local.h
+++ b/arch/mips/include/asm/local.h
@@ -193,29 +193,4 @@
 #define __local_add(i, l)	((l)->a.counter+=(i))
 #define __local_sub(i, l)	((l)->a.counter-=(i))
 
-/* Need to disable preemption for the cpu local counters otherwise we could
-   still access a variable of a previous CPU in a non atomic way. */
-#define cpu_local_wrap_v(l)	 	\
-	({ local_t res__;		\
-	   preempt_disable(); 		\
-	   res__ = (l);			\
-	   preempt_enable();		\
-	   res__; })
-#define cpu_local_wrap(l)		\
-	({ preempt_disable();		\
-	   l;				\
-	   preempt_enable(); })		\
-
-#define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
-#define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
-#define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var(l)))
-#define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var(l)))
-#define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
-#define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
-
-#define __cpu_local_inc(l)	cpu_local_inc(l)
-#define __cpu_local_dec(l)	cpu_local_dec(l)
-#define __cpu_local_add(i, l)	cpu_local_add((i), (l))
-#define __cpu_local_sub(i, l)	cpu_local_sub((i), (l))
-
 #endif /* _ARCH_MIPS_LOCAL_H */
diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 5ebf825..3beea14 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -102,28 +102,6 @@
  */
 extern unsigned int PCI_DMA_BUS_IS_PHYS;
 
-#ifdef CONFIG_DMA_NEED_PCI_MAP_STATE
-
-/* pci_unmap_{single,page} is not a nop, thus... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)		((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)		((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	(((PTR)->LEN_NAME) = (VAL))
-
-#else /* CONFIG_DMA_NEED_PCI_MAP_STATE  */
-
-/* pci_unmap_{page,single} is a nop so... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME)		(0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
-
-#endif /* CONFIG_DMA_NEED_PCI_MAP_STATE  */
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index 65c679e..1b5a664 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -1004,6 +1004,7 @@
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_UTIME
@@ -1013,6 +1014,7 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_UNAME
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index bde79ef..a39d059 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -249,22 +249,6 @@
 }
 #endif
 
-SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name)
-{
-	int ret = 0;
-
-	down_read(&uts_sem);
-	if (copy_to_user(name, utsname(), sizeof *name))
-		ret = -EFAULT;
-	up_read(&uts_sem);
-
-	if (current->personality == PER_LINUX32 && !ret)
-		if (copy_to_user(name->machine, "mips\0\0\0", 8))
-			ret = -EFAULT;
-
-	return ret;
-}
-
 SYSCALL_DEFINE1(32_personality, unsigned long, personality)
 {
 	int ret;
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 054861c..c51b95f 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -493,36 +493,6 @@
 		ret = ptrace_setfpregs(child, (__u32 __user *) data);
 		break;
 
-	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-	case PTRACE_CONT: { /* restart after signal. */
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		if (request == PTRACE_SYSCALL) {
-			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		}
-		else {
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		}
-		child->exit_code = data;
-		wake_up_process(child);
-		ret = 0;
-		break;
-	}
-
-	/*
-	 * make the child exit.  Best I can do is send it a sigkill.
-	 * perhaps it should be put in the status that it wants to
-	 * exit.
-	 */
-	case PTRACE_KILL:
-		ret = 0;
-		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
-			break;
-		child->exit_code = SIGKILL;
-		wake_up_process(child);
-		break;
-
 	case PTRACE_GET_THREAD_AREA:
 		ret = put_user(task_thread_info(child)->tp_value,
 				(unsigned long __user *) data);
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 66b5a48..44337ba 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -181,7 +181,7 @@
 	PTR	sys_exit
 	PTR	compat_sys_wait4
 	PTR	sys_kill			/* 6060 */
-	PTR	sys_32_newuname
+	PTR	sys_newuname
 	PTR	sys_semget
 	PTR	sys_semop
 	PTR	sys_n32_semctl
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 515f9ea..813689e 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -325,7 +325,7 @@
 	PTR	sys32_sigreturn
 	PTR	sys32_clone			/* 4120 */
 	PTR	sys_setdomainname
-	PTR	sys_32_newuname
+	PTR	sys_newuname
 	PTR	sys_ni_syscall			/* sys_modify_ldt */
 	PTR	compat_sys_adjtimex
 	PTR	sys_mprotect			/* 4125 */
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 3f7f466..e96b1c3 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -215,48 +215,6 @@
 	return error;
 }
 
-/*
- * Compacrapability ...
- */
-SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
-{
-	if (name && !copy_to_user(name, utsname(), sizeof (*name)))
-		return 0;
-	return -EFAULT;
-}
-
-/*
- * Compacrapability ...
- */
-SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
-{
-	int error;
-
-	if (!name)
-		return -EFAULT;
-	if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
-		return -EFAULT;
-
-	error = __copy_to_user(&name->sysname, &utsname()->sysname,
-			       __OLD_UTS_LEN);
-	error -= __put_user(0, name->sysname + __OLD_UTS_LEN);
-	error -= __copy_to_user(&name->nodename, &utsname()->nodename,
-				__OLD_UTS_LEN);
-	error -= __put_user(0, name->nodename + __OLD_UTS_LEN);
-	error -= __copy_to_user(&name->release, &utsname()->release,
-				__OLD_UTS_LEN);
-	error -= __put_user(0, name->release + __OLD_UTS_LEN);
-	error -= __copy_to_user(&name->version, &utsname()->version,
-				__OLD_UTS_LEN);
-	error -= __put_user(0, name->version + __OLD_UTS_LEN);
-	error -= __copy_to_user(&name->machine, &utsname()->machine,
-				__OLD_UTS_LEN);
-	error = __put_user(0, name->machine + __OLD_UTS_LEN);
-	error = error ? -EFAULT : 0;
-
-	return error;
-}
-
 SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
 {
 	struct thread_info *ti = task_thread_info(current);
@@ -407,94 +365,6 @@
 }
 
 /*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second,
-	unsigned long, third, void __user *, ptr, long, fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr,
-		                      second, NULL);
-	case SEMTIMEDOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr,
-				      second,
-				      (const struct timespec __user *)fifth);
-	case SEMGET:
-		return sys_semget(first, second, third);
-	case SEMCTL: {
-		union semun fourth;
-		if (!ptr)
-			return -EINVAL;
-		if (get_user(fourth.__pad, (void __user *__user *) ptr))
-			return -EFAULT;
-		return sys_semctl(first, second, third, fourth);
-	}
-
-	case MSGSND:
-		return sys_msgsnd(first, (struct msgbuf __user *) ptr,
-				  second, third);
-	case MSGRCV:
-		switch (version) {
-		case 0: {
-			struct ipc_kludge tmp;
-			if (!ptr)
-				return -EINVAL;
-
-			if (copy_from_user(&tmp,
-					   (struct ipc_kludge __user *) ptr,
-					   sizeof(tmp)))
-				return -EFAULT;
-			return sys_msgrcv(first, tmp.msgp, second,
-					  tmp.msgtyp, third);
-		}
-		default:
-			return sys_msgrcv(first,
-					  (struct msgbuf __user *) ptr,
-					  second, fifth, third);
-		}
-	case MSGGET:
-		return sys_msgget((key_t) first, second);
-	case MSGCTL:
-		return sys_msgctl(first, second,
-				  (struct msqid_ds __user *) ptr);
-
-	case SHMAT:
-		switch (version) {
-		default: {
-			unsigned long raddr;
-			ret = do_shmat(first, (char __user *) ptr, second,
-				       &raddr);
-			if (ret)
-				return ret;
-			return put_user(raddr, (unsigned long __user *) third);
-		}
-		case 1:	/* iBCS2 emulator entry point */
-			if (!segment_eq(get_fs(), get_ds()))
-				return -EINVAL;
-			return do_shmat(first, (char __user *) ptr, second,
-				        (unsigned long *) third);
-		}
-	case SHMDT:
-		return sys_shmdt((char __user *)ptr);
-	case SHMGET:
-		return sys_shmget(first, second, third);
-	case SHMCTL:
-		return sys_shmctl(first, second,
-				  (struct shmid_ds __user *) ptr);
-	default:
-		return -ENOSYS;
-	}
-}
-
-/*
  * No implemented yet ...
  */
 SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
diff --git a/arch/mips/txx9/generic/7segled.c b/arch/mips/txx9/generic/7segled.c
index 727ab21..7f8416f 100644
--- a/arch/mips/txx9/generic/7segled.c
+++ b/arch/mips/txx9/generic/7segled.c
@@ -58,13 +58,16 @@
 static SYSDEV_ATTR(ascii, 0200, NULL, ascii_store);
 static SYSDEV_ATTR(raw, 0200, NULL, raw_store);
 
-static ssize_t map_seg7_show(struct sysdev_class *class, char *buf)
+static ssize_t map_seg7_show(struct sysdev_class *class,
+			     struct sysdev_class_attribute *attr,
+			     char *buf)
 {
 	memcpy(buf, &txx9_seg7map, sizeof(txx9_seg7map));
 	return sizeof(txx9_seg7map);
 }
 
 static ssize_t map_seg7_store(struct sysdev_class *class,
+			      struct sysdev_class_attribute *attr,
 			      const char *buf, size_t size)
 {
 	if (size != sizeof(txx9_seg7map))
diff --git a/arch/mn10300/include/asm/dma-mapping.h b/arch/mn10300/include/asm/dma-mapping.h
index ccae8f6..4ed1522 100644
--- a/arch/mn10300/include/asm/dma-mapping.h
+++ b/arch/mn10300/include/asm/dma-mapping.h
@@ -17,6 +17,11 @@
 #include <asm/cache.h>
 #include <asm/io.h>
 
+/*
+ * See Documentation/DMA-API.txt for the description of how the
+ * following DMA API should work.
+ */
+
 extern void *dma_alloc_coherent(struct device *dev, size_t size,
 				dma_addr_t *dma_handle, int flag);
 
@@ -26,13 +31,6 @@
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent((d), (s), (h), (f))
 #define dma_free_noncoherent(d, s, v, h)  dma_free_coherent((d), (s), (v), (h))
 
-/*
- * Map a single buffer of the indicated size for DMA in streaming mode.  The
- * 32-bit bus address to use is returned.
- *
- * Once the device is given the dma address, the device owns this memory until
- * either pci_unmap_single or pci_dma_sync_single is performed.
- */
 static inline
 dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 			  enum dma_data_direction direction)
@@ -42,14 +40,6 @@
 	return virt_to_bus(ptr);
 }
 
-/*
- * Unmap a single streaming mode DMA translation.  The dma_addr and size must
- * match what was provided for in a previous pci_map_single call.  All other
- * usages are undefined.
- *
- * After this call, reads by the cpu to the buffer are guarenteed to see
- * whatever the device wrote there.
- */
 static inline
 void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		      enum dma_data_direction direction)
@@ -57,20 +47,6 @@
 	BUG_ON(direction == DMA_NONE);
 }
 
-/*
- * Map a set of buffers described by scatterlist in streaming mode for DMA.
- * This is the scather-gather version of the above pci_map_single interface.
- * Here the scatter gather list elements are each tagged with the appropriate
- * dma address and length.  They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of DMA
- *       address/length pairs than there are SG table elements.  (for example
- *       via virtual mapping capabilities) The routine returns the number of
- *       addr/length pairs actually used, at most nents.
- *
- * Device ownership issues as mentioned above for pci_map_single are the same
- * here.
- */
 static inline
 int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
 	       enum dma_data_direction direction)
@@ -91,11 +67,6 @@
 	return nents;
 }
 
-/*
- * Unmap a set of streaming mode DMA translations.
- * Again, cpu read rules concerning calls here are the same as for
- * pci_unmap_single() above.
- */
 static inline
 void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 		  enum dma_data_direction direction)
@@ -103,10 +74,6 @@
 	BUG_ON(!valid_dma_direction(direction));
 }
 
-/*
- * pci_{map,unmap}_single_page maps a kernel page to a dma_addr_t. identical
- * to pci_map_single, but takes a struct page instead of a virtual address
- */
 static inline
 dma_addr_t dma_map_page(struct device *dev, struct page *page,
 			unsigned long offset, size_t size,
@@ -123,15 +90,6 @@
 	BUG_ON(direction == DMA_NONE);
 }
 
-/*
- * Make physical memory consistent for a single streaming mode DMA translation
- * after a transfer.
- *
- * If you perform a pci_map_single() but wish to interrogate the buffer using
- * the cpu, yet do not wish to teardown the PCI dma mapping, you must call this
- * function before doing so.  At the next point you give the PCI dma address
- * back to the card, the device again owns the buffer.
- */
 static inline
 void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
 			     size_t size, enum dma_data_direction direction)
@@ -161,13 +119,6 @@
 }
 
 
-/*
- * Make physical memory consistent for a set of streaming mode DMA translations
- * after a transfer.
- *
- * The same as pci_dma_sync_single but for a scatter-gather list, same rules
- * and usage.
- */
 static inline
 void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
 			 int nelems, enum dma_data_direction direction)
@@ -187,12 +138,6 @@
 	return 0;
 }
 
-/*
- * Return whether the given PCI device DMA address mask can be supported
- * properly.  For example, if your device can only drive the low 24-bits during
- * PCI bus mastering, then you would pass 0x00ffffff as the mask to this
- * function.
- */
 static inline
 int dma_supported(struct device *dev, u64 mask)
 {
diff --git a/arch/mn10300/include/asm/ptrace.h b/arch/mn10300/include/asm/ptrace.h
index 1b0ba5e..7c2e911 100644
--- a/arch/mn10300/include/asm/ptrace.h
+++ b/arch/mn10300/include/asm/ptrace.h
@@ -99,8 +99,6 @@
 extern void show_regs(struct pt_regs *);
 
 #define arch_has_single_step()	(1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
 
 #endif  /*  !__ASSEMBLY  */
 
diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h
index c05acb9..9d056f5 100644
--- a/arch/mn10300/include/asm/unistd.h
+++ b/arch/mn10300/include/asm/unistd.h
@@ -363,6 +363,7 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
@@ -375,6 +376,7 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_SELECT
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index 88e3e1c..d9ed5a1 100644
--- a/arch/mn10300/kernel/entry.S
+++ b/arch/mn10300/kernel/entry.S
@@ -468,7 +468,7 @@
 	.long sys_settimeofday
 	.long sys_getgroups16	/* 80 */
 	.long sys_setgroups16
-	.long old_select
+	.long sys_old_select
 	.long sys_symlink
 	.long sys_lstat
 	.long sys_readlink	/* 85 */
diff --git a/arch/mn10300/kernel/sys_mn10300.c b/arch/mn10300/kernel/sys_mn10300.c
index 17cc6ce..815f135 100644
--- a/arch/mn10300/kernel/sys_mn10300.c
+++ b/arch/mn10300/kernel/sys_mn10300.c
@@ -31,109 +31,3 @@
 		return -EINVAL;
 	return sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
 }
-
-struct sel_arg_struct {
-	unsigned long n;
-	fd_set *inp;
-	fd_set *outp;
-	fd_set *exp;
-	struct timeval *tvp;
-};
-
-asmlinkage int old_select(struct sel_arg_struct __user *arg)
-{
-	struct sel_arg_struct a;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-	/* sys_select() does the appropriate kernel locking */
-	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-}
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage long sys_ipc(uint call, int first, int second,
-			int third, void __user *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr,
-				      second, NULL);
-	case SEMTIMEDOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr,
-				      second,
-				      (const struct timespec __user *)fifth);
-	case SEMGET:
-		return sys_semget(first, second, third);
-	case SEMCTL: {
-		union semun fourth;
-		if (!ptr)
-			return -EINVAL;
-		if (get_user(fourth.__pad, (void __user * __user *) ptr))
-			return -EFAULT;
-		return sys_semctl(first, second, third, fourth);
-	}
-
-	case MSGSND:
-		return sys_msgsnd(first, (struct msgbuf __user *) ptr,
-				  second, third);
-	case MSGRCV:
-		switch (version) {
-		case 0: {
-			struct ipc_kludge tmp;
-			if (!ptr)
-				return -EINVAL;
-
-			if (copy_from_user(&tmp,
-					   (struct ipc_kludge __user *) ptr,
-					   sizeof(tmp)))
-				return -EFAULT;
-			return sys_msgrcv(first, tmp.msgp, second,
-					  tmp.msgtyp, third);
-		}
-		default:
-			return sys_msgrcv(first,
-					  (struct msgbuf __user *) ptr,
-					   second, fifth, third);
-		}
-	case MSGGET:
-		return sys_msgget((key_t) first, second);
-	case MSGCTL:
-		return sys_msgctl(first, second,
-				   (struct msqid_ds __user *) ptr);
-
-	case SHMAT:
-		switch (version) {
-		default: {
-			ulong raddr;
-			ret = do_shmat(first, (char __user *) ptr, second,
-				       &raddr);
-			if (ret)
-				return ret;
-			return put_user(raddr, (ulong *) third);
-		}
-		case 1:	/* iBCS2 emulator entry point */
-			if (!segment_eq(get_fs(), get_ds()))
-				return -EINVAL;
-			return do_shmat(first, (char __user *) ptr, second,
-					(ulong *) third);
-		}
-	case SHMDT:
-		return sys_shmdt((char __user *)ptr);
-	case SHMGET:
-		return sys_shmget(first, second, third);
-	case SHMCTL:
-		return sys_shmctl(first, second,
-				  (struct shmid_ds __user *) ptr);
-	default:
-		return -EINVAL;
-	}
-}
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index f388dc6..9c4da3d 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -95,6 +95,9 @@
 config STACKTRACE_SUPPORT
 	def_bool y
 
+config NEED_DMA_MAP_STATE
+	def_bool y
+
 config ISA_DMA_API
 	bool
 
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
index bc989e5..7305ac8 100644
--- a/arch/parisc/Kconfig.debug
+++ b/arch/parisc/Kconfig.debug
@@ -12,4 +12,18 @@
          portion of the kernel code won't be covered by a TLB anymore.
          If in doubt, say "N".
 
+config DEBUG_STRICT_USER_COPY_CHECKS
+	bool "Strict copy size checks"
+	depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING
+	---help---
+	  Enabling this option turns a certain set of sanity checks for user
+	  copy operations into compile time failures.
+
+	  The copy_from_user() etc checks are there to help test if there
+	  are sufficient security checks on the length argument of
+	  the copy operation, by having gcc prove that the argument is
+	  within bounds.
+
+	  If unsure, or if you run an older (pre 4.4) gcc, say N.
+
 endmenu
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
index 7f32611..02b77ba 100644
--- a/arch/parisc/include/asm/compat.h
+++ b/arch/parisc/include/asm/compat.h
@@ -7,7 +7,8 @@
 #include <linux/sched.h>
 #include <linux/thread_info.h>
 
-#define COMPAT_USER_HZ 100
+#define COMPAT_USER_HZ 		100
+#define COMPAT_UTS_MACHINE	"parisc\0\0"
 
 typedef u32	compat_size_t;
 typedef s32	compat_ssize_t;
diff --git a/arch/parisc/include/asm/param.h b/arch/parisc/include/asm/param.h
index 32e03d8..965d454 100644
--- a/arch/parisc/include/asm/param.h
+++ b/arch/parisc/include/asm/param.h
@@ -1,22 +1 @@
-#ifndef _ASMPARISC_PARAM_H
-#define _ASMPARISC_PARAM_H
-
-#ifdef __KERNEL__
-#define HZ		CONFIG_HZ
-#define USER_HZ		100		/* some user API use "ticks" */
-#define CLOCKS_PER_SEC	(USER_HZ)	/* like times() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE	4096
-
-#ifndef NOGROUP
-#define NOGROUP		(-1)
-#endif
-
-#define MAXHOSTNAMELEN	64	/* max length of hostname */
-
-#endif
+#include <asm-generic/param.h>
diff --git a/arch/parisc/include/asm/pci.h b/arch/parisc/include/asm/pci.h
index 64c7aa5..2242a5c 100644
--- a/arch/parisc/include/asm/pci.h
+++ b/arch/parisc/include/asm/pci.h
@@ -183,20 +183,6 @@
 	void (*fixup_bus)(struct pci_bus *bus);
 };
 
-/* pci_unmap_{single,page} is not a nop, thus... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
-	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
-	__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)			\
-	((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
-	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)			\
-	((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
-	(((PTR)->LEN_NAME) = (VAL))
-
 /*
 ** Stuff declared in arch/parisc/kernel/pci.c
 */
diff --git a/arch/parisc/include/asm/ptrace.h b/arch/parisc/include/asm/ptrace.h
index aead40b..7f09533 100644
--- a/arch/parisc/include/asm/ptrace.h
+++ b/arch/parisc/include/asm/ptrace.h
@@ -47,13 +47,8 @@
 
 #define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))
 
-struct task_struct;
 #define arch_has_single_step()	1
-void user_disable_single_step(struct task_struct *task);
-void user_enable_single_step(struct task_struct *task);
-
 #define arch_has_block_step()	1
-void user_enable_block_step(struct task_struct *task);
 
 /* XXX should we use iaoq[1] or iaoq[0] ? */
 #define user_mode(regs)			(((regs)->iaoq[0] & 3) ? 1 : 0)
diff --git a/arch/parisc/include/asm/system.h b/arch/parisc/include/asm/system.h
index d91357b..4653c77 100644
--- a/arch/parisc/include/asm/system.h
+++ b/arch/parisc/include/asm/system.h
@@ -160,7 +160,7 @@
    ldcd). */
 
 #define __PA_LDCW_ALIGNMENT	4
-#define __ldcw_align(a) ((volatile unsigned int *)a)
+#define __ldcw_align(a) (&(a)->slock)
 #define __LDCW	"ldcw,co"
 
 #endif /*!CONFIG_PA20*/
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index 7cf799d..ff4cf9d 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -7,6 +7,7 @@
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm/cache.h>
+#include <asm/errno.h>
 #include <asm-generic/uaccess-unaligned.h>
 
 #define VERIFY_READ 0
@@ -234,13 +235,35 @@
 
 unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len);
 #define __copy_to_user copy_to_user
-unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len);
-#define __copy_from_user copy_from_user
+unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len);
 unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len);
 #define __copy_in_user copy_in_user
 #define __copy_to_user_inatomic __copy_to_user
 #define __copy_from_user_inatomic __copy_from_user
 
+extern void copy_from_user_overflow(void)
+#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
+        __compiletime_error("copy_from_user() buffer size is not provably correct")
+#else
+        __compiletime_warning("copy_from_user() buffer size is not provably correct")
+#endif
+;
+
+static inline unsigned long __must_check copy_from_user(void *to,
+                                          const void __user *from,
+                                          unsigned long n)
+{
+        int sz = __compiletime_object_size(to);
+        int ret = -EFAULT;
+
+        if (likely(sz == -1 || !__builtin_constant_p(n) || sz >= n))
+                ret = __copy_from_user(to, from, n);
+        else
+                copy_from_user_overflow();
+
+        return ret;
+}
+
 struct pt_regs;
 int fixup_exception(struct pt_regs *regs);
 
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h
index cda1583..1ce7d28 100644
--- a/arch/parisc/include/asm/unistd.h
+++ b/arch/parisc/include/asm/unistd.h
@@ -811,8 +811,10 @@
 #define __NR_pwritev		(__NR_Linux + 316)
 #define __NR_rt_tgsigqueueinfo	(__NR_Linux + 317)
 #define __NR_perf_event_open	(__NR_Linux + 318)
+#define __NR_recvmmsg		(__NR_Linux + 319)
+#define __NR_accept4		(__NR_Linux + 320)
 
-#define __NR_Linux_syscalls	(__NR_perf_event_open + 1)
+#define __NR_Linux_syscalls	(__NR_accept4 + 1)
 
 
 #define __IGNORE_select		/* newselect */
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 1054baa..d054f3d 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -171,14 +171,14 @@
 		cache_info.ic_conf.cc_cst,
 		cache_info.ic_conf.cc_hv);
 
-	printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
+	printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n",
 		cache_info.dt_conf.tc_sh,
 		cache_info.dt_conf.tc_page,
 		cache_info.dt_conf.tc_cst,
 		cache_info.dt_conf.tc_aid,
 		cache_info.dt_conf.tc_pad1);
 
-	printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
+	printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n",
 		cache_info.it_conf.tc_sh,
 		cache_info.it_conf.tc_page,
 		cache_info.it_conf.tc_cst,
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 9147391..c9b9322 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -234,18 +234,3 @@
 
 	return err;
 }
-
-long parisc_newuname(struct new_utsname __user *name)
-{
-	int err = sys_newuname(name);
-
-#ifdef CONFIG_COMPAT
-	if (!err && personality(current->personality) == PER_LINUX32) {
-		if (__put_user(0, name->machine + 6) ||
-		    __put_user(0, name->machine + 7))
-			err = -EFAULT;
-	}
-#endif
-
-	return err;
-}
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 01c4fcf..3d52c97 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -127,7 +127,7 @@
 	ENTRY_SAME(socketpair)
 	ENTRY_SAME(setpgid)
 	ENTRY_SAME(send)
-	ENTRY_OURS(newuname)
+	ENTRY_SAME(newuname)
 	ENTRY_SAME(umask)		/* 60 */
 	ENTRY_SAME(chroot)
 	ENTRY_COMP(ustat)
@@ -417,6 +417,8 @@
 	ENTRY_COMP(pwritev)
 	ENTRY_COMP(rt_tgsigqueueinfo)
 	ENTRY_SAME(perf_event_open)
+	ENTRY_COMP(recvmmsg)
+	ENTRY_SAME(accept4)		/* 320 */
 
 	/* Nothing yet */
 
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index a79c6f9..05511cc 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -250,9 +250,21 @@
 }
 module_init(rtc_init);
 
-void __init time_init(void)
+void read_persistent_clock(struct timespec *ts)
 {
 	static struct pdc_tod tod_data;
+	if (pdc_tod_read(&tod_data) == 0) {
+		ts->tv_sec = tod_data.tod_sec;
+		ts->tv_nsec = tod_data.tod_usec * 1000;
+	} else {
+		printk(KERN_ERR "Error reading tod clock\n");
+	        ts->tv_sec = 0;
+		ts->tv_nsec = 0;
+	}
+}
+
+void __init time_init(void)
+{
 	unsigned long current_cr16_khz;
 
 	clocktick = (100 * PAGE0->mem_10msec) / HZ;
@@ -264,19 +276,4 @@
 	clocksource_cr16.mult = clocksource_khz2mult(current_cr16_khz,
 						clocksource_cr16.shift);
 	clocksource_register(&clocksource_cr16);
-
-	if (pdc_tod_read(&tod_data) == 0) {
-		unsigned long flags;
-
-		write_seqlock_irqsave(&xtime_lock, flags);
-		xtime.tv_sec = tod_data.tod_sec;
-		xtime.tv_nsec = tod_data.tod_usec * 1000;
-		set_normalized_timespec(&wall_to_monotonic,
-		                        -xtime.tv_sec, -xtime.tv_nsec);
-		write_sequnlock_irqrestore(&xtime_lock, flags);
-	} else {
-		printk(KERN_ERR "Error reading tod clock\n");
-	        xtime.tv_sec = 0;
-		xtime.tv_nsec = 0;
-	}
 }
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index e6f4b7a..92d977b 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
+#include <linux/ratelimit.h>
 #include <asm/uaccess.h>
 
 /* #define DEBUG_UNALIGNED 1 */
@@ -446,8 +447,7 @@
 
 void handle_unaligned(struct pt_regs *regs)
 {
-	static unsigned long unaligned_count = 0;
-	static unsigned long last_time = 0;
+	static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5);
 	unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
 	int modify = 0;
 	int ret = ERR_NOTHANDLED;
@@ -460,14 +460,8 @@
 			goto force_sigbus;
 		}
 
-		if (unaligned_count > 5 &&
-				time_after(jiffies, last_time + 5 * HZ)) {
-			unaligned_count = 0;
-			last_time = jiffies;
-		}
-
-		if (!(current->thread.flags & PARISC_UAC_NOPRINT) 
-		    && ++unaligned_count < 5) {
+		if (!(current->thread.flags & PARISC_UAC_NOPRINT) &&
+			__ratelimit(&ratelimit)) {
 			char buf[256];
 			sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n",
 				current->comm, task_pid_nr(current), regs->ior, regs->iaoq[0]);
diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S
index d172d42..f8c45cc 100644
--- a/arch/parisc/lib/fixup.S
+++ b/arch/parisc/lib/fixup.S
@@ -36,8 +36,8 @@
 #endif
 	/* t2 = &__per_cpu_offset[smp_processor_id()]; */
 	LDREGX \t2(\t1),\t2 
-	addil LT%per_cpu__exception_data,%r27
-	LDREG RT%per_cpu__exception_data(%r1),\t1
+	addil LT%exception_data,%r27
+	LDREG RT%exception_data(%r1),\t1
 	/* t1 = &__get_cpu_var(exception_data) */
 	add,l \t1,\t2,\t1
 	/* t1 = t1->fault_ip */
@@ -46,8 +46,8 @@
 #else
 	.macro  get_fault_ip t1 t2
 	/* t1 = &__get_cpu_var(exception_data) */
-	addil LT%per_cpu__exception_data,%r27
-	LDREG RT%per_cpu__exception_data(%r1),\t2
+	addil LT%exception_data,%r27
+	LDREG RT%exception_data(%r1),\t2
 	/* t1 = t2->fault_ip */
 	LDREG EXCDATA_IP(\t2), \t1
 	.endm
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index abf41f4..1dbca5c 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -475,7 +475,8 @@
 	return pa_memcpy((void __force *)dst, src, len);
 }
 
-unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len)
+EXPORT_SYMBOL(__copy_from_user);
+unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len)
 {
 	mtsp(get_user_space(), 1);
 	mtsp(get_kernel_space(), 2);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 155d571..8a54eb8 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -672,6 +672,9 @@
 	bool
 	default y
 
+config NEED_DMA_MAP_STATE
+	def_bool (PPC64 || NOT_COHERENT_CACHE)
+
 config GENERIC_ISA_DMA
 	bool
 	depends on PPC64 || POWER4 || 6xx && !CPM2
diff --git a/arch/powerpc/boot/dts/gef_ppc9a.dts b/arch/powerpc/boot/dts/gef_ppc9a.dts
index 977f260..83f4b79 100644
--- a/arch/powerpc/boot/dts/gef_ppc9a.dts
+++ b/arch/powerpc/boot/dts/gef_ppc9a.dts
@@ -1,7 +1,7 @@
 /*
- * GE Fanuc PPC9A Device Tree Source
+ * GE PPC9A Device Tree Source
  *
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, 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
diff --git a/arch/powerpc/boot/dts/gef_sbc310.dts b/arch/powerpc/boot/dts/gef_sbc310.dts
index 8e4efff..fc3a331 100644
--- a/arch/powerpc/boot/dts/gef_sbc310.dts
+++ b/arch/powerpc/boot/dts/gef_sbc310.dts
@@ -1,7 +1,7 @@
 /*
- * GE Fanuc SBC310 Device Tree Source
+ * GE SBC310 Device Tree Source
  *
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, 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
diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts
index bb70600..c0671cc 100644
--- a/arch/powerpc/boot/dts/gef_sbc610.dts
+++ b/arch/powerpc/boot/dts/gef_sbc610.dts
@@ -1,7 +1,7 @@
 /*
- * GE Fanuc SBC610 Device Tree Source
+ * GE SBC610 Device Tree Source
  *
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, 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
diff --git a/arch/powerpc/boot/dts/kmeter1.dts b/arch/powerpc/boot/dts/kmeter1.dts
index 65b8b4f..d8b5d12 100644
--- a/arch/powerpc/boot/dts/kmeter1.dts
+++ b/arch/powerpc/boot/dts/kmeter1.dts
@@ -490,7 +490,7 @@
 			compatible = "cfi-flash";
 			/*
 			 * The Intel P30 chip has 2 non-identical chips on
-			 * one die, so we need to define 2 seperate regions
+			 * one die, so we need to define 2 separate regions
 			 * that are scanned by physmap_of independantly.
 			 */
 			reg = <0 0x00000000 0x02000000
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index 4774c2f..396d21a 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -7,7 +7,8 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 
-#define COMPAT_USER_HZ	100
+#define COMPAT_USER_HZ		100
+#define COMPAT_UTS_MACHINE	"ppc\0\0"
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 80a973b..c85ef23 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -127,9 +127,6 @@
 	return dma_ops->dma_supported(dev, mask);
 }
 
-/* We have our own implementation of pci_set_dma_mask() */
-#define HAVE_ARCH_PCI_SET_DMA_MASK
-
 static inline int dma_set_mask(struct device *dev, u64 dma_mask)
 {
 	struct dma_map_ops *dma_ops = get_dma_ops(dev);
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h
index af2abe7..aadf2dd 100644
--- a/arch/powerpc/include/asm/kvm_asm.h
+++ b/arch/powerpc/include/asm/kvm_asm.h
@@ -97,4 +97,10 @@
 #define RESUME_HOST             RESUME_FLAG_HOST
 #define RESUME_HOST_NV          (RESUME_FLAG_HOST|RESUME_FLAG_NV)
 
+#define KVM_GUEST_MODE_NONE	0
+#define KVM_GUEST_MODE_GUEST	1
+#define KVM_GUEST_MODE_SKIP	2
+
+#define KVM_INST_FETCH_FAILED	-1
+
 #endif /* __POWERPC_KVM_ASM_H__ */
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 74b7369..db7db0a 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -22,7 +22,7 @@
 
 #include <linux/types.h>
 #include <linux/kvm_host.h>
-#include <asm/kvm_ppc.h>
+#include <asm/kvm_book3s_64_asm.h>
 
 struct kvmppc_slb {
 	u64 esid;
@@ -33,7 +33,8 @@
 	bool Ks;
 	bool Kp;
 	bool nx;
-	bool large;
+	bool large;	/* PTEs are 16MB */
+	bool tb;	/* 1TB segment */
 	bool class;
 };
 
@@ -69,6 +70,7 @@
 
 struct kvmppc_vcpu_book3s {
 	struct kvm_vcpu vcpu;
+	struct kvmppc_book3s_shadow_vcpu shadow_vcpu;
 	struct kvmppc_sid_map sid_map[SID_MAP_NUM];
 	struct kvmppc_slb slb[64];
 	struct {
@@ -89,6 +91,7 @@
 	u64 vsid_next;
 	u64 vsid_max;
 	int context_id;
+	ulong prog_flags; /* flags to inject when giving a 700 trap */
 };
 
 #define CONTEXT_HOST		0
@@ -119,6 +122,10 @@
 
 extern u32 kvmppc_trampoline_lowmem;
 extern u32 kvmppc_trampoline_enter;
+extern void kvmppc_rmcall(ulong srr0, ulong srr1);
+extern void kvmppc_load_up_fpu(void);
+extern void kvmppc_load_up_altivec(void);
+extern void kvmppc_load_up_vsx(void);
 
 static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
 {
diff --git a/arch/powerpc/include/asm/kvm_book3s_64_asm.h b/arch/powerpc/include/asm/kvm_book3s_64_asm.h
index 2e06ee8..183461b 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64_asm.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64_asm.h
@@ -20,6 +20,8 @@
 #ifndef __ASM_KVM_BOOK3S_ASM_H__
 #define __ASM_KVM_BOOK3S_ASM_H__
 
+#ifdef __ASSEMBLY__
+
 #ifdef CONFIG_KVM_BOOK3S_64_HANDLER
 
 #include <asm/kvm_asm.h>
@@ -55,4 +57,20 @@
 
 #endif /* CONFIG_KVM_BOOK3S_64_HANDLER */
 
+#else  /*__ASSEMBLY__ */
+
+struct kvmppc_book3s_shadow_vcpu {
+	ulong gpr[14];
+	u32 cr;
+	u32 xer;
+	ulong host_r1;
+	ulong host_r2;
+	ulong handler;
+	ulong scratch0;
+	ulong scratch1;
+	ulong vmhandler;
+};
+
+#endif /*__ASSEMBLY__ */
+
 #endif /* __ASM_KVM_BOOK3S_ASM_H__ */
diff --git a/arch/powerpc/include/asm/kvm_e500.h b/arch/powerpc/include/asm/kvm_e500.h
index 9d497ce..7fea26f 100644
--- a/arch/powerpc/include/asm/kvm_e500.h
+++ b/arch/powerpc/include/asm/kvm_e500.h
@@ -52,9 +52,12 @@
 	u32 mas5;
 	u32 mas6;
 	u32 mas7;
+	u32 l1csr0;
 	u32 l1csr1;
 	u32 hid0;
 	u32 hid1;
+	u32 tlb0cfg;
+	u32 tlb1cfg;
 
 	struct kvm_vcpu vcpu;
 };
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 1201f62..5e5bae7 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -167,23 +167,40 @@
 	ulong trampoline_lowmem;
 	ulong trampoline_enter;
 	ulong highmem_handler;
+	ulong rmcall;
 	ulong host_paca_phys;
 	struct kvmppc_mmu mmu;
 #endif
 
-	u64 fpr[32];
 	ulong gpr[32];
 
+	u64 fpr[32];
+	u32 fpscr;
+
+#ifdef CONFIG_ALTIVEC
+	vector128 vr[32];
+	vector128 vscr;
+#endif
+
+#ifdef CONFIG_VSX
+	u64 vsr[32];
+#endif
+
 	ulong pc;
-	u32 cr;
 	ulong ctr;
 	ulong lr;
+
+#ifdef CONFIG_BOOKE
 	ulong xer;
+	u32 cr;
+#endif
 
 	ulong msr;
 #ifdef CONFIG_PPC64
 	ulong shadow_msr;
+	ulong shadow_srr1;
 	ulong hflags;
+	ulong guest_owned_ext;
 #endif
 	u32 mmucr;
 	ulong sprg0;
@@ -242,6 +259,8 @@
 #endif
 	ulong fault_dear;
 	ulong fault_esr;
+	ulong queued_dear;
+	ulong queued_esr;
 	gpa_t paddr_accessed;
 
 	u8 io_gpr; /* GPR used as IO source/target */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 269ee46..e264282 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -28,6 +28,9 @@
 #include <linux/types.h>
 #include <linux/kvm_types.h>
 #include <linux/kvm_host.h>
+#ifdef CONFIG_PPC_BOOK3S
+#include <asm/kvm_book3s.h>
+#endif
 
 enum emulation_result {
 	EMULATE_DONE,         /* no further processing */
@@ -80,8 +83,9 @@
 
 extern void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu);
 extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu);
-extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags);
 extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu);
 extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                        struct kvm_interrupt *irq);
 
@@ -95,4 +99,81 @@
 
 extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu);
 
+#ifdef CONFIG_PPC_BOOK3S
+
+/* We assume we're always acting on the current vcpu */
+
+static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
+{
+	if ( num < 14 ) {
+		get_paca()->shadow_vcpu.gpr[num] = val;
+		to_book3s(vcpu)->shadow_vcpu.gpr[num] = val;
+	} else
+		vcpu->arch.gpr[num] = val;
+}
+
+static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num)
+{
+	if ( num < 14 )
+		return get_paca()->shadow_vcpu.gpr[num];
+	else
+		return vcpu->arch.gpr[num];
+}
+
+static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val)
+{
+	get_paca()->shadow_vcpu.cr = val;
+	to_book3s(vcpu)->shadow_vcpu.cr = val;
+}
+
+static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu)
+{
+	return get_paca()->shadow_vcpu.cr;
+}
+
+static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val)
+{
+	get_paca()->shadow_vcpu.xer = val;
+	to_book3s(vcpu)->shadow_vcpu.xer = val;
+}
+
+static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu)
+{
+	return get_paca()->shadow_vcpu.xer;
+}
+
+#else
+
+static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
+{
+	vcpu->arch.gpr[num] = val;
+}
+
+static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num)
+{
+	return vcpu->arch.gpr[num];
+}
+
+static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val)
+{
+	vcpu->arch.cr = val;
+}
+
+static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.cr;
+}
+
+static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val)
+{
+	vcpu->arch.xer = val;
+}
+
+static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.xer;
+}
+
+#endif
+
 #endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/include/asm/local.h b/arch/powerpc/include/asm/local.h
index ce58c80..c2410af 100644
--- a/arch/powerpc/include/asm/local.h
+++ b/arch/powerpc/include/asm/local.h
@@ -172,29 +172,4 @@
 #define __local_add(i,l)	((l)->a.counter+=(i))
 #define __local_sub(i,l)	((l)->a.counter-=(i))
 
-/* Need to disable preemption for the cpu local counters otherwise we could
-   still access a variable of a previous CPU in a non atomic way. */
-#define cpu_local_wrap_v(l)	 	\
-	({ local_t res__;		\
-	   preempt_disable(); 		\
-	   res__ = (l);			\
-	   preempt_enable();		\
-	   res__; })
-#define cpu_local_wrap(l)		\
-	({ preempt_disable();		\
-	   l;				\
-	   preempt_enable(); })		\
-
-#define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
-#define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
-#define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var(l)))
-#define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var(l)))
-#define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
-#define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
-
-#define __cpu_local_inc(l)	cpu_local_inc(l)
-#define __cpu_local_dec(l)	cpu_local_dec(l)
-#define __cpu_local_add(i, l)	cpu_local_add((i), (l))
-#define __cpu_local_sub(i, l)	cpu_local_sub((i), (l))
-
 #endif /* _ARCH_POWERPC_LOCAL_H */
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 5e9b4ef..a011603 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -14,11 +14,17 @@
 #define _ASM_POWERPC_PACA_H
 #ifdef __KERNEL__
 
+#ifdef CONFIG_PPC64
+
+#include <linux/init.h>
 #include <asm/types.h>
 #include <asm/lppaca.h>
 #include <asm/mmu.h>
 #include <asm/page.h>
 #include <asm/exception-64e.h>
+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
+#include <asm/kvm_book3s_64_asm.h>
+#endif
 
 register struct paca_struct *local_paca asm("r13");
 
@@ -135,13 +141,26 @@
 		u64     esid;
 		u64     vsid;
 	} kvm_slb[64];			/* guest SLB */
+	/* We use this to store guest state in */
+	struct kvmppc_book3s_shadow_vcpu shadow_vcpu;
 	u8 kvm_slb_max;			/* highest used guest slb entry */
 	u8 kvm_in_guest;		/* are we inside the guest? */
 #endif
 };
 
-extern struct paca_struct paca[];
-extern void initialise_pacas(void);
+extern struct paca_struct *paca;
+extern __initdata struct paca_struct boot_paca;
+extern void initialise_paca(struct paca_struct *new_paca, int cpu);
+
+extern void allocate_pacas(void);
+extern void free_unused_pacas(void);
+
+#else /* CONFIG_PPC64 */
+
+static inline void allocate_pacas(void) { };
+static inline void free_unused_pacas(void) { };
+
+#endif /* CONFIG_PPC64 */
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_PACA_H */
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index b5ea626..a20a9ad 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -141,38 +141,6 @@
 
 #define HAVE_PCI_LEGACY	1
 
-#if defined(CONFIG_PPC64) || defined(CONFIG_NOT_COHERENT_CACHE)
-/*
- * For 64-bit kernels, pci_unmap_{single,page} is not a nop.
- * For 32-bit non-coherent kernels, pci_dma_sync_single_for_cpu() and
- * so on are not nops.
- * and thus...
- */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
-	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
-	__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)			\
-	((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
-	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)			\
-	((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
-	(((PTR)->LEN_NAME) = (VAL))
-
-#else /* 32-bit && coherent */
-
-/* pci_unmap_{page,single} is a nop so... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME)		(0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
-
-#endif /* CONFIG_PPC64 || CONFIG_NOT_COHERENT_CACHE */
-
 #ifdef CONFIG_PPC64
 
 /* The PCI address space does not equal the physical memory address
diff --git a/arch/powerpc/include/asm/perf_event.h b/arch/powerpc/include/asm/perf_event.h
index 3288ce3..e6d4ce6 100644
--- a/arch/powerpc/include/asm/perf_event.h
+++ b/arch/powerpc/include/asm/perf_event.h
@@ -1,110 +1,23 @@
 /*
- * Performance event support - PowerPC-specific definitions.
+ * Performance event support - hardware-specific disambiguation
  *
- * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ * For now this is a compile-time decision, but eventually it should be
+ * runtime.  This would allow multiplatform perf event support for e300 (fsl
+ * embedded perf counters) plus server/classic, and would accommodate
+ * devices other than the core which provide their own performance counters.
+ *
+ * Copyright 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.
  */
-#include <linux/types.h>
 
-#include <asm/hw_irq.h>
-
-#define MAX_HWEVENTS		8
-#define MAX_EVENT_ALTERNATIVES	8
-#define MAX_LIMITED_HWCOUNTERS	2
-
-/*
- * This struct provides the constants and functions needed to
- * describe the PMU on a particular POWER-family CPU.
- */
-struct power_pmu {
-	const char	*name;
-	int		n_counter;
-	int		max_alternatives;
-	unsigned long	add_fields;
-	unsigned long	test_adder;
-	int		(*compute_mmcr)(u64 events[], int n_ev,
-				unsigned int hwc[], unsigned long mmcr[]);
-	int		(*get_constraint)(u64 event_id, unsigned long *mskp,
-				unsigned long *valp);
-	int		(*get_alternatives)(u64 event_id, unsigned int flags,
-				u64 alt[]);
-	void		(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
-	int		(*limited_pmc_event)(u64 event_id);
-	u32		flags;
-	int		n_generic;
-	int		*generic_events;
-	int		(*cache_events)[PERF_COUNT_HW_CACHE_MAX]
-			       [PERF_COUNT_HW_CACHE_OP_MAX]
-			       [PERF_COUNT_HW_CACHE_RESULT_MAX];
-};
-
-/*
- * Values for power_pmu.flags
- */
-#define PPMU_LIMITED_PMC5_6	1	/* PMC5/6 have limited function */
-#define PPMU_ALT_SIPR		2	/* uses alternate posn for SIPR/HV */
-
-/*
- * Values for flags to get_alternatives()
- */
-#define PPMU_LIMITED_PMC_OK	1	/* can put this on a limited PMC */
-#define PPMU_LIMITED_PMC_REQD	2	/* have to put this on a limited PMC */
-#define PPMU_ONLY_COUNT_RUN	4	/* only counting in run state */
-
-extern int register_power_pmu(struct power_pmu *);
-
-struct pt_regs;
-extern unsigned long perf_misc_flags(struct pt_regs *regs);
-extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
-
-#define PERF_EVENT_INDEX_OFFSET	1
-
-/*
- * Only override the default definitions in include/linux/perf_event.h
- * if we have hardware PMU support.
- */
 #ifdef CONFIG_PPC_PERF_CTRS
-#define perf_misc_flags(regs)	perf_misc_flags(regs)
+#include <asm/perf_event_server.h>
 #endif
 
-/*
- * The power_pmu.get_constraint function returns a 32/64-bit value and
- * a 32/64-bit mask that express the constraints between this event_id and
- * other events.
- *
- * The value and mask are divided up into (non-overlapping) bitfields
- * of three different types:
- *
- * Select field: this expresses the constraint that some set of bits
- * in MMCR* needs to be set to a specific value for this event_id.  For a
- * select field, the mask contains 1s in every bit of the field, and
- * the value contains a unique value for each possible setting of the
- * MMCR* bits.  The constraint checking code will ensure that two events
- * that set the same field in their masks have the same value in their
- * value dwords.
- *
- * Add field: this expresses the constraint that there can be at most
- * N events in a particular class.  A field of k bits can be used for
- * N <= 2^(k-1) - 1.  The mask has the most significant bit of the field
- * set (and the other bits 0), and the value has only the least significant
- * bit of the field set.  In addition, the 'add_fields' and 'test_adder'
- * in the struct power_pmu for this processor come into play.  The
- * add_fields value contains 1 in the LSB of the field, and the
- * test_adder contains 2^(k-1) - 1 - N in the field.
- *
- * NAND field: this expresses the constraint that you may not have events
- * in all of a set of classes.  (For example, on PPC970, you can't select
- * events from the FPU, ISU and IDU simultaneously, although any two are
- * possible.)  For N classes, the field is N+1 bits wide, and each class
- * is assigned one bit from the least-significant N bits.  The mask has
- * only the most-significant bit set, and the value has only the bit
- * for the event_id's class set.  The test_adder has the least significant
- * bit set in the field.
- *
- * If an event_id is not subject to the constraint expressed by a particular
- * field, then it will have 0 in both the mask and value for that field.
- */
+#ifdef CONFIG_FSL_EMB_PERF_EVENT
+#include <asm/perf_event_fsl_emb.h>
+#endif
diff --git a/arch/powerpc/include/asm/perf_event_fsl_emb.h b/arch/powerpc/include/asm/perf_event_fsl_emb.h
new file mode 100644
index 0000000..718a9fa
--- /dev/null
+++ b/arch/powerpc/include/asm/perf_event_fsl_emb.h
@@ -0,0 +1,50 @@
+/*
+ * Performance event support - Freescale embedded specific definitions.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ * Copyright 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.
+ */
+
+#include <linux/types.h>
+#include <asm/hw_irq.h>
+
+#define MAX_HWEVENTS 4
+
+/* event flags */
+#define FSL_EMB_EVENT_VALID      1
+#define FSL_EMB_EVENT_RESTRICTED 2
+
+/* upper half of event flags is PMLCb */
+#define FSL_EMB_EVENT_THRESHMUL  0x0000070000000000ULL
+#define FSL_EMB_EVENT_THRESH     0x0000003f00000000ULL
+
+struct fsl_emb_pmu {
+	const char	*name;
+	int		n_counter; /* total number of counters */
+
+	/*
+	 * The number of contiguous counters starting at zero that
+	 * can hold restricted events, or zero if there are no
+	 * restricted events.
+	 *
+	 * This isn't a very flexible method of expressing constraints,
+	 * but it's very simple and is adequate for existing chips.
+	 */
+	int		n_restricted;
+
+	/* Returns event flags and PMLCb (FSL_EMB_EVENT_*) */
+	u64		(*xlate_event)(u64 event_id);
+
+	int		n_generic;
+	int		*generic_events;
+	int		(*cache_events)[PERF_COUNT_HW_CACHE_MAX]
+			       [PERF_COUNT_HW_CACHE_OP_MAX]
+			       [PERF_COUNT_HW_CACHE_RESULT_MAX];
+};
+
+int register_fsl_emb_pmu(struct fsl_emb_pmu *);
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
new file mode 100644
index 0000000..8f1df12
--- /dev/null
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -0,0 +1,110 @@
+/*
+ * Performance event support - PowerPC classic/server specific definitions.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <asm/hw_irq.h>
+
+#define MAX_HWEVENTS		8
+#define MAX_EVENT_ALTERNATIVES	8
+#define MAX_LIMITED_HWCOUNTERS	2
+
+/*
+ * This struct provides the constants and functions needed to
+ * describe the PMU on a particular POWER-family CPU.
+ */
+struct power_pmu {
+	const char	*name;
+	int		n_counter;
+	int		max_alternatives;
+	unsigned long	add_fields;
+	unsigned long	test_adder;
+	int		(*compute_mmcr)(u64 events[], int n_ev,
+				unsigned int hwc[], unsigned long mmcr[]);
+	int		(*get_constraint)(u64 event_id, unsigned long *mskp,
+				unsigned long *valp);
+	int		(*get_alternatives)(u64 event_id, unsigned int flags,
+				u64 alt[]);
+	void		(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
+	int		(*limited_pmc_event)(u64 event_id);
+	u32		flags;
+	int		n_generic;
+	int		*generic_events;
+	int		(*cache_events)[PERF_COUNT_HW_CACHE_MAX]
+			       [PERF_COUNT_HW_CACHE_OP_MAX]
+			       [PERF_COUNT_HW_CACHE_RESULT_MAX];
+};
+
+/*
+ * Values for power_pmu.flags
+ */
+#define PPMU_LIMITED_PMC5_6	1	/* PMC5/6 have limited function */
+#define PPMU_ALT_SIPR		2	/* uses alternate posn for SIPR/HV */
+
+/*
+ * Values for flags to get_alternatives()
+ */
+#define PPMU_LIMITED_PMC_OK	1	/* can put this on a limited PMC */
+#define PPMU_LIMITED_PMC_REQD	2	/* have to put this on a limited PMC */
+#define PPMU_ONLY_COUNT_RUN	4	/* only counting in run state */
+
+extern int register_power_pmu(struct power_pmu *);
+
+struct pt_regs;
+extern unsigned long perf_misc_flags(struct pt_regs *regs);
+extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
+
+#define PERF_EVENT_INDEX_OFFSET	1
+
+/*
+ * Only override the default definitions in include/linux/perf_event.h
+ * if we have hardware PMU support.
+ */
+#ifdef CONFIG_PPC_PERF_CTRS
+#define perf_misc_flags(regs)	perf_misc_flags(regs)
+#endif
+
+/*
+ * The power_pmu.get_constraint function returns a 32/64-bit value and
+ * a 32/64-bit mask that express the constraints between this event_id and
+ * other events.
+ *
+ * The value and mask are divided up into (non-overlapping) bitfields
+ * of three different types:
+ *
+ * Select field: this expresses the constraint that some set of bits
+ * in MMCR* needs to be set to a specific value for this event_id.  For a
+ * select field, the mask contains 1s in every bit of the field, and
+ * the value contains a unique value for each possible setting of the
+ * MMCR* bits.  The constraint checking code will ensure that two events
+ * that set the same field in their masks have the same value in their
+ * value dwords.
+ *
+ * Add field: this expresses the constraint that there can be at most
+ * N events in a particular class.  A field of k bits can be used for
+ * N <= 2^(k-1) - 1.  The mask has the most significant bit of the field
+ * set (and the other bits 0), and the value has only the least significant
+ * bit of the field set.  In addition, the 'add_fields' and 'test_adder'
+ * in the struct power_pmu for this processor come into play.  The
+ * add_fields value contains 1 in the LSB of the field, and the
+ * test_adder contains 2^(k-1) - 1 - N in the field.
+ *
+ * NAND field: this expresses the constraint that you may not have events
+ * in all of a set of classes.  (For example, on PPC970, you can't select
+ * events from the FPU, ISU and IDU simultaneously, although any two are
+ * possible.)  For N classes, the field is N+1 bits wide, and each class
+ * is assigned one bit from the least-significant N bits.  The mask has
+ * only the most-significant bit set, and the value has only the bit
+ * for the event_id's class set.  The test_adder has the least significant
+ * bit set in the field.
+ *
+ * If an event_id is not subject to the constraint expressed by a particular
+ * field, then it will have 0 in both the mask and value for that field.
+ */
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index b451081..9e2d84c 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -137,15 +137,8 @@
 } while (0)
 #endif /* __powerpc64__ */
 
-/*
- * These are defined as per linux/ptrace.h, which see.
- */
 #define arch_has_single_step()	(1)
 #define arch_has_block_step()	(!cpu_has_feature(CPU_FTR_601))
-extern void user_enable_single_step(struct task_struct *);
-extern void user_enable_block_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
-
 #define ARCH_HAS_USER_SINGLE_STEP_INFO
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index bc8dd53..5572e86 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -426,6 +426,10 @@
 #define   SRR1_WAKEMT		0x00280000 /* mtctrl */
 #define   SRR1_WAKEDEC		0x00180000 /* Decrementer interrupt */
 #define   SRR1_WAKETHERM	0x00100000 /* Thermal management interrupt */
+#define   SRR1_PROGFPE		0x00100000 /* Floating Point Enabled */
+#define   SRR1_PROGPRIV		0x00040000 /* Privileged instruction */
+#define   SRR1_PROGTRAP		0x00020000 /* Trap */
+#define   SRR1_PROGADDR		0x00010000 /* SRR0 contains subsequent addr */
 #define SPRN_HSRR0	0x13A	/* Save/Restore Register 0 */
 #define SPRN_HSRR1	0x13B	/* Save/Restore Register 1 */
 
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 8808d30..414d434 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -421,8 +421,8 @@
 /* Bit definitions related to the DBCR2. */
 #define DBCR2_DAC1US	0xC0000000	/* Data Addr Cmp 1 Sup/User   */
 #define DBCR2_DAC1ER	0x30000000	/* Data Addr Cmp 1 Eff/Real */
-#define DBCR2_DAC2US	0x00000000	/* Data Addr Cmp 2 Sup/User   */
-#define DBCR2_DAC2ER	0x00000000	/* Data Addr Cmp 2 Eff/Real */
+#define DBCR2_DAC2US	0x0C000000	/* Data Addr Cmp 2 Sup/User   */
+#define DBCR2_DAC2ER	0x03000000	/* Data Addr Cmp 2 Eff/Real */
 #define DBCR2_DAC12M	0x00800000	/* DAC 1-2 range enable */
 #define DBCR2_DAC12MM	0x00400000	/* DAC 1-2 Mask mode*/
 #define DBCR2_DAC12MX	0x00C00000	/* DAC 1-2 range eXclusive */
diff --git a/arch/powerpc/include/asm/reg_fsl_emb.h b/arch/powerpc/include/asm/reg_fsl_emb.h
index 0de404d..77bb71c 100644
--- a/arch/powerpc/include/asm/reg_fsl_emb.h
+++ b/arch/powerpc/include/asm/reg_fsl_emb.h
@@ -31,7 +31,7 @@
 #define PMLCA_FCM0	0x08000000	/* Freeze when PMM==0 */
 #define PMLCA_CE	0x04000000	/* Condition Enable */
 
-#define PMLCA_EVENT_MASK 0x007f0000	/* Event field */
+#define PMLCA_EVENT_MASK 0x00ff0000	/* Event field */
 #define PMLCA_EVENT_SHIFT	16
 
 #define PMRN_PMLCB0	0x110	/* PM Local Control B0 */
diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h
index eb8eb40..4084e56 100644
--- a/arch/powerpc/include/asm/syscalls.h
+++ b/arch/powerpc/include/asm/syscalls.h
@@ -7,7 +7,6 @@
 #include <linux/types.h>
 #include <asm/signal.h>
 
-struct new_utsname;
 struct pt_regs;
 struct rtas_args;
 struct sigaction;
@@ -35,12 +34,9 @@
 asmlinkage long sys_rt_sigaction(int sig,
 		const struct sigaction __user *act,
 		struct sigaction __user *oact, size_t sigsetsize);
-asmlinkage int sys_ipc(uint call, int first, unsigned long second,
-		long third, void __user *ptr, long fifth);
 asmlinkage long ppc64_personality(unsigned long personality);
 asmlinkage int ppc_rtas(struct rtas_args __user *uargs);
 asmlinkage time_t sys64_time(time_t __user * tloc);
-asmlinkage long ppc_newuname(struct new_utsname __user * name);
 
 asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset,
 		size_t sigsetsize);
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index 07d2d19..a5ee345 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -125,7 +125,7 @@
 SYS32ONLY(sigreturn)
 PPC_SYS(clone)
 COMPAT_SYS_SPU(setdomainname)
-PPC_SYS_SPU(newuname)
+SYSCALL_SPU(newuname)
 SYSCALL(ni_syscall)
 COMPAT_SYS_SPU(adjtimex)
 SYSCALL_SPU(mprotect)
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index f6ca761..f0a1026 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -364,6 +364,7 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
@@ -376,6 +377,7 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_UNAME
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index c002b04..8773263 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -98,11 +98,16 @@
 
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
-obj-$(CONFIG_PPC_PERF_CTRS)	+= perf_event.o perf_callchain.o
+obj-$(CONFIG_PERF_EVENTS)	+= perf_callchain.o
+
+obj-$(CONFIG_PPC_PERF_CTRS)	+= perf_event.o
 obj64-$(CONFIG_PPC_PERF_CTRS)	+= power4-pmu.o ppc970-pmu.o power5-pmu.o \
 				   power5+-pmu.o power6-pmu.o power7-pmu.o
 obj32-$(CONFIG_PPC_PERF_CTRS)	+= mpc7450-pmu.o
 
+obj-$(CONFIG_FSL_EMB_PERF_EVENT) += perf_event_fsl_emb.o
+obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o
+
 obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
 
 ifneq ($(CONFIG_PPC_INDIRECT_IO),y)
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index a6c2b63..957ceb7 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -194,6 +194,30 @@
 	DEFINE(PACA_KVM_IN_GUEST, offsetof(struct paca_struct, kvm_in_guest));
 	DEFINE(PACA_KVM_SLB, offsetof(struct paca_struct, kvm_slb));
 	DEFINE(PACA_KVM_SLB_MAX, offsetof(struct paca_struct, kvm_slb_max));
+	DEFINE(PACA_KVM_CR, offsetof(struct paca_struct, shadow_vcpu.cr));
+	DEFINE(PACA_KVM_XER, offsetof(struct paca_struct, shadow_vcpu.xer));
+	DEFINE(PACA_KVM_R0, offsetof(struct paca_struct, shadow_vcpu.gpr[0]));
+	DEFINE(PACA_KVM_R1, offsetof(struct paca_struct, shadow_vcpu.gpr[1]));
+	DEFINE(PACA_KVM_R2, offsetof(struct paca_struct, shadow_vcpu.gpr[2]));
+	DEFINE(PACA_KVM_R3, offsetof(struct paca_struct, shadow_vcpu.gpr[3]));
+	DEFINE(PACA_KVM_R4, offsetof(struct paca_struct, shadow_vcpu.gpr[4]));
+	DEFINE(PACA_KVM_R5, offsetof(struct paca_struct, shadow_vcpu.gpr[5]));
+	DEFINE(PACA_KVM_R6, offsetof(struct paca_struct, shadow_vcpu.gpr[6]));
+	DEFINE(PACA_KVM_R7, offsetof(struct paca_struct, shadow_vcpu.gpr[7]));
+	DEFINE(PACA_KVM_R8, offsetof(struct paca_struct, shadow_vcpu.gpr[8]));
+	DEFINE(PACA_KVM_R9, offsetof(struct paca_struct, shadow_vcpu.gpr[9]));
+	DEFINE(PACA_KVM_R10, offsetof(struct paca_struct, shadow_vcpu.gpr[10]));
+	DEFINE(PACA_KVM_R11, offsetof(struct paca_struct, shadow_vcpu.gpr[11]));
+	DEFINE(PACA_KVM_R12, offsetof(struct paca_struct, shadow_vcpu.gpr[12]));
+	DEFINE(PACA_KVM_R13, offsetof(struct paca_struct, shadow_vcpu.gpr[13]));
+	DEFINE(PACA_KVM_HOST_R1, offsetof(struct paca_struct, shadow_vcpu.host_r1));
+	DEFINE(PACA_KVM_HOST_R2, offsetof(struct paca_struct, shadow_vcpu.host_r2));
+	DEFINE(PACA_KVM_VMHANDLER, offsetof(struct paca_struct,
+					    shadow_vcpu.vmhandler));
+	DEFINE(PACA_KVM_SCRATCH0, offsetof(struct paca_struct,
+					   shadow_vcpu.scratch0));
+	DEFINE(PACA_KVM_SCRATCH1, offsetof(struct paca_struct,
+					   shadow_vcpu.scratch1));
 #endif
 #endif /* CONFIG_PPC64 */
 
@@ -389,8 +413,6 @@
 	DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
 	DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
 	DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
-	DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
-	DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
 	DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
 	DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
 	DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr));
@@ -411,11 +433,16 @@
 	DEFINE(VCPU_HOST_R2, offsetof(struct kvm_vcpu, arch.host_r2));
 	DEFINE(VCPU_HOST_MSR, offsetof(struct kvm_vcpu, arch.host_msr));
 	DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
+	DEFINE(VCPU_SHADOW_SRR1, offsetof(struct kvm_vcpu, arch.shadow_srr1));
 	DEFINE(VCPU_TRAMPOLINE_LOWMEM, offsetof(struct kvm_vcpu, arch.trampoline_lowmem));
 	DEFINE(VCPU_TRAMPOLINE_ENTER, offsetof(struct kvm_vcpu, arch.trampoline_enter));
 	DEFINE(VCPU_HIGHMEM_HANDLER, offsetof(struct kvm_vcpu, arch.highmem_handler));
+	DEFINE(VCPU_RMCALL, offsetof(struct kvm_vcpu, arch.rmcall));
 	DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags));
-#endif
+#else
+	DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
+	DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
+#endif /* CONFIG_PPC64 */
 #endif
 #ifdef CONFIG_44x
 	DEFINE(PGD_T_LOG2, PGD_T_LOG2);
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c
index bb37b1d..01fe9ce 100644
--- a/arch/powerpc/kernel/cacheinfo.c
+++ b/arch/powerpc/kernel/cacheinfo.c
@@ -642,7 +642,7 @@
 	&cache_assoc_attr,
 };
 
-static struct sysfs_ops cache_index_ops = {
+static const struct sysfs_ops cache_index_ops = {
 	.show = cache_index_show,
 };
 
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 2fc82ba..8af4949 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1808,7 +1808,7 @@
 		.icache_bsize		= 64,
 		.dcache_bsize		= 64,
 		.num_pmcs		= 4,
-		.oprofile_cpu_type	= "ppc/e500", /* xxx - galak, e500mc? */
+		.oprofile_cpu_type	= "ppc/e500mc",
 		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
 		.cpu_setup		= __setup_cpu_e500mc,
 		.machine_check		= machine_check_e500,
diff --git a/arch/powerpc/kernel/e500-pmu.c b/arch/powerpc/kernel/e500-pmu.c
new file mode 100644
index 0000000..7c07de0
--- /dev/null
+++ b/arch/powerpc/kernel/e500-pmu.c
@@ -0,0 +1,129 @@
+/*
+ * Performance counter support for e500 family processors.
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ * Copyright 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.
+ */
+#include <linux/string.h>
+#include <linux/perf_event.h>
+#include <asm/reg.h>
+#include <asm/cputable.h>
+
+/*
+ * Map of generic hardware event types to hardware events
+ * Zero if unsupported
+ */
+static int e500_generic_events[] = {
+	[PERF_COUNT_HW_CPU_CYCLES] = 1,
+	[PERF_COUNT_HW_INSTRUCTIONS] = 2,
+	[PERF_COUNT_HW_CACHE_MISSES] = 41, /* Data L1 cache reloads */
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 12,
+	[PERF_COUNT_HW_BRANCH_MISSES] = 15,
+};
+
+#define C(x)	PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static int e500_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+	/*
+	 * D-cache misses are not split into read/write/prefetch;
+	 * use raw event 41.
+	 */
+	[C(L1D)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	27,		0	},
+		[C(OP_WRITE)] = {	28,		0	},
+		[C(OP_PREFETCH)] = {	29,		0	},
+	},
+	[C(L1I)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	2,		60	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	0,		0	},
+	},
+	/*
+	 * Assuming LL means L2, it's not a good match for this model.
+	 * It allocates only on L1 castout or explicit prefetch, and
+	 * does not have separate read/write events (but it does have
+	 * separate instruction/data events).
+	 */
+	[C(LL)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	0,		0	},
+		[C(OP_WRITE)] = {	0,		0	},
+		[C(OP_PREFETCH)] = {	0,		0	},
+	},
+	/*
+	 * There are data/instruction MMU misses, but that's a miss on
+	 * the chip's internal level-one TLB which is probably not
+	 * what the user wants.  Instead, unified level-two TLB misses
+	 * are reported here.
+	 */
+	[C(DTLB)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	26,		66	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+	[C(BPU)] = {		/* 	RESULT_ACCESS	RESULT_MISS */
+		[C(OP_READ)] = {	12,		15 	},
+		[C(OP_WRITE)] = {	-1,		-1	},
+		[C(OP_PREFETCH)] = {	-1,		-1	},
+	},
+};
+
+static int num_events = 128;
+
+/* Upper half of event id is PMLCb, for threshold events */
+static u64 e500_xlate_event(u64 event_id)
+{
+	u32 event_low = (u32)event_id;
+	u64 ret;
+
+	if (event_low >= num_events)
+		return 0;
+
+	ret = FSL_EMB_EVENT_VALID;
+
+	if (event_low >= 76 && event_low <= 81) {
+		ret |= FSL_EMB_EVENT_RESTRICTED;
+		ret |= event_id &
+		       (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH);
+	} else if (event_id &
+	           (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH)) {
+		/* Threshold requested on non-threshold event */
+		return 0;
+	}
+
+	return ret;
+}
+
+static struct fsl_emb_pmu e500_pmu = {
+	.name			= "e500 family",
+	.n_counter		= 4,
+	.n_restricted		= 2,
+	.xlate_event		= e500_xlate_event,
+	.n_generic		= ARRAY_SIZE(e500_generic_events),
+	.generic_events		= e500_generic_events,
+	.cache_events		= &e500_cache_events,
+};
+
+static int init_e500_pmu(void)
+{
+	if (!cur_cpu_spec->oprofile_cpu_type)
+		return -ENODEV;
+
+	if (!strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/e500mc"))
+		num_events = 256;
+	else if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/e500"))
+		return -ENODEV;
+
+	return register_fsl_emb_pmu(&e500_pmu);
+}
+
+arch_initcall(init_e500_pmu);
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 9258074..bed9a29 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -219,7 +219,8 @@
 	 * physical cpu id in r24, we need to search the pacas to find
 	 * which logical id maps to our physical one.
 	 */
-	LOAD_REG_ADDR(r13, paca)	/* Get base vaddr of paca array	 */
+	LOAD_REG_ADDR(r13, paca)	/* Load paca pointer		 */
+	ld	r13,0(r13)		/* Get base vaddr of paca array	 */
 	li	r5,0			/* logical cpu id                */
 1:	lhz	r6,PACAHWCPUID(r13)	/* Load HW procid from paca      */
 	cmpw	r6,r24			/* Compare to our id             */
@@ -536,7 +537,8 @@
 	mtmsrd	r3			/* RI on */
 
 	/* Set up a paca value for this processor. */
-	LOAD_REG_ADDR(r4,paca)		/* Get base vaddr of paca array	*/
+	LOAD_REG_ADDR(r4,paca)		/* Load paca pointer		*/
+	ld	r4,0(r4)		/* Get base vaddr of paca array	*/
 	mulli	r13,r24,PACA_SIZE	/* Calculate vaddr of right paca */
 	add	r13,r13,r4		/* for this processor.		*/
 	mtspr	SPRN_SPRG_PACA,r13	/* Save vaddr of paca in an SPRG*/
@@ -615,6 +617,17 @@
 	std	r3,0(r1)		/* Zero the stack frame pointer	*/
 	bl	.start_secondary
 	b	.
+/*
+ * Reset stack pointer and call start_secondary
+ * to continue with online operation when woken up
+ * from cede in cpu offline.
+ */
+_GLOBAL(start_secondary_resume)
+	ld	r1,PACAKSAVE(r13)	/* Reload kernel stack pointer */
+	li	r3,0
+	std	r3,0(r1)		/* Zero the stack frame pointer	*/
+	bl	.start_secondary
+	b	.
 #endif
 
 /*
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 9ddfaef..035ada5 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -469,7 +469,7 @@
 		return -ENODEV;
 
 	/*
-	 * Before we register the platfrom serial devices, we need
+	 * Before we register the platform serial devices, we need
 	 * to fixup their interrupts and their IO ports.
 	 */
 	DBG("Fixing serial ports interrupts and IO ports ...\n");
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index d16b1ea..0c40c6f 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -9,11 +9,15 @@
 
 #include <linux/threads.h>
 #include <linux/module.h>
+#include <linux/lmb.h>
 
+#include <asm/firmware.h>
 #include <asm/lppaca.h>
 #include <asm/paca.h>
 #include <asm/sections.h>
 #include <asm/pgtable.h>
+#include <asm/iseries/lpar_map.h>
+#include <asm/iseries/hv_types.h>
 
 /* This symbol is provided by the linker - let it fill in the paca
  * field correctly */
@@ -70,37 +74,82 @@
  * processors.  The processor VPD array needs one entry per physical
  * processor (not thread).
  */
-struct paca_struct paca[NR_CPUS];
+struct paca_struct *paca;
 EXPORT_SYMBOL(paca);
 
-void __init initialise_pacas(void)
-{
-	int cpu;
+struct paca_struct boot_paca;
 
-	/* The TOC register (GPR2) points 32kB into the TOC, so that 64kB
-	 * of the TOC can be addressed using a single machine instruction.
-	 */
+void __init initialise_paca(struct paca_struct *new_paca, int cpu)
+{
+       /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB
+	* of the TOC can be addressed using a single machine instruction.
+	*/
 	unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL;
 
-	/* Can't use for_each_*_cpu, as they aren't functional yet */
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
-		struct paca_struct *new_paca = &paca[cpu];
-
 #ifdef CONFIG_PPC_BOOK3S
-		new_paca->lppaca_ptr = &lppaca[cpu];
+	new_paca->lppaca_ptr = &lppaca[cpu];
 #else
-		new_paca->kernel_pgd = swapper_pg_dir;
+	new_paca->kernel_pgd = swapper_pg_dir;
 #endif
-		new_paca->lock_token = 0x8000;
-		new_paca->paca_index = cpu;
-		new_paca->kernel_toc = kernel_toc;
-		new_paca->kernelbase = (unsigned long) _stext;
-		new_paca->kernel_msr = MSR_KERNEL;
-		new_paca->hw_cpu_id = 0xffff;
-		new_paca->__current = &init_task;
+	new_paca->lock_token = 0x8000;
+	new_paca->paca_index = cpu;
+	new_paca->kernel_toc = kernel_toc;
+	new_paca->kernelbase = (unsigned long) _stext;
+	new_paca->kernel_msr = MSR_KERNEL;
+	new_paca->hw_cpu_id = 0xffff;
+	new_paca->__current = &init_task;
 #ifdef CONFIG_PPC_STD_MMU_64
-		new_paca->slb_shadow_ptr = &slb_shadow[cpu];
+	new_paca->slb_shadow_ptr = &slb_shadow[cpu];
 #endif /* CONFIG_PPC_STD_MMU_64 */
+}
 
-	}
+static int __initdata paca_size;
+
+void __init allocate_pacas(void)
+{
+	int nr_cpus, cpu, limit;
+
+	/*
+	 * We can't take SLB misses on the paca, and we want to access them
+	 * in real mode, so allocate them within the RMA and also within
+	 * the first segment. On iSeries they must be within the area mapped
+	 * by the HV, which is HvPagesToMap * HVPAGESIZE bytes.
+	 */
+	limit = min(0x10000000ULL, lmb.rmo_size);
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		limit = min(limit, HvPagesToMap * HVPAGESIZE);
+
+	nr_cpus = NR_CPUS;
+	/* On iSeries we know we can never have more than 64 cpus */
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		nr_cpus = min(64, nr_cpus);
+
+	paca_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpus);
+
+	paca = __va(lmb_alloc_base(paca_size, PAGE_SIZE, limit));
+	memset(paca, 0, paca_size);
+
+	printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n",
+		paca_size, nr_cpus, paca);
+
+	/* Can't use for_each_*_cpu, as they aren't functional yet */
+	for (cpu = 0; cpu < nr_cpus; cpu++)
+		initialise_paca(&paca[cpu], cpu);
+}
+
+void __init free_unused_pacas(void)
+{
+	int new_size;
+
+	new_size = PAGE_ALIGN(sizeof(struct paca_struct) * num_possible_cpus());
+
+	if (new_size >= paca_size)
+		return;
+
+	lmb_free(__pa(paca) + new_size, paca_size - new_size);
+
+	printk(KERN_DEBUG "Freed %u bytes for unused pacas\n",
+		paca_size - new_size);
+
+	paca_size = new_size;
 }
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 2597f95..f3c42ce5 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -63,21 +63,6 @@
 }
 EXPORT_SYMBOL(get_pci_dma_ops);
 
-int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	return dma_set_mask(&dev->dev, mask);
-}
-
-int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	int rc;
-
-	rc = dma_set_mask(&dev->dev, mask);
-	dev->dev.coherent_dma_mask = dev->dma_mask;
-
-	return rc;
-}
-
 struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
 {
 	struct pci_controller *phb;
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index b6cf8f1..5120bd4 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -1164,10 +1164,10 @@
 	 * Finally record data if requested.
 	 */
 	if (record) {
-		struct perf_sample_data data = {
-			.addr	= ~0ULL,
-			.period	= event->hw.last_period,
-		};
+		struct perf_sample_data data;
+
+		perf_sample_data_init(&data, ~0ULL);
+		data.period = event->hw.last_period;
 
 		if (event->attr.sample_type & PERF_SAMPLE_ADDR)
 			perf_get_data_addr(regs, &data.addr);
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c
new file mode 100644
index 0000000..369872f
--- /dev/null
+++ b/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -0,0 +1,654 @@
+/*
+ * Performance event support - Freescale Embedded Performance Monitor
+ *
+ * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
+ * Copyright 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.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/perf_event.h>
+#include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <asm/reg_fsl_emb.h>
+#include <asm/pmc.h>
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+#include <asm/ptrace.h>
+
+struct cpu_hw_events {
+	int n_events;
+	int disabled;
+	u8  pmcs_enabled;
+	struct perf_event *event[MAX_HWEVENTS];
+};
+static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+
+static struct fsl_emb_pmu *ppmu;
+
+/* Number of perf_events counting hardware events */
+static atomic_t num_events;
+/* Used to avoid races in calling reserve/release_pmc_hardware */
+static DEFINE_MUTEX(pmc_reserve_mutex);
+
+/*
+ * If interrupts were soft-disabled when a PMU interrupt occurs, treat
+ * it as an NMI.
+ */
+static inline int perf_intr_is_nmi(struct pt_regs *regs)
+{
+#ifdef __powerpc64__
+	return !regs->softe;
+#else
+	return 0;
+#endif
+}
+
+static void perf_event_interrupt(struct pt_regs *regs);
+
+/*
+ * Read one performance monitor counter (PMC).
+ */
+static unsigned long read_pmc(int idx)
+{
+	unsigned long val;
+
+	switch (idx) {
+	case 0:
+		val = mfpmr(PMRN_PMC0);
+		break;
+	case 1:
+		val = mfpmr(PMRN_PMC1);
+		break;
+	case 2:
+		val = mfpmr(PMRN_PMC2);
+		break;
+	case 3:
+		val = mfpmr(PMRN_PMC3);
+		break;
+	default:
+		printk(KERN_ERR "oops trying to read PMC%d\n", idx);
+		val = 0;
+	}
+	return val;
+}
+
+/*
+ * Write one PMC.
+ */
+static void write_pmc(int idx, unsigned long val)
+{
+	switch (idx) {
+	case 0:
+		mtpmr(PMRN_PMC0, val);
+		break;
+	case 1:
+		mtpmr(PMRN_PMC1, val);
+		break;
+	case 2:
+		mtpmr(PMRN_PMC2, val);
+		break;
+	case 3:
+		mtpmr(PMRN_PMC3, val);
+		break;
+	default:
+		printk(KERN_ERR "oops trying to write PMC%d\n", idx);
+	}
+
+	isync();
+}
+
+/*
+ * Write one local control A register
+ */
+static void write_pmlca(int idx, unsigned long val)
+{
+	switch (idx) {
+	case 0:
+		mtpmr(PMRN_PMLCA0, val);
+		break;
+	case 1:
+		mtpmr(PMRN_PMLCA1, val);
+		break;
+	case 2:
+		mtpmr(PMRN_PMLCA2, val);
+		break;
+	case 3:
+		mtpmr(PMRN_PMLCA3, val);
+		break;
+	default:
+		printk(KERN_ERR "oops trying to write PMLCA%d\n", idx);
+	}
+
+	isync();
+}
+
+/*
+ * Write one local control B register
+ */
+static void write_pmlcb(int idx, unsigned long val)
+{
+	switch (idx) {
+	case 0:
+		mtpmr(PMRN_PMLCB0, val);
+		break;
+	case 1:
+		mtpmr(PMRN_PMLCB1, val);
+		break;
+	case 2:
+		mtpmr(PMRN_PMLCB2, val);
+		break;
+	case 3:
+		mtpmr(PMRN_PMLCB3, val);
+		break;
+	default:
+		printk(KERN_ERR "oops trying to write PMLCB%d\n", idx);
+	}
+
+	isync();
+}
+
+static void fsl_emb_pmu_read(struct perf_event *event)
+{
+	s64 val, delta, prev;
+
+	/*
+	 * Performance monitor interrupts come even when interrupts
+	 * are soft-disabled, as long as interrupts are hard-enabled.
+	 * Therefore we treat them like NMIs.
+	 */
+	do {
+		prev = atomic64_read(&event->hw.prev_count);
+		barrier();
+		val = read_pmc(event->hw.idx);
+	} while (atomic64_cmpxchg(&event->hw.prev_count, prev, val) != prev);
+
+	/* The counters are only 32 bits wide */
+	delta = (val - prev) & 0xfffffffful;
+	atomic64_add(delta, &event->count);
+	atomic64_sub(delta, &event->hw.period_left);
+}
+
+/*
+ * Disable all events to prevent PMU interrupts and to allow
+ * events to be added or removed.
+ */
+void hw_perf_disable(void)
+{
+	struct cpu_hw_events *cpuhw;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	cpuhw = &__get_cpu_var(cpu_hw_events);
+
+	if (!cpuhw->disabled) {
+		cpuhw->disabled = 1;
+
+		/*
+		 * Check if we ever enabled the PMU on this cpu.
+		 */
+		if (!cpuhw->pmcs_enabled) {
+			ppc_enable_pmcs();
+			cpuhw->pmcs_enabled = 1;
+		}
+
+		if (atomic_read(&num_events)) {
+			/*
+			 * Set the 'freeze all counters' bit, and disable
+			 * interrupts.  The barrier is to make sure the
+			 * mtpmr has been executed and the PMU has frozen
+			 * the events before we return.
+			 */
+
+			mtpmr(PMRN_PMGC0, PMGC0_FAC);
+			isync();
+		}
+	}
+	local_irq_restore(flags);
+}
+
+/*
+ * Re-enable all events if disable == 0.
+ * If we were previously disabled and events were added, then
+ * put the new config on the PMU.
+ */
+void hw_perf_enable(void)
+{
+	struct cpu_hw_events *cpuhw;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	cpuhw = &__get_cpu_var(cpu_hw_events);
+	if (!cpuhw->disabled)
+		goto out;
+
+	cpuhw->disabled = 0;
+	ppc_set_pmu_inuse(cpuhw->n_events != 0);
+
+	if (cpuhw->n_events > 0) {
+		mtpmr(PMRN_PMGC0, PMGC0_PMIE | PMGC0_FCECE);
+		isync();
+	}
+
+ out:
+	local_irq_restore(flags);
+}
+
+static int collect_events(struct perf_event *group, int max_count,
+			  struct perf_event *ctrs[])
+{
+	int n = 0;
+	struct perf_event *event;
+
+	if (!is_software_event(group)) {
+		if (n >= max_count)
+			return -1;
+		ctrs[n] = group;
+		n++;
+	}
+	list_for_each_entry(event, &group->sibling_list, group_entry) {
+		if (!is_software_event(event) &&
+		    event->state != PERF_EVENT_STATE_OFF) {
+			if (n >= max_count)
+				return -1;
+			ctrs[n] = event;
+			n++;
+		}
+	}
+	return n;
+}
+
+/* perf must be disabled, context locked on entry */
+static int fsl_emb_pmu_enable(struct perf_event *event)
+{
+	struct cpu_hw_events *cpuhw;
+	int ret = -EAGAIN;
+	int num_counters = ppmu->n_counter;
+	u64 val;
+	int i;
+
+	cpuhw = &get_cpu_var(cpu_hw_events);
+
+	if (event->hw.config & FSL_EMB_EVENT_RESTRICTED)
+		num_counters = ppmu->n_restricted;
+
+	/*
+	 * Allocate counters from top-down, so that restricted-capable
+	 * counters are kept free as long as possible.
+	 */
+	for (i = num_counters - 1; i >= 0; i--) {
+		if (cpuhw->event[i])
+			continue;
+
+		break;
+	}
+
+	if (i < 0)
+		goto out;
+
+	event->hw.idx = i;
+	cpuhw->event[i] = event;
+	++cpuhw->n_events;
+
+	val = 0;
+	if (event->hw.sample_period) {
+		s64 left = atomic64_read(&event->hw.period_left);
+		if (left < 0x80000000L)
+			val = 0x80000000L - left;
+	}
+	atomic64_set(&event->hw.prev_count, val);
+	write_pmc(i, val);
+	perf_event_update_userpage(event);
+
+	write_pmlcb(i, event->hw.config >> 32);
+	write_pmlca(i, event->hw.config_base);
+
+	ret = 0;
+ out:
+	put_cpu_var(cpu_hw_events);
+	return ret;
+}
+
+/* perf must be disabled, context locked on entry */
+static void fsl_emb_pmu_disable(struct perf_event *event)
+{
+	struct cpu_hw_events *cpuhw;
+	int i = event->hw.idx;
+
+	if (i < 0)
+		goto out;
+
+	fsl_emb_pmu_read(event);
+
+	cpuhw = &get_cpu_var(cpu_hw_events);
+
+	WARN_ON(event != cpuhw->event[event->hw.idx]);
+
+	write_pmlca(i, 0);
+	write_pmlcb(i, 0);
+	write_pmc(i, 0);
+
+	cpuhw->event[i] = NULL;
+	event->hw.idx = -1;
+
+	/*
+	 * TODO: if at least one restricted event exists, and we
+	 * just freed up a non-restricted-capable counter, and
+	 * there is a restricted-capable counter occupied by
+	 * a non-restricted event, migrate that event to the
+	 * vacated counter.
+	 */
+
+	cpuhw->n_events--;
+
+ out:
+	put_cpu_var(cpu_hw_events);
+}
+
+/*
+ * Re-enable interrupts on a event after they were throttled
+ * because they were coming too fast.
+ *
+ * Context is locked on entry, but perf is not disabled.
+ */
+static void fsl_emb_pmu_unthrottle(struct perf_event *event)
+{
+	s64 val, left;
+	unsigned long flags;
+
+	if (event->hw.idx < 0 || !event->hw.sample_period)
+		return;
+	local_irq_save(flags);
+	perf_disable();
+	fsl_emb_pmu_read(event);
+	left = event->hw.sample_period;
+	event->hw.last_period = left;
+	val = 0;
+	if (left < 0x80000000L)
+		val = 0x80000000L - left;
+	write_pmc(event->hw.idx, val);
+	atomic64_set(&event->hw.prev_count, val);
+	atomic64_set(&event->hw.period_left, left);
+	perf_event_update_userpage(event);
+	perf_enable();
+	local_irq_restore(flags);
+}
+
+static struct pmu fsl_emb_pmu = {
+	.enable		= fsl_emb_pmu_enable,
+	.disable	= fsl_emb_pmu_disable,
+	.read		= fsl_emb_pmu_read,
+	.unthrottle	= fsl_emb_pmu_unthrottle,
+};
+
+/*
+ * Release the PMU if this is the last perf_event.
+ */
+static void hw_perf_event_destroy(struct perf_event *event)
+{
+	if (!atomic_add_unless(&num_events, -1, 1)) {
+		mutex_lock(&pmc_reserve_mutex);
+		if (atomic_dec_return(&num_events) == 0)
+			release_pmc_hardware();
+		mutex_unlock(&pmc_reserve_mutex);
+	}
+}
+
+/*
+ * Translate a generic cache event_id config to a raw event_id code.
+ */
+static int hw_perf_cache_event(u64 config, u64 *eventp)
+{
+	unsigned long type, op, result;
+	int ev;
+
+	if (!ppmu->cache_events)
+		return -EINVAL;
+
+	/* unpack config */
+	type = config & 0xff;
+	op = (config >> 8) & 0xff;
+	result = (config >> 16) & 0xff;
+
+	if (type >= PERF_COUNT_HW_CACHE_MAX ||
+	    op >= PERF_COUNT_HW_CACHE_OP_MAX ||
+	    result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+		return -EINVAL;
+
+	ev = (*ppmu->cache_events)[type][op][result];
+	if (ev == 0)
+		return -EOPNOTSUPP;
+	if (ev == -1)
+		return -EINVAL;
+	*eventp = ev;
+	return 0;
+}
+
+const struct pmu *hw_perf_event_init(struct perf_event *event)
+{
+	u64 ev;
+	struct perf_event *events[MAX_HWEVENTS];
+	int n;
+	int err;
+	int num_restricted;
+	int i;
+
+	switch (event->attr.type) {
+	case PERF_TYPE_HARDWARE:
+		ev = event->attr.config;
+		if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0)
+			return ERR_PTR(-EOPNOTSUPP);
+		ev = ppmu->generic_events[ev];
+		break;
+
+	case PERF_TYPE_HW_CACHE:
+		err = hw_perf_cache_event(event->attr.config, &ev);
+		if (err)
+			return ERR_PTR(err);
+		break;
+
+	case PERF_TYPE_RAW:
+		ev = event->attr.config;
+		break;
+
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	event->hw.config = ppmu->xlate_event(ev);
+	if (!(event->hw.config & FSL_EMB_EVENT_VALID))
+		return ERR_PTR(-EINVAL);
+
+	/*
+	 * If this is in a group, check if it can go on with all the
+	 * other hardware events in the group.  We assume the event
+	 * hasn't been linked into its leader's sibling list at this point.
+	 */
+	n = 0;
+	if (event->group_leader != event) {
+		n = collect_events(event->group_leader,
+		                   ppmu->n_counter - 1, events);
+		if (n < 0)
+			return ERR_PTR(-EINVAL);
+	}
+
+	if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) {
+		num_restricted = 0;
+		for (i = 0; i < n; i++) {
+			if (events[i]->hw.config & FSL_EMB_EVENT_RESTRICTED)
+				num_restricted++;
+		}
+
+		if (num_restricted >= ppmu->n_restricted)
+			return ERR_PTR(-EINVAL);
+	}
+
+	event->hw.idx = -1;
+
+	event->hw.config_base = PMLCA_CE | PMLCA_FCM1 |
+	                        (u32)((ev << 16) & PMLCA_EVENT_MASK);
+
+	if (event->attr.exclude_user)
+		event->hw.config_base |= PMLCA_FCU;
+	if (event->attr.exclude_kernel)
+		event->hw.config_base |= PMLCA_FCS;
+	if (event->attr.exclude_idle)
+		return ERR_PTR(-ENOTSUPP);
+
+	event->hw.last_period = event->hw.sample_period;
+	atomic64_set(&event->hw.period_left, event->hw.last_period);
+
+	/*
+	 * See if we need to reserve the PMU.
+	 * If no events are currently in use, then we have to take a
+	 * mutex to ensure that we don't race with another task doing
+	 * reserve_pmc_hardware or release_pmc_hardware.
+	 */
+	err = 0;
+	if (!atomic_inc_not_zero(&num_events)) {
+		mutex_lock(&pmc_reserve_mutex);
+		if (atomic_read(&num_events) == 0 &&
+		    reserve_pmc_hardware(perf_event_interrupt))
+			err = -EBUSY;
+		else
+			atomic_inc(&num_events);
+		mutex_unlock(&pmc_reserve_mutex);
+
+		mtpmr(PMRN_PMGC0, PMGC0_FAC);
+		isync();
+	}
+	event->destroy = hw_perf_event_destroy;
+
+	if (err)
+		return ERR_PTR(err);
+	return &fsl_emb_pmu;
+}
+
+/*
+ * A counter has overflowed; update its count and record
+ * things if requested.  Note that interrupts are hard-disabled
+ * here so there is no possibility of being interrupted.
+ */
+static void record_and_restart(struct perf_event *event, unsigned long val,
+			       struct pt_regs *regs, int nmi)
+{
+	u64 period = event->hw.sample_period;
+	s64 prev, delta, left;
+	int record = 0;
+
+	/* we don't have to worry about interrupts here */
+	prev = atomic64_read(&event->hw.prev_count);
+	delta = (val - prev) & 0xfffffffful;
+	atomic64_add(delta, &event->count);
+
+	/*
+	 * See if the total period for this event has expired,
+	 * and update for the next period.
+	 */
+	val = 0;
+	left = atomic64_read(&event->hw.period_left) - delta;
+	if (period) {
+		if (left <= 0) {
+			left += period;
+			if (left <= 0)
+				left = period;
+			record = 1;
+		}
+		if (left < 0x80000000LL)
+			val = 0x80000000LL - left;
+	}
+
+	/*
+	 * Finally record data if requested.
+	 */
+	if (record) {
+		struct perf_sample_data data = {
+			.period	= event->hw.last_period,
+		};
+
+		if (perf_event_overflow(event, nmi, &data, regs)) {
+			/*
+			 * Interrupts are coming too fast - throttle them
+			 * by setting the event to 0, so it will be
+			 * at least 2^30 cycles until the next interrupt
+			 * (assuming each event counts at most 2 counts
+			 * per cycle).
+			 */
+			val = 0;
+			left = ~0ULL >> 1;
+		}
+	}
+
+	write_pmc(event->hw.idx, val);
+	atomic64_set(&event->hw.prev_count, val);
+	atomic64_set(&event->hw.period_left, left);
+	perf_event_update_userpage(event);
+}
+
+static void perf_event_interrupt(struct pt_regs *regs)
+{
+	int i;
+	struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+	struct perf_event *event;
+	unsigned long val;
+	int found = 0;
+	int nmi;
+
+	nmi = perf_intr_is_nmi(regs);
+	if (nmi)
+		nmi_enter();
+	else
+		irq_enter();
+
+	for (i = 0; i < ppmu->n_counter; ++i) {
+		event = cpuhw->event[i];
+
+		val = read_pmc(i);
+		if ((int)val < 0) {
+			if (event) {
+				/* event has overflowed */
+				found = 1;
+				record_and_restart(event, val, regs, nmi);
+			} else {
+				/*
+				 * Disabled counter is negative,
+				 * reset it just in case.
+				 */
+				write_pmc(i, 0);
+			}
+		}
+	}
+
+	/* PMM will keep counters frozen until we return from the interrupt. */
+	mtmsr(mfmsr() | MSR_PMM);
+	mtpmr(PMRN_PMGC0, PMGC0_PMIE | PMGC0_FCECE);
+	isync();
+
+	if (nmi)
+		nmi_exit();
+	else
+		irq_exit();
+}
+
+void hw_perf_event_setup(int cpu)
+{
+	struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu);
+
+	memset(cpuhw, 0, sizeof(*cpuhw));
+}
+
+int register_fsl_emb_pmu(struct fsl_emb_pmu *pmu)
+{
+	if (ppmu)
+		return -EBUSY;		/* something's already registered */
+
+	ppmu = pmu;
+	pr_info("%s performance monitor hardware support registered\n",
+		pmu->name);
+
+	return 0;
+}
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 42545145..ab3e392 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -107,6 +107,7 @@
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_VSX
 EXPORT_SYMBOL(giveup_vsx);
+EXPORT_SYMBOL_GPL(__giveup_vsx);
 #endif /* CONFIG_VSX */
 #ifdef CONFIG_SPE
 EXPORT_SYMBOL(giveup_spe);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 43238b2..05131d6 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -43,6 +43,7 @@
 #include <asm/smp.h>
 #include <asm/system.h>
 #include <asm/mmu.h>
+#include <asm/paca.h>
 #include <asm/pgtable.h>
 #include <asm/pci.h>
 #include <asm/iommu.h>
@@ -721,6 +722,8 @@
 	 * FIXME .. and the initrd too? */
 	move_device_tree();
 
+	allocate_pacas();
+
 	DBG("Scanning CPUs ...\n");
 
 	/* Retreive CPU related informations from the flat tree
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index d9b0586..ed2cfe1 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -940,7 +940,7 @@
 {
 	switch (slot) {
 	case 1:
-		if (child->thread.iac1 == 0)
+		if ((child->thread.dbcr0 & DBCR0_IAC1) == 0)
 			return -ENOENT;
 
 		if (dbcr_iac_range(child) & DBCR_IAC12MODE) {
@@ -952,7 +952,7 @@
 		child->thread.dbcr0 &= ~DBCR0_IAC1;
 		break;
 	case 2:
-		if (child->thread.iac2 == 0)
+		if ((child->thread.dbcr0 & DBCR0_IAC2) == 0)
 			return -ENOENT;
 
 		if (dbcr_iac_range(child) & DBCR_IAC12MODE)
@@ -963,7 +963,7 @@
 		break;
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
 	case 3:
-		if (child->thread.iac3 == 0)
+		if ((child->thread.dbcr0 & DBCR0_IAC3) == 0)
 			return -ENOENT;
 
 		if (dbcr_iac_range(child) & DBCR_IAC34MODE) {
@@ -975,7 +975,7 @@
 		child->thread.dbcr0 &= ~DBCR0_IAC3;
 		break;
 	case 4:
-		if (child->thread.iac4 == 0)
+		if ((child->thread.dbcr0 & DBCR0_IAC4) == 0)
 			return -ENOENT;
 
 		if (dbcr_iac_range(child) & DBCR_IAC34MODE)
@@ -1054,7 +1054,7 @@
 static int del_dac(struct task_struct *child, int slot)
 {
 	if (slot == 1) {
-		if (child->thread.dac1 == 0)
+		if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0)
 			return -ENOENT;
 
 		child->thread.dac1 = 0;
@@ -1070,7 +1070,7 @@
 		child->thread.dvc1 = 0;
 #endif
 	} else if (slot == 2) {
-		if (child->thread.dac1 == 0)
+		if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0)
 			return -ENOENT;
 
 #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 03dd6a2..48f0a00 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -36,6 +36,7 @@
 #include <linux/lmb.h>
 #include <linux/of_platform.h>
 #include <asm/io.h>
+#include <asm/paca.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
 #include <asm/vdso_datapage.h>
@@ -493,6 +494,8 @@
 	 * here will have to be reworked
 	 */
 	cpu_init_thread_core_maps(nthreads);
+
+	free_unused_pacas();
 }
 #endif /* CONFIG_SMP */
 
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 6568406..6354739 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -144,9 +144,9 @@
 #endif /* CONFIG_SMP */
 
 /* Put the paca pointer into r13 and SPRG_PACA */
-void __init setup_paca(int cpu)
+static void __init setup_paca(struct paca_struct *new_paca)
 {
-	local_paca = &paca[cpu];
+	local_paca = new_paca;
 	mtspr(SPRN_SPRG_PACA, local_paca);
 #ifdef CONFIG_PPC_BOOK3E
 	mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb);
@@ -176,14 +176,12 @@
 {
 	/* -------- printk is _NOT_ safe to use here ! ------- */
 
-	/* Fill in any unititialised pacas */
-	initialise_pacas();
-
 	/* Identify CPU type */
 	identify_cpu(0, mfspr(SPRN_PVR));
 
 	/* Assume we're on cpu 0 for now. Don't write to the paca yet! */
-	setup_paca(0);
+	initialise_paca(&boot_paca, 0);
+	setup_paca(&boot_paca);
 
 	/* Initialize lockdep early or else spinlocks will blow */
 	lockdep_init();
@@ -203,7 +201,7 @@
 	early_init_devtree(__va(dt_ptr));
 
 	/* Now we know the logical id of our boot cpu, setup the paca. */
-	setup_paca(boot_cpuid);
+	setup_paca(&paca[boot_cpuid]);
 
 	/* Fix up paca fields required for the boot cpu */
 	get_paca()->cpu_start = 1;
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index 3370e62..f2496f2 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -42,100 +42,6 @@
 #include <asm/time.h>
 #include <asm/unistd.h>
 
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-int sys_ipc(uint call, int first, unsigned long second, long third,
-	    void __user *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	ret = -ENOSYS;
-	switch (call) {
-	case SEMOP:
-		ret = sys_semtimedop(first, (struct sembuf __user *)ptr,
-				      (unsigned)second, NULL);
-		break;
-	case SEMTIMEDOP:
-		ret = sys_semtimedop(first, (struct sembuf __user *)ptr,
-				      (unsigned)second,
-				      (const struct timespec __user *) fifth);
-		break;
-	case SEMGET:
-		ret = sys_semget (first, (int)second, third);
-		break;
-	case SEMCTL: {
-		union semun fourth;
-
-		ret = -EINVAL;
-		if (!ptr)
-			break;
-		if ((ret = get_user(fourth.__pad, (void __user * __user *)ptr)))
-			break;
-		ret = sys_semctl(first, (int)second, third, fourth);
-		break;
-	}
-	case MSGSND:
-		ret = sys_msgsnd(first, (struct msgbuf __user *)ptr,
-				 (size_t)second, third);
-		break;
-	case MSGRCV:
-		switch (version) {
-		case 0: {
-			struct ipc_kludge tmp;
-
-			ret = -EINVAL;
-			if (!ptr)
-				break;
-			if ((ret = copy_from_user(&tmp,
-						(struct ipc_kludge __user *) ptr,
-						sizeof (tmp)) ? -EFAULT : 0))
-				break;
-			ret = sys_msgrcv(first, tmp.msgp, (size_t) second,
-					  tmp.msgtyp, third);
-			break;
-		}
-		default:
-			ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
-					  (size_t)second, fifth, third);
-			break;
-		}
-		break;
-	case MSGGET:
-		ret = sys_msgget((key_t)first, (int)second);
-		break;
-	case MSGCTL:
-		ret = sys_msgctl(first, (int)second,
-				  (struct msqid_ds __user *)ptr);
-		break;
-	case SHMAT: {
-		ulong raddr;
-		ret = do_shmat(first, (char __user *)ptr, (int)second, &raddr);
-		if (ret)
-			break;
-		ret = put_user(raddr, (ulong __user *) third);
-		break;
-	}
-	case SHMDT:
-		ret = sys_shmdt((char __user *)ptr);
-		break;
-	case SHMGET:
-		ret = sys_shmget(first, (size_t)second, third);
-		break;
-	case SHMCTL:
-		ret = sys_shmctl(first, (int)second,
-				 (struct shmid_ds __user *)ptr);
-		break;
-	}
-
-	return ret;
-}
-
 static inline unsigned long do_mmap2(unsigned long addr, size_t len,
 			unsigned long prot, unsigned long flags,
 			unsigned long fd, unsigned long off, int shift)
@@ -210,76 +116,6 @@
 }
 #endif
 
-#ifdef CONFIG_PPC64
-#define OVERRIDE_MACHINE    (personality(current->personality) == PER_LINUX32)
-#else
-#define OVERRIDE_MACHINE    0
-#endif
-
-static inline int override_machine(char __user *mach)
-{
-	if (OVERRIDE_MACHINE) {
-		/* change ppc64 to ppc */
-		if (__put_user(0, mach+3) || __put_user(0, mach+4))
-			return -EFAULT;
-	}
-	return 0;
-}
-
-long ppc_newuname(struct new_utsname __user * name)
-{
-	int err = 0;
-
-	down_read(&uts_sem);
-	if (copy_to_user(name, utsname(), sizeof(*name)))
-		err = -EFAULT;
-	up_read(&uts_sem);
-	if (!err)
-		err = override_machine(name->machine);
-	return err;
-}
-
-int sys_uname(struct old_utsname __user *name)
-{
-	int err = 0;
-	
-	down_read(&uts_sem);
-	if (copy_to_user(name, utsname(), sizeof(*name)))
-		err = -EFAULT;
-	up_read(&uts_sem);
-	if (!err)
-		err = override_machine(name->machine);
-	return err;
-}
-
-int sys_olduname(struct oldold_utsname __user *name)
-{
-	int error;
-
-	if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
-		return -EFAULT;
-  
-	down_read(&uts_sem);
-	error = __copy_to_user(&name->sysname, &utsname()->sysname,
-			       __OLD_UTS_LEN);
-	error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->nodename, &utsname()->nodename,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->release, &utsname()->release,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->release + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->version, &utsname()->version,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->version + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->machine, &utsname()->machine,
-				__OLD_UTS_LEN);
-	error |= override_machine(name->machine);
-	up_read(&uts_sem);
-
-	return error? -EFAULT: 0;
-}
-
 long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
 		      u32 len_high, u32 len_low)
 {
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c
index 61af58f..65ea083 100644
--- a/arch/powerpc/kvm/44x_emulate.c
+++ b/arch/powerpc/kvm/44x_emulate.c
@@ -65,13 +65,14 @@
 			 */
 			switch (dcrn) {
 			case DCRN_CPR0_CONFIG_ADDR:
-				vcpu->arch.gpr[rt] = vcpu->arch.cpr0_cfgaddr;
+				kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
 				break;
 			case DCRN_CPR0_CONFIG_DATA:
 				local_irq_disable();
 				mtdcr(DCRN_CPR0_CONFIG_ADDR,
 					  vcpu->arch.cpr0_cfgaddr);
-				vcpu->arch.gpr[rt] = mfdcr(DCRN_CPR0_CONFIG_DATA);
+				kvmppc_set_gpr(vcpu, rt,
+					       mfdcr(DCRN_CPR0_CONFIG_DATA));
 				local_irq_enable();
 				break;
 			default:
@@ -93,11 +94,11 @@
 			/* emulate some access in kernel */
 			switch (dcrn) {
 			case DCRN_CPR0_CONFIG_ADDR:
-				vcpu->arch.cpr0_cfgaddr = vcpu->arch.gpr[rs];
+				vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
 				break;
 			default:
 				run->dcr.dcrn = dcrn;
-				run->dcr.data = vcpu->arch.gpr[rs];
+				run->dcr.data = kvmppc_get_gpr(vcpu, rs);
 				run->dcr.is_write = 1;
 				vcpu->arch.dcr_needed = 1;
 				kvmppc_account_exit(vcpu, DCR_EXITS);
@@ -146,13 +147,13 @@
 
 	switch (sprn) {
 	case SPRN_PID:
-		kvmppc_set_pid(vcpu, vcpu->arch.gpr[rs]); break;
+		kvmppc_set_pid(vcpu, kvmppc_get_gpr(vcpu, rs)); break;
 	case SPRN_MMUCR:
-		vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.mmucr = kvmppc_get_gpr(vcpu, rs); break;
 	case SPRN_CCR0:
-		vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.ccr0 = kvmppc_get_gpr(vcpu, rs); break;
 	case SPRN_CCR1:
-		vcpu->arch.ccr1 = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.ccr1 = kvmppc_get_gpr(vcpu, rs); break;
 	default:
 		emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs);
 	}
@@ -167,13 +168,13 @@
 
 	switch (sprn) {
 	case SPRN_PID:
-		vcpu->arch.gpr[rt] = vcpu->arch.pid; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.pid); break;
 	case SPRN_MMUCR:
-		vcpu->arch.gpr[rt] = vcpu->arch.mmucr; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.mmucr); break;
 	case SPRN_CCR0:
-		vcpu->arch.gpr[rt] = vcpu->arch.ccr0; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ccr0); break;
 	case SPRN_CCR1:
-		vcpu->arch.gpr[rt] = vcpu->arch.ccr1; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ccr1); break;
 	default:
 		emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt);
 	}
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index ff3cb63..2570fcc 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -439,7 +439,7 @@
 	struct kvmppc_44x_tlbe *tlbe;
 	unsigned int gtlb_index;
 
-	gtlb_index = vcpu->arch.gpr[ra];
+	gtlb_index = kvmppc_get_gpr(vcpu, ra);
 	if (gtlb_index > KVM44x_GUEST_TLB_SIZE) {
 		printk("%s: index %d\n", __func__, gtlb_index);
 		kvmppc_dump_vcpu(vcpu);
@@ -455,15 +455,15 @@
 	switch (ws) {
 	case PPC44x_TLB_PAGEID:
 		tlbe->tid = get_mmucr_stid(vcpu);
-		tlbe->word0 = vcpu->arch.gpr[rs];
+		tlbe->word0 = kvmppc_get_gpr(vcpu, rs);
 		break;
 
 	case PPC44x_TLB_XLAT:
-		tlbe->word1 = vcpu->arch.gpr[rs];
+		tlbe->word1 = kvmppc_get_gpr(vcpu, rs);
 		break;
 
 	case PPC44x_TLB_ATTRIB:
-		tlbe->word2 = vcpu->arch.gpr[rs];
+		tlbe->word2 = kvmppc_get_gpr(vcpu, rs);
 		break;
 
 	default:
@@ -500,18 +500,20 @@
 	unsigned int as = get_mmucr_sts(vcpu);
 	unsigned int pid = get_mmucr_stid(vcpu);
 
-	ea = vcpu->arch.gpr[rb];
+	ea = kvmppc_get_gpr(vcpu, rb);
 	if (ra)
-		ea += vcpu->arch.gpr[ra];
+		ea += kvmppc_get_gpr(vcpu, ra);
 
 	gtlb_index = kvmppc_44x_tlb_index(vcpu, ea, pid, as);
 	if (rc) {
+		u32 cr = kvmppc_get_cr(vcpu);
+
 		if (gtlb_index < 0)
-			vcpu->arch.cr &= ~0x20000000;
+			kvmppc_set_cr(vcpu, cr & ~0x20000000);
 		else
-			vcpu->arch.cr |= 0x20000000;
+			kvmppc_set_cr(vcpu, cr | 0x20000000);
 	}
-	vcpu->arch.gpr[rt] = gtlb_index;
+	kvmppc_set_gpr(vcpu, rt, gtlb_index);
 
 	kvmppc_set_exit_type(vcpu, EMULATED_TLBSX_EXITS);
 	return EMULATE_DONE;
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index fe037fd..60624cc 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -20,6 +20,7 @@
 	bool
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
+	select KVM_MMIO
 
 config KVM_BOOK3S_64_HANDLER
 	bool
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 3e294bd..9a271f0 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -33,12 +33,9 @@
 
 /* #define EXIT_DEBUG */
 /* #define EXIT_DEBUG_SIMPLE */
+/* #define DEBUG_EXT */
 
-/* Without AGGRESSIVE_DEC we only fire off a DEC interrupt when DEC turns 0.
- * When set, we retrigger a DEC interrupt after that if DEC <= 0.
- * PPC32 Linux runs faster without AGGRESSIVE_DEC, PPC64 Linux requires it. */
-
-/* #define AGGRESSIVE_DEC */
+static void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "exits",       VCPU_STAT(sum_exits) },
@@ -72,16 +69,24 @@
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
 	memcpy(get_paca()->kvm_slb, to_book3s(vcpu)->slb_shadow, sizeof(get_paca()->kvm_slb));
+	memcpy(&get_paca()->shadow_vcpu, &to_book3s(vcpu)->shadow_vcpu,
+	       sizeof(get_paca()->shadow_vcpu));
 	get_paca()->kvm_slb_max = to_book3s(vcpu)->slb_shadow_max;
 }
 
 void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
 {
 	memcpy(to_book3s(vcpu)->slb_shadow, get_paca()->kvm_slb, sizeof(get_paca()->kvm_slb));
+	memcpy(&to_book3s(vcpu)->shadow_vcpu, &get_paca()->shadow_vcpu,
+	       sizeof(get_paca()->shadow_vcpu));
 	to_book3s(vcpu)->slb_shadow_max = get_paca()->kvm_slb_max;
+
+	kvmppc_giveup_ext(vcpu, MSR_FP);
+	kvmppc_giveup_ext(vcpu, MSR_VEC);
+	kvmppc_giveup_ext(vcpu, MSR_VSX);
 }
 
-#if defined(AGGRESSIVE_DEC) || defined(EXIT_DEBUG)
+#if defined(EXIT_DEBUG)
 static u32 kvmppc_get_dec(struct kvm_vcpu *vcpu)
 {
 	u64 jd = mftb() - vcpu->arch.dec_jiffies;
@@ -89,6 +94,23 @@
 }
 #endif
 
+static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.shadow_msr = vcpu->arch.msr;
+	/* Guest MSR values */
+	vcpu->arch.shadow_msr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE |
+				 MSR_BE | MSR_DE;
+	/* Process MSR values */
+	vcpu->arch.shadow_msr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR |
+				 MSR_EE;
+	/* External providers the guest reserved */
+	vcpu->arch.shadow_msr |= (vcpu->arch.msr & vcpu->arch.guest_owned_ext);
+	/* 64-bit Process MSR values */
+#ifdef CONFIG_PPC_BOOK3S_64
+	vcpu->arch.shadow_msr |= MSR_ISF | MSR_HV;
+#endif
+}
+
 void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
 {
 	ulong old_msr = vcpu->arch.msr;
@@ -96,12 +118,10 @@
 #ifdef EXIT_DEBUG
 	printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
 #endif
+
 	msr &= to_book3s(vcpu)->msr_mask;
 	vcpu->arch.msr = msr;
-	vcpu->arch.shadow_msr = msr | MSR_USER32;
-	vcpu->arch.shadow_msr &= ( MSR_VEC | MSR_VSX | MSR_FP | MSR_FE0 |
-				   MSR_USER64 | MSR_SE | MSR_BE | MSR_DE |
-				   MSR_FE1);
+	kvmppc_recalc_shadow_msr(vcpu);
 
 	if (msr & (MSR_WE|MSR_POW)) {
 		if (!vcpu->arch.pending_exceptions) {
@@ -125,11 +145,10 @@
 	vcpu->arch.mmu.reset_msr(vcpu);
 }
 
-void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
+static int kvmppc_book3s_vec2irqprio(unsigned int vec)
 {
 	unsigned int prio;
 
-	vcpu->stat.queue_intr++;
 	switch (vec) {
 	case 0x100: prio = BOOK3S_IRQPRIO_SYSTEM_RESET;		break;
 	case 0x200: prio = BOOK3S_IRQPRIO_MACHINE_CHECK;	break;
@@ -149,15 +168,31 @@
 	default:    prio = BOOK3S_IRQPRIO_MAX;			break;
 	}
 
-	set_bit(prio, &vcpu->arch.pending_exceptions);
+	return prio;
+}
+
+static void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
+					  unsigned int vec)
+{
+	clear_bit(kvmppc_book3s_vec2irqprio(vec),
+		  &vcpu->arch.pending_exceptions);
+}
+
+void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
+{
+	vcpu->stat.queue_intr++;
+
+	set_bit(kvmppc_book3s_vec2irqprio(vec),
+		&vcpu->arch.pending_exceptions);
 #ifdef EXIT_DEBUG
 	printk(KERN_INFO "Queueing interrupt %x\n", vec);
 #endif
 }
 
 
-void kvmppc_core_queue_program(struct kvm_vcpu *vcpu)
+void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags)
 {
+	to_book3s(vcpu)->prog_flags = flags;
 	kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_PROGRAM);
 }
 
@@ -171,6 +206,11 @@
 	return test_bit(BOOK3S_INTERRUPT_DECREMENTER >> 7, &vcpu->arch.pending_exceptions);
 }
 
+void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu)
+{
+	kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER);
+}
+
 void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                 struct kvm_interrupt *irq)
 {
@@ -181,6 +221,7 @@
 {
 	int deliver = 1;
 	int vec = 0;
+	ulong flags = 0ULL;
 
 	switch (priority) {
 	case BOOK3S_IRQPRIO_DECREMENTER:
@@ -214,6 +255,7 @@
 		break;
 	case BOOK3S_IRQPRIO_PROGRAM:
 		vec = BOOK3S_INTERRUPT_PROGRAM;
+		flags = to_book3s(vcpu)->prog_flags;
 		break;
 	case BOOK3S_IRQPRIO_VSX:
 		vec = BOOK3S_INTERRUPT_VSX;
@@ -244,7 +286,7 @@
 #endif
 
 	if (deliver)
-		kvmppc_inject_interrupt(vcpu, vec, 0ULL);
+		kvmppc_inject_interrupt(vcpu, vec, flags);
 
 	return deliver;
 }
@@ -254,21 +296,15 @@
 	unsigned long *pending = &vcpu->arch.pending_exceptions;
 	unsigned int priority;
 
-	/* XXX be more clever here - no need to mftb() on every entry */
-	/* Issue DEC again if it's still active */
-#ifdef AGGRESSIVE_DEC
-	if (vcpu->arch.msr & MSR_EE)
-		if (kvmppc_get_dec(vcpu) & 0x80000000)
-			kvmppc_core_queue_dec(vcpu);
-#endif
-
 #ifdef EXIT_DEBUG
 	if (vcpu->arch.pending_exceptions)
 		printk(KERN_EMERG "KVM: Check pending: %lx\n", vcpu->arch.pending_exceptions);
 #endif
 	priority = __ffs(*pending);
 	while (priority <= (sizeof(unsigned int) * 8)) {
-		if (kvmppc_book3s_irqprio_deliver(vcpu, priority)) {
+		if (kvmppc_book3s_irqprio_deliver(vcpu, priority) &&
+		    (priority != BOOK3S_IRQPRIO_DECREMENTER)) {
+			/* DEC interrupts get cleared by mtdec */
 			clear_bit(priority, &vcpu->arch.pending_exceptions);
 			break;
 		}
@@ -503,14 +539,14 @@
 		/* Page not found in guest PTE entries */
 		vcpu->arch.dear = vcpu->arch.fault_dear;
 		to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr;
-		vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x00000000f8000000ULL);
+		vcpu->arch.msr |= (vcpu->arch.shadow_srr1 & 0x00000000f8000000ULL);
 		kvmppc_book3s_queue_irqprio(vcpu, vec);
 	} else if (page_found == -EPERM) {
 		/* Storage protection */
 		vcpu->arch.dear = vcpu->arch.fault_dear;
 		to_book3s(vcpu)->dsisr = vcpu->arch.fault_dsisr & ~DSISR_NOHPTE;
 		to_book3s(vcpu)->dsisr |= DSISR_PROTFAULT;
-		vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x00000000f8000000ULL);
+		vcpu->arch.msr |= (vcpu->arch.shadow_srr1 & 0x00000000f8000000ULL);
 		kvmppc_book3s_queue_irqprio(vcpu, vec);
 	} else if (page_found == -EINVAL) {
 		/* Page not found in guest SLB */
@@ -532,13 +568,122 @@
 		r = kvmppc_emulate_mmio(run, vcpu);
 		if ( r == RESUME_HOST_NV )
 			r = RESUME_HOST;
-		if ( r == RESUME_GUEST_NV )
-			r = RESUME_GUEST;
 	}
 
 	return r;
 }
 
+static inline int get_fpr_index(int i)
+{
+#ifdef CONFIG_VSX
+	i *= 2;
+#endif
+	return i;
+}
+
+/* Give up external provider (FPU, Altivec, VSX) */
+static void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
+{
+	struct thread_struct *t = &current->thread;
+	u64 *vcpu_fpr = vcpu->arch.fpr;
+	u64 *vcpu_vsx = vcpu->arch.vsr;
+	u64 *thread_fpr = (u64*)t->fpr;
+	int i;
+
+	if (!(vcpu->arch.guest_owned_ext & msr))
+		return;
+
+#ifdef DEBUG_EXT
+	printk(KERN_INFO "Giving up ext 0x%lx\n", msr);
+#endif
+
+	switch (msr) {
+	case MSR_FP:
+		giveup_fpu(current);
+		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
+			vcpu_fpr[i] = thread_fpr[get_fpr_index(i)];
+
+		vcpu->arch.fpscr = t->fpscr.val;
+		break;
+	case MSR_VEC:
+#ifdef CONFIG_ALTIVEC
+		giveup_altivec(current);
+		memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr));
+		vcpu->arch.vscr = t->vscr;
+#endif
+		break;
+	case MSR_VSX:
+#ifdef CONFIG_VSX
+		__giveup_vsx(current);
+		for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
+			vcpu_vsx[i] = thread_fpr[get_fpr_index(i) + 1];
+#endif
+		break;
+	default:
+		BUG();
+	}
+
+	vcpu->arch.guest_owned_ext &= ~msr;
+	current->thread.regs->msr &= ~msr;
+	kvmppc_recalc_shadow_msr(vcpu);
+}
+
+/* Handle external providers (FPU, Altivec, VSX) */
+static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
+			     ulong msr)
+{
+	struct thread_struct *t = &current->thread;
+	u64 *vcpu_fpr = vcpu->arch.fpr;
+	u64 *vcpu_vsx = vcpu->arch.vsr;
+	u64 *thread_fpr = (u64*)t->fpr;
+	int i;
+
+	if (!(vcpu->arch.msr & msr)) {
+		kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+		return RESUME_GUEST;
+	}
+
+#ifdef DEBUG_EXT
+	printk(KERN_INFO "Loading up ext 0x%lx\n", msr);
+#endif
+
+	current->thread.regs->msr |= msr;
+
+	switch (msr) {
+	case MSR_FP:
+		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
+			thread_fpr[get_fpr_index(i)] = vcpu_fpr[i];
+
+		t->fpscr.val = vcpu->arch.fpscr;
+		t->fpexc_mode = 0;
+		kvmppc_load_up_fpu();
+		break;
+	case MSR_VEC:
+#ifdef CONFIG_ALTIVEC
+		memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
+		t->vscr = vcpu->arch.vscr;
+		t->vrsave = -1;
+		kvmppc_load_up_altivec();
+#endif
+		break;
+	case MSR_VSX:
+#ifdef CONFIG_VSX
+		for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr); i++)
+			thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
+		kvmppc_load_up_vsx();
+#endif
+		break;
+	default:
+		BUG();
+	}
+
+	vcpu->arch.guest_owned_ext |= msr;
+
+	kvmppc_recalc_shadow_msr(vcpu);
+
+	return RESUME_GUEST;
+}
+
 int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        unsigned int exit_nr)
 {
@@ -563,7 +708,7 @@
 	case BOOK3S_INTERRUPT_INST_STORAGE:
 		vcpu->stat.pf_instruc++;
 		/* only care about PTEG not found errors, but leave NX alone */
-		if (vcpu->arch.shadow_msr & 0x40000000) {
+		if (vcpu->arch.shadow_srr1 & 0x40000000) {
 			r = kvmppc_handle_pagefault(run, vcpu, vcpu->arch.pc, exit_nr);
 			vcpu->stat.sp_instruc++;
 		} else if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
@@ -575,7 +720,7 @@
 			 */
 			kvmppc_mmu_pte_flush(vcpu, vcpu->arch.pc, ~0xFFFULL);
 		} else {
-			vcpu->arch.msr |= (vcpu->arch.shadow_msr & 0x58000000);
+			vcpu->arch.msr |= vcpu->arch.shadow_srr1 & 0x58000000;
 			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
 			kvmppc_mmu_pte_flush(vcpu, vcpu->arch.pc, ~0xFFFULL);
 			r = RESUME_GUEST;
@@ -621,6 +766,9 @@
 	case BOOK3S_INTERRUPT_PROGRAM:
 	{
 		enum emulation_result er;
+		ulong flags;
+
+		flags = vcpu->arch.shadow_srr1 & 0x1f0000ull;
 
 		if (vcpu->arch.msr & MSR_PR) {
 #ifdef EXIT_DEBUG
@@ -628,7 +776,7 @@
 #endif
 			if ((vcpu->arch.last_inst & 0xff0007ff) !=
 			    (INS_DCBZ & 0xfffffff7)) {
-				kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+				kvmppc_core_queue_program(vcpu, flags);
 				r = RESUME_GUEST;
 				break;
 			}
@@ -638,12 +786,12 @@
 		er = kvmppc_emulate_instruction(run, vcpu);
 		switch (er) {
 		case EMULATE_DONE:
-			r = RESUME_GUEST;
+			r = RESUME_GUEST_NV;
 			break;
 		case EMULATE_FAIL:
 			printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
 			       __func__, vcpu->arch.pc, vcpu->arch.last_inst);
-			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+			kvmppc_core_queue_program(vcpu, flags);
 			r = RESUME_GUEST;
 			break;
 		default:
@@ -653,23 +801,30 @@
 	}
 	case BOOK3S_INTERRUPT_SYSCALL:
 #ifdef EXIT_DEBUG
-		printk(KERN_INFO "Syscall Nr %d\n", (int)vcpu->arch.gpr[0]);
+		printk(KERN_INFO "Syscall Nr %d\n", (int)kvmppc_get_gpr(vcpu, 0));
 #endif
 		vcpu->stat.syscall_exits++;
 		kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
 		r = RESUME_GUEST;
 		break;
-	case BOOK3S_INTERRUPT_MACHINE_CHECK:
 	case BOOK3S_INTERRUPT_FP_UNAVAIL:
-	case BOOK3S_INTERRUPT_TRACE:
+		r = kvmppc_handle_ext(vcpu, exit_nr, MSR_FP);
+		break;
 	case BOOK3S_INTERRUPT_ALTIVEC:
+		r = kvmppc_handle_ext(vcpu, exit_nr, MSR_VEC);
+		break;
 	case BOOK3S_INTERRUPT_VSX:
+		r = kvmppc_handle_ext(vcpu, exit_nr, MSR_VSX);
+		break;
+	case BOOK3S_INTERRUPT_MACHINE_CHECK:
+	case BOOK3S_INTERRUPT_TRACE:
 		kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
 		r = RESUME_GUEST;
 		break;
 	default:
 		/* Ugh - bork here! What did we get? */
-		printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n", exit_nr, vcpu->arch.pc, vcpu->arch.shadow_msr);
+		printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n",
+			exit_nr, vcpu->arch.pc, vcpu->arch.shadow_srr1);
 		r = RESUME_HOST;
 		BUG();
 		break;
@@ -712,10 +867,10 @@
 	int i;
 
 	regs->pc = vcpu->arch.pc;
-	regs->cr = vcpu->arch.cr;
+	regs->cr = kvmppc_get_cr(vcpu);
 	regs->ctr = vcpu->arch.ctr;
 	regs->lr = vcpu->arch.lr;
-	regs->xer = vcpu->arch.xer;
+	regs->xer = kvmppc_get_xer(vcpu);
 	regs->msr = vcpu->arch.msr;
 	regs->srr0 = vcpu->arch.srr0;
 	regs->srr1 = vcpu->arch.srr1;
@@ -729,7 +884,7 @@
 	regs->sprg7 = vcpu->arch.sprg6;
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
-		regs->gpr[i] = vcpu->arch.gpr[i];
+		regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
 
 	return 0;
 }
@@ -739,10 +894,10 @@
 	int i;
 
 	vcpu->arch.pc = regs->pc;
-	vcpu->arch.cr = regs->cr;
+	kvmppc_set_cr(vcpu, regs->cr);
 	vcpu->arch.ctr = regs->ctr;
 	vcpu->arch.lr = regs->lr;
-	vcpu->arch.xer = regs->xer;
+	kvmppc_set_xer(vcpu, regs->xer);
 	kvmppc_set_msr(vcpu, regs->msr);
 	vcpu->arch.srr0 = regs->srr0;
 	vcpu->arch.srr1 = regs->srr1;
@@ -754,8 +909,8 @@
 	vcpu->arch.sprg6 = regs->sprg5;
 	vcpu->arch.sprg7 = regs->sprg6;
 
-	for (i = 0; i < ARRAY_SIZE(vcpu->arch.gpr); i++)
-		vcpu->arch.gpr[i] = regs->gpr[i];
+	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
+		kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
 
 	return 0;
 }
@@ -850,7 +1005,7 @@
 	int is_dirty = 0;
 	int r, n;
 
-	down_write(&kvm->slots_lock);
+	mutex_lock(&kvm->slots_lock);
 
 	r = kvm_get_dirty_log(kvm, log, &is_dirty);
 	if (r)
@@ -858,7 +1013,7 @@
 
 	/* If nothing is dirty, don't bother messing with page tables. */
 	if (is_dirty) {
-		memslot = &kvm->memslots[log->slot];
+		memslot = &kvm->memslots->memslots[log->slot];
 
 		ga = memslot->base_gfn << PAGE_SHIFT;
 		ga_end = ga + (memslot->npages << PAGE_SHIFT);
@@ -872,7 +1027,7 @@
 
 	r = 0;
 out:
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 	return r;
 }
 
@@ -910,6 +1065,7 @@
 	vcpu->arch.trampoline_lowmem = kvmppc_trampoline_lowmem;
 	vcpu->arch.trampoline_enter = kvmppc_trampoline_enter;
 	vcpu->arch.highmem_handler = (ulong)kvmppc_handler_highmem;
+	vcpu->arch.rmcall = *(ulong*)kvmppc_rmcall;
 
 	vcpu->arch.shadow_msr = MSR_USER64;
 
@@ -943,6 +1099,10 @@
 int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
 	int ret;
+	struct thread_struct ext_bkp;
+	bool save_vec = current->thread.used_vr;
+	bool save_vsx = current->thread.used_vsr;
+	ulong ext_msr;
 
 	/* No need to go into the guest when all we do is going out */
 	if (signal_pending(current)) {
@@ -950,6 +1110,35 @@
 		return -EINTR;
 	}
 
+	/* Save FPU state in stack */
+	if (current->thread.regs->msr & MSR_FP)
+		giveup_fpu(current);
+	memcpy(ext_bkp.fpr, current->thread.fpr, sizeof(current->thread.fpr));
+	ext_bkp.fpscr = current->thread.fpscr;
+	ext_bkp.fpexc_mode = current->thread.fpexc_mode;
+
+#ifdef CONFIG_ALTIVEC
+	/* Save Altivec state in stack */
+	if (save_vec) {
+		if (current->thread.regs->msr & MSR_VEC)
+			giveup_altivec(current);
+		memcpy(ext_bkp.vr, current->thread.vr, sizeof(ext_bkp.vr));
+		ext_bkp.vscr = current->thread.vscr;
+		ext_bkp.vrsave = current->thread.vrsave;
+	}
+	ext_bkp.used_vr = current->thread.used_vr;
+#endif
+
+#ifdef CONFIG_VSX
+	/* Save VSX state in stack */
+	if (save_vsx && (current->thread.regs->msr & MSR_VSX))
+			__giveup_vsx(current);
+	ext_bkp.used_vsr = current->thread.used_vsr;
+#endif
+
+	/* Remember the MSR with disabled extensions */
+	ext_msr = current->thread.regs->msr;
+
 	/* XXX we get called with irq disabled - change that! */
 	local_irq_enable();
 
@@ -957,6 +1146,32 @@
 
 	local_irq_disable();
 
+	current->thread.regs->msr = ext_msr;
+
+	/* Make sure we save the guest FPU/Altivec/VSX state */
+	kvmppc_giveup_ext(vcpu, MSR_FP);
+	kvmppc_giveup_ext(vcpu, MSR_VEC);
+	kvmppc_giveup_ext(vcpu, MSR_VSX);
+
+	/* Restore FPU state from stack */
+	memcpy(current->thread.fpr, ext_bkp.fpr, sizeof(ext_bkp.fpr));
+	current->thread.fpscr = ext_bkp.fpscr;
+	current->thread.fpexc_mode = ext_bkp.fpexc_mode;
+
+#ifdef CONFIG_ALTIVEC
+	/* Restore Altivec state from stack */
+	if (save_vec && current->thread.used_vr) {
+		memcpy(current->thread.vr, ext_bkp.vr, sizeof(ext_bkp.vr));
+		current->thread.vscr = ext_bkp.vscr;
+		current->thread.vrsave= ext_bkp.vrsave;
+	}
+	current->thread.used_vr = ext_bkp.used_vr;
+#endif
+
+#ifdef CONFIG_VSX
+	current->thread.used_vsr = ext_bkp.used_vsr;
+#endif
+
 	return ret;
 }
 
diff --git a/arch/powerpc/kvm/book3s_64_emulate.c b/arch/powerpc/kvm/book3s_64_emulate.c
index 1027eac..2b0ee7e 100644
--- a/arch/powerpc/kvm/book3s_64_emulate.c
+++ b/arch/powerpc/kvm/book3s_64_emulate.c
@@ -65,11 +65,11 @@
 	case 31:
 		switch (get_xop(inst)) {
 		case OP_31_XOP_MFMSR:
-			vcpu->arch.gpr[get_rt(inst)] = vcpu->arch.msr;
+			kvmppc_set_gpr(vcpu, get_rt(inst), vcpu->arch.msr);
 			break;
 		case OP_31_XOP_MTMSRD:
 		{
-			ulong rs = vcpu->arch.gpr[get_rs(inst)];
+			ulong rs = kvmppc_get_gpr(vcpu, get_rs(inst));
 			if (inst & 0x10000) {
 				vcpu->arch.msr &= ~(MSR_RI | MSR_EE);
 				vcpu->arch.msr |= rs & (MSR_RI | MSR_EE);
@@ -78,30 +78,30 @@
 			break;
 		}
 		case OP_31_XOP_MTMSR:
-			kvmppc_set_msr(vcpu, vcpu->arch.gpr[get_rs(inst)]);
+			kvmppc_set_msr(vcpu, kvmppc_get_gpr(vcpu, get_rs(inst)));
 			break;
 		case OP_31_XOP_MFSRIN:
 		{
 			int srnum;
 
-			srnum = (vcpu->arch.gpr[get_rb(inst)] >> 28) & 0xf;
+			srnum = (kvmppc_get_gpr(vcpu, get_rb(inst)) >> 28) & 0xf;
 			if (vcpu->arch.mmu.mfsrin) {
 				u32 sr;
 				sr = vcpu->arch.mmu.mfsrin(vcpu, srnum);
-				vcpu->arch.gpr[get_rt(inst)] = sr;
+				kvmppc_set_gpr(vcpu, get_rt(inst), sr);
 			}
 			break;
 		}
 		case OP_31_XOP_MTSRIN:
 			vcpu->arch.mmu.mtsrin(vcpu,
-				(vcpu->arch.gpr[get_rb(inst)] >> 28) & 0xf,
-				vcpu->arch.gpr[get_rs(inst)]);
+				(kvmppc_get_gpr(vcpu, get_rb(inst)) >> 28) & 0xf,
+				kvmppc_get_gpr(vcpu, get_rs(inst)));
 			break;
 		case OP_31_XOP_TLBIE:
 		case OP_31_XOP_TLBIEL:
 		{
 			bool large = (inst & 0x00200000) ? true : false;
-			ulong addr = vcpu->arch.gpr[get_rb(inst)];
+			ulong addr = kvmppc_get_gpr(vcpu, get_rb(inst));
 			vcpu->arch.mmu.tlbie(vcpu, addr, large);
 			break;
 		}
@@ -111,14 +111,16 @@
 			if (!vcpu->arch.mmu.slbmte)
 				return EMULATE_FAIL;
 
-			vcpu->arch.mmu.slbmte(vcpu, vcpu->arch.gpr[get_rs(inst)],
-						vcpu->arch.gpr[get_rb(inst)]);
+			vcpu->arch.mmu.slbmte(vcpu,
+					kvmppc_get_gpr(vcpu, get_rs(inst)),
+					kvmppc_get_gpr(vcpu, get_rb(inst)));
 			break;
 		case OP_31_XOP_SLBIE:
 			if (!vcpu->arch.mmu.slbie)
 				return EMULATE_FAIL;
 
-			vcpu->arch.mmu.slbie(vcpu, vcpu->arch.gpr[get_rb(inst)]);
+			vcpu->arch.mmu.slbie(vcpu,
+					kvmppc_get_gpr(vcpu, get_rb(inst)));
 			break;
 		case OP_31_XOP_SLBIA:
 			if (!vcpu->arch.mmu.slbia)
@@ -132,9 +134,9 @@
 			} else {
 				ulong t, rb;
 
-				rb = vcpu->arch.gpr[get_rb(inst)];
+				rb = kvmppc_get_gpr(vcpu, get_rb(inst));
 				t = vcpu->arch.mmu.slbmfee(vcpu, rb);
-				vcpu->arch.gpr[get_rt(inst)] = t;
+				kvmppc_set_gpr(vcpu, get_rt(inst), t);
 			}
 			break;
 		case OP_31_XOP_SLBMFEV:
@@ -143,20 +145,20 @@
 			} else {
 				ulong t, rb;
 
-				rb = vcpu->arch.gpr[get_rb(inst)];
+				rb = kvmppc_get_gpr(vcpu, get_rb(inst));
 				t = vcpu->arch.mmu.slbmfev(vcpu, rb);
-				vcpu->arch.gpr[get_rt(inst)] = t;
+				kvmppc_set_gpr(vcpu, get_rt(inst), t);
 			}
 			break;
 		case OP_31_XOP_DCBZ:
 		{
-			ulong rb =  vcpu->arch.gpr[get_rb(inst)];
+			ulong rb = kvmppc_get_gpr(vcpu, get_rb(inst));
 			ulong ra = 0;
 			ulong addr;
 			u32 zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
 			if (get_ra(inst))
-				ra = vcpu->arch.gpr[get_ra(inst)];
+				ra = kvmppc_get_gpr(vcpu, get_ra(inst));
 
 			addr = (ra + rb) & ~31ULL;
 			if (!(vcpu->arch.msr & MSR_SF))
@@ -233,43 +235,44 @@
 int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
 {
 	int emulated = EMULATE_DONE;
+	ulong spr_val = kvmppc_get_gpr(vcpu, rs);
 
 	switch (sprn) {
 	case SPRN_SDR1:
-		to_book3s(vcpu)->sdr1 = vcpu->arch.gpr[rs];
+		to_book3s(vcpu)->sdr1 = spr_val;
 		break;
 	case SPRN_DSISR:
-		to_book3s(vcpu)->dsisr = vcpu->arch.gpr[rs];
+		to_book3s(vcpu)->dsisr = spr_val;
 		break;
 	case SPRN_DAR:
-		vcpu->arch.dear = vcpu->arch.gpr[rs];
+		vcpu->arch.dear = spr_val;
 		break;
 	case SPRN_HIOR:
-		to_book3s(vcpu)->hior = vcpu->arch.gpr[rs];
+		to_book3s(vcpu)->hior = spr_val;
 		break;
 	case SPRN_IBAT0U ... SPRN_IBAT3L:
 	case SPRN_IBAT4U ... SPRN_IBAT7L:
 	case SPRN_DBAT0U ... SPRN_DBAT3L:
 	case SPRN_DBAT4U ... SPRN_DBAT7L:
-		kvmppc_write_bat(vcpu, sprn, (u32)vcpu->arch.gpr[rs]);
+		kvmppc_write_bat(vcpu, sprn, (u32)spr_val);
 		/* BAT writes happen so rarely that we're ok to flush
 		 * everything here */
 		kvmppc_mmu_pte_flush(vcpu, 0, 0);
 		break;
 	case SPRN_HID0:
-		to_book3s(vcpu)->hid[0] = vcpu->arch.gpr[rs];
+		to_book3s(vcpu)->hid[0] = spr_val;
 		break;
 	case SPRN_HID1:
-		to_book3s(vcpu)->hid[1] = vcpu->arch.gpr[rs];
+		to_book3s(vcpu)->hid[1] = spr_val;
 		break;
 	case SPRN_HID2:
-		to_book3s(vcpu)->hid[2] = vcpu->arch.gpr[rs];
+		to_book3s(vcpu)->hid[2] = spr_val;
 		break;
 	case SPRN_HID4:
-		to_book3s(vcpu)->hid[4] = vcpu->arch.gpr[rs];
+		to_book3s(vcpu)->hid[4] = spr_val;
 		break;
 	case SPRN_HID5:
-		to_book3s(vcpu)->hid[5] = vcpu->arch.gpr[rs];
+		to_book3s(vcpu)->hid[5] = spr_val;
 		/* guest HID5 set can change is_dcbz32 */
 		if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
 		    (mfmsr() & MSR_HV))
@@ -299,38 +302,38 @@
 
 	switch (sprn) {
 	case SPRN_SDR1:
-		vcpu->arch.gpr[rt] = to_book3s(vcpu)->sdr1;
+		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->sdr1);
 		break;
 	case SPRN_DSISR:
-		vcpu->arch.gpr[rt] = to_book3s(vcpu)->dsisr;
+		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->dsisr);
 		break;
 	case SPRN_DAR:
-		vcpu->arch.gpr[rt] = vcpu->arch.dear;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear);
 		break;
 	case SPRN_HIOR:
-		vcpu->arch.gpr[rt] = to_book3s(vcpu)->hior;
+		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hior);
 		break;
 	case SPRN_HID0:
-		vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[0];
+		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[0]);
 		break;
 	case SPRN_HID1:
-		vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[1];
+		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[1]);
 		break;
 	case SPRN_HID2:
-		vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[2];
+		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[2]);
 		break;
 	case SPRN_HID4:
-		vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[4];
+		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[4]);
 		break;
 	case SPRN_HID5:
-		vcpu->arch.gpr[rt] = to_book3s(vcpu)->hid[5];
+		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[5]);
 		break;
 	case SPRN_THRM1:
 	case SPRN_THRM2:
 	case SPRN_THRM3:
 	case SPRN_CTRLF:
 	case SPRN_CTRLT:
-		vcpu->arch.gpr[rt] = 0;
+		kvmppc_set_gpr(vcpu, rt, 0);
 		break;
 	default:
 		printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn);
diff --git a/arch/powerpc/kvm/book3s_64_exports.c b/arch/powerpc/kvm/book3s_64_exports.c
index 5b2db38..1dd5a1d 100644
--- a/arch/powerpc/kvm/book3s_64_exports.c
+++ b/arch/powerpc/kvm/book3s_64_exports.c
@@ -22,3 +22,11 @@
 
 EXPORT_SYMBOL_GPL(kvmppc_trampoline_enter);
 EXPORT_SYMBOL_GPL(kvmppc_trampoline_lowmem);
+EXPORT_SYMBOL_GPL(kvmppc_rmcall);
+EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu);
+#ifdef CONFIG_ALTIVEC
+EXPORT_SYMBOL_GPL(kvmppc_load_up_altivec);
+#endif
+#ifdef CONFIG_VSX
+EXPORT_SYMBOL_GPL(kvmppc_load_up_vsx);
+#endif
diff --git a/arch/powerpc/kvm/book3s_64_interrupts.S b/arch/powerpc/kvm/book3s_64_interrupts.S
index 7b55d80..c1584d0 100644
--- a/arch/powerpc/kvm/book3s_64_interrupts.S
+++ b/arch/powerpc/kvm/book3s_64_interrupts.S
@@ -28,11 +28,6 @@
 #define ULONG_SIZE 8
 #define VCPU_GPR(n)     (VCPU_GPRS + (n * ULONG_SIZE))
 
-.macro mfpaca tmp_reg, src_reg, offset, vcpu_reg
-	ld	\tmp_reg, (PACA_EXMC+\offset)(r13)
-	std	\tmp_reg, VCPU_GPR(\src_reg)(\vcpu_reg)
-.endm
-
 .macro DISABLE_INTERRUPTS
        mfmsr   r0
        rldicl  r0,r0,48,1
@@ -40,6 +35,26 @@
        mtmsrd  r0,1
 .endm
 
+#define VCPU_LOAD_NVGPRS(vcpu) \
+	ld	r14, VCPU_GPR(r14)(vcpu); \
+	ld	r15, VCPU_GPR(r15)(vcpu); \
+	ld	r16, VCPU_GPR(r16)(vcpu); \
+	ld	r17, VCPU_GPR(r17)(vcpu); \
+	ld	r18, VCPU_GPR(r18)(vcpu); \
+	ld	r19, VCPU_GPR(r19)(vcpu); \
+	ld	r20, VCPU_GPR(r20)(vcpu); \
+	ld	r21, VCPU_GPR(r21)(vcpu); \
+	ld	r22, VCPU_GPR(r22)(vcpu); \
+	ld	r23, VCPU_GPR(r23)(vcpu); \
+	ld	r24, VCPU_GPR(r24)(vcpu); \
+	ld	r25, VCPU_GPR(r25)(vcpu); \
+	ld	r26, VCPU_GPR(r26)(vcpu); \
+	ld	r27, VCPU_GPR(r27)(vcpu); \
+	ld	r28, VCPU_GPR(r28)(vcpu); \
+	ld	r29, VCPU_GPR(r29)(vcpu); \
+	ld	r30, VCPU_GPR(r30)(vcpu); \
+	ld	r31, VCPU_GPR(r31)(vcpu); \
+
 /*****************************************************************************
  *                                                                           *
  *     Guest entry / exit code that is in kernel module memory (highmem)     *
@@ -67,61 +82,32 @@
 	SAVE_NVGPRS(r1)
 
 	/* Save LR */
-	mflr	r14
-	std	r14, _LINK(r1)
-
-/* XXX optimize non-volatile loading away */
-kvm_start_lightweight:
-
-	DISABLE_INTERRUPTS
-
-	/* Save R1/R2 in the PACA */
-	std	r1, PACAR1(r13)
-	std	r2, (PACA_EXMC+EX_SRR0)(r13)
-	ld	r3, VCPU_HIGHMEM_HANDLER(r4)
-	std	r3, PACASAVEDMSR(r13)
+	std	r0, _LINK(r1)
 
 	/* Load non-volatile guest state from the vcpu */
-	ld	r14, VCPU_GPR(r14)(r4)
-	ld	r15, VCPU_GPR(r15)(r4)
-	ld	r16, VCPU_GPR(r16)(r4)
-	ld	r17, VCPU_GPR(r17)(r4)
-	ld	r18, VCPU_GPR(r18)(r4)
-	ld	r19, VCPU_GPR(r19)(r4)
-	ld	r20, VCPU_GPR(r20)(r4)
-	ld	r21, VCPU_GPR(r21)(r4)
-	ld	r22, VCPU_GPR(r22)(r4)
-	ld	r23, VCPU_GPR(r23)(r4)
-	ld	r24, VCPU_GPR(r24)(r4)
-	ld	r25, VCPU_GPR(r25)(r4)
-	ld	r26, VCPU_GPR(r26)(r4)
-	ld	r27, VCPU_GPR(r27)(r4)
-	ld	r28, VCPU_GPR(r28)(r4)
-	ld	r29, VCPU_GPR(r29)(r4)
-	ld	r30, VCPU_GPR(r30)(r4)
-	ld	r31, VCPU_GPR(r31)(r4)
+	VCPU_LOAD_NVGPRS(r4)
+
+	/* Save R1/R2 in the PACA */
+	std	r1, PACA_KVM_HOST_R1(r13)
+	std	r2, PACA_KVM_HOST_R2(r13)
+
+	/* XXX swap in/out on load? */
+	ld	r3, VCPU_HIGHMEM_HANDLER(r4)
+	std	r3, PACA_KVM_VMHANDLER(r13)
+
+kvm_start_lightweight:
 
 	ld	r9, VCPU_PC(r4)			/* r9 = vcpu->arch.pc */
 	ld	r10, VCPU_SHADOW_MSR(r4)	/* r10 = vcpu->arch.shadow_msr */
 
-	ld	r3, VCPU_TRAMPOLINE_ENTER(r4)
-	mtsrr0	r3
-
-	LOAD_REG_IMMEDIATE(r3, MSR_KERNEL & ~(MSR_IR | MSR_DR))
-	mtsrr1	r3
-
-	/* Load guest state in the respective registers */
-	lwz	r3, VCPU_CR(r4)		/* r3 = vcpu->arch.cr */
-	stw	r3, (PACA_EXMC + EX_CCR)(r13)
-
-	ld	r3, VCPU_CTR(r4)	/* r3 = vcpu->arch.ctr */
-	mtctr	r3			/* CTR = r3 */
+	/* Load some guest state in the respective registers */
+	ld	r5, VCPU_CTR(r4)	/* r5 = vcpu->arch.ctr */
+					/* will be swapped in by rmcall */
 
 	ld	r3, VCPU_LR(r4)		/* r3 = vcpu->arch.lr */
 	mtlr	r3			/* LR = r3 */
 
-	ld	r3, VCPU_XER(r4)	/* r3 = vcpu->arch.xer */
-	std	r3, (PACA_EXMC + EX_R3)(r13)
+	DISABLE_INTERRUPTS
 
 	/* Some guests may need to have dcbz set to 32 byte length.
 	 *
@@ -141,36 +127,15 @@
 	mtspr   SPRN_HID5,r3
 
 no_dcbz32_on:
-	/*	Load guest GPRs */
 
-	ld	r3, VCPU_GPR(r9)(r4)
-	std	r3, (PACA_EXMC + EX_R9)(r13)
-	ld	r3, VCPU_GPR(r10)(r4)
-	std	r3, (PACA_EXMC + EX_R10)(r13)
-	ld	r3, VCPU_GPR(r11)(r4)
-	std	r3, (PACA_EXMC + EX_R11)(r13)
-	ld	r3, VCPU_GPR(r12)(r4)
-	std	r3, (PACA_EXMC + EX_R12)(r13)
-	ld	r3, VCPU_GPR(r13)(r4)
-	std	r3, (PACA_EXMC + EX_R13)(r13)
+	ld	r6, VCPU_RMCALL(r4)
+	mtctr	r6
 
-	ld	r0, VCPU_GPR(r0)(r4)
-	ld	r1, VCPU_GPR(r1)(r4)
-	ld	r2, VCPU_GPR(r2)(r4)
-	ld	r3, VCPU_GPR(r3)(r4)
-	ld	r5, VCPU_GPR(r5)(r4)
-	ld	r6, VCPU_GPR(r6)(r4)
-	ld	r7, VCPU_GPR(r7)(r4)
-	ld	r8, VCPU_GPR(r8)(r4)
-	ld	r4, VCPU_GPR(r4)(r4)
-
-	/* This sets the Magic value for the trampoline */
-
-	li	r11, 1
-	stb	r11, PACA_KVM_IN_GUEST(r13)
+	ld	r3, VCPU_TRAMPOLINE_ENTER(r4)
+	LOAD_REG_IMMEDIATE(r4, MSR_KERNEL & ~(MSR_IR | MSR_DR))
 
 	/* Jump to SLB patching handlder and into our guest */
-	RFI
+	bctr
 
 /*
  * This is the handler in module memory. It gets jumped at from the
@@ -184,125 +149,70 @@
 	/*
 	 * Register usage at this point:
 	 *
-	 * R00   = guest R13
-	 * R01   = host R1
-	 * R02   = host R2
-	 * R10   = guest PC
-	 * R11   = guest MSR
-	 * R12   = exit handler id
-	 * R13   = PACA
-	 * PACA.exmc.R9    = guest R1
-	 * PACA.exmc.R10   = guest R10
-	 * PACA.exmc.R11   = guest R11
-	 * PACA.exmc.R12   = guest R12
-	 * PACA.exmc.R13   = guest R2
-	 * PACA.exmc.DAR   = guest DAR
-	 * PACA.exmc.DSISR = guest DSISR
-	 * PACA.exmc.LR    = guest instruction
-	 * PACA.exmc.CCR   = guest CR
-	 * PACA.exmc.SRR0  = guest R0
+	 * R0         = guest last inst
+	 * R1         = host R1
+	 * R2         = host R2
+	 * R3         = guest PC
+	 * R4         = guest MSR
+	 * R5         = guest DAR
+	 * R6         = guest DSISR
+	 * R13        = PACA
+	 * PACA.KVM.* = guest *
 	 *
 	 */
 
-	std	r3, (PACA_EXMC+EX_R3)(r13)
-
-	/* save the exit id in R3 */
-	mr	r3, r12
-
-	/* R12 = vcpu */
-	ld	r12, GPR4(r1)
+	/* R7 = vcpu */
+	ld	r7, GPR4(r1)
 
 	/* Now save the guest state */
 
-	std	r0, VCPU_GPR(r13)(r12)
-	std	r4, VCPU_GPR(r4)(r12)
-	std	r5, VCPU_GPR(r5)(r12)
-	std	r6, VCPU_GPR(r6)(r12)
-	std	r7, VCPU_GPR(r7)(r12)
-	std	r8, VCPU_GPR(r8)(r12)
-	std	r9, VCPU_GPR(r9)(r12)
+	stw	r0, VCPU_LAST_INST(r7)
 
-	/* get registers from PACA */
-	mfpaca	r5, r0, EX_SRR0, r12
-	mfpaca	r5, r3, EX_R3, r12
-	mfpaca	r5, r1, EX_R9, r12
-	mfpaca	r5, r10, EX_R10, r12
-	mfpaca	r5, r11, EX_R11, r12
-	mfpaca	r5, r12, EX_R12, r12
-	mfpaca	r5, r2, EX_R13, r12
+	std	r3, VCPU_PC(r7)
+	std	r4, VCPU_SHADOW_SRR1(r7)
+	std	r5, VCPU_FAULT_DEAR(r7)
+	std	r6, VCPU_FAULT_DSISR(r7)
 
-	lwz	r5, (PACA_EXMC+EX_LR)(r13)
-	stw	r5, VCPU_LAST_INST(r12)
-
-	lwz	r5, (PACA_EXMC+EX_CCR)(r13)
-	stw	r5, VCPU_CR(r12)
-
-	ld	r5, VCPU_HFLAGS(r12)
+	ld	r5, VCPU_HFLAGS(r7)
 	rldicl.	r5, r5, 0, 63		/* CR = ((r5 & 1) == 0) */
 	beq	no_dcbz32_off
 
+	li	r4, 0
 	mfspr   r5,SPRN_HID5
-	rldimi  r5,r5,6,56
+	rldimi  r5,r4,6,56
 	mtspr   SPRN_HID5,r5
 
 no_dcbz32_off:
 
-	/* XXX maybe skip on lightweight? */
-	std	r14, VCPU_GPR(r14)(r12)
-	std	r15, VCPU_GPR(r15)(r12)
-	std	r16, VCPU_GPR(r16)(r12)
-	std	r17, VCPU_GPR(r17)(r12)
-	std	r18, VCPU_GPR(r18)(r12)
-	std	r19, VCPU_GPR(r19)(r12)
-	std	r20, VCPU_GPR(r20)(r12)
-	std	r21, VCPU_GPR(r21)(r12)
-	std	r22, VCPU_GPR(r22)(r12)
-	std	r23, VCPU_GPR(r23)(r12)
-	std	r24, VCPU_GPR(r24)(r12)
-	std	r25, VCPU_GPR(r25)(r12)
-	std	r26, VCPU_GPR(r26)(r12)
-	std	r27, VCPU_GPR(r27)(r12)
-	std	r28, VCPU_GPR(r28)(r12)
-	std	r29, VCPU_GPR(r29)(r12)
-	std	r30, VCPU_GPR(r30)(r12)
-	std	r31, VCPU_GPR(r31)(r12)
+	std	r14, VCPU_GPR(r14)(r7)
+	std	r15, VCPU_GPR(r15)(r7)
+	std	r16, VCPU_GPR(r16)(r7)
+	std	r17, VCPU_GPR(r17)(r7)
+	std	r18, VCPU_GPR(r18)(r7)
+	std	r19, VCPU_GPR(r19)(r7)
+	std	r20, VCPU_GPR(r20)(r7)
+	std	r21, VCPU_GPR(r21)(r7)
+	std	r22, VCPU_GPR(r22)(r7)
+	std	r23, VCPU_GPR(r23)(r7)
+	std	r24, VCPU_GPR(r24)(r7)
+	std	r25, VCPU_GPR(r25)(r7)
+	std	r26, VCPU_GPR(r26)(r7)
+	std	r27, VCPU_GPR(r27)(r7)
+	std	r28, VCPU_GPR(r28)(r7)
+	std	r29, VCPU_GPR(r29)(r7)
+	std	r30, VCPU_GPR(r30)(r7)
+	std	r31, VCPU_GPR(r31)(r7)
 
-	/* Restore non-volatile host registers (r14 - r31) */
-	REST_NVGPRS(r1)
-
-	/* Save guest PC (R10) */
-	std	r10, VCPU_PC(r12)
-
-	/* Save guest msr (R11) */
-	std	r11, VCPU_SHADOW_MSR(r12)
-
-	/* Save guest CTR (in R12) */
+	/* Save guest CTR */
 	mfctr	r5
-	std	r5, VCPU_CTR(r12)
+	std	r5, VCPU_CTR(r7)
 
 	/* Save guest LR */
 	mflr	r5
-	std	r5, VCPU_LR(r12)
-
-	/* Save guest XER */
-	mfxer	r5
-	std	r5, VCPU_XER(r12)
-
-	/* Save guest DAR */
-	ld	r5, (PACA_EXMC+EX_DAR)(r13)
-	std	r5, VCPU_FAULT_DEAR(r12)
-
-	/* Save guest DSISR */
-	lwz	r5, (PACA_EXMC+EX_DSISR)(r13)
-	std	r5, VCPU_FAULT_DSISR(r12)
+	std	r5, VCPU_LR(r7)
 
 	/* Restore host msr -> SRR1 */
-	ld	r7, VCPU_HOST_MSR(r12)
-	mtsrr1	r7
-
-	/* Restore host IP -> SRR0 */
-	ld	r6, VCPU_HOST_RETIP(r12)
-	mtsrr0	r6
+	ld	r6, VCPU_HOST_MSR(r7)
 
 	/*
 	 * For some interrupts, we need to call the real Linux
@@ -314,13 +224,14 @@
 	 * r3 = address of interrupt handler (exit reason)
 	 */
 
-	cmpwi	r3, BOOK3S_INTERRUPT_EXTERNAL
+	cmpwi	r12, BOOK3S_INTERRUPT_EXTERNAL
 	beq	call_linux_handler
-	cmpwi	r3, BOOK3S_INTERRUPT_DECREMENTER
+	cmpwi	r12, BOOK3S_INTERRUPT_DECREMENTER
 	beq	call_linux_handler
 
-	/* Back to Interruptable Mode! (goto kvm_return_point) */
-	RFI
+	/* Back to EE=1 */
+	mtmsr	r6
+	b	kvm_return_point
 
 call_linux_handler:
 
@@ -333,16 +244,22 @@
 	 * interrupt handler!
 	 *
 	 * R3 still contains the exit code,
-	 * R6 VCPU_HOST_RETIP and
-	 * R7 VCPU_HOST_MSR
+	 * R5 VCPU_HOST_RETIP and
+	 * R6 VCPU_HOST_MSR
 	 */
 
-	mtlr	r3
+	/* Restore host IP -> SRR0 */
+	ld	r5, VCPU_HOST_RETIP(r7)
 
-	ld	r5, VCPU_TRAMPOLINE_LOWMEM(r12)
-	mtsrr0	r5
-	LOAD_REG_IMMEDIATE(r5, MSR_KERNEL & ~(MSR_IR | MSR_DR))
-	mtsrr1	r5
+	/* XXX Better move to a safe function?
+	 *     What if we get an HTAB flush in between mtsrr0 and mtsrr1? */
+
+	mtlr	r12
+
+	ld	r4, VCPU_TRAMPOLINE_LOWMEM(r7)
+	mtsrr0	r4
+	LOAD_REG_IMMEDIATE(r3, MSR_KERNEL & ~(MSR_IR | MSR_DR))
+	mtsrr1	r3
 
 	RFI
 
@@ -351,42 +268,51 @@
 
 	/* Jump back to lightweight entry if we're supposed to */
 	/* go back into the guest */
-	mr	r5, r3
+
+	/* Pass the exit number as 3rd argument to kvmppc_handle_exit */
+	mr	r5, r12
+
 	/* Restore r3 (kvm_run) and r4 (vcpu) */
 	REST_2GPRS(3, r1)
 	bl	KVMPPC_HANDLE_EXIT
 
-#if 0 /* XXX get lightweight exits back */
+	/* If RESUME_GUEST, get back in the loop */
 	cmpwi	r3, RESUME_GUEST
-	bne	kvm_exit_heavyweight
+	beq	kvm_loop_lightweight
 
-	/* put VCPU and KVM_RUN back into place and roll again! */
-	REST_2GPRS(3, r1)
-	b	kvm_start_lightweight
+	cmpwi	r3, RESUME_GUEST_NV
+	beq	kvm_loop_heavyweight
 
-kvm_exit_heavyweight:
-	/* Restore non-volatile host registers */
-	ld	r14, _LINK(r1)
-	mtlr	r14
-	REST_NVGPRS(r1)
+kvm_exit_loop:
 
-	addi    r1, r1, SWITCH_FRAME_SIZE
-#else
 	ld	r4, _LINK(r1)
 	mtlr	r4
 
-	cmpwi	r3, RESUME_GUEST
-	bne	kvm_exit_heavyweight
+	/* Restore non-volatile host registers (r14 - r31) */
+	REST_NVGPRS(r1)
 
+	addi    r1, r1, SWITCH_FRAME_SIZE
+	blr
+
+kvm_loop_heavyweight:
+
+	ld	r4, _LINK(r1)
+	std     r4, (16 + SWITCH_FRAME_SIZE)(r1)
+
+	/* Load vcpu and cpu_run */
 	REST_2GPRS(3, r1)
 
-	addi    r1, r1, SWITCH_FRAME_SIZE
+	/* Load non-volatile guest state from the vcpu */
+	VCPU_LOAD_NVGPRS(r4)
 
-	b	kvm_start_entry
+	/* Jump back into the beginning of this function */
+	b	kvm_start_lightweight
 
-kvm_exit_heavyweight:
+kvm_loop_lightweight:
 
-	addi    r1, r1, SWITCH_FRAME_SIZE
-#endif
+	/* We'll need the vcpu pointer */
+	REST_GPR(4, r1)
 
-	blr
+	/* Jump back into the beginning of this function */
+	b	kvm_start_lightweight
+
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index e4beeb3..512dcff 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -54,7 +54,7 @@
 		if (!vcpu_book3s->slb[i].valid)
 			continue;
 
-		if (vcpu_book3s->slb[i].large)
+		if (vcpu_book3s->slb[i].tb)
 			cmp_esid = esid_1t;
 
 		if (vcpu_book3s->slb[i].esid == cmp_esid)
@@ -65,9 +65,10 @@
 		eaddr, esid, esid_1t);
 	for (i = 0; i < vcpu_book3s->slb_nr; i++) {
 	    if (vcpu_book3s->slb[i].vsid)
-		dprintk("  %d: %c%c %llx %llx\n", i,
+		dprintk("  %d: %c%c%c %llx %llx\n", i,
 			vcpu_book3s->slb[i].valid ? 'v' : ' ',
 			vcpu_book3s->slb[i].large ? 'l' : ' ',
+			vcpu_book3s->slb[i].tb    ? 't' : ' ',
 			vcpu_book3s->slb[i].esid,
 			vcpu_book3s->slb[i].vsid);
 	}
@@ -84,7 +85,7 @@
 	if (!slb)
 		return 0;
 
-	if (slb->large)
+	if (slb->tb)
 		return (((u64)eaddr >> 12) & 0xfffffff) |
 		       (((u64)slb->vsid) << 28);
 
@@ -309,7 +310,8 @@
 	slbe = &vcpu_book3s->slb[slb_nr];
 
 	slbe->large = (rs & SLB_VSID_L) ? 1 : 0;
-	slbe->esid  = slbe->large ? esid_1t : esid;
+	slbe->tb    = (rs & SLB_VSID_B_1T) ? 1 : 0;
+	slbe->esid  = slbe->tb ? esid_1t : esid;
 	slbe->vsid  = rs >> 12;
 	slbe->valid = (rb & SLB_ESID_V) ? 1 : 0;
 	slbe->Ks    = (rs & SLB_VSID_KS) ? 1 : 0;
diff --git a/arch/powerpc/kvm/book3s_64_rmhandlers.S b/arch/powerpc/kvm/book3s_64_rmhandlers.S
index fb7dd2e..c83c60a 100644
--- a/arch/powerpc/kvm/book3s_64_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_64_rmhandlers.S
@@ -45,36 +45,25 @@
 	 * To distinguish, we check a magic byte in the PACA
 	 */
 	mfspr	r13, SPRN_SPRG_PACA		/* r13 = PACA */
-	std	r12, (PACA_EXMC + EX_R12)(r13)
+	std	r12, PACA_KVM_SCRATCH0(r13)
 	mfcr	r12
-	stw	r12, (PACA_EXMC + EX_CCR)(r13)
+	stw	r12, PACA_KVM_SCRATCH1(r13)
 	lbz	r12, PACA_KVM_IN_GUEST(r13)
-	cmpwi	r12, 0
+	cmpwi	r12, KVM_GUEST_MODE_NONE
 	bne	..kvmppc_handler_hasmagic_\intno
 	/* No KVM guest? Then jump back to the Linux handler! */
-	lwz	r12, (PACA_EXMC + EX_CCR)(r13)
+	lwz	r12, PACA_KVM_SCRATCH1(r13)
 	mtcr	r12
-	ld	r12, (PACA_EXMC + EX_R12)(r13)
+	ld	r12, PACA_KVM_SCRATCH0(r13)
 	mfspr	r13, SPRN_SPRG_SCRATCH0		/* r13 = original r13 */
 	b	kvmppc_resume_\intno		/* Get back original handler */
 
 	/* Now we know we're handling a KVM guest */
 ..kvmppc_handler_hasmagic_\intno:
-	/* Unset guest state */
-	li	r12, 0
-	stb	r12, PACA_KVM_IN_GUEST(r13)
 
-	std	r1, (PACA_EXMC+EX_R9)(r13)
-	std	r10, (PACA_EXMC+EX_R10)(r13)
-	std	r11, (PACA_EXMC+EX_R11)(r13)
-	std	r2, (PACA_EXMC+EX_R13)(r13)
-
-	mfsrr0	r10
-	mfsrr1	r11
-
-	/* Restore R1/R2 so we can handle faults */
-	ld	r1, PACAR1(r13)
-	ld	r2, (PACA_EXMC+EX_SRR0)(r13)
+	/* Should we just skip the faulting instruction? */
+	cmpwi	r12, KVM_GUEST_MODE_SKIP
+	beq	kvmppc_handler_skip_ins
 
 	/* Let's store which interrupt we're handling */
 	li	r12, \intno
@@ -102,23 +91,107 @@
 INTERRUPT_TRAMPOLINE	BOOK3S_INTERRUPT_VSX
 
 /*
+ * Bring us back to the faulting code, but skip the
+ * faulting instruction.
+ *
+ * This is a generic exit path from the interrupt
+ * trampolines above.
+ *
+ * Input Registers:
+ *
+ * R12               = free
+ * R13               = PACA
+ * PACA.KVM.SCRATCH0 = guest R12
+ * PACA.KVM.SCRATCH1 = guest CR
+ * SPRG_SCRATCH0     = guest R13
+ *
+ */
+kvmppc_handler_skip_ins:
+
+	/* Patch the IP to the next instruction */
+	mfsrr0	r12
+	addi	r12, r12, 4
+	mtsrr0	r12
+
+	/* Clean up all state */
+	lwz	r12, PACA_KVM_SCRATCH1(r13)
+	mtcr	r12
+	ld	r12, PACA_KVM_SCRATCH0(r13)
+	mfspr	r13, SPRN_SPRG_SCRATCH0
+
+	/* And get back into the code */
+	RFI
+
+/*
  * This trampoline brings us back to a real mode handler
  *
  * Input Registers:
  *
- * R6 = SRR0
- * R7 = SRR1
+ * R5 = SRR0
+ * R6 = SRR1
  * LR = real-mode IP
  *
  */
 .global kvmppc_handler_lowmem_trampoline
 kvmppc_handler_lowmem_trampoline:
 
-	mtsrr0	r6
-	mtsrr1	r7
+	mtsrr0	r5
+	mtsrr1	r6
 	blr
 kvmppc_handler_lowmem_trampoline_end:
 
+/*
+ * Call a function in real mode
+ *
+ * Input Registers:
+ *
+ * R3 = function
+ * R4 = MSR
+ * R5 = CTR
+ *
+ */
+_GLOBAL(kvmppc_rmcall)
+	mtmsr	r4		/* Disable relocation, so mtsrr
+				   doesn't get interrupted */
+	mtctr	r5
+	mtsrr0	r3
+	mtsrr1	r4
+	RFI
+
+/*
+ * Activate current's external feature (FPU/Altivec/VSX)
+ */
+#define define_load_up(what) 				\
+							\
+_GLOBAL(kvmppc_load_up_ ## what);			\
+	subi	r1, r1, INT_FRAME_SIZE;			\
+	mflr	r3;					\
+	std	r3, _LINK(r1);				\
+	mfmsr	r4;					\
+	std	r31, GPR3(r1);				\
+	mr	r31, r4;				\
+	li	r5, MSR_DR;				\
+	oris	r5, r5, MSR_EE@h;			\
+	andc	r4, r4, r5;				\
+	mtmsr	r4;					\
+							\
+	bl	.load_up_ ## what;			\
+							\
+	mtmsr	r31;					\
+	ld	r3, _LINK(r1);				\
+	ld	r31, GPR3(r1);				\
+	addi	r1, r1, INT_FRAME_SIZE;			\
+	mtlr	r3;					\
+	blr
+
+define_load_up(fpu)
+#ifdef CONFIG_ALTIVEC
+define_load_up(altivec)
+#endif
+#ifdef CONFIG_VSX
+define_load_up(vsx)
+#endif
+
 .global kvmppc_trampoline_lowmem
 kvmppc_trampoline_lowmem:
 	.long kvmppc_handler_lowmem_trampoline - _stext
diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/book3s_64_slb.S
index ecd237a..35b76272 100644
--- a/arch/powerpc/kvm/book3s_64_slb.S
+++ b/arch/powerpc/kvm/book3s_64_slb.S
@@ -31,7 +31,7 @@
 #define REBOLT_SLB_ENTRY(num) \
 	ld	r10, SHADOW_SLB_ESID(num)(r11); \
 	cmpdi	r10, 0; \
-	beq	slb_exit_skip_1; \
+	beq	slb_exit_skip_ ## num; \
 	oris	r10, r10, SLB_ESID_V@h; \
 	ld	r9, SHADOW_SLB_VSID(num)(r11); \
 	slbmte	r9, r10; \
@@ -51,23 +51,21 @@
 	 *
 	 * MSR = ~IR|DR
 	 * R13 = PACA
+	 * R1 = host R1
+	 * R2 = host R2
 	 * R9 = guest IP
 	 * R10 = guest MSR
-	 * R11 = free
-	 * R12 = free
-	 * PACA[PACA_EXMC + EX_R9] = guest R9
-	 * PACA[PACA_EXMC + EX_R10] = guest R10
-	 * PACA[PACA_EXMC + EX_R11] = guest R11
-	 * PACA[PACA_EXMC + EX_R12] = guest R12
-	 * PACA[PACA_EXMC + EX_R13] = guest R13
-	 * PACA[PACA_EXMC + EX_CCR] = guest CR
-	 * PACA[PACA_EXMC + EX_R3] = guest XER
+	 * all other GPRS = free
+	 * PACA[KVM_CR] = guest CR
+	 * PACA[KVM_XER] = guest XER
 	 */
 
 	mtsrr0	r9
 	mtsrr1	r10
 
-	mtspr	SPRN_SPRG_SCRATCH0, r0
+	/* Activate guest mode, so faults get handled by KVM */
+	li	r11, KVM_GUEST_MODE_GUEST
+	stb	r11, PACA_KVM_IN_GUEST(r13)
 
 	/* Remove LPAR shadow entries */
 
@@ -131,20 +129,27 @@
 
 	/* Enter guest */
 
-	mfspr	r0, SPRN_SPRG_SCRATCH0
+	ld	r0, (PACA_KVM_R0)(r13)
+	ld	r1, (PACA_KVM_R1)(r13)
+	ld	r2, (PACA_KVM_R2)(r13)
+	ld	r3, (PACA_KVM_R3)(r13)
+	ld	r4, (PACA_KVM_R4)(r13)
+	ld	r5, (PACA_KVM_R5)(r13)
+	ld	r6, (PACA_KVM_R6)(r13)
+	ld	r7, (PACA_KVM_R7)(r13)
+	ld	r8, (PACA_KVM_R8)(r13)
+	ld	r9, (PACA_KVM_R9)(r13)
+	ld	r10, (PACA_KVM_R10)(r13)
+	ld	r12, (PACA_KVM_R12)(r13)
 
-	ld	r9, (PACA_EXMC+EX_R9)(r13)
-	ld	r10, (PACA_EXMC+EX_R10)(r13)
-	ld	r12, (PACA_EXMC+EX_R12)(r13)
-
-	lwz	r11, (PACA_EXMC+EX_CCR)(r13)
+	lwz	r11, (PACA_KVM_CR)(r13)
 	mtcr	r11
 
-	ld	r11, (PACA_EXMC+EX_R3)(r13)
+	ld	r11, (PACA_KVM_XER)(r13)
 	mtxer	r11
 
-	ld	r11, (PACA_EXMC+EX_R11)(r13)
-	ld	r13, (PACA_EXMC+EX_R13)(r13)
+	ld	r11, (PACA_KVM_R11)(r13)
+	ld	r13, (PACA_KVM_R13)(r13)
 
 	RFI
 kvmppc_handler_trampoline_enter_end:
@@ -162,28 +167,54 @@
 
 	/* Register usage at this point:
 	 *
-	 * SPRG_SCRATCH0 = guest R13
-	 * R01           = host R1
-	 * R02           = host R2
-	 * R10           = guest PC
-	 * R11           = guest MSR
-	 * R12           = exit handler id
-	 * R13           = PACA
-	 * PACA.exmc.CCR  = guest CR
-	 * PACA.exmc.R9  = guest R1
-	 * PACA.exmc.R10 = guest R10
-	 * PACA.exmc.R11 = guest R11
-	 * PACA.exmc.R12 = guest R12
-	 * PACA.exmc.R13 = guest R2
+	 * SPRG_SCRATCH0     = guest R13
+	 * R12               = exit handler id
+	 * R13               = PACA
+	 * PACA.KVM.SCRATCH0 = guest R12
+	 * PACA.KVM.SCRATCH1 = guest CR
 	 *
 	 */
 
 	/* Save registers */
 
-	std	r0, (PACA_EXMC+EX_SRR0)(r13)
-	std	r9, (PACA_EXMC+EX_R3)(r13)
-	std	r10, (PACA_EXMC+EX_LR)(r13)
-	std	r11, (PACA_EXMC+EX_DAR)(r13)
+	std	r0, PACA_KVM_R0(r13)
+	std	r1, PACA_KVM_R1(r13)
+	std	r2, PACA_KVM_R2(r13)
+	std	r3, PACA_KVM_R3(r13)
+	std	r4, PACA_KVM_R4(r13)
+	std	r5, PACA_KVM_R5(r13)
+	std	r6, PACA_KVM_R6(r13)
+	std	r7, PACA_KVM_R7(r13)
+	std	r8, PACA_KVM_R8(r13)
+	std	r9, PACA_KVM_R9(r13)
+	std	r10, PACA_KVM_R10(r13)
+	std	r11, PACA_KVM_R11(r13)
+
+	/* Restore R1/R2 so we can handle faults */
+	ld	r1, PACA_KVM_HOST_R1(r13)
+	ld	r2, PACA_KVM_HOST_R2(r13)
+
+	/* Save guest PC and MSR in GPRs */
+	mfsrr0	r3
+	mfsrr1	r4
+
+	/* Get scratch'ed off registers */
+	mfspr	r9, SPRN_SPRG_SCRATCH0
+	std	r9, PACA_KVM_R13(r13)
+
+	ld	r8, PACA_KVM_SCRATCH0(r13)
+	std	r8, PACA_KVM_R12(r13)
+
+	lwz	r7, PACA_KVM_SCRATCH1(r13)
+	stw	r7, PACA_KVM_CR(r13)
+
+	/* Save more register state  */
+
+	mfxer	r6
+	stw	r6, PACA_KVM_XER(r13)
+
+	mfdar	r5
+	mfdsisr	r6
 
 	/*
 	 * In order for us to easily get the last instruction,
@@ -202,17 +233,28 @@
 
 ld_last_inst:
 	/* Save off the guest instruction we're at */
+
+	/* Set guest mode to 'jump over instruction' so if lwz faults
+	 * we'll just continue at the next IP. */
+	li	r9, KVM_GUEST_MODE_SKIP
+	stb	r9, PACA_KVM_IN_GUEST(r13)
+
 	/*    1) enable paging for data */
 	mfmsr	r9
 	ori	r11, r9, MSR_DR			/* Enable paging for data */
 	mtmsr	r11
 	/*    2) fetch the instruction */
-	lwz	r0, 0(r10)
+	li	r0, KVM_INST_FETCH_FAILED	/* In case lwz faults */
+	lwz	r0, 0(r3)
 	/*    3) disable paging again */
 	mtmsr	r9
 
 no_ld_last_inst:
 
+	/* Unset guest mode */
+	li	r9, KVM_GUEST_MODE_NONE
+	stb	r9, PACA_KVM_IN_GUEST(r13)
+
 	/* Restore bolted entries from the shadow and fix it along the way */
 
 	/* We don't store anything in entry 0, so we don't need to take care of it */
@@ -233,29 +275,27 @@
 
 slb_do_exit:
 
-	/* Restore registers */
-
-	ld	r11, (PACA_EXMC+EX_DAR)(r13)
-	ld	r10, (PACA_EXMC+EX_LR)(r13)
-	ld	r9, (PACA_EXMC+EX_R3)(r13)
-
-	/* Save last inst */
-	stw	r0, (PACA_EXMC+EX_LR)(r13)
-
-	/* Save DAR and DSISR before going to paged mode */
-	mfdar	r0
-	std	r0, (PACA_EXMC+EX_DAR)(r13)
-	mfdsisr	r0
-	stw	r0, (PACA_EXMC+EX_DSISR)(r13)
+	/* Register usage at this point:
+	 *
+	 * R0         = guest last inst
+	 * R1         = host R1
+	 * R2         = host R2
+	 * R3         = guest PC
+	 * R4         = guest MSR
+	 * R5         = guest DAR
+	 * R6         = guest DSISR
+	 * R12        = exit handler id
+	 * R13        = PACA
+	 * PACA.KVM.* = guest *
+	 *
+	 */
 
 	/* RFI into the highmem handler */
-	mfmsr	r0
-	ori	r0, r0, MSR_IR|MSR_DR|MSR_RI	/* Enable paging */
-	mtsrr1	r0
-	ld	r0, PACASAVEDMSR(r13)		/* Highmem handler address */
-	mtsrr0	r0
-
-	mfspr	r0, SPRN_SPRG_SCRATCH0
+	mfmsr	r7
+	ori	r7, r7, MSR_IR|MSR_DR|MSR_RI	/* Enable paging */
+	mtsrr1	r7
+	ld	r8, PACA_KVM_VMHANDLER(r13)	/* Highmem handler address */
+	mtsrr0	r8
 
 	RFI
 kvmppc_handler_trampoline_exit_end:
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 06f5a9e..4d686cc 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -69,10 +69,10 @@
 
 	for (i = 0; i < 32; i += 4) {
 		printk("gpr%02d: %08lx %08lx %08lx %08lx\n", i,
-		       vcpu->arch.gpr[i],
-		       vcpu->arch.gpr[i+1],
-		       vcpu->arch.gpr[i+2],
-		       vcpu->arch.gpr[i+3]);
+		       kvmppc_get_gpr(vcpu, i),
+		       kvmppc_get_gpr(vcpu, i+1),
+		       kvmppc_get_gpr(vcpu, i+2),
+		       kvmppc_get_gpr(vcpu, i+3));
 	}
 }
 
@@ -82,8 +82,32 @@
 	set_bit(priority, &vcpu->arch.pending_exceptions);
 }
 
-void kvmppc_core_queue_program(struct kvm_vcpu *vcpu)
+static void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu,
+                                        ulong dear_flags, ulong esr_flags)
 {
+	vcpu->arch.queued_dear = dear_flags;
+	vcpu->arch.queued_esr = esr_flags;
+	kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
+}
+
+static void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
+                                           ulong dear_flags, ulong esr_flags)
+{
+	vcpu->arch.queued_dear = dear_flags;
+	vcpu->arch.queued_esr = esr_flags;
+	kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE);
+}
+
+static void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu,
+                                           ulong esr_flags)
+{
+	vcpu->arch.queued_esr = esr_flags;
+	kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE);
+}
+
+void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong esr_flags)
+{
+	vcpu->arch.queued_esr = esr_flags;
 	kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM);
 }
 
@@ -97,6 +121,11 @@
 	return test_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions);
 }
 
+void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu)
+{
+	clear_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions);
+}
+
 void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                 struct kvm_interrupt *irq)
 {
@@ -109,14 +138,19 @@
 {
 	int allowed = 0;
 	ulong msr_mask;
+	bool update_esr = false, update_dear = false;
 
 	switch (priority) {
-	case BOOKE_IRQPRIO_PROGRAM:
 	case BOOKE_IRQPRIO_DTLB_MISS:
+	case BOOKE_IRQPRIO_DATA_STORAGE:
+		update_dear = true;
+		/* fall through */
+	case BOOKE_IRQPRIO_INST_STORAGE:
+	case BOOKE_IRQPRIO_PROGRAM:
+		update_esr = true;
+		/* fall through */
 	case BOOKE_IRQPRIO_ITLB_MISS:
 	case BOOKE_IRQPRIO_SYSCALL:
-	case BOOKE_IRQPRIO_DATA_STORAGE:
-	case BOOKE_IRQPRIO_INST_STORAGE:
 	case BOOKE_IRQPRIO_FP_UNAVAIL:
 	case BOOKE_IRQPRIO_SPE_UNAVAIL:
 	case BOOKE_IRQPRIO_SPE_FP_DATA:
@@ -151,6 +185,10 @@
 		vcpu->arch.srr0 = vcpu->arch.pc;
 		vcpu->arch.srr1 = vcpu->arch.msr;
 		vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
+		if (update_esr == true)
+			vcpu->arch.esr = vcpu->arch.queued_esr;
+		if (update_dear == true)
+			vcpu->arch.dear = vcpu->arch.queued_dear;
 		kvmppc_set_msr(vcpu, vcpu->arch.msr & msr_mask);
 
 		clear_bit(priority, &vcpu->arch.pending_exceptions);
@@ -223,8 +261,7 @@
 		if (vcpu->arch.msr & MSR_PR) {
 			/* Program traps generated by user-level software must be handled
 			 * by the guest kernel. */
-			vcpu->arch.esr = vcpu->arch.fault_esr;
-			kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM);
+			kvmppc_core_queue_program(vcpu, vcpu->arch.fault_esr);
 			r = RESUME_GUEST;
 			kvmppc_account_exit(vcpu, USR_PR_INST);
 			break;
@@ -280,16 +317,14 @@
 		break;
 
 	case BOOKE_INTERRUPT_DATA_STORAGE:
-		vcpu->arch.dear = vcpu->arch.fault_dear;
-		vcpu->arch.esr = vcpu->arch.fault_esr;
-		kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE);
+		kvmppc_core_queue_data_storage(vcpu, vcpu->arch.fault_dear,
+		                               vcpu->arch.fault_esr);
 		kvmppc_account_exit(vcpu, DSI_EXITS);
 		r = RESUME_GUEST;
 		break;
 
 	case BOOKE_INTERRUPT_INST_STORAGE:
-		vcpu->arch.esr = vcpu->arch.fault_esr;
-		kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE);
+		kvmppc_core_queue_inst_storage(vcpu, vcpu->arch.fault_esr);
 		kvmppc_account_exit(vcpu, ISI_EXITS);
 		r = RESUME_GUEST;
 		break;
@@ -310,9 +345,9 @@
 		gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
 		if (gtlb_index < 0) {
 			/* The guest didn't have a mapping for it. */
-			kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
-			vcpu->arch.dear = vcpu->arch.fault_dear;
-			vcpu->arch.esr = vcpu->arch.fault_esr;
+			kvmppc_core_queue_dtlb_miss(vcpu,
+			                            vcpu->arch.fault_dear,
+			                            vcpu->arch.fault_esr);
 			kvmppc_mmu_dtlb_miss(vcpu);
 			kvmppc_account_exit(vcpu, DTLB_REAL_MISS_EXITS);
 			r = RESUME_GUEST;
@@ -426,7 +461,7 @@
 {
 	vcpu->arch.pc = 0;
 	vcpu->arch.msr = 0;
-	vcpu->arch.gpr[1] = (16<<20) - 8; /* -8 for the callee-save LR slot */
+	kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */
 
 	vcpu->arch.shadow_pid = 1;
 
@@ -444,10 +479,10 @@
 	int i;
 
 	regs->pc = vcpu->arch.pc;
-	regs->cr = vcpu->arch.cr;
+	regs->cr = kvmppc_get_cr(vcpu);
 	regs->ctr = vcpu->arch.ctr;
 	regs->lr = vcpu->arch.lr;
-	regs->xer = vcpu->arch.xer;
+	regs->xer = kvmppc_get_xer(vcpu);
 	regs->msr = vcpu->arch.msr;
 	regs->srr0 = vcpu->arch.srr0;
 	regs->srr1 = vcpu->arch.srr1;
@@ -461,7 +496,7 @@
 	regs->sprg7 = vcpu->arch.sprg6;
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
-		regs->gpr[i] = vcpu->arch.gpr[i];
+		regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
 
 	return 0;
 }
@@ -471,10 +506,10 @@
 	int i;
 
 	vcpu->arch.pc = regs->pc;
-	vcpu->arch.cr = regs->cr;
+	kvmppc_set_cr(vcpu, regs->cr);
 	vcpu->arch.ctr = regs->ctr;
 	vcpu->arch.lr = regs->lr;
-	vcpu->arch.xer = regs->xer;
+	kvmppc_set_xer(vcpu, regs->xer);
 	kvmppc_set_msr(vcpu, regs->msr);
 	vcpu->arch.srr0 = regs->srr0;
 	vcpu->arch.srr1 = regs->srr1;
@@ -486,8 +521,8 @@
 	vcpu->arch.sprg6 = regs->sprg5;
 	vcpu->arch.sprg7 = regs->sprg6;
 
-	for (i = 0; i < ARRAY_SIZE(vcpu->arch.gpr); i++)
-		vcpu->arch.gpr[i] = regs->gpr[i];
+	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
+		kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
 
 	return 0;
 }
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index aebc65e..cbc790e 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -62,20 +62,20 @@
 
 		case OP_31_XOP_MFMSR:
 			rt = get_rt(inst);
-			vcpu->arch.gpr[rt] = vcpu->arch.msr;
+			kvmppc_set_gpr(vcpu, rt, vcpu->arch.msr);
 			kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS);
 			break;
 
 		case OP_31_XOP_MTMSR:
 			rs = get_rs(inst);
 			kvmppc_set_exit_type(vcpu, EMULATED_MTMSR_EXITS);
-			kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]);
+			kvmppc_set_msr(vcpu, kvmppc_get_gpr(vcpu, rs));
 			break;
 
 		case OP_31_XOP_WRTEE:
 			rs = get_rs(inst);
 			vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
-							 | (vcpu->arch.gpr[rs] & MSR_EE);
+					| (kvmppc_get_gpr(vcpu, rs) & MSR_EE);
 			kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
 			break;
 
@@ -101,22 +101,23 @@
 int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
 {
 	int emulated = EMULATE_DONE;
+	ulong spr_val = kvmppc_get_gpr(vcpu, rs);
 
 	switch (sprn) {
 	case SPRN_DEAR:
-		vcpu->arch.dear = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.dear = spr_val; break;
 	case SPRN_ESR:
-		vcpu->arch.esr = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.esr = spr_val; break;
 	case SPRN_DBCR0:
-		vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.dbcr0 = spr_val; break;
 	case SPRN_DBCR1:
-		vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.dbcr1 = spr_val; break;
 	case SPRN_DBSR:
-		vcpu->arch.dbsr &= ~vcpu->arch.gpr[rs]; break;
+		vcpu->arch.dbsr &= ~spr_val; break;
 	case SPRN_TSR:
-		vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break;
+		vcpu->arch.tsr &= ~spr_val; break;
 	case SPRN_TCR:
-		vcpu->arch.tcr = vcpu->arch.gpr[rs];
+		vcpu->arch.tcr = spr_val;
 		kvmppc_emulate_dec(vcpu);
 		break;
 
@@ -124,64 +125,64 @@
 	 * loaded into the real SPRGs when resuming the
 	 * guest. */
 	case SPRN_SPRG4:
-		vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.sprg4 = spr_val; break;
 	case SPRN_SPRG5:
-		vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.sprg5 = spr_val; break;
 	case SPRN_SPRG6:
-		vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.sprg6 = spr_val; break;
 	case SPRN_SPRG7:
-		vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break;
+		vcpu->arch.sprg7 = spr_val; break;
 
 	case SPRN_IVPR:
-		vcpu->arch.ivpr = vcpu->arch.gpr[rs];
+		vcpu->arch.ivpr = spr_val;
 		break;
 	case SPRN_IVOR0:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = spr_val;
 		break;
 	case SPRN_IVOR1:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = spr_val;
 		break;
 	case SPRN_IVOR2:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = spr_val;
 		break;
 	case SPRN_IVOR3:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = spr_val;
 		break;
 	case SPRN_IVOR4:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = spr_val;
 		break;
 	case SPRN_IVOR5:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = spr_val;
 		break;
 	case SPRN_IVOR6:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = spr_val;
 		break;
 	case SPRN_IVOR7:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = spr_val;
 		break;
 	case SPRN_IVOR8:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = spr_val;
 		break;
 	case SPRN_IVOR9:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = spr_val;
 		break;
 	case SPRN_IVOR10:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = spr_val;
 		break;
 	case SPRN_IVOR11:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = spr_val;
 		break;
 	case SPRN_IVOR12:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = spr_val;
 		break;
 	case SPRN_IVOR13:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = spr_val;
 		break;
 	case SPRN_IVOR14:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = spr_val;
 		break;
 	case SPRN_IVOR15:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = spr_val;
 		break;
 
 	default:
@@ -197,65 +198,65 @@
 
 	switch (sprn) {
 	case SPRN_IVPR:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivpr); break;
 	case SPRN_DEAR:
-		vcpu->arch.gpr[rt] = vcpu->arch.dear; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear); break;
 	case SPRN_ESR:
-		vcpu->arch.gpr[rt] = vcpu->arch.esr; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.esr); break;
 	case SPRN_DBCR0:
-		vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr0); break;
 	case SPRN_DBCR1:
-		vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr1); break;
 	case SPRN_DBSR:
-		vcpu->arch.gpr[rt] = vcpu->arch.dbsr; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbsr); break;
 
 	case SPRN_IVOR0:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]);
 		break;
 	case SPRN_IVOR1:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK]);
 		break;
 	case SPRN_IVOR2:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE]);
 		break;
 	case SPRN_IVOR3:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE]);
 		break;
 	case SPRN_IVOR4:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL]);
 		break;
 	case SPRN_IVOR5:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT]);
 		break;
 	case SPRN_IVOR6:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM]);
 		break;
 	case SPRN_IVOR7:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL]);
 		break;
 	case SPRN_IVOR8:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL]);
 		break;
 	case SPRN_IVOR9:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL]);
 		break;
 	case SPRN_IVOR10:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER]);
 		break;
 	case SPRN_IVOR11:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FIT];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_FIT]);
 		break;
 	case SPRN_IVOR12:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG]);
 		break;
 	case SPRN_IVOR13:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]);
 		break;
 	case SPRN_IVOR14:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]);
 		break;
 	case SPRN_IVOR15:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]);
 		break;
 
 	default:
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c
index 64949ee..efa1198 100644
--- a/arch/powerpc/kvm/e500.c
+++ b/arch/powerpc/kvm/e500.c
@@ -60,6 +60,12 @@
 
 	kvmppc_e500_tlb_setup(vcpu_e500);
 
+	/* Registers init */
+	vcpu->arch.pvr = mfspr(SPRN_PVR);
+
+	/* Since booke kvm only support one core, update all vcpus' PIR to 0 */
+	vcpu->vcpu_id = 0;
+
 	return 0;
 }
 
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index be95b8d..8e3edfb 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -74,54 +74,59 @@
 {
 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 	int emulated = EMULATE_DONE;
+	ulong spr_val = kvmppc_get_gpr(vcpu, rs);
 
 	switch (sprn) {
 	case SPRN_PID:
 		vcpu_e500->pid[0] = vcpu->arch.shadow_pid =
-			vcpu->arch.pid = vcpu->arch.gpr[rs];
+			vcpu->arch.pid = spr_val;
 		break;
 	case SPRN_PID1:
-		vcpu_e500->pid[1] = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->pid[1] = spr_val; break;
 	case SPRN_PID2:
-		vcpu_e500->pid[2] = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->pid[2] = spr_val; break;
 	case SPRN_MAS0:
-		vcpu_e500->mas0 = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->mas0 = spr_val; break;
 	case SPRN_MAS1:
-		vcpu_e500->mas1 = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->mas1 = spr_val; break;
 	case SPRN_MAS2:
-		vcpu_e500->mas2 = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->mas2 = spr_val; break;
 	case SPRN_MAS3:
-		vcpu_e500->mas3 = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->mas3 = spr_val; break;
 	case SPRN_MAS4:
-		vcpu_e500->mas4 = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->mas4 = spr_val; break;
 	case SPRN_MAS6:
-		vcpu_e500->mas6 = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->mas6 = spr_val; break;
 	case SPRN_MAS7:
-		vcpu_e500->mas7 = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->mas7 = spr_val; break;
+	case SPRN_L1CSR0:
+		vcpu_e500->l1csr0 = spr_val;
+		vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC);
+		break;
 	case SPRN_L1CSR1:
-		vcpu_e500->l1csr1 = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->l1csr1 = spr_val; break;
 	case SPRN_HID0:
-		vcpu_e500->hid0 = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->hid0 = spr_val; break;
 	case SPRN_HID1:
-		vcpu_e500->hid1 = vcpu->arch.gpr[rs]; break;
+		vcpu_e500->hid1 = spr_val; break;
 
 	case SPRN_MMUCSR0:
 		emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500,
-				vcpu->arch.gpr[rs]);
+				spr_val);
 		break;
 
 	/* extra exceptions */
 	case SPRN_IVOR32:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
 		break;
 	case SPRN_IVOR33:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = spr_val;
 		break;
 	case SPRN_IVOR34:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val;
 		break;
 	case SPRN_IVOR35:
-		vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = vcpu->arch.gpr[rs];
+		vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val;
 		break;
 
 	default:
@@ -138,63 +143,57 @@
 
 	switch (sprn) {
 	case SPRN_PID:
-		vcpu->arch.gpr[rt] = vcpu_e500->pid[0]; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[0]); break;
 	case SPRN_PID1:
-		vcpu->arch.gpr[rt] = vcpu_e500->pid[1]; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[1]); break;
 	case SPRN_PID2:
-		vcpu->arch.gpr[rt] = vcpu_e500->pid[2]; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[2]); break;
 	case SPRN_MAS0:
-		vcpu->arch.gpr[rt] = vcpu_e500->mas0; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas0); break;
 	case SPRN_MAS1:
-		vcpu->arch.gpr[rt] = vcpu_e500->mas1; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas1); break;
 	case SPRN_MAS2:
-		vcpu->arch.gpr[rt] = vcpu_e500->mas2; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas2); break;
 	case SPRN_MAS3:
-		vcpu->arch.gpr[rt] = vcpu_e500->mas3; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas3); break;
 	case SPRN_MAS4:
-		vcpu->arch.gpr[rt] = vcpu_e500->mas4; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas4); break;
 	case SPRN_MAS6:
-		vcpu->arch.gpr[rt] = vcpu_e500->mas6; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas6); break;
 	case SPRN_MAS7:
-		vcpu->arch.gpr[rt] = vcpu_e500->mas7; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas7); break;
 
 	case SPRN_TLB0CFG:
-		vcpu->arch.gpr[rt] = mfspr(SPRN_TLB0CFG);
-		vcpu->arch.gpr[rt] &= ~0xfffUL;
-		vcpu->arch.gpr[rt] |= vcpu_e500->guest_tlb_size[0];
-		break;
-
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->tlb0cfg); break;
 	case SPRN_TLB1CFG:
-		vcpu->arch.gpr[rt] = mfspr(SPRN_TLB1CFG);
-		vcpu->arch.gpr[rt] &= ~0xfffUL;
-		vcpu->arch.gpr[rt] |= vcpu_e500->guest_tlb_size[1];
-		break;
-
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->tlb1cfg); break;
+	case SPRN_L1CSR0:
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr0); break;
 	case SPRN_L1CSR1:
-		vcpu->arch.gpr[rt] = vcpu_e500->l1csr1; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr1); break;
 	case SPRN_HID0:
-		vcpu->arch.gpr[rt] = vcpu_e500->hid0; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid0); break;
 	case SPRN_HID1:
-		vcpu->arch.gpr[rt] = vcpu_e500->hid1; break;
+		kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid1); break;
 
 	case SPRN_MMUCSR0:
-		vcpu->arch.gpr[rt] = 0; break;
+		kvmppc_set_gpr(vcpu, rt, 0); break;
 
 	case SPRN_MMUCFG:
-		vcpu->arch.gpr[rt] = mfspr(SPRN_MMUCFG); break;
+		kvmppc_set_gpr(vcpu, rt, mfspr(SPRN_MMUCFG)); break;
 
 	/* extra exceptions */
 	case SPRN_IVOR32:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]);
 		break;
 	case SPRN_IVOR33:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]);
 		break;
 	case SPRN_IVOR34:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]);
 		break;
 	case SPRN_IVOR35:
-		vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR];
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]);
 		break;
 	default:
 		emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt);
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index fb1e1dc..0d772e6 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -417,7 +417,7 @@
 	int esel, tlbsel;
 	gva_t ea;
 
-	ea = ((ra) ? vcpu->arch.gpr[ra] : 0) + vcpu->arch.gpr[rb];
+	ea = ((ra) ? kvmppc_get_gpr(vcpu, ra) : 0) + kvmppc_get_gpr(vcpu, rb);
 
 	ia = (ea >> 2) & 0x1;
 
@@ -470,7 +470,7 @@
 	struct tlbe *gtlbe = NULL;
 	gva_t ea;
 
-	ea = vcpu->arch.gpr[rb];
+	ea = kvmppc_get_gpr(vcpu, rb);
 
 	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
 		esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
@@ -728,6 +728,12 @@
 	if (vcpu_e500->shadow_pages[1] == NULL)
 		goto err_out_page0;
 
+	/* Init TLB configuration register */
+	vcpu_e500->tlb0cfg = mfspr(SPRN_TLB0CFG) & ~0xfffUL;
+	vcpu_e500->tlb0cfg |= vcpu_e500->guest_tlb_size[0];
+	vcpu_e500->tlb1cfg = mfspr(SPRN_TLB1CFG) & ~0xfffUL;
+	vcpu_e500->tlb1cfg |= vcpu_e500->guest_tlb_size[1];
+
 	return 0;
 
 err_out_page0:
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 4a9ac66..cb72a65 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -83,6 +83,9 @@
 
 	pr_debug("mtDEC: %x\n", vcpu->arch.dec);
 #ifdef CONFIG_PPC64
+	/* mtdec lowers the interrupt line when positive. */
+	kvmppc_core_dequeue_dec(vcpu);
+
 	/* POWER4+ triggers a dec interrupt if the value is < 0 */
 	if (vcpu->arch.dec & 0x80000000) {
 		hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
@@ -140,14 +143,18 @@
 
 	pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
 
+	/* Try again next time */
+	if (inst == KVM_INST_FETCH_FAILED)
+		return EMULATE_DONE;
+
 	switch (get_op(inst)) {
 	case OP_TRAP:
 #ifdef CONFIG_PPC64
 	case OP_TRAP_64:
+		kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP);
 #else
-		vcpu->arch.esr |= ESR_PTR;
+		kvmppc_core_queue_program(vcpu, vcpu->arch.esr | ESR_PTR);
 #endif
-		kvmppc_core_queue_program(vcpu);
 		advance = 0;
 		break;
 
@@ -167,14 +174,14 @@
 		case OP_31_XOP_STWX:
 			rs = get_rs(inst);
 			emulated = kvmppc_handle_store(run, vcpu,
-			                               vcpu->arch.gpr[rs],
+						       kvmppc_get_gpr(vcpu, rs),
 			                               4, 1);
 			break;
 
 		case OP_31_XOP_STBX:
 			rs = get_rs(inst);
 			emulated = kvmppc_handle_store(run, vcpu,
-			                               vcpu->arch.gpr[rs],
+						       kvmppc_get_gpr(vcpu, rs),
 			                               1, 1);
 			break;
 
@@ -183,14 +190,14 @@
 			ra = get_ra(inst);
 			rb = get_rb(inst);
 
-			ea = vcpu->arch.gpr[rb];
+			ea = kvmppc_get_gpr(vcpu, rb);
 			if (ra)
-				ea += vcpu->arch.gpr[ra];
+				ea += kvmppc_get_gpr(vcpu, ra);
 
 			emulated = kvmppc_handle_store(run, vcpu,
-			                               vcpu->arch.gpr[rs],
+						       kvmppc_get_gpr(vcpu, rs),
 			                               1, 1);
-			vcpu->arch.gpr[rs] = ea;
+			kvmppc_set_gpr(vcpu, rs, ea);
 			break;
 
 		case OP_31_XOP_LHZX:
@@ -203,12 +210,12 @@
 			ra = get_ra(inst);
 			rb = get_rb(inst);
 
-			ea = vcpu->arch.gpr[rb];
+			ea = kvmppc_get_gpr(vcpu, rb);
 			if (ra)
-				ea += vcpu->arch.gpr[ra];
+				ea += kvmppc_get_gpr(vcpu, ra);
 
 			emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
-			vcpu->arch.gpr[ra] = ea;
+			kvmppc_set_gpr(vcpu, ra, ea);
 			break;
 
 		case OP_31_XOP_MFSPR:
@@ -217,47 +224,49 @@
 
 			switch (sprn) {
 			case SPRN_SRR0:
-				vcpu->arch.gpr[rt] = vcpu->arch.srr0; break;
+				kvmppc_set_gpr(vcpu, rt, vcpu->arch.srr0); break;
 			case SPRN_SRR1:
-				vcpu->arch.gpr[rt] = vcpu->arch.srr1; break;
+				kvmppc_set_gpr(vcpu, rt, vcpu->arch.srr1); break;
 			case SPRN_PVR:
-				vcpu->arch.gpr[rt] = vcpu->arch.pvr; break;
+				kvmppc_set_gpr(vcpu, rt, vcpu->arch.pvr); break;
 			case SPRN_PIR:
-				vcpu->arch.gpr[rt] = vcpu->vcpu_id; break;
+				kvmppc_set_gpr(vcpu, rt, vcpu->vcpu_id); break;
 			case SPRN_MSSSR0:
-				vcpu->arch.gpr[rt] = 0; break;
+				kvmppc_set_gpr(vcpu, rt, 0); break;
 
 			/* Note: mftb and TBRL/TBWL are user-accessible, so
 			 * the guest can always access the real TB anyways.
 			 * In fact, we probably will never see these traps. */
 			case SPRN_TBWL:
-				vcpu->arch.gpr[rt] = get_tb() >> 32; break;
+				kvmppc_set_gpr(vcpu, rt, get_tb() >> 32); break;
 			case SPRN_TBWU:
-				vcpu->arch.gpr[rt] = get_tb(); break;
+				kvmppc_set_gpr(vcpu, rt, get_tb()); break;
 
 			case SPRN_SPRG0:
-				vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break;
+				kvmppc_set_gpr(vcpu, rt, vcpu->arch.sprg0); break;
 			case SPRN_SPRG1:
-				vcpu->arch.gpr[rt] = vcpu->arch.sprg1; break;
+				kvmppc_set_gpr(vcpu, rt, vcpu->arch.sprg1); break;
 			case SPRN_SPRG2:
-				vcpu->arch.gpr[rt] = vcpu->arch.sprg2; break;
+				kvmppc_set_gpr(vcpu, rt, vcpu->arch.sprg2); break;
 			case SPRN_SPRG3:
-				vcpu->arch.gpr[rt] = vcpu->arch.sprg3; break;
+				kvmppc_set_gpr(vcpu, rt, vcpu->arch.sprg3); break;
 			/* Note: SPRG4-7 are user-readable, so we don't get
 			 * a trap. */
 
 			case SPRN_DEC:
 			{
 				u64 jd = get_tb() - vcpu->arch.dec_jiffies;
-				vcpu->arch.gpr[rt] = vcpu->arch.dec - jd;
-				pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n", vcpu->arch.dec, jd, vcpu->arch.gpr[rt]);
+				kvmppc_set_gpr(vcpu, rt, vcpu->arch.dec - jd);
+				pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n",
+					 vcpu->arch.dec, jd,
+					 kvmppc_get_gpr(vcpu, rt));
 				break;
 			}
 			default:
 				emulated = kvmppc_core_emulate_mfspr(vcpu, sprn, rt);
 				if (emulated == EMULATE_FAIL) {
 					printk("mfspr: unknown spr %x\n", sprn);
-					vcpu->arch.gpr[rt] = 0;
+					kvmppc_set_gpr(vcpu, rt, 0);
 				}
 				break;
 			}
@@ -269,7 +278,7 @@
 			rb = get_rb(inst);
 
 			emulated = kvmppc_handle_store(run, vcpu,
-			                               vcpu->arch.gpr[rs],
+						       kvmppc_get_gpr(vcpu, rs),
 			                               2, 1);
 			break;
 
@@ -278,14 +287,14 @@
 			ra = get_ra(inst);
 			rb = get_rb(inst);
 
-			ea = vcpu->arch.gpr[rb];
+			ea = kvmppc_get_gpr(vcpu, rb);
 			if (ra)
-				ea += vcpu->arch.gpr[ra];
+				ea += kvmppc_get_gpr(vcpu, ra);
 
 			emulated = kvmppc_handle_store(run, vcpu,
-			                               vcpu->arch.gpr[rs],
+						       kvmppc_get_gpr(vcpu, rs),
 			                               2, 1);
-			vcpu->arch.gpr[ra] = ea;
+			kvmppc_set_gpr(vcpu, ra, ea);
 			break;
 
 		case OP_31_XOP_MTSPR:
@@ -293,9 +302,9 @@
 			rs = get_rs(inst);
 			switch (sprn) {
 			case SPRN_SRR0:
-				vcpu->arch.srr0 = vcpu->arch.gpr[rs]; break;
+				vcpu->arch.srr0 = kvmppc_get_gpr(vcpu, rs); break;
 			case SPRN_SRR1:
-				vcpu->arch.srr1 = vcpu->arch.gpr[rs]; break;
+				vcpu->arch.srr1 = kvmppc_get_gpr(vcpu, rs); break;
 
 			/* XXX We need to context-switch the timebase for
 			 * watchdog and FIT. */
@@ -305,18 +314,18 @@
 			case SPRN_MSSSR0: break;
 
 			case SPRN_DEC:
-				vcpu->arch.dec = vcpu->arch.gpr[rs];
+				vcpu->arch.dec = kvmppc_get_gpr(vcpu, rs);
 				kvmppc_emulate_dec(vcpu);
 				break;
 
 			case SPRN_SPRG0:
-				vcpu->arch.sprg0 = vcpu->arch.gpr[rs]; break;
+				vcpu->arch.sprg0 = kvmppc_get_gpr(vcpu, rs); break;
 			case SPRN_SPRG1:
-				vcpu->arch.sprg1 = vcpu->arch.gpr[rs]; break;
+				vcpu->arch.sprg1 = kvmppc_get_gpr(vcpu, rs); break;
 			case SPRN_SPRG2:
-				vcpu->arch.sprg2 = vcpu->arch.gpr[rs]; break;
+				vcpu->arch.sprg2 = kvmppc_get_gpr(vcpu, rs); break;
 			case SPRN_SPRG3:
-				vcpu->arch.sprg3 = vcpu->arch.gpr[rs]; break;
+				vcpu->arch.sprg3 = kvmppc_get_gpr(vcpu, rs); break;
 
 			default:
 				emulated = kvmppc_core_emulate_mtspr(vcpu, sprn, rs);
@@ -348,7 +357,7 @@
 			rb = get_rb(inst);
 
 			emulated = kvmppc_handle_store(run, vcpu,
-			                               vcpu->arch.gpr[rs],
+						       kvmppc_get_gpr(vcpu, rs),
 			                               4, 0);
 			break;
 
@@ -363,7 +372,7 @@
 			rb = get_rb(inst);
 
 			emulated = kvmppc_handle_store(run, vcpu,
-			                               vcpu->arch.gpr[rs],
+						       kvmppc_get_gpr(vcpu, rs),
 			                               2, 0);
 			break;
 
@@ -382,7 +391,7 @@
 		ra = get_ra(inst);
 		rt = get_rt(inst);
 		emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
-		vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
 		break;
 
 	case OP_LBZ:
@@ -394,35 +403,39 @@
 		ra = get_ra(inst);
 		rt = get_rt(inst);
 		emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
-		vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
 		break;
 
 	case OP_STW:
 		rs = get_rs(inst);
-		emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
 		                               4, 1);
 		break;
 
 	case OP_STWU:
 		ra = get_ra(inst);
 		rs = get_rs(inst);
-		emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
 		                               4, 1);
-		vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
 		break;
 
 	case OP_STB:
 		rs = get_rs(inst);
-		emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
 		                               1, 1);
 		break;
 
 	case OP_STBU:
 		ra = get_ra(inst);
 		rs = get_rs(inst);
-		emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
 		                               1, 1);
-		vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
 		break;
 
 	case OP_LHZ:
@@ -434,21 +447,23 @@
 		ra = get_ra(inst);
 		rt = get_rt(inst);
 		emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
-		vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
 		break;
 
 	case OP_STH:
 		rs = get_rs(inst);
-		emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
 		                               2, 1);
 		break;
 
 	case OP_STHU:
 		ra = get_ra(inst);
 		rs = get_rs(inst);
-		emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
+		emulated = kvmppc_handle_store(run, vcpu,
+					       kvmppc_get_gpr(vcpu, rs),
 		                               2, 1);
-		vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
+		kvmppc_set_gpr(vcpu, ra, vcpu->arch.paddr_accessed);
 		break;
 
 	default:
@@ -461,6 +476,7 @@
 			advance = 0;
 			printk(KERN_ERR "Couldn't emulate instruction 0x%08x "
 			       "(op %d xop %d)\n", inst, get_op(inst), get_xop(inst));
+			kvmppc_core_queue_program(vcpu, 0);
 		}
 	}
 
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index f06cf93..51aedd7 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -137,6 +137,7 @@
 {
 	kvmppc_free_vcpus(kvm);
 	kvm_free_physmem(kvm);
+	cleanup_srcu_struct(&kvm->srcu);
 	kfree(kvm);
 }
 
@@ -165,14 +166,24 @@
 	return -EINVAL;
 }
 
-int kvm_arch_set_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem,
-                               struct kvm_memory_slot old,
-                               int user_alloc)
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+                                   struct kvm_memory_slot *memslot,
+                                   struct kvm_memory_slot old,
+                                   struct kvm_userspace_memory_region *mem,
+                                   int user_alloc)
 {
 	return 0;
 }
 
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+               struct kvm_userspace_memory_region *mem,
+               struct kvm_memory_slot old,
+               int user_alloc)
+{
+       return;
+}
+
+
 void kvm_arch_flush_shadow(struct kvm *kvm)
 {
 }
@@ -260,34 +271,35 @@
 static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu,
                                      struct kvm_run *run)
 {
-	ulong *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
-	*gpr = run->dcr.data;
+	kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, run->dcr.data);
 }
 
 static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
                                       struct kvm_run *run)
 {
-	ulong *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
+	ulong gpr;
 
-	if (run->mmio.len > sizeof(*gpr)) {
+	if (run->mmio.len > sizeof(gpr)) {
 		printk(KERN_ERR "bad MMIO length: %d\n", run->mmio.len);
 		return;
 	}
 
 	if (vcpu->arch.mmio_is_bigendian) {
 		switch (run->mmio.len) {
-		case 4: *gpr = *(u32 *)run->mmio.data; break;
-		case 2: *gpr = *(u16 *)run->mmio.data; break;
-		case 1: *gpr = *(u8 *)run->mmio.data; break;
+		case 4: gpr = *(u32 *)run->mmio.data; break;
+		case 2: gpr = *(u16 *)run->mmio.data; break;
+		case 1: gpr = *(u8 *)run->mmio.data; break;
 		}
 	} else {
 		/* Convert BE data from userland back to LE. */
 		switch (run->mmio.len) {
-		case 4: *gpr = ld_le32((u32 *)run->mmio.data); break;
-		case 2: *gpr = ld_le16((u16 *)run->mmio.data); break;
-		case 1: *gpr = *(u8 *)run->mmio.data; break;
+		case 4: gpr = ld_le32((u32 *)run->mmio.data); break;
+		case 2: gpr = ld_le16((u16 *)run->mmio.data); break;
+		case 1: gpr = *(u8 *)run->mmio.data; break;
 		}
 	}
+
+	kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);
 }
 
 int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 4ec900a..b1dbd9e 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -47,7 +47,7 @@
 #include "mmu_decl.h"
 
 #if defined(CONFIG_KERNEL_START_BOOL) || defined(CONFIG_LOWMEM_SIZE_BOOL)
-/* The ammount of lowmem must be within 0xF0000000 - KERNELBASE. */
+/* The amount of lowmem must be within 0xF0000000 - KERNELBASE. */
 #if (CONFIG_LOWMEM_SIZE > (0xF0000000 - PAGE_OFFSET))
 #error "You must adjust CONFIG_LOWMEM_SIZE or CONFIG_START_KERNEL"
 #endif
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index b037d95..64c0022 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -451,7 +451,7 @@
 	nid = of_node_to_nid_single(cpu);
 
 	if (nid < 0 || !node_online(nid))
-		nid = any_online_node(NODE_MASK_ALL);
+		nid = first_online_node;
 out:
 	map_cpu_to_node(lcpu, nid);
 
@@ -1114,7 +1114,7 @@
 	int nid, found = 0;
 
 	if (!numa_enabled || (min_common_depth < 0))
-		return any_online_node(NODE_MASK_ALL);
+		return first_online_node;
 
 	memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
 	if (memory) {
@@ -1125,7 +1125,7 @@
 	}
 
 	if (nid < 0 || !node_online(nid))
-		nid = any_online_node(NODE_MASK_ALL);
+		nid = first_online_node;
 
 	if (NODE_DATA(nid)->node_spanned_pages)
 		return nid;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
index 6f8ebe1..072b948 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
@@ -553,7 +553,7 @@
 	return 0;
 }
 
-static struct watchdog_info mpc5200_wdt_info = {
+static const struct watchdog_info mpc5200_wdt_info = {
 	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 	.identity	= WDT_IDENTITY,
 };
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
index 9d962d7..d4a09f8 100644
--- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
+++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
@@ -24,7 +24,7 @@
 
 #include "pq2.h"
 
-static DEFINE_SPINLOCK(pci_pic_lock);
+static DEFINE_RAW_SPINLOCK(pci_pic_lock);
 
 struct pq2ads_pci_pic {
 	struct device_node *node;
@@ -45,12 +45,12 @@
 
 	if (irq != -1) {
 		unsigned long flags;
-		spin_lock_irqsave(&pci_pic_lock, flags);
+		raw_spin_lock_irqsave(&pci_pic_lock, flags);
 
 		setbits32(&priv->regs->mask, 1 << irq);
 		mb();
 
-		spin_unlock_irqrestore(&pci_pic_lock, flags);
+		raw_spin_unlock_irqrestore(&pci_pic_lock, flags);
 	}
 }
 
@@ -62,9 +62,9 @@
 	if (irq != -1) {
 		unsigned long flags;
 
-		spin_lock_irqsave(&pci_pic_lock, flags);
+		raw_spin_lock_irqsave(&pci_pic_lock, flags);
 		clrbits32(&priv->regs->mask, 1 << irq);
-		spin_unlock_irqrestore(&pci_pic_lock, flags);
+		raw_spin_unlock_irqrestore(&pci_pic_lock, flags);
 	}
 }
 
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
index 42e87f0..d48527f 100644
--- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
+++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
@@ -50,7 +50,7 @@
 
 #define socrates_fpga_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
 
-static DEFINE_SPINLOCK(socrates_fpga_pic_lock);
+static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock);
 
 static void __iomem *socrates_fpga_pic_iobase;
 static struct irq_host *socrates_fpga_pic_irq_host;
@@ -80,9 +80,9 @@
 	if (i == 3)
 		return NO_IRQ;
 
-	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	cause = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i));
-	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 	for (i = SOCRATES_FPGA_NUM_IRQS - 1; i >= 0; i--) {
 		if (cause >> (i + 16))
 			break;
@@ -116,12 +116,12 @@
 	hwirq = socrates_fpga_irq_to_hw(virq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
-	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
 		& SOCRATES_FPGA_IRQ_MASK;
 	mask |= (1 << (hwirq + 16));
 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
-	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
 static void socrates_fpga_pic_mask(unsigned int virq)
@@ -134,12 +134,12 @@
 	hwirq = socrates_fpga_irq_to_hw(virq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
-	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
 		& SOCRATES_FPGA_IRQ_MASK;
 	mask &= ~(1 << hwirq);
 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
-	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
 static void socrates_fpga_pic_mask_ack(unsigned int virq)
@@ -152,13 +152,13 @@
 	hwirq = socrates_fpga_irq_to_hw(virq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
-	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
 		& SOCRATES_FPGA_IRQ_MASK;
 	mask &= ~(1 << hwirq);
 	mask |= (1 << (hwirq + 16));
 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
-	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
 static void socrates_fpga_pic_unmask(unsigned int virq)
@@ -171,12 +171,12 @@
 	hwirq = socrates_fpga_irq_to_hw(virq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
-	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
 		& SOCRATES_FPGA_IRQ_MASK;
 	mask |= (1 << hwirq);
 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
-	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
 static void socrates_fpga_pic_eoi(unsigned int virq)
@@ -189,12 +189,12 @@
 	hwirq = socrates_fpga_irq_to_hw(virq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
-	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
 		& SOCRATES_FPGA_IRQ_MASK;
 	mask |= (1 << (hwirq + 16));
 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
-	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
 static int socrates_fpga_pic_set_type(unsigned int virq,
@@ -220,14 +220,14 @@
 	default:
 		return -EINVAL;
 	}
-	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	mask = socrates_fpga_pic_read(FPGA_PIC_IRQCFG);
 	if (polarity)
 		mask |= (1 << hwirq);
 	else
 		mask &= ~(1 << hwirq);
 	socrates_fpga_pic_write(FPGA_PIC_IRQCFG, mask);
-	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 	return 0;
 }
 
@@ -314,14 +314,14 @@
 
 	socrates_fpga_pic_iobase = of_iomap(pic, 0);
 
-	spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
+	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(0),
 			SOCRATES_FPGA_IRQ_MASK << 16);
 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(1),
 			SOCRATES_FPGA_IRQ_MASK << 16);
 	socrates_fpga_pic_write(FPGA_PIC_IRQMASK(2),
 			SOCRATES_FPGA_IRQ_MASK << 16);
-	spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 
 	pr_info("FPGA PIC: Setting up Socrates FPGA PIC\n");
 }
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 2bbfd53..fbe9f36 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -33,32 +33,32 @@
 	  This option enables support for the MPC8610 HPCD board.
 
 config GEF_PPC9A
-	bool "GE Fanuc PPC9A"
+	bool "GE PPC9A"
 	select DEFAULT_UIMAGE
 	select MMIO_NVRAM
 	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	help
-	  This option enables support for GE Fanuc's PPC9A.
+	  This option enables support for the GE PPC9A.
 
 config GEF_SBC310
-	bool "GE Fanuc SBC310"
+	bool "GE SBC310"
 	select DEFAULT_UIMAGE
 	select MMIO_NVRAM
 	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	help
-	  This option enables support for GE Fanuc's SBC310.
+	  This option enables support for the GE SBC310.
 
 config GEF_SBC610
-	bool "GE Fanuc SBC610"
+	bool "GE SBC610"
 	select DEFAULT_UIMAGE
 	select MMIO_NVRAM
 	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
 	select HAS_RAPIDIO
 	help
-	  This option enables support for GE Fanuc's SBC610.
+	  This option enables support for the GE SBC610.
 
 endif
 
diff --git a/arch/powerpc/platforms/86xx/gef_gpio.c b/arch/powerpc/platforms/86xx/gef_gpio.c
index b2ea887..11f7b2b 100644
--- a/arch/powerpc/platforms/86xx/gef_gpio.c
+++ b/arch/powerpc/platforms/86xx/gef_gpio.c
@@ -1,9 +1,9 @@
 /*
- * Driver for GE Fanuc's FPGA based GPIO pins
+ * Driver for GE FPGA based GPIO
  *
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ * Author: Martyn Welch <martyn.welch@ge.com>
  *
- * 2008 (c) GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * 2008 (c) GE Intelligent Platforms Embedded Systems, 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
@@ -164,6 +164,6 @@
 };
 arch_initcall(gef_gpio_init);
 
-MODULE_DESCRIPTION("GE Fanuc I/O FPGA GPIO driver");
-MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com");
+MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
 MODULE_LICENSE("GPL");
diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c
index 0110a87..6df9e25 100644
--- a/arch/powerpc/platforms/86xx/gef_pic.c
+++ b/arch/powerpc/platforms/86xx/gef_pic.c
@@ -1,9 +1,9 @@
 /*
- * Interrupt handling for GE Fanuc's FPGA based PIC
+ * Interrupt handling for GE FPGA based PIC
  *
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ * Author: Martyn Welch <martyn.welch@ge.com>
  *
- * 2008 (c) GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * 2008 (c) GE Intelligent Platforms Embedded Systems, 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
@@ -49,7 +49,7 @@
 #define gef_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
 
 
-static DEFINE_SPINLOCK(gef_pic_lock);
+static DEFINE_RAW_SPINLOCK(gef_pic_lock);
 
 static void __iomem *gef_pic_irq_reg_base;
 static struct irq_host *gef_pic_irq_host;
@@ -118,11 +118,11 @@
 
 	hwirq = gef_irq_to_hw(virq);
 
-	spin_lock_irqsave(&gef_pic_lock, flags);
+	raw_spin_lock_irqsave(&gef_pic_lock, flags);
 	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
 	mask &= ~(1 << hwirq);
 	out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
-	spin_unlock_irqrestore(&gef_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
 }
 
 static void gef_pic_mask_ack(unsigned int virq)
@@ -141,11 +141,11 @@
 
 	hwirq = gef_irq_to_hw(virq);
 
-	spin_lock_irqsave(&gef_pic_lock, flags);
+	raw_spin_lock_irqsave(&gef_pic_lock, flags);
 	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
 	mask |= (1 << hwirq);
 	out_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0), mask);
-	spin_unlock_irqrestore(&gef_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
 }
 
 static struct irq_chip gef_pic_chip = {
@@ -199,7 +199,7 @@
 	/* Map the devices registers into memory */
 	gef_pic_irq_reg_base = of_iomap(np, 0);
 
-	spin_lock_irqsave(&gef_pic_lock, flags);
+	raw_spin_lock_irqsave(&gef_pic_lock, flags);
 
 	/* Initialise everything as masked. */
 	out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_INTR_MASK, 0);
@@ -208,7 +208,7 @@
 	out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU0_MCP_MASK, 0);
 	out_be32(gef_pic_irq_reg_base + GEF_PIC_CPU1_MCP_MASK, 0);
 
-	spin_unlock_irqrestore(&gef_pic_lock, flags);
+	raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
 
 	/* Map controller */
 	gef_pic_cascade_irq = irq_of_parse_and_map(np, 0);
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
index a792e5d..60ce07e 100644
--- a/arch/powerpc/platforms/86xx/gef_ppc9a.c
+++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
@@ -1,9 +1,9 @@
 /*
- * GE Fanuc PPC9A board support
+ * GE PPC9A board support
  *
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ * Author: Martyn Welch <martyn.welch@ge.com>
  *
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, 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
@@ -82,7 +82,7 @@
 	}
 #endif
 
-	printk(KERN_INFO "GE Fanuc Intelligent Platforms PPC9A 6U VME SBC\n");
+	printk(KERN_INFO "GE Intelligent Platforms PPC9A 6U VME SBC\n");
 
 #ifdef CONFIG_SMP
 	mpc86xx_smp_init();
@@ -151,7 +151,7 @@
 {
 	uint svid = mfspr(SPRN_SVR);
 
-	seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n");
+	seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n");
 
 	seq_printf(m, "Revision\t: %u%c\n", gef_ppc9a_get_pcb_rev(),
 		('A' + gef_ppc9a_get_board_rev()));
@@ -235,7 +235,7 @@
 machine_device_initcall(gef_ppc9a, declare_of_platform_devices);
 
 define_machine(gef_ppc9a) {
-	.name			= "GE Fanuc PPC9A",
+	.name			= "GE PPC9A",
 	.probe			= gef_ppc9a_probe,
 	.setup_arch		= gef_ppc9a_setup_arch,
 	.init_IRQ		= gef_ppc9a_init_irq,
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
index 6a1a613..3ecee25 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc310.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
@@ -1,9 +1,9 @@
 /*
- * GE Fanuc SBC310 board support
+ * GE SBC310 board support
  *
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ * Author: Martyn Welch <martyn.welch@ge.com>
  *
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, 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
@@ -82,7 +82,7 @@
 	}
 #endif
 
-	printk(KERN_INFO "GE Fanuc Intelligent Platforms SBC310 6U VPX SBC\n");
+	printk(KERN_INFO "GE Intelligent Platforms SBC310 6U VPX SBC\n");
 
 #ifdef CONFIG_SMP
 	mpc86xx_smp_init();
@@ -142,7 +142,7 @@
 {
 	uint svid = mfspr(SPRN_SVR);
 
-	seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n");
+	seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n");
 
 	seq_printf(m, "Board ID\t: 0x%2.2x\n", gef_sbc310_get_board_id());
 	seq_printf(m, "Revision\t: %u%c\n", gef_sbc310_get_pcb_rev(),
@@ -223,7 +223,7 @@
 machine_device_initcall(gef_sbc310, declare_of_platform_devices);
 
 define_machine(gef_sbc310) {
-	.name			= "GE Fanuc SBC310",
+	.name			= "GE SBC310",
 	.probe			= gef_sbc310_probe,
 	.setup_arch		= gef_sbc310_setup_arch,
 	.init_IRQ		= gef_sbc310_init_irq,
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
index e10688a..5090d60 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc610.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
@@ -1,9 +1,9 @@
 /*
- * GE Fanuc SBC610 board support
+ * GE SBC610 board support
  *
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ * Author: Martyn Welch <martyn.welch@ge.com>
  *
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, 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
@@ -82,7 +82,7 @@
 	}
 #endif
 
-	printk(KERN_INFO "GE Fanuc Intelligent Platforms SBC610 6U VPX SBC\n");
+	printk(KERN_INFO "GE Intelligent Platforms SBC610 6U VPX SBC\n");
 
 #ifdef CONFIG_SMP
 	mpc86xx_smp_init();
@@ -133,7 +133,7 @@
 {
 	uint svid = mfspr(SPRN_SVR);
 
-	seq_printf(m, "Vendor\t\t: GE Fanuc Intelligent Platforms\n");
+	seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n");
 
 	seq_printf(m, "Revision\t: %u%c\n", gef_sbc610_get_pcb_rev(),
 		('A' + gef_sbc610_get_board_rev() - 1));
@@ -212,7 +212,7 @@
 machine_device_initcall(gef_sbc610, declare_of_platform_devices);
 
 define_machine(gef_sbc610) {
-	.name			= "GE Fanuc SBC610",
+	.name			= "GE SBC610",
 	.probe			= gef_sbc610_probe,
 	.setup_arch		= gef_sbc610_setup_arch,
 	.init_IRQ		= gef_sbc610_init_irq,
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index fa0f690..a8aae0b 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -144,6 +144,16 @@
 	  and some e300 cores (c3 and c4).  Select this only if your
 	  core supports the Embedded Performance Monitor APU
 
+config FSL_EMB_PERF_EVENT
+	bool
+	depends on FSL_EMB_PERFMON && PERF_EVENTS && !PPC_PERF_CTRS
+	default y
+
+config FSL_EMB_PERF_EVENT_E500
+	bool
+	depends on FSL_EMB_PERF_EVENT && E500
+	default y
+
 config 4xx
 	bool
 	depends on 40x || 44x
diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S
index 5369653..fba5bf9 100644
--- a/arch/powerpc/platforms/iseries/exception.S
+++ b/arch/powerpc/platforms/iseries/exception.S
@@ -43,17 +43,14 @@
 	LOAD_REG_ADDR(r23, alpaca)
 	li	r0,ALPACA_SIZE
 	sub	r23,r13,r23
-	divdu	r23,r23,r0		/* r23 has cpu number */
-	LOAD_REG_ADDR(r13, paca)
-	mulli	r0,r23,PACA_SIZE
-	add	r13,r13,r0
-	mtspr	SPRN_SPRG_PACA,r13	/* Save it away for the future */
-	mfmsr	r24
-	ori	r24,r24,MSR_RI
-	mtmsrd	r24			/* RI on */
-	mr	r24,r23
+	divdu	r24,r23,r0		/* r24 has cpu number */
 	cmpwi	0,r24,0			/* Are we processor 0? */
 	bne	1f
+	LOAD_REG_ADDR(r13, boot_paca)
+	mtspr	SPRN_SPRG_PACA,r13	/* Save it away for the future */
+	mfmsr	r23
+	ori	r23,r23,MSR_RI
+	mtmsrd	r23			/* RI on */
 	b	.__start_initialization_iSeries	/* Start up the first processor */
 1:	mfspr	r4,SPRN_CTRLF
 	li	r5,CTRL_RUNLATCH	/* Turn off the run light */
@@ -86,6 +83,16 @@
 #endif
 
 2:
+	/* Load our paca now that it's been allocated */
+	LOAD_REG_ADDR(r13, paca)
+	ld	r13,0(r13)
+	mulli	r0,r24,PACA_SIZE
+	add	r13,r13,r0
+	mtspr	SPRN_SPRG_PACA,r13	/* Save it away for the future */
+	mfmsr	r23
+	ori	r23,r23,MSR_RI
+	mtmsrd	r23			/* RI on */
+
 	HMT_LOW
 #ifdef CONFIG_SMP
 	lbz	r23,PACAPROCSTART(r13)	/* Test if this processor
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index d1b124e..a8e1d5d 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -122,44 +122,32 @@
 		if (!get_lppaca()->shared_proc)
 			get_lppaca()->donate_dedicated_cpu = 1;
 
-		printk(KERN_INFO
-			"cpu %u (hwid %u) ceding for offline with hint %d\n",
-			cpu, hwcpu, cede_latency_hint);
 		while (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) {
 			extended_cede_processor(cede_latency_hint);
-			printk(KERN_INFO "cpu %u (hwid %u) returned from cede.\n",
-				cpu, hwcpu);
-			printk(KERN_INFO
-			"Decrementer value = %x Timebase value = %llx\n",
-			get_dec(), get_tb());
 		}
 
-		printk(KERN_INFO "cpu %u (hwid %u) got prodded to go online\n",
-			cpu, hwcpu);
-
 		if (!get_lppaca()->shared_proc)
 			get_lppaca()->donate_dedicated_cpu = 0;
 		get_lppaca()->idle = 0;
+
+		if (get_preferred_offline_state(cpu) == CPU_STATE_ONLINE) {
+			unregister_slb_shadow(hwcpu, __pa(get_slb_shadow()));
+
+			/*
+			 * Call to start_secondary_resume() will not return.
+			 * Kernel stack will be reset and start_secondary()
+			 * will be called to continue the online operation.
+			 */
+			start_secondary_resume();
+		}
 	}
 
-	if (get_preferred_offline_state(cpu) == CPU_STATE_ONLINE) {
-		unregister_slb_shadow(hwcpu, __pa(get_slb_shadow()));
+	/* Requested state is CPU_STATE_OFFLINE at this point */
+	WARN_ON(get_preferred_offline_state(cpu) != CPU_STATE_OFFLINE);
 
-		/*
-		 * NOTE: Calling start_secondary() here for now to
-		 * start new context.
-		 * However, need to do it cleanly by resetting the
-		 * stack pointer.
-		 */
-		start_secondary();
-
-	} else if (get_preferred_offline_state(cpu) == CPU_STATE_OFFLINE) {
-
-		set_cpu_current_state(cpu, CPU_STATE_OFFLINE);
-		unregister_slb_shadow(hard_smp_processor_id(),
-					__pa(get_slb_shadow()));
-		rtas_stop_self();
-	}
+	set_cpu_current_state(cpu, CPU_STATE_OFFLINE);
+	unregister_slb_shadow(hwcpu, __pa(get_slb_shadow()));
+	rtas_stop_self();
 
 	/* Should never get here... */
 	BUG();
diff --git a/arch/powerpc/platforms/pseries/offline_states.h b/arch/powerpc/platforms/pseries/offline_states.h
index 22574e0..75a6f48 100644
--- a/arch/powerpc/platforms/pseries/offline_states.h
+++ b/arch/powerpc/platforms/pseries/offline_states.h
@@ -9,10 +9,31 @@
 	CPU_MAX_OFFLINE_STATES
 };
 
+#ifdef CONFIG_HOTPLUG_CPU
 extern enum cpu_state_vals get_cpu_current_state(int cpu);
 extern void set_cpu_current_state(int cpu, enum cpu_state_vals state);
-extern enum cpu_state_vals get_preferred_offline_state(int cpu);
 extern void set_preferred_offline_state(int cpu, enum cpu_state_vals state);
 extern void set_default_offline_state(int cpu);
+#else
+static inline enum cpu_state_vals get_cpu_current_state(int cpu)
+{
+	return CPU_STATE_ONLINE;
+}
+
+static inline void set_cpu_current_state(int cpu, enum cpu_state_vals state)
+{
+}
+
+static inline void set_preferred_offline_state(int cpu, enum cpu_state_vals state)
+{
+}
+
+static inline void set_default_offline_state(int cpu)
+{
+}
+#endif
+
+extern enum cpu_state_vals get_preferred_offline_state(int cpu);
 extern int start_secondary(void);
+extern void start_secondary_resume(void);
 #endif
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index 0603c91..a05f8d4 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -259,12 +259,12 @@
 	return plpar_hcall_norets(H_IPI, servernum, mfrr);
 }
 
-static inline long plpar_xirr(unsigned long *xirr_ret)
+static inline long plpar_xirr(unsigned long *xirr_ret, unsigned char cppr)
 {
 	long rc;
 	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
 
-	rc = plpar_hcall(H_XIRR, retbuf);
+	rc = plpar_hcall(H_XIRR, retbuf, cppr);
 
 	*xirr_ret = retbuf[0];
 
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 4ca6410..1bcedd8 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -120,12 +120,12 @@
 
 /* LPAR low level accessors */
 
-static inline unsigned int lpar_xirr_info_get(void)
+static inline unsigned int lpar_xirr_info_get(unsigned char cppr)
 {
 	unsigned long lpar_rc;
 	unsigned long return_value;
 
-	lpar_rc = plpar_xirr(&return_value);
+	lpar_rc = plpar_xirr(&return_value, cppr);
 	if (lpar_rc != H_SUCCESS)
 		panic(" bad return code xirr - rc = %lx\n", lpar_rc);
 	return (unsigned int)return_value;
@@ -331,7 +331,8 @@
 
 static unsigned int xics_get_irq_lpar(void)
 {
-	unsigned int xirr = lpar_xirr_info_get();
+	struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
+	unsigned int xirr = lpar_xirr_info_get(os_cppr->stack[os_cppr->index]);
 	unsigned int vec = xics_xirr_vector(xirr);
 	unsigned int irq;
 
diff --git a/arch/powerpc/sysdev/cpm2_pic.h b/arch/powerpc/sysdev/cpm2_pic.h
index 30e5828..2c5f70c 100644
--- a/arch/powerpc/sysdev/cpm2_pic.h
+++ b/arch/powerpc/sysdev/cpm2_pic.h
@@ -3,6 +3,6 @@
 
 extern unsigned int cpm2_get_irq(void);
 
-extern void cpm2_pic_init(struct device_node*);
+extern void cpm2_pic_init(struct device_node *);
 
 #endif /* _PPC_KERNEL_CPM2_H */
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index d927da8..541ba98 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -33,7 +33,7 @@
 
 #include "qe_ic.h"
 
-static DEFINE_SPINLOCK(qe_ic_lock);
+static DEFINE_RAW_SPINLOCK(qe_ic_lock);
 
 static struct qe_ic_info qe_ic_info[] = {
 	[1] = {
@@ -201,13 +201,13 @@
 	unsigned long flags;
 	u32 temp;
 
-	spin_lock_irqsave(&qe_ic_lock, flags);
+	raw_spin_lock_irqsave(&qe_ic_lock, flags);
 
 	temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
 	qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
 		    temp | qe_ic_info[src].mask);
 
-	spin_unlock_irqrestore(&qe_ic_lock, flags);
+	raw_spin_unlock_irqrestore(&qe_ic_lock, flags);
 }
 
 static void qe_ic_mask_irq(unsigned int virq)
@@ -217,7 +217,7 @@
 	unsigned long flags;
 	u32 temp;
 
-	spin_lock_irqsave(&qe_ic_lock, flags);
+	raw_spin_lock_irqsave(&qe_ic_lock, flags);
 
 	temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
 	qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
@@ -233,7 +233,7 @@
 	 */
 	mb();
 
-	spin_unlock_irqrestore(&qe_ic_lock, flags);
+	raw_spin_unlock_irqrestore(&qe_ic_lock, flags);
 }
 
 static struct irq_chip qe_ic_irq_chip = {
diff --git a/arch/s390/crypto/sha_common.c b/arch/s390/crypto/sha_common.c
index 7903ec4..f42dbab 100644
--- a/arch/s390/crypto/sha_common.c
+++ b/arch/s390/crypto/sha_common.c
@@ -79,7 +79,7 @@
 	memset(ctx->buf + index, 0x00, end - index - 8);
 
 	/*
-	 * Append message length. Well, SHA-512 wants a 128 bit lenght value,
+	 * Append message length. Well, SHA-512 wants a 128 bit length value,
 	 * nevertheless we use u64, should be enough for now...
 	 */
 	bits = ctx->count * 8;
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 341aff2..cd128b0 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -288,46 +288,30 @@
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
 	sb->s_magic = HYPFS_MAGIC;
 	sb->s_op = &hypfs_s_ops;
-	if (hypfs_parse_options(data, sb)) {
-		rc = -EINVAL;
-		goto err_alloc;
-	}
+	if (hypfs_parse_options(data, sb))
+		return -EINVAL;
 	root_inode = hypfs_make_inode(sb, S_IFDIR | 0755);
-	if (!root_inode) {
-		rc = -ENOMEM;
-		goto err_alloc;
-	}
+	if (!root_inode)
+		return -ENOMEM;
 	root_inode->i_op = &simple_dir_inode_operations;
 	root_inode->i_fop = &simple_dir_operations;
-	root_dentry = d_alloc_root(root_inode);
+	sb->s_root = root_dentry = d_alloc_root(root_inode);
 	if (!root_dentry) {
 		iput(root_inode);
-		rc = -ENOMEM;
-		goto err_alloc;
+		return -ENOMEM;
 	}
 	if (MACHINE_IS_VM)
 		rc = hypfs_vm_create_files(sb, root_dentry);
 	else
 		rc = hypfs_diag_create_files(sb, root_dentry);
 	if (rc)
-		goto err_tree;
+		return rc;
 	sbi->update_file = hypfs_create_update_file(sb, root_dentry);
-	if (IS_ERR(sbi->update_file)) {
-		rc = PTR_ERR(sbi->update_file);
-		goto err_tree;
-	}
+	if (IS_ERR(sbi->update_file))
+		return PTR_ERR(sbi->update_file);
 	hypfs_update_update(sb);
-	sb->s_root = root_dentry;
 	pr_info("Hypervisor filesystem mounted\n");
 	return 0;
-
-err_tree:
-	hypfs_delete_tree(root_dentry);
-	d_genocide(root_dentry);
-	dput(root_dentry);
-err_alloc:
-	kfree(sbi);
-	return rc;
 }
 
 static int hypfs_get_super(struct file_system_type *fst, int flags,
@@ -340,12 +324,12 @@
 {
 	struct hypfs_sb_info *sb_info = sb->s_fs_info;
 
-	if (sb->s_root) {
+	if (sb->s_root)
 		hypfs_delete_tree(sb->s_root);
+	if (sb_info->update_file)
 		hypfs_remove(sb_info->update_file);
-		kfree(sb->s_fs_info);
-		sb->s_fs_info = NULL;
-	}
+	kfree(sb->s_fs_info);
+	sb->s_fs_info = NULL;
 	kill_litter_super(sb);
 }
 
diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h
index e85679a..e34347d 100644
--- a/arch/s390/include/asm/cio.h
+++ b/arch/s390/include/asm/cio.h
@@ -20,7 +20,7 @@
 /**
  * struct ccw1 - channel command word
  * @cmd_code: command code
- * @flags: flags, like IDA adressing, etc.
+ * @flags: flags, like IDA addressing, etc.
  * @count: byte count
  * @cda: data address
  *
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index 01a0802..104f200 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -35,7 +35,8 @@
 
 extern long psw32_user_bits;
 
-#define COMPAT_USER_HZ	100
+#define COMPAT_USER_HZ		100
+#define COMPAT_UTS_MACHINE	"s390\0\0\0\0"
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index dd2d913..fef9b33 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -489,9 +489,6 @@
  * These are defined as per linux/ptrace.h, which see.
  */
 #define arch_has_single_step()	(1)
-struct task_struct;
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
 extern void show_regs(struct pt_regs * regs);
 
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index c666bfe..9b04b11 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -321,11 +321,6 @@
 #define QDIO_ERROR_ACTIVATE_CHECK_CONDITION	0x40
 #define QDIO_ERROR_SLSB_STATE			0x80
 
-/* for qdio_initialize */
-#define QDIO_INBOUND_0COPY_SBALS		0x01
-#define QDIO_OUTBOUND_0COPY_SBALS		0x02
-#define QDIO_USE_OUTBOUND_PCIS			0x04
-
 /* for qdio_cleanup */
 #define QDIO_FLAG_CLEANUP_USING_CLEAR		0x01
 #define QDIO_FLAG_CLEANUP_USING_HALT		0x02
@@ -344,7 +339,6 @@
  * @input_handler: handler to be called for input queues
  * @output_handler: handler to be called for output queues
  * @int_parm: interruption parameter
- * @flags: initialization flags
  * @input_sbal_addr_array:  address of no_input_qs * 128 pointers
  * @output_sbal_addr_array: address of no_output_qs * 128 pointers
  */
@@ -361,7 +355,6 @@
 	qdio_handler_t *input_handler;
 	qdio_handler_t *output_handler;
 	unsigned long int_parm;
-	unsigned long flags;
 	void **input_sbal_addr_array;
 	void **output_sbal_addr_array;
 };
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h
index 6e9f049..5f00751 100644
--- a/arch/s390/include/asm/unistd.h
+++ b/arch/s390/include/asm/unistd.h
@@ -392,6 +392,7 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_MMAP
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 30de2d0..672ce52 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -547,7 +547,7 @@
 	.globl	sys32_newuname_wrapper
 sys32_newuname_wrapper:
 	llgtr	%r2,%r2			# struct new_utsname *
-	jg	sys_s390_newuname	# branch to system call
+	jg	sys_newuname		# branch to system call
 
 	.globl	compat_sys_adjtimex_wrapper
 compat_sys_adjtimex_wrapper:
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index e1e5e76..eb15c12 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -24,17 +24,13 @@
 void __init startup_init(void);
 void die(const char * str, struct pt_regs * regs, long err);
 
-struct new_utsname;
-struct mmap_arg_struct;
+struct s390_mmap_arg_struct;
 struct fadvise64_64_args;
 struct old_sigaction;
-struct sel_arg_struct;
 
-long sys_mmap2(struct mmap_arg_struct __user  *arg);
-long sys_s390_old_mmap(struct mmap_arg_struct __user *arg);
-long sys_ipc(uint call, int first, unsigned long second,
+long sys_mmap2(struct s390_mmap_arg_struct __user  *arg);
+long sys_s390_ipc(uint call, int first, unsigned long second,
 	     unsigned long third, void __user *ptr);
-long sys_s390_newuname(struct new_utsname __user *name);
 long sys_s390_personality(unsigned long personality);
 long sys_s390_fadvise64(int fd, u32 offset_high, u32 offset_low,
 		    size_t len, int advice);
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
index 27af3bf..2e82fdd 100644
--- a/arch/s390/kernel/sclp.S
+++ b/arch/s390/kernel/sclp.S
@@ -235,7 +235,7 @@
 	lh	%r9,0(%r8)			# update sccb length
 	ar	%r9,%r6
 	sth	%r9,0(%r8)
-	ar	%r7,%r6				# update current mto adress
+	ar	%r7,%r6				# update current mto address
 	ltr	%r0,%r0				# more characters?
 	jnz	.LinitmtoS4
 	l	%r2,.LwritedataS4-.LbaseS4(%r13)# write data
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 8b10127..29f65bc 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -1020,7 +1020,9 @@
 	return rc;
 }
 
-static ssize_t __ref rescan_store(struct sysdev_class *class, const char *buf,
+static ssize_t __ref rescan_store(struct sysdev_class *class,
+				  struct sysdev_class_attribute *attr,
+				  const char *buf,
 				  size_t count)
 {
 	int rc;
@@ -1031,7 +1033,9 @@
 static SYSDEV_CLASS_ATTR(rescan, 0200, NULL, rescan_store);
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static ssize_t dispatching_show(struct sysdev_class *class, char *buf)
+static ssize_t dispatching_show(struct sysdev_class *class,
+				struct sysdev_class_attribute *attr,
+				char *buf)
 {
 	ssize_t count;
 
@@ -1041,7 +1045,9 @@
 	return count;
 }
 
-static ssize_t dispatching_store(struct sysdev_class *dev, const char *buf,
+static ssize_t dispatching_store(struct sysdev_class *dev,
+				 struct sysdev_class_attribute *attr,
+				 const char *buf,
 				 size_t count)
 {
 	int val, rc;
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index 86a74c9..7b6b0f8 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -33,13 +33,12 @@
 #include "entry.h"
 
 /*
- * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls. Linux for S/390 isn't able to handle more than 5
- * system call parameters, so these system calls used a memory
- * block for parameter passing..
+ * Perform the mmap() system call. Linux for S/390 isn't able to handle more
+ * than 5 system call parameters, so this system call uses a memory block
+ * for parameter passing.
  */
 
-struct mmap_arg_struct {
+struct s390_mmap_arg_struct {
 	unsigned long addr;
 	unsigned long len;
 	unsigned long prot;
@@ -48,9 +47,9 @@
 	unsigned long offset;
 };
 
-SYSCALL_DEFINE1(mmap2, struct mmap_arg_struct __user *, arg)
+SYSCALL_DEFINE1(mmap2, struct s390_mmap_arg_struct __user *, arg)
 {
-	struct mmap_arg_struct a;
+	struct s390_mmap_arg_struct a;
 	int error = -EFAULT;
 
 	if (copy_from_user(&a, arg, sizeof(a)))
@@ -60,29 +59,12 @@
 	return error;
 }
 
-SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct __user *, arg)
-{
-	struct mmap_arg_struct a;
-	long error = -EFAULT;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		goto out;
-
-	error = -EINVAL;
-	if (a.offset & ~PAGE_MASK)
-		goto out;
-
-	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
-out:
-	return error;
-}
-
 /*
  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  *
  * This is really horribly ugly.
  */
-SYSCALL_DEFINE5(ipc, uint, call, int, first, unsigned long, second,
+SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, unsigned long, second,
 		unsigned long, third, void __user *, ptr)
 {
         struct ipc_kludge tmp;
@@ -149,17 +131,6 @@
 }
 
 #ifdef CONFIG_64BIT
-SYSCALL_DEFINE1(s390_newuname, struct new_utsname __user *, name)
-{
-	int ret = sys_newuname(name);
-
-	if (personality(current->personality) == PER_LINUX32 && !ret) {
-		ret = copy_to_user(name->machine, "s390\0\0\0\0", 8);
-		if (ret) ret = -EFAULT;
-	}
-	return ret;
-}
-
 SYSCALL_DEFINE1(s390_personality, unsigned long, personality)
 {
 	int ret;
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 30eca07..201ce6b 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -98,7 +98,7 @@
 SYSCALL(sys_swapon,sys_swapon,sys32_swapon_wrapper)
 SYSCALL(sys_reboot,sys_reboot,sys32_reboot_wrapper)
 SYSCALL(sys_ni_syscall,sys_ni_syscall,old32_readdir_wrapper)	/* old readdir syscall */
-SYSCALL(sys_s390_old_mmap,sys_s390_old_mmap,old32_mmap_wrapper)	/* 90 */
+SYSCALL(sys_old_mmap,sys_old_mmap,old32_mmap_wrapper)		/* 90 */
 SYSCALL(sys_munmap,sys_munmap,sys32_munmap_wrapper)
 SYSCALL(sys_truncate,sys_truncate,sys32_truncate_wrapper)
 SYSCALL(sys_ftruncate,sys_ftruncate,sys32_ftruncate_wrapper)
@@ -125,12 +125,12 @@
 SYSCALL(sys_wait4,sys_wait4,compat_sys_wait4_wrapper)
 SYSCALL(sys_swapoff,sys_swapoff,sys32_swapoff_wrapper)		/* 115 */
 SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper)
-SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper)
+SYSCALL(sys_s390_ipc,sys_s390_ipc,sys32_ipc_wrapper)
 SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper)
 SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn)
 SYSCALL(sys_clone,sys_clone,sys_clone_wrapper)			/* 120 */
 SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper)
-SYSCALL(sys_newuname,sys_s390_newuname,sys32_newuname_wrapper)
+SYSCALL(sys_newuname,sys_newuname,sys32_newuname_wrapper)
 NI_SYSCALL							/* modify_ldt for i386 */
 SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex_wrapper)
 SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper)	/* 125 */
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index a8f93f1..aa2483e 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -73,15 +73,15 @@
 }
 EXPORT_SYMBOL(monotonic_clock);
 
-void tod_to_timeval(__u64 todval, struct timespec *xtime)
+void tod_to_timeval(__u64 todval, struct timespec *xt)
 {
 	unsigned long long sec;
 
 	sec = todval >> 12;
 	do_div(sec, 1000000);
-	xtime->tv_sec = sec;
+	xt->tv_sec = sec;
 	todval -= (sec * 1000000) << 12;
-	xtime->tv_nsec = ((todval * 1000) >> 12);
+	xt->tv_nsec = ((todval * 1000) >> 12);
 }
 EXPORT_SYMBOL(tod_to_timeval);
 
@@ -216,8 +216,8 @@
 	++vdso_data->tb_update_count;
 	smp_wmb();
 	vdso_data->xtime_tod_stamp = clock->cycle_last;
-	vdso_data->xtime_clock_sec = xtime.tv_sec;
-	vdso_data->xtime_clock_nsec = xtime.tv_nsec;
+	vdso_data->xtime_clock_sec = wall_time->tv_sec;
+	vdso_data->xtime_clock_nsec = wall_time->tv_nsec;
 	vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec;
 	vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec;
 	smp_wmb();
@@ -1116,14 +1116,18 @@
 /*
  * ETR class attributes
  */
-static ssize_t etr_stepping_port_show(struct sysdev_class *class, char *buf)
+static ssize_t etr_stepping_port_show(struct sysdev_class *class,
+					struct sysdev_class_attribute *attr,
+					char *buf)
 {
 	return sprintf(buf, "%i\n", etr_port0.esw.p);
 }
 
 static SYSDEV_CLASS_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL);
 
-static ssize_t etr_stepping_mode_show(struct sysdev_class *class, char *buf)
+static ssize_t etr_stepping_mode_show(struct sysdev_class *class,
+				      	struct sysdev_class_attribute *attr,
+					char *buf)
 {
 	char *mode_str;
 
@@ -1584,7 +1588,9 @@
 	.name	= "stp",
 };
 
-static ssize_t stp_ctn_id_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_ctn_id_show(struct sysdev_class *class,
+				struct sysdev_class_attribute *attr,
+				char *buf)
 {
 	if (!stp_online)
 		return -ENODATA;
@@ -1594,7 +1600,9 @@
 
 static SYSDEV_CLASS_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL);
 
-static ssize_t stp_ctn_type_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_ctn_type_show(struct sysdev_class *class,
+				struct sysdev_class_attribute *attr,
+				char *buf)
 {
 	if (!stp_online)
 		return -ENODATA;
@@ -1603,7 +1611,9 @@
 
 static SYSDEV_CLASS_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL);
 
-static ssize_t stp_dst_offset_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_dst_offset_show(struct sysdev_class *class,
+				   struct sysdev_class_attribute *attr,
+				   char *buf)
 {
 	if (!stp_online || !(stp_info.vbits & 0x2000))
 		return -ENODATA;
@@ -1612,7 +1622,9 @@
 
 static SYSDEV_CLASS_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL);
 
-static ssize_t stp_leap_seconds_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_leap_seconds_show(struct sysdev_class *class,
+					struct sysdev_class_attribute *attr,
+					char *buf)
 {
 	if (!stp_online || !(stp_info.vbits & 0x8000))
 		return -ENODATA;
@@ -1621,7 +1633,9 @@
 
 static SYSDEV_CLASS_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL);
 
-static ssize_t stp_stratum_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_stratum_show(struct sysdev_class *class,
+				struct sysdev_class_attribute *attr,
+				char *buf)
 {
 	if (!stp_online)
 		return -ENODATA;
@@ -1630,7 +1644,9 @@
 
 static SYSDEV_CLASS_ATTR(stratum, 0400, stp_stratum_show, NULL);
 
-static ssize_t stp_time_offset_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_time_offset_show(struct sysdev_class *class,
+				struct sysdev_class_attribute *attr,
+				char *buf)
 {
 	if (!stp_online || !(stp_info.vbits & 0x0800))
 		return -ENODATA;
@@ -1639,7 +1655,9 @@
 
 static SYSDEV_CLASS_ATTR(time_offset, 0400, stp_time_offset_show, NULL);
 
-static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_time_zone_offset_show(struct sysdev_class *class,
+				struct sysdev_class_attribute *attr,
+				char *buf)
 {
 	if (!stp_online || !(stp_info.vbits & 0x4000))
 		return -ENODATA;
@@ -1649,7 +1667,9 @@
 static SYSDEV_CLASS_ATTR(time_zone_offset, 0400,
 			 stp_time_zone_offset_show, NULL);
 
-static ssize_t stp_timing_mode_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_timing_mode_show(struct sysdev_class *class,
+				struct sysdev_class_attribute *attr,
+				char *buf)
 {
 	if (!stp_online)
 		return -ENODATA;
@@ -1658,7 +1678,9 @@
 
 static SYSDEV_CLASS_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL);
 
-static ssize_t stp_timing_state_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_timing_state_show(struct sysdev_class *class,
+				struct sysdev_class_attribute *attr,
+				char *buf)
 {
 	if (!stp_online)
 		return -ENODATA;
@@ -1667,12 +1689,15 @@
 
 static SYSDEV_CLASS_ATTR(timing_state, 0400, stp_timing_state_show, NULL);
 
-static ssize_t stp_online_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_online_show(struct sysdev_class *class,
+				struct sysdev_class_attribute *attr,
+				char *buf)
 {
 	return sprintf(buf, "%i\n", stp_online);
 }
 
 static ssize_t stp_online_store(struct sysdev_class *class,
+				struct sysdev_class_attribute *attr,
 				const char *buf, size_t count)
 {
 	unsigned int value;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 3fa0a10..4929286 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -242,6 +242,7 @@
 	kvm_free_physmem(kvm);
 	free_page((unsigned long)(kvm->arch.sca));
 	debug_unregister(kvm->arch.dbf);
+	cleanup_srcu_struct(&kvm->srcu);
 	kfree(kvm);
 }
 
@@ -690,14 +691,12 @@
 }
 
 /* Section: memory related */
-int kvm_arch_set_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem,
-				struct kvm_memory_slot old,
-				int user_alloc)
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+				   struct kvm_memory_slot *memslot,
+				   struct kvm_memory_slot old,
+				   struct kvm_userspace_memory_region *mem,
+				   int user_alloc)
 {
-	int i;
-	struct kvm_vcpu *vcpu;
-
 	/* A few sanity checks. We can have exactly one memory slot which has
 	   to start at guest virtual zero and which has to be located at a
 	   page boundary in userland and which has to end at a page boundary.
@@ -720,14 +719,23 @@
 	if (!user_alloc)
 		return -EINVAL;
 
+	return 0;
+}
+
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+				struct kvm_userspace_memory_region *mem,
+				struct kvm_memory_slot old,
+				int user_alloc)
+{
+	int i;
+	struct kvm_vcpu *vcpu;
+
 	/* request update of sie control block for all available vcpus */
 	kvm_for_each_vcpu(i, vcpu, kvm) {
 		if (test_and_set_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
 			continue;
 		kvm_s390_inject_sigp_stop(vcpu, ACTION_RELOADVCPU_ON_STOP);
 	}
-
-	return 0;
 }
 
 void kvm_arch_flush_shadow(struct kvm *kvm)
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 06cce82..60f09ab 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -67,10 +67,14 @@
 
 static inline void kvm_s390_vcpu_set_mem(struct kvm_vcpu *vcpu)
 {
+	int idx;
 	struct kvm_memory_slot *mem;
+	struct kvm_memslots *memslots;
 
-	down_read(&vcpu->kvm->slots_lock);
-	mem = &vcpu->kvm->memslots[0];
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
+	memslots = rcu_dereference(vcpu->kvm->memslots);
+
+	mem = &memslots->memslots[0];
 
 	vcpu->arch.sie_block->gmsor = mem->userspace_addr;
 	vcpu->arch.sie_block->gmslm =
@@ -78,7 +82,7 @@
 		(mem->npages << PAGE_SHIFT) +
 		VIRTIODESCSPACE - 1ul;
 
-	up_read(&vcpu->kvm->slots_lock);
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 }
 
 /* implemented in priv.c */
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index cd54a1c..761ab8b 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -2,7 +2,8 @@
 # Makefile for s390-specific library files..
 #
 
-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o usercopy.o
+lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+obj-y += usercopy.o
 obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index 76a3637b..f16bd04 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -374,7 +374,7 @@
 #ifdef CONFIG_CMM_IUCV
 #define SMSG_PREFIX "CMM"
 static void
-cmm_smsg_target(char *from, char *msg)
+cmm_smsg_target(const char *from, char *msg)
 {
 	long nr, seconds;
 
diff --git a/arch/score/include/asm/ptrace.h b/arch/score/include/asm/ptrace.h
index d40e691..e89dc9b 100644
--- a/arch/score/include/asm/ptrace.h
+++ b/arch/score/include/asm/ptrace.h
@@ -90,8 +90,7 @@
 			 unsigned short *);
 
 #define arch_has_single_step()	(1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_SCORE_PTRACE_H */
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 05cef50..8d90564 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -183,6 +183,9 @@
 config DMA_NONCOHERENT
 	def_bool !DMA_COHERENT
 
+config NEED_DMA_MAP_STATE
+	def_bool DMA_NONCOHERENT
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index be300aa..7da0fc9 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -419,6 +419,9 @@
 		I2C_BOARD_INFO("migor_ts", 0x51),
 		.irq = 38, /* IRQ6 */
 	},
+	{
+		I2C_BOARD_INFO("wm8978", 0x1a),
+	},
 };
 
 static struct i2c_board_info migor_i2c_camera[] = {
@@ -619,6 +622,19 @@
 
 	platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
 
+	/* SIU: Port B */
+	gpio_request(GPIO_FN_SIUBOLR, NULL);
+	gpio_request(GPIO_FN_SIUBOBT, NULL);
+	gpio_request(GPIO_FN_SIUBISLD, NULL);
+	gpio_request(GPIO_FN_SIUBOSLD, NULL);
+	gpio_request(GPIO_FN_SIUMCKB, NULL);
+
+	/*
+	 * The original driver sets SIUB OLR/OBT, ILR/IBT, and SIUA OLR/OBT to
+	 * output. Need only SIUB, set to output for master mode (table 34.2)
+	 */
+	__raw_writew(__raw_readw(PORT_MSELCRA) | 1, PORT_MSELCRA);
+
 	i2c_register_board_info(0, migor_i2c_devices,
 				ARRAY_SIZE(migor_i2c_devices));
 
diff --git a/arch/sh/boot/compressed/cache.c b/arch/sh/boot/compressed/cache.c
index e27fc74..d0b77b6 100644
--- a/arch/sh/boot/compressed/cache.c
+++ b/arch/sh/boot/compressed/cache.c
@@ -5,7 +5,7 @@
 
 	for (i = 0; i < (32 * 1024); i += 32) {
 		(void)*p;
-		p += (32 / sizeof (int));
+		p += (32 / sizeof(int));
 	}
 
 	return 0;
diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h
index da3ebec..1f4e562 100644
--- a/arch/sh/include/asm/cacheflush.h
+++ b/arch/sh/include/asm/cacheflush.h
@@ -86,8 +86,8 @@
 	struct page *page, unsigned long vaddr, void *dst, const void *src,
 	unsigned long len);
 
-#define flush_cache_vmap(start, end)		flush_cache_all()
-#define flush_cache_vunmap(start, end)		flush_cache_all()
+#define flush_cache_vmap(start, end)		local_flush_cache_all(NULL)
+#define flush_cache_vunmap(start, end)		local_flush_cache_all(NULL)
 
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
diff --git a/arch/sh/include/asm/dma-register.h b/arch/sh/include/asm/dma-register.h
new file mode 100644
index 0000000..51cd78f
--- /dev/null
+++ b/arch/sh/include/asm/dma-register.h
@@ -0,0 +1,51 @@
+/*
+ * Common header for the legacy SH DMA driver and the new dmaengine driver
+ *
+ * extracted from arch/sh/include/asm/dma-sh.h:
+ *
+ * Copyright (C) 2000  Takashi YOSHII
+ * Copyright (C) 2003  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.
+ */
+#ifndef DMA_REGISTER_H
+#define DMA_REGISTER_H
+
+/* DMA register */
+#define SAR	0x00
+#define DAR	0x04
+#define TCR	0x08
+#define CHCR	0x0C
+#define DMAOR	0x40
+
+/* DMAOR definitions */
+#define DMAOR_AE	0x00000004
+#define DMAOR_NMIF	0x00000002
+#define DMAOR_DME	0x00000001
+
+/* Definitions for the SuperH DMAC */
+#define REQ_L	0x00000000
+#define REQ_E	0x00080000
+#define RACK_H	0x00000000
+#define RACK_L	0x00040000
+#define ACK_R	0x00000000
+#define ACK_W	0x00020000
+#define ACK_H	0x00000000
+#define ACK_L	0x00010000
+#define DM_INC	0x00004000
+#define DM_DEC	0x00008000
+#define DM_FIX	0x0000c000
+#define SM_INC	0x00001000
+#define SM_DEC	0x00002000
+#define SM_FIX	0x00003000
+#define RS_IN	0x00000200
+#define RS_OUT	0x00000300
+#define TS_BLK	0x00000040
+#define TM_BUR	0x00000020
+#define CHCR_DE	0x00000001
+#define CHCR_TE	0x00000002
+#define CHCR_IE	0x00000004
+
+#endif
diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h
index e934a2e..f3acb8e 100644
--- a/arch/sh/include/asm/dma-sh.h
+++ b/arch/sh/include/asm/dma-sh.h
@@ -11,7 +11,8 @@
 #ifndef __DMA_SH_H
 #define __DMA_SH_H
 
-#include <asm/dma.h>
+#include <asm/dma-register.h>
+#include <cpu/dma-register.h>
 #include <cpu/dma.h>
 
 /* DMAOR contorl: The DMAOR access size is different by CPU.*/
@@ -53,34 +54,6 @@
 #endif
 };
 
-/* Definitions for the SuperH DMAC */
-#define REQ_L	0x00000000
-#define REQ_E	0x00080000
-#define RACK_H	0x00000000
-#define RACK_L	0x00040000
-#define ACK_R	0x00000000
-#define ACK_W	0x00020000
-#define ACK_H	0x00000000
-#define ACK_L	0x00010000
-#define DM_INC	0x00004000
-#define DM_DEC	0x00008000
-#define DM_FIX	0x0000c000
-#define SM_INC	0x00001000
-#define SM_DEC	0x00002000
-#define SM_FIX	0x00003000
-#define RS_IN	0x00000200
-#define RS_OUT	0x00000300
-#define TS_BLK	0x00000040
-#define TM_BUR	0x00000020
-#define CHCR_DE 0x00000001
-#define CHCR_TE 0x00000002
-#define CHCR_IE 0x00000004
-
-/* DMAOR definitions */
-#define DMAOR_AE	0x00000004
-#define DMAOR_NMIF	0x00000002
-#define DMAOR_DME	0x00000001
-
 /*
  * Define the default configuration for dual address memory-memory transfer.
  * The 0x400 value represents auto-request, external->external.
@@ -111,61 +84,4 @@
 #endif
 };
 
-/* DMA register */
-#define SAR     0x00
-#define DAR     0x04
-#define TCR     0x08
-#define CHCR    0x0C
-#define DMAOR	0x40
-
-/*
- * for dma engine
- *
- * SuperH DMA mode
- */
-#define SHDMA_MIX_IRQ	(1 << 1)
-#define SHDMA_DMAOR1	(1 << 2)
-#define SHDMA_DMAE1	(1 << 3)
-
-enum sh_dmae_slave_chan_id {
-	SHDMA_SLAVE_SCIF0_TX,
-	SHDMA_SLAVE_SCIF0_RX,
-	SHDMA_SLAVE_SCIF1_TX,
-	SHDMA_SLAVE_SCIF1_RX,
-	SHDMA_SLAVE_SCIF2_TX,
-	SHDMA_SLAVE_SCIF2_RX,
-	SHDMA_SLAVE_SCIF3_TX,
-	SHDMA_SLAVE_SCIF3_RX,
-	SHDMA_SLAVE_SCIF4_TX,
-	SHDMA_SLAVE_SCIF4_RX,
-	SHDMA_SLAVE_SCIF5_TX,
-	SHDMA_SLAVE_SCIF5_RX,
-	SHDMA_SLAVE_SIUA_TX,
-	SHDMA_SLAVE_SIUA_RX,
-	SHDMA_SLAVE_SIUB_TX,
-	SHDMA_SLAVE_SIUB_RX,
-	SHDMA_SLAVE_NUMBER,	/* Must stay last */
-};
-
-struct sh_dmae_slave_config {
-	enum sh_dmae_slave_chan_id	slave_id;
-	dma_addr_t			addr;
-	u32				chcr;
-	char				mid_rid;
-};
-
-struct sh_dmae_pdata {
-	unsigned int mode;
-	struct sh_dmae_slave_config *config;
-	int config_num;
-};
-
-struct device;
-
-struct sh_dmae_slave {
-	enum sh_dmae_slave_chan_id	slave_id; /* Set by the platform */
-	struct device			*dma_dev; /* Set by the platform */
-	struct sh_dmae_slave_config	*config;  /* Set by the driver */
-};
-
 #endif /* __DMA_SH_H */
diff --git a/arch/sh/include/asm/dmaengine.h b/arch/sh/include/asm/dmaengine.h
new file mode 100644
index 0000000..bf2f30cf
--- /dev/null
+++ b/arch/sh/include/asm/dmaengine.h
@@ -0,0 +1,93 @@
+/*
+ * Header for the new SH dmaengine driver
+ *
+ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.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.
+ */
+#ifndef ASM_DMAENGINE_H
+#define ASM_DMAENGINE_H
+
+#include <linux/dmaengine.h>
+#include <linux/list.h>
+
+#include <asm/dma-register.h>
+
+#define SH_DMAC_MAX_CHANNELS	6
+
+enum sh_dmae_slave_chan_id {
+	SHDMA_SLAVE_SCIF0_TX,
+	SHDMA_SLAVE_SCIF0_RX,
+	SHDMA_SLAVE_SCIF1_TX,
+	SHDMA_SLAVE_SCIF1_RX,
+	SHDMA_SLAVE_SCIF2_TX,
+	SHDMA_SLAVE_SCIF2_RX,
+	SHDMA_SLAVE_SCIF3_TX,
+	SHDMA_SLAVE_SCIF3_RX,
+	SHDMA_SLAVE_SCIF4_TX,
+	SHDMA_SLAVE_SCIF4_RX,
+	SHDMA_SLAVE_SCIF5_TX,
+	SHDMA_SLAVE_SCIF5_RX,
+	SHDMA_SLAVE_SIUA_TX,
+	SHDMA_SLAVE_SIUA_RX,
+	SHDMA_SLAVE_SIUB_TX,
+	SHDMA_SLAVE_SIUB_RX,
+	SHDMA_SLAVE_NUMBER,	/* Must stay last */
+};
+
+struct sh_dmae_slave_config {
+	enum sh_dmae_slave_chan_id	slave_id;
+	dma_addr_t			addr;
+	u32				chcr;
+	char				mid_rid;
+};
+
+struct sh_dmae_channel {
+	unsigned int	offset;
+	unsigned int	dmars;
+	unsigned int	dmars_bit;
+};
+
+struct sh_dmae_pdata {
+	struct sh_dmae_slave_config *slave;
+	int slave_num;
+	struct sh_dmae_channel *channel;
+	int channel_num;
+	unsigned int ts_low_shift;
+	unsigned int ts_low_mask;
+	unsigned int ts_high_shift;
+	unsigned int ts_high_mask;
+	unsigned int *ts_shift;
+	int ts_shift_num;
+	u16 dmaor_init;
+};
+
+struct device;
+
+/* Used by slave DMA clients to request DMA to/from a specific peripheral */
+struct sh_dmae_slave {
+	enum sh_dmae_slave_chan_id	slave_id; /* Set by the platform */
+	struct device			*dma_dev; /* Set by the platform */
+	struct sh_dmae_slave_config	*config;  /* Set by the driver */
+};
+
+struct sh_dmae_regs {
+	u32 sar; /* SAR / source address */
+	u32 dar; /* DAR / destination address */
+	u32 tcr; /* TCR / transfer count */
+};
+
+struct sh_desc {
+	struct sh_dmae_regs hw;
+	struct list_head node;
+	struct dma_async_tx_descriptor async_tx;
+	enum dma_data_direction direction;
+	dma_cookie_t cookie;
+	size_t partial;
+	int chunks;
+	int mark;
+};
+
+#endif
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 7dab7b23..f689554 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -291,21 +291,21 @@
  * doesn't exist, so everything must go through page tables.
  */
 #ifdef CONFIG_MMU
-void __iomem *__ioremap_caller(unsigned long offset, unsigned long size,
+void __iomem *__ioremap_caller(phys_addr_t offset, unsigned long size,
 			       pgprot_t prot, void *caller);
 void __iounmap(void __iomem *addr);
 
 static inline void __iomem *
-__ioremap(unsigned long offset, unsigned long size, pgprot_t prot)
+__ioremap(phys_addr_t offset, unsigned long size, pgprot_t prot)
 {
 	return __ioremap_caller(offset, size, prot, __builtin_return_address(0));
 }
 
 static inline void __iomem *
-__ioremap_29bit(unsigned long offset, unsigned long size, pgprot_t prot)
+__ioremap_29bit(phys_addr_t offset, unsigned long size, pgprot_t prot)
 {
 #ifdef CONFIG_29BIT
-	unsigned long last_addr = offset + size - 1;
+	phys_addr_t last_addr = offset + size - 1;
 
 	/*
 	 * For P1 and P2 space this is trivial, as everything is already
@@ -329,7 +329,7 @@
 }
 
 static inline void __iomem *
-__ioremap_mode(unsigned long offset, unsigned long size, pgprot_t prot)
+__ioremap_mode(phys_addr_t offset, unsigned long size, pgprot_t prot)
 {
 	void __iomem *ret;
 
@@ -349,35 +349,32 @@
 #define __iounmap(addr)				do { } while (0)
 #endif /* CONFIG_MMU */
 
-static inline void __iomem *
-ioremap(unsigned long offset, unsigned long size)
+static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
 {
 	return __ioremap_mode(offset, size, PAGE_KERNEL_NOCACHE);
 }
 
 static inline void __iomem *
-ioremap_cache(unsigned long offset, unsigned long size)
+ioremap_cache(phys_addr_t offset, unsigned long size)
 {
 	return __ioremap_mode(offset, size, PAGE_KERNEL);
 }
 
 #ifdef CONFIG_HAVE_IOREMAP_PROT
 static inline void __iomem *
-ioremap_prot(resource_size_t offset, unsigned long size, unsigned long flags)
+ioremap_prot(phys_addr_t offset, unsigned long size, unsigned long flags)
 {
 	return __ioremap_mode(offset, size, __pgprot(flags));
 }
 #endif
 
 #ifdef CONFIG_IOREMAP_FIXED
-extern void __iomem *ioremap_fixed(resource_size_t, unsigned long,
-				   unsigned long, pgprot_t);
+extern void __iomem *ioremap_fixed(phys_addr_t, unsigned long, pgprot_t);
 extern int iounmap_fixed(void __iomem *);
 extern void ioremap_fixed_init(void);
 #else
 static inline void __iomem *
-ioremap_fixed(resource_size_t phys_addr, unsigned long offset,
-	      unsigned long size, pgprot_t prot)
+ioremap_fixed(phys_addr_t phys_addr, unsigned long size, pgprot_t prot)
 {
 	BUG();
 	return NULL;
diff --git a/arch/sh/include/asm/mmu.h b/arch/sh/include/asm/mmu.h
index 15a05b6..19fe845 100644
--- a/arch/sh/include/asm/mmu.h
+++ b/arch/sh/include/asm/mmu.h
@@ -55,19 +55,29 @@
 
 #ifdef CONFIG_PMB
 /* arch/sh/mm/pmb.c */
-long pmb_remap(unsigned long virt, unsigned long phys,
-	       unsigned long size, pgprot_t prot);
-void pmb_unmap(unsigned long addr);
-void pmb_init(void);
 bool __in_29bit_mode(void);
+
+void pmb_init(void);
+int pmb_bolt_mapping(unsigned long virt, phys_addr_t phys,
+		     unsigned long size, pgprot_t prot);
+void __iomem *pmb_remap_caller(phys_addr_t phys, unsigned long size,
+			       pgprot_t prot, void *caller);
+int pmb_unmap(void __iomem *addr);
+
 #else
-static inline long pmb_remap(unsigned long virt, unsigned long phys,
-			     unsigned long size, pgprot_t prot)
+
+static inline void __iomem *
+pmb_remap_caller(phys_addr_t phys, unsigned long size,
+		 pgprot_t prot, void *caller)
+{
+	return NULL;
+}
+
+static inline int pmb_unmap(void __iomem *addr)
 {
 	return -EINVAL;
 }
 
-#define pmb_unmap(addr)		do { } while (0)
 #define pmb_init(addr)		do { } while (0)
 
 #ifdef CONFIG_29BIT
@@ -77,6 +87,13 @@
 #endif
 
 #endif /* CONFIG_PMB */
+
+static inline void __iomem *
+pmb_remap(phys_addr_t phys, unsigned long size, pgprot_t prot)
+{
+	return pmb_remap_caller(phys, size, prot, __builtin_return_address(0));
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __MMU_H */
diff --git a/arch/sh/include/asm/pci.h b/arch/sh/include/asm/pci.h
index 1042f7f..8bd952f 100644
--- a/arch/sh/include/asm/pci.h
+++ b/arch/sh/include/asm/pci.h
@@ -83,25 +83,6 @@
  */
 #define PCI_DMA_BUS_IS_PHYS	(dma_ops->is_phys)
 
-/* pci_unmap_{single,page} being a nop depends upon the
- * configuration.
- */
-#ifdef CONFIG_DMA_NONCOHERENT
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)		((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)		((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	(((PTR)->LEN_NAME) = (VAL))
-#else
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME)		(0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
-#endif
-
 #ifdef CONFIG_PCI
 /*
  * None of the SH PCI controllers support MWI, it is always treated as a
diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h
index e11b14e..2168fde 100644
--- a/arch/sh/include/asm/ptrace.h
+++ b/arch/sh/include/asm/ptrace.h
@@ -123,8 +123,6 @@
 struct task_struct;
 
 #define arch_has_single_step()	(1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
 
 struct perf_event;
 struct perf_sample_data;
diff --git a/arch/sh/include/asm/siu.h b/arch/sh/include/asm/siu.h
index 57565a3..f1b1e69 100644
--- a/arch/sh/include/asm/siu.h
+++ b/arch/sh/include/asm/siu.h
@@ -11,7 +11,7 @@
 #ifndef ASM_SIU_H
 #define ASM_SIU_H
 
-#include <asm/dma-sh.h>
+#include <asm/dmaengine.h>
 
 struct device;
 
diff --git a/arch/sh/include/asm/syscalls.h b/arch/sh/include/asm/syscalls.h
index c1e2b8d..507725a 100644
--- a/arch/sh/include/asm/syscalls.h
+++ b/arch/sh/include/asm/syscalls.h
@@ -3,17 +3,12 @@
 
 #ifdef __KERNEL__
 
-struct old_utsname;
-
 asmlinkage int old_mmap(unsigned long addr, unsigned long len,
 			unsigned long prot, unsigned long flags,
 			int fd, unsigned long off);
 asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
 			  unsigned long prot, unsigned long flags,
 			  unsigned long fd, unsigned long pgoff);
-asmlinkage int sys_ipc(uint call, int first, int second,
-		       int third, void __user *ptr, long fifth);
-asmlinkage int sys_uname(struct old_utsname __user *name);
 
 #ifdef CONFIG_SUPERH32
 # include "syscalls_32.h"
diff --git a/arch/sh/include/asm/topology.h b/arch/sh/include/asm/topology.h
index 37cdadd..88e7340 100644
--- a/arch/sh/include/asm/topology.h
+++ b/arch/sh/include/asm/topology.h
@@ -35,7 +35,7 @@
 
 #define pcibus_to_node(bus)	((void)(bus), -1)
 #define cpumask_of_pcibus(bus)	(pcibus_to_node(bus) == -1 ? \
-					CPU_MASK_ALL_PTR : \
+					cpu_all_mask : \
 					cpumask_of_node(pcibus_to_node(bus)))
 
 #endif
diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h
index 365744b..0e7f0fc 100644
--- a/arch/sh/include/asm/unistd_32.h
+++ b/arch/sh/include/asm/unistd_32.h
@@ -358,6 +358,7 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
@@ -370,6 +371,7 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_UNAME
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h
index 25de158..0580c33 100644
--- a/arch/sh/include/asm/unistd_64.h
+++ b/arch/sh/include/asm/unistd_64.h
@@ -398,6 +398,7 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
@@ -410,6 +411,7 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_UNAME
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/sh/include/cpu-sh3/cpu/dma-register.h b/arch/sh/include/cpu-sh3/cpu/dma-register.h
new file mode 100644
index 0000000..2349e48
--- /dev/null
+++ b/arch/sh/include/cpu-sh3/cpu/dma-register.h
@@ -0,0 +1,41 @@
+/*
+ * SH3 CPU-specific DMA definitions, used by both DMA drivers
+ *
+ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.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.
+ */
+#ifndef CPU_DMA_REGISTER_H
+#define CPU_DMA_REGISTER_H
+
+#define CHCR_TS_LOW_MASK	0x18
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
+
+#define DMAOR_INIT	DMAOR_DME
+
+/*
+ * The SuperH DMAC supports a number of transmit sizes, we list them here,
+ * with their respective values as they appear in the CHCR registers.
+ */
+enum {
+	XMIT_SZ_8BIT,
+	XMIT_SZ_16BIT,
+	XMIT_SZ_32BIT,
+	XMIT_SZ_128BIT,
+};
+
+/* log2(size / 8) - used to calculate number of transfers */
+#define TS_SHIFT {			\
+	[XMIT_SZ_8BIT]		= 0,	\
+	[XMIT_SZ_16BIT]		= 1,	\
+	[XMIT_SZ_32BIT]		= 2,	\
+	[XMIT_SZ_128BIT]	= 4,	\
+}
+
+#define TS_INDEX2VAL(i)	(((i) & 3) << CHCR_TS_LOW_SHIFT)
+
+#endif
diff --git a/arch/sh/include/cpu-sh3/cpu/dma.h b/arch/sh/include/cpu-sh3/cpu/dma.h
index 207811a..24e28b9 100644
--- a/arch/sh/include/cpu-sh3/cpu/dma.h
+++ b/arch/sh/include/cpu-sh3/cpu/dma.h
@@ -20,31 +20,4 @@
 #define TS_32		0x00000010
 #define TS_128		0x00000018
 
-#define CHCR_TS_LOW_MASK	0x18
-#define CHCR_TS_LOW_SHIFT	3
-#define CHCR_TS_HIGH_MASK	0
-#define CHCR_TS_HIGH_SHIFT	0
-
-#define DMAOR_INIT	DMAOR_DME
-
-/*
- * The SuperH DMAC supports a number of transmit sizes, we list them here,
- * with their respective values as they appear in the CHCR registers.
- */
-enum {
-	XMIT_SZ_8BIT,
-	XMIT_SZ_16BIT,
-	XMIT_SZ_32BIT,
-	XMIT_SZ_128BIT,
-};
-
-#define TS_SHIFT {			\
-	[XMIT_SZ_8BIT]		= 0,	\
-	[XMIT_SZ_16BIT]		= 1,	\
-	[XMIT_SZ_32BIT]		= 2,	\
-	[XMIT_SZ_128BIT]	= 4,	\
-}
-
-#define TS_INDEX2VAL(i)	(((i) & 3) << CHCR_TS_LOW_SHIFT)
-
 #endif /* __ASM_CPU_SH3_DMA_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-register.h b/arch/sh/include/cpu-sh4/cpu/dma-register.h
new file mode 100644
index 0000000..55f9fec
--- /dev/null
+++ b/arch/sh/include/cpu-sh4/cpu/dma-register.h
@@ -0,0 +1,112 @@
+/*
+ * SH4 CPU-specific DMA definitions, used by both DMA drivers
+ *
+ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.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.
+ */
+#ifndef CPU_DMA_REGISTER_H
+#define CPU_DMA_REGISTER_H
+
+/* SH7751/7760/7780 DMA IRQ sources */
+
+#ifdef CONFIG_CPU_SH4A
+
+#define DMAOR_INIT	DMAOR_DME
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7343) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7730)
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0x00300000
+#define CHCR_TS_HIGH_SHIFT	(20 - 2)	/* 2 bits for shifted low TS */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7764)
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
+#else /* SH7785 */
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
+#endif
+
+/* Transmit sizes and respective CHCR register values */
+enum {
+	XMIT_SZ_8BIT		= 0,
+	XMIT_SZ_16BIT		= 1,
+	XMIT_SZ_32BIT		= 2,
+	XMIT_SZ_64BIT		= 7,
+	XMIT_SZ_128BIT		= 3,
+	XMIT_SZ_256BIT		= 4,
+	XMIT_SZ_128BIT_BLK	= 0xb,
+	XMIT_SZ_256BIT_BLK	= 0xc,
+};
+
+/* log2(size / 8) - used to calculate number of transfers */
+#define TS_SHIFT {			\
+	[XMIT_SZ_8BIT]		= 0,	\
+	[XMIT_SZ_16BIT]		= 1,	\
+	[XMIT_SZ_32BIT]		= 2,	\
+	[XMIT_SZ_64BIT]		= 3,	\
+	[XMIT_SZ_128BIT]	= 4,	\
+	[XMIT_SZ_256BIT]	= 5,	\
+	[XMIT_SZ_128BIT_BLK]	= 4,	\
+	[XMIT_SZ_256BIT_BLK]	= 5,	\
+}
+
+#define TS_INDEX2VAL(i)	((((i) & 3) << CHCR_TS_LOW_SHIFT) | \
+			 ((((i) >> 2) & 3) << CHCR_TS_HIGH_SHIFT))
+
+#else /* CONFIG_CPU_SH4A */
+
+#define DMAOR_INIT	(0x8000 | DMAOR_DME)
+
+#define CHCR_TS_LOW_MASK	0x70
+#define CHCR_TS_LOW_SHIFT	4
+#define CHCR_TS_HIGH_MASK	0
+#define CHCR_TS_HIGH_SHIFT	0
+
+/* Transmit sizes and respective CHCR register values */
+enum {
+	XMIT_SZ_8BIT	= 1,
+	XMIT_SZ_16BIT	= 2,
+	XMIT_SZ_32BIT	= 3,
+	XMIT_SZ_64BIT	= 0,
+	XMIT_SZ_256BIT	= 4,
+};
+
+/* log2(size / 8) - used to calculate number of transfers */
+#define TS_SHIFT {			\
+	[XMIT_SZ_8BIT]		= 0,	\
+	[XMIT_SZ_16BIT]		= 1,	\
+	[XMIT_SZ_32BIT]		= 2,	\
+	[XMIT_SZ_64BIT]		= 3,	\
+	[XMIT_SZ_256BIT]	= 5,	\
+}
+
+#define TS_INDEX2VAL(i)	(((i) & 7) << CHCR_TS_LOW_SHIFT)
+
+#endif /* CONFIG_CPU_SH4A */
+
+#endif
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
index e734ea4..9647e68 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
@@ -8,20 +8,12 @@
 #define DMAE0_IRQ	78	/* DMA Error IRQ*/
 #define SH_DMAC_BASE0	0xFE008020
 #define SH_DMARS_BASE0	0xFE009000
-#define CHCR_TS_LOW_MASK	0x00000018
-#define CHCR_TS_LOW_SHIFT	3
-#define CHCR_TS_HIGH_MASK	0
-#define CHCR_TS_HIGH_SHIFT	0
 #elif defined(CONFIG_CPU_SUBTYPE_SH7722)
 #define DMTE0_IRQ	48
 #define DMTE4_IRQ	76
 #define DMAE0_IRQ	78	/* DMA Error IRQ*/
 #define SH_DMAC_BASE0	0xFE008020
 #define SH_DMARS_BASE0	0xFE009000
-#define CHCR_TS_LOW_MASK	0x00000018
-#define CHCR_TS_LOW_SHIFT	3
-#define CHCR_TS_HIGH_MASK	0x00300000
-#define CHCR_TS_HIGH_SHIFT	20
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
 	defined(CONFIG_CPU_SUBTYPE_SH7764)
 #define DMTE0_IRQ	34
@@ -29,10 +21,6 @@
 #define DMAE0_IRQ	38
 #define SH_DMAC_BASE0	0xFF608020
 #define SH_DMARS_BASE0	0xFF609000
-#define CHCR_TS_LOW_MASK	0x00000018
-#define CHCR_TS_LOW_SHIFT	3
-#define CHCR_TS_HIGH_MASK	0
-#define CHCR_TS_HIGH_SHIFT	0
 #elif defined(CONFIG_CPU_SUBTYPE_SH7723)
 #define DMTE0_IRQ	48	/* DMAC0A*/
 #define DMTE4_IRQ	76	/* DMAC0B */
@@ -46,10 +34,6 @@
 #define SH_DMAC_BASE0	0xFE008020
 #define SH_DMAC_BASE1	0xFDC08020
 #define SH_DMARS_BASE0	0xFDC09000
-#define CHCR_TS_LOW_MASK	0x00000018
-#define CHCR_TS_LOW_SHIFT	3
-#define CHCR_TS_HIGH_MASK	0
-#define CHCR_TS_HIGH_SHIFT	0
 #elif defined(CONFIG_CPU_SUBTYPE_SH7724)
 #define DMTE0_IRQ	48	/* DMAC0A*/
 #define DMTE4_IRQ	76	/* DMAC0B */
@@ -64,10 +48,6 @@
 #define SH_DMAC_BASE1	0xFDC08020
 #define SH_DMARS_BASE0	0xFE009000
 #define SH_DMARS_BASE1	0xFDC09000
-#define CHCR_TS_LOW_MASK	0x00000018
-#define CHCR_TS_LOW_SHIFT	3
-#define CHCR_TS_HIGH_MASK	0x00600000
-#define CHCR_TS_HIGH_SHIFT	21
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define DMTE0_IRQ	34
 #define DMTE4_IRQ	44
@@ -80,10 +60,6 @@
 #define SH_DMAC_BASE0	0xFC808020
 #define SH_DMAC_BASE1	0xFC818020
 #define SH_DMARS_BASE0	0xFC809000
-#define CHCR_TS_LOW_MASK	0x00000018
-#define CHCR_TS_LOW_SHIFT	3
-#define CHCR_TS_HIGH_MASK	0
-#define CHCR_TS_HIGH_SHIFT	0
 #else /* SH7785 */
 #define DMTE0_IRQ	33
 #define DMTE4_IRQ	37
@@ -97,10 +73,6 @@
 #define SH_DMAC_BASE0	0xFC808020
 #define SH_DMAC_BASE1	0xFCC08020
 #define SH_DMARS_BASE0	0xFC809000
-#define CHCR_TS_LOW_MASK	0x00000018
-#define CHCR_TS_LOW_SHIFT	3
-#define CHCR_TS_HIGH_MASK	0
-#define CHCR_TS_HIGH_SHIFT	0
 #endif
 
 #define REQ_HE		0x000000C0
@@ -108,38 +80,4 @@
 #define REQ_LE		0x00000040
 #define TM_BURST	0x00000020
 
-/*
- * The SuperH DMAC supports a number of transmit sizes, we list them here,
- * with their respective values as they appear in the CHCR registers.
- *
- * Defaults to a 64-bit transfer size.
- */
-enum {
-	XMIT_SZ_8BIT		= 0,
-	XMIT_SZ_16BIT		= 1,
-	XMIT_SZ_32BIT		= 2,
-	XMIT_SZ_64BIT		= 7,
-	XMIT_SZ_128BIT		= 3,
-	XMIT_SZ_256BIT		= 4,
-	XMIT_SZ_128BIT_BLK	= 0xb,
-	XMIT_SZ_256BIT_BLK	= 0xc,
-};
-
-/*
- * The DMA count is defined as the number of bytes to transfer.
- */
-#define TS_SHIFT {			\
-	[XMIT_SZ_8BIT]		= 0,	\
-	[XMIT_SZ_16BIT]		= 1,	\
-	[XMIT_SZ_32BIT]		= 2,	\
-	[XMIT_SZ_64BIT]		= 3,	\
-	[XMIT_SZ_128BIT]	= 4,	\
-	[XMIT_SZ_256BIT]	= 5,	\
-	[XMIT_SZ_128BIT_BLK]	= 4,	\
-	[XMIT_SZ_256BIT_BLK]	= 5,	\
-}
-
-#define TS_INDEX2VAL(i)	((((i) & 3) << CHCR_TS_LOW_SHIFT) | \
-			 ((((i) >> 2) & 3) << CHCR_TS_HIGH_SHIFT))
-
 #endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma.h b/arch/sh/include/cpu-sh4/cpu/dma.h
index 114a369..ca747e9 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma.h
@@ -5,9 +5,8 @@
 
 #ifdef CONFIG_CPU_SH4A
 
-#define DMAOR_INIT	(DMAOR_DME)
-
 #include <cpu/dma-sh4a.h>
+
 #else /* CONFIG_CPU_SH4A */
 /*
  * SH7750/SH7751/SH7760
@@ -17,7 +16,6 @@
 #define DMTE6_IRQ	46
 #define DMAE0_IRQ	38
 
-#define DMAOR_INIT	(0x8000|DMAOR_DME)
 #define SH_DMAC_BASE0	0xffa00000
 #define SH_DMAC_BASE1	0xffa00070
 /* Definitions for the SuperH DMAC */
@@ -27,40 +25,8 @@
 #define TS_32		0x00000030
 #define TS_64		0x00000000
 
-#define CHCR_TS_LOW_MASK	0x70
-#define CHCR_TS_LOW_SHIFT	4
-#define CHCR_TS_HIGH_MASK	0
-#define CHCR_TS_HIGH_SHIFT	0
-
 #define DMAOR_COD	0x00000008
 
-/*
- * The SuperH DMAC supports a number of transmit sizes, we list them here,
- * with their respective values as they appear in the CHCR registers.
- *
- * Defaults to a 64-bit transfer size.
- */
-enum {
-	XMIT_SZ_8BIT	= 1,
-	XMIT_SZ_16BIT	= 2,
-	XMIT_SZ_32BIT	= 3,
-	XMIT_SZ_64BIT	= 0,
-	XMIT_SZ_256BIT	= 4,
-};
-
-/*
- * The DMA count is defined as the number of bytes to transfer.
- */
-#define TS_SHIFT {			\
-	[XMIT_SZ_8BIT]		= 0,	\
-	[XMIT_SZ_16BIT]		= 1,	\
-	[XMIT_SZ_32BIT]		= 2,	\
-	[XMIT_SZ_64BIT]		= 3,	\
-	[XMIT_SZ_256BIT]	= 5,	\
-}
-
-#define TS_INDEX2VAL(i)	(((i) & 7) << CHCR_TS_LOW_SHIFT)
-
 #endif
 
 #endif /* __ASM_CPU_SH4_DMA_H */
diff --git a/arch/sh/include/mach-migor/mach/migor.h b/arch/sh/include/mach-migor/mach/migor.h
index cee6cb8..42fccf9 100644
--- a/arch/sh/include/mach-migor/mach/migor.h
+++ b/arch/sh/include/mach-migor/mach/migor.h
@@ -1,6 +1,7 @@
 #ifndef __ASM_SH_MIGOR_H
 #define __ASM_SH_MIGOR_H
 
+#define PORT_MSELCRA 0xa4050180
 #define PORT_MSELCRB 0xa4050182
 #define BSC_CS4BCR 0xfec10010
 #define BSC_CS6ABCR 0xfec1001c
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 83da5de..e9fa1bfe 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -404,7 +404,7 @@
  *  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 precidence: dev+con > dev only > con only.
+ * order of precedence: dev+con > dev only > con only.
  */
 static struct clk *clk_find(const char *dev_id, const char *con_id)
 {
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index fc065f9..14726ee 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -326,7 +326,7 @@
 	NULL,
 };
 
-static struct sysfs_ops sq_sysfs_ops = {
+static const struct sysfs_ops sq_sysfs_ops = {
 	.show	= sq_sysfs_show,
 	.store	= sq_sysfs_store,
 };
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index ef3f978..fd7e363 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -7,19 +7,167 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-#include <linux/platform_device.h>
 #include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
-#include <linux/mm.h>
+#include <linux/sh_timer.h>
 #include <linux/uio_driver.h>
 #include <linux/usb/m66592.h>
-#include <linux/sh_timer.h>
+
 #include <asm/clock.h>
+#include <asm/dmaengine.h>
 #include <asm/mmzone.h>
-#include <asm/dma-sh.h>
+#include <asm/siu.h>
+
+#include <cpu/dma-register.h>
 #include <cpu/sh7722.h>
 
+static struct sh_dmae_slave_config sh7722_dmae_slaves[] = {
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF0_TX,
+		.addr		= 0xffe0000c,
+		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x21,
+	}, {
+		.slave_id	= SHDMA_SLAVE_SCIF0_RX,
+		.addr		= 0xffe00014,
+		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x22,
+	}, {
+		.slave_id	= SHDMA_SLAVE_SCIF1_TX,
+		.addr		= 0xffe1000c,
+		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x25,
+	}, {
+		.slave_id	= SHDMA_SLAVE_SCIF1_RX,
+		.addr		= 0xffe10014,
+		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x26,
+	}, {
+		.slave_id	= SHDMA_SLAVE_SCIF2_TX,
+		.addr		= 0xffe2000c,
+		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x29,
+	}, {
+		.slave_id	= SHDMA_SLAVE_SCIF2_RX,
+		.addr		= 0xffe20014,
+		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x2a,
+	}, {
+		.slave_id	= SHDMA_SLAVE_SIUA_TX,
+		.addr		= 0xa454c098,
+		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.mid_rid	= 0xb1,
+	}, {
+		.slave_id	= SHDMA_SLAVE_SIUA_RX,
+		.addr		= 0xa454c090,
+		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.mid_rid	= 0xb2,
+	}, {
+		.slave_id	= SHDMA_SLAVE_SIUB_TX,
+		.addr		= 0xa454c09c,
+		.chcr		= DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.mid_rid	= 0xb5,
+	}, {
+		.slave_id	= SHDMA_SLAVE_SIUB_RX,
+		.addr		= 0xa454c094,
+		.chcr		= DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.mid_rid	= 0xb6,
+	},
+};
+
+static struct sh_dmae_channel sh7722_dmae_channels[] = {
+	{
+		.offset = 0,
+		.dmars = 0,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x10,
+		.dmars = 0,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x20,
+		.dmars = 4,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x30,
+		.dmars = 4,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x50,
+		.dmars = 8,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x60,
+		.dmars = 8,
+		.dmars_bit = 8,
+	}
+};
+
+static unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma_platform_data = {
+	.slave		= sh7722_dmae_slaves,
+	.slave_num	= ARRAY_SIZE(sh7722_dmae_slaves),
+	.channel	= sh7722_dmae_channels,
+	.channel_num	= ARRAY_SIZE(sh7722_dmae_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct resource sh7722_dmae_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xfe008020,
+		.end	= 0xfe00808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xfe009000,
+		.end	= 0xfe00900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMA error IRQ */
+		.start	= 78,
+		.end	= 78,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channels 0-3 */
+		.start	= 48,
+		.end	= 51,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channels 4-5 */
+		.start	= 76,
+		.end	= 77,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device dma_device = {
+	.name		= "sh-dma-engine",
+	.id		= -1,
+	.resource	= sh7722_dmae_resources,
+	.num_resources	= ARRAY_SIZE(sh7722_dmae_resources),
+	.dev		= {
+		.platform_data	= &dma_platform_data,
+	},
+	.archdata = {
+		.hwblk_id = HWBLK_DMAC,
+	},
+};
+
 /* Serial */
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase        = 0xffe00000,
@@ -388,15 +536,36 @@
 	},
 };
 
-static struct sh_dmae_pdata dma_platform_data = {
-	.mode = 0,
+static struct siu_platform siu_platform_data = {
+	.dma_dev	= &dma_device.dev,
+	.dma_slave_tx_a	= SHDMA_SLAVE_SIUA_TX,
+	.dma_slave_rx_a	= SHDMA_SLAVE_SIUA_RX,
+	.dma_slave_tx_b	= SHDMA_SLAVE_SIUB_TX,
+	.dma_slave_rx_b	= SHDMA_SLAVE_SIUB_RX,
 };
 
-static struct platform_device dma_device = {
-	.name		= "sh-dma-engine",
+static struct resource siu_resources[] = {
+	[0] = {
+		.start	= 0xa4540000,
+		.end	= 0xa454c10f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 108,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device siu_device = {
+	.name		= "sh_siu",
 	.id		= -1,
-	.dev		= {
-		.platform_data	= &dma_platform_data,
+	.dev = {
+		.platform_data	= &siu_platform_data,
+	},
+	.resource	= siu_resources,
+	.num_resources	= ARRAY_SIZE(siu_resources),
+	.archdata = {
+		.hwblk_id = HWBLK_SIU,
 	},
 };
 
@@ -414,6 +583,7 @@
 	&vpu_device,
 	&veu_device,
 	&jpu_device,
+	&siu_device,
 	&dma_device,
 };
 
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index 31e3451..e7fa2a9 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -21,22 +21,189 @@
 #include <linux/sh_timer.h>
 #include <linux/io.h>
 #include <linux/notifier.h>
+
 #include <asm/suspend.h>
 #include <asm/clock.h>
-#include <asm/dma-sh.h>
+#include <asm/dmaengine.h>
 #include <asm/mmzone.h>
+
+#include <cpu/dma-register.h>
 #include <cpu/sh7724.h>
 
 /* DMA */
-static struct sh_dmae_pdata dma_platform_data = {
-	.mode = SHDMA_DMAOR1,
+static struct sh_dmae_channel sh7724_dmae0_channels[] = {
+	{
+		.offset = 0,
+		.dmars = 0,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x10,
+		.dmars = 0,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x20,
+		.dmars = 4,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x30,
+		.dmars = 4,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x50,
+		.dmars = 8,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x60,
+		.dmars = 8,
+		.dmars_bit = 8,
+	}
 };
 
-static struct platform_device dma_device = {
-	.name	= "sh-dma-engine",
-	.id		= -1,
-	.dev	= {
-		.platform_data	= &dma_platform_data,
+static struct sh_dmae_channel sh7724_dmae1_channels[] = {
+	{
+		.offset = 0,
+		.dmars = 0,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x10,
+		.dmars = 0,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x20,
+		.dmars = 4,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x30,
+		.dmars = 4,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x50,
+		.dmars = 8,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x60,
+		.dmars = 8,
+		.dmars_bit = 8,
+	}
+};
+
+static unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+	.channel	= sh7724_dmae0_channels,
+	.channel_num	= ARRAY_SIZE(sh7724_dmae0_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+	.channel	= sh7724_dmae1_channels,
+	.channel_num	= ARRAY_SIZE(sh7724_dmae1_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+/* Resource order important! */
+static struct resource sh7724_dmae0_resources[] = {
+	{
+		/* Channel registers and DMAOR */
+		.start	= 0xfe008020,
+		.end	= 0xfe00808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMARSx */
+		.start	= 0xfe009000,
+		.end	= 0xfe00900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMA error IRQ */
+		.start	= 78,
+		.end	= 78,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channels 0-3 */
+		.start	= 48,
+		.end	= 51,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channels 4-5 */
+		.start	= 76,
+		.end	= 77,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/* Resource order important! */
+static struct resource sh7724_dmae1_resources[] = {
+	{
+		/* Channel registers and DMAOR */
+		.start	= 0xfdc08020,
+		.end	= 0xfdc0808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMARSx */
+		.start	= 0xfdc09000,
+		.end	= 0xfdc0900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMA error IRQ */
+		.start	= 74,
+		.end	= 74,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channels 0-3 */
+		.start	= 40,
+		.end	= 43,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channels 4-5 */
+		.start	= 72,
+		.end	= 73,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device dma0_device = {
+	.name		= "sh-dma-engine",
+	.id		= 0,
+	.resource	= sh7724_dmae0_resources,
+	.num_resources	= ARRAY_SIZE(sh7724_dmae0_resources),
+	.dev		= {
+		.platform_data	= &dma0_platform_data,
+	},
+	.archdata = {
+		.hwblk_id = HWBLK_DMAC0,
+	},
+};
+
+static struct platform_device dma1_device = {
+	.name		= "sh-dma-engine",
+	.id		= 1,
+	.resource	= sh7724_dmae1_resources,
+	.num_resources	= ARRAY_SIZE(sh7724_dmae1_resources),
+	.dev		= {
+		.platform_data	= &dma1_platform_data,
+	},
+	.archdata = {
+		.hwblk_id = HWBLK_DMAC1,
 	},
 };
 
@@ -663,7 +830,8 @@
 	&tmu3_device,
 	&tmu4_device,
 	&tmu5_device,
-	&dma_device,
+	&dma0_device,
+	&dma1_device,
 	&rtc_device,
 	&iic0_device,
 	&iic1_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index f8f2161..02e792c 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -13,7 +13,10 @@
 #include <linux/io.h>
 #include <linux/serial_sci.h>
 #include <linux/sh_timer.h>
-#include <asm/dma-sh.h>
+
+#include <asm/dmaengine.h>
+
+#include <cpu/dma-register.h>
 
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xffe00000,
@@ -247,15 +250,131 @@
 	.resource	= rtc_resources,
 };
 
-static struct sh_dmae_pdata dma_platform_data = {
-	.mode = (SHDMA_MIX_IRQ | SHDMA_DMAOR1),
+/* DMA */
+static struct sh_dmae_channel sh7780_dmae0_channels[] = {
+	{
+		.offset = 0,
+		.dmars = 0,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x10,
+		.dmars = 0,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x20,
+		.dmars = 4,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x30,
+		.dmars = 4,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x50,
+		.dmars = 8,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x60,
+		.dmars = 8,
+		.dmars_bit = 8,
+	}
 };
 
-static struct platform_device dma_device = {
+static struct sh_dmae_channel sh7780_dmae1_channels[] = {
+	{
+		.offset = 0,
+	}, {
+		.offset = 0x10,
+	}, {
+		.offset = 0x20,
+	}, {
+		.offset = 0x30,
+	}, {
+		.offset = 0x50,
+	}, {
+		.offset = 0x60,
+	}
+};
+
+static unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+	.channel	= sh7780_dmae0_channels,
+	.channel_num	= ARRAY_SIZE(sh7780_dmae0_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+	.channel	= sh7780_dmae1_channels,
+	.channel_num	= ARRAY_SIZE(sh7780_dmae1_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct resource sh7780_dmae0_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xfc808020,
+		.end	= 0xfc80808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xfc809000,
+		.end	= 0xfc80900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* Real DMA error IRQ is 38, and channel IRQs are 34-37, 44-45 */
+		.start	= 34,
+		.end	= 34,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+};
+
+static struct resource sh7780_dmae1_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xfc818020,
+		.end	= 0xfc81808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	/* DMAC1 has no DMARS */
+	{
+		/* Real DMA error IRQ is 38, and channel IRQs are 46-47, 92-95 */
+		.start	= 46,
+		.end	= 46,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+};
+
+static struct platform_device dma0_device = {
 	.name           = "sh-dma-engine",
-	.id             = -1,
+	.id             = 0,
+	.resource	= sh7780_dmae0_resources,
+	.num_resources	= ARRAY_SIZE(sh7780_dmae0_resources),
 	.dev            = {
-		.platform_data  = &dma_platform_data,
+		.platform_data	= &dma0_platform_data,
+	},
+};
+
+static struct platform_device dma1_device = {
+	.name		= "sh-dma-engine",
+	.id		= 1,
+	.resource	= sh7780_dmae1_resources,
+	.num_resources	= ARRAY_SIZE(sh7780_dmae1_resources),
+	.dev		= {
+		.platform_data	= &dma1_platform_data,
 	},
 };
 
@@ -269,7 +388,8 @@
 	&tmu4_device,
 	&tmu5_device,
 	&rtc_device,
-	&dma_device,
+	&dma0_device,
+	&dma1_device,
 };
 
 static int __init sh7780_devices_setup(void)
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index 23448d8..1fcd88b 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -14,9 +14,12 @@
 #include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/sh_timer.h>
-#include <asm/dma-sh.h>
+
+#include <asm/dmaengine.h>
 #include <asm/mmzone.h>
 
+#include <cpu/dma-register.h>
+
 static struct plat_sci_port scif0_platform_data = {
 	.mapbase	= 0xffea0000,
 	.flags		= UPF_BOOT_AUTOCONF,
@@ -295,15 +298,131 @@
 	.num_resources	= ARRAY_SIZE(tmu5_resources),
 };
 
-static struct sh_dmae_pdata dma_platform_data = {
-	.mode = (SHDMA_MIX_IRQ | SHDMA_DMAOR1),
+/* DMA */
+static struct sh_dmae_channel sh7785_dmae0_channels[] = {
+	{
+		.offset = 0,
+		.dmars = 0,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x10,
+		.dmars = 0,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x20,
+		.dmars = 4,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x30,
+		.dmars = 4,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x50,
+		.dmars = 8,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x60,
+		.dmars = 8,
+		.dmars_bit = 8,
+	}
 };
 
-static struct platform_device dma_device = {
+static struct sh_dmae_channel sh7785_dmae1_channels[] = {
+	{
+		.offset = 0,
+	}, {
+		.offset = 0x10,
+	}, {
+		.offset = 0x20,
+	}, {
+		.offset = 0x30,
+	}, {
+		.offset = 0x50,
+	}, {
+		.offset = 0x60,
+	}
+};
+
+static unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+	.channel	= sh7785_dmae0_channels,
+	.channel_num	= ARRAY_SIZE(sh7785_dmae0_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+	.channel	= sh7785_dmae1_channels,
+	.channel_num	= ARRAY_SIZE(sh7785_dmae1_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct resource sh7785_dmae0_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xfc808020,
+		.end	= 0xfc80808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xfc809000,
+		.end	= 0xfc80900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* Real DMA error IRQ is 39, and channel IRQs are 33-38 */
+		.start	= 33,
+		.end	= 33,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+};
+
+static struct resource sh7785_dmae1_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xfcc08020,
+		.end	= 0xfcc0808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	/* DMAC1 has no DMARS */
+	{
+		/* Real DMA error IRQ is 58, and channel IRQs are 52-57 */
+		.start	= 52,
+		.end	= 52,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+};
+
+static struct platform_device dma0_device = {
 	.name           = "sh-dma-engine",
-	.id             = -1,
+	.id             = 0,
+	.resource	= sh7785_dmae0_resources,
+	.num_resources	= ARRAY_SIZE(sh7785_dmae0_resources),
 	.dev            = {
-		.platform_data  = &dma_platform_data,
+		.platform_data	= &dma0_platform_data,
+	},
+};
+
+static struct platform_device dma1_device = {
+	.name		= "sh-dma-engine",
+	.id		= 1,
+	.resource	= sh7785_dmae1_resources,
+	.num_resources	= ARRAY_SIZE(sh7785_dmae1_resources),
+	.dev		= {
+		.platform_data	= &dma1_platform_data,
 	},
 };
 
@@ -320,7 +439,8 @@
 	&tmu3_device,
 	&tmu4_device,
 	&tmu5_device,
-	&dma_device,
+	&dma0_device,
+	&dma1_device,
 };
 
 static int __init sh7785_devices_setup(void)
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c
index e2f1753..675eea7 100644
--- a/arch/sh/kernel/hw_breakpoint.c
+++ b/arch/sh/kernel/hw_breakpoint.c
@@ -143,26 +143,6 @@
 	return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
 }
 
-/*
- * Store a breakpoint's encoded address, length, and type.
- */
-static int arch_store_info(struct perf_event *bp)
-{
-	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
-
-	/*
-	 * User-space requests will always have the address field populated
-	 * For kernel-addresses, either the address or symbol name can be
-	 * specified.
-	 */
-	if (info->name)
-		info->address = (unsigned long)kallsyms_lookup_name(info->name);
-	if (info->address)
-		return 0;
-
-	return -EINVAL;
-}
-
 int arch_bp_generic_fields(int sh_len, int sh_type,
 			   int *gen_len, int *gen_type)
 {
@@ -276,10 +256,12 @@
 		return ret;
 	}
 
-	ret = arch_store_info(bp);
-
-	if (ret < 0)
-		return ret;
+	/*
+	 * For kernel-addresses, either the address or symbol name can be
+	 * specified.
+	 */
+	if (info->name)
+		info->address = (unsigned long)kallsyms_lookup_name(info->name);
 
 	/*
 	 * Check that the low-order bits of the address are appropriate
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 3459e70..8870d6b 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -443,7 +443,7 @@
 
 	nodes_clear(node_online_map);
 
-	/* Setup bootmem with available RAM */
+	pmb_init();
 	lmb_init();
 	setup_memory();
 	sparse_init();
@@ -452,7 +452,6 @@
 	conswitchp = &dummy_con;
 #endif
 	paging_init();
-	pmb_init();
 
 	ioremap_fixed_init();
 
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index 71399cd..81f5837 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -53,110 +53,6 @@
 	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
 }
 
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage int sys_ipc(uint call, int first, int second,
-		       int third, void __user *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	if (call <= SEMTIMEDOP)
-		switch (call) {
-		case SEMOP:
-			return sys_semtimedop(first,
-					      (struct sembuf __user *)ptr,
-					      second, NULL);
-		case SEMTIMEDOP:
-			return sys_semtimedop(first,
-				(struct sembuf __user *)ptr, second,
-			        (const struct timespec __user *)fifth);
-		case SEMGET:
-			return sys_semget (first, second, third);
-		case SEMCTL: {
-			union semun fourth;
-			if (!ptr)
-				return -EINVAL;
-			if (get_user(fourth.__pad, (void __user * __user *) ptr))
-				return -EFAULT;
-			return sys_semctl (first, second, third, fourth);
-			}
-		default:
-			return -EINVAL;
-		}
-
-	if (call <= MSGCTL)
-		switch (call) {
-		case MSGSND:
-			return sys_msgsnd (first, (struct msgbuf __user *) ptr,
-					  second, third);
-		case MSGRCV:
-			switch (version) {
-			case 0:
-			{
-				struct ipc_kludge tmp;
-
-				if (!ptr)
-					return -EINVAL;
-
-				if (copy_from_user(&tmp,
-					(struct ipc_kludge __user *) ptr,
-						   sizeof (tmp)))
-					return -EFAULT;
-
-				return sys_msgrcv (first, tmp.msgp, second,
-						   tmp.msgtyp, third);
-			}
-			default:
-				return sys_msgrcv (first,
-						   (struct msgbuf __user *) ptr,
-						   second, fifth, third);
-			}
-		case MSGGET:
-			return sys_msgget ((key_t) first, second);
-		case MSGCTL:
-			return sys_msgctl (first, second,
-					   (struct msqid_ds __user *) ptr);
-		default:
-			return -EINVAL;
-		}
-	if (call <= SHMCTL)
-		switch (call) {
-		case SHMAT:
-			switch (version) {
-			default: {
-				ulong raddr;
-				ret = do_shmat (first, (char __user *) ptr,
-						 second, &raddr);
-				if (ret)
-					return ret;
-				return put_user (raddr, (ulong __user *) third);
-			}
-			case 1:	/* iBCS2 emulator entry point */
-				if (!segment_eq(get_fs(), get_ds()))
-					return -EINVAL;
-				return do_shmat (first, (char __user *) ptr,
-						  second, (ulong *) third);
-			}
-		case SHMDT:
-			return sys_shmdt ((char __user *)ptr);
-		case SHMGET:
-			return sys_shmget (first, second, third);
-		case SHMCTL:
-			return sys_shmctl (first, second,
-					   (struct shmid_ds __user *) ptr);
-		default:
-			return -EINVAL;
-		}
-
-	return -EINVAL;
-}
-
 /* sys_cacheflush -- flush (part of) the processor cache.  */
 asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op)
 {
@@ -197,14 +93,3 @@
 	up_read(&current->mm->mmap_sem);
 	return 0;
 }
-
-asmlinkage int sys_uname(struct old_utsname __user *name)
-{
-	int err;
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err = copy_to_user(name, utsname(), sizeof(*name));
-	up_read(&uts_sem);
-	return err?-EFAULT:0;
-}
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 953fa16..8a0072d 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -39,12 +39,12 @@
 void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
 int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
 
-#ifdef CONFIG_GENERIC_CMOS_UPDATE
 void read_persistent_clock(struct timespec *ts)
 {
 	rtc_sh_get_time(ts);
 }
 
+#ifdef CONFIG_GENERIC_CMOS_UPDATE
 int update_persistent_clock(struct timespec now)
 {
 	return rtc_sh_set_time(now.tv_sec);
@@ -113,9 +113,5 @@
 	hwblk_init();
 	clk_init();
 
-	rtc_sh_get_time(&xtime);
-	set_normalized_timespec(&wall_to_monotonic,
-				-xtime.tv_sec, -xtime.tv_nsec);
-
 	late_time_init = sh_late_time_init;
 }
diff --git a/arch/sh/lib/libgcc.h b/arch/sh/lib/libgcc.h
index 3f19d1c..05909d58 100644
--- a/arch/sh/lib/libgcc.h
+++ b/arch/sh/lib/libgcc.h
@@ -17,8 +17,7 @@
 #error I feel sick.
 #endif
 
-typedef union
-{
+typedef union {
 	struct DWstruct s;
 	long long ll;
 } DWunion;
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index c68d2d7..1ab2385 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -34,11 +34,12 @@
  * caller shouldn't need to know that small detail.
  */
 void __iomem * __init_refok
-__ioremap_caller(unsigned long phys_addr, unsigned long size,
+__ioremap_caller(phys_addr_t phys_addr, unsigned long size,
 		 pgprot_t pgprot, void *caller)
 {
 	struct vm_struct *area;
 	unsigned long offset, last_addr, addr, orig_addr;
+	void __iomem *mapped;
 
 	/* Don't allow wraparound or zero size */
 	last_addr = phys_addr + size - 1;
@@ -46,6 +47,20 @@
 		return NULL;
 
 	/*
+	 * If we can't yet use the regular approach, go the fixmap route.
+	 */
+	if (!mem_init_done)
+		return ioremap_fixed(phys_addr, size, pgprot);
+
+	/*
+	 * First try to remap through the PMB.
+	 * PMB entries are all pre-faulted.
+	 */
+	mapped = pmb_remap_caller(phys_addr, size, pgprot, caller);
+	if (mapped && !IS_ERR(mapped))
+		return mapped;
+
+	/*
 	 * Mappings have to be page-aligned
 	 */
 	offset = phys_addr & ~PAGE_MASK;
@@ -53,12 +68,6 @@
 	size = PAGE_ALIGN(last_addr+1) - phys_addr;
 
 	/*
-	 * If we can't yet use the regular approach, go the fixmap route.
-	 */
-	if (!mem_init_done)
-		return ioremap_fixed(phys_addr, offset, size, pgprot);
-
-	/*
 	 * Ok, go for it..
 	 */
 	area = get_vm_area_caller(size, VM_IOREMAP, caller);
@@ -67,33 +76,10 @@
 	area->phys_addr = phys_addr;
 	orig_addr = addr = (unsigned long)area->addr;
 
-#ifdef CONFIG_PMB
-	/*
-	 * First try to remap through the PMB once a valid VMA has been
-	 * established. Smaller allocations (or the rest of the size
-	 * remaining after a PMB mapping due to the size not being
-	 * perfectly aligned on a PMB size boundary) are then mapped
-	 * through the UTLB using conventional page tables.
-	 *
-	 * PMB entries are all pre-faulted.
-	 */
-	if (unlikely(phys_addr >= P1SEG)) {
-		unsigned long mapped;
-
-		mapped = pmb_remap(addr, phys_addr, size, pgprot);
-		if (likely(mapped)) {
-			addr		+= mapped;
-			phys_addr	+= mapped;
-			size		-= mapped;
-		}
+	if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
+		vunmap((void *)orig_addr);
+		return NULL;
 	}
-#endif
-
-	if (likely(size))
-		if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
-			vunmap((void *)orig_addr);
-			return NULL;
-		}
 
 	return (void __iomem *)(offset + (char *)orig_addr);
 }
@@ -133,23 +119,11 @@
 	if (iounmap_fixed(addr) == 0)
 		return;
 
-#ifdef CONFIG_PMB
 	/*
-	 * Purge any PMB entries that may have been established for this
-	 * mapping, then proceed with conventional VMA teardown.
-	 *
-	 * XXX: Note that due to the way that remove_vm_area() does
-	 * matching of the resultant VMA, we aren't able to fast-forward
-	 * the address past the PMB space until the end of the VMA where
-	 * the page tables reside. As such, unmap_vm_area() will be
-	 * forced to linearly scan over the area until it finds the page
-	 * tables where PTEs that need to be unmapped actually reside,
-	 * which is far from optimal. Perhaps we need to use a separate
-	 * VMA for the PMB mappings?
-	 *					-- PFM.
+	 * If the PMB handled it, there's nothing else to do.
 	 */
-	pmb_unmap(vaddr);
-#endif
+	if (pmb_unmap(addr) == 0)
+		return;
 
 	p = remove_vm_area((void *)(vaddr & PAGE_MASK));
 	if (!p) {
diff --git a/arch/sh/mm/ioremap_fixed.c b/arch/sh/mm/ioremap_fixed.c
index 0b78b1e..7f682e5 100644
--- a/arch/sh/mm/ioremap_fixed.c
+++ b/arch/sh/mm/ioremap_fixed.c
@@ -45,14 +45,21 @@
 }
 
 void __init __iomem *
-ioremap_fixed(resource_size_t phys_addr, unsigned long offset,
-	      unsigned long size, pgprot_t prot)
+ioremap_fixed(phys_addr_t phys_addr, unsigned long size, pgprot_t prot)
 {
 	enum fixed_addresses idx0, idx;
 	struct ioremap_map *map;
 	unsigned int nrpages;
+	unsigned long offset;
 	int i, slot;
 
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(phys_addr + size) - phys_addr;
+
 	slot = -1;
 	for (i = 0; i < FIX_N_IOREMAPS; i++) {
 		map = &ioremap_maps[i];
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
index 422e927..961b340 100644
--- a/arch/sh/mm/numa.c
+++ b/arch/sh/mm/numa.c
@@ -74,6 +74,9 @@
 	start_pfn = start >> PAGE_SHIFT;
 	end_pfn = end >> PAGE_SHIFT;
 
+	pmb_bolt_mapping((unsigned long)__va(start), start, end - start,
+			 PAGE_KERNEL);
+
 	lmb_add(start, end - start);
 
 	__add_active_range(nid, start_pfn, end_pfn);
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index 198bcff..a4662e2 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -23,7 +23,8 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
-#include <linux/rwlock.h>
+#include <linux/vmalloc.h>
+#include <asm/cacheflush.h>
 #include <asm/sizes.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -52,12 +53,24 @@
 	struct pmb_entry *link;
 };
 
+static struct {
+	unsigned long size;
+	int flag;
+} pmb_sizes[] = {
+	{ .size	= SZ_512M, .flag = PMB_SZ_512M, },
+	{ .size = SZ_128M, .flag = PMB_SZ_128M, },
+	{ .size = SZ_64M,  .flag = PMB_SZ_64M,  },
+	{ .size = SZ_16M,  .flag = PMB_SZ_16M,  },
+};
+
 static void pmb_unmap_entry(struct pmb_entry *, int depth);
 
 static DEFINE_RWLOCK(pmb_rwlock);
 static struct pmb_entry pmb_entry_list[NR_PMB_ENTRIES];
 static DECLARE_BITMAP(pmb_map, NR_PMB_ENTRIES);
 
+static unsigned int pmb_iomapping_enabled;
+
 static __always_inline unsigned long mk_pmb_entry(unsigned int entry)
 {
 	return (entry & PMB_E_MASK) << PMB_E_SHIFT;
@@ -73,6 +86,142 @@
 	return mk_pmb_entry(entry) | PMB_DATA;
 }
 
+static __always_inline unsigned int pmb_ppn_in_range(unsigned long ppn)
+{
+	return ppn >= __pa(memory_start) && ppn < __pa(memory_end);
+}
+
+/*
+ * Ensure that the PMB entries match our cache configuration.
+ *
+ * When we are in 32-bit address extended mode, CCR.CB becomes
+ * invalid, so care must be taken to manually adjust cacheable
+ * translations.
+ */
+static __always_inline unsigned long pmb_cache_flags(void)
+{
+	unsigned long flags = 0;
+
+#if defined(CONFIG_CACHE_OFF)
+	flags |= PMB_WT | PMB_UB;
+#elif defined(CONFIG_CACHE_WRITETHROUGH)
+	flags |= PMB_C | PMB_WT | PMB_UB;
+#elif defined(CONFIG_CACHE_WRITEBACK)
+	flags |= PMB_C;
+#endif
+
+	return flags;
+}
+
+/*
+ * Convert typical pgprot value to the PMB equivalent
+ */
+static inline unsigned long pgprot_to_pmb_flags(pgprot_t prot)
+{
+	unsigned long pmb_flags = 0;
+	u64 flags = pgprot_val(prot);
+
+	if (flags & _PAGE_CACHABLE)
+		pmb_flags |= PMB_C;
+	if (flags & _PAGE_WT)
+		pmb_flags |= PMB_WT | PMB_UB;
+
+	return pmb_flags;
+}
+
+static inline bool pmb_can_merge(struct pmb_entry *a, struct pmb_entry *b)
+{
+	return (b->vpn == (a->vpn + a->size)) &&
+	       (b->ppn == (a->ppn + a->size)) &&
+	       (b->flags == a->flags);
+}
+
+static bool pmb_mapping_exists(unsigned long vaddr, phys_addr_t phys,
+			       unsigned long size)
+{
+	int i;
+
+	read_lock(&pmb_rwlock);
+
+	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
+		struct pmb_entry *pmbe, *iter;
+		unsigned long span;
+
+		if (!test_bit(i, pmb_map))
+			continue;
+
+		pmbe = &pmb_entry_list[i];
+
+		/*
+		 * See if VPN and PPN are bounded by an existing mapping.
+		 */
+		if ((vaddr < pmbe->vpn) || (vaddr >= (pmbe->vpn + pmbe->size)))
+			continue;
+		if ((phys < pmbe->ppn) || (phys >= (pmbe->ppn + pmbe->size)))
+			continue;
+
+		/*
+		 * Now see if we're in range of a simple mapping.
+		 */
+		if (size <= pmbe->size) {
+			read_unlock(&pmb_rwlock);
+			return true;
+		}
+
+		span = pmbe->size;
+
+		/*
+		 * Finally for sizes that involve compound mappings, walk
+		 * the chain.
+		 */
+		for (iter = pmbe->link; iter; iter = iter->link)
+			span += iter->size;
+
+		/*
+		 * Nothing else to do if the range requirements are met.
+		 */
+		if (size <= span) {
+			read_unlock(&pmb_rwlock);
+			return true;
+		}
+	}
+
+	read_unlock(&pmb_rwlock);
+	return false;
+}
+
+static bool pmb_size_valid(unsigned long size)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
+		if (pmb_sizes[i].size == size)
+			return true;
+
+	return false;
+}
+
+static inline bool pmb_addr_valid(unsigned long addr, unsigned long size)
+{
+	return (addr >= P1SEG && (addr + size - 1) < P3SEG);
+}
+
+static inline bool pmb_prot_valid(pgprot_t prot)
+{
+	return (pgprot_val(prot) & _PAGE_USER) == 0;
+}
+
+static int pmb_size_to_flags(unsigned long size)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
+		if (pmb_sizes[i].size == size)
+			return pmb_sizes[i].flag;
+
+	return 0;
+}
+
 static int pmb_alloc_entry(void)
 {
 	int pos;
@@ -140,33 +289,22 @@
 }
 
 /*
- * Ensure that the PMB entries match our cache configuration.
- *
- * When we are in 32-bit address extended mode, CCR.CB becomes
- * invalid, so care must be taken to manually adjust cacheable
- * translations.
- */
-static __always_inline unsigned long pmb_cache_flags(void)
-{
-	unsigned long flags = 0;
-
-#if defined(CONFIG_CACHE_WRITETHROUGH)
-	flags |= PMB_C | PMB_WT | PMB_UB;
-#elif defined(CONFIG_CACHE_WRITEBACK)
-	flags |= PMB_C;
-#endif
-
-	return flags;
-}
-
-/*
  * Must be run uncached.
  */
 static void __set_pmb_entry(struct pmb_entry *pmbe)
 {
-	writel_uncached(pmbe->vpn | PMB_V, mk_pmb_addr(pmbe->entry));
-	writel_uncached(pmbe->ppn | pmbe->flags | PMB_V,
-			mk_pmb_data(pmbe->entry));
+	unsigned long addr, data;
+
+	addr = mk_pmb_addr(pmbe->entry);
+	data = mk_pmb_data(pmbe->entry);
+
+	jump_to_uncached();
+
+	/* Set V-bit */
+	__raw_writel(pmbe->vpn | PMB_V, addr);
+	__raw_writel(pmbe->ppn | pmbe->flags | PMB_V, data);
+
+	back_to_cached();
 }
 
 static void __clear_pmb_entry(struct pmb_entry *pmbe)
@@ -194,144 +332,155 @@
 	spin_unlock_irqrestore(&pmbe->lock, flags);
 }
 
-static struct {
-	unsigned long size;
-	int flag;
-} pmb_sizes[] = {
-	{ .size	= SZ_512M, .flag = PMB_SZ_512M, },
-	{ .size = SZ_128M, .flag = PMB_SZ_128M, },
-	{ .size = SZ_64M,  .flag = PMB_SZ_64M,  },
-	{ .size = SZ_16M,  .flag = PMB_SZ_16M,  },
-};
-
-long pmb_remap(unsigned long vaddr, unsigned long phys,
-	       unsigned long size, pgprot_t prot)
+int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
+		     unsigned long size, pgprot_t prot)
 {
 	struct pmb_entry *pmbp, *pmbe;
-	unsigned long wanted;
-	int pmb_flags, i;
-	long err;
-	u64 flags;
+	unsigned long orig_addr, orig_size;
+	unsigned long flags, pmb_flags;
+	int i, mapped;
 
-	flags = pgprot_val(prot);
+	if (!pmb_addr_valid(vaddr, size))
+		return -EFAULT;
+	if (pmb_mapping_exists(vaddr, phys, size))
+		return 0;
 
-	pmb_flags = PMB_WT | PMB_UB;
+	orig_addr = vaddr;
+	orig_size = size;
 
-	/* Convert typical pgprot value to the PMB equivalent */
-	if (flags & _PAGE_CACHABLE) {
-		pmb_flags |= PMB_C;
+	flush_tlb_kernel_range(vaddr, vaddr + size);
 
-		if ((flags & _PAGE_WT) == 0)
-			pmb_flags &= ~(PMB_WT | PMB_UB);
-	}
-
+	pmb_flags = pgprot_to_pmb_flags(prot);
 	pmbp = NULL;
-	wanted = size;
 
-again:
-	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
-		unsigned long flags;
+	do {
+		for (i = mapped = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
+			if (size < pmb_sizes[i].size)
+				continue;
 
-		if (size < pmb_sizes[i].size)
-			continue;
+			pmbe = pmb_alloc(vaddr, phys, pmb_flags |
+					 pmb_sizes[i].flag, PMB_NO_ENTRY);
+			if (IS_ERR(pmbe)) {
+				pmb_unmap_entry(pmbp, mapped);
+				return PTR_ERR(pmbe);
+			}
 
-		pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag,
-				 PMB_NO_ENTRY);
-		if (IS_ERR(pmbe)) {
-			err = PTR_ERR(pmbe);
-			goto out;
+			spin_lock_irqsave(&pmbe->lock, flags);
+
+			pmbe->size = pmb_sizes[i].size;
+
+			__set_pmb_entry(pmbe);
+
+			phys	+= pmbe->size;
+			vaddr	+= pmbe->size;
+			size	-= pmbe->size;
+
+			/*
+			 * Link adjacent entries that span multiple PMB
+			 * entries for easier tear-down.
+			 */
+			if (likely(pmbp)) {
+				spin_lock(&pmbp->lock);
+				pmbp->link = pmbe;
+				spin_unlock(&pmbp->lock);
+			}
+
+			pmbp = pmbe;
+
+			/*
+			 * Instead of trying smaller sizes on every
+			 * iteration (even if we succeed in allocating
+			 * space), try using pmb_sizes[i].size again.
+			 */
+			i--;
+			mapped++;
+
+			spin_unlock_irqrestore(&pmbe->lock, flags);
 		}
+	} while (size >= SZ_16M);
 
-		spin_lock_irqsave(&pmbe->lock, flags);
+	flush_cache_vmap(orig_addr, orig_addr + orig_size);
 
-		__set_pmb_entry(pmbe);
-
-		phys	+= pmb_sizes[i].size;
-		vaddr	+= pmb_sizes[i].size;
-		size	-= pmb_sizes[i].size;
-
-		pmbe->size = pmb_sizes[i].size;
-
-		/*
-		 * Link adjacent entries that span multiple PMB entries
-		 * for easier tear-down.
-		 */
-		if (likely(pmbp)) {
-			spin_lock(&pmbp->lock);
-			pmbp->link = pmbe;
-			spin_unlock(&pmbp->lock);
-		}
-
-		pmbp = pmbe;
-
-		/*
-		 * Instead of trying smaller sizes on every iteration
-		 * (even if we succeed in allocating space), try using
-		 * pmb_sizes[i].size again.
-		 */
-		i--;
-
-		spin_unlock_irqrestore(&pmbe->lock, flags);
-	}
-
-	if (size >= SZ_16M)
-		goto again;
-
-	return wanted - size;
-
-out:
-	pmb_unmap_entry(pmbp, NR_PMB_ENTRIES);
-
-	return err;
+	return 0;
 }
 
-void pmb_unmap(unsigned long addr)
+void __iomem *pmb_remap_caller(phys_addr_t phys, unsigned long size,
+			       pgprot_t prot, void *caller)
+{
+	unsigned long vaddr;
+	phys_addr_t offset, last_addr;
+	phys_addr_t align_mask;
+	unsigned long aligned;
+	struct vm_struct *area;
+	int i, ret;
+
+	if (!pmb_iomapping_enabled)
+		return NULL;
+
+	/*
+	 * Small mappings need to go through the TLB.
+	 */
+	if (size < SZ_16M)
+		return ERR_PTR(-EINVAL);
+	if (!pmb_prot_valid(prot))
+		return ERR_PTR(-EINVAL);
+
+	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
+		if (size >= pmb_sizes[i].size)
+			break;
+
+	last_addr = phys + size;
+	align_mask = ~(pmb_sizes[i].size - 1);
+	offset = phys & ~align_mask;
+	phys &= align_mask;
+	aligned = ALIGN(last_addr, pmb_sizes[i].size) - phys;
+
+	/*
+	 * XXX: This should really start from uncached_end, but this
+	 * causes the MMU to reset, so for now we restrict it to the
+	 * 0xb000...0xc000 range.
+	 */
+	area = __get_vm_area_caller(aligned, VM_IOREMAP, 0xb0000000,
+				    P3SEG, caller);
+	if (!area)
+		return NULL;
+
+	area->phys_addr = phys;
+	vaddr = (unsigned long)area->addr;
+
+	ret = pmb_bolt_mapping(vaddr, phys, size, prot);
+	if (unlikely(ret != 0))
+		return ERR_PTR(ret);
+
+	return (void __iomem *)(offset + (char *)vaddr);
+}
+
+int pmb_unmap(void __iomem *addr)
 {
 	struct pmb_entry *pmbe = NULL;
-	int i;
+	unsigned long vaddr = (unsigned long __force)addr;
+	int i, found = 0;
 
 	read_lock(&pmb_rwlock);
 
 	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
 		if (test_bit(i, pmb_map)) {
 			pmbe = &pmb_entry_list[i];
-			if (pmbe->vpn == addr)
+			if (pmbe->vpn == vaddr) {
+				found = 1;
 				break;
+			}
 		}
 	}
 
 	read_unlock(&pmb_rwlock);
 
-	pmb_unmap_entry(pmbe, NR_PMB_ENTRIES);
-}
+	if (found) {
+		pmb_unmap_entry(pmbe, NR_PMB_ENTRIES);
+		return 0;
+	}
 
-static bool pmb_can_merge(struct pmb_entry *a, struct pmb_entry *b)
-{
-	return (b->vpn == (a->vpn + a->size)) &&
-	       (b->ppn == (a->ppn + a->size)) &&
-	       (b->flags == a->flags);
-}
-
-static bool pmb_size_valid(unsigned long size)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
-		if (pmb_sizes[i].size == size)
-			return true;
-
-	return false;
-}
-
-static int pmb_size_to_flags(unsigned long size)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
-		if (pmb_sizes[i].size == size)
-			return pmb_sizes[i].flag;
-
-	return 0;
+	return -EINVAL;
 }
 
 static void __pmb_unmap_entry(struct pmb_entry *pmbe, int depth)
@@ -351,6 +500,8 @@
 		 */
 		__clear_pmb_entry(pmbe);
 
+		flush_cache_vunmap(pmbe->vpn, pmbe->vpn + pmbe->size);
+
 		pmbe = pmblink->link;
 
 		pmb_free(pmblink);
@@ -369,11 +520,6 @@
 	write_unlock_irqrestore(&pmb_rwlock, flags);
 }
 
-static __always_inline unsigned int pmb_ppn_in_range(unsigned long ppn)
-{
-	return ppn >= __pa(memory_start) && ppn < __pa(memory_end);
-}
-
 static void __init pmb_notify(void)
 {
 	int i;
@@ -625,6 +771,18 @@
 }
 #endif
 
+static int __init early_pmb(char *p)
+{
+	if (!p)
+		return 0;
+
+	if (strstr(p, "iomap"))
+		pmb_iomapping_enabled = 1;
+
+	return 0;
+}
+early_param("pmb", early_pmb);
+
 void __init pmb_init(void)
 {
 	/* Synchronize software state */
@@ -713,7 +871,7 @@
 
 	return 0;
 }
-postcore_initcall(pmb_debugfs_init);
+subsys_initcall(pmb_debugfs_init);
 
 #ifdef CONFIG_PM
 static int pmb_sysdev_suspend(struct sys_device *dev, pm_message_t state)
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 4097f6a..6db5136 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -127,6 +127,9 @@
 	bool
 	default y if SPARC32
 
+config NEED_DMA_MAP_STATE
+	def_bool y
+
 config GENERIC_ISA_DMA
 	bool
 	default y if SPARC32
diff --git a/arch/sparc/configs/sparc32_defconfig b/arch/sparc/configs/sparc32_defconfig
index 99a1f19..6a8d078 100644
--- a/arch/sparc/configs/sparc32_defconfig
+++ b/arch/sparc/configs/sparc32_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.33-rc2
-# Mon Jan 11 23:20:31 2010
+# Linux kernel version: 2.6.33
+# Wed Mar  3 02:52:23 2010
 #
 # CONFIG_64BIT is not set
 CONFIG_SPARC=y
@@ -9,6 +9,8 @@
 # CONFIG_SPARC64 is not set
 CONFIG_ARCH_DEFCONFIG="arch/sparc/configs/sparc32_defconfig"
 CONFIG_BITS=32
+CONFIG_GENERIC_TIME=y
+CONFIG_ARCH_USES_GETTIMEOFFSET=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_MMU=y
 CONFIG_HIGHMEM=y
@@ -48,11 +50,6 @@
 # CONFIG_TREE_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_GROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_RT_GROUP_SCHED=y
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
@@ -68,6 +65,7 @@
 CONFIG_RD_GZIP=y
 CONFIG_RD_BZIP2=y
 CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -211,7 +209,6 @@
 CONFIG_PCI=y
 CONFIG_PCI_SYSCALL=y
 # CONFIG_ARCH_SUPPORTS_MSI is not set
-CONFIG_PCI_LEGACY=y
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCI_IOV is not set
@@ -232,7 +229,6 @@
 # Networking options
 #
 CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
@@ -379,11 +375,13 @@
 # CONFIG_TIFM_CORE is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_HP_ILO is not set
+# CONFIG_TI_DAC7512 is not set
 # CONFIG_C2PORT is not set
 
 #
 # EEPROM support
 #
+# CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_93CX6 is not set
 # CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
@@ -507,7 +505,9 @@
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
 # CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_ENC28J60 is not set
 # CONFIG_ETHOC is not set
+# CONFIG_GRETH is not set
 # CONFIG_DNET is not set
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
@@ -521,6 +521,7 @@
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
 # CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_KS8851_MLL is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
@@ -563,6 +564,7 @@
 # CONFIG_MLX4_CORE is not set
 # CONFIG_TEHUTI is not set
 # CONFIG_BNX2X is not set
+# CONFIG_QLCNIC is not set
 # CONFIG_QLGE is not set
 # CONFIG_SFC is not set
 # CONFIG_BE2NET is not set
@@ -665,6 +667,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_SUNCORE=y
 CONFIG_SERIAL_SUNZILOG=y
 CONFIG_SERIAL_SUNZILOG_CONSOLE=y
@@ -689,7 +692,23 @@
 # CONFIG_TCG_TPM is not set
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
-# CONFIG_SPI is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=m
+CONFIG_SPI_XILINX=m
+CONFIG_SPI_XILINX_PLTFM=m
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
 
 #
 # PPS support
@@ -706,10 +725,13 @@
 #
 # Native drivers
 #
+# CONFIG_SENSORS_ADCXX is not set
 # CONFIG_SENSORS_I5K_AMB is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_MAX1111 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
 # CONFIG_SENSORS_SIS5595 is not set
@@ -720,6 +742,7 @@
 # CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83627HF is not set
 # CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
 # CONFIG_THERMAL is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
@@ -736,6 +759,8 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_MC13783 is not set
+# CONFIG_AB4500_CORE is not set
 # CONFIG_REGULATOR is not set
 # CONFIG_MEDIA_SUPPORT is not set
 
@@ -743,6 +768,7 @@
 # Graphics support
 #
 CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
 # CONFIG_FB is not set
@@ -808,6 +834,14 @@
 #
 # SPI RTC drivers
 #
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
 
 #
 # Platform RTC drivers
@@ -1180,9 +1214,11 @@
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_DECOMPRESS=y
 CONFIG_DECOMPRESS_GZIP=y
 CONFIG_DECOMPRESS_BZIP2=y
 CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig
index 41c5a56..56e3163 100644
--- a/arch/sparc/configs/sparc64_defconfig
+++ b/arch/sparc/configs/sparc64_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.33-rc2
-# Wed Jan 20 16:31:47 2010
+# Linux kernel version: 2.6.33
+# Wed Mar  3 02:54:29 2010
 #
 CONFIG_64BIT=y
 CONFIG_SPARC=y
@@ -55,14 +55,10 @@
 # CONFIG_RCU_TRACE is not set
 CONFIG_RCU_FANOUT=64
 # CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_RCU_FAST_NO_HZ is not set
 # CONFIG_TREE_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=18
-CONFIG_GROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_RT_GROUP_SCHED=y
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 CONFIG_RELAY=y
@@ -77,6 +73,7 @@
 CONFIG_RD_GZIP=y
 CONFIG_RD_BZIP2=y
 CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -105,7 +102,6 @@
 # Kernel Performance Events And Counters
 #
 CONFIG_PERF_EVENTS=y
-CONFIG_EVENT_PROFILE=y
 CONFIG_PERF_COUNTERS=y
 # CONFIG_DEBUG_PERF_USE_VMALLOC is not set
 CONFIG_VM_EVENT_COUNTERS=y
@@ -266,7 +262,6 @@
 CONFIG_PCI_SYSCALL=y
 CONFIG_ARCH_SUPPORTS_MSI=y
 CONFIG_PCI_MSI=y
-# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCI_IOV is not set
@@ -290,7 +285,6 @@
 # Networking options
 #
 CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
@@ -425,10 +419,6 @@
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
-
-#
-# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
-#
 # CONFIG_BLK_DEV_DRBD is not set
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
@@ -677,6 +667,7 @@
 CONFIG_SUNVNET=m
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_ETHOC is not set
+# CONFIG_GRETH is not set
 # CONFIG_DNET is not set
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
@@ -691,6 +682,7 @@
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_KSZ884X_PCI is not set
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
 # CONFIG_E100 is not set
@@ -741,6 +733,7 @@
 # CONFIG_CHELSIO_T3 is not set
 # CONFIG_ENIC is not set
 # CONFIG_IXGBE is not set
+# CONFIG_IXGBEVF is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_VXGE is not set
@@ -751,6 +744,7 @@
 # CONFIG_MLX4_CORE is not set
 # CONFIG_TEHUTI is not set
 # CONFIG_BNX2X is not set
+# CONFIG_QLCNIC is not set
 # CONFIG_QLGE is not set
 # CONFIG_SFC is not set
 # CONFIG_BE2NET is not set
@@ -1028,6 +1022,7 @@
 # CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_AMC6821 is not set
 # CONFIG_SENSORS_THMC50 is not set
 # CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_TMP421 is not set
@@ -1076,6 +1071,7 @@
 # Graphics support
 #
 CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
 # CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
@@ -1279,6 +1275,7 @@
 # CONFIG_SND_YMFPCI is not set
 CONFIG_SND_USB=y
 # CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_UA101 is not set
 # CONFIG_SND_USB_CAIAQ is not set
 CONFIG_SND_SPARC=y
 # CONFIG_SND_SUN_AMD7930 is not set
@@ -1301,6 +1298,7 @@
 #
 # Special HID drivers
 #
+# CONFIG_HID_3M_PCT is not set
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
@@ -1317,14 +1315,19 @@
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
 CONFIG_HID_MICROSOFT=y
+# CONFIG_HID_MOSART is not set
 CONFIG_HID_MONTEREY=y
 CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
 CONFIG_HID_PANTHERLORD=y
 # CONFIG_PANTHERLORD_FF is not set
 CONFIG_HID_PETALYNX=y
+# CONFIG_HID_QUANTA is not set
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
+# CONFIG_HID_STANTUM is not set
 CONFIG_HID_SUNPLUS=y
 CONFIG_HID_GREENASIA=y
 # CONFIG_GREENASIA_FF is not set
@@ -1807,6 +1810,7 @@
 CONFIG_CRYPTO_MANAGER2=y
 CONFIG_CRYPTO_GF128MUL=m
 CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_PCRYPT is not set
 CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_AUTHENC=y
@@ -1904,9 +1908,11 @@
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_DECOMPRESS=y
 CONFIG_DECOMPRESS_GZIP=y
 CONFIG_DECOMPRESS_BZIP2=y
 CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_LZO=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index 0e70625..5016f76 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -5,7 +5,8 @@
  */
 #include <linux/types.h>
 
-#define COMPAT_USER_HZ	100
+#define COMPAT_USER_HZ		100
+#define COMPAT_UTS_MACHINE	"sparc\0\0"
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h
index 5a8c308..4b4a0c0 100644
--- a/arch/sparc/include/asm/dma-mapping.h
+++ b/arch/sparc/include/asm/dma-mapping.h
@@ -8,7 +8,6 @@
 #define DMA_ERROR_CODE	(~(dma_addr_t)0x0)
 
 extern int dma_supported(struct device *dev, u64 mask);
-extern int dma_set_mask(struct device *dev, u64 dma_mask);
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
@@ -62,4 +61,17 @@
 	return (1 << INTERNODE_CACHE_SHIFT);
 }
 
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+#ifdef CONFIG_PCI
+	if (dev->bus == &pci_bus_type) {
+		if (!dev->dma_mask || !dma_supported(dev, mask))
+			return -EINVAL;
+		*dev->dma_mask = mask;
+		return 0;
+	}
+#endif
+	return -EINVAL;
+}
+
 #endif
diff --git a/arch/sparc/include/asm/fbio.h b/arch/sparc/include/asm/fbio.h
index b9215a0..0a21da8 100644
--- a/arch/sparc/include/asm/fbio.h
+++ b/arch/sparc/include/asm/fbio.h
@@ -173,7 +173,7 @@
 	int     mdi_ncluts;     /* Number of implemented CLUTs in this MDI */
         int     mdi_type;       /* FBTYPE name */
         int     mdi_height;     /* height */
-        int     mdi_width;      /* widht */
+        int     mdi_width;      /* width */
         int     mdi_size;       /* available ram */
         int     mdi_mode;       /* 8bpp, 16bpp or 32bpp */
         int     mdi_pixfreq;    /* pixel clock (from PROM) */
diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h
index 679c750..2889574 100644
--- a/arch/sparc/include/asm/io_32.h
+++ b/arch/sparc/include/asm/io_32.h
@@ -249,10 +249,14 @@
 
 #define ioread8(X)			readb(X)
 #define ioread16(X)			readw(X)
+#define ioread16be(X)			__raw_readw(X)
 #define ioread32(X)			readl(X)
+#define ioread32be(X)			__raw_readl(X)
 #define iowrite8(val,X)			writeb(val,X)
 #define iowrite16(val,X)		writew(val,X)
+#define iowrite16be(val,X)		__raw_writew(val,X)
 #define iowrite32(val,X)		writel(val,X)
+#define iowrite32be(val,X)		__raw_writel(val,X)
 
 static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
 {
diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h
index 4aee21d..9517d06 100644
--- a/arch/sparc/include/asm/io_64.h
+++ b/arch/sparc/include/asm/io_64.h
@@ -468,10 +468,14 @@
 
 #define ioread8(X)			readb(X)
 #define ioread16(X)			readw(X)
+#define ioread16be(X)			__raw_readw(X)
 #define ioread32(X)			readl(X)
+#define ioread32be(X)			__raw_readl(X)
 #define iowrite8(val,X)			writeb(val,X)
 #define iowrite16(val,X)		writew(val,X)
+#define iowrite16be(val,X)		__raw_writew(val,X)
 #define iowrite32(val,X)		writel(val,X)
+#define iowrite32be(val,X)		__raw_writel(val,X)
 
 /* Create a virtual mapping cookie for an IO port range */
 extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h
index e769f66..332ac9a 100644
--- a/arch/sparc/include/asm/pci_32.h
+++ b/arch/sparc/include/asm/pci_32.h
@@ -32,20 +32,6 @@
 
 struct pci_dev;
 
-/* pci_unmap_{single,page} is not a nop, thus... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
-	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
-	__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)			\
-	((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
-	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)			\
-	((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
-	(((PTR)->LEN_NAME) = (VAL))
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 					enum pci_dma_burst_strategy *strat,
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h
index b0576df..5312782 100644
--- a/arch/sparc/include/asm/pci_64.h
+++ b/arch/sparc/include/asm/pci_64.h
@@ -32,20 +32,6 @@
  */
 #define PCI_DMA_BUS_IS_PHYS	(0)
 
-/* pci_unmap_{single,page} is not a nop, thus... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
-	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
-	__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)			\
-	((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
-	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)			\
-	((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
-	(((PTR)->LEN_NAME) = (VAL))
-
 /* PCI IOMMU mapping bypass support. */
 
 /* PCI 64-bit addressing works for all slots on all controller
diff --git a/arch/sparc/include/asm/perfctr.h b/arch/sparc/include/asm/perfctr.h
index 8368730..8d8720a 100644
--- a/arch/sparc/include/asm/perfctr.h
+++ b/arch/sparc/include/asm/perfctr.h
@@ -10,8 +10,8 @@
  * from enumeration below.  The meaning of further arguments
  * are determined by the operation code.
  *
- * int sys_perfctr(int opcode, unsigned long arg0,
- *                 unsigned long arg1, unsigned long arg2)
+ * NOTE: This system call is no longer provided, use the perf_events
+ *       infrastructure.
  *
  * Pointers which are passed by the user are pointers to 64-bit
  * integers.
diff --git a/arch/sparc/include/asm/system_64.h b/arch/sparc/include/asm/system_64.h
index d47a98e..d24cfe1 100644
--- a/arch/sparc/include/asm/system_64.h
+++ b/arch/sparc/include/asm/system_64.h
@@ -143,15 +143,7 @@
 	 * and 2 stores in this critical code path.  -DaveM
 	 */
 #define switch_to(prev, next, last)					\
-do {	if (test_thread_flag(TIF_PERFCTR)) {				\
-		unsigned long __tmp;					\
-		read_pcr(__tmp);					\
-		current_thread_info()->pcr_reg = __tmp;			\
-		read_pic(__tmp);					\
-		current_thread_info()->kernel_cntd0 += (unsigned int)(__tmp);\
-		current_thread_info()->kernel_cntd1 += ((__tmp) >> 32);	\
-	}								\
-	flush_tlb_pending();						\
+do {	flush_tlb_pending();						\
 	save_and_clear_fpu();						\
 	/* If you are tempted to conditionalize the following */	\
 	/* so that ASI is only written if it changes, think again. */	\
@@ -197,11 +189,6 @@
 	        "l1", "l2", "l3", "l4", "l5", "l6", "l7",		\
 	  "i0", "i1", "i2", "i3", "i4", "i5",				\
 	  "o0", "o1", "o2", "o3", "o4", "o5",       "o7");		\
-	/* If you fuck with this, update ret_from_syscall code too. */	\
-	if (test_thread_flag(TIF_PERFCTR)) {				\
-		write_pcr(current_thread_info()->pcr_reg);		\
-		reset_pic();						\
-	}								\
 } while(0)
 
 static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index 39be9f2..9e2d944 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -58,11 +58,6 @@
 	unsigned long		gsr[7];
 	unsigned long		xfsr[7];
 
-	__u64			__user *user_cntd0;
-	__u64			__user *user_cntd1;
-	__u64			kernel_cntd0, kernel_cntd1;
-	__u64			pcr_reg;
-
 	struct restart_block	restart_block;
 
 	struct pt_regs		*kern_una_regs;
@@ -96,15 +91,10 @@
 #define TI_RWIN_SPTRS	0x000003c8
 #define TI_GSR		0x00000400
 #define TI_XFSR		0x00000438
-#define TI_USER_CNTD0	0x00000470
-#define TI_USER_CNTD1	0x00000478
-#define TI_KERN_CNTD0	0x00000480
-#define TI_KERN_CNTD1	0x00000488
-#define TI_PCR		0x00000490
-#define TI_RESTART_BLOCK 0x00000498
-#define TI_KUNA_REGS	0x000004c8
-#define TI_KUNA_INSN	0x000004d0
-#define TI_FPREGS	0x00000500
+#define TI_RESTART_BLOCK 0x00000470
+#define TI_KUNA_REGS	0x000004a0
+#define TI_KUNA_INSN	0x000004a8
+#define TI_FPREGS	0x000004c0
 
 /* We embed this in the uppermost byte of thread_info->flags */
 #define FAULT_CODE_WRITE	0x01	/* Write access, implies D-TLB	   */
@@ -199,7 +189,7 @@
  *
  * On trap return we need to test several values:
  *
- * user:	need_resched, notify_resume, sigpending, wsaved, perfctr
+ * user:	need_resched, notify_resume, sigpending, wsaved
  * kernel:	fpdepth
  *
  * So to check for work in the kernel case we simply load the fpdepth
@@ -220,7 +210,7 @@
 #define TIF_NOTIFY_RESUME	1	/* callback before returning to user */
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
-#define TIF_PERFCTR		4	/* performance counters active */
+/* flag bit 4 is available */
 #define TIF_UNALIGNED		5	/* allowed to do unaligned accesses */
 /* flag bit 6 is available */
 #define TIF_32BIT		7	/* 32-bit binary */
@@ -241,7 +231,6 @@
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_PERFCTR		(1<<TIF_PERFCTR)
 #define _TIF_UNALIGNED		(1<<TIF_UNALIGNED)
 #define _TIF_32BIT		(1<<TIF_32BIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
@@ -252,7 +241,7 @@
 
 #define _TIF_USER_WORK_MASK	((0xff << TI_FLAG_WSAVED_SHIFT) | \
 				 _TIF_DO_NOTIFY_RESUME_MASK | \
-				 _TIF_NEED_RESCHED | _TIF_PERFCTR)
+				 _TIF_NEED_RESCHED)
 #define _TIF_DO_NOTIFY_RESUME_MASK	(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING)
 
 /*
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h
index cb4b9bf..d0b3b01 100644
--- a/arch/sparc/include/asm/unistd.h
+++ b/arch/sparc/include/asm/unistd.h
@@ -432,7 +432,9 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#ifndef __32bit_syscall_numbers__
+#ifdef __32bit_syscall_numbers__
+#define __ARCH_WANT_SYS_IPC
+#else
 #define __ARCH_WANT_COMPAT_SYS_TIME
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #endif
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h
index 4f53a23..c011b93 100644
--- a/arch/sparc/kernel/entry.h
+++ b/arch/sparc/kernel/entry.h
@@ -48,7 +48,6 @@
 extern unsigned int dcache_parity_tl1_occurred;
 extern unsigned int icache_parity_tl1_occurred;
 
-extern asmlinkage void update_perfctrs(void);
 extern asmlinkage void sparc_breakpoint(struct pt_regs *regs);
 extern void timer_interrupt(int irq, struct pt_regs *regs);
 
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 5fad949..8414549 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -862,13 +862,3 @@
 	return 0;
 }
 EXPORT_SYMBOL(dma_supported);
-
-int dma_set_mask(struct device *dev, u64 dma_mask)
-{
-#ifdef CONFIG_PCI
-	if (dev->bus == &pci_bus_type)
-		return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
-#endif
-	return -EINVAL;
-}
-EXPORT_SYMBOL(dma_set_mask);
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 3c8c44f..84e5386 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -676,17 +676,6 @@
 }
 EXPORT_SYMBOL(dma_supported);
 
-int dma_set_mask(struct device *dev, u64 dma_mask)
-{
-#ifdef CONFIG_PCI
-	if (dev->bus == &pci_bus_type)
-		return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
-#endif
-	return -EOPNOTSUPP;
-}
-EXPORT_SYMBOL(dma_set_mask);
-
-
 #ifdef CONFIG_PROC_FS
 
 static int sparc_io_proc_show(struct seq_file *m, void *v)
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
index d242a73..b287b62 100644
--- a/arch/sparc/kernel/nmi.c
+++ b/arch/sparc/kernel/nmi.c
@@ -21,7 +21,6 @@
 
 #include <asm/perf_event.h>
 #include <asm/ptrace.h>
-#include <asm/local.h>
 #include <asm/pcr.h>
 
 /* We don't have a real NMI on sparc64, but we can fake one
@@ -113,13 +112,13 @@
 		touched = 1;
 	}
 	if (!touched && __get_cpu_var(last_irq_sum) == sum) {
-		__this_cpu_inc(per_cpu_var(alert_counter));
-		if (__this_cpu_read(per_cpu_var(alert_counter)) == 30 * nmi_hz)
+		__this_cpu_inc(alert_counter);
+		if (__this_cpu_read(alert_counter) == 30 * nmi_hz)
 			die_nmi("BUG: NMI Watchdog detected LOCKUP",
 				regs, panic_on_timeout);
 	} else {
 		__get_cpu_var(last_irq_sum) = sum;
-		__this_cpu_write(per_cpu_var(alert_counter), 0);
+		__this_cpu_write(alert_counter, 0);
 	}
 	if (__get_cpu_var(wd_enabled)) {
 		write_pic(picl_value(nmi_hz));
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 9f2b2ba..68cb9b4 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -1189,7 +1189,7 @@
 
 	regs = args->regs;
 
-	data.addr = 0;
+	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -1353,7 +1353,7 @@
 }
 
 /* Like powerpc we can't get PMU interrupts within the PMU handler,
- * so no need for seperate NMI and IRQ chains as on x86.
+ * so no need for separate NMI and IRQ chains as on x86.
  */
 static DEFINE_PER_CPU(struct perf_callchain_entry, callchain);
 
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index cb70476..a5cf386 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -352,12 +352,6 @@
 		else
 			t->utraps[0]--;
 	}
-
-	if (test_and_clear_thread_flag(TIF_PERFCTR)) {
-		t->user_cntd0 = t->user_cntd1 = NULL;
-		t->pcr_reg = 0;
-		write_pcr(0);
-	}
 }
 
 void flush_thread(void)
@@ -371,13 +365,6 @@
 
 	set_thread_wsaved(0);
 
-	/* Turn off performance counters if on. */
-	if (test_and_clear_thread_flag(TIF_PERFCTR)) {
-		t->user_cntd0 = t->user_cntd1 = NULL;
-		t->pcr_reg = 0;
-		write_pcr(0);
-	}
-
 	/* Clear FPU register state. */
 	t->fpsaved[0] = 0;
 	
@@ -591,16 +578,6 @@
 		t->kregs->u_regs[UREG_FP] =
 		  ((unsigned long) child_sf) - STACK_BIAS;
 
-		/* Special case, if we are spawning a kernel thread from
-		 * a userspace task (usermode helper, NFS or similar), we
-		 * must disable performance counters in the child because
-		 * the address space and protection realm are changing.
-		 */
-		if (t->flags & _TIF_PERFCTR) {
-			t->user_cntd0 = t->user_cntd1 = NULL;
-			t->pcr_reg = 0;
-			t->flags &= ~_TIF_PERFCTR;
-		}
 		t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT);
 		t->kregs->u_regs[UREG_G6] = (unsigned long) t;
 		t->kregs->u_regs[UREG_G4] = (unsigned long) t->task;
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index fd3cee4..83f1873 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -65,48 +65,6 @@
 		ba,pt			%xcc, __handle_user_windows_continue
 
 		 andn			%l1, %l4, %l1
-__handle_perfctrs:
-		call			update_perfctrs
-		 wrpr			%g0, RTRAP_PSTATE, %pstate
-		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
-		ldub			[%g6 + TI_WSAVED], %o2
-		brz,pt			%o2, 1f
-		 nop
-		/* Redo userwin+sched+sig checks */
-		call			fault_in_user_windows
-
-		 wrpr			%g0, RTRAP_PSTATE, %pstate
-		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
-		ldx			[%g6 + TI_FLAGS], %l0
-		andcc			%l0, _TIF_NEED_RESCHED, %g0
-		be,pt			%xcc, 1f
-
-		 nop
-		call			schedule
-		 wrpr			%g0, RTRAP_PSTATE, %pstate
-		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
-		ldx			[%g6 + TI_FLAGS], %l0
-1:		andcc			%l0, _TIF_DO_NOTIFY_RESUME_MASK, %g0
-
-		be,pt			%xcc, __handle_perfctrs_continue
-		 sethi			%hi(TSTATE_PEF), %o0
-		mov			%l5, %o1
-		add			%sp, PTREGS_OFF, %o0
-		mov			%l0, %o2
-		call			do_notify_resume
-
-		 wrpr			%g0, RTRAP_PSTATE, %pstate
-		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
-		/* Signal delivery can modify pt_regs tstate, so we must
-		 * reload it.
-		 */
-		ldx			[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
-		sethi			%hi(0xf << 20), %l4
-		and			%l1, %l4, %l4
-		andn			%l1, %l4, %l1
-		ba,pt			%xcc, __handle_perfctrs_continue
-
-		 sethi			%hi(TSTATE_PEF), %o0
 __handle_userfpu:
 		rd			%fprs, %l5
 		andcc			%l5, FPRS_FEF, %g0
@@ -149,11 +107,11 @@
 rtrap_irq:
 rtrap:
 #ifndef CONFIG_SMP
-		sethi			%hi(per_cpu____cpu_data), %l0
-		lduw			[%l0 + %lo(per_cpu____cpu_data)], %l1
+		sethi			%hi(__cpu_data), %l0
+		lduw			[%l0 + %lo(__cpu_data)], %l1
 #else
-		sethi			%hi(per_cpu____cpu_data), %l0
-		or			%l0, %lo(per_cpu____cpu_data), %l0
+		sethi			%hi(__cpu_data), %l0
+		or			%l0, %lo(__cpu_data), %l0
 		lduw			[%l0 + %g5], %l1
 #endif
 		cmp			%l1, 0
@@ -191,9 +149,9 @@
 		 * take until the next local IRQ before the signal/resched
 		 * event would be handled.
 		 *
-		 * This also means that if we have to deal with performance
-		 * counters or user windows, we have to redo all of these
-		 * sched+signal checks with IRQs disabled.
+		 * This also means that if we have to deal with user
+		 * windows, we have to redo all of these sched+signal checks
+		 * with IRQs disabled.
 		 */
 to_user:	wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		wrpr			0, %pil
@@ -214,12 +172,8 @@
 		brnz,pn			%o2, __handle_user_windows
 		 nop
 __handle_user_windows_continue:
-		ldx			[%g6 + TI_FLAGS], %l5
-		andcc			%l5, _TIF_PERFCTR, %g0
 		sethi			%hi(TSTATE_PEF), %o0
-		bne,pn			%xcc, __handle_perfctrs
-__handle_perfctrs_continue:
-		 andcc			%l1, %o0, %g0
+		andcc			%l1, %o0, %g0
 
 		/* This fpdepth clear is necessary for non-syscall rtraps only */
 user_nowork:
diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S
index e706113..46a76ba 100644
--- a/arch/sparc/kernel/sys32.S
+++ b/arch/sparc/kernel/sys32.S
@@ -51,7 +51,6 @@
 SIGN1(sys32_wait4, compat_sys_wait4, %o2)
 SIGN1(sys32_creat, sys_creat, %o1)
 SIGN1(sys32_mknod, sys_mknod, %o1)
-SIGN1(sys32_perfctr, sys_perfctr, %o0)
 SIGN1(sys32_umount, sys_umount, %o1)
 SIGN1(sys32_signal, sys_signal, %o0)
 SIGN1(sys32_access, sys_access, %o1)
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c
index 3a82e65..ee995b7 100644
--- a/arch/sparc/kernel/sys_sparc_32.c
+++ b/arch/sparc/kernel/sys_sparc_32.c
@@ -98,119 +98,6 @@
 	return error;
 }
 
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-
-asmlinkage int sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fifth)
-{
-	int version, err;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	if (call <= SEMCTL)
-		switch (call) {
-		case SEMOP:
-			err = sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL);
-			goto out;
-		case SEMTIMEDOP:
-			err = sys_semtimedop (first, (struct sembuf __user *)ptr, second, (const struct timespec __user *) fifth);
-			goto out;
-		case SEMGET:
-			err = sys_semget (first, second, third);
-			goto out;
-		case SEMCTL: {
-			union semun fourth;
-			err = -EINVAL;
-			if (!ptr)
-				goto out;
-			err = -EFAULT;
-			if (get_user(fourth.__pad,
-				     (void __user * __user *)ptr))
-				goto out;
-			err = sys_semctl (first, second, third, fourth);
-			goto out;
-			}
-		default:
-			err = -ENOSYS;
-			goto out;
-		}
-	if (call <= MSGCTL) 
-		switch (call) {
-		case MSGSND:
-			err = sys_msgsnd (first, (struct msgbuf __user *) ptr, 
-					  second, third);
-			goto out;
-		case MSGRCV:
-			switch (version) {
-			case 0: {
-				struct ipc_kludge tmp;
-				err = -EINVAL;
-				if (!ptr)
-					goto out;
-				err = -EFAULT;
-				if (copy_from_user(&tmp, (struct ipc_kludge __user *) ptr, sizeof (tmp)))
-					goto out;
-				err = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
-				goto out;
-				}
-			case 1: default:
-				err = sys_msgrcv (first,
-						  (struct msgbuf __user *) ptr,
-						  second, fifth, third);
-				goto out;
-			}
-		case MSGGET:
-			err = sys_msgget ((key_t) first, second);
-			goto out;
-		case MSGCTL:
-			err = sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
-			goto out;
-		default:
-			err = -ENOSYS;
-			goto out;
-		}
-	if (call <= SHMCTL) 
-		switch (call) {
-		case SHMAT:
-			switch (version) {
-			case 0: default: {
-				ulong raddr;
-				err = do_shmat (first, (char __user *) ptr, second, &raddr);
-				if (err)
-					goto out;
-				err = -EFAULT;
-				if (put_user (raddr, (ulong __user *) third))
-					goto out;
-				err = 0;
-				goto out;
-				}
-			case 1:	/* iBCS2 emulator entry point */
-				err = -EINVAL;
-				goto out;
-			}
-		case SHMDT: 
-			err = sys_shmdt ((char __user *)ptr);
-			goto out;
-		case SHMGET:
-			err = sys_shmget (first, second, third);
-			goto out;
-		case SHMCTL:
-			err = sys_shmctl (first, second, (struct shmid_ds __user *) ptr);
-			goto out;
-		default:
-			err = -ENOSYS;
-			goto out;
-		}
-	else
-		err = -ENOSYS;
-out:
-	return err;
-}
-
 int sparc_mmap_check(unsigned long addr, unsigned long len)
 {
 	if (ARCH_SUN4C &&
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index d77f543..3d435c4 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -27,7 +27,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/utrap.h>
-#include <asm/perfctr.h>
 #include <asm/unistd.h>
 
 #include "entry.h"
@@ -427,7 +426,7 @@
  * This is really horribly ugly.
  */
 
-SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
+SYSCALL_DEFINE6(sparc_ipc, unsigned int, call, int, first, unsigned long, second,
 		unsigned long, third, void __user *, ptr, long, fifth)
 {
 	long err;
@@ -511,17 +510,6 @@
 	return err;
 }
 
-SYSCALL_DEFINE1(sparc64_newuname, struct new_utsname __user *, name)
-{
-	int ret = sys_newuname(name);
-	
-	if (current->personality == PER_LINUX32 && !ret) {
-		ret = (copy_to_user(name->machine, "sparc\0\0", 8)
-		       ? -EFAULT : 0);
-	}
-	return ret;
-}
-
 SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality)
 {
 	int ret;
@@ -766,109 +754,6 @@
 	return ret;
 }
 
-/* Invoked by rtrap code to update performance counters in
- * user space.
- */
-asmlinkage void update_perfctrs(void)
-{
-	unsigned long pic, tmp;
-
-	read_pic(pic);
-	tmp = (current_thread_info()->kernel_cntd0 += (unsigned int)pic);
-	__put_user(tmp, current_thread_info()->user_cntd0);
-	tmp = (current_thread_info()->kernel_cntd1 += (pic >> 32));
-	__put_user(tmp, current_thread_info()->user_cntd1);
-	reset_pic();
-}
-
-SYSCALL_DEFINE4(perfctr, int, opcode, unsigned long, arg0,
-		unsigned long, arg1, unsigned long, arg2)
-{
-	int err = 0;
-
-	switch(opcode) {
-	case PERFCTR_ON:
-		current_thread_info()->pcr_reg = arg2;
-		current_thread_info()->user_cntd0 = (u64 __user *) arg0;
-		current_thread_info()->user_cntd1 = (u64 __user *) arg1;
-		current_thread_info()->kernel_cntd0 =
-			current_thread_info()->kernel_cntd1 = 0;
-		write_pcr(arg2);
-		reset_pic();
-		set_thread_flag(TIF_PERFCTR);
-		break;
-
-	case PERFCTR_OFF:
-		err = -EINVAL;
-		if (test_thread_flag(TIF_PERFCTR)) {
-			current_thread_info()->user_cntd0 =
-				current_thread_info()->user_cntd1 = NULL;
-			current_thread_info()->pcr_reg = 0;
-			write_pcr(0);
-			clear_thread_flag(TIF_PERFCTR);
-			err = 0;
-		}
-		break;
-
-	case PERFCTR_READ: {
-		unsigned long pic, tmp;
-
-		if (!test_thread_flag(TIF_PERFCTR)) {
-			err = -EINVAL;
-			break;
-		}
-		read_pic(pic);
-		tmp = (current_thread_info()->kernel_cntd0 += (unsigned int)pic);
-		err |= __put_user(tmp, current_thread_info()->user_cntd0);
-		tmp = (current_thread_info()->kernel_cntd1 += (pic >> 32));
-		err |= __put_user(tmp, current_thread_info()->user_cntd1);
-		reset_pic();
-		break;
-	}
-
-	case PERFCTR_CLRPIC:
-		if (!test_thread_flag(TIF_PERFCTR)) {
-			err = -EINVAL;
-			break;
-		}
-		current_thread_info()->kernel_cntd0 =
-			current_thread_info()->kernel_cntd1 = 0;
-		reset_pic();
-		break;
-
-	case PERFCTR_SETPCR: {
-		u64 __user *user_pcr = (u64 __user *)arg0;
-
-		if (!test_thread_flag(TIF_PERFCTR)) {
-			err = -EINVAL;
-			break;
-		}
-		err |= __get_user(current_thread_info()->pcr_reg, user_pcr);
-		write_pcr(current_thread_info()->pcr_reg);
-		current_thread_info()->kernel_cntd0 =
-			current_thread_info()->kernel_cntd1 = 0;
-		reset_pic();
-		break;
-	}
-
-	case PERFCTR_GETPCR: {
-		u64 __user *user_pcr = (u64 __user *)arg0;
-
-		if (!test_thread_flag(TIF_PERFCTR)) {
-			err = -EINVAL;
-			break;
-		}
-		err |= __put_user(current_thread_info()->pcr_reg, user_pcr);
-		break;
-	}
-
-	default:
-		err = -EINVAL;
-		break;
-	};
-	return err;
-}
-
 /*
  * Do a system call from kernel instead of calling sys_execve so we
  * end up with proper pt_regs.
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index dc4a458..1d7e274 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -110,31 +110,12 @@
 
 	.globl	ret_from_syscall
 ret_from_syscall:
-	/* Clear current_thread_info()->new_child, and
-	 * check performance counter stuff too.
-	 */
+	/* Clear current_thread_info()->new_child. */
 	stb	%g0, [%g6 + TI_NEW_CHILD]
 	ldx	[%g6 + TI_FLAGS], %l0
 	call	schedule_tail
 	 mov	%g7, %o0
-	andcc	%l0, _TIF_PERFCTR, %g0
-	be,pt	%icc, 1f
-	 nop
-	ldx	[%g6 + TI_PCR], %o7
-	wr	%g0, %o7, %pcr
-
-	/* Blackbird errata workaround.  See commentary in
-	 * smp.c:smp_percpu_timer_interrupt() for more
-	 * information.
-	 */
-	ba,pt	%xcc, 99f
-	 nop
-
-	.align	64
-99:	wr	%g0, %g0, %pic
-	rd	%pic, %g0
-
-1:	ba,pt	%xcc, ret_sys_call
+	ba,pt	%xcc, ret_sys_call
 	 ldx	[%sp + PTREGS_OFF + PT_V9_I0], %o0
 
 	.globl	sparc_exit
diff --git a/arch/sparc/kernel/systbls.h b/arch/sparc/kernel/systbls.h
index d2f999a..118759c 100644
--- a/arch/sparc/kernel/systbls.h
+++ b/arch/sparc/kernel/systbls.h
@@ -6,15 +6,12 @@
 #include <asm/utrap.h>
 #include <asm/signal.h>
 
-struct new_utsname;
-
 extern asmlinkage unsigned long sys_getpagesize(void);
 extern asmlinkage long sparc_pipe(struct pt_regs *regs);
-extern asmlinkage long sys_ipc(unsigned int call, int first,
+extern asmlinkage long sys_sparc_ipc(unsigned int call, int first,
 			       unsigned long second,
 			       unsigned long third,
 			       void __user *ptr, long fifth);
-extern asmlinkage long sparc64_newuname(struct new_utsname __user *name);
 extern asmlinkage long sparc64_personality(unsigned long personality);
 extern asmlinkage long sys64_munmap(unsigned long addr, size_t len);
 extern asmlinkage unsigned long sys64_mremap(unsigned long addr,
@@ -36,8 +33,6 @@
 					struct sigaction __user *oact,
 					void __user *restorer,
 					size_t sigsetsize);
-extern asmlinkage long sys_perfctr(int opcode, unsigned long arg0,
-				   unsigned long arg1, unsigned long arg2);
 
 extern asmlinkage void sparc64_set_context(struct pt_regs *regs);
 extern asmlinkage void sparc64_get_context(struct pt_regs *regs);
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index e575b46..9db058d 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -21,7 +21,7 @@
 /*0*/	.word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write
 /*5*/	.word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link
 /*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod
-/*15*/	.word sys_chmod, sys_lchown16, sys_brk, sys32_perfctr, sys32_lseek
+/*15*/	.word sys_chmod, sys_lchown16, sys_brk, sys_nis_syscall, sys32_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
 /*25*/	.word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause
 /*30*/	.word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
@@ -55,7 +55,7 @@
 /*170*/	.word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents
 	.word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr
 /*180*/	.word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall
-	.word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sys_sparc64_newuname
+	.word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sys_newuname
 /*190*/	.word sys32_init_module, sys_sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl
 	.word sys32_epoll_wait, sys32_ioprio_set, sys_getppid, sys32_sigaction, sys_sgetmask
 /*200*/	.word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir
@@ -96,7 +96,7 @@
 /*0*/	.word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write
 /*5*/	.word sys_open, sys_close, sys_wait4, sys_creat, sys_link
 /*10*/  .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod
-/*15*/	.word sys_chmod, sys_lchown, sys_brk, sys_perfctr, sys_lseek
+/*15*/	.word sys_chmod, sys_lchown, sys_brk, sys_nis_syscall, sys_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
 /*25*/	.word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
 /*30*/	.word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
@@ -130,13 +130,13 @@
 /*170*/	.word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
 	.word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
 /*180*/	.word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall
-	.word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_sparc64_newuname
+	.word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname
 /*190*/	.word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl
 	.word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask
 /*200*/	.word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
 	.word sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64
 /*210*/	.word sys_fadvise64_64, sys_tgkill, sys_waitpid, sys_swapoff, sys_sysinfo
-	.word sys_ipc, sys_nis_syscall, sys_clone, sys_ioprio_get, sys_adjtimex
+	.word sys_sparc_ipc, sys_nis_syscall, sys_clone, sys_ioprio_get, sys_adjtimex
 /*220*/	.word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid
 	.word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
 /*230*/	.word sys_select, sys_nis_syscall, sys_splice, sys_stime, sys_statfs64
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index 10f7bb9..bdc05a2 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -2548,15 +2548,6 @@
 					       rwbuf_stkptrs) ||
 		     TI_GSR != offsetof(struct thread_info, gsr) ||
 		     TI_XFSR != offsetof(struct thread_info, xfsr) ||
-		     TI_USER_CNTD0 != offsetof(struct thread_info,
-					       user_cntd0) ||
-		     TI_USER_CNTD1 != offsetof(struct thread_info,
-					       user_cntd1) ||
-		     TI_KERN_CNTD0 != offsetof(struct thread_info,
-					       kernel_cntd0) ||
-		     TI_KERN_CNTD1 != offsetof(struct thread_info,
-					       kernel_cntd1) ||
-		     TI_PCR != offsetof(struct thread_info, pcr_reg) ||
 		     TI_PRE_COUNT != offsetof(struct thread_info,
 					      preempt_count) ||
 		     TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
diff --git a/arch/sparc/prom/p1275.c b/arch/sparc/prom/p1275.c
index 4b7c937..2d8b70d 100644
--- a/arch/sparc/prom/p1275.c
+++ b/arch/sparc/prom/p1275.c
@@ -32,10 +32,9 @@
 extern void prom_cif_callback(void);
 
 /*
- * This provides SMP safety on the p1275buf. prom_callback() drops this lock
- * to allow recursuve acquisition.
+ * This provides SMP safety on the p1275buf.
  */
-DEFINE_SPINLOCK(prom_entry_lock);
+DEFINE_RAW_SPINLOCK(prom_entry_lock);
 
 long p1275_cmd(const char *service, long fmt, ...)
 {
@@ -47,7 +46,9 @@
 	
 	p = p1275buf.prom_buffer;
 
-	spin_lock_irqsave(&prom_entry_lock, flags);
+	raw_local_save_flags(flags);
+	raw_local_irq_restore(PIL_NMI);
+	raw_spin_lock(&prom_entry_lock);
 
 	p1275buf.prom_args[0] = (unsigned long)p;		/* service */
 	strcpy (p, service);
@@ -139,7 +140,8 @@
 	va_end(list);
 	x = p1275buf.prom_args [nargs + 3];
 
-	spin_unlock_irqrestore(&prom_entry_lock, flags);
+	raw_spin_unlock(&prom_entry_lock);
+	raw_local_irq_restore(flags);
 
 	return x;
 }
diff --git a/arch/um/.gitignore b/arch/um/.gitignore
new file mode 100644
index 0000000..a73d3a1
--- /dev/null
+++ b/arch/um/.gitignore
@@ -0,0 +1,3 @@
+kernel/config.c
+kernel/config.tmp
+kernel/vmlinux.lds
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index cf8a97f..64cda95 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -18,10 +18,10 @@
 {
 	struct chan *chan = data;
 	struct line *line = chan->line;
-	struct tty_struct *tty = line->tty;
+	struct tty_struct *tty;
 
 	if (line)
-		chan_interrupt(&line->chan_list, &line->task, tty, irq);
+		chan_interrupt(&line->chan_list, &line->task, line->tty, irq);
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 3b3c366..de317d0 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -140,7 +140,7 @@
 		goto out;
 	}
 
-	err = may_open(&nd.path, MAY_READ, FMODE_READ);
+	err = may_open(&nd.path, MAY_READ, O_RDONLY);
 	if (result) {
 		mconsole_reply(req, "Failed to open file", 1, 0);
 		path_put(&nd.path);
diff --git a/arch/um/include/asm/dma-mapping.h b/arch/um/include/asm/dma-mapping.h
index 378de4b..b948c14 100644
--- a/arch/um/include/asm/dma-mapping.h
+++ b/arch/um/include/asm/dma-mapping.h
@@ -104,14 +104,6 @@
 }
 
 static inline void
-dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
-		      unsigned long offset, size_t size,
-		      enum dma_data_direction direction)
-{
-	BUG();
-}
-
-static inline void
 dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 	       enum dma_data_direction direction)
 {
diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h
index 6c88990..2cd899f 100644
--- a/arch/um/include/asm/ptrace-generic.h
+++ b/arch/um/include/asm/ptrace-generic.h
@@ -16,6 +16,8 @@
 	struct uml_pt_regs regs;
 };
 
+#define arch_has_single_step()	(1)
+
 #define EMPTY_REGS { .regs = EMPTY_UML_PT_REGS }
 
 #define PT_REGS_IP(r) UPT_IP(&(r)->regs)
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 8e3d69e..4845099 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -12,16 +12,25 @@
 #endif
 #include "skas_ptrace.h"
 
-static inline void set_singlestepping(struct task_struct *child, int on)
+
+
+void user_enable_single_step(struct task_struct *child)
 {
-	if (on)
-		child->ptrace |= PT_DTRACE;
-	else
-		child->ptrace &= ~PT_DTRACE;
+	child->ptrace |= PT_DTRACE;
 	child->thread.singlestep_syscall = 0;
 
 #ifdef SUBARCH_SET_SINGLESTEPPING
-	SUBARCH_SET_SINGLESTEPPING(child, on);
+	SUBARCH_SET_SINGLESTEPPING(child, 1);
+#endif
+}
+
+void user_disable_single_step(struct task_struct *child)
+{
+	child->ptrace &= ~PT_DTRACE;
+	child->thread.singlestep_syscall = 0;
+
+#ifdef SUBARCH_SET_SINGLESTEPPING
+	SUBARCH_SET_SINGLESTEPPING(child, 0);
 #endif
 }
 
@@ -30,7 +39,7 @@
  */
 void ptrace_disable(struct task_struct *child)
 {
-	set_singlestepping(child,0);
+	user_disable_single_step(child);
 }
 
 extern int peek_user(struct task_struct * child, long addr, long data);
@@ -69,53 +78,6 @@
 		ret = -EIO;
 		break;
 
-	/* continue and stop at next (return from) syscall */
-	case PTRACE_SYSCALL:
-	/* restart after signal. */
-	case PTRACE_CONT: {
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-
-		set_singlestepping(child, 0);
-		if (request == PTRACE_SYSCALL)
-			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->exit_code = data;
-		wake_up_process(child);
-		ret = 0;
-		break;
-	}
-
-/*
- * make the child exit.  Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
-	case PTRACE_KILL: {
-		ret = 0;
-		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
-			break;
-
-		set_singlestepping(child, 0);
-		child->exit_code = SIGKILL;
-		wake_up_process(child);
-		break;
-	}
-
-	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		set_singlestepping(child, 1);
-		child->exit_code = data;
-		/* give it a chance to run. */
-		wake_up_process(child);
-		ret = 0;
-		break;
-	}
-
 #ifdef PTRACE_GETREGS
 	case PTRACE_GETREGS: { /* Get all gp regs from the child. */
 		if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) {
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index cccab85..4393173 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -51,51 +51,6 @@
 	return err;
 }
 
-long sys_uname(struct old_utsname __user * name)
-{
-	long err;
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err = copy_to_user(name, utsname(), sizeof (*name));
-	up_read(&uts_sem);
-	return err?-EFAULT:0;
-}
-
-long sys_olduname(struct oldold_utsname __user * name)
-{
-	long error;
-
-	if (!name)
-		return -EFAULT;
-	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
-		return -EFAULT;
-
-	down_read(&uts_sem);
-
-	error = __copy_to_user(&name->sysname, &utsname()->sysname,
-			       __OLD_UTS_LEN);
-	error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->nodename, &utsname()->nodename,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->release, &utsname()->release,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->release + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->version, &utsname()->version,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->version + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->machine, &utsname()->machine,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->machine + __OLD_UTS_LEN);
-
-	up_read(&uts_sem);
-
-	error = error ? -EFAULT : 0;
-
-	return error;
-}
-
 int kernel_execve(const char *filename, char *const argv[], char *const envp[])
 {
 	mm_segment_t fs;
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 1b549bc..804b28d 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -6,6 +6,8 @@
 	ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
 	sys_call_table.o tls.o
 
+obj-$(CONFIG_BINFMT_ELF) += elfcore.o
+
 subarch-obj-y = lib/semaphore_32.o lib/string_32.o
 subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
 subarch-obj-$(CONFIG_MODULES) += kernel/module.o
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h
index 7708854..e64cd41 100644
--- a/arch/um/sys-i386/asm/elf.h
+++ b/arch/um/sys-i386/asm/elf.h
@@ -116,47 +116,4 @@
 	}							\
 } while (0)
 
-/*
- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
- * extra segments containing the vsyscall DSO contents.  Dumping its
- * contents makes post-mortem fully interpretable later without matching up
- * the same kernel and hardware config to see what PC values meant.
- * Dumping its extra ELF program headers includes all the other information
- * a debugger needs to easily find how the vsyscall DSO was being used.
- */
-#define ELF_CORE_EXTRA_PHDRS						      \
-	(vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0 )
-
-#define ELF_CORE_WRITE_EXTRA_PHDRS					      \
-if ( vsyscall_ehdr ) {							      \
-	const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
-	const struct elf_phdr *const phdrp =				      \
-		(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
-	int i;								      \
-	Elf32_Off ofs = 0;						      \
-	for (i = 0; i < ehdrp->e_phnum; ++i) {				      \
-		struct elf_phdr phdr = phdrp[i];			      \
-		if (phdr.p_type == PT_LOAD) {				      \
-			ofs = phdr.p_offset = offset;			      \
-			offset += phdr.p_filesz;			      \
-		}							      \
-		else							      \
-			phdr.p_offset += ofs;				      \
-		phdr.p_paddr = 0; /* match other core phdrs */		      \
-		DUMP_WRITE(&phdr, sizeof(phdr));			      \
-	}								      \
-}
-#define ELF_CORE_WRITE_EXTRA_DATA					      \
-if ( vsyscall_ehdr ) {							      \
-	const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr;    \
-	const struct elf_phdr *const phdrp =				      \
-		(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);   \
-	int i;								      \
-	for (i = 0; i < ehdrp->e_phnum; ++i) {				      \
-		if (phdrp[i].p_type == PT_LOAD)				      \
-			DUMP_WRITE((void *) phdrp[i].p_vaddr,		      \
-				   phdrp[i].p_filesz);			      \
-	}								      \
-}
-
 #endif
diff --git a/arch/um/sys-i386/elfcore.c b/arch/um/sys-i386/elfcore.c
new file mode 100644
index 0000000..6bb49b6
--- /dev/null
+++ b/arch/um/sys-i386/elfcore.c
@@ -0,0 +1,83 @@
+#include <linux/elf.h>
+#include <linux/coredump.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/elf.h>
+
+
+Elf32_Half elf_core_extra_phdrs(void)
+{
+	return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
+}
+
+int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
+			       unsigned long limit)
+{
+	if ( vsyscall_ehdr ) {
+		const struct elfhdr *const ehdrp =
+			(struct elfhdr *) vsyscall_ehdr;
+		const struct elf_phdr *const phdrp =
+			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+		int i;
+		Elf32_Off ofs = 0;
+
+		for (i = 0; i < ehdrp->e_phnum; ++i) {
+			struct elf_phdr phdr = phdrp[i];
+
+			if (phdr.p_type == PT_LOAD) {
+				ofs = phdr.p_offset = offset;
+				offset += phdr.p_filesz;
+			} else {
+				phdr.p_offset += ofs;
+			}
+			phdr.p_paddr = 0; /* match other core phdrs */
+			*size += sizeof(phdr);
+			if (*size > limit
+			    || !dump_write(file, &phdr, sizeof(phdr)))
+				return 0;
+		}
+	}
+	return 1;
+}
+
+int elf_core_write_extra_data(struct file *file, size_t *size,
+			      unsigned long limit)
+{
+	if ( vsyscall_ehdr ) {
+		const struct elfhdr *const ehdrp =
+			(struct elfhdr *) vsyscall_ehdr;
+		const struct elf_phdr *const phdrp =
+			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+		int i;
+
+		for (i = 0; i < ehdrp->e_phnum; ++i) {
+			if (phdrp[i].p_type == PT_LOAD) {
+				void *addr = (void *) phdrp[i].p_vaddr;
+				size_t filesz = phdrp[i].p_filesz;
+
+				*size += filesz;
+				if (*size > limit
+				    || !dump_write(file, addr, filesz))
+					return 0;
+			}
+		}
+	}
+	return 1;
+}
+
+size_t elf_core_extra_data_size(void)
+{
+	if ( vsyscall_ehdr ) {
+		const struct elfhdr *const ehdrp =
+			(struct elfhdr *)vsyscall_ehdr;
+		const struct elf_phdr *const phdrp =
+			(const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+		int i;
+
+		for (i = 0; i < ehdrp->e_phnum; ++i)
+			if (phdrp[i].p_type == PT_LOAD)
+				return (size_t) phdrp[i].p_filesz;
+	}
+	return 0;
+}
diff --git a/arch/um/sys-i386/shared/sysdep/syscalls.h b/arch/um/sys-i386/shared/sysdep/syscalls.h
index e778767..05cb796 100644
--- a/arch/um/sys-i386/shared/sysdep/syscalls.h
+++ b/arch/um/sys-i386/shared/sysdep/syscalls.h
@@ -13,8 +13,6 @@
  */
 extern syscall_handler_t sys_rt_sigaction;
 
-extern syscall_handler_t old_mmap_i386;
-
 extern syscall_handler_t *sys_call_table[];
 
 #define EXECUTE_SYSCALL(syscall, regs) \
diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S
index c6260dd..de274071 100644
--- a/arch/um/sys-i386/sys_call_table.S
+++ b/arch/um/sys-i386/sys_call_table.S
@@ -7,7 +7,7 @@
 #define sys_vm86old sys_ni_syscall
 #define sys_vm86 sys_ni_syscall
 
-#define old_mmap old_mmap_i386
+#define old_mmap sys_old_mmap
 
 #define ptregs_fork sys_fork
 #define ptregs_execve sys_execve
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
index 857ca0b..70ca357 100644
--- a/arch/um/sys-i386/syscalls.c
+++ b/arch/um/sys-i386/syscalls.c
@@ -12,57 +12,6 @@
 #include "asm/unistd.h"
 
 /*
- * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls. Linux/i386 didn't use to be able to handle more than
- * 4 system call parameters, so these system calls used a memory
- * block for parameter passing..
- */
-
-struct mmap_arg_struct {
-	unsigned long addr;
-	unsigned long len;
-	unsigned long prot;
-	unsigned long flags;
-	unsigned long fd;
-	unsigned long offset;
-};
-
-extern int old_mmap(unsigned long addr, unsigned long len,
-		    unsigned long prot, unsigned long flags,
-		    unsigned long fd, unsigned long offset);
-
-long old_mmap_i386(struct mmap_arg_struct __user *arg)
-{
-	struct mmap_arg_struct a;
-	int err = -EFAULT;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		goto out;
-
-	err = old_mmap(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
- out:
-	return err;
-}
-
-struct sel_arg_struct {
-	unsigned long n;
-	fd_set __user *inp;
-	fd_set __user *outp;
-	fd_set __user *exp;
-	struct timeval __user *tvp;
-};
-
-long old_select(struct sel_arg_struct __user *arg)
-{
-	struct sel_arg_struct a;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-	/* sys_select() does the appropriate kernel locking */
-	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-}
-
-/*
  * The prototype on i386 is:
  *
  *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
@@ -85,92 +34,6 @@
 	return ret;
 }
 
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-long sys_ipc (uint call, int first, int second,
-	     int third, void __user *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		return sys_semtimedop(first, (struct sembuf __user *) ptr,
-				      second, NULL);
-	case SEMTIMEDOP:
-		return sys_semtimedop(first, (struct sembuf __user *) ptr,
-				      second,
-				      (const struct timespec __user *) fifth);
-	case SEMGET:
-		return sys_semget (first, second, third);
-	case SEMCTL: {
-		union semun fourth;
-		if (!ptr)
-			return -EINVAL;
-		if (get_user(fourth.__pad, (void __user * __user *) ptr))
-			return -EFAULT;
-		return sys_semctl (first, second, third, fourth);
-	}
-
-	case MSGSND:
-		return sys_msgsnd (first, (struct msgbuf *) ptr,
-				   second, third);
-	case MSGRCV:
-		switch (version) {
-		case 0: {
-			struct ipc_kludge tmp;
-			if (!ptr)
-				return -EINVAL;
-
-			if (copy_from_user(&tmp,
-					   (struct ipc_kludge *) ptr,
-					   sizeof (tmp)))
-				return -EFAULT;
-			return sys_msgrcv (first, tmp.msgp, second,
-					   tmp.msgtyp, third);
-		}
-		default:
-		        panic("msgrcv with version != 0");
-			return sys_msgrcv (first,
-					   (struct msgbuf *) ptr,
-					   second, fifth, third);
-		}
-	case MSGGET:
-		return sys_msgget ((key_t) first, second);
-	case MSGCTL:
-		return sys_msgctl (first, second, (struct msqid_ds *) ptr);
-
-	case SHMAT:
-		switch (version) {
-		default: {
-			ulong raddr;
-			ret = do_shmat (first, (char *) ptr, second, &raddr);
-			if (ret)
-				return ret;
-			return put_user (raddr, (ulong *) third);
-		}
-		case 1:	/* iBCS2 emulator entry point */
-			if (!segment_eq(get_fs(), get_ds()))
-				return -EINVAL;
-			return do_shmat (first, (char *) ptr, second, (ulong *) third);
-		}
-	case SHMDT:
-		return sys_shmdt ((char *)ptr);
-	case SHMGET:
-		return sys_shmget (first, second, third);
-	case SHMCTL:
-		return sys_shmctl (first, second,
-				   (struct shmid_ds *) ptr);
-	default:
-		return -ENOSYS;
-	}
-}
-
 long sys_sigaction(int sig, const struct old_sigaction __user *act,
 			 struct old_sigaction __user *oact)
 {
diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c
index dd21d69..47d469e 100644
--- a/arch/um/sys-x86_64/syscall_table.c
+++ b/arch/um/sys-x86_64/syscall_table.c
@@ -26,11 +26,6 @@
 
 /* On UML we call it this way ("old" means it's not mmap2) */
 #define sys_mmap old_mmap
-/*
- * On x86-64 sys_uname is actually sys_newuname plus a compatibility trick.
- * See arch/x86_64/kernel/sys_x86_64.c
- */
-#define sys_uname sys_uname64
 
 #define stub_clone sys_clone
 #define stub_fork sys_fork
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index f1199fd..f3d82bb 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -12,20 +12,6 @@
 #include "asm/uaccess.h"
 #include "os.h"
 
-asmlinkage long sys_uname64(struct new_utsname __user * name)
-{
-	int err;
-
-	down_read(&uts_sem);
-	err = copy_to_user(name, utsname(), sizeof (*name));
-	up_read(&uts_sem);
-
-	if (personality(current->personality) == PER_LINUX32)
-		err |= copy_to_user(&name->machine, "i686", 5);
-
-	return err ? -EFAULT : 0;
-}
-
 long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
 {
 	unsigned long *ptr = addr, tmp;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0896008..0eacb1f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -31,6 +31,7 @@
 	select ARCH_WANT_FRAME_POINTERS
 	select HAVE_DMA_ATTRS
 	select HAVE_KRETPROBES
+	select HAVE_OPTPROBES
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FUNCTION_TRACER
@@ -101,6 +102,9 @@
 config SBUS
 	bool
 
+config NEED_DMA_MAP_STATE
+       def_bool (X86_64 || DMAR || DMA_API_DEBUG)
+
 config GENERIC_ISA_DMA
 	def_bool y
 
@@ -184,6 +188,9 @@
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
 	def_bool y
 
+config HAVE_EARLY_RES
+	def_bool y
+
 config HAVE_INTEL_TXT
 	def_bool y
 	depends on EXPERIMENTAL && DMAR && ACPI
@@ -389,8 +396,12 @@
 
 config X86_MRST
        bool "Moorestown MID platform"
+	depends on PCI
+	depends on PCI_GOANY
 	depends on X86_32
 	depends on X86_EXTENDED_PLATFORM
+	depends on X86_IO_APIC
+	select APB_TIMER
 	---help---
 	  Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin
 	  Internet Device(MID) platform. Moorestown consists of two chips:
@@ -425,6 +436,7 @@
 config X86_NUMAQ
 	bool "NUMAQ (IBM/Sequent)"
 	depends on X86_32_NON_STANDARD
+	depends on PCI
 	select NUMA
 	select X86_MPPARSE
 	---help---
@@ -569,6 +581,18 @@
 	  Enable to debug paravirt_ops internals.  Specifically, BUG if
 	  a paravirt_op is missing when it is called.
 
+config NO_BOOTMEM
+	default y
+	bool "Disable Bootmem code"
+	---help---
+	  Use early_res directly instead of bootmem before slab is ready.
+		- allocator (buddy) [generic]
+		- early allocator (bootmem) [generic]
+		- very early allocator (reserve_early*()) [x86]
+		- very very early allocator (early brk model) [x86]
+	  So reduce one layer between early allocator to final allocator
+
+
 config MEMTEST
 	bool "Memtest"
 	---help---
@@ -613,6 +637,16 @@
 	def_bool y
 	depends on HPET_TIMER && (RTC=y || RTC=m || RTC_DRV_CMOS=m || RTC_DRV_CMOS=y)
 
+config APB_TIMER
+       def_bool y if MRST
+       prompt "Langwell APB Timer Support" if X86_MRST
+       help
+         APB timer is the replacement for 8254, HPET on X86 MID platforms.
+         The APBT provides a stable time base on SMP
+         systems, unlike the TSC, but it is more expensive to access,
+         as it is off-chip. APB timers are always running regardless of CPU
+         C states, they are used as per CPU clockevent device when possible.
+
 # Mark as embedded because too many people got it wrong.
 # The code disables itself when not needed.
 config DMI
@@ -628,7 +662,7 @@
 	bool "GART IOMMU support" if EMBEDDED
 	default y
 	select SWIOTLB
-	depends on X86_64 && PCI
+	depends on X86_64 && PCI && K8_NB
 	---help---
 	  Support for full DMA access of devices with 32bit memory access only
 	  on systems with more than 3GB. This is usually needed for USB,
@@ -2027,7 +2061,7 @@
 
 config K8_NB
 	def_bool y
-	depends on AGP_AMD64 || (X86_64 && (GART_IOMMU || (PCI && NUMA)))
+	depends on CPU_SUP_AMD && PCI
 
 source "drivers/pcmcia/Kconfig"
 
diff --git a/arch/x86/crypto/twofish-i586-asm_32.S b/arch/x86/crypto/twofish-i586-asm_32.S
index 39b98ed..575331c 100644
--- a/arch/x86/crypto/twofish-i586-asm_32.S
+++ b/arch/x86/crypto/twofish-i586-asm_32.S
@@ -22,7 +22,7 @@
 
 #include <asm/asm-offsets.h>
 
-/* return adress at 0 */
+/* return address at 0 */
 
 #define in_blk    12  /* input byte array address parameter*/
 #define out_blk   8  /* output byte array address parameter*/
@@ -230,8 +230,8 @@
 	push    %edi
 
 	mov	tfm + 16(%esp),	%ebp	/* abuse the base pointer: set new base bointer to the crypto tfm */
-	add	$crypto_tfm_ctx_offset, %ebp	/* ctx adress */
-	mov     in_blk+16(%esp),%edi	/* input adress in edi */
+	add	$crypto_tfm_ctx_offset, %ebp	/* ctx address */
+	mov     in_blk+16(%esp),%edi	/* input address in edi */
 
 	mov	(%edi),		%eax
 	mov	b_offset(%edi),	%ebx
@@ -286,8 +286,8 @@
 
 
 	mov	tfm + 16(%esp),	%ebp	/* abuse the base pointer: set new base bointer to the crypto tfm */
-	add	$crypto_tfm_ctx_offset, %ebp	/* ctx adress */
-	mov     in_blk+16(%esp),%edi	/* input adress in edi */
+	add	$crypto_tfm_ctx_offset, %ebp	/* ctx address */
+	mov     in_blk+16(%esp),%edi	/* input address in edi */
 
 	mov	(%edi),		%eax
 	mov	b_offset(%edi),	%ebx
diff --git a/arch/x86/crypto/twofish-x86_64-asm_64.S b/arch/x86/crypto/twofish-x86_64-asm_64.S
index 35974a5..573aa10 100644
--- a/arch/x86/crypto/twofish-x86_64-asm_64.S
+++ b/arch/x86/crypto/twofish-x86_64-asm_64.S
@@ -221,11 +221,11 @@
 twofish_enc_blk:
 	pushq    R1
 
-	/* %rdi contains the crypto tfm adress */
-	/* %rsi contains the output adress */
-	/* %rdx contains the input adress */
-	add	$crypto_tfm_ctx_offset, %rdi	/* set ctx adress */
-	/* ctx adress is moved to free one non-rex register
+	/* %rdi contains the crypto tfm address */
+	/* %rsi contains the output address */
+	/* %rdx contains the input address */
+	add	$crypto_tfm_ctx_offset, %rdi	/* set ctx address */
+	/* ctx address is moved to free one non-rex register
 	as target for the 8bit high operations */
 	mov	%rdi,		%r11
 
@@ -274,11 +274,11 @@
 twofish_dec_blk:
 	pushq    R1
 
-	/* %rdi contains the crypto tfm adress */
-	/* %rsi contains the output adress */
-	/* %rdx contains the input adress */
-	add	$crypto_tfm_ctx_offset, %rdi	/* set ctx adress */
-	/* ctx adress is moved to free one non-rex register
+	/* %rdi contains the crypto tfm address */
+	/* %rsi contains the output address */
+	/* %rdx contains the input address */
+	add	$crypto_tfm_ctx_offset, %rdi	/* set ctx address */
+	/* ctx address is moved to free one non-rex register
 	as target for the 8bit high operations */
 	mov	%rdi,		%r11
 
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index 9046e4a..280c019 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -327,7 +327,6 @@
 	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
 	current->mm->cached_hole_size = 0;
 
-	current->mm->mmap = NULL;
 	install_exec_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
 
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 53147ad..59b4556 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -563,7 +563,7 @@
 	.quad quiet_ni_syscall			/* old mpx syscall holder */
 	.quad sys_setpgid
 	.quad quiet_ni_syscall			/* old ulimit syscall holder */
-	.quad sys32_olduname
+	.quad sys_olduname
 	.quad sys_umask		/* 60 */
 	.quad sys_chroot
 	.quad compat_sys_ustat
@@ -586,7 +586,7 @@
 	.quad compat_sys_settimeofday
 	.quad sys_getgroups16	/* 80 */
 	.quad sys_setgroups16
-	.quad sys32_old_select
+	.quad compat_sys_old_select
 	.quad sys_symlink
 	.quad sys_lstat
 	.quad sys_readlink		/* 85 */
@@ -613,7 +613,7 @@
 	.quad compat_sys_newstat
 	.quad compat_sys_newlstat
 	.quad compat_sys_newfstat
-	.quad sys32_uname
+	.quad sys_uname
 	.quad stub32_iopl		/* 110 */
 	.quad sys_vhangup
 	.quad quiet_ni_syscall	/* old "idle" system call */
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 422572c..74c3543 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -143,7 +143,7 @@
  * block for parameter passing..
  */
 
-struct mmap_arg_struct {
+struct mmap_arg_struct32 {
 	unsigned int addr;
 	unsigned int len;
 	unsigned int prot;
@@ -152,9 +152,9 @@
 	unsigned int offset;
 };
 
-asmlinkage long sys32_mmap(struct mmap_arg_struct __user *arg)
+asmlinkage long sys32_mmap(struct mmap_arg_struct32 __user *arg)
 {
-	struct mmap_arg_struct a;
+	struct mmap_arg_struct32 a;
 
 	if (copy_from_user(&a, arg, sizeof(a)))
 		return -EFAULT;
@@ -332,24 +332,6 @@
 	return alarm_setitimer(seconds);
 }
 
-struct sel_arg_struct {
-	unsigned int n;
-	unsigned int inp;
-	unsigned int outp;
-	unsigned int exp;
-	unsigned int tvp;
-};
-
-asmlinkage long sys32_old_select(struct sel_arg_struct __user *arg)
-{
-	struct sel_arg_struct a;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-	return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp),
-				 compat_ptr(a.exp), compat_ptr(a.tvp));
-}
-
 asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr,
 			      int options)
 {
@@ -466,58 +448,6 @@
 	return ret;
 }
 
-asmlinkage long sys32_olduname(struct oldold_utsname __user *name)
-{
-	char *arch = "x86_64";
-	int err;
-
-	if (!name)
-		return -EFAULT;
-	if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
-		return -EFAULT;
-
-	down_read(&uts_sem);
-
-	err = __copy_to_user(&name->sysname, &utsname()->sysname,
-			     __OLD_UTS_LEN);
-	err |= __put_user(0, name->sysname+__OLD_UTS_LEN);
-	err |= __copy_to_user(&name->nodename, &utsname()->nodename,
-			      __OLD_UTS_LEN);
-	err |= __put_user(0, name->nodename+__OLD_UTS_LEN);
-	err |= __copy_to_user(&name->release, &utsname()->release,
-			      __OLD_UTS_LEN);
-	err |= __put_user(0, name->release+__OLD_UTS_LEN);
-	err |= __copy_to_user(&name->version, &utsname()->version,
-			      __OLD_UTS_LEN);
-	err |= __put_user(0, name->version+__OLD_UTS_LEN);
-
-	if (personality(current->personality) == PER_LINUX32)
-		arch = "i686";
-
-	err |= __copy_to_user(&name->machine, arch, strlen(arch) + 1);
-
-	up_read(&uts_sem);
-
-	err = err ? -EFAULT : 0;
-
-	return err;
-}
-
-long sys32_uname(struct old_utsname __user *name)
-{
-	int err;
-
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err = copy_to_user(name, utsname(), sizeof(*name));
-	up_read(&uts_sem);
-	if (personality(current->personality) == PER_LINUX32)
-		err |= copy_to_user(&name->machine, "i686", 5);
-
-	return err ? -EFAULT : 0;
-}
-
 asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
 			     compat_uptr_t __user *envp, struct pt_regs *regs)
 {
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 9f828f8..493092e 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -11,6 +11,7 @@
 header-y += ucontext.h
 header-y += processor-flags.h
 header-y += hw_breakpoint.h
+header-y += hyperv.h
 
 unifdef-y += e820.h
 unifdef-y += ist.h
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index f1e253c..b09ec55 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -165,10 +165,12 @@
  * invalid instruction possible) or if the instructions are changed from a
  * consistent state to another consistent state atomically.
  * More care must be taken when modifying code in the SMP case because of
- * Intel's errata.
+ * Intel's errata. text_poke_smp() takes care that errata, but still
+ * doesn't support NMI/MCE handler code modifying.
  * On the local CPU you need to be protected again NMI or MCE handlers seeing an
  * inconsistent instruction while you patch.
  */
 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);
 
 #endif /* _ASM_X86_ALTERNATIVE_H */
diff --git a/arch/x86/include/asm/apb_timer.h b/arch/x86/include/asm/apb_timer.h
new file mode 100644
index 0000000..c74a2ee
--- /dev/null
+++ b/arch/x86/include/asm/apb_timer.h
@@ -0,0 +1,70 @@
+/*
+ * apb_timer.h: Driver for Langwell APB timer based on Synopsis DesignWare
+ *
+ * (C) Copyright 2009 Intel Corporation
+ * Author: Jacob Pan (jacob.jun.pan@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:
+ */
+
+#ifndef ASM_X86_APBT_H
+#define ASM_X86_APBT_H
+#include <linux/sfi.h>
+
+#ifdef CONFIG_APB_TIMER
+
+/* Langwell DW APB timer registers */
+#define APBTMR_N_LOAD_COUNT    0x00
+#define APBTMR_N_CURRENT_VALUE 0x04
+#define APBTMR_N_CONTROL       0x08
+#define APBTMR_N_EOI           0x0c
+#define APBTMR_N_INT_STATUS    0x10
+
+#define APBTMRS_INT_STATUS     0xa0
+#define APBTMRS_EOI            0xa4
+#define APBTMRS_RAW_INT_STATUS 0xa8
+#define APBTMRS_COMP_VERSION   0xac
+#define APBTMRS_REG_SIZE       0x14
+
+/* register bits */
+#define APBTMR_CONTROL_ENABLE  (1<<0)
+#define APBTMR_CONTROL_MODE_PERIODIC   (1<<1) /*1: periodic 0:free running */
+#define APBTMR_CONTROL_INT     (1<<2)
+
+/* default memory mapped register base */
+#define LNW_SCU_ADDR           0xFF100000
+#define LNW_EXT_TIMER_OFFSET   0x1B800
+#define APBT_DEFAULT_BASE      (LNW_SCU_ADDR+LNW_EXT_TIMER_OFFSET)
+#define LNW_EXT_TIMER_PGOFFSET         0x800
+
+/* APBT clock speed range from PCLK to fabric base, 25-100MHz */
+#define APBT_MAX_FREQ          50
+#define APBT_MIN_FREQ          1
+#define APBT_MMAP_SIZE         1024
+
+#define APBT_DEV_USED  1
+
+extern void apbt_time_init(void);
+extern struct clock_event_device *global_clock_event;
+extern unsigned long apbt_quick_calibrate(void);
+extern int arch_setup_apbt_irqs(int irq, int trigger, int mask, int cpu);
+extern void apbt_setup_secondary_clock(void);
+extern unsigned int boot_cpu_id;
+extern int disable_apbt_percpu;
+
+extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint);
+extern void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr);
+extern int sfi_mtimer_num;
+
+#else /* CONFIG_APB_TIMER */
+
+static inline unsigned long apbt_quick_calibrate(void) {return 0; }
+static inline void apbt_time_init(void) {return 0; }
+
+#endif
+#endif /* ASM_X86_APBT_H */
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index 9a9c7bd..306160e 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -8,7 +8,8 @@
 #include <linux/sched.h>
 #include <asm/user32.h>
 
-#define COMPAT_USER_HZ	100
+#define COMPAT_USER_HZ		100
+#define COMPAT_UTS_MACHINE	"i686\0\0"
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index 761249e..0e22296 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -111,11 +111,8 @@
 
 extern u64 find_e820_area(u64 start, u64 end, u64 size, u64 align);
 extern u64 find_e820_area_size(u64 start, u64 *sizep, u64 align);
-extern void reserve_early(u64 start, u64 end, char *name);
-extern void reserve_early_overlap_ok(u64 start, u64 end, char *name);
-extern void free_early(u64 start, u64 end);
-extern void early_res_to_bootmem(u64 start, u64 end);
 extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
+#include <linux/early_res.h>
 
 extern unsigned long e820_end_of_ram_pfn(void);
 extern unsigned long e820_end_of_low_ram_pfn(void);
diff --git a/arch/x86/include/asm/highmem.h b/arch/x86/include/asm/highmem.h
index 014c2b85..a726650 100644
--- a/arch/x86/include/asm/highmem.h
+++ b/arch/x86/include/asm/highmem.h
@@ -66,10 +66,6 @@
 void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
 struct page *kmap_atomic_to_page(void *ptr);
 
-#ifndef CONFIG_PARAVIRT
-#define kmap_atomic_pte(page, type)	kmap_atomic(page, type)
-#endif
-
 #define flush_cache_kmaps()	do { } while (0)
 
 extern void add_highpages_with_active_regions(int nid, unsigned long start_pfn,
diff --git a/arch/x86/include/asm/hw_breakpoint.h b/arch/x86/include/asm/hw_breakpoint.h
index 0675a7c..2a1bd8f 100644
--- a/arch/x86/include/asm/hw_breakpoint.h
+++ b/arch/x86/include/asm/hw_breakpoint.h
@@ -10,7 +10,6 @@
  * (display/resolving)
  */
 struct arch_hw_breakpoint {
-	char		*name; /* Contains name of the symbol to set bkpt */
 	unsigned long	address;
 	u8		len;
 	u8		type;
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index eeac829..a929c9e 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -53,13 +53,6 @@
 extern void call_function_interrupt(void);
 extern void call_function_single_interrupt(void);
 
-/* PIC specific functions */
-extern void disable_8259A_irq(unsigned int irq);
-extern void enable_8259A_irq(unsigned int irq);
-extern int i8259A_irq_pending(unsigned int irq);
-extern void make_8259A_irq(unsigned int irq);
-extern void init_8259A(int aeoi);
-
 /* IOAPIC */
 #define IO_APIC_IRQ(x) (((x) >= NR_IRQS_LEGACY) || ((1<<(x)) & io_apic_irqs))
 extern unsigned long io_apic_irqs;
diff --git a/arch/x86/include/asm/hyperv.h b/arch/x86/include/asm/hyperv.h
new file mode 100644
index 0000000..e153a2b3
--- /dev/null
+++ b/arch/x86/include/asm/hyperv.h
@@ -0,0 +1,186 @@
+#ifndef _ASM_X86_KVM_HYPERV_H
+#define _ASM_X86_KVM_HYPERV_H
+
+#include <linux/types.h>
+
+/*
+ * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
+ * is set by CPUID(HvCpuIdFunctionVersionAndFeatures).
+ */
+#define HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS	0x40000000
+#define HYPERV_CPUID_INTERFACE			0x40000001
+#define HYPERV_CPUID_VERSION			0x40000002
+#define HYPERV_CPUID_FEATURES			0x40000003
+#define HYPERV_CPUID_ENLIGHTMENT_INFO		0x40000004
+#define HYPERV_CPUID_IMPLEMENT_LIMITS		0x40000005
+
+/*
+ * Feature identification. EAX indicates which features are available
+ * to the partition based upon the current partition privileges.
+ */
+
+/* VP Runtime (HV_X64_MSR_VP_RUNTIME) available */
+#define HV_X64_MSR_VP_RUNTIME_AVAILABLE		(1 << 0)
+/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
+#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE	(1 << 1)
+/*
+ * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM
+ * and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15) available
+ */
+#define HV_X64_MSR_SYNIC_AVAILABLE		(1 << 2)
+/*
+ * Synthetic Timer MSRs (HV_X64_MSR_STIMER0_CONFIG through
+ * HV_X64_MSR_STIMER3_COUNT) available
+ */
+#define HV_X64_MSR_SYNTIMER_AVAILABLE		(1 << 3)
+/*
+ * APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
+ * are available
+ */
+#define HV_X64_MSR_APIC_ACCESS_AVAILABLE	(1 << 4)
+/* Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL) available*/
+#define HV_X64_MSR_HYPERCALL_AVAILABLE		(1 << 5)
+/* Access virtual processor index MSR (HV_X64_MSR_VP_INDEX) available*/
+#define HV_X64_MSR_VP_INDEX_AVAILABLE		(1 << 6)
+/* Virtual system reset MSR (HV_X64_MSR_RESET) is available*/
+#define HV_X64_MSR_RESET_AVAILABLE		(1 << 7)
+ /*
+  * Access statistics pages MSRs (HV_X64_MSR_STATS_PARTITION_RETAIL_PAGE,
+  * HV_X64_MSR_STATS_PARTITION_INTERNAL_PAGE, HV_X64_MSR_STATS_VP_RETAIL_PAGE,
+  * HV_X64_MSR_STATS_VP_INTERNAL_PAGE) available
+  */
+#define HV_X64_MSR_STAT_PAGES_AVAILABLE		(1 << 8)
+
+/*
+ * Feature identification: EBX indicates which flags were specified at
+ * partition creation. The format is the same as the partition creation
+ * flag structure defined in section Partition Creation Flags.
+ */
+#define HV_X64_CREATE_PARTITIONS		(1 << 0)
+#define HV_X64_ACCESS_PARTITION_ID		(1 << 1)
+#define HV_X64_ACCESS_MEMORY_POOL		(1 << 2)
+#define HV_X64_ADJUST_MESSAGE_BUFFERS		(1 << 3)
+#define HV_X64_POST_MESSAGES			(1 << 4)
+#define HV_X64_SIGNAL_EVENTS			(1 << 5)
+#define HV_X64_CREATE_PORT			(1 << 6)
+#define HV_X64_CONNECT_PORT			(1 << 7)
+#define HV_X64_ACCESS_STATS			(1 << 8)
+#define HV_X64_DEBUGGING			(1 << 11)
+#define HV_X64_CPU_POWER_MANAGEMENT		(1 << 12)
+#define HV_X64_CONFIGURE_PROFILER		(1 << 13)
+
+/*
+ * Feature identification. EDX indicates which miscellaneous features
+ * are available to the partition.
+ */
+/* The MWAIT instruction is available (per section MONITOR / MWAIT) */
+#define HV_X64_MWAIT_AVAILABLE				(1 << 0)
+/* Guest debugging support is available */
+#define HV_X64_GUEST_DEBUGGING_AVAILABLE		(1 << 1)
+/* Performance Monitor support is available*/
+#define HV_X64_PERF_MONITOR_AVAILABLE			(1 << 2)
+/* Support for physical CPU dynamic partitioning events is available*/
+#define HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE	(1 << 3)
+/*
+ * Support for passing hypercall input parameter block via XMM
+ * registers is available
+ */
+#define HV_X64_HYPERCALL_PARAMS_XMM_AVAILABLE		(1 << 4)
+/* Support for a virtual guest idle state is available */
+#define HV_X64_GUEST_IDLE_STATE_AVAILABLE		(1 << 5)
+
+/*
+ * Implementation recommendations. Indicates which behaviors the hypervisor
+ * recommends the OS implement for optimal performance.
+ */
+ /*
+  * Recommend using hypercall for address space switches rather
+  * than MOV to CR3 instruction
+  */
+#define HV_X64_MWAIT_RECOMMENDED		(1 << 0)
+/* Recommend using hypercall for local TLB flushes rather
+ * than INVLPG or MOV to CR3 instructions */
+#define HV_X64_LOCAL_TLB_FLUSH_RECOMMENDED	(1 << 1)
+/*
+ * Recommend using hypercall for remote TLB flushes rather
+ * than inter-processor interrupts
+ */
+#define HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED	(1 << 2)
+/*
+ * Recommend using MSRs for accessing APIC registers
+ * EOI, ICR and TPR rather than their memory-mapped counterparts
+ */
+#define HV_X64_APIC_ACCESS_RECOMMENDED		(1 << 3)
+/* Recommend using the hypervisor-provided MSR to initiate a system RESET */
+#define HV_X64_SYSTEM_RESET_RECOMMENDED		(1 << 4)
+/*
+ * Recommend using relaxed timing for this partition. If used,
+ * the VM should disable any watchdog timeouts that rely on the
+ * timely delivery of external interrupts
+ */
+#define HV_X64_RELAXED_TIMING_RECOMMENDED	(1 << 5)
+
+/* MSR used to identify the guest OS. */
+#define HV_X64_MSR_GUEST_OS_ID			0x40000000
+
+/* MSR used to setup pages used to communicate with the hypervisor. */
+#define HV_X64_MSR_HYPERCALL			0x40000001
+
+/* MSR used to provide vcpu index */
+#define HV_X64_MSR_VP_INDEX			0x40000002
+
+/* Define the virtual APIC registers */
+#define HV_X64_MSR_EOI				0x40000070
+#define HV_X64_MSR_ICR				0x40000071
+#define HV_X64_MSR_TPR				0x40000072
+#define HV_X64_MSR_APIC_ASSIST_PAGE		0x40000073
+
+/* Define synthetic interrupt controller model specific registers. */
+#define HV_X64_MSR_SCONTROL			0x40000080
+#define HV_X64_MSR_SVERSION			0x40000081
+#define HV_X64_MSR_SIEFP			0x40000082
+#define HV_X64_MSR_SIMP				0x40000083
+#define HV_X64_MSR_EOM				0x40000084
+#define HV_X64_MSR_SINT0			0x40000090
+#define HV_X64_MSR_SINT1			0x40000091
+#define HV_X64_MSR_SINT2			0x40000092
+#define HV_X64_MSR_SINT3			0x40000093
+#define HV_X64_MSR_SINT4			0x40000094
+#define HV_X64_MSR_SINT5			0x40000095
+#define HV_X64_MSR_SINT6			0x40000096
+#define HV_X64_MSR_SINT7			0x40000097
+#define HV_X64_MSR_SINT8			0x40000098
+#define HV_X64_MSR_SINT9			0x40000099
+#define HV_X64_MSR_SINT10			0x4000009A
+#define HV_X64_MSR_SINT11			0x4000009B
+#define HV_X64_MSR_SINT12			0x4000009C
+#define HV_X64_MSR_SINT13			0x4000009D
+#define HV_X64_MSR_SINT14			0x4000009E
+#define HV_X64_MSR_SINT15			0x4000009F
+
+
+#define HV_X64_MSR_HYPERCALL_ENABLE		0x00000001
+#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT	12
+#define HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_MASK	\
+		(~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1))
+
+/* Declare the various hypercall operations. */
+#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT		0x0008
+
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE		0x00000001
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT	12
+#define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_MASK	\
+		(~((1ull << HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT) - 1))
+
+#define HV_PROCESSOR_POWER_STATE_C0		0
+#define HV_PROCESSOR_POWER_STATE_C1		1
+#define HV_PROCESSOR_POWER_STATE_C2		2
+#define HV_PROCESSOR_POWER_STATE_C3		3
+
+/* hypercall status code */
+#define HV_STATUS_SUCCESS			0
+#define HV_STATUS_INVALID_HYPERCALL_CODE	2
+#define HV_STATUS_INVALID_HYPERCALL_INPUT	3
+#define HV_STATUS_INVALID_ALIGNMENT		4
+
+#endif
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index 58d7091..1655147 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -24,12 +24,7 @@
 #define SLAVE_ICW4_DEFAULT	0x01
 #define PIC_ICW4_AEOI		2
 
-extern spinlock_t i8259A_lock;
-
-extern void init_8259A(int auto_eoi);
-extern void enable_8259A_irq(unsigned int irq);
-extern void disable_8259A_irq(unsigned int irq);
-extern unsigned int startup_8259A_irq(unsigned int irq);
+extern raw_spinlock_t i8259A_lock;
 
 /* the PIC may need a careful delay on some platforms, hence specific calls */
 static inline unsigned char inb_pic(unsigned int port)
@@ -57,7 +52,17 @@
 
 extern struct irq_chip i8259A_chip;
 
-extern void mask_8259A(void);
-extern void unmask_8259A(void);
+struct legacy_pic {
+	int nr_legacy_irqs;
+	struct irq_chip *chip;
+	void (*mask_all)(void);
+	void (*restore_mask)(void);
+	void (*init)(int auto_eoi);
+	int (*irq_pending)(unsigned int irq);
+	void (*make_irq)(unsigned int irq);
+};
+
+extern struct legacy_pic *legacy_pic;
+extern struct legacy_pic null_legacy_pic;
 
 #endif /* _ASM_X86_I8259_H */
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 7c7c16c..35832a0 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -143,8 +143,6 @@
 /* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */
 extern int timer_through_8259;
 
-extern void io_apic_disable_legacy(void);
-
 /*
  * If we use the IO-APIC for IRQ routing, disable automatic
  * assignment of PCI IRQ's.
@@ -160,6 +158,7 @@
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
+void setup_IO_APIC_irq_extra(u32 gsi);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
 extern void ioapic_insert_resources(void);
@@ -188,6 +187,7 @@
 int mp_find_ioapic(int gsi);
 int mp_find_ioapic_pin(int ioapic, int gsi);
 void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
+extern void __init pre_init_apic_IRQ0(void);
 
 #else  /* !CONFIG_X86_IO_APIC */
 
@@ -197,7 +197,11 @@
 static inline void ioapic_init_mappings(void)	{ }
 static inline void ioapic_insert_resources(void) { }
 static inline void probe_nr_irqs_gsi(void)	{ }
+static inline int mp_find_ioapic(int gsi) { return 0; }
 
+struct io_apic_irq_attr;
+static inline int io_apic_set_pci_routing(struct device *dev, int irq,
+		 struct io_apic_irq_attr *irq_attr) { return 0; }
 #endif
 
 #endif /* _ASM_X86_IO_APIC_H */
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 4611f08..8767d99 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -28,28 +28,33 @@
 #define MCE_VECTOR			0x12
 
 /*
- * IDT vectors usable for external interrupt sources start
- * at 0x20:
+ * IDT vectors usable for external interrupt sources start at 0x20.
+ * (0x80 is the syscall vector, 0x30-0x3f are for ISA)
  */
 #define FIRST_EXTERNAL_VECTOR		0x20
-
-#ifdef CONFIG_X86_32
-# define SYSCALL_VECTOR			0x80
-# define IA32_SYSCALL_VECTOR		0x80
-#else
-# define IA32_SYSCALL_VECTOR		0x80
-#endif
+/*
+ * We start allocating at 0x21 to spread out vectors evenly between
+ * priority levels. (0x80 is the syscall vector)
+ */
+#define VECTOR_OFFSET_START		1
 
 /*
- * Reserve the lowest usable priority level 0x20 - 0x2f for triggering
- * cleanup after irq migration.
+ * Reserve the lowest usable vector (and hence lowest priority)  0x20 for
+ * triggering cleanup after irq migration. 0x21-0x2f will still be used
+ * for device interrupts.
  */
 #define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
 
+#define IA32_SYSCALL_VECTOR		0x80
+#ifdef CONFIG_X86_32
+# define SYSCALL_VECTOR			0x80
+#endif
+
 /*
  * Vectors 0x30-0x3f are used for ISA interrupts.
+ *   round up to the next 16-vector boundary
  */
-#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 0x10)
+#define IRQ0_VECTOR			((FIRST_EXTERNAL_VECTOR + 16) & ~15)
 
 #define IRQ1_VECTOR			(IRQ0_VECTOR +  1)
 #define IRQ2_VECTOR			(IRQ0_VECTOR +  2)
@@ -120,13 +125,6 @@
  */
 #define MCE_SELF_VECTOR			0xeb
 
-/*
- * First APIC vector available to drivers: (vectors 0x30-0xee) we
- * start at 0x31(0x41) to spread out vectors evenly between priority
- * levels. (0x80 is the syscall vector)
- */
-#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
-
 #define NR_VECTORS			 256
 
 #define FPU_IRQ				  13
@@ -154,21 +152,21 @@
 
 #define NR_IRQS_LEGACY			  16
 
-#define CPU_VECTOR_LIMIT		(  8 * NR_CPUS      )
 #define IO_APIC_VECTOR_LIMIT		( 32 * MAX_IO_APICS )
 
 #ifdef CONFIG_X86_IO_APIC
 # ifdef CONFIG_SPARSE_IRQ
+#  define CPU_VECTOR_LIMIT		(64 * NR_CPUS)
 #  define NR_IRQS					\
 	(CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ?	\
 		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
 		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
 # else
-#  if NR_CPUS < MAX_IO_APICS
-#   define NR_IRQS 			(NR_VECTORS + 4*CPU_VECTOR_LIMIT)
-#  else
-#   define NR_IRQS			(NR_VECTORS + IO_APIC_VECTOR_LIMIT)
-#  endif
+#  define CPU_VECTOR_LIMIT		(32 * NR_CPUS)
+#  define NR_IRQS					\
+	(CPU_VECTOR_LIMIT < IO_APIC_VECTOR_LIMIT ?	\
+		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
+		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
 # endif
 #else /* !CONFIG_X86_IO_APIC: */
 # define NR_IRQS			NR_IRQS_LEGACY
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index 4fe681d..4ffa345 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -32,7 +32,10 @@
 
 typedef u8 kprobe_opcode_t;
 #define BREAKPOINT_INSTRUCTION	0xcc
-#define RELATIVEJUMP_INSTRUCTION 0xe9
+#define RELATIVEJUMP_OPCODE 0xe9
+#define RELATIVEJUMP_SIZE 5
+#define RELATIVECALL_OPCODE 0xe8
+#define RELATIVE_ADDR_SIZE 4
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
 #define MIN_STACK_SIZE(ADDR)					       \
@@ -44,6 +47,17 @@
 
 #define flush_insn_slot(p)	do { } while (0)
 
+/* optinsn template addresses */
+extern kprobe_opcode_t optprobe_template_entry;
+extern kprobe_opcode_t optprobe_template_val;
+extern kprobe_opcode_t optprobe_template_call;
+extern kprobe_opcode_t optprobe_template_end;
+#define MAX_OPTIMIZED_LENGTH (MAX_INSN_SIZE + RELATIVE_ADDR_SIZE)
+#define MAX_OPTINSN_SIZE 				\
+	(((unsigned long)&optprobe_template_end -	\
+	  (unsigned long)&optprobe_template_entry) +	\
+	 MAX_OPTIMIZED_LENGTH + RELATIVEJUMP_SIZE)
+
 extern const int kretprobe_blacklist_size;
 
 void arch_remove_kprobe(struct kprobe *p);
@@ -64,6 +78,21 @@
 	int boostable;
 };
 
+struct arch_optimized_insn {
+	/* copy of the original instructions */
+	kprobe_opcode_t copied_insn[RELATIVE_ADDR_SIZE];
+	/* detour code buffer */
+	kprobe_opcode_t *insn;
+	/* the size of instructions copied to detour code buffer */
+	size_t size;
+};
+
+/* Return true (!0) if optinsn is prepared for optimization. */
+static inline int arch_prepared_optinsn(struct arch_optimized_insn *optinsn)
+{
+	return optinsn->size;
+}
+
 struct prev_kprobe {
 	struct kprobe *kp;
 	unsigned long status;
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 7c18e12..7a6f54f 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -54,13 +54,23 @@
 struct x86_emulate_ops {
 	/*
 	 * read_std: Read bytes of standard (non-emulated/special) memory.
-	 *           Used for instruction fetch, stack operations, and others.
+	 *           Used for descriptor reading.
 	 *  @addr:  [IN ] Linear address from which to read.
 	 *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
 	 *  @bytes: [IN ] Number of bytes to read from memory.
 	 */
 	int (*read_std)(unsigned long addr, void *val,
-			unsigned int bytes, struct kvm_vcpu *vcpu);
+			unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error);
+
+	/*
+	 * fetch: Read bytes of standard (non-emulated/special) memory.
+	 *        Used for instruction fetch.
+	 *  @addr:  [IN ] Linear address from which to read.
+	 *  @val:   [OUT] Value read from memory, zero-extended to 'u_long'.
+	 *  @bytes: [IN ] Number of bytes to read from memory.
+	 */
+	int (*fetch)(unsigned long addr, void *val,
+			unsigned int bytes, struct kvm_vcpu *vcpu, u32 *error);
 
 	/*
 	 * read_emulated: Read bytes from emulated/special memory area.
@@ -74,7 +84,7 @@
 			     struct kvm_vcpu *vcpu);
 
 	/*
-	 * write_emulated: Read bytes from emulated/special memory area.
+	 * write_emulated: Write bytes to emulated/special memory area.
 	 *  @addr:  [IN ] Linear address to which to write.
 	 *  @val:   [IN ] Value to write to memory (low-order bytes used as
 	 *                required).
@@ -168,6 +178,7 @@
 
 /* Execution mode, passed to the emulator. */
 #define X86EMUL_MODE_REAL     0	/* Real mode.             */
+#define X86EMUL_MODE_VM86     1	/* Virtual 8086 mode.     */
 #define X86EMUL_MODE_PROT16   2	/* 16-bit protected mode. */
 #define X86EMUL_MODE_PROT32   4	/* 32-bit protected mode. */
 #define X86EMUL_MODE_PROT64   8	/* 64-bit (long) mode.    */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 4f865e8..06d9e79 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -25,7 +25,7 @@
 #include <asm/mtrr.h>
 #include <asm/msr-index.h>
 
-#define KVM_MAX_VCPUS 16
+#define KVM_MAX_VCPUS 64
 #define KVM_MEMORY_SLOTS 32
 /* memory slots that does not exposed to userspace */
 #define KVM_PRIVATE_MEM_SLOTS 4
@@ -38,19 +38,6 @@
 #define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS |	\
 				  0xFFFFFF0000000000ULL)
 
-#define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST				\
-	(X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD)
-#define KVM_GUEST_CR0_MASK						\
-	(KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE)
-#define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST				\
-	(X86_CR0_WP | X86_CR0_NE | X86_CR0_TS | X86_CR0_MP)
-#define KVM_VM_CR0_ALWAYS_ON						\
-	(KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE)
-#define KVM_GUEST_CR4_MASK						\
-	(X86_CR4_VME | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE | X86_CR4_VMXE)
-#define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE)
-#define KVM_RMODE_VM_CR4_ALWAYS_ON (X86_CR4_VME | X86_CR4_PAE | X86_CR4_VMXE)
-
 #define INVALID_PAGE (~(hpa_t)0)
 #define UNMAPPED_GVA (~(gpa_t)0)
 
@@ -256,7 +243,8 @@
 	void (*new_cr3)(struct kvm_vcpu *vcpu);
 	int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err);
 	void (*free)(struct kvm_vcpu *vcpu);
-	gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva);
+	gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
+			    u32 *error);
 	void (*prefetch_page)(struct kvm_vcpu *vcpu,
 			      struct kvm_mmu_page *page);
 	int (*sync_page)(struct kvm_vcpu *vcpu,
@@ -282,13 +270,15 @@
 	u32 regs_dirty;
 
 	unsigned long cr0;
+	unsigned long cr0_guest_owned_bits;
 	unsigned long cr2;
 	unsigned long cr3;
 	unsigned long cr4;
+	unsigned long cr4_guest_owned_bits;
 	unsigned long cr8;
 	u32 hflags;
 	u64 pdptrs[4]; /* pae */
-	u64 shadow_efer;
+	u64 efer;
 	u64 apic_base;
 	struct kvm_lapic *apic;    /* kernel irqchip context */
 	int32_t apic_arb_prio;
@@ -374,17 +364,27 @@
 	/* used for guest single stepping over the given code position */
 	u16 singlestep_cs;
 	unsigned long singlestep_rip;
+	/* fields used by HYPER-V emulation */
+	u64 hv_vapic;
 };
 
 struct kvm_mem_alias {
 	gfn_t base_gfn;
 	unsigned long npages;
 	gfn_t target_gfn;
+#define KVM_ALIAS_INVALID     1UL
+	unsigned long flags;
 };
 
-struct kvm_arch{
-	int naliases;
+#define KVM_ARCH_HAS_UNALIAS_INSTANTIATION
+
+struct kvm_mem_aliases {
 	struct kvm_mem_alias aliases[KVM_ALIAS_SLOTS];
+	int naliases;
+};
+
+struct kvm_arch {
+	struct kvm_mem_aliases *aliases;
 
 	unsigned int n_free_mmu_pages;
 	unsigned int n_requested_mmu_pages;
@@ -416,6 +416,10 @@
 	s64 kvmclock_offset;
 
 	struct kvm_xen_hvm_config xen_hvm_config;
+
+	/* fields used by HYPER-V emulation */
+	u64 hv_guest_os_id;
+	u64 hv_hypercall;
 };
 
 struct kvm_vm_stat {
@@ -471,6 +475,7 @@
 	int (*hardware_setup)(void);               /* __init */
 	void (*hardware_unsetup)(void);            /* __exit */
 	bool (*cpu_has_accelerated_tpr)(void);
+	void (*cpuid_update)(struct kvm_vcpu *vcpu);
 
 	/* Create, but do not attach this VCPU */
 	struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm, unsigned id);
@@ -492,6 +497,7 @@
 	void (*set_segment)(struct kvm_vcpu *vcpu,
 			    struct kvm_segment *var, int seg);
 	void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);
+	void (*decache_cr0_guest_bits)(struct kvm_vcpu *vcpu);
 	void (*decache_cr4_guest_bits)(struct kvm_vcpu *vcpu);
 	void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0);
 	void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
@@ -501,12 +507,13 @@
 	void (*set_idt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
 	void (*get_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
 	void (*set_gdt)(struct kvm_vcpu *vcpu, struct descriptor_table *dt);
-	unsigned long (*get_dr)(struct kvm_vcpu *vcpu, int dr);
-	void (*set_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long value,
-		       int *exception);
+	int (*get_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long *dest);
+	int (*set_dr)(struct kvm_vcpu *vcpu, int dr, unsigned long value);
 	void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg);
 	unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
 	void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
+	void (*fpu_activate)(struct kvm_vcpu *vcpu);
+	void (*fpu_deactivate)(struct kvm_vcpu *vcpu);
 
 	void (*tlb_flush)(struct kvm_vcpu *vcpu);
 
@@ -531,7 +538,8 @@
 	int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
 	int (*get_tdp_level)(void);
 	u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio);
-	bool (*gb_page_enable)(void);
+	int (*get_lpage_level)(void);
+	bool (*rdtscp_supported)(void);
 
 	const struct trace_print_flags *exit_reasons_str;
 };
@@ -606,8 +614,7 @@
 		    unsigned long value);
 
 void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
-int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
-				int type_bits, int seg);
+int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg);
 
 int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason);
 
@@ -653,6 +660,10 @@
 int kvm_mmu_load(struct kvm_vcpu *vcpu);
 void kvm_mmu_unload(struct kvm_vcpu *vcpu);
 void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
+gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
+gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
+gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
+gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva, u32 *error);
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
@@ -666,6 +677,7 @@
 
 int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
 int complete_pio(struct kvm_vcpu *vcpu);
+bool kvm_check_iopl(struct kvm_vcpu *vcpu);
 
 struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn);
 
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index c584076..ffae142 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -2,6 +2,7 @@
 #define _ASM_X86_KVM_PARA_H
 
 #include <linux/types.h>
+#include <asm/hyperv.h>
 
 /* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx.  It
  * should be used to determine that a VM is running under KVM.
diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h
index 47b9b6f..2e99724 100644
--- a/arch/x86/include/asm/local.h
+++ b/arch/x86/include/asm/local.h
@@ -195,41 +195,4 @@
 #define __local_add(i, l)	local_add((i), (l))
 #define __local_sub(i, l)	local_sub((i), (l))
 
-/* Use these for per-cpu local_t variables: on some archs they are
- * much more efficient than these naive implementations.  Note they take
- * a variable, not an address.
- *
- * X86_64: This could be done better if we moved the per cpu data directly
- * after GS.
- */
-
-/* Need to disable preemption for the cpu local counters otherwise we could
-   still access a variable of a previous CPU in a non atomic way. */
-#define cpu_local_wrap_v(l)		\
-({					\
-	local_t res__;			\
-	preempt_disable(); 		\
-	res__ = (l);			\
-	preempt_enable();		\
-	res__;				\
-})
-#define cpu_local_wrap(l)		\
-({					\
-	preempt_disable();		\
-	(l);				\
-	preempt_enable();		\
-})					\
-
-#define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var((l))))
-#define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var((l)), (i)))
-#define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var((l))))
-#define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var((l))))
-#define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var((l))))
-#define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var((l))))
-
-#define __cpu_local_inc(l)	cpu_local_inc((l))
-#define __cpu_local_dec(l)	cpu_local_dec((l))
-#define __cpu_local_add(i, l)	cpu_local_add((i), (l))
-#define __cpu_local_sub(i, l)	cpu_local_sub((i), (l))
-
 #endif /* _ASM_X86_LOCAL_H */
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
new file mode 100644
index 0000000..451d30e
--- /dev/null
+++ b/arch/x86/include/asm/mrst.h
@@ -0,0 +1,19 @@
+/*
+ * mrst.h: Intel Moorestown platform specific setup code
+ *
+ * (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.
+ */
+#ifndef _ASM_X86_MRST_H
+#define _ASM_X86_MRST_H
+extern int pci_mrst_init(void);
+int __init sfi_parse_mrtc(struct sfi_table_header *table);
+
+#define SFI_MTMR_MAX_NUM 8
+#define SFI_MRTC_MAX	8
+
+#endif /* _ASM_X86_MRST_H */
diff --git a/arch/x86/include/asm/numaq.h b/arch/x86/include/asm/numaq.h
index 13370b9..37c5165 100644
--- a/arch/x86/include/asm/numaq.h
+++ b/arch/x86/include/asm/numaq.h
@@ -30,6 +30,7 @@
 
 extern int found_numaq;
 extern int get_memcfg_numaq(void);
+extern int pci_numaq_init(void);
 
 extern void *xquad_portio;
 
diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h
index 3a57385..101229b 100644
--- a/arch/x86/include/asm/olpc.h
+++ b/arch/x86/include/asm/olpc.h
@@ -13,7 +13,6 @@
 
 #define OLPC_F_PRESENT		0x01
 #define OLPC_F_DCON		0x02
-#define OLPC_F_VSA		0x04
 
 #ifdef CONFIG_OLPC
 
@@ -51,18 +50,6 @@
 }
 
 /*
- * The VSA is software from AMD that typical Geode bioses will include.
- * It is used to emulate the PCI bus, VGA, etc.  OLPC's Open Firmware does
- * not include the VSA; instead, PCI is emulated by the kernel.
- *
- * The VSA is described further in arch/x86/pci/olpc.c.
- */
-static inline int olpc_has_vsa(void)
-{
-	return (olpc_platform_info.flags & OLPC_F_VSA) ? 1 : 0;
-}
-
-/*
  * The "Mass Production" version of OLPC's XO is identified as being model
  * C2.  During the prototype phase, the following models (in chronological
  * order) were created: A1, B1, B2, B3, B4, C1.  The A1 through B2 models
@@ -87,13 +74,10 @@
 	return 0;
 }
 
-static inline int olpc_has_vsa(void)
-{
-	return 0;
-}
-
 #endif
 
+extern int pci_olpc_init(void);
+
 /* EC related functions */
 
 extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index dd59a85..5653f43 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -435,15 +435,6 @@
 	PVOP_VCALL1(pv_mmu_ops.release_pud, pfn);
 }
 
-#ifdef CONFIG_HIGHPTE
-static inline void *kmap_atomic_pte(struct page *page, enum km_type type)
-{
-	unsigned long ret;
-	ret = PVOP_CALL2(unsigned long, pv_mmu_ops.kmap_atomic_pte, page, type);
-	return (void *)ret;
-}
-#endif
-
 static inline void pte_update(struct mm_struct *mm, unsigned long addr,
 			      pte_t *ptep)
 {
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index b1e70d5..db9ef55 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -304,10 +304,6 @@
 #endif	/* PAGETABLE_LEVELS == 4 */
 #endif	/* PAGETABLE_LEVELS >= 3 */
 
-#ifdef CONFIG_HIGHPTE
-	void *(*kmap_atomic_pte)(struct page *page, enum km_type type);
-#endif
-
 	struct pv_lazy_ops lazy_mode;
 
 	/* dom0 ops */
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index ada8c20..404a880 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -45,8 +45,15 @@
 
 #ifdef CONFIG_PCI
 extern unsigned int pcibios_assign_all_busses(void);
+extern int pci_legacy_init(void);
+# ifdef CONFIG_ACPI
+#  define x86_default_pci_init pci_acpi_init
+# else
+#  define x86_default_pci_init pci_legacy_init
+# endif
 #else
-#define pcibios_assign_all_busses()	0
+# define pcibios_assign_all_busses()	0
+# define x86_default_pci_init		NULL
 #endif
 
 extern unsigned long pci_mem_start;
@@ -90,40 +97,14 @@
 
 #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
 
-#if defined(CONFIG_X86_64) || defined(CONFIG_DMAR) || defined(CONFIG_DMA_API_DEBUG)
-
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)       \
-	        dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)         \
-	        __u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)                  \
-	        ((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)         \
-	        (((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)                    \
-	        ((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)           \
-	        (((PTR)->LEN_NAME) = (VAL))
-
-#else
-
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)       dma_addr_t ADDR_NAME[0];
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) unsigned LEN_NAME[0];
-#define pci_unmap_addr(PTR, ADDR_NAME)  sizeof((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \
-	        do { break; } while (pci_unmap_addr(PTR, ADDR_NAME))
-#define pci_unmap_len(PTR, LEN_NAME)            sizeof((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
-	        do { break; } while (pci_unmap_len(PTR, LEN_NAME))
-
-#endif
-
 #endif  /* __KERNEL__ */
 
 #ifdef CONFIG_X86_64
 #include "pci_64.h"
 #endif
 
+void dma32_reserve_bootmem(void);
+
 /* implement the pci_ DMA API in terms of the generic device dma_ one */
 #include <asm-generic/pci-dma-compat.h>
 
diff --git a/arch/x86/include/asm/pci_64.h b/arch/x86/include/asm/pci_64.h
index ae5e40f..fe15cfb 100644
--- a/arch/x86/include/asm/pci_64.h
+++ b/arch/x86/include/asm/pci_64.h
@@ -22,8 +22,6 @@
 extern int (*pci_config_write)(int seg, int bus, int dev, int fn,
 			       int reg, int len, u32 value);
 
-extern void dma32_reserve_bootmem(void);
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_X86_PCI_64_H */
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index 05b58cc..1a04223 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -83,7 +83,6 @@
 
 extern unsigned int pcibios_irq_mask;
 
-extern int pcibios_scanned;
 extern spinlock_t pci_config_lock;
 
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
@@ -106,16 +105,15 @@
 extern int pci_direct_probe(void);
 extern void pci_direct_init(int type);
 extern void pci_pcbios_init(void);
-extern int pci_olpc_init(void);
 extern void __init dmi_check_pciprobe(void);
 extern void __init dmi_check_skip_isa_align(void);
 
 /* some common used subsys_initcalls */
 extern int __init pci_acpi_init(void);
-extern int __init pcibios_irq_init(void);
-extern int __init pci_visws_init(void);
-extern int __init pci_numaq_init(void);
+extern void __init pcibios_irq_init(void);
 extern int __init pcibios_init(void);
+extern int pci_legacy_init(void);
+extern void pcibios_fixup_irqs(void);
 
 /* pci-mmconfig.c */
 
@@ -183,3 +181,17 @@
 {
 	asm volatile("movl %%eax,(%1)" : : "a" (val), "r" (pos) : "memory");
 }
+
+#ifdef CONFIG_PCI
+# ifdef CONFIG_ACPI
+#  define x86_default_pci_init		pci_acpi_init
+# else
+#  define x86_default_pci_init		pci_legacy_init
+# endif
+# define x86_default_pci_init_irq	pcibios_irq_init
+# define x86_default_pci_fixup_irqs	pcibios_fixup_irqs
+#else
+# define x86_default_pci_init		NULL
+# define x86_default_pci_init_irq	NULL
+# define x86_default_pci_fixup_irqs	NULL
+#endif
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 0c44196..66a272d 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -25,19 +25,18 @@
  */
 #ifdef CONFIG_SMP
 #define PER_CPU(var, reg)						\
-	__percpu_mov_op %__percpu_seg:per_cpu__this_cpu_off, reg;	\
-	lea per_cpu__##var(reg), reg
-#define PER_CPU_VAR(var)	%__percpu_seg:per_cpu__##var
+	__percpu_mov_op %__percpu_seg:this_cpu_off, reg;		\
+	lea var(reg), reg
+#define PER_CPU_VAR(var)	%__percpu_seg:var
 #else /* ! SMP */
-#define PER_CPU(var, reg)						\
-	__percpu_mov_op $per_cpu__##var, reg
-#define PER_CPU_VAR(var)	per_cpu__##var
+#define PER_CPU(var, reg)	__percpu_mov_op $var, reg
+#define PER_CPU_VAR(var)	var
 #endif	/* SMP */
 
 #ifdef CONFIG_X86_64_SMP
 #define INIT_PER_CPU_VAR(var)  init_per_cpu__##var
 #else
-#define INIT_PER_CPU_VAR(var)  per_cpu__##var
+#define INIT_PER_CPU_VAR(var)  var
 #endif
 
 #else /* ...!ASSEMBLY */
@@ -60,12 +59,12 @@
  * There also must be an entry in vmlinux_64.lds.S
  */
 #define DECLARE_INIT_PER_CPU(var) \
-       extern typeof(per_cpu_var(var)) init_per_cpu_var(var)
+       extern typeof(var) init_per_cpu_var(var)
 
 #ifdef CONFIG_X86_64_SMP
 #define init_per_cpu_var(var)  init_per_cpu__##var
 #else
-#define init_per_cpu_var(var)  per_cpu_var(var)
+#define init_per_cpu_var(var)  var
 #endif
 
 /* For arch-specific code, we can use direct single-insn ops (they
@@ -104,6 +103,64 @@
 	}						\
 } while (0)
 
+/*
+ * Generate a percpu add to memory instruction and optimize code
+ * if a one is added or subtracted.
+ */
+#define percpu_add_op(var, val)						\
+do {									\
+	typedef typeof(var) pao_T__;					\
+	const int pao_ID__ = (__builtin_constant_p(val) &&		\
+			      ((val) == 1 || (val) == -1)) ? (val) : 0;	\
+	if (0) {							\
+		pao_T__ pao_tmp__;					\
+		pao_tmp__ = (val);					\
+	}								\
+	switch (sizeof(var)) {						\
+	case 1:								\
+		if (pao_ID__ == 1)					\
+			asm("incb "__percpu_arg(0) : "+m" (var));	\
+		else if (pao_ID__ == -1)				\
+			asm("decb "__percpu_arg(0) : "+m" (var));	\
+		else							\
+			asm("addb %1, "__percpu_arg(0)			\
+			    : "+m" (var)				\
+			    : "qi" ((pao_T__)(val)));			\
+		break;							\
+	case 2:								\
+		if (pao_ID__ == 1)					\
+			asm("incw "__percpu_arg(0) : "+m" (var));	\
+		else if (pao_ID__ == -1)				\
+			asm("decw "__percpu_arg(0) : "+m" (var));	\
+		else							\
+			asm("addw %1, "__percpu_arg(0)			\
+			    : "+m" (var)				\
+			    : "ri" ((pao_T__)(val)));			\
+		break;							\
+	case 4:								\
+		if (pao_ID__ == 1)					\
+			asm("incl "__percpu_arg(0) : "+m" (var));	\
+		else if (pao_ID__ == -1)				\
+			asm("decl "__percpu_arg(0) : "+m" (var));	\
+		else							\
+			asm("addl %1, "__percpu_arg(0)			\
+			    : "+m" (var)				\
+			    : "ri" ((pao_T__)(val)));			\
+		break;							\
+	case 8:								\
+		if (pao_ID__ == 1)					\
+			asm("incq "__percpu_arg(0) : "+m" (var));	\
+		else if (pao_ID__ == -1)				\
+			asm("decq "__percpu_arg(0) : "+m" (var));	\
+		else							\
+			asm("addq %1, "__percpu_arg(0)			\
+			    : "+m" (var)				\
+			    : "re" ((pao_T__)(val)));			\
+		break;							\
+	default: __bad_percpu_size();					\
+	}								\
+} while (0)
+
 #define percpu_from_op(op, var, constraint)		\
 ({							\
 	typeof(var) pfo_ret__;				\
@@ -142,16 +199,14 @@
  * per-thread variables implemented as per-cpu variables and thus
  * stable for the duration of the respective task.
  */
-#define percpu_read(var)	percpu_from_op("mov", per_cpu__##var,	\
-					       "m" (per_cpu__##var))
-#define percpu_read_stable(var)	percpu_from_op("mov", per_cpu__##var,	\
-					       "p" (&per_cpu__##var))
-#define percpu_write(var, val)	percpu_to_op("mov", per_cpu__##var, val)
-#define percpu_add(var, val)	percpu_to_op("add", per_cpu__##var, val)
-#define percpu_sub(var, val)	percpu_to_op("sub", per_cpu__##var, val)
-#define percpu_and(var, val)	percpu_to_op("and", per_cpu__##var, val)
-#define percpu_or(var, val)	percpu_to_op("or", per_cpu__##var, val)
-#define percpu_xor(var, val)	percpu_to_op("xor", per_cpu__##var, val)
+#define percpu_read(var)		percpu_from_op("mov", var, "m" (var))
+#define percpu_read_stable(var)		percpu_from_op("mov", var, "p" (&(var)))
+#define percpu_write(var, val)		percpu_to_op("mov", var, val)
+#define percpu_add(var, val)		percpu_add_op(var, val)
+#define percpu_sub(var, val)		percpu_add_op(var, -(val))
+#define percpu_and(var, val)		percpu_to_op("and", var, val)
+#define percpu_or(var, val)		percpu_to_op("or", var, val)
+#define percpu_xor(var, val)		percpu_to_op("xor", var, val)
 
 #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))
@@ -160,9 +215,9 @@
 #define __this_cpu_write_1(pcp, val)	percpu_to_op("mov", (pcp), val)
 #define __this_cpu_write_2(pcp, val)	percpu_to_op("mov", (pcp), val)
 #define __this_cpu_write_4(pcp, val)	percpu_to_op("mov", (pcp), val)
-#define __this_cpu_add_1(pcp, val)	percpu_to_op("add", (pcp), val)
-#define __this_cpu_add_2(pcp, val)	percpu_to_op("add", (pcp), val)
-#define __this_cpu_add_4(pcp, val)	percpu_to_op("add", (pcp), val)
+#define __this_cpu_add_1(pcp, val)	percpu_add_op((pcp), val)
+#define __this_cpu_add_2(pcp, val)	percpu_add_op((pcp), val)
+#define __this_cpu_add_4(pcp, val)	percpu_add_op((pcp), val)
 #define __this_cpu_and_1(pcp, val)	percpu_to_op("and", (pcp), val)
 #define __this_cpu_and_2(pcp, val)	percpu_to_op("and", (pcp), val)
 #define __this_cpu_and_4(pcp, val)	percpu_to_op("and", (pcp), val)
@@ -179,9 +234,9 @@
 #define this_cpu_write_1(pcp, val)	percpu_to_op("mov", (pcp), val)
 #define this_cpu_write_2(pcp, val)	percpu_to_op("mov", (pcp), val)
 #define this_cpu_write_4(pcp, val)	percpu_to_op("mov", (pcp), val)
-#define this_cpu_add_1(pcp, val)	percpu_to_op("add", (pcp), val)
-#define this_cpu_add_2(pcp, val)	percpu_to_op("add", (pcp), val)
-#define this_cpu_add_4(pcp, val)	percpu_to_op("add", (pcp), val)
+#define this_cpu_add_1(pcp, val)	percpu_add_op((pcp), val)
+#define this_cpu_add_2(pcp, val)	percpu_add_op((pcp), val)
+#define this_cpu_add_4(pcp, val)	percpu_add_op((pcp), val)
 #define this_cpu_and_1(pcp, val)	percpu_to_op("and", (pcp), val)
 #define this_cpu_and_2(pcp, val)	percpu_to_op("and", (pcp), val)
 #define this_cpu_and_4(pcp, val)	percpu_to_op("and", (pcp), val)
@@ -192,9 +247,9 @@
 #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 irqsafe_cpu_add_1(pcp, val)	percpu_to_op("add", (pcp), val)
-#define irqsafe_cpu_add_2(pcp, val)	percpu_to_op("add", (pcp), val)
-#define irqsafe_cpu_add_4(pcp, val)	percpu_to_op("add", (pcp), val)
+#define irqsafe_cpu_add_1(pcp, val)	percpu_add_op((pcp), val)
+#define irqsafe_cpu_add_2(pcp, val)	percpu_add_op((pcp), val)
+#define irqsafe_cpu_add_4(pcp, val)	percpu_add_op((pcp), val)
 #define irqsafe_cpu_and_1(pcp, val)	percpu_to_op("and", (pcp), val)
 #define irqsafe_cpu_and_2(pcp, val)	percpu_to_op("and", (pcp), val)
 #define irqsafe_cpu_and_4(pcp, val)	percpu_to_op("and", (pcp), val)
@@ -212,19 +267,19 @@
 #ifdef CONFIG_X86_64
 #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)
-#define __this_cpu_add_8(pcp, val)	percpu_to_op("add", (pcp), val)
+#define __this_cpu_add_8(pcp, val)	percpu_add_op((pcp), val)
 #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_read_8(pcp)		percpu_from_op("mov", (pcp), "m"(pcp))
 #define this_cpu_write_8(pcp, val)	percpu_to_op("mov", (pcp), val)
-#define this_cpu_add_8(pcp, val)	percpu_to_op("add", (pcp), val)
+#define this_cpu_add_8(pcp, val)	percpu_add_op((pcp), val)
 #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 irqsafe_cpu_add_8(pcp, val)	percpu_to_op("add", (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)
@@ -236,7 +291,7 @@
 ({									\
 	int old__;							\
 	asm volatile("btr %2,"__percpu_arg(1)"\n\tsbbl %0,%0"		\
-		     : "=r" (old__), "+m" (per_cpu__##var)		\
+		     : "=r" (old__), "+m" (var)				\
 		     : "dIr" (bit));					\
 	old__;								\
 })
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index befd172..db6109a 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -18,7 +18,7 @@
 #define MSR_ARCH_PERFMON_EVENTSEL0			     0x186
 #define MSR_ARCH_PERFMON_EVENTSEL1			     0x187
 
-#define ARCH_PERFMON_EVENTSEL0_ENABLE			  (1 << 22)
+#define ARCH_PERFMON_EVENTSEL_ENABLE			  (1 << 22)
 #define ARCH_PERFMON_EVENTSEL_ANY			  (1 << 21)
 #define ARCH_PERFMON_EVENTSEL_INT			  (1 << 20)
 #define ARCH_PERFMON_EVENTSEL_OS			  (1 << 17)
@@ -50,7 +50,7 @@
 	 INTEL_ARCH_INV_MASK| \
 	 INTEL_ARCH_EDGE_MASK|\
 	 INTEL_ARCH_UNIT_MASK|\
-	 INTEL_ARCH_EVTSEL_MASK)
+	 INTEL_ARCH_EVENT_MASK)
 
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL		      0x3c
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK		(0x00 << 8)
@@ -117,6 +117,18 @@
  */
 #define X86_PMC_IDX_FIXED_BTS				(X86_PMC_IDX_FIXED + 16)
 
+/* IbsFetchCtl bits/masks */
+#define IBS_FETCH_RAND_EN		(1ULL<<57)
+#define IBS_FETCH_VAL			(1ULL<<49)
+#define IBS_FETCH_ENABLE		(1ULL<<48)
+#define IBS_FETCH_CNT			0xFFFF0000ULL
+#define IBS_FETCH_MAX_CNT		0x0000FFFFULL
+
+/* IbsOpCtl bits */
+#define IBS_OP_CNT_CTL			(1ULL<<19)
+#define IBS_OP_VAL			(1ULL<<18)
+#define IBS_OP_ENABLE			(1ULL<<17)
+#define IBS_OP_MAX_CNT			0x0000FFFFULL
 
 #ifdef CONFIG_PERF_EVENTS
 extern void init_hw_perf_events(void);
diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h
index a286683..47339a1 100644
--- a/arch/x86/include/asm/pgtable_32.h
+++ b/arch/x86/include/asm/pgtable_32.h
@@ -54,10 +54,10 @@
 	 in_irq() ? KM_IRQ_PTE :	\
 	 KM_PTE0)
 #define pte_offset_map(dir, address)					\
-	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), __KM_PTE) +		\
+	((pte_t *)kmap_atomic(pmd_page(*(dir)), __KM_PTE) +		\
 	 pte_index((address)))
 #define pte_offset_map_nested(dir, address)				\
-	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE1) +		\
+	((pte_t *)kmap_atomic(pmd_page(*(dir)), KM_PTE1) +		\
 	 pte_index((address)))
 #define pte_unmap(pte) kunmap_atomic((pte), __KM_PTE)
 #define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h
index 4009f65..6f414ed 100644
--- a/arch/x86/include/asm/proto.h
+++ b/arch/x86/include/asm/proto.h
@@ -23,14 +23,4 @@
 
 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
 
-/*
- * This looks more complex than it should be. But we need to
- * get the type for the ~ right in round_down (it needs to be
- * as wide as the result!), and we want to evaluate the macro
- * arguments just once each.
- */
-#define __round_mask(x,y) ((__typeof__(x))((y)-1))
-#define round_up(x,y) ((((x)-1) | __round_mask(x,y))+1)
-#define round_down(x,y) ((x) & ~__round_mask(x,y))
-
 #endif /* _ASM_X86_PROTO_H */
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index 2010280..69a686a 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -274,14 +274,7 @@
 		return 0;
 }
 
-/*
- * These are defined as per linux/ptrace.h, which see.
- */
 #define arch_has_single_step()	(1)
-extern void user_enable_single_step(struct task_struct *);
-extern void user_disable_single_step(struct task_struct *);
-
-extern void user_enable_block_step(struct task_struct *);
 #ifdef CONFIG_X86_DEBUGCTLMSR
 #define arch_has_block_step()	(1)
 #else
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index 18e496c..86b1506 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -37,10 +37,8 @@
 
 #ifdef CONFIG_X86_VISWS
 extern void visws_early_detect(void);
-extern int is_visws_box(void);
 #else
 static inline void visws_early_detect(void) { }
-static inline int is_visws_box(void) { return 0; }
 #endif
 
 extern unsigned long saved_video_mode;
diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
index 1fecb7e..38638cd 100644
--- a/arch/x86/include/asm/svm.h
+++ b/arch/x86/include/asm/svm.h
@@ -313,7 +313,7 @@
 
 #define SVM_EXIT_ERR		-1
 
-#define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) /* TS and MP */
+#define SVM_CR0_SELECTIVE_MASK (X86_CR0_TS | X86_CR0_MP)
 
 #define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda"
 #define SVM_VMRUN  ".byte 0x0f, 0x01, 0xd8"
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index d5f6904..3ad4217 100644
--- a/arch/x86/include/asm/sys_ia32.h
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -26,8 +26,8 @@
 asmlinkage long sys32_fstat64(unsigned int, struct stat64 __user *);
 asmlinkage long sys32_fstatat(unsigned int, char __user *,
 			      struct stat64 __user *, int);
-struct mmap_arg_struct;
-asmlinkage long sys32_mmap(struct mmap_arg_struct __user *);
+struct mmap_arg_struct32;
+asmlinkage long sys32_mmap(struct mmap_arg_struct32 __user *);
 asmlinkage long sys32_mprotect(unsigned long, size_t, unsigned long);
 
 struct sigaction32;
@@ -40,8 +40,6 @@
 				     compat_sigset_t __user *, unsigned int);
 asmlinkage long sys32_alarm(unsigned int);
 
-struct sel_arg_struct;
-asmlinkage long sys32_old_select(struct sel_arg_struct __user *);
 asmlinkage long sys32_waitpid(compat_pid_t, unsigned int *, int);
 asmlinkage long sys32_sysfs(int, u32, u32);
 
@@ -56,11 +54,6 @@
 asmlinkage long sys32_personality(unsigned long);
 asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
 
-struct oldold_utsname;
-struct old_utsname;
-asmlinkage long sys32_olduname(struct oldold_utsname __user *);
-long sys32_uname(struct old_utsname __user *);
-
 asmlinkage long sys32_execve(char __user *, compat_uptr_t __user *,
 			     compat_uptr_t __user *, struct pt_regs *);
 asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index 8868b94..5c044b4 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -50,18 +50,6 @@
 			     struct old_sigaction __user *);
 unsigned long sys_sigreturn(struct pt_regs *);
 
-/* kernel/sys_i386_32.c */
-struct mmap_arg_struct;
-struct sel_arg_struct;
-struct oldold_utsname;
-struct old_utsname;
-
-asmlinkage int old_mmap(struct mmap_arg_struct __user *);
-asmlinkage int old_select(struct sel_arg_struct __user *);
-asmlinkage int sys_ipc(uint, int, int, int, void __user *, long);
-asmlinkage int sys_uname(struct old_utsname __user *);
-asmlinkage int sys_olduname(struct oldold_utsname __user *);
-
 /* kernel/vm86_32.c */
 int sys_vm86old(struct vm86_struct __user *, struct pt_regs *);
 int sys_vm86(unsigned long, unsigned long, struct pt_regs *);
@@ -73,11 +61,8 @@
 long sys_arch_prctl(int, unsigned long);
 
 /* kernel/sys_x86_64.c */
-struct new_utsname;
-
 asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long,
 			 unsigned long, unsigned long, unsigned long);
-asmlinkage long sys_uname(struct new_utsname __user *);
 
 #endif /* CONFIG_X86_32 */
 #endif /* _ASM_X86_SYSCALLS_H */
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
index e04740f..b8fe48e 100644
--- a/arch/x86/include/asm/system.h
+++ b/arch/x86/include/asm/system.h
@@ -32,7 +32,7 @@
 	"movl %P[task_canary](%[next]), %%ebx\n\t"			\
 	"movl %%ebx, "__percpu_arg([stack_canary])"\n\t"
 #define __switch_canary_oparam						\
-	, [stack_canary] "=m" (per_cpu_var(stack_canary.canary))
+	, [stack_canary] "=m" (stack_canary.canary)
 #define __switch_canary_iparam						\
 	, [task_canary] "i" (offsetof(struct task_struct, stack_canary))
 #else	/* CC_STACKPROTECTOR */
@@ -114,7 +114,7 @@
 	"movq %P[task_canary](%%rsi),%%r8\n\t"				  \
 	"movq %%r8,"__percpu_arg([gs_canary])"\n\t"
 #define __switch_canary_oparam						  \
-	, [gs_canary] "=m" (per_cpu_var(irq_stack_union.stack_canary))
+	, [gs_canary] "=m" (irq_stack_union.stack_canary)
 #define __switch_canary_iparam						  \
 	, [task_canary] "i" (offsetof(struct task_struct, stack_canary))
 #else	/* CC_STACKPROTECTOR */
@@ -133,7 +133,7 @@
 	     __switch_canary						  \
 	     "movq %P[thread_info](%%rsi),%%r8\n\t"			  \
 	     "movq %%rax,%%rdi\n\t" 					  \
-	     "testl  %[_tif_fork],%P[ti_flags](%%r8)\n\t"	  \
+	     "testl  %[_tif_fork],%P[ti_flags](%%r8)\n\t"		  \
 	     "jnz   ret_from_fork\n\t"					  \
 	     RESTORE_CONTEXT						  \
 	     : "=a" (last)					  	  \
@@ -143,7 +143,7 @@
 	       [ti_flags] "i" (offsetof(struct thread_info, flags)),	  \
 	       [_tif_fork] "i" (_TIF_FORK),			  	  \
 	       [thread_info] "i" (offsetof(struct task_struct, stack)),   \
-	       [current_task] "m" (per_cpu_var(current_task))		  \
+	       [current_task] "m" (current_task)			  \
 	       __switch_canary_iparam					  \
 	     : "memory", "cc" __EXTRA_CLOBBER)
 #endif
diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
index 3baf379..beb9b5f 100644
--- a/arch/x86/include/asm/unistd_32.h
+++ b/arch/x86/include/asm/unistd_32.h
@@ -354,6 +354,7 @@
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_IPC
 #define __ARCH_WANT_SYS_PAUSE
 #define __ARCH_WANT_SYS_SGETMASK
 #define __ARCH_WANT_SYS_SIGNAL
@@ -366,6 +367,9 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_UNAME
+#define __ARCH_WANT_SYS_OLD_MMAP
+#define __ARCH_WANT_SYS_OLD_SELECT
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
index 4843f7b..ff4307b 100644
--- a/arch/x86/include/asm/unistd_64.h
+++ b/arch/x86/include/asm/unistd_64.h
@@ -146,7 +146,7 @@
 #define __NR_kill				62
 __SYSCALL(__NR_kill, sys_kill)
 #define __NR_uname				63
-__SYSCALL(__NR_uname, sys_uname)
+__SYSCALL(__NR_uname, sys_newuname)
 
 #define __NR_semget				64
 __SYSCALL(__NR_semget, sys_semget)
@@ -680,6 +680,7 @@
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_NICE
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLD_UNAME
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
diff --git a/arch/x86/include/asm/visws/cobalt.h b/arch/x86/include/asm/visws/cobalt.h
index 166adf6..2edb376 100644
--- a/arch/x86/include/asm/visws/cobalt.h
+++ b/arch/x86/include/asm/visws/cobalt.h
@@ -122,4 +122,6 @@
 
 extern char visws_board_rev;
 
+extern int pci_visws_init(void);
+
 #endif /* _ASM_X86_VISWS_COBALT_H */
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 2b49454..fb9a080 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -53,6 +53,7 @@
  */
 #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
 #define SECONDARY_EXEC_ENABLE_EPT               0x00000002
+#define SECONDARY_EXEC_RDTSCP			0x00000008
 #define SECONDARY_EXEC_ENABLE_VPID              0x00000020
 #define SECONDARY_EXEC_WBINVD_EXITING		0x00000040
 #define SECONDARY_EXEC_UNRESTRICTED_GUEST	0x00000080
@@ -251,6 +252,7 @@
 #define EXIT_REASON_MSR_READ            31
 #define EXIT_REASON_MSR_WRITE           32
 #define EXIT_REASON_MWAIT_INSTRUCTION   36
+#define EXIT_REASON_MONITOR_INSTRUCTION 39
 #define EXIT_REASON_PAUSE_INSTRUCTION   40
 #define EXIT_REASON_MCE_DURING_VMENTRY	 41
 #define EXIT_REASON_TPR_BELOW_THRESHOLD 43
@@ -362,6 +364,7 @@
 #define VMX_EPTP_UC_BIT				(1ull << 8)
 #define VMX_EPTP_WB_BIT				(1ull << 14)
 #define VMX_EPT_2MB_PAGE_BIT			(1ull << 16)
+#define VMX_EPT_1GB_PAGE_BIT			(1ull << 17)
 #define VMX_EPT_EXTENT_INDIVIDUAL_BIT		(1ull << 24)
 #define VMX_EPT_EXTENT_CONTEXT_BIT		(1ull << 25)
 #define VMX_EPT_EXTENT_GLOBAL_BIT		(1ull << 26)
@@ -374,7 +377,7 @@
 #define VMX_EPT_READABLE_MASK			0x1ull
 #define VMX_EPT_WRITABLE_MASK			0x2ull
 #define VMX_EPT_EXECUTABLE_MASK			0x4ull
-#define VMX_EPT_IGMT_BIT    			(1ull << 6)
+#define VMX_EPT_IPAT_BIT    			(1ull << 6)
 
 #define VMX_EPT_IDENTITY_PAGETABLE_ADDR		0xfffbc000ul
 
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 60cc352..519b543 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -99,6 +99,20 @@
 };
 
 /**
+ * struct x86_init_pci - platform specific pci init functions
+ * @arch_init:			platform specific pci arch init call
+ * @init:			platform specific pci subsystem init
+ * @init_irq:			platform specific pci irq init
+ * @fixup_irqs:			platform specific pci irq fixup
+ */
+struct x86_init_pci {
+	int (*arch_init)(void);
+	int (*init)(void);
+	void (*init_irq)(void);
+	void (*fixup_irqs)(void);
+};
+
+/**
  * struct x86_init_ops - functions for platform specific setup
  *
  */
@@ -110,6 +124,7 @@
 	struct x86_init_paging		paging;
 	struct x86_init_timers		timers;
 	struct x86_init_iommu		iommu;
+	struct x86_init_pci		pci;
 };
 
 /**
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index d87f09b..4c58352 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -87,6 +87,7 @@
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 
 obj-$(CONFIG_HPET_TIMER) 	+= hpet.o
+obj-$(CONFIG_APB_TIMER)		+= apb_timer.o
 
 obj-$(CONFIG_K8_NB)		+= k8.o
 obj-$(CONFIG_DEBUG_RODATA_TEST)	+= test_rodata.o
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index f957030..a54d714 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -35,6 +35,7 @@
 #include <linux/ioport.h>
 #include <linux/pci.h>
 
+#include <asm/pci_x86.h>
 #include <asm/pgtable.h>
 #include <asm/io_apic.h>
 #include <asm/apic.h>
@@ -447,6 +448,12 @@
 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
 {
 	*irq = gsi;
+
+#ifdef CONFIG_X86_IO_APIC
+	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
+		setup_IO_APIC_irq_extra(gsi);
+#endif
+
 	return 0;
 }
 
@@ -474,7 +481,8 @@
 		plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);
 	}
 #endif
-	acpi_gsi_to_irq(plat_gsi, &irq);
+	irq = plat_gsi;
+
 	return irq;
 }
 
@@ -1617,6 +1625,9 @@
 
 	acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet);
 
+	if (!acpi_noirq)
+		x86_init.pci.init = pci_acpi_init;
+
 	return 0;
 }
 
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index e6ea034..3a4bf35 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -7,6 +7,7 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/memory.h>
+#include <linux/stop_machine.h>
 #include <asm/alternative.h>
 #include <asm/sections.h>
 #include <asm/pgtable.h>
@@ -572,3 +573,62 @@
 	local_irq_restore(flags);
 	return addr;
 }
+
+/*
+ * Cross-modifying kernel text with stop_machine().
+ * This code originally comes from immediate value.
+ */
+static atomic_t stop_machine_first;
+static int wrote_text;
+
+struct text_poke_params {
+	void *addr;
+	const void *opcode;
+	size_t len;
+};
+
+static int __kprobes stop_machine_text_poke(void *data)
+{
+	struct text_poke_params *tpp = data;
+
+	if (atomic_dec_and_test(&stop_machine_first)) {
+		text_poke(tpp->addr, tpp->opcode, tpp->len);
+		smp_wmb();	/* Make sure other cpus see that this has run */
+		wrote_text = 1;
+	} else {
+		while (!wrote_text)
+			cpu_relax();
+		smp_mb();	/* Load wrote_text before following execution */
+	}
+
+	flush_icache_range((unsigned long)tpp->addr,
+			   (unsigned long)tpp->addr + tpp->len);
+	return 0;
+}
+
+/**
+ * text_poke_smp - Update instructions on a live kernel on SMP
+ * @addr: address to modify
+ * @opcode: source of the copy
+ * @len: length to copy
+ *
+ * Modify multi-byte instruction by using stop_machine() on SMP. This allows
+ * user to poke/set multi-byte text on SMP. Only non-NMI/MCE code modifying
+ * should be allowed, since stop_machine() does _not_ protect code against
+ * NMI and MCE.
+ *
+ * Note: Must be called under get_online_cpus() and text_mutex.
+ */
+void *__kprobes text_poke_smp(void *addr, const void *opcode, size_t len)
+{
+	struct text_poke_params tpp;
+
+	tpp.addr = addr;
+	tpp.opcode = opcode;
+	tpp.len = len;
+	atomic_set(&stop_machine_first, 1);
+	wrote_text = 0;
+	stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
+	return addr;
+}
+
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
new file mode 100644
index 0000000..4b70995
--- /dev/null
+++ b/arch/x86/kernel/apb_timer.c
@@ -0,0 +1,784 @@
+/*
+ * apb_timer.c: Driver for Langwell APB timers
+ *
+ * (C) Copyright 2009 Intel Corporation
+ * Author: Jacob Pan (jacob.jun.pan@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:
+ * Langwell is the south complex of Intel Moorestown MID platform. There are
+ * eight external timers in total that can be used by the operating system.
+ * The timer information, such as frequency and addresses, is provided to the
+ * OS via SFI tables.
+ * Timer interrupts are routed via FW/HW emulated IOAPIC independently via
+ * individual redirection table entries (RTE).
+ * Unlike HPET, there is no master counter, therefore one of the timers are
+ * used as clocksource. The overall allocation looks like:
+ *  - timer 0 - NR_CPUs for per cpu timer
+ *  - one timer for clocksource
+ *  - one timer for watchdog driver.
+ * It is also worth notice that APB timer does not support true one-shot mode,
+ * free-running mode will be used here to emulate one-shot mode.
+ * APB timer can also be used as broadcast timer along with per cpu local APIC
+ * timer, but by default APB timer has higher rating than local APIC timers.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/pm.h>
+#include <linux/pci.h>
+#include <linux/sfi.h>
+#include <linux/interrupt.h>
+#include <linux/cpu.h>
+#include <linux/irq.h>
+
+#include <asm/fixmap.h>
+#include <asm/apb_timer.h>
+
+#define APBT_MASK			CLOCKSOURCE_MASK(32)
+#define APBT_SHIFT			22
+#define APBT_CLOCKEVENT_RATING		150
+#define APBT_CLOCKSOURCE_RATING		250
+#define APBT_MIN_DELTA_USEC		200
+
+#define EVT_TO_APBT_DEV(evt) container_of(evt, struct apbt_dev, evt)
+#define APBT_CLOCKEVENT0_NUM   (0)
+#define APBT_CLOCKEVENT1_NUM   (1)
+#define APBT_CLOCKSOURCE_NUM   (2)
+
+static unsigned long apbt_address;
+static int apb_timer_block_enabled;
+static void __iomem *apbt_virt_address;
+static int phy_cs_timer_id;
+
+/*
+ * Common DW APB timer info
+ */
+static uint64_t apbt_freq;
+
+static void apbt_set_mode(enum clock_event_mode mode,
+			  struct clock_event_device *evt);
+static int apbt_next_event(unsigned long delta,
+			   struct clock_event_device *evt);
+static cycle_t apbt_read_clocksource(struct clocksource *cs);
+static void apbt_restart_clocksource(struct clocksource *cs);
+
+struct apbt_dev {
+	struct clock_event_device evt;
+	unsigned int num;
+	int cpu;
+	unsigned int irq;
+	unsigned int tick;
+	unsigned int count;
+	unsigned int flags;
+	char name[10];
+};
+
+int disable_apbt_percpu __cpuinitdata;
+
+static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev);
+
+#ifdef CONFIG_SMP
+static unsigned int apbt_num_timers_used;
+static struct apbt_dev *apbt_devs;
+#endif
+
+static	inline unsigned long apbt_readl_reg(unsigned long a)
+{
+	return readl(apbt_virt_address + a);
+}
+
+static inline void apbt_writel_reg(unsigned long d, unsigned long a)
+{
+	writel(d, apbt_virt_address + a);
+}
+
+static inline unsigned long apbt_readl(int n, unsigned long a)
+{
+	return readl(apbt_virt_address + a + n * APBTMRS_REG_SIZE);
+}
+
+static inline void apbt_writel(int n, unsigned long d, unsigned long a)
+{
+	writel(d, apbt_virt_address + a + n * APBTMRS_REG_SIZE);
+}
+
+static inline void apbt_set_mapping(void)
+{
+	struct sfi_timer_table_entry *mtmr;
+
+	if (apbt_virt_address) {
+		pr_debug("APBT base already mapped\n");
+		return;
+	}
+	mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM);
+	if (mtmr == NULL) {
+		printk(KERN_ERR "Failed to get MTMR %d from SFI\n",
+		       APBT_CLOCKEVENT0_NUM);
+		return;
+	}
+	apbt_address = (unsigned long)mtmr->phys_addr;
+	if (!apbt_address) {
+		printk(KERN_WARNING "No timer base from SFI, use default\n");
+		apbt_address = APBT_DEFAULT_BASE;
+	}
+	apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE);
+	if (apbt_virt_address) {
+		pr_debug("Mapped APBT physical addr %p at virtual addr %p\n",\
+			 (void *)apbt_address, (void *)apbt_virt_address);
+	} else {
+		pr_debug("Failed mapping APBT phy address at %p\n",\
+			 (void *)apbt_address);
+		goto panic_noapbt;
+	}
+	apbt_freq = mtmr->freq_hz / USEC_PER_SEC;
+	sfi_free_mtmr(mtmr);
+
+	/* Now figure out the physical timer id for clocksource device */
+	mtmr = sfi_get_mtmr(APBT_CLOCKSOURCE_NUM);
+	if (mtmr == NULL)
+		goto panic_noapbt;
+
+	/* Now figure out the physical timer id */
+	phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff)
+		/ APBTMRS_REG_SIZE;
+	pr_debug("Use timer %d for clocksource\n", phy_cs_timer_id);
+	return;
+
+panic_noapbt:
+	panic("Failed to setup APB system timer\n");
+
+}
+
+static inline void apbt_clear_mapping(void)
+{
+	iounmap(apbt_virt_address);
+	apbt_virt_address = NULL;
+}
+
+/*
+ * APBT timer interrupt enable / disable
+ */
+static inline int is_apbt_capable(void)
+{
+	return apbt_virt_address ? 1 : 0;
+}
+
+static struct clocksource clocksource_apbt = {
+	.name		= "apbt",
+	.rating		= APBT_CLOCKSOURCE_RATING,
+	.read		= apbt_read_clocksource,
+	.mask		= APBT_MASK,
+	.shift		= APBT_SHIFT,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+	.resume		= apbt_restart_clocksource,
+};
+
+/* boot APB clock event device */
+static struct clock_event_device apbt_clockevent = {
+	.name		= "apbt0",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode	= apbt_set_mode,
+	.set_next_event = apbt_next_event,
+	.shift		= APBT_SHIFT,
+	.irq		= 0,
+	.rating		= APBT_CLOCKEVENT_RATING,
+};
+
+/*
+ * if user does not want to use per CPU apb timer, just give it a lower rating
+ * than local apic timer and skip the late per cpu timer init.
+ */
+static inline int __init setup_x86_mrst_timer(char *arg)
+{
+	if (!arg)
+		return -EINVAL;
+
+	if (strcmp("apbt_only", arg) == 0)
+		disable_apbt_percpu = 0;
+	else if (strcmp("lapic_and_apbt", arg) == 0)
+		disable_apbt_percpu = 1;
+	else {
+		pr_warning("X86 MRST timer option %s not recognised"
+			   " use x86_mrst_timer=apbt_only or lapic_and_apbt\n",
+			   arg);
+		return -EINVAL;
+	}
+	return 0;
+}
+__setup("x86_mrst_timer=", setup_x86_mrst_timer);
+
+/*
+ * start count down from 0xffff_ffff. this is done by toggling the enable bit
+ * then load initial load count to ~0.
+ */
+static void apbt_start_counter(int n)
+{
+	unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
+
+	ctrl &= ~APBTMR_CONTROL_ENABLE;
+	apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+	apbt_writel(n, ~0, APBTMR_N_LOAD_COUNT);
+	/* enable, mask interrupt */
+	ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
+	ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT);
+	apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+	/* read it once to get cached counter value initialized */
+	apbt_read_clocksource(&clocksource_apbt);
+}
+
+static irqreturn_t apbt_interrupt_handler(int irq, void *data)
+{
+	struct apbt_dev *dev = (struct apbt_dev *)data;
+	struct clock_event_device *aevt = &dev->evt;
+
+	if (!aevt->event_handler) {
+		printk(KERN_INFO "Spurious APBT timer interrupt on %d\n",
+		       dev->num);
+		return IRQ_NONE;
+	}
+	aevt->event_handler(aevt);
+	return IRQ_HANDLED;
+}
+
+static void apbt_restart_clocksource(struct clocksource *cs)
+{
+	apbt_start_counter(phy_cs_timer_id);
+}
+
+/* Setup IRQ routing via IOAPIC */
+#ifdef CONFIG_SMP
+static void apbt_setup_irq(struct apbt_dev *adev)
+{
+	struct irq_chip *chip;
+	struct irq_desc *desc;
+
+	/* timer0 irq has been setup early */
+	if (adev->irq == 0)
+		return;
+	desc = irq_to_desc(adev->irq);
+	chip = get_irq_chip(adev->irq);
+	disable_irq(adev->irq);
+	desc->status |= IRQ_MOVE_PCNTXT;
+	irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
+	/* APB timer irqs are set up as mp_irqs, timer is edge triggerred */
+	set_irq_chip_and_handler_name(adev->irq, chip, handle_edge_irq, "edge");
+	enable_irq(adev->irq);
+	if (system_state == SYSTEM_BOOTING)
+		if (request_irq(adev->irq, apbt_interrupt_handler,
+				IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+				adev->name, adev)) {
+			printk(KERN_ERR "Failed request IRQ for APBT%d\n",
+			       adev->num);
+		}
+}
+#endif
+
+static void apbt_enable_int(int n)
+{
+	unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
+	/* clear pending intr */
+	apbt_readl(n, APBTMR_N_EOI);
+	ctrl &= ~APBTMR_CONTROL_INT;
+	apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+}
+
+static void apbt_disable_int(int n)
+{
+	unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
+
+	ctrl |= APBTMR_CONTROL_INT;
+	apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+}
+
+
+static int __init apbt_clockevent_register(void)
+{
+	struct sfi_timer_table_entry *mtmr;
+	struct apbt_dev *adev = &__get_cpu_var(cpu_apbt_dev);
+
+	mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM);
+	if (mtmr == NULL) {
+		printk(KERN_ERR "Failed to get MTMR %d from SFI\n",
+		       APBT_CLOCKEVENT0_NUM);
+		return -ENODEV;
+	}
+
+	/*
+	 * We need to calculate the scaled math multiplication factor for
+	 * nanosecond to apbt tick conversion.
+	 * mult = (nsec/cycle)*2^APBT_SHIFT
+	 */
+	apbt_clockevent.mult = div_sc((unsigned long) mtmr->freq_hz
+				      , NSEC_PER_SEC, APBT_SHIFT);
+
+	/* Calculate the min / max delta */
+	apbt_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
+							   &apbt_clockevent);
+	apbt_clockevent.min_delta_ns = clockevent_delta2ns(
+		APBT_MIN_DELTA_USEC*apbt_freq,
+		&apbt_clockevent);
+	/*
+	 * Start apbt with the boot cpu mask and make it
+	 * global if not used for per cpu timer.
+	 */
+	apbt_clockevent.cpumask = cpumask_of(smp_processor_id());
+	adev->num = smp_processor_id();
+	memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device));
+
+	if (disable_apbt_percpu) {
+		apbt_clockevent.rating = APBT_CLOCKEVENT_RATING - 100;
+		global_clock_event = &adev->evt;
+		printk(KERN_DEBUG "%s clockevent registered as global\n",
+		       global_clock_event->name);
+	}
+
+	if (request_irq(apbt_clockevent.irq, apbt_interrupt_handler,
+			IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+			apbt_clockevent.name, adev)) {
+		printk(KERN_ERR "Failed request IRQ for APBT%d\n",
+		       apbt_clockevent.irq);
+	}
+
+	clockevents_register_device(&adev->evt);
+	/* Start APBT 0 interrupts */
+	apbt_enable_int(APBT_CLOCKEVENT0_NUM);
+
+	sfi_free_mtmr(mtmr);
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+/* Should be called with per cpu */
+void apbt_setup_secondary_clock(void)
+{
+	struct apbt_dev *adev;
+	struct clock_event_device *aevt;
+	int cpu;
+
+	/* Don't register boot CPU clockevent */
+	cpu = smp_processor_id();
+	if (cpu == boot_cpu_id)
+		return;
+	/*
+	 * We need to calculate the scaled math multiplication factor for
+	 * nanosecond to apbt tick conversion.
+	 * mult = (nsec/cycle)*2^APBT_SHIFT
+	 */
+	printk(KERN_INFO "Init per CPU clockevent %d\n", cpu);
+	adev = &per_cpu(cpu_apbt_dev, cpu);
+	aevt = &adev->evt;
+
+	memcpy(aevt, &apbt_clockevent, sizeof(*aevt));
+	aevt->cpumask = cpumask_of(cpu);
+	aevt->name = adev->name;
+	aevt->mode = CLOCK_EVT_MODE_UNUSED;
+
+	printk(KERN_INFO "Registering CPU %d clockevent device %s, mask %08x\n",
+	       cpu, aevt->name, *(u32 *)aevt->cpumask);
+
+	apbt_setup_irq(adev);
+
+	clockevents_register_device(aevt);
+
+	apbt_enable_int(cpu);
+
+	return;
+}
+
+/*
+ * this notify handler process CPU hotplug events. in case of S0i3, nonboot
+ * cpus are disabled/enabled frequently, for performance reasons, we keep the
+ * per cpu timer irq registered so that we do need to do free_irq/request_irq.
+ *
+ * TODO: it might be more reliable to directly disable percpu clockevent device
+ * without the notifier chain. currently, cpu 0 may get interrupts from other
+ * cpu timers during the offline process due to the ordering of notification.
+ * the extra interrupt is harmless.
+ */
+static int apbt_cpuhp_notify(struct notifier_block *n,
+			     unsigned long action, void *hcpu)
+{
+	unsigned long cpu = (unsigned long)hcpu;
+	struct apbt_dev *adev = &per_cpu(cpu_apbt_dev, cpu);
+
+	switch (action & 0xf) {
+	case CPU_DEAD:
+		apbt_disable_int(cpu);
+		if (system_state == SYSTEM_RUNNING)
+			pr_debug("skipping APBT CPU %lu offline\n", cpu);
+		else if (adev) {
+			pr_debug("APBT clockevent for cpu %lu offline\n", cpu);
+			free_irq(adev->irq, adev);
+		}
+		break;
+	default:
+		pr_debug(KERN_INFO "APBT notified %lu, no action\n", action);
+	}
+	return NOTIFY_OK;
+}
+
+static __init int apbt_late_init(void)
+{
+	if (disable_apbt_percpu)
+		return 0;
+	/* This notifier should be called after workqueue is ready */
+	hotcpu_notifier(apbt_cpuhp_notify, -20);
+	return 0;
+}
+fs_initcall(apbt_late_init);
+#else
+
+void apbt_setup_secondary_clock(void) {}
+
+#endif /* CONFIG_SMP */
+
+static void apbt_set_mode(enum clock_event_mode mode,
+			  struct clock_event_device *evt)
+{
+	unsigned long ctrl;
+	uint64_t delta;
+	int timer_num;
+	struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
+
+	timer_num = adev->num;
+	pr_debug("%s CPU %d timer %d mode=%d\n",
+		 __func__, first_cpu(*evt->cpumask), timer_num, mode);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * apbt_clockevent.mult;
+		delta >>= apbt_clockevent.shift;
+		ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+		ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
+		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+		/*
+		 * DW APB p. 46, have to disable timer before load counter,
+		 * may cause sync problem.
+		 */
+		ctrl &= ~APBTMR_CONTROL_ENABLE;
+		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+		udelay(1);
+		pr_debug("Setting clock period %d for HZ %d\n", (int)delta, HZ);
+		apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
+		ctrl |= APBTMR_CONTROL_ENABLE;
+		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+		break;
+		/* APB timer does not have one-shot mode, use free running mode */
+	case CLOCK_EVT_MODE_ONESHOT:
+		ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+		/*
+		 * set free running mode, this mode will let timer reload max
+		 * timeout which will give time (3min on 25MHz clock) to rearm
+		 * the next event, therefore emulate the one-shot mode.
+		 */
+		ctrl &= ~APBTMR_CONTROL_ENABLE;
+		ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
+
+		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+		/* write again to set free running mode */
+		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+
+		/*
+		 * DW APB p. 46, load counter with all 1s before starting free
+		 * running mode.
+		 */
+		apbt_writel(timer_num, ~0, APBTMR_N_LOAD_COUNT);
+		ctrl &= ~APBTMR_CONTROL_INT;
+		ctrl |= APBTMR_CONTROL_ENABLE;
+		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		apbt_disable_int(timer_num);
+		ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+		ctrl &= ~APBTMR_CONTROL_ENABLE;
+		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		apbt_enable_int(timer_num);
+		break;
+	}
+}
+
+static int apbt_next_event(unsigned long delta,
+			   struct clock_event_device *evt)
+{
+	unsigned long ctrl;
+	int timer_num;
+
+	struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
+
+	timer_num = adev->num;
+	/* Disable timer */
+	ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+	ctrl &= ~APBTMR_CONTROL_ENABLE;
+	apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+	/* write new count */
+	apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
+	ctrl |= APBTMR_CONTROL_ENABLE;
+	apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+	return 0;
+}
+
+/*
+ * APB timer clock is not in sync with pclk on Langwell, which translates to
+ * unreliable read value caused by sampling error. the error does not add up
+ * overtime and only happens when sampling a 0 as a 1 by mistake. so the time
+ * would go backwards. the following code is trying to prevent time traveling
+ * backwards. little bit paranoid.
+ */
+static cycle_t apbt_read_clocksource(struct clocksource *cs)
+{
+	unsigned long t0, t1, t2;
+	static unsigned long last_read;
+
+bad_count:
+	t1 = apbt_readl(phy_cs_timer_id,
+			APBTMR_N_CURRENT_VALUE);
+	t2 = apbt_readl(phy_cs_timer_id,
+			APBTMR_N_CURRENT_VALUE);
+	if (unlikely(t1 < t2)) {
+		pr_debug("APBT: read current count error %lx:%lx:%lx\n",
+			 t1, t2, t2 - t1);
+		goto bad_count;
+	}
+	/*
+	 * check against cached last read, makes sure time does not go back.
+	 * it could be a normal rollover but we will do tripple check anyway
+	 */
+	if (unlikely(t2 > last_read)) {
+		/* check if we have a normal rollover */
+		unsigned long raw_intr_status =
+			apbt_readl_reg(APBTMRS_RAW_INT_STATUS);
+		/*
+		 * cs timer interrupt is masked but raw intr bit is set if
+		 * rollover occurs. then we read EOI reg to clear it.
+		 */
+		if (raw_intr_status & (1 << phy_cs_timer_id)) {
+			apbt_readl(phy_cs_timer_id, APBTMR_N_EOI);
+			goto out;
+		}
+		pr_debug("APB CS going back %lx:%lx:%lx ",
+			 t2, last_read, t2 - last_read);
+bad_count_x3:
+		pr_debug(KERN_INFO "tripple check enforced\n");
+		t0 = apbt_readl(phy_cs_timer_id,
+				APBTMR_N_CURRENT_VALUE);
+		udelay(1);
+		t1 = apbt_readl(phy_cs_timer_id,
+				APBTMR_N_CURRENT_VALUE);
+		udelay(1);
+		t2 = apbt_readl(phy_cs_timer_id,
+				APBTMR_N_CURRENT_VALUE);
+		if ((t2 > t1) || (t1 > t0)) {
+			printk(KERN_ERR "Error: APB CS tripple check failed\n");
+			goto bad_count_x3;
+		}
+	}
+out:
+	last_read = t2;
+	return (cycle_t)~t2;
+}
+
+static int apbt_clocksource_register(void)
+{
+	u64 start, now;
+	cycle_t t1;
+
+	/* Start the counter, use timer 2 as source, timer 0/1 for event */
+	apbt_start_counter(phy_cs_timer_id);
+
+	/* Verify whether apbt counter works */
+	t1 = apbt_read_clocksource(&clocksource_apbt);
+	rdtscll(start);
+
+	/*
+	 * We don't know the TSC frequency yet, but waiting for
+	 * 200000 TSC cycles is safe:
+	 * 4 GHz == 50us
+	 * 1 GHz == 200us
+	 */
+	do {
+		rep_nop();
+		rdtscll(now);
+	} while ((now - start) < 200000UL);
+
+	/* APBT is the only always on clocksource, it has to work! */
+	if (t1 == apbt_read_clocksource(&clocksource_apbt))
+		panic("APBT counter not counting. APBT disabled\n");
+
+	/*
+	 * initialize and register APBT clocksource
+	 * convert that to ns/clock cycle
+	 * mult = (ns/c) * 2^APBT_SHIFT
+	 */
+	clocksource_apbt.mult = div_sc(MSEC_PER_SEC,
+				       (unsigned long) apbt_freq, APBT_SHIFT);
+	clocksource_register(&clocksource_apbt);
+
+	return 0;
+}
+
+/*
+ * Early setup the APBT timer, only use timer 0 for booting then switch to
+ * per CPU timer if possible.
+ * returns 1 if per cpu apbt is setup
+ * returns 0 if no per cpu apbt is chosen
+ * panic if set up failed, this is the only platform timer on Moorestown.
+ */
+void __init apbt_time_init(void)
+{
+#ifdef CONFIG_SMP
+	int i;
+	struct sfi_timer_table_entry *p_mtmr;
+	unsigned int percpu_timer;
+	struct apbt_dev *adev;
+#endif
+
+	if (apb_timer_block_enabled)
+		return;
+	apbt_set_mapping();
+	if (apbt_virt_address) {
+		pr_debug("Found APBT version 0x%lx\n",\
+			 apbt_readl_reg(APBTMRS_COMP_VERSION));
+	} else
+		goto out_noapbt;
+	/*
+	 * Read the frequency and check for a sane value, for ESL model
+	 * we extend the possible clock range to allow time scaling.
+	 */
+
+	if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) {
+		pr_debug("APBT has invalid freq 0x%llx\n", apbt_freq);
+		goto out_noapbt;
+	}
+	if (apbt_clocksource_register()) {
+		pr_debug("APBT has failed to register clocksource\n");
+		goto out_noapbt;
+	}
+	if (!apbt_clockevent_register())
+		apb_timer_block_enabled = 1;
+	else {
+		pr_debug("APBT has failed to register clockevent\n");
+		goto out_noapbt;
+	}
+#ifdef CONFIG_SMP
+	/* kernel cmdline disable apb timer, so we will use lapic timers */
+	if (disable_apbt_percpu) {
+		printk(KERN_INFO "apbt: disabled per cpu timer\n");
+		return;
+	}
+	pr_debug("%s: %d CPUs online\n", __func__, num_online_cpus());
+	if (num_possible_cpus() <= sfi_mtimer_num) {
+		percpu_timer = 1;
+		apbt_num_timers_used = num_possible_cpus();
+	} else {
+		percpu_timer = 0;
+		apbt_num_timers_used = 1;
+		adev = &per_cpu(cpu_apbt_dev, 0);
+		adev->flags &= ~APBT_DEV_USED;
+	}
+	pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used);
+
+	/* here we set up per CPU timer data structure */
+	apbt_devs = kzalloc(sizeof(struct apbt_dev) * apbt_num_timers_used,
+			    GFP_KERNEL);
+	if (!apbt_devs) {
+		printk(KERN_ERR "Failed to allocate APB timer devices\n");
+		return;
+	}
+	for (i = 0; i < apbt_num_timers_used; i++) {
+		adev = &per_cpu(cpu_apbt_dev, i);
+		adev->num = i;
+		adev->cpu = i;
+		p_mtmr = sfi_get_mtmr(i);
+		if (p_mtmr) {
+			adev->tick = p_mtmr->freq_hz;
+			adev->irq = p_mtmr->irq;
+		} else
+			printk(KERN_ERR "Failed to get timer for cpu %d\n", i);
+		adev->count = 0;
+		sprintf(adev->name, "apbt%d", i);
+	}
+#endif
+
+	return;
+
+out_noapbt:
+	apbt_clear_mapping();
+	apb_timer_block_enabled = 0;
+	panic("failed to enable APB timer\n");
+}
+
+static inline void apbt_disable(int n)
+{
+	if (is_apbt_capable()) {
+		unsigned long ctrl =  apbt_readl(n, APBTMR_N_CONTROL);
+		ctrl &= ~APBTMR_CONTROL_ENABLE;
+		apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+	}
+}
+
+/* called before apb_timer_enable, use early map */
+unsigned long apbt_quick_calibrate()
+{
+	int i, scale;
+	u64 old, new;
+	cycle_t t1, t2;
+	unsigned long khz = 0;
+	u32 loop, shift;
+
+	apbt_set_mapping();
+	apbt_start_counter(phy_cs_timer_id);
+
+	/* check if the timer can count down, otherwise return */
+	old = apbt_read_clocksource(&clocksource_apbt);
+	i = 10000;
+	while (--i) {
+		if (old != apbt_read_clocksource(&clocksource_apbt))
+			break;
+	}
+	if (!i)
+		goto failed;
+
+	/* count 16 ms */
+	loop = (apbt_freq * 1000) << 4;
+
+	/* restart the timer to ensure it won't get to 0 in the calibration */
+	apbt_start_counter(phy_cs_timer_id);
+
+	old = apbt_read_clocksource(&clocksource_apbt);
+	old += loop;
+
+	t1 = __native_read_tsc();
+
+	do {
+		new = apbt_read_clocksource(&clocksource_apbt);
+	} while (new < old);
+
+	t2 = __native_read_tsc();
+
+	shift = 5;
+	if (unlikely(loop >> shift == 0)) {
+		printk(KERN_INFO
+		       "APBT TSC calibration failed, not enough resolution\n");
+		return 0;
+	}
+	scale = (int)div_u64((t2 - t1), loop >> shift);
+	khz = (scale * apbt_freq * 1000) >> shift;
+	printk(KERN_INFO "TSC freq calculated by APB timer is %lu khz\n", khz);
+	return khz;
+failed:
+	return 0;
+}
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index f147a95..3704997 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -31,7 +31,6 @@
 #include <asm/x86_init.h>
 
 int gart_iommu_aperture;
-EXPORT_SYMBOL_GPL(gart_iommu_aperture);
 int gart_iommu_aperture_disabled __initdata;
 int gart_iommu_aperture_allowed __initdata;
 
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 6e29b2a..00187f1 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1390,7 +1390,7 @@
 	}
 
 	local_irq_save(flags);
-	mask_8259A();
+	legacy_pic->mask_all();
 	mask_IO_APIC_setup(ioapic_entries);
 
 	if (dmar_table_init_ret)
@@ -1422,7 +1422,7 @@
 nox2apic:
 	if (!ret) /* IR enabling failed */
 		restore_IO_APIC_setup(ioapic_entries);
-	unmask_8259A();
+	legacy_pic->restore_mask();
 	local_irq_restore(flags);
 
 out:
@@ -2018,7 +2018,7 @@
 		}
 
 		mask_IO_APIC_setup(ioapic_entries);
-		mask_8259A();
+		legacy_pic->mask_all();
 	}
 
 	if (x2apic_mode)
@@ -2062,7 +2062,7 @@
 
 	if (intr_remapping_enabled) {
 		reenable_intr_remapping(x2apic_mode);
-		unmask_8259A();
+		legacy_pic->restore_mask();
 		restore_IO_APIC_setup(ioapic_entries);
 		free_ioapic_entries(ioapic_entries);
 	}
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index e3c3d82..09d3b17 100644
--- a/arch/x86/kernel/apic/apic_flat_64.c
+++ b/arch/x86/kernel/apic/apic_flat_64.c
@@ -223,7 +223,7 @@
 };
 
 /*
- * Physflat mode is used when there are more than 8 CPUs on a AMD system.
+ * Physflat mode is used when there are more than 8 CPUs on a system.
  * We cannot use logical delivery in this case because the mask
  * overflows, so use physical mode.
  */
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 6bdd2c7..e4e0ddc 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -73,8 +73,8 @@
  */
 int sis_apic_bug = -1;
 
-static DEFINE_SPINLOCK(ioapic_lock);
-static DEFINE_SPINLOCK(vector_lock);
+static DEFINE_RAW_SPINLOCK(ioapic_lock);
+static DEFINE_RAW_SPINLOCK(vector_lock);
 
 /*
  * # of IRQ routing registers
@@ -94,8 +94,6 @@
 /* # of MP IRQ source entries */
 int mp_irq_entries;
 
-/* Number of legacy interrupts */
-static int nr_legacy_irqs __read_mostly = NR_IRQS_LEGACY;
 /* GSI interrupts */
 static int nr_irqs_gsi = NR_IRQS_LEGACY;
 
@@ -140,33 +138,10 @@
 
 /* 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[] = {
+static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
 #else
-static struct irq_cfg irq_cfgx[NR_IRQS] = {
+static struct irq_cfg irq_cfgx[NR_IRQS];
 #endif
-	[0]  = { .vector = IRQ0_VECTOR,  },
-	[1]  = { .vector = IRQ1_VECTOR,  },
-	[2]  = { .vector = IRQ2_VECTOR,  },
-	[3]  = { .vector = IRQ3_VECTOR,  },
-	[4]  = { .vector = IRQ4_VECTOR,  },
-	[5]  = { .vector = IRQ5_VECTOR,  },
-	[6]  = { .vector = IRQ6_VECTOR,  },
-	[7]  = { .vector = IRQ7_VECTOR,  },
-	[8]  = { .vector = IRQ8_VECTOR,  },
-	[9]  = { .vector = IRQ9_VECTOR,  },
-	[10] = { .vector = IRQ10_VECTOR, },
-	[11] = { .vector = IRQ11_VECTOR, },
-	[12] = { .vector = IRQ12_VECTOR, },
-	[13] = { .vector = IRQ13_VECTOR, },
-	[14] = { .vector = IRQ14_VECTOR, },
-	[15] = { .vector = IRQ15_VECTOR, },
-};
-
-void __init io_apic_disable_legacy(void)
-{
-	nr_legacy_irqs = 0;
-	nr_irqs_gsi = 0;
-}
 
 int __init arch_early_irq_init(void)
 {
@@ -176,6 +151,11 @@
 	int node;
 	int i;
 
+	if (!legacy_pic->nr_legacy_irqs) {
+		nr_irqs_gsi = 0;
+		io_apic_irqs = ~0UL;
+	}
+
 	cfg = irq_cfgx;
 	count = ARRAY_SIZE(irq_cfgx);
 	node= cpu_to_node(boot_cpu_id);
@@ -185,8 +165,14 @@
 		desc->chip_data = &cfg[i];
 		zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
 		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_NOWAIT, node);
-		if (i < nr_legacy_irqs)
-			cpumask_setall(cfg[i].domain);
+		/*
+		 * For legacy IRQ's, start with assigning irq0 to irq15 to
+		 * IRQ0_VECTOR to IRQ15_VECTOR on cpu 0.
+		 */
+		if (i < legacy_pic->nr_legacy_irqs) {
+			cfg[i].vector = IRQ0_VECTOR + i;
+			cpumask_set_cpu(0, cfg[i].domain);
+		}
 	}
 
 	return 0;
@@ -406,7 +392,7 @@
 	struct irq_pin_list *entry;
 	unsigned long flags;
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	for_each_irq_pin(entry, cfg->irq_2_pin) {
 		unsigned int reg;
 		int pin;
@@ -415,11 +401,11 @@
 		reg = io_apic_read(entry->apic, 0x10 + pin*2);
 		/* Is the remote IRR bit set? */
 		if (reg & IO_APIC_REDIR_REMOTE_IRR) {
-			spin_unlock_irqrestore(&ioapic_lock, flags);
+			raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 			return true;
 		}
 	}
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	return false;
 }
@@ -433,10 +419,10 @@
 {
 	union entry_union eu;
 	unsigned long flags;
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
 	eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 	return eu.entry;
 }
 
@@ -459,9 +445,9 @@
 void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	__ioapic_write_entry(apic, pin, e);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 /*
@@ -474,10 +460,10 @@
 	unsigned long flags;
 	union entry_union eu = { .entry.mask = 1 };
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	io_apic_write(apic, 0x10 + 2*pin, eu.w1);
 	io_apic_write(apic, 0x11 + 2*pin, eu.w2);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 /*
@@ -604,9 +590,9 @@
 
 	BUG_ON(!cfg);
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	__mask_IO_APIC_irq(cfg);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 static void unmask_IO_APIC_irq_desc(struct irq_desc *desc)
@@ -614,9 +600,9 @@
 	struct irq_cfg *cfg = desc->chip_data;
 	unsigned long flags;
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	__unmask_IO_APIC_irq(cfg);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 static void mask_IO_APIC_irq(unsigned int irq)
@@ -865,7 +851,7 @@
  */
 static int EISA_ELCR(unsigned int irq)
 {
-	if (irq < nr_legacy_irqs) {
+	if (irq < legacy_pic->nr_legacy_irqs) {
 		unsigned int port = 0x4d0 + (irq >> 3);
 		return (inb(port) >> (irq & 7)) & 1;
 	}
@@ -1140,12 +1126,12 @@
 	/* Used to the online set of cpus does not change
 	 * during assign_irq_vector.
 	 */
-	spin_lock(&vector_lock);
+	raw_spin_lock(&vector_lock);
 }
 
 void unlock_vector_lock(void)
 {
-	spin_unlock(&vector_lock);
+	raw_spin_unlock(&vector_lock);
 }
 
 static int
@@ -1162,7 +1148,8 @@
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START;
+	static int current_offset = VECTOR_OFFSET_START % 8;
 	unsigned int old_vector;
 	int cpu, err;
 	cpumask_var_t tmp_mask;
@@ -1198,7 +1185,7 @@
 		if (vector >= first_system_vector) {
 			/* If out of vectors on large boxen, must share them. */
 			offset = (offset + 1) % 8;
-			vector = FIRST_DEVICE_VECTOR + offset;
+			vector = FIRST_EXTERNAL_VECTOR + offset;
 		}
 		if (unlikely(current_vector == vector))
 			continue;
@@ -1232,9 +1219,9 @@
 	int err;
 	unsigned long flags;
 
-	spin_lock_irqsave(&vector_lock, flags);
+	raw_spin_lock_irqsave(&vector_lock, flags);
 	err = __assign_irq_vector(irq, cfg, mask);
-	spin_unlock_irqrestore(&vector_lock, flags);
+	raw_spin_unlock_irqrestore(&vector_lock, flags);
 	return err;
 }
 
@@ -1268,11 +1255,16 @@
 void __setup_vector_irq(int cpu)
 {
 	/* Initialize vector_irq on a new cpu */
-	/* This function must be called with vector_lock held */
 	int irq, vector;
 	struct irq_cfg *cfg;
 	struct irq_desc *desc;
 
+	/*
+	 * vector_lock will make sure that we don't run into irq vector
+	 * assignments that might be happening on another cpu in parallel,
+	 * while we setup our initial vector to irq mappings.
+	 */
+	raw_spin_lock(&vector_lock);
 	/* Mark the inuse vectors */
 	for_each_irq_desc(irq, desc) {
 		cfg = desc->chip_data;
@@ -1291,6 +1283,7 @@
 		if (!cpumask_test_cpu(cpu, cfg->domain))
 			per_cpu(vector_irq, cpu)[vector] = -1;
 	}
+	raw_spin_unlock(&vector_lock);
 }
 
 static struct irq_chip ioapic_chip;
@@ -1440,6 +1433,14 @@
 
 	cfg = desc->chip_data;
 
+	/*
+	 * For legacy irqs, cfg->domain starts with cpu 0 for legacy
+	 * controllers like 8259. Now that IO-APIC can handle this irq, update
+	 * the cfg->domain.
+	 */
+	if (irq < legacy_pic->nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain))
+		apic->vector_allocation_domain(0, cfg->domain);
+
 	if (assign_irq_vector(irq, cfg, apic->target_cpus()))
 		return;
 
@@ -1461,8 +1462,8 @@
 	}
 
 	ioapic_register_intr(irq, desc, trigger);
-	if (irq < nr_legacy_irqs)
-		disable_8259A_irq(irq);
+	if (irq < legacy_pic->nr_legacy_irqs)
+		legacy_pic->chip->mask(irq);
 
 	ioapic_write_entry(apic_id, pin, entry);
 }
@@ -1473,7 +1474,7 @@
 
 static void __init setup_IO_APIC_irqs(void)
 {
-	int apic_id = 0, pin, idx, irq;
+	int apic_id, pin, idx, irq;
 	int notcon = 0;
 	struct irq_desc *desc;
 	struct irq_cfg *cfg;
@@ -1481,14 +1482,7 @@
 
 	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		apic_id = mp_find_ioapic(0);
-		if (apic_id < 0)
-			apic_id = 0;
-	}
-#endif
-
+	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
 		if (idx == -1) {
@@ -1510,6 +1504,9 @@
 
 		irq = pin_2_irq(idx, apic_id, pin);
 
+		if ((apic_id > 0) && (irq > 16))
+			continue;
+
 		/*
 		 * Skip the timer IRQ if there's a quirk handler
 		 * installed and if it returns 1:
@@ -1539,6 +1536,56 @@
 }
 
 /*
+ * for the gsit that is not in first ioapic
+ * but could not use acpi_register_gsi()
+ * like some special sci in IBM x3330
+ */
+void setup_IO_APIC_irq_extra(u32 gsi)
+{
+	int apic_id = 0, pin, idx, irq;
+	int node = cpu_to_node(boot_cpu_id);
+	struct irq_desc *desc;
+	struct irq_cfg *cfg;
+
+	/*
+	 * Convert 'gsi' to 'ioapic.pin'.
+	 */
+	apic_id = mp_find_ioapic(gsi);
+	if (apic_id < 0)
+		return;
+
+	pin = mp_find_ioapic_pin(apic_id, gsi);
+	idx = find_irq_entry(apic_id, pin, mp_INT);
+	if (idx == -1)
+		return;
+
+	irq = pin_2_irq(idx, apic_id, pin);
+#ifdef CONFIG_SPARSE_IRQ
+	desc = irq_to_desc(irq);
+	if (desc)
+		return;
+#endif
+	desc = irq_to_desc_alloc_node(irq, node);
+	if (!desc) {
+		printk(KERN_INFO "can not get irq_desc for %d\n", irq);
+		return;
+	}
+
+	cfg = desc->chip_data;
+	add_pin_to_irq_node(cfg, node, apic_id, pin);
+
+	if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
+		pr_debug("Pin %d-%d already programmed\n",
+			 mp_ioapics[apic_id].apicid, pin);
+		return;
+	}
+	set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
+
+	setup_IO_APIC_irq(apic_id, pin, irq, desc,
+			irq_trigger(idx), irq_polarity(idx));
+}
+
+/*
  * Set up the timer pin, possibly with the 8259A-master behind.
  */
 static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin,
@@ -1601,14 +1648,14 @@
 
 	for (apic = 0; apic < nr_ioapics; apic++) {
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	reg_00.raw = io_apic_read(apic, 0);
 	reg_01.raw = io_apic_read(apic, 1);
 	if (reg_01.bits.version >= 0x10)
 		reg_02.raw = io_apic_read(apic, 2);
 	if (reg_01.bits.version >= 0x20)
 		reg_03.raw = io_apic_read(apic, 3);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	printk("\n");
 	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].apicid);
@@ -1825,12 +1872,12 @@
 	unsigned int v;
 	unsigned long flags;
 
-	if (!nr_legacy_irqs)
+	if (!legacy_pic->nr_legacy_irqs)
 		return;
 
 	printk(KERN_DEBUG "\nprinting PIC contents\n");
 
-	spin_lock_irqsave(&i8259A_lock, flags);
+	raw_spin_lock_irqsave(&i8259A_lock, flags);
 
 	v = inb(0xa1) << 8 | inb(0x21);
 	printk(KERN_DEBUG "... PIC  IMR: %04x\n", v);
@@ -1844,7 +1891,7 @@
 	outb(0x0a,0xa0);
 	outb(0x0a,0x20);
 
-	spin_unlock_irqrestore(&i8259A_lock, flags);
+	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 
 	printk(KERN_DEBUG "... PIC  ISR: %04x\n", v);
 
@@ -1903,13 +1950,13 @@
 	 * The number of IO-APIC IRQ registers (== #pins):
 	 */
 	for (apic = 0; apic < nr_ioapics; apic++) {
-		spin_lock_irqsave(&ioapic_lock, flags);
+		raw_spin_lock_irqsave(&ioapic_lock, flags);
 		reg_01.raw = io_apic_read(apic, 1);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
+		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 		nr_ioapic_registers[apic] = reg_01.bits.entries+1;
 	}
 
-	if (!nr_legacy_irqs)
+	if (!legacy_pic->nr_legacy_irqs)
 		return;
 
 	for(apic = 0; apic < nr_ioapics; apic++) {
@@ -1966,7 +2013,7 @@
 	 */
 	clear_IO_APIC();
 
-	if (!nr_legacy_irqs)
+	if (!legacy_pic->nr_legacy_irqs)
 		return;
 
 	/*
@@ -2045,9 +2092,9 @@
 	for (apic_id = 0; apic_id < nr_ioapics; apic_id++) {
 
 		/* Read the register 0 value */
-		spin_lock_irqsave(&ioapic_lock, flags);
+		raw_spin_lock_irqsave(&ioapic_lock, flags);
 		reg_00.raw = io_apic_read(apic_id, 0);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
+		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		old_id = mp_ioapics[apic_id].apicid;
 
@@ -2106,16 +2153,16 @@
 			mp_ioapics[apic_id].apicid);
 
 		reg_00.bits.ID = mp_ioapics[apic_id].apicid;
-		spin_lock_irqsave(&ioapic_lock, flags);
+		raw_spin_lock_irqsave(&ioapic_lock, flags);
 		io_apic_write(apic_id, 0, reg_00.raw);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
+		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		/*
 		 * Sanity check
 		 */
-		spin_lock_irqsave(&ioapic_lock, flags);
+		raw_spin_lock_irqsave(&ioapic_lock, flags);
 		reg_00.raw = io_apic_read(apic_id, 0);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
+		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 		if (reg_00.bits.ID != mp_ioapics[apic_id].apicid)
 			printk("could not set ID!\n");
 		else
@@ -2198,15 +2245,15 @@
 	unsigned long flags;
 	struct irq_cfg *cfg;
 
-	spin_lock_irqsave(&ioapic_lock, flags);
-	if (irq < nr_legacy_irqs) {
-		disable_8259A_irq(irq);
-		if (i8259A_irq_pending(irq))
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
+	if (irq < legacy_pic->nr_legacy_irqs) {
+		legacy_pic->chip->mask(irq);
+		if (legacy_pic->irq_pending(irq))
 			was_pending = 1;
 	}
 	cfg = irq_cfg(irq);
 	__unmask_IO_APIC_irq(cfg);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	return was_pending;
 }
@@ -2217,9 +2264,9 @@
 	struct irq_cfg *cfg = irq_cfg(irq);
 	unsigned long flags;
 
-	spin_lock_irqsave(&vector_lock, flags);
+	raw_spin_lock_irqsave(&vector_lock, flags);
 	apic->send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector);
-	spin_unlock_irqrestore(&vector_lock, flags);
+	raw_spin_unlock_irqrestore(&vector_lock, flags);
 
 	return 1;
 }
@@ -2312,14 +2359,14 @@
 	irq = desc->irq;
 	cfg = desc->chip_data;
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	ret = set_desc_affinity(desc, mask, &dest);
 	if (!ret) {
 		/* Only the high 8 bits are valid. */
 		dest = SET_APIC_LOGICAL_ID(dest);
 		__target_IO_APIC_irq(irq, dest, cfg);
 	}
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	return ret;
 }
@@ -2554,9 +2601,9 @@
 	irq = desc->irq;
 	cfg = desc->chip_data;
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	__eoi_ioapic_irq(irq, cfg);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
 static void ack_apic_level(unsigned int irq)
@@ -2734,8 +2781,8 @@
 			 * so default to an old-fashioned 8259
 			 * interrupt if we can..
 			 */
-			if (irq < nr_legacy_irqs)
-				make_8259A_irq(irq);
+			if (irq < legacy_pic->nr_legacy_irqs)
+				legacy_pic->make_irq(irq);
 			else
 				/* Strange. Oh, well.. */
 				desc->chip = &no_irq_chip;
@@ -2892,7 +2939,7 @@
 	/*
 	 * get/set the timer IRQ vector:
 	 */
-	disable_8259A_irq(0);
+	legacy_pic->chip->mask(0);
 	assign_irq_vector(0, cfg, apic->target_cpus());
 
 	/*
@@ -2905,7 +2952,7 @@
 	 * automatically.
 	 */
 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
-	init_8259A(1);
+	legacy_pic->init(1);
 #ifdef CONFIG_X86_32
 	{
 		unsigned int ver;
@@ -2964,7 +3011,7 @@
 		if (timer_irq_works()) {
 			if (nmi_watchdog == NMI_IO_APIC) {
 				setup_nmi();
-				enable_8259A_irq(0);
+				legacy_pic->chip->unmask(0);
 			}
 			if (disable_timer_pin_1 > 0)
 				clear_IO_APIC_pin(0, pin1);
@@ -2987,14 +3034,14 @@
 		 */
 		replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
 		setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
-		enable_8259A_irq(0);
+		legacy_pic->chip->unmask(0);
 		if (timer_irq_works()) {
 			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
 			timer_through_8259 = 1;
 			if (nmi_watchdog == NMI_IO_APIC) {
-				disable_8259A_irq(0);
+				legacy_pic->chip->mask(0);
 				setup_nmi();
-				enable_8259A_irq(0);
+				legacy_pic->chip->unmask(0);
 			}
 			goto out;
 		}
@@ -3002,7 +3049,7 @@
 		 * Cleanup, just in case ...
 		 */
 		local_irq_disable();
-		disable_8259A_irq(0);
+		legacy_pic->chip->mask(0);
 		clear_IO_APIC_pin(apic2, pin2);
 		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
 	}
@@ -3021,22 +3068,22 @@
 
 	lapic_register_intr(0, desc);
 	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
-	enable_8259A_irq(0);
+	legacy_pic->chip->unmask(0);
 
 	if (timer_irq_works()) {
 		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
 		goto out;
 	}
 	local_irq_disable();
-	disable_8259A_irq(0);
+	legacy_pic->chip->mask(0);
 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
 	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
 
 	apic_printk(APIC_QUIET, KERN_INFO
 		    "...trying to set up timer as ExtINT IRQ...\n");
 
-	init_8259A(0);
-	make_8259A_irq(0);
+	legacy_pic->init(0);
+	legacy_pic->make_irq(0);
 	apic_write(APIC_LVT0, APIC_DM_EXTINT);
 
 	unlock_ExtINT_logic();
@@ -3078,7 +3125,7 @@
 	/*
 	 * calling enable_IO_APIC() is moved to setup_local_APIC for BP
 	 */
-	io_apic_irqs = nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
+	io_apic_irqs = legacy_pic->nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
 
 	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
 	/*
@@ -3089,7 +3136,7 @@
 	sync_Arb_IDs();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
-	if (nr_legacy_irqs)
+	if (legacy_pic->nr_legacy_irqs)
 		check_timer();
 }
 
@@ -3138,13 +3185,13 @@
 	data = container_of(dev, struct sysfs_ioapic_data, dev);
 	entry = data->entry;
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	reg_00.raw = io_apic_read(dev->id, 0);
 	if (reg_00.bits.ID != mp_ioapics[dev->id].apicid) {
 		reg_00.bits.ID = mp_ioapics[dev->id].apicid;
 		io_apic_write(dev->id, 0, reg_00.raw);
 	}
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
 		ioapic_write_entry(dev->id, i, entry[i]);
 
@@ -3207,7 +3254,7 @@
 	if (irq_want < nr_irqs_gsi)
 		irq_want = nr_irqs_gsi;
 
-	spin_lock_irqsave(&vector_lock, flags);
+	raw_spin_lock_irqsave(&vector_lock, flags);
 	for (new = irq_want; new < nr_irqs; new++) {
 		desc_new = irq_to_desc_alloc_node(new, node);
 		if (!desc_new) {
@@ -3226,14 +3273,11 @@
 			irq = new;
 		break;
 	}
-	spin_unlock_irqrestore(&vector_lock, flags);
+	raw_spin_unlock_irqrestore(&vector_lock, flags);
 
-	if (irq > 0) {
-		dynamic_irq_init(irq);
-		/* restore it, in case dynamic_irq_init clear it */
-		if (desc_new)
-			desc_new->chip_data = cfg_new;
-	}
+	if (irq > 0)
+		dynamic_irq_init_keep_chip_data(irq);
+
 	return irq;
 }
 
@@ -3255,20 +3299,13 @@
 void destroy_irq(unsigned int irq)
 {
 	unsigned long flags;
-	struct irq_cfg *cfg;
-	struct irq_desc *desc;
 
-	/* store it, in case dynamic_irq_cleanup clear it */
-	desc = irq_to_desc(irq);
-	cfg = desc->chip_data;
-	dynamic_irq_cleanup(irq);
-	/* connect back irq_cfg */
-	desc->chip_data = cfg;
+	dynamic_irq_cleanup_keep_chip_data(irq);
 
 	free_irte(irq);
-	spin_lock_irqsave(&vector_lock, flags);
-	__clear_irq_vector(irq, cfg);
-	spin_unlock_irqrestore(&vector_lock, flags);
+	raw_spin_lock_irqsave(&vector_lock, flags);
+	__clear_irq_vector(irq, get_irq_chip_data(irq));
+	raw_spin_unlock_irqrestore(&vector_lock, flags);
 }
 
 /*
@@ -3805,9 +3842,9 @@
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	reg_01.raw = io_apic_read(ioapic, 1);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	return reg_01.bits.entries;
 }
@@ -3890,7 +3927,7 @@
 	/*
 	 * IRQs < 16 are already in the irq_2_pin[] map
 	 */
-	if (irq >= nr_legacy_irqs) {
+	if (irq >= legacy_pic->nr_legacy_irqs) {
 		cfg = desc->chip_data;
 		if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) {
 			printk(KERN_INFO "can not add pin %d for irq %d\n",
@@ -3969,9 +4006,9 @@
 	if (physids_empty(apic_id_map))
 		apic->ioapic_phys_id_map(&phys_cpu_present_map, &apic_id_map);
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	reg_00.raw = io_apic_read(ioapic, 0);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	if (apic_id >= get_physical_broadcast()) {
 		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
@@ -4005,10 +4042,10 @@
 	if (reg_00.bits.ID != apic_id) {
 		reg_00.bits.ID = apic_id;
 
-		spin_lock_irqsave(&ioapic_lock, flags);
+		raw_spin_lock_irqsave(&ioapic_lock, flags);
 		io_apic_write(ioapic, 0, reg_00.raw);
 		reg_00.raw = io_apic_read(ioapic, 0);
-		spin_unlock_irqrestore(&ioapic_lock, flags);
+		raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 		/* Sanity check */
 		if (reg_00.bits.ID != apic_id) {
@@ -4029,9 +4066,9 @@
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
 
-	spin_lock_irqsave(&ioapic_lock, flags);
+	raw_spin_lock_irqsave(&ioapic_lock, flags);
 	reg_01.raw = io_apic_read(ioapic, 1);
-	spin_unlock_irqrestore(&ioapic_lock, flags);
+	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	return reg_01.bits.version;
 }
@@ -4063,27 +4100,23 @@
 #ifdef CONFIG_SMP
 void __init setup_ioapic_dest(void)
 {
-	int pin, ioapic = 0, irq, irq_entry;
+	int pin, ioapic, irq, irq_entry;
 	struct irq_desc *desc;
 	const struct cpumask *mask;
 
 	if (skip_ioapic_setup == 1)
 		return;
 
-#ifdef CONFIG_ACPI
-	if (!acpi_disabled && acpi_ioapic) {
-		ioapic = mp_find_ioapic(0);
-		if (ioapic < 0)
-			ioapic = 0;
-	}
-#endif
-
+	for (ioapic = 0; ioapic < nr_ioapics; ioapic++)
 	for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
 		irq_entry = find_irq_entry(ioapic, pin, mp_INT);
 		if (irq_entry == -1)
 			continue;
 		irq = pin_2_irq(irq_entry, ioapic, pin);
 
+		if ((ioapic > 0) && (irq > 16))
+			continue;
+
 		desc = irq_to_desc(irq);
 
 		/*
@@ -4268,3 +4301,24 @@
 
 	nr_ioapics++;
 }
+
+/* Enable IOAPIC early just for system timer */
+void __init pre_init_apic_IRQ0(void)
+{
+	struct irq_cfg *cfg;
+	struct irq_desc *desc;
+
+	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);
+#endif
+	desc = irq_to_desc_alloc_node(0, 0);
+
+	setup_local_APIC();
+
+	cfg = irq_cfg(0);
+	add_pin_to_irq_node(cfg, 0, 0, 0);
+	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
+
+	setup_IO_APIC_irq(0, 0, 0, desc, 0, 0);
+}
diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c
index 0159a69..8aa65ad 100644
--- a/arch/x86/kernel/apic/nmi.c
+++ b/arch/x86/kernel/apic/nmi.c
@@ -177,7 +177,7 @@
 error:
 	if (nmi_watchdog == NMI_IO_APIC) {
 		if (!timer_through_8259)
-			disable_8259A_irq(0);
+			legacy_pic->chip->mask(0);
 		on_each_cpu(__acpi_nmi_disable, NULL, 1);
 	}
 
@@ -416,13 +416,13 @@
 
 	/* We can be called before check_nmi_watchdog, hence NULL check. */
 	if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
-		static DEFINE_SPINLOCK(lock);	/* Serialise the printks */
+		static DEFINE_RAW_SPINLOCK(lock); /* Serialise the printks */
 
-		spin_lock(&lock);
+		raw_spin_lock(&lock);
 		printk(KERN_WARNING "NMI backtrace for cpu %d\n", cpu);
 		show_regs(regs);
 		dump_stack();
-		spin_unlock(&lock);
+		raw_spin_unlock(&lock);
 		cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
 
 		rc = 1;
@@ -438,8 +438,8 @@
 		 * Ayiee, looks like this CPU is stuck ...
 		 * wait a few IRQs (5 seconds) before doing the oops ...
 		 */
-		__this_cpu_inc(per_cpu_var(alert_counter));
-		if (__this_cpu_read(per_cpu_var(alert_counter)) == 5 * nmi_hz)
+		__this_cpu_inc(alert_counter);
+		if (__this_cpu_read(alert_counter) == 5 * nmi_hz)
 			/*
 			 * die_nmi will return ONLY if NOTIFY_STOP happens..
 			 */
@@ -447,7 +447,7 @@
 				regs, panic_on_timeout);
 	} else {
 		__get_cpu_var(last_irq_sum) = sum;
-		__this_cpu_write(per_cpu_var(alert_counter), 0);
+		__this_cpu_write(alert_counter, 0);
 	}
 
 	/* see if the nmi watchdog went off */
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
index 47dd856..3e28401 100644
--- a/arch/x86/kernel/apic/numaq_32.c
+++ b/arch/x86/kernel/apic/numaq_32.c
@@ -277,6 +277,7 @@
 		x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus;
 		x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info;
 		x86_init.timers.tsc_pre_init = numaq_tsc_init;
+		x86_init.pci.init = pci_numaq_init;
 	}
 }
 
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 3740c8a..49dbeae 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -120,11 +120,9 @@
 unsigned long sn_rtc_cycles_per_second;
 EXPORT_SYMBOL(sn_rtc_cycles_per_second);
 
-/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
-
 static const struct cpumask *uv_target_cpus(void)
 {
-	return cpumask_of(0);
+	return cpu_online_mask;
 }
 
 static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask)
diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig b/arch/x86/kernel/cpu/cpufreq/Kconfig
index f138c6c..870e6cc 100644
--- a/arch/x86/kernel/cpu/cpufreq/Kconfig
+++ b/arch/x86/kernel/cpu/cpufreq/Kconfig
@@ -10,6 +10,20 @@
 
 comment "CPUFreq processor drivers"
 
+config X86_PCC_CPUFREQ
+	tristate "Processor Clocking Control interface driver"
+	depends on ACPI && ACPI_PROCESSOR
+	help
+	  This driver adds support for the PCC interface.
+
+	  For details, take a look at:
+	  <file:Documentation/cpu-freq/pcc-cpufreq.txt>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pcc-cpufreq.
+
+	  If in doubt, say N.
+
 config X86_ACPI_CPUFREQ
 	tristate "ACPI Processor P-States driver"
 	select CPU_FREQ_TABLE
diff --git a/arch/x86/kernel/cpu/cpufreq/Makefile b/arch/x86/kernel/cpu/cpufreq/Makefile
index 509296d..1840c0a 100644
--- a/arch/x86/kernel/cpu/cpufreq/Makefile
+++ b/arch/x86/kernel/cpu/cpufreq/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_X86_POWERNOW_K8)		+= powernow-k8.o
 obj-$(CONFIG_X86_ACPI_CPUFREQ)		+= acpi-cpufreq.o
+obj-$(CONFIG_X86_PCC_CPUFREQ)		+= pcc-cpufreq.o
 obj-$(CONFIG_X86_POWERNOW_K6)		+= powernow-k6.o
 obj-$(CONFIG_X86_POWERNOW_K7)		+= powernow-k7.o
 obj-$(CONFIG_X86_LONGHAUL)		+= longhaul.o
diff --git a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
new file mode 100644
index 0000000..ff36d29
--- /dev/null
+++ b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
@@ -0,0 +1,620 @@
+/*
+ *  pcc-cpufreq.c - Processor Clocking Control firmware cpufreq interface
+ *
+ *  Copyright (C) 2009 Red Hat, Matthew Garrett <mjg@redhat.com>
+ *  Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ *	Nagananda Chumbalkar <nagananda.chumbalkar@hp.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; 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, GOOD TITLE or NON
+ *  INFRINGEMENT. See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/compiler.h>
+
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+
+#include <acpi/processor.h>
+
+#define PCC_VERSION 	"1.00.00"
+#define POLL_LOOPS 	300
+
+#define CMD_COMPLETE 	0x1
+#define CMD_GET_FREQ 	0x0
+#define CMD_SET_FREQ 	0x1
+
+#define BUF_SZ		4
+
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER,	\
+					     "pcc-cpufreq", msg)
+
+struct pcc_register_resource {
+	u8 descriptor;
+	u16 length;
+	u8 space_id;
+	u8 bit_width;
+	u8 bit_offset;
+	u8 access_size;
+	u64 address;
+} __attribute__ ((packed));
+
+struct pcc_memory_resource {
+	u8 descriptor;
+	u16 length;
+	u8 space_id;
+	u8 resource_usage;
+	u8 type_specific;
+	u64 granularity;
+	u64 minimum;
+	u64 maximum;
+	u64 translation_offset;
+	u64 address_length;
+} __attribute__ ((packed));
+
+static struct cpufreq_driver pcc_cpufreq_driver;
+
+struct pcc_header {
+	u32 signature;
+	u16 length;
+	u8 major;
+	u8 minor;
+	u32 features;
+	u16 command;
+	u16 status;
+	u32 latency;
+	u32 minimum_time;
+	u32 maximum_time;
+	u32 nominal;
+	u32 throttled_frequency;
+	u32 minimum_frequency;
+};
+
+static void __iomem *pcch_virt_addr;
+static struct pcc_header __iomem *pcch_hdr;
+
+static DEFINE_SPINLOCK(pcc_lock);
+
+static struct acpi_generic_address doorbell;
+
+static u64 doorbell_preserve;
+static u64 doorbell_write;
+
+static u8 OSC_UUID[16] = {0x63, 0x9B, 0x2C, 0x9F, 0x70, 0x91, 0x49, 0x1f,
+			  0xBB, 0x4F, 0xA5, 0x98, 0x2F, 0xA1, 0xB5, 0x46};
+
+struct pcc_cpu {
+	u32 input_offset;
+	u32 output_offset;
+};
+
+static struct pcc_cpu *pcc_cpu_info;
+
+static int pcc_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+				     policy->cpuinfo.max_freq);
+	return 0;
+}
+
+static inline void pcc_cmd(void)
+{
+	u64 doorbell_value;
+	int i;
+
+	acpi_read(&doorbell_value, &doorbell);
+	acpi_write((doorbell_value & doorbell_preserve) | doorbell_write,
+		   &doorbell);
+
+	for (i = 0; i < POLL_LOOPS; i++) {
+		if (ioread16(&pcch_hdr->status) & CMD_COMPLETE)
+			break;
+	}
+}
+
+static inline void pcc_clear_mapping(void)
+{
+	if (pcch_virt_addr)
+		iounmap(pcch_virt_addr);
+	pcch_virt_addr = NULL;
+}
+
+static unsigned int pcc_get_freq(unsigned int cpu)
+{
+	struct pcc_cpu *pcc_cpu_data;
+	unsigned int curr_freq;
+	unsigned int freq_limit;
+	u16 status;
+	u32 input_buffer;
+	u32 output_buffer;
+
+	spin_lock(&pcc_lock);
+
+	dprintk("get: get_freq for CPU %d\n", cpu);
+	pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu);
+
+	input_buffer = 0x1;
+	iowrite32(input_buffer,
+			(pcch_virt_addr + pcc_cpu_data->input_offset));
+	iowrite16(CMD_GET_FREQ, &pcch_hdr->command);
+
+	pcc_cmd();
+
+	output_buffer =
+		ioread32(pcch_virt_addr + pcc_cpu_data->output_offset);
+
+	/* Clear the input buffer - we are done with the current command */
+	memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ);
+
+	status = ioread16(&pcch_hdr->status);
+	if (status != CMD_COMPLETE) {
+		dprintk("get: FAILED: for CPU %d, status is %d\n",
+			cpu, status);
+		goto cmd_incomplete;
+	}
+	iowrite16(0, &pcch_hdr->status);
+	curr_freq = (((ioread32(&pcch_hdr->nominal) * (output_buffer & 0xff))
+			/ 100) * 1000);
+
+	dprintk("get: SUCCESS: (virtual) output_offset for cpu %d is "
+		"0x%x, contains a value of: 0x%x. Speed is: %d MHz\n",
+		cpu, (pcch_virt_addr + pcc_cpu_data->output_offset),
+		output_buffer, curr_freq);
+
+	freq_limit = (output_buffer >> 8) & 0xff;
+	if (freq_limit != 0xff) {
+		dprintk("get: frequency for cpu %d is being temporarily"
+			" capped at %d\n", cpu, curr_freq);
+	}
+
+	spin_unlock(&pcc_lock);
+	return curr_freq;
+
+cmd_incomplete:
+	iowrite16(0, &pcch_hdr->status);
+	spin_unlock(&pcc_lock);
+	return -EINVAL;
+}
+
+static int pcc_cpufreq_target(struct cpufreq_policy *policy,
+			      unsigned int target_freq,
+			      unsigned int relation)
+{
+	struct pcc_cpu *pcc_cpu_data;
+	struct cpufreq_freqs freqs;
+	u16 status;
+	u32 input_buffer;
+	int cpu;
+
+	spin_lock(&pcc_lock);
+	cpu = policy->cpu;
+	pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu);
+
+	dprintk("target: CPU %d should go to target freq: %d "
+		"(virtual) input_offset is 0x%x\n",
+		cpu, target_freq,
+		(pcch_virt_addr + pcc_cpu_data->input_offset));
+
+	freqs.new = target_freq;
+	freqs.cpu = cpu;
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	input_buffer = 0x1 | (((target_freq * 100)
+			       / (ioread32(&pcch_hdr->nominal) * 1000)) << 8);
+	iowrite32(input_buffer,
+			(pcch_virt_addr + pcc_cpu_data->input_offset));
+	iowrite16(CMD_SET_FREQ, &pcch_hdr->command);
+
+	pcc_cmd();
+
+	/* Clear the input buffer - we are done with the current command */
+	memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ);
+
+	status = ioread16(&pcch_hdr->status);
+	if (status != CMD_COMPLETE) {
+		dprintk("target: FAILED for cpu %d, with status: 0x%x\n",
+			cpu, status);
+		goto cmd_incomplete;
+	}
+	iowrite16(0, &pcch_hdr->status);
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	dprintk("target: was SUCCESSFUL for cpu %d\n", cpu);
+	spin_unlock(&pcc_lock);
+
+	return 0;
+
+cmd_incomplete:
+	iowrite16(0, &pcch_hdr->status);
+	spin_unlock(&pcc_lock);
+	return -EINVAL;
+}
+
+static int pcc_get_offset(int cpu)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *pccp, *offset;
+	struct pcc_cpu *pcc_cpu_data;
+	struct acpi_processor *pr;
+	int ret = 0;
+
+	pr = per_cpu(processors, cpu);
+	pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu);
+
+	status = acpi_evaluate_object(pr->handle, "PCCP", NULL, &buffer);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	pccp = buffer.pointer;
+	if (!pccp || pccp->type != ACPI_TYPE_PACKAGE) {
+		ret = -ENODEV;
+		goto out_free;
+	};
+
+	offset = &(pccp->package.elements[0]);
+	if (!offset || offset->type != ACPI_TYPE_INTEGER) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	pcc_cpu_data->input_offset = offset->integer.value;
+
+	offset = &(pccp->package.elements[1]);
+	if (!offset || offset->type != ACPI_TYPE_INTEGER) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	pcc_cpu_data->output_offset = offset->integer.value;
+
+	memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ);
+	memset_io((pcch_virt_addr + pcc_cpu_data->output_offset), 0, BUF_SZ);
+
+	dprintk("pcc_get_offset: for CPU %d: pcc_cpu_data "
+		"input_offset: 0x%x, pcc_cpu_data output_offset: 0x%x\n",
+		cpu, pcc_cpu_data->input_offset, pcc_cpu_data->output_offset);
+out_free:
+	kfree(buffer.pointer);
+	return ret;
+}
+
+static int __init pcc_cpufreq_do_osc(acpi_handle *handle)
+{
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object in_params[4];
+	union acpi_object *out_obj;
+	u32 capabilities[2];
+	u32 errors;
+	u32 supported;
+	int ret = 0;
+
+	input.count = 4;
+	input.pointer = in_params;
+	input.count = 4;
+	input.pointer = in_params;
+	in_params[0].type               = ACPI_TYPE_BUFFER;
+	in_params[0].buffer.length      = 16;
+	in_params[0].buffer.pointer     = OSC_UUID;
+	in_params[1].type               = ACPI_TYPE_INTEGER;
+	in_params[1].integer.value      = 1;
+	in_params[2].type               = ACPI_TYPE_INTEGER;
+	in_params[2].integer.value      = 2;
+	in_params[3].type               = ACPI_TYPE_BUFFER;
+	in_params[3].buffer.length      = 8;
+	in_params[3].buffer.pointer     = (u8 *)&capabilities;
+
+	capabilities[0] = OSC_QUERY_ENABLE;
+	capabilities[1] = 0x1;
+
+	status = acpi_evaluate_object(*handle, "_OSC", &input, &output);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	if (!output.length)
+		return -ENODEV;
+
+	out_obj = output.pointer;
+	if (out_obj->type != ACPI_TYPE_BUFFER) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
+	if (errors) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	supported = *((u32 *)(out_obj->buffer.pointer + 4));
+	if (!(supported & 0x1)) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	kfree(output.pointer);
+	capabilities[0] = 0x0;
+	capabilities[1] = 0x1;
+
+	status = acpi_evaluate_object(*handle, "_OSC", &input, &output);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	if (!output.length)
+		return -ENODEV;
+
+	out_obj = output.pointer;
+	if (out_obj->type != ACPI_TYPE_BUFFER) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
+	if (errors) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	supported = *((u32 *)(out_obj->buffer.pointer + 4));
+	if (!(supported & 0x1)) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+out_free:
+	kfree(output.pointer);
+	return ret;
+}
+
+static int __init pcc_cpufreq_probe(void)
+{
+	acpi_status status;
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	struct pcc_memory_resource *mem_resource;
+	struct pcc_register_resource *reg_resource;
+	union acpi_object *out_obj, *member;
+	acpi_handle handle, osc_handle;
+	int ret = 0;
+
+	status = acpi_get_handle(NULL, "\\_SB", &handle);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	status = acpi_get_handle(handle, "_OSC", &osc_handle);
+	if (ACPI_SUCCESS(status)) {
+		ret = pcc_cpufreq_do_osc(&osc_handle);
+		if (ret)
+			dprintk("probe: _OSC evaluation did not succeed\n");
+		/* Firmware's use of _OSC is optional */
+		ret = 0;
+	}
+
+	status = acpi_evaluate_object(handle, "PCCH", NULL, &output);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	out_obj = output.pointer;
+	if (out_obj->type != ACPI_TYPE_PACKAGE) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	member = &out_obj->package.elements[0];
+	if (member->type != ACPI_TYPE_BUFFER) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	mem_resource = (struct pcc_memory_resource *)member->buffer.pointer;
+
+	dprintk("probe: mem_resource descriptor: 0x%x,"
+		" length: %d, space_id: %d, resource_usage: %d,"
+		" type_specific: %d, granularity: 0x%llx,"
+		" minimum: 0x%llx, maximum: 0x%llx,"
+		" translation_offset: 0x%llx, address_length: 0x%llx\n",
+		mem_resource->descriptor, mem_resource->length,
+		mem_resource->space_id, mem_resource->resource_usage,
+		mem_resource->type_specific, mem_resource->granularity,
+		mem_resource->minimum, mem_resource->maximum,
+		mem_resource->translation_offset,
+		mem_resource->address_length);
+
+	if (mem_resource->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	pcch_virt_addr = ioremap_nocache(mem_resource->minimum,
+					mem_resource->address_length);
+	if (pcch_virt_addr == NULL) {
+		dprintk("probe: could not map shared mem region\n");
+		goto out_free;
+	}
+	pcch_hdr = pcch_virt_addr;
+
+	dprintk("probe: PCCH header (virtual) addr: 0x%p\n", pcch_hdr);
+	dprintk("probe: PCCH header is at physical address: 0x%llx,"
+		" signature: 0x%x, length: %d bytes, major: %d, minor: %d,"
+		" supported features: 0x%x, command field: 0x%x,"
+		" status field: 0x%x, nominal latency: %d us\n",
+		mem_resource->minimum, ioread32(&pcch_hdr->signature),
+		ioread16(&pcch_hdr->length), ioread8(&pcch_hdr->major),
+		ioread8(&pcch_hdr->minor), ioread32(&pcch_hdr->features),
+		ioread16(&pcch_hdr->command), ioread16(&pcch_hdr->status),
+		ioread32(&pcch_hdr->latency));
+
+	dprintk("probe: min time between commands: %d us,"
+		" max time between commands: %d us,"
+		" nominal CPU frequency: %d MHz,"
+		" minimum CPU frequency: %d MHz,"
+		" minimum CPU frequency without throttling: %d MHz\n",
+		ioread32(&pcch_hdr->minimum_time),
+		ioread32(&pcch_hdr->maximum_time),
+		ioread32(&pcch_hdr->nominal),
+		ioread32(&pcch_hdr->throttled_frequency),
+		ioread32(&pcch_hdr->minimum_frequency));
+
+	member = &out_obj->package.elements[1];
+	if (member->type != ACPI_TYPE_BUFFER) {
+		ret = -ENODEV;
+		goto pcch_free;
+	}
+
+	reg_resource = (struct pcc_register_resource *)member->buffer.pointer;
+
+	doorbell.space_id = reg_resource->space_id;
+	doorbell.bit_width = reg_resource->bit_width;
+	doorbell.bit_offset = reg_resource->bit_offset;
+	doorbell.access_width = 64;
+	doorbell.address = reg_resource->address;
+
+	dprintk("probe: doorbell: space_id is %d, bit_width is %d, "
+		"bit_offset is %d, access_width is %d, address is 0x%llx\n",
+		doorbell.space_id, doorbell.bit_width, doorbell.bit_offset,
+		doorbell.access_width, reg_resource->address);
+
+	member = &out_obj->package.elements[2];
+	if (member->type != ACPI_TYPE_INTEGER) {
+		ret = -ENODEV;
+		goto pcch_free;
+	}
+
+	doorbell_preserve = member->integer.value;
+
+	member = &out_obj->package.elements[3];
+	if (member->type != ACPI_TYPE_INTEGER) {
+		ret = -ENODEV;
+		goto pcch_free;
+	}
+
+	doorbell_write = member->integer.value;
+
+	dprintk("probe: doorbell_preserve: 0x%llx,"
+		" doorbell_write: 0x%llx\n",
+		doorbell_preserve, doorbell_write);
+
+	pcc_cpu_info = alloc_percpu(struct pcc_cpu);
+	if (!pcc_cpu_info) {
+		ret = -ENOMEM;
+		goto pcch_free;
+	}
+
+	printk(KERN_DEBUG "pcc-cpufreq: (v%s) driver loaded with frequency"
+	       " limits: %d MHz, %d MHz\n", PCC_VERSION,
+	       ioread32(&pcch_hdr->minimum_frequency),
+	       ioread32(&pcch_hdr->nominal));
+	kfree(output.pointer);
+	return ret;
+pcch_free:
+	pcc_clear_mapping();
+out_free:
+	kfree(output.pointer);
+	return ret;
+}
+
+static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	unsigned int cpu = policy->cpu;
+	unsigned int result = 0;
+
+	if (!pcch_virt_addr) {
+		result = -1;
+		goto pcch_null;
+	}
+
+	result = pcc_get_offset(cpu);
+	if (result) {
+		dprintk("init: PCCP evaluation failed\n");
+		goto free;
+	}
+
+	policy->max = policy->cpuinfo.max_freq =
+		ioread32(&pcch_hdr->nominal) * 1000;
+	policy->min = policy->cpuinfo.min_freq =
+		ioread32(&pcch_hdr->minimum_frequency) * 1000;
+	policy->cur = pcc_get_freq(cpu);
+
+	dprintk("init: policy->max is %d, policy->min is %d\n",
+		policy->max, policy->min);
+
+	return 0;
+free:
+	pcc_clear_mapping();
+	free_percpu(pcc_cpu_info);
+pcch_null:
+	return result;
+}
+
+static int pcc_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+
+static struct cpufreq_driver pcc_cpufreq_driver = {
+	.flags = CPUFREQ_CONST_LOOPS,
+	.get = pcc_get_freq,
+	.verify = pcc_cpufreq_verify,
+	.target = pcc_cpufreq_target,
+	.init = pcc_cpufreq_cpu_init,
+	.exit = pcc_cpufreq_cpu_exit,
+	.name = "pcc-cpufreq",
+	.owner = THIS_MODULE,
+};
+
+static int __init pcc_cpufreq_init(void)
+{
+	int ret;
+
+	if (acpi_disabled)
+		return 0;
+
+	ret = pcc_cpufreq_probe();
+	if (ret) {
+		dprintk("pcc_cpufreq_init: PCCH evaluation failed\n");
+		return ret;
+	}
+
+	ret = cpufreq_register_driver(&pcc_cpufreq_driver);
+
+	return ret;
+}
+
+static void __exit pcc_cpufreq_exit(void)
+{
+	cpufreq_unregister_driver(&pcc_cpufreq_driver);
+
+	pcc_clear_mapping();
+
+	free_percpu(pcc_cpu_info);
+}
+
+MODULE_AUTHOR("Matthew Garrett, Naga Chumbalkar");
+MODULE_VERSION(PCC_VERSION);
+MODULE_DESCRIPTION("Processor Clocking Control interface driver");
+MODULE_LICENSE("GPL");
+
+late_initcall(pcc_cpufreq_init);
+module_exit(pcc_cpufreq_exit);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 879666f..7e1cca1 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -70,7 +70,8 @@
 	if (c->x86_power & (1 << 8)) {
 		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
 		set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
-		sched_clock_stable = 1;
+		if (!check_tsc_unstable())
+			sched_clock_stable = 1;
 	}
 
 	/*
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index eddb1bd..b3eeb66 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -903,7 +903,7 @@
 	return ret;
 }
 
-static struct sysfs_ops sysfs_ops = {
+static const struct sysfs_ops sysfs_ops = {
 	.show   = show,
 	.store  = store,
 };
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index a8aacd4..bd58de4 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -46,6 +46,11 @@
 
 #include "mce-internal.h"
 
+#define rcu_dereference_check_mce(p) \
+	rcu_dereference_check((p), \
+			      rcu_read_lock_sched_held() || \
+			      lockdep_is_held(&mce_read_mutex))
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/mce.h>
 
@@ -158,7 +163,7 @@
 	mce->finished = 0;
 	wmb();
 	for (;;) {
-		entry = rcu_dereference(mcelog.next);
+		entry = rcu_dereference_check_mce(mcelog.next);
 		for (;;) {
 			/*
 			 * When the buffer fills up discard new entries.
@@ -1500,7 +1505,7 @@
 		return -ENOMEM;
 
 	mutex_lock(&mce_read_mutex);
-	next = rcu_dereference(mcelog.next);
+	next = rcu_dereference_check_mce(mcelog.next);
 
 	/* Only supports full reads right now */
 	if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) {
@@ -1565,7 +1570,7 @@
 static unsigned int mce_poll(struct file *file, poll_table *wait)
 {
 	poll_wait(file, &mce_wait, wait);
-	if (rcu_dereference(mcelog.next))
+	if (rcu_dereference_check_mce(mcelog.next))
 		return POLLIN | POLLRDNORM;
 	return 0;
 }
@@ -2044,6 +2049,7 @@
 		struct mce_bank *b = &mce_banks[i];
 		struct sysdev_attribute *a = &b->attr;
 
+		sysfs_attr_init(&a->attr);
 		a->attr.name	= b->attrname;
 		snprintf(b->attrname, ATTR_LEN, "bank%d", i);
 
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 83a3d1f..cda932c 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -388,7 +388,7 @@
 	return ret;
 }
 
-static struct sysfs_ops threshold_ops = {
+static const struct sysfs_ops threshold_ops = {
 	.show			= show,
 	.store			= store,
 };
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 7c78563..d15df6e 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -95,7 +95,7 @@
 
 		/* Already owned by someone else? */
 		if (val & CMCI_EN) {
-			if (test_and_clear_bit(i, owned) || boot)
+			if (test_and_clear_bit(i, owned) && !boot)
 				print_update("SHD", &hdr, i);
 			__clear_bit(i, __get_cpu_var(mce_poll_banks));
 			continue;
@@ -107,7 +107,7 @@
 
 		/* Did the enable bit stick? -- the bank supports CMCI */
 		if (val & CMCI_EN) {
-			if (!test_and_set_bit(i, owned) || boot)
+			if (!test_and_set_bit(i, owned) && !boot)
 				print_update("CMCI", &hdr, i);
 			__clear_bit(i, __get_cpu_var(mce_poll_banks));
 		} else {
diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c
index 09b1698..06130b5 100644
--- a/arch/x86/kernel/cpu/mtrr/cleanup.c
+++ b/arch/x86/kernel/cpu/mtrr/cleanup.c
@@ -22,10 +22,10 @@
 #include <linux/pci.h>
 #include <linux/smp.h>
 #include <linux/cpu.h>
-#include <linux/sort.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/kvm_para.h>
+#include <linux/range.h>
 
 #include <asm/processor.h>
 #include <asm/e820.h>
@@ -34,11 +34,6 @@
 
 #include "mtrr.h"
 
-struct res_range {
-	unsigned long	start;
-	unsigned long	end;
-};
-
 struct var_mtrr_range_state {
 	unsigned long	base_pfn;
 	unsigned long	size_pfn;
@@ -56,7 +51,7 @@
 /* Should be related to MTRR_VAR_RANGES nums */
 #define RANGE_NUM				256
 
-static struct res_range __initdata		range[RANGE_NUM];
+static struct range __initdata		range[RANGE_NUM];
 static int __initdata				nr_range;
 
 static struct var_mtrr_range_state __initdata	range_state[RANGE_NUM];
@@ -64,152 +59,11 @@
 static int __initdata debug_print;
 #define Dprintk(x...) do { if (debug_print) printk(KERN_DEBUG x); } while (0)
 
-
-static int __init
-add_range(struct res_range *range, int nr_range,
-	  unsigned long start, unsigned long end)
-{
-	/* Out of slots: */
-	if (nr_range >= RANGE_NUM)
-		return nr_range;
-
-	range[nr_range].start = start;
-	range[nr_range].end = end;
-
-	nr_range++;
-
-	return nr_range;
-}
-
-static int __init
-add_range_with_merge(struct res_range *range, int nr_range,
-		     unsigned long start, unsigned long end)
-{
-	int i;
-
-	/* Try to merge it with old one: */
-	for (i = 0; i < nr_range; i++) {
-		unsigned long final_start, final_end;
-		unsigned long common_start, common_end;
-
-		if (!range[i].end)
-			continue;
-
-		common_start = max(range[i].start, start);
-		common_end = min(range[i].end, end);
-		if (common_start > common_end + 1)
-			continue;
-
-		final_start = min(range[i].start, start);
-		final_end = max(range[i].end, end);
-
-		range[i].start = final_start;
-		range[i].end =  final_end;
-		return nr_range;
-	}
-
-	/* Need to add it: */
-	return add_range(range, nr_range, start, end);
-}
-
-static void __init
-subtract_range(struct res_range *range, unsigned long start, unsigned long end)
-{
-	int i, j;
-
-	for (j = 0; j < RANGE_NUM; j++) {
-		if (!range[j].end)
-			continue;
-
-		if (start <= range[j].start && end >= range[j].end) {
-			range[j].start = 0;
-			range[j].end = 0;
-			continue;
-		}
-
-		if (start <= range[j].start && end < range[j].end &&
-		    range[j].start < end + 1) {
-			range[j].start = end + 1;
-			continue;
-		}
-
-
-		if (start > range[j].start && end >= range[j].end &&
-		    range[j].end > start - 1) {
-			range[j].end = start - 1;
-			continue;
-		}
-
-		if (start > range[j].start && end < range[j].end) {
-			/* Find the new spare: */
-			for (i = 0; i < RANGE_NUM; i++) {
-				if (range[i].end == 0)
-					break;
-			}
-			if (i < RANGE_NUM) {
-				range[i].end = range[j].end;
-				range[i].start = end + 1;
-			} else {
-				printk(KERN_ERR "run of slot in ranges\n");
-			}
-			range[j].end = start - 1;
-			continue;
-		}
-	}
-}
-
-static int __init cmp_range(const void *x1, const void *x2)
-{
-	const struct res_range *r1 = x1;
-	const struct res_range *r2 = x2;
-	long start1, start2;
-
-	start1 = r1->start;
-	start2 = r2->start;
-
-	return start1 - start2;
-}
-
-static int __init clean_sort_range(struct res_range *range, int az)
-{
-	int i, j, k = az - 1, nr_range = 0;
-
-	for (i = 0; i < k; i++) {
-		if (range[i].end)
-			continue;
-		for (j = k; j > i; j--) {
-			if (range[j].end) {
-				k = j;
-				break;
-			}
-		}
-		if (j == i)
-			break;
-		range[i].start = range[k].start;
-		range[i].end   = range[k].end;
-		range[k].start = 0;
-		range[k].end   = 0;
-		k--;
-	}
-	/* count it */
-	for (i = 0; i < az; i++) {
-		if (!range[i].end) {
-			nr_range = i;
-			break;
-		}
-	}
-
-	/* sort them */
-	sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL);
-
-	return nr_range;
-}
-
 #define BIOS_BUG_MSG KERN_WARNING \
 	"WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n"
 
 static int __init
-x86_get_mtrr_mem_range(struct res_range *range, int nr_range,
+x86_get_mtrr_mem_range(struct range *range, int nr_range,
 		       unsigned long extra_remove_base,
 		       unsigned long extra_remove_size)
 {
@@ -223,14 +77,14 @@
 			continue;
 		base = range_state[i].base_pfn;
 		size = range_state[i].size_pfn;
-		nr_range = add_range_with_merge(range, nr_range, base,
-						base + size - 1);
+		nr_range = add_range_with_merge(range, RANGE_NUM, nr_range,
+						base, base + size);
 	}
 	if (debug_print) {
 		printk(KERN_DEBUG "After WB checking\n");
 		for (i = 0; i < nr_range; i++)
-			printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n",
-				 range[i].start, range[i].end + 1);
+			printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n",
+				 range[i].start, range[i].end);
 	}
 
 	/* Take out UC ranges: */
@@ -252,19 +106,19 @@
 			size -= (1<<(20-PAGE_SHIFT)) - base;
 			base = 1<<(20-PAGE_SHIFT);
 		}
-		subtract_range(range, base, base + size - 1);
+		subtract_range(range, RANGE_NUM, base, base + size);
 	}
 	if (extra_remove_size)
-		subtract_range(range, extra_remove_base,
-				 extra_remove_base + extra_remove_size  - 1);
+		subtract_range(range, RANGE_NUM, extra_remove_base,
+				 extra_remove_base + extra_remove_size);
 
 	if  (debug_print) {
 		printk(KERN_DEBUG "After UC checking\n");
 		for (i = 0; i < RANGE_NUM; i++) {
 			if (!range[i].end)
 				continue;
-			printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n",
-				 range[i].start, range[i].end + 1);
+			printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n",
+				 range[i].start, range[i].end);
 		}
 	}
 
@@ -273,26 +127,22 @@
 	if  (debug_print) {
 		printk(KERN_DEBUG "After sorting\n");
 		for (i = 0; i < nr_range; i++)
-			printk(KERN_DEBUG "MTRR MAP PFN: %016lx - %016lx\n",
-				 range[i].start, range[i].end + 1);
+			printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n",
+				 range[i].start, range[i].end);
 	}
 
-	/* clear those is not used */
-	for (i = nr_range; i < RANGE_NUM; i++)
-		memset(&range[i], 0, sizeof(range[i]));
-
 	return nr_range;
 }
 
 #ifdef CONFIG_MTRR_SANITIZER
 
-static unsigned long __init sum_ranges(struct res_range *range, int nr_range)
+static unsigned long __init sum_ranges(struct range *range, int nr_range)
 {
 	unsigned long sum = 0;
 	int i;
 
 	for (i = 0; i < nr_range; i++)
-		sum += range[i].end + 1 - range[i].start;
+		sum += range[i].end - range[i].start;
 
 	return sum;
 }
@@ -621,7 +471,7 @@
 early_param("mtrr_spare_reg_nr", parse_mtrr_spare_reg);
 
 static int __init
-x86_setup_var_mtrrs(struct res_range *range, int nr_range,
+x86_setup_var_mtrrs(struct range *range, int nr_range,
 		    u64 chunk_size, u64 gran_size)
 {
 	struct var_mtrr_state var_state;
@@ -639,7 +489,7 @@
 	/* Write the range: */
 	for (i = 0; i < nr_range; i++) {
 		set_var_mtrr_range(&var_state, range[i].start,
-				   range[i].end - range[i].start + 1);
+				   range[i].end - range[i].start);
 	}
 
 	/* Write the last range: */
@@ -742,7 +592,7 @@
 		      unsigned long x_remove_base,
 		      unsigned long x_remove_size, int i)
 {
-	static struct res_range range_new[RANGE_NUM];
+	static struct range range_new[RANGE_NUM];
 	unsigned long range_sums_new;
 	static int nr_range_new;
 	int num_reg;
@@ -869,10 +719,10 @@
 	 * [0, 1M) should always be covered by var mtrr with WB
 	 * and fixed mtrrs should take effect before var mtrr for it:
 	 */
-	nr_range = add_range_with_merge(range, nr_range, 0,
-					(1ULL<<(20 - PAGE_SHIFT)) - 1);
+	nr_range = add_range_with_merge(range, RANGE_NUM, nr_range, 0,
+					1ULL<<(20 - PAGE_SHIFT));
 	/* Sort the ranges: */
-	sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL);
+	sort_range(range, nr_range);
 
 	range_sums = sum_ranges(range, nr_range);
 	printk(KERN_INFO "total RAM covered: %ldM\n",
@@ -1089,9 +939,9 @@
 	nr_range = 0;
 	if (mtrr_tom2) {
 		range[nr_range].start = (1ULL<<(32 - PAGE_SHIFT));
-		range[nr_range].end = (mtrr_tom2 >> PAGE_SHIFT) - 1;
-		if (highest_pfn < range[nr_range].end + 1)
-			highest_pfn = range[nr_range].end + 1;
+		range[nr_range].end = mtrr_tom2 >> PAGE_SHIFT;
+		if (highest_pfn < range[nr_range].end)
+			highest_pfn = range[nr_range].end;
 		nr_range++;
 	}
 	nr_range = x86_get_mtrr_mem_range(range, nr_range, 0, 0);
@@ -1103,15 +953,15 @@
 
 	/* Check the holes: */
 	for (i = 0; i < nr_range - 1; i++) {
-		if (range[i].end + 1 < range[i+1].start)
-			total_trim_size += real_trim_memory(range[i].end + 1,
+		if (range[i].end < range[i+1].start)
+			total_trim_size += real_trim_memory(range[i].end,
 							    range[i+1].start);
 	}
 
 	/* Check the top: */
 	i = nr_range - 1;
-	if (range[i].end + 1 < end_pfn)
-		total_trim_size += real_trim_memory(range[i].end + 1,
+	if (range[i].end < end_pfn)
+		total_trim_size += real_trim_memory(range[i].end,
 							 end_pfn);
 
 	if (total_trim_size) {
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index fe4622e..79556bd 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -145,6 +145,7 @@
 
 /**
  * ipi_handler - Synchronisation handler. Executed by "other" CPUs.
+ * @info: pointer to mtrr configuration data
  *
  * Returns nothing.
  */
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 641ccb9..42aafd1 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -73,10 +73,10 @@
 struct event_constraint {
 	union {
 		unsigned long	idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-		u64		idxmsk64[1];
+		u64		idxmsk64;
 	};
-	int	code;
-	int	cmask;
+	u64	code;
+	u64	cmask;
 	int	weight;
 };
 
@@ -103,7 +103,7 @@
 };
 
 #define __EVENT_CONSTRAINT(c, n, m, w) {\
-	{ .idxmsk64[0] = (n) },		\
+	{ .idxmsk64 = (n) },		\
 	.code = (c),			\
 	.cmask = (m),			\
 	.weight = (w),			\
@@ -116,7 +116,7 @@
 	EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVTSEL_MASK)
 
 #define FIXED_EVENT_CONSTRAINT(c, n)	\
-	EVENT_CONSTRAINT(c, n, INTEL_ARCH_FIXED_MASK)
+	EVENT_CONSTRAINT(c, (1ULL << (32+n)), INTEL_ARCH_FIXED_MASK)
 
 #define EVENT_CONSTRAINT_END		\
 	EVENT_CONSTRAINT(0, 0, 0)
@@ -503,6 +503,9 @@
 	 */
 	if (attr->type == PERF_TYPE_RAW) {
 		hwc->config |= x86_pmu.raw_event(attr->config);
+		if ((hwc->config & ARCH_PERFMON_EVENTSEL_ANY) &&
+		    perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
+			return -EACCES;
 		return 0;
 	}
 
@@ -553,9 +556,9 @@
 		if (!test_bit(idx, cpuc->active_mask))
 			continue;
 		rdmsrl(x86_pmu.eventsel + idx, val);
-		if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE))
+		if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE))
 			continue;
-		val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+		val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
 		wrmsrl(x86_pmu.eventsel + idx, val);
 	}
 }
@@ -590,7 +593,7 @@
 			continue;
 
 		val = event->hw.config;
-		val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 		wrmsrl(x86_pmu.eventsel + idx, val);
 	}
 }
@@ -612,8 +615,8 @@
 	bitmap_zero(used_mask, X86_PMC_IDX_MAX);
 
 	for (i = 0; i < n; i++) {
-		constraints[i] =
-		  x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]);
+		c = x86_pmu.get_event_constraints(cpuc, cpuc->event_list[i]);
+		constraints[i] = c;
 	}
 
 	/*
@@ -676,7 +679,7 @@
 			if (c->weight != w)
 				continue;
 
-			for_each_bit(j, c->idxmsk, X86_PMC_IDX_MAX) {
+			for_each_set_bit(j, c->idxmsk, X86_PMC_IDX_MAX) {
 				if (!test_bit(j, used_mask))
 					break;
 			}
@@ -853,7 +856,7 @@
 static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, int idx)
 {
 	(void)checking_wrmsrl(hwc->config_base + idx,
-			      hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE);
+			      hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE);
 }
 
 static inline void x86_pmu_disable_event(struct hw_perf_event *hwc, int idx)
@@ -1094,8 +1097,7 @@
 	int idx, handled = 0;
 	u64 val;
 
-	data.addr = 0;
-	data.raw = NULL;
+	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -1347,6 +1349,7 @@
 
 void __init init_hw_perf_events(void)
 {
+	struct event_constraint *c;
 	int err;
 
 	pr_info("Performance Events: ");
@@ -1395,6 +1398,16 @@
 		__EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_events) - 1,
 				   0, x86_pmu.num_events);
 
+	if (x86_pmu.event_constraints) {
+		for_each_event_constraint(c, x86_pmu.event_constraints) {
+			if (c->cmask != INTEL_ARCH_FIXED_MASK)
+				continue;
+
+			c->idxmsk64 |= (1ULL << x86_pmu.num_events) - 1;
+			c->weight += x86_pmu.num_events;
+		}
+	}
+
 	pr_info("... version:                %d\n",     x86_pmu.version);
 	pr_info("... bit width:              %d\n",     x86_pmu.event_bits);
 	pr_info("... generic registers:      %d\n",     x86_pmu.num_events);
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index cf6590c..44b60c8 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1,7 +1,7 @@
 #ifdef CONFIG_CPU_SUP_INTEL
 
 /*
- * Intel PerfMon v3. Used on Core2 and later.
+ * Intel PerfMon, used on Core and later.
  */
 static const u64 intel_perfmon_event_map[] =
 {
@@ -27,8 +27,14 @@
 
 static struct event_constraint intel_core2_event_constraints[] =
 {
-	FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */
-	FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */
+	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+	FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+	/*
+	 * Core2 has Fixed Counter 2 listed as CPU_CLK_UNHALTED.REF and event
+	 * 0x013c as CPU_CLK_UNHALTED.BUS and specifies there is a fixed
+	 * ratio between these counters.
+	 */
+	/* FIXED_EVENT_CONSTRAINT(0x013c, 2),  CPU_CLK_UNHALTED.REF */
 	INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */
 	INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
 	INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
@@ -37,14 +43,16 @@
 	INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */
 	INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */
 	INTEL_EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */
+	INTEL_EVENT_CONSTRAINT(0xc9, 0x1), /* ITLB_MISS_RETIRED (T30-9) */
 	INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */
 	EVENT_CONSTRAINT_END
 };
 
 static struct event_constraint intel_nehalem_event_constraints[] =
 {
-	FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */
-	FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */
+	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+	FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+	/* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
 	INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */
 	INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */
 	INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */
@@ -58,8 +66,9 @@
 
 static struct event_constraint intel_westmere_event_constraints[] =
 {
-	FIXED_EVENT_CONSTRAINT(0xc0, (0xf|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */
-	FIXED_EVENT_CONSTRAINT(0x3c, (0xf|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */
+	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+	FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+	/* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
 	INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */
 	INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */
 	INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */
@@ -68,8 +77,9 @@
 
 static struct event_constraint intel_gen_event_constraints[] =
 {
-	FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */
-	FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */
+	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+	FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+	/* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
 	EVENT_CONSTRAINT_END
 };
 
@@ -580,10 +590,9 @@
 
 	ds->bts_index = ds->bts_buffer_base;
 
+	perf_sample_data_init(&data, 0);
 
 	data.period	= event->hw.last_period;
-	data.addr	= 0;
-	data.raw	= NULL;
 	regs.ip		= 0;
 
 	/*
@@ -732,8 +741,7 @@
 	int bit, loops;
 	u64 ack, status;
 
-	data.addr = 0;
-	data.raw = NULL;
+	perf_sample_data_init(&data, 0);
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
 
@@ -757,7 +765,7 @@
 
 	inc_irq_stat(apic_perf_irqs);
 	ack = status;
-	for_each_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
+	for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
 		struct perf_event *event = cpuc->events[bit];
 
 		clear_bit(bit, (unsigned long *) &status);
@@ -935,7 +943,7 @@
 		x86_pmu.event_constraints = intel_nehalem_event_constraints;
 		pr_cont("Nehalem/Corei7 events, ");
 		break;
-	case 28:
+	case 28: /* Atom */
 		memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
 		       sizeof(hw_cache_event_ids));
 
@@ -951,6 +959,7 @@
 		x86_pmu.event_constraints = intel_westmere_event_constraints;
 		pr_cont("Westmere events, ");
 		break;
+
 	default:
 		/*
 		 * default constraints for v2 and up
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
index 1ca5ba0..a4e67b9 100644
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -62,7 +62,7 @@
 
 	/* p6 only has one enable register */
 	rdmsrl(MSR_P6_EVNTSEL0, val);
-	val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+	val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
 	wrmsrl(MSR_P6_EVNTSEL0, val);
 }
 
@@ -72,7 +72,7 @@
 
 	/* p6 only has one enable register */
 	rdmsrl(MSR_P6_EVNTSEL0, val);
-	val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+	val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 	wrmsrl(MSR_P6_EVNTSEL0, val);
 }
 
@@ -83,7 +83,7 @@
 	u64 val = P6_NOP_EVENT;
 
 	if (cpuc->enabled)
-		val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
 	(void)checking_wrmsrl(hwc->config_base + idx, val);
 }
@@ -95,7 +95,7 @@
 
 	val = hwc->config;
 	if (cpuc->enabled)
-		val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
 	(void)checking_wrmsrl(hwc->config_base + idx, val);
 }
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index 74f4e85..fb329e9 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -680,7 +680,7 @@
 	cpu_nmi_set_wd_enabled();
 
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
-	evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+	evntsel |= ARCH_PERFMON_EVENTSEL_ENABLE;
 	wrmsr(evntsel_msr, evntsel, 0);
 	intel_arch_wd_ops.checkbit = 1ULL << (eax.split.bit_width - 1);
 	return 1;
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index dce99ab..d5e2a2e 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -120,9 +120,15 @@
 {
 #ifdef CONFIG_FRAME_POINTER
 	struct stack_frame *frame = (struct stack_frame *)bp;
+	unsigned long next;
 
-	if (!in_irq_stack(stack, irq_stack, irq_stack_end))
-		return (unsigned long)frame->next_frame;
+	if (!in_irq_stack(stack, irq_stack, irq_stack_end)) {
+		if (!probe_kernel_address(&frame->next_frame, next))
+			return next;
+		else
+			WARN_ONCE(1, "Perf: bad frame pointer = %p in "
+				  "callchain\n", &frame->next_frame);
+	}
 #endif
 	return bp;
 }
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index a966b75..740b440 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -12,21 +12,13 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/kexec.h>
-#include <linux/module.h>
-#include <linux/mm.h>
 #include <linux/pfn.h>
 #include <linux/suspend.h>
 #include <linux/firmware-map.h>
 
-#include <asm/pgtable.h>
-#include <asm/page.h>
 #include <asm/e820.h>
 #include <asm/proto.h>
 #include <asm/setup.h>
-#include <asm/trampoline.h>
 
 /*
  * The e820 map is the map that gets modified e.g. with command line parameters
@@ -730,288 +722,6 @@
 #endif
 
 /*
- * Early reserved memory areas.
- */
-#define MAX_EARLY_RES 32
-
-struct early_res {
-	u64 start, end;
-	char name[16];
-	char overlap_ok;
-};
-static struct early_res early_res[MAX_EARLY_RES] __initdata = {
-	{ 0, PAGE_SIZE, "BIOS data page", 1 },	/* BIOS data page */
-#if defined(CONFIG_X86_32) && defined(CONFIG_X86_TRAMPOLINE)
-	/*
-	 * But first pinch a few for the stack/trampoline stuff
-	 * FIXME: Don't need the extra page at 4K, but need to fix
-	 * trampoline before removing it. (see the GDT stuff)
-	 */
-	{ PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE", 1 },
-#endif
-
-	{}
-};
-
-static int __init find_overlapped_early(u64 start, u64 end)
-{
-	int i;
-	struct early_res *r;
-
-	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
-		r = &early_res[i];
-		if (end > r->start && start < r->end)
-			break;
-	}
-
-	return i;
-}
-
-/*
- * Drop the i-th range from the early reservation map,
- * by copying any higher ranges down one over it, and
- * clearing what had been the last slot.
- */
-static void __init drop_range(int i)
-{
-	int j;
-
-	for (j = i + 1; j < MAX_EARLY_RES && early_res[j].end; j++)
-		;
-
-	memmove(&early_res[i], &early_res[i + 1],
-	       (j - 1 - i) * sizeof(struct early_res));
-
-	early_res[j - 1].end = 0;
-}
-
-/*
- * Split any existing ranges that:
- *  1) are marked 'overlap_ok', and
- *  2) overlap with the stated range [start, end)
- * into whatever portion (if any) of the existing range is entirely
- * below or entirely above the stated range.  Drop the portion
- * of the existing range that overlaps with the stated range,
- * which will allow the caller of this routine to then add that
- * stated range without conflicting with any existing range.
- */
-static void __init drop_overlaps_that_are_ok(u64 start, u64 end)
-{
-	int i;
-	struct early_res *r;
-	u64 lower_start, lower_end;
-	u64 upper_start, upper_end;
-	char name[16];
-
-	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
-		r = &early_res[i];
-
-		/* Continue past non-overlapping ranges */
-		if (end <= r->start || start >= r->end)
-			continue;
-
-		/*
-		 * Leave non-ok overlaps as is; let caller
-		 * panic "Overlapping early reservations"
-		 * when it hits this overlap.
-		 */
-		if (!r->overlap_ok)
-			return;
-
-		/*
-		 * We have an ok overlap.  We will drop it from the early
-		 * reservation map, and add back in any non-overlapping
-		 * portions (lower or upper) as separate, overlap_ok,
-		 * non-overlapping ranges.
-		 */
-
-		/* 1. Note any non-overlapping (lower or upper) ranges. */
-		strncpy(name, r->name, sizeof(name) - 1);
-
-		lower_start = lower_end = 0;
-		upper_start = upper_end = 0;
-		if (r->start < start) {
-		 	lower_start = r->start;
-			lower_end = start;
-		}
-		if (r->end > end) {
-			upper_start = end;
-			upper_end = r->end;
-		}
-
-		/* 2. Drop the original ok overlapping range */
-		drop_range(i);
-
-		i--;		/* resume for-loop on copied down entry */
-
-		/* 3. Add back in any non-overlapping ranges. */
-		if (lower_end)
-			reserve_early_overlap_ok(lower_start, lower_end, name);
-		if (upper_end)
-			reserve_early_overlap_ok(upper_start, upper_end, name);
-	}
-}
-
-static void __init __reserve_early(u64 start, u64 end, char *name,
-						int overlap_ok)
-{
-	int i;
-	struct early_res *r;
-
-	i = find_overlapped_early(start, end);
-	if (i >= MAX_EARLY_RES)
-		panic("Too many early reservations");
-	r = &early_res[i];
-	if (r->end)
-		panic("Overlapping early reservations "
-		      "%llx-%llx %s to %llx-%llx %s\n",
-		      start, end - 1, name?name:"", r->start,
-		      r->end - 1, r->name);
-	r->start = start;
-	r->end = end;
-	r->overlap_ok = overlap_ok;
-	if (name)
-		strncpy(r->name, name, sizeof(r->name) - 1);
-}
-
-/*
- * A few early reservtations come here.
- *
- * The 'overlap_ok' in the name of this routine does -not- mean it
- * is ok for these reservations to overlap an earlier reservation.
- * Rather it means that it is ok for subsequent reservations to
- * overlap this one.
- *
- * Use this entry point to reserve early ranges when you are doing
- * so out of "Paranoia", reserving perhaps more memory than you need,
- * just in case, and don't mind a subsequent overlapping reservation
- * that is known to be needed.
- *
- * The drop_overlaps_that_are_ok() call here isn't really needed.
- * It would be needed if we had two colliding 'overlap_ok'
- * reservations, so that the second such would not panic on the
- * overlap with the first.  We don't have any such as of this
- * writing, but might as well tolerate such if it happens in
- * the future.
- */
-void __init reserve_early_overlap_ok(u64 start, u64 end, char *name)
-{
-	drop_overlaps_that_are_ok(start, end);
-	__reserve_early(start, end, name, 1);
-}
-
-/*
- * Most early reservations come here.
- *
- * We first have drop_overlaps_that_are_ok() drop any pre-existing
- * 'overlap_ok' ranges, so that we can then reserve this memory
- * range without risk of panic'ing on an overlapping overlap_ok
- * early reservation.
- */
-void __init reserve_early(u64 start, u64 end, char *name)
-{
-	if (start >= end)
-		return;
-
-	drop_overlaps_that_are_ok(start, end);
-	__reserve_early(start, end, name, 0);
-}
-
-void __init free_early(u64 start, u64 end)
-{
-	struct early_res *r;
-	int i;
-
-	i = find_overlapped_early(start, end);
-	r = &early_res[i];
-	if (i >= MAX_EARLY_RES || r->end != end || r->start != start)
-		panic("free_early on not reserved area: %llx-%llx!",
-			 start, end - 1);
-
-	drop_range(i);
-}
-
-void __init early_res_to_bootmem(u64 start, u64 end)
-{
-	int i, count;
-	u64 final_start, final_end;
-
-	count  = 0;
-	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++)
-		count++;
-
-	printk(KERN_INFO "(%d early reservations) ==> bootmem [%010llx - %010llx]\n",
-			 count, start, end);
-	for (i = 0; i < count; i++) {
-		struct early_res *r = &early_res[i];
-		printk(KERN_INFO "  #%d [%010llx - %010llx] %16s", i,
-			r->start, r->end, r->name);
-		final_start = max(start, r->start);
-		final_end = min(end, r->end);
-		if (final_start >= final_end) {
-			printk(KERN_CONT "\n");
-			continue;
-		}
-		printk(KERN_CONT " ==> [%010llx - %010llx]\n",
-			final_start, final_end);
-		reserve_bootmem_generic(final_start, final_end - final_start,
-				BOOTMEM_DEFAULT);
-	}
-}
-
-/* Check for already reserved areas */
-static inline int __init bad_addr(u64 *addrp, u64 size, u64 align)
-{
-	int i;
-	u64 addr = *addrp;
-	int changed = 0;
-	struct early_res *r;
-again:
-	i = find_overlapped_early(addr, addr + size);
-	r = &early_res[i];
-	if (i < MAX_EARLY_RES && r->end) {
-		*addrp = addr = round_up(r->end, align);
-		changed = 1;
-		goto again;
-	}
-	return changed;
-}
-
-/* Check for already reserved areas */
-static inline int __init bad_addr_size(u64 *addrp, u64 *sizep, u64 align)
-{
-	int i;
-	u64 addr = *addrp, last;
-	u64 size = *sizep;
-	int changed = 0;
-again:
-	last = addr + size;
-	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++) {
-		struct early_res *r = &early_res[i];
-		if (last > r->start && addr < r->start) {
-			size = r->start - addr;
-			changed = 1;
-			goto again;
-		}
-		if (last > r->end && addr < r->end) {
-			addr = round_up(r->end, align);
-			size = last - addr;
-			changed = 1;
-			goto again;
-		}
-		if (last <= r->end && addr >= r->start) {
-			(*sizep)++;
-			return 0;
-		}
-	}
-	if (changed) {
-		*addrp = addr;
-		*sizep = size;
-	}
-	return changed;
-}
-
-/*
  * Find a free area with specified alignment in a specific range.
  */
 u64 __init find_e820_area(u64 start, u64 end, u64 size, u64 align)
@@ -1020,29 +730,36 @@
 
 	for (i = 0; i < e820.nr_map; i++) {
 		struct e820entry *ei = &e820.map[i];
-		u64 addr, last;
-		u64 ei_last;
+		u64 addr;
+		u64 ei_start, ei_last;
 
 		if (ei->type != E820_RAM)
 			continue;
-		addr = round_up(ei->addr, align);
+
 		ei_last = ei->addr + ei->size;
-		if (addr < start)
-			addr = round_up(start, align);
-		if (addr >= ei_last)
-			continue;
-		while (bad_addr(&addr, size, align) && addr+size <= ei_last)
-			;
-		last = addr + size;
-		if (last > ei_last)
-			continue;
-		if (last > end)
-			continue;
-		return addr;
+		ei_start = ei->addr;
+		addr = find_early_area(ei_start, ei_last, start, end,
+					 size, align);
+
+		if (addr != -1ULL)
+			return addr;
 	}
 	return -1ULL;
 }
 
+u64 __init find_fw_memmap_area(u64 start, u64 end, u64 size, u64 align)
+{
+	return find_e820_area(start, end, size, align);
+}
+
+u64 __init get_max_mapped(void)
+{
+	u64 end = max_pfn_mapped;
+
+	end <<= PAGE_SHIFT;
+
+	return end;
+}
 /*
  * Find next free range after *start
  */
@@ -1052,25 +769,19 @@
 
 	for (i = 0; i < e820.nr_map; i++) {
 		struct e820entry *ei = &e820.map[i];
-		u64 addr, last;
-		u64 ei_last;
+		u64 addr;
+		u64 ei_start, ei_last;
 
 		if (ei->type != E820_RAM)
 			continue;
-		addr = round_up(ei->addr, align);
+
 		ei_last = ei->addr + ei->size;
-		if (addr < start)
-			addr = round_up(start, align);
-		if (addr >= ei_last)
-			continue;
-		*sizep = ei_last - addr;
-		while (bad_addr_size(&addr, sizep, align) &&
-			addr + *sizep <= ei_last)
-			;
-		last = addr + *sizep;
-		if (last > ei_last)
-			continue;
-		return addr;
+		ei_start = ei->addr;
+		addr = find_early_area_size(ei_start, ei_last, start,
+					 sizep, align);
+
+		if (addr != -1ULL)
+			return addr;
 	}
 
 	return -1ULL;
@@ -1429,6 +1140,8 @@
 			end = MAX_RESOURCE_SIZE;
 		if (start >= end)
 			continue;
+		printk(KERN_DEBUG "reserve RAM buffer: %016llx - %016llx ",
+			       start, end);
 		reserve_region_with_split(&iomem_resource, start, end,
 					  "RAM buffer");
 	}
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 5051b94..adedeef 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -29,6 +29,16 @@
 
 void __init i386_start_kernel(void)
 {
+#ifdef CONFIG_X86_TRAMPOLINE
+	/*
+	 * But first pinch a few for the stack/trampoline stuff
+	 * FIXME: Don't need the extra page at 4K, but need to fix
+	 * trampoline before removing it. (see the GDT stuff)
+	 */
+	reserve_early_overlap_ok(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE,
+					 "EX TRAMPOLINE");
+#endif
+
 	reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
 
 #ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 7fd318b..37c3d4b 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -442,8 +442,8 @@
 	 */
 	cmpb $0,ready
 	jne 1f
-	movl $per_cpu__gdt_page,%eax
-	movl $per_cpu__stack_canary,%ecx
+	movl $gdt_page,%eax
+	movl $stack_canary,%ecx
 	movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax)
 	shrl $16, %ecx
 	movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax)
@@ -706,7 +706,7 @@
 	.word 0				# 32 bit align gdt_desc.address
 ENTRY(early_gdt_descr)
 	.word GDT_ENTRIES*8-1
-	.long per_cpu__gdt_page		/* Overwritten for secondary CPUs */
+	.long gdt_page			/* Overwritten for secondary CPUs */
 
 /*
  * The boot_gdt must mirror the equivalent in setup.S and is
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 2d8b503..3d1e6f1 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -27,7 +27,7 @@
 #define GET_CR2_INTO_RCX movq %cr2, %rcx
 #endif
 
-/* we are not able to switch in one step to the final KERNEL ADRESS SPACE
+/* we are not able to switch in one step to the final KERNEL ADDRESS SPACE
  * because we need identity-mapped pages.
  *
  */
diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c
index dca2802..d6cc065 100644
--- a/arch/x86/kernel/hw_breakpoint.c
+++ b/arch/x86/kernel/hw_breakpoint.c
@@ -344,13 +344,6 @@
 	}
 
 	/*
-	 * For kernel-addresses, either the address or symbol name can be
-	 * specified.
-	 */
-	if (info->name)
-		info->address = (unsigned long)
-				kallsyms_lookup_name(info->name);
-	/*
 	 * Check that the low-order bits of the address are appropriate
 	 * for the alignment implied by len.
 	 */
@@ -535,8 +528,3 @@
 {
 	/* TODO */
 }
-
-void hw_breakpoint_pmu_unthrottle(struct perf_event *bp)
-{
-	/* TODO */
-}
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index df89102..fb725ee 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -32,8 +32,14 @@
  */
 
 static int i8259A_auto_eoi;
-DEFINE_SPINLOCK(i8259A_lock);
+DEFINE_RAW_SPINLOCK(i8259A_lock);
 static void mask_and_ack_8259A(unsigned int);
+static void mask_8259A(void);
+static void unmask_8259A(void);
+static void disable_8259A_irq(unsigned int irq);
+static void enable_8259A_irq(unsigned int irq);
+static void init_8259A(int auto_eoi);
+static int i8259A_irq_pending(unsigned int irq);
 
 struct irq_chip i8259A_chip = {
 	.name		= "XT-PIC",
@@ -63,51 +69,51 @@
  */
 unsigned long io_apic_irqs;
 
-void disable_8259A_irq(unsigned int irq)
+static void disable_8259A_irq(unsigned int irq)
 {
 	unsigned int mask = 1 << irq;
 	unsigned long flags;
 
-	spin_lock_irqsave(&i8259A_lock, flags);
+	raw_spin_lock_irqsave(&i8259A_lock, flags);
 	cached_irq_mask |= mask;
 	if (irq & 8)
 		outb(cached_slave_mask, PIC_SLAVE_IMR);
 	else
 		outb(cached_master_mask, PIC_MASTER_IMR);
-	spin_unlock_irqrestore(&i8259A_lock, flags);
+	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
-void enable_8259A_irq(unsigned int irq)
+static void enable_8259A_irq(unsigned int irq)
 {
 	unsigned int mask = ~(1 << irq);
 	unsigned long flags;
 
-	spin_lock_irqsave(&i8259A_lock, flags);
+	raw_spin_lock_irqsave(&i8259A_lock, flags);
 	cached_irq_mask &= mask;
 	if (irq & 8)
 		outb(cached_slave_mask, PIC_SLAVE_IMR);
 	else
 		outb(cached_master_mask, PIC_MASTER_IMR);
-	spin_unlock_irqrestore(&i8259A_lock, flags);
+	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
-int i8259A_irq_pending(unsigned int irq)
+static int i8259A_irq_pending(unsigned int irq)
 {
 	unsigned int mask = 1<<irq;
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&i8259A_lock, flags);
+	raw_spin_lock_irqsave(&i8259A_lock, flags);
 	if (irq < 8)
 		ret = inb(PIC_MASTER_CMD) & mask;
 	else
 		ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
-	spin_unlock_irqrestore(&i8259A_lock, flags);
+	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 
 	return ret;
 }
 
-void make_8259A_irq(unsigned int irq)
+static void make_8259A_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
 	io_apic_irqs &= ~(1<<irq);
@@ -150,7 +156,7 @@
 	unsigned int irqmask = 1 << irq;
 	unsigned long flags;
 
-	spin_lock_irqsave(&i8259A_lock, flags);
+	raw_spin_lock_irqsave(&i8259A_lock, flags);
 	/*
 	 * Lightweight spurious IRQ detection. We do not want
 	 * to overdo spurious IRQ handling - it's usually a sign
@@ -183,7 +189,7 @@
 		outb(cached_master_mask, PIC_MASTER_IMR);
 		outb(0x60+irq, PIC_MASTER_CMD);	/* 'Specific EOI to master */
 	}
-	spin_unlock_irqrestore(&i8259A_lock, flags);
+	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 	return;
 
 spurious_8259A_irq:
@@ -281,37 +287,37 @@
 
 device_initcall(i8259A_init_sysfs);
 
-void mask_8259A(void)
+static void mask_8259A(void)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&i8259A_lock, flags);
+	raw_spin_lock_irqsave(&i8259A_lock, flags);
 
 	outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */
 	outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-2 */
 
-	spin_unlock_irqrestore(&i8259A_lock, flags);
+	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
-void unmask_8259A(void)
+static void unmask_8259A(void)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&i8259A_lock, flags);
+	raw_spin_lock_irqsave(&i8259A_lock, flags);
 
 	outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
 	outb(cached_slave_mask, PIC_SLAVE_IMR);	  /* restore slave IRQ mask */
 
-	spin_unlock_irqrestore(&i8259A_lock, flags);
+	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
-void init_8259A(int auto_eoi)
+static void init_8259A(int auto_eoi)
 {
 	unsigned long flags;
 
 	i8259A_auto_eoi = auto_eoi;
 
-	spin_lock_irqsave(&i8259A_lock, flags);
+	raw_spin_lock_irqsave(&i8259A_lock, flags);
 
 	outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */
 	outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-2 */
@@ -356,5 +362,49 @@
 	outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
 	outb(cached_slave_mask, PIC_SLAVE_IMR);	  /* restore slave IRQ mask */
 
-	spin_unlock_irqrestore(&i8259A_lock, flags);
+	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
+
+/*
+ * make i8259 a driver so that we can select pic functions at run time. the goal
+ * is to make x86 binary compatible among pc compatible and non-pc compatible
+ * platforms, such as x86 MID.
+ */
+
+static void legacy_pic_noop(void) { };
+static void legacy_pic_uint_noop(unsigned int unused) { };
+static void legacy_pic_int_noop(int unused) { };
+
+static struct irq_chip dummy_pic_chip  = {
+	.name = "dummy pic",
+	.mask = legacy_pic_uint_noop,
+	.unmask = legacy_pic_uint_noop,
+	.disable = legacy_pic_uint_noop,
+	.mask_ack = legacy_pic_uint_noop,
+};
+static int legacy_pic_irq_pending_noop(unsigned int irq)
+{
+	return 0;
+}
+
+struct legacy_pic null_legacy_pic = {
+	.nr_legacy_irqs = 0,
+	.chip = &dummy_pic_chip,
+	.mask_all = legacy_pic_noop,
+	.restore_mask = legacy_pic_noop,
+	.init = legacy_pic_int_noop,
+	.irq_pending = legacy_pic_irq_pending_noop,
+	.make_irq = legacy_pic_uint_noop,
+};
+
+struct legacy_pic default_legacy_pic = {
+	.nr_legacy_irqs = NR_IRQS_LEGACY,
+	.chip  = &i8259A_chip,
+	.mask_all  = mask_8259A,
+	.restore_mask = unmask_8259A,
+	.init = init_8259A,
+	.irq_pending = i8259A_irq_pending,
+	.make_irq = make_8259A_irq,
+};
+
+struct legacy_pic *legacy_pic = &default_legacy_pic;
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index d593222..ef257fc 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -84,24 +84,7 @@
 };
 
 DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
-	[0 ... IRQ0_VECTOR - 1] = -1,
-	[IRQ0_VECTOR] = 0,
-	[IRQ1_VECTOR] = 1,
-	[IRQ2_VECTOR] = 2,
-	[IRQ3_VECTOR] = 3,
-	[IRQ4_VECTOR] = 4,
-	[IRQ5_VECTOR] = 5,
-	[IRQ6_VECTOR] = 6,
-	[IRQ7_VECTOR] = 7,
-	[IRQ8_VECTOR] = 8,
-	[IRQ9_VECTOR] = 9,
-	[IRQ10_VECTOR] = 10,
-	[IRQ11_VECTOR] = 11,
-	[IRQ12_VECTOR] = 12,
-	[IRQ13_VECTOR] = 13,
-	[IRQ14_VECTOR] = 14,
-	[IRQ15_VECTOR] = 15,
-	[IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
+	[0 ... NR_VECTORS - 1] = -1,
 };
 
 int vector_used_by_percpu_irq(unsigned int vector)
@@ -123,12 +106,12 @@
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
 	init_bsp_APIC();
 #endif
-	init_8259A(0);
+	legacy_pic->init(0);
 
 	/*
 	 * 16 old-style INTA-cycle interrupts:
 	 */
-	for (i = 0; i < NR_IRQS_LEGACY; i++) {
+	for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) {
 		struct irq_desc *desc = irq_to_desc(i);
 
 		desc->status = IRQ_DISABLED;
@@ -142,6 +125,19 @@
 
 void __init init_IRQ(void)
 {
+	int i;
+
+	/*
+	 * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
+	 * If these IRQ's are handled by legacy interrupt-controllers like PIC,
+	 * then this configuration will likely be static after the boot. If
+	 * these IRQ's are handled by more mordern controllers like IO-APIC,
+	 * then this vector space can be freed and re-used dynamically as the
+	 * irq's migrate etc.
+	 */
+	for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
+		per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;
+
 	x86_init.irqs.intr_init();
 }
 
diff --git a/arch/x86/kernel/k8.c b/arch/x86/kernel/k8.c
index cbc4332..9b89546 100644
--- a/arch/x86/kernel/k8.c
+++ b/arch/x86/kernel/k8.c
@@ -121,3 +121,17 @@
 }
 EXPORT_SYMBOL_GPL(k8_flush_garts);
 
+static __init int init_k8_nbs(void)
+{
+	int err = 0;
+
+	err = cache_k8_northbridges();
+
+	if (err < 0)
+		printk(KERN_NOTICE "K8 NB: Cannot enumerate AMD northbridges.\n");
+
+	return err;
+}
+
+/* This has to go after the PCI subsystem */
+fs_initcall(init_k8_nbs);
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index 5de9f4a..b43bbae 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -49,6 +49,7 @@
 #include <linux/module.h>
 #include <linux/kdebug.h>
 #include <linux/kallsyms.h>
+#include <linux/ftrace.h>
 
 #include <asm/cacheflush.h>
 #include <asm/desc.h>
@@ -106,16 +107,22 @@
 };
 const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist);
 
-/* Insert a jump instruction at address 'from', which jumps to address 'to'.*/
-static void __kprobes set_jmp_op(void *from, void *to)
+static void __kprobes __synthesize_relative_insn(void *from, void *to, u8 op)
 {
-	struct __arch_jmp_op {
-		char op;
+	struct __arch_relative_insn {
+		u8 op;
 		s32 raddr;
-	} __attribute__((packed)) * jop;
-	jop = (struct __arch_jmp_op *)from;
-	jop->raddr = (s32)((long)(to) - ((long)(from) + 5));
-	jop->op = RELATIVEJUMP_INSTRUCTION;
+	} __attribute__((packed)) *insn;
+
+	insn = (struct __arch_relative_insn *)from;
+	insn->raddr = (s32)((long)(to) - ((long)(from) + 5));
+	insn->op = op;
+}
+
+/* Insert a jump instruction at address 'from', which jumps to address 'to'.*/
+static void __kprobes synthesize_reljump(void *from, void *to)
+{
+	__synthesize_relative_insn(from, to, RELATIVEJUMP_OPCODE);
 }
 
 /*
@@ -202,7 +209,7 @@
 	/*
 	 *  Basically, kp->ainsn.insn has an original instruction.
 	 *  However, RIP-relative instruction can not do single-stepping
-	 *  at different place, fix_riprel() tweaks the displacement of
+	 *  at different place, __copy_instruction() tweaks the displacement of
 	 *  that instruction. In that case, we can't recover the instruction
 	 *  from the kp->ainsn.insn.
 	 *
@@ -284,21 +291,37 @@
 }
 
 /*
- * Adjust the displacement if the instruction uses the %rip-relative
- * addressing mode.
+ * Copy an instruction and adjust the displacement if the instruction
+ * uses the %rip-relative addressing mode.
  * If it does, Return the address of the 32-bit displacement word.
  * If not, return null.
  * Only applicable to 64-bit x86.
  */
-static void __kprobes fix_riprel(struct kprobe *p)
+static int __kprobes __copy_instruction(u8 *dest, u8 *src, int recover)
 {
-#ifdef CONFIG_X86_64
 	struct insn insn;
-	kernel_insn_init(&insn, p->ainsn.insn);
+	int ret;
+	kprobe_opcode_t buf[MAX_INSN_SIZE];
 
+	kernel_insn_init(&insn, src);
+	if (recover) {
+		insn_get_opcode(&insn);
+		if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION) {
+			ret = recover_probed_instruction(buf,
+							 (unsigned long)src);
+			if (ret)
+				return 0;
+			kernel_insn_init(&insn, buf);
+		}
+	}
+	insn_get_length(&insn);
+	memcpy(dest, insn.kaddr, insn.length);
+
+#ifdef CONFIG_X86_64
 	if (insn_rip_relative(&insn)) {
 		s64 newdisp;
 		u8 *disp;
+		kernel_insn_init(&insn, dest);
 		insn_get_displacement(&insn);
 		/*
 		 * The copied instruction uses the %rip-relative addressing
@@ -312,20 +335,23 @@
 		 * extension of the original signed 32-bit displacement would
 		 * have given.
 		 */
-		newdisp = (u8 *) p->addr + (s64) insn.displacement.value -
-			  (u8 *) p->ainsn.insn;
+		newdisp = (u8 *) src + (s64) insn.displacement.value -
+			  (u8 *) dest;
 		BUG_ON((s64) (s32) newdisp != newdisp); /* Sanity check.  */
-		disp = (u8 *) p->ainsn.insn + insn_offset_displacement(&insn);
+		disp = (u8 *) dest + insn_offset_displacement(&insn);
 		*(s32 *) disp = (s32) newdisp;
 	}
 #endif
+	return insn.length;
 }
 
 static void __kprobes arch_copy_kprobe(struct kprobe *p)
 {
-	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
-
-	fix_riprel(p);
+	/*
+	 * Copy an instruction without recovering int3, because it will be
+	 * put by another subsystem.
+	 */
+	__copy_instruction(p->ainsn.insn, p->addr, 0);
 
 	if (can_boost(p->addr))
 		p->ainsn.boostable = 0;
@@ -406,18 +432,6 @@
 		update_debugctlmsr(current->thread.debugctlmsr);
 }
 
-static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
-{
-	clear_btf();
-	regs->flags |= X86_EFLAGS_TF;
-	regs->flags &= ~X86_EFLAGS_IF;
-	/* single step inline if the instruction is an int3 */
-	if (p->opcode == BREAKPOINT_INSTRUCTION)
-		regs->ip = (unsigned long)p->addr;
-	else
-		regs->ip = (unsigned long)p->ainsn.insn;
-}
-
 void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 				      struct pt_regs *regs)
 {
@@ -429,20 +443,50 @@
 	*sara = (unsigned long) &kretprobe_trampoline;
 }
 
+#ifdef CONFIG_OPTPROBES
+static int  __kprobes setup_detour_execution(struct kprobe *p,
+					     struct pt_regs *regs,
+					     int reenter);
+#else
+#define setup_detour_execution(p, regs, reenter) (0)
+#endif
+
 static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs,
-				       struct kprobe_ctlblk *kcb)
+				       struct kprobe_ctlblk *kcb, int reenter)
 {
+	if (setup_detour_execution(p, regs, reenter))
+		return;
+
 #if !defined(CONFIG_PREEMPT)
 	if (p->ainsn.boostable == 1 && !p->post_handler) {
 		/* Boost up -- we can execute copied instructions directly */
-		reset_current_kprobe();
+		if (!reenter)
+			reset_current_kprobe();
+		/*
+		 * Reentering boosted probe doesn't reset current_kprobe,
+		 * nor set current_kprobe, because it doesn't use single
+		 * stepping.
+		 */
 		regs->ip = (unsigned long)p->ainsn.insn;
 		preempt_enable_no_resched();
 		return;
 	}
 #endif
-	prepare_singlestep(p, regs);
-	kcb->kprobe_status = KPROBE_HIT_SS;
+	if (reenter) {
+		save_previous_kprobe(kcb);
+		set_current_kprobe(p, regs, kcb);
+		kcb->kprobe_status = KPROBE_REENTER;
+	} else
+		kcb->kprobe_status = KPROBE_HIT_SS;
+	/* Prepare real single stepping */
+	clear_btf();
+	regs->flags |= X86_EFLAGS_TF;
+	regs->flags &= ~X86_EFLAGS_IF;
+	/* single step inline if the instruction is an int3 */
+	if (p->opcode == BREAKPOINT_INSTRUCTION)
+		regs->ip = (unsigned long)p->addr;
+	else
+		regs->ip = (unsigned long)p->ainsn.insn;
 }
 
 /*
@@ -456,11 +500,8 @@
 	switch (kcb->kprobe_status) {
 	case KPROBE_HIT_SSDONE:
 	case KPROBE_HIT_ACTIVE:
-		save_previous_kprobe(kcb);
-		set_current_kprobe(p, regs, kcb);
 		kprobes_inc_nmissed_count(p);
-		prepare_singlestep(p, regs);
-		kcb->kprobe_status = KPROBE_REENTER;
+		setup_singlestep(p, regs, kcb, 1);
 		break;
 	case KPROBE_HIT_SS:
 		/* A probe has been hit in the codepath leading up to, or just
@@ -535,13 +576,13 @@
 			 * more here.
 			 */
 			if (!p->pre_handler || !p->pre_handler(p, regs))
-				setup_singlestep(p, regs, kcb);
+				setup_singlestep(p, regs, kcb, 0);
 			return 1;
 		}
 	} else if (kprobe_running()) {
 		p = __get_cpu_var(current_kprobe);
 		if (p->break_handler && p->break_handler(p, regs)) {
-			setup_singlestep(p, regs, kcb);
+			setup_singlestep(p, regs, kcb, 0);
 			return 1;
 		}
 	} /* else: not a kprobe fault; let the kernel handle it */
@@ -550,6 +591,69 @@
 	return 0;
 }
 
+#ifdef CONFIG_X86_64
+#define SAVE_REGS_STRING		\
+	/* Skip cs, ip, orig_ax. */	\
+	"	subq $24, %rsp\n"	\
+	"	pushq %rdi\n"		\
+	"	pushq %rsi\n"		\
+	"	pushq %rdx\n"		\
+	"	pushq %rcx\n"		\
+	"	pushq %rax\n"		\
+	"	pushq %r8\n"		\
+	"	pushq %r9\n"		\
+	"	pushq %r10\n"		\
+	"	pushq %r11\n"		\
+	"	pushq %rbx\n"		\
+	"	pushq %rbp\n"		\
+	"	pushq %r12\n"		\
+	"	pushq %r13\n"		\
+	"	pushq %r14\n"		\
+	"	pushq %r15\n"
+#define RESTORE_REGS_STRING		\
+	"	popq %r15\n"		\
+	"	popq %r14\n"		\
+	"	popq %r13\n"		\
+	"	popq %r12\n"		\
+	"	popq %rbp\n"		\
+	"	popq %rbx\n"		\
+	"	popq %r11\n"		\
+	"	popq %r10\n"		\
+	"	popq %r9\n"		\
+	"	popq %r8\n"		\
+	"	popq %rax\n"		\
+	"	popq %rcx\n"		\
+	"	popq %rdx\n"		\
+	"	popq %rsi\n"		\
+	"	popq %rdi\n"		\
+	/* Skip orig_ax, ip, cs */	\
+	"	addq $24, %rsp\n"
+#else
+#define SAVE_REGS_STRING		\
+	/* Skip cs, ip, orig_ax and gs. */	\
+	"	subl $16, %esp\n"	\
+	"	pushl %fs\n"		\
+	"	pushl %ds\n"		\
+	"	pushl %es\n"		\
+	"	pushl %eax\n"		\
+	"	pushl %ebp\n"		\
+	"	pushl %edi\n"		\
+	"	pushl %esi\n"		\
+	"	pushl %edx\n"		\
+	"	pushl %ecx\n"		\
+	"	pushl %ebx\n"
+#define RESTORE_REGS_STRING		\
+	"	popl %ebx\n"		\
+	"	popl %ecx\n"		\
+	"	popl %edx\n"		\
+	"	popl %esi\n"		\
+	"	popl %edi\n"		\
+	"	popl %ebp\n"		\
+	"	popl %eax\n"		\
+	/* Skip ds, es, fs, gs, orig_ax, and ip. Note: don't pop cs here*/\
+	"	addl $24, %esp\n"
+#endif
+
 /*
  * When a retprobed function returns, this code saves registers and
  * calls trampoline_handler() runs, which calls the kretprobe's handler.
@@ -563,65 +667,16 @@
 			/* We don't bother saving the ss register */
 			"	pushq %rsp\n"
 			"	pushfq\n"
-			/*
-			 * Skip cs, ip, orig_ax.
-			 * trampoline_handler() will plug in these values
-			 */
-			"	subq $24, %rsp\n"
-			"	pushq %rdi\n"
-			"	pushq %rsi\n"
-			"	pushq %rdx\n"
-			"	pushq %rcx\n"
-			"	pushq %rax\n"
-			"	pushq %r8\n"
-			"	pushq %r9\n"
-			"	pushq %r10\n"
-			"	pushq %r11\n"
-			"	pushq %rbx\n"
-			"	pushq %rbp\n"
-			"	pushq %r12\n"
-			"	pushq %r13\n"
-			"	pushq %r14\n"
-			"	pushq %r15\n"
+			SAVE_REGS_STRING
 			"	movq %rsp, %rdi\n"
 			"	call trampoline_handler\n"
 			/* Replace saved sp with true return address. */
 			"	movq %rax, 152(%rsp)\n"
-			"	popq %r15\n"
-			"	popq %r14\n"
-			"	popq %r13\n"
-			"	popq %r12\n"
-			"	popq %rbp\n"
-			"	popq %rbx\n"
-			"	popq %r11\n"
-			"	popq %r10\n"
-			"	popq %r9\n"
-			"	popq %r8\n"
-			"	popq %rax\n"
-			"	popq %rcx\n"
-			"	popq %rdx\n"
-			"	popq %rsi\n"
-			"	popq %rdi\n"
-			/* Skip orig_ax, ip, cs */
-			"	addq $24, %rsp\n"
+			RESTORE_REGS_STRING
 			"	popfq\n"
 #else
 			"	pushf\n"
-			/*
-			 * Skip cs, ip, orig_ax and gs.
-			 * trampoline_handler() will plug in these values
-			 */
-			"	subl $16, %esp\n"
-			"	pushl %fs\n"
-			"	pushl %es\n"
-			"	pushl %ds\n"
-			"	pushl %eax\n"
-			"	pushl %ebp\n"
-			"	pushl %edi\n"
-			"	pushl %esi\n"
-			"	pushl %edx\n"
-			"	pushl %ecx\n"
-			"	pushl %ebx\n"
+			SAVE_REGS_STRING
 			"	movl %esp, %eax\n"
 			"	call trampoline_handler\n"
 			/* Move flags to cs */
@@ -629,15 +684,7 @@
 			"	movl %edx, 52(%esp)\n"
 			/* Replace saved flags with true return address. */
 			"	movl %eax, 56(%esp)\n"
-			"	popl %ebx\n"
-			"	popl %ecx\n"
-			"	popl %edx\n"
-			"	popl %esi\n"
-			"	popl %edi\n"
-			"	popl %ebp\n"
-			"	popl %eax\n"
-			/* Skip ds, es, fs, gs, orig_ax and ip */
-			"	addl $24, %esp\n"
+			RESTORE_REGS_STRING
 			"	popf\n"
 #endif
 			"	ret\n");
@@ -805,8 +852,8 @@
 			 * These instructions can be executed directly if it
 			 * jumps back to correct address.
 			 */
-			set_jmp_op((void *)regs->ip,
-				   (void *)orig_ip + (regs->ip - copy_ip));
+			synthesize_reljump((void *)regs->ip,
+				(void *)orig_ip + (regs->ip - copy_ip));
 			p->ainsn.boostable = 1;
 		} else {
 			p->ainsn.boostable = -1;
@@ -1033,6 +1080,358 @@
 	return 0;
 }
 
+
+#ifdef CONFIG_OPTPROBES
+
+/* Insert a call instruction at address 'from', which calls address 'to'.*/
+static void __kprobes synthesize_relcall(void *from, void *to)
+{
+	__synthesize_relative_insn(from, to, RELATIVECALL_OPCODE);
+}
+
+/* Insert a move instruction which sets a pointer to eax/rdi (1st arg). */
+static void __kprobes synthesize_set_arg1(kprobe_opcode_t *addr,
+					  unsigned long val)
+{
+#ifdef CONFIG_X86_64
+	*addr++ = 0x48;
+	*addr++ = 0xbf;
+#else
+	*addr++ = 0xb8;
+#endif
+	*(unsigned long *)addr = val;
+}
+
+void __kprobes kprobes_optinsn_template_holder(void)
+{
+	asm volatile (
+			".global optprobe_template_entry\n"
+			"optprobe_template_entry: \n"
+#ifdef CONFIG_X86_64
+			/* We don't bother saving the ss register */
+			"	pushq %rsp\n"
+			"	pushfq\n"
+			SAVE_REGS_STRING
+			"	movq %rsp, %rsi\n"
+			".global optprobe_template_val\n"
+			"optprobe_template_val: \n"
+			ASM_NOP5
+			ASM_NOP5
+			".global optprobe_template_call\n"
+			"optprobe_template_call: \n"
+			ASM_NOP5
+			/* Move flags to rsp */
+			"	movq 144(%rsp), %rdx\n"
+			"	movq %rdx, 152(%rsp)\n"
+			RESTORE_REGS_STRING
+			/* Skip flags entry */
+			"	addq $8, %rsp\n"
+			"	popfq\n"
+#else /* CONFIG_X86_32 */
+			"	pushf\n"
+			SAVE_REGS_STRING
+			"	movl %esp, %edx\n"
+			".global optprobe_template_val\n"
+			"optprobe_template_val: \n"
+			ASM_NOP5
+			".global optprobe_template_call\n"
+			"optprobe_template_call: \n"
+			ASM_NOP5
+			RESTORE_REGS_STRING
+			"	addl $4, %esp\n"	/* skip cs */
+			"	popf\n"
+#endif
+			".global optprobe_template_end\n"
+			"optprobe_template_end: \n");
+}
+
+#define TMPL_MOVE_IDX \
+	((long)&optprobe_template_val - (long)&optprobe_template_entry)
+#define TMPL_CALL_IDX \
+	((long)&optprobe_template_call - (long)&optprobe_template_entry)
+#define TMPL_END_IDX \
+	((long)&optprobe_template_end - (long)&optprobe_template_entry)
+
+#define INT3_SIZE sizeof(kprobe_opcode_t)
+
+/* Optimized kprobe call back function: called from optinsn */
+static void __kprobes optimized_callback(struct optimized_kprobe *op,
+					 struct pt_regs *regs)
+{
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	preempt_disable();
+	if (kprobe_running()) {
+		kprobes_inc_nmissed_count(&op->kp);
+	} else {
+		/* Save skipped registers */
+#ifdef CONFIG_X86_64
+		regs->cs = __KERNEL_CS;
+#else
+		regs->cs = __KERNEL_CS | get_kernel_rpl();
+		regs->gs = 0;
+#endif
+		regs->ip = (unsigned long)op->kp.addr + INT3_SIZE;
+		regs->orig_ax = ~0UL;
+
+		__get_cpu_var(current_kprobe) = &op->kp;
+		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+		opt_pre_handler(&op->kp, regs);
+		__get_cpu_var(current_kprobe) = NULL;
+	}
+	preempt_enable_no_resched();
+}
+
+static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src)
+{
+	int len = 0, ret;
+
+	while (len < RELATIVEJUMP_SIZE) {
+		ret = __copy_instruction(dest + len, src + len, 1);
+		if (!ret || !can_boost(dest + len))
+			return -EINVAL;
+		len += ret;
+	}
+	/* Check whether the address range is reserved */
+	if (ftrace_text_reserved(src, src + len - 1) ||
+	    alternatives_text_reserved(src, src + len - 1))
+		return -EBUSY;
+
+	return len;
+}
+
+/* Check whether insn is indirect jump */
+static int __kprobes insn_is_indirect_jump(struct insn *insn)
+{
+	return ((insn->opcode.bytes[0] == 0xff &&
+		(X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
+		insn->opcode.bytes[0] == 0xea);	/* Segment based jump */
+}
+
+/* Check whether insn jumps into specified address range */
+static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
+{
+	unsigned long target = 0;
+
+	switch (insn->opcode.bytes[0]) {
+	case 0xe0:	/* loopne */
+	case 0xe1:	/* loope */
+	case 0xe2:	/* loop */
+	case 0xe3:	/* jcxz */
+	case 0xe9:	/* near relative jump */
+	case 0xeb:	/* short relative jump */
+		break;
+	case 0x0f:
+		if ((insn->opcode.bytes[1] & 0xf0) == 0x80) /* jcc near */
+			break;
+		return 0;
+	default:
+		if ((insn->opcode.bytes[0] & 0xf0) == 0x70) /* jcc short */
+			break;
+		return 0;
+	}
+	target = (unsigned long)insn->next_byte + insn->immediate.value;
+
+	return (start <= target && target <= start + len);
+}
+
+/* Decode whole function to ensure any instructions don't jump into target */
+static int __kprobes can_optimize(unsigned long paddr)
+{
+	int ret;
+	unsigned long addr, size = 0, offset = 0;
+	struct insn insn;
+	kprobe_opcode_t buf[MAX_INSN_SIZE];
+	/* Dummy buffers for lookup_symbol_attrs */
+	static char __dummy_buf[KSYM_NAME_LEN];
+
+	/* Lookup symbol including addr */
+	if (!kallsyms_lookup(paddr, &size, &offset, NULL, __dummy_buf))
+		return 0;
+
+	/* Check there is enough space for a relative jump. */
+	if (size - offset < RELATIVEJUMP_SIZE)
+		return 0;
+
+	/* Decode instructions */
+	addr = paddr - offset;
+	while (addr < paddr - offset + size) { /* Decode until function end */
+		if (search_exception_tables(addr))
+			/*
+			 * Since some fixup code will jumps into this function,
+			 * we can't optimize kprobe in this function.
+			 */
+			return 0;
+		kernel_insn_init(&insn, (void *)addr);
+		insn_get_opcode(&insn);
+		if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION) {
+			ret = recover_probed_instruction(buf, addr);
+			if (ret)
+				return 0;
+			kernel_insn_init(&insn, buf);
+		}
+		insn_get_length(&insn);
+		/* Recover address */
+		insn.kaddr = (void *)addr;
+		insn.next_byte = (void *)(addr + insn.length);
+		/* Check any instructions don't jump into target */
+		if (insn_is_indirect_jump(&insn) ||
+		    insn_jump_into_range(&insn, paddr + INT3_SIZE,
+					 RELATIVE_ADDR_SIZE))
+			return 0;
+		addr += insn.length;
+	}
+
+	return 1;
+}
+
+/* Check optimized_kprobe can actually be optimized. */
+int __kprobes arch_check_optimized_kprobe(struct optimized_kprobe *op)
+{
+	int i;
+	struct kprobe *p;
+
+	for (i = 1; i < op->optinsn.size; i++) {
+		p = get_kprobe(op->kp.addr + i);
+		if (p && !kprobe_disabled(p))
+			return -EEXIST;
+	}
+
+	return 0;
+}
+
+/* Check the addr is within the optimized instructions. */
+int __kprobes arch_within_optimized_kprobe(struct optimized_kprobe *op,
+					   unsigned long addr)
+{
+	return ((unsigned long)op->kp.addr <= addr &&
+		(unsigned long)op->kp.addr + op->optinsn.size > addr);
+}
+
+/* Free optimized instruction slot */
+static __kprobes
+void __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty)
+{
+	if (op->optinsn.insn) {
+		free_optinsn_slot(op->optinsn.insn, dirty);
+		op->optinsn.insn = NULL;
+		op->optinsn.size = 0;
+	}
+}
+
+void __kprobes arch_remove_optimized_kprobe(struct optimized_kprobe *op)
+{
+	__arch_remove_optimized_kprobe(op, 1);
+}
+
+/*
+ * Copy replacing target instructions
+ * Target instructions MUST be relocatable (checked inside)
+ */
+int __kprobes arch_prepare_optimized_kprobe(struct optimized_kprobe *op)
+{
+	u8 *buf;
+	int ret;
+	long rel;
+
+	if (!can_optimize((unsigned long)op->kp.addr))
+		return -EILSEQ;
+
+	op->optinsn.insn = get_optinsn_slot();
+	if (!op->optinsn.insn)
+		return -ENOMEM;
+
+	/*
+	 * Verify if the address gap is in 2GB range, because this uses
+	 * a relative jump.
+	 */
+	rel = (long)op->optinsn.insn - (long)op->kp.addr + RELATIVEJUMP_SIZE;
+	if (abs(rel) > 0x7fffffff)
+		return -ERANGE;
+
+	buf = (u8 *)op->optinsn.insn;
+
+	/* Copy instructions into the out-of-line buffer */
+	ret = copy_optimized_instructions(buf + TMPL_END_IDX, op->kp.addr);
+	if (ret < 0) {
+		__arch_remove_optimized_kprobe(op, 0);
+		return ret;
+	}
+	op->optinsn.size = ret;
+
+	/* Copy arch-dep-instance from template */
+	memcpy(buf, &optprobe_template_entry, TMPL_END_IDX);
+
+	/* Set probe information */
+	synthesize_set_arg1(buf + TMPL_MOVE_IDX, (unsigned long)op);
+
+	/* Set probe function call */
+	synthesize_relcall(buf + TMPL_CALL_IDX, optimized_callback);
+
+	/* Set returning jmp instruction at the tail of out-of-line buffer */
+	synthesize_reljump(buf + TMPL_END_IDX + op->optinsn.size,
+			   (u8 *)op->kp.addr + op->optinsn.size);
+
+	flush_icache_range((unsigned long) buf,
+			   (unsigned long) buf + TMPL_END_IDX +
+			   op->optinsn.size + RELATIVEJUMP_SIZE);
+	return 0;
+}
+
+/* Replace a breakpoint (int3) with a relative jump.  */
+int __kprobes arch_optimize_kprobe(struct optimized_kprobe *op)
+{
+	unsigned char jmp_code[RELATIVEJUMP_SIZE];
+	s32 rel = (s32)((long)op->optinsn.insn -
+			((long)op->kp.addr + RELATIVEJUMP_SIZE));
+
+	/* Backup instructions which will be replaced by jump address */
+	memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
+	       RELATIVE_ADDR_SIZE);
+
+	jmp_code[0] = RELATIVEJUMP_OPCODE;
+	*(s32 *)(&jmp_code[1]) = rel;
+
+	/*
+	 * 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;
+}
+
+/* Replace a relative jump with a breakpoint (int3).  */
+void __kprobes arch_unoptimize_kprobe(struct optimized_kprobe *op)
+{
+	u8 buf[RELATIVEJUMP_SIZE];
+
+	/* Set int3 to first byte for kprobes */
+	buf[0] = BREAKPOINT_INSTRUCTION;
+	memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
+	text_poke_smp(op->kp.addr, buf, RELATIVEJUMP_SIZE);
+}
+
+static int  __kprobes setup_detour_execution(struct kprobe *p,
+					     struct pt_regs *regs,
+					     int reenter)
+{
+	struct optimized_kprobe *op;
+
+	if (p->flags & KPROBE_FLAG_OPTIMIZED) {
+		/* This kprobe is really able to run optimized path. */
+		op = container_of(p, struct optimized_kprobe, kp);
+		/* Detour through copied instructions */
+		regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
+		if (!reenter)
+			reset_current_kprobe();
+		preempt_enable_no_resched();
+		return 1;
+	}
+	return 0;
+}
+#endif
+
 int __init arch_init_kprobes(void)
 {
 	return 0;
diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c
index 712d15f..7182580 100644
--- a/arch/x86/kernel/mmconf-fam10h_64.c
+++ b/arch/x86/kernel/mmconf-fam10h_64.c
@@ -7,6 +7,8 @@
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <linux/dmi.h>
+#include <linux/range.h>
+
 #include <asm/pci-direct.h>
 #include <linux/sort.h>
 #include <asm/io.h>
@@ -30,11 +32,6 @@
 	{ 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 },
 };
 
-struct range {
-	u64 start;
-	u64 end;
-};
-
 static int __cpuinit cmp_range(const void *x1, const void *x2)
 {
 	const struct range *r1 = x1;
diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c
index 3b7078a..0aad867 100644
--- a/arch/x86/kernel/mrst.c
+++ b/arch/x86/kernel/mrst.c
@@ -10,8 +10,211 @@
  * of the License.
  */
 #include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sfi.h>
+#include <linux/irq.h>
+#include <linux/module.h>
 
 #include <asm/setup.h>
+#include <asm/mpspec_def.h>
+#include <asm/hw_irq.h>
+#include <asm/apic.h>
+#include <asm/io_apic.h>
+#include <asm/mrst.h>
+#include <asm/io.h>
+#include <asm/i8259.h>
+#include <asm/apb_timer.h>
+
+static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
+static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
+int sfi_mtimer_num;
+
+struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
+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)
+{
+	struct sfi_table_simple *sb;
+	struct sfi_timer_table_entry *pentry;
+	struct mpc_intsrc mp_irq;
+	int totallen;
+
+	sb = (struct sfi_table_simple *)table;
+	if (!sfi_mtimer_num) {
+		sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb,
+					struct sfi_timer_table_entry);
+		pentry = (struct sfi_timer_table_entry *) sb->pentry;
+		totallen = sfi_mtimer_num * sizeof(*pentry);
+		memcpy(sfi_mtimer_array, pentry, totallen);
+	}
+
+	printk(KERN_INFO "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,"
+			" irq = %d\n", totallen, (u32)pentry->phys_addr,
+			pentry->freq_hz, pentry->irq);
+			if (!pentry->irq)
+				continue;
+			mp_irq.type = MP_IOAPIC;
+			mp_irq.irqtype = mp_INT;
+/* triggering mode edge bit 2-3, active high polarity bit 0-1 */
+			mp_irq.irqflag = 5;
+			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);
+	}
+
+	return 0;
+}
+
+struct sfi_timer_table_entry *sfi_get_mtmr(int hint)
+{
+	int i;
+	if (hint < sfi_mtimer_num) {
+		if (!sfi_mtimer_usage[hint]) {
+			pr_debug("hint taken for timer %d irq %d\n",\
+				hint, sfi_mtimer_array[hint].irq);
+			sfi_mtimer_usage[hint] = 1;
+			return &sfi_mtimer_array[hint];
+		}
+	}
+	/* take the first timer available */
+	for (i = 0; i < sfi_mtimer_num;) {
+		if (!sfi_mtimer_usage[i]) {
+			sfi_mtimer_usage[i] = 1;
+			return &sfi_mtimer_array[i];
+		}
+		i++;
+	}
+	return NULL;
+}
+
+void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr)
+{
+	int i;
+	for (i = 0; i < sfi_mtimer_num;) {
+		if (mtmr->irq == sfi_mtimer_array[i].irq) {
+			sfi_mtimer_usage[i] = 0;
+			return;
+		}
+		i++;
+	}
+}
+
+/* parse all the mrtc info to a global mrtc array */
+int __init sfi_parse_mrtc(struct sfi_table_header *table)
+{
+	struct sfi_table_simple *sb;
+	struct sfi_rtc_table_entry *pentry;
+	struct mpc_intsrc mp_irq;
+
+	int totallen;
+
+	sb = (struct sfi_table_simple *)table;
+	if (!sfi_mrtc_num) {
+		sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb,
+						struct sfi_rtc_table_entry);
+		pentry = (struct sfi_rtc_table_entry *)sb->pentry;
+		totallen = sfi_mrtc_num * sizeof(*pentry);
+		memcpy(sfi_mrtc_array, pentry, totallen);
+	}
+
+	printk(KERN_INFO "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",
+			totallen, (u32)pentry->phys_addr, pentry->irq);
+		mp_irq.type = MP_IOAPIC;
+		mp_irq.irqtype = mp_INT;
+		mp_irq.irqflag = 0;
+		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);
+	}
+	return 0;
+}
+
+/*
+ * the secondary clock in Moorestown can be APBT or LAPIC clock, default to
+ * APBT but cmdline option can also override it.
+ */
+static void __cpuinit mrst_setup_secondary_clock(void)
+{
+	/* restore default lapic clock if disabled by cmdline */
+	if (disable_apbt_percpu)
+		return setup_secondary_APIC_clock();
+	apbt_setup_secondary_clock();
+}
+
+static unsigned long __init mrst_calibrate_tsc(void)
+{
+	unsigned long flags, fast_calibrate;
+
+	local_irq_save(flags);
+	fast_calibrate = apbt_quick_calibrate();
+	local_irq_restore(flags);
+
+	if (fast_calibrate)
+		return fast_calibrate;
+
+	return 0;
+}
+
+void __init mrst_time_init(void)
+{
+	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);
+}
+
+/*
+ * if we use per cpu apb timer, the bootclock already setup. if we use lapic
+ * timer and one apbt timer for broadcast, we need to set up lapic boot clock.
+ */
+static void __init mrst_setup_boot_clock(void)
+{
+	pr_info("%s: per cpu apbt flag %d \n", __func__, disable_apbt_percpu);
+	if (disable_apbt_percpu)
+		setup_boot_APIC_clock();
+};
 
 /*
  * Moorestown specific x86_init function overrides and early setup
@@ -21,4 +224,17 @@
 {
 	x86_init.resources.probe_roms = x86_init_noop;
 	x86_init.resources.reserve_resources = x86_init_noop;
+
+	x86_init.timers.timer_init = mrst_time_init;
+	x86_init.timers.setup_percpu_clockev = mrst_setup_boot_clock;
+
+	x86_init.irqs.pre_vector_init = x86_init_noop;
+
+	x86_cpuinit.setup_percpu_clockev = mrst_setup_secondary_clock;
+
+	x86_platform.calibrate_tsc = mrst_calibrate_tsc;
+	x86_init.pci.init = pci_mrst_init;
+	x86_init.pci.fixup_irqs = x86_init_noop;
+
+	legacy_pic = &null_legacy_pic;
 }
diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c
index 9d1d263..8297160 100644
--- a/arch/x86/kernel/olpc.c
+++ b/arch/x86/kernel/olpc.c
@@ -17,7 +17,9 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/string.h>
+
 #include <asm/geode.h>
+#include <asm/setup.h>
 #include <asm/olpc.h>
 
 #ifdef CONFIG_OPEN_FIRMWARE
@@ -243,9 +245,11 @@
 	olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0,
 			(unsigned char *) &olpc_platform_info.ecver, 1);
 
-	/* check to see if the VSA exists */
-	if (cs5535_has_vsa2())
-		olpc_platform_info.flags |= OLPC_F_VSA;
+#ifdef CONFIG_PCI_OLPC
+	/* If the VSA exists let it emulate PCI, if not emulate in kernel */
+	if (!cs5535_has_vsa2())
+		x86_init.pci.arch_init = pci_olpc_init;
+#endif
 
 	printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
 			((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 1b1739d..1db183e 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -428,10 +428,6 @@
 	.ptep_modify_prot_start = __ptep_modify_prot_start,
 	.ptep_modify_prot_commit = __ptep_modify_prot_commit,
 
-#ifdef CONFIG_HIGHPTE
-	.kmap_atomic_pte = kmap_atomic,
-#endif
-
 #if PAGETABLE_LEVELS >= 3
 #ifdef CONFIG_X86_PAE
 	.set_pte_atomic = native_set_pte_atomic,
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 2bbde60..fb99f7e 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -1309,7 +1309,7 @@
 /*
  * get_tce_space_from_tar():
  * Function for kdump case. Get the tce tables from first kernel
- * by reading the contents of the base adress register of calgary iommu
+ * by reading the contents of the base address register of calgary iommu
  */
 static void __init get_tce_space_from_tar(void)
 {
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 75e14e2..a4ac764 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -38,7 +38,7 @@
  * This variable becomes 1 if iommu=pt is passed on the kernel command line.
  * If this variable is 1, IOMMU implementations do no DMA translation for
  * devices and allow every device to access to whole physical memory. This is
- * useful if a user want to use an IOMMU only for KVM device assignment to
+ * useful if a user wants to use an IOMMU only for KVM device assignment to
  * guests and not for driver dma translation.
  */
 int iommu_pass_through __read_mostly;
@@ -65,7 +65,7 @@
 }
 EXPORT_SYMBOL(dma_set_mask);
 
-#ifdef CONFIG_X86_64
+#if defined(CONFIG_X86_64) && !defined(CONFIG_NUMA)
 static __initdata void *dma32_bootmem_ptr;
 static unsigned long dma32_bootmem_size __initdata = (128ULL<<20);
 
@@ -116,14 +116,21 @@
 	dma32_bootmem_ptr = NULL;
 	dma32_bootmem_size = 0;
 }
+#else
+void __init dma32_reserve_bootmem(void)
+{
+}
+static void __init dma32_free_bootmem(void)
+{
+}
+
 #endif
 
 void __init pci_iommu_alloc(void)
 {
-#ifdef CONFIG_X86_64
 	/* free the range so iommu could get some range less than 4G */
 	dma32_free_bootmem();
-#endif
+
 	if (pci_swiotlb_detect())
 		goto out;
 
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 34de53b..f3af115 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -735,7 +735,7 @@
 	unsigned long scratch;
 	long i;
 
-	if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0)
+	if (num_k8_northbridges == 0)
 		return 0;
 
 #ifndef CONFIG_AGP_AMD64
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 02d6780..ad95406 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -607,7 +607,7 @@
 {
 #ifdef CONFIG_SMP
 	if (pm_idle == poll_idle && smp_num_siblings > 1) {
-		printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
+		printk_once(KERN_WARNING "WARNING: polling idle and HT enabled,"
 			" performance may degrade.\n");
 	}
 #endif
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 2d96aab..a503b1f 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -581,7 +581,7 @@
 	struct perf_event_attr attr;
 
 	/*
-	 * We shoud have at least an inactive breakpoint at this
+	 * We should have at least an inactive breakpoint at this
 	 * slot. It means the user is writing dr7 without having
 	 * written the address register first
 	 */
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 704bddc..8e1aac8 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -461,6 +461,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini3,1"),
 		},
 	},
+	{	/* Handle problems with rebooting on the iMac9,1. */
+		.callback = set_pci_reboot,
+		.ident = "Apple iMac9,1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
+		},
+	},
 	{ }
 };
 
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index cb42109..5d7ba1a 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -969,16 +969,12 @@
 #endif
 
 	initmem_init(0, max_pfn, acpi, k8);
-
-#ifdef CONFIG_X86_64
-	/*
-	 * dma32_reserve_bootmem() allocates bootmem which may conflict
-	 * with the crashkernel command line, so do that after
-	 * reserve_crashkernel()
-	 */
-	dma32_reserve_bootmem();
+#ifndef CONFIG_NO_BOOTMEM
+	early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT);
 #endif
 
+	dma32_reserve_bootmem();
+
 	reserve_ibft_region();
 
 #ifdef CONFIG_KVM_CLOCK
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 35abcb8..ef6370b 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -137,7 +137,13 @@
 
 static void __init pcpu_fc_free(void *ptr, size_t size)
 {
+#ifdef CONFIG_NO_BOOTMEM
+	u64 start = __pa(ptr);
+	u64 end = start + size;
+	free_early_partial(start, end);
+#else
 	free_bootmem(__pa(ptr), size);
+#endif
 }
 
 static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 9b44011..a02e80c 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -48,6 +48,7 @@
 #include <linux/err.h>
 #include <linux/nmi.h>
 #include <linux/tboot.h>
+#include <linux/stackprotector.h>
 
 #include <asm/acpi.h>
 #include <asm/desc.h>
@@ -67,6 +68,7 @@
 #include <linux/mc146818rtc.h>
 
 #include <asm/smpboot_hooks.h>
+#include <asm/i8259.h>
 
 #ifdef CONFIG_X86_32
 u8 apicid_2_node[MAX_APICID];
@@ -241,6 +243,11 @@
 	map_cpu_to_logical_apicid();
 
 	notify_cpu_starting(cpuid);
+
+	/*
+	 * Need to setup vector mappings before we enable interrupts.
+	 */
+	__setup_vector_irq(smp_processor_id());
 	/*
 	 * Get our bogomips.
 	 *
@@ -286,9 +293,9 @@
 	check_tsc_sync_target();
 
 	if (nmi_watchdog == NMI_IO_APIC) {
-		disable_8259A_irq(0);
+		legacy_pic->chip->mask(0);
 		enable_NMI_through_LVT0();
-		enable_8259A_irq(0);
+		legacy_pic->chip->unmask(0);
 	}
 
 #ifdef CONFIG_X86_32
@@ -315,7 +322,6 @@
 	 */
 	ipi_call_lock();
 	lock_vector_lock();
-	__setup_vector_irq(smp_processor_id());
 	set_cpu_online(smp_processor_id(), true);
 	unlock_vector_lock();
 	ipi_call_unlock();
@@ -325,6 +331,9 @@
 	/* enable local interrupts */
 	local_irq_enable();
 
+	/* to prevent fake stack check failure in clock setup */
+	boot_init_stack_canary();
+
 	x86_cpuinit.setup_percpu_clockev();
 
 	wmb();
@@ -1212,11 +1221,12 @@
 
 	total_cpus = max_t(int, possible, num_processors + disabled_cpus);
 
-	if (possible > CONFIG_NR_CPUS) {
+	/* nr_cpu_ids could be reduced via nr_cpus= */
+	if (possible > nr_cpu_ids) {
 		printk(KERN_WARNING
 			"%d Processors exceeds NR_CPUS limit of %d\n",
-			possible, CONFIG_NR_CPUS);
-		possible = CONFIG_NR_CPUS;
+			possible, nr_cpu_ids);
+		possible = nr_cpu_ids;
 	}
 
 	printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c
index dee1ff7..196552b 100644
--- a/arch/x86/kernel/sys_i386_32.c
+++ b/arch/x86/kernel/sys_i386_32.c
@@ -25,191 +25,6 @@
 #include <asm/syscalls.h>
 
 /*
- * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls. Linux/i386 didn't use to be able to handle more than
- * 4 system call parameters, so these system calls used a memory
- * block for parameter passing..
- */
-
-struct mmap_arg_struct {
-	unsigned long addr;
-	unsigned long len;
-	unsigned long prot;
-	unsigned long flags;
-	unsigned long fd;
-	unsigned long offset;
-};
-
-asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
-{
-	struct mmap_arg_struct a;
-	int err = -EFAULT;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		goto out;
-
-	err = -EINVAL;
-	if (a.offset & ~PAGE_MASK)
-		goto out;
-
-	err = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags,
-			a.fd, a.offset >> PAGE_SHIFT);
-out:
-	return err;
-}
-
-
-struct sel_arg_struct {
-	unsigned long n;
-	fd_set __user *inp, *outp, *exp;
-	struct timeval __user *tvp;
-};
-
-asmlinkage int old_select(struct sel_arg_struct __user *arg)
-{
-	struct sel_arg_struct a;
-
-	if (copy_from_user(&a, arg, sizeof(a)))
-		return -EFAULT;
-	/* sys_select() does the appropriate kernel locking */
-	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-}
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-asmlinkage int sys_ipc(uint call, int first, int second,
-			int third, void __user *ptr, long fifth)
-{
-	int version, ret;
-
-	version = call >> 16; /* hack for backward compatibility */
-	call &= 0xffff;
-
-	switch (call) {
-	case SEMOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr, second, NULL);
-	case SEMTIMEDOP:
-		return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
-					(const struct timespec __user *)fifth);
-
-	case SEMGET:
-		return sys_semget(first, second, third);
-	case SEMCTL: {
-		union semun fourth;
-		if (!ptr)
-			return -EINVAL;
-		if (get_user(fourth.__pad, (void __user * __user *) ptr))
-			return -EFAULT;
-		return sys_semctl(first, second, third, fourth);
-	}
-
-	case MSGSND:
-		return sys_msgsnd(first, (struct msgbuf __user *) ptr,
-				   second, third);
-	case MSGRCV:
-		switch (version) {
-		case 0: {
-			struct ipc_kludge tmp;
-			if (!ptr)
-				return -EINVAL;
-
-			if (copy_from_user(&tmp,
-					   (struct ipc_kludge __user *) ptr,
-					   sizeof(tmp)))
-				return -EFAULT;
-			return sys_msgrcv(first, tmp.msgp, second,
-					   tmp.msgtyp, third);
-		}
-		default:
-			return sys_msgrcv(first,
-					   (struct msgbuf __user *) ptr,
-					   second, fifth, third);
-		}
-	case MSGGET:
-		return sys_msgget((key_t) first, second);
-	case MSGCTL:
-		return sys_msgctl(first, second, (struct msqid_ds __user *) ptr);
-
-	case SHMAT:
-		switch (version) {
-		default: {
-			ulong raddr;
-			ret = do_shmat(first, (char __user *) ptr, second, &raddr);
-			if (ret)
-				return ret;
-			return put_user(raddr, (ulong __user *) third);
-		}
-		case 1:	/* iBCS2 emulator entry point */
-			if (!segment_eq(get_fs(), get_ds()))
-				return -EINVAL;
-			/* The "(ulong *) third" is valid _only_ because of the kernel segment thing */
-			return do_shmat(first, (char __user *) ptr, second, (ulong *) third);
-		}
-	case SHMDT:
-		return sys_shmdt((char __user *)ptr);
-	case SHMGET:
-		return sys_shmget(first, second, third);
-	case SHMCTL:
-		return sys_shmctl(first, second,
-				   (struct shmid_ds __user *) ptr);
-	default:
-		return -ENOSYS;
-	}
-}
-
-/*
- * Old cruft
- */
-asmlinkage int sys_uname(struct old_utsname __user *name)
-{
-	int err;
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err = copy_to_user(name, utsname(), sizeof(*name));
-	up_read(&uts_sem);
-	return err? -EFAULT:0;
-}
-
-asmlinkage int sys_olduname(struct oldold_utsname __user *name)
-{
-	int error;
-
-	if (!name)
-		return -EFAULT;
-	if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
-		return -EFAULT;
-
-	down_read(&uts_sem);
-
-	error = __copy_to_user(&name->sysname, &utsname()->sysname,
-			       __OLD_UTS_LEN);
-	error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->nodename, &utsname()->nodename,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->release, &utsname()->release,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->release + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->version, &utsname()->version,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->version + __OLD_UTS_LEN);
-	error |= __copy_to_user(&name->machine, &utsname()->machine,
-				__OLD_UTS_LEN);
-	error |= __put_user(0, name->machine + __OLD_UTS_LEN);
-
-	up_read(&uts_sem);
-
-	error = error ? -EFAULT : 0;
-
-	return error;
-}
-
-
-/*
  * Do a system call from kernel instead of calling sys_execve so we
  * end up with proper pt_regs.
  */
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
index 8aa2057..ff14a50 100644
--- a/arch/x86/kernel/sys_x86_64.c
+++ b/arch/x86/kernel/sys_x86_64.c
@@ -209,15 +209,3 @@
 
 	return addr;
 }
-
-
-SYSCALL_DEFINE1(uname, struct new_utsname __user *, name)
-{
-	int err;
-	down_read(&uts_sem);
-	err = copy_to_user(name, utsname(), sizeof(*name));
-	up_read(&uts_sem);
-	if (personality(current->personality) == PER_LINUX32)
-		err |= copy_to_user(&name->machine, "i686", 5);
-	return err ? -EFAULT : 0;
-}
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index 15228b5..8b37293 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -81,7 +81,7 @@
 	.long sys_settimeofday
 	.long sys_getgroups16	/* 80 */
 	.long sys_setgroups16
-	.long old_select
+	.long sys_old_select
 	.long sys_symlink
 	.long sys_lstat
 	.long sys_readlink	/* 85 */
@@ -89,7 +89,7 @@
 	.long sys_swapon
 	.long sys_reboot
 	.long sys_old_readdir
-	.long old_mmap		/* 90 */
+	.long sys_old_mmap	/* 90 */
 	.long sys_munmap
 	.long sys_truncate
 	.long sys_ftruncate
diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c
index be25734..fb5cc5e1 100644
--- a/arch/x86/kernel/time.c
+++ b/arch/x86/kernel/time.c
@@ -70,11 +70,11 @@
 		 * manually to deassert NMI lines for the watchdog if run
 		 * on an 82489DX-based system.
 		 */
-		spin_lock(&i8259A_lock);
+		raw_spin_lock(&i8259A_lock);
 		outb(0x0c, PIC_MASTER_OCW3);
 		/* Ack the IRQ; AEOI will end it automatically. */
 		inb(PIC_MASTER_POLL);
-		spin_unlock(&i8259A_lock);
+		raw_spin_unlock(&i8259A_lock);
 	}
 
 	global_clock_event->event_handler(global_clock_event);
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 208a857..9faf91a 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -50,7 +50,7 @@
 	 *   unstable. We do this because unlike Time Of Day,
 	 *   the scheduler clock tolerates small errors and it's
 	 *   very important for it to be as fast as the platform
-	 *   can achive it. )
+	 *   can achieve it. )
 	 */
 	if (unlikely(tsc_disabled)) {
 		/* No locking but a rare wrong value is not a big deal: */
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c
index 34a279a..e680ea5 100644
--- a/arch/x86/kernel/visws_quirks.c
+++ b/arch/x86/kernel/visws_quirks.c
@@ -49,11 +49,6 @@
 char visws_board_type	= -1;
 char visws_board_rev	= -1;
 
-int is_visws_box(void)
-{
-	return visws_board_type >= 0;
-}
-
 static void __init visws_time_init(void)
 {
 	printk(KERN_INFO "Starting Cobalt Timer system clock\n");
@@ -242,6 +237,8 @@
 	x86_init.irqs.pre_vector_init = visws_pre_intr_init;
 	x86_init.irqs.trap_init = visws_trap_init;
 	x86_init.timers.timer_init = visws_time_init;
+	x86_init.pci.init = pci_visws_init;
+	x86_init.pci.init_irq = x86_init_noop;
 
 	/*
 	 * Install reboot quirks:
@@ -508,7 +505,7 @@
  */
 static unsigned int startup_piix4_master_irq(unsigned int irq)
 {
-	init_8259A(0);
+	legacy_pic->init(0);
 
 	return startup_cobalt_irq(irq);
 }
@@ -532,9 +529,6 @@
 
 static struct irq_chip piix4_virtual_irq_type = {
 	.name =		"PIIX4-virtual",
-	.shutdown =	disable_8259A_irq,
-	.enable =	enable_8259A_irq,
-	.disable =	disable_8259A_irq,
 };
 
 
@@ -559,7 +553,7 @@
 	struct irq_desc *desc;
 	unsigned long flags;
 
-	spin_lock_irqsave(&i8259A_lock, flags);
+	raw_spin_lock_irqsave(&i8259A_lock, flags);
 
 	/* Find out what's interrupting in the PIIX4 master 8259 */
 	outb(0x0c, 0x20);		/* OCW3 Poll command */
@@ -596,7 +590,7 @@
 		outb(0x60 + realirq, 0x20);
 	}
 
-	spin_unlock_irqrestore(&i8259A_lock, flags);
+	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 
 	desc = irq_to_desc(realirq);
 
@@ -609,12 +603,12 @@
 		handle_IRQ_event(realirq, desc->action);
 
 	if (!(desc->status & IRQ_DISABLED))
-		enable_8259A_irq(realirq);
+		legacy_pic->chip->unmask(realirq);
 
 	return IRQ_HANDLED;
 
 out_unlock:
-	spin_unlock_irqrestore(&i8259A_lock, flags);
+	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 	return IRQ_NONE;
 }
 
@@ -628,6 +622,12 @@
 	.name =		"cascade",
 };
 
+static inline void set_piix4_virtual_irq_type(void)
+{
+	piix4_virtual_irq_type.shutdown = i8259A_chip.mask;
+	piix4_virtual_irq_type.enable =	i8259A_chip.unmask;
+	piix4_virtual_irq_type.disable = i8259A_chip.mask;
+}
 
 void init_VISWS_APIC_irqs(void)
 {
@@ -653,6 +653,7 @@
 			desc->chip = &piix4_master_irq_type;
 		}
 		else if (i < CO_IRQ_APIC0) {
+			set_piix4_virtual_irq_type();
 			desc->chip = &piix4_virtual_irq_type;
 		}
 		else if (IS_CO_APIC(i)) {
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index d430e4c..7dd599d 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -33,6 +33,7 @@
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
 #include <asm/apic.h>
+#include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/timer.h>
 #include <asm/vmi_time.h>
@@ -266,30 +267,6 @@
 {
 }
 
-#ifdef CONFIG_HIGHPTE
-static void *vmi_kmap_atomic_pte(struct page *page, enum km_type type)
-{
-	void *va = kmap_atomic(page, type);
-
-	/*
-	 * Internally, the VMI ROM must map virtual addresses to physical
-	 * addresses for processing MMU updates.  By the time MMU updates
-	 * are issued, this information is typically already lost.
-	 * Fortunately, the VMI provides a cache of mapping slots for active
-	 * page tables.
-	 *
-	 * We use slot zero for the linear mapping of physical memory, and
-	 * in HIGHPTE kernels, slot 1 and 2 for KM_PTE0 and KM_PTE1.
-	 *
-	 *  args:                 SLOT                 VA    COUNT PFN
-	 */
-	BUG_ON(type != KM_PTE0 && type != KM_PTE1);
-	vmi_ops.set_linear_mapping((type - KM_PTE0)+1, va, 1, page_to_pfn(page));
-
-	return va;
-}
-#endif
-
 static void vmi_allocate_pte(struct mm_struct *mm, unsigned long pfn)
 {
 	vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0);
@@ -640,6 +617,12 @@
 	u64 reloc;
 	const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc;
 
+	/*
+	 * Prevent page tables from being allocated in highmem, even if
+	 * CONFIG_HIGHPTE is enabled.
+	 */
+	__userpte_alloc_gfp &= ~__GFP_HIGHMEM;
+
 	if (call_vrom_func(vmi_rom, vmi_init) != 0) {
 		printk(KERN_ERR "VMI ROM failed to initialize!");
 		return 0;
@@ -778,10 +761,6 @@
 
 	/* Set linear is needed in all cases */
 	vmi_ops.set_linear_mapping = vmi_get_function(VMI_CALL_SetLinearMapping);
-#ifdef CONFIG_HIGHPTE
-	if (vmi_ops.set_linear_mapping)
-		pv_mmu_ops.kmap_atomic_pte = vmi_kmap_atomic_pte;
-#endif
 
 	/*
 	 * These MUST always be patched.  Don't support indirect jumps
diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c
index 74c92bb..5e1ff66 100644
--- a/arch/x86/kernel/vmiclock_32.c
+++ b/arch/x86/kernel/vmiclock_32.c
@@ -79,11 +79,7 @@
 
 static inline unsigned int vmi_get_timer_vector(void)
 {
-#ifdef CONFIG_X86_IO_APIC
-	return FIRST_DEVICE_VECTOR;
-#else
-	return FIRST_EXTERNAL_VECTOR;
-#endif
+	return IRQ0_VECTOR;
 }
 
 /** vmi clockchip */
@@ -171,7 +167,7 @@
 {
 	/* Unfortunately, set_next_event interface only passes relative
 	 * expiry, but we want absolute expiry.  It'd be better if were
-	 * were passed an aboslute expiry, since a bunch of time may
+	 * were passed an absolute expiry, since a bunch of time may
 	 * have been stolen between the time the delta is computed and
 	 * when we set the alarm below. */
 	cycle_t now = vmi_timer_ops.get_cycle_counter(vmi_counter(VMI_ONESHOT));
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index f92a0da..44879df 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -341,7 +341,7 @@
  * Per-cpu symbols which need to be offset from __per_cpu_load
  * for the boot processor.
  */
-#define INIT_PER_CPU(x) init_per_cpu__##x = per_cpu__##x + __per_cpu_load
+#define INIT_PER_CPU(x) init_per_cpu__##x = x + __per_cpu_load
 INIT_PER_CPU(gdt_page);
 INIT_PER_CPU(irq_stack_union);
 
@@ -352,7 +352,7 @@
 	   "kernel image bigger than KERNEL_IMAGE_SIZE");
 
 #ifdef CONFIG_SMP
-. = ASSERT((per_cpu__irq_stack_union == 0),
+. = ASSERT((irq_stack_union == 0),
            "irq_stack_union is not at start of per-cpu area");
 #endif
 
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 9055e58..1c0c6ab 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -301,7 +301,8 @@
 	register_sysctl_table(kernel_root_table2);
 #endif
 	on_each_cpu(cpu_vsyscall_init, NULL, 1);
-	hotcpu_notifier(cpu_vsyscall_notifier, 0);
+	/* notifier priority > KVM */
+	hotcpu_notifier(cpu_vsyscall_notifier, 30);
 	return 0;
 }
 
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index ee5746c9..61a1e8c 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -4,9 +4,11 @@
  *  For licencing details see kernel-base/COPYING
  */
 #include <linux/init.h>
+#include <linux/ioport.h>
 
 #include <asm/bios_ebda.h>
 #include <asm/paravirt.h>
+#include <asm/pci_x86.h>
 #include <asm/mpspec.h>
 #include <asm/setup.h>
 #include <asm/apic.h>
@@ -70,6 +72,12 @@
 	.iommu = {
 		.iommu_init		= iommu_init_noop,
 	},
+
+	.pci = {
+		.init			= x86_default_pci_init,
+		.init_irq		= x86_default_pci_init_irq,
+		.fixup_irqs		= x86_default_pci_fixup_irqs,
+	},
 };
 
 struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = {
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 3c4d0109..970bbd4 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -29,6 +29,7 @@
 	select HAVE_KVM_EVENTFD
 	select KVM_APIC_ARCHITECTURE
 	select USER_RETURN_NOTIFIER
+	select KVM_MMIO
 	---help---
 	  Support hosting fully virtualized guest machines using hardware
 	  virtualization extensions.  You will need a fairly recent
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 7e8faea..4dade6a 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -32,7 +32,7 @@
 #include <linux/module.h>
 #include <asm/kvm_emulate.h>
 
-#include "mmu.h"		/* for is_long_mode() */
+#include "x86.h"
 
 /*
  * Opcode effective-address decode tables.
@@ -76,6 +76,8 @@
 #define GroupDual   (1<<15)     /* Alternate decoding of mod == 3 */
 #define GroupMask   0xff        /* Group number stored in bits 0:7 */
 /* Misc flags */
+#define Lock        (1<<26) /* lock prefix is allowed for the instruction */
+#define Priv        (1<<27) /* instruction generates #GP if current CPL != 0 */
 #define No64	    (1<<28)
 /* Source 2 operand type */
 #define Src2None    (0<<29)
@@ -88,39 +90,40 @@
 enum {
 	Group1_80, Group1_81, Group1_82, Group1_83,
 	Group1A, Group3_Byte, Group3, Group4, Group5, Group7,
+	Group8, Group9,
 };
 
 static u32 opcode_table[256] = {
 	/* 0x00 - 0x07 */
-	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+	ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
 	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
 	ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,
 	ImplicitOps | Stack | No64, ImplicitOps | Stack | No64,
 	/* 0x08 - 0x0F */
-	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+	ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
 	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
 	ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,
 	ImplicitOps | Stack | No64, 0,
 	/* 0x10 - 0x17 */
-	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+	ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
 	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
 	ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,
 	ImplicitOps | Stack | No64, ImplicitOps | Stack | No64,
 	/* 0x18 - 0x1F */
-	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+	ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
 	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
 	ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,
 	ImplicitOps | Stack | No64, ImplicitOps | Stack | No64,
 	/* 0x20 - 0x27 */
-	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+	ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
 	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
 	DstAcc | SrcImmByte, DstAcc | SrcImm, 0, 0,
 	/* 0x28 - 0x2F */
-	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+	ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
 	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
 	0, 0, 0, 0,
 	/* 0x30 - 0x37 */
-	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+	ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
 	ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
 	0, 0, 0, 0,
 	/* 0x38 - 0x3F */
@@ -156,7 +159,7 @@
 	Group | Group1_80, Group | Group1_81,
 	Group | Group1_82, Group | Group1_83,
 	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
-	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
+	ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
 	/* 0x88 - 0x8F */
 	ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov,
 	ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
@@ -210,7 +213,7 @@
 	SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps,
 	/* 0xF0 - 0xF7 */
 	0, 0, 0, 0,
-	ImplicitOps, ImplicitOps, Group | Group3_Byte, Group | Group3,
+	ImplicitOps | Priv, ImplicitOps, Group | Group3_Byte, Group | Group3,
 	/* 0xF8 - 0xFF */
 	ImplicitOps, 0, ImplicitOps, ImplicitOps,
 	ImplicitOps, ImplicitOps, Group | Group4, Group | Group5,
@@ -218,16 +221,20 @@
 
 static u32 twobyte_table[256] = {
 	/* 0x00 - 0x0F */
-	0, Group | GroupDual | Group7, 0, 0, 0, ImplicitOps, ImplicitOps, 0,
-	ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
+	0, Group | GroupDual | Group7, 0, 0,
+	0, ImplicitOps, ImplicitOps | Priv, 0,
+	ImplicitOps | Priv, ImplicitOps | Priv, 0, 0,
+	0, ImplicitOps | ModRM, 0, 0,
 	/* 0x10 - 0x1F */
 	0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0,
 	/* 0x20 - 0x2F */
-	ModRM | ImplicitOps, ModRM, ModRM | ImplicitOps, ModRM, 0, 0, 0, 0,
+	ModRM | ImplicitOps | Priv, ModRM | Priv,
+	ModRM | ImplicitOps | Priv, ModRM | Priv,
+	0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0x30 - 0x3F */
-	ImplicitOps, 0, ImplicitOps, 0,
-	ImplicitOps, ImplicitOps, 0, 0,
+	ImplicitOps | Priv, 0, ImplicitOps | Priv, 0,
+	ImplicitOps, ImplicitOps | Priv, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0x40 - 0x47 */
 	DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
@@ -257,21 +264,23 @@
 	DstMem | SrcReg | Src2CL | ModRM, 0, 0,
 	/* 0xA8 - 0xAF */
 	ImplicitOps | Stack, ImplicitOps | Stack,
-	0, DstMem | SrcReg | ModRM | BitOp,
+	0, DstMem | SrcReg | ModRM | BitOp | Lock,
 	DstMem | SrcReg | Src2ImmByte | ModRM,
 	DstMem | SrcReg | Src2CL | ModRM,
 	ModRM, 0,
 	/* 0xB0 - 0xB7 */
-	ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0,
-	    DstMem | SrcReg | ModRM | BitOp,
+	ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,
+	0, DstMem | SrcReg | ModRM | BitOp | Lock,
 	0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
 	    DstReg | SrcMem16 | ModRM | Mov,
 	/* 0xB8 - 0xBF */
-	0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM | BitOp,
+	0, 0,
+	Group | Group8, DstMem | SrcReg | ModRM | BitOp | Lock,
 	0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
 	    DstReg | SrcMem16 | ModRM | Mov,
 	/* 0xC0 - 0xCF */
-	0, 0, 0, DstMem | SrcReg | ModRM | Mov, 0, 0, 0, ImplicitOps | ModRM,
+	0, 0, 0, DstMem | SrcReg | ModRM | Mov,
+	0, 0, 0, Group | GroupDual | Group9,
 	0, 0, 0, 0, 0, 0, 0, 0,
 	/* 0xD0 - 0xDF */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -283,25 +292,41 @@
 
 static u32 group_table[] = {
 	[Group1_80*8] =
-	ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
-	ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
-	ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
-	ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
+	ByteOp | DstMem | SrcImm | ModRM | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | Lock,
+	ByteOp | DstMem | SrcImm | ModRM,
 	[Group1_81*8] =
-	DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
-	DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
-	DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
-	DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM,
+	DstMem | SrcImm | ModRM | Lock,
+	DstMem | SrcImm | ModRM | Lock,
+	DstMem | SrcImm | ModRM | Lock,
+	DstMem | SrcImm | ModRM | Lock,
+	DstMem | SrcImm | ModRM | Lock,
+	DstMem | SrcImm | ModRM | Lock,
+	DstMem | SrcImm | ModRM | Lock,
+	DstMem | SrcImm | ModRM,
 	[Group1_82*8] =
-	ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
-	ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
-	ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
-	ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
+	ByteOp | DstMem | SrcImm | ModRM | No64 | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | No64 | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | No64 | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | No64 | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | No64 | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | No64 | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | No64 | Lock,
+	ByteOp | DstMem | SrcImm | ModRM | No64,
 	[Group1_83*8] =
-	DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
-	DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
-	DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
-	DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM,
+	DstMem | SrcImmByte | ModRM | Lock,
+	DstMem | SrcImmByte | ModRM | Lock,
+	DstMem | SrcImmByte | ModRM | Lock,
+	DstMem | SrcImmByte | ModRM | Lock,
+	DstMem | SrcImmByte | ModRM | Lock,
+	DstMem | SrcImmByte | ModRM | Lock,
+	DstMem | SrcImmByte | ModRM | Lock,
+	DstMem | SrcImmByte | ModRM,
 	[Group1A*8] =
 	DstMem | SrcNone | ModRM | Mov | Stack, 0, 0, 0, 0, 0, 0, 0,
 	[Group3_Byte*8] =
@@ -320,24 +345,39 @@
 	SrcMem | ModRM | Stack, 0,
 	SrcMem | ModRM | Stack, 0, SrcMem | ModRM | Stack, 0,
 	[Group7*8] =
-	0, 0, ModRM | SrcMem, ModRM | SrcMem,
+	0, 0, ModRM | SrcMem | Priv, ModRM | SrcMem | Priv,
 	SrcNone | ModRM | DstMem | Mov, 0,
-	SrcMem16 | ModRM | Mov, SrcMem | ModRM | ByteOp,
+	SrcMem16 | ModRM | Mov | Priv, SrcMem | ModRM | ByteOp | Priv,
+	[Group8*8] =
+	0, 0, 0, 0,
+	DstMem | SrcImmByte | ModRM, DstMem | SrcImmByte | ModRM | Lock,
+	DstMem | SrcImmByte | ModRM | Lock, DstMem | SrcImmByte | ModRM | Lock,
+	[Group9*8] =
+	0, ImplicitOps | ModRM | Lock, 0, 0, 0, 0, 0, 0,
 };
 
 static u32 group2_table[] = {
 	[Group7*8] =
-	SrcNone | ModRM, 0, 0, SrcNone | ModRM,
+	SrcNone | ModRM | Priv, 0, 0, SrcNone | ModRM,
 	SrcNone | ModRM | DstMem | Mov, 0,
 	SrcMem16 | ModRM | Mov, 0,
+	[Group9*8] =
+	0, 0, 0, 0, 0, 0, 0, 0,
 };
 
 /* EFLAGS bit definitions. */
+#define EFLG_ID (1<<21)
+#define EFLG_VIP (1<<20)
+#define EFLG_VIF (1<<19)
+#define EFLG_AC (1<<18)
 #define EFLG_VM (1<<17)
 #define EFLG_RF (1<<16)
+#define EFLG_IOPL (3<<12)
+#define EFLG_NT (1<<14)
 #define EFLG_OF (1<<11)
 #define EFLG_DF (1<<10)
 #define EFLG_IF (1<<9)
+#define EFLG_TF (1<<8)
 #define EFLG_SF (1<<7)
 #define EFLG_ZF (1<<6)
 #define EFLG_AF (1<<4)
@@ -606,7 +646,7 @@
 
 	if (linear < fc->start || linear >= fc->end) {
 		size = min(15UL, PAGE_SIZE - offset_in_page(linear));
-		rc = ops->read_std(linear, fc->data, size, ctxt->vcpu);
+		rc = ops->fetch(linear, fc->data, size, ctxt->vcpu, NULL);
 		if (rc)
 			return rc;
 		fc->start = linear;
@@ -661,11 +701,11 @@
 		op_bytes = 3;
 	*address = 0;
 	rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2,
-			   ctxt->vcpu);
+			   ctxt->vcpu, NULL);
 	if (rc)
 		return rc;
 	rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes,
-			   ctxt->vcpu);
+			   ctxt->vcpu, NULL);
 	return rc;
 }
 
@@ -889,6 +929,7 @@
 
 	switch (mode) {
 	case X86EMUL_MODE_REAL:
+	case X86EMUL_MODE_VM86:
 	case X86EMUL_MODE_PROT16:
 		def_op_bytes = def_ad_bytes = 2;
 		break;
@@ -975,7 +1016,7 @@
 	}
 
 	if (mode == X86EMUL_MODE_PROT64 && (c->d & No64)) {
-		kvm_report_emulation_failure(ctxt->vcpu, "invalid x86/64 instruction");;
+		kvm_report_emulation_failure(ctxt->vcpu, "invalid x86/64 instruction");
 		return -1;
 	}
 
@@ -1196,13 +1237,56 @@
 	rc = ops->read_emulated(register_address(c, ss_base(ctxt),
 						 c->regs[VCPU_REGS_RSP]),
 				dest, len, ctxt->vcpu);
-	if (rc != 0)
+	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
 	register_address_increment(c, &c->regs[VCPU_REGS_RSP], len);
 	return rc;
 }
 
+static int emulate_popf(struct x86_emulate_ctxt *ctxt,
+		       struct x86_emulate_ops *ops,
+		       void *dest, int len)
+{
+	int rc;
+	unsigned long val, change_mask;
+	int iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
+	int cpl = kvm_x86_ops->get_cpl(ctxt->vcpu);
+
+	rc = emulate_pop(ctxt, ops, &val, len);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	change_mask = EFLG_CF | EFLG_PF | EFLG_AF | EFLG_ZF | EFLG_SF | EFLG_OF
+		| EFLG_TF | EFLG_DF | EFLG_NT | EFLG_RF | EFLG_AC | EFLG_ID;
+
+	switch(ctxt->mode) {
+	case X86EMUL_MODE_PROT64:
+	case X86EMUL_MODE_PROT32:
+	case X86EMUL_MODE_PROT16:
+		if (cpl == 0)
+			change_mask |= EFLG_IOPL;
+		if (cpl <= iopl)
+			change_mask |= EFLG_IF;
+		break;
+	case X86EMUL_MODE_VM86:
+		if (iopl < 3) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			return X86EMUL_PROPAGATE_FAULT;
+		}
+		change_mask |= EFLG_IF;
+		break;
+	default: /* real mode */
+		change_mask |= (EFLG_IOPL | EFLG_IF);
+		break;
+	}
+
+	*(unsigned long *)dest =
+		(ctxt->eflags & ~change_mask) | (val & change_mask);
+
+	return rc;
+}
+
 static void emulate_push_sreg(struct x86_emulate_ctxt *ctxt, int seg)
 {
 	struct decode_cache *c = &ctxt->decode;
@@ -1225,7 +1309,7 @@
 	if (rc != 0)
 		return rc;
 
-	rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)selector, 1, seg);
+	rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)selector, seg);
 	return rc;
 }
 
@@ -1370,7 +1454,7 @@
 	int rc;
 
 	rc = ops->read_emulated(memop, &old, 8, ctxt->vcpu);
-	if (rc != 0)
+	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
 	if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) ||
@@ -1385,7 +1469,7 @@
 		       (u32) c->regs[VCPU_REGS_RBX];
 
 		rc = ops->cmpxchg_emulated(memop, &old, &new, 8, ctxt->vcpu);
-		if (rc != 0)
+		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		ctxt->eflags |= EFLG_ZF;
 	}
@@ -1407,7 +1491,7 @@
 	rc = emulate_pop(ctxt, ops, &cs, c->op_bytes);
 	if (rc)
 		return rc;
-	rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, 1, VCPU_SREG_CS);
+	rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, VCPU_SREG_CS);
 	return rc;
 }
 
@@ -1451,7 +1535,7 @@
 					&c->dst.val,
 					c->dst.bytes,
 					ctxt->vcpu);
-		if (rc != 0)
+		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		break;
 	case OP_NONE:
@@ -1514,9 +1598,8 @@
 	u64 msr_data;
 
 	/* syscall is not available in real mode */
-	if (c->lock_prefix || ctxt->mode == X86EMUL_MODE_REAL
-		|| !(ctxt->vcpu->arch.cr0 & X86_CR0_PE))
-		return -1;
+	if (ctxt->mode == X86EMUL_MODE_REAL || ctxt->mode == X86EMUL_MODE_VM86)
+		return X86EMUL_UNHANDLEABLE;
 
 	setup_syscalls_segments(ctxt, &cs, &ss);
 
@@ -1553,7 +1636,7 @@
 		ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
 	}
 
-	return 0;
+	return X86EMUL_CONTINUE;
 }
 
 static int
@@ -1563,22 +1646,17 @@
 	struct kvm_segment cs, ss;
 	u64 msr_data;
 
-	/* inject #UD if LOCK prefix is used */
-	if (c->lock_prefix)
-		return -1;
-
-	/* inject #GP if in real mode or paging is disabled */
-	if (ctxt->mode == X86EMUL_MODE_REAL ||
-		!(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) {
+	/* inject #GP if in real mode */
+	if (ctxt->mode == X86EMUL_MODE_REAL) {
 		kvm_inject_gp(ctxt->vcpu, 0);
-		return -1;
+		return X86EMUL_UNHANDLEABLE;
 	}
 
 	/* XXX sysenter/sysexit have not been tested in 64bit mode.
 	* Therefore, we inject an #UD.
 	*/
 	if (ctxt->mode == X86EMUL_MODE_PROT64)
-		return -1;
+		return X86EMUL_UNHANDLEABLE;
 
 	setup_syscalls_segments(ctxt, &cs, &ss);
 
@@ -1587,13 +1665,13 @@
 	case X86EMUL_MODE_PROT32:
 		if ((msr_data & 0xfffc) == 0x0) {
 			kvm_inject_gp(ctxt->vcpu, 0);
-			return -1;
+			return X86EMUL_PROPAGATE_FAULT;
 		}
 		break;
 	case X86EMUL_MODE_PROT64:
 		if (msr_data == 0x0) {
 			kvm_inject_gp(ctxt->vcpu, 0);
-			return -1;
+			return X86EMUL_PROPAGATE_FAULT;
 		}
 		break;
 	}
@@ -1618,7 +1696,7 @@
 	kvm_x86_ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_ESP, &msr_data);
 	c->regs[VCPU_REGS_RSP] = msr_data;
 
-	return 0;
+	return X86EMUL_CONTINUE;
 }
 
 static int
@@ -1629,21 +1707,11 @@
 	u64 msr_data;
 	int usermode;
 
-	/* inject #UD if LOCK prefix is used */
-	if (c->lock_prefix)
-		return -1;
-
-	/* inject #GP if in real mode or paging is disabled */
-	if (ctxt->mode == X86EMUL_MODE_REAL
-		|| !(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) {
+	/* inject #GP if in real mode or Virtual 8086 mode */
+	if (ctxt->mode == X86EMUL_MODE_REAL ||
+	    ctxt->mode == X86EMUL_MODE_VM86) {
 		kvm_inject_gp(ctxt->vcpu, 0);
-		return -1;
-	}
-
-	/* sysexit must be called from CPL 0 */
-	if (kvm_x86_ops->get_cpl(ctxt->vcpu) != 0) {
-		kvm_inject_gp(ctxt->vcpu, 0);
-		return -1;
+		return X86EMUL_UNHANDLEABLE;
 	}
 
 	setup_syscalls_segments(ctxt, &cs, &ss);
@@ -1661,7 +1729,7 @@
 		cs.selector = (u16)(msr_data + 16);
 		if ((msr_data & 0xfffc) == 0x0) {
 			kvm_inject_gp(ctxt->vcpu, 0);
-			return -1;
+			return X86EMUL_PROPAGATE_FAULT;
 		}
 		ss.selector = (u16)(msr_data + 24);
 		break;
@@ -1669,7 +1737,7 @@
 		cs.selector = (u16)(msr_data + 32);
 		if (msr_data == 0x0) {
 			kvm_inject_gp(ctxt->vcpu, 0);
-			return -1;
+			return X86EMUL_PROPAGATE_FAULT;
 		}
 		ss.selector = cs.selector + 8;
 		cs.db = 0;
@@ -1685,7 +1753,58 @@
 	c->eip = ctxt->vcpu->arch.regs[VCPU_REGS_RDX];
 	c->regs[VCPU_REGS_RSP] = ctxt->vcpu->arch.regs[VCPU_REGS_RCX];
 
-	return 0;
+	return X86EMUL_CONTINUE;
+}
+
+static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt)
+{
+	int iopl;
+	if (ctxt->mode == X86EMUL_MODE_REAL)
+		return false;
+	if (ctxt->mode == X86EMUL_MODE_VM86)
+		return true;
+	iopl = (ctxt->eflags & X86_EFLAGS_IOPL) >> IOPL_SHIFT;
+	return kvm_x86_ops->get_cpl(ctxt->vcpu) > iopl;
+}
+
+static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
+					    struct x86_emulate_ops *ops,
+					    u16 port, u16 len)
+{
+	struct kvm_segment tr_seg;
+	int r;
+	u16 io_bitmap_ptr;
+	u8 perm, bit_idx = port & 0x7;
+	unsigned mask = (1 << len) - 1;
+
+	kvm_get_segment(ctxt->vcpu, &tr_seg, VCPU_SREG_TR);
+	if (tr_seg.unusable)
+		return false;
+	if (tr_seg.limit < 103)
+		return false;
+	r = ops->read_std(tr_seg.base + 102, &io_bitmap_ptr, 2, ctxt->vcpu,
+			  NULL);
+	if (r != X86EMUL_CONTINUE)
+		return false;
+	if (io_bitmap_ptr + port/8 > tr_seg.limit)
+		return false;
+	r = ops->read_std(tr_seg.base + io_bitmap_ptr + port/8, &perm, 1,
+			  ctxt->vcpu, NULL);
+	if (r != X86EMUL_CONTINUE)
+		return false;
+	if ((perm >> bit_idx) & mask)
+		return false;
+	return true;
+}
+
+static bool emulator_io_permited(struct x86_emulate_ctxt *ctxt,
+				 struct x86_emulate_ops *ops,
+				 u16 port, u16 len)
+{
+	if (emulator_bad_iopl(ctxt))
+		if (!emulator_io_port_access_allowed(ctxt, ops, port, len))
+			return false;
+	return true;
 }
 
 int
@@ -1709,6 +1828,18 @@
 	memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
 	saved_eip = c->eip;
 
+	/* LOCK prefix is allowed only with some instructions */
+	if (c->lock_prefix && !(c->d & Lock)) {
+		kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+		goto done;
+	}
+
+	/* Privileged instruction can be executed only in CPL=0 */
+	if ((c->d & Priv) && kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+		kvm_inject_gp(ctxt->vcpu, 0);
+		goto done;
+	}
+
 	if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs))
 		memop = c->modrm_ea;
 
@@ -1749,7 +1880,7 @@
 					&c->src.val,
 					c->src.bytes,
 					ctxt->vcpu);
-		if (rc != 0)
+		if (rc != X86EMUL_CONTINUE)
 			goto done;
 		c->src.orig_val = c->src.val;
 	}
@@ -1768,12 +1899,15 @@
 			c->dst.ptr = (void *)c->dst.ptr +
 						   (c->src.val & mask) / 8;
 		}
-		if (!(c->d & Mov) &&
-				   /* optimisation - avoid slow emulated read */
-		    ((rc = ops->read_emulated((unsigned long)c->dst.ptr,
-					   &c->dst.val,
-					  c->dst.bytes, ctxt->vcpu)) != 0))
-			goto done;
+		if (!(c->d & Mov)) {
+			/* optimisation - avoid slow emulated read */
+			rc = ops->read_emulated((unsigned long)c->dst.ptr,
+						&c->dst.val,
+						c->dst.bytes,
+						ctxt->vcpu);
+			if (rc != X86EMUL_CONTINUE)
+				goto done;
+		}
 	}
 	c->dst.orig_val = c->dst.val;
 
@@ -1876,7 +2010,12 @@
 		break;
 	case 0x6c:		/* insb */
 	case 0x6d:		/* insw/insd */
-		 if (kvm_emulate_pio_string(ctxt->vcpu,
+		if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX],
+					  (c->d & ByteOp) ? 1 : c->op_bytes)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+		if (kvm_emulate_pio_string(ctxt->vcpu,
 				1,
 				(c->d & ByteOp) ? 1 : c->op_bytes,
 				c->rep_prefix ?
@@ -1892,6 +2031,11 @@
 		return 0;
 	case 0x6e:		/* outsb */
 	case 0x6f:		/* outsw/outsd */
+		if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX],
+					  (c->d & ByteOp) ? 1 : c->op_bytes)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
 		if (kvm_emulate_pio_string(ctxt->vcpu,
 				0,
 				(c->d & ByteOp) ? 1 : c->op_bytes,
@@ -1978,25 +2122,19 @@
 		break;
 	case 0x8e: { /* mov seg, r/m16 */
 		uint16_t sel;
-		int type_bits;
-		int err;
 
 		sel = c->src.val;
+
+		if (c->modrm_reg == VCPU_SREG_CS ||
+		    c->modrm_reg > VCPU_SREG_GS) {
+			kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			goto done;
+		}
+
 		if (c->modrm_reg == VCPU_SREG_SS)
 			toggle_interruptibility(ctxt, X86_SHADOW_INT_MOV_SS);
 
-		if (c->modrm_reg <= 5) {
-			type_bits = (c->modrm_reg == 1) ? 9 : 1;
-			err = kvm_load_segment_descriptor(ctxt->vcpu, sel,
-							  type_bits, c->modrm_reg);
-		} else {
-			printk(KERN_INFO "Invalid segreg in modrm byte 0x%02x\n",
-					c->modrm);
-			goto cannot_emulate;
-		}
-
-		if (err < 0)
-			goto cannot_emulate;
+		rc = kvm_load_segment_descriptor(ctxt->vcpu, sel, c->modrm_reg);
 
 		c->dst.type = OP_NONE;  /* Disable writeback. */
 		break;
@@ -2025,7 +2163,10 @@
 		c->dst.type = OP_REG;
 		c->dst.ptr = (unsigned long *) &ctxt->eflags;
 		c->dst.bytes = c->op_bytes;
-		goto pop_instruction;
+		rc = emulate_popf(ctxt, ops, &c->dst.val, c->op_bytes);
+		if (rc != X86EMUL_CONTINUE)
+			goto done;
+		break;
 	case 0xa0 ... 0xa1:	/* mov */
 		c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
 		c->dst.val = c->src.val;
@@ -2039,11 +2180,12 @@
 		c->dst.ptr = (unsigned long *)register_address(c,
 						   es_base(ctxt),
 						   c->regs[VCPU_REGS_RDI]);
-		if ((rc = ops->read_emulated(register_address(c,
-					   seg_override_base(ctxt, c),
-					c->regs[VCPU_REGS_RSI]),
+		rc = ops->read_emulated(register_address(c,
+						seg_override_base(ctxt, c),
+						c->regs[VCPU_REGS_RSI]),
 					&c->dst.val,
-					c->dst.bytes, ctxt->vcpu)) != 0)
+					c->dst.bytes, ctxt->vcpu);
+		if (rc != X86EMUL_CONTINUE)
 			goto done;
 		register_address_increment(c, &c->regs[VCPU_REGS_RSI],
 				       (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
@@ -2058,10 +2200,11 @@
 		c->src.ptr = (unsigned long *)register_address(c,
 				       seg_override_base(ctxt, c),
 						   c->regs[VCPU_REGS_RSI]);
-		if ((rc = ops->read_emulated((unsigned long)c->src.ptr,
-						&c->src.val,
-						c->src.bytes,
-						ctxt->vcpu)) != 0)
+		rc = ops->read_emulated((unsigned long)c->src.ptr,
+					&c->src.val,
+					c->src.bytes,
+					ctxt->vcpu);
+		if (rc != X86EMUL_CONTINUE)
 			goto done;
 
 		c->dst.type = OP_NONE; /* Disable writeback. */
@@ -2069,10 +2212,11 @@
 		c->dst.ptr = (unsigned long *)register_address(c,
 						   es_base(ctxt),
 						   c->regs[VCPU_REGS_RDI]);
-		if ((rc = ops->read_emulated((unsigned long)c->dst.ptr,
-						&c->dst.val,
-						c->dst.bytes,
-						ctxt->vcpu)) != 0)
+		rc = ops->read_emulated((unsigned long)c->dst.ptr,
+					&c->dst.val,
+					c->dst.bytes,
+					ctxt->vcpu);
+		if (rc != X86EMUL_CONTINUE)
 			goto done;
 
 		DPRINTF("cmps: mem1=0x%p mem2=0x%p\n", c->src.ptr, c->dst.ptr);
@@ -2102,12 +2246,13 @@
 		c->dst.type = OP_REG;
 		c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
 		c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
-		if ((rc = ops->read_emulated(register_address(c,
-						 seg_override_base(ctxt, c),
-						 c->regs[VCPU_REGS_RSI]),
-						 &c->dst.val,
-						 c->dst.bytes,
-						 ctxt->vcpu)) != 0)
+		rc = ops->read_emulated(register_address(c,
+						seg_override_base(ctxt, c),
+						c->regs[VCPU_REGS_RSI]),
+					&c->dst.val,
+					c->dst.bytes,
+					ctxt->vcpu);
+		if (rc != X86EMUL_CONTINUE)
 			goto done;
 		register_address_increment(c, &c->regs[VCPU_REGS_RSI],
 				       (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
@@ -2163,11 +2308,9 @@
 	case 0xe9: /* jmp rel */
 		goto jmp;
 	case 0xea: /* jmp far */
-		if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val, 9,
-					VCPU_SREG_CS) < 0) {
-			DPRINTF("jmp far: Failed to load CS descriptor\n");
-			goto cannot_emulate;
-		}
+		if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val,
+						VCPU_SREG_CS))
+			goto done;
 
 		c->eip = c->src.val;
 		break;
@@ -2185,7 +2328,13 @@
 	case 0xef: /* out (e/r)ax,dx */
 		port = c->regs[VCPU_REGS_RDX];
 		io_dir_in = 0;
-	do_io:	if (kvm_emulate_pio(ctxt->vcpu, io_dir_in,
+	do_io:
+		if (!emulator_io_permited(ctxt, ops, port,
+					  (c->d & ByteOp) ? 1 : c->op_bytes)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+		if (kvm_emulate_pio(ctxt->vcpu, io_dir_in,
 				   (c->d & ByteOp) ? 1 : c->op_bytes,
 				   port) != 0) {
 			c->eip = saved_eip;
@@ -2210,13 +2359,21 @@
 		c->dst.type = OP_NONE;	/* Disable writeback. */
 		break;
 	case 0xfa: /* cli */
-		ctxt->eflags &= ~X86_EFLAGS_IF;
-		c->dst.type = OP_NONE;	/* Disable writeback. */
+		if (emulator_bad_iopl(ctxt))
+			kvm_inject_gp(ctxt->vcpu, 0);
+		else {
+			ctxt->eflags &= ~X86_EFLAGS_IF;
+			c->dst.type = OP_NONE;	/* Disable writeback. */
+		}
 		break;
 	case 0xfb: /* sti */
-		toggle_interruptibility(ctxt, X86_SHADOW_INT_STI);
-		ctxt->eflags |= X86_EFLAGS_IF;
-		c->dst.type = OP_NONE;	/* Disable writeback. */
+		if (emulator_bad_iopl(ctxt))
+			kvm_inject_gp(ctxt->vcpu, 0);
+		else {
+			toggle_interruptibility(ctxt, X86_SHADOW_INT_STI);
+			ctxt->eflags |= X86_EFLAGS_IF;
+			c->dst.type = OP_NONE;	/* Disable writeback. */
+		}
 		break;
 	case 0xfc: /* cld */
 		ctxt->eflags &= ~EFLG_DF;
@@ -2319,8 +2476,9 @@
 		}
 		break;
 	case 0x05: 		/* syscall */
-		if (emulate_syscall(ctxt) == -1)
-			goto cannot_emulate;
+		rc = emulate_syscall(ctxt);
+		if (rc != X86EMUL_CONTINUE)
+			goto done;
 		else
 			goto writeback;
 		break;
@@ -2391,14 +2549,16 @@
 		c->dst.type = OP_NONE;
 		break;
 	case 0x34:		/* sysenter */
-		if (emulate_sysenter(ctxt) == -1)
-			goto cannot_emulate;
+		rc = emulate_sysenter(ctxt);
+		if (rc != X86EMUL_CONTINUE)
+			goto done;
 		else
 			goto writeback;
 		break;
 	case 0x35:		/* sysexit */
-		if (emulate_sysexit(ctxt) == -1)
-			goto cannot_emulate;
+		rc = emulate_sysexit(ctxt);
+		if (rc != X86EMUL_CONTINUE)
+			goto done;
 		else
 			goto writeback;
 		break;
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 15578f1..294698b 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -242,11 +242,11 @@
 {
 	struct kvm_kpit_state *ps = container_of(kian, struct kvm_kpit_state,
 						 irq_ack_notifier);
-	spin_lock(&ps->inject_lock);
+	raw_spin_lock(&ps->inject_lock);
 	if (atomic_dec_return(&ps->pit_timer.pending) < 0)
 		atomic_inc(&ps->pit_timer.pending);
 	ps->irq_ack = 1;
-	spin_unlock(&ps->inject_lock);
+	raw_spin_unlock(&ps->inject_lock);
 }
 
 void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
@@ -605,7 +605,7 @@
 	.write    = speaker_ioport_write,
 };
 
-/* Caller must have writers lock on slots_lock */
+/* Caller must hold slots_lock */
 struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
 {
 	struct kvm_pit *pit;
@@ -624,7 +624,7 @@
 
 	mutex_init(&pit->pit_state.lock);
 	mutex_lock(&pit->pit_state.lock);
-	spin_lock_init(&pit->pit_state.inject_lock);
+	raw_spin_lock_init(&pit->pit_state.inject_lock);
 
 	kvm->arch.vpit = pit;
 	pit->kvm = kvm;
@@ -645,13 +645,13 @@
 	kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
 
 	kvm_iodevice_init(&pit->dev, &pit_dev_ops);
-	ret = __kvm_io_bus_register_dev(&kvm->pio_bus, &pit->dev);
+	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &pit->dev);
 	if (ret < 0)
 		goto fail;
 
 	if (flags & KVM_PIT_SPEAKER_DUMMY) {
 		kvm_iodevice_init(&pit->speaker_dev, &speaker_dev_ops);
-		ret = __kvm_io_bus_register_dev(&kvm->pio_bus,
+		ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS,
 						&pit->speaker_dev);
 		if (ret < 0)
 			goto fail_unregister;
@@ -660,11 +660,12 @@
 	return pit;
 
 fail_unregister:
-	__kvm_io_bus_unregister_dev(&kvm->pio_bus, &pit->dev);
+	kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->dev);
 
 fail:
-	if (pit->irq_source_id >= 0)
-		kvm_free_irq_source_id(kvm, pit->irq_source_id);
+	kvm_unregister_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
+	kvm_unregister_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier);
+	kvm_free_irq_source_id(kvm, pit->irq_source_id);
 
 	kfree(pit);
 	return NULL;
@@ -723,12 +724,12 @@
 		/* Try to inject pending interrupts when
 		 * last one has been acked.
 		 */
-		spin_lock(&ps->inject_lock);
+		raw_spin_lock(&ps->inject_lock);
 		if (atomic_read(&ps->pit_timer.pending) && ps->irq_ack) {
 			ps->irq_ack = 0;
 			inject = 1;
 		}
-		spin_unlock(&ps->inject_lock);
+		raw_spin_unlock(&ps->inject_lock);
 		if (inject)
 			__inject_pit_timer_intr(kvm);
 	}
diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h
index d4c1c7f..900d6b0 100644
--- a/arch/x86/kvm/i8254.h
+++ b/arch/x86/kvm/i8254.h
@@ -27,7 +27,7 @@
 	u32    speaker_data_on;
 	struct mutex lock;
 	struct kvm_pit *pit;
-	spinlock_t inject_lock;
+	raw_spinlock_t inject_lock;
 	unsigned long irq_ack;
 	struct kvm_irq_ack_notifier irq_ack_notifier;
 };
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index d057c0c..07771da 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -44,18 +44,19 @@
 	 * Other interrupt may be delivered to PIC while lock is dropped but
 	 * it should be safe since PIC state is already updated at this stage.
 	 */
-	spin_unlock(&s->pics_state->lock);
+	raw_spin_unlock(&s->pics_state->lock);
 	kvm_notify_acked_irq(s->pics_state->kvm, SELECT_PIC(irq), irq);
-	spin_lock(&s->pics_state->lock);
+	raw_spin_lock(&s->pics_state->lock);
 }
 
 void kvm_pic_clear_isr_ack(struct kvm *kvm)
 {
 	struct kvm_pic *s = pic_irqchip(kvm);
-	spin_lock(&s->lock);
+
+	raw_spin_lock(&s->lock);
 	s->pics[0].isr_ack = 0xff;
 	s->pics[1].isr_ack = 0xff;
-	spin_unlock(&s->lock);
+	raw_spin_unlock(&s->lock);
 }
 
 /*
@@ -156,9 +157,9 @@
 
 void kvm_pic_update_irq(struct kvm_pic *s)
 {
-	spin_lock(&s->lock);
+	raw_spin_lock(&s->lock);
 	pic_update_irq(s);
-	spin_unlock(&s->lock);
+	raw_spin_unlock(&s->lock);
 }
 
 int kvm_pic_set_irq(void *opaque, int irq, int level)
@@ -166,14 +167,14 @@
 	struct kvm_pic *s = opaque;
 	int ret = -1;
 
-	spin_lock(&s->lock);
+	raw_spin_lock(&s->lock);
 	if (irq >= 0 && irq < PIC_NUM_PINS) {
 		ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
 		pic_update_irq(s);
 		trace_kvm_pic_set_irq(irq >> 3, irq & 7, s->pics[irq >> 3].elcr,
 				      s->pics[irq >> 3].imr, ret == 0);
 	}
-	spin_unlock(&s->lock);
+	raw_spin_unlock(&s->lock);
 
 	return ret;
 }
@@ -203,7 +204,7 @@
 	int irq, irq2, intno;
 	struct kvm_pic *s = pic_irqchip(kvm);
 
-	spin_lock(&s->lock);
+	raw_spin_lock(&s->lock);
 	irq = pic_get_irq(&s->pics[0]);
 	if (irq >= 0) {
 		pic_intack(&s->pics[0], irq);
@@ -228,7 +229,7 @@
 		intno = s->pics[0].irq_base + irq;
 	}
 	pic_update_irq(s);
-	spin_unlock(&s->lock);
+	raw_spin_unlock(&s->lock);
 
 	return intno;
 }
@@ -442,7 +443,7 @@
 			printk(KERN_ERR "PIC: non byte write\n");
 		return 0;
 	}
-	spin_lock(&s->lock);
+	raw_spin_lock(&s->lock);
 	switch (addr) {
 	case 0x20:
 	case 0x21:
@@ -455,7 +456,7 @@
 		elcr_ioport_write(&s->pics[addr & 1], addr, data);
 		break;
 	}
-	spin_unlock(&s->lock);
+	raw_spin_unlock(&s->lock);
 	return 0;
 }
 
@@ -472,7 +473,7 @@
 			printk(KERN_ERR "PIC: non byte read\n");
 		return 0;
 	}
-	spin_lock(&s->lock);
+	raw_spin_lock(&s->lock);
 	switch (addr) {
 	case 0x20:
 	case 0x21:
@@ -486,7 +487,7 @@
 		break;
 	}
 	*(unsigned char *)val = data;
-	spin_unlock(&s->lock);
+	raw_spin_unlock(&s->lock);
 	return 0;
 }
 
@@ -520,7 +521,7 @@
 	s = kzalloc(sizeof(struct kvm_pic), GFP_KERNEL);
 	if (!s)
 		return NULL;
-	spin_lock_init(&s->lock);
+	raw_spin_lock_init(&s->lock);
 	s->kvm = kvm;
 	s->pics[0].elcr_mask = 0xf8;
 	s->pics[1].elcr_mask = 0xde;
@@ -533,7 +534,9 @@
 	 * Initialize PIO device
 	 */
 	kvm_iodevice_init(&s->dev, &picdev_ops);
-	ret = kvm_io_bus_register_dev(kvm, &kvm->pio_bus, &s->dev);
+	mutex_lock(&kvm->slots_lock);
+	ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &s->dev);
+	mutex_unlock(&kvm->slots_lock);
 	if (ret < 0) {
 		kfree(s);
 		return NULL;
@@ -541,3 +544,14 @@
 
 	return s;
 }
+
+void kvm_destroy_pic(struct kvm *kvm)
+{
+	struct kvm_pic *vpic = kvm->arch.vpic;
+
+	if (vpic) {
+		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev);
+		kvm->arch.vpic = NULL;
+		kfree(vpic);
+	}
+}
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index be399e2..34b15915 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -62,7 +62,7 @@
 };
 
 struct kvm_pic {
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	unsigned pending_acks;
 	struct kvm *kvm;
 	struct kvm_kpic_state pics[2]; /* 0 is master pic, 1 is slave pic */
@@ -75,6 +75,7 @@
 };
 
 struct kvm_pic *kvm_create_pic(struct kvm *kvm);
+void kvm_destroy_pic(struct kvm *kvm);
 int kvm_pic_read_irq(struct kvm *kvm);
 void kvm_pic_update_irq(struct kvm_pic *s);
 void kvm_pic_clear_isr_ack(struct kvm *kvm);
diff --git a/arch/x86/kvm/kvm_cache_regs.h b/arch/x86/kvm/kvm_cache_regs.h
index 7bcc5b6..cff851c 100644
--- a/arch/x86/kvm/kvm_cache_regs.h
+++ b/arch/x86/kvm/kvm_cache_regs.h
@@ -1,6 +1,11 @@
 #ifndef ASM_KVM_CACHE_REGS_H
 #define ASM_KVM_CACHE_REGS_H
 
+#define KVM_POSSIBLE_CR0_GUEST_BITS X86_CR0_TS
+#define KVM_POSSIBLE_CR4_GUEST_BITS				  \
+	(X86_CR4_PVI | X86_CR4_DE | X86_CR4_PCE | X86_CR4_OSFXSR  \
+	 | X86_CR4_OSXMMEXCPT | X86_CR4_PGE)
+
 static inline unsigned long kvm_register_read(struct kvm_vcpu *vcpu,
 					      enum kvm_reg reg)
 {
@@ -38,4 +43,30 @@
 	return vcpu->arch.pdptrs[index];
 }
 
+static inline ulong kvm_read_cr0_bits(struct kvm_vcpu *vcpu, ulong mask)
+{
+	ulong tmask = mask & KVM_POSSIBLE_CR0_GUEST_BITS;
+	if (tmask & vcpu->arch.cr0_guest_owned_bits)
+		kvm_x86_ops->decache_cr0_guest_bits(vcpu);
+	return vcpu->arch.cr0 & mask;
+}
+
+static inline ulong kvm_read_cr0(struct kvm_vcpu *vcpu)
+{
+	return kvm_read_cr0_bits(vcpu, ~0UL);
+}
+
+static inline ulong kvm_read_cr4_bits(struct kvm_vcpu *vcpu, ulong mask)
+{
+	ulong tmask = mask & KVM_POSSIBLE_CR4_GUEST_BITS;
+	if (tmask & vcpu->arch.cr4_guest_owned_bits)
+		kvm_x86_ops->decache_cr4_guest_bits(vcpu);
+	return vcpu->arch.cr4 & mask;
+}
+
+static inline ulong kvm_read_cr4(struct kvm_vcpu *vcpu)
+{
+	return kvm_read_cr4_bits(vcpu, ~0UL);
+}
+
 #endif
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index ba8c045..4b224f9 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1246,3 +1246,34 @@
 
 	return 0;
 }
+
+int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 reg, u64 data)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (!irqchip_in_kernel(vcpu->kvm))
+		return 1;
+
+	/* if this is ICR write vector before command */
+	if (reg == APIC_ICR)
+		apic_reg_write(apic, APIC_ICR2, (u32)(data >> 32));
+	return apic_reg_write(apic, reg, (u32)data);
+}
+
+int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+	u32 low, high = 0;
+
+	if (!irqchip_in_kernel(vcpu->kvm))
+		return 1;
+
+	if (apic_reg_read(apic, reg, 4, &low))
+		return 1;
+	if (reg == APIC_ICR)
+		apic_reg_read(apic, APIC_ICR2, 4, &high);
+
+	*data = (((u64)high) << 32) | low;
+
+	return 0;
+}
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 40010b0..f5fe32c 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -48,4 +48,12 @@
 
 int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data);
 int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
+
+int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data);
+int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
+
+static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.hv_vapic & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE;
+}
 #endif
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 89a49fb..741373e 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -18,6 +18,7 @@
  */
 
 #include "mmu.h"
+#include "x86.h"
 #include "kvm_cache_regs.h"
 
 #include <linux/kvm_host.h>
@@ -29,6 +30,7 @@
 #include <linux/swap.h>
 #include <linux/hugetlb.h>
 #include <linux/compiler.h>
+#include <linux/srcu.h>
 
 #include <asm/page.h>
 #include <asm/cmpxchg.h>
@@ -136,16 +138,6 @@
 #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK \
 			| PT64_NX_MASK)
 
-#define PFERR_PRESENT_MASK (1U << 0)
-#define PFERR_WRITE_MASK (1U << 1)
-#define PFERR_USER_MASK (1U << 2)
-#define PFERR_RSVD_MASK (1U << 3)
-#define PFERR_FETCH_MASK (1U << 4)
-
-#define PT_PDPE_LEVEL 3
-#define PT_DIRECTORY_LEVEL 2
-#define PT_PAGE_TABLE_LEVEL 1
-
 #define RMAP_EXT 4
 
 #define ACC_EXEC_MASK    1
@@ -153,6 +145,9 @@
 #define ACC_USER_MASK    PT_USER_MASK
 #define ACC_ALL          (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK)
 
+#include <trace/events/kvm.h>
+
+#undef TRACE_INCLUDE_FILE
 #define CREATE_TRACE_POINTS
 #include "mmutrace.h"
 
@@ -229,7 +224,7 @@
 
 static int is_write_protection(struct kvm_vcpu *vcpu)
 {
-	return vcpu->arch.cr0 & X86_CR0_WP;
+	return kvm_read_cr0_bits(vcpu, X86_CR0_WP);
 }
 
 static int is_cpuid_PSE36(void)
@@ -239,7 +234,7 @@
 
 static int is_nx(struct kvm_vcpu *vcpu)
 {
-	return vcpu->arch.shadow_efer & EFER_NX;
+	return vcpu->arch.efer & EFER_NX;
 }
 
 static int is_shadow_present_pte(u64 pte)
@@ -253,7 +248,7 @@
 	return pte & PT_PAGE_SIZE_MASK;
 }
 
-static int is_writeble_pte(unsigned long pte)
+static int is_writable_pte(unsigned long pte)
 {
 	return pte & PT_WRITABLE_MASK;
 }
@@ -470,24 +465,10 @@
 
 static int host_mapping_level(struct kvm *kvm, gfn_t gfn)
 {
-	unsigned long page_size = PAGE_SIZE;
-	struct vm_area_struct *vma;
-	unsigned long addr;
+	unsigned long page_size;
 	int i, ret = 0;
 
-	addr = gfn_to_hva(kvm, gfn);
-	if (kvm_is_error_hva(addr))
-		return PT_PAGE_TABLE_LEVEL;
-
-	down_read(&current->mm->mmap_sem);
-	vma = find_vma(current->mm, addr);
-	if (!vma)
-		goto out;
-
-	page_size = vma_kernel_pagesize(vma);
-
-out:
-	up_read(&current->mm->mmap_sem);
+	page_size = kvm_host_page_size(kvm, gfn);
 
 	for (i = PT_PAGE_TABLE_LEVEL;
 	     i < (PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES); ++i) {
@@ -503,8 +484,7 @@
 static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
 {
 	struct kvm_memory_slot *slot;
-	int host_level;
-	int level = PT_PAGE_TABLE_LEVEL;
+	int host_level, level, max_level;
 
 	slot = gfn_to_memslot(vcpu->kvm, large_gfn);
 	if (slot && slot->dirty_bitmap)
@@ -515,7 +495,10 @@
 	if (host_level == PT_PAGE_TABLE_LEVEL)
 		return host_level;
 
-	for (level = PT_DIRECTORY_LEVEL; level <= host_level; ++level)
+	max_level = kvm_x86_ops->get_lpage_level() < host_level ?
+		kvm_x86_ops->get_lpage_level() : host_level;
+
+	for (level = PT_DIRECTORY_LEVEL; level <= max_level; ++level)
 		if (has_wrprotected_page(vcpu->kvm, large_gfn, level))
 			break;
 
@@ -633,7 +616,7 @@
 	pfn = spte_to_pfn(*spte);
 	if (*spte & shadow_accessed_mask)
 		kvm_set_pfn_accessed(pfn);
-	if (is_writeble_pte(*spte))
+	if (is_writable_pte(*spte))
 		kvm_set_pfn_dirty(pfn);
 	rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt], sp->role.level);
 	if (!*rmapp) {
@@ -662,6 +645,7 @@
 			prev_desc = desc;
 			desc = desc->more;
 		}
+		pr_err("rmap_remove: %p %llx many->many\n", spte, *spte);
 		BUG();
 	}
 }
@@ -708,7 +692,7 @@
 		BUG_ON(!spte);
 		BUG_ON(!(*spte & PT_PRESENT_MASK));
 		rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte);
-		if (is_writeble_pte(*spte)) {
+		if (is_writable_pte(*spte)) {
 			__set_spte(spte, *spte & ~PT_WRITABLE_MASK);
 			write_protected = 1;
 		}
@@ -732,7 +716,7 @@
 			BUG_ON(!(*spte & PT_PRESENT_MASK));
 			BUG_ON((*spte & (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)) != (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK));
 			pgprintk("rmap_write_protect(large): spte %p %llx %lld\n", spte, *spte, gfn);
-			if (is_writeble_pte(*spte)) {
+			if (is_writable_pte(*spte)) {
 				rmap_remove(kvm, spte);
 				--kvm->stat.lpages;
 				__set_spte(spte, shadow_trap_nonpresent_pte);
@@ -787,7 +771,7 @@
 
 			new_spte &= ~PT_WRITABLE_MASK;
 			new_spte &= ~SPTE_HOST_WRITEABLE;
-			if (is_writeble_pte(*spte))
+			if (is_writable_pte(*spte))
 				kvm_set_pfn_dirty(spte_to_pfn(*spte));
 			__set_spte(spte, new_spte);
 			spte = rmap_next(kvm, rmapp, spte);
@@ -805,35 +789,32 @@
 					 unsigned long data))
 {
 	int i, j;
+	int ret;
 	int retval = 0;
+	struct kvm_memslots *slots;
 
-	/*
-	 * If mmap_sem isn't taken, we can look the memslots with only
-	 * the mmu_lock by skipping over the slots with userspace_addr == 0.
-	 */
-	for (i = 0; i < kvm->nmemslots; i++) {
-		struct kvm_memory_slot *memslot = &kvm->memslots[i];
+	slots = rcu_dereference(kvm->memslots);
+
+	for (i = 0; i < slots->nmemslots; i++) {
+		struct kvm_memory_slot *memslot = &slots->memslots[i];
 		unsigned long start = memslot->userspace_addr;
 		unsigned long end;
 
-		/* mmu_lock protects userspace_addr */
-		if (!start)
-			continue;
-
 		end = start + (memslot->npages << PAGE_SHIFT);
 		if (hva >= start && hva < end) {
 			gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT;
 
-			retval |= handler(kvm, &memslot->rmap[gfn_offset],
-					  data);
+			ret = handler(kvm, &memslot->rmap[gfn_offset], data);
 
 			for (j = 0; j < KVM_NR_PAGE_SIZES - 1; ++j) {
 				int idx = gfn_offset;
 				idx /= KVM_PAGES_PER_HPAGE(PT_DIRECTORY_LEVEL + j);
-				retval |= handler(kvm,
+				ret |= handler(kvm,
 					&memslot->lpage_info[j][idx].rmap_pde,
 					data);
 			}
+			trace_kvm_age_page(hva, memslot, ret);
+			retval |= ret;
 		}
 	}
 
@@ -856,9 +837,15 @@
 	u64 *spte;
 	int young = 0;
 
-	/* always return old for EPT */
+	/*
+	 * Emulate the accessed bit for EPT, by checking if this page has
+	 * an EPT mapping, and clearing it if it does. On the next access,
+	 * a new EPT mapping will be established.
+	 * This has some overhead, but not as much as the cost of swapping
+	 * out actively used pages or breaking up actively used hugepages.
+	 */
 	if (!shadow_accessed_mask)
-		return 0;
+		return kvm_unmap_rmapp(kvm, rmapp, data);
 
 	spte = rmap_next(kvm, rmapp, NULL);
 	while (spte) {
@@ -1615,7 +1602,7 @@
 
 static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn)
 {
-	int slot = memslot_id(kvm, gfn_to_memslot(kvm, gfn));
+	int slot = memslot_id(kvm, gfn);
 	struct kvm_mmu_page *sp = page_header(__pa(pte));
 
 	__set_bit(slot, sp->slot_bitmap);
@@ -1639,7 +1626,7 @@
 {
 	struct page *page;
 
-	gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva);
+	gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL);
 
 	if (gpa == UNMAPPED_GVA)
 		return NULL;
@@ -1852,7 +1839,7 @@
 		 * is responsibility of mmu_get_page / kvm_sync_page.
 		 * Same reasoning can be applied to dirty page accounting.
 		 */
-		if (!can_unsync && is_writeble_pte(*sptep))
+		if (!can_unsync && is_writable_pte(*sptep))
 			goto set_pte;
 
 		if (mmu_need_write_protect(vcpu, gfn, can_unsync)) {
@@ -1860,7 +1847,7 @@
 				 __func__, gfn);
 			ret = 1;
 			pte_access &= ~ACC_WRITE_MASK;
-			if (is_writeble_pte(spte))
+			if (is_writable_pte(spte))
 				spte &= ~PT_WRITABLE_MASK;
 		}
 	}
@@ -1881,7 +1868,7 @@
 			 bool reset_host_protection)
 {
 	int was_rmapped = 0;
-	int was_writeble = is_writeble_pte(*sptep);
+	int was_writable = is_writable_pte(*sptep);
 	int rmap_count;
 
 	pgprintk("%s: spte %llx access %x write_fault %d"
@@ -1932,7 +1919,7 @@
 		if (rmap_count > RMAP_RECYCLE_THRESHOLD)
 			rmap_recycle(vcpu, sptep, gfn);
 	} else {
-		if (was_writeble)
+		if (was_writable)
 			kvm_release_pfn_dirty(pfn);
 		else
 			kvm_release_pfn_clean(pfn);
@@ -2162,8 +2149,11 @@
 	spin_unlock(&vcpu->kvm->mmu_lock);
 }
 
-static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
+static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr,
+				  u32 access, u32 *error)
 {
+	if (error)
+		*error = 0;
 	return vaddr;
 }
 
@@ -2747,7 +2737,7 @@
 	if (tdp_enabled)
 		return 0;
 
-	gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva);
+	gpa = kvm_mmu_gva_to_gpa_read(vcpu, gva, NULL);
 
 	spin_lock(&vcpu->kvm->mmu_lock);
 	r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT);
@@ -2847,16 +2837,13 @@
 	 */
 	page = alloc_page(GFP_KERNEL | __GFP_DMA32);
 	if (!page)
-		goto error_1;
+		return -ENOMEM;
+
 	vcpu->arch.mmu.pae_root = page_address(page);
 	for (i = 0; i < 4; ++i)
 		vcpu->arch.mmu.pae_root[i] = INVALID_PAGE;
 
 	return 0;
-
-error_1:
-	free_mmu_pages(vcpu);
-	return -ENOMEM;
 }
 
 int kvm_mmu_create(struct kvm_vcpu *vcpu)
@@ -2936,10 +2923,9 @@
 	spin_lock(&kvm_lock);
 
 	list_for_each_entry(kvm, &vm_list, vm_list) {
-		int npages;
+		int npages, idx;
 
-		if (!down_read_trylock(&kvm->slots_lock))
-			continue;
+		idx = srcu_read_lock(&kvm->srcu);
 		spin_lock(&kvm->mmu_lock);
 		npages = kvm->arch.n_alloc_mmu_pages -
 			 kvm->arch.n_free_mmu_pages;
@@ -2952,7 +2938,7 @@
 		nr_to_scan--;
 
 		spin_unlock(&kvm->mmu_lock);
-		up_read(&kvm->slots_lock);
+		srcu_read_unlock(&kvm->srcu, idx);
 	}
 	if (kvm_freed)
 		list_move_tail(&kvm_freed->vm_list, &vm_list);
@@ -3019,9 +3005,11 @@
 	int i;
 	unsigned int nr_mmu_pages;
 	unsigned int  nr_pages = 0;
+	struct kvm_memslots *slots;
 
-	for (i = 0; i < kvm->nmemslots; i++)
-		nr_pages += kvm->memslots[i].npages;
+	slots = rcu_dereference(kvm->memslots);
+	for (i = 0; i < slots->nmemslots; i++)
+		nr_pages += slots->memslots[i].npages;
 
 	nr_mmu_pages = nr_pages * KVM_PERMILLE_MMU_PAGES / 1000;
 	nr_mmu_pages = max(nr_mmu_pages,
@@ -3246,7 +3234,7 @@
 		if (is_shadow_present_pte(ent) && !is_last_spte(ent, level))
 			audit_mappings_page(vcpu, ent, va, level - 1);
 		else {
-			gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, va);
+			gpa_t gpa = kvm_mmu_gva_to_gpa_read(vcpu, va, NULL);
 			gfn_t gfn = gpa >> PAGE_SHIFT;
 			pfn_t pfn = gfn_to_pfn(vcpu->kvm, gfn);
 			hpa_t hpa = (hpa_t)pfn << PAGE_SHIFT;
@@ -3291,10 +3279,12 @@
 static int count_rmaps(struct kvm_vcpu *vcpu)
 {
 	int nmaps = 0;
-	int i, j, k;
+	int i, j, k, idx;
 
+	idx = srcu_read_lock(&kvm->srcu);
+	slots = rcu_dereference(kvm->memslots);
 	for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
-		struct kvm_memory_slot *m = &vcpu->kvm->memslots[i];
+		struct kvm_memory_slot *m = &slots->memslots[i];
 		struct kvm_rmap_desc *d;
 
 		for (j = 0; j < m->npages; ++j) {
@@ -3317,6 +3307,7 @@
 			}
 		}
 	}
+	srcu_read_unlock(&kvm->srcu, idx);
 	return nmaps;
 }
 
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 61a1b38..be66759 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -2,6 +2,7 @@
 #define __KVM_X86_MMU_H
 
 #include <linux/kvm_host.h>
+#include "kvm_cache_regs.h"
 
 #define PT64_PT_BITS 9
 #define PT64_ENT_PER_PAGE (1 << PT64_PT_BITS)
@@ -37,6 +38,16 @@
 #define PT32_ROOT_LEVEL 2
 #define PT32E_ROOT_LEVEL 3
 
+#define PT_PDPE_LEVEL 3
+#define PT_DIRECTORY_LEVEL 2
+#define PT_PAGE_TABLE_LEVEL 1
+
+#define PFERR_PRESENT_MASK (1U << 0)
+#define PFERR_WRITE_MASK (1U << 1)
+#define PFERR_USER_MASK (1U << 2)
+#define PFERR_RSVD_MASK (1U << 3)
+#define PFERR_FETCH_MASK (1U << 4)
+
 int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]);
 
 static inline void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
@@ -53,30 +64,6 @@
 	return kvm_mmu_load(vcpu);
 }
 
-static inline int is_long_mode(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_X86_64
-	return vcpu->arch.shadow_efer & EFER_LMA;
-#else
-	return 0;
-#endif
-}
-
-static inline int is_pae(struct kvm_vcpu *vcpu)
-{
-	return vcpu->arch.cr4 & X86_CR4_PAE;
-}
-
-static inline int is_pse(struct kvm_vcpu *vcpu)
-{
-	return vcpu->arch.cr4 & X86_CR4_PSE;
-}
-
-static inline int is_paging(struct kvm_vcpu *vcpu)
-{
-	return vcpu->arch.cr0 & X86_CR0_PG;
-}
-
 static inline int is_present_gpte(unsigned long pte)
 {
 	return pte & PT_PRESENT_MASK;
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index ede2131..81eab9a 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -162,7 +162,7 @@
 		if (rsvd_fault)
 			goto access_error;
 
-		if (write_fault && !is_writeble_pte(pte))
+		if (write_fault && !is_writable_pte(pte))
 			if (user_fault || is_write_protection(vcpu))
 				goto access_error;
 
@@ -490,18 +490,23 @@
 	spin_unlock(&vcpu->kvm->mmu_lock);
 }
 
-static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
+static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr, u32 access,
+			       u32 *error)
 {
 	struct guest_walker walker;
 	gpa_t gpa = UNMAPPED_GVA;
 	int r;
 
-	r = FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
+	r = FNAME(walk_addr)(&walker, vcpu, vaddr,
+			     !!(access & PFERR_WRITE_MASK),
+			     !!(access & PFERR_USER_MASK),
+			     !!(access & PFERR_FETCH_MASK));
 
 	if (r) {
 		gpa = gfn_to_gpa(walker.gfn);
 		gpa |= vaddr & ~PAGE_MASK;
-	}
+	} else if (error)
+		*error = walker.error_code;
 
 	return gpa;
 }
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 1d9b338..52f78dd0 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -231,7 +231,7 @@
 		efer &= ~EFER_LME;
 
 	to_svm(vcpu)->vmcb->save.efer = efer | EFER_SVME;
-	vcpu->arch.shadow_efer = efer;
+	vcpu->arch.efer = efer;
 }
 
 static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
@@ -540,6 +540,8 @@
 	struct vmcb_control_area *control = &svm->vmcb->control;
 	struct vmcb_save_area *save = &svm->vmcb->save;
 
+	svm->vcpu.fpu_active = 1;
+
 	control->intercept_cr_read = 	INTERCEPT_CR0_MASK |
 					INTERCEPT_CR3_MASK |
 					INTERCEPT_CR4_MASK;
@@ -552,13 +554,19 @@
 	control->intercept_dr_read = 	INTERCEPT_DR0_MASK |
 					INTERCEPT_DR1_MASK |
 					INTERCEPT_DR2_MASK |
-					INTERCEPT_DR3_MASK;
+					INTERCEPT_DR3_MASK |
+					INTERCEPT_DR4_MASK |
+					INTERCEPT_DR5_MASK |
+					INTERCEPT_DR6_MASK |
+					INTERCEPT_DR7_MASK;
 
 	control->intercept_dr_write = 	INTERCEPT_DR0_MASK |
 					INTERCEPT_DR1_MASK |
 					INTERCEPT_DR2_MASK |
 					INTERCEPT_DR3_MASK |
+					INTERCEPT_DR4_MASK |
 					INTERCEPT_DR5_MASK |
+					INTERCEPT_DR6_MASK |
 					INTERCEPT_DR7_MASK;
 
 	control->intercept_exceptions = (1 << PF_VECTOR) |
@@ -569,6 +577,7 @@
 	control->intercept = 	(1ULL << INTERCEPT_INTR) |
 				(1ULL << INTERCEPT_NMI) |
 				(1ULL << INTERCEPT_SMI) |
+				(1ULL << INTERCEPT_SELECTIVE_CR0) |
 				(1ULL << INTERCEPT_CPUID) |
 				(1ULL << INTERCEPT_INVD) |
 				(1ULL << INTERCEPT_HLT) |
@@ -641,10 +650,8 @@
 		control->intercept &= ~((1ULL << INTERCEPT_TASK_SWITCH) |
 					(1ULL << INTERCEPT_INVLPG));
 		control->intercept_exceptions &= ~(1 << PF_VECTOR);
-		control->intercept_cr_read &= ~(INTERCEPT_CR0_MASK|
-						INTERCEPT_CR3_MASK);
-		control->intercept_cr_write &= ~(INTERCEPT_CR0_MASK|
-						 INTERCEPT_CR3_MASK);
+		control->intercept_cr_read &= ~INTERCEPT_CR3_MASK;
+		control->intercept_cr_write &= ~INTERCEPT_CR3_MASK;
 		save->g_pat = 0x0007040600070406ULL;
 		save->cr3 = 0;
 		save->cr4 = 0;
@@ -730,7 +737,6 @@
 	init_vmcb(svm);
 
 	fx_init(&svm->vcpu);
-	svm->vcpu.fpu_active = 1;
 	svm->vcpu.arch.apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
 	if (kvm_vcpu_is_bsp(&svm->vcpu))
 		svm->vcpu.arch.apic_base |= MSR_IA32_APICBASE_BSP;
@@ -765,14 +771,16 @@
 	if (unlikely(cpu != vcpu->cpu)) {
 		u64 delta;
 
-		/*
-		 * Make sure that the guest sees a monotonically
-		 * increasing TSC.
-		 */
-		delta = vcpu->arch.host_tsc - native_read_tsc();
-		svm->vmcb->control.tsc_offset += delta;
-		if (is_nested(svm))
-			svm->nested.hsave->control.tsc_offset += delta;
+		if (check_tsc_unstable()) {
+			/*
+			 * Make sure that the guest sees a monotonically
+			 * increasing TSC.
+			 */
+			delta = vcpu->arch.host_tsc - native_read_tsc();
+			svm->vmcb->control.tsc_offset += delta;
+			if (is_nested(svm))
+				svm->nested.hsave->control.tsc_offset += delta;
+		}
 		vcpu->cpu = cpu;
 		kvm_migrate_timers(vcpu);
 		svm->asid_generation = 0;
@@ -954,42 +962,59 @@
 	svm->vmcb->save.gdtr.base = dt->base ;
 }
 
+static void svm_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
+{
+}
+
 static void svm_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
 {
 }
 
+static void update_cr0_intercept(struct vcpu_svm *svm)
+{
+	ulong gcr0 = svm->vcpu.arch.cr0;
+	u64 *hcr0 = &svm->vmcb->save.cr0;
+
+	if (!svm->vcpu.fpu_active)
+		*hcr0 |= SVM_CR0_SELECTIVE_MASK;
+	else
+		*hcr0 = (*hcr0 & ~SVM_CR0_SELECTIVE_MASK)
+			| (gcr0 & SVM_CR0_SELECTIVE_MASK);
+
+
+	if (gcr0 == *hcr0 && svm->vcpu.fpu_active) {
+		svm->vmcb->control.intercept_cr_read &= ~INTERCEPT_CR0_MASK;
+		svm->vmcb->control.intercept_cr_write &= ~INTERCEPT_CR0_MASK;
+	} else {
+		svm->vmcb->control.intercept_cr_read |= INTERCEPT_CR0_MASK;
+		svm->vmcb->control.intercept_cr_write |= INTERCEPT_CR0_MASK;
+	}
+}
+
 static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
 #ifdef CONFIG_X86_64
-	if (vcpu->arch.shadow_efer & EFER_LME) {
+	if (vcpu->arch.efer & EFER_LME) {
 		if (!is_paging(vcpu) && (cr0 & X86_CR0_PG)) {
-			vcpu->arch.shadow_efer |= EFER_LMA;
+			vcpu->arch.efer |= EFER_LMA;
 			svm->vmcb->save.efer |= EFER_LMA | EFER_LME;
 		}
 
 		if (is_paging(vcpu) && !(cr0 & X86_CR0_PG)) {
-			vcpu->arch.shadow_efer &= ~EFER_LMA;
+			vcpu->arch.efer &= ~EFER_LMA;
 			svm->vmcb->save.efer &= ~(EFER_LMA | EFER_LME);
 		}
 	}
 #endif
-	if (npt_enabled)
-		goto set;
-
-	if ((vcpu->arch.cr0 & X86_CR0_TS) && !(cr0 & X86_CR0_TS)) {
-		svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
-		vcpu->fpu_active = 1;
-	}
-
 	vcpu->arch.cr0 = cr0;
-	cr0 |= X86_CR0_PG | X86_CR0_WP;
-	if (!vcpu->fpu_active) {
-		svm->vmcb->control.intercept_exceptions |= (1 << NM_VECTOR);
+
+	if (!npt_enabled)
+		cr0 |= X86_CR0_PG | X86_CR0_WP;
+
+	if (!vcpu->fpu_active)
 		cr0 |= X86_CR0_TS;
-	}
-set:
 	/*
 	 * re-enable caching here because the QEMU bios
 	 * does not do it - this results in some delay at
@@ -997,6 +1022,7 @@
 	 */
 	cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
 	svm->vmcb->save.cr0 = cr0;
+	update_cr0_intercept(svm);
 }
 
 static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -1102,76 +1128,70 @@
 	svm->vmcb->control.asid = sd->next_asid++;
 }
 
-static unsigned long svm_get_dr(struct kvm_vcpu *vcpu, int dr)
+static int svm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *dest)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
-	unsigned long val;
 
 	switch (dr) {
 	case 0 ... 3:
-		val = vcpu->arch.db[dr];
+		*dest = vcpu->arch.db[dr];
 		break;
+	case 4:
+		if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
+			return EMULATE_FAIL; /* will re-inject UD */
+		/* fall through */
 	case 6:
 		if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
-			val = vcpu->arch.dr6;
+			*dest = vcpu->arch.dr6;
 		else
-			val = svm->vmcb->save.dr6;
+			*dest = svm->vmcb->save.dr6;
 		break;
+	case 5:
+		if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
+			return EMULATE_FAIL; /* will re-inject UD */
+		/* fall through */
 	case 7:
 		if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
-			val = vcpu->arch.dr7;
+			*dest = vcpu->arch.dr7;
 		else
-			val = svm->vmcb->save.dr7;
+			*dest = svm->vmcb->save.dr7;
 		break;
-	default:
-		val = 0;
 	}
 
-	return val;
+	return EMULATE_DONE;
 }
 
-static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value,
-		       int *exception)
+static int svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	*exception = 0;
-
 	switch (dr) {
 	case 0 ... 3:
 		vcpu->arch.db[dr] = value;
 		if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP))
 			vcpu->arch.eff_db[dr] = value;
-		return;
-	case 4 ... 5:
-		if (vcpu->arch.cr4 & X86_CR4_DE)
-			*exception = UD_VECTOR;
-		return;
+		break;
+	case 4:
+		if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
+			return EMULATE_FAIL; /* will re-inject UD */
+		/* fall through */
 	case 6:
-		if (value & 0xffffffff00000000ULL) {
-			*exception = GP_VECTOR;
-			return;
-		}
 		vcpu->arch.dr6 = (value & DR6_VOLATILE) | DR6_FIXED_1;
-		return;
+		break;
+	case 5:
+		if (kvm_read_cr4_bits(vcpu, X86_CR4_DE))
+			return EMULATE_FAIL; /* will re-inject UD */
+		/* fall through */
 	case 7:
-		if (value & 0xffffffff00000000ULL) {
-			*exception = GP_VECTOR;
-			return;
-		}
 		vcpu->arch.dr7 = (value & DR7_VOLATILE) | DR7_FIXED_1;
 		if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) {
 			svm->vmcb->save.dr7 = vcpu->arch.dr7;
 			vcpu->arch.switch_db_regs = (value & DR7_BP_EN_MASK);
 		}
-		return;
-	default:
-		/* FIXME: Possible case? */
-		printk(KERN_DEBUG "%s: unexpected dr %u\n",
-		       __func__, dr);
-		*exception = UD_VECTOR;
-		return;
+		break;
 	}
+
+	return EMULATE_DONE;
 }
 
 static int pf_interception(struct vcpu_svm *svm)
@@ -1239,13 +1259,17 @@
 	return 1;
 }
 
+static void svm_fpu_activate(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_svm *svm = to_svm(vcpu);
+	svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
+	svm->vcpu.fpu_active = 1;
+	update_cr0_intercept(svm);
+}
+
 static int nm_interception(struct vcpu_svm *svm)
 {
-	svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
-	if (!(svm->vcpu.arch.cr0 & X86_CR0_TS))
-		svm->vmcb->save.cr0 &= ~X86_CR0_TS;
-	svm->vcpu.fpu_active = 1;
-
+	svm_fpu_activate(&svm->vcpu);
 	return 1;
 }
 
@@ -1337,7 +1361,7 @@
 
 static int nested_svm_check_permissions(struct vcpu_svm *svm)
 {
-	if (!(svm->vcpu.arch.shadow_efer & EFER_SVME)
+	if (!(svm->vcpu.arch.efer & EFER_SVME)
 	    || !is_paging(&svm->vcpu)) {
 		kvm_queue_exception(&svm->vcpu, UD_VECTOR);
 		return 1;
@@ -1740,8 +1764,8 @@
 	hsave->save.ds     = vmcb->save.ds;
 	hsave->save.gdtr   = vmcb->save.gdtr;
 	hsave->save.idtr   = vmcb->save.idtr;
-	hsave->save.efer   = svm->vcpu.arch.shadow_efer;
-	hsave->save.cr0    = svm->vcpu.arch.cr0;
+	hsave->save.efer   = svm->vcpu.arch.efer;
+	hsave->save.cr0    = kvm_read_cr0(&svm->vcpu);
 	hsave->save.cr4    = svm->vcpu.arch.cr4;
 	hsave->save.rflags = vmcb->save.rflags;
 	hsave->save.rip    = svm->next_rip;
@@ -2153,9 +2177,10 @@
 	u32 ecx = svm->vcpu.arch.regs[VCPU_REGS_RCX];
 	u64 data;
 
-	if (svm_get_msr(&svm->vcpu, ecx, &data))
+	if (svm_get_msr(&svm->vcpu, ecx, &data)) {
+		trace_kvm_msr_read_ex(ecx);
 		kvm_inject_gp(&svm->vcpu, 0);
-	else {
+	} else {
 		trace_kvm_msr_read(ecx, data);
 
 		svm->vcpu.arch.regs[VCPU_REGS_RAX] = data & 0xffffffff;
@@ -2247,13 +2272,15 @@
 	u64 data = (svm->vcpu.arch.regs[VCPU_REGS_RAX] & -1u)
 		| ((u64)(svm->vcpu.arch.regs[VCPU_REGS_RDX] & -1u) << 32);
 
-	trace_kvm_msr_write(ecx, data);
 
 	svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
-	if (svm_set_msr(&svm->vcpu, ecx, data))
+	if (svm_set_msr(&svm->vcpu, ecx, data)) {
+		trace_kvm_msr_write_ex(ecx, data);
 		kvm_inject_gp(&svm->vcpu, 0);
-	else
+	} else {
+		trace_kvm_msr_write(ecx, data);
 		skip_emulated_instruction(&svm->vcpu);
+	}
 	return 1;
 }
 
@@ -2297,7 +2324,7 @@
 	[SVM_EXIT_READ_CR3]           		= emulate_on_interception,
 	[SVM_EXIT_READ_CR4]           		= emulate_on_interception,
 	[SVM_EXIT_READ_CR8]           		= emulate_on_interception,
-	/* for now: */
+	[SVM_EXIT_CR0_SEL_WRITE]		= emulate_on_interception,
 	[SVM_EXIT_WRITE_CR0]          		= emulate_on_interception,
 	[SVM_EXIT_WRITE_CR3]          		= emulate_on_interception,
 	[SVM_EXIT_WRITE_CR4]          		= emulate_on_interception,
@@ -2306,11 +2333,17 @@
 	[SVM_EXIT_READ_DR1]			= emulate_on_interception,
 	[SVM_EXIT_READ_DR2]			= emulate_on_interception,
 	[SVM_EXIT_READ_DR3]			= emulate_on_interception,
+	[SVM_EXIT_READ_DR4]			= emulate_on_interception,
+	[SVM_EXIT_READ_DR5]			= emulate_on_interception,
+	[SVM_EXIT_READ_DR6]			= emulate_on_interception,
+	[SVM_EXIT_READ_DR7]			= emulate_on_interception,
 	[SVM_EXIT_WRITE_DR0]			= emulate_on_interception,
 	[SVM_EXIT_WRITE_DR1]			= emulate_on_interception,
 	[SVM_EXIT_WRITE_DR2]			= emulate_on_interception,
 	[SVM_EXIT_WRITE_DR3]			= emulate_on_interception,
+	[SVM_EXIT_WRITE_DR4]			= emulate_on_interception,
 	[SVM_EXIT_WRITE_DR5]			= emulate_on_interception,
+	[SVM_EXIT_WRITE_DR6]			= emulate_on_interception,
 	[SVM_EXIT_WRITE_DR7]			= emulate_on_interception,
 	[SVM_EXIT_EXCP_BASE + DB_VECTOR]	= db_interception,
 	[SVM_EXIT_EXCP_BASE + BP_VECTOR]	= bp_interception,
@@ -2383,20 +2416,10 @@
 
 	svm_complete_interrupts(svm);
 
-	if (npt_enabled) {
-		int mmu_reload = 0;
-		if ((vcpu->arch.cr0 ^ svm->vmcb->save.cr0) & X86_CR0_PG) {
-			svm_set_cr0(vcpu, svm->vmcb->save.cr0);
-			mmu_reload = 1;
-		}
+	if (!(svm->vmcb->control.intercept_cr_write & INTERCEPT_CR0_MASK))
 		vcpu->arch.cr0 = svm->vmcb->save.cr0;
+	if (npt_enabled)
 		vcpu->arch.cr3 = svm->vmcb->save.cr3;
-		if (mmu_reload) {
-			kvm_mmu_reset_context(vcpu);
-			kvm_mmu_load(vcpu);
-		}
-	}
-
 
 	if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
 		kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
@@ -2798,12 +2821,6 @@
 
 	svm->vmcb->save.cr3 = root;
 	force_new_asid(vcpu);
-
-	if (vcpu->fpu_active) {
-		svm->vmcb->control.intercept_exceptions |= (1 << NM_VECTOR);
-		svm->vmcb->save.cr0 |= X86_CR0_TS;
-		vcpu->fpu_active = 0;
-	}
 }
 
 static int is_disabled(void)
@@ -2852,6 +2869,10 @@
 	return 0;
 }
 
+static void svm_cpuid_update(struct kvm_vcpu *vcpu)
+{
+}
+
 static const struct trace_print_flags svm_exit_reasons_str[] = {
 	{ SVM_EXIT_READ_CR0,           		"read_cr0" },
 	{ SVM_EXIT_READ_CR3,	      		"read_cr3" },
@@ -2905,9 +2926,22 @@
 	{ -1, NULL }
 };
 
-static bool svm_gb_page_enable(void)
+static int svm_get_lpage_level(void)
 {
-	return true;
+	return PT_PDPE_LEVEL;
+}
+
+static bool svm_rdtscp_supported(void)
+{
+	return false;
+}
+
+static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_svm *svm = to_svm(vcpu);
+
+	update_cr0_intercept(svm);
+	svm->vmcb->control.intercept_exceptions |= 1 << NM_VECTOR;
 }
 
 static struct kvm_x86_ops svm_x86_ops = {
@@ -2936,6 +2970,7 @@
 	.set_segment = svm_set_segment,
 	.get_cpl = svm_get_cpl,
 	.get_cs_db_l_bits = kvm_get_cs_db_l_bits,
+	.decache_cr0_guest_bits = svm_decache_cr0_guest_bits,
 	.decache_cr4_guest_bits = svm_decache_cr4_guest_bits,
 	.set_cr0 = svm_set_cr0,
 	.set_cr3 = svm_set_cr3,
@@ -2950,6 +2985,8 @@
 	.cache_reg = svm_cache_reg,
 	.get_rflags = svm_get_rflags,
 	.set_rflags = svm_set_rflags,
+	.fpu_activate = svm_fpu_activate,
+	.fpu_deactivate = svm_fpu_deactivate,
 
 	.tlb_flush = svm_flush_tlb,
 
@@ -2975,7 +3012,11 @@
 	.get_mt_mask = svm_get_mt_mask,
 
 	.exit_reasons_str = svm_exit_reasons_str,
-	.gb_page_enable = svm_gb_page_enable,
+	.get_lpage_level = svm_get_lpage_level,
+
+	.cpuid_update = svm_cpuid_update,
+
+	.rdtscp_supported = svm_rdtscp_supported,
 };
 
 static int __init svm_init(void)
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index 816e044..6ad30a2 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -56,6 +56,38 @@
 );
 
 /*
+ * Tracepoint for hypercall.
+ */
+TRACE_EVENT(kvm_hv_hypercall,
+	TP_PROTO(__u16 code, bool fast, __u16 rep_cnt, __u16 rep_idx,
+		 __u64 ingpa, __u64 outgpa),
+	TP_ARGS(code, fast, rep_cnt, rep_idx, ingpa, outgpa),
+
+	TP_STRUCT__entry(
+		__field(	__u16, 		code		)
+		__field(	bool,		fast		)
+		__field(	__u16,		rep_cnt		)
+		__field(	__u16,		rep_idx		)
+		__field(	__u64,		ingpa		)
+		__field(	__u64,		outgpa		)
+	),
+
+	TP_fast_assign(
+		__entry->code		= code;
+		__entry->fast		= fast;
+		__entry->rep_cnt	= rep_cnt;
+		__entry->rep_idx	= rep_idx;
+		__entry->ingpa		= ingpa;
+		__entry->outgpa		= outgpa;
+	),
+
+	TP_printk("code 0x%x %s cnt 0x%x idx 0x%x in 0x%llx out 0x%llx",
+		  __entry->code, __entry->fast ? "fast" : "slow",
+		  __entry->rep_cnt, __entry->rep_idx,  __entry->ingpa,
+		  __entry->outgpa)
+);
+
+/*
  * Tracepoint for PIO.
  */
 TRACE_EVENT(kvm_pio,
@@ -214,28 +246,33 @@
  * Tracepoint for guest MSR access.
  */
 TRACE_EVENT(kvm_msr,
-	TP_PROTO(unsigned int rw, unsigned int ecx, unsigned long data),
-	TP_ARGS(rw, ecx, data),
+	TP_PROTO(unsigned write, u32 ecx, u64 data, bool exception),
+	TP_ARGS(write, ecx, data, exception),
 
 	TP_STRUCT__entry(
-		__field(	unsigned int,	rw		)
-		__field(	unsigned int,	ecx		)
-		__field(	unsigned long,	data		)
+		__field(	unsigned,	write		)
+		__field(	u32,		ecx		)
+		__field(	u64,		data		)
+		__field(	u8,		exception	)
 	),
 
 	TP_fast_assign(
-		__entry->rw		= rw;
+		__entry->write		= write;
 		__entry->ecx		= ecx;
 		__entry->data		= data;
+		__entry->exception	= exception;
 	),
 
-	TP_printk("msr_%s %x = 0x%lx",
-		  __entry->rw ? "write" : "read",
-		  __entry->ecx, __entry->data)
+	TP_printk("msr_%s %x = 0x%llx%s",
+		  __entry->write ? "write" : "read",
+		  __entry->ecx, __entry->data,
+		  __entry->exception ? " (#GP)" : "")
 );
 
-#define trace_kvm_msr_read(ecx, data)		trace_kvm_msr(0, ecx, data)
-#define trace_kvm_msr_write(ecx, data)		trace_kvm_msr(1, ecx, data)
+#define trace_kvm_msr_read(ecx, data)      trace_kvm_msr(0, ecx, data, false)
+#define trace_kvm_msr_write(ecx, data)     trace_kvm_msr(1, ecx, data, false)
+#define trace_kvm_msr_read_ex(ecx)         trace_kvm_msr(0, ecx, 0, true)
+#define trace_kvm_msr_write_ex(ecx, data)  trace_kvm_msr(1, ecx, data, true)
 
 /*
  * Tracepoint for guest CR access.
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index d4918d6..14873b9 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -61,6 +61,21 @@
 static int __read_mostly emulate_invalid_guest_state = 0;
 module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 
+#define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST				\
+	(X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD)
+#define KVM_GUEST_CR0_MASK						\
+	(KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE)
+#define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST				\
+	(X86_CR0_WP | X86_CR0_NE)
+#define KVM_VM_CR0_ALWAYS_ON						\
+	(KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE)
+#define KVM_CR4_GUEST_OWNED_BITS				      \
+	(X86_CR4_PVI | X86_CR4_DE | X86_CR4_PCE | X86_CR4_OSFXSR      \
+	 | X86_CR4_OSXMMEXCPT)
+
+#define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE)
+#define KVM_RMODE_VM_CR4_ALWAYS_ON (X86_CR4_VME | X86_CR4_PAE | X86_CR4_VMXE)
+
 /*
  * These 2 parameters are used to config the controls for Pause-Loop Exiting:
  * ple_gap:    upper bound on the amount of time between two successive
@@ -136,6 +151,8 @@
 	ktime_t entry_time;
 	s64 vnmi_blocked_time;
 	u32 exit_reason;
+
+	bool rdtscp_enabled;
 };
 
 static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
@@ -210,7 +227,7 @@
 #ifdef CONFIG_X86_64
 	MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR,
 #endif
-	MSR_EFER, MSR_K6_STAR,
+	MSR_EFER, MSR_TSC_AUX, MSR_K6_STAR,
 };
 #define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index)
 
@@ -301,6 +318,11 @@
 	return !!(vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT);
 }
 
+static inline bool cpu_has_vmx_ept_1g_page(void)
+{
+	return !!(vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT);
+}
+
 static inline int cpu_has_vmx_invept_individual_addr(void)
 {
 	return !!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT);
@@ -336,9 +358,7 @@
 
 static inline int vm_need_virtualize_apic_accesses(struct kvm *kvm)
 {
-	return flexpriority_enabled &&
-		(cpu_has_vmx_virtualize_apic_accesses()) &&
-		(irqchip_in_kernel(kvm));
+	return flexpriority_enabled && irqchip_in_kernel(kvm);
 }
 
 static inline int cpu_has_vmx_vpid(void)
@@ -347,6 +367,12 @@
 		SECONDARY_EXEC_ENABLE_VPID;
 }
 
+static inline int cpu_has_vmx_rdtscp(void)
+{
+	return vmcs_config.cpu_based_2nd_exec_ctrl &
+		SECONDARY_EXEC_RDTSCP;
+}
+
 static inline int cpu_has_virtual_nmis(void)
 {
 	return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
@@ -551,22 +577,18 @@
 {
 	u32 eb;
 
-	eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR);
-	if (!vcpu->fpu_active)
-		eb |= 1u << NM_VECTOR;
-	/*
-	 * Unconditionally intercept #DB so we can maintain dr6 without
-	 * reading it every exit.
-	 */
-	eb |= 1u << DB_VECTOR;
-	if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
-		if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
-			eb |= 1u << BP_VECTOR;
-	}
+	eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
+	     (1u << NM_VECTOR) | (1u << DB_VECTOR);
+	if ((vcpu->guest_debug &
+	     (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
+	    (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP))
+		eb |= 1u << BP_VECTOR;
 	if (to_vmx(vcpu)->rmode.vm86_active)
 		eb = ~0;
 	if (enable_ept)
 		eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
+	if (vcpu->fpu_active)
+		eb &= ~(1u << NM_VECTOR);
 	vmcs_write32(EXCEPTION_BITMAP, eb);
 }
 
@@ -589,7 +611,7 @@
 	u64 guest_efer;
 	u64 ignore_bits;
 
-	guest_efer = vmx->vcpu.arch.shadow_efer;
+	guest_efer = vmx->vcpu.arch.efer;
 
 	/*
 	 * NX is emulated; LMA and LME handled by hardware; SCE meaninless
@@ -767,22 +789,30 @@
 
 static void vmx_fpu_activate(struct kvm_vcpu *vcpu)
 {
+	ulong cr0;
+
 	if (vcpu->fpu_active)
 		return;
 	vcpu->fpu_active = 1;
-	vmcs_clear_bits(GUEST_CR0, X86_CR0_TS);
-	if (vcpu->arch.cr0 & X86_CR0_TS)
-		vmcs_set_bits(GUEST_CR0, X86_CR0_TS);
+	cr0 = vmcs_readl(GUEST_CR0);
+	cr0 &= ~(X86_CR0_TS | X86_CR0_MP);
+	cr0 |= kvm_read_cr0_bits(vcpu, X86_CR0_TS | X86_CR0_MP);
+	vmcs_writel(GUEST_CR0, cr0);
 	update_exception_bitmap(vcpu);
+	vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
+	vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
 }
 
+static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu);
+
 static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu)
 {
-	if (!vcpu->fpu_active)
-		return;
-	vcpu->fpu_active = 0;
-	vmcs_set_bits(GUEST_CR0, X86_CR0_TS);
+	vmx_decache_cr0_guest_bits(vcpu);
+	vmcs_set_bits(GUEST_CR0, X86_CR0_TS | X86_CR0_MP);
 	update_exception_bitmap(vcpu);
+	vcpu->arch.cr0_guest_owned_bits = 0;
+	vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
+	vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
 }
 
 static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
@@ -878,6 +908,11 @@
 	vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
 }
 
+static bool vmx_rdtscp_supported(void)
+{
+	return cpu_has_vmx_rdtscp();
+}
+
 /*
  * Swap MSR entry in host/guest MSR entry array.
  */
@@ -913,12 +948,15 @@
 		index = __find_msr_index(vmx, MSR_CSTAR);
 		if (index >= 0)
 			move_msr_up(vmx, index, save_nmsrs++);
+		index = __find_msr_index(vmx, MSR_TSC_AUX);
+		if (index >= 0 && vmx->rdtscp_enabled)
+			move_msr_up(vmx, index, save_nmsrs++);
 		/*
 		 * MSR_K6_STAR is only needed on long mode guests, and only
 		 * if efer.sce is enabled.
 		 */
 		index = __find_msr_index(vmx, MSR_K6_STAR);
-		if ((index >= 0) && (vmx->vcpu.arch.shadow_efer & EFER_SCE))
+		if ((index >= 0) && (vmx->vcpu.arch.efer & EFER_SCE))
 			move_msr_up(vmx, index, save_nmsrs++);
 	}
 #endif
@@ -1002,6 +1040,10 @@
 	case MSR_IA32_SYSENTER_ESP:
 		data = vmcs_readl(GUEST_SYSENTER_ESP);
 		break;
+	case MSR_TSC_AUX:
+		if (!to_vmx(vcpu)->rdtscp_enabled)
+			return 1;
+		/* Otherwise falls through */
 	default:
 		vmx_load_host_state(to_vmx(vcpu));
 		msr = find_msr_entry(to_vmx(vcpu), msr_index);
@@ -1065,7 +1107,15 @@
 			vcpu->arch.pat = data;
 			break;
 		}
-		/* Otherwise falls through to kvm_set_msr_common */
+		ret = kvm_set_msr_common(vcpu, msr_index, data);
+		break;
+	case MSR_TSC_AUX:
+		if (!vmx->rdtscp_enabled)
+			return 1;
+		/* Check reserved bit, higher 32 bits should be zero */
+		if ((data >> 32) != 0)
+			return 1;
+		/* Otherwise falls through */
 	default:
 		msr = find_msr_entry(vmx, msr_index);
 		if (msr) {
@@ -1224,6 +1274,8 @@
 	      CPU_BASED_USE_IO_BITMAPS |
 	      CPU_BASED_MOV_DR_EXITING |
 	      CPU_BASED_USE_TSC_OFFSETING |
+	      CPU_BASED_MWAIT_EXITING |
+	      CPU_BASED_MONITOR_EXITING |
 	      CPU_BASED_INVLPG_EXITING;
 	opt = CPU_BASED_TPR_SHADOW |
 	      CPU_BASED_USE_MSR_BITMAPS |
@@ -1243,7 +1295,8 @@
 			SECONDARY_EXEC_ENABLE_VPID |
 			SECONDARY_EXEC_ENABLE_EPT |
 			SECONDARY_EXEC_UNRESTRICTED_GUEST |
-			SECONDARY_EXEC_PAUSE_LOOP_EXITING;
+			SECONDARY_EXEC_PAUSE_LOOP_EXITING |
+			SECONDARY_EXEC_RDTSCP;
 		if (adjust_vmx_controls(min2, opt2,
 					MSR_IA32_VMX_PROCBASED_CTLS2,
 					&_cpu_based_2nd_exec_control) < 0)
@@ -1457,8 +1510,12 @@
 static gva_t rmode_tss_base(struct kvm *kvm)
 {
 	if (!kvm->arch.tss_addr) {
-		gfn_t base_gfn = kvm->memslots[0].base_gfn +
-				 kvm->memslots[0].npages - 3;
+		struct kvm_memslots *slots;
+		gfn_t base_gfn;
+
+		slots = rcu_dereference(kvm->memslots);
+		base_gfn = kvm->memslots->memslots[0].base_gfn +
+				 kvm->memslots->memslots[0].npages - 3;
 		return base_gfn << PAGE_SHIFT;
 	}
 	return kvm->arch.tss_addr;
@@ -1544,9 +1601,7 @@
 	 * of this msr depends on is_long_mode().
 	 */
 	vmx_load_host_state(to_vmx(vcpu));
-	vcpu->arch.shadow_efer = efer;
-	if (!msr)
-		return;
+	vcpu->arch.efer = efer;
 	if (efer & EFER_LMA) {
 		vmcs_write32(VM_ENTRY_CONTROLS,
 			     vmcs_read32(VM_ENTRY_CONTROLS) |
@@ -1576,13 +1631,13 @@
 			     (guest_tr_ar & ~AR_TYPE_MASK)
 			     | AR_TYPE_BUSY_64_TSS);
 	}
-	vcpu->arch.shadow_efer |= EFER_LMA;
-	vmx_set_efer(vcpu, vcpu->arch.shadow_efer);
+	vcpu->arch.efer |= EFER_LMA;
+	vmx_set_efer(vcpu, vcpu->arch.efer);
 }
 
 static void exit_lmode(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.shadow_efer &= ~EFER_LMA;
+	vcpu->arch.efer &= ~EFER_LMA;
 
 	vmcs_write32(VM_ENTRY_CONTROLS,
 		     vmcs_read32(VM_ENTRY_CONTROLS)
@@ -1598,10 +1653,20 @@
 		ept_sync_context(construct_eptp(vcpu->arch.mmu.root_hpa));
 }
 
+static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
+{
+	ulong cr0_guest_owned_bits = vcpu->arch.cr0_guest_owned_bits;
+
+	vcpu->arch.cr0 &= ~cr0_guest_owned_bits;
+	vcpu->arch.cr0 |= vmcs_readl(GUEST_CR0) & cr0_guest_owned_bits;
+}
+
 static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.cr4 &= KVM_GUEST_CR4_MASK;
-	vcpu->arch.cr4 |= vmcs_readl(GUEST_CR4) & ~KVM_GUEST_CR4_MASK;
+	ulong cr4_guest_owned_bits = vcpu->arch.cr4_guest_owned_bits;
+
+	vcpu->arch.cr4 &= ~cr4_guest_owned_bits;
+	vcpu->arch.cr4 |= vmcs_readl(GUEST_CR4) & cr4_guest_owned_bits;
 }
 
 static void ept_load_pdptrs(struct kvm_vcpu *vcpu)
@@ -1646,7 +1711,7 @@
 			     (CPU_BASED_CR3_LOAD_EXITING |
 			      CPU_BASED_CR3_STORE_EXITING));
 		vcpu->arch.cr0 = cr0;
-		vmx_set_cr4(vcpu, vcpu->arch.cr4);
+		vmx_set_cr4(vcpu, kvm_read_cr4(vcpu));
 	} else if (!is_paging(vcpu)) {
 		/* From nonpaging to paging */
 		vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
@@ -1654,23 +1719,13 @@
 			     ~(CPU_BASED_CR3_LOAD_EXITING |
 			       CPU_BASED_CR3_STORE_EXITING));
 		vcpu->arch.cr0 = cr0;
-		vmx_set_cr4(vcpu, vcpu->arch.cr4);
+		vmx_set_cr4(vcpu, kvm_read_cr4(vcpu));
 	}
 
 	if (!(cr0 & X86_CR0_WP))
 		*hw_cr0 &= ~X86_CR0_WP;
 }
 
-static void ept_update_paging_mode_cr4(unsigned long *hw_cr4,
-					struct kvm_vcpu *vcpu)
-{
-	if (!is_paging(vcpu)) {
-		*hw_cr4 &= ~X86_CR4_PAE;
-		*hw_cr4 |= X86_CR4_PSE;
-	} else if (!(vcpu->arch.cr4 & X86_CR4_PAE))
-		*hw_cr4 &= ~X86_CR4_PAE;
-}
-
 static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -1682,8 +1737,6 @@
 	else
 		hw_cr0 = (cr0 & ~KVM_GUEST_CR0_MASK) | KVM_VM_CR0_ALWAYS_ON;
 
-	vmx_fpu_deactivate(vcpu);
-
 	if (vmx->rmode.vm86_active && (cr0 & X86_CR0_PE))
 		enter_pmode(vcpu);
 
@@ -1691,7 +1744,7 @@
 		enter_rmode(vcpu);
 
 #ifdef CONFIG_X86_64
-	if (vcpu->arch.shadow_efer & EFER_LME) {
+	if (vcpu->arch.efer & EFER_LME) {
 		if (!is_paging(vcpu) && (cr0 & X86_CR0_PG))
 			enter_lmode(vcpu);
 		if (is_paging(vcpu) && !(cr0 & X86_CR0_PG))
@@ -1702,12 +1755,12 @@
 	if (enable_ept)
 		ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
 
+	if (!vcpu->fpu_active)
+		hw_cr0 |= X86_CR0_TS | X86_CR0_MP;
+
 	vmcs_writel(CR0_READ_SHADOW, cr0);
 	vmcs_writel(GUEST_CR0, hw_cr0);
 	vcpu->arch.cr0 = cr0;
-
-	if (!(cr0 & X86_CR0_TS) || !(cr0 & X86_CR0_PE))
-		vmx_fpu_activate(vcpu);
 }
 
 static u64 construct_eptp(unsigned long root_hpa)
@@ -1738,8 +1791,6 @@
 
 	vmx_flush_tlb(vcpu);
 	vmcs_writel(GUEST_CR3, guest_cr3);
-	if (vcpu->arch.cr0 & X86_CR0_PE)
-		vmx_fpu_deactivate(vcpu);
 }
 
 static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -1748,8 +1799,14 @@
 		    KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
 
 	vcpu->arch.cr4 = cr4;
-	if (enable_ept)
-		ept_update_paging_mode_cr4(&hw_cr4, vcpu);
+	if (enable_ept) {
+		if (!is_paging(vcpu)) {
+			hw_cr4 &= ~X86_CR4_PAE;
+			hw_cr4 |= X86_CR4_PSE;
+		} else if (!(cr4 & X86_CR4_PAE)) {
+			hw_cr4 &= ~X86_CR4_PAE;
+		}
+	}
 
 	vmcs_writel(CR4_READ_SHADOW, cr4);
 	vmcs_writel(GUEST_CR4, hw_cr4);
@@ -1787,7 +1844,7 @@
 
 static int vmx_get_cpl(struct kvm_vcpu *vcpu)
 {
-	if (!(vcpu->arch.cr0 & X86_CR0_PE)) /* if real mode */
+	if (!is_protmode(vcpu))
 		return 0;
 
 	if (vmx_get_rflags(vcpu) & X86_EFLAGS_VM) /* if virtual 8086 */
@@ -2042,7 +2099,7 @@
 static bool guest_state_valid(struct kvm_vcpu *vcpu)
 {
 	/* real mode guest state checks */
-	if (!(vcpu->arch.cr0 & X86_CR0_PE)) {
+	if (!is_protmode(vcpu)) {
 		if (!rmode_segment_valid(vcpu, VCPU_SREG_CS))
 			return false;
 		if (!rmode_segment_valid(vcpu, VCPU_SREG_SS))
@@ -2175,7 +2232,7 @@
 	struct kvm_userspace_memory_region kvm_userspace_mem;
 	int r = 0;
 
-	down_write(&kvm->slots_lock);
+	mutex_lock(&kvm->slots_lock);
 	if (kvm->arch.apic_access_page)
 		goto out;
 	kvm_userspace_mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
@@ -2188,7 +2245,7 @@
 
 	kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00);
 out:
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 	return r;
 }
 
@@ -2197,7 +2254,7 @@
 	struct kvm_userspace_memory_region kvm_userspace_mem;
 	int r = 0;
 
-	down_write(&kvm->slots_lock);
+	mutex_lock(&kvm->slots_lock);
 	if (kvm->arch.ept_identity_pagetable)
 		goto out;
 	kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT;
@@ -2212,7 +2269,7 @@
 	kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
 			kvm->arch.ept_identity_map_addr >> PAGE_SHIFT);
 out:
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 	return r;
 }
 
@@ -2384,14 +2441,12 @@
 	for (i = 0; i < NR_VMX_MSR; ++i) {
 		u32 index = vmx_msr_index[i];
 		u32 data_low, data_high;
-		u64 data;
 		int j = vmx->nmsrs;
 
 		if (rdmsr_safe(index, &data_low, &data_high) < 0)
 			continue;
 		if (wrmsr_safe(index, data_low, data_high) < 0)
 			continue;
-		data = data_low | ((u64)data_high << 32);
 		vmx->guest_msrs[j].index = i;
 		vmx->guest_msrs[j].data = 0;
 		vmx->guest_msrs[j].mask = -1ull;
@@ -2404,7 +2459,10 @@
 	vmcs_write32(VM_ENTRY_CONTROLS, vmcs_config.vmentry_ctrl);
 
 	vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
-	vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
+	vmx->vcpu.arch.cr4_guest_owned_bits = KVM_CR4_GUEST_OWNED_BITS;
+	if (enable_ept)
+		vmx->vcpu.arch.cr4_guest_owned_bits |= X86_CR4_PGE;
+	vmcs_writel(CR4_GUEST_HOST_MASK, ~vmx->vcpu.arch.cr4_guest_owned_bits);
 
 	tsc_base = vmx->vcpu.kvm->arch.vm_init_tsc;
 	rdtscll(tsc_this);
@@ -2429,10 +2487,10 @@
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	u64 msr;
-	int ret;
+	int ret, idx;
 
 	vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));
-	down_read(&vcpu->kvm->slots_lock);
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
 	if (!init_rmode(vmx->vcpu.kvm)) {
 		ret = -ENOMEM;
 		goto out;
@@ -2526,7 +2584,7 @@
 		vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
 
 	vmx->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
-	vmx_set_cr0(&vmx->vcpu, vmx->vcpu.arch.cr0); /* enter rmode */
+	vmx_set_cr0(&vmx->vcpu, kvm_read_cr0(vcpu)); /* enter rmode */
 	vmx_set_cr4(&vmx->vcpu, 0);
 	vmx_set_efer(&vmx->vcpu, 0);
 	vmx_fpu_activate(&vmx->vcpu);
@@ -2540,7 +2598,7 @@
 	vmx->emulation_required = 0;
 
 out:
-	up_read(&vcpu->kvm->slots_lock);
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 	return ret;
 }
 
@@ -2717,6 +2775,12 @@
 		kvm_queue_exception(vcpu, vec);
 		return 1;
 	case BP_VECTOR:
+		/*
+		 * Update instruction length as we may reinject the exception
+		 * from user space while in guest debugging mode.
+		 */
+		to_vmx(vcpu)->vcpu.arch.event_exit_inst_len =
+			vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
 		if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
 			return 0;
 		/* fall through */
@@ -2839,6 +2903,13 @@
 		kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7);
 		/* fall through */
 	case BP_VECTOR:
+		/*
+		 * Update instruction length as we may reinject #BP from
+		 * user space while in guest debugging mode. Reading it for
+		 * #DB as well causes no harm, it is not used in that case.
+		 */
+		vmx->vcpu.arch.event_exit_inst_len =
+			vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
 		kvm_run->exit_reason = KVM_EXIT_DEBUG;
 		kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip;
 		kvm_run->debug.arch.exception = ex_no;
@@ -2940,11 +3011,10 @@
 		};
 		break;
 	case 2: /* clts */
-		vmx_fpu_deactivate(vcpu);
-		vcpu->arch.cr0 &= ~X86_CR0_TS;
-		vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
-		vmx_fpu_activate(vcpu);
+		vmx_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
+		trace_kvm_cr_write(0, kvm_read_cr0(vcpu));
 		skip_emulated_instruction(vcpu);
+		vmx_fpu_activate(vcpu);
 		return 1;
 	case 1: /*mov from cr*/
 		switch (cr) {
@@ -2962,7 +3032,9 @@
 		}
 		break;
 	case 3: /* lmsw */
-		kvm_lmsw(vcpu, (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f);
+		val = (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f;
+		trace_kvm_cr_write(0, (kvm_read_cr0(vcpu) & ~0xful) | val);
+		kvm_lmsw(vcpu, val);
 
 		skip_emulated_instruction(vcpu);
 		return 1;
@@ -2975,12 +3047,22 @@
 	return 0;
 }
 
+static int check_dr_alias(struct kvm_vcpu *vcpu)
+{
+	if (kvm_read_cr4_bits(vcpu, X86_CR4_DE)) {
+		kvm_queue_exception(vcpu, UD_VECTOR);
+		return -1;
+	}
+	return 0;
+}
+
 static int handle_dr(struct kvm_vcpu *vcpu)
 {
 	unsigned long exit_qualification;
 	unsigned long val;
 	int dr, reg;
 
+	/* Do not handle if the CPL > 0, will trigger GP on re-entry */
 	if (!kvm_require_cpl(vcpu, 0))
 		return 1;
 	dr = vmcs_readl(GUEST_DR7);
@@ -3016,14 +3098,20 @@
 		case 0 ... 3:
 			val = vcpu->arch.db[dr];
 			break;
+		case 4:
+			if (check_dr_alias(vcpu) < 0)
+				return 1;
+			/* fall through */
 		case 6:
 			val = vcpu->arch.dr6;
 			break;
-		case 7:
+		case 5:
+			if (check_dr_alias(vcpu) < 0)
+				return 1;
+			/* fall through */
+		default: /* 7 */
 			val = vcpu->arch.dr7;
 			break;
-		default:
-			val = 0;
 		}
 		kvm_register_write(vcpu, reg, val);
 	} else {
@@ -3034,21 +3122,25 @@
 			if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP))
 				vcpu->arch.eff_db[dr] = val;
 			break;
-		case 4 ... 5:
-			if (vcpu->arch.cr4 & X86_CR4_DE)
-				kvm_queue_exception(vcpu, UD_VECTOR);
-			break;
+		case 4:
+			if (check_dr_alias(vcpu) < 0)
+				return 1;
+			/* fall through */
 		case 6:
 			if (val & 0xffffffff00000000ULL) {
-				kvm_queue_exception(vcpu, GP_VECTOR);
-				break;
+				kvm_inject_gp(vcpu, 0);
+				return 1;
 			}
 			vcpu->arch.dr6 = (val & DR6_VOLATILE) | DR6_FIXED_1;
 			break;
-		case 7:
+		case 5:
+			if (check_dr_alias(vcpu) < 0)
+				return 1;
+			/* fall through */
+		default: /* 7 */
 			if (val & 0xffffffff00000000ULL) {
-				kvm_queue_exception(vcpu, GP_VECTOR);
-				break;
+				kvm_inject_gp(vcpu, 0);
+				return 1;
 			}
 			vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1;
 			if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) {
@@ -3075,6 +3167,7 @@
 	u64 data;
 
 	if (vmx_get_msr(vcpu, ecx, &data)) {
+		trace_kvm_msr_read_ex(ecx);
 		kvm_inject_gp(vcpu, 0);
 		return 1;
 	}
@@ -3094,13 +3187,13 @@
 	u64 data = (vcpu->arch.regs[VCPU_REGS_RAX] & -1u)
 		| ((u64)(vcpu->arch.regs[VCPU_REGS_RDX] & -1u) << 32);
 
-	trace_kvm_msr_write(ecx, data);
-
 	if (vmx_set_msr(vcpu, ecx, data) != 0) {
+		trace_kvm_msr_write_ex(ecx, data);
 		kvm_inject_gp(vcpu, 0);
 		return 1;
 	}
 
+	trace_kvm_msr_write(ecx, data);
 	skip_emulated_instruction(vcpu);
 	return 1;
 }
@@ -3385,7 +3478,6 @@
 		}
 
 		if (err != EMULATE_DONE) {
-			kvm_report_emulation_failure(vcpu, "emulation failure");
 			vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
 			vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
 			vcpu->run->internal.ndata = 0;
@@ -3416,6 +3508,12 @@
 	return 1;
 }
 
+static int handle_invalid_op(struct kvm_vcpu *vcpu)
+{
+	kvm_queue_exception(vcpu, UD_VECTOR);
+	return 1;
+}
+
 /*
  * The exit handlers return 1 if the exit was handled fully and guest execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
@@ -3453,6 +3551,8 @@
 	[EXIT_REASON_EPT_VIOLATION]	      = handle_ept_violation,
 	[EXIT_REASON_EPT_MISCONFIG]           = handle_ept_misconfig,
 	[EXIT_REASON_PAUSE_INSTRUCTION]       = handle_pause,
+	[EXIT_REASON_MWAIT_INSTRUCTION]	      = handle_invalid_op,
+	[EXIT_REASON_MONITOR_INSTRUCTION]     = handle_invalid_op,
 };
 
 static const int kvm_vmx_max_exit_handlers =
@@ -3686,9 +3786,6 @@
 	 */
 	vmcs_writel(HOST_CR0, read_cr0());
 
-	if (vcpu->arch.switch_db_regs)
-		set_debugreg(vcpu->arch.dr6, 6);
-
 	asm(
 		/* Store host registers */
 		"push %%"R"dx; push %%"R"bp;"
@@ -3789,9 +3886,6 @@
 				  | (1 << VCPU_EXREG_PDPTR));
 	vcpu->arch.regs_dirty = 0;
 
-	if (vcpu->arch.switch_db_regs)
-		get_debugreg(vcpu->arch.dr6, 6);
-
 	vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
 	if (vmx->rmode.irq.pending)
 		fixup_rmode_irq(vmx);
@@ -3920,7 +4014,7 @@
 	 *   b. VT-d with snooping control feature: snooping control feature of
 	 *	VT-d engine can guarantee the cache correctness. Just set it
 	 *	to WB to keep consistent with host. So the same as item 3.
-	 * 3. EPT without VT-d: always map as WB and set IGMT=1 to keep
+	 * 3. EPT without VT-d: always map as WB and set IPAT=1 to keep
 	 *    consistent with host MTRR
 	 */
 	if (is_mmio)
@@ -3931,37 +4025,88 @@
 		      VMX_EPT_MT_EPTE_SHIFT;
 	else
 		ret = (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT)
-			| VMX_EPT_IGMT_BIT;
+			| VMX_EPT_IPAT_BIT;
 
 	return ret;
 }
 
+#define _ER(x) { EXIT_REASON_##x, #x }
+
 static const struct trace_print_flags vmx_exit_reasons_str[] = {
-	{ EXIT_REASON_EXCEPTION_NMI,           "exception" },
-	{ EXIT_REASON_EXTERNAL_INTERRUPT,      "ext_irq" },
-	{ EXIT_REASON_TRIPLE_FAULT,            "triple_fault" },
-	{ EXIT_REASON_NMI_WINDOW,              "nmi_window" },
-	{ EXIT_REASON_IO_INSTRUCTION,          "io_instruction" },
-	{ EXIT_REASON_CR_ACCESS,               "cr_access" },
-	{ EXIT_REASON_DR_ACCESS,               "dr_access" },
-	{ EXIT_REASON_CPUID,                   "cpuid" },
-	{ EXIT_REASON_MSR_READ,                "rdmsr" },
-	{ EXIT_REASON_MSR_WRITE,               "wrmsr" },
-	{ EXIT_REASON_PENDING_INTERRUPT,       "interrupt_window" },
-	{ EXIT_REASON_HLT,                     "halt" },
-	{ EXIT_REASON_INVLPG,                  "invlpg" },
-	{ EXIT_REASON_VMCALL,                  "hypercall" },
-	{ EXIT_REASON_TPR_BELOW_THRESHOLD,     "tpr_below_thres" },
-	{ EXIT_REASON_APIC_ACCESS,             "apic_access" },
-	{ EXIT_REASON_WBINVD,                  "wbinvd" },
-	{ EXIT_REASON_TASK_SWITCH,             "task_switch" },
-	{ EXIT_REASON_EPT_VIOLATION,           "ept_violation" },
+	_ER(EXCEPTION_NMI),
+	_ER(EXTERNAL_INTERRUPT),
+	_ER(TRIPLE_FAULT),
+	_ER(PENDING_INTERRUPT),
+	_ER(NMI_WINDOW),
+	_ER(TASK_SWITCH),
+	_ER(CPUID),
+	_ER(HLT),
+	_ER(INVLPG),
+	_ER(RDPMC),
+	_ER(RDTSC),
+	_ER(VMCALL),
+	_ER(VMCLEAR),
+	_ER(VMLAUNCH),
+	_ER(VMPTRLD),
+	_ER(VMPTRST),
+	_ER(VMREAD),
+	_ER(VMRESUME),
+	_ER(VMWRITE),
+	_ER(VMOFF),
+	_ER(VMON),
+	_ER(CR_ACCESS),
+	_ER(DR_ACCESS),
+	_ER(IO_INSTRUCTION),
+	_ER(MSR_READ),
+	_ER(MSR_WRITE),
+	_ER(MWAIT_INSTRUCTION),
+	_ER(MONITOR_INSTRUCTION),
+	_ER(PAUSE_INSTRUCTION),
+	_ER(MCE_DURING_VMENTRY),
+	_ER(TPR_BELOW_THRESHOLD),
+	_ER(APIC_ACCESS),
+	_ER(EPT_VIOLATION),
+	_ER(EPT_MISCONFIG),
+	_ER(WBINVD),
 	{ -1, NULL }
 };
 
-static bool vmx_gb_page_enable(void)
+#undef _ER
+
+static int vmx_get_lpage_level(void)
 {
-	return false;
+	if (enable_ept && !cpu_has_vmx_ept_1g_page())
+		return PT_DIRECTORY_LEVEL;
+	else
+		/* For shadow and EPT supported 1GB page */
+		return PT_PDPE_LEVEL;
+}
+
+static inline u32 bit(int bitno)
+{
+	return 1 << (bitno & 31);
+}
+
+static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
+{
+	struct kvm_cpuid_entry2 *best;
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	u32 exec_control;
+
+	vmx->rdtscp_enabled = false;
+	if (vmx_rdtscp_supported()) {
+		exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+		if (exec_control & SECONDARY_EXEC_RDTSCP) {
+			best = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
+			if (best && (best->edx & bit(X86_FEATURE_RDTSCP)))
+				vmx->rdtscp_enabled = true;
+			else {
+				exec_control &= ~SECONDARY_EXEC_RDTSCP;
+				vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
+						exec_control);
+			}
+		}
+	}
 }
 
 static struct kvm_x86_ops vmx_x86_ops = {
@@ -3990,6 +4135,7 @@
 	.set_segment = vmx_set_segment,
 	.get_cpl = vmx_get_cpl,
 	.get_cs_db_l_bits = vmx_get_cs_db_l_bits,
+	.decache_cr0_guest_bits = vmx_decache_cr0_guest_bits,
 	.decache_cr4_guest_bits = vmx_decache_cr4_guest_bits,
 	.set_cr0 = vmx_set_cr0,
 	.set_cr3 = vmx_set_cr3,
@@ -4002,6 +4148,8 @@
 	.cache_reg = vmx_cache_reg,
 	.get_rflags = vmx_get_rflags,
 	.set_rflags = vmx_set_rflags,
+	.fpu_activate = vmx_fpu_activate,
+	.fpu_deactivate = vmx_fpu_deactivate,
 
 	.tlb_flush = vmx_flush_tlb,
 
@@ -4027,7 +4175,11 @@
 	.get_mt_mask = vmx_get_mt_mask,
 
 	.exit_reasons_str = vmx_exit_reasons_str,
-	.gb_page_enable = vmx_gb_page_enable,
+	.get_lpage_level = vmx_get_lpage_level,
+
+	.cpuid_update = vmx_cpuid_update,
+
+	.rdtscp_supported = vmx_rdtscp_supported,
 };
 
 static int __init vmx_init(void)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index a1e1bc9..e46282a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -38,6 +38,7 @@
 #include <linux/intel-iommu.h>
 #include <linux/cpufreq.h>
 #include <linux/user-return-notifier.h>
+#include <linux/srcu.h>
 #include <trace/events/kvm.h>
 #undef TRACE_INCLUDE_FILE
 #define CREATE_TRACE_POINTS
@@ -93,16 +94,16 @@
 
 struct kvm_shared_msrs_global {
 	int nr;
-	struct kvm_shared_msr {
-		u32 msr;
-		u64 value;
-	} msrs[KVM_NR_SHARED_MSRS];
+	u32 msrs[KVM_NR_SHARED_MSRS];
 };
 
 struct kvm_shared_msrs {
 	struct user_return_notifier urn;
 	bool registered;
-	u64 current_value[KVM_NR_SHARED_MSRS];
+	struct kvm_shared_msr_values {
+		u64 host;
+		u64 curr;
+	} values[KVM_NR_SHARED_MSRS];
 };
 
 static struct kvm_shared_msrs_global __read_mostly shared_msrs_global;
@@ -147,53 +148,64 @@
 static void kvm_on_user_return(struct user_return_notifier *urn)
 {
 	unsigned slot;
-	struct kvm_shared_msr *global;
 	struct kvm_shared_msrs *locals
 		= container_of(urn, struct kvm_shared_msrs, urn);
+	struct kvm_shared_msr_values *values;
 
 	for (slot = 0; slot < shared_msrs_global.nr; ++slot) {
-		global = &shared_msrs_global.msrs[slot];
-		if (global->value != locals->current_value[slot]) {
-			wrmsrl(global->msr, global->value);
-			locals->current_value[slot] = global->value;
+		values = &locals->values[slot];
+		if (values->host != values->curr) {
+			wrmsrl(shared_msrs_global.msrs[slot], values->host);
+			values->curr = values->host;
 		}
 	}
 	locals->registered = false;
 	user_return_notifier_unregister(urn);
 }
 
-void kvm_define_shared_msr(unsigned slot, u32 msr)
+static void shared_msr_update(unsigned slot, u32 msr)
 {
-	int cpu;
+	struct kvm_shared_msrs *smsr;
 	u64 value;
 
+	smsr = &__get_cpu_var(shared_msrs);
+	/* only read, and nobody should modify it at this time,
+	 * so don't need lock */
+	if (slot >= shared_msrs_global.nr) {
+		printk(KERN_ERR "kvm: invalid MSR slot!");
+		return;
+	}
+	rdmsrl_safe(msr, &value);
+	smsr->values[slot].host = value;
+	smsr->values[slot].curr = value;
+}
+
+void kvm_define_shared_msr(unsigned slot, u32 msr)
+{
 	if (slot >= shared_msrs_global.nr)
 		shared_msrs_global.nr = slot + 1;
-	shared_msrs_global.msrs[slot].msr = msr;
-	rdmsrl_safe(msr, &value);
-	shared_msrs_global.msrs[slot].value = value;
-	for_each_online_cpu(cpu)
-		per_cpu(shared_msrs, cpu).current_value[slot] = value;
+	shared_msrs_global.msrs[slot] = msr;
+	/* we need ensured the shared_msr_global have been updated */
+	smp_wmb();
 }
 EXPORT_SYMBOL_GPL(kvm_define_shared_msr);
 
 static void kvm_shared_msr_cpu_online(void)
 {
 	unsigned i;
-	struct kvm_shared_msrs *locals = &__get_cpu_var(shared_msrs);
 
 	for (i = 0; i < shared_msrs_global.nr; ++i)
-		locals->current_value[i] = shared_msrs_global.msrs[i].value;
+		shared_msr_update(i, shared_msrs_global.msrs[i]);
 }
 
 void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
 {
 	struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs);
 
-	if (((value ^ smsr->current_value[slot]) & mask) == 0)
+	if (((value ^ smsr->values[slot].curr) & mask) == 0)
 		return;
-	smsr->current_value[slot] = value;
-	wrmsrl(shared_msrs_global.msrs[slot].msr, value);
+	smsr->values[slot].curr = value;
+	wrmsrl(shared_msrs_global.msrs[slot], value);
 	if (!smsr->registered) {
 		smsr->urn.on_user_return = kvm_on_user_return;
 		user_return_notifier_register(&smsr->urn);
@@ -257,12 +269,68 @@
 }
 EXPORT_SYMBOL_GPL(kvm_set_apic_base);
 
+#define EXCPT_BENIGN		0
+#define EXCPT_CONTRIBUTORY	1
+#define EXCPT_PF		2
+
+static int exception_class(int vector)
+{
+	switch (vector) {
+	case PF_VECTOR:
+		return EXCPT_PF;
+	case DE_VECTOR:
+	case TS_VECTOR:
+	case NP_VECTOR:
+	case SS_VECTOR:
+	case GP_VECTOR:
+		return EXCPT_CONTRIBUTORY;
+	default:
+		break;
+	}
+	return EXCPT_BENIGN;
+}
+
+static void kvm_multiple_exception(struct kvm_vcpu *vcpu,
+		unsigned nr, bool has_error, u32 error_code)
+{
+	u32 prev_nr;
+	int class1, class2;
+
+	if (!vcpu->arch.exception.pending) {
+	queue:
+		vcpu->arch.exception.pending = true;
+		vcpu->arch.exception.has_error_code = has_error;
+		vcpu->arch.exception.nr = nr;
+		vcpu->arch.exception.error_code = error_code;
+		return;
+	}
+
+	/* to check exception */
+	prev_nr = vcpu->arch.exception.nr;
+	if (prev_nr == DF_VECTOR) {
+		/* triple fault -> shutdown */
+		set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
+		return;
+	}
+	class1 = exception_class(prev_nr);
+	class2 = exception_class(nr);
+	if ((class1 == EXCPT_CONTRIBUTORY && class2 == EXCPT_CONTRIBUTORY)
+		|| (class1 == EXCPT_PF && class2 != EXCPT_BENIGN)) {
+		/* generate double fault per SDM Table 5-5 */
+		vcpu->arch.exception.pending = true;
+		vcpu->arch.exception.has_error_code = true;
+		vcpu->arch.exception.nr = DF_VECTOR;
+		vcpu->arch.exception.error_code = 0;
+	} else
+		/* replace previous exception with a new one in a hope
+		   that instruction re-execution will regenerate lost
+		   exception */
+		goto queue;
+}
+
 void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr)
 {
-	WARN_ON(vcpu->arch.exception.pending);
-	vcpu->arch.exception.pending = true;
-	vcpu->arch.exception.has_error_code = false;
-	vcpu->arch.exception.nr = nr;
+	kvm_multiple_exception(vcpu, nr, false, 0);
 }
 EXPORT_SYMBOL_GPL(kvm_queue_exception);
 
@@ -270,25 +338,6 @@
 			   u32 error_code)
 {
 	++vcpu->stat.pf_guest;
-
-	if (vcpu->arch.exception.pending) {
-		switch(vcpu->arch.exception.nr) {
-		case DF_VECTOR:
-			/* triple fault -> shutdown */
-			set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
-			return;
-		case PF_VECTOR:
-			vcpu->arch.exception.nr = DF_VECTOR;
-			vcpu->arch.exception.error_code = 0;
-			return;
-		default:
-			/* replace previous exception with a new one in a hope
-			   that instruction re-execution will regenerate lost
-			   exception */
-			vcpu->arch.exception.pending = false;
-			break;
-		}
-	}
 	vcpu->arch.cr2 = addr;
 	kvm_queue_exception_e(vcpu, PF_VECTOR, error_code);
 }
@@ -301,11 +350,7 @@
 
 void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
 {
-	WARN_ON(vcpu->arch.exception.pending);
-	vcpu->arch.exception.pending = true;
-	vcpu->arch.exception.has_error_code = true;
-	vcpu->arch.exception.nr = nr;
-	vcpu->arch.exception.error_code = error_code;
+	kvm_multiple_exception(vcpu, nr, true, error_code);
 }
 EXPORT_SYMBOL_GPL(kvm_queue_exception_e);
 
@@ -383,12 +428,18 @@
 
 void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
-	if (cr0 & CR0_RESERVED_BITS) {
+	cr0 |= X86_CR0_ET;
+
+#ifdef CONFIG_X86_64
+	if (cr0 & 0xffffffff00000000UL) {
 		printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n",
-		       cr0, vcpu->arch.cr0);
+		       cr0, kvm_read_cr0(vcpu));
 		kvm_inject_gp(vcpu, 0);
 		return;
 	}
+#endif
+
+	cr0 &= ~CR0_RESERVED_BITS;
 
 	if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD)) {
 		printk(KERN_DEBUG "set_cr0: #GP, CD == 0 && NW == 1\n");
@@ -405,7 +456,7 @@
 
 	if (!is_paging(vcpu) && (cr0 & X86_CR0_PG)) {
 #ifdef CONFIG_X86_64
-		if ((vcpu->arch.shadow_efer & EFER_LME)) {
+		if ((vcpu->arch.efer & EFER_LME)) {
 			int cs_db, cs_l;
 
 			if (!is_pae(vcpu)) {
@@ -443,13 +494,13 @@
 
 void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
 {
-	kvm_set_cr0(vcpu, (vcpu->arch.cr0 & ~0x0ful) | (msw & 0x0f));
+	kvm_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~0x0ful) | (msw & 0x0f));
 }
 EXPORT_SYMBOL_GPL(kvm_lmsw);
 
 void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
-	unsigned long old_cr4 = vcpu->arch.cr4;
+	unsigned long old_cr4 = kvm_read_cr4(vcpu);
 	unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE;
 
 	if (cr4 & CR4_RESERVED_BITS) {
@@ -575,9 +626,11 @@
  * kvm-specific. Those are put in the beginning of the list.
  */
 
-#define KVM_SAVE_MSRS_BEGIN	2
+#define KVM_SAVE_MSRS_BEGIN	5
 static u32 msrs_to_save[] = {
 	MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
+	HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL,
+	HV_X64_MSR_APIC_ASSIST_PAGE,
 	MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
 	MSR_K6_STAR,
 #ifdef CONFIG_X86_64
@@ -602,7 +655,7 @@
 	}
 
 	if (is_paging(vcpu)
-	    && (vcpu->arch.shadow_efer & EFER_LME) != (efer & EFER_LME)) {
+	    && (vcpu->arch.efer & EFER_LME) != (efer & EFER_LME)) {
 		printk(KERN_DEBUG "set_efer: #GP, change LME while paging\n");
 		kvm_inject_gp(vcpu, 0);
 		return;
@@ -633,9 +686,9 @@
 	kvm_x86_ops->set_efer(vcpu, efer);
 
 	efer &= ~EFER_LMA;
-	efer |= vcpu->arch.shadow_efer & EFER_LMA;
+	efer |= vcpu->arch.efer & EFER_LMA;
 
-	vcpu->arch.shadow_efer = efer;
+	vcpu->arch.efer = efer;
 
 	vcpu->arch.mmu.base_role.nxe = (efer & EFER_NX) && !tdp_enabled;
 	kvm_mmu_reset_context(vcpu);
@@ -957,6 +1010,100 @@
 	return r;
 }
 
+static bool kvm_hv_hypercall_enabled(struct kvm *kvm)
+{
+	return kvm->arch.hv_hypercall & HV_X64_MSR_HYPERCALL_ENABLE;
+}
+
+static bool kvm_hv_msr_partition_wide(u32 msr)
+{
+	bool r = false;
+	switch (msr) {
+	case HV_X64_MSR_GUEST_OS_ID:
+	case HV_X64_MSR_HYPERCALL:
+		r = true;
+		break;
+	}
+
+	return r;
+}
+
+static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+{
+	struct kvm *kvm = vcpu->kvm;
+
+	switch (msr) {
+	case HV_X64_MSR_GUEST_OS_ID:
+		kvm->arch.hv_guest_os_id = data;
+		/* setting guest os id to zero disables hypercall page */
+		if (!kvm->arch.hv_guest_os_id)
+			kvm->arch.hv_hypercall &= ~HV_X64_MSR_HYPERCALL_ENABLE;
+		break;
+	case HV_X64_MSR_HYPERCALL: {
+		u64 gfn;
+		unsigned long addr;
+		u8 instructions[4];
+
+		/* if guest os id is not set hypercall should remain disabled */
+		if (!kvm->arch.hv_guest_os_id)
+			break;
+		if (!(data & HV_X64_MSR_HYPERCALL_ENABLE)) {
+			kvm->arch.hv_hypercall = data;
+			break;
+		}
+		gfn = data >> HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT;
+		addr = gfn_to_hva(kvm, gfn);
+		if (kvm_is_error_hva(addr))
+			return 1;
+		kvm_x86_ops->patch_hypercall(vcpu, instructions);
+		((unsigned char *)instructions)[3] = 0xc3; /* ret */
+		if (copy_to_user((void __user *)addr, instructions, 4))
+			return 1;
+		kvm->arch.hv_hypercall = data;
+		break;
+	}
+	default:
+		pr_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x "
+			  "data 0x%llx\n", msr, data);
+		return 1;
+	}
+	return 0;
+}
+
+static int set_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+{
+	switch (msr) {
+	case HV_X64_MSR_APIC_ASSIST_PAGE: {
+		unsigned long addr;
+
+		if (!(data & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE)) {
+			vcpu->arch.hv_vapic = data;
+			break;
+		}
+		addr = gfn_to_hva(vcpu->kvm, data >>
+				  HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT);
+		if (kvm_is_error_hva(addr))
+			return 1;
+		if (clear_user((void __user *)addr, PAGE_SIZE))
+			return 1;
+		vcpu->arch.hv_vapic = data;
+		break;
+	}
+	case HV_X64_MSR_EOI:
+		return kvm_hv_vapic_msr_write(vcpu, APIC_EOI, data);
+	case HV_X64_MSR_ICR:
+		return kvm_hv_vapic_msr_write(vcpu, APIC_ICR, data);
+	case HV_X64_MSR_TPR:
+		return kvm_hv_vapic_msr_write(vcpu, APIC_TASKPRI, data);
+	default:
+		pr_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x "
+			  "data 0x%llx\n", msr, data);
+		return 1;
+	}
+
+	return 0;
+}
+
 int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
 	switch (msr) {
@@ -1071,6 +1218,16 @@
 		pr_unimpl(vcpu, "unimplemented perfctr wrmsr: "
 			"0x%x data 0x%llx\n", msr, data);
 		break;
+	case HV_X64_MSR_GUEST_OS_ID ... HV_X64_MSR_SINT15:
+		if (kvm_hv_msr_partition_wide(msr)) {
+			int r;
+			mutex_lock(&vcpu->kvm->lock);
+			r = set_msr_hyperv_pw(vcpu, msr, data);
+			mutex_unlock(&vcpu->kvm->lock);
+			return r;
+		} else
+			return set_msr_hyperv(vcpu, msr, data);
+		break;
 	default:
 		if (msr && (msr == vcpu->kvm->arch.xen_hvm_config.msr))
 			return xen_hvm_config(vcpu, data);
@@ -1170,6 +1327,54 @@
 	return 0;
 }
 
+static int get_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+	u64 data = 0;
+	struct kvm *kvm = vcpu->kvm;
+
+	switch (msr) {
+	case HV_X64_MSR_GUEST_OS_ID:
+		data = kvm->arch.hv_guest_os_id;
+		break;
+	case HV_X64_MSR_HYPERCALL:
+		data = kvm->arch.hv_hypercall;
+		break;
+	default:
+		pr_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
+		return 1;
+	}
+
+	*pdata = data;
+	return 0;
+}
+
+static int get_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+	u64 data = 0;
+
+	switch (msr) {
+	case HV_X64_MSR_VP_INDEX: {
+		int r;
+		struct kvm_vcpu *v;
+		kvm_for_each_vcpu(r, v, vcpu->kvm)
+			if (v == vcpu)
+				data = r;
+		break;
+	}
+	case HV_X64_MSR_EOI:
+		return kvm_hv_vapic_msr_read(vcpu, APIC_EOI, pdata);
+	case HV_X64_MSR_ICR:
+		return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata);
+	case HV_X64_MSR_TPR:
+		return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata);
+	default:
+		pr_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
+		return 1;
+	}
+	*pdata = data;
+	return 0;
+}
+
 int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 {
 	u64 data;
@@ -1221,7 +1426,7 @@
 		data |= (((uint64_t)4ULL) << 40);
 		break;
 	case MSR_EFER:
-		data = vcpu->arch.shadow_efer;
+		data = vcpu->arch.efer;
 		break;
 	case MSR_KVM_WALL_CLOCK:
 		data = vcpu->kvm->arch.wall_clock;
@@ -1236,6 +1441,16 @@
 	case MSR_IA32_MCG_STATUS:
 	case MSR_IA32_MC0_CTL ... MSR_IA32_MC0_CTL + 4 * KVM_MAX_MCE_BANKS - 1:
 		return get_msr_mce(vcpu, msr, pdata);
+	case HV_X64_MSR_GUEST_OS_ID ... HV_X64_MSR_SINT15:
+		if (kvm_hv_msr_partition_wide(msr)) {
+			int r;
+			mutex_lock(&vcpu->kvm->lock);
+			r = get_msr_hyperv_pw(vcpu, msr, pdata);
+			mutex_unlock(&vcpu->kvm->lock);
+			return r;
+		} else
+			return get_msr_hyperv(vcpu, msr, pdata);
+		break;
 	default:
 		if (!ignore_msrs) {
 			pr_unimpl(vcpu, "unhandled rdmsr: 0x%x\n", msr);
@@ -1261,15 +1476,15 @@
 		    int (*do_msr)(struct kvm_vcpu *vcpu,
 				  unsigned index, u64 *data))
 {
-	int i;
+	int i, idx;
 
 	vcpu_load(vcpu);
 
-	down_read(&vcpu->kvm->slots_lock);
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
 	for (i = 0; i < msrs->nmsrs; ++i)
 		if (do_msr(vcpu, entries[i].index, &entries[i].data))
 			break;
-	up_read(&vcpu->kvm->slots_lock);
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
 	vcpu_put(vcpu);
 
@@ -1351,6 +1566,11 @@
 	case KVM_CAP_XEN_HVM:
 	case KVM_CAP_ADJUST_CLOCK:
 	case KVM_CAP_VCPU_EVENTS:
+	case KVM_CAP_HYPERV:
+	case KVM_CAP_HYPERV_VAPIC:
+	case KVM_CAP_HYPERV_SPIN:
+	case KVM_CAP_PCI_SEGMENT:
+	case KVM_CAP_X86_ROBUST_SINGLESTEP:
 		r = 1;
 		break;
 	case KVM_CAP_COALESCED_MMIO:
@@ -1464,8 +1684,8 @@
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
-	kvm_x86_ops->vcpu_put(vcpu);
 	kvm_put_guest_fpu(vcpu);
+	kvm_x86_ops->vcpu_put(vcpu);
 }
 
 static int is_efer_nx(void)
@@ -1530,6 +1750,7 @@
 	cpuid_fix_nx_cap(vcpu);
 	r = 0;
 	kvm_apic_set_version(vcpu);
+	kvm_x86_ops->cpuid_update(vcpu);
 
 out_free:
 	vfree(cpuid_entries);
@@ -1552,6 +1773,7 @@
 		goto out;
 	vcpu->arch.cpuid_nent = cpuid->nent;
 	kvm_apic_set_version(vcpu);
+	kvm_x86_ops->cpuid_update(vcpu);
 	return 0;
 
 out:
@@ -1594,12 +1816,15 @@
 			 u32 index, int *nent, int maxnent)
 {
 	unsigned f_nx = is_efer_nx() ? F(NX) : 0;
-	unsigned f_gbpages = kvm_x86_ops->gb_page_enable() ? F(GBPAGES) : 0;
 #ifdef CONFIG_X86_64
+	unsigned f_gbpages = (kvm_x86_ops->get_lpage_level() == PT_PDPE_LEVEL)
+				? F(GBPAGES) : 0;
 	unsigned f_lm = F(LM);
 #else
+	unsigned f_gbpages = 0;
 	unsigned f_lm = 0;
 #endif
+	unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0;
 
 	/* cpuid 1.edx */
 	const u32 kvm_supported_word0_x86_features =
@@ -1619,7 +1844,7 @@
 		F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
 		F(PAT) | F(PSE36) | 0 /* Reserved */ |
 		f_nx | 0 /* Reserved */ | F(MMXEXT) | F(MMX) |
-		F(FXSR) | F(FXSR_OPT) | f_gbpages | 0 /* RDTSCP */ |
+		F(FXSR) | F(FXSR_OPT) | f_gbpages | f_rdtscp |
 		0 /* Reserved */ | f_lm | F(3DNOWEXT) | F(3DNOW);
 	/* cpuid 1.ecx */
 	const u32 kvm_supported_word4_x86_features =
@@ -1866,7 +2091,7 @@
 		return 0;
 	if (mce->status & MCI_STATUS_UC) {
 		if ((vcpu->arch.mcg_status & MCG_STATUS_MCIP) ||
-		    !(vcpu->arch.cr4 & X86_CR4_MCE)) {
+		    !kvm_read_cr4_bits(vcpu, X86_CR4_MCE)) {
 			printk(KERN_DEBUG "kvm: set_mce: "
 			       "injects mce exception while "
 			       "previous one is in progress!\n");
@@ -2160,14 +2385,14 @@
 	if (kvm_nr_mmu_pages < KVM_MIN_ALLOC_MMU_PAGES)
 		return -EINVAL;
 
-	down_write(&kvm->slots_lock);
+	mutex_lock(&kvm->slots_lock);
 	spin_lock(&kvm->mmu_lock);
 
 	kvm_mmu_change_mmu_pages(kvm, kvm_nr_mmu_pages);
 	kvm->arch.n_requested_mmu_pages = kvm_nr_mmu_pages;
 
 	spin_unlock(&kvm->mmu_lock);
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 	return 0;
 }
 
@@ -2176,13 +2401,35 @@
 	return kvm->arch.n_alloc_mmu_pages;
 }
 
+gfn_t unalias_gfn_instantiation(struct kvm *kvm, gfn_t gfn)
+{
+	int i;
+	struct kvm_mem_alias *alias;
+	struct kvm_mem_aliases *aliases;
+
+	aliases = rcu_dereference(kvm->arch.aliases);
+
+	for (i = 0; i < aliases->naliases; ++i) {
+		alias = &aliases->aliases[i];
+		if (alias->flags & KVM_ALIAS_INVALID)
+			continue;
+		if (gfn >= alias->base_gfn
+		    && gfn < alias->base_gfn + alias->npages)
+			return alias->target_gfn + gfn - alias->base_gfn;
+	}
+	return gfn;
+}
+
 gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
 {
 	int i;
 	struct kvm_mem_alias *alias;
+	struct kvm_mem_aliases *aliases;
 
-	for (i = 0; i < kvm->arch.naliases; ++i) {
-		alias = &kvm->arch.aliases[i];
+	aliases = rcu_dereference(kvm->arch.aliases);
+
+	for (i = 0; i < aliases->naliases; ++i) {
+		alias = &aliases->aliases[i];
 		if (gfn >= alias->base_gfn
 		    && gfn < alias->base_gfn + alias->npages)
 			return alias->target_gfn + gfn - alias->base_gfn;
@@ -2200,6 +2447,7 @@
 {
 	int r, n;
 	struct kvm_mem_alias *p;
+	struct kvm_mem_aliases *aliases, *old_aliases;
 
 	r = -EINVAL;
 	/* General sanity checks */
@@ -2216,26 +2464,48 @@
 	    < alias->target_phys_addr)
 		goto out;
 
-	down_write(&kvm->slots_lock);
-	spin_lock(&kvm->mmu_lock);
+	r = -ENOMEM;
+	aliases = kzalloc(sizeof(struct kvm_mem_aliases), GFP_KERNEL);
+	if (!aliases)
+		goto out;
 
-	p = &kvm->arch.aliases[alias->slot];
+	mutex_lock(&kvm->slots_lock);
+
+	/* invalidate any gfn reference in case of deletion/shrinking */
+	memcpy(aliases, kvm->arch.aliases, sizeof(struct kvm_mem_aliases));
+	aliases->aliases[alias->slot].flags |= KVM_ALIAS_INVALID;
+	old_aliases = kvm->arch.aliases;
+	rcu_assign_pointer(kvm->arch.aliases, aliases);
+	synchronize_srcu_expedited(&kvm->srcu);
+	kvm_mmu_zap_all(kvm);
+	kfree(old_aliases);
+
+	r = -ENOMEM;
+	aliases = kzalloc(sizeof(struct kvm_mem_aliases), GFP_KERNEL);
+	if (!aliases)
+		goto out_unlock;
+
+	memcpy(aliases, kvm->arch.aliases, sizeof(struct kvm_mem_aliases));
+
+	p = &aliases->aliases[alias->slot];
 	p->base_gfn = alias->guest_phys_addr >> PAGE_SHIFT;
 	p->npages = alias->memory_size >> PAGE_SHIFT;
 	p->target_gfn = alias->target_phys_addr >> PAGE_SHIFT;
+	p->flags &= ~(KVM_ALIAS_INVALID);
 
 	for (n = KVM_ALIAS_SLOTS; n > 0; --n)
-		if (kvm->arch.aliases[n - 1].npages)
+		if (aliases->aliases[n - 1].npages)
 			break;
-	kvm->arch.naliases = n;
+	aliases->naliases = n;
 
-	spin_unlock(&kvm->mmu_lock);
-	kvm_mmu_zap_all(kvm);
+	old_aliases = kvm->arch.aliases;
+	rcu_assign_pointer(kvm->arch.aliases, aliases);
+	synchronize_srcu_expedited(&kvm->srcu);
+	kfree(old_aliases);
+	r = 0;
 
-	up_write(&kvm->slots_lock);
-
-	return 0;
-
+out_unlock:
+	mutex_unlock(&kvm->slots_lock);
 out:
 	return r;
 }
@@ -2273,18 +2543,18 @@
 	r = 0;
 	switch (chip->chip_id) {
 	case KVM_IRQCHIP_PIC_MASTER:
-		spin_lock(&pic_irqchip(kvm)->lock);
+		raw_spin_lock(&pic_irqchip(kvm)->lock);
 		memcpy(&pic_irqchip(kvm)->pics[0],
 			&chip->chip.pic,
 			sizeof(struct kvm_pic_state));
-		spin_unlock(&pic_irqchip(kvm)->lock);
+		raw_spin_unlock(&pic_irqchip(kvm)->lock);
 		break;
 	case KVM_IRQCHIP_PIC_SLAVE:
-		spin_lock(&pic_irqchip(kvm)->lock);
+		raw_spin_lock(&pic_irqchip(kvm)->lock);
 		memcpy(&pic_irqchip(kvm)->pics[1],
 			&chip->chip.pic,
 			sizeof(struct kvm_pic_state));
-		spin_unlock(&pic_irqchip(kvm)->lock);
+		raw_spin_unlock(&pic_irqchip(kvm)->lock);
 		break;
 	case KVM_IRQCHIP_IOAPIC:
 		r = kvm_set_ioapic(kvm, &chip->chip.ioapic);
@@ -2364,29 +2634,62 @@
 int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 				      struct kvm_dirty_log *log)
 {
-	int r;
-	int n;
+	int r, n, i;
 	struct kvm_memory_slot *memslot;
-	int is_dirty = 0;
+	unsigned long is_dirty = 0;
+	unsigned long *dirty_bitmap = NULL;
 
-	down_write(&kvm->slots_lock);
+	mutex_lock(&kvm->slots_lock);
 
-	r = kvm_get_dirty_log(kvm, log, &is_dirty);
-	if (r)
+	r = -EINVAL;
+	if (log->slot >= KVM_MEMORY_SLOTS)
 		goto out;
 
+	memslot = &kvm->memslots->memslots[log->slot];
+	r = -ENOENT;
+	if (!memslot->dirty_bitmap)
+		goto out;
+
+	n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
+
+	r = -ENOMEM;
+	dirty_bitmap = vmalloc(n);
+	if (!dirty_bitmap)
+		goto out;
+	memset(dirty_bitmap, 0, n);
+
+	for (i = 0; !is_dirty && i < n/sizeof(long); i++)
+		is_dirty = memslot->dirty_bitmap[i];
+
 	/* If nothing is dirty, don't bother messing with page tables. */
 	if (is_dirty) {
+		struct kvm_memslots *slots, *old_slots;
+
 		spin_lock(&kvm->mmu_lock);
 		kvm_mmu_slot_remove_write_access(kvm, log->slot);
 		spin_unlock(&kvm->mmu_lock);
-		memslot = &kvm->memslots[log->slot];
-		n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
-		memset(memslot->dirty_bitmap, 0, n);
+
+		slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
+		if (!slots)
+			goto out_free;
+
+		memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots));
+		slots->memslots[log->slot].dirty_bitmap = dirty_bitmap;
+
+		old_slots = kvm->memslots;
+		rcu_assign_pointer(kvm->memslots, slots);
+		synchronize_srcu_expedited(&kvm->srcu);
+		dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap;
+		kfree(old_slots);
 	}
+
 	r = 0;
+	if (copy_to_user(log->dirty_bitmap, dirty_bitmap, n))
+		r = -EFAULT;
+out_free:
+	vfree(dirty_bitmap);
 out:
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 	return r;
 }
 
@@ -2469,6 +2772,8 @@
 		if (vpic) {
 			r = kvm_ioapic_init(kvm);
 			if (r) {
+				kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
+							  &vpic->dev);
 				kfree(vpic);
 				goto create_irqchip_unlock;
 			}
@@ -2480,10 +2785,8 @@
 		r = kvm_setup_default_irq_routing(kvm);
 		if (r) {
 			mutex_lock(&kvm->irq_lock);
-			kfree(kvm->arch.vpic);
-			kfree(kvm->arch.vioapic);
-			kvm->arch.vpic = NULL;
-			kvm->arch.vioapic = NULL;
+			kvm_ioapic_destroy(kvm);
+			kvm_destroy_pic(kvm);
 			mutex_unlock(&kvm->irq_lock);
 		}
 	create_irqchip_unlock:
@@ -2499,7 +2802,7 @@
 				   sizeof(struct kvm_pit_config)))
 			goto out;
 	create_pit:
-		down_write(&kvm->slots_lock);
+		mutex_lock(&kvm->slots_lock);
 		r = -EEXIST;
 		if (kvm->arch.vpit)
 			goto create_pit_unlock;
@@ -2508,7 +2811,7 @@
 		if (kvm->arch.vpit)
 			r = 0;
 	create_pit_unlock:
-		up_write(&kvm->slots_lock);
+		mutex_unlock(&kvm->slots_lock);
 		break;
 	case KVM_IRQ_LINE_STATUS:
 	case KVM_IRQ_LINE: {
@@ -2725,7 +3028,7 @@
 	    !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, len, v))
 		return 0;
 
-	return kvm_io_bus_write(&vcpu->kvm->mmio_bus, addr, len, v);
+	return kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, len, v);
 }
 
 static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
@@ -2734,17 +3037,44 @@
 	    !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, len, v))
 		return 0;
 
-	return kvm_io_bus_read(&vcpu->kvm->mmio_bus, addr, len, v);
+	return kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, len, v);
 }
 
-static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes,
-			       struct kvm_vcpu *vcpu)
+gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error);
+}
+
+ gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	access |= PFERR_FETCH_MASK;
+	return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error);
+}
+
+gpa_t kvm_mmu_gva_to_gpa_write(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	access |= PFERR_WRITE_MASK;
+	return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, access, error);
+}
+
+/* uses this to access any guest's mapped memory without checking CPL */
+gpa_t kvm_mmu_gva_to_gpa_system(struct kvm_vcpu *vcpu, gva_t gva, u32 *error)
+{
+	return vcpu->arch.mmu.gva_to_gpa(vcpu, gva, 0, error);
+}
+
+static int kvm_read_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
+				      struct kvm_vcpu *vcpu, u32 access,
+				      u32 *error)
 {
 	void *data = val;
 	int r = X86EMUL_CONTINUE;
 
 	while (bytes) {
-		gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+		gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr, access, error);
 		unsigned offset = addr & (PAGE_SIZE-1);
 		unsigned toread = min(bytes, (unsigned)PAGE_SIZE - offset);
 		int ret;
@@ -2767,14 +3097,37 @@
 	return r;
 }
 
+/* used for instruction fetching */
+static int kvm_fetch_guest_virt(gva_t addr, void *val, unsigned int bytes,
+				struct kvm_vcpu *vcpu, u32 *error)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu,
+					  access | PFERR_FETCH_MASK, error);
+}
+
+static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes,
+			       struct kvm_vcpu *vcpu, u32 *error)
+{
+	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
+					  error);
+}
+
+static int kvm_read_guest_virt_system(gva_t addr, void *val, unsigned int bytes,
+			       struct kvm_vcpu *vcpu, u32 *error)
+{
+	return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, error);
+}
+
 static int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes,
-				struct kvm_vcpu *vcpu)
+				struct kvm_vcpu *vcpu, u32 *error)
 {
 	void *data = val;
 	int r = X86EMUL_CONTINUE;
 
 	while (bytes) {
-		gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+		gpa_t gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, error);
 		unsigned offset = addr & (PAGE_SIZE-1);
 		unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset);
 		int ret;
@@ -2804,6 +3157,7 @@
 				  struct kvm_vcpu *vcpu)
 {
 	gpa_t                 gpa;
+	u32 error_code;
 
 	if (vcpu->mmio_read_completed) {
 		memcpy(val, vcpu->mmio_data, bytes);
@@ -2813,17 +3167,20 @@
 		return X86EMUL_CONTINUE;
 	}
 
-	gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+	gpa = kvm_mmu_gva_to_gpa_read(vcpu, addr, &error_code);
+
+	if (gpa == UNMAPPED_GVA) {
+		kvm_inject_page_fault(vcpu, addr, error_code);
+		return X86EMUL_PROPAGATE_FAULT;
+	}
 
 	/* For APIC access vmexit */
 	if ((gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
 		goto mmio;
 
-	if (kvm_read_guest_virt(addr, val, bytes, vcpu)
+	if (kvm_read_guest_virt(addr, val, bytes, vcpu, NULL)
 				== X86EMUL_CONTINUE)
 		return X86EMUL_CONTINUE;
-	if (gpa == UNMAPPED_GVA)
-		return X86EMUL_PROPAGATE_FAULT;
 
 mmio:
 	/*
@@ -2862,11 +3219,12 @@
 					   struct kvm_vcpu *vcpu)
 {
 	gpa_t                 gpa;
+	u32 error_code;
 
-	gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+	gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, &error_code);
 
 	if (gpa == UNMAPPED_GVA) {
-		kvm_inject_page_fault(vcpu, addr, 2);
+		kvm_inject_page_fault(vcpu, addr, error_code);
 		return X86EMUL_PROPAGATE_FAULT;
 	}
 
@@ -2930,7 +3288,7 @@
 		char *kaddr;
 		u64 val;
 
-		gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr);
+		gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, NULL);
 
 		if (gpa == UNMAPPED_GVA ||
 		   (gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE)
@@ -2967,35 +3325,21 @@
 
 int emulate_clts(struct kvm_vcpu *vcpu)
 {
-	kvm_x86_ops->set_cr0(vcpu, vcpu->arch.cr0 & ~X86_CR0_TS);
+	kvm_x86_ops->set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~X86_CR0_TS));
+	kvm_x86_ops->fpu_activate(vcpu);
 	return X86EMUL_CONTINUE;
 }
 
 int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long *dest)
 {
-	struct kvm_vcpu *vcpu = ctxt->vcpu;
-
-	switch (dr) {
-	case 0 ... 3:
-		*dest = kvm_x86_ops->get_dr(vcpu, dr);
-		return X86EMUL_CONTINUE;
-	default:
-		pr_unimpl(vcpu, "%s: unexpected dr %u\n", __func__, dr);
-		return X86EMUL_UNHANDLEABLE;
-	}
+	return kvm_x86_ops->get_dr(ctxt->vcpu, dr, dest);
 }
 
 int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, unsigned long value)
 {
 	unsigned long mask = (ctxt->mode == X86EMUL_MODE_PROT64) ? ~0ULL : ~0U;
-	int exception;
 
-	kvm_x86_ops->set_dr(ctxt->vcpu, dr, value & mask, &exception);
-	if (exception) {
-		/* FIXME: better handling */
-		return X86EMUL_UNHANDLEABLE;
-	}
-	return X86EMUL_CONTINUE;
+	return kvm_x86_ops->set_dr(ctxt->vcpu, dr, value & mask);
 }
 
 void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context)
@@ -3009,7 +3353,7 @@
 
 	rip_linear = rip + get_segment_base(vcpu, VCPU_SREG_CS);
 
-	kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu);
+	kvm_read_guest_virt(rip_linear, (void *)opcodes, 4, vcpu, NULL);
 
 	printk(KERN_ERR "emulation failed (%s) rip %lx %02x %02x %02x %02x\n",
 	       context, rip, opcodes[0], opcodes[1], opcodes[2], opcodes[3]);
@@ -3017,7 +3361,8 @@
 EXPORT_SYMBOL_GPL(kvm_report_emulation_failure);
 
 static struct x86_emulate_ops emulate_ops = {
-	.read_std            = kvm_read_guest_virt,
+	.read_std            = kvm_read_guest_virt_system,
+	.fetch               = kvm_fetch_guest_virt,
 	.read_emulated       = emulator_read_emulated,
 	.write_emulated      = emulator_write_emulated,
 	.cmpxchg_emulated    = emulator_cmpxchg_emulated,
@@ -3060,8 +3405,9 @@
 		vcpu->arch.emulate_ctxt.vcpu = vcpu;
 		vcpu->arch.emulate_ctxt.eflags = kvm_get_rflags(vcpu);
 		vcpu->arch.emulate_ctxt.mode =
+			(!is_protmode(vcpu)) ? X86EMUL_MODE_REAL :
 			(vcpu->arch.emulate_ctxt.eflags & X86_EFLAGS_VM)
-			? X86EMUL_MODE_REAL : cs_l
+			? X86EMUL_MODE_VM86 : cs_l
 			? X86EMUL_MODE_PROT64 :	cs_db
 			? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
 
@@ -3153,12 +3499,17 @@
 	gva_t q = vcpu->arch.pio.guest_gva;
 	unsigned bytes;
 	int ret;
+	u32 error_code;
 
 	bytes = vcpu->arch.pio.size * vcpu->arch.pio.cur_count;
 	if (vcpu->arch.pio.in)
-		ret = kvm_write_guest_virt(q, p, bytes, vcpu);
+		ret = kvm_write_guest_virt(q, p, bytes, vcpu, &error_code);
 	else
-		ret = kvm_read_guest_virt(q, p, bytes, vcpu);
+		ret = kvm_read_guest_virt(q, p, bytes, vcpu, &error_code);
+
+	if (ret == X86EMUL_PROPAGATE_FAULT)
+		kvm_inject_page_fault(vcpu, q, error_code);
+
 	return ret;
 }
 
@@ -3179,7 +3530,7 @@
 		if (io->in) {
 			r = pio_copy_data(vcpu);
 			if (r)
-				return r;
+				goto out;
 		}
 
 		delta = 1;
@@ -3206,7 +3557,7 @@
 			kvm_register_write(vcpu, VCPU_REGS_RSI, val);
 		}
 	}
-
+out:
 	io->count -= io->cur_count;
 	io->cur_count = 0;
 
@@ -3219,11 +3570,12 @@
 	int r;
 
 	if (vcpu->arch.pio.in)
-		r = kvm_io_bus_read(&vcpu->kvm->pio_bus, vcpu->arch.pio.port,
+		r = kvm_io_bus_read(vcpu->kvm, KVM_PIO_BUS, vcpu->arch.pio.port,
 				    vcpu->arch.pio.size, pd);
 	else
-		r = kvm_io_bus_write(&vcpu->kvm->pio_bus, vcpu->arch.pio.port,
-				     vcpu->arch.pio.size, pd);
+		r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS,
+				     vcpu->arch.pio.port, vcpu->arch.pio.size,
+				     pd);
 	return r;
 }
 
@@ -3234,7 +3586,7 @@
 	int i, r = 0;
 
 	for (i = 0; i < io->cur_count; i++) {
-		if (kvm_io_bus_write(&vcpu->kvm->pio_bus,
+		if (kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS,
 				     io->port, io->size, pd)) {
 			r = -EOPNOTSUPP;
 			break;
@@ -3248,6 +3600,8 @@
 {
 	unsigned long val;
 
+	trace_kvm_pio(!in, port, size, 1);
+
 	vcpu->run->exit_reason = KVM_EXIT_IO;
 	vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
 	vcpu->run->io.size = vcpu->arch.pio.size = size;
@@ -3259,11 +3613,10 @@
 	vcpu->arch.pio.down = 0;
 	vcpu->arch.pio.rep = 0;
 
-	trace_kvm_pio(vcpu->run->io.direction == KVM_EXIT_IO_OUT, port,
-		      size, 1);
-
-	val = kvm_register_read(vcpu, VCPU_REGS_RAX);
-	memcpy(vcpu->arch.pio_data, &val, 4);
+	if (!vcpu->arch.pio.in) {
+		val = kvm_register_read(vcpu, VCPU_REGS_RAX);
+		memcpy(vcpu->arch.pio_data, &val, 4);
+	}
 
 	if (!kernel_pio(vcpu, vcpu->arch.pio_data)) {
 		complete_pio(vcpu);
@@ -3280,6 +3633,8 @@
 	unsigned now, in_page;
 	int ret = 0;
 
+	trace_kvm_pio(!in, port, size, count);
+
 	vcpu->run->exit_reason = KVM_EXIT_IO;
 	vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
 	vcpu->run->io.size = vcpu->arch.pio.size = size;
@@ -3291,9 +3646,6 @@
 	vcpu->arch.pio.down = down;
 	vcpu->arch.pio.rep = rep;
 
-	trace_kvm_pio(vcpu->run->io.direction == KVM_EXIT_IO_OUT, port,
-		      size, count);
-
 	if (!count) {
 		kvm_x86_ops->skip_emulated_instruction(vcpu);
 		return 1;
@@ -3325,10 +3677,8 @@
 	if (!vcpu->arch.pio.in) {
 		/* string PIO write */
 		ret = pio_copy_data(vcpu);
-		if (ret == X86EMUL_PROPAGATE_FAULT) {
-			kvm_inject_gp(vcpu, 0);
+		if (ret == X86EMUL_PROPAGATE_FAULT)
 			return 1;
-		}
 		if (ret == 0 && !pio_string_write(vcpu)) {
 			complete_pio(vcpu);
 			if (vcpu->arch.pio.count == 0)
@@ -3487,11 +3837,76 @@
 		return a0 | ((gpa_t)a1 << 32);
 }
 
+int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
+{
+	u64 param, ingpa, outgpa, ret;
+	uint16_t code, rep_idx, rep_cnt, res = HV_STATUS_SUCCESS, rep_done = 0;
+	bool fast, longmode;
+	int cs_db, cs_l;
+
+	/*
+	 * hypercall generates UD from non zero cpl and real mode
+	 * per HYPER-V spec
+	 */
+	if (kvm_x86_ops->get_cpl(vcpu) != 0 || !is_protmode(vcpu)) {
+		kvm_queue_exception(vcpu, UD_VECTOR);
+		return 0;
+	}
+
+	kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
+	longmode = is_long_mode(vcpu) && cs_l == 1;
+
+	if (!longmode) {
+		param = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDX) << 32) |
+			(kvm_register_read(vcpu, VCPU_REGS_RAX) & 0xffffffff);
+		ingpa = ((u64)kvm_register_read(vcpu, VCPU_REGS_RBX) << 32) |
+			(kvm_register_read(vcpu, VCPU_REGS_RCX) & 0xffffffff);
+		outgpa = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDI) << 32) |
+			(kvm_register_read(vcpu, VCPU_REGS_RSI) & 0xffffffff);
+	}
+#ifdef CONFIG_X86_64
+	else {
+		param = kvm_register_read(vcpu, VCPU_REGS_RCX);
+		ingpa = kvm_register_read(vcpu, VCPU_REGS_RDX);
+		outgpa = kvm_register_read(vcpu, VCPU_REGS_R8);
+	}
+#endif
+
+	code = param & 0xffff;
+	fast = (param >> 16) & 0x1;
+	rep_cnt = (param >> 32) & 0xfff;
+	rep_idx = (param >> 48) & 0xfff;
+
+	trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa);
+
+	switch (code) {
+	case HV_X64_HV_NOTIFY_LONG_SPIN_WAIT:
+		kvm_vcpu_on_spin(vcpu);
+		break;
+	default:
+		res = HV_STATUS_INVALID_HYPERCALL_CODE;
+		break;
+	}
+
+	ret = res | (((u64)rep_done & 0xfff) << 32);
+	if (longmode) {
+		kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
+	} else {
+		kvm_register_write(vcpu, VCPU_REGS_RDX, ret >> 32);
+		kvm_register_write(vcpu, VCPU_REGS_RAX, ret & 0xffffffff);
+	}
+
+	return 1;
+}
+
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
 {
 	unsigned long nr, a0, a1, a2, a3, ret;
 	int r = 1;
 
+	if (kvm_hv_hypercall_enabled(vcpu->kvm))
+		return kvm_hv_hypercall(vcpu);
+
 	nr = kvm_register_read(vcpu, VCPU_REGS_RAX);
 	a0 = kvm_register_read(vcpu, VCPU_REGS_RBX);
 	a1 = kvm_register_read(vcpu, VCPU_REGS_RCX);
@@ -3534,10 +3949,8 @@
 int kvm_fix_hypercall(struct kvm_vcpu *vcpu)
 {
 	char instruction[3];
-	int ret = 0;
 	unsigned long rip = kvm_rip_read(vcpu);
 
-
 	/*
 	 * Blow out the MMU to ensure that no other VCPU has an active mapping
 	 * to ensure that the updated hypercall appears atomically across all
@@ -3546,11 +3959,8 @@
 	kvm_mmu_zap_all(vcpu->kvm);
 
 	kvm_x86_ops->patch_hypercall(vcpu, instruction);
-	if (emulator_write_emulated(rip, instruction, 3, vcpu)
-	    != X86EMUL_CONTINUE)
-		ret = -EFAULT;
 
-	return ret;
+	return emulator_write_emulated(rip, instruction, 3, vcpu);
 }
 
 static u64 mk_cr_64(u64 curr_cr, u32 new_val)
@@ -3583,10 +3993,9 @@
 {
 	unsigned long value;
 
-	kvm_x86_ops->decache_cr4_guest_bits(vcpu);
 	switch (cr) {
 	case 0:
-		value = vcpu->arch.cr0;
+		value = kvm_read_cr0(vcpu);
 		break;
 	case 2:
 		value = vcpu->arch.cr2;
@@ -3595,7 +4004,7 @@
 		value = vcpu->arch.cr3;
 		break;
 	case 4:
-		value = vcpu->arch.cr4;
+		value = kvm_read_cr4(vcpu);
 		break;
 	case 8:
 		value = kvm_get_cr8(vcpu);
@@ -3613,7 +4022,7 @@
 {
 	switch (cr) {
 	case 0:
-		kvm_set_cr0(vcpu, mk_cr_64(vcpu->arch.cr0, val));
+		kvm_set_cr0(vcpu, mk_cr_64(kvm_read_cr0(vcpu), val));
 		*rflags = kvm_get_rflags(vcpu);
 		break;
 	case 2:
@@ -3623,7 +4032,7 @@
 		kvm_set_cr3(vcpu, val);
 		break;
 	case 4:
-		kvm_set_cr4(vcpu, mk_cr_64(vcpu->arch.cr4, val));
+		kvm_set_cr4(vcpu, mk_cr_64(kvm_read_cr4(vcpu), val));
 		break;
 	case 8:
 		kvm_set_cr8(vcpu, val & 0xfUL);
@@ -3690,6 +4099,7 @@
 	}
 	return best;
 }
+EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry);
 
 int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
 {
@@ -3773,14 +4183,15 @@
 static void vapic_exit(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
+	int idx;
 
 	if (!apic || !apic->vapic_addr)
 		return;
 
-	down_read(&vcpu->kvm->slots_lock);
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
 	kvm_release_page_dirty(apic->vapic_page);
 	mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
-	up_read(&vcpu->kvm->slots_lock);
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 }
 
 static void update_cr8_intercept(struct kvm_vcpu *vcpu)
@@ -3876,12 +4287,17 @@
 			r = 0;
 			goto out;
 		}
+		if (test_and_clear_bit(KVM_REQ_DEACTIVATE_FPU, &vcpu->requests)) {
+			vcpu->fpu_active = 0;
+			kvm_x86_ops->fpu_deactivate(vcpu);
+		}
 	}
 
 	preempt_disable();
 
 	kvm_x86_ops->prepare_guest_switch(vcpu);
-	kvm_load_guest_fpu(vcpu);
+	if (vcpu->fpu_active)
+		kvm_load_guest_fpu(vcpu);
 
 	local_irq_disable();
 
@@ -3909,7 +4325,7 @@
 		kvm_lapic_sync_to_vapic(vcpu);
 	}
 
-	up_read(&vcpu->kvm->slots_lock);
+	srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
 
 	kvm_guest_enter();
 
@@ -3951,7 +4367,7 @@
 
 	preempt_enable();
 
-	down_read(&vcpu->kvm->slots_lock);
+	vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 
 	/*
 	 * Profile KVM exit RIPs:
@@ -3973,6 +4389,7 @@
 static int __vcpu_run(struct kvm_vcpu *vcpu)
 {
 	int r;
+	struct kvm *kvm = vcpu->kvm;
 
 	if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
 		pr_debug("vcpu %d received sipi with vector # %x\n",
@@ -3984,7 +4401,7 @@
 		vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
 	}
 
-	down_read(&vcpu->kvm->slots_lock);
+	vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
 	vapic_enter(vcpu);
 
 	r = 1;
@@ -3992,9 +4409,9 @@
 		if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
 			r = vcpu_enter_guest(vcpu);
 		else {
-			up_read(&vcpu->kvm->slots_lock);
+			srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
 			kvm_vcpu_block(vcpu);
-			down_read(&vcpu->kvm->slots_lock);
+			vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
 			if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
 			{
 				switch(vcpu->arch.mp_state) {
@@ -4029,13 +4446,13 @@
 			++vcpu->stat.signal_exits;
 		}
 		if (need_resched()) {
-			up_read(&vcpu->kvm->slots_lock);
+			srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
 			kvm_resched(vcpu);
-			down_read(&vcpu->kvm->slots_lock);
+			vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
 		}
 	}
 
-	up_read(&vcpu->kvm->slots_lock);
+	srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
 	post_kvm_run_save(vcpu);
 
 	vapic_exit(vcpu);
@@ -4074,10 +4491,10 @@
 		vcpu->mmio_read_completed = 1;
 		vcpu->mmio_needed = 0;
 
-		down_read(&vcpu->kvm->slots_lock);
+		vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 		r = emulate_instruction(vcpu, vcpu->arch.mmio_fault_cr2, 0,
 					EMULTYPE_NO_DECODE);
-		up_read(&vcpu->kvm->slots_lock);
+		srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
 		if (r == EMULATE_DO_MMIO) {
 			/*
 			 * Read-modify-write.  Back to userspace.
@@ -4204,13 +4621,12 @@
 	sregs->gdt.limit = dt.limit;
 	sregs->gdt.base = dt.base;
 
-	kvm_x86_ops->decache_cr4_guest_bits(vcpu);
-	sregs->cr0 = vcpu->arch.cr0;
+	sregs->cr0 = kvm_read_cr0(vcpu);
 	sregs->cr2 = vcpu->arch.cr2;
 	sregs->cr3 = vcpu->arch.cr3;
-	sregs->cr4 = vcpu->arch.cr4;
+	sregs->cr4 = kvm_read_cr4(vcpu);
 	sregs->cr8 = kvm_get_cr8(vcpu);
-	sregs->efer = vcpu->arch.shadow_efer;
+	sregs->efer = vcpu->arch.efer;
 	sregs->apic_base = kvm_get_apic_base(vcpu);
 
 	memset(sregs->interrupt_bitmap, 0, sizeof sregs->interrupt_bitmap);
@@ -4298,14 +4714,23 @@
 {
 	struct descriptor_table dtable;
 	u16 index = selector >> 3;
+	int ret;
+	u32 err;
+	gva_t addr;
 
 	get_segment_descriptor_dtable(vcpu, selector, &dtable);
 
 	if (dtable.limit < index * 8 + 7) {
 		kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc);
-		return 1;
+		return X86EMUL_PROPAGATE_FAULT;
 	}
-	return kvm_read_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu);
+	addr = dtable.base + index * 8;
+	ret = kvm_read_guest_virt_system(addr, seg_desc, sizeof(*seg_desc),
+					 vcpu,  &err);
+	if (ret == X86EMUL_PROPAGATE_FAULT)
+		kvm_inject_page_fault(vcpu, addr, err);
+
+       return ret;
 }
 
 /* allowed just for 8 bytes segments */
@@ -4319,15 +4744,23 @@
 
 	if (dtable.limit < index * 8 + 7)
 		return 1;
-	return kvm_write_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu);
+	return kvm_write_guest_virt(dtable.base + index*8, seg_desc, sizeof(*seg_desc), vcpu, NULL);
 }
 
-static gpa_t get_tss_base_addr(struct kvm_vcpu *vcpu,
+static gpa_t get_tss_base_addr_write(struct kvm_vcpu *vcpu,
+			       struct desc_struct *seg_desc)
+{
+	u32 base_addr = get_desc_base(seg_desc);
+
+	return kvm_mmu_gva_to_gpa_write(vcpu, base_addr, NULL);
+}
+
+static gpa_t get_tss_base_addr_read(struct kvm_vcpu *vcpu,
 			     struct desc_struct *seg_desc)
 {
 	u32 base_addr = get_desc_base(seg_desc);
 
-	return vcpu->arch.mmu.gva_to_gpa(vcpu, base_addr);
+	return kvm_mmu_gva_to_gpa_read(vcpu, base_addr, NULL);
 }
 
 static u16 get_segment_selector(struct kvm_vcpu *vcpu, int seg)
@@ -4338,18 +4771,6 @@
 	return kvm_seg.selector;
 }
 
-static int load_segment_descriptor_to_kvm_desct(struct kvm_vcpu *vcpu,
-						u16 selector,
-						struct kvm_segment *kvm_seg)
-{
-	struct desc_struct seg_desc;
-
-	if (load_guest_segment_descriptor(vcpu, selector, &seg_desc))
-		return 1;
-	seg_desct_to_kvm_desct(&seg_desc, selector, kvm_seg);
-	return 0;
-}
-
 static int kvm_load_realmode_segment(struct kvm_vcpu *vcpu, u16 selector, int seg)
 {
 	struct kvm_segment segvar = {
@@ -4367,7 +4788,7 @@
 		.unusable = 0,
 	};
 	kvm_x86_ops->set_segment(vcpu, &segvar, seg);
-	return 0;
+	return X86EMUL_CONTINUE;
 }
 
 static int is_vm86_segment(struct kvm_vcpu *vcpu, int seg)
@@ -4377,24 +4798,112 @@
 		(kvm_get_rflags(vcpu) & X86_EFLAGS_VM);
 }
 
-int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
-				int type_bits, int seg)
+int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg)
 {
 	struct kvm_segment kvm_seg;
+	struct desc_struct seg_desc;
+	u8 dpl, rpl, cpl;
+	unsigned err_vec = GP_VECTOR;
+	u32 err_code = 0;
+	bool null_selector = !(selector & ~0x3); /* 0000-0003 are null */
+	int ret;
 
-	if (is_vm86_segment(vcpu, seg) || !(vcpu->arch.cr0 & X86_CR0_PE))
+	if (is_vm86_segment(vcpu, seg) || !is_protmode(vcpu))
 		return kvm_load_realmode_segment(vcpu, selector, seg);
-	if (load_segment_descriptor_to_kvm_desct(vcpu, selector, &kvm_seg))
-		return 1;
-	kvm_seg.type |= type_bits;
 
-	if (seg != VCPU_SREG_SS && seg != VCPU_SREG_CS &&
-	    seg != VCPU_SREG_LDTR)
-		if (!kvm_seg.s)
-			kvm_seg.unusable = 1;
+	/* NULL selector is not valid for TR, CS and SS */
+	if ((seg == VCPU_SREG_CS || seg == VCPU_SREG_SS || seg == VCPU_SREG_TR)
+	    && null_selector)
+		goto exception;
 
+	/* TR should be in GDT only */
+	if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
+		goto exception;
+
+	ret = load_guest_segment_descriptor(vcpu, selector, &seg_desc);
+	if (ret)
+		return ret;
+
+	seg_desct_to_kvm_desct(&seg_desc, selector, &kvm_seg);
+
+	if (null_selector) { /* for NULL selector skip all following checks */
+		kvm_seg.unusable = 1;
+		goto load;
+	}
+
+	err_code = selector & 0xfffc;
+	err_vec = GP_VECTOR;
+
+	/* can't load system descriptor into segment selecor */
+	if (seg <= VCPU_SREG_GS && !kvm_seg.s)
+		goto exception;
+
+	if (!kvm_seg.present) {
+		err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR;
+		goto exception;
+	}
+
+	rpl = selector & 3;
+	dpl = kvm_seg.dpl;
+	cpl = kvm_x86_ops->get_cpl(vcpu);
+
+	switch (seg) {
+	case VCPU_SREG_SS:
+		/*
+		 * segment is not a writable data segment or segment
+		 * selector's RPL != CPL or segment selector's RPL != CPL
+		 */
+		if (rpl != cpl || (kvm_seg.type & 0xa) != 0x2 || dpl != cpl)
+			goto exception;
+		break;
+	case VCPU_SREG_CS:
+		if (!(kvm_seg.type & 8))
+			goto exception;
+
+		if (kvm_seg.type & 4) {
+			/* conforming */
+			if (dpl > cpl)
+				goto exception;
+		} else {
+			/* nonconforming */
+			if (rpl > cpl || dpl != cpl)
+				goto exception;
+		}
+		/* CS(RPL) <- CPL */
+		selector = (selector & 0xfffc) | cpl;
+            break;
+	case VCPU_SREG_TR:
+		if (kvm_seg.s || (kvm_seg.type != 1 && kvm_seg.type != 9))
+			goto exception;
+		break;
+	case VCPU_SREG_LDTR:
+		if (kvm_seg.s || kvm_seg.type != 2)
+			goto exception;
+		break;
+	default: /*  DS, ES, FS, or GS */
+		/*
+		 * segment is not a data or readable code segment or
+		 * ((segment is a data or nonconforming code segment)
+		 * and (both RPL and CPL > DPL))
+		 */
+		if ((kvm_seg.type & 0xa) == 0x8 ||
+		    (((kvm_seg.type & 0xc) != 0xc) && (rpl > dpl && cpl > dpl)))
+			goto exception;
+		break;
+	}
+
+	if (!kvm_seg.unusable && kvm_seg.s) {
+		/* mark segment as accessed */
+		kvm_seg.type |= 1;
+		seg_desc.type |= 1;
+		save_guest_segment_descriptor(vcpu, selector, &seg_desc);
+	}
+load:
 	kvm_set_segment(vcpu, &kvm_seg, seg);
-	return 0;
+	return X86EMUL_CONTINUE;
+exception:
+	kvm_queue_exception_e(vcpu, err_vec, err_code);
+	return X86EMUL_PROPAGATE_FAULT;
 }
 
 static void save_state_to_tss32(struct kvm_vcpu *vcpu,
@@ -4420,6 +4929,14 @@
 	tss->ldt_selector = get_segment_selector(vcpu, VCPU_SREG_LDTR);
 }
 
+static void kvm_load_segment_selector(struct kvm_vcpu *vcpu, u16 sel, int seg)
+{
+	struct kvm_segment kvm_seg;
+	kvm_get_segment(vcpu, &kvm_seg, seg);
+	kvm_seg.selector = sel;
+	kvm_set_segment(vcpu, &kvm_seg, seg);
+}
+
 static int load_state_from_tss32(struct kvm_vcpu *vcpu,
 				  struct tss_segment_32 *tss)
 {
@@ -4437,25 +4954,41 @@
 	kvm_register_write(vcpu, VCPU_REGS_RSI, tss->esi);
 	kvm_register_write(vcpu, VCPU_REGS_RDI, tss->edi);
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ldt_selector, 0, VCPU_SREG_LDTR))
+	/*
+	 * SDM says that segment selectors are loaded before segment
+	 * descriptors
+	 */
+	kvm_load_segment_selector(vcpu, tss->ldt_selector, VCPU_SREG_LDTR);
+	kvm_load_segment_selector(vcpu, tss->es, VCPU_SREG_ES);
+	kvm_load_segment_selector(vcpu, tss->cs, VCPU_SREG_CS);
+	kvm_load_segment_selector(vcpu, tss->ss, VCPU_SREG_SS);
+	kvm_load_segment_selector(vcpu, tss->ds, VCPU_SREG_DS);
+	kvm_load_segment_selector(vcpu, tss->fs, VCPU_SREG_FS);
+	kvm_load_segment_selector(vcpu, tss->gs, VCPU_SREG_GS);
+
+	/*
+	 * Now load segment descriptors. If fault happenes at this stage
+	 * it is handled in a context of new task
+	 */
+	if (kvm_load_segment_descriptor(vcpu, tss->ldt_selector, VCPU_SREG_LDTR))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES))
+	if (kvm_load_segment_descriptor(vcpu, tss->es, VCPU_SREG_ES))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS))
+	if (kvm_load_segment_descriptor(vcpu, tss->cs, VCPU_SREG_CS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS))
+	if (kvm_load_segment_descriptor(vcpu, tss->ss, VCPU_SREG_SS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS))
+	if (kvm_load_segment_descriptor(vcpu, tss->ds, VCPU_SREG_DS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->fs, 1, VCPU_SREG_FS))
+	if (kvm_load_segment_descriptor(vcpu, tss->fs, VCPU_SREG_FS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->gs, 1, VCPU_SREG_GS))
+	if (kvm_load_segment_descriptor(vcpu, tss->gs, VCPU_SREG_GS))
 		return 1;
 	return 0;
 }
@@ -4495,19 +5028,33 @@
 	kvm_register_write(vcpu, VCPU_REGS_RSI, tss->si);
 	kvm_register_write(vcpu, VCPU_REGS_RDI, tss->di);
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ldt, 0, VCPU_SREG_LDTR))
+	/*
+	 * SDM says that segment selectors are loaded before segment
+	 * descriptors
+	 */
+	kvm_load_segment_selector(vcpu, tss->ldt, VCPU_SREG_LDTR);
+	kvm_load_segment_selector(vcpu, tss->es, VCPU_SREG_ES);
+	kvm_load_segment_selector(vcpu, tss->cs, VCPU_SREG_CS);
+	kvm_load_segment_selector(vcpu, tss->ss, VCPU_SREG_SS);
+	kvm_load_segment_selector(vcpu, tss->ds, VCPU_SREG_DS);
+
+	/*
+	 * Now load segment descriptors. If fault happenes at this stage
+	 * it is handled in a context of new task
+	 */
+	if (kvm_load_segment_descriptor(vcpu, tss->ldt, VCPU_SREG_LDTR))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->es, 1, VCPU_SREG_ES))
+	if (kvm_load_segment_descriptor(vcpu, tss->es, VCPU_SREG_ES))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->cs, 9, VCPU_SREG_CS))
+	if (kvm_load_segment_descriptor(vcpu, tss->cs, VCPU_SREG_CS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ss, 1, VCPU_SREG_SS))
+	if (kvm_load_segment_descriptor(vcpu, tss->ss, VCPU_SREG_SS))
 		return 1;
 
-	if (kvm_load_segment_descriptor(vcpu, tss->ds, 1, VCPU_SREG_DS))
+	if (kvm_load_segment_descriptor(vcpu, tss->ds, VCPU_SREG_DS))
 		return 1;
 	return 0;
 }
@@ -4529,7 +5076,7 @@
 			    sizeof tss_segment_16))
 		goto out;
 
-	if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc),
+	if (kvm_read_guest(vcpu->kvm, get_tss_base_addr_read(vcpu, nseg_desc),
 			   &tss_segment_16, sizeof tss_segment_16))
 		goto out;
 
@@ -4537,7 +5084,7 @@
 		tss_segment_16.prev_task_link = old_tss_sel;
 
 		if (kvm_write_guest(vcpu->kvm,
-				    get_tss_base_addr(vcpu, nseg_desc),
+				    get_tss_base_addr_write(vcpu, nseg_desc),
 				    &tss_segment_16.prev_task_link,
 				    sizeof tss_segment_16.prev_task_link))
 			goto out;
@@ -4568,7 +5115,7 @@
 			    sizeof tss_segment_32))
 		goto out;
 
-	if (kvm_read_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc),
+	if (kvm_read_guest(vcpu->kvm, get_tss_base_addr_read(vcpu, nseg_desc),
 			   &tss_segment_32, sizeof tss_segment_32))
 		goto out;
 
@@ -4576,7 +5123,7 @@
 		tss_segment_32.prev_task_link = old_tss_sel;
 
 		if (kvm_write_guest(vcpu->kvm,
-				    get_tss_base_addr(vcpu, nseg_desc),
+				    get_tss_base_addr_write(vcpu, nseg_desc),
 				    &tss_segment_32.prev_task_link,
 				    sizeof tss_segment_32.prev_task_link))
 			goto out;
@@ -4599,7 +5146,7 @@
 	u32 old_tss_base = get_segment_base(vcpu, VCPU_SREG_TR);
 	u16 old_tss_sel = get_segment_selector(vcpu, VCPU_SREG_TR);
 
-	old_tss_base = vcpu->arch.mmu.gva_to_gpa(vcpu, old_tss_base);
+	old_tss_base = kvm_mmu_gva_to_gpa_write(vcpu, old_tss_base, NULL);
 
 	/* FIXME: Handle errors. Failure to read either TSS or their
 	 * descriptors should generate a pagefault.
@@ -4658,7 +5205,7 @@
 					      &nseg_desc);
 	}
 
-	kvm_x86_ops->set_cr0(vcpu, vcpu->arch.cr0 | X86_CR0_TS);
+	kvm_x86_ops->set_cr0(vcpu, kvm_read_cr0(vcpu) | X86_CR0_TS);
 	seg_desct_to_kvm_desct(&nseg_desc, tss_selector, &tr_seg);
 	tr_seg.type = 11;
 	kvm_set_segment(vcpu, &tr_seg, VCPU_SREG_TR);
@@ -4689,17 +5236,15 @@
 
 	kvm_set_cr8(vcpu, sregs->cr8);
 
-	mmu_reset_needed |= vcpu->arch.shadow_efer != sregs->efer;
+	mmu_reset_needed |= vcpu->arch.efer != sregs->efer;
 	kvm_x86_ops->set_efer(vcpu, sregs->efer);
 	kvm_set_apic_base(vcpu, sregs->apic_base);
 
-	kvm_x86_ops->decache_cr4_guest_bits(vcpu);
-
-	mmu_reset_needed |= vcpu->arch.cr0 != sregs->cr0;
+	mmu_reset_needed |= kvm_read_cr0(vcpu) != sregs->cr0;
 	kvm_x86_ops->set_cr0(vcpu, sregs->cr0);
 	vcpu->arch.cr0 = sregs->cr0;
 
-	mmu_reset_needed |= vcpu->arch.cr4 != sregs->cr4;
+	mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;
 	kvm_x86_ops->set_cr4(vcpu, sregs->cr4);
 	if (!is_long_mode(vcpu) && is_pae(vcpu)) {
 		load_pdptrs(vcpu, vcpu->arch.cr3);
@@ -4734,7 +5279,7 @@
 	/* Older userspace won't unhalt the vcpu on reset. */
 	if (kvm_vcpu_is_bsp(vcpu) && kvm_rip_read(vcpu) == 0xfff0 &&
 	    sregs->cs.selector == 0xf000 && sregs->cs.base == 0xffff0000 &&
-	    !(vcpu->arch.cr0 & X86_CR0_PE))
+	    !is_protmode(vcpu))
 		vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
 
 	vcpu_put(vcpu);
@@ -4832,11 +5377,12 @@
 {
 	unsigned long vaddr = tr->linear_address;
 	gpa_t gpa;
+	int idx;
 
 	vcpu_load(vcpu);
-	down_read(&vcpu->kvm->slots_lock);
-	gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, vaddr);
-	up_read(&vcpu->kvm->slots_lock);
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
+	gpa = kvm_mmu_gva_to_gpa_system(vcpu, vaddr, NULL);
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 	tr->physical_address = gpa;
 	tr->valid = gpa != UNMAPPED_GVA;
 	tr->writeable = 1;
@@ -4917,14 +5463,14 @@
 
 void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
 {
-	if (!vcpu->fpu_active || vcpu->guest_fpu_loaded)
+	if (vcpu->guest_fpu_loaded)
 		return;
 
 	vcpu->guest_fpu_loaded = 1;
 	kvm_fx_save(&vcpu->arch.host_fx_image);
 	kvm_fx_restore(&vcpu->arch.guest_fx_image);
+	trace_kvm_fpu(1);
 }
-EXPORT_SYMBOL_GPL(kvm_load_guest_fpu);
 
 void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
 {
@@ -4935,8 +5481,9 @@
 	kvm_fx_save(&vcpu->arch.guest_fx_image);
 	kvm_fx_restore(&vcpu->arch.host_fx_image);
 	++vcpu->stat.fpu_reload;
+	set_bit(KVM_REQ_DEACTIVATE_FPU, &vcpu->requests);
+	trace_kvm_fpu(0);
 }
-EXPORT_SYMBOL_GPL(kvm_put_guest_fpu);
 
 void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
 {
@@ -5088,11 +5635,13 @@
 
 void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
+	int idx;
+
 	kfree(vcpu->arch.mce_banks);
 	kvm_free_lapic(vcpu);
-	down_read(&vcpu->kvm->slots_lock);
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
 	kvm_mmu_destroy(vcpu);
-	up_read(&vcpu->kvm->slots_lock);
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 	free_page((unsigned long)vcpu->arch.pio_data);
 }
 
@@ -5103,6 +5652,12 @@
 	if (!kvm)
 		return ERR_PTR(-ENOMEM);
 
+	kvm->arch.aliases = kzalloc(sizeof(struct kvm_mem_aliases), GFP_KERNEL);
+	if (!kvm->arch.aliases) {
+		kfree(kvm);
+		return ERR_PTR(-ENOMEM);
+	}
+
 	INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
 	INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
 
@@ -5159,16 +5714,18 @@
 		put_page(kvm->arch.apic_access_page);
 	if (kvm->arch.ept_identity_pagetable)
 		put_page(kvm->arch.ept_identity_pagetable);
+	cleanup_srcu_struct(&kvm->srcu);
+	kfree(kvm->arch.aliases);
 	kfree(kvm);
 }
 
-int kvm_arch_set_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem,
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+				struct kvm_memory_slot *memslot,
 				struct kvm_memory_slot old,
+				struct kvm_userspace_memory_region *mem,
 				int user_alloc)
 {
-	int npages = mem->memory_size >> PAGE_SHIFT;
-	struct kvm_memory_slot *memslot = &kvm->memslots[mem->slot];
+	int npages = memslot->npages;
 
 	/*To keep backward compatibility with older userspace,
 	 *x86 needs to hanlde !user_alloc case.
@@ -5188,26 +5745,35 @@
 			if (IS_ERR((void *)userspace_addr))
 				return PTR_ERR((void *)userspace_addr);
 
-			/* set userspace_addr atomically for kvm_hva_to_rmapp */
-			spin_lock(&kvm->mmu_lock);
 			memslot->userspace_addr = userspace_addr;
-			spin_unlock(&kvm->mmu_lock);
-		} else {
-			if (!old.user_alloc && old.rmap) {
-				int ret;
-
-				down_write(&current->mm->mmap_sem);
-				ret = do_munmap(current->mm, old.userspace_addr,
-						old.npages * PAGE_SIZE);
-				up_write(&current->mm->mmap_sem);
-				if (ret < 0)
-					printk(KERN_WARNING
-				       "kvm_vm_ioctl_set_memory_region: "
-				       "failed to munmap memory\n");
-			}
 		}
 	}
 
+
+	return 0;
+}
+
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+				struct kvm_userspace_memory_region *mem,
+				struct kvm_memory_slot old,
+				int user_alloc)
+{
+
+	int npages = mem->memory_size >> PAGE_SHIFT;
+
+	if (!user_alloc && !old.user_alloc && old.rmap && !npages) {
+		int ret;
+
+		down_write(&current->mm->mmap_sem);
+		ret = do_munmap(current->mm, old.userspace_addr,
+				old.npages * PAGE_SIZE);
+		up_write(&current->mm->mmap_sem);
+		if (ret < 0)
+			printk(KERN_WARNING
+			       "kvm_vm_ioctl_set_memory_region: "
+			       "failed to munmap memory\n");
+	}
+
 	spin_lock(&kvm->mmu_lock);
 	if (!kvm->arch.n_requested_mmu_pages) {
 		unsigned int nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
@@ -5216,8 +5782,6 @@
 
 	kvm_mmu_slot_remove_write_access(kvm, mem->slot);
 	spin_unlock(&kvm->mmu_lock);
-
-	return 0;
 }
 
 void kvm_arch_flush_shadow(struct kvm *kvm)
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 5eadea5..2d101639 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -2,6 +2,7 @@
 #define ARCH_X86_KVM_X86_H
 
 #include <linux/kvm_host.h>
+#include "kvm_cache_regs.h"
 
 static inline void kvm_clear_exception_queue(struct kvm_vcpu *vcpu)
 {
@@ -35,4 +36,33 @@
 struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
                                              u32 function, u32 index);
 
+static inline bool is_protmode(struct kvm_vcpu *vcpu)
+{
+	return kvm_read_cr0_bits(vcpu, X86_CR0_PE);
+}
+
+static inline int is_long_mode(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_X86_64
+	return vcpu->arch.efer & EFER_LMA;
+#else
+	return 0;
+#endif
+}
+
+static inline int is_pae(struct kvm_vcpu *vcpu)
+{
+	return kvm_read_cr4_bits(vcpu, X86_CR4_PAE);
+}
+
+static inline int is_pse(struct kvm_vcpu *vcpu)
+{
+	return kvm_read_cr4_bits(vcpu, X86_CR4_PSE);
+}
+
+static inline int is_paging(struct kvm_vcpu *vcpu)
+{
+	return kvm_read_cr0_bits(vcpu, X86_CR0_PG);
+}
+
 #endif
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 2226f2c..5cb3f0f 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -750,6 +750,7 @@
 	free_area_init_nodes(max_zone_pfns);
 }
 
+#ifndef CONFIG_NO_BOOTMEM
 static unsigned long __init setup_node_bootmem(int nodeid,
 				 unsigned long start_pfn,
 				 unsigned long end_pfn,
@@ -766,13 +767,14 @@
 	printk(KERN_INFO "  node %d bootmap %08lx - %08lx\n",
 		 nodeid, bootmap, bootmap + bootmap_size);
 	free_bootmem_with_active_regions(nodeid, end_pfn);
-	early_res_to_bootmem(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
 
 	return bootmap + bootmap_size;
 }
+#endif
 
 void __init setup_bootmem_allocator(void)
 {
+#ifndef CONFIG_NO_BOOTMEM
 	int nodeid;
 	unsigned long bootmap_size, bootmap;
 	/*
@@ -784,11 +786,13 @@
 	if (bootmap == -1L)
 		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
 	reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
+#endif
 
 	printk(KERN_INFO "  mapped low ram: 0 - %08lx\n",
 		 max_pfn_mapped<<PAGE_SHIFT);
 	printk(KERN_INFO "  low ram: 0 - %08lx\n", max_low_pfn<<PAGE_SHIFT);
 
+#ifndef CONFIG_NO_BOOTMEM
 	for_each_online_node(nodeid) {
 		 unsigned long start_pfn, end_pfn;
 
@@ -806,6 +810,7 @@
 		bootmap = setup_node_bootmem(nodeid, start_pfn, end_pfn,
 						 bootmap);
 	}
+#endif
 
 	after_bootmem = 1;
 }
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 69ddfbd..e9b040e 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -572,6 +572,7 @@
 void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
 				int acpi, int k8)
 {
+#ifndef CONFIG_NO_BOOTMEM
 	unsigned long bootmap_size, bootmap;
 
 	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
@@ -579,13 +580,15 @@
 				 PAGE_SIZE);
 	if (bootmap == -1L)
 		panic("Cannot find bootmem map of size %ld\n", bootmap_size);
+	reserve_early(bootmap, bootmap + bootmap_size, "BOOTMAP");
 	/* don't touch min_low_pfn */
 	bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap >> PAGE_SHIFT,
 					 0, end_pfn);
 	e820_register_active_regions(0, start_pfn, end_pfn);
 	free_bootmem_with_active_regions(0, end_pfn);
-	early_res_to_bootmem(0, end_pfn<<PAGE_SHIFT);
-	reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT);
+#else
+	e820_register_active_regions(0, start_pfn, end_pfn);
+#endif
 }
 #endif
 
@@ -974,7 +977,7 @@
 			if (pmd_none(*pmd)) {
 				pte_t entry;
 
-				p = vmemmap_alloc_block(PMD_SIZE, node);
+				p = vmemmap_alloc_block_buf(PMD_SIZE, node);
 				if (!p)
 					return -ENOMEM;
 
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index b20760c..809baaa 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -418,7 +418,10 @@
 
 	for_each_online_node(nid) {
 		memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+		NODE_DATA(nid)->node_id = nid;
+#ifndef CONFIG_NO_BOOTMEM
 		NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
+#endif
 	}
 
 	setup_bootmem_allocator();
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index 3307ea8..8948f47 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -163,30 +163,48 @@
 				    unsigned long end, unsigned long size,
 				    unsigned long align)
 {
-	unsigned long mem = find_e820_area(start, end, size, align);
-	void *ptr;
+	unsigned long mem;
 
+	/*
+	 * put it on high as possible
+	 * something will go with NODE_DATA
+	 */
+	if (start < (MAX_DMA_PFN<<PAGE_SHIFT))
+		start = MAX_DMA_PFN<<PAGE_SHIFT;
+	if (start < (MAX_DMA32_PFN<<PAGE_SHIFT) &&
+	    end > (MAX_DMA32_PFN<<PAGE_SHIFT))
+		start = MAX_DMA32_PFN<<PAGE_SHIFT;
+	mem = find_e820_area(start, end, size, align);
 	if (mem != -1L)
 		return __va(mem);
 
-	ptr = __alloc_bootmem_nopanic(size, align, __pa(MAX_DMA_ADDRESS));
-	if (ptr == NULL) {
-		printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
+	/* extend the search scope */
+	end = max_pfn_mapped << PAGE_SHIFT;
+	if (end > (MAX_DMA32_PFN<<PAGE_SHIFT))
+		start = MAX_DMA32_PFN<<PAGE_SHIFT;
+	else
+		start = MAX_DMA_PFN<<PAGE_SHIFT;
+	mem = find_e820_area(start, end, size, align);
+	if (mem != -1L)
+		return __va(mem);
+
+	printk(KERN_ERR "Cannot find %lu bytes in node %d\n",
 		       size, nodeid);
-		return NULL;
-	}
-	return ptr;
+
+	return NULL;
 }
 
 /* Initialize bootmem allocator for a node */
 void __init
 setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 {
-	unsigned long start_pfn, last_pfn, bootmap_pages, bootmap_size;
+	unsigned long start_pfn, last_pfn, nodedata_phys;
 	const int pgdat_size = roundup(sizeof(pg_data_t), PAGE_SIZE);
-	unsigned long bootmap_start, nodedata_phys;
-	void *bootmap;
 	int nid;
+#ifndef CONFIG_NO_BOOTMEM
+	unsigned long bootmap_start, bootmap_pages, bootmap_size;
+	void *bootmap;
+#endif
 
 	if (!end)
 		return;
@@ -200,7 +218,7 @@
 
 	start = roundup(start, ZONE_ALIGN);
 
-	printk(KERN_INFO "Bootmem setup node %d %016lx-%016lx\n", nodeid,
+	printk(KERN_INFO "Initmem setup node %d %016lx-%016lx\n", nodeid,
 	       start, end);
 
 	start_pfn = start >> PAGE_SHIFT;
@@ -211,14 +229,21 @@
 	if (node_data[nodeid] == NULL)
 		return;
 	nodedata_phys = __pa(node_data[nodeid]);
+	reserve_early(nodedata_phys, nodedata_phys + pgdat_size, "NODE_DATA");
 	printk(KERN_INFO "  NODE_DATA [%016lx - %016lx]\n", nodedata_phys,
 		nodedata_phys + pgdat_size - 1);
+	nid = phys_to_nid(nodedata_phys);
+	if (nid != nodeid)
+		printk(KERN_INFO "    NODE_DATA(%d) on node %d\n", nodeid, nid);
 
 	memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t));
-	NODE_DATA(nodeid)->bdata = &bootmem_node_data[nodeid];
+	NODE_DATA(nodeid)->node_id = nodeid;
 	NODE_DATA(nodeid)->node_start_pfn = start_pfn;
 	NODE_DATA(nodeid)->node_spanned_pages = last_pfn - start_pfn;
 
+#ifndef CONFIG_NO_BOOTMEM
+	NODE_DATA(nodeid)->bdata = &bootmem_node_data[nodeid];
+
 	/*
 	 * Find a place for the bootmem map
 	 * nodedata_phys could be on other nodes by alloc_bootmem,
@@ -227,11 +252,7 @@
 	 * of alloc_bootmem, that could clash with reserved range
 	 */
 	bootmap_pages = bootmem_bootmap_pages(last_pfn - start_pfn);
-	nid = phys_to_nid(nodedata_phys);
-	if (nid == nodeid)
-		bootmap_start = roundup(nodedata_phys + pgdat_size, PAGE_SIZE);
-	else
-		bootmap_start = roundup(start, PAGE_SIZE);
+	bootmap_start = roundup(nodedata_phys + pgdat_size, PAGE_SIZE);
 	/*
 	 * SMP_CACHE_BYTES could be enough, but init_bootmem_node like
 	 * to use that to align to PAGE_SIZE
@@ -239,18 +260,13 @@
 	bootmap = early_node_mem(nodeid, bootmap_start, end,
 				 bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);
 	if (bootmap == NULL)  {
-		if (nodedata_phys < start || nodedata_phys >= end) {
-			/*
-			 * only need to free it if it is from other node
-			 * bootmem
-			 */
-			if (nid != nodeid)
-				free_bootmem(nodedata_phys, pgdat_size);
-		}
+		free_early(nodedata_phys, nodedata_phys + pgdat_size);
 		node_data[nodeid] = NULL;
 		return;
 	}
 	bootmap_start = __pa(bootmap);
+	reserve_early(bootmap_start, bootmap_start+(bootmap_pages<<PAGE_SHIFT),
+			"BOOTMAP");
 
 	bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
 					 bootmap_start >> PAGE_SHIFT,
@@ -259,31 +275,12 @@
 	printk(KERN_INFO "  bootmap [%016lx -  %016lx] pages %lx\n",
 		 bootmap_start, bootmap_start + bootmap_size - 1,
 		 bootmap_pages);
-
-	free_bootmem_with_active_regions(nodeid, end);
-
-	/*
-	 * convert early reserve to bootmem reserve earlier
-	 * otherwise early_node_mem could use early reserved mem
-	 * on previous node
-	 */
-	early_res_to_bootmem(start, end);
-
-	/*
-	 * in some case early_node_mem could use alloc_bootmem
-	 * to get range on other node, don't reserve that again
-	 */
-	if (nid != nodeid)
-		printk(KERN_INFO "    NODE_DATA(%d) on node %d\n", nodeid, nid);
-	else
-		reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys,
-					pgdat_size, BOOTMEM_DEFAULT);
 	nid = phys_to_nid(bootmap_start);
 	if (nid != nodeid)
 		printk(KERN_INFO "    bootmap(%d) on node %d\n", nodeid, nid);
-	else
-		reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start,
-				 bootmap_pages<<PAGE_SHIFT, BOOTMEM_DEFAULT);
+
+	free_bootmem_with_active_regions(nodeid, end);
+#endif
 
 	node_set_online(nodeid);
 }
@@ -709,6 +706,10 @@
 	for_each_online_node(i)
 		pages += free_all_bootmem_node(NODE_DATA(i));
 
+#ifdef CONFIG_NO_BOOTMEM
+	pages += free_all_memory_core_early(MAX_NUMNODES);
+#endif
+
 	return pages;
 }
 
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 1d4eb93..cf07c26 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -291,8 +291,29 @@
 	 */
 	if (kernel_set_to_readonly &&
 	    within(address, (unsigned long)_text,
-		   (unsigned long)__end_rodata_hpage_align))
-		pgprot_val(forbidden) |= _PAGE_RW;
+		   (unsigned long)__end_rodata_hpage_align)) {
+		unsigned int level;
+
+		/*
+		 * Don't enforce the !RW mapping for the kernel text mapping,
+		 * if the current mapping is already using small page mapping.
+		 * No need to work hard to preserve large page mappings in this
+		 * case.
+		 *
+		 * This also fixes the Linux Xen paravirt guest boot failure
+		 * (because of unexpected read-only mappings for kernel identity
+		 * mappings). In this paravirt guest case, the kernel text
+		 * mapping and the kernel identity mapping share the same
+		 * page-table pages. Thus we can't really use different
+		 * protections for the kernel text and identity mappings. Also,
+		 * these shared mappings are made of small page mappings.
+		 * Thus this don't enforce !RW mapping for small page kernel
+		 * text mapping logic will help Linux Xen parvirt guest boot
+		 * aswell.
+		 */
+		if (lookup_address(address, &level) && (level != PG_LEVEL_4K))
+			pgprot_val(forbidden) |= _PAGE_RW;
+	}
 #endif
 
 	prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index 6a58256..090cbbe 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -46,17 +46,6 @@
 
 static unsigned long reset_value[NUM_VIRT_COUNTERS];
 
-/* IbsFetchCtl bits/masks */
-#define IBS_FETCH_RAND_EN		(1ULL<<57)
-#define IBS_FETCH_VAL			(1ULL<<49)
-#define IBS_FETCH_ENABLE		(1ULL<<48)
-#define IBS_FETCH_CNT_MASK		0xFFFF0000ULL
-
-/* IbsOpCtl bits */
-#define IBS_OP_CNT_CTL			(1ULL<<19)
-#define IBS_OP_VAL			(1ULL<<18)
-#define IBS_OP_ENABLE			(1ULL<<17)
-
 #define IBS_FETCH_SIZE			6
 #define IBS_OP_SIZE			12
 
@@ -182,7 +171,7 @@
 			continue;
 		}
 		rdmsrl(msrs->controls[i].addr, val);
-		if (val & ARCH_PERFMON_EVENTSEL0_ENABLE)
+		if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
 			op_x86_warn_in_use(i);
 		val &= model->reserved;
 		wrmsrl(msrs->controls[i].addr, val);
@@ -290,7 +279,7 @@
 			oprofile_write_commit(&entry);
 
 			/* reenable the IRQ */
-			ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT_MASK);
+			ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT);
 			ctl |= IBS_FETCH_ENABLE;
 			wrmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
 		}
@@ -330,7 +319,7 @@
 		return;
 
 	if (ibs_config.fetch_enabled) {
-		val = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF;
+		val = (ibs_config.max_cnt_fetch >> 4) & IBS_FETCH_MAX_CNT;
 		val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0;
 		val |= IBS_FETCH_ENABLE;
 		wrmsrl(MSR_AMD64_IBSFETCHCTL, val);
@@ -352,7 +341,7 @@
 			 * avoid underflows.
 			 */
 			ibs_op_ctl = min(ibs_op_ctl + IBS_RANDOM_MAXCNT_OFFSET,
-					 0xFFFFULL);
+					 IBS_OP_MAX_CNT);
 		}
 		if (ibs_caps & IBS_CAPS_OPCNT && ibs_config.dispatched_ops)
 			ibs_op_ctl |= IBS_OP_CNT_CTL;
@@ -409,7 +398,7 @@
 		if (!reset_value[op_x86_phys_to_virt(i)])
 			continue;
 		rdmsrl(msrs->controls[i].addr, val);
-		val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 		wrmsrl(msrs->controls[i].addr, val);
 	}
 
@@ -429,7 +418,7 @@
 		if (!reset_value[op_x86_phys_to_virt(i)])
 			continue;
 		rdmsrl(msrs->controls[i].addr, val);
-		val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+		val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
 		wrmsrl(msrs->controls[i].addr, val);
 	}
 
diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c
index 5d1727b..2bf90fa 100644
--- a/arch/x86/oprofile/op_model_ppro.c
+++ b/arch/x86/oprofile/op_model_ppro.c
@@ -88,7 +88,7 @@
 			continue;
 		}
 		rdmsrl(msrs->controls[i].addr, val);
-		if (val & ARCH_PERFMON_EVENTSEL0_ENABLE)
+		if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
 			op_x86_warn_in_use(i);
 		val &= model->reserved;
 		wrmsrl(msrs->controls[i].addr, val);
@@ -166,7 +166,7 @@
 	for (i = 0; i < num_counters; ++i) {
 		if (reset_value[i]) {
 			rdmsrl(msrs->controls[i].addr, val);
-			val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+			val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 			wrmsrl(msrs->controls[i].addr, val);
 		}
 	}
@@ -184,7 +184,7 @@
 		if (!reset_value[i])
 			continue;
 		rdmsrl(msrs->controls[i].addr, val);
-		val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+		val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
 		wrmsrl(msrs->controls[i].addr, val);
 	}
 }
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index 39fba37..b110d97 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -13,9 +13,10 @@
 
 obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
 
+obj-$(CONFIG_X86_MRST)		+= mrst.o
+
 obj-y				+= common.o early.o
-obj-y				+= amd_bus.o
-obj-$(CONFIG_X86_64)		+= bus_numa.o
+obj-y				+= amd_bus.o bus_numa.o
 
 ifeq ($(CONFIG_PCI_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 5f11ff6..6e22454 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -298,17 +298,14 @@
 {
 	struct pci_dev *dev = NULL;
 
-	if (pcibios_scanned)
-		return 0;
-
 	if (acpi_noirq)
-		return 0;
+		return -ENODEV;
 
 	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
 	acpi_irq_penalty_init();
-	pcibios_scanned++;
 	pcibios_enable_irq = acpi_pci_irq_enable;
 	pcibios_disable_irq = acpi_pci_irq_disable;
+	x86_init.pci.init_irq = x86_init_noop;
 
 	if (pci_routeirq) {
 		/*
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 95ecbd4..fc1e8fe 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -2,11 +2,11 @@
 #include <linux/pci.h>
 #include <linux/topology.h>
 #include <linux/cpu.h>
+#include <linux/range.h>
+
 #include <asm/pci_x86.h>
 
-#ifdef CONFIG_X86_64
 #include <asm/pci-direct.h>
-#endif
 
 #include "bus_numa.h"
 
@@ -15,60 +15,6 @@
  * also get peer root bus resource for io,mmio
  */
 
-#ifdef CONFIG_X86_64
-
-#define RANGE_NUM 16
-
-struct res_range {
-	size_t start;
-	size_t end;
-};
-
-static void __init update_range(struct res_range *range, size_t start,
-				size_t end)
-{
-	int i;
-	int j;
-
-	for (j = 0; j < RANGE_NUM; j++) {
-		if (!range[j].end)
-			continue;
-
-		if (start <= range[j].start && end >= range[j].end) {
-			range[j].start = 0;
-			range[j].end = 0;
-			continue;
-		}
-
-		if (start <= range[j].start && end < range[j].end && range[j].start < end + 1) {
-			range[j].start = end + 1;
-			continue;
-		}
-
-
-		if (start > range[j].start && end >= range[j].end && range[j].end > start - 1) {
-			range[j].end = start - 1;
-			continue;
-		}
-
-		if (start > range[j].start && end < range[j].end) {
-			/* find the new spare */
-			for (i = 0; i < RANGE_NUM; i++) {
-				if (range[i].end == 0)
-					break;
-			}
-			if (i < RANGE_NUM) {
-				range[i].end = range[j].end;
-				range[i].start = end + 1;
-			} else {
-				printk(KERN_ERR "run of slot in ranges\n");
-			}
-			range[j].end = start - 1;
-			continue;
-		}
-	}
-}
-
 struct pci_hostbridge_probe {
 	u32 bus;
 	u32 slot;
@@ -111,6 +57,8 @@
 	fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1;
 }
 
+#define RANGE_NUM 16
+
 /**
  * early_fill_mp_bus_to_node()
  * called before pcibios_scan_root and pci_scan_bus
@@ -130,16 +78,17 @@
 	struct pci_root_info *info;
 	u32 reg;
 	struct resource *res;
-	size_t start;
-	size_t end;
-	struct res_range range[RANGE_NUM];
+	u64 start;
+	u64 end;
+	struct range range[RANGE_NUM];
 	u64 val;
 	u32 address;
+	bool found;
 
 	if (!early_pci_allowed())
 		return -1;
 
-	found_all_numa_early = 0;
+	found = false;
 	for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
 		u32 id;
 		u16 device;
@@ -153,12 +102,12 @@
 		device = (id>>16) & 0xffff;
 		if (pci_probes[i].vendor == vendor &&
 		    pci_probes[i].device == device) {
-			found_all_numa_early = 1;
+			found = true;
 			break;
 		}
 	}
 
-	if (!found_all_numa_early)
+	if (!found)
 		return 0;
 
 	pci_root_num = 0;
@@ -196,7 +145,7 @@
 	def_link = (reg >> 8) & 0x03;
 
 	memset(range, 0, sizeof(range));
-	range[0].end = 0xffff;
+	add_range(range, RANGE_NUM, 0, 0, 0xffff + 1);
 	/* io port resource */
 	for (i = 0; i < 4; i++) {
 		reg = read_pci_config(bus, slot, 1, 0xc0 + (i << 3));
@@ -220,13 +169,13 @@
 
 		info = &pci_root_info[j];
 		printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
-		       node, link, (u64)start, (u64)end);
+		       node, link, start, end);
 
 		/* kernel only handle 16 bit only */
 		if (end > 0xffff)
 			end = 0xffff;
 		update_res(info, start, end, IORESOURCE_IO, 1);
-		update_range(range, start, end);
+		subtract_range(range, RANGE_NUM, start, end + 1);
 	}
 	/* add left over io port range to def node/link, [0, 0xffff] */
 	/* find the position */
@@ -241,29 +190,32 @@
 			if (!range[i].end)
 				continue;
 
-			update_res(info, range[i].start, range[i].end,
+			update_res(info, range[i].start, range[i].end - 1,
 				   IORESOURCE_IO, 1);
 		}
 	}
 
 	memset(range, 0, sizeof(range));
 	/* 0xfd00000000-0xffffffffff for HT */
-	range[0].end = (0xfdULL<<32) - 1;
+	end = cap_resource((0xfdULL<<32) - 1);
+	end++;
+	add_range(range, RANGE_NUM, 0, 0, end);
 
 	/* need to take out [0, TOM) for RAM*/
 	address = MSR_K8_TOP_MEM1;
 	rdmsrl(address, val);
 	end = (val & 0xffffff800000ULL);
-	printk(KERN_INFO "TOM: %016lx aka %ldM\n", end, end>>20);
+	printk(KERN_INFO "TOM: %016llx aka %lldM\n", end, end>>20);
 	if (end < (1ULL<<32))
-		update_range(range, 0, end - 1);
+		subtract_range(range, RANGE_NUM, 0, end);
 
 	/* get mmconfig */
 	get_pci_mmcfg_amd_fam10h_range();
 	/* need to take out mmconf range */
 	if (fam10h_mmconf_end) {
 		printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end);
-		update_range(range, fam10h_mmconf_start, fam10h_mmconf_end);
+		subtract_range(range, RANGE_NUM, fam10h_mmconf_start,
+				 fam10h_mmconf_end + 1);
 	}
 
 	/* mmio resource */
@@ -293,7 +245,7 @@
 		info = &pci_root_info[j];
 
 		printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
-		       node, link, (u64)start, (u64)end);
+		       node, link, start, end);
 		/*
 		 * some sick allocation would have range overlap with fam10h
 		 * mmconf range, so need to update start and end.
@@ -318,14 +270,15 @@
 				/* we got a hole */
 				endx = fam10h_mmconf_start - 1;
 				update_res(info, start, endx, IORESOURCE_MEM, 0);
-				update_range(range, start, endx);
-				printk(KERN_CONT " ==> [%llx, %llx]", (u64)start, endx);
+				subtract_range(range, RANGE_NUM, start,
+						 endx + 1);
+				printk(KERN_CONT " ==> [%llx, %llx]", start, endx);
 				start = fam10h_mmconf_end + 1;
 				changed = 1;
 			}
 			if (changed) {
 				if (start <= end) {
-					printk(KERN_CONT " %s [%llx, %llx]", endx?"and":"==>", (u64)start, (u64)end);
+					printk(KERN_CONT " %s [%llx, %llx]", endx ? "and" : "==>", start, end);
 				} else {
 					printk(KERN_CONT "%s\n", endx?"":" ==> none");
 					continue;
@@ -333,8 +286,9 @@
 			}
 		}
 
-		update_res(info, start, end, IORESOURCE_MEM, 1);
-		update_range(range, start, end);
+		update_res(info, cap_resource(start), cap_resource(end),
+				 IORESOURCE_MEM, 1);
+		subtract_range(range, RANGE_NUM, start, end + 1);
 		printk(KERN_CONT "\n");
 	}
 
@@ -348,8 +302,8 @@
 		address = MSR_K8_TOP_MEM2;
 		rdmsrl(address, val);
 		end = (val & 0xffffff800000ULL);
-		printk(KERN_INFO "TOM2: %016lx aka %ldM\n", end, end>>20);
-		update_range(range, 1ULL<<32, end - 1);
+		printk(KERN_INFO "TOM2: %016llx aka %lldM\n", end, end>>20);
+		subtract_range(range, RANGE_NUM, 1ULL<<32, end);
 	}
 
 	/*
@@ -368,7 +322,8 @@
 			if (!range[i].end)
 				continue;
 
-			update_res(info, range[i].start, range[i].end,
+			update_res(info, cap_resource(range[i].start),
+				   cap_resource(range[i].end - 1),
 				   IORESOURCE_MEM, 1);
 		}
 	}
@@ -384,24 +339,14 @@
 		       info->bus_min, info->bus_max, info->node, info->link);
 		for (j = 0; j < res_num; j++) {
 			res = &info->res[j];
-			printk(KERN_DEBUG "bus: %02x index %x %s: [%llx, %llx]\n",
-			       busnum, j,
-			       (res->flags & IORESOURCE_IO)?"io port":"mmio",
-			       res->start, res->end);
+			printk(KERN_DEBUG "bus: %02x index %x %pR\n",
+				       busnum, j, res);
 		}
 	}
 
 	return 0;
 }
 
-#else  /* !CONFIG_X86_64 */
-
-static int __init early_fill_mp_bus_info(void) { return 0; }
-
-#endif /* !CONFIG_X86_64 */
-
-/* common 32/64 bit code */
-
 #define ENABLE_CF8_EXT_CFG      (1ULL << 46)
 
 static void enable_pci_io_ecs(void *unused)
diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c
index 12d54ff..64a1228 100644
--- a/arch/x86/pci/bus_numa.c
+++ b/arch/x86/pci/bus_numa.c
@@ -1,11 +1,11 @@
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/range.h>
 
 #include "bus_numa.h"
 
 int pci_root_num;
 struct pci_root_info pci_root_info[PCI_ROOT_NR];
-int found_all_numa_early;
 
 void x86_pci_root_bus_res_quirks(struct pci_bus *b)
 {
@@ -21,10 +21,6 @@
 	if (!pci_root_num)
 		return;
 
-	/* for amd, if only one root bus, don't need to do anything */
-	if (pci_root_num < 2 && found_all_numa_early)
-		return;
-
 	for (i = 0; i < pci_root_num; i++) {
 		if (pci_root_info[i].bus_min == b->number)
 			break;
@@ -52,8 +48,8 @@
 	}
 }
 
-void __devinit update_res(struct pci_root_info *info, size_t start,
-			      size_t end, unsigned long flags, int merge)
+void __devinit update_res(struct pci_root_info *info, resource_size_t start,
+			  resource_size_t end, unsigned long flags, int merge)
 {
 	int i;
 	struct resource *res;
@@ -61,25 +57,28 @@
 	if (start > end)
 		return;
 
+	if (start == MAX_RESOURCE)
+		return;
+
 	if (!merge)
 		goto addit;
 
 	/* try to merge it with old one */
 	for (i = 0; i < info->res_num; i++) {
-		size_t final_start, final_end;
-		size_t common_start, common_end;
+		resource_size_t final_start, final_end;
+		resource_size_t common_start, common_end;
 
 		res = &info->res[i];
 		if (res->flags != flags)
 			continue;
 
-		common_start = max((size_t)res->start, start);
-		common_end = min((size_t)res->end, end);
+		common_start = max(res->start, start);
+		common_end = min(res->end, end);
 		if (common_start > common_end + 1)
 			continue;
 
-		final_start = min((size_t)res->start, start);
-		final_end = max((size_t)res->end, end);
+		final_start = min(res->start, start);
+		final_end = max(res->end, end);
 
 		res->start = final_start;
 		res->end = final_end;
diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h
index 731b64e..804a4b4 100644
--- a/arch/x86/pci/bus_numa.h
+++ b/arch/x86/pci/bus_numa.h
@@ -1,5 +1,5 @@
-#ifdef CONFIG_X86_64
-
+#ifndef __BUS_NUMA_H
+#define __BUS_NUMA_H
 /*
  * sub bus (transparent) will use entres from 3 to store extra from
  * root, so need to make sure we have enough slot there.
@@ -19,8 +19,7 @@
 #define PCI_ROOT_NR 4
 extern int pci_root_num;
 extern struct pci_root_info pci_root_info[PCI_ROOT_NR];
-extern int found_all_numa_early;
 
-extern void update_res(struct pci_root_info *info, size_t start,
-			      size_t end, unsigned long flags, int merge);
+extern void update_res(struct pci_root_info *info, resource_size_t start,
+		      resource_size_t end, unsigned long flags, int merge);
 #endif
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 3736176..294e10c 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -72,12 +72,6 @@
 };
 
 /*
- * legacy, numa, and acpi all want to call pcibios_scan_root
- * from their initcalls. This flag prevents that.
- */
-int pcibios_scanned;
-
-/*
  * This interrupt-safe spinlock protects all accesses to PCI
  * configuration space.
  */
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 5a8fbf8..dece3eb 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -255,10 +255,6 @@
  */
 fs_initcall(pcibios_assign_resources);
 
-void __weak x86_pci_root_bus_res_quirks(struct pci_bus *b)
-{
-}
-
 /*
  *  If we set up a device for bus mastering, we need to check the latency
  *  timer as certain crappy BIOSes forget to set it properly.
diff --git a/arch/x86/pci/init.c b/arch/x86/pci/init.c
index 25a1f8e..adb62aa 100644
--- a/arch/x86/pci/init.c
+++ b/arch/x86/pci/init.c
@@ -1,6 +1,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <asm/pci_x86.h>
+#include <asm/x86_init.h>
 
 /* arch_initcall has too random ordering, so call the initializers
    in the right sequence from here. */
@@ -15,10 +16,9 @@
 	if (!(pci_probe & PCI_PROBE_NOEARLY))
 		pci_mmcfg_early_init();
 
-#ifdef CONFIG_PCI_OLPC
-	if (!pci_olpc_init())
-		return 0;	/* skip additional checks if it's an XO */
-#endif
+	if (x86_init.pci.arch_init && !x86_init.pci.arch_init())
+		return 0;
+
 #ifdef CONFIG_PCI_BIOS
 	pci_pcbios_init();
 #endif
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index b02f6d8..8b10752 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -53,7 +53,7 @@
 	int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
 };
 
-int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
+int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;
 void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
 
 /*
@@ -1018,7 +1018,7 @@
 	return 1;
 }
 
-static void __init pcibios_fixup_irqs(void)
+void __init pcibios_fixup_irqs(void)
 {
 	struct pci_dev *dev = NULL;
 	u8 pin;
@@ -1112,12 +1112,12 @@
 	{ }
 };
 
-int __init pcibios_irq_init(void)
+void __init pcibios_irq_init(void)
 {
 	DBG(KERN_DEBUG "PCI: IRQ init\n");
 
-	if (pcibios_enable_irq || raw_pci_ops == NULL)
-		return 0;
+	if (raw_pci_ops == NULL)
+		return;
 
 	dmi_check_system(pciirq_dmi_table);
 
@@ -1144,9 +1144,7 @@
 			pirq_table = NULL;
 	}
 
-	pcibios_enable_irq = pirq_enable_irq;
-
-	pcibios_fixup_irqs();
+	x86_init.pci.fixup_irqs();
 
 	if (io_apic_assign_pci_irqs && pci_routeirq) {
 		struct pci_dev *dev = NULL;
@@ -1159,8 +1157,6 @@
 		for_each_pci_dev(dev)
 			pirq_enable_irq(dev);
 	}
-
-	return 0;
 }
 
 static void pirq_penalize_isa_irq(int irq, int active)
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 4061bb0..0db5eaf 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -35,16 +35,13 @@
 	}
 }
 
-static int __init pci_legacy_init(void)
+int __init pci_legacy_init(void)
 {
 	if (!raw_pci_ops) {
 		printk("PCI: System does not support PCI\n");
 		return 0;
 	}
 
-	if (pcibios_scanned++)
-		return 0;
-
 	printk("PCI: Probing PCI hardware\n");
 	pci_root_bus = pcibios_scan_root(0);
 	if (pci_root_bus)
@@ -55,18 +52,15 @@
 
 int __init pci_subsys_init(void)
 {
-#ifdef CONFIG_X86_NUMAQ
-	pci_numaq_init();
-#endif
-#ifdef CONFIG_ACPI
-	pci_acpi_init();
-#endif
-#ifdef CONFIG_X86_VISWS
-	pci_visws_init();
-#endif
-	pci_legacy_init();
+	/*
+	 * The init function returns an non zero value when
+	 * pci_legacy_init should be invoked.
+	 */
+	if (x86_init.pci.init())
+		pci_legacy_init();
+
 	pcibios_fixup_peer_bridges();
-	pcibios_irq_init();
+	x86_init.pci.init_irq();
 	pcibios_init();
 
 	return 0;
diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c
new file mode 100644
index 0000000..8bf2fcb
--- /dev/null
+++ b/arch/x86/pci/mrst.c
@@ -0,0 +1,262 @@
+/*
+ * Moorestown PCI support
+ *   Copyright (c) 2008 Intel Corporation
+ *     Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Moorestown has an interesting PCI implementation:
+ *   - configuration space is memory mapped (as defined by MCFG)
+ *   - Lincroft devices also have a real, type 1 configuration space
+ *   - Early Lincroft silicon has a type 1 access bug that will cause
+ *     a hang if non-existent devices are accessed
+ *   - some devices have the "fixed BAR" capability, which means
+ *     they can't be relocated or modified; check for that during
+ *     BAR sizing
+ *
+ * So, we use the MCFG space for all reads and writes, but also send
+ * Lincroft writes to type 1 space.  But only read/write if the device
+ * actually exists, otherwise return all 1s for reads and bit bucket
+ * the writes.
+ */
+
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+
+#include <asm/acpi.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/pci_x86.h>
+#include <asm/hw_irq.h>
+#include <asm/io_apic.h>
+
+#define PCIE_CAP_OFFSET	0x100
+
+/* Fixed BAR fields */
+#define PCIE_VNDR_CAP_ID_FIXED_BAR 0x00	/* Fixed BAR (TBD) */
+#define PCI_FIXED_BAR_0_SIZE	0x04
+#define PCI_FIXED_BAR_1_SIZE	0x08
+#define PCI_FIXED_BAR_2_SIZE	0x0c
+#define PCI_FIXED_BAR_3_SIZE	0x10
+#define PCI_FIXED_BAR_4_SIZE	0x14
+#define PCI_FIXED_BAR_5_SIZE	0x1c
+
+/**
+ * fixed_bar_cap - return the offset of the fixed BAR cap if found
+ * @bus: PCI bus
+ * @devfn: device in question
+ *
+ * Look for the fixed BAR cap on @bus and @devfn, returning its offset
+ * if found or 0 otherwise.
+ */
+static int fixed_bar_cap(struct pci_bus *bus, unsigned int devfn)
+{
+	int pos;
+	u32 pcie_cap = 0, cap_data;
+
+	pos = PCIE_CAP_OFFSET;
+
+	if (!raw_pci_ext_ops)
+		return 0;
+
+	while (pos) {
+		if (raw_pci_ext_ops->read(pci_domain_nr(bus), bus->number,
+					  devfn, pos, 4, &pcie_cap))
+			return 0;
+
+		if (pcie_cap == 0xffffffff)
+			return 0;
+
+		if (PCI_EXT_CAP_ID(pcie_cap) == PCI_EXT_CAP_ID_VNDR) {
+			raw_pci_ext_ops->read(pci_domain_nr(bus), bus->number,
+					      devfn, pos + 4, 4, &cap_data);
+			if ((cap_data & 0xffff) == PCIE_VNDR_CAP_ID_FIXED_BAR)
+				return pos;
+		}
+
+		pos = pcie_cap >> 20;
+	}
+
+	return 0;
+}
+
+static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn,
+				   int reg, int len, u32 val, int offset)
+{
+	u32 size;
+	unsigned int domain, busnum;
+	int bar = (reg - PCI_BASE_ADDRESS_0) >> 2;
+
+	domain = pci_domain_nr(bus);
+	busnum = bus->number;
+
+	if (val == ~0 && len == 4) {
+		unsigned long decode;
+
+		raw_pci_ext_ops->read(domain, busnum, devfn,
+			       offset + 8 + (bar * 4), 4, &size);
+
+		/* Turn the size into a decode pattern for the sizing code */
+		if (size) {
+			decode = size - 1;
+			decode |= decode >> 1;
+			decode |= decode >> 2;
+			decode |= decode >> 4;
+			decode |= decode >> 8;
+			decode |= decode >> 16;
+			decode++;
+			decode = ~(decode - 1);
+		} else {
+			decode = ~0;
+		}
+
+		/*
+		 * If val is all ones, the core code is trying to size the reg,
+		 * so update the mmconfig space with the real size.
+		 *
+		 * Note: this assumes the fixed size we got is a power of two.
+		 */
+		return raw_pci_ext_ops->write(domain, busnum, devfn, reg, 4,
+				       decode);
+	}
+
+	/* This is some other kind of BAR write, so just do it. */
+	return raw_pci_ext_ops->write(domain, busnum, devfn, reg, len, val);
+}
+
+/**
+ * type1_access_ok - check whether to use type 1
+ * @bus: bus number
+ * @devfn: device & function in question
+ *
+ * If the bus is on a Lincroft chip and it exists, or is not on a Lincroft at
+ * all, the we can go ahead with any reads & writes.  If it's on a Lincroft,
+ * but doesn't exist, avoid the access altogether to keep the chip from
+ * hanging.
+ */
+static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
+{
+	/* This is a workaround for A0 LNC bug where PCI status register does
+	 * not have new CAP bit set. can not be written by SW either.
+	 *
+	 * PCI header type in real LNC indicates a single function device, this
+	 * will prevent probing other devices under the same function in PCI
+	 * shim. Therefore, use the header type in shim instead.
+	 */
+	if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE)
+		return 0;
+	if (bus == 0 && (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(0, 0)))
+		return 1;
+	return 0; /* langwell on others */
+}
+
+static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
+		    int size, u32 *value)
+{
+	if (type1_access_ok(bus->number, devfn, where))
+		return pci_direct_conf1.read(pci_domain_nr(bus), bus->number,
+					devfn, where, size, value);
+	return raw_pci_ext_ops->read(pci_domain_nr(bus), bus->number,
+			      devfn, where, size, value);
+}
+
+static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
+		     int size, u32 value)
+{
+	int offset;
+
+	/* On MRST, there is no PCI ROM BAR, this will cause a subsequent read
+	 * to ROM BAR return 0 then being ignored.
+	 */
+	if (where == PCI_ROM_ADDRESS)
+		return 0;
+
+	/*
+	 * Devices with fixed BARs need special handling:
+	 *   - BAR sizing code will save, write ~0, read size, restore
+	 *   - so writes to fixed BARs need special handling
+	 *   - other writes to fixed BAR devices should go through mmconfig
+	 */
+	offset = fixed_bar_cap(bus, devfn);
+	if (offset &&
+	    (where >= PCI_BASE_ADDRESS_0 && where <= PCI_BASE_ADDRESS_5)) {
+		return pci_device_update_fixed(bus, devfn, where, size, value,
+					       offset);
+	}
+
+	/*
+	 * On Moorestown update both real & mmconfig space
+	 * Note: early Lincroft silicon can't handle type 1 accesses to
+	 *       non-existent devices, so just eat the write in that case.
+	 */
+	if (type1_access_ok(bus->number, devfn, where))
+		return pci_direct_conf1.write(pci_domain_nr(bus), bus->number,
+					      devfn, where, size, value);
+	return raw_pci_ext_ops->write(pci_domain_nr(bus), bus->number, devfn,
+			       where, size, value);
+}
+
+static int mrst_pci_irq_enable(struct pci_dev *dev)
+{
+	u8 pin;
+	struct io_apic_irq_attr irq_attr;
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+
+	/* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
+	 * IOAPIC RTE entries, so we just enable RTE for the device.
+	 */
+	irq_attr.ioapic = mp_find_ioapic(dev->irq);
+	irq_attr.ioapic_pin = dev->irq;
+	irq_attr.trigger = 1; /* level */
+	irq_attr.polarity = 1; /* active low */
+	io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr);
+
+	return 0;
+}
+
+struct pci_ops pci_mrst_ops = {
+	.read = pci_read,
+	.write = pci_write,
+};
+
+/**
+ * pci_mrst_init - installs pci_mrst_ops
+ *
+ * Moorestown has an interesting PCI implementation (see above).
+ * Called when the early platform detection installs it.
+ */
+int __init pci_mrst_init(void)
+{
+	printk(KERN_INFO "Moorestown platform detected, using MRST PCI ops\n");
+	pci_mmcfg_late_init();
+	pcibios_enable_irq = mrst_pci_irq_enable;
+	pci_root_ops = pci_mrst_ops;
+	/* Continue with standard init */
+	return 1;
+}
+
+/*
+ * Langwell devices reside at fixed offsets, don't try to move them.
+ */
+static void __devinit pci_fixed_bar_fixup(struct pci_dev *dev)
+{
+	unsigned long offset;
+	u32 size;
+	int i;
+
+	/* Fixup the BAR sizes for fixed BAR devices and make them unmoveable */
+	offset = fixed_bar_cap(dev->bus, dev->devfn);
+	if (!offset || PCI_DEVFN(2, 0) == dev->devfn ||
+	    PCI_DEVFN(2, 2) == dev->devfn)
+		return;
+
+	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+		pci_read_config_dword(dev, offset + 8 + (i * 4), &size);
+		dev->resource[i].end = dev->resource[i].start + size - 1;
+		dev->resource[i].flags |= IORESOURCE_PCI_FIXED;
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixed_bar_fixup);
diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c
index 8884a1c..8223738 100644
--- a/arch/x86/pci/numaq_32.c
+++ b/arch/x86/pci/numaq_32.c
@@ -148,14 +148,8 @@
 {
 	int quad;
 
-	if (!found_numaq)
-		return 0;
-
 	raw_pci_ops = &pci_direct_conf1_mq;
 
-	if (pcibios_scanned++)
-		return 0;
-
 	pci_root_bus = pcibios_scan_root(0);
 	if (pci_root_bus)
 		pci_bus_add_devices(pci_root_bus);
diff --git a/arch/x86/pci/olpc.c b/arch/x86/pci/olpc.c
index b889d82..b348154 100644
--- a/arch/x86/pci/olpc.c
+++ b/arch/x86/pci/olpc.c
@@ -304,9 +304,6 @@
 
 int __init pci_olpc_init(void)
 {
-	if (!machine_is_olpc() || olpc_has_vsa())
-		return -ENODEV;
-
 	printk(KERN_INFO "PCI: Using configuration type OLPC\n");
 	raw_pci_ops = &pci_olpc_conf;
 	is_lx = is_geode_lx();
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c
index bcead7a..03008f7 100644
--- a/arch/x86/pci/visws.c
+++ b/arch/x86/pci/visws.c
@@ -69,9 +69,6 @@
 
 int __init pci_visws_init(void)
 {
-	if (!is_visws_box())
-		return -1;
-
 	pcibios_enable_irq = &pci_visws_enable_irq;
 	pcibios_disable_irq = &pci_visws_disable_irq;
 
@@ -90,5 +87,6 @@
 	pci_scan_bus_with_sysdata(pci_bus1);
 	pci_fixup_irqs(pci_common_swizzle, visws_map_irq);
 	pcibios_resource_survey();
-	return 0;
+	/* Request bus scan */
+	return 1;
 }
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 36daccb..b607239 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -50,6 +50,7 @@
 #include <asm/traps.h>
 #include <asm/setup.h>
 #include <asm/desc.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 #include <asm/reboot.h>
@@ -1094,6 +1095,12 @@
 
 	__supported_pte_mask |= _PAGE_IOMAP;
 
+	/*
+	 * Prevent page tables from being allocated in highmem, even
+	 * if CONFIG_HIGHPTE is enabled.
+	 */
+	__userpte_alloc_gfp &= ~__GFP_HIGHMEM;
+
 	/* Work out if we support NX */
 	x86_configure_nx();
 
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index bf4cd6b..f9eb7de 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1427,23 +1427,6 @@
 #endif
 }
 
-#ifdef CONFIG_HIGHPTE
-static void *xen_kmap_atomic_pte(struct page *page, enum km_type type)
-{
-	pgprot_t prot = PAGE_KERNEL;
-
-	if (PagePinned(page))
-		prot = PAGE_KERNEL_RO;
-
-	if (0 && PageHighMem(page))
-		printk("mapping highpte %lx type %d prot %s\n",
-		       page_to_pfn(page), type,
-		       (unsigned long)pgprot_val(prot) & _PAGE_RW ? "WRITE" : "READ");
-
-	return kmap_atomic_prot(page, type, prot);
-}
-#endif
-
 #ifdef CONFIG_X86_32
 static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
 {
@@ -1902,10 +1885,6 @@
 	.alloc_pmd_clone = paravirt_nop,
 	.release_pmd = xen_release_pmd_init,
 
-#ifdef CONFIG_HIGHPTE
-	.kmap_atomic_pte = xen_kmap_atomic_pte,
-#endif
-
 #ifdef CONFIG_X86_64
 	.set_pte = xen_set_pte,
 #else
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 563d205..deafb65 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -361,7 +361,7 @@
 		alternatives_smp_switch(0);
 }
 
-static void __cpuinit xen_play_dead(void) /* used only with CPU_HOTPLUG */
+static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */
 {
 	play_dead_common();
 	HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S
index 88e15de..22a2093 100644
--- a/arch/x86/xen/xen-asm_32.S
+++ b/arch/x86/xen/xen-asm_32.S
@@ -90,9 +90,9 @@
 	GET_THREAD_INFO(%eax)
 	movl TI_cpu(%eax), %eax
 	movl __per_cpu_offset(,%eax,4), %eax
-	mov per_cpu__xen_vcpu(%eax), %eax
+	mov xen_vcpu(%eax), %eax
 #else
-	movl per_cpu__xen_vcpu, %eax
+	movl xen_vcpu, %eax
 #endif
 
 	/* check IF state we're restoring */
diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h
index 66410ac..4609b0f 100644
--- a/arch/xtensa/include/asm/pci.h
+++ b/arch/xtensa/include/asm/pci.h
@@ -56,14 +56,6 @@
 
 #define PCI_DMA_BUS_IS_PHYS	(1)
 
-/* pci_unmap_{page,single} is a no-op, so */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
-#define pci_ubnmap_len(PTR, LEN_NAME)		(0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
-
 /* Map a range of PCI memory or I/O space for a device into user space */
 int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
                         enum pci_mmap_state mmap_state, int write_combine);
diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h
index 905e1e6..3c549f7 100644
--- a/arch/xtensa/include/asm/ptrace.h
+++ b/arch/xtensa/include/asm/ptrace.h
@@ -113,6 +113,7 @@
 
 #include <variant/core.h>
 
+# define arch_has_single_step()	(1)
 # define task_pt_regs(tsk) ((struct pt_regs*) \
   (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
 # define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 80d24c4..77fc9f6 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -104,7 +104,7 @@
  *   excsave has been restored, and
  *   stack pointer (a1) has been set.
  *
- * Note: _user_exception might be at an odd adress. Don't use call0..call12
+ * Note: _user_exception might be at an odd address. Don't use call0..call12
  */
 
 ENTRY(user_exception)
@@ -244,7 +244,7 @@
  *   excsave has been restored, and
  *   stack pointer (a1) has been set.
  *
- * Note: _kernel_exception might be at an odd adress. Don't use call0..call12
+ * Note: _kernel_exception might be at an odd address. Don't use call0..call12
  */
 
 ENTRY(kernel_exception)
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 9486882..9d4e1ce 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -30,6 +30,17 @@
 #include <asm/elf.h>
 #include <asm/coprocessor.h>
 
+
+void user_enable_single_step(struct task_struct *child)
+{
+	child->ptrace |= PT_SINGLESTEP;
+}
+
+void user_disable_single_step(struct task_struct *child)
+{
+	child->ptrace &= ~PT_SINGLESTEP;
+}
+
 /*
  * Called by kernel/ptrace.c when detaching to disable single stepping.
  */
@@ -268,51 +279,6 @@
 		ret = ptrace_pokeusr(child, addr, data);
 		break;
 
-	/* continue and stop at next (return from) syscall */
-
-	case PTRACE_SYSCALL:
-	case PTRACE_CONT: /* restart after signal. */
-	{
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		if (request == PTRACE_SYSCALL)
-			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		else
-			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->exit_code = data;
-		/* Make sure the single step bit is not set. */
-		child->ptrace &= ~PT_SINGLESTEP;
-		wake_up_process(child);
-		ret = 0;
-		break;
-	}
-
-	/*
-	 * make the child exit.  Best I can do is send it a sigkill.
-	 * perhaps it should be put in the status that it wants to
-	 * exit.
-	 */
-	case PTRACE_KILL:
-		ret = 0;
-		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
-			break;
-		child->exit_code = SIGKILL;
-		child->ptrace &= ~PT_SINGLESTEP;
-		wake_up_process(child);
-		break;
-
-	case PTRACE_SINGLESTEP:
-		ret = -EIO;
-		if (!valid_signal(data))
-			break;
-		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
-		child->ptrace |= PT_SINGLESTEP;
-		child->exit_code = data;
-		wake_up_process(child);
-		ret = 0;
-		break;
-
 	case PTRACE_GETREGS:
 		ret = ptrace_getregs(child, (void __user *) data);
 		break;
diff --git a/block/Kconfig b/block/Kconfig
index e20fbde..62a5921 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -78,7 +78,7 @@
 	Protection.  If in doubt, say N.
 
 config BLK_CGROUP
-	bool
+	tristate
 	depends on CGROUPS
 	default n
 	---help---
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched
index b71abfb..fc71cf07 100644
--- a/block/Kconfig.iosched
+++ b/block/Kconfig.iosched
@@ -23,6 +23,7 @@
 
 config IOSCHED_CFQ
 	tristate "CFQ I/O scheduler"
+	select BLK_CGROUP if CFQ_GROUP_IOSCHED
 	default y
 	---help---
 	  The CFQ I/O scheduler tries to distribute bandwidth equally
@@ -35,7 +36,6 @@
 config CFQ_GROUP_IOSCHED
 	bool "CFQ Group Scheduling support"
 	depends on IOSCHED_CFQ && CGROUPS
-	select BLK_CGROUP
 	default n
 	---help---
 	  Enable group IO scheduling in CFQ.
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index c85d74c..4b686ad 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -23,6 +23,31 @@
 struct blkio_cgroup blkio_root_cgroup = { .weight = 2*BLKIO_WEIGHT_DEFAULT };
 EXPORT_SYMBOL_GPL(blkio_root_cgroup);
 
+static struct cgroup_subsys_state *blkiocg_create(struct cgroup_subsys *,
+						  struct cgroup *);
+static int blkiocg_can_attach(struct cgroup_subsys *, struct cgroup *,
+			      struct task_struct *, bool);
+static void blkiocg_attach(struct cgroup_subsys *, struct cgroup *,
+			   struct cgroup *, struct task_struct *, bool);
+static void blkiocg_destroy(struct cgroup_subsys *, struct cgroup *);
+static int blkiocg_populate(struct cgroup_subsys *, struct cgroup *);
+
+struct cgroup_subsys blkio_subsys = {
+	.name = "blkio",
+	.create = blkiocg_create,
+	.can_attach = blkiocg_can_attach,
+	.attach = blkiocg_attach,
+	.destroy = blkiocg_destroy,
+	.populate = blkiocg_populate,
+#ifdef CONFIG_BLK_CGROUP
+	/* note: blkio_subsys_id is otherwise defined in blk-cgroup.h */
+	.subsys_id = blkio_subsys_id,
+#endif
+	.use_id = 1,
+	.module = THIS_MODULE,
+};
+EXPORT_SYMBOL_GPL(blkio_subsys);
+
 struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup)
 {
 	return container_of(cgroup_subsys_state(cgroup, blkio_subsys_id),
@@ -253,7 +278,8 @@
 done:
 	free_css_id(&blkio_subsys, &blkcg->css);
 	rcu_read_unlock();
-	kfree(blkcg);
+	if (blkcg != &blkio_root_cgroup)
+		kfree(blkcg);
 }
 
 static struct cgroup_subsys_state *
@@ -319,17 +345,6 @@
 	task_unlock(tsk);
 }
 
-struct cgroup_subsys blkio_subsys = {
-	.name = "blkio",
-	.create = blkiocg_create,
-	.can_attach = blkiocg_can_attach,
-	.attach = blkiocg_attach,
-	.destroy = blkiocg_destroy,
-	.populate = blkiocg_populate,
-	.subsys_id = blkio_subsys_id,
-	.use_id = 1,
-};
-
 void blkio_policy_register(struct blkio_policy_type *blkiop)
 {
 	spin_lock(&blkio_list_lock);
@@ -345,3 +360,17 @@
 	spin_unlock(&blkio_list_lock);
 }
 EXPORT_SYMBOL_GPL(blkio_policy_unregister);
+
+static int __init init_cgroup_blkio(void)
+{
+	return cgroup_load_subsys(&blkio_subsys);
+}
+
+static void __exit exit_cgroup_blkio(void)
+{
+	cgroup_unload_subsys(&blkio_subsys);
+}
+
+module_init(init_cgroup_blkio);
+module_exit(exit_cgroup_blkio);
+MODULE_LICENSE("GPL");
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 84bf745..8ccc204 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -15,7 +15,13 @@
 
 #include <linux/cgroup.h>
 
-#ifdef CONFIG_BLK_CGROUP
+#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
+
+#ifndef CONFIG_BLK_CGROUP
+/* When blk-cgroup is a module, its subsys_id isn't a compile-time constant */
+extern struct cgroup_subsys blkio_subsys;
+#define blkio_subsys_id blkio_subsys.subsys_id
+#endif
 
 struct blkio_cgroup {
 	struct cgroup_subsys_state css;
@@ -91,7 +97,7 @@
 			struct blkio_group *blkg, unsigned long dequeue) {}
 #endif
 
-#ifdef CONFIG_BLK_CGROUP
+#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
 extern struct blkio_cgroup blkio_root_cgroup;
 extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
 extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index 15c6308..96e83c2 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -278,7 +278,7 @@
 	NULL,
 };
 
-static struct sysfs_ops integrity_ops = {
+static const struct sysfs_ops integrity_ops = {
 	.show	= &integrity_attr_show,
 	.store	= &integrity_attr_store,
 };
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index e854424..2ae2cb3 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -450,7 +450,7 @@
 	kmem_cache_free(blk_requestq_cachep, q);
 }
 
-static struct sysfs_ops queue_sysfs_ops = {
+static const struct sysfs_ops queue_sysfs_ops = {
 	.show	= queue_attr_show,
 	.store	= queue_attr_store,
 };
diff --git a/block/bsg.c b/block/bsg.c
index a9fd2d8..46597a6 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -260,7 +260,7 @@
 		return ERR_PTR(ret);
 
 	/*
-	 * map scatter-gather elements seperately and string them to request
+	 * map scatter-gather elements separately and string them to request
 	 */
 	rq = blk_get_request(q, rw, GFP_KERNEL);
 	if (!rq)
diff --git a/block/elevator.c b/block/elevator.c
index ee3a883..df75676 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -892,7 +892,7 @@
 	return error;
 }
 
-static struct sysfs_ops elv_sysfs_ops = {
+static const struct sysfs_ops elv_sysfs_ops = {
 	.show	= elv_attr_show,
 	.store	= elv_attr_store,
 };
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 6a2e295..403857a 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -826,8 +826,8 @@
 	help
 	  This option enables the generic pseudo random number generator
 	  for cryptographic modules.  Uses the Algorithm specified in
-	  ANSI X9.31 A.2.4. Not this option must be enabled if CRYPTO_FIPS 
-	  is selected
+	  ANSI X9.31 A.2.4. Note that this option must be enabled if
+	  CRYPTO_FIPS is selected
 
 source "drivers/crypto/Kconfig"
 
diff --git a/crypto/ahash.c b/crypto/ahash.c
index 33a4ff4..b8c59b8 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -78,7 +78,6 @@
 	walk->data -= walk->offset;
 
 	if (nbytes && walk->offset & alignmask && !err) {
-		walk->offset += alignmask - 1;
 		walk->offset = ALIGN(walk->offset, alignmask + 1);
 		walk->data += walk->offset;
 
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 1887090..2bb7348 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -386,11 +386,13 @@
 {
 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-	struct ablkcipher_request *abreq = aead_request_ctx(req);
+	struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
 	struct crypto_ablkcipher *enc = ctx->enc;
 	struct scatterlist *dst = req->dst;
 	unsigned int cryptlen = req->cryptlen;
-	u8 *iv = (u8 *)(abreq + 1) + crypto_ablkcipher_reqsize(enc);
+	struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
+						    + ctx->reqoff);
+	u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc);
 	int err;
 
 	ablkcipher_request_set_tfm(abreq, enc);
@@ -454,7 +456,7 @@
 	unsigned int authsize;
 
 	areq_ctx->complete = authenc_verify_ahash_done;
-	areq_ctx->complete = authenc_verify_ahash_update_done;
+	areq_ctx->update_complete = authenc_verify_ahash_update_done;
 
 	ohash = authenc_ahash_fn(req, CRYPTO_TFM_REQ_MAY_SLEEP);
 	if (IS_ERR(ohash))
@@ -546,10 +548,6 @@
 	if (IS_ERR(auth))
 		return PTR_ERR(auth);
 
-	ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) +
-			    crypto_ahash_alignmask(auth),
-			    crypto_ahash_alignmask(auth) + 1);
-
 	enc = crypto_spawn_skcipher(&ictx->enc);
 	err = PTR_ERR(enc);
 	if (IS_ERR(enc))
@@ -558,13 +556,18 @@
 	ctx->auth = auth;
 	ctx->enc = enc;
 
-	tfm->crt_aead.reqsize = max_t(unsigned int,
-				crypto_ahash_reqsize(auth) + ctx->reqoff +
-				sizeof(struct authenc_request_ctx) +
+	ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) +
+			    crypto_ahash_alignmask(auth),
+			    crypto_ahash_alignmask(auth) + 1) +
+		      crypto_ablkcipher_ivsize(enc);
+
+	tfm->crt_aead.reqsize = sizeof(struct authenc_request_ctx) +
+				ctx->reqoff +
+				max_t(unsigned int,
+				crypto_ahash_reqsize(auth) +
 				sizeof(struct ahash_request),
 				sizeof(struct skcipher_givcrypt_request) +
-				crypto_ablkcipher_reqsize(enc) +
-				crypto_ablkcipher_ivsize(enc));
+				crypto_ablkcipher_reqsize(enc));
 
 	return 0;
 
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 704c141..ef71318 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -31,7 +31,7 @@
 };
 
 struct cryptd_queue {
-	struct cryptd_cpu_queue *cpu_queue;
+	struct cryptd_cpu_queue __percpu *cpu_queue;
 };
 
 struct cryptd_instance_ctx {
diff --git a/crypto/md5.c b/crypto/md5.c
index 9fda213..30efc7d 100644
--- a/crypto/md5.c
+++ b/crypto/md5.c
@@ -234,6 +234,7 @@
 	.export		=	md5_export,
 	.import		=	md5_import,
 	.descsize	=	sizeof(struct md5_state),
+	.statesize	=	sizeof(struct md5_state),
 	.base		=	{
 		.cra_name	=	"md5",
 		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 368ae6d..a2b902f 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -96,8 +96,6 @@
 
 source "drivers/rtc/Kconfig"
 
-source "drivers/clocksource/Kconfig"
-
 source "drivers/dma/Kconfig"
 
 source "drivers/dca/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 81e3659..34f1e10 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -99,6 +99,7 @@
 obj-y				+= firmware/
 obj-$(CONFIG_CRYPTO)		+= crypto/
 obj-$(CONFIG_SUPERH)		+= sh/
+obj-$(CONFIG_ARCH_SHMOBILE)	+= sh/
 obj-$(CONFIG_GENERIC_TIME)	+= clocksource/
 obj-$(CONFIG_DMA_ENGINE)	+= dma/
 obj-$(CONFIG_DCA)		+= dca/
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index b2586f5..d9a85f1 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -605,7 +605,7 @@
 	list_for_each_entry(dock_station, &dock_stations, sibling) {
 		/*
 		 * An ATA bay can be in a dock and itself can be ejected
-		 * seperately, so there are two 'dock stations' which need the
+		 * separately, so there are two 'dock stations' which need the
 		 * ops
 		 */
 		dd = find_dock_dependent_device(dock_station, handle);
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 7ad48df..b872546 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -279,9 +279,9 @@
 	/* 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_CPUS);
+				     acpi_parse_x2apic_affinity, nr_cpu_ids);
 		acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
-				      acpi_parse_processor_affinity, NR_CPUS);
+				     acpi_parse_processor_affinity, nr_cpu_ids);
 		ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
 					    acpi_parse_memory_affinity,
 					    NR_NODE_MEMBLKS);
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index d0d25e2..1ac678d 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -435,7 +435,7 @@
 				found_dev->wakeup.gpe_device)) {
 				printk(KERN_WARNING
 				       "ACPI: '%s' and '%s' have the same GPE, "
-				       "can't disable/enable one seperately\n",
+				       "can't disable/enable one separately\n",
 				       dev->pnp.bus_id, found_dev->pnp.bus_id);
 				dev->wakeup.state.enabled =
 				    found_dev->wakeup.state.enabled;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 9863c98..e9b7b40 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -123,6 +123,8 @@
 #endif
 
 DEFINE_PER_CPU(struct acpi_processor *, processors);
+EXPORT_PER_CPU_SYMBOL(processors);
+
 struct acpi_processor_errata errata __read_mostly;
 
 /* --------------------------------------------------------------------------
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index a959f6a..d648a98 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -561,7 +561,7 @@
 }
 
 int acpi_processor_preregister_performance(
-		struct acpi_processor_performance *performance)
+		struct acpi_processor_performance __percpu *performance)
 {
 	int count, count_target;
 	int retval = 0;
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index a206a12..743f244 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -101,6 +101,7 @@
 	struct acpi_table_header *header = NULL;
 	struct acpi_table_attr *attr = NULL;
 
+	sysfs_attr_init(&table_attr->attr.attr);
 	if (table_header->signature[0] != '\0')
 		memcpy(table_attr->name, table_header->signature,
 			ACPI_NAME_SIZE);
@@ -475,6 +476,7 @@
 			goto fail;
 		strncpy(name, buffer, strlen(buffer) + 1);
 
+		sysfs_attr_init(&counter_attrs[i].attr);
 		counter_attrs[i].attr.name = name;
 		counter_attrs[i].attr.mode = 0644;
 		counter_attrs[i].show = counter_show;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 9c77b0d..4a28420 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2232,7 +2232,7 @@
 		 * Some drives were very specific about that exact sequence.
 		 *
 		 * Note that ATA4 says lba is mandatory so the second check
-		 * shoud never trigger.
+		 * should never trigger.
 		 */
 		if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
 			err_mask = ata_dev_init_params(dev, id[3], id[6]);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 02441fd5..561dec2 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -2287,7 +2287,7 @@
  *	@qc: command
  *
  *	Drain the FIFO and device of any stuck data following a command
- *	failing to complete. In some cases this is neccessary before a
+ *	failing to complete. In some cases this is necessary before a
  *	reset will recover the device.
  *
  */
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index 294f302..8e5e132 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -161,7 +161,7 @@
  *
  *	Called when the libata layer is about to issue a command. We wrap
  *	this interface so that we can load the correct ATA timings if
- *	neccessary.
+ *	necessary.
  */
 
 static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc)
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index c86c716..727a81c 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -180,7 +180,7 @@
  *	@id: Entry in match table
  *
  *	Perform basic initialisation. We set the device up so we access all
- *	ports via BAR4. This is neccessary to work around errata.
+ *	ports via BAR4. This is necessary to work around errata.
  */
 
 static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 3610353..147de2f 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -131,7 +131,7 @@
  *	@qc: command
  *
  *	Drain the FIFO and device of any stuck data following a command
- *	failing to complete. In some cases this is neccessary before a
+ *	failing to complete. In some cases this is necessary before a
  *	reset will recover the device.
  *
  */
diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c
index fe3a865..b0ca5a47 100644
--- a/drivers/auxdisplay/cfag12864bfb.c
+++ b/drivers/auxdisplay/cfag12864bfb.c
@@ -81,7 +81,7 @@
 	.fb_mmap = cfag12864bfb_mmap,
 };
 
-static int __init cfag12864bfb_probe(struct platform_device *device)
+static int __devinit cfag12864bfb_probe(struct platform_device *device)
 {
 	int ret = -EINVAL;
  	struct fb_info *info = framebuffer_alloc(0, &device->dev);
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index ee37727..fd52c48 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -3,35 +3,50 @@
 config UEVENT_HELPER_PATH
 	string "path to uevent helper"
 	depends on HOTPLUG
-	default "/sbin/hotplug"
+	default ""
 	help
 	  Path to uevent helper program forked by the kernel for
 	  every uevent.
+	  Before the switch to the netlink-based uevent source, this was
+	  used to hook hotplug scripts into kernel device events. It
+	  usually pointed to a shell script at /sbin/hotplug.
+	  This should not be used today, because usual systems create
+	  many events at bootup or device discovery in a very short time
+	  frame. One forked process per event can create so many processes
+	  that it creates a high system load, or on smaller systems
+	  it is known to create out-of-memory situations during bootup.
 
 config DEVTMPFS
-	bool "Create a kernel maintained /dev tmpfs (EXPERIMENTAL)"
+	bool "Maintain a devtmpfs filesystem to mount at /dev"
 	depends on HOTPLUG && SHMEM && TMPFS
 	help
-	  This creates a tmpfs filesystem, and mounts it at bootup
-	  and mounts it at /dev. The kernel driver core creates device
-	  nodes for all registered devices in that filesystem. All device
-	  nodes are owned by root and have the default mode of 0600.
-	  Userspace can add and delete the nodes as needed. This is
-	  intended to simplify bootup, and make it possible to delay
-	  the initial coldplug at bootup done by udev in userspace.
-	  It should also provide a simpler way for rescue systems
-	  to bring up a kernel with dynamic major/minor numbers.
-	  Meaningful symlinks, permissions and device ownership must
-	  still be handled by userspace.
-	  If unsure, say N here.
+	  This creates a tmpfs filesystem instance early at bootup.
+	  In this filesystem, the kernel driver core maintains device
+	  nodes with their default names and permissions for all
+	  registered devices with an assigned major/minor number.
+	  Userspace can modify the filesystem content as needed, add
+	  symlinks, and apply needed permissions.
+	  It provides a fully functional /dev directory, where usually
+	  udev runs on top, managing permissions and adding meaningful
+	  symlinks.
+	  In very limited environments, it may provide a sufficient
+	  functional /dev without any further help. It also allows simple
+	  rescue systems, and reliably handles dynamic major/minor numbers.
 
 config DEVTMPFS_MOUNT
-	bool "Automount devtmpfs at /dev"
+	bool "Automount devtmpfs at /dev, after the kernel mounted the rootfs"
 	depends on DEVTMPFS
 	help
-	  This will mount devtmpfs at /dev if the kernel mounts the root
-	  filesystem. It will not affect initramfs based mounting.
-	  If unsure, say N here.
+	  This will instruct the kernel to automatically mount the
+	  devtmpfs filesystem at /dev, directly after the kernel has
+	  mounted the root filesystem. The behavior can be overridden
+	  with the commandline parameter: devtmpfs.mount=0|1.
+	  This option does not affect initramfs based booting, here
+	  the devtmpfs filesystem always needs to be mounted manually
+	  after the roots is mounted.
+	  With this option enabled, it allows to bring up a system in
+	  rescue mode with init=/bin/sh, even when the /dev directory
+	  on the rootfs is completely empty.
 
 config STANDALONE
 	bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index c0c5a43..71f6af5 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -70,7 +70,7 @@
 	return ret;
 }
 
-static struct sysfs_ops driver_sysfs_ops = {
+static const struct sysfs_ops driver_sysfs_ops = {
 	.show	= drv_attr_show,
 	.store	= drv_attr_store,
 };
@@ -115,7 +115,7 @@
 	return ret;
 }
 
-static struct sysfs_ops bus_sysfs_ops = {
+static const struct sysfs_ops bus_sysfs_ops = {
 	.show	= bus_attr_show,
 	.store	= bus_attr_store,
 };
@@ -154,7 +154,7 @@
 	return 0;
 }
 
-static struct kset_uevent_ops bus_uevent_ops = {
+static const struct kset_uevent_ops bus_uevent_ops = {
 	.filter = bus_uevent_filter,
 };
 
@@ -173,10 +173,10 @@
 	dev = bus_find_device_by_name(bus, NULL, buf);
 	if (dev && dev->driver == drv) {
 		if (dev->parent)	/* Needed for USB */
-			down(&dev->parent->sem);
+			device_lock(dev->parent);
 		device_release_driver(dev);
 		if (dev->parent)
-			up(&dev->parent->sem);
+			device_unlock(dev->parent);
 		err = count;
 	}
 	put_device(dev);
@@ -200,12 +200,12 @@
 	dev = bus_find_device_by_name(bus, NULL, buf);
 	if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
 		if (dev->parent)	/* Needed for USB */
-			down(&dev->parent->sem);
-		down(&dev->sem);
+			device_lock(dev->parent);
+		device_lock(dev);
 		err = driver_probe_device(drv, dev);
-		up(&dev->sem);
+		device_unlock(dev);
 		if (dev->parent)
-			up(&dev->parent->sem);
+			device_unlock(dev->parent);
 
 		if (err > 0) {
 			/* success */
@@ -744,10 +744,10 @@
 
 	if (!dev->driver) {
 		if (dev->parent)	/* Needed for USB */
-			down(&dev->parent->sem);
+			device_lock(dev->parent);
 		ret = device_attach(dev);
 		if (dev->parent)
-			up(&dev->parent->sem);
+			device_unlock(dev->parent);
 	}
 	return ret < 0 ? ret : 0;
 }
@@ -779,10 +779,10 @@
 {
 	if (dev->driver) {
 		if (dev->parent)        /* Needed for USB */
-			down(&dev->parent->sem);
+			device_lock(dev->parent);
 		device_release_driver(dev);
 		if (dev->parent)
-			up(&dev->parent->sem);
+			device_unlock(dev->parent);
 	}
 	return bus_rescan_devices_helper(dev, NULL);
 }
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 6e2c3b0..0147f47 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -31,7 +31,7 @@
 	ssize_t ret = -EIO;
 
 	if (class_attr->show)
-		ret = class_attr->show(cp->class, buf);
+		ret = class_attr->show(cp->class, class_attr, buf);
 	return ret;
 }
 
@@ -43,7 +43,7 @@
 	ssize_t ret = -EIO;
 
 	if (class_attr->store)
-		ret = class_attr->store(cp->class, buf, count);
+		ret = class_attr->store(cp->class, class_attr, buf, count);
 	return ret;
 }
 
@@ -63,7 +63,7 @@
 	kfree(cp);
 }
 
-static struct sysfs_ops class_sysfs_ops = {
+static const struct sysfs_ops class_sysfs_ops = {
 	.show	= class_attr_show,
 	.store	= class_attr_store,
 };
@@ -490,6 +490,16 @@
 	class_put(parent);
 }
 
+ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr,
+                        	char *buf)
+{
+	struct class_attribute_string *cs;
+	cs = container_of(attr, struct class_attribute_string, attr);
+	return snprintf(buf, PAGE_SIZE, "%s\n", cs->str);
+}
+
+EXPORT_SYMBOL_GPL(show_class_attr_string);
+
 struct class_compat {
 	struct kobject *kobj;
 };
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 2820257..ef55df3 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -100,7 +100,7 @@
 	return ret;
 }
 
-static struct sysfs_ops dev_sysfs_ops = {
+static const struct sysfs_ops dev_sysfs_ops = {
 	.show	= dev_attr_show,
 	.store	= dev_attr_store,
 };
@@ -252,7 +252,7 @@
 	return retval;
 }
 
-static struct kset_uevent_ops device_uevent_ops = {
+static const struct kset_uevent_ops device_uevent_ops = {
 	.filter =	dev_uevent_filter,
 	.name =		dev_uevent_name,
 	.uevent =	dev_uevent,
@@ -306,15 +306,10 @@
 {
 	enum kobject_action action;
 
-	if (kobject_action_type(buf, count, &action) == 0) {
+	if (kobject_action_type(buf, count, &action) == 0)
 		kobject_uevent(&dev->kobj, action);
-		goto out;
-	}
-
-	dev_err(dev, "uevent: unsupported action-string; this will "
-		     "be ignored in a future kernel version\n");
-	kobject_uevent(&dev->kobj, KOBJ_ADD);
-out:
+	else
+		dev_err(dev, "uevent: unknown action-string\n");
 	return count;
 }
 
@@ -607,6 +602,7 @@
 	int retval;
 
 	if (dev->class) {
+		static DEFINE_MUTEX(gdp_mutex);
 		struct kobject *kobj = NULL;
 		struct kobject *parent_kobj;
 		struct kobject *k;
@@ -623,6 +619,8 @@
 		else
 			parent_kobj = &parent->kobj;
 
+		mutex_lock(&gdp_mutex);
+
 		/* find our class-directory at the parent and reference it */
 		spin_lock(&dev->class->p->class_dirs.list_lock);
 		list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
@@ -631,20 +629,26 @@
 				break;
 			}
 		spin_unlock(&dev->class->p->class_dirs.list_lock);
-		if (kobj)
+		if (kobj) {
+			mutex_unlock(&gdp_mutex);
 			return kobj;
+		}
 
 		/* or create a new class-directory at the parent device */
 		k = kobject_create();
-		if (!k)
+		if (!k) {
+			mutex_unlock(&gdp_mutex);
 			return NULL;
+		}
 		k->kset = &dev->class->p->class_dirs;
 		retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
 		if (retval < 0) {
+			mutex_unlock(&gdp_mutex);
 			kobject_put(k);
 			return NULL;
 		}
 		/* do not emit an uevent for this simple "glue" directory */
+		mutex_unlock(&gdp_mutex);
 		return k;
 	}
 
@@ -1574,22 +1578,16 @@
 	if (old_class_name) {
 		new_class_name = make_class_name(dev->class->name, &dev->kobj);
 		if (new_class_name) {
-			error = sysfs_create_link_nowarn(&dev->parent->kobj,
-							 &dev->kobj,
-							 new_class_name);
-			if (error)
-				goto out;
-			sysfs_remove_link(&dev->parent->kobj, old_class_name);
+			error = sysfs_rename_link(&dev->parent->kobj,
+						  &dev->kobj,
+						  old_class_name,
+						  new_class_name);
 		}
 	}
 #else
 	if (dev->class) {
-		error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj,
-						 &dev->kobj, dev_name(dev));
-		if (error)
-			goto out;
-		sysfs_remove_link(&dev->class->p->class_subsys.kobj,
-				  old_device_name);
+		error = sysfs_rename_link(&dev->class->p->class_subsys.kobj,
+					  &dev->kobj, old_device_name, new_name);
 	}
 #endif
 
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 958bd15..7036e8e 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -13,8 +13,11 @@
 
 #include "base.h"
 
+static struct sysdev_class_attribute *cpu_sysdev_class_attrs[];
+
 struct sysdev_class cpu_sysdev_class = {
 	.name = "cpu",
+	.attrs = cpu_sysdev_class_attrs,
 };
 EXPORT_SYMBOL(cpu_sysdev_class);
 
@@ -76,34 +79,24 @@
 }
 
 #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
-static ssize_t cpu_probe_store(struct class *class, const char *buf,
+static ssize_t cpu_probe_store(struct sys_device *dev,
+				struct sysdev_attribute *attr,
+				const char *buf,
 			       size_t count)
 {
 	return arch_cpu_probe(buf, count);
 }
 
-static ssize_t cpu_release_store(struct class *class, const char *buf,
+static ssize_t cpu_release_store(struct sys_device *dev,
+				struct sysdev_attribute *attr,
+				const char *buf,
 				 size_t count)
 {
 	return arch_cpu_release(buf, count);
 }
 
-static CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
-static CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store);
-
-int __init cpu_probe_release_init(void)
-{
-	int rc;
-
-	rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
-			       &class_attr_probe.attr);
-	if (!rc)
-		rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
-				       &class_attr_release.attr);
-
-	return rc;
-}
-device_initcall(cpu_probe_release_init);
+static SYSDEV_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
+static SYSDEV_ATTR(release, S_IWUSR, NULL, cpu_release_store);
 #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
 
 #else /* ... !CONFIG_HOTPLUG_CPU */
@@ -141,31 +134,39 @@
 /*
  * Print cpu online, possible, present, and system maps
  */
-static ssize_t print_cpus_map(char *buf, const struct cpumask *map)
+
+struct cpu_attr {
+	struct sysdev_class_attribute attr;
+	const struct cpumask *const * const map;
+};
+
+static ssize_t show_cpus_attr(struct sysdev_class *class,
+			      struct sysdev_class_attribute *attr,
+			      char *buf)
 {
-	int n = cpulist_scnprintf(buf, PAGE_SIZE-2, map);
+	struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr);
+	int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *(ca->map));
 
 	buf[n++] = '\n';
 	buf[n] = '\0';
 	return n;
 }
 
-#define	print_cpus_func(type) \
-static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf)	\
-{									\
-	return print_cpus_map(buf, cpu_##type##_mask);			\
-}									\
-static struct sysdev_class_attribute attr_##type##_map = 		\
-	_SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL)
+#define _CPU_ATTR(name, map)						\
+	{ _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map }
 
-print_cpus_func(online);
-print_cpus_func(possible);
-print_cpus_func(present);
+/* Keep in sync with cpu_sysdev_class_attrs */
+static struct cpu_attr cpu_attrs[] = {
+	_CPU_ATTR(online, &cpu_online_mask),
+	_CPU_ATTR(possible, &cpu_possible_mask),
+	_CPU_ATTR(present, &cpu_present_mask),
+};
 
 /*
  * Print values for NR_CPUS and offlined cpus
  */
-static ssize_t print_cpus_kernel_max(struct sysdev_class *class, char *buf)
+static ssize_t print_cpus_kernel_max(struct sysdev_class *class,
+				     struct sysdev_class_attribute *attr, char *buf)
 {
 	int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
 	return n;
@@ -175,7 +176,8 @@
 /* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
 unsigned int total_cpus;
 
-static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf)
+static ssize_t print_cpus_offline(struct sysdev_class *class,
+				  struct sysdev_class_attribute *attr, char *buf)
 {
 	int n = 0, len = PAGE_SIZE-2;
 	cpumask_var_t offline;
@@ -204,29 +206,6 @@
 }
 static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
 
-static struct sysdev_class_attribute *cpu_state_attr[] = {
-	&attr_online_map,
-	&attr_possible_map,
-	&attr_present_map,
-	&attr_kernel_max,
-	&attr_offline,
-};
-
-static int cpu_states_init(void)
-{
-	int i;
-	int err = 0;
-
-	for (i = 0;  i < ARRAY_SIZE(cpu_state_attr); i++) {
-		int ret;
-		ret = sysdev_class_create_file(&cpu_sysdev_class,
-						cpu_state_attr[i]);
-		if (!err)
-			err = ret;
-	}
-	return err;
-}
-
 /*
  * register_cpu - Setup a sysfs device for a CPU.
  * @cpu - cpu->hotpluggable field set to 1 will generate a control file in
@@ -272,9 +251,6 @@
 	int err;
 
 	err = sysdev_class_register(&cpu_sysdev_class);
-	if (!err)
-		err = cpu_states_init();
-
 #if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
 	if (!err)
 		err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
@@ -282,3 +258,16 @@
 
 	return err;
 }
+
+static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = {
+#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+	&attr_probe,
+	&attr_release,
+#endif
+	&cpu_attrs[0].attr,
+	&cpu_attrs[1].attr,
+	&cpu_attrs[2].attr,
+	&attr_kernel_max,
+	&attr_offline,
+	NULL
+};
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index ee95c76..c89291f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -85,7 +85,7 @@
  * for before calling this. (It is ok to call with no other effort
  * from a driver's probe() method.)
  *
- * This function must be called with @dev->sem held.
+ * This function must be called with the device lock held.
  */
 int device_bind_driver(struct device *dev)
 {
@@ -190,8 +190,8 @@
  * This function returns -ENODEV if the device is not registered,
  * 1 if the device is bound successfully and 0 otherwise.
  *
- * This function must be called with @dev->sem held.  When called for a
- * USB interface, @dev->parent->sem must be held as well.
+ * This function must be called with @dev lock held.  When called for a
+ * USB interface, @dev->parent lock must be held as well.
  */
 int driver_probe_device(struct device_driver *drv, struct device *dev)
 {
@@ -233,13 +233,13 @@
  * 0 if no matching driver was found;
  * -ENODEV if the device is not registered.
  *
- * When called for a USB interface, @dev->parent->sem must be held.
+ * When called for a USB interface, @dev->parent lock must be held.
  */
 int device_attach(struct device *dev)
 {
 	int ret = 0;
 
-	down(&dev->sem);
+	device_lock(dev);
 	if (dev->driver) {
 		ret = device_bind_driver(dev);
 		if (ret == 0)
@@ -253,7 +253,7 @@
 		ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
 		pm_runtime_put_sync(dev);
 	}
-	up(&dev->sem);
+	device_unlock(dev);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(device_attach);
@@ -276,13 +276,13 @@
 		return 0;
 
 	if (dev->parent)	/* Needed for USB */
-		down(&dev->parent->sem);
-	down(&dev->sem);
+		device_lock(dev->parent);
+	device_lock(dev);
 	if (!dev->driver)
 		driver_probe_device(drv, dev);
-	up(&dev->sem);
+	device_unlock(dev);
 	if (dev->parent)
-		up(&dev->parent->sem);
+		device_unlock(dev->parent);
 
 	return 0;
 }
@@ -303,8 +303,8 @@
 EXPORT_SYMBOL_GPL(driver_attach);
 
 /*
- * __device_release_driver() must be called with @dev->sem held.
- * When called for a USB interface, @dev->parent->sem must be held as well.
+ * __device_release_driver() must be called with @dev lock held.
+ * When called for a USB interface, @dev->parent lock must be held as well.
  */
 static void __device_release_driver(struct device *dev)
 {
@@ -343,7 +343,7 @@
  * @dev: device.
  *
  * Manually detach device from driver.
- * When called for a USB interface, @dev->parent->sem must be held.
+ * When called for a USB interface, @dev->parent lock must be held.
  */
 void device_release_driver(struct device *dev)
 {
@@ -352,9 +352,9 @@
 	 * within their ->remove callback for the same device, they
 	 * will deadlock right here.
 	 */
-	down(&dev->sem);
+	device_lock(dev);
 	__device_release_driver(dev);
-	up(&dev->sem);
+	device_unlock(dev);
 }
 EXPORT_SYMBOL_GPL(device_release_driver);
 
@@ -381,13 +381,13 @@
 		spin_unlock(&drv->p->klist_devices.k_lock);
 
 		if (dev->parent)	/* Needed for USB */
-			down(&dev->parent->sem);
-		down(&dev->sem);
+			device_lock(dev->parent);
+		device_lock(dev);
 		if (dev->driver == drv)
 			__device_release_driver(dev);
-		up(&dev->sem);
+		device_unlock(dev);
 		if (dev->parent)
-			up(&dev->parent->sem);
+			device_unlock(dev->parent);
 		put_device(dev);
 	}
 }
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 42ae452..dac478c 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -301,6 +301,19 @@
 		if (dentry->d_inode) {
 			err = vfs_getattr(nd.path.mnt, dentry, &stat);
 			if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
+				struct iattr newattrs;
+				/*
+				 * before unlinking this node, reset permissions
+				 * of possible references like hardlinks
+				 */
+				newattrs.ia_uid = 0;
+				newattrs.ia_gid = 0;
+				newattrs.ia_mode = stat.mode & ~0777;
+				newattrs.ia_valid =
+					ATTR_UID|ATTR_GID|ATTR_MODE;
+				mutex_lock(&dentry->d_inode->i_mutex);
+				notify_change(dentry, &newattrs);
+				mutex_unlock(&dentry->d_inode->i_mutex);
 				err = vfs_unlink(nd.path.dentry->d_inode,
 						 dentry);
 				if (!err || err == -ENOENT)
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index a950241..d0dc26a 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -19,7 +19,6 @@
 #include <linux/kthread.h>
 #include <linux/highmem.h>
 #include <linux/firmware.h>
-#include "base.h"
 
 #define to_dev(obj) container_of(obj, struct device, kobj)
 
@@ -69,7 +68,9 @@
 }
 
 static ssize_t
-firmware_timeout_show(struct class *class, char *buf)
+firmware_timeout_show(struct class *class,
+		      struct class_attribute *attr,
+		      char *buf)
 {
 	return sprintf(buf, "%d\n", loading_timeout);
 }
@@ -87,7 +88,9 @@
  *	Note: zero means 'wait forever'.
  **/
 static ssize_t
-firmware_timeout_store(struct class *class, const char *buf, size_t count)
+firmware_timeout_store(struct class *class,
+			struct class_attribute *attr,
+			const char *buf, size_t count)
 {
 	loading_timeout = simple_strtol(buf, NULL, 10);
 	if (loading_timeout < 0)
@@ -610,7 +613,7 @@
 }
 
 /**
- * request_firmware_nowait: asynchronous version of request_firmware
+ * request_firmware_nowait - asynchronous version of request_firmware
  * @module: module requesting the firmware
  * @uevent: sends uevent to copy the firmware image if this flag
  *	is non-zero else the firmware copy must be done manually.
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index bd02505..2f86915 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -44,7 +44,7 @@
 	return retval;
 }
 
-static struct kset_uevent_ops memory_uevent_ops = {
+static const struct kset_uevent_ops memory_uevent_ops = {
 	.name		= memory_uevent_name,
 	.uevent		= memory_uevent,
 };
@@ -309,17 +309,18 @@
  * Block size attribute stuff
  */
 static ssize_t
-print_block_size(struct class *class, char *buf)
+print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr,
+		 char *buf)
 {
 	return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);
 }
 
-static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
+static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
 
 static int block_size_init(void)
 {
 	return sysfs_create_file(&memory_sysdev_class.kset.kobj,
-				&class_attr_block_size_bytes.attr);
+				&attr_block_size_bytes.attr);
 }
 
 /*
@@ -330,7 +331,8 @@
  */
 #ifdef CONFIG_ARCH_MEMORY_PROBE
 static ssize_t
-memory_probe_store(struct class *class, const char *buf, size_t count)
+memory_probe_store(struct class *class, struct class_attribute *attr,
+		   const char *buf, size_t count)
 {
 	u64 phys_addr;
 	int nid;
@@ -367,7 +369,9 @@
 
 /* Soft offline a page */
 static ssize_t
-store_soft_offline_page(struct class *class, const char *buf, size_t count)
+store_soft_offline_page(struct class *class,
+			struct class_attribute *attr,
+			const char *buf, size_t count)
 {
 	int ret;
 	u64 pfn;
@@ -384,7 +388,9 @@
 
 /* Forcibly offline a page, including killing processes. */
 static ssize_t
-store_hard_offline_page(struct class *class, const char *buf, size_t count)
+store_hard_offline_page(struct class *class,
+			struct class_attribute *attr,
+			const char *buf, size_t count)
 {
 	int ret;
 	u64 pfn;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 7012279..ad43185 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -16,8 +16,11 @@
 #include <linux/device.h>
 #include <linux/swap.h>
 
+static struct sysdev_class_attribute *node_state_attrs[];
+
 static struct sysdev_class node_class = {
 	.name = "node",
+	.attrs = node_state_attrs,
 };
 
 
@@ -544,76 +547,52 @@
 	return n;
 }
 
-static ssize_t print_nodes_possible(struct sysdev_class *class, char *buf)
-{
-	return print_nodes_state(N_POSSIBLE, buf);
-}
-
-static ssize_t print_nodes_online(struct sysdev_class *class, char *buf)
-{
-	return print_nodes_state(N_ONLINE, buf);
-}
-
-static ssize_t print_nodes_has_normal_memory(struct sysdev_class *class,
-						char *buf)
-{
-	return print_nodes_state(N_NORMAL_MEMORY, buf);
-}
-
-static ssize_t print_nodes_has_cpu(struct sysdev_class *class, char *buf)
-{
-	return print_nodes_state(N_CPU, buf);
-}
-
-static SYSDEV_CLASS_ATTR(possible, 0444, print_nodes_possible, NULL);
-static SYSDEV_CLASS_ATTR(online, 0444, print_nodes_online, NULL);
-static SYSDEV_CLASS_ATTR(has_normal_memory, 0444, print_nodes_has_normal_memory,
-									NULL);
-static SYSDEV_CLASS_ATTR(has_cpu, 0444, print_nodes_has_cpu, NULL);
-
-#ifdef CONFIG_HIGHMEM
-static ssize_t print_nodes_has_high_memory(struct sysdev_class *class,
-						 char *buf)
-{
-	return print_nodes_state(N_HIGH_MEMORY, buf);
-}
-
-static SYSDEV_CLASS_ATTR(has_high_memory, 0444, print_nodes_has_high_memory,
-									 NULL);
-#endif
-
-struct sysdev_class_attribute *node_state_attr[] = {
-	&attr_possible,
-	&attr_online,
-	&attr_has_normal_memory,
-#ifdef CONFIG_HIGHMEM
-	&attr_has_high_memory,
-#endif
-	&attr_has_cpu,
+struct node_attr {
+	struct sysdev_class_attribute attr;
+	enum node_states state;
 };
 
-static int node_states_init(void)
+static ssize_t show_node_state(struct sysdev_class *class,
+			       struct sysdev_class_attribute *attr, char *buf)
 {
-	int i;
-	int err = 0;
-
-	for (i = 0;  i < NR_NODE_STATES; i++) {
-		int ret;
-		ret = sysdev_class_create_file(&node_class, node_state_attr[i]);
-		if (!err)
-			err = ret;
-	}
-	return err;
+	struct node_attr *na = container_of(attr, struct node_attr, attr);
+	return print_nodes_state(na->state, buf);
 }
 
+#define _NODE_ATTR(name, state) \
+	{ _SYSDEV_CLASS_ATTR(name, 0444, show_node_state, NULL), state }
+
+static struct node_attr node_state_attr[] = {
+	_NODE_ATTR(possible, N_POSSIBLE),
+	_NODE_ATTR(online, N_ONLINE),
+	_NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY),
+	_NODE_ATTR(has_cpu, N_CPU),
+#ifdef CONFIG_HIGHMEM
+	_NODE_ATTR(has_high_memory, N_HIGH_MEMORY),
+#endif
+};
+
+static struct sysdev_class_attribute *node_state_attrs[] = {
+	&node_state_attr[0].attr,
+	&node_state_attr[1].attr,
+	&node_state_attr[2].attr,
+	&node_state_attr[3].attr,
+#ifdef CONFIG_HIGHMEM
+	&node_state_attr[4].attr,
+#endif
+	NULL
+};
+
 #define NODE_CALLBACK_PRI	2	/* lower than SLAB */
 static int __init register_node_type(void)
 {
 	int ret;
 
+ 	BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES);
+ 	BUILD_BUG_ON(ARRAY_SIZE(node_state_attrs)-1 != NR_NODE_STATES);
+
 	ret = sysdev_class_register(&node_class);
 	if (!ret) {
-		ret = node_states_init();
 		hotplug_memory_notifier(node_memory_callback,
 					NODE_CALLBACK_PRI);
 	}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 58efaf2..1ba9d617 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -128,7 +128,7 @@
 };
 
 /**
- * platform_device_put
+ * platform_device_put - destroy a platform device
  * @pdev: platform device to free
  *
  * Free all memory associated with a platform device.  This function must
@@ -152,7 +152,7 @@
 }
 
 /**
- * platform_device_alloc
+ * platform_device_alloc - create a platform device
  * @name: base name of the device we're adding
  * @id: instance id
  *
@@ -177,7 +177,7 @@
 EXPORT_SYMBOL_GPL(platform_device_alloc);
 
 /**
- * platform_device_add_resources
+ * platform_device_add_resources - add resources to a platform device
  * @pdev: platform device allocated by platform_device_alloc to add resources to
  * @res: set of resources that needs to be allocated for the device
  * @num: number of resources
@@ -202,7 +202,7 @@
 EXPORT_SYMBOL_GPL(platform_device_add_resources);
 
 /**
- * platform_device_add_data
+ * platform_device_add_data - add platform-specific data to a platform device
  * @pdev: platform device allocated by platform_device_alloc to add resources to
  * @data: platform specific data for this platform device
  * @size: size of platform specific data
@@ -344,7 +344,7 @@
 EXPORT_SYMBOL_GPL(platform_device_unregister);
 
 /**
- * platform_device_register_simple
+ * platform_device_register_simple - add a platform-level device and its resources
  * @name: base name of the device we're adding
  * @id: instance id
  * @res: set of resources that needs to be allocated for the device
@@ -396,7 +396,7 @@
 EXPORT_SYMBOL_GPL(platform_device_register_simple);
 
 /**
- * platform_device_register_data
+ * platform_device_register_data - add a platform-level device with platform-specific data
  * @parent: parent device for the device we're adding
  * @name: base name of the device we're adding
  * @id: instance id
@@ -473,7 +473,7 @@
 }
 
 /**
- * platform_driver_register
+ * platform_driver_register - register a driver for platform-level devices
  * @drv: platform driver structure
  */
 int platform_driver_register(struct platform_driver *drv)
@@ -491,7 +491,7 @@
 EXPORT_SYMBOL_GPL(platform_driver_register);
 
 /**
- * platform_driver_unregister
+ * platform_driver_unregister - unregister a driver for platform-level devices
  * @drv: platform driver structure
  */
 void platform_driver_unregister(struct platform_driver *drv)
@@ -548,6 +548,64 @@
 }
 EXPORT_SYMBOL_GPL(platform_driver_probe);
 
+/**
+ * platform_create_bundle - register driver and create corresponding device
+ * @driver: platform driver structure
+ * @probe: the driver probe routine, probably from an __init section
+ * @res: set of resources that needs to be allocated for the device
+ * @n_res: number of resources
+ * @data: platform specific data for this platform device
+ * @size: size of platform specific data
+ *
+ * Use this in legacy-style modules that probe hardware directly and
+ * register a single platform device and corresponding platform driver.
+ */
+struct platform_device * __init_or_module platform_create_bundle(
+			struct platform_driver *driver,
+			int (*probe)(struct platform_device *),
+			struct resource *res, unsigned int n_res,
+			const void *data, size_t size)
+{
+	struct platform_device *pdev;
+	int error;
+
+	pdev = platform_device_alloc(driver->driver.name, -1);
+	if (!pdev) {
+		error = -ENOMEM;
+		goto err_out;
+	}
+
+	if (res) {
+		error = platform_device_add_resources(pdev, res, n_res);
+		if (error)
+			goto err_pdev_put;
+	}
+
+	if (data) {
+		error = platform_device_add_data(pdev, data, size);
+		if (error)
+			goto err_pdev_put;
+	}
+
+	error = platform_device_add(pdev);
+	if (error)
+		goto err_pdev_put;
+
+	error = platform_driver_probe(driver, probe);
+	if (error)
+		goto err_pdev_del;
+
+	return pdev;
+
+err_pdev_del:
+	platform_device_del(pdev);
+err_pdev_put:
+	platform_device_put(pdev);
+err_out:
+	return ERR_PTR(error);
+}
+EXPORT_SYMBOL_GPL(platform_create_bundle);
+
 /* modalias support enables more hands-off userspace setup:
  * (a) environment variable lets new-style hotplug events work once system is
  *     fully running:  "modprobe $MODALIAS"
@@ -578,7 +636,7 @@
 }
 
 static const struct platform_device_id *platform_match_id(
-			struct platform_device_id *id,
+			const struct platform_device_id *id,
 			struct platform_device *pdev)
 {
 	while (id->name[0]) {
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index 3ce3519..89de753 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -1,6 +1,7 @@
 obj-$(CONFIG_PM)	+= sysfs.o
 obj-$(CONFIG_PM_SLEEP)	+= main.o
 obj-$(CONFIG_PM_RUNTIME)	+= runtime.o
+obj-$(CONFIG_PM_OPS)	+= generic_ops.o
 obj-$(CONFIG_PM_TRACE_RTC)	+= trace.o
 
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
new file mode 100644
index 0000000..4b29d49
--- /dev/null
+++ b/drivers/base/power/generic_ops.c
@@ -0,0 +1,233 @@
+/*
+ * drivers/base/power/generic_ops.c - Generic PM callbacks for subsystems
+ *
+ * Copyright (c) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * pm_generic_runtime_idle - Generic runtime idle callback for subsystems.
+ * @dev: Device to handle.
+ *
+ * If PM operations are defined for the @dev's driver and they include
+ * ->runtime_idle(), execute it and return its error code, if nonzero.
+ * Otherwise, execute pm_runtime_suspend() for the device and return 0.
+ */
+int pm_generic_runtime_idle(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+	if (pm && pm->runtime_idle) {
+		int ret = pm->runtime_idle(dev);
+		if (ret)
+			return ret;
+	}
+
+	pm_runtime_suspend(dev);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pm_generic_runtime_idle);
+
+/**
+ * pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems.
+ * @dev: Device to suspend.
+ *
+ * If PM operations are defined for the @dev's driver and they include
+ * ->runtime_suspend(), execute it and return its error code.  Otherwise,
+ * return -EINVAL.
+ */
+int pm_generic_runtime_suspend(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	int ret;
+
+	ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : -EINVAL;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pm_generic_runtime_suspend);
+
+/**
+ * pm_generic_runtime_resume - Generic runtime resume callback for subsystems.
+ * @dev: Device to resume.
+ *
+ * If PM operations are defined for the @dev's driver and they include
+ * ->runtime_resume(), execute it and return its error code.  Otherwise,
+ * return -EINVAL.
+ */
+int pm_generic_runtime_resume(struct device *dev)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	int ret;
+
+	ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : -EINVAL;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pm_generic_runtime_resume);
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_SLEEP
+/**
+ * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback.
+ * @dev: Device to handle.
+ * @event: PM transition of the system under way.
+ *
+ * If the device has not been suspended at run time, execute the
+ * suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and
+ * return its error code.  Otherwise, return zero.
+ */
+static int __pm_generic_call(struct device *dev, int event)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	int (*callback)(struct device *);
+
+	if (!pm || pm_runtime_suspended(dev))
+		return 0;
+
+	switch (event) {
+	case PM_EVENT_SUSPEND:
+		callback = pm->suspend;
+		break;
+	case PM_EVENT_FREEZE:
+		callback = pm->freeze;
+		break;
+	case PM_EVENT_HIBERNATE:
+		callback = pm->poweroff;
+		break;
+	case PM_EVENT_THAW:
+		callback = pm->thaw;
+		break;
+	default:
+		callback = NULL;
+		break;
+	}
+
+	return callback ? callback(dev) : 0;
+}
+
+/**
+ * pm_generic_suspend - Generic suspend callback for subsystems.
+ * @dev: Device to suspend.
+ */
+int pm_generic_suspend(struct device *dev)
+{
+	return __pm_generic_call(dev, PM_EVENT_SUSPEND);
+}
+EXPORT_SYMBOL_GPL(pm_generic_suspend);
+
+/**
+ * pm_generic_freeze - Generic freeze callback for subsystems.
+ * @dev: Device to freeze.
+ */
+int pm_generic_freeze(struct device *dev)
+{
+	return __pm_generic_call(dev, PM_EVENT_FREEZE);
+}
+EXPORT_SYMBOL_GPL(pm_generic_freeze);
+
+/**
+ * pm_generic_poweroff - Generic poweroff callback for subsystems.
+ * @dev: Device to handle.
+ */
+int pm_generic_poweroff(struct device *dev)
+{
+	return __pm_generic_call(dev, PM_EVENT_HIBERNATE);
+}
+EXPORT_SYMBOL_GPL(pm_generic_poweroff);
+
+/**
+ * pm_generic_thaw - Generic thaw callback for subsystems.
+ * @dev: Device to thaw.
+ */
+int pm_generic_thaw(struct device *dev)
+{
+	return __pm_generic_call(dev, PM_EVENT_THAW);
+}
+EXPORT_SYMBOL_GPL(pm_generic_thaw);
+
+/**
+ * __pm_generic_resume - Generic resume/restore callback for subsystems.
+ * @dev: Device to handle.
+ * @event: PM transition of the system under way.
+ *
+ * Execute the resume/resotre callback provided by the @dev's driver, if
+ * defined.  If it returns 0, change the device's runtime PM status to 'active'.
+ * Return the callback's error code.
+ */
+static int __pm_generic_resume(struct device *dev, int event)
+{
+	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	int (*callback)(struct device *);
+	int ret;
+
+	if (!pm)
+		return 0;
+
+	switch (event) {
+	case PM_EVENT_RESUME:
+		callback = pm->resume;
+		break;
+	case PM_EVENT_RESTORE:
+		callback = pm->restore;
+		break;
+	default:
+		callback = NULL;
+		break;
+	}
+
+	if (!callback)
+		return 0;
+
+	ret = callback(dev);
+	if (!ret) {
+		pm_runtime_disable(dev);
+		pm_runtime_set_active(dev);
+		pm_runtime_enable(dev);
+	}
+
+	return ret;
+}
+
+/**
+ * pm_generic_resume - Generic resume callback for subsystems.
+ * @dev: Device to resume.
+ */
+int pm_generic_resume(struct device *dev)
+{
+	return __pm_generic_resume(dev, PM_EVENT_RESUME);
+}
+EXPORT_SYMBOL_GPL(pm_generic_resume);
+
+/**
+ * pm_generic_restore - Generic restore callback for subsystems.
+ * @dev: Device to restore.
+ */
+int pm_generic_restore(struct device *dev)
+{
+	return __pm_generic_resume(dev, PM_EVENT_RESTORE);
+}
+EXPORT_SYMBOL_GPL(pm_generic_restore);
+#endif /* CONFIG_PM_SLEEP */
+
+struct dev_pm_ops generic_subsys_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+	.suspend = pm_generic_suspend,
+	.resume = pm_generic_resume,
+	.freeze = pm_generic_freeze,
+	.thaw = pm_generic_thaw,
+	.poweroff = pm_generic_poweroff,
+	.restore = pm_generic_restore,
+#endif
+#ifdef CONFIG_PM_RUNTIME
+	.runtime_suspend = pm_generic_runtime_suspend,
+	.runtime_resume = pm_generic_runtime_resume,
+	.runtime_idle = pm_generic_runtime_idle,
+#endif
+};
+EXPORT_SYMBOL_GPL(generic_subsys_pm_ops);
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 0e26a6f..d477f4d 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -35,8 +35,8 @@
  * because children are guaranteed to be discovered after parents, and
  * are inserted at the back of the list on discovery.
  *
- * Since device_pm_add() may be called with a device semaphore held,
- * we must never try to acquire a device semaphore while holding
+ * Since device_pm_add() may be called with a device lock held,
+ * we must never try to acquire a device lock while holding
  * dpm_list_mutex.
  */
 
@@ -508,7 +508,7 @@
 	TRACE_RESUME(0);
 
 	dpm_wait(dev->parent, async);
-	down(&dev->sem);
+	device_lock(dev);
 
 	dev->power.status = DPM_RESUMING;
 
@@ -543,7 +543,7 @@
 		}
 	}
  End:
-	up(&dev->sem);
+	device_unlock(dev);
 	complete_all(&dev->power.completion);
 
 	TRACE_RESUME(error);
@@ -629,7 +629,7 @@
  */
 static void device_complete(struct device *dev, pm_message_t state)
 {
-	down(&dev->sem);
+	device_lock(dev);
 
 	if (dev->class && dev->class->pm && dev->class->pm->complete) {
 		pm_dev_dbg(dev, state, "completing class ");
@@ -646,7 +646,7 @@
 		dev->bus->pm->complete(dev);
 	}
 
-	up(&dev->sem);
+	device_unlock(dev);
 }
 
 /**
@@ -809,7 +809,7 @@
 	int error = 0;
 
 	dpm_wait_for_children(dev, async);
-	down(&dev->sem);
+	device_lock(dev);
 
 	if (async_error)
 		goto End;
@@ -849,7 +849,7 @@
 		dev->power.status = DPM_OFF;
 
  End:
-	up(&dev->sem);
+	device_unlock(dev);
 	complete_all(&dev->power.completion);
 
 	return error;
@@ -938,7 +938,7 @@
 {
 	int error = 0;
 
-	down(&dev->sem);
+	device_lock(dev);
 
 	if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) {
 		pm_dev_dbg(dev, state, "preparing ");
@@ -962,7 +962,7 @@
 		suspend_report_result(dev->class->pm->prepare, error);
 	}
  End:
-	up(&dev->sem);
+	device_unlock(dev);
 
 	return error;
 }
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 0d90390..8980fee 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -54,7 +54,7 @@
 	return -EIO;
 }
 
-static struct sysfs_ops sysfs_ops = {
+static const struct sysfs_ops sysfs_ops = {
 	.show	= sysdev_show,
 	.store	= sysdev_store,
 };
@@ -89,7 +89,7 @@
 	struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
 
 	if (class_attr->show)
-		return class_attr->show(class, buffer);
+		return class_attr->show(class, class_attr, buffer);
 	return -EIO;
 }
 
@@ -100,11 +100,11 @@
 	struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
 
 	if (class_attr->store)
-		return class_attr->store(class, buffer, count);
+		return class_attr->store(class, class_attr, buffer, count);
 	return -EIO;
 }
 
-static struct sysfs_ops sysfs_class_ops = {
+static const struct sysfs_ops sysfs_class_ops = {
 	.show	= sysdev_class_show,
 	.store	= sysdev_class_store,
 };
@@ -145,13 +145,20 @@
 	if (retval)
 		return retval;
 
-	return kset_register(&cls->kset);
+	retval = kset_register(&cls->kset);
+	if (!retval && cls->attrs)
+		retval = sysfs_create_files(&cls->kset.kobj,
+					    (const struct attribute **)cls->attrs);
+	return retval;
 }
 
 void sysdev_class_unregister(struct sysdev_class *cls)
 {
 	pr_debug("Unregistering sysdev class '%s'\n",
 		 kobject_name(&cls->kset.kobj));
+	if (cls->attrs)
+		sysfs_remove_files(&cls->kset.kobj,
+				   (const struct attribute **)cls->attrs);
 	kset_unregister(&cls->kset);
 }
 
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 2bf3a6e..d9301e8 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -95,7 +95,7 @@
 
 /* All EEs on the free list should have ID_VACANT (== 0)
  * freshly allocated EEs get !ID_VACANT (== 1)
- * so if it says "cannot dereference null pointer at adress 0x00000001",
+ * so if it says "cannot dereference null pointer at address 0x00000001",
  * it is most likely one of these :( */
 
 #define ID_IN_SYNC      (4711ULL)
@@ -1171,7 +1171,7 @@
 /* Meta data layout
    We reserve a 128MB Block (4k aligned)
    * either at the end of the backing device
-   * or on a seperate meta data device. */
+   * or on a separate meta data device. */
 
 #define MD_RESERVED_SECT (128LU << 11)  /* 128 MB, unit sectors */
 /* The following numbers are sectors */
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index f22c1bc..16119d7 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -57,7 +57,7 @@
  *
  *  It may me handed over to the local disk subsystem.
  *  It may be completed by the local disk subsystem,
- *    either sucessfully or with io-error.
+ *    either successfully or with io-error.
  *  In case it is a READ request, and it failed locally,
  *    it may be retried remotely.
  *
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index b9b1170..90c4038 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -144,13 +144,23 @@
  * Better audit of register_blkdev.
  */
 
-#define FLOPPY_SANITY_CHECK
 #undef  FLOPPY_SILENT_DCL_CLEAR
 
 #define REALLY_SLOW_IO
 
 #define DEBUGT 2
-#define DCL_DEBUG	/* debug disk change line */
+
+#define DPRINT(format, args...) \
+	pr_info("floppy%d: " format, current_drive, ##args)
+
+#define DCL_DEBUG		/* debug disk change line */
+#ifdef DCL_DEBUG
+#define debug_dcl(test, fmt, args...) \
+	do { if ((test) & FD_DEBUG) DPRINT(fmt, ##args); } while (0)
+#else
+#define debug_dcl(test, fmt, args...) \
+	do { if (0) DPRINT(fmt, ##args); } while (0)
+#endif
 
 /* do print messages for unexpected interrupts */
 static int print_unex = 1;
@@ -180,6 +190,8 @@
 #include <linux/mod_devicetable.h>
 #include <linux/buffer_head.h>	/* for invalidate_buffers() */
 #include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
 
 /*
  * PS/2 floppies have much slower step rates than regular floppies.
@@ -191,8 +203,6 @@
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
 
 static int FLOPPY_IRQ = 6;
 static int FLOPPY_DMA = 2;
@@ -241,8 +251,6 @@
 
 static int irqdma_allocated;
 
-#define DEVICE_NAME "floppy"
-
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/cdrom.h>	/* for the compatibility eject ioctl */
@@ -250,7 +258,7 @@
 
 static struct request *current_req;
 static struct request_queue *floppy_queue;
-static void do_fd_request(struct request_queue * q);
+static void do_fd_request(struct request_queue *q);
 
 #ifndef fd_get_dma_residue
 #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
@@ -263,7 +271,7 @@
 #endif
 
 #ifndef fd_dma_mem_alloc
-#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size))
+#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL, get_order(size))
 #endif
 
 static inline void fallback_on_nodma_alloc(char **addr, size_t l)
@@ -273,7 +281,7 @@
 		return;		/* we have the memory */
 	if (can_use_virtual_dma != 2)
 		return;		/* no fallback allowed */
-	printk("DMA memory shortage. Temporarily falling back on virtual DMA\n");
+	pr_info("DMA memory shortage. Temporarily falling back on virtual DMA\n");
 	*addr = (char *)nodma_mem_alloc(l);
 #else
 	return;
@@ -283,59 +291,50 @@
 /* End dma memory related stuff */
 
 static unsigned long fake_change;
-static int initialising = 1;
+static bool initialized;
 
-#define ITYPE(x) (((x)>>2) & 0x1f)
-#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
-#define UNIT(x) ((x) & 0x03)	/* drive on fdc */
-#define FDC(x) (((x) & 0x04) >> 2)	/* fdc of drive */
+#define ITYPE(x)	(((x) >> 2) & 0x1f)
+#define TOMINOR(x)	((x & 3) | ((x & 4) << 5))
+#define UNIT(x)		((x) & 0x03)		/* drive on fdc */
+#define FDC(x)		(((x) & 0x04) >> 2)	/* fdc of drive */
 	/* reverse mapping from unit and fdc to drive */
 #define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2))
-#define DP (&drive_params[current_drive])
-#define DRS (&drive_state[current_drive])
-#define DRWE (&write_errors[current_drive])
-#define FDCS (&fdc_state[fdc])
-#define CLEARF(x) clear_bit(x##_BIT, &DRS->flags)
-#define SETF(x) set_bit(x##_BIT, &DRS->flags)
-#define TESTF(x) test_bit(x##_BIT, &DRS->flags)
 
-#define UDP (&drive_params[drive])
-#define UDRS (&drive_state[drive])
-#define UDRWE (&write_errors[drive])
-#define UFDCS (&fdc_state[FDC(drive)])
-#define UCLEARF(x) clear_bit(x##_BIT, &UDRS->flags)
-#define USETF(x) set_bit(x##_BIT, &UDRS->flags)
-#define UTESTF(x) test_bit(x##_BIT, &UDRS->flags)
+#define DP	(&drive_params[current_drive])
+#define DRS	(&drive_state[current_drive])
+#define DRWE	(&write_errors[current_drive])
+#define FDCS	(&fdc_state[fdc])
 
-#define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args)
+#define UDP	(&drive_params[drive])
+#define UDRS	(&drive_state[drive])
+#define UDRWE	(&write_errors[drive])
+#define UFDCS	(&fdc_state[FDC(drive)])
 
-#define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2)
-#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
-
-#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x)))
+#define PH_HEAD(floppy, head) (((((floppy)->stretch & 2) >> 1) ^ head) << 2)
+#define STRETCH(floppy)	((floppy)->stretch & FD_STRETCH)
 
 /* read/write */
-#define COMMAND raw_cmd->cmd[0]
-#define DR_SELECT raw_cmd->cmd[1]
-#define TRACK raw_cmd->cmd[2]
-#define HEAD raw_cmd->cmd[3]
-#define SECTOR raw_cmd->cmd[4]
-#define SIZECODE raw_cmd->cmd[5]
-#define SECT_PER_TRACK raw_cmd->cmd[6]
-#define GAP raw_cmd->cmd[7]
-#define SIZECODE2 raw_cmd->cmd[8]
+#define COMMAND		(raw_cmd->cmd[0])
+#define DR_SELECT	(raw_cmd->cmd[1])
+#define TRACK		(raw_cmd->cmd[2])
+#define HEAD		(raw_cmd->cmd[3])
+#define SECTOR		(raw_cmd->cmd[4])
+#define SIZECODE	(raw_cmd->cmd[5])
+#define SECT_PER_TRACK	(raw_cmd->cmd[6])
+#define GAP		(raw_cmd->cmd[7])
+#define SIZECODE2	(raw_cmd->cmd[8])
 #define NR_RW 9
 
 /* format */
-#define F_SIZECODE raw_cmd->cmd[2]
-#define F_SECT_PER_TRACK raw_cmd->cmd[3]
-#define F_GAP raw_cmd->cmd[4]
-#define F_FILL raw_cmd->cmd[5]
+#define F_SIZECODE	(raw_cmd->cmd[2])
+#define F_SECT_PER_TRACK (raw_cmd->cmd[3])
+#define F_GAP		(raw_cmd->cmd[4])
+#define F_FILL		(raw_cmd->cmd[5])
 #define NR_F 6
 
 /*
- * Maximum disk size (in kilobytes). This default is used whenever the
- * current disk size is unknown.
+ * Maximum disk size (in kilobytes).
+ * This default is used whenever the current disk size is unknown.
  * [Now it is rather a minimum]
  */
 #define MAX_DISK_SIZE 4		/* 3984 */
@@ -345,16 +344,17 @@
  */
 #define MAX_REPLIES 16
 static unsigned char reply_buffer[MAX_REPLIES];
-static int inr;			/* size of reply buffer, when called from interrupt */
-#define ST0 (reply_buffer[0])
-#define ST1 (reply_buffer[1])
-#define ST2 (reply_buffer[2])
-#define ST3 (reply_buffer[0])	/* result of GETSTATUS */
-#define R_TRACK (reply_buffer[3])
-#define R_HEAD (reply_buffer[4])
-#define R_SECTOR (reply_buffer[5])
-#define R_SIZECODE (reply_buffer[6])
-#define SEL_DLY (2*HZ/100)
+static int inr;		/* size of reply buffer, when called from interrupt */
+#define ST0		(reply_buffer[0])
+#define ST1		(reply_buffer[1])
+#define ST2		(reply_buffer[2])
+#define ST3		(reply_buffer[0])	/* result of GETSTATUS */
+#define R_TRACK		(reply_buffer[3])
+#define R_HEAD		(reply_buffer[4])
+#define R_SECTOR	(reply_buffer[5])
+#define R_SIZECODE	(reply_buffer[6])
+
+#define SEL_DLY		(2 * HZ / 100)
 
 /*
  * this struct defines the different floppy drive types.
@@ -505,9 +505,9 @@
 static int probing;
 
 /* Synchronization of FDC access. */
-#define FD_COMMAND_NONE -1
-#define FD_COMMAND_ERROR 2
-#define FD_COMMAND_OKAY 3
+#define FD_COMMAND_NONE		-1
+#define FD_COMMAND_ERROR	2
+#define FD_COMMAND_OKAY		3
 
 static volatile int command_status = FD_COMMAND_NONE;
 static unsigned long fdc_busy;
@@ -515,11 +515,6 @@
 static DECLARE_WAIT_QUEUE_HEAD(command_done);
 
 #define NO_SIGNAL (!interruptible || !signal_pending(current))
-#define CALL(x) if ((x) == -EINTR) return -EINTR
-#define ECALL(x) if ((ret = (x))) return ret;
-#define _WAIT(x,i) CALL(ret=wait_til_done((x),i))
-#define WAIT(x) _WAIT((x),interruptible)
-#define IWAIT(x) _WAIT((x),1)
 
 /* Errors during formatting are counted here. */
 static int format_errors;
@@ -545,8 +540,9 @@
 static int *errors;
 typedef void (*done_f)(int);
 static struct cont_t {
-	void (*interrupt)(void);	/* this is called after the interrupt of the
-					 * main command */
+	void (*interrupt)(void);
+				/* this is called after the interrupt of the
+				 * main command */
 	void (*redo)(void);	/* this is called to retry the operation */
 	void (*error)(void);	/* this is called to tally an error */
 	done_f done;		/* this is called to say if the operation has
@@ -571,7 +567,6 @@
  * reset doesn't need to be tested before sending commands, because
  * output_byte is automatically disabled when reset is set.
  */
-#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } }
 static void reset_fdc(void);
 
 /*
@@ -579,9 +574,9 @@
  * information to interrupts. They are the data used for the current
  * request.
  */
-#define NO_TRACK -1
-#define NEED_1_RECAL -2
-#define NEED_2_RECAL -3
+#define NO_TRACK	-1
+#define NEED_1_RECAL	-2
+#define NEED_2_RECAL	-3
 
 static int usage_count;
 
@@ -621,39 +616,35 @@
 	debugtimer = jiffies;
 }
 
-static inline void debugt(const char *message)
+static inline void debugt(const char *func, const char *msg)
 {
 	if (DP->flags & DEBUGT)
-		printk("%s dtime=%lu\n", message, jiffies - debugtimer);
+		pr_info("%s:%s dtime=%lu\n", func, msg, jiffies - debugtimer);
 }
 #else
 static inline void set_debugt(void) { }
-static inline void debugt(const char *message) { }
+static inline void debugt(const char *func, const char *msg) { }
 #endif /* DEBUGT */
 
-typedef void (*timeout_fn) (unsigned long);
+typedef void (*timeout_fn)(unsigned long);
 static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
 
 static const char *timeout_message;
 
-#ifdef FLOPPY_SANITY_CHECK
-static void is_alive(const char *message)
+static void is_alive(const char *func, const char *message)
 {
 	/* this routine checks whether the floppy driver is "alive" */
-	if (test_bit(0, &fdc_busy) && command_status < 2
-	    && !timer_pending(&fd_timeout)) {
-		DPRINT("timeout handler died: %s\n", message);
+	if (test_bit(0, &fdc_busy) && command_status < 2 &&
+	    !timer_pending(&fd_timeout)) {
+		DPRINT("%s: timeout handler died.  %s\n", func, message);
 	}
 }
-#endif
 
-static void (*do_floppy) (void) = NULL;
-
-#ifdef FLOPPY_SANITY_CHECK
+static void (*do_floppy)(void) = NULL;
 
 #define OLOGSIZE 20
 
-static void (*lasthandler) (void);
+static void (*lasthandler)(void);
 static unsigned long interruptjiffies;
 static unsigned long resultjiffies;
 static int resultsize;
@@ -666,12 +657,11 @@
 } output_log[OLOGSIZE];
 
 static int output_log_pos;
-#endif
 
 #define current_reqD -1
 #define MAXTIMEOUT -2
 
-static void __reschedule_timeout(int drive, const char *message, int marg)
+static void __reschedule_timeout(int drive, const char *message)
 {
 	if (drive == current_reqD)
 		drive = current_drive;
@@ -682,25 +672,22 @@
 	} else
 		fd_timeout.expires = jiffies + UDP->timeout;
 	add_timer(&fd_timeout);
-	if (UDP->flags & FD_DEBUG) {
-		DPRINT("reschedule timeout ");
-		printk(message, marg);
-		printk("\n");
-	}
+	if (UDP->flags & FD_DEBUG)
+		DPRINT("reschedule timeout %s\n", message);
 	timeout_message = message;
 }
 
-static void reschedule_timeout(int drive, const char *message, int marg)
+static void reschedule_timeout(int drive, const char *message)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&floppy_lock, flags);
-	__reschedule_timeout(drive, message, marg);
+	__reschedule_timeout(drive, message);
 	spin_unlock_irqrestore(&floppy_lock, flags);
 }
 
-#define INFBOUND(a,b) (a)=max_t(int, a, b)
-#define SUPBOUND(a,b) (a)=min_t(int, a, b)
+#define INFBOUND(a, b) (a) = max_t(int, a, b)
+#define SUPBOUND(a, b) (a) = min_t(int, a, b)
 
 /*
  * Bottom half floppy driver.
@@ -739,7 +726,6 @@
 {
 	int fdc = FDC(drive);
 
-#ifdef FLOPPY_SANITY_CHECK
 	if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
 		DPRINT("WARNING disk change called early\n");
 	if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
@@ -748,31 +734,27 @@
 		DPRINT("drive=%d fdc=%d dor=%x\n", drive, FDC(drive),
 		       (unsigned int)FDCS->dor);
 	}
-#endif
 
-#ifdef DCL_DEBUG
-	if (UDP->flags & FD_DEBUG) {
-		DPRINT("checking disk change line for drive %d\n", drive);
-		DPRINT("jiffies=%lu\n", jiffies);
-		DPRINT("disk change line=%x\n", fd_inb(FD_DIR) & 0x80);
-		DPRINT("flags=%lx\n", UDRS->flags);
-	}
-#endif
+	debug_dcl(UDP->flags,
+		  "checking disk change line for drive %d\n", drive);
+	debug_dcl(UDP->flags, "jiffies=%lu\n", jiffies);
+	debug_dcl(UDP->flags, "disk change line=%x\n", fd_inb(FD_DIR) & 0x80);
+	debug_dcl(UDP->flags, "flags=%lx\n", UDRS->flags);
+
 	if (UDP->flags & FD_BROKEN_DCL)
-		return UTESTF(FD_DISK_CHANGED);
+		return test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
 	if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80) {
-		USETF(FD_VERIFY);	/* verify write protection */
-		if (UDRS->maxblock) {
-			/* mark it changed */
-			USETF(FD_DISK_CHANGED);
-		}
+		set_bit(FD_VERIFY_BIT, &UDRS->flags);
+					/* verify write protection */
+
+		if (UDRS->maxblock)	/* mark it changed */
+			set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
 
 		/* invalidate its geometry */
 		if (UDRS->keep_data >= 0) {
 			if ((UDP->flags & FTD_MSG) &&
 			    current_type[drive] != NULL)
-				DPRINT("Disk type is undefined after "
-				       "disk change\n");
+				DPRINT("Disk type is undefined after disk change\n");
 			current_type[drive] = NULL;
 			floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1;
 		}
@@ -780,7 +762,7 @@
 		return 1;
 	} else {
 		UDRS->last_checked = jiffies;
-		UCLEARF(FD_DISK_NEWCHANGE);
+		clear_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags);
 	}
 	return 0;
 }
@@ -790,6 +772,12 @@
 	return ((dor & (0x10 << unit)) && (dor & 3) == unit);
 }
 
+static bool is_ready_state(int status)
+{
+	int state = status & (STATUS_READY | STATUS_DIR | STATUS_DMA);
+	return state == STATUS_READY;
+}
+
 static int set_dor(int fdc, char mask, char data)
 {
 	unsigned char unit;
@@ -806,11 +794,8 @@
 		unit = olddor & 0x3;
 		if (is_selected(olddor, unit) && !is_selected(newdor, unit)) {
 			drive = REVDRIVE(fdc, unit);
-#ifdef DCL_DEBUG
-			if (UDP->flags & FD_DEBUG) {
-				DPRINT("calling disk change from set_dor\n");
-			}
-#endif
+			debug_dcl(UDP->flags,
+				  "calling disk change from set_dor\n");
 			disk_change(drive);
 		}
 		FDCS->dor = newdor;
@@ -834,8 +819,10 @@
 	DRS->select_date = jiffies;
 }
 
-/* reset all driver information about the current fdc. This is needed after
- * a reset, and after a raw command. */
+/*
+ * Reset all driver information about the current fdc.
+ * This is needed after a reset, and after a raw command.
+ */
 static void reset_fdc_info(int mode)
 {
 	int drive;
@@ -857,7 +844,7 @@
 		current_drive = drive;
 	}
 	if (fdc != 1 && fdc != 0) {
-		printk("bad fdc value\n");
+		pr_info("bad fdc value\n");
 		return;
 	}
 	set_dor(fdc, ~0, 8);
@@ -871,11 +858,10 @@
 }
 
 /* locks the driver */
-static int _lock_fdc(int drive, int interruptible, int line)
+static int _lock_fdc(int drive, bool interruptible, int line)
 {
 	if (!usage_count) {
-		printk(KERN_ERR
-		       "Trying to lock fdc while usage count=0 at line %d\n",
+		pr_err("Trying to lock fdc while usage count=0 at line %d\n",
 		       line);
 		return -1;
 	}
@@ -904,15 +890,13 @@
 	}
 	command_status = FD_COMMAND_NONE;
 
-	__reschedule_timeout(drive, "lock fdc", 0);
+	__reschedule_timeout(drive, "lock fdc");
 	set_fdc(drive);
 	return 0;
 }
 
-#define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__)
-
-#define LOCK_FDC(drive,interruptible) \
-if (lock_fdc(drive,interruptible)) return -EINTR;
+#define lock_fdc(drive, interruptible)			\
+	_lock_fdc(drive, interruptible, __LINE__)
 
 /* unlocks the driver */
 static inline void unlock_fdc(void)
@@ -924,7 +908,7 @@
 		DPRINT("FDC access conflict!\n");
 
 	if (do_floppy)
-		DPRINT("device interrupt still active at FDC release: %p!\n",
+		DPRINT("device interrupt still active at FDC release: %pf!\n",
 		       do_floppy);
 	command_status = FD_COMMAND_NONE;
 	spin_lock_irqsave(&floppy_lock, flags);
@@ -1003,7 +987,7 @@
 
 static DECLARE_WORK(floppy_work, NULL);
 
-static void schedule_bh(void (*handler) (void))
+static void schedule_bh(void (*handler)(void))
 {
 	PREPARE_WORK(&floppy_work, (work_func_t)handler);
 	schedule_work(&floppy_work);
@@ -1026,11 +1010,7 @@
  * transfer */
 static void fd_watchdog(void)
 {
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG) {
-		DPRINT("calling disk change from watchdog\n");
-	}
-#endif
+	debug_dcl(DP->flags, "calling disk change from watchdog\n");
 
 	if (disk_change(current_drive)) {
 		DPRINT("disk removed during i/o\n");
@@ -1039,7 +1019,7 @@
 		reset_fdc();
 	} else {
 		del_timer(&fd_timer);
-		fd_timer.function = (timeout_fn) fd_watchdog;
+		fd_timer.function = (timeout_fn)fd_watchdog;
 		fd_timer.expires = jiffies + HZ / 10;
 		add_timer(&fd_timer);
 	}
@@ -1105,25 +1085,23 @@
 {
 	unsigned long f;
 
-#ifdef FLOPPY_SANITY_CHECK
 	if (raw_cmd->length == 0) {
 		int i;
 
-		printk("zero dma transfer size:");
+		pr_info("zero dma transfer size:");
 		for (i = 0; i < raw_cmd->cmd_count; i++)
-			printk("%x,", raw_cmd->cmd[i]);
-		printk("\n");
+			pr_cont("%x,", raw_cmd->cmd[i]);
+		pr_cont("\n");
 		cont->done(0);
 		FDCS->reset = 1;
 		return;
 	}
 	if (((unsigned long)raw_cmd->kernel_data) % 512) {
-		printk("non aligned address: %p\n", raw_cmd->kernel_data);
+		pr_info("non aligned address: %p\n", raw_cmd->kernel_data);
 		cont->done(0);
 		FDCS->reset = 1;
 		return;
 	}
-#endif
 	f = claim_dma_lock();
 	fd_disable_dma();
 #ifdef fd_dma_setup
@@ -1165,7 +1143,7 @@
 		if (status & STATUS_READY)
 			return status;
 	}
-	if (!initialising) {
+	if (initialized) {
 		DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc);
 		show_floppy();
 	}
@@ -1176,22 +1154,21 @@
 /* sends a command byte to the fdc */
 static int output_byte(char byte)
 {
-	int status;
+	int status = wait_til_ready();
 
-	if ((status = wait_til_ready()) < 0)
+	if (status < 0)
 		return -1;
-	if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) {
+
+	if (is_ready_state(status)) {
 		fd_outb(byte, FD_DATA);
-#ifdef FLOPPY_SANITY_CHECK
 		output_log[output_log_pos].data = byte;
 		output_log[output_log_pos].status = status;
 		output_log[output_log_pos].jiffies = jiffies;
 		output_log_pos = (output_log_pos + 1) % OLOGSIZE;
-#endif
 		return 0;
 	}
 	FDCS->reset = 1;
-	if (!initialising) {
+	if (initialized) {
 		DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
 		       byte, fdc, status);
 		show_floppy();
@@ -1199,8 +1176,6 @@
 	return -1;
 }
 
-#define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;}
-
 /* gets the response from the fdc */
 static int result(void)
 {
@@ -1208,14 +1183,13 @@
 	int status = 0;
 
 	for (i = 0; i < MAX_REPLIES; i++) {
-		if ((status = wait_til_ready()) < 0)
+		status = wait_til_ready();
+		if (status < 0)
 			break;
 		status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA;
 		if ((status & ~STATUS_BUSY) == STATUS_READY) {
-#ifdef FLOPPY_SANITY_CHECK
 			resultjiffies = jiffies;
 			resultsize = i;
-#endif
 			return i;
 		}
 		if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY))
@@ -1223,10 +1197,9 @@
 		else
 			break;
 	}
-	if (!initialising) {
-		DPRINT
-		    ("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
-		     fdc, status, i);
+	if (initialized) {
+		DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
+		       fdc, status, i);
 		show_floppy();
 	}
 	FDCS->reset = 1;
@@ -1237,12 +1210,14 @@
 /* does the fdc need more output? */
 static int need_more_output(void)
 {
-	int status;
+	int status = wait_til_ready();
 
-	if ((status = wait_til_ready()) < 0)
+	if (status < 0)
 		return -1;
-	if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
+
+	if (is_ready_state(status))
 		return MORE_OUTPUT;
+
 	return result();
 }
 
@@ -1264,9 +1239,12 @@
 		default:
 			DPRINT("Invalid data rate for perpendicular mode!\n");
 			cont->done(0);
-			FDCS->reset = 1;	/* convenient way to return to
-						 * redo without to much hassle (deep
-						 * stack et al. */
+			FDCS->reset = 1;
+					/*
+					 * convenient way to return to
+					 * redo without too much hassle
+					 * (deep stack et al.)
+					 */
 			return;
 		}
 	} else
@@ -1366,9 +1344,9 @@
 
 	/* Convert step rate from microseconds to milliseconds and 4 bits */
 	srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR);
-	if (slow_floppy) {
+	if (slow_floppy)
 		srt = srt / 4;
-	}
+
 	SUPBOUND(srt, 0xf);
 	INFBOUND(srt, 0);
 
@@ -1415,16 +1393,46 @@
 	 * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
 	 */
 	FDCS->dtr = raw_cmd->rate & 3;
-	return (fd_wait_for_completion(jiffies + 2UL * HZ / 100,
-				       (timeout_fn) floppy_ready));
+	return fd_wait_for_completion(jiffies + 2UL * HZ / 100,
+				      (timeout_fn)floppy_ready);
 }				/* fdc_dtr */
 
 static void tell_sector(void)
 {
-	printk(": track %d, head %d, sector %d, size %d",
-	       R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE);
+	pr_cont(": track %d, head %d, sector %d, size %d",
+		R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE);
 }				/* tell_sector */
 
+static void print_errors(void)
+{
+	DPRINT("");
+	if (ST0 & ST0_ECE) {
+		pr_cont("Recalibrate failed!");
+	} else if (ST2 & ST2_CRC) {
+		pr_cont("data CRC error");
+		tell_sector();
+	} else if (ST1 & ST1_CRC) {
+		pr_cont("CRC error");
+		tell_sector();
+	} else if ((ST1 & (ST1_MAM | ST1_ND)) ||
+		   (ST2 & ST2_MAM)) {
+		if (!probing) {
+			pr_cont("sector not found");
+			tell_sector();
+		} else
+			pr_cont("probe failed...");
+	} else if (ST2 & ST2_WC) {	/* seek error */
+		pr_cont("wrong cylinder");
+	} else if (ST2 & ST2_BC) {	/* cylinder marked as bad */
+		pr_cont("bad cylinder");
+	} else {
+		pr_cont("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x",
+			ST0, ST1, ST2);
+		tell_sector();
+	}
+	pr_cont("\n");
+}
+
 /*
  * OK, this error interpreting routine is called after a
  * DMA read/write has succeeded
@@ -1437,7 +1445,7 @@
 	char bad;
 
 	if (inr != 7) {
-		DPRINT("-- FDC reply error");
+		DPRINT("-- FDC reply error\n");
 		FDCS->reset = 1;
 		return 1;
 	}
@@ -1450,43 +1458,17 @@
 		bad = 1;
 		if (ST1 & ST1_WP) {
 			DPRINT("Drive is write protected\n");
-			CLEARF(FD_DISK_WRITABLE);
+			clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags);
 			cont->done(0);
 			bad = 2;
 		} else if (ST1 & ST1_ND) {
-			SETF(FD_NEED_TWADDLE);
+			set_bit(FD_NEED_TWADDLE_BIT, &DRS->flags);
 		} else if (ST1 & ST1_OR) {
 			if (DP->flags & FTD_MSG)
 				DPRINT("Over/Underrun - retrying\n");
 			bad = 0;
 		} else if (*errors >= DP->max_errors.reporting) {
-			DPRINT("");
-			if (ST0 & ST0_ECE) {
-				printk("Recalibrate failed!");
-			} else if (ST2 & ST2_CRC) {
-				printk("data CRC error");
-				tell_sector();
-			} else if (ST1 & ST1_CRC) {
-				printk("CRC error");
-				tell_sector();
-			} else if ((ST1 & (ST1_MAM | ST1_ND))
-				   || (ST2 & ST2_MAM)) {
-				if (!probing) {
-					printk("sector not found");
-					tell_sector();
-				} else
-					printk("probe failed...");
-			} else if (ST2 & ST2_WC) {	/* seek error */
-				printk("wrong cylinder");
-			} else if (ST2 & ST2_BC) {	/* cylinder marked as bad */
-				printk("bad cylinder");
-			} else {
-				printk
-				    ("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x",
-				     ST0, ST1, ST2);
-				tell_sector();
-			}
-			printk("\n");
+			print_errors();
 		}
 		if (ST2 & ST2_WC || ST2 & ST2_BC)
 			/* wrong cylinder => recal */
@@ -1531,9 +1513,9 @@
 		 */
 		if (time_after(ready_date, jiffies + DP->select_delay)) {
 			ready_date -= DP->select_delay;
-			function = (timeout_fn) floppy_start;
+			function = (timeout_fn)floppy_start;
 		} else
-			function = (timeout_fn) setup_rw_floppy;
+			function = (timeout_fn)setup_rw_floppy;
 
 		/* wait until the floppy is spinning fast enough */
 		if (fd_wait_for_completion(ready_date, function))
@@ -1551,7 +1533,7 @@
 	for (i = 0; i < raw_cmd->cmd_count; i++)
 		r |= output_byte(raw_cmd->cmd[i]);
 
-	debugt("rw_command: ");
+	debugt(__func__, "rw_command");
 
 	if (r) {
 		cont->error();
@@ -1574,7 +1556,7 @@
  */
 static void seek_interrupt(void)
 {
-	debugt("seek interrupt:");
+	debugt(__func__, "");
 	if (inr != 2 || (ST0 & 0xF8) != 0x20) {
 		DPRINT("seek failed\n");
 		DRS->track = NEED_2_RECAL;
@@ -1583,14 +1565,11 @@
 		return;
 	}
 	if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek) {
-#ifdef DCL_DEBUG
-		if (DP->flags & FD_DEBUG) {
-			DPRINT
-			    ("clearing NEWCHANGE flag because of effective seek\n");
-			DPRINT("jiffies=%lu\n", jiffies);
-		}
-#endif
-		CLEARF(FD_DISK_NEWCHANGE);	/* effective seek */
+		debug_dcl(DP->flags,
+			  "clearing NEWCHANGE flag because of effective seek\n");
+		debug_dcl(DP->flags, "jiffies=%lu\n", jiffies);
+		clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags);
+					/* effective seek */
 		DRS->select_date = jiffies;
 	}
 	DRS->track = ST1;
@@ -1599,26 +1578,23 @@
 
 static void check_wp(void)
 {
-	if (TESTF(FD_VERIFY)) {
-		/* check write protection */
+	if (test_bit(FD_VERIFY_BIT, &DRS->flags)) {
+					/* check write protection */
 		output_byte(FD_GETSTATUS);
 		output_byte(UNIT(current_drive));
 		if (result() != 1) {
 			FDCS->reset = 1;
 			return;
 		}
-		CLEARF(FD_VERIFY);
-		CLEARF(FD_NEED_TWADDLE);
-#ifdef DCL_DEBUG
-		if (DP->flags & FD_DEBUG) {
-			DPRINT("checking whether disk is write protected\n");
-			DPRINT("wp=%x\n", ST3 & 0x40);
-		}
-#endif
+		clear_bit(FD_VERIFY_BIT, &DRS->flags);
+		clear_bit(FD_NEED_TWADDLE_BIT, &DRS->flags);
+		debug_dcl(DP->flags,
+			  "checking whether disk is write protected\n");
+		debug_dcl(DP->flags, "wp=%x\n", ST3 & 0x40);
 		if (!(ST3 & 0x40))
-			SETF(FD_DISK_WRITABLE);
+			set_bit(FD_DISK_WRITABLE_BIT, &DRS->flags);
 		else
-			CLEARF(FD_DISK_WRITABLE);
+			clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags);
 	}
 }
 
@@ -1628,19 +1604,15 @@
 
 	blind_seek = 0;
 
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG) {
-		DPRINT("calling disk change from seek\n");
-	}
-#endif
+	debug_dcl(DP->flags, "calling disk change from %s\n", __func__);
 
-	if (!TESTF(FD_DISK_NEWCHANGE) &&
+	if (!test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) &&
 	    disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) {
 		/* the media changed flag should be cleared after the seek.
 		 * If it isn't, this means that there is really no disk in
 		 * the drive.
 		 */
-		SETF(FD_DISK_CHANGED);
+		set_bit(FD_DISK_CHANGED_BIT, &DRS->flags);
 		cont->done(0);
 		cont->redo();
 		return;
@@ -1648,7 +1620,7 @@
 	if (DRS->track <= NEED_1_RECAL) {
 		recalibrate_floppy();
 		return;
-	} else if (TESTF(FD_DISK_NEWCHANGE) &&
+	} else if (test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) &&
 		   (raw_cmd->flags & FD_RAW_NEED_DISK) &&
 		   (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) {
 		/* we seek to clear the media-changed condition. Does anybody
@@ -1677,19 +1649,22 @@
 	do_floppy = seek_interrupt;
 	output_byte(FD_SEEK);
 	output_byte(UNIT(current_drive));
-	LAST_OUT(track);
-	debugt("seek command:");
+	if (output_byte(track) < 0) {
+		reset_fdc();
+		return;
+	}
+	debugt(__func__, "");
 }
 
 static void recal_interrupt(void)
 {
-	debugt("recal interrupt:");
+	debugt(__func__, "");
 	if (inr != 2)
 		FDCS->reset = 1;
 	else if (ST0 & ST0_ECE) {
 		switch (DRS->track) {
 		case NEED_1_RECAL:
-			debugt("recal interrupt need 1 recal:");
+			debugt(__func__, "need 1 recal");
 			/* after a second recalibrate, we still haven't
 			 * reached track 0. Probably no drive. Raise an
 			 * error, as failing immediately might upset
@@ -1698,25 +1673,21 @@
 			cont->redo();
 			return;
 		case NEED_2_RECAL:
-			debugt("recal interrupt need 2 recal:");
+			debugt(__func__, "need 2 recal");
 			/* If we already did a recalibrate,
 			 * and we are not at track 0, this
 			 * means we have moved. (The only way
 			 * not to move at recalibration is to
 			 * be already at track 0.) Clear the
 			 * new change flag */
-#ifdef DCL_DEBUG
-			if (DP->flags & FD_DEBUG) {
-				DPRINT
-				    ("clearing NEWCHANGE flag because of second recalibrate\n");
-			}
-#endif
+			debug_dcl(DP->flags,
+				  "clearing NEWCHANGE flag because of second recalibrate\n");
 
-			CLEARF(FD_DISK_NEWCHANGE);
+			clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags);
 			DRS->select_date = jiffies;
 			/* fall through */
 		default:
-			debugt("recal interrupt default:");
+			debugt(__func__, "default");
 			/* Recalibrate moves the head by at
 			 * most 80 steps. If after one
 			 * recalibrate we don't have reached
@@ -1738,8 +1709,8 @@
 	DPRINT("%s ", message);
 	if (inr >= 0)
 		for (i = 0; i < inr; i++)
-			printk("repl[%d]=%x ", i, reply_buffer[i]);
-	printk("\n");
+			pr_cont("repl[%d]=%x ", i, reply_buffer[i]);
+	pr_cont("\n");
 }
 
 /* interrupt handler. Note that this can be called externally on the Sparc */
@@ -1760,10 +1731,10 @@
 	do_floppy = NULL;
 	if (fdc >= N_FDC || FDCS->address == -1) {
 		/* we don't even know which FDC is the culprit */
-		printk("DOR0=%x\n", fdc_state[0].dor);
-		printk("floppy interrupt on bizarre fdc %d\n", fdc);
-		printk("handler=%p\n", handler);
-		is_alive("bizarre fdc");
+		pr_info("DOR0=%x\n", fdc_state[0].dor);
+		pr_info("floppy interrupt on bizarre fdc %d\n", fdc);
+		pr_info("handler=%pf\n", handler);
+		is_alive(__func__, "bizarre fdc");
 		return IRQ_NONE;
 	}
 
@@ -1777,7 +1748,7 @@
 	 * activity.
 	 */
 
-	do_print = !handler && print_unex && !initialising;
+	do_print = !handler && print_unex && initialized;
 
 	inr = result();
 	if (do_print)
@@ -1790,15 +1761,15 @@
 			if (do_print)
 				print_result("sensei", inr);
 			max_sensei--;
-		} while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2
-			 && max_sensei);
+		} while ((ST0 & 0x83) != UNIT(current_drive) &&
+			 inr == 2 && max_sensei);
 	}
 	if (!handler) {
 		FDCS->reset = 1;
 		return IRQ_NONE;
 	}
 	schedule_bh(handler);
-	is_alive("normal interrupt end");
+	is_alive(__func__, "normal interrupt end");
 
 	/* FIXME! Was it really for us? */
 	return IRQ_HANDLED;
@@ -1806,10 +1777,11 @@
 
 static void recalibrate_floppy(void)
 {
-	debugt("recalibrate floppy:");
+	debugt(__func__, "");
 	do_floppy = recal_interrupt;
 	output_byte(FD_RECALIBRATE);
-	LAST_OUT(UNIT(current_drive));
+	if (output_byte(UNIT(current_drive)) < 0)
+		reset_fdc();
 }
 
 /*
@@ -1817,10 +1789,10 @@
  */
 static void reset_interrupt(void)
 {
-	debugt("reset interrupt:");
+	debugt(__func__, "");
 	result();		/* get the status ready for set_fdc */
 	if (FDCS->reset) {
-		printk("reset set in interrupt, calling %p\n", cont->error);
+		pr_info("reset set in interrupt, calling %pf\n", cont->error);
 		cont->error();	/* a reset just after a reset. BAD! */
 	}
 	cont->redo();
@@ -1858,53 +1830,49 @@
 {
 	int i;
 
-	printk("\n");
-	printk("floppy driver state\n");
-	printk("-------------------\n");
-	printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n",
-	       jiffies, interruptjiffies, jiffies - interruptjiffies,
-	       lasthandler);
+	pr_info("\n");
+	pr_info("floppy driver state\n");
+	pr_info("-------------------\n");
+	pr_info("now=%lu last interrupt=%lu diff=%lu last called handler=%pf\n",
+		jiffies, interruptjiffies, jiffies - interruptjiffies,
+		lasthandler);
 
-#ifdef FLOPPY_SANITY_CHECK
-	printk("timeout_message=%s\n", timeout_message);
-	printk("last output bytes:\n");
+	pr_info("timeout_message=%s\n", timeout_message);
+	pr_info("last output bytes:\n");
 	for (i = 0; i < OLOGSIZE; i++)
-		printk("%2x %2x %lu\n",
-		       output_log[(i + output_log_pos) % OLOGSIZE].data,
-		       output_log[(i + output_log_pos) % OLOGSIZE].status,
-		       output_log[(i + output_log_pos) % OLOGSIZE].jiffies);
-	printk("last result at %lu\n", resultjiffies);
-	printk("last redo_fd_request at %lu\n", lastredo);
-	for (i = 0; i < resultsize; i++) {
-		printk("%2x ", reply_buffer[i]);
-	}
-	printk("\n");
-#endif
+		pr_info("%2x %2x %lu\n",
+			output_log[(i + output_log_pos) % OLOGSIZE].data,
+			output_log[(i + output_log_pos) % OLOGSIZE].status,
+			output_log[(i + output_log_pos) % OLOGSIZE].jiffies);
+	pr_info("last result at %lu\n", resultjiffies);
+	pr_info("last redo_fd_request at %lu\n", lastredo);
+	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1,
+		       reply_buffer, resultsize, true);
 
-	printk("status=%x\n", fd_inb(FD_STATUS));
-	printk("fdc_busy=%lu\n", fdc_busy);
+	pr_info("status=%x\n", fd_inb(FD_STATUS));
+	pr_info("fdc_busy=%lu\n", fdc_busy);
 	if (do_floppy)
-		printk("do_floppy=%p\n", do_floppy);
+		pr_info("do_floppy=%pf\n", do_floppy);
 	if (work_pending(&floppy_work))
-		printk("floppy_work.func=%p\n", floppy_work.func);
+		pr_info("floppy_work.func=%pf\n", floppy_work.func);
 	if (timer_pending(&fd_timer))
-		printk("fd_timer.function=%p\n", fd_timer.function);
+		pr_info("fd_timer.function=%pf\n", fd_timer.function);
 	if (timer_pending(&fd_timeout)) {
-		printk("timer_function=%p\n", fd_timeout.function);
-		printk("expires=%lu\n", fd_timeout.expires - jiffies);
-		printk("now=%lu\n", jiffies);
+		pr_info("timer_function=%pf\n", fd_timeout.function);
+		pr_info("expires=%lu\n", fd_timeout.expires - jiffies);
+		pr_info("now=%lu\n", jiffies);
 	}
-	printk("cont=%p\n", cont);
-	printk("current_req=%p\n", current_req);
-	printk("command_status=%d\n", command_status);
-	printk("\n");
+	pr_info("cont=%p\n", cont);
+	pr_info("current_req=%p\n", current_req);
+	pr_info("command_status=%d\n", command_status);
+	pr_info("\n");
 }
 
 static void floppy_shutdown(unsigned long data)
 {
 	unsigned long flags;
 
-	if (!initialising)
+	if (initialized)
 		show_floppy();
 	cancel_activity();
 
@@ -1916,17 +1884,17 @@
 
 	/* avoid dma going to a random drive after shutdown */
 
-	if (!initialising)
+	if (initialized)
 		DPRINT("floppy timeout called\n");
 	FDCS->reset = 1;
 	if (cont) {
 		cont->done(0);
 		cont->redo();	/* this will recall reset when needed */
 	} else {
-		printk("no cont in shutdown!\n");
+		pr_info("no cont in shutdown!\n");
 		process_fd_request();
 	}
-	is_alive("floppy shutdown");
+	is_alive(__func__, "");
 }
 
 /* start motor, check media-changed condition and write protection */
@@ -1954,27 +1922,26 @@
 	set_dor(fdc, mask, data);
 
 	/* wait_for_completion also schedules reset if needed. */
-	return (fd_wait_for_completion(DRS->select_date + DP->select_delay,
-				       (timeout_fn) function));
+	return fd_wait_for_completion(DRS->select_date + DP->select_delay,
+				      (timeout_fn)function);
 }
 
 static void floppy_ready(void)
 {
-	CHECK_RESET;
+	if (FDCS->reset) {
+		reset_fdc();
+		return;
+	}
 	if (start_motor(floppy_ready))
 		return;
 	if (fdc_dtr())
 		return;
 
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG) {
-		DPRINT("calling disk change from floppy_ready\n");
-	}
-#endif
+	debug_dcl(DP->flags, "calling disk change from floppy_ready\n");
 	if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
 	    disk_change(current_drive) && !DP->select_delay)
-		twaddle();	/* this clears the dcl on certain drive/controller
-				 * combinations */
+		twaddle();	/* this clears the dcl on certain
+				 * drive/controller combinations */
 
 #ifdef fd_chose_dma_mode
 	if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) {
@@ -1998,15 +1965,11 @@
 
 static void floppy_start(void)
 {
-	reschedule_timeout(current_reqD, "floppy start", 0);
+	reschedule_timeout(current_reqD, "floppy start");
 
 	scandrives();
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG) {
-		DPRINT("setting NEWCHANGE in floppy_start\n");
-	}
-#endif
-	SETF(FD_DISK_NEWCHANGE);
+	debug_dcl(DP->flags, "setting NEWCHANGE in floppy_start\n");
+	set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags);
 	floppy_ready();
 }
 
@@ -2026,7 +1989,7 @@
 
 static void do_wakeup(void)
 {
-	reschedule_timeout(MAXTIMEOUT, "do wakeup", 0);
+	reschedule_timeout(MAXTIMEOUT, "do wakeup");
 	cont = NULL;
 	command_status += 2;
 	wake_up(&command_done);
@@ -2046,7 +2009,7 @@
 	.done		= (done_f)empty
 };
 
-static int wait_til_done(void (*handler)(void), int interruptible)
+static int wait_til_done(void (*handler)(void), bool interruptible)
 {
 	int ret;
 
@@ -2064,7 +2027,7 @@
 			if (command_status >= 2 || !NO_SIGNAL)
 				break;
 
-			is_alive("wait_til_done");
+			is_alive(__func__, "");
 			schedule();
 		}
 
@@ -2180,9 +2143,9 @@
 	cont->redo();
 }
 
-#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
-#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1))
+#define FM_MODE(x, y) ((y) & ~(((x)->rate & 0x80) >> 1))
 #define CT(x) ((x) | 0xc0)
+
 static void setup_format_params(int track)
 {
 	int n;
@@ -2197,8 +2160,8 @@
 	raw_cmd = &default_raw_cmd;
 	raw_cmd->track = track;
 
-	raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
-	    FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK;
+	raw_cmd->flags = (FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
+			  FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK);
 	raw_cmd->rate = _floppy->rate & 0x43;
 	raw_cmd->cmd_count = NR_F;
 	COMMAND = FM_MODE(_floppy, FD_FORMAT);
@@ -2257,7 +2220,7 @@
 	buffer_track = -1;
 	setup_format_params(format_req.track << STRETCH(_floppy));
 	floppy_start();
-	debugt("queue format request");
+	debugt(__func__, "queue format request");
 }
 
 static struct cont_t format_cont = {
@@ -2271,7 +2234,9 @@
 {
 	int ret;
 
-	LOCK_FDC(drive, 1);
+	if (lock_fdc(drive, true))
+		return -EINTR;
+
 	set_floppy(drive);
 	if (!_floppy ||
 	    _floppy->track > DP->tracks ||
@@ -2286,7 +2251,9 @@
 	format_errors = 0;
 	cont = &format_cont;
 	errors = &format_errors;
-	IWAIT(redo_format);
+	ret = wait_til_done(redo_format, true);
+	if (ret == -EINTR)
+		return -EINTR;
 	process_fd_request();
 	return ret;
 }
@@ -2320,12 +2287,14 @@
 	struct request *req = current_req;
 	unsigned long flags;
 	int block;
+	char msg[sizeof("request done ") + sizeof(int) * 3];
 
 	probing = 0;
-	reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
+	snprintf(msg, sizeof(msg), "request done %d", uptodate);
+	reschedule_timeout(MAXTIMEOUT, msg);
 
 	if (!req) {
-		printk("floppy.c: no request in request_done\n");
+		pr_info("floppy.c: no request in request_done\n");
 		return;
 	}
 
@@ -2377,7 +2346,7 @@
 		DRS->first_read_date = jiffies;
 
 	nr_sectors = 0;
-	CODE2SIZE;
+	ssize = DIV_ROUND_UP(1 << SIZECODE, 4);
 
 	if (ST1 & ST1_EOC)
 		eoc = 1;
@@ -2393,20 +2362,18 @@
 		       R_HEAD - HEAD) * SECT_PER_TRACK +
 		      R_SECTOR - SECTOR + eoc) << SIZECODE >> 2;
 
-#ifdef FLOPPY_SANITY_CHECK
 	if (nr_sectors / ssize >
 	    DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) {
 		DPRINT("long rw: %x instead of %lx\n",
 		       nr_sectors, current_count_sectors);
-		printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
-		printk("rh=%d h=%d\n", R_HEAD, HEAD);
-		printk("rt=%d t=%d\n", R_TRACK, TRACK);
-		printk("heads=%d eoc=%d\n", heads, eoc);
-		printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
-		       fsector_t, ssize);
-		printk("in_sector_offset=%d\n", in_sector_offset);
+		pr_info("rs=%d s=%d\n", R_SECTOR, SECTOR);
+		pr_info("rh=%d h=%d\n", R_HEAD, HEAD);
+		pr_info("rt=%d t=%d\n", R_TRACK, TRACK);
+		pr_info("heads=%d eoc=%d\n", heads, eoc);
+		pr_info("spt=%d st=%d ss=%d\n",
+			SECT_PER_TRACK, fsector_t, ssize);
+		pr_info("in_sector_offset=%d\n", in_sector_offset);
 	}
-#endif
 
 	nr_sectors -= in_sector_offset;
 	INFBOUND(nr_sectors, 0);
@@ -2511,19 +2478,17 @@
 					      blk_rq_sectors(current_req));
 
 	remaining = current_count_sectors << 9;
-#ifdef FLOPPY_SANITY_CHECK
 	if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) {
 		DPRINT("in copy buffer\n");
-		printk("current_count_sectors=%ld\n", current_count_sectors);
-		printk("remaining=%d\n", remaining >> 9);
-		printk("current_req->nr_sectors=%u\n",
-		       blk_rq_sectors(current_req));
-		printk("current_req->current_nr_sectors=%u\n",
-		       blk_rq_cur_sectors(current_req));
-		printk("max_sector=%d\n", max_sector);
-		printk("ssize=%d\n", ssize);
+		pr_info("current_count_sectors=%ld\n", current_count_sectors);
+		pr_info("remaining=%d\n", remaining >> 9);
+		pr_info("current_req->nr_sectors=%u\n",
+			blk_rq_sectors(current_req));
+		pr_info("current_req->current_nr_sectors=%u\n",
+			blk_rq_cur_sectors(current_req));
+		pr_info("max_sector=%d\n", max_sector);
+		pr_info("ssize=%d\n", ssize);
 	}
-#endif
 
 	buffer_max = max(max_sector, buffer_max);
 
@@ -2539,26 +2504,24 @@
 		SUPBOUND(size, remaining);
 
 		buffer = page_address(bv->bv_page) + bv->bv_offset;
-#ifdef FLOPPY_SANITY_CHECK
 		if (dma_buffer + size >
 		    floppy_track_buffer + (max_buffer_sectors << 10) ||
 		    dma_buffer < floppy_track_buffer) {
 			DPRINT("buffer overrun in copy buffer %d\n",
-			       (int)((floppy_track_buffer -
-				      dma_buffer) >> 9));
-			printk("fsector_t=%d buffer_min=%d\n",
-			       fsector_t, buffer_min);
-			printk("current_count_sectors=%ld\n",
-			       current_count_sectors);
+			       (int)((floppy_track_buffer - dma_buffer) >> 9));
+			pr_info("fsector_t=%d buffer_min=%d\n",
+				fsector_t, buffer_min);
+			pr_info("current_count_sectors=%ld\n",
+				current_count_sectors);
 			if (CT(COMMAND) == FD_READ)
-				printk("read\n");
+				pr_info("read\n");
 			if (CT(COMMAND) == FD_WRITE)
-				printk("write\n");
+				pr_info("write\n");
 			break;
 		}
 		if (((unsigned long)buffer) % 512)
 			DPRINT("%p buffer not aligned\n", buffer);
-#endif
+
 		if (CT(COMMAND) == FD_READ)
 			memcpy(buffer, dma_buffer, size);
 		else
@@ -2567,13 +2530,11 @@
 		remaining -= size;
 		dma_buffer += size;
 	}
-#ifdef FLOPPY_SANITY_CHECK
 	if (remaining) {
 		if (remaining > 0)
 			max_sector -= remaining >> 9;
 		DPRINT("weirdness: remaining %d\n", remaining >> 9);
 	}
-#endif
 }
 
 /* work around a bug in pseudo DMA
@@ -2593,15 +2554,14 @@
 
 		hard_sectors = raw_cmd->length >> (7 + SIZECODE);
 		end_sector = SECTOR + hard_sectors - 1;
-#ifdef FLOPPY_SANITY_CHECK
 		if (end_sector > SECT_PER_TRACK) {
-			printk("too many sectors %d > %d\n",
-			       end_sector, SECT_PER_TRACK);
+			pr_info("too many sectors %d > %d\n",
+				end_sector, SECT_PER_TRACK);
 			return;
 		}
-#endif
-		SECT_PER_TRACK = end_sector;	/* make sure SECT_PER_TRACK points
-						 * to end of transfer */
+		SECT_PER_TRACK = end_sector;
+					/* make sure SECT_PER_TRACK
+					 * points to end of transfer */
 	}
 }
 
@@ -2624,7 +2584,7 @@
 	int ssize;
 
 	if (max_buffer_sectors == 0) {
-		printk("VFS: Block I/O scheduled on unopened device\n");
+		pr_info("VFS: Block I/O scheduled on unopened device\n");
 		return 0;
 	}
 
@@ -2641,7 +2601,7 @@
 		raw_cmd->flags |= FD_RAW_WRITE;
 		COMMAND = FM_MODE(_floppy, FD_WRITE);
 	} else {
-		DPRINT("make_raw_rw_request: unknown command\n");
+		DPRINT("%s: unknown command\n", __func__);
 		return 0;
 	}
 
@@ -2659,7 +2619,8 @@
 	HEAD = fsector_t / _floppy->sect;
 
 	if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) ||
-	     TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect)
+	     test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags)) &&
+	    fsector_t < _floppy->sect)
 		max_sector = _floppy->sect;
 
 	/* 2M disks have phantom sectors on the first track */
@@ -2685,7 +2646,7 @@
 	raw_cmd->track = TRACK << STRETCH(_floppy);
 	DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD);
 	GAP = _floppy->gap;
-	CODE2SIZE;
+	ssize = DIV_ROUND_UP(1 << SIZECODE, 4);
 	SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
 	SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) +
 	    FD_SECTBASE(_floppy);
@@ -2730,8 +2691,10 @@
 		}
 	} else if (in_sector_offset || blk_rq_sectors(current_req) < ssize) {
 		if (CT(COMMAND) == FD_WRITE) {
-			if (fsector_t + blk_rq_sectors(current_req) > ssize &&
-			    fsector_t + blk_rq_sectors(current_req) < ssize + ssize)
+			unsigned int sectors;
+
+			sectors = fsector_t + blk_rq_sectors(current_req);
+			if (sectors > ssize && sectors < ssize + ssize)
 				max_size = ssize + ssize;
 			else
 				max_size = ssize;
@@ -2752,12 +2715,10 @@
 		 * on a 64 bit machine!
 		 */
 		max_size = buffer_chain_size();
-		dma_limit =
-		    (MAX_DMA_ADDRESS -
-		     ((unsigned long)current_req->buffer)) >> 9;
-		if ((unsigned long)max_size > dma_limit) {
+		dma_limit = (MAX_DMA_ADDRESS -
+			     ((unsigned long)current_req->buffer)) >> 9;
+		if ((unsigned long)max_size > dma_limit)
 			max_size = dma_limit;
-		}
 		/* 64 kb boundaries */
 		if (CROSS_64KB(current_req->buffer, max_size << 9))
 			max_size = (K_64 -
@@ -2773,16 +2734,16 @@
 		 */
 		if (!direct ||
 		    (indirect * 2 > direct * 3 &&
-		     *errors < DP->max_errors.read_track && ((!probing
-		       || (DP->read_track & (1 << DRS->probed_format)))))) {
+		     *errors < DP->max_errors.read_track &&
+		     ((!probing ||
+		       (DP->read_track & (1 << DRS->probed_format)))))) {
 			max_size = blk_rq_sectors(current_req);
 		} else {
 			raw_cmd->kernel_data = current_req->buffer;
 			raw_cmd->length = current_count_sectors << 9;
 			if (raw_cmd->length == 0) {
-				DPRINT
-				    ("zero dma transfer attempted from make_raw_request\n");
-				DPRINT("indirect=%d direct=%d fsector_t=%d",
+				DPRINT("%s: zero dma transfer attempted\n", __func__);
+				DPRINT("indirect=%d direct=%d fsector_t=%d\n",
 				       indirect, direct, fsector_t);
 				return 0;
 			}
@@ -2802,25 +2763,22 @@
 	    ((CT(COMMAND) == FD_READ ||
 	      (!in_sector_offset && blk_rq_sectors(current_req) >= ssize)) &&
 	     max_sector > 2 * max_buffer_sectors + buffer_min &&
-	     max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)
-	    /* not enough space */
-	    ) {
+	     max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)) {
+		/* not enough space */
 		buffer_track = -1;
 		buffer_drive = current_drive;
 		buffer_max = buffer_min = aligned_sector_t;
 	}
 	raw_cmd->kernel_data = floppy_track_buffer +
-	    ((aligned_sector_t - buffer_min) << 9);
+		((aligned_sector_t - buffer_min) << 9);
 
 	if (CT(COMMAND) == FD_WRITE) {
 		/* copy write buffer to track buffer.
 		 * if we get here, we know that the write
 		 * is either aligned or the data already in the buffer
 		 * (buffer will be overwritten) */
-#ifdef FLOPPY_SANITY_CHECK
 		if (in_sector_offset && buffer_track == -1)
 			DPRINT("internal error offset !=0 on write\n");
-#endif
 		buffer_track = raw_cmd->track;
 		buffer_drive = current_drive;
 		copy_buffer(ssize, max_sector,
@@ -2834,7 +2792,6 @@
 	raw_cmd->length = in_sector_offset + current_count_sectors;
 	raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
 	raw_cmd->length <<= 9;
-#ifdef FLOPPY_SANITY_CHECK
 	if ((raw_cmd->length < current_count_sectors << 9) ||
 	    (raw_cmd->kernel_data != current_req->buffer &&
 	     CT(COMMAND) == FD_WRITE &&
@@ -2845,19 +2802,19 @@
 		DPRINT("fractionary current count b=%lx s=%lx\n",
 		       raw_cmd->length, current_count_sectors);
 		if (raw_cmd->kernel_data != current_req->buffer)
-			printk("addr=%d, length=%ld\n",
-			       (int)((raw_cmd->kernel_data -
-				      floppy_track_buffer) >> 9),
-			       current_count_sectors);
-		printk("st=%d ast=%d mse=%d msi=%d\n",
-		       fsector_t, aligned_sector_t, max_sector, max_size);
-		printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
-		printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
-		       COMMAND, SECTOR, HEAD, TRACK);
-		printk("buffer drive=%d\n", buffer_drive);
-		printk("buffer track=%d\n", buffer_track);
-		printk("buffer_min=%d\n", buffer_min);
-		printk("buffer_max=%d\n", buffer_max);
+			pr_info("addr=%d, length=%ld\n",
+				(int)((raw_cmd->kernel_data -
+				       floppy_track_buffer) >> 9),
+				current_count_sectors);
+		pr_info("st=%d ast=%d mse=%d msi=%d\n",
+			fsector_t, aligned_sector_t, max_sector, max_size);
+		pr_info("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
+		pr_info("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
+			COMMAND, SECTOR, HEAD, TRACK);
+		pr_info("buffer drive=%d\n", buffer_drive);
+		pr_info("buffer track=%d\n", buffer_track);
+		pr_info("buffer_min=%d\n", buffer_min);
+		pr_info("buffer_max=%d\n", buffer_max);
 		return 0;
 	}
 
@@ -2868,14 +2825,14 @@
 		    raw_cmd->kernel_data + raw_cmd->length >
 		    floppy_track_buffer + (max_buffer_sectors << 10)) {
 			DPRINT("buffer overrun in schedule dma\n");
-			printk("fsector_t=%d buffer_min=%d current_count=%ld\n",
-			       fsector_t, buffer_min, raw_cmd->length >> 9);
-			printk("current_count_sectors=%ld\n",
-			       current_count_sectors);
+			pr_info("fsector_t=%d buffer_min=%d current_count=%ld\n",
+				fsector_t, buffer_min, raw_cmd->length >> 9);
+			pr_info("current_count_sectors=%ld\n",
+				current_count_sectors);
 			if (CT(COMMAND) == FD_READ)
-				printk("read\n");
+				pr_info("read\n");
 			if (CT(COMMAND) == FD_WRITE)
-				printk("write\n");
+				pr_info("write\n");
 			return 0;
 		}
 	} else if (raw_cmd->length > blk_rq_bytes(current_req) ||
@@ -2884,14 +2841,13 @@
 		return 0;
 	} else if (raw_cmd->length < current_count_sectors << 9) {
 		DPRINT("more sectors than bytes\n");
-		printk("bytes=%ld\n", raw_cmd->length >> 9);
-		printk("sectors=%ld\n", current_count_sectors);
+		pr_info("bytes=%ld\n", raw_cmd->length >> 9);
+		pr_info("sectors=%ld\n", current_count_sectors);
 	}
 	if (raw_cmd->length == 0) {
 		DPRINT("zero dma transfer attempted from make_raw_request\n");
 		return 0;
 	}
-#endif
 
 	virtualdmabug_workaround();
 	return 2;
@@ -2899,7 +2855,6 @@
 
 static void redo_fd_request(void)
 {
-#define REPEAT {request_done(0); continue; }
 	int drive;
 	int tmp;
 
@@ -2907,63 +2862,63 @@
 	if (current_drive < N_DRIVE)
 		floppy_off(current_drive);
 
-	for (;;) {
-		if (!current_req) {
-			struct request *req;
+do_request:
+	if (!current_req) {
+		struct request *req;
 
-			spin_lock_irq(floppy_queue->queue_lock);
-			req = blk_fetch_request(floppy_queue);
-			spin_unlock_irq(floppy_queue->queue_lock);
-			if (!req) {
-				do_floppy = NULL;
-				unlock_fdc();
-				return;
-			}
-			current_req = req;
-		}
-		drive = (long)current_req->rq_disk->private_data;
-		set_fdc(drive);
-		reschedule_timeout(current_reqD, "redo fd request", 0);
-
-		set_floppy(drive);
-		raw_cmd = &default_raw_cmd;
-		raw_cmd->flags = 0;
-		if (start_motor(redo_fd_request))
+		spin_lock_irq(floppy_queue->queue_lock);
+		req = blk_fetch_request(floppy_queue);
+		spin_unlock_irq(floppy_queue->queue_lock);
+		if (!req) {
+			do_floppy = NULL;
+			unlock_fdc();
 			return;
-		disk_change(current_drive);
-		if (test_bit(current_drive, &fake_change) ||
-		    TESTF(FD_DISK_CHANGED)) {
-			DPRINT("disk absent or changed during operation\n");
-			REPEAT;
 		}
-		if (!_floppy) {	/* Autodetection */
-			if (!probing) {
-				DRS->probed_format = 0;
-				if (next_valid_format()) {
-					DPRINT("no autodetectable formats\n");
-					_floppy = NULL;
-					REPEAT;
-				}
-			}
-			probing = 1;
-			_floppy =
-			    floppy_type + DP->autodetect[DRS->probed_format];
-		} else
-			probing = 0;
-		errors = &(current_req->errors);
-		tmp = make_raw_rw_request();
-		if (tmp < 2) {
-			request_done(tmp);
-			continue;
-		}
-
-		if (TESTF(FD_NEED_TWADDLE))
-			twaddle();
-		schedule_bh(floppy_start);
-		debugt("queue fd request");
-		return;
+		current_req = req;
 	}
-#undef REPEAT
+	drive = (long)current_req->rq_disk->private_data;
+	set_fdc(drive);
+	reschedule_timeout(current_reqD, "redo fd request");
+
+	set_floppy(drive);
+	raw_cmd = &default_raw_cmd;
+	raw_cmd->flags = 0;
+	if (start_motor(redo_fd_request))
+		return;
+
+	disk_change(current_drive);
+	if (test_bit(current_drive, &fake_change) ||
+	    test_bit(FD_DISK_CHANGED_BIT, &DRS->flags)) {
+		DPRINT("disk absent or changed during operation\n");
+		request_done(0);
+		goto do_request;
+	}
+	if (!_floppy) {	/* Autodetection */
+		if (!probing) {
+			DRS->probed_format = 0;
+			if (next_valid_format()) {
+				DPRINT("no autodetectable formats\n");
+				_floppy = NULL;
+				request_done(0);
+				goto do_request;
+			}
+		}
+		probing = 1;
+		_floppy = floppy_type + DP->autodetect[DRS->probed_format];
+	} else
+		probing = 0;
+	errors = &(current_req->errors);
+	tmp = make_raw_rw_request();
+	if (tmp < 2) {
+		request_done(tmp);
+		goto do_request;
+	}
+
+	if (test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags))
+		twaddle();
+	schedule_bh(floppy_start);
+	debugt(__func__, "queue fd request");
+	return;
 }
 
 static struct cont_t rw_cont = {
@@ -2979,30 +2934,30 @@
 	schedule_bh(redo_fd_request);
 }
 
-static void do_fd_request(struct request_queue * q)
+static void do_fd_request(struct request_queue *q)
 {
 	if (max_buffer_sectors == 0) {
-		printk("VFS: do_fd_request called on non-open device\n");
+		pr_info("VFS: %s called on non-open device\n", __func__);
 		return;
 	}
 
 	if (usage_count == 0) {
-		printk("warning: usage count=0, current_req=%p exiting\n",
-		       current_req);
-		printk("sect=%ld type=%x flags=%x\n",
-		       (long)blk_rq_pos(current_req), current_req->cmd_type,
-		       current_req->cmd_flags);
+		pr_info("warning: usage count=0, current_req=%p exiting\n",
+			current_req);
+		pr_info("sect=%ld type=%x flags=%x\n",
+			(long)blk_rq_pos(current_req), current_req->cmd_type,
+			current_req->cmd_flags);
 		return;
 	}
 	if (test_bit(0, &fdc_busy)) {
 		/* fdc busy, this new request will be treated when the
 		   current one is done */
-		is_alive("do fd request, old request running");
+		is_alive(__func__, "old request running");
 		return;
 	}
-	lock_fdc(MAXTIMEOUT, 0);
+	lock_fdc(MAXTIMEOUT, false);
 	process_fd_request();
-	is_alive("do fd request");
+	is_alive(__func__, "");
 }
 
 static struct cont_t poll_cont = {
@@ -3012,24 +2967,18 @@
 	.done		= generic_done
 };
 
-static int poll_drive(int interruptible, int flag)
+static int poll_drive(bool interruptible, int flag)
 {
-	int ret;
-
 	/* no auto-sense, just clear dcl */
 	raw_cmd = &default_raw_cmd;
 	raw_cmd->flags = flag;
 	raw_cmd->track = 0;
 	raw_cmd->cmd_count = 0;
 	cont = &poll_cont;
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG) {
-		DPRINT("setting NEWCHANGE in poll_drive\n");
-	}
-#endif
-	SETF(FD_DISK_NEWCHANGE);
-	WAIT(floppy_ready);
-	return ret;
+	debug_dcl(DP->flags, "setting NEWCHANGE in poll_drive\n");
+	set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags);
+
+	return wait_til_done(floppy_ready, interruptible);
 }
 
 /*
@@ -3039,7 +2988,7 @@
 
 static void reset_intr(void)
 {
-	printk("weird, reset interrupt called\n");
+	pr_info("weird, reset interrupt called\n");
 }
 
 static struct cont_t reset_cont = {
@@ -3049,20 +2998,23 @@
 	.done		= generic_done
 };
 
-static int user_reset_fdc(int drive, int arg, int interruptible)
+static int user_reset_fdc(int drive, int arg, bool interruptible)
 {
 	int ret;
 
-	ret = 0;
-	LOCK_FDC(drive, interruptible);
+	if (lock_fdc(drive, interruptible))
+		return -EINTR;
+
 	if (arg == FD_RESET_ALWAYS)
 		FDCS->reset = 1;
 	if (FDCS->reset) {
 		cont = &reset_cont;
-		WAIT(reset_fdc);
+		ret = wait_til_done(reset_fdc, interruptible);
+		if (ret == -EINTR)
+			return -EINTR;
 	}
 	process_fd_request();
-	return ret;
+	return 0;
 }
 
 /*
@@ -3075,17 +3027,12 @@
 	return copy_to_user(param, address, size) ? -EFAULT : 0;
 }
 
-static inline int fd_copyin(void __user *param, void *address, unsigned long size)
+static inline int fd_copyin(void __user *param, void *address,
+			    unsigned long size)
 {
 	return copy_from_user(address, param, size) ? -EFAULT : 0;
 }
 
-#define _COPYOUT(x) (copy_to_user((void __user *)param, &(x), sizeof(x)) ? -EFAULT : 0)
-#define _COPYIN(x) (copy_from_user(&(x), (void __user *)param, sizeof(x)) ? -EFAULT : 0)
-
-#define COPYOUT(x) ECALL(_COPYOUT(x))
-#define COPYIN(x) ECALL(_COPYIN(x))
-
 static inline const char *drive_name(int type, int drive)
 {
 	struct floppy_struct *floppy;
@@ -3156,23 +3103,29 @@
 	.done		= raw_cmd_done
 };
 
-static inline int raw_cmd_copyout(int cmd, char __user *param,
+static inline int raw_cmd_copyout(int cmd, void __user *param,
 				  struct floppy_raw_cmd *ptr)
 {
 	int ret;
 
 	while (ptr) {
-		COPYOUT(*ptr);
+		ret = copy_to_user(param, ptr, sizeof(*ptr));
+		if (ret)
+			return -EFAULT;
 		param += sizeof(struct floppy_raw_cmd);
 		if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) {
-			if (ptr->length >= 0
-			    && ptr->length <= ptr->buffer_length)
-				ECALL(fd_copyout
-				      (ptr->data, ptr->kernel_data,
-				       ptr->buffer_length - ptr->length));
+			if (ptr->length >= 0 &&
+			    ptr->length <= ptr->buffer_length) {
+				long length = ptr->buffer_length - ptr->length;
+				ret = fd_copyout(ptr->data, ptr->kernel_data,
+						 length);
+				if (ret)
+					return ret;
+			}
 		}
 		ptr = ptr->next;
 	}
+
 	return 0;
 }
 
@@ -3195,7 +3148,7 @@
 	}
 }
 
-static inline int raw_cmd_copyin(int cmd, char __user *param,
+static inline int raw_cmd_copyin(int cmd, void __user *param,
 				 struct floppy_raw_cmd **rcmd)
 {
 	struct floppy_raw_cmd *ptr;
@@ -3203,17 +3156,19 @@
 	int i;
 
 	*rcmd = NULL;
-	while (1) {
-		ptr = (struct floppy_raw_cmd *)
-		    kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
-		if (!ptr)
-			return -ENOMEM;
-		*rcmd = ptr;
-		COPYIN(*ptr);
-		ptr->next = NULL;
-		ptr->buffer_length = 0;
-		param += sizeof(struct floppy_raw_cmd);
-		if (ptr->cmd_count > 33)
+
+loop:
+	ptr = kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
+	if (!ptr)
+		return -ENOMEM;
+	*rcmd = ptr;
+	ret = copy_from_user(ptr, param, sizeof(*ptr));
+	if (ret)
+		return -EFAULT;
+	ptr->next = NULL;
+	ptr->buffer_length = 0;
+	param += sizeof(struct floppy_raw_cmd);
+	if (ptr->cmd_count > 33)
 			/* the command may now also take up the space
 			 * initially intended for the reply & the
 			 * reply count. Needed for long 82078 commands
@@ -3222,31 +3177,35 @@
 			 * 16 bytes for a structure, you'll one day
 			 * discover that you really need 17...
 			 */
+		return -EINVAL;
+
+	for (i = 0; i < 16; i++)
+		ptr->reply[i] = 0;
+	ptr->resultcode = 0;
+	ptr->kernel_data = NULL;
+
+	if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
+		if (ptr->length <= 0)
 			return -EINVAL;
-
-		for (i = 0; i < 16; i++)
-			ptr->reply[i] = 0;
-		ptr->resultcode = 0;
-		ptr->kernel_data = NULL;
-
-		if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
-			if (ptr->length <= 0)
-				return -EINVAL;
-			ptr->kernel_data =
-			    (char *)fd_dma_mem_alloc(ptr->length);
-			fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length);
-			if (!ptr->kernel_data)
-				return -ENOMEM;
-			ptr->buffer_length = ptr->length;
-		}
-		if (ptr->flags & FD_RAW_WRITE)
-			ECALL(fd_copyin(ptr->data, ptr->kernel_data,
-					ptr->length));
-		rcmd = &(ptr->next);
-		if (!(ptr->flags & FD_RAW_MORE))
-			return 0;
-		ptr->rate &= 0x43;
+		ptr->kernel_data = (char *)fd_dma_mem_alloc(ptr->length);
+		fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length);
+		if (!ptr->kernel_data)
+			return -ENOMEM;
+		ptr->buffer_length = ptr->length;
 	}
+	if (ptr->flags & FD_RAW_WRITE) {
+		ret = fd_copyin(ptr->data, ptr->kernel_data, ptr->length);
+		if (ret)
+			return ret;
+	}
+
+	if (ptr->flags & FD_RAW_MORE) {
+		rcmd = &(ptr->next);
+		ptr->rate &= 0x43;
+		goto loop;
+	}
+
+	return 0;
 }
 
 static int raw_cmd_ioctl(int cmd, void __user *param)
@@ -3283,12 +3242,8 @@
 
 	raw_cmd = my_raw_cmd;
 	cont = &raw_cmd_cont;
-	ret = wait_til_done(floppy_start, 1);
-#ifdef DCL_DEBUG
-	if (DP->flags & FD_DEBUG) {
-		DPRINT("calling disk change from raw_cmd ioctl\n");
-	}
-#endif
+	ret = wait_til_done(floppy_start, true);
+	debug_dcl(DP->flags, "calling disk change from raw_cmd ioctl\n");
 
 	if (ret != -EINTR && FDCS->reset)
 		ret = -EIO;
@@ -3327,7 +3282,7 @@
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		mutex_lock(&open_lock);
-		if (lock_fdc(drive, 1)) {
+		if (lock_fdc(drive, true)) {
 			mutex_unlock(&open_lock);
 			return -EINTR;
 		}
@@ -3346,11 +3301,15 @@
 		mutex_unlock(&open_lock);
 	} else {
 		int oldStretch;
-		LOCK_FDC(drive, 1);
-		if (cmd != FDDEFPRM)
+
+		if (lock_fdc(drive, true))
+			return -EINTR;
+		if (cmd != FDDEFPRM) {
 			/* notice a disk change immediately, else
 			 * we lose our settings immediately*/
-			CALL(poll_drive(1, FD_RAW_NEED_DISK));
+			if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
+				return -EINTR;
+		}
 		oldStretch = g->stretch;
 		user_params[drive] = *g;
 		if (buffer_drive == drive)
@@ -3415,7 +3374,7 @@
 			*size = _IOC_SIZE(*cmd);
 			*cmd = ioctl_table[i];
 			if (*size > _IOC_SIZE(*cmd)) {
-				printk("ioctl not yet supported\n");
+				pr_info("ioctl not yet supported\n");
 				return -EFAULT;
 			}
 			return 0;
@@ -3429,8 +3388,10 @@
 	if (type)
 		*g = &floppy_type[type];
 	else {
-		LOCK_FDC(drive, 0);
-		CALL(poll_drive(0, 0));
+		if (lock_fdc(drive, false))
+			return -EINTR;
+		if (poll_drive(false, 0) == -EINTR)
+			return -EINTR;
 		process_fd_request();
 		*g = current_type[drive];
 	}
@@ -3459,10 +3420,6 @@
 static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
 		    unsigned long param)
 {
-#define FD_IOCTL_ALLOWED (mode & (FMODE_WRITE|FMODE_WRITE_IOCTL))
-#define OUT(c,x) case c: outparam = (const char *) (x); break
-#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
-
 	int drive = (long)bdev->bd_disk->private_data;
 	int type = ITYPE(UDRS->fd_device);
 	int i;
@@ -3474,26 +3431,28 @@
 		struct floppy_max_errors max_errors;
 		struct floppy_drive_params dp;
 	} inparam;		/* parameters coming from user space */
-	const char *outparam;	/* parameters passed back to user space */
+	const void *outparam;	/* parameters passed back to user space */
 
 	/* convert compatibility eject ioctls into floppy eject ioctl.
 	 * We do this in order to provide a means to eject floppy disks before
 	 * installing the new fdutils package */
 	if (cmd == CDROMEJECT ||	/* CD-ROM eject */
-	    cmd == 0x6470 /* SunOS floppy eject */ ) {
+	    cmd == 0x6470) {		/* SunOS floppy eject */
 		DPRINT("obsolete eject ioctl\n");
 		DPRINT("please use floppycontrol --eject\n");
 		cmd = FDEJECT;
 	}
 
-	/* convert the old style command into a new style command */
-	if ((cmd & 0xff00) == 0x0200) {
-		ECALL(normalize_ioctl(&cmd, &size));
-	} else
+	if (!((cmd & 0xff00) == 0x0200))
 		return -EINVAL;
 
+	/* convert the old style command into a new style command */
+	ret = normalize_ioctl(&cmd, &size);
+	if (ret)
+		return ret;
+
 	/* permission checks */
-	if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) ||
+	if (((cmd & 0x40) && !(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) ||
 	    ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
 		return -EPERM;
 
@@ -3501,129 +3460,142 @@
 		return -EINVAL;
 
 	/* copyin */
-	CLEARSTRUCT(&inparam);
-	if (_IOC_DIR(cmd) & _IOC_WRITE)
-	    ECALL(fd_copyin((void __user *)param, &inparam, size))
-
-		switch (cmd) {
-		case FDEJECT:
-			if (UDRS->fd_ref != 1)
-				/* somebody else has this drive open */
-				return -EBUSY;
-			LOCK_FDC(drive, 1);
-
-			/* do the actual eject. Fails on
-			 * non-Sparc architectures */
-			ret = fd_eject(UNIT(drive));
-
-			USETF(FD_DISK_CHANGED);
-			USETF(FD_VERIFY);
-			process_fd_request();
+	memset(&inparam, 0, sizeof(inparam));
+	if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		ret = fd_copyin((void __user *)param, &inparam, size);
+		if (ret)
 			return ret;
-		case FDCLRPRM:
-			LOCK_FDC(drive, 1);
-			current_type[drive] = NULL;
-			floppy_sizes[drive] = MAX_DISK_SIZE << 1;
-			UDRS->keep_data = 0;
-			return invalidate_drive(bdev);
-		case FDSETPRM:
-		case FDDEFPRM:
-			return set_geometry(cmd, &inparam.g,
-					    drive, type, bdev);
-		case FDGETPRM:
-			ECALL(get_floppy_geometry(drive, type,
-						  (struct floppy_struct **)
-						  &outparam));
-			break;
+	}
 
-		case FDMSGON:
-			UDP->flags |= FTD_MSG;
-			return 0;
-		case FDMSGOFF:
-			UDP->flags &= ~FTD_MSG;
-			return 0;
+	switch (cmd) {
+	case FDEJECT:
+		if (UDRS->fd_ref != 1)
+			/* somebody else has this drive open */
+			return -EBUSY;
+		if (lock_fdc(drive, true))
+			return -EINTR;
 
-		case FDFMTBEG:
-			LOCK_FDC(drive, 1);
-			CALL(poll_drive(1, FD_RAW_NEED_DISK));
-			ret = UDRS->flags;
-			process_fd_request();
-			if (ret & FD_VERIFY)
-				return -ENODEV;
-			if (!(ret & FD_DISK_WRITABLE))
-				return -EROFS;
-			return 0;
-		case FDFMTTRK:
-			if (UDRS->fd_ref != 1)
-				return -EBUSY;
-			return do_format(drive, &inparam.f);
-		case FDFMTEND:
-		case FDFLUSH:
-			LOCK_FDC(drive, 1);
-			return invalidate_drive(bdev);
+		/* do the actual eject. Fails on
+		 * non-Sparc architectures */
+		ret = fd_eject(UNIT(drive));
 
-		case FDSETEMSGTRESH:
-			UDP->max_errors.reporting =
-			    (unsigned short)(param & 0x0f);
-			return 0;
-			OUT(FDGETMAXERRS, &UDP->max_errors);
-			IN(FDSETMAXERRS, &UDP->max_errors, max_errors);
-
-		case FDGETDRVTYP:
-			outparam = drive_name(type, drive);
-			SUPBOUND(size, strlen(outparam) + 1);
-			break;
-
-			IN(FDSETDRVPRM, UDP, dp);
-			OUT(FDGETDRVPRM, UDP);
-
-		case FDPOLLDRVSTAT:
-			LOCK_FDC(drive, 1);
-			CALL(poll_drive(1, FD_RAW_NEED_DISK));
-			process_fd_request();
-			/* fall through */
-			OUT(FDGETDRVSTAT, UDRS);
-
-		case FDRESET:
-			return user_reset_fdc(drive, (int)param, 1);
-
-			OUT(FDGETFDCSTAT, UFDCS);
-
-		case FDWERRORCLR:
-			CLEARSTRUCT(UDRWE);
-			return 0;
-			OUT(FDWERRORGET, UDRWE);
-
-		case FDRAWCMD:
-			if (type)
-				return -EINVAL;
-			LOCK_FDC(drive, 1);
-			set_floppy(drive);
-			CALL(i = raw_cmd_ioctl(cmd, (void __user *)param));
-			process_fd_request();
-			return i;
-
-		case FDTWADDLE:
-			LOCK_FDC(drive, 1);
-			twaddle();
-			process_fd_request();
-			return 0;
-
-		default:
+		set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
+		set_bit(FD_VERIFY_BIT, &UDRS->flags);
+		process_fd_request();
+		return ret;
+	case FDCLRPRM:
+		if (lock_fdc(drive, true))
+			return -EINTR;
+		current_type[drive] = NULL;
+		floppy_sizes[drive] = MAX_DISK_SIZE << 1;
+		UDRS->keep_data = 0;
+		return invalidate_drive(bdev);
+	case FDSETPRM:
+	case FDDEFPRM:
+		return set_geometry(cmd, &inparam.g, drive, type, bdev);
+	case FDGETPRM:
+		ret = get_floppy_geometry(drive, type,
+					  (struct floppy_struct **)&outparam);
+		if (ret)
+			return ret;
+		break;
+	case FDMSGON:
+		UDP->flags |= FTD_MSG;
+		return 0;
+	case FDMSGOFF:
+		UDP->flags &= ~FTD_MSG;
+		return 0;
+	case FDFMTBEG:
+		if (lock_fdc(drive, true))
+			return -EINTR;
+		if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
+			return -EINTR;
+		ret = UDRS->flags;
+		process_fd_request();
+		if (ret & FD_VERIFY)
+			return -ENODEV;
+		if (!(ret & FD_DISK_WRITABLE))
+			return -EROFS;
+		return 0;
+	case FDFMTTRK:
+		if (UDRS->fd_ref != 1)
+			return -EBUSY;
+		return do_format(drive, &inparam.f);
+	case FDFMTEND:
+	case FDFLUSH:
+		if (lock_fdc(drive, true))
+			return -EINTR;
+		return invalidate_drive(bdev);
+	case FDSETEMSGTRESH:
+		UDP->max_errors.reporting = (unsigned short)(param & 0x0f);
+		return 0;
+	case FDGETMAXERRS:
+		outparam = &UDP->max_errors;
+		break;
+	case FDSETMAXERRS:
+		UDP->max_errors = inparam.max_errors;
+		break;
+	case FDGETDRVTYP:
+		outparam = drive_name(type, drive);
+		SUPBOUND(size, strlen((const char *)outparam) + 1);
+		break;
+	case FDSETDRVPRM:
+		*UDP = inparam.dp;
+		break;
+	case FDGETDRVPRM:
+		outparam = UDP;
+		break;
+	case FDPOLLDRVSTAT:
+		if (lock_fdc(drive, true))
+			return -EINTR;
+		if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
+			return -EINTR;
+		process_fd_request();
+		/* fall through */
+	case FDGETDRVSTAT:
+		outparam = UDRS;
+		break;
+	case FDRESET:
+		return user_reset_fdc(drive, (int)param, true);
+	case FDGETFDCSTAT:
+		outparam = UFDCS;
+		break;
+	case FDWERRORCLR:
+		memset(UDRWE, 0, sizeof(*UDRWE));
+		return 0;
+	case FDWERRORGET:
+		outparam = UDRWE;
+		break;
+	case FDRAWCMD:
+		if (type)
 			return -EINVAL;
-		}
+		if (lock_fdc(drive, true))
+			return -EINTR;
+		set_floppy(drive);
+		i = raw_cmd_ioctl(cmd, (void __user *)param);
+		if (i == -EINTR)
+			return -EINTR;
+		process_fd_request();
+		return i;
+	case FDTWADDLE:
+		if (lock_fdc(drive, true))
+			return -EINTR;
+		twaddle();
+		process_fd_request();
+		return 0;
+	default:
+		return -EINVAL;
+	}
 
 	if (_IOC_DIR(cmd) & _IOC_READ)
 		return fd_copyout((void __user *)param, outparam, size);
-	else
-		return 0;
-#undef OUT
-#undef IN
+
+	return 0;
 }
 
 static void __init config_types(void)
 {
-	int first = 1;
+	bool has_drive = false;
 	int drive;
 
 	/* read drive info out of physical CMOS */
@@ -3655,17 +3627,22 @@
 			name = temparea;
 		}
 		if (name) {
-			const char *prepend = ",";
-			if (first) {
-				prepend = KERN_INFO "Floppy drive(s):";
-				first = 0;
+			const char *prepend;
+			if (!has_drive) {
+				prepend = "";
+				has_drive = true;
+				pr_info("Floppy drive(s):");
+			} else {
+				prepend = ",";
 			}
-			printk("%s fd%d is %s", prepend, drive, name);
+
+			pr_cont("%s fd%d is %s", prepend, drive, name);
 		}
 		*UDP = *params;
 	}
-	if (!first)
-		printk("\n");
+
+	if (has_drive)
+		pr_cont("\n");
 }
 
 static int floppy_release(struct gendisk *disk, fmode_t mode)
@@ -3705,8 +3682,8 @@
 		goto out2;
 
 	if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) {
-		USETF(FD_DISK_CHANGED);
-		USETF(FD_VERIFY);
+		set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
+		set_bit(FD_VERIFY_BIT, &UDRS->flags);
 	}
 
 	if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (mode & FMODE_EXCL)))
@@ -3735,9 +3712,8 @@
 			INFBOUND(try, 16);
 			tmp = (char *)fd_dma_mem_alloc(1024 * try);
 		}
-		if (!tmp && !floppy_track_buffer) {
+		if (!tmp && !floppy_track_buffer)
 			fallback_on_nodma_alloc(&tmp, 2048 * try);
-		}
 		if (!tmp && !floppy_track_buffer) {
 			DPRINT("Unable to allocate DMA memory\n");
 			goto out;
@@ -3767,11 +3743,12 @@
 		if (mode & (FMODE_READ|FMODE_WRITE)) {
 			UDRS->last_checked = 0;
 			check_disk_change(bdev);
-			if (UTESTF(FD_DISK_CHANGED))
+			if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
 				goto out;
 		}
 		res = -EROFS;
-		if ((mode & FMODE_WRITE) && !(UTESTF(FD_DISK_WRITABLE)))
+		if ((mode & FMODE_WRITE) &&
+		    !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags))
 			goto out;
 	}
 	mutex_unlock(&open_lock);
@@ -3795,17 +3772,18 @@
 {
 	int drive = (long)disk->private_data;
 
-	if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
+	if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
+	    test_bit(FD_VERIFY_BIT, &UDRS->flags))
 		return 1;
 
 	if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
-		lock_fdc(drive, 0);
-		poll_drive(0, 0);
+		lock_fdc(drive, false);
+		poll_drive(false, 0);
 		process_fd_request();
 	}
 
-	if (UTESTF(FD_DISK_CHANGED) ||
-	    UTESTF(FD_VERIFY) ||
+	if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
+	    test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
 	    test_bit(drive, &fake_change) ||
 	    (!ITYPE(UDRS->fd_device) && !current_type[drive]))
 		return 1;
@@ -3818,8 +3796,7 @@
  * a disk in the drive, and whether that disk is writable.
  */
 
-static void floppy_rb0_complete(struct bio *bio,
-			       int err)
+static void floppy_rb0_complete(struct bio *bio, int err)
 {
 	complete((struct completion *)bio->bi_private);
 }
@@ -3877,14 +3854,16 @@
 	int cf;
 	int res = 0;
 
-	if (UTESTF(FD_DISK_CHANGED) ||
-	    UTESTF(FD_VERIFY) || test_bit(drive, &fake_change) || NO_GEOM) {
+	if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
+	    test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
+	    test_bit(drive, &fake_change) || NO_GEOM) {
 		if (usage_count == 0) {
-			printk("VFS: revalidate called on non-open device.\n");
+			pr_info("VFS: revalidate called on non-open device.\n");
 			return -EFAULT;
 		}
-		lock_fdc(drive, 0);
-		cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
+		lock_fdc(drive, false);
+		cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
+		      test_bit(FD_VERIFY_BIT, &UDRS->flags));
 		if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) {
 			process_fd_request();	/*already done by another thread */
 			return 0;
@@ -3894,7 +3873,7 @@
 		if (buffer_drive == drive)
 			buffer_track = -1;
 		clear_bit(drive, &fake_change);
-		UCLEARF(FD_DISK_CHANGED);
+		clear_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
 		if (cf)
 			UDRS->generation++;
 		if (NO_GEOM) {
@@ -3902,7 +3881,7 @@
 			res = __floppy_read_block_0(opened_bdev[drive]);
 		} else {
 			if (cf)
-				poll_drive(0, FD_RAW_NEED_DISK);
+				poll_drive(false, FD_RAW_NEED_DISK);
 			process_fd_request();
 		}
 	}
@@ -3934,21 +3913,21 @@
 	output_byte(FD_DUMPREGS);	/* 82072 and better know DUMPREGS */
 	if (FDCS->reset)
 		return FDC_NONE;
-	if ((r = result()) <= 0x00)
+	r = result();
+	if (r <= 0x00)
 		return FDC_NONE;	/* No FDC present ??? */
 	if ((r == 1) && (reply_buffer[0] == 0x80)) {
-		printk(KERN_INFO "FDC %d is an 8272A\n", fdc);
+		pr_info("FDC %d is an 8272A\n", fdc);
 		return FDC_8272A;	/* 8272a/765 don't know DUMPREGS */
 	}
 	if (r != 10) {
-		printk
-		    ("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n",
-		     fdc, r);
+		pr_info("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n",
+			fdc, r);
 		return FDC_UNKNOWN;
 	}
 
 	if (!fdc_configure()) {
-		printk(KERN_INFO "FDC %d is an 82072\n", fdc);
+		pr_info("FDC %d is an 82072\n", fdc);
 		return FDC_82072;	/* 82072 doesn't know CONFIGURE */
 	}
 
@@ -3956,52 +3935,50 @@
 	if (need_more_output() == MORE_OUTPUT) {
 		output_byte(0);
 	} else {
-		printk(KERN_INFO "FDC %d is an 82072A\n", fdc);
+		pr_info("FDC %d is an 82072A\n", fdc);
 		return FDC_82072A;	/* 82072A as found on Sparcs. */
 	}
 
 	output_byte(FD_UNLOCK);
 	r = result();
 	if ((r == 1) && (reply_buffer[0] == 0x80)) {
-		printk(KERN_INFO "FDC %d is a pre-1991 82077\n", fdc);
-		return FDC_82077_ORIG;	/* Pre-1991 82077, doesn't know 
+		pr_info("FDC %d is a pre-1991 82077\n", fdc);
+		return FDC_82077_ORIG;	/* Pre-1991 82077, doesn't know
 					 * LOCK/UNLOCK */
 	}
 	if ((r != 1) || (reply_buffer[0] != 0x00)) {
-		printk("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
-		       fdc, r);
+		pr_info("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
+			fdc, r);
 		return FDC_UNKNOWN;
 	}
 	output_byte(FD_PARTID);
 	r = result();
 	if (r != 1) {
-		printk("FDC %d init: PARTID: unexpected return of %d bytes.\n",
-		       fdc, r);
+		pr_info("FDC %d init: PARTID: unexpected return of %d bytes.\n",
+			fdc, r);
 		return FDC_UNKNOWN;
 	}
 	if (reply_buffer[0] == 0x80) {
-		printk(KERN_INFO "FDC %d is a post-1991 82077\n", fdc);
+		pr_info("FDC %d is a post-1991 82077\n", fdc);
 		return FDC_82077;	/* Revised 82077AA passes all the tests */
 	}
 	switch (reply_buffer[0] >> 5) {
 	case 0x0:
 		/* Either a 82078-1 or a 82078SL running at 5Volt */
-		printk(KERN_INFO "FDC %d is an 82078.\n", fdc);
+		pr_info("FDC %d is an 82078.\n", fdc);
 		return FDC_82078;
 	case 0x1:
-		printk(KERN_INFO "FDC %d is a 44pin 82078\n", fdc);
+		pr_info("FDC %d is a 44pin 82078\n", fdc);
 		return FDC_82078;
 	case 0x2:
-		printk(KERN_INFO "FDC %d is a S82078B\n", fdc);
+		pr_info("FDC %d is a S82078B\n", fdc);
 		return FDC_S82078B;
 	case 0x3:
-		printk(KERN_INFO "FDC %d is a National Semiconductor PC87306\n",
-		       fdc);
+		pr_info("FDC %d is a National Semiconductor PC87306\n", fdc);
 		return FDC_87306;
 	default:
-		printk(KERN_INFO
-		       "FDC %d init: 82078 variant with unknown PARTID=%d.\n",
-		       fdc, reply_buffer[0] >> 5);
+		pr_info("FDC %d init: 82078 variant with unknown PARTID=%d.\n",
+			fdc, reply_buffer[0] >> 5);
 		return FDC_82078_UNKN;
 	}
 }				/* get_fdc_version */
@@ -4113,9 +4090,9 @@
 				else
 					param = config_params[i].def_param;
 				if (config_params[i].fn)
-					config_params[i].
-					    fn(ints, param,
-					       config_params[i].param2);
+					config_params[i].fn(ints, param,
+							    config_params[i].
+							    param2);
 				if (config_params[i].var) {
 					DPRINT("%s=%d\n", str, param);
 					*config_params[i].var = param;
@@ -4129,8 +4106,8 @@
 
 		DPRINT("allowed options are:");
 		for (i = 0; i < ARRAY_SIZE(config_params); i++)
-			printk(" %s", config_params[i].name);
-		printk("\n");
+			pr_cont(" %s", config_params[i].name);
+		pr_cont("\n");
 	} else
 		DPRINT("botched floppy option\n");
 	DPRINT("Read Documentation/blockdev/floppy.txt\n");
@@ -4148,7 +4125,8 @@
 	drive = p->id;
 	return sprintf(buf, "%X\n", UDP->cmos);
 }
-DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
+
+DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL);
 
 static void floppy_device_release(struct device *dev)
 {
@@ -4160,7 +4138,7 @@
 
 	for (fdc = 0; fdc < N_FDC; fdc++)
 		if (FDCS->address != -1)
-			user_reset_fdc(-1, FD_RESET_ALWAYS, 0);
+			user_reset_fdc(-1, FD_RESET_ALWAYS, false);
 
 	return 0;
 }
@@ -4172,8 +4150,8 @@
 
 static struct platform_driver floppy_driver = {
 	.driver = {
-		.name = "floppy",
-		.pm = &floppy_pm_ops,
+		   .name = "floppy",
+		   .pm = &floppy_pm_ops,
 	},
 };
 
@@ -4245,16 +4223,16 @@
 		else
 			floppy_sizes[i] = MAX_DISK_SIZE << 1;
 
-	reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
+	reschedule_timeout(MAXTIMEOUT, "floppy init");
 	config_types();
 
 	for (i = 0; i < N_FDC; i++) {
 		fdc = i;
-		CLEARSTRUCT(FDCS);
+		memset(FDCS, 0, sizeof(*FDCS));
 		FDCS->dtr = -1;
 		FDCS->dor = 0x4;
 #if defined(__sparc__) || defined(__mc68000__)
-		/*sparcs/sun3x don't have a DOR reset which we can fall back on to */
+	/*sparcs/sun3x don't have a DOR reset which we can fall back on to */
 #ifdef __mc68000__
 		if (MACH_IS_SUN3X)
 #endif
@@ -4283,11 +4261,11 @@
 
 	/* initialise drive state */
 	for (drive = 0; drive < N_DRIVE; drive++) {
-		CLEARSTRUCT(UDRS);
-		CLEARSTRUCT(UDRWE);
-		USETF(FD_DISK_NEWCHANGE);
-		USETF(FD_DISK_CHANGED);
-		USETF(FD_VERIFY);
+		memset(UDRS, 0, sizeof(*UDRS));
+		memset(UDRWE, 0, sizeof(*UDRWE));
+		set_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags);
+		set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
+		set_bit(FD_VERIFY_BIT, &UDRS->flags);
 		UDRS->fd_device = -1;
 		floppy_track_buffer = NULL;
 		max_buffer_sectors = 0;
@@ -4307,7 +4285,7 @@
 		if (FDCS->address == -1)
 			continue;
 		FDCS->rawcmd = 2;
-		if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) {
+		if (user_reset_fdc(-1, FD_RESET_ALWAYS, false)) {
 			/* free ioports reserved by floppy_grab_irq_and_dma() */
 			floppy_release_regions(fdc);
 			FDCS->address = -1;
@@ -4330,12 +4308,12 @@
 		 * properly, so force a reset for the standard FDC clones,
 		 * to avoid interrupt garbage.
 		 */
-		user_reset_fdc(-1, FD_RESET_ALWAYS, 0);
+		user_reset_fdc(-1, FD_RESET_ALWAYS, false);
 	}
 	fdc = 0;
 	del_timer(&fd_timeout);
 	current_drive = 0;
-	initialising = 0;
+	initialized = true;
 	if (have_no_fdc) {
 		DPRINT("no floppy controllers found\n");
 		err = have_no_fdc;
@@ -4356,7 +4334,8 @@
 		if (err)
 			goto out_flush_work;
 
-		err = device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
+		err = device_create_file(&floppy_device[drive].dev,
+					 &dev_attr_cmos);
 		if (err)
 			goto out_unreg_platform_dev;
 
@@ -4420,8 +4399,10 @@
 	const struct io_region *p;
 
 	for (p = io_regions; p < ARRAY_END(io_regions); p++) {
-		if (!request_region(FDCS->address + p->offset, p->size, "floppy")) {
-			DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address + p->offset);
+		if (!request_region(FDCS->address + p->offset,
+				    p->size, "floppy")) {
+			DPRINT("Floppy io-port 0x%04lx in use\n",
+			       FDCS->address + p->offset);
 			floppy_release_allocated_regions(fdc, p);
 			return -EBUSY;
 		}
@@ -4512,11 +4493,9 @@
 static void floppy_release_irq_and_dma(void)
 {
 	int old_fdc;
-#ifdef FLOPPY_SANITY_CHECK
 #ifndef __sparc__
 	int drive;
 #endif
-#endif
 	long tmpsize;
 	unsigned long tmpaddr;
 	unsigned long flags;
@@ -4547,20 +4526,18 @@
 		buffer_min = buffer_max = -1;
 		fd_dma_mem_free(tmpaddr, tmpsize);
 	}
-#ifdef FLOPPY_SANITY_CHECK
 #ifndef __sparc__
 	for (drive = 0; drive < N_FDC * 4; drive++)
 		if (timer_pending(motor_off_timer + drive))
-			printk("motor off timer %d still active\n", drive);
+			pr_info("motor off timer %d still active\n", drive);
 #endif
 
 	if (timer_pending(&fd_timeout))
-		printk("floppy timer still active:%s\n", timeout_message);
+		pr_info("floppy timer still active:%s\n", timeout_message);
 	if (timer_pending(&fd_timer))
-		printk("auxiliary floppy timer still active\n");
+		pr_info("auxiliary floppy timer still active\n");
 	if (work_pending(&floppy_work))
-		printk("work still pending\n");
-#endif
+		pr_info("work still pending\n");
 	old_fdc = fdc;
 	for (fdc = 0; fdc < N_FDC; fdc++)
 		if (FDCS->address != -1)
@@ -4577,7 +4554,9 @@
 	char *ptr;
 
 	while (*cfg) {
-		for (ptr = cfg; *cfg && *cfg != ' ' && *cfg != '\t'; cfg++) ;
+		ptr = cfg;
+		while (*cfg && *cfg != ' ' && *cfg != '\t')
+			cfg++;
 		if (*cfg) {
 			*cfg = '\0';
 			cfg++;
@@ -4625,6 +4604,7 @@
 	/* eject disk, if any */
 	fd_eject(0);
 }
+
 module_exit(floppy_module_exit);
 
 module_param(floppy, charp, 0);
@@ -4636,9 +4616,10 @@
 
 /* This doesn't actually get used other than for module information */
 static const struct pnp_device_id floppy_pnpids[] = {
-	{ "PNP0700", 0 },
-	{ }
+	{"PNP0700", 0},
+	{}
 };
+
 MODULE_DEVICE_TABLE(pnp, floppy_pnpids);
 
 #else
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c
index a808b15..eb2091a 100644
--- a/drivers/block/osdblk.c
+++ b/drivers/block/osdblk.c
@@ -476,7 +476,9 @@
 	kfree(cls);
 }
 
-static ssize_t class_osdblk_list(struct class *c, char *data)
+static ssize_t class_osdblk_list(struct class *c,
+				struct class_attribute *attr,
+				char *data)
 {
 	int n = 0;
 	struct list_head *tmp;
@@ -500,7 +502,9 @@
 	return n;
 }
 
-static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count)
+static ssize_t class_osdblk_add(struct class *c,
+				struct class_attribute *attr,
+				const char *buf, size_t count)
 {
 	struct osdblk_device *osdev;
 	ssize_t rc;
@@ -592,7 +596,9 @@
 	return rc;
 }
 
-static ssize_t class_osdblk_remove(struct class *c, const char *buf,
+static ssize_t class_osdblk_remove(struct class *c,
+					struct class_attribute *attr,
+					const char *buf,
 					size_t count)
 {
 	struct osdblk_device *osdev = NULL;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index b72935b8..39c8514 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -284,7 +284,7 @@
 	return len;
 }
 
-static struct sysfs_ops kobj_pkt_ops = {
+static const struct sysfs_ops kobj_pkt_ops = {
 	.show = kobj_pkt_show,
 	.store = kobj_pkt_store
 };
@@ -337,7 +337,9 @@
 {
 	kfree(cls);
 }
-static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
+static ssize_t class_pktcdvd_show_map(struct class *c,
+					struct class_attribute *attr,
+					char *data)
 {
 	int n = 0;
 	int idx;
@@ -356,7 +358,9 @@
 	return n;
 }
 
-static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
+static ssize_t class_pktcdvd_store_add(struct class *c,
+					struct class_attribute *attr,
+					const char *buf,
 					size_t count)
 {
 	unsigned int major, minor;
@@ -376,7 +380,9 @@
 	return -EINVAL;
 }
 
-static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf,
+static ssize_t class_pktcdvd_store_remove(struct class *c,
+					  struct class_attribute *attr,
+					  const char *buf,
 					size_t count)
 {
 	unsigned int major, minor;
diff --git a/drivers/char/ChangeLog b/drivers/char/ChangeLog
deleted file mode 100644
index 56b8a2e..0000000
--- a/drivers/char/ChangeLog
+++ /dev/null
@@ -1,775 +0,0 @@
-2001-08-11  Tim Waugh  <twaugh@redhat.com>
-
-	* serial.c (get_pci_port): Deal with awkward Titan cards.
-
-1998-08-26  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* serial.c (rs_open): Correctly decrement the module in-use count
-		on errors.
-
-Thu Feb 19 14:24:08 1998  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* tty_io.c (tty_name): Remove the non-reentrant (and non-SMP safe)
-		version of tty_name, and rename the reentrant _tty_name
-		function to be tty_name.
-		(tty_open): Add a warning message stating callout devices
-		are deprecated.
-
-Mon Dec  1 08:24:15 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* tty_io.c (tty_get_baud_rate): Print a warning syslog if the
-		tty->alt_speed kludge is used; this means the system is
-		using the deprecated SPD_HI ioctls.
-
-Mon Nov 24 10:37:49 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* serial.c, esp.c, rocket.c: Change drivers to take advantage of
-	 	tty_get_baud_rate().
-	
-	* tty_io.c (tty_get_baud_rate): New function which computes the
-		correct baud rate for the tty.  More factoring out of
-		common code out of the serial driver to the high-level tty
-		functions....
-
-Sat Nov 22 07:53:36 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* serial.c, esp.c, rocket.c: Add tty->driver.break() routine, and
- 		allow high-level tty code to handle the break and soft
- 		carrier ioctls.
-	
-	* tty_ioctl.c (n_tty_ioctl): Support TIOCGSOFTCAR and
- 		TIOCSSOFTCAR, so that device drivers don't have to support
- 		it.
-
-	* serial.c (autoconfig): Change 16750 test to hopefully eliminate
-		false results by people with strange 16550As being
-		detected as 16750s.  Hopefully 16750s will still be
-		detected as 16750, and other weird UARTs won't get poorly
-		autodetected.  If this doesn't work, I'll have to disable
-		the auto identification for the 16750.
-
-	* tty_io.c (tty_hangup): Now actually do the tty hangup
-		processing during the timer processing, and disable
-		interrupts while doing the hangup processing.  This avoids
-		several nasty race conditions which happened when the
-		hangup processing was done asynchronously.
-		(tty_ioctl): Do break handling in the tty driver if
-		driver's break function is supported.  
-		(tty_flip_buffer_push): New exported function which should
-		be used by drivers to push characters in the flip buffer
-		to the tty handler.  This may either be done using a task
-		queue function for better CPU efficiency, or directly for
-		low latency operation.
-
-	* serial.c (rs_set_termios): Fix bug rs_set_termios when
-		transitioning away from B0, submitted by Stanislav
-		Voronyi. 
-
-Thu Jun 19 20:05:58 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* serial.c (begin_break, end_break, rs_ioctl): Applied patch
-		to support BSD ioctls to set and clear the break
-		condition explicitly.
-
-	* console.c (scrup, scrdown, insert_line, delete_line): Applied
-		fix suggested by Aaron Tiensivu to speed up block scrolls
-		up and down.
-
-	* n_tty.c (opost_block, write_chan): Added a modified "fast
- 		console" patch which processes a block of text via
-		"cooking" efficiently.
-
-Wed Jun 18 15:25:50 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* tty_io.c (init_dev, release_dev): Applied fix suggested by Bill
-		Hawes to prevent race conditions in the tty code.
-
-	* n_tty.c (n_tty_chars_in_buffer): Applied fix suggested by Bill
-		Hawes so that n_tty_chars_in_buffer returns the correct
-		value in the case when the tty is in cannonical mode.  (To
-		avoid a pty deadlock with telnetd.)
-
-Thu Feb 27 01:53:08 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* serial.c (change_speed): Add support for the termios flag
-		CMSPAR, which allows the user to select stick parity.
-		(i.e, if PARODD is set, the parity bit is always 1; if
-		PARRODD is not set, then the parity bit is always 0).
-
-Wed Feb 26 19:03:10 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* serial.c (cleanup_module): Fix memory leak when using the serial
-		driver as a module; make sure tmp_buf gets freed!
-
-Tue Feb 25 11:01:59 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* serial.c (set_modem_info): Add support for setting and clearing
-		the OUT1 and OUT2 bits.  (For special case UART's, usually
-		for half-duplex.)
-		(autoconfig, change_speed): Fix TI 16750 support.
-
-Sun Feb 16 00:14:43 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* tty_io.c (release_dev): Add sanity check to make sure there are
-		no waiters on tty->read_wait or tty->write_wait.
-
-	* serial.c (rs_init): Don't autoconfig a device if the I/O region
-		is already reserved.
-
-	* serial.c (serial_proc_info): Add support for /proc/serial.
-
-Thu Feb 13 00:49:10 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* serial.c (receive_chars): When the UART repotrs an overrun
- 		condition, it does so with a valid character.  Changed to
- 		not throw away the valid character, but instead report the
-		overrun after the valid character.
-
-	* serial.c: Added new #ifdef's for some of the advanced serial
-		driver features.  A minimal driver that only supports COM
-		1/2/3/4 without sharing serial interrupts only takes 17k;
-		the full driver takes 32k.
-		
-Wed Feb 12 14:50:44 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* vt.c:
-	* pty.c: 
-	* tty_ioctl.c: 
-	* serial.c: Update routines to use the new 2.1 memory access
-	 	routines.
-
-Wed Dec  4 07:51:52 1996  Theodore Ts'o  <tytso@localhost.mit.edu>
-
-	* serial.c (change_speed): Use save_flags(); cli() and
-		restore_flags() in order to ensure we don't accidentally
-		turn on interrupts when starting up the port.
-		(startup): Move the insertion of serial structure into the
-		IRQ chain earlier into the startup processing.  Interrupts
-		should be off this whole time, but we eventually will want
-		to reduce this window.
-
-Thu Nov 21 10:05:22 1996  Theodore Ts'o  <tytso@localhost.mit.edu>
-
-	* tty_ioctl.c (tty_wait_until_sent): Always check the driver
- 		wait_until_ready routine, even if there are no characters
- 		in the xmit buffer.  (There may be charactes in the device
- 		FIFO.)
-		(n_tty_ioctl): Add new flag tty->flow_stopped which
- 		indicates whether the tty is stopped due to a request by
- 		the TCXONC ioctl (used by tcflow).  If so, don't let an
- 		incoming XOFF character restart the tty.  The tty can only
- 		be restarted by another TCXONC request.
-
-	* tty_io.c (start_tty): Don't allow the tty to be restarted if
-		tty->flow_stopped is true.
-
-	* n_tty.c (n_tty_receive_char): If tty->flow_stopped is true, and
- 		IXANY is set, don't eat a character trying to restart the
- 		tty.
-
-	* serial.c (startup): Remove need for MCR_noint from the
- 		async_struct structure.  Only turn on DTR and RTS if the
- 		baud rate is not zero.
-		(change_speed): More accurately calculate the timeout
- 		value based on the word size.  Move responsibility of
- 		hangup when speed becomes B0 to rs_set_termios()
-		(set_serial_info): When changing the UART type set the
- 		current xmit_fifo_size as well as the permanent
- 		xmit_fifo_size.
-		(rs_ioctl): Fix TCSBRK (used by tcdrain) and TCSBRKP
- 		ioctls to return EINTR if interrupted by a signal.
-		(rs_set_termios): If the baud rate changes to or from B0,
- 		this function is now responsible for setting or clearing
- 		DTR and RTS.  DTR and RTS are only be changed on the
- 		transition to or from the B0 state.
-		(rs_close): Wait for the characters to drain based on
- 		info->timeout.  At low baud rates (50 bps), it may take a
- 		long time for the FIFO to completely drain out!
-		(rs_wait_until_sent): Fixed timeout handling.  Now
- 		releases control to the scheduler, but checks frequently
- 		enough so that the function is sensitive enough to pass
- 		the timing requirements of the NIST-PCTS.
-		(block_til_ready): When opening the device, don't turn on
- 		DTR and RTS if the baud rate is B0.
-
-Thu Nov 14 00:06:09 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* serial.c (autoconfig): Fix autoconfiguration problems;
-		info->flags wasn't getting initialized from the state
-		structure.  Put in more paranoid test for the 16750.
-
-Fri Nov  8 20:19:50 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* n_tty.c (n_tty_flush_buffer): Only call driver->unthrottle() if
- 		the tty was previous throttled.
-		(n_tty_set_termios, write_chan): Add changes suggested by
- 			Simon P. Allen to allow hardware cooking.
-
-	* tty_ioctl.c (set_termios): If we get a signal while waiting for
-		the tty to drain, return -EINTR.
-	
-	* serial.c (change_speed): Add support for CREAD, as required by
-	 	POSIX.
-
-Sat Nov  2 20:43:10 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* serial.c: Wholesale changes.  Added support for the Startech
- 		16650 and 16650V2 chips.  (WARNING: the new startech
- 		16650A may or may not work!)  Added support for the
- 		TI16750 (not yet tested).  Split async_struct into a
- 		transient part (async_struct) and a permanent part
-		(serial_state) which contains the configuration
- 		information for the ports.  Added new driver routines
- 		wait_until_sent() and send_xchar() to help with POSIX
- 		compliance.  Added support for radio clocks which waggle
-		the carrier detect line (CONFIG_HARD_PPS).
-	
-	* tty_ioctl.c (tty_wait_until_sent): Added call to new driver
-		function tty->driver.wait_until_sent(), which returns when
-		the tty's device xmit buffers are drained.  Needed for
-		full POSIX compliance.
-
-		(send_prio_char): New function, called by the ioctl's
-		TCIOFF and TCION; uses the new driver call send_xchar(),
-		which will send the XON or XOFF character at high priority
-		(and even if tty output is stopped).
-
-Wed Jun  5 18:52:04 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* pty.c (pty_close): When closing a pty, make sure packet mode is
-	 	cleared.
-
-Sun May 26 09:33:52 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* vesa_blank.c (set_vesa_blanking): Add missing verify_area() call.
-
-	* selection.c (set_selection): Add missing verify_area() call.
-
-	* tty_io.c (tty_ioctl): Add missing verify_area() calls.
-
-	* serial.c (rs_ioctl): Add missing verify_area() calls.
-		(rs_init): Allow initialization of serial driver
-		configuration from a module.
-
-	* random.c (extract_entropy): Add missing verify_area call.
-		Don't limit number of characters returned to
-		32,768. Extract entropy is now no longer a inlined
-		function.
-
-		(random_read): Check return value in case extract_entropy
-		returns an error.
-
-		(secure_tcp_sequence_number): New function which returns a
-		secure TCP sequence number.  This is needed to prevent some
-		nasty TCP hijacking attacks.
-	
-		(init_std_data): Initialize using gettimeofday() instead of
-		struct timeval xtime.
-
-		(fast_add_entropy_word, add_entropy_word): Rename the
-		inline function add_entropy_word() to
-		fast_add_entropy_word().  Make add_entropy_word() be the
-		non-inlined function which is used in non-timing critical
-		places, in order to save space.
-
-		(initialize_benchmark, begin_benchmark, end_benchmark): New
-		functions defined when RANDOM_BENCHMARK is defined.  They
-		allow us to benchmark the speed of the
-		add_timer_randomness() call.
-
-		(int_ln, rotate_left): Add two new inline functions with
-		i386 optimized asm instructions.  This speeds up the
-		critical add_entropy_word() and add_timer_randomness()
-		functions, which are called from interrupt handlers.
-
-Tue May  7 22:51:11 1996    <tytso@rsts-11.mit.edu>
-
-	* random.c (add_timer_randomness): Limit the amount randomness
-		that we estimate to 12 bits.  (An arbitrary amount).
-
-		(extract_entropy): To make it harder to analyze the hash
-		function, fold the hash function in half using XOR, and
-		use the folded result as the value to emit to the user.
-		Also, add timer randomness each pass through the
-		exact_entropy call, to increase the amount of unknown
-		values during the extraction process.
-
-		(random_ioctl): Use IOR/IOW definitions to define the
-		ioctl values used by the /dev/random driver.  Allow the
-		old ioctl values to be used for backwards compatibility
-		(for a limited amount of time).
-
-Wed Apr 24 14:02:04 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
-
-	* random.c (add_timer_randomness): Use 2nd derivative as well to
-		better estimate entropy.
-
-		(rand_initialize): Explicitly initialize all the pointers
-		to NULL.  (Clearing pointers using memset isn't portable.)
-		Initialize the random pool with OS-dependent data.
-
-		(random_write): Add sanity checking to the arguments to
-		random_write(), so that bad arguments won't cause a kernel
-		SEGV. 
-
-		(random_read): Update the access time of the device inode
-		when you return data to the user.
-
-		(random_ioctl): Wake up the random_wait channel when there
-		are only WAIT_INPUT_BITS available.  Add more paranoia
-		checks to make sure entropy_count doesn't go beyond the
-		bounds of (0, POOLSIZE).  Add a few missing verify_area
-		checks.  Add support for the RNDCLEARPOOL ioctl, which
-		zaps the random pool.
-
-		(add_timer_randomness): Wake up the random_wait
-		channel only when there are WAIT_INPUT_BITS available.
-
-		(random_select): Allow a random refresh daemon process to
-		select on /dev/random for writing; wake up the daemon when
-		there are less than WAIT_OUTPUT_BITS bits of randomness
-		available.
-
-Tue Apr 23 22:56:07 1996    <tytso@rsts-11.mit.edu>
-
-	* tty_io.c (init_dev): Change return code when user attempts to
-		open master pty which is already open from EAGAIN to EIO,
-		to match with BSD expectations.  EIO is more correct
-		anyway, since EAGAIN implies that retrying will be
-		successful --- which it might be.... Eventually!!
-
-	* pty.c (pty_open, pty_close): Fix wait loop so that we don't
-		busy loop while waiting for the master side to open.
-		Fix tty opening/closing logic.  TTY_SLAVE_CLOSED was
-		renamed to TTY_OTHER_CLOSED, so that the name is more
-		descriptive.  Also fixed code so that the tty flag
-		actually works correctly now....
-
-Mon Apr  1 10:22:01 1996    <tytso@rsts-11.mit.edu>
-
-	* serial.c (rs_close): Cleaned up modularization changes.
-		Remove code which forced line discipline back to N_TTY
-		this is done in the tty upper layers, and there's no
-		reason to do it here.  (Making this change also
-		removed the requirement that the serial module access
-		the internal kernel symbol "ldiscs".)
-
-	* tty_io.c (tty_init): Formally register a tty_driver entry for
-		/dev/tty (device 4, 0) and /dev/console (device 5, 0).
-		This guarantees that major device numbers 4 and 5 will be
-		reserved for the tty subsystem (as they have to be because
-		of /dev/tty and /dev/console).  Removed tty_regdev, as
-		this interface is no longer necessary.
-
-Sun Mar 17 20:42:47 GMT 1996 <ah@doc.ic.ac.uk>
-
-	* serial.c : modularisation (changes in linux/fs/device.c allow
-		kerneld to automatically load the serial module).
-
-	* Makefile, Config.in : serial modularisation adds.
-
-	* tty_io.c : tty_init_ctty used by to register "cua" driver just
-		for the /dev/tty device (5,0).  Added tty_regdev.
-	
-	* serial.c (shutdown, rs_ioctl) : when port shuts down wakeup processes
-	  waiting on delta_msr_wait. The TIOCMIWAIT ioctl returns EIO
-	  if no change was done since the time of call.
-
-Sat Mar 16 14:33:13 1996 <aeb@cwi.nl>
-
-	* tty_io.c (disassociate_ctty): If disassociate_ctty is called by
-		exit, do not perform an implicit vhangup on a pty.
-
-Fri Feb  9 14:15:47 1996    <tytso@rsts-11.mit.edu>
-
-	* serial.c (block_til_ready): Fixed another race condition which
-		happens if a hangup happens during the open.
-
-Wed Jan 10 10:08:00 1996    <tytso@rsts-11.mit.edu>
-
-	* serial.c (block_til_ready): Remove race condition which happened
-		if a hangup condition happened during the setup of the
-		UART, before rs_open() called block_til_ready().  This
-		caused the info->count counter to be erroneously
-		decremented.
-
-	* serial.c (startup, rs_open): Remove race condition that could
-		cause a memory leak of one page.  (Fortunately, both race
-		conditions were relatively rare in practice.)
-
-Tue Dec  5 13:21:27 1995    <tytso@rsts-11.mit.edu>
-
-	* serial.c (check_modem_status, rs_ioctl): Support the new
-		ioctl()'s TIOCGICOUNT, TIOCMIWAIT.  These allow an
-		application program to wait on a modem serial register
-		status bit change, and to find out how many changes have
-		taken place for the MSR bits.
-
-		(rs_write): Eliminate a race condition which is introduced
-		if it is necessary to wait for the semaphore.
-
-Sat Nov  4 17:14:45 1995    <tytso@rsts-11.mit.edu>
-
-	* tty_io.c (tty_init): Move registration of TTY_MAJOR and
-		TTY_AUX_MAJOR to the end, so that /proc/devices looks
-		prettier. 
-
-	* pty.c (pty_init): Use new major numbers for PTY master and slave
-		devices.  This allow us to have more than 64 pty's.  We
-		register the old pty devices for backwards compatibility.
-		Note that a system should either be using the old pty
-		devices or the new pty devices --- in general, it should
-		try to use both, since they map into the same pty table.
-		The old pty devices are strictly for backwards compatibility.
-
-Wed Oct 11 12:45:24 1995    <tytso@rsts-11.mit.edu>
-
-	* tty_io.c (disassociate_ctty): If disassociate_ctty is called by
-		exit, perform an implicit vhangup on the tty.
-
-	* pty.c (pty_close): When the master pty is closed, send a hangup
-		to the slave pty.
-		(pty_open): Use the flag TTY_SLAVE_CLOSED to test to see
-		if there are any open slave ptys, instead of using
-		tty->link->count.  The old method got confused if there
-		were processes that had hung-up file descriptors on the
-		slave tty.
-
-Tue May  2 00:53:25 1995    <tytso@rsx-11.mit.edu>
-
-	* tty_io.c (tty_set_ldisc): Wait until the output buffer is
-		drained before closing the old line discipline --- needed
-		in only one case: XON/XOFF processing.
-
-	* n_tty.c (n_tty_close): Don't bother waiting until the output
-		driver is closed; in general, the line discipline
-		shouldn't care if the hardware is finished
-		transmitting before the line discipline terminates.
-
-	* tty_io.c (release_dev): Shutdown the line discipline after
-		decrementing the tty count variable; but set the
-		TTY_CLOSING flag so that we know that this tty structure
-		isn't long for this world.
-
-	* tty_io.c (init_dev): Add sanity code to check to see if
-		TTY_CLOSING is set on a tty structure; if so, something
-		bad has happened (probably a line discipline close blocked
-		when it shouldn't have; so do a kernel printk and then
-		return an error).
-
-Wed Apr 26 10:23:44 1995  Theodore Y. Ts'o  <tytso@localhost>
-
-	* tty_io.c (release_dev): Try to shutdown the line discipline
-		*before* decrementing the tty count variable; this removes
-		a potential race condition which occurs when the line
-		discipline close blocks, and another process then tries
-		open the same serial port.
-
-	* serial.c (rs_hangup): When hanging up, flush the output buffer
-		before shutting down the UART.  Otherwise the line
-		discipline close blocks waiting for the characters to get
-		flushed, which never happens until the serial port gets reused.
-
-Wed Apr 12 08:06:16 1995  Theodore Y. Ts'o  <tytso@localhost>
-
-	* serial.c (do_serial_hangup, do_softint, check_modem_status,
-		rs_init):  Hangups are now scheduled via a separate tqueue
-		structure in the async_struct structure, tqueue_hangup.
-		This task is pushed on to the tq_schedule queue, so that
-		it is processed synchronously by the scheduler.
-
-Sat Feb 18 12:13:51 1995  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_io.c (disassociate_ctty, tty_open, tty_ioctl): Clear
-		current->tty_old_pgrp field when a session leader
-		acquires a controlling tty, and after a session leader
-		has disassociated from a controlling tty.
-
-Fri Feb 17 09:34:09 1995  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (rs_interrupt_single, rs_interrupt, rs_interrupt_multi): 
-		Change the number of passes made from 64 to be 256,
-		configurable with the #define RS_ISR_PASS_LIMIT.
-
-	* serial.c (rs_init, set_serial_info, get_serial_info, rs_close):
-		Remove support for closing_wait2.  Instead, set
-		tty->closing and rely on the line discipline to prevent
-		echo wars.
-
-	* n_tty.c (n_tty_receive_char):  IEXTEN does not need to be
-		enabled in order for IXANY to be active.
-
-		If tty->closing is set, then only process XON and XOFF
-                characters.
-
-Sun Feb 12 23:57:48 1995  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (rs_timer): Change the interrupt poll time from 60
-		seconds to 10 seconds, configurable with the #define
-		RS_STROBE_TIME.
-
-	* serial.c (rs_interrupt_multi, startup, shutdown, rs_ioctl,
-		set_multiport_struct, get_multiport_struct): Add
-		provisions for a new type of interrupt service routine,
-		which better supports multiple serial ports on a single
-		IRQ.  
-
-Sun Feb  5 19:35:11 1995  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_ioctl.c (n_tty_ioctl, set_termios, tty_wait_until_sent): 
-	* serial.c (rs_ioctl, rs_close): 
-	* cyclades.c (cy_ioctl, cy_close): 
-	* n_tty.c (n_tty_close):  Rename wait_until_sent to
-		tty_wait_until_sent, so that it's a better name to export
-		in ksyms.c.
-
-Sat Feb  4 23:36:20 1995  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (rs_close): Added missing check for closing_wait2 being
-		ASYNC_CLOSING_WAIT_NONE.
-
-Thu Jan 26 09:02:49 1995  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (rs_init, set_serial_info, get_serial_info,
-		rs_close): Support close_wait in the serial driver.
-		This is helpful for slow devices (like serial
-		plotters) so that their outputs don't get flushed upon
-		device close.  This has to be configurable because
-		normally we don't want ports to be hung up for long
-		periods of time during a close when they are not
-		connected to a device, or the device is powered off.
-
-		The default is to wait 30 seconds; in the case of a
-		very slow device, the close_wait timeout should be
-		lengthened.  If it is set to 0, the kernel will wait
-		forever for all of the data to be transmitted.
-
-Thu Jan 17 01:17:20 1995  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (startup, change_speed, rs_init): Add support to detect
-		the StarTech 16650 chip.  Treat it as a 16450 for now,
-		because of its FIFO bugs.
-
-Thu Jan  5 21:21:57 1995  <dahinds@users.sourceforge.net>
-
-	* serial.c: (receive_char): Added counter to prevent infinite loop
-		when a PCMCIA serial device is ejected.
-
-Thu Dec 29 17:53:48 1994    <tytso@rsx-11.mit.edu>
-
-	* tty_io.c (check_tty_count): New procedure which checks
-		tty->count to make sure that it matches with the number of
-		open file descriptors which point at the structure.  If
-		the number doesn't match, it prints a warning message.
-
-Wed Dec 28 15:41:51 1994    <tytso@rsx-11.mit.edu>
-
-	* tty_io.c (do_tty_hangup, disassociate_ctty): At hangup time,
-		save the tty's current foreground process group in the
-		session leader's task structure.  When the session leader
-		terminates, send a SIGHUP, SIGCONT to that process group.
-		This is not required by POSIX, but it's not prohibited
-		either, and it appears to be the least intrusive way
-		to fix a problem that dialup servers have with
-		orphaned process groups caused by modem hangups.
-
-Thu Dec  8 14:52:11 1994    <tytso@rsx-11.mit.edu>
-
-	* serial.c (rs_ioctl): Don't allow most ioctl's if the serial port
-		isn't initialized.
-
-	* serial.c (rs_close): Don't clear the IER if the serial port
-		isn't initialized. 
-
-	* serial.c (block_til_ready): Don't try to block on the dialin
-		port if the serial port isn't initialized.
-
-Wed Dec  7 10:48:30 1994  Si Park (si@wimpol.demon.co.uk)
-	* tty_io.c (tty_register_driver): Fix bug when linking onto
-		the tty_drivers list. We now test that there are elements
-		already on the list before setting the back link from the
-		first element to the new driver.
-
-	* tty_io.c (tty_unregister_driver): Fix bug in unlinking the
-		specified driver from the tty_drivers list. We were not
-		setting the back link correctly. This used to result in
-		a dangling back link pointer and cause panics on the next
-		call to get_tty_driver().
-
-Tue Nov 29 10:21:09 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_io.c (tty_unregister_driver): Fix bug in
-		tty_unregister_driver where the pointer to the refcount is
-		tested, instead of the refcount itself.  This caused
-		tty_unregister_driver to always return EBUSY.
-
-Sat Nov 26 11:59:24 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_io.c (tty_ioctl): Add support for the new ioctl
-		TIOCTTYGSTRUCT, which allow a kernel debugging program
-		direct read access to the tty and tty_driver structures.
-
-Fri Nov 25 17:26:22 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (rs_set_termios): Don't wake up processes blocked in
-		open when the CLOCAL flag changes, since a blocking
-		open only samples the CLOCAL flag once when it blocks,
-		and doesn't check it again.  (n.b.  FreeBSD has a
-		different behavior for blocking opens; it's not clear
-		whether Linux or FreeBSD's interpretation is correct.
-		POSIX doesn't give clear guidance on this issue, so
-		this may change in the future....)
-
-	* serial.c (block_til_ready): Use the correct termios structure to
-		check the CLOCAL flag.  If the cuaXX device is active,
-		then check the saved termios for the ttySXX device.
-		Otherwise, use the currently active termios structure.
-
-Sun Nov  6 21:05:44 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (change_speed): Add support for direct access of
-		57,600 and 115,200 bps.
-
-Wed Nov  2 10:32:36 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* n_tty.c (n_tty_receive_room): Only allow excess characters
-		through if we are in ICANON mode *and* there are other no
-		pending lines in the buffer.  Otherwise cut and paste over
-		4k breaks.
-
-Sat Oct 29 18:17:34 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (rs_ioctl, get_lsr_info): Added patch suggested by Arne
-		Riiber so that user mode programs can tell when the
-		transmitter shift register is empty.
-
-Thu Oct 27 23:14:29 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_ioctl.c (wait_until_sent): Added debugging printk statements
-		(under the #ifdef TTY_DEBUG_WAIT_UNTIL_SENT)  
-
-	* serial.c (rs_interrupt, rs_interrupt_single, receive_chars,
-		change_speed, rs_close): rs_close now disables receiver
-		interrupts when closing the serial port.  This allows the
-		serial port to close quickly when Linux and a modem (or a
-		mouse) are engaged in an echo war; when closing the serial
-		port, we now first stop listening to incoming characters,
-		and *then* wait for the transmit buffer to drain.  
-
-		In order to make this change, the info->read_status_mask
-		is now used to control what bits of the line status
-		register are looked at in the interrupt routine in all
-		cases; previously it was only used in receive_chars to
-		select a few of the status bits.
-
-Mon Oct 24 23:36:21 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (rs_close): Add a timeout to the transmitter flush
-		loop; this is just a sanity check in case we have flaky
-		(or non-existent-but-configured-by-the-user) hardware.
-
-Fri Oct 21 09:37:23 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_io.c (tty_fasync): When asynchronous I/O is enabled, if the
-		process or process group has not be specified yet, set it
-		to be the tty's process group, or if that is not yet set,
-		to the current process's pid.
-
-Thu Oct 20 23:17:28 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* n_tty.c (n_tty_receive_room): If we are doing input
-		canonicalization, let as many characters through as
-		possible, so that the excess characters can be "beeped".
-
-Tue Oct 18 10:02:43 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (rs_start): Removed an incorrect '!' that was
-		preventing transmit interrupts from being re-enabled in
-		rs_start().  Fortunately in most cases it would be
-		re-enabled elsewhere, but this still should be fixed
-		correctly.
-
-Sun Oct  9 23:46:03 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_io.c (do_tty_hangup): If the tty driver flags
-		TTY_DRIVER_RESET_TERMIOS is set, then reset the termios
-		settings back to the driver's initial configuration.  This
-		allows the termios settings to be reset even if a process
-		has hung up file descriptors keeping a pty's termios from
-		being freed and reset.
-
-	* tty_io.c (release_dev): Fix memory leak.  The pty's other
-		termios structure should also be freed.
-
-	* serial.c (rs_close, shutdown): Change how we wait for the
-		transmitter to completely drain before shutting down the
-		serial port.  We now do it by scheduling in another
-		process instead of busy looping with the interrupts turned
-		on.  This may eliminate some race condition problems that
-		some people seem to be reporting.
-
-Sun Sep 25 14:18:14 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_io.c (release_dev): When freeing a tty make sure that both
-		the tty and the o_tty (if present) aren't a process's
-		controlling tty.  (Previously, we only checked the tty.)
-
-	* serial.c (change_speed): Only enable the Modem Status
-		Interrupt for a port if CLOCAL is not set or CRTSCTS
-		is set.  If we're not checking the carrier detect and
-		CTS line, there's no point in enabling the modem
-		status interrupt.  This will save spurious interrupts
-		from slowing down systems who have terminals that
-		don't support either line.  (Of course, if you want
-		only one of CD and CTS support, you will need a
-		properly wired serial cable.)
-
-Thu Sep 22 08:32:48 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_io.c (do_SAK): Return if tty is null.
-
-	* tty_io.c (_tty_name): Return "NULL tty" if the passed in tty is
-		NULL.
-
-Sat Sep 17 13:19:25 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_ioctl.c (n_tty_ioctl): Fix TIOCGLCKTRMIOS and
-		TIOCSLCKTRMIOS, which were totally broken.  Remove
-		extra indirection from argument; it should be a struct
-		termios *, not a struct termios **.
-		&real_tty->termios_locked should have been
-		real_tty->termios_locked.  This caused us to be
-		reading and writing the termios_locked structure to
-		random places in kernel memory.  
-
-	* tty_io.c (release_dev): Oops!  Forgot to delete a critical kfree
-		of the locked_termios.  This leaves the locked_termios
-		structure pointed at a freed object.  
-
-Fri Sep 16 08:13:25 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* tty_io.c (tty_open): Don't check for an exclusive open until
-		after the device specific open routine has been called.
-		Otherwise, the serial device ref counting will be screwed
-		up.
-
-	* serial.c (rs_open, block_til_ready): Don't set termios structure
-		until after block_til_ready has returned successfully.
-		Modify block_til_ready to check the normal_termios
-		structure directly, so it doesn't rely on termios being
-		set before it's called.
-
-Thu Sep 15 23:34:01 1994  Theodore Y. Ts'o  (tytso@rt-11)
-
-	* serial.c (rs_close): Turn off interrupts during rs_close() to
-		prevent a race condition with the hangup code (which
-		runs during a software interrupt).
-
-	* tty_io.c (release_dev): Don't free the locked_termios structure;
-		its state must be retained across device opens.
-
-
-	* tty_io.c (tty_unregister_driver): Added function to unregister a
-		tty driver.  (For loadable device drivers.)
-
-
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 2fb3a48..4b66c69 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -57,7 +57,7 @@
 
 config AGP_AMD64
 	tristate "AMD Opteron/Athlon64 on-CPU GART support"
-	depends on AGP && X86
+	depends on AGP && X86 && K8_NB
 	help
 	  This option gives you AGP support for the GLX component of
 	  X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 8a713f1..a3e10dc 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -11,6 +11,9 @@
 #include <asm/smp.h>
 #include "agp.h"
 
+int intel_agp_enabled;
+EXPORT_SYMBOL(intel_agp_enabled);
+
 /*
  * If we have Intel graphics, we're not going to have anything other than
  * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
@@ -65,6 +68,10 @@
 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB	    0x0062
 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB    0x006a
 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG	    0x0046
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB  0x0100
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG  0x0102
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB  0x0104
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG  0x0106
 
 /* cover 915 and 945 variants */
 #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
@@ -99,7 +106,9 @@
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \
 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
-		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB)
+		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
+		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
+		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
 
 extern int agp_memory_reserved;
 
@@ -148,6 +157,25 @@
 #define INTEL_I7505_AGPCTRL	0x70
 #define INTEL_I7505_MCHCFG	0x50
 
+#define SNB_GMCH_CTRL	0x50
+#define SNB_GMCH_GMS_STOLEN_MASK	0xF8
+#define SNB_GMCH_GMS_STOLEN_32M		(1 << 3)
+#define SNB_GMCH_GMS_STOLEN_64M		(2 << 3)
+#define SNB_GMCH_GMS_STOLEN_96M		(3 << 3)
+#define SNB_GMCH_GMS_STOLEN_128M	(4 << 3)
+#define SNB_GMCH_GMS_STOLEN_160M	(5 << 3)
+#define SNB_GMCH_GMS_STOLEN_192M	(6 << 3)
+#define SNB_GMCH_GMS_STOLEN_224M	(7 << 3)
+#define SNB_GMCH_GMS_STOLEN_256M	(8 << 3)
+#define SNB_GMCH_GMS_STOLEN_288M	(9 << 3)
+#define SNB_GMCH_GMS_STOLEN_320M	(0xa << 3)
+#define SNB_GMCH_GMS_STOLEN_352M	(0xb << 3)
+#define SNB_GMCH_GMS_STOLEN_384M	(0xc << 3)
+#define SNB_GMCH_GMS_STOLEN_416M	(0xd << 3)
+#define SNB_GMCH_GMS_STOLEN_448M	(0xe << 3)
+#define SNB_GMCH_GMS_STOLEN_480M	(0xf << 3)
+#define SNB_GMCH_GMS_STOLEN_512M	(0x10 << 3)
+
 static const struct aper_size_info_fixed intel_i810_sizes[] =
 {
 	{64, 16384, 4},
@@ -270,7 +298,7 @@
 			j++;
 		}
 	} else {
-		/* sg may merge pages, but we have to seperate
+		/* sg may merge pages, but we have to separate
 		 * per-page addr for GTT */
 		unsigned int len, m;
 
@@ -294,6 +322,13 @@
 					off_t pg_start, int mask_type)
 {
 	int i, j;
+	u32 cache_bits = 0;
+
+	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
+	    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
+	{
+		cache_bits = I830_PTE_SYSTEM_CACHED;
+	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
@@ -614,7 +649,7 @@
 static void intel_i830_init_gtt_entries(void)
 {
 	u16 gmch_ctrl;
-	int gtt_entries;
+	int gtt_entries = 0;
 	u8 rdct;
 	int local = 0;
 	static const int ddt[4] = { 0, 16, 32, 64 };
@@ -706,6 +741,63 @@
 			gtt_entries = 0;
 			break;
 		}
+	} else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
+		   agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
+		/*
+		 * SandyBridge has new memory control reg at 0x50.w
+		 */
+		u16 snb_gmch_ctl;
+		pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
+		switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) {
+		case SNB_GMCH_GMS_STOLEN_32M:
+			gtt_entries = MB(32) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_64M:
+			gtt_entries = MB(64) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_96M:
+			gtt_entries = MB(96) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_128M:
+			gtt_entries = MB(128) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_160M:
+			gtt_entries = MB(160) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_192M:
+			gtt_entries = MB(192) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_224M:
+			gtt_entries = MB(224) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_256M:
+			gtt_entries = MB(256) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_288M:
+			gtt_entries = MB(288) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_320M:
+			gtt_entries = MB(320) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_352M:
+			gtt_entries = MB(352) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_384M:
+			gtt_entries = MB(384) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_416M:
+			gtt_entries = MB(416) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_448M:
+			gtt_entries = MB(448) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_480M:
+			gtt_entries = MB(480) - KB(size);
+			break;
+		case SNB_GMCH_GMS_STOLEN_512M:
+			gtt_entries = MB(512) - KB(size);
+			break;
+		}
 	} else {
 		switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
 		case I855_GMCH_GMS_STOLEN_1M:
@@ -1357,6 +1449,8 @@
 	case PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB:
 	case PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB:
 	case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
+	case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
+	case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
 		*gtt_offset = *gtt_size = MB(2);
 		break;
 	default:
@@ -2338,9 +2432,9 @@
 		NULL, &intel_g33_driver },
 	{ PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
 		NULL, &intel_g33_driver },
-	{ PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "Pineview",
+	{ PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "GMA3150",
 		NULL, &intel_g33_driver },
-	{ PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "Pineview",
+	{ PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "GMA3150",
 		NULL, &intel_g33_driver },
 	{ PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0,
 	    "GM45", NULL, &intel_i965_driver },
@@ -2355,13 +2449,17 @@
 	{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
 	    "G41", NULL, &intel_i965_driver },
 	{ PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0,
-	    "Ironlake/D", NULL, &intel_i965_driver },
+	    "HD Graphics", NULL, &intel_i965_driver },
 	{ PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
-	    "Ironlake/M", NULL, &intel_i965_driver },
+	    "HD Graphics", NULL, &intel_i965_driver },
 	{ PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
-	    "Ironlake/MA", NULL, &intel_i965_driver },
+	    "HD Graphics", NULL, &intel_i965_driver },
 	{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
-	    "Ironlake/MC2", NULL, &intel_i965_driver },
+	    "HD Graphics", NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, 0,
+	    "Sandybridge", NULL, &intel_i965_driver },
+	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, 0,
+	    "Sandybridge", NULL, &intel_i965_driver },
 	{ 0, 0, 0, NULL, NULL, NULL }
 };
 
@@ -2371,7 +2469,7 @@
 	struct agp_bridge_data *bridge;
 	u8 cap_ptr = 0;
 	struct resource *r;
-	int i;
+	int i, err;
 
 	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 
@@ -2463,7 +2561,10 @@
 	}
 
 	pci_set_drvdata(pdev, bridge);
-	return agp_add_bridge(bridge);
+	err = agp_add_bridge(bridge);
+	if (!err)
+		intel_agp_enabled = 1;
+	return err;
 }
 
 static void __devexit agp_intel_remove(struct pci_dev *pdev)
@@ -2568,6 +2669,8 @@
 	ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
 	ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
 	ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
+	ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
+	ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
 	{ }
 };
 
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index fe2cb2f..a7424bf 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -14,7 +14,7 @@
 /* et passe en argument a acinit, mais est scrute sur le bus pour s'adapter  */
 /* au nombre de cartes presentes sur le bus. IOCL code 6 affichait V2.4.3    */
 /* F.LAFORSE 28/11/95 creation de fichiers acXX.o avec les differentes       */
-/* adresses de base des cartes, IOCTL 6 plus complet                         */
+/* addresses de base des cartes, IOCTL 6 plus complet                         */
 /* J.PAGET le 19/08/96 copie de la version V2.6 en V2.8.0 sans modification  */
 /* de code autre que le texte V2.6.1 en V2.8.0                               */
 /*****************************************************************************/
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 4254457..b861c08 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -158,13 +158,11 @@
 
 #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
 
-#ifdef MODULE
 static long maddr[NR_CARDS];
 static int irq[NR_CARDS];
 
 module_param_array(maddr, long, NULL, 0);
 module_param_array(irq, int, NULL, 0);
-#endif
 
 #endif				/* CONFIG_ISA */
 
@@ -598,12 +596,6 @@
 	save_car = readb(base_addr + (CyCAR << index));
 	cy_writeb(base_addr + (CyCAR << index), save_xir);
 
-	/* validate the port# (as configured and open) */
-	if (channel + chip * 4 >= cinfo->nports) {
-		cy_writeb(base_addr + (CySRER << index),
-			  readb(base_addr + (CySRER << index)) & ~CyTxRdy);
-		goto end;
-	}
 	info = &cinfo->ports[channel + chip * 4];
 	tty = tty_port_tty_get(&info->port);
 	if (tty == NULL) {
@@ -3316,13 +3308,10 @@
 	unsigned short cy_isa_irq, nboard;
 	void __iomem *cy_isa_address;
 	unsigned short i, j, cy_isa_nchan;
-#ifdef MODULE
 	int isparam = 0;
-#endif
 
 	nboard = 0;
 
-#ifdef MODULE
 	/* Check for module parameters */
 	for (i = 0; i < NR_CARDS; i++) {
 		if (maddr[i] || i) {
@@ -3332,7 +3321,6 @@
 		if (!maddr[i])
 			break;
 	}
-#endif
 
 	/* scan the address table probing for Cyclom-Y/ISA boards */
 	for (i = 0; i < NR_ISA_ADDRS; i++) {
@@ -3353,11 +3341,10 @@
 			iounmap(cy_isa_address);
 			continue;
 		}
-#ifdef MODULE
+
 		if (isparam && i < NR_CARDS && irq[i])
 			cy_isa_irq = irq[i];
 		else
-#endif
 			/* find out the board's irq by probing */
 			cy_isa_irq = detect_isa_irq(cy_isa_address);
 		if (cy_isa_irq == 0) {
@@ -4208,3 +4195,4 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(CY_VERSION);
 MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR);
+MODULE_FIRMWARE("cyzfirm.bin");
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 4c3b59b..465185f 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -146,7 +146,7 @@
 		return;
 
 	/* This console adapter was removed so it is not usable. */
-	if (vtermnos[index] < 0)
+	if (vtermnos[index] == -1)
 		return;
 
 	while (count > 0 || i > 0) {
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c
index fd02426..21c5495 100644
--- a/drivers/char/hvc_iseries.c
+++ b/drivers/char/hvc_iseries.c
@@ -353,7 +353,7 @@
 
 	if (!hvlpevent_is_int(event)) {
 		printk(KERN_WARNING
-			"hvc: got unexpected close acknowlegement\n");
+			"hvc: got unexpected close acknowledgement\n");
 		return;
 	}
 
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c
index 21681a8..37b0542 100644
--- a/drivers/char/hvc_iucv.c
+++ b/drivers/char/hvc_iucv.c
@@ -139,6 +139,8 @@
  *
  * This function allocates a new struct iucv_tty_buffer element and, optionally,
  * allocates an internal data buffer with the specified size @size.
+ * The internal data buffer is always allocated with GFP_DMA which is
+ * required for receiving and sending data with IUCV.
  * Note: The total message size arises from the internal buffer size and the
  *	 members of the iucv_tty_msg structure.
  * The function returns NULL if memory allocation has failed.
@@ -154,7 +156,7 @@
 
 	if (size > 0) {
 		bufp->msg.length = MSG_SIZE(size);
-		bufp->mbuf = kmalloc(bufp->msg.length, flags);
+		bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA);
 		if (!bufp->mbuf) {
 			mempool_free(bufp, hvc_iucv_mempool);
 			return NULL;
@@ -237,7 +239,7 @@
 	if (!rb->mbuf) { /* message not yet received ... */
 		/* allocate mem to store msg data; if no memory is available
 		 * then leave the buffer on the list and re-try later */
-		rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC);
+		rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA);
 		if (!rb->mbuf)
 			return -ENOMEM;
 
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index 9b3e09c..10f868e 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -71,7 +71,7 @@
  *        x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1
  *
  * The RNG_CTL_VCO value of each noise cell must be programmed
- * seperately.  This is why 4 control register values must be provided
+ * separately.  This is why 4 control register values must be provided
  * to the hypervisor.  During a write, the hypervisor writes them all,
  * one at a time, to the actual RNG_CTL register.  The first three
  * values are used to setup the desired RNG_CTL_VCO for each entropy
diff --git a/drivers/char/ip2/i2hw.h b/drivers/char/ip2/i2hw.h
index 8aa6e7a..c0ba6c0 100644
--- a/drivers/char/ip2/i2hw.h
+++ b/drivers/char/ip2/i2hw.h
@@ -559,7 +559,7 @@
 
 2) It may be hard-coded into your source by including a .h file (typically
 	supplied by Computone), which declares a data array and initializes every
-	element. This acheives the same result as if an entire loadware file had 
+	element. This achieves the same result as if an entire loadware file had 
 	been read into the array.
 
 	This requires more data space in your program, but access to the file system
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 517271c..911e1da 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -208,6 +208,7 @@
 
 static void ip2_init_board(int, const struct firmware *);
 static unsigned short find_eisa_board(int);
+static int ip2_setup(char *str);
 
 /***************/
 /* Static Data */
@@ -263,7 +264,7 @@
 /* Macros */
 /**********/
 
-#if defined(MODULE) && defined(IP2DEBUG_OPEN)
+#ifdef IP2DEBUG_OPEN
 #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
 		    tty->name,(pCh->flags), \
 		    tty->count,/*GET_USE_COUNT(module)*/0,s)
@@ -285,7 +286,10 @@
 MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
 MODULE_LICENSE("GPL");
 
+#define	MAX_CMD_STR	50
+
 static int poll_only;
+static char cmd[MAX_CMD_STR];
 
 static int Eisa_irq;
 static int Eisa_slot;
@@ -309,6 +313,8 @@
 MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
 module_param(poll_only, bool, 0);
 MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
+module_param_string(ip2, cmd, MAX_CMD_STR, 0);
+MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='");
 
 /* for sysfs class support */
 static struct class *ip2_class;
@@ -487,7 +493,6 @@
 	return fw;
 }
 
-#ifndef MODULE
 /******************************************************************************
  *	ip2_setup:
  *		str: kernel command line string
@@ -531,7 +536,6 @@
 	return 1;
 }
 __setup("ip2=", ip2_setup);
-#endif /* !MODULE */
 
 static int __init ip2_loadmain(void)
 {
@@ -539,14 +543,20 @@
 	int err = 0;
 	i2eBordStrPtr pB = NULL;
 	int rc = -1;
-	struct pci_dev *pdev = NULL;
 	const struct firmware *fw = NULL;
+	char *str;
+
+	str = cmd;
 
 	if (poll_only) {
 		/* Hard lock the interrupts to zero */
 		irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
 	}
 
+	/* Check module parameter with 'ip2=' has been passed or not */
+	if (!poll_only && (!strncmp(str, "ip2=", 4)))
+		ip2_setup(str);
+
 	ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
 
 	/* process command line arguments to modprobe or
@@ -612,6 +622,7 @@
 		case PCI:
 #ifdef CONFIG_PCI
 		{
+			struct pci_dev *pdev = NULL;
 			u32 addr;
 			int status;
 
@@ -626,7 +637,7 @@
 
 			if (pci_enable_device(pdev)) {
 				dev_err(&pdev->dev, "can't enable device\n");
-				break;
+				goto out;
 			}
 			ip2config.type[i] = PCI;
 			ip2config.pci_dev[i] = pci_dev_get(pdev);
@@ -638,6 +649,8 @@
 				dev_err(&pdev->dev, "I/O address error\n");
 
 			ip2config.irq[i] = pdev->irq;
+out:
+			pci_dev_put(pdev);
 		}
 #else
 			printk(KERN_ERR "IP2: PCI card specified but PCI "
@@ -656,7 +669,6 @@
 			break;
 		}	/* switch */
 	}	/* for */
-	pci_dev_put(pdev);
 
 	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
 		if (ip2config.addr[i]) {
@@ -3197,3 +3209,5 @@
 };
 
 MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl);
+
+MODULE_FIRMWARE("intelliport2.bin");
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 176f175..4462b11 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -295,6 +295,9 @@
 static int force_kipmid[SI_MAX_PARMS];
 static int num_force_kipmid;
 
+static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
+static int num_max_busy_us;
+
 static int unload_when_empty = 1;
 
 static int try_smi_init(struct smi_info *smi);
@@ -925,23 +928,77 @@
 	}
 }
 
+/*
+ * Use -1 in the nsec value of the busy waiting timespec to tell that
+ * we are spinning in kipmid looking for something and not delaying
+ * between checks
+ */
+static inline void ipmi_si_set_not_busy(struct timespec *ts)
+{
+	ts->tv_nsec = -1;
+}
+static inline int ipmi_si_is_busy(struct timespec *ts)
+{
+	return ts->tv_nsec != -1;
+}
+
+static int ipmi_thread_busy_wait(enum si_sm_result smi_result,
+				 const struct smi_info *smi_info,
+				 struct timespec *busy_until)
+{
+	unsigned int max_busy_us = 0;
+
+	if (smi_info->intf_num < num_max_busy_us)
+		max_busy_us = kipmid_max_busy_us[smi_info->intf_num];
+	if (max_busy_us == 0 || smi_result != SI_SM_CALL_WITH_DELAY)
+		ipmi_si_set_not_busy(busy_until);
+	else if (!ipmi_si_is_busy(busy_until)) {
+		getnstimeofday(busy_until);
+		timespec_add_ns(busy_until, max_busy_us*NSEC_PER_USEC);
+	} else {
+		struct timespec now;
+		getnstimeofday(&now);
+		if (unlikely(timespec_compare(&now, busy_until) > 0)) {
+			ipmi_si_set_not_busy(busy_until);
+			return 0;
+		}
+	}
+	return 1;
+}
+
+
+/*
+ * A busy-waiting loop for speeding up IPMI operation.
+ *
+ * Lousy hardware makes this hard.  This is only enabled for systems
+ * that are not BT and do not have interrupts.  It starts spinning
+ * when an operation is complete or until max_busy tells it to stop
+ * (if that is enabled).  See the paragraph on kimid_max_busy_us in
+ * Documentation/IPMI.txt for details.
+ */
 static int ipmi_thread(void *data)
 {
 	struct smi_info *smi_info = data;
 	unsigned long flags;
 	enum si_sm_result smi_result;
+	struct timespec busy_until;
 
+	ipmi_si_set_not_busy(&busy_until);
 	set_user_nice(current, 19);
 	while (!kthread_should_stop()) {
+		int busy_wait;
+
 		spin_lock_irqsave(&(smi_info->si_lock), flags);
 		smi_result = smi_event_handler(smi_info, 0);
 		spin_unlock_irqrestore(&(smi_info->si_lock), flags);
+		busy_wait = ipmi_thread_busy_wait(smi_result, smi_info,
+						  &busy_until);
 		if (smi_result == SI_SM_CALL_WITHOUT_DELAY)
 			; /* do nothing */
-		else if (smi_result == SI_SM_CALL_WITH_DELAY)
+		else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait)
 			schedule();
 		else
-			schedule_timeout_interruptible(1);
+			schedule_timeout_interruptible(0);
 	}
 	return 0;
 }
@@ -1144,7 +1201,7 @@
 static unsigned int num_regsizes;
 static int           regshifts[SI_MAX_PARMS];
 static unsigned int num_regshifts;
-static int slave_addrs[SI_MAX_PARMS];
+static int slave_addrs[SI_MAX_PARMS]; /* Leaving 0 chooses the default value */
 static unsigned int num_slave_addrs;
 
 #define IPMI_IO_ADDR_SPACE  0
@@ -1212,6 +1269,11 @@
 MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are"
 		 " specified or found, default is 1.  Setting to 0"
 		 " is useful for hot add of devices using hotmod.");
+module_param_array(kipmid_max_busy_us, uint, &num_max_busy_us, 0644);
+MODULE_PARM_DESC(kipmid_max_busy_us,
+		 "Max time (in microseconds) to busy-wait for IPMI data before"
+		 " sleeping. 0 (default) means to wait forever. Set to 100-500"
+		 " if kipmid is using up a lot of CPU time.");
 
 
 static void std_irq_cleanup(struct smi_info *info)
@@ -1607,7 +1669,7 @@
 		regsize = 1;
 		regshift = 0;
 		irq = 0;
-		ipmb = 0x20;
+		ipmb = 0; /* Choose the default if not specified */
 
 		next = strchr(curr, ':');
 		if (next) {
@@ -1799,6 +1861,7 @@
 		info->irq = irqs[i];
 		if (info->irq)
 			info->irq_setup = std_irq_setup;
+		info->slave_addr = slave_addrs[i];
 
 		try_smi_init(info);
 	}
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 300d5bd..be2e8f9 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -113,6 +113,8 @@
  *		64-bit verification
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/kernel.h>
@@ -140,7 +142,6 @@
 #define InterruptTheCard(base) outw(0, (base) + 0xc)
 #define ClearInterrupt(base) inw((base) + 0x0a)
 
-#define pr_dbg(str...) pr_debug("ISICOM: " str)
 #ifdef DEBUG
 #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
 #else
@@ -249,8 +250,7 @@
 		spin_unlock_irqrestore(&card->card_lock, card->flags);
 		msleep(10);
 	}
-	printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
-		card->base);
+	pr_warning("Failed to lock Card (0x%lx)\n", card->base);
 
 	return 0;	/* Failed to acquire the card! */
 }
@@ -379,13 +379,13 @@
 	char *name, const char *routine)
 {
 	if (!port) {
-		printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for "
-			"dev %s in %s.\n", name, routine);
+		pr_warning("Warning: bad isicom magic for dev %s in %s.\n",
+			   name, routine);
 		return 1;
 	}
 	if (port->magic != ISICOM_MAGIC) {
-		printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for "
-			"dev %s in %s.\n", name, routine);
+		pr_warning("Warning: NULL isicom port for dev %s in %s.\n",
+			   name, routine);
 		return 1;
 	}
 
@@ -450,8 +450,8 @@
 		if (!(inw(base + 0x02) & (1 << port->channel)))
 			continue;
 
-		pr_dbg("txing %d bytes, port%d.\n", txcount,
-			port->channel + 1);
+		pr_debug("txing %d bytes, port%d.\n",
+			 txcount, port->channel + 1);
 		outw((port->channel << isi_card[card].shift_count) | txcount,
 			base);
 		residue = NO;
@@ -547,8 +547,8 @@
 	byte_count = header & 0xff;
 
 	if (channel + 1 > card->port_count) {
-		printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
-			"%d(channel) > port_count.\n", base, channel+1);
+		pr_warning("%s(0x%lx): %d(channel) > port_count.\n",
+			   __func__, base, channel+1);
 		outw(0x0000, base+0x04); /* enable interrupts */
 		spin_unlock(&card->card_lock);
 		return IRQ_HANDLED;
@@ -582,14 +582,15 @@
 				if (port->status & ISI_DCD) {
 					if (!(header & ISI_DCD)) {
 					/* Carrier has been lost  */
-						pr_dbg("interrupt: DCD->low.\n"
-							);
+						pr_debug("%s: DCD->low.\n",
+							 __func__);
 						port->status &= ~ISI_DCD;
 						tty_hangup(tty);
 					}
 				} else if (header & ISI_DCD) {
 				/* Carrier has been detected */
-					pr_dbg("interrupt: DCD->high.\n");
+					pr_debug("%s: DCD->high.\n",
+						__func__);
 					port->status |= ISI_DCD;
 					wake_up_interruptible(&port->port.open_wait);
 				}
@@ -641,17 +642,19 @@
 			break;
 
 		case 2:	/* Statistics		 */
-			pr_dbg("isicom_interrupt: stats!!!.\n");
+			pr_debug("%s: stats!!!\n", __func__);
 			break;
 
 		default:
-			pr_dbg("Intr: Unknown code in status packet.\n");
+			pr_debug("%s: Unknown code in status packet.\n",
+				 __func__);
 			break;
 		}
 	} else {				/* Data   Packet */
 
 		count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
-		pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count);
+		pr_debug("%s: Can rx %d of %d bytes.\n",
+			 __func__, count, byte_count);
 		word_count = count >> 1;
 		insw(base, rp, word_count);
 		byte_count -= (word_count << 1);
@@ -661,8 +664,8 @@
 			byte_count -= 2;
 		}
 		if (byte_count > 0) {
-			pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
-				"bytes...\n", base, channel + 1);
+			pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n",
+				 __func__, base, channel + 1);
 		/* drain out unread xtra data */
 		while (byte_count > 0) {
 				inw(base);
@@ -888,8 +891,8 @@
 	struct isi_board *card = port->card;
 
 	if (--card->count < 0) {
-		pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
-			card->base, card->count);
+		pr_debug("%s: bad board(0x%lx) count %d.\n",
+			 __func__, card->base, card->count);
 		card->count = 0;
 	}
 	/* last port was closed, shutdown that board too */
@@ -1681,13 +1684,13 @@
 
 	retval = tty_register_driver(isicom_normal);
 	if (retval) {
-		pr_dbg("Couldn't register the dialin driver\n");
+		pr_debug("Couldn't register the dialin driver\n");
 		goto err_puttty;
 	}
 
 	retval = pci_register_driver(&isicom_driver);
 	if (retval < 0) {
-		printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
+		pr_err("Unable to register pci driver.\n");
 		goto err_unrtty;
 	}
 
@@ -1717,3 +1720,8 @@
 MODULE_AUTHOR("MultiTech");
 MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("isi608.bin");
+MODULE_FIRMWARE("isi608em.bin");
+MODULE_FIRMWARE("isi616em.bin");
+MODULE_FIRMWARE("isi4608.bin");
+MODULE_FIRMWARE("isi4616.bin");
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 48788db..1f3215a 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
- *  Added devfs support. 
+ *  Added devfs support.
  *    Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu>
  *  Shared /dev/zero mmapping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com>
  */
@@ -44,36 +44,6 @@
 	return min(sz, size);
 }
 
-/*
- * Architectures vary in how they handle caching for addresses
- * outside of main memory.
- *
- */
-static inline int uncached_access(struct file *file, unsigned long addr)
-{
-#if defined(CONFIG_IA64)
-	/*
-	 * On ia64, we ignore O_DSYNC because we cannot tolerate memory attribute aliases.
-	 */
-	return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
-#elif defined(CONFIG_MIPS)
-	{
-		extern int __uncached_access(struct file *file,
-					     unsigned long addr);
-
-		return __uncached_access(file, addr);
-	}
-#else
-	/*
-	 * Accessing memory above the top the kernel knows about or through a file pointer
-	 * that was marked O_DSYNC will be done non-cached.
-	 */
-	if (file->f_flags & O_DSYNC)
-		return 1;
-	return addr >= __pa(high_memory);
-#endif
-}
-
 #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
 static inline int valid_phys_addr_range(unsigned long addr, size_t count)
 {
@@ -115,15 +85,15 @@
 }
 #endif
 
-void __attribute__((weak)) unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr)
 {
 }
 
 /*
- * This funcion reads the *physical* memory. The f_pos points directly to the 
- * memory location. 
+ * This funcion reads the *physical* memory. The f_pos points directly to the
+ * memory location.
  */
-static ssize_t read_mem(struct file * file, char __user * buf,
+static ssize_t read_mem(struct file *file, char __user *buf,
 			size_t count, loff_t *ppos)
 {
 	unsigned long p = *ppos;
@@ -140,10 +110,10 @@
 		if (sz > 0) {
 			if (clear_user(buf, sz))
 				return -EFAULT;
-			buf += sz; 
-			p += sz; 
-			count -= sz; 
-			read += sz; 
+			buf += sz;
+			p += sz;
+			count -= sz;
+			read += sz;
 		}
 	}
 #endif
@@ -157,9 +127,9 @@
 			return -EPERM;
 
 		/*
-		 * On ia64 if a page has been mapped somewhere as
-		 * uncached, then it must also be accessed uncached
-		 * by the kernel or data corruption may occur
+		 * On ia64 if a page has been mapped somewhere as uncached, then
+		 * it must also be accessed uncached by the kernel or data
+		 * corruption may occur.
 		 */
 		ptr = xlate_dev_mem_ptr(p);
 		if (!ptr)
@@ -180,7 +150,7 @@
 	return read;
 }
 
-static ssize_t write_mem(struct file * file, const char __user * buf, 
+static ssize_t write_mem(struct file *file, const char __user *buf,
 			 size_t count, loff_t *ppos)
 {
 	unsigned long p = *ppos;
@@ -212,9 +182,9 @@
 			return -EPERM;
 
 		/*
-		 * On ia64 if a page has been mapped somewhere as
-		 * uncached, then it must also be accessed uncached
-		 * by the kernel or data corruption may occur
+		 * On ia64 if a page has been mapped somewhere as uncached, then
+		 * it must also be accessed uncached by the kernel or data
+		 * corruption may occur.
 		 */
 		ptr = xlate_dev_mem_ptr(p);
 		if (!ptr) {
@@ -242,13 +212,46 @@
 	return written;
 }
 
-int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file,
+int __weak phys_mem_access_prot_allowed(struct file *file,
 	unsigned long pfn, unsigned long size, pgprot_t *vma_prot)
 {
 	return 1;
 }
 
 #ifndef __HAVE_PHYS_MEM_ACCESS_PROT
+
+/*
+ * Architectures vary in how they handle caching for addresses
+ * outside of main memory.
+ *
+ */
+static int uncached_access(struct file *file, unsigned long addr)
+{
+#if defined(CONFIG_IA64)
+	/*
+	 * On ia64, we ignore O_DSYNC because we cannot tolerate memory
+	 * attribute aliases.
+	 */
+	return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
+#elif defined(CONFIG_MIPS)
+	{
+		extern int __uncached_access(struct file *file,
+					     unsigned long addr);
+
+		return __uncached_access(file, addr);
+	}
+#else
+	/*
+	 * Accessing memory above the top the kernel knows about or through a
+	 * file pointer
+	 * that was marked O_DSYNC will be done non-cached.
+	 */
+	if (file->f_flags & O_DSYNC)
+		return 1;
+	return addr >= __pa(high_memory);
+#endif
+}
+
 static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 				     unsigned long size, pgprot_t vma_prot)
 {
@@ -294,7 +297,7 @@
 #endif
 };
 
-static int mmap_mem(struct file * file, struct vm_area_struct * vma)
+static int mmap_mem(struct file *file, struct vm_area_struct *vma)
 {
 	size_t size = vma->vm_end - vma->vm_start;
 
@@ -329,7 +332,7 @@
 }
 
 #ifdef CONFIG_DEVKMEM
-static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
+static int mmap_kmem(struct file *file, struct vm_area_struct *vma)
 {
 	unsigned long pfn;
 
@@ -337,9 +340,9 @@
 	pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
 
 	/*
-	 * RED-PEN: on some architectures there is more mapped memory
-	 * than available in mem_map which pfn_valid checks
-	 * for. Perhaps should add a new macro here.
+	 * RED-PEN: on some architectures there is more mapped memory than
+	 * available in mem_map which pfn_valid checks for. Perhaps should add a
+	 * new macro here.
 	 *
 	 * RED-PEN: vmalloc is not supported right now.
 	 */
@@ -389,7 +392,7 @@
 /*
  * This function reads the *virtual* memory as seen by the kernel.
  */
-static ssize_t read_kmem(struct file *file, char __user *buf, 
+static ssize_t read_kmem(struct file *file, char __user *buf,
 			 size_t count, loff_t *ppos)
 {
 	unsigned long p = *ppos;
@@ -400,8 +403,8 @@
 	read = 0;
 	if (p < (unsigned long) high_memory) {
 		low_count = count;
-		if (count > (unsigned long) high_memory - p)
-			low_count = (unsigned long) high_memory - p;
+		if (count > (unsigned long)high_memory - p)
+			low_count = (unsigned long)high_memory - p;
 
 #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
 		/* we don't have page 0 mapped on sparc and m68k.. */
@@ -465,9 +468,8 @@
 }
 
 
-static inline ssize_t
-do_write_kmem(unsigned long p, const char __user *buf,
-	      size_t count, loff_t *ppos)
+static ssize_t do_write_kmem(unsigned long p, const char __user *buf,
+				size_t count, loff_t *ppos)
 {
 	ssize_t written, sz;
 	unsigned long copied;
@@ -491,9 +493,9 @@
 		sz = size_inside_page(p, count);
 
 		/*
-		 * On ia64 if a page has been mapped somewhere as
-		 * uncached, then it must also be accessed uncached
-		 * by the kernel or data corruption may occur
+		 * On ia64 if a page has been mapped somewhere as uncached, then
+		 * it must also be accessed uncached by the kernel or data
+		 * corruption may occur.
 		 */
 		ptr = xlate_dev_kmem_ptr((char *)p);
 
@@ -514,11 +516,10 @@
 	return written;
 }
 
-
 /*
  * This function writes to the *virtual* memory as seen by the kernel.
  */
-static ssize_t write_kmem(struct file * file, const char __user * buf, 
+static ssize_t write_kmem(struct file *file, const char __user *buf,
 			  size_t count, loff_t *ppos)
 {
 	unsigned long p = *ppos;
@@ -570,17 +571,17 @@
 #endif
 
 #ifdef CONFIG_DEVPORT
-static ssize_t read_port(struct file * file, char __user * buf,
+static ssize_t read_port(struct file *file, char __user *buf,
 			 size_t count, loff_t *ppos)
 {
 	unsigned long i = *ppos;
 	char __user *tmp = buf;
 
 	if (!access_ok(VERIFY_WRITE, buf, count))
-		return -EFAULT; 
+		return -EFAULT;
 	while (count-- > 0 && i < 65536) {
-		if (__put_user(inb(i),tmp) < 0) 
-			return -EFAULT;  
+		if (__put_user(inb(i), tmp) < 0)
+			return -EFAULT;
 		i++;
 		tmp++;
 	}
@@ -588,22 +589,22 @@
 	return tmp-buf;
 }
 
-static ssize_t write_port(struct file * file, const char __user * buf,
+static ssize_t write_port(struct file *file, const char __user *buf,
 			  size_t count, loff_t *ppos)
 {
 	unsigned long i = *ppos;
 	const char __user * tmp = buf;
 
-	if (!access_ok(VERIFY_READ,buf,count))
+	if (!access_ok(VERIFY_READ, buf, count))
 		return -EFAULT;
 	while (count-- > 0 && i < 65536) {
 		char c;
 		if (__get_user(c, tmp)) {
 			if (tmp > buf)
 				break;
-			return -EFAULT; 
+			return -EFAULT;
 		}
-		outb(c,i);
+		outb(c, i);
 		i++;
 		tmp++;
 	}
@@ -612,13 +613,13 @@
 }
 #endif
 
-static ssize_t read_null(struct file * file, char __user * buf,
+static ssize_t read_null(struct file *file, char __user *buf,
 			 size_t count, loff_t *ppos)
 {
 	return 0;
 }
 
-static ssize_t write_null(struct file * file, const char __user * buf,
+static ssize_t write_null(struct file *file, const char __user *buf,
 			  size_t count, loff_t *ppos)
 {
 	return count;
@@ -630,13 +631,13 @@
 	return sd->len;
 }
 
-static ssize_t splice_write_null(struct pipe_inode_info *pipe,struct file *out,
+static ssize_t splice_write_null(struct pipe_inode_info *pipe, struct file *out,
 				 loff_t *ppos, size_t len, unsigned int flags)
 {
 	return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null);
 }
 
-static ssize_t read_zero(struct file * file, char __user * buf, 
+static ssize_t read_zero(struct file *file, char __user *buf,
 			 size_t count, loff_t *ppos)
 {
 	size_t written;
@@ -667,7 +668,7 @@
 	return written ? written : -EFAULT;
 }
 
-static int mmap_zero(struct file * file, struct vm_area_struct * vma)
+static int mmap_zero(struct file *file, struct vm_area_struct *vma)
 {
 #ifndef CONFIG_MMU
 	return -ENOSYS;
@@ -677,7 +678,7 @@
 	return 0;
 }
 
-static ssize_t write_full(struct file * file, const char __user * buf,
+static ssize_t write_full(struct file *file, const char __user *buf,
 			  size_t count, loff_t *ppos)
 {
 	return -ENOSPC;
@@ -688,8 +689,7 @@
  * can fopen() both devices with "a" now.  This was previously impossible.
  * -- SRB.
  */
-
-static loff_t null_lseek(struct file * file, loff_t offset, int orig)
+static loff_t null_lseek(struct file *file, loff_t offset, int orig)
 {
 	return file->f_pos = 0;
 }
@@ -702,24 +702,31 @@
  * also note that seeking relative to the "end of file" isn't supported:
  * it has no meaning, so it returns -EINVAL.
  */
-static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
+static loff_t memory_lseek(struct file *file, loff_t offset, int orig)
 {
 	loff_t ret;
 
 	mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
 	switch (orig) {
-		case 0:
-			file->f_pos = offset;
-			ret = file->f_pos;
-			force_successful_syscall_return();
+	case SEEK_CUR:
+		offset += file->f_pos;
+		if ((unsigned long long)offset <
+		    (unsigned long long)file->f_pos) {
+			ret = -EOVERFLOW;
 			break;
-		case 1:
-			file->f_pos += offset;
-			ret = file->f_pos;
-			force_successful_syscall_return();
+		}
+	case SEEK_SET:
+		/* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */
+		if ((unsigned long long)offset >= ~0xFFFULL) {
+			ret = -EOVERFLOW;
 			break;
-		default:
-			ret = -EINVAL;
+		}
+		file->f_pos = offset;
+		ret = file->f_pos;
+		force_successful_syscall_return();
+		break;
+	default:
+		ret = -EINVAL;
 	}
 	mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
 	return ret;
@@ -803,7 +810,7 @@
 };
 #endif
 
-static ssize_t kmsg_write(struct file * file, const char __user * buf,
+static ssize_t kmsg_write(struct file *file, const char __user *buf,
 			  size_t count, loff_t *ppos)
 {
 	char *tmp;
@@ -825,7 +832,7 @@
 }
 
 static const struct file_operations kmsg_fops = {
-	.write =	kmsg_write,
+	.write = kmsg_write,
 };
 
 static const struct memdev {
@@ -876,7 +883,7 @@
 }
 
 static const struct file_operations memory_fops = {
-	.open		= memory_open,
+	.open = memory_open,
 };
 
 static char *mem_devnode(struct device *dev, mode_t *mode)
@@ -897,7 +904,7 @@
 	if (err)
 		return err;
 
-	if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
+	if (register_chrdev(MEM_MAJOR, "mem", &memory_fops))
 		printk("unable to get major %d for memory devs\n", MEM_MAJOR);
 
 	mem_class = class_create(THIS_MODULE, "mem");
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 918711a..04fd0d8 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -546,7 +546,7 @@
 {
 	int nodeid = data;
 	struct mmtimer_node *mn = &timers[nodeid];
-	struct mmtimer *x = rb_entry(mn->next, struct mmtimer, list);
+	struct mmtimer *x;
 	struct k_itimer *t;
 	unsigned long flags;
 
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 63ee3bb..166495d 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -164,24 +164,25 @@
 static unsigned int moxaLowWaterChk;
 static DEFINE_MUTEX(moxa_openlock);
 static DEFINE_SPINLOCK(moxa_lock);
-/* Variables for insmod */
-#ifdef MODULE
+
 static unsigned long baseaddr[MAX_BOARDS];
 static unsigned int type[MAX_BOARDS];
 static unsigned int numports[MAX_BOARDS];
-#endif
 
 MODULE_AUTHOR("William Chen");
 MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
 MODULE_LICENSE("GPL");
-#ifdef MODULE
+MODULE_FIRMWARE("c218tunx.cod");
+MODULE_FIRMWARE("cp204unx.cod");
+MODULE_FIRMWARE("c320tunx.cod");
+
 module_param_array(type, uint, NULL, 0);
 MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
 module_param_array(baseaddr, ulong, NULL, 0);
 MODULE_PARM_DESC(baseaddr, "base address");
 module_param_array(numports, uint, NULL, 0);
 MODULE_PARM_DESC(numports, "numports (ignored for C218)");
-#endif
+
 module_param(ttymajor, int, 0);
 
 /*
@@ -1024,6 +1025,8 @@
 {
 	unsigned int isabrds = 0;
 	int retval = 0;
+	struct moxa_board_conf *brd = moxa_boards;
+	unsigned int i;
 
 	printk(KERN_INFO "MOXA Intellio family driver version %s\n",
 			MOXA_VERSION);
@@ -1051,10 +1054,7 @@
 	}
 
 	/* Find the boards defined from module args. */
-#ifdef MODULE
-	{
-	struct moxa_board_conf *brd = moxa_boards;
-	unsigned int i;
+
 	for (i = 0; i < MAX_BOARDS; i++) {
 		if (!baseaddr[i])
 			break;
@@ -1087,8 +1087,6 @@
 			isabrds++;
 		}
 	}
-	}
-#endif
 
 #ifdef CONFIG_PCI
 	retval = pci_register_driver(&moxa_pci_driver);
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 3d92306..e0c5d2a 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -895,8 +895,7 @@
 	if (inb(info->ioaddr + UART_LSR) == 0xff) {
 		spin_unlock_irqrestore(&info->slock, flags);
 		if (capable(CAP_SYS_ADMIN)) {
-			if (tty)
-				set_bit(TTY_IO_ERROR, &tty->flags);
+			set_bit(TTY_IO_ERROR, &tty->flags);
 			return 0;
 		} else
 			return -ENODEV;
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 2e50f4d..bdae832 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -48,6 +48,7 @@
 #include <linux/audit.h>
 #include <linux/file.h>
 #include <linux/uaccess.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 
@@ -2091,3 +2092,19 @@
 	.receive_buf     = n_tty_receive_buf,
 	.write_wakeup    = n_tty_write_wakeup
 };
+
+/**
+ *	n_tty_inherit_ops	-	inherit N_TTY methods
+ *	@ops: struct tty_ldisc_ops where to save N_TTY methods
+ *
+ *	Used by a generic struct tty_ldisc_ops to easily inherit N_TTY
+ *	methods.
+ */
+
+void n_tty_inherit_ops(struct tty_ldisc_ops *ops)
+{
+	*ops = tty_ldisc_N_TTY;
+	ops->owner = NULL;
+	ops->refcount = ops->flags = 0;
+}
+EXPORT_SYMBOL_GPL(n_tty_inherit_ops);
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 2ad7d37..a3f32a1 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -136,10 +136,6 @@
 #define RECEIVE_BUF_MAX		4
 
 
-/* Define all types of vendors and devices to support */
-#define VENDOR1		0x1931	/* Vendor Option */
-#define DEVICE1		0x000c	/* HSDPA card */
-
 #define R_IIR		0x0000	/* Interrupt Identity Register */
 #define R_FCR		0x0000	/* Flow Control Register */
 #define R_IER		0x0004	/* Interrupt Enable Register */
@@ -371,6 +367,8 @@
 	struct mutex tty_sem;
 	wait_queue_head_t tty_wait;
 	struct async_icount tty_icount;
+
+	struct nozomi *dc;
 };
 
 /* Private data one for each card in the system */
@@ -405,7 +403,7 @@
 
 /*    Global variables */
 static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
-	{PCI_DEVICE(VENDOR1, DEVICE1)},
+	{PCI_DEVICE(0x1931, 0x000c)},	/* Nozomi HSDPA */
 	{},
 };
 
@@ -414,6 +412,8 @@
 static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
 static struct tty_driver *ntty_driver;
 
+static const struct tty_port_operations noz_tty_port_ops;
+
 /*
  * find card by tty_index
  */
@@ -853,8 +853,6 @@
 		goto put;
 	}
 
-	tty_buffer_request_room(tty, size);
-
 	while (size > 0) {
 		read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX);
 
@@ -1473,9 +1471,11 @@
 
 	for (i = 0; i < MAX_PORT; i++) {
 		struct device *tty_dev;
-
-		mutex_init(&dc->port[i].tty_sem);
-		tty_port_init(&dc->port[i].port);
+		struct port *port = &dc->port[i];
+		port->dc = dc;
+		mutex_init(&port->tty_sem);
+		tty_port_init(&port->port);
+		port->port.ops = &noz_tty_port_ops;
 		tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
 							&pdev->dev);
 
@@ -1600,67 +1600,74 @@
  * ----------------------------------------------------------------------------
  */
 
-/* Called when the userspace process opens the tty, /dev/noz*.  */
-static int ntty_open(struct tty_struct *tty, struct file *file)
+static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
 {
 	struct port *port = get_port_by_tty(tty);
 	struct nozomi *dc = get_dc_by_tty(tty);
-	unsigned long flags;
-
+	int ret;
 	if (!port || !dc || dc->state != NOZOMI_STATE_READY)
 		return -ENODEV;
-
-	if (mutex_lock_interruptible(&port->tty_sem))
-		return -ERESTARTSYS;
-
-	port->port.count++;
-	dc->open_ttys++;
-
-	/* Enable interrupt downlink for channel */
-	if (port->port.count == 1) {
-		tty->driver_data = port;
-		tty_port_tty_set(&port->port, tty);
-		DBG1("open: %d", port->token_dl);
-		spin_lock_irqsave(&dc->spin_mutex, flags);
-		dc->last_ier = dc->last_ier | port->token_dl;
-		writew(dc->last_ier, dc->reg_ier);
-		spin_unlock_irqrestore(&dc->spin_mutex, flags);
+	ret = tty_init_termios(tty);
+	if (ret == 0) {
+		tty_driver_kref_get(driver);
+		driver->ttys[tty->index] = tty;
 	}
-	mutex_unlock(&port->tty_sem);
+	return ret;
+}
+
+static void ntty_cleanup(struct tty_struct *tty)
+{
+	tty->driver_data = NULL;
+}
+
+static int ntty_activate(struct tty_port *tport, struct tty_struct *tty)
+{
+	struct port *port = container_of(tport, struct port, port);
+	struct nozomi *dc = port->dc;
+	unsigned long flags;
+
+	DBG1("open: %d", port->token_dl);
+	spin_lock_irqsave(&dc->spin_mutex, flags);
+	dc->last_ier = dc->last_ier | port->token_dl;
+	writew(dc->last_ier, dc->reg_ier);
+	dc->open_ttys++;
+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
+	printk("noz: activated %d: %p\n", tty->index, tport);
 	return 0;
 }
 
-/* Called when the userspace process close the tty, /dev/noz*. Also
-   called immediately if ntty_open fails in which case tty->driver_data
-   will be NULL an we exit by the first return */
-
-static void ntty_close(struct tty_struct *tty, struct file *file)
+static int ntty_open(struct tty_struct *tty, struct file *filp)
 {
-	struct nozomi *dc = get_dc_by_tty(tty);
-	struct port *nport = tty->driver_data;
-	struct tty_port *port = &nport->port;
+	struct port *port = get_port_by_tty(tty);
+	return tty_port_open(&port->port, tty, filp);
+}
+
+static void ntty_shutdown(struct tty_port *tport)
+{
+	struct port *port = container_of(tport, struct port, port);
+	struct nozomi *dc = port->dc;
 	unsigned long flags;
 
-	if (!dc || !nport)
-		return;
-
-	/* Users cannot interrupt a close */
-	mutex_lock(&nport->tty_sem);
-
-	WARN_ON(!port->count);
-
+	DBG1("close: %d", port->token_dl);
+	spin_lock_irqsave(&dc->spin_mutex, flags);
+	dc->last_ier &= ~(port->token_dl);
+	writew(dc->last_ier, dc->reg_ier);
 	dc->open_ttys--;
-	port->count--;
+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
+	printk("noz: shutdown %p\n", tport);
+}
 
-	if (port->count == 0) {
-		DBG1("close: %d", nport->token_dl);
-		tty_port_tty_set(port, NULL);
-		spin_lock_irqsave(&dc->spin_mutex, flags);
-		dc->last_ier &= ~(nport->token_dl);
-		writew(dc->last_ier, dc->reg_ier);
-		spin_unlock_irqrestore(&dc->spin_mutex, flags);
-	}
-	mutex_unlock(&nport->tty_sem);
+static void ntty_close(struct tty_struct *tty, struct file *filp)
+{
+	struct port *port = tty->driver_data;
+	if (port)
+		tty_port_close(&port->port, tty, filp);
+}
+
+static void ntty_hangup(struct tty_struct *tty)
+{
+	struct port *port = tty->driver_data;
+	tty_port_hangup(&port->port);
 }
 
 /*
@@ -1680,15 +1687,7 @@
 	if (!dc || !port)
 		return -ENODEV;
 
-	if (unlikely(!mutex_trylock(&port->tty_sem))) {
-		/*
-		 * must test lock as tty layer wraps calls
-		 * to this function with BKL
-		 */
-		dev_err(&dc->pdev->dev, "Would have deadlocked - "
-			"return EAGAIN\n");
-		return -EAGAIN;
-	}
+	mutex_lock(&port->tty_sem);
 
 	if (unlikely(!port->port.count)) {
 		DBG1(" ");
@@ -1728,25 +1727,23 @@
  * This method is called by the upper tty layer.
  *   #according to sources N_TTY.c it expects a value >= 0 and
  *    does not check for negative values.
+ *
+ * If the port is unplugged report lots of room and let the bits
+ * dribble away so we don't block anything.
  */
 static int ntty_write_room(struct tty_struct *tty)
 {
 	struct port *port = tty->driver_data;
-	int room = 0;
+	int room = 4096;
 	const struct nozomi *dc = get_dc_by_tty(tty);
 
-	if (!dc || !port)
-		return 0;
-	if (!mutex_trylock(&port->tty_sem))
-		return 0;
-
-	if (!port->port.count)
-		goto exit;
-
-	room = port->fifo_ul.size - kfifo_len(&port->fifo_ul);
-
-exit:
-	mutex_unlock(&port->tty_sem);
+	if (dc) {
+		mutex_lock(&port->tty_sem);
+		if (port->port.count)
+			room = port->fifo_ul.size -
+					kfifo_len(&port->fifo_ul);
+		mutex_unlock(&port->tty_sem);
+	}
 	return room;
 }
 
@@ -1906,10 +1903,16 @@
 	return rval;
 }
 
+static const struct tty_port_operations noz_tty_port_ops = {
+	.activate = ntty_activate,
+	.shutdown = ntty_shutdown,
+};
+
 static const struct tty_operations tty_ops = {
 	.ioctl = ntty_ioctl,
 	.open = ntty_open,
 	.close = ntty_close,
+	.hangup = ntty_hangup,
 	.write = ntty_write,
 	.write_room = ntty_write_room,
 	.unthrottle = ntty_unthrottle,
@@ -1917,6 +1920,8 @@
 	.chars_in_buffer = ntty_chars_in_buffer,
 	.tiocmget = ntty_tiocmget,
 	.tiocmset = ntty_tiocmset,
+	.install = ntty_install,
+	.cleanup = ntty_cleanup,
 };
 
 /* Module initialization */
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 385c44b..5ee4248 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -220,7 +220,7 @@
  *	@tty: tty being resized
  *	@ws: window size being set.
  *
- *	Update the termios variables and send the neccessary signals to
+ *	Update the termios variables and send the necessary signals to
  *	peform a terminal resize correctly
  */
 
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 2849713..2fd3d39 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1191,7 +1191,7 @@
 void generate_random_uuid(unsigned char uuid_out[16])
 {
 	get_random_bytes(uuid_out, 16);
-	/* Set UUID version to 4 --- truely random generation */
+	/* Set UUID version to 4 --- truly random generation */
 	uuid_out[6] = (uuid_out[6] & 0x0F) | 0x40;
 	/* Set the UUID variant to DCE */
 	uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80;
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 452370a..1ec3d5c 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -658,8 +658,7 @@
 			info->mon.char_max = char_count;
 		info->mon.char_last = char_count;
 #endif
-		len = tty_buffer_request_room(tty, char_count);
-		while (len--) {
+		while (char_count--) {
 			data = base_addr[CyRDR];
 			tty_insert_flip_char(tty, data, TTY_NORMAL);
 #ifdef CYCLOM_16Y_HACK
@@ -1990,7 +1989,7 @@
 	/*
 	 * Attempt to set up all channels to something reasonable, and
 	 * bang out a INIT_CHAN command.  We should then be able to limit
-	 * the ammount of fiddling we have to do in normal running.
+	 * the amount of fiddling we have to do in normal running.
 	 */
 
 	for (ch = 3; ch >= 0; ch--) {
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 268e17f..07ac14d 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -646,8 +646,6 @@
 	dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
 	port->hits[count > 8 ? 9 : count]++;
 
-	tty_buffer_request_room(tty, count);
-
 	while (count--)
 		tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
 	tty_flip_buffer_push(tty);
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 4846b73..0658fc5 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2031,7 +2031,7 @@
 	if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char"))
 		return 0;
 
-	if (!tty || !info->xmit_buf)
+	if (!info->xmit_buf)
 		return 0;
 
 	spin_lock_irqsave(&info->irq_spinlock, flags);
@@ -2121,7 +2121,7 @@
 	if (mgsl_paranoia_check(info, tty->name, "mgsl_write"))
 		goto cleanup;
 
-	if (!tty || !info->xmit_buf)
+	if (!info->xmit_buf)
 		goto cleanup;
 
 	if ( info->params.mode == MGSL_MODE_HDLC ||
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 8678f0c..4561ce2 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -468,7 +468,7 @@
 static unsigned int tbuf_bytes(struct slgt_info *info);
 static void reset_tbufs(struct slgt_info *info);
 static void tdma_reset(struct slgt_info *info);
-static void tx_load(struct slgt_info *info, const char *buf, unsigned int count);
+static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count);
 
 static void get_signals(struct slgt_info *info);
 static void set_signals(struct slgt_info *info);
@@ -813,59 +813,32 @@
 	int ret = 0;
 	struct slgt_info *info = tty->driver_data;
 	unsigned long flags;
-	unsigned int bufs_needed;
 
 	if (sanity_check(info, tty->name, "write"))
-		goto cleanup;
+		return -EIO;
+
 	DBGINFO(("%s write count=%d\n", info->device_name, count));
 
-	if (!info->tx_buf)
-		goto cleanup;
+	if (!info->tx_buf || (count > info->max_frame_size))
+		return -EIO;
 
-	if (count > info->max_frame_size) {
-		ret = -EIO;
-		goto cleanup;
-	}
+	if (!count || tty->stopped || tty->hw_stopped)
+		return 0;
 
-	if (!count)
-		goto cleanup;
+	spin_lock_irqsave(&info->lock, flags);
 
-	if (!info->tx_active && info->tx_count) {
+	if (info->tx_count) {
 		/* send accumulated data from send_char() */
-		tx_load(info, info->tx_buf, info->tx_count);
-		goto start;
+		if (!tx_load(info, info->tx_buf, info->tx_count))
+			goto cleanup;
+		info->tx_count = 0;
 	}
-	bufs_needed = (count/DMABUFSIZE);
-	if (count % DMABUFSIZE)
-		++bufs_needed;
-	if (bufs_needed > free_tbuf_count(info))
-		goto cleanup;
 
-	ret = info->tx_count = count;
-	tx_load(info, buf, count);
-	goto start;
-
-start:
- 	if (info->tx_count && !tty->stopped && !tty->hw_stopped) {
-		spin_lock_irqsave(&info->lock,flags);
-		if (!info->tx_active)
-		 	tx_start(info);
-		else if (!(rd_reg32(info, TDCSR) & BIT0)) {
-			/* transmit still active but transmit DMA stopped */
-			unsigned int i = info->tbuf_current;
-			if (!i)
-				i = info->tbuf_count;
-			i--;
-			/* if DMA buf unsent must try later after tx idle */
-			if (desc_count(info->tbufs[i]))
-				ret = 0;
-		}
-		if (ret > 0)
-			update_tx_timer(info);
-		spin_unlock_irqrestore(&info->lock,flags);
- 	}
+	if (tx_load(info, buf, count))
+		ret = count;
 
 cleanup:
+	spin_unlock_irqrestore(&info->lock, flags);
 	DBGINFO(("%s write rc=%d\n", info->device_name, ret));
 	return ret;
 }
@@ -882,7 +855,7 @@
 	if (!info->tx_buf)
 		return 0;
 	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_active && (info->tx_count < info->max_frame_size)) {
+	if (info->tx_count < info->max_frame_size) {
 		info->tx_buf[info->tx_count++] = ch;
 		ret = 1;
 	}
@@ -981,10 +954,8 @@
 	DBGINFO(("%s flush_chars start transmit\n", info->device_name));
 
 	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_active && info->tx_count) {
-		tx_load(info, info->tx_buf,info->tx_count);
-	 	tx_start(info);
-	}
+	if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
+		info->tx_count = 0;
 	spin_unlock_irqrestore(&info->lock,flags);
 }
 
@@ -997,10 +968,9 @@
 		return;
 	DBGINFO(("%s flush_buffer\n", info->device_name));
 
-	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_active)
-		info->tx_count = 0;
-	spin_unlock_irqrestore(&info->lock,flags);
+	spin_lock_irqsave(&info->lock, flags);
+	info->tx_count = 0;
+	spin_unlock_irqrestore(&info->lock, flags);
 
 	tty_wakeup(tty);
 }
@@ -1033,12 +1003,10 @@
 	if (sanity_check(info, tty->name, "tx_release"))
 		return;
 	DBGINFO(("%s tx_release\n", info->device_name));
-	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_active && info->tx_count) {
-		tx_load(info, info->tx_buf, info->tx_count);
-	 	tx_start(info);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
+	spin_lock_irqsave(&info->lock, flags);
+	if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
+		info->tx_count = 0;
+	spin_unlock_irqrestore(&info->lock, flags);
 }
 
 /*
@@ -1506,27 +1474,25 @@
 
 	DBGINFO(("%s hdlc_xmit\n", dev->name));
 
+	if (!skb->len)
+		return NETDEV_TX_OK;
+
 	/* stop sending until this frame completes */
 	netif_stop_queue(dev);
 
-	/* copy data to device buffers */
-	info->tx_count = skb->len;
-	tx_load(info, skb->data, skb->len);
-
 	/* update network statistics */
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
 
-	/* done with socket buffer, so free it */
-	dev_kfree_skb(skb);
-
 	/* save start time for transmit timeout detection */
 	dev->trans_start = jiffies;
 
-	spin_lock_irqsave(&info->lock,flags);
-	tx_start(info);
-	update_tx_timer(info);
-	spin_unlock_irqrestore(&info->lock,flags);
+	spin_lock_irqsave(&info->lock, flags);
+	tx_load(info, skb->data, skb->len);
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	/* done with socket buffer, so free it */
+	dev_kfree_skb(skb);
 
 	return NETDEV_TX_OK;
 }
@@ -2180,7 +2146,7 @@
 
 	if (info->params.mode == MGSL_MODE_ASYNC) {
 		if (status & IRQ_TXIDLE) {
-			if (info->tx_count)
+			if (info->tx_active)
 				isr_txeom(info, status);
 		}
 		if (info->rx_pio && (status & IRQ_RXDATA))
@@ -2276,13 +2242,42 @@
 	}
 }
 
+/*
+ * return true if there are unsent tx DMA buffers, otherwise false
+ *
+ * if there are unsent buffers then info->tbuf_start
+ * is set to index of first unsent buffer
+ */
+static bool unsent_tbufs(struct slgt_info *info)
+{
+	unsigned int i = info->tbuf_current;
+	bool rc = false;
+
+	/*
+	 * search backwards from last loaded buffer (precedes tbuf_current)
+	 * for first unsent buffer (desc_count > 0)
+	 */
+
+	do {
+		if (i)
+			i--;
+		else
+			i = info->tbuf_count - 1;
+		if (!desc_count(info->tbufs[i]))
+			break;
+		info->tbuf_start = i;
+		rc = true;
+	} while (i != info->tbuf_current);
+
+	return rc;
+}
+
 static void isr_txeom(struct slgt_info *info, unsigned short status)
 {
 	DBGISR(("%s txeom status=%04x\n", info->device_name, status));
 
 	slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
 	tdma_reset(info);
-	reset_tbufs(info);
 	if (status & IRQ_TXUNDER) {
 		unsigned short val = rd_reg16(info, TCR);
 		wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
@@ -2297,8 +2292,12 @@
 				info->icount.txok++;
 		}
 
+		if (unsent_tbufs(info)) {
+			tx_start(info);
+			update_tx_timer(info);
+			return;
+		}
 		info->tx_active = false;
-		info->tx_count = 0;
 
 		del_timer(&info->tx_timer);
 
@@ -3949,7 +3948,7 @@
 		info->tx_enabled = true;
 	}
 
-	if (info->tx_count) {
+	if (desc_count(info->tbufs[info->tbuf_start])) {
 		info->drop_rts_on_tx_done = false;
 
 		if (info->params.mode != MGSL_MODE_ASYNC) {
@@ -4772,25 +4771,36 @@
 }
 
 /*
- * load transmit DMA buffer(s) with data
+ * load data into transmit DMA buffer ring and start transmitter if needed
+ * return true if data accepted, otherwise false (buffers full)
  */
-static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
+static bool tx_load(struct slgt_info *info, const char *buf, unsigned int size)
 {
 	unsigned short count;
 	unsigned int i;
 	struct slgt_desc *d;
 
-	if (size == 0)
-		return;
+	/* check required buffer space */
+	if (DIV_ROUND_UP(size, DMABUFSIZE) > free_tbuf_count(info))
+		return false;
 
 	DBGDATA(info, buf, size, "tx");
 
+	/*
+	 * copy data to one or more DMA buffers in circular ring
+	 * tbuf_start   = first buffer for this data
+	 * tbuf_current = next free buffer
+	 *
+	 * Copy all data before making data visible to DMA controller by
+	 * setting descriptor count of the first buffer.
+	 * This prevents an active DMA controller from reading the first DMA
+	 * buffers of a frame and stopping before the final buffers are filled.
+	 */
+
 	info->tbuf_start = i = info->tbuf_current;
 
 	while (size) {
 		d = &info->tbufs[i];
-		if (++i == info->tbuf_count)
-			i = 0;
 
 		count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size);
 		memcpy(d->buf, buf, count);
@@ -4808,11 +4818,27 @@
 		else
 			set_desc_eof(*d, 0);
 
-		set_desc_count(*d, count);
+		/* set descriptor count for all but first buffer */
+		if (i != info->tbuf_start)
+			set_desc_count(*d, count);
 		d->buf_count = count;
+
+		if (++i == info->tbuf_count)
+			i = 0;
 	}
 
 	info->tbuf_current = i;
+
+	/* set first buffer count to make new data visible to DMA controller */
+	d = &info->tbufs[info->tbuf_start];
+	set_desc_count(*d, d->buf_count);
+
+	/* start transmitter if needed and update transmit timeout */
+	if (!info->tx_active)
+		tx_start(info);
+	update_tx_timer(info);
+
+	return true;
 }
 
 static int register_test(struct slgt_info *info)
@@ -4934,9 +4960,7 @@
 	spin_lock_irqsave(&info->lock,flags);
 	async_mode(info);
 	rx_start(info);
-	info->tx_count = count;
 	tx_load(info, buf, count);
-	tx_start(info);
 	spin_unlock_irqrestore(&info->lock, flags);
 
 	/* wait for receive complete */
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
index ac16fbe..283a15b 100644
--- a/drivers/char/tty_audit.c
+++ b/drivers/char/tty_audit.c
@@ -148,7 +148,6 @@
 	spin_lock_irq(&current->sighand->siglock);
 	sig->audit_tty = current->signal->audit_tty;
 	spin_unlock_irq(&current->sighand->siglock);
-	sig->tty_audit_buf = NULL;
 }
 
 /**
diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c
index 66fa4e1..af8d977 100644
--- a/drivers/char/tty_buffer.c
+++ b/drivers/char/tty_buffer.c
@@ -231,9 +231,10 @@
 EXPORT_SYMBOL_GPL(tty_buffer_request_room);
 
 /**
- *	tty_insert_flip_string	-	Add characters to the tty buffer
+ *	tty_insert_flip_string_fixed_flag - Add characters to the tty buffer
  *	@tty: tty structure
  *	@chars: characters
+ *	@flag: flag value for each character
  *	@size: size
  *
  *	Queue a series of bytes to the tty buffering. All the characters
@@ -242,18 +243,19 @@
  *	Locking: Called functions may take tty->buf.lock
  */
 
-int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
-				size_t size)
+int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
+		const unsigned char *chars, char flag, size_t size)
 {
 	int copied = 0;
 	do {
-		int space = tty_buffer_request_room(tty, size - copied);
+		int goal = min(size - copied, TTY_BUFFER_PAGE);
+		int space = tty_buffer_request_room(tty, goal);
 		struct tty_buffer *tb = tty->buf.tail;
 		/* If there is no space then tb may be NULL */
 		if (unlikely(space == 0))
 			break;
 		memcpy(tb->char_buf_ptr + tb->used, chars, space);
-		memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+		memset(tb->flag_buf_ptr + tb->used, flag, space);
 		tb->used += space;
 		copied += space;
 		chars += space;
@@ -262,7 +264,7 @@
 	} while (unlikely(size > copied));
 	return copied;
 }
-EXPORT_SYMBOL(tty_insert_flip_string);
+EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
 
 /**
  *	tty_insert_flip_string_flags	-	Add characters to the tty buffer
@@ -283,7 +285,8 @@
 {
 	int copied = 0;
 	do {
-		int space = tty_buffer_request_room(tty, size - copied);
+		int goal = min(size - copied, TTY_BUFFER_PAGE);
+		int space = tty_buffer_request_room(tty, goal);
 		struct tty_buffer *tb = tty->buf.tail;
 		/* If there is no space then tb may be NULL */
 		if (unlikely(space == 0))
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index dcb9083..a42c466 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2028,7 +2028,7 @@
  *	@rows: rows (character)
  *	@cols: cols (character)
  *
- *	Update the termios variables and send the neccessary signals to
+ *	Update the termios variables and send the necessary signals to
  *	peform a terminal resize correctly
  */
 
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index 3f653f7..500e740 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -706,12 +706,13 @@
 /**
  *	tty_ldisc_reinit	-	reinitialise the tty ldisc
  *	@tty: tty to reinit
+ *	@ldisc: line discipline to reinitialize
  *
- *	Switch the tty back to N_TTY line discipline and leave the
- *	ldisc state closed
+ *	Switch the tty to a line discipline and leave the ldisc
+ *	state closed
  */
 
-static void tty_ldisc_reinit(struct tty_struct *tty)
+static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
 {
 	struct tty_ldisc *ld;
 
@@ -721,10 +722,10 @@
 	/*
 	 *	Switch the line discipline back
 	 */
-	ld = tty_ldisc_get(N_TTY);
+	ld = tty_ldisc_get(ldisc);
 	BUG_ON(IS_ERR(ld));
 	tty_ldisc_assign(tty, ld);
-	tty_set_termios_ldisc(tty, N_TTY);
+	tty_set_termios_ldisc(tty, ldisc);
 }
 
 /**
@@ -745,6 +746,8 @@
 void tty_ldisc_hangup(struct tty_struct *tty)
 {
 	struct tty_ldisc *ld;
+	int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
+	int err = 0;
 
 	/*
 	 * FIXME! What are the locking issues here? This may me overdoing
@@ -772,25 +775,32 @@
 	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 	/*
 	 * Shutdown the current line discipline, and reset it to
-	 * N_TTY.
+	 * N_TTY if need be.
+	 *
+	 * Avoid racing set_ldisc or tty_ldisc_release
 	 */
-	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-		/* Avoid racing set_ldisc or tty_ldisc_release */
-		mutex_lock(&tty->ldisc_mutex);
-		tty_ldisc_halt(tty);
-		if (tty->ldisc) {	/* Not yet closed */
-			/* Switch back to N_TTY */
-			tty_ldisc_reinit(tty);
-			/* At this point we have a closed ldisc and we want to
-			   reopen it. We could defer this to the next open but
-			   it means auditing a lot of other paths so this is
-			   a FIXME */
-			WARN_ON(tty_ldisc_open(tty, tty->ldisc));
-			tty_ldisc_enable(tty);
+	mutex_lock(&tty->ldisc_mutex);
+	tty_ldisc_halt(tty);
+	/* At this point we have a closed ldisc and we want to
+	   reopen it. We could defer this to the next open but
+	   it means auditing a lot of other paths so this is
+	   a FIXME */
+	if (tty->ldisc) {	/* Not yet closed */
+		if (reset == 0) {
+			tty_ldisc_reinit(tty, tty->termios->c_line);
+			err = tty_ldisc_open(tty, tty->ldisc);
 		}
-		mutex_unlock(&tty->ldisc_mutex);
-		tty_reset_termios(tty);
+		/* If the re-open fails or we reset then go to N_TTY. The
+		   N_TTY open cannot fail */
+		if (reset || err) {
+			tty_ldisc_reinit(tty, N_TTY);
+			WARN_ON(tty_ldisc_open(tty, tty->ldisc));
+		}
+		tty_ldisc_enable(tty);
 	}
+	mutex_unlock(&tty->ldisc_mutex);
+	if (reset)
+		tty_reset_termios(tty);
 }
 
 /**
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 213373b..f404ccf 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -379,7 +379,7 @@
 	struct scatterlist sg[1];
 	struct virtio_console_control cpkt;
 	struct virtqueue *vq;
-	int len;
+	unsigned int len;
 
 	if (!use_multiport(port->portdev))
 		return 0;
@@ -1071,27 +1071,27 @@
 static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
 {
 	struct port_buffer *buf;
-	unsigned int ret;
-	int err;
+	unsigned int nr_added_bufs;
+	int ret;
 
-	ret = 0;
+	nr_added_bufs = 0;
 	do {
 		buf = alloc_buf(PAGE_SIZE);
 		if (!buf)
 			break;
 
 		spin_lock_irq(lock);
-		err = add_inbuf(vq, buf);
-		if (err < 0) {
+		ret = add_inbuf(vq, buf);
+		if (ret < 0) {
 			spin_unlock_irq(lock);
 			free_buf(buf);
 			break;
 		}
-		ret++;
+		nr_added_bufs++;
 		spin_unlock_irq(lock);
-	} while (err > 0);
+	} while (ret > 0);
 
-	return ret;
+	return nr_added_bufs;
 }
 
 static int add_port(struct ports_device *portdev, u32 id)
@@ -1100,6 +1100,7 @@
 	struct port *port;
 	struct port_buffer *buf;
 	dev_t devt;
+	unsigned int nr_added_bufs;
 	int err;
 
 	port = kmalloc(sizeof(*port), GFP_KERNEL);
@@ -1144,8 +1145,8 @@
 	init_waitqueue_head(&port->waitqueue);
 
 	/* Fill the in_vq with buffers so the host can send us data. */
-	err = fill_queue(port->in_vq, &port->inbuf_lock);
-	if (!err) {
+	nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock);
+	if (!nr_added_bufs) {
 		dev_err(port->dev, "Error allocating inbufs\n");
 		err = -ENOMEM;
 		goto free_device;
@@ -1442,12 +1443,14 @@
 	INIT_LIST_HEAD(&portdev->ports);
 
 	if (multiport) {
+		unsigned int nr_added_bufs;
+
 		spin_lock_init(&portdev->cvq_lock);
 		INIT_WORK(&portdev->control_work, &control_work_handler);
 		INIT_WORK(&portdev->config_work, &config_work_handler);
 
-		err = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
-		if (!err) {
+		nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+		if (!nr_added_bufs) {
 			dev_err(&vdev->dev,
 				"Error allocating buffers for control queue\n");
 			err = -ENOMEM;
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 50faa1f..bd1d116 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -821,7 +821,7 @@
  *
  *	Resize a virtual console, clipping according to the actual constraints.
  *	If the caller passes a tty structure then update the termios winsize
- *	information and perform any neccessary signal handling.
+ *	information and perform any necessary signal handling.
  *
  *	Caller must hold the console semaphore. Takes the termios mutex and
  *	ctrl_lock of the tty IFF a tty is passed.
@@ -2119,8 +2119,6 @@
 	uint8_t inverse;
 	uint8_t width;
 	u16 himask, charmask;
-	const unsigned char *orig_buf = NULL;
-	int orig_count;
 
 	if (in_interrupt())
 		return count;
@@ -2142,8 +2140,6 @@
 	    release_console_sem();
 	    return 0;
 	}
-	orig_buf = buf;
-	orig_count = count;
 
 	himask = vc->vc_hi_font_mask;
 	charmask = himask ? 0x1ff : 0xff;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 6aa1028..87778dc 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -888,7 +888,7 @@
 			ret = -EFAULT;
 			goto out;
 		}
-		if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) {
+		if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS && tmp.mode != VT_PROCESS_AUTO) {
 			ret = -EINVAL;
 			goto out;
 		}
@@ -1622,7 +1622,7 @@
 	 * telling it that it has acquired. Also check if it has died and
 	 * clean up (similar to logic employed in change_console())
 	 */
-	if (vc->vt_mode.mode == VT_PROCESS) {
+	if (vc->vt_mode.mode == VT_PROCESS || vc->vt_mode.mode == VT_PROCESS_AUTO) {
 		/*
 		 * Send the signal as privileged - kill_pid() will
 		 * tell us if the process has gone or something else
@@ -1682,7 +1682,7 @@
 	 * vt to auto control.
 	 */
 	vc = vc_cons[fg_console].d;
-	if (vc->vt_mode.mode == VT_PROCESS) {
+	if (vc->vt_mode.mode == VT_PROCESS || vc->vt_mode.mode == VT_PROCESS_AUTO) {
 		/*
 		 * Send the signal as privileged - kill_pid() will
 		 * tell us if the process has gone or something else
@@ -1693,27 +1693,28 @@
 		 */
 		vc->vt_newvt = new_vc->vc_num;
 		if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
+			if(vc->vt_mode.mode == VT_PROCESS)
+				/*
+				 * It worked. Mark the vt to switch to and
+				 * return. The process needs to send us a
+				 * VT_RELDISP ioctl to complete the switch.
+				 */
+				return;
+		} else {
 			/*
-			 * It worked. Mark the vt to switch to and
-			 * return. The process needs to send us a
-			 * VT_RELDISP ioctl to complete the switch.
+			 * The controlling process has died, so we revert back to
+			 * normal operation. In this case, we'll also change back
+			 * to KD_TEXT mode. I'm not sure if this is strictly correct
+			 * but it saves the agony when the X server dies and the screen
+			 * remains blanked due to KD_GRAPHICS! It would be nice to do
+			 * this outside of VT_PROCESS but there is no single process
+			 * to account for and tracking tty count may be undesirable.
 			 */
-			return;
+			reset_vc(vc);
 		}
 
 		/*
-		 * The controlling process has died, so we revert back to
-		 * normal operation. In this case, we'll also change back
-		 * to KD_TEXT mode. I'm not sure if this is strictly correct
-		 * but it saves the agony when the X server dies and the screen
-		 * remains blanked due to KD_GRAPHICS! It would be nice to do
-		 * this outside of VT_PROCESS but there is no single process
-		 * to account for and tracking tty count may be undesirable.
-		 */
-		reset_vc(vc);
-
-		/*
-		 * Fall through to normal (VT_AUTO) handling of the switch...
+		 * Fall through to normal (VT_AUTO and VT_PROCESS_AUTO) handling of the switch...
 		 */
 	}
 
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
deleted file mode 100644
index 08f726c..0000000
--- a/drivers/clocksource/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-config CS5535_CLOCK_EVENT_SRC
-	tristate "CS5535/CS5536 high-res timer (MFGPT) events"
-	depends on GENERIC_TIME && GENERIC_CLOCKEVENTS && CS5535_MFGPT
-	help
-	  This driver provides a clock event source based on the MFGPT
-	  timer(s) in the CS5535 and CS5536 companion chips.
-	  MFGPTs have a better resolution and max interval than the
-	  generic PIT, and are suitable for use as high-res timers.
-
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 67bc2ec..2d5d575 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -766,7 +766,7 @@
 	complete(&policy->kobj_unregister);
 }
 
-static struct sysfs_ops sysfs_ops = {
+static const struct sysfs_ops sysfs_ops = {
 	.show	= show,
 	.store	= store,
 };
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 73655ae..1aea715 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -100,8 +100,8 @@
 	int             needs_update;
 
 	unsigned int	expected_us;
-	u64		predicted_us;
 	unsigned int	measured_us;
+	u64		predicted_us;
 	unsigned int	exit_us;
 	unsigned int	bucket;
 	u64		correction_factor[BUCKETS];
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 97b0038..8719b36 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -22,6 +22,7 @@
 __setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
 
 static ssize_t show_available_governors(struct sysdev_class *class,
+					struct sysdev_class_attribute *attr,
 					char *buf)
 {
 	ssize_t i = 0;
@@ -41,6 +42,7 @@
 }
 
 static ssize_t show_current_driver(struct sysdev_class *class,
+				   struct sysdev_class_attribute *attr,
 				   char *buf)
 {
 	ssize_t ret;
@@ -56,6 +58,7 @@
 }
 
 static ssize_t show_current_governor(struct sysdev_class *class,
+				     struct sysdev_class_attribute *attr,
 				     char *buf)
 {
 	ssize_t ret;
@@ -71,6 +74,7 @@
 }
 
 static ssize_t store_current_governor(struct sysdev_class *class,
+				      struct sysdev_class_attribute *attr,
 				      const char *buf, size_t count)
 {
 	char gov_name[CPUIDLE_NAME_LEN];
@@ -191,7 +195,7 @@
 	return ret;
 }
 
-static struct sysfs_ops cpuidle_sysfs_ops = {
+static const struct sysfs_ops cpuidle_sysfs_ops = {
 	.show = cpuidle_show,
 	.store = cpuidle_store,
 };
@@ -277,7 +281,7 @@
 	return ret;
 }
 
-static struct sysfs_ops cpuidle_state_sysfs_ops = {
+static const struct sysfs_ops cpuidle_state_sysfs_ops = {
 	.show = cpuidle_state_show,
 };
 
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index 09ad915..73e8b17 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -321,7 +321,7 @@
 #define	HIFN_PUBOPLEN_MOD_M	0x0000007f	/* modulus length mask */
 #define	HIFN_PUBOPLEN_MOD_S	0		/* modulus length shift */
 #define	HIFN_PUBOPLEN_EXP_M	0x0003ff80	/* exponent length mask */
-#define	HIFN_PUBOPLEN_EXP_S	7		/* exponent lenght shift */
+#define	HIFN_PUBOPLEN_EXP_S	7		/* exponent length shift */
 #define	HIFN_PUBOPLEN_RED_M	0x003c0000	/* reducend length mask */
 #define	HIFN_PUBOPLEN_RED_S	18		/* reducend length shift */
 
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index e02d74b..c27f80e 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -13,6 +13,22 @@
 	  DMA Device drivers supported by the configured arch, it may
 	  be empty in some cases.
 
+config DMADEVICES_DEBUG
+        bool "DMA Engine debugging"
+        depends on DMADEVICES != n
+        help
+          This is an option for use by developers; most people should
+          say N here.  This enables DMA engine core and driver debugging.
+
+config DMADEVICES_VDEBUG
+        bool "DMA Engine verbose debugging"
+        depends on DMADEVICES_DEBUG != n
+        help
+          This is an option for use by developers; most people should
+          say N here.  This enables deeper (more verbose) debugging of
+          the DMA engine core and drivers.
+
+
 if DMADEVICES
 
 comment "DMA Devices"
@@ -69,6 +85,13 @@
 	  The Elo is the DMA controller on some 82xx and 83xx parts, and the
 	  Elo Plus is the DMA controller on 85xx and 86xx parts.
 
+config MPC512X_DMA
+	tristate "Freescale MPC512x built-in DMA engine support"
+	depends on PPC_MPC512x
+	select DMA_ENGINE
+	---help---
+	  Enable support for the Freescale MPC512x built-in DMA engine.
+
 config MV_XOR
 	bool "Marvell XOR engine support"
 	depends on PLAT_ORION
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 807053d..22bba3d 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -1,9 +1,17 @@
+ifeq ($(CONFIG_DMADEVICES_DEBUG),y)
+	EXTRA_CFLAGS	+= -DDEBUG
+endif
+ifeq ($(CONFIG_DMADEVICES_VDEBUG),y)
+	EXTRA_CFLAGS	+= -DVERBOSE_DEBUG
+endif
+
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
 obj-$(CONFIG_NET_DMA) += iovlock.o
 obj-$(CONFIG_DMATEST) += dmatest.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
 obj-$(CONFIG_MV_XOR) += mv_xor.o
 obj-$(CONFIG_DW_DMAC) += dw_dmac.o
 obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 64a9372..1656fdc 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -39,7 +39,6 @@
 	unsigned int sg_len;
 	struct coh901318_lli *data;
 	enum dma_data_direction dir;
-	int pending_irqs;
 	unsigned long flags;
 };
 
@@ -72,7 +71,6 @@
 
 	unsigned long nbr_active_done;
 	unsigned long busy;
-	int pending_irqs;
 
 	struct coh901318_base *base;
 };
@@ -80,18 +78,16 @@
 static void coh901318_list_print(struct coh901318_chan *cohc,
 				 struct coh901318_lli *lli)
 {
-	struct coh901318_lli *l;
-	dma_addr_t addr =  virt_to_phys(lli);
+	struct coh901318_lli *l = lli;
 	int i = 0;
 
-	while (addr) {
-		l = phys_to_virt(addr);
+	while (l) {
 		dev_vdbg(COHC_2_DEV(cohc), "i %d, lli %p, ctrl 0x%x, src 0x%x"
-			 ", dst 0x%x, link 0x%x link_virt 0x%p\n",
+			 ", dst 0x%x, link 0x%x virt_link_addr 0x%p\n",
 			 i, l, l->control, l->src_addr, l->dst_addr,
-			 l->link_addr, phys_to_virt(l->link_addr));
+			 l->link_addr, l->virt_link_addr);
 		i++;
-		addr = l->link_addr;
+		l = l->virt_link_addr;
 	}
 }
 
@@ -125,7 +121,7 @@
 		goto err_kmalloc;
 	tmp = dev_buf;
 
-	tmp += sprintf(tmp, "DMA -- enable dma channels\n");
+	tmp += sprintf(tmp, "DMA -- enabled dma channels\n");
 
 	for (i = 0; i < debugfs_dma_base->platform->max_channels; i++)
 		if (started_channels & (1 << i))
@@ -337,16 +333,22 @@
 		 * TODO: alloc a pile of descs instead of just one,
 		 * avoid many small allocations.
 		 */
-		desc = kmalloc(sizeof(struct coh901318_desc), GFP_NOWAIT);
+		desc = kzalloc(sizeof(struct coh901318_desc), GFP_NOWAIT);
 		if (desc == NULL)
 			goto out;
 		INIT_LIST_HEAD(&desc->node);
+		dma_async_tx_descriptor_init(&desc->desc, &cohc->chan);
 	} else {
 		/* Reuse an old desc. */
 		desc = list_first_entry(&cohc->free,
 					struct coh901318_desc,
 					node);
 		list_del(&desc->node);
+		/* Initialize it a bit so it's not insane */
+		desc->sg = NULL;
+		desc->sg_len = 0;
+		desc->desc.callback = NULL;
+		desc->desc.callback_param = NULL;
 	}
 
  out:
@@ -364,10 +366,6 @@
 coh901318_desc_submit(struct coh901318_chan *cohc, struct coh901318_desc *desc)
 {
 	list_add_tail(&desc->node, &cohc->active);
-
-	BUG_ON(cohc->pending_irqs != 0);
-
-	cohc->pending_irqs = desc->pending_irqs;
 }
 
 static struct coh901318_desc *
@@ -592,6 +590,10 @@
 	return cohd_que;
 }
 
+/*
+ * This tasklet is called from the interrupt handler to
+ * handle each descriptor (DMA job) that is sent to a channel.
+ */
 static void dma_tasklet(unsigned long data)
 {
 	struct coh901318_chan *cohc = (struct coh901318_chan *) data;
@@ -600,55 +602,58 @@
 	dma_async_tx_callback callback;
 	void *callback_param;
 
+	dev_vdbg(COHC_2_DEV(cohc), "[%s] chan_id %d"
+		 " nbr_active_done %ld\n", __func__,
+		 cohc->id, cohc->nbr_active_done);
+
 	spin_lock_irqsave(&cohc->lock, flags);
 
-	/* get first active entry from list */
+	/* get first active descriptor entry from list */
 	cohd_fin = coh901318_first_active_get(cohc);
 
-	BUG_ON(cohd_fin->pending_irqs == 0);
-
 	if (cohd_fin == NULL)
 		goto err;
 
-	cohd_fin->pending_irqs--;
-	cohc->completed = cohd_fin->desc.cookie;
-
-	if (cohc->nbr_active_done == 0)
-		return;
-
-	if (!cohd_fin->pending_irqs) {
-		/* release the lli allocation*/
-		coh901318_lli_free(&cohc->base->pool, &cohd_fin->data);
-	}
-
-	dev_vdbg(COHC_2_DEV(cohc), "[%s] chan_id %d pending_irqs %d"
-		 " nbr_active_done %ld\n", __func__,
-		 cohc->id, cohc->pending_irqs, cohc->nbr_active_done);
-
-	/* callback to client */
+	/* locate callback to client */
 	callback = cohd_fin->desc.callback;
 	callback_param = cohd_fin->desc.callback_param;
 
-	if (!cohd_fin->pending_irqs) {
-		coh901318_desc_remove(cohd_fin);
+	/* sign this job as completed on the channel */
+	cohc->completed = cohd_fin->desc.cookie;
 
-		/* return desc to free-list */
-		coh901318_desc_free(cohc, cohd_fin);
-	}
+	/* release the lli allocation and remove the descriptor */
+	coh901318_lli_free(&cohc->base->pool, &cohd_fin->data);
 
-	if (cohc->nbr_active_done)
-		cohc->nbr_active_done--;
+	/* return desc to free-list */
+	coh901318_desc_remove(cohd_fin);
+	coh901318_desc_free(cohc, cohd_fin);
 
+	spin_unlock_irqrestore(&cohc->lock, flags);
+
+	/* Call the callback when we're done */
+	if (callback)
+		callback(callback_param);
+
+	spin_lock_irqsave(&cohc->lock, flags);
+
+	/*
+	 * If another interrupt fired while the tasklet was scheduling,
+	 * we don't get called twice, so we have this number of active
+	 * counter that keep track of the number of IRQs expected to
+	 * be handled for this channel. If there happen to be more than
+	 * one IRQ to be ack:ed, we simply schedule this tasklet again.
+	 */
+	cohc->nbr_active_done--;
 	if (cohc->nbr_active_done) {
+		dev_dbg(COHC_2_DEV(cohc), "scheduling tasklet again, new IRQs "
+			"came in while we were scheduling this tasklet\n");
 		if (cohc_chan_conf(cohc)->priority_high)
 			tasklet_hi_schedule(&cohc->tasklet);
 		else
 			tasklet_schedule(&cohc->tasklet);
 	}
-	spin_unlock_irqrestore(&cohc->lock, flags);
 
-	if (callback)
-		callback(callback_param);
+	spin_unlock_irqrestore(&cohc->lock, flags);
 
 	return;
 
@@ -667,16 +672,17 @@
 	if (!cohc->allocated)
 		return;
 
-	BUG_ON(cohc->pending_irqs == 0);
+	spin_lock(&cohc->lock);
 
-	cohc->pending_irqs--;
 	cohc->nbr_active_done++;
 
-	if (cohc->pending_irqs == 0 && coh901318_queue_start(cohc) == NULL)
+	if (coh901318_queue_start(cohc) == NULL)
 		cohc->busy = 0;
 
 	BUG_ON(list_empty(&cohc->active));
 
+	spin_unlock(&cohc->lock);
+
 	if (cohc_chan_conf(cohc)->priority_high)
 		tasklet_hi_schedule(&cohc->tasklet);
 	else
@@ -870,6 +876,7 @@
 	struct coh901318_chan *cohc = to_coh901318_chan(chan);
 	int lli_len;
 	u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
+	int ret;
 
 	spin_lock_irqsave(&cohc->lock, flg);
 
@@ -890,22 +897,19 @@
 	if (data == NULL)
 		goto err;
 
-	cohd = coh901318_desc_get(cohc);
-	cohd->sg = NULL;
-	cohd->sg_len = 0;
-	cohd->data = data;
-
-	cohd->pending_irqs =
-		coh901318_lli_fill_memcpy(
-				&cohc->base->pool, data, src, size, dest,
-				cohc_chan_param(cohc)->ctrl_lli_chained,
-				ctrl_last);
-	cohd->flags = flags;
+	ret = coh901318_lli_fill_memcpy(
+		&cohc->base->pool, data, src, size, dest,
+		cohc_chan_param(cohc)->ctrl_lli_chained,
+		ctrl_last);
+	if (ret)
+		goto err;
 
 	COH_DBG(coh901318_list_print(cohc, data));
 
-	dma_async_tx_descriptor_init(&cohd->desc, chan);
-
+	/* Pick a descriptor to handle this transfer */
+	cohd = coh901318_desc_get(cohc);
+	cohd->data = data;
+	cohd->flags = flags;
 	cohd->desc.tx_submit = coh901318_tx_submit;
 
 	spin_unlock_irqrestore(&cohc->lock, flg);
@@ -924,6 +928,7 @@
 	struct coh901318_chan *cohc = to_coh901318_chan(chan);
 	struct coh901318_lli *data;
 	struct coh901318_desc *cohd;
+	const struct coh901318_params *params;
 	struct scatterlist *sg;
 	int len = 0;
 	int size;
@@ -931,7 +936,9 @@
 	u32 ctrl_chained = cohc_chan_param(cohc)->ctrl_lli_chained;
 	u32 ctrl = cohc_chan_param(cohc)->ctrl_lli;
 	u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
+	u32 config;
 	unsigned long flg;
+	int ret;
 
 	if (!sgl)
 		goto out;
@@ -947,15 +954,14 @@
 		/* Trigger interrupt after last lli */
 		ctrl_last |= COH901318_CX_CTRL_TC_IRQ_ENABLE;
 
-	cohd = coh901318_desc_get(cohc);
-	cohd->sg = NULL;
-	cohd->sg_len = 0;
-	cohd->dir = direction;
+	params = cohc_chan_param(cohc);
+	config = params->config;
 
 	if (direction == DMA_TO_DEVICE) {
 		u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE |
 			COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE;
 
+		config |= COH901318_CX_CFG_RM_MEMORY_TO_PRIMARY;
 		ctrl_chained |= tx_flags;
 		ctrl_last |= tx_flags;
 		ctrl |= tx_flags;
@@ -963,16 +969,14 @@
 		u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST |
 			COH901318_CX_CTRL_DST_ADDR_INC_ENABLE;
 
+		config |= COH901318_CX_CFG_RM_PRIMARY_TO_MEMORY;
 		ctrl_chained |= rx_flags;
 		ctrl_last |= rx_flags;
 		ctrl |= rx_flags;
 	} else
 		goto err_direction;
 
-	dma_async_tx_descriptor_init(&cohd->desc, chan);
-
-	cohd->desc.tx_submit = coh901318_tx_submit;
-
+	coh901318_set_conf(cohc, config);
 
 	/* The dma only supports transmitting packages up to
 	 * MAX_DMA_PACKET_SIZE. Calculate to total number of
@@ -994,32 +998,37 @@
 		len += factor;
 	}
 
+	pr_debug("Allocate %d lli:s for this transfer\n", len);
 	data = coh901318_lli_alloc(&cohc->base->pool, len);
 
 	if (data == NULL)
 		goto err_dma_alloc;
 
 	/* initiate allocated data list */
-	cohd->pending_irqs =
-		coh901318_lli_fill_sg(&cohc->base->pool, data, sgl, sg_len,
-				      cohc_dev_addr(cohc),
-				      ctrl_chained,
-				      ctrl,
-				      ctrl_last,
-				      direction, COH901318_CX_CTRL_TC_IRQ_ENABLE);
-	cohd->data = data;
-
-	cohd->flags = flags;
+	ret = coh901318_lli_fill_sg(&cohc->base->pool, data, sgl, sg_len,
+				    cohc_dev_addr(cohc),
+				    ctrl_chained,
+				    ctrl,
+				    ctrl_last,
+				    direction, COH901318_CX_CTRL_TC_IRQ_ENABLE);
+	if (ret)
+		goto err_lli_fill;
 
 	COH_DBG(coh901318_list_print(cohc, data));
 
+	/* Pick a descriptor to handle this transfer */
+	cohd = coh901318_desc_get(cohc);
+	cohd->dir = direction;
+	cohd->flags = flags;
+	cohd->desc.tx_submit = coh901318_tx_submit;
+	cohd->data = data;
+
 	spin_unlock_irqrestore(&cohc->lock, flg);
 
 	return &cohd->desc;
+ err_lli_fill:
  err_dma_alloc:
  err_direction:
-	coh901318_desc_remove(cohd);
-	coh901318_desc_free(cohc, cohd);
 	spin_unlock_irqrestore(&cohc->lock, flg);
  out:
 	return NULL;
@@ -1092,9 +1101,8 @@
 		/* release the lli allocation*/
 		coh901318_lli_free(&cohc->base->pool, &cohd->data);
 
-		coh901318_desc_remove(cohd);
-
 		/* return desc to free-list */
+		coh901318_desc_remove(cohd);
 		coh901318_desc_free(cohc, cohd);
 	}
 
@@ -1102,16 +1110,14 @@
 		/* release the lli allocation*/
 		coh901318_lli_free(&cohc->base->pool, &cohd->data);
 
-		coh901318_desc_remove(cohd);
-
 		/* return desc to free-list */
+		coh901318_desc_remove(cohd);
 		coh901318_desc_free(cohc, cohd);
 	}
 
 
 	cohc->nbr_active_done = 0;
 	cohc->busy = 0;
-	cohc->pending_irqs = 0;
 
 	spin_unlock_irqrestore(&cohc->lock, flags);
 }
@@ -1138,7 +1144,6 @@
 
 			spin_lock_init(&cohc->lock);
 
-			cohc->pending_irqs = 0;
 			cohc->nbr_active_done = 0;
 			cohc->busy = 0;
 			INIT_LIST_HEAD(&cohc->free);
@@ -1254,12 +1259,17 @@
 	base->dma_memcpy.device_issue_pending = coh901318_issue_pending;
 	base->dma_memcpy.device_terminate_all = coh901318_terminate_all;
 	base->dma_memcpy.dev = &pdev->dev;
+	/*
+	 * This controller can only access address at even 32bit boundaries,
+	 * i.e. 2^2
+	 */
+	base->dma_memcpy.copy_align = 2;
 	err = dma_async_device_register(&base->dma_memcpy);
 
 	if (err)
 		goto err_register_memcpy;
 
-	dev_dbg(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n",
+	dev_info(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n",
 		(u32) base->virtbase);
 
 	return err;
diff --git a/drivers/dma/coh901318_lli.c b/drivers/dma/coh901318_lli.c
index f5120f2..71d58c1 100644
--- a/drivers/dma/coh901318_lli.c
+++ b/drivers/dma/coh901318_lli.c
@@ -74,6 +74,8 @@
 
 	lli = head;
 	lli->phy_this = phy;
+	lli->link_addr = 0x00000000;
+	lli->virt_link_addr = 0x00000000U;
 
 	for (i = 1; i < len; i++) {
 		lli_prev = lli;
@@ -85,13 +87,13 @@
 
 		DEBUGFS_POOL_COUNTER_ADD(pool, 1);
 		lli->phy_this = phy;
+		lli->link_addr = 0x00000000;
+		lli->virt_link_addr = 0x00000000U;
 
 		lli_prev->link_addr = phy;
 		lli_prev->virt_link_addr = lli;
 	}
 
-	lli->link_addr = 0x00000000U;
-
 	spin_unlock(&pool->lock);
 
 	return head;
@@ -166,8 +168,7 @@
 	lli->src_addr = src;
 	lli->dst_addr = dst;
 
-	/* One irq per single transfer */
-	return 1;
+	return 0;
 }
 
 int
@@ -223,8 +224,7 @@
 	lli->src_addr = src;
 	lli->dst_addr = dst;
 
-	/* One irq per single transfer */
-	return 1;
+	return 0;
 }
 
 int
@@ -240,7 +240,6 @@
 	u32 ctrl_sg;
 	dma_addr_t src = 0;
 	dma_addr_t dst = 0;
-	int nbr_of_irq = 0;
 	u32 bytes_to_transfer;
 	u32 elem_size;
 
@@ -269,15 +268,12 @@
 			ctrl_sg = ctrl ? ctrl : ctrl_last;
 
 
-		if ((ctrl_sg & ctrl_irq_mask))
-			nbr_of_irq++;
-
 		if (dir == DMA_TO_DEVICE)
 			/* increment source address */
-			src = sg_dma_address(sg);
+			src = sg_phys(sg);
 		else
 			/* increment destination address */
-			dst =  sg_dma_address(sg);
+			dst =  sg_phys(sg);
 
 		bytes_to_transfer = sg_dma_len(sg);
 
@@ -310,8 +306,7 @@
 	}
 	spin_unlock(&pool->lock);
 
-	/* There can be many IRQs per sg transfer */
-	return nbr_of_irq;
+	return 0;
  err:
 	spin_unlock(&pool->lock);
 	return -EINVAL;
diff --git a/drivers/dma/coh901318_lli.h b/drivers/dma/coh901318_lli.h
index 7bf713b..7a5c809 100644
--- a/drivers/dma/coh901318_lli.h
+++ b/drivers/dma/coh901318_lli.h
@@ -30,7 +30,7 @@
  * @pool: pool handle
  * @dev: dma device
  * @lli_nbr: number of lli:s in the pool
- * @algin: adress alignemtn of lli:s
+ * @algin: address alignemtn of lli:s
  * returns 0 on success otherwise none zero
  */
 int coh901318_pool_create(struct coh901318_pool *pool,
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index e7a3230..87399ca 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -284,7 +284,7 @@
 /**
  * channel_table - percpu lookup table for memory-to-memory offload providers
  */
-static struct dma_chan_tbl_ent *channel_table[DMA_TX_TYPE_END];
+static struct dma_chan_tbl_ent __percpu *channel_table[DMA_TX_TYPE_END];
 
 static int __init dma_channel_table_init(void)
 {
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 948d563..6fa55fe 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -237,7 +237,7 @@
 	dma_cookie_t		cookie;
 	enum dma_status		status;
 	enum dma_ctrl_flags 	flags;
-	u8			pq_coefs[pq_sources];
+	u8			pq_coefs[pq_sources + 1];
 	int			ret;
 	int			src_cnt;
 	int			dst_cnt;
@@ -257,7 +257,7 @@
 	} else if (thread->type == DMA_PQ) {
 		src_cnt = pq_sources | 1; /* force odd to ensure dst = src */
 		dst_cnt = 2;
-		for (i = 0; i < pq_sources; i++)
+		for (i = 0; i < src_cnt; i++)
 			pq_coefs[i] = 1;
 	} else
 		goto err_srcs;
@@ -347,7 +347,7 @@
 		else if (thread->type == DMA_XOR)
 			tx = dev->device_prep_dma_xor(chan,
 						      dma_dsts[0] + dst_off,
-						      dma_srcs, xor_sources,
+						      dma_srcs, src_cnt,
 						      len, flags);
 		else if (thread->type == DMA_PQ) {
 			dma_addr_t dma_pq[dst_cnt];
@@ -355,7 +355,7 @@
 			for (i = 0; i < dst_cnt; i++)
 				dma_pq[i] = dma_dsts[i] + dst_off;
 			tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs,
-						     pq_sources, pq_coefs,
+						     src_cnt, pq_coefs,
 						     len, flags);
 		}
 
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 296f9e7..bbb4be5 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -37,19 +37,19 @@
 #include <asm/fsldma.h>
 #include "fsldma.h"
 
-static void dma_init(struct fsl_dma_chan *fsl_chan)
+static void dma_init(struct fsldma_chan *chan)
 {
 	/* Reset the channel */
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, 0, 32);
+	DMA_OUT(chan, &chan->regs->mr, 0, 32);
 
-	switch (fsl_chan->feature & FSL_DMA_IP_MASK) {
+	switch (chan->feature & FSL_DMA_IP_MASK) {
 	case FSL_DMA_IP_85XX:
 		/* Set the channel to below modes:
 		 * EIE - Error interrupt enable
 		 * EOSIE - End of segments interrupt enable (basic mode)
 		 * EOLNIE - End of links interrupt enable
 		 */
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EIE
+		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EIE
 				| FSL_DMA_MR_EOLNIE | FSL_DMA_MR_EOSIE, 32);
 		break;
 	case FSL_DMA_IP_83XX:
@@ -57,170 +57,146 @@
 		 * EOTIE - End-of-transfer interrupt enable
 		 * PRC_RM - PCI read multiple
 		 */
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EOTIE
+		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE
 				| FSL_DMA_MR_PRC_RM, 32);
 		break;
 	}
-
 }
 
-static void set_sr(struct fsl_dma_chan *fsl_chan, u32 val)
+static void set_sr(struct fsldma_chan *chan, u32 val)
 {
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->sr, val, 32);
+	DMA_OUT(chan, &chan->regs->sr, val, 32);
 }
 
-static u32 get_sr(struct fsl_dma_chan *fsl_chan)
+static u32 get_sr(struct fsldma_chan *chan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->sr, 32);
+	return DMA_IN(chan, &chan->regs->sr, 32);
 }
 
-static void set_desc_cnt(struct fsl_dma_chan *fsl_chan,
+static void set_desc_cnt(struct fsldma_chan *chan,
 				struct fsl_dma_ld_hw *hw, u32 count)
 {
-	hw->count = CPU_TO_DMA(fsl_chan, count, 32);
+	hw->count = CPU_TO_DMA(chan, count, 32);
 }
 
-static void set_desc_src(struct fsl_dma_chan *fsl_chan,
+static void set_desc_src(struct fsldma_chan *chan,
 				struct fsl_dma_ld_hw *hw, dma_addr_t src)
 {
 	u64 snoop_bits;
 
-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
 		? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
-	hw->src_addr = CPU_TO_DMA(fsl_chan, snoop_bits | src, 64);
+	hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64);
 }
 
-static void set_desc_dest(struct fsl_dma_chan *fsl_chan,
-				struct fsl_dma_ld_hw *hw, dma_addr_t dest)
+static void set_desc_dst(struct fsldma_chan *chan,
+				struct fsl_dma_ld_hw *hw, dma_addr_t dst)
 {
 	u64 snoop_bits;
 
-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
 		? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
-	hw->dst_addr = CPU_TO_DMA(fsl_chan, snoop_bits | dest, 64);
+	hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64);
 }
 
-static void set_desc_next(struct fsl_dma_chan *fsl_chan,
+static void set_desc_next(struct fsldma_chan *chan,
 				struct fsl_dma_ld_hw *hw, dma_addr_t next)
 {
 	u64 snoop_bits;
 
-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
 		? FSL_DMA_SNEN : 0;
-	hw->next_ln_addr = CPU_TO_DMA(fsl_chan, snoop_bits | next, 64);
+	hw->next_ln_addr = CPU_TO_DMA(chan, snoop_bits | next, 64);
 }
 
-static void set_cdar(struct fsl_dma_chan *fsl_chan, dma_addr_t addr)
+static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr)
 {
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->cdar, addr | FSL_DMA_SNEN, 64);
+	DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
 }
 
-static dma_addr_t get_cdar(struct fsl_dma_chan *fsl_chan)
+static dma_addr_t get_cdar(struct fsldma_chan *chan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->cdar, 64) & ~FSL_DMA_SNEN;
+	return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
 }
 
-static void set_ndar(struct fsl_dma_chan *fsl_chan, dma_addr_t addr)
+static dma_addr_t get_ndar(struct fsldma_chan *chan)
 {
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->ndar, addr, 64);
+	return DMA_IN(chan, &chan->regs->ndar, 64);
 }
 
-static dma_addr_t get_ndar(struct fsl_dma_chan *fsl_chan)
+static u32 get_bcr(struct fsldma_chan *chan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64);
+	return DMA_IN(chan, &chan->regs->bcr, 32);
 }
 
-static u32 get_bcr(struct fsl_dma_chan *fsl_chan)
+static int dma_is_idle(struct fsldma_chan *chan)
 {
-	return DMA_IN(fsl_chan, &fsl_chan->reg_base->bcr, 32);
-}
-
-static int dma_is_idle(struct fsl_dma_chan *fsl_chan)
-{
-	u32 sr = get_sr(fsl_chan);
+	u32 sr = get_sr(chan);
 	return (!(sr & FSL_DMA_SR_CB)) || (sr & FSL_DMA_SR_CH);
 }
 
-static void dma_start(struct fsl_dma_chan *fsl_chan)
+static void dma_start(struct fsldma_chan *chan)
 {
-	u32 mr_set = 0;
+	u32 mode;
 
-	if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->bcr, 0, 32);
-		mr_set |= FSL_DMA_MR_EMP_EN;
-	} else if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
-				& ~FSL_DMA_MR_EMP_EN, 32);
+	mode = DMA_IN(chan, &chan->regs->mr, 32);
+
+	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+		if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
+			DMA_OUT(chan, &chan->regs->bcr, 0, 32);
+			mode |= FSL_DMA_MR_EMP_EN;
+		} else {
+			mode &= ~FSL_DMA_MR_EMP_EN;
+		}
 	}
 
-	if (fsl_chan->feature & FSL_DMA_CHAN_START_EXT)
-		mr_set |= FSL_DMA_MR_EMS_EN;
+	if (chan->feature & FSL_DMA_CHAN_START_EXT)
+		mode |= FSL_DMA_MR_EMS_EN;
 	else
-		mr_set |= FSL_DMA_MR_CS;
+		mode |= FSL_DMA_MR_CS;
 
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
-			| mr_set, 32);
+	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 }
 
-static void dma_halt(struct fsl_dma_chan *fsl_chan)
+static void dma_halt(struct fsldma_chan *chan)
 {
+	u32 mode;
 	int i;
 
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CA,
-		32);
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~(FSL_DMA_MR_CS
-		| FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA), 32);
+	mode = DMA_IN(chan, &chan->regs->mr, 32);
+	mode |= FSL_DMA_MR_CA;
+	DMA_OUT(chan, &chan->regs->mr, mode, 32);
+
+	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA);
+	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 
 	for (i = 0; i < 100; i++) {
-		if (dma_is_idle(fsl_chan))
-			break;
+		if (dma_is_idle(chan))
+			return;
+
 		udelay(10);
 	}
-	if (i >= 100 && !dma_is_idle(fsl_chan))
-		dev_err(fsl_chan->dev, "DMA halt timeout!\n");
+
+	if (!dma_is_idle(chan))
+		dev_err(chan->dev, "DMA halt timeout!\n");
 }
 
-static void set_ld_eol(struct fsl_dma_chan *fsl_chan,
+static void set_ld_eol(struct fsldma_chan *chan,
 			struct fsl_desc_sw *desc)
 {
 	u64 snoop_bits;
 
-	snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
 		? FSL_DMA_SNEN : 0;
 
-	desc->hw.next_ln_addr = CPU_TO_DMA(fsl_chan,
-		DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
+	desc->hw.next_ln_addr = CPU_TO_DMA(chan,
+		DMA_TO_CPU(chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
 			| snoop_bits, 64);
 }
 
-static void append_ld_queue(struct fsl_dma_chan *fsl_chan,
-		struct fsl_desc_sw *new_desc)
-{
-	struct fsl_desc_sw *queue_tail = to_fsl_desc(fsl_chan->ld_queue.prev);
-
-	if (list_empty(&fsl_chan->ld_queue))
-		return;
-
-	/* Link to the new descriptor physical address and
-	 * Enable End-of-segment interrupt for
-	 * the last link descriptor.
-	 * (the previous node's next link descriptor)
-	 *
-	 * For FSL_DMA_IP_83xx, the snoop enable bit need be set.
-	 */
-	queue_tail->hw.next_ln_addr = CPU_TO_DMA(fsl_chan,
-			new_desc->async_tx.phys | FSL_DMA_EOSIE |
-			(((fsl_chan->feature & FSL_DMA_IP_MASK)
-				== FSL_DMA_IP_83XX) ? FSL_DMA_SNEN : 0), 64);
-}
-
 /**
  * fsl_chan_set_src_loop_size - Set source address hold transfer size
- * @fsl_chan : Freescale DMA channel
+ * @chan : Freescale DMA channel
  * @size     : Address loop size, 0 for disable loop
  *
  * The set source address hold transfer size. The source
@@ -229,29 +205,30 @@
  * read data from SA, SA + 1, SA + 2, SA + 3, then loop back to SA,
  * SA + 1 ... and so on.
  */
-static void fsl_chan_set_src_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+static void fsl_chan_set_src_loop_size(struct fsldma_chan *chan, int size)
 {
+	u32 mode;
+
+	mode = DMA_IN(chan, &chan->regs->mr, 32);
+
 	switch (size) {
 	case 0:
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) &
-			(~FSL_DMA_MR_SAHE), 32);
+		mode &= ~FSL_DMA_MR_SAHE;
 		break;
 	case 1:
 	case 2:
 	case 4:
 	case 8:
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) |
-			FSL_DMA_MR_SAHE | (__ilog2(size) << 14),
-			32);
+		mode |= FSL_DMA_MR_SAHE | (__ilog2(size) << 14);
 		break;
 	}
+
+	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 }
 
 /**
- * fsl_chan_set_dest_loop_size - Set destination address hold transfer size
- * @fsl_chan : Freescale DMA channel
+ * fsl_chan_set_dst_loop_size - Set destination address hold transfer size
+ * @chan : Freescale DMA channel
  * @size     : Address loop size, 0 for disable loop
  *
  * The set destination address hold transfer size. The destination
@@ -260,29 +237,30 @@
  * write data to TA, TA + 1, TA + 2, TA + 3, then loop back to TA,
  * TA + 1 ... and so on.
  */
-static void fsl_chan_set_dest_loop_size(struct fsl_dma_chan *fsl_chan, int size)
+static void fsl_chan_set_dst_loop_size(struct fsldma_chan *chan, int size)
 {
+	u32 mode;
+
+	mode = DMA_IN(chan, &chan->regs->mr, 32);
+
 	switch (size) {
 	case 0:
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) &
-			(~FSL_DMA_MR_DAHE), 32);
+		mode &= ~FSL_DMA_MR_DAHE;
 		break;
 	case 1:
 	case 2:
 	case 4:
 	case 8:
-		DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-			DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) |
-			FSL_DMA_MR_DAHE | (__ilog2(size) << 16),
-			32);
+		mode |= FSL_DMA_MR_DAHE | (__ilog2(size) << 16);
 		break;
 	}
+
+	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 }
 
 /**
  * fsl_chan_set_request_count - Set DMA Request Count for external control
- * @fsl_chan : Freescale DMA channel
+ * @chan : Freescale DMA channel
  * @size     : Number of bytes to transfer in a single request
  *
  * The Freescale DMA channel can be controlled by the external signal DREQ#.
@@ -292,35 +270,38 @@
  *
  * A size of 0 disables external pause control. The maximum size is 1024.
  */
-static void fsl_chan_set_request_count(struct fsl_dma_chan *fsl_chan, int size)
+static void fsl_chan_set_request_count(struct fsldma_chan *chan, int size)
 {
+	u32 mode;
+
 	BUG_ON(size > 1024);
-	DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
-		DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
-			| ((__ilog2(size) << 24) & 0x0f000000),
-		32);
+
+	mode = DMA_IN(chan, &chan->regs->mr, 32);
+	mode |= (__ilog2(size) << 24) & 0x0f000000;
+
+	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 }
 
 /**
  * fsl_chan_toggle_ext_pause - Toggle channel external pause status
- * @fsl_chan : Freescale DMA channel
+ * @chan : Freescale DMA channel
  * @enable   : 0 is disabled, 1 is enabled.
  *
  * The Freescale DMA channel can be controlled by the external signal DREQ#.
  * The DMA Request Count feature should be used in addition to this feature
  * to set the number of bytes to transfer before pausing the channel.
  */
-static void fsl_chan_toggle_ext_pause(struct fsl_dma_chan *fsl_chan, int enable)
+static void fsl_chan_toggle_ext_pause(struct fsldma_chan *chan, int enable)
 {
 	if (enable)
-		fsl_chan->feature |= FSL_DMA_CHAN_PAUSE_EXT;
+		chan->feature |= FSL_DMA_CHAN_PAUSE_EXT;
 	else
-		fsl_chan->feature &= ~FSL_DMA_CHAN_PAUSE_EXT;
+		chan->feature &= ~FSL_DMA_CHAN_PAUSE_EXT;
 }
 
 /**
  * fsl_chan_toggle_ext_start - Toggle channel external start status
- * @fsl_chan : Freescale DMA channel
+ * @chan : Freescale DMA channel
  * @enable   : 0 is disabled, 1 is enabled.
  *
  * If enable the external start, the channel can be started by an
@@ -328,141 +309,196 @@
  * transfer immediately. The DMA channel will wait for the
  * control pin asserted.
  */
-static void fsl_chan_toggle_ext_start(struct fsl_dma_chan *fsl_chan, int enable)
+static void fsl_chan_toggle_ext_start(struct fsldma_chan *chan, int enable)
 {
 	if (enable)
-		fsl_chan->feature |= FSL_DMA_CHAN_START_EXT;
+		chan->feature |= FSL_DMA_CHAN_START_EXT;
 	else
-		fsl_chan->feature &= ~FSL_DMA_CHAN_START_EXT;
+		chan->feature &= ~FSL_DMA_CHAN_START_EXT;
+}
+
+static void append_ld_queue(struct fsldma_chan *chan,
+			    struct fsl_desc_sw *desc)
+{
+	struct fsl_desc_sw *tail = to_fsl_desc(chan->ld_pending.prev);
+
+	if (list_empty(&chan->ld_pending))
+		goto out_splice;
+
+	/*
+	 * Add the hardware descriptor to the chain of hardware descriptors
+	 * that already exists in memory.
+	 *
+	 * This will un-set the EOL bit of the existing transaction, and the
+	 * last link in this transaction will become the EOL descriptor.
+	 */
+	set_desc_next(chan, &tail->hw, desc->async_tx.phys);
+
+	/*
+	 * Add the software descriptor and all children to the list
+	 * of pending transactions
+	 */
+out_splice:
+	list_splice_tail_init(&desc->tx_list, &chan->ld_pending);
 }
 
 static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 {
-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan);
+	struct fsldma_chan *chan = to_fsl_chan(tx->chan);
 	struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
 	struct fsl_desc_sw *child;
 	unsigned long flags;
 	dma_cookie_t cookie;
 
-	/* cookie increment and adding to ld_queue must be atomic */
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+	spin_lock_irqsave(&chan->desc_lock, flags);
 
-	cookie = fsl_chan->common.cookie;
+	/*
+	 * assign cookies to all of the software descriptors
+	 * that make up this transaction
+	 */
+	cookie = chan->common.cookie;
 	list_for_each_entry(child, &desc->tx_list, node) {
 		cookie++;
 		if (cookie < 0)
 			cookie = 1;
 
-		desc->async_tx.cookie = cookie;
+		child->async_tx.cookie = cookie;
 	}
 
-	fsl_chan->common.cookie = cookie;
-	append_ld_queue(fsl_chan, desc);
-	list_splice_init(&desc->tx_list, fsl_chan->ld_queue.prev);
+	chan->common.cookie = cookie;
 
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+	/* put this transaction onto the tail of the pending queue */
+	append_ld_queue(chan, desc);
+
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
 
 	return cookie;
 }
 
 /**
  * fsl_dma_alloc_descriptor - Allocate descriptor from channel's DMA pool.
- * @fsl_chan : Freescale DMA channel
+ * @chan : Freescale DMA channel
  *
  * Return - The descriptor allocated. NULL for failed.
  */
 static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
-					struct fsl_dma_chan *fsl_chan)
+					struct fsldma_chan *chan)
 {
+	struct fsl_desc_sw *desc;
 	dma_addr_t pdesc;
-	struct fsl_desc_sw *desc_sw;
 
-	desc_sw = dma_pool_alloc(fsl_chan->desc_pool, GFP_ATOMIC, &pdesc);
-	if (desc_sw) {
-		memset(desc_sw, 0, sizeof(struct fsl_desc_sw));
-		INIT_LIST_HEAD(&desc_sw->tx_list);
-		dma_async_tx_descriptor_init(&desc_sw->async_tx,
-						&fsl_chan->common);
-		desc_sw->async_tx.tx_submit = fsl_dma_tx_submit;
-		desc_sw->async_tx.phys = pdesc;
+	desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
+	if (!desc) {
+		dev_dbg(chan->dev, "out of memory for link desc\n");
+		return NULL;
 	}
 
-	return desc_sw;
+	memset(desc, 0, sizeof(*desc));
+	INIT_LIST_HEAD(&desc->tx_list);
+	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+	desc->async_tx.tx_submit = fsl_dma_tx_submit;
+	desc->async_tx.phys = pdesc;
+
+	return desc;
 }
 
 
 /**
  * fsl_dma_alloc_chan_resources - Allocate resources for DMA channel.
- * @fsl_chan : Freescale DMA channel
+ * @chan : Freescale DMA channel
  *
  * This function will create a dma pool for descriptor allocation.
  *
  * Return - The number of descriptors allocated.
  */
-static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
+static int fsl_dma_alloc_chan_resources(struct dma_chan *dchan)
 {
-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsldma_chan *chan = to_fsl_chan(dchan);
 
 	/* Has this channel already been allocated? */
-	if (fsl_chan->desc_pool)
+	if (chan->desc_pool)
 		return 1;
 
-	/* We need the descriptor to be aligned to 32bytes
+	/*
+	 * We need the descriptor to be aligned to 32bytes
 	 * for meeting FSL DMA specification requirement.
 	 */
-	fsl_chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
-			fsl_chan->dev, sizeof(struct fsl_desc_sw),
-			32, 0);
-	if (!fsl_chan->desc_pool) {
-		dev_err(fsl_chan->dev, "No memory for channel %d "
-			"descriptor dma pool.\n", fsl_chan->id);
-		return 0;
+	chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
+					  chan->dev,
+					  sizeof(struct fsl_desc_sw),
+					  __alignof__(struct fsl_desc_sw), 0);
+	if (!chan->desc_pool) {
+		dev_err(chan->dev, "unable to allocate channel %d "
+				   "descriptor pool\n", chan->id);
+		return -ENOMEM;
 	}
 
+	/* there is at least one descriptor free to be allocated */
 	return 1;
 }
 
 /**
- * fsl_dma_free_chan_resources - Free all resources of the channel.
- * @fsl_chan : Freescale DMA channel
+ * fsldma_free_desc_list - Free all descriptors in a queue
+ * @chan: Freescae DMA channel
+ * @list: the list to free
+ *
+ * LOCKING: must hold chan->desc_lock
  */
-static void fsl_dma_free_chan_resources(struct dma_chan *chan)
+static void fsldma_free_desc_list(struct fsldma_chan *chan,
+				  struct list_head *list)
 {
-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
 	struct fsl_desc_sw *desc, *_desc;
+
+	list_for_each_entry_safe(desc, _desc, list, node) {
+		list_del(&desc->node);
+		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+	}
+}
+
+static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
+					  struct list_head *list)
+{
+	struct fsl_desc_sw *desc, *_desc;
+
+	list_for_each_entry_safe_reverse(desc, _desc, list, node) {
+		list_del(&desc->node);
+		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+	}
+}
+
+/**
+ * fsl_dma_free_chan_resources - Free all resources of the channel.
+ * @chan : Freescale DMA channel
+ */
+static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
+{
+	struct fsldma_chan *chan = to_fsl_chan(dchan);
 	unsigned long flags;
 
-	dev_dbg(fsl_chan->dev, "Free all channel resources.\n");
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
-	list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) {
-#ifdef FSL_DMA_LD_DEBUG
-		dev_dbg(fsl_chan->dev,
-				"LD %p will be released.\n", desc);
-#endif
-		list_del(&desc->node);
-		/* free link descriptor */
-		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
-	}
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
-	dma_pool_destroy(fsl_chan->desc_pool);
+	dev_dbg(chan->dev, "Free all channel resources.\n");
+	spin_lock_irqsave(&chan->desc_lock, flags);
+	fsldma_free_desc_list(chan, &chan->ld_pending);
+	fsldma_free_desc_list(chan, &chan->ld_running);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
 
-	fsl_chan->desc_pool = NULL;
+	dma_pool_destroy(chan->desc_pool);
+	chan->desc_pool = NULL;
 }
 
 static struct dma_async_tx_descriptor *
-fsl_dma_prep_interrupt(struct dma_chan *chan, unsigned long flags)
+fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags)
 {
-	struct fsl_dma_chan *fsl_chan;
+	struct fsldma_chan *chan;
 	struct fsl_desc_sw *new;
 
-	if (!chan)
+	if (!dchan)
 		return NULL;
 
-	fsl_chan = to_fsl_chan(chan);
+	chan = to_fsl_chan(dchan);
 
-	new = fsl_dma_alloc_descriptor(fsl_chan);
+	new = fsl_dma_alloc_descriptor(chan);
 	if (!new) {
-		dev_err(fsl_chan->dev, "No free memory for link descriptor\n");
+		dev_err(chan->dev, "No free memory for link descriptor\n");
 		return NULL;
 	}
 
@@ -473,51 +509,50 @@
 	list_add_tail(&new->node, &new->tx_list);
 
 	/* Set End-of-link to the last link descriptor of new list*/
-	set_ld_eol(fsl_chan, new);
+	set_ld_eol(chan, new);
 
 	return &new->async_tx;
 }
 
 static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
-	struct dma_chan *chan, dma_addr_t dma_dest, dma_addr_t dma_src,
+	struct dma_chan *dchan, dma_addr_t dma_dst, dma_addr_t dma_src,
 	size_t len, unsigned long flags)
 {
-	struct fsl_dma_chan *fsl_chan;
+	struct fsldma_chan *chan;
 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new;
-	struct list_head *list;
 	size_t copy;
 
-	if (!chan)
+	if (!dchan)
 		return NULL;
 
 	if (!len)
 		return NULL;
 
-	fsl_chan = to_fsl_chan(chan);
+	chan = to_fsl_chan(dchan);
 
 	do {
 
 		/* Allocate the link descriptor from DMA pool */
-		new = fsl_dma_alloc_descriptor(fsl_chan);
+		new = fsl_dma_alloc_descriptor(chan);
 		if (!new) {
-			dev_err(fsl_chan->dev,
+			dev_err(chan->dev,
 					"No free memory for link descriptor\n");
 			goto fail;
 		}
 #ifdef FSL_DMA_LD_DEBUG
-		dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
+		dev_dbg(chan->dev, "new link desc alloc %p\n", new);
 #endif
 
 		copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT);
 
-		set_desc_cnt(fsl_chan, &new->hw, copy);
-		set_desc_src(fsl_chan, &new->hw, dma_src);
-		set_desc_dest(fsl_chan, &new->hw, dma_dest);
+		set_desc_cnt(chan, &new->hw, copy);
+		set_desc_src(chan, &new->hw, dma_src);
+		set_desc_dst(chan, &new->hw, dma_dst);
 
 		if (!first)
 			first = new;
 		else
-			set_desc_next(fsl_chan, &prev->hw, new->async_tx.phys);
+			set_desc_next(chan, &prev->hw, new->async_tx.phys);
 
 		new->async_tx.cookie = 0;
 		async_tx_ack(&new->async_tx);
@@ -525,7 +560,7 @@
 		prev = new;
 		len -= copy;
 		dma_src += copy;
-		dma_dest += copy;
+		dma_dst += copy;
 
 		/* Insert the link descriptor to the LD ring */
 		list_add_tail(&new->node, &first->tx_list);
@@ -535,7 +570,7 @@
 	new->async_tx.cookie = -EBUSY;
 
 	/* Set End-of-link to the last link descriptor of new list*/
-	set_ld_eol(fsl_chan, new);
+	set_ld_eol(chan, new);
 
 	return &first->async_tx;
 
@@ -543,12 +578,7 @@
 	if (!first)
 		return NULL;
 
-	list = &first->tx_list;
-	list_for_each_entry_safe_reverse(new, prev, list, node) {
-		list_del(&new->node);
-		dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);
-	}
-
+	fsldma_free_desc_list_reverse(chan, &first->tx_list);
 	return NULL;
 }
 
@@ -565,13 +595,12 @@
  * chan->private variable.
  */
 static struct dma_async_tx_descriptor *fsl_dma_prep_slave_sg(
-	struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
+	struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
 	enum dma_data_direction direction, unsigned long flags)
 {
-	struct fsl_dma_chan *fsl_chan;
+	struct fsldma_chan *chan;
 	struct fsl_desc_sw *first = NULL, *prev = NULL, *new = NULL;
 	struct fsl_dma_slave *slave;
-	struct list_head *tx_list;
 	size_t copy;
 
 	int i;
@@ -581,14 +610,14 @@
 	struct fsl_dma_hw_addr *hw;
 	dma_addr_t dma_dst, dma_src;
 
-	if (!chan)
+	if (!dchan)
 		return NULL;
 
-	if (!chan->private)
+	if (!dchan->private)
 		return NULL;
 
-	fsl_chan = to_fsl_chan(chan);
-	slave = chan->private;
+	chan = to_fsl_chan(dchan);
+	slave = dchan->private;
 
 	if (list_empty(&slave->addresses))
 		return NULL;
@@ -637,14 +666,14 @@
 			}
 
 			/* Allocate the link descriptor from DMA pool */
-			new = fsl_dma_alloc_descriptor(fsl_chan);
+			new = fsl_dma_alloc_descriptor(chan);
 			if (!new) {
-				dev_err(fsl_chan->dev, "No free memory for "
+				dev_err(chan->dev, "No free memory for "
 						       "link descriptor\n");
 				goto fail;
 			}
 #ifdef FSL_DMA_LD_DEBUG
-			dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new);
+			dev_dbg(chan->dev, "new link desc alloc %p\n", new);
 #endif
 
 			/*
@@ -671,9 +700,9 @@
 			}
 
 			/* Fill in the descriptor */
-			set_desc_cnt(fsl_chan, &new->hw, copy);
-			set_desc_src(fsl_chan, &new->hw, dma_src);
-			set_desc_dest(fsl_chan, &new->hw, dma_dst);
+			set_desc_cnt(chan, &new->hw, copy);
+			set_desc_src(chan, &new->hw, dma_src);
+			set_desc_dst(chan, &new->hw, dma_dst);
 
 			/*
 			 * If this is not the first descriptor, chain the
@@ -682,7 +711,7 @@
 			if (!first) {
 				first = new;
 			} else {
-				set_desc_next(fsl_chan, &prev->hw,
+				set_desc_next(chan, &prev->hw,
 					      new->async_tx.phys);
 			}
 
@@ -708,23 +737,23 @@
 	new->async_tx.cookie = -EBUSY;
 
 	/* Set End-of-link to the last link descriptor of new list */
-	set_ld_eol(fsl_chan, new);
+	set_ld_eol(chan, new);
 
 	/* Enable extra controller features */
-	if (fsl_chan->set_src_loop_size)
-		fsl_chan->set_src_loop_size(fsl_chan, slave->src_loop_size);
+	if (chan->set_src_loop_size)
+		chan->set_src_loop_size(chan, slave->src_loop_size);
 
-	if (fsl_chan->set_dest_loop_size)
-		fsl_chan->set_dest_loop_size(fsl_chan, slave->dst_loop_size);
+	if (chan->set_dst_loop_size)
+		chan->set_dst_loop_size(chan, slave->dst_loop_size);
 
-	if (fsl_chan->toggle_ext_start)
-		fsl_chan->toggle_ext_start(fsl_chan, slave->external_start);
+	if (chan->toggle_ext_start)
+		chan->toggle_ext_start(chan, slave->external_start);
 
-	if (fsl_chan->toggle_ext_pause)
-		fsl_chan->toggle_ext_pause(fsl_chan, slave->external_pause);
+	if (chan->toggle_ext_pause)
+		chan->toggle_ext_pause(chan, slave->external_pause);
 
-	if (fsl_chan->set_request_count)
-		fsl_chan->set_request_count(fsl_chan, slave->request_count);
+	if (chan->set_request_count)
+		chan->set_request_count(chan, slave->request_count);
 
 	return &first->async_tx;
 
@@ -741,215 +770,216 @@
 	 *
 	 * We're re-using variables for the loop, oh well
 	 */
-	tx_list = &first->tx_list;
-	list_for_each_entry_safe_reverse(new, prev, tx_list, node) {
-		list_del_init(&new->node);
-		dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys);
-	}
-
+	fsldma_free_desc_list_reverse(chan, &first->tx_list);
 	return NULL;
 }
 
-static void fsl_dma_device_terminate_all(struct dma_chan *chan)
+static void fsl_dma_device_terminate_all(struct dma_chan *dchan)
 {
-	struct fsl_dma_chan *fsl_chan;
-	struct fsl_desc_sw *desc, *tmp;
+	struct fsldma_chan *chan;
 	unsigned long flags;
 
-	if (!chan)
+	if (!dchan)
 		return;
 
-	fsl_chan = to_fsl_chan(chan);
+	chan = to_fsl_chan(dchan);
 
 	/* Halt the DMA engine */
-	dma_halt(fsl_chan);
+	dma_halt(chan);
 
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+	spin_lock_irqsave(&chan->desc_lock, flags);
 
 	/* Remove and free all of the descriptors in the LD queue */
-	list_for_each_entry_safe(desc, tmp, &fsl_chan->ld_queue, node) {
-		list_del(&desc->node);
-		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
-	}
+	fsldma_free_desc_list(chan, &chan->ld_pending);
+	fsldma_free_desc_list(chan, &chan->ld_running);
 
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
 }
 
 /**
  * fsl_dma_update_completed_cookie - Update the completed cookie.
- * @fsl_chan : Freescale DMA channel
+ * @chan : Freescale DMA channel
+ *
+ * CONTEXT: hardirq
  */
-static void fsl_dma_update_completed_cookie(struct fsl_dma_chan *fsl_chan)
+static void fsl_dma_update_completed_cookie(struct fsldma_chan *chan)
 {
-	struct fsl_desc_sw *cur_desc, *desc;
-	dma_addr_t ld_phy;
+	struct fsl_desc_sw *desc;
+	unsigned long flags;
+	dma_cookie_t cookie;
 
-	ld_phy = get_cdar(fsl_chan) & FSL_DMA_NLDA_MASK;
+	spin_lock_irqsave(&chan->desc_lock, flags);
 
-	if (ld_phy) {
-		cur_desc = NULL;
-		list_for_each_entry(desc, &fsl_chan->ld_queue, node)
-			if (desc->async_tx.phys == ld_phy) {
-				cur_desc = desc;
-				break;
-			}
-
-		if (cur_desc && cur_desc->async_tx.cookie) {
-			if (dma_is_idle(fsl_chan))
-				fsl_chan->completed_cookie =
-					cur_desc->async_tx.cookie;
-			else
-				fsl_chan->completed_cookie =
-					cur_desc->async_tx.cookie - 1;
-		}
+	if (list_empty(&chan->ld_running)) {
+		dev_dbg(chan->dev, "no running descriptors\n");
+		goto out_unlock;
 	}
+
+	/* Get the last descriptor, update the cookie to that */
+	desc = to_fsl_desc(chan->ld_running.prev);
+	if (dma_is_idle(chan))
+		cookie = desc->async_tx.cookie;
+	else {
+		cookie = desc->async_tx.cookie - 1;
+		if (unlikely(cookie < DMA_MIN_COOKIE))
+			cookie = DMA_MAX_COOKIE;
+	}
+
+	chan->completed_cookie = cookie;
+
+out_unlock:
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
+}
+
+/**
+ * fsldma_desc_status - Check the status of a descriptor
+ * @chan: Freescale DMA channel
+ * @desc: DMA SW descriptor
+ *
+ * This function will return the status of the given descriptor
+ */
+static enum dma_status fsldma_desc_status(struct fsldma_chan *chan,
+					  struct fsl_desc_sw *desc)
+{
+	return dma_async_is_complete(desc->async_tx.cookie,
+				     chan->completed_cookie,
+				     chan->common.cookie);
 }
 
 /**
  * fsl_chan_ld_cleanup - Clean up link descriptors
- * @fsl_chan : Freescale DMA channel
+ * @chan : Freescale DMA channel
  *
  * This function clean up the ld_queue of DMA channel.
- * If 'in_intr' is set, the function will move the link descriptor to
- * the recycle list. Otherwise, free it directly.
  */
-static void fsl_chan_ld_cleanup(struct fsl_dma_chan *fsl_chan)
+static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
 {
 	struct fsl_desc_sw *desc, *_desc;
 	unsigned long flags;
 
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+	spin_lock_irqsave(&chan->desc_lock, flags);
 
-	dev_dbg(fsl_chan->dev, "chan completed_cookie = %d\n",
-			fsl_chan->completed_cookie);
-	list_for_each_entry_safe(desc, _desc, &fsl_chan->ld_queue, node) {
+	dev_dbg(chan->dev, "chan completed_cookie = %d\n", chan->completed_cookie);
+	list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
 		dma_async_tx_callback callback;
 		void *callback_param;
 
-		if (dma_async_is_complete(desc->async_tx.cookie,
-			    fsl_chan->completed_cookie, fsl_chan->common.cookie)
-				== DMA_IN_PROGRESS)
+		if (fsldma_desc_status(chan, desc) == DMA_IN_PROGRESS)
 			break;
 
-		callback = desc->async_tx.callback;
-		callback_param = desc->async_tx.callback_param;
-
-		/* Remove from ld_queue list */
+		/* Remove from the list of running transactions */
 		list_del(&desc->node);
 
-		dev_dbg(fsl_chan->dev, "link descriptor %p will be recycle.\n",
-				desc);
-		dma_pool_free(fsl_chan->desc_pool, desc, desc->async_tx.phys);
-
 		/* Run the link descriptor callback function */
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
 		if (callback) {
-			spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
-			dev_dbg(fsl_chan->dev, "link descriptor %p callback\n",
-					desc);
+			spin_unlock_irqrestore(&chan->desc_lock, flags);
+			dev_dbg(chan->dev, "LD %p callback\n", desc);
 			callback(callback_param);
-			spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+			spin_lock_irqsave(&chan->desc_lock, flags);
 		}
+
+		/* Run any dependencies, then free the descriptor */
+		dma_run_dependencies(&desc->async_tx);
+		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
 	}
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
 }
 
 /**
- * fsl_chan_xfer_ld_queue - Transfer link descriptors in channel ld_queue.
- * @fsl_chan : Freescale DMA channel
+ * fsl_chan_xfer_ld_queue - transfer any pending transactions
+ * @chan : Freescale DMA channel
+ *
+ * This will make sure that any pending transactions will be run.
+ * If the DMA controller is idle, it will be started. Otherwise,
+ * the DMA controller's interrupt handler will start any pending
+ * transactions when it becomes idle.
  */
-static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan)
+static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
 {
-	struct list_head *ld_node;
-	dma_addr_t next_dest_addr;
+	struct fsl_desc_sw *desc;
 	unsigned long flags;
 
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
+	spin_lock_irqsave(&chan->desc_lock, flags);
 
-	if (!dma_is_idle(fsl_chan))
-		goto out_unlock;
-
-	dma_halt(fsl_chan);
-
-	/* If there are some link descriptors
-	 * not transfered in queue. We need to start it.
+	/*
+	 * If the list of pending descriptors is empty, then we
+	 * don't need to do any work at all
 	 */
-
-	/* Find the first un-transfer desciptor */
-	for (ld_node = fsl_chan->ld_queue.next;
-		(ld_node != &fsl_chan->ld_queue)
-			&& (dma_async_is_complete(
-				to_fsl_desc(ld_node)->async_tx.cookie,
-				fsl_chan->completed_cookie,
-				fsl_chan->common.cookie) == DMA_SUCCESS);
-		ld_node = ld_node->next);
-
-	if (ld_node != &fsl_chan->ld_queue) {
-		/* Get the ld start address from ld_queue */
-		next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys;
-		dev_dbg(fsl_chan->dev, "xfer LDs staring from 0x%llx\n",
-				(unsigned long long)next_dest_addr);
-		set_cdar(fsl_chan, next_dest_addr);
-		dma_start(fsl_chan);
-	} else {
-		set_cdar(fsl_chan, 0);
-		set_ndar(fsl_chan, 0);
+	if (list_empty(&chan->ld_pending)) {
+		dev_dbg(chan->dev, "no pending LDs\n");
+		goto out_unlock;
 	}
 
+	/*
+	 * The DMA controller is not idle, which means the interrupt
+	 * handler will start any queued transactions when it runs
+	 * at the end of the current transaction
+	 */
+	if (!dma_is_idle(chan)) {
+		dev_dbg(chan->dev, "DMA controller still busy\n");
+		goto out_unlock;
+	}
+
+	/*
+	 * TODO:
+	 * make sure the dma_halt() function really un-wedges the
+	 * controller as much as possible
+	 */
+	dma_halt(chan);
+
+	/*
+	 * If there are some link descriptors which have not been
+	 * transferred, we need to start the controller
+	 */
+
+	/*
+	 * Move all elements from the queue of pending transactions
+	 * onto the list of running transactions
+	 */
+	desc = list_first_entry(&chan->ld_pending, struct fsl_desc_sw, node);
+	list_splice_tail_init(&chan->ld_pending, &chan->ld_running);
+
+	/*
+	 * Program the descriptor's address into the DMA controller,
+	 * then start the DMA transaction
+	 */
+	set_cdar(chan, desc->async_tx.phys);
+	dma_start(chan);
+
 out_unlock:
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
 }
 
 /**
  * fsl_dma_memcpy_issue_pending - Issue the DMA start command
- * @fsl_chan : Freescale DMA channel
+ * @chan : Freescale DMA channel
  */
-static void fsl_dma_memcpy_issue_pending(struct dma_chan *chan)
+static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
 {
-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
-
-#ifdef FSL_DMA_LD_DEBUG
-	struct fsl_desc_sw *ld;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fsl_chan->desc_lock, flags);
-	if (list_empty(&fsl_chan->ld_queue)) {
-		spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
-		return;
-	}
-
-	dev_dbg(fsl_chan->dev, "--memcpy issue--\n");
-	list_for_each_entry(ld, &fsl_chan->ld_queue, node) {
-		int i;
-		dev_dbg(fsl_chan->dev, "Ch %d, LD %08x\n",
-				fsl_chan->id, ld->async_tx.phys);
-		for (i = 0; i < 8; i++)
-			dev_dbg(fsl_chan->dev, "LD offset %d: %08x\n",
-					i, *(((u32 *)&ld->hw) + i));
-	}
-	dev_dbg(fsl_chan->dev, "----------------\n");
-	spin_unlock_irqrestore(&fsl_chan->desc_lock, flags);
-#endif
-
-	fsl_chan_xfer_ld_queue(fsl_chan);
+	struct fsldma_chan *chan = to_fsl_chan(dchan);
+	fsl_chan_xfer_ld_queue(chan);
 }
 
 /**
  * fsl_dma_is_complete - Determine the DMA status
- * @fsl_chan : Freescale DMA channel
+ * @chan : Freescale DMA channel
  */
-static enum dma_status fsl_dma_is_complete(struct dma_chan *chan,
+static enum dma_status fsl_dma_is_complete(struct dma_chan *dchan,
 					dma_cookie_t cookie,
 					dma_cookie_t *done,
 					dma_cookie_t *used)
 {
-	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
+	struct fsldma_chan *chan = to_fsl_chan(dchan);
 	dma_cookie_t last_used;
 	dma_cookie_t last_complete;
 
-	fsl_chan_ld_cleanup(fsl_chan);
+	fsl_chan_ld_cleanup(chan);
 
-	last_used = chan->cookie;
-	last_complete = fsl_chan->completed_cookie;
+	last_used = dchan->cookie;
+	last_complete = chan->completed_cookie;
 
 	if (done)
 		*done = last_complete;
@@ -960,32 +990,37 @@
 	return dma_async_is_complete(cookie, last_complete, last_used);
 }
 
-static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data)
+/*----------------------------------------------------------------------------*/
+/* Interrupt Handling                                                         */
+/*----------------------------------------------------------------------------*/
+
+static irqreturn_t fsldma_chan_irq(int irq, void *data)
 {
-	struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
-	u32 stat;
+	struct fsldma_chan *chan = data;
 	int update_cookie = 0;
 	int xfer_ld_q = 0;
+	u32 stat;
 
-	stat = get_sr(fsl_chan);
-	dev_dbg(fsl_chan->dev, "event: channel %d, stat = 0x%x\n",
-						fsl_chan->id, stat);
-	set_sr(fsl_chan, stat);		/* Clear the event register */
+	/* save and clear the status register */
+	stat = get_sr(chan);
+	set_sr(chan, stat);
+	dev_dbg(chan->dev, "irq: channel %d, stat = 0x%x\n", chan->id, stat);
 
 	stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
 	if (!stat)
 		return IRQ_NONE;
 
 	if (stat & FSL_DMA_SR_TE)
-		dev_err(fsl_chan->dev, "Transfer Error!\n");
+		dev_err(chan->dev, "Transfer Error!\n");
 
-	/* Programming Error
+	/*
+	 * Programming Error
 	 * The DMA_INTERRUPT async_tx is a NULL transfer, which will
 	 * triger a PE interrupt.
 	 */
 	if (stat & FSL_DMA_SR_PE) {
-		dev_dbg(fsl_chan->dev, "event: Programming Error INT\n");
-		if (get_bcr(fsl_chan) == 0) {
+		dev_dbg(chan->dev, "irq: Programming Error INT\n");
+		if (get_bcr(chan) == 0) {
 			/* BCR register is 0, this is a DMA_INTERRUPT async_tx.
 			 * Now, update the completed cookie, and continue the
 			 * next uncompleted transfer.
@@ -996,208 +1031,296 @@
 		stat &= ~FSL_DMA_SR_PE;
 	}
 
-	/* If the link descriptor segment transfer finishes,
+	/*
+	 * If the link descriptor segment transfer finishes,
 	 * we will recycle the used descriptor.
 	 */
 	if (stat & FSL_DMA_SR_EOSI) {
-		dev_dbg(fsl_chan->dev, "event: End-of-segments INT\n");
-		dev_dbg(fsl_chan->dev, "event: clndar 0x%llx, nlndar 0x%llx\n",
-			(unsigned long long)get_cdar(fsl_chan),
-			(unsigned long long)get_ndar(fsl_chan));
+		dev_dbg(chan->dev, "irq: End-of-segments INT\n");
+		dev_dbg(chan->dev, "irq: clndar 0x%llx, nlndar 0x%llx\n",
+			(unsigned long long)get_cdar(chan),
+			(unsigned long long)get_ndar(chan));
 		stat &= ~FSL_DMA_SR_EOSI;
 		update_cookie = 1;
 	}
 
-	/* For MPC8349, EOCDI event need to update cookie
+	/*
+	 * For MPC8349, EOCDI event need to update cookie
 	 * and start the next transfer if it exist.
 	 */
 	if (stat & FSL_DMA_SR_EOCDI) {
-		dev_dbg(fsl_chan->dev, "event: End-of-Chain link INT\n");
+		dev_dbg(chan->dev, "irq: End-of-Chain link INT\n");
 		stat &= ~FSL_DMA_SR_EOCDI;
 		update_cookie = 1;
 		xfer_ld_q = 1;
 	}
 
-	/* If it current transfer is the end-of-transfer,
+	/*
+	 * If it current transfer is the end-of-transfer,
 	 * we should clear the Channel Start bit for
 	 * prepare next transfer.
 	 */
 	if (stat & FSL_DMA_SR_EOLNI) {
-		dev_dbg(fsl_chan->dev, "event: End-of-link INT\n");
+		dev_dbg(chan->dev, "irq: End-of-link INT\n");
 		stat &= ~FSL_DMA_SR_EOLNI;
 		xfer_ld_q = 1;
 	}
 
 	if (update_cookie)
-		fsl_dma_update_completed_cookie(fsl_chan);
+		fsl_dma_update_completed_cookie(chan);
 	if (xfer_ld_q)
-		fsl_chan_xfer_ld_queue(fsl_chan);
+		fsl_chan_xfer_ld_queue(chan);
 	if (stat)
-		dev_dbg(fsl_chan->dev, "event: unhandled sr 0x%02x\n",
-					stat);
+		dev_dbg(chan->dev, "irq: unhandled sr 0x%02x\n", stat);
 
-	dev_dbg(fsl_chan->dev, "event: Exit\n");
-	tasklet_schedule(&fsl_chan->tasklet);
+	dev_dbg(chan->dev, "irq: Exit\n");
+	tasklet_schedule(&chan->tasklet);
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t fsl_dma_do_interrupt(int irq, void *data)
-{
-	struct fsl_dma_device *fdev = (struct fsl_dma_device *)data;
-	u32 gsr;
-	int ch_nr;
-
-	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->reg_base)
-			: in_le32(fdev->reg_base);
-	ch_nr = (32 - ffs(gsr)) / 8;
-
-	return fdev->chan[ch_nr] ? fsl_dma_chan_do_interrupt(irq,
-			fdev->chan[ch_nr]) : IRQ_NONE;
-}
-
 static void dma_do_tasklet(unsigned long data)
 {
-	struct fsl_dma_chan *fsl_chan = (struct fsl_dma_chan *)data;
-	fsl_chan_ld_cleanup(fsl_chan);
+	struct fsldma_chan *chan = (struct fsldma_chan *)data;
+	fsl_chan_ld_cleanup(chan);
 }
 
-static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
-	struct device_node *node, u32 feature, const char *compatible)
+static irqreturn_t fsldma_ctrl_irq(int irq, void *data)
 {
-	struct fsl_dma_chan *new_fsl_chan;
-	int err;
+	struct fsldma_device *fdev = data;
+	struct fsldma_chan *chan;
+	unsigned int handled = 0;
+	u32 gsr, mask;
+	int i;
 
-	/* alloc channel */
-	new_fsl_chan = kzalloc(sizeof(struct fsl_dma_chan), GFP_KERNEL);
-	if (!new_fsl_chan) {
-		dev_err(fdev->dev, "No free memory for allocating "
-				"dma channels!\n");
-		return -ENOMEM;
+	gsr = (fdev->feature & FSL_DMA_BIG_ENDIAN) ? in_be32(fdev->regs)
+						   : in_le32(fdev->regs);
+	mask = 0xff000000;
+	dev_dbg(fdev->dev, "IRQ: gsr 0x%.8x\n", gsr);
+
+	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+		chan = fdev->chan[i];
+		if (!chan)
+			continue;
+
+		if (gsr & mask) {
+			dev_dbg(fdev->dev, "IRQ: chan %d\n", chan->id);
+			fsldma_chan_irq(irq, chan);
+			handled++;
+		}
+
+		gsr &= ~mask;
+		mask >>= 8;
 	}
 
-	/* get dma channel register base */
-	err = of_address_to_resource(node, 0, &new_fsl_chan->reg);
-	if (err) {
-		dev_err(fdev->dev, "Can't get %s property 'reg'\n",
-				node->full_name);
-		goto err_no_reg;
+	return IRQ_RETVAL(handled);
+}
+
+static void fsldma_free_irqs(struct fsldma_device *fdev)
+{
+	struct fsldma_chan *chan;
+	int i;
+
+	if (fdev->irq != NO_IRQ) {
+		dev_dbg(fdev->dev, "free per-controller IRQ\n");
+		free_irq(fdev->irq, fdev);
+		return;
 	}
 
-	new_fsl_chan->feature = feature;
-
-	if (!fdev->feature)
-		fdev->feature = new_fsl_chan->feature;
-
-	/* If the DMA device's feature is different than its channels',
-	 * report the bug.
-	 */
-	WARN_ON(fdev->feature != new_fsl_chan->feature);
-
-	new_fsl_chan->dev = fdev->dev;
-	new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start,
-			new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1);
-
-	new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7;
-	if (new_fsl_chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
-		dev_err(fdev->dev, "There is no %d channel!\n",
-				new_fsl_chan->id);
-		err = -EINVAL;
-		goto err_no_chan;
+	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+		chan = fdev->chan[i];
+		if (chan && chan->irq != NO_IRQ) {
+			dev_dbg(fdev->dev, "free channel %d IRQ\n", chan->id);
+			free_irq(chan->irq, chan);
+		}
 	}
-	fdev->chan[new_fsl_chan->id] = new_fsl_chan;
-	tasklet_init(&new_fsl_chan->tasklet, dma_do_tasklet,
-			(unsigned long)new_fsl_chan);
+}
 
-	/* Init the channel */
-	dma_init(new_fsl_chan);
+static int fsldma_request_irqs(struct fsldma_device *fdev)
+{
+	struct fsldma_chan *chan;
+	int ret;
+	int i;
 
-	/* Clear cdar registers */
-	set_cdar(new_fsl_chan, 0);
-
-	switch (new_fsl_chan->feature & FSL_DMA_IP_MASK) {
-	case FSL_DMA_IP_85XX:
-		new_fsl_chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
-	case FSL_DMA_IP_83XX:
-		new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
-		new_fsl_chan->set_src_loop_size = fsl_chan_set_src_loop_size;
-		new_fsl_chan->set_dest_loop_size = fsl_chan_set_dest_loop_size;
-		new_fsl_chan->set_request_count = fsl_chan_set_request_count;
+	/* if we have a per-controller IRQ, use that */
+	if (fdev->irq != NO_IRQ) {
+		dev_dbg(fdev->dev, "request per-controller IRQ\n");
+		ret = request_irq(fdev->irq, fsldma_ctrl_irq, IRQF_SHARED,
+				  "fsldma-controller", fdev);
+		return ret;
 	}
 
-	spin_lock_init(&new_fsl_chan->desc_lock);
-	INIT_LIST_HEAD(&new_fsl_chan->ld_queue);
+	/* no per-controller IRQ, use the per-channel IRQs */
+	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+		chan = fdev->chan[i];
+		if (!chan)
+			continue;
 
-	new_fsl_chan->common.device = &fdev->common;
+		if (chan->irq == NO_IRQ) {
+			dev_err(fdev->dev, "no interrupts property defined for "
+					   "DMA channel %d. Please fix your "
+					   "device tree\n", chan->id);
+			ret = -ENODEV;
+			goto out_unwind;
+		}
 
-	/* Add the channel to DMA device channel list */
-	list_add_tail(&new_fsl_chan->common.device_node,
-			&fdev->common.channels);
-	fdev->common.chancnt++;
-
-	new_fsl_chan->irq = irq_of_parse_and_map(node, 0);
-	if (new_fsl_chan->irq != NO_IRQ) {
-		err = request_irq(new_fsl_chan->irq,
-					&fsl_dma_chan_do_interrupt, IRQF_SHARED,
-					"fsldma-channel", new_fsl_chan);
-		if (err) {
-			dev_err(fdev->dev, "DMA channel %s request_irq error "
-				"with return %d\n", node->full_name, err);
-			goto err_no_irq;
+		dev_dbg(fdev->dev, "request channel %d IRQ\n", chan->id);
+		ret = request_irq(chan->irq, fsldma_chan_irq, IRQF_SHARED,
+				  "fsldma-chan", chan);
+		if (ret) {
+			dev_err(fdev->dev, "unable to request IRQ for DMA "
+					   "channel %d\n", chan->id);
+			goto out_unwind;
 		}
 	}
 
-	dev_info(fdev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
-		 compatible,
-		 new_fsl_chan->irq != NO_IRQ ? new_fsl_chan->irq : fdev->irq);
+	return 0;
+
+out_unwind:
+	for (/* none */; i >= 0; i--) {
+		chan = fdev->chan[i];
+		if (!chan)
+			continue;
+
+		if (chan->irq == NO_IRQ)
+			continue;
+
+		free_irq(chan->irq, chan);
+	}
+
+	return ret;
+}
+
+/*----------------------------------------------------------------------------*/
+/* OpenFirmware Subsystem                                                     */
+/*----------------------------------------------------------------------------*/
+
+static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
+	struct device_node *node, u32 feature, const char *compatible)
+{
+	struct fsldma_chan *chan;
+	struct resource res;
+	int err;
+
+	/* alloc channel */
+	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
+	if (!chan) {
+		dev_err(fdev->dev, "no free memory for DMA channels!\n");
+		err = -ENOMEM;
+		goto out_return;
+	}
+
+	/* ioremap registers for use */
+	chan->regs = of_iomap(node, 0);
+	if (!chan->regs) {
+		dev_err(fdev->dev, "unable to ioremap registers\n");
+		err = -ENOMEM;
+		goto out_free_chan;
+	}
+
+	err = of_address_to_resource(node, 0, &res);
+	if (err) {
+		dev_err(fdev->dev, "unable to find 'reg' property\n");
+		goto out_iounmap_regs;
+	}
+
+	chan->feature = feature;
+	if (!fdev->feature)
+		fdev->feature = chan->feature;
+
+	/*
+	 * If the DMA device's feature is different than the feature
+	 * of its channels, report the bug
+	 */
+	WARN_ON(fdev->feature != chan->feature);
+
+	chan->dev = fdev->dev;
+	chan->id = ((res.start - 0x100) & 0xfff) >> 7;
+	if (chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
+		dev_err(fdev->dev, "too many channels for device\n");
+		err = -EINVAL;
+		goto out_iounmap_regs;
+	}
+
+	fdev->chan[chan->id] = chan;
+	tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan);
+
+	/* Initialize the channel */
+	dma_init(chan);
+
+	/* Clear cdar registers */
+	set_cdar(chan, 0);
+
+	switch (chan->feature & FSL_DMA_IP_MASK) {
+	case FSL_DMA_IP_85XX:
+		chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
+	case FSL_DMA_IP_83XX:
+		chan->toggle_ext_start = fsl_chan_toggle_ext_start;
+		chan->set_src_loop_size = fsl_chan_set_src_loop_size;
+		chan->set_dst_loop_size = fsl_chan_set_dst_loop_size;
+		chan->set_request_count = fsl_chan_set_request_count;
+	}
+
+	spin_lock_init(&chan->desc_lock);
+	INIT_LIST_HEAD(&chan->ld_pending);
+	INIT_LIST_HEAD(&chan->ld_running);
+
+	chan->common.device = &fdev->common;
+
+	/* find the IRQ line, if it exists in the device tree */
+	chan->irq = irq_of_parse_and_map(node, 0);
+
+	/* Add the channel to DMA device channel list */
+	list_add_tail(&chan->common.device_node, &fdev->common.channels);
+	fdev->common.chancnt++;
+
+	dev_info(fdev->dev, "#%d (%s), irq %d\n", chan->id, compatible,
+		 chan->irq != NO_IRQ ? chan->irq : fdev->irq);
 
 	return 0;
 
-err_no_irq:
-	list_del(&new_fsl_chan->common.device_node);
-err_no_chan:
-	iounmap(new_fsl_chan->reg_base);
-err_no_reg:
-	kfree(new_fsl_chan);
+out_iounmap_regs:
+	iounmap(chan->regs);
+out_free_chan:
+	kfree(chan);
+out_return:
 	return err;
 }
 
-static void fsl_dma_chan_remove(struct fsl_dma_chan *fchan)
+static void fsl_dma_chan_remove(struct fsldma_chan *chan)
 {
-	if (fchan->irq != NO_IRQ)
-		free_irq(fchan->irq, fchan);
-	list_del(&fchan->common.device_node);
-	iounmap(fchan->reg_base);
-	kfree(fchan);
+	irq_dispose_mapping(chan->irq);
+	list_del(&chan->common.device_node);
+	iounmap(chan->regs);
+	kfree(chan);
 }
 
-static int __devinit of_fsl_dma_probe(struct of_device *dev,
+static int __devinit fsldma_of_probe(struct of_device *op,
 			const struct of_device_id *match)
 {
-	int err;
-	struct fsl_dma_device *fdev;
+	struct fsldma_device *fdev;
 	struct device_node *child;
+	int err;
 
-	fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
+	fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
 	if (!fdev) {
-		dev_err(&dev->dev, "No enough memory for 'priv'\n");
-		return -ENOMEM;
+		dev_err(&op->dev, "No enough memory for 'priv'\n");
+		err = -ENOMEM;
+		goto out_return;
 	}
-	fdev->dev = &dev->dev;
+
+	fdev->dev = &op->dev;
 	INIT_LIST_HEAD(&fdev->common.channels);
 
-	/* get DMA controller register base */
-	err = of_address_to_resource(dev->node, 0, &fdev->reg);
-	if (err) {
-		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
-				dev->node->full_name);
-		goto err_no_reg;
+	/* ioremap the registers for use */
+	fdev->regs = of_iomap(op->node, 0);
+	if (!fdev->regs) {
+		dev_err(&op->dev, "unable to ioremap registers\n");
+		err = -ENOMEM;
+		goto out_free_fdev;
 	}
 
-	dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
-			"controller at 0x%llx...\n",
-			match->compatible, (unsigned long long)fdev->reg.start);
-	fdev->reg_base = ioremap(fdev->reg.start, fdev->reg.end
-						- fdev->reg.start + 1);
+	/* map the channel IRQ if it exists, but don't hookup the handler yet */
+	fdev->irq = irq_of_parse_and_map(op->node, 0);
 
 	dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
 	dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
@@ -1210,103 +1333,111 @@
 	fdev->common.device_issue_pending = fsl_dma_memcpy_issue_pending;
 	fdev->common.device_prep_slave_sg = fsl_dma_prep_slave_sg;
 	fdev->common.device_terminate_all = fsl_dma_device_terminate_all;
-	fdev->common.dev = &dev->dev;
+	fdev->common.dev = &op->dev;
 
-	fdev->irq = irq_of_parse_and_map(dev->node, 0);
-	if (fdev->irq != NO_IRQ) {
-		err = request_irq(fdev->irq, &fsl_dma_do_interrupt, IRQF_SHARED,
-					"fsldma-device", fdev);
-		if (err) {
-			dev_err(&dev->dev, "DMA device request_irq error "
-				"with return %d\n", err);
-			goto err;
-		}
-	}
+	dev_set_drvdata(&op->dev, fdev);
 
-	dev_set_drvdata(&(dev->dev), fdev);
-
-	/* We cannot use of_platform_bus_probe() because there is no
-	 * of_platform_bus_remove.  Instead, we manually instantiate every DMA
+	/*
+	 * We cannot use of_platform_bus_probe() because there is no
+	 * of_platform_bus_remove(). Instead, we manually instantiate every DMA
 	 * channel object.
 	 */
-	for_each_child_of_node(dev->node, child) {
-		if (of_device_is_compatible(child, "fsl,eloplus-dma-channel"))
+	for_each_child_of_node(op->node, child) {
+		if (of_device_is_compatible(child, "fsl,eloplus-dma-channel")) {
 			fsl_dma_chan_probe(fdev, child,
 				FSL_DMA_IP_85XX | FSL_DMA_BIG_ENDIAN,
 				"fsl,eloplus-dma-channel");
-		if (of_device_is_compatible(child, "fsl,elo-dma-channel"))
+		}
+
+		if (of_device_is_compatible(child, "fsl,elo-dma-channel")) {
 			fsl_dma_chan_probe(fdev, child,
 				FSL_DMA_IP_83XX | FSL_DMA_LITTLE_ENDIAN,
 				"fsl,elo-dma-channel");
+		}
+	}
+
+	/*
+	 * Hookup the IRQ handler(s)
+	 *
+	 * If we have a per-controller interrupt, we prefer that to the
+	 * per-channel interrupts to reduce the number of shared interrupt
+	 * handlers on the same IRQ line
+	 */
+	err = fsldma_request_irqs(fdev);
+	if (err) {
+		dev_err(fdev->dev, "unable to request IRQs\n");
+		goto out_free_fdev;
 	}
 
 	dma_async_device_register(&fdev->common);
 	return 0;
 
-err:
-	iounmap(fdev->reg_base);
-err_no_reg:
+out_free_fdev:
+	irq_dispose_mapping(fdev->irq);
 	kfree(fdev);
+out_return:
 	return err;
 }
 
-static int of_fsl_dma_remove(struct of_device *of_dev)
+static int fsldma_of_remove(struct of_device *op)
 {
-	struct fsl_dma_device *fdev;
+	struct fsldma_device *fdev;
 	unsigned int i;
 
-	fdev = dev_get_drvdata(&of_dev->dev);
-
+	fdev = dev_get_drvdata(&op->dev);
 	dma_async_device_unregister(&fdev->common);
 
-	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++)
+	fsldma_free_irqs(fdev);
+
+	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
 		if (fdev->chan[i])
 			fsl_dma_chan_remove(fdev->chan[i]);
+	}
 
-	if (fdev->irq != NO_IRQ)
-		free_irq(fdev->irq, fdev);
-
-	iounmap(fdev->reg_base);
-
+	iounmap(fdev->regs);
+	dev_set_drvdata(&op->dev, NULL);
 	kfree(fdev);
-	dev_set_drvdata(&of_dev->dev, NULL);
 
 	return 0;
 }
 
-static struct of_device_id of_fsl_dma_ids[] = {
+static const struct of_device_id fsldma_of_ids[] = {
 	{ .compatible = "fsl,eloplus-dma", },
 	{ .compatible = "fsl,elo-dma", },
 	{}
 };
 
-static struct of_platform_driver of_fsl_dma_driver = {
-	.name = "fsl-elo-dma",
-	.match_table = of_fsl_dma_ids,
-	.probe = of_fsl_dma_probe,
-	.remove = of_fsl_dma_remove,
+static struct of_platform_driver fsldma_of_driver = {
+	.name		= "fsl-elo-dma",
+	.match_table	= fsldma_of_ids,
+	.probe		= fsldma_of_probe,
+	.remove		= fsldma_of_remove,
 };
 
-static __init int of_fsl_dma_init(void)
+/*----------------------------------------------------------------------------*/
+/* Module Init / Exit                                                         */
+/*----------------------------------------------------------------------------*/
+
+static __init int fsldma_init(void)
 {
 	int ret;
 
 	pr_info("Freescale Elo / Elo Plus DMA driver\n");
 
-	ret = of_register_platform_driver(&of_fsl_dma_driver);
+	ret = of_register_platform_driver(&fsldma_of_driver);
 	if (ret)
 		pr_err("fsldma: failed to register platform driver\n");
 
 	return ret;
 }
 
-static void __exit of_fsl_dma_exit(void)
+static void __exit fsldma_exit(void)
 {
-	of_unregister_platform_driver(&of_fsl_dma_driver);
+	of_unregister_platform_driver(&fsldma_of_driver);
 }
 
-subsys_initcall(of_fsl_dma_init);
-module_exit(of_fsl_dma_exit);
+subsys_initcall(fsldma_init);
+module_exit(fsldma_exit);
 
 MODULE_DESCRIPTION("Freescale Elo / Elo Plus DMA driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index 0df14cb..cb4d6ff 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -92,11 +92,9 @@
 	struct list_head node;
 	struct list_head tx_list;
 	struct dma_async_tx_descriptor async_tx;
-	struct list_head *ld;
-	void *priv;
 } __attribute__((aligned(32)));
 
-struct fsl_dma_chan_regs {
+struct fsldma_chan_regs {
 	u32 mr;	/* 0x00 - Mode Register */
 	u32 sr;	/* 0x04 - Status Register */
 	u64 cdar;	/* 0x08 - Current descriptor address register */
@@ -106,20 +104,19 @@
 	u64 ndar;	/* 0x24 - Next Descriptor Address Register */
 };
 
-struct fsl_dma_chan;
+struct fsldma_chan;
 #define FSL_DMA_MAX_CHANS_PER_DEVICE 4
 
-struct fsl_dma_device {
-	void __iomem *reg_base;	/* DGSR register base */
-	struct resource reg;	/* Resource for register */
+struct fsldma_device {
+	void __iomem *regs;	/* DGSR register base */
 	struct device *dev;
 	struct dma_device common;
-	struct fsl_dma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
+	struct fsldma_chan *chan[FSL_DMA_MAX_CHANS_PER_DEVICE];
 	u32 feature;		/* The same as DMA channels */
 	int irq;		/* Channel IRQ */
 };
 
-/* Define macros for fsl_dma_chan->feature property */
+/* Define macros for fsldma_chan->feature property */
 #define FSL_DMA_LITTLE_ENDIAN	0x00000000
 #define FSL_DMA_BIG_ENDIAN	0x00000001
 
@@ -130,28 +127,28 @@
 #define FSL_DMA_CHAN_PAUSE_EXT	0x00001000
 #define FSL_DMA_CHAN_START_EXT	0x00002000
 
-struct fsl_dma_chan {
-	struct fsl_dma_chan_regs __iomem *reg_base;
+struct fsldma_chan {
+	struct fsldma_chan_regs __iomem *regs;
 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
 	spinlock_t desc_lock;		/* Descriptor operation lock */
-	struct list_head ld_queue;	/* Link descriptors queue */
+	struct list_head ld_pending;	/* Link descriptors queue */
+	struct list_head ld_running;	/* Link descriptors queue */
 	struct dma_chan common;		/* DMA common channel */
 	struct dma_pool *desc_pool;	/* Descriptors pool */
 	struct device *dev;		/* Channel device */
-	struct resource reg;		/* Resource for register */
 	int irq;			/* Channel IRQ */
 	int id;				/* Raw id of this channel */
 	struct tasklet_struct tasklet;
 	u32 feature;
 
-	void (*toggle_ext_pause)(struct fsl_dma_chan *fsl_chan, int enable);
-	void (*toggle_ext_start)(struct fsl_dma_chan *fsl_chan, int enable);
-	void (*set_src_loop_size)(struct fsl_dma_chan *fsl_chan, int size);
-	void (*set_dest_loop_size)(struct fsl_dma_chan *fsl_chan, int size);
-	void (*set_request_count)(struct fsl_dma_chan *fsl_chan, int size);
+	void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
+	void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
+	void (*set_src_loop_size)(struct fsldma_chan *fsl_chan, int size);
+	void (*set_dst_loop_size)(struct fsldma_chan *fsl_chan, int size);
+	void (*set_request_count)(struct fsldma_chan *fsl_chan, int size);
 };
 
-#define to_fsl_chan(chan) container_of(chan, struct fsl_dma_chan, common)
+#define to_fsl_chan(chan) container_of(chan, struct fsldma_chan, common)
 #define to_fsl_desc(lh) container_of(lh, struct fsl_desc_sw, node)
 #define tx_to_fsl_desc(tx) container_of(tx, struct fsl_desc_sw, async_tx)
 
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index dcc4ab7..0099340 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -71,7 +71,7 @@
 	}
 
 	attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
-	for_each_bit(bit, &attnstatus, BITS_PER_LONG) {
+	for_each_set_bit(bit, &attnstatus, BITS_PER_LONG) {
 		chan = ioat_chan_by_index(instance, bit);
 		tasklet_schedule(&chan->cleanup_task);
 	}
@@ -94,16 +94,12 @@
 	return IRQ_HANDLED;
 }
 
-static void ioat1_cleanup_tasklet(unsigned long data);
-
 /* common channel initialization */
-void ioat_init_channel(struct ioatdma_device *device,
-		       struct ioat_chan_common *chan, int idx,
-		       void (*timer_fn)(unsigned long),
-		       void (*tasklet)(unsigned long),
-		       unsigned long ioat)
+void ioat_init_channel(struct ioatdma_device *device, struct ioat_chan_common *chan, int idx)
 {
 	struct dma_device *dma = &device->common;
+	struct dma_chan *c = &chan->common;
+	unsigned long data = (unsigned long) c;
 
 	chan->device = device;
 	chan->reg_base = device->reg_base + (0x80 * (idx + 1));
@@ -112,14 +108,12 @@
 	list_add_tail(&chan->common.device_node, &dma->channels);
 	device->idx[idx] = chan;
 	init_timer(&chan->timer);
-	chan->timer.function = timer_fn;
-	chan->timer.data = ioat;
-	tasklet_init(&chan->cleanup_task, tasklet, ioat);
+	chan->timer.function = device->timer_fn;
+	chan->timer.data = data;
+	tasklet_init(&chan->cleanup_task, device->cleanup_fn, data);
 	tasklet_disable(&chan->cleanup_task);
 }
 
-static void ioat1_timer_event(unsigned long data);
-
 /**
  * ioat1_dma_enumerate_channels - find and initialize the device's channels
  * @device: the device to be enumerated
@@ -155,10 +149,7 @@
 		if (!ioat)
 			break;
 
-		ioat_init_channel(device, &ioat->base, i,
-				  ioat1_timer_event,
-				  ioat1_cleanup_tasklet,
-				  (unsigned long) ioat);
+		ioat_init_channel(device, &ioat->base, i);
 		ioat->xfercap = xfercap;
 		spin_lock_init(&ioat->desc_lock);
 		INIT_LIST_HEAD(&ioat->free_desc);
@@ -532,12 +523,12 @@
 	return &desc->txd;
 }
 
-static void ioat1_cleanup_tasklet(unsigned long data)
+static void ioat1_cleanup_event(unsigned long data)
 {
-	struct ioat_dma_chan *chan = (void *)data;
+	struct ioat_dma_chan *ioat = to_ioat_chan((void *) data);
 
-	ioat1_cleanup(chan);
-	writew(IOAT_CHANCTRL_RUN, chan->base.reg_base + IOAT_CHANCTRL_OFFSET);
+	ioat1_cleanup(ioat);
+	writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
 void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
@@ -687,7 +678,7 @@
 
 static void ioat1_timer_event(unsigned long data)
 {
-	struct ioat_dma_chan *ioat = (void *) data;
+	struct ioat_dma_chan *ioat = to_ioat_chan((void *) data);
 	struct ioat_chan_common *chan = &ioat->base;
 
 	dev_dbg(to_dev(chan), "%s: state: %lx\n", __func__, chan->state);
@@ -734,16 +725,17 @@
 	spin_unlock_bh(&chan->cleanup_lock);
 }
 
-static enum dma_status
-ioat1_dma_is_complete(struct dma_chan *c, dma_cookie_t cookie,
+enum dma_status
+ioat_is_dma_complete(struct dma_chan *c, dma_cookie_t cookie,
 		      dma_cookie_t *done, dma_cookie_t *used)
 {
-	struct ioat_dma_chan *ioat = to_ioat_chan(c);
+	struct ioat_chan_common *chan = to_chan_common(c);
+	struct ioatdma_device *device = chan->device;
 
 	if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS)
 		return DMA_SUCCESS;
 
-	ioat1_cleanup(ioat);
+	device->cleanup_fn((unsigned long) c);
 
 	return ioat_is_complete(c, cookie, done, used);
 }
@@ -1146,7 +1138,7 @@
 	return entry->show(&chan->common, page);
 }
 
-struct sysfs_ops ioat_sysfs_ops = {
+const struct sysfs_ops ioat_sysfs_ops = {
 	.show	= ioat_attr_show,
 };
 
@@ -1199,12 +1191,14 @@
 	device->intr_quirk = ioat1_intr_quirk;
 	device->enumerate_channels = ioat1_enumerate_channels;
 	device->self_test = ioat_dma_self_test;
+	device->timer_fn = ioat1_timer_event;
+	device->cleanup_fn = ioat1_cleanup_event;
 	dma = &device->common;
 	dma->device_prep_dma_memcpy = ioat1_dma_prep_memcpy;
 	dma->device_issue_pending = ioat1_dma_memcpy_issue_pending;
 	dma->device_alloc_chan_resources = ioat1_dma_alloc_chan_resources;
 	dma->device_free_chan_resources = ioat1_dma_free_chan_resources;
-	dma->device_is_tx_complete = ioat1_dma_is_complete;
+	dma->device_is_tx_complete = ioat_is_dma_complete;
 
 	err = ioat_probe(device);
 	if (err)
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index bbc3e78..86b97ac 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -61,7 +61,7 @@
  * @intr_quirk: interrupt setup quirk (for ioat_v1 devices)
  * @enumerate_channels: hw version specific channel enumeration
  * @reset_hw: hw version specific channel (re)initialization
- * @cleanup_tasklet: select between the v2 and v3 cleanup routines
+ * @cleanup_fn: select between the v2 and v3 cleanup routines
  * @timer_fn: select between the v2 and v3 timer watchdog routines
  * @self_test: hardware version specific self test for each supported op type
  *
@@ -80,7 +80,7 @@
 	void (*intr_quirk)(struct ioatdma_device *device);
 	int (*enumerate_channels)(struct ioatdma_device *device);
 	int (*reset_hw)(struct ioat_chan_common *chan);
-	void (*cleanup_tasklet)(unsigned long data);
+	void (*cleanup_fn)(unsigned long data);
 	void (*timer_fn)(unsigned long data);
 	int (*self_test)(struct ioatdma_device *device);
 };
@@ -337,17 +337,16 @@
 					      void __iomem *iobase);
 unsigned long ioat_get_current_completion(struct ioat_chan_common *chan);
 void ioat_init_channel(struct ioatdma_device *device,
-		       struct ioat_chan_common *chan, int idx,
-		       void (*timer_fn)(unsigned long),
-		       void (*tasklet)(unsigned long),
-		       unsigned long ioat);
+		       struct ioat_chan_common *chan, int idx);
+enum dma_status ioat_is_dma_complete(struct dma_chan *c, dma_cookie_t cookie,
+				     dma_cookie_t *done, dma_cookie_t *used);
 void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
 		    size_t len, struct ioat_dma_descriptor *hw);
 bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
 			   unsigned long *phys_complete);
 void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
 void ioat_kobject_del(struct ioatdma_device *device);
-extern struct sysfs_ops ioat_sysfs_ops;
+extern const struct sysfs_ops ioat_sysfs_ops;
 extern struct ioat_sysfs_entry ioat_version_attr;
 extern struct ioat_sysfs_entry ioat_cap_attr;
 #endif /* IOATDMA_H */
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index 5cc37af..1ed5d66 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -51,48 +51,40 @@
 
 void __ioat2_issue_pending(struct ioat2_dma_chan *ioat)
 {
-	void * __iomem reg_base = ioat->base.reg_base;
+	struct ioat_chan_common *chan = &ioat->base;
 
-	ioat->pending = 0;
 	ioat->dmacount += ioat2_ring_pending(ioat);
 	ioat->issued = ioat->head;
 	/* make descriptor updates globally visible before notifying channel */
 	wmb();
-	writew(ioat->dmacount, reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
-	dev_dbg(to_dev(&ioat->base),
+	writew(ioat->dmacount, chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
+	dev_dbg(to_dev(chan),
 		"%s: head: %#x tail: %#x issued: %#x count: %#x\n",
 		__func__, ioat->head, ioat->tail, ioat->issued, ioat->dmacount);
 }
 
-void ioat2_issue_pending(struct dma_chan *chan)
+void ioat2_issue_pending(struct dma_chan *c)
 {
-	struct ioat2_dma_chan *ioat = to_ioat2_chan(chan);
+	struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
 
-	spin_lock_bh(&ioat->ring_lock);
-	if (ioat->pending == 1)
+	if (ioat2_ring_pending(ioat)) {
+		spin_lock_bh(&ioat->ring_lock);
 		__ioat2_issue_pending(ioat);
-	spin_unlock_bh(&ioat->ring_lock);
+		spin_unlock_bh(&ioat->ring_lock);
+	}
 }
 
 /**
  * ioat2_update_pending - log pending descriptors
  * @ioat: ioat2+ channel
  *
- * set pending to '1' unless pending is already set to '2', pending == 2
- * indicates that submission is temporarily blocked due to an in-flight
- * reset.  If we are already above the ioat_pending_level threshold then
- * just issue pending.
- *
- * called with ring_lock held
+ * Check if the number of unsubmitted descriptors has exceeded the
+ * watermark.  Called with ring_lock held
  */
 static void ioat2_update_pending(struct ioat2_dma_chan *ioat)
 {
-	if (unlikely(ioat->pending == 2))
-		return;
-	else if (ioat2_ring_pending(ioat) > ioat_pending_level)
+	if (ioat2_ring_pending(ioat) > ioat_pending_level)
 		__ioat2_issue_pending(ioat);
-	else
-		ioat->pending = 1;
 }
 
 static void __ioat2_start_null_desc(struct ioat2_dma_chan *ioat)
@@ -166,7 +158,7 @@
 			seen_current = true;
 	}
 	ioat->tail += i;
-	BUG_ON(!seen_current); /* no active descs have written a completion? */
+	BUG_ON(active && !seen_current); /* no active descs have written a completion? */
 
 	chan->last_completion = phys_complete;
 	if (ioat->head == ioat->tail) {
@@ -207,9 +199,9 @@
 	spin_unlock_bh(&chan->cleanup_lock);
 }
 
-void ioat2_cleanup_tasklet(unsigned long data)
+void ioat2_cleanup_event(unsigned long data)
 {
-	struct ioat2_dma_chan *ioat = (void *) data;
+	struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
 
 	ioat2_cleanup(ioat);
 	writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
@@ -291,7 +283,7 @@
 
 void ioat2_timer_event(unsigned long data)
 {
-	struct ioat2_dma_chan *ioat = (void *) data;
+	struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
 	struct ioat_chan_common *chan = &ioat->base;
 
 	spin_lock_bh(&chan->cleanup_lock);
@@ -397,10 +389,7 @@
 		if (!ioat)
 			break;
 
-		ioat_init_channel(device, &ioat->base, i,
-				  device->timer_fn,
-				  device->cleanup_tasklet,
-				  (unsigned long) ioat);
+		ioat_init_channel(device, &ioat->base, i);
 		ioat->xfercap_log = xfercap_log;
 		spin_lock_init(&ioat->ring_lock);
 		if (device->reset_hw(&ioat->base)) {
@@ -546,7 +535,6 @@
 	ioat->head = 0;
 	ioat->issued = 0;
 	ioat->tail = 0;
-	ioat->pending = 0;
 	ioat->alloc_order = order;
 	spin_unlock_bh(&ioat->ring_lock);
 
@@ -701,7 +689,7 @@
 
 			mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);
 			spin_unlock_bh(&chan->cleanup_lock);
-			device->timer_fn((unsigned long) ioat);
+			device->timer_fn((unsigned long) &chan->common);
 		} else
 			spin_unlock_bh(&chan->cleanup_lock);
 		return -ENOMEM;
@@ -785,7 +773,7 @@
 
 	tasklet_disable(&chan->cleanup_task);
 	del_timer_sync(&chan->timer);
-	device->cleanup_tasklet((unsigned long) ioat);
+	device->cleanup_fn((unsigned long) c);
 	device->reset_hw(chan);
 
 	spin_lock_bh(&ioat->ring_lock);
@@ -815,25 +803,9 @@
 
 	chan->last_completion = 0;
 	chan->completion_dma = 0;
-	ioat->pending = 0;
 	ioat->dmacount = 0;
 }
 
-enum dma_status
-ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie,
-		     dma_cookie_t *done, dma_cookie_t *used)
-{
-	struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
-	struct ioatdma_device *device = ioat->base.device;
-
-	if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS)
-		return DMA_SUCCESS;
-
-	device->cleanup_tasklet((unsigned long) ioat);
-
-	return ioat_is_complete(c, cookie, done, used);
-}
-
 static ssize_t ring_size_show(struct dma_chan *c, char *page)
 {
 	struct ioat2_dma_chan *ioat = to_ioat2_chan(c);
@@ -874,7 +846,7 @@
 
 	device->enumerate_channels = ioat2_enumerate_channels;
 	device->reset_hw = ioat2_reset_hw;
-	device->cleanup_tasklet = ioat2_cleanup_tasklet;
+	device->cleanup_fn = ioat2_cleanup_event;
 	device->timer_fn = ioat2_timer_event;
 	device->self_test = ioat_dma_self_test;
 	dma = &device->common;
@@ -882,7 +854,7 @@
 	dma->device_issue_pending = ioat2_issue_pending;
 	dma->device_alloc_chan_resources = ioat2_alloc_chan_resources;
 	dma->device_free_chan_resources = ioat2_free_chan_resources;
-	dma->device_is_tx_complete = ioat2_is_complete;
+	dma->device_is_tx_complete = ioat_is_dma_complete;
 
 	err = ioat_probe(device);
 	if (err)
diff --git a/drivers/dma/ioat/dma_v2.h b/drivers/dma/ioat/dma_v2.h
index 3afad8d..ef2871f 100644
--- a/drivers/dma/ioat/dma_v2.h
+++ b/drivers/dma/ioat/dma_v2.h
@@ -47,7 +47,6 @@
  * @head: allocated index
  * @issued: hardware notification point
  * @tail: cleanup index
- * @pending: lock free indicator for issued != head
  * @dmacount: identical to 'head' except for occasionally resetting to zero
  * @alloc_order: log2 of the number of allocated descriptors
  * @ring: software ring buffer implementation of hardware ring
@@ -61,7 +60,6 @@
 	u16 tail;
 	u16 dmacount;
 	u16 alloc_order;
-	int pending;
 	struct ioat_ring_ent **ring;
 	spinlock_t ring_lock;
 };
@@ -178,12 +176,10 @@
 void ioat2_issue_pending(struct dma_chan *chan);
 int ioat2_alloc_chan_resources(struct dma_chan *c);
 void ioat2_free_chan_resources(struct dma_chan *c);
-enum dma_status ioat2_is_complete(struct dma_chan *c, dma_cookie_t cookie,
-				  dma_cookie_t *done, dma_cookie_t *used);
 void __ioat2_restart_chan(struct ioat2_dma_chan *ioat);
 bool reshape_ring(struct ioat2_dma_chan *ioat, int order);
 void __ioat2_issue_pending(struct ioat2_dma_chan *ioat);
-void ioat2_cleanup_tasklet(unsigned long data);
+void ioat2_cleanup_event(unsigned long data);
 void ioat2_timer_event(unsigned long data);
 int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo);
 int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo);
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index 9908c9e..26febc5 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -293,17 +293,25 @@
 		}
 	}
 	ioat->tail += i;
-	BUG_ON(!seen_current); /* no active descs have written a completion? */
+	BUG_ON(active && !seen_current); /* no active descs have written a completion? */
 	chan->last_completion = phys_complete;
-	if (ioat->head == ioat->tail) {
+
+	active = ioat2_ring_active(ioat);
+	if (active == 0) {
 		dev_dbg(to_dev(chan), "%s: cancel completion timeout\n",
 			__func__);
 		clear_bit(IOAT_COMPLETION_PENDING, &chan->state);
 		mod_timer(&chan->timer, jiffies + IDLE_TIMEOUT);
 	}
+	/* 5 microsecond delay per pending descriptor */
+	writew(min((5 * active), IOAT_INTRDELAY_MASK),
+	       chan->device->reg_base + IOAT_INTRDELAY_OFFSET);
 }
 
-static void ioat3_cleanup(struct ioat2_dma_chan *ioat)
+/* try to cleanup, but yield (via spin_trylock) to incoming submissions
+ * with the expectation that we will immediately poll again shortly
+ */
+static void ioat3_cleanup_poll(struct ioat2_dma_chan *ioat)
 {
 	struct ioat_chan_common *chan = &ioat->base;
 	unsigned long phys_complete;
@@ -329,29 +337,41 @@
 	spin_unlock_bh(&chan->cleanup_lock);
 }
 
-static void ioat3_cleanup_tasklet(unsigned long data)
+/* run cleanup now because we already delayed the interrupt via INTRDELAY */
+static void ioat3_cleanup_sync(struct ioat2_dma_chan *ioat)
 {
-	struct ioat2_dma_chan *ioat = (void *) data;
+	struct ioat_chan_common *chan = &ioat->base;
+	unsigned long phys_complete;
 
-	ioat3_cleanup(ioat);
-	writew(IOAT_CHANCTRL_RUN | IOAT3_CHANCTRL_COMPL_DCA_EN,
-	       ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
+	prefetch(chan->completion);
+
+	spin_lock_bh(&chan->cleanup_lock);
+	if (!ioat_cleanup_preamble(chan, &phys_complete)) {
+		spin_unlock_bh(&chan->cleanup_lock);
+		return;
+	}
+	spin_lock_bh(&ioat->ring_lock);
+
+	__cleanup(ioat, phys_complete);
+
+	spin_unlock_bh(&ioat->ring_lock);
+	spin_unlock_bh(&chan->cleanup_lock);
+}
+
+static void ioat3_cleanup_event(unsigned long data)
+{
+	struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
+
+	ioat3_cleanup_sync(ioat);
+	writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
 static void ioat3_restart_channel(struct ioat2_dma_chan *ioat)
 {
 	struct ioat_chan_common *chan = &ioat->base;
 	unsigned long phys_complete;
-	u32 status;
 
-	status = ioat_chansts(chan);
-	if (is_ioat_active(status) || is_ioat_idle(status))
-		ioat_suspend(chan);
-	while (is_ioat_active(status) || is_ioat_idle(status)) {
-		status = ioat_chansts(chan);
-		cpu_relax();
-	}
-
+	ioat2_quiesce(chan, 0);
 	if (ioat_cleanup_preamble(chan, &phys_complete))
 		__cleanup(ioat, phys_complete);
 
@@ -360,7 +380,7 @@
 
 static void ioat3_timer_event(unsigned long data)
 {
-	struct ioat2_dma_chan *ioat = (void *) data;
+	struct ioat2_dma_chan *ioat = to_ioat2_chan((void *) data);
 	struct ioat_chan_common *chan = &ioat->base;
 
 	spin_lock_bh(&chan->cleanup_lock);
@@ -426,7 +446,7 @@
 	if (ioat_is_complete(c, cookie, done, used) == DMA_SUCCESS)
 		return DMA_SUCCESS;
 
-	ioat3_cleanup(ioat);
+	ioat3_cleanup_poll(ioat);
 
 	return ioat_is_complete(c, cookie, done, used);
 }
@@ -1239,11 +1259,11 @@
 
 	if (is_raid_device) {
 		dma->device_is_tx_complete = ioat3_is_complete;
-		device->cleanup_tasklet = ioat3_cleanup_tasklet;
+		device->cleanup_fn = ioat3_cleanup_event;
 		device->timer_fn = ioat3_timer_event;
 	} else {
-		dma->device_is_tx_complete = ioat2_is_complete;
-		device->cleanup_tasklet = ioat2_cleanup_tasklet;
+		dma->device_is_tx_complete = ioat_is_dma_complete;
+		device->cleanup_fn = ioat2_cleanup_event;
 		device->timer_fn = ioat2_timer_event;
 	}
 
diff --git a/drivers/dma/ioat/registers.h b/drivers/dma/ioat/registers.h
index e8ae63b..1391798 100644
--- a/drivers/dma/ioat/registers.h
+++ b/drivers/dma/ioat/registers.h
@@ -60,7 +60,7 @@
 #define IOAT_PERPORTOFFSET_OFFSET		0x0A	/* 16-bit */
 
 #define IOAT_INTRDELAY_OFFSET			0x0C	/* 16-bit */
-#define IOAT_INTRDELAY_INT_DELAY_MASK		0x3FFF	/* Interrupt Delay Time */
+#define IOAT_INTRDELAY_MASK			0x3FFF	/* Interrupt Delay Time */
 #define IOAT_INTRDELAY_COALESE_SUPPORT		0x8000	/* Interrupt Coalescing Supported */
 
 #define IOAT_DEVICE_STATUS_OFFSET		0x0E	/* 16-bit */
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index e80bae1..2a44639 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -348,6 +348,7 @@
 		break;
 	case IPU_PIX_FMT_BGRA32:
 	case IPU_PIX_FMT_BGR32:
+	case IPU_PIX_FMT_ABGR32:
 		params->ip.bpp	= 0;
 		params->ip.pfs	= 4;
 		params->ip.npb	= 7;
@@ -376,20 +377,6 @@
 		params->ip.wid2	= 7;		/* Blue bit width - 1 */
 		params->ip.wid3	= 7;		/* Alpha bit width - 1 */
 		break;
-	case IPU_PIX_FMT_ABGR32:
-		params->ip.bpp	= 0;
-		params->ip.pfs	= 4;
-		params->ip.npb	= 7;
-		params->ip.sat	= 2;		/* SAT = 32-bit access */
-		params->ip.ofs0	= 8;		/* Red bit offset */
-		params->ip.ofs1	= 16;		/* Green bit offset */
-		params->ip.ofs2	= 24;		/* Blue bit offset */
-		params->ip.ofs3	= 0;		/* Alpha bit offset */
-		params->ip.wid0	= 7;		/* Red bit width - 1 */
-		params->ip.wid1	= 7;		/* Green bit width - 1 */
-		params->ip.wid2	= 7;		/* Blue bit width - 1 */
-		params->ip.wid3	= 7;		/* Alpha bit width - 1 */
-		break;
 	case IPU_PIX_FMT_UYVY:
 		params->ip.bpp	= 2;
 		params->ip.pfs	= 6;
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
new file mode 100644
index 0000000..3fdf1f4
--- /dev/null
+++ b/drivers/dma/mpc512x_dma.c
@@ -0,0 +1,800 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008.
+ * Copyright (C) Semihalf 2009
+ *
+ * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description
+ * (defines, structures and comments) was taken from MPC5121 DMA driver
+ * written by Hongjun Chen <hong-jun.chen@freescale.com>.
+ *
+ * Approved as OSADL project by a majority of OSADL members and funded
+ * by OSADL membership fees in 2009;  for details see www.osadl.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., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This is initial version of MPC5121 DMA driver. Only memory to memory
+ * transfers are supported (tested using dmatest module).
+ */
+
+#include <linux/module.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#include <linux/random.h>
+
+/* Number of DMA Transfer descriptors allocated per channel */
+#define MPC_DMA_DESCRIPTORS	64
+
+/* Macro definitions */
+#define MPC_DMA_CHANNELS	64
+#define MPC_DMA_TCD_OFFSET	0x1000
+
+/* Arbitration mode of group and channel */
+#define MPC_DMA_DMACR_EDCG	(1 << 31)
+#define MPC_DMA_DMACR_ERGA	(1 << 3)
+#define MPC_DMA_DMACR_ERCA	(1 << 2)
+
+/* Error codes */
+#define MPC_DMA_DMAES_VLD	(1 << 31)
+#define MPC_DMA_DMAES_GPE	(1 << 15)
+#define MPC_DMA_DMAES_CPE	(1 << 14)
+#define MPC_DMA_DMAES_ERRCHN(err) \
+				(((err) >> 8) & 0x3f)
+#define MPC_DMA_DMAES_SAE	(1 << 7)
+#define MPC_DMA_DMAES_SOE	(1 << 6)
+#define MPC_DMA_DMAES_DAE	(1 << 5)
+#define MPC_DMA_DMAES_DOE	(1 << 4)
+#define MPC_DMA_DMAES_NCE	(1 << 3)
+#define MPC_DMA_DMAES_SGE	(1 << 2)
+#define MPC_DMA_DMAES_SBE	(1 << 1)
+#define MPC_DMA_DMAES_DBE	(1 << 0)
+
+#define MPC_DMA_TSIZE_1		0x00
+#define MPC_DMA_TSIZE_2		0x01
+#define MPC_DMA_TSIZE_4		0x02
+#define MPC_DMA_TSIZE_16	0x04
+#define MPC_DMA_TSIZE_32	0x05
+
+/* MPC5121 DMA engine registers */
+struct __attribute__ ((__packed__)) mpc_dma_regs {
+	/* 0x00 */
+	u32 dmacr;		/* DMA control register */
+	u32 dmaes;		/* DMA error status */
+	/* 0x08 */
+	u32 dmaerqh;		/* DMA enable request high(channels 63~32) */
+	u32 dmaerql;		/* DMA enable request low(channels 31~0) */
+	u32 dmaeeih;		/* DMA enable error interrupt high(ch63~32) */
+	u32 dmaeeil;		/* DMA enable error interrupt low(ch31~0) */
+	/* 0x18 */
+	u8 dmaserq;		/* DMA set enable request */
+	u8 dmacerq;		/* DMA clear enable request */
+	u8 dmaseei;		/* DMA set enable error interrupt */
+	u8 dmaceei;		/* DMA clear enable error interrupt */
+	/* 0x1c */
+	u8 dmacint;		/* DMA clear interrupt request */
+	u8 dmacerr;		/* DMA clear error */
+	u8 dmassrt;		/* DMA set start bit */
+	u8 dmacdne;		/* DMA clear DONE status bit */
+	/* 0x20 */
+	u32 dmainth;		/* DMA interrupt request high(ch63~32) */
+	u32 dmaintl;		/* DMA interrupt request low(ch31~0) */
+	u32 dmaerrh;		/* DMA error high(ch63~32) */
+	u32 dmaerrl;		/* DMA error low(ch31~0) */
+	/* 0x30 */
+	u32 dmahrsh;		/* DMA hw request status high(ch63~32) */
+	u32 dmahrsl;		/* DMA hardware request status low(ch31~0) */
+	u32 dmaihsa;		/* DMA interrupt high select AXE(ch63~32) */
+	u32 dmailsa;		/* DMA interrupt low select AXE(ch31~0) */
+	/* 0x40 ~ 0xff */
+	u32 reserve0[48];	/* Reserved */
+	/* 0x100 */
+	u8 dchpri[MPC_DMA_CHANNELS];
+	/* DMA channels(0~63) priority */
+};
+
+struct __attribute__ ((__packed__)) mpc_dma_tcd {
+	/* 0x00 */
+	u32 saddr;		/* Source address */
+
+	u32 smod:5;		/* Source address modulo */
+	u32 ssize:3;		/* Source data transfer size */
+	u32 dmod:5;		/* Destination address modulo */
+	u32 dsize:3;		/* Destination data transfer size */
+	u32 soff:16;		/* Signed source address offset */
+
+	/* 0x08 */
+	u32 nbytes;		/* Inner "minor" byte count */
+	u32 slast;		/* Last source address adjustment */
+	u32 daddr;		/* Destination address */
+
+	/* 0x14 */
+	u32 citer_elink:1;	/* Enable channel-to-channel linking on
+				 * minor loop complete
+				 */
+	u32 citer_linkch:6;	/* Link channel for minor loop complete */
+	u32 citer:9;		/* Current "major" iteration count */
+	u32 doff:16;		/* Signed destination address offset */
+
+	/* 0x18 */
+	u32 dlast_sga;		/* Last Destination address adjustment/scatter
+				 * gather address
+				 */
+
+	/* 0x1c */
+	u32 biter_elink:1;	/* Enable channel-to-channel linking on major
+				 * loop complete
+				 */
+	u32 biter_linkch:6;
+	u32 biter:9;		/* Beginning "major" iteration count */
+	u32 bwc:2;		/* Bandwidth control */
+	u32 major_linkch:6;	/* Link channel number */
+	u32 done:1;		/* Channel done */
+	u32 active:1;		/* Channel active */
+	u32 major_elink:1;	/* Enable channel-to-channel linking on major
+				 * loop complete
+				 */
+	u32 e_sg:1;		/* Enable scatter/gather processing */
+	u32 d_req:1;		/* Disable request */
+	u32 int_half:1;		/* Enable an interrupt when major counter is
+				 * half complete
+				 */
+	u32 int_maj:1;		/* Enable an interrupt when major iteration
+				 * count completes
+				 */
+	u32 start:1;		/* Channel start */
+};
+
+struct mpc_dma_desc {
+	struct dma_async_tx_descriptor	desc;
+	struct mpc_dma_tcd		*tcd;
+	dma_addr_t			tcd_paddr;
+	int				error;
+	struct list_head		node;
+};
+
+struct mpc_dma_chan {
+	struct dma_chan			chan;
+	struct list_head		free;
+	struct list_head		prepared;
+	struct list_head		queued;
+	struct list_head		active;
+	struct list_head		completed;
+	struct mpc_dma_tcd		*tcd;
+	dma_addr_t			tcd_paddr;
+	dma_cookie_t			completed_cookie;
+
+	/* Lock for this structure */
+	spinlock_t			lock;
+};
+
+struct mpc_dma {
+	struct dma_device		dma;
+	struct tasklet_struct		tasklet;
+	struct mpc_dma_chan		channels[MPC_DMA_CHANNELS];
+	struct mpc_dma_regs __iomem	*regs;
+	struct mpc_dma_tcd __iomem	*tcd;
+	int				irq;
+	uint				error_status;
+
+	/* Lock for error_status field in this structure */
+	spinlock_t			error_status_lock;
+};
+
+#define DRV_NAME	"mpc512x_dma"
+
+/* Convert struct dma_chan to struct mpc_dma_chan */
+static inline struct mpc_dma_chan *dma_chan_to_mpc_dma_chan(struct dma_chan *c)
+{
+	return container_of(c, struct mpc_dma_chan, chan);
+}
+
+/* Convert struct dma_chan to struct mpc_dma */
+static inline struct mpc_dma *dma_chan_to_mpc_dma(struct dma_chan *c)
+{
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(c);
+	return container_of(mchan, struct mpc_dma, channels[c->chan_id]);
+}
+
+/*
+ * Execute all queued DMA descriptors.
+ *
+ * Following requirements must be met while calling mpc_dma_execute():
+ * 	a) mchan->lock is acquired,
+ * 	b) mchan->active list is empty,
+ * 	c) mchan->queued list contains at least one entry.
+ */
+static void mpc_dma_execute(struct mpc_dma_chan *mchan)
+{
+	struct mpc_dma *mdma = dma_chan_to_mpc_dma(&mchan->chan);
+	struct mpc_dma_desc *first = NULL;
+	struct mpc_dma_desc *prev = NULL;
+	struct mpc_dma_desc *mdesc;
+	int cid = mchan->chan.chan_id;
+
+	/* Move all queued descriptors to active list */
+	list_splice_tail_init(&mchan->queued, &mchan->active);
+
+	/* Chain descriptors into one transaction */
+	list_for_each_entry(mdesc, &mchan->active, node) {
+		if (!first)
+			first = mdesc;
+
+		if (!prev) {
+			prev = mdesc;
+			continue;
+		}
+
+		prev->tcd->dlast_sga = mdesc->tcd_paddr;
+		prev->tcd->e_sg = 1;
+		mdesc->tcd->start = 1;
+
+		prev = mdesc;
+	}
+
+	prev->tcd->start = 0;
+	prev->tcd->int_maj = 1;
+
+	/* Send first descriptor in chain into hardware */
+	memcpy_toio(&mdma->tcd[cid], first->tcd, sizeof(struct mpc_dma_tcd));
+	out_8(&mdma->regs->dmassrt, cid);
+}
+
+/* Handle interrupt on one half of DMA controller (32 channels) */
+static void mpc_dma_irq_process(struct mpc_dma *mdma, u32 is, u32 es, int off)
+{
+	struct mpc_dma_chan *mchan;
+	struct mpc_dma_desc *mdesc;
+	u32 status = is | es;
+	int ch;
+
+	while ((ch = fls(status) - 1) >= 0) {
+		status &= ~(1 << ch);
+		mchan = &mdma->channels[ch + off];
+
+		spin_lock(&mchan->lock);
+
+		/* Check error status */
+		if (es & (1 << ch))
+			list_for_each_entry(mdesc, &mchan->active, node)
+				mdesc->error = -EIO;
+
+		/* Execute queued descriptors */
+		list_splice_tail_init(&mchan->active, &mchan->completed);
+		if (!list_empty(&mchan->queued))
+			mpc_dma_execute(mchan);
+
+		spin_unlock(&mchan->lock);
+	}
+}
+
+/* Interrupt handler */
+static irqreturn_t mpc_dma_irq(int irq, void *data)
+{
+	struct mpc_dma *mdma = data;
+	uint es;
+
+	/* Save error status register */
+	es = in_be32(&mdma->regs->dmaes);
+	spin_lock(&mdma->error_status_lock);
+	if ((es & MPC_DMA_DMAES_VLD) && mdma->error_status == 0)
+		mdma->error_status = es;
+	spin_unlock(&mdma->error_status_lock);
+
+	/* Handle interrupt on each channel */
+	mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth),
+					in_be32(&mdma->regs->dmaerrh), 32);
+	mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmaintl),
+					in_be32(&mdma->regs->dmaerrl), 0);
+
+	/* Ack interrupt on all channels */
+	out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
+
+	/* Schedule tasklet */
+	tasklet_schedule(&mdma->tasklet);
+
+	return IRQ_HANDLED;
+}
+
+/* DMA Tasklet */
+static void mpc_dma_tasklet(unsigned long data)
+{
+	struct mpc_dma *mdma = (void *)data;
+	dma_cookie_t last_cookie = 0;
+	struct mpc_dma_chan *mchan;
+	struct mpc_dma_desc *mdesc;
+	struct dma_async_tx_descriptor *desc;
+	unsigned long flags;
+	LIST_HEAD(list);
+	uint es;
+	int i;
+
+	spin_lock_irqsave(&mdma->error_status_lock, flags);
+	es = mdma->error_status;
+	mdma->error_status = 0;
+	spin_unlock_irqrestore(&mdma->error_status_lock, flags);
+
+	/* Print nice error report */
+	if (es) {
+		dev_err(mdma->dma.dev,
+			"Hardware reported following error(s) on channel %u:\n",
+						      MPC_DMA_DMAES_ERRCHN(es));
+
+		if (es & MPC_DMA_DMAES_GPE)
+			dev_err(mdma->dma.dev, "- Group Priority Error\n");
+		if (es & MPC_DMA_DMAES_CPE)
+			dev_err(mdma->dma.dev, "- Channel Priority Error\n");
+		if (es & MPC_DMA_DMAES_SAE)
+			dev_err(mdma->dma.dev, "- Source Address Error\n");
+		if (es & MPC_DMA_DMAES_SOE)
+			dev_err(mdma->dma.dev, "- Source Offset"
+						" Configuration Error\n");
+		if (es & MPC_DMA_DMAES_DAE)
+			dev_err(mdma->dma.dev, "- Destination Address"
+								" Error\n");
+		if (es & MPC_DMA_DMAES_DOE)
+			dev_err(mdma->dma.dev, "- Destination Offset"
+						" Configuration Error\n");
+		if (es & MPC_DMA_DMAES_NCE)
+			dev_err(mdma->dma.dev, "- NBytes/Citter"
+						" Configuration Error\n");
+		if (es & MPC_DMA_DMAES_SGE)
+			dev_err(mdma->dma.dev, "- Scatter/Gather"
+						" Configuration Error\n");
+		if (es & MPC_DMA_DMAES_SBE)
+			dev_err(mdma->dma.dev, "- Source Bus Error\n");
+		if (es & MPC_DMA_DMAES_DBE)
+			dev_err(mdma->dma.dev, "- Destination Bus Error\n");
+	}
+
+	for (i = 0; i < mdma->dma.chancnt; i++) {
+		mchan = &mdma->channels[i];
+
+		/* Get all completed descriptors */
+		spin_lock_irqsave(&mchan->lock, flags);
+		if (!list_empty(&mchan->completed))
+			list_splice_tail_init(&mchan->completed, &list);
+		spin_unlock_irqrestore(&mchan->lock, flags);
+
+		if (list_empty(&list))
+			continue;
+
+		/* Execute callbacks and run dependencies */
+		list_for_each_entry(mdesc, &list, node) {
+			desc = &mdesc->desc;
+
+			if (desc->callback)
+				desc->callback(desc->callback_param);
+
+			last_cookie = desc->cookie;
+			dma_run_dependencies(desc);
+		}
+
+		/* Free descriptors */
+		spin_lock_irqsave(&mchan->lock, flags);
+		list_splice_tail_init(&list, &mchan->free);
+		mchan->completed_cookie = last_cookie;
+		spin_unlock_irqrestore(&mchan->lock, flags);
+	}
+}
+
+/* Submit descriptor to hardware */
+static dma_cookie_t mpc_dma_tx_submit(struct dma_async_tx_descriptor *txd)
+{
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(txd->chan);
+	struct mpc_dma_desc *mdesc;
+	unsigned long flags;
+	dma_cookie_t cookie;
+
+	mdesc = container_of(txd, struct mpc_dma_desc, desc);
+
+	spin_lock_irqsave(&mchan->lock, flags);
+
+	/* Move descriptor to queue */
+	list_move_tail(&mdesc->node, &mchan->queued);
+
+	/* If channel is idle, execute all queued descriptors */
+	if (list_empty(&mchan->active))
+		mpc_dma_execute(mchan);
+
+	/* Update cookie */
+	cookie = mchan->chan.cookie + 1;
+	if (cookie <= 0)
+		cookie = 1;
+
+	mchan->chan.cookie = cookie;
+	mdesc->desc.cookie = cookie;
+
+	spin_unlock_irqrestore(&mchan->lock, flags);
+
+	return cookie;
+}
+
+/* Alloc channel resources */
+static int mpc_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+	struct mpc_dma_desc *mdesc;
+	struct mpc_dma_tcd *tcd;
+	dma_addr_t tcd_paddr;
+	unsigned long flags;
+	LIST_HEAD(descs);
+	int i;
+
+	/* Alloc DMA memory for Transfer Control Descriptors */
+	tcd = dma_alloc_coherent(mdma->dma.dev,
+			MPC_DMA_DESCRIPTORS * sizeof(struct mpc_dma_tcd),
+							&tcd_paddr, GFP_KERNEL);
+	if (!tcd)
+		return -ENOMEM;
+
+	/* Alloc descriptors for this channel */
+	for (i = 0; i < MPC_DMA_DESCRIPTORS; i++) {
+		mdesc = kzalloc(sizeof(struct mpc_dma_desc), GFP_KERNEL);
+		if (!mdesc) {
+			dev_notice(mdma->dma.dev, "Memory allocation error. "
+					"Allocated only %u descriptors\n", i);
+			break;
+		}
+
+		dma_async_tx_descriptor_init(&mdesc->desc, chan);
+		mdesc->desc.flags = DMA_CTRL_ACK;
+		mdesc->desc.tx_submit = mpc_dma_tx_submit;
+
+		mdesc->tcd = &tcd[i];
+		mdesc->tcd_paddr = tcd_paddr + (i * sizeof(struct mpc_dma_tcd));
+
+		list_add_tail(&mdesc->node, &descs);
+	}
+
+	/* Return error only if no descriptors were allocated */
+	if (i == 0) {
+		dma_free_coherent(mdma->dma.dev,
+			MPC_DMA_DESCRIPTORS * sizeof(struct mpc_dma_tcd),
+								tcd, tcd_paddr);
+		return -ENOMEM;
+	}
+
+	spin_lock_irqsave(&mchan->lock, flags);
+	mchan->tcd = tcd;
+	mchan->tcd_paddr = tcd_paddr;
+	list_splice_tail_init(&descs, &mchan->free);
+	spin_unlock_irqrestore(&mchan->lock, flags);
+
+	/* Enable Error Interrupt */
+	out_8(&mdma->regs->dmaseei, chan->chan_id);
+
+	return 0;
+}
+
+/* Free channel resources */
+static void mpc_dma_free_chan_resources(struct dma_chan *chan)
+{
+	struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+	struct mpc_dma_desc *mdesc, *tmp;
+	struct mpc_dma_tcd *tcd;
+	dma_addr_t tcd_paddr;
+	unsigned long flags;
+	LIST_HEAD(descs);
+
+	spin_lock_irqsave(&mchan->lock, flags);
+
+	/* Channel must be idle */
+	BUG_ON(!list_empty(&mchan->prepared));
+	BUG_ON(!list_empty(&mchan->queued));
+	BUG_ON(!list_empty(&mchan->active));
+	BUG_ON(!list_empty(&mchan->completed));
+
+	/* Move data */
+	list_splice_tail_init(&mchan->free, &descs);
+	tcd = mchan->tcd;
+	tcd_paddr = mchan->tcd_paddr;
+
+	spin_unlock_irqrestore(&mchan->lock, flags);
+
+	/* Free DMA memory used by descriptors */
+	dma_free_coherent(mdma->dma.dev,
+			MPC_DMA_DESCRIPTORS * sizeof(struct mpc_dma_tcd),
+								tcd, tcd_paddr);
+
+	/* Free descriptors */
+	list_for_each_entry_safe(mdesc, tmp, &descs, node)
+		kfree(mdesc);
+
+	/* Disable Error Interrupt */
+	out_8(&mdma->regs->dmaceei, chan->chan_id);
+}
+
+/* Send all pending descriptor to hardware */
+static void mpc_dma_issue_pending(struct dma_chan *chan)
+{
+	/*
+	 * We are posting descriptors to the hardware as soon as
+	 * they are ready, so this function does nothing.
+	 */
+}
+
+/* Check request completion status */
+static enum dma_status
+mpc_dma_is_tx_complete(struct dma_chan *chan, dma_cookie_t cookie,
+					dma_cookie_t *done, dma_cookie_t *used)
+{
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+	unsigned long flags;
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+
+	spin_lock_irqsave(&mchan->lock, flags);
+	last_used = mchan->chan.cookie;
+	last_complete = mchan->completed_cookie;
+	spin_unlock_irqrestore(&mchan->lock, flags);
+
+	if (done)
+		*done = last_complete;
+
+	if (used)
+		*used = last_used;
+
+	return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+/* Prepare descriptor for memory to memory copy */
+static struct dma_async_tx_descriptor *
+mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
+					size_t len, unsigned long flags)
+{
+	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+	struct mpc_dma_desc *mdesc = NULL;
+	struct mpc_dma_tcd *tcd;
+	unsigned long iflags;
+
+	/* Get free descriptor */
+	spin_lock_irqsave(&mchan->lock, iflags);
+	if (!list_empty(&mchan->free)) {
+		mdesc = list_first_entry(&mchan->free, struct mpc_dma_desc,
+									node);
+		list_del(&mdesc->node);
+	}
+	spin_unlock_irqrestore(&mchan->lock, iflags);
+
+	if (!mdesc)
+		return NULL;
+
+	mdesc->error = 0;
+	tcd = mdesc->tcd;
+
+	/* Prepare Transfer Control Descriptor for this transaction */
+	memset(tcd, 0, sizeof(struct mpc_dma_tcd));
+
+	if (IS_ALIGNED(src | dst | len, 32)) {
+		tcd->ssize = MPC_DMA_TSIZE_32;
+		tcd->dsize = MPC_DMA_TSIZE_32;
+		tcd->soff = 32;
+		tcd->doff = 32;
+	} else if (IS_ALIGNED(src | dst | len, 16)) {
+		tcd->ssize = MPC_DMA_TSIZE_16;
+		tcd->dsize = MPC_DMA_TSIZE_16;
+		tcd->soff = 16;
+		tcd->doff = 16;
+	} else if (IS_ALIGNED(src | dst | len, 4)) {
+		tcd->ssize = MPC_DMA_TSIZE_4;
+		tcd->dsize = MPC_DMA_TSIZE_4;
+		tcd->soff = 4;
+		tcd->doff = 4;
+	} else if (IS_ALIGNED(src | dst | len, 2)) {
+		tcd->ssize = MPC_DMA_TSIZE_2;
+		tcd->dsize = MPC_DMA_TSIZE_2;
+		tcd->soff = 2;
+		tcd->doff = 2;
+	} else {
+		tcd->ssize = MPC_DMA_TSIZE_1;
+		tcd->dsize = MPC_DMA_TSIZE_1;
+		tcd->soff = 1;
+		tcd->doff = 1;
+	}
+
+	tcd->saddr = src;
+	tcd->daddr = dst;
+	tcd->nbytes = len;
+	tcd->biter = 1;
+	tcd->citer = 1;
+
+	/* Place descriptor in prepared list */
+	spin_lock_irqsave(&mchan->lock, iflags);
+	list_add_tail(&mdesc->node, &mchan->prepared);
+	spin_unlock_irqrestore(&mchan->lock, iflags);
+
+	return &mdesc->desc;
+}
+
+static int __devinit mpc_dma_probe(struct of_device *op,
+					const struct of_device_id *match)
+{
+	struct device_node *dn = op->node;
+	struct device *dev = &op->dev;
+	struct dma_device *dma;
+	struct mpc_dma *mdma;
+	struct mpc_dma_chan *mchan;
+	struct resource res;
+	ulong regs_start, regs_size;
+	int retval, i;
+
+	mdma = devm_kzalloc(dev, sizeof(struct mpc_dma), GFP_KERNEL);
+	if (!mdma) {
+		dev_err(dev, "Memory exhausted!\n");
+		return -ENOMEM;
+	}
+
+	mdma->irq = irq_of_parse_and_map(dn, 0);
+	if (mdma->irq == NO_IRQ) {
+		dev_err(dev, "Error mapping IRQ!\n");
+		return -EINVAL;
+	}
+
+	retval = of_address_to_resource(dn, 0, &res);
+	if (retval) {
+		dev_err(dev, "Error parsing memory region!\n");
+		return retval;
+	}
+
+	regs_start = res.start;
+	regs_size = res.end - res.start + 1;
+
+	if (!devm_request_mem_region(dev, regs_start, regs_size, DRV_NAME)) {
+		dev_err(dev, "Error requesting memory region!\n");
+		return -EBUSY;
+	}
+
+	mdma->regs = devm_ioremap(dev, regs_start, regs_size);
+	if (!mdma->regs) {
+		dev_err(dev, "Error mapping memory region!\n");
+		return -ENOMEM;
+	}
+
+	mdma->tcd = (struct mpc_dma_tcd *)((u8 *)(mdma->regs)
+							+ MPC_DMA_TCD_OFFSET);
+
+	retval = devm_request_irq(dev, mdma->irq, &mpc_dma_irq, 0, DRV_NAME,
+									mdma);
+	if (retval) {
+		dev_err(dev, "Error requesting IRQ!\n");
+		return -EINVAL;
+	}
+
+	spin_lock_init(&mdma->error_status_lock);
+
+	dma = &mdma->dma;
+	dma->dev = dev;
+	dma->chancnt = MPC_DMA_CHANNELS;
+	dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources;
+	dma->device_free_chan_resources = mpc_dma_free_chan_resources;
+	dma->device_issue_pending = mpc_dma_issue_pending;
+	dma->device_is_tx_complete = mpc_dma_is_tx_complete;
+	dma->device_prep_dma_memcpy = mpc_dma_prep_memcpy;
+
+	INIT_LIST_HEAD(&dma->channels);
+	dma_cap_set(DMA_MEMCPY, dma->cap_mask);
+
+	for (i = 0; i < dma->chancnt; i++) {
+		mchan = &mdma->channels[i];
+
+		mchan->chan.device = dma;
+		mchan->chan.chan_id = i;
+		mchan->chan.cookie = 1;
+		mchan->completed_cookie = mchan->chan.cookie;
+
+		INIT_LIST_HEAD(&mchan->free);
+		INIT_LIST_HEAD(&mchan->prepared);
+		INIT_LIST_HEAD(&mchan->queued);
+		INIT_LIST_HEAD(&mchan->active);
+		INIT_LIST_HEAD(&mchan->completed);
+
+		spin_lock_init(&mchan->lock);
+		list_add_tail(&mchan->chan.device_node, &dma->channels);
+	}
+
+	tasklet_init(&mdma->tasklet, mpc_dma_tasklet, (unsigned long)mdma);
+
+	/*
+	 * Configure DMA Engine:
+	 * - Dynamic clock,
+	 * - Round-robin group arbitration,
+	 * - Round-robin channel arbitration.
+	 */
+	out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
+				MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
+
+	/* Disable hardware DMA requests */
+	out_be32(&mdma->regs->dmaerqh, 0);
+	out_be32(&mdma->regs->dmaerql, 0);
+
+	/* Disable error interrupts */
+	out_be32(&mdma->regs->dmaeeih, 0);
+	out_be32(&mdma->regs->dmaeeil, 0);
+
+	/* Clear interrupts status */
+	out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
+	out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
+
+	/* Route interrupts to IPIC */
+	out_be32(&mdma->regs->dmaihsa, 0);
+	out_be32(&mdma->regs->dmailsa, 0);
+
+	/* Register DMA engine */
+	dev_set_drvdata(dev, mdma);
+	retval = dma_async_device_register(dma);
+	if (retval) {
+		devm_free_irq(dev, mdma->irq, mdma);
+		irq_dispose_mapping(mdma->irq);
+	}
+
+	return retval;
+}
+
+static int __devexit mpc_dma_remove(struct of_device *op)
+{
+	struct device *dev = &op->dev;
+	struct mpc_dma *mdma = dev_get_drvdata(dev);
+
+	dma_async_device_unregister(&mdma->dma);
+	devm_free_irq(dev, mdma->irq, mdma);
+	irq_dispose_mapping(mdma->irq);
+
+	return 0;
+}
+
+static struct of_device_id mpc_dma_match[] = {
+	{ .compatible = "fsl,mpc5121-dma", },
+	{},
+};
+
+static struct of_platform_driver mpc_dma_driver = {
+	.match_table	= mpc_dma_match,
+	.probe		= mpc_dma_probe,
+	.remove		= __devexit_p(mpc_dma_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init mpc_dma_init(void)
+{
+	return of_register_platform_driver(&mpc_dma_driver);
+}
+module_init(mpc_dma_init);
+
+static void __exit mpc_dma_exit(void)
+{
+	of_unregister_platform_driver(&mpc_dma_driver);
+}
+module_exit(mpc_dma_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Piotr Ziecik <kosmo@semihalf.com>");
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index 0a3478e..e69d87f 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4940,7 +4940,7 @@
 	return ret;
 }
 
-static struct of_device_id __devinitdata ppc440spe_adma_of_match[] = {
+static const struct of_device_id ppc440spe_adma_of_match[] __devinitconst = {
 	{ .compatible	= "ibm,dma-440spe", },
 	{ .compatible	= "amcc,xor-accelerator", },
 	{},
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index b75ce8b..5d17e09 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -24,8 +24,10 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
-#include <cpu/dma.h>
-#include <asm/dma-sh.h>
+#include <linux/pm_runtime.h>
+
+#include <asm/dmaengine.h>
+
 #include "shdma.h"
 
 /* DMA descriptor control */
@@ -38,30 +40,32 @@
 };
 
 #define NR_DESCS_PER_CHANNEL 32
-/*
- * Define the default configuration for dual address memory-memory transfer.
- * The 0x400 value represents auto-request, external->external.
- *
- * And this driver set 4byte burst mode.
- * If you want to change mode, you need to change RS_DEFAULT of value.
- * (ex 1byte burst mode -> (RS_DUAL & ~TS_32)
- */
-#define RS_DEFAULT  (RS_DUAL)
+/* Default MEMCPY transfer size = 2^2 = 4 bytes */
+#define LOG2_DEFAULT_XFER_SIZE	2
 
 /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */
 static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)];
 
 static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
 
-#define SH_DMAC_CHAN_BASE(id) (dma_base_addr[id])
 static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
 {
-	ctrl_outl(data, SH_DMAC_CHAN_BASE(sh_dc->id) + reg);
+	__raw_writel(data, sh_dc->base + reg / sizeof(u32));
 }
 
 static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
 {
-	return ctrl_inl(SH_DMAC_CHAN_BASE(sh_dc->id) + reg);
+	return __raw_readl(sh_dc->base + reg / sizeof(u32));
+}
+
+static u16 dmaor_read(struct sh_dmae_device *shdev)
+{
+	return __raw_readw(shdev->chan_reg + DMAOR / sizeof(u32));
+}
+
+static void dmaor_write(struct sh_dmae_device *shdev, u16 data)
+{
+	__raw_writew(data, shdev->chan_reg + DMAOR / sizeof(u32));
 }
 
 /*
@@ -69,24 +73,23 @@
  *
  * SH7780 has two DMAOR register
  */
-static void sh_dmae_ctl_stop(int id)
+static void sh_dmae_ctl_stop(struct sh_dmae_device *shdev)
 {
-	unsigned short dmaor = dmaor_read_reg(id);
+	unsigned short dmaor = dmaor_read(shdev);
 
-	dmaor &= ~(DMAOR_NMIF | DMAOR_AE);
-	dmaor_write_reg(id, dmaor);
+	dmaor_write(shdev, dmaor & ~(DMAOR_NMIF | DMAOR_AE | DMAOR_DME));
 }
 
-static int sh_dmae_rst(int id)
+static int sh_dmae_rst(struct sh_dmae_device *shdev)
 {
 	unsigned short dmaor;
 
-	sh_dmae_ctl_stop(id);
-	dmaor = dmaor_read_reg(id) | DMAOR_INIT;
+	sh_dmae_ctl_stop(shdev);
+	dmaor = dmaor_read(shdev) | shdev->pdata->dmaor_init;
 
-	dmaor_write_reg(id, dmaor);
-	if (dmaor_read_reg(id) & (DMAOR_AE | DMAOR_NMIF)) {
-		pr_warning(KERN_ERR "dma-sh: Can't initialize DMAOR.\n");
+	dmaor_write(shdev, dmaor);
+	if (dmaor_read(shdev) & (DMAOR_AE | DMAOR_NMIF)) {
+		pr_warning("dma-sh: Can't initialize DMAOR.\n");
 		return -EINVAL;
 	}
 	return 0;
@@ -102,13 +105,36 @@
 	return false; /* waiting */
 }
 
-static unsigned int ts_shift[] = TS_SHIFT;
-static inline unsigned int calc_xmit_shift(u32 chcr)
+static unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan, u32 chcr)
 {
-	int cnt = ((chcr & CHCR_TS_LOW_MASK) >> CHCR_TS_LOW_SHIFT) |
-		((chcr & CHCR_TS_HIGH_MASK) >> CHCR_TS_HIGH_SHIFT);
+	struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
+						struct sh_dmae_device, common);
+	struct sh_dmae_pdata *pdata = shdev->pdata;
+	int cnt = ((chcr & pdata->ts_low_mask) >> pdata->ts_low_shift) |
+		((chcr & pdata->ts_high_mask) >> pdata->ts_high_shift);
 
-	return ts_shift[cnt];
+	if (cnt >= pdata->ts_shift_num)
+		cnt = 0;
+
+	return pdata->ts_shift[cnt];
+}
+
+static u32 log2size_to_chcr(struct sh_dmae_chan *sh_chan, int l2size)
+{
+	struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
+						struct sh_dmae_device, common);
+	struct sh_dmae_pdata *pdata = shdev->pdata;
+	int i;
+
+	for (i = 0; i < pdata->ts_shift_num; i++)
+		if (pdata->ts_shift[i] == l2size)
+			break;
+
+	if (i == pdata->ts_shift_num)
+		i = 0;
+
+	return ((i << pdata->ts_low_shift) & pdata->ts_low_mask) |
+		((i << pdata->ts_high_shift) & pdata->ts_high_mask);
 }
 
 static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
@@ -136,8 +162,13 @@
 
 static void dmae_init(struct sh_dmae_chan *sh_chan)
 {
-	u32 chcr = RS_DEFAULT; /* default is DUAL mode */
-	sh_chan->xmit_shift = calc_xmit_shift(chcr);
+	/*
+	 * Default configuration for dual address memory-memory transfer.
+	 * 0x400 represents auto-request.
+	 */
+	u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan,
+						   LOG2_DEFAULT_XFER_SIZE);
+	sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr);
 	sh_dmae_writel(sh_chan, chcr, CHCR);
 }
 
@@ -147,37 +178,26 @@
 	if (dmae_is_busy(sh_chan))
 		return -EBUSY;
 
-	sh_chan->xmit_shift = calc_xmit_shift(val);
+	sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val);
 	sh_dmae_writel(sh_chan, val, CHCR);
 
 	return 0;
 }
 
-#define DMARS_SHIFT	8
-#define DMARS_CHAN_MSK	0x01
 static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
 {
-	u32 addr;
-	int shift = 0;
+	struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
+						struct sh_dmae_device, common);
+	struct sh_dmae_pdata *pdata = shdev->pdata;
+	struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id];
+	u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16);
+	int shift = chan_pdata->dmars_bit;
 
 	if (dmae_is_busy(sh_chan))
 		return -EBUSY;
 
-	if (sh_chan->id & DMARS_CHAN_MSK)
-		shift = DMARS_SHIFT;
-
-	if (sh_chan->id < 6)
-		/* DMA0RS0 - DMA0RS2 */
-		addr = SH_DMARS_BASE0 + (sh_chan->id / 2) * 4;
-#ifdef SH_DMARS_BASE1
-	else if (sh_chan->id < 12)
-		/* DMA1RS0 - DMA1RS2 */
-		addr = SH_DMARS_BASE1 + ((sh_chan->id - 6) / 2) * 4;
-#endif
-	else
-		return -EINVAL;
-
-	ctrl_outw((val << shift) | (ctrl_inw(addr) & (0xFF00 >> shift)), addr);
+	__raw_writew((__raw_readw(addr) & (0xff00 >> shift)) | (val << shift),
+		     addr);
 
 	return 0;
 }
@@ -251,15 +271,15 @@
 	struct dma_device *dma_dev = sh_chan->common.device;
 	struct sh_dmae_device *shdev = container_of(dma_dev,
 					struct sh_dmae_device, common);
-	struct sh_dmae_pdata *pdata = &shdev->pdata;
+	struct sh_dmae_pdata *pdata = shdev->pdata;
 	int i;
 
 	if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER)
 		return NULL;
 
-	for (i = 0; i < pdata->config_num; i++)
-		if (pdata->config[i].slave_id == slave_id)
-			return pdata->config + i;
+	for (i = 0; i < pdata->slave_num; i++)
+		if (pdata->slave[i].slave_id == slave_id)
+			return pdata->slave + i;
 
 	return NULL;
 }
@@ -270,6 +290,8 @@
 	struct sh_desc *desc;
 	struct sh_dmae_slave *param = chan->private;
 
+	pm_runtime_get_sync(sh_chan->dev);
+
 	/*
 	 * This relies on the guarantee from dmaengine that alloc_chan_resources
 	 * never runs concurrently with itself or free_chan_resources.
@@ -288,9 +310,8 @@
 
 		dmae_set_dmars(sh_chan, cfg->mid_rid);
 		dmae_set_chcr(sh_chan, cfg->chcr);
-	} else {
-		if ((sh_dmae_readl(sh_chan, CHCR) & 0x700) != 0x400)
-			dmae_set_chcr(sh_chan, RS_DEFAULT);
+	} else if ((sh_dmae_readl(sh_chan, CHCR) & 0xf00) != 0x400) {
+		dmae_init(sh_chan);
 	}
 
 	spin_lock_bh(&sh_chan->desc_lock);
@@ -312,6 +333,9 @@
 	}
 	spin_unlock_bh(&sh_chan->desc_lock);
 
+	if (!sh_chan->descs_allocated)
+		pm_runtime_put(sh_chan->dev);
+
 	return sh_chan->descs_allocated;
 }
 
@@ -323,6 +347,7 @@
 	struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
 	struct sh_desc *desc, *_desc;
 	LIST_HEAD(list);
+	int descs = sh_chan->descs_allocated;
 
 	dmae_halt(sh_chan);
 
@@ -343,6 +368,9 @@
 
 	spin_unlock_bh(&sh_chan->desc_lock);
 
+	if (descs > 0)
+		pm_runtime_put(sh_chan->dev);
+
 	list_for_each_entry_safe(desc, _desc, &list, node)
 		kfree(desc);
 }
@@ -559,6 +587,19 @@
 	if (!chan)
 		return;
 
+	dmae_halt(sh_chan);
+
+	spin_lock_bh(&sh_chan->desc_lock);
+	if (!list_empty(&sh_chan->ld_queue)) {
+		/* Record partial transfer */
+		struct sh_desc *desc = list_entry(sh_chan->ld_queue.next,
+						  struct sh_desc, node);
+		desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
+			sh_chan->xmit_shift;
+
+	}
+	spin_unlock_bh(&sh_chan->desc_lock);
+
 	sh_dmae_chan_ld_cleanup(sh_chan, true);
 }
 
@@ -661,7 +702,7 @@
 
 static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
 {
-	struct sh_desc *sd;
+	struct sh_desc *desc;
 
 	spin_lock_bh(&sh_chan->desc_lock);
 	/* DMA work check */
@@ -671,10 +712,13 @@
 	}
 
 	/* Find the first not transferred desciptor */
-	list_for_each_entry(sd, &sh_chan->ld_queue, node)
-		if (sd->mark == DESC_SUBMITTED) {
+	list_for_each_entry(desc, &sh_chan->ld_queue, node)
+		if (desc->mark == DESC_SUBMITTED) {
+			dev_dbg(sh_chan->dev, "Queue #%d to %d: %u@%x -> %x\n",
+				desc->async_tx.cookie, sh_chan->id,
+				desc->hw.tcr, desc->hw.sar, desc->hw.dar);
 			/* Get the ld start address from ld_queue */
-			dmae_set_reg(sh_chan, &sd->hw);
+			dmae_set_reg(sh_chan, &desc->hw);
 			dmae_start(sh_chan);
 			break;
 		}
@@ -696,6 +740,7 @@
 	struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
 	dma_cookie_t last_used;
 	dma_cookie_t last_complete;
+	enum dma_status status;
 
 	sh_dmae_chan_ld_cleanup(sh_chan, false);
 
@@ -709,7 +754,27 @@
 	if (used)
 		*used = last_used;
 
-	return dma_async_is_complete(cookie, last_complete, last_used);
+	spin_lock_bh(&sh_chan->desc_lock);
+
+	status = dma_async_is_complete(cookie, last_complete, last_used);
+
+	/*
+	 * If we don't find cookie on the queue, it has been aborted and we have
+	 * to report error
+	 */
+	if (status != DMA_SUCCESS) {
+		struct sh_desc *desc;
+		status = DMA_ERROR;
+		list_for_each_entry(desc, &sh_chan->ld_queue, node)
+			if (desc->cookie == cookie) {
+				status = DMA_IN_PROGRESS;
+				break;
+			}
+	}
+
+	spin_unlock_bh(&sh_chan->desc_lock);
+
+	return status;
 }
 
 static irqreturn_t sh_dmae_interrupt(int irq, void *data)
@@ -732,40 +797,32 @@
 #if defined(CONFIG_CPU_SH4)
 static irqreturn_t sh_dmae_err(int irq, void *data)
 {
-	int err = 0;
 	struct sh_dmae_device *shdev = (struct sh_dmae_device *)data;
+	int i;
 
-	/* IRQ Multi */
-	if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
-		int __maybe_unused cnt = 0;
-		switch (irq) {
-#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)
-		case DMTE6_IRQ:
-			cnt++;
-#endif
-		case DMTE0_IRQ:
-			if (dmaor_read_reg(cnt) & (DMAOR_NMIF | DMAOR_AE)) {
-				disable_irq(irq);
-				return IRQ_HANDLED;
+	/* halt the dma controller */
+	sh_dmae_ctl_stop(shdev);
+
+	/* 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);
 			}
-		default:
-			return IRQ_NONE;
+			list_splice_init(&sh_chan->ld_queue, &sh_chan->ld_free);
 		}
-	} else {
-		/* reset dma controller */
-		err = sh_dmae_rst(0);
-		if (err)
-			return err;
-#ifdef SH_DMAC_BASE1
-		if (shdev->pdata.mode & SHDMA_DMAOR1) {
-			err = sh_dmae_rst(1);
-			if (err)
-				return err;
-		}
-#endif
-		disable_irq(irq);
-		return IRQ_HANDLED;
 	}
+	sh_dmae_rst(shdev);
+
+	return IRQ_HANDLED;
 }
 #endif
 
@@ -796,19 +853,12 @@
 	sh_dmae_chan_ld_cleanup(sh_chan, false);
 }
 
-static unsigned int get_dmae_irq(unsigned int id)
-{
-	unsigned int irq = 0;
-	if (id < ARRAY_SIZE(dmte_irq_map))
-		irq = dmte_irq_map[id];
-	return irq;
-}
-
-static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id)
+static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
+					int irq, unsigned long flags)
 {
 	int err;
-	unsigned int irq = get_dmae_irq(id);
-	unsigned long irqflags = IRQF_DISABLED;
+	struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id];
+	struct platform_device *pdev = to_platform_device(shdev->common.dev);
 	struct sh_dmae_chan *new_sh_chan;
 
 	/* alloc channel */
@@ -819,8 +869,13 @@
 		return -ENOMEM;
 	}
 
+	/* copy struct dma_device */
+	new_sh_chan->common.device = &shdev->common;
+
 	new_sh_chan->dev = shdev->common.dev;
 	new_sh_chan->id = id;
+	new_sh_chan->irq = irq;
+	new_sh_chan->base = shdev->chan_reg + chan_pdata->offset / sizeof(u32);
 
 	/* Init DMA tasklet */
 	tasklet_init(&new_sh_chan->tasklet, dmae_do_tasklet,
@@ -835,29 +890,20 @@
 	INIT_LIST_HEAD(&new_sh_chan->ld_queue);
 	INIT_LIST_HEAD(&new_sh_chan->ld_free);
 
-	/* copy struct dma_device */
-	new_sh_chan->common.device = &shdev->common;
-
 	/* Add the channel to DMA device channel list */
 	list_add_tail(&new_sh_chan->common.device_node,
 			&shdev->common.channels);
 	shdev->common.chancnt++;
 
-	if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
-		irqflags = IRQF_SHARED;
-#if defined(DMTE6_IRQ)
-		if (irq >= DMTE6_IRQ)
-			irq = DMTE6_IRQ;
-		else
-#endif
-			irq = DMTE0_IRQ;
-	}
-
-	snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
-		 "sh-dmae%d", new_sh_chan->id);
+	if (pdev->id >= 0)
+		snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
+			 "sh-dmae%d.%d", pdev->id, new_sh_chan->id);
+	else
+		snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
+			 "sh-dma%d", new_sh_chan->id);
 
 	/* set up channel irq */
-	err = request_irq(irq, &sh_dmae_interrupt, irqflags,
+	err = request_irq(irq, &sh_dmae_interrupt, flags,
 			  new_sh_chan->dev_id, new_sh_chan);
 	if (err) {
 		dev_err(shdev->common.dev, "DMA channel %d request_irq error "
@@ -881,12 +927,12 @@
 
 	for (i = shdev->common.chancnt - 1 ; i >= 0 ; i--) {
 		if (shdev->chan[i]) {
-			struct sh_dmae_chan *shchan = shdev->chan[i];
-			if (!(shdev->pdata.mode & SHDMA_MIX_IRQ))
-				free_irq(dmte_irq_map[i], shchan);
+			struct sh_dmae_chan *sh_chan = shdev->chan[i];
 
-			list_del(&shchan->common.device_node);
-			kfree(shchan);
+			free_irq(sh_chan->irq, sh_chan);
+
+			list_del(&sh_chan->common.device_node);
+			kfree(sh_chan);
 			shdev->chan[i] = NULL;
 		}
 	}
@@ -895,47 +941,84 @@
 
 static int __init sh_dmae_probe(struct platform_device *pdev)
 {
-	int err = 0, cnt, ecnt;
-	unsigned long irqflags = IRQF_DISABLED;
-#if defined(CONFIG_CPU_SH4)
-	int eirq[] = { DMAE0_IRQ,
-#if defined(DMAE1_IRQ)
-			DMAE1_IRQ
-#endif
-		};
-#endif
+	struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
+	unsigned long irqflags = IRQF_DISABLED,
+		chan_flag[SH_DMAC_MAX_CHANNELS] = {};
+	int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
+	int err, i, irq_cnt = 0, irqres = 0;
 	struct sh_dmae_device *shdev;
+	struct resource *chan, *dmars, *errirq_res, *chanirq_res;
 
 	/* get platform data */
-	if (!pdev->dev.platform_data)
+	if (!pdata || !pdata->channel_num)
 		return -ENODEV;
 
+	chan = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	/* DMARS area is optional, if absent, this controller cannot do slave DMA */
+	dmars = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	/*
+	 * IRQ resources:
+	 * 1. there always must be at least one IRQ IO-resource. On SH4 it is
+	 *    the error IRQ, in which case it is the only IRQ in this resource:
+	 *    start == end. If it is the only IRQ resource, all channels also
+	 *    use the same IRQ.
+	 * 2. DMA channel IRQ resources can be specified one per resource or in
+	 *    ranges (start != end)
+	 * 3. iff all events (channels and, optionally, error) on this
+	 *    controller use the same IRQ, only one IRQ resource can be
+	 *    specified, otherwise there must be one IRQ per channel, even if
+	 *    some of them are equal
+	 * 4. if all IRQs on this controller are equal or if some specific IRQs
+	 *    specify IORESOURCE_IRQ_SHAREABLE in their resources, they will be
+	 *    requested with the IRQF_SHARED flag
+	 */
+	errirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!chan || !errirq_res)
+		return -ENODEV;
+
+	if (!request_mem_region(chan->start, resource_size(chan), pdev->name)) {
+		dev_err(&pdev->dev, "DMAC register region already claimed\n");
+		return -EBUSY;
+	}
+
+	if (dmars && !request_mem_region(dmars->start, resource_size(dmars), pdev->name)) {
+		dev_err(&pdev->dev, "DMAC DMARS region already claimed\n");
+		err = -EBUSY;
+		goto ermrdmars;
+	}
+
+	err = -ENOMEM;
 	shdev = kzalloc(sizeof(struct sh_dmae_device), GFP_KERNEL);
 	if (!shdev) {
-		dev_err(&pdev->dev, "No enough memory\n");
-		return -ENOMEM;
+		dev_err(&pdev->dev, "Not enough memory\n");
+		goto ealloc;
+	}
+
+	shdev->chan_reg = ioremap(chan->start, resource_size(chan));
+	if (!shdev->chan_reg)
+		goto emapchan;
+	if (dmars) {
+		shdev->dmars = ioremap(dmars->start, resource_size(dmars));
+		if (!shdev->dmars)
+			goto emapdmars;
 	}
 
 	/* platform data */
-	memcpy(&shdev->pdata, pdev->dev.platform_data,
-			sizeof(struct sh_dmae_pdata));
+	shdev->pdata = pdata;
+
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(&pdev->dev);
 
 	/* reset dma controller */
-	err = sh_dmae_rst(0);
+	err = sh_dmae_rst(shdev);
 	if (err)
 		goto rst_err;
 
-	/* SH7780/85/23 has DMAOR1 */
-	if (shdev->pdata.mode & SHDMA_DMAOR1) {
-		err = sh_dmae_rst(1);
-		if (err)
-			goto rst_err;
-	}
-
 	INIT_LIST_HEAD(&shdev->common.channels);
 
 	dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
-	dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
+	if (dmars)
+		dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
 
 	shdev->common.device_alloc_chan_resources
 		= sh_dmae_alloc_chan_resources;
@@ -950,37 +1033,72 @@
 
 	shdev->common.dev = &pdev->dev;
 	/* Default transfer size of 32 bytes requires 32-byte alignment */
-	shdev->common.copy_align = 5;
+	shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;
 
 #if defined(CONFIG_CPU_SH4)
-	/* Non Mix IRQ mode SH7722/SH7730 etc... */
-	if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
+	chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+
+	if (!chanirq_res)
+		chanirq_res = errirq_res;
+	else
+		irqres++;
+
+	if (chanirq_res == errirq_res ||
+	    (errirq_res->flags & IORESOURCE_BITS) == IORESOURCE_IRQ_SHAREABLE)
 		irqflags = IRQF_SHARED;
-		eirq[0] = DMTE0_IRQ;
-#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)
-		eirq[1] = DMTE6_IRQ;
-#endif
+
+	errirq = errirq_res->start;
+
+	err = request_irq(errirq, sh_dmae_err, irqflags,
+			  "DMAC Address Error", shdev);
+	if (err) {
+		dev_err(&pdev->dev,
+			"DMA failed requesting irq #%d, error %d\n",
+			errirq, err);
+		goto eirq_err;
 	}
 
-	for (ecnt = 0 ; ecnt < ARRAY_SIZE(eirq); ecnt++) {
-		err = request_irq(eirq[ecnt], sh_dmae_err, irqflags,
-				  "DMAC Address Error", shdev);
-		if (err) {
-			dev_err(&pdev->dev, "DMA device request_irq"
-				"error (irq %d) with return %d\n",
-				eirq[ecnt], err);
-			goto eirq_err;
-		}
-	}
+#else
+	chanirq_res = errirq_res;
 #endif /* CONFIG_CPU_SH4 */
 
+	if (chanirq_res->start == chanirq_res->end &&
+	    !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
+		/* Special case - all multiplexed */
+		for (; irq_cnt < pdata->channel_num; irq_cnt++) {
+			chan_irq[irq_cnt] = chanirq_res->start;
+			chan_flag[irq_cnt] = IRQF_SHARED;
+		}
+	} else {
+		do {
+			for (i = chanirq_res->start; i <= chanirq_res->end; i++) {
+				if ((errirq_res->flags & IORESOURCE_BITS) ==
+				    IORESOURCE_IRQ_SHAREABLE)
+					chan_flag[irq_cnt] = IRQF_SHARED;
+				else
+					chan_flag[irq_cnt] = IRQF_DISABLED;
+				dev_dbg(&pdev->dev,
+					"Found IRQ %d for channel %d\n",
+					i, irq_cnt);
+				chan_irq[irq_cnt++] = i;
+			}
+			chanirq_res = platform_get_resource(pdev,
+						IORESOURCE_IRQ, ++irqres);
+		} while (irq_cnt < pdata->channel_num && chanirq_res);
+	}
+
+	if (irq_cnt < pdata->channel_num)
+		goto eirqres;
+
 	/* Create DMA Channel */
-	for (cnt = 0 ; cnt < MAX_DMA_CHANNELS ; cnt++) {
-		err = sh_dmae_chan_probe(shdev, cnt);
+	for (i = 0; i < pdata->channel_num; i++) {
+		err = sh_dmae_chan_probe(shdev, i, chan_irq[i], chan_flag[i]);
 		if (err)
 			goto chan_probe_err;
 	}
 
+	pm_runtime_put(&pdev->dev);
+
 	platform_set_drvdata(pdev, shdev);
 	dma_async_device_register(&shdev->common);
 
@@ -988,13 +1106,24 @@
 
 chan_probe_err:
 	sh_dmae_chan_remove(shdev);
-
+eirqres:
+#if defined(CONFIG_CPU_SH4)
+	free_irq(errirq, shdev);
 eirq_err:
-	for (ecnt-- ; ecnt >= 0; ecnt--)
-		free_irq(eirq[ecnt], shdev);
-
+#endif
 rst_err:
+	pm_runtime_put(&pdev->dev);
+	if (dmars)
+		iounmap(shdev->dmars);
+emapdmars:
+	iounmap(shdev->chan_reg);
+emapchan:
 	kfree(shdev);
+ealloc:
+	if (dmars)
+		release_mem_region(dmars->start, resource_size(dmars));
+ermrdmars:
+	release_mem_region(chan->start, resource_size(chan));
 
 	return err;
 }
@@ -1002,36 +1131,39 @@
 static int __exit sh_dmae_remove(struct platform_device *pdev)
 {
 	struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
+	struct resource *res;
+	int errirq = platform_get_irq(pdev, 0);
 
 	dma_async_device_unregister(&shdev->common);
 
-	if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
-		free_irq(DMTE0_IRQ, shdev);
-#if defined(DMTE6_IRQ)
-		free_irq(DMTE6_IRQ, shdev);
-#endif
-	}
+	if (errirq > 0)
+		free_irq(errirq, shdev);
 
 	/* channel data remove */
 	sh_dmae_chan_remove(shdev);
 
-	if (!(shdev->pdata.mode & SHDMA_MIX_IRQ)) {
-		free_irq(DMAE0_IRQ, shdev);
-#if defined(DMAE1_IRQ)
-		free_irq(DMAE1_IRQ, shdev);
-#endif
-	}
+	pm_runtime_disable(&pdev->dev);
+
+	if (shdev->dmars)
+		iounmap(shdev->dmars);
+	iounmap(shdev->chan_reg);
+
 	kfree(shdev);
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res)
+		release_mem_region(res->start, resource_size(res));
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res)
+		release_mem_region(res->start, resource_size(res));
+
 	return 0;
 }
 
 static void sh_dmae_shutdown(struct platform_device *pdev)
 {
 	struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
-	sh_dmae_ctl_stop(0);
-	if (shdev->pdata.mode & SHDMA_DMAOR1)
-		sh_dmae_ctl_stop(1);
+	sh_dmae_ctl_stop(shdev);
 }
 
 static struct platform_driver sh_dmae_driver = {
diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h
index 7e227f3..153609a 100644
--- a/drivers/dma/shdma.h
+++ b/drivers/dma/shdma.h
@@ -17,24 +17,10 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 
+#include <asm/dmaengine.h>
+
 #define SH_DMA_TCR_MAX 0x00FFFFFF	/* 16MB */
 
-struct sh_dmae_regs {
-	u32 sar; /* SAR / source address */
-	u32 dar; /* DAR / destination address */
-	u32 tcr; /* TCR / transfer count */
-};
-
-struct sh_desc {
-	struct sh_dmae_regs hw;
-	struct list_head node;
-	struct dma_async_tx_descriptor async_tx;
-	enum dma_data_direction direction;
-	dma_cookie_t cookie;
-	int chunks;
-	int mark;
-};
-
 struct device;
 
 struct sh_dmae_chan {
@@ -47,14 +33,18 @@
 	struct tasklet_struct tasklet;	/* Tasklet */
 	int descs_allocated;		/* desc count */
 	int xmit_shift;			/* log_2(bytes_per_xfer) */
+	int irq;
 	int id;				/* Raw id of this channel */
+	u32 __iomem *base;
 	char dev_id[16];		/* unique name per DMAC of channel */
 };
 
 struct sh_dmae_device {
 	struct dma_device common;
-	struct sh_dmae_chan *chan[MAX_DMA_CHANNELS];
-	struct sh_dmae_pdata pdata;
+	struct sh_dmae_chan *chan[SH_DMAC_MAX_CHANNELS];
+	struct sh_dmae_pdata *pdata;
+	u32 __iomem *chan_reg;
+	u16 __iomem *dmars;
 };
 
 #define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common)
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 3391e67..cf17dbb 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -13,7 +13,7 @@
 static int ecc_enable_override;
 module_param(ecc_enable_override, int, 0644);
 
-static struct msr *msrs;
+static struct msr __percpu *msrs;
 
 /* Lookup table for all possible MC control instances */
 struct amd64_pvt;
@@ -2553,14 +2553,14 @@
 
 		if (on) {
 			if (reg->l & K8_MSR_MCGCTL_NBE)
-				pvt->flags.ecc_report = 1;
+				pvt->flags.nb_mce_enable = 1;
 
 			reg->l |= K8_MSR_MCGCTL_NBE;
 		} else {
 			/*
-			 * Turn off ECC reporting only when it was off before
+			 * Turn off NB MCE reporting only when it was off before
 			 */
-			if (!pvt->flags.ecc_report)
+			if (!pvt->flags.nb_mce_enable)
 				reg->l &= ~K8_MSR_MCGCTL_NBE;
 		}
 	}
@@ -2571,22 +2571,11 @@
 	return 0;
 }
 
-/*
- * Only if 'ecc_enable_override' is set AND BIOS had ECC disabled, do "we"
- * enable it.
- */
 static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
 	u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
 
-	if (!ecc_enable_override)
-		return;
-
-	amd64_printk(KERN_WARNING,
-		"'ecc_enable_override' parameter is active, "
-		"Enabling AMD ECC hardware now: CAUTION\n");
-
 	amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCTL, &value);
 
 	/* turn on UECCn and CECCEn bits */
@@ -2611,6 +2600,8 @@
 			"This node reports that DRAM ECC is "
 			"currently Disabled; ENABLING now\n");
 
+		pvt->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);
@@ -2625,7 +2616,10 @@
 			amd64_printk(KERN_DEBUG,
 				"Hardware accepted DRAM ECC Enable\n");
 		}
+	} else {
+		pvt->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");
@@ -2644,12 +2638,18 @@
 	value &= ~mask;
 	value |= pvt->old_nbctl;
 
-	/* restore the NB Enable MCGCTL bit */
 	pci_write_config_dword(pvt->misc_f3_ctl, 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);
+		value &= ~K8_NBCFG_ECC_ENABLE;
+		pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value);
+	}
+
+	/* restore the NB Enable MCGCTL bit */
 	if (amd64_toggle_ecc_err_reporting(pvt, OFF))
-		amd64_printk(KERN_WARNING, "Error restoring ECC reporting over "
-					   "MCGCTL!\n");
+		amd64_printk(KERN_WARNING, "Error restoring NB MCGCTL settings!\n");
 }
 
 /*
@@ -2690,8 +2690,9 @@
 		if (!ecc_enable_override) {
 			amd64_printk(KERN_NOTICE, "%s", ecc_msg);
 			return -ENODEV;
+		} else {
+			amd64_printk(KERN_WARNING, "Forcing ECC checking on!\n");
 		}
-		ecc_enable_override = 0;
 	}
 
 	return 0;
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 41bc561..0d4bf56 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -487,7 +487,8 @@
 	/* misc settings */
 	struct flags {
 		unsigned long cf8_extcfg:1;
-		unsigned long ecc_report:1;
+		unsigned long nb_mce_enable:1;
+		unsigned long nb_ecc_prev:1;
 	} flags;
 };
 
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index d205d49..243e9aa 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -75,6 +75,14 @@
 #define E752X_NR_CSROWS		8	/* number of csrows */
 
 /* E752X register addresses - device 0 function 0 */
+#define E752X_MCHSCRB		0x52	/* Memory Scrub register (16b) */
+					/*
+					 * 6:5     Scrub Completion Count
+					 * 3:2     Scrub Rate (i3100 only)
+					 *      01=fast 10=normal
+					 * 1:0     Scrub Mode enable
+					 *      00=off 10=on
+					 */
 #define E752X_DRB		0x60	/* DRAM row boundary register (8b) */
 #define E752X_DRA		0x70	/* DRAM row attribute register (8b) */
 					/*
@@ -240,6 +248,41 @@
 		.ctl_name = "3100"},
 };
 
+/* Valid scrub rates for the e752x/3100 hardware memory scrubber. We
+ * map the scrubbing bandwidth to a hardware register value. The 'set'
+ * operation finds the 'matching or higher value'.  Note that scrubbing
+ * on the e752x can only be enabled/disabled.  The 3100 supports
+ * a normal and fast mode.
+ */
+
+#define SDRATE_EOT 0xFFFFFFFF
+
+struct scrubrate {
+	u32 bandwidth;	/* bandwidth consumed by scrubbing in bytes/sec */
+	u16 scrubval;	/* register value for scrub rate */
+};
+
+/* Rate below assumes same performance as i3100 using PC3200 DDR2 in
+ * normal mode.  e752x bridges don't support choosing normal or fast mode,
+ * so the scrubbing bandwidth value isn't all that important - scrubbing is
+ * either on or off.
+ */
+static const struct scrubrate scrubrates_e752x[] = {
+	{0,		0x00},	/* Scrubbing Off */
+	{500000,	0x02},	/* Scrubbing On */
+	{SDRATE_EOT,	0x00}	/* End of Table */
+};
+
+/* Fast mode: 2 GByte PC3200 DDR2 scrubbed in 33s = 63161283 bytes/s
+ * Normal mode: 125 (32000 / 256) times slower than fast mode.
+ */
+static const struct scrubrate scrubrates_i3100[] = {
+	{0,		0x00},	/* Scrubbing Off */
+	{500000,	0x0a},	/* Normal mode - 32k clocks */
+	{62500000,	0x06},	/* Fast mode - 256 clocks */
+	{SDRATE_EOT,	0x00}	/* End of Table */
+};
+
 static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
 				unsigned long page)
 {
@@ -915,6 +958,68 @@
 	e752x_process_error_info(mci, &info, 1);
 }
 
+/* Program byte/sec bandwidth scrub rate to hardware */
+static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *new_bw)
+{
+	const struct scrubrate *scrubrates;
+	struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+	struct pci_dev *pdev = pvt->dev_d0f0;
+	int i;
+
+	if (pvt->dev_info->ctl_dev == PCI_DEVICE_ID_INTEL_3100_0)
+		scrubrates = scrubrates_i3100;
+	else
+		scrubrates = scrubrates_e752x;
+
+	/* Translate the desired scrub rate to a e752x/3100 register value.
+	 * Search for the bandwidth that is equal or greater than the
+	 * desired rate and program the cooresponding register value.
+	 */
+	for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++)
+		if (scrubrates[i].bandwidth >= *new_bw)
+			break;
+
+	if (scrubrates[i].bandwidth == SDRATE_EOT)
+		return -1;
+
+	pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval);
+
+	return 0;
+}
+
+/* Convert current scrub rate value into byte/sec bandwidth */
+static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw)
+{
+	const struct scrubrate *scrubrates;
+	struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+	struct pci_dev *pdev = pvt->dev_d0f0;
+	u16 scrubval;
+	int i;
+
+	if (pvt->dev_info->ctl_dev == PCI_DEVICE_ID_INTEL_3100_0)
+		scrubrates = scrubrates_i3100;
+	else
+		scrubrates = scrubrates_e752x;
+
+	/* Find the bandwidth matching the memory scrubber configuration */
+	pci_read_config_word(pdev, E752X_MCHSCRB, &scrubval);
+	scrubval = scrubval & 0x0f;
+
+	for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++)
+		if (scrubrates[i].scrubval == scrubval)
+			break;
+
+	if (scrubrates[i].bandwidth == SDRATE_EOT) {
+		e752x_printk(KERN_WARNING,
+			"Invalid sdram scrub control value: 0x%x\n", scrubval);
+		return -1;
+	}
+
+	*bw = scrubrates[i].bandwidth;
+
+	return 0;
+}
+
 /* Return 1 if dual channel mode is active.  Else return 0. */
 static inline int dual_channel_active(u16 ddrcsr)
 {
@@ -1073,10 +1178,7 @@
 
 /* Setup system bus parity mask register.
  * Sysbus parity supported on:
- *   e7320/e7520/e7525 + Xeon
- *   i3100 + Xeon/Celeron
- * Sysbus parity not supported on:
- *   i3100 + Pentium M/Celeron M/Core Duo/Core2 Duo
+ * e7320/e7520/e7525 + Xeon
  */
 static void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt)
 {
@@ -1087,10 +1189,7 @@
 	/* Allow module parameter override, else see if CPU supports parity */
 	if (sysbus_parity != -1) {
 		enable = sysbus_parity;
-	} else if (cpu_id[0] &&
-		   ((strstr(cpu_id, "Pentium") && strstr(cpu_id, " M ")) ||
-		    (strstr(cpu_id, "Celeron") && strstr(cpu_id, " M ")) ||
-		    (strstr(cpu_id, "Core") && strstr(cpu_id, "Duo")))) {
+	} else if (cpu_id[0] && !strstr(cpu_id, "Xeon")) {
 		e752x_printk(KERN_INFO, "System Bus Parity not "
 			     "supported by CPU, disabling\n");
 		enable = 0;
@@ -1187,6 +1286,8 @@
 	mci->dev_name = pci_name(pdev);
 	mci->edac_check = e752x_check;
 	mci->ctl_page_to_phys = ctl_page_to_phys;
+	mci->set_sdram_scrub_rate = set_sdram_scrub_rate;
+	mci->get_sdram_scrub_rate = get_sdram_scrub_rate;
 
 	/* set the map type.  1 = normal, 0 = reversed
 	 * Must be set before e752x_init_csrows in case csrow mapping
diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
index 5376457..5fdedbc 100644
--- a/drivers/edac/edac_device_sysfs.c
+++ b/drivers/edac/edac_device_sysfs.c
@@ -137,7 +137,7 @@
 }
 
 /* edac_dev file operations for an 'ctl_info' */
-static struct sysfs_ops device_ctl_info_ops = {
+static const struct sysfs_ops device_ctl_info_ops = {
 	.show = edac_dev_ctl_info_show,
 	.store = edac_dev_ctl_info_store
 };
@@ -373,7 +373,7 @@
 }
 
 /* edac_dev file operations for an 'instance' */
-static struct sysfs_ops device_instance_ops = {
+static const struct sysfs_ops device_instance_ops = {
 	.show = edac_dev_instance_show,
 	.store = edac_dev_instance_store
 };
@@ -476,7 +476,7 @@
 }
 
 /* edac_dev file operations for a 'block' */
-static struct sysfs_ops device_block_ops = {
+static const struct sysfs_ops device_block_ops = {
 	.show = edac_dev_block_show,
 	.store = edac_dev_block_store
 };
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index e1d4ce0..88840e9 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -245,7 +245,7 @@
 	return -EIO;
 }
 
-static struct sysfs_ops csrowfs_ops = {
+static const struct sysfs_ops csrowfs_ops = {
 	.show = csrowdev_show,
 	.store = csrowdev_store
 };
@@ -575,7 +575,7 @@
 }
 
 /* Intermediate show/store table */
-static struct sysfs_ops mci_ops = {
+static const struct sysfs_ops mci_ops = {
 	.show = mcidev_show,
 	.store = mcidev_store
 };
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index fb60a87..bef94e3 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -121,7 +121,7 @@
 }
 
 /* fs_ops table */
-static struct sysfs_ops pci_instance_ops = {
+static const struct sysfs_ops pci_instance_ops = {
 	.show = edac_pci_instance_show,
 	.store = edac_pci_instance_store
 };
@@ -261,7 +261,7 @@
 	return -EIO;
 }
 
-static struct sysfs_ops edac_pci_sysfs_ops = {
+static const struct sysfs_ops edac_pci_sysfs_ops = {
 	.show = edac_pci_dev_show,
 	.store = edac_pci_dev_store
 };
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index ecd5928..94cac0a 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -239,16 +239,15 @@
 	/* we only need the error registers */
 	r.start += 0xe00;
 
-	if (!devm_request_mem_region(&op->dev, r.start,
-					r.end - r.start + 1, pdata->name)) {
+	if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
+					pdata->name)) {
 		printk(KERN_ERR "%s: Error while requesting mem region\n",
 		       __func__);
 		res = -EBUSY;
 		goto err;
 	}
 
-	pdata->pci_vbase = devm_ioremap(&op->dev, r.start,
-					r.end - r.start + 1);
+	pdata->pci_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
 	if (!pdata->pci_vbase) {
 		printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
 		res = -ENOMEM;
@@ -668,15 +667,125 @@
 
 /**************************** MC Err device ***************************/
 
+/*
+ * Taken from table 8-55 in the MPC8641 User's Manual and/or 9-61 in the
+ * MPC8572 User's Manual.  Each line represents a syndrome bit column as a
+ * 64-bit value, but split into an upper and lower 32-bit chunk.  The labels
+ * below correspond to Freescale's manuals.
+ */
+static unsigned int ecc_table[16] = {
+	/* MSB           LSB */
+	/* [0:31]    [32:63] */
+	0xf00fe11e, 0xc33c0ff7,	/* Syndrome bit 7 */
+	0x00ff00ff, 0x00fff0ff,
+	0x0f0f0f0f, 0x0f0fff00,
+	0x11113333, 0x7777000f,
+	0x22224444, 0x8888222f,
+	0x44448888, 0xffff4441,
+	0x8888ffff, 0x11118882,
+	0xffff1111, 0x22221114,	/* Syndrome bit 0 */
+};
+
+/*
+ * Calculate the correct ECC value for a 64-bit value specified by high:low
+ */
+static u8 calculate_ecc(u32 high, u32 low)
+{
+	u32 mask_low;
+	u32 mask_high;
+	int bit_cnt;
+	u8 ecc = 0;
+	int i;
+	int j;
+
+	for (i = 0; i < 8; i++) {
+		mask_high = ecc_table[i * 2];
+		mask_low = ecc_table[i * 2 + 1];
+		bit_cnt = 0;
+
+		for (j = 0; j < 32; j++) {
+			if ((mask_high >> j) & 1)
+				bit_cnt ^= (high >> j) & 1;
+			if ((mask_low >> j) & 1)
+				bit_cnt ^= (low >> j) & 1;
+		}
+
+		ecc |= bit_cnt << i;
+	}
+
+	return ecc;
+}
+
+/*
+ * Create the syndrome code which is generated if the data line specified by
+ * 'bit' failed.  Eg generate an 8-bit codes seen in Table 8-55 in the MPC8641
+ * User's Manual and 9-61 in the MPC8572 User's Manual.
+ */
+static u8 syndrome_from_bit(unsigned int bit) {
+	int i;
+	u8 syndrome = 0;
+
+	/*
+	 * Cycle through the upper or lower 32-bit portion of each value in
+	 * ecc_table depending on if 'bit' is in the upper or lower half of
+	 * 64-bit data.
+	 */
+	for (i = bit < 32; i < 16; i += 2)
+		syndrome |= ((ecc_table[i] >> (bit % 32)) & 1) << (i / 2);
+
+	return syndrome;
+}
+
+/*
+ * Decode data and ecc syndrome to determine what went wrong
+ * Note: This can only decode single-bit errors
+ */
+static void sbe_ecc_decode(u32 cap_high, u32 cap_low, u32 cap_ecc,
+		       int *bad_data_bit, int *bad_ecc_bit)
+{
+	int i;
+	u8 syndrome;
+
+	*bad_data_bit = -1;
+	*bad_ecc_bit = -1;
+
+	/*
+	 * Calculate the ECC of the captured data and XOR it with the captured
+	 * ECC to find an ECC syndrome value we can search for
+	 */
+	syndrome = calculate_ecc(cap_high, cap_low) ^ cap_ecc;
+
+	/* Check if a data line is stuck... */
+	for (i = 0; i < 64; i++) {
+		if (syndrome == syndrome_from_bit(i)) {
+			*bad_data_bit = i;
+			return;
+		}
+	}
+
+	/* If data is correct, check ECC bits for errors... */
+	for (i = 0; i < 8; i++) {
+		if ((syndrome >> i) & 0x1) {
+			*bad_ecc_bit = i;
+			return;
+		}
+	}
+}
+
 static void mpc85xx_mc_check(struct mem_ctl_info *mci)
 {
 	struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
 	struct csrow_info *csrow;
+	u32 bus_width;
 	u32 err_detect;
 	u32 syndrome;
 	u32 err_addr;
 	u32 pfn;
 	int row_index;
+	u32 cap_high;
+	u32 cap_low;
+	int bad_data_bit;
+	int bad_ecc_bit;
 
 	err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT);
 	if (!err_detect)
@@ -692,6 +801,15 @@
 	}
 
 	syndrome = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ECC);
+
+	/* Mask off appropriate bits of syndrome based on bus width */
+	bus_width = (in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG) &
+			DSC_DBW_MASK) ? 32 : 64;
+	if (bus_width == 64)
+		syndrome &= 0xff;
+	else
+		syndrome &= 0xffff;
+
 	err_addr = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ADDRESS);
 	pfn = err_addr >> PAGE_SHIFT;
 
@@ -701,14 +819,35 @@
 			break;
 	}
 
-	mpc85xx_mc_printk(mci, KERN_ERR, "Capture Data High: %#8.8x\n",
-			  in_be32(pdata->mc_vbase +
-				  MPC85XX_MC_CAPTURE_DATA_HI));
-	mpc85xx_mc_printk(mci, KERN_ERR, "Capture Data Low: %#8.8x\n",
-			  in_be32(pdata->mc_vbase +
-				  MPC85XX_MC_CAPTURE_DATA_LO));
-	mpc85xx_mc_printk(mci, KERN_ERR, "syndrome: %#8.8x\n", syndrome);
-	mpc85xx_mc_printk(mci, KERN_ERR, "err addr: %#8.8x\n", err_addr);
+	cap_high = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_HI);
+	cap_low = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_LO);
+
+	/*
+	 * Analyze single-bit errors on 64-bit wide buses
+	 * TODO: Add support for 32-bit wide buses
+	 */
+	if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) {
+		sbe_ecc_decode(cap_high, cap_low, syndrome,
+				&bad_data_bit, &bad_ecc_bit);
+
+		if (bad_data_bit != -1)
+			mpc85xx_mc_printk(mci, KERN_ERR,
+				"Faulty Data bit: %d\n", bad_data_bit);
+		if (bad_ecc_bit != -1)
+			mpc85xx_mc_printk(mci, KERN_ERR,
+				"Faulty ECC bit: %d\n", bad_ecc_bit);
+
+		mpc85xx_mc_printk(mci, KERN_ERR,
+			"Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n",
+			cap_high ^ (1 << (bad_data_bit - 32)),
+			cap_low ^ (1 << bad_data_bit),
+			syndrome ^ (1 << bad_ecc_bit));
+	}
+
+	mpc85xx_mc_printk(mci, KERN_ERR,
+			"Captured Data / ECC:\t%#8.8x_%08x / %#2.2x\n",
+			cap_high, cap_low, syndrome);
+	mpc85xx_mc_printk(mci, KERN_ERR, "Err addr: %#8.8x\n", err_addr);
 	mpc85xx_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn);
 
 	/* we are out of range */
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h
index 52432ee..cb24df8 100644
--- a/drivers/edac/mpc85xx_edac.h
+++ b/drivers/edac/mpc85xx_edac.h
@@ -48,6 +48,9 @@
 #define DSC_MEM_EN	0x80000000
 #define DSC_ECC_EN	0x20000000
 #define DSC_RD_EN	0x10000000
+#define DSC_DBW_MASK	0x00180000
+#define DSC_DBW_32	0x00080000
+#define DSC_DBW_64	0x00000000
 
 #define DSC_SDTYPE_MASK		0x07000000
 
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 66958b3..806c77b 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -39,10 +39,10 @@
 static int disable_dev[EISA_MAX_FORCED_DEV];
 static unsigned int disable_dev_count;
 
-static int is_forced_dev (int *forced_tab,
-			  int forced_count,
-			  struct eisa_root_device *root,
-			  struct eisa_device *edev)
+static int is_forced_dev(int *forced_tab,
+			 int forced_count,
+			 struct eisa_root_device *root,
+			 struct eisa_device *edev)
 {
 	int i, x;
 
@@ -55,21 +55,21 @@
 	return 0;
 }
 
-static void __init eisa_name_device (struct eisa_device *edev)
+static void __init eisa_name_device(struct eisa_device *edev)
 {
 #ifdef CONFIG_EISA_NAMES
 	int i;
 	for (i = 0; i < EISA_INFOS; i++) {
-		if (!strcmp (edev->id.sig, eisa_table[i].id.sig)) {
-			strlcpy (edev->pretty_name,
-				 eisa_table[i].name,
-				 sizeof(edev->pretty_name));
+		if (!strcmp(edev->id.sig, eisa_table[i].id.sig)) {
+			strlcpy(edev->pretty_name,
+				eisa_table[i].name,
+				sizeof(edev->pretty_name));
 			return;
 		}
 	}
 
 	/* No name was found */
-	sprintf (edev->pretty_name, "EISA device %.7s", edev->id.sig);
+	sprintf(edev->pretty_name, "EISA device %.7s", edev->id.sig);
 #endif
 }
 
@@ -91,7 +91,7 @@
 		 */
 		outb(0x80 + i, addr);
 #endif
-		sig[i] = inb (addr + i);
+		sig[i] = inb(addr + i);
 
 		if (!i && (sig[0] & 0x80))
 			return NULL;
@@ -106,17 +106,17 @@
         return sig_str;
 }
 
-static int eisa_bus_match (struct device *dev, struct device_driver *drv)
+static int eisa_bus_match(struct device *dev, struct device_driver *drv)
 {
-	struct eisa_device *edev = to_eisa_device (dev);
-	struct eisa_driver *edrv = to_eisa_driver (drv);
+	struct eisa_device *edev = to_eisa_device(dev);
+	struct eisa_driver *edrv = to_eisa_driver(drv);
 	const struct eisa_device_id *eids = edrv->id_table;
 
 	if (!eids)
 		return 0;
 
-	while (strlen (eids->sig)) {
-		if (!strcmp (eids->sig, edev->id.sig) &&
+	while (strlen(eids->sig)) {
+		if (!strcmp(eids->sig, edev->id.sig) &&
 		    edev->state & EISA_CONFIG_ENABLED) {
 			edev->id.driver_data = eids->driver_data;
 			return 1;
@@ -141,61 +141,71 @@
 	.match = eisa_bus_match,
 	.uevent = eisa_bus_uevent,
 };
+EXPORT_SYMBOL(eisa_bus_type);
 
-int eisa_driver_register (struct eisa_driver *edrv)
+int eisa_driver_register(struct eisa_driver *edrv)
 {
 	edrv->driver.bus = &eisa_bus_type;
-	return driver_register (&edrv->driver);
+	return driver_register(&edrv->driver);
 }
+EXPORT_SYMBOL(eisa_driver_register);
 
-void eisa_driver_unregister (struct eisa_driver *edrv)
+void eisa_driver_unregister(struct eisa_driver *edrv)
 {
-	driver_unregister (&edrv->driver);
+	driver_unregister(&edrv->driver);
 }
+EXPORT_SYMBOL(eisa_driver_unregister);
 
-static ssize_t eisa_show_sig (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t eisa_show_sig(struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
-        struct eisa_device *edev = to_eisa_device (dev);
-        return sprintf (buf,"%s\n", edev->id.sig);
+	struct eisa_device *edev = to_eisa_device(dev);
+	return sprintf(buf, "%s\n", edev->id.sig);
 }
 
 static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
 
-static ssize_t eisa_show_state (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t eisa_show_state(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
 {
-        struct eisa_device *edev = to_eisa_device (dev);
-        return sprintf (buf,"%d\n", edev->state & EISA_CONFIG_ENABLED);
+	struct eisa_device *edev = to_eisa_device(dev);
+	return sprintf(buf, "%d\n", edev->state & EISA_CONFIG_ENABLED);
 }
 
 static DEVICE_ATTR(enabled, S_IRUGO, eisa_show_state, NULL);
 
-static ssize_t eisa_show_modalias (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t eisa_show_modalias(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
 {
-        struct eisa_device *edev = to_eisa_device (dev);
-        return sprintf (buf, EISA_DEVICE_MODALIAS_FMT "\n", edev->id.sig);
+	struct eisa_device *edev = to_eisa_device(dev);
+	return sprintf(buf, EISA_DEVICE_MODALIAS_FMT "\n", edev->id.sig);
 }
 
 static DEVICE_ATTR(modalias, S_IRUGO, eisa_show_modalias, NULL);
 
-static int __init eisa_init_device (struct eisa_root_device *root,
-				    struct eisa_device *edev,
-				    int slot)
+static int __init eisa_init_device(struct eisa_root_device *root,
+				   struct eisa_device *edev,
+				   int slot)
 {
 	char *sig;
-        unsigned long sig_addr;
+	unsigned long sig_addr;
 	int i;
 
-	sig_addr = SLOT_ADDRESS (root, slot) + EISA_VENDOR_ID_OFFSET;
+	sig_addr = SLOT_ADDRESS(root, slot) + EISA_VENDOR_ID_OFFSET;
 
-	if (!(sig = decode_eisa_sig (sig_addr)))
+	sig = decode_eisa_sig(sig_addr);
+	if (!sig)
 		return -1;	/* No EISA device here */
 	
-	memcpy (edev->id.sig, sig, EISA_SIG_LEN);
+	memcpy(edev->id.sig, sig, EISA_SIG_LEN);
 	edev->slot = slot;
-	edev->state = inb (SLOT_ADDRESS (root, slot) + EISA_CONFIG_OFFSET) & EISA_CONFIG_ENABLED;
-	edev->base_addr = SLOT_ADDRESS (root, slot);
+	edev->state = inb(SLOT_ADDRESS(root, slot) + EISA_CONFIG_OFFSET)
+		      & EISA_CONFIG_ENABLED;
+	edev->base_addr = SLOT_ADDRESS(root, slot);
 	edev->dma_mask = root->dma_mask; /* Default DMA mask */
-	eisa_name_device (edev);
+	eisa_name_device(edev);
 	edev->dev.parent = root->dev;
 	edev->dev.bus = &eisa_bus_type;
 	edev->dev.dma_mask = &edev->dma_mask;
@@ -210,42 +220,45 @@
 #endif
 	}
 
-	if (is_forced_dev (enable_dev, enable_dev_count, root, edev))
+	if (is_forced_dev(enable_dev, enable_dev_count, root, edev))
 		edev->state = EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED;
 	
-	if (is_forced_dev (disable_dev, disable_dev_count, root, edev))
+	if (is_forced_dev(disable_dev, disable_dev_count, root, edev))
 		edev->state = EISA_CONFIG_FORCED;
 
 	return 0;
 }
 
-static int __init eisa_register_device (struct eisa_device *edev)
+static int __init eisa_register_device(struct eisa_device *edev)
 {
-	int rc = device_register (&edev->dev);
+	int rc = device_register(&edev->dev);
 	if (rc)
 		return rc;
 
-	rc = device_create_file (&edev->dev, &dev_attr_signature);
-	if (rc) goto err_devreg;
-	rc = device_create_file (&edev->dev, &dev_attr_enabled);
-	if (rc) goto err_sig;
-	rc = device_create_file (&edev->dev, &dev_attr_modalias);
-	if (rc) goto err_enab;
+	rc = device_create_file(&edev->dev, &dev_attr_signature);
+	if (rc)
+		goto err_devreg;
+	rc = device_create_file(&edev->dev, &dev_attr_enabled);
+	if (rc)
+		goto err_sig;
+	rc = device_create_file(&edev->dev, &dev_attr_modalias);
+	if (rc)
+		goto err_enab;
 
 	return 0;
 
 err_enab:
-	device_remove_file (&edev->dev, &dev_attr_enabled);
+	device_remove_file(&edev->dev, &dev_attr_enabled);
 err_sig:
-	device_remove_file (&edev->dev, &dev_attr_signature);
+	device_remove_file(&edev->dev, &dev_attr_signature);
 err_devreg:
 	device_unregister(&edev->dev);
 	return rc;
 }
 
-static int __init eisa_request_resources (struct eisa_root_device *root,
-					  struct eisa_device *edev,
-					  int slot)
+static int __init eisa_request_resources(struct eisa_root_device *root,
+					 struct eisa_device *edev,
+					 int slot)
 {
 	int i;
 
@@ -263,17 +276,19 @@
 		
 		if (slot) {
 			edev->res[i].name  = NULL;
-			edev->res[i].start = SLOT_ADDRESS (root, slot) + (i * 0x400);
+			edev->res[i].start = SLOT_ADDRESS(root, slot)
+					     + (i * 0x400);
 			edev->res[i].end   = edev->res[i].start + 0xff;
 			edev->res[i].flags = IORESOURCE_IO;
 		} else {
 			edev->res[i].name  = NULL;
-			edev->res[i].start = SLOT_ADDRESS (root, slot) + EISA_VENDOR_ID_OFFSET;
+			edev->res[i].start = SLOT_ADDRESS(root, slot)
+					     + EISA_VENDOR_ID_OFFSET;
 			edev->res[i].end   = edev->res[i].start + 3;
 			edev->res[i].flags = IORESOURCE_BUSY;
 		}
 
-		if (request_resource (root->res, &edev->res[i]))
+		if (request_resource(root->res, &edev->res[i]))
 			goto failed;
 	}
 
@@ -281,99 +296,100 @@
 	
  failed:
 	while (--i >= 0)
-		release_resource (&edev->res[i]);
+		release_resource(&edev->res[i]);
 
 	return -1;
 }
 
-static void __init eisa_release_resources (struct eisa_device *edev)
+static void __init eisa_release_resources(struct eisa_device *edev)
 {
 	int i;
 
 	for (i = 0; i < EISA_MAX_RESOURCES; i++)
 		if (edev->res[i].start || edev->res[i].end)
-			release_resource (&edev->res[i]);
+			release_resource(&edev->res[i]);
 }
 
-static int __init eisa_probe (struct eisa_root_device *root)
+static int __init eisa_probe(struct eisa_root_device *root)
 {
         int i, c;
 	struct eisa_device *edev;
 
-        printk (KERN_INFO "EISA: Probing bus %d at %s\n",
-		root->bus_nr, dev_name(root->dev));
+	printk(KERN_INFO "EISA: Probing bus %d at %s\n",
+	       root->bus_nr, dev_name(root->dev));
 
 	/* First try to get hold of slot 0. If there is no device
 	 * here, simply fail, unless root->force_probe is set. */
 	
-	if (!(edev = kzalloc (sizeof (*edev), GFP_KERNEL))) {
-		printk (KERN_ERR "EISA: Couldn't allocate mainboard slot\n");
+	edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+	if (!edev) {
+		printk(KERN_ERR "EISA: Couldn't allocate mainboard slot\n");
 		return -ENOMEM;
 	}
 		
-	if (eisa_request_resources (root, edev, 0)) {
-		printk (KERN_WARNING \
-			"EISA: Cannot allocate resource for mainboard\n");
-		kfree (edev);
+	if (eisa_request_resources(root, edev, 0)) {
+		printk(KERN_WARNING \
+		       "EISA: Cannot allocate resource for mainboard\n");
+		kfree(edev);
 		if (!root->force_probe)
 			return -EBUSY;
 		goto force_probe;
 	}
 
-	if (eisa_init_device (root, edev, 0)) {
-		eisa_release_resources (edev);
-		kfree (edev);
+	if (eisa_init_device(root, edev, 0)) {
+		eisa_release_resources(edev);
+		kfree(edev);
 		if (!root->force_probe)
 			return -ENODEV;
 		goto force_probe;
 	}
 
-	printk (KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig);
+	printk(KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig);
 
-	if (eisa_register_device (edev)) {
-		printk (KERN_ERR "EISA: Failed to register %s\n",
-			edev->id.sig);
-		eisa_release_resources (edev);
-		kfree (edev);
+	if (eisa_register_device(edev)) {
+		printk(KERN_ERR "EISA: Failed to register %s\n",
+		       edev->id.sig);
+		eisa_release_resources(edev);
+		kfree(edev);
 	}
 	
  force_probe:
 	
         for (c = 0, i = 1; i <= root->slots; i++) {
-		if (!(edev = kzalloc (sizeof (*edev), GFP_KERNEL))) {
-			printk (KERN_ERR "EISA: Out of memory for slot %d\n",
-				i);
+		edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+		if (!edev) {
+			printk(KERN_ERR "EISA: Out of memory for slot %d\n", i);
 			continue;
 		}
 
-		if (eisa_request_resources (root, edev, i)) {
-			printk (KERN_WARNING \
-				"Cannot allocate resource for EISA slot %d\n",
-				i);
-			kfree (edev);
+		if (eisa_request_resources(root, edev, i)) {
+			printk(KERN_WARNING \
+			       "Cannot allocate resource for EISA slot %d\n",
+			       i);
+			kfree(edev);
 			continue;
 		}
 
-                if (eisa_init_device (root, edev, i)) {
-			eisa_release_resources (edev);
-			kfree (edev);
+		if (eisa_init_device(root, edev, i)) {
+			eisa_release_resources(edev);
+			kfree(edev);
 			continue;
 		}
 		
-		printk (KERN_INFO "EISA: slot %d : %s detected",
-			i, edev->id.sig);
+		printk(KERN_INFO "EISA: slot %d : %s detected",
+		       i, edev->id.sig);
 			
 		switch (edev->state) {
 		case EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED:
-			printk (" (forced enabled)");
+			printk(" (forced enabled)");
 			break;
 
 		case EISA_CONFIG_FORCED:
-			printk (" (forced disabled)");
+			printk(" (forced disabled)");
 			break;
 
 		case 0:
-			printk (" (disabled)");
+			printk(" (disabled)");
 			break;
 		}
 			
@@ -381,15 +397,15 @@
 
 		c++;
 
-		if (eisa_register_device (edev)) {
-			printk (KERN_ERR "EISA: Failed to register %s\n",
-				edev->id.sig);
-			eisa_release_resources (edev);
-			kfree (edev);
+		if (eisa_register_device(edev)) {
+			printk(KERN_ERR "EISA: Failed to register %s\n",
+			       edev->id.sig);
+			eisa_release_resources(edev);
+			kfree(edev);
 		}
         }
 
-        printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s");
+	printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s");
 
 	return 0;
 }
@@ -403,7 +419,7 @@
 
 static int eisa_bus_count;
 
-int __init eisa_root_register (struct eisa_root_device *root)
+int __init eisa_root_register(struct eisa_root_device *root)
 {
 	int err;
 
@@ -417,35 +433,35 @@
 	root->eisa_root_res.end   = root->res->end;
 	root->eisa_root_res.flags = IORESOURCE_BUSY;
 
-	if ((err = request_resource (&eisa_root_res, &root->eisa_root_res)))
+	err = request_resource(&eisa_root_res, &root->eisa_root_res);
+	if (err)
 		return err;
 	
 	root->bus_nr = eisa_bus_count++;
 
-	if ((err = eisa_probe (root)))
-		release_resource (&root->eisa_root_res);
+	err = eisa_probe(root);
+	if (err)
+		release_resource(&root->eisa_root_res);
 
 	return err;
 }
 
-static int __init eisa_init (void)
+static int __init eisa_init(void)
 {
 	int r;
 	
-	if ((r = bus_register (&eisa_bus_type)))
+	r = bus_register(&eisa_bus_type);
+	if (r)
 		return r;
 
-	printk (KERN_INFO "EISA bus registered\n");
+	printk(KERN_INFO "EISA bus registered\n");
 	return 0;
 }
 
 module_param_array(enable_dev, int, &enable_dev_count, 0444);
 module_param_array(disable_dev, int, &disable_dev_count, 0444);
 
-postcore_initcall (eisa_init);
+postcore_initcall(eisa_init);
 
 int EISA_bus;		/* for legacy drivers */
-EXPORT_SYMBOL (EISA_bus);
-EXPORT_SYMBOL (eisa_bus_type);
-EXPORT_SYMBOL (eisa_driver_register);
-EXPORT_SYMBOL (eisa_driver_unregister);
+EXPORT_SYMBOL(EISA_bus);
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 4eeaed5..8be720b 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -25,6 +25,7 @@
 #include <linux/firewire.h>
 #include <linux/firewire-cdev.h>
 #include <linux/idr.h>
+#include <linux/irqflags.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/kref.h>
@@ -32,7 +33,6 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/poll.h>
-#include <linux/preempt.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
@@ -368,39 +368,56 @@
 	for_each_client(device, wake_up_client);
 }
 
-static int ioctl_get_info(struct client *client, void *buffer)
+union ioctl_arg {
+	struct fw_cdev_get_info			get_info;
+	struct fw_cdev_send_request		send_request;
+	struct fw_cdev_allocate			allocate;
+	struct fw_cdev_deallocate		deallocate;
+	struct fw_cdev_send_response		send_response;
+	struct fw_cdev_initiate_bus_reset	initiate_bus_reset;
+	struct fw_cdev_add_descriptor		add_descriptor;
+	struct fw_cdev_remove_descriptor	remove_descriptor;
+	struct fw_cdev_create_iso_context	create_iso_context;
+	struct fw_cdev_queue_iso		queue_iso;
+	struct fw_cdev_start_iso		start_iso;
+	struct fw_cdev_stop_iso			stop_iso;
+	struct fw_cdev_get_cycle_timer		get_cycle_timer;
+	struct fw_cdev_allocate_iso_resource	allocate_iso_resource;
+	struct fw_cdev_send_stream_packet	send_stream_packet;
+	struct fw_cdev_get_cycle_timer2		get_cycle_timer2;
+};
+
+static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_get_info *get_info = buffer;
+	struct fw_cdev_get_info *a = &arg->get_info;
 	struct fw_cdev_event_bus_reset bus_reset;
 	unsigned long ret = 0;
 
-	client->version = get_info->version;
-	get_info->version = FW_CDEV_VERSION;
-	get_info->card = client->device->card->index;
+	client->version = a->version;
+	a->version = FW_CDEV_VERSION;
+	a->card = client->device->card->index;
 
 	down_read(&fw_device_rwsem);
 
-	if (get_info->rom != 0) {
-		void __user *uptr = u64_to_uptr(get_info->rom);
-		size_t want = get_info->rom_length;
+	if (a->rom != 0) {
+		size_t want = a->rom_length;
 		size_t have = client->device->config_rom_length * 4;
 
-		ret = copy_to_user(uptr, client->device->config_rom,
-				   min(want, have));
+		ret = copy_to_user(u64_to_uptr(a->rom),
+				   client->device->config_rom, min(want, have));
 	}
-	get_info->rom_length = client->device->config_rom_length * 4;
+	a->rom_length = client->device->config_rom_length * 4;
 
 	up_read(&fw_device_rwsem);
 
 	if (ret != 0)
 		return -EFAULT;
 
-	client->bus_reset_closure = get_info->bus_reset_closure;
-	if (get_info->bus_reset != 0) {
-		void __user *uptr = u64_to_uptr(get_info->bus_reset);
-
+	client->bus_reset_closure = a->bus_reset_closure;
+	if (a->bus_reset != 0) {
 		fill_bus_reset_event(&bus_reset, client);
-		if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset)))
+		if (copy_to_user(u64_to_uptr(a->bus_reset),
+				 &bus_reset, sizeof(bus_reset)))
 			return -EFAULT;
 	}
 
@@ -571,11 +588,9 @@
 	return ret;
 }
 
-static int ioctl_send_request(struct client *client, void *buffer)
+static int ioctl_send_request(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_send_request *request = buffer;
-
-	switch (request->tcode) {
+	switch (arg->send_request.tcode) {
 	case TCODE_WRITE_QUADLET_REQUEST:
 	case TCODE_WRITE_BLOCK_REQUEST:
 	case TCODE_READ_QUADLET_REQUEST:
@@ -592,7 +607,7 @@
 		return -EINVAL;
 	}
 
-	return init_request(client, request, client->device->node_id,
+	return init_request(client, &arg->send_request, client->device->node_id,
 			    client->device->max_speed);
 }
 
@@ -683,9 +698,9 @@
 	kfree(r);
 }
 
-static int ioctl_allocate(struct client *client, void *buffer)
+static int ioctl_allocate(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_allocate *request = buffer;
+	struct fw_cdev_allocate *a = &arg->allocate;
 	struct address_handler_resource *r;
 	struct fw_address_region region;
 	int ret;
@@ -694,13 +709,13 @@
 	if (r == NULL)
 		return -ENOMEM;
 
-	region.start = request->offset;
-	region.end = request->offset + request->length;
-	r->handler.length = request->length;
+	region.start = a->offset;
+	region.end   = a->offset + a->length;
+	r->handler.length           = a->length;
 	r->handler.address_callback = handle_request;
-	r->handler.callback_data = r;
-	r->closure = request->closure;
-	r->client = client;
+	r->handler.callback_data    = r;
+	r->closure   = a->closure;
+	r->client    = client;
 
 	ret = fw_core_add_address_handler(&r->handler, &region);
 	if (ret < 0) {
@@ -714,27 +729,25 @@
 		release_address_handler(client, &r->resource);
 		return ret;
 	}
-	request->handle = r->resource.handle;
+	a->handle = r->resource.handle;
 
 	return 0;
 }
 
-static int ioctl_deallocate(struct client *client, void *buffer)
+static int ioctl_deallocate(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_deallocate *request = buffer;
-
-	return release_client_resource(client, request->handle,
+	return release_client_resource(client, arg->deallocate.handle,
 				       release_address_handler, NULL);
 }
 
-static int ioctl_send_response(struct client *client, void *buffer)
+static int ioctl_send_response(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_send_response *request = buffer;
+	struct fw_cdev_send_response *a = &arg->send_response;
 	struct client_resource *resource;
 	struct inbound_transaction_resource *r;
 	int ret = 0;
 
-	if (release_client_resource(client, request->handle,
+	if (release_client_resource(client, a->handle,
 				    release_request, &resource) < 0)
 		return -EINVAL;
 
@@ -743,28 +756,24 @@
 	if (is_fcp_request(r->request))
 		goto out;
 
-	if (request->length < r->length)
-		r->length = request->length;
-	if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) {
+	if (a->length < r->length)
+		r->length = a->length;
+	if (copy_from_user(r->data, u64_to_uptr(a->data), r->length)) {
 		ret = -EFAULT;
 		kfree(r->request);
 		goto out;
 	}
-	fw_send_response(client->device->card, r->request, request->rcode);
+	fw_send_response(client->device->card, r->request, a->rcode);
  out:
 	kfree(r);
 
 	return ret;
 }
 
-static int ioctl_initiate_bus_reset(struct client *client, void *buffer)
+static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_initiate_bus_reset *request = buffer;
-	int short_reset;
-
-	short_reset = (request->type == FW_CDEV_SHORT_RESET);
-
-	return fw_core_initiate_bus_reset(client->device->card, short_reset);
+	return fw_core_initiate_bus_reset(client->device->card,
+			arg->initiate_bus_reset.type == FW_CDEV_SHORT_RESET);
 }
 
 static void release_descriptor(struct client *client,
@@ -777,9 +786,9 @@
 	kfree(r);
 }
 
-static int ioctl_add_descriptor(struct client *client, void *buffer)
+static int ioctl_add_descriptor(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_add_descriptor *request = buffer;
+	struct fw_cdev_add_descriptor *a = &arg->add_descriptor;
 	struct descriptor_resource *r;
 	int ret;
 
@@ -787,22 +796,21 @@
 	if (!client->device->is_local)
 		return -ENOSYS;
 
-	if (request->length > 256)
+	if (a->length > 256)
 		return -EINVAL;
 
-	r = kmalloc(sizeof(*r) + request->length * 4, GFP_KERNEL);
+	r = kmalloc(sizeof(*r) + a->length * 4, GFP_KERNEL);
 	if (r == NULL)
 		return -ENOMEM;
 
-	if (copy_from_user(r->data,
-			   u64_to_uptr(request->data), request->length * 4)) {
+	if (copy_from_user(r->data, u64_to_uptr(a->data), a->length * 4)) {
 		ret = -EFAULT;
 		goto failed;
 	}
 
-	r->descriptor.length    = request->length;
-	r->descriptor.immediate = request->immediate;
-	r->descriptor.key       = request->key;
+	r->descriptor.length    = a->length;
+	r->descriptor.immediate = a->immediate;
+	r->descriptor.key       = a->key;
 	r->descriptor.data      = r->data;
 
 	ret = fw_core_add_descriptor(&r->descriptor);
@@ -815,7 +823,7 @@
 		fw_core_remove_descriptor(&r->descriptor);
 		goto failed;
 	}
-	request->handle = r->resource.handle;
+	a->handle = r->resource.handle;
 
 	return 0;
  failed:
@@ -824,11 +832,9 @@
 	return ret;
 }
 
-static int ioctl_remove_descriptor(struct client *client, void *buffer)
+static int ioctl_remove_descriptor(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_remove_descriptor *request = buffer;
-
-	return release_client_resource(client, request->handle,
+	return release_client_resource(client, arg->remove_descriptor.handle,
 				       release_descriptor, NULL);
 }
 
@@ -851,49 +857,44 @@
 		    sizeof(e->interrupt) + header_length, NULL, 0);
 }
 
-static int ioctl_create_iso_context(struct client *client, void *buffer)
+static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_create_iso_context *request = buffer;
+	struct fw_cdev_create_iso_context *a = &arg->create_iso_context;
 	struct fw_iso_context *context;
 
 	/* We only support one context at this time. */
 	if (client->iso_context != NULL)
 		return -EBUSY;
 
-	if (request->channel > 63)
+	if (a->channel > 63)
 		return -EINVAL;
 
-	switch (request->type) {
+	switch (a->type) {
 	case FW_ISO_CONTEXT_RECEIVE:
-		if (request->header_size < 4 || (request->header_size & 3))
+		if (a->header_size < 4 || (a->header_size & 3))
 			return -EINVAL;
-
 		break;
 
 	case FW_ISO_CONTEXT_TRANSMIT:
-		if (request->speed > SCODE_3200)
+		if (a->speed > SCODE_3200)
 			return -EINVAL;
-
 		break;
 
 	default:
 		return -EINVAL;
 	}
 
-	context =  fw_iso_context_create(client->device->card,
-					 request->type,
-					 request->channel,
-					 request->speed,
-					 request->header_size,
-					 iso_callback, client);
+	context = fw_iso_context_create(client->device->card, a->type,
+					a->channel, a->speed, a->header_size,
+					iso_callback, client);
 	if (IS_ERR(context))
 		return PTR_ERR(context);
 
-	client->iso_closure = request->closure;
+	client->iso_closure = a->closure;
 	client->iso_context = context;
 
 	/* We only support one context at this time. */
-	request->handle = 0;
+	a->handle = 0;
 
 	return 0;
 }
@@ -906,9 +907,9 @@
 #define GET_SY(v)		(((v) >> 20) & 0x0f)
 #define GET_HEADER_LENGTH(v)	(((v) >> 24) & 0xff)
 
-static int ioctl_queue_iso(struct client *client, void *buffer)
+static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_queue_iso *request = buffer;
+	struct fw_cdev_queue_iso *a = &arg->queue_iso;
 	struct fw_cdev_iso_packet __user *p, *end, *next;
 	struct fw_iso_context *ctx = client->iso_context;
 	unsigned long payload, buffer_end, header_length;
@@ -919,7 +920,7 @@
 		u8 header[256];
 	} u;
 
-	if (ctx == NULL || request->handle != 0)
+	if (ctx == NULL || a->handle != 0)
 		return -EINVAL;
 
 	/*
@@ -929,23 +930,23 @@
 	 * set them both to 0, which will still let packets with
 	 * payload_length == 0 through.  In other words, if no packets
 	 * use the indirect payload, the iso buffer need not be mapped
-	 * and the request->data pointer is ignored.
+	 * and the a->data pointer is ignored.
 	 */
 
-	payload = (unsigned long)request->data - client->vm_start;
+	payload = (unsigned long)a->data - client->vm_start;
 	buffer_end = client->buffer.page_count << PAGE_SHIFT;
-	if (request->data == 0 || client->buffer.pages == NULL ||
+	if (a->data == 0 || client->buffer.pages == NULL ||
 	    payload >= buffer_end) {
 		payload = 0;
 		buffer_end = 0;
 	}
 
-	p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request->packets);
+	p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets);
 
-	if (!access_ok(VERIFY_READ, p, request->size))
+	if (!access_ok(VERIFY_READ, p, a->size))
 		return -EFAULT;
 
-	end = (void __user *)p + request->size;
+	end = (void __user *)p + a->size;
 	count = 0;
 	while (p < end) {
 		if (get_user(control, &p->control))
@@ -995,61 +996,78 @@
 		count++;
 	}
 
-	request->size    -= uptr_to_u64(p) - request->packets;
-	request->packets  = uptr_to_u64(p);
-	request->data     = client->vm_start + payload;
+	a->size    -= uptr_to_u64(p) - a->packets;
+	a->packets  = uptr_to_u64(p);
+	a->data     = client->vm_start + payload;
 
 	return count;
 }
 
-static int ioctl_start_iso(struct client *client, void *buffer)
+static int ioctl_start_iso(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_start_iso *request = buffer;
+	struct fw_cdev_start_iso *a = &arg->start_iso;
 
-	if (client->iso_context == NULL || request->handle != 0)
+	if (client->iso_context == NULL || a->handle != 0)
 		return -EINVAL;
 
-	if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) {
-		if (request->tags == 0 || request->tags > 15)
-			return -EINVAL;
+	if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE &&
+	    (a->tags == 0 || a->tags > 15 || a->sync > 15))
+		return -EINVAL;
 
-		if (request->sync > 15)
-			return -EINVAL;
-	}
-
-	return fw_iso_context_start(client->iso_context, request->cycle,
-				    request->sync, request->tags);
+	return fw_iso_context_start(client->iso_context,
+				    a->cycle, a->sync, a->tags);
 }
 
-static int ioctl_stop_iso(struct client *client, void *buffer)
+static int ioctl_stop_iso(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_stop_iso *request = buffer;
+	struct fw_cdev_stop_iso *a = &arg->stop_iso;
 
-	if (client->iso_context == NULL || request->handle != 0)
+	if (client->iso_context == NULL || a->handle != 0)
 		return -EINVAL;
 
 	return fw_iso_context_stop(client->iso_context);
 }
 
-static int ioctl_get_cycle_timer(struct client *client, void *buffer)
+static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_get_cycle_timer *request = buffer;
+	struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2;
 	struct fw_card *card = client->device->card;
-	unsigned long long bus_time;
-	struct timeval tv;
-	unsigned long flags;
+	struct timespec ts = {0, 0};
+	u32 cycle_time;
+	int ret = 0;
 
-	preempt_disable();
-	local_irq_save(flags);
+	local_irq_disable();
 
-	bus_time = card->driver->get_bus_time(card);
-	do_gettimeofday(&tv);
+	cycle_time = card->driver->get_cycle_time(card);
 
-	local_irq_restore(flags);
-	preempt_enable();
+	switch (a->clk_id) {
+	case CLOCK_REALTIME:      getnstimeofday(&ts);                   break;
+	case CLOCK_MONOTONIC:     do_posix_clock_monotonic_gettime(&ts); break;
+	case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts);                  break;
+	default:
+		ret = -EINVAL;
+	}
 
-	request->local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
-	request->cycle_timer = bus_time & 0xffffffff;
+	local_irq_enable();
+
+	a->tv_sec      = ts.tv_sec;
+	a->tv_nsec     = ts.tv_nsec;
+	a->cycle_timer = cycle_time;
+
+	return ret;
+}
+
+static int ioctl_get_cycle_timer(struct client *client, union ioctl_arg *arg)
+{
+	struct fw_cdev_get_cycle_timer *a = &arg->get_cycle_timer;
+	struct fw_cdev_get_cycle_timer2 ct2;
+
+	ct2.clk_id = CLOCK_REALTIME;
+	ioctl_get_cycle_timer2(client, (union ioctl_arg *)&ct2);
+
+	a->local_time = ct2.tv_sec * USEC_PER_SEC + ct2.tv_nsec / NSEC_PER_USEC;
+	a->cycle_timer = ct2.cycle_timer;
+
 	return 0;
 }
 
@@ -1220,33 +1238,32 @@
 	return ret;
 }
 
-static int ioctl_allocate_iso_resource(struct client *client, void *buffer)
+static int ioctl_allocate_iso_resource(struct client *client,
+				       union ioctl_arg *arg)
 {
-	struct fw_cdev_allocate_iso_resource *request = buffer;
-
-	return init_iso_resource(client, request, ISO_RES_ALLOC);
+	return init_iso_resource(client,
+			&arg->allocate_iso_resource, ISO_RES_ALLOC);
 }
 
-static int ioctl_deallocate_iso_resource(struct client *client, void *buffer)
+static int ioctl_deallocate_iso_resource(struct client *client,
+					 union ioctl_arg *arg)
 {
-	struct fw_cdev_deallocate *request = buffer;
-
-	return release_client_resource(client, request->handle,
-				       release_iso_resource, NULL);
+	return release_client_resource(client,
+			arg->deallocate.handle, release_iso_resource, NULL);
 }
 
-static int ioctl_allocate_iso_resource_once(struct client *client, void *buffer)
+static int ioctl_allocate_iso_resource_once(struct client *client,
+					    union ioctl_arg *arg)
 {
-	struct fw_cdev_allocate_iso_resource *request = buffer;
-
-	return init_iso_resource(client, request, ISO_RES_ALLOC_ONCE);
+	return init_iso_resource(client,
+			&arg->allocate_iso_resource, ISO_RES_ALLOC_ONCE);
 }
 
-static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffer)
+static int ioctl_deallocate_iso_resource_once(struct client *client,
+					      union ioctl_arg *arg)
 {
-	struct fw_cdev_allocate_iso_resource *request = buffer;
-
-	return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE);
+	return init_iso_resource(client,
+			&arg->allocate_iso_resource, ISO_RES_DEALLOC_ONCE);
 }
 
 /*
@@ -1254,16 +1271,17 @@
  * limited by the device's link speed, the local node's link speed,
  * and all PHY port speeds between the two links.
  */
-static int ioctl_get_speed(struct client *client, void *buffer)
+static int ioctl_get_speed(struct client *client, union ioctl_arg *arg)
 {
 	return client->device->max_speed;
 }
 
-static int ioctl_send_broadcast_request(struct client *client, void *buffer)
+static int ioctl_send_broadcast_request(struct client *client,
+					union ioctl_arg *arg)
 {
-	struct fw_cdev_send_request *request = buffer;
+	struct fw_cdev_send_request *a = &arg->send_request;
 
-	switch (request->tcode) {
+	switch (a->tcode) {
 	case TCODE_WRITE_QUADLET_REQUEST:
 	case TCODE_WRITE_BLOCK_REQUEST:
 		break;
@@ -1272,36 +1290,36 @@
 	}
 
 	/* Security policy: Only allow accesses to Units Space. */
-	if (request->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END)
+	if (a->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END)
 		return -EACCES;
 
-	return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100);
+	return init_request(client, a, LOCAL_BUS | 0x3f, SCODE_100);
 }
 
-static int ioctl_send_stream_packet(struct client *client, void *buffer)
+static int ioctl_send_stream_packet(struct client *client, union ioctl_arg *arg)
 {
-	struct fw_cdev_send_stream_packet *p = buffer;
+	struct fw_cdev_send_stream_packet *a = &arg->send_stream_packet;
 	struct fw_cdev_send_request request;
 	int dest;
 
-	if (p->speed > client->device->card->link_speed ||
-	    p->length > 1024 << p->speed)
+	if (a->speed > client->device->card->link_speed ||
+	    a->length > 1024 << a->speed)
 		return -EIO;
 
-	if (p->tag > 3 || p->channel > 63 || p->sy > 15)
+	if (a->tag > 3 || a->channel > 63 || a->sy > 15)
 		return -EINVAL;
 
-	dest = fw_stream_packet_destination_id(p->tag, p->channel, p->sy);
+	dest = fw_stream_packet_destination_id(a->tag, a->channel, a->sy);
 	request.tcode		= TCODE_STREAM_DATA;
-	request.length		= p->length;
-	request.closure		= p->closure;
-	request.data		= p->data;
-	request.generation	= p->generation;
+	request.length		= a->length;
+	request.closure		= a->closure;
+	request.data		= a->data;
+	request.generation	= a->generation;
 
-	return init_request(client, &request, dest, p->speed);
+	return init_request(client, &request, dest, a->speed);
 }
 
-static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
+static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {
 	ioctl_get_info,
 	ioctl_send_request,
 	ioctl_allocate,
@@ -1322,47 +1340,35 @@
 	ioctl_get_speed,
 	ioctl_send_broadcast_request,
 	ioctl_send_stream_packet,
+	ioctl_get_cycle_timer2,
 };
 
 static int dispatch_ioctl(struct client *client,
 			  unsigned int cmd, void __user *arg)
 {
-	char buffer[sizeof(union {
-		struct fw_cdev_get_info			_00;
-		struct fw_cdev_send_request		_01;
-		struct fw_cdev_allocate			_02;
-		struct fw_cdev_deallocate		_03;
-		struct fw_cdev_send_response		_04;
-		struct fw_cdev_initiate_bus_reset	_05;
-		struct fw_cdev_add_descriptor		_06;
-		struct fw_cdev_remove_descriptor	_07;
-		struct fw_cdev_create_iso_context	_08;
-		struct fw_cdev_queue_iso		_09;
-		struct fw_cdev_start_iso		_0a;
-		struct fw_cdev_stop_iso			_0b;
-		struct fw_cdev_get_cycle_timer		_0c;
-		struct fw_cdev_allocate_iso_resource	_0d;
-		struct fw_cdev_send_stream_packet	_13;
-	})];
+	union ioctl_arg buffer;
 	int ret;
 
+	if (fw_device_is_shutdown(client->device))
+		return -ENODEV;
+
 	if (_IOC_TYPE(cmd) != '#' ||
 	    _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers))
 		return -EINVAL;
 
 	if (_IOC_DIR(cmd) & _IOC_WRITE) {
 		if (_IOC_SIZE(cmd) > sizeof(buffer) ||
-		    copy_from_user(buffer, arg, _IOC_SIZE(cmd)))
+		    copy_from_user(&buffer, arg, _IOC_SIZE(cmd)))
 			return -EFAULT;
 	}
 
-	ret = ioctl_handlers[_IOC_NR(cmd)](client, buffer);
+	ret = ioctl_handlers[_IOC_NR(cmd)](client, &buffer);
 	if (ret < 0)
 		return ret;
 
 	if (_IOC_DIR(cmd) & _IOC_READ) {
 		if (_IOC_SIZE(cmd) > sizeof(buffer) ||
-		    copy_to_user(arg, buffer, _IOC_SIZE(cmd)))
+		    copy_to_user(arg, &buffer, _IOC_SIZE(cmd)))
 			return -EFAULT;
 	}
 
@@ -1372,24 +1378,14 @@
 static long fw_device_op_ioctl(struct file *file,
 			       unsigned int cmd, unsigned long arg)
 {
-	struct client *client = file->private_data;
-
-	if (fw_device_is_shutdown(client->device))
-		return -ENODEV;
-
-	return dispatch_ioctl(client, cmd, (void __user *) arg);
+	return dispatch_ioctl(file->private_data, cmd, (void __user *)arg);
 }
 
 #ifdef CONFIG_COMPAT
 static long fw_device_op_compat_ioctl(struct file *file,
 				      unsigned int cmd, unsigned long arg)
 {
-	struct client *client = file->private_data;
-
-	if (fw_device_is_shutdown(client->device))
-		return -ENODEV;
-
-	return dispatch_ioctl(client, cmd, compat_ptr(arg));
+	return dispatch_ioctl(file->private_data, cmd, compat_ptr(arg));
 }
 #endif
 
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 9d0dfcb..5db0518 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -18,6 +18,7 @@
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include <linux/bug.h>
 #include <linux/ctype.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -32,7 +33,6 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/rwsem.h>
-#include <linux/semaphore.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/workqueue.h>
@@ -43,7 +43,7 @@
 
 #include "core.h"
 
-void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p)
+void fw_csr_iterator_init(struct fw_csr_iterator *ci, const u32 *p)
 {
 	ci->p = p + 1;
 	ci->end = ci->p + (p[0] >> 16);
@@ -59,9 +59,76 @@
 }
 EXPORT_SYMBOL(fw_csr_iterator_next);
 
+static const u32 *search_leaf(const u32 *directory, int search_key)
+{
+	struct fw_csr_iterator ci;
+	int last_key = 0, key, value;
+
+	fw_csr_iterator_init(&ci, directory);
+	while (fw_csr_iterator_next(&ci, &key, &value)) {
+		if (last_key == search_key &&
+		    key == (CSR_DESCRIPTOR | CSR_LEAF))
+			return ci.p - 1 + value;
+
+		last_key = key;
+	}
+
+	return NULL;
+}
+
+static int textual_leaf_to_string(const u32 *block, char *buf, size_t size)
+{
+	unsigned int quadlets, i;
+	char c;
+
+	if (!size || !buf)
+		return -EINVAL;
+
+	quadlets = min(block[0] >> 16, 256U);
+	if (quadlets < 2)
+		return -ENODATA;
+
+	if (block[1] != 0 || block[2] != 0)
+		/* unknown language/character set */
+		return -ENODATA;
+
+	block += 3;
+	quadlets -= 2;
+	for (i = 0; i < quadlets * 4 && i < size - 1; i++) {
+		c = block[i / 4] >> (24 - 8 * (i % 4));
+		if (c == '\0')
+			break;
+		buf[i] = c;
+	}
+	buf[i] = '\0';
+
+	return i;
+}
+
+/**
+ * fw_csr_string - reads a string from the configuration ROM
+ * @directory: e.g. root directory or unit directory
+ * @key: the key of the preceding directory entry
+ * @buf: where to put the string
+ * @size: size of @buf, in bytes
+ *
+ * The string is taken from a minimal ASCII text descriptor leaf after
+ * the immediate entry with @key.  The string is zero-terminated.
+ * Returns strlen(buf) or a negative error code.
+ */
+int fw_csr_string(const u32 *directory, int key, char *buf, size_t size)
+{
+	const u32 *leaf = search_leaf(directory, key);
+	if (!leaf)
+		return -ENOENT;
+
+	return textual_leaf_to_string(leaf, buf, size);
+}
+EXPORT_SYMBOL(fw_csr_string);
+
 static bool is_fw_unit(struct device *dev);
 
-static int match_unit_directory(u32 *directory, u32 match_flags,
+static int match_unit_directory(const u32 *directory, u32 match_flags,
 				const struct ieee1394_device_id *id)
 {
 	struct fw_csr_iterator ci;
@@ -195,7 +262,7 @@
 	struct config_rom_attribute *attr =
 		container_of(dattr, struct config_rom_attribute, attr);
 	struct fw_csr_iterator ci;
-	u32 *dir;
+	const u32 *dir;
 	int key, value, ret = -ENOENT;
 
 	down_read(&fw_device_rwsem);
@@ -226,10 +293,10 @@
 {
 	struct config_rom_attribute *attr =
 		container_of(dattr, struct config_rom_attribute, attr);
-	struct fw_csr_iterator ci;
-	u32 *dir, *block = NULL, *p, *end;
-	int length, key, value, last_key = 0, ret = -ENOENT;
-	char *b;
+	const u32 *dir;
+	size_t bufsize;
+	char dummy_buf[2];
+	int ret;
 
 	down_read(&fw_device_rwsem);
 
@@ -238,40 +305,23 @@
 	else
 		dir = fw_device(dev)->config_rom + 5;
 
-	fw_csr_iterator_init(&ci, dir);
-	while (fw_csr_iterator_next(&ci, &key, &value)) {
-		if (attr->key == last_key &&
-		    key == (CSR_DESCRIPTOR | CSR_LEAF))
-			block = ci.p - 1 + value;
-		last_key = key;
+	if (buf) {
+		bufsize = PAGE_SIZE - 1;
+	} else {
+		buf = dummy_buf;
+		bufsize = 1;
 	}
 
-	if (block == NULL)
-		goto out;
+	ret = fw_csr_string(dir, attr->key, buf, bufsize);
 
-	length = min(block[0] >> 16, 256U);
-	if (length < 3)
-		goto out;
-
-	if (block[1] != 0 || block[2] != 0)
-		/* Unknown encoding. */
-		goto out;
-
-	if (buf == NULL) {
-		ret = length * 4;
-		goto out;
+	if (ret >= 0) {
+		/* Strip trailing whitespace and add newline. */
+		while (ret > 0 && isspace(buf[ret - 1]))
+			ret--;
+		strcpy(buf + ret, "\n");
+		ret++;
 	}
 
-	b = buf;
-	end = &block[length + 1];
-	for (p = &block[3]; p < end; p++, b += 4)
-		* (u32 *) b = (__force u32) __cpu_to_be32(*p);
-
-	/* Strip trailing whitespace and add newline. */
-	while (b--, (isspace(*b) || *b == '\0') && b > buf);
-	strcpy(b + 1, "\n");
-	ret = b + 2 - buf;
- out:
 	up_read(&fw_device_rwsem);
 
 	return ret;
@@ -371,7 +421,7 @@
 	return ret;
 }
 
-static int units_sprintf(char *buf, u32 *directory)
+static int units_sprintf(char *buf, const u32 *directory)
 {
 	struct fw_csr_iterator ci;
 	int key, value;
@@ -441,28 +491,29 @@
 	return rcode;
 }
 
-#define READ_BIB_ROM_SIZE	256
-#define READ_BIB_STACK_SIZE	16
+#define MAX_CONFIG_ROM_SIZE 256
 
 /*
  * Read the bus info block, perform a speed probe, and read all of the rest of
  * the config ROM.  We do all this with a cached bus generation.  If the bus
- * generation changes under us, read_bus_info_block will fail and get retried.
+ * generation changes under us, read_config_rom will fail and get retried.
  * It's better to start all over in this case because the node from which we
  * are reading the ROM may have changed the ROM during the reset.
  */
-static int read_bus_info_block(struct fw_device *device, int generation)
+static int read_config_rom(struct fw_device *device, int generation)
 {
-	u32 *rom, *stack, *old_rom, *new_rom;
+	const u32 *old_rom, *new_rom;
+	u32 *rom, *stack;
 	u32 sp, key;
 	int i, end, length, ret = -1;
 
-	rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE +
-		      sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL);
+	rom = kmalloc(sizeof(*rom) * MAX_CONFIG_ROM_SIZE +
+		      sizeof(*stack) * MAX_CONFIG_ROM_SIZE, GFP_KERNEL);
 	if (rom == NULL)
 		return -ENOMEM;
 
-	stack = &rom[READ_BIB_ROM_SIZE];
+	stack = &rom[MAX_CONFIG_ROM_SIZE];
+	memset(rom, 0, sizeof(*rom) * MAX_CONFIG_ROM_SIZE);
 
 	device->max_speed = SCODE_100;
 
@@ -529,40 +580,54 @@
 		 */
 		key = stack[--sp];
 		i = key & 0xffffff;
-		if (i >= READ_BIB_ROM_SIZE)
-			/*
-			 * The reference points outside the standard
-			 * config rom area, something's fishy.
-			 */
+		if (WARN_ON(i >= MAX_CONFIG_ROM_SIZE))
 			goto out;
 
 		/* Read header quadlet for the block to get the length. */
 		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
 			goto out;
 		end = i + (rom[i] >> 16) + 1;
-		i++;
-		if (end > READ_BIB_ROM_SIZE)
+		if (end > MAX_CONFIG_ROM_SIZE) {
 			/*
-			 * This block extends outside standard config
-			 * area (and the array we're reading it
-			 * into).  That's broken, so ignore this
-			 * device.
+			 * This block extends outside the config ROM which is
+			 * a firmware bug.  Ignore this whole block, i.e.
+			 * simply set a fake block length of 0.
 			 */
-			goto out;
+			fw_error("skipped invalid ROM block %x at %llx\n",
+				 rom[i],
+				 i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
+			rom[i] = 0;
+			end = i;
+		}
+		i++;
 
 		/*
 		 * Now read in the block.  If this is a directory
 		 * block, check the entries as we read them to see if
 		 * it references another block, and push it in that case.
 		 */
-		while (i < end) {
+		for (; i < end; i++) {
 			if (read_rom(device, generation, i, &rom[i]) !=
 			    RCODE_COMPLETE)
 				goto out;
-			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
-			    sp < READ_BIB_STACK_SIZE)
-				stack[sp++] = i + rom[i];
-			i++;
+
+			if ((key >> 30) != 3 || (rom[i] >> 30) < 2)
+				continue;
+			/*
+			 * Offset points outside the ROM.  May be a firmware
+			 * bug or an Extended ROM entry (IEEE 1212-2001 clause
+			 * 7.7.18).  Simply overwrite this pointer here by a
+			 * fake immediate entry so that later iterators over
+			 * the ROM don't have to check offsets all the time.
+			 */
+			if (i + (rom[i] & 0xffffff) >= MAX_CONFIG_ROM_SIZE) {
+				fw_error("skipped unsupported ROM entry %x at %llx\n",
+					 rom[i],
+					 i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
+				rom[i] = 0;
+				continue;
+			}
+			stack[sp++] = i + rom[i];
 		}
 		if (length < i)
 			length = i;
@@ -762,9 +827,9 @@
 	struct fw_driver *driver = (struct fw_driver *)dev->driver;
 
 	if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) {
-		down(&dev->sem);
+		device_lock(dev);
 		driver->update(unit);
-		up(&dev->sem);
+		device_unlock(dev);
 	}
 
 	return 0;
@@ -905,7 +970,7 @@
 	 * device.
 	 */
 
-	if (read_bus_info_block(device, device->generation) < 0) {
+	if (read_config_rom(device, device->generation) < 0) {
 		if (device->config_rom_retries < MAX_RETRIES &&
 		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
 			device->config_rom_retries++;
@@ -1022,7 +1087,7 @@
 };
 
 /* Reread and compare bus info block and header of root directory */
-static int reread_bus_info_block(struct fw_device *device, int generation)
+static int reread_config_rom(struct fw_device *device, int generation)
 {
 	u32 q;
 	int i;
@@ -1048,7 +1113,7 @@
 	struct fw_card *card = device->card;
 	int node_id = device->node_id;
 
-	switch (reread_bus_info_block(device, device->generation)) {
+	switch (reread_config_rom(device, device->generation)) {
 	case REREAD_BIB_ERROR:
 		if (device->config_rom_retries < MAX_RETRIES / 2 &&
 		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
@@ -1082,7 +1147,7 @@
 	 */
 	device_for_each_child(&device->device, NULL, shutdown_unit);
 
-	if (read_bus_info_block(device, device->generation) < 0) {
+	if (read_config_rom(device, device->generation) < 0) {
 		if (device->config_rom_retries < MAX_RETRIES &&
 		    atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
 			device->config_rom_retries++;
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 495849e..673b03f 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -921,23 +921,15 @@
 		void *payload, size_t length, void *callback_data)
 {
 	int reg = offset & ~CSR_REGISTER_BASE;
-	unsigned long long bus_time;
 	__be32 *data = payload;
 	int rcode = RCODE_COMPLETE;
 
 	switch (reg) {
 	case CSR_CYCLE_TIME:
-	case CSR_BUS_TIME:
-		if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) {
-			rcode = RCODE_TYPE_ERROR;
-			break;
-		}
-
-		bus_time = card->driver->get_bus_time(card);
-		if (reg == CSR_CYCLE_TIME)
-			*data = cpu_to_be32(bus_time);
+		if (TCODE_IS_READ_REQUEST(tcode) && length == 4)
+			*data = cpu_to_be32(card->driver->get_cycle_time(card));
 		else
-			*data = cpu_to_be32(bus_time >> 25);
+			rcode = RCODE_TYPE_ERROR;
 		break;
 
 	case CSR_BROADCAST_CHANNEL:
@@ -968,6 +960,9 @@
 	case CSR_BUSY_TIMEOUT:
 		/* FIXME: Implement this. */
 
+	case CSR_BUS_TIME:
+		/* Useless without initialization by the bus manager. */
+
 	default:
 		rcode = RCODE_ADDRESS_ERROR;
 		break;
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index ed3b1a7..fb03213 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -70,7 +70,7 @@
 	int (*enable_phys_dma)(struct fw_card *card,
 			       int node_id, int generation);
 
-	u64 (*get_bus_time)(struct fw_card *card);
+	u32 (*get_cycle_time)(struct fw_card *card);
 
 	struct fw_iso_context *
 	(*allocate_iso_context)(struct fw_card *card,
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 43ebf33..75dc698 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -38,7 +38,6 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 
-#include <asm/atomic.h>
 #include <asm/byteorder.h>
 #include <asm/page.h>
 #include <asm/system.h>
@@ -73,20 +72,6 @@
 	__le16 transfer_status;
 } __attribute__((aligned(16)));
 
-struct db_descriptor {
-	__le16 first_size;
-	__le16 control;
-	__le16 second_req_count;
-	__le16 first_req_count;
-	__le32 branch_address;
-	__le16 second_res_count;
-	__le16 first_res_count;
-	__le32 reserved0;
-	__le32 first_buffer;
-	__le32 second_buffer;
-	__le32 reserved1;
-} __attribute__((aligned(16)));
-
 #define CONTROL_SET(regs)	(regs)
 #define CONTROL_CLEAR(regs)	((regs) + 4)
 #define COMMAND_PTR(regs)	((regs) + 12)
@@ -181,31 +166,16 @@
 	struct fw_card card;
 
 	__iomem char *registers;
-	dma_addr_t self_id_bus;
-	__le32 *self_id_cpu;
-	struct tasklet_struct bus_reset_tasklet;
 	int node_id;
 	int generation;
 	int request_generation;	/* for timestamping incoming requests */
-	atomic_t bus_seconds;
-
-	bool use_dualbuffer;
-	bool old_uninorth;
-	bool bus_reset_packet_quirk;
+	unsigned quirks;
 
 	/*
 	 * Spinlock for accessing fw_ohci data.  Never call out of
 	 * this driver with this lock held.
 	 */
 	spinlock_t lock;
-	u32 self_id_buffer[512];
-
-	/* Config rom buffers */
-	__be32 *config_rom;
-	dma_addr_t config_rom_bus;
-	__be32 *next_config_rom;
-	dma_addr_t next_config_rom_bus;
-	__be32 next_header;
 
 	struct ar_context ar_request_ctx;
 	struct ar_context ar_response_ctx;
@@ -217,6 +187,18 @@
 	u64 ir_context_channels;
 	u32 ir_context_mask;
 	struct iso_context *ir_context_list;
+
+	__be32    *config_rom;
+	dma_addr_t config_rom_bus;
+	__be32    *next_config_rom;
+	dma_addr_t next_config_rom_bus;
+	__be32     next_header;
+
+	__le32    *self_id_cpu;
+	dma_addr_t self_id_bus;
+	struct tasklet_struct bus_reset_tasklet;
+
+	u32 self_id_buffer[512];
 };
 
 static inline struct fw_ohci *fw_ohci(struct fw_card *card)
@@ -249,6 +231,30 @@
 
 static char ohci_driver_name[] = KBUILD_MODNAME;
 
+#define QUIRK_CYCLE_TIMER		1
+#define QUIRK_RESET_PACKET		2
+#define QUIRK_BE_HEADERS		4
+
+/* In case of multiple matches in ohci_quirks[], only the first one is used. */
+static const struct {
+	unsigned short vendor, device, flags;
+} ohci_quirks[] = {
+	{PCI_VENDOR_ID_TI,	PCI_ANY_ID,	QUIRK_RESET_PACKET},
+	{PCI_VENDOR_ID_AL,	PCI_ANY_ID,	QUIRK_CYCLE_TIMER},
+	{PCI_VENDOR_ID_NEC,	PCI_ANY_ID,	QUIRK_CYCLE_TIMER},
+	{PCI_VENDOR_ID_VIA,	PCI_ANY_ID,	QUIRK_CYCLE_TIMER},
+	{PCI_VENDOR_ID_APPLE,	PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS},
+};
+
+/* This overrides anything that was found in ohci_quirks[]. */
+static int param_quirks;
+module_param_named(quirks, param_quirks, int, 0644);
+MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
+	", nonatomic cycle timer = "	__stringify(QUIRK_CYCLE_TIMER)
+	", reset packet generation = "	__stringify(QUIRK_RESET_PACKET)
+	", AR/selfID endianess = "	__stringify(QUIRK_BE_HEADERS)
+	")");
+
 #ifdef CONFIG_FIREWIRE_OHCI_DEBUG
 
 #define OHCI_PARAM_DEBUG_AT_AR		1
@@ -275,7 +281,7 @@
 	    !(evt & OHCI1394_busReset))
 		return;
 
-	fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
+	fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
 	    evt & OHCI1394_selfIDComplete	? " selfID"		: "",
 	    evt & OHCI1394_RQPkt		? " AR_req"		: "",
 	    evt & OHCI1394_RSPkt		? " AR_resp"		: "",
@@ -285,7 +291,6 @@
 	    evt & OHCI1394_isochTx		? " IT"			: "",
 	    evt & OHCI1394_postedWriteErr	? " postedWriteErr"	: "",
 	    evt & OHCI1394_cycleTooLong		? " cycleTooLong"	: "",
-	    evt & OHCI1394_cycle64Seconds	? " cycle64Seconds"	: "",
 	    evt & OHCI1394_cycleInconsistent	? " cycleInconsistent"	: "",
 	    evt & OHCI1394_regAccessFail	? " regAccessFail"	: "",
 	    evt & OHCI1394_busReset		? " busReset"		: "",
@@ -293,8 +298,7 @@
 		    OHCI1394_RSPkt | OHCI1394_reqTxComplete |
 		    OHCI1394_respTxComplete | OHCI1394_isochRx |
 		    OHCI1394_isochTx | OHCI1394_postedWriteErr |
-		    OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds |
-		    OHCI1394_cycleInconsistent |
+		    OHCI1394_cycleTooLong | OHCI1394_cycleInconsistent |
 		    OHCI1394_regAccessFail | OHCI1394_busReset)
 						? " ?"			: "");
 }
@@ -524,7 +528,7 @@
 
 #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
 #define cond_le32_to_cpu(v) \
-	(ohci->old_uninorth ? (__force __u32)(v) : le32_to_cpu(v))
+	(ohci->quirks & QUIRK_BE_HEADERS ? (__force __u32)(v) : le32_to_cpu(v))
 #else
 #define cond_le32_to_cpu(v) le32_to_cpu(v)
 #endif
@@ -605,7 +609,7 @@
 	 * at a slightly incorrect time (in bus_reset_tasklet).
 	 */
 	if (evt == OHCI1394_evt_bus_reset) {
-		if (!ohci->bus_reset_packet_quirk)
+		if (!(ohci->quirks & QUIRK_RESET_PACKET))
 			ohci->request_generation = (p.header[2] >> 16) & 0xff;
 	} else if (ctx == &ohci->ar_request_ctx) {
 		fw_core_handle_request(&ohci->card, &p);
@@ -1329,7 +1333,7 @@
 	context_stop(&ohci->at_response_ctx);
 	reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
 
-	if (ohci->bus_reset_packet_quirk)
+	if (ohci->quirks & QUIRK_RESET_PACKET)
 		ohci->request_generation = generation;
 
 	/*
@@ -1384,7 +1388,7 @@
 static irqreturn_t irq_handler(int irq, void *data)
 {
 	struct fw_ohci *ohci = data;
-	u32 event, iso_event, cycle_time;
+	u32 event, iso_event;
 	int i;
 
 	event = reg_read(ohci, OHCI1394_IntEventClear);
@@ -1454,12 +1458,6 @@
 			fw_notify("isochronous cycle inconsistent\n");
 	}
 
-	if (event & OHCI1394_cycle64Seconds) {
-		cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-		if ((cycle_time & 0x80000000) == 0)
-			atomic_inc(&ohci->bus_seconds);
-	}
-
 	return IRQ_HANDLED;
 }
 
@@ -1553,8 +1551,7 @@
 		  OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
 		  OHCI1394_isochRx | OHCI1394_isochTx |
 		  OHCI1394_postedWriteErr | OHCI1394_cycleTooLong |
-		  OHCI1394_cycleInconsistent |
-		  OHCI1394_cycle64Seconds | OHCI1394_regAccessFail |
+		  OHCI1394_cycleInconsistent | OHCI1394_regAccessFail |
 		  OHCI1394_masterIntEnable);
 	if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
 		reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
@@ -1794,16 +1791,61 @@
 #endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */
 }
 
-static u64 ohci_get_bus_time(struct fw_card *card)
+static u32 cycle_timer_ticks(u32 cycle_timer)
+{
+	u32 ticks;
+
+	ticks = cycle_timer & 0xfff;
+	ticks += 3072 * ((cycle_timer >> 12) & 0x1fff);
+	ticks += (3072 * 8000) * (cycle_timer >> 25);
+
+	return ticks;
+}
+
+/*
+ * Some controllers exhibit one or more of the following bugs when updating the
+ * iso cycle timer register:
+ *  - When the lowest six bits are wrapping around to zero, a read that happens
+ *    at the same time will return garbage in the lowest ten bits.
+ *  - When the cycleOffset field wraps around to zero, the cycleCount field is
+ *    not incremented for about 60 ns.
+ *  - Occasionally, the entire register reads zero.
+ *
+ * To catch these, we read the register three times and ensure that the
+ * difference between each two consecutive reads is approximately the same, i.e.
+ * less than twice the other.  Furthermore, any negative difference indicates an
+ * error.  (A PCI read should take at least 20 ticks of the 24.576 MHz timer to
+ * execute, so we have enough precision to compute the ratio of the differences.)
+ */
+static u32 ohci_get_cycle_time(struct fw_card *card)
 {
 	struct fw_ohci *ohci = fw_ohci(card);
-	u32 cycle_time;
-	u64 bus_time;
+	u32 c0, c1, c2;
+	u32 t0, t1, t2;
+	s32 diff01, diff12;
+	int i;
 
-	cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-	bus_time = ((u64)atomic_read(&ohci->bus_seconds) << 32) | cycle_time;
+	c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
 
-	return bus_time;
+	if (ohci->quirks & QUIRK_CYCLE_TIMER) {
+		i = 0;
+		c1 = c2;
+		c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+		do {
+			c0 = c1;
+			c1 = c2;
+			c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+			t0 = cycle_timer_ticks(c0);
+			t1 = cycle_timer_ticks(c1);
+			t2 = cycle_timer_ticks(c2);
+			diff01 = t1 - t0;
+			diff12 = t2 - t1;
+		} while ((diff01 <= 0 || diff12 <= 0 ||
+			  diff01 / diff12 >= 2 || diff12 / diff01 >= 2)
+			 && i++ < 20);
+	}
+
+	return c2;
 }
 
 static void copy_iso_headers(struct iso_context *ctx, void *p)
@@ -1828,52 +1870,6 @@
 	ctx->header_length += ctx->base.header_size;
 }
 
-static int handle_ir_dualbuffer_packet(struct context *context,
-				       struct descriptor *d,
-				       struct descriptor *last)
-{
-	struct iso_context *ctx =
-		container_of(context, struct iso_context, context);
-	struct db_descriptor *db = (struct db_descriptor *) d;
-	__le32 *ir_header;
-	size_t header_length;
-	void *p, *end;
-
-	if (db->first_res_count != 0 && db->second_res_count != 0) {
-		if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) {
-			/* This descriptor isn't done yet, stop iteration. */
-			return 0;
-		}
-		ctx->excess_bytes -= le16_to_cpu(db->second_req_count);
-	}
-
-	header_length = le16_to_cpu(db->first_req_count) -
-		le16_to_cpu(db->first_res_count);
-
-	p = db + 1;
-	end = p + header_length;
-	while (p < end) {
-		copy_iso_headers(ctx, p);
-		ctx->excess_bytes +=
-			(le32_to_cpu(*(__le32 *)(p + 4)) >> 16) & 0xffff;
-		p += max(ctx->base.header_size, (size_t)8);
-	}
-
-	ctx->excess_bytes -= le16_to_cpu(db->second_req_count) -
-		le16_to_cpu(db->second_res_count);
-
-	if (le16_to_cpu(db->control) & DESCRIPTOR_IRQ_ALWAYS) {
-		ir_header = (__le32 *) (db + 1);
-		ctx->base.callback(&ctx->base,
-				   le32_to_cpu(ir_header[0]) & 0xffff,
-				   ctx->header_length, ctx->header,
-				   ctx->base.callback_data);
-		ctx->header_length = 0;
-	}
-
-	return 1;
-}
-
 static int handle_ir_packet_per_buffer(struct context *context,
 				       struct descriptor *d,
 				       struct descriptor *last)
@@ -1960,10 +1956,7 @@
 		channels = &ohci->ir_context_channels;
 		mask = &ohci->ir_context_mask;
 		list = ohci->ir_context_list;
-		if (ohci->use_dualbuffer)
-			callback = handle_ir_dualbuffer_packet;
-		else
-			callback = handle_ir_packet_per_buffer;
+		callback = handle_ir_packet_per_buffer;
 	}
 
 	spin_lock_irqsave(&ohci->lock, flags);
@@ -2026,8 +2019,6 @@
 	} else {
 		index = ctx - ohci->ir_context_list;
 		control = IR_CONTEXT_ISOCH_HEADER;
-		if (ohci->use_dualbuffer)
-			control |= IR_CONTEXT_DUAL_BUFFER_MODE;
 		match = (tags << 28) | (sync << 8) | ctx->base.channel;
 		if (cycle >= 0) {
 			match |= (cycle & 0x07fff) << 12;
@@ -2188,92 +2179,6 @@
 	return 0;
 }
 
-static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
-					     struct fw_iso_packet *packet,
-					     struct fw_iso_buffer *buffer,
-					     unsigned long payload)
-{
-	struct iso_context *ctx = container_of(base, struct iso_context, base);
-	struct db_descriptor *db = NULL;
-	struct descriptor *d;
-	struct fw_iso_packet *p;
-	dma_addr_t d_bus, page_bus;
-	u32 z, header_z, length, rest;
-	int page, offset, packet_count, header_size;
-
-	/*
-	 * FIXME: Cycle lost behavior should be configurable: lose
-	 * packet, retransmit or terminate..
-	 */
-
-	p = packet;
-	z = 2;
-
-	/*
-	 * The OHCI controller puts the isochronous header and trailer in the
-	 * buffer, so we need at least 8 bytes.
-	 */
-	packet_count = p->header_length / ctx->base.header_size;
-	header_size = packet_count * max(ctx->base.header_size, (size_t)8);
-
-	/* Get header size in number of descriptors. */
-	header_z = DIV_ROUND_UP(header_size, sizeof(*d));
-	page     = payload >> PAGE_SHIFT;
-	offset   = payload & ~PAGE_MASK;
-	rest     = p->payload_length;
-	/*
-	 * The controllers I've tested have not worked correctly when
-	 * second_req_count is zero.  Rather than do something we know won't
-	 * work, return an error
-	 */
-	if (rest == 0)
-		return -EINVAL;
-
-	while (rest > 0) {
-		d = context_get_descriptors(&ctx->context,
-					    z + header_z, &d_bus);
-		if (d == NULL)
-			return -ENOMEM;
-
-		db = (struct db_descriptor *) d;
-		db->control = cpu_to_le16(DESCRIPTOR_STATUS |
-					  DESCRIPTOR_BRANCH_ALWAYS);
-		db->first_size =
-		    cpu_to_le16(max(ctx->base.header_size, (size_t)8));
-		if (p->skip && rest == p->payload_length) {
-			db->control |= cpu_to_le16(DESCRIPTOR_WAIT);
-			db->first_req_count = db->first_size;
-		} else {
-			db->first_req_count = cpu_to_le16(header_size);
-		}
-		db->first_res_count = db->first_req_count;
-		db->first_buffer = cpu_to_le32(d_bus + sizeof(*db));
-
-		if (p->skip && rest == p->payload_length)
-			length = 4;
-		else if (offset + rest < PAGE_SIZE)
-			length = rest;
-		else
-			length = PAGE_SIZE - offset;
-
-		db->second_req_count = cpu_to_le16(length);
-		db->second_res_count = db->second_req_count;
-		page_bus = page_private(buffer->pages[page]);
-		db->second_buffer = cpu_to_le32(page_bus + offset);
-
-		if (p->interrupt && length == rest)
-			db->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS);
-
-		context_append(&ctx->context, d, z, header_z);
-		offset = (offset + length) & ~PAGE_MASK;
-		rest -= length;
-		if (offset == 0)
-			page++;
-	}
-
-	return 0;
-}
-
 static int ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base,
 					struct fw_iso_packet *packet,
 					struct fw_iso_buffer *buffer,
@@ -2364,9 +2269,6 @@
 	spin_lock_irqsave(&ctx->context.ohci->lock, flags);
 	if (base->type == FW_ISO_CONTEXT_TRANSMIT)
 		ret = ohci_queue_iso_transmit(base, packet, buffer, payload);
-	else if (ctx->context.ohci->use_dualbuffer)
-		ret = ohci_queue_iso_receive_dualbuffer(base, packet,
-							buffer, payload);
 	else
 		ret = ohci_queue_iso_receive_packet_per_buffer(base, packet,
 							buffer, payload);
@@ -2383,7 +2285,7 @@
 	.send_response		= ohci_send_response,
 	.cancel_packet		= ohci_cancel_packet,
 	.enable_phys_dma	= ohci_enable_phys_dma,
-	.get_bus_time		= ohci_get_bus_time,
+	.get_cycle_time		= ohci_get_cycle_time,
 
 	.allocate_iso_context	= ohci_allocate_iso_context,
 	.free_iso_context	= ohci_free_iso_context,
@@ -2421,17 +2323,13 @@
 #define ohci_pmac_off(dev)
 #endif /* CONFIG_PPC_PMAC */
 
-#define PCI_VENDOR_ID_AGERE		PCI_VENDOR_ID_ATT
-#define PCI_DEVICE_ID_AGERE_FW643	0x5901
-#define PCI_DEVICE_ID_TI_TSB43AB23	0x8024
-
 static int __devinit pci_probe(struct pci_dev *dev,
 			       const struct pci_device_id *ent)
 {
 	struct fw_ohci *ohci;
 	u32 bus_options, max_receive, link_speed, version;
 	u64 guid;
-	int err;
+	int i, err, n_ir, n_it;
 	size_t size;
 
 	ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
@@ -2472,36 +2370,15 @@
 		goto fail_iomem;
 	}
 
-	version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
-#if 0
-	/* FIXME: make it a context option or remove dual-buffer mode */
-	ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
-#endif
-
-	/* dual-buffer mode is broken if more than one IR context is active */
-	if (dev->vendor == PCI_VENDOR_ID_AGERE &&
-	    dev->device == PCI_DEVICE_ID_AGERE_FW643)
-		ohci->use_dualbuffer = false;
-
-	/* dual-buffer mode is broken */
-	if (dev->vendor == PCI_VENDOR_ID_RICOH &&
-	    dev->device == PCI_DEVICE_ID_RICOH_R5C832)
-		ohci->use_dualbuffer = false;
-
-/* x86-32 currently doesn't use highmem for dma_alloc_coherent */
-#if !defined(CONFIG_X86_32)
-	/* dual-buffer mode is broken with descriptor addresses above 2G */
-	if (dev->vendor == PCI_VENDOR_ID_TI &&
-	    (dev->device == PCI_DEVICE_ID_TI_TSB43AB22 ||
-	     dev->device == PCI_DEVICE_ID_TI_TSB43AB23))
-		ohci->use_dualbuffer = false;
-#endif
-
-#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
-	ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
-			     dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
-#endif
-	ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
+	for (i = 0; i < ARRAY_SIZE(ohci_quirks); i++)
+		if (ohci_quirks[i].vendor == dev->vendor &&
+		    (ohci_quirks[i].device == dev->device ||
+		     ohci_quirks[i].device == (unsigned short)PCI_ANY_ID)) {
+			ohci->quirks = ohci_quirks[i].flags;
+			break;
+		}
+	if (param_quirks)
+		ohci->quirks = param_quirks;
 
 	ar_context_init(&ohci->ar_request_ctx, ohci,
 			OHCI1394_AsReqRcvContextControlSet);
@@ -2516,17 +2393,19 @@
 		     OHCI1394_AsRspTrContextControlSet, handle_at_packet);
 
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
-	ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
+	ohci->ir_context_channels = ~0ULL;
+	ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
-	size = sizeof(struct iso_context) * hweight32(ohci->it_context_mask);
-	ohci->it_context_list = kzalloc(size, GFP_KERNEL);
+	n_ir = hweight32(ohci->ir_context_mask);
+	size = sizeof(struct iso_context) * n_ir;
+	ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
 
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
-	ohci->ir_context_channels = ~0ULL;
-	ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
+	ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
-	size = sizeof(struct iso_context) * hweight32(ohci->ir_context_mask);
-	ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
+	n_it = hweight32(ohci->it_context_mask);
+	size = sizeof(struct iso_context) * n_it;
+	ohci->it_context_list = kzalloc(size, GFP_KERNEL);
 
 	if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) {
 		err = -ENOMEM;
@@ -2553,8 +2432,11 @@
 	if (err)
 		goto fail_self_id;
 
-	fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
-		  dev_name(&dev->dev), version >> 16, version & 0xff);
+	version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
+	fw_notify("Added fw-ohci device %s, OHCI v%x.%x, "
+		  "%d IR + %d IT contexts, quirks 0x%x\n",
+		  dev_name(&dev->dev), version >> 16, version & 0xff,
+		  n_ir, n_it, ohci->quirks);
 
 	return 0;
 
@@ -2662,7 +2544,7 @@
 }
 #endif
 
-static struct pci_device_id pci_table[] = {
+static const struct pci_device_id pci_table[] = {
 	{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) },
 	{ }
 };
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index 70fef40..ca264f2 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -1014,7 +1014,8 @@
 	return 0;
 }
 
-static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, u32 *directory)
+static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt,
+				      const u32 *directory)
 {
 	struct fw_csr_iterator ci;
 	int key, value;
@@ -1027,7 +1028,7 @@
 	return 0;
 }
 
-static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
+static int sbp2_scan_unit_dir(struct sbp2_target *tgt, const u32 *directory,
 			      u32 *model, u32 *firmware_revision)
 {
 	struct fw_csr_iterator ci;
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 9e4f59d..110e24e 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -122,7 +122,7 @@
 	return ret;
 }
 
-static struct sysfs_ops edd_attr_ops = {
+static const struct sysfs_ops edd_attr_ops = {
 	.show = edd_attr_show,
 };
 
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index f4f709d..082f06e 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -362,7 +362,7 @@
 	return ret;
 }
 
-static struct sysfs_ops efivar_attr_ops = {
+static const struct sysfs_ops efivar_attr_ops = {
 	.show = efivar_attr_show,
 	.store = efivar_attr_store,
 };
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index a3600e3..ed2801c 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -519,7 +519,7 @@
 	return ret;
 }
 
-static struct sysfs_ops ibft_attr_ops = {
+static const struct sysfs_ops ibft_attr_ops = {
 	.show = ibft_show_attribute,
 };
 
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 56f9234..d59f7ca 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -74,7 +74,7 @@
 	NULL
 };
 
-static struct sysfs_ops memmap_attr_ops = {
+static const struct sysfs_ops memmap_attr_ops = {
 	.show = memmap_attr_show,
 };
 
@@ -122,29 +122,53 @@
 	return 0;
 }
 
+/*
+ * Add memmap entry on sysfs
+ */
+static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)
+{
+	static int map_entries_nr;
+	static struct kset *mmap_kset;
+
+	if (!mmap_kset) {
+		mmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
+		if (!mmap_kset)
+			return -ENOMEM;
+	}
+
+	entry->kobj.kset = mmap_kset;
+	if (kobject_add(&entry->kobj, NULL, "%d", map_entries_nr++))
+		kobject_put(&entry->kobj);
+
+	return 0;
+}
+
 /**
- * firmware_map_add() - Adds a firmware mapping entry.
+ * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
+ * memory hotplug.
  * @start: Start of the memory range.
  * @end:   End of the memory range (inclusive).
  * @type:  Type of the memory range.
  *
- * This function uses kmalloc() for memory
- * allocation. Use firmware_map_add_early() if you want to use the bootmem
- * allocator.
- *
- * That function must be called before late_initcall.
+ * Adds a firmware mapping entry. This function is for memory hotplug, it is
+ * similar to function firmware_map_add_early(). The only difference is that
+ * it will create the syfs entry dynamically.
  *
  * Returns 0 on success, or -ENOMEM if no memory could be allocated.
  **/
-int firmware_map_add(u64 start, u64 end, const char *type)
+int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type)
 {
 	struct firmware_map_entry *entry;
 
-	entry = kmalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
+	entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
 	if (!entry)
 		return -ENOMEM;
 
-	return firmware_map_add_entry(start, end, type, entry);
+	firmware_map_add_entry(start, end, type, entry);
+	/* create the memmap entry */
+	add_sysfs_fw_map_entry(entry);
+
+	return 0;
 }
 
 /**
@@ -154,7 +178,7 @@
  * @type:  Type of the memory range.
  *
  * Adds a firmware mapping entry. This function uses the bootmem allocator
- * for memory allocation. Use firmware_map_add() if you want to use kmalloc().
+ * for memory allocation.
  *
  * That function must be called before late_initcall.
  *
@@ -214,19 +238,10 @@
  */
 static int __init memmap_init(void)
 {
-	int i = 0;
 	struct firmware_map_entry *entry;
-	struct kset *memmap_kset;
 
-	memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
-	if (WARN_ON(!memmap_kset))
-		return -ENOMEM;
-
-	list_for_each_entry(entry, &map_entries, list) {
-		entry->kobj.kset = memmap_kset;
-		if (kobject_add(&entry->kobj, NULL, "%d", i++))
-			kobject_put(&entry->kobj);
-	}
+	list_for_each_entry(entry, &map_entries, list)
+		add_sysfs_fw_map_entry(entry);
 
 	return 0;
 }
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 1f1d88a..fee678f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -65,8 +65,17 @@
 
 # put expanders in the right section, in alphabetical order
 
+config GPIO_MAX730X
+	tristate
+
 comment "Memory mapped GPIO expanders:"
 
+config GPIO_IT8761E
+	tristate "IT8761E GPIO support"
+	depends on GPIOLIB
+	help
+	  Say yes here to support GPIO functionality of IT8761E super I/O chip.
+
 config GPIO_PL061
 	bool "PrimeCell PL061 GPIO support"
 	depends on ARM_AMBA
@@ -85,8 +94,32 @@
 	help
 	  Say yes here to support the NEC VR4100 series General-purpose I/O Uint
 
+config GPIO_SCH
+	tristate "Intel SCH GPIO"
+	depends on GPIOLIB && PCI
+	select MFD_CORE
+	select LPC_SCH
+	help
+	  Say yes here to support GPIO interface on Intel Poulsbo SCH.
+	  The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
+	  powered by the core power rail and are turned off during sleep
+	  modes (S3 and higher). The remaining four GPIOs are powered by
+	  the Intel SCH suspend power supply. These GPIOs remain
+	  active during S3. The suspend powered GPIOs can be used to wake the
+	  system from the Suspend-to-RAM state.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called sch-gpio.
+
 comment "I2C GPIO expanders:"
 
+config GPIO_MAX7300
+	tristate "Maxim MAX7300 GPIO expander"
+	depends on I2C
+	select GPIO_MAX730X
+	help
+	  GPIO driver for Maxim MAX7301 I2C-based GPIO expander.
+
 config GPIO_MAX732X
 	tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
 	depends on I2C
@@ -124,6 +157,13 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called pca953x.
 
+config GPIO_PCA953X_IRQ
+	bool "Interrupt controller support for PCA953x"
+	depends on GPIO_PCA953X=y
+	help
+	  Say yes here to enable the pca953x to be used as an interrupt
+	  controller. It requires the driver to be built in the kernel.
+
 config GPIO_PCF857X
 	tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
 	depends on I2C
@@ -162,6 +202,20 @@
 	  Say yes here to access the GPIO signals of WM831x power management
 	  chips from Wolfson Microelectronics.
 
+config GPIO_WM8350
+	tristate "WM8350 GPIOs"
+	depends on MFD_WM8350
+	help
+	  Say yes here to access the GPIO signals of WM8350 power management
+	  chips from Wolfson Microelectronics.
+
+config GPIO_WM8994
+	tristate "WM8994 GPIOs"
+	depends on MFD_WM8994
+	help
+	  Say yes here to access the GPIO signals of WM8994 audio hub
+	  CODECs from Wolfson Microelectronics.
+
 config GPIO_ADP5520
 	tristate "GPIO Support for ADP5520 PMIC"
 	depends on PMIC_ADP5520
@@ -226,8 +280,9 @@
 config GPIO_MAX7301
 	tristate "Maxim MAX7301 GPIO expander"
 	depends on SPI_MASTER
+	select GPIO_MAX730X
 	help
-	  gpio driver for Maxim MAX7301 SPI GPIO expander.
+	  GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
 
 config GPIO_MCP23S08
 	tristate "Microchip MCP23S08 I/O expander"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 4868723..10f3f8d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -7,6 +7,8 @@
 obj-$(CONFIG_GPIO_ADP5520)	+= adp5520-gpio.o
 obj-$(CONFIG_GPIO_ADP5588)	+= adp5588-gpio.o
 obj-$(CONFIG_GPIO_LANGWELL)	+= langwell_gpio.o
+obj-$(CONFIG_GPIO_MAX730X)	+= max730x.o
+obj-$(CONFIG_GPIO_MAX7300)	+= max7300.o
 obj-$(CONFIG_GPIO_MAX7301)	+= max7301.o
 obj-$(CONFIG_GPIO_MAX732X)	+= max732x.o
 obj-$(CONFIG_GPIO_MC33880)	+= mc33880.o
@@ -20,5 +22,9 @@
 obj-$(CONFIG_GPIO_XILINX)	+= xilinx_gpio.o
 obj-$(CONFIG_GPIO_CS5535)	+= cs5535-gpio.o
 obj-$(CONFIG_GPIO_BT8XX)	+= bt8xxgpio.o
+obj-$(CONFIG_GPIO_IT8761E)	+= it8761e_gpio.o
 obj-$(CONFIG_GPIO_VR41XX)	+= vr41xx_giu.o
 obj-$(CONFIG_GPIO_WM831X)	+= wm831x-gpio.o
+obj-$(CONFIG_GPIO_WM8350)	+= wm8350-gpiolib.o
+obj-$(CONFIG_GPIO_WM8994)	+= wm8994-gpio.o
+obj-$(CONFIG_GPIO_SCH)		+= sch_gpio.o
\ No newline at end of file
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c
index 0fdbe94..0c3c498 100644
--- a/drivers/gpio/cs5535-gpio.c
+++ b/drivers/gpio/cs5535-gpio.c
@@ -154,7 +154,7 @@
 
 static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	return cs5535_gpio_isset(offset, GPIO_OUTPUT_VAL);
+	return cs5535_gpio_isset(offset, GPIO_READ_BACK);
 }
 
 static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
@@ -172,6 +172,7 @@
 
 	spin_lock_irqsave(&chip->lock, flags);
 	__cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
+	__cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE);
 	spin_unlock_irqrestore(&chip->lock, flags);
 
 	return 0;
@@ -184,6 +185,7 @@
 
 	spin_lock_irqsave(&chip->lock, flags);
 
+	__cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
 	__cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
 	if (val)
 		__cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 350842a..6d1b866 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -623,7 +623,9 @@
  * /sys/class/gpio/unexport ... write-only
  *	integer N ... number of GPIO to unexport
  */
-static ssize_t export_store(struct class *class, const char *buf, size_t len)
+static ssize_t export_store(struct class *class,
+				struct class_attribute *attr,
+				const char *buf, size_t len)
 {
 	long	gpio;
 	int	status;
@@ -653,7 +655,9 @@
 	return status ? : len;
 }
 
-static ssize_t unexport_store(struct class *class, const char *buf, size_t len)
+static ssize_t unexport_store(struct class *class,
+				struct class_attribute *attr,
+				const char *buf, size_t len)
 {
 	long	gpio;
 	int	status;
@@ -1237,6 +1241,64 @@
 }
 EXPORT_SYMBOL_GPL(gpio_free);
 
+/**
+ * gpio_request_one - request a single GPIO with initial configuration
+ * @gpio:	the GPIO number
+ * @flags:	GPIO configuration as specified by GPIOF_*
+ * @label:	a literal description string of this GPIO
+ */
+int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
+{
+	int err;
+
+	err = gpio_request(gpio, label);
+	if (err)
+		return err;
+
+	if (flags & GPIOF_DIR_IN)
+		err = gpio_direction_input(gpio);
+	else
+		err = gpio_direction_output(gpio,
+				(flags & GPIOF_INIT_HIGH) ? 1 : 0);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_one);
+
+/**
+ * gpio_request_array - request multiple GPIOs in a single call
+ * @array:	array of the 'struct gpio'
+ * @num:	how many GPIOs in the array
+ */
+int gpio_request_array(struct gpio *array, size_t num)
+{
+	int i, err;
+
+	for (i = 0; i < num; i++, array++) {
+		err = gpio_request_one(array->gpio, array->flags, array->label);
+		if (err)
+			goto err_free;
+	}
+	return 0;
+
+err_free:
+	while (i--)
+		gpio_free((--array)->gpio);
+	return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_array);
+
+/**
+ * gpio_free_array - release multiple GPIOs in a single call
+ * @array:	array of the 'struct gpio'
+ * @num:	how many GPIOs in the array
+ */
+void gpio_free_array(struct gpio *array, size_t num)
+{
+	while (num--)
+		gpio_free((array++)->gpio);
+}
+EXPORT_SYMBOL_GPL(gpio_free_array);
 
 /**
  * gpiochip_is_requested - return string iff signal was requested
diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c
new file mode 100644
index 0000000..753219c
--- /dev/null
+++ b/drivers/gpio/it8761e_gpio.c
@@ -0,0 +1,231 @@
+/*
+ *  it8761_gpio.c - GPIO interface for IT8761E Super I/O chip
+ *
+ *  Author: Denis Turischev <denis@compulab.co.il>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License 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; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+
+#include <linux/gpio.h>
+
+#define SIO_CHIP_ID		0x8761
+#define CHIP_ID_HIGH_BYTE	0x20
+#define CHIP_ID_LOW_BYTE	0x21
+
+static u8 ports[2] = { 0x2e, 0x4e };
+static u8 port;
+
+static DEFINE_SPINLOCK(sio_lock);
+
+#define GPIO_NAME		"it8761-gpio"
+#define GPIO_BA_HIGH_BYTE	0x60
+#define GPIO_BA_LOW_BYTE	0x61
+#define GPIO_IOSIZE		4
+#define GPIO1X_IO		0xf0
+#define GPIO2X_IO		0xf1
+
+static u16 gpio_ba;
+
+static u8 read_reg(u8 addr, u8 port)
+{
+	outb(addr, port);
+	return inb(port + 1);
+}
+
+static void write_reg(u8 data, u8 addr, u8 port)
+{
+	outb(addr, port);
+	outb(data, port + 1);
+}
+
+static void enter_conf_mode(u8 port)
+{
+	outb(0x87, port);
+	outb(0x61, port);
+	outb(0x55, port);
+	outb((port == 0x2e) ? 0x55 : 0xaa, port);
+}
+
+static void exit_conf_mode(u8 port)
+{
+	outb(0x2, port);
+	outb(0x2, port + 1);
+}
+
+static void enter_gpio_mode(u8 port)
+{
+	write_reg(0x2, 0x7, port);
+}
+
+static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+	u16 reg;
+	u8 bit;
+
+	bit = gpio_num % 7;
+	reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba;
+
+	return !!(inb(reg) & (1 << bit));
+}
+
+static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+{
+	u8 curr_dirs;
+	u8 io_reg, bit;
+
+	bit = gpio_num % 7;
+	io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO;
+
+	spin_lock(&sio_lock);
+
+	enter_conf_mode(port);
+	enter_gpio_mode(port);
+
+	curr_dirs = read_reg(io_reg, port);
+
+	if (curr_dirs & (1 << bit))
+		write_reg(curr_dirs & ~(1 << bit), io_reg, port);
+
+	exit_conf_mode(port);
+
+	spin_unlock(&sio_lock);
+	return 0;
+}
+
+static void it8761e_gpio_set(struct gpio_chip *gc,
+				unsigned gpio_num, int val)
+{
+	u8 curr_vals, bit;
+	u16 reg;
+
+	bit = gpio_num % 7;
+	reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba;
+
+	spin_lock(&sio_lock);
+
+	curr_vals = inb(reg);
+	if (val)
+		outb(curr_vals | (1 << bit) , reg);
+	else
+		outb(curr_vals & ~(1 << bit), reg);
+
+	spin_unlock(&sio_lock);
+}
+
+static int it8761e_gpio_direction_out(struct gpio_chip *gc,
+					unsigned gpio_num, int val)
+{
+	u8 curr_dirs, io_reg, bit;
+
+	bit = gpio_num % 7;
+	io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO;
+
+	it8761e_gpio_set(gc, gpio_num, val);
+
+	spin_lock(&sio_lock);
+
+	enter_conf_mode(port);
+	enter_gpio_mode(port);
+
+	curr_dirs = read_reg(io_reg, port);
+
+	if (!(curr_dirs & (1 << bit)))
+		write_reg(curr_dirs | (1 << bit), io_reg, port);
+
+	exit_conf_mode(port);
+
+	spin_unlock(&sio_lock);
+	return 0;
+}
+
+static struct gpio_chip it8761e_gpio_chip = {
+	.label			= GPIO_NAME,
+	.owner			= THIS_MODULE,
+	.get			= it8761e_gpio_get,
+	.direction_input	= it8761e_gpio_direction_in,
+	.set			= it8761e_gpio_set,
+	.direction_output	= it8761e_gpio_direction_out,
+};
+
+static int __init it8761e_gpio_init(void)
+{
+	int i, id, err;
+
+	/* chip and port detection */
+	for (i = 0; i < ARRAY_SIZE(ports); i++) {
+		spin_lock(&sio_lock);
+		enter_conf_mode(ports[i]);
+
+		id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) +
+				read_reg(CHIP_ID_LOW_BYTE, ports[i]);
+
+		exit_conf_mode(ports[i]);
+		spin_unlock(&sio_lock);
+
+		if (id == SIO_CHIP_ID) {
+			port = ports[i];
+			break;
+		}
+	}
+
+	if (!port)
+		return -ENODEV;
+
+	/* fetch GPIO base address */
+	enter_conf_mode(port);
+	enter_gpio_mode(port);
+	gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) +
+				read_reg(GPIO_BA_LOW_BYTE, port);
+	exit_conf_mode(port);
+
+	if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME))
+		return -EBUSY;
+
+	it8761e_gpio_chip.base = -1;
+	it8761e_gpio_chip.ngpio = 14;
+
+	err = gpiochip_add(&it8761e_gpio_chip);
+	if (err < 0)
+		goto gpiochip_add_err;
+
+	return 0;
+
+gpiochip_add_err:
+	release_region(gpio_ba, GPIO_IOSIZE);
+	gpio_ba = 0;
+	return err;
+}
+
+static void __exit it8761e_gpio_exit(void)
+{
+	if (gpio_ba) {
+		gpiochip_remove(&it8761e_gpio_chip);
+
+		release_region(gpio_ba, GPIO_IOSIZE);
+		gpio_ba = 0;
+	}
+}
+module_init(it8761e_gpio_init);
+module_exit(it8761e_gpio_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/max7300.c b/drivers/gpio/max7300.c
new file mode 100644
index 0000000..9d74eef
--- /dev/null
+++ b/drivers/gpio/max7300.c
@@ -0,0 +1,94 @@
+/*
+ * drivers/gpio/max7300.c
+ *
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Check max730x.c for further details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/spi/max7301.h>
+
+static int max7300_i2c_write(struct device *dev, unsigned int reg,
+				unsigned int val)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	return i2c_smbus_write_byte_data(client, reg, val);
+}
+
+static int max7300_i2c_read(struct device *dev, unsigned int reg)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int __devinit max7300_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct max7301 *ts;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter,
+			I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+
+	ts->read = max7300_i2c_read;
+	ts->write = max7300_i2c_write;
+	ts->dev = &client->dev;
+
+	ret = __max730x_probe(ts);
+	if (ret)
+		kfree(ts);
+	return ret;
+}
+
+static int __devexit max7300_remove(struct i2c_client *client)
+{
+	return __max730x_remove(&client->dev);
+}
+
+static const struct i2c_device_id max7300_id[] = {
+	{ "max7300", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max7300_id);
+
+static struct i2c_driver max7300_driver = {
+	.driver = {
+		.name = "max7300",
+		.owner = THIS_MODULE,
+	},
+	.probe = max7300_probe,
+	.remove = __devexit_p(max7300_remove),
+	.id_table = max7300_id,
+};
+
+static int __init max7300_init(void)
+{
+	return i2c_add_driver(&max7300_driver);
+}
+subsys_initcall(max7300_init);
+
+static void __exit max7300_exit(void)
+{
+	i2c_del_driver(&max7300_driver);
+}
+module_exit(max7300_exit);
+
+MODULE_AUTHOR("Wolfram Sang");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX7300 GPIO-Expander");
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c
index 480956f..965d9b1 100644
--- a/drivers/gpio/max7301.c
+++ b/drivers/gpio/max7301.c
@@ -1,98 +1,41 @@
-/**
+/*
  * drivers/gpio/max7301.c
  *
  * Copyright (C) 2006 Juergen Beisert, Pengutronix
  * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * The Maxim's MAX7301 device is an SPI driven GPIO expander. There are
- * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more
- * details
- * Note:
- * - DIN must be stable at the rising edge of clock.
- * - when writing:
- *   - always clock in 16 clocks at once
- *   - at DIN: D15 first, D0 last
- *   - D0..D7 = databyte, D8..D14 = commandbyte
- *   - D15 = low -> write command
- * - when reading
- *   - always clock in 16 clocks at once
- *   - at DIN: D15 first, D0 last
- *   - D0..D7 = dummy, D8..D14 = register address
- *   - D15 = high -> read command
- *   - raise CS and assert it again
- *   - always clock in 16 clocks at once
- *   - at DOUT: D15 first, D0 last
- *   - D0..D7 contains the data from the first cycle
- *
- * The driver exports a standard gpiochip interface
+ * Check max730x.c for further details.
  */
 
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/max7301.h>
-#include <linux/gpio.h>
 
-#define DRIVER_NAME "max7301"
-
-/*
- * Pin configurations, see MAX7301 datasheet page 6
- */
-#define PIN_CONFIG_MASK 0x03
-#define PIN_CONFIG_IN_PULLUP 0x03
-#define PIN_CONFIG_IN_WO_PULLUP 0x02
-#define PIN_CONFIG_OUT 0x01
-
-#define PIN_NUMBER 28
-
-
-/*
- * Some registers must be read back to modify.
- * To save time we cache them here in memory
- */
-struct max7301 {
-	struct mutex	lock;
-	u8		port_config[8];	/* field 0 is unused */
-	u32		out_level;	/* cached output levels */
-	struct gpio_chip chip;
-	struct spi_device *spi;
-};
-
-/**
- * max7301_write - Write a new register content
- * @spi: The SPI device
- * @reg: Register offset
- * @val: Value to write
- *
- * A write to the MAX7301 means one message with one transfer
- *
- * Returns 0 if successful or a negative value on error
- */
-static int max7301_write(struct spi_device *spi, unsigned int reg, unsigned int val)
+/* A write to the MAX7301 means one message with one transfer */
+static int max7301_spi_write(struct device *dev, unsigned int reg,
+				unsigned int val)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
+
 	return spi_write(spi, (const u8 *)&word, sizeof(word));
 }
 
-/**
- * max7301_read - Read back register content
- * @spi: The SPI device
- * @reg: Register offset
- *
- * A read from the MAX7301 means two transfers; here, one message each
- *
- * Returns positive 8 bit value from device if successful or a
- * negative value on error
- */
-static int max7301_read(struct spi_device *spi, unsigned int reg)
+/* A read from the MAX7301 means two transfers; here, one message each */
+
+static int max7301_spi_read(struct device *dev, unsigned int reg)
 {
 	int ret;
 	u16 word;
+	struct spi_device *spi = to_spi_device(dev);
 
 	word = 0x8000 | (reg << 8);
 	ret = spi_write(spi, (const u8 *)&word, sizeof(word));
@@ -108,125 +51,13 @@
 	return word & 0xff;
 }
 
-static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct max7301 *ts = container_of(chip, struct max7301, chip);
-	u8 *config;
-	int ret;
-
-	/* First 4 pins are unused in the controller */
-	offset += 4;
-
-	config = &ts->port_config[offset >> 2];
-
-	mutex_lock(&ts->lock);
-
-	/* Standard GPIO API doesn't support pull-ups, has to be extended.
-	 * Hard-coding no pollup for now. */
-	*config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
-
-	ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
-
-	mutex_unlock(&ts->lock);
-
-	return ret;
-}
-
-static int __max7301_set(struct max7301 *ts, unsigned offset, int value)
-{
-	if (value) {
-		ts->out_level |= 1 << offset;
-		return max7301_write(ts->spi, 0x20 + offset, 0x01);
-	} else {
-		ts->out_level &= ~(1 << offset);
-		return max7301_write(ts->spi, 0x20 + offset, 0x00);
-	}
-}
-
-static int max7301_direction_output(struct gpio_chip *chip, unsigned offset,
-				    int value)
-{
-	struct max7301 *ts = container_of(chip, struct max7301, chip);
-	u8 *config;
-	int ret;
-
-	/* First 4 pins are unused in the controller */
-	offset += 4;
-
-	config = &ts->port_config[offset >> 2];
-
-	mutex_lock(&ts->lock);
-
-	*config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
-
-	ret = __max7301_set(ts, offset, value);
-
-	if (!ret)
-		ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
-
-	mutex_unlock(&ts->lock);
-
-	return ret;
-}
-
-static int max7301_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct max7301 *ts = container_of(chip, struct max7301, chip);
-	int config, level = -EINVAL;
-
-	/* First 4 pins are unused in the controller */
-	offset += 4;
-
-	mutex_lock(&ts->lock);
-
-	config = (ts->port_config[offset >> 2] >> ((offset & 3) * 2)) & 3;
-
-	switch (config) {
-	case 1:
-		/* Output: return cached level */
-		level =  !!(ts->out_level & (1 << offset));
-		break;
-	case 2:
-	case 3:
-		/* Input: read out */
-		level = max7301_read(ts->spi, 0x20 + offset) & 0x01;
-	}
-	mutex_unlock(&ts->lock);
-
-	return level;
-}
-
-static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct max7301 *ts = container_of(chip, struct max7301, chip);
-
-	/* First 4 pins are unused in the controller */
-	offset += 4;
-
-	mutex_lock(&ts->lock);
-
-	__max7301_set(ts, offset, value);
-
-	mutex_unlock(&ts->lock);
-}
-
 static int __devinit max7301_probe(struct spi_device *spi)
 {
 	struct max7301 *ts;
-	struct max7301_platform_data *pdata;
-	int i, ret;
+	int ret;
 
-	pdata = spi->dev.platform_data;
-	if (!pdata || !pdata->base) {
-		dev_dbg(&spi->dev, "incorrect or missing platform data\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * bits_per_word cannot be configured in platform data
-	 */
+	/* bits_per_word cannot be configured in platform data */
 	spi->bits_per_word = 16;
-
 	ret = spi_setup(spi);
 	if (ret < 0)
 		return ret;
@@ -235,90 +66,35 @@
 	if (!ts)
 		return -ENOMEM;
 
-	mutex_init(&ts->lock);
+	ts->read = max7301_spi_read;
+	ts->write = max7301_spi_write;
+	ts->dev = &spi->dev;
 
-	dev_set_drvdata(&spi->dev, ts);
-
-	/* Power up the chip and disable IRQ output */
-	max7301_write(spi, 0x04, 0x01);
-
-	ts->spi = spi;
-
-	ts->chip.label = DRIVER_NAME,
-
-	ts->chip.direction_input = max7301_direction_input;
-	ts->chip.get = max7301_get;
-	ts->chip.direction_output = max7301_direction_output;
-	ts->chip.set = max7301_set;
-
-	ts->chip.base = pdata->base;
-	ts->chip.ngpio = PIN_NUMBER;
-	ts->chip.can_sleep = 1;
-	ts->chip.dev = &spi->dev;
-	ts->chip.owner = THIS_MODULE;
-
-	/*
-	 * tristate all pins in hardware and cache the
-	 * register values for later use.
-	 */
-	for (i = 1; i < 8; i++) {
-		int j;
-		/* 0xAA means input with internal pullup disabled */
-		max7301_write(spi, 0x08 + i, 0xAA);
-		ts->port_config[i] = 0xAA;
-		for (j = 0; j < 4; j++) {
-			int offset = (i - 1) * 4 + j;
-			ret = max7301_direction_input(&ts->chip, offset);
-			if (ret)
-				goto exit_destroy;
-		}
-	}
-
-	ret = gpiochip_add(&ts->chip);
+	ret = __max730x_probe(ts);
 	if (ret)
-		goto exit_destroy;
-
-	return ret;
-
-exit_destroy:
-	dev_set_drvdata(&spi->dev, NULL);
-	mutex_destroy(&ts->lock);
-	kfree(ts);
+		kfree(ts);
 	return ret;
 }
 
 static int __devexit max7301_remove(struct spi_device *spi)
 {
-	struct max7301 *ts;
-	int ret;
-
-	ts = dev_get_drvdata(&spi->dev);
-	if (ts == NULL)
-		return -ENODEV;
-
-	dev_set_drvdata(&spi->dev, NULL);
-
-	/* Power down the chip and disable IRQ output */
-	max7301_write(spi, 0x04, 0x00);
-
-	ret = gpiochip_remove(&ts->chip);
-	if (!ret) {
-		mutex_destroy(&ts->lock);
-		kfree(ts);
-	} else
-		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
-			ret);
-
-	return ret;
+	return __max730x_remove(&spi->dev);
 }
 
+static const struct spi_device_id max7301_id[] = {
+	{ "max7301", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, max7301_id);
+
 static struct spi_driver max7301_driver = {
 	.driver = {
-		.name		= DRIVER_NAME,
-		.owner		= THIS_MODULE,
+		.name = "max7301",
+		.owner = THIS_MODULE,
 	},
-	.probe		= max7301_probe,
-	.remove		= __devexit_p(max7301_remove),
+	.probe = max7301_probe,
+	.remove = __devexit_p(max7301_remove),
+	.id_table = max7301_id,
 };
 
 static int __init max7301_init(void)
@@ -336,7 +112,6 @@
 }
 module_exit(max7301_exit);
 
-MODULE_AUTHOR("Juergen Beisert");
+MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
 MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MAX7301 SPI based GPIO-Expander");
-MODULE_ALIAS("spi:" DRIVER_NAME);
+MODULE_DESCRIPTION("MAX7301 GPIO-Expander");
diff --git a/drivers/gpio/max730x.c b/drivers/gpio/max730x.c
new file mode 100644
index 0000000..c9bced5
--- /dev/null
+++ b/drivers/gpio/max730x.c
@@ -0,0 +1,244 @@
+/**
+ * drivers/gpio/max7301.c
+ *
+ * Copyright (C) 2006 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The Maxim MAX7300/1 device is an I2C/SPI driven GPIO expander. There are
+ * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more
+ * details
+ * Note:
+ * - DIN must be stable at the rising edge of clock.
+ * - when writing:
+ *   - always clock in 16 clocks at once
+ *   - at DIN: D15 first, D0 last
+ *   - D0..D7 = databyte, D8..D14 = commandbyte
+ *   - D15 = low -> write command
+ * - when reading
+ *   - always clock in 16 clocks at once
+ *   - at DIN: D15 first, D0 last
+ *   - D0..D7 = dummy, D8..D14 = register address
+ *   - D15 = high -> read command
+ *   - raise CS and assert it again
+ *   - always clock in 16 clocks at once
+ *   - at DOUT: D15 first, D0 last
+ *   - D0..D7 contains the data from the first cycle
+ *
+ * The driver exports a standard gpiochip interface
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/spi/max7301.h>
+#include <linux/gpio.h>
+
+/*
+ * Pin configurations, see MAX7301 datasheet page 6
+ */
+#define PIN_CONFIG_MASK 0x03
+#define PIN_CONFIG_IN_PULLUP 0x03
+#define PIN_CONFIG_IN_WO_PULLUP 0x02
+#define PIN_CONFIG_OUT 0x01
+
+#define PIN_NUMBER 28
+
+static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct max7301 *ts = container_of(chip, struct max7301, chip);
+	u8 *config;
+	u8 offset_bits;
+	int ret;
+
+	/* First 4 pins are unused in the controller */
+	offset += 4;
+	offset_bits = (offset & 3) << 1;
+
+	config = &ts->port_config[offset >> 2];
+
+	mutex_lock(&ts->lock);
+
+	/* Standard GPIO API doesn't support pull-ups, has to be extended.
+	 * Hard-coding no pollup for now. */
+	*config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
+			   | (PIN_CONFIG_IN_WO_PULLUP << offset_bits);
+
+	ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config);
+
+	mutex_unlock(&ts->lock);
+
+	return ret;
+}
+
+static int __max7301_set(struct max7301 *ts, unsigned offset, int value)
+{
+	if (value) {
+		ts->out_level |= 1 << offset;
+		return ts->write(ts->dev, 0x20 + offset, 0x01);
+	} else {
+		ts->out_level &= ~(1 << offset);
+		return ts->write(ts->dev, 0x20 + offset, 0x00);
+	}
+}
+
+static int max7301_direction_output(struct gpio_chip *chip, unsigned offset,
+				    int value)
+{
+	struct max7301 *ts = container_of(chip, struct max7301, chip);
+	u8 *config;
+	u8 offset_bits;
+	int ret;
+
+	/* First 4 pins are unused in the controller */
+	offset += 4;
+	offset_bits = (offset & 3) << 1;
+
+	config = &ts->port_config[offset >> 2];
+
+	mutex_lock(&ts->lock);
+
+	*config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
+			   | (PIN_CONFIG_OUT << offset_bits);
+
+	ret = __max7301_set(ts, offset, value);
+
+	if (!ret)
+		ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config);
+
+	mutex_unlock(&ts->lock);
+
+	return ret;
+}
+
+static int max7301_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct max7301 *ts = container_of(chip, struct max7301, chip);
+	int config, level = -EINVAL;
+
+	/* First 4 pins are unused in the controller */
+	offset += 4;
+
+	mutex_lock(&ts->lock);
+
+	config = (ts->port_config[offset >> 2] >> ((offset & 3) << 1))
+			& PIN_CONFIG_MASK;
+
+	switch (config) {
+	case PIN_CONFIG_OUT:
+		/* Output: return cached level */
+		level =  !!(ts->out_level & (1 << offset));
+		break;
+	case PIN_CONFIG_IN_WO_PULLUP:
+	case PIN_CONFIG_IN_PULLUP:
+		/* Input: read out */
+		level = ts->read(ts->dev, 0x20 + offset) & 0x01;
+	}
+	mutex_unlock(&ts->lock);
+
+	return level;
+}
+
+static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct max7301 *ts = container_of(chip, struct max7301, chip);
+
+	/* First 4 pins are unused in the controller */
+	offset += 4;
+
+	mutex_lock(&ts->lock);
+
+	__max7301_set(ts, offset, value);
+
+	mutex_unlock(&ts->lock);
+}
+
+int __devinit __max730x_probe(struct max7301 *ts)
+{
+	struct device *dev = ts->dev;
+	struct max7301_platform_data *pdata;
+	int i, ret;
+
+	pdata = dev->platform_data;
+	if (!pdata || !pdata->base) {
+		dev_err(dev, "incorrect or missing platform data\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&ts->lock);
+	dev_set_drvdata(dev, ts);
+
+	/* Power up the chip and disable IRQ output */
+	ts->write(dev, 0x04, 0x01);
+
+	ts->chip.label = dev->driver->name;
+
+	ts->chip.direction_input = max7301_direction_input;
+	ts->chip.get = max7301_get;
+	ts->chip.direction_output = max7301_direction_output;
+	ts->chip.set = max7301_set;
+
+	ts->chip.base = pdata->base;
+	ts->chip.ngpio = PIN_NUMBER;
+	ts->chip.can_sleep = 1;
+	ts->chip.dev = dev;
+	ts->chip.owner = THIS_MODULE;
+
+	/*
+	 * tristate all pins in hardware and cache the
+	 * register values for later use.
+	 */
+	for (i = 1; i < 8; i++) {
+		int j;
+		/* 0xAA means input with internal pullup disabled */
+		ts->write(dev, 0x08 + i, 0xAA);
+		ts->port_config[i] = 0xAA;
+		for (j = 0; j < 4; j++) {
+			int offset = (i - 1) * 4 + j;
+			ret = max7301_direction_input(&ts->chip, offset);
+			if (ret)
+				goto exit_destroy;
+		}
+	}
+
+	ret = gpiochip_add(&ts->chip);
+	if (ret)
+		goto exit_destroy;
+
+	return ret;
+
+exit_destroy:
+	dev_set_drvdata(dev, NULL);
+	mutex_destroy(&ts->lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__max730x_probe);
+
+int __devexit __max730x_remove(struct device *dev)
+{
+	struct max7301 *ts = dev_get_drvdata(dev);
+	int ret;
+
+	if (ts == NULL)
+		return -ENODEV;
+
+	dev_set_drvdata(dev, NULL);
+
+	/* Power down the chip and disable IRQ output */
+	ts->write(dev, 0x04, 0x00);
+
+	ret = gpiochip_remove(&ts->chip);
+	if (!ret) {
+		mutex_destroy(&ts->lock);
+		kfree(ts);
+	} else
+		dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__max730x_remove);
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 6a2fb3f..ab5daab 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -14,6 +14,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
 #ifdef CONFIG_OF_GPIO
@@ -26,23 +28,28 @@
 #define PCA953X_INVERT         2
 #define PCA953X_DIRECTION      3
 
+#define PCA953X_GPIOS	       0x00FF
+#define PCA953X_INT	       0x0100
+
 static const struct i2c_device_id pca953x_id[] = {
-	{ "pca9534", 8, },
-	{ "pca9535", 16, },
+	{ "pca9534", 8  | PCA953X_INT, },
+	{ "pca9535", 16 | PCA953X_INT, },
 	{ "pca9536", 4, },
-	{ "pca9537", 4, },
-	{ "pca9538", 8, },
-	{ "pca9539", 16, },
-	{ "pca9554", 8, },
-	{ "pca9555", 16, },
+	{ "pca9537", 4  | PCA953X_INT, },
+	{ "pca9538", 8  | PCA953X_INT, },
+	{ "pca9539", 16 | PCA953X_INT, },
+	{ "pca9554", 8  | PCA953X_INT, },
+	{ "pca9555", 16 | PCA953X_INT, },
 	{ "pca9556", 8, },
 	{ "pca9557", 8, },
 
 	{ "max7310", 8, },
-	{ "max7315", 8, },
-	{ "pca6107", 8, },
-	{ "tca6408", 8, },
-	{ "tca6416", 16, },
+	{ "max7312", 16 | PCA953X_INT, },
+	{ "max7313", 16 | PCA953X_INT, },
+	{ "max7315", 8  | PCA953X_INT, },
+	{ "pca6107", 8  | PCA953X_INT, },
+	{ "tca6408", 8  | PCA953X_INT, },
+	{ "tca6416", 16 | PCA953X_INT, },
 	/* NYET:  { "tca6424", 24, }, */
 	{ }
 };
@@ -53,6 +60,15 @@
 	uint16_t reg_output;
 	uint16_t reg_direction;
 
+#ifdef CONFIG_GPIO_PCA953X_IRQ
+	struct mutex irq_lock;
+	uint16_t irq_mask;
+	uint16_t irq_stat;
+	uint16_t irq_trig_raise;
+	uint16_t irq_trig_fall;
+	int	 irq_base;
+#endif
+
 	struct i2c_client *client;
 	struct pca953x_platform_data *dyn_pdata;
 	struct gpio_chip gpio_chip;
@@ -202,6 +218,210 @@
 	gc->names = chip->names;
 }
 
+#ifdef CONFIG_GPIO_PCA953X_IRQ
+static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
+{
+	struct pca953x_chip *chip;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+	return chip->irq_base + off;
+}
+
+static void pca953x_irq_mask(unsigned int irq)
+{
+	struct pca953x_chip *chip = get_irq_chip_data(irq);
+
+	chip->irq_mask &= ~(1 << (irq - chip->irq_base));
+}
+
+static void pca953x_irq_unmask(unsigned int irq)
+{
+	struct pca953x_chip *chip = get_irq_chip_data(irq);
+
+	chip->irq_mask |= 1 << (irq - chip->irq_base);
+}
+
+static void pca953x_irq_bus_lock(unsigned int irq)
+{
+	struct pca953x_chip *chip = get_irq_chip_data(irq);
+
+	mutex_lock(&chip->irq_lock);
+}
+
+static void pca953x_irq_bus_sync_unlock(unsigned int irq)
+{
+	struct pca953x_chip *chip = get_irq_chip_data(irq);
+
+	mutex_unlock(&chip->irq_lock);
+}
+
+static int pca953x_irq_set_type(unsigned int irq, unsigned int type)
+{
+	struct pca953x_chip *chip = get_irq_chip_data(irq);
+	uint16_t level = irq - chip->irq_base;
+	uint16_t mask = 1 << level;
+
+	if (!(type & IRQ_TYPE_EDGE_BOTH)) {
+		dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
+			irq, type);
+		return -EINVAL;
+	}
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		chip->irq_trig_fall |= mask;
+	else
+		chip->irq_trig_fall &= ~mask;
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		chip->irq_trig_raise |= mask;
+	else
+		chip->irq_trig_raise &= ~mask;
+
+	return pca953x_gpio_direction_input(&chip->gpio_chip, level);
+}
+
+static struct irq_chip pca953x_irq_chip = {
+	.name			= "pca953x",
+	.mask			= pca953x_irq_mask,
+	.unmask			= pca953x_irq_unmask,
+	.bus_lock		= pca953x_irq_bus_lock,
+	.bus_sync_unlock	= pca953x_irq_bus_sync_unlock,
+	.set_type		= pca953x_irq_set_type,
+};
+
+static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
+{
+	uint16_t cur_stat;
+	uint16_t old_stat;
+	uint16_t pending;
+	uint16_t trigger;
+	int ret;
+
+	ret = pca953x_read_reg(chip, PCA953X_INPUT, &cur_stat);
+	if (ret)
+		return 0;
+
+	/* Remove output pins from the equation */
+	cur_stat &= chip->reg_direction;
+
+	old_stat = chip->irq_stat;
+	trigger = (cur_stat ^ old_stat) & chip->irq_mask;
+
+	if (!trigger)
+		return 0;
+
+	chip->irq_stat = cur_stat;
+
+	pending = (old_stat & chip->irq_trig_fall) |
+		  (cur_stat & chip->irq_trig_raise);
+	pending &= trigger;
+
+	return pending;
+}
+
+static irqreturn_t pca953x_irq_handler(int irq, void *devid)
+{
+	struct pca953x_chip *chip = devid;
+	uint16_t pending;
+	uint16_t level;
+
+	pending = pca953x_irq_pending(chip);
+
+	if (!pending)
+		return IRQ_HANDLED;
+
+	do {
+		level = __ffs(pending);
+		handle_nested_irq(level + chip->irq_base);
+
+		pending &= ~(1 << level);
+	} while (pending);
+
+	return IRQ_HANDLED;
+}
+
+static int pca953x_irq_setup(struct pca953x_chip *chip,
+			     const struct i2c_device_id *id)
+{
+	struct i2c_client *client = chip->client;
+	struct pca953x_platform_data *pdata = client->dev.platform_data;
+	int ret;
+
+	if (pdata->irq_base && (id->driver_data & PCA953X_INT)) {
+		int lvl;
+
+		ret = pca953x_read_reg(chip, PCA953X_INPUT,
+				       &chip->irq_stat);
+		if (ret)
+			goto out_failed;
+
+		/*
+		 * There is no way to know which GPIO line generated the
+		 * interrupt.  We have to rely on the previous read for
+		 * this purpose.
+		 */
+		chip->irq_stat &= chip->reg_direction;
+		chip->irq_base = pdata->irq_base;
+		mutex_init(&chip->irq_lock);
+
+		for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
+			int irq = lvl + chip->irq_base;
+
+			set_irq_chip_data(irq, chip);
+			set_irq_chip_and_handler(irq, &pca953x_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
+		}
+
+		ret = request_threaded_irq(client->irq,
+					   NULL,
+					   pca953x_irq_handler,
+					   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					   dev_name(&client->dev), chip);
+		if (ret) {
+			dev_err(&client->dev, "failed to request irq %d\n",
+				client->irq);
+			goto out_failed;
+		}
+
+		chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
+	}
+
+	return 0;
+
+out_failed:
+	chip->irq_base = 0;
+	return ret;
+}
+
+static void pca953x_irq_teardown(struct pca953x_chip *chip)
+{
+	if (chip->irq_base)
+		free_irq(chip->client->irq, chip);
+}
+#else /* CONFIG_GPIO_PCA953X_IRQ */
+static int pca953x_irq_setup(struct pca953x_chip *chip,
+			     const struct i2c_device_id *id)
+{
+	struct i2c_client *client = chip->client;
+	struct pca953x_platform_data *pdata = client->dev.platform_data;
+
+	if (pdata->irq_base && (id->driver_data & PCA953X_INT))
+		dev_warn(&client->dev, "interrupt support not compiled in\n");
+
+	return 0;
+}
+
+static void pca953x_irq_teardown(struct pca953x_chip *chip)
+{
+}
+#endif
+
 /*
  * Handlers for alternative sources of platform_data
  */
@@ -286,7 +506,7 @@
 	/* initialize cached registers from their original values.
 	 * we can't share this chip with another i2c master.
 	 */
-	pca953x_setup_gpio(chip, id->driver_data);
+	pca953x_setup_gpio(chip, id->driver_data & PCA953X_GPIOS);
 
 	ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
 	if (ret)
@@ -301,6 +521,9 @@
 	if (ret)
 		goto out_failed;
 
+	ret = pca953x_irq_setup(chip, id);
+	if (ret)
+		goto out_failed;
 
 	ret = gpiochip_add(&chip->gpio_chip);
 	if (ret)
@@ -317,6 +540,7 @@
 	return 0;
 
 out_failed:
+	pca953x_irq_teardown(chip);
 	kfree(chip->dyn_pdata);
 	kfree(chip);
 	return ret;
@@ -345,6 +569,7 @@
 		return ret;
 	}
 
+	pca953x_irq_teardown(chip);
 	kfree(chip->dyn_pdata);
 	kfree(chip);
 	return 0;
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c
index 4ee4c83..3ad1eeb 100644
--- a/drivers/gpio/pl061.c
+++ b/drivers/gpio/pl061.c
@@ -219,7 +219,7 @@
 		if (pending == 0)
 			continue;
 
-		for_each_bit(offset, &pending, PL061_GPIO_NR)
+		for_each_set_bit(offset, &pending, PL061_GPIO_NR)
 			generic_handle_irq(pl061_to_irq(&chip->gc, offset));
 	}
 	desc->chip->unmask(irq);
diff --git a/drivers/gpio/sch_gpio.c b/drivers/gpio/sch_gpio.c
new file mode 100644
index 0000000..5835213
--- /dev/null
+++ b/drivers/gpio/sch_gpio.c
@@ -0,0 +1,295 @@
+/*
+ *  sch_gpio.c - GPIO interface for Intel Poulsbo SCH
+ *
+ *  Copyright (c) 2010 CompuLab Ltd
+ *  Author: Denis Turischev <denis@compulab.co.il>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License 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; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+
+#include <linux/gpio.h>
+
+static DEFINE_SPINLOCK(gpio_lock);
+
+#define CGEN	(0x00)
+#define CGIO	(0x04)
+#define CGLV	(0x08)
+
+#define RGEN	(0x20)
+#define RGIO	(0x24)
+#define RGLV	(0x28)
+
+static unsigned short gpio_ba;
+
+static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
+{
+	u8 curr_dirs;
+	unsigned short offset, bit;
+
+	spin_lock(&gpio_lock);
+
+	offset = CGIO + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	curr_dirs = inb(gpio_ba + offset);
+
+	if (!(curr_dirs & (1 << bit)))
+		outb(curr_dirs | (1 << bit), gpio_ba + offset);
+
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+
+static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+	int res;
+	unsigned short offset, bit;
+
+	offset = CGLV + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	res = !!(inb(gpio_ba + offset) & (1 << bit));
+	return res;
+}
+
+static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+{
+	u8 curr_vals;
+	unsigned short offset, bit;
+
+	spin_lock(&gpio_lock);
+
+	offset = CGLV + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	curr_vals = inb(gpio_ba + offset);
+
+	if (val)
+		outb(curr_vals | (1 << bit), gpio_ba + offset);
+	else
+		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
+	spin_unlock(&gpio_lock);
+}
+
+static int sch_gpio_core_direction_out(struct gpio_chip *gc,
+					unsigned gpio_num, int val)
+{
+	u8 curr_dirs;
+	unsigned short offset, bit;
+
+	sch_gpio_core_set(gc, gpio_num, val);
+
+	spin_lock(&gpio_lock);
+
+	offset = CGIO + gpio_num / 8;
+	bit = gpio_num % 8;
+
+	curr_dirs = inb(gpio_ba + offset);
+	if (curr_dirs & (1 << bit))
+		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
+
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+
+static struct gpio_chip sch_gpio_core = {
+	.label			= "sch_gpio_core",
+	.owner			= THIS_MODULE,
+	.direction_input	= sch_gpio_core_direction_in,
+	.get			= sch_gpio_core_get,
+	.direction_output	= sch_gpio_core_direction_out,
+	.set			= sch_gpio_core_set,
+};
+
+static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
+					unsigned gpio_num)
+{
+	u8 curr_dirs;
+
+	spin_lock(&gpio_lock);
+
+	curr_dirs = inb(gpio_ba + RGIO);
+
+	if (!(curr_dirs & (1 << gpio_num)))
+		outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO);
+
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+
+static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+	return !!(inb(gpio_ba + RGLV) & (1 << gpio_num));
+}
+
+static void sch_gpio_resume_set(struct gpio_chip *gc,
+				unsigned gpio_num, int val)
+{
+	u8 curr_vals;
+
+	spin_lock(&gpio_lock);
+
+	curr_vals = inb(gpio_ba + RGLV);
+
+	if (val)
+		outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV);
+	else
+		outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV);
+
+	spin_unlock(&gpio_lock);
+}
+
+static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
+					unsigned gpio_num, int val)
+{
+	u8 curr_dirs;
+
+	sch_gpio_resume_set(gc, gpio_num, val);
+
+	spin_lock(&gpio_lock);
+
+	curr_dirs = inb(gpio_ba + RGIO);
+	if (curr_dirs & (1 << gpio_num))
+		outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO);
+
+	spin_unlock(&gpio_lock);
+	return 0;
+}
+
+static struct gpio_chip sch_gpio_resume = {
+	.label			= "sch_gpio_resume",
+	.owner			= THIS_MODULE,
+	.direction_input	= sch_gpio_resume_direction_in,
+	.get			= sch_gpio_resume_get,
+	.direction_output	= sch_gpio_resume_direction_out,
+	.set			= sch_gpio_resume_set,
+};
+
+static int __devinit sch_gpio_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int err;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res)
+		return -EBUSY;
+
+	if (!request_region(res->start, resource_size(res), pdev->name))
+		return -EBUSY;
+
+	gpio_ba = res->start;
+
+	sch_gpio_core.base = 0;
+	sch_gpio_core.ngpio = 10;
+	sch_gpio_core.dev = &pdev->dev;
+
+	sch_gpio_resume.base = 10;
+	sch_gpio_resume.ngpio = 4;
+	sch_gpio_resume.dev = &pdev->dev;
+
+	err = gpiochip_add(&sch_gpio_core);
+	if (err < 0)
+		goto err_sch_gpio_core;
+
+	err = gpiochip_add(&sch_gpio_resume);
+	if (err < 0)
+		goto err_sch_gpio_resume;
+
+	/*
+	 * GPIO[6:0] enabled by default
+	 * GPIO7 is configured by the CMC as SLPIOVR
+	 * Enable GPIO[9:8] core powered gpios explicitly
+	 */
+	outb(0x3, gpio_ba + CGEN + 1);
+	/*
+	 * SUS_GPIO[2:0] enabled by default
+	 * Enable SUS_GPIO3 resume powered gpio explicitly
+	 */
+	outb(0x8, gpio_ba + RGEN);
+
+	return 0;
+
+err_sch_gpio_resume:
+	err = gpiochip_remove(&sch_gpio_core);
+	if (err)
+		dev_err(&pdev->dev, "%s failed, %d\n",
+				"gpiochip_remove()", err);
+
+err_sch_gpio_core:
+	release_region(res->start, resource_size(res));
+	gpio_ba = 0;
+
+	return err;
+}
+
+static int __devexit sch_gpio_remove(struct platform_device *pdev)
+{
+	struct resource *res;
+	if (gpio_ba) {
+		int err;
+
+		err  = gpiochip_remove(&sch_gpio_core);
+		if (err)
+			dev_err(&pdev->dev, "%s failed, %d\n",
+				"gpiochip_remove()", err);
+		err = gpiochip_remove(&sch_gpio_resume);
+		if (err)
+			dev_err(&pdev->dev, "%s failed, %d\n",
+				"gpiochip_remove()", err);
+
+		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+
+		release_region(res->start, resource_size(res));
+		gpio_ba = 0;
+
+		return err;
+	}
+
+	return 0;
+}
+
+static struct platform_driver sch_gpio_driver = {
+	.driver = {
+		.name = "sch_gpio",
+		.owner = THIS_MODULE,
+	},
+	.probe		= sch_gpio_probe,
+	.remove		= __devexit_p(sch_gpio_remove),
+};
+
+static int __init sch_gpio_init(void)
+{
+	return platform_driver_register(&sch_gpio_driver);
+}
+
+static void __exit sch_gpio_exit(void)
+{
+	platform_driver_unregister(&sch_gpio_driver);
+}
+
+module_init(sch_gpio_init);
+module_exit(sch_gpio_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sch_gpio");
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c
index a4d344b..d4295fa 100644
--- a/drivers/gpio/timbgpio.c
+++ b/drivers/gpio/timbgpio.c
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
+#include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/timb_gpio.h>
 #include <linux/interrupt.h>
@@ -37,6 +38,8 @@
 #define TGPIO_ICR	0x14
 #define TGPIO_FLR	0x18
 #define TGPIO_LVR	0x1c
+#define TGPIO_VER	0x20
+#define TGPIO_BFLR	0x24
 
 struct timbgpio {
 	void __iomem		*membase;
@@ -125,17 +128,23 @@
 	struct timbgpio *tgpio = get_irq_chip_data(irq);
 	int offset = irq - tgpio->irq_base;
 	unsigned long flags;
-	u32 lvr, flr;
+	u32 lvr, flr, bflr = 0;
+	u32 ver;
 
 	if (offset < 0 || offset > tgpio->gpio.ngpio)
 		return -EINVAL;
 
+	ver = ioread32(tgpio->membase + TGPIO_VER);
+
 	spin_lock_irqsave(&tgpio->lock, flags);
 
 	lvr = ioread32(tgpio->membase + TGPIO_LVR);
 	flr = ioread32(tgpio->membase + TGPIO_FLR);
+	if (ver > 2)
+		bflr = ioread32(tgpio->membase + TGPIO_BFLR);
 
 	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+		bflr &= ~(1 << offset);
 		flr &= ~(1 << offset);
 		if (trigger & IRQ_TYPE_LEVEL_HIGH)
 			lvr |= 1 << offset;
@@ -143,21 +152,27 @@
 			lvr &= ~(1 << offset);
 	}
 
-	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
-		return -EINVAL;
-	else {
+	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+		if (ver < 3)
+			return -EINVAL;
+		else {
+			flr |= 1 << offset;
+			bflr |= 1 << offset;
+		}
+	} else {
+		bflr &= ~(1 << offset);
 		flr |= 1 << offset;
-		/* opposite compared to the datasheet, but it mirrors the
-		 * reality
-		 */
 		if (trigger & IRQ_TYPE_EDGE_FALLING)
-			lvr |= 1 << offset;
-		else
 			lvr &= ~(1 << offset);
+		else
+			lvr |= 1 << offset;
 	}
 
 	iowrite32(lvr, tgpio->membase + TGPIO_LVR);
 	iowrite32(flr, tgpio->membase + TGPIO_FLR);
+	if (ver > 2)
+		iowrite32(bflr, tgpio->membase + TGPIO_BFLR);
+
 	iowrite32(1 << offset, tgpio->membase + TGPIO_ICR);
 	spin_unlock_irqrestore(&tgpio->lock, flags);
 
@@ -174,7 +189,7 @@
 	ipr = ioread32(tgpio->membase + TGPIO_IPR);
 	iowrite32(ipr, tgpio->membase + TGPIO_ICR);
 
-	for_each_bit(offset, &ipr, tgpio->gpio.ngpio)
+	for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio)
 		generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
 }
 
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c
index b4468b6..d09021f 100644
--- a/drivers/gpio/wm831x-gpio.c
+++ b/drivers/gpio/wm831x-gpio.c
@@ -38,10 +38,14 @@
 {
 	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
 	struct wm831x *wm831x = wm831x_gpio->wm831x;
+	int val = WM831X_GPN_DIR;
+
+	if (wm831x->has_gpio_ena)
+		val |= WM831X_GPN_TRI;
 
 	return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
-			       WM831X_GPN_DIR | WM831X_GPN_TRI,
-			       WM831X_GPN_DIR);
+			       WM831X_GPN_DIR | WM831X_GPN_TRI |
+			       WM831X_GPN_FN_MASK, val);
 }
 
 static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -60,16 +64,6 @@
 		return 0;
 }
 
-static int wm831x_gpio_direction_out(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
-	struct wm831x *wm831x = wm831x_gpio->wm831x;
-
-	return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
-			       WM831X_GPN_DIR | WM831X_GPN_TRI, 0);
-}
-
 static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
@@ -79,6 +73,29 @@
 			value << offset);
 }
 
+static int wm831x_gpio_direction_out(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
+	struct wm831x *wm831x = wm831x_gpio->wm831x;
+	int val = 0;
+	int ret;
+
+	if (wm831x->has_gpio_ena)
+		val |= WM831X_GPN_TRI;
+
+	ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
+			      WM831X_GPN_DIR | WM831X_GPN_TRI |
+			      WM831X_GPN_FN_MASK, val);
+	if (ret < 0)
+		return ret;
+
+	/* Can only set GPIO state once it's in output mode */
+	wm831x_gpio_set(chip, offset, value);
+
+	return 0;
+}
+
 static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
@@ -95,7 +112,7 @@
 {
 	struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
 	struct wm831x *wm831x = wm831x_gpio->wm831x;
-	int i;
+	int i, tristated;
 
 	for (i = 0; i < chip->ngpio; i++) {
 		int gpio = i + chip->base;
@@ -162,15 +179,19 @@
 			break;
 		}
 
+		tristated = reg & WM831X_GPN_TRI;
+		if (wm831x->has_gpio_ena)
+			tristated = !tristated;
+
 		seq_printf(s, " %s %s %s %s%s\n"
 			   "                                  %s%s (0x%4x)\n",
 			   reg & WM831X_GPN_DIR ? "in" : "out",
 			   wm831x_gpio_get(chip, i) ? "high" : "low",
 			   pull,
 			   powerdomain,
-			   reg & WM831X_GPN_POL ? " inverted" : "",
+			   reg & WM831X_GPN_POL ? "" : " inverted",
 			   reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
-			   reg & WM831X_GPN_TRI ? " tristated" : "",
+			   tristated ? " tristated" : "",
 			   reg);
 	}
 }
diff --git a/drivers/gpio/wm8350-gpiolib.c b/drivers/gpio/wm8350-gpiolib.c
new file mode 100644
index 0000000..511840d
--- /dev/null
+++ b/drivers/gpio/wm8350-gpiolib.c
@@ -0,0 +1,181 @@
+/*
+ * wm835x-gpiolib.c  --  gpiolib support for Wolfson WM835x PMICs
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/gpio.h>
+
+struct wm8350_gpio_data {
+	struct wm8350 *wm8350;
+	struct gpio_chip gpio_chip;
+};
+
+static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct wm8350_gpio_data, gpio_chip);
+}
+
+static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+	return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
+			       1 << offset);
+}
+
+static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+	int ret;
+
+	ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
+	if (ret < 0)
+		return ret;
+
+	if (ret & (1 << offset))
+		return 1;
+	else
+		return 0;
+}
+
+static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+	if (value)
+		wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
+	else
+		wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
+}
+
+static int wm8350_gpio_direction_out(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+	int ret;
+
+	ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
+				1 << offset);
+	if (ret < 0)
+		return ret;
+
+	/* Don't have an atomic direction/value setup */
+	wm8350_gpio_set(chip, offset, value);
+
+	return 0;
+}
+
+static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+	struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+	if (!wm8350->irq_base)
+		return -EINVAL;
+
+	return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
+}
+
+static struct gpio_chip template_chip = {
+	.label			= "wm8350",
+	.owner			= THIS_MODULE,
+	.direction_input	= wm8350_gpio_direction_in,
+	.get			= wm8350_gpio_get,
+	.direction_output	= wm8350_gpio_direction_out,
+	.set			= wm8350_gpio_set,
+	.to_irq			= wm8350_gpio_to_irq,
+	.can_sleep		= 1,
+};
+
+static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
+{
+	struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
+	struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
+	struct wm8350_gpio_data *wm8350_gpio;
+	int ret;
+
+	wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL);
+	if (wm8350_gpio == NULL)
+		return -ENOMEM;
+
+	wm8350_gpio->wm8350 = wm8350;
+	wm8350_gpio->gpio_chip = template_chip;
+	wm8350_gpio->gpio_chip.ngpio = 13;
+	wm8350_gpio->gpio_chip.dev = &pdev->dev;
+	if (pdata && pdata->gpio_base)
+		wm8350_gpio->gpio_chip.base = pdata->gpio_base;
+	else
+		wm8350_gpio->gpio_chip.base = -1;
+
+	ret = gpiochip_add(&wm8350_gpio->gpio_chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+			ret);
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, wm8350_gpio);
+
+	return ret;
+
+err:
+	kfree(wm8350_gpio);
+	return ret;
+}
+
+static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
+{
+	struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&wm8350_gpio->gpio_chip);
+	if (ret == 0)
+		kfree(wm8350_gpio);
+
+	return ret;
+}
+
+static struct platform_driver wm8350_gpio_driver = {
+	.driver.name	= "wm8350-gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= wm8350_gpio_probe,
+	.remove		= __devexit_p(wm8350_gpio_remove),
+};
+
+static int __init wm8350_gpio_init(void)
+{
+	return platform_driver_register(&wm8350_gpio_driver);
+}
+subsys_initcall(wm8350_gpio_init);
+
+static void __exit wm8350_gpio_exit(void)
+{
+	platform_driver_unregister(&wm8350_gpio_driver);
+}
+module_exit(wm8350_gpio_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-gpio");
diff --git a/drivers/gpio/wm8994-gpio.c b/drivers/gpio/wm8994-gpio.c
new file mode 100644
index 0000000..de28b4a4
--- /dev/null
+++ b/drivers/gpio/wm8994-gpio.c
@@ -0,0 +1,204 @@
+/*
+ * wm8994-gpio.c  --  gpiolib support for Wolfson WM8994
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/pdata.h>
+#include <linux/mfd/wm8994/gpio.h>
+#include <linux/mfd/wm8994/registers.h>
+
+struct wm8994_gpio {
+	struct wm8994 *wm8994;
+	struct gpio_chip gpio_chip;
+};
+
+static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct wm8994_gpio, gpio_chip);
+}
+
+static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+	return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
+			       WM8994_GPN_DIR, WM8994_GPN_DIR);
+}
+
+static int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+	int ret;
+
+	ret = wm8994_reg_read(wm8994, WM8994_GPIO_1 + offset);
+	if (ret < 0)
+		return ret;
+
+	if (ret & WM8994_GPN_LVL)
+		return 1;
+	else
+		return 0;
+}
+
+static int wm8994_gpio_direction_out(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+	return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
+			       WM8994_GPN_DIR, 0);
+}
+
+static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+	if (value)
+		value = WM8994_GPN_LVL;
+
+	wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+	int i;
+
+	for (i = 0; i < chip->ngpio; i++) {
+		int gpio = i + chip->base;
+		int reg;
+		const char *label;
+
+		/* We report the GPIO even if it's not requested since
+		 * we're also reporting things like alternate
+		 * functions which apply even when the GPIO is not in
+		 * use as a GPIO.
+		 */
+		label = gpiochip_is_requested(chip, i);
+		if (!label)
+			label = "Unrequested";
+
+		seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
+
+		reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i);
+		if (reg < 0) {
+			dev_err(wm8994->dev,
+				"GPIO control %d read failed: %d\n",
+				gpio, reg);
+			seq_printf(s, "\n");
+			continue;
+		}
+
+		/* No decode yet; note that GPIO2 is special */
+		seq_printf(s, "(%x)\n", reg);
+	}
+}
+#else
+#define wm8994_gpio_dbg_show NULL
+#endif
+
+static struct gpio_chip template_chip = {
+	.label			= "wm8994",
+	.owner			= THIS_MODULE,
+	.direction_input	= wm8994_gpio_direction_in,
+	.get			= wm8994_gpio_get,
+	.direction_output	= wm8994_gpio_direction_out,
+	.set			= wm8994_gpio_set,
+	.dbg_show		= wm8994_gpio_dbg_show,
+	.can_sleep		= 1,
+};
+
+static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
+{
+	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
+	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+	struct wm8994_gpio *wm8994_gpio;
+	int ret;
+
+	wm8994_gpio = kzalloc(sizeof(*wm8994_gpio), GFP_KERNEL);
+	if (wm8994_gpio == NULL)
+		return -ENOMEM;
+
+	wm8994_gpio->wm8994 = wm8994;
+	wm8994_gpio->gpio_chip = template_chip;
+	wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX;
+	wm8994_gpio->gpio_chip.dev = &pdev->dev;
+	if (pdata && pdata->gpio_base)
+		wm8994_gpio->gpio_chip.base = pdata->gpio_base;
+	else
+		wm8994_gpio->gpio_chip.base = -1;
+
+	ret = gpiochip_add(&wm8994_gpio->gpio_chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+			ret);
+		goto err;
+	}
+
+	platform_set_drvdata(pdev, wm8994_gpio);
+
+	return ret;
+
+err:
+	kfree(wm8994_gpio);
+	return ret;
+}
+
+static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
+{
+	struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&wm8994_gpio->gpio_chip);
+	if (ret == 0)
+		kfree(wm8994_gpio);
+
+	return ret;
+}
+
+static struct platform_driver wm8994_gpio_driver = {
+	.driver.name	= "wm8994-gpio",
+	.driver.owner	= THIS_MODULE,
+	.probe		= wm8994_gpio_probe,
+	.remove		= __devexit_p(wm8994_gpio_remove),
+};
+
+static int __init wm8994_gpio_init(void)
+{
+	return platform_driver_register(&wm8994_gpio_driver);
+}
+subsys_initcall(wm8994_gpio_init);
+
+static void __exit wm8994_gpio_exit(void)
+{
+	platform_driver_unregister(&wm8994_gpio_driver);
+}
+module_exit(wm8994_gpio_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("GPIO interface for WM8994");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8994-gpio");
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 39c5aa7..abe3f44 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -4,7 +4,7 @@
 
 ccflags-y := -Iinclude/drm
 
-drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
+drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_context.o drm_dma.o drm_drawable.o \
 		drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
 		drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
diff --git a/drivers/gpu/drm/drm_buffer.c b/drivers/gpu/drm/drm_buffer.c
new file mode 100644
index 0000000..55d03ed
--- /dev/null
+++ b/drivers/gpu/drm/drm_buffer.c
@@ -0,0 +1,184 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Pauli Nieminen.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+/*
+ * Multipart buffer for coping data which is larger than the page size.
+ *
+ * Authors:
+ * Pauli Nieminen <suokkos-at-gmail-dot-com>
+ */
+
+#include "drm_buffer.h"
+
+/**
+ * Allocate the drm buffer object.
+ *
+ *   buf: Pointer to a pointer where the object is stored.
+ *   size: The number of bytes to allocate.
+ */
+int drm_buffer_alloc(struct drm_buffer **buf, int size)
+{
+	int nr_pages = size / PAGE_SIZE + 1;
+	int idx;
+
+	/* Allocating pointer table to end of structure makes drm_buffer
+	 * variable sized */
+	*buf = kzalloc(sizeof(struct drm_buffer) + nr_pages*sizeof(char *),
+			GFP_KERNEL);
+
+	if (*buf == NULL) {
+		DRM_ERROR("Failed to allocate drm buffer object to hold"
+				" %d bytes in %d pages.\n",
+				size, nr_pages);
+		return -ENOMEM;
+	}
+
+	(*buf)->size = size;
+
+	for (idx = 0; idx < nr_pages; ++idx) {
+
+		(*buf)->data[idx] =
+			kmalloc(min(PAGE_SIZE, size - idx * PAGE_SIZE),
+				GFP_KERNEL);
+
+
+		if ((*buf)->data[idx] == NULL) {
+			DRM_ERROR("Failed to allocate %dth page for drm"
+					" buffer with %d bytes and %d pages.\n",
+					idx + 1, size, nr_pages);
+			goto error_out;
+		}
+
+	}
+
+	return 0;
+
+error_out:
+
+	/* Only last element can be null pointer so check for it first. */
+	if ((*buf)->data[idx])
+		kfree((*buf)->data[idx]);
+
+	for (--idx; idx >= 0; --idx)
+		kfree((*buf)->data[idx]);
+
+	kfree(*buf);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(drm_buffer_alloc);
+
+/**
+ * Copy the user data to the begin of the buffer and reset the processing
+ * iterator.
+ *
+ *   user_data: A pointer the data that is copied to the buffer.
+ *   size: The Number of bytes to copy.
+ */
+extern int drm_buffer_copy_from_user(struct drm_buffer *buf,
+		void __user *user_data, int size)
+{
+	int nr_pages = size / PAGE_SIZE + 1;
+	int idx;
+
+	if (size > buf->size) {
+		DRM_ERROR("Requesting to copy %d bytes to a drm buffer with"
+				" %d bytes space\n",
+				size, buf->size);
+		return -EFAULT;
+	}
+
+	for (idx = 0; idx < nr_pages; ++idx) {
+
+		if (DRM_COPY_FROM_USER(buf->data[idx],
+			user_data + idx * PAGE_SIZE,
+			min(PAGE_SIZE, size - idx * PAGE_SIZE))) {
+			DRM_ERROR("Failed to copy user data (%p) to drm buffer"
+					" (%p) %dth page.\n",
+					user_data, buf, idx);
+			return -EFAULT;
+
+		}
+	}
+	buf->iterator = 0;
+	return 0;
+}
+EXPORT_SYMBOL(drm_buffer_copy_from_user);
+
+/**
+ * Free the drm buffer object
+ */
+void drm_buffer_free(struct drm_buffer *buf)
+{
+
+	if (buf != NULL) {
+
+		int nr_pages = buf->size / PAGE_SIZE + 1;
+		int idx;
+		for (idx = 0; idx < nr_pages; ++idx)
+			kfree(buf->data[idx]);
+
+		kfree(buf);
+	}
+}
+EXPORT_SYMBOL(drm_buffer_free);
+
+/**
+ * Read an object from buffer that may be split to multiple parts. If object
+ * is not split function just returns the pointer to object in buffer. But in
+ * case of split object data is copied to given stack object that is suplied
+ * by caller.
+ *
+ * The processing location of the buffer is also advanced to the next byte
+ * after the object.
+ *
+ *   objsize: The size of the objet in bytes.
+ *   stack_obj: A pointer to a memory location where object can be copied.
+ */
+void *drm_buffer_read_object(struct drm_buffer *buf,
+		int objsize, void *stack_obj)
+{
+	int idx = drm_buffer_index(buf);
+	int page = drm_buffer_page(buf);
+	void *obj = 0;
+
+	if (idx + objsize <= PAGE_SIZE) {
+		obj = &buf->data[page][idx];
+	} else {
+		/* The object is split which forces copy to temporary object.*/
+		int beginsz = PAGE_SIZE - idx;
+		memcpy(stack_obj, &buf->data[page][idx], beginsz);
+
+		memcpy(stack_obj + beginsz, &buf->data[page + 1][0],
+				objsize - beginsz);
+
+		obj = stack_obj;
+	}
+
+	drm_buffer_advance(buf, objsize);
+	return obj;
+}
+EXPORT_SYMBOL(drm_buffer_read_object);
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 7d0f00a..f2aaf39 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -836,11 +836,7 @@
 			mode_changed = true;
 		} else if (set->fb == NULL) {
 			mode_changed = true;
-		} else if ((set->fb->bits_per_pixel !=
-			 set->crtc->fb->bits_per_pixel) ||
-			 set->fb->depth != set->crtc->fb->depth)
-			fb_changed = true;
-		else
+		} else
 			fb_changed = true;
 	}
 
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 766c468..f3c58e2 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -125,28 +125,28 @@
 
 	DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
-	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0),
-	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
 
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW)
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
 };
 
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index ab6c973..f97e7c4 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -60,8 +60,7 @@
 #define EDID_QUIRK_FIRST_DETAILED_PREFERRED	(1 << 5)
 /* use +hsync +vsync for detailed mode */
 #define EDID_QUIRK_DETAILED_SYNC_PP		(1 << 6)
-/* define the number of Extension EDID block */
-#define MAX_EDID_EXT_NUM 4
+
 
 #define LEVEL_DMT	0
 #define LEVEL_GTF	1
@@ -114,14 +113,14 @@
 };
 
 /**
- * edid_is_valid - sanity check EDID data
+ * drm_edid_is_valid - sanity check EDID data
  * @edid: EDID data
  *
  * Sanity check the EDID block by looking at the header, the version number
  * and the checksum.  Return 0 if the EDID doesn't check out, or 1 if it's
  * valid.
  */
-static bool edid_is_valid(struct edid *edid)
+bool drm_edid_is_valid(struct edid *edid)
 {
 	int i, score = 0;
 	u8 csum = 0;
@@ -163,6 +162,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL(drm_edid_is_valid);
 
 /**
  * edid_vendor - match a string against EDID's obfuscated vendor field
@@ -1112,8 +1112,8 @@
 	}
 
 	/* Chose real EDID extension number */
-	edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ?
-		       MAX_EDID_EXT_NUM : edid->extensions;
+	edid_ext_num = edid->extensions > DRM_MAX_EDID_EXT_NUM ?
+		DRM_MAX_EDID_EXT_NUM : edid->extensions;
 
 	/* Find CEA extension */
 	for (i = 0; i < edid_ext_num; i++) {
@@ -1195,7 +1195,7 @@
 	for (i = 0; i < 4; i++) {
 		if (drm_do_probe_ddc_edid(adapter, buf, len))
 			return -1;
-		if (edid_is_valid((struct edid *)buf))
+		if (drm_edid_is_valid((struct edid *)buf))
 			return 0;
 	}
 
@@ -1220,7 +1220,7 @@
 	int ret;
 	struct edid *edid;
 
-	edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1),
+	edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1),
 		       GFP_KERNEL);
 	if (edid == NULL) {
 		dev_warn(&connector->dev->pdev->dev,
@@ -1238,14 +1238,14 @@
 	if (edid->extensions != 0) {
 		int edid_ext_num = edid->extensions;
 
-		if (edid_ext_num > MAX_EDID_EXT_NUM) {
+		if (edid_ext_num > DRM_MAX_EDID_EXT_NUM) {
 			dev_warn(&connector->dev->pdev->dev,
 				 "The number of extension(%d) is "
 				 "over max (%d), actually read number (%d)\n",
-				 edid_ext_num, MAX_EDID_EXT_NUM,
-				 MAX_EDID_EXT_NUM);
+				 edid_ext_num, DRM_MAX_EDID_EXT_NUM,
+				 DRM_MAX_EDID_EXT_NUM);
 			/* Reset EDID extension number to be read */
-			edid_ext_num = MAX_EDID_EXT_NUM;
+			edid_ext_num = DRM_MAX_EDID_EXT_NUM;
 		}
 		/* Read EDID including extensions too */
 		ret = drm_ddc_read_edid(connector, adapter, (char *)edid,
@@ -1288,8 +1288,8 @@
 		goto end;
 
 	/* Chose real EDID extension number */
-	edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ?
-		       MAX_EDID_EXT_NUM : edid->extensions;
+	edid_ext_num = edid->extensions > DRM_MAX_EDID_EXT_NUM ?
+		       DRM_MAX_EDID_EXT_NUM : edid->extensions;
 
 	/* Find CEA extension */
 	for (i = 0; i < edid_ext_num; i++) {
@@ -1346,7 +1346,7 @@
 	if (edid == NULL) {
 		return 0;
 	}
-	if (!edid_is_valid(edid)) {
+	if (!drm_edid_is_valid(edid)) {
 		dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
 			 drm_get_connector_name(connector));
 		return 0;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 0f9e9055..5054970 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -27,6 +27,7 @@
  *      Dave Airlie <airlied@linux.ie>
  *      Jesse Barnes <jesse.barnes@intel.com>
  */
+#include <linux/kernel.h>
 #include <linux/sysrq.h>
 #include <linux/fb.h>
 #include "drmP.h"
@@ -50,21 +51,6 @@
 }
 EXPORT_SYMBOL(drm_fb_helper_add_connector);
 
-static int my_atoi(const char *name)
-{
-	int val = 0;
-
-	for (;; name++) {
-		switch (*name) {
-		case '0' ... '9':
-			val = 10*val+(*name-'0');
-			break;
-		default:
-			return val;
-		}
-	}
-}
-
 /**
  * drm_fb_helper_connector_parse_command_line - parse command line for connector
  * @connector - connector to parse line for
@@ -111,7 +97,7 @@
 			namelen = i;
 			if (!refresh_specified && !bpp_specified &&
 			    !yres_specified) {
-				refresh = my_atoi(&name[i+1]);
+				refresh = simple_strtol(&name[i+1], NULL, 10);
 				refresh_specified = 1;
 				if (cvt || rb)
 					cvt = 0;
@@ -121,7 +107,7 @@
 		case '-':
 			namelen = i;
 			if (!bpp_specified && !yres_specified) {
-				bpp = my_atoi(&name[i+1]);
+				bpp = simple_strtol(&name[i+1], NULL, 10);
 				bpp_specified = 1;
 				if (cvt || rb)
 					cvt = 0;
@@ -130,7 +116,7 @@
 			break;
 		case 'x':
 			if (!yres_specified) {
-				yres = my_atoi(&name[i+1]);
+				yres = simple_strtol(&name[i+1], NULL, 10);
 				yres_specified = 1;
 			} else
 				goto done;
@@ -170,7 +156,7 @@
 		}
 	}
 	if (i < 0 && yres_specified) {
-		xres = my_atoi(name);
+		xres = simple_strtol(name, NULL, 10);
 		res_specified = 1;
 	}
 done:
@@ -694,7 +680,7 @@
 	int i;
 
 	if (var->pixclock != 0) {
-		DRM_ERROR("PIXEL CLCOK SET\n");
+		DRM_ERROR("PIXEL CLOCK SET\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 8bf3770..aa89d4b 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -192,9 +192,7 @@
 	idr_remove(&filp->object_idr, handle);
 	spin_unlock(&filp->table_lock);
 
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_handle_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_handle_unreference_unlocked(obj);
 
 	return 0;
 }
@@ -325,9 +323,7 @@
 	}
 
 err:
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(obj);
 	return ret;
 }
 
@@ -358,9 +354,7 @@
 		return -ENOENT;
 
 	ret = drm_gem_handle_create(file_priv, obj, &handle);
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(obj);
 	if (ret)
 		return ret;
 
@@ -390,7 +384,7 @@
 {
 	struct drm_gem_object *obj = ptr;
 
-	drm_gem_object_handle_unreference(obj);
+	drm_gem_object_handle_unreference_unlocked(obj);
 
 	return 0;
 }
@@ -403,16 +397,25 @@
 void
 drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 {
-	mutex_lock(&dev->struct_mutex);
 	idr_for_each(&file_private->object_idr,
 		     &drm_gem_object_release_handle, NULL);
 
 	idr_destroy(&file_private->object_idr);
-	mutex_unlock(&dev->struct_mutex);
+}
+
+static void
+drm_gem_object_free_common(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	fput(obj->filp);
+	atomic_dec(&dev->object_count);
+	atomic_sub(obj->size, &dev->object_memory);
+	kfree(obj);
 }
 
 /**
  * Called after the last reference to the object has been lost.
+ * Must be called holding struct_ mutex
  *
  * Frees the object
  */
@@ -427,14 +430,40 @@
 	if (dev->driver->gem_free_object != NULL)
 		dev->driver->gem_free_object(obj);
 
-	fput(obj->filp);
-	atomic_dec(&dev->object_count);
-	atomic_sub(obj->size, &dev->object_memory);
-	kfree(obj);
+	drm_gem_object_free_common(obj);
 }
 EXPORT_SYMBOL(drm_gem_object_free);
 
 /**
+ * Called after the last reference to the object has been lost.
+ * Must be called without holding struct_mutex
+ *
+ * Frees the object
+ */
+void
+drm_gem_object_free_unlocked(struct kref *kref)
+{
+	struct drm_gem_object *obj = (struct drm_gem_object *) kref;
+	struct drm_device *dev = obj->dev;
+
+	if (dev->driver->gem_free_object_unlocked != NULL)
+		dev->driver->gem_free_object_unlocked(obj);
+	else if (dev->driver->gem_free_object != NULL) {
+		mutex_lock(&dev->struct_mutex);
+		dev->driver->gem_free_object(obj);
+		mutex_unlock(&dev->struct_mutex);
+	}
+
+	drm_gem_object_free_common(obj);
+}
+EXPORT_SYMBOL(drm_gem_object_free_unlocked);
+
+static void drm_gem_object_ref_bug(struct kref *list_kref)
+{
+	BUG();
+}
+
+/**
  * Called after the last handle to the object has been closed
  *
  * Removes any name for the object. Note that this must be
@@ -458,8 +487,10 @@
 		/*
 		 * The object name held a reference to this object, drop
 		 * that now.
+		*
+		* This cannot be the last reference, since the handle holds one too.
 		 */
-		drm_gem_object_unreference(obj);
+		kref_put(&obj->refcount, drm_gem_object_ref_bug);
 	} else
 		spin_unlock(&dev->object_name_lock);
 
@@ -477,11 +508,8 @@
 void drm_gem_vm_close(struct vm_area_struct *vma)
 {
 	struct drm_gem_object *obj = vma->vm_private_data;
-	struct drm_device *dev = obj->dev;
 
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(obj);
 }
 EXPORT_SYMBOL(drm_gem_vm_close);
 
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 7e42b7e..014ce24 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -70,19 +70,17 @@
 	return 0;
 }
 
-/* Display the version of drm_core. This doesn't work right in current design */
-static ssize_t version_show(struct class *dev, char *buf)
-{
-	return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR,
-		       CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
-}
-
 static char *drm_devnode(struct device *dev, mode_t *mode)
 {
 	return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
 }
 
-static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
+static CLASS_ATTR_STRING(version, S_IRUGO,
+		CORE_NAME " "
+		__stringify(CORE_MAJOR) "."
+		__stringify(CORE_MINOR) "."
+		__stringify(CORE_PATCHLEVEL) " "
+		CORE_DATE);
 
 /**
  * drm_sysfs_create - create a struct drm_sysfs_class structure
@@ -109,7 +107,7 @@
 	class->suspend = drm_class_suspend;
 	class->resume = drm_class_resume;
 
-	err = class_create_file(class, &class_attr_version);
+	err = class_create_file(class, &class_attr_version.attr);
 	if (err)
 		goto err_out_class;
 
@@ -132,7 +130,7 @@
 {
 	if ((drm_class == NULL) || (IS_ERR(drm_class)))
 		return;
-	class_remove_file(drm_class, &class_attr_version);
+	class_remove_file(drm_class, &class_attr_version.attr);
 	class_destroy(drm_class);
 }
 
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a894ade..1376dfe 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -162,7 +162,7 @@
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
-	if (!IS_IRONLAKE(dev)) {
+	if (!HAS_PCH_SPLIT(dev)) {
 		seq_printf(m, "Interrupt enable:    %08x\n",
 			   I915_READ(IER));
 		seq_printf(m, "Interrupt identity:  %08x\n",
@@ -350,6 +350,36 @@
 	return 0;
 }
 
+static const char *pin_flag(int pinned)
+{
+	if (pinned > 0)
+		return " P";
+	else if (pinned < 0)
+		return " p";
+	else
+		return "";
+}
+
+static const char *tiling_flag(int tiling)
+{
+	switch (tiling) {
+	default:
+	case I915_TILING_NONE: return "";
+	case I915_TILING_X: return " X";
+	case I915_TILING_Y: return " Y";
+	}
+}
+
+static const char *dirty_flag(int dirty)
+{
+	return dirty ? " dirty" : "";
+}
+
+static const char *purgeable_flag(int purgeable)
+{
+	return purgeable ? " purgeable" : "";
+}
+
 static int i915_error_state(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -357,6 +387,7 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_error_state *error;
 	unsigned long flags;
+	int i, page, offset, elt;
 
 	spin_lock_irqsave(&dev_priv->error_lock, flags);
 	if (!dev_priv->first_error) {
@@ -368,6 +399,7 @@
 
 	seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
 		   error->time.tv_usec);
+	seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
 	seq_printf(m, "EIR: 0x%08x\n", error->eir);
 	seq_printf(m, "  PGTBL_ER: 0x%08x\n", error->pgtbl_er);
 	seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm);
@@ -379,6 +411,59 @@
 		seq_printf(m, "  INSTPS: 0x%08x\n", error->instps);
 		seq_printf(m, "  INSTDONE1: 0x%08x\n", error->instdone1);
 	}
+	seq_printf(m, "seqno: 0x%08x\n", error->seqno);
+
+	if (error->active_bo_count) {
+		seq_printf(m, "Buffers [%d]:\n", error->active_bo_count);
+
+		for (i = 0; i < error->active_bo_count; i++) {
+			seq_printf(m, "  %08x %8zd %08x %08x %08x%s%s%s%s",
+				   error->active_bo[i].gtt_offset,
+				   error->active_bo[i].size,
+				   error->active_bo[i].read_domains,
+				   error->active_bo[i].write_domain,
+				   error->active_bo[i].seqno,
+				   pin_flag(error->active_bo[i].pinned),
+				   tiling_flag(error->active_bo[i].tiling),
+				   dirty_flag(error->active_bo[i].dirty),
+				   purgeable_flag(error->active_bo[i].purgeable));
+
+			if (error->active_bo[i].name)
+				seq_printf(m, " (name: %d)", error->active_bo[i].name);
+			if (error->active_bo[i].fence_reg != I915_FENCE_REG_NONE)
+				seq_printf(m, " (fence: %d)", error->active_bo[i].fence_reg);
+
+			seq_printf(m, "\n");
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) {
+		if (error->batchbuffer[i]) {
+			struct drm_i915_error_object *obj = error->batchbuffer[i];
+
+			seq_printf(m, "--- gtt_offset = 0x%08x\n", obj->gtt_offset);
+			offset = 0;
+			for (page = 0; page < obj->page_count; page++) {
+				for (elt = 0; elt < PAGE_SIZE/4; elt++) {
+					seq_printf(m, "%08x :  %08x\n", offset, obj->pages[page][elt]);
+					offset += 4;
+				}
+			}
+		}
+	}
+
+	if (error->ringbuffer) {
+		struct drm_i915_error_object *obj = error->ringbuffer;
+
+		seq_printf(m, "--- ringbuffer = 0x%08x\n", obj->gtt_offset);
+		offset = 0;
+		for (page = 0; page < obj->page_count; page++) {
+			for (elt = 0; elt < PAGE_SIZE/4; elt++) {
+				seq_printf(m, "%08x :  %08x\n", offset, obj->pages[page][elt]);
+				offset += 4;
+			}
+		}
+	}
 
 out:
 	spin_unlock_irqrestore(&dev_priv->error_lock, flags);
@@ -386,6 +471,165 @@
 	return 0;
 }
 
+static int i915_rstdby_delays(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u16 crstanddelay = I915_READ16(CRSTANDVID);
+
+	seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
+
+	return 0;
+}
+
+static int i915_cur_delayinfo(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u16 rgvswctl = I915_READ16(MEMSWCTL);
+
+	seq_printf(m, "Last command: 0x%01x\n", (rgvswctl >> 13) & 0x3);
+	seq_printf(m, "Command status: %d\n", (rgvswctl >> 12) & 1);
+	seq_printf(m, "P%d DELAY 0x%02x\n", (rgvswctl >> 8) & 0xf,
+		   rgvswctl & 0x3f);
+
+	return 0;
+}
+
+static int i915_delayfreq_table(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 delayfreq;
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
+		seq_printf(m, "P%02dVIDFREQ: 0x%08x\n", i, delayfreq);
+	}
+
+	return 0;
+}
+
+static inline int MAP_TO_MV(int map)
+{
+	return 1250 - (map * 25);
+}
+
+static int i915_inttoext_table(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 inttoext;
+	int i;
+
+	for (i = 1; i <= 32; i++) {
+		inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
+		seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
+	}
+
+	return 0;
+}
+
+static int i915_drpc_info(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 rgvmodectl = I915_READ(MEMMODECTL);
+
+	seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
+		   "yes" : "no");
+	seq_printf(m, "Boost freq: %d\n",
+		   (rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >>
+		   MEMMODE_BOOST_FREQ_SHIFT);
+	seq_printf(m, "HW control enabled: %s\n",
+		   rgvmodectl & MEMMODE_HWIDLE_EN ? "yes" : "no");
+	seq_printf(m, "SW control enabled: %s\n",
+		   rgvmodectl & MEMMODE_SWMODE_EN ? "yes" : "no");
+	seq_printf(m, "Gated voltage change: %s\n",
+		   rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no");
+	seq_printf(m, "Starting frequency: P%d\n",
+		   (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT);
+	seq_printf(m, "Max frequency: P%d\n",
+		   (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT);
+	seq_printf(m, "Min frequency: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
+
+	return 0;
+}
+
+static int i915_fbc_status(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_crtc *crtc;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	bool fbc_enabled = false;
+
+	if (!dev_priv->display.fbc_enabled) {
+		seq_printf(m, "FBC unsupported on this chipset\n");
+		return 0;
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (!crtc->enabled)
+			continue;
+		if (dev_priv->display.fbc_enabled(crtc))
+			fbc_enabled = true;
+	}
+
+	if (fbc_enabled) {
+		seq_printf(m, "FBC enabled\n");
+	} else {
+		seq_printf(m, "FBC disabled: ");
+		switch (dev_priv->no_fbc_reason) {
+		case FBC_STOLEN_TOO_SMALL:
+			seq_printf(m, "not enough stolen memory");
+			break;
+		case FBC_UNSUPPORTED_MODE:
+			seq_printf(m, "mode not supported");
+			break;
+		case FBC_MODE_TOO_LARGE:
+			seq_printf(m, "mode too large");
+			break;
+		case FBC_BAD_PLANE:
+			seq_printf(m, "FBC unsupported on plane");
+			break;
+		case FBC_NOT_TILED:
+			seq_printf(m, "scanout buffer not tiled");
+			break;
+		default:
+			seq_printf(m, "unknown reason");
+		}
+		seq_printf(m, "\n");
+	}
+	return 0;
+}
+
+static int i915_sr_status(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	bool sr_enabled = false;
+
+	if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev))
+		sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
+	else if (IS_I915GM(dev))
+		sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
+	else if (IS_PINEVIEW(dev))
+		sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
+
+	seq_printf(m, "self-refresh: %s\n", sr_enabled ? "enabled" :
+		   "disabled");
+
+	return 0;
+}
+
 static int
 i915_wedged_open(struct inode *inode,
 		 struct file *filp)
@@ -503,6 +747,13 @@
 	{"i915_ringbuffer_info", i915_ringbuffer_info, 0},
 	{"i915_batchbuffers", i915_batchbuffer_info, 0},
 	{"i915_error_state", i915_error_state, 0},
+	{"i915_rstdby_delays", i915_rstdby_delays, 0},
+	{"i915_cur_delayinfo", i915_cur_delayinfo, 0},
+	{"i915_delayfreq_table", i915_delayfreq_table, 0},
+	{"i915_inttoext_table", i915_inttoext_table, 0},
+	{"i915_drpc_info", i915_drpc_info, 0},
+	{"i915_fbc_status", i915_fbc_status, 0},
+	{"i915_sr_status", i915_sr_status, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 2307f98..8bfc0bb 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -35,6 +35,9 @@
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include <linux/vgaarb.h>
+#include <linux/acpi.h>
+#include <linux/pnp.h>
+#include <linux/vga_switcheroo.h>
 
 /* Really want an OS-independent resettable timer.  Would like to have
  * this loop run for (eg) 3 sec, but have the timer reset every time
@@ -933,6 +936,120 @@
 	return 0;
 }
 
+#define MCHBAR_I915 0x44
+#define MCHBAR_I965 0x48
+#define MCHBAR_SIZE (4*4096)
+
+#define DEVEN_REG 0x54
+#define   DEVEN_MCHBAR_EN (1 << 28)
+
+/* Allocate space for the MCH regs if needed, return nonzero on error */
+static int
+intel_alloc_mchbar_resource(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
+	u32 temp_lo, temp_hi = 0;
+	u64 mchbar_addr;
+	int ret = 0;
+
+	if (IS_I965G(dev))
+		pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
+	pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
+	mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
+
+	/* If ACPI doesn't have it, assume we need to allocate it ourselves */
+#ifdef CONFIG_PNP
+	if (mchbar_addr &&
+	    pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
+		ret = 0;
+		goto out;
+	}
+#endif
+
+	/* Get some space for it */
+	ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
+				     MCHBAR_SIZE, MCHBAR_SIZE,
+				     PCIBIOS_MIN_MEM,
+				     0,   pcibios_align_resource,
+				     dev_priv->bridge_dev);
+	if (ret) {
+		DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
+		dev_priv->mch_res.start = 0;
+		goto out;
+	}
+
+	if (IS_I965G(dev))
+		pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
+				       upper_32_bits(dev_priv->mch_res.start));
+
+	pci_write_config_dword(dev_priv->bridge_dev, reg,
+			       lower_32_bits(dev_priv->mch_res.start));
+out:
+	return ret;
+}
+
+/* Setup MCHBAR if possible, return true if we should disable it again */
+static void
+intel_setup_mchbar(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
+	u32 temp;
+	bool enabled;
+
+	dev_priv->mchbar_need_disable = false;
+
+	if (IS_I915G(dev) || IS_I915GM(dev)) {
+		pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
+		enabled = !!(temp & DEVEN_MCHBAR_EN);
+	} else {
+		pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
+		enabled = temp & 1;
+	}
+
+	/* If it's already enabled, don't have to do anything */
+	if (enabled)
+		return;
+
+	if (intel_alloc_mchbar_resource(dev))
+		return;
+
+	dev_priv->mchbar_need_disable = true;
+
+	/* Space is allocated or reserved, so enable it. */
+	if (IS_I915G(dev) || IS_I915GM(dev)) {
+		pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
+				       temp | DEVEN_MCHBAR_EN);
+	} else {
+		pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
+		pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
+	}
+}
+
+static void
+intel_teardown_mchbar(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
+	u32 temp;
+
+	if (dev_priv->mchbar_need_disable) {
+		if (IS_I915G(dev) || IS_I915GM(dev)) {
+			pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
+			temp &= ~DEVEN_MCHBAR_EN;
+			pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
+		} else {
+			pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
+			temp &= ~1;
+			pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
+		}
+	}
+
+	if (dev_priv->mch_res.start)
+		release_resource(&dev_priv->mch_res);
+}
+
 /**
  * i915_probe_agp - get AGP bootup configuration
  * @pdev: PCI device
@@ -978,59 +1095,123 @@
 	 * Some of the preallocated space is taken by the GTT
 	 * and popup.  GTT is 1K per MB of aperture size, and popup is 4K.
 	 */
-	if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev))
+	if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev))
 		overhead = 4096;
 	else
 		overhead = (*aperture_size / 1024) + 4096;
 
-	switch (tmp & INTEL_GMCH_GMS_MASK) {
-	case INTEL_855_GMCH_GMS_DISABLED:
-		DRM_ERROR("video memory is disabled\n");
-		return -1;
-	case INTEL_855_GMCH_GMS_STOLEN_1M:
-		stolen = 1 * 1024 * 1024;
-		break;
-	case INTEL_855_GMCH_GMS_STOLEN_4M:
-		stolen = 4 * 1024 * 1024;
-		break;
-	case INTEL_855_GMCH_GMS_STOLEN_8M:
-		stolen = 8 * 1024 * 1024;
-		break;
-	case INTEL_855_GMCH_GMS_STOLEN_16M:
-		stolen = 16 * 1024 * 1024;
-		break;
-	case INTEL_855_GMCH_GMS_STOLEN_32M:
-		stolen = 32 * 1024 * 1024;
-		break;
-	case INTEL_915G_GMCH_GMS_STOLEN_48M:
-		stolen = 48 * 1024 * 1024;
-		break;
-	case INTEL_915G_GMCH_GMS_STOLEN_64M:
-		stolen = 64 * 1024 * 1024;
-		break;
-	case INTEL_GMCH_GMS_STOLEN_128M:
-		stolen = 128 * 1024 * 1024;
-		break;
-	case INTEL_GMCH_GMS_STOLEN_256M:
-		stolen = 256 * 1024 * 1024;
-		break;
-	case INTEL_GMCH_GMS_STOLEN_96M:
-		stolen = 96 * 1024 * 1024;
-		break;
-	case INTEL_GMCH_GMS_STOLEN_160M:
-		stolen = 160 * 1024 * 1024;
-		break;
-	case INTEL_GMCH_GMS_STOLEN_224M:
-		stolen = 224 * 1024 * 1024;
-		break;
-	case INTEL_GMCH_GMS_STOLEN_352M:
-		stolen = 352 * 1024 * 1024;
-		break;
-	default:
-		DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
-			tmp & INTEL_GMCH_GMS_MASK);
-		return -1;
+	if (IS_GEN6(dev)) {
+		/* SNB has memory control reg at 0x50.w */
+		pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &tmp);
+
+		switch (tmp & SNB_GMCH_GMS_STOLEN_MASK) {
+		case INTEL_855_GMCH_GMS_DISABLED:
+			DRM_ERROR("video memory is disabled\n");
+			return -1;
+		case SNB_GMCH_GMS_STOLEN_32M:
+			stolen = 32 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_64M:
+			stolen = 64 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_96M:
+			stolen = 96 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_128M:
+			stolen = 128 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_160M:
+			stolen = 160 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_192M:
+			stolen = 192 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_224M:
+			stolen = 224 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_256M:
+			stolen = 256 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_288M:
+			stolen = 288 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_320M:
+			stolen = 320 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_352M:
+			stolen = 352 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_384M:
+			stolen = 384 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_416M:
+			stolen = 416 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_448M:
+			stolen = 448 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_480M:
+			stolen = 480 * 1024 * 1024;
+			break;
+		case SNB_GMCH_GMS_STOLEN_512M:
+			stolen = 512 * 1024 * 1024;
+			break;
+		default:
+			DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
+				  tmp & SNB_GMCH_GMS_STOLEN_MASK);
+			return -1;
+		}
+	} else {
+		switch (tmp & INTEL_GMCH_GMS_MASK) {
+		case INTEL_855_GMCH_GMS_DISABLED:
+			DRM_ERROR("video memory is disabled\n");
+			return -1;
+		case INTEL_855_GMCH_GMS_STOLEN_1M:
+			stolen = 1 * 1024 * 1024;
+			break;
+		case INTEL_855_GMCH_GMS_STOLEN_4M:
+			stolen = 4 * 1024 * 1024;
+			break;
+		case INTEL_855_GMCH_GMS_STOLEN_8M:
+			stolen = 8 * 1024 * 1024;
+			break;
+		case INTEL_855_GMCH_GMS_STOLEN_16M:
+			stolen = 16 * 1024 * 1024;
+			break;
+		case INTEL_855_GMCH_GMS_STOLEN_32M:
+			stolen = 32 * 1024 * 1024;
+			break;
+		case INTEL_915G_GMCH_GMS_STOLEN_48M:
+			stolen = 48 * 1024 * 1024;
+			break;
+		case INTEL_915G_GMCH_GMS_STOLEN_64M:
+			stolen = 64 * 1024 * 1024;
+			break;
+		case INTEL_GMCH_GMS_STOLEN_128M:
+			stolen = 128 * 1024 * 1024;
+			break;
+		case INTEL_GMCH_GMS_STOLEN_256M:
+			stolen = 256 * 1024 * 1024;
+			break;
+		case INTEL_GMCH_GMS_STOLEN_96M:
+			stolen = 96 * 1024 * 1024;
+			break;
+		case INTEL_GMCH_GMS_STOLEN_160M:
+			stolen = 160 * 1024 * 1024;
+			break;
+		case INTEL_GMCH_GMS_STOLEN_224M:
+			stolen = 224 * 1024 * 1024;
+			break;
+		case INTEL_GMCH_GMS_STOLEN_352M:
+			stolen = 352 * 1024 * 1024;
+			break;
+		default:
+			DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
+				  tmp & INTEL_GMCH_GMS_MASK);
+			return -1;
+		}
 	}
+
 	*preallocated_size = stolen - overhead;
 	*start = overhead;
 
@@ -1064,7 +1245,7 @@
 	int gtt_offset, gtt_size;
 
 	if (IS_I965G(dev)) {
-		if (IS_G4X(dev) || IS_IRONLAKE(dev)) {
+		if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
 			gtt_offset = 2*1024*1024;
 			gtt_size = 2*1024*1024;
 		} else {
@@ -1133,6 +1314,7 @@
 	/* Leave 1M for line length buffer & misc. */
 	compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0);
 	if (!compressed_fb) {
+		dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
 		i915_warn_stolen(dev);
 		return;
 	}
@@ -1140,6 +1322,7 @@
 	compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
 	if (!compressed_fb) {
 		i915_warn_stolen(dev);
+		dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
 		return;
 	}
 
@@ -1199,6 +1382,32 @@
 		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }
 
+static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
+	if (state == VGA_SWITCHEROO_ON) {
+		printk(KERN_INFO "i915: switched off\n");
+		/* i915 resume handler doesn't set to D0 */
+		pci_set_power_state(dev->pdev, PCI_D0);
+		i915_resume(dev);
+	} else {
+		printk(KERN_ERR "i915: switched off\n");
+		i915_suspend(dev, pmm);
+	}
+}
+
+static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	bool can_switch;
+
+	spin_lock(&dev->count_lock);
+	can_switch = (dev->open_count == 0);
+	spin_unlock(&dev->count_lock);
+	return can_switch;
+}
+
 static int i915_load_modeset_init(struct drm_device *dev,
 				  unsigned long prealloc_start,
 				  unsigned long prealloc_size,
@@ -1260,6 +1469,12 @@
 	if (ret)
 		goto destroy_ringbuffer;
 
+	ret = vga_switcheroo_register_client(dev->pdev,
+					     i915_switcheroo_set_state,
+					     i915_switcheroo_can_switch);
+	if (ret)
+		goto destroy_ringbuffer;
+
 	intel_modeset_init(dev);
 
 	ret = drm_irq_install(dev);
@@ -1281,7 +1496,9 @@
 	return 0;
 
 destroy_ringbuffer:
+	mutex_lock(&dev->struct_mutex);
 	i915_gem_cleanup_ringbuffer(dev);
+	mutex_unlock(&dev->struct_mutex);
 out:
 	return ret;
 }
@@ -1445,11 +1662,14 @@
 
 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
 	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
-	if (IS_G4X(dev) || IS_IRONLAKE(dev)) {
+	if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
 		dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
 		dev->driver->get_vblank_counter = gm45_get_vblank_counter;
 	}
 
+	/* Try to make sure MCHBAR is enabled before poking at it */
+	intel_setup_mchbar(dev);
+
 	i915_gem_load(dev);
 
 	/* Init HWS */
@@ -1523,6 +1743,8 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	i915_destroy_error_state(dev);
+
 	destroy_workqueue(dev_priv->wq);
 	del_timer_sync(&dev_priv->hangcheck_timer);
 
@@ -1544,6 +1766,7 @@
 			dev_priv->child_dev_num = 0;
 		}
 		drm_irq_uninstall(dev);
+		vga_switcheroo_unregister_client(dev->pdev);
 		vga_client_register(dev->pdev, NULL, NULL, NULL);
 	}
 
@@ -1569,6 +1792,8 @@
 		intel_cleanup_overlay(dev);
 	}
 
+	intel_teardown_mchbar(dev);
+
 	pci_dev_put(dev_priv->bridge_dev);
 	kfree(dev->dev_private);
 
@@ -1611,6 +1836,7 @@
 
 	if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
 		drm_fb_helper_restore();
+		vga_switcheroo_process_delayed_switch();
 		return;
 	}
 
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index cf4cb3e..1b2e954 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -49,6 +49,7 @@
 module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
 
 static struct drm_driver driver;
+extern int intel_agp_enabled;
 
 #define INTEL_VGA_DEVICE(id, info) {		\
 	.class = PCI_CLASS_DISPLAY_VGA << 8,	\
@@ -136,6 +137,16 @@
 	.has_hotplug = 1,
 };
 
+const static struct intel_device_info intel_sandybridge_d_info = {
+	.is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+	.has_hotplug = 1,
+};
+
+const static struct intel_device_info intel_sandybridge_m_info = {
+	.is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1,
+	.has_hotplug = 1,
+};
+
 const static struct pci_device_id pciidlist[] = {
 	INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
 	INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
@@ -167,6 +178,8 @@
 	INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
 	INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
 	INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
+	INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info),
+	INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info),
 	{0, 0, 0}
 };
 
@@ -201,7 +214,7 @@
 	return 0;
 }
 
-static int i915_suspend(struct drm_device *dev, pm_message_t state)
+int i915_suspend(struct drm_device *dev, pm_message_t state)
 {
 	int error;
 
@@ -255,7 +268,7 @@
 	return error;
 }
 
-static int i915_resume(struct drm_device *dev)
+int i915_resume(struct drm_device *dev)
 {
 	if (pci_enable_device(dev->pdev))
 		return -EIO;
@@ -546,6 +559,11 @@
 
 static int __init i915_init(void)
 {
+	if (!intel_agp_enabled) {
+		DRM_ERROR("drm/i915 can't work without intel_agp module!\n");
+		return -ENODEV;
+	}
+
 	driver.num_ioctls = i915_max_ioctl;
 
 	i915_gem_shrinker_init();
@@ -571,6 +589,11 @@
 		driver.driver_features &= ~DRIVER_MODESET;
 #endif
 
+	if (!(driver.driver_features & DRIVER_MODESET)) {
+		driver.suspend = i915_suspend;
+		driver.resume = i915_resume;
+	}
+
 	return drm_init(&driver);
 }
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b99b6a8..979439c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -150,7 +150,27 @@
 	u32 instps;
 	u32 instdone1;
 	u32 seqno;
+	u64 bbaddr;
 	struct timeval time;
+	struct drm_i915_error_object {
+		int page_count;
+		u32 gtt_offset;
+		u32 *pages[0];
+	} *ringbuffer, *batchbuffer[2];
+	struct drm_i915_error_buffer {
+		size_t size;
+		u32 name;
+		u32 seqno;
+		u32 gtt_offset;
+		u32 read_domains;
+		u32 write_domain;
+		u32 fence_reg;
+		s32 pinned:2;
+		u32 tiling:2;
+		u32 dirty:1;
+		u32 purgeable:1;
+	} *active_bo;
+	u32 active_bo_count;
 };
 
 struct drm_i915_display_funcs {
@@ -192,6 +212,14 @@
 	u8 cursor_needs_physical : 1;
 };
 
+enum no_fbc_reason {
+	FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */
+	FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
+	FBC_MODE_TOO_LARGE, /* mode too large for compression */
+	FBC_BAD_PLANE, /* fbc not supported on plane */
+	FBC_NOT_TILED, /* buffer not tiled */
+};
+
 typedef struct drm_i915_private {
 	struct drm_device *dev;
 
@@ -452,6 +480,7 @@
 	u32 savePIPEB_DATA_N1;
 	u32 savePIPEB_LINK_M1;
 	u32 savePIPEB_LINK_N1;
+	u32 saveMCHBAR_RENDER_STANDBY;
 
 	struct {
 		struct drm_mm gtt_space;
@@ -590,6 +619,14 @@
 	int child_dev_num;
 	struct child_device_config *child_dev;
 	struct drm_connector *int_lvds_connector;
+
+	bool mchbar_need_disable;
+
+	u8 cur_delay;
+	u8 min_delay;
+	u8 max_delay;
+
+	enum no_fbc_reason no_fbc_reason;
 } drm_i915_private_t;
 
 /** driver private structure attached to each drm_gem_object */
@@ -736,6 +773,8 @@
 extern unsigned int i915_powersave;
 extern unsigned int i915_lvds_downclock;
 
+extern int i915_suspend(struct drm_device *dev, pm_message_t state);
+extern int i915_resume(struct drm_device *dev);
 extern void i915_save_display(struct drm_device *dev);
 extern void i915_restore_display(struct drm_device *dev);
 extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
@@ -761,6 +800,7 @@
 
 /* i915_irq.c */
 void i915_hangcheck_elapsed(unsigned long data);
+void i915_destroy_error_state(struct drm_device *dev);
 extern int i915_irq_emit(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 extern int i915_irq_wait(struct drm_device *dev, void *data,
@@ -897,7 +937,8 @@
 void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj);
 bool i915_tiling_ok(struct drm_device *dev, int stride, int size,
 		    int tiling_mode);
-bool i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj);
+bool i915_gem_object_fence_offset_ok(struct drm_gem_object *obj,
+				     int tiling_mode);
 
 /* i915_gem_debug.c */
 void i915_gem_dump_object(struct drm_gem_object *obj, int len,
@@ -1026,7 +1067,7 @@
 #define IS_845G(dev)		((dev)->pci_device == 0x2562)
 #define IS_I85X(dev)		((dev)->pci_device == 0x3582)
 #define IS_I865G(dev)		((dev)->pci_device == 0x2572)
-#define IS_I8XX(dev)		(INTEL_INFO(dev)->is_i8xx)
+#define IS_GEN2(dev)		(INTEL_INFO(dev)->is_i8xx)
 #define IS_I915G(dev)		(INTEL_INFO(dev)->is_i915g)
 #define IS_I915GM(dev)		((dev)->pci_device == 0x2592)
 #define IS_I945G(dev)		((dev)->pci_device == 0x2772)
@@ -1045,8 +1086,29 @@
 #define IS_I9XX(dev)		(INTEL_INFO(dev)->is_i9xx)
 #define IS_MOBILE(dev)		(INTEL_INFO(dev)->is_mobile)
 
+#define IS_GEN3(dev)	(IS_I915G(dev) ||			\
+			 IS_I915GM(dev) ||			\
+			 IS_I945G(dev) ||			\
+			 IS_I945GM(dev) ||			\
+			 IS_G33(dev) || \
+			 IS_PINEVIEW(dev))
+#define IS_GEN4(dev)	((dev)->pci_device == 0x2972 ||		\
+			 (dev)->pci_device == 0x2982 ||		\
+			 (dev)->pci_device == 0x2992 ||		\
+			 (dev)->pci_device == 0x29A2 ||		\
+			 (dev)->pci_device == 0x2A02 ||		\
+			 (dev)->pci_device == 0x2A12 ||		\
+			 (dev)->pci_device == 0x2E02 ||		\
+			 (dev)->pci_device == 0x2E12 ||		\
+			 (dev)->pci_device == 0x2E22 ||		\
+			 (dev)->pci_device == 0x2E32 ||		\
+			 (dev)->pci_device == 0x2A42 ||		\
+			 (dev)->pci_device == 0x2E42)
+
 #define I915_NEED_GFX_HWS(dev)	(INTEL_INFO(dev)->need_gfx_hws)
 
+#define IS_GEN6(dev)	((dev)->pci_device == 0x0102)
+
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
  * rows, which changed the alignment requirements and fence programming.
  */
@@ -1067,6 +1129,9 @@
 #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
 #define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)
 
+#define HAS_PCH_SPLIT(dev) (IS_IRONLAKE(dev) ||	\
+			    IS_GEN6(dev))
+
 #define PRIMARY_RINGBUFFER_SIZE         (128*1024)
 
 #endif
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ec8a0d7..fba37e9 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -128,9 +128,7 @@
 		return -ENOMEM;
 
 	ret = drm_gem_handle_create(file_priv, obj, &handle);
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_handle_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_handle_unreference_unlocked(obj);
 
 	if (ret)
 		return ret;
@@ -488,7 +486,7 @@
 	 */
 	if (args->offset > obj->size || args->size > obj->size ||
 	    args->offset + args->size > obj->size) {
-		drm_gem_object_unreference(obj);
+		drm_gem_object_unreference_unlocked(obj);
 		return -EINVAL;
 	}
 
@@ -501,7 +499,7 @@
 							file_priv);
 	}
 
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference_unlocked(obj);
 
 	return ret;
 }
@@ -961,7 +959,7 @@
 	 */
 	if (args->offset > obj->size || args->size > obj->size ||
 	    args->offset + args->size > obj->size) {
-		drm_gem_object_unreference(obj);
+		drm_gem_object_unreference_unlocked(obj);
 		return -EINVAL;
 	}
 
@@ -995,7 +993,7 @@
 		DRM_INFO("pwrite failed %d\n", ret);
 #endif
 
-	drm_gem_object_unreference(obj);
+	drm_gem_object_unreference_unlocked(obj);
 
 	return ret;
 }
@@ -1138,9 +1136,7 @@
 		       PROT_READ | PROT_WRITE, MAP_SHARED,
 		       args->offset);
 	up_write(&current->mm->mmap_sem);
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(obj);
 	if (IS_ERR((void *)addr))
 		return addr;
 
@@ -1562,6 +1558,38 @@
 	i915_verify_inactive(dev, __FILE__, __LINE__);
 }
 
+static void
+i915_gem_process_flushing_list(struct drm_device *dev,
+			       uint32_t flush_domains, uint32_t seqno)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv, *next;
+
+	list_for_each_entry_safe(obj_priv, next,
+				 &dev_priv->mm.gpu_write_list,
+				 gpu_write_list) {
+		struct drm_gem_object *obj = obj_priv->obj;
+
+		if ((obj->write_domain & flush_domains) ==
+		    obj->write_domain) {
+			uint32_t old_write_domain = obj->write_domain;
+
+			obj->write_domain = 0;
+			list_del_init(&obj_priv->gpu_write_list);
+			i915_gem_object_move_to_active(obj, seqno);
+
+			/* update the fence lru list */
+			if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
+				list_move_tail(&obj_priv->fence_list,
+						&dev_priv->mm.fence_list);
+
+			trace_i915_gem_object_change_domain(obj,
+							    obj->read_domains,
+							    old_write_domain);
+		}
+	}
+}
+
 /**
  * Creates a new sequence number, emitting a write of it to the status page
  * plus an interrupt, which will trigger i915_user_interrupt_handler.
@@ -1620,29 +1648,8 @@
 	/* Associate any objects on the flushing list matching the write
 	 * domain we're flushing with our flush.
 	 */
-	if (flush_domains != 0) {
-		struct drm_i915_gem_object *obj_priv, *next;
-
-		list_for_each_entry_safe(obj_priv, next,
-					 &dev_priv->mm.gpu_write_list,
-					 gpu_write_list) {
-			struct drm_gem_object *obj = obj_priv->obj;
-
-			if ((obj->write_domain & flush_domains) ==
-			    obj->write_domain) {
-				uint32_t old_write_domain = obj->write_domain;
-
-				obj->write_domain = 0;
-				list_del_init(&obj_priv->gpu_write_list);
-				i915_gem_object_move_to_active(obj, seqno);
-
-				trace_i915_gem_object_change_domain(obj,
-								    obj->read_domains,
-								    old_write_domain);
-			}
-		}
-
-	}
+	if (flush_domains != 0) 
+		i915_gem_process_flushing_list(dev, flush_domains, seqno);
 
 	if (!dev_priv->mm.suspended) {
 		mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
@@ -1822,7 +1829,7 @@
 		return -EIO;
 
 	if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
-		if (IS_IRONLAKE(dev))
+		if (HAS_PCH_SPLIT(dev))
 			ier = I915_READ(DEIER) | I915_READ(GTIER);
 		else
 			ier = I915_READ(IER);
@@ -1991,6 +1998,7 @@
 i915_gem_object_unbind(struct drm_gem_object *obj)
 {
 	struct drm_device *dev = obj->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	int ret = 0;
 
@@ -2046,8 +2054,10 @@
 	}
 
 	/* Remove ourselves from the LRU list if present. */
+	spin_lock(&dev_priv->mm.active_list_lock);
 	if (!list_empty(&obj_priv->list))
 		list_del_init(&obj_priv->list);
+	spin_unlock(&dev_priv->mm.active_list_lock);
 
 	if (i915_gem_object_is_purgeable(obj_priv))
 		i915_gem_object_truncate(obj);
@@ -2085,11 +2095,34 @@
 }
 
 static int
+i915_gpu_idle(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	bool lists_empty;
+	uint32_t seqno;
+
+	spin_lock(&dev_priv->mm.active_list_lock);
+	lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
+		      list_empty(&dev_priv->mm.active_list);
+	spin_unlock(&dev_priv->mm.active_list_lock);
+
+	if (lists_empty)
+		return 0;
+
+	/* Flush everything onto the inactive list. */
+	i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+	seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
+	if (seqno == 0)
+		return -ENOMEM;
+
+	return i915_wait_request(dev, seqno);
+}
+
+static int
 i915_gem_evict_everything(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	int ret;
-	uint32_t seqno;
 	bool lists_empty;
 
 	spin_lock(&dev_priv->mm.active_list_lock);
@@ -2102,12 +2135,7 @@
 		return -ENOSPC;
 
 	/* Flush everything (on to the inactive lists) and evict */
-	i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
-	seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
-	if (seqno == 0)
-		return -ENOMEM;
-
-	ret = i915_wait_request(dev, seqno);
+	ret = i915_gpu_idle(dev);
 	if (ret)
 		return ret;
 
@@ -2265,6 +2293,28 @@
 	return 0;
 }
 
+static void sandybridge_write_fence_reg(struct drm_i915_fence_reg *reg)
+{
+	struct drm_gem_object *obj = reg->obj;
+	struct drm_device *dev = obj->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv = obj->driver_private;
+	int regnum = obj_priv->fence_reg;
+	uint64_t val;
+
+	val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) &
+		    0xfffff000) << 32;
+	val |= obj_priv->gtt_offset & 0xfffff000;
+	val |= (uint64_t)((obj_priv->stride / 128) - 1) <<
+		SANDYBRIDGE_FENCE_PITCH_SHIFT;
+
+	if (obj_priv->tiling_mode == I915_TILING_Y)
+		val |= 1 << I965_FENCE_TILING_Y_SHIFT;
+	val |= I965_FENCE_REG_VALID;
+
+	I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (regnum * 8), val);
+}
+
 static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
 {
 	struct drm_gem_object *obj = reg->obj;
@@ -2361,6 +2411,58 @@
 	I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
 }
 
+static int i915_find_fence_reg(struct drm_device *dev)
+{
+	struct drm_i915_fence_reg *reg = NULL;
+	struct drm_i915_gem_object *obj_priv = NULL;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_gem_object *obj = NULL;
+	int i, avail, ret;
+
+	/* First try to find a free reg */
+	avail = 0;
+	for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
+		reg = &dev_priv->fence_regs[i];
+		if (!reg->obj)
+			return i;
+
+		obj_priv = reg->obj->driver_private;
+		if (!obj_priv->pin_count)
+		    avail++;
+	}
+
+	if (avail == 0)
+		return -ENOSPC;
+
+	/* None available, try to steal one or wait for a user to finish */
+	i = I915_FENCE_REG_NONE;
+	list_for_each_entry(obj_priv, &dev_priv->mm.fence_list,
+			    fence_list) {
+		obj = obj_priv->obj;
+
+		if (obj_priv->pin_count)
+			continue;
+
+		/* found one! */
+		i = obj_priv->fence_reg;
+		break;
+	}
+
+	BUG_ON(i == I915_FENCE_REG_NONE);
+
+	/* We only have a reference on obj from the active list. put_fence_reg
+	 * might drop that one, causing a use-after-free in it. So hold a
+	 * private reference to obj like the other callers of put_fence_reg
+	 * (set_tiling ioctl) do. */
+	drm_gem_object_reference(obj);
+	ret = i915_gem_object_put_fence_reg(obj);
+	drm_gem_object_unreference(obj);
+	if (ret != 0)
+		return ret;
+
+	return i;
+}
+
 /**
  * i915_gem_object_get_fence_reg - set up a fence reg for an object
  * @obj: object to map through a fence reg
@@ -2381,8 +2483,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	struct drm_i915_fence_reg *reg = NULL;
-	struct drm_i915_gem_object *old_obj_priv = NULL;
-	int i, ret, avail;
+	int ret;
 
 	/* Just update our place in the LRU if our fence is getting used. */
 	if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
@@ -2410,86 +2511,27 @@
 		break;
 	}
 
-	/* First try to find a free reg */
-	avail = 0;
-	for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
-		reg = &dev_priv->fence_regs[i];
-		if (!reg->obj)
-			break;
+	ret = i915_find_fence_reg(dev);
+	if (ret < 0)
+		return ret;
 
-		old_obj_priv = reg->obj->driver_private;
-		if (!old_obj_priv->pin_count)
-		    avail++;
-	}
-
-	/* None available, try to steal one or wait for a user to finish */
-	if (i == dev_priv->num_fence_regs) {
-		struct drm_gem_object *old_obj = NULL;
-
-		if (avail == 0)
-			return -ENOSPC;
-
-		list_for_each_entry(old_obj_priv, &dev_priv->mm.fence_list,
-				    fence_list) {
-			old_obj = old_obj_priv->obj;
-
-			if (old_obj_priv->pin_count)
-				continue;
-
-			/* Take a reference, as otherwise the wait_rendering
-			 * below may cause the object to get freed out from
-			 * under us.
-			 */
-			drm_gem_object_reference(old_obj);
-
-			/* i915 uses fences for GPU access to tiled buffers */
-			if (IS_I965G(dev) || !old_obj_priv->active)
-				break;
-
-			/* This brings the object to the head of the LRU if it
-			 * had been written to.  The only way this should
-			 * result in us waiting longer than the expected
-			 * optimal amount of time is if there was a
-			 * fence-using buffer later that was read-only.
-			 */
-			i915_gem_object_flush_gpu_write_domain(old_obj);
-			ret = i915_gem_object_wait_rendering(old_obj);
-			if (ret != 0) {
-				drm_gem_object_unreference(old_obj);
-				return ret;
-			}
-
-			break;
-		}
-
-		/*
-		 * Zap this virtual mapping so we can set up a fence again
-		 * for this object next time we need it.
-		 */
-		i915_gem_release_mmap(old_obj);
-
-		i = old_obj_priv->fence_reg;
-		reg = &dev_priv->fence_regs[i];
-
-		old_obj_priv->fence_reg = I915_FENCE_REG_NONE;
-		list_del_init(&old_obj_priv->fence_list);
-
-		drm_gem_object_unreference(old_obj);
-	}
-
-	obj_priv->fence_reg = i;
+	obj_priv->fence_reg = ret;
+	reg = &dev_priv->fence_regs[obj_priv->fence_reg];
 	list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
 
 	reg->obj = obj;
 
-	if (IS_I965G(dev))
+	if (IS_GEN6(dev))
+		sandybridge_write_fence_reg(reg);
+	else if (IS_I965G(dev))
 		i965_write_fence_reg(reg);
 	else if (IS_I9XX(dev))
 		i915_write_fence_reg(reg);
 	else
 		i830_write_fence_reg(reg);
 
-	trace_i915_gem_object_get_fence(obj, i, obj_priv->tiling_mode);
+	trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg,
+			obj_priv->tiling_mode);
 
 	return 0;
 }
@@ -2508,9 +2550,12 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 
-	if (IS_I965G(dev))
+	if (IS_GEN6(dev)) {
+		I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 +
+			     (obj_priv->fence_reg * 8), 0);
+	} else if (IS_I965G(dev)) {
 		I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
-	else {
+	} else {
 		uint32_t fence_reg;
 
 		if (obj_priv->fence_reg < 8)
@@ -2544,6 +2589,12 @@
 	if (obj_priv->fence_reg == I915_FENCE_REG_NONE)
 		return 0;
 
+	/* If we've changed tiling, GTT-mappings of the object
+	 * need to re-fault to ensure that the correct fence register
+	 * setup is in place.
+	 */
+	i915_gem_release_mmap(obj);
+
 	/* On the i915, GPU access to tiled buffers is via a fence,
 	 * therefore we must wait for any outstanding access to complete
 	 * before clearing the fence.
@@ -2552,12 +2603,12 @@
 		int ret;
 
 		i915_gem_object_flush_gpu_write_domain(obj);
-		i915_gem_object_flush_gtt_write_domain(obj);
 		ret = i915_gem_object_wait_rendering(obj);
 		if (ret != 0)
 			return ret;
 	}
 
+	i915_gem_object_flush_gtt_write_domain(obj);
 	i915_gem_clear_fence_reg (obj);
 
 	return 0;
@@ -2697,7 +2748,6 @@
 i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
 {
 	struct drm_device *dev = obj->dev;
-	uint32_t seqno;
 	uint32_t old_write_domain;
 
 	if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
@@ -2706,9 +2756,8 @@
 	/* Queue the GPU write cache flushing we need. */
 	old_write_domain = obj->write_domain;
 	i915_gem_flush(dev, 0, obj->write_domain);
-	seqno = i915_add_request(dev, NULL, obj->write_domain);
+	(void) i915_add_request(dev, NULL, obj->write_domain);
 	BUG_ON(obj->write_domain);
-	i915_gem_object_move_to_active(obj, seqno);
 
 	trace_i915_gem_object_change_domain(obj,
 					    obj->read_domains,
@@ -3247,7 +3296,8 @@
 	             obj_priv->tiling_mode != I915_TILING_NONE;
 
 	/* Check fence reg constraints and rebind if necessary */
-	if (need_fence && !i915_obj_fenceable(dev, obj))
+	if (need_fence && !i915_gem_object_fence_offset_ok(obj,
+	    obj_priv->tiling_mode))
 		i915_gem_object_unbind(obj);
 
 	/* Choose the GTT offset for our buffer and put it there. */
@@ -3317,6 +3367,16 @@
 		}
 
 		/* Validate that the target is in a valid r/w GPU domain */
+		if (reloc->write_domain & (reloc->write_domain - 1)) {
+			DRM_ERROR("reloc with multiple write domains: "
+				  "obj %p target %d offset %d "
+				  "read %08x write %08x",
+				  obj, reloc->target_handle,
+				  (int) reloc->offset,
+				  reloc->read_domains,
+				  reloc->write_domain);
+			return -EINVAL;
+		}
 		if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
 		    reloc->read_domains & I915_GEM_DOMAIN_CPU) {
 			DRM_ERROR("reloc with read/write CPU domains: "
@@ -4445,8 +4505,7 @@
 i915_gem_idle(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t seqno, cur_seqno, last_seqno;
-	int stuck, ret;
+	int ret;
 
 	mutex_lock(&dev->struct_mutex);
 
@@ -4455,115 +4514,36 @@
 		return 0;
 	}
 
-	/* Hack!  Don't let anybody do execbuf while we don't control the chip.
-	 * We need to replace this with a semaphore, or something.
-	 */
-	dev_priv->mm.suspended = 1;
-	del_timer(&dev_priv->hangcheck_timer);
-
-	/* Cancel the retire work handler, wait for it to finish if running
-	 */
-	mutex_unlock(&dev->struct_mutex);
-	cancel_delayed_work_sync(&dev_priv->mm.retire_work);
-	mutex_lock(&dev->struct_mutex);
-
-	i915_kernel_lost_context(dev);
-
-	/* Flush the GPU along with all non-CPU write domains
-	 */
-	i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
-	seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
-
-	if (seqno == 0) {
-		mutex_unlock(&dev->struct_mutex);
-		return -ENOMEM;
-	}
-
-	dev_priv->mm.waiting_gem_seqno = seqno;
-	last_seqno = 0;
-	stuck = 0;
-	for (;;) {
-		cur_seqno = i915_get_gem_seqno(dev);
-		if (i915_seqno_passed(cur_seqno, seqno))
-			break;
-		if (last_seqno == cur_seqno) {
-			if (stuck++ > 100) {
-				DRM_ERROR("hardware wedged\n");
-				atomic_set(&dev_priv->mm.wedged, 1);
-				DRM_WAKEUP(&dev_priv->irq_queue);
-				break;
-			}
-		}
-		msleep(10);
-		last_seqno = cur_seqno;
-	}
-	dev_priv->mm.waiting_gem_seqno = 0;
-
-	i915_gem_retire_requests(dev);
-
-	spin_lock(&dev_priv->mm.active_list_lock);
-	if (!atomic_read(&dev_priv->mm.wedged)) {
-		/* Active and flushing should now be empty as we've
-		 * waited for a sequence higher than any pending execbuffer
-		 */
-		WARN_ON(!list_empty(&dev_priv->mm.active_list));
-		WARN_ON(!list_empty(&dev_priv->mm.flushing_list));
-		/* Request should now be empty as we've also waited
-		 * for the last request in the list
-		 */
-		WARN_ON(!list_empty(&dev_priv->mm.request_list));
-	}
-
-	/* Empty the active and flushing lists to inactive.  If there's
-	 * anything left at this point, it means that we're wedged and
-	 * nothing good's going to happen by leaving them there.  So strip
-	 * the GPU domains and just stuff them onto inactive.
-	 */
-	while (!list_empty(&dev_priv->mm.active_list)) {
-		struct drm_gem_object *obj;
-		uint32_t old_write_domain;
-
-		obj = list_first_entry(&dev_priv->mm.active_list,
-				       struct drm_i915_gem_object,
-				       list)->obj;
-		old_write_domain = obj->write_domain;
-		obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
-		i915_gem_object_move_to_inactive(obj);
-
-		trace_i915_gem_object_change_domain(obj,
-						    obj->read_domains,
-						    old_write_domain);
-	}
-	spin_unlock(&dev_priv->mm.active_list_lock);
-
-	while (!list_empty(&dev_priv->mm.flushing_list)) {
-		struct drm_gem_object *obj;
-		uint32_t old_write_domain;
-
-		obj = list_first_entry(&dev_priv->mm.flushing_list,
-				       struct drm_i915_gem_object,
-				       list)->obj;
-		old_write_domain = obj->write_domain;
-		obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
-		i915_gem_object_move_to_inactive(obj);
-
-		trace_i915_gem_object_change_domain(obj,
-						    obj->read_domains,
-						    old_write_domain);
-	}
-
-
-	/* Move all inactive buffers out of the GTT. */
-	ret = i915_gem_evict_from_inactive_list(dev);
-	WARN_ON(!list_empty(&dev_priv->mm.inactive_list));
+	ret = i915_gpu_idle(dev);
 	if (ret) {
 		mutex_unlock(&dev->struct_mutex);
 		return ret;
 	}
 
+	/* Under UMS, be paranoid and evict. */
+	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
+		ret = i915_gem_evict_from_inactive_list(dev);
+		if (ret) {
+			mutex_unlock(&dev->struct_mutex);
+			return ret;
+		}
+	}
+
+	/* Hack!  Don't let anybody do execbuf while we don't control the chip.
+	 * We need to replace this with a semaphore, or something.
+	 * And not confound mm.suspended!
+	 */
+	dev_priv->mm.suspended = 1;
+	del_timer(&dev_priv->hangcheck_timer);
+
+	i915_kernel_lost_context(dev);
 	i915_gem_cleanup_ringbuffer(dev);
+
 	mutex_unlock(&dev->struct_mutex);
 
+	/* Cancel the retire work handler, which should be idle now. */
+	cancel_delayed_work_sync(&dev_priv->mm.retire_work);
+
 	return 0;
 }
 
@@ -4607,8 +4587,13 @@
 	}
 	dev_priv->hws_obj = obj;
 	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-	I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
-	I915_READ(HWS_PGA); /* posting read */
+	if (IS_GEN6(dev)) {
+		I915_WRITE(HWS_PGA_GEN6, dev_priv->status_gfx_addr);
+		I915_READ(HWS_PGA_GEN6); /* posting read */
+	} else {
+		I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
+		I915_READ(HWS_PGA); /* posting read */
+	}
 	DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
 
 	return 0;
@@ -4850,7 +4835,8 @@
 	spin_unlock(&shrink_list_lock);
 
 	/* Old X drivers will take 0-2 for front, back, depth buffers */
-	dev_priv->fence_reg_start = 3;
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		dev_priv->fence_reg_start = 3;
 
 	if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
 		dev_priv->num_fence_regs = 16;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index df278b2..b5c55d8 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -25,8 +25,6 @@
  *
  */
 
-#include <linux/acpi.h>
-#include <linux/pnp.h>
 #include "linux/string.h"
 #include "linux/bitops.h"
 #include "drmP.h"
@@ -83,120 +81,6 @@
  * to match what the GPU expects.
  */
 
-#define MCHBAR_I915 0x44
-#define MCHBAR_I965 0x48
-#define MCHBAR_SIZE (4*4096)
-
-#define DEVEN_REG 0x54
-#define   DEVEN_MCHBAR_EN (1 << 28)
-
-/* Allocate space for the MCH regs if needed, return nonzero on error */
-static int
-intel_alloc_mchbar_resource(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
-	u32 temp_lo, temp_hi = 0;
-	u64 mchbar_addr;
-	int ret = 0;
-
-	if (IS_I965G(dev))
-		pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
-	pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
-	mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
-
-	/* If ACPI doesn't have it, assume we need to allocate it ourselves */
-#ifdef CONFIG_PNP
-	if (mchbar_addr &&
-	    pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
-		ret = 0;
-		goto out;
-	}
-#endif
-
-	/* Get some space for it */
-	ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
-				     MCHBAR_SIZE, MCHBAR_SIZE,
-				     PCIBIOS_MIN_MEM,
-				     0,   pcibios_align_resource,
-				     dev_priv->bridge_dev);
-	if (ret) {
-		DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
-		dev_priv->mch_res.start = 0;
-		goto out;
-	}
-
-	if (IS_I965G(dev))
-		pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
-				       upper_32_bits(dev_priv->mch_res.start));
-
-	pci_write_config_dword(dev_priv->bridge_dev, reg,
-			       lower_32_bits(dev_priv->mch_res.start));
-out:
-	return ret;
-}
-
-/* Setup MCHBAR if possible, return true if we should disable it again */
-static bool
-intel_setup_mchbar(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
-	u32 temp;
-	bool need_disable = false, enabled;
-
-	if (IS_I915G(dev) || IS_I915GM(dev)) {
-		pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
-		enabled = !!(temp & DEVEN_MCHBAR_EN);
-	} else {
-		pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
-		enabled = temp & 1;
-	}
-
-	/* If it's already enabled, don't have to do anything */
-	if (enabled)
-		goto out;
-
-	if (intel_alloc_mchbar_resource(dev))
-		goto out;
-
-	need_disable = true;
-
-	/* Space is allocated or reserved, so enable it. */
-	if (IS_I915G(dev) || IS_I915GM(dev)) {
-		pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
-				       temp | DEVEN_MCHBAR_EN);
-	} else {
-		pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
-		pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
-	}
-out:
-	return need_disable;
-}
-
-static void
-intel_teardown_mchbar(struct drm_device *dev, bool disable)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
-	u32 temp;
-
-	if (disable) {
-		if (IS_I915G(dev) || IS_I915GM(dev)) {
-			pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
-			temp &= ~DEVEN_MCHBAR_EN;
-			pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
-		} else {
-			pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
-			temp &= ~1;
-			pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
-		}
-	}
-
-	if (dev_priv->mch_res.start)
-		release_resource(&dev_priv->mch_res);
-}
-
 /**
  * Detects bit 6 swizzling of address lookup between IGD access and CPU
  * access through main memory.
@@ -207,9 +91,8 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
 	uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-	bool need_disable;
 
-	if (IS_IRONLAKE(dev)) {
+	if (IS_IRONLAKE(dev) || IS_GEN6(dev)) {
 		/* On Ironlake whatever DRAM config, GPU always do
 		 * same swizzling setup.
 		 */
@@ -224,9 +107,6 @@
 	} else if (IS_MOBILE(dev)) {
 		uint32_t dcc;
 
-		/* Try to make sure MCHBAR is enabled before poking at it */
-		need_disable = intel_setup_mchbar(dev);
-
 		/* On mobile 9xx chipsets, channel interleave by the CPU is
 		 * determined by DCC.  For single-channel, neither the CPU
 		 * nor the GPU do swizzling.  For dual channel interleaved,
@@ -266,8 +146,6 @@
 			swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
 			swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
 		}
-
-		intel_teardown_mchbar(dev, need_disable);
 	} else {
 		/* The 965, G33, and newer, have a very flexible memory
 		 * configuration.  It will enable dual-channel mode
@@ -302,39 +180,6 @@
 	dev_priv->mm.bit_6_swizzle_y = swizzle_y;
 }
 
-
-/**
- * Returns whether an object is currently fenceable.  If not, it may need
- * to be unbound and have its pitch adjusted.
- */
-bool
-i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj)
-{
-	struct drm_i915_gem_object *obj_priv = obj->driver_private;
-
-	if (IS_I965G(dev)) {
-		/* The 965 can have fences at any page boundary. */
-		if (obj->size & 4095)
-			return false;
-		return true;
-	} else if (IS_I9XX(dev)) {
-		if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
-			return false;
-	} else {
-		if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
-			return false;
-	}
-
-	/* Power of two sized... */
-	if (obj->size & (obj->size - 1))
-		return false;
-
-	/* Objects must be size aligned as well */
-	if (obj_priv->gtt_offset & (obj->size - 1))
-		return false;
-	return true;
-}
-
 /* Check pitch constriants for all chips & tiling formats */
 bool
 i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
@@ -391,7 +236,7 @@
 	return true;
 }
 
-static bool
+bool
 i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
 {
 	struct drm_device *dev = obj->dev;
@@ -438,9 +283,7 @@
 	obj_priv = obj->driver_private;
 
 	if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
-		mutex_lock(&dev->struct_mutex);
-		drm_gem_object_unreference(obj);
-		mutex_unlock(&dev->struct_mutex);
+		drm_gem_object_unreference_unlocked(obj);
 		return -EINVAL;
 	}
 
@@ -493,12 +336,6 @@
 			goto err;
 		}
 
-		/* If we've changed tiling, GTT-mappings of the object
-		 * need to re-fault to ensure that the correct fence register
-		 * setup is in place.
-		 */
-		i915_gem_release_mmap(obj);
-
 		obj_priv->tiling_mode = args->tiling_mode;
 		obj_priv->stride = args->stride;
 	}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index a17d6bdf..5388354 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -166,7 +166,7 @@
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		ironlake_enable_display_irq(dev_priv, DE_GSE);
 	else
 		i915_enable_pipestat(dev_priv, 1,
@@ -269,6 +269,57 @@
 	drm_sysfs_hotplug_event(dev);
 }
 
+static void i915_handle_rps_change(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 busy_up, busy_down, max_avg, min_avg;
+	u16 rgvswctl;
+	u8 new_delay = dev_priv->cur_delay;
+
+	I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS) & ~MEMINT_EVAL_CHG);
+	busy_up = I915_READ(RCPREVBSYTUPAVG);
+	busy_down = I915_READ(RCPREVBSYTDNAVG);
+	max_avg = I915_READ(RCBMAXAVG);
+	min_avg = I915_READ(RCBMINAVG);
+
+	/* Handle RCS change request from hw */
+	if (busy_up > max_avg) {
+		if (dev_priv->cur_delay != dev_priv->max_delay)
+			new_delay = dev_priv->cur_delay - 1;
+		if (new_delay < dev_priv->max_delay)
+			new_delay = dev_priv->max_delay;
+	} else if (busy_down < min_avg) {
+		if (dev_priv->cur_delay != dev_priv->min_delay)
+			new_delay = dev_priv->cur_delay + 1;
+		if (new_delay > dev_priv->min_delay)
+			new_delay = dev_priv->min_delay;
+	}
+
+	DRM_DEBUG("rps change requested: %d -> %d\n",
+		  dev_priv->cur_delay, new_delay);
+
+	rgvswctl = I915_READ(MEMSWCTL);
+	if (rgvswctl & MEMCTL_CMD_STS) {
+		DRM_ERROR("gpu busy, RCS change rejected\n");
+		return; /* still busy with another command */
+	}
+
+	/* Program the new state */
+	rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
+		(new_delay << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
+	I915_WRITE(MEMSWCTL, rgvswctl);
+	POSTING_READ(MEMSWCTL);
+
+	rgvswctl |= MEMCTL_CMD_STS;
+	I915_WRITE(MEMSWCTL, rgvswctl);
+
+	dev_priv->cur_delay = new_delay;
+
+	DRM_DEBUG("rps changed\n");
+
+	return;
+}
+
 irqreturn_t ironlake_irq_handler(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -331,6 +382,11 @@
 		queue_work(dev_priv->wq, &dev_priv->hotplug_work);
 	}
 
+	if (de_iir & DE_PCU_EVENT) {
+		I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS));
+		i915_handle_rps_change(dev);
+	}
+
 	/* should clear PCH hotplug event before clear CPU irq */
 	I915_WRITE(SDEIIR, pch_iir);
 	I915_WRITE(GTIIR, gt_iir);
@@ -376,6 +432,121 @@
 	}
 }
 
+static struct drm_i915_error_object *
+i915_error_object_create(struct drm_device *dev,
+			 struct drm_gem_object *src)
+{
+	struct drm_i915_error_object *dst;
+	struct drm_i915_gem_object *src_priv;
+	int page, page_count;
+
+	if (src == NULL)
+		return NULL;
+
+	src_priv = src->driver_private;
+	if (src_priv->pages == NULL)
+		return NULL;
+
+	page_count = src->size / PAGE_SIZE;
+
+	dst = kmalloc(sizeof(*dst) + page_count * sizeof (u32 *), GFP_ATOMIC);
+	if (dst == NULL)
+		return NULL;
+
+	for (page = 0; page < page_count; page++) {
+		void *s, *d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
+		if (d == NULL)
+			goto unwind;
+		s = kmap_atomic(src_priv->pages[page], KM_USER0);
+		memcpy(d, s, PAGE_SIZE);
+		kunmap_atomic(s, KM_USER0);
+		dst->pages[page] = d;
+	}
+	dst->page_count = page_count;
+	dst->gtt_offset = src_priv->gtt_offset;
+
+	return dst;
+
+unwind:
+	while (page--)
+		kfree(dst->pages[page]);
+	kfree(dst);
+	return NULL;
+}
+
+static void
+i915_error_object_free(struct drm_i915_error_object *obj)
+{
+	int page;
+
+	if (obj == NULL)
+		return;
+
+	for (page = 0; page < obj->page_count; page++)
+		kfree(obj->pages[page]);
+
+	kfree(obj);
+}
+
+static void
+i915_error_state_free(struct drm_device *dev,
+		      struct drm_i915_error_state *error)
+{
+	i915_error_object_free(error->batchbuffer[0]);
+	i915_error_object_free(error->batchbuffer[1]);
+	i915_error_object_free(error->ringbuffer);
+	kfree(error->active_bo);
+	kfree(error);
+}
+
+static u32
+i915_get_bbaddr(struct drm_device *dev, u32 *ring)
+{
+	u32 cmd;
+
+	if (IS_I830(dev) || IS_845G(dev))
+		cmd = MI_BATCH_BUFFER;
+	else if (IS_I965G(dev))
+		cmd = (MI_BATCH_BUFFER_START | (2 << 6) |
+		       MI_BATCH_NON_SECURE_I965);
+	else
+		cmd = (MI_BATCH_BUFFER_START | (2 << 6));
+
+	return ring[0] == cmd ? ring[1] : 0;
+}
+
+static u32
+i915_ringbuffer_last_batch(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 head, bbaddr;
+	u32 *ring;
+
+	/* Locate the current position in the ringbuffer and walk back
+	 * to find the most recently dispatched batch buffer.
+	 */
+	bbaddr = 0;
+	head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
+	ring = (u32 *)(dev_priv->ring.virtual_start + head);
+
+	while (--ring >= (u32 *)dev_priv->ring.virtual_start) {
+		bbaddr = i915_get_bbaddr(dev, ring);
+		if (bbaddr)
+			break;
+	}
+
+	if (bbaddr == 0) {
+		ring = (u32 *)(dev_priv->ring.virtual_start + dev_priv->ring.Size);
+		while (--ring >= (u32 *)dev_priv->ring.virtual_start) {
+			bbaddr = i915_get_bbaddr(dev, ring);
+			if (bbaddr)
+				break;
+		}
+	}
+
+	return bbaddr;
+}
+
 /**
  * i915_capture_error_state - capture an error record for later analysis
  * @dev: drm device
@@ -388,19 +559,26 @@
 static void i915_capture_error_state(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj_priv;
 	struct drm_i915_error_state *error;
+	struct drm_gem_object *batchbuffer[2];
 	unsigned long flags;
+	u32 bbaddr;
+	int count;
 
 	spin_lock_irqsave(&dev_priv->error_lock, flags);
-	if (dev_priv->first_error)
-		goto out;
+	error = dev_priv->first_error;
+	spin_unlock_irqrestore(&dev_priv->error_lock, flags);
+	if (error)
+		return;
 
 	error = kmalloc(sizeof(*error), GFP_ATOMIC);
 	if (!error) {
-		DRM_DEBUG_DRIVER("out ot memory, not capturing error state\n");
-		goto out;
+		DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
+		return;
 	}
 
+	error->seqno = i915_get_gem_seqno(dev);
 	error->eir = I915_READ(EIR);
 	error->pgtbl_er = I915_READ(PGTBL_ER);
 	error->pipeastat = I915_READ(PIPEASTAT);
@@ -411,6 +589,7 @@
 		error->ipehr = I915_READ(IPEHR);
 		error->instdone = I915_READ(INSTDONE);
 		error->acthd = I915_READ(ACTHD);
+		error->bbaddr = 0;
 	} else {
 		error->ipeir = I915_READ(IPEIR_I965);
 		error->ipehr = I915_READ(IPEHR_I965);
@@ -418,14 +597,101 @@
 		error->instps = I915_READ(INSTPS);
 		error->instdone1 = I915_READ(INSTDONE1);
 		error->acthd = I915_READ(ACTHD_I965);
+		error->bbaddr = I915_READ64(BB_ADDR);
+	}
+
+	bbaddr = i915_ringbuffer_last_batch(dev);
+
+	/* Grab the current batchbuffer, most likely to have crashed. */
+	batchbuffer[0] = NULL;
+	batchbuffer[1] = NULL;
+	count = 0;
+	list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
+		struct drm_gem_object *obj = obj_priv->obj;
+
+		if (batchbuffer[0] == NULL &&
+		    bbaddr >= obj_priv->gtt_offset &&
+		    bbaddr < obj_priv->gtt_offset + obj->size)
+			batchbuffer[0] = obj;
+
+		if (batchbuffer[1] == NULL &&
+		    error->acthd >= obj_priv->gtt_offset &&
+		    error->acthd < obj_priv->gtt_offset + obj->size &&
+		    batchbuffer[0] != obj)
+			batchbuffer[1] = obj;
+
+		count++;
+	}
+
+	/* We need to copy these to an anonymous buffer as the simplest
+	 * method to avoid being overwritten by userpace.
+	 */
+	error->batchbuffer[0] = i915_error_object_create(dev, batchbuffer[0]);
+	error->batchbuffer[1] = i915_error_object_create(dev, batchbuffer[1]);
+
+	/* Record the ringbuffer */
+	error->ringbuffer = i915_error_object_create(dev, dev_priv->ring.ring_obj);
+
+	/* Record buffers on the active list. */
+	error->active_bo = NULL;
+	error->active_bo_count = 0;
+
+	if (count)
+		error->active_bo = kmalloc(sizeof(*error->active_bo)*count,
+					   GFP_ATOMIC);
+
+	if (error->active_bo) {
+		int i = 0;
+		list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
+			struct drm_gem_object *obj = obj_priv->obj;
+
+			error->active_bo[i].size = obj->size;
+			error->active_bo[i].name = obj->name;
+			error->active_bo[i].seqno = obj_priv->last_rendering_seqno;
+			error->active_bo[i].gtt_offset = obj_priv->gtt_offset;
+			error->active_bo[i].read_domains = obj->read_domains;
+			error->active_bo[i].write_domain = obj->write_domain;
+			error->active_bo[i].fence_reg = obj_priv->fence_reg;
+			error->active_bo[i].pinned = 0;
+			if (obj_priv->pin_count > 0)
+				error->active_bo[i].pinned = 1;
+			if (obj_priv->user_pin_count > 0)
+				error->active_bo[i].pinned = -1;
+			error->active_bo[i].tiling = obj_priv->tiling_mode;
+			error->active_bo[i].dirty = obj_priv->dirty;
+			error->active_bo[i].purgeable = obj_priv->madv != I915_MADV_WILLNEED;
+
+			if (++i == count)
+				break;
+		}
+		error->active_bo_count = i;
 	}
 
 	do_gettimeofday(&error->time);
 
-	dev_priv->first_error = error;
-
-out:
+	spin_lock_irqsave(&dev_priv->error_lock, flags);
+	if (dev_priv->first_error == NULL) {
+		dev_priv->first_error = error;
+		error = NULL;
+	}
 	spin_unlock_irqrestore(&dev_priv->error_lock, flags);
+
+	if (error)
+		i915_error_state_free(dev, error);
+}
+
+void i915_destroy_error_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_error_state *error;
+
+	spin_lock(&dev_priv->error_lock);
+	error = dev_priv->first_error;
+	dev_priv->first_error = NULL;
+	spin_unlock(&dev_priv->error_lock);
+
+	if (error)
+		i915_error_state_free(dev, error);
 }
 
 /**
@@ -576,7 +842,7 @@
 
 	atomic_inc(&dev_priv->irq_received);
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		return ironlake_irq_handler(dev);
 
 	iir = I915_READ(IIR);
@@ -737,7 +1003,7 @@
 
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
 	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
-		if (IS_IRONLAKE(dev))
+		if (HAS_PCH_SPLIT(dev))
 			ironlake_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
 		else
 			i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
@@ -753,7 +1019,7 @@
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
 	BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
 	if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
-		if (IS_IRONLAKE(dev))
+		if (HAS_PCH_SPLIT(dev))
 			ironlake_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
 		else
 			i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
@@ -861,7 +1127,7 @@
 		return -EINVAL;
 
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		ironlake_enable_display_irq(dev_priv, (pipe == 0) ? 
 					    DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
 	else if (IS_I965G(dev))
@@ -883,7 +1149,7 @@
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		ironlake_disable_display_irq(dev_priv, (pipe == 0) ? 
 					     DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
 	else
@@ -897,7 +1163,7 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (!IS_IRONLAKE(dev))
+	if (!HAS_PCH_SPLIT(dev))
 		opregion_enable_asle(dev);
 	dev_priv->irq_enabled = 1;
 }
@@ -973,7 +1239,11 @@
 	struct drm_device *dev = (struct drm_device *)data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	uint32_t acthd;
-       
+
+	/* No reset support on this chip yet. */
+	if (IS_GEN6(dev))
+		return;
+
 	if (!IS_I965G(dev))
 		acthd = I915_READ(ACTHD);
 	else
@@ -1064,6 +1334,13 @@
 	I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg);
 	(void) I915_READ(SDEIER);
 
+	if (IS_IRONLAKE_M(dev)) {
+		/* Clear & enable PCU event interrupts */
+		I915_WRITE(DEIIR, DE_PCU_EVENT);
+		I915_WRITE(DEIER, I915_READ(DEIER) | DE_PCU_EVENT);
+		ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT);
+	}
+
 	return 0;
 }
 
@@ -1076,7 +1353,7 @@
 	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
 	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
 
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		ironlake_irq_preinstall(dev);
 		return;
 	}
@@ -1108,7 +1385,7 @@
 
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		return ironlake_irq_postinstall(dev);
 
 	/* Unmask the interrupts that we always want on. */
@@ -1196,7 +1473,7 @@
 
 	dev_priv->vblank_pipe = 0;
 
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		ironlake_irq_uninstall(dev);
 		return;
 	}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ab1bd2d..3d59862 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -53,6 +53,25 @@
 #define INTEL_GMCH_GMS_STOLEN_224M	(0xc << 4)
 #define INTEL_GMCH_GMS_STOLEN_352M	(0xd << 4)
 
+#define SNB_GMCH_CTRL	0x50
+#define SNB_GMCH_GMS_STOLEN_MASK	0xF8
+#define SNB_GMCH_GMS_STOLEN_32M		(1 << 3)
+#define SNB_GMCH_GMS_STOLEN_64M		(2 << 3)
+#define SNB_GMCH_GMS_STOLEN_96M		(3 << 3)
+#define SNB_GMCH_GMS_STOLEN_128M	(4 << 3)
+#define SNB_GMCH_GMS_STOLEN_160M	(5 << 3)
+#define SNB_GMCH_GMS_STOLEN_192M	(6 << 3)
+#define SNB_GMCH_GMS_STOLEN_224M	(7 << 3)
+#define SNB_GMCH_GMS_STOLEN_256M	(8 << 3)
+#define SNB_GMCH_GMS_STOLEN_288M	(9 << 3)
+#define SNB_GMCH_GMS_STOLEN_320M	(0xa << 3)
+#define SNB_GMCH_GMS_STOLEN_352M	(0xb << 3)
+#define SNB_GMCH_GMS_STOLEN_384M	(0xc << 3)
+#define SNB_GMCH_GMS_STOLEN_416M	(0xd << 3)
+#define SNB_GMCH_GMS_STOLEN_448M	(0xe << 3)
+#define SNB_GMCH_GMS_STOLEN_480M	(0xf << 3)
+#define SNB_GMCH_GMS_STOLEN_512M	(0x10 << 3)
+
 /* PCI config space */
 
 #define HPLLCC	0xc0 /* 855 only */
@@ -61,6 +80,7 @@
 #define   GC_CLOCK_100_200		(1 << 0)
 #define   GC_CLOCK_100_133		(2 << 0)
 #define   GC_CLOCK_166_250		(3 << 0)
+#define GCFGC2	0xda
 #define GCFGC	0xf0 /* 915+ only */
 #define   GC_LOW_FREQUENCY_ENABLE	(1 << 7)
 #define   GC_DISPLAY_CLOCK_190_200_MHZ	(0 << 4)
@@ -234,6 +254,9 @@
 #define   I965_FENCE_REG_VALID		(1<<0)
 #define   I965_FENCE_MAX_PITCH_VAL	0x0400
 
+#define FENCE_REG_SANDYBRIDGE_0		0x100000
+#define   SANDYBRIDGE_FENCE_PITCH_SHIFT	32
+
 /*
  * Instruction and interrupt control regs
  */
@@ -265,6 +288,7 @@
 #define INSTDONE1	0x0207c /* 965+ only */
 #define ACTHD_I965	0x02074
 #define HWS_PGA		0x02080
+#define HWS_PGA_GEN6	0x04080
 #define HWS_ADDRESS_MASK	0xfffff000
 #define HWS_START_ADDRESS_SHIFT	4
 #define PWRCTXA		0x2088 /* 965GM+ only */
@@ -282,7 +306,7 @@
 #define   I915_PIPE_CONTROL_NOTIFY_INTERRUPT		(1<<18)
 #define   I915_DISPLAY_PORT_INTERRUPT			(1<<17)
 #define   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT	(1<<15)
-#define   I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT	(1<<14)
+#define   I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT	(1<<14) /* p-state */
 #define   I915_HWB_OOM_INTERRUPT			(1<<13)
 #define   I915_SYNC_STATUS_INTERRUPT			(1<<12)
 #define   I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT	(1<<11)
@@ -306,11 +330,14 @@
 #define   I915_ERROR_MEMORY_REFRESH			(1<<1)
 #define   I915_ERROR_INSTRUCTION			(1<<0)
 #define INSTPM	        0x020c0
+#define   INSTPM_SELF_EN (1<<12) /* 915GM only */
 #define ACTHD	        0x020c8
 #define FW_BLC		0x020d8
 #define FW_BLC2	 	0x020dc
 #define FW_BLC_SELF	0x020e0 /* 915+ only */
-#define   FW_BLC_SELF_EN (1<<15)
+#define   FW_BLC_SELF_EN_MASK      (1<<31)
+#define   FW_BLC_SELF_FIFO_MASK    (1<<16) /* 945 only */
+#define   FW_BLC_SELF_EN           (1<<15) /* 945 only */
 #define MM_BURST_LENGTH     0x00700000
 #define MM_FIFO_WATERMARK   0x0001F000
 #define LM_BURST_LENGTH     0x00000700
@@ -324,6 +351,7 @@
 #define   CM0_COLOR_EVICT_DISABLE (1<<3)
 #define   CM0_DEPTH_WRITE_DISABLE (1<<1)
 #define   CM0_RC_OP_FLUSH_DISABLE (1<<0)
+#define BB_ADDR		0x02140 /* 8 bytes */
 #define GFX_FLSH_CNTL	0x02170 /* 915+ only */
 
 
@@ -784,10 +812,144 @@
 #define CLKCFG_MEM_800					(3 << 4)
 #define CLKCFG_MEM_MASK					(7 << 4)
 
-/** GM965 GM45 render standby register */
-#define MCHBAR_RENDER_STANDBY	0x111B8
+#define CRSTANDVID		0x11100
+#define PXVFREQ_BASE		0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
+#define   PXVFREQ_PX_MASK	0x7f000000
+#define   PXVFREQ_PX_SHIFT	24
+#define VIDFREQ_BASE		0x11110
+#define VIDFREQ1		0x11110 /* VIDFREQ1-4 (0x1111c) (Cantiga) */
+#define VIDFREQ2		0x11114
+#define VIDFREQ3		0x11118
+#define VIDFREQ4		0x1111c
+#define   VIDFREQ_P0_MASK	0x1f000000
+#define   VIDFREQ_P0_SHIFT	24
+#define   VIDFREQ_P0_CSCLK_MASK	0x00f00000
+#define   VIDFREQ_P0_CSCLK_SHIFT 20
+#define   VIDFREQ_P0_CRCLK_MASK	0x000f0000
+#define   VIDFREQ_P0_CRCLK_SHIFT 16
+#define   VIDFREQ_P1_MASK	0x00001f00
+#define   VIDFREQ_P1_SHIFT	8
+#define   VIDFREQ_P1_CSCLK_MASK	0x000000f0
+#define   VIDFREQ_P1_CSCLK_SHIFT 4
+#define   VIDFREQ_P1_CRCLK_MASK	0x0000000f
+#define INTTOEXT_BASE_ILK	0x11300
+#define INTTOEXT_BASE		0x11120 /* INTTOEXT1-8 (0x1113c) */
+#define   INTTOEXT_MAP3_SHIFT	24
+#define   INTTOEXT_MAP3_MASK	(0x1f << INTTOEXT_MAP3_SHIFT)
+#define   INTTOEXT_MAP2_SHIFT	16
+#define   INTTOEXT_MAP2_MASK	(0x1f << INTTOEXT_MAP2_SHIFT)
+#define   INTTOEXT_MAP1_SHIFT	8
+#define   INTTOEXT_MAP1_MASK	(0x1f << INTTOEXT_MAP1_SHIFT)
+#define   INTTOEXT_MAP0_SHIFT	0
+#define   INTTOEXT_MAP0_MASK	(0x1f << INTTOEXT_MAP0_SHIFT)
+#define MEMSWCTL		0x11170 /* Ironlake only */
+#define   MEMCTL_CMD_MASK	0xe000
+#define   MEMCTL_CMD_SHIFT	13
+#define   MEMCTL_CMD_RCLK_OFF	0
+#define   MEMCTL_CMD_RCLK_ON	1
+#define   MEMCTL_CMD_CHFREQ	2
+#define   MEMCTL_CMD_CHVID	3
+#define   MEMCTL_CMD_VMMOFF	4
+#define   MEMCTL_CMD_VMMON	5
+#define   MEMCTL_CMD_STS	(1<<12) /* write 1 triggers command, clears
+					   when command complete */
+#define   MEMCTL_FREQ_MASK	0x0f00 /* jitter, from 0-15 */
+#define   MEMCTL_FREQ_SHIFT	8
+#define   MEMCTL_SFCAVM		(1<<7)
+#define   MEMCTL_TGT_VID_MASK	0x007f
+#define MEMIHYST		0x1117c
+#define MEMINTREN		0x11180 /* 16 bits */
+#define   MEMINT_RSEXIT_EN	(1<<8)
+#define   MEMINT_CX_SUPR_EN	(1<<7)
+#define   MEMINT_CONT_BUSY_EN	(1<<6)
+#define   MEMINT_AVG_BUSY_EN	(1<<5)
+#define   MEMINT_EVAL_CHG_EN	(1<<4)
+#define   MEMINT_MON_IDLE_EN	(1<<3)
+#define   MEMINT_UP_EVAL_EN	(1<<2)
+#define   MEMINT_DOWN_EVAL_EN	(1<<1)
+#define   MEMINT_SW_CMD_EN	(1<<0)
+#define MEMINTRSTR		0x11182 /* 16 bits */
+#define   MEM_RSEXIT_MASK	0xc000
+#define   MEM_RSEXIT_SHIFT	14
+#define   MEM_CONT_BUSY_MASK	0x3000
+#define   MEM_CONT_BUSY_SHIFT	12
+#define   MEM_AVG_BUSY_MASK	0x0c00
+#define   MEM_AVG_BUSY_SHIFT	10
+#define   MEM_EVAL_CHG_MASK	0x0300
+#define   MEM_EVAL_BUSY_SHIFT	8
+#define   MEM_MON_IDLE_MASK	0x00c0
+#define   MEM_MON_IDLE_SHIFT	6
+#define   MEM_UP_EVAL_MASK	0x0030
+#define   MEM_UP_EVAL_SHIFT	4
+#define   MEM_DOWN_EVAL_MASK	0x000c
+#define   MEM_DOWN_EVAL_SHIFT	2
+#define   MEM_SW_CMD_MASK	0x0003
+#define   MEM_INT_STEER_GFX	0
+#define   MEM_INT_STEER_CMR	1
+#define   MEM_INT_STEER_SMI	2
+#define   MEM_INT_STEER_SCI	3
+#define MEMINTRSTS		0x11184
+#define   MEMINT_RSEXIT		(1<<7)
+#define   MEMINT_CONT_BUSY	(1<<6)
+#define   MEMINT_AVG_BUSY	(1<<5)
+#define   MEMINT_EVAL_CHG	(1<<4)
+#define   MEMINT_MON_IDLE	(1<<3)
+#define   MEMINT_UP_EVAL	(1<<2)
+#define   MEMINT_DOWN_EVAL	(1<<1)
+#define   MEMINT_SW_CMD		(1<<0)
+#define MEMMODECTL		0x11190
+#define   MEMMODE_BOOST_EN	(1<<31)
+#define   MEMMODE_BOOST_FREQ_MASK 0x0f000000 /* jitter for boost, 0-15 */
+#define   MEMMODE_BOOST_FREQ_SHIFT 24
+#define   MEMMODE_IDLE_MODE_MASK 0x00030000
+#define   MEMMODE_IDLE_MODE_SHIFT 16
+#define   MEMMODE_IDLE_MODE_EVAL 0
+#define   MEMMODE_IDLE_MODE_CONT 1
+#define   MEMMODE_HWIDLE_EN	(1<<15)
+#define   MEMMODE_SWMODE_EN	(1<<14)
+#define   MEMMODE_RCLK_GATE	(1<<13)
+#define   MEMMODE_HW_UPDATE	(1<<12)
+#define   MEMMODE_FSTART_MASK	0x00000f00 /* starting jitter, 0-15 */
+#define   MEMMODE_FSTART_SHIFT	8
+#define   MEMMODE_FMAX_MASK	0x000000f0 /* max jitter, 0-15 */
+#define   MEMMODE_FMAX_SHIFT	4
+#define   MEMMODE_FMIN_MASK	0x0000000f /* min jitter, 0-15 */
+#define RCBMAXAVG		0x1119c
+#define MEMSWCTL2		0x1119e /* Cantiga only */
+#define   SWMEMCMD_RENDER_OFF	(0 << 13)
+#define   SWMEMCMD_RENDER_ON	(1 << 13)
+#define   SWMEMCMD_SWFREQ	(2 << 13)
+#define   SWMEMCMD_TARVID	(3 << 13)
+#define   SWMEMCMD_VRM_OFF	(4 << 13)
+#define   SWMEMCMD_VRM_ON	(5 << 13)
+#define   CMDSTS		(1<<12)
+#define   SFCAVM		(1<<11)
+#define   SWFREQ_MASK		0x0380 /* P0-7 */
+#define   SWFREQ_SHIFT		7
+#define   TARVID_MASK		0x001f
+#define MEMSTAT_CTG		0x111a0
+#define RCBMINAVG		0x111a0
+#define RCUPEI			0x111b0
+#define RCDNEI			0x111b4
+#define MCHBAR_RENDER_STANDBY		0x111b8
 #define   RCX_SW_EXIT		(1<<23)
 #define   RSX_STATUS_MASK	0x00700000
+#define VIDCTL			0x111c0
+#define VIDSTS			0x111c8
+#define VIDSTART		0x111cc /* 8 bits */
+#define MEMSTAT_ILK			0x111f8
+#define   MEMSTAT_VID_MASK	0x7f00
+#define   MEMSTAT_VID_SHIFT	8
+#define   MEMSTAT_PSTATE_MASK	0x00f8
+#define   MEMSTAT_PSTATE_SHIFT  3
+#define   MEMSTAT_MON_ACTV	(1<<2)
+#define   MEMSTAT_SRC_CTL_MASK	0x0003
+#define   MEMSTAT_SRC_CTL_CORE	0
+#define   MEMSTAT_SRC_CTL_TRB	1
+#define   MEMSTAT_SRC_CTL_THM	2
+#define   MEMSTAT_SRC_CTL_STDBY 3
+#define RCPREVBSYTUPAVG		0x113b8
+#define RCPREVBSYTDNAVG		0x113bc
 #define PEG_BAND_GAP_DATA	0x14d68
 
 /*
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index a3b90c9..ac0d1a7 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -682,6 +682,8 @@
 		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
 		I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR);
 		I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL);
+		I915_WRITE(MCHBAR_RENDER_STANDBY,
+			   dev_priv->saveMCHBAR_RENDER_STANDBY);
 	} else {
 		I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
 		I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
@@ -745,11 +747,16 @@
 		dev_priv->saveGTIMR = I915_READ(GTIMR);
 		dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR);
 		dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR);
+		dev_priv->saveMCHBAR_RENDER_STANDBY =
+			I915_READ(MCHBAR_RENDER_STANDBY);
 	} else {
 		dev_priv->saveIER = I915_READ(IER);
 		dev_priv->saveIMR = I915_READ(IMR);
 	}
 
+	if (IS_IRONLAKE_M(dev))
+		ironlake_disable_drps(dev);
+
 	/* Cache mode state */
 	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
 
@@ -820,6 +827,9 @@
 	/* Clock gating state */
 	intel_init_clock_gating(dev);
 
+	if (IS_IRONLAKE_M(dev))
+		ironlake_enable_drps(dev);
+
 	/* Cache mode state */
 	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
 
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 15fbc1b..70c9d4b 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -247,6 +247,7 @@
 parse_general_features(struct drm_i915_private *dev_priv,
 		       struct bdb_header *bdb)
 {
+	struct drm_device *dev = dev_priv->dev;
 	struct bdb_general_features *general;
 
 	/* Set sensible defaults in case we can't find the general block */
@@ -263,7 +264,7 @@
 			if (IS_I85X(dev_priv->dev))
 				dev_priv->lvds_ssc_freq =
 					general->ssc_freq ? 66 : 48;
-			else if (IS_IRONLAKE(dev_priv->dev))
+			else if (IS_IRONLAKE(dev_priv->dev) || IS_GEN6(dev))
 				dev_priv->lvds_ssc_freq =
 					general->ssc_freq ? 100 : 120;
 			else
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 79dd402..fccf074 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -39,7 +39,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 temp, reg;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		reg = PCH_ADPA;
 	else
 		reg = ADPA;
@@ -113,7 +113,7 @@
 	else
 		dpll_md_reg = DPLL_B_MD;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		adpa_reg = PCH_ADPA;
 	else
 		adpa_reg = ADPA;
@@ -122,7 +122,7 @@
 	 * Disable separate mode multiplier used when cloning SDVO to CRT
 	 * XXX this needs to be adjusted when we really are cloning
 	 */
-	if (IS_I965G(dev) && !IS_IRONLAKE(dev)) {
+	if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
 		dpll_md = I915_READ(dpll_md_reg);
 		I915_WRITE(dpll_md_reg,
 			   dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
@@ -136,11 +136,11 @@
 
 	if (intel_crtc->pipe == 0) {
 		adpa |= ADPA_PIPE_A_SELECT;
-		if (!IS_IRONLAKE(dev))
+		if (!HAS_PCH_SPLIT(dev))
 			I915_WRITE(BCLRPAT_A, 0);
 	} else {
 		adpa |= ADPA_PIPE_B_SELECT;
-		if (!IS_IRONLAKE(dev))
+		if (!HAS_PCH_SPLIT(dev))
 			I915_WRITE(BCLRPAT_B, 0);
 	}
 
@@ -202,7 +202,7 @@
 	u32 hotplug_en;
 	int i, tries = 0;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		return intel_ironlake_crt_detect_hotplug(connector);
 
 	/*
@@ -524,7 +524,7 @@
 					  &intel_output->enc);
 
 	/* Set up the DDC bus. */
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		i2c_reg = PCH_GPIOA;
 	else {
 		i2c_reg = GPIOA;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b27202d..9cd6de5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -232,7 +232,7 @@
 #define G4X_P2_DISPLAY_PORT_FAST           10
 #define G4X_P2_DISPLAY_PORT_LIMIT          0
 
-/* Ironlake */
+/* Ironlake / Sandybridge */
 /* as we calculate clock using (register_value + 2) for
    N/M1/M2, so here the range value for them is (actual_value-2).
  */
@@ -690,7 +690,7 @@
 	struct drm_device *dev = crtc->dev;
 	const intel_limit_t *limit;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		limit = intel_ironlake_limit(crtc);
 	else if (IS_G4X(dev)) {
 		limit = intel_g4x_limit(crtc);
@@ -886,7 +886,7 @@
 	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
 		int lvds_reg;
 
-		if (IS_IRONLAKE(dev))
+		if (HAS_PCH_SPLIT(dev))
 			lvds_reg = PCH_LVDS;
 		else
 			lvds_reg = LVDS;
@@ -1188,25 +1188,30 @@
 	if (intel_fb->obj->size > dev_priv->cfb_size) {
 		DRM_DEBUG_KMS("framebuffer too large, disabling "
 				"compression\n");
+		dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
 		goto out_disable;
 	}
 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
 	    (mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
 		DRM_DEBUG_KMS("mode incompatible with compression, "
 				"disabling\n");
+		dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE;
 		goto out_disable;
 	}
 	if ((mode->hdisplay > 2048) ||
 	    (mode->vdisplay > 1536)) {
 		DRM_DEBUG_KMS("mode too large for compression, disabling\n");
+		dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE;
 		goto out_disable;
 	}
 	if ((IS_I915GM(dev) || IS_I945GM(dev)) && plane != 0) {
 		DRM_DEBUG_KMS("plane not 0, disabling compression\n");
+		dev_priv->no_fbc_reason = FBC_BAD_PLANE;
 		goto out_disable;
 	}
 	if (obj_priv->tiling_mode != I915_TILING_X) {
 		DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n");
+		dev_priv->no_fbc_reason = FBC_NOT_TILED;
 		goto out_disable;
 	}
 
@@ -1366,7 +1371,7 @@
 			dspcntr &= ~DISPPLANE_TILED;
 	}
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		/* must disable */
 		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
@@ -1427,7 +1432,7 @@
 	u8 sr1;
 	u32 vga_reg;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		vga_reg = CPU_VGACNTRL;
 	else
 		vga_reg = VGACNTRL;
@@ -2111,7 +2116,7 @@
 				  struct drm_display_mode *adjusted_mode)
 {
 	struct drm_device *dev = crtc->dev;
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		/* FDI link clock is fixed at 2.7G */
 		if (mode->clock * 3 > 27000 * 4)
 			return MODE_CLOCK_HIGH;
@@ -2757,11 +2762,22 @@
 		srwm = total_size - sr_entries;
 		if (srwm < 0)
 			srwm = 1;
-		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
+
+		if (IS_I945G(dev) || IS_I945GM(dev))
+			I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
+		else if (IS_I915GM(dev)) {
+			/* 915M has a smaller SRWM field */
+			I915_WRITE(FW_BLC_SELF, srwm & 0x3f);
+			I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
+		}
 	} else {
 		/* Turn off self refresh if both pipes are enabled */
-		I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
-					& ~FW_BLC_SELF_EN);
+		if (IS_I945G(dev) || IS_I945GM(dev)) {
+			I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
+				   & ~FW_BLC_SELF_EN);
+		} else if (IS_I915GM(dev)) {
+			I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
+		}
 	}
 
 	DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
@@ -2967,7 +2983,7 @@
 					refclk / 1000);
 	} else if (IS_I9XX(dev)) {
 		refclk = 96000;
-		if (IS_IRONLAKE(dev))
+		if (HAS_PCH_SPLIT(dev))
 			refclk = 120000; /* 120Mhz refclk */
 	} else {
 		refclk = 48000;
@@ -3025,7 +3041,7 @@
 	}
 
 	/* FDI link */
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		int lane, link_bw, bpp;
 		/* eDP doesn't require FDI link, so just set DP M/N
 		   according to current link config */
@@ -3102,7 +3118,7 @@
 	 * PCH B stepping, previous chipset stepping should be
 	 * ignoring this setting.
 	 */
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		temp = I915_READ(PCH_DREF_CONTROL);
 		/* Always enable nonspread source */
 		temp &= ~DREF_NONSPREAD_SOURCE_MASK;
@@ -3149,7 +3165,7 @@
 				reduced_clock.m2;
 	}
 
-	if (!IS_IRONLAKE(dev))
+	if (!HAS_PCH_SPLIT(dev))
 		dpll = DPLL_VGA_MODE_DIS;
 
 	if (IS_I9XX(dev)) {
@@ -3162,7 +3178,7 @@
 			sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
 			if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
 				dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
-			else if (IS_IRONLAKE(dev))
+			else if (HAS_PCH_SPLIT(dev))
 				dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
 		}
 		if (is_dp)
@@ -3174,7 +3190,7 @@
 		else {
 			dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
 			/* also FPA1 */
-			if (IS_IRONLAKE(dev))
+			if (HAS_PCH_SPLIT(dev))
 				dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
 			if (IS_G4X(dev) && has_reduced_clock)
 				dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
@@ -3193,7 +3209,7 @@
 			dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
 			break;
 		}
-		if (IS_I965G(dev) && !IS_IRONLAKE(dev))
+		if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev))
 			dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
 	} else {
 		if (is_lvds) {
@@ -3227,7 +3243,7 @@
 
 	/* Ironlake's plane is forced to pipe, bit 24 is to
 	   enable color space conversion */
-	if (!IS_IRONLAKE(dev)) {
+	if (!HAS_PCH_SPLIT(dev)) {
 		if (pipe == 0)
 			dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
 		else
@@ -3254,14 +3270,14 @@
 
 
 	/* Disable the panel fitter if it was on our pipe */
-	if (!IS_IRONLAKE(dev) && intel_panel_fitter_pipe(dev) == pipe)
+	if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe)
 		I915_WRITE(PFIT_CONTROL, 0);
 
 	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 	drm_mode_debug_printmodeline(mode);
 
 	/* assign to Ironlake registers */
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		fp_reg = pch_fp_reg;
 		dpll_reg = pch_dpll_reg;
 	}
@@ -3282,7 +3298,7 @@
 	if (is_lvds) {
 		u32 lvds;
 
-		if (IS_IRONLAKE(dev))
+		if (HAS_PCH_SPLIT(dev))
 			lvds_reg = PCH_LVDS;
 
 		lvds = I915_READ(lvds_reg);
@@ -3304,12 +3320,12 @@
 		/* set the dithering flag */
 		if (IS_I965G(dev)) {
 			if (dev_priv->lvds_dither) {
-				if (IS_IRONLAKE(dev))
+				if (HAS_PCH_SPLIT(dev))
 					pipeconf |= PIPE_ENABLE_DITHER;
 				else
 					lvds |= LVDS_ENABLE_DITHER;
 			} else {
-				if (IS_IRONLAKE(dev))
+				if (HAS_PCH_SPLIT(dev))
 					pipeconf &= ~PIPE_ENABLE_DITHER;
 				else
 					lvds &= ~LVDS_ENABLE_DITHER;
@@ -3328,7 +3344,7 @@
 		/* Wait for the clocks to stabilize. */
 		udelay(150);
 
-		if (IS_I965G(dev) && !IS_IRONLAKE(dev)) {
+		if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
 			if (is_sdvo) {
 				sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
 				I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
@@ -3375,14 +3391,14 @@
 	/* pipesrc and dspsize control the size that is scaled from, which should
 	 * always be the user's requested size.
 	 */
-	if (!IS_IRONLAKE(dev)) {
+	if (!HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) |
 				(mode->hdisplay - 1));
 		I915_WRITE(dsppos_reg, 0);
 	}
 	I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
 
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m);
 		I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n);
 		I915_WRITE(link_m1_reg, m_n.link_m);
@@ -3438,7 +3454,7 @@
 		return;
 
 	/* use legacy palette for Ironlake */
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A :
 						   LGC_PALETTE_B;
 
@@ -3553,11 +3569,10 @@
 	intel_crtc->cursor_bo = bo;
 
 	return 0;
-fail:
-	mutex_lock(&dev->struct_mutex);
 fail_locked:
-	drm_gem_object_unreference(bo);
 	mutex_unlock(&dev->struct_mutex);
+fail:
+	drm_gem_object_unreference_unlocked(bo);
 	return ret;
 }
 
@@ -3922,7 +3937,7 @@
 	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
 	int dpll = I915_READ(dpll_reg);
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		return;
 
 	if (!dev_priv->lvds_downclock_avail)
@@ -3961,7 +3976,7 @@
 	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
 	int dpll = I915_READ(dpll_reg);
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		return;
 
 	if (!dev_priv->lvds_downclock_avail)
@@ -4011,6 +4026,11 @@
 
 	mutex_lock(&dev->struct_mutex);
 
+	if (IS_I945G(dev) || IS_I945GM(dev)) {
+		DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
+		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
+	}
+
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		/* Skip inactive CRTCs */
 		if (!crtc->fb)
@@ -4044,9 +4064,17 @@
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return;
 
-	if (!dev_priv->busy)
+	if (!dev_priv->busy) {
+		if (IS_I945G(dev) || IS_I945GM(dev)) {
+			u32 fw_blc_self;
+
+			DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
+			fw_blc_self = I915_READ(FW_BLC_SELF);
+			fw_blc_self &= ~FW_BLC_SELF_EN;
+			I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
+		}
 		dev_priv->busy = true;
-	else
+	} else
 		mod_timer(&dev_priv->idle_timer, jiffies +
 			  msecs_to_jiffies(GPU_IDLE_TIMEOUT));
 
@@ -4058,6 +4086,14 @@
 		intel_fb = to_intel_framebuffer(crtc->fb);
 		if (intel_fb->obj == obj) {
 			if (!intel_crtc->busy) {
+				if (IS_I945G(dev) || IS_I945GM(dev)) {
+					u32 fw_blc_self;
+
+					DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
+					fw_blc_self = I915_READ(FW_BLC_SELF);
+					fw_blc_self &= ~FW_BLC_SELF_EN;
+					I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
+				}
 				/* Non-busy -> busy, upclock */
 				intel_increase_pllclock(crtc, true);
 				intel_crtc->busy = true;
@@ -4382,7 +4418,7 @@
 	if (IS_MOBILE(dev) && !IS_I830(dev))
 		intel_lvds_init(dev);
 
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		int found;
 
 		if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
@@ -4451,7 +4487,7 @@
 			DRM_DEBUG_KMS("probing DP_D\n");
 			intel_dp_init(dev, DP_D);
 		}
-	} else if (IS_I8XX(dev))
+	} else if (IS_GEN2(dev))
 		intel_dvo_init(dev);
 
 	if (SUPPORTS_TV(dev))
@@ -4476,9 +4512,7 @@
 		intelfb_remove(dev, fb);
 
 	drm_framebuffer_cleanup(fb);
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(intel_fb->obj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(intel_fb->obj);
 
 	kfree(intel_fb);
 }
@@ -4541,9 +4575,7 @@
 
 	ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj);
 	if (ret) {
-		mutex_lock(&dev->struct_mutex);
-		drm_gem_object_unreference(obj);
-		mutex_unlock(&dev->struct_mutex);
+		drm_gem_object_unreference_unlocked(obj);
 		return NULL;
 	}
 
@@ -4591,6 +4623,91 @@
 	return NULL;
 }
 
+void ironlake_enable_drps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 rgvmodectl = I915_READ(MEMMODECTL), rgvswctl;
+	u8 fmax, fmin, fstart, vstart;
+	int i = 0;
+
+	/* 100ms RC evaluation intervals */
+	I915_WRITE(RCUPEI, 100000);
+	I915_WRITE(RCDNEI, 100000);
+
+	/* Set max/min thresholds to 90ms and 80ms respectively */
+	I915_WRITE(RCBMAXAVG, 90000);
+	I915_WRITE(RCBMINAVG, 80000);
+
+	I915_WRITE(MEMIHYST, 1);
+
+	/* Set up min, max, and cur for interrupt handling */
+	fmax = (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT;
+	fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
+	fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
+		MEMMODE_FSTART_SHIFT;
+	vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
+		PXVFREQ_PX_SHIFT;
+
+	dev_priv->max_delay = fstart; /* can't go to fmax w/o IPS */
+	dev_priv->min_delay = fmin;
+	dev_priv->cur_delay = fstart;
+
+	I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
+
+	/*
+	 * Interrupts will be enabled in ironlake_irq_postinstall
+	 */
+
+	I915_WRITE(VIDSTART, vstart);
+	POSTING_READ(VIDSTART);
+
+	rgvmodectl |= MEMMODE_SWMODE_EN;
+	I915_WRITE(MEMMODECTL, rgvmodectl);
+
+	while (I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) {
+		if (i++ > 100) {
+			DRM_ERROR("stuck trying to change perf mode\n");
+			break;
+		}
+		msleep(1);
+	}
+	msleep(1);
+
+	rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
+		(fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
+	I915_WRITE(MEMSWCTL, rgvswctl);
+	POSTING_READ(MEMSWCTL);
+
+	rgvswctl |= MEMCTL_CMD_STS;
+	I915_WRITE(MEMSWCTL, rgvswctl);
+}
+
+void ironlake_disable_drps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 rgvswctl;
+	u8 fstart;
+
+	/* Ack interrupts, disable EFC interrupt */
+	I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
+	I915_WRITE(MEMINTRSTS, MEMINT_EVAL_CHG);
+	I915_WRITE(DEIER, I915_READ(DEIER) & ~DE_PCU_EVENT);
+	I915_WRITE(DEIIR, DE_PCU_EVENT);
+	I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
+
+	/* Go back to the starting frequency */
+	fstart = (I915_READ(MEMMODECTL) & MEMMODE_FSTART_MASK) >>
+		MEMMODE_FSTART_SHIFT;
+	rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
+		(fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
+	I915_WRITE(MEMSWCTL, rgvswctl);
+	msleep(1);
+	rgvswctl |= MEMCTL_CMD_STS;
+	I915_WRITE(MEMSWCTL, rgvswctl);
+	msleep(1);
+
+}
+
 void intel_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4599,7 +4716,7 @@
 	 * Disable clock gating reported to work incorrectly according to the
 	 * specs, but enable as much else as we can.
 	 */
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		return;
 	} else if (IS_G4X(dev)) {
 		uint32_t dspclk_gate;
@@ -4672,7 +4789,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	/* We always want a DPMS function */
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		dev_priv->display.dpms = ironlake_crtc_dpms;
 	else
 		dev_priv->display.dpms = i9xx_crtc_dpms;
@@ -4715,7 +4832,7 @@
 			i830_get_display_clock_speed;
 
 	/* For FIFO watermark updates */
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		dev_priv->display.update_wm = NULL;
 	else if (IS_G4X(dev))
 		dev_priv->display.update_wm = g4x_update_wm;
@@ -4774,11 +4891,6 @@
 	DRM_DEBUG_KMS("%d display pipe%s available.\n",
 		  num_pipe, num_pipe > 1 ? "s" : "");
 
-	if (IS_I85X(dev))
-		pci_read_config_word(dev->pdev, HPLLCC, &dev_priv->orig_clock);
-	else if (IS_I9XX(dev) || IS_G4X(dev))
-		pci_read_config_word(dev->pdev, GCFGC, &dev_priv->orig_clock);
-
 	for (i = 0; i < num_pipe; i++) {
 		intel_crtc_init(dev, i);
 	}
@@ -4787,6 +4899,9 @@
 
 	intel_init_clock_gating(dev);
 
+	if (IS_IRONLAKE_M(dev))
+		ironlake_enable_drps(dev);
+
 	INIT_WORK(&dev_priv->idle_work, intel_idle_update);
 	setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
 		    (unsigned long)dev);
@@ -4834,6 +4949,9 @@
 		drm_gem_object_unreference(dev_priv->pwrctx);
 	}
 
+	if (IS_IRONLAKE_M(dev))
+		ironlake_disable_drps(dev);
+
 	mutex_unlock(&dev->struct_mutex);
 
 	drm_mode_config_cleanup(dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 439506c..3ef3a0d 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -231,7 +231,7 @@
 	 */
 	if (IS_eDP(intel_output))
 		aux_clock_divider = 225; /* eDP input clock at 450Mhz */
-	else if (IS_IRONLAKE(dev))
+	else if (HAS_PCH_SPLIT(dev))
 		aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */
 	else
 		aux_clock_divider = intel_hrawclk(dev) / 2;
@@ -584,7 +584,7 @@
 	intel_dp_compute_m_n(3, lane_count,
 			     mode->clock, adjusted_mode->clock, &m_n);
 
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		if (intel_crtc->pipe == 0) {
 			I915_WRITE(TRANSA_DATA_M1,
 				   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
@@ -1176,7 +1176,7 @@
 
 	dp_priv->has_audio = false;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		return ironlake_dp_detect(connector);
 
 	temp = I915_READ(PORT_HOTPLUG_EN);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a51573d..3a467ca 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -209,6 +209,8 @@
 extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
 				    u16 *blue, int regno);
 extern void intel_init_clock_gating(struct drm_device *dev);
+extern void ironlake_enable_drps(struct drm_device *dev);
+extern void ironlake_disable_drps(struct drm_device *dev);
 
 extern int intel_framebuffer_create(struct drm_device *dev,
 				    struct drm_mode_fb_cmd *mode_cmd,
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index aaabbcb..8cd791d 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -35,6 +35,7 @@
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
+#include <linux/vga_switcheroo.h>
 
 #include "drmP.h"
 #include "drm.h"
@@ -235,6 +236,7 @@
 			obj_priv->gtt_offset, fbo);
 
 	mutex_unlock(&dev->struct_mutex);
+	vga_switcheroo_client_fb_set(dev->pdev, info);
 	return 0;
 
 out_unpin:
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 0e268de..a30f8bf 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -82,7 +82,7 @@
 	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
 	 * we do this anyway which shows more stable in testing.
 	 */
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE);
 		POSTING_READ(hdmi_priv->sdvox_reg);
 	}
@@ -99,7 +99,7 @@
 	/* HW workaround, need to write this twice for issue that may result
 	 * in first write getting masked.
 	 */
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(hdmi_priv->sdvox_reg, temp);
 		POSTING_READ(hdmi_priv->sdvox_reg);
 	}
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 8673c73..fcc753c 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -128,7 +128,7 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(PCH_GMBUS0, 0);
 	} else {
 		I915_WRITE(GMBUS0, 0);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index c2e8a45..14e516f 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -56,7 +56,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 blc_pwm_ctl, reg;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		reg = BLC_PWM_CPU_CTL;
 	else
 		reg = BLC_PWM_CTL;
@@ -74,7 +74,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		reg = BLC_PWM_PCH_CTL2;
 	else
 		reg = BLC_PWM_CTL;
@@ -89,17 +89,22 @@
 static void intel_lvds_set_power(struct drm_device *dev, bool on)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 pp_status, ctl_reg, status_reg;
+	u32 pp_status, ctl_reg, status_reg, lvds_reg;
 
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		ctl_reg = PCH_PP_CONTROL;
 		status_reg = PCH_PP_STATUS;
+		lvds_reg = PCH_LVDS;
 	} else {
 		ctl_reg = PP_CONTROL;
 		status_reg = PP_STATUS;
+		lvds_reg = LVDS;
 	}
 
 	if (on) {
+		I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
+		POSTING_READ(lvds_reg);
+
 		I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
 			   POWER_TARGET_ON);
 		do {
@@ -115,6 +120,9 @@
 		do {
 			pp_status = I915_READ(status_reg);
 		} while (pp_status & PP_ON);
+
+		I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
+		POSTING_READ(lvds_reg);
 	}
 }
 
@@ -137,7 +145,7 @@
 	u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
 	u32 pwm_ctl_reg;
 
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		pp_on_reg = PCH_PP_ON_DELAYS;
 		pp_off_reg = PCH_PP_OFF_DELAYS;
 		pp_ctl_reg = PCH_PP_CONTROL;
@@ -174,7 +182,7 @@
 	u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
 	u32 pwm_ctl_reg;
 
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		pp_on_reg = PCH_PP_ON_DELAYS;
 		pp_off_reg = PCH_PP_OFF_DELAYS;
 		pp_ctl_reg = PCH_PP_CONTROL;
@@ -297,7 +305,7 @@
 	}
 
 	/* full screen scale for now */
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		goto out;
 
 	/* 965+ wants fuzzy fitting */
@@ -327,7 +335,7 @@
 	 * to register description and PRM.
 	 * Change the value here to see the borders for debugging
 	 */
-	if (!IS_IRONLAKE(dev)) {
+	if (!HAS_PCH_SPLIT(dev)) {
 		I915_WRITE(BCLRPAT_A, 0);
 		I915_WRITE(BCLRPAT_B, 0);
 	}
@@ -548,7 +556,7 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg;
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		reg = BLC_PWM_CPU_CTL;
 	else
 		reg = BLC_PWM_CTL;
@@ -587,7 +595,7 @@
 	 * settings.
 	 */
 
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		return;
 
 	/*
@@ -655,8 +663,15 @@
  */
 static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
 	enum drm_connector_status status = connector_status_connected;
 
+	/* ACPI lid methods were generally unreliable in this generation, so
+	 * don't even bother.
+	 */
+	if (IS_GEN2(dev))
+		return connector_status_connected;
+
 	if (!dmi_check_system(bad_lid_status) && !acpi_lid_open())
 		status = connector_status_disconnected;
 
@@ -1020,7 +1035,7 @@
 		return;
 	}
 
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
 			return;
 		if (dev_priv->edp_support) {
@@ -1123,7 +1138,7 @@
 	 */
 
 	/* Ironlake: FIXME if still fail, not try pipe mode now */
-	if (IS_IRONLAKE(dev))
+	if (HAS_PCH_SPLIT(dev))
 		goto failed;
 
 	lvds = I915_READ(LVDS);
@@ -1144,7 +1159,7 @@
 		goto failed;
 
 out:
-	if (IS_IRONLAKE(dev)) {
+	if (HAS_PCH_SPLIT(dev)) {
 		u32 pwm;
 		/* make sure PWM is enabled */
 		pwm = I915_READ(BLC_PWM_CPU_CTL2);
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 2639591..d355d1d 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -172,7 +172,7 @@
 #define OFC_UPDATE		0x1
 
 #define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev))
-#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev))
+#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev))
 
 
 static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
@@ -199,16 +199,11 @@
 
 static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
 {
-	struct drm_device *dev = overlay->dev;
-        drm_i915_private_t *dev_priv = dev->dev_private;
-
 	if (OVERLAY_NONPHYSICAL(overlay->dev))
 		io_mapping_unmap_atomic(overlay->virt_addr);
 
 	overlay->virt_addr = NULL;
 
-	I915_READ(OVADD); /* flush wc cashes */
-
 	return;
 }
 
@@ -225,9 +220,7 @@
 	overlay->active = 1;
 	overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP;
 
-	BEGIN_LP_RING(6);
-	OUT_RING(MI_FLUSH);
-	OUT_RING(MI_NOOP);
+	BEGIN_LP_RING(4);
 	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
 	OUT_RING(overlay->flip_addr | OFC_UPDATE);
 	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
@@ -267,9 +260,7 @@
 	if (tmp & (1 << 17))
 		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
 
-	BEGIN_LP_RING(4);
-	OUT_RING(MI_FLUSH);
-	OUT_RING(MI_NOOP);
+	BEGIN_LP_RING(2);
 	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
 	OUT_RING(flip_addr);
         ADVANCE_LP_RING();
@@ -338,9 +329,7 @@
 	/* wait for overlay to go idle */
 	overlay->hw_wedged = SWITCH_OFF_STAGE_1;
 
-	BEGIN_LP_RING(6);
-	OUT_RING(MI_FLUSH);
-	OUT_RING(MI_NOOP);
+	BEGIN_LP_RING(4);
 	OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
 	OUT_RING(flip_addr);
         OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
@@ -358,9 +347,7 @@
 	/* turn overlay off */
 	overlay->hw_wedged = SWITCH_OFF_STAGE_2;
 
-	BEGIN_LP_RING(6);
-        OUT_RING(MI_FLUSH);
-        OUT_RING(MI_NOOP);
+	BEGIN_LP_RING(4);
         OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
 	OUT_RING(flip_addr);
         OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
@@ -435,9 +422,7 @@
 
 			overlay->hw_wedged = SWITCH_OFF_STAGE_2;
 
-			BEGIN_LP_RING(6);
-			OUT_RING(MI_FLUSH);
-			OUT_RING(MI_NOOP);
+			BEGIN_LP_RING(4);
 			OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
 			OUT_RING(flip_addr);
 			OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
@@ -1179,7 +1164,7 @@
 out_unlock:
 	mutex_unlock(&dev->struct_mutex);
 	mutex_unlock(&dev->mode_config.mutex);
-	drm_gem_object_unreference(new_bo);
+	drm_gem_object_unreference_unlocked(new_bo);
 	kfree(params);
 
 	return ret;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 82678d3..48daee5 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -35,6 +35,7 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "intel_sdvo_regs.h"
+#include <linux/dmi.h>
 
 static char *tv_format_names[] = {
 	"NTSC_M"   , "NTSC_J"  , "NTSC_443",
@@ -2283,6 +2284,25 @@
 		return 0x72;
 }
 
+static int intel_sdvo_bad_tv_callback(const struct dmi_system_id *id)
+{
+	DRM_DEBUG_KMS("Ignoring bad SDVO TV connector for %s\n", id->ident);
+	return 1;
+}
+
+static struct dmi_system_id intel_sdvo_bad_tv[] = {
+	{
+		.callback = intel_sdvo_bad_tv_callback,
+		.ident = "IntelG45/ICH10R/DME1737",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "IBM CORPORATION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "4800784"),
+		},
+	},
+
+	{ }	/* terminating entry */
+};
+
 static bool
 intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
 {
@@ -2323,7 +2343,8 @@
 					(1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
 					(1 << INTEL_ANALOG_CLONE_BIT);
 		}
-	} else if (flags & SDVO_OUTPUT_SVID0) {
+	} else if ((flags & SDVO_OUTPUT_SVID0) &&
+		   !dmi_check_system(intel_sdvo_bad_tv)) {
 
 		sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0;
 		encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index 48c290b..32db806 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -16,7 +16,7 @@
              nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
              nv04_graph.o nv10_graph.o nv20_graph.o \
              nv40_graph.o nv50_graph.o \
-             nv40_grctx.o \
+             nv40_grctx.o nv50_grctx.o \
              nv04_instmem.o nv50_instmem.o \
              nv50_crtc.o nv50_dac.o nv50_sor.o \
              nv50_cursor.o nv50_display.o nv50_fbcon.o \
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 48227e7..0e0730a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -11,6 +11,8 @@
 #include "nouveau_drm.h"
 #include "nv50_display.h"
 
+#include <linux/vga_switcheroo.h>
+
 #define NOUVEAU_DSM_SUPPORTED 0x00
 #define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00
 
@@ -28,31 +30,30 @@
 #define NOUVEAU_DSM_POWER_SPEED 0x01
 #define NOUVEAU_DSM_POWER_STAMINA 0x02
 
-static int nouveau_dsm(struct drm_device *dev, int func, int arg, int *result)
-{
-	static char muid[] = {
-		0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
-		0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
-	};
+static struct nouveau_dsm_priv {
+	bool dsm_detected;
+	acpi_handle dhandle;
+	acpi_handle dsm_handle;
+} nouveau_dsm_priv;
 
-	struct pci_dev *pdev = dev->pdev;
-	struct acpi_handle *handle;
+static const char nouveau_dsm_muid[] = {
+	0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
+	0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
+};
+
+static int nouveau_dsm(acpi_handle handle, int func, int arg, int *result)
+{
 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_object_list input;
 	union acpi_object params[4];
 	union acpi_object *obj;
 	int err;
 
-	handle = DEVICE_ACPI_HANDLE(&pdev->dev);
-
-	if (!handle)
-		return -ENODEV;
-
 	input.count = 4;
 	input.pointer = params;
 	params[0].type = ACPI_TYPE_BUFFER;
-	params[0].buffer.length = sizeof(muid);
-	params[0].buffer.pointer = (char *)muid;
+	params[0].buffer.length = sizeof(nouveau_dsm_muid);
+	params[0].buffer.pointer = (char *)nouveau_dsm_muid;
 	params[1].type = ACPI_TYPE_INTEGER;
 	params[1].integer.value = 0x00000102;
 	params[2].type = ACPI_TYPE_INTEGER;
@@ -62,7 +63,7 @@
 
 	err = acpi_evaluate_object(handle, "_DSM", &input, &output);
 	if (err) {
-		NV_INFO(dev, "failed to evaluate _DSM: %d\n", err);
+		printk(KERN_INFO "failed to evaluate _DSM: %d\n", err);
 		return err;
 	}
 
@@ -86,40 +87,119 @@
 	return 0;
 }
 
-int nouveau_hybrid_setup(struct drm_device *dev)
+static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id)
 {
-	int result;
+	return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL);
+}
 
-	if (nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STATE,
-								&result))
-		return -ENODEV;
-
-	NV_INFO(dev, "_DSM hardware status gave 0x%x\n", result);
-
-	if (result) { /* Ensure that the external GPU is enabled */
-		nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_SPEED, NULL);
-		nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_SPEED,
-									NULL);
-	} else { /* Stamina mode - disable the external GPU */
-		nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_STAMINA,
-									NULL);
-		nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STAMINA,
-									NULL);
-	}
-
+static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state)
+{
+	int arg;
+	if (state == VGA_SWITCHEROO_ON)
+		arg = NOUVEAU_DSM_POWER_SPEED;
+	else
+		arg = NOUVEAU_DSM_POWER_STAMINA;
+	nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL);
 	return 0;
 }
 
-bool nouveau_dsm_probe(struct drm_device *dev)
+static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id)
 {
-	int support = 0;
+	if (id == VGA_SWITCHEROO_IGD)
+		return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_STAMINA);
+	else
+		return nouveau_dsm_switch_mux(nouveau_dsm_priv.dsm_handle, NOUVEAU_DSM_LED_SPEED);
+}
 
-	if (nouveau_dsm(dev, NOUVEAU_DSM_SUPPORTED,
-				NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &support))
+static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,
+				   enum vga_switcheroo_state state)
+{
+	if (id == VGA_SWITCHEROO_IGD)
+		return 0;
+
+	return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dsm_handle, state);
+}
+
+static int nouveau_dsm_init(void)
+{
+	return 0;
+}
+
+static int nouveau_dsm_get_client_id(struct pci_dev *pdev)
+{
+	if (nouveau_dsm_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
+		return VGA_SWITCHEROO_IGD;
+	else
+		return VGA_SWITCHEROO_DIS;
+}
+
+static struct vga_switcheroo_handler nouveau_dsm_handler = {
+	.switchto = nouveau_dsm_switchto,
+	.power_state = nouveau_dsm_power_state,
+	.init = nouveau_dsm_init,
+	.get_client_id = nouveau_dsm_get_client_id,
+};
+
+static bool nouveau_dsm_pci_probe(struct pci_dev *pdev)
+{
+	acpi_handle dhandle, nvidia_handle;
+	acpi_status status;
+	int ret;
+	uint32_t result;
+
+	dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
+	if (!dhandle)
+		return false;
+	status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
+	if (ACPI_FAILURE(status)) {
+		return false;
+	}
+
+	ret= nouveau_dsm(nvidia_handle, NOUVEAU_DSM_SUPPORTED,
+			 NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result);
+	if (ret < 0)
 		return false;
 
-	if (!support)
-		return false;
-
+	nouveau_dsm_priv.dhandle = dhandle;
+	nouveau_dsm_priv.dsm_handle = nvidia_handle;
 	return true;
 }
+
+static bool nouveau_dsm_detect(void)
+{
+	char acpi_method_name[255] = { 0 };
+	struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
+	struct pci_dev *pdev = NULL;
+	int has_dsm = 0;
+	int vga_count = 0;
+	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
+		vga_count++;
+
+		has_dsm |= (nouveau_dsm_pci_probe(pdev) == true);
+	}
+
+	if (vga_count == 2 && has_dsm) {
+		acpi_get_name(nouveau_dsm_priv.dsm_handle, ACPI_FULL_PATHNAME, &buffer);
+		printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
+		       acpi_method_name);
+		nouveau_dsm_priv.dsm_detected = true;
+		return true;
+	}
+	return false;
+}
+
+void nouveau_register_dsm_handler(void)
+{
+	bool r;
+
+	r = nouveau_dsm_detect();
+	if (!r)
+		return;
+
+	vga_switcheroo_register_handler(&nouveau_dsm_handler);
+}
+
+void nouveau_unregister_dsm_handler(void)
+{
+	vga_switcheroo_unregister_handler();
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 0e9cd1d..75bceee7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -311,11 +311,11 @@
 
 	/* C51 has misaligned regs on purpose. Marvellous */
 	if (reg & 0x2 ||
-	    (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51))
+	    (reg & 0x1 && dev_priv->vbios.chip_version != 0x51))
 		NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg);
 
 	/* warn on C51 regs that haven't been verified accessible in tracing */
-	if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 &&
+	if (reg & 0x1 && dev_priv->vbios.chip_version == 0x51 &&
 	    reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
 		NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n",
 			reg);
@@ -420,7 +420,7 @@
 	LOG_OLD_VALUE(bios_rd32(bios, reg));
 	BIOSLOG(bios, "	Write: Reg: 0x%08X, Data: 0x%08X\n", reg, data);
 
-	if (dev_priv->VBIOS.execute) {
+	if (dev_priv->vbios.execute) {
 		still_alive();
 		nv_wr32(bios->dev, reg, data);
 	}
@@ -647,7 +647,7 @@
 	reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16);
 	reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1;
 
-	if (dev_priv->VBIOS.execute) {
+	if (dev_priv->vbios.execute) {
 		still_alive();
 		nv_wr32(dev, reg + 4, reg1);
 		nv_wr32(dev, reg + 0, reg0);
@@ -689,7 +689,7 @@
 static int dcb_entry_idx_from_crtchead(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 
 	/*
 	 * For the results of this function to be correct, CR44 must have been
@@ -700,7 +700,7 @@
 
 	uint8_t dcb_entry = NVReadVgaCrtc5758(dev, bios->state.crtchead, 0);
 
-	if (dcb_entry > bios->bdcb.dcb.entries) {
+	if (dcb_entry > bios->dcb.entries) {
 		NV_ERROR(dev, "CR58 doesn't have a valid DCB entry currently "
 				"(%02X)\n", dcb_entry);
 		dcb_entry = 0x7f;	/* unused / invalid marker */
@@ -713,25 +713,26 @@
 init_i2c_device_find(struct drm_device *dev, int i2c_index)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct bios_parsed_dcb *bdcb = &dev_priv->VBIOS.bdcb;
+	struct dcb_table *dcb = &dev_priv->vbios.dcb;
 
 	if (i2c_index == 0xff) {
 		/* note: dcb_entry_idx_from_crtchead needs pre-script set-up */
 		int idx = dcb_entry_idx_from_crtchead(dev), shift = 0;
-		int default_indices = bdcb->i2c_default_indices;
+		int default_indices = dcb->i2c_default_indices;
 
-		if (idx != 0x7f && bdcb->dcb.entry[idx].i2c_upper_default)
+		if (idx != 0x7f && dcb->entry[idx].i2c_upper_default)
 			shift = 4;
 
 		i2c_index = (default_indices >> shift) & 0xf;
 	}
 	if (i2c_index == 0x80)	/* g80+ */
-		i2c_index = bdcb->i2c_default_indices & 0xf;
+		i2c_index = dcb->i2c_default_indices & 0xf;
 
 	return nouveau_i2c_find(dev, i2c_index);
 }
 
-static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
+static uint32_t
+get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
 {
 	/*
 	 * For mlv < 0x80, it is an index into a table of TMDS base addresses.
@@ -744,6 +745,7 @@
 	 */
 
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nvbios *bios = &dev_priv->vbios;
 	const int pramdac_offset[13] = {
 		0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000 };
 	const uint32_t pramdac_table[4] = {
@@ -756,13 +758,12 @@
 		dcb_entry = dcb_entry_idx_from_crtchead(dev);
 		if (dcb_entry == 0x7f)
 			return 0;
-		dacoffset = pramdac_offset[
-				dev_priv->VBIOS.bdcb.dcb.entry[dcb_entry].or];
+		dacoffset = pramdac_offset[bios->dcb.entry[dcb_entry].or];
 		if (mlv == 0x81)
 			dacoffset ^= 8;
 		return 0x6808b0 + dacoffset;
 	} else {
-		if (mlv > ARRAY_SIZE(pramdac_table)) {
+		if (mlv >= ARRAY_SIZE(pramdac_table)) {
 			NV_ERROR(dev, "Magic Lookup Value too big (%02X)\n",
 									mlv);
 			return 0;
@@ -2574,19 +2575,19 @@
 
 	const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
 	const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
-	const uint8_t *gpio_table = &bios->data[bios->bdcb.gpio_table_ptr];
+	const uint8_t *gpio_table = &bios->data[bios->dcb.gpio_table_ptr];
 	const uint8_t *gpio_entry;
 	int i;
 
 	if (!iexec->execute)
 		return 1;
 
-	if (bios->bdcb.version != 0x40) {
+	if (bios->dcb.version != 0x40) {
 		NV_ERROR(bios->dev, "DCB table not version 4.0\n");
 		return 0;
 	}
 
-	if (!bios->bdcb.gpio_table_ptr) {
+	if (!bios->dcb.gpio_table_ptr) {
 		NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n");
 		return 0;
 	}
@@ -3123,7 +3124,7 @@
 		      struct dcb_entry *dcbent, int head, bool dl)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	struct init_exec iexec = {true, false};
 
 	NV_TRACE(dev, "0x%04X: Parsing digital output script table\n",
@@ -3140,7 +3141,7 @@
 static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & OUTPUT_C ? 1 : 0);
 	uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]);
 
@@ -3194,7 +3195,7 @@
 	 * of a list of pxclks and script pointers.
 	 */
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	unsigned int outputset = (dcbent->or == 4) ? 1 : 0;
 	uint16_t scriptptr = 0, clktable;
 	uint8_t clktableptr = 0;
@@ -3261,7 +3262,7 @@
 	 */
 
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
 	uint32_t sel_clk_binding, sel_clk;
 	int ret;
@@ -3395,7 +3396,7 @@
 #ifndef __powerpc__
 		NV_ERROR(dev, "Pointer to flat panel table invalid\n");
 #endif
-		bios->pub.digital_min_front_porch = 0x4b;
+		bios->digital_min_front_porch = 0x4b;
 		return 0;
 	}
 
@@ -3428,7 +3429,7 @@
 		 * fptable[4] is the minimum
 		 * RAMDAC_FP_HCRTC -> RAMDAC_FP_HSYNC_START gap
 		 */
-		bios->pub.digital_min_front_porch = fptable[4];
+		bios->digital_min_front_porch = fptable[4];
 		ofs = -7;
 		break;
 	default:
@@ -3467,7 +3468,7 @@
 
 	/* nv4x cards need both a strap value and fpindex of 0xf to use DDC */
 	if (lth.lvds_ver > 0x10)
-		bios->pub.fp_no_ddc = fpstrapping != 0xf || fpindex != 0xf;
+		bios->fp_no_ddc = fpstrapping != 0xf || fpindex != 0xf;
 
 	/*
 	 * If either the strap or xlated fpindex value are 0xf there is no
@@ -3491,7 +3492,7 @@
 bool nouveau_bios_fp_mode(struct drm_device *dev, struct drm_display_mode *mode)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr];
 
 	if (!mode)	/* just checking whether we can produce a mode */
@@ -3544,7 +3545,7 @@
 	 * at which modes should be set up in the dual link style.
 	 *
 	 * Following the header, the BMP (ver 0xa) table has several records,
-	 * indexed by a seperate xlat table, indexed in turn by the fp strap in
+	 * indexed by a separate xlat table, indexed in turn by the fp strap in
 	 * EXTDEV_BOOT. Each record had a config byte, followed by 6 script
 	 * numbers for use by INIT_SUB which controlled panel init and power,
 	 * and finally a dword of ms to sleep between power off and on
@@ -3562,11 +3563,11 @@
 	 * until later, when this function should be called with non-zero pxclk
 	 */
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	int fpstrapping = get_fp_strap(dev, bios), lvdsmanufacturerindex = 0;
 	struct lvdstableheader lth;
 	uint16_t lvdsofs;
-	int ret, chip_version = bios->pub.chip_version;
+	int ret, chip_version = bios->chip_version;
 
 	ret = parse_lvds_manufacturer_table_header(dev, bios, &lth);
 	if (ret)
@@ -3682,7 +3683,7 @@
 			 uint16_t record, int record_len, int record_nr)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	uint32_t entry;
 	uint16_t table;
 	int i, v;
@@ -3716,7 +3717,7 @@
 		      int *length)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	uint8_t *table;
 
 	if (!bios->display.dp_table_ptr) {
@@ -3725,7 +3726,7 @@
 	}
 	table = &bios->data[bios->display.dp_table_ptr];
 
-	if (table[0] != 0x21) {
+	if (table[0] != 0x20 && table[0] != 0x21) {
 		NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n",
 			 table[0]);
 		return NULL;
@@ -3765,7 +3766,7 @@
 	 */
 
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	uint8_t *table = &bios->data[bios->display.script_table_ptr];
 	uint8_t *otable = NULL;
 	uint16_t script;
@@ -3918,8 +3919,8 @@
 	 */
 
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
-	int cv = bios->pub.chip_version;
+	struct nvbios *bios = &dev_priv->vbios;
+	int cv = bios->chip_version;
 	uint16_t clktable = 0, scriptptr;
 	uint32_t sel_clk_binding, sel_clk;
 
@@ -3978,8 +3979,8 @@
 	 */
 
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
-	int cv = bios->pub.chip_version, pllindex = 0;
+	struct nvbios *bios = &dev_priv->vbios;
+	int cv = bios->chip_version, pllindex = 0;
 	uint8_t pll_lim_ver = 0, headerlen = 0, recordlen = 0, entries = 0;
 	uint32_t crystal_strap_mask, crystal_straps;
 
@@ -4332,7 +4333,7 @@
 	 */
 
 	bios->major_version = bios->data[offset + 3];
-	bios->pub.chip_version = bios->data[offset + 2];
+	bios->chip_version = bios->data[offset + 2];
 	NV_TRACE(dev, "Bios version %02x.%02x.%02x.%02x\n",
 		 bios->data[offset + 3], bios->data[offset + 2],
 		 bios->data[offset + 1], bios->data[offset]);
@@ -4402,7 +4403,7 @@
 	}
 
 	/* First entry is normal dac, 2nd tv-out perhaps? */
-	bios->pub.dactestval = ROM32(bios->data[load_table_ptr + headerlen]) & 0x3ff;
+	bios->dactestval = ROM32(bios->data[load_table_ptr + headerlen]) & 0x3ff;
 
 	return 0;
 }
@@ -4526,8 +4527,8 @@
 		return -ENOSYS;
 	}
 
-	bios->pub.dactestval = ROM32(bios->data[daccmpoffset + dacheaderlen]);
-	bios->pub.tvdactestval = ROM32(bios->data[daccmpoffset + dacheaderlen + 4]);
+	bios->dactestval = ROM32(bios->data[daccmpoffset + dacheaderlen]);
+	bios->tvdactestval = ROM32(bios->data[daccmpoffset + dacheaderlen + 4]);
 
 	return 0;
 }
@@ -4796,11 +4797,11 @@
 	uint16_t legacy_scripts_offset, legacy_i2c_offset;
 
 	/* load needed defaults in case we can't parse this info */
-	bios->bdcb.dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX;
-	bios->bdcb.dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX;
-	bios->bdcb.dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX;
-	bios->bdcb.dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX;
-	bios->pub.digital_min_front_porch = 0x4b;
+	bios->dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX;
+	bios->dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX;
+	bios->dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX;
+	bios->dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX;
+	bios->digital_min_front_porch = 0x4b;
 	bios->fmaxvco = 256000;
 	bios->fminvco = 128000;
 	bios->fp.duallink_transition_clk = 90000;
@@ -4907,10 +4908,10 @@
 	bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset];
 	bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1];
 	bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2];
-	bios->bdcb.dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4];
-	bios->bdcb.dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5];
-	bios->bdcb.dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6];
-	bios->bdcb.dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7];
+	bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4];
+	bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5];
+	bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6];
+	bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7];
 
 	if (bmplength > 74) {
 		bios->fmaxvco = ROM32(bmp[67]);
@@ -4984,7 +4985,8 @@
 		else
 			NV_WARN(dev,
 				"DCB I2C table has more entries than indexable "
-				"(%d entries, max index 15)\n", i2ctable[2]);
+				"(%d entries, max %d)\n", i2ctable[2],
+				DCB_MAX_NUM_I2C_ENTRIES);
 		entry_len = i2ctable[3];
 		/* [4] is i2c_default_indices, read in parse_dcb_table() */
 	}
@@ -5000,8 +5002,8 @@
 
 	if (index == 0xf)
 		return 0;
-	if (index > i2c_entries) {
-		NV_ERROR(dev, "DCB I2C index too big (%d > %d)\n",
+	if (index >= i2c_entries) {
+		NV_ERROR(dev, "DCB I2C index too big (%d >= %d)\n",
 			 index, i2ctable[2]);
 		return -ENOENT;
 	}
@@ -5036,7 +5038,7 @@
 static struct dcb_gpio_entry *
 new_gpio_entry(struct nvbios *bios)
 {
-	struct parsed_dcb_gpio *gpio = &bios->bdcb.gpio;
+	struct dcb_gpio_table *gpio = &bios->dcb.gpio;
 
 	return &gpio->entry[gpio->entries++];
 }
@@ -5045,14 +5047,14 @@
 nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	int i;
 
-	for (i = 0; i < bios->bdcb.gpio.entries; i++) {
-		if (bios->bdcb.gpio.entry[i].tag != tag)
+	for (i = 0; i < bios->dcb.gpio.entries; i++) {
+		if (bios->dcb.gpio.entry[i].tag != tag)
 			continue;
 
-		return &bios->bdcb.gpio.entry[i];
+		return &bios->dcb.gpio.entry[i];
 	}
 
 	return NULL;
@@ -5100,7 +5102,7 @@
 parse_dcb_gpio_table(struct nvbios *bios)
 {
 	struct drm_device *dev = bios->dev;
-	uint16_t gpio_table_ptr = bios->bdcb.gpio_table_ptr;
+	uint16_t gpio_table_ptr = bios->dcb.gpio_table_ptr;
 	uint8_t *gpio_table = &bios->data[gpio_table_ptr];
 	int header_len = gpio_table[1],
 	    entries = gpio_table[2],
@@ -5108,7 +5110,7 @@
 	void (*parse_entry)(struct nvbios *, uint16_t) = NULL;
 	int i;
 
-	if (bios->bdcb.version >= 0x40) {
+	if (bios->dcb.version >= 0x40) {
 		if (gpio_table_ptr && entry_len != 4) {
 			NV_WARN(dev, "Invalid DCB GPIO table entry length.\n");
 			return;
@@ -5116,7 +5118,7 @@
 
 		parse_entry = parse_dcb40_gpio_entry;
 
-	} else if (bios->bdcb.version >= 0x30) {
+	} else if (bios->dcb.version >= 0x30) {
 		if (gpio_table_ptr && entry_len != 2) {
 			NV_WARN(dev, "Invalid DCB GPIO table entry length.\n");
 			return;
@@ -5124,7 +5126,7 @@
 
 		parse_entry = parse_dcb30_gpio_entry;
 
-	} else if (bios->bdcb.version >= 0x22) {
+	} else if (bios->dcb.version >= 0x22) {
 		/*
 		 * DCBs older than v3.0 don't really have a GPIO
 		 * table, instead they keep some GPIO info at fixed
@@ -5158,30 +5160,67 @@
 nouveau_bios_connector_entry(struct drm_device *dev, int index)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	struct dcb_connector_table_entry *cte;
 
-	if (index >= bios->bdcb.connector.entries)
+	if (index >= bios->dcb.connector.entries)
 		return NULL;
 
-	cte = &bios->bdcb.connector.entry[index];
+	cte = &bios->dcb.connector.entry[index];
 	if (cte->type == 0xff)
 		return NULL;
 
 	return cte;
 }
 
+static enum dcb_connector_type
+divine_connector_type(struct nvbios *bios, int index)
+{
+	struct dcb_table *dcb = &bios->dcb;
+	unsigned encoders = 0, type = DCB_CONNECTOR_NONE;
+	int i;
+
+	for (i = 0; i < dcb->entries; i++) {
+		if (dcb->entry[i].connector == index)
+			encoders |= (1 << dcb->entry[i].type);
+	}
+
+	if (encoders & (1 << OUTPUT_DP)) {
+		if (encoders & (1 << OUTPUT_TMDS))
+			type = DCB_CONNECTOR_DP;
+		else
+			type = DCB_CONNECTOR_eDP;
+	} else
+	if (encoders & (1 << OUTPUT_TMDS)) {
+		if (encoders & (1 << OUTPUT_ANALOG))
+			type = DCB_CONNECTOR_DVI_I;
+		else
+			type = DCB_CONNECTOR_DVI_D;
+	} else
+	if (encoders & (1 << OUTPUT_ANALOG)) {
+		type = DCB_CONNECTOR_VGA;
+	} else
+	if (encoders & (1 << OUTPUT_LVDS)) {
+		type = DCB_CONNECTOR_LVDS;
+	} else
+	if (encoders & (1 << OUTPUT_TV)) {
+		type = DCB_CONNECTOR_TV_0;
+	}
+
+	return type;
+}
+
 static void
 parse_dcb_connector_table(struct nvbios *bios)
 {
 	struct drm_device *dev = bios->dev;
-	struct dcb_connector_table *ct = &bios->bdcb.connector;
+	struct dcb_connector_table *ct = &bios->dcb.connector;
 	struct dcb_connector_table_entry *cte;
-	uint8_t *conntab = &bios->data[bios->bdcb.connector_table_ptr];
+	uint8_t *conntab = &bios->data[bios->dcb.connector_table_ptr];
 	uint8_t *entry;
 	int i;
 
-	if (!bios->bdcb.connector_table_ptr) {
+	if (!bios->dcb.connector_table_ptr) {
 		NV_DEBUG_KMS(dev, "No DCB connector table present\n");
 		return;
 	}
@@ -5203,6 +5242,7 @@
 			cte->entry = ROM16(entry[0]);
 		else
 			cte->entry = ROM32(entry[0]);
+
 		cte->type  = (cte->entry & 0x000000ff) >> 0;
 		cte->index = (cte->entry & 0x00000f00) >> 8;
 		switch (cte->entry & 0x00033000) {
@@ -5228,10 +5268,33 @@
 
 		NV_INFO(dev, "  %d: 0x%08x: type 0x%02x idx %d tag 0x%02x\n",
 			i, cte->entry, cte->type, cte->index, cte->gpio_tag);
+
+		/* check for known types, fallback to guessing the type
+		 * from attached encoders if we hit an unknown.
+		 */
+		switch (cte->type) {
+		case DCB_CONNECTOR_VGA:
+		case DCB_CONNECTOR_TV_0:
+		case DCB_CONNECTOR_TV_1:
+		case DCB_CONNECTOR_TV_3:
+		case DCB_CONNECTOR_DVI_I:
+		case DCB_CONNECTOR_DVI_D:
+		case DCB_CONNECTOR_LVDS:
+		case DCB_CONNECTOR_DP:
+		case DCB_CONNECTOR_eDP:
+		case DCB_CONNECTOR_HDMI_0:
+		case DCB_CONNECTOR_HDMI_1:
+			break;
+		default:
+			cte->type = divine_connector_type(bios, cte->index);
+			NV_WARN(dev, "unknown type, using 0x%02x", cte->type);
+			break;
+		}
+
 	}
 }
 
-static struct dcb_entry *new_dcb_entry(struct parsed_dcb *dcb)
+static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb)
 {
 	struct dcb_entry *entry = &dcb->entry[dcb->entries];
 
@@ -5241,7 +5304,7 @@
 	return entry;
 }
 
-static void fabricate_vga_output(struct parsed_dcb *dcb, int i2c, int heads)
+static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads)
 {
 	struct dcb_entry *entry = new_dcb_entry(dcb);
 
@@ -5252,7 +5315,7 @@
 	/* "or" mostly unused in early gen crt modesetting, 0 is fine */
 }
 
-static void fabricate_dvi_i_output(struct parsed_dcb *dcb, bool twoHeads)
+static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads)
 {
 	struct dcb_entry *entry = new_dcb_entry(dcb);
 
@@ -5279,7 +5342,7 @@
 #endif
 }
 
-static void fabricate_tv_output(struct parsed_dcb *dcb, bool twoHeads)
+static void fabricate_tv_output(struct dcb_table *dcb, bool twoHeads)
 {
 	struct dcb_entry *entry = new_dcb_entry(dcb);
 
@@ -5290,13 +5353,13 @@
 }
 
 static bool
-parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
+parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
 		  uint32_t conn, uint32_t conf, struct dcb_entry *entry)
 {
 	entry->type = conn & 0xf;
 	entry->i2c_index = (conn >> 4) & 0xf;
 	entry->heads = (conn >> 8) & 0xf;
-	if (bdcb->version >= 0x40)
+	if (dcb->version >= 0x40)
 		entry->connector = (conn >> 12) & 0xf;
 	entry->bus = (conn >> 16) & 0xf;
 	entry->location = (conn >> 20) & 0x3;
@@ -5314,7 +5377,7 @@
 		 * Although the rest of a CRT conf dword is usually
 		 * zeros, mac biosen have stuff there so we must mask
 		 */
-		entry->crtconf.maxfreq = (bdcb->version < 0x30) ?
+		entry->crtconf.maxfreq = (dcb->version < 0x30) ?
 					 (conf & 0xffff) * 10 :
 					 (conf & 0xff) * 10000;
 		break;
@@ -5323,7 +5386,7 @@
 		uint32_t mask;
 		if (conf & 0x1)
 			entry->lvdsconf.use_straps_for_mode = true;
-		if (bdcb->version < 0x22) {
+		if (dcb->version < 0x22) {
 			mask = ~0xd;
 			/*
 			 * The laptop in bug 14567 lies and claims to not use
@@ -5347,7 +5410,7 @@
 			 * Until we even try to use these on G8x, it's
 			 * useless reporting unknown bits.  They all are.
 			 */
-			if (bdcb->version >= 0x40)
+			if (dcb->version >= 0x40)
 				break;
 
 			NV_ERROR(dev, "Unknown LVDS configuration bits, "
@@ -5357,7 +5420,7 @@
 		}
 	case OUTPUT_TV:
 	{
-		if (bdcb->version >= 0x30)
+		if (dcb->version >= 0x30)
 			entry->tvconf.has_component_output = conf & (0x8 << 4);
 		else
 			entry->tvconf.has_component_output = false;
@@ -5384,8 +5447,10 @@
 		break;
 	case 0xe:
 		/* weird g80 mobile type that "nv" treats as a terminator */
-		bdcb->dcb.entries--;
+		dcb->entries--;
 		return false;
+	default:
+		break;
 	}
 
 	/* unsure what DCB version introduces this, 3.0? */
@@ -5396,7 +5461,7 @@
 }
 
 static bool
-parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
+parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb,
 		  uint32_t conn, uint32_t conf, struct dcb_entry *entry)
 {
 	switch (conn & 0x0000000f) {
@@ -5462,27 +5527,27 @@
 	return true;
 }
 
-static bool parse_dcb_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
+static bool parse_dcb_entry(struct drm_device *dev, struct dcb_table *dcb,
 			    uint32_t conn, uint32_t conf)
 {
-	struct dcb_entry *entry = new_dcb_entry(&bdcb->dcb);
+	struct dcb_entry *entry = new_dcb_entry(dcb);
 	bool ret;
 
-	if (bdcb->version >= 0x20)
-		ret = parse_dcb20_entry(dev, bdcb, conn, conf, entry);
+	if (dcb->version >= 0x20)
+		ret = parse_dcb20_entry(dev, dcb, conn, conf, entry);
 	else
-		ret = parse_dcb15_entry(dev, &bdcb->dcb, conn, conf, entry);
+		ret = parse_dcb15_entry(dev, dcb, conn, conf, entry);
 	if (!ret)
 		return ret;
 
-	read_dcb_i2c_entry(dev, bdcb->version, bdcb->i2c_table,
-			   entry->i2c_index, &bdcb->dcb.i2c[entry->i2c_index]);
+	read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
+			   entry->i2c_index, &dcb->i2c[entry->i2c_index]);
 
 	return true;
 }
 
 static
-void merge_like_dcb_entries(struct drm_device *dev, struct parsed_dcb *dcb)
+void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb)
 {
 	/*
 	 * DCB v2.0 lists each output combination separately.
@@ -5534,8 +5599,7 @@
 parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct bios_parsed_dcb *bdcb = &bios->bdcb;
-	struct parsed_dcb *dcb;
+	struct dcb_table *dcb = &bios->dcb;
 	uint16_t dcbptr = 0, i2ctabptr = 0;
 	uint8_t *dcbtable;
 	uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
@@ -5543,9 +5607,6 @@
 	int recordlength = 8, confofs = 4;
 	int i;
 
-	dcb = bios->pub.dcb = &bdcb->dcb;
-	dcb->entries = 0;
-
 	/* get the offset from 0x36 */
 	if (dev_priv->card_type > NV_04) {
 		dcbptr = ROM16(bios->data[0x36]);
@@ -5567,21 +5628,21 @@
 	dcbtable = &bios->data[dcbptr];
 
 	/* get DCB version */
-	bdcb->version = dcbtable[0];
+	dcb->version = dcbtable[0];
 	NV_TRACE(dev, "Found Display Configuration Block version %d.%d\n",
-		 bdcb->version >> 4, bdcb->version & 0xf);
+		 dcb->version >> 4, dcb->version & 0xf);
 
-	if (bdcb->version >= 0x20) { /* NV17+ */
+	if (dcb->version >= 0x20) { /* NV17+ */
 		uint32_t sig;
 
-		if (bdcb->version >= 0x30) { /* NV40+ */
+		if (dcb->version >= 0x30) { /* NV40+ */
 			headerlen = dcbtable[1];
 			entries = dcbtable[2];
 			recordlength = dcbtable[3];
 			i2ctabptr = ROM16(dcbtable[4]);
 			sig = ROM32(dcbtable[6]);
-			bdcb->gpio_table_ptr = ROM16(dcbtable[10]);
-			bdcb->connector_table_ptr = ROM16(dcbtable[20]);
+			dcb->gpio_table_ptr = ROM16(dcbtable[10]);
+			dcb->connector_table_ptr = ROM16(dcbtable[20]);
 		} else {
 			i2ctabptr = ROM16(dcbtable[2]);
 			sig = ROM32(dcbtable[4]);
@@ -5593,7 +5654,7 @@
 					"signature (%08X)\n", sig);
 			return -EINVAL;
 		}
-	} else if (bdcb->version >= 0x15) { /* some NV11 and NV20 */
+	} else if (dcb->version >= 0x15) { /* some NV11 and NV20 */
 		char sig[8] = { 0 };
 
 		strncpy(sig, (char *)&dcbtable[-7], 7);
@@ -5641,14 +5702,11 @@
 	if (!i2ctabptr)
 		NV_WARN(dev, "No pointer to DCB I2C port table\n");
 	else {
-		bdcb->i2c_table = &bios->data[i2ctabptr];
-		if (bdcb->version >= 0x30)
-			bdcb->i2c_default_indices = bdcb->i2c_table[4];
+		dcb->i2c_table = &bios->data[i2ctabptr];
+		if (dcb->version >= 0x30)
+			dcb->i2c_default_indices = dcb->i2c_table[4];
 	}
 
-	parse_dcb_gpio_table(bios);
-	parse_dcb_connector_table(bios);
-
 	if (entries > DCB_MAX_NUM_ENTRIES)
 		entries = DCB_MAX_NUM_ENTRIES;
 
@@ -5673,7 +5731,7 @@
 		NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n",
 			     dcb->entries, connection, config);
 
-		if (!parse_dcb_entry(dev, bdcb, connection, config))
+		if (!parse_dcb_entry(dev, dcb, connection, config))
 			break;
 	}
 
@@ -5681,18 +5739,22 @@
 	 * apart for v2.1+ not being known for requiring merging, this
 	 * guarantees dcbent->index is the index of the entry in the rom image
 	 */
-	if (bdcb->version < 0x21)
+	if (dcb->version < 0x21)
 		merge_like_dcb_entries(dev, dcb);
 
-	return dcb->entries ? 0 : -ENXIO;
+	if (!dcb->entries)
+		return -ENXIO;
+
+	parse_dcb_gpio_table(bios);
+	parse_dcb_connector_table(bios);
+	return 0;
 }
 
 static void
 fixup_legacy_connector(struct nvbios *bios)
 {
-	struct bios_parsed_dcb *bdcb = &bios->bdcb;
-	struct parsed_dcb *dcb = &bdcb->dcb;
-	int high = 0, i;
+	struct dcb_table *dcb = &bios->dcb;
+	int i, i2c, i2c_conn[DCB_MAX_NUM_I2C_ENTRIES] = { };
 
 	/*
 	 * DCB 3.0 also has the table in most cases, but there are some cards
@@ -5700,9 +5762,11 @@
 	 * indices are all 0.  We don't need the connector indices on pre-G80
 	 * chips (yet?) so limit the use to DCB 4.0 and above.
 	 */
-	if (bdcb->version >= 0x40)
+	if (dcb->version >= 0x40)
 		return;
 
+	dcb->connector.entries = 0;
+
 	/*
 	 * No known connector info before v3.0, so make it up.  the rule here
 	 * is: anything on the same i2c bus is considered to be on the same
@@ -5710,37 +5774,38 @@
 	 * its own unique connector index.
 	 */
 	for (i = 0; i < dcb->entries; i++) {
-		if (dcb->entry[i].i2c_index == 0xf)
-			continue;
-
 		/*
 		 * Ignore the I2C index for on-chip TV-out, as there
 		 * are cards with bogus values (nv31m in bug 23212),
 		 * and it's otherwise useless.
 		 */
 		if (dcb->entry[i].type == OUTPUT_TV &&
-		    dcb->entry[i].location == DCB_LOC_ON_CHIP) {
+		    dcb->entry[i].location == DCB_LOC_ON_CHIP)
 			dcb->entry[i].i2c_index = 0xf;
+		i2c = dcb->entry[i].i2c_index;
+
+		if (i2c_conn[i2c]) {
+			dcb->entry[i].connector = i2c_conn[i2c] - 1;
 			continue;
 		}
 
-		dcb->entry[i].connector = dcb->entry[i].i2c_index;
-		if (dcb->entry[i].connector > high)
-			high = dcb->entry[i].connector;
+		dcb->entry[i].connector = dcb->connector.entries++;
+		if (i2c != 0xf)
+			i2c_conn[i2c] = dcb->connector.entries;
 	}
 
-	for (i = 0; i < dcb->entries; i++) {
-		if (dcb->entry[i].i2c_index != 0xf)
-			continue;
-
-		dcb->entry[i].connector = ++high;
+	/* Fake the connector table as well as just connector indices */
+	for (i = 0; i < dcb->connector.entries; i++) {
+		dcb->connector.entry[i].index = i;
+		dcb->connector.entry[i].type = divine_connector_type(bios, i);
+		dcb->connector.entry[i].gpio_tag = 0xff;
 	}
 }
 
 static void
 fixup_legacy_i2c(struct nvbios *bios)
 {
-	struct parsed_dcb *dcb = &bios->bdcb.dcb;
+	struct dcb_table *dcb = &bios->dcb;
 	int i;
 
 	for (i = 0; i < dcb->entries; i++) {
@@ -5826,7 +5891,7 @@
 uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	const uint8_t edid_sig[] = {
 			0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
 	uint16_t offset = 0;
@@ -5859,7 +5924,7 @@
 			    struct dcb_entry *dcbent)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	struct init_exec iexec = { true, false };
 
 	mutex_lock(&bios->lock);
@@ -5872,7 +5937,7 @@
 static bool NVInitVBIOS(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 
 	memset(bios, 0, sizeof(struct nvbios));
 	mutex_init(&bios->lock);
@@ -5888,7 +5953,7 @@
 static int nouveau_parse_vbios_struct(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' };
 	const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 };
 	int offset;
@@ -5915,7 +5980,7 @@
 nouveau_run_vbios_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	int i, ret = 0;
 
 	NVLockVgaCrtcs(dev, false);
@@ -5946,9 +6011,9 @@
 	}
 
 	if (dev_priv->card_type >= NV_50) {
-		for (i = 0; i < bios->bdcb.dcb.entries; i++) {
+		for (i = 0; i < bios->dcb.entries; i++) {
 			nouveau_bios_run_display_table(dev,
-						       &bios->bdcb.dcb.entry[i],
+						       &bios->dcb.entry[i],
 						       0, 0);
 		}
 	}
@@ -5962,11 +6027,11 @@
 nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	struct dcb_i2c_entry *entry;
 	int i;
 
-	entry = &bios->bdcb.dcb.i2c[0];
+	entry = &bios->dcb.i2c[0];
 	for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++, entry++)
 		nouveau_i2c_fini(dev, entry);
 }
@@ -5975,13 +6040,11 @@
 nouveau_bios_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	uint32_t saved_nv_pextdev_boot_0;
 	bool was_locked;
 	int ret;
 
-	dev_priv->vbios = &bios->pub;
-
 	if (!NVInitVBIOS(dev))
 		return -ENODEV;
 
@@ -6023,10 +6086,8 @@
 	bios_wr32(bios, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0);
 
 	ret = nouveau_run_vbios_init(dev);
-	if (ret) {
-		dev_priv->vbios = NULL;
+	if (ret)
 		return ret;
-	}
 
 	/* feature_byte on BMP is poor, but init always sets CR4B */
 	was_locked = NVLockVgaCrtcs(dev, false);
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index fd94bd6..9f688aa 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -34,9 +34,67 @@
 
 #define DCB_LOC_ON_CHIP 0
 
+struct dcb_i2c_entry {
+	uint8_t port_type;
+	uint8_t read, write;
+	struct nouveau_i2c_chan *chan;
+};
+
+enum dcb_gpio_tag {
+	DCB_GPIO_TVDAC0 = 0xc,
+	DCB_GPIO_TVDAC1 = 0x2d,
+};
+
+struct dcb_gpio_entry {
+	enum dcb_gpio_tag tag;
+	int line;
+	bool invert;
+};
+
+struct dcb_gpio_table {
+	int entries;
+	struct dcb_gpio_entry entry[DCB_MAX_NUM_GPIO_ENTRIES];
+};
+
+enum dcb_connector_type {
+	DCB_CONNECTOR_VGA = 0x00,
+	DCB_CONNECTOR_TV_0 = 0x10,
+	DCB_CONNECTOR_TV_1 = 0x11,
+	DCB_CONNECTOR_TV_3 = 0x13,
+	DCB_CONNECTOR_DVI_I = 0x30,
+	DCB_CONNECTOR_DVI_D = 0x31,
+	DCB_CONNECTOR_LVDS = 0x40,
+	DCB_CONNECTOR_DP = 0x46,
+	DCB_CONNECTOR_eDP = 0x47,
+	DCB_CONNECTOR_HDMI_0 = 0x60,
+	DCB_CONNECTOR_HDMI_1 = 0x61,
+	DCB_CONNECTOR_NONE = 0xff
+};
+
+struct dcb_connector_table_entry {
+	uint32_t entry;
+	enum dcb_connector_type type;
+	uint8_t index;
+	uint8_t gpio_tag;
+};
+
+struct dcb_connector_table {
+	int entries;
+	struct dcb_connector_table_entry entry[DCB_MAX_NUM_CONNECTOR_ENTRIES];
+};
+
+enum dcb_type {
+	OUTPUT_ANALOG = 0,
+	OUTPUT_TV = 1,
+	OUTPUT_TMDS = 2,
+	OUTPUT_LVDS = 3,
+	OUTPUT_DP = 6,
+	OUTPUT_ANY = -1
+};
+
 struct dcb_entry {
 	int index;	/* may not be raw dcb index if merging has happened */
-	uint8_t type;
+	enum dcb_type type;
 	uint8_t i2c_index;
 	uint8_t heads;
 	uint8_t connector;
@@ -71,69 +129,22 @@
 	bool i2c_upper_default;
 };
 
-struct dcb_i2c_entry {
-	uint8_t port_type;
-	uint8_t read, write;
-	struct nouveau_i2c_chan *chan;
-};
-
-struct parsed_dcb {
-	int entries;
-	struct dcb_entry entry[DCB_MAX_NUM_ENTRIES];
-	struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES];
-};
-
-enum dcb_gpio_tag {
-	DCB_GPIO_TVDAC0 = 0xc,
-	DCB_GPIO_TVDAC1 = 0x2d,
-};
-
-struct dcb_gpio_entry {
-	enum dcb_gpio_tag tag;
-	int line;
-	bool invert;
-};
-
-struct parsed_dcb_gpio {
-	int entries;
-	struct dcb_gpio_entry entry[DCB_MAX_NUM_GPIO_ENTRIES];
-};
-
-struct dcb_connector_table_entry {
-	uint32_t entry;
-	uint8_t type;
-	uint8_t index;
-	uint8_t gpio_tag;
-};
-
-struct dcb_connector_table {
-	int entries;
-	struct dcb_connector_table_entry entry[DCB_MAX_NUM_CONNECTOR_ENTRIES];
-};
-
-struct bios_parsed_dcb {
+struct dcb_table {
 	uint8_t version;
 
-	struct parsed_dcb dcb;
+	int entries;
+	struct dcb_entry entry[DCB_MAX_NUM_ENTRIES];
 
 	uint8_t *i2c_table;
 	uint8_t i2c_default_indices;
+	struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES];
 
 	uint16_t gpio_table_ptr;
-	struct parsed_dcb_gpio gpio;
+	struct dcb_gpio_table gpio;
 	uint16_t connector_table_ptr;
 	struct dcb_connector_table connector;
 };
 
-enum nouveau_encoder_type {
-	OUTPUT_ANALOG = 0,
-	OUTPUT_TV = 1,
-	OUTPUT_TMDS = 2,
-	OUTPUT_LVDS = 3,
-	OUTPUT_DP = 6,
-	OUTPUT_ANY = -1
-};
-
 enum nouveau_or {
 	OUTPUT_A = (1 << 0),
 	OUTPUT_B = (1 << 1),
@@ -190,8 +201,8 @@
 	int refclk;
 };
 
-struct nouveau_bios_info {
-	struct parsed_dcb *dcb;
+struct nvbios {
+	struct drm_device *dev;
 
 	uint8_t chip_version;
 
@@ -199,11 +210,6 @@
 	uint32_t tvdactestval;
 	uint8_t digital_min_front_porch;
 	bool fp_no_ddc;
-};
-
-struct nvbios {
-	struct drm_device *dev;
-	struct nouveau_bios_info pub;
 
 	struct mutex lock;
 
@@ -234,7 +240,7 @@
 	uint16_t some_script_ptr; /* BIT I + 14 */
 	uint16_t init96_tbl_ptr; /* BIT I + 16 */
 
-	struct bios_parsed_dcb bdcb;
+	struct dcb_table dcb;
 
 	struct {
 		int crtchead;
diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c
index ee2b845..88f9bc0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_calc.c
+++ b/drivers/gpu/drm/nouveau/nouveau_calc.c
@@ -274,7 +274,7 @@
 	 * returns calculated clock
 	 */
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int cv = dev_priv->vbios->chip_version;
+	int cv = dev_priv->vbios.chip_version;
 	int minvco = pll_lim->vco1.minfreq, maxvco = pll_lim->vco1.maxfreq;
 	int minM = pll_lim->vco1.min_m, maxM = pll_lim->vco1.max_m;
 	int minN = pll_lim->vco1.min_n, maxN = pll_lim->vco1.max_n;
@@ -373,7 +373,7 @@
 	 * returns calculated clock
 	 */
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int chip_version = dev_priv->vbios->chip_version;
+	int chip_version = dev_priv->vbios.chip_version;
 	int minvco1 = pll_lim->vco1.minfreq, maxvco1 = pll_lim->vco1.maxfreq;
 	int minvco2 = pll_lim->vco2.minfreq, maxvco2 = pll_lim->vco2.maxfreq;
 	int minU1 = pll_lim->vco1.min_inputfreq, minU2 = pll_lim->vco2.min_inputfreq;
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
index 2281f99..6dfb425 100644
--- a/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -35,22 +35,27 @@
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *pb = chan->pushbuf_bo;
 	struct nouveau_gpuobj *pushbuf = NULL;
-	uint32_t start = pb->bo.mem.mm_node->start << PAGE_SHIFT;
 	int ret;
 
+	if (dev_priv->card_type >= NV_50) {
+		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
+					     dev_priv->vm_end, NV_DMA_ACCESS_RO,
+					     NV_DMA_TARGET_AGP, &pushbuf);
+		chan->pushbuf_base = pb->bo.offset;
+	} else
 	if (pb->bo.mem.mem_type == TTM_PL_TT) {
 		ret = nouveau_gpuobj_gart_dma_new(chan, 0,
 						  dev_priv->gart_info.aper_size,
 						  NV_DMA_ACCESS_RO, &pushbuf,
 						  NULL);
-		chan->pushbuf_base = start;
+		chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT;
 	} else
 	if (dev_priv->card_type != NV_04) {
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
 					     dev_priv->fb_available_size,
 					     NV_DMA_ACCESS_RO,
 					     NV_DMA_TARGET_VIDMEM, &pushbuf);
-		chan->pushbuf_base = start;
+		chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT;
 	} else {
 		/* NV04 cmdbuf hack, from original ddx.. not sure of it's
 		 * exact reason for existing :)  PCI access to cmdbuf in
@@ -61,7 +66,7 @@
 					     dev_priv->fb_available_size,
 					     NV_DMA_ACCESS_RO,
 					     NV_DMA_TARGET_PCI, &pushbuf);
-		chan->pushbuf_base = start;
+		chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT;
 	}
 
 	ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf);
@@ -275,9 +280,18 @@
 	 */
 	nouveau_fence_fini(chan);
 
-	/* Ensure the channel is no longer active on the GPU */
+	/* This will prevent pfifo from switching channels. */
 	pfifo->reassign(dev, false);
 
+	/* We want to give pgraph a chance to idle and get rid of all potential
+	 * errors. We need to do this before the lock, otherwise the irq handler
+	 * is unable to process them.
+	 */
+	if (pgraph->channel(dev) == chan)
+		nouveau_wait_for_idle(dev);
+
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+
 	pgraph->fifo_access(dev, false);
 	if (pgraph->channel(dev) == chan)
 		pgraph->unload_context(dev);
@@ -293,6 +307,8 @@
 
 	pfifo->reassign(dev, true);
 
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
 	/* Release the channel's resources */
 	nouveau_gpuobj_ref_del(dev, &chan->pushbuf);
 	if (chan->pushbuf_bo) {
@@ -369,6 +385,14 @@
 		return ret;
 	init->channel  = chan->id;
 
+	if (chan->dma.ib_max)
+		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
+					NOUVEAU_GEM_DOMAIN_GART;
+	else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM)
+		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
+	else
+		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
+
 	init->subchan[0].handle = NvM2MF;
 	if (dev_priv->card_type < NV_50)
 		init->subchan[0].grclass = 0x0039;
@@ -408,7 +432,6 @@
  ***********************************/
 
 struct drm_ioctl_desc nouveau_ioctls[] = {
-	DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
@@ -418,13 +441,9 @@
 	DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF_CALL, nouveau_gem_ioctl_pushbuf_call, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PIN, nouveau_gem_ioctl_pin, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_UNPIN, nouveau_gem_ioctl_unpin, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF_CALL2, nouveau_gem_ioctl_pushbuf_call2, DRM_AUTH),
 };
 
 int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index d2f6335..24327f46 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -218,7 +218,7 @@
 			connector->interlace_allowed = true;
 	}
 
-	if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
+	if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
 		drm_connector_property_set_value(connector,
 			dev->mode_config.dvi_i_subconnector_property,
 			nv_encoder->dcb->type == OUTPUT_TMDS ?
@@ -236,15 +236,17 @@
 	struct nouveau_i2c_chan *i2c;
 	int type, flags;
 
-	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+	if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS)
 		nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
 	if (nv_encoder && nv_connector->native_mode) {
+		unsigned status = connector_status_connected;
+
 #ifdef CONFIG_ACPI
 		if (!nouveau_ignorelid && !acpi_lid_open())
-			return connector_status_disconnected;
+			status = connector_status_unknown;
 #endif
 		nouveau_connector_set_encoder(connector, nv_encoder);
-		return connector_status_connected;
+		return status;
 	}
 
 	/* Cleanup the previous EDID block. */
@@ -279,7 +281,7 @@
 		 * same i2c channel so the value returned from ddc_detect
 		 * isn't necessarily correct.
 		 */
-		if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
+		if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
 			if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
 				type = OUTPUT_TMDS;
 			else
@@ -321,11 +323,11 @@
 static void
 nouveau_connector_force(struct drm_connector *connector)
 {
-	struct drm_device *dev = connector->dev;
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_encoder *nv_encoder;
 	int type;
 
-	if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
+	if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
 		if (connector->force == DRM_FORCE_ON_DIGITAL)
 			type = OUTPUT_TMDS;
 		else
@@ -335,7 +337,7 @@
 
 	nv_encoder = find_encoder_by_type(connector, type);
 	if (!nv_encoder) {
-		NV_ERROR(dev, "can't find encoder to force %s on!\n",
+		NV_ERROR(connector->dev, "can't find encoder to force %s on!\n",
 			 drm_get_connector_name(connector));
 		connector->status = connector_status_disconnected;
 		return;
@@ -369,7 +371,7 @@
 		}
 
 		/* LVDS always needs gpu scaling */
-		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS &&
+		if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS &&
 		    value == DRM_MODE_SCALE_NONE)
 			return -EINVAL;
 
@@ -535,7 +537,7 @@
 	/* If we're not LVDS, destroy the previous native mode, the attached
 	 * monitor could have changed.
 	 */
-	if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
+	if (nv_connector->dcb->type != DCB_CONNECTOR_LVDS &&
 	    nv_connector->native_mode) {
 		drm_mode_destroy(dev, nv_connector->native_mode);
 		nv_connector->native_mode = NULL;
@@ -563,7 +565,7 @@
 		ret = get_slave_funcs(nv_encoder)->
 			get_modes(to_drm_encoder(nv_encoder), connector);
 
-	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+	if (nv_encoder->dcb->type == OUTPUT_LVDS)
 		ret += nouveau_connector_scaler_modes_add(connector);
 
 	return ret;
@@ -613,6 +615,9 @@
 
 		clock *= 3;
 		break;
+	default:
+		BUG_ON(1);
+		return MODE_BAD;
 	}
 
 	if (clock < min_clock)
@@ -680,7 +685,7 @@
 	/* Firstly try getting EDID over DDC, if allowed and I2C channel
 	 * is available.
 	 */
-	if (!dev_priv->VBIOS.pub.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
+	if (!dev_priv->vbios.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
 		i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
 
 	if (i2c) {
@@ -695,7 +700,7 @@
 	 */
 	if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) &&
 	     (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
-	      dev_priv->VBIOS.pub.fp_no_ddc)) {
+	      dev_priv->vbios.fp_no_ddc)) {
 		nv_connector->native_mode = drm_mode_duplicate(dev, &native);
 		goto out;
 	}
@@ -704,7 +709,7 @@
 	 * stored for the panel stored in them.
 	 */
 	if (!nv_connector->edid && !nv_connector->native_mode &&
-	    !dev_priv->VBIOS.pub.fp_no_ddc) {
+	    !dev_priv->vbios.fp_no_ddc) {
 		struct edid *edid =
 			(struct edid *)nouveau_bios_embedded_edid(dev);
 		if (edid) {
@@ -739,46 +744,66 @@
 }
 
 int
-nouveau_connector_create(struct drm_device *dev, int index, int type)
+nouveau_connector_create(struct drm_device *dev,
+			 struct dcb_connector_table_entry *dcb)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_connector *nv_connector = NULL;
 	struct drm_connector *connector;
 	struct drm_encoder *encoder;
-	int ret;
+	int ret, type;
 
 	NV_DEBUG_KMS(dev, "\n");
 
+	switch (dcb->type) {
+	case DCB_CONNECTOR_NONE:
+		return 0;
+	case DCB_CONNECTOR_VGA:
+		NV_INFO(dev, "Detected a VGA connector\n");
+		type = DRM_MODE_CONNECTOR_VGA;
+		break;
+	case DCB_CONNECTOR_TV_0:
+	case DCB_CONNECTOR_TV_1:
+	case DCB_CONNECTOR_TV_3:
+		NV_INFO(dev, "Detected a TV connector\n");
+		type = DRM_MODE_CONNECTOR_TV;
+		break;
+	case DCB_CONNECTOR_DVI_I:
+		NV_INFO(dev, "Detected a DVI-I connector\n");
+		type = DRM_MODE_CONNECTOR_DVII;
+		break;
+	case DCB_CONNECTOR_DVI_D:
+		NV_INFO(dev, "Detected a DVI-D connector\n");
+		type = DRM_MODE_CONNECTOR_DVID;
+		break;
+	case DCB_CONNECTOR_HDMI_0:
+	case DCB_CONNECTOR_HDMI_1:
+		NV_INFO(dev, "Detected a HDMI connector\n");
+		type = DRM_MODE_CONNECTOR_HDMIA;
+		break;
+	case DCB_CONNECTOR_LVDS:
+		NV_INFO(dev, "Detected a LVDS connector\n");
+		type = DRM_MODE_CONNECTOR_LVDS;
+		break;
+	case DCB_CONNECTOR_DP:
+		NV_INFO(dev, "Detected a DisplayPort connector\n");
+		type = DRM_MODE_CONNECTOR_DisplayPort;
+		break;
+	case DCB_CONNECTOR_eDP:
+		NV_INFO(dev, "Detected an eDP connector\n");
+		type = DRM_MODE_CONNECTOR_eDP;
+		break;
+	default:
+		NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type);
+		return -EINVAL;
+	}
+
 	nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
 	if (!nv_connector)
 		return -ENOMEM;
-	nv_connector->dcb = nouveau_bios_connector_entry(dev, index);
+	nv_connector->dcb = dcb;
 	connector = &nv_connector->base;
 
-	switch (type) {
-	case DRM_MODE_CONNECTOR_VGA:
-		NV_INFO(dev, "Detected a VGA connector\n");
-		break;
-	case DRM_MODE_CONNECTOR_DVID:
-		NV_INFO(dev, "Detected a DVI-D connector\n");
-		break;
-	case DRM_MODE_CONNECTOR_DVII:
-		NV_INFO(dev, "Detected a DVI-I connector\n");
-		break;
-	case DRM_MODE_CONNECTOR_LVDS:
-		NV_INFO(dev, "Detected a LVDS connector\n");
-		break;
-	case DRM_MODE_CONNECTOR_TV:
-		NV_INFO(dev, "Detected a TV connector\n");
-		break;
-	case DRM_MODE_CONNECTOR_DisplayPort:
-		NV_INFO(dev, "Detected a DisplayPort connector\n");
-		break;
-	default:
-		NV_ERROR(dev, "Unknown connector, this is not good.\n");
-		break;
-	}
-
 	/* defaults, will get overridden in detect() */
 	connector->interlace_allowed = false;
 	connector->doublescan_allowed = false;
@@ -786,44 +811,11 @@
 	drm_connector_init(dev, connector, &nouveau_connector_funcs, type);
 	drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
 
-	/* Init DVI-I specific properties */
-	if (type == DRM_MODE_CONNECTOR_DVII) {
-		drm_mode_create_dvi_i_properties(dev);
-		drm_connector_attach_property(connector, dev->mode_config.dvi_i_subconnector_property, 0);
-		drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
-	}
-
-	if (type != DRM_MODE_CONNECTOR_LVDS)
-		nv_connector->use_dithering = false;
-
-	if (type == DRM_MODE_CONNECTOR_DVID ||
-	    type == DRM_MODE_CONNECTOR_DVII ||
-	    type == DRM_MODE_CONNECTOR_LVDS ||
-	    type == DRM_MODE_CONNECTOR_DisplayPort) {
-		nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
-
-		drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property,
-					      nv_connector->scaling_mode);
-		drm_connector_attach_property(connector, dev->mode_config.dithering_mode_property,
-					      nv_connector->use_dithering ? DRM_MODE_DITHERING_ON
-					      : DRM_MODE_DITHERING_OFF);
-
-	} else {
-		nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
-
-		if (type == DRM_MODE_CONNECTOR_VGA  &&
-				dev_priv->card_type >= NV_50) {
-			drm_connector_attach_property(connector,
-					dev->mode_config.scaling_mode_property,
-					nv_connector->scaling_mode);
-		}
-	}
-
 	/* attach encoders */
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 
-		if (nv_encoder->dcb->connector != index)
+		if (nv_encoder->dcb->connector != dcb->index)
 			continue;
 
 		if (get_slave_funcs(nv_encoder))
@@ -832,9 +824,52 @@
 		drm_mode_connector_attach_encoder(connector, encoder);
 	}
 
+	if (!connector->encoder_ids[0]) {
+		NV_WARN(dev, "  no encoders, ignoring\n");
+		drm_connector_cleanup(connector);
+		kfree(connector);
+		return 0;
+	}
+
+	/* Init DVI-I specific properties */
+	if (dcb->type == DCB_CONNECTOR_DVI_I) {
+		drm_mode_create_dvi_i_properties(dev);
+		drm_connector_attach_property(connector, dev->mode_config.dvi_i_subconnector_property, 0);
+		drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
+	}
+
+	if (dcb->type != DCB_CONNECTOR_LVDS)
+		nv_connector->use_dithering = false;
+
+	switch (dcb->type) {
+	case DCB_CONNECTOR_VGA:
+		if (dev_priv->card_type >= NV_50) {
+			drm_connector_attach_property(connector,
+					dev->mode_config.scaling_mode_property,
+					nv_connector->scaling_mode);
+		}
+		/* fall-through */
+	case DCB_CONNECTOR_TV_0:
+	case DCB_CONNECTOR_TV_1:
+	case DCB_CONNECTOR_TV_3:
+		nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
+		break;
+	default:
+		nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
+
+		drm_connector_attach_property(connector,
+				dev->mode_config.scaling_mode_property,
+				nv_connector->scaling_mode);
+		drm_connector_attach_property(connector,
+				dev->mode_config.dithering_mode_property,
+				nv_connector->use_dithering ?
+				DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF);
+		break;
+	}
+
 	drm_sysfs_connector_add(connector);
 
-	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+	if (dcb->type == DCB_CONNECTOR_LVDS) {
 		ret = nouveau_connector_create_lvds(dev, connector);
 		if (ret) {
 			connector->funcs->destroy(connector);
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 728b809..4ef38ab 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -49,6 +49,7 @@
 	return container_of(con, struct nouveau_connector, base);
 }
 
-int nouveau_connector_create(struct drm_device *dev, int i2c_index, int type);
+int nouveau_connector_create(struct drm_device *,
+			     struct dcb_connector_table_entry *);
 
 #endif /* __NOUVEAU_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
index d79db36..8ff9ef5 100644
--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c
@@ -47,12 +47,23 @@
 	seq_printf(m, "           cur: 0x%08x\n", chan->dma.cur << 2);
 	seq_printf(m, "           put: 0x%08x\n", chan->dma.put << 2);
 	seq_printf(m, "          free: 0x%08x\n", chan->dma.free << 2);
+	if (chan->dma.ib_max) {
+		seq_printf(m, "        ib max: 0x%08x\n", chan->dma.ib_max);
+		seq_printf(m, "        ib put: 0x%08x\n", chan->dma.ib_put);
+		seq_printf(m, "       ib free: 0x%08x\n", chan->dma.ib_free);
+	}
 
 	seq_printf(m, "gpu fifo state:\n");
 	seq_printf(m, "           get: 0x%08x\n",
 					nvchan_rd32(chan, chan->user_get));
 	seq_printf(m, "           put: 0x%08x\n",
 					nvchan_rd32(chan, chan->user_put));
+	if (chan->dma.ib_max) {
+		seq_printf(m, "        ib get: 0x%08x\n",
+			   nvchan_rd32(chan, 0x88));
+		seq_printf(m, "        ib put: 0x%08x\n",
+			   nvchan_rd32(chan, 0x8c));
+	}
 
 	seq_printf(m, "last fence    : %d\n", chan->fence.sequence);
 	seq_printf(m, "last signalled: %d\n", chan->fence.sequence_ack);
@@ -133,9 +144,22 @@
 	return 0;
 }
 
+static int
+nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_nouveau_private *dev_priv = node->minor->dev->dev_private;
+	int i;
+
+	for (i = 0; i < dev_priv->vbios.length; i++)
+		seq_printf(m, "%c", dev_priv->vbios.data[i]);
+	return 0;
+}
+
 static struct drm_info_list nouveau_debugfs_list[] = {
 	{ "chipset", nouveau_debugfs_chipset_info, 0, NULL },
 	{ "memory", nouveau_debugfs_memory_info, 0, NULL },
+	{ "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL },
 };
 #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index dfc9439..cf1c5c0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -39,11 +39,8 @@
 	if (drm_fb->fbdev)
 		nouveau_fbcon_remove(dev, drm_fb);
 
-	if (fb->nvbo) {
-		mutex_lock(&dev->struct_mutex);
-		drm_gem_object_unreference(fb->nvbo->gem);
-		mutex_unlock(&dev->struct_mutex);
-	}
+	if (fb->nvbo)
+		drm_gem_object_unreference_unlocked(fb->nvbo->gem);
 
 	drm_framebuffer_cleanup(drm_fb);
 	kfree(fb);
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index 50d9e67..c8482a1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -32,7 +32,22 @@
 void
 nouveau_dma_pre_init(struct nouveau_channel *chan)
 {
-	chan->dma.max  = (chan->pushbuf_bo->bo.mem.size >> 2) - 2;
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_bo *pushbuf = chan->pushbuf_bo;
+
+	if (dev_priv->card_type == NV_50) {
+		const int ib_size = pushbuf->bo.mem.size / 2;
+
+		chan->dma.ib_base = (pushbuf->bo.mem.size - ib_size) >> 2;
+		chan->dma.ib_max = (ib_size / 8) - 1;
+		chan->dma.ib_put = 0;
+		chan->dma.ib_free = chan->dma.ib_max - chan->dma.ib_put;
+
+		chan->dma.max = (pushbuf->bo.mem.size - ib_size) >> 2;
+	} else {
+		chan->dma.max  = (pushbuf->bo.mem.size >> 2) - 2;
+	}
+
 	chan->dma.put  = 0;
 	chan->dma.cur  = chan->dma.put;
 	chan->dma.free = chan->dma.max - chan->dma.cur;
@@ -162,12 +177,101 @@
 	return (val - chan->pushbuf_base) >> 2;
 }
 
+void
+nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
+	      int delta, int length)
+{
+	struct nouveau_bo *pb = chan->pushbuf_bo;
+	uint64_t offset = bo->bo.offset + delta;
+	int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
+
+	BUG_ON(chan->dma.ib_free < 1);
+	nouveau_bo_wr32(pb, ip++, lower_32_bits(offset));
+	nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8);
+
+	chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max;
+	nvchan_wr32(chan, 0x8c, chan->dma.ib_put);
+	chan->dma.ib_free--;
+}
+
+static int
+nv50_dma_push_wait(struct nouveau_channel *chan, int count)
+{
+	uint32_t cnt = 0, prev_get = 0;
+
+	while (chan->dma.ib_free < count) {
+		uint32_t get = nvchan_rd32(chan, 0x88);
+		if (get != prev_get) {
+			prev_get = get;
+			cnt = 0;
+		}
+
+		if ((++cnt & 0xff) == 0) {
+			DRM_UDELAY(1);
+			if (cnt > 100000)
+				return -EBUSY;
+		}
+
+		chan->dma.ib_free = get - chan->dma.ib_put;
+		if (chan->dma.ib_free <= 0)
+			chan->dma.ib_free += chan->dma.ib_max + 1;
+	}
+
+	return 0;
+}
+
+static int
+nv50_dma_wait(struct nouveau_channel *chan, int slots, int count)
+{
+	uint32_t cnt = 0, prev_get = 0;
+	int ret;
+
+	ret = nv50_dma_push_wait(chan, slots + 1);
+	if (unlikely(ret))
+		return ret;
+
+	while (chan->dma.free < count) {
+		int get = READ_GET(chan, &prev_get, &cnt);
+		if (unlikely(get < 0)) {
+			if (get == -EINVAL)
+				continue;
+
+			return get;
+		}
+
+		if (get <= chan->dma.cur) {
+			chan->dma.free = chan->dma.max - chan->dma.cur;
+			if (chan->dma.free >= count)
+				break;
+
+			FIRE_RING(chan);
+			do {
+				get = READ_GET(chan, &prev_get, &cnt);
+				if (unlikely(get < 0)) {
+					if (get == -EINVAL)
+						continue;
+					return get;
+				}
+			} while (get == 0);
+			chan->dma.cur = 0;
+			chan->dma.put = 0;
+		}
+
+		chan->dma.free = get - chan->dma.cur - 1;
+	}
+
+	return 0;
+}
+
 int
-nouveau_dma_wait(struct nouveau_channel *chan, int size)
+nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size)
 {
 	uint32_t prev_get = 0, cnt = 0;
 	int get;
 
+	if (chan->dma.ib_max)
+		return nv50_dma_wait(chan, slots, size);
+
 	while (chan->dma.free < size) {
 		get = READ_GET(chan, &prev_get, &cnt);
 		if (unlikely(get == -EBUSY))
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index dabfd65..8b05c15 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -31,6 +31,9 @@
 #define NOUVEAU_DMA_DEBUG 0
 #endif
 
+void nv50_dma_push(struct nouveau_channel *, struct nouveau_bo *,
+		   int delta, int length);
+
 /*
  * There's a hw race condition where you can't jump to your PUT offset,
  * to avoid this we jump to offset + SKIPS and fill the difference with
@@ -96,13 +99,11 @@
 static __must_check inline int
 RING_SPACE(struct nouveau_channel *chan, int size)
 {
-	if (chan->dma.free < size) {
-		int ret;
+	int ret;
 
-		ret = nouveau_dma_wait(chan, size);
-		if (ret)
-			return ret;
-	}
+	ret = nouveau_dma_wait(chan, 1, size);
+	if (ret)
+		return ret;
 
 	chan->dma.free -= size;
 	return 0;
@@ -146,7 +147,13 @@
 		return;
 	chan->accel_done = true;
 
-	WRITE_PUT(chan->dma.cur);
+	if (chan->dma.ib_max) {
+		nv50_dma_push(chan, chan->pushbuf_bo, chan->dma.put << 2,
+			      (chan->dma.cur - chan->dma.put) << 2);
+	} else {
+		WRITE_PUT(chan->dma.cur);
+	}
+
 	chan->dma.put = chan->dma.cur;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index da3b93b..30cc09e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -75,11 +75,11 @@
 int nouveau_ignorelid = 0;
 module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
 
-MODULE_PARM_DESC(noagp, "Disable all acceleration");
+MODULE_PARM_DESC(noaccel, "Disable all acceleration");
 int nouveau_noaccel = 0;
 module_param_named(noaccel, nouveau_noaccel, int, 0400);
 
-MODULE_PARM_DESC(noagp, "Disable fbcon acceleration");
+MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
 int nouveau_nofbaccel = 0;
 module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
 
@@ -135,7 +135,7 @@
 	drm_put_dev(dev);
 }
 
-static int
+int
 nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
@@ -233,7 +233,7 @@
 	return ret;
 }
 
-static int
+int
 nouveau_pci_resume(struct pci_dev *pdev)
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
@@ -402,8 +402,10 @@
 			nouveau_modeset = 1;
 	}
 
-	if (nouveau_modeset == 1)
+	if (nouveau_modeset == 1) {
 		driver.driver_features |= DRIVER_MODESET;
+		nouveau_register_dsm_handler();
+	}
 
 	return drm_init(&driver);
 }
@@ -411,6 +413,7 @@
 static void __exit nouveau_exit(void)
 {
 	drm_exit(&driver);
+	nouveau_unregister_dsm_handler();
 }
 
 module_init(nouveau_init);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 1c15ef3..4b9aaf2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -34,7 +34,7 @@
 
 #define DRIVER_MAJOR		0
 #define DRIVER_MINOR		0
-#define DRIVER_PATCHLEVEL	15
+#define DRIVER_PATCHLEVEL	16
 
 #define NOUVEAU_FAMILY   0x0000FFFF
 #define NOUVEAU_FLAGS    0xFFFF0000
@@ -83,6 +83,7 @@
 	struct drm_file *reserved_by;
 	struct list_head entry;
 	int pbbo_index;
+	bool validate_mapped;
 
 	struct nouveau_channel *channel;
 
@@ -239,6 +240,11 @@
 		int cur;
 		int put;
 		/* access via pushbuf_bo */
+
+		int ib_base;
+		int ib_max;
+		int ib_free;
+		int ib_put;
 	} dma;
 
 	uint32_t sw_subchannel[8];
@@ -533,6 +539,9 @@
 	struct nouveau_engine engine;
 	struct nouveau_channel *channel;
 
+	/* For PFIFO and PGRAPH. */
+	spinlock_t context_switch_lock;
+
 	/* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */
 	struct nouveau_gpuobj *ramht;
 	uint32_t ramin_rsvd_vram;
@@ -544,7 +553,7 @@
 	uint32_t ramro_offset;
 	uint32_t ramro_size;
 
-	/* base physical adresses */
+	/* base physical addresses */
 	uint64_t fb_phys;
 	uint64_t fb_available_size;
 	uint64_t fb_mappable_pages;
@@ -596,8 +605,7 @@
 
 	struct list_head gpuobj_list;
 
-	struct nvbios VBIOS;
-	struct nouveau_bios_info *vbios;
+	struct nvbios vbios;
 
 	struct nv04_mode_state mode_reg;
 	struct nv04_mode_state saved_reg;
@@ -614,7 +622,6 @@
 	} susres;
 
 	struct backlight_device *backlight;
-	bool acpi_dsm;
 
 	struct nouveau_channel *evo;
 
@@ -682,6 +689,9 @@
 extern int nouveau_nofbaccel;
 extern int nouveau_noaccel;
 
+extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state);
+extern int nouveau_pci_resume(struct pci_dev *pdev);
+
 /* nouveau_state.c */
 extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
 extern int  nouveau_load(struct drm_device *, unsigned long flags);
@@ -696,12 +706,6 @@
 			       uint32_t reg, uint32_t mask, uint32_t val);
 extern bool nouveau_wait_for_idle(struct drm_device *);
 extern int  nouveau_card_init(struct drm_device *);
-extern int  nouveau_ioctl_card_init(struct drm_device *, void *data,
-				    struct drm_file *);
-extern int  nouveau_ioctl_suspend(struct drm_device *, void *data,
-				  struct drm_file *);
-extern int  nouveau_ioctl_resume(struct drm_device *, void *data,
-				 struct drm_file *);
 
 /* nouveau_mem.c */
 extern int  nouveau_mem_init_heap(struct mem_block **, uint64_t start,
@@ -845,21 +849,15 @@
 /* nouveau_dma.c */
 extern void nouveau_dma_pre_init(struct nouveau_channel *);
 extern int  nouveau_dma_init(struct nouveau_channel *);
-extern int  nouveau_dma_wait(struct nouveau_channel *, int size);
+extern int  nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
 
 /* nouveau_acpi.c */
-#ifdef CONFIG_ACPI
-extern int nouveau_hybrid_setup(struct drm_device *dev);
-extern bool nouveau_dsm_probe(struct drm_device *dev);
+#if defined(CONFIG_ACPI)
+void nouveau_register_dsm_handler(void);
+void nouveau_unregister_dsm_handler(void);
 #else
-static inline int nouveau_hybrid_setup(struct drm_device *dev)
-{
-	return 0;
-}
-static inline bool nouveau_dsm_probe(struct drm_device *dev)
-{
-	return false;
-}
+static inline void nouveau_register_dsm_handler(void) {}
+static inline void nouveau_unregister_dsm_handler(void) {}
 #endif
 
 /* nouveau_backlight.c */
@@ -1027,6 +1025,7 @@
 extern int  nv50_graph_load_context(struct nouveau_channel *);
 extern int  nv50_graph_unload_context(struct drm_device *);
 extern void nv50_graph_context_switch(struct drm_device *);
+extern int  nv50_grctx_init(struct nouveau_grctx *);
 
 /* nouveau_grctx.c */
 extern int  nouveau_grctx_prog_load(struct drm_device *);
@@ -1152,16 +1151,6 @@
 				 struct drm_file *);
 extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *,
 				     struct drm_file *);
-extern int nouveau_gem_ioctl_pushbuf_call(struct drm_device *, void *,
-					  struct drm_file *);
-extern int nouveau_gem_ioctl_pushbuf_call2(struct drm_device *, void *,
-					   struct drm_file *);
-extern int nouveau_gem_ioctl_pin(struct drm_device *, void *,
-				 struct drm_file *);
-extern int nouveau_gem_ioctl_unpin(struct drm_device *, void *,
-				   struct drm_file *);
-extern int nouveau_gem_ioctl_tile(struct drm_device *, void *,
-				  struct drm_file *);
 extern int nouveau_gem_ioctl_cpu_prep(struct drm_device *, void *,
 				      struct drm_file *);
 extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index ea879a2..68cedd9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -36,6 +36,7 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/screen_info.h>
+#include <linux/vga_switcheroo.h>
 
 #include "drmP.h"
 #include "drm.h"
@@ -370,6 +371,7 @@
 						nvbo->bo.offset, nvbo);
 
 	mutex_unlock(&dev->struct_mutex);
+	vga_switcheroo_client_fb_set(dev->pdev, info);
 	return 0;
 
 out_unref:
@@ -401,10 +403,8 @@
 
 		unregister_framebuffer(info);
 		nouveau_bo_unmap(nouveau_fb->nvbo);
-		mutex_lock(&dev->struct_mutex);
-		drm_gem_object_unreference(nouveau_fb->nvbo->gem);
+		drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem);
 		nouveau_fb->nvbo = NULL;
-		mutex_unlock(&dev->struct_mutex);
 		if (par)
 			drm_fb_helper_free(&par->helper);
 		framebuffer_release(info);
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 70cc308..0d22f66 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -167,12 +167,10 @@
 
 	ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle);
 out:
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_handle_unreference(nvbo->gem);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_handle_unreference_unlocked(nvbo->gem);
 
 	if (ret)
-		drm_gem_object_unreference(nvbo->gem);
+		drm_gem_object_unreference_unlocked(nvbo->gem);
 	return ret;
 }
 
@@ -243,6 +241,11 @@
 			nouveau_fence_unref((void *)&prev_fence);
 		}
 
+		if (unlikely(nvbo->validate_mapped)) {
+			ttm_bo_kunmap(&nvbo->kmap);
+			nvbo->validate_mapped = false;
+		}
+
 		list_del(&nvbo->entry);
 		nvbo->reserved_by = NULL;
 		ttm_bo_unreserve(&nvbo->bo);
@@ -302,11 +305,14 @@
 			if (ret == -EAGAIN)
 				ret = ttm_bo_wait_unreserved(&nvbo->bo, false);
 			drm_gem_object_unreference(gem);
-			if (ret)
+			if (ret) {
+				NV_ERROR(dev, "fail reserve\n");
 				return ret;
+			}
 			goto retry;
 		}
 
+		b->user_priv = (uint64_t)(unsigned long)nvbo;
 		nvbo->reserved_by = file_priv;
 		nvbo->pbbo_index = i;
 		if ((b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
@@ -336,8 +342,10 @@
 			}
 
 			ret = ttm_bo_wait_cpu(&nvbo->bo, false);
-			if (ret)
+			if (ret) {
+				NV_ERROR(dev, "fail wait_cpu\n");
 				return ret;
+			}
 			goto retry;
 		}
 	}
@@ -351,6 +359,7 @@
 {
 	struct drm_nouveau_gem_pushbuf_bo __user *upbbo =
 				(void __force __user *)(uintptr_t)user_pbbo_ptr;
+	struct drm_device *dev = chan->dev;
 	struct nouveau_bo *nvbo;
 	int ret, relocs = 0;
 
@@ -362,39 +371,46 @@
 			spin_lock(&nvbo->bo.lock);
 			ret = ttm_bo_wait(&nvbo->bo, false, false, false);
 			spin_unlock(&nvbo->bo.lock);
-			if (unlikely(ret))
+			if (unlikely(ret)) {
+				NV_ERROR(dev, "fail wait other chan\n");
 				return ret;
+			}
 		}
 
 		ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains,
 					     b->write_domains,
 					     b->valid_domains);
-		if (unlikely(ret))
+		if (unlikely(ret)) {
+			NV_ERROR(dev, "fail set_domain\n");
 			return ret;
+		}
 
 		nvbo->channel = chan;
 		ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
 				      false, false);
 		nvbo->channel = NULL;
-		if (unlikely(ret))
+		if (unlikely(ret)) {
+			NV_ERROR(dev, "fail ttm_validate\n");
 			return ret;
+		}
 
-		if (nvbo->bo.offset == b->presumed_offset &&
+		if (nvbo->bo.offset == b->presumed.offset &&
 		    ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
-		      b->presumed_domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
+		      b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
 		     (nvbo->bo.mem.mem_type == TTM_PL_TT &&
-		      b->presumed_domain & NOUVEAU_GEM_DOMAIN_GART)))
+		      b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART)))
 			continue;
 
 		if (nvbo->bo.mem.mem_type == TTM_PL_TT)
-			b->presumed_domain = NOUVEAU_GEM_DOMAIN_GART;
+			b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
 		else
-			b->presumed_domain = NOUVEAU_GEM_DOMAIN_VRAM;
-		b->presumed_offset = nvbo->bo.offset;
-		b->presumed_ok = 0;
+			b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
+		b->presumed.offset = nvbo->bo.offset;
+		b->presumed.valid = 0;
 		relocs++;
 
-		if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index], b, sizeof(*b)))
+		if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed,
+				     &b->presumed, sizeof(b->presumed)))
 			return -EFAULT;
 	}
 
@@ -408,6 +424,7 @@
 			     uint64_t user_buffers, int nr_buffers,
 			     struct validate_op *op, int *apply_relocs)
 {
+	struct drm_device *dev = chan->dev;
 	int ret, relocs = 0;
 
 	INIT_LIST_HEAD(&op->vram_list);
@@ -418,11 +435,14 @@
 		return 0;
 
 	ret = validate_init(chan, file_priv, pbbo, nr_buffers, op);
-	if (unlikely(ret))
+	if (unlikely(ret)) {
+		NV_ERROR(dev, "validate_init\n");
 		return ret;
+	}
 
 	ret = validate_list(chan, &op->vram_list, pbbo, user_buffers);
 	if (unlikely(ret < 0)) {
+		NV_ERROR(dev, "validate vram_list\n");
 		validate_fini(op, NULL);
 		return ret;
 	}
@@ -430,6 +450,7 @@
 
 	ret = validate_list(chan, &op->gart_list, pbbo, user_buffers);
 	if (unlikely(ret < 0)) {
+		NV_ERROR(dev, "validate gart_list\n");
 		validate_fini(op, NULL);
 		return ret;
 	}
@@ -437,6 +458,7 @@
 
 	ret = validate_list(chan, &op->both_list, pbbo, user_buffers);
 	if (unlikely(ret < 0)) {
+		NV_ERROR(dev, "validate both_list\n");
 		validate_fini(op, NULL);
 		return ret;
 	}
@@ -465,59 +487,82 @@
 }
 
 static int
-nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo,
-				struct drm_nouveau_gem_pushbuf_bo *bo,
-				unsigned nr_relocs, uint64_t ptr_relocs,
-				unsigned nr_dwords, unsigned first_dword,
-				uint32_t *pushbuf, bool is_iomem)
+nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev,
+				struct drm_nouveau_gem_pushbuf *req,
+				struct drm_nouveau_gem_pushbuf_bo *bo)
 {
 	struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
-	struct drm_device *dev = chan->dev;
 	int ret = 0;
 	unsigned i;
 
-	reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc));
+	reloc = u_memcpya(req->relocs, req->nr_relocs, sizeof(*reloc));
 	if (IS_ERR(reloc))
 		return PTR_ERR(reloc);
 
-	for (i = 0; i < nr_relocs; i++) {
+	for (i = 0; i < req->nr_relocs; i++) {
 		struct drm_nouveau_gem_pushbuf_reloc *r = &reloc[i];
 		struct drm_nouveau_gem_pushbuf_bo *b;
+		struct nouveau_bo *nvbo;
 		uint32_t data;
 
-		if (r->bo_index >= nr_bo || r->reloc_index < first_dword ||
-		    r->reloc_index >= first_dword + nr_dwords) {
-			NV_ERROR(dev, "Bad relocation %d\n", i);
-			NV_ERROR(dev, "  bo: %d max %d\n", r->bo_index, nr_bo);
-			NV_ERROR(dev, "  id: %d max %d\n", r->reloc_index, nr_dwords);
+		if (unlikely(r->bo_index > req->nr_buffers)) {
+			NV_ERROR(dev, "reloc bo index invalid\n");
 			ret = -EINVAL;
 			break;
 		}
 
 		b = &bo[r->bo_index];
-		if (b->presumed_ok)
+		if (b->presumed.valid)
 			continue;
 
+		if (unlikely(r->reloc_bo_index > req->nr_buffers)) {
+			NV_ERROR(dev, "reloc container bo index invalid\n");
+			ret = -EINVAL;
+			break;
+		}
+		nvbo = (void *)(unsigned long)bo[r->reloc_bo_index].user_priv;
+
+		if (unlikely(r->reloc_bo_offset + 4 >
+			     nvbo->bo.mem.num_pages << PAGE_SHIFT)) {
+			NV_ERROR(dev, "reloc outside of bo\n");
+			ret = -EINVAL;
+			break;
+		}
+
+		if (!nvbo->kmap.virtual) {
+			ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages,
+					  &nvbo->kmap);
+			if (ret) {
+				NV_ERROR(dev, "failed kmap for reloc\n");
+				break;
+			}
+			nvbo->validate_mapped = true;
+		}
+
 		if (r->flags & NOUVEAU_GEM_RELOC_LOW)
-			data = b->presumed_offset + r->data;
+			data = b->presumed.offset + r->data;
 		else
 		if (r->flags & NOUVEAU_GEM_RELOC_HIGH)
-			data = (b->presumed_offset + r->data) >> 32;
+			data = (b->presumed.offset + r->data) >> 32;
 		else
 			data = r->data;
 
 		if (r->flags & NOUVEAU_GEM_RELOC_OR) {
-			if (b->presumed_domain == NOUVEAU_GEM_DOMAIN_GART)
+			if (b->presumed.domain == NOUVEAU_GEM_DOMAIN_GART)
 				data |= r->tor;
 			else
 				data |= r->vor;
 		}
 
-		if (is_iomem)
-			iowrite32_native(data, (void __force __iomem *)
-						&pushbuf[r->reloc_index]);
-		else
-			pushbuf[r->reloc_index] = data;
+		spin_lock(&nvbo->bo.lock);
+		ret = ttm_bo_wait(&nvbo->bo, false, false, false);
+		spin_unlock(&nvbo->bo.lock);
+		if (ret) {
+			NV_ERROR(dev, "reloc wait_idle failed: %d\n", ret);
+			break;
+		}
+
+		nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data);
 	}
 
 	kfree(reloc);
@@ -528,37 +573,48 @@
 nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
 			  struct drm_file *file_priv)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_gem_pushbuf *req = data;
-	struct drm_nouveau_gem_pushbuf_bo *bo = NULL;
+	struct drm_nouveau_gem_pushbuf_push *push;
+	struct drm_nouveau_gem_pushbuf_bo *bo;
 	struct nouveau_channel *chan;
 	struct validate_op op;
-	struct nouveau_fence* fence = 0;
-	uint32_t *pushbuf = NULL;
-	int ret = 0, do_reloc = 0, i;
+	struct nouveau_fence *fence = 0;
+	int i, j, ret = 0, do_reloc = 0;
 
 	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
 
-	if (req->nr_dwords >= chan->dma.max ||
-	    req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS ||
-	    req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS) {
-		NV_ERROR(dev, "Pushbuf config exceeds limits:\n");
-		NV_ERROR(dev, "  dwords : %d max %d\n", req->nr_dwords,
-			 chan->dma.max - 1);
-		NV_ERROR(dev, "  buffers: %d max %d\n", req->nr_buffers,
-			 NOUVEAU_GEM_MAX_BUFFERS);
-		NV_ERROR(dev, "  relocs : %d max %d\n", req->nr_relocs,
-			 NOUVEAU_GEM_MAX_RELOCS);
+	req->vram_available = dev_priv->fb_aper_free;
+	req->gart_available = dev_priv->gart_info.aper_free;
+	if (unlikely(req->nr_push == 0))
+		goto out_next;
+
+	if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) {
+		NV_ERROR(dev, "pushbuf push count exceeds limit: %d max %d\n",
+			 req->nr_push, NOUVEAU_GEM_MAX_PUSH);
 		return -EINVAL;
 	}
 
-	pushbuf = u_memcpya(req->dwords, req->nr_dwords, sizeof(uint32_t));
-	if (IS_ERR(pushbuf))
-		return PTR_ERR(pushbuf);
+	if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) {
+		NV_ERROR(dev, "pushbuf bo count exceeds limit: %d max %d\n",
+			 req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS);
+		return -EINVAL;
+	}
+
+	if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) {
+		NV_ERROR(dev, "pushbuf reloc count exceeds limit: %d max %d\n",
+			 req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS);
+		return -EINVAL;
+	}
+
+	push = u_memcpya(req->push, req->nr_push, sizeof(*push));
+	if (IS_ERR(push))
+		return PTR_ERR(push);
 
 	bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
 	if (IS_ERR(bo)) {
-		kfree(pushbuf);
+		kfree(push);
 		return PTR_ERR(bo);
 	}
 
@@ -567,215 +623,89 @@
 	/* Validate buffer list */
 	ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
 					   req->nr_buffers, &op, &do_reloc);
-	if (ret)
-		goto out;
-
-	/* Apply any relocations that are required */
-	if (do_reloc) {
-		ret = nouveau_gem_pushbuf_reloc_apply(chan, req->nr_buffers,
-						      bo, req->nr_relocs,
-						      req->relocs,
-						      req->nr_dwords, 0,
-						      pushbuf, false);
-		if (ret)
-			goto out;
-	}
-
-	/* Emit push buffer to the hw
-	 */
-	ret = RING_SPACE(chan, req->nr_dwords);
-	if (ret)
-		goto out;
-
-	OUT_RINGp(chan, pushbuf, req->nr_dwords);
-
-	ret = nouveau_fence_new(chan, &fence, true);
-	if (ret) {
-		NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
-		WIND_RING(chan);
-		goto out;
-	}
-
-	if (nouveau_gem_pushbuf_sync(chan)) {
-		ret = nouveau_fence_wait(fence, NULL, false, false);
-		if (ret) {
-			for (i = 0; i < req->nr_dwords; i++)
-				NV_ERROR(dev, "0x%08x\n", pushbuf[i]);
-			NV_ERROR(dev, "^^ above push buffer is fail :(\n");
-		}
-	}
-
-out:
-	validate_fini(&op, fence);
-	nouveau_fence_unref((void**)&fence);
-	mutex_unlock(&dev->struct_mutex);
-	kfree(pushbuf);
-	kfree(bo);
-	return ret;
-}
-
-#define PUSHBUF_CAL (dev_priv->card_type >= NV_20)
-
-int
-nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
-			       struct drm_file *file_priv)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct drm_nouveau_gem_pushbuf_call *req = data;
-	struct drm_nouveau_gem_pushbuf_bo *bo = NULL;
-	struct nouveau_channel *chan;
-	struct drm_gem_object *gem;
-	struct nouveau_bo *pbbo;
-	struct validate_op op;
-	struct nouveau_fence* fence = 0;
-	int i, ret = 0, do_reloc = 0;
-
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
-
-	if (unlikely(req->handle == 0))
-		goto out_next;
-
-	if (req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS ||
-	    req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS) {
-		NV_ERROR(dev, "Pushbuf config exceeds limits:\n");
-		NV_ERROR(dev, "  buffers: %d max %d\n", req->nr_buffers,
-			 NOUVEAU_GEM_MAX_BUFFERS);
-		NV_ERROR(dev, "  relocs : %d max %d\n", req->nr_relocs,
-			 NOUVEAU_GEM_MAX_RELOCS);
-		return -EINVAL;
-	}
-
-	bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
-	if (IS_ERR(bo))
-		return PTR_ERR(bo);
-
-	mutex_lock(&dev->struct_mutex);
-
-	/* Validate buffer list */
-	ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
-					   req->nr_buffers, &op, &do_reloc);
 	if (ret) {
 		NV_ERROR(dev, "validate: %d\n", ret);
 		goto out;
 	}
 
-	/* Validate DMA push buffer */
-	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
-	if (!gem) {
-		NV_ERROR(dev, "Unknown pb handle 0x%08x\n", req->handle);
-		ret = -EINVAL;
-		goto out;
-	}
-	pbbo = nouveau_gem_object(gem);
-
-	if ((req->offset & 3) || req->nr_dwords < 2 ||
-	    (unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size ||
-	    (unsigned long)req->nr_dwords >
-	     ((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) {
-		NV_ERROR(dev, "pb call misaligned or out of bounds: "
-			      "%d + %d * 4 > %ld\n",
-			 req->offset, req->nr_dwords, pbbo->bo.mem.size);
-		ret = -EINVAL;
-		drm_gem_object_unreference(gem);
-		goto out;
-	}
-
-	ret = ttm_bo_reserve(&pbbo->bo, false, false, true,
-			     chan->fence.sequence);
-	if (ret) {
-		NV_ERROR(dev, "resv pb: %d\n", ret);
-		drm_gem_object_unreference(gem);
-		goto out;
-	}
-
-	nouveau_bo_placement_set(pbbo, 1 << chan->pushbuf_bo->bo.mem.mem_type);
-	ret = ttm_bo_validate(&pbbo->bo, &pbbo->placement, false, false);
-	if (ret) {
-		NV_ERROR(dev, "validate pb: %d\n", ret);
-		ttm_bo_unreserve(&pbbo->bo);
-		drm_gem_object_unreference(gem);
-		goto out;
-	}
-
-	list_add_tail(&pbbo->entry, &op.both_list);
-
-	/* If presumed return address doesn't match, we need to map the
-	 * push buffer and fix it..
-	 */
-	if (!PUSHBUF_CAL) {
-		uint32_t retaddy;
-
-		if (chan->dma.free < 4 + NOUVEAU_DMA_SKIPS) {
-			ret = nouveau_dma_wait(chan, 4 + NOUVEAU_DMA_SKIPS);
-			if (ret) {
-				NV_ERROR(dev, "jmp_space: %d\n", ret);
-				goto out;
-			}
-		}
-
-		retaddy  = chan->pushbuf_base + ((chan->dma.cur + 2) << 2);
-		retaddy |= 0x20000000;
-		if (retaddy != req->suffix0) {
-			req->suffix0 = retaddy;
-			do_reloc = 1;
-		}
-	}
-
 	/* Apply any relocations that are required */
 	if (do_reloc) {
-		void *pbvirt;
-		bool is_iomem;
-		ret = ttm_bo_kmap(&pbbo->bo, 0, pbbo->bo.mem.num_pages,
-				  &pbbo->kmap);
-		if (ret) {
-			NV_ERROR(dev, "kmap pb: %d\n", ret);
-			goto out;
-		}
-
-		pbvirt = ttm_kmap_obj_virtual(&pbbo->kmap, &is_iomem);
-		ret = nouveau_gem_pushbuf_reloc_apply(chan, req->nr_buffers, bo,
-						      req->nr_relocs,
-						      req->relocs,
-						      req->nr_dwords,
-						      req->offset / 4,
-						      pbvirt, is_iomem);
-
-		if (!PUSHBUF_CAL) {
-			nouveau_bo_wr32(pbbo,
-					req->offset / 4 + req->nr_dwords - 2,
-					req->suffix0);
-		}
-
-		ttm_bo_kunmap(&pbbo->kmap);
+		ret = nouveau_gem_pushbuf_reloc_apply(dev, req, bo);
 		if (ret) {
 			NV_ERROR(dev, "reloc apply: %d\n", ret);
 			goto out;
 		}
 	}
 
-	if (PUSHBUF_CAL) {
-		ret = RING_SPACE(chan, 2);
+	if (chan->dma.ib_max) {
+		ret = nouveau_dma_wait(chan, req->nr_push + 1, 6);
+		if (ret) {
+			NV_INFO(dev, "nv50cal_space: %d\n", ret);
+			goto out;
+		}
+
+		for (i = 0; i < req->nr_push; i++) {
+			struct nouveau_bo *nvbo = (void *)(unsigned long)
+				bo[push[i].bo_index].user_priv;
+
+			nv50_dma_push(chan, nvbo, push[i].offset,
+				      push[i].length);
+		}
+	} else
+	if (dev_priv->card_type >= NV_20) {
+		ret = RING_SPACE(chan, req->nr_push * 2);
 		if (ret) {
 			NV_ERROR(dev, "cal_space: %d\n", ret);
 			goto out;
 		}
-		OUT_RING(chan, ((pbbo->bo.mem.mm_node->start << PAGE_SHIFT) +
-				  req->offset) | 2);
-		OUT_RING(chan, 0);
+
+		for (i = 0; i < req->nr_push; i++) {
+			struct nouveau_bo *nvbo = (void *)(unsigned long)
+				bo[push[i].bo_index].user_priv;
+			struct drm_mm_node *mem = nvbo->bo.mem.mm_node;
+
+			OUT_RING(chan, ((mem->start << PAGE_SHIFT) +
+					push[i].offset) | 2);
+			OUT_RING(chan, 0);
+		}
 	} else {
-		ret = RING_SPACE(chan, 2 + NOUVEAU_DMA_SKIPS);
+		ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS));
 		if (ret) {
 			NV_ERROR(dev, "jmp_space: %d\n", ret);
 			goto out;
 		}
-		OUT_RING(chan, ((pbbo->bo.mem.mm_node->start << PAGE_SHIFT) +
-				  req->offset) | 0x20000000);
-		OUT_RING(chan, 0);
 
-		/* Space the jumps apart with NOPs. */
-		for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)
+		for (i = 0; i < req->nr_push; i++) {
+			struct nouveau_bo *nvbo = (void *)(unsigned long)
+				bo[push[i].bo_index].user_priv;
+			struct drm_mm_node *mem = nvbo->bo.mem.mm_node;
+			uint32_t cmd;
+
+			cmd = chan->pushbuf_base + ((chan->dma.cur + 2) << 2);
+			cmd |= 0x20000000;
+			if (unlikely(cmd != req->suffix0)) {
+				if (!nvbo->kmap.virtual) {
+					ret = ttm_bo_kmap(&nvbo->bo, 0,
+							  nvbo->bo.mem.
+							  num_pages,
+							  &nvbo->kmap);
+					if (ret) {
+						WIND_RING(chan);
+						goto out;
+					}
+					nvbo->validate_mapped = true;
+				}
+
+				nouveau_bo_wr32(nvbo, (push[i].offset +
+						push[i].length - 8) / 4, cmd);
+			}
+
+			OUT_RING(chan, ((mem->start << PAGE_SHIFT) +
+					push[i].offset) | 0x20000000);
 			OUT_RING(chan, 0);
+			for (j = 0; j < NOUVEAU_DMA_SKIPS; j++)
+				OUT_RING(chan, 0);
+		}
 	}
 
 	ret = nouveau_fence_new(chan, &fence, true);
@@ -790,9 +720,14 @@
 	nouveau_fence_unref((void**)&fence);
 	mutex_unlock(&dev->struct_mutex);
 	kfree(bo);
+	kfree(push);
 
 out_next:
-	if (PUSHBUF_CAL) {
+	if (chan->dma.ib_max) {
+		req->suffix0 = 0x00000000;
+		req->suffix1 = 0x00000000;
+	} else
+	if (dev_priv->card_type >= NV_20) {
 		req->suffix0 = 0x00020000;
 		req->suffix1 = 0x00000000;
 	} else {
@@ -804,19 +739,6 @@
 	return ret;
 }
 
-int
-nouveau_gem_ioctl_pushbuf_call2(struct drm_device *dev, void *data,
-				struct drm_file *file_priv)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct drm_nouveau_gem_pushbuf_call *req = data;
-
-	req->vram_available = dev_priv->fb_aper_free;
-	req->gart_available = dev_priv->gart_info.aper_free;
-
-	return nouveau_gem_ioctl_pushbuf_call(dev, data, file_priv);
-}
-
 static inline uint32_t
 domain_to_ttm(struct nouveau_bo *nvbo, uint32_t domain)
 {
@@ -831,74 +753,6 @@
 }
 
 int
-nouveau_gem_ioctl_pin(struct drm_device *dev, void *data,
-		      struct drm_file *file_priv)
-{
-	struct drm_nouveau_gem_pin *req = data;
-	struct drm_gem_object *gem;
-	struct nouveau_bo *nvbo;
-	int ret = 0;
-
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		NV_ERROR(dev, "pin only allowed without kernel modesetting\n");
-		return -EINVAL;
-	}
-
-	if (!DRM_SUSER(DRM_CURPROC))
-		return -EPERM;
-
-	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
-	if (!gem)
-		return -EINVAL;
-	nvbo = nouveau_gem_object(gem);
-
-	ret = nouveau_bo_pin(nvbo, domain_to_ttm(nvbo, req->domain));
-	if (ret)
-		goto out;
-
-	req->offset = nvbo->bo.offset;
-	if (nvbo->bo.mem.mem_type == TTM_PL_TT)
-		req->domain = NOUVEAU_GEM_DOMAIN_GART;
-	else
-		req->domain = NOUVEAU_GEM_DOMAIN_VRAM;
-
-out:
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gem);
-	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
-}
-
-int
-nouveau_gem_ioctl_unpin(struct drm_device *dev, void *data,
-			struct drm_file *file_priv)
-{
-	struct drm_nouveau_gem_pin *req = data;
-	struct drm_gem_object *gem;
-	int ret;
-
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
-	if (drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
-	if (!gem)
-		return -EINVAL;
-
-	ret = nouveau_bo_unpin(nouveau_gem_object(gem));
-
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gem);
-	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
-}
-
-int
 nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
 			   struct drm_file *file_priv)
 {
@@ -935,9 +789,7 @@
 	}
 
 out:
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gem);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gem);
 	return ret;
 }
 
@@ -965,9 +817,7 @@
 	ret = 0;
 
 out:
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gem);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gem);
 	return ret;
 }
 
@@ -986,9 +836,7 @@
 		return -EINVAL;
 
 	ret = nouveau_gem_info(gem, req);
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gem);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gem);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c
index dc46792..7855b35 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hw.c
+++ b/drivers/gpu/drm/nouveau/nouveau_hw.c
@@ -160,7 +160,7 @@
 setPLL_single(struct drm_device *dev, uint32_t reg, struct nouveau_pll_vals *pv)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int chip_version = dev_priv->vbios->chip_version;
+	int chip_version = dev_priv->vbios.chip_version;
 	uint32_t oldpll = NVReadRAMDAC(dev, 0, reg);
 	int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff;
 	uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1;
@@ -216,7 +216,7 @@
 		       struct nouveau_pll_vals *pv)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int chip_version = dev_priv->vbios->chip_version;
+	int chip_version = dev_priv->vbios.chip_version;
 	bool nv3035 = chip_version == 0x30 || chip_version == 0x35;
 	uint32_t reg2 = reg1 + ((reg1 == NV_RAMDAC_VPLL2) ? 0x5c : 0x70);
 	uint32_t oldpll1 = NVReadRAMDAC(dev, 0, reg1);
@@ -374,7 +374,7 @@
 		  struct nouveau_pll_vals *pv)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int cv = dev_priv->vbios->chip_version;
+	int cv = dev_priv->vbios.chip_version;
 
 	if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 ||
 	    cv >= 0x40) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c
index 70e994d..88583e7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_i2c.c
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c
@@ -254,16 +254,16 @@
 nouveau_i2c_find(struct drm_device *dev, int index)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 
-	if (index > DCB_MAX_NUM_I2C_ENTRIES)
+	if (index >= DCB_MAX_NUM_I2C_ENTRIES)
 		return NULL;
 
-	if (!bios->bdcb.dcb.i2c[index].chan) {
-		if (nouveau_i2c_init(dev, &bios->bdcb.dcb.i2c[index], index))
+	if (!bios->dcb.i2c[index].chan) {
+		if (nouveau_i2c_init(dev, &bios->dcb.i2c[index], index))
 			return NULL;
 	}
 
-	return bios->bdcb.dcb.i2c[index].chan;
+	return bios->dcb.i2c[index].chan;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
index 447f9f6..95220dd 100644
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -691,11 +691,14 @@
 	struct drm_device *dev = (struct drm_device *)arg;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	uint32_t status, fbdev_flags = 0;
+	unsigned long flags;
 
 	status = nv_rd32(dev, NV03_PMC_INTR_0);
 	if (!status)
 		return IRQ_NONE;
 
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+
 	if (dev_priv->fbdev_info) {
 		fbdev_flags = dev_priv->fbdev_info->flags;
 		dev_priv->fbdev_info->flags |= FBINFO_HWACCEL_DISABLED;
@@ -733,5 +736,7 @@
 	if (dev_priv->fbdev_info)
 		dev_priv->fbdev_info->flags = fbdev_flags;
 
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
 	return IRQ_HANDLED;
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c
index d99dc08..9537f3e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_notifier.c
+++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c
@@ -61,11 +61,8 @@
 
 	chan->notifier_bo = ntfy;
 out_err:
-	if (ret) {
-		mutex_lock(&dev->struct_mutex);
-		drm_gem_object_unreference(ntfy->gem);
-		mutex_unlock(&dev->struct_mutex);
-	}
+	if (ret)
+		drm_gem_object_unreference_unlocked(ntfy->gem);
 
 	return ret;
 }
@@ -81,8 +78,8 @@
 	nouveau_bo_unmap(chan->notifier_bo);
 	mutex_lock(&dev->struct_mutex);
 	nouveau_bo_unpin(chan->notifier_bo);
-	drm_gem_object_unreference(chan->notifier_bo->gem);
 	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(chan->notifier_bo->gem);
 	nouveau_mem_takedown(&chan->notifier_heap);
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index a4851af..eb8f084 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -29,6 +29,7 @@
 #include "drm_sarea.h"
 #include "drm_crtc_helper.h"
 #include <linux/vgaarb.h>
+#include <linux/vga_switcheroo.h>
 
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
@@ -371,6 +372,30 @@
 	return ret;
 }
 
+static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
+					 enum vga_switcheroo_state state)
+{
+	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
+	if (state == VGA_SWITCHEROO_ON) {
+		printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
+		nouveau_pci_resume(pdev);
+	} else {
+		printk(KERN_ERR "VGA switcheroo: switched nouveau off\n");
+		nouveau_pci_suspend(pdev, pmm);
+	}
+}
+
+static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	bool can_switch;
+
+	spin_lock(&dev->count_lock);
+	can_switch = (dev->open_count == 0);
+	spin_unlock(&dev->count_lock);
+	return can_switch;
+}
+
 int
 nouveau_card_init(struct drm_device *dev)
 {
@@ -384,6 +409,8 @@
 		return 0;
 
 	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
+	vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
+				       nouveau_switcheroo_can_switch);
 
 	/* Initialise internal driver API hooks */
 	ret = nouveau_init_engine_ptrs(dev);
@@ -391,6 +418,7 @@
 		goto out;
 	engine = &dev_priv->engine;
 	dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
+	spin_lock_init(&dev_priv->context_switch_lock);
 
 	/* Parse BIOS tables / Run init tables if card not POSTed */
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
@@ -617,11 +645,6 @@
 	NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
 		 dev->pci_vendor, dev->pci_device, dev->pdev->class);
 
-	dev_priv->acpi_dsm = nouveau_dsm_probe(dev);
-
-	if (dev_priv->acpi_dsm)
-		nouveau_hybrid_setup(dev);
-
 	dev_priv->wq = create_workqueue("nouveau");
 	if (!dev_priv->wq)
 		return -EINVAL;
@@ -776,13 +799,6 @@
 	return 0;
 }
 
-int
-nouveau_ioctl_card_init(struct drm_device *dev, void *data,
-			struct drm_file *file_priv)
-{
-	return nouveau_card_init(dev);
-}
-
 int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
 						struct drm_file *file_priv)
 {
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c
index d2f143e..a1d1ebb 100644
--- a/drivers/gpu/drm/nouveau/nv04_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv04_crtc.c
@@ -926,9 +926,7 @@
 	nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset);
 	nv_crtc->cursor.show(nv_crtc, true);
 out:
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gem);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gem);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c
index 1d73b15..1cb19e3 100644
--- a/drivers/gpu/drm/nouveau/nv04_dac.c
+++ b/drivers/gpu/drm/nouveau/nv04_dac.c
@@ -230,13 +230,13 @@
 	if (dcb->type == OUTPUT_TV) {
 		testval = RGB_TEST_DATA(0xa0, 0xa0, 0xa0);
 
-		if (dev_priv->vbios->tvdactestval)
-			testval = dev_priv->vbios->tvdactestval;
+		if (dev_priv->vbios.tvdactestval)
+			testval = dev_priv->vbios.tvdactestval;
 	} else {
 		testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */
 
-		if (dev_priv->vbios->dactestval)
-			testval = dev_priv->vbios->dactestval;
+		if (dev_priv->vbios.dactestval)
+			testval = dev_priv->vbios.dactestval;
 	}
 
 	saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c
index 483f875..41634d4 100644
--- a/drivers/gpu/drm/nouveau/nv04_dfp.c
+++ b/drivers/gpu/drm/nouveau/nv04_dfp.c
@@ -269,10 +269,10 @@
 	regp->fp_horiz_regs[FP_TOTAL] = output_mode->htotal - 1;
 	if (!nv_gf4_disp_arch(dev) ||
 	    (output_mode->hsync_start - output_mode->hdisplay) >=
-					dev_priv->vbios->digital_min_front_porch)
+					dev_priv->vbios.digital_min_front_porch)
 		regp->fp_horiz_regs[FP_CRTC] = output_mode->hdisplay;
 	else
-		regp->fp_horiz_regs[FP_CRTC] = output_mode->hsync_start - dev_priv->vbios->digital_min_front_porch - 1;
+		regp->fp_horiz_regs[FP_CRTC] = output_mode->hsync_start - dev_priv->vbios.digital_min_front_porch - 1;
 	regp->fp_horiz_regs[FP_SYNC_START] = output_mode->hsync_start - 1;
 	regp->fp_horiz_regs[FP_SYNC_END] = output_mode->hsync_end - 1;
 	regp->fp_horiz_regs[FP_VALID_START] = output_mode->hskew;
diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c
index ef77215..c7898b4 100644
--- a/drivers/gpu/drm/nouveau/nv04_display.c
+++ b/drivers/gpu/drm/nouveau/nv04_display.c
@@ -93,10 +93,9 @@
 nv04_display_create(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct parsed_dcb *dcb = dev_priv->vbios->dcb;
+	struct dcb_table *dcb = &dev_priv->vbios.dcb;
 	struct drm_encoder *encoder;
 	struct drm_crtc *crtc;
-	uint16_t connector[16] = { 0 };
 	int i, ret;
 
 	NV_DEBUG_KMS(dev, "\n");
@@ -154,52 +153,10 @@
 
 		if (ret)
 			continue;
-
-		connector[dcbent->connector] |= (1 << dcbent->type);
 	}
 
-	for (i = 0; i < dcb->entries; i++) {
-		struct dcb_entry *dcbent = &dcb->entry[i];
-		uint16_t encoders;
-		int type;
-
-		encoders = connector[dcbent->connector];
-		if (!(encoders & (1 << dcbent->type)))
-			continue;
-		connector[dcbent->connector] = 0;
-
-		switch (dcbent->type) {
-		case OUTPUT_ANALOG:
-			if (!MULTIPLE_ENCODERS(encoders))
-				type = DRM_MODE_CONNECTOR_VGA;
-			else
-				type = DRM_MODE_CONNECTOR_DVII;
-			break;
-		case OUTPUT_TMDS:
-			if (!MULTIPLE_ENCODERS(encoders))
-				type = DRM_MODE_CONNECTOR_DVID;
-			else
-				type = DRM_MODE_CONNECTOR_DVII;
-			break;
-		case OUTPUT_LVDS:
-			type = DRM_MODE_CONNECTOR_LVDS;
-#if 0
-			/* don't create i2c adapter when lvds ddc not allowed */
-			if (dcbent->lvdsconf.use_straps_for_mode ||
-			    dev_priv->vbios->fp_no_ddc)
-				i2c_index = 0xf;
-#endif
-			break;
-		case OUTPUT_TV:
-			type = DRM_MODE_CONNECTOR_TV;
-			break;
-		default:
-			type = DRM_MODE_CONNECTOR_Unknown;
-			continue;
-		}
-
-		nouveau_connector_create(dev, dcbent->connector, type);
-	}
+	for (i = 0; i < dcb->connector.entries; i++)
+		nouveau_connector_create(dev, &dcb->connector.entry[i]);
 
 	/* Save previous state */
 	NVLockVgaCrtcs(dev, false);
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
index fd01caa..3da90c2 100644
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -118,7 +118,7 @@
 		return;
 	}
 
-	width = (image->width + 31) & ~31;
+	width = ALIGN(image->width, 32);
 	dsize = (width * image->height) >> 5;
 
 	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c
index f31347b..66fe559 100644
--- a/drivers/gpu/drm/nouveau/nv04_fifo.c
+++ b/drivers/gpu/drm/nouveau/nv04_fifo.c
@@ -117,6 +117,7 @@
 {
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	unsigned long flags;
 	int ret;
 
 	ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), ~0,
@@ -127,6 +128,8 @@
 	if (ret)
 		return ret;
 
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+
 	/* Setup initial state */
 	dev_priv->engine.instmem.prepare_access(dev, true);
 	RAMFC_WR(DMA_PUT, chan->pushbuf_base);
@@ -144,6 +147,8 @@
 	/* enable the fifo dma operation */
 	nv_wr32(dev, NV04_PFIFO_MODE,
 		nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id));
+
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c
index 9c63099..c4e3404 100644
--- a/drivers/gpu/drm/nouveau/nv04_tv.c
+++ b/drivers/gpu/drm/nouveau/nv04_tv.c
@@ -262,7 +262,7 @@
 	nv_encoder->or = ffs(entry->or) - 1;
 
 	/* Run the slave-specific initialization */
-	adap = &dev_priv->vbios->dcb->i2c[i2c_index].chan->adapter;
+	adap = &dev_priv->vbios.dcb.i2c[i2c_index].chan->adapter;
 
 	was_locked = NVLockVgaCrtcs(dev, false);
 
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c
index 21ac6e4..74c8803 100644
--- a/drivers/gpu/drm/nouveau/nv17_tv.c
+++ b/drivers/gpu/drm/nouveau/nv17_tv.c
@@ -45,8 +45,8 @@
 
 #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
 	testval = RGB_TEST_DATA(0x82, 0xeb, 0x82);
-	if (dev_priv->vbios->tvdactestval)
-		testval = dev_priv->vbios->tvdactestval;
+	if (dev_priv->vbios.tvdactestval)
+		testval = dev_priv->vbios.tvdactestval;
 
 	dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
 	head = (dacclk & 0x100) >> 8;
@@ -367,7 +367,7 @@
 			     !enc->crtc &&
 			     nv04_dfp_get_bound_head(dev, dcb) == head) {
 				nv04_dfp_bind_head(dev, dcb, head ^ 1,
-						dev_priv->VBIOS.fp.dual_link);
+						dev_priv->vbios.fp.dual_link);
 			}
 		}
 
diff --git a/drivers/gpu/drm/nouveau/nv40_fifo.c b/drivers/gpu/drm/nouveau/nv40_fifo.c
index b4f19cc..6b2ef4a 100644
--- a/drivers/gpu/drm/nouveau/nv40_fifo.c
+++ b/drivers/gpu/drm/nouveau/nv40_fifo.c
@@ -37,6 +37,7 @@
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	uint32_t fc = NV40_RAMFC(chan->id);
+	unsigned long flags;
 	int ret;
 
 	ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0,
@@ -45,6 +46,8 @@
 	if (ret)
 		return ret;
 
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+
 	dev_priv->engine.instmem.prepare_access(dev, true);
 	nv_wi32(dev, fc +  0, chan->pushbuf_base);
 	nv_wi32(dev, fc +  4, chan->pushbuf_base);
@@ -63,6 +66,8 @@
 	/* enable the fifo dma operation */
 	nv_wr32(dev, NV04_PFIFO_MODE,
 		nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id));
+
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index d1a651e..cfabeb9 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -358,9 +358,7 @@
 	nv_crtc->cursor.show(nv_crtc, true);
 
 out:
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gem);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gem);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c
index f08f042..1fd9537 100644
--- a/drivers/gpu/drm/nouveau/nv50_dac.c
+++ b/drivers/gpu/drm/nouveau/nv50_dac.c
@@ -79,8 +79,8 @@
 	}
 
 	/* Use bios provided value if possible. */
-	if (dev_priv->vbios->dactestval) {
-		load_pattern = dev_priv->vbios->dactestval;
+	if (dev_priv->vbios.dactestval) {
+		load_pattern = dev_priv->vbios.dactestval;
 		NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n",
 			  load_pattern);
 	} else {
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 90f0bf5..61a89f2 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -370,9 +370,7 @@
 		struct nouveau_connector *conn = nouveau_connector(connector);
 		struct dcb_gpio_entry *gpio;
 
-		if (connector->connector_type != DRM_MODE_CONNECTOR_DVII &&
-		    connector->connector_type != DRM_MODE_CONNECTOR_DVID &&
-		    connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
+		if (conn->dcb->gpio_tag == 0xff)
 			continue;
 
 		gpio = nouveau_bios_gpio_entry(dev, conn->dcb->gpio_tag);
@@ -465,8 +463,7 @@
 int nv50_display_create(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct parsed_dcb *dcb = dev_priv->vbios->dcb;
-	uint32_t connector[16] = {};
+	struct dcb_table *dcb = &dev_priv->vbios.dcb;
 	int ret, i;
 
 	NV_DEBUG_KMS(dev, "\n");
@@ -522,44 +519,13 @@
 			NV_WARN(dev, "DCB encoder %d unknown\n", entry->type);
 			continue;
 		}
-
-		connector[entry->connector] |= (1 << entry->type);
 	}
 
-	/* It appears that DCB 3.0+ VBIOS has a connector table, however,
-	 * I'm not 100% certain how to decode it correctly yet so just
-	 * look at what encoders are present on each connector index and
-	 * attempt to derive the connector type from that.
-	 */
-	for (i = 0 ; i < dcb->entries; i++) {
-		struct dcb_entry *entry = &dcb->entry[i];
-		uint16_t encoders;
-		int type;
-
-		encoders = connector[entry->connector];
-		if (!(encoders & (1 << entry->type)))
+	for (i = 0 ; i < dcb->connector.entries; i++) {
+		if (i != 0 && dcb->connector.entry[i].index ==
+			      dcb->connector.entry[i - 1].index)
 			continue;
-		connector[entry->connector] = 0;
-
-		if (encoders & (1 << OUTPUT_DP)) {
-			type = DRM_MODE_CONNECTOR_DisplayPort;
-		} else if (encoders & (1 << OUTPUT_TMDS)) {
-			if (encoders & (1 << OUTPUT_ANALOG))
-				type = DRM_MODE_CONNECTOR_DVII;
-			else
-				type = DRM_MODE_CONNECTOR_DVID;
-		} else if (encoders & (1 << OUTPUT_ANALOG)) {
-			type = DRM_MODE_CONNECTOR_VGA;
-		} else if (encoders & (1 << OUTPUT_LVDS)) {
-			type = DRM_MODE_CONNECTOR_LVDS;
-		} else {
-			type = DRM_MODE_CONNECTOR_Unknown;
-		}
-
-		if (type == DRM_MODE_CONNECTOR_Unknown)
-			continue;
-
-		nouveau_connector_create(dev, entry->connector, type);
+		nouveau_connector_create(dev, &dcb->connector.entry[i]);
 	}
 
 	ret = nv50_display_init(dev);
@@ -667,8 +633,8 @@
 		return -1;
 	}
 
-	for (i = 0; i < dev_priv->vbios->dcb->entries; i++) {
-		struct dcb_entry *dcbent = &dev_priv->vbios->dcb->entry[i];
+	for (i = 0; i < dev_priv->vbios.dcb.entries; i++) {
+		struct dcb_entry *dcbent = &dev_priv->vbios.dcb.entry[i];
 
 		if (dcbent->type != type)
 			continue;
@@ -692,7 +658,7 @@
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_connector *nv_connector = NULL;
 	struct drm_encoder *encoder;
-	struct nvbios *bios = &dev_priv->VBIOS;
+	struct nvbios *bios = &dev_priv->vbios;
 	uint32_t mc, script = 0, or;
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@@ -710,7 +676,7 @@
 	switch (dcbent->type) {
 	case OUTPUT_LVDS:
 		script = (mc >> 8) & 0xf;
-		if (bios->pub.fp_no_ddc) {
+		if (bios->fp_no_ddc) {
 			if (bios->fp.dual_link)
 				script |= 0x0100;
 			if (bios->fp.if_is_24bit)
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index 0f57cdf..993c712 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -109,7 +109,7 @@
 		return;
 	}
 
-	width = (image->width + 31) & ~31;
+	width = ALIGN(image->width, 32);
 	dwords = (width * image->height) >> 5;
 
 	BEGIN_RING(chan, NvSub2D, 0x0814, 2);
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c
index 204a79f..e20c0e2 100644
--- a/drivers/gpu/drm/nouveau/nv50_fifo.c
+++ b/drivers/gpu/drm/nouveau/nv50_fifo.c
@@ -243,6 +243,7 @@
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *ramfc = NULL;
+	unsigned long flags;
 	int ret;
 
 	NV_DEBUG(dev, "ch%d\n", chan->id);
@@ -278,19 +279,21 @@
 			return ret;
 	}
 
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+
 	dev_priv->engine.instmem.prepare_access(dev, true);
 
-	nv_wo32(dev, ramfc, 0x08/4, chan->pushbuf_base);
-	nv_wo32(dev, ramfc, 0x10/4, chan->pushbuf_base);
 	nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4);
 	nv_wo32(dev, ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4));
-	nv_wo32(dev, ramfc, 0x3c/4, 0x00086078);
 	nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff);
 	nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff);
 	nv_wo32(dev, ramfc, 0x40/4, 0x00000000);
 	nv_wo32(dev, ramfc, 0x7c/4, 0x30000001);
 	nv_wo32(dev, ramfc, 0x78/4, 0x00000000);
-	nv_wo32(dev, ramfc, 0x4c/4, 0xffffffff);
+	nv_wo32(dev, ramfc, 0x3c/4, 0x403f6078);
+	nv_wo32(dev, ramfc, 0x50/4, chan->pushbuf_base +
+				    chan->dma.ib_base * 4);
+	nv_wo32(dev, ramfc, 0x54/4, drm_order(chan->dma.ib_max + 1) << 16);
 
 	if (!IS_G80) {
 		nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id);
@@ -306,10 +309,12 @@
 	ret = nv50_fifo_channel_enable(dev, chan->id, false);
 	if (ret) {
 		NV_ERROR(dev, "error enabling ch%d: %d\n", chan->id, ret);
+		spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 		nouveau_gpuobj_ref_del(dev, &chan->ramfc);
 		return ret;
 	}
 
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
index 6d50480..857a096 100644
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -28,30 +28,7 @@
 #include "drm.h"
 #include "nouveau_drv.h"
 
-MODULE_FIRMWARE("nouveau/nv50.ctxprog");
-MODULE_FIRMWARE("nouveau/nv50.ctxvals");
-MODULE_FIRMWARE("nouveau/nv84.ctxprog");
-MODULE_FIRMWARE("nouveau/nv84.ctxvals");
-MODULE_FIRMWARE("nouveau/nv86.ctxprog");
-MODULE_FIRMWARE("nouveau/nv86.ctxvals");
-MODULE_FIRMWARE("nouveau/nv92.ctxprog");
-MODULE_FIRMWARE("nouveau/nv92.ctxvals");
-MODULE_FIRMWARE("nouveau/nv94.ctxprog");
-MODULE_FIRMWARE("nouveau/nv94.ctxvals");
-MODULE_FIRMWARE("nouveau/nv96.ctxprog");
-MODULE_FIRMWARE("nouveau/nv96.ctxvals");
-MODULE_FIRMWARE("nouveau/nv98.ctxprog");
-MODULE_FIRMWARE("nouveau/nv98.ctxvals");
-MODULE_FIRMWARE("nouveau/nva0.ctxprog");
-MODULE_FIRMWARE("nouveau/nva0.ctxvals");
-MODULE_FIRMWARE("nouveau/nva5.ctxprog");
-MODULE_FIRMWARE("nouveau/nva5.ctxvals");
-MODULE_FIRMWARE("nouveau/nva8.ctxprog");
-MODULE_FIRMWARE("nouveau/nva8.ctxvals");
-MODULE_FIRMWARE("nouveau/nvaa.ctxprog");
-MODULE_FIRMWARE("nouveau/nvaa.ctxvals");
-MODULE_FIRMWARE("nouveau/nvac.ctxprog");
-MODULE_FIRMWARE("nouveau/nvac.ctxvals");
+#include "nouveau_grctx.h"
 
 #define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
 
@@ -111,9 +88,34 @@
 
 	NV_DEBUG(dev, "\n");
 
-	nouveau_grctx_prog_load(dev);
-	if (!dev_priv->engine.graph.ctxprog)
-		dev_priv->engine.graph.accel_blocked = true;
+	if (nouveau_ctxfw) {
+		nouveau_grctx_prog_load(dev);
+		dev_priv->engine.graph.grctx_size = 0x70000;
+	}
+	if (!dev_priv->engine.graph.ctxprog) {
+		struct nouveau_grctx ctx = {};
+		uint32_t *cp = kmalloc(512 * 4, GFP_KERNEL);
+		int i;
+		if (!cp) {
+			NV_ERROR(dev, "Couldn't alloc ctxprog! Disabling acceleration.\n");
+			dev_priv->engine.graph.accel_blocked = true;
+			return 0;
+		}
+		ctx.dev = dev;
+		ctx.mode = NOUVEAU_GRCTX_PROG;
+		ctx.data = cp;
+		ctx.ctxprog_max = 512;
+		if (!nv50_grctx_init(&ctx)) {
+			dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4;
+
+			nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
+			for (i = 0; i < ctx.ctxprog_len; i++)
+				nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]);
+		} else {
+			dev_priv->engine.graph.accel_blocked = true;
+		}
+		kfree(cp);
+	}
 
 	nv_wr32(dev, 0x400320, 4);
 	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
@@ -193,13 +195,13 @@
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *ramin = chan->ramin->gpuobj;
 	struct nouveau_gpuobj *ctx;
-	uint32_t grctx_size = 0x70000;
+	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
 	int hdr, ret;
 
 	NV_DEBUG(dev, "ch%d\n", chan->id);
 
-	ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, grctx_size, 0x1000,
-				     NVOBJ_FLAG_ZERO_ALLOC |
+	ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size,
+				     0x1000, NVOBJ_FLAG_ZERO_ALLOC |
 				     NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx);
 	if (ret)
 		return ret;
@@ -209,7 +211,7 @@
 	dev_priv->engine.instmem.prepare_access(dev, true);
 	nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002);
 	nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance +
-					   grctx_size - 1);
+					   pgraph->grctx_size - 1);
 	nv_wo32(dev, ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance);
 	nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0);
 	nv_wo32(dev, ramin, (hdr + 0x10)/4, 0);
@@ -217,7 +219,15 @@
 	dev_priv->engine.instmem.finish_access(dev);
 
 	dev_priv->engine.instmem.prepare_access(dev, true);
-	nouveau_grctx_vals_load(dev, ctx);
+	if (!pgraph->ctxprog) {
+		struct nouveau_grctx ctx = {};
+		ctx.dev = chan->dev;
+		ctx.mode = NOUVEAU_GRCTX_VALS;
+		ctx.data = chan->ramin_grctx->gpuobj;
+		nv50_grctx_init(&ctx);
+	} else {
+		nouveau_grctx_vals_load(dev, ctx);
+	}
 	nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12);
 	if ((dev_priv->chipset & 0xf0) == 0xa0)
 		nv_wo32(dev, ctx, 0x00004/4, 0x00000000);
diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c
new file mode 100644
index 0000000..d105fcd
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_grctx.c
@@ -0,0 +1,2367 @@
+/*
+ * Copyright 2009 Marcin Kościelnicki
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define CP_FLAG_CLEAR                 0
+#define CP_FLAG_SET                   1
+#define CP_FLAG_SWAP_DIRECTION        ((0 * 32) + 0)
+#define CP_FLAG_SWAP_DIRECTION_LOAD   0
+#define CP_FLAG_SWAP_DIRECTION_SAVE   1
+#define CP_FLAG_UNK01                 ((0 * 32) + 1)
+#define CP_FLAG_UNK01_CLEAR           0
+#define CP_FLAG_UNK01_SET             1
+#define CP_FLAG_UNK03                 ((0 * 32) + 3)
+#define CP_FLAG_UNK03_CLEAR           0
+#define CP_FLAG_UNK03_SET             1
+#define CP_FLAG_USER_SAVE             ((0 * 32) + 5)
+#define CP_FLAG_USER_SAVE_NOT_PENDING 0
+#define CP_FLAG_USER_SAVE_PENDING     1
+#define CP_FLAG_USER_LOAD             ((0 * 32) + 6)
+#define CP_FLAG_USER_LOAD_NOT_PENDING 0
+#define CP_FLAG_USER_LOAD_PENDING     1
+#define CP_FLAG_UNK0B                 ((0 * 32) + 0xb)
+#define CP_FLAG_UNK0B_CLEAR           0
+#define CP_FLAG_UNK0B_SET             1
+#define CP_FLAG_UNK1D                 ((0 * 32) + 0x1d)
+#define CP_FLAG_UNK1D_CLEAR           0
+#define CP_FLAG_UNK1D_SET             1
+#define CP_FLAG_UNK20                 ((1 * 32) + 0)
+#define CP_FLAG_UNK20_CLEAR           0
+#define CP_FLAG_UNK20_SET             1
+#define CP_FLAG_STATUS                ((2 * 32) + 0)
+#define CP_FLAG_STATUS_BUSY           0
+#define CP_FLAG_STATUS_IDLE           1
+#define CP_FLAG_AUTO_SAVE             ((2 * 32) + 4)
+#define CP_FLAG_AUTO_SAVE_NOT_PENDING 0
+#define CP_FLAG_AUTO_SAVE_PENDING     1
+#define CP_FLAG_AUTO_LOAD             ((2 * 32) + 5)
+#define CP_FLAG_AUTO_LOAD_NOT_PENDING 0
+#define CP_FLAG_AUTO_LOAD_PENDING     1
+#define CP_FLAG_XFER                  ((2 * 32) + 11)
+#define CP_FLAG_XFER_IDLE             0
+#define CP_FLAG_XFER_BUSY             1
+#define CP_FLAG_NEWCTX                ((2 * 32) + 12)
+#define CP_FLAG_NEWCTX_BUSY           0
+#define CP_FLAG_NEWCTX_DONE           1
+#define CP_FLAG_ALWAYS                ((2 * 32) + 13)
+#define CP_FLAG_ALWAYS_FALSE          0
+#define CP_FLAG_ALWAYS_TRUE           1
+
+#define CP_CTX                   0x00100000
+#define CP_CTX_COUNT             0x000f0000
+#define CP_CTX_COUNT_SHIFT               16
+#define CP_CTX_REG               0x00003fff
+#define CP_LOAD_SR               0x00200000
+#define CP_LOAD_SR_VALUE         0x000fffff
+#define CP_BRA                   0x00400000
+#define CP_BRA_IP                0x0001ff00
+#define CP_BRA_IP_SHIFT                   8
+#define CP_BRA_IF_CLEAR          0x00000080
+#define CP_BRA_FLAG              0x0000007f
+#define CP_WAIT                  0x00500000
+#define CP_WAIT_SET              0x00000080
+#define CP_WAIT_FLAG             0x0000007f
+#define CP_SET                   0x00700000
+#define CP_SET_1                 0x00000080
+#define CP_SET_FLAG              0x0000007f
+#define CP_NEWCTX                0x00600004
+#define CP_NEXT_TO_SWAP          0x00600005
+#define CP_SET_CONTEXT_POINTER   0x00600006
+#define CP_SET_XFER_POINTER      0x00600007
+#define CP_ENABLE                0x00600009
+#define CP_END                   0x0060000c
+#define CP_NEXT_TO_CURRENT       0x0060000d
+#define CP_DISABLE1              0x0090ffff
+#define CP_DISABLE2              0x0091ffff
+#define CP_XFER_1      0x008000ff
+#define CP_XFER_2      0x008800ff
+#define CP_SEEK_1      0x00c000ff
+#define CP_SEEK_2      0x00c800ff
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_grctx.h"
+
+/*
+ * This code deals with PGRAPH contexts on NV50 family cards. Like NV40, it's
+ * the GPU itself that does context-switching, but it needs a special
+ * microcode to do it. And it's the driver's task to supply this microcode,
+ * further known as ctxprog, as well as the initial context values, known
+ * as ctxvals.
+ *
+ * Without ctxprog, you cannot switch contexts. Not even in software, since
+ * the majority of context [xfer strands] isn't accessible directly. You're
+ * stuck with a single channel, and you also suffer all the problems resulting
+ * from missing ctxvals, since you cannot load them.
+ *
+ * Without ctxvals, you're stuck with PGRAPH's default context. It's enough to
+ * run 2d operations, but trying to utilise 3d or CUDA will just lock you up,
+ * since you don't have... some sort of needed setup.
+ *
+ * Nouveau will just disable acceleration if not given ctxprog + ctxvals, since
+ * it's too much hassle to handle no-ctxprog as a special case.
+ */
+
+/*
+ * How ctxprogs work.
+ *
+ * The ctxprog is written in its own kind of microcode, with very small and
+ * crappy set of available commands. You upload it to a small [512 insns]
+ * area of memory on PGRAPH, and it'll be run when PFIFO wants PGRAPH to
+ * switch channel. or when the driver explicitely requests it. Stuff visible
+ * to ctxprog consists of: PGRAPH MMIO registers, PGRAPH context strands,
+ * the per-channel context save area in VRAM [known as ctxvals or grctx],
+ * 4 flags registers, a scratch register, two grctx pointers, plus many
+ * random poorly-understood details.
+ *
+ * When ctxprog runs, it's supposed to check what operations are asked of it,
+ * save old context if requested, optionally reset PGRAPH and switch to the
+ * new channel, and load the new context. Context consists of three major
+ * parts: subset of MMIO registers and two "xfer areas".
+ */
+
+/* TODO:
+ *  - document unimplemented bits compared to nvidia
+ *  - NVAx: make a TP subroutine, use it.
+ *  - use 0x4008fc instead of 0x1540?
+ */
+
+enum cp_label {
+	cp_check_load = 1,
+	cp_setup_auto_load,
+	cp_setup_load,
+	cp_setup_save,
+	cp_swap_state,
+	cp_prepare_exit,
+	cp_exit,
+};
+
+static void nv50_graph_construct_mmio(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_xfer1(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_xfer2(struct nouveau_grctx *ctx);
+
+/* Main function: construct the ctxprog skeleton, call the other functions. */
+
+int
+nv50_grctx_init(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+
+	switch (dev_priv->chipset) {
+	case 0x50:
+	case 0x84:
+	case 0x86:
+	case 0x92:
+	case 0x94:
+	case 0x96:
+	case 0x98:
+	case 0xa0:
+	case 0xa5:
+	case 0xa8:
+	case 0xaa:
+	case 0xac:
+		break;
+	default:
+		NV_ERROR(ctx->dev, "I don't know how to make a ctxprog for "
+				   "your NV%x card.\n", dev_priv->chipset);
+		NV_ERROR(ctx->dev, "Disabling acceleration. Please contact "
+				   "the devs.\n");
+		return -ENOSYS;
+	}
+	/* decide whether we're loading/unloading the context */
+	cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save);
+	cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save);
+
+	cp_name(ctx, cp_check_load);
+	cp_bra (ctx, AUTO_LOAD, PENDING, cp_setup_auto_load);
+	cp_bra (ctx, USER_LOAD, PENDING, cp_setup_load);
+	cp_bra (ctx, ALWAYS, TRUE, cp_exit);
+
+	/* setup for context load */
+	cp_name(ctx, cp_setup_auto_load);
+	cp_out (ctx, CP_DISABLE1);
+	cp_out (ctx, CP_DISABLE2);
+	cp_out (ctx, CP_ENABLE);
+	cp_out (ctx, CP_NEXT_TO_SWAP);
+	cp_set (ctx, UNK01, SET);
+	cp_name(ctx, cp_setup_load);
+	cp_out (ctx, CP_NEWCTX);
+	cp_wait(ctx, NEWCTX, BUSY);
+	cp_set (ctx, UNK1D, CLEAR);
+	cp_set (ctx, SWAP_DIRECTION, LOAD);
+	cp_bra (ctx, UNK0B, SET, cp_prepare_exit);
+	cp_bra (ctx, ALWAYS, TRUE, cp_swap_state);
+
+	/* setup for context save */
+	cp_name(ctx, cp_setup_save);
+	cp_set (ctx, UNK1D, SET);
+	cp_wait(ctx, STATUS, BUSY);
+	cp_set (ctx, UNK01, SET);
+	cp_set (ctx, SWAP_DIRECTION, SAVE);
+
+	/* general PGRAPH state */
+	cp_name(ctx, cp_swap_state);
+	cp_set (ctx, UNK03, SET);
+	cp_pos (ctx, 0x00004/4);
+	cp_ctx (ctx, 0x400828, 1); /* needed. otherwise, flickering happens. */
+	cp_pos (ctx, 0x00100/4);
+	nv50_graph_construct_mmio(ctx);
+	nv50_graph_construct_xfer1(ctx);
+	nv50_graph_construct_xfer2(ctx);
+
+	cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_check_load);
+
+	cp_set (ctx, UNK20, SET);
+	cp_set (ctx, SWAP_DIRECTION, SAVE); /* no idea why this is needed, but fixes at least one lockup. */
+	cp_lsr (ctx, ctx->ctxvals_base);
+	cp_out (ctx, CP_SET_XFER_POINTER);
+	cp_lsr (ctx, 4);
+	cp_out (ctx, CP_SEEK_1);
+	cp_out (ctx, CP_XFER_1);
+	cp_wait(ctx, XFER, BUSY);
+
+	/* pre-exit state updates */
+	cp_name(ctx, cp_prepare_exit);
+	cp_set (ctx, UNK01, CLEAR);
+	cp_set (ctx, UNK03, CLEAR);
+	cp_set (ctx, UNK1D, CLEAR);
+
+	cp_bra (ctx, USER_SAVE, PENDING, cp_exit);
+	cp_out (ctx, CP_NEXT_TO_CURRENT);
+
+	cp_name(ctx, cp_exit);
+	cp_set (ctx, USER_SAVE, NOT_PENDING);
+	cp_set (ctx, USER_LOAD, NOT_PENDING);
+	cp_out (ctx, CP_END);
+	ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */
+
+	return 0;
+}
+
+/*
+ * Constructs MMIO part of ctxprog and ctxvals. Just a matter of knowing which
+ * registers to save/restore and the default values for them.
+ */
+
+static void
+nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i, j;
+	int offset, base;
+	uint32_t units = nv_rd32 (ctx->dev, 0x1540);
+
+	/* 0800 */
+	cp_ctx(ctx, 0x400808, 7);
+	gr_def(ctx, 0x400814, 0x00000030);
+	cp_ctx(ctx, 0x400834, 0x32);
+	if (dev_priv->chipset == 0x50) {
+		gr_def(ctx, 0x400834, 0xff400040);
+		gr_def(ctx, 0x400838, 0xfff00080);
+		gr_def(ctx, 0x40083c, 0xfff70090);
+		gr_def(ctx, 0x400840, 0xffe806a8);
+	}
+	gr_def(ctx, 0x400844, 0x00000002);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		gr_def(ctx, 0x400894, 0x00001000);
+	gr_def(ctx, 0x4008e8, 0x00000003);
+	gr_def(ctx, 0x4008ec, 0x00001000);
+	if (dev_priv->chipset == 0x50)
+		cp_ctx(ctx, 0x400908, 0xb);
+	else if (dev_priv->chipset < 0xa0)
+		cp_ctx(ctx, 0x400908, 0xc);
+	else
+		cp_ctx(ctx, 0x400908, 0xe);
+
+	if (dev_priv->chipset >= 0xa0)
+		cp_ctx(ctx, 0x400b00, 0x1);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		cp_ctx(ctx, 0x400b10, 0x1);
+		gr_def(ctx, 0x400b10, 0x0001629d);
+		cp_ctx(ctx, 0x400b20, 0x1);
+		gr_def(ctx, 0x400b20, 0x0001629d);
+	}
+
+	/* 0C00 */
+	cp_ctx(ctx, 0x400c08, 0x2);
+	gr_def(ctx, 0x400c08, 0x0000fe0c);
+
+	/* 1000 */
+	if (dev_priv->chipset < 0xa0) {
+		cp_ctx(ctx, 0x401008, 0x4);
+		gr_def(ctx, 0x401014, 0x00001000);
+	} else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) {
+		cp_ctx(ctx, 0x401008, 0x5);
+		gr_def(ctx, 0x401018, 0x00001000);
+	} else {
+		cp_ctx(ctx, 0x401008, 0x5);
+		gr_def(ctx, 0x401018, 0x00004000);
+	}
+
+	/* 1400 */
+	cp_ctx(ctx, 0x401400, 0x8);
+	cp_ctx(ctx, 0x401424, 0x3);
+	if (dev_priv->chipset == 0x50)
+		gr_def(ctx, 0x40142c, 0x0001fd87);
+	else
+		gr_def(ctx, 0x40142c, 0x00000187);
+	cp_ctx(ctx, 0x401540, 0x5);
+	gr_def(ctx, 0x401550, 0x00001018);
+
+	/* 1800 */
+	cp_ctx(ctx, 0x401814, 0x1);
+	gr_def(ctx, 0x401814, 0x000000ff);
+	if (dev_priv->chipset == 0x50) {
+		cp_ctx(ctx, 0x40181c, 0xe);
+		gr_def(ctx, 0x401850, 0x00000004);
+	} else if (dev_priv->chipset < 0xa0) {
+		cp_ctx(ctx, 0x40181c, 0xf);
+		gr_def(ctx, 0x401854, 0x00000004);
+	} else {
+		cp_ctx(ctx, 0x40181c, 0x13);
+		gr_def(ctx, 0x401864, 0x00000004);
+	}
+
+	/* 1C00 */
+	cp_ctx(ctx, 0x401c00, 0x1);
+	switch (dev_priv->chipset) {
+	case 0x50:
+		gr_def(ctx, 0x401c00, 0x0001005f);
+		break;
+	case 0x84:
+	case 0x86:
+	case 0x94:
+		gr_def(ctx, 0x401c00, 0x044d00df);
+		break;
+	case 0x92:
+	case 0x96:
+	case 0x98:
+	case 0xa0:
+	case 0xaa:
+	case 0xac:
+		gr_def(ctx, 0x401c00, 0x042500df);
+		break;
+	case 0xa5:
+	case 0xa8:
+		gr_def(ctx, 0x401c00, 0x142500df);
+		break;
+	}
+
+	/* 2400 */
+	cp_ctx(ctx, 0x402400, 0x1);
+	if (dev_priv->chipset == 0x50)
+		cp_ctx(ctx, 0x402408, 0x1);
+	else
+		cp_ctx(ctx, 0x402408, 0x2);
+	gr_def(ctx, 0x402408, 0x00000600);
+
+	/* 2800 */
+	cp_ctx(ctx, 0x402800, 0x1);
+	if (dev_priv->chipset == 0x50)
+		gr_def(ctx, 0x402800, 0x00000006);
+
+	/* 2C00 */
+	cp_ctx(ctx, 0x402c08, 0x6);
+	if (dev_priv->chipset != 0x50)
+		gr_def(ctx, 0x402c14, 0x01000000);
+	gr_def(ctx, 0x402c18, 0x000000ff);
+	if (dev_priv->chipset == 0x50)
+		cp_ctx(ctx, 0x402ca0, 0x1);
+	else
+		cp_ctx(ctx, 0x402ca0, 0x2);
+	if (dev_priv->chipset < 0xa0)
+		gr_def(ctx, 0x402ca0, 0x00000400);
+	else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa)
+		gr_def(ctx, 0x402ca0, 0x00000800);
+	else
+		gr_def(ctx, 0x402ca0, 0x00000400);
+	cp_ctx(ctx, 0x402cac, 0x4);
+
+	/* 3000 */
+	cp_ctx(ctx, 0x403004, 0x1);
+	gr_def(ctx, 0x403004, 0x00000001);
+
+	/* 3404 */
+	if (dev_priv->chipset >= 0xa0) {
+		cp_ctx(ctx, 0x403404, 0x1);
+		gr_def(ctx, 0x403404, 0x00000001);
+	}
+
+	/* 5000 */
+	cp_ctx(ctx, 0x405000, 0x1);
+	switch (dev_priv->chipset) {
+	case 0x50:
+		gr_def(ctx, 0x405000, 0x00300080);
+		break;
+	case 0x84:
+	case 0xa0:
+	case 0xa5:
+	case 0xa8:
+	case 0xaa:
+	case 0xac:
+		gr_def(ctx, 0x405000, 0x000e0080);
+		break;
+	case 0x86:
+	case 0x92:
+	case 0x94:
+	case 0x96:
+	case 0x98:
+		gr_def(ctx, 0x405000, 0x00000080);
+		break;
+	}
+	cp_ctx(ctx, 0x405014, 0x1);
+	gr_def(ctx, 0x405014, 0x00000004);
+	cp_ctx(ctx, 0x40501c, 0x1);
+	cp_ctx(ctx, 0x405024, 0x1);
+	cp_ctx(ctx, 0x40502c, 0x1);
+
+	/* 5400 or maybe 4800 */
+	if (dev_priv->chipset == 0x50) {
+		offset = 0x405400;
+		cp_ctx(ctx, 0x405400, 0xea);
+	} else if (dev_priv->chipset < 0x94) {
+		offset = 0x405400;
+		cp_ctx(ctx, 0x405400, 0xcb);
+	} else if (dev_priv->chipset < 0xa0) {
+		offset = 0x405400;
+		cp_ctx(ctx, 0x405400, 0xcc);
+	} else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		offset = 0x404800;
+		cp_ctx(ctx, 0x404800, 0xda);
+	} else {
+		offset = 0x405400;
+		cp_ctx(ctx, 0x405400, 0xd4);
+	}
+	gr_def(ctx, offset + 0x0c, 0x00000002);
+	gr_def(ctx, offset + 0x10, 0x00000001);
+	if (dev_priv->chipset >= 0x94)
+		offset += 4;
+	gr_def(ctx, offset + 0x1c, 0x00000001);
+	gr_def(ctx, offset + 0x20, 0x00000100);
+	gr_def(ctx, offset + 0x38, 0x00000002);
+	gr_def(ctx, offset + 0x3c, 0x00000001);
+	gr_def(ctx, offset + 0x40, 0x00000001);
+	gr_def(ctx, offset + 0x50, 0x00000001);
+	gr_def(ctx, offset + 0x54, 0x003fffff);
+	gr_def(ctx, offset + 0x58, 0x00001fff);
+	gr_def(ctx, offset + 0x60, 0x00000001);
+	gr_def(ctx, offset + 0x64, 0x00000001);
+	gr_def(ctx, offset + 0x6c, 0x00000001);
+	gr_def(ctx, offset + 0x70, 0x00000001);
+	gr_def(ctx, offset + 0x74, 0x00000001);
+	gr_def(ctx, offset + 0x78, 0x00000004);
+	gr_def(ctx, offset + 0x7c, 0x00000001);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		offset += 4;
+	gr_def(ctx, offset + 0x80, 0x00000001);
+	gr_def(ctx, offset + 0x84, 0x00000001);
+	gr_def(ctx, offset + 0x88, 0x00000007);
+	gr_def(ctx, offset + 0x8c, 0x00000001);
+	gr_def(ctx, offset + 0x90, 0x00000007);
+	gr_def(ctx, offset + 0x94, 0x00000001);
+	gr_def(ctx, offset + 0x98, 0x00000001);
+	gr_def(ctx, offset + 0x9c, 0x00000001);
+	if (dev_priv->chipset == 0x50) {
+		 gr_def(ctx, offset + 0xb0, 0x00000001);
+		 gr_def(ctx, offset + 0xb4, 0x00000001);
+		 gr_def(ctx, offset + 0xbc, 0x00000001);
+		 gr_def(ctx, offset + 0xc0, 0x0000000a);
+		 gr_def(ctx, offset + 0xd0, 0x00000040);
+		 gr_def(ctx, offset + 0xd8, 0x00000002);
+		 gr_def(ctx, offset + 0xdc, 0x00000100);
+		 gr_def(ctx, offset + 0xe0, 0x00000001);
+		 gr_def(ctx, offset + 0xe4, 0x00000100);
+		 gr_def(ctx, offset + 0x100, 0x00000001);
+		 gr_def(ctx, offset + 0x124, 0x00000004);
+		 gr_def(ctx, offset + 0x13c, 0x00000001);
+		 gr_def(ctx, offset + 0x140, 0x00000100);
+		 gr_def(ctx, offset + 0x148, 0x00000001);
+		 gr_def(ctx, offset + 0x154, 0x00000100);
+		 gr_def(ctx, offset + 0x158, 0x00000001);
+		 gr_def(ctx, offset + 0x15c, 0x00000100);
+		 gr_def(ctx, offset + 0x164, 0x00000001);
+		 gr_def(ctx, offset + 0x170, 0x00000100);
+		 gr_def(ctx, offset + 0x174, 0x00000001);
+		 gr_def(ctx, offset + 0x17c, 0x00000001);
+		 gr_def(ctx, offset + 0x188, 0x00000002);
+		 gr_def(ctx, offset + 0x190, 0x00000001);
+		 gr_def(ctx, offset + 0x198, 0x00000001);
+		 gr_def(ctx, offset + 0x1ac, 0x00000003);
+		 offset += 0xd0;
+	} else {
+		gr_def(ctx, offset + 0xb0, 0x00000001);
+		gr_def(ctx, offset + 0xb4, 0x00000100);
+		gr_def(ctx, offset + 0xbc, 0x00000001);
+		gr_def(ctx, offset + 0xc8, 0x00000100);
+		gr_def(ctx, offset + 0xcc, 0x00000001);
+		gr_def(ctx, offset + 0xd0, 0x00000100);
+		gr_def(ctx, offset + 0xd8, 0x00000001);
+		gr_def(ctx, offset + 0xe4, 0x00000100);
+	}
+	gr_def(ctx, offset + 0xf8, 0x00000004);
+	gr_def(ctx, offset + 0xfc, 0x00000070);
+	gr_def(ctx, offset + 0x100, 0x00000080);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		offset += 4;
+	gr_def(ctx, offset + 0x114, 0x0000000c);
+	if (dev_priv->chipset == 0x50)
+		offset -= 4;
+	gr_def(ctx, offset + 0x11c, 0x00000008);
+	gr_def(ctx, offset + 0x120, 0x00000014);
+	if (dev_priv->chipset == 0x50) {
+		gr_def(ctx, offset + 0x124, 0x00000026);
+		offset -= 0x18;
+	} else {
+		gr_def(ctx, offset + 0x128, 0x00000029);
+		gr_def(ctx, offset + 0x12c, 0x00000027);
+		gr_def(ctx, offset + 0x130, 0x00000026);
+		gr_def(ctx, offset + 0x134, 0x00000008);
+		gr_def(ctx, offset + 0x138, 0x00000004);
+		gr_def(ctx, offset + 0x13c, 0x00000027);
+	}
+	gr_def(ctx, offset + 0x148, 0x00000001);
+	gr_def(ctx, offset + 0x14c, 0x00000002);
+	gr_def(ctx, offset + 0x150, 0x00000003);
+	gr_def(ctx, offset + 0x154, 0x00000004);
+	gr_def(ctx, offset + 0x158, 0x00000005);
+	gr_def(ctx, offset + 0x15c, 0x00000006);
+	gr_def(ctx, offset + 0x160, 0x00000007);
+	gr_def(ctx, offset + 0x164, 0x00000001);
+	gr_def(ctx, offset + 0x1a8, 0x000000cf);
+	if (dev_priv->chipset == 0x50)
+		offset -= 4;
+	gr_def(ctx, offset + 0x1d8, 0x00000080);
+	gr_def(ctx, offset + 0x1dc, 0x00000004);
+	gr_def(ctx, offset + 0x1e0, 0x00000004);
+	if (dev_priv->chipset == 0x50)
+		offset -= 4;
+	else
+		gr_def(ctx, offset + 0x1e4, 0x00000003);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		gr_def(ctx, offset + 0x1ec, 0x00000003);
+		offset += 8;
+	}
+	gr_def(ctx, offset + 0x1e8, 0x00000001);
+	if (dev_priv->chipset == 0x50)
+		offset -= 4;
+	gr_def(ctx, offset + 0x1f4, 0x00000012);
+	gr_def(ctx, offset + 0x1f8, 0x00000010);
+	gr_def(ctx, offset + 0x1fc, 0x0000000c);
+	gr_def(ctx, offset + 0x200, 0x00000001);
+	gr_def(ctx, offset + 0x210, 0x00000004);
+	gr_def(ctx, offset + 0x214, 0x00000002);
+	gr_def(ctx, offset + 0x218, 0x00000004);
+	if (dev_priv->chipset >= 0xa0)
+		offset += 4;
+	gr_def(ctx, offset + 0x224, 0x003fffff);
+	gr_def(ctx, offset + 0x228, 0x00001fff);
+	if (dev_priv->chipset == 0x50)
+		offset -= 0x20;
+	else if (dev_priv->chipset >= 0xa0) {
+		gr_def(ctx, offset + 0x250, 0x00000001);
+		gr_def(ctx, offset + 0x254, 0x00000001);
+		gr_def(ctx, offset + 0x258, 0x00000002);
+		offset += 0x10;
+	}
+	gr_def(ctx, offset + 0x250, 0x00000004);
+	gr_def(ctx, offset + 0x254, 0x00000014);
+	gr_def(ctx, offset + 0x258, 0x00000001);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		offset += 4;
+	gr_def(ctx, offset + 0x264, 0x00000002);
+	if (dev_priv->chipset >= 0xa0)
+		offset += 8;
+	gr_def(ctx, offset + 0x270, 0x00000001);
+	gr_def(ctx, offset + 0x278, 0x00000002);
+	gr_def(ctx, offset + 0x27c, 0x00001000);
+	if (dev_priv->chipset == 0x50)
+		offset -= 0xc;
+	else {
+		gr_def(ctx, offset + 0x280, 0x00000e00);
+		gr_def(ctx, offset + 0x284, 0x00001000);
+		gr_def(ctx, offset + 0x288, 0x00001e00);
+	}
+	gr_def(ctx, offset + 0x290, 0x00000001);
+	gr_def(ctx, offset + 0x294, 0x00000001);
+	gr_def(ctx, offset + 0x298, 0x00000001);
+	gr_def(ctx, offset + 0x29c, 0x00000001);
+	gr_def(ctx, offset + 0x2a0, 0x00000001);
+	gr_def(ctx, offset + 0x2b0, 0x00000200);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		gr_def(ctx, offset + 0x2b4, 0x00000200);
+		offset += 4;
+	}
+	if (dev_priv->chipset < 0xa0) {
+		gr_def(ctx, offset + 0x2b8, 0x00000001);
+		gr_def(ctx, offset + 0x2bc, 0x00000070);
+		gr_def(ctx, offset + 0x2c0, 0x00000080);
+		gr_def(ctx, offset + 0x2cc, 0x00000001);
+		gr_def(ctx, offset + 0x2d0, 0x00000070);
+		gr_def(ctx, offset + 0x2d4, 0x00000080);
+	} else {
+		gr_def(ctx, offset + 0x2b8, 0x00000001);
+		gr_def(ctx, offset + 0x2bc, 0x000000f0);
+		gr_def(ctx, offset + 0x2c0, 0x000000ff);
+		gr_def(ctx, offset + 0x2cc, 0x00000001);
+		gr_def(ctx, offset + 0x2d0, 0x000000f0);
+		gr_def(ctx, offset + 0x2d4, 0x000000ff);
+		gr_def(ctx, offset + 0x2dc, 0x00000009);
+		offset += 4;
+	}
+	gr_def(ctx, offset + 0x2e4, 0x00000001);
+	gr_def(ctx, offset + 0x2e8, 0x000000cf);
+	gr_def(ctx, offset + 0x2f0, 0x00000001);
+	gr_def(ctx, offset + 0x300, 0x000000cf);
+	gr_def(ctx, offset + 0x308, 0x00000002);
+	gr_def(ctx, offset + 0x310, 0x00000001);
+	gr_def(ctx, offset + 0x318, 0x00000001);
+	gr_def(ctx, offset + 0x320, 0x000000cf);
+	gr_def(ctx, offset + 0x324, 0x000000cf);
+	gr_def(ctx, offset + 0x328, 0x00000001);
+
+	/* 6000? */
+	if (dev_priv->chipset == 0x50)
+		cp_ctx(ctx, 0x4063e0, 0x1);
+
+	/* 6800 */
+	if (dev_priv->chipset < 0x90) {
+		cp_ctx(ctx, 0x406814, 0x2b);
+		gr_def(ctx, 0x406818, 0x00000f80);
+		gr_def(ctx, 0x406860, 0x007f0080);
+		gr_def(ctx, 0x40689c, 0x007f0080);
+	} else {
+		cp_ctx(ctx, 0x406814, 0x4);
+		if (dev_priv->chipset == 0x98)
+			gr_def(ctx, 0x406818, 0x00000f80);
+		else
+			gr_def(ctx, 0x406818, 0x00001f80);
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+			gr_def(ctx, 0x40681c, 0x00000030);
+		cp_ctx(ctx, 0x406830, 0x3);
+	}
+
+	/* 7000: per-ROP group state */
+	for (i = 0; i < 8; i++) {
+		if (units & (1<<(i+16))) {
+			cp_ctx(ctx, 0x407000 + (i<<8), 3);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, 0x407000 + (i<<8), 0x1b74f820);
+			else if (dev_priv->chipset != 0xa5)
+				gr_def(ctx, 0x407000 + (i<<8), 0x3b74f821);
+			else
+				gr_def(ctx, 0x407000 + (i<<8), 0x7b74f821);
+			gr_def(ctx, 0x407004 + (i<<8), 0x89058001);
+
+			if (dev_priv->chipset == 0x50) {
+				cp_ctx(ctx, 0x407010 + (i<<8), 1);
+			} else if (dev_priv->chipset < 0xa0) {
+				cp_ctx(ctx, 0x407010 + (i<<8), 2);
+				gr_def(ctx, 0x407010 + (i<<8), 0x00001000);
+				gr_def(ctx, 0x407014 + (i<<8), 0x0000001f);
+			} else {
+				cp_ctx(ctx, 0x407010 + (i<<8), 3);
+				gr_def(ctx, 0x407010 + (i<<8), 0x00001000);
+				if (dev_priv->chipset != 0xa5)
+					gr_def(ctx, 0x407014 + (i<<8), 0x000000ff);
+				else
+					gr_def(ctx, 0x407014 + (i<<8), 0x000001ff);
+			}
+
+			cp_ctx(ctx, 0x407080 + (i<<8), 4);
+			if (dev_priv->chipset != 0xa5)
+				gr_def(ctx, 0x407080 + (i<<8), 0x027c10fa);
+			else
+				gr_def(ctx, 0x407080 + (i<<8), 0x827c10fa);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, 0x407084 + (i<<8), 0x000000c0);
+			else
+				gr_def(ctx, 0x407084 + (i<<8), 0x400000c0);
+			gr_def(ctx, 0x407088 + (i<<8), 0xb7892080);
+
+			if (dev_priv->chipset < 0xa0)
+				cp_ctx(ctx, 0x407094 + (i<<8), 1);
+			else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa)
+				cp_ctx(ctx, 0x407094 + (i<<8), 3);
+			else {
+				cp_ctx(ctx, 0x407094 + (i<<8), 4);
+				gr_def(ctx, 0x4070a0 + (i<<8), 1);
+			}
+		}
+	}
+
+	cp_ctx(ctx, 0x407c00, 0x3);
+	if (dev_priv->chipset < 0x90)
+		gr_def(ctx, 0x407c00, 0x00010040);
+	else if (dev_priv->chipset < 0xa0)
+		gr_def(ctx, 0x407c00, 0x00390040);
+	else
+		gr_def(ctx, 0x407c00, 0x003d0040);
+	gr_def(ctx, 0x407c08, 0x00000022);
+	if (dev_priv->chipset >= 0xa0) {
+		cp_ctx(ctx, 0x407c10, 0x3);
+		cp_ctx(ctx, 0x407c20, 0x1);
+		cp_ctx(ctx, 0x407c2c, 0x1);
+	}
+
+	if (dev_priv->chipset < 0xa0) {
+		cp_ctx(ctx, 0x407d00, 0x9);
+	} else {
+		cp_ctx(ctx, 0x407d00, 0x15);
+	}
+	if (dev_priv->chipset == 0x98)
+		gr_def(ctx, 0x407d08, 0x00380040);
+	else {
+		if (dev_priv->chipset < 0x90)
+			gr_def(ctx, 0x407d08, 0x00010040);
+		else if (dev_priv->chipset < 0xa0)
+			gr_def(ctx, 0x407d08, 0x00390040);
+		else
+			gr_def(ctx, 0x407d08, 0x003d0040);
+		gr_def(ctx, 0x407d0c, 0x00000022);
+	}
+
+	/* 8000+: per-TP state */
+	for (i = 0; i < 10; i++) {
+		if (units & (1<<i)) {
+			if (dev_priv->chipset < 0xa0)
+				base = 0x408000 + (i<<12);
+			else
+				base = 0x408000 + (i<<11);
+			if (dev_priv->chipset < 0xa0)
+				offset = base + 0xc00;
+			else
+				offset = base + 0x80;
+			cp_ctx(ctx, offset + 0x00, 1);
+			gr_def(ctx, offset + 0x00, 0x0000ff0a);
+			cp_ctx(ctx, offset + 0x08, 1);
+
+			/* per-MP state */
+			for (j = 0; j < (dev_priv->chipset < 0xa0 ? 2 : 4); j++) {
+				if (!(units & (1 << (j+24)))) continue;
+				if (dev_priv->chipset < 0xa0)
+					offset = base + 0x200 + (j<<7);
+				else
+					offset = base + 0x100 + (j<<7);
+				cp_ctx(ctx, offset, 0x20);
+				gr_def(ctx, offset + 0x00, 0x01800000);
+				gr_def(ctx, offset + 0x04, 0x00160000);
+				gr_def(ctx, offset + 0x08, 0x01800000);
+				gr_def(ctx, offset + 0x18, 0x0003ffff);
+				switch (dev_priv->chipset) {
+				case 0x50:
+					gr_def(ctx, offset + 0x1c, 0x00080000);
+					break;
+				case 0x84:
+					gr_def(ctx, offset + 0x1c, 0x00880000);
+					break;
+				case 0x86:
+					gr_def(ctx, offset + 0x1c, 0x008c0000);
+					break;
+				case 0x92:
+				case 0x96:
+				case 0x98:
+					gr_def(ctx, offset + 0x1c, 0x118c0000);
+					break;
+				case 0x94:
+					gr_def(ctx, offset + 0x1c, 0x10880000);
+					break;
+				case 0xa0:
+				case 0xa5:
+					gr_def(ctx, offset + 0x1c, 0x310c0000);
+					break;
+				case 0xa8:
+				case 0xaa:
+				case 0xac:
+					gr_def(ctx, offset + 0x1c, 0x300c0000);
+					break;
+				}
+				gr_def(ctx, offset + 0x40, 0x00010401);
+				if (dev_priv->chipset == 0x50)
+					gr_def(ctx, offset + 0x48, 0x00000040);
+				else
+					gr_def(ctx, offset + 0x48, 0x00000078);
+				gr_def(ctx, offset + 0x50, 0x000000bf);
+				gr_def(ctx, offset + 0x58, 0x00001210);
+				if (dev_priv->chipset == 0x50)
+					gr_def(ctx, offset + 0x5c, 0x00000080);
+				else
+					gr_def(ctx, offset + 0x5c, 0x08000080);
+				if (dev_priv->chipset >= 0xa0)
+					gr_def(ctx, offset + 0x68, 0x0000003e);
+			}
+
+			if (dev_priv->chipset < 0xa0)
+				cp_ctx(ctx, base + 0x300, 0x4);
+			else
+				cp_ctx(ctx, base + 0x300, 0x5);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, base + 0x304, 0x00007070);
+			else if (dev_priv->chipset < 0xa0)
+				gr_def(ctx, base + 0x304, 0x00027070);
+			else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa)
+				gr_def(ctx, base + 0x304, 0x01127070);
+			else
+				gr_def(ctx, base + 0x304, 0x05127070);
+
+			if (dev_priv->chipset < 0xa0)
+				cp_ctx(ctx, base + 0x318, 1);
+			else
+				cp_ctx(ctx, base + 0x320, 1);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, base + 0x318, 0x0003ffff);
+			else if (dev_priv->chipset < 0xa0)
+				gr_def(ctx, base + 0x318, 0x03ffffff);
+			else
+				gr_def(ctx, base + 0x320, 0x07ffffff);
+
+			if (dev_priv->chipset < 0xa0)
+				cp_ctx(ctx, base + 0x324, 5);
+			else
+				cp_ctx(ctx, base + 0x328, 4);
+
+			if (dev_priv->chipset < 0xa0) {
+				cp_ctx(ctx, base + 0x340, 9);
+				offset = base + 0x340;
+			} else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) {
+				cp_ctx(ctx, base + 0x33c, 0xb);
+				offset = base + 0x344;
+			} else {
+				cp_ctx(ctx, base + 0x33c, 0xd);
+				offset = base + 0x344;
+			}
+			gr_def(ctx, offset + 0x0, 0x00120407);
+			gr_def(ctx, offset + 0x4, 0x05091507);
+			if (dev_priv->chipset == 0x84)
+				gr_def(ctx, offset + 0x8, 0x05100202);
+			else
+				gr_def(ctx, offset + 0x8, 0x05010202);
+			gr_def(ctx, offset + 0xc, 0x00030201);
+
+			cp_ctx(ctx, base + 0x400, 2);
+			gr_def(ctx, base + 0x404, 0x00000040);
+			cp_ctx(ctx, base + 0x40c, 2);
+			gr_def(ctx, base + 0x40c, 0x0d0c0b0a);
+			gr_def(ctx, base + 0x410, 0x00141210);
+
+			if (dev_priv->chipset < 0xa0)
+				offset = base + 0x800;
+			else
+				offset = base + 0x500;
+			cp_ctx(ctx, offset, 6);
+			gr_def(ctx, offset + 0x0, 0x000001f0);
+			gr_def(ctx, offset + 0x4, 0x00000001);
+			gr_def(ctx, offset + 0x8, 0x00000003);
+			if (dev_priv->chipset == 0x50 || dev_priv->chipset >= 0xaa)
+				gr_def(ctx, offset + 0xc, 0x00008000);
+			gr_def(ctx, offset + 0x14, 0x00039e00);
+			cp_ctx(ctx, offset + 0x1c, 2);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, offset + 0x1c, 0x00000040);
+			else
+				gr_def(ctx, offset + 0x1c, 0x00000100);
+			gr_def(ctx, offset + 0x20, 0x00003800);
+
+			if (dev_priv->chipset >= 0xa0) {
+				cp_ctx(ctx, base + 0x54c, 2);
+				if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa)
+					gr_def(ctx, base + 0x54c, 0x003fe006);
+				else
+					gr_def(ctx, base + 0x54c, 0x003fe007);
+				gr_def(ctx, base + 0x550, 0x003fe000);
+			}
+
+			if (dev_priv->chipset < 0xa0)
+				offset = base + 0xa00;
+			else
+				offset = base + 0x680;
+			cp_ctx(ctx, offset, 1);
+			gr_def(ctx, offset, 0x00404040);
+
+			if (dev_priv->chipset < 0xa0)
+				offset = base + 0xe00;
+			else
+				offset = base + 0x700;
+			cp_ctx(ctx, offset, 2);
+			if (dev_priv->chipset < 0xa0)
+				gr_def(ctx, offset, 0x0077f005);
+			else if (dev_priv->chipset == 0xa5)
+				gr_def(ctx, offset, 0x6cf7f007);
+			else if (dev_priv->chipset == 0xa8)
+				gr_def(ctx, offset, 0x6cfff007);
+			else if (dev_priv->chipset == 0xac)
+				gr_def(ctx, offset, 0x0cfff007);
+			else
+				gr_def(ctx, offset, 0x0cf7f007);
+			if (dev_priv->chipset == 0x50)
+				gr_def(ctx, offset + 0x4, 0x00007fff);
+			else if (dev_priv->chipset < 0xa0)
+				gr_def(ctx, offset + 0x4, 0x003f7fff);
+			else
+				gr_def(ctx, offset + 0x4, 0x02bf7fff);
+			cp_ctx(ctx, offset + 0x2c, 1);
+			if (dev_priv->chipset == 0x50) {
+				cp_ctx(ctx, offset + 0x50, 9);
+				gr_def(ctx, offset + 0x54, 0x000003ff);
+				gr_def(ctx, offset + 0x58, 0x00000003);
+				gr_def(ctx, offset + 0x5c, 0x00000003);
+				gr_def(ctx, offset + 0x60, 0x000001ff);
+				gr_def(ctx, offset + 0x64, 0x0000001f);
+				gr_def(ctx, offset + 0x68, 0x0000000f);
+				gr_def(ctx, offset + 0x6c, 0x0000000f);
+			} else if(dev_priv->chipset < 0xa0) {
+				cp_ctx(ctx, offset + 0x50, 1);
+				cp_ctx(ctx, offset + 0x70, 1);
+			} else {
+				cp_ctx(ctx, offset + 0x50, 1);
+				cp_ctx(ctx, offset + 0x60, 5);
+			}
+		}
+	}
+}
+
+/*
+ * xfer areas. These are a pain.
+ *
+ * There are 2 xfer areas: the first one is big and contains all sorts of
+ * stuff, the second is small and contains some per-TP context.
+ *
+ * Each area is split into 8 "strands". The areas, when saved to grctx,
+ * are made of 8-word blocks. Each block contains a single word from
+ * each strand. The strands are independent of each other, their
+ * addresses are unrelated to each other, and data in them is closely
+ * packed together. The strand layout varies a bit between cards: here
+ * and there, a single word is thrown out in the middle and the whole
+ * strand is offset by a bit from corresponding one on another chipset.
+ * For this reason, addresses of stuff in strands are almost useless.
+ * Knowing sequence of stuff and size of gaps between them is much more
+ * useful, and that's how we build the strands in our generator.
+ *
+ * NVA0 takes this mess to a whole new level by cutting the old strands
+ * into a few dozen pieces [known as genes], rearranging them randomly,
+ * and putting them back together to make new strands. Hopefully these
+ * genes correspond more or less directly to the same PGRAPH subunits
+ * as in 400040 register.
+ *
+ * The most common value in default context is 0, and when the genes
+ * are separated by 0's, gene bounduaries are quite speculative...
+ * some of them can be clearly deduced, others can be guessed, and yet
+ * others won't be resolved without figuring out the real meaning of
+ * given ctxval. For the same reason, ending point of each strand
+ * is unknown. Except for strand 0, which is the longest strand and
+ * its end corresponds to end of the whole xfer.
+ *
+ * An unsolved mystery is the seek instruction: it takes an argument
+ * in bits 8-18, and that argument is clearly the place in strands to
+ * seek to... but the offsets don't seem to correspond to offsets as
+ * seen in grctx. Perhaps there's another, real, not randomly-changing
+ * addressing in strands, and the xfer insn just happens to skip over
+ * the unused bits? NV10-NV30 PIPE comes to mind...
+ *
+ * As far as I know, there's no way to access the xfer areas directly
+ * without the help of ctxprog.
+ */
+
+static inline void
+xf_emit(struct nouveau_grctx *ctx, int num, uint32_t val) {
+	int i;
+	if (val && ctx->mode == NOUVEAU_GRCTX_VALS)
+		for (i = 0; i < num; i++)
+			nv_wo32(ctx->dev, ctx->data, ctx->ctxvals_pos + (i << 3), val);
+	ctx->ctxvals_pos += num << 3;
+}
+
+/* Gene declarations... */
+
+static void nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk2(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk3(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk4(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk5(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk6(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk7(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk8(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk9(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_unk10(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx);
+static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx);
+
+static void
+nv50_graph_construct_xfer1(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i;
+	int offset;
+	int size = 0;
+	uint32_t units = nv_rd32 (ctx->dev, 0x1540);
+
+	offset = (ctx->ctxvals_pos+0x3f)&~0x3f;
+	ctx->ctxvals_base = offset;
+
+	if (dev_priv->chipset < 0xa0) {
+		/* Strand 0 */
+		ctx->ctxvals_pos = offset;
+		switch (dev_priv->chipset) {
+		case 0x50:
+			xf_emit(ctx, 0x99, 0);
+			break;
+		case 0x84:
+		case 0x86:
+			xf_emit(ctx, 0x384, 0);
+			break;
+		case 0x92:
+		case 0x94:
+		case 0x96:
+		case 0x98:
+			xf_emit(ctx, 0x380, 0);
+			break;
+		}
+		nv50_graph_construct_gene_m2mf (ctx);
+		switch (dev_priv->chipset) {
+		case 0x50:
+		case 0x84:
+		case 0x86:
+		case 0x98:
+			xf_emit(ctx, 0x4c4, 0);
+			break;
+		case 0x92:
+		case 0x94:
+		case 0x96:
+			xf_emit(ctx, 0x984, 0);
+			break;
+		}
+		nv50_graph_construct_gene_unk5(ctx);
+		if (dev_priv->chipset == 0x50)
+			xf_emit(ctx, 0xa, 0);
+		else
+			xf_emit(ctx, 0xb, 0);
+		nv50_graph_construct_gene_unk4(ctx);
+		nv50_graph_construct_gene_unk3(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 1 */
+		ctx->ctxvals_pos = offset + 0x1;
+		nv50_graph_construct_gene_unk6(ctx);
+		nv50_graph_construct_gene_unk7(ctx);
+		nv50_graph_construct_gene_unk8(ctx);
+		switch (dev_priv->chipset) {
+		case 0x50:
+		case 0x92:
+			xf_emit(ctx, 0xfb, 0);
+			break;
+		case 0x84:
+			xf_emit(ctx, 0xd3, 0);
+			break;
+		case 0x94:
+		case 0x96:
+			xf_emit(ctx, 0xab, 0);
+			break;
+		case 0x86:
+		case 0x98:
+			xf_emit(ctx, 0x6b, 0);
+			break;
+		}
+		xf_emit(ctx, 2, 0x4e3bfdf);
+		xf_emit(ctx, 4, 0);
+		xf_emit(ctx, 1, 0x0fac6881);
+		xf_emit(ctx, 0xb, 0);
+		xf_emit(ctx, 2, 0x4e3bfdf);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 2 */
+		ctx->ctxvals_pos = offset + 0x2;
+		switch (dev_priv->chipset) {
+		case 0x50:
+		case 0x92:
+			xf_emit(ctx, 0xa80, 0);
+			break;
+		case 0x84:
+			xf_emit(ctx, 0xa7e, 0);
+			break;
+		case 0x94:
+		case 0x96:
+			xf_emit(ctx, 0xa7c, 0);
+			break;
+		case 0x86:
+		case 0x98:
+			xf_emit(ctx, 0xa7a, 0);
+			break;
+		}
+		xf_emit(ctx, 1, 0x3fffff);
+		xf_emit(ctx, 2, 0);
+		xf_emit(ctx, 1, 0x1fff);
+		xf_emit(ctx, 0xe, 0);
+		nv50_graph_construct_gene_unk9(ctx);
+		nv50_graph_construct_gene_unk2(ctx);
+		nv50_graph_construct_gene_unk1(ctx);
+		nv50_graph_construct_gene_unk10(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 3: per-ROP group state */
+		ctx->ctxvals_pos = offset + 3;
+		for (i = 0; i < 6; i++)
+			if (units & (1 << (i + 16)))
+				nv50_graph_construct_gene_ropc(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strands 4-7: per-TP state */
+		for (i = 0; i < 4; i++) {
+			ctx->ctxvals_pos = offset + 4 + i;
+			if (units & (1 << (2 * i)))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << (2 * i + 1)))
+				nv50_graph_construct_xfer_tp(ctx);
+			if ((ctx->ctxvals_pos-offset)/8 > size)
+				size = (ctx->ctxvals_pos-offset)/8;
+		}
+	} else {
+		/* Strand 0 */
+		ctx->ctxvals_pos = offset;
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+			xf_emit(ctx, 0x385, 0);
+		else
+			xf_emit(ctx, 0x384, 0);
+		nv50_graph_construct_gene_m2mf(ctx);
+		xf_emit(ctx, 0x950, 0);
+		nv50_graph_construct_gene_unk10(ctx);
+		xf_emit(ctx, 1, 0x0fac6881);
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+			xf_emit(ctx, 1, 1);
+			xf_emit(ctx, 3, 0);
+		}
+		nv50_graph_construct_gene_unk8(ctx);
+		if (dev_priv->chipset == 0xa0)
+			xf_emit(ctx, 0x189, 0);
+		else if (dev_priv->chipset < 0xa8)
+			xf_emit(ctx, 0x99, 0);
+		else if (dev_priv->chipset == 0xaa)
+			xf_emit(ctx, 0x65, 0);
+		else
+			xf_emit(ctx, 0x6d, 0);
+		nv50_graph_construct_gene_unk9(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 1 */
+		ctx->ctxvals_pos = offset + 1;
+		nv50_graph_construct_gene_unk1(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 2 */
+		ctx->ctxvals_pos = offset + 2;
+		if (dev_priv->chipset == 0xa0) {
+			nv50_graph_construct_gene_unk2(ctx);
+		}
+		xf_emit(ctx, 0x36, 0);
+		nv50_graph_construct_gene_unk5(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 3 */
+		ctx->ctxvals_pos = offset + 3;
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 1, 1);
+		nv50_graph_construct_gene_unk6(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 4 */
+		ctx->ctxvals_pos = offset + 4;
+		if (dev_priv->chipset == 0xa0)
+			xf_emit(ctx, 0xa80, 0);
+		else
+			xf_emit(ctx, 0xa7a, 0);
+		xf_emit(ctx, 1, 0x3fffff);
+		xf_emit(ctx, 2, 0);
+		xf_emit(ctx, 1, 0x1fff);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 5 */
+		ctx->ctxvals_pos = offset + 5;
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 1, 0x0fac6881);
+		xf_emit(ctx, 0xb, 0);
+		xf_emit(ctx, 2, 0x4e3bfdf);
+		xf_emit(ctx, 3, 0);
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+			xf_emit(ctx, 1, 0x11);
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 2, 0x4e3bfdf);
+		xf_emit(ctx, 2, 0);
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+			xf_emit(ctx, 1, 0x11);
+		xf_emit(ctx, 1, 0);
+		for (i = 0; i < 8; i++)
+			if (units & (1<<(i+16)))
+				nv50_graph_construct_gene_ropc(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 6 */
+		ctx->ctxvals_pos = offset + 6;
+		nv50_graph_construct_gene_unk3(ctx);
+		xf_emit(ctx, 0xb, 0);
+		nv50_graph_construct_gene_unk4(ctx);
+		nv50_graph_construct_gene_unk7(ctx);
+		if (units & (1 << 0))
+			nv50_graph_construct_xfer_tp(ctx);
+		if (units & (1 << 1))
+			nv50_graph_construct_xfer_tp(ctx);
+		if (units & (1 << 2))
+			nv50_graph_construct_xfer_tp(ctx);
+		if (units & (1 << 3))
+			nv50_graph_construct_xfer_tp(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 7 */
+		ctx->ctxvals_pos = offset + 7;
+		if (dev_priv->chipset == 0xa0) {
+			if (units & (1 << 4))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << 5))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << 6))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << 7))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << 8))
+				nv50_graph_construct_xfer_tp(ctx);
+			if (units & (1 << 9))
+				nv50_graph_construct_xfer_tp(ctx);
+		} else {
+			nv50_graph_construct_gene_unk2(ctx);
+		}
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+	}
+
+	ctx->ctxvals_pos = offset + size * 8;
+	ctx->ctxvals_pos = (ctx->ctxvals_pos+0x3f)&~0x3f;
+	cp_lsr (ctx, offset);
+	cp_out (ctx, CP_SET_XFER_POINTER);
+	cp_lsr (ctx, size);
+	cp_out (ctx, CP_SEEK_1);
+	cp_out (ctx, CP_XFER_1);
+	cp_wait(ctx, XFER, BUSY);
+}
+
+/*
+ * non-trivial demagiced parts of ctx init go here
+ */
+
+static void
+nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx)
+{
+	/* m2mf state */
+	xf_emit (ctx, 1, 0);		/* DMA_NOTIFY instance >> 4 */
+	xf_emit (ctx, 1, 0);		/* DMA_BUFFER_IN instance >> 4 */
+	xf_emit (ctx, 1, 0);		/* DMA_BUFFER_OUT instance >> 4 */
+	xf_emit (ctx, 1, 0);		/* OFFSET_IN */
+	xf_emit (ctx, 1, 0);		/* OFFSET_OUT */
+	xf_emit (ctx, 1, 0);		/* PITCH_IN */
+	xf_emit (ctx, 1, 0);		/* PITCH_OUT */
+	xf_emit (ctx, 1, 0);		/* LINE_LENGTH */
+	xf_emit (ctx, 1, 0);		/* LINE_COUNT */
+	xf_emit (ctx, 1, 0x21);		/* FORMAT: bits 0-4 INPUT_INC, bits 5-9 OUTPUT_INC */
+	xf_emit (ctx, 1, 1);		/* LINEAR_IN */
+	xf_emit (ctx, 1, 0x2);		/* TILING_MODE_IN: bits 0-2 y tiling, bits 3-5 z tiling */
+	xf_emit (ctx, 1, 0x100);	/* TILING_PITCH_IN */
+	xf_emit (ctx, 1, 0x100);	/* TILING_HEIGHT_IN */
+	xf_emit (ctx, 1, 1);		/* TILING_DEPTH_IN */
+	xf_emit (ctx, 1, 0);		/* TILING_POSITION_IN_Z */
+	xf_emit (ctx, 1, 0);		/* TILING_POSITION_IN */
+	xf_emit (ctx, 1, 1);		/* LINEAR_OUT */
+	xf_emit (ctx, 1, 0x2);		/* TILING_MODE_OUT: bits 0-2 y tiling, bits 3-5 z tiling */
+	xf_emit (ctx, 1, 0x100);	/* TILING_PITCH_OUT */
+	xf_emit (ctx, 1, 0x100);	/* TILING_HEIGHT_OUT */
+	xf_emit (ctx, 1, 1);		/* TILING_DEPTH_OUT */
+	xf_emit (ctx, 1, 0);		/* TILING_POSITION_OUT_Z */
+	xf_emit (ctx, 1, 0);		/* TILING_POSITION_OUT */
+	xf_emit (ctx, 1, 0);		/* OFFSET_IN_HIGH */
+	xf_emit (ctx, 1, 0);		/* OFFSET_OUT_HIGH */
+}
+
+static void
+nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* end of area 2 on pre-NVA0, area 1 on NVAx */
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x80);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0x80c14);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0x3ff);
+	else
+		xf_emit(ctx, 1, 0x7ff);
+	switch (dev_priv->chipset) {
+	case 0x50:
+	case 0x86:
+	case 0x98:
+	case 0xaa:
+	case 0xac:
+		xf_emit(ctx, 0x542, 0);
+		break;
+	case 0x84:
+	case 0x92:
+	case 0x94:
+	case 0x96:
+		xf_emit(ctx, 0x942, 0);
+		break;
+	case 0xa0:
+		xf_emit(ctx, 0x2042, 0);
+		break;
+	case 0xa5:
+	case 0xa8:
+		xf_emit(ctx, 0x842, 0);
+		break;
+	}
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x80);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x27);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x26);
+	xf_emit(ctx, 3, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk10(struct nouveau_grctx *ctx)
+{
+	/* end of area 2 on pre-NVA0, area 1 on NVAx */
+	xf_emit(ctx, 0x10, 0x04000000);
+	xf_emit(ctx, 0x24, 0);
+	xf_emit(ctx, 2, 0x04e3bfdf);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x1fe21);
+}
+
+static void
+nv50_graph_construct_gene_unk2(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* middle of area 2 on pre-NVA0, beginning of area 2 on NVA0, area 7 on >NVA0 */
+	if (dev_priv->chipset != 0x50) {
+		xf_emit(ctx, 5, 0);
+		xf_emit(ctx, 1, 0x80c14);
+		xf_emit(ctx, 2, 0);
+		xf_emit(ctx, 1, 0x804);
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 2, 4);
+		xf_emit(ctx, 1, 0x8100c12);
+	}
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x10);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 3, 0);
+	else
+		xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x804);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x1a);
+	if (dev_priv->chipset != 0x50)
+		xf_emit(ctx, 1, 0x7f);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x80c14);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 6, 0);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0x3ff);
+	else
+		xf_emit(ctx, 1, 0x7ff);
+	xf_emit(ctx, 1, 0x80c14);
+	xf_emit(ctx, 0x38, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 0x38, 0);
+	xf_emit(ctx, 2, 0x88);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 0x16, 0);
+	xf_emit(ctx, 1, 0x26);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x3f800000);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 4, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x1a);
+	xf_emit(ctx, 1, 0x10);
+	if (dev_priv->chipset != 0x50)
+		xf_emit(ctx, 0x28, 0);
+	else
+		xf_emit(ctx, 0x25, 0);
+	xf_emit(ctx, 1, 0x52);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x26);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x1a);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x00ffff00);
+	xf_emit(ctx, 1, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk3(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* end of area 0 on pre-NVA0, beginning of area 6 on NVAx */
+	xf_emit(ctx, 1, 0x3f);
+	xf_emit(ctx, 0xa, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 0x04000000);
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 4);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 0x10, 0);
+	else
+		xf_emit(ctx, 0x11, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x1001);
+	xf_emit(ctx, 4, 0xffff);
+	xf_emit(ctx, 0x20, 0);
+	xf_emit(ctx, 0x10, 0x3f800000);
+	xf_emit(ctx, 1, 0x10);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0);
+	else
+		xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 2, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk4(struct nouveau_grctx *ctx)
+{
+	/* middle of area 0 on pre-NVA0, middle of area 6 on NVAx */
+	xf_emit(ctx, 2, 0x04000000);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x80);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x80);
+	xf_emit(ctx, 1, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk5(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* middle of area 0 on pre-NVA0 [after m2mf], end of area 2 on NVAx */
+	xf_emit(ctx, 2, 4);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0x1c4d, 0);
+	else
+		xf_emit(ctx, 0x1c4b, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0x8100c12);
+	if (dev_priv->chipset != 0x50)
+		xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x80c14);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0x80c14);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 1, 0x27);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x3c1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x16, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 1, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk6(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* beginning of area 1 on pre-NVA0 [after m2mf], area 3 on NVAx */
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0xf);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 8, 0);
+	else
+		xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x20);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0x11, 0);
+	else if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 0xf, 0);
+	else
+		xf_emit(ctx, 0xe, 0);
+	xf_emit(ctx, 1, 0x1a);
+	xf_emit(ctx, 0xd, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 8);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0x3ff);
+	else
+		xf_emit(ctx, 1, 0x7ff);
+	if (dev_priv->chipset == 0xa8)
+		xf_emit(ctx, 1, 0x1e00);
+	xf_emit(ctx, 0xc, 0);
+	xf_emit(ctx, 1, 0xf);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 0x125, 0);
+	else if (dev_priv->chipset < 0xa0)
+		xf_emit(ctx, 0x126, 0);
+	else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa)
+		xf_emit(ctx, 0x124, 0);
+	else
+		xf_emit(ctx, 0x1f7, 0);
+	xf_emit(ctx, 1, 0xf);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 3, 0);
+	else
+		xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0xa1, 0);
+	else
+		xf_emit(ctx, 0x5a, 0);
+	xf_emit(ctx, 1, 0xf);
+	if (dev_priv->chipset < 0xa0)
+		xf_emit(ctx, 0x834, 0);
+	else if (dev_priv->chipset == 0xa0)
+		xf_emit(ctx, 0x1873, 0);
+	else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0x8ba, 0);
+	else
+		xf_emit(ctx, 0x833, 0);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 0xf, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk7(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* middle of area 1 on pre-NVA0 [after m2mf], middle of area 6 on NVAx */
+	xf_emit(ctx, 2, 0);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 2, 1);
+	else
+		xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0x100);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 8);
+	xf_emit(ctx, 5, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 3, 1);
+	xf_emit(ctx, 1, 0xcf);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 6, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 3, 1);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x15);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x4444480);
+	xf_emit(ctx, 0x37, 0);
+}
+
+static void
+nv50_graph_construct_gene_unk8(struct nouveau_grctx *ctx)
+{
+	/* middle of area 1 on pre-NVA0 [after m2mf], middle of area 0 on NVAx */
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x100);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x10001);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x10001);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x10001);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 2);
+}
+
+static void
+nv50_graph_construct_gene_unk9(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	/* middle of area 2 on pre-NVA0 [after m2mf], end of area 0 on NVAx */
+	xf_emit(ctx, 1, 0x3f800000);
+	xf_emit(ctx, 6, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0x1a);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x12, 0);
+	xf_emit(ctx, 1, 0x00ffff00);
+	xf_emit(ctx, 6, 0);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 0xf, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 2, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 3);
+	else if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 0x04000000);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 5);
+	xf_emit(ctx, 1, 0x52);
+	if (dev_priv->chipset == 0x50) {
+		xf_emit(ctx, 0x13, 0);
+	} else {
+		xf_emit(ctx, 4, 0);
+		xf_emit(ctx, 1, 1);
+		if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+			xf_emit(ctx, 0x11, 0);
+		else
+			xf_emit(ctx, 0x10, 0);
+	}
+	xf_emit(ctx, 0x10, 0x3f800000);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 0x26, 0);
+	xf_emit(ctx, 1, 0x8100c12);
+	xf_emit(ctx, 1, 5);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 4, 0xffff);
+	if (dev_priv->chipset != 0x50)
+		xf_emit(ctx, 1, 3);
+	if (dev_priv->chipset < 0xa0)
+		xf_emit(ctx, 0x1f, 0);
+	else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0xc, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x00ffff00);
+	xf_emit(ctx, 1, 0x1a);
+	if (dev_priv->chipset != 0x50) {
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 1, 3);
+	}
+	if (dev_priv->chipset < 0xa0)
+		xf_emit(ctx, 0x26, 0);
+	else
+		xf_emit(ctx, 0x3c, 0);
+	xf_emit(ctx, 1, 0x102);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 4, 4);
+	if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0x3ff);
+	else
+		xf_emit(ctx, 1, 0x7ff);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x102);
+	xf_emit(ctx, 9, 0);
+	xf_emit(ctx, 4, 4);
+	xf_emit(ctx, 0x2c, 0);
+}
+
+static void
+nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int magic2;
+	if (dev_priv->chipset == 0x50) {
+		magic2 = 0x00003e60;
+	} else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) {
+		magic2 = 0x001ffe67;
+	} else {
+		magic2 = 0x00087e67;
+	}
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, magic2);
+	xf_emit(ctx, 4, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 7, 0);
+	if (dev_priv->chipset >= 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 0x15);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 4, 0);
+	if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa0) {
+		xf_emit(ctx, 1, 4);
+		xf_emit(ctx, 1, 0x400);
+		xf_emit(ctx, 1, 0x300);
+		xf_emit(ctx, 1, 0x1001);
+		if (dev_priv->chipset != 0xa0) {
+			if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+				xf_emit(ctx, 1, 0);
+			else
+				xf_emit(ctx, 1, 0x15);
+		}
+		xf_emit(ctx, 3, 0);
+	}
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x13, 0);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 0x10, 0);
+	xf_emit(ctx, 0x10, 0x3f800000);
+	xf_emit(ctx, 0x19, 0);
+	xf_emit(ctx, 1, 0x10);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x3f);
+	xf_emit(ctx, 6, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset >= 0xa0) {
+		xf_emit(ctx, 2, 0);
+		xf_emit(ctx, 1, 0x1001);
+		xf_emit(ctx, 0xb, 0);
+	} else {
+		xf_emit(ctx, 0xc, 0);
+	}
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x11);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 4, 0);
+	else
+		xf_emit(ctx, 6, 0);
+	xf_emit(ctx, 3, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, magic2);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 0x18, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 8, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 8, 1);
+		xf_emit(ctx, 3, 0);
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 5, 0);
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 0x16, 0);
+	} else {
+		if (dev_priv->chipset >= 0xa0)
+			xf_emit(ctx, 0x1b, 0);
+		else
+			xf_emit(ctx, 0x15, 0);
+	}
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 1);
+	if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 4, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 0x10, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 0x10, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 8, 1);
+		xf_emit(ctx, 3, 0);
+	}
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x5b, 0);
+}
+
+static void
+nv50_graph_construct_xfer_tp_x1(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int magic3;
+	if (dev_priv->chipset == 0x50)
+		magic3 = 0x1000;
+	else if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa8)
+		magic3 = 0x1e00;
+	else
+		magic3 = 0;
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 4);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0x24, 0);
+	else if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 0x14, 0);
+	else
+		xf_emit(ctx, 0x15, 0);
+	xf_emit(ctx, 2, 4);
+	if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 1, 0x03020100);
+	else
+		xf_emit(ctx, 1, 0x00608080);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 2, 4);
+	xf_emit(ctx, 1, 0x80);
+	if (magic3)
+		xf_emit(ctx, 1, magic3);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 0x24, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0x80);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0x03020100);
+	xf_emit(ctx, 1, 3);
+	if (magic3)
+		xf_emit(ctx, 1, magic3);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 4);
+	if (dev_priv->chipset == 0x94 || dev_priv->chipset == 0x96)
+		xf_emit(ctx, 0x1024, 0);
+	else if (dev_priv->chipset < 0xa0)
+		xf_emit(ctx, 0xa24, 0);
+	else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa)
+		xf_emit(ctx, 0x214, 0);
+	else
+		xf_emit(ctx, 0x414, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 2, 0);
+}
+
+static void
+nv50_graph_construct_xfer_tp_x2(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int magic1, magic2;
+	if (dev_priv->chipset == 0x50) {
+		magic1 = 0x3ff;
+		magic2 = 0x00003e60;
+	} else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) {
+		magic1 = 0x7ff;
+		magic2 = 0x001ffe67;
+	} else {
+		magic1 = 0x7ff;
+		magic2 = 0x00087e67;
+	}
+	xf_emit(ctx, 3, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0xc, 0);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 0xb, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 4, 0xffff);
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 5, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 1, 3);
+		xf_emit(ctx, 1, 0);
+	} else if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0xa, 0);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 0x18, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 8, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 8, 1);
+		xf_emit(ctx, 1, 0);
+	}
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 3, 0xcf);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0xa, 0);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 8, 1);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, magic2);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x11);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 2, 1);
+	else
+		xf_emit(ctx, 1, 1);
+	if(dev_priv->chipset == 0x50)
+		xf_emit(ctx, 1, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 5, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, magic1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x28, 0);
+	xf_emit(ctx, 8, 8);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 8, 0x400);
+	xf_emit(ctx, 8, 0x300);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x20);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 0x100);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x40);
+	xf_emit(ctx, 1, 0x100);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 4, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, magic2);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 9, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x400);
+	xf_emit(ctx, 1, 0x300);
+	xf_emit(ctx, 1, 0x1001);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 4, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 1, 0xf);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 0x15, 0);
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 3, 0);
+	} else
+		xf_emit(ctx, 0x17, 0);
+	if (dev_priv->chipset >= 0xa0)
+		xf_emit(ctx, 1, 0x0fac6881);
+	xf_emit(ctx, 1, magic2);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 3, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 2, 1);
+	else
+		xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 2, 0);
+	else if (dev_priv->chipset != 0x50)
+		xf_emit(ctx, 1, 0);
+}
+
+static void
+nv50_graph_construct_xfer_tp_x3(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 2, 0);
+	else
+		xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0x2a712488);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x4085c000);
+	xf_emit(ctx, 1, 0x40);
+	xf_emit(ctx, 1, 0x100);
+	xf_emit(ctx, 1, 0x10100);
+	xf_emit(ctx, 1, 0x02800000);
+}
+
+static void
+nv50_graph_construct_xfer_tp_x4(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	xf_emit(ctx, 2, 0x04e3bfdf);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x00ffff00);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 2, 1);
+	else
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 0x00ffff00);
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0x30201000);
+	xf_emit(ctx, 1, 0x70605040);
+	xf_emit(ctx, 1, 0xb8a89888);
+	xf_emit(ctx, 1, 0xf8e8d8c8);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x1a);
+}
+
+static void
+nv50_graph_construct_xfer_tp_x5(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 0xfac6881);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 2, 0);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 0xb, 0);
+	else
+		xf_emit(ctx, 0xa, 0);
+	xf_emit(ctx, 8, 1);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0xfac6881);
+	xf_emit(ctx, 1, 0xf);
+	xf_emit(ctx, 7, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 1);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 6, 0);
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 6, 0);
+	} else {
+		xf_emit(ctx, 0xb, 0);
+	}
+}
+
+static void
+nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	if (dev_priv->chipset < 0xa0) {
+		nv50_graph_construct_xfer_tp_x1(ctx);
+		nv50_graph_construct_xfer_tp_x2(ctx);
+		nv50_graph_construct_xfer_tp_x3(ctx);
+		if (dev_priv->chipset == 0x50)
+			xf_emit(ctx, 0xf, 0);
+		else
+			xf_emit(ctx, 0x12, 0);
+		nv50_graph_construct_xfer_tp_x4(ctx);
+	} else {
+		nv50_graph_construct_xfer_tp_x3(ctx);
+		if (dev_priv->chipset < 0xaa)
+			xf_emit(ctx, 0xc, 0);
+		else
+			xf_emit(ctx, 0xa, 0);
+		nv50_graph_construct_xfer_tp_x2(ctx);
+		nv50_graph_construct_xfer_tp_x5(ctx);
+		nv50_graph_construct_xfer_tp_x4(ctx);
+		nv50_graph_construct_xfer_tp_x1(ctx);
+	}
+}
+
+static void
+nv50_graph_construct_xfer_tp2(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i, mpcnt;
+	if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa)
+		mpcnt = 1;
+	else if (dev_priv->chipset < 0xa0 || dev_priv->chipset >= 0xa8)
+		mpcnt = 2;
+	else
+		mpcnt = 3;
+	for (i = 0; i < mpcnt; i++) {
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 1, 0x80);
+		xf_emit(ctx, 1, 0x80007004);
+		xf_emit(ctx, 1, 0x04000400);
+		if (dev_priv->chipset >= 0xa0)
+			xf_emit(ctx, 1, 0xc0);
+		xf_emit(ctx, 1, 0x1000);
+		xf_emit(ctx, 2, 0);
+		if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa8) {
+			xf_emit(ctx, 1, 0xe00);
+			xf_emit(ctx, 1, 0x1e00);
+		}
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 2, 0);
+		if (dev_priv->chipset == 0x50)
+			xf_emit(ctx, 2, 0x1000);
+		xf_emit(ctx, 1, 1);
+		xf_emit(ctx, 1, 0);
+		xf_emit(ctx, 1, 4);
+		xf_emit(ctx, 1, 2);
+		if (dev_priv->chipset >= 0xaa)
+			xf_emit(ctx, 0xb, 0);
+		else if (dev_priv->chipset >= 0xa0)
+			xf_emit(ctx, 0xc, 0);
+		else
+			xf_emit(ctx, 0xa, 0);
+	}
+	xf_emit(ctx, 1, 0x08100c12);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset >= 0xa0) {
+		xf_emit(ctx, 1, 0x1fe21);
+	}
+	xf_emit(ctx, 5, 0);
+	xf_emit(ctx, 4, 0xffff);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 2, 0x10001);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 0x1fe21);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 4, 0);
+	xf_emit(ctx, 1, 0x08100c12);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 8, 0);
+	xf_emit(ctx, 1, 0xfac6881);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa)
+		xf_emit(ctx, 1, 3);
+	xf_emit(ctx, 3, 0);
+	xf_emit(ctx, 1, 4);
+	xf_emit(ctx, 9, 0);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 2, 1);
+	xf_emit(ctx, 1, 2);
+	xf_emit(ctx, 3, 1);
+	xf_emit(ctx, 1, 0);
+	if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) {
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 0x10, 1);
+		xf_emit(ctx, 8, 2);
+		xf_emit(ctx, 0x18, 1);
+		xf_emit(ctx, 3, 0);
+	}
+	xf_emit(ctx, 1, 4);
+	if (dev_priv->chipset == 0x50)
+		xf_emit(ctx, 0x3a0, 0);
+	else if (dev_priv->chipset < 0x94)
+		xf_emit(ctx, 0x3a2, 0);
+	else if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa)
+		xf_emit(ctx, 0x39f, 0);
+	else
+		xf_emit(ctx, 0x3a3, 0);
+	xf_emit(ctx, 1, 0x11);
+	xf_emit(ctx, 1, 0);
+	xf_emit(ctx, 1, 1);
+	xf_emit(ctx, 0x2d, 0);
+}
+
+static void
+nv50_graph_construct_xfer2(struct nouveau_grctx *ctx)
+{
+	struct drm_nouveau_private *dev_priv = ctx->dev->dev_private;
+	int i;
+	uint32_t offset;
+	uint32_t units = nv_rd32 (ctx->dev, 0x1540);
+	int size = 0;
+
+	offset = (ctx->ctxvals_pos+0x3f)&~0x3f;
+
+	if (dev_priv->chipset < 0xa0) {
+		for (i = 0; i < 8; i++) {
+			ctx->ctxvals_pos = offset + i;
+			if (i == 0)
+				xf_emit(ctx, 1, 0x08100c12);
+			if (units & (1 << i))
+				nv50_graph_construct_xfer_tp2(ctx);
+			if ((ctx->ctxvals_pos-offset)/8 > size)
+				size = (ctx->ctxvals_pos-offset)/8;
+		}
+	} else {
+		/* Strand 0: TPs 0, 1 */
+		ctx->ctxvals_pos = offset;
+		xf_emit(ctx, 1, 0x08100c12);
+		if (units & (1 << 0))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 1))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 0: TPs 2, 3 */
+		ctx->ctxvals_pos = offset + 1;
+		if (units & (1 << 2))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 3))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 0: TPs 4, 5, 6 */
+		ctx->ctxvals_pos = offset + 2;
+		if (units & (1 << 4))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 5))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 6))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+
+		/* Strand 0: TPs 7, 8, 9 */
+		ctx->ctxvals_pos = offset + 3;
+		if (units & (1 << 7))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 8))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if (units & (1 << 9))
+			nv50_graph_construct_xfer_tp2(ctx);
+		if ((ctx->ctxvals_pos-offset)/8 > size)
+			size = (ctx->ctxvals_pos-offset)/8;
+	}
+	ctx->ctxvals_pos = offset + size * 8;
+	ctx->ctxvals_pos = (ctx->ctxvals_pos+0x3f)&~0x3f;
+	cp_lsr (ctx, offset);
+	cp_out (ctx, CP_SET_XFER_POINTER);
+	cp_lsr (ctx, size);
+	cp_out (ctx, CP_SEEK_2);
+	cp_out (ctx, CP_XFER_2);
+	cp_wait(ctx, XFER, BUSY);
+}
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c
index f0dc4e3..de1f5b0 100644
--- a/drivers/gpu/drm/nouveau/nv50_instmem.c
+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c
@@ -390,7 +390,7 @@
 	if (gpuobj->im_backing)
 		return -EINVAL;
 
-	*sz = (*sz + (NV50_INSTMEM_PAGE_SIZE-1)) & ~(NV50_INSTMEM_PAGE_SIZE-1);
+	*sz = ALIGN(*sz, NV50_INSTMEM_PAGE_SIZE);
 	if (*sz == 0)
 		return -EINVAL;
 
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index 1cc7b93..ed38262 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -30,6 +30,9 @@
 $(obj)/rs600_reg_safe.h: $(src)/reg_srcs/rs600 $(obj)/mkregtable
 	$(call if_changed,mkregtable)
 
+$(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable
+	$(call if_changed,mkregtable)
+
 $(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h
 
 $(obj)/r200.o: $(obj)/r200_reg_safe.h
@@ -42,6 +45,8 @@
 
 $(obj)/rs600.o: $(obj)/rs600_reg_safe.h
 
+$(obj)/r600_cs.o: $(obj)/r600_reg_safe.h
+
 radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
 	radeon_irq.o r300_cmdbuf.o r600_cp.o
 # add KMS driver
@@ -54,8 +59,10 @@
 	radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
 	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
 	r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
-	r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o
+	r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
+	evergreen.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
+radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
 
 obj-$(CONFIG_DRM_RADEON)+= radeon.o
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c
index 7f152f6..d75788f 100644
--- a/drivers/gpu/drm/radeon/atom.c
+++ b/drivers/gpu/drm/radeon/atom.c
@@ -881,8 +881,6 @@
 	uint8_t attr = U8((*ptr)++), shift;
 	uint32_t saved, dst;
 	int dptr = *ptr;
-	attr &= 0x38;
-	attr |= atom_def_dst[attr >> 3] << 6;
 	SDEBUG("   dst: ");
 	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
 	shift = atom_get_src(ctx, attr, ptr);
@@ -897,8 +895,6 @@
 	uint8_t attr = U8((*ptr)++), shift;
 	uint32_t saved, dst;
 	int dptr = *ptr;
-	attr &= 0x38;
-	attr |= atom_def_dst[attr >> 3] << 6;
 	SDEBUG("   dst: ");
 	dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1);
 	shift = atom_get_src(ctx, attr, ptr);
diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h
index 91ad0d1..6732b5d 100644
--- a/drivers/gpu/drm/radeon/atombios.h
+++ b/drivers/gpu/drm/radeon/atombios.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2007 Advanced Micro Devices, Inc.
+ * Copyright 2006-2007 Advanced Micro Devices, Inc.  
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -20,10 +20,12 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/****************************************************************************/
+
+/****************************************************************************/	
 /*Portion I: Definitions  shared between VBIOS and Driver                   */
 /****************************************************************************/
 
+
 #ifndef _ATOMBIOS_H
 #define _ATOMBIOS_H
 
@@ -40,39 +42,46 @@
 #endif
 
 #ifdef _H2INC
-#ifndef ULONG
-typedef unsigned long ULONG;
-#endif
+  #ifndef ULONG 
+    typedef unsigned long ULONG;
+  #endif
 
-#ifndef UCHAR
-typedef unsigned char UCHAR;
-#endif
+  #ifndef UCHAR
+    typedef unsigned char UCHAR;
+  #endif
 
-#ifndef USHORT
-typedef unsigned short USHORT;
+  #ifndef USHORT 
+    typedef unsigned short USHORT;
+  #endif
 #endif
-#endif
-
-#define ATOM_DAC_A            0
+      
+#define ATOM_DAC_A            0 
 #define ATOM_DAC_B            1
 #define ATOM_EXT_DAC          2
 
 #define ATOM_CRTC1            0
 #define ATOM_CRTC2            1
+#define ATOM_CRTC3            2
+#define ATOM_CRTC4            3
+#define ATOM_CRTC5            4
+#define ATOM_CRTC6            5
+#define ATOM_CRTC_INVALID     0xFF
 
 #define ATOM_DIGA             0
 #define ATOM_DIGB             1
 
 #define ATOM_PPLL1            0
 #define ATOM_PPLL2            1
+#define ATOM_DCPLL            2
+#define ATOM_PPLL_INVALID     0xFF
 
 #define ATOM_SCALER1          0
 #define ATOM_SCALER2          1
 
-#define ATOM_SCALER_DISABLE   0
-#define ATOM_SCALER_CENTER    1
-#define ATOM_SCALER_EXPANSION 2
-#define ATOM_SCALER_MULTI_EX  3
+#define ATOM_SCALER_DISABLE   0   
+#define ATOM_SCALER_CENTER    1   
+#define ATOM_SCALER_EXPANSION 2   
+#define ATOM_SCALER_MULTI_EX  3   
 
 #define ATOM_DISABLE          0
 #define ATOM_ENABLE           1
@@ -82,6 +91,7 @@
 #define ATOM_LCD_SELFTEST_START									(ATOM_DISABLE+5)
 #define ATOM_LCD_SELFTEST_STOP									(ATOM_ENABLE+5)
 #define ATOM_ENCODER_INIT			                  (ATOM_DISABLE+7)
+#define ATOM_GET_STATUS                         (ATOM_DISABLE+8)
 
 #define ATOM_BLANKING         1
 #define ATOM_BLANKING_OFF     0
@@ -114,7 +124,7 @@
 #define ATOM_DAC2_CV          ATOM_DAC1_CV
 #define ATOM_DAC2_NTSC        ATOM_DAC1_NTSC
 #define ATOM_DAC2_PAL         ATOM_DAC1_PAL
-
+ 
 #define ATOM_PM_ON            0
 #define ATOM_PM_STANDBY       1
 #define ATOM_PM_SUSPEND       2
@@ -134,6 +144,7 @@
 #define ATOM_PANEL_MISC_TEMPORAL           0x00000040
 #define ATOM_PANEL_MISC_API_ENABLED        0x00000080
 
+
 #define MEMTYPE_DDR1              "DDR1"
 #define MEMTYPE_DDR2              "DDR2"
 #define MEMTYPE_DDR3              "DDR3"
@@ -145,19 +156,19 @@
 
 /* Maximum size of that FireGL flag string */
 
-#define ATOM_FIREGL_FLAG_STRING     "FGL"	/* Flag used to enable FireGL Support */
-#define ATOM_MAX_SIZE_OF_FIREGL_FLAG_STRING  3	/* sizeof( ATOM_FIREGL_FLAG_STRING ) */
+#define ATOM_FIREGL_FLAG_STRING     "FGL"             //Flag used to enable FireGL Support
+#define ATOM_MAX_SIZE_OF_FIREGL_FLAG_STRING  3        //sizeof( ATOM_FIREGL_FLAG_STRING )
 
-#define ATOM_FAKE_DESKTOP_STRING    "DSK"	/* Flag used to enable mobile ASIC on Desktop */
-#define ATOM_MAX_SIZE_OF_FAKE_DESKTOP_STRING  ATOM_MAX_SIZE_OF_FIREGL_FLAG_STRING
+#define ATOM_FAKE_DESKTOP_STRING    "DSK"             //Flag used to enable mobile ASIC on Desktop
+#define ATOM_MAX_SIZE_OF_FAKE_DESKTOP_STRING  ATOM_MAX_SIZE_OF_FIREGL_FLAG_STRING 
 
-#define ATOM_M54T_FLAG_STRING       "M54T"	/* Flag used to enable M54T Support */
-#define ATOM_MAX_SIZE_OF_M54T_FLAG_STRING    4	/* sizeof( ATOM_M54T_FLAG_STRING ) */
+#define ATOM_M54T_FLAG_STRING       "M54T"            //Flag used to enable M54T Support
+#define ATOM_MAX_SIZE_OF_M54T_FLAG_STRING    4        //sizeof( ATOM_M54T_FLAG_STRING )
 
 #define HW_ASSISTED_I2C_STATUS_FAILURE          2
 #define HW_ASSISTED_I2C_STATUS_SUCCESS          1
 
-#pragma pack(1)			/* BIOS data must use byte aligment */
+#pragma pack(1)                                       /* BIOS data must use byte aligment */
 
 /*  Define offset to location of ROM header. */
 
@@ -165,367 +176,410 @@
 #define OFFSET_TO_ATOM_ROM_IMAGE_SIZE				    0x00000002L
 
 #define OFFSET_TO_ATOMBIOS_ASIC_BUS_MEM_TYPE    0x94
-#define MAXSIZE_OF_ATOMBIOS_ASIC_BUS_MEM_TYPE   20	/* including the terminator 0x0! */
+#define MAXSIZE_OF_ATOMBIOS_ASIC_BUS_MEM_TYPE   20    /* including the terminator 0x0! */
 #define	OFFSET_TO_GET_ATOMBIOS_STRINGS_NUMBER		0x002f
 #define	OFFSET_TO_GET_ATOMBIOS_STRINGS_START		0x006e
 
 /* Common header for all ROM Data tables.
-  Every table pointed  _ATOM_MASTER_DATA_TABLE has this common header.
+  Every table pointed  _ATOM_MASTER_DATA_TABLE has this common header. 
   And the pointer actually points to this header. */
 
-typedef struct _ATOM_COMMON_TABLE_HEADER {
-	USHORT usStructureSize;
-	UCHAR ucTableFormatRevision;	/*Change it when the Parser is not backward compatible */
-	UCHAR ucTableContentRevision;	/*Change it only when the table needs to change but the firmware */
-	/*Image can't be updated, while Driver needs to carry the new table! */
-} ATOM_COMMON_TABLE_HEADER;
+typedef struct _ATOM_COMMON_TABLE_HEADER
+{
+  USHORT usStructureSize;
+  UCHAR  ucTableFormatRevision;   /*Change it when the Parser is not backward compatible */
+  UCHAR  ucTableContentRevision;  /*Change it only when the table needs to change but the firmware */
+                                  /*Image can't be updated, while Driver needs to carry the new table! */
+}ATOM_COMMON_TABLE_HEADER;
 
-typedef struct _ATOM_ROM_HEADER {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR uaFirmWareSignature[4];	/*Signature to distinguish between Atombios and non-atombios,
-					   atombios should init it as "ATOM", don't change the position */
-	USHORT usBiosRuntimeSegmentAddress;
-	USHORT usProtectedModeInfoOffset;
-	USHORT usConfigFilenameOffset;
-	USHORT usCRC_BlockOffset;
-	USHORT usBIOS_BootupMessageOffset;
-	USHORT usInt10Offset;
-	USHORT usPciBusDevInitCode;
-	USHORT usIoBaseAddress;
-	USHORT usSubsystemVendorID;
-	USHORT usSubsystemID;
-	USHORT usPCI_InfoOffset;
-	USHORT usMasterCommandTableOffset;	/*Offset for SW to get all command table offsets, Don't change the position */
-	USHORT usMasterDataTableOffset;	/*Offset for SW to get all data table offsets, Don't change the position */
-	UCHAR ucExtendedFunctionCode;
-	UCHAR ucReserved;
-} ATOM_ROM_HEADER;
+typedef struct _ATOM_ROM_HEADER
+{
+  ATOM_COMMON_TABLE_HEADER		sHeader;
+  UCHAR	 uaFirmWareSignature[4];    /*Signature to distinguish between Atombios and non-atombios, 
+                                      atombios should init it as "ATOM", don't change the position */
+  USHORT usBiosRuntimeSegmentAddress;
+  USHORT usProtectedModeInfoOffset;
+  USHORT usConfigFilenameOffset;
+  USHORT usCRC_BlockOffset;
+  USHORT usBIOS_BootupMessageOffset;
+  USHORT usInt10Offset;
+  USHORT usPciBusDevInitCode;
+  USHORT usIoBaseAddress;
+  USHORT usSubsystemVendorID;
+  USHORT usSubsystemID;
+  USHORT usPCI_InfoOffset; 
+  USHORT usMasterCommandTableOffset; /*Offset for SW to get all command table offsets, Don't change the position */
+  USHORT usMasterDataTableOffset;   /*Offset for SW to get all data table offsets, Don't change the position */
+  UCHAR  ucExtendedFunctionCode;
+  UCHAR  ucReserved;
+}ATOM_ROM_HEADER;
 
 /*==============================Command Table Portion==================================== */
 
 #ifdef	UEFI_BUILD
-#define	UTEMP	USHORT
-#define	USHORT	void*
+	#define	UTEMP	USHORT
+	#define	USHORT	void*
 #endif
 
-typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES {
-	USHORT ASIC_Init;	/* Function Table, used by various SW components,latest version 1.1 */
-	USHORT GetDisplaySurfaceSize;	/* Atomic Table,  Used by Bios when enabling HW ICON */
-	USHORT ASIC_RegistersInit;	/* Atomic Table,  indirectly used by various SW components,called from ASIC_Init */
-	USHORT VRAM_BlockVenderDetection;	/* Atomic Table,  used only by Bios */
-	USHORT DIGxEncoderControl;	/* Only used by Bios */
-	USHORT MemoryControllerInit;	/* Atomic Table,  indirectly used by various SW components,called from ASIC_Init */
-	USHORT EnableCRTCMemReq;	/* Function Table,directly used by various SW components,latest version 2.1 */
-	USHORT MemoryParamAdjust;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock if needed */
-	USHORT DVOEncoderControl;	/* Function Table,directly used by various SW components,latest version 1.2 */
-	USHORT GPIOPinControl;	/* Atomic Table,  only used by Bios */
-	USHORT SetEngineClock;	/*Function Table,directly used by various SW components,latest version 1.1 */
-	USHORT SetMemoryClock;	/* Function Table,directly used by various SW components,latest version 1.1 */
-	USHORT SetPixelClock;	/*Function Table,directly used by various SW components,latest version 1.2 */
-	USHORT DynamicClockGating;	/* Atomic Table,  indirectly used by various SW components,called from ASIC_Init */
-	USHORT ResetMemoryDLL;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
-	USHORT ResetMemoryDevice;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
-	USHORT MemoryPLLInit;
-	USHORT AdjustDisplayPll;	/* only used by Bios */
-	USHORT AdjustMemoryController;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
-	USHORT EnableASIC_StaticPwrMgt;	/* Atomic Table,  only used by Bios */
-	USHORT ASIC_StaticPwrMgtStatusChange;	/* Obsolete, only used by Bios */
-	USHORT DAC_LoadDetection;	/* Atomic Table,  directly used by various SW components,latest version 1.2 */
-	USHORT LVTMAEncoderControl;	/* Atomic Table,directly used by various SW components,latest version 1.3 */
-	USHORT LCD1OutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT DAC1EncoderControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT DAC2EncoderControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT DVOOutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT CV1OutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT GetConditionalGoldenSetting;	/* only used by Bios */
-	USHORT TVEncoderControl;	/* Function Table,directly used by various SW components,latest version 1.1 */
-	USHORT TMDSAEncoderControl;	/* Atomic Table,  directly used by various SW components,latest version 1.3 */
-	USHORT LVDSEncoderControl;	/* Atomic Table,  directly used by various SW components,latest version 1.3 */
-	USHORT TV1OutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT EnableScaler;	/* Atomic Table,  used only by Bios */
-	USHORT BlankCRTC;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT EnableCRTC;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT GetPixelClock;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT EnableVGA_Render;	/* Function Table,directly used by various SW components,latest version 1.1 */
-	USHORT EnableVGA_Access;	/* Obsolete ,     only used by Bios */
-	USHORT SetCRTC_Timing;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT SetCRTC_OverScan;	/* Atomic Table,  used by various SW components,latest version 1.1 */
-	USHORT SetCRTC_Replication;	/* Atomic Table,  used only by Bios */
-	USHORT SelectCRTC_Source;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT EnableGraphSurfaces;	/* Atomic Table,  used only by Bios */
-	USHORT UpdateCRTC_DoubleBufferRegisters;
-	USHORT LUT_AutoFill;	/* Atomic Table,  only used by Bios */
-	USHORT EnableHW_IconCursor;	/* Atomic Table,  only used by Bios */
-	USHORT GetMemoryClock;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT GetEngineClock;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT SetCRTC_UsingDTDTiming;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT ExternalEncoderControl;	/* Atomic Table,  directly used by various SW components,latest version 2.1 */
-	USHORT LVTMAOutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT VRAM_BlockDetectionByStrap;	/* Atomic Table,  used only by Bios */
-	USHORT MemoryCleanUp;	/* Atomic Table,  only used by Bios */
-	USHORT ProcessI2cChannelTransaction;	/* Function Table,only used by Bios */
-	USHORT WriteOneByteToHWAssistedI2C;	/* Function Table,indirectly used by various SW components */
-	USHORT ReadHWAssistedI2CStatus;	/* Atomic Table,  indirectly used by various SW components */
-	USHORT SpeedFanControl;	/* Function Table,indirectly used by various SW components,called from ASIC_Init */
-	USHORT PowerConnectorDetection;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT MC_Synchronization;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
-	USHORT ComputeMemoryEnginePLL;	/* Atomic Table,  indirectly used by various SW components,called from SetMemory/EngineClock */
-	USHORT MemoryRefreshConversion;	/* Atomic Table,  indirectly used by various SW components,called from SetMemory or SetEngineClock */
-	USHORT VRAM_GetCurrentInfoBlock;	/* Atomic Table,  used only by Bios */
-	USHORT DynamicMemorySettings;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
-	USHORT MemoryTraining;	/* Atomic Table,  used only by Bios */
-	USHORT EnableSpreadSpectrumOnPPLL;	/* Atomic Table,  directly used by various SW components,latest version 1.2 */
-	USHORT TMDSAOutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT SetVoltage;	/* Function Table,directly and/or indirectly used by various SW components,latest version 1.1 */
-	USHORT DAC1OutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT DAC2OutputControl;	/* Atomic Table,  directly used by various SW components,latest version 1.1 */
-	USHORT SetupHWAssistedI2CStatus;	/* Function Table,only used by Bios, obsolete soon.Switch to use "ReadEDIDFromHWAssistedI2C" */
-	USHORT ClockSource;	/* Atomic Table,  indirectly used by various SW components,called from ASIC_Init */
-	USHORT MemoryDeviceInit;	/* Atomic Table,  indirectly used by various SW components,called from SetMemoryClock */
-	USHORT EnableYUV;	/* Atomic Table,  indirectly used by various SW components,called from EnableVGARender */
-	USHORT DIG1EncoderControl;	/* Atomic Table,directly used by various SW components,latest version 1.1 */
-	USHORT DIG2EncoderControl;	/* Atomic Table,directly used by various SW components,latest version 1.1 */
-	USHORT DIG1TransmitterControl;	/* Atomic Table,directly used by various SW components,latest version 1.1 */
-	USHORT DIG2TransmitterControl;	/* Atomic Table,directly used by various SW components,latest version 1.1 */
-	USHORT ProcessAuxChannelTransaction;	/* Function Table,only used by Bios */
-	USHORT DPEncoderService;	/* Function Table,only used by Bios */
-} ATOM_MASTER_LIST_OF_COMMAND_TABLES;
+typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{
+  USHORT ASIC_Init;                              //Function Table, used by various SW components,latest version 1.1
+  USHORT GetDisplaySurfaceSize;                  //Atomic Table,  Used by Bios when enabling HW ICON
+  USHORT ASIC_RegistersInit;                     //Atomic Table,  indirectly used by various SW components,called from ASIC_Init
+  USHORT VRAM_BlockVenderDetection;              //Atomic Table,  used only by Bios
+  USHORT DIGxEncoderControl;										 //Only used by Bios
+  USHORT MemoryControllerInit;                   //Atomic Table,  indirectly used by various SW components,called from ASIC_Init
+  USHORT EnableCRTCMemReq;                       //Function Table,directly used by various SW components,latest version 2.1
+  USHORT MemoryParamAdjust; 										 //Atomic Table,  indirectly used by various SW components,called from SetMemoryClock if needed
+  USHORT DVOEncoderControl;                      //Function Table,directly used by various SW components,latest version 1.2
+  USHORT GPIOPinControl;												 //Atomic Table,  only used by Bios
+  USHORT SetEngineClock;                         //Function Table,directly used by various SW components,latest version 1.1
+  USHORT SetMemoryClock;                         //Function Table,directly used by various SW components,latest version 1.1
+  USHORT SetPixelClock;                          //Function Table,directly used by various SW components,latest version 1.2  
+  USHORT DynamicClockGating;                     //Atomic Table,  indirectly used by various SW components,called from ASIC_Init
+  USHORT ResetMemoryDLL;                         //Atomic Table,  indirectly used by various SW components,called from SetMemoryClock
+  USHORT ResetMemoryDevice;                      //Atomic Table,  indirectly used by various SW components,called from SetMemoryClock
+  USHORT MemoryPLLInit;
+  USHORT AdjustDisplayPll;												//only used by Bios
+  USHORT AdjustMemoryController;                 //Atomic Table,  indirectly used by various SW components,called from SetMemoryClock                
+  USHORT EnableASIC_StaticPwrMgt;                //Atomic Table,  only used by Bios
+  USHORT ASIC_StaticPwrMgtStatusChange;          //Obsolete ,     only used by Bios   
+  USHORT DAC_LoadDetection;                      //Atomic Table,  directly used by various SW components,latest version 1.2  
+  USHORT LVTMAEncoderControl;                    //Atomic Table,directly used by various SW components,latest version 1.3
+  USHORT LCD1OutputControl;                      //Atomic Table,  directly used by various SW components,latest version 1.1 
+  USHORT DAC1EncoderControl;                     //Atomic Table,  directly used by various SW components,latest version 1.1  
+  USHORT DAC2EncoderControl;                     //Atomic Table,  directly used by various SW components,latest version 1.1 
+  USHORT DVOOutputControl;                       //Atomic Table,  directly used by various SW components,latest version 1.1 
+  USHORT CV1OutputControl;                       //Atomic Table,  Atomic Table,  Obsolete from Ry6xx, use DAC2 Output instead 
+  USHORT GetConditionalGoldenSetting;            //only used by Bios
+  USHORT TVEncoderControl;                       //Function Table,directly used by various SW components,latest version 1.1
+  USHORT TMDSAEncoderControl;                    //Atomic Table,  directly used by various SW components,latest version 1.3
+  USHORT LVDSEncoderControl;                     //Atomic Table,  directly used by various SW components,latest version 1.3
+  USHORT TV1OutputControl;                       //Atomic Table,  Obsolete from Ry6xx, use DAC2 Output instead
+  USHORT EnableScaler;                           //Atomic Table,  used only by Bios
+  USHORT BlankCRTC;                              //Atomic Table,  directly used by various SW components,latest version 1.1 
+  USHORT EnableCRTC;                             //Atomic Table,  directly used by various SW components,latest version 1.1 
+  USHORT GetPixelClock;                          //Atomic Table,  directly used by various SW components,latest version 1.1 
+  USHORT EnableVGA_Render;                       //Function Table,directly used by various SW components,latest version 1.1
+  USHORT GetSCLKOverMCLKRatio;                   //Atomic Table,  only used by Bios
+  USHORT SetCRTC_Timing;                         //Atomic Table,  directly used by various SW components,latest version 1.1
+  USHORT SetCRTC_OverScan;                       //Atomic Table,  used by various SW components,latest version 1.1 
+  USHORT SetCRTC_Replication;                    //Atomic Table,  used only by Bios
+  USHORT SelectCRTC_Source;                      //Atomic Table,  directly used by various SW components,latest version 1.1 
+  USHORT EnableGraphSurfaces;                    //Atomic Table,  used only by Bios
+  USHORT UpdateCRTC_DoubleBufferRegisters;
+  USHORT LUT_AutoFill;                           //Atomic Table,  only used by Bios
+  USHORT EnableHW_IconCursor;                    //Atomic Table,  only used by Bios
+  USHORT GetMemoryClock;                         //Atomic Table,  directly used by various SW components,latest version 1.1 
+  USHORT GetEngineClock;                         //Atomic Table,  directly used by various SW components,latest version 1.1 
+  USHORT SetCRTC_UsingDTDTiming;                 //Atomic Table,  directly used by various SW components,latest version 1.1
+  USHORT ExternalEncoderControl;                 //Atomic Table,  directly used by various SW components,latest version 2.1
+  USHORT LVTMAOutputControl;                     //Atomic Table,  directly used by various SW components,latest version 1.1
+  USHORT VRAM_BlockDetectionByStrap;             //Atomic Table,  used only by Bios
+  USHORT MemoryCleanUp;                          //Atomic Table,  only used by Bios    
+  USHORT ProcessI2cChannelTransaction;           //Function Table,only used by Bios
+  USHORT WriteOneByteToHWAssistedI2C;            //Function Table,indirectly used by various SW components 
+  USHORT ReadHWAssistedI2CStatus;                //Atomic Table,  indirectly used by various SW components
+  USHORT SpeedFanControl;                        //Function Table,indirectly used by various SW components,called from ASIC_Init
+  USHORT PowerConnectorDetection;                //Atomic Table,  directly used by various SW components,latest version 1.1
+  USHORT MC_Synchronization;                     //Atomic Table,  indirectly used by various SW components,called from SetMemoryClock
+  USHORT ComputeMemoryEnginePLL;                 //Atomic Table,  indirectly used by various SW components,called from SetMemory/EngineClock
+  USHORT MemoryRefreshConversion;                //Atomic Table,  indirectly used by various SW components,called from SetMemory or SetEngineClock
+  USHORT VRAM_GetCurrentInfoBlock;               //Atomic Table,  used only by Bios
+  USHORT DynamicMemorySettings;                  //Atomic Table,  indirectly used by various SW components,called from SetMemoryClock
+  USHORT MemoryTraining;                         //Atomic Table,  used only by Bios
+  USHORT EnableSpreadSpectrumOnPPLL;             //Atomic Table,  directly used by various SW components,latest version 1.2
+  USHORT TMDSAOutputControl;                     //Atomic Table,  directly used by various SW components,latest version 1.1
+  USHORT SetVoltage;                             //Function Table,directly and/or indirectly used by various SW components,latest version 1.1
+  USHORT DAC1OutputControl;                      //Atomic Table,  directly used by various SW components,latest version 1.1
+  USHORT DAC2OutputControl;                      //Atomic Table,  directly used by various SW components,latest version 1.1
+  USHORT SetupHWAssistedI2CStatus;               //Function Table,only used by Bios, obsolete soon.Switch to use "ReadEDIDFromHWAssistedI2C"
+  USHORT ClockSource;                            //Atomic Table,  indirectly used by various SW components,called from ASIC_Init
+  USHORT MemoryDeviceInit;                       //Atomic Table,  indirectly used by various SW components,called from SetMemoryClock
+  USHORT EnableYUV;                              //Atomic Table,  indirectly used by various SW components,called from EnableVGARender
+  USHORT DIG1EncoderControl;                     //Atomic Table,directly used by various SW components,latest version 1.1
+  USHORT DIG2EncoderControl;                     //Atomic Table,directly used by various SW components,latest version 1.1
+  USHORT DIG1TransmitterControl;                 //Atomic Table,directly used by various SW components,latest version 1.1
+  USHORT DIG2TransmitterControl;	               //Atomic Table,directly used by various SW components,latest version 1.1 
+  USHORT ProcessAuxChannelTransaction;					 //Function Table,only used by Bios
+  USHORT DPEncoderService;											 //Function Table,only used by Bios
+}ATOM_MASTER_LIST_OF_COMMAND_TABLES;   
 
-/*  For backward compatible */
+// For backward compatible 
 #define ReadEDIDFromHWAssistedI2C                ProcessI2cChannelTransaction
 #define UNIPHYTransmitterControl						     DIG1TransmitterControl
 #define LVTMATransmitterControl							     DIG2TransmitterControl
 #define SetCRTC_DPM_State                        GetConditionalGoldenSetting
 #define SetUniphyInstance                        ASIC_StaticPwrMgtStatusChange
+#define HPDInterruptService                      ReadHWAssistedI2CStatus
+#define EnableVGA_Access                         GetSCLKOverMCLKRatio
 
-typedef struct _ATOM_MASTER_COMMAND_TABLE {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_MASTER_LIST_OF_COMMAND_TABLES ListOfCommandTables;
-} ATOM_MASTER_COMMAND_TABLE;
+typedef struct _ATOM_MASTER_COMMAND_TABLE
+{
+  ATOM_COMMON_TABLE_HEADER           sHeader;
+  ATOM_MASTER_LIST_OF_COMMAND_TABLES ListOfCommandTables;
+}ATOM_MASTER_COMMAND_TABLE;
 
-/****************************************************************************/
-/*  Structures used in every command table */
-/****************************************************************************/
-typedef struct _ATOM_TABLE_ATTRIBUTE {
+/****************************************************************************/	
+// Structures used in every command table
+/****************************************************************************/	
+typedef struct _ATOM_TABLE_ATTRIBUTE
+{
 #if ATOM_BIG_ENDIAN
-	USHORT UpdatedByUtility:1;	/* [15]=Table updated by utility flag */
-	USHORT PS_SizeInBytes:7;	/* [14:8]=Size of parameter space in Bytes (multiple of a dword), */
-	USHORT WS_SizeInBytes:8;	/* [7:0]=Size of workspace in Bytes (in multiple of a dword), */
+  USHORT  UpdatedByUtility:1;         //[15]=Table updated by utility flag
+  USHORT  PS_SizeInBytes:7;           //[14:8]=Size of parameter space in Bytes (multiple of a dword), 
+  USHORT  WS_SizeInBytes:8;           //[7:0]=Size of workspace in Bytes (in multiple of a dword), 
 #else
-	USHORT WS_SizeInBytes:8;	/* [7:0]=Size of workspace in Bytes (in multiple of a dword), */
-	USHORT PS_SizeInBytes:7;	/* [14:8]=Size of parameter space in Bytes (multiple of a dword), */
-	USHORT UpdatedByUtility:1;	/* [15]=Table updated by utility flag */
+  USHORT  WS_SizeInBytes:8;           //[7:0]=Size of workspace in Bytes (in multiple of a dword), 
+  USHORT  PS_SizeInBytes:7;           //[14:8]=Size of parameter space in Bytes (multiple of a dword), 
+  USHORT  UpdatedByUtility:1;         //[15]=Table updated by utility flag
 #endif
-} ATOM_TABLE_ATTRIBUTE;
+}ATOM_TABLE_ATTRIBUTE;
 
-typedef union _ATOM_TABLE_ATTRIBUTE_ACCESS {
-	ATOM_TABLE_ATTRIBUTE sbfAccess;
-	USHORT susAccess;
-} ATOM_TABLE_ATTRIBUTE_ACCESS;
+typedef union _ATOM_TABLE_ATTRIBUTE_ACCESS
+{
+  ATOM_TABLE_ATTRIBUTE sbfAccess;
+  USHORT               susAccess;
+}ATOM_TABLE_ATTRIBUTE_ACCESS;
 
-/****************************************************************************/
-/*  Common header for all command tables. */
-/*  Every table pointed by _ATOM_MASTER_COMMAND_TABLE has this common header. */
-/*  And the pointer actually points to this header. */
-/****************************************************************************/
-typedef struct _ATOM_COMMON_ROM_COMMAND_TABLE_HEADER {
-	ATOM_COMMON_TABLE_HEADER CommonHeader;
-	ATOM_TABLE_ATTRIBUTE TableAttribute;
-} ATOM_COMMON_ROM_COMMAND_TABLE_HEADER;
+/****************************************************************************/	
+// Common header for all command tables.
+// Every table pointed by _ATOM_MASTER_COMMAND_TABLE has this common header. 
+// And the pointer actually points to this header.
+/****************************************************************************/	
+typedef struct _ATOM_COMMON_ROM_COMMAND_TABLE_HEADER
+{
+  ATOM_COMMON_TABLE_HEADER CommonHeader;
+  ATOM_TABLE_ATTRIBUTE     TableAttribute;	
+}ATOM_COMMON_ROM_COMMAND_TABLE_HEADER;
 
-/****************************************************************************/
-/*  Structures used by ComputeMemoryEnginePLLTable */
-/****************************************************************************/
+/****************************************************************************/	
+// Structures used by ComputeMemoryEnginePLLTable
+/****************************************************************************/	
 #define COMPUTE_MEMORY_PLL_PARAM        1
 #define COMPUTE_ENGINE_PLL_PARAM        2
 
-typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS {
-	ULONG ulClock;		/* When returen, it's the re-calculated clock based on given Fb_div Post_Div and ref_div */
-	UCHAR ucAction;		/* 0:reserved //1:Memory //2:Engine */
-	UCHAR ucReserved;	/* may expand to return larger Fbdiv later */
-	UCHAR ucFbDiv;		/* return value */
-	UCHAR ucPostDiv;	/* return value */
-} COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS;
+typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS
+{
+  ULONG   ulClock;        //When returen, it's the re-calculated clock based on given Fb_div Post_Div and ref_div
+  UCHAR   ucAction;       //0:reserved //1:Memory //2:Engine  
+  UCHAR   ucReserved;     //may expand to return larger Fbdiv later
+  UCHAR   ucFbDiv;        //return value
+  UCHAR   ucPostDiv;      //return value
+}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS;
 
-typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2 {
-	ULONG ulClock;		/* When return, [23:0] return real clock */
-	UCHAR ucAction;		/* 0:reserved;COMPUTE_MEMORY_PLL_PARAM:Memory;COMPUTE_ENGINE_PLL_PARAM:Engine. it return ref_div to be written to register */
-	USHORT usFbDiv;		/* return Feedback value to be written to register */
-	UCHAR ucPostDiv;	/* return post div to be written to register */
-} COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2;
+typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2
+{
+  ULONG   ulClock;        //When return, [23:0] return real clock 
+  UCHAR   ucAction;       //0:reserved;COMPUTE_MEMORY_PLL_PARAM:Memory;COMPUTE_ENGINE_PLL_PARAM:Engine. it return ref_div to be written to register
+  USHORT  usFbDiv;		    //return Feedback value to be written to register
+  UCHAR   ucPostDiv;      //return post div to be written to register
+}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2;
 #define COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION   COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS
 
-#define SET_CLOCK_FREQ_MASK                     0x00FFFFFF	/* Clock change tables only take bit [23:0] as the requested clock value */
-#define USE_NON_BUS_CLOCK_MASK                  0x01000000	/* Applicable to both memory and engine clock change, when set, it uses another clock as the temporary clock (engine uses memory and vice versa) */
-#define USE_MEMORY_SELF_REFRESH_MASK            0x02000000	/* Only applicable to memory clock change, when set, using memory self refresh during clock transition */
-#define SKIP_INTERNAL_MEMORY_PARAMETER_CHANGE   0x04000000	/* Only applicable to memory clock change, when set, the table will skip predefined internal memory parameter change */
-#define FIRST_TIME_CHANGE_CLOCK									0x08000000	/* Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup */
-#define SKIP_SW_PROGRAM_PLL											0x10000000	/* Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL */
+
+#define SET_CLOCK_FREQ_MASK                     0x00FFFFFF  //Clock change tables only take bit [23:0] as the requested clock value
+#define USE_NON_BUS_CLOCK_MASK                  0x01000000  //Applicable to both memory and engine clock change, when set, it uses another clock as the temporary clock (engine uses memory and vice versa)
+#define USE_MEMORY_SELF_REFRESH_MASK            0x02000000	//Only applicable to memory clock change, when set, using memory self refresh during clock transition
+#define SKIP_INTERNAL_MEMORY_PARAMETER_CHANGE   0x04000000  //Only applicable to memory clock change, when set, the table will skip predefined internal memory parameter change
+#define FIRST_TIME_CHANGE_CLOCK									0x08000000	//Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup
+#define SKIP_SW_PROGRAM_PLL											0x10000000	//Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL
 #define USE_SS_ENABLED_PIXEL_CLOCK  USE_NON_BUS_CLOCK_MASK
 
-#define b3USE_NON_BUS_CLOCK_MASK                  0x01	/* Applicable to both memory and engine clock change, when set, it uses another clock as the temporary clock (engine uses memory and vice versa) */
-#define b3USE_MEMORY_SELF_REFRESH                 0x02	/* Only applicable to memory clock change, when set, using memory self refresh during clock transition */
-#define b3SKIP_INTERNAL_MEMORY_PARAMETER_CHANGE   0x04	/* Only applicable to memory clock change, when set, the table will skip predefined internal memory parameter change */
-#define b3FIRST_TIME_CHANGE_CLOCK									0x08	/* Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup */
-#define b3SKIP_SW_PROGRAM_PLL											0x10	/* Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL */
+#define b3USE_NON_BUS_CLOCK_MASK                  0x01       //Applicable to both memory and engine clock change, when set, it uses another clock as the temporary clock (engine uses memory and vice versa)
+#define b3USE_MEMORY_SELF_REFRESH                 0x02	     //Only applicable to memory clock change, when set, using memory self refresh during clock transition
+#define b3SKIP_INTERNAL_MEMORY_PARAMETER_CHANGE   0x04       //Only applicable to memory clock change, when set, the table will skip predefined internal memory parameter change
+#define b3FIRST_TIME_CHANGE_CLOCK									0x08       //Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup
+#define b3SKIP_SW_PROGRAM_PLL											0x10			 //Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL
 
-typedef struct _ATOM_COMPUTE_CLOCK_FREQ {
+typedef struct _ATOM_COMPUTE_CLOCK_FREQ
+{
 #if ATOM_BIG_ENDIAN
-	ULONG ulComputeClockFlag:8;	/*  =1: COMPUTE_MEMORY_PLL_PARAM, =2: COMPUTE_ENGINE_PLL_PARAM */
-	ULONG ulClockFreq:24;	/*  in unit of 10kHz */
+  ULONG ulComputeClockFlag:8;                 // =1: COMPUTE_MEMORY_PLL_PARAM, =2: COMPUTE_ENGINE_PLL_PARAM
+  ULONG ulClockFreq:24;                       // in unit of 10kHz
 #else
-	ULONG ulClockFreq:24;	/*  in unit of 10kHz */
-	ULONG ulComputeClockFlag:8;	/*  =1: COMPUTE_MEMORY_PLL_PARAM, =2: COMPUTE_ENGINE_PLL_PARAM */
+  ULONG ulClockFreq:24;                       // in unit of 10kHz
+  ULONG ulComputeClockFlag:8;                 // =1: COMPUTE_MEMORY_PLL_PARAM, =2: COMPUTE_ENGINE_PLL_PARAM
 #endif
-} ATOM_COMPUTE_CLOCK_FREQ;
+}ATOM_COMPUTE_CLOCK_FREQ;
 
-typedef struct _ATOM_S_MPLL_FB_DIVIDER {
-	USHORT usFbDivFrac;
-	USHORT usFbDiv;
-} ATOM_S_MPLL_FB_DIVIDER;
+typedef struct _ATOM_S_MPLL_FB_DIVIDER
+{
+  USHORT usFbDivFrac;  
+  USHORT usFbDiv;  
+}ATOM_S_MPLL_FB_DIVIDER;
 
-typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 {
-	union {
-		ATOM_COMPUTE_CLOCK_FREQ ulClock;	/* Input Parameter */
-		ATOM_S_MPLL_FB_DIVIDER ulFbDiv;	/* Output Parameter */
-	};
-	UCHAR ucRefDiv;		/* Output Parameter */
-	UCHAR ucPostDiv;	/* Output Parameter */
-	UCHAR ucCntlFlag;	/* Output Parameter */
-	UCHAR ucReserved;
-} COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3;
+typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3
+{
+  union
+  {
+    ATOM_COMPUTE_CLOCK_FREQ  ulClock;         //Input Parameter
+    ATOM_S_MPLL_FB_DIVIDER   ulFbDiv;         //Output Parameter
+  };
+  UCHAR   ucRefDiv;                           //Output Parameter      
+  UCHAR   ucPostDiv;                          //Output Parameter      
+  UCHAR   ucCntlFlag;                         //Output Parameter      
+  UCHAR   ucReserved;
+}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3;
 
-/*  ucCntlFlag */
+// ucCntlFlag
 #define ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN          1
 #define ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE            2
 #define ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE         4
+#define ATOM_PLL_CNTL_FLAG_SPLL_ISPARE_9						8
 
-typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER {
-	ATOM_COMPUTE_CLOCK_FREQ ulClock;
-	ULONG ulReserved[2];
-} DYNAMICE_MEMORY_SETTINGS_PARAMETER;
 
-typedef struct _DYNAMICE_ENGINE_SETTINGS_PARAMETER {
-	ATOM_COMPUTE_CLOCK_FREQ ulClock;
-	ULONG ulMemoryClock;
-	ULONG ulReserved;
-} DYNAMICE_ENGINE_SETTINGS_PARAMETER;
+// V4 are only used for APU which PLL outside GPU
+typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4
+{
+#if ATOM_BIG_ENDIAN
+  ULONG  ucPostDiv;          //return parameter: post divider which is used to program to register directly
+  ULONG  ulClock:24;         //Input= target clock, output = actual clock 
+#else
+  ULONG  ulClock:24;         //Input= target clock, output = actual clock 
+  ULONG  ucPostDiv;          //return parameter: post divider which is used to program to register directly
+#endif
+}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4;
 
-/****************************************************************************/
-/*  Structures used by SetEngineClockTable */
-/****************************************************************************/
-typedef struct _SET_ENGINE_CLOCK_PARAMETERS {
-	ULONG ulTargetEngineClock;	/* In 10Khz unit */
-} SET_ENGINE_CLOCK_PARAMETERS;
+typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER
+{
+  ATOM_COMPUTE_CLOCK_FREQ ulClock;
+  ULONG ulReserved[2];
+}DYNAMICE_MEMORY_SETTINGS_PARAMETER;
 
-typedef struct _SET_ENGINE_CLOCK_PS_ALLOCATION {
-	ULONG ulTargetEngineClock;	/* In 10Khz unit */
-	COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved;
-} SET_ENGINE_CLOCK_PS_ALLOCATION;
+typedef struct _DYNAMICE_ENGINE_SETTINGS_PARAMETER
+{
+  ATOM_COMPUTE_CLOCK_FREQ ulClock;
+  ULONG ulMemoryClock;
+  ULONG ulReserved;
+}DYNAMICE_ENGINE_SETTINGS_PARAMETER;
 
-/****************************************************************************/
-/*  Structures used by SetMemoryClockTable */
-/****************************************************************************/
-typedef struct _SET_MEMORY_CLOCK_PARAMETERS {
-	ULONG ulTargetMemoryClock;	/* In 10Khz unit */
-} SET_MEMORY_CLOCK_PARAMETERS;
+/****************************************************************************/	
+// Structures used by SetEngineClockTable
+/****************************************************************************/	
+typedef struct _SET_ENGINE_CLOCK_PARAMETERS
+{
+  ULONG ulTargetEngineClock;          //In 10Khz unit
+}SET_ENGINE_CLOCK_PARAMETERS;
 
-typedef struct _SET_MEMORY_CLOCK_PS_ALLOCATION {
-	ULONG ulTargetMemoryClock;	/* In 10Khz unit */
-	COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved;
-} SET_MEMORY_CLOCK_PS_ALLOCATION;
+typedef struct _SET_ENGINE_CLOCK_PS_ALLOCATION
+{
+  ULONG ulTargetEngineClock;          //In 10Khz unit
+  COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved;
+}SET_ENGINE_CLOCK_PS_ALLOCATION;
 
-/****************************************************************************/
-/*  Structures used by ASIC_Init.ctb */
-/****************************************************************************/
-typedef struct _ASIC_INIT_PARAMETERS {
-	ULONG ulDefaultEngineClock;	/* In 10Khz unit */
-	ULONG ulDefaultMemoryClock;	/* In 10Khz unit */
-} ASIC_INIT_PARAMETERS;
+/****************************************************************************/	
+// Structures used by SetMemoryClockTable
+/****************************************************************************/	
+typedef struct _SET_MEMORY_CLOCK_PARAMETERS
+{
+  ULONG ulTargetMemoryClock;          //In 10Khz unit
+}SET_MEMORY_CLOCK_PARAMETERS;
 
-typedef struct _ASIC_INIT_PS_ALLOCATION {
-	ASIC_INIT_PARAMETERS sASICInitClocks;
-	SET_ENGINE_CLOCK_PS_ALLOCATION sReserved;	/* Caller doesn't need to init this structure */
-} ASIC_INIT_PS_ALLOCATION;
+typedef struct _SET_MEMORY_CLOCK_PS_ALLOCATION
+{
+  ULONG ulTargetMemoryClock;          //In 10Khz unit
+  COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved;
+}SET_MEMORY_CLOCK_PS_ALLOCATION;
 
-/****************************************************************************/
-/*  Structure used by DynamicClockGatingTable.ctb */
-/****************************************************************************/
-typedef struct _DYNAMIC_CLOCK_GATING_PARAMETERS {
-	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
-	UCHAR ucPadding[3];
-} DYNAMIC_CLOCK_GATING_PARAMETERS;
+/****************************************************************************/	
+// Structures used by ASIC_Init.ctb
+/****************************************************************************/	
+typedef struct _ASIC_INIT_PARAMETERS
+{
+  ULONG ulDefaultEngineClock;         //In 10Khz unit
+  ULONG ulDefaultMemoryClock;         //In 10Khz unit
+}ASIC_INIT_PARAMETERS;
+
+typedef struct _ASIC_INIT_PS_ALLOCATION
+{
+  ASIC_INIT_PARAMETERS sASICInitClocks;
+  SET_ENGINE_CLOCK_PS_ALLOCATION sReserved; //Caller doesn't need to init this structure
+}ASIC_INIT_PS_ALLOCATION;
+
+/****************************************************************************/	
+// Structure used by DynamicClockGatingTable.ctb
+/****************************************************************************/	
+typedef struct _DYNAMIC_CLOCK_GATING_PARAMETERS 
+{
+  UCHAR ucEnable;                     // ATOM_ENABLE or ATOM_DISABLE
+  UCHAR ucPadding[3];
+}DYNAMIC_CLOCK_GATING_PARAMETERS;
 #define  DYNAMIC_CLOCK_GATING_PS_ALLOCATION  DYNAMIC_CLOCK_GATING_PARAMETERS
 
-/****************************************************************************/
-/*  Structure used by EnableASIC_StaticPwrMgtTable.ctb */
-/****************************************************************************/
-typedef struct _ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS {
-	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
-	UCHAR ucPadding[3];
-} ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS;
+/****************************************************************************/	
+// Structure used by EnableASIC_StaticPwrMgtTable.ctb
+/****************************************************************************/	
+typedef struct _ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS
+{
+  UCHAR ucEnable;                     // ATOM_ENABLE or ATOM_DISABLE
+  UCHAR ucPadding[3];
+}ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS;
 #define ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION  ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by DAC_LoadDetectionTable.ctb */
-/****************************************************************************/
-typedef struct _DAC_LOAD_DETECTION_PARAMETERS {
-	USHORT usDeviceID;	/* {ATOM_DEVICE_CRTx_SUPPORT,ATOM_DEVICE_TVx_SUPPORT,ATOM_DEVICE_CVx_SUPPORT} */
-	UCHAR ucDacType;	/* {ATOM_DAC_A,ATOM_DAC_B, ATOM_EXT_DAC} */
-	UCHAR ucMisc;		/* Valid only when table revision =1.3 and above */
-} DAC_LOAD_DETECTION_PARAMETERS;
+/****************************************************************************/	
+// Structures used by DAC_LoadDetectionTable.ctb
+/****************************************************************************/	
+typedef struct _DAC_LOAD_DETECTION_PARAMETERS
+{
+  USHORT usDeviceID;                  //{ATOM_DEVICE_CRTx_SUPPORT,ATOM_DEVICE_TVx_SUPPORT,ATOM_DEVICE_CVx_SUPPORT}
+  UCHAR  ucDacType;                   //{ATOM_DAC_A,ATOM_DAC_B, ATOM_EXT_DAC}
+  UCHAR  ucMisc;											//Valid only when table revision =1.3 and above
+}DAC_LOAD_DETECTION_PARAMETERS;
 
-/*  DAC_LOAD_DETECTION_PARAMETERS.ucMisc */
+// DAC_LOAD_DETECTION_PARAMETERS.ucMisc
 #define DAC_LOAD_MISC_YPrPb						0x01
 
-typedef struct _DAC_LOAD_DETECTION_PS_ALLOCATION {
-	DAC_LOAD_DETECTION_PARAMETERS sDacload;
-	ULONG Reserved[2];	/*  Don't set this one, allocation for EXT DAC */
-} DAC_LOAD_DETECTION_PS_ALLOCATION;
+typedef struct _DAC_LOAD_DETECTION_PS_ALLOCATION
+{
+  DAC_LOAD_DETECTION_PARAMETERS            sDacload;
+  ULONG                                    Reserved[2];// Don't set this one, allocation for EXT DAC
+}DAC_LOAD_DETECTION_PS_ALLOCATION;
 
-/****************************************************************************/
-/*  Structures used by DAC1EncoderControlTable.ctb and DAC2EncoderControlTable.ctb */
-/****************************************************************************/
-typedef struct _DAC_ENCODER_CONTROL_PARAMETERS {
-	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
-	UCHAR ucDacStandard;	/*  See definition of ATOM_DACx_xxx, For DEC3.0, bit 7 used as internal flag to indicate DAC2 (==1) or DAC1 (==0) */
-	UCHAR ucAction;		/*  0: turn off encoder */
-	/*  1: setup and turn on encoder */
-	/*  7: ATOM_ENCODER_INIT Initialize DAC */
-} DAC_ENCODER_CONTROL_PARAMETERS;
+/****************************************************************************/	
+// Structures used by DAC1EncoderControlTable.ctb and DAC2EncoderControlTable.ctb
+/****************************************************************************/	
+typedef struct _DAC_ENCODER_CONTROL_PARAMETERS 
+{
+  USHORT usPixelClock;                // in 10KHz; for bios convenient
+  UCHAR  ucDacStandard;               // See definition of ATOM_DACx_xxx, For DEC3.0, bit 7 used as internal flag to indicate DAC2 (==1) or DAC1 (==0)
+  UCHAR  ucAction;                    // 0: turn off encoder
+                                      // 1: setup and turn on encoder
+                                      // 7: ATOM_ENCODER_INIT Initialize DAC
+}DAC_ENCODER_CONTROL_PARAMETERS;
 
 #define DAC_ENCODER_CONTROL_PS_ALLOCATION  DAC_ENCODER_CONTROL_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by DIG1EncoderControlTable */
-/*                     DIG2EncoderControlTable */
-/*                     ExternalEncoderControlTable */
-/****************************************************************************/
-typedef struct _DIG_ENCODER_CONTROL_PARAMETERS {
-	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
-	UCHAR ucConfig;
-	/*  [2] Link Select: */
-	/*  =0: PHY linkA if bfLane<3 */
-	/*  =1: PHY linkB if bfLanes<3 */
-	/*  =0: PHY linkA+B if bfLanes=3 */
-	/*  [3] Transmitter Sel */
-	/*  =0: UNIPHY or PCIEPHY */
-	/*  =1: LVTMA */
-	UCHAR ucAction;		/*  =0: turn off encoder */
-	/*  =1: turn on encoder */
-	UCHAR ucEncoderMode;
-	/*  =0: DP   encoder */
-	/*  =1: LVDS encoder */
-	/*  =2: DVI  encoder */
-	/*  =3: HDMI encoder */
-	/*  =4: SDVO encoder */
-	UCHAR ucLaneNum;	/*  how many lanes to enable */
-	UCHAR ucReserved[2];
-} DIG_ENCODER_CONTROL_PARAMETERS;
+/****************************************************************************/	
+// Structures used by DIG1EncoderControlTable
+//                    DIG2EncoderControlTable
+//                    ExternalEncoderControlTable
+/****************************************************************************/	
+typedef struct _DIG_ENCODER_CONTROL_PARAMETERS
+{
+  USHORT usPixelClock;		// in 10KHz; for bios convenient
+  UCHAR  ucConfig;		  
+                            // [2] Link Select:
+                            // =0: PHY linkA if bfLane<3
+                            // =1: PHY linkB if bfLanes<3
+                            // =0: PHY linkA+B if bfLanes=3
+                            // [3] Transmitter Sel
+                            // =0: UNIPHY or PCIEPHY
+                            // =1: LVTMA 					
+  UCHAR ucAction;           // =0: turn off encoder					
+                            // =1: turn on encoder			
+  UCHAR ucEncoderMode;
+                            // =0: DP   encoder      
+                            // =1: LVDS encoder          
+                            // =2: DVI  encoder  
+                            // =3: HDMI encoder
+                            // =4: SDVO encoder
+  UCHAR ucLaneNum;          // how many lanes to enable
+  UCHAR ucReserved[2];
+}DIG_ENCODER_CONTROL_PARAMETERS;
 #define DIG_ENCODER_CONTROL_PS_ALLOCATION			  DIG_ENCODER_CONTROL_PARAMETERS
 #define EXTERNAL_ENCODER_CONTROL_PARAMETER			DIG_ENCODER_CONTROL_PARAMETERS
 
-/* ucConfig */
+//ucConfig
 #define ATOM_ENCODER_CONFIG_DPLINKRATE_MASK				0x01
 #define ATOM_ENCODER_CONFIG_DPLINKRATE_1_62GHZ		0x00
 #define ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ		0x01
@@ -539,52 +593,57 @@
 #define ATOM_ENCODER_CONFIG_LVTMA								  0x08
 #define ATOM_ENCODER_CONFIG_TRANSMITTER1				  0x00
 #define ATOM_ENCODER_CONFIG_TRANSMITTER2				  0x08
-#define ATOM_ENCODER_CONFIG_DIGB								  0x80	/*  VBIOS Internal use, outside SW should set this bit=0 */
-/*  ucAction */
-/*  ATOM_ENABLE:  Enable Encoder */
-/*  ATOM_DISABLE: Disable Encoder */
+#define ATOM_ENCODER_CONFIG_DIGB								  0x80			// VBIOS Internal use, outside SW should set this bit=0
+// ucAction
+// ATOM_ENABLE:  Enable Encoder
+// ATOM_DISABLE: Disable Encoder
 
-/* ucEncoderMode */
+//ucEncoderMode
 #define ATOM_ENCODER_MODE_DP											0
 #define ATOM_ENCODER_MODE_LVDS										1
 #define ATOM_ENCODER_MODE_DVI											2
 #define ATOM_ENCODER_MODE_HDMI										3
 #define ATOM_ENCODER_MODE_SDVO										4
+#define ATOM_ENCODER_MODE_DP_AUDIO                5
 #define ATOM_ENCODER_MODE_TV											13
 #define ATOM_ENCODER_MODE_CV											14
 #define ATOM_ENCODER_MODE_CRT											15
 
-typedef struct _ATOM_DIG_ENCODER_CONFIG_V2 {
+typedef struct _ATOM_DIG_ENCODER_CONFIG_V2
+{
 #if ATOM_BIG_ENDIAN
-	UCHAR ucReserved1:2;
-	UCHAR ucTransmitterSel:2;	/*  =0: UniphyAB, =1: UniphyCD  =2: UniphyEF */
-	UCHAR ucLinkSel:1;	/*  =0: linkA/C/E =1: linkB/D/F */
-	UCHAR ucReserved:1;
-	UCHAR ucDPLinkRate:1;	/*  =0: 1.62Ghz, =1: 2.7Ghz */
+    UCHAR ucReserved1:2;
+    UCHAR ucTransmitterSel:2;     // =0: UniphyAB, =1: UniphyCD  =2: UniphyEF
+    UCHAR ucLinkSel:1;            // =0: linkA/C/E =1: linkB/D/F
+    UCHAR ucReserved:1;
+    UCHAR ucDPLinkRate:1;         // =0: 1.62Ghz, =1: 2.7Ghz
 #else
-	UCHAR ucDPLinkRate:1;	/*  =0: 1.62Ghz, =1: 2.7Ghz */
-	UCHAR ucReserved:1;
-	UCHAR ucLinkSel:1;	/*  =0: linkA/C/E =1: linkB/D/F */
-	UCHAR ucTransmitterSel:2;	/*  =0: UniphyAB, =1: UniphyCD  =2: UniphyEF */
-	UCHAR ucReserved1:2;
+    UCHAR ucDPLinkRate:1;         // =0: 1.62Ghz, =1: 2.7Ghz
+    UCHAR ucReserved:1;
+    UCHAR ucLinkSel:1;            // =0: linkA/C/E =1: linkB/D/F
+    UCHAR ucTransmitterSel:2;     // =0: UniphyAB, =1: UniphyCD  =2: UniphyEF
+    UCHAR ucReserved1:2;
 #endif
-} ATOM_DIG_ENCODER_CONFIG_V2;
+}ATOM_DIG_ENCODER_CONFIG_V2;
 
-typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V2 {
-	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
-	ATOM_DIG_ENCODER_CONFIG_V2 acConfig;
-	UCHAR ucAction;
-	UCHAR ucEncoderMode;
-	/*  =0: DP   encoder */
-	/*  =1: LVDS encoder */
-	/*  =2: DVI  encoder */
-	/*  =3: HDMI encoder */
-	/*  =4: SDVO encoder */
-	UCHAR ucLaneNum;	/*  how many lanes to enable */
-	UCHAR ucReserved[2];
-} DIG_ENCODER_CONTROL_PARAMETERS_V2;
 
-/* ucConfig */
+typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V2
+{
+  USHORT usPixelClock;      // in 10KHz; for bios convenient
+  ATOM_DIG_ENCODER_CONFIG_V2 acConfig;
+  UCHAR ucAction;                                       
+  UCHAR ucEncoderMode;
+                            // =0: DP   encoder      
+                            // =1: LVDS encoder          
+                            // =2: DVI  encoder  
+                            // =3: HDMI encoder
+                            // =4: SDVO encoder
+  UCHAR ucLaneNum;          // how many lanes to enable
+  UCHAR ucStatus;           // = DP_LINK_TRAINING_COMPLETE or DP_LINK_TRAINING_INCOMPLETE, only used by VBIOS with command ATOM_ENCODER_CMD_QUERY_DP_LINK_TRAINING_STATUS
+  UCHAR ucReserved;
+}DIG_ENCODER_CONTROL_PARAMETERS_V2;
+
+//ucConfig
 #define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_MASK				0x01
 #define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_1_62GHZ		  0x00
 #define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_2_70GHZ		  0x01
@@ -596,58 +655,122 @@
 #define ATOM_ENCODER_CONFIG_V2_TRANSMITTER2				    0x08
 #define ATOM_ENCODER_CONFIG_V2_TRANSMITTER3				    0x10
 
-/****************************************************************************/
-/*  Structures used by UNIPHYTransmitterControlTable */
-/*                     LVTMATransmitterControlTable */
-/*                     DVOOutputControlTable */
-/****************************************************************************/
-typedef struct _ATOM_DP_VS_MODE {
-	UCHAR ucLaneSel;
-	UCHAR ucLaneSet;
-} ATOM_DP_VS_MODE;
+// ucAction:
+// ATOM_DISABLE
+// ATOM_ENABLE
+#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_START       0x08
+#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1    0x09
+#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2    0x0a
+#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE    0x0b
+#define ATOM_ENCODER_CMD_DP_VIDEO_OFF                 0x0c
+#define ATOM_ENCODER_CMD_DP_VIDEO_ON                  0x0d
+#define ATOM_ENCODER_CMD_QUERY_DP_LINK_TRAINING_STATUS    0x0e
+#define ATOM_ENCODER_CMD_SETUP                        0x0f
 
-typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS {
-	union {
-		USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
-		USHORT usInitInfo;	/*  when init uniphy,lower 8bit is used for connector type defined in objectid.h */
-		ATOM_DP_VS_MODE asMode;	/*  DP Voltage swing mode */
+// ucStatus
+#define ATOM_ENCODER_STATUS_LINK_TRAINING_COMPLETE    0x10
+#define ATOM_ENCODER_STATUS_LINK_TRAINING_INCOMPLETE  0x00
+
+// Following function ENABLE sub-function will be used by driver when TMDS/HDMI/LVDS is used, disable function will be used by driver
+typedef struct _ATOM_DIG_ENCODER_CONFIG_V3
+{
+#if ATOM_BIG_ENDIAN
+    UCHAR ucReserved1:1;
+    UCHAR ucDigSel:3;             // =0: DIGA/B/C/D/E/F
+    UCHAR ucReserved:3;
+    UCHAR ucDPLinkRate:1;         // =0: 1.62Ghz, =1: 2.7Ghz
+#else
+    UCHAR ucDPLinkRate:1;         // =0: 1.62Ghz, =1: 2.7Ghz
+    UCHAR ucReserved:3;
+    UCHAR ucDigSel:3;             // =0: DIGA/B/C/D/E/F
+    UCHAR ucReserved1:1;
+#endif
+}ATOM_DIG_ENCODER_CONFIG_V3;
+
+#define ATOM_ENCODER_CONFIG_V3_ENCODER_SEL					  0x70
+
+
+typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V3
+{
+  USHORT usPixelClock;      // in 10KHz; for bios convenient
+  ATOM_DIG_ENCODER_CONFIG_V3 acConfig;
+  UCHAR ucAction;                              
+  UCHAR ucEncoderMode;
+                            // =0: DP   encoder      
+                            // =1: LVDS encoder          
+                            // =2: DVI  encoder  
+                            // =3: HDMI encoder
+                            // =4: SDVO encoder
+                            // =5: DP audio
+  UCHAR ucLaneNum;          // how many lanes to enable
+  UCHAR ucBitPerColor;      // only valid for DP mode when ucAction = ATOM_ENCODER_CMD_SETUP
+  UCHAR ucReserved;
+}DIG_ENCODER_CONTROL_PARAMETERS_V3;
+
+
+// define ucBitPerColor: 
+#define PANEL_BPC_UNDEFINE                               0x00
+#define PANEL_6BIT_PER_COLOR                             0x01 
+#define PANEL_8BIT_PER_COLOR                             0x02
+#define PANEL_10BIT_PER_COLOR                            0x03
+#define PANEL_12BIT_PER_COLOR                            0x04
+#define PANEL_16BIT_PER_COLOR                            0x05
+
+/****************************************************************************/	
+// Structures used by UNIPHYTransmitterControlTable
+//                    LVTMATransmitterControlTable
+//                    DVOOutputControlTable
+/****************************************************************************/	
+typedef struct _ATOM_DP_VS_MODE
+{
+  UCHAR ucLaneSel;
+  UCHAR ucLaneSet;
+}ATOM_DP_VS_MODE;
+
+typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS
+{
+	union
+	{
+  USHORT usPixelClock;		// in 10KHz; for bios convenient
+	USHORT usInitInfo;			// when init uniphy,lower 8bit is used for connector type defined in objectid.h
+  ATOM_DP_VS_MODE asMode; // DP Voltage swing mode
 	};
-	UCHAR ucConfig;
-	/*  [0]=0: 4 lane Link, */
-	/*     =1: 8 lane Link ( Dual Links TMDS ) */
-	/*  [1]=0: InCoherent mode */
-	/*     =1: Coherent Mode */
-	/*  [2] Link Select: */
-	/*  =0: PHY linkA   if bfLane<3 */
-	/*  =1: PHY linkB   if bfLanes<3 */
-	/*  =0: PHY linkA+B if bfLanes=3 */
-	/*  [5:4]PCIE lane Sel */
-	/*  =0: lane 0~3 or 0~7 */
-	/*  =1: lane 4~7 */
-	/*  =2: lane 8~11 or 8~15 */
-	/*  =3: lane 12~15 */
-	UCHAR ucAction;		/*  =0: turn off encoder */
-	/*  =1: turn on encoder */
-	UCHAR ucReserved[4];
-} DIG_TRANSMITTER_CONTROL_PARAMETERS;
+  UCHAR ucConfig;
+													// [0]=0: 4 lane Link,      
+													//    =1: 8 lane Link ( Dual Links TMDS ) 
+                          // [1]=0: InCoherent mode   
+													//    =1: Coherent Mode										
+													// [2] Link Select:
+  												// =0: PHY linkA   if bfLane<3
+													// =1: PHY linkB   if bfLanes<3
+		  										// =0: PHY linkA+B if bfLanes=3		
+                          // [5:4]PCIE lane Sel
+                          // =0: lane 0~3 or 0~7
+                          // =1: lane 4~7
+                          // =2: lane 8~11 or 8~15
+                          // =3: lane 12~15 
+	UCHAR ucAction;				  // =0: turn off encoder					
+	                        // =1: turn on encoder			
+  UCHAR ucReserved[4];
+}DIG_TRANSMITTER_CONTROL_PARAMETERS;
 
-#define DIG_TRANSMITTER_CONTROL_PS_ALLOCATION		DIG_TRANSMITTER_CONTROL_PARAMETERS
+#define DIG_TRANSMITTER_CONTROL_PS_ALLOCATION		DIG_TRANSMITTER_CONTROL_PARAMETERS					
 
-/* ucInitInfo */
-#define ATOM_TRAMITTER_INITINFO_CONNECTOR_MASK	0x00ff
+//ucInitInfo
+#define ATOM_TRAMITTER_INITINFO_CONNECTOR_MASK	0x00ff			
 
-/* ucConfig */
+//ucConfig 
 #define ATOM_TRANSMITTER_CONFIG_8LANE_LINK			0x01
 #define ATOM_TRANSMITTER_CONFIG_COHERENT				0x02
 #define ATOM_TRANSMITTER_CONFIG_LINK_SEL_MASK		0x04
 #define ATOM_TRANSMITTER_CONFIG_LINKA						0x00
 #define ATOM_TRANSMITTER_CONFIG_LINKB						0x04
-#define ATOM_TRANSMITTER_CONFIG_LINKA_B					0x00
+#define ATOM_TRANSMITTER_CONFIG_LINKA_B					0x00			
 #define ATOM_TRANSMITTER_CONFIG_LINKB_A					0x04
 
-#define ATOM_TRANSMITTER_CONFIG_ENCODER_SEL_MASK	0x08	/*  only used when ATOM_TRANSMITTER_ACTION_ENABLE */
-#define ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER		0x00	/*  only used when ATOM_TRANSMITTER_ACTION_ENABLE */
-#define ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER		0x08	/*  only used when ATOM_TRANSMITTER_ACTION_ENABLE */
+#define ATOM_TRANSMITTER_CONFIG_ENCODER_SEL_MASK	0x08			// only used when ATOM_TRANSMITTER_ACTION_ENABLE
+#define ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER		0x00				// only used when ATOM_TRANSMITTER_ACTION_ENABLE
+#define ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER		0x08				// only used when ATOM_TRANSMITTER_ACTION_ENABLE
 
 #define ATOM_TRANSMITTER_CONFIG_CLKSRC_MASK			0x30
 #define ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL			0x00
@@ -661,7 +784,7 @@
 #define ATOM_TRANSMITTER_CONFIG_LANE_8_15				0x80
 #define ATOM_TRANSMITTER_CONFIG_LANE_12_15			0xc0
 
-/* ucAction */
+//ucAction
 #define ATOM_TRANSMITTER_ACTION_DISABLE					       0
 #define ATOM_TRANSMITTER_ACTION_ENABLE					       1
 #define ATOM_TRANSMITTER_ACTION_LCD_BLOFF				       2
@@ -674,93 +797,168 @@
 #define ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT		       9
 #define ATOM_TRANSMITTER_ACTION_SETUP						       10
 #define ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH           11
+#define ATOM_TRANSMITTER_ACTION_POWER_ON               12
+#define ATOM_TRANSMITTER_ACTION_POWER_OFF              13
 
-/*  Following are used for DigTransmitterControlTable ver1.2 */
-typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V2 {
+// Following are used for DigTransmitterControlTable ver1.2
+typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V2
+{
 #if ATOM_BIG_ENDIAN
-	UCHAR ucTransmitterSel:2;	/* bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) */
-	/*         =1 Dig Transmitter 2 ( Uniphy CD ) */
-	/*         =2 Dig Transmitter 3 ( Uniphy EF ) */
-	UCHAR ucReserved:1;
-	UCHAR fDPConnector:1;	/* bit4=0: DP connector  =1: None DP connector */
-	UCHAR ucEncoderSel:1;	/* bit3=0: Data/Clk path source from DIGA( DIG inst0 ). =1: Data/clk path source from DIGB ( DIG inst1 ) */
-	UCHAR ucLinkSel:1;	/* bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E */
-	/*     =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F */
+  UCHAR ucTransmitterSel:2;         //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB )
+                                    //        =1 Dig Transmitter 2 ( Uniphy CD )
+                                    //        =2 Dig Transmitter 3 ( Uniphy EF )
+  UCHAR ucReserved:1;               
+  UCHAR fDPConnector:1;             //bit4=0: DP connector  =1: None DP connector
+  UCHAR ucEncoderSel:1;             //bit3=0: Data/Clk path source from DIGA( DIG inst0 ). =1: Data/clk path source from DIGB ( DIG inst1 )
+  UCHAR ucLinkSel:1;                //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E
+                                    //    =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F
 
-	UCHAR fCoherentMode:1;	/* bit1=1: Coherent Mode ( for DVI/HDMI mode ) */
-	UCHAR fDualLinkConnector:1;	/* bit0=1: Dual Link DVI connector */
+  UCHAR fCoherentMode:1;            //bit1=1: Coherent Mode ( for DVI/HDMI mode )
+  UCHAR fDualLinkConnector:1;       //bit0=1: Dual Link DVI connector
 #else
-	UCHAR fDualLinkConnector:1;	/* bit0=1: Dual Link DVI connector */
-	UCHAR fCoherentMode:1;	/* bit1=1: Coherent Mode ( for DVI/HDMI mode ) */
-	UCHAR ucLinkSel:1;	/* bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E */
-	/*     =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F */
-	UCHAR ucEncoderSel:1;	/* bit3=0: Data/Clk path source from DIGA( DIG inst0 ). =1: Data/clk path source from DIGB ( DIG inst1 ) */
-	UCHAR fDPConnector:1;	/* bit4=0: DP connector  =1: None DP connector */
-	UCHAR ucReserved:1;
-	UCHAR ucTransmitterSel:2;	/* bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) */
-	/*         =1 Dig Transmitter 2 ( Uniphy CD ) */
-	/*         =2 Dig Transmitter 3 ( Uniphy EF ) */
+  UCHAR fDualLinkConnector:1;       //bit0=1: Dual Link DVI connector
+  UCHAR fCoherentMode:1;            //bit1=1: Coherent Mode ( for DVI/HDMI mode )
+  UCHAR ucLinkSel:1;                //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E
+                                    //    =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F
+  UCHAR ucEncoderSel:1;             //bit3=0: Data/Clk path source from DIGA( DIG inst0 ). =1: Data/clk path source from DIGB ( DIG inst1 )
+  UCHAR fDPConnector:1;             //bit4=0: DP connector  =1: None DP connector
+  UCHAR ucReserved:1;               
+  UCHAR ucTransmitterSel:2;         //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB )
+                                    //        =1 Dig Transmitter 2 ( Uniphy CD )
+                                    //        =2 Dig Transmitter 3 ( Uniphy EF )
 #endif
-} ATOM_DIG_TRANSMITTER_CONFIG_V2;
+}ATOM_DIG_TRANSMITTER_CONFIG_V2;
 
-/* ucConfig */
-/* Bit0 */
+//ucConfig 
+//Bit0
 #define ATOM_TRANSMITTER_CONFIG_V2_DUAL_LINK_CONNECTOR			0x01
 
-/* Bit1 */
+//Bit1
 #define ATOM_TRANSMITTER_CONFIG_V2_COHERENT				          0x02
 
-/* Bit2 */
+//Bit2
 #define ATOM_TRANSMITTER_CONFIG_V2_LINK_SEL_MASK		        0x04
-#define ATOM_TRANSMITTER_CONFIG_V2_LINKA			            0x00
+#define ATOM_TRANSMITTER_CONFIG_V2_LINKA  			            0x00
 #define ATOM_TRANSMITTER_CONFIG_V2_LINKB				            0x04
 
-/*  Bit3 */
+// Bit3
 #define ATOM_TRANSMITTER_CONFIG_V2_ENCODER_SEL_MASK	        0x08
-#define ATOM_TRANSMITTER_CONFIG_V2_DIG1_ENCODER		          0x00	/*  only used when ucAction == ATOM_TRANSMITTER_ACTION_ENABLE or ATOM_TRANSMITTER_ACTION_SETUP */
-#define ATOM_TRANSMITTER_CONFIG_V2_DIG2_ENCODER		          0x08	/*  only used when ucAction == ATOM_TRANSMITTER_ACTION_ENABLE or ATOM_TRANSMITTER_ACTION_SETUP */
+#define ATOM_TRANSMITTER_CONFIG_V2_DIG1_ENCODER		          0x00				// only used when ucAction == ATOM_TRANSMITTER_ACTION_ENABLE or ATOM_TRANSMITTER_ACTION_SETUP
+#define ATOM_TRANSMITTER_CONFIG_V2_DIG2_ENCODER		          0x08				// only used when ucAction == ATOM_TRANSMITTER_ACTION_ENABLE or ATOM_TRANSMITTER_ACTION_SETUP
 
-/*  Bit4 */
+// Bit4
 #define ATOM_TRASMITTER_CONFIG_V2_DP_CONNECTOR			        0x10
 
-/*  Bit7:6 */
+// Bit7:6
 #define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER_SEL_MASK     0xC0
-#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER1			0x00	/* AB */
-#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER2			0x40	/* CD */
-#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER3			0x80	/* EF */
+#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER1           	0x00	//AB
+#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER2           	0x40	//CD
+#define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER3           	0x80	//EF
 
-typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 {
-	union {
-		USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
-		USHORT usInitInfo;	/*  when init uniphy,lower 8bit is used for connector type defined in objectid.h */
-		ATOM_DP_VS_MODE asMode;	/*  DP Voltage swing mode */
+typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V2
+{
+	union
+	{
+  USHORT usPixelClock;		// in 10KHz; for bios convenient
+	USHORT usInitInfo;			// when init uniphy,lower 8bit is used for connector type defined in objectid.h
+  ATOM_DP_VS_MODE asMode; // DP Voltage swing mode
 	};
-	ATOM_DIG_TRANSMITTER_CONFIG_V2 acConfig;
-	UCHAR ucAction;		/*  define as ATOM_TRANSMITER_ACTION_XXX */
-	UCHAR ucReserved[4];
-} DIG_TRANSMITTER_CONTROL_PARAMETERS_V2;
+  ATOM_DIG_TRANSMITTER_CONFIG_V2 acConfig;
+	UCHAR ucAction;				  // define as ATOM_TRANSMITER_ACTION_XXX
+  UCHAR ucReserved[4];
+}DIG_TRANSMITTER_CONTROL_PARAMETERS_V2;
 
-/****************************************************************************/
-/*  Structures used by DAC1OuputControlTable */
-/*                     DAC2OuputControlTable */
-/*                     LVTMAOutputControlTable  (Before DEC30) */
-/*                     TMDSAOutputControlTable  (Before DEC30) */
-/****************************************************************************/
-typedef struct _DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS {
-	UCHAR ucAction;		/*  Possible input:ATOM_ENABLE||ATOMDISABLE */
-	/*  When the display is LCD, in addition to above: */
-	/*  ATOM_LCD_BLOFF|| ATOM_LCD_BLON ||ATOM_LCD_BL_BRIGHTNESS_CONTROL||ATOM_LCD_SELFTEST_START|| */
-	/*  ATOM_LCD_SELFTEST_STOP */
+typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V3
+{
+#if ATOM_BIG_ENDIAN
+  UCHAR ucTransmitterSel:2;         //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB )
+                                    //        =1 Dig Transmitter 2 ( Uniphy CD )
+                                    //        =2 Dig Transmitter 3 ( Uniphy EF )
+  UCHAR ucRefClkSource:2;           //bit5:4: PPLL1 =0, PPLL2=1, EXT_CLK=2
+  UCHAR ucEncoderSel:1;             //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F
+  UCHAR ucLinkSel:1;                //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E
+                                    //    =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F
+  UCHAR fCoherentMode:1;            //bit1=1: Coherent Mode ( for DVI/HDMI mode )
+  UCHAR fDualLinkConnector:1;       //bit0=1: Dual Link DVI connector
+#else
+  UCHAR fDualLinkConnector:1;       //bit0=1: Dual Link DVI connector
+  UCHAR fCoherentMode:1;            //bit1=1: Coherent Mode ( for DVI/HDMI mode )
+  UCHAR ucLinkSel:1;                //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E
+                                    //    =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F
+  UCHAR ucEncoderSel:1;             //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F
+  UCHAR ucRefClkSource:2;           //bit5:4: PPLL1 =0, PPLL2=1, EXT_CLK=2
+  UCHAR ucTransmitterSel:2;         //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB )
+                                    //        =1 Dig Transmitter 2 ( Uniphy CD )
+                                    //        =2 Dig Transmitter 3 ( Uniphy EF )
+#endif
+}ATOM_DIG_TRANSMITTER_CONFIG_V3;
 
-	UCHAR aucPadding[3];	/*  padding to DWORD aligned */
-} DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS;
+typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V3
+{
+	union
+	{
+    USHORT usPixelClock;		// in 10KHz; for bios convenient
+	  USHORT usInitInfo;			// when init uniphy,lower 8bit is used for connector type defined in objectid.h
+    ATOM_DP_VS_MODE asMode; // DP Voltage swing mode
+	};
+  ATOM_DIG_TRANSMITTER_CONFIG_V3 acConfig;
+	UCHAR ucAction;				    // define as ATOM_TRANSMITER_ACTION_XXX
+  UCHAR ucLaneNum;
+  UCHAR ucReserved[3];
+}DIG_TRANSMITTER_CONTROL_PARAMETERS_V3;
+
+//ucConfig 
+//Bit0
+#define ATOM_TRANSMITTER_CONFIG_V3_DUAL_LINK_CONNECTOR			0x01
+
+//Bit1
+#define ATOM_TRANSMITTER_CONFIG_V3_COHERENT				          0x02
+
+//Bit2
+#define ATOM_TRANSMITTER_CONFIG_V3_LINK_SEL_MASK		        0x04
+#define ATOM_TRANSMITTER_CONFIG_V3_LINKA  			            0x00
+#define ATOM_TRANSMITTER_CONFIG_V3_LINKB				            0x04
+
+// Bit3
+#define ATOM_TRANSMITTER_CONFIG_V3_ENCODER_SEL_MASK	        0x08
+#define ATOM_TRANSMITTER_CONFIG_V3_DIG1_ENCODER		          0x00
+#define ATOM_TRANSMITTER_CONFIG_V3_DIG2_ENCODER		          0x08
+
+// Bit5:4
+#define ATOM_TRASMITTER_CONFIG_V3_REFCLK_SEL_MASK 	        0x30
+#define ATOM_TRASMITTER_CONFIG_V3_P1PLL          		        0x00
+#define ATOM_TRASMITTER_CONFIG_V3_P2PLL		                  0x10
+#define ATOM_TRASMITTER_CONFIG_V3_REFCLK_SRC_EXT            0x20
+
+// Bit7:6
+#define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER_SEL_MASK     0xC0
+#define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER1           	0x00	//AB
+#define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER2           	0x40	//CD
+#define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER3           	0x80	//EF
+
+/****************************************************************************/	
+// Structures used by DAC1OuputControlTable
+//                    DAC2OuputControlTable
+//                    LVTMAOutputControlTable  (Before DEC30)
+//                    TMDSAOutputControlTable  (Before DEC30)
+/****************************************************************************/	
+typedef struct _DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+{
+  UCHAR  ucAction;                    // Possible input:ATOM_ENABLE||ATOMDISABLE
+                                      // When the display is LCD, in addition to above:
+                                      // ATOM_LCD_BLOFF|| ATOM_LCD_BLON ||ATOM_LCD_BL_BRIGHTNESS_CONTROL||ATOM_LCD_SELFTEST_START||
+                                      // ATOM_LCD_SELFTEST_STOP
+                                      
+  UCHAR  aucPadding[3];               // padding to DWORD aligned
+}DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS;
 
 #define DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
 
-#define CRT1_OUTPUT_CONTROL_PARAMETERS     DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+
+#define CRT1_OUTPUT_CONTROL_PARAMETERS     DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS 
 #define CRT1_OUTPUT_CONTROL_PS_ALLOCATION  DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION
 
-#define CRT2_OUTPUT_CONTROL_PARAMETERS     DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
+#define CRT2_OUTPUT_CONTROL_PARAMETERS     DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS 
 #define CRT2_OUTPUT_CONTROL_PS_ALLOCATION  DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION
 
 #define CV1_OUTPUT_CONTROL_PARAMETERS      DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS
@@ -782,397 +980,550 @@
 #define DVO_OUTPUT_CONTROL_PS_ALLOCATION   DIG_TRANSMITTER_CONTROL_PS_ALLOCATION
 #define DVO_OUTPUT_CONTROL_PARAMETERS_V3	 DIG_TRANSMITTER_CONTROL_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by BlankCRTCTable */
-/****************************************************************************/
-typedef struct _BLANK_CRTC_PARAMETERS {
-	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
-	UCHAR ucBlanking;	/*  ATOM_BLANKING or ATOM_BLANKINGOFF */
-	USHORT usBlackColorRCr;
-	USHORT usBlackColorGY;
-	USHORT usBlackColorBCb;
-} BLANK_CRTC_PARAMETERS;
+/****************************************************************************/	
+// Structures used by BlankCRTCTable
+/****************************************************************************/	
+typedef struct _BLANK_CRTC_PARAMETERS
+{
+  UCHAR  ucCRTC;                    	// ATOM_CRTC1 or ATOM_CRTC2
+  UCHAR  ucBlanking;                  // ATOM_BLANKING or ATOM_BLANKINGOFF
+  USHORT usBlackColorRCr;
+  USHORT usBlackColorGY;
+  USHORT usBlackColorBCb;
+}BLANK_CRTC_PARAMETERS;
 #define BLANK_CRTC_PS_ALLOCATION    BLANK_CRTC_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by EnableCRTCTable */
-/*                     EnableCRTCMemReqTable */
-/*                     UpdateCRTC_DoubleBufferRegistersTable */
-/****************************************************************************/
-typedef struct _ENABLE_CRTC_PARAMETERS {
-	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
-	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
-	UCHAR ucPadding[2];
-} ENABLE_CRTC_PARAMETERS;
+/****************************************************************************/	
+// Structures used by EnableCRTCTable
+//                    EnableCRTCMemReqTable
+//                    UpdateCRTC_DoubleBufferRegistersTable
+/****************************************************************************/	
+typedef struct _ENABLE_CRTC_PARAMETERS
+{
+  UCHAR ucCRTC;                    	  // ATOM_CRTC1 or ATOM_CRTC2
+  UCHAR ucEnable;                     // ATOM_ENABLE or ATOM_DISABLE 
+  UCHAR ucPadding[2];
+}ENABLE_CRTC_PARAMETERS;
 #define ENABLE_CRTC_PS_ALLOCATION   ENABLE_CRTC_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by SetCRTC_OverScanTable */
-/****************************************************************************/
-typedef struct _SET_CRTC_OVERSCAN_PARAMETERS {
-	USHORT usOverscanRight;	/*  right */
-	USHORT usOverscanLeft;	/*  left */
-	USHORT usOverscanBottom;	/*  bottom */
-	USHORT usOverscanTop;	/*  top */
-	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
-	UCHAR ucPadding[3];
-} SET_CRTC_OVERSCAN_PARAMETERS;
+/****************************************************************************/	
+// Structures used by SetCRTC_OverScanTable
+/****************************************************************************/	
+typedef struct _SET_CRTC_OVERSCAN_PARAMETERS
+{
+  USHORT usOverscanRight;             // right
+  USHORT usOverscanLeft;              // left
+  USHORT usOverscanBottom;            // bottom
+  USHORT usOverscanTop;               // top
+  UCHAR  ucCRTC;                      // ATOM_CRTC1 or ATOM_CRTC2
+  UCHAR  ucPadding[3];
+}SET_CRTC_OVERSCAN_PARAMETERS;
 #define SET_CRTC_OVERSCAN_PS_ALLOCATION  SET_CRTC_OVERSCAN_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by SetCRTC_ReplicationTable */
-/****************************************************************************/
-typedef struct _SET_CRTC_REPLICATION_PARAMETERS {
-	UCHAR ucH_Replication;	/*  horizontal replication */
-	UCHAR ucV_Replication;	/*  vertical replication */
-	UCHAR usCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
-	UCHAR ucPadding;
-} SET_CRTC_REPLICATION_PARAMETERS;
+/****************************************************************************/	
+// Structures used by SetCRTC_ReplicationTable
+/****************************************************************************/	
+typedef struct _SET_CRTC_REPLICATION_PARAMETERS
+{
+  UCHAR ucH_Replication;              // horizontal replication
+  UCHAR ucV_Replication;              // vertical replication
+  UCHAR usCRTC;                       // ATOM_CRTC1 or ATOM_CRTC2
+  UCHAR ucPadding;
+}SET_CRTC_REPLICATION_PARAMETERS;
 #define SET_CRTC_REPLICATION_PS_ALLOCATION  SET_CRTC_REPLICATION_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by SelectCRTC_SourceTable */
-/****************************************************************************/
-typedef struct _SELECT_CRTC_SOURCE_PARAMETERS {
-	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
-	UCHAR ucDevice;		/*  ATOM_DEVICE_CRT1|ATOM_DEVICE_CRT2|.... */
-	UCHAR ucPadding[2];
-} SELECT_CRTC_SOURCE_PARAMETERS;
+/****************************************************************************/	
+// Structures used by SelectCRTC_SourceTable
+/****************************************************************************/	
+typedef struct _SELECT_CRTC_SOURCE_PARAMETERS
+{
+  UCHAR ucCRTC;                    	  // ATOM_CRTC1 or ATOM_CRTC2
+  UCHAR ucDevice;                     // ATOM_DEVICE_CRT1|ATOM_DEVICE_CRT2|....
+  UCHAR ucPadding[2];
+}SELECT_CRTC_SOURCE_PARAMETERS;
 #define SELECT_CRTC_SOURCE_PS_ALLOCATION  SELECT_CRTC_SOURCE_PARAMETERS
 
-typedef struct _SELECT_CRTC_SOURCE_PARAMETERS_V2 {
-	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
-	UCHAR ucEncoderID;	/*  DAC1/DAC2/TVOUT/DIG1/DIG2/DVO */
-	UCHAR ucEncodeMode;	/*  Encoding mode, only valid when using DIG1/DIG2/DVO */
-	UCHAR ucPadding;
-} SELECT_CRTC_SOURCE_PARAMETERS_V2;
+typedef struct _SELECT_CRTC_SOURCE_PARAMETERS_V2
+{
+  UCHAR ucCRTC;                    	  // ATOM_CRTC1 or ATOM_CRTC2
+  UCHAR ucEncoderID;                  // DAC1/DAC2/TVOUT/DIG1/DIG2/DVO
+  UCHAR ucEncodeMode;									// Encoding mode, only valid when using DIG1/DIG2/DVO
+  UCHAR ucPadding;
+}SELECT_CRTC_SOURCE_PARAMETERS_V2;
 
-/* ucEncoderID */
-/* #define ASIC_INT_DAC1_ENCODER_ID                                              0x00 */
-/* #define ASIC_INT_TV_ENCODER_ID                                                                        0x02 */
-/* #define ASIC_INT_DIG1_ENCODER_ID                                                              0x03 */
-/* #define ASIC_INT_DAC2_ENCODER_ID                                                              0x04 */
-/* #define ASIC_EXT_TV_ENCODER_ID                                                                        0x06 */
-/* #define ASIC_INT_DVO_ENCODER_ID                                                                       0x07 */
-/* #define ASIC_INT_DIG2_ENCODER_ID                                                              0x09 */
-/* #define ASIC_EXT_DIG_ENCODER_ID                                                                       0x05 */
+//ucEncoderID
+//#define ASIC_INT_DAC1_ENCODER_ID    						0x00 
+//#define ASIC_INT_TV_ENCODER_ID									0x02
+//#define ASIC_INT_DIG1_ENCODER_ID								0x03
+//#define ASIC_INT_DAC2_ENCODER_ID								0x04
+//#define ASIC_EXT_TV_ENCODER_ID									0x06
+//#define ASIC_INT_DVO_ENCODER_ID									0x07
+//#define ASIC_INT_DIG2_ENCODER_ID								0x09
+//#define ASIC_EXT_DIG_ENCODER_ID									0x05
 
-/* ucEncodeMode */
-/* #define ATOM_ENCODER_MODE_DP                                                                          0 */
-/* #define ATOM_ENCODER_MODE_LVDS                                                                        1 */
-/* #define ATOM_ENCODER_MODE_DVI                                                                         2 */
-/* #define ATOM_ENCODER_MODE_HDMI                                                                        3 */
-/* #define ATOM_ENCODER_MODE_SDVO                                                                        4 */
-/* #define ATOM_ENCODER_MODE_TV                                                                          13 */
-/* #define ATOM_ENCODER_MODE_CV                                                                          14 */
-/* #define ATOM_ENCODER_MODE_CRT                                                                         15 */
+//ucEncodeMode
+//#define ATOM_ENCODER_MODE_DP										0
+//#define ATOM_ENCODER_MODE_LVDS									1
+//#define ATOM_ENCODER_MODE_DVI										2
+//#define ATOM_ENCODER_MODE_HDMI									3
+//#define ATOM_ENCODER_MODE_SDVO									4
+//#define ATOM_ENCODER_MODE_TV										13
+//#define ATOM_ENCODER_MODE_CV										14
+//#define ATOM_ENCODER_MODE_CRT										15
 
-/****************************************************************************/
-/*  Structures used by SetPixelClockTable */
-/*                     GetPixelClockTable */
-/****************************************************************************/
-/* Major revision=1., Minor revision=1 */
-typedef struct _PIXEL_CLOCK_PARAMETERS {
-	USHORT usPixelClock;	/*  in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) */
-	/*  0 means disable PPLL */
-	USHORT usRefDiv;	/*  Reference divider */
-	USHORT usFbDiv;		/*  feedback divider */
-	UCHAR ucPostDiv;	/*  post divider */
-	UCHAR ucFracFbDiv;	/*  fractional feedback divider */
-	UCHAR ucPpll;		/*  ATOM_PPLL1 or ATOM_PPL2 */
-	UCHAR ucRefDivSrc;	/*  ATOM_PJITTER or ATO_NONPJITTER */
-	UCHAR ucCRTC;		/*  Which CRTC uses this Ppll */
-	UCHAR ucPadding;
-} PIXEL_CLOCK_PARAMETERS;
+/****************************************************************************/	
+// Structures used by SetPixelClockTable
+//                    GetPixelClockTable 
+/****************************************************************************/	
+//Major revision=1., Minor revision=1
+typedef struct _PIXEL_CLOCK_PARAMETERS
+{
+  USHORT usPixelClock;                // in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div)
+                                      // 0 means disable PPLL
+  USHORT usRefDiv;                    // Reference divider
+  USHORT usFbDiv;                     // feedback divider
+  UCHAR  ucPostDiv;                   // post divider	
+  UCHAR  ucFracFbDiv;                 // fractional feedback divider
+  UCHAR  ucPpll;                      // ATOM_PPLL1 or ATOM_PPL2
+  UCHAR  ucRefDivSrc;                 // ATOM_PJITTER or ATO_NONPJITTER
+  UCHAR  ucCRTC;                      // Which CRTC uses this Ppll
+  UCHAR  ucPadding;
+}PIXEL_CLOCK_PARAMETERS;
 
-/* Major revision=1., Minor revision=2, add ucMiscIfno */
-/* ucMiscInfo: */
+//Major revision=1., Minor revision=2, add ucMiscIfno
+//ucMiscInfo:
 #define MISC_FORCE_REPROG_PIXEL_CLOCK 0x1
 #define MISC_DEVICE_INDEX_MASK        0xF0
 #define MISC_DEVICE_INDEX_SHIFT       4
 
-typedef struct _PIXEL_CLOCK_PARAMETERS_V2 {
-	USHORT usPixelClock;	/*  in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) */
-	/*  0 means disable PPLL */
-	USHORT usRefDiv;	/*  Reference divider */
-	USHORT usFbDiv;		/*  feedback divider */
-	UCHAR ucPostDiv;	/*  post divider */
-	UCHAR ucFracFbDiv;	/*  fractional feedback divider */
-	UCHAR ucPpll;		/*  ATOM_PPLL1 or ATOM_PPL2 */
-	UCHAR ucRefDivSrc;	/*  ATOM_PJITTER or ATO_NONPJITTER */
-	UCHAR ucCRTC;		/*  Which CRTC uses this Ppll */
-	UCHAR ucMiscInfo;	/*  Different bits for different purpose, bit [7:4] as device index, bit[0]=Force prog */
-} PIXEL_CLOCK_PARAMETERS_V2;
+typedef struct _PIXEL_CLOCK_PARAMETERS_V2
+{
+  USHORT usPixelClock;                // in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div)
+                                      // 0 means disable PPLL
+  USHORT usRefDiv;                    // Reference divider
+  USHORT usFbDiv;                     // feedback divider
+  UCHAR  ucPostDiv;                   // post divider	
+  UCHAR  ucFracFbDiv;                 // fractional feedback divider
+  UCHAR  ucPpll;                      // ATOM_PPLL1 or ATOM_PPL2
+  UCHAR  ucRefDivSrc;                 // ATOM_PJITTER or ATO_NONPJITTER
+  UCHAR  ucCRTC;                      // Which CRTC uses this Ppll
+  UCHAR  ucMiscInfo;                  // Different bits for different purpose, bit [7:4] as device index, bit[0]=Force prog
+}PIXEL_CLOCK_PARAMETERS_V2;
 
-/* Major revision=1., Minor revision=3, structure/definition change */
-/* ucEncoderMode: */
-/* ATOM_ENCODER_MODE_DP */
-/* ATOM_ENOCDER_MODE_LVDS */
-/* ATOM_ENOCDER_MODE_DVI */
-/* ATOM_ENOCDER_MODE_HDMI */
-/* ATOM_ENOCDER_MODE_SDVO */
-/* ATOM_ENCODER_MODE_TV                                                                          13 */
-/* ATOM_ENCODER_MODE_CV                                                                          14 */
-/* ATOM_ENCODER_MODE_CRT                                                                         15 */
+//Major revision=1., Minor revision=3, structure/definition change
+//ucEncoderMode:
+//ATOM_ENCODER_MODE_DP
+//ATOM_ENOCDER_MODE_LVDS
+//ATOM_ENOCDER_MODE_DVI
+//ATOM_ENOCDER_MODE_HDMI
+//ATOM_ENOCDER_MODE_SDVO
+//ATOM_ENCODER_MODE_TV										13
+//ATOM_ENCODER_MODE_CV										14
+//ATOM_ENCODER_MODE_CRT										15
 
-/* ucDVOConfig */
-/* #define DVO_ENCODER_CONFIG_RATE_SEL                                                   0x01 */
-/* #define DVO_ENCODER_CONFIG_DDR_SPEED                                          0x00 */
-/* #define DVO_ENCODER_CONFIG_SDR_SPEED                                          0x01 */
-/* #define DVO_ENCODER_CONFIG_OUTPUT_SEL                                         0x0c */
-/* #define DVO_ENCODER_CONFIG_LOW12BIT                                                   0x00 */
-/* #define DVO_ENCODER_CONFIG_UPPER12BIT                                         0x04 */
-/* #define DVO_ENCODER_CONFIG_24BIT                                                              0x08 */
+//ucDVOConfig
+//#define DVO_ENCODER_CONFIG_RATE_SEL							0x01
+//#define DVO_ENCODER_CONFIG_DDR_SPEED						0x00
+//#define DVO_ENCODER_CONFIG_SDR_SPEED						0x01
+//#define DVO_ENCODER_CONFIG_OUTPUT_SEL						0x0c
+//#define DVO_ENCODER_CONFIG_LOW12BIT							0x00
+//#define DVO_ENCODER_CONFIG_UPPER12BIT						0x04
+//#define DVO_ENCODER_CONFIG_24BIT								0x08
 
-/* ucMiscInfo: also changed, see below */
+//ucMiscInfo: also changed, see below
 #define PIXEL_CLOCK_MISC_FORCE_PROG_PPLL						0x01
 #define PIXEL_CLOCK_MISC_VGA_MODE										0x02
 #define PIXEL_CLOCK_MISC_CRTC_SEL_MASK							0x04
 #define PIXEL_CLOCK_MISC_CRTC_SEL_CRTC1							0x00
 #define PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2							0x04
 #define PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK			0x08
+#define PIXEL_CLOCK_MISC_REF_DIV_SRC                    0x10
+// V1.4 for RoadRunner
+#define PIXEL_CLOCK_V4_MISC_SS_ENABLE               0x10
+#define PIXEL_CLOCK_V4_MISC_COHERENT_MODE           0x20
 
-typedef struct _PIXEL_CLOCK_PARAMETERS_V3 {
-	USHORT usPixelClock;	/*  in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) */
-	/*  0 means disable PPLL. For VGA PPLL,make sure this value is not 0. */
-	USHORT usRefDiv;	/*  Reference divider */
-	USHORT usFbDiv;		/*  feedback divider */
-	UCHAR ucPostDiv;	/*  post divider */
-	UCHAR ucFracFbDiv;	/*  fractional feedback divider */
-	UCHAR ucPpll;		/*  ATOM_PPLL1 or ATOM_PPL2 */
-	UCHAR ucTransmitterId;	/*  graphic encoder id defined in objectId.h */
-	union {
-		UCHAR ucEncoderMode;	/*  encoder type defined as ATOM_ENCODER_MODE_DP/DVI/HDMI/ */
-		UCHAR ucDVOConfig;	/*  when use DVO, need to know SDR/DDR, 12bit or 24bit */
+typedef struct _PIXEL_CLOCK_PARAMETERS_V3
+{
+  USHORT usPixelClock;                // in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div)
+                                      // 0 means disable PPLL. For VGA PPLL,make sure this value is not 0.
+  USHORT usRefDiv;                    // Reference divider
+  USHORT usFbDiv;                     // feedback divider
+  UCHAR  ucPostDiv;                   // post divider	
+  UCHAR  ucFracFbDiv;                 // fractional feedback divider
+  UCHAR  ucPpll;                      // ATOM_PPLL1 or ATOM_PPL2
+  UCHAR  ucTransmitterId;             // graphic encoder id defined in objectId.h
+	union
+	{
+  UCHAR  ucEncoderMode;               // encoder type defined as ATOM_ENCODER_MODE_DP/DVI/HDMI/
+	UCHAR  ucDVOConfig;									// when use DVO, need to know SDR/DDR, 12bit or 24bit
 	};
-	UCHAR ucMiscInfo;	/*  bit[0]=Force program, bit[1]= set pclk for VGA, b[2]= CRTC sel */
-	/*  bit[3]=0:use PPLL for dispclk source, =1: use engine clock for dispclock source */
-} PIXEL_CLOCK_PARAMETERS_V3;
+  UCHAR  ucMiscInfo;                  // bit[0]=Force program, bit[1]= set pclk for VGA, b[2]= CRTC sel
+                                      // bit[3]=0:use PPLL for dispclk source, =1: use engine clock for dispclock source
+                                      // bit[4]=0:use XTALIN as the source of reference divider,=1 use the pre-defined clock as the source of reference divider
+}PIXEL_CLOCK_PARAMETERS_V3;
 
 #define PIXEL_CLOCK_PARAMETERS_LAST			PIXEL_CLOCK_PARAMETERS_V2
 #define GET_PIXEL_CLOCK_PS_ALLOCATION		PIXEL_CLOCK_PARAMETERS_LAST
 
-/****************************************************************************/
-/*  Structures used by AdjustDisplayPllTable */
-/****************************************************************************/
-typedef struct _ADJUST_DISPLAY_PLL_PARAMETERS {
+typedef struct _PIXEL_CLOCK_PARAMETERS_V5
+{
+  UCHAR  ucCRTC;             // ATOM_CRTC1~6, indicate the CRTC controller to 
+                             // drive the pixel clock. not used for DCPLL case.
+  union{
+  UCHAR  ucReserved;
+  UCHAR  ucFracFbDiv;        // [gphan] temporary to prevent build problem.  remove it after driver code is changed.
+  };
+  USHORT usPixelClock;       // target the pixel clock to drive the CRTC timing
+                             // 0 means disable PPLL/DCPLL. 
+  USHORT usFbDiv;            // feedback divider integer part. 
+  UCHAR  ucPostDiv;          // post divider. 
+  UCHAR  ucRefDiv;           // Reference divider
+  UCHAR  ucPpll;             // ATOM_PPLL1/ATOM_PPLL2/ATOM_DCPLL
+  UCHAR  ucTransmitterID;    // ASIC encoder id defined in objectId.h, 
+                             // indicate which graphic encoder will be used. 
+  UCHAR  ucEncoderMode;      // Encoder mode: 
+  UCHAR  ucMiscInfo;         // bit[0]= Force program PPLL 
+                             // bit[1]= when VGA timing is used. 
+                             // bit[3:2]= HDMI panel bit depth: =0: 24bpp =1:30bpp, =2:32bpp
+                             // bit[4]= RefClock source for PPLL. 
+                             // =0: XTLAIN( default mode )
+	                           // =1: other external clock source, which is pre-defined
+                             //     by VBIOS depend on the feature required.
+                             // bit[7:5]: reserved.
+  ULONG  ulFbDivDecFrac;     // 20 bit feedback divider decimal fraction part, range from 1~999999 ( 0.000001 to 0.999999 )
+
+}PIXEL_CLOCK_PARAMETERS_V5;
+
+#define PIXEL_CLOCK_V5_MISC_FORCE_PROG_PPLL					0x01
+#define PIXEL_CLOCK_V5_MISC_VGA_MODE								0x02
+#define PIXEL_CLOCK_V5_MISC_HDMI_BPP_MASK           0x0c
+#define PIXEL_CLOCK_V5_MISC_HDMI_24BPP              0x00
+#define PIXEL_CLOCK_V5_MISC_HDMI_30BPP              0x04
+#define PIXEL_CLOCK_V5_MISC_HDMI_32BPP              0x08
+#define PIXEL_CLOCK_V5_MISC_REF_DIV_SRC             0x10
+
+typedef struct _GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V2
+{
+  PIXEL_CLOCK_PARAMETERS_V3 sDispClkInput;
+}GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V2;
+
+typedef struct _GET_DISP_PLL_STATUS_OUTPUT_PARAMETERS_V2
+{
+  UCHAR  ucStatus;
+  UCHAR  ucRefDivSrc;                 // =1: reference clock source from XTALIN, =0: source from PCIE ref clock
+  UCHAR  ucReserved[2];
+}GET_DISP_PLL_STATUS_OUTPUT_PARAMETERS_V2;
+
+typedef struct _GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V3
+{
+  PIXEL_CLOCK_PARAMETERS_V5 sDispClkInput;
+}GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V3;
+
+/****************************************************************************/	
+// Structures used by AdjustDisplayPllTable
+/****************************************************************************/	
+typedef struct _ADJUST_DISPLAY_PLL_PARAMETERS
+{
 	USHORT usPixelClock;
 	UCHAR ucTransmitterID;
 	UCHAR ucEncodeMode;
-	union {
-		UCHAR ucDVOConfig;	/* if DVO, need passing link rate and output 12bitlow or 24bit */
-		UCHAR ucConfig;	/* if none DVO, not defined yet */
+	union
+	{
+		UCHAR ucDVOConfig;									//if DVO, need passing link rate and output 12bitlow or 24bit
+		UCHAR ucConfig;											//if none DVO, not defined yet
 	};
 	UCHAR ucReserved[3];
-} ADJUST_DISPLAY_PLL_PARAMETERS;
+}ADJUST_DISPLAY_PLL_PARAMETERS;
 
 #define ADJUST_DISPLAY_CONFIG_SS_ENABLE       0x10
-
 #define ADJUST_DISPLAY_PLL_PS_ALLOCATION			ADJUST_DISPLAY_PLL_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by EnableYUVTable */
-/****************************************************************************/
-typedef struct _ENABLE_YUV_PARAMETERS {
-	UCHAR ucEnable;		/*  ATOM_ENABLE:Enable YUV or ATOM_DISABLE:Disable YUV (RGB) */
-	UCHAR ucCRTC;		/*  Which CRTC needs this YUV or RGB format */
-	UCHAR ucPadding[2];
-} ENABLE_YUV_PARAMETERS;
+typedef struct _ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3
+{
+	USHORT usPixelClock;                    // target pixel clock
+	UCHAR ucTransmitterID;                  // transmitter id defined in objectid.h
+	UCHAR ucEncodeMode;                     // encoder mode: CRT, LVDS, DP, TMDS or HDMI
+  UCHAR ucDispPllConfig;                 // display pll configure parameter defined as following DISPPLL_CONFIG_XXXX
+	UCHAR ucReserved[3];
+}ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3;
+
+// usDispPllConfig v1.2 for RoadRunner
+#define DISPPLL_CONFIG_DVO_RATE_SEL                0x0001     // need only when ucTransmitterID = DVO
+#define DISPPLL_CONFIG_DVO_DDR_SPEED               0x0000     // need only when ucTransmitterID = DVO
+#define DISPPLL_CONFIG_DVO_SDR_SPEED               0x0001     // need only when ucTransmitterID = DVO
+#define DISPPLL_CONFIG_DVO_OUTPUT_SEL              0x000c     // need only when ucTransmitterID = DVO
+#define DISPPLL_CONFIG_DVO_LOW12BIT                0x0000     // need only when ucTransmitterID = DVO
+#define DISPPLL_CONFIG_DVO_UPPER12BIT              0x0004     // need only when ucTransmitterID = DVO
+#define DISPPLL_CONFIG_DVO_24BIT                   0x0008     // need only when ucTransmitterID = DVO
+#define DISPPLL_CONFIG_SS_ENABLE                   0x0010     // Only used when ucEncoderMode = DP or LVDS
+#define DISPPLL_CONFIG_COHERENT_MODE               0x0020     // Only used when ucEncoderMode = TMDS or HDMI
+#define DISPPLL_CONFIG_DUAL_LINK                   0x0040     // Only used when ucEncoderMode = TMDS or LVDS
+
+
+typedef struct _ADJUST_DISPLAY_PLL_OUTPUT_PARAMETERS_V3
+{
+  ULONG ulDispPllFreq;                 // return display PPLL freq which is used to generate the pixclock, and related idclk, symclk etc
+  UCHAR ucRefDiv;                      // if it is none-zero, it is used to be calculated the other ppll parameter fb_divider and post_div ( if it is not given )
+  UCHAR ucPostDiv;                     // if it is none-zero, it is used to be calculated the other ppll parameter fb_divider
+  UCHAR ucReserved[2];  
+}ADJUST_DISPLAY_PLL_OUTPUT_PARAMETERS_V3;
+
+typedef struct _ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3
+{
+  union 
+  {
+    ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3  sInput;
+    ADJUST_DISPLAY_PLL_OUTPUT_PARAMETERS_V3 sOutput;
+  };
+} ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3;
+
+/****************************************************************************/	
+// Structures used by EnableYUVTable
+/****************************************************************************/	
+typedef struct _ENABLE_YUV_PARAMETERS
+{
+  UCHAR ucEnable;                     // ATOM_ENABLE:Enable YUV or ATOM_DISABLE:Disable YUV (RGB)
+  UCHAR ucCRTC;                       // Which CRTC needs this YUV or RGB format
+  UCHAR ucPadding[2];
+}ENABLE_YUV_PARAMETERS;
 #define ENABLE_YUV_PS_ALLOCATION ENABLE_YUV_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by GetMemoryClockTable */
-/****************************************************************************/
-typedef struct _GET_MEMORY_CLOCK_PARAMETERS {
-	ULONG ulReturnMemoryClock;	/*  current memory speed in 10KHz unit */
+/****************************************************************************/	
+// Structures used by GetMemoryClockTable
+/****************************************************************************/	
+typedef struct _GET_MEMORY_CLOCK_PARAMETERS
+{
+  ULONG ulReturnMemoryClock;          // current memory speed in 10KHz unit
 } GET_MEMORY_CLOCK_PARAMETERS;
 #define GET_MEMORY_CLOCK_PS_ALLOCATION  GET_MEMORY_CLOCK_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by GetEngineClockTable */
-/****************************************************************************/
-typedef struct _GET_ENGINE_CLOCK_PARAMETERS {
-	ULONG ulReturnEngineClock;	/*  current engine speed in 10KHz unit */
+/****************************************************************************/	
+// Structures used by GetEngineClockTable
+/****************************************************************************/	
+typedef struct _GET_ENGINE_CLOCK_PARAMETERS
+{
+  ULONG ulReturnEngineClock;          // current engine speed in 10KHz unit
 } GET_ENGINE_CLOCK_PARAMETERS;
 #define GET_ENGINE_CLOCK_PS_ALLOCATION  GET_ENGINE_CLOCK_PARAMETERS
 
-/****************************************************************************/
-/*  Following Structures and constant may be obsolete */
-/****************************************************************************/
-/* Maxium 8 bytes,the data read in will be placed in the parameter space. */
-/* Read operaion successeful when the paramter space is non-zero, otherwise read operation failed */
-typedef struct _READ_EDID_FROM_HW_I2C_DATA_PARAMETERS {
-	USHORT usPrescale;	/* Ratio between Engine clock and I2C clock */
-	USHORT usVRAMAddress;	/* Adress in Frame Buffer where to pace raw EDID */
-	USHORT usStatus;	/* When use output: lower byte EDID checksum, high byte hardware status */
-	/* WHen use input:  lower byte as 'byte to read':currently limited to 128byte or 1byte */
-	UCHAR ucSlaveAddr;	/* Read from which slave */
-	UCHAR ucLineNumber;	/* Read from which HW assisted line */
-} READ_EDID_FROM_HW_I2C_DATA_PARAMETERS;
+/****************************************************************************/	
+// Following Structures and constant may be obsolete
+/****************************************************************************/	
+//Maxium 8 bytes,the data read in will be placed in the parameter space.
+//Read operaion successeful when the paramter space is non-zero, otherwise read operation failed
+typedef struct _READ_EDID_FROM_HW_I2C_DATA_PARAMETERS
+{
+  USHORT    usPrescale;         //Ratio between Engine clock and I2C clock
+  USHORT    usVRAMAddress;      //Adress in Frame Buffer where to pace raw EDID
+  USHORT    usStatus;           //When use output: lower byte EDID checksum, high byte hardware status
+                                //WHen use input:  lower byte as 'byte to read':currently limited to 128byte or 1byte
+  UCHAR     ucSlaveAddr;        //Read from which slave
+  UCHAR     ucLineNumber;       //Read from which HW assisted line
+}READ_EDID_FROM_HW_I2C_DATA_PARAMETERS;
 #define READ_EDID_FROM_HW_I2C_DATA_PS_ALLOCATION  READ_EDID_FROM_HW_I2C_DATA_PARAMETERS
 
+
 #define  ATOM_WRITE_I2C_FORMAT_PSOFFSET_PSDATABYTE                  0
 #define  ATOM_WRITE_I2C_FORMAT_PSOFFSET_PSTWODATABYTES              1
 #define  ATOM_WRITE_I2C_FORMAT_PSCOUNTER_PSOFFSET_IDDATABLOCK       2
 #define  ATOM_WRITE_I2C_FORMAT_PSCOUNTER_IDOFFSET_PLUS_IDDATABLOCK  3
 #define  ATOM_WRITE_I2C_FORMAT_IDCOUNTER_IDOFFSET_IDDATABLOCK       4
 
-typedef struct _WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS {
-	USHORT usPrescale;	/* Ratio between Engine clock and I2C clock */
-	USHORT usByteOffset;	/* Write to which byte */
-	/* Upper portion of usByteOffset is Format of data */
-	/* 1bytePS+offsetPS */
-	/* 2bytesPS+offsetPS */
-	/* blockID+offsetPS */
-	/* blockID+offsetID */
-	/* blockID+counterID+offsetID */
-	UCHAR ucData;		/* PS data1 */
-	UCHAR ucStatus;		/* Status byte 1=success, 2=failure, Also is used as PS data2 */
-	UCHAR ucSlaveAddr;	/* Write to which slave */
-	UCHAR ucLineNumber;	/* Write from which HW assisted line */
-} WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS;
+typedef struct _WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS
+{
+  USHORT    usPrescale;         //Ratio between Engine clock and I2C clock
+  USHORT    usByteOffset;       //Write to which byte
+                                //Upper portion of usByteOffset is Format of data 
+                                //1bytePS+offsetPS
+                                //2bytesPS+offsetPS
+                                //blockID+offsetPS
+                                //blockID+offsetID
+                                //blockID+counterID+offsetID
+  UCHAR     ucData;             //PS data1
+  UCHAR     ucStatus;           //Status byte 1=success, 2=failure, Also is used as PS data2
+  UCHAR     ucSlaveAddr;        //Write to which slave
+  UCHAR     ucLineNumber;       //Write from which HW assisted line
+}WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS;
 
 #define WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION  WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS
 
-typedef struct _SET_UP_HW_I2C_DATA_PARAMETERS {
-	USHORT usPrescale;	/* Ratio between Engine clock and I2C clock */
-	UCHAR ucSlaveAddr;	/* Write to which slave */
-	UCHAR ucLineNumber;	/* Write from which HW assisted line */
-} SET_UP_HW_I2C_DATA_PARAMETERS;
+typedef struct _SET_UP_HW_I2C_DATA_PARAMETERS
+{
+  USHORT    usPrescale;         //Ratio between Engine clock and I2C clock
+  UCHAR     ucSlaveAddr;        //Write to which slave
+  UCHAR     ucLineNumber;       //Write from which HW assisted line
+}SET_UP_HW_I2C_DATA_PARAMETERS;
+
 
 /**************************************************************************/
 #define SPEED_FAN_CONTROL_PS_ALLOCATION   WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS
 
-/****************************************************************************/
-/*  Structures used by PowerConnectorDetectionTable */
-/****************************************************************************/
-typedef struct _POWER_CONNECTOR_DETECTION_PARAMETERS {
-	UCHAR ucPowerConnectorStatus;	/* Used for return value 0: detected, 1:not detected */
-	UCHAR ucPwrBehaviorId;
-	USHORT usPwrBudget;	/* how much power currently boot to in unit of watt */
-} POWER_CONNECTOR_DETECTION_PARAMETERS;
+/****************************************************************************/	
+// Structures used by PowerConnectorDetectionTable
+/****************************************************************************/	
+typedef struct	_POWER_CONNECTOR_DETECTION_PARAMETERS
+{
+  UCHAR   ucPowerConnectorStatus;      //Used for return value 0: detected, 1:not detected
+	UCHAR   ucPwrBehaviorId;							
+	USHORT	usPwrBudget;								 //how much power currently boot to in unit of watt
+}POWER_CONNECTOR_DETECTION_PARAMETERS;
 
-typedef struct POWER_CONNECTOR_DETECTION_PS_ALLOCATION {
-	UCHAR ucPowerConnectorStatus;	/* Used for return value 0: detected, 1:not detected */
-	UCHAR ucReserved;
-	USHORT usPwrBudget;	/* how much power currently boot to in unit of watt */
-	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;
-} POWER_CONNECTOR_DETECTION_PS_ALLOCATION;
+typedef struct POWER_CONNECTOR_DETECTION_PS_ALLOCATION
+{                               
+  UCHAR   ucPowerConnectorStatus;      //Used for return value 0: detected, 1:not detected
+	UCHAR   ucReserved;
+	USHORT	usPwrBudget;								 //how much power currently boot to in unit of watt
+  WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION    sReserved;
+}POWER_CONNECTOR_DETECTION_PS_ALLOCATION;
 
 /****************************LVDS SS Command Table Definitions**********************/
 
-/****************************************************************************/
-/*  Structures used by EnableSpreadSpectrumOnPPLLTable */
-/****************************************************************************/
-typedef struct _ENABLE_LVDS_SS_PARAMETERS {
-	USHORT usSpreadSpectrumPercentage;
-	UCHAR ucSpreadSpectrumType;	/* Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */
-	UCHAR ucSpreadSpectrumStepSize_Delay;	/* bits3:2 SS_STEP_SIZE; bit 6:4 SS_DELAY */
-	UCHAR ucEnable;		/* ATOM_ENABLE or ATOM_DISABLE */
-	UCHAR ucPadding[3];
-} ENABLE_LVDS_SS_PARAMETERS;
+/****************************************************************************/	
+// Structures used by EnableSpreadSpectrumOnPPLLTable
+/****************************************************************************/	
+typedef struct	_ENABLE_LVDS_SS_PARAMETERS
+{
+  USHORT  usSpreadSpectrumPercentage;       
+  UCHAR   ucSpreadSpectrumType;           //Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD
+  UCHAR   ucSpreadSpectrumStepSize_Delay; //bits3:2 SS_STEP_SIZE; bit 6:4 SS_DELAY
+  UCHAR   ucEnable;                       //ATOM_ENABLE or ATOM_DISABLE
+  UCHAR   ucPadding[3];
+}ENABLE_LVDS_SS_PARAMETERS;
 
-/* ucTableFormatRevision=1,ucTableContentRevision=2 */
-typedef struct _ENABLE_LVDS_SS_PARAMETERS_V2 {
-	USHORT usSpreadSpectrumPercentage;
-	UCHAR ucSpreadSpectrumType;	/* Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */
-	UCHAR ucSpreadSpectrumStep;	/*  */
-	UCHAR ucEnable;		/* ATOM_ENABLE or ATOM_DISABLE */
-	UCHAR ucSpreadSpectrumDelay;
-	UCHAR ucSpreadSpectrumRange;
-	UCHAR ucPadding;
-} ENABLE_LVDS_SS_PARAMETERS_V2;
+//ucTableFormatRevision=1,ucTableContentRevision=2
+typedef struct	_ENABLE_LVDS_SS_PARAMETERS_V2
+{
+  USHORT  usSpreadSpectrumPercentage;       
+  UCHAR   ucSpreadSpectrumType;           //Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD
+  UCHAR   ucSpreadSpectrumStep;           //
+  UCHAR   ucEnable;                       //ATOM_ENABLE or ATOM_DISABLE
+  UCHAR   ucSpreadSpectrumDelay;
+  UCHAR   ucSpreadSpectrumRange;
+  UCHAR   ucPadding;
+}ENABLE_LVDS_SS_PARAMETERS_V2;
 
-/* This new structure is based on ENABLE_LVDS_SS_PARAMETERS but expands to SS on PPLL, so other devices can use SS. */
-typedef struct _ENABLE_SPREAD_SPECTRUM_ON_PPLL {
-	USHORT usSpreadSpectrumPercentage;
-	UCHAR ucSpreadSpectrumType;	/*  Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */
-	UCHAR ucSpreadSpectrumStep;	/*  */
-	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
-	UCHAR ucSpreadSpectrumDelay;
-	UCHAR ucSpreadSpectrumRange;
-	UCHAR ucPpll;		/*  ATOM_PPLL1/ATOM_PPLL2 */
-} ENABLE_SPREAD_SPECTRUM_ON_PPLL;
+//This new structure is based on ENABLE_LVDS_SS_PARAMETERS but expands to SS on PPLL, so other devices can use SS.
+typedef struct	_ENABLE_SPREAD_SPECTRUM_ON_PPLL
+{
+  USHORT  usSpreadSpectrumPercentage;
+  UCHAR   ucSpreadSpectrumType;           // Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD
+  UCHAR   ucSpreadSpectrumStep;           //
+  UCHAR   ucEnable;                       // ATOM_ENABLE or ATOM_DISABLE
+  UCHAR   ucSpreadSpectrumDelay;
+  UCHAR   ucSpreadSpectrumRange;
+  UCHAR   ucPpll;												  // ATOM_PPLL1/ATOM_PPLL2
+}ENABLE_SPREAD_SPECTRUM_ON_PPLL;
+
+typedef struct _ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2
+{
+  USHORT  usSpreadSpectrumPercentage;
+  UCHAR   ucSpreadSpectrumType;	        // Bit[0]: 0-Down Spread,1-Center Spread. 
+                                        // Bit[1]: 1-Ext. 0-Int. 
+                                        // Bit[3:2]: =0 P1PLL =1 P2PLL =2 DCPLL
+                                        // Bits[7:4] reserved
+  UCHAR   ucEnable;	                    // ATOM_ENABLE or ATOM_DISABLE
+  USHORT  usSpreadSpectrumAmount;      	// Includes SS_AMOUNT_FBDIV[7:0] and SS_AMOUNT_NFRAC_SLIP[11:8]    
+  USHORT  usSpreadSpectrumStep;	        // SS_STEP_SIZE_DSFRAC
+}ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2;
+
+#define ATOM_PPLL_SS_TYPE_V2_DOWN_SPREAD      0x00
+#define ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD    0x01
+#define ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD       0x02
+#define ATOM_PPLL_SS_TYPE_V2_PPLL_SEL_MASK    0x0c
+#define ATOM_PPLL_SS_TYPE_V2_P1PLL            0x00
+#define ATOM_PPLL_SS_TYPE_V2_P2PLL            0x04
+#define ATOM_PPLL_SS_TYPE_V2_DCPLL            0x08
+#define ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK     0x00FF
+#define ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT    0
+#define ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK     0x0F00
+#define ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT    8
 
 #define ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION  ENABLE_SPREAD_SPECTRUM_ON_PPLL
 
 /**************************************************************************/
 
-typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION {
-	PIXEL_CLOCK_PARAMETERS sPCLKInput;
-	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;	/* Caller doesn't need to init this portion */
-} SET_PIXEL_CLOCK_PS_ALLOCATION;
+typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION
+{
+  PIXEL_CLOCK_PARAMETERS sPCLKInput;
+  ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;//Caller doesn't need to init this portion 
+}SET_PIXEL_CLOCK_PS_ALLOCATION;
 
 #define ENABLE_VGA_RENDER_PS_ALLOCATION   SET_PIXEL_CLOCK_PS_ALLOCATION
 
-/****************************************************************************/
-/*  Structures used by ### */
-/****************************************************************************/
-typedef struct _MEMORY_TRAINING_PARAMETERS {
-	ULONG ulTargetMemoryClock;	/* In 10Khz unit */
-} MEMORY_TRAINING_PARAMETERS;
+/****************************************************************************/	
+// Structures used by ###
+/****************************************************************************/	
+typedef struct	_MEMORY_TRAINING_PARAMETERS
+{
+  ULONG ulTargetMemoryClock;          //In 10Khz unit
+}MEMORY_TRAINING_PARAMETERS;
 #define MEMORY_TRAINING_PS_ALLOCATION MEMORY_TRAINING_PARAMETERS
 
+
 /****************************LVDS and other encoder command table definitions **********************/
 
-/****************************************************************************/
-/*  Structures used by LVDSEncoderControlTable   (Before DCE30) */
-/*                     LVTMAEncoderControlTable  (Before DCE30) */
-/*                     TMDSAEncoderControlTable  (Before DCE30) */
-/****************************************************************************/
-typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS {
-	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
-	UCHAR ucMisc;		/*  bit0=0: Enable single link */
-	/*      =1: Enable dual link */
-	/*  Bit1=0: 666RGB */
-	/*      =1: 888RGB */
-	UCHAR ucAction;		/*  0: turn off encoder */
-	/*  1: setup and turn on encoder */
-} LVDS_ENCODER_CONTROL_PARAMETERS;
+
+/****************************************************************************/	
+// Structures used by LVDSEncoderControlTable   (Before DCE30)
+//                    LVTMAEncoderControlTable  (Before DCE30)
+//                    TMDSAEncoderControlTable  (Before DCE30)
+/****************************************************************************/	
+typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS
+{
+  USHORT usPixelClock;  // in 10KHz; for bios convenient
+  UCHAR  ucMisc;        // bit0=0: Enable single link
+                        //     =1: Enable dual link
+                        // Bit1=0: 666RGB
+                        //     =1: 888RGB
+  UCHAR  ucAction;      // 0: turn off encoder
+                        // 1: setup and turn on encoder
+}LVDS_ENCODER_CONTROL_PARAMETERS;
 
 #define LVDS_ENCODER_CONTROL_PS_ALLOCATION  LVDS_ENCODER_CONTROL_PARAMETERS
-
+   
 #define TMDS1_ENCODER_CONTROL_PARAMETERS    LVDS_ENCODER_CONTROL_PARAMETERS
 #define TMDS1_ENCODER_CONTROL_PS_ALLOCATION TMDS1_ENCODER_CONTROL_PARAMETERS
 
 #define TMDS2_ENCODER_CONTROL_PARAMETERS    TMDS1_ENCODER_CONTROL_PARAMETERS
 #define TMDS2_ENCODER_CONTROL_PS_ALLOCATION TMDS2_ENCODER_CONTROL_PARAMETERS
 
-/* ucTableFormatRevision=1,ucTableContentRevision=2 */
-typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS_V2 {
-	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
-	UCHAR ucMisc;		/*  see PANEL_ENCODER_MISC_xx definitions below */
-	UCHAR ucAction;		/*  0: turn off encoder */
-	/*  1: setup and turn on encoder */
-	UCHAR ucTruncate;	/*  bit0=0: Disable truncate */
-	/*      =1: Enable truncate */
-	/*  bit4=0: 666RGB */
-	/*      =1: 888RGB */
-	UCHAR ucSpatial;	/*  bit0=0: Disable spatial dithering */
-	/*      =1: Enable spatial dithering */
-	/*  bit4=0: 666RGB */
-	/*      =1: 888RGB */
-	UCHAR ucTemporal;	/*  bit0=0: Disable temporal dithering */
-	/*      =1: Enable temporal dithering */
-	/*  bit4=0: 666RGB */
-	/*      =1: 888RGB */
-	/*  bit5=0: Gray level 2 */
-	/*      =1: Gray level 4 */
-	UCHAR ucFRC;		/*  bit4=0: 25FRC_SEL pattern E */
-	/*      =1: 25FRC_SEL pattern F */
-	/*  bit6:5=0: 50FRC_SEL pattern A */
-	/*        =1: 50FRC_SEL pattern B */
-	/*        =2: 50FRC_SEL pattern C */
-	/*        =3: 50FRC_SEL pattern D */
-	/*  bit7=0: 75FRC_SEL pattern E */
-	/*      =1: 75FRC_SEL pattern F */
-} LVDS_ENCODER_CONTROL_PARAMETERS_V2;
+
+//ucTableFormatRevision=1,ucTableContentRevision=2
+typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS_V2
+{
+  USHORT usPixelClock;  // in 10KHz; for bios convenient
+  UCHAR  ucMisc;        // see PANEL_ENCODER_MISC_xx defintions below
+  UCHAR  ucAction;      // 0: turn off encoder
+                        // 1: setup and turn on encoder
+  UCHAR  ucTruncate;    // bit0=0: Disable truncate
+                        //     =1: Enable truncate
+                        // bit4=0: 666RGB
+                        //     =1: 888RGB
+  UCHAR  ucSpatial;     // bit0=0: Disable spatial dithering
+                        //     =1: Enable spatial dithering
+                        // bit4=0: 666RGB
+                        //     =1: 888RGB
+  UCHAR  ucTemporal;    // bit0=0: Disable temporal dithering
+                        //     =1: Enable temporal dithering
+                        // bit4=0: 666RGB
+                        //     =1: 888RGB
+                        // bit5=0: Gray level 2
+                        //     =1: Gray level 4
+  UCHAR  ucFRC;         // bit4=0: 25FRC_SEL pattern E
+                        //     =1: 25FRC_SEL pattern F
+                        // bit6:5=0: 50FRC_SEL pattern A
+                        //       =1: 50FRC_SEL pattern B
+                        //       =2: 50FRC_SEL pattern C
+                        //       =3: 50FRC_SEL pattern D
+                        // bit7=0: 75FRC_SEL pattern E
+                        //     =1: 75FRC_SEL pattern F
+}LVDS_ENCODER_CONTROL_PARAMETERS_V2;
 
 #define LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2  LVDS_ENCODER_CONTROL_PARAMETERS_V2
-
+   
 #define TMDS1_ENCODER_CONTROL_PARAMETERS_V2    LVDS_ENCODER_CONTROL_PARAMETERS_V2
 #define TMDS1_ENCODER_CONTROL_PS_ALLOCATION_V2 TMDS1_ENCODER_CONTROL_PARAMETERS_V2
-
+  
 #define TMDS2_ENCODER_CONTROL_PARAMETERS_V2    TMDS1_ENCODER_CONTROL_PARAMETERS_V2
 #define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_V2 TMDS2_ENCODER_CONTROL_PARAMETERS_V2
 
@@ -1185,38 +1536,42 @@
 #define TMDS2_ENCODER_CONTROL_PARAMETERS_V3    LVDS_ENCODER_CONTROL_PARAMETERS_V3
 #define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_V3 TMDS2_ENCODER_CONTROL_PARAMETERS_V3
 
-/****************************************************************************/
-/*  Structures used by ### */
-/****************************************************************************/
-typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS {
-	UCHAR ucEnable;		/*  Enable or Disable External TMDS encoder */
-	UCHAR ucMisc;		/*  Bit0=0:Enable Single link;=1:Enable Dual link;Bit1 {=0:666RGB, =1:888RGB} */
-	UCHAR ucPadding[2];
-} ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS;
+/****************************************************************************/	
+// Structures used by ###
+/****************************************************************************/	
+typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS
+{                               
+  UCHAR    ucEnable;            // Enable or Disable External TMDS encoder
+  UCHAR    ucMisc;              // Bit0=0:Enable Single link;=1:Enable Dual link;Bit1 {=0:666RGB, =1:888RGB}
+  UCHAR    ucPadding[2];
+}ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS;
 
-typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION {
-	ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS sXTmdsEncoder;
-	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;	/* Caller doesn't need to init this portion */
-} ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION;
+typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION
+{                               
+  ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS    sXTmdsEncoder;
+  WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION   sReserved;     //Caller doesn't need to init this portion
+}ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION;
 
 #define ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS_V2  LVDS_ENCODER_CONTROL_PARAMETERS_V2
 
-typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION_V2 {
-	ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS_V2 sXTmdsEncoder;
-	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;	/* Caller doesn't need to init this portion */
-} ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION_V2;
+typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION_V2
+{                               
+  ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS_V2    sXTmdsEncoder;
+  WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION      sReserved;     //Caller doesn't need to init this portion
+}ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION_V2;
 
-typedef struct _EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION {
-	DIG_ENCODER_CONTROL_PARAMETERS sDigEncoder;
-	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;
-} EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION;
+typedef struct _EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION
+{
+  DIG_ENCODER_CONTROL_PARAMETERS            sDigEncoder;
+  WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;
+}EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION;
 
-/****************************************************************************/
-/*  Structures used by DVOEncoderControlTable */
-/****************************************************************************/
-/* ucTableFormatRevision=1,ucTableContentRevision=3 */
+/****************************************************************************/	
+// Structures used by DVOEncoderControlTable
+/****************************************************************************/	
+//ucTableFormatRevision=1,ucTableContentRevision=3
 
-/* ucDVOConfig: */
+//ucDVOConfig:
 #define DVO_ENCODER_CONFIG_RATE_SEL							0x01
 #define DVO_ENCODER_CONFIG_DDR_SPEED						0x00
 #define DVO_ENCODER_CONFIG_SDR_SPEED						0x01
@@ -1225,21 +1580,22 @@
 #define DVO_ENCODER_CONFIG_UPPER12BIT						0x04
 #define DVO_ENCODER_CONFIG_24BIT								0x08
 
-typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V3 {
-	USHORT usPixelClock;
-	UCHAR ucDVOConfig;
-	UCHAR ucAction;		/* ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT */
-	UCHAR ucReseved[4];
-} DVO_ENCODER_CONTROL_PARAMETERS_V3;
+typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V3
+{
+  USHORT usPixelClock; 
+  UCHAR  ucDVOConfig;
+  UCHAR  ucAction;														//ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT
+  UCHAR  ucReseved[4];
+}DVO_ENCODER_CONTROL_PARAMETERS_V3;
 #define DVO_ENCODER_CONTROL_PS_ALLOCATION_V3	DVO_ENCODER_CONTROL_PARAMETERS_V3
 
-/* ucTableFormatRevision=1 */
-/* ucTableContentRevision=3 structure is not changed but usMisc add bit 1 as another input for */
-/*  bit1=0: non-coherent mode */
-/*      =1: coherent mode */
+//ucTableFormatRevision=1
+//ucTableContentRevision=3 structure is not changed but usMisc add bit 1 as another input for 
+// bit1=0: non-coherent mode
+//     =1: coherent mode
 
-/* ========================================================================================== */
-/* Only change is here next time when changing encoder parameter definitions again! */
+//==========================================================================================
+//Only change is here next time when changing encoder parameter definitions again!
 #define LVDS_ENCODER_CONTROL_PARAMETERS_LAST     LVDS_ENCODER_CONTROL_PARAMETERS_V3
 #define LVDS_ENCODER_CONTROL_PS_ALLOCATION_LAST  LVDS_ENCODER_CONTROL_PARAMETERS_LAST
 
@@ -1252,7 +1608,7 @@
 #define DVO_ENCODER_CONTROL_PARAMETERS_LAST      DVO_ENCODER_CONTROL_PARAMETERS
 #define DVO_ENCODER_CONTROL_PS_ALLOCATION_LAST   DVO_ENCODER_CONTROL_PS_ALLOCATION
 
-/* ========================================================================================== */
+//==========================================================================================
 #define PANEL_ENCODER_MISC_DUAL                0x01
 #define PANEL_ENCODER_MISC_COHERENT            0x02
 #define	PANEL_ENCODER_MISC_TMDS_LINKB					 0x04
@@ -1281,159 +1637,159 @@
 #define PANEL_ENCODER_75FRC_E                  0x00
 #define PANEL_ENCODER_75FRC_F                  0x80
 
-/****************************************************************************/
-/*  Structures used by SetVoltageTable */
-/****************************************************************************/
+/****************************************************************************/	
+// Structures used by SetVoltageTable
+/****************************************************************************/	
 #define SET_VOLTAGE_TYPE_ASIC_VDDC             1
 #define SET_VOLTAGE_TYPE_ASIC_MVDDC            2
 #define SET_VOLTAGE_TYPE_ASIC_MVDDQ            3
 #define SET_VOLTAGE_TYPE_ASIC_VDDCI            4
 #define SET_VOLTAGE_INIT_MODE                  5
-#define SET_VOLTAGE_GET_MAX_VOLTAGE            6	/* Gets the Max. voltage for the soldered Asic */
+#define SET_VOLTAGE_GET_MAX_VOLTAGE            6					//Gets the Max. voltage for the soldered Asic
 
 #define SET_ASIC_VOLTAGE_MODE_ALL_SOURCE       0x1
 #define SET_ASIC_VOLTAGE_MODE_SOURCE_A         0x2
 #define SET_ASIC_VOLTAGE_MODE_SOURCE_B         0x4
 
 #define	SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE      0x0
-#define	SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL      0x1
+#define	SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL      0x1	
 #define	SET_ASIC_VOLTAGE_MODE_GET_GPIOMASK     0x2
 
-typedef struct _SET_VOLTAGE_PARAMETERS {
-	UCHAR ucVoltageType;	/*  To tell which voltage to set up, VDDC/MVDDC/MVDDQ */
-	UCHAR ucVoltageMode;	/*  To set all, to set source A or source B or ... */
-	UCHAR ucVoltageIndex;	/*  An index to tell which voltage level */
-	UCHAR ucReserved;
-} SET_VOLTAGE_PARAMETERS;
+typedef struct	_SET_VOLTAGE_PARAMETERS
+{
+  UCHAR    ucVoltageType;               // To tell which voltage to set up, VDDC/MVDDC/MVDDQ
+  UCHAR    ucVoltageMode;               // To set all, to set source A or source B or ...
+  UCHAR    ucVoltageIndex;              // An index to tell which voltage level
+  UCHAR    ucReserved;          
+}SET_VOLTAGE_PARAMETERS;
 
-typedef struct _SET_VOLTAGE_PARAMETERS_V2 {
-	UCHAR ucVoltageType;	/*  To tell which voltage to set up, VDDC/MVDDC/MVDDQ */
-	UCHAR ucVoltageMode;	/*  Not used, maybe use for state machine for differen power mode */
-	USHORT usVoltageLevel;	/*  real voltage level */
-} SET_VOLTAGE_PARAMETERS_V2;
+typedef struct	_SET_VOLTAGE_PARAMETERS_V2
+{
+  UCHAR    ucVoltageType;               // To tell which voltage to set up, VDDC/MVDDC/MVDDQ
+  UCHAR    ucVoltageMode;               // Not used, maybe use for state machine for differen power mode
+  USHORT   usVoltageLevel;              // real voltage level
+}SET_VOLTAGE_PARAMETERS_V2;
 
-typedef struct _SET_VOLTAGE_PS_ALLOCATION {
-	SET_VOLTAGE_PARAMETERS sASICSetVoltage;
-	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;
-} SET_VOLTAGE_PS_ALLOCATION;
+typedef struct _SET_VOLTAGE_PS_ALLOCATION
+{
+  SET_VOLTAGE_PARAMETERS sASICSetVoltage;
+  WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;
+}SET_VOLTAGE_PS_ALLOCATION;
 
-/****************************************************************************/
-/*  Structures used by TVEncoderControlTable */
-/****************************************************************************/
-typedef struct _TV_ENCODER_CONTROL_PARAMETERS {
-	USHORT usPixelClock;	/*  in 10KHz; for bios convenient */
-	UCHAR ucTvStandard;	/*  See definition "ATOM_TV_NTSC ..." */
-	UCHAR ucAction;		/*  0: turn off encoder */
-	/*  1: setup and turn on encoder */
-} TV_ENCODER_CONTROL_PARAMETERS;
+/****************************************************************************/	
+// Structures used by TVEncoderControlTable
+/****************************************************************************/	
+typedef struct _TV_ENCODER_CONTROL_PARAMETERS
+{
+  USHORT usPixelClock;                // in 10KHz; for bios convenient
+  UCHAR  ucTvStandard;                // See definition "ATOM_TV_NTSC ..."
+  UCHAR  ucAction;                    // 0: turn off encoder
+                                      // 1: setup and turn on encoder
+}TV_ENCODER_CONTROL_PARAMETERS;
 
-typedef struct _TV_ENCODER_CONTROL_PS_ALLOCATION {
-	TV_ENCODER_CONTROL_PARAMETERS sTVEncoder;
-	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;	/*  Don't set this one */
-} TV_ENCODER_CONTROL_PS_ALLOCATION;
+typedef struct _TV_ENCODER_CONTROL_PS_ALLOCATION
+{
+  TV_ENCODER_CONTROL_PARAMETERS sTVEncoder;          
+  WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION    sReserved; // Don't set this one
+}TV_ENCODER_CONTROL_PS_ALLOCATION;
 
-/* ==============================Data Table Portion==================================== */
+//==============================Data Table Portion====================================
 
-#ifdef	UEFI_BUILD
-#define	UTEMP	USHORT
-#define	USHORT	void*
-#endif
+/****************************************************************************/	
+// Structure used in Data.mtb
+/****************************************************************************/	
+typedef struct _ATOM_MASTER_LIST_OF_DATA_TABLES
+{
+  USHORT        UtilityPipeLine;	        // Offest for the utility to get parser info,Don't change this position!
+  USHORT        MultimediaCapabilityInfo; // Only used by MM Lib,latest version 1.1, not configuable from Bios, need to include the table to build Bios 
+  USHORT        MultimediaConfigInfo;     // Only used by MM Lib,latest version 2.1, not configuable from Bios, need to include the table to build Bios
+  USHORT        StandardVESA_Timing;      // Only used by Bios
+  USHORT        FirmwareInfo;             // Shared by various SW components,latest version 1.4
+  USHORT        DAC_Info;                 // Will be obsolete from R600
+  USHORT        LVDS_Info;                // Shared by various SW components,latest version 1.1 
+  USHORT        TMDS_Info;                // Will be obsolete from R600
+  USHORT        AnalogTV_Info;            // Shared by various SW components,latest version 1.1 
+  USHORT        SupportedDevicesInfo;     // Will be obsolete from R600
+  USHORT        GPIO_I2C_Info;            // Shared by various SW components,latest version 1.2 will be used from R600           
+  USHORT        VRAM_UsageByFirmware;     // Shared by various SW components,latest version 1.3 will be used from R600
+  USHORT        GPIO_Pin_LUT;             // Shared by various SW components,latest version 1.1
+  USHORT        VESA_ToInternalModeLUT;   // Only used by Bios
+  USHORT        ComponentVideoInfo;       // Shared by various SW components,latest version 2.1 will be used from R600
+  USHORT        PowerPlayInfo;            // Shared by various SW components,latest version 2.1,new design from R600
+  USHORT        CompassionateData;        // Will be obsolete from R600
+  USHORT        SaveRestoreInfo;          // Only used by Bios
+  USHORT        PPLL_SS_Info;             // Shared by various SW components,latest version 1.2, used to call SS_Info, change to new name because of int ASIC SS info
+  USHORT        OemInfo;                  // Defined and used by external SW, should be obsolete soon
+  USHORT        XTMDS_Info;               // Will be obsolete from R600
+  USHORT        MclkSS_Info;              // Shared by various SW components,latest version 1.1, only enabled when ext SS chip is used
+  USHORT        Object_Header;            // Shared by various SW components,latest version 1.1
+  USHORT        IndirectIOAccess;         // Only used by Bios,this table position can't change at all!!
+  USHORT        MC_InitParameter;         // Only used by command table
+  USHORT        ASIC_VDDC_Info;						// Will be obsolete from R600
+  USHORT        ASIC_InternalSS_Info;			// New tabel name from R600, used to be called "ASIC_MVDDC_Info"
+  USHORT        TV_VideoMode;							// Only used by command table
+  USHORT        VRAM_Info;								// Only used by command table, latest version 1.3
+  USHORT        MemoryTrainingInfo;				// Used for VBIOS and Diag utility for memory training purpose since R600. the new table rev start from 2.1
+  USHORT        IntegratedSystemInfo;			// Shared by various SW components
+  USHORT        ASIC_ProfilingInfo;				// New table name from R600, used to be called "ASIC_VDDCI_Info" for pre-R600
+  USHORT        VoltageObjectInfo;				// Shared by various SW components, latest version 1.1
+	USHORT				PowerSourceInfo;					// Shared by various SW components, latest versoin 1.1
+}ATOM_MASTER_LIST_OF_DATA_TABLES;
 
-/****************************************************************************/
-/*  Structure used in Data.mtb */
-/****************************************************************************/
-typedef struct _ATOM_MASTER_LIST_OF_DATA_TABLES {
-	USHORT UtilityPipeLine;	/*  Offest for the utility to get parser info,Don't change this position! */
-	USHORT MultimediaCapabilityInfo;	/*  Only used by MM Lib,latest version 1.1, not configuable from Bios, need to include the table to build Bios */
-	USHORT MultimediaConfigInfo;	/*  Only used by MM Lib,latest version 2.1, not configuable from Bios, need to include the table to build Bios */
-	USHORT StandardVESA_Timing;	/*  Only used by Bios */
-	USHORT FirmwareInfo;	/*  Shared by various SW components,latest version 1.4 */
-	USHORT DAC_Info;	/*  Will be obsolete from R600 */
-	USHORT LVDS_Info;	/*  Shared by various SW components,latest version 1.1 */
-	USHORT TMDS_Info;	/*  Will be obsolete from R600 */
-	USHORT AnalogTV_Info;	/*  Shared by various SW components,latest version 1.1 */
-	USHORT SupportedDevicesInfo;	/*  Will be obsolete from R600 */
-	USHORT GPIO_I2C_Info;	/*  Shared by various SW components,latest version 1.2 will be used from R600 */
-	USHORT VRAM_UsageByFirmware;	/*  Shared by various SW components,latest version 1.3 will be used from R600 */
-	USHORT GPIO_Pin_LUT;	/*  Shared by various SW components,latest version 1.1 */
-	USHORT VESA_ToInternalModeLUT;	/*  Only used by Bios */
-	USHORT ComponentVideoInfo;	/*  Shared by various SW components,latest version 2.1 will be used from R600 */
-	USHORT PowerPlayInfo;	/*  Shared by various SW components,latest version 2.1,new design from R600 */
-	USHORT CompassionateData;	/*  Will be obsolete from R600 */
-	USHORT SaveRestoreInfo;	/*  Only used by Bios */
-	USHORT PPLL_SS_Info;	/*  Shared by various SW components,latest version 1.2, used to call SS_Info, change to new name because of int ASIC SS info */
-	USHORT OemInfo;		/*  Defined and used by external SW, should be obsolete soon */
-	USHORT XTMDS_Info;	/*  Will be obsolete from R600 */
-	USHORT MclkSS_Info;	/*  Shared by various SW components,latest version 1.1, only enabled when ext SS chip is used */
-	USHORT Object_Header;	/*  Shared by various SW components,latest version 1.1 */
-	USHORT IndirectIOAccess;	/*  Only used by Bios,this table position can't change at all!! */
-	USHORT MC_InitParameter;	/*  Only used by command table */
-	USHORT ASIC_VDDC_Info;	/*  Will be obsolete from R600 */
-	USHORT ASIC_InternalSS_Info;	/*  New tabel name from R600, used to be called "ASIC_MVDDC_Info" */
-	USHORT TV_VideoMode;	/*  Only used by command table */
-	USHORT VRAM_Info;	/*  Only used by command table, latest version 1.3 */
-	USHORT MemoryTrainingInfo;	/*  Used for VBIOS and Diag utility for memory training purpose since R600. the new table rev start from 2.1 */
-	USHORT IntegratedSystemInfo;	/*  Shared by various SW components */
-	USHORT ASIC_ProfilingInfo;	/*  New table name from R600, used to be called "ASIC_VDDCI_Info" for pre-R600 */
-	USHORT VoltageObjectInfo;	/*  Shared by various SW components, latest version 1.1 */
-	USHORT PowerSourceInfo;	/*  Shared by various SW components, latest versoin 1.1 */
-} ATOM_MASTER_LIST_OF_DATA_TABLES;
+typedef struct _ATOM_MASTER_DATA_TABLE
+{ 
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  ATOM_MASTER_LIST_OF_DATA_TABLES   ListOfDataTables;
+}ATOM_MASTER_DATA_TABLE;
 
-#ifdef	UEFI_BUILD
-#define	USHORT	UTEMP
-#endif
+/****************************************************************************/	
+// Structure used in MultimediaCapabilityInfoTable
+/****************************************************************************/	
+typedef struct _ATOM_MULTIMEDIA_CAPABILITY_INFO
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  ULONG                    ulSignature;      // HW info table signature string "$ATI"
+  UCHAR                    ucI2C_Type;       // I2C type (normal GP_IO, ImpactTV GP_IO, Dedicated I2C pin, etc)
+  UCHAR                    ucTV_OutInfo;     // Type of TV out supported (3:0) and video out crystal frequency (6:4) and TV data port (7)
+  UCHAR                    ucVideoPortInfo;  // Provides the video port capabilities
+  UCHAR                    ucHostPortInfo;   // Provides host port configuration information
+}ATOM_MULTIMEDIA_CAPABILITY_INFO;
 
-typedef struct _ATOM_MASTER_DATA_TABLE {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_MASTER_LIST_OF_DATA_TABLES ListOfDataTables;
-} ATOM_MASTER_DATA_TABLE;
+/****************************************************************************/	
+// Structure used in MultimediaConfigInfoTable
+/****************************************************************************/	
+typedef struct _ATOM_MULTIMEDIA_CONFIG_INFO
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;
+  ULONG                    ulSignature;      // MM info table signature sting "$MMT"
+  UCHAR                    ucTunerInfo;      // Type of tuner installed on the adapter (4:0) and video input for tuner (7:5)
+  UCHAR                    ucAudioChipInfo;  // List the audio chip type (3:0) product type (4) and OEM revision (7:5)
+  UCHAR                    ucProductID;      // Defines as OEM ID or ATI board ID dependent on product type setting
+  UCHAR                    ucMiscInfo1;      // Tuner voltage (1:0) HW teletext support (3:2) FM audio decoder (5:4) reserved (6) audio scrambling (7)
+  UCHAR                    ucMiscInfo2;      // I2S input config (0) I2S output config (1) I2S Audio Chip (4:2) SPDIF Output Config (5) reserved (7:6)
+  UCHAR                    ucMiscInfo3;      // Video Decoder Type (3:0) Video In Standard/Crystal (7:4)
+  UCHAR                    ucMiscInfo4;      // Video Decoder Host Config (2:0) reserved (7:3)
+  UCHAR                    ucVideoInput0Info;// Video Input 0 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6)
+  UCHAR                    ucVideoInput1Info;// Video Input 1 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6)
+  UCHAR                    ucVideoInput2Info;// Video Input 2 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6)
+  UCHAR                    ucVideoInput3Info;// Video Input 3 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6)
+  UCHAR                    ucVideoInput4Info;// Video Input 4 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6)
+}ATOM_MULTIMEDIA_CONFIG_INFO;
 
-/****************************************************************************/
-/*  Structure used in MultimediaCapabilityInfoTable */
-/****************************************************************************/
-typedef struct _ATOM_MULTIMEDIA_CAPABILITY_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ULONG ulSignature;	/*  HW info table signature string "$ATI" */
-	UCHAR ucI2C_Type;	/*  I2C type (normal GP_IO, ImpactTV GP_IO, Dedicated I2C pin, etc) */
-	UCHAR ucTV_OutInfo;	/*  Type of TV out supported (3:0) and video out crystal frequency (6:4) and TV data port (7) */
-	UCHAR ucVideoPortInfo;	/*  Provides the video port capabilities */
-	UCHAR ucHostPortInfo;	/*  Provides host port configuration information */
-} ATOM_MULTIMEDIA_CAPABILITY_INFO;
+/****************************************************************************/	
+// Structures used in FirmwareInfoTable
+/****************************************************************************/	
 
-/****************************************************************************/
-/*  Structure used in MultimediaConfigInfoTable */
-/****************************************************************************/
-typedef struct _ATOM_MULTIMEDIA_CONFIG_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ULONG ulSignature;	/*  MM info table signature sting "$MMT" */
-	UCHAR ucTunerInfo;	/*  Type of tuner installed on the adapter (4:0) and video input for tuner (7:5) */
-	UCHAR ucAudioChipInfo;	/*  List the audio chip type (3:0) product type (4) and OEM revision (7:5) */
-	UCHAR ucProductID;	/*  Defines as OEM ID or ATI board ID dependent on product type setting */
-	UCHAR ucMiscInfo1;	/*  Tuner voltage (1:0) HW teletext support (3:2) FM audio decoder (5:4) reserved (6) audio scrambling (7) */
-	UCHAR ucMiscInfo2;	/*  I2S input config (0) I2S output config (1) I2S Audio Chip (4:2) SPDIF Output Config (5) reserved (7:6) */
-	UCHAR ucMiscInfo3;	/*  Video Decoder Type (3:0) Video In Standard/Crystal (7:4) */
-	UCHAR ucMiscInfo4;	/*  Video Decoder Host Config (2:0) reserved (7:3) */
-	UCHAR ucVideoInput0Info;	/*  Video Input 0 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */
-	UCHAR ucVideoInput1Info;	/*  Video Input 1 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */
-	UCHAR ucVideoInput2Info;	/*  Video Input 2 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */
-	UCHAR ucVideoInput3Info;	/*  Video Input 3 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */
-	UCHAR ucVideoInput4Info;	/*  Video Input 4 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */
-} ATOM_MULTIMEDIA_CONFIG_INFO;
-
-/****************************************************************************/
-/*  Structures used in FirmwareInfoTable */
-/****************************************************************************/
-
-/*  usBIOSCapability Definition: */
-/*  Bit 0 = 0: Bios image is not Posted, =1:Bios image is Posted; */
-/*  Bit 1 = 0: Dual CRTC is not supported, =1: Dual CRTC is supported; */
-/*  Bit 2 = 0: Extended Desktop is not supported, =1: Extended Desktop is supported; */
-/*  Others: Reserved */
+// usBIOSCapability Defintion:
+// Bit 0 = 0: Bios image is not Posted, =1:Bios image is Posted; 
+// Bit 1 = 0: Dual CRTC is not supported, =1: Dual CRTC is supported; 
+// Bit 2 = 0: Extended Desktop is not supported, =1: Extended Desktop is supported; 
+// Others: Reserved
 #define ATOM_BIOS_INFO_ATOM_FIRMWARE_POSTED         0x0001
 #define ATOM_BIOS_INFO_DUAL_CRTC_SUPPORT            0x0002
 #define ATOM_BIOS_INFO_EXTENDED_DESKTOP_SUPPORT     0x0004
-#define ATOM_BIOS_INFO_MEMORY_CLOCK_SS_SUPPORT      0x0008
-#define ATOM_BIOS_INFO_ENGINE_CLOCK_SS_SUPPORT      0x0010
+#define ATOM_BIOS_INFO_MEMORY_CLOCK_SS_SUPPORT      0x0008		// (valid from v1.1 ~v1.4):=1: memclk SS enable, =0 memclk SS disable. 
+#define ATOM_BIOS_INFO_ENGINE_CLOCK_SS_SUPPORT      0x0010		// (valid from v1.1 ~v1.4):=1: engclk SS enable, =0 engclk SS disable. 
 #define ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU         0x0020
 #define ATOM_BIOS_INFO_WMI_SUPPORT                  0x0040
 #define ATOM_BIOS_INFO_PPMODE_ASSIGNGED_BY_SYSTEM   0x0080
@@ -1441,242 +1797,292 @@
 #define ATOM_BIOS_INFO_HYPERMEMORY_SIZE_MASK        0x1E00
 #define ATOM_BIOS_INFO_VPOST_WITHOUT_FIRST_MODE_SET 0x2000
 #define ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE  0x4000
+#define ATOM_BIOS_INFO_MEMORY_CLOCK_EXT_SS_SUPPORT  0x0008		// (valid from v2.1 ): =1: memclk ss enable with external ss chip
+#define ATOM_BIOS_INFO_ENGINE_CLOCK_EXT_SS_SUPPORT  0x0010		// (valid from v2.1 ): =1: engclk ss enable with external ss chip
 
 #ifndef _H2INC
 
-/* Please don't add or expand this bitfield structure below, this one will retire soon.! */
-typedef struct _ATOM_FIRMWARE_CAPABILITY {
+//Please don't add or expand this bitfield structure below, this one will retire soon.!
+typedef struct _ATOM_FIRMWARE_CAPABILITY
+{
 #if ATOM_BIG_ENDIAN
-	USHORT Reserved:3;
-	USHORT HyperMemory_Size:4;
-	USHORT HyperMemory_Support:1;
-	USHORT PPMode_Assigned:1;
-	USHORT WMI_SUPPORT:1;
-	USHORT GPUControlsBL:1;
-	USHORT EngineClockSS_Support:1;
-	USHORT MemoryClockSS_Support:1;
-	USHORT ExtendedDesktopSupport:1;
-	USHORT DualCRTC_Support:1;
-	USHORT FirmwarePosted:1;
+  USHORT Reserved:3;
+  USHORT HyperMemory_Size:4;
+  USHORT HyperMemory_Support:1;
+  USHORT PPMode_Assigned:1;
+  USHORT WMI_SUPPORT:1;
+  USHORT GPUControlsBL:1;
+  USHORT EngineClockSS_Support:1;
+  USHORT MemoryClockSS_Support:1;
+  USHORT ExtendedDesktopSupport:1;
+  USHORT DualCRTC_Support:1;
+  USHORT FirmwarePosted:1;
 #else
-	USHORT FirmwarePosted:1;
-	USHORT DualCRTC_Support:1;
-	USHORT ExtendedDesktopSupport:1;
-	USHORT MemoryClockSS_Support:1;
-	USHORT EngineClockSS_Support:1;
-	USHORT GPUControlsBL:1;
-	USHORT WMI_SUPPORT:1;
-	USHORT PPMode_Assigned:1;
-	USHORT HyperMemory_Support:1;
-	USHORT HyperMemory_Size:4;
-	USHORT Reserved:3;
+  USHORT FirmwarePosted:1;
+  USHORT DualCRTC_Support:1;
+  USHORT ExtendedDesktopSupport:1;
+  USHORT MemoryClockSS_Support:1;
+  USHORT EngineClockSS_Support:1;
+  USHORT GPUControlsBL:1;
+  USHORT WMI_SUPPORT:1;
+  USHORT PPMode_Assigned:1;
+  USHORT HyperMemory_Support:1;
+  USHORT HyperMemory_Size:4;
+  USHORT Reserved:3;
 #endif
-} ATOM_FIRMWARE_CAPABILITY;
+}ATOM_FIRMWARE_CAPABILITY;
 
-typedef union _ATOM_FIRMWARE_CAPABILITY_ACCESS {
-	ATOM_FIRMWARE_CAPABILITY sbfAccess;
-	USHORT susAccess;
-} ATOM_FIRMWARE_CAPABILITY_ACCESS;
+typedef union _ATOM_FIRMWARE_CAPABILITY_ACCESS
+{
+  ATOM_FIRMWARE_CAPABILITY sbfAccess;
+  USHORT                   susAccess;
+}ATOM_FIRMWARE_CAPABILITY_ACCESS;
 
 #else
 
-typedef union _ATOM_FIRMWARE_CAPABILITY_ACCESS {
-	USHORT susAccess;
-} ATOM_FIRMWARE_CAPABILITY_ACCESS;
+typedef union _ATOM_FIRMWARE_CAPABILITY_ACCESS
+{
+  USHORT                   susAccess;
+}ATOM_FIRMWARE_CAPABILITY_ACCESS;
 
 #endif
 
-typedef struct _ATOM_FIRMWARE_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ULONG ulFirmwareRevision;
-	ULONG ulDefaultEngineClock;	/* In 10Khz unit */
-	ULONG ulDefaultMemoryClock;	/* In 10Khz unit */
-	ULONG ulDriverTargetEngineClock;	/* In 10Khz unit */
-	ULONG ulDriverTargetMemoryClock;	/* In 10Khz unit */
-	ULONG ulMaxEngineClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulMaxMemoryClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulMaxPixelClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulASICMaxEngineClock;	/* In 10Khz unit */
-	ULONG ulASICMaxMemoryClock;	/* In 10Khz unit */
-	UCHAR ucASICMaxTemperature;
-	UCHAR ucPadding[3];	/* Don't use them */
-	ULONG aulReservedForBIOS[3];	/* Don't use them */
-	USHORT usMinEngineClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxEngineClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinEngineClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMinMemoryClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxMemoryClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinMemoryClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMaxPixelClock;	/* In 10Khz unit, Max.  Pclk */
-	USHORT usMinPixelClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxPixelClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinPixelClockPLL_Output;	/* In 10Khz unit, the definitions above can't change!!! */
-	ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
-	USHORT usReferenceClock;	/* In 10Khz unit */
-	USHORT usPM_RTS_Location;	/* RTS PM4 starting location in ROM in 1Kb unit */
-	UCHAR ucPM_RTS_StreamSize;	/* RTS PM4 packets in Kb unit */
-	UCHAR ucDesign_ID;	/* Indicate what is the board design */
-	UCHAR ucMemoryModule_ID;	/* Indicate what is the board design */
-} ATOM_FIRMWARE_INFO;
+typedef struct _ATOM_FIRMWARE_INFO
+{
+  ATOM_COMMON_TABLE_HEADER        sHeader; 
+  ULONG                           ulFirmwareRevision;
+  ULONG                           ulDefaultEngineClock;       //In 10Khz unit
+  ULONG                           ulDefaultMemoryClock;       //In 10Khz unit
+  ULONG                           ulDriverTargetEngineClock;  //In 10Khz unit
+  ULONG                           ulDriverTargetMemoryClock;  //In 10Khz unit
+  ULONG                           ulMaxEngineClockPLL_Output; //In 10Khz unit
+  ULONG                           ulMaxMemoryClockPLL_Output; //In 10Khz unit
+  ULONG                           ulMaxPixelClockPLL_Output;  //In 10Khz unit
+  ULONG                           ulASICMaxEngineClock;       //In 10Khz unit
+  ULONG                           ulASICMaxMemoryClock;       //In 10Khz unit
+  UCHAR                           ucASICMaxTemperature;
+  UCHAR                           ucPadding[3];               //Don't use them
+  ULONG                           aulReservedForBIOS[3];      //Don't use them
+  USHORT                          usMinEngineClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMaxEngineClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMinEngineClockPLL_Output; //In 10Khz unit
+  USHORT                          usMinMemoryClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMaxMemoryClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMinMemoryClockPLL_Output; //In 10Khz unit
+  USHORT                          usMaxPixelClock;            //In 10Khz unit, Max.  Pclk
+  USHORT                          usMinPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMaxPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMinPixelClockPLL_Output;  //In 10Khz unit, the definitions above can't change!!!
+  ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
+  USHORT                          usReferenceClock;           //In 10Khz unit	
+  USHORT                          usPM_RTS_Location;          //RTS PM4 starting location in ROM in 1Kb unit 
+  UCHAR                           ucPM_RTS_StreamSize;        //RTS PM4 packets in Kb unit
+  UCHAR                           ucDesign_ID;                //Indicate what is the board design
+  UCHAR                           ucMemoryModule_ID;          //Indicate what is the board design
+}ATOM_FIRMWARE_INFO;
 
-typedef struct _ATOM_FIRMWARE_INFO_V1_2 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ULONG ulFirmwareRevision;
-	ULONG ulDefaultEngineClock;	/* In 10Khz unit */
-	ULONG ulDefaultMemoryClock;	/* In 10Khz unit */
-	ULONG ulDriverTargetEngineClock;	/* In 10Khz unit */
-	ULONG ulDriverTargetMemoryClock;	/* In 10Khz unit */
-	ULONG ulMaxEngineClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulMaxMemoryClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulMaxPixelClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulASICMaxEngineClock;	/* In 10Khz unit */
-	ULONG ulASICMaxMemoryClock;	/* In 10Khz unit */
-	UCHAR ucASICMaxTemperature;
-	UCHAR ucMinAllowedBL_Level;
-	UCHAR ucPadding[2];	/* Don't use them */
-	ULONG aulReservedForBIOS[2];	/* Don't use them */
-	ULONG ulMinPixelClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMinEngineClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxEngineClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinEngineClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMinMemoryClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxMemoryClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinMemoryClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMaxPixelClock;	/* In 10Khz unit, Max.  Pclk */
-	USHORT usMinPixelClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxPixelClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinPixelClockPLL_Output;	/* In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output */
-	ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
-	USHORT usReferenceClock;	/* In 10Khz unit */
-	USHORT usPM_RTS_Location;	/* RTS PM4 starting location in ROM in 1Kb unit */
-	UCHAR ucPM_RTS_StreamSize;	/* RTS PM4 packets in Kb unit */
-	UCHAR ucDesign_ID;	/* Indicate what is the board design */
-	UCHAR ucMemoryModule_ID;	/* Indicate what is the board design */
-} ATOM_FIRMWARE_INFO_V1_2;
+typedef struct _ATOM_FIRMWARE_INFO_V1_2
+{
+  ATOM_COMMON_TABLE_HEADER        sHeader; 
+  ULONG                           ulFirmwareRevision;
+  ULONG                           ulDefaultEngineClock;       //In 10Khz unit
+  ULONG                           ulDefaultMemoryClock;       //In 10Khz unit
+  ULONG                           ulDriverTargetEngineClock;  //In 10Khz unit
+  ULONG                           ulDriverTargetMemoryClock;  //In 10Khz unit
+  ULONG                           ulMaxEngineClockPLL_Output; //In 10Khz unit
+  ULONG                           ulMaxMemoryClockPLL_Output; //In 10Khz unit
+  ULONG                           ulMaxPixelClockPLL_Output;  //In 10Khz unit
+  ULONG                           ulASICMaxEngineClock;       //In 10Khz unit
+  ULONG                           ulASICMaxMemoryClock;       //In 10Khz unit
+  UCHAR                           ucASICMaxTemperature;
+  UCHAR                           ucMinAllowedBL_Level;
+  UCHAR                           ucPadding[2];               //Don't use them
+  ULONG                           aulReservedForBIOS[2];      //Don't use them
+  ULONG                           ulMinPixelClockPLL_Output;  //In 10Khz unit
+  USHORT                          usMinEngineClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMaxEngineClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMinEngineClockPLL_Output; //In 10Khz unit
+  USHORT                          usMinMemoryClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMaxMemoryClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMinMemoryClockPLL_Output; //In 10Khz unit
+  USHORT                          usMaxPixelClock;            //In 10Khz unit, Max.  Pclk
+  USHORT                          usMinPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMaxPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMinPixelClockPLL_Output;  //In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output
+  ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
+  USHORT                          usReferenceClock;           //In 10Khz unit	
+  USHORT                          usPM_RTS_Location;          //RTS PM4 starting location in ROM in 1Kb unit 
+  UCHAR                           ucPM_RTS_StreamSize;        //RTS PM4 packets in Kb unit
+  UCHAR                           ucDesign_ID;                //Indicate what is the board design
+  UCHAR                           ucMemoryModule_ID;          //Indicate what is the board design
+}ATOM_FIRMWARE_INFO_V1_2;
 
-typedef struct _ATOM_FIRMWARE_INFO_V1_3 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ULONG ulFirmwareRevision;
-	ULONG ulDefaultEngineClock;	/* In 10Khz unit */
-	ULONG ulDefaultMemoryClock;	/* In 10Khz unit */
-	ULONG ulDriverTargetEngineClock;	/* In 10Khz unit */
-	ULONG ulDriverTargetMemoryClock;	/* In 10Khz unit */
-	ULONG ulMaxEngineClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulMaxMemoryClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulMaxPixelClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulASICMaxEngineClock;	/* In 10Khz unit */
-	ULONG ulASICMaxMemoryClock;	/* In 10Khz unit */
-	UCHAR ucASICMaxTemperature;
-	UCHAR ucMinAllowedBL_Level;
-	UCHAR ucPadding[2];	/* Don't use them */
-	ULONG aulReservedForBIOS;	/* Don't use them */
-	ULONG ul3DAccelerationEngineClock;	/* In 10Khz unit */
-	ULONG ulMinPixelClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMinEngineClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxEngineClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinEngineClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMinMemoryClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxMemoryClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinMemoryClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMaxPixelClock;	/* In 10Khz unit, Max.  Pclk */
-	USHORT usMinPixelClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxPixelClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinPixelClockPLL_Output;	/* In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output */
-	ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
-	USHORT usReferenceClock;	/* In 10Khz unit */
-	USHORT usPM_RTS_Location;	/* RTS PM4 starting location in ROM in 1Kb unit */
-	UCHAR ucPM_RTS_StreamSize;	/* RTS PM4 packets in Kb unit */
-	UCHAR ucDesign_ID;	/* Indicate what is the board design */
-	UCHAR ucMemoryModule_ID;	/* Indicate what is the board design */
-} ATOM_FIRMWARE_INFO_V1_3;
+typedef struct _ATOM_FIRMWARE_INFO_V1_3
+{
+  ATOM_COMMON_TABLE_HEADER        sHeader; 
+  ULONG                           ulFirmwareRevision;
+  ULONG                           ulDefaultEngineClock;       //In 10Khz unit
+  ULONG                           ulDefaultMemoryClock;       //In 10Khz unit
+  ULONG                           ulDriverTargetEngineClock;  //In 10Khz unit
+  ULONG                           ulDriverTargetMemoryClock;  //In 10Khz unit
+  ULONG                           ulMaxEngineClockPLL_Output; //In 10Khz unit
+  ULONG                           ulMaxMemoryClockPLL_Output; //In 10Khz unit
+  ULONG                           ulMaxPixelClockPLL_Output;  //In 10Khz unit
+  ULONG                           ulASICMaxEngineClock;       //In 10Khz unit
+  ULONG                           ulASICMaxMemoryClock;       //In 10Khz unit
+  UCHAR                           ucASICMaxTemperature;
+  UCHAR                           ucMinAllowedBL_Level;
+  UCHAR                           ucPadding[2];               //Don't use them
+  ULONG                           aulReservedForBIOS;         //Don't use them
+  ULONG                           ul3DAccelerationEngineClock;//In 10Khz unit
+  ULONG                           ulMinPixelClockPLL_Output;  //In 10Khz unit
+  USHORT                          usMinEngineClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMaxEngineClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMinEngineClockPLL_Output; //In 10Khz unit
+  USHORT                          usMinMemoryClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMaxMemoryClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMinMemoryClockPLL_Output; //In 10Khz unit
+  USHORT                          usMaxPixelClock;            //In 10Khz unit, Max.  Pclk
+  USHORT                          usMinPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMaxPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMinPixelClockPLL_Output;  //In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output
+  ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
+  USHORT                          usReferenceClock;           //In 10Khz unit	
+  USHORT                          usPM_RTS_Location;          //RTS PM4 starting location in ROM in 1Kb unit 
+  UCHAR                           ucPM_RTS_StreamSize;        //RTS PM4 packets in Kb unit
+  UCHAR                           ucDesign_ID;                //Indicate what is the board design
+  UCHAR                           ucMemoryModule_ID;          //Indicate what is the board design
+}ATOM_FIRMWARE_INFO_V1_3;
 
-typedef struct _ATOM_FIRMWARE_INFO_V1_4 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ULONG ulFirmwareRevision;
-	ULONG ulDefaultEngineClock;	/* In 10Khz unit */
-	ULONG ulDefaultMemoryClock;	/* In 10Khz unit */
-	ULONG ulDriverTargetEngineClock;	/* In 10Khz unit */
-	ULONG ulDriverTargetMemoryClock;	/* In 10Khz unit */
-	ULONG ulMaxEngineClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulMaxMemoryClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulMaxPixelClockPLL_Output;	/* In 10Khz unit */
-	ULONG ulASICMaxEngineClock;	/* In 10Khz unit */
-	ULONG ulASICMaxMemoryClock;	/* In 10Khz unit */
-	UCHAR ucASICMaxTemperature;
-	UCHAR ucMinAllowedBL_Level;
-	USHORT usBootUpVDDCVoltage;	/* In MV unit */
-	USHORT usLcdMinPixelClockPLL_Output;	/*  In MHz unit */
-	USHORT usLcdMaxPixelClockPLL_Output;	/*  In MHz unit */
-	ULONG ul3DAccelerationEngineClock;	/* In 10Khz unit */
-	ULONG ulMinPixelClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMinEngineClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxEngineClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinEngineClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMinMemoryClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxMemoryClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinMemoryClockPLL_Output;	/* In 10Khz unit */
-	USHORT usMaxPixelClock;	/* In 10Khz unit, Max.  Pclk */
-	USHORT usMinPixelClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMaxPixelClockPLL_Input;	/* In 10Khz unit */
-	USHORT usMinPixelClockPLL_Output;	/* In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output */
-	ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
-	USHORT usReferenceClock;	/* In 10Khz unit */
-	USHORT usPM_RTS_Location;	/* RTS PM4 starting location in ROM in 1Kb unit */
-	UCHAR ucPM_RTS_StreamSize;	/* RTS PM4 packets in Kb unit */
-	UCHAR ucDesign_ID;	/* Indicate what is the board design */
-	UCHAR ucMemoryModule_ID;	/* Indicate what is the board design */
-} ATOM_FIRMWARE_INFO_V1_4;
+typedef struct _ATOM_FIRMWARE_INFO_V1_4
+{
+  ATOM_COMMON_TABLE_HEADER        sHeader; 
+  ULONG                           ulFirmwareRevision;
+  ULONG                           ulDefaultEngineClock;       //In 10Khz unit
+  ULONG                           ulDefaultMemoryClock;       //In 10Khz unit
+  ULONG                           ulDriverTargetEngineClock;  //In 10Khz unit
+  ULONG                           ulDriverTargetMemoryClock;  //In 10Khz unit
+  ULONG                           ulMaxEngineClockPLL_Output; //In 10Khz unit
+  ULONG                           ulMaxMemoryClockPLL_Output; //In 10Khz unit
+  ULONG                           ulMaxPixelClockPLL_Output;  //In 10Khz unit
+  ULONG                           ulASICMaxEngineClock;       //In 10Khz unit
+  ULONG                           ulASICMaxMemoryClock;       //In 10Khz unit
+  UCHAR                           ucASICMaxTemperature;
+  UCHAR                           ucMinAllowedBL_Level;
+  USHORT                          usBootUpVDDCVoltage;        //In MV unit
+  USHORT                          usLcdMinPixelClockPLL_Output; // In MHz unit
+  USHORT                          usLcdMaxPixelClockPLL_Output; // In MHz unit
+  ULONG                           ul3DAccelerationEngineClock;//In 10Khz unit
+  ULONG                           ulMinPixelClockPLL_Output;  //In 10Khz unit
+  USHORT                          usMinEngineClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMaxEngineClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMinEngineClockPLL_Output; //In 10Khz unit
+  USHORT                          usMinMemoryClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMaxMemoryClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMinMemoryClockPLL_Output; //In 10Khz unit
+  USHORT                          usMaxPixelClock;            //In 10Khz unit, Max.  Pclk
+  USHORT                          usMinPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMaxPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMinPixelClockPLL_Output;  //In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output
+  ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
+  USHORT                          usReferenceClock;           //In 10Khz unit	
+  USHORT                          usPM_RTS_Location;          //RTS PM4 starting location in ROM in 1Kb unit 
+  UCHAR                           ucPM_RTS_StreamSize;        //RTS PM4 packets in Kb unit
+  UCHAR                           ucDesign_ID;                //Indicate what is the board design
+  UCHAR                           ucMemoryModule_ID;          //Indicate what is the board design
+}ATOM_FIRMWARE_INFO_V1_4;
 
-#define ATOM_FIRMWARE_INFO_LAST  ATOM_FIRMWARE_INFO_V1_4
+//the structure below to be used from Cypress
+typedef struct _ATOM_FIRMWARE_INFO_V2_1
+{
+  ATOM_COMMON_TABLE_HEADER        sHeader; 
+  ULONG                           ulFirmwareRevision;
+  ULONG                           ulDefaultEngineClock;       //In 10Khz unit
+  ULONG                           ulDefaultMemoryClock;       //In 10Khz unit
+  ULONG                           ulReserved1;
+  ULONG                           ulReserved2;
+  ULONG                           ulMaxEngineClockPLL_Output; //In 10Khz unit
+  ULONG                           ulMaxMemoryClockPLL_Output; //In 10Khz unit
+  ULONG                           ulMaxPixelClockPLL_Output;  //In 10Khz unit
+  ULONG                           ulBinaryAlteredInfo;        //Was ulASICMaxEngineClock
+  ULONG                           ulDefaultDispEngineClkFreq; //In 10Khz unit
+  UCHAR                           ucReserved1;                //Was ucASICMaxTemperature;
+  UCHAR                           ucMinAllowedBL_Level;
+  USHORT                          usBootUpVDDCVoltage;        //In MV unit
+  USHORT                          usLcdMinPixelClockPLL_Output; // In MHz unit
+  USHORT                          usLcdMaxPixelClockPLL_Output; // In MHz unit
+  ULONG                           ulReserved4;                //Was ulAsicMaximumVoltage
+  ULONG                           ulMinPixelClockPLL_Output;  //In 10Khz unit
+  USHORT                          usMinEngineClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMaxEngineClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMinEngineClockPLL_Output; //In 10Khz unit
+  USHORT                          usMinMemoryClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMaxMemoryClockPLL_Input;  //In 10Khz unit
+  USHORT                          usMinMemoryClockPLL_Output; //In 10Khz unit
+  USHORT                          usMaxPixelClock;            //In 10Khz unit, Max.  Pclk
+  USHORT                          usMinPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMaxPixelClockPLL_Input;   //In 10Khz unit
+  USHORT                          usMinPixelClockPLL_Output;  //In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output
+  ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability;
+  USHORT                          usCoreReferenceClock;       //In 10Khz unit	
+  USHORT                          usMemoryReferenceClock;     //In 10Khz unit	
+  USHORT                          usUniphyDPModeExtClkFreq;   //In 10Khz unit, if it is 0, In DP Mode Uniphy Input clock from internal PPLL, otherwise Input clock from external Spread clock
+  UCHAR                           ucMemoryModule_ID;          //Indicate what is the board design
+  UCHAR                           ucReserved4[3];
+}ATOM_FIRMWARE_INFO_V2_1;
 
-/****************************************************************************/
-/*  Structures used in IntegratedSystemInfoTable */
-/****************************************************************************/
+
+#define ATOM_FIRMWARE_INFO_LAST  ATOM_FIRMWARE_INFO_V2_1
+
+/****************************************************************************/	
+// Structures used in IntegratedSystemInfoTable
+/****************************************************************************/	
 #define IGP_CAP_FLAG_DYNAMIC_CLOCK_EN      0x2
 #define IGP_CAP_FLAG_AC_CARD               0x4
 #define IGP_CAP_FLAG_SDVO_CARD             0x8
 #define IGP_CAP_FLAG_POSTDIV_BY_2_MODE     0x10
 
-typedef struct _ATOM_INTEGRATED_SYSTEM_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ULONG ulBootUpEngineClock;	/* in 10kHz unit */
-	ULONG ulBootUpMemoryClock;	/* in 10kHz unit */
-	ULONG ulMaxSystemMemoryClock;	/* in 10kHz unit */
-	ULONG ulMinSystemMemoryClock;	/* in 10kHz unit */
-	UCHAR ucNumberOfCyclesInPeriodHi;
-	UCHAR ucLCDTimingSel;	/* =0:not valid.!=0 sel this timing descriptor from LCD EDID. */
-	USHORT usReserved1;
-	USHORT usInterNBVoltageLow;	/* An intermidiate PMW value to set the voltage */
-	USHORT usInterNBVoltageHigh;	/* Another intermidiate PMW value to set the voltage */
-	ULONG ulReserved[2];
+typedef struct _ATOM_INTEGRATED_SYSTEM_INFO
+{
+  ATOM_COMMON_TABLE_HEADER        sHeader; 
+  ULONG	                          ulBootUpEngineClock;		    //in 10kHz unit
+  ULONG	                          ulBootUpMemoryClock;		    //in 10kHz unit
+  ULONG	                          ulMaxSystemMemoryClock;	    //in 10kHz unit
+  ULONG	                          ulMinSystemMemoryClock;	    //in 10kHz unit
+  UCHAR                           ucNumberOfCyclesInPeriodHi;
+  UCHAR                           ucLCDTimingSel;             //=0:not valid.!=0 sel this timing descriptor from LCD EDID.
+  USHORT                          usReserved1;
+  USHORT                          usInterNBVoltageLow;        //An intermidiate PMW value to set the voltage 
+  USHORT                          usInterNBVoltageHigh;       //Another intermidiate PMW value to set the voltage 
+  ULONG	                          ulReserved[2];
 
-	USHORT usFSBClock;	/* In MHz unit */
-	USHORT usCapabilityFlag;	/* Bit0=1 indicates the fake HDMI support,Bit1=0/1 for Dynamic clocking dis/enable */
-	/* Bit[3:2]== 0:No PCIE card, 1:AC card, 2:SDVO card */
-	/* Bit[4]==1: P/2 mode, ==0: P/1 mode */
-	USHORT usPCIENBCfgReg7;	/* bit[7:0]=MUX_Sel, bit[9:8]=MUX_SEL_LEVEL2, bit[10]=Lane_Reversal */
-	USHORT usK8MemoryClock;	/* in MHz unit */
-	USHORT usK8SyncStartDelay;	/* in 0.01 us unit */
-	USHORT usK8DataReturnTime;	/* in 0.01 us unit */
-	UCHAR ucMaxNBVoltage;
-	UCHAR ucMinNBVoltage;
-	UCHAR ucMemoryType;	/* [7:4]=1:DDR1;=2:DDR2;=3:DDR3.[3:0] is reserved */
-	UCHAR ucNumberOfCyclesInPeriod;	/* CG.FVTHROT_PWM_CTRL_REG0.NumberOfCyclesInPeriod */
-	UCHAR ucStartingPWM_HighTime;	/* CG.FVTHROT_PWM_CTRL_REG0.StartingPWM_HighTime */
-	UCHAR ucHTLinkWidth;	/* 16 bit vs. 8 bit */
-	UCHAR ucMaxNBVoltageHigh;
-	UCHAR ucMinNBVoltageHigh;
-} ATOM_INTEGRATED_SYSTEM_INFO;
+  USHORT	                        usFSBClock;			            //In MHz unit
+  USHORT                          usCapabilityFlag;		        //Bit0=1 indicates the fake HDMI support,Bit1=0/1 for Dynamic clocking dis/enable
+																                              //Bit[3:2]== 0:No PCIE card, 1:AC card, 2:SDVO card
+                                                              //Bit[4]==1: P/2 mode, ==0: P/1 mode
+  USHORT	                        usPCIENBCfgReg7;				    //bit[7:0]=MUX_Sel, bit[9:8]=MUX_SEL_LEVEL2, bit[10]=Lane_Reversal
+  USHORT	                        usK8MemoryClock;            //in MHz unit
+  USHORT	                        usK8SyncStartDelay;         //in 0.01 us unit
+  USHORT	                        usK8DataReturnTime;         //in 0.01 us unit
+  UCHAR                           ucMaxNBVoltage;
+  UCHAR                           ucMinNBVoltage;
+  UCHAR                           ucMemoryType;					      //[7:4]=1:DDR1;=2:DDR2;=3:DDR3.[3:0] is reserved
+  UCHAR                           ucNumberOfCyclesInPeriod;		//CG.FVTHROT_PWM_CTRL_REG0.NumberOfCyclesInPeriod 
+  UCHAR                           ucStartingPWM_HighTime;     //CG.FVTHROT_PWM_CTRL_REG0.StartingPWM_HighTime
+  UCHAR                           ucHTLinkWidth;              //16 bit vs. 8 bit
+  UCHAR                           ucMaxNBVoltageHigh;    
+  UCHAR                           ucMinNBVoltageHigh;
+}ATOM_INTEGRATED_SYSTEM_INFO;
 
 /* Explanation on entries in ATOM_INTEGRATED_SYSTEM_INFO
-ulBootUpMemoryClock:    For Intel IGP,it's the UMA system memory clock
+ulBootUpMemoryClock:    For Intel IGP,it's the UMA system memory clock 
                         For AMD IGP,it's 0 if no SidePort memory installed or it's the boot-up SidePort memory clock
 ulMaxSystemMemoryClock: For Intel IGP,it's the Max freq from memory SPD if memory runs in ASYNC mode or otherwise (SYNC mode) it's 0
                         For AMD IGP,for now this can be 0
-ulMinSystemMemoryClock: For Intel IGP,it's 133MHz if memory runs in ASYNC mode or otherwise (SYNC mode) it's 0
+ulMinSystemMemoryClock: For Intel IGP,it's 133MHz if memory runs in ASYNC mode or otherwise (SYNC mode) it's 0 
                         For AMD IGP,for now this can be 0
 
-usFSBClock:             For Intel IGP,it's FSB Freq
+usFSBClock:             For Intel IGP,it's FSB Freq 
                         For AMD IGP,it's HT Link Speed
 
 usK8MemoryClock:        For AMD IGP only. For RevF CPU, set it to 200
@@ -1687,98 +2093,113 @@
 ucMaxNBVoltage:         Voltage regulator dependent PWM value. Low 8 bits of the value for the max voltage.Set this one to 0xFF if VC without PWM. Set this to 0x0 if no VC at all.
 ucMinNBVoltage:         Voltage regulator dependent PWM value. Low 8 bits of the value for the min voltage.Set this one to 0x00 if VC without PWM or no VC at all.
 
-ucNumberOfCyclesInPeriod:   Indicate how many cycles when PWM duty is 100%. low 8 bits of the value.
-ucNumberOfCyclesInPeriodHi: Indicate how many cycles when PWM duty is 100%. high 8 bits of the value.If the PWM has an inverter,set bit [7]==1,otherwise set it 0
+ucNumberOfCyclesInPeriod:   Indicate how many cycles when PWM duty is 100%. low 8 bits of the value. 
+ucNumberOfCyclesInPeriodHi: Indicate how many cycles when PWM duty is 100%. high 8 bits of the value.If the PWM has an inverter,set bit [7]==1,otherwise set it 0 
 
 ucMaxNBVoltageHigh:     Voltage regulator dependent PWM value. High 8 bits of  the value for the max voltage.Set this one to 0xFF if VC without PWM. Set this to 0x0 if no VC at all.
 ucMinNBVoltageHigh:     Voltage regulator dependent PWM value. High 8 bits of the value for the min voltage.Set this one to 0x00 if VC without PWM or no VC at all.
 
+
 usInterNBVoltageLow:    Voltage regulator dependent PWM value. The value makes the the voltage >=Min NB voltage but <=InterNBVoltageHigh. Set this to 0x0000 if VC without PWM or no VC at all.
 usInterNBVoltageHigh:   Voltage regulator dependent PWM value. The value makes the the voltage >=InterNBVoltageLow but <=Max NB voltage.Set this to 0x0000 if VC without PWM or no VC at all.
 */
 
+
 /*
 The following IGP table is introduced from RS780, which is supposed to be put by SBIOS in FB before IGP VBIOS starts VPOST;
-Then VBIOS will copy the whole structure to its image so all GPU SW components can access this data structure to get whatever they need.
+Then VBIOS will copy the whole structure to its image so all GPU SW components can access this data structure to get whatever they need. 
 The enough reservation should allow us to never change table revisions. Whenever needed, a GPU SW component can use reserved portion for new data entries.
 
 SW components can access the IGP system infor structure in the same way as before
 */
 
-typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ULONG ulBootUpEngineClock;	/* in 10kHz unit */
-	ULONG ulReserved1[2];	/* must be 0x0 for the reserved */
-	ULONG ulBootUpUMAClock;	/* in 10kHz unit */
-	ULONG ulBootUpSidePortClock;	/* in 10kHz unit */
-	ULONG ulMinSidePortClock;	/* in 10kHz unit */
-	ULONG ulReserved2[6];	/* must be 0x0 for the reserved */
-	ULONG ulSystemConfig;	/* see explanation below */
-	ULONG ulBootUpReqDisplayVector;
-	ULONG ulOtherDisplayMisc;
-	ULONG ulDDISlot1Config;
-	ULONG ulDDISlot2Config;
-	UCHAR ucMemoryType;	/* [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved */
-	UCHAR ucUMAChannelNumber;
-	UCHAR ucDockingPinBit;
-	UCHAR ucDockingPinPolarity;
-	ULONG ulDockingPinCFGInfo;
-	ULONG ulCPUCapInfo;
-	USHORT usNumberOfCyclesInPeriod;
-	USHORT usMaxNBVoltage;
-	USHORT usMinNBVoltage;
-	USHORT usBootUpNBVoltage;
-	ULONG ulHTLinkFreq;	/* in 10Khz */
-	USHORT usMinHTLinkWidth;
-	USHORT usMaxHTLinkWidth;
-	USHORT usUMASyncStartDelay;
-	USHORT usUMADataReturnTime;
-	USHORT usLinkStatusZeroTime;
-	USHORT usReserved;
-	ULONG ulHighVoltageHTLinkFreq;	/*  in 10Khz */
-	ULONG ulLowVoltageHTLinkFreq;	/*  in 10Khz */
-	USHORT usMaxUpStreamHTLinkWidth;
-	USHORT usMaxDownStreamHTLinkWidth;
-	USHORT usMinUpStreamHTLinkWidth;
-	USHORT usMinDownStreamHTLinkWidth;
-	ULONG ulReserved3[97];	/* must be 0x0 */
-} ATOM_INTEGRATED_SYSTEM_INFO_V2;
+
+typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V2
+{
+  ATOM_COMMON_TABLE_HEADER   sHeader;
+  ULONG	                     ulBootUpEngineClock;       //in 10kHz unit
+  ULONG			     ulReserved1[2];            //must be 0x0 for the reserved
+  ULONG	                     ulBootUpUMAClock;          //in 10kHz unit
+  ULONG	                     ulBootUpSidePortClock;     //in 10kHz unit
+  ULONG	                     ulMinSidePortClock;        //in 10kHz unit
+  ULONG			     ulReserved2[6];            //must be 0x0 for the reserved
+  ULONG                      ulSystemConfig;            //see explanation below
+  ULONG                      ulBootUpReqDisplayVector;
+  ULONG                      ulOtherDisplayMisc;
+  ULONG                      ulDDISlot1Config;
+  ULONG                      ulDDISlot2Config;
+  UCHAR                      ucMemoryType;              //[3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved
+  UCHAR                      ucUMAChannelNumber;
+  UCHAR                      ucDockingPinBit;
+  UCHAR                      ucDockingPinPolarity;
+  ULONG                      ulDockingPinCFGInfo;
+  ULONG                      ulCPUCapInfo;
+  USHORT                     usNumberOfCyclesInPeriod;
+  USHORT                     usMaxNBVoltage;
+  USHORT                     usMinNBVoltage;
+  USHORT                     usBootUpNBVoltage;
+  ULONG                      ulHTLinkFreq;              //in 10Khz
+  USHORT                     usMinHTLinkWidth;
+  USHORT                     usMaxHTLinkWidth;
+  USHORT                     usUMASyncStartDelay;
+  USHORT                     usUMADataReturnTime;
+  USHORT                     usLinkStatusZeroTime;
+  USHORT                     usDACEfuse;				//for storing badgap value (for RS880 only)
+  ULONG                      ulHighVoltageHTLinkFreq;     // in 10Khz
+  ULONG                      ulLowVoltageHTLinkFreq;      // in 10Khz
+  USHORT                     usMaxUpStreamHTLinkWidth;
+  USHORT                     usMaxDownStreamHTLinkWidth;
+  USHORT                     usMinUpStreamHTLinkWidth;
+  USHORT                     usMinDownStreamHTLinkWidth;
+  USHORT                     usFirmwareVersion;         //0 means FW is not supported. Otherwise it's the FW version loaded by SBIOS and driver should enable FW.
+  USHORT                     usFullT0Time;             // Input to calculate minimum HT link change time required by NB P-State. Unit is 0.01us.
+  ULONG                      ulReserved3[96];          //must be 0x0
+}ATOM_INTEGRATED_SYSTEM_INFO_V2;   
 
 /*
 ulBootUpEngineClock:   Boot-up Engine Clock in 10Khz;
 ulBootUpUMAClock:      Boot-up UMA Clock in 10Khz; it must be 0x0 when UMA is not present
 ulBootUpSidePortClock: Boot-up SidePort Clock in 10Khz; it must be 0x0 when SidePort Memory is not present,this could be equal to or less than maximum supported Sideport memory clock
 
-ulSystemConfig:
-Bit[0]=1: PowerExpress mode =0 Non-PowerExpress mode;
+ulSystemConfig:  
+Bit[0]=1: PowerExpress mode =0 Non-PowerExpress mode; 
 Bit[1]=1: system boots up at AMD overdrived state or user customized  mode. In this case, driver will just stick to this boot-up mode. No other PowerPlay state
       =0: system boots up at driver control state. Power state depends on PowerPlay table.
 Bit[2]=1: PWM method is used on NB voltage control. =0: GPIO method is used.
 Bit[3]=1: Only one power state(Performance) will be supported.
       =0: Multiple power states supported from PowerPlay table.
-Bit[4]=1: CLMC is supported and enabled on current system.
-      =0: CLMC is not supported or enabled on current system. SBIOS need to support HT link/freq change through ATIF interface.
-Bit[5]=1: Enable CDLW for all driver control power states. Max HT width is from SBIOS, while Min HT width is determined by display requirement.
+Bit[4]=1: CLMC is supported and enabled on current system. 
+      =0: CLMC is not supported or enabled on current system. SBIOS need to support HT link/freq change through ATIF interface.  
+Bit[5]=1: Enable CDLW for all driver control power states. Max HT width is from SBIOS, while Min HT width is determined by display requirement.  
       =0: CDLW is disabled. If CLMC is enabled case, Min HT width will be set equal to Max HT width. If CLMC disabled case, Max HT width will be applied.
 Bit[6]=1: High Voltage requested for all power states. In this case, voltage will be forced at 1.1v and powerplay table voltage drop/throttling request will be ignored.
       =0: Voltage settings is determined by powerplay table.
 Bit[7]=1: Enable CLMC as hybrid Mode. CDLD and CILR will be disabled in this case and we're using legacy C1E. This is workaround for CPU(Griffin) performance issue.
       =0: Enable CLMC as regular mode, CDLD and CILR will be enabled.
+Bit[8]=1: CDLF is supported and enabled on current system.
+      =0: CDLF is not supported or enabled on current system.
+Bit[9]=1: DLL Shut Down feature is enabled on current system.
+      =0: DLL Shut Down feature is not enabled or supported on current system.
 
 ulBootUpReqDisplayVector: This dword is a bit vector indicates what display devices are requested during boot-up. Refer to ATOM_DEVICE_xxx_SUPPORT for the bit vector definitions.
 
 ulOtherDisplayMisc: [15:8]- Bootup LCD Expansion selection; 0-center, 1-full panel size expansion;
-			              [7:0] - BootupTV standard selection; This is a bit vector to indicate what TV standards are supported by the system. Refer to ucTVSuppportedStd definition;
+			              [7:0] - BootupTV standard selection; This is a bit vector to indicate what TV standards are supported by the system. Refer to ucTVSupportedStd definition;
 
 ulDDISlot1Config: Describes the PCIE lane configuration on this DDI PCIE slot (ADD2 card) or connector (Mobile design).
       [3:0]  - Bit vector to indicate PCIE lane config of the DDI slot/connector on chassis (bit 0=1 lane 3:0; bit 1=1 lane 7:4; bit 2=1 lane 11:8; bit 3=1 lane 15:12)
-			[7:4]  - Bit vector to indicate PCIE lane config of the same DDI slot/connector on docking station (bit 0=1 lane 3:0; bit 1=1 lane 7:4; bit 2=1 lane 11:8; bit 3=1 lane 15:12)
-			[15:8] - Lane configuration attribute;
+			[7:4]  - Bit vector to indicate PCIE lane config of the same DDI slot/connector on docking station (bit 4=1 lane 3:0; bit 5=1 lane 7:4; bit 6=1 lane 11:8; bit 7=1 lane 15:12)
+      When a DDI connector is not "paired" (meaming two connections mutualexclusive on chassis or docking, only one of them can be connected at one time.
+      in both chassis and docking, SBIOS has to duplicate the same PCIE lane info from chassis to docking or vice versa. For example:
+      one DDI connector is only populated in docking with PCIE lane 8-11, but there is no paired connection on chassis, SBIOS has to copy bit 6 to bit 2.
+
+			[15:8] - Lane configuration attribute; 
       [23:16]- Connector type, possible value:
                CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D
                CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D
                CONNECTOR_OBJECT_ID_HDMI_TYPE_A
                CONNECTOR_OBJECT_ID_DISPLAYPORT
+               CONNECTOR_OBJECT_ID_eDP
 			[31:24]- Reserved
 
 ulDDISlot2Config: Same as Slot1.
@@ -1787,29 +2208,31 @@
 
 ucUMAChannelNumber:  how many channels for the UMA;
 
-ulDockingPinCFGInfo: [15:0]-Bus/Device/Function # to CFG to read this Docking Pin; [31:16]-reg offset in CFG to read this pin
+ulDockingPinCFGInfo: [15:0]-Bus/Device/Function # to CFG to read this Docking Pin; [31:16]-reg offset in CFG to read this pin 
 ucDockingPinBit:     which bit in this register to read the pin status;
 ucDockingPinPolarity:Polarity of the pin when docked;
 
 ulCPUCapInfo:        [7:0]=1:Griffin;[7:0]=2:Greyhound;[7:0]=3:K8, other bits reserved for now and must be 0x0
 
 usNumberOfCyclesInPeriod:Indicate how many cycles when PWM duty is 100%.
-usMaxNBVoltage:Max. voltage control value in either PWM or GPIO mode.
+
+usMaxNBVoltage:Max. voltage control value in either PWM or GPIO mode. 
 usMinNBVoltage:Min. voltage control value in either PWM or GPIO mode.
                     GPIO mode: both usMaxNBVoltage & usMinNBVoltage have a valid value ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE=0
                     PWM mode: both usMaxNBVoltage & usMinNBVoltage have a valid value ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE=1
                     GPU SW don't control mode: usMaxNBVoltage & usMinNBVoltage=0 and no care about ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE
+
 usBootUpNBVoltage:Boot-up voltage regulator dependent PWM value.
 
 ulHTLinkFreq:       Bootup HT link Frequency in 10Khz.
-usMinHTLinkWidth:   Bootup minimum HT link width. If CDLW disabled, this is equal to usMaxHTLinkWidth.
+usMinHTLinkWidth:   Bootup minimum HT link width. If CDLW disabled, this is equal to usMaxHTLinkWidth. 
                     If CDLW enabled, both upstream and downstream width should be the same during bootup.
-usMaxHTLinkWidth:   Bootup maximum HT link width. If CDLW disabled, this is equal to usMinHTLinkWidth.
-                    If CDLW enabled, both upstream and downstream width should be the same during bootup.
+usMaxHTLinkWidth:   Bootup maximum HT link width. If CDLW disabled, this is equal to usMinHTLinkWidth. 
+                    If CDLW enabled, both upstream and downstream width should be the same during bootup.  
 
-usUMASyncStartDelay: Memory access latency, required for watermark calculation
+usUMASyncStartDelay: Memory access latency, required for watermark calculation 
 usUMADataReturnTime: Memory access latency, required for watermark calculation
-usLinkStatusZeroTime:Memory access latency required for watermark calculation, set this to 0x0 for K8 CPU, set a proper value in 0.01 the unit of us
+usLinkStatusZeroTime:Memory access latency required for watermark calculation, set this to 0x0 for K8 CPU, set a proper value in 0.01 the unit of us 
 for Griffin or Greyhound. SBIOS needs to convert to actual time by:
                      if T0Ttime [5:4]=00b, then usLinkStatusZeroTime=T0Ttime [3:0]*0.1us (0.0 to 1.5us)
                      if T0Ttime [5:4]=01b, then usLinkStatusZeroTime=T0Ttime [3:0]*0.5us (0.0 to 7.5us)
@@ -1817,7 +2240,7 @@
                      if T0Ttime [5:4]=11b, and T0Ttime [3:0]=0x0 to 0xa, then usLinkStatusZeroTime=T0Ttime [3:0]*20us (0.0 to 200us)
 
 ulHighVoltageHTLinkFreq:     HT link frequency for power state with low voltage. If boot up runs in HT1, this must be 0.
-                             This must be less than or equal to ulHTLinkFreq(bootup frequency).
+                             This must be less than or equal to ulHTLinkFreq(bootup frequency). 
 ulLowVoltageHTLinkFreq:      HT link frequency for power state with low voltage or voltage scaling 1.0v~1.1v. If boot up runs in HT1, this must be 0.
                              This must be less than or equal to ulHighVoltageHTLinkFreq.
 
@@ -1827,14 +2250,17 @@
 usMinDownStreamHTLinkWidth:  same as above.
 */
 
+
 #define SYSTEM_CONFIG_POWEREXPRESS_ENABLE                 0x00000001
 #define SYSTEM_CONFIG_RUN_AT_OVERDRIVE_ENGINE             0x00000002
-#define SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE                  0x00000004
+#define SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE                  0x00000004 
 #define SYSTEM_CONFIG_PERFORMANCE_POWERSTATE_ONLY         0x00000008
 #define SYSTEM_CONFIG_CLMC_ENABLED                        0x00000010
 #define SYSTEM_CONFIG_CDLW_ENABLED                        0x00000020
 #define SYSTEM_CONFIG_HIGH_VOLTAGE_REQUESTED              0x00000040
 #define SYSTEM_CONFIG_CLMC_HYBRID_MODE_ENABLED            0x00000080
+#define SYSTEM_CONFIG_CDLF_ENABLED                        0x00000100
+#define SYSTEM_CONFIG_DLL_SHUTDOWN_ENABLED                0x00000200
 
 #define IGP_DDI_SLOT_LANE_CONFIG_MASK                     0x000000FF
 
@@ -1851,6 +2277,41 @@
 
 #define IGP_DDI_SLOT_CONNECTOR_TYPE_MASK                  0x00FF0000
 
+// IntegratedSystemInfoTable new Rev is V5 after V2, because of the real rev of V2 is v1.4. This rev is used for RR
+typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V5
+{
+  ATOM_COMMON_TABLE_HEADER   sHeader;
+  ULONG	                     ulBootUpEngineClock;       //in 10kHz unit
+  ULONG                      ulDentistVCOFreq;          //Dentist VCO clock in 10kHz unit, the source of GPU SCLK, LCLK, UCLK and VCLK. 
+  ULONG                      ulLClockFreq;              //GPU Lclk freq in 10kHz unit, have relationship with NCLK in NorthBridge
+  ULONG	                     ulBootUpUMAClock;          //in 10kHz unit
+  ULONG                      ulReserved1[8];            //must be 0x0 for the reserved
+  ULONG                      ulBootUpReqDisplayVector;
+  ULONG                      ulOtherDisplayMisc;
+  ULONG                      ulReserved2[4];            //must be 0x0 for the reserved
+  ULONG                      ulSystemConfig;            //TBD
+  ULONG                      ulCPUCapInfo;              //TBD
+  USHORT                     usMaxNBVoltage;            //high NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse;
+  USHORT                     usMinNBVoltage;            //low NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse;
+  USHORT                     usBootUpNBVoltage;         //boot up NB voltage
+  UCHAR                      ucHtcTmpLmt;               //bit [22:16] of D24F3x64 Hardware Thermal Control (HTC) Register, may not be needed, TBD
+  UCHAR                      ucTjOffset;                //bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed, TBD
+  ULONG                      ulReserved3[4];            //must be 0x0 for the reserved
+  ULONG                      ulDDISlot1Config;          //see above ulDDISlot1Config definition
+  ULONG                      ulDDISlot2Config;
+  ULONG                      ulDDISlot3Config;
+  ULONG                      ulDDISlot4Config;
+  ULONG                      ulReserved4[4];            //must be 0x0 for the reserved
+  UCHAR                      ucMemoryType;              //[3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved
+  UCHAR                      ucUMAChannelNumber;
+  USHORT                     usReserved;
+  ULONG                      ulReserved5[4];            //must be 0x0 for the reserved
+  ULONG                      ulCSR_M3_ARB_CNTL_DEFAULT[10];//arrays with values for CSR M3 arbiter for default
+  ULONG                      ulCSR_M3_ARB_CNTL_UVD[10]; //arrays with values for CSR M3 arbiter for UVD playback
+  ULONG                      ulCSR_M3_ARB_CNTL_FS3D[10];//arrays with values for CSR M3 arbiter for Full Screen 3D applications
+  ULONG                      ulReserved6[61];           //must be 0x0
+}ATOM_INTEGRATED_SYSTEM_INFO_V5;   
+
 #define ATOM_CRT_INT_ENCODER1_INDEX                       0x00000000
 #define ATOM_LCD_INT_ENCODER1_INDEX                       0x00000001
 #define ATOM_TV_INT_ENCODER1_INDEX                        0x00000002
@@ -1866,8 +2327,8 @@
 #define ATOM_DFP_INT_ENCODER3_INDEX                       0x0000000C
 #define ATOM_DFP_INT_ENCODER4_INDEX                       0x0000000D
 
-/*  define ASIC internal encoder id ( bit vector ) */
-#define ASIC_INT_DAC1_ENCODER_ID											0x00
+// define ASIC internal encoder id ( bit vector ), used for CRTC_SourceSelTable
+#define ASIC_INT_DAC1_ENCODER_ID    											0x00 
 #define ASIC_INT_TV_ENCODER_ID														0x02
 #define ASIC_INT_DIG1_ENCODER_ID													0x03
 #define ASIC_INT_DAC2_ENCODER_ID													0x04
@@ -1875,10 +2336,24 @@
 #define ASIC_INT_DVO_ENCODER_ID														0x07
 #define ASIC_INT_DIG2_ENCODER_ID													0x09
 #define ASIC_EXT_DIG_ENCODER_ID														0x05
+#define ASIC_EXT_DIG2_ENCODER_ID													0x08
+#define ASIC_INT_DIG3_ENCODER_ID													0x0a
+#define ASIC_INT_DIG4_ENCODER_ID													0x0b
+#define ASIC_INT_DIG5_ENCODER_ID													0x0c
+#define ASIC_INT_DIG6_ENCODER_ID													0x0d
 
-/* define Encoder attribute */
+//define Encoder attribute
 #define ATOM_ANALOG_ENCODER																0
-#define ATOM_DIGITAL_ENCODER															1
+#define ATOM_DIGITAL_ENCODER															1		
+#define ATOM_DP_ENCODER															      2		
+
+#define ATOM_ENCODER_ENUM_MASK                            0x70
+#define ATOM_ENCODER_ENUM_ID1                             0x00
+#define ATOM_ENCODER_ENUM_ID2                             0x10
+#define ATOM_ENCODER_ENUM_ID3                             0x20
+#define ATOM_ENCODER_ENUM_ID4                             0x30
+#define ATOM_ENCODER_ENUM_ID5                             0x40 
+#define ATOM_ENCODER_ENUM_ID6                             0x50
 
 #define ATOM_DEVICE_CRT1_INDEX                            0x00000000
 #define ATOM_DEVICE_LCD1_INDEX                            0x00000001
@@ -1886,45 +2361,40 @@
 #define ATOM_DEVICE_DFP1_INDEX                            0x00000003
 #define ATOM_DEVICE_CRT2_INDEX                            0x00000004
 #define ATOM_DEVICE_LCD2_INDEX                            0x00000005
-#define ATOM_DEVICE_TV2_INDEX                             0x00000006
+#define ATOM_DEVICE_DFP6_INDEX                            0x00000006
 #define ATOM_DEVICE_DFP2_INDEX                            0x00000007
 #define ATOM_DEVICE_CV_INDEX                              0x00000008
-#define ATOM_DEVICE_DFP3_INDEX														0x00000009
-#define ATOM_DEVICE_DFP4_INDEX														0x0000000A
-#define ATOM_DEVICE_DFP5_INDEX														0x0000000B
+#define ATOM_DEVICE_DFP3_INDEX                            0x00000009
+#define ATOM_DEVICE_DFP4_INDEX                            0x0000000A
+#define ATOM_DEVICE_DFP5_INDEX                            0x0000000B
+
 #define ATOM_DEVICE_RESERVEDC_INDEX                       0x0000000C
 #define ATOM_DEVICE_RESERVEDD_INDEX                       0x0000000D
 #define ATOM_DEVICE_RESERVEDE_INDEX                       0x0000000E
 #define ATOM_DEVICE_RESERVEDF_INDEX                       0x0000000F
 #define ATOM_MAX_SUPPORTED_DEVICE_INFO                    (ATOM_DEVICE_DFP3_INDEX+1)
 #define ATOM_MAX_SUPPORTED_DEVICE_INFO_2                  ATOM_MAX_SUPPORTED_DEVICE_INFO
-#define ATOM_MAX_SUPPORTED_DEVICE_INFO_3                  (ATOM_DEVICE_DFP5_INDEX + 1)
+#define ATOM_MAX_SUPPORTED_DEVICE_INFO_3                  (ATOM_DEVICE_DFP5_INDEX + 1 )
 
 #define ATOM_MAX_SUPPORTED_DEVICE                         (ATOM_DEVICE_RESERVEDF_INDEX+1)
 
-#define ATOM_DEVICE_CRT1_SUPPORT                          (0x1L << ATOM_DEVICE_CRT1_INDEX)
-#define ATOM_DEVICE_LCD1_SUPPORT                          (0x1L << ATOM_DEVICE_LCD1_INDEX)
-#define ATOM_DEVICE_TV1_SUPPORT                           (0x1L << ATOM_DEVICE_TV1_INDEX)
-#define ATOM_DEVICE_DFP1_SUPPORT                          (0x1L << ATOM_DEVICE_DFP1_INDEX)
-#define ATOM_DEVICE_CRT2_SUPPORT                          (0x1L << ATOM_DEVICE_CRT2_INDEX)
-#define ATOM_DEVICE_LCD2_SUPPORT                          (0x1L << ATOM_DEVICE_LCD2_INDEX)
-#define ATOM_DEVICE_TV2_SUPPORT                           (0x1L << ATOM_DEVICE_TV2_INDEX)
-#define ATOM_DEVICE_DFP2_SUPPORT                          (0x1L << ATOM_DEVICE_DFP2_INDEX)
-#define ATOM_DEVICE_CV_SUPPORT                            (0x1L << ATOM_DEVICE_CV_INDEX)
-#define ATOM_DEVICE_DFP3_SUPPORT													(0x1L << ATOM_DEVICE_DFP3_INDEX)
-#define ATOM_DEVICE_DFP4_SUPPORT													(0x1L << ATOM_DEVICE_DFP4_INDEX )
-#define ATOM_DEVICE_DFP5_SUPPORT													(0x1L << ATOM_DEVICE_DFP5_INDEX)
+#define ATOM_DEVICE_CRT1_SUPPORT                          (0x1L << ATOM_DEVICE_CRT1_INDEX )
+#define ATOM_DEVICE_LCD1_SUPPORT                          (0x1L << ATOM_DEVICE_LCD1_INDEX )
+#define ATOM_DEVICE_TV1_SUPPORT                           (0x1L << ATOM_DEVICE_TV1_INDEX  )
+#define ATOM_DEVICE_DFP1_SUPPORT                          (0x1L << ATOM_DEVICE_DFP1_INDEX )
+#define ATOM_DEVICE_CRT2_SUPPORT                          (0x1L << ATOM_DEVICE_CRT2_INDEX )
+#define ATOM_DEVICE_LCD2_SUPPORT                          (0x1L << ATOM_DEVICE_LCD2_INDEX )
+#define ATOM_DEVICE_DFP6_SUPPORT                          (0x1L << ATOM_DEVICE_DFP6_INDEX )
+#define ATOM_DEVICE_DFP2_SUPPORT                          (0x1L << ATOM_DEVICE_DFP2_INDEX )
+#define ATOM_DEVICE_CV_SUPPORT                            (0x1L << ATOM_DEVICE_CV_INDEX   )
+#define ATOM_DEVICE_DFP3_SUPPORT                          (0x1L << ATOM_DEVICE_DFP3_INDEX )
+#define ATOM_DEVICE_DFP4_SUPPORT                          (0x1L << ATOM_DEVICE_DFP4_INDEX )
+#define ATOM_DEVICE_DFP5_SUPPORT                          (0x1L << ATOM_DEVICE_DFP5_INDEX )
 
-#define ATOM_DEVICE_CRT_SUPPORT \
-	(ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_CRT2_SUPPORT)
-#define ATOM_DEVICE_DFP_SUPPORT \
-	(ATOM_DEVICE_DFP1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT | \
-	 ATOM_DEVICE_DFP3_SUPPORT | ATOM_DEVICE_DFP4_SUPPORT | \
-	 ATOM_DEVICE_DFP5_SUPPORT)
-#define ATOM_DEVICE_TV_SUPPORT \
-	(ATOM_DEVICE_TV1_SUPPORT  | ATOM_DEVICE_TV2_SUPPORT)
-#define ATOM_DEVICE_LCD_SUPPORT \
-	(ATOM_DEVICE_LCD1_SUPPORT | ATOM_DEVICE_LCD2_SUPPORT)
+#define ATOM_DEVICE_CRT_SUPPORT                           (ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_CRT2_SUPPORT)
+#define ATOM_DEVICE_DFP_SUPPORT                           (ATOM_DEVICE_DFP1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT |  ATOM_DEVICE_DFP3_SUPPORT | ATOM_DEVICE_DFP4_SUPPORT | ATOM_DEVICE_DFP5_SUPPORT | ATOM_DEVICE_DFP6_SUPPORT)
+#define ATOM_DEVICE_TV_SUPPORT                            (ATOM_DEVICE_TV1_SUPPORT)
+#define ATOM_DEVICE_LCD_SUPPORT                           (ATOM_DEVICE_LCD1_SUPPORT | ATOM_DEVICE_LCD2_SUPPORT)
 
 #define ATOM_DEVICE_CONNECTOR_TYPE_MASK                   0x000000F0
 #define ATOM_DEVICE_CONNECTOR_TYPE_SHIFT                  0x00000004
@@ -1942,6 +2412,7 @@
 #define ATOM_DEVICE_CONNECTOR_CASE_1                      0x0000000E
 #define ATOM_DEVICE_CONNECTOR_DISPLAYPORT                 0x0000000F
 
+
 #define ATOM_DEVICE_DAC_INFO_MASK                         0x0000000F
 #define ATOM_DEVICE_DAC_INFO_SHIFT                        0x00000000
 #define ATOM_DEVICE_DAC_INFO_NODAC                        0x00000000
@@ -1958,139 +2429,150 @@
 #define ATOM_DEVICE_I2C_ID_SHIFT                          0x00000004
 #define ATOM_DEVICE_I2C_ID_IS_FOR_NON_MM_USE              0x00000001
 #define ATOM_DEVICE_I2C_ID_IS_FOR_MM_USE                  0x00000002
-#define ATOM_DEVICE_I2C_ID_IS_FOR_SDVO_USE                0x00000003	/* For IGP RS600 */
-#define ATOM_DEVICE_I2C_ID_IS_FOR_DAC_SCL                 0x00000004	/* For IGP RS690 */
+#define ATOM_DEVICE_I2C_ID_IS_FOR_SDVO_USE                0x00000003    //For IGP RS600
+#define ATOM_DEVICE_I2C_ID_IS_FOR_DAC_SCL                 0x00000004    //For IGP RS690
 
 #define ATOM_DEVICE_I2C_HARDWARE_CAP_MASK                 0x00000080
 #define ATOM_DEVICE_I2C_HARDWARE_CAP_SHIFT                0x00000007
 #define	ATOM_DEVICE_USES_SOFTWARE_ASSISTED_I2C            0x00000000
 #define	ATOM_DEVICE_USES_HARDWARE_ASSISTED_I2C            0x00000001
 
-/*   usDeviceSupport: */
-/*   Bits0       = 0 - no CRT1 support= 1- CRT1 is supported */
-/*   Bit 1       = 0 - no LCD1 support= 1- LCD1 is supported */
-/*   Bit 2       = 0 - no TV1  support= 1- TV1  is supported */
-/*   Bit 3       = 0 - no DFP1 support= 1- DFP1 is supported */
-/*   Bit 4       = 0 - no CRT2 support= 1- CRT2 is supported */
-/*   Bit 5       = 0 - no LCD2 support= 1- LCD2 is supported */
-/*   Bit 6       = 0 - no TV2  support= 1- TV2  is supported */
-/*   Bit 7       = 0 - no DFP2 support= 1- DFP2 is supported */
-/*   Bit 8       = 0 - no CV   support= 1- CV   is supported */
-/*   Bit 9       = 0 - no DFP3 support= 1- DFP3 is supported */
-/*   Byte1 (Supported Device Info) */
-/*   Bit 0       = = 0 - no CV support= 1- CV is supported */
-/*  */
-/*  */
+//  usDeviceSupport:
+//  Bits0	= 0 - no CRT1 support= 1- CRT1 is supported
+//  Bit 1	= 0 - no LCD1 support= 1- LCD1 is supported
+//  Bit 2	= 0 - no TV1  support= 1- TV1  is supported
+//  Bit 3	= 0 - no DFP1 support= 1- DFP1 is supported
+//  Bit 4	= 0 - no CRT2 support= 1- CRT2 is supported
+//  Bit 5	= 0 - no LCD2 support= 1- LCD2 is supported
+//  Bit 6	= 0 - no DFP6 support= 1- DFP6 is supported
+//  Bit 7	= 0 - no DFP2 support= 1- DFP2 is supported
+//  Bit 8	= 0 - no CV   support= 1- CV   is supported
+//  Bit 9	= 0 - no DFP3 support= 1- DFP3 is supported
+//  Bit 10      = 0 - no DFP4 support= 1- DFP4 is supported
+//  Bit 11      = 0 - no DFP5 support= 1- DFP5 is supported
+//   
+//  
 
-/*               ucI2C_ConfigID */
-/*     [7:0] - I2C LINE Associate ID */
-/*           = 0   - no I2C */
-/*     [7]               -       HW_Cap        = 1,  [6:0]=HW assisted I2C ID(HW line selection) */
-/*                           =   0,  [6:0]=SW assisted I2C ID */
-/*     [6-4]     - HW_ENGINE_ID  =       1,  HW engine for NON multimedia use */
-/*                           =   2,      HW engine for Multimedia use */
-/*                           =   3-7     Reserved for future I2C engines */
-/*               [3-0] - I2C_LINE_MUX  = A Mux number when it's HW assisted I2C or GPIO ID when it's SW I2C */
+/****************************************************************************/
+/* Structure used in MclkSS_InfoTable                                       */
+/****************************************************************************/
+//		ucI2C_ConfigID
+//    [7:0] - I2C LINE Associate ID
+//          = 0   - no I2C
+//    [7]		-	HW_Cap        =	1,  [6:0]=HW assisted I2C ID(HW line selection)
+//                          =	0,  [6:0]=SW assisted I2C ID
+//    [6-4]	- HW_ENGINE_ID  =	1,  HW engine for NON multimedia use
+//                          =	2,	HW engine for Multimedia use
+//                          =	3-7	Reserved for future I2C engines
+//		[3-0] - I2C_LINE_MUX  = A Mux number when it's HW assisted I2C or GPIO ID when it's SW I2C
 
-typedef struct _ATOM_I2C_ID_CONFIG {
+typedef struct _ATOM_I2C_ID_CONFIG
+{
 #if ATOM_BIG_ENDIAN
-	UCHAR bfHW_Capable:1;
-	UCHAR bfHW_EngineID:3;
-	UCHAR bfI2C_LineMux:4;
+  UCHAR   bfHW_Capable:1;
+  UCHAR   bfHW_EngineID:3;
+  UCHAR   bfI2C_LineMux:4;
 #else
-	UCHAR bfI2C_LineMux:4;
-	UCHAR bfHW_EngineID:3;
-	UCHAR bfHW_Capable:1;
+  UCHAR   bfI2C_LineMux:4;
+  UCHAR   bfHW_EngineID:3;
+  UCHAR   bfHW_Capable:1;
 #endif
-} ATOM_I2C_ID_CONFIG;
+}ATOM_I2C_ID_CONFIG;
 
-typedef union _ATOM_I2C_ID_CONFIG_ACCESS {
-	ATOM_I2C_ID_CONFIG sbfAccess;
-	UCHAR ucAccess;
-} ATOM_I2C_ID_CONFIG_ACCESS;
+typedef union _ATOM_I2C_ID_CONFIG_ACCESS
+{
+  ATOM_I2C_ID_CONFIG sbfAccess;
+  UCHAR              ucAccess;
+}ATOM_I2C_ID_CONFIG_ACCESS;
+   
 
-/****************************************************************************/
-/*  Structure used in GPIO_I2C_InfoTable */
-/****************************************************************************/
-typedef struct _ATOM_GPIO_I2C_ASSIGMENT {
-	USHORT usClkMaskRegisterIndex;
-	USHORT usClkEnRegisterIndex;
-	USHORT usClkY_RegisterIndex;
-	USHORT usClkA_RegisterIndex;
-	USHORT usDataMaskRegisterIndex;
-	USHORT usDataEnRegisterIndex;
-	USHORT usDataY_RegisterIndex;
-	USHORT usDataA_RegisterIndex;
-	ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;
-	UCHAR ucClkMaskShift;
-	UCHAR ucClkEnShift;
-	UCHAR ucClkY_Shift;
-	UCHAR ucClkA_Shift;
-	UCHAR ucDataMaskShift;
-	UCHAR ucDataEnShift;
-	UCHAR ucDataY_Shift;
-	UCHAR ucDataA_Shift;
-	UCHAR ucReserved1;
-	UCHAR ucReserved2;
-} ATOM_GPIO_I2C_ASSIGMENT;
+/****************************************************************************/	
+// Structure used in GPIO_I2C_InfoTable
+/****************************************************************************/	
+typedef struct _ATOM_GPIO_I2C_ASSIGMENT
+{
+  USHORT                    usClkMaskRegisterIndex;
+  USHORT                    usClkEnRegisterIndex;
+  USHORT                    usClkY_RegisterIndex;
+  USHORT                    usClkA_RegisterIndex;
+  USHORT                    usDataMaskRegisterIndex;
+  USHORT                    usDataEnRegisterIndex;
+  USHORT                    usDataY_RegisterIndex;
+  USHORT                    usDataA_RegisterIndex;
+  ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;
+  UCHAR                     ucClkMaskShift;
+  UCHAR                     ucClkEnShift;
+  UCHAR                     ucClkY_Shift;
+  UCHAR                     ucClkA_Shift;
+  UCHAR                     ucDataMaskShift;
+  UCHAR                     ucDataEnShift;
+  UCHAR                     ucDataY_Shift;
+  UCHAR                     ucDataA_Shift;
+  UCHAR                     ucReserved1;
+  UCHAR                     ucReserved2;
+}ATOM_GPIO_I2C_ASSIGMENT;
 
-typedef struct _ATOM_GPIO_I2C_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_GPIO_I2C_ASSIGMENT asGPIO_Info[ATOM_MAX_SUPPORTED_DEVICE];
-} ATOM_GPIO_I2C_INFO;
+typedef struct _ATOM_GPIO_I2C_INFO
+{ 
+  ATOM_COMMON_TABLE_HEADER	sHeader;
+  ATOM_GPIO_I2C_ASSIGMENT   asGPIO_Info[ATOM_MAX_SUPPORTED_DEVICE];
+}ATOM_GPIO_I2C_INFO;
 
-/****************************************************************************/
-/*  Common Structure used in other structures */
-/****************************************************************************/
+/****************************************************************************/	
+// Common Structure used in other structures
+/****************************************************************************/	
 
 #ifndef _H2INC
-
-/* Please don't add or expand this bitfield structure below, this one will retire soon.! */
-typedef struct _ATOM_MODE_MISC_INFO {
+  
+//Please don't add or expand this bitfield structure below, this one will retire soon.!
+typedef struct _ATOM_MODE_MISC_INFO
+{ 
 #if ATOM_BIG_ENDIAN
-	USHORT Reserved:6;
-	USHORT RGB888:1;
-	USHORT DoubleClock:1;
-	USHORT Interlace:1;
-	USHORT CompositeSync:1;
-	USHORT V_ReplicationBy2:1;
-	USHORT H_ReplicationBy2:1;
-	USHORT VerticalCutOff:1;
-	USHORT VSyncPolarity:1;	/* 0=Active High, 1=Active Low */
-	USHORT HSyncPolarity:1;	/* 0=Active High, 1=Active Low */
-	USHORT HorizontalCutOff:1;
+  USHORT Reserved:6;
+  USHORT RGB888:1;
+  USHORT DoubleClock:1;
+  USHORT Interlace:1;
+  USHORT CompositeSync:1;
+  USHORT V_ReplicationBy2:1;
+  USHORT H_ReplicationBy2:1;
+  USHORT VerticalCutOff:1;
+  USHORT VSyncPolarity:1;      //0=Active High, 1=Active Low
+  USHORT HSyncPolarity:1;      //0=Active High, 1=Active Low
+  USHORT HorizontalCutOff:1;
 #else
-	USHORT HorizontalCutOff:1;
-	USHORT HSyncPolarity:1;	/* 0=Active High, 1=Active Low */
-	USHORT VSyncPolarity:1;	/* 0=Active High, 1=Active Low */
-	USHORT VerticalCutOff:1;
-	USHORT H_ReplicationBy2:1;
-	USHORT V_ReplicationBy2:1;
-	USHORT CompositeSync:1;
-	USHORT Interlace:1;
-	USHORT DoubleClock:1;
-	USHORT RGB888:1;
-	USHORT Reserved:6;
+  USHORT HorizontalCutOff:1;
+  USHORT HSyncPolarity:1;      //0=Active High, 1=Active Low
+  USHORT VSyncPolarity:1;      //0=Active High, 1=Active Low
+  USHORT VerticalCutOff:1;
+  USHORT H_ReplicationBy2:1;
+  USHORT V_ReplicationBy2:1;
+  USHORT CompositeSync:1;
+  USHORT Interlace:1;
+  USHORT DoubleClock:1;
+  USHORT RGB888:1;
+  USHORT Reserved:6;           
 #endif
-} ATOM_MODE_MISC_INFO;
-
-typedef union _ATOM_MODE_MISC_INFO_ACCESS {
-	ATOM_MODE_MISC_INFO sbfAccess;
-	USHORT usAccess;
-} ATOM_MODE_MISC_INFO_ACCESS;
-
+}ATOM_MODE_MISC_INFO;
+  
+typedef union _ATOM_MODE_MISC_INFO_ACCESS
+{ 
+  ATOM_MODE_MISC_INFO sbfAccess;
+  USHORT              usAccess;
+}ATOM_MODE_MISC_INFO_ACCESS;
+  
 #else
-
-typedef union _ATOM_MODE_MISC_INFO_ACCESS {
-	USHORT usAccess;
-} ATOM_MODE_MISC_INFO_ACCESS;
-
+  
+typedef union _ATOM_MODE_MISC_INFO_ACCESS
+{ 
+  USHORT              usAccess;
+}ATOM_MODE_MISC_INFO_ACCESS;
+   
 #endif
 
-/*  usModeMiscInfo- */
+// usModeMiscInfo-
 #define ATOM_H_CUTOFF           0x01
-#define ATOM_HSYNC_POLARITY     0x02	/* 0=Active High, 1=Active Low */
-#define ATOM_VSYNC_POLARITY     0x04	/* 0=Active High, 1=Active Low */
+#define ATOM_HSYNC_POLARITY     0x02             //0=Active High, 1=Active Low
+#define ATOM_VSYNC_POLARITY     0x04             //0=Active High, 1=Active Low
 #define ATOM_V_CUTOFF           0x08
 #define ATOM_H_REPLICATIONBY2   0x10
 #define ATOM_V_REPLICATIONBY2   0x20
@@ -2099,10 +2581,10 @@
 #define ATOM_DOUBLE_CLOCK_MODE  0x100
 #define ATOM_RGB888_MODE        0x200
 
-/* usRefreshRate- */
+//usRefreshRate-
 #define ATOM_REFRESH_43         43
 #define ATOM_REFRESH_47         47
-#define ATOM_REFRESH_56         56
+#define ATOM_REFRESH_56         56	
 #define ATOM_REFRESH_60         60
 #define ATOM_REFRESH_65         65
 #define ATOM_REFRESH_70         70
@@ -2110,192 +2592,233 @@
 #define ATOM_REFRESH_75         75
 #define ATOM_REFRESH_85         85
 
-/*  ATOM_MODE_TIMING data are exactly the same as VESA timing data. */
-/*  Translation from EDID to ATOM_MODE_TIMING, use the following formula. */
-/*  */
-/*       VESA_HTOTAL                     =       VESA_ACTIVE + 2* VESA_BORDER + VESA_BLANK */
-/*                                               =       EDID_HA + EDID_HBL */
-/*       VESA_HDISP                      =       VESA_ACTIVE     =       EDID_HA */
-/*       VESA_HSYNC_START        =       VESA_ACTIVE + VESA_BORDER + VESA_FRONT_PORCH */
-/*                                               =       EDID_HA + EDID_HSO */
-/*       VESA_HSYNC_WIDTH        =       VESA_HSYNC_TIME =       EDID_HSPW */
-/*       VESA_BORDER                     =       EDID_BORDER */
+// ATOM_MODE_TIMING data are exactly the same as VESA timing data.
+// Translation from EDID to ATOM_MODE_TIMING, use the following formula.
+//
+//	VESA_HTOTAL			=	VESA_ACTIVE + 2* VESA_BORDER + VESA_BLANK
+//						=	EDID_HA + EDID_HBL
+//	VESA_HDISP			=	VESA_ACTIVE	=	EDID_HA
+//	VESA_HSYNC_START	=	VESA_ACTIVE + VESA_BORDER + VESA_FRONT_PORCH
+//						=	EDID_HA + EDID_HSO
+//	VESA_HSYNC_WIDTH	=	VESA_HSYNC_TIME	=	EDID_HSPW
+//	VESA_BORDER			=	EDID_BORDER
 
-/****************************************************************************/
-/*  Structure used in SetCRTC_UsingDTDTimingTable */
-/****************************************************************************/
-typedef struct _SET_CRTC_USING_DTD_TIMING_PARAMETERS {
-	USHORT usH_Size;
-	USHORT usH_Blanking_Time;
-	USHORT usV_Size;
-	USHORT usV_Blanking_Time;
-	USHORT usH_SyncOffset;
-	USHORT usH_SyncWidth;
-	USHORT usV_SyncOffset;
-	USHORT usV_SyncWidth;
-	ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo;
-	UCHAR ucH_Border;	/*  From DFP EDID */
-	UCHAR ucV_Border;
-	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
-	UCHAR ucPadding[3];
-} SET_CRTC_USING_DTD_TIMING_PARAMETERS;
+/****************************************************************************/	
+// Structure used in SetCRTC_UsingDTDTimingTable
+/****************************************************************************/	
+typedef struct _SET_CRTC_USING_DTD_TIMING_PARAMETERS
+{
+  USHORT  usH_Size;
+  USHORT  usH_Blanking_Time;
+  USHORT  usV_Size;
+  USHORT  usV_Blanking_Time;			
+  USHORT  usH_SyncOffset;
+  USHORT  usH_SyncWidth;
+  USHORT  usV_SyncOffset;
+  USHORT  usV_SyncWidth;
+  ATOM_MODE_MISC_INFO_ACCESS  susModeMiscInfo;  
+  UCHAR   ucH_Border;         // From DFP EDID
+  UCHAR   ucV_Border;
+  UCHAR   ucCRTC;             // ATOM_CRTC1 or ATOM_CRTC2  
+  UCHAR   ucPadding[3];
+}SET_CRTC_USING_DTD_TIMING_PARAMETERS;
 
-/****************************************************************************/
-/*  Structure used in SetCRTC_TimingTable */
-/****************************************************************************/
-typedef struct _SET_CRTC_TIMING_PARAMETERS {
-	USHORT usH_Total;	/*  horizontal total */
-	USHORT usH_Disp;	/*  horizontal display */
-	USHORT usH_SyncStart;	/*  horozontal Sync start */
-	USHORT usH_SyncWidth;	/*  horizontal Sync width */
-	USHORT usV_Total;	/*  vertical total */
-	USHORT usV_Disp;	/*  vertical display */
-	USHORT usV_SyncStart;	/*  vertical Sync start */
-	USHORT usV_SyncWidth;	/*  vertical Sync width */
-	ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo;
-	UCHAR ucCRTC;		/*  ATOM_CRTC1 or ATOM_CRTC2 */
-	UCHAR ucOverscanRight;	/*  right */
-	UCHAR ucOverscanLeft;	/*  left */
-	UCHAR ucOverscanBottom;	/*  bottom */
-	UCHAR ucOverscanTop;	/*  top */
-	UCHAR ucReserved;
-} SET_CRTC_TIMING_PARAMETERS;
+/****************************************************************************/	
+// Structure used in SetCRTC_TimingTable
+/****************************************************************************/	
+typedef struct _SET_CRTC_TIMING_PARAMETERS
+{
+  USHORT                      usH_Total;        // horizontal total
+  USHORT                      usH_Disp;         // horizontal display
+  USHORT                      usH_SyncStart;    // horozontal Sync start
+  USHORT                      usH_SyncWidth;    // horizontal Sync width
+  USHORT                      usV_Total;        // vertical total
+  USHORT                      usV_Disp;         // vertical display
+  USHORT                      usV_SyncStart;    // vertical Sync start
+  USHORT                      usV_SyncWidth;    // vertical Sync width
+  ATOM_MODE_MISC_INFO_ACCESS  susModeMiscInfo;
+  UCHAR                       ucCRTC;           // ATOM_CRTC1 or ATOM_CRTC2
+  UCHAR                       ucOverscanRight;  // right
+  UCHAR                       ucOverscanLeft;   // left
+  UCHAR                       ucOverscanBottom; // bottom
+  UCHAR                       ucOverscanTop;    // top
+  UCHAR                       ucReserved;
+}SET_CRTC_TIMING_PARAMETERS;
 #define SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION SET_CRTC_TIMING_PARAMETERS
 
-/****************************************************************************/
-/*  Structure used in StandardVESA_TimingTable */
-/*                    AnalogTV_InfoTable */
-/*                    ComponentVideoInfoTable */
-/****************************************************************************/
-typedef struct _ATOM_MODE_TIMING {
-	USHORT usCRTC_H_Total;
-	USHORT usCRTC_H_Disp;
-	USHORT usCRTC_H_SyncStart;
-	USHORT usCRTC_H_SyncWidth;
-	USHORT usCRTC_V_Total;
-	USHORT usCRTC_V_Disp;
-	USHORT usCRTC_V_SyncStart;
-	USHORT usCRTC_V_SyncWidth;
-	USHORT usPixelClock;	/* in 10Khz unit */
-	ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo;
-	USHORT usCRTC_OverscanRight;
-	USHORT usCRTC_OverscanLeft;
-	USHORT usCRTC_OverscanBottom;
-	USHORT usCRTC_OverscanTop;
-	USHORT usReserve;
-	UCHAR ucInternalModeNumber;
-	UCHAR ucRefreshRate;
-} ATOM_MODE_TIMING;
+/****************************************************************************/	
+// Structure used in StandardVESA_TimingTable
+//                   AnalogTV_InfoTable 
+//                   ComponentVideoInfoTable
+/****************************************************************************/	
+typedef struct _ATOM_MODE_TIMING
+{
+  USHORT  usCRTC_H_Total;
+  USHORT  usCRTC_H_Disp;
+  USHORT  usCRTC_H_SyncStart;
+  USHORT  usCRTC_H_SyncWidth;
+  USHORT  usCRTC_V_Total;
+  USHORT  usCRTC_V_Disp;
+  USHORT  usCRTC_V_SyncStart;
+  USHORT  usCRTC_V_SyncWidth;
+  USHORT  usPixelClock;					                 //in 10Khz unit
+  ATOM_MODE_MISC_INFO_ACCESS  susModeMiscInfo;
+  USHORT  usCRTC_OverscanRight;
+  USHORT  usCRTC_OverscanLeft;
+  USHORT  usCRTC_OverscanBottom;
+  USHORT  usCRTC_OverscanTop;
+  USHORT  usReserve;
+  UCHAR   ucInternalModeNumber;
+  UCHAR   ucRefreshRate;
+}ATOM_MODE_TIMING;
 
-typedef struct _ATOM_DTD_FORMAT {
-	USHORT usPixClk;
-	USHORT usHActive;
-	USHORT usHBlanking_Time;
-	USHORT usVActive;
-	USHORT usVBlanking_Time;
-	USHORT usHSyncOffset;
-	USHORT usHSyncWidth;
-	USHORT usVSyncOffset;
-	USHORT usVSyncWidth;
-	USHORT usImageHSize;
-	USHORT usImageVSize;
-	UCHAR ucHBorder;
-	UCHAR ucVBorder;
-	ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo;
-	UCHAR ucInternalModeNumber;
-	UCHAR ucRefreshRate;
-} ATOM_DTD_FORMAT;
+typedef struct _ATOM_DTD_FORMAT
+{
+  USHORT  usPixClk;
+  USHORT  usHActive;
+  USHORT  usHBlanking_Time;
+  USHORT  usVActive;
+  USHORT  usVBlanking_Time;			
+  USHORT  usHSyncOffset;
+  USHORT  usHSyncWidth;
+  USHORT  usVSyncOffset;
+  USHORT  usVSyncWidth;
+  USHORT  usImageHSize;
+  USHORT  usImageVSize;
+  UCHAR   ucHBorder;
+  UCHAR   ucVBorder;
+  ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo;
+  UCHAR   ucInternalModeNumber;
+  UCHAR   ucRefreshRate;
+}ATOM_DTD_FORMAT;
 
-/****************************************************************************/
-/*  Structure used in LVDS_InfoTable */
-/*   * Need a document to describe this table */
-/****************************************************************************/
+/****************************************************************************/	
+// Structure used in LVDS_InfoTable 
+//  * Need a document to describe this table
+/****************************************************************************/	
 #define SUPPORTED_LCD_REFRESHRATE_30Hz          0x0004
 #define SUPPORTED_LCD_REFRESHRATE_40Hz          0x0008
 #define SUPPORTED_LCD_REFRESHRATE_50Hz          0x0010
 #define SUPPORTED_LCD_REFRESHRATE_60Hz          0x0020
 
-/* Once DAL sees this CAP is set, it will read EDID from LCD on its own instead of using sLCDTiming in ATOM_LVDS_INFO_V12. */
-/* Other entries in ATOM_LVDS_INFO_V12 are still valid/useful to DAL */
-#define	LCDPANEL_CAP_READ_EDID									0x1
+//ucTableFormatRevision=1
+//ucTableContentRevision=1
+typedef struct _ATOM_LVDS_INFO
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  ATOM_DTD_FORMAT     sLCDTiming;
+  USHORT              usModePatchTableOffset;
+  USHORT              usSupportedRefreshRate;     //Refer to panel info table in ATOMBIOS extension Spec.
+  USHORT              usOffDelayInMs;
+  UCHAR               ucPowerSequenceDigOntoDEin10Ms;
+  UCHAR               ucPowerSequenceDEtoBLOnin10Ms;
+  UCHAR               ucLVDS_Misc;               // Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level}
+                                                 // Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888}
+                                                 // Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled}
+                                                 // Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled}
+  UCHAR               ucPanelDefaultRefreshRate;
+  UCHAR               ucPanelIdentification;
+  UCHAR               ucSS_Id;
+}ATOM_LVDS_INFO;
 
-/* ucTableFormatRevision=1 */
-/* ucTableContentRevision=1 */
-typedef struct _ATOM_LVDS_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_DTD_FORMAT sLCDTiming;
-	USHORT usModePatchTableOffset;
-	USHORT usSupportedRefreshRate;	/* Refer to panel info table in ATOMBIOS extension Spec. */
-	USHORT usOffDelayInMs;
-	UCHAR ucPowerSequenceDigOntoDEin10Ms;
-	UCHAR ucPowerSequenceDEtoBLOnin10Ms;
-	UCHAR ucLVDS_Misc;	/*  Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level} */
-	/*  Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888} */
-	/*  Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled} */
-	/*  Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled} */
-	UCHAR ucPanelDefaultRefreshRate;
-	UCHAR ucPanelIdentification;
-	UCHAR ucSS_Id;
-} ATOM_LVDS_INFO;
+//ucTableFormatRevision=1
+//ucTableContentRevision=2
+typedef struct _ATOM_LVDS_INFO_V12
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  ATOM_DTD_FORMAT     sLCDTiming;
+  USHORT              usExtInfoTableOffset;
+  USHORT              usSupportedRefreshRate;     //Refer to panel info table in ATOMBIOS extension Spec.
+  USHORT              usOffDelayInMs;
+  UCHAR               ucPowerSequenceDigOntoDEin10Ms;
+  UCHAR               ucPowerSequenceDEtoBLOnin10Ms;
+  UCHAR               ucLVDS_Misc;               // Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level}
+                                                 // Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888}
+                                                 // Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled}
+                                                 // Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled}
+  UCHAR               ucPanelDefaultRefreshRate;
+  UCHAR               ucPanelIdentification;
+  UCHAR               ucSS_Id;
+  USHORT              usLCDVenderID;
+  USHORT              usLCDProductID;
+  UCHAR               ucLCDPanel_SpecialHandlingCap; 
+	UCHAR								ucPanelInfoSize;					//  start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable
+  UCHAR               ucReserved[2];
+}ATOM_LVDS_INFO_V12;
 
-/* ucTableFormatRevision=1 */
-/* ucTableContentRevision=2 */
-typedef struct _ATOM_LVDS_INFO_V12 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_DTD_FORMAT sLCDTiming;
-	USHORT usExtInfoTableOffset;
-	USHORT usSupportedRefreshRate;	/* Refer to panel info table in ATOMBIOS extension Spec. */
-	USHORT usOffDelayInMs;
-	UCHAR ucPowerSequenceDigOntoDEin10Ms;
-	UCHAR ucPowerSequenceDEtoBLOnin10Ms;
-	UCHAR ucLVDS_Misc;	/*  Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level} */
-	/*  Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888} */
-	/*  Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled} */
-	/*  Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled} */
-	UCHAR ucPanelDefaultRefreshRate;
-	UCHAR ucPanelIdentification;
-	UCHAR ucSS_Id;
-	USHORT usLCDVenderID;
-	USHORT usLCDProductID;
-	UCHAR ucLCDPanel_SpecialHandlingCap;
-	UCHAR ucPanelInfoSize;	/*   start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable */
-	UCHAR ucReserved[2];
-} ATOM_LVDS_INFO_V12;
+//Definitions for ucLCDPanel_SpecialHandlingCap:
+
+//Once DAL sees this CAP is set, it will read EDID from LCD on its own instead of using sLCDTiming in ATOM_LVDS_INFO_V12. 
+//Other entries in ATOM_LVDS_INFO_V12 are still valid/useful to DAL 
+#define	LCDPANEL_CAP_READ_EDID                  0x1
+
+//If a design supports DRR (dynamic refresh rate) on internal panels (LVDS or EDP), this cap is set in ucLCDPanel_SpecialHandlingCap together
+//with multiple supported refresh rates@usSupportedRefreshRate. This cap should not be set when only slow refresh rate is supported (static
+//refresh rate switch by SW. This is only valid from ATOM_LVDS_INFO_V12
+#define	LCDPANEL_CAP_DRR_SUPPORTED              0x2
+
+//Use this cap bit for a quick reference whether an embadded panel (LCD1 ) is LVDS or eDP.
+#define	LCDPANEL_CAP_eDP                        0x4
+
+
+//Color Bit Depth definition in EDID V1.4 @BYTE 14h
+//Bit 6  5  4
+                              //      0  0  0  -  Color bit depth is undefined
+                              //      0  0  1  -  6 Bits per Primary Color
+                              //      0  1  0  -  8 Bits per Primary Color
+                              //      0  1  1  - 10 Bits per Primary Color
+                              //      1  0  0  - 12 Bits per Primary Color
+                              //      1  0  1  - 14 Bits per Primary Color
+                              //      1  1  0  - 16 Bits per Primary Color
+                              //      1  1  1  - Reserved
+
+#define PANEL_COLOR_BIT_DEPTH_MASK    0x70
+
+// Bit7:{=0:Random Dithering disabled;1 Random Dithering enabled}   
+#define PANEL_RANDOM_DITHER   0x80
+#define PANEL_RANDOM_DITHER_MASK   0x80
+
 
 #define ATOM_LVDS_INFO_LAST  ATOM_LVDS_INFO_V12
 
-typedef struct _ATOM_PATCH_RECORD_MODE {
-	UCHAR ucRecordType;
-	USHORT usHDisp;
-	USHORT usVDisp;
-} ATOM_PATCH_RECORD_MODE;
+typedef struct  _ATOM_PATCH_RECORD_MODE
+{
+  UCHAR     ucRecordType;
+  USHORT    usHDisp;
+  USHORT    usVDisp;
+}ATOM_PATCH_RECORD_MODE;
 
-typedef struct _ATOM_LCD_RTS_RECORD {
-	UCHAR ucRecordType;
-	UCHAR ucRTSValue;
-} ATOM_LCD_RTS_RECORD;
+typedef struct  _ATOM_LCD_RTS_RECORD
+{
+  UCHAR     ucRecordType;
+  UCHAR     ucRTSValue;
+}ATOM_LCD_RTS_RECORD;
 
-/* !! If the record below exits, it shoud always be the first record for easy use in command table!!! */
-typedef struct _ATOM_LCD_MODE_CONTROL_CAP {
-	UCHAR ucRecordType;
-	USHORT usLCDCap;
-} ATOM_LCD_MODE_CONTROL_CAP;
+//!! If the record below exits, it shoud always be the first record for easy use in command table!!! 
+// The record below is only used when LVDS_Info is present. From ATOM_LVDS_INFO_V12, use ucLCDPanel_SpecialHandlingCap instead.
+typedef struct  _ATOM_LCD_MODE_CONTROL_CAP
+{
+  UCHAR     ucRecordType;
+  USHORT    usLCDCap;
+}ATOM_LCD_MODE_CONTROL_CAP;
 
 #define LCD_MODE_CAP_BL_OFF                   1
 #define LCD_MODE_CAP_CRTC_OFF                 2
 #define LCD_MODE_CAP_PANEL_OFF                4
 
-typedef struct _ATOM_FAKE_EDID_PATCH_RECORD {
-	UCHAR ucRecordType;
-	UCHAR ucFakeEDIDLength;
-	UCHAR ucFakeEDIDString[1];	/*  This actually has ucFakeEdidLength elements. */
+typedef struct _ATOM_FAKE_EDID_PATCH_RECORD
+{
+  UCHAR ucRecordType;
+  UCHAR ucFakeEDIDLength;
+  UCHAR ucFakeEDIDString[1];    // This actually has ucFakeEdidLength elements.
 } ATOM_FAKE_EDID_PATCH_RECORD;
 
-typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD {
-	UCHAR ucRecordType;
-	USHORT usHSize;
-	USHORT usVSize;
-} ATOM_PANEL_RESOLUTION_PATCH_RECORD;
+typedef struct  _ATOM_PANEL_RESOLUTION_PATCH_RECORD
+{
+   UCHAR    ucRecordType;
+   USHORT		usHSize;
+   USHORT		usVSize;
+}ATOM_PANEL_RESOLUTION_PATCH_RECORD;
 
 #define LCD_MODE_PATCH_RECORD_MODE_TYPE       1
 #define LCD_RTS_RECORD_TYPE                   2
@@ -2306,21 +2829,25 @@
 
 /****************************Spread Spectrum Info Table Definitions **********************/
 
-/* ucTableFormatRevision=1 */
-/* ucTableContentRevision=2 */
-typedef struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT {
-	USHORT usSpreadSpectrumPercentage;
-	UCHAR ucSpreadSpectrumType;	/* Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */
-	UCHAR ucSS_Step;
-	UCHAR ucSS_Delay;
-	UCHAR ucSS_Id;
-	UCHAR ucRecommendedRef_Div;
-	UCHAR ucSS_Range;	/* it was reserved for V11 */
-} ATOM_SPREAD_SPECTRUM_ASSIGNMENT;
+//ucTableFormatRevision=1
+//ucTableContentRevision=2
+typedef struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT
+{
+  USHORT              usSpreadSpectrumPercentage; 
+  UCHAR               ucSpreadSpectrumType;	    //Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Bit2=1: PCIE REFCLK SS =0 iternal PPLL SS  Others:TBD
+  UCHAR               ucSS_Step;
+  UCHAR               ucSS_Delay;
+  UCHAR               ucSS_Id;
+  UCHAR               ucRecommendedRef_Div;
+  UCHAR               ucSS_Range;               //it was reserved for V11
+}ATOM_SPREAD_SPECTRUM_ASSIGNMENT;
 
 #define ATOM_MAX_SS_ENTRY                      16
-#define ATOM_DP_SS_ID1												 0x0f1	/*  SS modulation freq=30k */
-#define ATOM_DP_SS_ID2												 0x0f2	/*  SS modulation freq=33k */
+#define ATOM_DP_SS_ID1												 0x0f1			// SS ID for internal DP stream at 2.7Ghz. if ATOM_DP_SS_ID2 does not exist in SS_InfoTable, it is used for internal DP stream at 1.62Ghz as well. 
+#define ATOM_DP_SS_ID2												 0x0f2			// SS ID for internal DP stream at 1.62Ghz, if it exists in SS_InfoTable. 
+#define ATOM_LVLINK_2700MHz_SS_ID              0x0f3      // SS ID for LV link translator chip at 2.7Ghz
+#define ATOM_LVLINK_1620MHz_SS_ID              0x0f4      // SS ID for LV link translator chip at 1.62Ghz
+
 
 #define ATOM_SS_DOWN_SPREAD_MODE_MASK          0x00000000
 #define ATOM_SS_DOWN_SPREAD_MODE               0x00000000
@@ -2329,29 +2856,30 @@
 #define ATOM_INTERNAL_SS_MASK                  0x00000000
 #define ATOM_EXTERNAL_SS_MASK                  0x00000002
 #define EXEC_SS_STEP_SIZE_SHIFT                2
-#define EXEC_SS_DELAY_SHIFT                    4
+#define EXEC_SS_DELAY_SHIFT                    4    
 #define ACTIVEDATA_TO_BLON_DELAY_SHIFT         4
 
-typedef struct _ATOM_SPREAD_SPECTRUM_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_SPREAD_SPECTRUM_ASSIGNMENT asSS_Info[ATOM_MAX_SS_ENTRY];
-} ATOM_SPREAD_SPECTRUM_INFO;
+typedef struct _ATOM_SPREAD_SPECTRUM_INFO
+{ 
+  ATOM_COMMON_TABLE_HEADER	sHeader;
+  ATOM_SPREAD_SPECTRUM_ASSIGNMENT   asSS_Info[ATOM_MAX_SS_ENTRY];
+}ATOM_SPREAD_SPECTRUM_INFO;
 
-/****************************************************************************/
-/*  Structure used in AnalogTV_InfoTable (Top level) */
-/****************************************************************************/
-/* ucTVBootUpDefaultStd definiton: */
+/****************************************************************************/	
+// Structure used in AnalogTV_InfoTable (Top level)
+/****************************************************************************/	
+//ucTVBootUpDefaultStd definiton:
 
-/* ATOM_TV_NTSC                1 */
-/* ATOM_TV_NTSCJ               2 */
-/* ATOM_TV_PAL                 3 */
-/* ATOM_TV_PALM                4 */
-/* ATOM_TV_PALCN               5 */
-/* ATOM_TV_PALN                6 */
-/* ATOM_TV_PAL60               7 */
-/* ATOM_TV_SECAM               8 */
+//ATOM_TV_NTSC                1
+//ATOM_TV_NTSCJ               2
+//ATOM_TV_PAL                 3
+//ATOM_TV_PALM                4
+//ATOM_TV_PALCN               5
+//ATOM_TV_PALN                6
+//ATOM_TV_PAL60               7
+//ATOM_TV_SECAM               8
 
-/* ucTVSuppportedStd definition: */
+//ucTVSupportedStd definition:
 #define NTSC_SUPPORT          0x1
 #define NTSCJ_SUPPORT         0x2
 
@@ -2364,46 +2892,58 @@
 
 #define MAX_SUPPORTED_TV_TIMING    2
 
-typedef struct _ATOM_ANALOG_TV_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR ucTV_SupportedStandard;
-	UCHAR ucTV_BootUpDefaultStandard;
-	UCHAR ucExt_TV_ASIC_ID;
-	UCHAR ucExt_TV_ASIC_SlaveAddr;
-	/*ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING]; */
-	ATOM_MODE_TIMING aModeTimings[MAX_SUPPORTED_TV_TIMING];
-} ATOM_ANALOG_TV_INFO;
+typedef struct _ATOM_ANALOG_TV_INFO
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  UCHAR                    ucTV_SupportedStandard;
+  UCHAR                    ucTV_BootUpDefaultStandard; 
+  UCHAR                    ucExt_TV_ASIC_ID;
+  UCHAR                    ucExt_TV_ASIC_SlaveAddr;
+  /*ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING];*/
+  ATOM_MODE_TIMING         aModeTimings[MAX_SUPPORTED_TV_TIMING];
+}ATOM_ANALOG_TV_INFO;
 
 #define MAX_SUPPORTED_TV_TIMING_V1_2    3
 
-typedef struct _ATOM_ANALOG_TV_INFO_V1_2 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR                    ucTV_SupportedStandard;
-	UCHAR                    ucTV_BootUpDefaultStandard;
-	UCHAR                    ucExt_TV_ASIC_ID;
-	UCHAR                    ucExt_TV_ASIC_SlaveAddr;
-	ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING];
-} ATOM_ANALOG_TV_INFO_V1_2;
+typedef struct _ATOM_ANALOG_TV_INFO_V1_2
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  UCHAR                    ucTV_SupportedStandard;
+  UCHAR                    ucTV_BootUpDefaultStandard; 
+  UCHAR                    ucExt_TV_ASIC_ID;
+  UCHAR                    ucExt_TV_ASIC_SlaveAddr;
+  ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING];
+}ATOM_ANALOG_TV_INFO_V1_2;
+
+typedef struct _ATOM_DPCD_INFO
+{
+  UCHAR   ucRevisionNumber;        //10h : Revision 1.0; 11h : Revision 1.1   
+  UCHAR   ucMaxLinkRate;           //06h : 1.62Gbps per lane; 0Ah = 2.7Gbps per lane
+  UCHAR   ucMaxLane;               //Bits 4:0 = MAX_LANE_COUNT (1/2/4). Bit 7 = ENHANCED_FRAME_CAP 
+  UCHAR   ucMaxDownSpread;         //Bit0 = 0: No Down spread; Bit0 = 1: 0.5% (Subject to change according to DP spec)
+}ATOM_DPCD_INFO;
+
+#define ATOM_DPCD_MAX_LANE_MASK    0x1F
 
 /**************************************************************************/
-/*  VRAM usage and their definitions */
+// VRAM usage and their defintions
 
-/*  One chunk of VRAM used by Bios are for HWICON surfaces,EDID data. */
-/*  Current Mode timing and Dail Timing and/or STD timing data EACH device. They can be broken down as below. */
-/*  All the addresses below are the offsets from the frame buffer start.They all MUST be Dword aligned! */
-/*  To driver: The physical address of this memory portion=mmFB_START(4K aligned)+ATOMBIOS_VRAM_USAGE_START_ADDR+ATOM_x_ADDR */
-/*  To Bios:  ATOMBIOS_VRAM_USAGE_START_ADDR+ATOM_x_ADDR->MM_INDEX */
+// One chunk of VRAM used by Bios are for HWICON surfaces,EDID data.
+// Current Mode timing and Dail Timing and/or STD timing data EACH device. They can be broken down as below.
+// All the addresses below are the offsets from the frame buffer start.They all MUST be Dword aligned!
+// To driver: The physical address of this memory portion=mmFB_START(4K aligned)+ATOMBIOS_VRAM_USAGE_START_ADDR+ATOM_x_ADDR
+// To Bios:  ATOMBIOS_VRAM_USAGE_START_ADDR+ATOM_x_ADDR->MM_INDEX 
 
 #ifndef VESA_MEMORY_IN_64K_BLOCK
-#define VESA_MEMORY_IN_64K_BLOCK        0x100	/* 256*64K=16Mb (Max. VESA memory is 16Mb!) */
+#define VESA_MEMORY_IN_64K_BLOCK        0x100       //256*64K=16Mb (Max. VESA memory is 16Mb!)
 #endif
 
-#define ATOM_EDID_RAW_DATASIZE          256	/* In Bytes */
-#define ATOM_HWICON_SURFACE_SIZE        4096	/* In Bytes */
+#define ATOM_EDID_RAW_DATASIZE          256         //In Bytes
+#define ATOM_HWICON_SURFACE_SIZE        4096        //In Bytes
 #define ATOM_HWICON_INFOTABLE_SIZE      32
 #define MAX_DTD_MODE_IN_VRAM            6
-#define ATOM_DTD_MODE_SUPPORT_TBL_SIZE  (MAX_DTD_MODE_IN_VRAM*28)	/* 28= (SIZEOF ATOM_DTD_FORMAT) */
-#define ATOM_STD_MODE_SUPPORT_TBL_SIZE  (32*8)	/* 32 is a predefined number,8= (SIZEOF ATOM_STD_FORMAT) */
+#define ATOM_DTD_MODE_SUPPORT_TBL_SIZE  (MAX_DTD_MODE_IN_VRAM*28)    //28= (SIZEOF ATOM_DTD_FORMAT) 
+#define ATOM_STD_MODE_SUPPORT_TBL_SIZE  32*8                         //32 is a predefined number,8= (SIZEOF ATOM_STD_FORMAT)
 #define DFP_ENCODER_TYPE_OFFSET					0x80
 #define DP_ENCODER_LANE_NUM_OFFSET			0x84
 #define DP_ENCODER_LINK_RATE_OFFSET			0x88
@@ -2417,7 +2957,7 @@
 
 #define ATOM_LCD1_EDID_ADDR             (ATOM_CRT1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
 #define ATOM_LCD1_DTD_MODE_TBL_ADDR     (ATOM_LCD1_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
-#define ATOM_LCD1_STD_MODE_TBL_ADDR	(ATOM_LCD1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_LCD1_STD_MODE_TBL_ADDR   	(ATOM_LCD1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
 
 #define ATOM_TV1_DTD_MODE_TBL_ADDR      (ATOM_LCD1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
 
@@ -2431,13 +2971,13 @@
 
 #define ATOM_LCD2_EDID_ADDR             (ATOM_CRT2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
 #define ATOM_LCD2_DTD_MODE_TBL_ADDR     (ATOM_LCD2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
-#define ATOM_LCD2_STD_MODE_TBL_ADDR	(ATOM_LCD2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_LCD2_STD_MODE_TBL_ADDR   	(ATOM_LCD2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
 
-#define ATOM_TV2_EDID_ADDR              (ATOM_LCD2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
-#define ATOM_TV2_DTD_MODE_TBL_ADDR      (ATOM_TV2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
-#define ATOM_TV2_STD_MODE_TBL_ADDR	  (ATOM_TV2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_DFP6_EDID_ADDR             (ATOM_LCD2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_DFP6_DTD_MODE_TBL_ADDR     (ATOM_DFP6_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
+#define ATOM_DFP6_STD_MODE_TBL_ADDR     (ATOM_DFP6_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
 
-#define ATOM_DFP2_EDID_ADDR             (ATOM_TV2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_DFP2_EDID_ADDR             (ATOM_DFP6_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE)
 #define ATOM_DFP2_DTD_MODE_TBL_ADDR     (ATOM_DFP2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
 #define ATOM_DFP2_STD_MODE_TBL_ADDR     (ATOM_DFP2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
 
@@ -2457,533 +2997,850 @@
 #define ATOM_DFP5_DTD_MODE_TBL_ADDR     (ATOM_DFP5_EDID_ADDR + ATOM_EDID_RAW_DATASIZE)
 #define ATOM_DFP5_STD_MODE_TBL_ADDR     (ATOM_DFP5_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE)
 
-#define ATOM_DP_TRAINING_TBL_ADDR	(ATOM_DFP5_STD_MODE_TBL_ADDR+ATOM_STD_MODE_SUPPORT_TBL_SIZE)
+#define ATOM_DP_TRAINING_TBL_ADDR				(ATOM_DFP5_STD_MODE_TBL_ADDR+ATOM_STD_MODE_SUPPORT_TBL_SIZE)       
 
-#define ATOM_STACK_STORAGE_START        (ATOM_DP_TRAINING_TBL_ADDR + 256)
-#define ATOM_STACK_STORAGE_END          (ATOM_STACK_STORAGE_START + 512)
+#define ATOM_STACK_STORAGE_START        (ATOM_DP_TRAINING_TBL_ADDR+256)       
+#define ATOM_STACK_STORAGE_END          ATOM_STACK_STORAGE_START+512        
 
-/* The size below is in Kb! */
+//The size below is in Kb!
 #define ATOM_VRAM_RESERVE_SIZE         ((((ATOM_STACK_STORAGE_END - ATOM_HWICON1_SURFACE_ADDR)>>10)+4)&0xFFFC)
-
+   
 #define	ATOM_VRAM_OPERATION_FLAGS_MASK         0xC0000000L
 #define ATOM_VRAM_OPERATION_FLAGS_SHIFT        30
 #define	ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION   0x1
 #define	ATOM_VRAM_BLOCK_NEEDS_RESERVATION      0x0
 
-/***********************************************************************************/
-/*  Structure used in VRAM_UsageByFirmwareTable */
-/*  Note1: This table is filled by SetBiosReservationStartInFB in CoreCommSubs.asm */
-/*         at running time. */
-/*  note2: From RV770, the memory is more than 32bit addressable, so we will change */
-/*         ucTableFormatRevision=1,ucTableContentRevision=4, the strcuture remains */
-/*         exactly same as 1.1 and 1.2 (1.3 is never in use), but ulStartAddrUsedByFirmware */
-/*         (in offset to start of memory address) is KB aligned instead of byte aligend. */
-/***********************************************************************************/
+/***********************************************************************************/	
+// Structure used in VRAM_UsageByFirmwareTable
+// Note1: This table is filled by SetBiosReservationStartInFB in CoreCommSubs.asm
+//        at running time.   
+// note2: From RV770, the memory is more than 32bit addressable, so we will change 
+//        ucTableFormatRevision=1,ucTableContentRevision=4, the strcuture remains 
+//        exactly same as 1.1 and 1.2 (1.3 is never in use), but ulStartAddrUsedByFirmware 
+//        (in offset to start of memory address) is KB aligned instead of byte aligend.
+/***********************************************************************************/	
+// Note3:
+/* If we change usReserved to "usFBUsedbyDrvInKB", then to VBIOS this usFBUsedbyDrvInKB is a predefined, unchanged constant across VGA or non VGA adapter,
+for CAIL, The size of FB access area is known, only thing missing is the Offset of FB Access area, so we can  have:
+
+If (ulStartAddrUsedByFirmware!=0)
+FBAccessAreaOffset= ulStartAddrUsedByFirmware - usFBUsedbyDrvInKB;
+Reserved area has been claimed by VBIOS including this FB access area; CAIL doesn't need to reserve any extra area for this purpose
+else	//Non VGA case
+ if (FB_Size<=2Gb)
+    FBAccessAreaOffset= FB_Size - usFBUsedbyDrvInKB;
+ else
+	  FBAccessAreaOffset= Aper_Size - usFBUsedbyDrvInKB
+
+CAIL needs to claim an reserved area defined by FBAccessAreaOffset and usFBUsedbyDrvInKB in non VGA case.*/
+
 #define ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO			1
 
-typedef struct _ATOM_FIRMWARE_VRAM_RESERVE_INFO {
-	ULONG ulStartAddrUsedByFirmware;
-	USHORT usFirmwareUseInKb;
-	USHORT usReserved;
-} ATOM_FIRMWARE_VRAM_RESERVE_INFO;
+typedef struct _ATOM_FIRMWARE_VRAM_RESERVE_INFO
+{
+  ULONG   ulStartAddrUsedByFirmware;
+  USHORT  usFirmwareUseInKb;
+  USHORT  usReserved;
+}ATOM_FIRMWARE_VRAM_RESERVE_INFO;
 
-typedef struct _ATOM_VRAM_USAGE_BY_FIRMWARE {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_FIRMWARE_VRAM_RESERVE_INFO
-	    asFirmwareVramReserveInfo[ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO];
-} ATOM_VRAM_USAGE_BY_FIRMWARE;
+typedef struct _ATOM_VRAM_USAGE_BY_FIRMWARE
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  ATOM_FIRMWARE_VRAM_RESERVE_INFO	asFirmwareVramReserveInfo[ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO];
+}ATOM_VRAM_USAGE_BY_FIRMWARE;
 
-/****************************************************************************/
-/*  Structure used in GPIO_Pin_LUTTable */
-/****************************************************************************/
-typedef struct _ATOM_GPIO_PIN_ASSIGNMENT {
-	USHORT usGpioPin_AIndex;
-	UCHAR ucGpioPinBitShift;
-	UCHAR ucGPIO_ID;
-} ATOM_GPIO_PIN_ASSIGNMENT;
+// change verion to 1.5, when allow driver to allocate the vram area for command table access. 
+typedef struct _ATOM_FIRMWARE_VRAM_RESERVE_INFO_V1_5
+{
+  ULONG   ulStartAddrUsedByFirmware;
+  USHORT  usFirmwareUseInKb;
+  USHORT  usFBUsedByDrvInKb;
+}ATOM_FIRMWARE_VRAM_RESERVE_INFO_V1_5;
 
-typedef struct _ATOM_GPIO_PIN_LUT {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_GPIO_PIN_ASSIGNMENT asGPIO_Pin[1];
-} ATOM_GPIO_PIN_LUT;
+typedef struct _ATOM_VRAM_USAGE_BY_FIRMWARE_V1_5
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  ATOM_FIRMWARE_VRAM_RESERVE_INFO_V1_5	asFirmwareVramReserveInfo[ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO];
+}ATOM_VRAM_USAGE_BY_FIRMWARE_V1_5;
 
-/****************************************************************************/
-/*  Structure used in ComponentVideoInfoTable */
-/****************************************************************************/
+/****************************************************************************/	
+// Structure used in GPIO_Pin_LUTTable
+/****************************************************************************/	
+typedef struct _ATOM_GPIO_PIN_ASSIGNMENT
+{
+  USHORT                   usGpioPin_AIndex;
+  UCHAR                    ucGpioPinBitShift;
+  UCHAR                    ucGPIO_ID;
+}ATOM_GPIO_PIN_ASSIGNMENT;
+
+typedef struct _ATOM_GPIO_PIN_LUT
+{
+  ATOM_COMMON_TABLE_HEADER  sHeader;
+  ATOM_GPIO_PIN_ASSIGNMENT	asGPIO_Pin[1];
+}ATOM_GPIO_PIN_LUT;
+
+/****************************************************************************/	
+// Structure used in ComponentVideoInfoTable	
+/****************************************************************************/	
 #define GPIO_PIN_ACTIVE_HIGH          0x1
 
 #define MAX_SUPPORTED_CV_STANDARDS    5
 
-/*  definitions for ATOM_D_INFO.ucSettings */
-#define ATOM_GPIO_SETTINGS_BITSHIFT_MASK  0x1F	/*  [4:0] */
-#define ATOM_GPIO_SETTINGS_RESERVED_MASK  0x60	/*  [6:5] = must be zeroed out */
-#define ATOM_GPIO_SETTINGS_ACTIVE_MASK    0x80	/*  [7] */
+// definitions for ATOM_D_INFO.ucSettings
+#define ATOM_GPIO_SETTINGS_BITSHIFT_MASK  0x1F    // [4:0]
+#define ATOM_GPIO_SETTINGS_RESERVED_MASK  0x60    // [6:5] = must be zeroed out
+#define ATOM_GPIO_SETTINGS_ACTIVE_MASK    0x80    // [7]
 
-typedef struct _ATOM_GPIO_INFO {
-	USHORT usAOffset;
-	UCHAR ucSettings;
-	UCHAR ucReserved;
-} ATOM_GPIO_INFO;
+typedef struct _ATOM_GPIO_INFO
+{
+  USHORT  usAOffset;
+  UCHAR   ucSettings;
+  UCHAR   ucReserved;
+}ATOM_GPIO_INFO;
 
-/*  definitions for ATOM_COMPONENT_VIDEO_INFO.ucMiscInfo (bit vector) */
+// definitions for ATOM_COMPONENT_VIDEO_INFO.ucMiscInfo (bit vector)
 #define ATOM_CV_RESTRICT_FORMAT_SELECTION           0x2
 
-/*  definitions for ATOM_COMPONENT_VIDEO_INFO.uc480i/uc480p/uc720p/uc1080i */
-#define ATOM_GPIO_DEFAULT_MODE_EN                   0x80	/* [7]; */
-#define ATOM_GPIO_SETTING_PERMODE_MASK              0x7F	/* [6:0] */
+// definitions for ATOM_COMPONENT_VIDEO_INFO.uc480i/uc480p/uc720p/uc1080i
+#define ATOM_GPIO_DEFAULT_MODE_EN                   0x80 //[7];
+#define ATOM_GPIO_SETTING_PERMODE_MASK              0x7F //[6:0]
 
-/*  definitions for ATOM_COMPONENT_VIDEO_INFO.ucLetterBoxMode */
-/* Line 3 out put 5V. */
-#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_A       0x01	/* represent gpio 3 state for 16:9 */
-#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_B       0x02	/* represent gpio 4 state for 16:9 */
-#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_SHIFT   0x0
+// definitions for ATOM_COMPONENT_VIDEO_INFO.ucLetterBoxMode
+//Line 3 out put 5V.
+#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_A       0x01     //represent gpio 3 state for 16:9
+#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_B       0x02     //represent gpio 4 state for 16:9
+#define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_SHIFT   0x0   
 
-/* Line 3 out put 2.2V */
-#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_A 0x04	/* represent gpio 3 state for 4:3 Letter box */
-#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_B 0x08	/* represent gpio 4 state for 4:3 Letter box */
-#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_SHIFT 0x2
+//Line 3 out put 2.2V              
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_A 0x04     //represent gpio 3 state for 4:3 Letter box
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_B 0x08     //represent gpio 4 state for 4:3 Letter box
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_SHIFT 0x2     
 
-/* Line 3 out put 0V */
-#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_A        0x10	/* represent gpio 3 state for 4:3 */
-#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_B        0x20	/* represent gpio 4 state for 4:3 */
-#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_SHIFT    0x4
+//Line 3 out put 0V
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_A        0x10     //represent gpio 3 state for 4:3
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_B        0x20     //represent gpio 4 state for 4:3
+#define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_SHIFT    0x4 
 
-#define ATOM_CV_LINE3_ASPECTRATIO_MASK              0x3F	/*  bit [5:0] */
+#define ATOM_CV_LINE3_ASPECTRATIO_MASK              0x3F     // bit [5:0]
 
-#define ATOM_CV_LINE3_ASPECTRATIO_EXIST             0x80	/* bit 7 */
+#define ATOM_CV_LINE3_ASPECTRATIO_EXIST             0x80     //bit 7
 
-/* GPIO bit index in gpio setting per mode value, also represend the block no. in gpio blocks. */
-#define ATOM_GPIO_INDEX_LINE3_ASPECRATIO_GPIO_A   3	/* bit 3 in uc480i/uc480p/uc720p/uc1080i, which represend the default gpio bit setting for the mode. */
-#define ATOM_GPIO_INDEX_LINE3_ASPECRATIO_GPIO_B   4	/* bit 4 in uc480i/uc480p/uc720p/uc1080i, which represend the default gpio bit setting for the mode. */
+//GPIO bit index in gpio setting per mode value, also represend the block no. in gpio blocks.
+#define ATOM_GPIO_INDEX_LINE3_ASPECRATIO_GPIO_A   3   //bit 3 in uc480i/uc480p/uc720p/uc1080i, which represend the default gpio bit setting for the mode.
+#define ATOM_GPIO_INDEX_LINE3_ASPECRATIO_GPIO_B   4   //bit 4 in uc480i/uc480p/uc720p/uc1080i, which represend the default gpio bit setting for the mode.
 
-typedef struct _ATOM_COMPONENT_VIDEO_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usMask_PinRegisterIndex;
-	USHORT usEN_PinRegisterIndex;
-	USHORT usY_PinRegisterIndex;
-	USHORT usA_PinRegisterIndex;
-	UCHAR ucBitShift;
-	UCHAR ucPinActiveState;	/* ucPinActiveState: Bit0=1 active high, =0 active low */
-	ATOM_DTD_FORMAT sReserved;	/*  must be zeroed out */
-	UCHAR ucMiscInfo;
-	UCHAR uc480i;
-	UCHAR uc480p;
-	UCHAR uc720p;
-	UCHAR uc1080i;
-	UCHAR ucLetterBoxMode;
-	UCHAR ucReserved[3];
-	UCHAR ucNumOfWbGpioBlocks;	/* For Component video D-Connector support. If zere, NTSC type connector */
-	ATOM_GPIO_INFO aWbGpioStateBlock[MAX_SUPPORTED_CV_STANDARDS];
-	ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_CV_STANDARDS];
-} ATOM_COMPONENT_VIDEO_INFO;
 
-/* ucTableFormatRevision=2 */
-/* ucTableContentRevision=1 */
-typedef struct _ATOM_COMPONENT_VIDEO_INFO_V21 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR ucMiscInfo;
-	UCHAR uc480i;
-	UCHAR uc480p;
-	UCHAR uc720p;
-	UCHAR uc1080i;
-	UCHAR ucReserved;
-	UCHAR ucLetterBoxMode;
-	UCHAR ucNumOfWbGpioBlocks;	/* For Component video D-Connector support. If zere, NTSC type connector */
-	ATOM_GPIO_INFO aWbGpioStateBlock[MAX_SUPPORTED_CV_STANDARDS];
-	ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_CV_STANDARDS];
-} ATOM_COMPONENT_VIDEO_INFO_V21;
+typedef struct _ATOM_COMPONENT_VIDEO_INFO
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;
+  USHORT             usMask_PinRegisterIndex;
+  USHORT             usEN_PinRegisterIndex;
+  USHORT             usY_PinRegisterIndex;
+  USHORT             usA_PinRegisterIndex;
+  UCHAR              ucBitShift;
+  UCHAR              ucPinActiveState;  //ucPinActiveState: Bit0=1 active high, =0 active low
+  ATOM_DTD_FORMAT    sReserved;         // must be zeroed out
+  UCHAR              ucMiscInfo;
+  UCHAR              uc480i;
+  UCHAR              uc480p;
+  UCHAR              uc720p;
+  UCHAR              uc1080i;
+  UCHAR              ucLetterBoxMode;
+  UCHAR              ucReserved[3];
+  UCHAR              ucNumOfWbGpioBlocks; //For Component video D-Connector support. If zere, NTSC type connector
+  ATOM_GPIO_INFO     aWbGpioStateBlock[MAX_SUPPORTED_CV_STANDARDS];
+  ATOM_DTD_FORMAT    aModeTimings[MAX_SUPPORTED_CV_STANDARDS];
+}ATOM_COMPONENT_VIDEO_INFO;
+
+//ucTableFormatRevision=2
+//ucTableContentRevision=1
+typedef struct _ATOM_COMPONENT_VIDEO_INFO_V21
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;
+  UCHAR              ucMiscInfo;
+  UCHAR              uc480i;
+  UCHAR              uc480p;
+  UCHAR              uc720p;
+  UCHAR              uc1080i;
+  UCHAR              ucReserved;
+  UCHAR              ucLetterBoxMode;
+  UCHAR              ucNumOfWbGpioBlocks; //For Component video D-Connector support. If zere, NTSC type connector
+  ATOM_GPIO_INFO     aWbGpioStateBlock[MAX_SUPPORTED_CV_STANDARDS];
+  ATOM_DTD_FORMAT    aModeTimings[MAX_SUPPORTED_CV_STANDARDS];
+}ATOM_COMPONENT_VIDEO_INFO_V21;
 
 #define ATOM_COMPONENT_VIDEO_INFO_LAST  ATOM_COMPONENT_VIDEO_INFO_V21
 
-/****************************************************************************/
-/*  Structure used in object_InfoTable */
-/****************************************************************************/
-typedef struct _ATOM_OBJECT_HEADER {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usDeviceSupport;
-	USHORT usConnectorObjectTableOffset;
-	USHORT usRouterObjectTableOffset;
-	USHORT usEncoderObjectTableOffset;
-	USHORT usProtectionObjectTableOffset;	/* only available when Protection block is independent. */
-	USHORT usDisplayPathTableOffset;
-} ATOM_OBJECT_HEADER;
+/****************************************************************************/	
+// Structure used in object_InfoTable
+/****************************************************************************/	
+typedef struct _ATOM_OBJECT_HEADER
+{ 
+  ATOM_COMMON_TABLE_HEADER	sHeader;
+  USHORT                    usDeviceSupport;
+  USHORT                    usConnectorObjectTableOffset;
+  USHORT                    usRouterObjectTableOffset;
+  USHORT                    usEncoderObjectTableOffset;
+  USHORT                    usProtectionObjectTableOffset; //only available when Protection block is independent.
+  USHORT                    usDisplayPathTableOffset;
+}ATOM_OBJECT_HEADER;
 
-typedef struct _ATOM_DISPLAY_OBJECT_PATH {
-	USHORT usDeviceTag;	/* supported device */
-	USHORT usSize;		/* the size of ATOM_DISPLAY_OBJECT_PATH */
-	USHORT usConnObjectId;	/* Connector Object ID */
-	USHORT usGPUObjectId;	/* GPU ID */
-	USHORT usGraphicObjIds[1];	/* 1st Encoder Obj source from GPU to last Graphic Obj destinate to connector. */
-} ATOM_DISPLAY_OBJECT_PATH;
+typedef struct _ATOM_OBJECT_HEADER_V3
+{ 
+  ATOM_COMMON_TABLE_HEADER	sHeader;
+  USHORT                    usDeviceSupport;
+  USHORT                    usConnectorObjectTableOffset;
+  USHORT                    usRouterObjectTableOffset;
+  USHORT                    usEncoderObjectTableOffset;
+  USHORT                    usProtectionObjectTableOffset; //only available when Protection block is independent.
+  USHORT                    usDisplayPathTableOffset;
+  USHORT                    usMiscObjectTableOffset;
+}ATOM_OBJECT_HEADER_V3;
 
-typedef struct _ATOM_DISPLAY_OBJECT_PATH_TABLE {
-	UCHAR ucNumOfDispPath;
-	UCHAR ucVersion;
-	UCHAR ucPadding[2];
-	ATOM_DISPLAY_OBJECT_PATH asDispPath[1];
-} ATOM_DISPLAY_OBJECT_PATH_TABLE;
-
-typedef struct _ATOM_OBJECT	/* each object has this structure */
+typedef struct  _ATOM_DISPLAY_OBJECT_PATH
 {
-	USHORT usObjectID;
-	USHORT usSrcDstTableOffset;
-	USHORT usRecordOffset;	/* this pointing to a bunch of records defined below */
-	USHORT usReserved;
-} ATOM_OBJECT;
+  USHORT    usDeviceTag;                                   //supported device 
+  USHORT    usSize;                                        //the size of ATOM_DISPLAY_OBJECT_PATH
+  USHORT    usConnObjectId;                                //Connector Object ID 
+  USHORT    usGPUObjectId;                                 //GPU ID 
+  USHORT    usGraphicObjIds[1];                             //1st Encoder Obj source from GPU to last Graphic Obj destinate to connector.
+}ATOM_DISPLAY_OBJECT_PATH;
 
-typedef struct _ATOM_OBJECT_TABLE	/* Above 4 object table offset pointing to a bunch of objects all have this structure */
+typedef struct _ATOM_DISPLAY_OBJECT_PATH_TABLE
 {
-	UCHAR ucNumberOfObjects;
-	UCHAR ucPadding[3];
-	ATOM_OBJECT asObjects[1];
-} ATOM_OBJECT_TABLE;
+  UCHAR                           ucNumOfDispPath;
+  UCHAR                           ucVersion;
+  UCHAR                           ucPadding[2];
+  ATOM_DISPLAY_OBJECT_PATH        asDispPath[1];
+}ATOM_DISPLAY_OBJECT_PATH_TABLE;
 
-typedef struct _ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT	/* usSrcDstTableOffset pointing to this structure */
+
+typedef struct _ATOM_OBJECT                                //each object has this structure    
 {
-	UCHAR ucNumberOfSrc;
-	USHORT usSrcObjectID[1];
-	UCHAR ucNumberOfDst;
-	USHORT usDstObjectID[1];
-} ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT;
+  USHORT              usObjectID;
+  USHORT              usSrcDstTableOffset;
+  USHORT              usRecordOffset;                     //this pointing to a bunch of records defined below
+  USHORT              usReserved;
+}ATOM_OBJECT;
 
-/* Related definitions, all records are differnt but they have a commond header */
-typedef struct _ATOM_COMMON_RECORD_HEADER {
-	UCHAR ucRecordType;	/* An emun to indicate the record type */
-	UCHAR ucRecordSize;	/* The size of the whole record in byte */
-} ATOM_COMMON_RECORD_HEADER;
+typedef struct _ATOM_OBJECT_TABLE                         //Above 4 object table offset pointing to a bunch of objects all have this structure     
+{
+  UCHAR               ucNumberOfObjects;
+  UCHAR               ucPadding[3];
+  ATOM_OBJECT         asObjects[1];
+}ATOM_OBJECT_TABLE;
 
-#define ATOM_I2C_RECORD_TYPE                           1
+typedef struct _ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT         //usSrcDstTableOffset pointing to this structure
+{
+  UCHAR               ucNumberOfSrc;
+  USHORT              usSrcObjectID[1];
+  UCHAR               ucNumberOfDst;
+  USHORT              usDstObjectID[1];
+}ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT;
+
+
+//Two definitions below are for OPM on MXM module designs
+
+#define EXT_HPDPIN_LUTINDEX_0                   0
+#define EXT_HPDPIN_LUTINDEX_1                   1
+#define EXT_HPDPIN_LUTINDEX_2                   2
+#define EXT_HPDPIN_LUTINDEX_3                   3
+#define EXT_HPDPIN_LUTINDEX_4                   4
+#define EXT_HPDPIN_LUTINDEX_5                   5
+#define EXT_HPDPIN_LUTINDEX_6                   6
+#define EXT_HPDPIN_LUTINDEX_7                   7
+#define MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES   (EXT_HPDPIN_LUTINDEX_7+1)
+
+#define EXT_AUXDDC_LUTINDEX_0                   0
+#define EXT_AUXDDC_LUTINDEX_1                   1
+#define EXT_AUXDDC_LUTINDEX_2                   2
+#define EXT_AUXDDC_LUTINDEX_3                   3
+#define EXT_AUXDDC_LUTINDEX_4                   4
+#define EXT_AUXDDC_LUTINDEX_5                   5
+#define EXT_AUXDDC_LUTINDEX_6                   6
+#define EXT_AUXDDC_LUTINDEX_7                   7
+#define MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES   (EXT_AUXDDC_LUTINDEX_7+1)
+
+typedef struct _EXT_DISPLAY_PATH
+{
+  USHORT  usDeviceTag;                    //A bit vector to show what devices are supported 
+  USHORT  usDeviceACPIEnum;               //16bit device ACPI id. 
+  USHORT  usDeviceConnector;              //A physical connector for displays to plug in, using object connector definitions
+  UCHAR   ucExtAUXDDCLutIndex;            //An index into external AUX/DDC channel LUT
+  UCHAR   ucExtHPDPINLutIndex;            //An index into external HPD pin LUT
+  USHORT  usExtEncoderObjId;              //external encoder object id
+  USHORT  usReserved[3]; 
+}EXT_DISPLAY_PATH;
+   
+#define NUMBER_OF_UCHAR_FOR_GUID          16
+#define MAX_NUMBER_OF_EXT_DISPLAY_PATH    7
+
+typedef  struct _ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;
+  UCHAR                    ucGuid [NUMBER_OF_UCHAR_FOR_GUID];     // a GUID is a 16 byte long string
+  EXT_DISPLAY_PATH         sPath[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; // total of fixed 7 entries.
+  UCHAR                    ucChecksum;                            // a  simple Checksum of the sum of whole structure equal to 0x0. 
+  UCHAR                    Reserved [7];                          // for potential expansion
+}ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO;
+
+//Related definitions, all records are differnt but they have a commond header
+typedef struct _ATOM_COMMON_RECORD_HEADER
+{
+  UCHAR               ucRecordType;                      //An emun to indicate the record type
+  UCHAR               ucRecordSize;                      //The size of the whole record in byte
+}ATOM_COMMON_RECORD_HEADER;
+
+
+#define ATOM_I2C_RECORD_TYPE                           1         
 #define ATOM_HPD_INT_RECORD_TYPE                       2
 #define ATOM_OUTPUT_PROTECTION_RECORD_TYPE             3
 #define ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE          4
-#define	ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD_TYPE	     5	/* Obsolete, switch to use GPIO_CNTL_RECORD_TYPE */
-#define ATOM_ENCODER_FPGA_CONTROL_RECORD_TYPE          6	/* Obsolete, switch to use GPIO_CNTL_RECORD_TYPE */
+#define	ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD_TYPE	     5 //Obsolete, switch to use GPIO_CNTL_RECORD_TYPE
+#define ATOM_ENCODER_FPGA_CONTROL_RECORD_TYPE          6 //Obsolete, switch to use GPIO_CNTL_RECORD_TYPE
 #define ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD_TYPE      7
-#define ATOM_JTAG_RECORD_TYPE                          8	/* Obsolete, switch to use GPIO_CNTL_RECORD_TYPE */
+#define ATOM_JTAG_RECORD_TYPE                          8 //Obsolete, switch to use GPIO_CNTL_RECORD_TYPE
 #define ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE              9
 #define ATOM_ENCODER_DVO_CF_RECORD_TYPE               10
 #define ATOM_CONNECTOR_CF_RECORD_TYPE                 11
 #define	ATOM_CONNECTOR_HARDCODE_DTD_RECORD_TYPE	      12
 #define ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD_TYPE  13
-#define ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE				14
-#define ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE					15
+#define ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE	      14
+#define ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE	15
+#define ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE          16 //This is for the case when connectors are not known to object table
+#define ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE          17 //This is for the case when connectors are not known to object table
+#define ATOM_OBJECT_LINK_RECORD_TYPE                   18 //Once this record is present under one object, it indicats the oobject is linked to another obj described by the record
+#define ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE          19
 
-/* Must be updated when new record type is added,equal to that record definition! */
-#define ATOM_MAX_OBJECT_RECORD_NUMBER             ATOM_CONNECTOR_CF_RECORD_TYPE
 
-typedef struct _ATOM_I2C_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	ATOM_I2C_ID_CONFIG sucI2cId;
-	UCHAR ucI2CAddr;	/* The slave address, it's 0 when the record is attached to connector for DDC */
-} ATOM_I2C_RECORD;
+//Must be updated when new record type is added,equal to that record definition!
+#define ATOM_MAX_OBJECT_RECORD_NUMBER             ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE
 
-typedef struct _ATOM_HPD_INT_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	UCHAR ucHPDIntGPIOID;	/* Corresponding block in GPIO_PIN_INFO table gives the pin info */
-	UCHAR ucPlugged_PinState;
-} ATOM_HPD_INT_RECORD;
+typedef struct  _ATOM_I2C_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  ATOM_I2C_ID_CONFIG          sucI2cId; 
+  UCHAR                       ucI2CAddr;              //The slave address, it's 0 when the record is attached to connector for DDC
+}ATOM_I2C_RECORD;
 
-typedef struct _ATOM_OUTPUT_PROTECTION_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	UCHAR ucProtectionFlag;
-	UCHAR ucReserved;
-} ATOM_OUTPUT_PROTECTION_RECORD;
+typedef struct  _ATOM_HPD_INT_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  UCHAR                       ucHPDIntGPIOID;         //Corresponding block in GPIO_PIN_INFO table gives the pin info           
+  UCHAR                       ucPlugged_PinState;
+}ATOM_HPD_INT_RECORD;
 
-typedef struct _ATOM_CONNECTOR_DEVICE_TAG {
-	ULONG ulACPIDeviceEnum;	/* Reserved for now */
-	USHORT usDeviceID;	/* This Id is same as "ATOM_DEVICE_XXX_SUPPORT" */
-	USHORT usPadding;
-} ATOM_CONNECTOR_DEVICE_TAG;
 
-typedef struct _ATOM_CONNECTOR_DEVICE_TAG_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	UCHAR ucNumberOfDevice;
-	UCHAR ucReserved;
-	ATOM_CONNECTOR_DEVICE_TAG asDeviceTag[1];	/* This Id is same as "ATOM_DEVICE_XXX_SUPPORT", 1 is only for allocation */
-} ATOM_CONNECTOR_DEVICE_TAG_RECORD;
+typedef struct  _ATOM_OUTPUT_PROTECTION_RECORD 
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  UCHAR                       ucProtectionFlag;
+  UCHAR                       ucReserved;
+}ATOM_OUTPUT_PROTECTION_RECORD;
 
-typedef struct _ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	UCHAR ucConfigGPIOID;
-	UCHAR ucConfigGPIOState;	/* Set to 1 when it's active high to enable external flow in */
-	UCHAR ucFlowinGPIPID;
-	UCHAR ucExtInGPIPID;
-} ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD;
+typedef struct  _ATOM_CONNECTOR_DEVICE_TAG
+{
+  ULONG                       ulACPIDeviceEnum;       //Reserved for now
+  USHORT                      usDeviceID;             //This Id is same as "ATOM_DEVICE_XXX_SUPPORT"
+  USHORT                      usPadding;
+}ATOM_CONNECTOR_DEVICE_TAG;
 
-typedef struct _ATOM_ENCODER_FPGA_CONTROL_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	UCHAR ucCTL1GPIO_ID;
-	UCHAR ucCTL1GPIOState;	/* Set to 1 when it's active high */
-	UCHAR ucCTL2GPIO_ID;
-	UCHAR ucCTL2GPIOState;	/* Set to 1 when it's active high */
-	UCHAR ucCTL3GPIO_ID;
-	UCHAR ucCTL3GPIOState;	/* Set to 1 when it's active high */
-	UCHAR ucCTLFPGA_IN_ID;
-	UCHAR ucPadding[3];
-} ATOM_ENCODER_FPGA_CONTROL_RECORD;
+typedef struct  _ATOM_CONNECTOR_DEVICE_TAG_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  UCHAR                       ucNumberOfDevice;
+  UCHAR                       ucReserved;
+  ATOM_CONNECTOR_DEVICE_TAG   asDeviceTag[1];         //This Id is same as "ATOM_DEVICE_XXX_SUPPORT", 1 is only for allocation
+}ATOM_CONNECTOR_DEVICE_TAG_RECORD;
 
-typedef struct _ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	UCHAR ucGPIOID;		/* Corresponding block in GPIO_PIN_INFO table gives the pin info */
-	UCHAR ucTVActiveState;	/* Indicating when the pin==0 or 1 when TV is connected */
-} ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD;
 
-typedef struct _ATOM_JTAG_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	UCHAR ucTMSGPIO_ID;
-	UCHAR ucTMSGPIOState;	/* Set to 1 when it's active high */
-	UCHAR ucTCKGPIO_ID;
-	UCHAR ucTCKGPIOState;	/* Set to 1 when it's active high */
-	UCHAR ucTDOGPIO_ID;
-	UCHAR ucTDOGPIOState;	/* Set to 1 when it's active high */
-	UCHAR ucTDIGPIO_ID;
-	UCHAR ucTDIGPIOState;	/* Set to 1 when it's active high */
-	UCHAR ucPadding[2];
-} ATOM_JTAG_RECORD;
+typedef struct  _ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  UCHAR						            ucConfigGPIOID;
+  UCHAR						            ucConfigGPIOState;	    //Set to 1 when it's active high to enable external flow in
+  UCHAR                       ucFlowinGPIPID;
+  UCHAR                       ucExtInGPIPID;
+}ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD;
 
-/* The following generic object gpio pin control record type will replace JTAG_RECORD/FPGA_CONTROL_RECORD/DVI_EXT_INPUT_RECORD above gradually */
-typedef struct _ATOM_GPIO_PIN_CONTROL_PAIR {
-	UCHAR ucGPIOID;		/*  GPIO_ID, find the corresponding ID in GPIO_LUT table */
-	UCHAR ucGPIO_PinState;	/*  Pin state showing how to set-up the pin */
-} ATOM_GPIO_PIN_CONTROL_PAIR;
+typedef struct  _ATOM_ENCODER_FPGA_CONTROL_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  UCHAR                       ucCTL1GPIO_ID;
+  UCHAR                       ucCTL1GPIOState;        //Set to 1 when it's active high
+  UCHAR                       ucCTL2GPIO_ID;
+  UCHAR                       ucCTL2GPIOState;        //Set to 1 when it's active high
+  UCHAR                       ucCTL3GPIO_ID;
+  UCHAR                       ucCTL3GPIOState;        //Set to 1 when it's active high
+  UCHAR                       ucCTLFPGA_IN_ID;
+  UCHAR                       ucPadding[3];
+}ATOM_ENCODER_FPGA_CONTROL_RECORD;
 
-typedef struct _ATOM_OBJECT_GPIO_CNTL_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	UCHAR ucFlags;		/*  Future expnadibility */
-	UCHAR ucNumberOfPins;	/*  Number of GPIO pins used to control the object */
-	ATOM_GPIO_PIN_CONTROL_PAIR asGpio[1];	/*  the real gpio pin pair determined by number of pins ucNumberOfPins */
-} ATOM_OBJECT_GPIO_CNTL_RECORD;
+typedef struct  _ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  UCHAR                       ucGPIOID;               //Corresponding block in GPIO_PIN_INFO table gives the pin info 
+  UCHAR                       ucTVActiveState;        //Indicating when the pin==0 or 1 when TV is connected
+}ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD;
 
-/* Definitions for GPIO pin state */
+typedef struct  _ATOM_JTAG_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  UCHAR                       ucTMSGPIO_ID;
+  UCHAR                       ucTMSGPIOState;         //Set to 1 when it's active high
+  UCHAR                       ucTCKGPIO_ID;
+  UCHAR                       ucTCKGPIOState;         //Set to 1 when it's active high
+  UCHAR                       ucTDOGPIO_ID;
+  UCHAR                       ucTDOGPIOState;         //Set to 1 when it's active high
+  UCHAR                       ucTDIGPIO_ID;
+  UCHAR                       ucTDIGPIOState;         //Set to 1 when it's active high
+  UCHAR                       ucPadding[2];
+}ATOM_JTAG_RECORD;
+
+
+//The following generic object gpio pin control record type will replace JTAG_RECORD/FPGA_CONTROL_RECORD/DVI_EXT_INPUT_RECORD above gradually
+typedef struct _ATOM_GPIO_PIN_CONTROL_PAIR
+{
+  UCHAR                       ucGPIOID;               // GPIO_ID, find the corresponding ID in GPIO_LUT table
+  UCHAR                       ucGPIO_PinState;        // Pin state showing how to set-up the pin
+}ATOM_GPIO_PIN_CONTROL_PAIR;
+
+typedef struct  _ATOM_OBJECT_GPIO_CNTL_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  UCHAR                       ucFlags;                // Future expnadibility
+  UCHAR                       ucNumberOfPins;         // Number of GPIO pins used to control the object
+  ATOM_GPIO_PIN_CONTROL_PAIR  asGpio[1];              // the real gpio pin pair determined by number of pins ucNumberOfPins
+}ATOM_OBJECT_GPIO_CNTL_RECORD;
+
+//Definitions for GPIO pin state 
 #define GPIO_PIN_TYPE_INPUT             0x00
 #define GPIO_PIN_TYPE_OUTPUT            0x10
 #define GPIO_PIN_TYPE_HW_CONTROL        0x20
 
-/* For GPIO_PIN_TYPE_OUTPUT the following is defined */
+//For GPIO_PIN_TYPE_OUTPUT the following is defined 
 #define GPIO_PIN_OUTPUT_STATE_MASK      0x01
 #define GPIO_PIN_OUTPUT_STATE_SHIFT     0
 #define GPIO_PIN_STATE_ACTIVE_LOW       0x0
 #define GPIO_PIN_STATE_ACTIVE_HIGH      0x1
 
-typedef struct _ATOM_ENCODER_DVO_CF_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	ULONG ulStrengthControl;	/*  DVOA strength control for CF */
-	UCHAR ucPadding[2];
-} ATOM_ENCODER_DVO_CF_RECORD;
+// Indexes to GPIO array in GLSync record 
+#define ATOM_GPIO_INDEX_GLSYNC_REFCLK    0
+#define ATOM_GPIO_INDEX_GLSYNC_HSYNC     1
+#define ATOM_GPIO_INDEX_GLSYNC_VSYNC     2
+#define ATOM_GPIO_INDEX_GLSYNC_SWAP_REQ  3
+#define ATOM_GPIO_INDEX_GLSYNC_SWAP_GNT  4
+#define ATOM_GPIO_INDEX_GLSYNC_INTERRUPT 5
+#define ATOM_GPIO_INDEX_GLSYNC_V_RESET   6
+#define ATOM_GPIO_INDEX_GLSYNC_MAX       7
 
-/*  value for ATOM_CONNECTOR_CF_RECORD.ucConnectedDvoBundle */
+typedef struct  _ATOM_ENCODER_DVO_CF_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  ULONG                       ulStrengthControl;      // DVOA strength control for CF
+  UCHAR                       ucPadding[2];
+}ATOM_ENCODER_DVO_CF_RECORD;
+
+// value for ATOM_CONNECTOR_CF_RECORD.ucConnectedDvoBundle
 #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_UPPER12BITBUNDLEA   1
 #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_LOWER12BITBUNDLEB   2
 
-typedef struct _ATOM_CONNECTOR_CF_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	USHORT usMaxPixClk;
-	UCHAR ucFlowCntlGpioId;
-	UCHAR ucSwapCntlGpioId;
-	UCHAR ucConnectedDvoBundle;
-	UCHAR ucPadding;
-} ATOM_CONNECTOR_CF_RECORD;
+typedef struct  _ATOM_CONNECTOR_CF_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  USHORT                      usMaxPixClk;
+  UCHAR                       ucFlowCntlGpioId;
+  UCHAR                       ucSwapCntlGpioId;
+  UCHAR                       ucConnectedDvoBundle;
+  UCHAR                       ucPadding;
+}ATOM_CONNECTOR_CF_RECORD;
 
-typedef struct _ATOM_CONNECTOR_HARDCODE_DTD_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	ATOM_DTD_FORMAT asTiming;
-} ATOM_CONNECTOR_HARDCODE_DTD_RECORD;
+typedef struct  _ATOM_CONNECTOR_HARDCODE_DTD_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+	ATOM_DTD_FORMAT							asTiming;
+}ATOM_CONNECTOR_HARDCODE_DTD_RECORD;
 
-typedef struct _ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;	/* ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD_TYPE */
-	UCHAR ucSubConnectorType;	/* CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D|X_ID_DUAL_LINK_DVI_D|HDMI_TYPE_A */
-	UCHAR ucReserved;
-} ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD;
+typedef struct _ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;                //ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD_TYPE
+  UCHAR                       ucSubConnectorType;     //CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D|X_ID_DUAL_LINK_DVI_D|HDMI_TYPE_A
+  UCHAR                       ucReserved;
+}ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD;
 
-typedef struct _ATOM_ROUTER_DDC_PATH_SELECT_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	UCHAR ucMuxType;	/* decide the number of ucMuxState, =0, no pin state, =1: single state with complement, >1: multiple state */
-	UCHAR ucMuxControlPin;
-	UCHAR ucMuxState[2];	/* for alligment purpose */
-} ATOM_ROUTER_DDC_PATH_SELECT_RECORD;
 
-typedef struct _ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD {
-	ATOM_COMMON_RECORD_HEADER sheader;
-	UCHAR ucMuxType;
-	UCHAR ucMuxControlPin;
-	UCHAR ucMuxState[2];	/* for alligment purpose */
-} ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD;
+typedef struct _ATOM_ROUTER_DDC_PATH_SELECT_RECORD
+{
+	ATOM_COMMON_RECORD_HEADER   sheader;                
+	UCHAR												ucMuxType;							//decide the number of ucMuxState, =0, no pin state, =1: single state with complement, >1: multiple state
+	UCHAR												ucMuxControlPin;
+	UCHAR												ucMuxState[2];					//for alligment purpose
+}ATOM_ROUTER_DDC_PATH_SELECT_RECORD;
 
-/*  define ucMuxType */
+typedef struct _ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD
+{
+	ATOM_COMMON_RECORD_HEADER   sheader;                
+	UCHAR												ucMuxType;
+	UCHAR												ucMuxControlPin;
+	UCHAR												ucMuxState[2];					//for alligment purpose
+}ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD;
+
+// define ucMuxType
 #define ATOM_ROUTER_MUX_PIN_STATE_MASK								0x0f
 #define ATOM_ROUTER_MUX_PIN_SINGLE_STATE_COMPLEMENT		0x01
 
-/****************************************************************************/
-/*  ASIC voltage data table */
-/****************************************************************************/
-typedef struct _ATOM_VOLTAGE_INFO_HEADER {
-	USHORT usVDDCBaseLevel;	/* In number of 50mv unit */
-	USHORT usReserved;	/* For possible extension table offset */
-	UCHAR ucNumOfVoltageEntries;
-	UCHAR ucBytesPerVoltageEntry;
-	UCHAR ucVoltageStep;	/* Indicating in how many mv increament is one step, 0.5mv unit */
-	UCHAR ucDefaultVoltageEntry;
-	UCHAR ucVoltageControlI2cLine;
-	UCHAR ucVoltageControlAddress;
-	UCHAR ucVoltageControlOffset;
-} ATOM_VOLTAGE_INFO_HEADER;
+typedef struct _ATOM_CONNECTOR_HPDPIN_LUT_RECORD     //record for ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  UCHAR                       ucHPDPINMap[MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES];  //An fixed size array which maps external pins to internal GPIO_PIN_INFO table 
+}ATOM_CONNECTOR_HPDPIN_LUT_RECORD;
 
-typedef struct _ATOM_VOLTAGE_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_VOLTAGE_INFO_HEADER viHeader;
-	UCHAR ucVoltageEntries[64];	/* 64 is for allocation, the actual number of entry is present at ucNumOfVoltageEntries*ucBytesPerVoltageEntry */
-} ATOM_VOLTAGE_INFO;
+typedef struct _ATOM_CONNECTOR_AUXDDC_LUT_RECORD  //record for ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  ATOM_I2C_ID_CONFIG          ucAUXDDCMap[MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES];  //An fixed size array which maps external pins to internal DDC ID
+}ATOM_CONNECTOR_AUXDDC_LUT_RECORD;
 
-typedef struct _ATOM_VOLTAGE_FORMULA {
-	USHORT usVoltageBaseLevel;	/*  In number of 1mv unit */
-	USHORT usVoltageStep;	/*  Indicating in how many mv increament is one step, 1mv unit */
-	UCHAR ucNumOfVoltageEntries;	/*  Number of Voltage Entry, which indicate max Voltage */
-	UCHAR ucFlag;		/*  bit0=0 :step is 1mv =1 0.5mv */
-	UCHAR ucBaseVID;	/*  if there is no lookup table, VID= BaseVID + ( Vol - BaseLevle ) /VoltageStep */
-	UCHAR ucReserved;
-	UCHAR ucVIDAdjustEntries[32];	/*  32 is for allocation, the actual number of entry is present at ucNumOfVoltageEntries */
-} ATOM_VOLTAGE_FORMULA;
+typedef struct _ATOM_OBJECT_LINK_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  USHORT                      usObjectID;         //could be connector, encorder or other object in object.h
+}ATOM_OBJECT_LINK_RECORD;
 
-typedef struct _ATOM_VOLTAGE_CONTROL {
-	UCHAR ucVoltageControlId;	/* Indicate it is controlled by I2C or GPIO or HW state machine */
-	UCHAR ucVoltageControlI2cLine;
-	UCHAR ucVoltageControlAddress;
-	UCHAR ucVoltageControlOffset;
-	USHORT usGpioPin_AIndex;	/* GPIO_PAD register index */
-	UCHAR ucGpioPinBitShift[9];	/* at most 8 pin support 255 VIDs, termintate with 0xff */
-	UCHAR ucReserved;
-} ATOM_VOLTAGE_CONTROL;
+typedef struct _ATOM_CONNECTOR_REMOTE_CAP_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  USHORT                      usReserved;
+}ATOM_CONNECTOR_REMOTE_CAP_RECORD;
 
-/*  Define ucVoltageControlId */
+/****************************************************************************/	
+// ASIC voltage data table
+/****************************************************************************/	
+typedef struct  _ATOM_VOLTAGE_INFO_HEADER
+{
+   USHORT   usVDDCBaseLevel;                //In number of 50mv unit
+   USHORT   usReserved;                     //For possible extension table offset
+   UCHAR    ucNumOfVoltageEntries;
+   UCHAR    ucBytesPerVoltageEntry;
+   UCHAR    ucVoltageStep;                  //Indicating in how many mv increament is one step, 0.5mv unit
+   UCHAR    ucDefaultVoltageEntry;
+   UCHAR    ucVoltageControlI2cLine;
+   UCHAR    ucVoltageControlAddress;
+   UCHAR    ucVoltageControlOffset;
+}ATOM_VOLTAGE_INFO_HEADER;
+
+typedef struct  _ATOM_VOLTAGE_INFO
+{
+   ATOM_COMMON_TABLE_HEADER	sHeader; 
+   ATOM_VOLTAGE_INFO_HEADER viHeader;
+   UCHAR    ucVoltageEntries[64];            //64 is for allocation, the actual number of entry is present at ucNumOfVoltageEntries*ucBytesPerVoltageEntry
+}ATOM_VOLTAGE_INFO;
+
+
+typedef struct  _ATOM_VOLTAGE_FORMULA
+{
+   USHORT   usVoltageBaseLevel;             // In number of 1mv unit
+   USHORT   usVoltageStep;                  // Indicating in how many mv increament is one step, 1mv unit
+	 UCHAR		ucNumOfVoltageEntries;					// Number of Voltage Entry, which indicate max Voltage
+	 UCHAR		ucFlag;													// bit0=0 :step is 1mv =1 0.5mv
+	 UCHAR		ucBaseVID;											// if there is no lookup table, VID= BaseVID + ( Vol - BaseLevle ) /VoltageStep
+	 UCHAR		ucReserved;
+	 UCHAR		ucVIDAdjustEntries[32];					// 32 is for allocation, the actual number of entry is present at ucNumOfVoltageEntries
+}ATOM_VOLTAGE_FORMULA;
+
+typedef struct  _VOLTAGE_LUT_ENTRY
+{
+	 USHORT		usVoltageCode;									// The Voltage ID, either GPIO or I2C code
+	 USHORT		usVoltageValue;									// The corresponding Voltage Value, in mV
+}VOLTAGE_LUT_ENTRY;
+
+typedef struct  _ATOM_VOLTAGE_FORMULA_V2
+{
+	 UCHAR		ucNumOfVoltageEntries;					// Number of Voltage Entry, which indicate max Voltage
+	 UCHAR		ucReserved[3];
+	 VOLTAGE_LUT_ENTRY asVIDAdjustEntries[32];// 32 is for allocation, the actual number of entries is in ucNumOfVoltageEntries
+}ATOM_VOLTAGE_FORMULA_V2;
+
+typedef struct _ATOM_VOLTAGE_CONTROL
+{
+	UCHAR		 ucVoltageControlId;							//Indicate it is controlled by I2C or GPIO or HW state machine		
+  UCHAR    ucVoltageControlI2cLine;
+  UCHAR    ucVoltageControlAddress;
+  UCHAR    ucVoltageControlOffset;	 	
+  USHORT   usGpioPin_AIndex;								//GPIO_PAD register index
+  UCHAR    ucGpioPinBitShift[9];						//at most 8 pin support 255 VIDs, termintate with 0xff
+	UCHAR		 ucReserved;
+}ATOM_VOLTAGE_CONTROL;
+
+// Define ucVoltageControlId
 #define	VOLTAGE_CONTROLLED_BY_HW							0x00
 #define	VOLTAGE_CONTROLLED_BY_I2C_MASK				0x7F
 #define	VOLTAGE_CONTROLLED_BY_GPIO						0x80
-#define	VOLTAGE_CONTROL_ID_LM64								0x01	/* I2C control, used for R5xx Core Voltage */
-#define	VOLTAGE_CONTROL_ID_DAC								0x02	/* I2C control, used for R5xx/R6xx MVDDC,MVDDQ or VDDCI */
-#define	VOLTAGE_CONTROL_ID_VT116xM						0x03	/* I2C control, used for R6xx Core Voltage */
-#define VOLTAGE_CONTROL_ID_DS4402							0x04
+#define	VOLTAGE_CONTROL_ID_LM64								0x01									//I2C control, used for R5xx Core Voltage
+#define	VOLTAGE_CONTROL_ID_DAC								0x02									//I2C control, used for R5xx/R6xx MVDDC,MVDDQ or VDDCI
+#define	VOLTAGE_CONTROL_ID_VT116xM						0x03									//I2C control, used for R6xx Core Voltage
+#define VOLTAGE_CONTROL_ID_DS4402							0x04									
 
-typedef struct _ATOM_VOLTAGE_OBJECT {
-	UCHAR ucVoltageType;	/* Indicate Voltage Source: VDDC, MVDDC, MVDDQ or MVDDCI */
-	UCHAR ucSize;		/* Size of Object */
-	ATOM_VOLTAGE_CONTROL asControl;	/* describ how to control */
-	ATOM_VOLTAGE_FORMULA asFormula;	/* Indicate How to convert real Voltage to VID */
-} ATOM_VOLTAGE_OBJECT;
+typedef struct  _ATOM_VOLTAGE_OBJECT
+{
+ 	 UCHAR		ucVoltageType;									//Indicate Voltage Source: VDDC, MVDDC, MVDDQ or MVDDCI	 
+	 UCHAR		ucSize;													//Size of Object	
+	 ATOM_VOLTAGE_CONTROL			asControl;			//describ how to control 	 
+ 	 ATOM_VOLTAGE_FORMULA			asFormula;			//Indicate How to convert real Voltage to VID 
+}ATOM_VOLTAGE_OBJECT;
 
-typedef struct _ATOM_VOLTAGE_OBJECT_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_VOLTAGE_OBJECT asVoltageObj[3];	/* Info for Voltage control */
-} ATOM_VOLTAGE_OBJECT_INFO;
+typedef struct  _ATOM_VOLTAGE_OBJECT_V2
+{
+ 	 UCHAR		ucVoltageType;									//Indicate Voltage Source: VDDC, MVDDC, MVDDQ or MVDDCI	 
+	 UCHAR		ucSize;													//Size of Object	
+	 ATOM_VOLTAGE_CONTROL			asControl;			//describ how to control 	 
+ 	 ATOM_VOLTAGE_FORMULA_V2	asFormula;			//Indicate How to convert real Voltage to VID 
+}ATOM_VOLTAGE_OBJECT_V2;
 
-typedef struct _ATOM_LEAKID_VOLTAGE {
-	UCHAR ucLeakageId;
-	UCHAR ucReserved;
-	USHORT usVoltage;
-} ATOM_LEAKID_VOLTAGE;
+typedef struct  _ATOM_VOLTAGE_OBJECT_INFO
+{
+   ATOM_COMMON_TABLE_HEADER	sHeader; 
+	 ATOM_VOLTAGE_OBJECT			asVoltageObj[3];	//Info for Voltage control	  	 
+}ATOM_VOLTAGE_OBJECT_INFO;
 
-typedef struct _ATOM_ASIC_PROFILE_VOLTAGE {
-	UCHAR ucProfileId;
-	UCHAR ucReserved;
-	USHORT usSize;
-	USHORT usEfuseSpareStartAddr;
-	USHORT usFuseIndex[8];	/* from LSB to MSB, Max 8bit,end of 0xffff if less than 8 efuse id, */
-	ATOM_LEAKID_VOLTAGE asLeakVol[2];	/* Leakid and relatd voltage */
-} ATOM_ASIC_PROFILE_VOLTAGE;
+typedef struct  _ATOM_VOLTAGE_OBJECT_INFO_V2
+{
+   ATOM_COMMON_TABLE_HEADER	sHeader; 
+	 ATOM_VOLTAGE_OBJECT_V2			asVoltageObj[3];	//Info for Voltage control	  	 
+}ATOM_VOLTAGE_OBJECT_INFO_V2;
 
-/* ucProfileId */
-#define	ATOM_ASIC_PROFILE_ID_EFUSE_VOLTAGE			1
+typedef struct  _ATOM_LEAKID_VOLTAGE
+{
+	UCHAR		ucLeakageId;
+	UCHAR		ucReserved;
+	USHORT	usVoltage;
+}ATOM_LEAKID_VOLTAGE;
+
+typedef struct  _ATOM_ASIC_PROFILE_VOLTAGE
+{
+	UCHAR		ucProfileId;
+	UCHAR		ucReserved;
+	USHORT	usSize;
+	USHORT	usEfuseSpareStartAddr;
+	USHORT	usFuseIndex[8];												//from LSB to MSB, Max 8bit,end of 0xffff if less than 8 efuse id, 
+	ATOM_LEAKID_VOLTAGE					asLeakVol[2];			//Leakid and relatd voltage
+}ATOM_ASIC_PROFILE_VOLTAGE;
+
+//ucProfileId
+#define	ATOM_ASIC_PROFILE_ID_EFUSE_VOLTAGE			1		
 #define	ATOM_ASIC_PROFILE_ID_EFUSE_PERFORMANCE_VOLTAGE			1
 #define	ATOM_ASIC_PROFILE_ID_EFUSE_THERMAL_VOLTAGE					2
 
-typedef struct _ATOM_ASIC_PROFILING_INFO {
-	ATOM_COMMON_TABLE_HEADER asHeader;
-	ATOM_ASIC_PROFILE_VOLTAGE asVoltage;
-} ATOM_ASIC_PROFILING_INFO;
+typedef struct  _ATOM_ASIC_PROFILING_INFO
+{
+  ATOM_COMMON_TABLE_HEADER			asHeader; 
+	ATOM_ASIC_PROFILE_VOLTAGE			asVoltage;
+}ATOM_ASIC_PROFILING_INFO;
 
-typedef struct _ATOM_POWER_SOURCE_OBJECT {
-	UCHAR ucPwrSrcId;	/*  Power source */
-	UCHAR ucPwrSensorType;	/*  GPIO, I2C or none */
-	UCHAR ucPwrSensId;	/*  if GPIO detect, it is GPIO id,  if I2C detect, it is I2C id */
-	UCHAR ucPwrSensSlaveAddr;	/*  Slave address if I2C detect */
-	UCHAR ucPwrSensRegIndex;	/*  I2C register Index if I2C detect */
-	UCHAR ucPwrSensRegBitMask;	/*  detect which bit is used if I2C detect */
-	UCHAR ucPwrSensActiveState;	/*  high active or low active */
-	UCHAR ucReserve[3];	/*  reserve */
-	USHORT usSensPwr;	/*  in unit of watt */
-} ATOM_POWER_SOURCE_OBJECT;
+typedef struct _ATOM_POWER_SOURCE_OBJECT
+{
+	UCHAR	ucPwrSrcId;													// Power source
+	UCHAR	ucPwrSensorType;										// GPIO, I2C or none
+	UCHAR	ucPwrSensId;											  // if GPIO detect, it is GPIO id,  if I2C detect, it is I2C id
+	UCHAR	ucPwrSensSlaveAddr;									// Slave address if I2C detect
+	UCHAR ucPwrSensRegIndex;									// I2C register Index if I2C detect
+	UCHAR ucPwrSensRegBitMask;								// detect which bit is used if I2C detect
+	UCHAR	ucPwrSensActiveState;								// high active or low active
+	UCHAR	ucReserve[3];												// reserve		
+	USHORT usSensPwr;													// in unit of watt
+}ATOM_POWER_SOURCE_OBJECT;
 
-typedef struct _ATOM_POWER_SOURCE_INFO {
-	ATOM_COMMON_TABLE_HEADER asHeader;
-	UCHAR asPwrbehave[16];
-	ATOM_POWER_SOURCE_OBJECT asPwrObj[1];
-} ATOM_POWER_SOURCE_INFO;
+typedef struct _ATOM_POWER_SOURCE_INFO
+{
+		ATOM_COMMON_TABLE_HEADER		asHeader;
+		UCHAR												asPwrbehave[16];
+		ATOM_POWER_SOURCE_OBJECT		asPwrObj[1];
+}ATOM_POWER_SOURCE_INFO;
 
-/* Define ucPwrSrcId */
+
+//Define ucPwrSrcId
 #define POWERSOURCE_PCIE_ID1						0x00
 #define POWERSOURCE_6PIN_CONNECTOR_ID1	0x01
 #define POWERSOURCE_8PIN_CONNECTOR_ID1	0x02
 #define POWERSOURCE_6PIN_CONNECTOR_ID2	0x04
 #define POWERSOURCE_8PIN_CONNECTOR_ID2	0x08
 
-/* define ucPwrSensorId */
+//define ucPwrSensorId
 #define POWER_SENSOR_ALWAYS							0x00
 #define POWER_SENSOR_GPIO								0x01
 #define POWER_SENSOR_I2C								0x02
 
+typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V6
+{
+  ATOM_COMMON_TABLE_HEADER   sHeader;
+  ULONG  ulBootUpEngineClock;
+  ULONG  ulDentistVCOFreq;          
+  ULONG  ulBootUpUMAClock;          
+  ULONG  ulReserved1[8];            
+  ULONG  ulBootUpReqDisplayVector;
+  ULONG  ulOtherDisplayMisc;
+  ULONG  ulGPUCapInfo;
+  ULONG  ulReserved2[3];            
+  ULONG  ulSystemConfig;            
+  ULONG  ulCPUCapInfo;              
+  USHORT usMaxNBVoltage;  
+  USHORT usMinNBVoltage;  
+  USHORT usBootUpNBVoltage;         
+  USHORT usExtDispConnInfoOffset;  
+  UCHAR  ucHtcTmpLmt;   
+  UCHAR  ucTjOffset;    
+  UCHAR  ucMemoryType;  
+  UCHAR  ucUMAChannelNumber;
+  ULONG  ulCSR_M3_ARB_CNTL_DEFAULT[10];  
+  ULONG  ulCSR_M3_ARB_CNTL_UVD[10]; 
+  ULONG  ulCSR_M3_ARB_CNTL_FS3D[10];
+  ULONG  ulReserved3[42]; 
+  ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO sExtDispConnInfo;   
+}ATOM_INTEGRATED_SYSTEM_INFO_V6;   
+
+/**********************************************************************************************************************
+// ATOM_INTEGRATED_SYSTEM_INFO_V6 Description
+//ulBootUpEngineClock:              VBIOS bootup Engine clock frequency, in 10kHz unit. 
+//ulDentistVCOFreq:                 Dentist VCO clock in 10kHz unit. 
+//ulBootUpUMAClock:                 System memory boot up clock frequency in 10Khz unit. 
+//ulReserved1[8]                    Reserved by now, must be 0x0. 
+//ulBootUpReqDisplayVector	        VBIOS boot up display IDs
+//                                  ATOM_DEVICE_CRT1_SUPPORT                  0x0001
+//                                  ATOM_DEVICE_CRT2_SUPPORT                  0x0010
+//                                  ATOM_DEVICE_DFP1_SUPPORT                  0x0008 
+//                                  ATOM_DEVICE_DFP6_SUPPORT                  0x0040 
+//                                  ATOM_DEVICE_DFP2_SUPPORT                  0x0080       
+//                                  ATOM_DEVICE_DFP3_SUPPORT                  0x0200       
+//                                  ATOM_DEVICE_DFP4_SUPPORT                  0x0400        
+//                                  ATOM_DEVICE_DFP5_SUPPORT                  0x0800
+//                                  ATOM_DEVICE_LCD1_SUPPORT                  0x0002
+//ulOtherDisplayMisc      	        Other display related flags, not defined yet. 
+//ulGPUCapInfo                      TBD
+//ulReserved2[3]                    must be 0x0 for the reserved.
+//ulSystemConfig                    TBD
+//ulCPUCapInfo                      TBD
+//usMaxNBVoltage                    High NB voltage in unit of mv, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse. 
+//usMinNBVoltage                    Low NB voltage in unit of mv, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse.
+//usBootUpNBVoltage                 Boot up NB voltage in unit of mv.
+//ucHtcTmpLmt                       Bit [22:16] of D24F3x64 Thermal Control (HTC) Register.
+//ucTjOffset                        Bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed.
+//ucMemoryType                      [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved.
+//ucUMAChannelNumber      	        System memory channel numbers. 
+//usExtDispConnectionInfoOffset     ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO offset relative to beginning of this table. 
+//ulCSR_M3_ARB_CNTL_DEFAULT[10]     Arrays with values for CSR M3 arbiter for default
+//ulCSR_M3_ARB_CNTL_UVD[10]         Arrays with values for CSR M3 arbiter for UVD playback.
+//ulCSR_M3_ARB_CNTL_FS3D[10]        Arrays with values for CSR M3 arbiter for Full Screen 3D applications.
+**********************************************************************************************************************/
+
 /**************************************************************************/
-/*  This portion is only used when ext thermal chip or engine/memory clock SS chip is populated on a design */
-/* Memory SS Info Table */
-/* Define Memory Clock SS chip ID */
+// This portion is only used when ext thermal chip or engine/memory clock SS chip is populated on a design
+//Memory SS Info Table
+//Define Memory Clock SS chip ID
 #define ICS91719  1
 #define ICS91720  2
 
-/* Define one structure to inform SW a "block of data" writing to external SS chip via I2C protocol */
-typedef struct _ATOM_I2C_DATA_RECORD {
-	UCHAR ucNunberOfBytes;	/* Indicates how many bytes SW needs to write to the external ASIC for one block, besides to "Start" and "Stop" */
-	UCHAR ucI2CData[1];	/* I2C data in bytes, should be less than 16 bytes usually */
-} ATOM_I2C_DATA_RECORD;
+//Define one structure to inform SW a "block of data" writing to external SS chip via I2C protocol
+typedef struct _ATOM_I2C_DATA_RECORD
+{
+  UCHAR         ucNunberOfBytes;                                              //Indicates how many bytes SW needs to write to the external ASIC for one block, besides to "Start" and "Stop"
+  UCHAR         ucI2CData[1];                                                 //I2C data in bytes, should be less than 16 bytes usually
+}ATOM_I2C_DATA_RECORD;
 
-/* Define one structure to inform SW how many blocks of data writing to external SS chip via I2C protocol, in addition to other information */
-typedef struct _ATOM_I2C_DEVICE_SETUP_INFO {
-	ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;	/* I2C line and HW/SW assisted cap. */
-	UCHAR ucSSChipID;	/* SS chip being used */
-	UCHAR ucSSChipSlaveAddr;	/* Slave Address to set up this SS chip */
-	UCHAR ucNumOfI2CDataRecords;	/* number of data block */
-	ATOM_I2C_DATA_RECORD asI2CData[1];
-} ATOM_I2C_DEVICE_SETUP_INFO;
 
-/* ========================================================================================== */
-typedef struct _ATOM_ASIC_MVDD_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_I2C_DEVICE_SETUP_INFO asI2CSetup[1];
-} ATOM_ASIC_MVDD_INFO;
+//Define one structure to inform SW how many blocks of data writing to external SS chip via I2C protocol, in addition to other information
+typedef struct _ATOM_I2C_DEVICE_SETUP_INFO
+{
+  ATOM_I2C_ID_CONFIG_ACCESS       sucI2cId;               //I2C line and HW/SW assisted cap.
+  UCHAR		                        ucSSChipID;             //SS chip being used
+  UCHAR		                        ucSSChipSlaveAddr;      //Slave Address to set up this SS chip
+  UCHAR                           ucNumOfI2CDataRecords;  //number of data block
+  ATOM_I2C_DATA_RECORD            asI2CData[1];  
+}ATOM_I2C_DEVICE_SETUP_INFO;
 
-/* ========================================================================================== */
+//==========================================================================================
+typedef struct  _ATOM_ASIC_MVDD_INFO
+{
+  ATOM_COMMON_TABLE_HEADER	      sHeader; 
+  ATOM_I2C_DEVICE_SETUP_INFO      asI2CSetup[1];
+}ATOM_ASIC_MVDD_INFO;
+
+//==========================================================================================
 #define ATOM_MCLK_SS_INFO         ATOM_ASIC_MVDD_INFO
 
-/* ========================================================================================== */
+//==========================================================================================
 /**************************************************************************/
 
-typedef struct _ATOM_ASIC_SS_ASSIGNMENT {
-	ULONG ulTargetClockRange;	/* Clock Out frequence (VCO ), in unit of 10Khz */
-	USHORT usSpreadSpectrumPercentage;	/* in unit of 0.01% */
-	USHORT usSpreadRateInKhz;	/* in unit of kHz, modulation freq */
-	UCHAR ucClockIndication;	/* Indicate which clock source needs SS */
-	UCHAR ucSpreadSpectrumMode;	/* Bit1=0 Down Spread,=1 Center Spread. */
-	UCHAR ucReserved[2];
-} ATOM_ASIC_SS_ASSIGNMENT;
+typedef struct _ATOM_ASIC_SS_ASSIGNMENT
+{
+	ULONG								ulTargetClockRange;						//Clock Out frequence (VCO ), in unit of 10Khz
+  USHORT              usSpreadSpectrumPercentage;		//in unit of 0.01%
+	USHORT							usSpreadRateInKhz;						//in unit of kHz, modulation freq
+  UCHAR               ucClockIndication;					  //Indicate which clock source needs SS
+	UCHAR								ucSpreadSpectrumMode;					//Bit1=0 Down Spread,=1 Center Spread.
+	UCHAR								ucReserved[2];
+}ATOM_ASIC_SS_ASSIGNMENT;
 
-/* Define ucSpreadSpectrumType */
+//Define ucClockIndication, SW uses the IDs below to search if the SS is requried/enabled on a clock branch/signal type.
+//SS is not required or enabled if a match is not found.
 #define ASIC_INTERNAL_MEMORY_SS			1
 #define ASIC_INTERNAL_ENGINE_SS			2
-#define ASIC_INTERNAL_UVD_SS				3
+#define ASIC_INTERNAL_UVD_SS        3
+#define ASIC_INTERNAL_SS_ON_TMDS    4
+#define ASIC_INTERNAL_SS_ON_HDMI    5
+#define ASIC_INTERNAL_SS_ON_LVDS    6
+#define ASIC_INTERNAL_SS_ON_DP      7
+#define ASIC_INTERNAL_SS_ON_DCPLL   8
 
-typedef struct _ATOM_ASIC_INTERNAL_SS_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_ASIC_SS_ASSIGNMENT asSpreadSpectrum[4];
-} ATOM_ASIC_INTERNAL_SS_INFO;
+typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V2
+{
+	ULONG								ulTargetClockRange;						//For mem/engine/uvd, Clock Out frequence (VCO ), in unit of 10Khz
+                                                    //For TMDS/HDMI/LVDS, it is pixel clock , for DP, it is link clock ( 27000 or 16200 )
+  USHORT              usSpreadSpectrumPercentage;		//in unit of 0.01%
+	USHORT							usSpreadRateIn10Hz;						//in unit of 10Hz, modulation freq
+  UCHAR               ucClockIndication;					  //Indicate which clock source needs SS
+	UCHAR								ucSpreadSpectrumMode;					//Bit0=0 Down Spread,=1 Center Spread, bit1=0: internal SS bit1=1: external SS
+	UCHAR								ucReserved[2];
+}ATOM_ASIC_SS_ASSIGNMENT_V2;
 
-/* ==============================Scratch Pad Definition Portion=============================== */
+//ucSpreadSpectrumMode
+//#define ATOM_SS_DOWN_SPREAD_MODE_MASK          0x00000000
+//#define ATOM_SS_DOWN_SPREAD_MODE               0x00000000
+//#define ATOM_SS_CENTRE_SPREAD_MODE_MASK        0x00000001
+//#define ATOM_SS_CENTRE_SPREAD_MODE             0x00000001
+//#define ATOM_INTERNAL_SS_MASK                  0x00000000
+//#define ATOM_EXTERNAL_SS_MASK                  0x00000002
+
+typedef struct _ATOM_ASIC_INTERNAL_SS_INFO
+{
+  ATOM_COMMON_TABLE_HEADER	      sHeader; 
+  ATOM_ASIC_SS_ASSIGNMENT		      asSpreadSpectrum[4];
+}ATOM_ASIC_INTERNAL_SS_INFO;
+
+typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V2
+{
+  ATOM_COMMON_TABLE_HEADER	      sHeader; 
+  ATOM_ASIC_SS_ASSIGNMENT_V2		  asSpreadSpectrum[1];      //this is point only. 
+}ATOM_ASIC_INTERNAL_SS_INFO_V2;
+
+typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V3
+{
+	ULONG								ulTargetClockRange;						//For mem/engine/uvd, Clock Out frequence (VCO ), in unit of 10Khz
+                                                    //For TMDS/HDMI/LVDS, it is pixel clock , for DP, it is link clock ( 27000 or 16200 )
+  USHORT              usSpreadSpectrumPercentage;		//in unit of 0.01%
+	USHORT							usSpreadRateIn10Hz;						//in unit of 10Hz, modulation freq
+  UCHAR               ucClockIndication;					  //Indicate which clock source needs SS
+	UCHAR								ucSpreadSpectrumMode;					//Bit0=0 Down Spread,=1 Center Spread, bit1=0: internal SS bit1=1: external SS
+	UCHAR								ucReserved[2];
+}ATOM_ASIC_SS_ASSIGNMENT_V3;
+
+typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3
+{
+  ATOM_COMMON_TABLE_HEADER	      sHeader; 
+  ATOM_ASIC_SS_ASSIGNMENT_V3		  asSpreadSpectrum[1];      //this is pointer only. 
+}ATOM_ASIC_INTERNAL_SS_INFO_V3;
+
+
+//==============================Scratch Pad Definition Portion===============================
 #define ATOM_DEVICE_CONNECT_INFO_DEF  0
 #define ATOM_ROM_LOCATION_DEF         1
 #define ATOM_TV_STANDARD_DEF          2
@@ -2995,7 +3852,8 @@
 #define ATOM_I2C_CHANNEL_STATUS_DEF   8
 #define ATOM_I2C_CHANNEL_STATUS1_DEF  9
 
-/*  BIOS_0_SCRATCH Definition */
+
+// BIOS_0_SCRATCH Definition 
 #define ATOM_S0_CRT1_MONO               0x00000001L
 #define ATOM_S0_CRT1_COLOR              0x00000002L
 #define ATOM_S0_CRT1_MASK               (ATOM_S0_CRT1_MONO+ATOM_S0_CRT1_COLOR)
@@ -3008,6 +3866,7 @@
 #define ATOM_S0_CV_DIN_A                0x00000020L
 #define ATOM_S0_CV_MASK_A               (ATOM_S0_CV_A+ATOM_S0_CV_DIN_A)
 
+
 #define ATOM_S0_CRT2_MONO               0x00000100L
 #define ATOM_S0_CRT2_COLOR              0x00000200L
 #define ATOM_S0_CRT2_MASK               (ATOM_S0_CRT2_MONO+ATOM_S0_CRT2_COLOR)
@@ -3025,28 +3884,27 @@
 #define ATOM_S0_DFP2                    0x00020000L
 #define ATOM_S0_LCD1                    0x00040000L
 #define ATOM_S0_LCD2                    0x00080000L
-#define ATOM_S0_TV2                     0x00100000L
-#define ATOM_S0_DFP3			0x00200000L
-#define ATOM_S0_DFP4			0x00400000L
-#define ATOM_S0_DFP5			0x00800000L
+#define ATOM_S0_DFP6                    0x00100000L
+#define ATOM_S0_DFP3                    0x00200000L
+#define ATOM_S0_DFP4                    0x00400000L
+#define ATOM_S0_DFP5                    0x00800000L
 
-#define ATOM_S0_DFP_MASK \
-	(ATOM_S0_DFP1 | ATOM_S0_DFP2 | ATOM_S0_DFP3 | ATOM_S0_DFP4 | ATOM_S0_DFP5)
+#define ATOM_S0_DFP_MASK                ATOM_S0_DFP1 | ATOM_S0_DFP2 | ATOM_S0_DFP3 | ATOM_S0_DFP4 | ATOM_S0_DFP5 | ATOM_S0_DFP6
 
-#define ATOM_S0_FAD_REGISTER_BUG        0x02000000L	/*  If set, indicates we are running a PCIE asic with */
-						    /*  the FAD/HDP reg access bug.  Bit is read by DAL */
+#define ATOM_S0_FAD_REGISTER_BUG        0x02000000L // If set, indicates we are running a PCIE asic with 
+                                                    // the FAD/HDP reg access bug.  Bit is read by DAL, this is obsolete from RV5xx
 
 #define ATOM_S0_THERMAL_STATE_MASK      0x1C000000L
 #define ATOM_S0_THERMAL_STATE_SHIFT     26
 
 #define ATOM_S0_SYSTEM_POWER_STATE_MASK 0xE0000000L
-#define ATOM_S0_SYSTEM_POWER_STATE_SHIFT 29
+#define ATOM_S0_SYSTEM_POWER_STATE_SHIFT 29 
 
 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_AC     1
 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_DC     2
 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LITEAC 3
 
-/* Byte aligned definition for BIOS usage */
+//Byte aligned defintion for BIOS usage
 #define ATOM_S0_CRT1_MONOb0             0x01
 #define ATOM_S0_CRT1_COLORb0            0x02
 #define ATOM_S0_CRT1_MASKb0             (ATOM_S0_CRT1_MONOb0+ATOM_S0_CRT1_COLORb0)
@@ -3076,8 +3934,11 @@
 #define ATOM_S0_DFP2b2                  0x02
 #define ATOM_S0_LCD1b2                  0x04
 #define ATOM_S0_LCD2b2                  0x08
-#define ATOM_S0_TV2b2                   0x10
-#define ATOM_S0_DFP3b2									0x20
+#define ATOM_S0_DFP6b2                  0x10
+#define ATOM_S0_DFP3b2                  0x20
+#define ATOM_S0_DFP4b2                  0x40
+#define ATOM_S0_DFP5b2                  0x80
+
 
 #define ATOM_S0_THERMAL_STATE_MASKb3    0x1C
 #define ATOM_S0_THERMAL_STATE_SHIFTb3   2
@@ -3085,43 +3946,20 @@
 #define ATOM_S0_SYSTEM_POWER_STATE_MASKb3 0xE0
 #define ATOM_S0_LCD1_SHIFT              18
 
-/*  BIOS_1_SCRATCH Definition */
+// BIOS_1_SCRATCH Definition
 #define ATOM_S1_ROM_LOCATION_MASK       0x0000FFFFL
 #define ATOM_S1_PCI_BUS_DEV_MASK        0xFFFF0000L
 
-/*       BIOS_2_SCRATCH Definition */
+//	BIOS_2_SCRATCH Definition
 #define ATOM_S2_TV1_STANDARD_MASK       0x0000000FL
 #define ATOM_S2_CURRENT_BL_LEVEL_MASK   0x0000FF00L
 #define ATOM_S2_CURRENT_BL_LEVEL_SHIFT  8
 
-#define ATOM_S2_CRT1_DPMS_STATE         0x00010000L
-#define ATOM_S2_LCD1_DPMS_STATE	        0x00020000L
-#define ATOM_S2_TV1_DPMS_STATE          0x00040000L
-#define ATOM_S2_DFP1_DPMS_STATE         0x00080000L
-#define ATOM_S2_CRT2_DPMS_STATE         0x00100000L
-#define ATOM_S2_LCD2_DPMS_STATE         0x00200000L
-#define ATOM_S2_TV2_DPMS_STATE          0x00400000L
-#define ATOM_S2_DFP2_DPMS_STATE         0x00800000L
-#define ATOM_S2_CV_DPMS_STATE           0x01000000L
-#define ATOM_S2_DFP3_DPMS_STATE					0x02000000L
-#define ATOM_S2_DFP4_DPMS_STATE					0x04000000L
-#define ATOM_S2_DFP5_DPMS_STATE					0x08000000L
-
-#define ATOM_S2_DFP_DPM_STATE \
-	(ATOM_S2_DFP1_DPMS_STATE | ATOM_S2_DFP2_DPMS_STATE | \
-	 ATOM_S2_DFP3_DPMS_STATE | ATOM_S2_DFP4_DPMS_STATE | \
-	 ATOM_S2_DFP5_DPMS_STATE)
-
-#define ATOM_S2_DEVICE_DPMS_STATE \
-	(ATOM_S2_CRT1_DPMS_STATE + ATOM_S2_LCD1_DPMS_STATE + \
-	 ATOM_S2_TV1_DPMS_STATE + ATOM_S2_DFP_DPMS_STATE + \
-	 ATOM_S2_CRT2_DPMS_STATE + ATOM_S2_LCD2_DPMS_STATE + \
-	 ATOM_S2_TV2_DPMS_STATE + ATOM_S2_CV_DPMS_STATE)
-
 #define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASK       0x0C000000L
 #define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASK_SHIFT 26
 #define ATOM_S2_FORCEDLOWPWRMODE_STATE_CHANGE     0x10000000L
 
+#define ATOM_S2_DEVICE_DPMS_STATE       0x00010000L
 #define ATOM_S2_VRI_BRIGHT_ENABLE       0x20000000L
 
 #define ATOM_S2_DISPLAY_ROTATION_0_DEGREE     0x0
@@ -3131,21 +3969,11 @@
 #define ATOM_S2_DISPLAY_ROTATION_DEGREE_SHIFT 30
 #define ATOM_S2_DISPLAY_ROTATION_ANGLE_MASK   0xC0000000L
 
-/* Byte aligned definition for BIOS usage */
+
+//Byte aligned defintion for BIOS usage
 #define ATOM_S2_TV1_STANDARD_MASKb0     0x0F
 #define ATOM_S2_CURRENT_BL_LEVEL_MASKb1 0xFF
-#define ATOM_S2_CRT1_DPMS_STATEb2       0x01
-#define ATOM_S2_LCD1_DPMS_STATEb2       0x02
-#define ATOM_S2_TV1_DPMS_STATEb2        0x04
-#define ATOM_S2_DFP1_DPMS_STATEb2       0x08
-#define ATOM_S2_CRT2_DPMS_STATEb2       0x10
-#define ATOM_S2_LCD2_DPMS_STATEb2       0x20
-#define ATOM_S2_TV2_DPMS_STATEb2        0x40
-#define ATOM_S2_DFP2_DPMS_STATEb2       0x80
-#define ATOM_S2_CV_DPMS_STATEb3         0x01
-#define ATOM_S2_DFP3_DPMS_STATEb3				0x02
-#define ATOM_S2_DFP4_DPMS_STATEb3				0x04
-#define ATOM_S2_DFP5_DPMS_STATEb3				0x08
+#define ATOM_S2_DEVICE_DPMS_STATEb2     0x01
 
 #define ATOM_S2_DEVICE_DPMS_MASKw1      0x3FF
 #define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASKb3     0x0C
@@ -3153,21 +3981,22 @@
 #define ATOM_S2_VRI_BRIGHT_ENABLEb3     0x20
 #define ATOM_S2_ROTATION_STATE_MASKb3   0xC0
 
-/*  BIOS_3_SCRATCH Definition */
+
+// BIOS_3_SCRATCH Definition
 #define ATOM_S3_CRT1_ACTIVE             0x00000001L
 #define ATOM_S3_LCD1_ACTIVE             0x00000002L
 #define ATOM_S3_TV1_ACTIVE              0x00000004L
 #define ATOM_S3_DFP1_ACTIVE             0x00000008L
 #define ATOM_S3_CRT2_ACTIVE             0x00000010L
 #define ATOM_S3_LCD2_ACTIVE             0x00000020L
-#define ATOM_S3_TV2_ACTIVE              0x00000040L
+#define ATOM_S3_DFP6_ACTIVE             0x00000040L
 #define ATOM_S3_DFP2_ACTIVE             0x00000080L
 #define ATOM_S3_CV_ACTIVE               0x00000100L
 #define ATOM_S3_DFP3_ACTIVE							0x00000200L
 #define ATOM_S3_DFP4_ACTIVE							0x00000400L
 #define ATOM_S3_DFP5_ACTIVE							0x00000800L
 
-#define ATOM_S3_DEVICE_ACTIVE_MASK      0x000003FFL
+#define ATOM_S3_DEVICE_ACTIVE_MASK      0x00000FFFL
 
 #define ATOM_S3_LCD_FULLEXPANSION_ACTIVE         0x00001000L
 #define ATOM_S3_LCD_EXPANSION_ASPEC_RATIO_ACTIVE 0x00002000L
@@ -3178,7 +4007,7 @@
 #define ATOM_S3_DFP1_CRTC_ACTIVE        0x00080000L
 #define ATOM_S3_CRT2_CRTC_ACTIVE        0x00100000L
 #define ATOM_S3_LCD2_CRTC_ACTIVE        0x00200000L
-#define ATOM_S3_TV2_CRTC_ACTIVE         0x00400000L
+#define ATOM_S3_DFP6_CRTC_ACTIVE        0x00400000L
 #define ATOM_S3_DFP2_CRTC_ACTIVE        0x00800000L
 #define ATOM_S3_CV_CRTC_ACTIVE          0x01000000L
 #define ATOM_S3_DFP3_CRTC_ACTIVE				0x02000000L
@@ -3187,17 +4016,18 @@
 
 #define ATOM_S3_DEVICE_CRTC_ACTIVE_MASK 0x0FFF0000L
 #define ATOM_S3_ASIC_GUI_ENGINE_HUNG    0x20000000L
+//Below two definitions are not supported in pplib, but in the old powerplay in DAL
 #define ATOM_S3_ALLOW_FAST_PWR_SWITCH   0x40000000L
 #define ATOM_S3_RQST_GPU_USE_MIN_PWR    0x80000000L
 
-/* Byte aligned definition for BIOS usage */
+//Byte aligned defintion for BIOS usage
 #define ATOM_S3_CRT1_ACTIVEb0           0x01
 #define ATOM_S3_LCD1_ACTIVEb0           0x02
 #define ATOM_S3_TV1_ACTIVEb0            0x04
 #define ATOM_S3_DFP1_ACTIVEb0           0x08
 #define ATOM_S3_CRT2_ACTIVEb0           0x10
 #define ATOM_S3_LCD2_ACTIVEb0           0x20
-#define ATOM_S3_TV2_ACTIVEb0            0x40
+#define ATOM_S3_DFP6_ACTIVEb0           0x40
 #define ATOM_S3_DFP2_ACTIVEb0           0x80
 #define ATOM_S3_CV_ACTIVEb1             0x01
 #define ATOM_S3_DFP3_ACTIVEb1						0x02
@@ -3212,7 +4042,7 @@
 #define ATOM_S3_DFP1_CRTC_ACTIVEb2      0x08
 #define ATOM_S3_CRT2_CRTC_ACTIVEb2      0x10
 #define ATOM_S3_LCD2_CRTC_ACTIVEb2      0x20
-#define ATOM_S3_TV2_CRTC_ACTIVEb2       0x40
+#define ATOM_S3_DFP6_CRTC_ACTIVEb2      0x40
 #define ATOM_S3_DFP2_CRTC_ACTIVEb2      0x80
 #define ATOM_S3_CV_CRTC_ACTIVEb3        0x01
 #define ATOM_S3_DFP3_CRTC_ACTIVEb3			0x02
@@ -3221,35 +4051,31 @@
 
 #define ATOM_S3_ACTIVE_CRTC2w1          0xFFF
 
-#define ATOM_S3_ASIC_GUI_ENGINE_HUNGb3	0x20
-#define ATOM_S3_ALLOW_FAST_PWR_SWITCHb3 0x40
-#define ATOM_S3_RQST_GPU_USE_MIN_PWRb3  0x80
-
-/*  BIOS_4_SCRATCH Definition */
+// BIOS_4_SCRATCH Definition
 #define ATOM_S4_LCD1_PANEL_ID_MASK      0x000000FFL
 #define ATOM_S4_LCD1_REFRESH_MASK       0x0000FF00L
 #define ATOM_S4_LCD1_REFRESH_SHIFT      8
 
-/* Byte aligned definition for BIOS usage */
+//Byte aligned defintion for BIOS usage
 #define ATOM_S4_LCD1_PANEL_ID_MASKb0	  0x0FF
 #define ATOM_S4_LCD1_REFRESH_MASKb1		  ATOM_S4_LCD1_PANEL_ID_MASKb0
 #define ATOM_S4_VRAM_INFO_MASKb2        ATOM_S4_LCD1_PANEL_ID_MASKb0
 
-/*  BIOS_5_SCRATCH Definition, BIOS_5_SCRATCH is used by Firmware only !!!! */
+// BIOS_5_SCRATCH Definition, BIOS_5_SCRATCH is used by Firmware only !!!!
 #define ATOM_S5_DOS_REQ_CRT1b0          0x01
 #define ATOM_S5_DOS_REQ_LCD1b0          0x02
 #define ATOM_S5_DOS_REQ_TV1b0           0x04
 #define ATOM_S5_DOS_REQ_DFP1b0          0x08
 #define ATOM_S5_DOS_REQ_CRT2b0          0x10
 #define ATOM_S5_DOS_REQ_LCD2b0          0x20
-#define ATOM_S5_DOS_REQ_TV2b0           0x40
+#define ATOM_S5_DOS_REQ_DFP6b0          0x40
 #define ATOM_S5_DOS_REQ_DFP2b0          0x80
 #define ATOM_S5_DOS_REQ_CVb1            0x01
 #define ATOM_S5_DOS_REQ_DFP3b1					0x02
 #define ATOM_S5_DOS_REQ_DFP4b1					0x04
 #define ATOM_S5_DOS_REQ_DFP5b1					0x08
 
-#define ATOM_S5_DOS_REQ_DEVICEw0        0x03FF
+#define ATOM_S5_DOS_REQ_DEVICEw0        0x0FFF
 
 #define ATOM_S5_DOS_REQ_CRT1            0x0001
 #define ATOM_S5_DOS_REQ_LCD1            0x0002
@@ -3257,22 +4083,21 @@
 #define ATOM_S5_DOS_REQ_DFP1            0x0008
 #define ATOM_S5_DOS_REQ_CRT2            0x0010
 #define ATOM_S5_DOS_REQ_LCD2            0x0020
-#define ATOM_S5_DOS_REQ_TV2             0x0040
+#define ATOM_S5_DOS_REQ_DFP6            0x0040
 #define ATOM_S5_DOS_REQ_DFP2            0x0080
 #define ATOM_S5_DOS_REQ_CV              0x0100
-#define ATOM_S5_DOS_REQ_DFP3						0x0200
-#define ATOM_S5_DOS_REQ_DFP4						0x0400
-#define ATOM_S5_DOS_REQ_DFP5						0x0800
+#define ATOM_S5_DOS_REQ_DFP3            0x0200
+#define ATOM_S5_DOS_REQ_DFP4            0x0400
+#define ATOM_S5_DOS_REQ_DFP5            0x0800
 
 #define ATOM_S5_DOS_FORCE_CRT1b2        ATOM_S5_DOS_REQ_CRT1b0
 #define ATOM_S5_DOS_FORCE_TV1b2         ATOM_S5_DOS_REQ_TV1b0
 #define ATOM_S5_DOS_FORCE_CRT2b2        ATOM_S5_DOS_REQ_CRT2b0
 #define ATOM_S5_DOS_FORCE_CVb3          ATOM_S5_DOS_REQ_CVb1
-#define ATOM_S5_DOS_FORCE_DEVICEw1 \
-	(ATOM_S5_DOS_FORCE_CRT1b2 + ATOM_S5_DOS_FORCE_TV1b2 + \
-	 ATOM_S5_DOS_FORCE_CRT2b2 + (ATOM_S5_DOS_FORCE_CVb3 << 8))
+#define ATOM_S5_DOS_FORCE_DEVICEw1      (ATOM_S5_DOS_FORCE_CRT1b2+ATOM_S5_DOS_FORCE_TV1b2+ATOM_S5_DOS_FORCE_CRT2b2+\
+                                        (ATOM_S5_DOS_FORCE_CVb3<<8))
 
-/*  BIOS_6_SCRATCH Definition */
+// BIOS_6_SCRATCH Definition
 #define ATOM_S6_DEVICE_CHANGE           0x00000001L
 #define ATOM_S6_SCALER_CHANGE           0x00000002L
 #define ATOM_S6_LID_CHANGE              0x00000004L
@@ -3285,11 +4110,11 @@
 #define ATOM_S6_HW_I2C_BUSY_STATE       0x00000200L
 #define ATOM_S6_THERMAL_STATE_CHANGE    0x00000400L
 #define ATOM_S6_INTERRUPT_SET_BY_BIOS   0x00000800L
-#define ATOM_S6_REQ_LCD_EXPANSION_FULL         0x00001000L	/* Normal expansion Request bit for LCD */
-#define ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIO  0x00002000L	/* Aspect ratio expansion Request bit for LCD */
+#define ATOM_S6_REQ_LCD_EXPANSION_FULL         0x00001000L //Normal expansion Request bit for LCD
+#define ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIO  0x00002000L //Aspect ratio expansion Request bit for LCD
 
-#define ATOM_S6_DISPLAY_STATE_CHANGE    0x00004000L	/* This bit is recycled when ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE is set,previously it's SCL2_H_expansion */
-#define ATOM_S6_I2C_STATE_CHANGE        0x00008000L	/* This bit is recycled,when ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE is set,previously it's SCL2_V_expansion */
+#define ATOM_S6_DISPLAY_STATE_CHANGE    0x00004000L        //This bit is recycled when ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE is set,previously it's SCL2_H_expansion
+#define ATOM_S6_I2C_STATE_CHANGE        0x00008000L        //This bit is recycled,when ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE is set,previously it's SCL2_V_expansion
 
 #define ATOM_S6_ACC_REQ_CRT1            0x00010000L
 #define ATOM_S6_ACC_REQ_LCD1            0x00020000L
@@ -3297,7 +4122,7 @@
 #define ATOM_S6_ACC_REQ_DFP1            0x00080000L
 #define ATOM_S6_ACC_REQ_CRT2            0x00100000L
 #define ATOM_S6_ACC_REQ_LCD2            0x00200000L
-#define ATOM_S6_ACC_REQ_TV2             0x00400000L
+#define ATOM_S6_ACC_REQ_DFP6            0x00400000L
 #define ATOM_S6_ACC_REQ_DFP2            0x00800000L
 #define ATOM_S6_ACC_REQ_CV              0x01000000L
 #define ATOM_S6_ACC_REQ_DFP3						0x02000000L
@@ -3310,7 +4135,7 @@
 #define ATOM_S6_VRI_BRIGHTNESS_CHANGE       0x40000000L
 #define ATOM_S6_CONFIG_DISPLAY_CHANGE_MASK  0x80000000L
 
-/* Byte aligned definition for BIOS usage */
+//Byte aligned defintion for BIOS usage
 #define ATOM_S6_DEVICE_CHANGEb0         0x01
 #define ATOM_S6_SCALER_CHANGEb0         0x02
 #define ATOM_S6_LID_CHANGEb0            0x04
@@ -3320,11 +4145,11 @@
 #define ATOM_S6_LID_STATEb0             0x40
 #define ATOM_S6_DOCK_STATEb0            0x80
 #define ATOM_S6_CRITICAL_STATEb1        0x01
-#define ATOM_S6_HW_I2C_BUSY_STATEb1     0x02
+#define ATOM_S6_HW_I2C_BUSY_STATEb1     0x02  
 #define ATOM_S6_THERMAL_STATE_CHANGEb1  0x04
 #define ATOM_S6_INTERRUPT_SET_BY_BIOSb1 0x08
-#define ATOM_S6_REQ_LCD_EXPANSION_FULLb1        0x10
-#define ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIOb1 0x20
+#define ATOM_S6_REQ_LCD_EXPANSION_FULLb1        0x10    
+#define ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIOb1 0x20 
 
 #define ATOM_S6_ACC_REQ_CRT1b2          0x01
 #define ATOM_S6_ACC_REQ_LCD1b2          0x02
@@ -3332,12 +4157,12 @@
 #define ATOM_S6_ACC_REQ_DFP1b2          0x08
 #define ATOM_S6_ACC_REQ_CRT2b2          0x10
 #define ATOM_S6_ACC_REQ_LCD2b2          0x20
-#define ATOM_S6_ACC_REQ_TV2b2           0x40
+#define ATOM_S6_ACC_REQ_DFP6b2          0x40
 #define ATOM_S6_ACC_REQ_DFP2b2          0x80
 #define ATOM_S6_ACC_REQ_CVb3            0x01
-#define ATOM_S6_ACC_REQ_DFP3b3					0x02
-#define ATOM_S6_ACC_REQ_DFP4b3					0x04
-#define ATOM_S6_ACC_REQ_DFP5b3					0x08
+#define ATOM_S6_ACC_REQ_DFP3b3          0x02
+#define ATOM_S6_ACC_REQ_DFP4b3          0x04
+#define ATOM_S6_ACC_REQ_DFP5b3          0x08
 
 #define ATOM_S6_ACC_REQ_DEVICEw1        ATOM_S5_DOS_REQ_DEVICEw0
 #define ATOM_S6_SYSTEM_POWER_MODE_CHANGEb3 0x10
@@ -3366,7 +4191,7 @@
 #define ATOM_S6_VRI_BRIGHTNESS_CHANGE_SHIFT     30
 #define ATOM_S6_CONFIG_DISPLAY_CHANGE_SHIFT     31
 
-/*  BIOS_7_SCRATCH Definition, BIOS_7_SCRATCH is used by Firmware only !!!! */
+// BIOS_7_SCRATCH Definition, BIOS_7_SCRATCH is used by Firmware only !!!!
 #define ATOM_S7_DOS_MODE_TYPEb0             0x03
 #define ATOM_S7_DOS_MODE_VGAb0              0x00
 #define ATOM_S7_DOS_MODE_VESAb0             0x01
@@ -3378,220 +4203,194 @@
 
 #define ATOM_S7_DOS_8BIT_DAC_EN_SHIFT       8
 
-/*  BIOS_8_SCRATCH Definition */
+// BIOS_8_SCRATCH Definition
 #define ATOM_S8_I2C_CHANNEL_BUSY_MASK       0x00000FFFF
-#define ATOM_S8_I2C_HW_ENGINE_BUSY_MASK     0x0FFFF0000
+#define ATOM_S8_I2C_HW_ENGINE_BUSY_MASK     0x0FFFF0000   
 
 #define ATOM_S8_I2C_CHANNEL_BUSY_SHIFT      0
 #define ATOM_S8_I2C_ENGINE_BUSY_SHIFT       16
 
-/*  BIOS_9_SCRATCH Definition */
-#ifndef ATOM_S9_I2C_CHANNEL_COMPLETED_MASK
+// BIOS_9_SCRATCH Definition
+#ifndef ATOM_S9_I2C_CHANNEL_COMPLETED_MASK 
 #define ATOM_S9_I2C_CHANNEL_COMPLETED_MASK  0x0000FFFF
 #endif
-#ifndef ATOM_S9_I2C_CHANNEL_ABORTED_MASK
+#ifndef ATOM_S9_I2C_CHANNEL_ABORTED_MASK  
 #define ATOM_S9_I2C_CHANNEL_ABORTED_MASK    0xFFFF0000
 #endif
-#ifndef ATOM_S9_I2C_CHANNEL_COMPLETED_SHIFT
+#ifndef ATOM_S9_I2C_CHANNEL_COMPLETED_SHIFT 
 #define ATOM_S9_I2C_CHANNEL_COMPLETED_SHIFT 0
 #endif
-#ifndef ATOM_S9_I2C_CHANNEL_ABORTED_SHIFT
+#ifndef ATOM_S9_I2C_CHANNEL_ABORTED_SHIFT   
 #define ATOM_S9_I2C_CHANNEL_ABORTED_SHIFT   16
 #endif
 
+ 
 #define ATOM_FLAG_SET                         0x20
 #define ATOM_FLAG_CLEAR                       0
-#define CLEAR_ATOM_S6_ACC_MODE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_ACC_MODE_SHIFT | ATOM_FLAG_CLEAR)
-#define SET_ATOM_S6_DEVICE_CHANGE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_DEVICE_CHANGE_SHIFT | ATOM_FLAG_SET)
-#define SET_ATOM_S6_VRI_BRIGHTNESS_CHANGE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_VRI_BRIGHTNESS_CHANGE_SHIFT | ATOM_FLAG_SET)
-#define SET_ATOM_S6_SCALER_CHANGE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_SCALER_CHANGE_SHIFT | ATOM_FLAG_SET)
-#define SET_ATOM_S6_LID_CHANGE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_LID_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define CLEAR_ATOM_S6_ACC_MODE                ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_ACC_MODE_SHIFT | ATOM_FLAG_CLEAR)
+#define SET_ATOM_S6_DEVICE_CHANGE             ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_DEVICE_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_VRI_BRIGHTNESS_CHANGE     ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_VRI_BRIGHTNESS_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_SCALER_CHANGE             ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_SCALER_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_LID_CHANGE                ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_LID_CHANGE_SHIFT | ATOM_FLAG_SET)
 
-#define SET_ATOM_S6_LID_STATE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) |\
-	 ATOM_S6_LID_STATE_SHIFT | ATOM_FLAG_SET)
-#define CLEAR_ATOM_S6_LID_STATE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_LID_STATE_SHIFT | ATOM_FLAG_CLEAR)
+#define SET_ATOM_S6_LID_STATE                 ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_LID_STATE_SHIFT | ATOM_FLAG_SET)
+#define CLEAR_ATOM_S6_LID_STATE               ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_LID_STATE_SHIFT | ATOM_FLAG_CLEAR)
 
-#define SET_ATOM_S6_DOCK_CHANGE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8)| \
-	 ATOM_S6_DOCKING_CHANGE_SHIFT | ATOM_FLAG_SET)
-#define SET_ATOM_S6_DOCK_STATE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_DOCK_STATE_SHIFT | ATOM_FLAG_SET)
-#define CLEAR_ATOM_S6_DOCK_STATE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_DOCK_STATE_SHIFT | ATOM_FLAG_CLEAR)
+#define SET_ATOM_S6_DOCK_CHANGE			          ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_DOCKING_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_DOCK_STATE                ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_DOCK_STATE_SHIFT | ATOM_FLAG_SET)
+#define CLEAR_ATOM_S6_DOCK_STATE              ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_DOCK_STATE_SHIFT | ATOM_FLAG_CLEAR)
 
-#define SET_ATOM_S6_THERMAL_STATE_CHANGE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_THERMAL_STATE_CHANGE_SHIFT | ATOM_FLAG_SET)
-#define SET_ATOM_S6_SYSTEM_POWER_MODE_CHANGE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_SYSTEM_POWER_MODE_CHANGE_SHIFT | ATOM_FLAG_SET)
-#define SET_ATOM_S6_INTERRUPT_SET_BY_BIOS \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_INTERRUPT_SET_BY_BIOS_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_THERMAL_STATE_CHANGE      ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_THERMAL_STATE_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_SYSTEM_POWER_MODE_CHANGE  ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_SYSTEM_POWER_MODE_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define SET_ATOM_S6_INTERRUPT_SET_BY_BIOS     ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_INTERRUPT_SET_BY_BIOS_SHIFT | ATOM_FLAG_SET)
 
-#define SET_ATOM_S6_CRITICAL_STATE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_CRITICAL_STATE_SHIFT | ATOM_FLAG_SET)
-#define CLEAR_ATOM_S6_CRITICAL_STATE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_CRITICAL_STATE_SHIFT | ATOM_FLAG_CLEAR)
+#define SET_ATOM_S6_CRITICAL_STATE            ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_CRITICAL_STATE_SHIFT | ATOM_FLAG_SET)
+#define CLEAR_ATOM_S6_CRITICAL_STATE          ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_CRITICAL_STATE_SHIFT | ATOM_FLAG_CLEAR)
 
-#define SET_ATOM_S6_REQ_SCALER \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_REQ_SCALER_SHIFT | ATOM_FLAG_SET)
-#define CLEAR_ATOM_S6_REQ_SCALER \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_REQ_SCALER_SHIFT | ATOM_FLAG_CLEAR )
+#define SET_ATOM_S6_REQ_SCALER                ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_REQ_SCALER_SHIFT | ATOM_FLAG_SET)  
+#define CLEAR_ATOM_S6_REQ_SCALER              ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_REQ_SCALER_SHIFT | ATOM_FLAG_CLEAR )
 
-#define SET_ATOM_S6_REQ_SCALER_ARATIO \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_REQ_SCALER_ARATIO_SHIFT | ATOM_FLAG_SET )
-#define CLEAR_ATOM_S6_REQ_SCALER_ARATIO \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_REQ_SCALER_ARATIO_SHIFT | ATOM_FLAG_CLEAR )
+#define SET_ATOM_S6_REQ_SCALER_ARATIO         ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_REQ_SCALER_ARATIO_SHIFT | ATOM_FLAG_SET )
+#define CLEAR_ATOM_S6_REQ_SCALER_ARATIO       ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_REQ_SCALER_ARATIO_SHIFT | ATOM_FLAG_CLEAR )
 
-#define SET_ATOM_S6_I2C_STATE_CHANGE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_I2C_STATE_CHANGE_SHIFT | ATOM_FLAG_SET )
+#define SET_ATOM_S6_I2C_STATE_CHANGE          ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_I2C_STATE_CHANGE_SHIFT | ATOM_FLAG_SET )
 
-#define SET_ATOM_S6_DISPLAY_STATE_CHANGE \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_DISPLAY_STATE_CHANGE_SHIFT | ATOM_FLAG_SET )
+#define SET_ATOM_S6_DISPLAY_STATE_CHANGE      ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_DISPLAY_STATE_CHANGE_SHIFT | ATOM_FLAG_SET )
 
-#define SET_ATOM_S6_DEVICE_RECONFIG \
-	((ATOM_ACC_CHANGE_INFO_DEF << 8) | \
-	 ATOM_S6_CONFIG_DISPLAY_CHANGE_SHIFT | ATOM_FLAG_SET)
-#define CLEAR_ATOM_S0_LCD1 \
-	((ATOM_DEVICE_CONNECT_INFO_DEF << 8 ) | \
-	 ATOM_S0_LCD1_SHIFT | ATOM_FLAG_CLEAR )
-#define SET_ATOM_S7_DOS_8BIT_DAC_EN \
-	((ATOM_DOS_MODE_INFO_DEF << 8) | \
-	 ATOM_S7_DOS_8BIT_DAC_EN_SHIFT | ATOM_FLAG_SET )
-#define CLEAR_ATOM_S7_DOS_8BIT_DAC_EN \
-	((ATOM_DOS_MODE_INFO_DEF << 8) | \
-	 ATOM_S7_DOS_8BIT_DAC_EN_SHIFT | ATOM_FLAG_CLEAR )
+#define SET_ATOM_S6_DEVICE_RECONFIG           ((ATOM_ACC_CHANGE_INFO_DEF << 8 )|ATOM_S6_CONFIG_DISPLAY_CHANGE_SHIFT | ATOM_FLAG_SET)
+#define CLEAR_ATOM_S0_LCD1                    ((ATOM_DEVICE_CONNECT_INFO_DEF << 8 )|  ATOM_S0_LCD1_SHIFT | ATOM_FLAG_CLEAR )
+#define SET_ATOM_S7_DOS_8BIT_DAC_EN           ((ATOM_DOS_MODE_INFO_DEF << 8 )|ATOM_S7_DOS_8BIT_DAC_EN_SHIFT | ATOM_FLAG_SET )
+#define CLEAR_ATOM_S7_DOS_8BIT_DAC_EN         ((ATOM_DOS_MODE_INFO_DEF << 8 )|ATOM_S7_DOS_8BIT_DAC_EN_SHIFT | ATOM_FLAG_CLEAR )
 
-/****************************************************************************/
-/* Portion II: Definitinos only used in Driver */
+/****************************************************************************/	
+//Portion II: Definitinos only used in Driver
 /****************************************************************************/
 
-/*  Macros used by driver */
+// Macros used by driver
+#ifdef __cplusplus
+#define GetIndexIntoMasterTable(MasterOrData, FieldName) ((reinterpret_cast<char*>(&(static_cast<ATOM_MASTER_LIST_OF_##MasterOrData##_TABLES*>(0))->FieldName)-static_cast<char*>(0))/sizeof(USHORT))
 
-#define	GetIndexIntoMasterTable(MasterOrData, FieldName) (((char *)(&((ATOM_MASTER_LIST_OF_##MasterOrData##_TABLES *)0)->FieldName)-(char *)0)/sizeof(USHORT))
+#define GET_COMMAND_TABLE_COMMANDSET_REVISION(TABLE_HEADER_OFFSET) (((static_cast<ATOM_COMMON_TABLE_HEADER*>(TABLE_HEADER_OFFSET))->ucTableFormatRevision )&0x3F)
+#define GET_COMMAND_TABLE_PARAMETER_REVISION(TABLE_HEADER_OFFSET)  (((static_cast<ATOM_COMMON_TABLE_HEADER*>(TABLE_HEADER_OFFSET))->ucTableContentRevision)&0x3F)
+#else // not __cplusplus
+#define	GetIndexIntoMasterTable(MasterOrData, FieldName) (((char*)(&((ATOM_MASTER_LIST_OF_##MasterOrData##_TABLES*)0)->FieldName)-(char*)0)/sizeof(USHORT))
 
 #define GET_COMMAND_TABLE_COMMANDSET_REVISION(TABLE_HEADER_OFFSET) ((((ATOM_COMMON_TABLE_HEADER*)TABLE_HEADER_OFFSET)->ucTableFormatRevision)&0x3F)
 #define GET_COMMAND_TABLE_PARAMETER_REVISION(TABLE_HEADER_OFFSET)  ((((ATOM_COMMON_TABLE_HEADER*)TABLE_HEADER_OFFSET)->ucTableContentRevision)&0x3F)
+#endif // __cplusplus
 
 #define GET_DATA_TABLE_MAJOR_REVISION GET_COMMAND_TABLE_COMMANDSET_REVISION
 #define GET_DATA_TABLE_MINOR_REVISION GET_COMMAND_TABLE_PARAMETER_REVISION
 
-/****************************************************************************/
-/* Portion III: Definitinos only used in VBIOS */
+/****************************************************************************/	
+//Portion III: Definitinos only used in VBIOS
 /****************************************************************************/
 #define ATOM_DAC_SRC					0x80
 #define ATOM_SRC_DAC1					0
 #define ATOM_SRC_DAC2					0x80
 
-#ifdef	UEFI_BUILD
-#define	USHORT	UTEMP
-#endif
-
-typedef struct _MEMORY_PLLINIT_PARAMETERS {
-	ULONG ulTargetMemoryClock;	/* In 10Khz unit */
-	UCHAR ucAction;		/* not define yet */
-	UCHAR ucFbDiv_Hi;	/* Fbdiv Hi byte */
-	UCHAR ucFbDiv;		/* FB value */
-	UCHAR ucPostDiv;	/* Post div */
-} MEMORY_PLLINIT_PARAMETERS;
+typedef struct _MEMORY_PLLINIT_PARAMETERS
+{
+  ULONG ulTargetMemoryClock; //In 10Khz unit
+  UCHAR   ucAction;					 //not define yet
+  UCHAR   ucFbDiv_Hi;				 //Fbdiv Hi byte
+  UCHAR   ucFbDiv;					 //FB value
+  UCHAR   ucPostDiv;				 //Post div
+}MEMORY_PLLINIT_PARAMETERS;
 
 #define MEMORY_PLLINIT_PS_ALLOCATION  MEMORY_PLLINIT_PARAMETERS
 
-#define	GPIO_PIN_WRITE													0x01
+
+#define	GPIO_PIN_WRITE													0x01			
 #define	GPIO_PIN_READ														0x00
 
-typedef struct _GPIO_PIN_CONTROL_PARAMETERS {
-	UCHAR ucGPIO_ID;	/* return value, read from GPIO pins */
-	UCHAR ucGPIOBitShift;	/* define which bit in uGPIOBitVal need to be update */
-	UCHAR ucGPIOBitVal;	/* Set/Reset corresponding bit defined in ucGPIOBitMask */
-	UCHAR ucAction;		/* =GPIO_PIN_WRITE: Read; =GPIO_PIN_READ: Write */
-} GPIO_PIN_CONTROL_PARAMETERS;
+typedef struct  _GPIO_PIN_CONTROL_PARAMETERS
+{
+  UCHAR ucGPIO_ID;           //return value, read from GPIO pins
+  UCHAR ucGPIOBitShift;	     //define which bit in uGPIOBitVal need to be update 
+	UCHAR ucGPIOBitVal;		     //Set/Reset corresponding bit defined in ucGPIOBitMask
+  UCHAR ucAction;				     //=GPIO_PIN_WRITE: Read; =GPIO_PIN_READ: Write
+}GPIO_PIN_CONTROL_PARAMETERS;
 
-typedef struct _ENABLE_SCALER_PARAMETERS {
-	UCHAR ucScaler;		/*  ATOM_SCALER1, ATOM_SCALER2 */
-	UCHAR ucEnable;		/*  ATOM_SCALER_DISABLE or ATOM_SCALER_CENTER or ATOM_SCALER_EXPANSION */
-	UCHAR ucTVStandard;	/*  */
-	UCHAR ucPadding[1];
-} ENABLE_SCALER_PARAMETERS;
-#define ENABLE_SCALER_PS_ALLOCATION ENABLE_SCALER_PARAMETERS
+typedef struct _ENABLE_SCALER_PARAMETERS
+{
+  UCHAR ucScaler;            // ATOM_SCALER1, ATOM_SCALER2
+  UCHAR ucEnable;            // ATOM_SCALER_DISABLE or ATOM_SCALER_CENTER or ATOM_SCALER_EXPANSION
+  UCHAR ucTVStandard;        // 
+  UCHAR ucPadding[1];
+}ENABLE_SCALER_PARAMETERS; 
+#define ENABLE_SCALER_PS_ALLOCATION ENABLE_SCALER_PARAMETERS 
 
-/* ucEnable: */
+//ucEnable:
 #define SCALER_BYPASS_AUTO_CENTER_NO_REPLICATION    0
 #define SCALER_BYPASS_AUTO_CENTER_AUTO_REPLICATION  1
 #define SCALER_ENABLE_2TAP_ALPHA_MODE               2
 #define SCALER_ENABLE_MULTITAP_MODE                 3
 
-typedef struct _ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS {
-	ULONG usHWIconHorzVertPosn;	/*  Hardware Icon Vertical position */
-	UCHAR ucHWIconVertOffset;	/*  Hardware Icon Vertical offset */
-	UCHAR ucHWIconHorzOffset;	/*  Hardware Icon Horizontal offset */
-	UCHAR ucSelection;	/*  ATOM_CURSOR1 or ATOM_ICON1 or ATOM_CURSOR2 or ATOM_ICON2 */
-	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
-} ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS;
+typedef struct _ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS
+{
+  ULONG  usHWIconHorzVertPosn;        // Hardware Icon Vertical position
+  UCHAR  ucHWIconVertOffset;          // Hardware Icon Vertical offset
+  UCHAR  ucHWIconHorzOffset;          // Hardware Icon Horizontal offset
+  UCHAR  ucSelection;                 // ATOM_CURSOR1 or ATOM_ICON1 or ATOM_CURSOR2 or ATOM_ICON2
+  UCHAR  ucEnable;                    // ATOM_ENABLE or ATOM_DISABLE
+}ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS;
 
-typedef struct _ENABLE_HARDWARE_ICON_CURSOR_PS_ALLOCATION {
-	ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS sEnableIcon;
-	ENABLE_CRTC_PARAMETERS sReserved;
-} ENABLE_HARDWARE_ICON_CURSOR_PS_ALLOCATION;
+typedef struct _ENABLE_HARDWARE_ICON_CURSOR_PS_ALLOCATION
+{
+  ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS  sEnableIcon;
+  ENABLE_CRTC_PARAMETERS                  sReserved;  
+}ENABLE_HARDWARE_ICON_CURSOR_PS_ALLOCATION;
 
-typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS {
-	USHORT usHight;		/*  Image Hight */
-	USHORT usWidth;		/*  Image Width */
-	UCHAR ucSurface;	/*  Surface 1 or 2 */
-	UCHAR ucPadding[3];
-} ENABLE_GRAPH_SURFACE_PARAMETERS;
+typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS
+{
+  USHORT usHight;                     // Image Hight
+  USHORT usWidth;                     // Image Width
+  UCHAR  ucSurface;                   // Surface 1 or 2	
+  UCHAR  ucPadding[3];
+}ENABLE_GRAPH_SURFACE_PARAMETERS;
 
-typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS_V1_2 {
-	USHORT usHight;		/*  Image Hight */
-	USHORT usWidth;		/*  Image Width */
-	UCHAR ucSurface;	/*  Surface 1 or 2 */
-	UCHAR ucEnable;		/*  ATOM_ENABLE or ATOM_DISABLE */
-	UCHAR ucPadding[2];
-} ENABLE_GRAPH_SURFACE_PARAMETERS_V1_2;
+typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS_V1_2
+{
+  USHORT usHight;                     // Image Hight
+  USHORT usWidth;                     // Image Width
+  UCHAR  ucSurface;                   // Surface 1 or 2
+  UCHAR  ucEnable;                    // ATOM_ENABLE or ATOM_DISABLE
+  UCHAR  ucPadding[2];
+}ENABLE_GRAPH_SURFACE_PARAMETERS_V1_2;
 
-typedef struct _ENABLE_GRAPH_SURFACE_PS_ALLOCATION {
-	ENABLE_GRAPH_SURFACE_PARAMETERS sSetSurface;
-	ENABLE_YUV_PS_ALLOCATION sReserved;	/*  Don't set this one */
-} ENABLE_GRAPH_SURFACE_PS_ALLOCATION;
+typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS_V1_3
+{
+  USHORT usHight;                     // Image Hight
+  USHORT usWidth;                     // Image Width
+  UCHAR  ucSurface;                   // Surface 1 or 2
+  UCHAR  ucEnable;                    // ATOM_ENABLE or ATOM_DISABLE
+  USHORT usDeviceId;                  // Active Device Id for this surface. If no device, set to 0. 
+}ENABLE_GRAPH_SURFACE_PARAMETERS_V1_3;
 
-typedef struct _MEMORY_CLEAN_UP_PARAMETERS {
-	USHORT usMemoryStart;	/* in 8Kb boundry, offset from memory base address */
-	USHORT usMemorySize;	/* 8Kb blocks aligned */
-} MEMORY_CLEAN_UP_PARAMETERS;
+typedef struct _ENABLE_GRAPH_SURFACE_PS_ALLOCATION
+{
+  ENABLE_GRAPH_SURFACE_PARAMETERS sSetSurface;          
+  ENABLE_YUV_PS_ALLOCATION        sReserved; // Don't set this one
+}ENABLE_GRAPH_SURFACE_PS_ALLOCATION;
+
+typedef struct _MEMORY_CLEAN_UP_PARAMETERS
+{
+  USHORT  usMemoryStart;                //in 8Kb boundry, offset from memory base address
+  USHORT  usMemorySize;                 //8Kb blocks aligned
+}MEMORY_CLEAN_UP_PARAMETERS;
 #define MEMORY_CLEAN_UP_PS_ALLOCATION MEMORY_CLEAN_UP_PARAMETERS
 
-typedef struct _GET_DISPLAY_SURFACE_SIZE_PARAMETERS {
-	USHORT usX_Size;	/* When use as input parameter, usX_Size indicates which CRTC */
-	USHORT usY_Size;
-} GET_DISPLAY_SURFACE_SIZE_PARAMETERS;
+typedef struct  _GET_DISPLAY_SURFACE_SIZE_PARAMETERS
+{
+  USHORT  usX_Size;                     //When use as input parameter, usX_Size indicates which CRTC                 
+  USHORT  usY_Size;
+}GET_DISPLAY_SURFACE_SIZE_PARAMETERS; 
 
-typedef struct _INDIRECT_IO_ACCESS {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR IOAccessSequence[256];
+typedef struct _INDIRECT_IO_ACCESS
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  UCHAR                    IOAccessSequence[256];
 } INDIRECT_IO_ACCESS;
 
 #define INDIRECT_READ              0x00
@@ -3615,93 +4414,108 @@
 #define INDIRECT_IO_NBMISC_READ    INDIRECT_IO_NBMISC | INDIRECT_READ
 #define INDIRECT_IO_NBMISC_WRITE   INDIRECT_IO_NBMISC | INDIRECT_WRITE
 
-typedef struct _ATOM_OEM_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;
-} ATOM_OEM_INFO;
+typedef struct _ATOM_OEM_INFO
+{ 
+  ATOM_COMMON_TABLE_HEADER	sHeader;
+  ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;
+}ATOM_OEM_INFO;
 
-typedef struct _ATOM_TV_MODE {
-	UCHAR ucVMode_Num;	/* Video mode number */
-	UCHAR ucTV_Mode_Num;	/* Internal TV mode number */
-} ATOM_TV_MODE;
+typedef struct _ATOM_TV_MODE
+{
+   UCHAR	ucVMode_Num;			  //Video mode number
+   UCHAR	ucTV_Mode_Num;			//Internal TV mode number
+}ATOM_TV_MODE;
 
-typedef struct _ATOM_BIOS_INT_TVSTD_MODE {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usTV_Mode_LUT_Offset;	/*  Pointer to standard to internal number conversion table */
-	USHORT usTV_FIFO_Offset;	/*  Pointer to FIFO entry table */
-	USHORT usNTSC_Tbl_Offset;	/*  Pointer to SDTV_Mode_NTSC table */
-	USHORT usPAL_Tbl_Offset;	/*  Pointer to SDTV_Mode_PAL table */
-	USHORT usCV_Tbl_Offset;	/*  Pointer to SDTV_Mode_PAL table */
-} ATOM_BIOS_INT_TVSTD_MODE;
+typedef struct _ATOM_BIOS_INT_TVSTD_MODE
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+   USHORT	usTV_Mode_LUT_Offset;	// Pointer to standard to internal number conversion table
+   USHORT	usTV_FIFO_Offset;		  // Pointer to FIFO entry table
+   USHORT	usNTSC_Tbl_Offset;		// Pointer to SDTV_Mode_NTSC table
+   USHORT	usPAL_Tbl_Offset;		  // Pointer to SDTV_Mode_PAL table 
+   USHORT	usCV_Tbl_Offset;		  // Pointer to SDTV_Mode_PAL table 
+}ATOM_BIOS_INT_TVSTD_MODE;
 
-typedef struct _ATOM_TV_MODE_SCALER_PTR {
-	USHORT ucFilter0_Offset;	/* Pointer to filter format 0 coefficients */
-	USHORT usFilter1_Offset;	/* Pointer to filter format 0 coefficients */
-	UCHAR ucTV_Mode_Num;
-} ATOM_TV_MODE_SCALER_PTR;
 
-typedef struct _ATOM_STANDARD_VESA_TIMING {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_DTD_FORMAT aModeTimings[16];	/*  16 is not the real array number, just for initial allocation */
-} ATOM_STANDARD_VESA_TIMING;
+typedef struct _ATOM_TV_MODE_SCALER_PTR
+{
+   USHORT	ucFilter0_Offset;		//Pointer to filter format 0 coefficients
+   USHORT	usFilter1_Offset;		//Pointer to filter format 0 coefficients
+   UCHAR	ucTV_Mode_Num;
+}ATOM_TV_MODE_SCALER_PTR;
 
-typedef struct _ATOM_STD_FORMAT {
-	USHORT usSTD_HDisp;
-	USHORT usSTD_VDisp;
-	USHORT usSTD_RefreshRate;
-	USHORT usReserved;
-} ATOM_STD_FORMAT;
+typedef struct _ATOM_STANDARD_VESA_TIMING
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  ATOM_DTD_FORMAT 				 aModeTimings[16];      // 16 is not the real array number, just for initial allocation
+}ATOM_STANDARD_VESA_TIMING;
 
-typedef struct _ATOM_VESA_TO_EXTENDED_MODE {
-	USHORT usVESA_ModeNumber;
-	USHORT usExtendedModeNumber;
-} ATOM_VESA_TO_EXTENDED_MODE;
 
-typedef struct _ATOM_VESA_TO_INTENAL_MODE_LUT {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	ATOM_VESA_TO_EXTENDED_MODE asVESA_ToExtendedModeInfo[76];
-} ATOM_VESA_TO_INTENAL_MODE_LUT;
+typedef struct _ATOM_STD_FORMAT
+{ 
+  USHORT    usSTD_HDisp;
+  USHORT    usSTD_VDisp;
+  USHORT    usSTD_RefreshRate;
+  USHORT    usReserved;
+}ATOM_STD_FORMAT;
+
+typedef struct _ATOM_VESA_TO_EXTENDED_MODE
+{
+  USHORT  usVESA_ModeNumber;
+  USHORT  usExtendedModeNumber;
+}ATOM_VESA_TO_EXTENDED_MODE;
+
+typedef struct _ATOM_VESA_TO_INTENAL_MODE_LUT
+{ 
+  ATOM_COMMON_TABLE_HEADER   sHeader;  
+  ATOM_VESA_TO_EXTENDED_MODE asVESA_ToExtendedModeInfo[76];
+}ATOM_VESA_TO_INTENAL_MODE_LUT;
 
 /*************** ATOM Memory Related Data Structure ***********************/
-typedef struct _ATOM_MEMORY_VENDOR_BLOCK {
-	UCHAR ucMemoryType;
-	UCHAR ucMemoryVendor;
-	UCHAR ucAdjMCId;
-	UCHAR ucDynClkId;
-	ULONG ulDllResetClkRange;
-} ATOM_MEMORY_VENDOR_BLOCK;
+typedef struct _ATOM_MEMORY_VENDOR_BLOCK{
+	UCHAR												ucMemoryType;
+	UCHAR												ucMemoryVendor;
+	UCHAR												ucAdjMCId;
+	UCHAR												ucDynClkId;
+	ULONG												ulDllResetClkRange;
+}ATOM_MEMORY_VENDOR_BLOCK;
 
-typedef struct _ATOM_MEMORY_SETTING_ID_CONFIG {
+
+typedef struct _ATOM_MEMORY_SETTING_ID_CONFIG{
 #if ATOM_BIG_ENDIAN
-	ULONG ucMemBlkId:8;
-	ULONG ulMemClockRange:24;
+	ULONG												ucMemBlkId:8;
+	ULONG												ulMemClockRange:24;
 #else
-	ULONG ulMemClockRange:24;
-	ULONG ucMemBlkId:8;
+	ULONG												ulMemClockRange:24;
+	ULONG												ucMemBlkId:8;
 #endif
-} ATOM_MEMORY_SETTING_ID_CONFIG;
+}ATOM_MEMORY_SETTING_ID_CONFIG;
 
-typedef union _ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS {
-	ATOM_MEMORY_SETTING_ID_CONFIG slAccess;
-	ULONG ulAccess;
-} ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS;
+typedef union _ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS
+{
+  ATOM_MEMORY_SETTING_ID_CONFIG slAccess;
+  ULONG                         ulAccess;
+}ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS;
 
-typedef struct _ATOM_MEMORY_SETTING_DATA_BLOCK {
-	ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS ulMemoryID;
-	ULONG aulMemData[1];
-} ATOM_MEMORY_SETTING_DATA_BLOCK;
 
-typedef struct _ATOM_INIT_REG_INDEX_FORMAT {
-	USHORT usRegIndex;	/*  MC register index */
-	UCHAR ucPreRegDataLength;	/*  offset in ATOM_INIT_REG_DATA_BLOCK.saRegDataBuf */
-} ATOM_INIT_REG_INDEX_FORMAT;
+typedef struct _ATOM_MEMORY_SETTING_DATA_BLOCK{
+	ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS			ulMemoryID;
+	ULONG															        aulMemData[1];
+}ATOM_MEMORY_SETTING_DATA_BLOCK;
 
-typedef struct _ATOM_INIT_REG_BLOCK {
-	USHORT usRegIndexTblSize;	/* size of asRegIndexBuf */
-	USHORT usRegDataBlkSize;	/* size of ATOM_MEMORY_SETTING_DATA_BLOCK */
-	ATOM_INIT_REG_INDEX_FORMAT asRegIndexBuf[1];
-	ATOM_MEMORY_SETTING_DATA_BLOCK asRegDataBuf[1];
-} ATOM_INIT_REG_BLOCK;
+
+typedef struct _ATOM_INIT_REG_INDEX_FORMAT{
+	 USHORT											usRegIndex;                                     // MC register index
+	 UCHAR											ucPreRegDataLength;                             // offset in ATOM_INIT_REG_DATA_BLOCK.saRegDataBuf
+}ATOM_INIT_REG_INDEX_FORMAT;
+
+
+typedef struct _ATOM_INIT_REG_BLOCK{
+	USHORT													usRegIndexTblSize;													//size of asRegIndexBuf
+	USHORT													usRegDataBlkSize;														//size of ATOM_MEMORY_SETTING_DATA_BLOCK
+	ATOM_INIT_REG_INDEX_FORMAT			asRegIndexBuf[1];
+	ATOM_MEMORY_SETTING_DATA_BLOCK	asRegDataBuf[1];
+}ATOM_INIT_REG_BLOCK;
 
 #define END_OF_REG_INDEX_BLOCK  0x0ffff
 #define END_OF_REG_DATA_BLOCK   0x00000000
@@ -3716,16 +4530,19 @@
 #define INDEX_ACCESS_RANGE_END		    (INDEX_ACCESS_RANGE_BEGIN + 1)
 #define VALUE_INDEX_ACCESS_SINGLE	    (INDEX_ACCESS_RANGE_END + 1)
 
-typedef struct _ATOM_MC_INIT_PARAM_TABLE {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usAdjustARB_SEQDataOffset;
-	USHORT usMCInitMemTypeTblOffset;
-	USHORT usMCInitCommonTblOffset;
-	USHORT usMCInitPowerDownTblOffset;
-	ULONG ulARB_SEQDataBuf[32];
-	ATOM_INIT_REG_BLOCK asMCInitMemType;
-	ATOM_INIT_REG_BLOCK asMCInitCommon;
-} ATOM_MC_INIT_PARAM_TABLE;
+
+typedef struct _ATOM_MC_INIT_PARAM_TABLE
+{ 
+  ATOM_COMMON_TABLE_HEADER		sHeader;
+  USHORT											usAdjustARB_SEQDataOffset;
+  USHORT											usMCInitMemTypeTblOffset;
+  USHORT											usMCInitCommonTblOffset;
+  USHORT											usMCInitPowerDownTblOffset;
+	ULONG												ulARB_SEQDataBuf[32];
+	ATOM_INIT_REG_BLOCK					asMCInitMemType;
+	ATOM_INIT_REG_BLOCK					asMCInitCommon;
+}ATOM_MC_INIT_PARAM_TABLE;
+
 
 #define _4Mx16              0x2
 #define _4Mx32              0x3
@@ -3751,221 +4568,272 @@
 
 #define QIMONDA             INFINEON
 #define PROMOS              MOSEL
+#define KRETON              INFINEON
 
-/* ///////////Support for GDDR5 MC uCode to reside in upper 64K of ROM///////////// */
+/////////////Support for GDDR5 MC uCode to reside in upper 64K of ROM/////////////
 
 #define UCODE_ROM_START_ADDRESS		0x1c000
-#define	UCODE_SIGNATURE			0x4375434d	/*  'MCuC' - MC uCode */
+#define	UCODE_SIGNATURE			0x4375434d // 'MCuC' - MC uCode
 
-/* uCode block header for reference */
+//uCode block header for reference
 
-typedef struct _MCuCodeHeader {
-	ULONG ulSignature;
-	UCHAR ucRevision;
-	UCHAR ucChecksum;
-	UCHAR ucReserved1;
-	UCHAR ucReserved2;
-	USHORT usParametersLength;
-	USHORT usUCodeLength;
-	USHORT usReserved1;
-	USHORT usReserved2;
+typedef struct _MCuCodeHeader
+{
+  ULONG  ulSignature;
+  UCHAR  ucRevision;
+  UCHAR  ucChecksum;
+  UCHAR  ucReserved1;
+  UCHAR  ucReserved2;
+  USHORT usParametersLength;
+  USHORT usUCodeLength;
+  USHORT usReserved1;
+  USHORT usReserved2;
 } MCuCodeHeader;
 
-/* //////////////////////////////////////////////////////////////////////////////// */
+//////////////////////////////////////////////////////////////////////////////////
 
 #define ATOM_MAX_NUMBER_OF_VRAM_MODULE	16
 
 #define ATOM_VRAM_MODULE_MEMORY_VENDOR_ID_MASK	0xF
-typedef struct _ATOM_VRAM_MODULE_V1 {
-	ULONG ulReserved;
-	USHORT usEMRSValue;
-	USHORT usMRSValue;
-	USHORT usReserved;
-	UCHAR ucExtMemoryID;	/*  An external indicator (by hardcode, callback or pin) to tell what is the current memory module */
-	UCHAR ucMemoryType;	/*  [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] reserved; */
-	UCHAR ucMemoryVenderID;	/*  Predefined,never change across designs or memory type/vender */
-	UCHAR ucMemoryDeviceCfg;	/*  [7:4]=0x0:4M;=0x1:8M;=0x2:16M;0x3:32M....[3:0]=0x0:x4;=0x1:x8;=0x2:x16;=0x3:x32... */
-	UCHAR ucRow;		/*  Number of Row,in power of 2; */
-	UCHAR ucColumn;		/*  Number of Column,in power of 2; */
-	UCHAR ucBank;		/*  Nunber of Bank; */
-	UCHAR ucRank;		/*  Number of Rank, in power of 2 */
-	UCHAR ucChannelNum;	/*  Number of channel; */
-	UCHAR ucChannelConfig;	/*  [3:0]=Indication of what channel combination;[4:7]=Channel bit width, in number of 2 */
-	UCHAR ucDefaultMVDDQ_ID;	/*  Default MVDDQ setting for this memory block, ID linking to MVDDQ info table to find real set-up data; */
-	UCHAR ucDefaultMVDDC_ID;	/*  Default MVDDC setting for this memory block, ID linking to MVDDC info table to find real set-up data; */
-	UCHAR ucReserved[2];
-} ATOM_VRAM_MODULE_V1;
+typedef struct _ATOM_VRAM_MODULE_V1
+{
+  ULONG                      ulReserved;
+  USHORT                     usEMRSValue;  
+  USHORT                     usMRSValue;
+  USHORT                     usReserved;
+  UCHAR                      ucExtMemoryID;     // An external indicator (by hardcode, callback or pin) to tell what is the current memory module
+  UCHAR                      ucMemoryType;      // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] reserved;
+  UCHAR                      ucMemoryVenderID;  // Predefined,never change across designs or memory type/vender 
+  UCHAR                      ucMemoryDeviceCfg; // [7:4]=0x0:4M;=0x1:8M;=0x2:16M;0x3:32M....[3:0]=0x0:x4;=0x1:x8;=0x2:x16;=0x3:x32...
+  UCHAR                      ucRow;             // Number of Row,in power of 2;
+  UCHAR                      ucColumn;          // Number of Column,in power of 2;
+  UCHAR                      ucBank;            // Nunber of Bank;
+  UCHAR                      ucRank;            // Number of Rank, in power of 2
+  UCHAR                      ucChannelNum;      // Number of channel;
+  UCHAR                      ucChannelConfig;   // [3:0]=Indication of what channel combination;[4:7]=Channel bit width, in number of 2
+  UCHAR                      ucDefaultMVDDQ_ID; // Default MVDDQ setting for this memory block, ID linking to MVDDQ info table to find real set-up data;
+  UCHAR                      ucDefaultMVDDC_ID; // Default MVDDC setting for this memory block, ID linking to MVDDC info table to find real set-up data;
+  UCHAR                      ucReserved[2];
+}ATOM_VRAM_MODULE_V1;
 
-typedef struct _ATOM_VRAM_MODULE_V2 {
-	ULONG ulReserved;
-	ULONG ulFlags;		/*  To enable/disable functionalities based on memory type */
-	ULONG ulEngineClock;	/*  Override of default engine clock for particular memory type */
-	ULONG ulMemoryClock;	/*  Override of default memory clock for particular memory type */
-	USHORT usEMRS2Value;	/*  EMRS2 Value is used for GDDR2 and GDDR4 memory type */
-	USHORT usEMRS3Value;	/*  EMRS3 Value is used for GDDR2 and GDDR4 memory type */
-	USHORT usEMRSValue;
-	USHORT usMRSValue;
-	USHORT usReserved;
-	UCHAR ucExtMemoryID;	/*  An external indicator (by hardcode, callback or pin) to tell what is the current memory module */
-	UCHAR ucMemoryType;	/*  [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] - must not be used for now; */
-	UCHAR ucMemoryVenderID;	/*  Predefined,never change across designs or memory type/vender. If not predefined, vendor detection table gets executed */
-	UCHAR ucMemoryDeviceCfg;	/*  [7:4]=0x0:4M;=0x1:8M;=0x2:16M;0x3:32M....[3:0]=0x0:x4;=0x1:x8;=0x2:x16;=0x3:x32... */
-	UCHAR ucRow;		/*  Number of Row,in power of 2; */
-	UCHAR ucColumn;		/*  Number of Column,in power of 2; */
-	UCHAR ucBank;		/*  Nunber of Bank; */
-	UCHAR ucRank;		/*  Number of Rank, in power of 2 */
-	UCHAR ucChannelNum;	/*  Number of channel; */
-	UCHAR ucChannelConfig;	/*  [3:0]=Indication of what channel combination;[4:7]=Channel bit width, in number of 2 */
-	UCHAR ucDefaultMVDDQ_ID;	/*  Default MVDDQ setting for this memory block, ID linking to MVDDQ info table to find real set-up data; */
-	UCHAR ucDefaultMVDDC_ID;	/*  Default MVDDC setting for this memory block, ID linking to MVDDC info table to find real set-up data; */
-	UCHAR ucRefreshRateFactor;
-	UCHAR ucReserved[3];
-} ATOM_VRAM_MODULE_V2;
 
-typedef struct _ATOM_MEMORY_TIMING_FORMAT {
-	ULONG ulClkRange;	/*  memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing */
-	union {
-		USHORT usMRS;	/*  mode register */
-		USHORT usDDR3_MR0;
-	};
-	union {
-		USHORT usEMRS;	/*  extended mode register */
-		USHORT usDDR3_MR1;
-	};
-	UCHAR ucCL;		/*  CAS latency */
-	UCHAR ucWL;		/*  WRITE Latency */
-	UCHAR uctRAS;		/*  tRAS */
-	UCHAR uctRC;		/*  tRC */
-	UCHAR uctRFC;		/*  tRFC */
-	UCHAR uctRCDR;		/*  tRCDR */
-	UCHAR uctRCDW;		/*  tRCDW */
-	UCHAR uctRP;		/*  tRP */
-	UCHAR uctRRD;		/*  tRRD */
-	UCHAR uctWR;		/*  tWR */
-	UCHAR uctWTR;		/*  tWTR */
-	UCHAR uctPDIX;		/*  tPDIX */
-	UCHAR uctFAW;		/*  tFAW */
-	UCHAR uctAOND;		/*  tAOND */
-	union {
-		struct {
-			UCHAR ucflag;	/*  flag to control memory timing calculation. bit0= control EMRS2 Infineon */
-			UCHAR ucReserved;
-		};
-		USHORT usDDR3_MR2;
-	};
-} ATOM_MEMORY_TIMING_FORMAT;
+typedef struct _ATOM_VRAM_MODULE_V2
+{
+  ULONG                      ulReserved;
+  ULONG                      ulFlags;     			// To enable/disable functionalities based on memory type
+  ULONG                      ulEngineClock;     // Override of default engine clock for particular memory type
+  ULONG                      ulMemoryClock;     // Override of default memory clock for particular memory type
+  USHORT                     usEMRS2Value;      // EMRS2 Value is used for GDDR2 and GDDR4 memory type
+  USHORT                     usEMRS3Value;      // EMRS3 Value is used for GDDR2 and GDDR4 memory type
+  USHORT                     usEMRSValue;  
+  USHORT                     usMRSValue;
+  USHORT                     usReserved;
+  UCHAR                      ucExtMemoryID;     // An external indicator (by hardcode, callback or pin) to tell what is the current memory module
+  UCHAR                      ucMemoryType;      // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] - must not be used for now;
+  UCHAR                      ucMemoryVenderID;  // Predefined,never change across designs or memory type/vender. If not predefined, vendor detection table gets executed
+  UCHAR                      ucMemoryDeviceCfg; // [7:4]=0x0:4M;=0x1:8M;=0x2:16M;0x3:32M....[3:0]=0x0:x4;=0x1:x8;=0x2:x16;=0x3:x32...
+  UCHAR                      ucRow;             // Number of Row,in power of 2;
+  UCHAR                      ucColumn;          // Number of Column,in power of 2;
+  UCHAR                      ucBank;            // Nunber of Bank;
+  UCHAR                      ucRank;            // Number of Rank, in power of 2
+  UCHAR                      ucChannelNum;      // Number of channel;
+  UCHAR                      ucChannelConfig;   // [3:0]=Indication of what channel combination;[4:7]=Channel bit width, in number of 2
+  UCHAR                      ucDefaultMVDDQ_ID; // Default MVDDQ setting for this memory block, ID linking to MVDDQ info table to find real set-up data;
+  UCHAR                      ucDefaultMVDDC_ID; // Default MVDDC setting for this memory block, ID linking to MVDDC info table to find real set-up data;
+  UCHAR                      ucRefreshRateFactor;
+  UCHAR                      ucReserved[3];
+}ATOM_VRAM_MODULE_V2;
 
-typedef struct _ATOM_MEMORY_TIMING_FORMAT_V1 {
-	ULONG ulClkRange;	/*  memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing */
-	USHORT usMRS;		/*  mode register */
-	USHORT usEMRS;		/*  extended mode register */
-	UCHAR ucCL;		/*  CAS latency */
-	UCHAR ucWL;		/*  WRITE Latency */
-	UCHAR uctRAS;		/*  tRAS */
-	UCHAR uctRC;		/*  tRC */
-	UCHAR uctRFC;		/*  tRFC */
-	UCHAR uctRCDR;		/*  tRCDR */
-	UCHAR uctRCDW;		/*  tRCDW */
-	UCHAR uctRP;		/*  tRP */
-	UCHAR uctRRD;		/*  tRRD */
-	UCHAR uctWR;		/*  tWR */
-	UCHAR uctWTR;		/*  tWTR */
-	UCHAR uctPDIX;		/*  tPDIX */
-	UCHAR uctFAW;		/*  tFAW */
-	UCHAR uctAOND;		/*  tAOND */
-	UCHAR ucflag;		/*  flag to control memory timing calculation. bit0= control EMRS2 Infineon */
-/* ///////////////////////GDDR parameters/////////////////////////////////// */
-	UCHAR uctCCDL;		/*  */
-	UCHAR uctCRCRL;		/*  */
-	UCHAR uctCRCWL;		/*  */
-	UCHAR uctCKE;		/*  */
-	UCHAR uctCKRSE;		/*  */
-	UCHAR uctCKRSX;		/*  */
-	UCHAR uctFAW32;		/*  */
-	UCHAR ucReserved1;	/*  */
-	UCHAR ucReserved2;	/*  */
-	UCHAR ucTerminator;
-} ATOM_MEMORY_TIMING_FORMAT_V1;
 
-typedef struct _ATOM_MEMORY_FORMAT {
-	ULONG ulDllDisClock;	/*  memory DLL will be disable when target memory clock is below this clock */
-	union {
-		USHORT usEMRS2Value;	/*  EMRS2 Value is used for GDDR2 and GDDR4 memory type */
-		USHORT usDDR3_Reserved;	/*  Not used for DDR3 memory */
-	};
-	union {
-		USHORT usEMRS3Value;	/*  EMRS3 Value is used for GDDR2 and GDDR4 memory type */
-		USHORT usDDR3_MR3;	/*  Used for DDR3 memory */
-	};
-	UCHAR ucMemoryType;	/*  [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] - must not be used for now; */
-	UCHAR ucMemoryVenderID;	/*  Predefined,never change across designs or memory type/vender. If not predefined, vendor detection table gets executed */
-	UCHAR ucRow;		/*  Number of Row,in power of 2; */
-	UCHAR ucColumn;		/*  Number of Column,in power of 2; */
-	UCHAR ucBank;		/*  Nunber of Bank; */
-	UCHAR ucRank;		/*  Number of Rank, in power of 2 */
-	UCHAR ucBurstSize;	/*  burst size, 0= burst size=4  1= burst size=8 */
-	UCHAR ucDllDisBit;	/*  position of DLL Enable/Disable bit in EMRS ( Extended Mode Register ) */
-	UCHAR ucRefreshRateFactor;	/*  memory refresh rate in unit of ms */
-	UCHAR ucDensity;	/*  _8Mx32, _16Mx32, _16Mx16, _32Mx16 */
-	UCHAR ucPreamble;	/* [7:4] Write Preamble, [3:0] Read Preamble */
-	UCHAR ucMemAttrib;	/*  Memory Device Addribute, like RDBI/WDBI etc */
-	ATOM_MEMORY_TIMING_FORMAT asMemTiming[5];	/* Memory Timing block sort from lower clock to higher clock */
-} ATOM_MEMORY_FORMAT;
+typedef	struct _ATOM_MEMORY_TIMING_FORMAT
+{
+	ULONG											 ulClkRange;				// memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing 	
+  union{
+	  USHORT										 usMRS;							// mode register						
+    USHORT                     usDDR3_MR0;
+  };
+  union{
+	  USHORT										 usEMRS;						// extended mode register
+    USHORT                     usDDR3_MR1;
+  };
+	UCHAR											 ucCL;							// CAS latency
+	UCHAR											 ucWL;							// WRITE Latency				
+	UCHAR											 uctRAS;						// tRAS
+	UCHAR											 uctRC;							// tRC	
+	UCHAR											 uctRFC;						// tRFC
+	UCHAR											 uctRCDR;						// tRCDR	
+	UCHAR											 uctRCDW;						// tRCDW
+	UCHAR											 uctRP;							// tRP
+	UCHAR											 uctRRD;						// tRRD	
+	UCHAR											 uctWR;							// tWR
+	UCHAR											 uctWTR;						// tWTR
+	UCHAR											 uctPDIX;						// tPDIX
+	UCHAR											 uctFAW;						// tFAW
+	UCHAR											 uctAOND;						// tAOND
+  union 
+  {
+    struct {
+	    UCHAR											 ucflag;						// flag to control memory timing calculation. bit0= control EMRS2 Infineon 
+	    UCHAR											 ucReserved;						
+    };
+    USHORT                   usDDR3_MR2;
+  };
+}ATOM_MEMORY_TIMING_FORMAT;
 
-typedef struct _ATOM_VRAM_MODULE_V3 {
-	ULONG ulChannelMapCfg;	/*  board dependent paramenter:Channel combination */
-	USHORT usSize;		/*  size of ATOM_VRAM_MODULE_V3 */
-	USHORT usDefaultMVDDQ;	/*  board dependent parameter:Default Memory Core Voltage */
-	USHORT usDefaultMVDDC;	/*  board dependent parameter:Default Memory IO Voltage */
-	UCHAR ucExtMemoryID;	/*  An external indicator (by hardcode, callback or pin) to tell what is the current memory module */
-	UCHAR ucChannelNum;	/*  board dependent parameter:Number of channel; */
-	UCHAR ucChannelSize;	/*  board dependent parameter:32bit or 64bit */
-	UCHAR ucVREFI;		/*  board dependnt parameter: EXT or INT +160mv to -140mv */
-	UCHAR ucNPL_RT;		/*  board dependent parameter:NPL round trip delay, used for calculate memory timing parameters */
-	UCHAR ucFlag;		/*  To enable/disable functionalities based on memory type */
-	ATOM_MEMORY_FORMAT asMemory;	/*  describ all of video memory parameters from memory spec */
-} ATOM_VRAM_MODULE_V3;
 
-/* ATOM_VRAM_MODULE_V3.ucNPL_RT */
+typedef	struct _ATOM_MEMORY_TIMING_FORMAT_V1
+{
+	ULONG											 ulClkRange;				// memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing 	
+	USHORT										 usMRS;							// mode register						
+	USHORT										 usEMRS;						// extended mode register
+	UCHAR											 ucCL;							// CAS latency
+	UCHAR											 ucWL;							// WRITE Latency				
+	UCHAR											 uctRAS;						// tRAS
+	UCHAR											 uctRC;							// tRC	
+	UCHAR											 uctRFC;						// tRFC
+	UCHAR											 uctRCDR;						// tRCDR	
+	UCHAR											 uctRCDW;						// tRCDW
+	UCHAR											 uctRP;							// tRP
+	UCHAR											 uctRRD;						// tRRD	
+	UCHAR											 uctWR;							// tWR
+	UCHAR											 uctWTR;						// tWTR
+	UCHAR											 uctPDIX;						// tPDIX
+	UCHAR											 uctFAW;						// tFAW
+	UCHAR											 uctAOND;						// tAOND
+	UCHAR											 ucflag;						// flag to control memory timing calculation. bit0= control EMRS2 Infineon 
+////////////////////////////////////GDDR parameters///////////////////////////////////
+	UCHAR											 uctCCDL;						// 
+	UCHAR											 uctCRCRL;						// 
+	UCHAR											 uctCRCWL;						// 
+	UCHAR											 uctCKE;						// 
+	UCHAR											 uctCKRSE;						// 
+	UCHAR											 uctCKRSX;						// 
+	UCHAR											 uctFAW32;						// 
+	UCHAR											 ucMR5lo;					// 
+	UCHAR											 ucMR5hi;					// 
+	UCHAR											 ucTerminator;
+}ATOM_MEMORY_TIMING_FORMAT_V1;
+
+typedef	struct _ATOM_MEMORY_TIMING_FORMAT_V2
+{
+	ULONG											 ulClkRange;				// memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing 	
+	USHORT										 usMRS;							// mode register						
+	USHORT										 usEMRS;						// extended mode register
+	UCHAR											 ucCL;							// CAS latency
+	UCHAR											 ucWL;							// WRITE Latency				
+	UCHAR											 uctRAS;						// tRAS
+	UCHAR											 uctRC;							// tRC	
+	UCHAR											 uctRFC;						// tRFC
+	UCHAR											 uctRCDR;						// tRCDR	
+	UCHAR											 uctRCDW;						// tRCDW
+	UCHAR											 uctRP;							// tRP
+	UCHAR											 uctRRD;						// tRRD	
+	UCHAR											 uctWR;							// tWR
+	UCHAR											 uctWTR;						// tWTR
+	UCHAR											 uctPDIX;						// tPDIX
+	UCHAR											 uctFAW;						// tFAW
+	UCHAR											 uctAOND;						// tAOND
+	UCHAR											 ucflag;						// flag to control memory timing calculation. bit0= control EMRS2 Infineon 
+////////////////////////////////////GDDR parameters///////////////////////////////////
+	UCHAR											 uctCCDL;						// 
+	UCHAR											 uctCRCRL;						// 
+	UCHAR											 uctCRCWL;						// 
+	UCHAR											 uctCKE;						// 
+	UCHAR											 uctCKRSE;						// 
+	UCHAR											 uctCKRSX;						// 
+	UCHAR											 uctFAW32;						// 
+	UCHAR											 ucMR4lo;					// 
+	UCHAR											 ucMR4hi;					// 
+	UCHAR											 ucMR5lo;					// 
+	UCHAR											 ucMR5hi;					// 
+	UCHAR											 ucTerminator;
+	UCHAR											 ucReserved;	
+}ATOM_MEMORY_TIMING_FORMAT_V2;
+
+typedef	struct _ATOM_MEMORY_FORMAT
+{
+	ULONG											 ulDllDisClock;			// memory DLL will be disable when target memory clock is below this clock
+  union{
+    USHORT                     usEMRS2Value;      // EMRS2 Value is used for GDDR2 and GDDR4 memory type
+    USHORT                     usDDR3_Reserved;   // Not used for DDR3 memory
+  };
+  union{
+    USHORT                     usEMRS3Value;      // EMRS3 Value is used for GDDR2 and GDDR4 memory type
+    USHORT                     usDDR3_MR3;        // Used for DDR3 memory
+  };
+  UCHAR                      ucMemoryType;      // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] - must not be used for now;
+  UCHAR                      ucMemoryVenderID;  // Predefined,never change across designs or memory type/vender. If not predefined, vendor detection table gets executed
+  UCHAR                      ucRow;             // Number of Row,in power of 2;
+  UCHAR                      ucColumn;          // Number of Column,in power of 2;
+  UCHAR                      ucBank;            // Nunber of Bank;
+  UCHAR                      ucRank;            // Number of Rank, in power of 2
+	UCHAR											 ucBurstSize;				// burst size, 0= burst size=4  1= burst size=8
+  UCHAR                      ucDllDisBit;				// position of DLL Enable/Disable bit in EMRS ( Extended Mode Register )
+  UCHAR                      ucRefreshRateFactor;	// memory refresh rate in unit of ms	
+	UCHAR											 ucDensity;					// _8Mx32, _16Mx32, _16Mx16, _32Mx16
+	UCHAR											 ucPreamble;				//[7:4] Write Preamble, [3:0] Read Preamble
+  UCHAR											 ucMemAttrib;				// Memory Device Addribute, like RDBI/WDBI etc
+	ATOM_MEMORY_TIMING_FORMAT	 asMemTiming[5];		//Memory Timing block sort from lower clock to higher clock
+}ATOM_MEMORY_FORMAT;
+
+
+typedef struct _ATOM_VRAM_MODULE_V3
+{
+	ULONG											 ulChannelMapCfg;		// board dependent paramenter:Channel combination
+	USHORT										 usSize;						// size of ATOM_VRAM_MODULE_V3
+  USHORT                     usDefaultMVDDQ;		// board dependent parameter:Default Memory Core Voltage
+  USHORT                     usDefaultMVDDC;		// board dependent parameter:Default Memory IO Voltage
+	UCHAR                      ucExtMemoryID;     // An external indicator (by hardcode, callback or pin) to tell what is the current memory module
+  UCHAR                      ucChannelNum;      // board dependent parameter:Number of channel;
+	UCHAR											 ucChannelSize;			// board dependent parameter:32bit or 64bit	
+	UCHAR											 ucVREFI;						// board dependnt parameter: EXT or INT +160mv to -140mv
+	UCHAR											 ucNPL_RT;					// board dependent parameter:NPL round trip delay, used for calculate memory timing parameters
+	UCHAR											 ucFlag;						// To enable/disable functionalities based on memory type
+	ATOM_MEMORY_FORMAT				 asMemory;					// describ all of video memory parameters from memory spec
+}ATOM_VRAM_MODULE_V3;
+
+
+//ATOM_VRAM_MODULE_V3.ucNPL_RT
 #define NPL_RT_MASK															0x0f
 #define BATTERY_ODT_MASK												0xc0
 
 #define ATOM_VRAM_MODULE		 ATOM_VRAM_MODULE_V3
 
-typedef struct _ATOM_VRAM_MODULE_V4 {
-	ULONG ulChannelMapCfg;	/*  board dependent parameter: Channel combination */
-	USHORT usModuleSize;	/*  size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE */
-	USHORT usPrivateReserved;	/*  BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */
-	/*  MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) */
-	USHORT usReserved;
-	UCHAR ucExtMemoryID;	/*  An external indicator (by hardcode, callback or pin) to tell what is the current memory module */
-	UCHAR ucMemoryType;	/*  [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now; */
-	UCHAR ucChannelNum;	/*  Number of channels present in this module config */
-	UCHAR ucChannelWidth;	/*  0 - 32 bits; 1 - 64 bits */
-	UCHAR ucDensity;	/*  _8Mx32, _16Mx32, _16Mx16, _32Mx16 */
-	UCHAR ucFlag;		/*  To enable/disable functionalities based on memory type */
-	UCHAR ucMisc;		/*  bit0: 0 - single rank; 1 - dual rank;   bit2: 0 - burstlength 4, 1 - burstlength 8 */
-	UCHAR ucVREFI;		/*  board dependent parameter */
-	UCHAR ucNPL_RT;		/*  board dependent parameter:NPL round trip delay, used for calculate memory timing parameters */
-	UCHAR ucPreamble;	/*  [7:4] Write Preamble, [3:0] Read Preamble */
-	UCHAR ucMemorySize;	/*  BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */
-	/*  Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros */
-	UCHAR ucReserved[3];
+typedef struct _ATOM_VRAM_MODULE_V4
+{
+  ULONG	  ulChannelMapCfg;	                // board dependent parameter: Channel combination
+  USHORT  usModuleSize;                     // size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE
+  USHORT  usPrivateReserved;                // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!!
+                                            // MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS)
+  USHORT  usReserved;
+  UCHAR   ucExtMemoryID;    		            // An external indicator (by hardcode, callback or pin) to tell what is the current memory module
+  UCHAR   ucMemoryType;                     // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now;
+  UCHAR   ucChannelNum;                     // Number of channels present in this module config
+  UCHAR   ucChannelWidth;                   // 0 - 32 bits; 1 - 64 bits
+	UCHAR   ucDensity;                        // _8Mx32, _16Mx32, _16Mx16, _32Mx16
+	UCHAR	  ucFlag;						                // To enable/disable functionalities based on memory type
+	UCHAR	  ucMisc;						                // bit0: 0 - single rank; 1 - dual rank;   bit2: 0 - burstlength 4, 1 - burstlength 8
+  UCHAR		ucVREFI;                          // board dependent parameter
+  UCHAR   ucNPL_RT;                         // board dependent parameter:NPL round trip delay, used for calculate memory timing parameters
+  UCHAR		ucPreamble;                       // [7:4] Write Preamble, [3:0] Read Preamble
+  UCHAR   ucMemorySize;                     // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!!
+                                            // Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros
+  UCHAR   ucReserved[3];
 
-/* compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level */
-	union {
-		USHORT usEMRS2Value;	/*  EMRS2 Value is used for GDDR2 and GDDR4 memory type */
-		USHORT usDDR3_Reserved;
-	};
-	union {
-		USHORT usEMRS3Value;	/*  EMRS3 Value is used for GDDR2 and GDDR4 memory type */
-		USHORT usDDR3_MR3;	/*  Used for DDR3 memory */
-	};
-	UCHAR ucMemoryVenderID;	/*  Predefined, If not predefined, vendor detection table gets executed */
-	UCHAR ucRefreshRateFactor;	/*  [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) */
-	UCHAR ucReserved2[2];
-	ATOM_MEMORY_TIMING_FORMAT asMemTiming[5];	/* Memory Timing block sort from lower clock to higher clock */
-} ATOM_VRAM_MODULE_V4;
+//compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level
+  union{
+    USHORT	usEMRS2Value;                   // EMRS2 Value is used for GDDR2 and GDDR4 memory type
+    USHORT  usDDR3_Reserved;
+  };
+  union{
+    USHORT	usEMRS3Value;                   // EMRS3 Value is used for GDDR2 and GDDR4 memory type
+    USHORT  usDDR3_MR3;                     // Used for DDR3 memory
+  };  
+  UCHAR   ucMemoryVenderID;  		            // Predefined, If not predefined, vendor detection table gets executed
+  UCHAR	  ucRefreshRateFactor;              // [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms)
+  UCHAR   ucReserved2[2];
+  ATOM_MEMORY_TIMING_FORMAT  asMemTiming[5];//Memory Timing block sort from lower clock to higher clock
+}ATOM_VRAM_MODULE_V4;
 
 #define VRAM_MODULE_V4_MISC_RANK_MASK       0x3
 #define VRAM_MODULE_V4_MISC_DUAL_RANK       0x1
@@ -3973,96 +4841,139 @@
 #define VRAM_MODULE_V4_MISC_BL8             0x4
 #define VRAM_MODULE_V4_MISC_DUAL_CS         0x10
 
-typedef struct _ATOM_VRAM_MODULE_V5 {
-	ULONG ulChannelMapCfg;	/*  board dependent parameter: Channel combination */
-	USHORT usModuleSize;	/*  size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE */
-	USHORT usPrivateReserved;	/*  BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */
-	/*  MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) */
-	USHORT usReserved;
-	UCHAR ucExtMemoryID;	/*  An external indicator (by hardcode, callback or pin) to tell what is the current memory module */
-	UCHAR ucMemoryType;	/*  [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now; */
-	UCHAR ucChannelNum;	/*  Number of channels present in this module config */
-	UCHAR ucChannelWidth;	/*  0 - 32 bits; 1 - 64 bits */
-	UCHAR ucDensity;	/*  _8Mx32, _16Mx32, _16Mx16, _32Mx16 */
-	UCHAR ucFlag;		/*  To enable/disable functionalities based on memory type */
-	UCHAR ucMisc;		/*  bit0: 0 - single rank; 1 - dual rank;   bit2: 0 - burstlength 4, 1 - burstlength 8 */
-	UCHAR ucVREFI;		/*  board dependent parameter */
-	UCHAR ucNPL_RT;		/*  board dependent parameter:NPL round trip delay, used for calculate memory timing parameters */
-	UCHAR ucPreamble;	/*  [7:4] Write Preamble, [3:0] Read Preamble */
-	UCHAR ucMemorySize;	/*  BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */
-	/*  Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros */
-	UCHAR ucReserved[3];
+typedef struct _ATOM_VRAM_MODULE_V5
+{
+  ULONG	  ulChannelMapCfg;	                // board dependent parameter: Channel combination
+  USHORT  usModuleSize;                     // size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE
+  USHORT  usPrivateReserved;                // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!!
+                                            // MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS)
+  USHORT  usReserved;
+  UCHAR   ucExtMemoryID;    		            // An external indicator (by hardcode, callback or pin) to tell what is the current memory module
+  UCHAR   ucMemoryType;                     // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now;
+  UCHAR   ucChannelNum;                     // Number of channels present in this module config
+  UCHAR   ucChannelWidth;                   // 0 - 32 bits; 1 - 64 bits
+	UCHAR   ucDensity;                        // _8Mx32, _16Mx32, _16Mx16, _32Mx16
+	UCHAR	  ucFlag;						                // To enable/disable functionalities based on memory type
+	UCHAR	  ucMisc;						                // bit0: 0 - single rank; 1 - dual rank;   bit2: 0 - burstlength 4, 1 - burstlength 8
+  UCHAR		ucVREFI;                          // board dependent parameter
+  UCHAR   ucNPL_RT;                         // board dependent parameter:NPL round trip delay, used for calculate memory timing parameters
+  UCHAR		ucPreamble;                       // [7:4] Write Preamble, [3:0] Read Preamble
+  UCHAR   ucMemorySize;                     // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!!
+                                            // Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros
+  UCHAR   ucReserved[3];
 
-/* compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level */
-	USHORT usEMRS2Value;	/*  EMRS2 Value is used for GDDR2 and GDDR4 memory type */
-	USHORT usEMRS3Value;	/*  EMRS3 Value is used for GDDR2 and GDDR4 memory type */
-	UCHAR ucMemoryVenderID;	/*  Predefined, If not predefined, vendor detection table gets executed */
-	UCHAR ucRefreshRateFactor;	/*  [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) */
-	UCHAR ucFIFODepth;	/*  FIFO depth supposes to be detected during vendor detection, but if we dont do vendor detection we have to hardcode FIFO Depth */
-	UCHAR ucCDR_Bandwidth;	/*  [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth */
-	ATOM_MEMORY_TIMING_FORMAT_V1 asMemTiming[5];	/* Memory Timing block sort from lower clock to higher clock */
-} ATOM_VRAM_MODULE_V5;
+//compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level
+  USHORT	usEMRS2Value;      		            // EMRS2 Value is used for GDDR2 and GDDR4 memory type
+  USHORT	usEMRS3Value;      		            // EMRS3 Value is used for GDDR2 and GDDR4 memory type
+  UCHAR   ucMemoryVenderID;  		            // Predefined, If not predefined, vendor detection table gets executed
+  UCHAR	  ucRefreshRateFactor;              // [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms)
+  UCHAR	  ucFIFODepth;			                // FIFO depth supposes to be detected during vendor detection, but if we dont do vendor detection we have to hardcode FIFO Depth
+  UCHAR   ucCDR_Bandwidth;		   // [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth
+  ATOM_MEMORY_TIMING_FORMAT_V1  asMemTiming[5];//Memory Timing block sort from lower clock to higher clock
+}ATOM_VRAM_MODULE_V5;
 
-typedef struct _ATOM_VRAM_INFO_V2 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR ucNumOfVRAMModule;
-	ATOM_VRAM_MODULE aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE];	/*  just for allocation, real number of blocks is in ucNumOfVRAMModule; */
-} ATOM_VRAM_INFO_V2;
+typedef struct _ATOM_VRAM_MODULE_V6
+{
+  ULONG	  ulChannelMapCfg;	                // board dependent parameter: Channel combination
+  USHORT  usModuleSize;                     // size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE
+  USHORT  usPrivateReserved;                // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!!
+                                            // MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS)
+  USHORT  usReserved;
+  UCHAR   ucExtMemoryID;    		            // An external indicator (by hardcode, callback or pin) to tell what is the current memory module
+  UCHAR   ucMemoryType;                     // [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now;
+  UCHAR   ucChannelNum;                     // Number of channels present in this module config
+  UCHAR   ucChannelWidth;                   // 0 - 32 bits; 1 - 64 bits
+	UCHAR   ucDensity;                        // _8Mx32, _16Mx32, _16Mx16, _32Mx16
+	UCHAR	  ucFlag;						                // To enable/disable functionalities based on memory type
+	UCHAR	  ucMisc;						                // bit0: 0 - single rank; 1 - dual rank;   bit2: 0 - burstlength 4, 1 - burstlength 8
+  UCHAR		ucVREFI;                          // board dependent parameter
+  UCHAR   ucNPL_RT;                         // board dependent parameter:NPL round trip delay, used for calculate memory timing parameters
+  UCHAR		ucPreamble;                       // [7:4] Write Preamble, [3:0] Read Preamble
+  UCHAR   ucMemorySize;                     // BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!!
+                                            // Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros
+  UCHAR   ucReserved[3];
 
-typedef struct _ATOM_VRAM_INFO_V3 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usMemAdjustTblOffset;	/*  offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting */
-	USHORT usMemClkPatchTblOffset;	/*      offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting */
-	USHORT usRerseved;
-	UCHAR aVID_PinsShift[9];	/*  8 bit strap maximum+terminator */
-	UCHAR ucNumOfVRAMModule;
-	ATOM_VRAM_MODULE aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE];	/*  just for allocation, real number of blocks is in ucNumOfVRAMModule; */
-	ATOM_INIT_REG_BLOCK asMemPatch;	/*  for allocation */
-	/*      ATOM_INIT_REG_BLOCK                              aMemAdjust; */
-} ATOM_VRAM_INFO_V3;
+//compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level
+  USHORT	usEMRS2Value;      		            // EMRS2 Value is used for GDDR2 and GDDR4 memory type
+  USHORT	usEMRS3Value;      		            // EMRS3 Value is used for GDDR2 and GDDR4 memory type
+  UCHAR   ucMemoryVenderID;  		            // Predefined, If not predefined, vendor detection table gets executed
+  UCHAR	  ucRefreshRateFactor;              // [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms)
+  UCHAR	  ucFIFODepth;			                // FIFO depth supposes to be detected during vendor detection, but if we dont do vendor detection we have to hardcode FIFO Depth
+  UCHAR   ucCDR_Bandwidth;		   // [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth
+  ATOM_MEMORY_TIMING_FORMAT_V2  asMemTiming[5];//Memory Timing block sort from lower clock to higher clock
+}ATOM_VRAM_MODULE_V6;
+
+
+
+typedef struct _ATOM_VRAM_INFO_V2
+{
+  ATOM_COMMON_TABLE_HEADER   sHeader;
+  UCHAR                      ucNumOfVRAMModule;
+  ATOM_VRAM_MODULE           aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE];      // just for allocation, real number of blocks is in ucNumOfVRAMModule;
+}ATOM_VRAM_INFO_V2;
+
+typedef struct _ATOM_VRAM_INFO_V3
+{
+  ATOM_COMMON_TABLE_HEADER   sHeader;
+	USHORT										 usMemAdjustTblOffset;													 // offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting
+	USHORT										 usMemClkPatchTblOffset;												 //	offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting
+	USHORT										 usRerseved;
+	UCHAR           	         aVID_PinsShift[9];															 // 8 bit strap maximum+terminator
+  UCHAR                      ucNumOfVRAMModule;
+  ATOM_VRAM_MODULE		       aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE];      // just for allocation, real number of blocks is in ucNumOfVRAMModule;
+	ATOM_INIT_REG_BLOCK				 asMemPatch;																		 // for allocation
+																																						 //	ATOM_INIT_REG_BLOCK				 aMemAdjust;
+}ATOM_VRAM_INFO_V3;
 
 #define	ATOM_VRAM_INFO_LAST	     ATOM_VRAM_INFO_V3
 
-typedef struct _ATOM_VRAM_INFO_V4 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usMemAdjustTblOffset;	/*  offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting */
-	USHORT usMemClkPatchTblOffset;	/*      offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting */
-	USHORT usRerseved;
-	UCHAR ucMemDQ7_0ByteRemap;	/*  DQ line byte remap, =0: Memory Data line BYTE0, =1: BYTE1, =2: BYTE2, =3: BYTE3 */
-	ULONG ulMemDQ7_0BitRemap;	/*  each DQ line ( 7~0) use 3bits, like: DQ0=Bit[2:0], DQ1:[5:3], ... DQ7:[23:21] */
-	UCHAR ucReservde[4];
-	UCHAR ucNumOfVRAMModule;
-	ATOM_VRAM_MODULE_V4 aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE];	/*  just for allocation, real number of blocks is in ucNumOfVRAMModule; */
-	ATOM_INIT_REG_BLOCK asMemPatch;	/*  for allocation */
-	/*      ATOM_INIT_REG_BLOCK                              aMemAdjust; */
-} ATOM_VRAM_INFO_V4;
+typedef struct _ATOM_VRAM_INFO_V4
+{
+  ATOM_COMMON_TABLE_HEADER   sHeader;
+	USHORT										 usMemAdjustTblOffset;													 // offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting
+	USHORT										 usMemClkPatchTblOffset;												 //	offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting
+	USHORT										 usRerseved;
+	UCHAR           	         ucMemDQ7_0ByteRemap;													   // DQ line byte remap, =0: Memory Data line BYTE0, =1: BYTE1, =2: BYTE2, =3: BYTE3
+  ULONG                      ulMemDQ7_0BitRemap;                             // each DQ line ( 7~0) use 3bits, like: DQ0=Bit[2:0], DQ1:[5:3], ... DQ7:[23:21]
+  UCHAR                      ucReservde[4]; 
+  UCHAR                      ucNumOfVRAMModule;
+  ATOM_VRAM_MODULE_V4		     aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE];      // just for allocation, real number of blocks is in ucNumOfVRAMModule;
+	ATOM_INIT_REG_BLOCK				 asMemPatch;																		 // for allocation
+																																						 //	ATOM_INIT_REG_BLOCK				 aMemAdjust;
+}ATOM_VRAM_INFO_V4;
 
-typedef struct _ATOM_VRAM_GPIO_DETECTION_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR aVID_PinsShift[9];	/* 8 bit strap maximum+terminator */
-} ATOM_VRAM_GPIO_DETECTION_INFO;
+typedef struct _ATOM_VRAM_GPIO_DETECTION_INFO
+{
+  ATOM_COMMON_TABLE_HEADER   sHeader;
+  UCHAR           	         aVID_PinsShift[9];   //8 bit strap maximum+terminator
+}ATOM_VRAM_GPIO_DETECTION_INFO;
 
-typedef struct _ATOM_MEMORY_TRAINING_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR ucTrainingLoop;
-	UCHAR ucReserved[3];
-	ATOM_INIT_REG_BLOCK asMemTrainingSetting;
-} ATOM_MEMORY_TRAINING_INFO;
 
-typedef struct SW_I2C_CNTL_DATA_PARAMETERS {
-	UCHAR ucControl;
-	UCHAR ucData;
-	UCHAR ucSatus;
-	UCHAR ucTemp;
+typedef struct _ATOM_MEMORY_TRAINING_INFO
+{
+	ATOM_COMMON_TABLE_HEADER   sHeader;
+	UCHAR											 ucTrainingLoop;
+	UCHAR											 ucReserved[3];
+	ATOM_INIT_REG_BLOCK				 asMemTrainingSetting;
+}ATOM_MEMORY_TRAINING_INFO;
+
+
+typedef struct SW_I2C_CNTL_DATA_PARAMETERS
+{
+  UCHAR    ucControl;
+  UCHAR    ucData; 
+  UCHAR    ucSatus; 
+  UCHAR    ucTemp; 
 } SW_I2C_CNTL_DATA_PARAMETERS;
 
 #define SW_I2C_CNTL_DATA_PS_ALLOCATION  SW_I2C_CNTL_DATA_PARAMETERS
 
-typedef struct _SW_I2C_IO_DATA_PARAMETERS {
-	USHORT GPIO_Info;
-	UCHAR ucAct;
-	UCHAR ucData;
-} SW_I2C_IO_DATA_PARAMETERS;
+typedef struct _SW_I2C_IO_DATA_PARAMETERS
+{                               
+  USHORT   GPIO_Info;
+  UCHAR    ucAct; 
+  UCHAR    ucData; 
+ } SW_I2C_IO_DATA_PARAMETERS;
 
 #define SW_I2C_IO_DATA_PS_ALLOCATION  SW_I2C_IO_DATA_PARAMETERS
 
@@ -4087,127 +4998,136 @@
 #define SW_I2C_CNTL_CLOSE     5
 #define SW_I2C_CNTL_WRITE1BIT 6
 
-/* ==============================VESA definition Portion=============================== */
+//==============================VESA definition Portion===============================
 #define VESA_OEM_PRODUCT_REV			            '01.00'
-#define VESA_MODE_ATTRIBUTE_MODE_SUPPORT	     0xBB	/* refer to VBE spec p.32, no TTY support */
+#define VESA_MODE_ATTRIBUTE_MODE_SUPPORT	     0xBB	//refer to VBE spec p.32, no TTY support
 #define VESA_MODE_WIN_ATTRIBUTE						     7
 #define VESA_WIN_SIZE											     64
 
-typedef struct _PTR_32_BIT_STRUCTURE {
-	USHORT Offset16;
-	USHORT Segment16;
+typedef struct _PTR_32_BIT_STRUCTURE
+{
+	USHORT	Offset16;			
+	USHORT	Segment16;				
 } PTR_32_BIT_STRUCTURE;
 
-typedef union _PTR_32_BIT_UNION {
-	PTR_32_BIT_STRUCTURE SegmentOffset;
-	ULONG Ptr32_Bit;
+typedef union _PTR_32_BIT_UNION
+{
+	PTR_32_BIT_STRUCTURE	SegmentOffset;
+	ULONG					        Ptr32_Bit;
 } PTR_32_BIT_UNION;
 
-typedef struct _VBE_1_2_INFO_BLOCK_UPDATABLE {
-	UCHAR VbeSignature[4];
-	USHORT VbeVersion;
-	PTR_32_BIT_UNION OemStringPtr;
-	UCHAR Capabilities[4];
-	PTR_32_BIT_UNION VideoModePtr;
-	USHORT TotalMemory;
+typedef struct _VBE_1_2_INFO_BLOCK_UPDATABLE
+{
+	UCHAR				      VbeSignature[4];
+	USHORT				    VbeVersion;
+	PTR_32_BIT_UNION	OemStringPtr;
+	UCHAR				      Capabilities[4];
+	PTR_32_BIT_UNION	VideoModePtr;
+	USHORT				    TotalMemory;
 } VBE_1_2_INFO_BLOCK_UPDATABLE;
 
-typedef struct _VBE_2_0_INFO_BLOCK_UPDATABLE {
-	VBE_1_2_INFO_BLOCK_UPDATABLE CommonBlock;
-	USHORT OemSoftRev;
-	PTR_32_BIT_UNION OemVendorNamePtr;
-	PTR_32_BIT_UNION OemProductNamePtr;
-	PTR_32_BIT_UNION OemProductRevPtr;
+
+typedef struct _VBE_2_0_INFO_BLOCK_UPDATABLE
+{
+	VBE_1_2_INFO_BLOCK_UPDATABLE	CommonBlock;
+	USHORT							    OemSoftRev;
+	PTR_32_BIT_UNION				OemVendorNamePtr;
+	PTR_32_BIT_UNION				OemProductNamePtr;
+	PTR_32_BIT_UNION				OemProductRevPtr;
 } VBE_2_0_INFO_BLOCK_UPDATABLE;
 
-typedef union _VBE_VERSION_UNION {
-	VBE_2_0_INFO_BLOCK_UPDATABLE VBE_2_0_InfoBlock;
-	VBE_1_2_INFO_BLOCK_UPDATABLE VBE_1_2_InfoBlock;
+typedef union _VBE_VERSION_UNION
+{
+	VBE_2_0_INFO_BLOCK_UPDATABLE	VBE_2_0_InfoBlock;
+	VBE_1_2_INFO_BLOCK_UPDATABLE	VBE_1_2_InfoBlock;
 } VBE_VERSION_UNION;
 
-typedef struct _VBE_INFO_BLOCK {
-	VBE_VERSION_UNION UpdatableVBE_Info;
-	UCHAR Reserved[222];
-	UCHAR OemData[256];
+typedef struct _VBE_INFO_BLOCK
+{
+	VBE_VERSION_UNION			UpdatableVBE_Info;
+	UCHAR						      Reserved[222];
+	UCHAR						      OemData[256];
 } VBE_INFO_BLOCK;
 
-typedef struct _VBE_FP_INFO {
-	USHORT HSize;
-	USHORT VSize;
-	USHORT FPType;
-	UCHAR RedBPP;
-	UCHAR GreenBPP;
-	UCHAR BlueBPP;
-	UCHAR ReservedBPP;
-	ULONG RsvdOffScrnMemSize;
-	ULONG RsvdOffScrnMEmPtr;
-	UCHAR Reserved[14];
+typedef struct _VBE_FP_INFO
+{
+  USHORT	HSize;
+	USHORT	VSize;
+	USHORT	FPType;
+	UCHAR		RedBPP;
+	UCHAR		GreenBPP;
+	UCHAR		BlueBPP;
+	UCHAR		ReservedBPP;
+	ULONG		RsvdOffScrnMemSize;
+	ULONG		RsvdOffScrnMEmPtr;
+	UCHAR		Reserved[14];
 } VBE_FP_INFO;
 
-typedef struct _VESA_MODE_INFO_BLOCK {
-/*  Mandatory information for all VBE revisions */
-	USHORT ModeAttributes;	/*                  dw      ?       ; mode attributes */
-	UCHAR WinAAttributes;	/*                    db      ?       ; window A attributes */
-	UCHAR WinBAttributes;	/*                    db      ?       ; window B attributes */
-	USHORT WinGranularity;	/*                    dw      ?       ; window granularity */
-	USHORT WinSize;		/*                    dw      ?       ; window size */
-	USHORT WinASegment;	/*                    dw      ?       ; window A start segment */
-	USHORT WinBSegment;	/*                    dw      ?       ; window B start segment */
-	ULONG WinFuncPtr;	/*                    dd      ?       ; real mode pointer to window function */
-	USHORT BytesPerScanLine;	/*                    dw      ?       ; bytes per scan line */
+typedef struct _VESA_MODE_INFO_BLOCK
+{
+// Mandatory information for all VBE revisions
+  USHORT    ModeAttributes;  //			dw	?	; mode attributes
+	UCHAR     WinAAttributes;  //			db	?	; window A attributes
+	UCHAR     WinBAttributes;  //			db	?	; window B attributes
+	USHORT    WinGranularity;  //			dw	?	; window granularity
+	USHORT    WinSize;         //			dw	?	; window size
+	USHORT    WinASegment;     //			dw	?	; window A start segment
+	USHORT    WinBSegment;     //			dw	?	; window B start segment
+	ULONG     WinFuncPtr;      //			dd	?	; real mode pointer to window function
+	USHORT    BytesPerScanLine;//			dw	?	; bytes per scan line
 
-/* ; Mandatory information for VBE 1.2 and above */
-	USHORT XResolution;	/*                         dw      ?       ; horizontal resolution in pixels or characters */
-	USHORT YResolution;	/*                   dw      ?       ; vertical resolution in pixels or characters */
-	UCHAR XCharSize;	/*                   db      ?       ; character cell width in pixels */
-	UCHAR YCharSize;	/*                   db      ?       ; character cell height in pixels */
-	UCHAR NumberOfPlanes;	/*                   db      ?       ; number of memory planes */
-	UCHAR BitsPerPixel;	/*                   db      ?       ; bits per pixel */
-	UCHAR NumberOfBanks;	/*                   db      ?       ; number of banks */
-	UCHAR MemoryModel;	/*                   db      ?       ; memory model type */
-	UCHAR BankSize;		/*                   db      ?       ; bank size in KB */
-	UCHAR NumberOfImagePages;	/*            db    ?       ; number of images */
-	UCHAR ReservedForPageFunction;	/* db  1       ; reserved for page function */
+//; Mandatory information for VBE 1.2 and above
+  USHORT    XResolution;      //			dw	?	; horizontal resolution in pixels or characters
+	USHORT    YResolution;      //			dw	?	; vertical resolution in pixels or characters
+	UCHAR     XCharSize;        //			db	?	; character cell width in pixels
+	UCHAR     YCharSize;        //			db	?	; character cell height in pixels
+	UCHAR     NumberOfPlanes;   //			db	?	; number of memory planes
+	UCHAR     BitsPerPixel;     //			db	?	; bits per pixel
+	UCHAR     NumberOfBanks;    //			db	?	; number of banks
+	UCHAR     MemoryModel;      //			db	?	; memory model type
+	UCHAR     BankSize;         //			db	?	; bank size in KB
+	UCHAR     NumberOfImagePages;//		  db	?	; number of images
+	UCHAR     ReservedForPageFunction;//db	1	; reserved for page function
 
-/* ; Direct Color fields(required for direct/6 and YUV/7 memory models) */
-	UCHAR RedMaskSize;	/*           db      ?       ; size of direct color red mask in bits */
-	UCHAR RedFieldPosition;	/*           db      ?       ; bit position of lsb of red mask */
-	UCHAR GreenMaskSize;	/*           db      ?       ; size of direct color green mask in bits */
-	UCHAR GreenFieldPosition;	/*           db      ?       ; bit position of lsb of green mask */
-	UCHAR BlueMaskSize;	/*           db      ?       ; size of direct color blue mask in bits */
-	UCHAR BlueFieldPosition;	/*           db      ?       ; bit position of lsb of blue mask */
-	UCHAR RsvdMaskSize;	/*           db      ?       ; size of direct color reserved mask in bits */
-	UCHAR RsvdFieldPosition;	/*           db      ?       ; bit position of lsb of reserved mask */
-	UCHAR DirectColorModeInfo;	/*           db      ?       ; direct color mode attributes */
+//; Direct Color fields(required for direct/6 and YUV/7 memory models)
+	UCHAR			RedMaskSize;        //		db	?	; size of direct color red mask in bits
+	UCHAR			RedFieldPosition;   //		db	?	; bit position of lsb of red mask
+	UCHAR			GreenMaskSize;      //		db	?	; size of direct color green mask in bits
+	UCHAR			GreenFieldPosition; //		db	?	; bit position of lsb of green mask
+	UCHAR			BlueMaskSize;       //		db	?	; size of direct color blue mask in bits
+	UCHAR			BlueFieldPosition;  //		db	?	; bit position of lsb of blue mask
+	UCHAR			RsvdMaskSize;       //		db	?	; size of direct color reserved mask in bits
+	UCHAR			RsvdFieldPosition;  //		db	?	; bit position of lsb of reserved mask
+	UCHAR			DirectColorModeInfo;//		db	?	; direct color mode attributes
 
-/* ; Mandatory information for VBE 2.0 and above */
-	ULONG PhysBasePtr;	/*           dd      ?       ; physical address for flat memory frame buffer */
-	ULONG Reserved_1;	/*           dd      0       ; reserved - always set to 0 */
-	USHORT Reserved_2;	/*     dw    0       ; reserved - always set to 0 */
+//; Mandatory information for VBE 2.0 and above
+	ULONG			PhysBasePtr;        //		dd	?	; physical address for flat memory frame buffer
+	ULONG			Reserved_1;         //		dd	0	; reserved - always set to 0
+	USHORT		Reserved_2;         //	  dw	0	; reserved - always set to 0
 
-/* ; Mandatory information for VBE 3.0 and above */
-	USHORT LinBytesPerScanLine;	/*         dw      ?       ; bytes per scan line for linear modes */
-	UCHAR BnkNumberOfImagePages;	/*         db      ?       ; number of images for banked modes */
-	UCHAR LinNumberOfImagPages;	/*         db      ?       ; number of images for linear modes */
-	UCHAR LinRedMaskSize;	/*         db      ?       ; size of direct color red mask(linear modes) */
-	UCHAR LinRedFieldPosition;	/*         db      ?       ; bit position of lsb of red mask(linear modes) */
-	UCHAR LinGreenMaskSize;	/*         db      ?       ; size of direct color green mask(linear modes) */
-	UCHAR LinGreenFieldPosition;	/*         db      ?       ; bit position of lsb of green mask(linear modes) */
-	UCHAR LinBlueMaskSize;	/*         db      ?       ; size of direct color blue mask(linear modes) */
-	UCHAR LinBlueFieldPosition;	/*         db      ?       ; bit position of lsb of blue mask(linear modes) */
-	UCHAR LinRsvdMaskSize;	/*         db      ?       ; size of direct color reserved mask(linear modes) */
-	UCHAR LinRsvdFieldPosition;	/*         db      ?       ; bit position of lsb of reserved mask(linear modes) */
-	ULONG MaxPixelClock;	/*         dd      ?       ; maximum pixel clock(in Hz) for graphics mode */
-	UCHAR Reserved;		/*         db      190 dup (0) */
+//; Mandatory information for VBE 3.0 and above
+	USHORT		LinBytesPerScanLine;  //	dw	?	; bytes per scan line for linear modes
+	UCHAR			BnkNumberOfImagePages;//	db	?	; number of images for banked modes
+	UCHAR			LinNumberOfImagPages; //	db	?	; number of images for linear modes
+	UCHAR			LinRedMaskSize;       //	db	?	; size of direct color red mask(linear modes)
+	UCHAR			LinRedFieldPosition;  //	db	?	; bit position of lsb of red mask(linear modes)
+	UCHAR			LinGreenMaskSize;     //	db	?	; size of direct color green mask(linear modes)
+	UCHAR			LinGreenFieldPosition;//	db	?	; bit position of lsb of green mask(linear modes)
+	UCHAR			LinBlueMaskSize;      //	db	?	; size of direct color blue mask(linear modes)
+	UCHAR			LinBlueFieldPosition; //	db	?	; bit position of lsb of blue mask(linear modes)
+	UCHAR			LinRsvdMaskSize;      //	db	?	; size of direct color reserved mask(linear modes)
+	UCHAR			LinRsvdFieldPosition; //	db	?	; bit position of lsb of reserved mask(linear modes)
+	ULONG			MaxPixelClock;        //	dd	?	; maximum pixel clock(in Hz) for graphics mode
+	UCHAR			Reserved;             //	db	190 dup (0)
 } VESA_MODE_INFO_BLOCK;
 
-/*  BIOS function CALLS */
-#define ATOM_BIOS_EXTENDED_FUNCTION_CODE        0xA0	/*  ATI Extended Function code */
+// BIOS function CALLS
+#define ATOM_BIOS_EXTENDED_FUNCTION_CODE        0xA0	        // ATI Extended Function code
 #define ATOM_BIOS_FUNCTION_COP_MODE             0x00
 #define ATOM_BIOS_FUNCTION_SHORT_QUERY1         0x04
 #define ATOM_BIOS_FUNCTION_SHORT_QUERY2         0x05
 #define ATOM_BIOS_FUNCTION_SHORT_QUERY3         0x06
-#define ATOM_BIOS_FUNCTION_GET_DDC              0x0B
+#define ATOM_BIOS_FUNCTION_GET_DDC              0x0B   
 #define ATOM_BIOS_FUNCTION_ASIC_DSTATE          0x0E
 #define ATOM_BIOS_FUNCTION_DEBUG_PLAY           0x0F
 #define ATOM_BIOS_FUNCTION_STV_STD              0x16
@@ -4217,100 +5137,135 @@
 #define ATOM_BIOS_FUNCTION_PANEL_CONTROL        0x82
 #define ATOM_BIOS_FUNCTION_OLD_DEVICE_DET       0x83
 #define ATOM_BIOS_FUNCTION_OLD_DEVICE_SWITCH    0x84
-#define ATOM_BIOS_FUNCTION_HW_ICON              0x8A
+#define ATOM_BIOS_FUNCTION_HW_ICON              0x8A 
 #define ATOM_BIOS_FUNCTION_SET_CMOS             0x8B
-#define SUB_FUNCTION_UPDATE_DISPLAY_INFO        0x8000	/*  Sub function 80 */
-#define SUB_FUNCTION_UPDATE_EXPANSION_INFO      0x8100	/*  Sub function 80 */
+#define SUB_FUNCTION_UPDATE_DISPLAY_INFO        0x8000          // Sub function 80
+#define SUB_FUNCTION_UPDATE_EXPANSION_INFO      0x8100          // Sub function 80
 
 #define ATOM_BIOS_FUNCTION_DISPLAY_INFO         0x8D
 #define ATOM_BIOS_FUNCTION_DEVICE_ON_OFF        0x8E
-#define ATOM_BIOS_FUNCTION_VIDEO_STATE          0x8F
-#define ATOM_SUB_FUNCTION_GET_CRITICAL_STATE    0x0300	/*  Sub function 03 */
-#define ATOM_SUB_FUNCTION_GET_LIDSTATE          0x0700	/*  Sub function 7 */
-#define ATOM_SUB_FUNCTION_THERMAL_STATE_NOTICE  0x1400	/*  Notify caller the current thermal state */
-#define ATOM_SUB_FUNCTION_CRITICAL_STATE_NOTICE 0x8300	/*  Notify caller the current critical state */
-#define ATOM_SUB_FUNCTION_SET_LIDSTATE          0x8500	/*  Sub function 85 */
-#define ATOM_SUB_FUNCTION_GET_REQ_DISPLAY_FROM_SBIOS_MODE 0x8900	/*  Sub function 89 */
-#define ATOM_SUB_FUNCTION_INFORM_ADC_SUPPORT    0x9400	/*  Notify caller that ADC is supported */
+#define ATOM_BIOS_FUNCTION_VIDEO_STATE          0x8F 
+#define ATOM_SUB_FUNCTION_GET_CRITICAL_STATE    0x0300          // Sub function 03  
+#define ATOM_SUB_FUNCTION_GET_LIDSTATE          0x0700          // Sub function 7
+#define ATOM_SUB_FUNCTION_THERMAL_STATE_NOTICE  0x1400          // Notify caller the current thermal state
+#define ATOM_SUB_FUNCTION_CRITICAL_STATE_NOTICE 0x8300          // Notify caller the current critical state
+#define ATOM_SUB_FUNCTION_SET_LIDSTATE          0x8500          // Sub function 85
+#define ATOM_SUB_FUNCTION_GET_REQ_DISPLAY_FROM_SBIOS_MODE 0x8900// Sub function 89
+#define ATOM_SUB_FUNCTION_INFORM_ADC_SUPPORT    0x9400          // Notify caller that ADC is supported
+     
 
-#define ATOM_BIOS_FUNCTION_VESA_DPMS            0x4F10	/*  Set DPMS */
-#define ATOM_SUB_FUNCTION_SET_DPMS              0x0001	/*  BL: Sub function 01 */
-#define ATOM_SUB_FUNCTION_GET_DPMS              0x0002	/*  BL: Sub function 02 */
-#define ATOM_PARAMETER_VESA_DPMS_ON             0x0000	/*  BH Parameter for DPMS ON. */
-#define ATOM_PARAMETER_VESA_DPMS_STANDBY        0x0100	/*  BH Parameter for DPMS STANDBY */
-#define ATOM_PARAMETER_VESA_DPMS_SUSPEND        0x0200	/*  BH Parameter for DPMS SUSPEND */
-#define ATOM_PARAMETER_VESA_DPMS_OFF            0x0400	/*  BH Parameter for DPMS OFF */
-#define ATOM_PARAMETER_VESA_DPMS_REDUCE_ON      0x0800	/*  BH Parameter for DPMS REDUCE ON (NOT SUPPORTED) */
+#define ATOM_BIOS_FUNCTION_VESA_DPMS            0x4F10          // Set DPMS 
+#define ATOM_SUB_FUNCTION_SET_DPMS              0x0001          // BL: Sub function 01 
+#define ATOM_SUB_FUNCTION_GET_DPMS              0x0002          // BL: Sub function 02 
+#define ATOM_PARAMETER_VESA_DPMS_ON             0x0000          // BH Parameter for DPMS ON.  
+#define ATOM_PARAMETER_VESA_DPMS_STANDBY        0x0100          // BH Parameter for DPMS STANDBY  
+#define ATOM_PARAMETER_VESA_DPMS_SUSPEND        0x0200          // BH Parameter for DPMS SUSPEND
+#define ATOM_PARAMETER_VESA_DPMS_OFF            0x0400          // BH Parameter for DPMS OFF
+#define ATOM_PARAMETER_VESA_DPMS_REDUCE_ON      0x0800          // BH Parameter for DPMS REDUCE ON (NOT SUPPORTED)
 
 #define ATOM_BIOS_RETURN_CODE_MASK              0x0000FF00L
 #define ATOM_BIOS_REG_HIGH_MASK                 0x0000FF00L
 #define ATOM_BIOS_REG_LOW_MASK                  0x000000FFL
 
-/*  structure used for VBIOS only */
+// structure used for VBIOS only
 
-/* DispOutInfoTable */
-typedef struct _ASIC_TRANSMITTER_INFO {
+//DispOutInfoTable
+typedef struct _ASIC_TRANSMITTER_INFO
+{
 	USHORT usTransmitterObjId;
 	USHORT usSupportDevice;
-	UCHAR ucTransmitterCmdTblId;
-	UCHAR ucConfig;
-	UCHAR ucEncoderID;	/* available 1st encoder ( default ) */
-	UCHAR ucOptionEncoderID;	/* available 2nd encoder ( optional ) */
-	UCHAR uc2ndEncoderID;
-	UCHAR ucReserved;
-} ASIC_TRANSMITTER_INFO;
+  UCHAR  ucTransmitterCmdTblId;
+	UCHAR  ucConfig;
+	UCHAR  ucEncoderID;					 //available 1st encoder ( default )
+	UCHAR  ucOptionEncoderID;    //available 2nd encoder ( optional )
+	UCHAR  uc2ndEncoderID;
+	UCHAR  ucReserved;
+}ASIC_TRANSMITTER_INFO;
 
-typedef struct _ASIC_ENCODER_INFO {
+typedef struct _ASIC_ENCODER_INFO
+{
 	UCHAR ucEncoderID;
 	UCHAR ucEncoderConfig;
-	USHORT usEncoderCmdTblId;
-} ASIC_ENCODER_INFO;
+  USHORT usEncoderCmdTblId;
+}ASIC_ENCODER_INFO;
 
-typedef struct _ATOM_DISP_OUT_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
+typedef struct _ATOM_DISP_OUT_INFO
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
 	USHORT ptrTransmitterInfo;
 	USHORT ptrEncoderInfo;
-	ASIC_TRANSMITTER_INFO asTransmitterInfo[1];
-	ASIC_ENCODER_INFO asEncoderInfo[1];
-} ATOM_DISP_OUT_INFO;
+	ASIC_TRANSMITTER_INFO  asTransmitterInfo[1];
+	ASIC_ENCODER_INFO      asEncoderInfo[1];
+}ATOM_DISP_OUT_INFO;
 
-/*  DispDevicePriorityInfo */
-typedef struct _ATOM_DISPLAY_DEVICE_PRIORITY_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
+typedef struct _ATOM_DISP_OUT_INFO_V2
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+	USHORT ptrTransmitterInfo;
+	USHORT ptrEncoderInfo;
+  USHORT ptrMainCallParserFar;                  // direct address of main parser call in VBIOS binary. 
+	ASIC_TRANSMITTER_INFO  asTransmitterInfo[1];
+	ASIC_ENCODER_INFO      asEncoderInfo[1];
+}ATOM_DISP_OUT_INFO_V2;
+
+// DispDevicePriorityInfo
+typedef struct _ATOM_DISPLAY_DEVICE_PRIORITY_INFO
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
 	USHORT asDevicePriority[16];
-} ATOM_DISPLAY_DEVICE_PRIORITY_INFO;
+}ATOM_DISPLAY_DEVICE_PRIORITY_INFO;
 
-/* ProcessAuxChannelTransactionTable */
-typedef struct _PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS {
-	USHORT lpAuxRequest;
-	USHORT lpDataOut;
-	UCHAR ucChannelID;
-	union {
-		UCHAR ucReplyStatus;
-		UCHAR ucDelay;
+//ProcessAuxChannelTransactionTable
+typedef struct _PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS
+{
+	USHORT	lpAuxRequest;
+	USHORT  lpDataOut;
+	UCHAR		ucChannelID;
+	union
+	{
+  UCHAR   ucReplyStatus;
+	UCHAR   ucDelay;
 	};
-	UCHAR ucDataOutLen;
-	UCHAR ucReserved;
-} PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS;
+  UCHAR   ucDataOutLen;
+	UCHAR   ucReserved;
+}PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS;
+
+//ProcessAuxChannelTransactionTable
+typedef struct _PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2
+{
+	USHORT	lpAuxRequest;
+	USHORT  lpDataOut;
+	UCHAR		ucChannelID;
+	union
+	{
+  UCHAR   ucReplyStatus;
+	UCHAR   ucDelay;
+	};
+  UCHAR   ucDataOutLen;
+	UCHAR   ucHPD_ID;                                       //=0: HPD1, =1: HPD2, =2: HPD3, =3: HPD4, =4: HPD5, =5: HPD6
+}PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2;
 
 #define PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION			PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS
 
-/* GetSinkType */
+//GetSinkType
 
-typedef struct _DP_ENCODER_SERVICE_PARAMETERS {
+typedef struct _DP_ENCODER_SERVICE_PARAMETERS
+{
 	USHORT ucLinkClock;
-	union {
-		UCHAR ucConfig;	/*  for DP training command */
-		UCHAR ucI2cId;	/*  use for GET_SINK_TYPE command */
+	union 
+	{
+	UCHAR ucConfig;				// for DP training command
+	UCHAR ucI2cId;				// use for GET_SINK_TYPE command
 	};
 	UCHAR ucAction;
 	UCHAR ucStatus;
 	UCHAR ucLaneNum;
 	UCHAR ucReserved[2];
-} DP_ENCODER_SERVICE_PARAMETERS;
+}DP_ENCODER_SERVICE_PARAMETERS;
 
-/*  ucAction */
+// ucAction
 #define ATOM_DP_ACTION_GET_SINK_TYPE							0x01
+/* obselete */
 #define ATOM_DP_ACTION_TRAINING_START							0x02
 #define ATOM_DP_ACTION_TRAINING_COMPLETE					0x03
 #define ATOM_DP_ACTION_TRAINING_PATTERN_SEL				0x04
@@ -4318,7 +5273,7 @@
 #define ATOM_DP_ACTION_GET_VSWING_PREEMP					0x06
 #define ATOM_DP_ACTION_BLANKING                   0x07
 
-/*  ucConfig */
+// ucConfig
 #define ATOM_DP_CONFIG_ENCODER_SEL_MASK						0x03
 #define ATOM_DP_CONFIG_DIG1_ENCODER								0x00
 #define ATOM_DP_CONFIG_DIG2_ENCODER								0x01
@@ -4326,14 +5281,14 @@
 #define ATOM_DP_CONFIG_LINK_SEL_MASK							0x04
 #define ATOM_DP_CONFIG_LINK_A											0x00
 #define ATOM_DP_CONFIG_LINK_B											0x04
-
+/* /obselete */
 #define DP_ENCODER_SERVICE_PS_ALLOCATION				WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS
 
-/*  DP_TRAINING_TABLE */
-#define DPCD_SET_LINKRATE_LANENUM_PATTERN1_TBL_ADDR				ATOM_DP_TRAINING_TBL_ADDR
+// DP_TRAINING_TABLE
+#define DPCD_SET_LINKRATE_LANENUM_PATTERN1_TBL_ADDR				ATOM_DP_TRAINING_TBL_ADDR		
 #define DPCD_SET_SS_CNTL_TBL_ADDR													(ATOM_DP_TRAINING_TBL_ADDR + 8 )
-#define DPCD_SET_LANE_VSWING_PREEMP_TBL_ADDR							(ATOM_DP_TRAINING_TBL_ADDR + 16)
-#define DPCD_SET_TRAINING_PATTERN0_TBL_ADDR								(ATOM_DP_TRAINING_TBL_ADDR + 24)
+#define DPCD_SET_LANE_VSWING_PREEMP_TBL_ADDR							(ATOM_DP_TRAINING_TBL_ADDR + 16 )
+#define DPCD_SET_TRAINING_PATTERN0_TBL_ADDR								(ATOM_DP_TRAINING_TBL_ADDR + 24 )
 #define DPCD_SET_TRAINING_PATTERN2_TBL_ADDR								(ATOM_DP_TRAINING_TBL_ADDR + 32)
 #define DPCD_GET_LINKRATE_LANENUM_SS_TBL_ADDR							(ATOM_DP_TRAINING_TBL_ADDR + 40)
 #define	DPCD_GET_LANE_STATUS_ADJUST_TBL_ADDR							(ATOM_DP_TRAINING_TBL_ADDR + 48)
@@ -4341,183 +5296,241 @@
 #define DP_I2C_AUX_DDC_WRITE_TBL_ADDR											(ATOM_DP_TRAINING_TBL_ADDR + 64)
 #define DP_I2C_AUX_DDC_READ_START_TBL_ADDR								(ATOM_DP_TRAINING_TBL_ADDR + 72)
 #define DP_I2C_AUX_DDC_READ_TBL_ADDR											(ATOM_DP_TRAINING_TBL_ADDR + 76)
-#define DP_I2C_AUX_DDC_READ_END_TBL_ADDR									(ATOM_DP_TRAINING_TBL_ADDR + 80)
+#define DP_I2C_AUX_DDC_WRITE_END_TBL_ADDR                 (ATOM_DP_TRAINING_TBL_ADDR + 80) 
+#define DP_I2C_AUX_DDC_READ_END_TBL_ADDR									(ATOM_DP_TRAINING_TBL_ADDR + 84)
 
-typedef struct _PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS {
-	UCHAR ucI2CSpeed;
-	union {
-		UCHAR ucRegIndex;
-		UCHAR ucStatus;
+typedef struct _PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS
+{
+	UCHAR   ucI2CSpeed;
+ 	union
+	{
+   UCHAR ucRegIndex;
+   UCHAR ucStatus;
 	};
-	USHORT lpI2CDataOut;
-	UCHAR ucFlag;
-	UCHAR ucTransBytes;
-	UCHAR ucSlaveAddr;
-	UCHAR ucLineNumber;
-} PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS;
+	USHORT  lpI2CDataOut;
+  UCHAR   ucFlag;               
+  UCHAR   ucTransBytes;
+  UCHAR   ucSlaveAddr;
+  UCHAR   ucLineNumber;
+}PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS;
 
 #define PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION       PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS
 
-/* ucFlag */
+//ucFlag
 #define HW_I2C_WRITE        1
 #define HW_I2C_READ         0
+#define I2C_2BYTE_ADDR      0x02
 
-/****************************************************************************/
-/* Portion VI: Definitinos being oboselete */
+typedef struct _SET_HWBLOCK_INSTANCE_PARAMETER_V2
+{
+   UCHAR ucHWBlkInst;                // HW block instance, 0, 1, 2, ...
+   UCHAR ucReserved[3]; 
+}SET_HWBLOCK_INSTANCE_PARAMETER_V2;
+
+#define HWBLKINST_INSTANCE_MASK       0x07
+#define HWBLKINST_HWBLK_MASK          0xF0
+#define HWBLKINST_HWBLK_SHIFT         0x04
+
+//ucHWBlock
+#define SELECT_DISP_ENGINE            0
+#define SELECT_DISP_PLL               1
+#define SELECT_DCIO_UNIPHY_LINK0      2
+#define SELECT_DCIO_UNIPHY_LINK1      3
+#define SELECT_DCIO_IMPCAL            4
+#define SELECT_DCIO_DIG               6
+#define SELECT_CRTC_PIXEL_RATE        7
+
+/****************************************************************************/	
+//Portion VI: Definitinos for vbios MC scratch registers that driver used
 /****************************************************************************/
 
-/* ========================================================================================== */
-/* Remove the definitions below when driver is ready! */
-typedef struct _ATOM_DAC_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usMaxFrequency;	/*  in 10kHz unit */
-	USHORT usReserved;
-} ATOM_DAC_INFO;
+#define MC_MISC0__MEMORY_TYPE_MASK    0xF0000000
+#define MC_MISC0__MEMORY_TYPE__GDDR1  0x10000000
+#define MC_MISC0__MEMORY_TYPE__DDR2   0x20000000
+#define MC_MISC0__MEMORY_TYPE__GDDR3  0x30000000
+#define MC_MISC0__MEMORY_TYPE__GDDR4  0x40000000
+#define MC_MISC0__MEMORY_TYPE__GDDR5  0x50000000
+#define MC_MISC0__MEMORY_TYPE__DDR3   0xB0000000
 
-typedef struct _COMPASSIONATE_DATA {
-	ATOM_COMMON_TABLE_HEADER sHeader;
+/****************************************************************************/	
+//Portion VI: Definitinos being oboselete
+/****************************************************************************/
 
-	/* ==============================  DAC1 portion */
-	UCHAR ucDAC1_BG_Adjustment;
-	UCHAR ucDAC1_DAC_Adjustment;
-	USHORT usDAC1_FORCE_Data;
-	/* ==============================  DAC2 portion */
-	UCHAR ucDAC2_CRT2_BG_Adjustment;
-	UCHAR ucDAC2_CRT2_DAC_Adjustment;
-	USHORT usDAC2_CRT2_FORCE_Data;
-	USHORT usDAC2_CRT2_MUX_RegisterIndex;
-	UCHAR ucDAC2_CRT2_MUX_RegisterInfo;	/* Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low */
-	UCHAR ucDAC2_NTSC_BG_Adjustment;
-	UCHAR ucDAC2_NTSC_DAC_Adjustment;
-	USHORT usDAC2_TV1_FORCE_Data;
-	USHORT usDAC2_TV1_MUX_RegisterIndex;
-	UCHAR ucDAC2_TV1_MUX_RegisterInfo;	/* Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low */
-	UCHAR ucDAC2_CV_BG_Adjustment;
-	UCHAR ucDAC2_CV_DAC_Adjustment;
-	USHORT usDAC2_CV_FORCE_Data;
-	USHORT usDAC2_CV_MUX_RegisterIndex;
-	UCHAR ucDAC2_CV_MUX_RegisterInfo;	/* Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low */
-	UCHAR ucDAC2_PAL_BG_Adjustment;
-	UCHAR ucDAC2_PAL_DAC_Adjustment;
-	USHORT usDAC2_TV2_FORCE_Data;
-} COMPASSIONATE_DATA;
+//==========================================================================================
+//Remove the definitions below when driver is ready!
+typedef struct _ATOM_DAC_INFO
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  USHORT                   usMaxFrequency;      // in 10kHz unit
+  USHORT                   usReserved;
+}ATOM_DAC_INFO;
+
+
+typedef struct  _COMPASSIONATE_DATA           
+{
+  ATOM_COMMON_TABLE_HEADER sHeader; 
+
+  //==============================  DAC1 portion
+  UCHAR   ucDAC1_BG_Adjustment;
+  UCHAR   ucDAC1_DAC_Adjustment;
+  USHORT  usDAC1_FORCE_Data;
+  //==============================  DAC2 portion
+  UCHAR   ucDAC2_CRT2_BG_Adjustment;
+  UCHAR   ucDAC2_CRT2_DAC_Adjustment;
+  USHORT  usDAC2_CRT2_FORCE_Data;
+  USHORT  usDAC2_CRT2_MUX_RegisterIndex;
+  UCHAR   ucDAC2_CRT2_MUX_RegisterInfo;     //Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low
+  UCHAR   ucDAC2_NTSC_BG_Adjustment;
+  UCHAR   ucDAC2_NTSC_DAC_Adjustment;
+  USHORT  usDAC2_TV1_FORCE_Data;
+  USHORT  usDAC2_TV1_MUX_RegisterIndex;
+  UCHAR   ucDAC2_TV1_MUX_RegisterInfo;      //Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low
+  UCHAR   ucDAC2_CV_BG_Adjustment;
+  UCHAR   ucDAC2_CV_DAC_Adjustment;
+  USHORT  usDAC2_CV_FORCE_Data;
+  USHORT  usDAC2_CV_MUX_RegisterIndex;
+  UCHAR   ucDAC2_CV_MUX_RegisterInfo;       //Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low
+  UCHAR   ucDAC2_PAL_BG_Adjustment;
+  UCHAR   ucDAC2_PAL_DAC_Adjustment;
+  USHORT  usDAC2_TV2_FORCE_Data;
+}COMPASSIONATE_DATA;
 
 /****************************Supported Device Info Table Definitions**********************/
-/*   ucConnectInfo: */
-/*     [7:4] - connector type */
-/*       = 1   - VGA connector */
-/*       = 2   - DVI-I */
-/*       = 3   - DVI-D */
-/*       = 4   - DVI-A */
-/*       = 5   - SVIDEO */
-/*       = 6   - COMPOSITE */
-/*       = 7   - LVDS */
-/*       = 8   - DIGITAL LINK */
-/*       = 9   - SCART */
-/*       = 0xA - HDMI_type A */
-/*       = 0xB - HDMI_type B */
-/*       = 0xE - Special case1 (DVI+DIN) */
-/*       Others=TBD */
-/*     [3:0] - DAC Associated */
-/*       = 0   - no DAC */
-/*       = 1   - DACA */
-/*       = 2   - DACB */
-/*       = 3   - External DAC */
-/*       Others=TBD */
-/*  */
+//  ucConnectInfo:
+//    [7:4] - connector type
+//      = 1   - VGA connector   
+//      = 2   - DVI-I
+//      = 3   - DVI-D
+//      = 4   - DVI-A
+//      = 5   - SVIDEO
+//      = 6   - COMPOSITE
+//      = 7   - LVDS
+//      = 8   - DIGITAL LINK
+//      = 9   - SCART
+//      = 0xA - HDMI_type A
+//      = 0xB - HDMI_type B
+//      = 0xE - Special case1 (DVI+DIN)
+//      Others=TBD
+//    [3:0] - DAC Associated
+//      = 0   - no DAC
+//      = 1   - DACA
+//      = 2   - DACB
+//      = 3   - External DAC
+//      Others=TBD
+//    
 
-typedef struct _ATOM_CONNECTOR_INFO {
+typedef struct _ATOM_CONNECTOR_INFO
+{
 #if ATOM_BIG_ENDIAN
-	UCHAR bfConnectorType:4;
-	UCHAR bfAssociatedDAC:4;
+  UCHAR   bfConnectorType:4;
+  UCHAR   bfAssociatedDAC:4;
 #else
-	UCHAR bfAssociatedDAC:4;
-	UCHAR bfConnectorType:4;
+  UCHAR   bfAssociatedDAC:4;
+  UCHAR   bfConnectorType:4;
 #endif
-} ATOM_CONNECTOR_INFO;
+}ATOM_CONNECTOR_INFO;
 
-typedef union _ATOM_CONNECTOR_INFO_ACCESS {
-	ATOM_CONNECTOR_INFO sbfAccess;
-	UCHAR ucAccess;
-} ATOM_CONNECTOR_INFO_ACCESS;
+typedef union _ATOM_CONNECTOR_INFO_ACCESS
+{
+  ATOM_CONNECTOR_INFO sbfAccess;
+  UCHAR               ucAccess;
+}ATOM_CONNECTOR_INFO_ACCESS;
 
-typedef struct _ATOM_CONNECTOR_INFO_I2C {
-	ATOM_CONNECTOR_INFO_ACCESS sucConnectorInfo;
-	ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;
-} ATOM_CONNECTOR_INFO_I2C;
+typedef struct _ATOM_CONNECTOR_INFO_I2C
+{
+  ATOM_CONNECTOR_INFO_ACCESS sucConnectorInfo;
+  ATOM_I2C_ID_CONFIG_ACCESS  sucI2cId;
+}ATOM_CONNECTOR_INFO_I2C;
 
-typedef struct _ATOM_SUPPORTED_DEVICES_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usDeviceSupport;
-	ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO];
-} ATOM_SUPPORTED_DEVICES_INFO;
+
+typedef struct _ATOM_SUPPORTED_DEVICES_INFO
+{ 
+  ATOM_COMMON_TABLE_HEADER	sHeader;
+  USHORT                    usDeviceSupport;
+  ATOM_CONNECTOR_INFO_I2C   asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO];
+}ATOM_SUPPORTED_DEVICES_INFO;
 
 #define NO_INT_SRC_MAPPED       0xFF
 
-typedef struct _ATOM_CONNECTOR_INC_SRC_BITMAP {
-	UCHAR ucIntSrcBitmap;
-} ATOM_CONNECTOR_INC_SRC_BITMAP;
+typedef struct _ATOM_CONNECTOR_INC_SRC_BITMAP
+{
+  UCHAR   ucIntSrcBitmap;
+}ATOM_CONNECTOR_INC_SRC_BITMAP;
 
-typedef struct _ATOM_SUPPORTED_DEVICES_INFO_2 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usDeviceSupport;
-	ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_2];
-	ATOM_CONNECTOR_INC_SRC_BITMAP
-	    asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_2];
-} ATOM_SUPPORTED_DEVICES_INFO_2;
+typedef struct _ATOM_SUPPORTED_DEVICES_INFO_2
+{ 
+  ATOM_COMMON_TABLE_HEADER      sHeader;
+  USHORT                        usDeviceSupport;
+  ATOM_CONNECTOR_INFO_I2C       asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_2];
+  ATOM_CONNECTOR_INC_SRC_BITMAP asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_2];
+}ATOM_SUPPORTED_DEVICES_INFO_2;
 
-typedef struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usDeviceSupport;
-	ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE];
-	ATOM_CONNECTOR_INC_SRC_BITMAP asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE];
-} ATOM_SUPPORTED_DEVICES_INFO_2d1;
+typedef struct _ATOM_SUPPORTED_DEVICES_INFO_2d1
+{ 
+  ATOM_COMMON_TABLE_HEADER      sHeader;
+  USHORT                        usDeviceSupport;
+  ATOM_CONNECTOR_INFO_I2C       asConnInfo[ATOM_MAX_SUPPORTED_DEVICE];
+  ATOM_CONNECTOR_INC_SRC_BITMAP asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE];
+}ATOM_SUPPORTED_DEVICES_INFO_2d1;
 
 #define ATOM_SUPPORTED_DEVICES_INFO_LAST ATOM_SUPPORTED_DEVICES_INFO_2d1
 
-typedef struct _ATOM_MISC_CONTROL_INFO {
-	USHORT usFrequency;
-	UCHAR ucPLL_ChargePump;	/*  PLL charge-pump gain control */
-	UCHAR ucPLL_DutyCycle;	/*  PLL duty cycle control */
-	UCHAR ucPLL_VCO_Gain;	/*  PLL VCO gain control */
-	UCHAR ucPLL_VoltageSwing;	/*  PLL driver voltage swing control */
-} ATOM_MISC_CONTROL_INFO;
+
+
+typedef struct _ATOM_MISC_CONTROL_INFO
+{
+   USHORT usFrequency;
+   UCHAR  ucPLL_ChargePump;				                // PLL charge-pump gain control
+   UCHAR  ucPLL_DutyCycle;				                // PLL duty cycle control
+   UCHAR  ucPLL_VCO_Gain;				                  // PLL VCO gain control
+   UCHAR  ucPLL_VoltageSwing;			                // PLL driver voltage swing control
+}ATOM_MISC_CONTROL_INFO;  
+
 
 #define ATOM_MAX_MISC_INFO       4
 
-typedef struct _ATOM_TMDS_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usMaxFrequency;	/*  in 10Khz */
-	ATOM_MISC_CONTROL_INFO asMiscInfo[ATOM_MAX_MISC_INFO];
-} ATOM_TMDS_INFO;
+typedef struct _ATOM_TMDS_INFO
+{
+  ATOM_COMMON_TABLE_HEADER sHeader;  
+  USHORT							usMaxFrequency;             // in 10Khz
+  ATOM_MISC_CONTROL_INFO				asMiscInfo[ATOM_MAX_MISC_INFO];
+}ATOM_TMDS_INFO;
 
-typedef struct _ATOM_ENCODER_ANALOG_ATTRIBUTE {
-	UCHAR ucTVStandard;	/* Same as TV standards defined above, */
-	UCHAR ucPadding[1];
-} ATOM_ENCODER_ANALOG_ATTRIBUTE;
 
-typedef struct _ATOM_ENCODER_DIGITAL_ATTRIBUTE {
-	UCHAR ucAttribute;	/* Same as other digital encoder attributes defined above */
-	UCHAR ucPadding[1];
-} ATOM_ENCODER_DIGITAL_ATTRIBUTE;
+typedef struct _ATOM_ENCODER_ANALOG_ATTRIBUTE
+{
+  UCHAR ucTVStandard;     //Same as TV standards defined above, 
+  UCHAR ucPadding[1];
+}ATOM_ENCODER_ANALOG_ATTRIBUTE;
 
-typedef union _ATOM_ENCODER_ATTRIBUTE {
-	ATOM_ENCODER_ANALOG_ATTRIBUTE sAlgAttrib;
-	ATOM_ENCODER_DIGITAL_ATTRIBUTE sDigAttrib;
-} ATOM_ENCODER_ATTRIBUTE;
+typedef struct _ATOM_ENCODER_DIGITAL_ATTRIBUTE
+{
+  UCHAR ucAttribute;      //Same as other digital encoder attributes defined above
+  UCHAR ucPadding[1];		
+}ATOM_ENCODER_DIGITAL_ATTRIBUTE;
 
-typedef struct _DVO_ENCODER_CONTROL_PARAMETERS {
-	USHORT usPixelClock;
-	USHORT usEncoderID;
-	UCHAR ucDeviceType;	/* Use ATOM_DEVICE_xxx1_Index to indicate device type only. */
-	UCHAR ucAction;		/* ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT */
-	ATOM_ENCODER_ATTRIBUTE usDevAttr;
-} DVO_ENCODER_CONTROL_PARAMETERS;
+typedef union _ATOM_ENCODER_ATTRIBUTE
+{
+  ATOM_ENCODER_ANALOG_ATTRIBUTE sAlgAttrib;
+  ATOM_ENCODER_DIGITAL_ATTRIBUTE sDigAttrib;
+}ATOM_ENCODER_ATTRIBUTE;
 
-typedef struct _DVO_ENCODER_CONTROL_PS_ALLOCATION {
-	DVO_ENCODER_CONTROL_PARAMETERS sDVOEncoder;
-	WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved;	/* Caller doesn't need to init this portion */
-} DVO_ENCODER_CONTROL_PS_ALLOCATION;
+
+typedef struct _DVO_ENCODER_CONTROL_PARAMETERS
+{
+  USHORT usPixelClock; 
+  USHORT usEncoderID; 
+  UCHAR  ucDeviceType;												//Use ATOM_DEVICE_xxx1_Index to indicate device type only.	
+  UCHAR  ucAction;														//ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT
+  ATOM_ENCODER_ATTRIBUTE usDevAttr;     		
+}DVO_ENCODER_CONTROL_PARAMETERS;
+
+typedef struct _DVO_ENCODER_CONTROL_PS_ALLOCATION
+{                               
+  DVO_ENCODER_CONTROL_PARAMETERS    sDVOEncoder;
+  WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION      sReserved;     //Caller doesn't need to init this portion
+}DVO_ENCODER_CONTROL_PS_ALLOCATION;
+
 
 #define ATOM_XTMDS_ASIC_SI164_ID        1
 #define ATOM_XTMDS_ASIC_SI178_ID        2
@@ -4526,27 +5539,30 @@
 #define ATOM_XTMDS_SUPPORTED_DUALLINK   0x00000002
 #define ATOM_XTMDS_MVPU_FPGA            0x00000004
 
-typedef struct _ATOM_XTMDS_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	USHORT usSingleLinkMaxFrequency;
-	ATOM_I2C_ID_CONFIG_ACCESS sucI2cId;	/* Point the ID on which I2C is used to control external chip */
-	UCHAR ucXtransimitterID;
-	UCHAR ucSupportedLink;	/*  Bit field, bit0=1, single link supported;bit1=1,dual link supported */
-	UCHAR ucSequnceAlterID;	/*  Even with the same external TMDS asic, it's possible that the program seqence alters */
-	/*  due to design. This ID is used to alert driver that the sequence is not "standard"! */
-	UCHAR ucMasterAddress;	/*  Address to control Master xTMDS Chip */
-	UCHAR ucSlaveAddress;	/*  Address to control Slave xTMDS Chip */
-} ATOM_XTMDS_INFO;
+                           
+typedef struct _ATOM_XTMDS_INFO
+{
+  ATOM_COMMON_TABLE_HEADER   sHeader;  
+  USHORT                     usSingleLinkMaxFrequency; 
+  ATOM_I2C_ID_CONFIG_ACCESS  sucI2cId;           //Point the ID on which I2C is used to control external chip
+  UCHAR                      ucXtransimitterID;          
+  UCHAR                      ucSupportedLink;    // Bit field, bit0=1, single link supported;bit1=1,dual link supported
+  UCHAR                      ucSequnceAlterID;   // Even with the same external TMDS asic, it's possible that the program seqence alters 
+                                                 // due to design. This ID is used to alert driver that the sequence is not "standard"!              
+  UCHAR                      ucMasterAddress;    // Address to control Master xTMDS Chip
+  UCHAR                      ucSlaveAddress;     // Address to control Slave xTMDS Chip
+}ATOM_XTMDS_INFO;
 
-typedef struct _DFP_DPMS_STATUS_CHANGE_PARAMETERS {
-	UCHAR ucEnable;		/*  ATOM_ENABLE=On or ATOM_DISABLE=Off */
-	UCHAR ucDevice;		/*  ATOM_DEVICE_DFP1_INDEX.... */
-	UCHAR ucPadding[2];
-} DFP_DPMS_STATUS_CHANGE_PARAMETERS;
+typedef struct _DFP_DPMS_STATUS_CHANGE_PARAMETERS
+{  
+  UCHAR ucEnable;                     // ATOM_ENABLE=On or ATOM_DISABLE=Off
+  UCHAR ucDevice;                     // ATOM_DEVICE_DFP1_INDEX....
+  UCHAR ucPadding[2];             
+}DFP_DPMS_STATUS_CHANGE_PARAMETERS;
 
 /****************************Legacy Power Play Table Definitions **********************/
 
-/* Definitions for ulPowerPlayMiscInfo */
+//Definitions for ulPowerPlayMiscInfo
 #define ATOM_PM_MISCINFO_SPLIT_CLOCK                     0x00000000L
 #define ATOM_PM_MISCINFO_USING_MCLK_SRC                  0x00000001L
 #define ATOM_PM_MISCINFO_USING_SCLK_SRC                  0x00000002L
@@ -4558,8 +5574,8 @@
 
 #define ATOM_PM_MISCINFO_ENGINE_CLOCK_CONTRL_EN          0x00000020L
 #define ATOM_PM_MISCINFO_MEMORY_CLOCK_CONTRL_EN          0x00000040L
-#define ATOM_PM_MISCINFO_PROGRAM_VOLTAGE                 0x00000080L	/* When this bit set, ucVoltageDropIndex is not an index for GPIO pin, but a voltage ID that SW needs program */
-
+#define ATOM_PM_MISCINFO_PROGRAM_VOLTAGE                 0x00000080L  //When this bit set, ucVoltageDropIndex is not an index for GPIO pin, but a voltage ID that SW needs program  
+ 
 #define ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN      0x00000100L
 #define ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN         0x00000200L
 #define ATOM_PM_MISCINFO_ASIC_SLEEP_MODE_EN              0x00000400L
@@ -4569,22 +5585,22 @@
 #define ATOM_PM_MISCINFO_LOW_LCD_REFRESH_RATE            0x00004000L
 
 #define ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE             0x00008000L
-#define ATOM_PM_MISCINFO_OVER_CLOCK_MODE                 0x00010000L
+#define ATOM_PM_MISCINFO_OVER_CLOCK_MODE                 0x00010000L 
 #define ATOM_PM_MISCINFO_OVER_DRIVE_MODE                 0x00020000L
 #define ATOM_PM_MISCINFO_POWER_SAVING_MODE               0x00040000L
 #define ATOM_PM_MISCINFO_THERMAL_DIODE_MODE              0x00080000L
 
-#define ATOM_PM_MISCINFO_FRAME_MODULATION_MASK           0x00300000L	/* 0-FM Disable, 1-2 level FM, 2-4 level FM, 3-Reserved */
-#define ATOM_PM_MISCINFO_FRAME_MODULATION_SHIFT          20
+#define ATOM_PM_MISCINFO_FRAME_MODULATION_MASK           0x00300000L  //0-FM Disable, 1-2 level FM, 2-4 level FM, 3-Reserved
+#define ATOM_PM_MISCINFO_FRAME_MODULATION_SHIFT          20 
 
 #define ATOM_PM_MISCINFO_DYN_CLK_3D_IDLE                 0x00400000L
 #define ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2      0x00800000L
 #define ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4      0x01000000L
-#define ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN            0x02000000L	/* When set, Dynamic */
-#define ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN        0x04000000L	/* When set, Dynamic */
-#define ATOM_PM_MISCINFO_3D_ACCELERATION_EN              0x08000000L	/* When set, This mode is for acceleated 3D mode */
+#define ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN            0x02000000L  //When set, Dynamic 
+#define ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN        0x04000000L  //When set, Dynamic
+#define ATOM_PM_MISCINFO_3D_ACCELERATION_EN              0x08000000L  //When set, This mode is for acceleated 3D mode
 
-#define ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_MASK   0x70000000L	/* 1-Optimal Battery Life Group, 2-High Battery, 3-Balanced, 4-High Performance, 5- Optimal Performance (Default state with Default clocks) */
+#define ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_MASK   0x70000000L  //1-Optimal Battery Life Group, 2-High Battery, 3-Balanced, 4-High Performance, 5- Optimal Performance (Default state with Default clocks) 
 #define ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_SHIFT  28
 #define ATOM_PM_MISCINFO_ENABLE_BACK_BIAS                0x80000000L
 
@@ -4594,55 +5610,59 @@
 #define ATOM_PM_MISCINFO2_FS3D_OVERDRIVE_INFO            0x00000008L
 #define ATOM_PM_MISCINFO2_FORCEDLOWPWR_MODE              0x00000010L
 #define ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN       0x00000020L
-#define ATOM_PM_MISCINFO2_VIDEO_PLAYBACK_CAPABLE         0x00000040L	/* If this bit is set in multi-pp mode, then driver will pack up one with the minior power consumption. */
-								      /* If it's not set in any pp mode, driver will use its default logic to pick a pp mode in video playback */
+#define ATOM_PM_MISCINFO2_VIDEO_PLAYBACK_CAPABLE         0x00000040L  //If this bit is set in multi-pp mode, then driver will pack up one with the minior power consumption. 
+                                                                      //If it's not set in any pp mode, driver will use its default logic to pick a pp mode in video playback
 #define ATOM_PM_MISCINFO2_NOT_VALID_ON_DC                0x00000080L
 #define ATOM_PM_MISCINFO2_STUTTER_MODE_EN                0x00000100L
-#define ATOM_PM_MISCINFO2_UVD_SUPPORT_MODE               0x00000200L
+#define ATOM_PM_MISCINFO2_UVD_SUPPORT_MODE               0x00000200L 
 
-/* ucTableFormatRevision=1 */
-/* ucTableContentRevision=1 */
-typedef struct _ATOM_POWERMODE_INFO {
-	ULONG ulMiscInfo;	/* The power level should be arranged in ascending order */
-	ULONG ulReserved1;	/*  must set to 0 */
-	ULONG ulReserved2;	/*  must set to 0 */
-	USHORT usEngineClock;
-	USHORT usMemoryClock;
-	UCHAR ucVoltageDropIndex;	/*  index to GPIO table */
-	UCHAR ucSelectedPanel_RefreshRate;	/*  panel refresh rate */
-	UCHAR ucMinTemperature;
-	UCHAR ucMaxTemperature;
-	UCHAR ucNumPciELanes;	/*  number of PCIE lanes */
-} ATOM_POWERMODE_INFO;
+//ucTableFormatRevision=1
+//ucTableContentRevision=1
+typedef struct  _ATOM_POWERMODE_INFO
+{
+  ULONG     ulMiscInfo;                 //The power level should be arranged in ascending order
+  ULONG     ulReserved1;                // must set to 0
+  ULONG     ulReserved2;                // must set to 0
+  USHORT    usEngineClock;
+  USHORT    usMemoryClock;
+  UCHAR     ucVoltageDropIndex;         // index to GPIO table
+  UCHAR     ucSelectedPanel_RefreshRate;// panel refresh rate
+  UCHAR     ucMinTemperature;
+  UCHAR     ucMaxTemperature;
+  UCHAR     ucNumPciELanes;             // number of PCIE lanes
+}ATOM_POWERMODE_INFO;
 
-/* ucTableFormatRevision=2 */
-/* ucTableContentRevision=1 */
-typedef struct _ATOM_POWERMODE_INFO_V2 {
-	ULONG ulMiscInfo;	/* The power level should be arranged in ascending order */
-	ULONG ulMiscInfo2;
-	ULONG ulEngineClock;
-	ULONG ulMemoryClock;
-	UCHAR ucVoltageDropIndex;	/*  index to GPIO table */
-	UCHAR ucSelectedPanel_RefreshRate;	/*  panel refresh rate */
-	UCHAR ucMinTemperature;
-	UCHAR ucMaxTemperature;
-	UCHAR ucNumPciELanes;	/*  number of PCIE lanes */
-} ATOM_POWERMODE_INFO_V2;
+//ucTableFormatRevision=2
+//ucTableContentRevision=1
+typedef struct  _ATOM_POWERMODE_INFO_V2
+{
+  ULONG     ulMiscInfo;                 //The power level should be arranged in ascending order
+  ULONG     ulMiscInfo2;                
+  ULONG     ulEngineClock;                
+  ULONG     ulMemoryClock;
+  UCHAR     ucVoltageDropIndex;         // index to GPIO table
+  UCHAR     ucSelectedPanel_RefreshRate;// panel refresh rate
+  UCHAR     ucMinTemperature;
+  UCHAR     ucMaxTemperature;
+  UCHAR     ucNumPciELanes;             // number of PCIE lanes
+}ATOM_POWERMODE_INFO_V2;
 
-/* ucTableFormatRevision=2 */
-/* ucTableContentRevision=2 */
-typedef struct _ATOM_POWERMODE_INFO_V3 {
-	ULONG ulMiscInfo;	/* The power level should be arranged in ascending order */
-	ULONG ulMiscInfo2;
-	ULONG ulEngineClock;
-	ULONG ulMemoryClock;
-	UCHAR ucVoltageDropIndex;	/*  index to Core (VDDC) votage table */
-	UCHAR ucSelectedPanel_RefreshRate;	/*  panel refresh rate */
-	UCHAR ucMinTemperature;
-	UCHAR ucMaxTemperature;
-	UCHAR ucNumPciELanes;	/*  number of PCIE lanes */
-	UCHAR ucVDDCI_VoltageDropIndex;	/*  index to VDDCI votage table */
-} ATOM_POWERMODE_INFO_V3;
+//ucTableFormatRevision=2
+//ucTableContentRevision=2
+typedef struct  _ATOM_POWERMODE_INFO_V3
+{
+  ULONG     ulMiscInfo;                 //The power level should be arranged in ascending order
+  ULONG     ulMiscInfo2;                
+  ULONG     ulEngineClock;                
+  ULONG     ulMemoryClock;
+  UCHAR     ucVoltageDropIndex;         // index to Core (VDDC) votage table
+  UCHAR     ucSelectedPanel_RefreshRate;// panel refresh rate
+  UCHAR     ucMinTemperature;
+  UCHAR     ucMaxTemperature;
+  UCHAR     ucNumPciELanes;             // number of PCIE lanes
+  UCHAR     ucVDDCI_VoltageDropIndex;   // index to VDDCI votage table
+}ATOM_POWERMODE_INFO_V3;
+
 
 #define ATOM_MAX_NUMBEROF_POWER_BLOCK  8
 
@@ -4655,40 +5675,44 @@
 #define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_MUA6649   0x04
 #define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_LM64      0x05
 #define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_F75375    0x06
-#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ASC7512   0x07	/*  Andigilog */
+#define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ASC7512   0x07	// Andigilog
 
-typedef struct _ATOM_POWERPLAY_INFO {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR ucOverdriveThermalController;
-	UCHAR ucOverdriveI2cLine;
-	UCHAR ucOverdriveIntBitmap;
-	UCHAR ucOverdriveControllerAddress;
-	UCHAR ucSizeOfPowerModeEntry;
-	UCHAR ucNumOfPowerModeEntries;
-	ATOM_POWERMODE_INFO asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
-} ATOM_POWERPLAY_INFO;
 
-typedef struct _ATOM_POWERPLAY_INFO_V2 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR ucOverdriveThermalController;
-	UCHAR ucOverdriveI2cLine;
-	UCHAR ucOverdriveIntBitmap;
-	UCHAR ucOverdriveControllerAddress;
-	UCHAR ucSizeOfPowerModeEntry;
-	UCHAR ucNumOfPowerModeEntries;
-	ATOM_POWERMODE_INFO_V2 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
-} ATOM_POWERPLAY_INFO_V2;
+typedef struct  _ATOM_POWERPLAY_INFO
+{
+  ATOM_COMMON_TABLE_HEADER	sHeader; 
+  UCHAR    ucOverdriveThermalController;
+  UCHAR    ucOverdriveI2cLine;
+  UCHAR    ucOverdriveIntBitmap;
+  UCHAR    ucOverdriveControllerAddress;
+  UCHAR    ucSizeOfPowerModeEntry;
+  UCHAR    ucNumOfPowerModeEntries;
+  ATOM_POWERMODE_INFO asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
+}ATOM_POWERPLAY_INFO;
 
-typedef struct _ATOM_POWERPLAY_INFO_V3 {
-	ATOM_COMMON_TABLE_HEADER sHeader;
-	UCHAR ucOverdriveThermalController;
-	UCHAR ucOverdriveI2cLine;
-	UCHAR ucOverdriveIntBitmap;
-	UCHAR ucOverdriveControllerAddress;
-	UCHAR ucSizeOfPowerModeEntry;
-	UCHAR ucNumOfPowerModeEntries;
-	ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
-} ATOM_POWERPLAY_INFO_V3;
+typedef struct  _ATOM_POWERPLAY_INFO_V2
+{
+  ATOM_COMMON_TABLE_HEADER	sHeader; 
+  UCHAR    ucOverdriveThermalController;
+  UCHAR    ucOverdriveI2cLine;
+  UCHAR    ucOverdriveIntBitmap;
+  UCHAR    ucOverdriveControllerAddress;
+  UCHAR    ucSizeOfPowerModeEntry;
+  UCHAR    ucNumOfPowerModeEntries;
+  ATOM_POWERMODE_INFO_V2 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
+}ATOM_POWERPLAY_INFO_V2;
+  
+typedef struct  _ATOM_POWERPLAY_INFO_V3
+{
+  ATOM_COMMON_TABLE_HEADER	sHeader; 
+  UCHAR    ucOverdriveThermalController;
+  UCHAR    ucOverdriveI2cLine;
+  UCHAR    ucOverdriveIntBitmap;
+  UCHAR    ucOverdriveControllerAddress;
+  UCHAR    ucSizeOfPowerModeEntry;
+  UCHAR    ucNumOfPowerModeEntries;
+  ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK];
+}ATOM_POWERPLAY_INFO_V3;
 
 /* New PPlib */
 /**************************************************************************/
@@ -4873,40 +5897,42 @@
       UCHAR  ucMaxHTLinkWidth;            // From SBIOS - {2, 4, 8, 16}
       UCHAR  ucMinHTLinkWidth;            // From SBIOS - {2, 4, 8, 16}. Effective only if CDLW enabled. Minimum down stream width could be bigger as display BW requriement.
       USHORT usHTLinkFreq;                // See definition ATOM_PPLIB_RS780_HTLINKFREQ_xxx or in MHz(>=200).
-      ULONG  ulFlags;
+      ULONG  ulFlags; 
 } ATOM_PPLIB_RS780_CLOCK_INFO;
 
-#define ATOM_PPLIB_RS780_VOLTAGE_NONE       0
-#define ATOM_PPLIB_RS780_VOLTAGE_LOW        1
-#define ATOM_PPLIB_RS780_VOLTAGE_HIGH       2
-#define ATOM_PPLIB_RS780_VOLTAGE_VARIABLE   3
+#define ATOM_PPLIB_RS780_VOLTAGE_NONE       0 
+#define ATOM_PPLIB_RS780_VOLTAGE_LOW        1 
+#define ATOM_PPLIB_RS780_VOLTAGE_HIGH       2 
+#define ATOM_PPLIB_RS780_VOLTAGE_VARIABLE   3 
 
 #define ATOM_PPLIB_RS780_SPMCLK_NONE        0   // We cannot change the side port memory clock, leave it as it is.
 #define ATOM_PPLIB_RS780_SPMCLK_LOW         1
 #define ATOM_PPLIB_RS780_SPMCLK_HIGH        2
 
-#define ATOM_PPLIB_RS780_HTLINKFREQ_NONE       0
-#define ATOM_PPLIB_RS780_HTLINKFREQ_LOW        1
-#define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH       2
+#define ATOM_PPLIB_RS780_HTLINKFREQ_NONE       0 
+#define ATOM_PPLIB_RS780_HTLINKFREQ_LOW        1 
+#define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH       2 
 
 /**************************************************************************/
 
-/*  Following definitions are for compatiblity issue in different SW components. */
+
+// Following definitions are for compatiblity issue in different SW components. 
 #define ATOM_MASTER_DATA_TABLE_REVISION   0x01
-#define Object_Info												Object_Header
+#define Object_Info												Object_Header			
 #define	AdjustARB_SEQ											MC_InitParameter
 #define	VRAM_GPIO_DetectionInfo						VoltageObjectInfo
-#define	ASIC_VDDCI_Info                   ASIC_ProfilingInfo
+#define	ASIC_VDDCI_Info                   ASIC_ProfilingInfo														
 #define ASIC_MVDDQ_Info										MemoryTrainingInfo
-#define SS_Info                           PPLL_SS_Info
+#define SS_Info                           PPLL_SS_Info                      
 #define ASIC_MVDDC_Info                   ASIC_InternalSS_Info
 #define DispDevicePriorityInfo						SaveRestoreInfo
 #define DispOutInfo												TV_VideoMode
 
+
 #define ATOM_ENCODER_OBJECT_TABLE         ATOM_OBJECT_TABLE
 #define ATOM_CONNECTOR_OBJECT_TABLE       ATOM_OBJECT_TABLE
 
-/* New device naming, remove them when both DAL/VBIOS is ready */
+//New device naming, remove them when both DAL/VBIOS is ready
 #define DFP2I_OUTPUT_CONTROL_PARAMETERS    CRT1_OUTPUT_CONTROL_PARAMETERS
 #define DFP2I_OUTPUT_CONTROL_PS_ALLOCATION DFP2I_OUTPUT_CONTROL_PARAMETERS
 
@@ -4921,7 +5947,7 @@
 
 #define ATOM_DEVICE_DFP1I_INDEX            ATOM_DEVICE_DFP1_INDEX
 #define ATOM_DEVICE_DFP1X_INDEX            ATOM_DEVICE_DFP2_INDEX
-
+ 
 #define ATOM_DEVICE_DFP2I_INDEX            0x00000009
 #define ATOM_DEVICE_DFP2I_SUPPORT          (0x1L << ATOM_DEVICE_DFP2I_INDEX)
 
@@ -4939,7 +5965,7 @@
 
 #define ATOM_S3_DFP2I_ACTIVEb1             0x02
 
-#define ATOM_S3_DFP1I_ACTIVE               ATOM_S3_DFP1_ACTIVE
+#define ATOM_S3_DFP1I_ACTIVE               ATOM_S3_DFP1_ACTIVE 
 #define ATOM_S3_DFP1X_ACTIVE               ATOM_S3_DFP2_ACTIVE
 
 #define ATOM_S3_DFP2I_ACTIVE               0x00000200L
@@ -4958,14 +5984,14 @@
 #define ATOM_S6_ACC_REQ_DFP2Ib3            0x02
 #define ATOM_S6_ACC_REQ_DFP2I              0x02000000L
 
-#define TMDS1XEncoderControl               DVOEncoderControl
+#define TMDS1XEncoderControl               DVOEncoderControl           
 #define DFP1XOutputControl                 DVOOutputControl
 
 #define ExternalDFPOutputControl           DFP1XOutputControl
 #define EnableExternalTMDS_Encoder         TMDS1XEncoderControl
 
 #define DFP1IOutputControl                 TMDSAOutputControl
-#define DFP2IOutputControl                 LVTMAOutputControl
+#define DFP2IOutputControl                 LVTMAOutputControl      
 
 #define DAC1_ENCODER_CONTROL_PARAMETERS    DAC_ENCODER_CONTROL_PARAMETERS
 #define DAC1_ENCODER_CONTROL_PS_ALLOCATION DAC_ENCODER_CONTROL_PS_ALLOCATION
@@ -4974,7 +6000,7 @@
 #define DAC2_ENCODER_CONTROL_PS_ALLOCATION DAC_ENCODER_CONTROL_PS_ALLOCATION
 
 #define ucDac1Standard  ucDacStandard
-#define ucDac2Standard  ucDacStandard
+#define ucDac2Standard  ucDacStandard  
 
 #define TMDS1EncoderControl TMDSAEncoderControl
 #define TMDS2EncoderControl LVTMAEncoderControl
@@ -4984,12 +6010,56 @@
 #define CRT1OutputControl   DAC1OutputControl
 #define CRT2OutputControl   DAC2OutputControl
 
-/* These two lines will be removed for sure in a few days, will follow up with Michael V. */
+//These two lines will be removed for sure in a few days, will follow up with Michael V.
 #define EnableLVDS_SS   EnableSpreadSpectrumOnPPLL
-#define ENABLE_LVDS_SS_PARAMETERS_V3  ENABLE_SPREAD_SPECTRUM_ON_PPLL
+#define ENABLE_LVDS_SS_PARAMETERS_V3  ENABLE_SPREAD_SPECTRUM_ON_PPLL  
+
+//#define ATOM_S2_CRT1_DPMS_STATE         0x00010000L
+//#define ATOM_S2_LCD1_DPMS_STATE	        ATOM_S2_CRT1_DPMS_STATE
+//#define ATOM_S2_TV1_DPMS_STATE          ATOM_S2_CRT1_DPMS_STATE
+//#define ATOM_S2_DFP1_DPMS_STATE         ATOM_S2_CRT1_DPMS_STATE
+//#define ATOM_S2_CRT2_DPMS_STATE         ATOM_S2_CRT1_DPMS_STATE
+
+#define ATOM_S6_ACC_REQ_TV2             0x00400000L
+#define ATOM_DEVICE_TV2_INDEX           0x00000006
+#define ATOM_DEVICE_TV2_SUPPORT         (0x1L << ATOM_DEVICE_TV2_INDEX)
+#define ATOM_S0_TV2                     0x00100000L
+#define ATOM_S3_TV2_ACTIVE              ATOM_S3_DFP6_ACTIVE
+#define ATOM_S3_TV2_CRTC_ACTIVE         ATOM_S3_DFP6_CRTC_ACTIVE
+
+//
+#define ATOM_S2_CRT1_DPMS_STATE         0x00010000L
+#define ATOM_S2_LCD1_DPMS_STATE	        0x00020000L
+#define ATOM_S2_TV1_DPMS_STATE          0x00040000L
+#define ATOM_S2_DFP1_DPMS_STATE         0x00080000L
+#define ATOM_S2_CRT2_DPMS_STATE         0x00100000L
+#define ATOM_S2_LCD2_DPMS_STATE         0x00200000L
+#define ATOM_S2_TV2_DPMS_STATE          0x00400000L
+#define ATOM_S2_DFP2_DPMS_STATE         0x00800000L
+#define ATOM_S2_CV_DPMS_STATE           0x01000000L
+#define ATOM_S2_DFP3_DPMS_STATE					0x02000000L
+#define ATOM_S2_DFP4_DPMS_STATE					0x04000000L
+#define ATOM_S2_DFP5_DPMS_STATE					0x08000000L
+
+#define ATOM_S2_CRT1_DPMS_STATEb2       0x01
+#define ATOM_S2_LCD1_DPMS_STATEb2       0x02
+#define ATOM_S2_TV1_DPMS_STATEb2        0x04
+#define ATOM_S2_DFP1_DPMS_STATEb2       0x08
+#define ATOM_S2_CRT2_DPMS_STATEb2       0x10
+#define ATOM_S2_LCD2_DPMS_STATEb2       0x20
+#define ATOM_S2_TV2_DPMS_STATEb2        0x40
+#define ATOM_S2_DFP2_DPMS_STATEb2       0x80
+#define ATOM_S2_CV_DPMS_STATEb3         0x01
+#define ATOM_S2_DFP3_DPMS_STATEb3				0x02
+#define ATOM_S2_DFP4_DPMS_STATEb3				0x04
+#define ATOM_S2_DFP5_DPMS_STATEb3				0x08
+
+#define ATOM_S3_ASIC_GUI_ENGINE_HUNGb3	0x20
+#define ATOM_S3_ALLOW_FAST_PWR_SWITCHb3 0x40
+#define ATOM_S3_RQST_GPU_USE_MIN_PWRb3  0x80
 
 /*********************************************************************************/
 
-#pragma pack()			/*  BIOS data must use byte aligment */
+#pragma pack() // BIOS data must use byte aligment
 
 #endif /* _ATOMBIOS_H */
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index af464e35..dd9fdf5 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -245,21 +245,25 @@
 
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-		atombios_enable_crtc(crtc, 1);
+		atombios_enable_crtc(crtc, ATOM_ENABLE);
 		if (ASIC_IS_DCE3(rdev))
-			atombios_enable_crtc_memreq(crtc, 1);
-		atombios_blank_crtc(crtc, 0);
-		drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
+			atombios_enable_crtc_memreq(crtc, ATOM_ENABLE);
+		atombios_blank_crtc(crtc, ATOM_DISABLE);
+		/* XXX re-enable when interrupt support is added */
+		if (!ASIC_IS_DCE4(rdev))
+			drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
 		radeon_crtc_load_lut(crtc);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
-		drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
-		atombios_blank_crtc(crtc, 1);
+		/* XXX re-enable when interrupt support is added */
+		if (!ASIC_IS_DCE4(rdev))
+			drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
+		atombios_blank_crtc(crtc, ATOM_ENABLE);
 		if (ASIC_IS_DCE3(rdev))
-			atombios_enable_crtc_memreq(crtc, 0);
-		atombios_enable_crtc(crtc, 0);
+			atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
+		atombios_enable_crtc(crtc, ATOM_DISABLE);
 		break;
 	}
 }
@@ -349,6 +353,11 @@
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+union atom_enable_ss {
+	ENABLE_LVDS_SS_PARAMETERS legacy;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION v1;
+};
+
 static void atombios_set_ss(struct drm_crtc *crtc, int enable)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -358,11 +367,14 @@
 	struct radeon_encoder *radeon_encoder = NULL;
 	struct radeon_encoder_atom_dig *dig = NULL;
 	int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
-	ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION args;
-	ENABLE_LVDS_SS_PARAMETERS legacy_args;
+	union atom_enable_ss args;
 	uint16_t percentage = 0;
 	uint8_t type = 0, step = 0, delay = 0, range = 0;
 
+	/* XXX add ss support for DCE4 */
+	if (ASIC_IS_DCE4(rdev))
+		return;
+
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		if (encoder->crtc == crtc) {
 			radeon_encoder = to_radeon_encoder(encoder);
@@ -386,29 +398,28 @@
 	if (!radeon_encoder)
 		return;
 
+	memset(&args, 0, sizeof(args));
 	if (ASIC_IS_AVIVO(rdev)) {
-		memset(&args, 0, sizeof(args));
-		args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
-		args.ucSpreadSpectrumType = type;
-		args.ucSpreadSpectrumStep = step;
-		args.ucSpreadSpectrumDelay = delay;
-		args.ucSpreadSpectrumRange = range;
-		args.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-		args.ucEnable = enable;
-		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+		args.v1.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
+		args.v1.ucSpreadSpectrumType = type;
+		args.v1.ucSpreadSpectrumStep = step;
+		args.v1.ucSpreadSpectrumDelay = delay;
+		args.v1.ucSpreadSpectrumRange = range;
+		args.v1.ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
+		args.v1.ucEnable = enable;
 	} else {
-		memset(&legacy_args, 0, sizeof(legacy_args));
-		legacy_args.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
-		legacy_args.ucSpreadSpectrumType = type;
-		legacy_args.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2;
-		legacy_args.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4;
-		legacy_args.ucEnable = enable;
-		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&legacy_args);
+		args.legacy.usSpreadSpectrumPercentage = cpu_to_le16(percentage);
+		args.legacy.ucSpreadSpectrumType = type;
+		args.legacy.ucSpreadSpectrumStepSize_Delay = (step & 3) << 2;
+		args.legacy.ucSpreadSpectrumStepSize_Delay |= (delay & 7) << 4;
+		args.legacy.ucEnable = enable;
 	}
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
 union adjust_pixel_clock {
 	ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 v3;
 };
 
 static u32 atombios_adjust_pll(struct drm_crtc *crtc,
@@ -420,10 +431,24 @@
 	struct drm_encoder *encoder = NULL;
 	struct radeon_encoder *radeon_encoder = NULL;
 	u32 adjusted_clock = mode->clock;
+	int encoder_mode = 0;
 
 	/* reset the pll flags */
 	pll->flags = 0;
 
+	/* select the PLL algo */
+	if (ASIC_IS_AVIVO(rdev)) {
+		if (radeon_new_pll == 0)
+			pll->algo = PLL_ALGO_LEGACY;
+		else
+			pll->algo = PLL_ALGO_NEW;
+	} else {
+		if (radeon_new_pll == 1)
+			pll->algo = PLL_ALGO_NEW;
+		else
+			pll->algo = PLL_ALGO_LEGACY;
+	}
+
 	if (ASIC_IS_AVIVO(rdev)) {
 		if ((rdev->family == CHIP_RS600) ||
 		    (rdev->family == CHIP_RS690) ||
@@ -448,10 +473,16 @@
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		if (encoder->crtc == crtc) {
 			radeon_encoder = to_radeon_encoder(encoder);
+			encoder_mode = atombios_get_encoder_mode(encoder);
 			if (ASIC_IS_AVIVO(rdev)) {
 				/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
 				if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
 					adjusted_clock = mode->clock * 2;
+				/* LVDS PLL quirks */
+				if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
+					struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+					pll->algo = dig->pll_algo;
+				}
 			} else {
 				if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
 					pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
@@ -468,14 +499,9 @@
 	 */
 	if (ASIC_IS_DCE3(rdev)) {
 		union adjust_pixel_clock args;
-		struct radeon_encoder_atom_dig *dig;
 		u8 frev, crev;
 		int index;
 
-		if (!radeon_encoder->enc_priv)
-			return adjusted_clock;
-		dig = radeon_encoder->enc_priv;
-
 		index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
 		atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
 				      &crev);
@@ -489,12 +515,51 @@
 			case 2:
 				args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
 				args.v1.ucTransmitterID = radeon_encoder->encoder_id;
-				args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder);
+				args.v1.ucEncodeMode = encoder_mode;
 
 				atom_execute_table(rdev->mode_info.atom_context,
 						   index, (uint32_t *)&args);
 				adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
 				break;
+			case 3:
+				args.v3.sInput.usPixelClock = cpu_to_le16(mode->clock / 10);
+				args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;
+				args.v3.sInput.ucEncodeMode = encoder_mode;
+				args.v3.sInput.ucDispPllConfig = 0;
+				if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+					struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+					if (encoder_mode == ATOM_ENCODER_MODE_DP)
+						args.v3.sInput.ucDispPllConfig |=
+							DISPPLL_CONFIG_COHERENT_MODE;
+					else {
+						if (dig->coherent_mode)
+							args.v3.sInput.ucDispPllConfig |=
+								DISPPLL_CONFIG_COHERENT_MODE;
+						if (mode->clock > 165000)
+							args.v3.sInput.ucDispPllConfig |=
+								DISPPLL_CONFIG_DUAL_LINK;
+					}
+				} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+					/* may want to enable SS on DP/eDP eventually */
+					args.v3.sInput.ucDispPllConfig |=
+						DISPPLL_CONFIG_SS_ENABLE;
+					if (mode->clock > 165000)
+						args.v3.sInput.ucDispPllConfig |=
+							DISPPLL_CONFIG_DUAL_LINK;
+				}
+				atom_execute_table(rdev->mode_info.atom_context,
+						   index, (uint32_t *)&args);
+				adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10;
+				if (args.v3.sOutput.ucRefDiv) {
+					pll->flags |= RADEON_PLL_USE_REF_DIV;
+					pll->reference_div = args.v3.sOutput.ucRefDiv;
+				}
+				if (args.v3.sOutput.ucPostDiv) {
+					pll->flags |= RADEON_PLL_USE_POST_DIV;
+					pll->post_div = args.v3.sOutput.ucPostDiv;
+				}
+				break;
 			default:
 				DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 				return adjusted_clock;
@@ -513,9 +578,47 @@
 	PIXEL_CLOCK_PARAMETERS v1;
 	PIXEL_CLOCK_PARAMETERS_V2 v2;
 	PIXEL_CLOCK_PARAMETERS_V3 v3;
+	PIXEL_CLOCK_PARAMETERS_V5 v5;
 };
 
-void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
+static void atombios_crtc_set_dcpll(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	u8 frev, crev;
+	int index;
+	union set_pixel_clock args;
+
+	memset(&args, 0, sizeof(args));
+
+	index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
+	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
+			      &crev);
+
+	switch (frev) {
+	case 1:
+		switch (crev) {
+		case 5:
+			/* if the default dcpll clock is specified,
+			 * SetPixelClock provides the dividers
+			 */
+			args.v5.ucCRTC = ATOM_CRTC_INVALID;
+			args.v5.usPixelClock = rdev->clock.default_dispclk;
+			args.v5.ucPpll = ATOM_DCPLL;
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+			return;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+		return;
+	}
+	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+}
+
+static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
@@ -529,12 +632,14 @@
 	u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
 	struct radeon_pll *pll;
 	u32 adjusted_clock;
+	int encoder_mode = 0;
 
 	memset(&args, 0, sizeof(args));
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		if (encoder->crtc == crtc) {
 			radeon_encoder = to_radeon_encoder(encoder);
+			encoder_mode = atombios_get_encoder_mode(encoder);
 			break;
 		}
 	}
@@ -542,26 +647,24 @@
 	if (!radeon_encoder)
 		return;
 
-	if (radeon_crtc->crtc_id == 0)
+	switch (radeon_crtc->pll_id) {
+	case ATOM_PPLL1:
 		pll = &rdev->clock.p1pll;
-	else
+		break;
+	case ATOM_PPLL2:
 		pll = &rdev->clock.p2pll;
+		break;
+	case ATOM_DCPLL:
+	case ATOM_PPLL_INVALID:
+		pll = &rdev->clock.dcpll;
+		break;
+	}
 
 	/* adjust pixel clock as needed */
 	adjusted_clock = atombios_adjust_pll(crtc, mode, pll);
 
-	if (ASIC_IS_AVIVO(rdev)) {
-		if (radeon_new_pll)
-			radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock,
-						 &fb_div, &frac_fb_div,
-						 &ref_div, &post_div);
-		else
-			radeon_compute_pll(pll, adjusted_clock, &pll_clock,
-					   &fb_div, &frac_fb_div,
-					   &ref_div, &post_div);
-	} else
-		radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
-				   &ref_div, &post_div);
+	radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
+			   &ref_div, &post_div);
 
 	index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
 	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
@@ -576,8 +679,7 @@
 			args.v1.usFbDiv = cpu_to_le16(fb_div);
 			args.v1.ucFracFbDiv = frac_fb_div;
 			args.v1.ucPostDiv = post_div;
-			args.v1.ucPpll =
-			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
+			args.v1.ucPpll = radeon_crtc->pll_id;
 			args.v1.ucCRTC = radeon_crtc->crtc_id;
 			args.v1.ucRefDivSrc = 1;
 			break;
@@ -587,8 +689,7 @@
 			args.v2.usFbDiv = cpu_to_le16(fb_div);
 			args.v2.ucFracFbDiv = frac_fb_div;
 			args.v2.ucPostDiv = post_div;
-			args.v2.ucPpll =
-			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
+			args.v2.ucPpll = radeon_crtc->pll_id;
 			args.v2.ucCRTC = radeon_crtc->crtc_id;
 			args.v2.ucRefDivSrc = 1;
 			break;
@@ -598,12 +699,22 @@
 			args.v3.usFbDiv = cpu_to_le16(fb_div);
 			args.v3.ucFracFbDiv = frac_fb_div;
 			args.v3.ucPostDiv = post_div;
-			args.v3.ucPpll =
-			    radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
-			args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2);
+			args.v3.ucPpll = radeon_crtc->pll_id;
+			args.v3.ucMiscInfo = (radeon_crtc->pll_id << 2);
 			args.v3.ucTransmitterId = radeon_encoder->encoder_id;
-			args.v3.ucEncoderMode =
-			    atombios_get_encoder_mode(encoder);
+			args.v3.ucEncoderMode = encoder_mode;
+			break;
+		case 5:
+			args.v5.ucCRTC = radeon_crtc->crtc_id;
+			args.v5.usPixelClock = cpu_to_le16(mode->clock / 10);
+			args.v5.ucRefDiv = ref_div;
+			args.v5.usFbDiv = cpu_to_le16(fb_div);
+			args.v5.ulFbDivDecFrac = cpu_to_le32(frac_fb_div * 100000);
+			args.v5.ucPostDiv = post_div;
+			args.v5.ucMiscInfo = 0; /* HDMI depth, etc. */
+			args.v5.ucTransmitterID = radeon_encoder->encoder_id;
+			args.v5.ucEncoderMode = encoder_mode;
+			args.v5.ucPpll = radeon_crtc->pll_id;
 			break;
 		default:
 			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
@@ -618,6 +729,140 @@
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y,
+				   struct drm_framebuffer *old_fb)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_framebuffer *radeon_fb;
+	struct drm_gem_object *obj;
+	struct radeon_bo *rbo;
+	uint64_t fb_location;
+	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
+	int r;
+
+	/* no fb bound */
+	if (!crtc->fb) {
+		DRM_DEBUG("No FB bound\n");
+		return 0;
+	}
+
+	radeon_fb = to_radeon_framebuffer(crtc->fb);
+
+	/* Pin framebuffer & get tilling informations */
+	obj = radeon_fb->obj;
+	rbo = obj->driver_private;
+	r = radeon_bo_reserve(rbo, false);
+	if (unlikely(r != 0))
+		return r;
+	r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
+	if (unlikely(r != 0)) {
+		radeon_bo_unreserve(rbo);
+		return -EINVAL;
+	}
+	radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
+	radeon_bo_unreserve(rbo);
+
+	switch (crtc->fb->bits_per_pixel) {
+	case 8:
+		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) |
+			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED));
+		break;
+	case 15:
+		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
+			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555));
+		break;
+	case 16:
+		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
+			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565));
+		break;
+	case 24:
+	case 32:
+		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
+			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));
+		break;
+	default:
+		DRM_ERROR("Unsupported screen depth %d\n",
+			  crtc->fb->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	switch (radeon_crtc->crtc_id) {
+	case 0:
+		WREG32(AVIVO_D1VGA_CONTROL, 0);
+		break;
+	case 1:
+		WREG32(AVIVO_D2VGA_CONTROL, 0);
+		break;
+	case 2:
+		WREG32(EVERGREEN_D3VGA_CONTROL, 0);
+		break;
+	case 3:
+		WREG32(EVERGREEN_D4VGA_CONTROL, 0);
+		break;
+	case 4:
+		WREG32(EVERGREEN_D5VGA_CONTROL, 0);
+		break;
+	case 5:
+		WREG32(EVERGREEN_D6VGA_CONTROL, 0);
+		break;
+	default:
+		break;
+	}
+
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
+	       upper_32_bits(fb_location));
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
+	       upper_32_bits(fb_location));
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+	       (u32)fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+	       (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
+	WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
+
+	WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
+	WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
+
+	fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
+	WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
+	WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
+
+	WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
+	       crtc->mode.vdisplay);
+	x &= ~3;
+	y &= ~1;
+	WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
+	       (x << 16) | y);
+	WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
+	       (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
+
+	if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
+		WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset,
+		       EVERGREEN_INTERLEAVE_EN);
+	else
+		WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
+
+	if (old_fb && old_fb != crtc->fb) {
+		radeon_fb = to_radeon_framebuffer(old_fb);
+		rbo = radeon_fb->obj->driver_private;
+		r = radeon_bo_reserve(rbo, false);
+		if (unlikely(r != 0))
+			return r;
+		radeon_bo_unpin(rbo);
+		radeon_bo_unreserve(rbo);
+	}
+
+	/* Bytes per pixel may have changed */
+	radeon_bandwidth_update(rdev);
+
+	return 0;
+}
+
 static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
 			       struct drm_framebuffer *old_fb)
 {
@@ -755,7 +1000,9 @@
 	struct drm_device *dev = crtc->dev;
 	struct radeon_device *rdev = dev->dev_private;
 
-	if (ASIC_IS_AVIVO(rdev))
+	if (ASIC_IS_DCE4(rdev))
+		return evergreen_crtc_set_base(crtc, x, y, old_fb);
+	else if (ASIC_IS_AVIVO(rdev))
 		return avivo_crtc_set_base(crtc, x, y, old_fb);
 	else
 		return radeon_crtc_set_base(crtc, x, y, old_fb);
@@ -785,6 +1032,46 @@
 	}
 }
 
+static int radeon_atom_pick_pll(struct drm_crtc *crtc)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_encoder *test_encoder;
+	struct drm_crtc *test_crtc;
+	uint32_t pll_in_use = 0;
+
+	if (ASIC_IS_DCE4(rdev)) {
+		/* if crtc is driving DP and we have an ext clock, use that */
+		list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {
+			if (test_encoder->crtc && (test_encoder->crtc == crtc)) {
+				if (atombios_get_encoder_mode(test_encoder) == ATOM_ENCODER_MODE_DP) {
+					if (rdev->clock.dp_extclk)
+						return ATOM_PPLL_INVALID;
+				}
+			}
+		}
+
+		/* otherwise, pick one of the plls */
+		list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) {
+			struct radeon_crtc *radeon_test_crtc;
+
+			if (crtc == test_crtc)
+				continue;
+
+			radeon_test_crtc = to_radeon_crtc(test_crtc);
+			if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) &&
+			    (radeon_test_crtc->pll_id <= ATOM_PPLL2))
+				pll_in_use |= (1 << radeon_test_crtc->pll_id);
+		}
+		if (!(pll_in_use & 1))
+			return ATOM_PPLL1;
+		return ATOM_PPLL2;
+	} else
+		return radeon_crtc->crtc_id;
+
+}
+
 int atombios_crtc_mode_set(struct drm_crtc *crtc,
 			   struct drm_display_mode *mode,
 			   struct drm_display_mode *adjusted_mode,
@@ -796,19 +1083,27 @@
 
 	/* TODO color tiling */
 
+	/* pick pll */
+	radeon_crtc->pll_id = radeon_atom_pick_pll(crtc);
+
 	atombios_set_ss(crtc, 0);
+	/* always set DCPLL */
+	if (ASIC_IS_DCE4(rdev))
+		atombios_crtc_set_dcpll(crtc);
 	atombios_crtc_set_pll(crtc, adjusted_mode);
 	atombios_set_ss(crtc, 1);
-	atombios_crtc_set_timing(crtc, adjusted_mode);
 
-	if (ASIC_IS_AVIVO(rdev))
-		atombios_crtc_set_base(crtc, x, y, old_fb);
+	if (ASIC_IS_DCE4(rdev))
+		atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
+	else if (ASIC_IS_AVIVO(rdev))
+		atombios_crtc_set_timing(crtc, adjusted_mode);
 	else {
+		atombios_crtc_set_timing(crtc, adjusted_mode);
 		if (radeon_crtc->crtc_id == 0)
 			atombios_set_crtc_dtd_timing(crtc, adjusted_mode);
-		atombios_crtc_set_base(crtc, x, y, old_fb);
 		radeon_legacy_atom_fixup(crtc);
 	}
+	atombios_crtc_set_base(crtc, x, y, old_fb);
 	atombios_overscan_setup(crtc, mode, adjusted_mode);
 	atombios_scaler_setup(crtc);
 	return 0;
@@ -825,14 +1120,14 @@
 
 static void atombios_crtc_prepare(struct drm_crtc *crtc)
 {
-	atombios_lock_crtc(crtc, 1);
+	atombios_lock_crtc(crtc, ATOM_ENABLE);
 	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 }
 
 static void atombios_crtc_commit(struct drm_crtc *crtc)
 {
 	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
-	atombios_lock_crtc(crtc, 0);
+	atombios_lock_crtc(crtc, ATOM_DISABLE);
 }
 
 static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
@@ -848,8 +1143,37 @@
 void radeon_atombios_init_crtc(struct drm_device *dev,
 			       struct radeon_crtc *radeon_crtc)
 {
-	if (radeon_crtc->crtc_id == 1)
-		radeon_crtc->crtc_offset =
-		    AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (ASIC_IS_DCE4(rdev)) {
+		switch (radeon_crtc->crtc_id) {
+		case 0:
+		default:
+			radeon_crtc->crtc_offset = EVERGREEN_CRTC0_REGISTER_OFFSET;
+			break;
+		case 1:
+			radeon_crtc->crtc_offset = EVERGREEN_CRTC1_REGISTER_OFFSET;
+			break;
+		case 2:
+			radeon_crtc->crtc_offset = EVERGREEN_CRTC2_REGISTER_OFFSET;
+			break;
+		case 3:
+			radeon_crtc->crtc_offset = EVERGREEN_CRTC3_REGISTER_OFFSET;
+			break;
+		case 4:
+			radeon_crtc->crtc_offset = EVERGREEN_CRTC4_REGISTER_OFFSET;
+			break;
+		case 5:
+			radeon_crtc->crtc_offset = EVERGREEN_CRTC5_REGISTER_OFFSET;
+			break;
+		}
+	} else {
+		if (radeon_crtc->crtc_id == 1)
+			radeon_crtc->crtc_offset =
+				AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
+		else
+			radeon_crtc->crtc_offset = 0;
+	}
+	radeon_crtc->pll_id = -1;
 	drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
 }
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 99915a6..8a133bd 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -321,6 +321,10 @@
 		train_set[lane] = v | p;
 }
 
+union aux_channel_transaction {
+	PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
+	PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
+};
 
 /* radeon aux chan functions */
 bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes,
@@ -329,7 +333,7 @@
 {
 	struct drm_device *dev = chan->dev;
 	struct radeon_device *rdev = dev->dev_private;
-	PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION args;
+	union aux_channel_transaction args;
 	int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
 	unsigned char *base;
 	int retry_count = 0;
@@ -341,31 +345,33 @@
 retry:
 	memcpy(base, req_bytes, num_bytes);
 
-	args.lpAuxRequest = 0;
-	args.lpDataOut = 16;
-	args.ucDataOutLen = 0;
-	args.ucChannelID = chan->rec.i2c_id;
-	args.ucDelay = delay / 10;
+	args.v1.lpAuxRequest = 0;
+	args.v1.lpDataOut = 16;
+	args.v1.ucDataOutLen = 0;
+	args.v1.ucChannelID = chan->rec.i2c_id;
+	args.v1.ucDelay = delay / 10;
+	if (ASIC_IS_DCE4(rdev))
+		args.v2.ucHPD_ID = chan->rec.hpd_id;
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 
-	if (args.ucReplyStatus && !args.ucDataOutLen) {
-		if (args.ucReplyStatus == 0x20 && retry_count++ < 10)
+	if (args.v1.ucReplyStatus && !args.v1.ucDataOutLen) {
+		if (args.v1.ucReplyStatus == 0x20 && retry_count++ < 10)
 			goto retry;
 		DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x after %d retries\n",
 			  req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3],
-			  chan->rec.i2c_id, args.ucReplyStatus, retry_count);
+			  chan->rec.i2c_id, args.v1.ucReplyStatus, retry_count);
 		return false;
 	}
 
-	if (args.ucDataOutLen && read_byte && read_buf_len) {
-		if (read_buf_len < args.ucDataOutLen) {
+	if (args.v1.ucDataOutLen && read_byte && read_buf_len) {
+		if (read_buf_len < args.v1.ucDataOutLen) {
 			DRM_ERROR("Buffer to small for return answer %d %d\n",
-				  read_buf_len, args.ucDataOutLen);
+				  read_buf_len, args.v1.ucDataOutLen);
 			return false;
 		}
 		{
-			int len = min(read_buf_len, args.ucDataOutLen);
+			int len = min(read_buf_len, args.v1.ucDataOutLen);
 			memcpy(read_byte, base + 16, len);
 		}
 	}
@@ -626,12 +632,19 @@
 	dp_set_link_bw_lanes(radeon_connector, link_configuration);
 	/* disable downspread on the sink */
 	dp_set_downspread(radeon_connector, 0);
-	/* start training on the source */
-	radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START,
-				  dig_connector->dp_clock, enc_id, 0);
-	/* set training pattern 1 on the source */
-	radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
-				  dig_connector->dp_clock, enc_id, 0);
+	if (ASIC_IS_DCE4(rdev)) {
+		/* start training on the source */
+		atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
+		/* set training pattern 1 on the source */
+		atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1);
+	} else {
+		/* start training on the source */
+		radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START,
+					  dig_connector->dp_clock, enc_id, 0);
+		/* set training pattern 1 on the source */
+		radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
+					  dig_connector->dp_clock, enc_id, 0);
+	}
 
 	/* set initial vs/emph */
 	memset(train_set, 0, 4);
@@ -691,8 +704,11 @@
 	/* set training pattern 2 on the sink */
 	dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2);
 	/* set training pattern 2 on the source */
-	radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
-				  dig_connector->dp_clock, enc_id, 1);
+	if (ASIC_IS_DCE4(rdev))
+		atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2);
+	else
+		radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL,
+					  dig_connector->dp_clock, enc_id, 1);
 
 	/* channel equalization loop */
 	tries = 0;
@@ -729,7 +745,11 @@
 			  >> DP_TRAIN_PRE_EMPHASIS_SHIFT);
 
 	/* disable the training pattern on the sink */
-	dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE);
+	if (ASIC_IS_DCE4(rdev))
+		atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
+	else
+		radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE,
+					  dig_connector->dp_clock, enc_id, 0);
 
 	radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE,
 				  dig_connector->dp_clock, enc_id, 0);
diff --git a/drivers/gpu/drm/radeon/avivod.h b/drivers/gpu/drm/radeon/avivod.h
index d4e6e6e..3c391e7 100644
--- a/drivers/gpu/drm/radeon/avivod.h
+++ b/drivers/gpu/drm/radeon/avivod.h
@@ -30,11 +30,13 @@
 
 #define	D1CRTC_CONTROL					0x6080
 #define		CRTC_EN						(1 << 0)
+#define	D1CRTC_STATUS					0x609c
 #define	D1CRTC_UPDATE_LOCK				0x60E8
 #define	D1GRPH_PRIMARY_SURFACE_ADDRESS			0x6110
 #define	D1GRPH_SECONDARY_SURFACE_ADDRESS		0x6118
 
 #define	D2CRTC_CONTROL					0x6880
+#define	D2CRTC_STATUS					0x689c
 #define	D2CRTC_UPDATE_LOCK				0x68E8
 #define	D2GRPH_PRIMARY_SURFACE_ADDRESS			0x6910
 #define	D2GRPH_SECONDARY_SURFACE_ADDRESS		0x6918
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
new file mode 100644
index 0000000..bd2e7aa
--- /dev/null
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -0,0 +1,767 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Alex Deucher
+ */
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+#include "drmP.h"
+#include "radeon.h"
+#include "radeon_drm.h"
+#include "rv770d.h"
+#include "atom.h"
+#include "avivod.h"
+#include "evergreen_reg.h"
+
+static void evergreen_gpu_init(struct radeon_device *rdev);
+void evergreen_fini(struct radeon_device *rdev);
+
+bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
+{
+	bool connected = false;
+	/* XXX */
+	return connected;
+}
+
+void evergreen_hpd_set_polarity(struct radeon_device *rdev,
+				enum radeon_hpd_id hpd)
+{
+	/* XXX */
+}
+
+void evergreen_hpd_init(struct radeon_device *rdev)
+{
+	/* XXX */
+}
+
+
+void evergreen_bandwidth_update(struct radeon_device *rdev)
+{
+	/* XXX */
+}
+
+void evergreen_hpd_fini(struct radeon_device *rdev)
+{
+	/* XXX */
+}
+
+static int evergreen_mc_wait_for_idle(struct radeon_device *rdev)
+{
+	unsigned i;
+	u32 tmp;
+
+	for (i = 0; i < rdev->usec_timeout; i++) {
+		/* read MC_STATUS */
+		tmp = RREG32(SRBM_STATUS) & 0x1F00;
+		if (!tmp)
+			return 0;
+		udelay(1);
+	}
+	return -1;
+}
+
+/*
+ * GART
+ */
+int evergreen_pcie_gart_enable(struct radeon_device *rdev)
+{
+	u32 tmp;
+	int r, i;
+
+	if (rdev->gart.table.vram.robj == NULL) {
+		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
+		return -EINVAL;
+	}
+	r = radeon_gart_table_vram_pin(rdev);
+	if (r)
+		return r;
+	radeon_gart_restore(rdev);
+	/* Setup L2 cache */
+	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
+				ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+				EFFECTIVE_L2_QUEUE_SIZE(7));
+	WREG32(VM_L2_CNTL2, 0);
+	WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
+	/* Setup TLB control */
+	tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
+		SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+		SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
+		EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
+	WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
+	WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
+	WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
+	WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
+	WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+	WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
+	WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
+				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
+	WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
+			(u32)(rdev->dummy_page.addr >> 12));
+	for (i = 1; i < 7; i++)
+		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
+
+	r600_pcie_gart_tlb_flush(rdev);
+	rdev->gart.ready = true;
+	return 0;
+}
+
+void evergreen_pcie_gart_disable(struct radeon_device *rdev)
+{
+	u32 tmp;
+	int i, r;
+
+	/* Disable all tables */
+	for (i = 0; i < 7; i++)
+		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
+
+	/* Setup L2 cache */
+	WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING |
+				EFFECTIVE_L2_QUEUE_SIZE(7));
+	WREG32(VM_L2_CNTL2, 0);
+	WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
+	/* Setup TLB control */
+	tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
+	WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
+	WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
+	WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
+	if (rdev->gart.table.vram.robj) {
+		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+		if (likely(r == 0)) {
+			radeon_bo_kunmap(rdev->gart.table.vram.robj);
+			radeon_bo_unpin(rdev->gart.table.vram.robj);
+			radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		}
+	}
+}
+
+void evergreen_pcie_gart_fini(struct radeon_device *rdev)
+{
+	evergreen_pcie_gart_disable(rdev);
+	radeon_gart_table_vram_free(rdev);
+	radeon_gart_fini(rdev);
+}
+
+
+void evergreen_agp_enable(struct radeon_device *rdev)
+{
+	u32 tmp;
+	int i;
+
+	/* Setup L2 cache */
+	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
+				ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+				EFFECTIVE_L2_QUEUE_SIZE(7));
+	WREG32(VM_L2_CNTL2, 0);
+	WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
+	/* Setup TLB control */
+	tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
+		SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+		SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
+		EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
+	WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
+	WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
+	WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
+	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
+	for (i = 0; i < 7; i++)
+		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
+}
+
+static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)
+{
+	save->vga_control[0] = RREG32(D1VGA_CONTROL);
+	save->vga_control[1] = RREG32(D2VGA_CONTROL);
+	save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL);
+	save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL);
+	save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL);
+	save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL);
+	save->vga_render_control = RREG32(VGA_RENDER_CONTROL);
+	save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
+	save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
+	save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
+	save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
+	save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
+	save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
+	save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
+
+	/* Stop all video */
+	WREG32(VGA_RENDER_CONTROL, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+
+	WREG32(D1VGA_CONTROL, 0);
+	WREG32(D2VGA_CONTROL, 0);
+	WREG32(EVERGREEN_D3VGA_CONTROL, 0);
+	WREG32(EVERGREEN_D4VGA_CONTROL, 0);
+	WREG32(EVERGREEN_D5VGA_CONTROL, 0);
+	WREG32(EVERGREEN_D6VGA_CONTROL, 0);
+}
+
+static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
+{
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET,
+	       upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET,
+	       (u32)rdev->mc.vram_start);
+
+	WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start));
+	WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start);
+	/* Unlock host access */
+	WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);
+	mdelay(1);
+	/* Restore video state */
+	WREG32(D1VGA_CONTROL, save->vga_control[0]);
+	WREG32(D2VGA_CONTROL, save->vga_control[1]);
+	WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]);
+	WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]);
+	WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]);
+	WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]);
+	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+	WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
+}
+
+static void evergreen_mc_program(struct radeon_device *rdev)
+{
+	struct evergreen_mc_save save;
+	u32 tmp;
+	int i, j;
+
+	/* Initialize HDP */
+	for (i = 0, j = 0; i < 32; i++, j += 0x18) {
+		WREG32((0x2c14 + j), 0x00000000);
+		WREG32((0x2c18 + j), 0x00000000);
+		WREG32((0x2c1c + j), 0x00000000);
+		WREG32((0x2c20 + j), 0x00000000);
+		WREG32((0x2c24 + j), 0x00000000);
+	}
+	WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
+
+	evergreen_mc_stop(rdev, &save);
+	if (evergreen_mc_wait_for_idle(rdev)) {
+		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+	}
+	/* Lockout access through VGA aperture*/
+	WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
+	/* Update configuration */
+	if (rdev->flags & RADEON_IS_AGP) {
+		if (rdev->mc.vram_start < rdev->mc.gtt_start) {
+			/* VRAM before AGP */
+			WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+				rdev->mc.vram_start >> 12);
+			WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+				rdev->mc.gtt_end >> 12);
+		} else {
+			/* VRAM after AGP */
+			WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+				rdev->mc.gtt_start >> 12);
+			WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+				rdev->mc.vram_end >> 12);
+		}
+	} else {
+		WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+			rdev->mc.vram_start >> 12);
+		WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+			rdev->mc.vram_end >> 12);
+	}
+	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+	tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
+	tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
+	WREG32(MC_VM_FB_LOCATION, tmp);
+	WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
+	WREG32(HDP_NONSURFACE_INFO, (2 << 7));
+	WREG32(HDP_NONSURFACE_SIZE, (rdev->mc.mc_vram_size - 1) | 0x3FF);
+	if (rdev->flags & RADEON_IS_AGP) {
+		WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
+		WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
+		WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22);
+	} else {
+		WREG32(MC_VM_AGP_BASE, 0);
+		WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF);
+		WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF);
+	}
+	if (evergreen_mc_wait_for_idle(rdev)) {
+		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+	}
+	evergreen_mc_resume(rdev, &save);
+	/* we need to own VRAM, so turn off the VGA renderer here
+	 * to stop it overwriting our objects */
+	rv515_vga_render_disable(rdev);
+}
+
+#if 0
+/*
+ * CP.
+ */
+static void evergreen_cp_stop(struct radeon_device *rdev)
+{
+	/* XXX */
+}
+
+
+static int evergreen_cp_load_microcode(struct radeon_device *rdev)
+{
+	/* XXX */
+
+	return 0;
+}
+
+
+/*
+ * Core functions
+ */
+static u32 evergreen_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
+						  u32 num_backends,
+						  u32 backend_disable_mask)
+{
+	u32 backend_map = 0;
+
+	return backend_map;
+}
+#endif
+
+static void evergreen_gpu_init(struct radeon_device *rdev)
+{
+	/* XXX */
+}
+
+int evergreen_mc_init(struct radeon_device *rdev)
+{
+	fixed20_12 a;
+	u32 tmp;
+	int chansize, numchan;
+
+	/* Get VRAM informations */
+	rdev->mc.vram_is_ddr = true;
+	tmp = RREG32(MC_ARB_RAMCFG);
+	if (tmp & CHANSIZE_OVERRIDE) {
+		chansize = 16;
+	} else if (tmp & CHANSIZE_MASK) {
+		chansize = 64;
+	} else {
+		chansize = 32;
+	}
+	tmp = RREG32(MC_SHARED_CHMAP);
+	switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
+	case 0:
+	default:
+		numchan = 1;
+		break;
+	case 1:
+		numchan = 2;
+		break;
+	case 2:
+		numchan = 4;
+		break;
+	case 3:
+		numchan = 8;
+		break;
+	}
+	rdev->mc.vram_width = numchan * chansize;
+	/* Could aper size report 0 ? */
+	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
+	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+	/* Setup GPU memory space */
+	/* size in MB on evergreen */
+	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
+	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
+	rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	/* FIXME remove this once we support unmappable VRAM */
+	if (rdev->mc.mc_vram_size > rdev->mc.aper_size) {
+		rdev->mc.mc_vram_size = rdev->mc.aper_size;
+		rdev->mc.real_vram_size = rdev->mc.aper_size;
+	}
+	r600_vram_gtt_location(rdev, &rdev->mc);
+	/* FIXME: we should enforce default clock in case GPU is not in
+	 * default setup
+	 */
+	a.full = rfixed_const(100);
+	rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
+	rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+	return 0;
+}
+
+int evergreen_gpu_reset(struct radeon_device *rdev)
+{
+	/* FIXME: implement for evergreen */
+	return 0;
+}
+
+static int evergreen_startup(struct radeon_device *rdev)
+{
+#if 0
+	int r;
+
+	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
+		r = r600_init_microcode(rdev);
+		if (r) {
+			DRM_ERROR("Failed to load firmware!\n");
+			return r;
+		}
+	}
+#endif
+	evergreen_mc_program(rdev);
+#if 0
+	if (rdev->flags & RADEON_IS_AGP) {
+		evergreem_agp_enable(rdev);
+	} else {
+		r = evergreen_pcie_gart_enable(rdev);
+		if (r)
+			return r;
+	}
+#endif
+	evergreen_gpu_init(rdev);
+#if 0
+	if (!rdev->r600_blit.shader_obj) {
+		r = r600_blit_init(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failed blitter (%d).\n", r);
+			return r;
+		}
+	}
+
+	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+	if (unlikely(r != 0))
+		return r;
+	r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
+			&rdev->r600_blit.shader_gpu_addr);
+	radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+	if (r) {
+		DRM_ERROR("failed to pin blit object %d\n", r);
+		return r;
+	}
+
+	/* Enable IRQ */
+	r = r600_irq_init(rdev);
+	if (r) {
+		DRM_ERROR("radeon: IH init failed (%d).\n", r);
+		radeon_irq_kms_fini(rdev);
+		return r;
+	}
+	r600_irq_set(rdev);
+
+	r = radeon_ring_init(rdev, rdev->cp.ring_size);
+	if (r)
+		return r;
+	r = evergreen_cp_load_microcode(rdev);
+	if (r)
+		return r;
+	r = r600_cp_resume(rdev);
+	if (r)
+		return r;
+	/* write back buffer are not vital so don't worry about failure */
+	r600_wb_enable(rdev);
+#endif
+	return 0;
+}
+
+int evergreen_resume(struct radeon_device *rdev)
+{
+	int r;
+
+	/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
+	 * posting will perform necessary task to bring back GPU into good
+	 * shape.
+	 */
+	/* post card */
+	atom_asic_init(rdev->mode_info.atom_context);
+	/* Initialize clocks */
+	r = radeon_clocks_init(rdev);
+	if (r) {
+		return r;
+	}
+
+	r = evergreen_startup(rdev);
+	if (r) {
+		DRM_ERROR("r600 startup failed on resume\n");
+		return r;
+	}
+#if 0
+	r = r600_ib_test(rdev);
+	if (r) {
+		DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+		return r;
+	}
+#endif
+	return r;
+
+}
+
+int evergreen_suspend(struct radeon_device *rdev)
+{
+#if 0
+	int r;
+
+	/* FIXME: we should wait for ring to be empty */
+	r700_cp_stop(rdev);
+	rdev->cp.ready = false;
+	r600_wb_disable(rdev);
+	evergreen_pcie_gart_disable(rdev);
+	/* unpin shaders bo */
+	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+	if (likely(r == 0)) {
+		radeon_bo_unpin(rdev->r600_blit.shader_obj);
+		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+	}
+#endif
+	return 0;
+}
+
+static bool evergreen_card_posted(struct radeon_device *rdev)
+{
+	u32 reg;
+
+	/* first check CRTCs */
+	reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
+		RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) |
+		RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) |
+		RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) |
+		RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) |
+		RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
+	if (reg & EVERGREEN_CRTC_MASTER_EN)
+		return true;
+
+	/* then check MEM_SIZE, in case the crtcs are off */
+	if (RREG32(CONFIG_MEMSIZE))
+		return true;
+
+	return false;
+}
+
+/* Plan is to move initialization in that function and use
+ * helper function so that radeon_device_init pretty much
+ * do nothing more than calling asic specific function. This
+ * should also allow to remove a bunch of callback function
+ * like vram_info.
+ */
+int evergreen_init(struct radeon_device *rdev)
+{
+	int r;
+
+	r = radeon_dummy_page_init(rdev);
+	if (r)
+		return r;
+	/* This don't do much */
+	r = radeon_gem_init(rdev);
+	if (r)
+		return r;
+	/* Read BIOS */
+	if (!radeon_get_bios(rdev)) {
+		if (ASIC_IS_AVIVO(rdev))
+			return -EINVAL;
+	}
+	/* Must be an ATOMBIOS */
+	if (!rdev->is_atom_bios) {
+		dev_err(rdev->dev, "Expecting atombios for R600 GPU\n");
+		return -EINVAL;
+	}
+	r = radeon_atombios_init(rdev);
+	if (r)
+		return r;
+	/* Post card if necessary */
+	if (!evergreen_card_posted(rdev)) {
+		if (!rdev->bios) {
+			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
+			return -EINVAL;
+		}
+		DRM_INFO("GPU not posted. posting now...\n");
+		atom_asic_init(rdev->mode_info.atom_context);
+	}
+	/* Initialize scratch registers */
+	r600_scratch_init(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
+	/* Initialize clocks */
+	radeon_get_clock_info(rdev->ddev);
+	r = radeon_clocks_init(rdev);
+	if (r)
+		return r;
+	/* Initialize power management */
+	radeon_pm_init(rdev);
+	/* Fence driver */
+	r = radeon_fence_driver_init(rdev);
+	if (r)
+		return r;
+	/* initialize AGP */
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r)
+			radeon_agp_disable(rdev);
+	}
+	/* initialize memory controller */
+	r = evergreen_mc_init(rdev);
+	if (r)
+		return r;
+	/* Memory manager */
+	r = radeon_bo_init(rdev);
+	if (r)
+		return r;
+#if 0
+	r = radeon_irq_kms_init(rdev);
+	if (r)
+		return r;
+
+	rdev->cp.ring_obj = NULL;
+	r600_ring_init(rdev, 1024 * 1024);
+
+	rdev->ih.ring_obj = NULL;
+	r600_ih_ring_init(rdev, 64 * 1024);
+
+	r = r600_pcie_gart_init(rdev);
+	if (r)
+		return r;
+#endif
+	rdev->accel_working = false;
+	r = evergreen_startup(rdev);
+	if (r) {
+		evergreen_suspend(rdev);
+		/*r600_wb_fini(rdev);*/
+		/*radeon_ring_fini(rdev);*/
+		/*evergreen_pcie_gart_fini(rdev);*/
+		rdev->accel_working = false;
+	}
+	if (rdev->accel_working) {
+		r = radeon_ib_pool_init(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r);
+			rdev->accel_working = false;
+		}
+		r = r600_ib_test(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failed testing IB (%d).\n", r);
+			rdev->accel_working = false;
+		}
+	}
+	return 0;
+}
+
+void evergreen_fini(struct radeon_device *rdev)
+{
+	evergreen_suspend(rdev);
+#if 0
+	r600_blit_fini(rdev);
+	r600_irq_fini(rdev);
+	radeon_irq_kms_fini(rdev);
+	radeon_ring_fini(rdev);
+	r600_wb_fini(rdev);
+	evergreen_pcie_gart_fini(rdev);
+#endif
+	radeon_gem_fini(rdev);
+	radeon_fence_driver_fini(rdev);
+	radeon_clocks_fini(rdev);
+	radeon_agp_fini(rdev);
+	radeon_bo_fini(rdev);
+	radeon_atombios_fini(rdev);
+	kfree(rdev->bios);
+	rdev->bios = NULL;
+	radeon_dummy_page_fini(rdev);
+}
diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h
new file mode 100644
index 0000000..f7c7c96
--- /dev/null
+++ b/drivers/gpu/drm/radeon/evergreen_reg.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Alex Deucher
+ */
+#ifndef __EVERGREEN_REG_H__
+#define __EVERGREEN_REG_H__
+
+/* evergreen */
+#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS               0x310
+#define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH          0x324
+#define EVERGREEN_D3VGA_CONTROL                         0x3e0
+#define EVERGREEN_D4VGA_CONTROL                         0x3e4
+#define EVERGREEN_D5VGA_CONTROL                         0x3e8
+#define EVERGREEN_D6VGA_CONTROL                         0x3ec
+
+#define EVERGREEN_P1PLL_SS_CNTL                         0x414
+#define EVERGREEN_P2PLL_SS_CNTL                         0x454
+#       define EVERGREEN_PxPLL_SS_EN                    (1 << 12)
+/* GRPH blocks at 0x6800, 0x7400, 0x10000, 0x10c00, 0x11800, 0x12400 */
+#define EVERGREEN_GRPH_ENABLE                           0x6800
+#define EVERGREEN_GRPH_CONTROL                          0x6804
+#       define EVERGREEN_GRPH_DEPTH(x)                  (((x) & 0x3) << 0)
+#       define EVERGREEN_GRPH_DEPTH_8BPP                0
+#       define EVERGREEN_GRPH_DEPTH_16BPP               1
+#       define EVERGREEN_GRPH_DEPTH_32BPP               2
+#       define EVERGREEN_GRPH_FORMAT(x)                 (((x) & 0x7) << 8)
+/* 8 BPP */
+#       define EVERGREEN_GRPH_FORMAT_INDEXED            0
+/* 16 BPP */
+#       define EVERGREEN_GRPH_FORMAT_ARGB1555           0
+#       define EVERGREEN_GRPH_FORMAT_ARGB565            1
+#       define EVERGREEN_GRPH_FORMAT_ARGB4444           2
+#       define EVERGREEN_GRPH_FORMAT_AI88               3
+#       define EVERGREEN_GRPH_FORMAT_MONO16             4
+#       define EVERGREEN_GRPH_FORMAT_BGRA5551           5
+/* 32 BPP */
+#       define EVERGREEN_GRPH_FORMAT_ARGB8888           0
+#       define EVERGREEN_GRPH_FORMAT_ARGB2101010        1
+#       define EVERGREEN_GRPH_FORMAT_32BPP_DIG          2
+#       define EVERGREEN_GRPH_FORMAT_8B_ARGB2101010     3
+#       define EVERGREEN_GRPH_FORMAT_BGRA1010102        4
+#       define EVERGREEN_GRPH_FORMAT_8B_BGRA1010102     5
+#       define EVERGREEN_GRPH_FORMAT_RGB111110          6
+#       define EVERGREEN_GRPH_FORMAT_BGR101111          7
+#define EVERGREEN_GRPH_SWAP_CONTROL                     0x680c
+#       define EVERGREEN_GRPH_ENDIAN_SWAP(x)            (((x) & 0x3) << 0)
+#       define EVERGREEN_GRPH_ENDIAN_NONE               0
+#       define EVERGREEN_GRPH_ENDIAN_8IN16              1
+#       define EVERGREEN_GRPH_ENDIAN_8IN32              2
+#       define EVERGREEN_GRPH_ENDIAN_8IN64              3
+#       define EVERGREEN_GRPH_RED_CROSSBAR(x)           (((x) & 0x3) << 4)
+#       define EVERGREEN_GRPH_RED_SEL_R                 0
+#       define EVERGREEN_GRPH_RED_SEL_G                 1
+#       define EVERGREEN_GRPH_RED_SEL_B                 2
+#       define EVERGREEN_GRPH_RED_SEL_A                 3
+#       define EVERGREEN_GRPH_GREEN_CROSSBAR(x)         (((x) & 0x3) << 6)
+#       define EVERGREEN_GRPH_GREEN_SEL_G               0
+#       define EVERGREEN_GRPH_GREEN_SEL_B               1
+#       define EVERGREEN_GRPH_GREEN_SEL_A               2
+#       define EVERGREEN_GRPH_GREEN_SEL_R               3
+#       define EVERGREEN_GRPH_BLUE_CROSSBAR(x)          (((x) & 0x3) << 8)
+#       define EVERGREEN_GRPH_BLUE_SEL_B                0
+#       define EVERGREEN_GRPH_BLUE_SEL_A                1
+#       define EVERGREEN_GRPH_BLUE_SEL_R                2
+#       define EVERGREEN_GRPH_BLUE_SEL_G                3
+#       define EVERGREEN_GRPH_ALPHA_CROSSBAR(x)         (((x) & 0x3) << 10)
+#       define EVERGREEN_GRPH_ALPHA_SEL_A               0
+#       define EVERGREEN_GRPH_ALPHA_SEL_R               1
+#       define EVERGREEN_GRPH_ALPHA_SEL_G               2
+#       define EVERGREEN_GRPH_ALPHA_SEL_B               3
+#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS          0x6810
+#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS        0x6814
+#       define EVERGREEN_GRPH_DFQ_ENABLE                (1 << 0)
+#       define EVERGREEN_GRPH_SURFACE_ADDRESS_MASK      0xffffff00
+#define EVERGREEN_GRPH_PITCH                            0x6818
+#define EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH     0x681c
+#define EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH   0x6820
+#define EVERGREEN_GRPH_SURFACE_OFFSET_X                 0x6824
+#define EVERGREEN_GRPH_SURFACE_OFFSET_Y                 0x6828
+#define EVERGREEN_GRPH_X_START                          0x682c
+#define EVERGREEN_GRPH_Y_START                          0x6830
+#define EVERGREEN_GRPH_X_END                            0x6834
+#define EVERGREEN_GRPH_Y_END                            0x6838
+
+/* CUR blocks at 0x6998, 0x7598, 0x10198, 0x10d98, 0x11998, 0x12598 */
+#define EVERGREEN_CUR_CONTROL                           0x6998
+#       define EVERGREEN_CURSOR_EN                      (1 << 0)
+#       define EVERGREEN_CURSOR_MODE(x)                 (((x) & 0x3) << 8)
+#       define EVERGREEN_CURSOR_MONO                    0
+#       define EVERGREEN_CURSOR_24_1                    1
+#       define EVERGREEN_CURSOR_24_8_PRE_MULT           2
+#       define EVERGREEN_CURSOR_24_8_UNPRE_MULT         3
+#       define EVERGREEN_CURSOR_2X_MAGNIFY              (1 << 16)
+#       define EVERGREEN_CURSOR_FORCE_MC_ON             (1 << 20)
+#       define EVERGREEN_CURSOR_URGENT_CONTROL(x)       (((x) & 0x7) << 24)
+#       define EVERGREEN_CURSOR_URGENT_ALWAYS           0
+#       define EVERGREEN_CURSOR_URGENT_1_8              1
+#       define EVERGREEN_CURSOR_URGENT_1_4              2
+#       define EVERGREEN_CURSOR_URGENT_3_8              3
+#       define EVERGREEN_CURSOR_URGENT_1_2              4
+#define EVERGREEN_CUR_SURFACE_ADDRESS                   0x699c
+#       define EVERGREEN_CUR_SURFACE_ADDRESS_MASK       0xfffff000
+#define EVERGREEN_CUR_SIZE                              0x69a0
+#define EVERGREEN_CUR_SURFACE_ADDRESS_HIGH              0x69a4
+#define EVERGREEN_CUR_POSITION                          0x69a8
+#define EVERGREEN_CUR_HOT_SPOT                          0x69ac
+#define EVERGREEN_CUR_COLOR1                            0x69b0
+#define EVERGREEN_CUR_COLOR2                            0x69b4
+#define EVERGREEN_CUR_UPDATE                            0x69b8
+#       define EVERGREEN_CURSOR_UPDATE_PENDING          (1 << 0)
+#       define EVERGREEN_CURSOR_UPDATE_TAKEN            (1 << 1)
+#       define EVERGREEN_CURSOR_UPDATE_LOCK             (1 << 16)
+#       define EVERGREEN_CURSOR_DISABLE_MULTIPLE_UPDATE (1 << 24)
+
+/* LUT blocks at 0x69e0, 0x75e0, 0x101e0, 0x10de0, 0x119e0, 0x125e0 */
+#define EVERGREEN_DC_LUT_RW_MODE                        0x69e0
+#define EVERGREEN_DC_LUT_RW_INDEX                       0x69e4
+#define EVERGREEN_DC_LUT_SEQ_COLOR                      0x69e8
+#define EVERGREEN_DC_LUT_PWL_DATA                       0x69ec
+#define EVERGREEN_DC_LUT_30_COLOR                       0x69f0
+#define EVERGREEN_DC_LUT_VGA_ACCESS_ENABLE              0x69f4
+#define EVERGREEN_DC_LUT_WRITE_EN_MASK                  0x69f8
+#define EVERGREEN_DC_LUT_AUTOFILL                       0x69fc
+#define EVERGREEN_DC_LUT_CONTROL                        0x6a00
+#define EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE              0x6a04
+#define EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN             0x6a08
+#define EVERGREEN_DC_LUT_BLACK_OFFSET_RED               0x6a0c
+#define EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE              0x6a10
+#define EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN             0x6a14
+#define EVERGREEN_DC_LUT_WHITE_OFFSET_RED               0x6a18
+
+#define EVERGREEN_DATA_FORMAT                           0x6b00
+#       define EVERGREEN_INTERLEAVE_EN                  (1 << 0)
+#define EVERGREEN_DESKTOP_HEIGHT                        0x6b04
+
+#define EVERGREEN_VIEWPORT_START                        0x6d70
+#define EVERGREEN_VIEWPORT_SIZE                         0x6d74
+
+/* display controller offsets used for crtc/cur/lut/grph/viewport/etc. */
+#define EVERGREEN_CRTC0_REGISTER_OFFSET                 (0x6df0 - 0x6df0)
+#define EVERGREEN_CRTC1_REGISTER_OFFSET                 (0x79f0 - 0x6df0)
+#define EVERGREEN_CRTC2_REGISTER_OFFSET                 (0x105f0 - 0x6df0)
+#define EVERGREEN_CRTC3_REGISTER_OFFSET                 (0x111f0 - 0x6df0)
+#define EVERGREEN_CRTC4_REGISTER_OFFSET                 (0x11df0 - 0x6df0)
+#define EVERGREEN_CRTC5_REGISTER_OFFSET                 (0x129f0 - 0x6df0)
+
+/* CRTC blocks at 0x6df0, 0x79f0, 0x105f0, 0x111f0, 0x11df0, 0x129f0 */
+#define EVERGREEN_CRTC_CONTROL                          0x6e70
+#       define EVERGREEN_CRTC_MASTER_EN                 (1 << 0)
+#define EVERGREEN_CRTC_UPDATE_LOCK                      0x6ed4
+
+#define EVERGREEN_DC_GPIO_HPD_MASK                      0x64b0
+#define EVERGREEN_DC_GPIO_HPD_A                         0x64b4
+#define EVERGREEN_DC_GPIO_HPD_EN                        0x64b8
+#define EVERGREEN_DC_GPIO_HPD_Y                         0x64bc
+
+#endif
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index c0d4650..91eb762 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -197,13 +197,13 @@
 {
 	uint32_t tmp;
 
+	radeon_gart_restore(rdev);
 	/* discard memory request outside of configured range */
 	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
 	WREG32(RADEON_AIC_CNTL, tmp);
 	/* set address range for PCI address translate */
-	WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location);
-	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
-	WREG32(RADEON_AIC_HI_ADDR, tmp);
+	WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_start);
+	WREG32(RADEON_AIC_HI_ADDR, rdev->mc.gtt_end);
 	/* set PCI GART page-table base address */
 	WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr);
 	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
@@ -312,9 +312,11 @@
 		/* Vertical blank interrupts */
 		if (status & RADEON_CRTC_VBLANK_STAT) {
 			drm_handle_vblank(rdev->ddev, 0);
+			wake_up(&rdev->irq.vblank_queue);
 		}
 		if (status & RADEON_CRTC2_VBLANK_STAT) {
 			drm_handle_vblank(rdev->ddev, 1);
+			wake_up(&rdev->irq.vblank_queue);
 		}
 		if (status & RADEON_FP_DETECT_STAT) {
 			queue_hotplug = true;
@@ -366,8 +368,8 @@
 	radeon_ring_write(rdev, PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));
 	radeon_ring_write(rdev, RADEON_RB3D_ZC_FLUSH_ALL);
 	/* Wait until IDLE & CLEAN */
-	radeon_ring_write(rdev, PACKET0(0x1720, 0));
-	radeon_ring_write(rdev, (1 << 16) | (1 << 17));
+	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
+	radeon_ring_write(rdev, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
 	radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
 	radeon_ring_write(rdev, rdev->config.r100.hdp_cntl |
 				RADEON_HDP_READ_BUFFER_INVALIDATE);
@@ -1701,7 +1703,7 @@
 	}
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		tmp = RREG32(RADEON_RBBM_STATUS);
-		if (!(tmp & (1 << 31))) {
+		if (!(tmp & RADEON_RBBM_ACTIVE)) {
 			return 0;
 		}
 		DRM_UDELAY(1);
@@ -1716,8 +1718,8 @@
 
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		/* read MC_STATUS */
-		tmp = RREG32(0x0150);
-		if (tmp & (1 << 2)) {
+		tmp = RREG32(RADEON_MC_STATUS);
+		if (tmp & RADEON_MC_IDLE) {
 			return 0;
 		}
 		DRM_UDELAY(1);
@@ -1790,7 +1792,7 @@
 	}
 	/* Check if GPU is idle */
 	status = RREG32(RADEON_RBBM_STATUS);
-	if (status & (1 << 31)) {
+	if (status & RADEON_RBBM_ACTIVE) {
 		DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
 		return -1;
 	}
@@ -1800,6 +1802,9 @@
 
 void r100_set_common_regs(struct radeon_device *rdev)
 {
+	struct drm_device *dev = rdev->ddev;
+	bool force_dac2 = false;
+
 	/* set these so they don't interfere with anything */
 	WREG32(RADEON_OV0_SCALE_CNTL, 0);
 	WREG32(RADEON_SUBPIC_CNTL, 0);
@@ -1808,6 +1813,68 @@
 	WREG32(RADEON_DVI_I2C_CNTL_1, 0);
 	WREG32(RADEON_CAP0_TRIG_CNTL, 0);
 	WREG32(RADEON_CAP1_TRIG_CNTL, 0);
+
+	/* always set up dac2 on rn50 and some rv100 as lots
+	 * of servers seem to wire it up to a VGA port but
+	 * don't report it in the bios connector
+	 * table.
+	 */
+	switch (dev->pdev->device) {
+		/* RN50 */
+	case 0x515e:
+	case 0x5969:
+		force_dac2 = true;
+		break;
+		/* RV100*/
+	case 0x5159:
+	case 0x515a:
+		/* DELL triple head servers */
+		if ((dev->pdev->subsystem_vendor == 0x1028 /* DELL */) &&
+		    ((dev->pdev->subsystem_device == 0x016c) ||
+		     (dev->pdev->subsystem_device == 0x016d) ||
+		     (dev->pdev->subsystem_device == 0x016e) ||
+		     (dev->pdev->subsystem_device == 0x016f) ||
+		     (dev->pdev->subsystem_device == 0x0170) ||
+		     (dev->pdev->subsystem_device == 0x017d) ||
+		     (dev->pdev->subsystem_device == 0x017e) ||
+		     (dev->pdev->subsystem_device == 0x0183) ||
+		     (dev->pdev->subsystem_device == 0x018a) ||
+		     (dev->pdev->subsystem_device == 0x019a)))
+			force_dac2 = true;
+		break;
+	}
+
+	if (force_dac2) {
+		u32 disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
+		u32 tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
+		u32 dac2_cntl = RREG32(RADEON_DAC_CNTL2);
+
+		/* For CRT on DAC2, don't turn it on if BIOS didn't
+		   enable it, even it's detected.
+		*/
+
+		/* force it to crtc0 */
+		dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
+		dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
+		disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
+
+		/* set up the TV DAC */
+		tv_dac_cntl &= ~(RADEON_TV_DAC_PEDESTAL |
+				 RADEON_TV_DAC_STD_MASK |
+				 RADEON_TV_DAC_RDACPD |
+				 RADEON_TV_DAC_GDACPD |
+				 RADEON_TV_DAC_BDACPD |
+				 RADEON_TV_DAC_BGADJ_MASK |
+				 RADEON_TV_DAC_DACADJ_MASK);
+		tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
+				RADEON_TV_DAC_NHOLD |
+				RADEON_TV_DAC_STD_PS2 |
+				(0x58 << 16));
+
+		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
+		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
+	}
 }
 
 /*
@@ -1889,17 +1956,20 @@
 void r100_vram_init_sizes(struct radeon_device *rdev)
 {
 	u64 config_aper_size;
-	u32 accessible;
 
+	/* work out accessible VRAM */
+	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
+	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+	rdev->mc.visible_vram_size = r100_get_accessible_vram(rdev);
+	/* FIXME we don't use the second aperture yet when we could use it */
+	if (rdev->mc.visible_vram_size > rdev->mc.aper_size)
+		rdev->mc.visible_vram_size = rdev->mc.aper_size;
 	config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
-
 	if (rdev->flags & RADEON_IS_IGP) {
 		uint32_t tom;
 		/* read NB_TOM to get the amount of ram stolen for the GPU */
 		tom = RREG32(RADEON_NB_TOM);
 		rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
-		/* for IGPs we need to keep VRAM where it was put by the BIOS */
-		rdev->mc.vram_location = (tom & 0xffff) << 16;
 		WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
 		rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
 	} else {
@@ -1911,30 +1981,19 @@
 			rdev->mc.real_vram_size = 8192 * 1024;
 			WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
 		}
-		/* let driver place VRAM */
-		rdev->mc.vram_location = 0xFFFFFFFFUL;
-		 /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - 
-		  * Novell bug 204882 + along with lots of ubuntu ones */
+		/* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - 
+		 * Novell bug 204882 + along with lots of ubuntu ones
+		 */
 		if (config_aper_size > rdev->mc.real_vram_size)
 			rdev->mc.mc_vram_size = config_aper_size;
 		else
 			rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
 	}
-
-	/* work out accessible VRAM */
-	accessible = r100_get_accessible_vram(rdev);
-
-	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
-	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
-
-	if (accessible > rdev->mc.aper_size)
-		accessible = rdev->mc.aper_size;
-
-	if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
+	/* FIXME remove this once we support unmappable VRAM */
+	if (rdev->mc.mc_vram_size > rdev->mc.aper_size) {
 		rdev->mc.mc_vram_size = rdev->mc.aper_size;
-
-	if (rdev->mc.real_vram_size > rdev->mc.aper_size)
 		rdev->mc.real_vram_size = rdev->mc.aper_size;
+	}
 }
 
 void r100_vga_set_state(struct radeon_device *rdev, bool state)
@@ -1951,11 +2010,18 @@
 	WREG32(RADEON_CONFIG_CNTL, temp);
 }
 
-void r100_vram_info(struct radeon_device *rdev)
+void r100_mc_init(struct radeon_device *rdev)
 {
-	r100_vram_get_type(rdev);
+	u64 base;
 
+	r100_vram_get_type(rdev);
 	r100_vram_init_sizes(rdev);
+	base = rdev->mc.aper_base;
+	if (rdev->flags & RADEON_IS_IGP)
+		base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
+	radeon_vram_location(rdev, &rdev->mc, base);
+	if (!(rdev->flags & RADEON_IS_AGP))
+		radeon_gtt_location(rdev, &rdev->mc);
 }
 
 
@@ -3226,10 +3292,9 @@
 void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save)
 {
 	/* Update base address for crtc */
-	WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_location);
+	WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_start);
 	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
-		WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR,
-				rdev->mc.vram_location);
+		WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR, rdev->mc.vram_start);
 	}
 	/* Restore CRTC registers */
 	WREG8(R_0003C2_GENMO_WT, save->GENMO_WT);
@@ -3390,32 +3455,6 @@
 	rdev->bios = NULL;
 }
 
-int r100_mc_init(struct radeon_device *rdev)
-{
-	int r;
-	u32 tmp;
-
-	/* Setup GPU memory space */
-	rdev->mc.vram_location = 0xFFFFFFFFUL;
-	rdev->mc.gtt_location = 0xFFFFFFFFUL;
-	if (rdev->flags & RADEON_IS_IGP) {
-		tmp = G_00015C_MC_FB_START(RREG32(R_00015C_NB_TOM));
-		rdev->mc.vram_location = tmp << 16;
-	}
-	if (rdev->flags & RADEON_IS_AGP) {
-		r = radeon_agp_init(rdev);
-		if (r) {
-			radeon_agp_disable(rdev);
-		} else {
-			rdev->mc.gtt_location = rdev->mc.agp_base;
-		}
-	}
-	r = radeon_mc_setup(rdev);
-	if (r)
-		return r;
-	return 0;
-}
-
 int r100_init(struct radeon_device *rdev)
 {
 	int r;
@@ -3458,12 +3497,15 @@
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
 	radeon_pm_init(rdev);
-	/* Get vram informations */
-	r100_vram_info(rdev);
-	/* Initialize memory controller (also test AGP) */
-	r = r100_mc_init(rdev);
-	if (r)
-		return r;
+	/* initialize AGP */
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r) {
+			radeon_agp_disable(rdev);
+		}
+	}
+	/* initialize VRAM */
+	r100_mc_init(rdev);
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
 	if (r)
diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c
index ff1e0cd..1146c99 100644
--- a/drivers/gpu/drm/radeon/r200.c
+++ b/drivers/gpu/drm/radeon/r200.c
@@ -31,6 +31,7 @@
 #include "radeon_reg.h"
 #include "radeon.h"
 
+#include "r100d.h"
 #include "r200_reg_safe.h"
 
 #include "r100_track.h"
@@ -79,6 +80,51 @@
 	return vtx_size;
 }
 
+int r200_copy_dma(struct radeon_device *rdev,
+		  uint64_t src_offset,
+		  uint64_t dst_offset,
+		  unsigned num_pages,
+		  struct radeon_fence *fence)
+{
+	uint32_t size;
+	uint32_t cur_size;
+	int i, num_loops;
+	int r = 0;
+
+	/* radeon pitch is /64 */
+	size = num_pages << PAGE_SHIFT;
+	num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
+	r = radeon_ring_lock(rdev, num_loops * 4 + 64);
+	if (r) {
+		DRM_ERROR("radeon: moving bo (%d).\n", r);
+		return r;
+	}
+	/* Must wait for 2D idle & clean before DMA or hangs might happen */
+	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
+	radeon_ring_write(rdev, (1 << 16));
+	for (i = 0; i < num_loops; i++) {
+		cur_size = size;
+		if (cur_size > 0x1FFFFF) {
+			cur_size = 0x1FFFFF;
+		}
+		size -= cur_size;
+		radeon_ring_write(rdev, PACKET0(0x720, 2));
+		radeon_ring_write(rdev, src_offset);
+		radeon_ring_write(rdev, dst_offset);
+		radeon_ring_write(rdev, cur_size | (1 << 31) | (1 << 30));
+		src_offset += cur_size;
+		dst_offset += cur_size;
+	}
+	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
+	radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE);
+	if (fence) {
+		r = radeon_fence_emit(rdev, fence);
+	}
+	radeon_ring_unlock_commit(rdev);
+	return r;
+}
+
+
 static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
 {
 	int vtx_size, i, tex_size;
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 43b55a0..4cef90c 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -117,18 +117,19 @@
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
+	radeon_gart_restore(rdev);
 	/* discard memory request outside of configured range */
 	tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
 	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
-	WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_location);
-	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - RADEON_GPU_PAGE_SIZE;
+	WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_start);
+	tmp = rdev->mc.gtt_end & ~RADEON_GPU_PAGE_MASK;
 	WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp);
 	WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
 	WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
 	table_addr = rdev->gart.table_addr;
 	WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr);
 	/* FIXME: setup default page */
-	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_location);
+	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start);
 	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0);
 	/* Clear error */
 	WREG32_PCIE(0x18, 0);
@@ -174,18 +175,20 @@
 	/* Who ever call radeon_fence_emit should call ring_lock and ask
 	 * for enough space (today caller are ib schedule and buffer move) */
 	/* Write SC register so SC & US assert idle */
-	radeon_ring_write(rdev, PACKET0(0x43E0, 0));
+	radeon_ring_write(rdev, PACKET0(R300_RE_SCISSORS_TL, 0));
 	radeon_ring_write(rdev, 0);
-	radeon_ring_write(rdev, PACKET0(0x43E4, 0));
+	radeon_ring_write(rdev, PACKET0(R300_RE_SCISSORS_BR, 0));
 	radeon_ring_write(rdev, 0);
 	/* Flush 3D cache */
-	radeon_ring_write(rdev, PACKET0(0x4E4C, 0));
-	radeon_ring_write(rdev, (2 << 0));
-	radeon_ring_write(rdev, PACKET0(0x4F18, 0));
-	radeon_ring_write(rdev, (1 << 0));
+	radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, R300_RB3D_DC_FLUSH);
+	radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
+	radeon_ring_write(rdev, R300_ZC_FLUSH);
 	/* Wait until IDLE & CLEAN */
-	radeon_ring_write(rdev, PACKET0(0x1720, 0));
-	radeon_ring_write(rdev, (1 << 17) | (1 << 16)  | (1 << 9));
+	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
+	radeon_ring_write(rdev, (RADEON_WAIT_3D_IDLECLEAN |
+				 RADEON_WAIT_2D_IDLECLEAN |
+				 RADEON_WAIT_DMA_GUI_IDLE));
 	radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0));
 	radeon_ring_write(rdev, rdev->config.r300.hdp_cntl |
 				RADEON_HDP_READ_BUFFER_INVALIDATE);
@@ -198,50 +201,6 @@
 	radeon_ring_write(rdev, RADEON_SW_INT_FIRE);
 }
 
-int r300_copy_dma(struct radeon_device *rdev,
-		  uint64_t src_offset,
-		  uint64_t dst_offset,
-		  unsigned num_pages,
-		  struct radeon_fence *fence)
-{
-	uint32_t size;
-	uint32_t cur_size;
-	int i, num_loops;
-	int r = 0;
-
-	/* radeon pitch is /64 */
-	size = num_pages << PAGE_SHIFT;
-	num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
-	r = radeon_ring_lock(rdev, num_loops * 4 + 64);
-	if (r) {
-		DRM_ERROR("radeon: moving bo (%d).\n", r);
-		return r;
-	}
-	/* Must wait for 2D idle & clean before DMA or hangs might happen */
-	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0 ));
-	radeon_ring_write(rdev, (1 << 16));
-	for (i = 0; i < num_loops; i++) {
-		cur_size = size;
-		if (cur_size > 0x1FFFFF) {
-			cur_size = 0x1FFFFF;
-		}
-		size -= cur_size;
-		radeon_ring_write(rdev, PACKET0(0x720, 2));
-		radeon_ring_write(rdev, src_offset);
-		radeon_ring_write(rdev, dst_offset);
-		radeon_ring_write(rdev, cur_size | (1 << 31) | (1 << 30));
-		src_offset += cur_size;
-		dst_offset += cur_size;
-	}
-	radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
-	radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE);
-	if (fence) {
-		r = radeon_fence_emit(rdev, fence);
-	}
-	radeon_ring_unlock_commit(rdev);
-	return r;
-}
-
 void r300_ring_start(struct radeon_device *rdev)
 {
 	unsigned gb_tile_config;
@@ -281,8 +240,8 @@
 	radeon_ring_write(rdev,
 			  RADEON_WAIT_2D_IDLECLEAN |
 			  RADEON_WAIT_3D_IDLECLEAN);
-	radeon_ring_write(rdev, PACKET0(0x170C, 0));
-	radeon_ring_write(rdev, 1 << 31);
+	radeon_ring_write(rdev, PACKET0(R300_DST_PIPE_CONFIG, 0));
+	radeon_ring_write(rdev, R300_PIPE_AUTO_CONFIG);
 	radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0));
 	radeon_ring_write(rdev, 0);
 	radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0));
@@ -349,8 +308,8 @@
 
 	for (i = 0; i < rdev->usec_timeout; i++) {
 		/* read MC_STATUS */
-		tmp = RREG32(0x0150);
-		if (tmp & (1 << 4)) {
+		tmp = RREG32(RADEON_MC_STATUS);
+		if (tmp & R300_MC_IDLE) {
 			return 0;
 		}
 		DRM_UDELAY(1);
@@ -395,8 +354,8 @@
 		       "programming pipes. Bad things might happen.\n");
 	}
 
-	tmp = RREG32(0x170C);
-	WREG32(0x170C, tmp | (1 << 31));
+	tmp = RREG32(R300_DST_PIPE_CONFIG);
+	WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG);
 
 	WREG32(R300_RB2D_DSTCACHE_MODE,
 	       R300_DC_AUTOFLUSH_ENABLE |
@@ -437,8 +396,8 @@
 			/* GA still busy soft reset it */
 			WREG32(0x429C, 0x200);
 			WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0);
-			WREG32(0x43E0, 0);
-			WREG32(0x43E4, 0);
+			WREG32(R300_RE_SCISSORS_TL, 0);
+			WREG32(R300_RE_SCISSORS_BR, 0);
 			WREG32(0x24AC, 0);
 		}
 		/* Wait to prevent race in RBBM_STATUS */
@@ -488,7 +447,7 @@
 	}
 	/* Check if GPU is idle */
 	status = RREG32(RADEON_RBBM_STATUS);
-	if (status & (1 << 31)) {
+	if (status & RADEON_RBBM_ACTIVE) {
 		DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
 		return -1;
 	}
@@ -500,13 +459,13 @@
 /*
  * r300,r350,rv350,rv380 VRAM info
  */
-void r300_vram_info(struct radeon_device *rdev)
+void r300_mc_init(struct radeon_device *rdev)
 {
-	uint32_t tmp;
+	u64 base;
+	u32 tmp;
 
 	/* DDR for all card after R300 & IGP */
 	rdev->mc.vram_is_ddr = true;
-
 	tmp = RREG32(RADEON_MEM_CNTL);
 	tmp &= R300_MEM_NUM_CHANNELS_MASK;
 	switch (tmp) {
@@ -515,8 +474,13 @@
 	case 2: rdev->mc.vram_width = 256; break;
 	default:  rdev->mc.vram_width = 128; break;
 	}
-
 	r100_vram_init_sizes(rdev);
+	base = rdev->mc.aper_base;
+	if (rdev->flags & RADEON_IS_IGP)
+		base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
+	radeon_vram_location(rdev, &rdev->mc, base);
+	if (!(rdev->flags & RADEON_IS_AGP))
+		radeon_gtt_location(rdev, &rdev->mc);
 }
 
 void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes)
@@ -578,6 +542,40 @@
 
 }
 
+int rv370_get_pcie_lanes(struct radeon_device *rdev)
+{
+	u32 link_width_cntl;
+
+	if (rdev->flags & RADEON_IS_IGP)
+		return 0;
+
+	if (!(rdev->flags & RADEON_IS_PCIE))
+		return 0;
+
+	/* FIXME wait for idle */
+
+	if (rdev->family < CHIP_R600)
+		link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
+	else
+		link_width_cntl = RREG32_PCIE_P(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
+
+	switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) {
+	case RADEON_PCIE_LC_LINK_WIDTH_X0:
+		return 0;
+	case RADEON_PCIE_LC_LINK_WIDTH_X1:
+		return 1;
+	case RADEON_PCIE_LC_LINK_WIDTH_X2:
+		return 2;
+	case RADEON_PCIE_LC_LINK_WIDTH_X4:
+		return 4;
+	case RADEON_PCIE_LC_LINK_WIDTH_X8:
+		return 8;
+	case RADEON_PCIE_LC_LINK_WIDTH_X16:
+	default:
+		return 16;
+	}
+}
+
 #if defined(CONFIG_DEBUG_FS)
 static int rv370_debugfs_pcie_gart_info(struct seq_file *m, void *data)
 {
@@ -707,6 +705,8 @@
 			tile_flags |= R300_TXO_MACRO_TILE;
 		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
 			tile_flags |= R300_TXO_MICRO_TILE;
+		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+			tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
 
 		tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
 		tmp |= tile_flags;
@@ -757,6 +757,8 @@
 			tile_flags |= R300_COLOR_TILE_ENABLE;
 		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
 			tile_flags |= R300_COLOR_MICROTILE_ENABLE;
+		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+			tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
 
 		tmp = idx_value & ~(0x7 << 16);
 		tmp |= tile_flags;
@@ -828,7 +830,9 @@
 		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
 			tile_flags |= R300_DEPTHMACROTILE_ENABLE;
 		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-			tile_flags |= R300_DEPTHMICROTILE_TILED;;
+			tile_flags |= R300_DEPTHMICROTILE_TILED;
+		else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+			tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
 
 		tmp = idx_value & ~(0x7 << 16);
 		tmp |= tile_flags;
@@ -1387,12 +1391,15 @@
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
 	radeon_pm_init(rdev);
-	/* Get vram informations */
-	r300_vram_info(rdev);
-	/* Initialize memory controller (also test AGP) */
-	r = r420_mc_init(rdev);
-	if (r)
-		return r;
+	/* initialize AGP */
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r) {
+			radeon_agp_disable(rdev);
+		}
+	}
+	/* initialize memory controller */
+	r300_mc_init(rdev);
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
 	if (r)
diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c
index 34bffa0..ea46d55 100644
--- a/drivers/gpu/drm/radeon/r300_cmdbuf.c
+++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c
@@ -33,6 +33,7 @@
 
 #include "drmP.h"
 #include "drm.h"
+#include "drm_buffer.h"
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 #include "r300_reg.h"
@@ -299,46 +300,42 @@
 	int reg;
 	int sz;
 	int i;
-	int values[64];
+	u32 *value;
 	RING_LOCALS;
 
 	sz = header.packet0.count;
 	reg = (header.packet0.reghi << 8) | header.packet0.reglo;
 
 	if ((sz > 64) || (sz < 0)) {
-		DRM_ERROR
-		    ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
-		     reg, sz);
+		DRM_ERROR("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
+			 reg, sz);
 		return -EINVAL;
 	}
+
 	for (i = 0; i < sz; i++) {
-		values[i] = ((int *)cmdbuf->buf)[i];
 		switch (r300_reg_flags[(reg >> 2) + i]) {
 		case MARK_SAFE:
 			break;
 		case MARK_CHECK_OFFSET:
-			if (!radeon_check_offset(dev_priv, (u32) values[i])) {
-				DRM_ERROR
-				    ("Offset failed range check (reg=%04x sz=%d)\n",
-				     reg, sz);
+			value = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
+			if (!radeon_check_offset(dev_priv, *value)) {
+				DRM_ERROR("Offset failed range check (reg=%04x sz=%d)\n",
+					 reg, sz);
 				return -EINVAL;
 			}
 			break;
 		default:
 			DRM_ERROR("Register %04x failed check as flag=%02x\n",
-				  reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
+				reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
 			return -EINVAL;
 		}
 	}
 
 	BEGIN_RING(1 + sz);
 	OUT_RING(CP_PACKET0(reg, sz - 1));
-	OUT_RING_TABLE(values, sz);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
 	ADVANCE_RING();
 
-	cmdbuf->buf += sz * 4;
-	cmdbuf->bufsz -= sz * 4;
-
 	return 0;
 }
 
@@ -362,7 +359,7 @@
 	if (!sz)
 		return 0;
 
-	if (sz * 4 > cmdbuf->bufsz)
+	if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
 		return -EINVAL;
 
 	if (reg + sz * 4 >= 0x10000) {
@@ -380,12 +377,9 @@
 
 	BEGIN_RING(1 + sz);
 	OUT_RING(CP_PACKET0(reg, sz - 1));
-	OUT_RING_TABLE((int *)cmdbuf->buf, sz);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
 	ADVANCE_RING();
 
-	cmdbuf->buf += sz * 4;
-	cmdbuf->bufsz -= sz * 4;
-
 	return 0;
 }
 
@@ -407,7 +401,7 @@
 
 	if (!sz)
 		return 0;
-	if (sz * 16 > cmdbuf->bufsz)
+	if (sz * 16 > drm_buffer_unprocessed(cmdbuf->buffer))
 		return -EINVAL;
 
 	/* VAP is very sensitive so we purge cache before we program it
@@ -426,7 +420,7 @@
 	BEGIN_RING(3 + sz * 4);
 	OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
 	OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
-	OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * 4);
 	ADVANCE_RING();
 
 	BEGIN_RING(2);
@@ -434,9 +428,6 @@
 	OUT_RING(0);
 	ADVANCE_RING();
 
-	cmdbuf->buf += sz * 16;
-	cmdbuf->bufsz -= sz * 16;
-
 	return 0;
 }
 
@@ -449,14 +440,14 @@
 {
 	RING_LOCALS;
 
-	if (8 * 4 > cmdbuf->bufsz)
+	if (8 * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
 		return -EINVAL;
 
 	BEGIN_RING(10);
 	OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
 	OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
 		 (1 << R300_PRIM_NUM_VERTICES_SHIFT));
-	OUT_RING_TABLE((int *)cmdbuf->buf, 8);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, 8);
 	ADVANCE_RING();
 
 	BEGIN_RING(4);
@@ -468,9 +459,6 @@
 	/* set flush flag */
 	dev_priv->track_flush |= RADEON_FLUSH_EMITED;
 
-	cmdbuf->buf += 8 * 4;
-	cmdbuf->bufsz -= 8 * 4;
-
 	return 0;
 }
 
@@ -480,28 +468,29 @@
 {
 	int count, i, k;
 #define MAX_ARRAY_PACKET  64
-	u32 payload[MAX_ARRAY_PACKET];
+	u32 *data;
 	u32 narrays;
 	RING_LOCALS;
 
-	count = (header >> 16) & 0x3fff;
+	count = (header & RADEON_CP_PACKET_COUNT_MASK) >> 16;
 
 	if ((count + 1) > MAX_ARRAY_PACKET) {
 		DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
 			  count);
 		return -EINVAL;
 	}
-	memset(payload, 0, MAX_ARRAY_PACKET * 4);
-	memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
-
 	/* carefully check packet contents */
 
-	narrays = payload[0];
+	/* We have already read the header so advance the buffer. */
+	drm_buffer_advance(cmdbuf->buffer, 4);
+
+	narrays = *(u32 *)drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
 	k = 0;
 	i = 1;
 	while ((k < narrays) && (i < (count + 1))) {
 		i++;		/* skip attribute field */
-		if (!radeon_check_offset(dev_priv, payload[i])) {
+		data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
+		if (!radeon_check_offset(dev_priv, *data)) {
 			DRM_ERROR
 			    ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
 			     k, i);
@@ -512,7 +501,8 @@
 		if (k == narrays)
 			break;
 		/* have one more to process, they come in pairs */
-		if (!radeon_check_offset(dev_priv, payload[i])) {
+		data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
+		if (!radeon_check_offset(dev_priv, *data)) {
 			DRM_ERROR
 			    ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
 			     k, i);
@@ -533,30 +523,30 @@
 
 	BEGIN_RING(count + 2);
 	OUT_RING(header);
-	OUT_RING_TABLE(payload, count + 1);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 1);
 	ADVANCE_RING();
 
-	cmdbuf->buf += (count + 2) * 4;
-	cmdbuf->bufsz -= (count + 2) * 4;
-
 	return 0;
 }
 
 static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
 					     drm_radeon_kcmd_buffer_t *cmdbuf)
 {
-	u32 *cmd = (u32 *) cmdbuf->buf;
+	u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
 	int count, ret;
 	RING_LOCALS;
 
-	count=(cmd[0]>>16) & 0x3fff;
 
-	if (cmd[0] & 0x8000) {
+	count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16;
+
+	if (*cmd & 0x8000) {
 		u32 offset;
-
-		if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+		u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
+		if (*cmd1 & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
 			      | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-			offset = cmd[2] << 10;
+
+			u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
+			offset = *cmd2 << 10;
 			ret = !radeon_check_offset(dev_priv, offset);
 			if (ret) {
 				DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
@@ -564,9 +554,10 @@
 			}
 		}
 
-		if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
-		    (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-			offset = cmd[3] << 10;
+		if ((*cmd1 & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
+		    (*cmd1 & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+			u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
+			offset = *cmd3 << 10;
 			ret = !radeon_check_offset(dev_priv, offset);
 			if (ret) {
 				DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
@@ -577,28 +568,25 @@
 	}
 
 	BEGIN_RING(count+2);
-	OUT_RING(cmd[0]);
-	OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
 	ADVANCE_RING();
 
-	cmdbuf->buf += (count+2)*4;
-	cmdbuf->bufsz -= (count+2)*4;
-
 	return 0;
 }
 
 static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
 					    drm_radeon_kcmd_buffer_t *cmdbuf)
 {
-	u32 *cmd;
+	u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
+	u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
 	int count;
 	int expected_count;
 	RING_LOCALS;
 
-	cmd = (u32 *) cmdbuf->buf;
-	count = (cmd[0]>>16) & 0x3fff;
-	expected_count = cmd[1] >> 16;
-	if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
+	count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16;
+
+	expected_count = *cmd1 >> 16;
+	if (!(*cmd1 & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
 		expected_count = (expected_count+1)/2;
 
 	if (count && count != expected_count) {
@@ -608,55 +596,53 @@
 	}
 
 	BEGIN_RING(count+2);
-	OUT_RING(cmd[0]);
-	OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
 	ADVANCE_RING();
 
-	cmdbuf->buf += (count+2)*4;
-	cmdbuf->bufsz -= (count+2)*4;
-
 	if (!count) {
-		drm_r300_cmd_header_t header;
+		drm_r300_cmd_header_t stack_header, *header;
+		u32 *cmd1, *cmd2, *cmd3;
 
-		if (cmdbuf->bufsz < 4*4 + sizeof(header)) {
+		if (drm_buffer_unprocessed(cmdbuf->buffer)
+				< 4*4 + sizeof(stack_header)) {
 			DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n");
 			return -EINVAL;
 		}
 
-		header.u = *(unsigned int *)cmdbuf->buf;
+		header = drm_buffer_read_object(cmdbuf->buffer,
+				sizeof(stack_header), &stack_header);
 
-		cmdbuf->buf += sizeof(header);
-		cmdbuf->bufsz -= sizeof(header);
-		cmd = (u32 *) cmdbuf->buf;
+		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
+		cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
+		cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
+		cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
 
-		if (header.header.cmd_type != R300_CMD_PACKET3 ||
-		    header.packet3.packet != R300_CMD_PACKET3_RAW ||
-		    cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
+		if (header->header.cmd_type != R300_CMD_PACKET3 ||
+		    header->packet3.packet != R300_CMD_PACKET3_RAW ||
+		    *cmd != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
 			DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n");
 			return -EINVAL;
 		}
 
-		if ((cmd[1] & 0x8000ffff) != 0x80000810) {
-			DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+		if ((*cmd1 & 0x8000ffff) != 0x80000810) {
+			DRM_ERROR("Invalid indx_buffer reg address %08X\n",
+					*cmd1);
 			return -EINVAL;
 		}
-		if (!radeon_check_offset(dev_priv, cmd[2])) {
-			DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+		if (!radeon_check_offset(dev_priv, *cmd2)) {
+			DRM_ERROR("Invalid indx_buffer offset is %08X\n",
+					*cmd2);
 			return -EINVAL;
 		}
-		if (cmd[3] != expected_count) {
+		if (*cmd3 != expected_count) {
 			DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n",
-				cmd[3], expected_count);
+				*cmd3, expected_count);
 			return -EINVAL;
 		}
 
 		BEGIN_RING(4);
-		OUT_RING(cmd[0]);
-		OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3);
+		OUT_RING_DRM_BUFFER(cmdbuf->buffer, 4);
 		ADVANCE_RING();
-
-		cmdbuf->buf += 4*4;
-		cmdbuf->bufsz -= 4*4;
 	}
 
 	return 0;
@@ -665,39 +651,39 @@
 static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
 					    drm_radeon_kcmd_buffer_t *cmdbuf)
 {
-	u32 header;
+	u32 *header;
 	int count;
 	RING_LOCALS;
 
-	if (4 > cmdbuf->bufsz)
+	if (4 > drm_buffer_unprocessed(cmdbuf->buffer))
 		return -EINVAL;
 
 	/* Fixme !! This simply emits a packet without much checking.
 	   We need to be smarter. */
 
 	/* obtain first word - actual packet3 header */
-	header = *(u32 *) cmdbuf->buf;
+	header = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
 
 	/* Is it packet 3 ? */
-	if ((header >> 30) != 0x3) {
-		DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
+	if ((*header >> 30) != 0x3) {
+		DRM_ERROR("Not a packet3 header (0x%08x)\n", *header);
 		return -EINVAL;
 	}
 
-	count = (header >> 16) & 0x3fff;
+	count = (*header >> 16) & 0x3fff;
 
 	/* Check again now that we know how much data to expect */
-	if ((count + 2) * 4 > cmdbuf->bufsz) {
+	if ((count + 2) * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) {
 		DRM_ERROR
 		    ("Expected packet3 of length %d but have only %d bytes left\n",
-		     (count + 2) * 4, cmdbuf->bufsz);
+		     (count + 2) * 4, drm_buffer_unprocessed(cmdbuf->buffer));
 		return -EINVAL;
 	}
 
 	/* Is it a packet type we know about ? */
-	switch (header & 0xff00) {
+	switch (*header & 0xff00) {
 	case RADEON_3D_LOAD_VBPNTR:	/* load vertex array pointers */
-		return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
+		return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, *header);
 
 	case RADEON_CNTL_BITBLT_MULTI:
 		return r300_emit_bitblt_multi(dev_priv, cmdbuf);
@@ -723,18 +709,14 @@
 		/* these packets are safe */
 		break;
 	default:
-		DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
+		DRM_ERROR("Unknown packet3 header (0x%08x)\n", *header);
 		return -EINVAL;
 	}
 
 	BEGIN_RING(count + 2);
-	OUT_RING(header);
-	OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2);
 	ADVANCE_RING();
 
-	cmdbuf->buf += (count + 2) * 4;
-	cmdbuf->bufsz -= (count + 2) * 4;
-
 	return 0;
 }
 
@@ -748,8 +730,7 @@
 {
 	int n;
 	int ret;
-	char *orig_buf = cmdbuf->buf;
-	int orig_bufsz = cmdbuf->bufsz;
+	int orig_iter = cmdbuf->buffer->iterator;
 
 	/* This is a do-while-loop so that we run the interior at least once,
 	 * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
@@ -761,8 +742,7 @@
 			if (ret)
 				return ret;
 
-			cmdbuf->buf = orig_buf;
-			cmdbuf->bufsz = orig_bufsz;
+			cmdbuf->buffer->iterator = orig_iter;
 		}
 
 		switch (header.packet3.packet) {
@@ -785,9 +765,9 @@
 			break;
 
 		default:
-			DRM_ERROR("bad packet3 type %i at %p\n",
+			DRM_ERROR("bad packet3 type %i at byte %d\n",
 				  header.packet3.packet,
-				  cmdbuf->buf - sizeof(header));
+				  cmdbuf->buffer->iterator - (int)sizeof(header));
 			return -EINVAL;
 		}
 
@@ -923,12 +903,13 @@
 			drm_r300_cmd_header_t header)
 {
 	u32 *ref_age_base;
-	u32 i, buf_idx, h_pending;
-	u64 ptr_addr;
+	u32 i, *buf_idx, h_pending;
+	u64 *ptr_addr;
+	u64 stack_ptr_addr;
 	RING_LOCALS;
 
-	if (cmdbuf->bufsz <
-	    (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) {
+	if (drm_buffer_unprocessed(cmdbuf->buffer) <
+	    (sizeof(u64) + header.scratch.n_bufs * sizeof(*buf_idx))) {
 		return -EINVAL;
 	}
 
@@ -938,36 +919,35 @@
 
 	dev_priv->scratch_ages[header.scratch.reg]++;
 
-	ptr_addr = get_unaligned((u64 *)cmdbuf->buf);
-	ref_age_base = (u32 *)(unsigned long)ptr_addr;
-
-	cmdbuf->buf += sizeof(u64);
-	cmdbuf->bufsz -= sizeof(u64);
+	ptr_addr = drm_buffer_read_object(cmdbuf->buffer,
+			sizeof(stack_ptr_addr), &stack_ptr_addr);
+	ref_age_base = (u32 *)(unsigned long)*ptr_addr;
 
 	for (i=0; i < header.scratch.n_bufs; i++) {
-		buf_idx = *(u32 *)cmdbuf->buf;
-		buf_idx *= 2; /* 8 bytes per buf */
+		buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
+		*buf_idx *= 2; /* 8 bytes per buf */
 
-		if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
+		if (DRM_COPY_TO_USER(ref_age_base + *buf_idx,
+				&dev_priv->scratch_ages[header.scratch.reg],
+				sizeof(u32)))
 			return -EINVAL;
-		}
 
-		if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
+		if (DRM_COPY_FROM_USER(&h_pending,
+				ref_age_base + *buf_idx + 1,
+				sizeof(u32)))
 			return -EINVAL;
-		}
 
-		if (h_pending == 0) {
+		if (h_pending == 0)
 			return -EINVAL;
-		}
 
 		h_pending--;
 
-		if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
+		if (DRM_COPY_TO_USER(ref_age_base + *buf_idx + 1,
+					&h_pending,
+					sizeof(u32)))
 			return -EINVAL;
-		}
 
-		cmdbuf->buf += sizeof(buf_idx);
-		cmdbuf->bufsz -= sizeof(buf_idx);
+		drm_buffer_advance(cmdbuf->buffer, sizeof(*buf_idx));
 	}
 
 	BEGIN_RING(2);
@@ -1009,19 +989,16 @@
 	DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type);
 	if (!sz)
 		return 0;
-	if (sz * stride * 4 > cmdbuf->bufsz)
+	if (sz * stride * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
 		return -EINVAL;
 
 	BEGIN_RING(3 + sz * stride);
 	OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr);
 	OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1));
-	OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * stride);
 
 	ADVANCE_RING();
 
-	cmdbuf->buf += sz * stride * 4;
-	cmdbuf->bufsz -= sz * stride * 4;
-
 	return 0;
 }
 
@@ -1053,19 +1030,18 @@
 			goto cleanup;
 	}
 
-	while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
+	while (drm_buffer_unprocessed(cmdbuf->buffer)
+			>= sizeof(drm_r300_cmd_header_t)) {
 		int idx;
-		drm_r300_cmd_header_t header;
+		drm_r300_cmd_header_t *header, stack_header;
 
-		header.u = *(unsigned int *)cmdbuf->buf;
+		header = drm_buffer_read_object(cmdbuf->buffer,
+				sizeof(stack_header), &stack_header);
 
-		cmdbuf->buf += sizeof(header);
-		cmdbuf->bufsz -= sizeof(header);
-
-		switch (header.header.cmd_type) {
+		switch (header->header.cmd_type) {
 		case R300_CMD_PACKET0:
 			DRM_DEBUG("R300_CMD_PACKET0\n");
-			ret = r300_emit_packet0(dev_priv, cmdbuf, header);
+			ret = r300_emit_packet0(dev_priv, cmdbuf, *header);
 			if (ret) {
 				DRM_ERROR("r300_emit_packet0 failed\n");
 				goto cleanup;
@@ -1074,7 +1050,7 @@
 
 		case R300_CMD_VPU:
 			DRM_DEBUG("R300_CMD_VPU\n");
-			ret = r300_emit_vpu(dev_priv, cmdbuf, header);
+			ret = r300_emit_vpu(dev_priv, cmdbuf, *header);
 			if (ret) {
 				DRM_ERROR("r300_emit_vpu failed\n");
 				goto cleanup;
@@ -1083,7 +1059,7 @@
 
 		case R300_CMD_PACKET3:
 			DRM_DEBUG("R300_CMD_PACKET3\n");
-			ret = r300_emit_packet3(dev_priv, cmdbuf, header);
+			ret = r300_emit_packet3(dev_priv, cmdbuf, *header);
 			if (ret) {
 				DRM_ERROR("r300_emit_packet3 failed\n");
 				goto cleanup;
@@ -1117,8 +1093,8 @@
 				int i;
 				RING_LOCALS;
 
-				BEGIN_RING(header.delay.count);
-				for (i = 0; i < header.delay.count; i++)
+				BEGIN_RING(header->delay.count);
+				for (i = 0; i < header->delay.count; i++)
 					OUT_RING(RADEON_CP_PACKET2);
 				ADVANCE_RING();
 			}
@@ -1126,7 +1102,7 @@
 
 		case R300_CMD_DMA_DISCARD:
 			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
-			idx = header.dma.buf_idx;
+			idx = header->dma.buf_idx;
 			if (idx < 0 || idx >= dma->buf_count) {
 				DRM_ERROR("buffer index %d (of %d max)\n",
 					  idx, dma->buf_count - 1);
@@ -1149,12 +1125,12 @@
 
 		case R300_CMD_WAIT:
 			DRM_DEBUG("R300_CMD_WAIT\n");
-			r300_cmd_wait(dev_priv, header);
+			r300_cmd_wait(dev_priv, *header);
 			break;
 
 		case R300_CMD_SCRATCH:
 			DRM_DEBUG("R300_CMD_SCRATCH\n");
-			ret = r300_scratch(dev_priv, cmdbuf, header);
+			ret = r300_scratch(dev_priv, cmdbuf, *header);
 			if (ret) {
 				DRM_ERROR("r300_scratch failed\n");
 				goto cleanup;
@@ -1168,16 +1144,16 @@
 				goto cleanup;
 			}
 			DRM_DEBUG("R300_CMD_R500FP\n");
-			ret = r300_emit_r500fp(dev_priv, cmdbuf, header);
+			ret = r300_emit_r500fp(dev_priv, cmdbuf, *header);
 			if (ret) {
 				DRM_ERROR("r300_emit_r500fp failed\n");
 				goto cleanup;
 			}
 			break;
 		default:
-			DRM_ERROR("bad cmd_type %i at %p\n",
-				  header.header.cmd_type,
-				  cmdbuf->buf - sizeof(header));
+			DRM_ERROR("bad cmd_type %i at byte %d\n",
+				  header->header.cmd_type,
+				  cmdbuf->buffer->iterator - (int)sizeof(*header));
 			ret = -EINVAL;
 			goto cleanup;
 		}
diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h
index 1735a2b..1a0d536 100644
--- a/drivers/gpu/drm/radeon/r300_reg.h
+++ b/drivers/gpu/drm/radeon/r300_reg.h
@@ -952,6 +952,7 @@
 #       define R300_TXO_ENDIAN_HALFDW_SWAP       (3 << 0)
 #       define R300_TXO_MACRO_TILE               (1 << 2)
 #       define R300_TXO_MICRO_TILE               (1 << 3)
+#       define R300_TXO_MICRO_TILE_SQUARE        (2 << 3)
 #       define R300_TXO_OFFSET_MASK              0xffffffe0
 #       define R300_TXO_OFFSET_SHIFT             5
 	/* END: Guess from R200 */
@@ -1360,6 +1361,7 @@
 #       define R300_COLORPITCH_MASK              0x00001FF8 /* GUESS */
 #       define R300_COLOR_TILE_ENABLE            (1 << 16) /* GUESS */
 #       define R300_COLOR_MICROTILE_ENABLE       (1 << 17) /* GUESS */
+#       define R300_COLOR_MICROTILE_SQUARE_ENABLE (2 << 17)
 #       define R300_COLOR_ENDIAN_NO_SWAP         (0 << 18) /* GUESS */
 #       define R300_COLOR_ENDIAN_WORD_SWAP       (1 << 18) /* GUESS */
 #       define R300_COLOR_ENDIAN_DWORD_SWAP      (2 << 18) /* GUESS */
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index d937324..c7593b8 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -40,28 +40,6 @@
 	rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm);
 }
 
-int r420_mc_init(struct radeon_device *rdev)
-{
-	int r;
-
-	/* Setup GPU memory space */
-	rdev->mc.vram_location = 0xFFFFFFFFUL;
-	rdev->mc.gtt_location = 0xFFFFFFFFUL;
-	if (rdev->flags & RADEON_IS_AGP) {
-		r = radeon_agp_init(rdev);
-		if (r) {
-			radeon_agp_disable(rdev);
-		} else {
-			rdev->mc.gtt_location = rdev->mc.agp_base;
-		}
-	}
-	r = radeon_mc_setup(rdev);
-	if (r) {
-		return r;
-	}
-	return 0;
-}
-
 void r420_pipes_init(struct radeon_device *rdev)
 {
 	unsigned tmp;
@@ -69,7 +47,8 @@
 	unsigned num_pipes;
 
 	/* GA_ENHANCE workaround TCL deadlock issue */
-	WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3));
+	WREG32(R300_GA_ENHANCE, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL |
+	       (1 << 2) | (1 << 3));
 	/* add idle wait as per freedesktop.org bug 24041 */
 	if (r100_gui_wait_for_idle(rdev)) {
 		printk(KERN_WARNING "Failed to wait GUI idle while "
@@ -97,17 +76,17 @@
 		tmp = (7 << 1);
 		break;
 	}
-	WREG32(0x42C8, (1 << num_pipes) - 1);
+	WREG32(R500_SU_REG_DEST, (1 << num_pipes) - 1);
 	/* Sub pixel 1/12 so we can have 4K rendering according to doc */
-	tmp |= (1 << 4) | (1 << 0);
-	WREG32(0x4018, tmp);
+	tmp |= R300_TILE_SIZE_16 | R300_ENABLE_TILING;
+	WREG32(R300_GB_TILE_CONFIG, tmp);
 	if (r100_gui_wait_for_idle(rdev)) {
 		printk(KERN_WARNING "Failed to wait GUI idle while "
 		       "programming pipes. Bad things might happen.\n");
 	}
 
-	tmp = RREG32(0x170C);
-	WREG32(0x170C, tmp | (1 << 31));
+	tmp = RREG32(R300_DST_PIPE_CONFIG);
+	WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG);
 
 	WREG32(R300_RB2D_DSTCACHE_MODE,
 	       RREG32(R300_RB2D_DSTCACHE_MODE) |
@@ -348,13 +327,15 @@
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
 	radeon_pm_init(rdev);
-	/* Get vram informations */
-	r300_vram_info(rdev);
-	/* Initialize memory controller (also test AGP) */
-	r = r420_mc_init(rdev);
-	if (r) {
-		return r;
+	/* initialize AGP */
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r) {
+			radeon_agp_disable(rdev);
+		}
 	}
+	/* initialize memory controller */
+	r300_mc_init(rdev);
 	r420_debugfs(rdev);
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h
index 74ad89b..0cf2ad2 100644
--- a/drivers/gpu/drm/radeon/r500_reg.h
+++ b/drivers/gpu/drm/radeon/r500_reg.h
@@ -717,54 +717,62 @@
 #define AVIVO_DVOA_BIT_DEPTH_CONTROL			0x7988
 
 #define AVIVO_DC_GPIO_HPD_A                 0x7e94
-
-#define AVIVO_GPIO_0                        0x7e30
-#define AVIVO_GPIO_1                        0x7e40
-#define AVIVO_GPIO_2                        0x7e50
-#define AVIVO_GPIO_3                        0x7e60
-
 #define AVIVO_DC_GPIO_HPD_Y                 0x7e9c
 
-#define AVIVO_I2C_STATUS					0x7d30
-#	define AVIVO_I2C_STATUS_DONE				(1 << 0)
-#	define AVIVO_I2C_STATUS_NACK				(1 << 1)
-#	define AVIVO_I2C_STATUS_HALT				(1 << 2)
-#	define AVIVO_I2C_STATUS_GO				(1 << 3)
-#	define AVIVO_I2C_STATUS_MASK				0x7
-/* If radeon_mm_i2c is to be believed, this is HALT, NACK, and maybe
- * DONE? */
-#	define AVIVO_I2C_STATUS_CMD_RESET			0x7
-#	define AVIVO_I2C_STATUS_CMD_WAIT			(1 << 3)
-#define AVIVO_I2C_STOP						0x7d34
-#define AVIVO_I2C_START_CNTL				0x7d38
-#	define AVIVO_I2C_START						(1 << 8)
-#	define AVIVO_I2C_CONNECTOR0					(0 << 16)
-#	define AVIVO_I2C_CONNECTOR1					(1 << 16)
-#define R520_I2C_START (1<<0)
-#define R520_I2C_STOP (1<<1)
-#define R520_I2C_RX (1<<2)
-#define R520_I2C_EN (1<<8)
-#define R520_I2C_DDC1 (0<<16)
-#define R520_I2C_DDC2 (1<<16)
-#define R520_I2C_DDC3 (2<<16)
-#define R520_I2C_DDC_MASK (3<<16)
-#define AVIVO_I2C_CONTROL2					0x7d3c
-#	define AVIVO_I2C_7D3C_SIZE_SHIFT			8
-#	define AVIVO_I2C_7D3C_SIZE_MASK				(0xf << 8)
-#define AVIVO_I2C_CONTROL3						0x7d40
-/* Reading is done 4 bytes at a time: read the bottom 8 bits from
- * 7d44, four times in a row.
- * Writing is a little more complex.  First write DATA with
- * 0xnnnnnnzz, then 0xnnnnnnyy, where nnnnnn is some non-deterministic
- * magic number, zz is, I think, the slave address, and yy is the byte
- * you want to write. */
-#define AVIVO_I2C_DATA						0x7d44
-#define R520_I2C_ADDR_COUNT_MASK (0x7)
-#define R520_I2C_DATA_COUNT_SHIFT (8)
-#define R520_I2C_DATA_COUNT_MASK (0xF00)
-#define AVIVO_I2C_CNTL						0x7d50
-#	define AVIVO_I2C_EN							(1 << 0)
-#	define AVIVO_I2C_RESET						(1 << 8)
+#define AVIVO_DC_I2C_STATUS1				0x7d30
+#	define AVIVO_DC_I2C_DONE			(1 << 0)
+#	define AVIVO_DC_I2C_NACK			(1 << 1)
+#	define AVIVO_DC_I2C_HALT			(1 << 2)
+#	define AVIVO_DC_I2C_GO			        (1 << 3)
+#define AVIVO_DC_I2C_RESET 				0x7d34
+#	define AVIVO_DC_I2C_SOFT_RESET			(1 << 0)
+#	define AVIVO_DC_I2C_ABORT			(1 << 8)
+#define AVIVO_DC_I2C_CONTROL1 				0x7d38
+#	define AVIVO_DC_I2C_START			(1 << 0)
+#	define AVIVO_DC_I2C_STOP			(1 << 1)
+#	define AVIVO_DC_I2C_RECEIVE			(1 << 2)
+#	define AVIVO_DC_I2C_EN			        (1 << 8)
+#	define AVIVO_DC_I2C_PIN_SELECT(x)		((x) << 16)
+#	define AVIVO_SEL_DDC1			        0
+#	define AVIVO_SEL_DDC2			        1
+#	define AVIVO_SEL_DDC3			        2
+#define AVIVO_DC_I2C_CONTROL2 				0x7d3c
+#	define AVIVO_DC_I2C_ADDR_COUNT(x)		((x) << 0)
+#	define AVIVO_DC_I2C_DATA_COUNT(x)		((x) << 8)
+#define AVIVO_DC_I2C_CONTROL3 				0x7d40
+#	define AVIVO_DC_I2C_DATA_DRIVE_EN		(1 << 0)
+#	define AVIVO_DC_I2C_DATA_DRIVE_SEL		(1 << 1)
+#	define AVIVO_DC_I2C_CLK_DRIVE_EN		(1 << 7)
+#	define AVIVO_DC_I2C_RD_INTRA_BYTE_DELAY(x)      ((x) << 8)
+#	define AVIVO_DC_I2C_WR_INTRA_BYTE_DELAY(x)	((x) << 16)
+#	define AVIVO_DC_I2C_TIME_LIMIT(x)		((x) << 24)
+#define AVIVO_DC_I2C_DATA 				0x7d44
+#define AVIVO_DC_I2C_INTERRUPT_CONTROL 			0x7d48
+#	define AVIVO_DC_I2C_INTERRUPT_STATUS		(1 << 0)
+#	define AVIVO_DC_I2C_INTERRUPT_AK		(1 << 8)
+#	define AVIVO_DC_I2C_INTERRUPT_ENABLE		(1 << 16)
+#define AVIVO_DC_I2C_ARBITRATION 			0x7d50
+#	define AVIVO_DC_I2C_SW_WANTS_TO_USE_I2C		(1 << 0)
+#	define AVIVO_DC_I2C_SW_CAN_USE_I2C		(1 << 1)
+#	define AVIVO_DC_I2C_SW_DONE_USING_I2C		(1 << 8)
+#	define AVIVO_DC_I2C_HW_NEEDS_I2C		(1 << 9)
+#	define AVIVO_DC_I2C_ABORT_HDCP_I2C		(1 << 16)
+#	define AVIVO_DC_I2C_HW_USING_I2C		(1 << 17)
+
+#define AVIVO_DC_GPIO_DDC1_MASK 		        0x7e40
+#define AVIVO_DC_GPIO_DDC1_A 		                0x7e44
+#define AVIVO_DC_GPIO_DDC1_EN 		                0x7e48
+#define AVIVO_DC_GPIO_DDC1_Y 		                0x7e4c
+
+#define AVIVO_DC_GPIO_DDC2_MASK 		        0x7e50
+#define AVIVO_DC_GPIO_DDC2_A 		                0x7e54
+#define AVIVO_DC_GPIO_DDC2_EN 		                0x7e58
+#define AVIVO_DC_GPIO_DDC2_Y 		                0x7e5c
+
+#define AVIVO_DC_GPIO_DDC3_MASK 		        0x7e60
+#define AVIVO_DC_GPIO_DDC3_A 		                0x7e64
+#define AVIVO_DC_GPIO_DDC3_EN 		                0x7e68
+#define AVIVO_DC_GPIO_DDC3_Y 		                0x7e6c
 
 #define AVIVO_DISP_INTERRUPT_STATUS                             0x7edc
 #       define AVIVO_D1_VBLANK_INTERRUPT                        (1 << 4)
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c
index ddf5731..2b8a5dd 100644
--- a/drivers/gpu/drm/radeon/r520.c
+++ b/drivers/gpu/drm/radeon/r520.c
@@ -119,13 +119,15 @@
 		rdev->mc.vram_width *= 2;
 }
 
-void r520_vram_info(struct radeon_device *rdev)
+void r520_mc_init(struct radeon_device *rdev)
 {
 	fixed20_12 a;
 
 	r520_vram_get_type(rdev);
-
 	r100_vram_init_sizes(rdev);
+	radeon_vram_location(rdev, &rdev->mc, 0);
+	if (!(rdev->flags & RADEON_IS_AGP))
+		radeon_gtt_location(rdev, &rdev->mc);
 	/* FIXME: we should enforce default clock in case GPU is not in
 	 * default setup
 	 */
@@ -267,12 +269,15 @@
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
 	radeon_pm_init(rdev);
-	/* Get vram informations */
-	r520_vram_info(rdev);
-	/* Initialize memory controller (also test AGP) */
-	r = r420_mc_init(rdev);
-	if (r)
-		return r;
+	/* initialize AGP */
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r) {
+			radeon_agp_disable(rdev);
+		}
+	}
+	/* initialize memory controller */
+	r520_mc_init(rdev);
 	rv515_debugfs(rdev);
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 2ffcf5a..c522901 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -353,23 +353,14 @@
 /*
  * R600 PCIE GART
  */
-int r600_gart_clear_page(struct radeon_device *rdev, int i)
-{
-	void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
-	u64 pte;
-
-	if (i < 0 || i > rdev->gart.num_gpu_pages)
-		return -EINVAL;
-	pte = 0;
-	writeq(pte, ((void __iomem *)ptr) + (i * 8));
-	return 0;
-}
-
 void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
 {
 	unsigned i;
 	u32 tmp;
 
+	/* flush hdp cache so updates hit vram */
+	WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+
 	WREG32(VM_CONTEXT0_INVALIDATION_LOW_ADDR, rdev->mc.gtt_start >> 12);
 	WREG32(VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (rdev->mc.gtt_end - 1) >> 12);
 	WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1));
@@ -416,6 +407,7 @@
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
+	radeon_gart_restore(rdev);
 
 	/* Setup L2 cache */
 	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
@@ -619,6 +611,68 @@
 	rv515_vga_render_disable(rdev);
 }
 
+/**
+ * r600_vram_gtt_location - try to find VRAM & GTT location
+ * @rdev: radeon device structure holding all necessary informations
+ * @mc: memory controller structure holding memory informations
+ *
+ * Function will place try to place VRAM at same place as in CPU (PCI)
+ * address space as some GPU seems to have issue when we reprogram at
+ * different address space.
+ *
+ * If there is not enough space to fit the unvisible VRAM after the
+ * aperture then we limit the VRAM size to the aperture.
+ *
+ * If we are using AGP then place VRAM adjacent to AGP aperture are we need
+ * them to be in one from GPU point of view so that we can program GPU to
+ * catch access outside them (weird GPU policy see ??).
+ *
+ * This function will never fails, worst case are limiting VRAM or GTT.
+ *
+ * Note: GTT start, end, size should be initialized before calling this
+ * function on AGP platform.
+ */
+void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
+{
+	u64 size_bf, size_af;
+
+	if (mc->mc_vram_size > 0xE0000000) {
+		/* leave room for at least 512M GTT */
+		dev_warn(rdev->dev, "limiting VRAM\n");
+		mc->real_vram_size = 0xE0000000;
+		mc->mc_vram_size = 0xE0000000;
+	}
+	if (rdev->flags & RADEON_IS_AGP) {
+		size_bf = mc->gtt_start;
+		size_af = 0xFFFFFFFF - mc->gtt_end + 1;
+		if (size_bf > size_af) {
+			if (mc->mc_vram_size > size_bf) {
+				dev_warn(rdev->dev, "limiting VRAM\n");
+				mc->real_vram_size = size_bf;
+				mc->mc_vram_size = size_bf;
+			}
+			mc->vram_start = mc->gtt_start - mc->mc_vram_size;
+		} else {
+			if (mc->mc_vram_size > size_af) {
+				dev_warn(rdev->dev, "limiting VRAM\n");
+				mc->real_vram_size = size_af;
+				mc->mc_vram_size = size_af;
+			}
+			mc->vram_start = mc->gtt_end;
+		}
+		mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
+		dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
+				mc->mc_vram_size >> 20, mc->vram_start,
+				mc->vram_end, mc->real_vram_size >> 20);
+	} else {
+		u64 base = 0;
+		if (rdev->flags & RADEON_IS_IGP)
+			base = (RREG32(MC_VM_FB_LOCATION) & 0xFFFF) << 24;
+		radeon_vram_location(rdev, &rdev->mc, base);
+		radeon_gtt_location(rdev, mc);
+	}
+}
+
 int r600_mc_init(struct radeon_device *rdev)
 {
 	fixed20_12 a;
@@ -658,75 +712,21 @@
 	/* Setup GPU memory space */
 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
-
-	if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
+	rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	/* FIXME remove this once we support unmappable VRAM */
+	if (rdev->mc.mc_vram_size > rdev->mc.aper_size) {
 		rdev->mc.mc_vram_size = rdev->mc.aper_size;
-
-	if (rdev->mc.real_vram_size > rdev->mc.aper_size)
 		rdev->mc.real_vram_size = rdev->mc.aper_size;
-
-	if (rdev->flags & RADEON_IS_AGP) {
-		/* gtt_size is setup by radeon_agp_init */
-		rdev->mc.gtt_location = rdev->mc.agp_base;
-		tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
-		/* Try to put vram before or after AGP because we
-		 * we want SYSTEM_APERTURE to cover both VRAM and
-		 * AGP so that GPU can catch out of VRAM/AGP access
-		 */
-		if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) {
-			/* Enough place before */
-			rdev->mc.vram_location = rdev->mc.gtt_location -
-							rdev->mc.mc_vram_size;
-		} else if (tmp > rdev->mc.mc_vram_size) {
-			/* Enough place after */
-			rdev->mc.vram_location = rdev->mc.gtt_location +
-							rdev->mc.gtt_size;
-		} else {
-			/* Try to setup VRAM then AGP might not
-			 * not work on some card
-			 */
-			rdev->mc.vram_location = 0x00000000UL;
-			rdev->mc.gtt_location = rdev->mc.mc_vram_size;
-		}
-	} else {
-		rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
-		rdev->mc.vram_location = (RREG32(MC_VM_FB_LOCATION) &
-							0xFFFF) << 24;
-		tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
-		if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
-			/* Enough place after vram */
-			rdev->mc.gtt_location = tmp;
-		} else if (rdev->mc.vram_location >= rdev->mc.gtt_size) {
-			/* Enough place before vram */
-			rdev->mc.gtt_location = 0;
-		} else {
-			/* Not enough place after or before shrink
-			 * gart size
-			 */
-			if (rdev->mc.vram_location > (0xFFFFFFFFUL - tmp)) {
-				rdev->mc.gtt_location = 0;
-				rdev->mc.gtt_size = rdev->mc.vram_location;
-			} else {
-				rdev->mc.gtt_location = tmp;
-				rdev->mc.gtt_size = 0xFFFFFFFFUL - tmp;
-			}
-		}
-		rdev->mc.gtt_location = rdev->mc.mc_vram_size;
 	}
-	rdev->mc.vram_start = rdev->mc.vram_location;
-	rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
-	rdev->mc.gtt_start = rdev->mc.gtt_location;
-	rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+	r600_vram_gtt_location(rdev, &rdev->mc);
 	/* FIXME: we should enforce default clock in case GPU is not in
 	 * default setup
 	 */
 	a.full = rfixed_const(100);
 	rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
 	rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
-
 	if (rdev->flags & RADEON_IS_IGP)
 		rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
-
 	return 0;
 }
 
@@ -981,6 +981,9 @@
 {
 	u32 tiling_config;
 	u32 ramcfg;
+	u32 backend_map;
+	u32 cc_rb_backend_disable;
+	u32 cc_gc_shader_pipe_config;
 	u32 tmp;
 	int i, j;
 	u32 sq_config;
@@ -1090,8 +1093,11 @@
 	default:
 		break;
 	}
+	rdev->config.r600.tiling_npipes = rdev->config.r600.max_tile_pipes;
+	rdev->config.r600.tiling_nbanks = 4 << ((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
 	tiling_config |= BANK_TILING((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
 	tiling_config |= GROUP_SIZE(0);
+	rdev->config.r600.tiling_group_size = 256;
 	tmp = (ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT;
 	if (tmp > 3) {
 		tiling_config |= ROW_TILING(3);
@@ -1101,24 +1107,33 @@
 		tiling_config |= SAMPLE_SPLIT(tmp);
 	}
 	tiling_config |= BANK_SWAPS(1);
-	tmp = r600_get_tile_pipe_to_backend_map(rdev->config.r600.max_tile_pipes,
-						rdev->config.r600.max_backends,
-						(0xff << rdev->config.r600.max_backends) & 0xff);
-	tiling_config |= BACKEND_MAP(tmp);
+
+	cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000;
+	cc_rb_backend_disable |=
+		BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << rdev->config.r600.max_backends) & R6XX_MAX_BACKENDS_MASK);
+
+	cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
+	cc_gc_shader_pipe_config |=
+		INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << rdev->config.r600.max_pipes) & R6XX_MAX_PIPES_MASK);
+	cc_gc_shader_pipe_config |=
+		INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << rdev->config.r600.max_simds) & R6XX_MAX_SIMDS_MASK);
+
+	backend_map = r600_get_tile_pipe_to_backend_map(rdev->config.r600.max_tile_pipes,
+							(R6XX_MAX_BACKENDS -
+							 r600_count_pipe_bits((cc_rb_backend_disable &
+									       R6XX_MAX_BACKENDS_MASK) >> 16)),
+							(cc_rb_backend_disable >> 16));
+
+	tiling_config |= BACKEND_MAP(backend_map);
 	WREG32(GB_TILING_CONFIG, tiling_config);
 	WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff);
 	WREG32(HDP_TILING_CONFIG, tiling_config & 0xffff);
 
-	tmp = BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << rdev->config.r600.max_backends) & R6XX_MAX_BACKENDS_MASK);
-	WREG32(CC_RB_BACKEND_DISABLE, tmp);
-
 	/* Setup pipes */
-	tmp = INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << rdev->config.r600.max_pipes) & R6XX_MAX_PIPES_MASK);
-	tmp |= INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << rdev->config.r600.max_simds) & R6XX_MAX_SIMDS_MASK);
-	WREG32(CC_GC_SHADER_PIPE_CONFIG, tmp);
-	WREG32(GC_USER_SHADER_PIPE_CONFIG, tmp);
+	WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable);
+	WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
 
-	tmp = R6XX_MAX_BACKENDS - r600_count_pipe_bits(tmp & INACTIVE_QD_PIPES_MASK);
+	tmp = R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8);
 	WREG32(VGT_OUT_DEALLOC_CNTL, (tmp * 4) & DEALLOC_DIST_MASK);
 	WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((tmp * 4) - 2) & VTX_REUSE_DEPTH_MASK);
 
@@ -1783,12 +1798,17 @@
 			  struct radeon_fence *fence)
 {
 	/* Also consider EVENT_WRITE_EOP.  it handles the interrupts + timestamps + events */
+
+	radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
+	radeon_ring_write(rdev, CACHE_FLUSH_AND_INV_EVENT);
+	/* wait for 3D idle clean */
+	radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
+	radeon_ring_write(rdev, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
+	radeon_ring_write(rdev, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit);
 	/* Emit fence sequence & fire IRQ */
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
 	radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2));
 	radeon_ring_write(rdev, fence->seq);
-	radeon_ring_write(rdev, PACKET0(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0));
-	radeon_ring_write(rdev, 1);
 	/* CP_INTERRUPT packet 3 no longer exists, use packet 0 */
 	radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0));
 	radeon_ring_write(rdev, RB_INT_STAT);
@@ -2745,6 +2765,7 @@
 			case 0: /* D1 vblank */
 				if (disp_int & LB_D1_VBLANK_INTERRUPT) {
 					drm_handle_vblank(rdev->ddev, 0);
+					wake_up(&rdev->irq.vblank_queue);
 					disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
 				}
@@ -2765,6 +2786,7 @@
 			case 0: /* D2 vblank */
 				if (disp_int & LB_D2_VBLANK_INTERRUPT) {
 					drm_handle_vblank(rdev->ddev, 1);
+					wake_up(&rdev->irq.vblank_queue);
 					disp_int &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
 				}
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c
index 0dcb690..db92801 100644
--- a/drivers/gpu/drm/radeon/r600_audio.c
+++ b/drivers/gpu/drm/radeon/r600_audio.c
@@ -35,7 +35,7 @@
  */
 static int r600_audio_chipset_supported(struct radeon_device *rdev)
 {
-	return (rdev->family >= CHIP_R600 && rdev->family < CHIP_RV710)
+	return rdev->family >= CHIP_R600
 		|| rdev->family == CHIP_RS600
 		|| rdev->family == CHIP_RS690
 		|| rdev->family == CHIP_RS740;
@@ -147,15 +147,23 @@
 }
 
 /*
+ * turn on/off audio engine
+ */
+static void r600_audio_engine_enable(struct radeon_device *rdev, bool enable)
+{
+	DRM_INFO("%s audio support", enable ? "Enabling" : "Disabling");
+	WREG32_P(R600_AUDIO_ENABLE, enable ? 0x81000000 : 0x0, ~0x81000000);
+}
+
+/*
  * initialize the audio vars and register the update timer
  */
 int r600_audio_init(struct radeon_device *rdev)
 {
-	if (!r600_audio_chipset_supported(rdev))
+	if (!radeon_audio || !r600_audio_chipset_supported(rdev))
 		return 0;
 
-	DRM_INFO("%s audio support", radeon_audio ? "Enabling" : "Disabling");
-	WREG32_P(R600_AUDIO_ENABLE, radeon_audio ? 0x81000000 : 0x0, ~0x81000000);
+	r600_audio_engine_enable(rdev, true);
 
 	rdev->audio_channels = -1;
 	rdev->audio_rate = -1;
@@ -258,9 +266,10 @@
  */
 void r600_audio_fini(struct radeon_device *rdev)
 {
-	if (!r600_audio_chipset_supported(rdev))
+	if (!radeon_audio || !r600_audio_chipset_supported(rdev))
 		return;
 
 	del_timer(&rdev->audio_timer);
-	WREG32_P(R600_AUDIO_ENABLE, 0x0, ~0x81000000);
+
+	r600_audio_engine_enable(rdev, false);
 }
diff --git a/drivers/gpu/drm/radeon/r600_blit.c b/drivers/gpu/drm/radeon/r600_blit.c
index 5ea4323..f4fb88e 100644
--- a/drivers/gpu/drm/radeon/r600_blit.c
+++ b/drivers/gpu/drm/radeon/r600_blit.c
@@ -49,7 +49,7 @@
 	RING_LOCALS;
 	DRM_DEBUG("\n");
 
-	h = (h + 7) & ~7;
+	h = ALIGN(h, 8);
 	if (h < 8)
 		h = 8;
 
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c
index 446b765..f6c6c77 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -25,7 +25,7 @@
 	u32 cb_color_info;
 	int pitch, slice;
 
-	h = (h + 7) & ~7;
+	h = ALIGN(h, 8);
 	if (h < 8)
 		h = 8;
 
@@ -396,15 +396,13 @@
 				    NUM_ES_STACK_ENTRIES(num_es_stack_entries));
 
 	/* emit an IB pointing at default state */
-	dwords = (rdev->r600_blit.state_len + 0xf) & ~0xf;
+	dwords = ALIGN(rdev->r600_blit.state_len, 0x10);
 	gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset;
 	radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
 	radeon_ring_write(rdev, gpu_addr & 0xFFFFFFFC);
 	radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF);
 	radeon_ring_write(rdev, dwords);
 
-	radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
-	radeon_ring_write(rdev, CACHE_FLUSH_AND_INV_EVENT);
 	/* SQ config */
 	radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 6));
 	radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
@@ -578,9 +576,9 @@
 	ring_size = num_loops * dwords_per_loop;
 	/* set default  + shaders */
 	ring_size += 40; /* shaders + def state */
-	ring_size += 7; /* fence emit for VB IB */
+	ring_size += 10; /* fence emit for VB IB */
 	ring_size += 5; /* done copy */
-	ring_size += 7; /* fence emit for done copy */
+	ring_size += 10; /* fence emit for done copy */
 	r = radeon_ring_lock(rdev, ring_size);
 	if (r)
 		return r;
@@ -594,13 +592,6 @@
 {
 	int r;
 
-	radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
-	radeon_ring_write(rdev, CACHE_FLUSH_AND_INV_EVENT);
-	/* wait for 3D idle clean */
-	radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
-	radeon_ring_write(rdev, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
-	radeon_ring_write(rdev, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit);
-
 	if (rdev->r600_blit.vb_ib)
 		r600_vb_ib_put(rdev);
 
diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.c b/drivers/gpu/drm/radeon/r600_blit_shaders.c
index d745e81..a112c59 100644
--- a/drivers/gpu/drm/radeon/r600_blit_shaders.c
+++ b/drivers/gpu/drm/radeon/r600_blit_shaders.c
@@ -9,11 +9,6 @@
 	0xc0012800,
 	0x80000000,
 	0x80000000,
-	0xc0004600,
-	0x00000016,
-	0xc0016800,
-	0x00000010,
-	0x00028000,
 	0xc0016800,
 	0x00000010,
 	0x00008000,
@@ -531,11 +526,6 @@
 	0xc0012800,
 	0x80000000,
 	0x80000000,
-	0xc0004600,
-	0x00000016,
-	0xc0016800,
-	0x00000010,
-	0x00028000,
 	0xc0016800,
 	0x00000010,
 	0x00008000,
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
index 75bcf35..40416c0 100644
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ b/drivers/gpu/drm/radeon/r600_cp.c
@@ -734,8 +734,8 @@
 	u32 hdp_host_path_cntl;
 	u32 backend_map;
 	u32 gb_tiling_config = 0;
-	u32 cc_rb_backend_disable = 0;
-	u32 cc_gc_shader_pipe_config = 0;
+	u32 cc_rb_backend_disable;
+	u32 cc_gc_shader_pipe_config;
 	u32 ramcfg;
 
 	/* setup chip specs */
@@ -857,29 +857,44 @@
 
 	gb_tiling_config |= R600_BANK_SWAPS(1);
 
-	backend_map = r600_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
-							dev_priv->r600_max_backends,
-							(0xff << dev_priv->r600_max_backends) & 0xff);
-	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
+	cc_rb_backend_disable = RADEON_READ(R600_CC_RB_BACKEND_DISABLE) & 0x00ff0000;
+	cc_rb_backend_disable |=
+		R600_BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R6XX_MAX_BACKENDS_MASK);
 
-	cc_gc_shader_pipe_config =
+	cc_gc_shader_pipe_config = RADEON_READ(R600_CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
+	cc_gc_shader_pipe_config |=
 		R600_INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R6XX_MAX_PIPES_MASK);
 	cc_gc_shader_pipe_config |=
 		R600_INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R6XX_MAX_SIMDS_MASK);
 
-	cc_rb_backend_disable =
-		R600_BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R6XX_MAX_BACKENDS_MASK);
+	backend_map = r600_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
+							(R6XX_MAX_BACKENDS -
+							 r600_count_pipe_bits((cc_rb_backend_disable &
+									       R6XX_MAX_BACKENDS_MASK) >> 16)),
+							(cc_rb_backend_disable >> 16));
+	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
 
 	RADEON_WRITE(R600_GB_TILING_CONFIG,      gb_tiling_config);
 	RADEON_WRITE(R600_DCP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
 	RADEON_WRITE(R600_HDP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
+	if (gb_tiling_config & 0xc0) {
+		dev_priv->r600_group_size = 512;
+	} else {
+		dev_priv->r600_group_size = 256;
+	}
+	dev_priv->r600_npipes = 1 << ((gb_tiling_config >> 1) & 0x7);
+	if (gb_tiling_config & 0x30) {
+		dev_priv->r600_nbanks = 8;
+	} else {
+		dev_priv->r600_nbanks = 4;
+	}
 
 	RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
 	RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
 	RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
 
 	num_qd_pipes =
-		R6XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK);
+		R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8);
 	RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK);
 	RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK);
 
@@ -1151,7 +1166,8 @@
 
 }
 
-static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
+static u32 r700_get_tile_pipe_to_backend_map(drm_radeon_private_t *dev_priv,
+					     u32 num_tile_pipes,
 					     u32 num_backends,
 					     u32 backend_disable_mask)
 {
@@ -1162,6 +1178,7 @@
 	u32 swizzle_pipe[R7XX_MAX_PIPES];
 	u32 cur_backend;
 	u32 i;
+	bool force_no_swizzle;
 
 	if (num_tile_pipes > R7XX_MAX_PIPES)
 		num_tile_pipes = R7XX_MAX_PIPES;
@@ -1191,6 +1208,18 @@
 	if (enabled_backends_count != num_backends)
 		num_backends = enabled_backends_count;
 
+	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
+	case CHIP_RV770:
+	case CHIP_RV730:
+		force_no_swizzle = false;
+		break;
+	case CHIP_RV710:
+	case CHIP_RV740:
+	default:
+		force_no_swizzle = true;
+		break;
+	}
+
 	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES);
 	switch (num_tile_pipes) {
 	case 1:
@@ -1201,49 +1230,100 @@
 		swizzle_pipe[1] = 1;
 		break;
 	case 3:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 1;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 1;
+		}
 		break;
 	case 4:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 3;
-		swizzle_pipe[3] = 1;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 3;
+			swizzle_pipe[3] = 1;
+		}
 		break;
 	case 5:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 1;
-		swizzle_pipe[4] = 3;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 1;
+			swizzle_pipe[4] = 3;
+		}
 		break;
 	case 6:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 5;
-		swizzle_pipe[4] = 3;
-		swizzle_pipe[5] = 1;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+			swizzle_pipe[5] = 5;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 5;
+			swizzle_pipe[4] = 3;
+			swizzle_pipe[5] = 1;
+		}
 		break;
 	case 7:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 6;
-		swizzle_pipe[4] = 3;
-		swizzle_pipe[5] = 1;
-		swizzle_pipe[6] = 5;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+			swizzle_pipe[5] = 5;
+			swizzle_pipe[6] = 6;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 6;
+			swizzle_pipe[4] = 3;
+			swizzle_pipe[5] = 1;
+			swizzle_pipe[6] = 5;
+		}
 		break;
 	case 8:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 6;
-		swizzle_pipe[4] = 3;
-		swizzle_pipe[5] = 1;
-		swizzle_pipe[6] = 7;
-		swizzle_pipe[7] = 5;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+			swizzle_pipe[5] = 5;
+			swizzle_pipe[6] = 6;
+			swizzle_pipe[7] = 7;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 6;
+			swizzle_pipe[4] = 3;
+			swizzle_pipe[5] = 1;
+			swizzle_pipe[6] = 7;
+			swizzle_pipe[7] = 5;
+		}
 		break;
 	}
 
@@ -1264,8 +1344,10 @@
 			  drm_radeon_private_t *dev_priv)
 {
 	int i, j, num_qd_pipes;
+	u32 ta_aux_cntl;
 	u32 sx_debug_1;
 	u32 smx_dc_ctl0;
+	u32 db_debug3;
 	u32 num_gs_verts_per_thread;
 	u32 vgt_gs_per_es;
 	u32 gs_prim_buffer_depth = 0;
@@ -1276,8 +1358,8 @@
 	u32 sq_dyn_gpr_size_simd_ab_0;
 	u32 backend_map;
 	u32 gb_tiling_config = 0;
-	u32 cc_rb_backend_disable = 0;
-	u32 cc_gc_shader_pipe_config = 0;
+	u32 cc_rb_backend_disable;
+	u32 cc_gc_shader_pipe_config;
 	u32 mc_arb_ramcfg;
 	u32 db_debug4;
 
@@ -1428,38 +1510,51 @@
 
 	gb_tiling_config |= R600_BANK_SWAPS(1);
 
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740)
-		backend_map = 0x28;
-	else
-		backend_map = r700_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
-								dev_priv->r600_max_backends,
-								(0xff << dev_priv->r600_max_backends) & 0xff);
-	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
+	cc_rb_backend_disable = RADEON_READ(R600_CC_RB_BACKEND_DISABLE) & 0x00ff0000;
+	cc_rb_backend_disable |=
+		R600_BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R7XX_MAX_BACKENDS_MASK);
 
-	cc_gc_shader_pipe_config =
+	cc_gc_shader_pipe_config = RADEON_READ(R600_CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
+	cc_gc_shader_pipe_config |=
 		R600_INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R7XX_MAX_PIPES_MASK);
 	cc_gc_shader_pipe_config |=
 		R600_INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R7XX_MAX_SIMDS_MASK);
 
-	cc_rb_backend_disable =
-		R600_BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R7XX_MAX_BACKENDS_MASK);
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740)
+		backend_map = 0x28;
+	else
+		backend_map = r700_get_tile_pipe_to_backend_map(dev_priv,
+								dev_priv->r600_max_tile_pipes,
+								(R7XX_MAX_BACKENDS -
+								 r600_count_pipe_bits((cc_rb_backend_disable &
+										       R7XX_MAX_BACKENDS_MASK) >> 16)),
+								(cc_rb_backend_disable >> 16));
+	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
 
 	RADEON_WRITE(R600_GB_TILING_CONFIG,      gb_tiling_config);
 	RADEON_WRITE(R600_DCP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
 	RADEON_WRITE(R600_HDP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
+	if (gb_tiling_config & 0xc0) {
+		dev_priv->r600_group_size = 512;
+	} else {
+		dev_priv->r600_group_size = 256;
+	}
+	dev_priv->r600_npipes = 1 << ((gb_tiling_config >> 1) & 0x7);
+	if (gb_tiling_config & 0x30) {
+		dev_priv->r600_nbanks = 8;
+	} else {
+		dev_priv->r600_nbanks = 4;
+	}
 
 	RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
 	RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
-	RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
 
 	RADEON_WRITE(R700_CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
 	RADEON_WRITE(R700_CGTS_SYS_TCC_DISABLE, 0);
 	RADEON_WRITE(R700_CGTS_TCC_DISABLE, 0);
-	RADEON_WRITE(R700_CGTS_USER_SYS_TCC_DISABLE, 0);
-	RADEON_WRITE(R700_CGTS_USER_TCC_DISABLE, 0);
 
 	num_qd_pipes =
-		R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK);
+		R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8);
 	RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK);
 	RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK);
 
@@ -1469,10 +1564,8 @@
 
 	RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, R700_STQ_SPLIT(0x30));
 
-	RADEON_WRITE(R600_TA_CNTL_AUX, (R600_DISABLE_CUBE_ANISO |
-					R600_SYNC_GRADIENT |
-					R600_SYNC_WALKER |
-					R600_SYNC_ALIGNER));
+	ta_aux_cntl = RADEON_READ(R600_TA_CNTL_AUX);
+	RADEON_WRITE(R600_TA_CNTL_AUX, ta_aux_cntl | R600_DISABLE_CUBE_ANISO);
 
 	sx_debug_1 = RADEON_READ(R700_SX_DEBUG_1);
 	sx_debug_1 |= R700_ENABLE_NEW_SMX_ADDRESS;
@@ -1483,14 +1576,28 @@
 	smx_dc_ctl0 |= R700_CACHE_DEPTH((dev_priv->r700_sx_num_of_sets * 64) - 1);
 	RADEON_WRITE(R600_SMX_DC_CTL0, smx_dc_ctl0);
 
-	RADEON_WRITE(R700_SMX_EVENT_CTL, (R700_ES_FLUSH_CTL(4) |
-					  R700_GS_FLUSH_CTL(4) |
-					  R700_ACK_FLUSH_CTL(3) |
-					  R700_SYNC_FLUSH_CTL));
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) != CHIP_RV740)
+		RADEON_WRITE(R700_SMX_EVENT_CTL, (R700_ES_FLUSH_CTL(4) |
+						  R700_GS_FLUSH_CTL(4) |
+						  R700_ACK_FLUSH_CTL(3) |
+						  R700_SYNC_FLUSH_CTL));
 
-	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)
-		RADEON_WRITE(R700_DB_DEBUG3, R700_DB_CLK_OFF_DELAY(0x1f));
-	else {
+	db_debug3 = RADEON_READ(R700_DB_DEBUG3);
+	db_debug3 &= ~R700_DB_CLK_OFF_DELAY(0x1f);
+	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
+	case CHIP_RV770:
+	case CHIP_RV740:
+		db_debug3 |= R700_DB_CLK_OFF_DELAY(0x1f);
+		break;
+	case CHIP_RV710:
+	case CHIP_RV730:
+	default:
+		db_debug3 |= R700_DB_CLK_OFF_DELAY(2);
+		break;
+	}
+	RADEON_WRITE(R700_DB_DEBUG3, db_debug3);
+
+	if ((dev_priv->flags & RADEON_FAMILY_MASK) != CHIP_RV770) {
 		db_debug4 = RADEON_READ(RV700_DB_DEBUG4);
 		db_debug4 |= RV700_DISABLE_TILE_COVERED_FOR_PS_ITER;
 		RADEON_WRITE(RV700_DB_DEBUG4, db_debug4);
@@ -1519,10 +1626,10 @@
 			    R600_ALU_UPDATE_FIFO_HIWATER(0x8));
 	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
 	case CHIP_RV770:
-		sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x1);
-		break;
 	case CHIP_RV730:
 	case CHIP_RV710:
+		sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x1);
+		break;
 	case CHIP_RV740:
 	default:
 		sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4);
@@ -2529,3 +2636,12 @@
 	mutex_unlock(&dev_priv->cs_mutex);
 	return r;
 }
+
+void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size)
+{
+	struct drm_radeon_private *dev_priv = dev->dev_private;
+
+	*npipes = dev_priv->r600_npipes;
+	*nbanks = dev_priv->r600_nbanks;
+	*group_size = dev_priv->r600_group_size;
+}
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index e4c45ec..cd2c63b 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -28,6 +28,7 @@
 #include "drmP.h"
 #include "radeon.h"
 #include "r600d.h"
+#include "r600_reg_safe.h"
 
 static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
 					struct radeon_cs_reloc **cs_reloc);
@@ -35,11 +36,313 @@
 					struct radeon_cs_reloc **cs_reloc);
 typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
 static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
+extern void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size);
+
 
 struct r600_cs_track {
-	u32	cb_color0_base_last;
+	/* configuration we miror so that we use same code btw kms/ums */
+	u32			group_size;
+	u32			nbanks;
+	u32			npipes;
+	/* value we track */
+	u32			nsamples;
+	u32			cb_color_base_last[8];
+	struct radeon_bo	*cb_color_bo[8];
+	u32			cb_color_bo_offset[8];
+	struct radeon_bo	*cb_color_frag_bo[8];
+	struct radeon_bo	*cb_color_tile_bo[8];
+	u32			cb_color_info[8];
+	u32			cb_color_size_idx[8];
+	u32			cb_target_mask;
+	u32			cb_shader_mask;
+	u32			cb_color_size[8];
+	u32			vgt_strmout_en;
+	u32			vgt_strmout_buffer_en;
+	u32			db_depth_control;
+	u32			db_depth_info;
+	u32			db_depth_size_idx;
+	u32			db_depth_view;
+	u32			db_depth_size;
+	u32			db_offset;
+	struct radeon_bo	*db_bo;
 };
 
+static inline int r600_bpe_from_format(u32 *bpe, u32 format)
+{
+	switch (format) {
+	case V_038004_COLOR_8:
+	case V_038004_COLOR_4_4:
+	case V_038004_COLOR_3_3_2:
+	case V_038004_FMT_1:
+		*bpe = 1;
+		break;
+	case V_038004_COLOR_16:
+	case V_038004_COLOR_16_FLOAT:
+	case V_038004_COLOR_8_8:
+	case V_038004_COLOR_5_6_5:
+	case V_038004_COLOR_6_5_5:
+	case V_038004_COLOR_1_5_5_5:
+	case V_038004_COLOR_4_4_4_4:
+	case V_038004_COLOR_5_5_5_1:
+		*bpe = 2;
+		break;
+	case V_038004_FMT_8_8_8:
+		*bpe = 3;
+		break;
+	case V_038004_COLOR_32:
+	case V_038004_COLOR_32_FLOAT:
+	case V_038004_COLOR_16_16:
+	case V_038004_COLOR_16_16_FLOAT:
+	case V_038004_COLOR_8_24:
+	case V_038004_COLOR_8_24_FLOAT:
+	case V_038004_COLOR_24_8:
+	case V_038004_COLOR_24_8_FLOAT:
+	case V_038004_COLOR_10_11_11:
+	case V_038004_COLOR_10_11_11_FLOAT:
+	case V_038004_COLOR_11_11_10:
+	case V_038004_COLOR_11_11_10_FLOAT:
+	case V_038004_COLOR_2_10_10_10:
+	case V_038004_COLOR_8_8_8_8:
+	case V_038004_COLOR_10_10_10_2:
+	case V_038004_FMT_5_9_9_9_SHAREDEXP:
+	case V_038004_FMT_32_AS_8:
+	case V_038004_FMT_32_AS_8_8:
+		*bpe = 4;
+		break;
+	case V_038004_COLOR_X24_8_32_FLOAT:
+	case V_038004_COLOR_32_32:
+	case V_038004_COLOR_32_32_FLOAT:
+	case V_038004_COLOR_16_16_16_16:
+	case V_038004_COLOR_16_16_16_16_FLOAT:
+		*bpe = 8;
+		break;
+	case V_038004_FMT_16_16_16:
+	case V_038004_FMT_16_16_16_FLOAT:
+		*bpe = 6;
+		break;
+	case V_038004_FMT_32_32_32:
+	case V_038004_FMT_32_32_32_FLOAT:
+		*bpe = 12;
+		break;
+	case V_038004_COLOR_32_32_32_32:
+	case V_038004_COLOR_32_32_32_32_FLOAT:
+		*bpe = 16;
+		break;
+	case V_038004_FMT_GB_GR:
+	case V_038004_FMT_BG_RG:
+	case V_038004_COLOR_INVALID:
+		*bpe = 16;
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void r600_cs_track_init(struct r600_cs_track *track)
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		track->cb_color_base_last[i] = 0;
+		track->cb_color_size[i] = 0;
+		track->cb_color_size_idx[i] = 0;
+		track->cb_color_info[i] = 0;
+		track->cb_color_bo[i] = NULL;
+		track->cb_color_bo_offset[i] = 0xFFFFFFFF;
+	}
+	track->cb_target_mask = 0xFFFFFFFF;
+	track->cb_shader_mask = 0xFFFFFFFF;
+	track->db_bo = NULL;
+	/* assume the biggest format and that htile is enabled */
+	track->db_depth_info = 7 | (1 << 25);
+	track->db_depth_view = 0xFFFFC000;
+	track->db_depth_size = 0xFFFFFFFF;
+	track->db_depth_size_idx = 0;
+	track->db_depth_control = 0xFFFFFFFF;
+}
+
+static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
+{
+	struct r600_cs_track *track = p->track;
+	u32 bpe = 0, pitch, slice_tile_max, size, tmp, height;
+	volatile u32 *ib = p->ib->ptr;
+
+	if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
+		dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
+		return -EINVAL;
+	}
+	size = radeon_bo_size(track->cb_color_bo[i]);
+	if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) {
+		dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
+			 __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]),
+			i, track->cb_color_info[i]);
+		return -EINVAL;
+	}
+	pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) << 3;
+	slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1;
+	if (!pitch) {
+		dev_warn(p->dev, "%s:%d cb pitch (%d) for %d invalid (0x%08X)\n",
+			__func__, __LINE__, pitch, i, track->cb_color_size[i]);
+		return -EINVAL;
+	}
+	height = size / (pitch * bpe);
+	if (height > 8192)
+		height = 8192;
+	switch (G_0280A0_ARRAY_MODE(track->cb_color_info[i])) {
+	case V_0280A0_ARRAY_LINEAR_GENERAL:
+	case V_0280A0_ARRAY_LINEAR_ALIGNED:
+		if (pitch & 0x3f) {
+			dev_warn(p->dev, "%s:%d cb pitch (%d x %d = %d) invalid\n",
+				__func__, __LINE__, pitch, bpe, pitch * bpe);
+			return -EINVAL;
+		}
+		if ((pitch * bpe) & (track->group_size - 1)) {
+			dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
+				__func__, __LINE__, pitch);
+			return -EINVAL;
+		}
+		break;
+	case V_0280A0_ARRAY_1D_TILED_THIN1:
+		if ((pitch * 8 * bpe * track->nsamples) & (track->group_size - 1)) {
+			dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
+				__func__, __LINE__, pitch);
+			return -EINVAL;
+		}
+		height &= ~0x7;
+		if (!height)
+			height = 8;
+		break;
+	case V_0280A0_ARRAY_2D_TILED_THIN1:
+		if (pitch & ((8 * track->nbanks) - 1)) {
+			dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
+				__func__, __LINE__, pitch);
+			return -EINVAL;
+		}
+		tmp = pitch * 8 * bpe * track->nsamples;
+		tmp = tmp / track->nbanks;
+		if (tmp & (track->group_size - 1)) {
+			dev_warn(p->dev, "%s:%d cb pitch (%d) invalid\n",
+				__func__, __LINE__, pitch);
+			return -EINVAL;
+		}
+		height &= ~((16 * track->npipes) - 1);
+		if (!height)
+			height = 16 * track->npipes;
+		break;
+	default:
+		dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
+			G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
+			track->cb_color_info[i]);
+		return -EINVAL;
+	}
+	/* check offset */
+	tmp = height * pitch;
+	if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
+		dev_warn(p->dev, "%s offset[%d] %d to big\n", __func__, i, track->cb_color_bo_offset[i]);
+		return -EINVAL;
+	}
+	/* limit max tile */
+	tmp = (height * pitch) >> 6;
+	if (tmp < slice_tile_max)
+		slice_tile_max = tmp;
+	tmp = S_028060_PITCH_TILE_MAX((pitch >> 3) - 1) |
+		S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
+	ib[track->cb_color_size_idx[i]] = tmp;
+	return 0;
+}
+
+static int r600_cs_track_check(struct radeon_cs_parser *p)
+{
+	struct r600_cs_track *track = p->track;
+	u32 tmp;
+	int r, i;
+	volatile u32 *ib = p->ib->ptr;
+
+	/* on legacy kernel we don't perform advanced check */
+	if (p->rdev == NULL)
+		return 0;
+	/* we don't support out buffer yet */
+	if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) {
+		dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
+		return -EINVAL;
+	}
+	/* check that we have a cb for each enabled target, we don't check
+	 * shader_mask because it seems mesa isn't always setting it :(
+	 */
+	tmp = track->cb_target_mask;
+	for (i = 0; i < 8; i++) {
+		if ((tmp >> (i * 4)) & 0xF) {
+			/* at least one component is enabled */
+			if (track->cb_color_bo[i] == NULL) {
+				dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
+					__func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i);
+				return -EINVAL;
+			}
+			/* perform rewrite of CB_COLOR[0-7]_SIZE */
+			r = r600_cs_track_validate_cb(p, i);
+			if (r)
+				return r;
+		}
+	}
+	/* Check depth buffer */
+	if (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
+		G_028800_Z_ENABLE(track->db_depth_control)) {
+		u32 nviews, bpe, ntiles;
+		if (track->db_bo == NULL) {
+			dev_warn(p->dev, "z/stencil with no depth buffer\n");
+			return -EINVAL;
+		}
+		if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
+			dev_warn(p->dev, "this kernel doesn't support z/stencil htile\n");
+			return -EINVAL;
+		}
+		switch (G_028010_FORMAT(track->db_depth_info)) {
+		case V_028010_DEPTH_16:
+			bpe = 2;
+			break;
+		case V_028010_DEPTH_X8_24:
+		case V_028010_DEPTH_8_24:
+		case V_028010_DEPTH_X8_24_FLOAT:
+		case V_028010_DEPTH_8_24_FLOAT:
+		case V_028010_DEPTH_32_FLOAT:
+			bpe = 4;
+			break;
+		case V_028010_DEPTH_X24_8_32_FLOAT:
+			bpe = 8;
+			break;
+		default:
+			dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
+			return -EINVAL;
+		}
+		if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
+			if (!track->db_depth_size_idx) {
+				dev_warn(p->dev, "z/stencil buffer size not set\n");
+				return -EINVAL;
+			}
+			printk_once(KERN_WARNING "You have old & broken userspace please consider updating mesa\n");
+			tmp = radeon_bo_size(track->db_bo) - track->db_offset;
+			tmp = (tmp / bpe) >> 6;
+			if (!tmp) {
+				dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
+						track->db_depth_size, bpe, track->db_offset,
+						radeon_bo_size(track->db_bo));
+				return -EINVAL;
+			}
+			ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
+		} else {
+			ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
+			nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
+			tmp = ntiles * bpe * 64 * nviews;
+			if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
+				dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %d -> %d have %ld)\n",
+						track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
+						radeon_bo_size(track->db_bo));
+				return -EINVAL;
+			}
+		}
+	}
+	return 0;
+}
+
 /**
  * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
  * @parser:	parser structure holding parsing context.
@@ -359,6 +662,334 @@
 	return 0;
 }
 
+/**
+ * r600_cs_check_reg() - check if register is authorized or not
+ * @parser: parser structure holding parsing context
+ * @reg: register we are testing
+ * @idx: index into the cs buffer
+ *
+ * This function will test against r600_reg_safe_bm and return 0
+ * if register is safe. If register is not flag as safe this function
+ * will test it against a list of register needind special handling.
+ */
+static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
+{
+	struct r600_cs_track *track = (struct r600_cs_track *)p->track;
+	struct radeon_cs_reloc *reloc;
+	u32 last_reg = ARRAY_SIZE(r600_reg_safe_bm);
+	u32 m, i, tmp, *ib;
+	int r;
+
+	i = (reg >> 7);
+	if (i > last_reg) {
+		dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
+		return -EINVAL;
+	}
+	m = 1 << ((reg >> 2) & 31);
+	if (!(r600_reg_safe_bm[i] & m))
+		return 0;
+	ib = p->ib->ptr;
+	switch (reg) {
+	/* force following reg to 0 in an attemp to disable out buffer
+	 * which will need us to better understand how it works to perform
+	 * security check on it (Jerome)
+	 */
+	case R_0288A8_SQ_ESGS_RING_ITEMSIZE:
+	case R_008C44_SQ_ESGS_RING_SIZE:
+	case R_0288B0_SQ_ESTMP_RING_ITEMSIZE:
+	case R_008C54_SQ_ESTMP_RING_SIZE:
+	case R_0288C0_SQ_FBUF_RING_ITEMSIZE:
+	case R_008C74_SQ_FBUF_RING_SIZE:
+	case R_0288B4_SQ_GSTMP_RING_ITEMSIZE:
+	case R_008C5C_SQ_GSTMP_RING_SIZE:
+	case R_0288AC_SQ_GSVS_RING_ITEMSIZE:
+	case R_008C4C_SQ_GSVS_RING_SIZE:
+	case R_0288BC_SQ_PSTMP_RING_ITEMSIZE:
+	case R_008C6C_SQ_PSTMP_RING_SIZE:
+	case R_0288C4_SQ_REDUC_RING_ITEMSIZE:
+	case R_008C7C_SQ_REDUC_RING_SIZE:
+	case R_0288B8_SQ_VSTMP_RING_ITEMSIZE:
+	case R_008C64_SQ_VSTMP_RING_SIZE:
+	case R_0288C8_SQ_GS_VERT_ITEMSIZE:
+		/* get value to populate the IB don't remove */
+		tmp =radeon_get_ib_value(p, idx);
+		ib[idx] = 0;
+		break;
+	case R_028800_DB_DEPTH_CONTROL:
+		track->db_depth_control = radeon_get_ib_value(p, idx);
+		break;
+	case R_028010_DB_DEPTH_INFO:
+		track->db_depth_info = radeon_get_ib_value(p, idx);
+		break;
+	case R_028004_DB_DEPTH_VIEW:
+		track->db_depth_view = radeon_get_ib_value(p, idx);
+		break;
+	case R_028000_DB_DEPTH_SIZE:
+		track->db_depth_size = radeon_get_ib_value(p, idx);
+		track->db_depth_size_idx = idx;
+		break;
+	case R_028AB0_VGT_STRMOUT_EN:
+		track->vgt_strmout_en = radeon_get_ib_value(p, idx);
+		break;
+	case R_028B20_VGT_STRMOUT_BUFFER_EN:
+		track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx);
+		break;
+	case R_028238_CB_TARGET_MASK:
+		track->cb_target_mask = radeon_get_ib_value(p, idx);
+		break;
+	case R_02823C_CB_SHADER_MASK:
+		track->cb_shader_mask = radeon_get_ib_value(p, idx);
+		break;
+	case R_028C04_PA_SC_AA_CONFIG:
+		tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx));
+		track->nsamples = 1 << tmp;
+		break;
+	case R_0280A0_CB_COLOR0_INFO:
+	case R_0280A4_CB_COLOR1_INFO:
+	case R_0280A8_CB_COLOR2_INFO:
+	case R_0280AC_CB_COLOR3_INFO:
+	case R_0280B0_CB_COLOR4_INFO:
+	case R_0280B4_CB_COLOR5_INFO:
+	case R_0280B8_CB_COLOR6_INFO:
+	case R_0280BC_CB_COLOR7_INFO:
+		tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
+		track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
+		break;
+	case R_028060_CB_COLOR0_SIZE:
+	case R_028064_CB_COLOR1_SIZE:
+	case R_028068_CB_COLOR2_SIZE:
+	case R_02806C_CB_COLOR3_SIZE:
+	case R_028070_CB_COLOR4_SIZE:
+	case R_028074_CB_COLOR5_SIZE:
+	case R_028078_CB_COLOR6_SIZE:
+	case R_02807C_CB_COLOR7_SIZE:
+		tmp = (reg - R_028060_CB_COLOR0_SIZE) / 4;
+		track->cb_color_size[tmp] = radeon_get_ib_value(p, idx);
+		track->cb_color_size_idx[tmp] = idx;
+		break;
+		/* This register were added late, there is userspace
+		 * which does provide relocation for those but set
+		 * 0 offset. In order to avoid breaking old userspace
+		 * we detect this and set address to point to last
+		 * CB_COLOR0_BASE, note that if userspace doesn't set
+		 * CB_COLOR0_BASE before this register we will report
+		 * error. Old userspace always set CB_COLOR0_BASE
+		 * before any of this.
+		 */
+	case R_0280E0_CB_COLOR0_FRAG:
+	case R_0280E4_CB_COLOR1_FRAG:
+	case R_0280E8_CB_COLOR2_FRAG:
+	case R_0280EC_CB_COLOR3_FRAG:
+	case R_0280F0_CB_COLOR4_FRAG:
+	case R_0280F4_CB_COLOR5_FRAG:
+	case R_0280F8_CB_COLOR6_FRAG:
+	case R_0280FC_CB_COLOR7_FRAG:
+		tmp = (reg - R_0280E0_CB_COLOR0_FRAG) / 4;
+		if (!r600_cs_packet_next_is_pkt3_nop(p)) {
+			if (!track->cb_color_base_last[tmp]) {
+				dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
+				return -EINVAL;
+			}
+			ib[idx] = track->cb_color_base_last[tmp];
+			printk_once(KERN_WARNING "You have old & broken userspace "
+					"please consider updating mesa & xf86-video-ati\n");
+			track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
+		} else {
+			r = r600_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+				return -EINVAL;
+			}
+			ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+			track->cb_color_frag_bo[tmp] = reloc->robj;
+		}
+		break;
+	case R_0280C0_CB_COLOR0_TILE:
+	case R_0280C4_CB_COLOR1_TILE:
+	case R_0280C8_CB_COLOR2_TILE:
+	case R_0280CC_CB_COLOR3_TILE:
+	case R_0280D0_CB_COLOR4_TILE:
+	case R_0280D4_CB_COLOR5_TILE:
+	case R_0280D8_CB_COLOR6_TILE:
+	case R_0280DC_CB_COLOR7_TILE:
+		tmp = (reg - R_0280C0_CB_COLOR0_TILE) / 4;
+		if (!r600_cs_packet_next_is_pkt3_nop(p)) {
+			if (!track->cb_color_base_last[tmp]) {
+				dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
+				return -EINVAL;
+			}
+			ib[idx] = track->cb_color_base_last[tmp];
+			printk_once(KERN_WARNING "You have old & broken userspace "
+					"please consider updating mesa & xf86-video-ati\n");
+			track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
+		} else {
+			r = r600_cs_packet_next_reloc(p, &reloc);
+			if (r) {
+				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
+				return -EINVAL;
+			}
+			ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+			track->cb_color_tile_bo[tmp] = reloc->robj;
+		}
+		break;
+	case CB_COLOR0_BASE:
+	case CB_COLOR1_BASE:
+	case CB_COLOR2_BASE:
+	case CB_COLOR3_BASE:
+	case CB_COLOR4_BASE:
+	case CB_COLOR5_BASE:
+	case CB_COLOR6_BASE:
+	case CB_COLOR7_BASE:
+		r = r600_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+					"0x%04X\n", reg);
+			return -EINVAL;
+		}
+		tmp = (reg - CB_COLOR0_BASE) / 4;
+		track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx);
+		ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+		track->cb_color_base_last[tmp] = ib[idx];
+		track->cb_color_bo[tmp] = reloc->robj;
+		break;
+	case DB_DEPTH_BASE:
+		r = r600_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+					"0x%04X\n", reg);
+			return -EINVAL;
+		}
+		track->db_offset = radeon_get_ib_value(p, idx);
+		ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+		track->db_bo = reloc->robj;
+		break;
+	case DB_HTILE_DATA_BASE:
+	case SQ_PGM_START_FS:
+	case SQ_PGM_START_ES:
+	case SQ_PGM_START_VS:
+	case SQ_PGM_START_GS:
+	case SQ_PGM_START_PS:
+		r = r600_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+					"0x%04X\n", reg);
+			return -EINVAL;
+		}
+		ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+		break;
+	default:
+		dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static inline unsigned minify(unsigned size, unsigned levels)
+{
+	size = size >> levels;
+	if (size < 1)
+		size = 1;
+	return size;
+}
+
+static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels,
+				unsigned w0, unsigned h0, unsigned d0, unsigned bpe,
+				unsigned *l0_size, unsigned *mipmap_size)
+{
+	unsigned offset, i, level, face;
+	unsigned width, height, depth, rowstride, size;
+
+	w0 = minify(w0, 0);
+	h0 = minify(h0, 0);
+	d0 = minify(d0, 0);
+	for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) {
+		width = minify(w0, i);
+		height = minify(h0, i);
+		depth = minify(d0, i);
+		for(face = 0; face < nfaces; face++) {
+			rowstride = ((width * bpe) + 255) & ~255;
+			size = height * rowstride * depth;
+			offset += size;
+			offset = (offset + 0x1f) & ~0x1f;
+		}
+	}
+	*l0_size = (((w0 * bpe) + 255) & ~255) * h0 * d0;
+	*mipmap_size = offset;
+	if (!blevel)
+		*mipmap_size -= *l0_size;
+	if (!nlevels)
+		*mipmap_size = *l0_size;
+}
+
+/**
+ * r600_check_texture_resource() - check if register is authorized or not
+ * @p: parser structure holding parsing context
+ * @idx: index into the cs buffer
+ * @texture: texture's bo structure
+ * @mipmap: mipmap's bo structure
+ *
+ * This function will check that the resource has valid field and that
+ * the texture and mipmap bo object are big enough to cover this resource.
+ */
+static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
+						struct radeon_bo *texture,
+						struct radeon_bo *mipmap)
+{
+	u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0;
+	u32 word0, word1, l0_size, mipmap_size;
+
+	/* on legacy kernel we don't perform advanced check */
+	if (p->rdev == NULL)
+		return 0;
+	word0 = radeon_get_ib_value(p, idx + 0);
+	word1 = radeon_get_ib_value(p, idx + 1);
+	w0 = G_038000_TEX_WIDTH(word0) + 1;
+	h0 = G_038004_TEX_HEIGHT(word1) + 1;
+	d0 = G_038004_TEX_DEPTH(word1);
+	nfaces = 1;
+	switch (G_038000_DIM(word0)) {
+	case V_038000_SQ_TEX_DIM_1D:
+	case V_038000_SQ_TEX_DIM_2D:
+	case V_038000_SQ_TEX_DIM_3D:
+		break;
+	case V_038000_SQ_TEX_DIM_CUBEMAP:
+		nfaces = 6;
+		break;
+	case V_038000_SQ_TEX_DIM_1D_ARRAY:
+	case V_038000_SQ_TEX_DIM_2D_ARRAY:
+	case V_038000_SQ_TEX_DIM_2D_MSAA:
+	case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA:
+	default:
+		dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0));
+		return -EINVAL;
+	}
+	if (r600_bpe_from_format(&bpe,  G_038004_DATA_FORMAT(word1))) {
+		dev_warn(p->dev, "%s:%d texture invalid format %d\n",
+			 __func__, __LINE__, G_038004_DATA_FORMAT(word1));
+		return -EINVAL;
+	}
+	word0 = radeon_get_ib_value(p, idx + 4);
+	word1 = radeon_get_ib_value(p, idx + 5);
+	blevel = G_038010_BASE_LEVEL(word0);
+	nlevels = G_038014_LAST_LEVEL(word1);
+	r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe, &l0_size, &mipmap_size);
+	/* using get ib will give us the offset into the texture bo */
+	word0 = radeon_get_ib_value(p, idx + 2);
+	if ((l0_size + word0) > radeon_bo_size(texture)) {
+		dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n",
+			w0, h0, bpe, word0, l0_size, radeon_bo_size(texture));
+		return -EINVAL;
+	}
+	/* using get ib will give us the offset into the mipmap bo */
+	word0 = radeon_get_ib_value(p, idx + 3);
+	if ((mipmap_size + word0) > radeon_bo_size(mipmap)) {
+		dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
+			w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int r600_packet3_check(struct radeon_cs_parser *p,
 				struct radeon_cs_packet *pkt)
 {
@@ -408,12 +1039,22 @@
 		}
 		ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
 		ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+		r = r600_cs_track_check(p);
+		if (r) {
+			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+			return r;
+		}
 		break;
 	case PACKET3_DRAW_INDEX_AUTO:
 		if (pkt->count != 1) {
 			DRM_ERROR("bad DRAW_INDEX_AUTO\n");
 			return -EINVAL;
 		}
+		r = r600_cs_track_check(p);
+		if (r) {
+			dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
+			return r;
+		}
 		break;
 	case PACKET3_DRAW_INDEX_IMMD_BE:
 	case PACKET3_DRAW_INDEX_IMMD:
@@ -421,6 +1062,11 @@
 			DRM_ERROR("bad DRAW_INDEX_IMMD\n");
 			return -EINVAL;
 		}
+		r = r600_cs_track_check(p);
+		if (r) {
+			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
+			return r;
+		}
 		break;
 	case PACKET3_WAIT_REG_MEM:
 		if (pkt->count != 5) {
@@ -493,30 +1139,9 @@
 		}
 		for (i = 0; i < pkt->count; i++) {
 			reg = start_reg + (4 * i);
-			switch (reg) {
-			case SQ_ESGS_RING_BASE:
-			case SQ_GSVS_RING_BASE:
-			case SQ_ESTMP_RING_BASE:
-			case SQ_GSTMP_RING_BASE:
-			case SQ_VSTMP_RING_BASE:
-			case SQ_PSTMP_RING_BASE:
-			case SQ_FBUF_RING_BASE:
-			case SQ_REDUC_RING_BASE:
-			case SX_MEMORY_EXPORT_BASE:
-				r = r600_cs_packet_next_reloc(p, &reloc);
-				if (r) {
-					DRM_ERROR("bad SET_CONFIG_REG "
-							"0x%04X\n", reg);
-					return -EINVAL;
-				}
-				ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-				break;
-			case CP_COHER_BASE:
-				/* use PACKET3_SURFACE_SYNC */
-				return -EINVAL;
-			default:
-				break;
-			}
+			r = r600_cs_check_reg(p, reg, idx+1+i);
+			if (r)
+				return r;
 		}
 		break;
 	case PACKET3_SET_CONTEXT_REG:
@@ -530,106 +1155,9 @@
 		}
 		for (i = 0; i < pkt->count; i++) {
 			reg = start_reg + (4 * i);
-			switch (reg) {
-			/* This register were added late, there is userspace
-			 * which does provide relocation for those but set
-			 * 0 offset. In order to avoid breaking old userspace
-			 * we detect this and set address to point to last
-			 * CB_COLOR0_BASE, note that if userspace doesn't set
-			 * CB_COLOR0_BASE before this register we will report
-			 * error. Old userspace always set CB_COLOR0_BASE
-			 * before any of this.
-			 */
-			case R_0280E0_CB_COLOR0_FRAG:
-			case R_0280E4_CB_COLOR1_FRAG:
-			case R_0280E8_CB_COLOR2_FRAG:
-			case R_0280EC_CB_COLOR3_FRAG:
-			case R_0280F0_CB_COLOR4_FRAG:
-			case R_0280F4_CB_COLOR5_FRAG:
-			case R_0280F8_CB_COLOR6_FRAG:
-			case R_0280FC_CB_COLOR7_FRAG:
-			case R_0280C0_CB_COLOR0_TILE:
-			case R_0280C4_CB_COLOR1_TILE:
-			case R_0280C8_CB_COLOR2_TILE:
-			case R_0280CC_CB_COLOR3_TILE:
-			case R_0280D0_CB_COLOR4_TILE:
-			case R_0280D4_CB_COLOR5_TILE:
-			case R_0280D8_CB_COLOR6_TILE:
-			case R_0280DC_CB_COLOR7_TILE:
-				if (!r600_cs_packet_next_is_pkt3_nop(p)) {
-					if (!track->cb_color0_base_last) {
-						dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
-						return -EINVAL;
-					}
-					ib[idx+1+i] = track->cb_color0_base_last;
-					printk_once(KERN_WARNING "radeon: You have old & broken userspace "
-						"please consider updating mesa & xf86-video-ati\n");
-				} else {
-					r = r600_cs_packet_next_reloc(p, &reloc);
-					if (r) {
-						dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
-						return -EINVAL;
-					}
-					ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-				}
-				break;
-			case DB_DEPTH_BASE:
-			case DB_HTILE_DATA_BASE:
-			case CB_COLOR0_BASE:
-				r = r600_cs_packet_next_reloc(p, &reloc);
-				if (r) {
-					DRM_ERROR("bad SET_CONTEXT_REG "
-							"0x%04X\n", reg);
-					return -EINVAL;
-				}
-				ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-				track->cb_color0_base_last = ib[idx+1+i];
-				break;
-			case CB_COLOR1_BASE:
-			case CB_COLOR2_BASE:
-			case CB_COLOR3_BASE:
-			case CB_COLOR4_BASE:
-			case CB_COLOR5_BASE:
-			case CB_COLOR6_BASE:
-			case CB_COLOR7_BASE:
-			case SQ_PGM_START_FS:
-			case SQ_PGM_START_ES:
-			case SQ_PGM_START_VS:
-			case SQ_PGM_START_GS:
-			case SQ_PGM_START_PS:
-				r = r600_cs_packet_next_reloc(p, &reloc);
-				if (r) {
-					DRM_ERROR("bad SET_CONTEXT_REG "
-							"0x%04X\n", reg);
-					return -EINVAL;
-				}
-				ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-				break;
-			case VGT_DMA_BASE:
-			case VGT_DMA_BASE_HI:
-				/* These should be handled by DRAW_INDEX packet 3 */
-			case VGT_STRMOUT_BASE_OFFSET_0:
-			case VGT_STRMOUT_BASE_OFFSET_1:
-			case VGT_STRMOUT_BASE_OFFSET_2:
-			case VGT_STRMOUT_BASE_OFFSET_3:
-			case VGT_STRMOUT_BASE_OFFSET_HI_0:
-			case VGT_STRMOUT_BASE_OFFSET_HI_1:
-			case VGT_STRMOUT_BASE_OFFSET_HI_2:
-			case VGT_STRMOUT_BASE_OFFSET_HI_3:
-			case VGT_STRMOUT_BUFFER_BASE_0:
-			case VGT_STRMOUT_BUFFER_BASE_1:
-			case VGT_STRMOUT_BUFFER_BASE_2:
-			case VGT_STRMOUT_BUFFER_BASE_3:
-			case VGT_STRMOUT_BUFFER_OFFSET_0:
-			case VGT_STRMOUT_BUFFER_OFFSET_1:
-			case VGT_STRMOUT_BUFFER_OFFSET_2:
-			case VGT_STRMOUT_BUFFER_OFFSET_3:
-				/* These should be handled by STRMOUT_BUFFER packet 3 */
-				DRM_ERROR("bad context reg: 0x%08x\n", reg);
-				return -EINVAL;
-			default:
-				break;
-			}
+			r = r600_cs_check_reg(p, reg, idx+1+i);
+			if (r)
+				return r;
 		}
 		break;
 	case PACKET3_SET_RESOURCE:
@@ -646,6 +1174,9 @@
 			return -EINVAL;
 		}
 		for (i = 0; i < (pkt->count / 7); i++) {
+			struct radeon_bo *texture, *mipmap;
+			u32 size, offset;
+
 			switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
 			case SQ_TEX_VTX_VALID_TEXTURE:
 				/* tex base */
@@ -655,6 +1186,7 @@
 					return -EINVAL;
 				}
 				ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+				texture = reloc->robj;
 				/* tex mip base */
 				r = r600_cs_packet_next_reloc(p, &reloc);
 				if (r) {
@@ -662,6 +1194,11 @@
 					return -EINVAL;
 				}
 				ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+				mipmap = reloc->robj;
+				r = r600_check_texture_resource(p,  idx+(i*7)+1,
+						texture, mipmap);
+				if (r)
+					return r;
 				break;
 			case SQ_TEX_VTX_VALID_BUFFER:
 				/* vtx base */
@@ -670,6 +1207,13 @@
 					DRM_ERROR("bad SET_RESOURCE\n");
 					return -EINVAL;
 				}
+				offset = radeon_get_ib_value(p, idx+1+(i*7)+0);
+				size = radeon_get_ib_value(p, idx+1+(i*7)+1);
+				if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
+					/* force size to size of the buffer */
+					dev_warn(p->dev, "vbo resource seems too big for the bo\n");
+					ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj);
+				}
 				ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
 				ib[idx+1+(i*7)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
 				break;
@@ -760,11 +1304,28 @@
 	struct r600_cs_track *track;
 	int r;
 
-	track = kzalloc(sizeof(*track), GFP_KERNEL);
-	p->track = track;
+	if (p->track == NULL) {
+		/* initialize tracker, we are in kms */
+		track = kzalloc(sizeof(*track), GFP_KERNEL);
+		if (track == NULL)
+			return -ENOMEM;
+		r600_cs_track_init(track);
+		if (p->rdev->family < CHIP_RV770) {
+			track->npipes = p->rdev->config.r600.tiling_npipes;
+			track->nbanks = p->rdev->config.r600.tiling_nbanks;
+			track->group_size = p->rdev->config.r600.tiling_group_size;
+		} else if (p->rdev->family <= CHIP_RV740) {
+			track->npipes = p->rdev->config.rv770.tiling_npipes;
+			track->nbanks = p->rdev->config.rv770.tiling_nbanks;
+			track->group_size = p->rdev->config.rv770.tiling_group_size;
+		}
+		p->track = track;
+	}
 	do {
 		r = r600_cs_packet_parse(p, &pkt, p->idx);
 		if (r) {
+			kfree(p->track);
+			p->track = NULL;
 			return r;
 		}
 		p->idx += pkt.count + 2;
@@ -779,9 +1340,13 @@
 			break;
 		default:
 			DRM_ERROR("Unknown packet type %d !\n", pkt.type);
+			kfree(p->track);
+			p->track = NULL;
 			return -EINVAL;
 		}
 		if (r) {
+			kfree(p->track);
+			p->track = NULL;
 			return r;
 		}
 	} while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
@@ -791,6 +1356,8 @@
 		mdelay(1);
 	}
 #endif
+	kfree(p->track);
+	p->track = NULL;
 	return 0;
 }
 
@@ -833,9 +1400,16 @@
 {
 	struct radeon_cs_parser parser;
 	struct radeon_cs_chunk *ib_chunk;
-	struct radeon_ib	fake_ib;
+	struct radeon_ib fake_ib;
+	struct r600_cs_track *track;
 	int r;
 
+	/* initialize tracker */
+	track = kzalloc(sizeof(*track), GFP_KERNEL);
+	if (track == NULL)
+		return -ENOMEM;
+	r600_cs_track_init(track);
+	r600_cs_legacy_get_tiling_conf(dev, &track->npipes, &track->nbanks, &track->group_size);
 	/* initialize parser */
 	memset(&parser, 0, sizeof(struct radeon_cs_parser));
 	parser.filp = filp;
@@ -843,6 +1417,7 @@
 	parser.rdev = NULL;
 	parser.family = family;
 	parser.ib = &fake_ib;
+	parser.track = track;
 	fake_ib.ptr = ib;
 	r = radeon_cs_parser_init(&parser, data);
 	if (r) {
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 3048088..5b2e4d4 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -883,6 +883,16 @@
 
 #define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL		0x5480
 
+#define R_028C04_PA_SC_AA_CONFIG                     0x028C04
+#define   S_028C04_MSAA_NUM_SAMPLES(x)                 (((x) & 0x3) << 0)
+#define   G_028C04_MSAA_NUM_SAMPLES(x)                 (((x) >> 0) & 0x3)
+#define   C_028C04_MSAA_NUM_SAMPLES                    0xFFFFFFFC
+#define   S_028C04_AA_MASK_CENTROID_DTMN(x)            (((x) & 0x1) << 4)
+#define   G_028C04_AA_MASK_CENTROID_DTMN(x)            (((x) >> 4) & 0x1)
+#define   C_028C04_AA_MASK_CENTROID_DTMN               0xFFFFFFEF
+#define   S_028C04_MAX_SAMPLE_DIST(x)                  (((x) & 0xF) << 13)
+#define   G_028C04_MAX_SAMPLE_DIST(x)                  (((x) >> 13) & 0xF)
+#define   C_028C04_MAX_SAMPLE_DIST                     0xFFFE1FFF
 #define R_0280E0_CB_COLOR0_FRAG                      0x0280E0
 #define   S_0280E0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
 #define   G_0280E0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
@@ -905,6 +915,461 @@
 #define R_0280D4_CB_COLOR5_TILE                      0x0280D4
 #define R_0280D8_CB_COLOR6_TILE                      0x0280D8
 #define R_0280DC_CB_COLOR7_TILE                      0x0280DC
-
+#define R_0280A0_CB_COLOR0_INFO                      0x0280A0
+#define   S_0280A0_ENDIAN(x)                           (((x) & 0x3) << 0)
+#define   G_0280A0_ENDIAN(x)                           (((x) >> 0) & 0x3)
+#define   C_0280A0_ENDIAN                              0xFFFFFFFC
+#define   S_0280A0_FORMAT(x)                           (((x) & 0x3F) << 2)
+#define   G_0280A0_FORMAT(x)                           (((x) >> 2) & 0x3F)
+#define   C_0280A0_FORMAT                              0xFFFFFF03
+#define     V_0280A0_COLOR_INVALID                     0x00000000
+#define     V_0280A0_COLOR_8                           0x00000001
+#define     V_0280A0_COLOR_4_4                         0x00000002
+#define     V_0280A0_COLOR_3_3_2                       0x00000003
+#define     V_0280A0_COLOR_16                          0x00000005
+#define     V_0280A0_COLOR_16_FLOAT                    0x00000006
+#define     V_0280A0_COLOR_8_8                         0x00000007
+#define     V_0280A0_COLOR_5_6_5                       0x00000008
+#define     V_0280A0_COLOR_6_5_5                       0x00000009
+#define     V_0280A0_COLOR_1_5_5_5                     0x0000000A
+#define     V_0280A0_COLOR_4_4_4_4                     0x0000000B
+#define     V_0280A0_COLOR_5_5_5_1                     0x0000000C
+#define     V_0280A0_COLOR_32                          0x0000000D
+#define     V_0280A0_COLOR_32_FLOAT                    0x0000000E
+#define     V_0280A0_COLOR_16_16                       0x0000000F
+#define     V_0280A0_COLOR_16_16_FLOAT                 0x00000010
+#define     V_0280A0_COLOR_8_24                        0x00000011
+#define     V_0280A0_COLOR_8_24_FLOAT                  0x00000012
+#define     V_0280A0_COLOR_24_8                        0x00000013
+#define     V_0280A0_COLOR_24_8_FLOAT                  0x00000014
+#define     V_0280A0_COLOR_10_11_11                    0x00000015
+#define     V_0280A0_COLOR_10_11_11_FLOAT              0x00000016
+#define     V_0280A0_COLOR_11_11_10                    0x00000017
+#define     V_0280A0_COLOR_11_11_10_FLOAT              0x00000018
+#define     V_0280A0_COLOR_2_10_10_10                  0x00000019
+#define     V_0280A0_COLOR_8_8_8_8                     0x0000001A
+#define     V_0280A0_COLOR_10_10_10_2                  0x0000001B
+#define     V_0280A0_COLOR_X24_8_32_FLOAT              0x0000001C
+#define     V_0280A0_COLOR_32_32                       0x0000001D
+#define     V_0280A0_COLOR_32_32_FLOAT                 0x0000001E
+#define     V_0280A0_COLOR_16_16_16_16                 0x0000001F
+#define     V_0280A0_COLOR_16_16_16_16_FLOAT           0x00000020
+#define     V_0280A0_COLOR_32_32_32_32                 0x00000022
+#define     V_0280A0_COLOR_32_32_32_32_FLOAT           0x00000023
+#define   S_0280A0_ARRAY_MODE(x)                       (((x) & 0xF) << 8)
+#define   G_0280A0_ARRAY_MODE(x)                       (((x) >> 8) & 0xF)
+#define   C_0280A0_ARRAY_MODE                          0xFFFFF0FF
+#define     V_0280A0_ARRAY_LINEAR_GENERAL              0x00000000
+#define     V_0280A0_ARRAY_LINEAR_ALIGNED              0x00000001
+#define     V_0280A0_ARRAY_1D_TILED_THIN1              0x00000002
+#define     V_0280A0_ARRAY_2D_TILED_THIN1              0x00000004
+#define   S_0280A0_NUMBER_TYPE(x)                      (((x) & 0x7) << 12)
+#define   G_0280A0_NUMBER_TYPE(x)                      (((x) >> 12) & 0x7)
+#define   C_0280A0_NUMBER_TYPE                         0xFFFF8FFF
+#define   S_0280A0_READ_SIZE(x)                        (((x) & 0x1) << 15)
+#define   G_0280A0_READ_SIZE(x)                        (((x) >> 15) & 0x1)
+#define   C_0280A0_READ_SIZE                           0xFFFF7FFF
+#define   S_0280A0_COMP_SWAP(x)                        (((x) & 0x3) << 16)
+#define   G_0280A0_COMP_SWAP(x)                        (((x) >> 16) & 0x3)
+#define   C_0280A0_COMP_SWAP                           0xFFFCFFFF
+#define   S_0280A0_TILE_MODE(x)                        (((x) & 0x3) << 18)
+#define   G_0280A0_TILE_MODE(x)                        (((x) >> 18) & 0x3)
+#define   C_0280A0_TILE_MODE                           0xFFF3FFFF
+#define   S_0280A0_BLEND_CLAMP(x)                      (((x) & 0x1) << 20)
+#define   G_0280A0_BLEND_CLAMP(x)                      (((x) >> 20) & 0x1)
+#define   C_0280A0_BLEND_CLAMP                         0xFFEFFFFF
+#define   S_0280A0_CLEAR_COLOR(x)                      (((x) & 0x1) << 21)
+#define   G_0280A0_CLEAR_COLOR(x)                      (((x) >> 21) & 0x1)
+#define   C_0280A0_CLEAR_COLOR                         0xFFDFFFFF
+#define   S_0280A0_BLEND_BYPASS(x)                     (((x) & 0x1) << 22)
+#define   G_0280A0_BLEND_BYPASS(x)                     (((x) >> 22) & 0x1)
+#define   C_0280A0_BLEND_BYPASS                        0xFFBFFFFF
+#define   S_0280A0_BLEND_FLOAT32(x)                    (((x) & 0x1) << 23)
+#define   G_0280A0_BLEND_FLOAT32(x)                    (((x) >> 23) & 0x1)
+#define   C_0280A0_BLEND_FLOAT32                       0xFF7FFFFF
+#define   S_0280A0_SIMPLE_FLOAT(x)                     (((x) & 0x1) << 24)
+#define   G_0280A0_SIMPLE_FLOAT(x)                     (((x) >> 24) & 0x1)
+#define   C_0280A0_SIMPLE_FLOAT                        0xFEFFFFFF
+#define   S_0280A0_ROUND_MODE(x)                       (((x) & 0x1) << 25)
+#define   G_0280A0_ROUND_MODE(x)                       (((x) >> 25) & 0x1)
+#define   C_0280A0_ROUND_MODE                          0xFDFFFFFF
+#define   S_0280A0_TILE_COMPACT(x)                     (((x) & 0x1) << 26)
+#define   G_0280A0_TILE_COMPACT(x)                     (((x) >> 26) & 0x1)
+#define   C_0280A0_TILE_COMPACT                        0xFBFFFFFF
+#define   S_0280A0_SOURCE_FORMAT(x)                    (((x) & 0x1) << 27)
+#define   G_0280A0_SOURCE_FORMAT(x)                    (((x) >> 27) & 0x1)
+#define   C_0280A0_SOURCE_FORMAT                       0xF7FFFFFF
+#define R_0280A4_CB_COLOR1_INFO                      0x0280A4
+#define R_0280A8_CB_COLOR2_INFO                      0x0280A8
+#define R_0280AC_CB_COLOR3_INFO                      0x0280AC
+#define R_0280B0_CB_COLOR4_INFO                      0x0280B0
+#define R_0280B4_CB_COLOR5_INFO                      0x0280B4
+#define R_0280B8_CB_COLOR6_INFO                      0x0280B8
+#define R_0280BC_CB_COLOR7_INFO                      0x0280BC
+#define R_028060_CB_COLOR0_SIZE                      0x028060
+#define   S_028060_PITCH_TILE_MAX(x)                   (((x) & 0x3FF) << 0)
+#define   G_028060_PITCH_TILE_MAX(x)                   (((x) >> 0) & 0x3FF)
+#define   C_028060_PITCH_TILE_MAX                      0xFFFFFC00
+#define   S_028060_SLICE_TILE_MAX(x)                   (((x) & 0xFFFFF) << 10)
+#define   G_028060_SLICE_TILE_MAX(x)                   (((x) >> 10) & 0xFFFFF)
+#define   C_028060_SLICE_TILE_MAX                      0xC00003FF
+#define R_028064_CB_COLOR1_SIZE                      0x028064
+#define R_028068_CB_COLOR2_SIZE                      0x028068
+#define R_02806C_CB_COLOR3_SIZE                      0x02806C
+#define R_028070_CB_COLOR4_SIZE                      0x028070
+#define R_028074_CB_COLOR5_SIZE                      0x028074
+#define R_028078_CB_COLOR6_SIZE                      0x028078
+#define R_02807C_CB_COLOR7_SIZE                      0x02807C
+#define R_028238_CB_TARGET_MASK                      0x028238
+#define   S_028238_TARGET0_ENABLE(x)                   (((x) & 0xF) << 0)
+#define   G_028238_TARGET0_ENABLE(x)                   (((x) >> 0) & 0xF)
+#define   C_028238_TARGET0_ENABLE                      0xFFFFFFF0
+#define   S_028238_TARGET1_ENABLE(x)                   (((x) & 0xF) << 4)
+#define   G_028238_TARGET1_ENABLE(x)                   (((x) >> 4) & 0xF)
+#define   C_028238_TARGET1_ENABLE                      0xFFFFFF0F
+#define   S_028238_TARGET2_ENABLE(x)                   (((x) & 0xF) << 8)
+#define   G_028238_TARGET2_ENABLE(x)                   (((x) >> 8) & 0xF)
+#define   C_028238_TARGET2_ENABLE                      0xFFFFF0FF
+#define   S_028238_TARGET3_ENABLE(x)                   (((x) & 0xF) << 12)
+#define   G_028238_TARGET3_ENABLE(x)                   (((x) >> 12) & 0xF)
+#define   C_028238_TARGET3_ENABLE                      0xFFFF0FFF
+#define   S_028238_TARGET4_ENABLE(x)                   (((x) & 0xF) << 16)
+#define   G_028238_TARGET4_ENABLE(x)                   (((x) >> 16) & 0xF)
+#define   C_028238_TARGET4_ENABLE                      0xFFF0FFFF
+#define   S_028238_TARGET5_ENABLE(x)                   (((x) & 0xF) << 20)
+#define   G_028238_TARGET5_ENABLE(x)                   (((x) >> 20) & 0xF)
+#define   C_028238_TARGET5_ENABLE                      0xFF0FFFFF
+#define   S_028238_TARGET6_ENABLE(x)                   (((x) & 0xF) << 24)
+#define   G_028238_TARGET6_ENABLE(x)                   (((x) >> 24) & 0xF)
+#define   C_028238_TARGET6_ENABLE                      0xF0FFFFFF
+#define   S_028238_TARGET7_ENABLE(x)                   (((x) & 0xF) << 28)
+#define   G_028238_TARGET7_ENABLE(x)                   (((x) >> 28) & 0xF)
+#define   C_028238_TARGET7_ENABLE                      0x0FFFFFFF
+#define R_02823C_CB_SHADER_MASK                      0x02823C
+#define   S_02823C_OUTPUT0_ENABLE(x)                   (((x) & 0xF) << 0)
+#define   G_02823C_OUTPUT0_ENABLE(x)                   (((x) >> 0) & 0xF)
+#define   C_02823C_OUTPUT0_ENABLE                      0xFFFFFFF0
+#define   S_02823C_OUTPUT1_ENABLE(x)                   (((x) & 0xF) << 4)
+#define   G_02823C_OUTPUT1_ENABLE(x)                   (((x) >> 4) & 0xF)
+#define   C_02823C_OUTPUT1_ENABLE                      0xFFFFFF0F
+#define   S_02823C_OUTPUT2_ENABLE(x)                   (((x) & 0xF) << 8)
+#define   G_02823C_OUTPUT2_ENABLE(x)                   (((x) >> 8) & 0xF)
+#define   C_02823C_OUTPUT2_ENABLE                      0xFFFFF0FF
+#define   S_02823C_OUTPUT3_ENABLE(x)                   (((x) & 0xF) << 12)
+#define   G_02823C_OUTPUT3_ENABLE(x)                   (((x) >> 12) & 0xF)
+#define   C_02823C_OUTPUT3_ENABLE                      0xFFFF0FFF
+#define   S_02823C_OUTPUT4_ENABLE(x)                   (((x) & 0xF) << 16)
+#define   G_02823C_OUTPUT4_ENABLE(x)                   (((x) >> 16) & 0xF)
+#define   C_02823C_OUTPUT4_ENABLE                      0xFFF0FFFF
+#define   S_02823C_OUTPUT5_ENABLE(x)                   (((x) & 0xF) << 20)
+#define   G_02823C_OUTPUT5_ENABLE(x)                   (((x) >> 20) & 0xF)
+#define   C_02823C_OUTPUT5_ENABLE                      0xFF0FFFFF
+#define   S_02823C_OUTPUT6_ENABLE(x)                   (((x) & 0xF) << 24)
+#define   G_02823C_OUTPUT6_ENABLE(x)                   (((x) >> 24) & 0xF)
+#define   C_02823C_OUTPUT6_ENABLE                      0xF0FFFFFF
+#define   S_02823C_OUTPUT7_ENABLE(x)                   (((x) & 0xF) << 28)
+#define   G_02823C_OUTPUT7_ENABLE(x)                   (((x) >> 28) & 0xF)
+#define   C_02823C_OUTPUT7_ENABLE                      0x0FFFFFFF
+#define R_028AB0_VGT_STRMOUT_EN                      0x028AB0
+#define   S_028AB0_STREAMOUT(x)                        (((x) & 0x1) << 0)
+#define   G_028AB0_STREAMOUT(x)                        (((x) >> 0) & 0x1)
+#define   C_028AB0_STREAMOUT                           0xFFFFFFFE
+#define R_028B20_VGT_STRMOUT_BUFFER_EN               0x028B20
+#define   S_028B20_BUFFER_0_EN(x)                      (((x) & 0x1) << 0)
+#define   G_028B20_BUFFER_0_EN(x)                      (((x) >> 0) & 0x1)
+#define   C_028B20_BUFFER_0_EN                         0xFFFFFFFE
+#define   S_028B20_BUFFER_1_EN(x)                      (((x) & 0x1) << 1)
+#define   G_028B20_BUFFER_1_EN(x)                      (((x) >> 1) & 0x1)
+#define   C_028B20_BUFFER_1_EN                         0xFFFFFFFD
+#define   S_028B20_BUFFER_2_EN(x)                      (((x) & 0x1) << 2)
+#define   G_028B20_BUFFER_2_EN(x)                      (((x) >> 2) & 0x1)
+#define   C_028B20_BUFFER_2_EN                         0xFFFFFFFB
+#define   S_028B20_BUFFER_3_EN(x)                      (((x) & 0x1) << 3)
+#define   G_028B20_BUFFER_3_EN(x)                      (((x) >> 3) & 0x1)
+#define   C_028B20_BUFFER_3_EN                         0xFFFFFFF7
+#define   S_028B20_SIZE(x)                             (((x) & 0xFFFFFFFF) << 0)
+#define   G_028B20_SIZE(x)                             (((x) >> 0) & 0xFFFFFFFF)
+#define   C_028B20_SIZE                                0x00000000
+#define R_038000_SQ_TEX_RESOURCE_WORD0_0             0x038000
+#define   S_038000_DIM(x)                              (((x) & 0x7) << 0)
+#define   G_038000_DIM(x)                              (((x) >> 0) & 0x7)
+#define   C_038000_DIM                                 0xFFFFFFF8
+#define     V_038000_SQ_TEX_DIM_1D                     0x00000000
+#define     V_038000_SQ_TEX_DIM_2D                     0x00000001
+#define     V_038000_SQ_TEX_DIM_3D                     0x00000002
+#define     V_038000_SQ_TEX_DIM_CUBEMAP                0x00000003
+#define     V_038000_SQ_TEX_DIM_1D_ARRAY               0x00000004
+#define     V_038000_SQ_TEX_DIM_2D_ARRAY               0x00000005
+#define     V_038000_SQ_TEX_DIM_2D_MSAA                0x00000006
+#define     V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA          0x00000007
+#define   S_038000_TILE_MODE(x)                        (((x) & 0xF) << 3)
+#define   G_038000_TILE_MODE(x)                        (((x) >> 3) & 0xF)
+#define   C_038000_TILE_MODE                           0xFFFFFF87
+#define   S_038000_TILE_TYPE(x)                        (((x) & 0x1) << 7)
+#define   G_038000_TILE_TYPE(x)                        (((x) >> 7) & 0x1)
+#define   C_038000_TILE_TYPE                           0xFFFFFF7F
+#define   S_038000_PITCH(x)                            (((x) & 0x7FF) << 8)
+#define   G_038000_PITCH(x)                            (((x) >> 8) & 0x7FF)
+#define   C_038000_PITCH                               0xFFF800FF
+#define   S_038000_TEX_WIDTH(x)                        (((x) & 0x1FFF) << 19)
+#define   G_038000_TEX_WIDTH(x)                        (((x) >> 19) & 0x1FFF)
+#define   C_038000_TEX_WIDTH                           0x0007FFFF
+#define R_038004_SQ_TEX_RESOURCE_WORD1_0             0x038004
+#define   S_038004_TEX_HEIGHT(x)                       (((x) & 0x1FFF) << 0)
+#define   G_038004_TEX_HEIGHT(x)                       (((x) >> 0) & 0x1FFF)
+#define   C_038004_TEX_HEIGHT                          0xFFFFE000
+#define   S_038004_TEX_DEPTH(x)                        (((x) & 0x1FFF) << 13)
+#define   G_038004_TEX_DEPTH(x)                        (((x) >> 13) & 0x1FFF)
+#define   C_038004_TEX_DEPTH                           0xFC001FFF
+#define   S_038004_DATA_FORMAT(x)                      (((x) & 0x3F) << 26)
+#define   G_038004_DATA_FORMAT(x)                      (((x) >> 26) & 0x3F)
+#define   C_038004_DATA_FORMAT                         0x03FFFFFF
+#define     V_038004_COLOR_INVALID                     0x00000000
+#define     V_038004_COLOR_8                           0x00000001
+#define     V_038004_COLOR_4_4                         0x00000002
+#define     V_038004_COLOR_3_3_2                       0x00000003
+#define     V_038004_COLOR_16                          0x00000005
+#define     V_038004_COLOR_16_FLOAT                    0x00000006
+#define     V_038004_COLOR_8_8                         0x00000007
+#define     V_038004_COLOR_5_6_5                       0x00000008
+#define     V_038004_COLOR_6_5_5                       0x00000009
+#define     V_038004_COLOR_1_5_5_5                     0x0000000A
+#define     V_038004_COLOR_4_4_4_4                     0x0000000B
+#define     V_038004_COLOR_5_5_5_1                     0x0000000C
+#define     V_038004_COLOR_32                          0x0000000D
+#define     V_038004_COLOR_32_FLOAT                    0x0000000E
+#define     V_038004_COLOR_16_16                       0x0000000F
+#define     V_038004_COLOR_16_16_FLOAT                 0x00000010
+#define     V_038004_COLOR_8_24                        0x00000011
+#define     V_038004_COLOR_8_24_FLOAT                  0x00000012
+#define     V_038004_COLOR_24_8                        0x00000013
+#define     V_038004_COLOR_24_8_FLOAT                  0x00000014
+#define     V_038004_COLOR_10_11_11                    0x00000015
+#define     V_038004_COLOR_10_11_11_FLOAT              0x00000016
+#define     V_038004_COLOR_11_11_10                    0x00000017
+#define     V_038004_COLOR_11_11_10_FLOAT              0x00000018
+#define     V_038004_COLOR_2_10_10_10                  0x00000019
+#define     V_038004_COLOR_8_8_8_8                     0x0000001A
+#define     V_038004_COLOR_10_10_10_2                  0x0000001B
+#define     V_038004_COLOR_X24_8_32_FLOAT              0x0000001C
+#define     V_038004_COLOR_32_32                       0x0000001D
+#define     V_038004_COLOR_32_32_FLOAT                 0x0000001E
+#define     V_038004_COLOR_16_16_16_16                 0x0000001F
+#define     V_038004_COLOR_16_16_16_16_FLOAT           0x00000020
+#define     V_038004_COLOR_32_32_32_32                 0x00000022
+#define     V_038004_COLOR_32_32_32_32_FLOAT           0x00000023
+#define     V_038004_FMT_1                             0x00000025
+#define     V_038004_FMT_GB_GR                         0x00000027
+#define     V_038004_FMT_BG_RG                         0x00000028
+#define     V_038004_FMT_32_AS_8                       0x00000029
+#define     V_038004_FMT_32_AS_8_8                     0x0000002A
+#define     V_038004_FMT_5_9_9_9_SHAREDEXP             0x0000002B
+#define     V_038004_FMT_8_8_8                         0x0000002C
+#define     V_038004_FMT_16_16_16                      0x0000002D
+#define     V_038004_FMT_16_16_16_FLOAT                0x0000002E
+#define     V_038004_FMT_32_32_32                      0x0000002F
+#define     V_038004_FMT_32_32_32_FLOAT                0x00000030
+#define R_038010_SQ_TEX_RESOURCE_WORD4_0             0x038010
+#define   S_038010_FORMAT_COMP_X(x)                    (((x) & 0x3) << 0)
+#define   G_038010_FORMAT_COMP_X(x)                    (((x) >> 0) & 0x3)
+#define   C_038010_FORMAT_COMP_X                       0xFFFFFFFC
+#define   S_038010_FORMAT_COMP_Y(x)                    (((x) & 0x3) << 2)
+#define   G_038010_FORMAT_COMP_Y(x)                    (((x) >> 2) & 0x3)
+#define   C_038010_FORMAT_COMP_Y                       0xFFFFFFF3
+#define   S_038010_FORMAT_COMP_Z(x)                    (((x) & 0x3) << 4)
+#define   G_038010_FORMAT_COMP_Z(x)                    (((x) >> 4) & 0x3)
+#define   C_038010_FORMAT_COMP_Z                       0xFFFFFFCF
+#define   S_038010_FORMAT_COMP_W(x)                    (((x) & 0x3) << 6)
+#define   G_038010_FORMAT_COMP_W(x)                    (((x) >> 6) & 0x3)
+#define   C_038010_FORMAT_COMP_W                       0xFFFFFF3F
+#define   S_038010_NUM_FORMAT_ALL(x)                   (((x) & 0x3) << 8)
+#define   G_038010_NUM_FORMAT_ALL(x)                   (((x) >> 8) & 0x3)
+#define   C_038010_NUM_FORMAT_ALL                      0xFFFFFCFF
+#define   S_038010_SRF_MODE_ALL(x)                     (((x) & 0x1) << 10)
+#define   G_038010_SRF_MODE_ALL(x)                     (((x) >> 10) & 0x1)
+#define   C_038010_SRF_MODE_ALL                        0xFFFFFBFF
+#define   S_038010_FORCE_DEGAMMA(x)                    (((x) & 0x1) << 11)
+#define   G_038010_FORCE_DEGAMMA(x)                    (((x) >> 11) & 0x1)
+#define   C_038010_FORCE_DEGAMMA                       0xFFFFF7FF
+#define   S_038010_ENDIAN_SWAP(x)                      (((x) & 0x3) << 12)
+#define   G_038010_ENDIAN_SWAP(x)                      (((x) >> 12) & 0x3)
+#define   C_038010_ENDIAN_SWAP                         0xFFFFCFFF
+#define   S_038010_REQUEST_SIZE(x)                     (((x) & 0x3) << 14)
+#define   G_038010_REQUEST_SIZE(x)                     (((x) >> 14) & 0x3)
+#define   C_038010_REQUEST_SIZE                        0xFFFF3FFF
+#define   S_038010_DST_SEL_X(x)                        (((x) & 0x7) << 16)
+#define   G_038010_DST_SEL_X(x)                        (((x) >> 16) & 0x7)
+#define   C_038010_DST_SEL_X                           0xFFF8FFFF
+#define   S_038010_DST_SEL_Y(x)                        (((x) & 0x7) << 19)
+#define   G_038010_DST_SEL_Y(x)                        (((x) >> 19) & 0x7)
+#define   C_038010_DST_SEL_Y                           0xFFC7FFFF
+#define   S_038010_DST_SEL_Z(x)                        (((x) & 0x7) << 22)
+#define   G_038010_DST_SEL_Z(x)                        (((x) >> 22) & 0x7)
+#define   C_038010_DST_SEL_Z                           0xFE3FFFFF
+#define   S_038010_DST_SEL_W(x)                        (((x) & 0x7) << 25)
+#define   G_038010_DST_SEL_W(x)                        (((x) >> 25) & 0x7)
+#define   C_038010_DST_SEL_W                           0xF1FFFFFF
+#define   S_038010_BASE_LEVEL(x)                       (((x) & 0xF) << 28)
+#define   G_038010_BASE_LEVEL(x)                       (((x) >> 28) & 0xF)
+#define   C_038010_BASE_LEVEL                          0x0FFFFFFF
+#define R_038014_SQ_TEX_RESOURCE_WORD5_0             0x038014
+#define   S_038014_LAST_LEVEL(x)                       (((x) & 0xF) << 0)
+#define   G_038014_LAST_LEVEL(x)                       (((x) >> 0) & 0xF)
+#define   C_038014_LAST_LEVEL                          0xFFFFFFF0
+#define   S_038014_BASE_ARRAY(x)                       (((x) & 0x1FFF) << 4)
+#define   G_038014_BASE_ARRAY(x)                       (((x) >> 4) & 0x1FFF)
+#define   C_038014_BASE_ARRAY                          0xFFFE000F
+#define   S_038014_LAST_ARRAY(x)                       (((x) & 0x1FFF) << 17)
+#define   G_038014_LAST_ARRAY(x)                       (((x) >> 17) & 0x1FFF)
+#define   C_038014_LAST_ARRAY                          0xC001FFFF
+#define R_0288A8_SQ_ESGS_RING_ITEMSIZE               0x0288A8
+#define   S_0288A8_ITEMSIZE(x)                         (((x) & 0x7FFF) << 0)
+#define   G_0288A8_ITEMSIZE(x)                         (((x) >> 0) & 0x7FFF)
+#define   C_0288A8_ITEMSIZE                            0xFFFF8000
+#define R_008C44_SQ_ESGS_RING_SIZE                   0x008C44
+#define   S_008C44_MEM_SIZE(x)                         (((x) & 0xFFFFFFFF) << 0)
+#define   G_008C44_MEM_SIZE(x)                         (((x) >> 0) & 0xFFFFFFFF)
+#define   C_008C44_MEM_SIZE                            0x00000000
+#define R_0288B0_SQ_ESTMP_RING_ITEMSIZE              0x0288B0
+#define   S_0288B0_ITEMSIZE(x)                         (((x) & 0x7FFF) << 0)
+#define   G_0288B0_ITEMSIZE(x)                         (((x) >> 0) & 0x7FFF)
+#define   C_0288B0_ITEMSIZE                            0xFFFF8000
+#define R_008C54_SQ_ESTMP_RING_SIZE                  0x008C54
+#define   S_008C54_MEM_SIZE(x)                         (((x) & 0xFFFFFFFF) << 0)
+#define   G_008C54_MEM_SIZE(x)                         (((x) >> 0) & 0xFFFFFFFF)
+#define   C_008C54_MEM_SIZE                            0x00000000
+#define R_0288C0_SQ_FBUF_RING_ITEMSIZE               0x0288C0
+#define   S_0288C0_ITEMSIZE(x)                         (((x) & 0x7FFF) << 0)
+#define   G_0288C0_ITEMSIZE(x)                         (((x) >> 0) & 0x7FFF)
+#define   C_0288C0_ITEMSIZE                            0xFFFF8000
+#define R_008C74_SQ_FBUF_RING_SIZE                   0x008C74
+#define   S_008C74_MEM_SIZE(x)                         (((x) & 0xFFFFFFFF) << 0)
+#define   G_008C74_MEM_SIZE(x)                         (((x) >> 0) & 0xFFFFFFFF)
+#define   C_008C74_MEM_SIZE                            0x00000000
+#define R_0288B4_SQ_GSTMP_RING_ITEMSIZE              0x0288B4
+#define   S_0288B4_ITEMSIZE(x)                         (((x) & 0x7FFF) << 0)
+#define   G_0288B4_ITEMSIZE(x)                         (((x) >> 0) & 0x7FFF)
+#define   C_0288B4_ITEMSIZE                            0xFFFF8000
+#define R_008C5C_SQ_GSTMP_RING_SIZE                  0x008C5C
+#define   S_008C5C_MEM_SIZE(x)                         (((x) & 0xFFFFFFFF) << 0)
+#define   G_008C5C_MEM_SIZE(x)                         (((x) >> 0) & 0xFFFFFFFF)
+#define   C_008C5C_MEM_SIZE                            0x00000000
+#define R_0288AC_SQ_GSVS_RING_ITEMSIZE               0x0288AC
+#define   S_0288AC_ITEMSIZE(x)                         (((x) & 0x7FFF) << 0)
+#define   G_0288AC_ITEMSIZE(x)                         (((x) >> 0) & 0x7FFF)
+#define   C_0288AC_ITEMSIZE                            0xFFFF8000
+#define R_008C4C_SQ_GSVS_RING_SIZE                   0x008C4C
+#define   S_008C4C_MEM_SIZE(x)                         (((x) & 0xFFFFFFFF) << 0)
+#define   G_008C4C_MEM_SIZE(x)                         (((x) >> 0) & 0xFFFFFFFF)
+#define   C_008C4C_MEM_SIZE                            0x00000000
+#define R_0288BC_SQ_PSTMP_RING_ITEMSIZE              0x0288BC
+#define   S_0288BC_ITEMSIZE(x)                         (((x) & 0x7FFF) << 0)
+#define   G_0288BC_ITEMSIZE(x)                         (((x) >> 0) & 0x7FFF)
+#define   C_0288BC_ITEMSIZE                            0xFFFF8000
+#define R_008C6C_SQ_PSTMP_RING_SIZE                  0x008C6C
+#define   S_008C6C_MEM_SIZE(x)                         (((x) & 0xFFFFFFFF) << 0)
+#define   G_008C6C_MEM_SIZE(x)                         (((x) >> 0) & 0xFFFFFFFF)
+#define   C_008C6C_MEM_SIZE                            0x00000000
+#define R_0288C4_SQ_REDUC_RING_ITEMSIZE              0x0288C4
+#define   S_0288C4_ITEMSIZE(x)                         (((x) & 0x7FFF) << 0)
+#define   G_0288C4_ITEMSIZE(x)                         (((x) >> 0) & 0x7FFF)
+#define   C_0288C4_ITEMSIZE                            0xFFFF8000
+#define R_008C7C_SQ_REDUC_RING_SIZE                  0x008C7C
+#define   S_008C7C_MEM_SIZE(x)                         (((x) & 0xFFFFFFFF) << 0)
+#define   G_008C7C_MEM_SIZE(x)                         (((x) >> 0) & 0xFFFFFFFF)
+#define   C_008C7C_MEM_SIZE                            0x00000000
+#define R_0288B8_SQ_VSTMP_RING_ITEMSIZE              0x0288B8
+#define   S_0288B8_ITEMSIZE(x)                         (((x) & 0x7FFF) << 0)
+#define   G_0288B8_ITEMSIZE(x)                         (((x) >> 0) & 0x7FFF)
+#define   C_0288B8_ITEMSIZE                            0xFFFF8000
+#define R_008C64_SQ_VSTMP_RING_SIZE                  0x008C64
+#define   S_008C64_MEM_SIZE(x)                         (((x) & 0xFFFFFFFF) << 0)
+#define   G_008C64_MEM_SIZE(x)                         (((x) >> 0) & 0xFFFFFFFF)
+#define   C_008C64_MEM_SIZE                            0x00000000
+#define R_0288C8_SQ_GS_VERT_ITEMSIZE                 0x0288C8
+#define   S_0288C8_ITEMSIZE(x)                         (((x) & 0x7FFF) << 0)
+#define   G_0288C8_ITEMSIZE(x)                         (((x) >> 0) & 0x7FFF)
+#define   C_0288C8_ITEMSIZE                            0xFFFF8000
+#define R_028010_DB_DEPTH_INFO                       0x028010
+#define   S_028010_FORMAT(x)                           (((x) & 0x7) << 0)
+#define   G_028010_FORMAT(x)                           (((x) >> 0) & 0x7)
+#define   C_028010_FORMAT                              0xFFFFFFF8
+#define     V_028010_DEPTH_INVALID                     0x00000000
+#define     V_028010_DEPTH_16                          0x00000001
+#define     V_028010_DEPTH_X8_24                       0x00000002
+#define     V_028010_DEPTH_8_24                        0x00000003
+#define     V_028010_DEPTH_X8_24_FLOAT                 0x00000004
+#define     V_028010_DEPTH_8_24_FLOAT                  0x00000005
+#define     V_028010_DEPTH_32_FLOAT                    0x00000006
+#define     V_028010_DEPTH_X24_8_32_FLOAT              0x00000007
+#define   S_028010_READ_SIZE(x)                        (((x) & 0x1) << 3)
+#define   G_028010_READ_SIZE(x)                        (((x) >> 3) & 0x1)
+#define   C_028010_READ_SIZE                           0xFFFFFFF7
+#define   S_028010_ARRAY_MODE(x)                       (((x) & 0xF) << 15)
+#define   G_028010_ARRAY_MODE(x)                       (((x) >> 15) & 0xF)
+#define   C_028010_ARRAY_MODE                          0xFFF87FFF
+#define   S_028010_TILE_SURFACE_ENABLE(x)              (((x) & 0x1) << 25)
+#define   G_028010_TILE_SURFACE_ENABLE(x)              (((x) >> 25) & 0x1)
+#define   C_028010_TILE_SURFACE_ENABLE                 0xFDFFFFFF
+#define   S_028010_TILE_COMPACT(x)                     (((x) & 0x1) << 26)
+#define   G_028010_TILE_COMPACT(x)                     (((x) >> 26) & 0x1)
+#define   C_028010_TILE_COMPACT                        0xFBFFFFFF
+#define   S_028010_ZRANGE_PRECISION(x)                 (((x) & 0x1) << 31)
+#define   G_028010_ZRANGE_PRECISION(x)                 (((x) >> 31) & 0x1)
+#define   C_028010_ZRANGE_PRECISION                    0x7FFFFFFF
+#define R_028000_DB_DEPTH_SIZE                       0x028000
+#define   S_028000_PITCH_TILE_MAX(x)                   (((x) & 0x3FF) << 0)
+#define   G_028000_PITCH_TILE_MAX(x)                   (((x) >> 0) & 0x3FF)
+#define   C_028000_PITCH_TILE_MAX                      0xFFFFFC00
+#define   S_028000_SLICE_TILE_MAX(x)                   (((x) & 0xFFFFF) << 10)
+#define   G_028000_SLICE_TILE_MAX(x)                   (((x) >> 10) & 0xFFFFF)
+#define   C_028000_SLICE_TILE_MAX                      0xC00003FF
+#define R_028004_DB_DEPTH_VIEW                       0x028004
+#define   S_028004_SLICE_START(x)                      (((x) & 0x7FF) << 0)
+#define   G_028004_SLICE_START(x)                      (((x) >> 0) & 0x7FF)
+#define   C_028004_SLICE_START                         0xFFFFF800
+#define   S_028004_SLICE_MAX(x)                        (((x) & 0x7FF) << 13)
+#define   G_028004_SLICE_MAX(x)                        (((x) >> 13) & 0x7FF)
+#define   C_028004_SLICE_MAX                           0xFF001FFF
+#define R_028800_DB_DEPTH_CONTROL                    0x028800
+#define   S_028800_STENCIL_ENABLE(x)                   (((x) & 0x1) << 0)
+#define   G_028800_STENCIL_ENABLE(x)                   (((x) >> 0) & 0x1)
+#define   C_028800_STENCIL_ENABLE                      0xFFFFFFFE
+#define   S_028800_Z_ENABLE(x)                         (((x) & 0x1) << 1)
+#define   G_028800_Z_ENABLE(x)                         (((x) >> 1) & 0x1)
+#define   C_028800_Z_ENABLE                            0xFFFFFFFD
+#define   S_028800_Z_WRITE_ENABLE(x)                   (((x) & 0x1) << 2)
+#define   G_028800_Z_WRITE_ENABLE(x)                   (((x) >> 2) & 0x1)
+#define   C_028800_Z_WRITE_ENABLE                      0xFFFFFFFB
+#define   S_028800_ZFUNC(x)                            (((x) & 0x7) << 4)
+#define   G_028800_ZFUNC(x)                            (((x) >> 4) & 0x7)
+#define   C_028800_ZFUNC                               0xFFFFFF8F
+#define   S_028800_BACKFACE_ENABLE(x)                  (((x) & 0x1) << 7)
+#define   G_028800_BACKFACE_ENABLE(x)                  (((x) >> 7) & 0x1)
+#define   C_028800_BACKFACE_ENABLE                     0xFFFFFF7F
+#define   S_028800_STENCILFUNC(x)                      (((x) & 0x7) << 8)
+#define   G_028800_STENCILFUNC(x)                      (((x) >> 8) & 0x7)
+#define   C_028800_STENCILFUNC                         0xFFFFF8FF
+#define   S_028800_STENCILFAIL(x)                      (((x) & 0x7) << 11)
+#define   G_028800_STENCILFAIL(x)                      (((x) >> 11) & 0x7)
+#define   C_028800_STENCILFAIL                         0xFFFFC7FF
+#define   S_028800_STENCILZPASS(x)                     (((x) & 0x7) << 14)
+#define   G_028800_STENCILZPASS(x)                     (((x) >> 14) & 0x7)
+#define   C_028800_STENCILZPASS                        0xFFFE3FFF
+#define   S_028800_STENCILZFAIL(x)                     (((x) & 0x7) << 17)
+#define   G_028800_STENCILZFAIL(x)                     (((x) >> 17) & 0x7)
+#define   C_028800_STENCILZFAIL                        0xFFF1FFFF
+#define   S_028800_STENCILFUNC_BF(x)                   (((x) & 0x7) << 20)
+#define   G_028800_STENCILFUNC_BF(x)                   (((x) >> 20) & 0x7)
+#define   C_028800_STENCILFUNC_BF                      0xFF8FFFFF
+#define   S_028800_STENCILFAIL_BF(x)                   (((x) & 0x7) << 23)
+#define   G_028800_STENCILFAIL_BF(x)                   (((x) >> 23) & 0x7)
+#define   C_028800_STENCILFAIL_BF                      0xFC7FFFFF
+#define   S_028800_STENCILZPASS_BF(x)                  (((x) & 0x7) << 26)
+#define   G_028800_STENCILZPASS_BF(x)                  (((x) >> 26) & 0x7)
+#define   C_028800_STENCILZPASS_BF                     0xE3FFFFFF
+#define   S_028800_STENCILZFAIL_BF(x)                  (((x) & 0x7) << 29)
+#define   G_028800_STENCILZFAIL_BF(x)                  (((x) >> 29) & 0x7)
+#define   C_028800_STENCILZFAIL_BF                     0x1FFFFFFF
 
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c0356bb..829e26e 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -89,6 +89,7 @@
 extern int radeon_connector_table;
 extern int radeon_tv;
 extern int radeon_new_pll;
+extern int radeon_dynpm;
 extern int radeon_audio;
 
 /*
@@ -118,6 +119,21 @@
 /*
  * BIOS.
  */
+#define ATRM_BIOS_PAGE 4096
+
+#if defined(CONFIG_VGA_SWITCHEROO)
+bool radeon_atrm_supported(struct pci_dev *pdev);
+int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len);
+#else
+static inline bool radeon_atrm_supported(struct pci_dev *pdev)
+{
+	return false;
+}
+
+static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len){
+	return -EINVAL;
+}
+#endif
 bool radeon_get_bios(struct radeon_device *rdev);
 
 
@@ -138,17 +154,23 @@
 struct radeon_clock {
 	struct radeon_pll p1pll;
 	struct radeon_pll p2pll;
+	struct radeon_pll dcpll;
 	struct radeon_pll spll;
 	struct radeon_pll mpll;
 	/* 10 Khz units */
 	uint32_t default_mclk;
 	uint32_t default_sclk;
+	uint32_t default_dispclk;
+	uint32_t dp_extclk;
 };
 
 /*
  * Power management
  */
 int radeon_pm_init(struct radeon_device *rdev);
+void radeon_pm_compute_clocks(struct radeon_device *rdev);
+void radeon_combios_get_power_modes(struct radeon_device *rdev);
+void radeon_atombios_get_power_modes(struct radeon_device *rdev);
 
 /*
  * Fences.
@@ -275,6 +297,7 @@
 };
 
 #define RADEON_GPU_PAGE_SIZE 4096
+#define RADEON_GPU_PAGE_MASK (RADEON_GPU_PAGE_SIZE - 1)
 
 struct radeon_gart {
 	dma_addr_t			table_addr;
@@ -309,21 +332,19 @@
 	/* for some chips with <= 32MB we need to lie
 	 * about vram size near mc fb location */
 	u64			mc_vram_size;
-	u64			gtt_location;
+	u64			visible_vram_size;
 	u64			gtt_size;
 	u64			gtt_start;
 	u64			gtt_end;
-	u64			vram_location;
 	u64			vram_start;
 	u64			vram_end;
 	unsigned		vram_width;
 	u64			real_vram_size;
 	int			vram_mtrr;
 	bool			vram_is_ddr;
-	bool                    igp_sideport_enabled;
+	bool			igp_sideport_enabled;
 };
 
-int radeon_mc_setup(struct radeon_device *rdev);
 bool radeon_combios_sideport_present(struct radeon_device *rdev);
 bool radeon_atombios_sideport_present(struct radeon_device *rdev);
 
@@ -348,6 +369,7 @@
 	bool		sw_int;
 	/* FIXME: use a define max crtc rather than hardcode it */
 	bool		crtc_vblank_int[2];
+	wait_queue_head_t	vblank_queue;
 	/* FIXME: use defines for max hpd/dacs */
 	bool            hpd[6];
 	spinlock_t sw_lock;
@@ -379,6 +401,7 @@
 struct radeon_ib_pool {
 	struct mutex		mutex;
 	struct radeon_bo	*robj;
+	struct list_head	bogus_ib;
 	struct radeon_ib	ibs[RADEON_IB_POOL_SIZE];
 	bool			ready;
 	unsigned		head_id;
@@ -433,6 +456,7 @@
 int radeon_ib_pool_init(struct radeon_device *rdev);
 void radeon_ib_pool_fini(struct radeon_device *rdev);
 int radeon_ib_test(struct radeon_device *rdev);
+extern void radeon_ib_bogus_add(struct radeon_device *rdev, struct radeon_ib *ib);
 /* Ring access between begin & end cannot sleep */
 void radeon_ring_free_size(struct radeon_device *rdev);
 int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw);
@@ -570,7 +594,99 @@
  * Equation between gpu/memory clock and available bandwidth is hw dependent
  * (type of memory, bus size, efficiency, ...)
  */
+enum radeon_pm_state {
+	PM_STATE_DISABLED,
+	PM_STATE_MINIMUM,
+	PM_STATE_PAUSED,
+	PM_STATE_ACTIVE
+};
+enum radeon_pm_action {
+	PM_ACTION_NONE,
+	PM_ACTION_MINIMUM,
+	PM_ACTION_DOWNCLOCK,
+	PM_ACTION_UPCLOCK
+};
+
+enum radeon_voltage_type {
+	VOLTAGE_NONE = 0,
+	VOLTAGE_GPIO,
+	VOLTAGE_VDDC,
+	VOLTAGE_SW
+};
+
+enum radeon_pm_state_type {
+	POWER_STATE_TYPE_DEFAULT,
+	POWER_STATE_TYPE_POWERSAVE,
+	POWER_STATE_TYPE_BATTERY,
+	POWER_STATE_TYPE_BALANCED,
+	POWER_STATE_TYPE_PERFORMANCE,
+};
+
+enum radeon_pm_clock_mode_type {
+	POWER_MODE_TYPE_DEFAULT,
+	POWER_MODE_TYPE_LOW,
+	POWER_MODE_TYPE_MID,
+	POWER_MODE_TYPE_HIGH,
+};
+
+struct radeon_voltage {
+	enum radeon_voltage_type type;
+	/* gpio voltage */
+	struct radeon_gpio_rec gpio;
+	u32 delay; /* delay in usec from voltage drop to sclk change */
+	bool active_high; /* voltage drop is active when bit is high */
+	/* VDDC voltage */
+	u8 vddc_id; /* index into vddc voltage table */
+	u8 vddci_id; /* index into vddci voltage table */
+	bool vddci_enabled;
+	/* r6xx+ sw */
+	u32 voltage;
+};
+
+struct radeon_pm_non_clock_info {
+	/* pcie lanes */
+	int pcie_lanes;
+	/* standardized non-clock flags */
+	u32 flags;
+};
+
+struct radeon_pm_clock_info {
+	/* memory clock */
+	u32 mclk;
+	/* engine clock */
+	u32 sclk;
+	/* voltage info */
+	struct radeon_voltage voltage;
+	/* standardized clock flags - not sure we'll need these */
+	u32 flags;
+};
+
+struct radeon_power_state {
+	enum radeon_pm_state_type type;
+	/* XXX: use a define for num clock modes */
+	struct radeon_pm_clock_info clock_info[8];
+	/* number of valid clock modes in this power state */
+	int num_clock_modes;
+	struct radeon_pm_clock_info *default_clock_mode;
+	/* non clock info about this state */
+	struct radeon_pm_non_clock_info non_clock_info;
+	bool voltage_drop_active;
+};
+
+/*
+ * Some modes are overclocked by very low value, accept them
+ */
+#define RADEON_MODE_OVERCLOCK_MARGIN 500 /* 5 MHz */
+
 struct radeon_pm {
+	struct mutex		mutex;
+	struct delayed_work	idle_work;
+	enum radeon_pm_state	state;
+	enum radeon_pm_action	planned_action;
+	unsigned long		action_timeout;
+	bool 			downclocked;
+	int			active_crtcs;
+	int			req_vblank;
 	fixed20_12		max_bandwidth;
 	fixed20_12		igp_sideport_mclk;
 	fixed20_12		igp_system_mclk;
@@ -582,6 +698,15 @@
 	fixed20_12		core_bandwidth;
 	fixed20_12		sclk;
 	fixed20_12		needed_bandwidth;
+	/* XXX: use a define for num power modes */
+	struct radeon_power_state power_state[8];
+	/* number of valid power states */
+	int                     num_power_states;
+	struct radeon_power_state *current_power_state;
+	struct radeon_pm_clock_info *current_clock_mode;
+	struct radeon_power_state *requested_power_state;
+	struct radeon_pm_clock_info *requested_clock_mode;
+	struct radeon_power_state *default_power_state;
 };
 
 
@@ -651,6 +776,7 @@
 	void (*set_engine_clock)(struct radeon_device *rdev, uint32_t eng_clock);
 	uint32_t (*get_memory_clock)(struct radeon_device *rdev);
 	void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock);
+	int (*get_pcie_lanes)(struct radeon_device *rdev);
 	void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
 	void (*set_clock_gating)(struct radeon_device *rdev, int enable);
 	int (*set_surface_reg)(struct radeon_device *rdev, int reg,
@@ -701,6 +827,9 @@
 	unsigned sx_max_export_pos_size;
 	unsigned sx_max_export_smx_size;
 	unsigned sq_num_cf_insts;
+	unsigned tiling_nbanks;
+	unsigned tiling_npipes;
+	unsigned tiling_group_size;
 };
 
 struct rv770_asic {
@@ -721,6 +850,9 @@
 	unsigned sc_prim_fifo_size;
 	unsigned sc_hiz_tile_fifo_size;
 	unsigned sc_earlyz_tile_fifo_fize;
+	unsigned tiling_nbanks;
+	unsigned tiling_npipes;
+	unsigned tiling_group_size;
 };
 
 union radeon_asic_config {
@@ -830,6 +962,8 @@
 	struct r600_ih ih; /* r6/700 interrupt ring */
 	struct workqueue_struct *wq;
 	struct work_struct hotplug_work;
+	int num_crtc; /* number of crtcs */
+	struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
 
 	/* audio stuff */
 	struct timer_list	audio_timer;
@@ -838,6 +972,8 @@
 	int			audio_bits_per_sample;
 	uint8_t			audio_status_bits;
 	uint8_t			audio_category_code;
+
+	bool powered_down;
 };
 
 int radeon_device_init(struct radeon_device *rdev,
@@ -895,6 +1031,8 @@
 #define WREG32_MC(reg, v) rdev->mc_wreg(rdev, (reg), (v))
 #define RREG32_PCIE(reg) rv370_pcie_rreg(rdev, (reg))
 #define WREG32_PCIE(reg, v) rv370_pcie_wreg(rdev, (reg), (v))
+#define RREG32_PCIE_P(reg) rdev->pciep_rreg(rdev, (reg))
+#define WREG32_PCIE_P(reg, v) rdev->pciep_wreg(rdev, (reg), (v))
 #define WREG32_P(reg, val, mask)				\
 	do {							\
 		uint32_t tmp_ = RREG32(reg);			\
@@ -956,7 +1094,7 @@
 #define ASIC_IS_AVIVO(rdev) ((rdev->family >= CHIP_RS600))
 #define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620))
 #define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730))
-
+#define ASIC_IS_DCE4(rdev) ((rdev->family >= CHIP_CEDAR))
 
 /*
  * BIOS helpers.
@@ -1015,6 +1153,7 @@
 #define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
 #define radeon_get_memory_clock(rdev) (rdev)->asic->get_memory_clock((rdev))
 #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_memory_clock((rdev), (e))
+#define radeon_get_pcie_lanes(rdev) (rdev)->asic->get_pcie_lanes((rdev))
 #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l))
 #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e))
 #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s)))
@@ -1029,6 +1168,7 @@
 /* AGP */
 extern void radeon_agp_disable(struct radeon_device *rdev);
 extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
+extern void radeon_gart_restore(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
 extern void radeon_modeset_fini(struct radeon_device *rdev);
 extern bool radeon_card_posted(struct radeon_device *rdev);
@@ -1042,6 +1182,10 @@
 extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
 extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain);
 extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo);
+extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base);
+extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
+extern int radeon_resume_kms(struct drm_device *dev);
+extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state);
 
 /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
 struct r100_mc_save {
@@ -1096,7 +1240,7 @@
 /* r300,r350,rv350,rv370,rv380 */
 extern void r300_set_reg_safe(struct radeon_device *rdev);
 extern void r300_mc_program(struct radeon_device *rdev);
-extern void r300_vram_info(struct radeon_device *rdev);
+extern void r300_mc_init(struct radeon_device *rdev);
 extern void r300_clock_startup(struct radeon_device *rdev);
 extern int r300_mc_wait_for_idle(struct radeon_device *rdev);
 extern int rv370_pcie_gart_init(struct radeon_device *rdev);
@@ -1105,7 +1249,6 @@
 extern void rv370_pcie_gart_disable(struct radeon_device *rdev);
 
 /* r420,r423,rv410 */
-extern int r420_mc_init(struct radeon_device *rdev);
 extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg);
 extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v);
 extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
@@ -1147,13 +1290,13 @@
 					struct drm_display_mode *mode2);
 
 /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */
+extern void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
 extern bool r600_card_posted(struct radeon_device *rdev);
 extern void r600_cp_stop(struct radeon_device *rdev);
 extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size);
 extern int r600_cp_resume(struct radeon_device *rdev);
 extern void r600_cp_fini(struct radeon_device *rdev);
 extern int r600_count_pipe_bits(uint32_t val);
-extern int r600_gart_clear_page(struct radeon_device *rdev, int i);
 extern int r600_mc_wait_for_idle(struct radeon_device *rdev);
 extern int r600_pcie_gart_init(struct radeon_device *rdev);
 extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev);
@@ -1189,6 +1332,14 @@
 					    uint8_t status_bits,
 					    uint8_t category_code);
 
+/* evergreen */
+struct evergreen_mc_save {
+	u32 vga_control[6];
+	u32 vga_render_control;
+	u32 vga_hdp_control;
+	u32 crtc_control[6];
+};
+
 #include "radeon_object.h"
 
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c
index c0681a55..c445779 100644
--- a/drivers/gpu/drm/radeon/radeon_agp.c
+++ b/drivers/gpu/drm/radeon/radeon_agp.c
@@ -237,6 +237,10 @@
 
 	rdev->mc.agp_base = rdev->ddev->agp->agp_info.aper_base;
 	rdev->mc.gtt_size = rdev->ddev->agp->agp_info.aper_size << 20;
+	rdev->mc.gtt_start = rdev->mc.agp_base;
+	rdev->mc.gtt_end = rdev->mc.gtt_start + rdev->mc.gtt_size - 1;
+	dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n",
+		rdev->mc.gtt_size >> 20, rdev->mc.gtt_start, rdev->mc.gtt_end);
 
 	/* workaround some hw issues */
 	if (rdev->family < CHIP_R200) {
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 05ee1ae..d3a157b 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -43,7 +43,7 @@
 void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
 
 /*
- * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
+ * r100,rv100,rs100,rv200,rs200
  */
 extern int r100_init(struct radeon_device *rdev);
 extern void r100_fini(struct radeon_device *rdev);
@@ -108,6 +108,52 @@
 	.set_engine_clock = &radeon_legacy_set_engine_clock,
 	.get_memory_clock = &radeon_legacy_get_memory_clock,
 	.set_memory_clock = NULL,
+	.get_pcie_lanes = NULL,
+	.set_pcie_lanes = NULL,
+	.set_clock_gating = &radeon_legacy_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
+	.bandwidth_update = &r100_bandwidth_update,
+	.hpd_init = &r100_hpd_init,
+	.hpd_fini = &r100_hpd_fini,
+	.hpd_sense = &r100_hpd_sense,
+	.hpd_set_polarity = &r100_hpd_set_polarity,
+	.ioctl_wait_idle = NULL,
+};
+
+/*
+ * r200,rv250,rs300,rv280
+ */
+extern int r200_copy_dma(struct radeon_device *rdev,
+			uint64_t src_offset,
+			uint64_t dst_offset,
+			unsigned num_pages,
+			struct radeon_fence *fence);
+static struct radeon_asic r200_asic = {
+	.init = &r100_init,
+	.fini = &r100_fini,
+	.suspend = &r100_suspend,
+	.resume = &r100_resume,
+	.vga_set_state = &r100_vga_set_state,
+	.gpu_reset = &r100_gpu_reset,
+	.gart_tlb_flush = &r100_pci_gart_tlb_flush,
+	.gart_set_page = &r100_pci_gart_set_page,
+	.cp_commit = &r100_cp_commit,
+	.ring_start = &r100_ring_start,
+	.ring_test = &r100_ring_test,
+	.ring_ib_execute = &r100_ring_ib_execute,
+	.irq_set = &r100_irq_set,
+	.irq_process = &r100_irq_process,
+	.get_vblank_counter = &r100_get_vblank_counter,
+	.fence_ring_emit = &r100_fence_ring_emit,
+	.cs_parse = &r100_cs_parse,
+	.copy_blit = &r100_copy_blit,
+	.copy_dma = &r200_copy_dma,
+	.copy = &r100_copy_blit,
+	.get_engine_clock = &radeon_legacy_get_engine_clock,
+	.set_engine_clock = &radeon_legacy_set_engine_clock,
+	.get_memory_clock = &radeon_legacy_get_memory_clock,
+	.set_memory_clock = NULL,
 	.set_pcie_lanes = NULL,
 	.set_clock_gating = &radeon_legacy_set_clock_gating,
 	.set_surface_reg = r100_set_surface_reg,
@@ -138,11 +184,8 @@
 extern uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
 extern void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
-extern int r300_copy_dma(struct radeon_device *rdev,
-			uint64_t src_offset,
-			uint64_t dst_offset,
-			unsigned num_pages,
-			struct radeon_fence *fence);
+extern int rv370_get_pcie_lanes(struct radeon_device *rdev);
+
 static struct radeon_asic r300_asic = {
 	.init = &r300_init,
 	.fini = &r300_fini,
@@ -162,7 +205,46 @@
 	.fence_ring_emit = &r300_fence_ring_emit,
 	.cs_parse = &r300_cs_parse,
 	.copy_blit = &r100_copy_blit,
-	.copy_dma = &r300_copy_dma,
+	.copy_dma = &r200_copy_dma,
+	.copy = &r100_copy_blit,
+	.get_engine_clock = &radeon_legacy_get_engine_clock,
+	.set_engine_clock = &radeon_legacy_set_engine_clock,
+	.get_memory_clock = &radeon_legacy_get_memory_clock,
+	.set_memory_clock = NULL,
+	.get_pcie_lanes = &rv370_get_pcie_lanes,
+	.set_pcie_lanes = &rv370_set_pcie_lanes,
+	.set_clock_gating = &radeon_legacy_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
+	.bandwidth_update = &r100_bandwidth_update,
+	.hpd_init = &r100_hpd_init,
+	.hpd_fini = &r100_hpd_fini,
+	.hpd_sense = &r100_hpd_sense,
+	.hpd_set_polarity = &r100_hpd_set_polarity,
+	.ioctl_wait_idle = NULL,
+};
+
+
+static struct radeon_asic r300_asic_pcie = {
+	.init = &r300_init,
+	.fini = &r300_fini,
+	.suspend = &r300_suspend,
+	.resume = &r300_resume,
+	.vga_set_state = &r100_vga_set_state,
+	.gpu_reset = &r300_gpu_reset,
+	.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
+	.gart_set_page = &rv370_pcie_gart_set_page,
+	.cp_commit = &r100_cp_commit,
+	.ring_start = &r300_ring_start,
+	.ring_test = &r100_ring_test,
+	.ring_ib_execute = &r100_ring_ib_execute,
+	.irq_set = &r100_irq_set,
+	.irq_process = &r100_irq_process,
+	.get_vblank_counter = &r100_get_vblank_counter,
+	.fence_ring_emit = &r300_fence_ring_emit,
+	.cs_parse = &r300_cs_parse,
+	.copy_blit = &r100_copy_blit,
+	.copy_dma = &r200_copy_dma,
 	.copy = &r100_copy_blit,
 	.get_engine_clock = &radeon_legacy_get_engine_clock,
 	.set_engine_clock = &radeon_legacy_set_engine_clock,
@@ -206,12 +288,13 @@
 	.fence_ring_emit = &r300_fence_ring_emit,
 	.cs_parse = &r300_cs_parse,
 	.copy_blit = &r100_copy_blit,
-	.copy_dma = &r300_copy_dma,
+	.copy_dma = &r200_copy_dma,
 	.copy = &r100_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
 	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.get_pcie_lanes = &rv370_get_pcie_lanes,
 	.set_pcie_lanes = &rv370_set_pcie_lanes,
 	.set_clock_gating = &radeon_atom_set_clock_gating,
 	.set_surface_reg = r100_set_surface_reg,
@@ -255,12 +338,13 @@
 	.fence_ring_emit = &r300_fence_ring_emit,
 	.cs_parse = &r300_cs_parse,
 	.copy_blit = &r100_copy_blit,
-	.copy_dma = &r300_copy_dma,
+	.copy_dma = &r200_copy_dma,
 	.copy = &r100_copy_blit,
 	.get_engine_clock = &radeon_legacy_get_engine_clock,
 	.set_engine_clock = &radeon_legacy_set_engine_clock,
 	.get_memory_clock = &radeon_legacy_get_memory_clock,
 	.set_memory_clock = NULL,
+	.get_pcie_lanes = NULL,
 	.set_pcie_lanes = NULL,
 	.set_clock_gating = &radeon_legacy_set_clock_gating,
 	.set_surface_reg = r100_set_surface_reg,
@@ -314,14 +398,17 @@
 	.fence_ring_emit = &r300_fence_ring_emit,
 	.cs_parse = &r300_cs_parse,
 	.copy_blit = &r100_copy_blit,
-	.copy_dma = &r300_copy_dma,
+	.copy_dma = &r200_copy_dma,
 	.copy = &r100_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
 	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.get_pcie_lanes = NULL,
 	.set_pcie_lanes = NULL,
 	.set_clock_gating = &radeon_atom_set_clock_gating,
+	.set_surface_reg = r100_set_surface_reg,
+	.clear_surface_reg = r100_clear_surface_reg,
 	.bandwidth_update = &rs600_bandwidth_update,
 	.hpd_init = &rs600_hpd_init,
 	.hpd_fini = &rs600_hpd_fini,
@@ -360,12 +447,13 @@
 	.fence_ring_emit = &r300_fence_ring_emit,
 	.cs_parse = &r300_cs_parse,
 	.copy_blit = &r100_copy_blit,
-	.copy_dma = &r300_copy_dma,
-	.copy = &r300_copy_dma,
+	.copy_dma = &r200_copy_dma,
+	.copy = &r200_copy_dma,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
 	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.get_pcie_lanes = NULL,
 	.set_pcie_lanes = NULL,
 	.set_clock_gating = &radeon_atom_set_clock_gating,
 	.set_surface_reg = r100_set_surface_reg,
@@ -412,12 +500,13 @@
 	.fence_ring_emit = &r300_fence_ring_emit,
 	.cs_parse = &r300_cs_parse,
 	.copy_blit = &r100_copy_blit,
-	.copy_dma = &r300_copy_dma,
+	.copy_dma = &r200_copy_dma,
 	.copy = &r100_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
 	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.get_pcie_lanes = &rv370_get_pcie_lanes,
 	.set_pcie_lanes = &rv370_set_pcie_lanes,
 	.set_clock_gating = &radeon_atom_set_clock_gating,
 	.set_surface_reg = r100_set_surface_reg,
@@ -455,12 +544,13 @@
 	.fence_ring_emit = &r300_fence_ring_emit,
 	.cs_parse = &r300_cs_parse,
 	.copy_blit = &r100_copy_blit,
-	.copy_dma = &r300_copy_dma,
+	.copy_dma = &r200_copy_dma,
 	.copy = &r100_copy_blit,
 	.get_engine_clock = &radeon_atom_get_engine_clock,
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
 	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.get_pcie_lanes = &rv370_get_pcie_lanes,
 	.set_pcie_lanes = &rv370_set_pcie_lanes,
 	.set_clock_gating = &radeon_atom_set_clock_gating,
 	.set_surface_reg = r100_set_surface_reg,
@@ -538,8 +628,9 @@
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
 	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.get_pcie_lanes = &rv370_get_pcie_lanes,
 	.set_pcie_lanes = NULL,
-	.set_clock_gating = &radeon_atom_set_clock_gating,
+	.set_clock_gating = NULL,
 	.set_surface_reg = r600_set_surface_reg,
 	.clear_surface_reg = r600_clear_surface_reg,
 	.bandwidth_update = &rv515_bandwidth_update,
@@ -583,6 +674,7 @@
 	.set_engine_clock = &radeon_atom_set_engine_clock,
 	.get_memory_clock = &radeon_atom_get_memory_clock,
 	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.get_pcie_lanes = &rv370_get_pcie_lanes,
 	.set_pcie_lanes = NULL,
 	.set_clock_gating = &radeon_atom_set_clock_gating,
 	.set_surface_reg = r600_set_surface_reg,
@@ -595,4 +687,54 @@
 	.ioctl_wait_idle = r600_ioctl_wait_idle,
 };
 
+/*
+ * evergreen
+ */
+int evergreen_init(struct radeon_device *rdev);
+void evergreen_fini(struct radeon_device *rdev);
+int evergreen_suspend(struct radeon_device *rdev);
+int evergreen_resume(struct radeon_device *rdev);
+int evergreen_gpu_reset(struct radeon_device *rdev);
+void evergreen_bandwidth_update(struct radeon_device *rdev);
+void evergreen_hpd_init(struct radeon_device *rdev);
+void evergreen_hpd_fini(struct radeon_device *rdev);
+bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd);
+void evergreen_hpd_set_polarity(struct radeon_device *rdev,
+				enum radeon_hpd_id hpd);
+
+static struct radeon_asic evergreen_asic = {
+	.init = &evergreen_init,
+	.fini = &evergreen_fini,
+	.suspend = &evergreen_suspend,
+	.resume = &evergreen_resume,
+	.cp_commit = NULL,
+	.gpu_reset = &evergreen_gpu_reset,
+	.vga_set_state = &r600_vga_set_state,
+	.gart_tlb_flush = &r600_pcie_gart_tlb_flush,
+	.gart_set_page = &rs600_gart_set_page,
+	.ring_test = NULL,
+	.ring_ib_execute = NULL,
+	.irq_set = NULL,
+	.irq_process = NULL,
+	.get_vblank_counter = NULL,
+	.fence_ring_emit = NULL,
+	.cs_parse = NULL,
+	.copy_blit = NULL,
+	.copy_dma = NULL,
+	.copy = NULL,
+	.get_engine_clock = &radeon_atom_get_engine_clock,
+	.set_engine_clock = &radeon_atom_set_engine_clock,
+	.get_memory_clock = &radeon_atom_get_memory_clock,
+	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.set_pcie_lanes = NULL,
+	.set_clock_gating = NULL,
+	.set_surface_reg = r600_set_surface_reg,
+	.clear_surface_reg = r600_clear_surface_reg,
+	.bandwidth_update = &evergreen_bandwidth_update,
+	.hpd_init = &evergreen_hpd_init,
+	.hpd_fini = &evergreen_hpd_fini,
+	.hpd_sense = &evergreen_hpd_sense,
+	.hpd_set_polarity = &evergreen_hpd_set_polarity,
+};
+
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 4d88315..93783b1 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -159,8 +159,15 @@
 							    struct radeon_gpio_rec *gpio)
 {
 	struct radeon_hpd hpd;
+	u32 reg;
+
+	if (ASIC_IS_DCE4(rdev))
+		reg = EVERGREEN_DC_GPIO_HPD_A;
+	else
+		reg = AVIVO_DC_GPIO_HPD_A;
+
 	hpd.gpio = *gpio;
-	if (gpio->reg == AVIVO_DC_GPIO_HPD_A) {
+	if (gpio->reg == reg) {
 		switch(gpio->mask) {
 		case (1 << 0):
 			hpd.hpd = RADEON_HPD_1;
@@ -574,6 +581,9 @@
 				ddc_bus.valid = false;
 			}
 
+			/* needed for aux chan transactions */
+			ddc_bus.hpd_id = hpd.hpd ? (hpd.hpd - 1) : 0;
+
 			conn_id = le16_to_cpu(path->usConnObjectId);
 
 			if (!radeon_atom_apply_quirks
@@ -838,6 +848,7 @@
 	ATOM_FIRMWARE_INFO_V1_2 info_12;
 	ATOM_FIRMWARE_INFO_V1_3 info_13;
 	ATOM_FIRMWARE_INFO_V1_4 info_14;
+	ATOM_FIRMWARE_INFO_V2_1 info_21;
 };
 
 bool radeon_atom_get_clock_info(struct drm_device *dev)
@@ -849,6 +860,7 @@
 	uint8_t frev, crev;
 	struct radeon_pll *p1pll = &rdev->clock.p1pll;
 	struct radeon_pll *p2pll = &rdev->clock.p2pll;
+	struct radeon_pll *dcpll = &rdev->clock.dcpll;
 	struct radeon_pll *spll = &rdev->clock.spll;
 	struct radeon_pll *mpll = &rdev->clock.mpll;
 	uint16_t data_offset;
@@ -951,8 +963,19 @@
 		rdev->clock.default_mclk =
 		    le32_to_cpu(firmware_info->info.ulDefaultMemoryClock);
 
+		if (ASIC_IS_DCE4(rdev)) {
+			rdev->clock.default_dispclk =
+				le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
+			if (rdev->clock.default_dispclk == 0)
+				rdev->clock.default_dispclk = 60000; /* 600 Mhz */
+			rdev->clock.dp_extclk =
+				le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
+		}
+		*dcpll = *p1pll;
+
 		return true;
 	}
+
 	return false;
 }
 
@@ -1091,6 +1114,30 @@
 	return ss;
 }
 
+static void radeon_atom_apply_lvds_quirks(struct drm_device *dev,
+					  struct radeon_encoder_atom_dig *lvds)
+{
+
+	/* Toshiba A300-1BU laptop panel doesn't like new pll divider algo */
+	if ((dev->pdev->device == 0x95c4) &&
+	    (dev->pdev->subsystem_vendor == 0x1179) &&
+	    (dev->pdev->subsystem_device == 0xff50)) {
+		if ((lvds->native_mode.hdisplay == 1280) &&
+		    (lvds->native_mode.vdisplay == 800))
+			lvds->pll_algo = PLL_ALGO_LEGACY;
+	}
+
+	/* Dell Studio 15 laptop panel doesn't like new pll divider algo */
+	if ((dev->pdev->device == 0x95c4) &&
+	    (dev->pdev->subsystem_vendor == 0x1028) &&
+	    (dev->pdev->subsystem_device == 0x029f)) {
+		if ((lvds->native_mode.hdisplay == 1280) &&
+		    (lvds->native_mode.vdisplay == 800))
+			lvds->pll_algo = PLL_ALGO_LEGACY;
+	}
+
+}
+
 union lvds_info {
 	struct _ATOM_LVDS_INFO info;
 	struct _ATOM_LVDS_INFO_V12 info_12;
@@ -1161,6 +1208,21 @@
 
 		lvds->ss = radeon_atombios_get_ss_info(encoder, lvds_info->info.ucSS_Id);
 
+		if (ASIC_IS_AVIVO(rdev)) {
+			if (radeon_new_pll == 0)
+				lvds->pll_algo = PLL_ALGO_LEGACY;
+			else
+				lvds->pll_algo = PLL_ALGO_NEW;
+		} else {
+			if (radeon_new_pll == 1)
+				lvds->pll_algo = PLL_ALGO_NEW;
+			else
+				lvds->pll_algo = PLL_ALGO_LEGACY;
+		}
+
+		/* LVDS quirks */
+		radeon_atom_apply_lvds_quirks(dev, lvds);
+
 		encoder->native_mode = lvds->native_mode;
 	}
 	return lvds;
@@ -1385,6 +1447,371 @@
 	return tv_dac;
 }
 
+union power_info {
+	struct _ATOM_POWERPLAY_INFO info;
+	struct _ATOM_POWERPLAY_INFO_V2 info_2;
+	struct _ATOM_POWERPLAY_INFO_V3 info_3;
+	struct _ATOM_PPLIB_POWERPLAYTABLE info_4;
+};
+
+void radeon_atombios_get_power_modes(struct radeon_device *rdev)
+{
+	struct radeon_mode_info *mode_info = &rdev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
+	u16 data_offset;
+	u8 frev, crev;
+	u32 misc, misc2 = 0, sclk, mclk;
+	union power_info *power_info;
+	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
+	struct _ATOM_PPLIB_STATE *power_state;
+	int num_modes = 0, i, j;
+	int state_index = 0, mode_index = 0;
+
+	atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
+
+	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
+
+	rdev->pm.default_power_state = NULL;
+
+	if (power_info) {
+		if (frev < 4) {
+			num_modes = power_info->info.ucNumOfPowerModeEntries;
+			if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
+				num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
+			for (i = 0; i < num_modes; i++) {
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+				switch (frev) {
+				case 1:
+					rdev->pm.power_state[state_index].num_clock_modes = 1;
+					rdev->pm.power_state[state_index].clock_info[0].mclk =
+						le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
+					rdev->pm.power_state[state_index].clock_info[0].sclk =
+						le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock);
+					/* skip invalid modes */
+					if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
+					    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
+						continue;
+					/* skip overclock modes for now */
+					if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
+					     rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
+					    (rdev->pm.power_state[state_index].clock_info[0].sclk >
+					     rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
+						continue;
+					rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
+						power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
+					misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
+					if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+							VOLTAGE_GPIO;
+						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
+							radeon_lookup_gpio(rdev,
+							power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex);
+						if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
+							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+								true;
+						else
+							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+								false;
+					} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
+						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+							VOLTAGE_VDDC;
+						rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
+							power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
+					}
+					/* order matters! */
+					if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_POWERSAVE;
+					if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BATTERY;
+					if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BATTERY;
+					if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BALANCED;
+					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_PERFORMANCE;
+					if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_DEFAULT;
+						rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+						rdev->pm.power_state[state_index].default_clock_mode =
+							&rdev->pm.power_state[state_index].clock_info[0];
+					}
+					state_index++;
+					break;
+				case 2:
+					rdev->pm.power_state[state_index].num_clock_modes = 1;
+					rdev->pm.power_state[state_index].clock_info[0].mclk =
+						le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
+					rdev->pm.power_state[state_index].clock_info[0].sclk =
+						le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock);
+					/* skip invalid modes */
+					if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
+					    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
+						continue;
+					/* skip overclock modes for now */
+					if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
+					     rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
+					    (rdev->pm.power_state[state_index].clock_info[0].sclk >
+					     rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
+						continue;
+					rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
+						power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
+					misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
+					misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2);
+					if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+							VOLTAGE_GPIO;
+						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
+							radeon_lookup_gpio(rdev,
+							power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex);
+						if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
+							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+								true;
+						else
+							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+								false;
+					} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
+						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+							VOLTAGE_VDDC;
+						rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
+							power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
+					}
+					/* order matters! */
+					if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_POWERSAVE;
+					if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BATTERY;
+					if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BATTERY;
+					if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BALANCED;
+					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_PERFORMANCE;
+					if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BALANCED;
+					if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_DEFAULT;
+						rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+						rdev->pm.power_state[state_index].default_clock_mode =
+							&rdev->pm.power_state[state_index].clock_info[0];
+					}
+					state_index++;
+					break;
+				case 3:
+					rdev->pm.power_state[state_index].num_clock_modes = 1;
+					rdev->pm.power_state[state_index].clock_info[0].mclk =
+						le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
+					rdev->pm.power_state[state_index].clock_info[0].sclk =
+						le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock);
+					/* skip invalid modes */
+					if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
+					    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
+						continue;
+					/* skip overclock modes for now */
+					if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
+					     rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
+					    (rdev->pm.power_state[state_index].clock_info[0].sclk >
+					     rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
+						continue;
+					rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
+						power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
+					misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
+					misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2);
+					if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) {
+						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+							VOLTAGE_GPIO;
+						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio =
+							radeon_lookup_gpio(rdev,
+							power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex);
+						if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)
+							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+								true;
+						else
+							rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+								false;
+					} else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) {
+						rdev->pm.power_state[state_index].clock_info[0].voltage.type =
+							VOLTAGE_VDDC;
+						rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
+							power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex;
+						if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) {
+							rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled =
+								true;
+							rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id =
+							power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
+						}
+					}
+					/* order matters! */
+					if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_POWERSAVE;
+					if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BATTERY;
+					if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BATTERY;
+					if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BALANCED;
+					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_PERFORMANCE;
+					if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BALANCED;
+					if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_DEFAULT;
+						rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+						rdev->pm.power_state[state_index].default_clock_mode =
+							&rdev->pm.power_state[state_index].clock_info[0];
+					}
+					state_index++;
+					break;
+				}
+			}
+		} else if (frev == 4) {
+			for (i = 0; i < power_info->info_4.ucNumStates; i++) {
+				mode_index = 0;
+				power_state = (struct _ATOM_PPLIB_STATE *)
+					(mode_info->atom_context->bios +
+					 data_offset +
+					 le16_to_cpu(power_info->info_4.usStateArrayOffset) +
+					 i * power_info->info_4.ucStateEntrySize);
+				non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
+					(mode_info->atom_context->bios +
+					 data_offset +
+					 le16_to_cpu(power_info->info_4.usNonClockInfoArrayOffset) +
+					 (power_state->ucNonClockStateIndex *
+					  power_info->info_4.ucNonClockSize));
+				for (j = 0; j < (power_info->info_4.ucStateEntrySize - 1); j++) {
+					if (rdev->flags & RADEON_IS_IGP) {
+						struct _ATOM_PPLIB_RS780_CLOCK_INFO *clock_info =
+							(struct _ATOM_PPLIB_RS780_CLOCK_INFO *)
+							(mode_info->atom_context->bios +
+							 data_offset +
+							 le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
+							 (power_state->ucClockStateIndices[j] *
+							  power_info->info_4.ucClockInfoSize));
+						sclk = le16_to_cpu(clock_info->usLowEngineClockLow);
+						sclk |= clock_info->ucLowEngineClockHigh << 16;
+						rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
+						/* skip invalid modes */
+						if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
+							continue;
+						/* skip overclock modes for now */
+						if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
+						    rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN)
+							continue;
+						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
+							VOLTAGE_SW;
+						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
+							clock_info->usVDDC;
+						mode_index++;
+					} else {
+						struct _ATOM_PPLIB_R600_CLOCK_INFO *clock_info =
+							(struct _ATOM_PPLIB_R600_CLOCK_INFO *)
+							(mode_info->atom_context->bios +
+							 data_offset +
+							 le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) +
+							 (power_state->ucClockStateIndices[j] *
+							  power_info->info_4.ucClockInfoSize));
+						sclk = le16_to_cpu(clock_info->usEngineClockLow);
+						sclk |= clock_info->ucEngineClockHigh << 16;
+						mclk = le16_to_cpu(clock_info->usMemoryClockLow);
+						mclk |= clock_info->ucMemoryClockHigh << 16;
+						rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk;
+						rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
+						/* skip invalid modes */
+						if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
+						    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
+							continue;
+						/* skip overclock modes for now */
+						if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk >
+						     rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
+						    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
+						     rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
+							continue;
+						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
+							VOLTAGE_SW;
+						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
+							clock_info->usVDDC;
+						mode_index++;
+					}
+				}
+				rdev->pm.power_state[state_index].num_clock_modes = mode_index;
+				if (mode_index) {
+					misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
+					misc2 = le16_to_cpu(non_clock_info->usClassification);
+					rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
+						((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>
+						ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
+					switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
+					case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BATTERY;
+						break;
+					case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_BALANCED;
+						break;
+					case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_PERFORMANCE;
+						break;
+					}
+					if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
+						rdev->pm.power_state[state_index].type =
+							POWER_STATE_TYPE_DEFAULT;
+						rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+						rdev->pm.power_state[state_index].default_clock_mode =
+							&rdev->pm.power_state[state_index].clock_info[mode_index - 1];
+					}
+					state_index++;
+				}
+			}
+		}
+	} else {
+		/* XXX figure out some good default low power mode for cards w/out power tables */
+	}
+
+	if (rdev->pm.default_power_state == NULL) {
+		/* add the default mode */
+		rdev->pm.power_state[state_index].type =
+			POWER_STATE_TYPE_DEFAULT;
+		rdev->pm.power_state[state_index].num_clock_modes = 1;
+		rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
+		rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
+		rdev->pm.power_state[state_index].default_clock_mode =
+			&rdev->pm.power_state[state_index].clock_info[0];
+		rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+		if (rdev->asic->get_pcie_lanes)
+			rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev);
+		else
+			rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16;
+		rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+		state_index++;
+	}
+	rdev->pm.num_power_states = state_index;
+
+	rdev->pm.current_power_state = rdev->pm.default_power_state;
+	rdev->pm.current_clock_mode =
+		rdev->pm.default_power_state->default_clock_mode;
+}
+
 void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
 {
 	DYNAMIC_CLOCK_GATING_PS_ALLOCATION args;
@@ -1395,16 +1822,6 @@
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
-void radeon_atom_static_pwrmgt_setup(struct radeon_device *rdev, int enable)
-{
-	ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION args;
-	int index = GetIndexIntoMasterTable(COMMAND, EnableASIC_StaticPwrMgt);
-
-	args.ucEnable = enable;
-
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
 uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev)
 {
 	GET_ENGINE_CLOCK_PS_ALLOCATION args;
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
new file mode 100644
index 0000000..3f557c4
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2010 Red Hat Inc.
+ * Author : Dave Airlie <airlied@redhat.com>
+ *
+ * Licensed under GPLv2
+ *
+ * ATPX support for both Intel/ATI
+ */
+#include <linux/vga_switcheroo.h>
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <linux/pci.h>
+
+#define ATPX_VERSION 0
+#define ATPX_GPU_PWR 2
+#define ATPX_MUX_SELECT 3
+
+#define ATPX_INTEGRATED 0
+#define ATPX_DISCRETE 1
+
+#define ATPX_MUX_IGD 0
+#define ATPX_MUX_DISCRETE 1
+
+static struct radeon_atpx_priv {
+	bool atpx_detected;
+	/* handle for device - and atpx */
+	acpi_handle dhandle;
+	acpi_handle atpx_handle;
+	acpi_handle atrm_handle;
+} radeon_atpx_priv;
+
+/* retrieve the ROM in 4k blocks */
+static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
+			    int offset, int len)
+{
+	acpi_status status;
+	union acpi_object atrm_arg_elements[2], *obj;
+	struct acpi_object_list atrm_arg;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
+
+	atrm_arg.count = 2;
+	atrm_arg.pointer = &atrm_arg_elements[0];
+
+	atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
+	atrm_arg_elements[0].integer.value = offset;
+
+	atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
+	atrm_arg_elements[1].integer.value = len;
+
+	status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
+	if (ACPI_FAILURE(status)) {
+		printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
+		return -ENODEV;
+	}
+
+	obj = (union acpi_object *)buffer.pointer;
+	memcpy(bios+offset, obj->buffer.pointer, len);
+	kfree(buffer.pointer);
+	return len;
+}
+
+bool radeon_atrm_supported(struct pci_dev *pdev)
+{
+	/* get the discrete ROM only via ATRM */
+	if (!radeon_atpx_priv.atpx_detected)
+		return false;
+
+	if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
+		return false;
+	return true;
+}
+
+
+int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len)
+{
+	return radeon_atrm_call(radeon_atpx_priv.atrm_handle, bios, offset, len);
+}
+
+static int radeon_atpx_get_version(acpi_handle handle)
+{
+	acpi_status status;
+	union acpi_object atpx_arg_elements[2], *obj;
+	struct acpi_object_list atpx_arg;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	atpx_arg.count = 2;
+	atpx_arg.pointer = &atpx_arg_elements[0];
+
+	atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
+	atpx_arg_elements[0].integer.value = ATPX_VERSION;
+
+	atpx_arg_elements[1].type = ACPI_TYPE_INTEGER;
+	atpx_arg_elements[1].integer.value = ATPX_VERSION;
+
+	status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
+	if (ACPI_FAILURE(status)) {
+		printk("%s: failed to call ATPX: %s\n", __func__, acpi_format_exception(status));
+		return -ENOSYS;
+	}
+	obj = (union acpi_object *)buffer.pointer;
+	if (obj && (obj->type == ACPI_TYPE_BUFFER))
+		printk(KERN_INFO "radeon atpx: version is %d\n", *((u8 *)(obj->buffer.pointer) + 2));
+	kfree(buffer.pointer);
+	return 0;
+}
+
+static int radeon_atpx_execute(acpi_handle handle, int cmd_id, u16 value)
+{
+	acpi_status status;
+	union acpi_object atpx_arg_elements[2];
+	struct acpi_object_list atpx_arg;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	uint8_t buf[4] = {0};
+
+	if (!handle)
+		return -EINVAL;
+
+	atpx_arg.count = 2;
+	atpx_arg.pointer = &atpx_arg_elements[0];
+
+	atpx_arg_elements[0].type = ACPI_TYPE_INTEGER;
+	atpx_arg_elements[0].integer.value = cmd_id;
+
+	buf[2] = value & 0xff;
+	buf[3] = (value >> 8) & 0xff;
+
+	atpx_arg_elements[1].type = ACPI_TYPE_BUFFER;
+	atpx_arg_elements[1].buffer.length = 4;
+	atpx_arg_elements[1].buffer.pointer = buf;
+
+	status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
+	if (ACPI_FAILURE(status)) {
+		printk("%s: failed to call ATPX: %s\n", __func__, acpi_format_exception(status));
+		return -ENOSYS;
+	}
+	kfree(buffer.pointer);
+
+	return 0;
+}
+
+static int radeon_atpx_set_discrete_state(acpi_handle handle, int state)
+{
+	return radeon_atpx_execute(handle, ATPX_GPU_PWR, state);
+}
+
+static int radeon_atpx_switch_mux(acpi_handle handle, int mux_id)
+{
+	return radeon_atpx_execute(handle, ATPX_MUX_SELECT, mux_id);
+}
+
+
+static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
+{
+	if (id == VGA_SWITCHEROO_IGD)
+		radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 0);
+	else
+		radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 1);
+	return 0;
+}
+
+static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
+				   enum vga_switcheroo_state state)
+{
+	/* on w500 ACPI can't change intel gpu state */
+	if (id == VGA_SWITCHEROO_IGD)
+		return 0;
+
+	radeon_atpx_set_discrete_state(radeon_atpx_priv.atpx_handle, state);
+	return 0;
+}
+
+static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
+{
+	acpi_handle dhandle, atpx_handle, atrm_handle;
+	acpi_status status;
+
+	dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
+	if (!dhandle)
+		return false;
+
+	status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
+	if (ACPI_FAILURE(status))
+		return false;
+
+	status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
+	if (ACPI_FAILURE(status))
+		return false;
+
+	radeon_atpx_priv.dhandle = dhandle;
+	radeon_atpx_priv.atpx_handle = atpx_handle;
+	radeon_atpx_priv.atrm_handle = atrm_handle;
+	return true;
+}
+
+static int radeon_atpx_init(void)
+{
+	/* set up the ATPX handle */
+
+	radeon_atpx_get_version(radeon_atpx_priv.atpx_handle);
+	return 0;
+}
+
+static int radeon_atpx_get_client_id(struct pci_dev *pdev)
+{
+	if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
+		return VGA_SWITCHEROO_IGD;
+	else
+		return VGA_SWITCHEROO_DIS;
+}
+
+static struct vga_switcheroo_handler radeon_atpx_handler = {
+	.switchto = radeon_atpx_switchto,
+	.power_state = radeon_atpx_power_state,
+	.init = radeon_atpx_init,
+	.get_client_id = radeon_atpx_get_client_id,
+};
+
+static bool radeon_atpx_detect(void)
+{
+	char acpi_method_name[255] = { 0 };
+	struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
+	struct pci_dev *pdev = NULL;
+	bool has_atpx = false;
+	int vga_count = 0;
+
+	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
+		vga_count++;
+
+		has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
+	}
+
+	if (has_atpx && vga_count == 2) {
+		acpi_get_name(radeon_atpx_priv.atpx_handle, ACPI_FULL_PATHNAME, &buffer);
+		printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
+		       acpi_method_name);
+		radeon_atpx_priv.atpx_detected = true;
+		return true;
+	}
+	return false;
+}
+
+void radeon_register_atpx_handler(void)
+{
+	bool r;
+
+	/* detect if we have any ATPX + 2 VGA in the system */
+	r = radeon_atpx_detect();
+	if (!r)
+		return;
+
+	vga_switcheroo_register_handler(&radeon_atpx_handler);
+}
+
+void radeon_unregister_atpx_handler(void)
+{
+	vga_switcheroo_unregister_handler();
+}
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index 9069217..5572404 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -30,6 +30,7 @@
 #include "radeon.h"
 #include "atom.h"
 
+#include <linux/vga_switcheroo.h>
 /*
  * BIOS.
  */
@@ -62,7 +63,7 @@
 		iounmap(bios);
 		return false;
 	}
-	memcpy(rdev->bios, bios, size);
+	memcpy_fromio(rdev->bios, bios, size);
 	iounmap(bios);
 	return true;
 }
@@ -93,6 +94,38 @@
 	return true;
 }
 
+/* ATRM is used to get the BIOS on the discrete cards in
+ * dual-gpu systems.
+ */
+static bool radeon_atrm_get_bios(struct radeon_device *rdev)
+{
+	int ret;
+	int size = 64 * 1024;
+	int i;
+
+	if (!radeon_atrm_supported(rdev->pdev))
+		return false;
+
+	rdev->bios = kmalloc(size, GFP_KERNEL);
+	if (!rdev->bios) {
+		DRM_ERROR("Unable to allocate bios\n");
+		return false;
+	}
+
+	for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
+		ret = radeon_atrm_get_bios_chunk(rdev->bios,
+						 (i * ATRM_BIOS_PAGE),
+						 ATRM_BIOS_PAGE);
+		if (ret <= 0)
+			break;
+	}
+
+	if (i == 0 || rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
+		kfree(rdev->bios);
+		return false;
+	}
+	return true;
+}
 static bool r700_read_disabled_bios(struct radeon_device *rdev)
 {
 	uint32_t viph_control;
@@ -388,16 +421,16 @@
 		return legacy_read_disabled_bios(rdev);
 }
 
+
 bool radeon_get_bios(struct radeon_device *rdev)
 {
 	bool r;
 	uint16_t tmp;
 
-	if (rdev->flags & RADEON_IS_IGP) {
+	r = radeon_atrm_get_bios(rdev);
+	if (r == false)
 		r = igp_read_bios_from_vram(rdev);
-		if (r == false)
-			r = radeon_read_bios(rdev);
-	} else
+	if (r == false)
 		r = radeon_read_bios(rdev);
 	if (r == false) {
 		r = radeon_read_disabled_bios(rdev);
@@ -408,6 +441,13 @@
 		return false;
 	}
 	if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) {
+		printk("BIOS signature incorrect %x %x\n", rdev->bios[0], rdev->bios[1]);
+		goto free_bios;
+	}
+
+	tmp = RBIOS16(0x18);
+	if (RBIOS8(tmp + 0x14) != 0x0) {
+		DRM_INFO("Not an x86 BIOS ROM, not using.\n");
 		goto free_bios;
 	}
 
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c
index 73c4405..f64936c 100644
--- a/drivers/gpu/drm/radeon/radeon_clocks.c
+++ b/drivers/gpu/drm/radeon/radeon_clocks.c
@@ -96,6 +96,7 @@
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_pll *p1pll = &rdev->clock.p1pll;
 	struct radeon_pll *p2pll = &rdev->clock.p2pll;
+	struct radeon_pll *dcpll = &rdev->clock.dcpll;
 	struct radeon_pll *spll = &rdev->clock.spll;
 	struct radeon_pll *mpll = &rdev->clock.mpll;
 	int ret;
@@ -204,6 +205,17 @@
 		p2pll->max_frac_feedback_div = 0;
 	}
 
+	/* dcpll is DCE4 only */
+	dcpll->min_post_div = 2;
+	dcpll->max_post_div = 0x7f;
+	dcpll->min_frac_feedback_div = 0;
+	dcpll->max_frac_feedback_div = 9;
+	dcpll->min_ref_div = 2;
+	dcpll->max_ref_div = 0x3ff;
+	dcpll->min_feedback_div = 4;
+	dcpll->max_feedback_div = 0xfff;
+	dcpll->best_vco = 0;
+
 	p1pll->min_ref_div = 2;
 	p1pll->max_ref_div = 0x3ff;
 	p1pll->min_feedback_div = 4;
@@ -846,8 +858,10 @@
 	/* XXX make sure engine is idle */
 
 	if (radeon_dynclks != -1) {
-		if (radeon_dynclks)
-			radeon_set_clock_gating(rdev, 1);
+		if (radeon_dynclks) {
+			if (rdev->asic->set_clock_gating)
+				radeon_set_clock_gating(rdev, 1);
+		}
 	}
 	radeon_apply_clock_quirks(rdev);
 	return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 22d4761..e9ea38e 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -150,6 +150,9 @@
 	int rev;
 	uint16_t offset = 0, check_offset;
 
+	if (!rdev->bios)
+		return 0;
+
 	switch (table) {
 		/* absolute offset tables */
 	case COMBIOS_ASIC_INIT_1_TABLE:
@@ -443,6 +446,39 @@
 
 }
 
+bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
+{
+	int edid_info;
+	struct edid *edid;
+	edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE);
+	if (!edid_info)
+		return false;
+
+	edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1),
+		       GFP_KERNEL);
+	if (edid == NULL)
+		return false;
+
+	memcpy((unsigned char *)edid,
+	       (unsigned char *)(rdev->bios + edid_info), EDID_LENGTH);
+
+	if (!drm_edid_is_valid(edid)) {
+		kfree(edid);
+		return false;
+	}
+
+	rdev->mode_info.bios_hardcoded_edid = edid;
+	return true;
+}
+
+struct edid *
+radeon_combios_get_hardcoded_edid(struct radeon_device *rdev)
+{
+	if (rdev->mode_info.bios_hardcoded_edid)
+		return rdev->mode_info.bios_hardcoded_edid;
+	return NULL;
+}
+
 static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rdev,
 						       int ddc_line)
 {
@@ -486,9 +522,65 @@
 		i2c.y_data_reg = ddc_line;
 	}
 
-	if (rdev->family < CHIP_R200)
-		i2c.hw_capable = false;
-	else {
+	switch (rdev->family) {
+	case CHIP_R100:
+	case CHIP_RV100:
+	case CHIP_RS100:
+	case CHIP_RV200:
+	case CHIP_RS200:
+	case CHIP_RS300:
+		switch (ddc_line) {
+		case RADEON_GPIO_DVI_DDC:
+			/* in theory this should be hw capable,
+			 * but it doesn't seem to work
+			 */
+			i2c.hw_capable = false;
+			break;
+		default:
+			i2c.hw_capable = false;
+			break;
+		}
+		break;
+	case CHIP_R200:
+		switch (ddc_line) {
+		case RADEON_GPIO_DVI_DDC:
+		case RADEON_GPIO_MONID:
+			i2c.hw_capable = true;
+			break;
+		default:
+			i2c.hw_capable = false;
+			break;
+		}
+		break;
+	case CHIP_RV250:
+	case CHIP_RV280:
+		switch (ddc_line) {
+		case RADEON_GPIO_VGA_DDC:
+		case RADEON_GPIO_DVI_DDC:
+		case RADEON_GPIO_CRT2_DDC:
+			i2c.hw_capable = true;
+			break;
+		default:
+			i2c.hw_capable = false;
+			break;
+		}
+		break;
+	case CHIP_R300:
+	case CHIP_R350:
+		switch (ddc_line) {
+		case RADEON_GPIO_VGA_DDC:
+		case RADEON_GPIO_DVI_DDC:
+			i2c.hw_capable = true;
+			break;
+		default:
+			i2c.hw_capable = false;
+			break;
+		}
+		break;
+	case CHIP_RV350:
+	case CHIP_RV380:
+	case CHIP_RS400:
+	case CHIP_RS480:
 		switch (ddc_line) {
 		case RADEON_GPIO_VGA_DDC:
 		case RADEON_GPIO_DVI_DDC:
@@ -504,9 +596,14 @@
 			i2c.hw_capable = false;
 			break;
 		}
+		break;
+	default:
+		i2c.hw_capable = false;
+		break;
 	}
 	i2c.mm_i2c = false;
 	i2c.i2c_id = 0;
+	i2c.hpd_id = 0;
 
 	if (ddc_line)
 		i2c.valid = true;
@@ -527,9 +624,6 @@
 	int8_t rev;
 	uint16_t sclk, mclk;
 
-	if (rdev->bios == NULL)
-		return false;
-
 	pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE);
 	if (pll_info) {
 		rev = RBIOS8(pll_info);
@@ -654,9 +748,6 @@
 	if (!p_dac)
 		return NULL;
 
-	if (rdev->bios == NULL)
-		goto out;
-
 	/* check CRT table */
 	dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
 	if (dac_info) {
@@ -673,7 +764,6 @@
 		found = 1;
 	}
 
-out:
 	if (!found) /* fallback to defaults */
 		radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac);
 
@@ -687,9 +777,6 @@
 	uint16_t tv_info;
 	enum radeon_tv_std tv_std = TV_STD_NTSC;
 
-	if (rdev->bios == NULL)
-		return tv_std;
-
 	tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
 	if (tv_info) {
 		if (RBIOS8(tv_info + 6) == 'T') {
@@ -793,9 +880,6 @@
 	if (!tv_dac)
 		return NULL;
 
-	if (rdev->bios == NULL)
-		goto out;
-
 	/* first check TV table */
 	dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
 	if (dac_info) {
@@ -857,7 +941,6 @@
 		}
 	}
 
-out:
 	if (!found) /* fallback to defaults */
 		radeon_legacy_get_tv_dac_info_from_table(rdev, tv_dac);
 
@@ -945,11 +1028,6 @@
 	int tmp, i;
 	struct radeon_encoder_lvds *lvds = NULL;
 
-	if (rdev->bios == NULL) {
-		lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
-		goto out;
-	}
-
 	lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE);
 
 	if (lcd_info) {
@@ -1050,7 +1128,7 @@
 		DRM_INFO("No panel info found in BIOS\n");
 		lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
 	}
-out:
+
 	if (lvds)
 		encoder->native_mode = lvds->native_mode;
 	return lvds;
@@ -1102,9 +1180,6 @@
 	int i, n;
 	uint8_t ver;
 
-	if (rdev->bios == NULL)
-		return false;
-
 	tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE);
 
 	if (tmds_info) {
@@ -1184,9 +1259,6 @@
 	enum radeon_combios_ddc gpio;
 	struct radeon_i2c_bus_rec i2c_bus;
 
-	if (rdev->bios == NULL)
-		return false;
-
 	tmds->i2c_bus = NULL;
 	if (rdev->flags & RADEON_IS_IGP) {
 		offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE);
@@ -1253,7 +1325,10 @@
 				tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
 				break;
 			case DDC_LCD: /* MM i2c */
-				DRM_ERROR("MM i2c requires hw i2c engine\n");
+				i2c_bus.valid = true;
+				i2c_bus.hw_capable = true;
+				i2c_bus.mm_i2c = true;
+				tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
 				break;
 			default:
 				DRM_ERROR("Unsupported gpio %d\n", gpio);
@@ -1909,9 +1984,6 @@
 	struct radeon_i2c_bus_rec ddc_i2c;
 	struct radeon_hpd hpd;
 
-	if (rdev->bios == NULL)
-		return false;
-
 	conn_info = combios_get_table_offset(dev, COMBIOS_CONNECTOR_INFO_TABLE);
 	if (conn_info) {
 		for (i = 0; i < 4; i++) {
@@ -2278,6 +2350,115 @@
 	return true;
 }
 
+void radeon_combios_get_power_modes(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	u16 offset, misc, misc2 = 0;
+	u8 rev, blocks, tmp;
+	int state_index = 0;
+
+	rdev->pm.default_power_state = NULL;
+
+	if (rdev->flags & RADEON_IS_MOBILITY) {
+		offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE);
+		if (offset) {
+			rev = RBIOS8(offset);
+			blocks = RBIOS8(offset + 0x2);
+			/* power mode 0 tends to be the only valid one */
+			rdev->pm.power_state[state_index].num_clock_modes = 1;
+			rdev->pm.power_state[state_index].clock_info[0].mclk = RBIOS32(offset + 0x5 + 0x2);
+			rdev->pm.power_state[state_index].clock_info[0].sclk = RBIOS32(offset + 0x5 + 0x6);
+			if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
+			    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
+				goto default_mode;
+			/* skip overclock modes for now */
+			if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
+			     rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
+			    (rdev->pm.power_state[state_index].clock_info[0].sclk >
+			     rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
+				goto default_mode;
+			rdev->pm.power_state[state_index].type =
+				POWER_STATE_TYPE_BATTERY;
+			misc = RBIOS16(offset + 0x5 + 0x0);
+			if (rev > 4)
+				misc2 = RBIOS16(offset + 0x5 + 0xe);
+			if (misc & 0x4) {
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_GPIO;
+				if (misc & 0x8)
+					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+						true;
+				else
+					rdev->pm.power_state[state_index].clock_info[0].voltage.active_high =
+						false;
+				rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = true;
+				if (rev < 6) {
+					rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg =
+						RBIOS16(offset + 0x5 + 0xb) * 4;
+					tmp = RBIOS8(offset + 0x5 + 0xd);
+					rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp);
+				} else {
+					u8 entries = RBIOS8(offset + 0x5 + 0xb);
+					u16 voltage_table_offset = RBIOS16(offset + 0x5 + 0xc);
+					if (entries && voltage_table_offset) {
+						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.reg =
+							RBIOS16(voltage_table_offset) * 4;
+						tmp = RBIOS8(voltage_table_offset + 0x2);
+						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.mask = (1 << tmp);
+					} else
+						rdev->pm.power_state[state_index].clock_info[0].voltage.gpio.valid = false;
+				}
+				switch ((misc2 & 0x700) >> 8) {
+				case 0:
+				default:
+					rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 0;
+					break;
+				case 1:
+					rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 33;
+					break;
+				case 2:
+					rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 66;
+					break;
+				case 3:
+					rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 99;
+					break;
+				case 4:
+					rdev->pm.power_state[state_index].clock_info[0].voltage.delay = 132;
+					break;
+				}
+			} else
+				rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+			if (rev > 6)
+				rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
+					RBIOS8(offset + 0x5 + 0x10);
+			state_index++;
+		} else {
+			/* XXX figure out some good default low power mode for mobility cards w/out power tables */
+		}
+	} else {
+		/* XXX figure out some good default low power mode for desktop cards */
+	}
+
+default_mode:
+	/* add the default mode */
+	rdev->pm.power_state[state_index].type =
+		POWER_STATE_TYPE_DEFAULT;
+	rdev->pm.power_state[state_index].num_clock_modes = 1;
+	rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
+	rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
+	rdev->pm.power_state[state_index].default_clock_mode = &rdev->pm.power_state[state_index].clock_info[0];
+	rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+	if (rdev->asic->get_pcie_lanes)
+		rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev);
+	else
+		rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16;
+	rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+	rdev->pm.num_power_states = state_index + 1;
+
+	rdev->pm.current_power_state = rdev->pm.default_power_state;
+	rdev->pm.current_clock_mode =
+		rdev->pm.default_power_state->default_clock_mode;
+}
+
 void radeon_external_tmds_setup(struct drm_encoder *encoder)
 {
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -2289,23 +2470,21 @@
 	switch (tmds->dvo_chip) {
 	case DVO_SIL164:
 		/* sil 164 */
-		radeon_i2c_do_lock(tmds->i2c_bus, 1);
-		radeon_i2c_sw_put_byte(tmds->i2c_bus,
-				       tmds->slave_addr,
-				       0x08, 0x30);
-		radeon_i2c_sw_put_byte(tmds->i2c_bus,
+		radeon_i2c_put_byte(tmds->i2c_bus,
+				    tmds->slave_addr,
+				    0x08, 0x30);
+		radeon_i2c_put_byte(tmds->i2c_bus,
 				       tmds->slave_addr,
 				       0x09, 0x00);
-		radeon_i2c_sw_put_byte(tmds->i2c_bus,
-				       tmds->slave_addr,
-				       0x0a, 0x90);
-		radeon_i2c_sw_put_byte(tmds->i2c_bus,
-				       tmds->slave_addr,
-				       0x0c, 0x89);
-		radeon_i2c_sw_put_byte(tmds->i2c_bus,
+		radeon_i2c_put_byte(tmds->i2c_bus,
+				    tmds->slave_addr,
+				    0x0a, 0x90);
+		radeon_i2c_put_byte(tmds->i2c_bus,
+				    tmds->slave_addr,
+				    0x0c, 0x89);
+		radeon_i2c_put_byte(tmds->i2c_bus,
 				       tmds->slave_addr,
 				       0x08, 0x3b);
-		radeon_i2c_do_lock(tmds->i2c_bus, 0);
 		break;
 	case DVO_SIL1178:
 		/* sil 1178 - untested */
@@ -2338,9 +2517,6 @@
 	uint32_t reg, val, and_mask, or_mask;
 	struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
 
-	if (rdev->bios == NULL)
-		return false;
-
 	if (!tmds)
 		return false;
 
@@ -2390,11 +2566,9 @@
 						index++;
 						val = RBIOS8(index);
 						index++;
-						radeon_i2c_do_lock(tmds->i2c_bus, 1);
-						radeon_i2c_sw_put_byte(tmds->i2c_bus,
-								       slave_addr,
-								       reg, val);
-						radeon_i2c_do_lock(tmds->i2c_bus, 0);
+						radeon_i2c_put_byte(tmds->i2c_bus,
+								    slave_addr,
+								    reg, val);
 						break;
 					default:
 						DRM_ERROR("Unknown id %d\n", id >> 13);
@@ -2447,11 +2621,9 @@
 					reg = id & 0x1fff;
 					val = RBIOS8(index);
 					index += 1;
-					radeon_i2c_do_lock(tmds->i2c_bus, 1);
-					radeon_i2c_sw_put_byte(tmds->i2c_bus,
-							       tmds->slave_addr,
-							       reg, val);
-					radeon_i2c_do_lock(tmds->i2c_bus, 0);
+					radeon_i2c_put_byte(tmds->i2c_bus,
+							    tmds->slave_addr,
+							    reg, val);
 					break;
 				default:
 					DRM_ERROR("Unknown id %d\n", id >> 13);
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 65f8194..ee0083f 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -479,10 +479,8 @@
 		ret = connector_status_connected;
 	else {
 		if (radeon_connector->ddc_bus) {
-			radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 			radeon_connector->edid = drm_get_edid(&radeon_connector->base,
 							      &radeon_connector->ddc_bus->adapter);
-			radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 			if (radeon_connector->edid)
 				ret = connector_status_connected;
 		}
@@ -587,19 +585,14 @@
 	if (!encoder)
 		ret = connector_status_disconnected;
 
-	if (radeon_connector->ddc_bus) {
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
+	if (radeon_connector->ddc_bus)
 		dret = radeon_ddc_probe(radeon_connector);
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
-	}
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
 			radeon_connector->edid = NULL;
 		}
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 
 		if (!radeon_connector->edid) {
 			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
@@ -744,19 +737,14 @@
 	enum drm_connector_status ret = connector_status_disconnected;
 	bool dret = false;
 
-	if (radeon_connector->ddc_bus) {
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
+	if (radeon_connector->ddc_bus)
 		dret = radeon_ddc_probe(radeon_connector);
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
-	}
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
 			radeon_connector->edid = NULL;
 		}
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 
 		if (!radeon_connector->edid) {
 			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
@@ -952,7 +940,7 @@
 	if (radeon_connector->edid)
 		kfree(radeon_connector->edid);
 	if (radeon_dig_connector->dp_i2c_bus)
-		radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus);
+		radeon_i2c_destroy_dp(radeon_dig_connector->dp_i2c_bus);
 	kfree(radeon_connector->con_priv);
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
@@ -988,12 +976,10 @@
 			ret = connector_status_connected;
 		}
 	} else {
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 		if (radeon_ddc_probe(radeon_connector)) {
 			radeon_dig_connector->dp_sink_type = sink_type;
 			ret = connector_status_connected;
 		}
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 	}
 
 	return ret;
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 06123ba..dc6eba6 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -1644,6 +1644,7 @@
 	radeon_cp_load_microcode(dev_priv);
 	radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
 
+	dev_priv->have_z_offset = 0;
 	radeon_do_engine_reset(dev);
 	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
 
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index e9d0850..70ba02e 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -194,11 +194,8 @@
 	}
 	radeon_bo_list_unreserve(&parser->validated);
 	for (i = 0; i < parser->nrelocs; i++) {
-		if (parser->relocs[i].gobj) {
-			mutex_lock(&parser->rdev->ddev->struct_mutex);
-			drm_gem_object_unreference(parser->relocs[i].gobj);
-			mutex_unlock(&parser->rdev->ddev->struct_mutex);
-		}
+		if (parser->relocs[i].gobj)
+			drm_gem_object_unreference_unlocked(parser->relocs[i].gobj);
 	}
 	kfree(parser->track);
 	kfree(parser->relocs);
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index 28772a3..b7023ff 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -36,7 +36,14 @@
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	uint32_t cur_lock;
 
-	if (ASIC_IS_AVIVO(rdev)) {
+	if (ASIC_IS_DCE4(rdev)) {
+		cur_lock = RREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset);
+		if (lock)
+			cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK;
+		else
+			cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
+		WREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
+	} else if (ASIC_IS_AVIVO(rdev)) {
 		cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
 		if (lock)
 			cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
@@ -58,7 +65,10 @@
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct radeon_device *rdev = crtc->dev->dev_private;
 
-	if (ASIC_IS_AVIVO(rdev)) {
+	if (ASIC_IS_DCE4(rdev)) {
+		WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
+		WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
+	} else if (ASIC_IS_AVIVO(rdev)) {
 		WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
 		WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
 	} else {
@@ -81,10 +91,14 @@
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct radeon_device *rdev = crtc->dev->dev_private;
 
-	if (ASIC_IS_AVIVO(rdev)) {
+	if (ASIC_IS_DCE4(rdev)) {
+		WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
+		WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN |
+		       EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
+	} else if (ASIC_IS_AVIVO(rdev)) {
 		WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
 		WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
-			     (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
+		       (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
 	} else {
 		switch (radeon_crtc->crtc_id) {
 		case 0:
@@ -109,7 +123,10 @@
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct radeon_device *rdev = crtc->dev->dev_private;
 
-	if (ASIC_IS_AVIVO(rdev)) {
+	if (ASIC_IS_DCE4(rdev)) {
+		WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 0);
+		WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
+	} else if (ASIC_IS_AVIVO(rdev)) {
 		if (rdev->family >= CHIP_RV770) {
 			if (radeon_crtc->crtc_id)
 				WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, 0);
@@ -169,17 +186,13 @@
 unpin:
 	if (radeon_crtc->cursor_bo) {
 		radeon_gem_object_unpin(radeon_crtc->cursor_bo);
-		mutex_lock(&crtc->dev->struct_mutex);
-		drm_gem_object_unreference(radeon_crtc->cursor_bo);
-		mutex_unlock(&crtc->dev->struct_mutex);
+		drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo);
 	}
 
 	radeon_crtc->cursor_bo = obj;
 	return 0;
 fail:
-	mutex_lock(&crtc->dev->struct_mutex);
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&crtc->dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(obj);
 
 	return 0;
 }
@@ -201,7 +214,20 @@
 		yorigin = CURSOR_HEIGHT - 1;
 
 	radeon_lock_cursor(crtc, true);
-	if (ASIC_IS_AVIVO(rdev)) {
+	if (ASIC_IS_DCE4(rdev)) {
+		/* cursors are offset into the total surface */
+		x += crtc->x;
+		y += crtc->y;
+		DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
+
+		/* XXX: check if evergreen has the same issues as avivo chips */
+		WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset,
+		       ((xorigin ? 0 : x) << 16) |
+		       (yorigin ? 0 : y));
+		WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
+		WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
+		       ((radeon_crtc->cursor_width - 1) << 16) | (radeon_crtc->cursor_height - 1));
+	} else if (ASIC_IS_AVIVO(rdev)) {
 		int w = radeon_crtc->cursor_width;
 		int i = 0;
 		struct drm_crtc *crtc_p;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 768b150..e28e4ed 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -30,6 +30,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/radeon_drm.h>
 #include <linux/vgaarb.h>
+#include <linux/vga_switcheroo.h>
 #include "radeon_reg.h"
 #include "radeon.h"
 #include "radeon_asic.h"
@@ -100,79 +101,102 @@
 	}
 }
 
-/*
- * MC common functions
+/**
+ * radeon_vram_location - try to find VRAM location
+ * @rdev: radeon device structure holding all necessary informations
+ * @mc: memory controller structure holding memory informations
+ * @base: base address at which to put VRAM
+ *
+ * Function will place try to place VRAM at base address provided
+ * as parameter (which is so far either PCI aperture address or
+ * for IGP TOM base address).
+ *
+ * If there is not enough space to fit the unvisible VRAM in the 32bits
+ * address space then we limit the VRAM size to the aperture.
+ *
+ * If we are using AGP and if the AGP aperture doesn't allow us to have
+ * room for all the VRAM than we restrict the VRAM to the PCI aperture
+ * size and print a warning.
+ *
+ * This function will never fails, worst case are limiting VRAM.
+ *
+ * Note: GTT start, end, size should be initialized before calling this
+ * function on AGP platform.
+ *
+ * Note: We don't explictly enforce VRAM start to be aligned on VRAM size,
+ * this shouldn't be a problem as we are using the PCI aperture as a reference.
+ * Otherwise this would be needed for rv280, all r3xx, and all r4xx, but
+ * not IGP.
+ *
+ * Note: we use mc_vram_size as on some board we need to program the mc to
+ * cover the whole aperture even if VRAM size is inferior to aperture size
+ * Novell bug 204882 + along with lots of ubuntu ones
+ *
+ * Note: when limiting vram it's safe to overwritte real_vram_size because
+ * we are not in case where real_vram_size is inferior to mc_vram_size (ie
+ * note afected by bogus hw of Novell bug 204882 + along with lots of ubuntu
+ * ones)
+ *
+ * Note: IGP TOM addr should be the same as the aperture addr, we don't
+ * explicitly check for that thought.
+ *
+ * FIXME: when reducing VRAM size align new size on power of 2.
  */
-int radeon_mc_setup(struct radeon_device *rdev)
+void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base)
 {
-	uint32_t tmp;
-
-	/* Some chips have an "issue" with the memory controller, the
-	 * location must be aligned to the size. We just align it down,
-	 * too bad if we walk over the top of system memory, we don't
-	 * use DMA without a remapped anyway.
-	 * Affected chips are rv280, all r3xx, and all r4xx, but not IGP
-	 */
-	/* FGLRX seems to setup like this, VRAM a 0, then GART.
-	 */
-	/*
-	 * Note: from R6xx the address space is 40bits but here we only
-	 * use 32bits (still have to see a card which would exhaust 4G
-	 * address space).
-	 */
-	if (rdev->mc.vram_location != 0xFFFFFFFFUL) {
-		/* vram location was already setup try to put gtt after
-		 * if it fits */
-		tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
-		tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
-		if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
-			rdev->mc.gtt_location = tmp;
-		} else {
-			if (rdev->mc.gtt_size >= rdev->mc.vram_location) {
-				printk(KERN_ERR "[drm] GTT too big to fit "
-				       "before or after vram location.\n");
-				return -EINVAL;
-			}
-			rdev->mc.gtt_location = 0;
-		}
-	} else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) {
-		/* gtt location was already setup try to put vram before
-		 * if it fits */
-		if (rdev->mc.mc_vram_size < rdev->mc.gtt_location) {
-			rdev->mc.vram_location = 0;
-		} else {
-			tmp = rdev->mc.gtt_location + rdev->mc.gtt_size;
-			tmp += (rdev->mc.mc_vram_size - 1);
-			tmp &= ~(rdev->mc.mc_vram_size - 1);
-			if ((0xFFFFFFFFUL - tmp) >= rdev->mc.mc_vram_size) {
-				rdev->mc.vram_location = tmp;
-			} else {
-				printk(KERN_ERR "[drm] vram too big to fit "
-				       "before or after GTT location.\n");
-				return -EINVAL;
-			}
-		}
-	} else {
-		rdev->mc.vram_location = 0;
-		tmp = rdev->mc.mc_vram_size;
-		tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
-		rdev->mc.gtt_location = tmp;
+	mc->vram_start = base;
+	if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) {
+		dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
+		mc->real_vram_size = mc->aper_size;
+		mc->mc_vram_size = mc->aper_size;
 	}
-	rdev->mc.vram_start = rdev->mc.vram_location;
-	rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
-	rdev->mc.gtt_start = rdev->mc.gtt_location;
-	rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
-	DRM_INFO("radeon: VRAM %uM\n", (unsigned)(rdev->mc.mc_vram_size >> 20));
-	DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n",
-		 (unsigned)rdev->mc.vram_location,
-		 (unsigned)(rdev->mc.vram_location + rdev->mc.mc_vram_size - 1));
-	DRM_INFO("radeon: GTT %uM\n", (unsigned)(rdev->mc.gtt_size >> 20));
-	DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n",
-		 (unsigned)rdev->mc.gtt_location,
-		 (unsigned)(rdev->mc.gtt_location + rdev->mc.gtt_size - 1));
-	return 0;
+	mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
+	if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_end <= mc->gtt_end) {
+		dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
+		mc->real_vram_size = mc->aper_size;
+		mc->mc_vram_size = mc->aper_size;
+	}
+	mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
+	dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
+			mc->mc_vram_size >> 20, mc->vram_start,
+			mc->vram_end, mc->real_vram_size >> 20);
 }
 
+/**
+ * radeon_gtt_location - try to find GTT location
+ * @rdev: radeon device structure holding all necessary informations
+ * @mc: memory controller structure holding memory informations
+ *
+ * Function will place try to place GTT before or after VRAM.
+ *
+ * If GTT size is bigger than space left then we ajust GTT size.
+ * Thus function will never fails.
+ *
+ * FIXME: when reducing GTT size align new size on power of 2.
+ */
+void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
+{
+	u64 size_af, size_bf;
+
+	size_af = 0xFFFFFFFF - mc->vram_end;
+	size_bf = mc->vram_start;
+	if (size_bf > size_af) {
+		if (mc->gtt_size > size_bf) {
+			dev_warn(rdev->dev, "limiting GTT\n");
+			mc->gtt_size = size_bf;
+		}
+		mc->gtt_start = mc->vram_start - mc->gtt_size;
+	} else {
+		if (mc->gtt_size > size_af) {
+			dev_warn(rdev->dev, "limiting GTT\n");
+			mc->gtt_size = size_af;
+		}
+		mc->gtt_start = mc->vram_end + 1;
+	}
+	mc->gtt_end = mc->gtt_start + mc->gtt_size - 1;
+	dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n",
+			mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end);
+}
 
 /*
  * GPU helpers function.
@@ -182,7 +206,16 @@
 	uint32_t reg;
 
 	/* first check CRTCs */
-	if (ASIC_IS_AVIVO(rdev)) {
+	if (ASIC_IS_DCE4(rdev)) {
+		reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) |
+			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) |
+			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) |
+			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) |
+			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) |
+			RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
+		if (reg & EVERGREEN_CRTC_MASTER_EN)
+			return true;
+	} else if (ASIC_IS_AVIVO(rdev)) {
 		reg = RREG32(AVIVO_D1CRTC_CONTROL) |
 		      RREG32(AVIVO_D2CRTC_CONTROL);
 		if (reg & AVIVO_CRTC_EN) {
@@ -229,6 +262,8 @@
 
 int radeon_dummy_page_init(struct radeon_device *rdev)
 {
+	if (rdev->dummy_page.page)
+		return 0;
 	rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO);
 	if (rdev->dummy_page.page == NULL)
 		return -ENOMEM;
@@ -310,7 +345,7 @@
 		rdev->mc_rreg = &rs600_mc_rreg;
 		rdev->mc_wreg = &rs600_mc_wreg;
 	}
-	if (rdev->family >= CHIP_R600) {
+	if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_RV740)) {
 		rdev->pciep_rreg = &r600_pciep_rreg;
 		rdev->pciep_wreg = &r600_pciep_wreg;
 	}
@@ -329,21 +364,22 @@
 	case CHIP_RS100:
 	case CHIP_RV200:
 	case CHIP_RS200:
+		rdev->asic = &r100_asic;
+		break;
 	case CHIP_R200:
 	case CHIP_RV250:
 	case CHIP_RS300:
 	case CHIP_RV280:
-		rdev->asic = &r100_asic;
+		rdev->asic = &r200_asic;
 		break;
 	case CHIP_R300:
 	case CHIP_R350:
 	case CHIP_RV350:
 	case CHIP_RV380:
-		rdev->asic = &r300_asic;
-		if (rdev->flags & RADEON_IS_PCIE) {
-			rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
-			rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
-		}
+		if (rdev->flags & RADEON_IS_PCIE)
+			rdev->asic = &r300_asic_pcie;
+		else
+			rdev->asic = &r300_asic;
 		break;
 	case CHIP_R420:
 	case CHIP_R423:
@@ -387,6 +423,13 @@
 	case CHIP_RV740:
 		rdev->asic = &rv770_asic;
 		break;
+	case CHIP_CEDAR:
+	case CHIP_REDWOOD:
+	case CHIP_JUNIPER:
+	case CHIP_CYPRESS:
+	case CHIP_HEMLOCK:
+		rdev->asic = &evergreen_asic;
+		break;
 	default:
 		/* FIXME: not supported yet */
 		return -EINVAL;
@@ -613,6 +656,36 @@
 	}
 }
 
+static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct radeon_device *rdev = dev->dev_private;
+	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
+	if (state == VGA_SWITCHEROO_ON) {
+		printk(KERN_INFO "radeon: switched on\n");
+		/* don't suspend or resume card normally */
+		rdev->powered_down = false;
+		radeon_resume_kms(dev);
+	} else {
+		printk(KERN_INFO "radeon: switched off\n");
+		radeon_suspend_kms(dev, pmm);
+		/* don't suspend or resume card normally */
+		rdev->powered_down = true;
+	}
+}
+
+static bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	bool can_switch;
+
+	spin_lock(&dev->count_lock);
+	can_switch = (dev->open_count == 0);
+	spin_unlock(&dev->count_lock);
+	return can_switch;
+}
+
+
 int radeon_device_init(struct radeon_device *rdev,
 		       struct drm_device *ddev,
 		       struct pci_dev *pdev,
@@ -638,11 +711,14 @@
 	mutex_init(&rdev->cs_mutex);
 	mutex_init(&rdev->ib_pool.mutex);
 	mutex_init(&rdev->cp.mutex);
+	mutex_init(&rdev->dc_hw_i2c_mutex);
 	if (rdev->family >= CHIP_R600)
 		spin_lock_init(&rdev->ih.lock);
 	mutex_init(&rdev->gem.mutex);
+	mutex_init(&rdev->pm.mutex);
 	rwlock_init(&rdev->fence_drv.lock);
 	INIT_LIST_HEAD(&rdev->gem.objects);
+	init_waitqueue_head(&rdev->irq.vblank_queue);
 
 	/* setup workqueue */
 	rdev->wq = create_workqueue("radeon");
@@ -692,6 +768,9 @@
 	/* this will fail for cards that aren't VGA class devices, just
 	 * ignore it */
 	vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
+	vga_switcheroo_register_client(rdev->pdev,
+				       radeon_switcheroo_set_state,
+				       radeon_switcheroo_can_switch);
 
 	r = radeon_init(rdev);
 	if (r)
@@ -723,6 +802,7 @@
 	rdev->shutdown = true;
 	radeon_fini(rdev);
 	destroy_workqueue(rdev->wq);
+	vga_switcheroo_unregister_client(rdev->pdev);
 	vga_client_register(rdev->pdev, NULL, NULL, NULL);
 	iounmap(rdev->rmmio);
 	rdev->rmmio = NULL;
@@ -746,6 +826,8 @@
 	}
 	rdev = dev->dev_private;
 
+	if (rdev->powered_down)
+		return 0;
 	/* unpin the front buffers */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
@@ -791,6 +873,9 @@
 {
 	struct radeon_device *rdev = dev->dev_private;
 
+	if (rdev->powered_down)
+		return 0;
+
 	acquire_console_sem();
 	pci_set_power_state(dev->pdev, PCI_D0);
 	pci_restore_state(dev->pdev);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 7e17a36..ba8d806 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -68,6 +68,36 @@
 	WREG32(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id);
 }
 
+static void evergreen_crtc_load_lut(struct drm_crtc *crtc)
+{
+	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int i;
+
+	DRM_DEBUG("%d\n", radeon_crtc->crtc_id);
+	WREG32(EVERGREEN_DC_LUT_CONTROL + radeon_crtc->crtc_offset, 0);
+
+	WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
+	WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
+
+	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff);
+	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff);
+	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff);
+
+	WREG32(EVERGREEN_DC_LUT_RW_MODE, radeon_crtc->crtc_id);
+	WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK, 0x00000007);
+
+	WREG32(EVERGREEN_DC_LUT_RW_INDEX, 0);
+	for (i = 0; i < 256; i++) {
+		WREG32(EVERGREEN_DC_LUT_30_COLOR,
+		       (radeon_crtc->lut_r[i] << 20) |
+		       (radeon_crtc->lut_g[i] << 10) |
+		       (radeon_crtc->lut_b[i] << 0));
+	}
+}
+
 static void legacy_crtc_load_lut(struct drm_crtc *crtc)
 {
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -100,7 +130,9 @@
 	if (!crtc->enabled)
 		return;
 
-	if (ASIC_IS_AVIVO(rdev))
+	if (ASIC_IS_DCE4(rdev))
+		evergreen_crtc_load_lut(crtc);
+	else if (ASIC_IS_AVIVO(rdev))
 		avivo_crtc_load_lut(crtc);
 	else
 		legacy_crtc_load_lut(crtc);
@@ -361,6 +393,8 @@
 
 int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
 {
+	struct drm_device *dev = radeon_connector->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
 	int ret = 0;
 
 	if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
@@ -373,11 +407,11 @@
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	if (!radeon_connector->edid) {
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 		radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
-		radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 	}
-
+	/* some servers provide a hardcoded edid in rom for KVMs */
+	if (!radeon_connector->edid)
+		radeon_connector->edid = radeon_combios_get_hardcoded_edid(rdev);
 	if (radeon_connector->edid) {
 		drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
 		ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
@@ -395,9 +429,7 @@
 
 	if (!radeon_connector->ddc_bus)
 		return -1;
-	radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
-	radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
 	if (edid) {
 		kfree(edid);
 	}
@@ -414,13 +446,13 @@
 	return n;
 }
 
-void radeon_compute_pll(struct radeon_pll *pll,
-			uint64_t freq,
-			uint32_t *dot_clock_p,
-			uint32_t *fb_div_p,
-			uint32_t *frac_fb_div_p,
-			uint32_t *ref_div_p,
-			uint32_t *post_div_p)
+static void radeon_compute_pll_legacy(struct radeon_pll *pll,
+				      uint64_t freq,
+				      uint32_t *dot_clock_p,
+				      uint32_t *fb_div_p,
+				      uint32_t *frac_fb_div_p,
+				      uint32_t *ref_div_p,
+				      uint32_t *post_div_p)
 {
 	uint32_t min_ref_div = pll->min_ref_div;
 	uint32_t max_ref_div = pll->max_ref_div;
@@ -580,95 +612,194 @@
 	*post_div_p = best_post_div;
 }
 
-void radeon_compute_pll_avivo(struct radeon_pll *pll,
-			      uint64_t freq,
-			      uint32_t *dot_clock_p,
-			      uint32_t *fb_div_p,
-			      uint32_t *frac_fb_div_p,
-			      uint32_t *ref_div_p,
-			      uint32_t *post_div_p)
+static bool
+calc_fb_div(struct radeon_pll *pll,
+	    uint32_t freq,
+            uint32_t post_div,
+            uint32_t ref_div,
+            uint32_t *fb_div,
+            uint32_t *fb_div_frac)
 {
-	fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq;
-	fixed20_12 pll_out_max, pll_out_min;
-	fixed20_12 pll_in_max, pll_in_min;
-	fixed20_12 reference_freq;
-	fixed20_12 error, ffreq, a, b;
+	fixed20_12 feedback_divider, a, b;
+	u32 vco_freq;
 
-	pll_out_max.full = rfixed_const(pll->pll_out_max);
-	pll_out_min.full = rfixed_const(pll->pll_out_min);
-	pll_in_max.full = rfixed_const(pll->pll_in_max);
-	pll_in_min.full = rfixed_const(pll->pll_in_min);
-	reference_freq.full = rfixed_const(pll->reference_freq);
-	do_div(freq, 10);
+	vco_freq = freq * post_div;
+	/* feedback_divider = vco_freq * ref_div / pll->reference_freq; */
+	a.full = rfixed_const(pll->reference_freq);
+	feedback_divider.full = rfixed_const(vco_freq);
+	feedback_divider.full = rfixed_div(feedback_divider, a);
+	a.full = rfixed_const(ref_div);
+	feedback_divider.full = rfixed_mul(feedback_divider, a);
+
+	if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+		/* feedback_divider = floor((feedback_divider * 10.0) + 0.5) * 0.1; */
+		a.full = rfixed_const(10);
+		feedback_divider.full = rfixed_mul(feedback_divider, a);
+		feedback_divider.full += rfixed_const_half(0);
+		feedback_divider.full = rfixed_floor(feedback_divider);
+		feedback_divider.full = rfixed_div(feedback_divider, a);
+
+		/* *fb_div = floor(feedback_divider); */
+		a.full = rfixed_floor(feedback_divider);
+		*fb_div = rfixed_trunc(a);
+		/* *fb_div_frac = fmod(feedback_divider, 1.0) * 10.0; */
+		a.full = rfixed_const(10);
+		b.full = rfixed_mul(feedback_divider, a);
+
+		feedback_divider.full = rfixed_floor(feedback_divider);
+		feedback_divider.full = rfixed_mul(feedback_divider, a);
+		feedback_divider.full = b.full - feedback_divider.full;
+		*fb_div_frac = rfixed_trunc(feedback_divider);
+	} else {
+		/* *fb_div = floor(feedback_divider + 0.5); */
+		feedback_divider.full += rfixed_const_half(0);
+		feedback_divider.full = rfixed_floor(feedback_divider);
+
+		*fb_div = rfixed_trunc(feedback_divider);
+		*fb_div_frac = 0;
+	}
+
+	if (((*fb_div) < pll->min_feedback_div) || ((*fb_div) > pll->max_feedback_div))
+		return false;
+	else
+		return true;
+}
+
+static bool
+calc_fb_ref_div(struct radeon_pll *pll,
+		uint32_t freq,
+		uint32_t post_div,
+		uint32_t *fb_div,
+                uint32_t *fb_div_frac,
+                uint32_t *ref_div)
+{
+	fixed20_12 ffreq, max_error, error, pll_out, a;
+	u32 vco;
+
 	ffreq.full = rfixed_const(freq);
-	error.full = rfixed_const(100 * 100);
+	/* max_error = ffreq * 0.0025; */
+	a.full = rfixed_const(400);
+	max_error.full = rfixed_div(ffreq, a);
 
-	/* max p */
-	p.full = rfixed_div(pll_out_max, ffreq);
-	p.full = rfixed_floor(p);
+	for ((*ref_div) = pll->min_ref_div; (*ref_div) < pll->max_ref_div; ++(*ref_div)) {
+		if (calc_fb_div(pll, freq, post_div, (*ref_div), fb_div, fb_div_frac)) {
+			vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac));
+			vco = vco / ((*ref_div) * 10);
 
-	/* min m */
-	m.full = rfixed_div(reference_freq, pll_in_max);
-	m.full = rfixed_ceil(m);
+			if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max))
+				continue;
 
-	while (1) {
-		n.full = rfixed_div(ffreq, reference_freq);
-		n.full = rfixed_mul(n, m);
-		n.full = rfixed_mul(n, p);
+			/* pll_out = vco / post_div; */
+			a.full = rfixed_const(post_div);
+			pll_out.full = rfixed_const(vco);
+			pll_out.full = rfixed_div(pll_out, a);
 
-		f_vco.full = rfixed_div(n, m);
-		f_vco.full = rfixed_mul(f_vco, reference_freq);
+			if (pll_out.full >= ffreq.full) {
+				error.full = pll_out.full - ffreq.full;
+				if (error.full <= max_error.full)
+					return true;
+			}
+		}
+	}
+	return false;
+}
 
-		f_pclk.full = rfixed_div(f_vco, p);
+static void radeon_compute_pll_new(struct radeon_pll *pll,
+				   uint64_t freq,
+				   uint32_t *dot_clock_p,
+				   uint32_t *fb_div_p,
+				   uint32_t *frac_fb_div_p,
+				   uint32_t *ref_div_p,
+				   uint32_t *post_div_p)
+{
+	u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0;
+	u32 best_freq = 0, vco_frequency;
 
-		if (f_pclk.full > ffreq.full)
-			error.full = f_pclk.full - ffreq.full;
-		else
-			error.full = ffreq.full - f_pclk.full;
-		error.full = rfixed_div(error, f_pclk);
-		a.full = rfixed_const(100 * 100);
-		error.full = rfixed_mul(error, a);
+	/* freq = freq / 10; */
+	do_div(freq, 10);
 
-		a.full = rfixed_mul(m, p);
-		a.full = rfixed_div(n, a);
-		best_freq.full = rfixed_mul(reference_freq, a);
+	if (pll->flags & RADEON_PLL_USE_POST_DIV) {
+		post_div = pll->post_div;
+		if ((post_div < pll->min_post_div) || (post_div > pll->max_post_div))
+			goto done;
 
-		if (rfixed_trunc(error) < 25)
-			break;
+		vco_frequency = freq * post_div;
+		if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
+			goto done;
 
-		a.full = rfixed_const(1);
-		m.full = m.full + a.full;
-		a.full = rfixed_div(reference_freq, m);
-		if (a.full >= pll_in_min.full)
-			continue;
+		if (pll->flags & RADEON_PLL_USE_REF_DIV) {
+			ref_div = pll->reference_div;
+			if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
+				goto done;
+			if (!calc_fb_div(pll, freq, post_div, ref_div, &fb_div, &fb_div_frac))
+				goto done;
+		}
+	} else {
+		for (post_div = pll->max_post_div; post_div >= pll->min_post_div; --post_div) {
+			if (pll->flags & RADEON_PLL_LEGACY) {
+				if ((post_div == 5) ||
+				    (post_div == 7) ||
+				    (post_div == 9) ||
+				    (post_div == 10) ||
+				    (post_div == 11))
+					continue;
+			}
 
-		m.full = rfixed_div(reference_freq, pll_in_max);
-		m.full = rfixed_ceil(m);
-		a.full= rfixed_const(1);
-		p.full = p.full - a.full;
-		a.full = rfixed_mul(p, ffreq);
-		if (a.full >= pll_out_min.full)
-			continue;
-		else {
-			DRM_ERROR("Unable to find pll dividers\n");
-			break;
+			if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
+				continue;
+
+			vco_frequency = freq * post_div;
+			if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
+				continue;
+			if (pll->flags & RADEON_PLL_USE_REF_DIV) {
+				ref_div = pll->reference_div;
+				if ((ref_div < pll->min_ref_div) || (ref_div > pll->max_ref_div))
+					goto done;
+				if (calc_fb_div(pll, freq, post_div, ref_div, &fb_div, &fb_div_frac))
+					break;
+			} else {
+				if (calc_fb_ref_div(pll, freq, post_div, &fb_div, &fb_div_frac, &ref_div))
+					break;
+			}
 		}
 	}
 
-	a.full = rfixed_const(10);
-	b.full = rfixed_mul(n, a);
+	best_freq = pll->reference_freq * 10 * fb_div;
+	best_freq += pll->reference_freq * fb_div_frac;
+	best_freq = best_freq / (ref_div * post_div);
 
-	frac_n.full = rfixed_floor(n);
-	frac_n.full = rfixed_mul(frac_n, a);
-	frac_n.full = b.full - frac_n.full;
+done:
+	if (best_freq == 0)
+		DRM_ERROR("Couldn't find valid PLL dividers\n");
 
-	*dot_clock_p = rfixed_trunc(best_freq);
-	*fb_div_p = rfixed_trunc(n);
-	*frac_fb_div_p = rfixed_trunc(frac_n);
-	*ref_div_p = rfixed_trunc(m);
-	*post_div_p = rfixed_trunc(p);
+	*dot_clock_p = best_freq / 10;
+	*fb_div_p = fb_div;
+	*frac_fb_div_p = fb_div_frac;
+	*ref_div_p = ref_div;
+	*post_div_p = post_div;
 
-	DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p);
+	DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p);
+}
+
+void radeon_compute_pll(struct radeon_pll *pll,
+			uint64_t freq,
+			uint32_t *dot_clock_p,
+			uint32_t *fb_div_p,
+			uint32_t *frac_fb_div_p,
+			uint32_t *ref_div_p,
+			uint32_t *post_div_p)
+{
+	switch (pll->algo) {
+	case PLL_ALGO_NEW:
+		radeon_compute_pll_new(pll, freq, dot_clock_p, fb_div_p,
+				       frac_fb_div_p, ref_div_p, post_div_p);
+		break;
+	case PLL_ALGO_LEGACY:
+	default:
+		radeon_compute_pll_legacy(pll, freq, dot_clock_p, fb_div_p,
+					  frac_fb_div_p, ref_div_p, post_div_p);
+		break;
+	}
 }
 
 static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -679,11 +810,8 @@
 	if (fb->fbdev)
 		radeonfb_remove(dev, fb);
 
-	if (radeon_fb->obj) {
-		mutex_lock(&dev->struct_mutex);
-		drm_gem_object_unreference(radeon_fb->obj);
-		mutex_unlock(&dev->struct_mutex);
-	}
+	if (radeon_fb->obj)
+		drm_gem_object_unreference_unlocked(radeon_fb->obj);
 	drm_framebuffer_cleanup(fb);
 	kfree(radeon_fb);
 }
@@ -819,7 +947,7 @@
 
 int radeon_modeset_init(struct radeon_device *rdev)
 {
-	int num_crtc = 2, i;
+	int i;
 	int ret;
 
 	drm_mode_config_init(rdev->ddev);
@@ -842,11 +970,23 @@
 		return ret;
 	}
 
+	/* check combios for a valid hardcoded EDID - Sun servers */
+	if (!rdev->is_atom_bios) {
+		/* check for hardcoded EDID in BIOS */
+		radeon_combios_check_hardcoded_edid(rdev);
+	}
+
 	if (rdev->flags & RADEON_SINGLE_CRTC)
-		num_crtc = 1;
+		rdev->num_crtc = 1;
+	else {
+		if (ASIC_IS_DCE4(rdev))
+			rdev->num_crtc = 6;
+		else
+			rdev->num_crtc = 2;
+	}
 
 	/* allocate crtcs */
-	for (i = 0; i < num_crtc; i++) {
+	for (i = 0; i < rdev->num_crtc; i++) {
 		radeon_crtc_init(rdev->ddev, i);
 	}
 
@@ -863,6 +1003,8 @@
 
 void radeon_modeset_fini(struct radeon_device *rdev)
 {
+	kfree(rdev->mode_info.bios_hardcoded_edid);
+
 	if (rdev->mode_info.mode_config_initialized) {
 		radeon_hpd_fini(rdev);
 		drm_mode_config_cleanup(rdev->ddev);
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 8ba3de7..6eec0ec 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -40,9 +40,11 @@
 
 /*
  * KMS wrapper.
+ * - 2.0.0 - initial interface
+ * - 2.1.0 - add square tiling interface
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	0
+#define KMS_DRIVER_MINOR	1
 #define KMS_DRIVER_PATCHLEVEL	0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -86,7 +88,8 @@
 int radeon_testing = 0;
 int radeon_connector_table = 0;
 int radeon_tv = 1;
-int radeon_new_pll = 1;
+int radeon_new_pll = -1;
+int radeon_dynpm = -1;
 int radeon_audio = 1;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
@@ -122,9 +125,12 @@
 MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
 module_param_named(tv, radeon_tv, int, 0444);
 
-MODULE_PARM_DESC(new_pll, "Select new PLL code for AVIVO chips");
+MODULE_PARM_DESC(new_pll, "Select new PLL code");
 module_param_named(new_pll, radeon_new_pll, int, 0444);
 
+MODULE_PARM_DESC(dynpm, "Disable/Enable dynamic power management (1 = enable)");
+module_param_named(dynpm, radeon_dynpm, int, 0444);
+
 MODULE_PARM_DESC(audio, "Audio enable (0 = disable)");
 module_param_named(audio, radeon_audio, int, 0444);
 
@@ -339,6 +345,7 @@
 		driver = &kms_driver;
 		driver->driver_features |= DRIVER_MODESET;
 		driver->num_ioctls = radeon_max_kms_ioctl;
+		radeon_register_atpx_handler();
 	}
 	/* if the vga console setting is enabled still
 	 * let modprobe override it */
@@ -348,6 +355,7 @@
 static void __exit radeon_exit(void)
 {
 	drm_exit(driver);
+	radeon_unregister_atpx_handler();
 }
 
 module_init(radeon_init);
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index c57ad60..ec55f2b 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -268,6 +268,8 @@
 
 	u32 scratch_ages[5];
 
+	int have_z_offset;
+
 	/* starting from here on, data is preserved accross an open */
 	uint32_t flags;		/* see radeon_chip_flags */
 	resource_size_t fb_aper_offset;
@@ -295,6 +297,9 @@
 	int r700_sc_prim_fifo_size;
 	int r700_sc_hiz_tile_fifo_size;
 	int r700_sc_earlyz_tile_fifo_fize;
+	int r600_group_size;
+	int r600_npipes;
+	int r600_nbanks;
 
 	struct mutex cs_mutex;
 	u32 cs_id_scnt;
@@ -310,9 +315,11 @@
 	u32 age;
 } drm_radeon_buf_priv_t;
 
+struct drm_buffer;
+
 typedef struct drm_radeon_kcmd_buffer {
 	int bufsz;
-	char *buf;
+	struct drm_buffer *buffer;
 	int nbox;
 	struct drm_clip_rect __user *boxes;
 } drm_radeon_kcmd_buffer_t;
@@ -455,6 +462,15 @@
 			   int sx, int sy, int dx, int dy,
 			   int w, int h, int src_pitch, int dst_pitch, int cpp);
 
+/* atpx handler */
+#if defined(CONFIG_VGA_SWITCHEROO)
+void radeon_register_atpx_handler(void);
+void radeon_unregister_atpx_handler(void);
+#else
+static inline void radeon_register_atpx_handler(void) {}
+static inline void radeon_unregister_atpx_handler(void) {}
+#endif
+
 /* Flags for stats.boxes
  */
 #define RADEON_BOX_DMA_IDLE      0x1
@@ -2122,4 +2138,32 @@
 	write &= mask;						\
 } while (0)
 
+/**
+ * Copy given number of dwords from drm buffer to the ring buffer.
+ */
+#define OUT_RING_DRM_BUFFER(buf, sz) do {				\
+	int _size = (sz) * 4;						\
+	struct drm_buffer *_buf = (buf);				\
+	int _part_size;							\
+	while (_size > 0) {						\
+		_part_size = _size;					\
+									\
+		if (write + _part_size/4 > mask)			\
+			_part_size = ((mask + 1) - write)*4;		\
+									\
+		if (drm_buffer_index(_buf) + _part_size > PAGE_SIZE)	\
+			_part_size = PAGE_SIZE - drm_buffer_index(_buf);\
+									\
+									\
+									\
+		memcpy(ring + write, &_buf->data[drm_buffer_page(_buf)]	\
+			[drm_buffer_index(_buf)], _part_size);		\
+									\
+		_size -= _part_size;					\
+		write = (write + _part_size/4) & mask;			\
+		drm_buffer_advance(_buf, _part_size);			\
+	}								\
+} while (0)
+
+
 #endif				/* __RADEON_DRV_H__ */
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 3c91724..bc926ea 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -53,7 +53,7 @@
 	/* DVO requires 2x ppll clocks depending on tmds chip */
 	if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT)
 		return index_mask;
-	
+
 	count = -1;
 	list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) {
 		struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder);
@@ -228,6 +228,32 @@
 	return NULL;
 }
 
+static struct radeon_connector_atom_dig *
+radeon_get_atom_connector_priv_from_encoder(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
+	struct radeon_connector_atom_dig *dig_connector;
+
+	if (!rdev->is_atom_bios)
+		return NULL;
+
+	connector = radeon_get_connector_for_encoder(encoder);
+	if (!connector)
+		return NULL;
+
+	radeon_connector = to_radeon_connector(connector);
+
+	if (!radeon_connector->con_priv)
+		return NULL;
+
+	dig_connector = radeon_connector->con_priv;
+
+	return dig_connector;
+}
+
 static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
 				   struct drm_display_mode *mode,
 				   struct drm_display_mode *adjusted_mode)
@@ -236,6 +262,9 @@
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 
+	/* adjust pm to upcoming mode change */
+	radeon_pm_compute_clocks(rdev);
+
 	/* set the active encoder to connector routing */
 	radeon_encoder_set_active_device(encoder);
 	drm_mode_set_crtcinfo(adjusted_mode, 0);
@@ -458,34 +487,20 @@
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	struct radeon_connector_atom_dig *dig_connector =
+		radeon_get_atom_connector_priv_from_encoder(encoder);
 	union lvds_encoder_control args;
 	int index = 0;
 	int hdmi_detected = 0;
 	uint8_t frev, crev;
-	struct radeon_encoder_atom_dig *dig;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector;
-	struct radeon_connector_atom_dig *dig_connector;
 
-	connector = radeon_get_connector_for_encoder(encoder);
-	if (!connector)
+	if (!dig || !dig_connector)
 		return;
 
-	radeon_connector = to_radeon_connector(connector);
-
-	if (!radeon_encoder->enc_priv)
-		return;
-
-	dig = radeon_encoder->enc_priv;
-
-	if (!radeon_connector->con_priv)
-		return;
-
-	if (drm_detect_hdmi_monitor(radeon_connector->edid))
+	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
 		hdmi_detected = 1;
 
-	dig_connector = radeon_connector->con_priv;
-
 	memset(&args, 0, sizeof(args));
 
 	switch (radeon_encoder->encoder_id) {
@@ -586,7 +601,7 @@
 {
 	struct drm_connector *connector;
 	struct radeon_connector *radeon_connector;
-	struct radeon_connector_atom_dig *radeon_dig_connector;
+	struct radeon_connector_atom_dig *dig_connector;
 
 	connector = radeon_get_connector_for_encoder(encoder);
 	if (!connector)
@@ -617,9 +632,9 @@
 		break;
 	case DRM_MODE_CONNECTOR_DisplayPort:
 	case DRM_MODE_CONNECTOR_eDP:
-		radeon_dig_connector = radeon_connector->con_priv;
-		if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
-		    (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
+		dig_connector = radeon_connector->con_priv;
+		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
 			return ATOM_ENCODER_MODE_DP;
 		else if (drm_detect_hdmi_monitor(radeon_connector->edid))
 			return ATOM_ENCODER_MODE_HDMI;
@@ -656,6 +671,18 @@
  * - 2 DIG encoder blocks.
  * DIG1/2 can drive UNIPHY0/1/2 link A or link B
  *
+ * DCE 4.0
+ * - 3 DIG transmitter blocks UNPHY0/1/2 (links A and B).
+ * Supports up to 6 digital outputs
+ * - 6 DIG encoder blocks.
+ * - DIG to PHY mapping is hardcoded
+ * DIG1 drives UNIPHY0 link A, A+B
+ * DIG2 drives UNIPHY0 link B
+ * DIG3 drives UNIPHY1 link A, A+B
+ * DIG4 drives UNIPHY1 link B
+ * DIG5 drives UNIPHY2 link A, A+B
+ * DIG6 drives UNIPHY2 link B
+ *
  * Routing
  * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links)
  * Examples:
@@ -664,88 +691,78 @@
  * crtc0 -> dig1 -> UNIPHY2 link  A   -> LVDS
  * crtc1 -> dig2 -> UNIPHY1 link  B+A -> TMDS/HDMI
  */
-static void
+
+union dig_encoder_control {
+	DIG_ENCODER_CONTROL_PS_ALLOCATION v1;
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
+	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
+};
+
+void
 atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-	DIG_ENCODER_CONTROL_PS_ALLOCATION args;
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	struct radeon_connector_atom_dig *dig_connector =
+		radeon_get_atom_connector_priv_from_encoder(encoder);
+	union dig_encoder_control args;
 	int index = 0, num = 0;
 	uint8_t frev, crev;
-	struct radeon_encoder_atom_dig *dig;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector;
-	struct radeon_connector_atom_dig *dig_connector;
 
-	connector = radeon_get_connector_for_encoder(encoder);
-	if (!connector)
+	if (!dig || !dig_connector)
 		return;
 
-	radeon_connector = to_radeon_connector(connector);
-
-	if (!radeon_connector->con_priv)
-		return;
-
-	dig_connector = radeon_connector->con_priv;
-
-	if (!radeon_encoder->enc_priv)
-		return;
-
-	dig = radeon_encoder->enc_priv;
-
 	memset(&args, 0, sizeof(args));
 
-	if (dig->dig_encoder)
-		index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
-	else
-		index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
+	if (ASIC_IS_DCE4(rdev))
+		index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl);
+	else {
+		if (dig->dig_encoder)
+			index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl);
+		else
+			index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
+	}
 	num = dig->dig_encoder + 1;
 
 	atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev);
 
-	args.ucAction = action;
-	args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+	args.v1.ucAction = action;
+	args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
+	args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder);
 
-	if (ASIC_IS_DCE32(rdev)) {
-		switch (radeon_encoder->encoder_id) {
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-			args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
-			break;
-		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-			args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
-			break;
-		}
+	if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
+		if (dig_connector->dp_clock == 270000)
+			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+		args.v1.ucLaneNum = dig_connector->dp_lane_count;
+	} else if (radeon_encoder->pixel_clock > 165000)
+		args.v1.ucLaneNum = 8;
+	else
+		args.v1.ucLaneNum = 4;
+
+	if (ASIC_IS_DCE4(rdev)) {
+		args.v3.acConfig.ucDigSel = dig->dig_encoder;
+		args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR;
 	} else {
 		switch (radeon_encoder->encoder_id) {
 		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-			args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1;
+			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1;
 			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
 		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-			args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2;
+			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+			args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3;
 			break;
 		}
+		if (dig_connector->linkb)
+			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
+		else
+			args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
 	}
 
-	args.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
-	if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
-		if (dig_connector->dp_clock == 270000)
-			args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
-		args.ucLaneNum = dig_connector->dp_lane_count;
-	} else if (radeon_encoder->pixel_clock > 165000)
-		args.ucLaneNum = 8;
-	else
-		args.ucLaneNum = 4;
-
-	if (dig_connector->linkb)
-		args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB;
-	else
-		args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
-
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 
 }
@@ -753,6 +770,7 @@
 union dig_transmitter_control {
 	DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1;
 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
 };
 
 void
@@ -761,37 +779,29 @@
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+	struct radeon_connector_atom_dig *dig_connector =
+		radeon_get_atom_connector_priv_from_encoder(encoder);
+	struct drm_connector *connector;
+	struct radeon_connector *radeon_connector;
 	union dig_transmitter_control args;
 	int index = 0, num = 0;
 	uint8_t frev, crev;
-	struct radeon_encoder_atom_dig *dig;
-	struct drm_connector *connector;
-	struct radeon_connector *radeon_connector;
-	struct radeon_connector_atom_dig *dig_connector;
 	bool is_dp = false;
+	int pll_id = 0;
+
+	if (!dig || !dig_connector)
+		return;
 
 	connector = radeon_get_connector_for_encoder(encoder);
-	if (!connector)
-		return;
-
 	radeon_connector = to_radeon_connector(connector);
 
-	if (!radeon_encoder->enc_priv)
-		return;
-
-	dig = radeon_encoder->enc_priv;
-
-	if (!radeon_connector->con_priv)
-		return;
-
-	dig_connector = radeon_connector->con_priv;
-
 	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
 		is_dp = true;
 
 	memset(&args, 0, sizeof(args));
 
-	if (ASIC_IS_DCE32(rdev))
+	if (ASIC_IS_DCE32(rdev) || ASIC_IS_DCE4(rdev))
 		index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl);
 	else {
 		switch (radeon_encoder->encoder_id) {
@@ -821,7 +831,54 @@
 		else
 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
 	}
-	if (ASIC_IS_DCE32(rdev)) {
+	if (ASIC_IS_DCE4(rdev)) {
+		if (is_dp)
+			args.v3.ucLaneNum = dig_connector->dp_lane_count;
+		else if (radeon_encoder->pixel_clock > 165000)
+			args.v3.ucLaneNum = 8;
+		else
+			args.v3.ucLaneNum = 4;
+
+		if (dig_connector->linkb) {
+			args.v3.acConfig.ucLinkSel = 1;
+			args.v3.acConfig.ucEncoderSel = 1;
+		}
+
+		/* Select the PLL for the PHY
+		 * DP PHY should be clocked from external src if there is
+		 * one.
+		 */
+		if (encoder->crtc) {
+			struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
+			pll_id = radeon_crtc->pll_id;
+		}
+		if (is_dp && rdev->clock.dp_extclk)
+			args.v3.acConfig.ucRefClkSource = 2; /* external src */
+		else
+			args.v3.acConfig.ucRefClkSource = pll_id;
+
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			args.v3.acConfig.ucTransmitterSel = 0;
+			num = 0;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+			args.v3.acConfig.ucTransmitterSel = 1;
+			num = 1;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+			args.v3.acConfig.ucTransmitterSel = 2;
+			num = 2;
+			break;
+		}
+
+		if (is_dp)
+			args.v3.acConfig.fCoherentMode = 1; /* DP requires coherent */
+		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+			if (dig->coherent_mode)
+				args.v3.acConfig.fCoherentMode = 1;
+		}
+	} else if (ASIC_IS_DCE32(rdev)) {
 		if (dig->dig_encoder == 1)
 			args.v2.acConfig.ucEncoderSel = 1;
 		if (dig_connector->linkb)
@@ -849,7 +906,6 @@
 				args.v2.acConfig.fCoherentMode = 1;
 		}
 	} else {
-
 		args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL;
 
 		if (dig->dig_encoder)
@@ -1024,9 +1080,12 @@
 		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 	}
 	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+
+	/* adjust pm to dpms change */
+	radeon_pm_compute_clocks(rdev);
 }
 
-union crtc_sourc_param {
+union crtc_source_param {
 	SELECT_CRTC_SOURCE_PS_ALLOCATION v1;
 	SELECT_CRTC_SOURCE_PARAMETERS_V2 v2;
 };
@@ -1038,7 +1097,7 @@
 	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-	union crtc_sourc_param args;
+	union crtc_source_param args;
 	int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
 	uint8_t frev, crev;
 	struct radeon_encoder_atom_dig *dig;
@@ -1107,10 +1166,26 @@
 			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
 				dig = radeon_encoder->enc_priv;
-				if (dig->dig_encoder)
-					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
-				else
+				switch (dig->dig_encoder) {
+				case 0:
 					args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID;
+					break;
+				case 1:
+					args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
+					break;
+				case 2:
+					args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID;
+					break;
+				case 3:
+					args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID;
+					break;
+				case 4:
+					args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID;
+					break;
+				case 5:
+					args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID;
+					break;
+				}
 				break;
 			case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
 				args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID;
@@ -1167,6 +1242,7 @@
 	}
 
 	/* set scaler clears this on some chips */
+	/* XXX check DCE4 */
 	if (!(radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))) {
 		if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE))
 			WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
@@ -1183,6 +1259,33 @@
 	struct drm_encoder *test_encoder;
 	struct radeon_encoder_atom_dig *dig;
 	uint32_t dig_enc_in_use = 0;
+
+	if (ASIC_IS_DCE4(rdev)) {
+		struct radeon_connector_atom_dig *dig_connector =
+			radeon_get_atom_connector_priv_from_encoder(encoder);
+
+		switch (radeon_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			if (dig_connector->linkb)
+				return 1;
+			else
+				return 0;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+			if (dig_connector->linkb)
+				return 3;
+			else
+				return 2;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+			if (dig_connector->linkb)
+				return 5;
+			else
+				return 4;
+			break;
+		}
+	}
+
 	/* on DCE32 and encoder can driver any block so just crtc id */
 	if (ASIC_IS_DCE32(rdev)) {
 		return radeon_crtc->crtc_id;
@@ -1254,15 +1357,26 @@
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
 	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
 	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-		/* disable the encoder and transmitter */
-		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-		atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
+		if (ASIC_IS_DCE4(rdev)) {
+			/* disable the transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+			/* setup and enable the encoder */
+			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP);
 
-		/* setup and enable the encoder and transmitter */
-		atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
-		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
-		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
-		atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+			/* init and enable the transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+		} else {
+			/* disable the encoder and transmitter */
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+			atombios_dig_encoder_setup(encoder, ATOM_DISABLE);
+
+			/* setup and enable the encoder and transmitter */
+			atombios_dig_encoder_setup(encoder, ATOM_ENABLE);
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
+			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+		}
 		break;
 	case ENCODER_OBJECT_ID_INTERNAL_DDI:
 		atombios_ddia_setup(encoder, ATOM_ENABLE);
@@ -1282,7 +1396,9 @@
 	}
 	atombios_apply_encoder_quirks(encoder, adjusted_mode);
 
-	r600_hdmi_setmode(encoder, adjusted_mode);
+	/* XXX */
+	if (!ASIC_IS_DCE4(rdev))
+		r600_hdmi_setmode(encoder, adjusted_mode);
 }
 
 static bool
@@ -1480,10 +1596,18 @@
 		return;
 
 	encoder = &radeon_encoder->base;
-	if (rdev->flags & RADEON_SINGLE_CRTC)
+	switch (rdev->num_crtc) {
+	case 1:
 		encoder->possible_crtcs = 0x1;
-	else
+		break;
+	case 2:
+	default:
 		encoder->possible_crtcs = 0x3;
+		break;
+	case 6:
+		encoder->possible_crtcs = 0x3f;
+		break;
+	}
 
 	radeon_encoder->enc_priv = NULL;
 
diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h
index 797972e..93c7d5d4 100644
--- a/drivers/gpu/drm/radeon/radeon_family.h
+++ b/drivers/gpu/drm/radeon/radeon_family.h
@@ -75,6 +75,11 @@
 	CHIP_RV730,
 	CHIP_RV710,
 	CHIP_RV740,
+	CHIP_CEDAR,
+	CHIP_REDWOOD,
+	CHIP_JUNIPER,
+	CHIP_CYPRESS,
+	CHIP_HEMLOCK,
 	CHIP_LAST,
 };
 
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index d71e346..8fccbf2 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -39,6 +39,8 @@
 
 #include "drm_fb_helper.h"
 
+#include <linux/vga_switcheroo.h>
+
 struct radeon_fb_device {
 	struct drm_fb_helper helper;
 	struct radeon_framebuffer	*rfb;
@@ -148,7 +150,6 @@
 	unsigned long tmp;
 	bool fb_tiled = false; /* useful for testing */
 	u32 tiling_flags = 0;
-	int crtc_count;
 
 	mode_cmd.width = surface_width;
 	mode_cmd.height = surface_height;
@@ -239,11 +240,7 @@
 	rfbdev = info->par;
 	rfbdev->helper.funcs = &radeon_fb_helper_funcs;
 	rfbdev->helper.dev = dev;
-	if (rdev->flags & RADEON_SINGLE_CRTC)
-		crtc_count = 1;
-	else
-		crtc_count = 2;
-	ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, crtc_count,
+	ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, rdev->num_crtc,
 					    RADEONFB_CONN_LIMIT);
 	if (ret)
 		goto out_unref;
@@ -257,7 +254,7 @@
 	info->flags = FBINFO_DEFAULT;
 	info->fbops = &radeonfb_ops;
 
-	tmp = fb_gpuaddr - rdev->mc.vram_location;
+	tmp = fb_gpuaddr - rdev->mc.vram_start;
 	info->fix.smem_start = rdev->mc.aper_base + tmp;
 	info->fix.smem_len = size;
 	info->screen_base = fbptr;
@@ -291,6 +288,7 @@
 	rfbdev->rdev = rdev;
 
 	mutex_unlock(&rdev->ddev->struct_mutex);
+	vga_switcheroo_client_fb_set(rdev->ddev->pdev, info);
 	return 0;
 
 out_unref:
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
index e73d56e..1770d3c 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -139,6 +139,7 @@
 	unsigned t;
 	unsigned p;
 	int i, j;
+	u64 page_base;
 
 	if (!rdev->gart.ready) {
 		WARN(1, "trying to unbind memory to unitialized GART !\n");
@@ -151,9 +152,11 @@
 			pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
 				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 			rdev->gart.pages[p] = NULL;
-			rdev->gart.pages_addr[p] = 0;
+			rdev->gart.pages_addr[p] = rdev->dummy_page.addr;
+			page_base = rdev->gart.pages_addr[p];
 			for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
-				radeon_gart_set_page(rdev, t, 0);
+				radeon_gart_set_page(rdev, t, page_base);
+				page_base += RADEON_GPU_PAGE_SIZE;
 			}
 		}
 	}
@@ -199,8 +202,26 @@
 	return 0;
 }
 
+void radeon_gart_restore(struct radeon_device *rdev)
+{
+	int i, j, t;
+	u64 page_base;
+
+	for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) {
+		page_base = rdev->gart.pages_addr[i];
+		for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
+			radeon_gart_set_page(rdev, t, page_base);
+			page_base += RADEON_GPU_PAGE_SIZE;
+		}
+	}
+	mb();
+	radeon_gart_tlb_flush(rdev);
+}
+
 int radeon_gart_init(struct radeon_device *rdev)
 {
+	int r, i;
+
 	if (rdev->gart.pages) {
 		return 0;
 	}
@@ -209,6 +230,9 @@
 		DRM_ERROR("Page size is smaller than GPU page size!\n");
 		return -EINVAL;
 	}
+	r = radeon_dummy_page_init(rdev);
+	if (r)
+		return r;
 	/* Compute table size */
 	rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE;
 	rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE;
@@ -227,6 +251,10 @@
 		radeon_gart_fini(rdev);
 		return -ENOMEM;
 	}
+	/* set GART entry to point to the dummy page by default */
+	for (i = 0; i < rdev->gart.num_cpu_pages; i++) {
+		rdev->gart.pages_addr[i] = rdev->dummy_page.addr;
+	}
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index db8e9a3..ef92d14 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -69,9 +69,7 @@
 		if (r != -ERESTARTSYS)
 			DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
 				  size, initial_domain, alignment, r);
-		mutex_lock(&rdev->ddev->struct_mutex);
-		drm_gem_object_unreference(gobj);
-		mutex_unlock(&rdev->ddev->struct_mutex);
+		drm_gem_object_unreference_unlocked(gobj);
 		return r;
 	}
 	gobj->driver_private = robj;
@@ -202,14 +200,10 @@
 	}
 	r = drm_gem_handle_create(filp, gobj, &handle);
 	if (r) {
-		mutex_lock(&dev->struct_mutex);
-		drm_gem_object_unreference(gobj);
-		mutex_unlock(&dev->struct_mutex);
+		drm_gem_object_unreference_unlocked(gobj);
 		return r;
 	}
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_handle_unreference(gobj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_handle_unreference_unlocked(gobj);
 	args->handle = handle;
 	return 0;
 }
@@ -236,9 +230,7 @@
 
 	r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
 
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gobj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gobj);
 	return r;
 }
 
@@ -255,9 +247,7 @@
 	}
 	robj = gobj->driver_private;
 	args->addr_ptr = radeon_bo_mmap_offset(robj);
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gobj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gobj);
 	return 0;
 }
 
@@ -288,9 +278,7 @@
 	default:
 		break;
 	}
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gobj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gobj);
 	return r;
 }
 
@@ -311,9 +299,7 @@
 	/* callback hw specific functions if any */
 	if (robj->rdev->asic->ioctl_wait_idle)
 		robj->rdev->asic->ioctl_wait_idle(robj->rdev, robj);
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gobj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gobj);
 	return r;
 }
 
@@ -331,9 +317,7 @@
 		return -EINVAL;
 	robj = gobj->driver_private;
 	r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch);
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gobj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gobj);
 	return r;
 }
 
@@ -356,8 +340,6 @@
 	radeon_bo_get_tiling_flags(rbo, &args->tiling_flags, &args->pitch);
 	radeon_bo_unreserve(rbo);
 out:
-	mutex_lock(&dev->struct_mutex);
-	drm_gem_object_unreference(gobj);
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(gobj);
 	return r;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index da3da1e..4ae50c1 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -26,6 +26,7 @@
 #include "drmP.h"
 #include "radeon_drm.h"
 #include "radeon.h"
+#include "atom.h"
 
 /**
  * radeon_ddc_probe
@@ -59,7 +60,7 @@
 }
 
 
-void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
+static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
 {
 	struct radeon_device *rdev = i2c->dev->dev_private;
 	struct radeon_i2c_bus_rec *rec = &i2c->rec;
@@ -71,13 +72,25 @@
 	 */
 	if (rec->hw_capable) {
 		if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
-			if (rec->a_clk_reg == RADEON_GPIO_MONID) {
+			u32 reg;
+
+			if (rdev->family >= CHIP_RV350)
+				reg = RADEON_GPIO_MONID;
+			else if ((rdev->family == CHIP_R300) ||
+				 (rdev->family == CHIP_R350))
+				reg = RADEON_GPIO_DVI_DDC;
+			else
+				reg = RADEON_GPIO_CRT2_DDC;
+
+			mutex_lock(&rdev->dc_hw_i2c_mutex);
+			if (rec->a_clk_reg == reg) {
 				WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
 							       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
 			} else {
 				WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
 							       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
 			}
+			mutex_unlock(&rdev->dc_hw_i2c_mutex);
 		}
 	}
 
@@ -168,6 +181,692 @@
 	WREG32(rec->en_data_reg, val);
 }
 
+static u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
+{
+	struct radeon_pll *spll = &rdev->clock.spll;
+	u32 sclk = radeon_get_engine_clock(rdev);
+	u32 prescale = 0;
+	u32 n, m;
+	u8 loop;
+	int i2c_clock;
+
+	switch (rdev->family) {
+	case CHIP_R100:
+	case CHIP_RV100:
+	case CHIP_RS100:
+	case CHIP_RV200:
+	case CHIP_RS200:
+	case CHIP_R200:
+	case CHIP_RV250:
+	case CHIP_RS300:
+	case CHIP_RV280:
+	case CHIP_R300:
+	case CHIP_R350:
+	case CHIP_RV350:
+		n = (spll->reference_freq) / (4 * 6);
+		for (loop = 1; loop < 255; loop++) {
+			if ((loop * (loop - 1)) > n)
+				break;
+		}
+		m = loop - 1;
+		prescale = m | (loop << 8);
+		break;
+	case CHIP_RV380:
+	case CHIP_RS400:
+	case CHIP_RS480:
+	case CHIP_R420:
+	case CHIP_R423:
+	case CHIP_RV410:
+		sclk = radeon_get_engine_clock(rdev);
+		prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
+		break;
+	case CHIP_RS600:
+	case CHIP_RS690:
+	case CHIP_RS740:
+		/* todo */
+		break;
+	case CHIP_RV515:
+	case CHIP_R520:
+	case CHIP_RV530:
+	case CHIP_RV560:
+	case CHIP_RV570:
+	case CHIP_R580:
+		i2c_clock = 50;
+		sclk = radeon_get_engine_clock(rdev);
+		if (rdev->family == CHIP_R520)
+			prescale = (127 << 8) + ((sclk * 10) / (4 * 127 * i2c_clock));
+		else
+			prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
+		break;
+	case CHIP_R600:
+	case CHIP_RV610:
+	case CHIP_RV630:
+	case CHIP_RV670:
+		/* todo */
+		break;
+	case CHIP_RV620:
+	case CHIP_RV635:
+	case CHIP_RS780:
+	case CHIP_RS880:
+	case CHIP_RV770:
+	case CHIP_RV730:
+	case CHIP_RV710:
+	case CHIP_RV740:
+		/* todo */
+		break;
+	case CHIP_CEDAR:
+	case CHIP_REDWOOD:
+	case CHIP_JUNIPER:
+	case CHIP_CYPRESS:
+	case CHIP_HEMLOCK:
+		/* todo */
+		break;
+	default:
+		DRM_ERROR("i2c: unhandled radeon chip\n");
+		break;
+	}
+	return prescale;
+}
+
+
+/* hw i2c engine for r1xx-4xx hardware
+ * hw can buffer up to 15 bytes
+ */
+static int r100_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
+			    struct i2c_msg *msgs, int num)
+{
+	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+	struct radeon_device *rdev = i2c->dev->dev_private;
+	struct radeon_i2c_bus_rec *rec = &i2c->rec;
+	struct i2c_msg *p;
+	int i, j, k, ret = num;
+	u32 prescale;
+	u32 i2c_cntl_0, i2c_cntl_1, i2c_data;
+	u32 tmp, reg;
+
+	mutex_lock(&rdev->dc_hw_i2c_mutex);
+	/* take the pm lock since we need a constant sclk */
+	mutex_lock(&rdev->pm.mutex);
+
+	prescale = radeon_get_i2c_prescale(rdev);
+
+	reg = ((prescale << RADEON_I2C_PRESCALE_SHIFT) |
+	       RADEON_I2C_START |
+	       RADEON_I2C_STOP |
+	       RADEON_I2C_GO);
+
+	if (rdev->is_atom_bios) {
+		tmp = RREG32(RADEON_BIOS_6_SCRATCH);
+		WREG32(RADEON_BIOS_6_SCRATCH, tmp | ATOM_S6_HW_I2C_BUSY_STATE);
+	}
+
+	if (rec->mm_i2c) {
+		i2c_cntl_0 = RADEON_I2C_CNTL_0;
+		i2c_cntl_1 = RADEON_I2C_CNTL_1;
+		i2c_data = RADEON_I2C_DATA;
+	} else {
+		i2c_cntl_0 = RADEON_DVI_I2C_CNTL_0;
+		i2c_cntl_1 = RADEON_DVI_I2C_CNTL_1;
+		i2c_data = RADEON_DVI_I2C_DATA;
+
+		switch (rdev->family) {
+		case CHIP_R100:
+		case CHIP_RV100:
+		case CHIP_RS100:
+		case CHIP_RV200:
+		case CHIP_RS200:
+		case CHIP_RS300:
+			switch (rec->mask_clk_reg) {
+			case RADEON_GPIO_DVI_DDC:
+				/* no gpio select bit */
+				break;
+			default:
+				DRM_ERROR("gpio not supported with hw i2c\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			break;
+		case CHIP_R200:
+			/* only bit 4 on r200 */
+			switch (rec->mask_clk_reg) {
+			case RADEON_GPIO_DVI_DDC:
+				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
+				break;
+			case RADEON_GPIO_MONID:
+				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
+				break;
+			default:
+				DRM_ERROR("gpio not supported with hw i2c\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			break;
+		case CHIP_RV250:
+		case CHIP_RV280:
+			/* bits 3 and 4 */
+			switch (rec->mask_clk_reg) {
+			case RADEON_GPIO_DVI_DDC:
+				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
+				break;
+			case RADEON_GPIO_VGA_DDC:
+				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC2);
+				break;
+			case RADEON_GPIO_CRT2_DDC:
+				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
+				break;
+			default:
+				DRM_ERROR("gpio not supported with hw i2c\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			break;
+		case CHIP_R300:
+		case CHIP_R350:
+			/* only bit 4 on r300/r350 */
+			switch (rec->mask_clk_reg) {
+			case RADEON_GPIO_VGA_DDC:
+				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
+				break;
+			case RADEON_GPIO_DVI_DDC:
+				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
+				break;
+			default:
+				DRM_ERROR("gpio not supported with hw i2c\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			break;
+		case CHIP_RV350:
+		case CHIP_RV380:
+		case CHIP_R420:
+		case CHIP_R423:
+		case CHIP_RV410:
+		case CHIP_RS400:
+		case CHIP_RS480:
+			/* bits 3 and 4 */
+			switch (rec->mask_clk_reg) {
+			case RADEON_GPIO_VGA_DDC:
+				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
+				break;
+			case RADEON_GPIO_DVI_DDC:
+				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC2);
+				break;
+			case RADEON_GPIO_MONID:
+				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
+				break;
+			default:
+				DRM_ERROR("gpio not supported with hw i2c\n");
+				ret = -EINVAL;
+				goto done;
+			}
+			break;
+		default:
+			DRM_ERROR("unsupported asic\n");
+			ret = -EINVAL;
+			goto done;
+			break;
+		}
+	}
+
+	/* check for bus probe */
+	p = &msgs[0];
+	if ((num == 1) && (p->len == 0)) {
+		WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
+				    RADEON_I2C_NACK |
+				    RADEON_I2C_HALT |
+				    RADEON_I2C_SOFT_RST));
+		WREG32(i2c_data, (p->addr << 1) & 0xff);
+		WREG32(i2c_data, 0);
+		WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) |
+				    (1 << RADEON_I2C_ADDR_COUNT_SHIFT) |
+				    RADEON_I2C_EN |
+				    (48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
+		WREG32(i2c_cntl_0, reg);
+		for (k = 0; k < 32; k++) {
+			udelay(10);
+			tmp = RREG32(i2c_cntl_0);
+			if (tmp & RADEON_I2C_GO)
+				continue;
+			tmp = RREG32(i2c_cntl_0);
+			if (tmp & RADEON_I2C_DONE)
+				break;
+			else {
+				DRM_DEBUG("i2c write error 0x%08x\n", tmp);
+				WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
+				ret = -EIO;
+				goto done;
+			}
+		}
+		goto done;
+	}
+
+	for (i = 0; i < num; i++) {
+		p = &msgs[i];
+		for (j = 0; j < p->len; j++) {
+			if (p->flags & I2C_M_RD) {
+				WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
+						    RADEON_I2C_NACK |
+						    RADEON_I2C_HALT |
+						    RADEON_I2C_SOFT_RST));
+				WREG32(i2c_data, ((p->addr << 1) & 0xff) | 0x1);
+				WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) |
+						    (1 << RADEON_I2C_ADDR_COUNT_SHIFT) |
+						    RADEON_I2C_EN |
+						    (48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
+				WREG32(i2c_cntl_0, reg | RADEON_I2C_RECEIVE);
+				for (k = 0; k < 32; k++) {
+					udelay(10);
+					tmp = RREG32(i2c_cntl_0);
+					if (tmp & RADEON_I2C_GO)
+						continue;
+					tmp = RREG32(i2c_cntl_0);
+					if (tmp & RADEON_I2C_DONE)
+						break;
+					else {
+						DRM_DEBUG("i2c read error 0x%08x\n", tmp);
+						WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
+						ret = -EIO;
+						goto done;
+					}
+				}
+				p->buf[j] = RREG32(i2c_data) & 0xff;
+			} else {
+				WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
+						    RADEON_I2C_NACK |
+						    RADEON_I2C_HALT |
+						    RADEON_I2C_SOFT_RST));
+				WREG32(i2c_data, (p->addr << 1) & 0xff);
+				WREG32(i2c_data, p->buf[j]);
+				WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) |
+						    (1 << RADEON_I2C_ADDR_COUNT_SHIFT) |
+						    RADEON_I2C_EN |
+						    (48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
+				WREG32(i2c_cntl_0, reg);
+				for (k = 0; k < 32; k++) {
+					udelay(10);
+					tmp = RREG32(i2c_cntl_0);
+					if (tmp & RADEON_I2C_GO)
+						continue;
+					tmp = RREG32(i2c_cntl_0);
+					if (tmp & RADEON_I2C_DONE)
+						break;
+					else {
+						DRM_DEBUG("i2c write error 0x%08x\n", tmp);
+						WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
+						ret = -EIO;
+						goto done;
+					}
+				}
+			}
+		}
+	}
+
+done:
+	WREG32(i2c_cntl_0, 0);
+	WREG32(i2c_cntl_1, 0);
+	WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
+			    RADEON_I2C_NACK |
+			    RADEON_I2C_HALT |
+			    RADEON_I2C_SOFT_RST));
+
+	if (rdev->is_atom_bios) {
+		tmp = RREG32(RADEON_BIOS_6_SCRATCH);
+		tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE;
+		WREG32(RADEON_BIOS_6_SCRATCH, tmp);
+	}
+
+	mutex_unlock(&rdev->pm.mutex);
+	mutex_unlock(&rdev->dc_hw_i2c_mutex);
+
+	return ret;
+}
+
+/* hw i2c engine for r5xx hardware
+ * hw can buffer up to 15 bytes
+ */
+static int r500_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
+			    struct i2c_msg *msgs, int num)
+{
+	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+	struct radeon_device *rdev = i2c->dev->dev_private;
+	struct radeon_i2c_bus_rec *rec = &i2c->rec;
+	struct i2c_msg *p;
+	int i, j, remaining, current_count, buffer_offset, ret = num;
+	u32 prescale;
+	u32 tmp, reg;
+	u32 saved1, saved2;
+
+	mutex_lock(&rdev->dc_hw_i2c_mutex);
+	/* take the pm lock since we need a constant sclk */
+	mutex_lock(&rdev->pm.mutex);
+
+	prescale = radeon_get_i2c_prescale(rdev);
+
+	/* clear gpio mask bits */
+	tmp = RREG32(rec->mask_clk_reg);
+	tmp &= ~rec->mask_clk_mask;
+	WREG32(rec->mask_clk_reg, tmp);
+	tmp = RREG32(rec->mask_clk_reg);
+
+	tmp = RREG32(rec->mask_data_reg);
+	tmp &= ~rec->mask_data_mask;
+	WREG32(rec->mask_data_reg, tmp);
+	tmp = RREG32(rec->mask_data_reg);
+
+	/* clear pin values */
+	tmp = RREG32(rec->a_clk_reg);
+	tmp &= ~rec->a_clk_mask;
+	WREG32(rec->a_clk_reg, tmp);
+	tmp = RREG32(rec->a_clk_reg);
+
+	tmp = RREG32(rec->a_data_reg);
+	tmp &= ~rec->a_data_mask;
+	WREG32(rec->a_data_reg, tmp);
+	tmp = RREG32(rec->a_data_reg);
+
+	/* set the pins to input */
+	tmp = RREG32(rec->en_clk_reg);
+	tmp &= ~rec->en_clk_mask;
+	WREG32(rec->en_clk_reg, tmp);
+	tmp = RREG32(rec->en_clk_reg);
+
+	tmp = RREG32(rec->en_data_reg);
+	tmp &= ~rec->en_data_mask;
+	WREG32(rec->en_data_reg, tmp);
+	tmp = RREG32(rec->en_data_reg);
+
+	/* */
+	tmp = RREG32(RADEON_BIOS_6_SCRATCH);
+	WREG32(RADEON_BIOS_6_SCRATCH, tmp | ATOM_S6_HW_I2C_BUSY_STATE);
+	saved1 = RREG32(AVIVO_DC_I2C_CONTROL1);
+	saved2 = RREG32(0x494);
+	WREG32(0x494, saved2 | 0x1);
+
+	WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_WANTS_TO_USE_I2C);
+	for (i = 0; i < 50; i++) {
+		udelay(1);
+		if (RREG32(AVIVO_DC_I2C_ARBITRATION) & AVIVO_DC_I2C_SW_CAN_USE_I2C)
+			break;
+	}
+	if (i == 50) {
+		DRM_ERROR("failed to get i2c bus\n");
+		ret = -EBUSY;
+		goto done;
+	}
+
+	reg = AVIVO_DC_I2C_START | AVIVO_DC_I2C_STOP | AVIVO_DC_I2C_EN;
+	switch (rec->mask_clk_reg) {
+	case AVIVO_DC_GPIO_DDC1_MASK:
+		reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC1);
+		break;
+	case AVIVO_DC_GPIO_DDC2_MASK:
+		reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC2);
+		break;
+	case AVIVO_DC_GPIO_DDC3_MASK:
+		reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC3);
+		break;
+	default:
+		DRM_ERROR("gpio not supported with hw i2c\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* check for bus probe */
+	p = &msgs[0];
+	if ((num == 1) && (p->len == 0)) {
+		WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
+					      AVIVO_DC_I2C_NACK |
+					      AVIVO_DC_I2C_HALT));
+		WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
+		udelay(1);
+		WREG32(AVIVO_DC_I2C_RESET, 0);
+
+		WREG32(AVIVO_DC_I2C_DATA, (p->addr << 1) & 0xff);
+		WREG32(AVIVO_DC_I2C_DATA, 0);
+
+		WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48));
+		WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) |
+					       AVIVO_DC_I2C_DATA_COUNT(1) |
+					       (prescale << 16)));
+		WREG32(AVIVO_DC_I2C_CONTROL1, reg);
+		WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
+		for (j = 0; j < 200; j++) {
+			udelay(50);
+			tmp = RREG32(AVIVO_DC_I2C_STATUS1);
+			if (tmp & AVIVO_DC_I2C_GO)
+				continue;
+			tmp = RREG32(AVIVO_DC_I2C_STATUS1);
+			if (tmp & AVIVO_DC_I2C_DONE)
+				break;
+			else {
+				DRM_DEBUG("i2c write error 0x%08x\n", tmp);
+				WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
+				ret = -EIO;
+				goto done;
+			}
+		}
+		goto done;
+	}
+
+	for (i = 0; i < num; i++) {
+		p = &msgs[i];
+		remaining = p->len;
+		buffer_offset = 0;
+		if (p->flags & I2C_M_RD) {
+			while (remaining) {
+				if (remaining > 15)
+					current_count = 15;
+				else
+					current_count = remaining;
+				WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
+							      AVIVO_DC_I2C_NACK |
+							      AVIVO_DC_I2C_HALT));
+				WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
+				udelay(1);
+				WREG32(AVIVO_DC_I2C_RESET, 0);
+
+				WREG32(AVIVO_DC_I2C_DATA, ((p->addr << 1) & 0xff) | 0x1);
+				WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48));
+				WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) |
+							       AVIVO_DC_I2C_DATA_COUNT(current_count) |
+							       (prescale << 16)));
+				WREG32(AVIVO_DC_I2C_CONTROL1, reg | AVIVO_DC_I2C_RECEIVE);
+				WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
+				for (j = 0; j < 200; j++) {
+					udelay(50);
+					tmp = RREG32(AVIVO_DC_I2C_STATUS1);
+					if (tmp & AVIVO_DC_I2C_GO)
+						continue;
+					tmp = RREG32(AVIVO_DC_I2C_STATUS1);
+					if (tmp & AVIVO_DC_I2C_DONE)
+						break;
+					else {
+						DRM_DEBUG("i2c read error 0x%08x\n", tmp);
+						WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
+						ret = -EIO;
+						goto done;
+					}
+				}
+				for (j = 0; j < current_count; j++)
+					p->buf[buffer_offset + j] = RREG32(AVIVO_DC_I2C_DATA) & 0xff;
+				remaining -= current_count;
+				buffer_offset += current_count;
+			}
+		} else {
+			while (remaining) {
+				if (remaining > 15)
+					current_count = 15;
+				else
+					current_count = remaining;
+				WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
+							      AVIVO_DC_I2C_NACK |
+							      AVIVO_DC_I2C_HALT));
+				WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
+				udelay(1);
+				WREG32(AVIVO_DC_I2C_RESET, 0);
+
+				WREG32(AVIVO_DC_I2C_DATA, (p->addr << 1) & 0xff);
+				for (j = 0; j < current_count; j++)
+					WREG32(AVIVO_DC_I2C_DATA, p->buf[buffer_offset + j]);
+
+				WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48));
+				WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) |
+							       AVIVO_DC_I2C_DATA_COUNT(current_count) |
+							       (prescale << 16)));
+				WREG32(AVIVO_DC_I2C_CONTROL1, reg);
+				WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
+				for (j = 0; j < 200; j++) {
+					udelay(50);
+					tmp = RREG32(AVIVO_DC_I2C_STATUS1);
+					if (tmp & AVIVO_DC_I2C_GO)
+						continue;
+					tmp = RREG32(AVIVO_DC_I2C_STATUS1);
+					if (tmp & AVIVO_DC_I2C_DONE)
+						break;
+					else {
+						DRM_DEBUG("i2c write error 0x%08x\n", tmp);
+						WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
+						ret = -EIO;
+						goto done;
+					}
+				}
+				remaining -= current_count;
+				buffer_offset += current_count;
+			}
+		}
+	}
+
+done:
+	WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
+				      AVIVO_DC_I2C_NACK |
+				      AVIVO_DC_I2C_HALT));
+	WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
+	udelay(1);
+	WREG32(AVIVO_DC_I2C_RESET, 0);
+
+	WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_DONE_USING_I2C);
+	WREG32(AVIVO_DC_I2C_CONTROL1, saved1);
+	WREG32(0x494, saved2);
+	tmp = RREG32(RADEON_BIOS_6_SCRATCH);
+	tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE;
+	WREG32(RADEON_BIOS_6_SCRATCH, tmp);
+
+	mutex_unlock(&rdev->pm.mutex);
+	mutex_unlock(&rdev->dc_hw_i2c_mutex);
+
+	return ret;
+}
+
+static int radeon_sw_i2c_xfer(struct i2c_adapter *i2c_adap,
+			      struct i2c_msg *msgs, int num)
+{
+	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+	int ret;
+
+	radeon_i2c_do_lock(i2c, 1);
+	ret = i2c_transfer(&i2c->algo.radeon.bit_adapter, msgs, num);
+	radeon_i2c_do_lock(i2c, 0);
+
+	return ret;
+}
+
+static int radeon_i2c_xfer(struct i2c_adapter *i2c_adap,
+			   struct i2c_msg *msgs, int num)
+{
+	struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+	struct radeon_device *rdev = i2c->dev->dev_private;
+	struct radeon_i2c_bus_rec *rec = &i2c->rec;
+	int ret;
+
+	switch (rdev->family) {
+	case CHIP_R100:
+	case CHIP_RV100:
+	case CHIP_RS100:
+	case CHIP_RV200:
+	case CHIP_RS200:
+	case CHIP_R200:
+	case CHIP_RV250:
+	case CHIP_RS300:
+	case CHIP_RV280:
+	case CHIP_R300:
+	case CHIP_R350:
+	case CHIP_RV350:
+	case CHIP_RV380:
+	case CHIP_R420:
+	case CHIP_R423:
+	case CHIP_RV410:
+	case CHIP_RS400:
+	case CHIP_RS480:
+		if (rec->hw_capable)
+			ret = r100_hw_i2c_xfer(i2c_adap, msgs, num);
+		else
+			ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
+		break;
+	case CHIP_RS600:
+	case CHIP_RS690:
+	case CHIP_RS740:
+		/* XXX fill in hw i2c implementation */
+		ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
+		break;
+	case CHIP_RV515:
+	case CHIP_R520:
+	case CHIP_RV530:
+	case CHIP_RV560:
+	case CHIP_RV570:
+	case CHIP_R580:
+		if (rec->hw_capable) {
+			if (rec->mm_i2c)
+				ret = r100_hw_i2c_xfer(i2c_adap, msgs, num);
+			else
+				ret = r500_hw_i2c_xfer(i2c_adap, msgs, num);
+		} else
+			ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
+		break;
+	case CHIP_R600:
+	case CHIP_RV610:
+	case CHIP_RV630:
+	case CHIP_RV670:
+		/* XXX fill in hw i2c implementation */
+		ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
+		break;
+	case CHIP_RV620:
+	case CHIP_RV635:
+	case CHIP_RS780:
+	case CHIP_RS880:
+	case CHIP_RV770:
+	case CHIP_RV730:
+	case CHIP_RV710:
+	case CHIP_RV740:
+		/* XXX fill in hw i2c implementation */
+		ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
+		break;
+	case CHIP_CEDAR:
+	case CHIP_REDWOOD:
+	case CHIP_JUNIPER:
+	case CHIP_CYPRESS:
+	case CHIP_HEMLOCK:
+		/* XXX fill in hw i2c implementation */
+		ret = radeon_sw_i2c_xfer(i2c_adap, msgs, num);
+		break;
+	default:
+		DRM_ERROR("i2c: unhandled radeon chip\n");
+		ret = -EIO;
+		break;
+	}
+
+	return ret;
+}
+
+static u32 radeon_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm radeon_i2c_algo = {
+	.master_xfer = radeon_i2c_xfer,
+	.functionality = radeon_i2c_func,
+};
+
 struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
 					  struct radeon_i2c_bus_rec *rec,
 					  const char *name)
@@ -179,23 +878,36 @@
 	if (i2c == NULL)
 		return NULL;
 
-	i2c->adapter.owner = THIS_MODULE;
-	i2c->dev = dev;
-	i2c_set_adapdata(&i2c->adapter, i2c);
-	i2c->adapter.algo_data = &i2c->algo.bit;
-	i2c->algo.bit.setsda = set_data;
-	i2c->algo.bit.setscl = set_clock;
-	i2c->algo.bit.getsda = get_data;
-	i2c->algo.bit.getscl = get_clock;
-	i2c->algo.bit.udelay = 20;
+	/* set the internal bit adapter */
+	i2c->algo.radeon.bit_adapter.owner = THIS_MODULE;
+	i2c_set_adapdata(&i2c->algo.radeon.bit_adapter, i2c);
+	sprintf(i2c->algo.radeon.bit_adapter.name, "Radeon internal i2c bit bus %s", name);
+	i2c->algo.radeon.bit_adapter.algo_data = &i2c->algo.radeon.bit_data;
+	i2c->algo.radeon.bit_data.setsda = set_data;
+	i2c->algo.radeon.bit_data.setscl = set_clock;
+	i2c->algo.radeon.bit_data.getsda = get_data;
+	i2c->algo.radeon.bit_data.getscl = get_clock;
+	i2c->algo.radeon.bit_data.udelay = 20;
 	/* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always
 	 * make this, 2 jiffies is a lot more reliable */
-	i2c->algo.bit.timeout = 2;
-	i2c->algo.bit.data = i2c;
-	i2c->rec = *rec;
-	ret = i2c_bit_add_bus(&i2c->adapter);
+	i2c->algo.radeon.bit_data.timeout = 2;
+	i2c->algo.radeon.bit_data.data = i2c;
+	ret = i2c_bit_add_bus(&i2c->algo.radeon.bit_adapter);
 	if (ret) {
-		DRM_INFO("Failed to register i2c %s\n", name);
+		DRM_ERROR("Failed to register internal bit i2c %s\n", name);
+		goto out_free;
+	}
+	/* set the radeon i2c adapter */
+	i2c->dev = dev;
+	i2c->rec = *rec;
+	i2c->adapter.owner = THIS_MODULE;
+	i2c_set_adapdata(&i2c->adapter, i2c);
+	sprintf(i2c->adapter.name, "Radeon i2c %s", name);
+	i2c->adapter.algo_data = &i2c->algo.radeon;
+	i2c->adapter.algo = &radeon_i2c_algo;
+	ret = i2c_add_adapter(&i2c->adapter);
+	if (ret) {
+		DRM_ERROR("Failed to register i2c %s\n", name);
 		goto out_free;
 	}
 
@@ -237,11 +949,19 @@
 
 }
 
-
 void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
 {
 	if (!i2c)
 		return;
+	i2c_del_adapter(&i2c->algo.radeon.bit_adapter);
+	i2c_del_adapter(&i2c->adapter);
+	kfree(i2c);
+}
+
+void radeon_i2c_destroy_dp(struct radeon_i2c_chan *i2c)
+{
+	if (!i2c)
+		return;
 
 	i2c_del_adapter(&i2c->adapter);
 	kfree(i2c);
@@ -252,10 +972,10 @@
 	return NULL;
 }
 
-void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
-			    u8 slave_addr,
-			    u8 addr,
-			    u8 *val)
+void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus,
+			 u8 slave_addr,
+			 u8 addr,
+			 u8 *val)
 {
 	u8 out_buf[2];
 	u8 in_buf[2];
@@ -286,10 +1006,10 @@
 	}
 }
 
-void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c_bus,
-			    u8 slave_addr,
-			    u8 addr,
-			    u8 val)
+void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus,
+			 u8 slave_addr,
+			 u8 addr,
+			 u8 val)
 {
 	uint8_t out_buf[2];
 	struct i2c_msg msg = {
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index f23b056..20ec276 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -30,6 +30,8 @@
 #include "radeon.h"
 #include "radeon_drm.h"
 
+#include <linux/vga_switcheroo.h>
+
 int radeon_driver_unload_kms(struct drm_device *dev)
 {
 	struct radeon_device *rdev = dev->dev_private;
@@ -136,6 +138,7 @@
 
 void radeon_driver_lastclose_kms(struct drm_device *dev)
 {
+	vga_switcheroo_process_delayed_switch();
 }
 
 int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
@@ -276,17 +279,17 @@
 	DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH),
 	DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH),
 	/* KMS */
-	DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
 };
 int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index b6d8081..df23d6a 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -403,7 +403,7 @@
 
 	/* if scanout was in GTT this really wouldn't work */
 	/* crtc offset is from display base addr not FB location */
-	radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location;
+	radeon_crtc->legacy_display_base_addr = rdev->mc.vram_start;
 
 	base -= radeon_crtc->legacy_display_base_addr;
 
@@ -582,29 +582,6 @@
 				   ? RADEON_CRTC_V_SYNC_POL
 				   : 0));
 
-	/* TODO -> Dell Server */
-	if (0) {
-		uint32_t disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
-		uint32_t tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
-		uint32_t dac2_cntl = RREG32(RADEON_DAC_CNTL2);
-		uint32_t crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
-
-		dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
-		dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
-
-		/* For CRT on DAC2, don't turn it on if BIOS didn't
-		   enable it, even it's detected.
-		*/
-		disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
-		tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16));
-		tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16));
-
-		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
-		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
-		WREG32(RADEON_DAC_CNTL2, dac2_cntl);
-		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
-	}
-
 	if (radeon_crtc->crtc_id) {
 		uint32_t crtc2_gen_cntl;
 		uint32_t disp2_merge_cntl;
@@ -726,6 +703,10 @@
 		pll = &rdev->clock.p1pll;
 
 	pll->flags = RADEON_PLL_LEGACY;
+	if (radeon_new_pll == 1)
+		pll->algo = PLL_ALGO_NEW;
+	else
+		pll->algo = PLL_ALGO_LEGACY;
 
 	if (mode->clock > 200000) /* range limits??? */
 		pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 38e45e2..cf389ce 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -115,6 +115,9 @@
 		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
 	else
 		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+
+	/* adjust pm to dpms change */
+	radeon_pm_compute_clocks(rdev);
 }
 
 static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
@@ -214,6 +217,11 @@
 				     struct drm_display_mode *adjusted_mode)
 {
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+
+	/* adjust pm to upcoming mode change */
+	radeon_pm_compute_clocks(rdev);
 
 	/* set the active encoder to connector routing */
 	radeon_encoder_set_active_device(encoder);
@@ -285,6 +293,9 @@
 		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
 	else
 		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+
+	/* adjust pm to dpms change */
+	radeon_pm_compute_clocks(rdev);
 }
 
 static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
@@ -470,6 +481,9 @@
 		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
 	else
 		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+
+	/* adjust pm to dpms change */
+	radeon_pm_compute_clocks(rdev);
 }
 
 static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
@@ -635,6 +649,9 @@
 		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
 	else
 		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+
+	/* adjust pm to dpms change */
+	radeon_pm_compute_clocks(rdev);
 }
 
 static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
@@ -842,6 +859,9 @@
 		radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
 	else
 		radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
+
+	/* adjust pm to dpms change */
+	radeon_pm_compute_clocks(rdev);
 }
 
 static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index e81b2ae..1702b82 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -83,6 +83,8 @@
 	bool valid;
 	/* id used by atom */
 	uint8_t i2c_id;
+	/* id used by atom */
+	uint8_t hpd_id;
 	/* can be used with hw i2c engine */
 	bool hw_capable;
 	/* uses multi-media i2c engine */
@@ -113,6 +115,7 @@
 
 #define RADEON_MAX_BIOS_CONNECTOR 16
 
+/* pll flags */
 #define RADEON_PLL_USE_BIOS_DIVS        (1 << 0)
 #define RADEON_PLL_NO_ODD_POST_DIV      (1 << 1)
 #define RADEON_PLL_USE_REF_DIV          (1 << 2)
@@ -127,6 +130,12 @@
 #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
 #define RADEON_PLL_USE_POST_DIV         (1 << 12)
 
+/* pll algo */
+enum radeon_pll_algo {
+	PLL_ALGO_LEGACY,
+	PLL_ALGO_NEW
+};
+
 struct radeon_pll {
 	/* reference frequency */
 	uint32_t reference_freq;
@@ -157,6 +166,13 @@
 
 	/* pll id */
 	uint32_t id;
+	/* pll algo */
+	enum radeon_pll_algo algo;
+};
+
+struct i2c_algo_radeon_data {
+	struct i2c_adapter bit_adapter;
+	struct i2c_algo_bit_data bit_data;
 };
 
 struct radeon_i2c_chan {
@@ -164,7 +180,7 @@
 	struct drm_device *dev;
 	union {
 		struct i2c_algo_dp_aux_data dp;
-		struct i2c_algo_bit_data bit;
+		struct i2c_algo_radeon_data radeon;
 	} algo;
 	struct radeon_i2c_bus_rec rec;
 };
@@ -193,7 +209,7 @@
 	struct card_info *atom_card_info;
 	enum radeon_connector_table connector_table;
 	bool mode_config_initialized;
-	struct radeon_crtc *crtcs[2];
+	struct radeon_crtc *crtcs[6];
 	/* DVI-I properties */
 	struct drm_property *coherent_mode_property;
 	/* DAC enable load detect */
@@ -202,7 +218,8 @@
 	struct drm_property *tv_std_property;
 	/* legacy TMDS PLL detect */
 	struct drm_property *tmds_pll_property;
-
+	/* hardcoded DFP edid from BIOS */
+	struct edid *bios_hardcoded_edid;
 };
 
 #define MAX_H_CODE_TIMING_LEN 32
@@ -237,6 +254,7 @@
 	fixed20_12 vsc;
 	fixed20_12 hsc;
 	struct drm_display_mode native_mode;
+	int pll_id;
 };
 
 struct radeon_encoder_primary_dac {
@@ -303,6 +321,7 @@
 	/* atom lvds */
 	uint32_t lvds_misc;
 	uint16_t panel_pwr_delay;
+	enum radeon_pll_algo pll_algo;
 	struct radeon_atom_ss *ss;
 	/* panel mode */
 	struct drm_display_mode native_mode;
@@ -398,6 +417,7 @@
 			  struct drm_connector *connector);
 extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
 extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
+extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action);
 extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
 					   int action, uint8_t lane_num,
 					   uint8_t lane_set);
@@ -411,14 +431,15 @@
 						 struct radeon_i2c_bus_rec *rec,
 						 const char *name);
 extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c);
-extern void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
-				   u8 slave_addr,
-				   u8 addr,
-				   u8 *val);
-extern void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c,
-				   u8 slave_addr,
-				   u8 addr,
-				   u8 val);
+extern void radeon_i2c_destroy_dp(struct radeon_i2c_chan *i2c);
+extern void radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus,
+				u8 slave_addr,
+				u8 addr,
+				u8 *val);
+extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
+				u8 slave_addr,
+				u8 addr,
+				u8 val);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
@@ -432,14 +453,6 @@
 			       uint32_t *ref_div_p,
 			       uint32_t *post_div_p);
 
-extern void radeon_compute_pll_avivo(struct radeon_pll *pll,
-				     uint64_t freq,
-				     uint32_t *dot_clock_p,
-				     uint32_t *fb_div_p,
-				     uint32_t *frac_fb_div_p,
-				     uint32_t *ref_div_p,
-				     uint32_t *post_div_p);
-
 extern void radeon_setup_encoder_clones(struct drm_device *dev);
 
 struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index);
@@ -473,6 +486,9 @@
 extern int radeon_crtc_cursor_move(struct drm_crtc *crtc,
 				   int x, int y);
 
+extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev);
+extern struct edid *
+radeon_combios_get_hardcoded_edid(struct radeon_device *rdev);
 extern bool radeon_atom_get_clock_info(struct drm_device *dev);
 extern bool radeon_combios_get_clock_info(struct drm_device *dev);
 extern struct radeon_encoder_atom_dig *
@@ -531,7 +547,6 @@
 			       struct radeon_crtc *radeon_crtc);
 void radeon_legacy_init_crtc(struct drm_device *dev,
 			     struct radeon_crtc *radeon_crtc);
-extern void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state);
 
 void radeon_get_clock_info(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index f1da370..fc9d00a 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -178,7 +178,6 @@
 {
 	int r, i;
 
-	radeon_ttm_placement_from_domain(bo, domain);
 	if (bo->pin_count) {
 		bo->pin_count++;
 		if (gpu_addr)
@@ -186,6 +185,8 @@
 		return 0;
 	}
 	radeon_ttm_placement_from_domain(bo, domain);
+	/* force to pin into visible video ram */
+	bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
 	for (i = 0; i < bo->placement.num_placement; i++)
 		bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
 	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 8bce64c..d4d1c39 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -18,21 +18,413 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  *
  * Authors: Rafał Miłecki <zajec5@gmail.com>
+ *          Alex Deucher <alexdeucher@gmail.com>
  */
 #include "drmP.h"
 #include "radeon.h"
+#include "avivod.h"
 
-int radeon_debugfs_pm_init(struct radeon_device *rdev);
+#define RADEON_IDLE_LOOP_MS 100
+#define RADEON_RECLOCK_DELAY_MS 200
+#define RADEON_WAIT_VBLANK_TIMEOUT 200
+
+static void radeon_pm_set_clocks_locked(struct radeon_device *rdev);
+static void radeon_pm_set_clocks(struct radeon_device *rdev);
+static void radeon_pm_idle_work_handler(struct work_struct *work);
+static int radeon_debugfs_pm_init(struct radeon_device *rdev);
+
+static const char *pm_state_names[4] = {
+	"PM_STATE_DISABLED",
+	"PM_STATE_MINIMUM",
+	"PM_STATE_PAUSED",
+	"PM_STATE_ACTIVE"
+};
+
+static const char *pm_state_types[5] = {
+	"Default",
+	"Powersave",
+	"Battery",
+	"Balanced",
+	"Performance",
+};
+
+static void radeon_print_power_mode_info(struct radeon_device *rdev)
+{
+	int i, j;
+	bool is_default;
+
+	DRM_INFO("%d Power State(s)\n", rdev->pm.num_power_states);
+	for (i = 0; i < rdev->pm.num_power_states; i++) {
+		if (rdev->pm.default_power_state == &rdev->pm.power_state[i])
+			is_default = true;
+		else
+			is_default = false;
+		DRM_INFO("State %d %s %s\n", i,
+			 pm_state_types[rdev->pm.power_state[i].type],
+			 is_default ? "(default)" : "");
+		if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP))
+			DRM_INFO("\t%d PCIE Lanes\n", rdev->pm.power_state[i].non_clock_info.pcie_lanes);
+		DRM_INFO("\t%d Clock Mode(s)\n", rdev->pm.power_state[i].num_clock_modes);
+		for (j = 0; j < rdev->pm.power_state[i].num_clock_modes; j++) {
+			if (rdev->flags & RADEON_IS_IGP)
+				DRM_INFO("\t\t%d engine: %d\n",
+					 j,
+					 rdev->pm.power_state[i].clock_info[j].sclk * 10);
+			else
+				DRM_INFO("\t\t%d engine/memory: %d/%d\n",
+					 j,
+					 rdev->pm.power_state[i].clock_info[j].sclk * 10,
+					 rdev->pm.power_state[i].clock_info[j].mclk * 10);
+		}
+	}
+}
+
+static struct radeon_power_state * radeon_pick_power_state(struct radeon_device *rdev,
+							   enum radeon_pm_state_type type)
+{
+	int i, j;
+	enum radeon_pm_state_type wanted_types[2];
+	int wanted_count;
+
+	switch (type) {
+	case POWER_STATE_TYPE_DEFAULT:
+	default:
+		return rdev->pm.default_power_state;
+	case POWER_STATE_TYPE_POWERSAVE:
+		if (rdev->flags & RADEON_IS_MOBILITY) {
+			wanted_types[0] = POWER_STATE_TYPE_POWERSAVE;
+			wanted_types[1] = POWER_STATE_TYPE_BATTERY;
+			wanted_count = 2;
+		} else {
+			wanted_types[0] = POWER_STATE_TYPE_PERFORMANCE;
+			wanted_count = 1;
+		}
+		break;
+	case POWER_STATE_TYPE_BATTERY:
+		if (rdev->flags & RADEON_IS_MOBILITY) {
+			wanted_types[0] = POWER_STATE_TYPE_BATTERY;
+			wanted_types[1] = POWER_STATE_TYPE_POWERSAVE;
+			wanted_count = 2;
+		} else {
+			wanted_types[0] = POWER_STATE_TYPE_PERFORMANCE;
+			wanted_count = 1;
+		}
+		break;
+	case POWER_STATE_TYPE_BALANCED:
+	case POWER_STATE_TYPE_PERFORMANCE:
+		wanted_types[0] = type;
+		wanted_count = 1;
+		break;
+	}
+
+	for (i = 0; i < wanted_count; i++) {
+		for (j = 0; j < rdev->pm.num_power_states; j++) {
+			if (rdev->pm.power_state[j].type == wanted_types[i])
+				return &rdev->pm.power_state[j];
+		}
+	}
+
+	return rdev->pm.default_power_state;
+}
+
+static struct radeon_pm_clock_info * radeon_pick_clock_mode(struct radeon_device *rdev,
+							    struct radeon_power_state *power_state,
+							    enum radeon_pm_clock_mode_type type)
+{
+	switch (type) {
+	case POWER_MODE_TYPE_DEFAULT:
+	default:
+		return power_state->default_clock_mode;
+	case POWER_MODE_TYPE_LOW:
+		return &power_state->clock_info[0];
+	case POWER_MODE_TYPE_MID:
+		if (power_state->num_clock_modes > 2)
+			return &power_state->clock_info[1];
+		else
+			return &power_state->clock_info[0];
+		break;
+	case POWER_MODE_TYPE_HIGH:
+		return &power_state->clock_info[power_state->num_clock_modes - 1];
+	}
+
+}
+
+static void radeon_get_power_state(struct radeon_device *rdev,
+				   enum radeon_pm_action action)
+{
+	switch (action) {
+	case PM_ACTION_MINIMUM:
+		rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_BATTERY);
+		rdev->pm.requested_clock_mode =
+			radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_LOW);
+		break;
+	case PM_ACTION_DOWNCLOCK:
+		rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_POWERSAVE);
+		rdev->pm.requested_clock_mode =
+			radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_MID);
+		break;
+	case PM_ACTION_UPCLOCK:
+		rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_DEFAULT);
+		rdev->pm.requested_clock_mode =
+			radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_HIGH);
+		break;
+	case PM_ACTION_NONE:
+	default:
+		DRM_ERROR("Requested mode for not defined action\n");
+		return;
+	}
+	DRM_INFO("Requested: e: %d m: %d p: %d\n",
+		 rdev->pm.requested_clock_mode->sclk,
+		 rdev->pm.requested_clock_mode->mclk,
+		 rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
+}
+
+static void radeon_set_power_state(struct radeon_device *rdev)
+{
+	/* if *_clock_mode are the same, *_power_state are as well */
+	if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode)
+		return;
+
+	DRM_INFO("Setting: e: %d m: %d p: %d\n",
+		 rdev->pm.requested_clock_mode->sclk,
+		 rdev->pm.requested_clock_mode->mclk,
+		 rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
+	/* set pcie lanes */
+	/* set voltage */
+	/* set engine clock */
+	radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk);
+	/* set memory clock */
+
+	rdev->pm.current_power_state = rdev->pm.requested_power_state;
+	rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode;
+}
 
 int radeon_pm_init(struct radeon_device *rdev)
 {
+	rdev->pm.state = PM_STATE_DISABLED;
+	rdev->pm.planned_action = PM_ACTION_NONE;
+	rdev->pm.downclocked = false;
+
+	if (rdev->bios) {
+		if (rdev->is_atom_bios)
+			radeon_atombios_get_power_modes(rdev);
+		else
+			radeon_combios_get_power_modes(rdev);
+		radeon_print_power_mode_info(rdev);
+	}
+
 	if (radeon_debugfs_pm_init(rdev)) {
 		DRM_ERROR("Failed to register debugfs file for PM!\n");
 	}
 
+	INIT_DELAYED_WORK(&rdev->pm.idle_work, radeon_pm_idle_work_handler);
+
+	if (radeon_dynpm != -1 && radeon_dynpm) {
+		rdev->pm.state = PM_STATE_PAUSED;
+		DRM_INFO("radeon: dynamic power management enabled\n");
+	}
+
+	DRM_INFO("radeon: power management initialized\n");
+
 	return 0;
 }
 
+void radeon_pm_compute_clocks(struct radeon_device *rdev)
+{
+	struct drm_device *ddev = rdev->ddev;
+	struct drm_connector *connector;
+	struct radeon_crtc *radeon_crtc;
+	int count = 0;
+
+	if (rdev->pm.state == PM_STATE_DISABLED)
+		return;
+
+	mutex_lock(&rdev->pm.mutex);
+
+	rdev->pm.active_crtcs = 0;
+	list_for_each_entry(connector,
+		&ddev->mode_config.connector_list, head) {
+		if (connector->encoder &&
+			connector->dpms != DRM_MODE_DPMS_OFF) {
+			radeon_crtc = to_radeon_crtc(connector->encoder->crtc);
+			rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
+			++count;
+		}
+	}
+
+	if (count > 1) {
+		if (rdev->pm.state == PM_STATE_ACTIVE) {
+			cancel_delayed_work(&rdev->pm.idle_work);
+
+			rdev->pm.state = PM_STATE_PAUSED;
+			rdev->pm.planned_action = PM_ACTION_UPCLOCK;
+			if (rdev->pm.downclocked)
+				radeon_pm_set_clocks(rdev);
+
+			DRM_DEBUG("radeon: dynamic power management deactivated\n");
+		}
+	} else if (count == 1) {
+		/* TODO: Increase clocks if needed for current mode */
+
+		if (rdev->pm.state == PM_STATE_MINIMUM) {
+			rdev->pm.state = PM_STATE_ACTIVE;
+			rdev->pm.planned_action = PM_ACTION_UPCLOCK;
+			radeon_pm_set_clocks(rdev);
+
+			queue_delayed_work(rdev->wq, &rdev->pm.idle_work,
+				msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+		}
+		else if (rdev->pm.state == PM_STATE_PAUSED) {
+			rdev->pm.state = PM_STATE_ACTIVE;
+			queue_delayed_work(rdev->wq, &rdev->pm.idle_work,
+				msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+			DRM_DEBUG("radeon: dynamic power management activated\n");
+		}
+	}
+	else { /* count == 0 */
+		if (rdev->pm.state != PM_STATE_MINIMUM) {
+			cancel_delayed_work(&rdev->pm.idle_work);
+
+			rdev->pm.state = PM_STATE_MINIMUM;
+			rdev->pm.planned_action = PM_ACTION_MINIMUM;
+			radeon_pm_set_clocks(rdev);
+		}
+	}
+
+	mutex_unlock(&rdev->pm.mutex);
+}
+
+static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish)
+{
+	u32 stat_crtc1 = 0, stat_crtc2 = 0;
+	bool in_vbl = true;
+
+	if (ASIC_IS_AVIVO(rdev)) {
+		if (rdev->pm.active_crtcs & (1 << 0)) {
+			stat_crtc1 = RREG32(D1CRTC_STATUS);
+			if (!(stat_crtc1 & 1))
+				in_vbl = false;
+		}
+		if (rdev->pm.active_crtcs & (1 << 1)) {
+			stat_crtc2 = RREG32(D2CRTC_STATUS);
+			if (!(stat_crtc2 & 1))
+				in_vbl = false;
+		}
+	}
+	if (in_vbl == false)
+		DRM_INFO("not in vbl for pm change %08x %08x at %s\n", stat_crtc1,
+			 stat_crtc2, finish ? "exit" : "entry");
+	return in_vbl;
+}
+static void radeon_pm_set_clocks_locked(struct radeon_device *rdev)
+{
+	/*radeon_fence_wait_last(rdev);*/
+	switch (rdev->pm.planned_action) {
+	case PM_ACTION_UPCLOCK:
+		rdev->pm.downclocked = false;
+		break;
+	case PM_ACTION_DOWNCLOCK:
+		rdev->pm.downclocked = true;
+		break;
+	case PM_ACTION_MINIMUM:
+		break;
+	case PM_ACTION_NONE:
+		DRM_ERROR("%s: PM_ACTION_NONE\n", __func__);
+		break;
+	}
+
+	/* check if we are in vblank */
+	radeon_pm_debug_check_in_vbl(rdev, false);
+	radeon_set_power_state(rdev);
+	radeon_pm_debug_check_in_vbl(rdev, true);
+	rdev->pm.planned_action = PM_ACTION_NONE;
+}
+
+static void radeon_pm_set_clocks(struct radeon_device *rdev)
+{
+	radeon_get_power_state(rdev, rdev->pm.planned_action);
+	mutex_lock(&rdev->cp.mutex);
+
+	if (rdev->pm.active_crtcs & (1 << 0)) {
+		rdev->pm.req_vblank |= (1 << 0);
+		drm_vblank_get(rdev->ddev, 0);
+	}
+	if (rdev->pm.active_crtcs & (1 << 1)) {
+		rdev->pm.req_vblank |= (1 << 1);
+		drm_vblank_get(rdev->ddev, 1);
+	}
+	if (rdev->pm.active_crtcs)
+		wait_event_interruptible_timeout(
+			rdev->irq.vblank_queue, 0,
+			msecs_to_jiffies(RADEON_WAIT_VBLANK_TIMEOUT));
+	if (rdev->pm.req_vblank & (1 << 0)) {
+		rdev->pm.req_vblank &= ~(1 << 0);
+		drm_vblank_put(rdev->ddev, 0);
+	}
+	if (rdev->pm.req_vblank & (1 << 1)) {
+		rdev->pm.req_vblank &= ~(1 << 1);
+		drm_vblank_put(rdev->ddev, 1);
+	}
+
+	radeon_pm_set_clocks_locked(rdev);
+	mutex_unlock(&rdev->cp.mutex);
+}
+
+static void radeon_pm_idle_work_handler(struct work_struct *work)
+{
+	struct radeon_device *rdev;
+	rdev = container_of(work, struct radeon_device,
+				pm.idle_work.work);
+
+	mutex_lock(&rdev->pm.mutex);
+	if (rdev->pm.state == PM_STATE_ACTIVE) {
+		unsigned long irq_flags;
+		int not_processed = 0;
+
+		read_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
+		if (!list_empty(&rdev->fence_drv.emited)) {
+			struct list_head *ptr;
+			list_for_each(ptr, &rdev->fence_drv.emited) {
+				/* count up to 3, that's enought info */
+				if (++not_processed >= 3)
+					break;
+			}
+		}
+		read_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
+
+		if (not_processed >= 3) { /* should upclock */
+			if (rdev->pm.planned_action == PM_ACTION_DOWNCLOCK) {
+				rdev->pm.planned_action = PM_ACTION_NONE;
+			} else if (rdev->pm.planned_action == PM_ACTION_NONE &&
+				rdev->pm.downclocked) {
+				rdev->pm.planned_action =
+					PM_ACTION_UPCLOCK;
+				rdev->pm.action_timeout = jiffies +
+				msecs_to_jiffies(RADEON_RECLOCK_DELAY_MS);
+			}
+		} else if (not_processed == 0) { /* should downclock */
+			if (rdev->pm.planned_action == PM_ACTION_UPCLOCK) {
+				rdev->pm.planned_action = PM_ACTION_NONE;
+			} else if (rdev->pm.planned_action == PM_ACTION_NONE &&
+				!rdev->pm.downclocked) {
+				rdev->pm.planned_action =
+					PM_ACTION_DOWNCLOCK;
+				rdev->pm.action_timeout = jiffies +
+				msecs_to_jiffies(RADEON_RECLOCK_DELAY_MS);
+			}
+		}
+
+		if (rdev->pm.planned_action != PM_ACTION_NONE &&
+		    jiffies > rdev->pm.action_timeout) {
+			radeon_pm_set_clocks(rdev);
+		}
+	}
+	mutex_unlock(&rdev->pm.mutex);
+
+	queue_delayed_work(rdev->wq, &rdev->pm.idle_work,
+					msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
+}
+
 /*
  * Debugfs info
  */
@@ -44,11 +436,14 @@
 	struct drm_device *dev = node->minor->dev;
 	struct radeon_device *rdev = dev->dev_private;
 
+	seq_printf(m, "state: %s\n", pm_state_names[rdev->pm.state]);
 	seq_printf(m, "default engine clock: %u0 kHz\n", rdev->clock.default_sclk);
 	seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
 	seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk);
 	if (rdev->asic->get_memory_clock)
 		seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
+	if (rdev->asic->get_pcie_lanes)
+		seq_printf(m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev));
 
 	return 0;
 }
@@ -58,7 +453,7 @@
 };
 #endif
 
-int radeon_debugfs_pm_init(struct radeon_device *rdev)
+static int radeon_debugfs_pm_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
 	return radeon_debugfs_add_files(rdev, radeon_pm_info_list, ARRAY_SIZE(radeon_pm_info_list));
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h
index 6d0a009..5c0dc08 100644
--- a/drivers/gpu/drm/radeon/radeon_reg.h
+++ b/drivers/gpu/drm/radeon/radeon_reg.h
@@ -54,7 +54,7 @@
 #include "r300_reg.h"
 #include "r500_reg.h"
 #include "r600_reg.h"
-
+#include "evergreen_reg.h"
 
 #define RADEON_MC_AGP_LOCATION		0x014c
 #define		RADEON_MC_AGP_START_MASK	0x0000FFFF
@@ -1060,32 +1060,38 @@
 
        /* Multimedia I2C bus */
 #define RADEON_I2C_CNTL_0		    0x0090
-#define RADEON_I2C_DONE                     (1 << 0)
-#define RADEON_I2C_NACK                     (1 << 1)
-#define RADEON_I2C_HALT                     (1 << 2)
-#define RADEON_I2C_SOFT_RST                 (1 << 5)
-#define RADEON_I2C_DRIVE_EN                 (1 << 6)
-#define RADEON_I2C_DRIVE_SEL                (1 << 7)
-#define RADEON_I2C_START                    (1 << 8)
-#define RADEON_I2C_STOP                     (1 << 9)
-#define RADEON_I2C_RECEIVE                  (1 << 10)
-#define RADEON_I2C_ABORT                    (1 << 11)
-#define RADEON_I2C_GO                       (1 << 12)
-#define RADEON_I2C_PRESCALE_SHIFT           16
+#       define RADEON_I2C_DONE              (1 << 0)
+#       define RADEON_I2C_NACK              (1 << 1)
+#       define RADEON_I2C_HALT              (1 << 2)
+#       define RADEON_I2C_SOFT_RST          (1 << 5)
+#       define RADEON_I2C_DRIVE_EN          (1 << 6)
+#       define RADEON_I2C_DRIVE_SEL         (1 << 7)
+#       define RADEON_I2C_START             (1 << 8)
+#       define RADEON_I2C_STOP              (1 << 9)
+#       define RADEON_I2C_RECEIVE           (1 << 10)
+#       define RADEON_I2C_ABORT             (1 << 11)
+#       define RADEON_I2C_GO                (1 << 12)
+#       define RADEON_I2C_PRESCALE_SHIFT    16
 #define RADEON_I2C_CNTL_1                   0x0094
-#define RADEON_I2C_DATA_COUNT_SHIFT         0
-#define RADEON_I2C_ADDR_COUNT_SHIFT         4
-#define RADEON_I2C_INTRA_BYTE_DELAY_SHIFT   8
-#define RADEON_I2C_SEL                      (1 << 16)
-#define RADEON_I2C_EN                       (1 << 17)
-#define RADEON_I2C_TIME_LIMIT_SHIFT         24
+#       define RADEON_I2C_DATA_COUNT_SHIFT  0
+#       define RADEON_I2C_ADDR_COUNT_SHIFT  4
+#       define RADEON_I2C_INTRA_BYTE_DELAY_SHIFT   8
+#       define RADEON_I2C_SEL               (1 << 16)
+#       define RADEON_I2C_EN                (1 << 17)
+#       define RADEON_I2C_TIME_LIMIT_SHIFT  24
 #define RADEON_I2C_DATA			    0x0098
 
 #define RADEON_DVI_I2C_CNTL_0		    0x02e0
 #       define R200_DVI_I2C_PIN_SEL(x)      ((x) << 3)
-#       define R200_SEL_DDC1                0 /* 0x60 - VGA_DDC */
-#       define R200_SEL_DDC2                1 /* 0x64 - DVI_DDC */
-#       define R200_SEL_DDC3                2 /* 0x68 - MONID_DDC */
+#       define R200_SEL_DDC1                0 /* depends on asic */
+#       define R200_SEL_DDC2                1 /* depends on asic */
+#       define R200_SEL_DDC3                2 /* depends on asic */
+#	define RADEON_SW_WANTS_TO_USE_DVI_I2C (1 << 13)
+#	define RADEON_SW_CAN_USE_DVI_I2C      (1 << 13)
+#	define RADEON_SW_DONE_USING_DVI_I2C   (1 << 14)
+#	define RADEON_HW_NEEDS_DVI_I2C        (1 << 14)
+#	define RADEON_ABORT_HW_DVI_I2C        (1 << 15)
+#	define RADEON_HW_USING_DVI_I2C        (1 << 15)
 #define RADEON_DVI_I2C_CNTL_1               0x02e4
 #define RADEON_DVI_I2C_DATA		    0x02e8
 
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 6579eb4..e50513a 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -34,6 +34,36 @@
 
 int radeon_debugfs_ib_init(struct radeon_device *rdev);
 
+void radeon_ib_bogus_cleanup(struct radeon_device *rdev)
+{
+	struct radeon_ib *ib, *n;
+
+	list_for_each_entry_safe(ib, n, &rdev->ib_pool.bogus_ib, list) {
+		list_del(&ib->list);
+		vfree(ib->ptr);
+		kfree(ib);
+	}
+}
+
+void radeon_ib_bogus_add(struct radeon_device *rdev, struct radeon_ib *ib)
+{
+	struct radeon_ib *bib;
+
+	bib = kmalloc(sizeof(*bib), GFP_KERNEL);
+	if (bib == NULL)
+		return;
+	bib->ptr = vmalloc(ib->length_dw * 4);
+	if (bib->ptr == NULL) {
+		kfree(bib);
+		return;
+	}
+	memcpy(bib->ptr, ib->ptr, ib->length_dw * 4);
+	bib->length_dw = ib->length_dw;
+	mutex_lock(&rdev->ib_pool.mutex);
+	list_add_tail(&bib->list, &rdev->ib_pool.bogus_ib);
+	mutex_unlock(&rdev->ib_pool.mutex);
+}
+
 /*
  * IB.
  */
@@ -142,6 +172,7 @@
 
 	if (rdev->ib_pool.robj)
 		return 0;
+	INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib);
 	/* Allocate 1M object buffer */
 	r = radeon_bo_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
 				true, RADEON_GEM_DOMAIN_GTT,
@@ -192,6 +223,8 @@
 		return;
 	}
 	mutex_lock(&rdev->ib_pool.mutex);
+	radeon_ib_bogus_cleanup(rdev);
+
 	if (rdev->ib_pool.robj) {
 		r = radeon_bo_reserve(rdev->ib_pool.robj, false);
 		if (likely(r == 0)) {
@@ -349,15 +382,49 @@
 	return 0;
 }
 
+static int radeon_debugfs_ib_bogus_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct radeon_device *rdev = node->info_ent->data;
+	struct radeon_ib *ib;
+	unsigned i;
+
+	mutex_lock(&rdev->ib_pool.mutex);
+	if (list_empty(&rdev->ib_pool.bogus_ib)) {
+		mutex_unlock(&rdev->ib_pool.mutex);
+		seq_printf(m, "no bogus IB recorded\n");
+		return 0;
+	}
+	ib = list_first_entry(&rdev->ib_pool.bogus_ib, struct radeon_ib, list);
+	list_del_init(&ib->list);
+	mutex_unlock(&rdev->ib_pool.mutex);
+	seq_printf(m, "IB size %05u dwords\n", ib->length_dw);
+	for (i = 0; i < ib->length_dw; i++) {
+		seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]);
+	}
+	vfree(ib->ptr);
+	kfree(ib);
+	return 0;
+}
+
 static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE];
 static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32];
+
+static struct drm_info_list radeon_debugfs_ib_bogus_info_list[] = {
+	{"radeon_ib_bogus", radeon_debugfs_ib_bogus_info, 0, NULL},
+};
 #endif
 
 int radeon_debugfs_ib_init(struct radeon_device *rdev)
 {
 #if defined(CONFIG_DEBUG_FS)
 	unsigned i;
+	int r;
 
+	radeon_debugfs_ib_bogus_info_list[0].data = rdev;
+	r = radeon_debugfs_add_files(rdev, radeon_debugfs_ib_bogus_info_list, 1);
+	if (r)
+		return r;
 	for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
 		sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i);
 		radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i];
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index 067167c..40ab6d9 100644
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ b/drivers/gpu/drm/radeon/radeon_state.c
@@ -29,6 +29,7 @@
 
 #include "drmP.h"
 #include "drm.h"
+#include "drm_buffer.h"
 #include "drm_sarea.h"
 #include "radeon_drm.h"
 #include "radeon_drv.h"
@@ -91,21 +92,27 @@
 static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
 						     dev_priv,
 						     struct drm_file *file_priv,
-						     int id, u32 *data)
+						     int id, struct drm_buffer *buf)
 {
+	u32 *data;
 	switch (id) {
 
 	case RADEON_EMIT_PP_MISC:
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-		    &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
+		data = drm_buffer_pointer_to_dword(buf,
+			(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4);
+
+		if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
 			DRM_ERROR("Invalid depth buffer offset\n");
 			return -EINVAL;
 		}
+		dev_priv->have_z_offset = 1;
 		break;
 
 	case RADEON_EMIT_PP_CNTL:
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-		    &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
+		data = drm_buffer_pointer_to_dword(buf,
+			(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4);
+
+		if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
 			DRM_ERROR("Invalid colour buffer offset\n");
 			return -EINVAL;
 		}
@@ -117,8 +124,8 @@
 	case R200_EMIT_PP_TXOFFSET_3:
 	case R200_EMIT_PP_TXOFFSET_4:
 	case R200_EMIT_PP_TXOFFSET_5:
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-						  &data[0])) {
+		data = drm_buffer_pointer_to_dword(buf, 0);
+		if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
 			DRM_ERROR("Invalid R200 texture offset\n");
 			return -EINVAL;
 		}
@@ -127,8 +134,9 @@
 	case RADEON_EMIT_PP_TXFILTER_0:
 	case RADEON_EMIT_PP_TXFILTER_1:
 	case RADEON_EMIT_PP_TXFILTER_2:
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-		    &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
+		data = drm_buffer_pointer_to_dword(buf,
+			(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4);
+		if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) {
 			DRM_ERROR("Invalid R100 texture offset\n");
 			return -EINVAL;
 		}
@@ -142,9 +150,10 @@
 	case R200_EMIT_PP_CUBIC_OFFSETS_5:{
 			int i;
 			for (i = 0; i < 5; i++) {
+				data = drm_buffer_pointer_to_dword(buf, i);
 				if (radeon_check_and_fixup_offset(dev_priv,
 								  file_priv,
-								  &data[i])) {
+								  data)) {
 					DRM_ERROR
 					    ("Invalid R200 cubic texture offset\n");
 					return -EINVAL;
@@ -158,9 +167,10 @@
 	case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
 			int i;
 			for (i = 0; i < 5; i++) {
+				data = drm_buffer_pointer_to_dword(buf, i);
 				if (radeon_check_and_fixup_offset(dev_priv,
 								  file_priv,
-								  &data[i])) {
+								  data)) {
 					DRM_ERROR
 					    ("Invalid R100 cubic texture offset\n");
 					return -EINVAL;
@@ -269,23 +279,24 @@
 						     cmdbuf,
 						     unsigned int *cmdsz)
 {
-	u32 *cmd = (u32 *) cmdbuf->buf;
+	u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0);
 	u32 offset, narrays;
 	int count, i, k;
 
-	*cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+	count = ((*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+	*cmdsz = 2 + count;
 
-	if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
+	if ((*cmd & 0xc0000000) != RADEON_CP_PACKET3) {
 		DRM_ERROR("Not a type 3 packet\n");
 		return -EINVAL;
 	}
 
-	if (4 * *cmdsz > cmdbuf->bufsz) {
+	if (4 * *cmdsz > drm_buffer_unprocessed(cmdbuf->buffer)) {
 		DRM_ERROR("Packet size larger than size of data provided\n");
 		return -EINVAL;
 	}
 
-	switch(cmd[0] & 0xff00) {
+	switch (*cmd & 0xff00) {
 	/* XXX Are there old drivers needing other packets? */
 
 	case RADEON_3D_DRAW_IMMD:
@@ -312,7 +323,6 @@
 		break;
 
 	case RADEON_3D_LOAD_VBPNTR:
-		count = (cmd[0] >> 16) & 0x3fff;
 
 		if (count > 18) { /* 12 arrays max */
 			DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
@@ -321,13 +331,16 @@
 		}
 
 		/* carefully check packet contents */
-		narrays = cmd[1] & ~0xc000;
+		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
+
+		narrays = *cmd & ~0xc000;
 		k = 0;
 		i = 2;
 		while ((k < narrays) && (i < (count + 2))) {
 			i++;		/* skip attribute field */
+			cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
 			if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-							  &cmd[i])) {
+							  cmd)) {
 				DRM_ERROR
 				    ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
 				     k, i);
@@ -338,8 +351,10 @@
 			if (k == narrays)
 				break;
 			/* have one more to process, they come in pairs */
+			cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i);
+
 			if (radeon_check_and_fixup_offset(dev_priv,
-							  file_priv, &cmd[i]))
+							  file_priv, cmd))
 			{
 				DRM_ERROR
 				    ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
@@ -363,7 +378,9 @@
 			DRM_ERROR("Invalid 3d packet for r200-class chip\n");
 			return -EINVAL;
 		}
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) {
+
+		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
+		if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
 				DRM_ERROR("Invalid rndr_gen_indx offset\n");
 				return -EINVAL;
 		}
@@ -374,12 +391,15 @@
 			DRM_ERROR("Invalid 3d packet for r100-class chip\n");
 			return -EINVAL;
 		}
-		if ((cmd[1] & 0x8000ffff) != 0x80000810) {
-			DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+
+		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
+		if ((*cmd & 0x8000ffff) != 0x80000810) {
+			DRM_ERROR("Invalid indx_buffer reg address %08X\n", *cmd);
 			return -EINVAL;
 		}
-		if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) {
-			DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
+		if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) {
+			DRM_ERROR("Invalid indx_buffer offset is %08X\n", *cmd);
 			return -EINVAL;
 		}
 		break;
@@ -388,31 +408,34 @@
 	case RADEON_CNTL_PAINT_MULTI:
 	case RADEON_CNTL_BITBLT_MULTI:
 		/* MSB of opcode: next DWORD GUI_CNTL */
-		if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+		cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1);
+		if (*cmd & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
 			      | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-			offset = cmd[2] << 10;
+			u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2);
+			offset = *cmd2 << 10;
 			if (radeon_check_and_fixup_offset
 			    (dev_priv, file_priv, &offset)) {
 				DRM_ERROR("Invalid first packet offset\n");
 				return -EINVAL;
 			}
-			cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
+			*cmd2 = (*cmd2 & 0xffc00000) | offset >> 10;
 		}
 
-		if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
-		    (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-			offset = cmd[3] << 10;
+		if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
+		    (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+			u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
+			offset = *cmd << 10;
 			if (radeon_check_and_fixup_offset
 			    (dev_priv, file_priv, &offset)) {
 				DRM_ERROR("Invalid second packet offset\n");
 				return -EINVAL;
 			}
-			cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
+			*cmd3 = (*cmd3 & 0xffc00000) | offset >> 10;
 		}
 		break;
 
 	default:
-		DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
+		DRM_ERROR("Invalid packet type %x\n", *cmd & 0xff00);
 		return -EINVAL;
 	}
 
@@ -876,6 +899,11 @@
 		if (tmp & RADEON_BACK)
 			flags |= RADEON_FRONT;
 	}
+	if (flags & (RADEON_DEPTH|RADEON_STENCIL)) {
+		if (!dev_priv->have_z_offset)
+			printk_once(KERN_ERR "radeon: illegal depth clear request. Buggy mesa detected - please update.\n");
+		flags &= ~(RADEON_DEPTH | RADEON_STENCIL);
+	}
 
 	if (flags & (RADEON_FRONT | RADEON_BACK)) {
 
@@ -1065,7 +1093,7 @@
 					/* judging by the first tile offset needed, could possibly
 					   directly address/clear 4x4 tiles instead of 8x2 * 4x4
 					   macro tiles, though would still need clear mask for
-					   right/bottom if truely 4x4 granularity is desired ? */
+					   right/bottom if truly 4x4 granularity is desired ? */
 					OUT_RING(tileoffset * 16);
 					/* the number of tiles to clear */
 					OUT_RING(nrtilesx + 1);
@@ -2611,7 +2639,6 @@
 {
 	int id = (int)header.packet.packet_id;
 	int sz, reg;
-	int *data = (int *)cmdbuf->buf;
 	RING_LOCALS;
 
 	if (id >= RADEON_MAX_STATE_PACKETS)
@@ -2620,23 +2647,22 @@
 	sz = packet[id].len;
 	reg = packet[id].start;
 
-	if (sz * sizeof(int) > cmdbuf->bufsz) {
+	if (sz * sizeof(u32) > drm_buffer_unprocessed(cmdbuf->buffer)) {
 		DRM_ERROR("Packet size provided larger than data provided\n");
 		return -EINVAL;
 	}
 
-	if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) {
+	if (radeon_check_and_fixup_packets(dev_priv, file_priv, id,
+				cmdbuf->buffer)) {
 		DRM_ERROR("Packet verification failed\n");
 		return -EINVAL;
 	}
 
 	BEGIN_RING(sz + 1);
 	OUT_RING(CP_PACKET0(reg, (sz - 1)));
-	OUT_RING_TABLE(data, sz);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
 	ADVANCE_RING();
 
-	cmdbuf->buf += sz * sizeof(int);
-	cmdbuf->bufsz -= sz * sizeof(int);
 	return 0;
 }
 
@@ -2653,10 +2679,8 @@
 	OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
 	OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
 	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
-	OUT_RING_TABLE(cmdbuf->buf, sz);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
 	ADVANCE_RING();
-	cmdbuf->buf += sz * sizeof(int);
-	cmdbuf->bufsz -= sz * sizeof(int);
 	return 0;
 }
 
@@ -2675,10 +2699,8 @@
 	OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
 	OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
 	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
-	OUT_RING_TABLE(cmdbuf->buf, sz);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
 	ADVANCE_RING();
-	cmdbuf->buf += sz * sizeof(int);
-	cmdbuf->bufsz -= sz * sizeof(int);
 	return 0;
 }
 
@@ -2696,11 +2718,9 @@
 	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
 	OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
 	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
-	OUT_RING_TABLE(cmdbuf->buf, sz);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
 	ADVANCE_RING();
 
-	cmdbuf->buf += sz * sizeof(int);
-	cmdbuf->bufsz -= sz * sizeof(int);
 	return 0;
 }
 
@@ -2714,7 +2734,7 @@
 
         if (!sz)
                 return 0;
-        if (sz * 4 > cmdbuf->bufsz)
+	if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer))
                 return -EINVAL;
 
 	BEGIN_RING(5 + sz);
@@ -2722,11 +2742,9 @@
 	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
 	OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
 	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
-	OUT_RING_TABLE(cmdbuf->buf, sz);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz);
 	ADVANCE_RING();
 
-	cmdbuf->buf += sz * sizeof(int);
-	cmdbuf->bufsz -= sz * sizeof(int);
 	return 0;
 }
 
@@ -2748,11 +2766,9 @@
 	}
 
 	BEGIN_RING(cmdsz);
-	OUT_RING_TABLE(cmdbuf->buf, cmdsz);
+	OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
 	ADVANCE_RING();
 
-	cmdbuf->buf += cmdsz * 4;
-	cmdbuf->bufsz -= cmdsz * 4;
 	return 0;
 }
 
@@ -2805,16 +2821,16 @@
 		}
 
 		BEGIN_RING(cmdsz);
-		OUT_RING_TABLE(cmdbuf->buf, cmdsz);
+		OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz);
 		ADVANCE_RING();
 
 	} while (++i < cmdbuf->nbox);
 	if (cmdbuf->nbox == 1)
 		cmdbuf->nbox = 0;
 
+	return 0;
       out:
-	cmdbuf->buf += cmdsz * 4;
-	cmdbuf->bufsz -= cmdsz * 4;
+	drm_buffer_advance(cmdbuf->buffer, cmdsz * 4);
 	return 0;
 }
 
@@ -2847,16 +2863,16 @@
 	return 0;
 }
 
-static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv)
+static int radeon_cp_cmdbuf(struct drm_device *dev, void *data,
+		struct drm_file *file_priv)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_buf *buf = NULL;
+	drm_radeon_cmd_header_t stack_header;
 	int idx;
 	drm_radeon_kcmd_buffer_t *cmdbuf = data;
-	drm_radeon_cmd_header_t header;
-	int orig_nbox, orig_bufsz;
-	char *kbuf = NULL;
+	int orig_nbox;
 
 	LOCK_TEST_WITH_RETURN(dev, file_priv);
 
@@ -2871,17 +2887,16 @@
 	 * races between checking values and using those values in other code,
 	 * and simply to avoid a lot of function calls to copy in data.
 	 */
-	orig_bufsz = cmdbuf->bufsz;
-	if (orig_bufsz != 0) {
-		kbuf = kmalloc(cmdbuf->bufsz, GFP_KERNEL);
-		if (kbuf == NULL)
-			return -ENOMEM;
-		if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf,
-				       cmdbuf->bufsz)) {
-			kfree(kbuf);
-			return -EFAULT;
-		}
-		cmdbuf->buf = kbuf;
+	if (cmdbuf->bufsz != 0) {
+		int rv;
+		void __user *buffer = cmdbuf->buffer;
+		rv = drm_buffer_alloc(&cmdbuf->buffer, cmdbuf->bufsz);
+		if (rv)
+			return rv;
+		rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer,
+						cmdbuf->bufsz);
+		if (rv)
+			return rv;
 	}
 
 	orig_nbox = cmdbuf->nbox;
@@ -2890,24 +2905,24 @@
 		int temp;
 		temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
 
-		if (orig_bufsz != 0)
-			kfree(kbuf);
+		if (cmdbuf->bufsz != 0)
+			drm_buffer_free(cmdbuf->buffer);
 
 		return temp;
 	}
 
 	/* microcode_version != r300 */
-	while (cmdbuf->bufsz >= sizeof(header)) {
+	while (drm_buffer_unprocessed(cmdbuf->buffer) >= sizeof(stack_header)) {
 
-		header.i = *(int *)cmdbuf->buf;
-		cmdbuf->buf += sizeof(header);
-		cmdbuf->bufsz -= sizeof(header);
+		drm_radeon_cmd_header_t *header;
+		header = drm_buffer_read_object(cmdbuf->buffer,
+				sizeof(stack_header), &stack_header);
 
-		switch (header.header.cmd_type) {
+		switch (header->header.cmd_type) {
 		case RADEON_CMD_PACKET:
 			DRM_DEBUG("RADEON_CMD_PACKET\n");
 			if (radeon_emit_packets
-			    (dev_priv, file_priv, header, cmdbuf)) {
+			    (dev_priv, file_priv, *header, cmdbuf)) {
 				DRM_ERROR("radeon_emit_packets failed\n");
 				goto err;
 			}
@@ -2915,7 +2930,7 @@
 
 		case RADEON_CMD_SCALARS:
 			DRM_DEBUG("RADEON_CMD_SCALARS\n");
-			if (radeon_emit_scalars(dev_priv, header, cmdbuf)) {
+			if (radeon_emit_scalars(dev_priv, *header, cmdbuf)) {
 				DRM_ERROR("radeon_emit_scalars failed\n");
 				goto err;
 			}
@@ -2923,7 +2938,7 @@
 
 		case RADEON_CMD_VECTORS:
 			DRM_DEBUG("RADEON_CMD_VECTORS\n");
-			if (radeon_emit_vectors(dev_priv, header, cmdbuf)) {
+			if (radeon_emit_vectors(dev_priv, *header, cmdbuf)) {
 				DRM_ERROR("radeon_emit_vectors failed\n");
 				goto err;
 			}
@@ -2931,7 +2946,7 @@
 
 		case RADEON_CMD_DMA_DISCARD:
 			DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
-			idx = header.dma.buf_idx;
+			idx = header->dma.buf_idx;
 			if (idx < 0 || idx >= dma->buf_count) {
 				DRM_ERROR("buffer index %d (of %d max)\n",
 					  idx, dma->buf_count - 1);
@@ -2968,7 +2983,7 @@
 
 		case RADEON_CMD_SCALARS2:
 			DRM_DEBUG("RADEON_CMD_SCALARS2\n");
-			if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) {
+			if (radeon_emit_scalars2(dev_priv, *header, cmdbuf)) {
 				DRM_ERROR("radeon_emit_scalars2 failed\n");
 				goto err;
 			}
@@ -2976,37 +2991,37 @@
 
 		case RADEON_CMD_WAIT:
 			DRM_DEBUG("RADEON_CMD_WAIT\n");
-			if (radeon_emit_wait(dev, header.wait.flags)) {
+			if (radeon_emit_wait(dev, header->wait.flags)) {
 				DRM_ERROR("radeon_emit_wait failed\n");
 				goto err;
 			}
 			break;
 		case RADEON_CMD_VECLINEAR:
 			DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
-			if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) {
+			if (radeon_emit_veclinear(dev_priv, *header, cmdbuf)) {
 				DRM_ERROR("radeon_emit_veclinear failed\n");
 				goto err;
 			}
 			break;
 
 		default:
-			DRM_ERROR("bad cmd_type %d at %p\n",
-				  header.header.cmd_type,
-				  cmdbuf->buf - sizeof(header));
+			DRM_ERROR("bad cmd_type %d at byte %d\n",
+				  header->header.cmd_type,
+				  cmdbuf->buffer->iterator);
 			goto err;
 		}
 	}
 
-	if (orig_bufsz != 0)
-		kfree(kbuf);
+	if (cmdbuf->bufsz != 0)
+		drm_buffer_free(cmdbuf->buffer);
 
 	DRM_DEBUG("DONE\n");
 	COMMIT_RING();
 	return 0;
 
       err:
-	if (orig_bufsz != 0)
-		kfree(kbuf);
+	if (cmdbuf->bufsz != 0)
+		drm_buffer_free(cmdbuf->buffer);
 	return -EINVAL;
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c
index 9f5e2f9..313c96b 100644
--- a/drivers/gpu/drm/radeon/radeon_test.c
+++ b/drivers/gpu/drm/radeon/radeon_test.c
@@ -186,7 +186,7 @@
 		radeon_bo_kunmap(gtt_obj[i]);
 
 		DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n",
-			 gtt_addr - rdev->mc.gtt_location);
+			 gtt_addr - rdev->mc.gtt_start);
 	}
 
 out_cleanup:
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 58b5adf..43c5ab3 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -150,7 +150,7 @@
 		man->default_caching = TTM_PL_FLAG_CACHED;
 		break;
 	case TTM_PL_TT:
-		man->gpu_offset = rdev->mc.gtt_location;
+		man->gpu_offset = rdev->mc.gtt_start;
 		man->available_caching = TTM_PL_MASK_CACHING;
 		man->default_caching = TTM_PL_FLAG_CACHED;
 		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA;
@@ -180,7 +180,7 @@
 		break;
 	case TTM_PL_VRAM:
 		/* "On-card" video ram */
-		man->gpu_offset = rdev->mc.vram_location;
+		man->gpu_offset = rdev->mc.vram_start;
 		man->flags = TTM_MEMTYPE_FLAG_FIXED |
 			     TTM_MEMTYPE_FLAG_NEEDS_IOREMAP |
 			     TTM_MEMTYPE_FLAG_MAPPABLE;
@@ -262,10 +262,10 @@
 
 	switch (old_mem->mem_type) {
 	case TTM_PL_VRAM:
-		old_start += rdev->mc.vram_location;
+		old_start += rdev->mc.vram_start;
 		break;
 	case TTM_PL_TT:
-		old_start += rdev->mc.gtt_location;
+		old_start += rdev->mc.gtt_start;
 		break;
 	default:
 		DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
@@ -273,10 +273,10 @@
 	}
 	switch (new_mem->mem_type) {
 	case TTM_PL_VRAM:
-		new_start += rdev->mc.vram_location;
+		new_start += rdev->mc.vram_start;
 		break;
 	case TTM_PL_TT:
-		new_start += rdev->mc.gtt_location;
+		new_start += rdev->mc.gtt_start;
 		break;
 	default:
 		DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600
new file mode 100644
index 0000000..8f414a5
--- /dev/null
+++ b/drivers/gpu/drm/radeon/reg_srcs/r600
@@ -0,0 +1,837 @@
+r600 0x9400
+0x000287A0 R7xx_CB_SHADER_CONTROL
+0x00028230 R7xx_PA_SC_EDGERULE
+0x000286C8 R7xx_SPI_THREAD_GROUPING
+0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
+0x000088C4 VGT_CACHE_INVALIDATION
+0x00028A50 VGT_ENHANCE
+0x000088CC VGT_ES_PER_GS
+0x00028A2C VGT_GROUP_DECR
+0x00028A28 VGT_GROUP_FIRST_DECR
+0x00028A24 VGT_GROUP_PRIM_TYPE
+0x00028A30 VGT_GROUP_VECT_0_CNTL
+0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL
+0x00028A34 VGT_GROUP_VECT_1_CNTL
+0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL
+0x00028A40 VGT_GS_MODE
+0x00028A6C VGT_GS_OUT_PRIM_TYPE
+0x000088C8 VGT_GS_PER_ES
+0x000088E8 VGT_GS_PER_VS
+0x000088D4 VGT_GS_VERTEX_REUSE
+0x00028A14 VGT_HOS_CNTL
+0x00028A18 VGT_HOS_MAX_TESS_LEVEL
+0x00028A1C VGT_HOS_MIN_TESS_LEVEL
+0x00028A20 VGT_HOS_REUSE_DEPTH
+0x0000895C VGT_INDEX_TYPE
+0x00028408 VGT_INDX_OFFSET
+0x00028AA0 VGT_INSTANCE_STEP_RATE_0
+0x00028AA4 VGT_INSTANCE_STEP_RATE_1
+0x000088C0 VGT_LAST_COPY_STATE
+0x00028400 VGT_MAX_VTX_INDX
+0x000088D8 VGT_MC_LAT_CNTL
+0x00028404 VGT_MIN_VTX_INDX
+0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN
+0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX
+0x00008970 VGT_NUM_INDICES
+0x00008974 VGT_NUM_INSTANCES
+0x00028A10 VGT_OUTPUT_PATH_CNTL
+0x00028C5C VGT_OUT_DEALLOC_CNTL
+0x00028A84 VGT_PRIMITIVEID_EN
+0x00008958 VGT_PRIMITIVE_TYPE
+0x00028AB4 VGT_REUSE_OFF
+0x00028C58 VGT_VERTEX_REUSE_BLOCK_CNTL
+0x00028AB8 VGT_VTX_CNT_EN
+0x000088B0 VGT_VTX_VECT_EJECT_REG
+0x00028810 PA_CL_CLIP_CNTL
+0x00008A14 PA_CL_ENHANCE
+0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
+0x00028C18 PA_CL_GB_HORZ_DISC_ADJ
+0x00028C0C PA_CL_GB_VERT_CLIP_ADJ
+0x00028C10 PA_CL_GB_VERT_DISC_ADJ
+0x00028820 PA_CL_NANINF_CNTL
+0x00028E1C PA_CL_POINT_CULL_RAD
+0x00028E18 PA_CL_POINT_SIZE
+0x00028E10 PA_CL_POINT_X_RAD
+0x00028E14 PA_CL_POINT_Y_RAD
+0x00028E2C PA_CL_UCP_0_W
+0x00028E3C PA_CL_UCP_1_W
+0x00028E4C PA_CL_UCP_2_W
+0x00028E5C PA_CL_UCP_3_W
+0x00028E6C PA_CL_UCP_4_W
+0x00028E7C PA_CL_UCP_5_W
+0x00028E20 PA_CL_UCP_0_X
+0x00028E30 PA_CL_UCP_1_X
+0x00028E40 PA_CL_UCP_2_X
+0x00028E50 PA_CL_UCP_3_X
+0x00028E60 PA_CL_UCP_4_X
+0x00028E70 PA_CL_UCP_5_X
+0x00028E24 PA_CL_UCP_0_Y
+0x00028E34 PA_CL_UCP_1_Y
+0x00028E44 PA_CL_UCP_2_Y
+0x00028E54 PA_CL_UCP_3_Y
+0x00028E64 PA_CL_UCP_4_Y
+0x00028E74 PA_CL_UCP_5_Y
+0x00028E28 PA_CL_UCP_0_Z
+0x00028E38 PA_CL_UCP_1_Z
+0x00028E48 PA_CL_UCP_2_Z
+0x00028E58 PA_CL_UCP_3_Z
+0x00028E68 PA_CL_UCP_4_Z
+0x00028E78 PA_CL_UCP_5_Z
+0x00028440 PA_CL_VPORT_XOFFSET_0
+0x00028458 PA_CL_VPORT_XOFFSET_1
+0x00028470 PA_CL_VPORT_XOFFSET_2
+0x00028488 PA_CL_VPORT_XOFFSET_3
+0x000284A0 PA_CL_VPORT_XOFFSET_4
+0x000284B8 PA_CL_VPORT_XOFFSET_5
+0x000284D0 PA_CL_VPORT_XOFFSET_6
+0x000284E8 PA_CL_VPORT_XOFFSET_7
+0x00028500 PA_CL_VPORT_XOFFSET_8
+0x00028518 PA_CL_VPORT_XOFFSET_9
+0x00028530 PA_CL_VPORT_XOFFSET_10
+0x00028548 PA_CL_VPORT_XOFFSET_11
+0x00028560 PA_CL_VPORT_XOFFSET_12
+0x00028578 PA_CL_VPORT_XOFFSET_13
+0x00028590 PA_CL_VPORT_XOFFSET_14
+0x000285A8 PA_CL_VPORT_XOFFSET_15
+0x0002843C PA_CL_VPORT_XSCALE_0
+0x00028454 PA_CL_VPORT_XSCALE_1
+0x0002846C PA_CL_VPORT_XSCALE_2
+0x00028484 PA_CL_VPORT_XSCALE_3
+0x0002849C PA_CL_VPORT_XSCALE_4
+0x000284B4 PA_CL_VPORT_XSCALE_5
+0x000284CC PA_CL_VPORT_XSCALE_6
+0x000284E4 PA_CL_VPORT_XSCALE_7
+0x000284FC PA_CL_VPORT_XSCALE_8
+0x00028514 PA_CL_VPORT_XSCALE_9
+0x0002852C PA_CL_VPORT_XSCALE_10
+0x00028544 PA_CL_VPORT_XSCALE_11
+0x0002855C PA_CL_VPORT_XSCALE_12
+0x00028574 PA_CL_VPORT_XSCALE_13
+0x0002858C PA_CL_VPORT_XSCALE_14
+0x000285A4 PA_CL_VPORT_XSCALE_15
+0x00028448 PA_CL_VPORT_YOFFSET_0
+0x00028460 PA_CL_VPORT_YOFFSET_1
+0x00028478 PA_CL_VPORT_YOFFSET_2
+0x00028490 PA_CL_VPORT_YOFFSET_3
+0x000284A8 PA_CL_VPORT_YOFFSET_4
+0x000284C0 PA_CL_VPORT_YOFFSET_5
+0x000284D8 PA_CL_VPORT_YOFFSET_6
+0x000284F0 PA_CL_VPORT_YOFFSET_7
+0x00028508 PA_CL_VPORT_YOFFSET_8
+0x00028520 PA_CL_VPORT_YOFFSET_9
+0x00028538 PA_CL_VPORT_YOFFSET_10
+0x00028550 PA_CL_VPORT_YOFFSET_11
+0x00028568 PA_CL_VPORT_YOFFSET_12
+0x00028580 PA_CL_VPORT_YOFFSET_13
+0x00028598 PA_CL_VPORT_YOFFSET_14
+0x000285B0 PA_CL_VPORT_YOFFSET_15
+0x00028444 PA_CL_VPORT_YSCALE_0
+0x0002845C PA_CL_VPORT_YSCALE_1
+0x00028474 PA_CL_VPORT_YSCALE_2
+0x0002848C PA_CL_VPORT_YSCALE_3
+0x000284A4 PA_CL_VPORT_YSCALE_4
+0x000284BC PA_CL_VPORT_YSCALE_5
+0x000284D4 PA_CL_VPORT_YSCALE_6
+0x000284EC PA_CL_VPORT_YSCALE_7
+0x00028504 PA_CL_VPORT_YSCALE_8
+0x0002851C PA_CL_VPORT_YSCALE_9
+0x00028534 PA_CL_VPORT_YSCALE_10
+0x0002854C PA_CL_VPORT_YSCALE_11
+0x00028564 PA_CL_VPORT_YSCALE_12
+0x0002857C PA_CL_VPORT_YSCALE_13
+0x00028594 PA_CL_VPORT_YSCALE_14
+0x000285AC PA_CL_VPORT_YSCALE_15
+0x00028450 PA_CL_VPORT_ZOFFSET_0
+0x00028468 PA_CL_VPORT_ZOFFSET_1
+0x00028480 PA_CL_VPORT_ZOFFSET_2
+0x00028498 PA_CL_VPORT_ZOFFSET_3
+0x000284B0 PA_CL_VPORT_ZOFFSET_4
+0x000284C8 PA_CL_VPORT_ZOFFSET_5
+0x000284E0 PA_CL_VPORT_ZOFFSET_6
+0x000284F8 PA_CL_VPORT_ZOFFSET_7
+0x00028510 PA_CL_VPORT_ZOFFSET_8
+0x00028528 PA_CL_VPORT_ZOFFSET_9
+0x00028540 PA_CL_VPORT_ZOFFSET_10
+0x00028558 PA_CL_VPORT_ZOFFSET_11
+0x00028570 PA_CL_VPORT_ZOFFSET_12
+0x00028588 PA_CL_VPORT_ZOFFSET_13
+0x000285A0 PA_CL_VPORT_ZOFFSET_14
+0x000285B8 PA_CL_VPORT_ZOFFSET_15
+0x0002844C PA_CL_VPORT_ZSCALE_0
+0x00028464 PA_CL_VPORT_ZSCALE_1
+0x0002847C PA_CL_VPORT_ZSCALE_2
+0x00028494 PA_CL_VPORT_ZSCALE_3
+0x000284AC PA_CL_VPORT_ZSCALE_4
+0x000284C4 PA_CL_VPORT_ZSCALE_5
+0x000284DC PA_CL_VPORT_ZSCALE_6
+0x000284F4 PA_CL_VPORT_ZSCALE_7
+0x0002850C PA_CL_VPORT_ZSCALE_8
+0x00028524 PA_CL_VPORT_ZSCALE_9
+0x0002853C PA_CL_VPORT_ZSCALE_10
+0x00028554 PA_CL_VPORT_ZSCALE_11
+0x0002856C PA_CL_VPORT_ZSCALE_12
+0x00028584 PA_CL_VPORT_ZSCALE_13
+0x0002859C PA_CL_VPORT_ZSCALE_14
+0x000285B4 PA_CL_VPORT_ZSCALE_15
+0x0002881C PA_CL_VS_OUT_CNTL
+0x00028818 PA_CL_VTE_CNTL
+0x00028C48 PA_SC_AA_MASK
+0x00008B40 PA_SC_AA_SAMPLE_LOCS_2S
+0x00008B44 PA_SC_AA_SAMPLE_LOCS_4S
+0x00008B48 PA_SC_AA_SAMPLE_LOCS_8S_WD0
+0x00008B4C PA_SC_AA_SAMPLE_LOCS_8S_WD1
+0x00028C20 PA_SC_AA_SAMPLE_LOCS_8S_WD1_MCTX
+0x00028C1C PA_SC_AA_SAMPLE_LOCS_MCTX
+0x00028214 PA_SC_CLIPRECT_0_BR
+0x0002821C PA_SC_CLIPRECT_1_BR
+0x00028224 PA_SC_CLIPRECT_2_BR
+0x0002822C PA_SC_CLIPRECT_3_BR
+0x00028210 PA_SC_CLIPRECT_0_TL
+0x00028218 PA_SC_CLIPRECT_1_TL
+0x00028220 PA_SC_CLIPRECT_2_TL
+0x00028228 PA_SC_CLIPRECT_3_TL
+0x0002820C PA_SC_CLIPRECT_RULE
+0x00008BF0 PA_SC_ENHANCE
+0x00028244 PA_SC_GENERIC_SCISSOR_BR
+0x00028240 PA_SC_GENERIC_SCISSOR_TL
+0x00028C00 PA_SC_LINE_CNTL
+0x00028A0C PA_SC_LINE_STIPPLE
+0x00008B10 PA_SC_LINE_STIPPLE_STATE
+0x00028A4C PA_SC_MODE_CNTL
+0x00028A48 PA_SC_MPASS_PS_CNTL
+0x00008B20 PA_SC_MULTI_CHIP_CNTL
+0x00028034 PA_SC_SCREEN_SCISSOR_BR
+0x00028030 PA_SC_SCREEN_SCISSOR_TL
+0x00028254 PA_SC_VPORT_SCISSOR_0_BR
+0x0002825C PA_SC_VPORT_SCISSOR_1_BR
+0x00028264 PA_SC_VPORT_SCISSOR_2_BR
+0x0002826C PA_SC_VPORT_SCISSOR_3_BR
+0x00028274 PA_SC_VPORT_SCISSOR_4_BR
+0x0002827C PA_SC_VPORT_SCISSOR_5_BR
+0x00028284 PA_SC_VPORT_SCISSOR_6_BR
+0x0002828C PA_SC_VPORT_SCISSOR_7_BR
+0x00028294 PA_SC_VPORT_SCISSOR_8_BR
+0x0002829C PA_SC_VPORT_SCISSOR_9_BR
+0x000282A4 PA_SC_VPORT_SCISSOR_10_BR
+0x000282AC PA_SC_VPORT_SCISSOR_11_BR
+0x000282B4 PA_SC_VPORT_SCISSOR_12_BR
+0x000282BC PA_SC_VPORT_SCISSOR_13_BR
+0x000282C4 PA_SC_VPORT_SCISSOR_14_BR
+0x000282CC PA_SC_VPORT_SCISSOR_15_BR
+0x00028250 PA_SC_VPORT_SCISSOR_0_TL
+0x00028258 PA_SC_VPORT_SCISSOR_1_TL
+0x00028260 PA_SC_VPORT_SCISSOR_2_TL
+0x00028268 PA_SC_VPORT_SCISSOR_3_TL
+0x00028270 PA_SC_VPORT_SCISSOR_4_TL
+0x00028278 PA_SC_VPORT_SCISSOR_5_TL
+0x00028280 PA_SC_VPORT_SCISSOR_6_TL
+0x00028288 PA_SC_VPORT_SCISSOR_7_TL
+0x00028290 PA_SC_VPORT_SCISSOR_8_TL
+0x00028298 PA_SC_VPORT_SCISSOR_9_TL
+0x000282A0 PA_SC_VPORT_SCISSOR_10_TL
+0x000282A8 PA_SC_VPORT_SCISSOR_11_TL
+0x000282B0 PA_SC_VPORT_SCISSOR_12_TL
+0x000282B8 PA_SC_VPORT_SCISSOR_13_TL
+0x000282C0 PA_SC_VPORT_SCISSOR_14_TL
+0x000282C8 PA_SC_VPORT_SCISSOR_15_TL
+0x000282D4 PA_SC_VPORT_ZMAX_0
+0x000282DC PA_SC_VPORT_ZMAX_1
+0x000282E4 PA_SC_VPORT_ZMAX_2
+0x000282EC PA_SC_VPORT_ZMAX_3
+0x000282F4 PA_SC_VPORT_ZMAX_4
+0x000282FC PA_SC_VPORT_ZMAX_5
+0x00028304 PA_SC_VPORT_ZMAX_6
+0x0002830C PA_SC_VPORT_ZMAX_7
+0x00028314 PA_SC_VPORT_ZMAX_8
+0x0002831C PA_SC_VPORT_ZMAX_9
+0x00028324 PA_SC_VPORT_ZMAX_10
+0x0002832C PA_SC_VPORT_ZMAX_11
+0x00028334 PA_SC_VPORT_ZMAX_12
+0x0002833C PA_SC_VPORT_ZMAX_13
+0x00028344 PA_SC_VPORT_ZMAX_14
+0x0002834C PA_SC_VPORT_ZMAX_15
+0x000282D0 PA_SC_VPORT_ZMIN_0
+0x000282D8 PA_SC_VPORT_ZMIN_1
+0x000282E0 PA_SC_VPORT_ZMIN_2
+0x000282E8 PA_SC_VPORT_ZMIN_3
+0x000282F0 PA_SC_VPORT_ZMIN_4
+0x000282F8 PA_SC_VPORT_ZMIN_5
+0x00028300 PA_SC_VPORT_ZMIN_6
+0x00028308 PA_SC_VPORT_ZMIN_7
+0x00028310 PA_SC_VPORT_ZMIN_8
+0x00028318 PA_SC_VPORT_ZMIN_9
+0x00028320 PA_SC_VPORT_ZMIN_10
+0x00028328 PA_SC_VPORT_ZMIN_11
+0x00028330 PA_SC_VPORT_ZMIN_12
+0x00028338 PA_SC_VPORT_ZMIN_13
+0x00028340 PA_SC_VPORT_ZMIN_14
+0x00028348 PA_SC_VPORT_ZMIN_15
+0x00028200 PA_SC_WINDOW_OFFSET
+0x00028208 PA_SC_WINDOW_SCISSOR_BR
+0x00028204 PA_SC_WINDOW_SCISSOR_TL
+0x00028A08 PA_SU_LINE_CNTL
+0x00028A04 PA_SU_POINT_MINMAX
+0x00028A00 PA_SU_POINT_SIZE
+0x00028E0C PA_SU_POLY_OFFSET_BACK_OFFSET
+0x00028E08 PA_SU_POLY_OFFSET_BACK_SCALE
+0x00028DFC PA_SU_POLY_OFFSET_CLAMP
+0x00028DF8 PA_SU_POLY_OFFSET_DB_FMT_CNTL
+0x00028E04 PA_SU_POLY_OFFSET_FRONT_OFFSET
+0x00028E00 PA_SU_POLY_OFFSET_FRONT_SCALE
+0x00028814 PA_SU_SC_MODE_CNTL
+0x00028C08 PA_SU_VTX_CNTL
+0x00008C00 SQ_CONFIG
+0x00008C04 SQ_GPR_RESOURCE_MGMT_1
+0x00008C08 SQ_GPR_RESOURCE_MGMT_2
+0x00008C10 SQ_STACK_RESOURCE_MGMT_1
+0x00008C14 SQ_STACK_RESOURCE_MGMT_2
+0x00008C0C SQ_THREAD_RESOURCE_MGMT
+0x00028380 SQ_VTX_SEMANTIC_0
+0x00028384 SQ_VTX_SEMANTIC_1
+0x00028388 SQ_VTX_SEMANTIC_2
+0x0002838C SQ_VTX_SEMANTIC_3
+0x00028390 SQ_VTX_SEMANTIC_4
+0x00028394 SQ_VTX_SEMANTIC_5
+0x00028398 SQ_VTX_SEMANTIC_6
+0x0002839C SQ_VTX_SEMANTIC_7
+0x000283A0 SQ_VTX_SEMANTIC_8
+0x000283A4 SQ_VTX_SEMANTIC_9
+0x000283A8 SQ_VTX_SEMANTIC_10
+0x000283AC SQ_VTX_SEMANTIC_11
+0x000283B0 SQ_VTX_SEMANTIC_12
+0x000283B4 SQ_VTX_SEMANTIC_13
+0x000283B8 SQ_VTX_SEMANTIC_14
+0x000283BC SQ_VTX_SEMANTIC_15
+0x000283C0 SQ_VTX_SEMANTIC_16
+0x000283C4 SQ_VTX_SEMANTIC_17
+0x000283C8 SQ_VTX_SEMANTIC_18
+0x000283CC SQ_VTX_SEMANTIC_19
+0x000283D0 SQ_VTX_SEMANTIC_20
+0x000283D4 SQ_VTX_SEMANTIC_21
+0x000283D8 SQ_VTX_SEMANTIC_22
+0x000283DC SQ_VTX_SEMANTIC_23
+0x000283E0 SQ_VTX_SEMANTIC_24
+0x000283E4 SQ_VTX_SEMANTIC_25
+0x000283E8 SQ_VTX_SEMANTIC_26
+0x000283EC SQ_VTX_SEMANTIC_27
+0x000283F0 SQ_VTX_SEMANTIC_28
+0x000283F4 SQ_VTX_SEMANTIC_29
+0x000283F8 SQ_VTX_SEMANTIC_30
+0x000283FC SQ_VTX_SEMANTIC_31
+0x000288E0 SQ_VTX_SEMANTIC_CLEAR
+0x0003CFF4 SQ_VTX_START_INST_LOC
+0x0003C000 SQ_TEX_SAMPLER_WORD0_0
+0x0003C004 SQ_TEX_SAMPLER_WORD1_0
+0x0003C008 SQ_TEX_SAMPLER_WORD2_0
+0x00030000 SQ_ALU_CONSTANT0_0
+0x00030004 SQ_ALU_CONSTANT1_0
+0x00030008 SQ_ALU_CONSTANT2_0
+0x0003000C SQ_ALU_CONSTANT3_0
+0x0003E380 SQ_BOOL_CONST_0
+0x0003E384 SQ_BOOL_CONST_1
+0x0003E388 SQ_BOOL_CONST_2
+0x0003E200 SQ_LOOP_CONST_0
+0x0003E200 SQ_LOOP_CONST_DX10_0
+0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0
+0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1
+0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2
+0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3
+0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4
+0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5
+0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6
+0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7
+0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8
+0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9
+0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10
+0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11
+0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12
+0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13
+0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14
+0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15
+0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0
+0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1
+0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2
+0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3
+0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4
+0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5
+0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6
+0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7
+0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8
+0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9
+0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10
+0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11
+0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12
+0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13
+0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14
+0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15
+0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0
+0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1
+0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2
+0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3
+0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4
+0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5
+0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6
+0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7
+0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8
+0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9
+0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10
+0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11
+0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12
+0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13
+0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14
+0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15
+0x000289C0 SQ_ALU_CONST_CACHE_GS_0
+0x000289C4 SQ_ALU_CONST_CACHE_GS_1
+0x000289C8 SQ_ALU_CONST_CACHE_GS_2
+0x000289CC SQ_ALU_CONST_CACHE_GS_3
+0x000289D0 SQ_ALU_CONST_CACHE_GS_4
+0x000289D4 SQ_ALU_CONST_CACHE_GS_5
+0x000289D8 SQ_ALU_CONST_CACHE_GS_6
+0x000289DC SQ_ALU_CONST_CACHE_GS_7
+0x000289E0 SQ_ALU_CONST_CACHE_GS_8
+0x000289E4 SQ_ALU_CONST_CACHE_GS_9
+0x000289E8 SQ_ALU_CONST_CACHE_GS_10
+0x000289EC SQ_ALU_CONST_CACHE_GS_11
+0x000289F0 SQ_ALU_CONST_CACHE_GS_12
+0x000289F4 SQ_ALU_CONST_CACHE_GS_13
+0x000289F8 SQ_ALU_CONST_CACHE_GS_14
+0x000289FC SQ_ALU_CONST_CACHE_GS_15
+0x00028940 SQ_ALU_CONST_CACHE_PS_0
+0x00028944 SQ_ALU_CONST_CACHE_PS_1
+0x00028948 SQ_ALU_CONST_CACHE_PS_2
+0x0002894C SQ_ALU_CONST_CACHE_PS_3
+0x00028950 SQ_ALU_CONST_CACHE_PS_4
+0x00028954 SQ_ALU_CONST_CACHE_PS_5
+0x00028958 SQ_ALU_CONST_CACHE_PS_6
+0x0002895C SQ_ALU_CONST_CACHE_PS_7
+0x00028960 SQ_ALU_CONST_CACHE_PS_8
+0x00028964 SQ_ALU_CONST_CACHE_PS_9
+0x00028968 SQ_ALU_CONST_CACHE_PS_10
+0x0002896C SQ_ALU_CONST_CACHE_PS_11
+0x00028970 SQ_ALU_CONST_CACHE_PS_12
+0x00028974 SQ_ALU_CONST_CACHE_PS_13
+0x00028978 SQ_ALU_CONST_CACHE_PS_14
+0x0002897C SQ_ALU_CONST_CACHE_PS_15
+0x00028980 SQ_ALU_CONST_CACHE_VS_0
+0x00028984 SQ_ALU_CONST_CACHE_VS_1
+0x00028988 SQ_ALU_CONST_CACHE_VS_2
+0x0002898C SQ_ALU_CONST_CACHE_VS_3
+0x00028990 SQ_ALU_CONST_CACHE_VS_4
+0x00028994 SQ_ALU_CONST_CACHE_VS_5
+0x00028998 SQ_ALU_CONST_CACHE_VS_6
+0x0002899C SQ_ALU_CONST_CACHE_VS_7
+0x000289A0 SQ_ALU_CONST_CACHE_VS_8
+0x000289A4 SQ_ALU_CONST_CACHE_VS_9
+0x000289A8 SQ_ALU_CONST_CACHE_VS_10
+0x000289AC SQ_ALU_CONST_CACHE_VS_11
+0x000289B0 SQ_ALU_CONST_CACHE_VS_12
+0x000289B4 SQ_ALU_CONST_CACHE_VS_13
+0x000289B8 SQ_ALU_CONST_CACHE_VS_14
+0x000289BC SQ_ALU_CONST_CACHE_VS_15
+0x000288D8 SQ_PGM_CF_OFFSET_ES
+0x000288DC SQ_PGM_CF_OFFSET_FS
+0x000288D4 SQ_PGM_CF_OFFSET_GS
+0x000288CC SQ_PGM_CF_OFFSET_PS
+0x000288D0 SQ_PGM_CF_OFFSET_VS
+0x00028854 SQ_PGM_EXPORTS_PS
+0x00028890 SQ_PGM_RESOURCES_ES
+0x000288A4 SQ_PGM_RESOURCES_FS
+0x0002887C SQ_PGM_RESOURCES_GS
+0x00028850 SQ_PGM_RESOURCES_PS
+0x00028868 SQ_PGM_RESOURCES_VS
+0x00009100 SPI_CONFIG_CNTL
+0x0000913C SPI_CONFIG_CNTL_1
+0x000286DC SPI_FOG_CNTL
+0x000286E4 SPI_FOG_FUNC_BIAS
+0x000286E0 SPI_FOG_FUNC_SCALE
+0x000286D8 SPI_INPUT_Z
+0x000286D4 SPI_INTERP_CONTROL_0
+0x00028644 SPI_PS_INPUT_CNTL_0
+0x00028648 SPI_PS_INPUT_CNTL_1
+0x0002864C SPI_PS_INPUT_CNTL_2
+0x00028650 SPI_PS_INPUT_CNTL_3
+0x00028654 SPI_PS_INPUT_CNTL_4
+0x00028658 SPI_PS_INPUT_CNTL_5
+0x0002865C SPI_PS_INPUT_CNTL_6
+0x00028660 SPI_PS_INPUT_CNTL_7
+0x00028664 SPI_PS_INPUT_CNTL_8
+0x00028668 SPI_PS_INPUT_CNTL_9
+0x0002866C SPI_PS_INPUT_CNTL_10
+0x00028670 SPI_PS_INPUT_CNTL_11
+0x00028674 SPI_PS_INPUT_CNTL_12
+0x00028678 SPI_PS_INPUT_CNTL_13
+0x0002867C SPI_PS_INPUT_CNTL_14
+0x00028680 SPI_PS_INPUT_CNTL_15
+0x00028684 SPI_PS_INPUT_CNTL_16
+0x00028688 SPI_PS_INPUT_CNTL_17
+0x0002868C SPI_PS_INPUT_CNTL_18
+0x00028690 SPI_PS_INPUT_CNTL_19
+0x00028694 SPI_PS_INPUT_CNTL_20
+0x00028698 SPI_PS_INPUT_CNTL_21
+0x0002869C SPI_PS_INPUT_CNTL_22
+0x000286A0 SPI_PS_INPUT_CNTL_23
+0x000286A4 SPI_PS_INPUT_CNTL_24
+0x000286A8 SPI_PS_INPUT_CNTL_25
+0x000286AC SPI_PS_INPUT_CNTL_26
+0x000286B0 SPI_PS_INPUT_CNTL_27
+0x000286B4 SPI_PS_INPUT_CNTL_28
+0x000286B8 SPI_PS_INPUT_CNTL_29
+0x000286BC SPI_PS_INPUT_CNTL_30
+0x000286C0 SPI_PS_INPUT_CNTL_31
+0x000286CC SPI_PS_IN_CONTROL_0
+0x000286D0 SPI_PS_IN_CONTROL_1
+0x000286C4 SPI_VS_OUT_CONFIG
+0x00028614 SPI_VS_OUT_ID_0
+0x00028618 SPI_VS_OUT_ID_1
+0x0002861C SPI_VS_OUT_ID_2
+0x00028620 SPI_VS_OUT_ID_3
+0x00028624 SPI_VS_OUT_ID_4
+0x00028628 SPI_VS_OUT_ID_5
+0x0002862C SPI_VS_OUT_ID_6
+0x00028630 SPI_VS_OUT_ID_7
+0x00028634 SPI_VS_OUT_ID_8
+0x00028638 SPI_VS_OUT_ID_9
+0x00028438 SX_ALPHA_REF
+0x00028410 SX_ALPHA_TEST_CONTROL
+0x00028350 SX_MISC
+0x0000A020 SMX_DC_CTL0
+0x0000A024 SMX_DC_CTL1
+0x0000A028 SMX_DC_CTL2
+0x00009608 TC_CNTL
+0x00009604 TC_INVALIDATE
+0x00009490 TD_CNTL
+0x00009400 TD_FILTER4
+0x00009404 TD_FILTER4_1
+0x00009408 TD_FILTER4_2
+0x0000940C TD_FILTER4_3
+0x00009410 TD_FILTER4_4
+0x00009414 TD_FILTER4_5
+0x00009418 TD_FILTER4_6
+0x0000941C TD_FILTER4_7
+0x00009420 TD_FILTER4_8
+0x00009424 TD_FILTER4_9
+0x00009428 TD_FILTER4_10
+0x0000942C TD_FILTER4_11
+0x00009430 TD_FILTER4_12
+0x00009434 TD_FILTER4_13
+0x00009438 TD_FILTER4_14
+0x0000943C TD_FILTER4_15
+0x00009440 TD_FILTER4_16
+0x00009444 TD_FILTER4_17
+0x00009448 TD_FILTER4_18
+0x0000944C TD_FILTER4_19
+0x00009450 TD_FILTER4_20
+0x00009454 TD_FILTER4_21
+0x00009458 TD_FILTER4_22
+0x0000945C TD_FILTER4_23
+0x00009460 TD_FILTER4_24
+0x00009464 TD_FILTER4_25
+0x00009468 TD_FILTER4_26
+0x0000946C TD_FILTER4_27
+0x00009470 TD_FILTER4_28
+0x00009474 TD_FILTER4_29
+0x00009478 TD_FILTER4_30
+0x0000947C TD_FILTER4_31
+0x00009480 TD_FILTER4_32
+0x00009484 TD_FILTER4_33
+0x00009488 TD_FILTER4_34
+0x0000948C TD_FILTER4_35
+0x0000A80C TD_GS_SAMPLER0_BORDER_ALPHA
+0x0000A81C TD_GS_SAMPLER1_BORDER_ALPHA
+0x0000A82C TD_GS_SAMPLER2_BORDER_ALPHA
+0x0000A83C TD_GS_SAMPLER3_BORDER_ALPHA
+0x0000A84C TD_GS_SAMPLER4_BORDER_ALPHA
+0x0000A85C TD_GS_SAMPLER5_BORDER_ALPHA
+0x0000A86C TD_GS_SAMPLER6_BORDER_ALPHA
+0x0000A87C TD_GS_SAMPLER7_BORDER_ALPHA
+0x0000A88C TD_GS_SAMPLER8_BORDER_ALPHA
+0x0000A89C TD_GS_SAMPLER9_BORDER_ALPHA
+0x0000A8AC TD_GS_SAMPLER10_BORDER_ALPHA
+0x0000A8BC TD_GS_SAMPLER11_BORDER_ALPHA
+0x0000A8CC TD_GS_SAMPLER12_BORDER_ALPHA
+0x0000A8DC TD_GS_SAMPLER13_BORDER_ALPHA
+0x0000A8EC TD_GS_SAMPLER14_BORDER_ALPHA
+0x0000A8FC TD_GS_SAMPLER15_BORDER_ALPHA
+0x0000A90C TD_GS_SAMPLER16_BORDER_ALPHA
+0x0000A91C TD_GS_SAMPLER17_BORDER_ALPHA
+0x0000A808 TD_GS_SAMPLER0_BORDER_BLUE
+0x0000A818 TD_GS_SAMPLER1_BORDER_BLUE
+0x0000A828 TD_GS_SAMPLER2_BORDER_BLUE
+0x0000A838 TD_GS_SAMPLER3_BORDER_BLUE
+0x0000A848 TD_GS_SAMPLER4_BORDER_BLUE
+0x0000A858 TD_GS_SAMPLER5_BORDER_BLUE
+0x0000A868 TD_GS_SAMPLER6_BORDER_BLUE
+0x0000A878 TD_GS_SAMPLER7_BORDER_BLUE
+0x0000A888 TD_GS_SAMPLER8_BORDER_BLUE
+0x0000A898 TD_GS_SAMPLER9_BORDER_BLUE
+0x0000A8A8 TD_GS_SAMPLER10_BORDER_BLUE
+0x0000A8B8 TD_GS_SAMPLER11_BORDER_BLUE
+0x0000A8C8 TD_GS_SAMPLER12_BORDER_BLUE
+0x0000A8D8 TD_GS_SAMPLER13_BORDER_BLUE
+0x0000A8E8 TD_GS_SAMPLER14_BORDER_BLUE
+0x0000A8F8 TD_GS_SAMPLER15_BORDER_BLUE
+0x0000A908 TD_GS_SAMPLER16_BORDER_BLUE
+0x0000A918 TD_GS_SAMPLER17_BORDER_BLUE
+0x0000A804 TD_GS_SAMPLER0_BORDER_GREEN
+0x0000A814 TD_GS_SAMPLER1_BORDER_GREEN
+0x0000A824 TD_GS_SAMPLER2_BORDER_GREEN
+0x0000A834 TD_GS_SAMPLER3_BORDER_GREEN
+0x0000A844 TD_GS_SAMPLER4_BORDER_GREEN
+0x0000A854 TD_GS_SAMPLER5_BORDER_GREEN
+0x0000A864 TD_GS_SAMPLER6_BORDER_GREEN
+0x0000A874 TD_GS_SAMPLER7_BORDER_GREEN
+0x0000A884 TD_GS_SAMPLER8_BORDER_GREEN
+0x0000A894 TD_GS_SAMPLER9_BORDER_GREEN
+0x0000A8A4 TD_GS_SAMPLER10_BORDER_GREEN
+0x0000A8B4 TD_GS_SAMPLER11_BORDER_GREEN
+0x0000A8C4 TD_GS_SAMPLER12_BORDER_GREEN
+0x0000A8D4 TD_GS_SAMPLER13_BORDER_GREEN
+0x0000A8E4 TD_GS_SAMPLER14_BORDER_GREEN
+0x0000A8F4 TD_GS_SAMPLER15_BORDER_GREEN
+0x0000A904 TD_GS_SAMPLER16_BORDER_GREEN
+0x0000A914 TD_GS_SAMPLER17_BORDER_GREEN
+0x0000A800 TD_GS_SAMPLER0_BORDER_RED
+0x0000A810 TD_GS_SAMPLER1_BORDER_RED
+0x0000A820 TD_GS_SAMPLER2_BORDER_RED
+0x0000A830 TD_GS_SAMPLER3_BORDER_RED
+0x0000A840 TD_GS_SAMPLER4_BORDER_RED
+0x0000A850 TD_GS_SAMPLER5_BORDER_RED
+0x0000A860 TD_GS_SAMPLER6_BORDER_RED
+0x0000A870 TD_GS_SAMPLER7_BORDER_RED
+0x0000A880 TD_GS_SAMPLER8_BORDER_RED
+0x0000A890 TD_GS_SAMPLER9_BORDER_RED
+0x0000A8A0 TD_GS_SAMPLER10_BORDER_RED
+0x0000A8B0 TD_GS_SAMPLER11_BORDER_RED
+0x0000A8C0 TD_GS_SAMPLER12_BORDER_RED
+0x0000A8D0 TD_GS_SAMPLER13_BORDER_RED
+0x0000A8E0 TD_GS_SAMPLER14_BORDER_RED
+0x0000A8F0 TD_GS_SAMPLER15_BORDER_RED
+0x0000A900 TD_GS_SAMPLER16_BORDER_RED
+0x0000A910 TD_GS_SAMPLER17_BORDER_RED
+0x0000A40C TD_PS_SAMPLER0_BORDER_ALPHA
+0x0000A41C TD_PS_SAMPLER1_BORDER_ALPHA
+0x0000A42C TD_PS_SAMPLER2_BORDER_ALPHA
+0x0000A43C TD_PS_SAMPLER3_BORDER_ALPHA
+0x0000A44C TD_PS_SAMPLER4_BORDER_ALPHA
+0x0000A45C TD_PS_SAMPLER5_BORDER_ALPHA
+0x0000A46C TD_PS_SAMPLER6_BORDER_ALPHA
+0x0000A47C TD_PS_SAMPLER7_BORDER_ALPHA
+0x0000A48C TD_PS_SAMPLER8_BORDER_ALPHA
+0x0000A49C TD_PS_SAMPLER9_BORDER_ALPHA
+0x0000A4AC TD_PS_SAMPLER10_BORDER_ALPHA
+0x0000A4BC TD_PS_SAMPLER11_BORDER_ALPHA
+0x0000A4CC TD_PS_SAMPLER12_BORDER_ALPHA
+0x0000A4DC TD_PS_SAMPLER13_BORDER_ALPHA
+0x0000A4EC TD_PS_SAMPLER14_BORDER_ALPHA
+0x0000A4FC TD_PS_SAMPLER15_BORDER_ALPHA
+0x0000A50C TD_PS_SAMPLER16_BORDER_ALPHA
+0x0000A51C TD_PS_SAMPLER17_BORDER_ALPHA
+0x0000A408 TD_PS_SAMPLER0_BORDER_BLUE
+0x0000A418 TD_PS_SAMPLER1_BORDER_BLUE
+0x0000A428 TD_PS_SAMPLER2_BORDER_BLUE
+0x0000A438 TD_PS_SAMPLER3_BORDER_BLUE
+0x0000A448 TD_PS_SAMPLER4_BORDER_BLUE
+0x0000A458 TD_PS_SAMPLER5_BORDER_BLUE
+0x0000A468 TD_PS_SAMPLER6_BORDER_BLUE
+0x0000A478 TD_PS_SAMPLER7_BORDER_BLUE
+0x0000A488 TD_PS_SAMPLER8_BORDER_BLUE
+0x0000A498 TD_PS_SAMPLER9_BORDER_BLUE
+0x0000A4A8 TD_PS_SAMPLER10_BORDER_BLUE
+0x0000A4B8 TD_PS_SAMPLER11_BORDER_BLUE
+0x0000A4C8 TD_PS_SAMPLER12_BORDER_BLUE
+0x0000A4D8 TD_PS_SAMPLER13_BORDER_BLUE
+0x0000A4E8 TD_PS_SAMPLER14_BORDER_BLUE
+0x0000A4F8 TD_PS_SAMPLER15_BORDER_BLUE
+0x0000A508 TD_PS_SAMPLER16_BORDER_BLUE
+0x0000A518 TD_PS_SAMPLER17_BORDER_BLUE
+0x0000A404 TD_PS_SAMPLER0_BORDER_GREEN
+0x0000A414 TD_PS_SAMPLER1_BORDER_GREEN
+0x0000A424 TD_PS_SAMPLER2_BORDER_GREEN
+0x0000A434 TD_PS_SAMPLER3_BORDER_GREEN
+0x0000A444 TD_PS_SAMPLER4_BORDER_GREEN
+0x0000A454 TD_PS_SAMPLER5_BORDER_GREEN
+0x0000A464 TD_PS_SAMPLER6_BORDER_GREEN
+0x0000A474 TD_PS_SAMPLER7_BORDER_GREEN
+0x0000A484 TD_PS_SAMPLER8_BORDER_GREEN
+0x0000A494 TD_PS_SAMPLER9_BORDER_GREEN
+0x0000A4A4 TD_PS_SAMPLER10_BORDER_GREEN
+0x0000A4B4 TD_PS_SAMPLER11_BORDER_GREEN
+0x0000A4C4 TD_PS_SAMPLER12_BORDER_GREEN
+0x0000A4D4 TD_PS_SAMPLER13_BORDER_GREEN
+0x0000A4E4 TD_PS_SAMPLER14_BORDER_GREEN
+0x0000A4F4 TD_PS_SAMPLER15_BORDER_GREEN
+0x0000A504 TD_PS_SAMPLER16_BORDER_GREEN
+0x0000A514 TD_PS_SAMPLER17_BORDER_GREEN
+0x0000A400 TD_PS_SAMPLER0_BORDER_RED
+0x0000A410 TD_PS_SAMPLER1_BORDER_RED
+0x0000A420 TD_PS_SAMPLER2_BORDER_RED
+0x0000A430 TD_PS_SAMPLER3_BORDER_RED
+0x0000A440 TD_PS_SAMPLER4_BORDER_RED
+0x0000A450 TD_PS_SAMPLER5_BORDER_RED
+0x0000A460 TD_PS_SAMPLER6_BORDER_RED
+0x0000A470 TD_PS_SAMPLER7_BORDER_RED
+0x0000A480 TD_PS_SAMPLER8_BORDER_RED
+0x0000A490 TD_PS_SAMPLER9_BORDER_RED
+0x0000A4A0 TD_PS_SAMPLER10_BORDER_RED
+0x0000A4B0 TD_PS_SAMPLER11_BORDER_RED
+0x0000A4C0 TD_PS_SAMPLER12_BORDER_RED
+0x0000A4D0 TD_PS_SAMPLER13_BORDER_RED
+0x0000A4E0 TD_PS_SAMPLER14_BORDER_RED
+0x0000A4F0 TD_PS_SAMPLER15_BORDER_RED
+0x0000A500 TD_PS_SAMPLER16_BORDER_RED
+0x0000A510 TD_PS_SAMPLER17_BORDER_RED
+0x0000AA00 TD_PS_SAMPLER0_CLEARTYPE_KERNEL
+0x0000AA04 TD_PS_SAMPLER1_CLEARTYPE_KERNEL
+0x0000AA08 TD_PS_SAMPLER2_CLEARTYPE_KERNEL
+0x0000AA0C TD_PS_SAMPLER3_CLEARTYPE_KERNEL
+0x0000AA10 TD_PS_SAMPLER4_CLEARTYPE_KERNEL
+0x0000AA14 TD_PS_SAMPLER5_CLEARTYPE_KERNEL
+0x0000AA18 TD_PS_SAMPLER6_CLEARTYPE_KERNEL
+0x0000AA1C TD_PS_SAMPLER7_CLEARTYPE_KERNEL
+0x0000AA20 TD_PS_SAMPLER8_CLEARTYPE_KERNEL
+0x0000AA24 TD_PS_SAMPLER9_CLEARTYPE_KERNEL
+0x0000AA28 TD_PS_SAMPLER10_CLEARTYPE_KERNEL
+0x0000AA2C TD_PS_SAMPLER11_CLEARTYPE_KERNEL
+0x0000AA30 TD_PS_SAMPLER12_CLEARTYPE_KERNEL
+0x0000AA34 TD_PS_SAMPLER13_CLEARTYPE_KERNEL
+0x0000AA38 TD_PS_SAMPLER14_CLEARTYPE_KERNEL
+0x0000AA3C TD_PS_SAMPLER15_CLEARTYPE_KERNEL
+0x0000AA40 TD_PS_SAMPLER16_CLEARTYPE_KERNEL
+0x0000AA44 TD_PS_SAMPLER17_CLEARTYPE_KERNEL
+0x0000A60C TD_VS_SAMPLER0_BORDER_ALPHA
+0x0000A61C TD_VS_SAMPLER1_BORDER_ALPHA
+0x0000A62C TD_VS_SAMPLER2_BORDER_ALPHA
+0x0000A63C TD_VS_SAMPLER3_BORDER_ALPHA
+0x0000A64C TD_VS_SAMPLER4_BORDER_ALPHA
+0x0000A65C TD_VS_SAMPLER5_BORDER_ALPHA
+0x0000A66C TD_VS_SAMPLER6_BORDER_ALPHA
+0x0000A67C TD_VS_SAMPLER7_BORDER_ALPHA
+0x0000A68C TD_VS_SAMPLER8_BORDER_ALPHA
+0x0000A69C TD_VS_SAMPLER9_BORDER_ALPHA
+0x0000A6AC TD_VS_SAMPLER10_BORDER_ALPHA
+0x0000A6BC TD_VS_SAMPLER11_BORDER_ALPHA
+0x0000A6CC TD_VS_SAMPLER12_BORDER_ALPHA
+0x0000A6DC TD_VS_SAMPLER13_BORDER_ALPHA
+0x0000A6EC TD_VS_SAMPLER14_BORDER_ALPHA
+0x0000A6FC TD_VS_SAMPLER15_BORDER_ALPHA
+0x0000A70C TD_VS_SAMPLER16_BORDER_ALPHA
+0x0000A71C TD_VS_SAMPLER17_BORDER_ALPHA
+0x0000A608 TD_VS_SAMPLER0_BORDER_BLUE
+0x0000A618 TD_VS_SAMPLER1_BORDER_BLUE
+0x0000A628 TD_VS_SAMPLER2_BORDER_BLUE
+0x0000A638 TD_VS_SAMPLER3_BORDER_BLUE
+0x0000A648 TD_VS_SAMPLER4_BORDER_BLUE
+0x0000A658 TD_VS_SAMPLER5_BORDER_BLUE
+0x0000A668 TD_VS_SAMPLER6_BORDER_BLUE
+0x0000A678 TD_VS_SAMPLER7_BORDER_BLUE
+0x0000A688 TD_VS_SAMPLER8_BORDER_BLUE
+0x0000A698 TD_VS_SAMPLER9_BORDER_BLUE
+0x0000A6A8 TD_VS_SAMPLER10_BORDER_BLUE
+0x0000A6B8 TD_VS_SAMPLER11_BORDER_BLUE
+0x0000A6C8 TD_VS_SAMPLER12_BORDER_BLUE
+0x0000A6D8 TD_VS_SAMPLER13_BORDER_BLUE
+0x0000A6E8 TD_VS_SAMPLER14_BORDER_BLUE
+0x0000A6F8 TD_VS_SAMPLER15_BORDER_BLUE
+0x0000A708 TD_VS_SAMPLER16_BORDER_BLUE
+0x0000A718 TD_VS_SAMPLER17_BORDER_BLUE
+0x0000A604 TD_VS_SAMPLER0_BORDER_GREEN
+0x0000A614 TD_VS_SAMPLER1_BORDER_GREEN
+0x0000A624 TD_VS_SAMPLER2_BORDER_GREEN
+0x0000A634 TD_VS_SAMPLER3_BORDER_GREEN
+0x0000A644 TD_VS_SAMPLER4_BORDER_GREEN
+0x0000A654 TD_VS_SAMPLER5_BORDER_GREEN
+0x0000A664 TD_VS_SAMPLER6_BORDER_GREEN
+0x0000A674 TD_VS_SAMPLER7_BORDER_GREEN
+0x0000A684 TD_VS_SAMPLER8_BORDER_GREEN
+0x0000A694 TD_VS_SAMPLER9_BORDER_GREEN
+0x0000A6A4 TD_VS_SAMPLER10_BORDER_GREEN
+0x0000A6B4 TD_VS_SAMPLER11_BORDER_GREEN
+0x0000A6C4 TD_VS_SAMPLER12_BORDER_GREEN
+0x0000A6D4 TD_VS_SAMPLER13_BORDER_GREEN
+0x0000A6E4 TD_VS_SAMPLER14_BORDER_GREEN
+0x0000A6F4 TD_VS_SAMPLER15_BORDER_GREEN
+0x0000A704 TD_VS_SAMPLER16_BORDER_GREEN
+0x0000A714 TD_VS_SAMPLER17_BORDER_GREEN
+0x0000A600 TD_VS_SAMPLER0_BORDER_RED
+0x0000A610 TD_VS_SAMPLER1_BORDER_RED
+0x0000A620 TD_VS_SAMPLER2_BORDER_RED
+0x0000A630 TD_VS_SAMPLER3_BORDER_RED
+0x0000A640 TD_VS_SAMPLER4_BORDER_RED
+0x0000A650 TD_VS_SAMPLER5_BORDER_RED
+0x0000A660 TD_VS_SAMPLER6_BORDER_RED
+0x0000A670 TD_VS_SAMPLER7_BORDER_RED
+0x0000A680 TD_VS_SAMPLER8_BORDER_RED
+0x0000A690 TD_VS_SAMPLER9_BORDER_RED
+0x0000A6A0 TD_VS_SAMPLER10_BORDER_RED
+0x0000A6B0 TD_VS_SAMPLER11_BORDER_RED
+0x0000A6C0 TD_VS_SAMPLER12_BORDER_RED
+0x0000A6D0 TD_VS_SAMPLER13_BORDER_RED
+0x0000A6E0 TD_VS_SAMPLER14_BORDER_RED
+0x0000A6F0 TD_VS_SAMPLER15_BORDER_RED
+0x0000A700 TD_VS_SAMPLER16_BORDER_RED
+0x0000A710 TD_VS_SAMPLER17_BORDER_RED
+0x00009508 TA_CNTL_AUX
+0x0002802C DB_DEPTH_CLEAR
+0x00028D24 DB_HTILE_SURFACE
+0x00028D34 DB_PREFETCH_LIMIT
+0x00028D30 DB_PRELOAD_CONTROL
+0x00028D0C DB_RENDER_CONTROL
+0x00028D10 DB_RENDER_OVERRIDE
+0x0002880C DB_SHADER_CONTROL
+0x00028D2C DB_SRESULTS_COMPARE_STATE1
+0x00028430 DB_STENCILREFMASK
+0x00028434 DB_STENCILREFMASK_BF
+0x00028028 DB_STENCIL_CLEAR
+0x00028780 CB_BLEND0_CONTROL
+0x00028784 CB_BLEND1_CONTROL
+0x00028788 CB_BLEND2_CONTROL
+0x0002878C CB_BLEND3_CONTROL
+0x00028790 CB_BLEND4_CONTROL
+0x00028794 CB_BLEND5_CONTROL
+0x00028798 CB_BLEND6_CONTROL
+0x0002879C CB_BLEND7_CONTROL
+0x00028804 CB_BLEND_CONTROL
+0x00028420 CB_BLEND_ALPHA
+0x0002841C CB_BLEND_BLUE
+0x00028418 CB_BLEND_GREEN
+0x00028414 CB_BLEND_RED
+0x0002812C CB_CLEAR_ALPHA
+0x00028128 CB_CLEAR_BLUE
+0x00028124 CB_CLEAR_GREEN
+0x00028120 CB_CLEAR_RED
+0x00028C30 CB_CLRCMP_CONTROL
+0x00028C38 CB_CLRCMP_DST
+0x00028C3C CB_CLRCMP_MSK
+0x00028C34 CB_CLRCMP_SRC
+0x00028100 CB_COLOR0_MASK
+0x00028104 CB_COLOR1_MASK
+0x00028108 CB_COLOR2_MASK
+0x0002810C CB_COLOR3_MASK
+0x00028110 CB_COLOR4_MASK
+0x00028114 CB_COLOR5_MASK
+0x00028118 CB_COLOR6_MASK
+0x0002811C CB_COLOR7_MASK
+0x00028080 CB_COLOR0_VIEW
+0x00028084 CB_COLOR1_VIEW
+0x00028088 CB_COLOR2_VIEW
+0x0002808C CB_COLOR3_VIEW
+0x00028090 CB_COLOR4_VIEW
+0x00028094 CB_COLOR5_VIEW
+0x00028098 CB_COLOR6_VIEW
+0x0002809C CB_COLOR7_VIEW
+0x00028808 CB_COLOR_CONTROL
+0x0002842C CB_FOG_BLUE
+0x00028428 CB_FOG_GREEN
+0x00028424 CB_FOG_RED
+0x00008040 WAIT_UNTIL
+0x00008950 CC_GC_SHADER_PIPE_CONFIG
+0x00008954 GC_USER_SHADER_PIPE_CONFIG
+0x00009714 VC_ENHANCE
+0x00009830 DB_DEBUG
+0x00009838 DB_WATERMARKS
+0x00028D28 DB_SRESULTS_COMPARE_STATE0
+0x00028D44 DB_ALPHA_TO_MASK
+0x00009504 TA_CNTL
+0x00009700 VC_CNTL
+0x00009718 VC_CONFIG
+0x0000A02C SMX_DC_MC_INTF_CTL
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c
index 287fceb..626d518 100644
--- a/drivers/gpu/drm/radeon/rs400.c
+++ b/drivers/gpu/drm/radeon/rs400.c
@@ -113,6 +113,7 @@
 	uint32_t size_reg;
 	uint32_t tmp;
 
+	radeon_gart_restore(rdev);
 	tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH);
 	tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS;
 	WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp);
@@ -150,9 +151,8 @@
 		WREG32(RADEON_AGP_BASE, 0xFFFFFFFF);
 		WREG32(RS480_AGP_BASE_2, 0);
 	}
-	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
-	tmp = REG_SET(RS690_MC_AGP_TOP, tmp >> 16);
-	tmp |= REG_SET(RS690_MC_AGP_START, rdev->mc.gtt_location >> 16);
+	tmp = REG_SET(RS690_MC_AGP_TOP, rdev->mc.gtt_end >> 16);
+	tmp |= REG_SET(RS690_MC_AGP_START, rdev->mc.gtt_start >> 16);
 	if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) {
 		WREG32_MC(RS690_MCCFG_AGP_LOCATION, tmp);
 		tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
@@ -251,14 +251,19 @@
 	}
 }
 
-void rs400_vram_info(struct radeon_device *rdev)
+void rs400_mc_init(struct radeon_device *rdev)
 {
+	u64 base;
+
 	rs400_gart_adjust_size(rdev);
+	rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev);
 	/* DDR for all card after R300 & IGP */
 	rdev->mc.vram_is_ddr = true;
 	rdev->mc.vram_width = 128;
-
 	r100_vram_init_sizes(rdev);
+	base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
+	radeon_vram_location(rdev, &rdev->mc, base);
+	radeon_gtt_location(rdev, &rdev->mc);
 }
 
 uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg)
@@ -362,22 +367,6 @@
 #endif
 }
 
-static int rs400_mc_init(struct radeon_device *rdev)
-{
-	int r;
-	u32 tmp;
-
-	/* Setup GPU memory space */
-	tmp = RREG32(R_00015C_NB_TOM);
-	rdev->mc.vram_location = G_00015C_MC_FB_START(tmp) << 16;
-	rdev->mc.gtt_location = 0xFFFFFFFFUL;
-	r = radeon_mc_setup(rdev);
-	rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev);
-	if (r)
-		return r;
-	return 0;
-}
-
 void rs400_mc_program(struct radeon_device *rdev)
 {
 	struct r100_mc_save save;
@@ -516,12 +505,8 @@
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
 	radeon_pm_init(rdev);
-	/* Get vram informations */
-	rs400_vram_info(rdev);
-	/* Initialize memory controller (also test AGP) */
-	r = rs400_mc_init(rdev);
-	if (r)
-		return r;
+	/* initialize memory controller */
+	rs400_mc_init(rdev);
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
 	if (r)
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index c381856..47f046b 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -45,23 +45,6 @@
 void rs600_gpu_init(struct radeon_device *rdev);
 int rs600_mc_wait_for_idle(struct radeon_device *rdev);
 
-int rs600_mc_init(struct radeon_device *rdev)
-{
-	/* read back the MC value from the hw */
-	int r;
-	u32 tmp;
-
-	/* Setup GPU memory space */
-	tmp = RREG32_MC(R_000004_MC_FB_LOCATION);
-	rdev->mc.vram_location = G_000004_MC_FB_START(tmp) << 16;
-	rdev->mc.gtt_location = 0xffffffffUL;
-	r = radeon_mc_setup(rdev);
-	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
-	if (r)
-		return r;
-	return 0;
-}
-
 /* hpd for digital panel detect/disconnect */
 bool rs600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
 {
@@ -213,6 +196,7 @@
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
+	radeon_gart_restore(rdev);
 	/* Enable bus master */
 	tmp = RREG32(R_00004C_BUS_CNTL) & C_00004C_BUS_MASTER_DIS;
 	WREG32(R_00004C_BUS_CNTL, tmp);
@@ -406,10 +390,14 @@
 		if (G_000044_SW_INT(status))
 			radeon_fence_process(rdev);
 		/* Vertical blank interrupts */
-		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int))
+		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) {
 			drm_handle_vblank(rdev->ddev, 0);
-		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int))
+			wake_up(&rdev->irq.vblank_queue);
+		}
+		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) {
 			drm_handle_vblank(rdev->ddev, 1);
+			wake_up(&rdev->irq.vblank_queue);
+		}
 		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) {
 			queue_hotplug = true;
 			DRM_DEBUG("HPD1\n");
@@ -470,22 +458,22 @@
 		dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
 }
 
-void rs600_vram_info(struct radeon_device *rdev)
+void rs600_mc_init(struct radeon_device *rdev)
 {
-	rdev->mc.vram_is_ddr = true;
-	rdev->mc.vram_width = 128;
-
-	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
-	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+	u64 base;
 
 	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
 	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
-
-	if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
-		rdev->mc.mc_vram_size = rdev->mc.aper_size;
-
-	if (rdev->mc.real_vram_size > rdev->mc.aper_size)
-		rdev->mc.real_vram_size = rdev->mc.aper_size;
+	rdev->mc.vram_is_ddr = true;
+	rdev->mc.vram_width = 128;
+	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
+	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
+	rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
+	base = RREG32_MC(R_000004_MC_FB_LOCATION);
+	base = G_000004_MC_FB_START(base) << 16;
+	radeon_vram_location(rdev, &rdev->mc, base);
+	radeon_gtt_location(rdev, &rdev->mc);
 }
 
 void rs600_bandwidth_update(struct radeon_device *rdev)
@@ -661,12 +649,8 @@
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
 	radeon_pm_init(rdev);
-	/* Get vram informations */
-	rs600_vram_info(rdev);
-	/* Initialize memory controller (also test AGP) */
-	r = rs600_mc_init(rdev);
-	if (r)
-		return r;
+	/* initialize memory controller */
+	rs600_mc_init(rdev);
 	rs600_debugfs(rdev);
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c
index 06e2771..83b9174 100644
--- a/drivers/gpu/drm/radeon/rs690.c
+++ b/drivers/gpu/drm/radeon/rs690.c
@@ -129,27 +129,21 @@
 	rdev->pm.sideport_bandwidth.full = rfixed_div(rdev->pm.sideport_bandwidth, tmp);
 }
 
-void rs690_vram_info(struct radeon_device *rdev)
+void rs690_mc_init(struct radeon_device *rdev)
 {
 	fixed20_12 a;
+	u64 base;
 
 	rs400_gart_adjust_size(rdev);
-
 	rdev->mc.vram_is_ddr = true;
 	rdev->mc.vram_width = 128;
-
 	rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
 	rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
-
 	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
 	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
-
-	if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
-		rdev->mc.mc_vram_size = rdev->mc.aper_size;
-
-	if (rdev->mc.real_vram_size > rdev->mc.aper_size)
-		rdev->mc.real_vram_size = rdev->mc.aper_size;
-
+	rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
+	base = G_000100_MC_FB_START(base) << 16;
 	rs690_pm_info(rdev);
 	/* FIXME: we should enforce default clock in case GPU is not in
 	 * default setup
@@ -160,22 +154,9 @@
 	a.full = rfixed_const(16);
 	/* core_bandwidth = sclk(Mhz) * 16 */
 	rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a);
-}
-
-static int rs690_mc_init(struct radeon_device *rdev)
-{
-	int r;
-	u32 tmp;
-
-	/* Setup GPU memory space */
-	tmp = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
-	rdev->mc.vram_location = G_000100_MC_FB_START(tmp) << 16;
-	rdev->mc.gtt_location = 0xFFFFFFFFUL;
-	r = radeon_mc_setup(rdev);
 	rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
-	if (r)
-		return r;
-	return 0;
+	radeon_vram_location(rdev, &rdev->mc, base);
+	radeon_gtt_location(rdev, &rdev->mc);
 }
 
 void rs690_line_buffer_adjust(struct radeon_device *rdev,
@@ -728,12 +709,8 @@
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
 	radeon_pm_init(rdev);
-	/* Get vram informations */
-	rs690_vram_info(rdev);
-	/* Initialize memory controller (also test AGP) */
-	r = rs690_mc_init(rdev);
-	if (r)
-		return r;
+	/* initialize memory controller */
+	rs690_mc_init(rdev);
 	rv515_debugfs(rdev);
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
index 0e1e6b8..bea747d 100644
--- a/drivers/gpu/drm/radeon/rv515.c
+++ b/drivers/gpu/drm/radeon/rv515.c
@@ -277,13 +277,15 @@
 	}
 }
 
-void rv515_vram_info(struct radeon_device *rdev)
+void rv515_mc_init(struct radeon_device *rdev)
 {
 	fixed20_12 a;
 
 	rv515_vram_get_type(rdev);
-
 	r100_vram_init_sizes(rdev);
+	radeon_vram_location(rdev, &rdev->mc, 0);
+	if (!(rdev->flags & RADEON_IS_AGP))
+		radeon_gtt_location(rdev, &rdev->mc);
 	/* FIXME: we should enforce default clock in case GPU is not in
 	 * default setup
 	 */
@@ -587,12 +589,15 @@
 	radeon_get_clock_info(rdev->ddev);
 	/* Initialize power management */
 	radeon_pm_init(rdev);
-	/* Get vram informations */
-	rv515_vram_info(rdev);
-	/* Initialize memory controller (also test AGP) */
-	r = r420_mc_init(rdev);
-	if (r)
-		return r;
+	/* initialize AGP */
+	if (rdev->flags & RADEON_IS_AGP) {
+		r = radeon_agp_init(rdev);
+		if (r) {
+			radeon_agp_disable(rdev);
+		}
+	}
+	/* initialize memory controller */
+	rv515_mc_init(rdev);
 	rv515_debugfs(rdev);
 	/* Fence driver */
 	r = radeon_fence_driver_init(rdev);
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 0302167..37887de 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -56,6 +56,7 @@
 	r = radeon_gart_table_vram_pin(rdev);
 	if (r)
 		return r;
+	radeon_gart_restore(rdev);
 	/* Setup L2 cache */
 	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
 				ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
@@ -273,9 +274,10 @@
 /*
  * Core functions
  */
-static u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
-						u32 num_backends,
-						u32 backend_disable_mask)
+static u32 r700_get_tile_pipe_to_backend_map(struct radeon_device *rdev,
+					     u32 num_tile_pipes,
+					     u32 num_backends,
+					     u32 backend_disable_mask)
 {
 	u32 backend_map = 0;
 	u32 enabled_backends_mask;
@@ -284,6 +286,7 @@
 	u32 swizzle_pipe[R7XX_MAX_PIPES];
 	u32 cur_backend;
 	u32 i;
+	bool force_no_swizzle;
 
 	if (num_tile_pipes > R7XX_MAX_PIPES)
 		num_tile_pipes = R7XX_MAX_PIPES;
@@ -313,6 +316,18 @@
 	if (enabled_backends_count != num_backends)
 		num_backends = enabled_backends_count;
 
+	switch (rdev->family) {
+	case CHIP_RV770:
+	case CHIP_RV730:
+		force_no_swizzle = false;
+		break;
+	case CHIP_RV710:
+	case CHIP_RV740:
+	default:
+		force_no_swizzle = true;
+		break;
+	}
+
 	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES);
 	switch (num_tile_pipes) {
 	case 1:
@@ -323,49 +338,100 @@
 		swizzle_pipe[1] = 1;
 		break;
 	case 3:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 1;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 1;
+		}
 		break;
 	case 4:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 3;
-		swizzle_pipe[3] = 1;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 3;
+			swizzle_pipe[3] = 1;
+		}
 		break;
 	case 5:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 1;
-		swizzle_pipe[4] = 3;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 1;
+			swizzle_pipe[4] = 3;
+		}
 		break;
 	case 6:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 5;
-		swizzle_pipe[4] = 3;
-		swizzle_pipe[5] = 1;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+			swizzle_pipe[5] = 5;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 5;
+			swizzle_pipe[4] = 3;
+			swizzle_pipe[5] = 1;
+		}
 		break;
 	case 7:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 6;
-		swizzle_pipe[4] = 3;
-		swizzle_pipe[5] = 1;
-		swizzle_pipe[6] = 5;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+			swizzle_pipe[5] = 5;
+			swizzle_pipe[6] = 6;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 6;
+			swizzle_pipe[4] = 3;
+			swizzle_pipe[5] = 1;
+			swizzle_pipe[6] = 5;
+		}
 		break;
 	case 8:
-		swizzle_pipe[0] = 0;
-		swizzle_pipe[1] = 2;
-		swizzle_pipe[2] = 4;
-		swizzle_pipe[3] = 6;
-		swizzle_pipe[4] = 3;
-		swizzle_pipe[5] = 1;
-		swizzle_pipe[6] = 7;
-		swizzle_pipe[7] = 5;
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+			swizzle_pipe[5] = 5;
+			swizzle_pipe[6] = 6;
+			swizzle_pipe[7] = 7;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 6;
+			swizzle_pipe[4] = 3;
+			swizzle_pipe[5] = 1;
+			swizzle_pipe[6] = 7;
+			swizzle_pipe[7] = 5;
+		}
 		break;
 	}
 
@@ -385,8 +451,10 @@
 static void rv770_gpu_init(struct radeon_device *rdev)
 {
 	int i, j, num_qd_pipes;
+	u32 ta_aux_cntl;
 	u32 sx_debug_1;
 	u32 smx_dc_ctl0;
+	u32 db_debug3;
 	u32 num_gs_verts_per_thread;
 	u32 vgt_gs_per_es;
 	u32 gs_prim_buffer_depth = 0;
@@ -515,6 +583,7 @@
 
 	switch (rdev->config.rv770.max_tile_pipes) {
 	case 1:
+	default:
 		gb_tiling_config |= PIPE_TILING(0);
 		break;
 	case 2:
@@ -526,16 +595,17 @@
 	case 8:
 		gb_tiling_config |= PIPE_TILING(3);
 		break;
-	default:
-		break;
 	}
+	rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes;
 
 	if (rdev->family == CHIP_RV770)
 		gb_tiling_config |= BANK_TILING(1);
 	else
 		gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT);
+	rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3);
 
 	gb_tiling_config |= GROUP_SIZE(0);
+	rdev->config.rv770.tiling_group_size = 256;
 
 	if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) {
 		gb_tiling_config |= ROW_TILING(3);
@@ -549,21 +619,27 @@
 
 	gb_tiling_config |= BANK_SWAPS(1);
 
-	if (rdev->family == CHIP_RV740)
-		backend_map = 0x28;
-	else
-		backend_map = r700_get_tile_pipe_to_backend_map(rdev->config.rv770.max_tile_pipes,
-								rdev->config.rv770.max_backends,
-								(0xff << rdev->config.rv770.max_backends) & 0xff);
-	gb_tiling_config |= BACKEND_MAP(backend_map);
+	cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000;
+	cc_rb_backend_disable |=
+		BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << rdev->config.rv770.max_backends) & R7XX_MAX_BACKENDS_MASK);
 
-	cc_gc_shader_pipe_config =
+	cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
+	cc_gc_shader_pipe_config |=
 		INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << rdev->config.rv770.max_pipes) & R7XX_MAX_PIPES_MASK);
 	cc_gc_shader_pipe_config |=
 		INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << rdev->config.rv770.max_simds) & R7XX_MAX_SIMDS_MASK);
 
-	cc_rb_backend_disable =
-		BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << rdev->config.rv770.max_backends) & R7XX_MAX_BACKENDS_MASK);
+	if (rdev->family == CHIP_RV740)
+		backend_map = 0x28;
+	else
+		backend_map = r700_get_tile_pipe_to_backend_map(rdev,
+								rdev->config.rv770.max_tile_pipes,
+								(R7XX_MAX_BACKENDS -
+								 r600_count_pipe_bits((cc_rb_backend_disable &
+										       R7XX_MAX_BACKENDS_MASK) >> 16)),
+								(cc_rb_backend_disable >> 16));
+	gb_tiling_config |= BACKEND_MAP(backend_map);
+
 
 	WREG32(GB_TILING_CONFIG, gb_tiling_config);
 	WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff));
@@ -571,16 +647,13 @@
 
 	WREG32(CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
 	WREG32(CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
-	WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
+	WREG32(CC_SYS_RB_BACKEND_DISABLE,  cc_rb_backend_disable);
 
-	WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
 	WREG32(CGTS_SYS_TCC_DISABLE, 0);
 	WREG32(CGTS_TCC_DISABLE, 0);
-	WREG32(CGTS_USER_SYS_TCC_DISABLE, 0);
-	WREG32(CGTS_USER_TCC_DISABLE, 0);
 
 	num_qd_pipes =
-		R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK);
+		R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8);
 	WREG32(VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & DEALLOC_DIST_MASK);
 	WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & VTX_REUSE_DEPTH_MASK);
 
@@ -590,10 +663,8 @@
 
 	WREG32(CP_MEQ_THRESHOLDS, STQ_SPLIT(0x30));
 
-	WREG32(TA_CNTL_AUX, (DISABLE_CUBE_ANISO |
-			     SYNC_GRADIENT |
-			     SYNC_WALKER |
-			     SYNC_ALIGNER));
+	ta_aux_cntl = RREG32(TA_CNTL_AUX);
+	WREG32(TA_CNTL_AUX, ta_aux_cntl | DISABLE_CUBE_ANISO);
 
 	sx_debug_1 = RREG32(SX_DEBUG_1);
 	sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS;
@@ -604,14 +675,28 @@
 	smx_dc_ctl0 |= CACHE_DEPTH((rdev->config.rv770.sx_num_of_sets * 64) - 1);
 	WREG32(SMX_DC_CTL0, smx_dc_ctl0);
 
-	WREG32(SMX_EVENT_CTL, (ES_FLUSH_CTL(4) |
-			       GS_FLUSH_CTL(4) |
-			       ACK_FLUSH_CTL(3) |
-			       SYNC_FLUSH_CTL));
+	if (rdev->family != CHIP_RV740)
+		WREG32(SMX_EVENT_CTL, (ES_FLUSH_CTL(4) |
+				       GS_FLUSH_CTL(4) |
+				       ACK_FLUSH_CTL(3) |
+				       SYNC_FLUSH_CTL));
 
-	if (rdev->family == CHIP_RV770)
-		WREG32(DB_DEBUG3, DB_CLK_OFF_DELAY(0x1f));
-	else {
+	db_debug3 = RREG32(DB_DEBUG3);
+	db_debug3 &= ~DB_CLK_OFF_DELAY(0x1f);
+	switch (rdev->family) {
+	case CHIP_RV770:
+	case CHIP_RV740:
+		db_debug3 |= DB_CLK_OFF_DELAY(0x1f);
+		break;
+	case CHIP_RV710:
+	case CHIP_RV730:
+	default:
+		db_debug3 |= DB_CLK_OFF_DELAY(2);
+		break;
+	}
+	WREG32(DB_DEBUG3, db_debug3);
+
+	if (rdev->family != CHIP_RV770) {
 		db_debug4 = RREG32(DB_DEBUG4);
 		db_debug4 |= DISABLE_TILE_COVERED_FOR_PS_ITER;
 		WREG32(DB_DEBUG4, db_debug4);
@@ -640,10 +725,10 @@
 			    ALU_UPDATE_FIFO_HIWATER(0x8));
 	switch (rdev->family) {
 	case CHIP_RV770:
-		sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x1);
-		break;
 	case CHIP_RV730:
 	case CHIP_RV710:
+		sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x1);
+		break;
 	case CHIP_RV740:
 	default:
 		sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x4);
@@ -816,45 +901,13 @@
 	/* Setup GPU memory space */
 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
-
-	if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
+	rdev->mc.visible_vram_size = rdev->mc.aper_size;
+	/* FIXME remove this once we support unmappable VRAM */
+	if (rdev->mc.mc_vram_size > rdev->mc.aper_size) {
 		rdev->mc.mc_vram_size = rdev->mc.aper_size;
-
-	if (rdev->mc.real_vram_size > rdev->mc.aper_size)
 		rdev->mc.real_vram_size = rdev->mc.aper_size;
-
-	if (rdev->flags & RADEON_IS_AGP) {
-		/* gtt_size is setup by radeon_agp_init */
-		rdev->mc.gtt_location = rdev->mc.agp_base;
-		tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
-		/* Try to put vram before or after AGP because we
-		 * we want SYSTEM_APERTURE to cover both VRAM and
-		 * AGP so that GPU can catch out of VRAM/AGP access
-		 */
-		if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) {
-			/* Enough place before */
-			rdev->mc.vram_location = rdev->mc.gtt_location -
-							rdev->mc.mc_vram_size;
-		} else if (tmp > rdev->mc.mc_vram_size) {
-			/* Enough place after */
-			rdev->mc.vram_location = rdev->mc.gtt_location +
-							rdev->mc.gtt_size;
-		} else {
-			/* Try to setup VRAM then AGP might not
-			 * not work on some card
-			 */
-			rdev->mc.vram_location = 0x00000000UL;
-			rdev->mc.gtt_location = rdev->mc.mc_vram_size;
-		}
-	} else {
-		rdev->mc.vram_location = 0x00000000UL;
-		rdev->mc.gtt_location = rdev->mc.mc_vram_size;
-		rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
 	}
-	rdev->mc.vram_start = rdev->mc.vram_location;
-	rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
-	rdev->mc.gtt_start = rdev->mc.gtt_location;
-	rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
+	r600_vram_gtt_location(rdev, &rdev->mc);
 	/* FIXME: we should enforce default clock in case GPU is not in
 	 * default setup
 	 */
@@ -863,6 +916,7 @@
 	rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
 	return 0;
 }
+
 int rv770_gpu_reset(struct radeon_device *rdev)
 {
 	/* FIXME: implement any rv770 specific bits */
@@ -1038,6 +1092,7 @@
 	r = radeon_fence_driver_init(rdev);
 	if (r)
 		return r;
+	/* initialize AGP */
 	if (rdev->flags & RADEON_IS_AGP) {
 		r = radeon_agp_init(rdev);
 		if (r)
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h
index a1367ab..9506f8c 100644
--- a/drivers/gpu/drm/radeon/rv770d.h
+++ b/drivers/gpu/drm/radeon/rv770d.h
@@ -343,4 +343,6 @@
 
 #define	WAIT_UNTIL					0x8040
 
+#define	SRBM_STATUS				        0x0E50
+
 #endif
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index c7320ce..89c38c4 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -128,7 +128,7 @@
 	NULL
 };
 
-static struct sysfs_ops ttm_bo_global_ops = {
+static const struct sysfs_ops ttm_bo_global_ops = {
 	.show = &ttm_bo_global_show
 };
 
diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c
index f5245c0..eb143e0 100644
--- a/drivers/gpu/drm/ttm/ttm_memory.c
+++ b/drivers/gpu/drm/ttm/ttm_memory.c
@@ -152,7 +152,7 @@
 	NULL
 };
 
-static struct sysfs_ops ttm_mem_zone_ops = {
+static const struct sysfs_ops ttm_mem_zone_ops = {
 	.show = &ttm_mem_zone_show,
 	.store = &ttm_mem_zone_store
 };
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 3d47a2c..a759170 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -480,7 +480,7 @@
 	void *from_virtual;
 	void *to_virtual;
 	int i;
-	int ret;
+	int ret = -ENOMEM;
 
 	if (ttm->page_flags & TTM_PAGE_FLAG_USER) {
 		ret = ttm_tt_set_user(ttm, ttm->tsk, ttm->start,
@@ -499,8 +499,10 @@
 
 	for (i = 0; i < ttm->num_pages; ++i) {
 		from_page = read_mapping_page(swap_space, i, NULL);
-		if (IS_ERR(from_page))
+		if (IS_ERR(from_page)) {
+			ret = PTR_ERR(from_page);
 			goto out_err;
+		}
 		to_page = __ttm_tt_get_page(ttm, i);
 		if (unlikely(to_page == NULL))
 			goto out_err;
@@ -523,7 +525,7 @@
 	return 0;
 out_err:
 	ttm_tt_free_alloced_pages(ttm);
-	return -ENOMEM;
+	return ret;
 }
 
 int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage)
@@ -535,6 +537,7 @@
 	void *from_virtual;
 	void *to_virtual;
 	int i;
+	int ret = -ENOMEM;
 
 	BUG_ON(ttm->state != tt_unbound && ttm->state != tt_unpopulated);
 	BUG_ON(ttm->caching_state != tt_cached);
@@ -557,7 +560,7 @@
 						0);
 		if (unlikely(IS_ERR(swap_storage))) {
 			printk(KERN_ERR "Failed allocating swap storage.\n");
-			return -ENOMEM;
+			return PTR_ERR(swap_storage);
 		}
 	} else
 		swap_storage = persistant_swap_storage;
@@ -569,9 +572,10 @@
 		if (unlikely(from_page == NULL))
 			continue;
 		to_page = read_mapping_page(swap_space, i, NULL);
-		if (unlikely(to_page == NULL))
+		if (unlikely(IS_ERR(to_page))) {
+			ret = PTR_ERR(to_page);
 			goto out_err;
-
+		}
 		preempt_disable();
 		from_virtual = kmap_atomic(from_page, KM_USER0);
 		to_virtual = kmap_atomic(to_page, KM_USER1);
@@ -595,5 +599,5 @@
 	if (!persistant_swap_storage)
 		fput(swap_storage);
 
-	return -ENOMEM;
+	return ret;
 }
diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c
index 5935b88..34079f2 100644
--- a/drivers/gpu/drm/via/via_irq.c
+++ b/drivers/gpu/drm/via/via_irq.c
@@ -150,7 +150,7 @@
 		cur_irq++;
 	}
 
-	/* Acknowlege interrupts */
+	/* Acknowledge interrupts */
 	VIA_WRITE(VIA_REG_INTERRUPT, status);
 
 
@@ -165,7 +165,7 @@
 	u32 status;
 
 	if (dev_priv) {
-		/* Acknowlege interrupts */
+		/* Acknowledge interrupts */
 		status = VIA_READ(VIA_REG_INTERRUPT);
 		VIA_WRITE(VIA_REG_INTERRUPT, status |
 			  dev_priv->irq_pending_mask);
diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig
index 0920492..61ab4da 100644
--- a/drivers/gpu/vga/Kconfig
+++ b/drivers/gpu/vga/Kconfig
@@ -16,3 +16,14 @@
 	help
 	  Reserves space in the kernel to maintain resource locking for
 	  multiple GPUS.  The overhead for each GPU is very small.
+
+config VGA_SWITCHEROO
+	bool "Laptop Hybrid Grapics - GPU switching support"
+	depends on X86
+	depends on ACPI
+	help
+	  Many laptops released in 2008/9/10 have two gpus with a multiplxer
+	  to switch between them. This adds support for dynamic switching when
+          X isn't running and delayed switching until the next logoff. This
+	  features is called hybrid graphics, ATI PowerXpress, and Nvidia
+	  HybridPower.
diff --git a/drivers/gpu/vga/Makefile b/drivers/gpu/vga/Makefile
index 7cc8c1e..14ca30b 100644
--- a/drivers/gpu/vga/Makefile
+++ b/drivers/gpu/vga/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_VGA_ARB)  += vgaarb.o
+obj-$(CONFIG_VGA_SWITCHEROO) += vga_switcheroo.o
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
new file mode 100644
index 0000000..d6d1149
--- /dev/null
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2010 Red Hat Inc.
+ * Author : Dave Airlie <airlied@redhat.com>
+ *
+ *
+ * Licensed under GPLv2
+ *
+ * vga_switcheroo.c - Support for laptop with dual GPU using one set of outputs
+
+ Switcher interface - methods require for ATPX and DCM
+ - switchto - this throws the output MUX switch
+ - discrete_set_power - sets the power state for the discrete card
+
+ GPU driver interface
+ - set_gpu_state - this should do the equiv of s/r for the card
+		  - this should *not* set the discrete power state
+ - switch_check  - check if the device is in a position to switch now
+ */
+
+#include <linux/module.h>
+#include <linux/dmi.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/fb.h>
+
+#include <linux/pci.h>
+#include <linux/vga_switcheroo.h>
+
+struct vga_switcheroo_client {
+	struct pci_dev *pdev;
+	struct fb_info *fb_info;
+	int pwr_state;
+	void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state);
+	bool (*can_switch)(struct pci_dev *pdev);
+	int id;
+	bool active;
+};
+
+static DEFINE_MUTEX(vgasr_mutex);
+
+struct vgasr_priv {
+
+	bool active;
+	bool delayed_switch_active;
+	enum vga_switcheroo_client_id delayed_client_id;
+
+	struct dentry *debugfs_root;
+	struct dentry *switch_file;
+
+	int registered_clients;
+	struct vga_switcheroo_client clients[VGA_SWITCHEROO_MAX_CLIENTS];
+
+	struct vga_switcheroo_handler *handler;
+};
+
+static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv);
+static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv);
+
+/* only one switcheroo per system */
+static struct vgasr_priv vgasr_priv;
+
+int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
+{
+	mutex_lock(&vgasr_mutex);
+	if (vgasr_priv.handler) {
+		mutex_unlock(&vgasr_mutex);
+		return -EINVAL;
+	}
+
+	vgasr_priv.handler = handler;
+	mutex_unlock(&vgasr_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(vga_switcheroo_register_handler);
+
+void vga_switcheroo_unregister_handler(void)
+{
+	mutex_lock(&vgasr_mutex);
+	vgasr_priv.handler = NULL;
+	mutex_unlock(&vgasr_mutex);
+}
+EXPORT_SYMBOL(vga_switcheroo_unregister_handler);
+
+static void vga_switcheroo_enable(void)
+{
+	int i;
+	int ret;
+	/* call the handler to init */
+	vgasr_priv.handler->init();
+
+	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+		ret = vgasr_priv.handler->get_client_id(vgasr_priv.clients[i].pdev);
+		if (ret < 0)
+			return;
+
+		vgasr_priv.clients[i].id = ret;
+	}
+	vga_switcheroo_debugfs_init(&vgasr_priv);
+	vgasr_priv.active = true;
+}
+
+int vga_switcheroo_register_client(struct pci_dev *pdev,
+				   void (*set_gpu_state)(struct pci_dev *pdev, enum vga_switcheroo_state),
+				   bool (*can_switch)(struct pci_dev *pdev))
+{
+	int index;
+
+	mutex_lock(&vgasr_mutex);
+	/* don't do IGD vs DIS here */
+	if (vgasr_priv.registered_clients & 1)
+		index = 1;
+	else
+		index = 0;
+
+	vgasr_priv.clients[index].pwr_state = VGA_SWITCHEROO_ON;
+	vgasr_priv.clients[index].pdev = pdev;
+	vgasr_priv.clients[index].set_gpu_state = set_gpu_state;
+	vgasr_priv.clients[index].can_switch = can_switch;
+	vgasr_priv.clients[index].id = -1;
+	if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
+		vgasr_priv.clients[index].active = true;
+
+	vgasr_priv.registered_clients |= (1 << index);
+
+	/* if we get two clients + handler */
+	if (vgasr_priv.registered_clients == 0x3 && vgasr_priv.handler) {
+		printk(KERN_INFO "vga_switcheroo: enabled\n");
+		vga_switcheroo_enable();
+	}
+	mutex_unlock(&vgasr_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(vga_switcheroo_register_client);
+
+void vga_switcheroo_unregister_client(struct pci_dev *pdev)
+{
+	int i;
+
+	mutex_lock(&vgasr_mutex);
+	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+		if (vgasr_priv.clients[i].pdev == pdev) {
+			vgasr_priv.registered_clients &= ~(1 << i);
+			break;
+		}
+	}
+
+	printk(KERN_INFO "vga_switcheroo: disabled\n");
+	vga_switcheroo_debugfs_fini(&vgasr_priv);
+	vgasr_priv.active = false;
+	mutex_unlock(&vgasr_mutex);
+}
+EXPORT_SYMBOL(vga_switcheroo_unregister_client);
+
+void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
+				 struct fb_info *info)
+{
+	int i;
+
+	mutex_lock(&vgasr_mutex);
+	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+		if (vgasr_priv.clients[i].pdev == pdev) {
+			vgasr_priv.clients[i].fb_info = info;
+			break;
+		}
+	}
+	mutex_unlock(&vgasr_mutex);
+}
+EXPORT_SYMBOL(vga_switcheroo_client_fb_set);
+
+static int vga_switcheroo_show(struct seq_file *m, void *v)
+{
+	int i;
+	mutex_lock(&vgasr_mutex);
+	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+		seq_printf(m, "%d:%c:%s:%s\n", i,
+			   vgasr_priv.clients[i].active ? '+' : ' ',
+			   vgasr_priv.clients[i].pwr_state ? "Pwr" : "Off",
+			   pci_name(vgasr_priv.clients[i].pdev));
+	}
+	mutex_unlock(&vgasr_mutex);
+	return 0;
+}
+
+static int vga_switcheroo_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, vga_switcheroo_show, NULL);
+}
+
+static int vga_switchon(struct vga_switcheroo_client *client)
+{
+	int ret;
+
+	ret = vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_ON);
+	/* call the driver callback to turn on device */
+	client->set_gpu_state(client->pdev, VGA_SWITCHEROO_ON);
+	client->pwr_state = VGA_SWITCHEROO_ON;
+	return 0;
+}
+
+static int vga_switchoff(struct vga_switcheroo_client *client)
+{
+	/* call the driver callback to turn off device */
+	client->set_gpu_state(client->pdev, VGA_SWITCHEROO_OFF);
+	vgasr_priv.handler->power_state(client->id, VGA_SWITCHEROO_OFF);
+	client->pwr_state = VGA_SWITCHEROO_OFF;
+	return 0;
+}
+
+static int vga_switchto(struct vga_switcheroo_client *new_client)
+{
+	int ret;
+	int i;
+	struct vga_switcheroo_client *active = NULL;
+
+	if (new_client->active == true)
+		return 0;
+
+	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+		if (vgasr_priv.clients[i].active == true) {
+			active = &vgasr_priv.clients[i];
+			break;
+		}
+	}
+	if (!active)
+		return 0;
+
+	/* power up the first device */
+	ret = pci_enable_device(new_client->pdev);
+	if (ret)
+		return ret;
+
+	if (new_client->pwr_state == VGA_SWITCHEROO_OFF)
+		vga_switchon(new_client);
+
+	/* swap shadow resource to denote boot VGA device has changed so X starts on new device */
+	active->active = false;
+
+	active->pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_ROM_SHADOW;
+	new_client->pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+
+	if (new_client->fb_info) {
+		struct fb_event event;
+		event.info = new_client->fb_info;
+		fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
+	}
+
+	ret = vgasr_priv.handler->switchto(new_client->id);
+	if (ret)
+		return ret;
+
+	if (active->pwr_state == VGA_SWITCHEROO_ON)
+		vga_switchoff(active);
+
+	new_client->active = true;
+	return 0;
+}
+
+static ssize_t
+vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
+			     size_t cnt, loff_t *ppos)
+{
+	char usercmd[64];
+	const char *pdev_name;
+	int i, ret;
+	bool delay = false, can_switch;
+	int client_id = -1;
+	struct vga_switcheroo_client *client = NULL;
+
+	if (cnt > 63)
+		cnt = 63;
+
+	if (copy_from_user(usercmd, ubuf, cnt))
+		return -EFAULT;
+
+	mutex_lock(&vgasr_mutex);
+
+	if (!vgasr_priv.active)
+		return -EINVAL;
+
+	/* pwr off the device not in use */
+	if (strncmp(usercmd, "OFF", 3) == 0) {
+		for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+			if (vgasr_priv.clients[i].active)
+				continue;
+			if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_ON)
+				vga_switchoff(&vgasr_priv.clients[i]);
+		}
+		goto out;
+	}
+	/* pwr on the device not in use */
+	if (strncmp(usercmd, "ON", 2) == 0) {
+		for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+			if (vgasr_priv.clients[i].active)
+				continue;
+			if (vgasr_priv.clients[i].pwr_state == VGA_SWITCHEROO_OFF)
+				vga_switchon(&vgasr_priv.clients[i]);
+		}
+		goto out;
+	}
+
+	/* request a delayed switch - test can we switch now */
+	if (strncmp(usercmd, "DIGD", 4) == 0) {
+		client_id = VGA_SWITCHEROO_IGD;
+		delay = true;
+	}
+
+	if (strncmp(usercmd, "DDIS", 4) == 0) {
+		client_id = VGA_SWITCHEROO_DIS;
+		delay = true;
+	}
+
+	if (strncmp(usercmd, "IGD", 3) == 0)
+		client_id = VGA_SWITCHEROO_IGD;
+
+	if (strncmp(usercmd, "DIS", 3) == 0)
+		client_id = VGA_SWITCHEROO_DIS;
+
+	if (client_id == -1)
+		goto out;
+
+	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+		if (vgasr_priv.clients[i].id == client_id) {
+			client = &vgasr_priv.clients[i];
+			break;
+		}
+	}
+
+	vgasr_priv.delayed_switch_active = false;
+	/* okay we want a switch - test if devices are willing to switch */
+	can_switch = true;
+	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+		can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev);
+		if (can_switch == false) {
+			printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i);
+			break;
+		}
+	}
+
+	if (can_switch == false && delay == false)
+		goto out;
+
+	if (can_switch == true) {
+		pdev_name = pci_name(client->pdev);
+		ret = vga_switchto(client);
+		if (ret)
+			printk(KERN_ERR "vga_switcheroo: switching failed %d\n", ret);
+	} else {
+		printk(KERN_INFO "vga_switcheroo: setting delayed switch to client %d\n", client->id);
+		vgasr_priv.delayed_switch_active = true;
+		vgasr_priv.delayed_client_id = client_id;
+
+		/* we should at least power up the card to
+		   make the switch faster */
+		if (client->pwr_state == VGA_SWITCHEROO_OFF)
+			vga_switchon(client);
+	}
+
+out:
+	mutex_unlock(&vgasr_mutex);
+	return cnt;
+}
+
+static const struct file_operations vga_switcheroo_debugfs_fops = {
+	.owner = THIS_MODULE,
+	.open = vga_switcheroo_debugfs_open,
+	.write = vga_switcheroo_debugfs_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv)
+{
+	if (priv->switch_file) {
+		debugfs_remove(priv->switch_file);
+		priv->switch_file = NULL;
+	}
+	if (priv->debugfs_root) {
+		debugfs_remove(priv->debugfs_root);
+		priv->debugfs_root = NULL;
+	}
+}
+
+static int vga_switcheroo_debugfs_init(struct vgasr_priv *priv)
+{
+	/* already initialised */
+	if (priv->debugfs_root)
+		return 0;
+	priv->debugfs_root = debugfs_create_dir("vgaswitcheroo", NULL);
+
+	if (!priv->debugfs_root) {
+		printk(KERN_ERR "vga_switcheroo: Cannot create /sys/kernel/debug/vgaswitcheroo\n");
+		goto fail;
+	}
+
+	priv->switch_file = debugfs_create_file("switch", 0644,
+						priv->debugfs_root, NULL, &vga_switcheroo_debugfs_fops);
+	if (!priv->switch_file) {
+		printk(KERN_ERR "vga_switcheroo: cannot create /sys/kernel/debug/vgaswitcheroo/switch\n");
+		goto fail;
+	}
+	return 0;
+fail:
+	vga_switcheroo_debugfs_fini(priv);
+	return -1;
+}
+
+int vga_switcheroo_process_delayed_switch(void)
+{
+	struct vga_switcheroo_client *client = NULL;
+	const char *pdev_name;
+	bool can_switch = true;
+	int i;
+	int ret;
+	int err = -EINVAL;
+
+	mutex_lock(&vgasr_mutex);
+	if (!vgasr_priv.delayed_switch_active)
+		goto err;
+
+	printk(KERN_INFO "vga_switcheroo: processing delayed switch to %d\n", vgasr_priv.delayed_client_id);
+
+	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
+		if (vgasr_priv.clients[i].id == vgasr_priv.delayed_client_id)
+			client = &vgasr_priv.clients[i];
+		can_switch = vgasr_priv.clients[i].can_switch(vgasr_priv.clients[i].pdev);
+		if (can_switch == false) {
+			printk(KERN_ERR "vga_switcheroo: client %d refused switch\n", i);
+			break;
+		}
+	}
+
+	if (can_switch == false || client == NULL)
+		goto err;
+
+	pdev_name = pci_name(client->pdev);
+	ret = vga_switchto(client);
+	if (ret)
+		printk(KERN_ERR "vga_switcheroo: delayed switching failed %d\n", ret);
+
+	vgasr_priv.delayed_switch_active = false;
+	err = 0;
+err:
+	mutex_unlock(&vgasr_mutex);
+	return err;
+}
+EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);
+
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 867e084..433602a 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -265,9 +265,10 @@
 static int hiddev_open(struct inode *inode, struct file *file)
 {
 	struct hiddev_list *list;
-	int res;
+	int res, i;
 
-	int i = iminor(inode) - HIDDEV_MINOR_BASE;
+	lock_kernel();
+	i = iminor(inode) - HIDDEV_MINOR_BASE;
 
 	if (i >= HIDDEV_MINORS || i < 0 || !hiddev_table[i])
 		return -ENODEV;
@@ -313,10 +314,12 @@
 			usbhid_open(hid);
 		}
 
+	unlock_kernel();
 	return 0;
 bail:
 	file->private_data = NULL;
 	kfree(list);
+	unlock_kernel();
 	return res;
 }
 
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 68cf877..e4595e6 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -170,6 +170,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called adm9240.
 
+config SENSORS_ADT7411
+	tristate "Analog Devices ADT7411"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Analog Devices
+	  ADT7411 voltage and temperature monitoring chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called adt7411.
+
 config SENSORS_ADT7462
 	tristate "Analog Devices ADT7462"
 	depends on I2C && EXPERIMENTAL
@@ -190,20 +200,6 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called adt7470.
 
-config SENSORS_ADT7473
-	tristate "Analog Devices ADT7473 (DEPRECATED)"
-	depends on I2C && EXPERIMENTAL
-	select SENSORS_ADT7475
-	help
-	  If you say yes here you get support for the Analog Devices
-	  ADT7473 temperature monitoring chips.
-
-	  This driver is deprecated, you should use the adt7475 driver
-	  instead.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called adt7473.
-
 config SENSORS_ADT7475
 	tristate "Analog Devices ADT7473, ADT7475, ADT7476 and ADT7490"
 	depends on I2C && EXPERIMENTAL
@@ -216,6 +212,19 @@
 	  This driver can also be build as a module.  If so, the module
 	  will be called adt7475.
 
+config SENSORS_ASC7621
+	tristate "Andigilog aSC7621"
+	depends on HWMON && I2C
+	help
+	  If you say yes here you get support for the aSC7621
+	  family of SMBus sensors chip found on most Intel X48, X38, 975,
+	  965 and 945 desktop boards.  Currently supported chips:
+	  aSC7621
+	  aSC7621a
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called asc7621.
+
 config SENSORS_K8TEMP
 	tristate "AMD Athlon64/FX or Opteron temperature sensor"
 	depends on X86 && PCI && EXPERIMENTAL
@@ -563,9 +572,10 @@
 	depends on I2C
 	help
 	  If you say yes here you get support for National Semiconductor LM90,
-	  LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim
+	  LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, Maxim
 	  MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
-	  MAX6680, MAX6681 and MAX6692 sensor chips.
+	  MAX6680, MAX6681 and MAX6692, and Winbond/Nuvoton W83L771AWG/ASG
+	  sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm90.
@@ -909,7 +919,8 @@
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the Winbond W83793
-	  hardware monitoring chip.
+	  hardware monitoring chip, including support for the integrated
+	  watchdog.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83793.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 4bc215c..4aa1a3d 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -29,12 +29,13 @@
 obj-$(CONFIG_SENSORS_ADM1031)	+= adm1031.o
 obj-$(CONFIG_SENSORS_ADM9240)	+= adm9240.o
 obj-$(CONFIG_SENSORS_ADS7828)	+= ads7828.o
+obj-$(CONFIG_SENSORS_ADT7411)	+= adt7411.o
 obj-$(CONFIG_SENSORS_ADT7462)	+= adt7462.o
 obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
-obj-$(CONFIG_SENSORS_ADT7473)	+= adt7473.o
 obj-$(CONFIG_SENSORS_ADT7475)	+= adt7475.o
 obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
 obj-$(CONFIG_SENSORS_AMS)	+= ams/
+obj-$(CONFIG_SENSORS_ASC7621)	+= asc7621.o
 obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_CORETEMP)	+= coretemp.o
 obj-$(CONFIG_SENSORS_DME1737)	+= dme1737.o
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
index 5e9e095..74d9c51 100644
--- a/drivers/hwmon/adcxx.c
+++ b/drivers/hwmon/adcxx.c
@@ -62,18 +62,23 @@
 	struct spi_device *spi = to_spi_device(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct adcxx *adc = dev_get_drvdata(&spi->dev);
-	u8 tx_buf[2] = { attr->index << 3 }; /* other bits are don't care */
+	u8 tx_buf[2];
 	u8 rx_buf[2];
 	int status;
-	int value;
+	u32 value;
 
 	if (mutex_lock_interruptible(&adc->lock))
 		return -ERESTARTSYS;
 
-	status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf),
-					rx_buf, sizeof(rx_buf));
+	if (adc->channels == 1) {
+		status = spi_read(spi, rx_buf, sizeof(rx_buf));
+	} else {
+		tx_buf[0] = attr->index << 3; /* other bits are don't care */
+		status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf),
+						rx_buf, sizeof(rx_buf));
+	}
 	if (status < 0) {
-		dev_warn(dev, "spi_write_then_read failed with status %d\n",
+		dev_warn(dev, "SPI synch. transfer failed with status %d\n",
 				status);
 		goto out;
 	}
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
new file mode 100644
index 0000000..3471884
--- /dev/null
+++ b/drivers/hwmon/adt7411.c
@@ -0,0 +1,366 @@
+/*
+ *  Driver for the ADT7411 (I2C/SPI 8 channel 10 bit ADC & temperature-sensor)
+ *
+ *  Copyright (C) 2008, 2010 Pengutronix
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  TODO: SPI, support for external temperature sensor
+ * 	  use power-down mode for suspend?, interrupt handling?
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#define ADT7411_REG_INT_TEMP_VDD_LSB		0x03
+#define ADT7411_REG_EXT_TEMP_AIN14_LSB		0x04
+#define ADT7411_REG_VDD_MSB			0x06
+#define ADT7411_REG_INT_TEMP_MSB		0x07
+#define ADT7411_REG_EXT_TEMP_AIN1_MSB		0x08
+
+#define ADT7411_REG_CFG1			0x18
+#define ADT7411_CFG1_START_MONITOR		(1 << 0)
+
+#define ADT7411_REG_CFG2			0x19
+#define ADT7411_CFG2_DISABLE_AVG		(1 << 5)
+
+#define ADT7411_REG_CFG3			0x1a
+#define ADT7411_CFG3_ADC_CLK_225		(1 << 0)
+#define ADT7411_CFG3_REF_VDD			(1 << 4)
+
+#define ADT7411_REG_DEVICE_ID			0x4d
+#define ADT7411_REG_MANUFACTURER_ID		0x4e
+
+#define ADT7411_DEVICE_ID			0x2
+#define ADT7411_MANUFACTURER_ID			0x41
+
+static const unsigned short normal_i2c[] = { 0x48, 0x4a, 0x4b, I2C_CLIENT_END };
+
+struct adt7411_data {
+	struct mutex device_lock;	/* for "atomic" device accesses */
+	struct mutex update_lock;
+	unsigned long next_update;
+	int vref_cached;
+	struct device *hwmon_dev;
+};
+
+/*
+ * When reading a register containing (up to 4) lsb, all associated
+ * msb-registers get locked by the hardware. After _one_ of those msb is read,
+ * _all_ are unlocked. In order to use this locking correctly, reading lsb/msb
+ * is protected here with a mutex, too.
+ */
+static int adt7411_read_10_bit(struct i2c_client *client, u8 lsb_reg,
+				u8 msb_reg, u8 lsb_shift)
+{
+	struct adt7411_data *data = i2c_get_clientdata(client);
+	int val, tmp;
+
+	mutex_lock(&data->device_lock);
+
+	val = i2c_smbus_read_byte_data(client, lsb_reg);
+	if (val < 0)
+		goto exit_unlock;
+
+	tmp = (val >> lsb_shift) & 3;
+	val = i2c_smbus_read_byte_data(client, msb_reg);
+
+	if (val >= 0)
+		val = (val << 2) | tmp;
+
+ exit_unlock:
+	mutex_unlock(&data->device_lock);
+
+	return val;
+}
+
+static int adt7411_modify_bit(struct i2c_client *client, u8 reg, u8 bit,
+				bool flag)
+{
+	struct adt7411_data *data = i2c_get_clientdata(client);
+	int ret, val;
+
+	mutex_lock(&data->device_lock);
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+	if (ret < 0)
+		goto exit_unlock;
+
+	if (flag)
+		val = ret | bit;
+	else
+		val = ret & ~bit;
+
+	ret = i2c_smbus_write_byte_data(client, reg, val);
+
+ exit_unlock:
+	mutex_unlock(&data->device_lock);
+	return ret;
+}
+
+static ssize_t adt7411_show_vdd(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB,
+			ADT7411_REG_VDD_MSB, 2);
+
+	return ret < 0 ? ret : sprintf(buf, "%u\n", ret * 7000 / 1024);
+}
+
+static ssize_t adt7411_show_temp(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int val = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB,
+			ADT7411_REG_INT_TEMP_MSB, 0);
+
+	if (val < 0)
+		return val;
+
+	val = val & 0x200 ? val - 0x400 : val; /* 10 bit signed */
+
+	return sprintf(buf, "%d\n", val * 250);
+}
+
+static ssize_t adt7411_show_input(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adt7411_data *data = i2c_get_clientdata(client);
+	int val;
+	u8 lsb_reg, lsb_shift;
+
+	mutex_lock(&data->update_lock);
+	if (time_after_eq(jiffies, data->next_update)) {
+		val = i2c_smbus_read_byte_data(client, ADT7411_REG_CFG3);
+		if (val < 0)
+			goto exit_unlock;
+
+		if (val & ADT7411_CFG3_REF_VDD) {
+			val = adt7411_read_10_bit(client,
+					ADT7411_REG_INT_TEMP_VDD_LSB,
+					ADT7411_REG_VDD_MSB, 2);
+			if (val < 0)
+				goto exit_unlock;
+
+			data->vref_cached = val * 7000 / 1024;
+		} else {
+			data->vref_cached = 2250;
+		}
+
+		data->next_update = jiffies + HZ;
+	}
+
+	lsb_reg = ADT7411_REG_EXT_TEMP_AIN14_LSB + (nr >> 2);
+	lsb_shift = 2 * (nr & 0x03);
+	val = adt7411_read_10_bit(client, lsb_reg,
+			ADT7411_REG_EXT_TEMP_AIN1_MSB + nr, lsb_shift);
+	if (val < 0)
+		goto exit_unlock;
+
+	val = sprintf(buf, "%u\n", val * data->vref_cached / 1024);
+ exit_unlock:
+	mutex_unlock(&data->update_lock);
+	return val;
+}
+
+static ssize_t adt7411_show_bit(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret = i2c_smbus_read_byte_data(client, attr2->index);
+
+	return ret < 0 ? ret : sprintf(buf, "%u\n", !!(ret & attr2->nr));
+}
+
+static ssize_t adt7411_set_bit(struct device *dev,
+			       struct device_attribute *attr, const char *buf,
+			       size_t count)
+{
+	struct sensor_device_attribute_2 *s_attr2 = to_sensor_dev_attr_2(attr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adt7411_data *data = i2c_get_clientdata(client);
+	int ret;
+	unsigned long flag;
+
+	ret = strict_strtoul(buf, 0, &flag);
+	if (ret || flag > 1)
+		return -EINVAL;
+
+	ret = adt7411_modify_bit(client, s_attr2->index, s_attr2->nr, flag);
+
+	/* force update */
+	mutex_lock(&data->update_lock);
+	data->next_update = jiffies;
+	mutex_unlock(&data->update_lock);
+
+	return ret < 0 ? ret : count;
+}
+
+#define ADT7411_BIT_ATTR(__name, __reg, __bit) \
+	SENSOR_DEVICE_ATTR_2(__name, S_IRUGO | S_IWUSR, adt7411_show_bit, \
+	adt7411_set_bit, __bit, __reg)
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, adt7411_show_temp, NULL);
+static DEVICE_ATTR(in0_input, S_IRUGO, adt7411_show_vdd, NULL);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, adt7411_show_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, adt7411_show_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, adt7411_show_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, adt7411_show_input, NULL, 3);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, adt7411_show_input, NULL, 4);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, adt7411_show_input, NULL, 5);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, adt7411_show_input, NULL, 6);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, adt7411_show_input, NULL, 7);
+static ADT7411_BIT_ATTR(no_average, ADT7411_REG_CFG2, ADT7411_CFG2_DISABLE_AVG);
+static ADT7411_BIT_ATTR(fast_sampling, ADT7411_REG_CFG3, ADT7411_CFG3_ADC_CLK_225);
+static ADT7411_BIT_ATTR(adc_ref_vdd, ADT7411_REG_CFG3, ADT7411_CFG3_REF_VDD);
+
+static struct attribute *adt7411_attrs[] = {
+	&dev_attr_temp1_input.attr,
+	&dev_attr_in0_input.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	&sensor_dev_attr_in8_input.dev_attr.attr,
+	&sensor_dev_attr_no_average.dev_attr.attr,
+	&sensor_dev_attr_fast_sampling.dev_attr.attr,
+	&sensor_dev_attr_adc_ref_vdd.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group adt7411_attr_grp = {
+	.attrs = adt7411_attrs,
+};
+
+static int adt7411_detect(struct i2c_client *client,
+			  struct i2c_board_info *info)
+{
+	int val;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	val = i2c_smbus_read_byte_data(client, ADT7411_REG_MANUFACTURER_ID);
+	if (val < 0 || val != ADT7411_MANUFACTURER_ID) {
+		dev_dbg(&client->dev, "Wrong manufacturer ID. Got %d, "
+			"expected %d\n", val, ADT7411_MANUFACTURER_ID);
+		return -ENODEV;
+	}
+
+	val = i2c_smbus_read_byte_data(client, ADT7411_REG_DEVICE_ID);
+	if (val < 0 || val != ADT7411_DEVICE_ID) {
+		dev_dbg(&client->dev, "Wrong device ID. Got %d, "
+			"expected %d\n", val, ADT7411_DEVICE_ID);
+		return -ENODEV;
+	}
+
+	strlcpy(info->type, "adt7411", I2C_NAME_SIZE);
+
+	return 0;
+}
+
+static int __devinit adt7411_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	struct adt7411_data *data;
+	int ret;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->device_lock);
+	mutex_init(&data->update_lock);
+
+	ret = adt7411_modify_bit(client, ADT7411_REG_CFG1,
+				 ADT7411_CFG1_START_MONITOR, 1);
+	if (ret < 0)
+		goto exit_free;
+
+	/* force update on first occasion */
+	data->next_update = jiffies;
+
+	ret = sysfs_create_group(&client->dev.kobj, &adt7411_attr_grp);
+	if (ret)
+		goto exit_free;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	dev_info(&client->dev, "successfully registered\n");
+
+	return 0;
+
+ exit_remove:
+	sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
+ exit_free:
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+	return ret;
+}
+
+static int __devexit adt7411_remove(struct i2c_client *client)
+{
+	struct adt7411_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+	return 0;
+}
+
+static const struct i2c_device_id adt7411_id[] = {
+	{ "adt7411", 0 },
+	{ }
+};
+
+static struct i2c_driver adt7411_driver = {
+	.driver		= {
+		.name		= "adt7411",
+	},
+	.probe  = adt7411_probe,
+	.remove	= __devexit_p(adt7411_remove),
+	.id_table = adt7411_id,
+	.detect = adt7411_detect,
+	.address_list = normal_i2c,
+	.class = I2C_CLASS_HWMON,
+};
+
+static int __init sensors_adt7411_init(void)
+{
+	return i2c_add_driver(&adt7411_driver);
+}
+module_init(sensors_adt7411_init)
+
+static void __exit sensors_adt7411_exit(void)
+{
+	i2c_del_driver(&adt7411_driver);
+}
+module_exit(sensors_adt7411_exit)
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de> and "
+	"Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_DESCRIPTION("ADT7411 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c
deleted file mode 100644
index 434576f..0000000
--- a/drivers/hwmon/adt7473.c
+++ /dev/null
@@ -1,1180 +0,0 @@
-/*
- * A hwmon driver for the Analog Devices ADT7473
- * Copyright (C) 2007 IBM
- *
- * Author: Darrick J. Wong <djwong@us.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/log2.h>
-
-/* Addresses to scan */
-static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, I2C_CLIENT_END };
-
-/* ADT7473 registers */
-#define ADT7473_REG_BASE_ADDR			0x20
-
-#define ADT7473_REG_VOLT_BASE_ADDR		0x21
-#define ADT7473_REG_VOLT_MIN_BASE_ADDR		0x46
-
-#define ADT7473_REG_TEMP_BASE_ADDR		0x25
-#define ADT7473_REG_TEMP_LIMITS_BASE_ADDR	0x4E
-#define ADT7473_REG_TEMP_TMIN_BASE_ADDR		0x67
-#define ADT7473_REG_TEMP_TMAX_BASE_ADDR		0x6A
-
-#define ADT7473_REG_FAN_BASE_ADDR		0x28
-#define ADT7473_REG_FAN_MIN_BASE_ADDR		0x54
-
-#define ADT7473_REG_PWM_BASE_ADDR		0x30
-#define	ADT7473_REG_PWM_MIN_BASE_ADDR		0x64
-#define ADT7473_REG_PWM_MAX_BASE_ADDR		0x38
-#define ADT7473_REG_PWM_BHVR_BASE_ADDR		0x5C
-#define		ADT7473_PWM_BHVR_MASK		0xE0
-#define		ADT7473_PWM_BHVR_SHIFT		5
-
-#define ADT7473_REG_CFG1			0x40
-#define 	ADT7473_CFG1_START		0x01
-#define		ADT7473_CFG1_READY		0x04
-#define ADT7473_REG_CFG2			0x73
-#define ADT7473_REG_CFG3			0x78
-#define ADT7473_REG_CFG4			0x7D
-#define		ADT7473_CFG4_MAX_DUTY_AT_OVT	0x08
-#define ADT7473_REG_CFG5			0x7C
-#define		ADT7473_CFG5_TEMP_TWOS		0x01
-#define		ADT7473_CFG5_TEMP_OFFSET	0x02
-
-#define ADT7473_REG_DEVICE			0x3D
-#define 	ADT7473_VENDOR			0x41
-#define ADT7473_REG_VENDOR			0x3E
-#define 	ADT7473_DEVICE			0x73
-#define ADT7473_REG_REVISION			0x3F
-#define 	ADT7473_REV_68			0x68
-#define 	ADT7473_REV_69			0x69
-
-#define ADT7473_REG_ALARM1			0x41
-#define		ADT7473_VCCP_ALARM		0x02
-#define		ADT7473_VCC_ALARM		0x04
-#define		ADT7473_R1T_ALARM		0x10
-#define		ADT7473_LT_ALARM		0x20
-#define		ADT7473_R2T_ALARM		0x40
-#define		ADT7473_OOL			0x80
-#define ADT7473_REG_ALARM2			0x42
-#define		ADT7473_OVT_ALARM		0x02
-#define		ADT7473_FAN1_ALARM		0x04
-#define		ADT7473_FAN2_ALARM		0x08
-#define		ADT7473_FAN3_ALARM		0x10
-#define		ADT7473_FAN4_ALARM		0x20
-#define		ADT7473_R1T_SHORT		0x40
-#define		ADT7473_R2T_SHORT		0x80
-
-#define ALARM2(x)	((x) << 8)
-
-#define ADT7473_VOLT_COUNT	2
-#define ADT7473_REG_VOLT(x)	(ADT7473_REG_VOLT_BASE_ADDR + (x))
-#define ADT7473_REG_VOLT_MIN(x)	(ADT7473_REG_VOLT_MIN_BASE_ADDR + ((x) * 2))
-#define ADT7473_REG_VOLT_MAX(x)	(ADT7473_REG_VOLT_MIN_BASE_ADDR + \
-				((x) * 2) + 1)
-
-#define ADT7473_TEMP_COUNT	3
-#define ADT7473_REG_TEMP(x)	(ADT7473_REG_TEMP_BASE_ADDR + (x))
-#define ADT7473_REG_TEMP_MIN(x) (ADT7473_REG_TEMP_LIMITS_BASE_ADDR + ((x) * 2))
-#define ADT7473_REG_TEMP_MAX(x) (ADT7473_REG_TEMP_LIMITS_BASE_ADDR + \
-				((x) * 2) + 1)
-#define ADT7473_REG_TEMP_TMIN(x)	(ADT7473_REG_TEMP_TMIN_BASE_ADDR + (x))
-#define ADT7473_REG_TEMP_TMAX(x)	(ADT7473_REG_TEMP_TMAX_BASE_ADDR + (x))
-
-#define ADT7473_FAN_COUNT	4
-#define ADT7473_REG_FAN(x)	(ADT7473_REG_FAN_BASE_ADDR + ((x) * 2))
-#define ADT7473_REG_FAN_MIN(x)	(ADT7473_REG_FAN_MIN_BASE_ADDR + ((x) * 2))
-
-#define ADT7473_PWM_COUNT	3
-#define ADT7473_REG_PWM(x)	(ADT7473_REG_PWM_BASE_ADDR + (x))
-#define ADT7473_REG_PWM_MAX(x)	(ADT7473_REG_PWM_MAX_BASE_ADDR + (x))
-#define ADT7473_REG_PWM_MIN(x)	(ADT7473_REG_PWM_MIN_BASE_ADDR + (x))
-#define ADT7473_REG_PWM_BHVR(x)	(ADT7473_REG_PWM_BHVR_BASE_ADDR + (x))
-
-/* How often do we reread sensors values? (In jiffies) */
-#define SENSOR_REFRESH_INTERVAL	(2 * HZ)
-
-/* How often do we reread sensor limit values? (In jiffies) */
-#define LIMIT_REFRESH_INTERVAL	(60 * HZ)
-
-/* datasheet says to divide this number by the fan reading to get fan rpm */
-#define FAN_PERIOD_TO_RPM(x)	((90000 * 60) / (x))
-#define FAN_RPM_TO_PERIOD	FAN_PERIOD_TO_RPM
-#define FAN_PERIOD_INVALID	65535
-#define FAN_DATA_VALID(x)	((x) && (x) != FAN_PERIOD_INVALID)
-
-struct adt7473_data {
-	struct device		*hwmon_dev;
-	struct attribute_group	attrs;
-	struct mutex		lock;
-	char			sensors_valid;
-	char			limits_valid;
-	unsigned long		sensors_last_updated;	/* In jiffies */
-	unsigned long		limits_last_updated;	/* In jiffies */
-
-	u8			volt[ADT7473_VOLT_COUNT];
-	s8			volt_min[ADT7473_VOLT_COUNT];
-	s8			volt_max[ADT7473_VOLT_COUNT];
-
-	s8			temp[ADT7473_TEMP_COUNT];
-	s8			temp_min[ADT7473_TEMP_COUNT];
-	s8			temp_max[ADT7473_TEMP_COUNT];
-	s8			temp_tmin[ADT7473_TEMP_COUNT];
-	/* This is called the !THERM limit in the datasheet */
-	s8			temp_tmax[ADT7473_TEMP_COUNT];
-
-	u16			fan[ADT7473_FAN_COUNT];
-	u16			fan_min[ADT7473_FAN_COUNT];
-
-	u8			pwm[ADT7473_PWM_COUNT];
-	u8			pwm_max[ADT7473_PWM_COUNT];
-	u8			pwm_min[ADT7473_PWM_COUNT];
-	u8			pwm_behavior[ADT7473_PWM_COUNT];
-
-	u8			temp_twos_complement;
-	u8			temp_offset;
-
-	u16			alarm;
-	u8			max_duty_at_overheat;
-};
-
-static int adt7473_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id);
-static int adt7473_detect(struct i2c_client *client,
-			  struct i2c_board_info *info);
-static int adt7473_remove(struct i2c_client *client);
-
-static const struct i2c_device_id adt7473_id[] = {
-	{ "adt7473", 0 },
-	{ }
-};
-
-static struct i2c_driver adt7473_driver = {
-	.class		= I2C_CLASS_HWMON,
-	.driver = {
-		.name	= "adt7473",
-	},
-	.probe		= adt7473_probe,
-	.remove		= adt7473_remove,
-	.id_table	= adt7473_id,
-	.detect		= adt7473_detect,
-	.address_list	= normal_i2c,
-};
-
-/*
- * 16-bit registers on the ADT7473 are low-byte first.  The data sheet says
- * that the low byte must be read before the high byte.
- */
-static inline int adt7473_read_word_data(struct i2c_client *client, u8 reg)
-{
-	u16 foo;
-	foo = i2c_smbus_read_byte_data(client, reg);
-	foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8);
-	return foo;
-}
-
-static inline int adt7473_write_word_data(struct i2c_client *client, u8 reg,
-					  u16 value)
-{
-	return i2c_smbus_write_byte_data(client, reg, value & 0xFF)
-	       && i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
-}
-
-static void adt7473_init_client(struct i2c_client *client)
-{
-	int reg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG1);
-
-	if (!(reg & ADT7473_CFG1_READY)) {
-		dev_err(&client->dev, "Chip not ready.\n");
-	} else {
-		/* start monitoring */
-		i2c_smbus_write_byte_data(client, ADT7473_REG_CFG1,
-					  reg | ADT7473_CFG1_START);
-	}
-}
-
-static struct adt7473_data *adt7473_update_device(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	unsigned long local_jiffies = jiffies;
-	u8 cfg;
-	int i;
-
-	mutex_lock(&data->lock);
-	if (time_before(local_jiffies, data->sensors_last_updated +
-		SENSOR_REFRESH_INTERVAL)
-		&& data->sensors_valid)
-		goto no_sensor_update;
-
-	for (i = 0; i < ADT7473_VOLT_COUNT; i++)
-		data->volt[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_VOLT(i));
-
-	/* Determine temperature encoding */
-	cfg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG5);
-	data->temp_twos_complement = (cfg & ADT7473_CFG5_TEMP_TWOS);
-
-	/*
-	 * What does this do? it implies a variable temperature sensor
-	 * offset, but the datasheet doesn't say anything about this bit
-	 * and other parts of the datasheet imply that "offset64" mode
-	 * means that you shift temp values by -64 if the above bit was set.
-	 */
-	data->temp_offset = (cfg & ADT7473_CFG5_TEMP_OFFSET);
-
-	for (i = 0; i < ADT7473_TEMP_COUNT; i++)
-		data->temp[i] = i2c_smbus_read_byte_data(client,
-							 ADT7473_REG_TEMP(i));
-
-	for (i = 0; i < ADT7473_FAN_COUNT; i++)
-		data->fan[i] = adt7473_read_word_data(client,
-						ADT7473_REG_FAN(i));
-
-	for (i = 0; i < ADT7473_PWM_COUNT; i++)
-		data->pwm[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_PWM(i));
-
-	data->alarm = i2c_smbus_read_byte_data(client, ADT7473_REG_ALARM1);
-	if (data->alarm & ADT7473_OOL)
-		data->alarm |= ALARM2(i2c_smbus_read_byte_data(client,
-							 ADT7473_REG_ALARM2));
-
-	data->sensors_last_updated = local_jiffies;
-	data->sensors_valid = 1;
-
-no_sensor_update:
-	if (time_before(local_jiffies, data->limits_last_updated +
-		LIMIT_REFRESH_INTERVAL)
-		&& data->limits_valid)
-		goto out;
-
-	for (i = 0; i < ADT7473_VOLT_COUNT; i++) {
-		data->volt_min[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_VOLT_MIN(i));
-		data->volt_max[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_VOLT_MAX(i));
-	}
-
-	for (i = 0; i < ADT7473_TEMP_COUNT; i++) {
-		data->temp_min[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_TEMP_MIN(i));
-		data->temp_max[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_TEMP_MAX(i));
-		data->temp_tmin[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_TEMP_TMIN(i));
-		data->temp_tmax[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_TEMP_TMAX(i));
-	}
-
-	for (i = 0; i < ADT7473_FAN_COUNT; i++)
-		data->fan_min[i] = adt7473_read_word_data(client,
-						ADT7473_REG_FAN_MIN(i));
-
-	for (i = 0; i < ADT7473_PWM_COUNT; i++) {
-		data->pwm_max[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_PWM_MAX(i));
-		data->pwm_min[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_PWM_MIN(i));
-		data->pwm_behavior[i] = i2c_smbus_read_byte_data(client,
-						ADT7473_REG_PWM_BHVR(i));
-	}
-
-	i = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG4);
-	data->max_duty_at_overheat = !!(i & ADT7473_CFG4_MAX_DUTY_AT_OVT);
-
-	data->limits_last_updated = local_jiffies;
-	data->limits_valid = 1;
-
-out:
-	mutex_unlock(&data->lock);
-	return data;
-}
-
-/*
- * Conversions
- */
-
-/* IN are scaled acording to built-in resistors */
-static const int adt7473_scaling[] = {  /* .001 Volts */
-	2250, 3300
-};
-#define SCALE(val, from, to)	(((val) * (to) + ((from) / 2)) / (from))
-
-static int decode_volt(int volt_index, u8 raw)
-{
-	return SCALE(raw, 192, adt7473_scaling[volt_index]);
-}
-
-static u8 encode_volt(int volt_index, int cooked)
-{
-	int raw = SCALE(cooked, adt7473_scaling[volt_index], 192);
-	return SENSORS_LIMIT(raw, 0, 255);
-}
-
-static ssize_t show_volt_min(struct device *dev,
-			     struct device_attribute *devattr,
-			     char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n",
-		       decode_volt(attr->index, data->volt_min[attr->index]));
-}
-
-static ssize_t set_volt_min(struct device *dev,
-			    struct device_attribute *devattr,
-			    const char *buf,
-			    size_t count)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long volt;
-
-	if (strict_strtol(buf, 10, &volt))
-		return -EINVAL;
-
-	volt = encode_volt(attr->index, volt);
-
-	mutex_lock(&data->lock);
-	data->volt_min[attr->index] = volt;
-	i2c_smbus_write_byte_data(client, ADT7473_REG_VOLT_MIN(attr->index),
-				  volt);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_volt_max(struct device *dev,
-			     struct device_attribute *devattr,
-			     char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n",
-		       decode_volt(attr->index, data->volt_max[attr->index]));
-}
-
-static ssize_t set_volt_max(struct device *dev,
-			    struct device_attribute *devattr,
-			    const char *buf,
-			    size_t count)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long volt;
-
-	if (strict_strtol(buf, 10, &volt))
-		return -EINVAL;
-
-	volt = encode_volt(attr->index, volt);
-
-	mutex_lock(&data->lock);
-	data->volt_max[attr->index] = volt;
-	i2c_smbus_write_byte_data(client, ADT7473_REG_VOLT_MAX(attr->index),
-				  volt);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_volt(struct device *dev, struct device_attribute *devattr,
-			 char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-
-	return sprintf(buf, "%d\n",
-		       decode_volt(attr->index, data->volt[attr->index]));
-}
-
-/*
- * This chip can report temperature data either as a two's complement
- * number in the range -128 to 127, or as an unsigned number that must
- * be offset by 64.
- */
-static int decode_temp(u8 twos_complement, u8 raw)
-{
-	return twos_complement ? (s8)raw : raw - 64;
-}
-
-static u8 encode_temp(u8 twos_complement, int cooked)
-{
-	u8 ret = twos_complement ? cooked & 0xFF : cooked + 64;
-	return SENSORS_LIMIT(ret, 0, 255);
-}
-
-static ssize_t show_temp_min(struct device *dev,
-			     struct device_attribute *devattr,
-			     char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n", 1000 * decode_temp(
-						data->temp_twos_complement,
-						data->temp_min[attr->index]));
-}
-
-static ssize_t set_temp_min(struct device *dev,
-			    struct device_attribute *devattr,
-			    const char *buf,
-			    size_t count)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp))
-		return -EINVAL;
-
-	temp = DIV_ROUND_CLOSEST(temp, 1000);
-	temp = encode_temp(data->temp_twos_complement, temp);
-
-	mutex_lock(&data->lock);
-	data->temp_min[attr->index] = temp;
-	i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_MIN(attr->index),
-				  temp);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_temp_max(struct device *dev,
-			     struct device_attribute *devattr,
-			     char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n", 1000 * decode_temp(
-						data->temp_twos_complement,
-						data->temp_max[attr->index]));
-}
-
-static ssize_t set_temp_max(struct device *dev,
-			    struct device_attribute *devattr,
-			    const char *buf,
-			    size_t count)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp))
-		return -EINVAL;
-
-	temp = DIV_ROUND_CLOSEST(temp, 1000);
-	temp = encode_temp(data->temp_twos_complement, temp);
-
-	mutex_lock(&data->lock);
-	data->temp_max[attr->index] = temp;
-	i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_MAX(attr->index),
-				  temp);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
-			 char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n", 1000 * decode_temp(
-						data->temp_twos_complement,
-						data->temp[attr->index]));
-}
-
-static ssize_t show_fan_min(struct device *dev,
-			    struct device_attribute *devattr,
-			    char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-
-	if (FAN_DATA_VALID(data->fan_min[attr->index]))
-		return sprintf(buf, "%d\n",
-			       FAN_PERIOD_TO_RPM(data->fan_min[attr->index]));
-	else
-		return sprintf(buf, "0\n");
-}
-
-static ssize_t set_fan_min(struct device *dev,
-			   struct device_attribute *devattr,
-			   const char *buf, size_t count)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp) || !temp)
-		return -EINVAL;
-
-	temp = FAN_RPM_TO_PERIOD(temp);
-	temp = SENSORS_LIMIT(temp, 1, 65534);
-
-	mutex_lock(&data->lock);
-	data->fan_min[attr->index] = temp;
-	adt7473_write_word_data(client, ADT7473_REG_FAN_MIN(attr->index), temp);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
-			char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-
-	if (FAN_DATA_VALID(data->fan[attr->index]))
-		return sprintf(buf, "%d\n",
-			       FAN_PERIOD_TO_RPM(data->fan[attr->index]));
-	else
-		return sprintf(buf, "0\n");
-}
-
-static ssize_t show_max_duty_at_crit(struct device *dev,
-				     struct device_attribute *devattr,
-				     char *buf)
-{
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n", data->max_duty_at_overheat);
-}
-
-static ssize_t set_max_duty_at_crit(struct device *dev,
-				    struct device_attribute *devattr,
-				    const char *buf,
-				    size_t count)
-{
-	u8 reg;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp))
-		return -EINVAL;
-
-	mutex_lock(&data->lock);
-	data->max_duty_at_overheat = !!temp;
-	reg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG4);
-	if (temp)
-		reg |= ADT7473_CFG4_MAX_DUTY_AT_OVT;
-	else
-		reg &= ~ADT7473_CFG4_MAX_DUTY_AT_OVT;
-	i2c_smbus_write_byte_data(client, ADT7473_REG_CFG4, reg);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
-			char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n", data->pwm[attr->index]);
-}
-
-static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
-			const char *buf, size_t count)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp))
-		return -EINVAL;
-
-	temp = SENSORS_LIMIT(temp, 0, 255);
-
-	mutex_lock(&data->lock);
-	data->pwm[attr->index] = temp;
-	i2c_smbus_write_byte_data(client, ADT7473_REG_PWM(attr->index), temp);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_pwm_max(struct device *dev,
-			    struct device_attribute *devattr,
-			    char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n", data->pwm_max[attr->index]);
-}
-
-static ssize_t set_pwm_max(struct device *dev,
-			   struct device_attribute *devattr,
-			   const char *buf,
-			   size_t count)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp))
-		return -EINVAL;
-
-	temp = SENSORS_LIMIT(temp, 0, 255);
-
-	mutex_lock(&data->lock);
-	data->pwm_max[attr->index] = temp;
-	i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_MAX(attr->index),
-				  temp);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_pwm_min(struct device *dev,
-			    struct device_attribute *devattr,
-			    char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n", data->pwm_min[attr->index]);
-}
-
-static ssize_t set_pwm_min(struct device *dev,
-			   struct device_attribute *devattr,
-			   const char *buf,
-			   size_t count)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp))
-		return -EINVAL;
-
-	temp = SENSORS_LIMIT(temp, 0, 255);
-
-	mutex_lock(&data->lock);
-	data->pwm_min[attr->index] = temp;
-	i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_MIN(attr->index),
-				  temp);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_temp_tmax(struct device *dev,
-			      struct device_attribute *devattr,
-			      char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n", 1000 * decode_temp(
-						data->temp_twos_complement,
-						data->temp_tmax[attr->index]));
-}
-
-static ssize_t set_temp_tmax(struct device *dev,
-			     struct device_attribute *devattr,
-			     const char *buf,
-			     size_t count)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp))
-		return -EINVAL;
-
-	temp = DIV_ROUND_CLOSEST(temp, 1000);
-	temp = encode_temp(data->temp_twos_complement, temp);
-
-	mutex_lock(&data->lock);
-	data->temp_tmax[attr->index] = temp;
-	i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_TMAX(attr->index),
-				  temp);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_temp_tmin(struct device *dev,
-			      struct device_attribute *devattr,
-			      char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	return sprintf(buf, "%d\n", 1000 * decode_temp(
-						data->temp_twos_complement,
-						data->temp_tmin[attr->index]));
-}
-
-static ssize_t set_temp_tmin(struct device *dev,
-			     struct device_attribute *devattr,
-			     const char *buf,
-			     size_t count)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp))
-		return -EINVAL;
-
-	temp = DIV_ROUND_CLOSEST(temp, 1000);
-	temp = encode_temp(data->temp_twos_complement, temp);
-
-	mutex_lock(&data->lock);
-	data->temp_tmin[attr->index] = temp;
-	i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_TMIN(attr->index),
-				  temp);
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_pwm_enable(struct device *dev,
-			       struct device_attribute *devattr,
-			       char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-
-	switch (data->pwm_behavior[attr->index] >> ADT7473_PWM_BHVR_SHIFT) {
-	case 3:
-		return sprintf(buf, "0\n");
-	case 7:
-		return sprintf(buf, "1\n");
-	default:
-		return sprintf(buf, "2\n");
-	}
-}
-
-static ssize_t set_pwm_enable(struct device *dev,
-			      struct device_attribute *devattr,
-			      const char *buf,
-			      size_t count)
-{
-	u8 reg;
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp))
-		return -EINVAL;
-
-	switch (temp) {
-	case 0:
-		temp = 3;
-		break;
-	case 1:
-		temp = 7;
-		break;
-	case 2:
-		/* Enter automatic mode with fans off */
-		temp = 4;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	mutex_lock(&data->lock);
-	reg = i2c_smbus_read_byte_data(client,
-				       ADT7473_REG_PWM_BHVR(attr->index));
-	reg = (temp << ADT7473_PWM_BHVR_SHIFT) |
-	      (reg & ~ADT7473_PWM_BHVR_MASK);
-	i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_BHVR(attr->index),
-				  reg);
-	data->pwm_behavior[attr->index] = reg;
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_pwm_auto_temp(struct device *dev,
-				  struct device_attribute *devattr,
-				  char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-	int bhvr = data->pwm_behavior[attr->index] >> ADT7473_PWM_BHVR_SHIFT;
-
-	switch (bhvr) {
-	case 3:
-	case 4:
-	case 7:
-		return sprintf(buf, "0\n");
-	case 0:
-	case 1:
-	case 5:
-	case 6:
-		return sprintf(buf, "%d\n", bhvr + 1);
-	case 2:
-		return sprintf(buf, "4\n");
-	}
-	/* shouldn't ever get here */
-	BUG();
-}
-
-static ssize_t set_pwm_auto_temp(struct device *dev,
-				 struct device_attribute *devattr,
-				 const char *buf,
-				 size_t count)
-{
-	u8 reg;
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct adt7473_data *data = i2c_get_clientdata(client);
-	long temp;
-
-	if (strict_strtol(buf, 10, &temp))
-		return -EINVAL;
-
-	switch (temp) {
-	case 1:
-	case 2:
-	case 6:
-	case 7:
-		temp--;
-		break;
-	case 0:
-		temp = 4;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	mutex_lock(&data->lock);
-	reg = i2c_smbus_read_byte_data(client,
-				       ADT7473_REG_PWM_BHVR(attr->index));
-	reg = (temp << ADT7473_PWM_BHVR_SHIFT) |
-	      (reg & ~ADT7473_PWM_BHVR_MASK);
-	i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_BHVR(attr->index),
-				  reg);
-	data->pwm_behavior[attr->index] = reg;
-	mutex_unlock(&data->lock);
-
-	return count;
-}
-
-static ssize_t show_alarm(struct device *dev,
-			  struct device_attribute *devattr,
-			  char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct adt7473_data *data = adt7473_update_device(dev);
-
-	if (data->alarm & attr->index)
-		return sprintf(buf, "1\n");
-	else
-		return sprintf(buf, "0\n");
-}
-
-
-static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_volt_max,
-			  set_volt_max, 0);
-static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_volt_max,
-			  set_volt_max, 1);
-
-static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_volt_min,
-			  set_volt_min, 0);
-static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_volt_min,
-			  set_volt_min, 1);
-
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_volt, NULL, 0);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_volt, NULL, 1);
-
-static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL,
-			  ADT7473_VCCP_ALARM);
-static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL,
-			  ADT7473_VCC_ALARM);
-
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
-			  set_temp_max, 0);
-static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
-			  set_temp_max, 1);
-static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max,
-			  set_temp_max, 2);
-
-static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min,
-			  set_temp_min, 0);
-static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min,
-			  set_temp_min, 1);
-static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min,
-			  set_temp_min, 2);
-
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
-
-static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
-			  ADT7473_R1T_ALARM | ALARM2(ADT7473_R1T_SHORT));
-static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
-			  ADT7473_LT_ALARM);
-static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
-			  ADT7473_R2T_ALARM | ALARM2(ADT7473_R2T_SHORT));
-
-static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
-			  set_fan_min, 0);
-static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
-			  set_fan_min, 1);
-static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
-			  set_fan_min, 2);
-static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
-			  set_fan_min, 3);
-
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
-
-static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL,
-			  ALARM2(ADT7473_FAN1_ALARM));
-static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL,
-			  ALARM2(ADT7473_FAN2_ALARM));
-static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL,
-			  ALARM2(ADT7473_FAN3_ALARM));
-static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL,
-			  ALARM2(ADT7473_FAN4_ALARM));
-
-static SENSOR_DEVICE_ATTR(pwm_use_point2_pwm_at_crit, S_IWUSR | S_IRUGO,
-			  show_max_duty_at_crit, set_max_duty_at_crit, 0);
-
-static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
-static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
-static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2);
-
-static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
-			  show_pwm_min, set_pwm_min, 0);
-static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO,
-			  show_pwm_min, set_pwm_min, 1);
-static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO,
-			  show_pwm_min, set_pwm_min, 2);
-
-static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
-			  show_pwm_max, set_pwm_max, 0);
-static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO,
-			  show_pwm_max, set_pwm_max, 1);
-static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO,
-			  show_pwm_max, set_pwm_max, 2);
-
-static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IWUSR | S_IRUGO,
-			  show_temp_tmin, set_temp_tmin, 0);
-static SENSOR_DEVICE_ATTR(temp2_auto_point1_temp, S_IWUSR | S_IRUGO,
-			  show_temp_tmin, set_temp_tmin, 1);
-static SENSOR_DEVICE_ATTR(temp3_auto_point1_temp, S_IWUSR | S_IRUGO,
-			  show_temp_tmin, set_temp_tmin, 2);
-
-static SENSOR_DEVICE_ATTR(temp1_auto_point2_temp, S_IWUSR | S_IRUGO,
-			  show_temp_tmax, set_temp_tmax, 0);
-static SENSOR_DEVICE_ATTR(temp2_auto_point2_temp, S_IWUSR | S_IRUGO,
-			  show_temp_tmax, set_temp_tmax, 1);
-static SENSOR_DEVICE_ATTR(temp3_auto_point2_temp, S_IWUSR | S_IRUGO,
-			  show_temp_tmax, set_temp_tmax, 2);
-
-static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
-			  set_pwm_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
-			  set_pwm_enable, 1);
-static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
-			  set_pwm_enable, 2);
-
-static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO,
-			  show_pwm_auto_temp, set_pwm_auto_temp, 0);
-static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO,
-			  show_pwm_auto_temp, set_pwm_auto_temp, 1);
-static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO,
-			  show_pwm_auto_temp, set_pwm_auto_temp, 2);
-
-static struct attribute *adt7473_attr[] =
-{
-	&sensor_dev_attr_in1_max.dev_attr.attr,
-	&sensor_dev_attr_in2_max.dev_attr.attr,
-	&sensor_dev_attr_in1_min.dev_attr.attr,
-	&sensor_dev_attr_in2_min.dev_attr.attr,
-	&sensor_dev_attr_in1_input.dev_attr.attr,
-	&sensor_dev_attr_in2_input.dev_attr.attr,
-	&sensor_dev_attr_in1_alarm.dev_attr.attr,
-	&sensor_dev_attr_in2_alarm.dev_attr.attr,
-
-	&sensor_dev_attr_temp1_max.dev_attr.attr,
-	&sensor_dev_attr_temp2_max.dev_attr.attr,
-	&sensor_dev_attr_temp3_max.dev_attr.attr,
-	&sensor_dev_attr_temp1_min.dev_attr.attr,
-	&sensor_dev_attr_temp2_min.dev_attr.attr,
-	&sensor_dev_attr_temp3_min.dev_attr.attr,
-	&sensor_dev_attr_temp1_input.dev_attr.attr,
-	&sensor_dev_attr_temp2_input.dev_attr.attr,
-	&sensor_dev_attr_temp3_input.dev_attr.attr,
-	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
-	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
-	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
-	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
-	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
-	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
-
-	&sensor_dev_attr_fan1_min.dev_attr.attr,
-	&sensor_dev_attr_fan2_min.dev_attr.attr,
-	&sensor_dev_attr_fan3_min.dev_attr.attr,
-	&sensor_dev_attr_fan4_min.dev_attr.attr,
-	&sensor_dev_attr_fan1_input.dev_attr.attr,
-	&sensor_dev_attr_fan2_input.dev_attr.attr,
-	&sensor_dev_attr_fan3_input.dev_attr.attr,
-	&sensor_dev_attr_fan4_input.dev_attr.attr,
-	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
-	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
-	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
-	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
-
-	&sensor_dev_attr_pwm_use_point2_pwm_at_crit.dev_attr.attr,
-
-	&sensor_dev_attr_pwm1.dev_attr.attr,
-	&sensor_dev_attr_pwm2.dev_attr.attr,
-	&sensor_dev_attr_pwm3.dev_attr.attr,
-	&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
-	&sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
-	&sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
-	&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
-	&sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
-	&sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
-
-	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
-	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
-	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
-	&sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
-	&sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
-	&sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
-
-	NULL
-};
-
-/* Return 0 if detection is successful, -ENODEV otherwise */
-static int adt7473_detect(struct i2c_client *client,
-			  struct i2c_board_info *info)
-{
-	struct i2c_adapter *adapter = client->adapter;
-	int vendor, device, revision;
-
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
-		return -ENODEV;
-
-	vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR);
-	if (vendor != ADT7473_VENDOR)
-		return -ENODEV;
-
-	device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE);
-	if (device != ADT7473_DEVICE)
-		return -ENODEV;
-
-	revision = i2c_smbus_read_byte_data(client, ADT7473_REG_REVISION);
-	if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69)
-		return -ENODEV;
-
-	strlcpy(info->type, "adt7473", I2C_NAME_SIZE);
-
-	return 0;
-}
-
-static int adt7473_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct adt7473_data *data;
-	int err;
-
-	data = kzalloc(sizeof(struct adt7473_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	i2c_set_clientdata(client, data);
-	mutex_init(&data->lock);
-
-	dev_info(&client->dev, "%s chip found\n", client->name);
-
-	/* Initialize the ADT7473 chip */
-	adt7473_init_client(client);
-
-	/* Register sysfs hooks */
-	data->attrs.attrs = adt7473_attr;
-	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
-	if (err)
-		goto exit_free;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-exit_free:
-	kfree(data);
-exit:
-	return err;
-}
-
-static int adt7473_remove(struct i2c_client *client)
-{
-	struct adt7473_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-	kfree(data);
-	return 0;
-}
-
-static int __init adt7473_init(void)
-{
-	pr_notice("The adt7473 driver is deprecated, please use the adt7475 "
-		  "driver instead\n");
-	return i2c_add_driver(&adt7473_driver);
-}
-
-static void __exit adt7473_exit(void)
-{
-	i2c_del_driver(&adt7473_driver);
-}
-
-MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
-MODULE_DESCRIPTION("ADT7473 driver");
-MODULE_LICENSE("GPL");
-
-module_init(adt7473_init);
-module_exit(adt7473_exit);
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
new file mode 100644
index 0000000..7f94810
--- /dev/null
+++ b/drivers/hwmon/asc7621.c
@@ -0,0 +1,1255 @@
+/*
+ * asc7621.c - Part of lm_sensors, Linux kernel modules for hardware monitoring
+ * Copyright (c) 2007, 2010 George Joseph  <george.joseph@fairview5.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {
+	0x2c, 0x2d, 0x2e, I2C_CLIENT_END
+};
+
+enum asc7621_type {
+	asc7621,
+	asc7621a
+};
+
+#define INTERVAL_HIGH   (HZ + HZ / 2)
+#define INTERVAL_LOW    (1 * 60 * HZ)
+#define PRI_NONE        0
+#define PRI_LOW         1
+#define PRI_HIGH        2
+#define FIRST_CHIP      asc7621
+#define LAST_CHIP       asc7621a
+
+struct asc7621_chip {
+	char *name;
+	enum asc7621_type chip_type;
+	u8 company_reg;
+	u8 company_id;
+	u8 verstep_reg;
+	u8 verstep_id;
+	unsigned short *addresses;
+};
+
+static struct asc7621_chip asc7621_chips[] = {
+	{
+		.name = "asc7621",
+		.chip_type = asc7621,
+		.company_reg = 0x3e,
+		.company_id = 0x61,
+		.verstep_reg = 0x3f,
+		.verstep_id = 0x6c,
+		.addresses = normal_i2c,
+	 },
+	{
+		.name = "asc7621a",
+		.chip_type = asc7621a,
+		.company_reg = 0x3e,
+		.company_id = 0x61,
+		.verstep_reg = 0x3f,
+		.verstep_id = 0x6d,
+		.addresses = normal_i2c,
+	 },
+};
+
+/*
+ * Defines the highest register to be used, not the count.
+ * The actual count will probably be smaller because of gaps
+ * in the implementation (unused register locations).
+ * This define will safely set the array size of both the parameter
+ * and data arrays.
+ * This comes from the data sheet register description table.
+ */
+#define LAST_REGISTER 0xff
+
+struct asc7621_data {
+	struct i2c_client client;
+	struct device *class_dev;
+	struct mutex update_lock;
+	int valid;		/* !=0 if following fields are valid */
+	unsigned long last_high_reading;	/* In jiffies */
+	unsigned long last_low_reading;		/* In jiffies */
+	/*
+	 * Registers we care about occupy the corresponding index
+	 * in the array.  Registers we don't care about are left
+	 * at 0.
+	 */
+	u8 reg[LAST_REGISTER + 1];
+};
+
+/*
+ * Macro to get the parent asc7621_param structure
+ * from a sensor_device_attribute passed into the
+ * show/store functions.
+ */
+#define to_asc7621_param(_sda) \
+	container_of(_sda, struct asc7621_param, sda)
+
+/*
+ * Each parameter to be retrieved needs an asc7621_param structure
+ * allocated.  It contains the sensor_device_attribute structure
+ * and the control info needed to retrieve the value from the register map.
+ */
+struct asc7621_param {
+	struct sensor_device_attribute sda;
+	u8 priority;
+	u8 msb[3];
+	u8 lsb[3];
+	u8 mask[3];
+	u8 shift[3];
+};
+
+/*
+ * This is the map that ultimately indicates whether we'll be
+ * retrieving a register value or not, and at what frequency.
+ */
+static u8 asc7621_register_priorities[255];
+
+static struct asc7621_data *asc7621_update_device(struct device *dev);
+
+static inline u8 read_byte(struct i2c_client *client, u8 reg)
+{
+	int res = i2c_smbus_read_byte_data(client, reg);
+	if (res < 0) {
+		dev_err(&client->dev,
+			"Unable to read from register 0x%02x.\n", reg);
+		return 0;
+	};
+	return res & 0xff;
+}
+
+static inline int write_byte(struct i2c_client *client, u8 reg, u8 data)
+{
+	int res = i2c_smbus_write_byte_data(client, reg, data);
+	if (res < 0) {
+		dev_err(&client->dev,
+			"Unable to write value 0x%02x to register 0x%02x.\n",
+			data, reg);
+	};
+	return res;
+}
+
+/*
+ * Data Handlers
+ * Each function handles the formatting, storage
+ * and retrieval of like parameters.
+ */
+
+#define SETUP_SHOW_data_param(d, a) \
+	struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \
+	struct asc7621_data *data = asc7621_update_device(d); \
+	struct asc7621_param *param = to_asc7621_param(sda)
+
+#define SETUP_STORE_data_param(d, a) \
+	struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \
+	struct i2c_client *client = to_i2c_client(d); \
+	struct asc7621_data *data = i2c_get_clientdata(client); \
+	struct asc7621_param *param = to_asc7621_param(sda)
+
+/*
+ * u8 is just what it sounds like...an unsigned byte with no
+ * special formatting.
+ */
+static ssize_t show_u8(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+
+	return sprintf(buf, "%u\n", data->reg[param->msb[0]]);
+}
+
+static ssize_t store_u8(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	long reqval;
+
+	if (strict_strtol(buf, 10, &reqval))
+		return -EINVAL;
+
+	reqval = SENSORS_LIMIT(reqval, 0, 255);
+
+	mutex_lock(&data->update_lock);
+	data->reg[param->msb[0]] = reqval;
+	write_byte(client, param->msb[0], reqval);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/*
+ * Many of the config values occupy only a few bits of a register.
+ */
+static ssize_t show_bitmask(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+
+	return sprintf(buf, "%u\n",
+		       (data->reg[param->msb[0]] >> param->
+			shift[0]) & param->mask[0]);
+}
+
+static ssize_t store_bitmask(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	long reqval;
+	u8 currval;
+
+	if (strict_strtol(buf, 10, &reqval))
+		return -EINVAL;
+
+	reqval = SENSORS_LIMIT(reqval, 0, param->mask[0]);
+
+	reqval = (reqval & param->mask[0]) << param->shift[0];
+
+	mutex_lock(&data->update_lock);
+	currval = read_byte(client, param->msb[0]);
+	reqval |= (currval & ~(param->mask[0] << param->shift[0]));
+	data->reg[param->msb[0]] = reqval;
+	write_byte(client, param->msb[0], reqval);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/*
+ * 16 bit fan rpm values
+ * reported by the device as the number of 11.111us periods (90khz)
+ * between full fan rotations.  Therefore...
+ * RPM = (90000 * 60) / register value
+ */
+static ssize_t show_fan16(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	u16 regval;
+
+	mutex_lock(&data->update_lock);
+	regval = (data->reg[param->msb[0]] << 8) | data->reg[param->lsb[0]];
+	mutex_unlock(&data->update_lock);
+
+	return sprintf(buf, "%u\n",
+		       (regval == 0 ? -1 : (regval) ==
+			0xffff ? 0 : 5400000 / regval));
+}
+
+static ssize_t store_fan16(struct device *dev,
+			   struct device_attribute *attr, const char *buf,
+			   size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	long reqval;
+
+	if (strict_strtol(buf, 10, &reqval))
+		return -EINVAL;
+
+	reqval =
+	    (SENSORS_LIMIT((reqval) <= 0 ? 0 : 5400000 / (reqval), 0, 65534));
+
+	mutex_lock(&data->update_lock);
+	data->reg[param->msb[0]] = (reqval >> 8) & 0xff;
+	data->reg[param->lsb[0]] = reqval & 0xff;
+	write_byte(client, param->msb[0], data->reg[param->msb[0]]);
+	write_byte(client, param->lsb[0], data->reg[param->lsb[0]]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/*
+ * Voltages are scaled in the device so that the nominal voltage
+ * is 3/4ths of the 0-255 range (i.e. 192).
+ * If all voltages are 'normal' then all voltage registers will
+ * read 0xC0.  This doesn't help us if we don't have a point of refernce.
+ * The data sheet however provides us with the full scale value for each
+ * which is stored in in_scaling.  The sda->index parameter value provides
+ * the index into in_scaling.
+ *
+ * NOTE: The chip expects the first 2 inputs be 2.5 and 2.25 volts
+ * respectively. That doesn't mean that's what the motherboard provides. :)
+ */
+
+static int asc7621_in_scaling[] = {
+	3320, 3000, 4380, 6640, 16000
+};
+
+static ssize_t show_in10(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	u16 regval;
+	u8 nr = sda->index;
+
+	mutex_lock(&data->update_lock);
+	regval = (data->reg[param->msb[0]] * asc7621_in_scaling[nr]) / 256;
+
+	/* The LSB value is a 2-bit scaling of the MSB's LSbit value.
+	 * I.E.  If the maximim voltage for this input is 6640 millivolts then
+	 * a MSB register value of 0 = 0mv and 255 = 6640mv.
+	 * A 1 step change therefore represents 25.9mv (6640 / 256).
+	 * The extra 2-bits therefore represent increments of 6.48mv.
+	 */
+	regval += ((asc7621_in_scaling[nr] / 256) / 4) *
+	    (data->reg[param->lsb[0]] >> 6);
+
+	mutex_unlock(&data->update_lock);
+
+	return sprintf(buf, "%u\n", regval);
+}
+
+/* 8 bit voltage values (the mins and maxs) */
+static ssize_t show_in8(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	u8 nr = sda->index;
+
+	return sprintf(buf, "%u\n",
+		       ((data->reg[param->msb[0]] *
+			 asc7621_in_scaling[nr]) / 256));
+}
+
+static ssize_t store_in8(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	long reqval;
+	u8 nr = sda->index;
+
+	if (strict_strtol(buf, 10, &reqval))
+		return -EINVAL;
+
+	reqval = SENSORS_LIMIT(reqval, 0, asc7621_in_scaling[nr]);
+
+	reqval = (reqval * 255 + 128) / asc7621_in_scaling[nr];
+
+	mutex_lock(&data->update_lock);
+	data->reg[param->msb[0]] = reqval;
+	write_byte(client, param->msb[0], reqval);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_temp8(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+
+	return sprintf(buf, "%d\n", ((s8) data->reg[param->msb[0]]) * 1000);
+}
+
+static ssize_t store_temp8(struct device *dev,
+			   struct device_attribute *attr, const char *buf,
+			   size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	long reqval;
+	s8 temp;
+
+	if (strict_strtol(buf, 10, &reqval))
+		return -EINVAL;
+
+	reqval = SENSORS_LIMIT(reqval, -127000, 127000);
+
+	temp = reqval / 1000;
+
+	mutex_lock(&data->update_lock);
+	data->reg[param->msb[0]] = temp;
+	write_byte(client, param->msb[0], temp);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/*
+ * Temperatures that occupy 2 bytes always have the whole
+ * number of degrees in the MSB with some part of the LSB
+ * indicating fractional degrees.
+ */
+
+/*   mmmmmmmm.llxxxxxx */
+static ssize_t show_temp10(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	u8 msb, lsb;
+	int temp;
+
+	mutex_lock(&data->update_lock);
+	msb = data->reg[param->msb[0]];
+	lsb = (data->reg[param->lsb[0]] >> 6) & 0x03;
+	temp = (((s8) msb) * 1000) + (lsb * 250);
+	mutex_unlock(&data->update_lock);
+
+	return sprintf(buf, "%d\n", temp);
+}
+
+/*   mmmmmm.ll */
+static ssize_t show_temp62(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	u8 regval = data->reg[param->msb[0]];
+	int temp = ((s8) (regval & 0xfc) * 1000) + ((regval & 0x03) * 250);
+
+	return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t store_temp62(struct device *dev,
+			    struct device_attribute *attr, const char *buf,
+			    size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	long reqval, i, f;
+	s8 temp;
+
+	if (strict_strtol(buf, 10, &reqval))
+		return -EINVAL;
+
+	reqval = SENSORS_LIMIT(reqval, -32000, 31750);
+	i = reqval / 1000;
+	f = reqval - (i * 1000);
+	temp = i << 2;
+	temp |= f / 250;
+
+	mutex_lock(&data->update_lock);
+	data->reg[param->msb[0]] = temp;
+	write_byte(client, param->msb[0], temp);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/*
+ * The aSC7621 doesn't provide an "auto_point2".  Instead, you
+ * specify the auto_point1 and a range.  To keep with the sysfs
+ * hwmon specs, we synthesize the auto_point_2 from them.
+ */
+
+static u32 asc7621_range_map[] = {
+	2000, 2500, 3330, 4000, 5000, 6670, 8000, 10000,
+	13330, 16000, 20000, 26670, 32000, 40000, 53330, 80000,
+};
+
+static ssize_t show_ap2_temp(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	long auto_point1;
+	u8 regval;
+	int temp;
+
+	mutex_lock(&data->update_lock);
+	auto_point1 = ((s8) data->reg[param->msb[1]]) * 1000;
+	regval =
+	    ((data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]);
+	temp = auto_point1 + asc7621_range_map[SENSORS_LIMIT(regval, 0, 15)];
+	mutex_unlock(&data->update_lock);
+
+	return sprintf(buf, "%d\n", temp);
+
+}
+
+static ssize_t store_ap2_temp(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	long reqval, auto_point1;
+	int i;
+	u8 currval, newval = 0;
+
+	if (strict_strtol(buf, 10, &reqval))
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	auto_point1 = data->reg[param->msb[1]] * 1000;
+	reqval = SENSORS_LIMIT(reqval, auto_point1 + 2000, auto_point1 + 80000);
+
+	for (i = ARRAY_SIZE(asc7621_range_map) - 1; i >= 0; i--) {
+		if (reqval >= auto_point1 + asc7621_range_map[i]) {
+			newval = i;
+			break;
+		}
+	}
+
+	newval = (newval & param->mask[0]) << param->shift[0];
+	currval = read_byte(client, param->msb[0]);
+	newval |= (currval & ~(param->mask[0] << param->shift[0]));
+	data->reg[param->msb[0]] = newval;
+	write_byte(client, param->msb[0], newval);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_pwm_ac(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	u8 config, altbit, regval;
+	u8 map[] = {
+		0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10,
+		0x08, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f
+	};
+
+	mutex_lock(&data->update_lock);
+	config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
+	altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1];
+	regval = config | (altbit << 3);
+	mutex_unlock(&data->update_lock);
+
+	return sprintf(buf, "%u\n", map[SENSORS_LIMIT(regval, 0, 15)]);
+}
+
+static ssize_t store_pwm_ac(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	unsigned long reqval;
+	u8 currval, config, altbit, newval;
+	u16 map[] = {
+		0x04, 0x00, 0x01, 0xff, 0x02, 0xff, 0x05, 0x06,
+		0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
+		0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
+	};
+
+	if (strict_strtoul(buf, 10, &reqval))
+		return -EINVAL;
+
+	if (reqval > 31)
+		return -EINVAL;
+
+	reqval = map[reqval];
+	if (reqval == 0xff)
+		return -EINVAL;
+
+	config = reqval & 0x07;
+	altbit = (reqval >> 3) & 0x01;
+
+	config = (config & param->mask[0]) << param->shift[0];
+	altbit = (altbit & param->mask[1]) << param->shift[1];
+
+	mutex_lock(&data->update_lock);
+	currval = read_byte(client, param->msb[0]);
+	newval = config | (currval & ~(param->mask[0] << param->shift[0]));
+	newval = altbit | (newval & ~(param->mask[1] << param->shift[1]));
+	data->reg[param->msb[0]] = newval;
+	write_byte(client, param->msb[0], newval);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_pwm_enable(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	u8 config, altbit, minoff, val, newval;
+
+	mutex_lock(&data->update_lock);
+	config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
+	altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1];
+	minoff = (data->reg[param->msb[2]] >> param->shift[2]) & param->mask[2];
+	mutex_unlock(&data->update_lock);
+
+	val = config | (altbit << 3);
+	newval = 0;
+
+	if (val == 3 || val >= 10)
+		newval = 255;
+	else if (val == 4)
+		newval = 0;
+	else if (val == 7)
+		newval = 1;
+	else if (minoff == 1)
+		newval = 2;
+	else
+		newval = 3;
+
+	return sprintf(buf, "%u\n", newval);
+}
+
+static ssize_t store_pwm_enable(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	long reqval;
+	u8 currval, config, altbit, newval, minoff = 255;
+
+	if (strict_strtol(buf, 10, &reqval))
+		return -EINVAL;
+
+	switch (reqval) {
+	case 0:
+		newval = 0x04;
+		break;
+	case 1:
+		newval = 0x07;
+		break;
+	case 2:
+		newval = 0x00;
+		minoff = 1;
+		break;
+	case 3:
+		newval = 0x00;
+		minoff = 0;
+		break;
+	case 255:
+		newval = 0x03;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	config = newval & 0x07;
+	altbit = (newval >> 3) & 0x01;
+
+	mutex_lock(&data->update_lock);
+	config = (config & param->mask[0]) << param->shift[0];
+	altbit = (altbit & param->mask[1]) << param->shift[1];
+	currval = read_byte(client, param->msb[0]);
+	newval = config | (currval & ~(param->mask[0] << param->shift[0]));
+	newval = altbit | (newval & ~(param->mask[1] << param->shift[1]));
+	data->reg[param->msb[0]] = newval;
+	write_byte(client, param->msb[0], newval);
+	if (minoff < 255) {
+		minoff = (minoff & param->mask[2]) << param->shift[2];
+		currval = read_byte(client, param->msb[2]);
+		newval =
+		    minoff | (currval & ~(param->mask[2] << param->shift[2]));
+		data->reg[param->msb[2]] = newval;
+		write_byte(client, param->msb[2], newval);
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static u32 asc7621_pwm_freq_map[] = {
+	10, 15, 23, 30, 38, 47, 62, 94,
+	23000, 24000, 25000, 26000, 27000, 28000, 29000, 30000
+};
+
+static ssize_t show_pwm_freq(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	u8 regval =
+	    (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
+
+	regval = SENSORS_LIMIT(regval, 0, 15);
+
+	return sprintf(buf, "%u\n", asc7621_pwm_freq_map[regval]);
+}
+
+static ssize_t store_pwm_freq(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	unsigned long reqval;
+	u8 currval, newval = 255;
+	int i;
+
+	if (strict_strtoul(buf, 10, &reqval))
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(asc7621_pwm_freq_map); i++) {
+		if (reqval == asc7621_pwm_freq_map[i]) {
+			newval = i;
+			break;
+		}
+	}
+	if (newval == 255)
+		return -EINVAL;
+
+	newval = (newval & param->mask[0]) << param->shift[0];
+
+	mutex_lock(&data->update_lock);
+	currval = read_byte(client, param->msb[0]);
+	newval |= (currval & ~(param->mask[0] << param->shift[0]));
+	data->reg[param->msb[0]] = newval;
+	write_byte(client, param->msb[0], newval);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static u32 asc7621_pwm_auto_spinup_map[] =  {
+	0, 100, 250, 400, 700, 1000, 2000, 4000
+};
+
+static ssize_t show_pwm_ast(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	u8 regval =
+	    (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
+
+	regval = SENSORS_LIMIT(regval, 0, 7);
+
+	return sprintf(buf, "%u\n", asc7621_pwm_auto_spinup_map[regval]);
+
+}
+
+static ssize_t store_pwm_ast(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	long reqval;
+	u8 currval, newval = 255;
+	u32 i;
+
+	if (strict_strtol(buf, 10, &reqval))
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(asc7621_pwm_auto_spinup_map); i++) {
+		if (reqval == asc7621_pwm_auto_spinup_map[i]) {
+			newval = i;
+			break;
+		}
+	}
+	if (newval == 255)
+		return -EINVAL;
+
+	newval = (newval & param->mask[0]) << param->shift[0];
+
+	mutex_lock(&data->update_lock);
+	currval = read_byte(client, param->msb[0]);
+	newval |= (currval & ~(param->mask[0] << param->shift[0]));
+	data->reg[param->msb[0]] = newval;
+	write_byte(client, param->msb[0], newval);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static u32 asc7621_temp_smoothing_time_map[] = {
+	35000, 17600, 11800, 7000, 4400, 3000, 1600, 800
+};
+
+static ssize_t show_temp_st(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	SETUP_SHOW_data_param(dev, attr);
+	u8 regval =
+	    (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
+	regval = SENSORS_LIMIT(regval, 0, 7);
+
+	return sprintf(buf, "%u\n", asc7621_temp_smoothing_time_map[regval]);
+}
+
+static ssize_t store_temp_st(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	SETUP_STORE_data_param(dev, attr);
+	long reqval;
+	u8 currval, newval = 255;
+	u32 i;
+
+	if (strict_strtol(buf, 10, &reqval))
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(asc7621_temp_smoothing_time_map); i++) {
+		if (reqval == asc7621_temp_smoothing_time_map[i]) {
+			newval = i;
+			break;
+		}
+	}
+
+	if (newval == 255)
+		return -EINVAL;
+
+	newval = (newval & param->mask[0]) << param->shift[0];
+
+	mutex_lock(&data->update_lock);
+	currval = read_byte(client, param->msb[0]);
+	newval |= (currval & ~(param->mask[0] << param->shift[0]));
+	data->reg[param->msb[0]] = newval;
+	write_byte(client, param->msb[0], newval);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/*
+ * End of data handlers
+ *
+ * These defines do nothing more than make the table easier
+ * to read when wrapped at column 80.
+ */
+
+/*
+ * Creates a variable length array inititalizer.
+ * VAA(1,3,5,7) would produce {1,3,5,7}
+ */
+#define VAA(args...) {args}
+
+#define PREAD(name, n, pri, rm, rl, m, s, r) \
+	{.sda = SENSOR_ATTR(name, S_IRUGO, show_##r, NULL, n), \
+	  .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \
+	  .shift[0] = s,}
+
+#define PWRITE(name, n, pri, rm, rl, m, s, r) \
+	{.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \
+	  .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \
+	  .shift[0] = s,}
+
+/*
+ * PWRITEM assumes that the initializers for the .msb, .lsb, .mask and .shift
+ * were created using the VAA macro.
+ */
+#define PWRITEM(name, n, pri, rm, rl, m, s, r) \
+	{.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \
+	  .priority = pri, .msb = rm, .lsb = rl, .mask = m, .shift = s,}
+
+static struct asc7621_param asc7621_params[] = {
+	PREAD(in0_input, 0, PRI_HIGH, 0x20, 0x13, 0, 0, in10),
+	PREAD(in1_input, 1, PRI_HIGH, 0x21, 0x18, 0, 0, in10),
+	PREAD(in2_input, 2, PRI_HIGH, 0x22, 0x11, 0, 0, in10),
+	PREAD(in3_input, 3, PRI_HIGH, 0x23, 0x12, 0, 0, in10),
+	PREAD(in4_input, 4, PRI_HIGH, 0x24, 0x14, 0, 0, in10),
+
+	PWRITE(in0_min, 0, PRI_LOW, 0x44, 0, 0, 0, in8),
+	PWRITE(in1_min, 1, PRI_LOW, 0x46, 0, 0, 0, in8),
+	PWRITE(in2_min, 2, PRI_LOW, 0x48, 0, 0, 0, in8),
+	PWRITE(in3_min, 3, PRI_LOW, 0x4a, 0, 0, 0, in8),
+	PWRITE(in4_min, 4, PRI_LOW, 0x4c, 0, 0, 0, in8),
+
+	PWRITE(in0_max, 0, PRI_LOW, 0x45, 0, 0, 0, in8),
+	PWRITE(in1_max, 1, PRI_LOW, 0x47, 0, 0, 0, in8),
+	PWRITE(in2_max, 2, PRI_LOW, 0x49, 0, 0, 0, in8),
+	PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8),
+	PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8),
+
+	PREAD(in0_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 0, bitmask),
+	PREAD(in1_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 1, bitmask),
+	PREAD(in2_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 2, bitmask),
+	PREAD(in3_alarm, 3, PRI_LOW, 0x41, 0, 0x01, 3, bitmask),
+	PREAD(in4_alarm, 4, PRI_LOW, 0x42, 0, 0x01, 0, bitmask),
+
+	PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16),
+	PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16),
+	PREAD(fan3_input, 2, PRI_HIGH, 0x2d, 0x2c, 0, 0, fan16),
+	PREAD(fan4_input, 3, PRI_HIGH, 0x2f, 0x2e, 0, 0, fan16),
+
+	PWRITE(fan1_min, 0, PRI_LOW, 0x55, 0x54, 0, 0, fan16),
+	PWRITE(fan2_min, 1, PRI_LOW, 0x57, 0x56, 0, 0, fan16),
+	PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16),
+	PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16),
+
+	PREAD(fan1_alarm, 0, PRI_LOW, 0x42, 0, 0x01, 0, bitmask),
+	PREAD(fan2_alarm, 1, PRI_LOW, 0x42, 0, 0x01, 1, bitmask),
+	PREAD(fan3_alarm, 2, PRI_LOW, 0x42, 0, 0x01, 2, bitmask),
+	PREAD(fan4_alarm, 3, PRI_LOW, 0x42, 0, 0x01, 3, bitmask),
+
+	PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10),
+	PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10),
+	PREAD(temp3_input, 2, PRI_HIGH, 0x27, 0x16, 0, 0, temp10),
+	PREAD(temp4_input, 3, PRI_HIGH, 0x33, 0x17, 0, 0, temp10),
+	PREAD(temp5_input, 4, PRI_HIGH, 0xf7, 0xf6, 0, 0, temp10),
+	PREAD(temp6_input, 5, PRI_HIGH, 0xf9, 0xf8, 0, 0, temp10),
+	PREAD(temp7_input, 6, PRI_HIGH, 0xfb, 0xfa, 0, 0, temp10),
+	PREAD(temp8_input, 7, PRI_HIGH, 0xfd, 0xfc, 0, 0, temp10),
+
+	PWRITE(temp1_min, 0, PRI_LOW, 0x4e, 0, 0, 0, temp8),
+	PWRITE(temp2_min, 1, PRI_LOW, 0x50, 0, 0, 0, temp8),
+	PWRITE(temp3_min, 2, PRI_LOW, 0x52, 0, 0, 0, temp8),
+	PWRITE(temp4_min, 3, PRI_LOW, 0x34, 0, 0, 0, temp8),
+
+	PWRITE(temp1_max, 0, PRI_LOW, 0x4f, 0, 0, 0, temp8),
+	PWRITE(temp2_max, 1, PRI_LOW, 0x51, 0, 0, 0, temp8),
+	PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8),
+	PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8),
+
+	PREAD(temp1_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 4, bitmask),
+	PREAD(temp2_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 5, bitmask),
+	PREAD(temp3_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 6, bitmask),
+	PREAD(temp4_alarm, 3, PRI_LOW, 0x43, 0, 0x01, 0, bitmask),
+
+	PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask),
+	PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask),
+	PWRITE(temp3_source, 2, PRI_LOW, 0x03, 0, 0x07, 4, bitmask),
+	PWRITE(temp4_source, 3, PRI_LOW, 0x03, 0, 0x07, 0, bitmask),
+
+	PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask),
+	PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask),
+	PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x64, 0, 0x01, 3, bitmask),
+	PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask),
+
+	PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st),
+	PWRITE(temp2_smoothing_time, 1, PRI_LOW, 0x63, 0, 0x07, 4, temp_st),
+	PWRITE(temp3_smoothing_time, 2, PRI_LOW, 0x63, 0, 0x07, 0, temp_st),
+	PWRITE(temp4_smoothing_time, 3, PRI_LOW, 0x3c, 0, 0x07, 0, temp_st),
+
+	PWRITE(temp1_auto_point1_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4,
+	       bitmask),
+	PWRITE(temp2_auto_point1_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0,
+	       bitmask),
+	PWRITE(temp3_auto_point1_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4,
+	       bitmask),
+	PWRITE(temp4_auto_point1_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0,
+	       bitmask),
+
+	PREAD(temp1_auto_point2_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4,
+	      bitmask),
+	PREAD(temp2_auto_point2_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0,
+	      bitmask),
+	PREAD(temp3_auto_point2_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4,
+	      bitmask),
+	PREAD(temp4_auto_point2_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0,
+	      bitmask),
+
+	PWRITE(temp1_auto_point1_temp, 0, PRI_LOW, 0x67, 0, 0, 0, temp8),
+	PWRITE(temp2_auto_point1_temp, 1, PRI_LOW, 0x68, 0, 0, 0, temp8),
+	PWRITE(temp3_auto_point1_temp, 2, PRI_LOW, 0x69, 0, 0, 0, temp8),
+	PWRITE(temp4_auto_point1_temp, 3, PRI_LOW, 0x3b, 0, 0, 0, temp8),
+
+	PWRITEM(temp1_auto_point2_temp, 0, PRI_LOW, VAA(0x5f, 0x67), VAA(0),
+		VAA(0x0f), VAA(4), ap2_temp),
+	PWRITEM(temp2_auto_point2_temp, 1, PRI_LOW, VAA(0x60, 0x68), VAA(0),
+		VAA(0x0f), VAA(4), ap2_temp),
+	PWRITEM(temp3_auto_point2_temp, 2, PRI_LOW, VAA(0x61, 0x69), VAA(0),
+		VAA(0x0f), VAA(4), ap2_temp),
+	PWRITEM(temp4_auto_point2_temp, 3, PRI_LOW, VAA(0x3c, 0x3b), VAA(0),
+		VAA(0x0f), VAA(4), ap2_temp),
+
+	PWRITE(temp1_crit, 0, PRI_LOW, 0x6a, 0, 0, 0, temp8),
+	PWRITE(temp2_crit, 1, PRI_LOW, 0x6b, 0, 0, 0, temp8),
+	PWRITE(temp3_crit, 2, PRI_LOW, 0x6c, 0, 0, 0, temp8),
+	PWRITE(temp4_crit, 3, PRI_LOW, 0x3d, 0, 0, 0, temp8),
+
+	PWRITE(temp5_enable, 4, PRI_LOW, 0x0e, 0, 0x01, 0, bitmask),
+	PWRITE(temp6_enable, 5, PRI_LOW, 0x0e, 0, 0x01, 1, bitmask),
+	PWRITE(temp7_enable, 6, PRI_LOW, 0x0e, 0, 0x01, 2, bitmask),
+	PWRITE(temp8_enable, 7, PRI_LOW, 0x0e, 0, 0x01, 3, bitmask),
+
+	PWRITE(remote1_offset, 0, PRI_LOW, 0x1c, 0, 0, 0, temp62),
+	PWRITE(remote2_offset, 1, PRI_LOW, 0x1d, 0, 0, 0, temp62),
+
+	PWRITE(pwm1, 0, PRI_HIGH, 0x30, 0, 0, 0, u8),
+	PWRITE(pwm2, 1, PRI_HIGH, 0x31, 0, 0, 0, u8),
+	PWRITE(pwm3, 2, PRI_HIGH, 0x32, 0, 0, 0, u8),
+
+	PWRITE(pwm1_invert, 0, PRI_LOW, 0x5c, 0, 0x01, 4, bitmask),
+	PWRITE(pwm2_invert, 1, PRI_LOW, 0x5d, 0, 0x01, 4, bitmask),
+	PWRITE(pwm3_invert, 2, PRI_LOW, 0x5e, 0, 0x01, 4, bitmask),
+
+	PWRITEM(pwm1_enable, 0, PRI_LOW, VAA(0x5c, 0x5c, 0x62), VAA(0, 0, 0),
+		VAA(0x07, 0x01, 0x01), VAA(5, 3, 5), pwm_enable),
+	PWRITEM(pwm2_enable, 1, PRI_LOW, VAA(0x5d, 0x5d, 0x62), VAA(0, 0, 0),
+		VAA(0x07, 0x01, 0x01), VAA(5, 3, 6), pwm_enable),
+	PWRITEM(pwm3_enable, 2, PRI_LOW, VAA(0x5e, 0x5e, 0x62), VAA(0, 0, 0),
+		VAA(0x07, 0x01, 0x01), VAA(5, 3, 7), pwm_enable),
+
+	PWRITEM(pwm1_auto_channels, 0, PRI_LOW, VAA(0x5c, 0x5c), VAA(0, 0),
+		VAA(0x07, 0x01), VAA(5, 3), pwm_ac),
+	PWRITEM(pwm2_auto_channels, 1, PRI_LOW, VAA(0x5d, 0x5d), VAA(0, 0),
+		VAA(0x07, 0x01), VAA(5, 3), pwm_ac),
+	PWRITEM(pwm3_auto_channels, 2, PRI_LOW, VAA(0x5e, 0x5e), VAA(0, 0),
+		VAA(0x07, 0x01), VAA(5, 3), pwm_ac),
+
+	PWRITE(pwm1_auto_point1_pwm, 0, PRI_LOW, 0x64, 0, 0, 0, u8),
+	PWRITE(pwm2_auto_point1_pwm, 1, PRI_LOW, 0x65, 0, 0, 0, u8),
+	PWRITE(pwm3_auto_point1_pwm, 2, PRI_LOW, 0x66, 0, 0, 0, u8),
+
+	PWRITE(pwm1_auto_point2_pwm, 0, PRI_LOW, 0x38, 0, 0, 0, u8),
+	PWRITE(pwm2_auto_point2_pwm, 1, PRI_LOW, 0x39, 0, 0, 0, u8),
+	PWRITE(pwm3_auto_point2_pwm, 2, PRI_LOW, 0x3a, 0, 0, 0, u8),
+
+	PWRITE(pwm1_freq, 0, PRI_LOW, 0x5f, 0, 0x0f, 0, pwm_freq),
+	PWRITE(pwm2_freq, 1, PRI_LOW, 0x60, 0, 0x0f, 0, pwm_freq),
+	PWRITE(pwm3_freq, 2, PRI_LOW, 0x61, 0, 0x0f, 0, pwm_freq),
+
+	PREAD(pwm1_auto_zone_assigned, 0, PRI_LOW, 0, 0, 0x03, 2, bitmask),
+	PREAD(pwm2_auto_zone_assigned, 1, PRI_LOW, 0, 0, 0x03, 4, bitmask),
+	PREAD(pwm3_auto_zone_assigned, 2, PRI_LOW, 0, 0, 0x03, 6, bitmask),
+
+	PWRITE(pwm1_auto_spinup_time, 0, PRI_LOW, 0x5c, 0, 0x07, 0, pwm_ast),
+	PWRITE(pwm2_auto_spinup_time, 1, PRI_LOW, 0x5d, 0, 0x07, 0, pwm_ast),
+	PWRITE(pwm3_auto_spinup_time, 2, PRI_LOW, 0x5e, 0, 0x07, 0, pwm_ast),
+
+	PWRITE(peci_enable, 0, PRI_LOW, 0x40, 0, 0x01, 4, bitmask),
+	PWRITE(peci_avg, 0, PRI_LOW, 0x36, 0, 0x07, 0, bitmask),
+	PWRITE(peci_domain, 0, PRI_LOW, 0x36, 0, 0x01, 3, bitmask),
+	PWRITE(peci_legacy, 0, PRI_LOW, 0x36, 0, 0x01, 4, bitmask),
+	PWRITE(peci_diode, 0, PRI_LOW, 0x0e, 0, 0x07, 4, bitmask),
+	PWRITE(peci_4domain, 0, PRI_LOW, 0x0e, 0, 0x01, 4, bitmask),
+
+};
+
+static struct asc7621_data *asc7621_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct asc7621_data *data = i2c_get_clientdata(client);
+	int i;
+
+/*
+ * The asc7621 chips guarantee consistent reads of multi-byte values
+ * regardless of the order of the reads.  No special logic is needed
+ * so we can just read the registers in whatever  order they appear
+ * in the asc7621_params array.
+ */
+
+	mutex_lock(&data->update_lock);
+
+	/* Read all the high priority registers */
+
+	if (!data->valid ||
+	    time_after(jiffies, data->last_high_reading + INTERVAL_HIGH)) {
+
+		for (i = 0; i < ARRAY_SIZE(asc7621_register_priorities); i++) {
+			if (asc7621_register_priorities[i] == PRI_HIGH) {
+				data->reg[i] =
+				    i2c_smbus_read_byte_data(client, i) & 0xff;
+			}
+		}
+		data->last_high_reading = jiffies;
+	};			/* last_reading */
+
+	/* Read all the low priority registers. */
+
+	if (!data->valid ||
+	    time_after(jiffies, data->last_low_reading + INTERVAL_LOW)) {
+
+		for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) {
+			if (asc7621_register_priorities[i] == PRI_LOW) {
+				data->reg[i] =
+				    i2c_smbus_read_byte_data(client, i) & 0xff;
+			}
+		}
+		data->last_low_reading = jiffies;
+	};			/* last_reading */
+
+	data->valid = 1;
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+/*
+ * Standard detection and initialization below
+ *
+ * Helper function that checks if an address is valid
+ * for a particular chip.
+ */
+
+static inline int valid_address_for_chip(int chip_type, int address)
+{
+	int i;
+
+	for (i = 0; asc7621_chips[chip_type].addresses[i] != I2C_CLIENT_END;
+	     i++) {
+		if (asc7621_chips[chip_type].addresses[i] == address)
+			return 1;
+	}
+	return 0;
+}
+
+static void asc7621_init_client(struct i2c_client *client)
+{
+	int value;
+
+	/* Warn if part was not "READY" */
+
+	value = read_byte(client, 0x40);
+
+	if (value & 0x02) {
+		dev_err(&client->dev,
+			"Client (%d,0x%02x) config is locked.\n",
+			i2c_adapter_id(client->adapter), client->addr);
+	};
+	if (!(value & 0x04)) {
+		dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n",
+			i2c_adapter_id(client->adapter), client->addr);
+	};
+
+/*
+ * Start monitoring
+ *
+ * Try to clear LOCK, Set START, save everything else
+ */
+	value = (value & ~0x02) | 0x01;
+	write_byte(client, 0x40, value & 0xff);
+
+}
+
+static int
+asc7621_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct asc7621_data *data;
+	int i, err;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	data = kzalloc(sizeof(struct asc7621_data), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	data->valid = 0;
+	mutex_init(&data->update_lock);
+
+	/* Initialize the asc7621 chip */
+	asc7621_init_client(client);
+
+	/* Create the sysfs entries */
+	for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) {
+		err =
+		    device_create_file(&client->dev,
+				       &(asc7621_params[i].sda.dev_attr));
+		if (err)
+			goto exit_remove;
+	}
+
+	data->class_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove;
+	}
+
+	return 0;
+
+exit_remove:
+	for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) {
+		device_remove_file(&client->dev,
+				   &(asc7621_params[i].sda.dev_attr));
+	}
+
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+	return err;
+}
+
+static int asc7621_detect(struct i2c_client *client,
+			  struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	int company, verstep, chip_index;
+	struct device *dev;
+
+	dev = &client->dev;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	for (chip_index = FIRST_CHIP; chip_index <= LAST_CHIP; chip_index++) {
+
+		if (!valid_address_for_chip(chip_index, client->addr))
+			continue;
+
+		company = read_byte(client,
+			asc7621_chips[chip_index].company_reg);
+		verstep = read_byte(client,
+			asc7621_chips[chip_index].verstep_reg);
+
+		if (company == asc7621_chips[chip_index].company_id &&
+		    verstep == asc7621_chips[chip_index].verstep_id) {
+			strlcpy(client->name, asc7621_chips[chip_index].name,
+				I2C_NAME_SIZE);
+			strlcpy(info->type, asc7621_chips[chip_index].name,
+				I2C_NAME_SIZE);
+
+			dev_info(&adapter->dev, "Matched %s\n",
+				 asc7621_chips[chip_index].name);
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
+static int asc7621_remove(struct i2c_client *client)
+{
+	struct asc7621_data *data = i2c_get_clientdata(client);
+	int i;
+
+	hwmon_device_unregister(data->class_dev);
+
+	for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) {
+		device_remove_file(&client->dev,
+				   &(asc7621_params[i].sda.dev_attr));
+	}
+
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+	return 0;
+}
+
+static const struct i2c_device_id asc7621_id[] = {
+	{"asc7621", asc7621},
+	{"asc7621a", asc7621a},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, asc7621_id);
+
+static struct i2c_driver asc7621_driver = {
+	.class = I2C_CLASS_HWMON,
+	.driver = {
+		.name = "asc7621",
+	},
+	.probe = asc7621_probe,
+	.remove = asc7621_remove,
+	.id_table = asc7621_id,
+	.detect = asc7621_detect,
+	.address_list = normal_i2c,
+};
+
+static int __init sm_asc7621_init(void)
+{
+	int i, j;
+/*
+ * Collect all the registers needed into a single array.
+ * This way, if a register isn't actually used for anything,
+ * we don't retrieve it.
+ */
+
+	for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) {
+		for (j = 0; j < ARRAY_SIZE(asc7621_params[i].msb); j++)
+			asc7621_register_priorities[asc7621_params[i].msb[j]] =
+			    asc7621_params[i].priority;
+		for (j = 0; j < ARRAY_SIZE(asc7621_params[i].lsb); j++)
+			asc7621_register_priorities[asc7621_params[i].lsb[j]] =
+			    asc7621_params[i].priority;
+	}
+	return i2c_add_driver(&asc7621_driver);
+}
+
+static void __exit sm_asc7621_exit(void)
+{
+	i2c_del_driver(&asc7621_driver);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("George Joseph");
+MODULE_DESCRIPTION("Andigilog aSC7621 and aSC7621a driver");
+
+module_init(sm_asc7621_init);
+module_exit(sm_asc7621_exit);
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index fa07282..0627f7a 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -267,7 +267,7 @@
 	struct list_head list; /* member of the watchdog_data_list */
 	struct kref kref;
 	struct miscdevice watchdog_miscdev;
-	int kind;
+	enum chips kind;
 	unsigned long watchdog_is_open;
 	char watchdog_expect_close;
 	char watchdog_name[10]; /* must be unique to avoid sysfs conflict */
@@ -325,8 +325,7 @@
 	int index = to_sensor_dev_attr(devattr)->index;
 	struct fschmd_data *data = fschmd_update_device(dev);
 
-	/* fscher / fschrc - 1 as data->kind is an array index, not a chips */
-	if (data->kind == (fscher - 1) || data->kind >= (fschrc - 1))
+	if (data->kind == fscher || data->kind >= fschrc)
 		return sprintf(buf, "%d\n", (data->volt[index] * dmi_vref *
 			dmi_mult[index]) / 255 + dmi_offset[index]);
 	else
@@ -492,7 +491,7 @@
 	int val = data->fan_min[index];
 
 	/* 0 = allow turning off (except on the syl), 1-255 = 50-100% */
-	if (val || data->kind == fscsyl - 1)
+	if (val || data->kind == fscsyl)
 		val = val / 2 + 128;
 
 	return sprintf(buf, "%d\n", val);
@@ -506,7 +505,7 @@
 	unsigned long v = simple_strtoul(buf, NULL, 10);
 
 	/* reg: 0 = allow turning off (except on the syl), 1-255 = 50-100% */
-	if (v || data->kind == fscsyl - 1) {
+	if (v || data->kind == fscsyl) {
 		v = SENSORS_LIMIT(v, 128, 255);
 		v = (v - 128) * 2 + 1;
 	}
@@ -1037,7 +1036,7 @@
 	else
 		return -ENODEV;
 
-	strlcpy(info->type, fschmd_id[kind - 1].name, I2C_NAME_SIZE);
+	strlcpy(info->type, fschmd_id[kind].name, I2C_NAME_SIZE);
 
 	return 0;
 }
@@ -1065,6 +1064,7 @@
 	   (where the client is found through a data ptr instead of the
 	   otherway around) */
 	data->client = client;
+	data->kind = kind;
 
 	if (kind == fscpos) {
 		/* The Poseidon has hardwired temp limits, fill these
@@ -1085,9 +1085,6 @@
 		}
 	}
 
-	/* i2c kind goes from 1-6, we want from 0-5 to address arrays */
-	data->kind = kind - 1;
-
 	/* Read in some never changing registers */
 	data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION);
 	data->global_control = i2c_smbus_read_byte_data(client,
diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c
index 19c01a49..09ea12e 100644
--- a/drivers/hwmon/g760a.c
+++ b/drivers/hwmon/g760a.c
@@ -68,7 +68,7 @@
 #define PWM_FROM_CNT(cnt)	(0xff-(cnt))
 #define PWM_TO_CNT(pwm)		(0xff-(pwm))
 
-unsigned int rpm_from_cnt(u8 val, u32 clk, u16 div)
+static inline unsigned int rpm_from_cnt(u8 val, u32 clk, u16 div)
 {
 	return ((val == 0x00) ? 0 : ((clk*30)/(val*div)));
 }
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 0ffe84d..1002bef 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -1,40 +1,40 @@
 /*
-    it87.c - Part of lm_sensors, Linux kernel modules for hardware
-             monitoring.
-
-    The IT8705F is an LPC-based Super I/O part that contains UARTs, a
-    parallel port, an IR port, a MIDI port, a floppy controller, etc., in
-    addition to an Environment Controller (Enhanced Hardware Monitor and
-    Fan Controller)
-
-    This driver supports only the Environment Controller in the IT8705F and
-    similar parts.  The other devices are supported by different drivers.
-
-    Supports: IT8705F  Super I/O chip w/LPC interface
-              IT8712F  Super I/O chip w/LPC interface
-              IT8716F  Super I/O chip w/LPC interface
-              IT8718F  Super I/O chip w/LPC interface
-              IT8720F  Super I/O chip w/LPC interface
-              IT8726F  Super I/O chip w/LPC interface
-              Sis950   A clone of the IT8705F
-
-    Copyright (C) 2001 Chris Gauthron
-    Copyright (C) 2005-2007 Jean Delvare <khali@linux-fr.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.
-*/
+ *  it87.c - Part of lm_sensors, Linux kernel modules for hardware
+ *           monitoring.
+ *
+ *  The IT8705F is an LPC-based Super I/O part that contains UARTs, a
+ *  parallel port, an IR port, a MIDI port, a floppy controller, etc., in
+ *  addition to an Environment Controller (Enhanced Hardware Monitor and
+ *  Fan Controller)
+ *
+ *  This driver supports only the Environment Controller in the IT8705F and
+ *  similar parts.  The other devices are supported by different drivers.
+ *
+ *  Supports: IT8705F  Super I/O chip w/LPC interface
+ *            IT8712F  Super I/O chip w/LPC interface
+ *            IT8716F  Super I/O chip w/LPC interface
+ *            IT8718F  Super I/O chip w/LPC interface
+ *            IT8720F  Super I/O chip w/LPC interface
+ *            IT8726F  Super I/O chip w/LPC interface
+ *            Sis950   A clone of the IT8705F
+ *
+ *  Copyright (C) 2001 Chris Gauthron
+ *  Copyright (C) 2005-2010 Jean Delvare <khali@linux-fr.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/init.h>
@@ -128,6 +128,7 @@
 #define IT87_SIO_GPIO5_REG	0x29
 #define IT87_SIO_PINX2_REG	0x2c	/* Pin selection */
 #define IT87_SIO_VID_REG	0xfc	/* VID value */
+#define IT87_SIO_BEEP_PIN_REG	0xf6	/* Beep pin mapping */
 
 /* Update battery voltage after every reading if true */
 static int update_vbat;
@@ -187,9 +188,13 @@
 
 #define IT87_REG_VIN_ENABLE    0x50
 #define IT87_REG_TEMP_ENABLE   0x51
+#define IT87_REG_BEEP_ENABLE   0x5c
 
 #define IT87_REG_CHIPID        0x58
 
+#define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i))
+#define IT87_REG_AUTO_PWM(nr, i)  (0x65 + (nr) * 8 + (i))
+
 #define IN_TO_REG(val)  (SENSORS_LIMIT((((val) + 8)/16),0,255))
 #define IN_FROM_REG(val) ((val) * 16)
 
@@ -246,6 +251,7 @@
 	/* Values read from Super-I/O config space */
 	u8 revision;
 	u8 vid_value;
+	u8 beep_pin;
 	/* Features skipped based on config or DMI */
 	u8 skip_vid;
 	u8 skip_fan;
@@ -279,9 +285,21 @@
 	u8 vid;			/* Register encoding, combined */
 	u8 vrm;
 	u32 alarms;		/* Register encoding, combined */
+	u8 beeps;		/* Register encoding */
 	u8 fan_main_ctrl;	/* Register value */
 	u8 fan_ctl;		/* Register value */
-	u8 manual_pwm_ctl[3];   /* manual PWM value set by user */
+
+	/* The following 3 arrays correspond to the same registers. The
+	 * meaning of bits 6-0 depends on the value of bit 7, and we want
+	 * to preserve settings on mode changes, so we have to track all
+	 * values separately. */
+	u8 pwm_ctrl[3];		/* Register value */
+	u8 pwm_duty[3];		/* Manual PWM value set by user (bit 6-0) */
+	u8 pwm_temp_map[3];	/* PWM to temp. chan. mapping (bits 1-0) */
+
+	/* Automatic fan speed control registers */
+	u8 auto_pwm[3][4];	/* [nr][3] is hard-coded */
+	s8 auto_temp[3][5];	/* [nr][0] is point1_temp_hyst */
 };
 
 static inline int has_16bit_fans(const struct it87_data *data)
@@ -296,6 +314,15 @@
 	    || data->type == it8720;
 }
 
+static inline int has_old_autopwm(const struct it87_data *data)
+{
+	/* The old automatic fan speed control interface is implemented
+	   by IT8705F chips up to revision F and IT8712F chips up to
+	   revision G. */
+	return (data->type == it87 && data->revision < 0x03)
+	    || (data->type == it8712 && data->revision < 0x08);
+}
+
 static int it87_probe(struct platform_device *pdev);
 static int __devexit it87_remove(struct platform_device *pdev);
 
@@ -352,7 +379,10 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val) < 0)
+		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val);
@@ -368,7 +398,10 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val) < 0)
+		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val);
@@ -441,7 +474,10 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+
+	if (strict_strtol(buf, 10, &val) < 0)
+		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
 	data->temp_high[nr] = TEMP_TO_REG(val);
@@ -456,7 +492,10 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+
+	if (strict_strtol(buf, 10, &val) < 0)
+		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
 	data->temp_low[nr] = TEMP_TO_REG(val);
@@ -483,8 +522,9 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = it87_update_device(dev);
-	u8 reg = data->sensor; /* In case the value is updated while we use it */
-	
+	u8 reg = data->sensor;		/* In case the value is updated while
+					   we use it */
+
 	if (reg & (1 << nr))
 		return sprintf(buf, "3\n");  /* thermal diode */
 	if (reg & (8 << nr))
@@ -498,7 +538,10 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+
+	if (strict_strtol(buf, 10, &val) < 0)
+		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
 
@@ -511,9 +554,9 @@
 	}
 	/* 3 = thermal diode; 4 = thermistor; 0 = disabled */
 	if (val == 3)
-	    data->sensor |= 1 << nr;
+		data->sensor |= 1 << nr;
 	else if (val == 4)
-	    data->sensor |= 8 << nr;
+		data->sensor |= 8 << nr;
 	else if (val != 0) {
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
@@ -531,6 +574,19 @@
 show_sensor_offset(3);
 
 /* 3 Fans */
+
+static int pwm_mode(const struct it87_data *data, int nr)
+{
+	int ctrl = data->fan_main_ctrl & (1 << nr);
+
+	if (ctrl == 0)					/* Full speed */
+		return 0;
+	if (data->pwm_ctrl[nr] & 0x80)			/* Automatic mode */
+		return 2;
+	else						/* Manual mode */
+		return 1;
+}
+
 static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
@@ -538,7 +594,7 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], 
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
 				DIV_FROM_REG(data->fan_div[nr])));
 }
 static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
@@ -548,8 +604,8 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf,"%d\n",
-		FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])));
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+				DIV_FROM_REG(data->fan_div[nr])));
 }
 static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -560,14 +616,14 @@
 	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
 }
-static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr,
-		char *buf)
+static ssize_t show_pwm_enable(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0);
+	return sprintf(buf, "%d\n", pwm_mode(data, nr));
 }
 static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -576,7 +632,7 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]);
+	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm_duty[nr]));
 }
 static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -593,15 +649,24 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
 	u8 reg;
 
+	if (strict_strtol(buf, 10, &val) < 0)
+		return -EINVAL;
+
 	mutex_lock(&data->update_lock);
 	reg = it87_read_value(data, IT87_REG_FAN_DIV);
 	switch (nr) {
-	case 0: data->fan_div[nr] = reg & 0x07; break;
-	case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break;
-	case 2: data->fan_div[nr] = (reg & 0x40) ? 3 : 1; break;
+	case 0:
+		data->fan_div[nr] = reg & 0x07;
+		break;
+	case 1:
+		data->fan_div[nr] = (reg >> 3) & 0x07;
+		break;
+	case 2:
+		data->fan_div[nr] = (reg & 0x40) ? 3 : 1;
+		break;
 	}
 
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
@@ -616,10 +681,13 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
 	int min;
 	u8 old;
 
+	if (strict_strtoul(buf, 10, &val) < 0)
+		return -EINVAL;
+
 	mutex_lock(&data->update_lock);
 	old = it87_read_value(data, IT87_REG_FAN_DIV);
 
@@ -651,6 +719,32 @@
 	mutex_unlock(&data->update_lock);
 	return count;
 }
+
+/* Returns 0 if OK, -EINVAL otherwise */
+static int check_trip_points(struct device *dev, int nr)
+{
+	const struct it87_data *data = dev_get_drvdata(dev);
+	int i, err = 0;
+
+	if (has_old_autopwm(data)) {
+		for (i = 0; i < 3; i++) {
+			if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
+				err = -EINVAL;
+		}
+		for (i = 0; i < 2; i++) {
+			if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
+				err = -EINVAL;
+		}
+	}
+
+	if (err) {
+		dev_err(dev, "Inconsistent trip points, not switching to "
+			"automatic mode\n");
+		dev_err(dev, "Adjust the trip points and try again\n");
+	}
+	return err;
+}
+
 static ssize_t set_pwm_enable(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
@@ -658,7 +752,16 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+
+	if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 2)
+		return -EINVAL;
+
+	/* Check trip points before switching to automatic mode */
+	if (val == 2) {
+		if (check_trip_points(dev, nr) < 0)
+			return -EINVAL;
+	}
 
 	mutex_lock(&data->update_lock);
 
@@ -669,16 +772,18 @@
 		it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr));
 		/* set on/off mode */
 		data->fan_main_ctrl &= ~(1 << nr);
-		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
-	} else if (val == 1) {
+		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
+				 data->fan_main_ctrl);
+	} else {
+		if (val == 1)				/* Manual mode */
+			data->pwm_ctrl[nr] = data->pwm_duty[nr];
+		else					/* Automatic mode */
+			data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
+		it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
 		/* set SmartGuardian mode */
 		data->fan_main_ctrl |= (1 << nr);
-		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
-		/* set saved pwm value, clear FAN_CTLX PWM mode bit */
-		it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
-	} else {
-		mutex_unlock(&data->update_lock);
-		return -EINVAL;
+		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
+				 data->fan_main_ctrl);
 	}
 
 	mutex_unlock(&data->update_lock);
@@ -691,15 +796,19 @@
 	int nr = sensor_attr->index;
 
 	struct it87_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
 
-	if (val < 0 || val > 255)
+	if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
-	data->manual_pwm_ctl[nr] = val;
-	if (data->fan_main_ctrl & (1 << nr))
-		it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
+	data->pwm_duty[nr] = PWM_TO_REG(val);
+	/* If we are in manual mode, write the duty cycle immediately;
+	 * otherwise, just store it for later use. */
+	if (!(data->pwm_ctrl[nr] & 0x80)) {
+		data->pwm_ctrl[nr] = data->pwm_duty[nr];
+		it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
+	}
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -707,9 +816,12 @@
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct it87_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
 	int i;
 
+	if (strict_strtoul(buf, 10, &val) < 0)
+		return -EINVAL;
+
 	/* Search for the nearest available frequency */
 	for (i = 0; i < 7; i++) {
 		if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2)
@@ -724,6 +836,132 @@
 
 	return count;
 }
+static ssize_t show_pwm_temp_map(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+
+	struct it87_data *data = it87_update_device(dev);
+	int map;
+
+	if (data->pwm_temp_map[nr] < 3)
+		map = 1 << data->pwm_temp_map[nr];
+	else
+		map = 0;			/* Should never happen */
+	return sprintf(buf, "%d\n", map);
+}
+static ssize_t set_pwm_temp_map(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+
+	struct it87_data *data = dev_get_drvdata(dev);
+	long val;
+	u8 reg;
+
+	/* This check can go away if we ever support automatic fan speed
+	   control on newer chips. */
+	if (!has_old_autopwm(data)) {
+		dev_notice(dev, "Mapping change disabled for safety reasons\n");
+		return -EINVAL;
+	}
+
+	if (strict_strtol(buf, 10, &val) < 0)
+		return -EINVAL;
+
+	switch (val) {
+	case (1 << 0):
+		reg = 0x00;
+		break;
+	case (1 << 1):
+		reg = 0x01;
+		break;
+	case (1 << 2):
+		reg = 0x02;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->pwm_temp_map[nr] = reg;
+	/* If we are in automatic mode, write the temp mapping immediately;
+	 * otherwise, just store it for later use. */
+	if (data->pwm_ctrl[nr] & 0x80) {
+		data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
+		it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_auto_pwm(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct it87_data *data = it87_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr =
+			to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int point = sensor_attr->index;
+
+	return sprintf(buf, "%d\n", PWM_FROM_REG(data->auto_pwm[nr][point]));
+}
+
+static ssize_t set_auto_pwm(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct it87_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sensor_attr =
+			to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int point = sensor_attr->index;
+	long val;
+
+	if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->auto_pwm[nr][point] = PWM_TO_REG(val);
+	it87_write_value(data, IT87_REG_AUTO_PWM(nr, point),
+			 data->auto_pwm[nr][point]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_auto_temp(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct it87_data *data = it87_update_device(dev);
+	struct sensor_device_attribute_2 *sensor_attr =
+			to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int point = sensor_attr->index;
+
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point]));
+}
+
+static ssize_t set_auto_temp(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct it87_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sensor_attr =
+			to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int point = sensor_attr->index;
+	long val;
+
+	if (strict_strtol(buf, 10, &val) < 0 || val < -128000 || val > 127000)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->auto_temp[nr][point] = TEMP_TO_REG(val);
+	it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point),
+			 data->auto_temp[nr][point]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
 
 #define show_fan_offset(offset)					\
 static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,		\
@@ -744,7 +982,36 @@
 		show_pwm, set_pwm, offset - 1);				\
 static DEVICE_ATTR(pwm##offset##_freq,					\
 		(offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO),		\
-		show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL));
+		show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL));	\
+static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp,		\
+		S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map,	\
+		offset - 1);						\
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_pwm,		\
+		S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm,		\
+		offset - 1, 0);						\
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_pwm,		\
+		S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm,		\
+		offset - 1, 1);						\
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_pwm,		\
+		S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm,		\
+		offset - 1, 2);						\
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_pwm,		\
+		S_IRUGO, show_auto_pwm, NULL, offset - 1, 3);		\
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp,		\
+		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
+		offset - 1, 1);						\
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp_hyst,	\
+		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
+		offset - 1, 0);						\
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_temp,		\
+		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
+		offset - 1, 2);						\
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_temp,		\
+		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
+		offset - 1, 3);						\
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_temp,		\
+		S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp,	\
+		offset - 1, 4);
 
 show_pwm_offset(1);
 show_pwm_offset(2);
@@ -775,7 +1042,10 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct it87_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+
+	if (strict_strtol(buf, 10, &val) < 0)
+		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN16_TO_REG(val);
@@ -805,7 +1075,8 @@
 show_fan16_offset(5);
 
 /* Alarms */
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%u\n", data->alarms);
@@ -836,27 +1107,78 @@
 static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17);
 static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18);
 
-static ssize_t
-show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct it87_data *data = it87_update_device(dev);
+	return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1);
+}
+static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int bitnr = to_sensor_dev_attr(attr)->index;
+	struct it87_data *data = dev_get_drvdata(dev);
+	long val;
+
+	if (strict_strtol(buf, 10, &val) < 0
+	 || (val != 0 && val != 1))
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
+	if (val)
+		data->beeps |= (1 << bitnr);
+	else
+		data->beeps &= ~(1 << bitnr);
+	it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
+			  show_beep, set_beep, 1);
+static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO, show_beep, NULL, 1);
+/* fanX_beep writability is set later */
+static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(fan4_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(fan5_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
+			  show_beep, set_beep, 2);
+static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2);
+
+static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct it87_data *data = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", data->vrm);
 }
-static ssize_t
-store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
 {
 	struct it87_data *data = dev_get_drvdata(dev);
-	u32 val;
+	unsigned long val;
 
-	val = simple_strtoul(buf, NULL, 10);
+	if (strict_strtoul(buf, 10, &val) < 0)
+		return -EINVAL;
+
 	data->vrm = val;
 
 	return count;
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 
-static ssize_t
-show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr,
+		char *buf)
 {
 	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
@@ -931,51 +1253,176 @@
 	.attrs = it87_attributes,
 };
 
-static struct attribute *it87_attributes_opt[] = {
+static struct attribute *it87_attributes_beep[] = {
+	&sensor_dev_attr_in0_beep.dev_attr.attr,
+	&sensor_dev_attr_in1_beep.dev_attr.attr,
+	&sensor_dev_attr_in2_beep.dev_attr.attr,
+	&sensor_dev_attr_in3_beep.dev_attr.attr,
+	&sensor_dev_attr_in4_beep.dev_attr.attr,
+	&sensor_dev_attr_in5_beep.dev_attr.attr,
+	&sensor_dev_attr_in6_beep.dev_attr.attr,
+	&sensor_dev_attr_in7_beep.dev_attr.attr,
+
+	&sensor_dev_attr_temp1_beep.dev_attr.attr,
+	&sensor_dev_attr_temp2_beep.dev_attr.attr,
+	&sensor_dev_attr_temp3_beep.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group it87_group_beep = {
+	.attrs = it87_attributes_beep,
+};
+
+static struct attribute *it87_attributes_fan16[5][3+1] = { {
 	&sensor_dev_attr_fan1_input16.dev_attr.attr,
 	&sensor_dev_attr_fan1_min16.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	NULL
+}, {
 	&sensor_dev_attr_fan2_input16.dev_attr.attr,
 	&sensor_dev_attr_fan2_min16.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	NULL
+}, {
 	&sensor_dev_attr_fan3_input16.dev_attr.attr,
 	&sensor_dev_attr_fan3_min16.dev_attr.attr,
+	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
+	NULL
+}, {
 	&sensor_dev_attr_fan4_input16.dev_attr.attr,
 	&sensor_dev_attr_fan4_min16.dev_attr.attr,
+	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
+	NULL
+}, {
 	&sensor_dev_attr_fan5_input16.dev_attr.attr,
 	&sensor_dev_attr_fan5_min16.dev_attr.attr,
+	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
+	NULL
+} };
 
+static const struct attribute_group it87_group_fan16[5] = {
+	{ .attrs = it87_attributes_fan16[0] },
+	{ .attrs = it87_attributes_fan16[1] },
+	{ .attrs = it87_attributes_fan16[2] },
+	{ .attrs = it87_attributes_fan16[3] },
+	{ .attrs = it87_attributes_fan16[4] },
+};
+
+static struct attribute *it87_attributes_fan[3][4+1] = { {
 	&sensor_dev_attr_fan1_input.dev_attr.attr,
 	&sensor_dev_attr_fan1_min.dev_attr.attr,
 	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	NULL
+}, {
 	&sensor_dev_attr_fan2_input.dev_attr.attr,
 	&sensor_dev_attr_fan2_min.dev_attr.attr,
 	&sensor_dev_attr_fan2_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	NULL
+}, {
 	&sensor_dev_attr_fan3_input.dev_attr.attr,
 	&sensor_dev_attr_fan3_min.dev_attr.attr,
 	&sensor_dev_attr_fan3_div.dev_attr.attr,
-
-	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
-	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
 	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
-	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
-	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
+	NULL
+} };
 
+static const struct attribute_group it87_group_fan[3] = {
+	{ .attrs = it87_attributes_fan[0] },
+	{ .attrs = it87_attributes_fan[1] },
+	{ .attrs = it87_attributes_fan[2] },
+};
+
+static const struct attribute_group *
+it87_get_fan_group(const struct it87_data *data)
+{
+	return has_16bit_fans(data) ? it87_group_fan16 : it87_group_fan;
+}
+
+static struct attribute *it87_attributes_pwm[3][4+1] = { {
 	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
-	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
-	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
 	&sensor_dev_attr_pwm1.dev_attr.attr,
-	&sensor_dev_attr_pwm2.dev_attr.attr,
-	&sensor_dev_attr_pwm3.dev_attr.attr,
 	&dev_attr_pwm1_freq.attr,
+	&sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
+	NULL
+}, {
+	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
 	&dev_attr_pwm2_freq.attr,
+	&sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
+	NULL
+}, {
+	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm3.dev_attr.attr,
 	&dev_attr_pwm3_freq.attr,
+	&sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
+	NULL
+} };
 
+static const struct attribute_group it87_group_pwm[3] = {
+	{ .attrs = it87_attributes_pwm[0] },
+	{ .attrs = it87_attributes_pwm[1] },
+	{ .attrs = it87_attributes_pwm[2] },
+};
+
+static struct attribute *it87_attributes_autopwm[3][9+1] = { {
+	&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
+	NULL
+}, {
+	&sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,
+	NULL
+}, {
+	&sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr,
+	NULL
+} };
+
+static const struct attribute_group it87_group_autopwm[3] = {
+	{ .attrs = it87_attributes_autopwm[0] },
+	{ .attrs = it87_attributes_autopwm[1] },
+	{ .attrs = it87_attributes_autopwm[2] },
+};
+
+static struct attribute *it87_attributes_fan_beep[] = {
+	&sensor_dev_attr_fan1_beep.dev_attr.attr,
+	&sensor_dev_attr_fan2_beep.dev_attr.attr,
+	&sensor_dev_attr_fan3_beep.dev_attr.attr,
+	&sensor_dev_attr_fan4_beep.dev_attr.attr,
+	&sensor_dev_attr_fan5_beep.dev_attr.attr,
+};
+
+static struct attribute *it87_attributes_vid[] = {
 	&dev_attr_vrm.attr,
 	&dev_attr_cpu0_vid.attr,
 	NULL
 };
 
-static const struct attribute_group it87_group_opt = {
-	.attrs = it87_attributes_opt,
+static const struct attribute_group it87_group_vid = {
+	.attrs = it87_attributes_vid,
 };
 
 /* SuperIO detection - will change isa_address if a chip is found */
@@ -1035,6 +1482,10 @@
 	if (sio_data->type == it87) {
 		/* The IT8705F doesn't have VID pins at all */
 		sio_data->skip_vid = 1;
+
+		/* The IT8705F has a different LD number for GPIO */
+		superio_select(5);
+		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
 	} else {
 		int reg;
 
@@ -1068,7 +1519,11 @@
 			pr_info("it87: in3 is VCC (+5V)\n");
 		if (reg & (1 << 1))
 			pr_info("it87: in7 is VCCH (+5V Stand-By)\n");
+
+		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
 	}
+	if (sio_data->beep_pin)
+		pr_info("it87: Beeping is supported\n");
 
 	/* Disable specific features based on DMI strings */
 	board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
@@ -1093,14 +1548,46 @@
 	return err;
 }
 
+static void it87_remove_files(struct device *dev)
+{
+	struct it87_data *data = platform_get_drvdata(pdev);
+	struct it87_sio_data *sio_data = dev->platform_data;
+	const struct attribute_group *fan_group = it87_get_fan_group(data);
+	int i;
+
+	sysfs_remove_group(&dev->kobj, &it87_group);
+	if (sio_data->beep_pin)
+		sysfs_remove_group(&dev->kobj, &it87_group_beep);
+	for (i = 0; i < 5; i++) {
+		if (!(data->has_fan & (1 << i)))
+			continue;
+		sysfs_remove_group(&dev->kobj, &fan_group[i]);
+		if (sio_data->beep_pin)
+			sysfs_remove_file(&dev->kobj,
+					  it87_attributes_fan_beep[i]);
+	}
+	for (i = 0; i < 3; i++) {
+		if (sio_data->skip_pwm & (1 << 0))
+			continue;
+		sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]);
+		if (has_old_autopwm(data))
+			sysfs_remove_group(&dev->kobj,
+					   &it87_group_autopwm[i]);
+	}
+	if (!sio_data->skip_vid)
+		sysfs_remove_group(&dev->kobj, &it87_group_vid);
+}
+
 static int __devinit it87_probe(struct platform_device *pdev)
 {
 	struct it87_data *data;
 	struct resource *res;
 	struct device *dev = &pdev->dev;
 	struct it87_sio_data *sio_data = dev->platform_data;
-	int err = 0;
+	const struct attribute_group *fan_group;
+	int err = 0, i;
 	int enable_pwm_interface;
+	int fan_beep_need_rw;
 	static const char *names[] = {
 		"it87",
 		"it8712",
@@ -1118,7 +1605,8 @@
 		goto ERROR0;
 	}
 
-	if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct it87_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto ERROR1;
 	}
@@ -1146,120 +1634,60 @@
 	it87_init_device(pdev);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&dev->kobj, &it87_group)))
+	err = sysfs_create_group(&dev->kobj, &it87_group);
+	if (err)
 		goto ERROR2;
 
+	if (sio_data->beep_pin) {
+		err = sysfs_create_group(&dev->kobj, &it87_group_beep);
+		if (err)
+			goto ERROR4;
+	}
+
 	/* Do not create fan files for disabled fans */
-	if (has_16bit_fans(data)) {
-		/* 16-bit tachometers */
-		if (data->has_fan & (1 << 0)) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_fan1_input16.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan1_min16.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan1_alarm.dev_attr)))
+	fan_group = it87_get_fan_group(data);
+	fan_beep_need_rw = 1;
+	for (i = 0; i < 5; i++) {
+		if (!(data->has_fan & (1 << i)))
+			continue;
+		err = sysfs_create_group(&dev->kobj, &fan_group[i]);
+		if (err)
+			goto ERROR4;
+
+		if (sio_data->beep_pin) {
+			err = sysfs_create_file(&dev->kobj,
+						it87_attributes_fan_beep[i]);
+			if (err)
 				goto ERROR4;
-		}
-		if (data->has_fan & (1 << 1)) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_fan2_input16.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan2_min16.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan2_alarm.dev_attr)))
-				goto ERROR4;
-		}
-		if (data->has_fan & (1 << 2)) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_fan3_input16.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan3_min16.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan3_alarm.dev_attr)))
-				goto ERROR4;
-		}
-		if (data->has_fan & (1 << 3)) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_fan4_input16.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan4_min16.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan4_alarm.dev_attr)))
-				goto ERROR4;
-		}
-		if (data->has_fan & (1 << 4)) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_fan5_input16.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan5_min16.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan5_alarm.dev_attr)))
-				goto ERROR4;
-		}
-	} else {
-		/* 8-bit tachometers with clock divider */
-		if (data->has_fan & (1 << 0)) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_fan1_input.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan1_min.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan1_div.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan1_alarm.dev_attr)))
-				goto ERROR4;
-		}
-		if (data->has_fan & (1 << 1)) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_fan2_input.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan2_min.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan2_div.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan2_alarm.dev_attr)))
-				goto ERROR4;
-		}
-		if (data->has_fan & (1 << 2)) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_fan3_input.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan3_min.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan3_div.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_fan3_alarm.dev_attr)))
-				goto ERROR4;
+			if (!fan_beep_need_rw)
+				continue;
+
+			/* As we have a single beep enable bit for all fans,
+			 * only the first enabled fan has a writable attribute
+			 * for it. */
+			if (sysfs_chmod_file(&dev->kobj,
+					     it87_attributes_fan_beep[i],
+					     S_IRUGO | S_IWUSR))
+				dev_dbg(dev, "chmod +w fan%d_beep failed\n",
+					i + 1);
+			fan_beep_need_rw = 0;
 		}
 	}
 
 	if (enable_pwm_interface) {
-		if (!(sio_data->skip_pwm & (1 << 0))) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_pwm1_enable.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_pwm1.dev_attr))
-			 || (err = device_create_file(dev,
-			     &dev_attr_pwm1_freq)))
+		for (i = 0; i < 3; i++) {
+			if (sio_data->skip_pwm & (1 << i))
+				continue;
+			err = sysfs_create_group(&dev->kobj,
+						 &it87_group_pwm[i]);
+			if (err)
 				goto ERROR4;
-		}
-		if (!(sio_data->skip_pwm & (1 << 1))) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_pwm2_enable.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_pwm2.dev_attr))
-			 || (err = device_create_file(dev,
-			     &dev_attr_pwm2_freq)))
-				goto ERROR4;
-		}
-		if (!(sio_data->skip_pwm & (1 << 2))) {
-			if ((err = device_create_file(dev,
-			     &sensor_dev_attr_pwm3_enable.dev_attr))
-			 || (err = device_create_file(dev,
-			     &sensor_dev_attr_pwm3.dev_attr))
-			 || (err = device_create_file(dev,
-			     &dev_attr_pwm3_freq)))
+
+			if (!has_old_autopwm(data))
+				continue;
+			err = sysfs_create_group(&dev->kobj,
+						 &it87_group_autopwm[i]);
+			if (err)
 				goto ERROR4;
 		}
 	}
@@ -1268,10 +1696,8 @@
 		data->vrm = vid_which_vrm();
 		/* VID reading from Super-I/O config space if available */
 		data->vid = sio_data->vid_value;
-		if ((err = device_create_file(dev,
-		     &dev_attr_vrm))
-		 || (err = device_create_file(dev,
-		     &dev_attr_cpu0_vid)))
+		err = sysfs_create_group(&dev->kobj, &it87_group_vid);
+		if (err)
 			goto ERROR4;
 	}
 
@@ -1284,8 +1710,7 @@
 	return 0;
 
 ERROR4:
-	sysfs_remove_group(&dev->kobj, &it87_group);
-	sysfs_remove_group(&dev->kobj, &it87_group_opt);
+	it87_remove_files(dev);
 ERROR2:
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
@@ -1300,8 +1725,7 @@
 	struct it87_data *data = platform_get_drvdata(pdev);
 
 	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&pdev->dev.kobj, &it87_group);
-	sysfs_remove_group(&pdev->dev.kobj, &it87_group_opt);
+	it87_remove_files(&pdev->dev);
 
 	release_region(data->addr, IT87_EC_EXTENT);
 	platform_set_drvdata(pdev, NULL);
@@ -1387,15 +1811,18 @@
 	int tmp, i;
 	u8 mask;
 
-	/* initialize to sane defaults:
-	 * - if the chip is in manual pwm mode, this will be overwritten with
-	 *   the actual settings on the chip (so in this case, initialization
-	 *   is not needed)
-	 * - if in automatic or on/off mode, we could switch to manual mode,
-	 *   read the registers and set manual_pwm_ctl accordingly, but currently
-	 *   this is not implemented, so we initialize to something sane */
+	/* For each PWM channel:
+	 * - If it is in automatic mode, setting to manual mode should set
+	 *   the fan to full speed by default.
+	 * - If it is in manual mode, we need a mapping to temperature
+	 *   channels to use when later setting to automatic mode later.
+	 *   Use a 1:1 mapping by default (we are clueless.)
+	 * In both cases, the value can (and should) be changed by the user
+	 * prior to switching to a different mode. */
 	for (i = 0; i < 3; i++) {
-		data->manual_pwm_ctl[i] = 0xff;
+		data->pwm_temp_map[i] = i;
+		data->pwm_duty[i] = 0x7f;	/* Full speed */
+		data->auto_pwm[i][3] = 0x7f;	/* Full speed, hard-coded */
 	}
 
 	/* Some chips seem to have default value 0xff for all limit
@@ -1436,7 +1863,8 @@
 	if ((data->fan_main_ctrl & mask) == 0) {
 		/* Enable all fan tachometers */
 		data->fan_main_ctrl |= mask;
-		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
+		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
+				 data->fan_main_ctrl);
 	}
 	data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
 
@@ -1461,30 +1889,32 @@
 	/* Fan input pins may be used for alternative functions */
 	data->has_fan &= ~sio_data->skip_fan;
 
-	/* Set current fan mode registers and the default settings for the
-	 * other mode registers */
-	for (i = 0; i < 3; i++) {
-		if (data->fan_main_ctrl & (1 << i)) {
-			/* pwm mode */
-			tmp = it87_read_value(data, IT87_REG_PWM(i));
-			if (tmp & 0x80) {
-				/* automatic pwm - not yet implemented, but
-				 * leave the settings made by the BIOS alone
-				 * until a change is requested via the sysfs
-				 * interface */
-			} else {
-				/* manual pwm */
-				data->manual_pwm_ctl[i] = PWM_FROM_REG(tmp);
-			}
-		}
- 	}
-
 	/* Start monitoring */
 	it87_write_value(data, IT87_REG_CONFIG,
 			 (it87_read_value(data, IT87_REG_CONFIG) & 0x36)
 			 | (update_vbat ? 0x41 : 0x01));
 }
 
+static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
+{
+	data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
+	if (data->pwm_ctrl[nr] & 0x80)	/* Automatic mode */
+		data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
+	else				/* Manual mode */
+		data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+
+	if (has_old_autopwm(data)) {
+		int i;
+
+		for (i = 0; i < 5 ; i++)
+			data->auto_temp[nr][i] = it87_read_value(data,
+						IT87_REG_AUTO_TEMP(nr, i));
+		for (i = 0; i < 3 ; i++)
+			data->auto_pwm[nr][i] = it87_read_value(data,
+						IT87_REG_AUTO_PWM(nr, i));
+	}
+}
+
 static struct it87_data *it87_update_device(struct device *dev)
 {
 	struct it87_data *data = dev_get_drvdata(dev);
@@ -1494,24 +1924,22 @@
 
 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
 	    || !data->valid) {
-
 		if (update_vbat) {
 			/* Cleared after each update, so reenable.  Value
-		 	  returned by this read will be previous value */	
+			   returned by this read will be previous value */
 			it87_write_value(data, IT87_REG_CONFIG,
-			   it87_read_value(data, IT87_REG_CONFIG) | 0x40);
+				it87_read_value(data, IT87_REG_CONFIG) | 0x40);
 		}
 		for (i = 0; i <= 7; i++) {
 			data->in[i] =
-			    it87_read_value(data, IT87_REG_VIN(i));
+				it87_read_value(data, IT87_REG_VIN(i));
 			data->in_min[i] =
-			    it87_read_value(data, IT87_REG_VIN_MIN(i));
+				it87_read_value(data, IT87_REG_VIN_MIN(i));
 			data->in_max[i] =
-			    it87_read_value(data, IT87_REG_VIN_MAX(i));
+				it87_read_value(data, IT87_REG_VIN_MAX(i));
 		}
 		/* in8 (battery) has no limit registers */
-		data->in[8] =
-		    it87_read_value(data, IT87_REG_VIN(8));
+		data->in[8] = it87_read_value(data, IT87_REG_VIN(8));
 
 		for (i = 0; i < 5; i++) {
 			/* Skip disabled fans */
@@ -1519,7 +1947,7 @@
 				continue;
 
 			data->fan_min[i] =
-			    it87_read_value(data, IT87_REG_FAN_MIN[i]);
+				it87_read_value(data, IT87_REG_FAN_MIN[i]);
 			data->fan[i] = it87_read_value(data,
 				       IT87_REG_FAN[i]);
 			/* Add high byte if in 16-bit mode */
@@ -1532,11 +1960,11 @@
 		}
 		for (i = 0; i < 3; i++) {
 			data->temp[i] =
-			    it87_read_value(data, IT87_REG_TEMP(i));
+				it87_read_value(data, IT87_REG_TEMP(i));
 			data->temp_high[i] =
-			    it87_read_value(data, IT87_REG_TEMP_HIGH(i));
+				it87_read_value(data, IT87_REG_TEMP_HIGH(i));
 			data->temp_low[i] =
-			    it87_read_value(data, IT87_REG_TEMP_LOW(i));
+				it87_read_value(data, IT87_REG_TEMP_LOW(i));
 		}
 
 		/* Newer chips don't have clock dividers */
@@ -1551,9 +1979,13 @@
 			it87_read_value(data, IT87_REG_ALARM1) |
 			(it87_read_value(data, IT87_REG_ALARM2) << 8) |
 			(it87_read_value(data, IT87_REG_ALARM3) << 16);
+		data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
+
 		data->fan_main_ctrl = it87_read_value(data,
 				IT87_REG_FAN_MAIN_CTRL);
 		data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
+		for (i = 0; i < 3; i++)
+			it87_update_pwm_ctrl(data, i);
 
 		data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
 		/* The 8705 does not have VID capability.
@@ -1628,7 +2060,7 @@
 static int __init sm_it87_init(void)
 {
 	int err;
-	unsigned short isa_address=0;
+	unsigned short isa_address = 0;
 	struct it87_sio_data sio_data;
 
 	memset(&sio_data, 0, sizeof(struct it87_sio_data));
@@ -1640,7 +2072,7 @@
 		return err;
 
 	err = it87_device_add(isa_address, &sio_data);
-	if (err){
+	if (err) {
 		platform_driver_unregister(&it87_driver);
 		return err;
 	}
@@ -1661,7 +2093,8 @@
 module_param(update_vbat, bool, 0);
 MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
 module_param(fix_pwm_polarity, bool, 0);
-MODULE_PARM_DESC(fix_pwm_polarity, "Force PWM polarity to active high (DANGEROUS)");
+MODULE_PARM_DESC(fix_pwm_polarity,
+		 "Force PWM polarity to active high (DANGEROUS)");
 MODULE_LICENSE("GPL");
 
 module_init(sm_it87_init);
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 7c9bdc1..7cc2708 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -1,7 +1,7 @@
 /*
  * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
  *          monitoring
- * Copyright (C) 2003-2009  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2010  Jean Delvare <khali@linux-fr.org>
  *
  * Based on the lm83 driver. The LM90 is a sensor chip made by National
  * Semiconductor. It reports up to two temperatures (its own plus up to
@@ -93,7 +93,8 @@
 static const unsigned short normal_i2c[] = {
 	0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
 
-enum chips { lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, max6646 };
+enum chips { lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, max6646,
+	w83l771 };
 
 /*
  * The LM90 registers
@@ -151,6 +152,7 @@
 static int lm90_probe(struct i2c_client *client,
 		      const struct i2c_device_id *id);
 static void lm90_init_client(struct i2c_client *client);
+static void lm90_alert(struct i2c_client *client, unsigned int flag);
 static int lm90_remove(struct i2c_client *client);
 static struct lm90_data *lm90_update_device(struct device *dev);
 
@@ -173,6 +175,7 @@
 	{ "max6659", max6657 },
 	{ "max6680", max6680 },
 	{ "max6681", max6680 },
+	{ "w83l771", w83l771 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm90_id);
@@ -184,6 +187,7 @@
 	},
 	.probe		= lm90_probe,
 	.remove		= lm90_remove,
+	.alert		= lm90_alert,
 	.id_table	= lm90_id,
 	.detect		= lm90_detect,
 	.address_list	= normal_i2c,
@@ -201,6 +205,9 @@
 	int kind;
 	int flags;
 
+	u8 config_orig;		/* Original configuration register value */
+	u8 alert_alarms;	/* Which alarm bits trigger ALERT# */
+
 	/* registers values */
 	s8 temp8[4];	/* 0: local low limit
 			   1: local high limit
@@ -758,6 +765,14 @@
 		 && reg_convrate <= 0x07) {
 			name = "max6646";
 		}
+	} else
+	if (address == 0x4C
+	 && man_id == 0x5C) { /* Winbond/Nuvoton */
+		if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */
+		 && (reg_config1 & 0x2A) == 0x00
+		 && reg_convrate <= 0x08) {
+			name = "w83l771";
+		}
 	}
 
 	if (!name) { /* identification failed */
@@ -794,6 +809,19 @@
 			new_client->flags &= ~I2C_CLIENT_PEC;
 	}
 
+	/* Different devices have different alarm bits triggering the
+	 * ALERT# output */
+	switch (data->kind) {
+	case lm90:
+	case lm99:
+	case lm86:
+		data->alert_alarms = 0x7b;
+		break;
+	default:
+		data->alert_alarms = 0x7c;
+		break;
+	}
+
 	/* Initialize the LM90 chip */
 	lm90_init_client(new_client);
 
@@ -830,7 +858,7 @@
 
 static void lm90_init_client(struct i2c_client *client)
 {
-	u8 config, config_orig;
+	u8 config;
 	struct lm90_data *data = i2c_get_clientdata(client);
 
 	/*
@@ -842,7 +870,7 @@
 		dev_warn(&client->dev, "Initialization failed!\n");
 		return;
 	}
-	config_orig = config;
+	data->config_orig = config;
 
 	/* Check Temperature Range Select */
 	if (data->kind == adt7461) {
@@ -860,7 +888,7 @@
 	}
 
 	config &= 0xBF;	/* run */
-	if (config != config_orig) /* Only write if changed */
+	if (config != data->config_orig) /* Only write if changed */
 		i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
 }
 
@@ -875,10 +903,46 @@
 		device_remove_file(&client->dev,
 				   &sensor_dev_attr_temp2_offset.dev_attr);
 
+	/* Restore initial configuration */
+	i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
+				  data->config_orig);
+
 	kfree(data);
 	return 0;
 }
 
+static void lm90_alert(struct i2c_client *client, unsigned int flag)
+{
+	struct lm90_data *data = i2c_get_clientdata(client);
+	u8 config, alarms;
+
+	lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);
+	if ((alarms & 0x7f) == 0) {
+		dev_info(&client->dev, "Everything OK\n");
+	} else {
+		if (alarms & 0x61)
+			dev_warn(&client->dev,
+				 "temp%d out of range, please check!\n", 1);
+		if (alarms & 0x1a)
+			dev_warn(&client->dev,
+				 "temp%d out of range, please check!\n", 2);
+		if (alarms & 0x04)
+			dev_warn(&client->dev,
+				 "temp%d diode open, please check!\n", 2);
+
+		/* Disable ALERT# output, because these chips don't implement
+		  SMBus alert correctly; they should only hold the alert line
+		  low briefly. */
+		if ((data->kind == adm1032 || data->kind == adt7461)
+		 && (alarms & data->alert_alarms)) {
+			dev_dbg(&client->dev, "Disabling ALERT#\n");
+			lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
+			i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
+						  config | 0x80);
+		}
+	}
+}
+
 static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
 {
 	int err;
@@ -966,6 +1030,21 @@
 		}
 		lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
 
+		/* Re-enable ALERT# output if it was originally enabled and
+		 * relevant alarms are all clear */
+		if ((data->config_orig & 0x80) == 0
+		 && (data->alarms & data->alert_alarms) == 0) {
+			u8 config;
+
+			lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
+			if (config & 0x80) {
+				dev_dbg(&client->dev, "Re-enabling ALERT#\n");
+				i2c_smbus_write_byte_data(client,
+							  LM90_REG_W_CONFIG1,
+							  config & ~0x80);
+			}
+		}
+
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
index a13b30e..d14a1af 100644
--- a/drivers/hwmon/tmp401.c
+++ b/drivers/hwmon/tmp401.c
@@ -134,7 +134,7 @@
 	struct mutex update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
-	int kind;
+	enum chips kind;
 
 	/* register values */
 	u8 status;
@@ -524,7 +524,7 @@
 	if (reg > 15)
 		return -ENODEV;
 
-	strlcpy(info->type, tmp401_id[kind - 1].name, I2C_NAME_SIZE);
+	strlcpy(info->type, tmp401_id[kind].name, I2C_NAME_SIZE);
 
 	return 0;
 }
@@ -572,8 +572,7 @@
 		goto exit_remove;
 	}
 
-	dev_info(&client->dev, "Detected TI %s chip\n",
-		 names[data->kind - 1]);
+	dev_info(&client->dev, "Detected TI %s chip\n", names[data->kind]);
 
 	return 0;
 
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 4f7c051..738c472 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -61,9 +61,9 @@
 #define TMP423_DEVICE_ID			0x23
 
 static const struct i2c_device_id tmp421_id[] = {
-	{ "tmp421", tmp421 },
-	{ "tmp422", tmp422 },
-	{ "tmp423", tmp423 },
+	{ "tmp421", 2 },
+	{ "tmp422", 3 },
+	{ "tmp423", 4 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, tmp421_id);
@@ -73,21 +73,23 @@
 	struct mutex update_lock;
 	char valid;
 	unsigned long last_updated;
-	int kind;
+	int channels;
 	u8 config;
 	s16 temp[4];
 };
 
 static int temp_from_s16(s16 reg)
 {
-	int temp = reg;
+	/* Mask out status bits */
+	int temp = reg & ~0xf;
 
 	return (temp * 1000 + 128) / 256;
 }
 
 static int temp_from_u16(u16 reg)
 {
-	int temp = reg;
+	/* Mask out status bits */
+	int temp = reg & ~0xf;
 
 	/* Add offset for extended temperature range. */
 	temp -= 64 * 256;
@@ -107,7 +109,7 @@
 		data->config = i2c_smbus_read_byte_data(client,
 			TMP421_CONFIG_REG_1);
 
-		for (i = 0; i <= data->kind; i++) {
+		for (i = 0; i < data->channels; i++) {
 			data->temp[i] = i2c_smbus_read_byte_data(client,
 				TMP421_TEMP_MSB[i]) << 8;
 			data->temp[i] |= i2c_smbus_read_byte_data(client,
@@ -166,7 +168,7 @@
 	devattr = container_of(a, struct device_attribute, attr);
 	index = to_sensor_dev_attr(devattr)->index;
 
-	if (data->kind > index)
+	if (index < data->channels)
 		return a->mode;
 
 	return 0;
@@ -252,9 +254,9 @@
 		return -ENODEV;
 	}
 
-	strlcpy(info->type, tmp421_id[kind - 1].name, I2C_NAME_SIZE);
+	strlcpy(info->type, tmp421_id[kind].name, I2C_NAME_SIZE);
 	dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n",
-		 names[kind - 1], client->addr);
+		 names[kind], client->addr);
 
 	return 0;
 }
@@ -271,7 +273,7 @@
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
-	data->kind = id->driver_data;
+	data->channels = id->driver_data;
 
 	err = tmp421_init_client(client);
 	if (err)
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index d47b4c9..e6078c9 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -948,8 +948,7 @@
 
 	address = val & ~(VT8231_EXTENT - 1);
 	if (address == 0) {
-		dev_err(&dev->dev, "base address not set -\
-				 upgrade BIOS or use force_addr=0xaddr\n");
+		dev_err(&dev->dev, "base address not set - upgrade BIOS or use force_addr=0xaddr\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 9a2022b..9de81a4 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -3,6 +3,10 @@
     Copyright (C) 2006 Winbond Electronics Corp.
                   Yuan Mu
                   Rudolf Marek <r.marek@assembler.cz>
+    Copyright (C) 2009-2010 Sven Anders <anders@anduras.de>, ANDURAS AG.
+		  Watchdog driver part
+		  (Based partially on fschmd driver,
+		   Copyright 2007-2008 by Hans de Goede)
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -35,6 +39,16 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/fs.h>
+#include <linux/watchdog.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/kref.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+/* Default values */
+#define WATCHDOG_TIMEOUT 2	/* 2 minute default timeout */
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
@@ -51,6 +65,18 @@
 module_param(reset, bool, 0);
 MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
 
+static int timeout = WATCHDOG_TIMEOUT;	/* default timeout in minutes */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,
+	"Watchdog timeout in minutes. 2<= timeout <=255 (default="
+				__MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+	"Watchdog cannot be stopped once started (default="
+				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
 /*
    Address 0x00, 0x0d, 0x0e, 0x0f in all three banks are reserved
    as ID, Bank Select registers
@@ -72,6 +98,11 @@
 #define W83793_REG_VID_LATCHB		0x08
 #define W83793_REG_VID_CTRL		0x59
 
+#define W83793_REG_WDT_LOCK		0x01
+#define W83793_REG_WDT_ENABLE		0x02
+#define W83793_REG_WDT_STATUS		0x03
+#define W83793_REG_WDT_TIMEOUT		0x04
+
 static u16 W83793_REG_TEMP_MODE[2] = { 0x5e, 0x5f };
 
 #define TEMP_READ	0
@@ -223,8 +254,37 @@
 	u8 tolerance[3];	/* Temp tolerance(Smart Fan I/II) */
 	u8 sf2_pwm[6][7];	/* Smart FanII: Fan duty cycle */
 	u8 sf2_temp[6][7];	/* Smart FanII: Temp level point */
+
+	/* watchdog */
+	struct i2c_client *client;
+	struct mutex watchdog_lock;
+	struct list_head list; /* member of the watchdog_data_list */
+	struct kref kref;
+	struct miscdevice watchdog_miscdev;
+	unsigned long watchdog_is_open;
+	char watchdog_expect_close;
+	char watchdog_name[10]; /* must be unique to avoid sysfs conflict */
+	unsigned int watchdog_caused_reboot;
+	int watchdog_timeout; /* watchdog timeout in minutes */
 };
 
+/* Somewhat ugly :( global data pointer list with all devices, so that
+   we can find our device data as when using misc_register. There is no
+   other method to get to one's device data from the open file-op and
+   for usage in the reboot notifier callback. */
+static LIST_HEAD(watchdog_data_list);
+
+/* Note this lock not only protect list access, but also data.kref access */
+static DEFINE_MUTEX(watchdog_data_mutex);
+
+/* Release our data struct when we're detached from the i2c client *and* all
+   references to our watchdog device are released */
+static void w83793_release_resources(struct kref *ref)
+{
+	struct w83793_data *data = container_of(ref, struct w83793_data, kref);
+	kfree(data);
+}
+
 static u8 w83793_read_value(struct i2c_client *client, u16 reg);
 static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value);
 static int w83793_probe(struct i2c_client *client,
@@ -1063,14 +1123,349 @@
 	/* Start monitoring */
 	w83793_write_value(client, W83793_REG_CONFIG,
 			   w83793_read_value(client, W83793_REG_CONFIG) | 0x01);
-
 }
 
+/*
+ * Watchdog routines
+ */
+
+static int watchdog_set_timeout(struct w83793_data *data, int timeout)
+{
+	int ret, mtimeout;
+
+	mtimeout = DIV_ROUND_UP(timeout, 60);
+
+	if (mtimeout > 255)
+		return -EINVAL;
+
+	mutex_lock(&data->watchdog_lock);
+	if (!data->client) {
+		ret = -ENODEV;
+		goto leave;
+	}
+
+	data->watchdog_timeout = mtimeout;
+
+	/* Set Timeout value (in Minutes) */
+	w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT,
+			   data->watchdog_timeout);
+
+	ret = mtimeout * 60;
+
+leave:
+	mutex_unlock(&data->watchdog_lock);
+	return ret;
+}
+
+static int watchdog_get_timeout(struct w83793_data *data)
+{
+	int timeout;
+
+	mutex_lock(&data->watchdog_lock);
+	timeout = data->watchdog_timeout * 60;
+	mutex_unlock(&data->watchdog_lock);
+
+	return timeout;
+}
+
+static int watchdog_trigger(struct w83793_data *data)
+{
+	int ret = 0;
+
+	mutex_lock(&data->watchdog_lock);
+	if (!data->client) {
+		ret = -ENODEV;
+		goto leave;
+	}
+
+	/* Set Timeout value (in Minutes) */
+	w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT,
+			   data->watchdog_timeout);
+
+leave:
+	mutex_unlock(&data->watchdog_lock);
+	return ret;
+}
+
+static int watchdog_enable(struct w83793_data *data)
+{
+	int ret = 0;
+
+	mutex_lock(&data->watchdog_lock);
+	if (!data->client) {
+		ret = -ENODEV;
+		goto leave;
+	}
+
+	/* Set initial timeout */
+	w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT,
+			   data->watchdog_timeout);
+
+	/* Enable Soft Watchdog */
+	w83793_write_value(data->client, W83793_REG_WDT_LOCK, 0x55);
+
+leave:
+	mutex_unlock(&data->watchdog_lock);
+	return ret;
+}
+
+static int watchdog_disable(struct w83793_data *data)
+{
+	int ret = 0;
+
+	mutex_lock(&data->watchdog_lock);
+	if (!data->client) {
+		ret = -ENODEV;
+		goto leave;
+	}
+
+	/* Disable Soft Watchdog */
+	w83793_write_value(data->client, W83793_REG_WDT_LOCK, 0xAA);
+
+leave:
+	mutex_unlock(&data->watchdog_lock);
+	return ret;
+}
+
+static int watchdog_open(struct inode *inode, struct file *filp)
+{
+	struct w83793_data *pos, *data = NULL;
+	int watchdog_is_open;
+
+	/* We get called from drivers/char/misc.c with misc_mtx hold, and we
+	   call misc_register() from  w83793_probe() with watchdog_data_mutex
+	   hold, as misc_register() takes the misc_mtx lock, this is a possible
+	   deadlock, so we use mutex_trylock here. */
+	if (!mutex_trylock(&watchdog_data_mutex))
+		return -ERESTARTSYS;
+	list_for_each_entry(pos, &watchdog_data_list, list) {
+		if (pos->watchdog_miscdev.minor == iminor(inode)) {
+			data = pos;
+			break;
+		}
+	}
+
+	/* Check, if device is already open */
+	watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open);
+
+	/* Increase data reference counter (if not already done).
+	   Note we can never not have found data, so we don't check for this */
+	if (!watchdog_is_open)
+		kref_get(&data->kref);
+
+	mutex_unlock(&watchdog_data_mutex);
+
+	/* Check, if device is already open and possibly issue error */
+	if (watchdog_is_open)
+		return -EBUSY;
+
+	/* Enable Soft Watchdog */
+	watchdog_enable(data);
+
+	/* Store pointer to data into filp's private data */
+	filp->private_data = data;
+
+	return nonseekable_open(inode, filp);
+}
+
+static int watchdog_close(struct inode *inode, struct file *filp)
+{
+	struct w83793_data *data = filp->private_data;
+
+	if (data->watchdog_expect_close) {
+		watchdog_disable(data);
+		data->watchdog_expect_close = 0;
+	} else {
+		watchdog_trigger(data);
+		dev_crit(&data->client->dev,
+			"unexpected close, not stopping watchdog!\n");
+	}
+
+	clear_bit(0, &data->watchdog_is_open);
+
+	/* Decrease data reference counter */
+	mutex_lock(&watchdog_data_mutex);
+	kref_put(&data->kref, w83793_release_resources);
+	mutex_unlock(&watchdog_data_mutex);
+
+	return 0;
+}
+
+static ssize_t watchdog_write(struct file *filp, const char __user *buf,
+	size_t count, loff_t *offset)
+{
+	size_t ret;
+	struct w83793_data *data = filp->private_data;
+
+	if (count) {
+		if (!nowayout) {
+			size_t i;
+
+			/* Clear it in case it was set with a previous write */
+			data->watchdog_expect_close = 0;
+
+			for (i = 0; i != count; i++) {
+				char c;
+				if (get_user(c, buf + i))
+					return -EFAULT;
+				if (c == 'V')
+					data->watchdog_expect_close = 1;
+			}
+		}
+		ret = watchdog_trigger(data);
+		if (ret < 0)
+			return ret;
+	}
+	return count;
+}
+
+static int watchdog_ioctl(struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg)
+{
+	static struct watchdog_info ident = {
+		.options = WDIOF_KEEPALIVEPING |
+			   WDIOF_SETTIMEOUT |
+			   WDIOF_CARDRESET,
+		.identity = "w83793 watchdog"
+	};
+
+	int val, ret = 0;
+	struct w83793_data *data = filp->private_data;
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		if (!nowayout)
+			ident.options |= WDIOF_MAGICCLOSE;
+		if (copy_to_user((void __user *)arg, &ident, sizeof(ident)))
+			ret = -EFAULT;
+		break;
+
+	case WDIOC_GETSTATUS:
+		val = data->watchdog_caused_reboot ? WDIOF_CARDRESET : 0;
+		ret = put_user(val, (int __user *)arg);
+		break;
+
+	case WDIOC_GETBOOTSTATUS:
+		ret = put_user(0, (int __user *)arg);
+		break;
+
+	case WDIOC_KEEPALIVE:
+		ret = watchdog_trigger(data);
+		break;
+
+	case WDIOC_GETTIMEOUT:
+		val = watchdog_get_timeout(data);
+		ret = put_user(val, (int __user *)arg);
+		break;
+
+	case WDIOC_SETTIMEOUT:
+		if (get_user(val, (int __user *)arg)) {
+			ret = -EFAULT;
+			break;
+		}
+		ret = watchdog_set_timeout(data, val);
+		if (ret > 0)
+			ret = put_user(ret, (int __user *)arg);
+		break;
+
+	case WDIOC_SETOPTIONS:
+		if (get_user(val, (int __user *)arg)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		if (val & WDIOS_DISABLECARD)
+			ret = watchdog_disable(data);
+		else if (val & WDIOS_ENABLECARD)
+			ret = watchdog_enable(data);
+		else
+			ret = -EINVAL;
+
+		break;
+	default:
+		ret = -ENOTTY;
+	}
+
+	return ret;
+}
+
+static const struct file_operations watchdog_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = watchdog_open,
+	.release = watchdog_close,
+	.write = watchdog_write,
+	.ioctl = watchdog_ioctl,
+};
+
+/*
+ *	Notifier for system down
+ */
+
+static int watchdog_notify_sys(struct notifier_block *this, unsigned long code,
+			       void *unused)
+{
+	struct w83793_data *data = NULL;
+
+	if (code == SYS_DOWN || code == SYS_HALT) {
+
+		/* Disable each registered watchdog */
+		mutex_lock(&watchdog_data_mutex);
+		list_for_each_entry(data, &watchdog_data_list, list) {
+			if (data->watchdog_miscdev.minor)
+				watchdog_disable(data);
+		}
+		mutex_unlock(&watchdog_data_mutex);
+	}
+
+	return NOTIFY_DONE;
+}
+
+/*
+ *	The WDT needs to learn about soft shutdowns in order to
+ *	turn the timebomb registers off.
+ */
+
+static struct notifier_block watchdog_notifier = {
+	.notifier_call = watchdog_notify_sys,
+};
+
+/*
+ * Init / remove routines
+ */
+
 static int w83793_remove(struct i2c_client *client)
 {
 	struct w83793_data *data = i2c_get_clientdata(client);
 	struct device *dev = &client->dev;
-	int i;
+	int i, tmp;
+
+	/* Unregister the watchdog (if registered) */
+	if (data->watchdog_miscdev.minor) {
+		misc_deregister(&data->watchdog_miscdev);
+
+		if (data->watchdog_is_open) {
+			dev_warn(&client->dev,
+				"i2c client detached with watchdog open! "
+				"Stopping watchdog.\n");
+			watchdog_disable(data);
+		}
+
+		mutex_lock(&watchdog_data_mutex);
+		list_del(&data->list);
+		mutex_unlock(&watchdog_data_mutex);
+
+		/* Tell the watchdog code the client is gone */
+		mutex_lock(&data->watchdog_lock);
+		data->client = NULL;
+		mutex_unlock(&data->watchdog_lock);
+	}
+
+	/* Reset Configuration Register to Disable Watch Dog Registers */
+	tmp = w83793_read_value(client, W83793_REG_CONFIG);
+	w83793_write_value(client, W83793_REG_CONFIG, tmp & ~0x04);
+
+	unregister_reboot_notifier(&watchdog_notifier);
 
 	hwmon_device_unregister(data->hwmon_dev);
 
@@ -1099,7 +1494,10 @@
 	if (data->lm75[1] != NULL)
 		i2c_unregister_device(data->lm75[1]);
 
-	kfree(data);
+	/* Decrease data reference counter */
+	mutex_lock(&watchdog_data_mutex);
+	kref_put(&data->kref, w83793_release_resources);
+	mutex_unlock(&watchdog_data_mutex);
 
 	return 0;
 }
@@ -1203,6 +1601,7 @@
 			const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
+	const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
 	struct w83793_data *data;
 	int i, tmp, val, err;
 	int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
@@ -1218,6 +1617,14 @@
 	i2c_set_clientdata(client, data);
 	data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL);
 	mutex_init(&data->update_lock);
+	mutex_init(&data->watchdog_lock);
+	INIT_LIST_HEAD(&data->list);
+	kref_init(&data->kref);
+
+	/* Store client pointer in our data struct for watchdog usage
+	   (where the client is found through a data ptr instead of the
+	   otherway around) */
+	data->client = client;
 
 	err = w83793_detect_subclients(client);
 	if (err)
@@ -1380,8 +1787,77 @@
 		goto exit_remove;
 	}
 
+	/* Watchdog initialization */
+
+	/* Register boot notifier */
+	err = register_reboot_notifier(&watchdog_notifier);
+	if (err != 0) {
+		dev_err(&client->dev,
+			"cannot register reboot notifier (err=%d)\n", err);
+		goto exit_devunreg;
+	}
+
+	/* Enable Watchdog registers.
+	   Set Configuration Register to Enable Watch Dog Registers
+	   (Bit 2) = XXXX, X1XX. */
+	tmp = w83793_read_value(client, W83793_REG_CONFIG);
+	w83793_write_value(client, W83793_REG_CONFIG, tmp | 0x04);
+
+	/* Set the default watchdog timeout */
+	data->watchdog_timeout = timeout;
+
+	/* Check, if last reboot was caused by watchdog */
+	data->watchdog_caused_reboot =
+	  w83793_read_value(data->client, W83793_REG_WDT_STATUS) & 0x01;
+
+	/* Disable Soft Watchdog during initialiation */
+	watchdog_disable(data);
+
+	/* We take the data_mutex lock early so that watchdog_open() cannot
+	   run when misc_register() has completed, but we've not yet added
+	   our data to the watchdog_data_list (and set the default timeout) */
+	mutex_lock(&watchdog_data_mutex);
+	for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) {
+		/* Register our watchdog part */
+		snprintf(data->watchdog_name, sizeof(data->watchdog_name),
+			"watchdog%c", (i == 0) ? '\0' : ('0' + i));
+		data->watchdog_miscdev.name = data->watchdog_name;
+		data->watchdog_miscdev.fops = &watchdog_fops;
+		data->watchdog_miscdev.minor = watchdog_minors[i];
+
+		err = misc_register(&data->watchdog_miscdev);
+		if (err == -EBUSY)
+			continue;
+		if (err) {
+			data->watchdog_miscdev.minor = 0;
+			dev_err(&client->dev,
+				"Registering watchdog chardev: %d\n", err);
+			break;
+		}
+
+		list_add(&data->list, &watchdog_data_list);
+
+		dev_info(&client->dev,
+			"Registered watchdog chardev major 10, minor: %d\n",
+			watchdog_minors[i]);
+		break;
+	}
+	if (i == ARRAY_SIZE(watchdog_minors)) {
+		data->watchdog_miscdev.minor = 0;
+		dev_warn(&client->dev, "Couldn't register watchdog chardev "
+			"(due to no free minor)\n");
+	}
+
+	mutex_unlock(&watchdog_data_mutex);
+
 	return 0;
 
+	/* Unregister hwmon device */
+
+exit_devunreg:
+
+	hwmon_device_unregister(data->hwmon_dev);
+
 	/* Unregister sysfs hooks */
 
 exit_remove:
@@ -1628,7 +2104,7 @@
 	i2c_del_driver(&w83793_driver);
 }
 
-MODULE_AUTHOR("Yuan Mu");
+MODULE_AUTHOR("Yuan Mu, Sven Anders");
 MODULE_DESCRIPTION("w83793 driver");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 8d8a00e..02ce9cf 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -61,6 +61,16 @@
 
 	  In doubt, say Y.
 
+config I2C_SMBUS
+	tristate "SMBus-specific protocols" if !I2C_HELPER_AUTO
+	help
+	  Say Y here if you want support for SMBus extensions to the I2C
+	  specification. At the moment, the only supported extension is
+	  the SMBus alert protocol.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-smbus.
+
 source drivers/i2c/algos/Kconfig
 source drivers/i2c/busses/Kconfig
 source drivers/i2c/chips/Kconfig
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index ba26e6c..acd0250 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_I2C_BOARDINFO)	+= i2c-boardinfo.o
 obj-$(CONFIG_I2C)		+= i2c-core.o
+obj-$(CONFIG_I2C_SMBUS)		+= i2c-smbus.o
 obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
 obj-y				+= busses/ chips/ algos/
 
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index 78d42aa..dcdaf8e 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -453,8 +453,6 @@
 		 */
 		int raise_fall_time;
 
-		struct i2c_algo_pca_data *pca_data = adap->algo_data;
-
 		/* Ignore the reset function from the module,
 		 * we can use the parallel bus reset
 		 */
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 7ce7577..6b6bd06 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -176,7 +176,7 @@
 	 */
 	if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) {
 		DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp));
-		return -ENXIO; /* definetly not PCF8584 */
+		return -ENXIO; /* definitely not PCF8584 */
 	}
 
 	/* load own address in S0, effective address is (own << 1) */
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 737f052..9c6170c 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -77,7 +77,7 @@
 	  will be called i2c-amd8111.
 
 config I2C_I801
-	tristate "Intel 82801 (ICH)"
+	tristate "Intel 82801 (ICH/PCH)"
 	depends on PCI
 	help
 	  If you say yes to this option, support will be included for the Intel
@@ -97,7 +97,8 @@
 	    ICH9
 	    Tolapai
 	    ICH10
-	    PCH
+	    3400/5 Series (PCH)
+	    Cougar Point (PCH)
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-i801.
@@ -105,6 +106,8 @@
 config I2C_ISCH
 	tristate "Intel SCH SMBus 1.0"
 	depends on PCI
+	select MFD_CORE
+	select LPC_SCH
 	help
 	  Say Y here if you want to use SMBus controller on the Intel SCH
 	  based systems.
@@ -418,13 +421,12 @@
 	  instead.
 
 config I2C_MPC
-	tristate "MPC107/824x/85xx/52xx/86xx"
+	tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
 	depends on PPC32
 	help
 	  If you say yes to this option, support will be included for the
-	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
-	  MPC85xx/MPC8641 family processors. The driver may also work on 52xx
-	  family processors, though interrupts are known not to work.
+	  built-in I2C interface on the MPC107, Tsi107, MPC512x, MPC52xx,
+	  MPC8240, MPC8245, MPC83xx, MPC85xx and MPC8641 family processors.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mpc.
@@ -439,6 +441,13 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mv64xxx.
 
+config I2C_NOMADIK
+	tristate "ST-Ericsson Nomadik/Ux500 I2C Controller"
+	depends on PLAT_NOMADIK
+	help
+	  If you say yes to this option, support will be included for the
+	  I2C interface from ST-Ericsson's Nomadik and Ux500 architectures.
+
 config I2C_OCORES
 	tristate "OpenCores I2C Controller"
 	depends on EXPERIMENTAL
@@ -574,12 +583,23 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-octeon.
 
+config I2C_XILINX
+	tristate "Xilinx I2C Controller"
+	depends on EXPERIMENTAL && HAS_IOMEM
+	help
+	  If you say yes to this option, support will be included for the
+	  Xilinx I2C controller.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called xilinx_i2c.
+
 comment "External I2C/SMBus adapter drivers"
 
 config I2C_PARPORT
 	tristate "Parallel port adapter"
 	depends on PARPORT
 	select I2C_ALGOBIT
+	select I2C_SMBUS
 	help
 	  This supports parallel port I2C adapters such as the ones made by
 	  Philips or Velleman, Analog Devices evaluation boards, and more.
@@ -603,6 +623,7 @@
 config I2C_PARPORT_LIGHT
 	tristate "Parallel port adapter (light)"
 	select I2C_ALGOBIT
+	select I2C_SMBUS
 	help
 	  This supports parallel port I2C adapters such as the ones made by
 	  Philips or Velleman, Analog Devices evaluation boards, and more.
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index c2c4ea1..097236f 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -42,6 +42,7 @@
 obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
+obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
 obj-$(CONFIG_I2C_OCORES)	+= i2c-ocores.o
 obj-$(CONFIG_I2C_OMAP)		+= i2c-omap.o
 obj-$(CONFIG_I2C_PASEMI)	+= i2c-pasemi.o
@@ -55,6 +56,7 @@
 obj-$(CONFIG_I2C_STU300)	+= i2c-stu300.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
+obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
 
 # External I2C/SMBus adapter drivers
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index 8de7d7b..bd8f1e4 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -480,7 +480,7 @@
 	.algo		= &smbus_algorithm,
 };
 
-static struct pci_device_id ali1535_ids[] = {
+static const struct pci_device_id ali1535_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
 	{ },
 };
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index 4687af4..a409cfc 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -417,7 +417,7 @@
 	ali1563_shutdown(dev);
 }
 
-static struct pci_device_id __devinitdata ali1563_id_table[] = {
+static const struct pci_device_id ali1563_id_table[] __devinitconst = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) },
 	{},
 };
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index e7e3205..659f63f 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -477,7 +477,7 @@
 	.algo		= &smbus_algorithm,
 };
 
-static struct pci_device_id ali15x3_ids[] = {
+static const struct pci_device_id ali15x3_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
 	{ 0, }
 };
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 8f0b90e..c5a9fa4 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -308,7 +308,7 @@
 	"nVidia nForce", "AMD8111",
 };
 
-static struct pci_device_id amd756_ids[] = {
+static const struct pci_device_id amd756_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B),
 	  .driver_data = AMD756 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413),
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 5b4ad86..d0dc970 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -351,7 +351,7 @@
 };
 
 
-static struct pci_device_id amd8111_ids[] = {
+static const struct pci_device_id amd8111_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) },
 	{ 0, }
 };
diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c
index 9e18ef9..3e72b69 100644
--- a/drivers/i2c/busses/i2c-designware.c
+++ b/drivers/i2c/busses/i2c-designware.c
@@ -497,13 +497,13 @@
 	int i;
 
 	if (abort_source & DW_IC_TX_ABRT_NOACK) {
-		for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+		for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
 			dev_dbg(dev->dev,
 				"%s: %s\n", __func__, abort_sources[i]);
 		return -EREMOTEIO;
 	}
 
-	for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+	for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
 		dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
 
 	if (abort_source & DW_IC_TX_ARB_LOST)
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index bec9b84..c767295 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -105,7 +105,7 @@
 	.algo_data	= &hydra_bit_data,
 };
 
-static struct pci_device_id hydra_ids[] = {
+static const struct pci_device_id hydra_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) },
 	{ 0, }
 };
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index df6ab553..9da5b05 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -41,7 +41,8 @@
   Tolapai               0x5032     32     hard     yes     yes     yes
   ICH10                 0x3a30     32     hard     yes     yes     yes
   ICH10                 0x3a60     32     hard     yes     yes     yes
-  PCH                   0x3b30     32     hard     yes     yes     yes
+  3400/5 Series (PCH)   0x3b30     32     hard     yes     yes     yes
+  Cougar Point (PCH)    0x1c22     32     hard     yes     yes     yes
 
   Features supported by this driver:
   Software PEC                     no
@@ -561,7 +562,7 @@
 	.algo		= &smbus_algorithm,
 };
 
-static struct pci_device_id i801_ids[] = {
+static const struct pci_device_id i801_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
@@ -578,6 +579,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CPT_SMBUS) },
 	{ 0, }
 };
 
@@ -707,6 +709,7 @@
 	case PCI_DEVICE_ID_INTEL_ICH10_4:
 	case PCI_DEVICE_ID_INTEL_ICH10_5:
 	case PCI_DEVICE_ID_INTEL_PCH_SMBUS:
+	case PCI_DEVICE_ID_INTEL_CPT_SMBUS:
 		i801_features |= FEATURE_I2C_BLOCK_READ;
 		/* fall through */
 	case PCI_DEVICE_ID_INTEL_82801DB_3:
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 75bf820..32375bd 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -627,7 +627,6 @@
 }
 
 static struct platform_driver i2c_imx_driver = {
-	.probe		= i2c_imx_probe,
 	.remove		= __exit_p(i2c_imx_remove),
 	.driver	= {
 		.name	= DRIVER_NAME,
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
index dba6eb0..ddc258e 100644
--- a/drivers/i2c/busses/i2c-isch.c
+++ b/drivers/i2c/busses/i2c-isch.c
@@ -27,7 +27,7 @@
 */
 
 #include <linux/module.h>
-#include <linux/pci.h>
+#include <linux/platform_device.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/stddef.h>
@@ -46,12 +46,6 @@
 #define SMBHSTDAT1	(7 + sch_smba)
 #define SMBBLKDAT	(0x20 + sch_smba)
 
-/* count for request_region */
-#define SMBIOSIZE	64
-
-/* PCI Address Constants */
-#define SMBBA_SCH	0x40
-
 /* Other settings */
 #define MAX_TIMEOUT	500
 
@@ -63,7 +57,6 @@
 #define SCH_BLOCK_DATA		0x05
 
 static unsigned short sch_smba;
-static struct pci_driver sch_driver;
 static struct i2c_adapter sch_adapter;
 
 /*
@@ -256,37 +249,23 @@
 	.algo		= &smbus_algorithm,
 };
 
-static struct pci_device_id sch_ids[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, sch_ids);
-
-static int __devinit sch_probe(struct pci_dev *dev,
-				const struct pci_device_id *id)
+static int __devinit smbus_sch_probe(struct platform_device *dev)
 {
+	struct resource *res;
 	int retval;
-	unsigned int smba;
 
-	pci_read_config_dword(dev, SMBBA_SCH, &smba);
-	if (!(smba & (1 << 31))) {
-		dev_err(&dev->dev, "SMBus I/O space disabled!\n");
-		return -ENODEV;
-	}
+	res = platform_get_resource(dev, IORESOURCE_IO, 0);
+	if (!res)
+		return -EBUSY;
 
-	sch_smba = (unsigned short)smba;
-	if (sch_smba == 0) {
-		dev_err(&dev->dev, "SMBus base address uninitialized!\n");
-		return -ENODEV;
-	}
-	if (acpi_check_region(sch_smba, SMBIOSIZE, sch_driver.name))
-		return -ENODEV;
-	if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) {
+	if (!request_region(res->start, resource_size(res), dev->name)) {
 		dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
 			sch_smba);
 		return -EBUSY;
 	}
+
+	sch_smba = res->start;
+
 	dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba);
 
 	/* set up the sysfs linkage to our parent device */
@@ -298,37 +277,43 @@
 	retval = i2c_add_adapter(&sch_adapter);
 	if (retval) {
 		dev_err(&dev->dev, "Couldn't register adapter!\n");
-		release_region(sch_smba, SMBIOSIZE);
+		release_region(res->start, resource_size(res));
 		sch_smba = 0;
 	}
 
 	return retval;
 }
 
-static void __devexit sch_remove(struct pci_dev *dev)
+static int __devexit smbus_sch_remove(struct platform_device *pdev)
 {
+	struct resource *res;
 	if (sch_smba) {
 		i2c_del_adapter(&sch_adapter);
-		release_region(sch_smba, SMBIOSIZE);
+		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+		release_region(res->start, resource_size(res));
 		sch_smba = 0;
 	}
+
+	return 0;
 }
 
-static struct pci_driver sch_driver = {
-	.name		= "isch_smbus",
-	.id_table	= sch_ids,
-	.probe		= sch_probe,
-	.remove		= __devexit_p(sch_remove),
+static struct platform_driver smbus_sch_driver = {
+	.driver = {
+		.name = "isch_smbus",
+		.owner = THIS_MODULE,
+	},
+	.probe		= smbus_sch_probe,
+	.remove		= __devexit_p(smbus_sch_remove),
 };
 
 static int __init i2c_sch_init(void)
 {
-	return pci_register_driver(&sch_driver);
+	return platform_driver_register(&smbus_sch_driver);
 }
 
 static void __exit i2c_sch_exit(void)
 {
-	pci_unregister_driver(&sch_driver);
+	platform_driver_unregister(&smbus_sch_driver);
 }
 
 MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
@@ -337,3 +322,4 @@
 
 module_init(i2c_sch_init);
 module_exit(i2c_sch_exit);
+MODULE_ALIAS("platform:isch_smbus");
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index f627001..78a15af 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -31,6 +31,9 @@
 
 #define DRV_NAME "mpc-i2c"
 
+#define MPC_I2C_CLOCK_LEGACY   0
+#define MPC_I2C_CLOCK_PRESERVE (~0U)
+
 #define MPC_I2C_FDR   0x04
 #define MPC_I2C_CR    0x08
 #define MPC_I2C_SR    0x0c
@@ -66,10 +69,9 @@
 	u16 fdr;	/* including dfsrr */
 };
 
-struct mpc_i2c_match_data {
-	void (*setclock)(struct device_node *node,
-			 struct mpc_i2c *i2c,
-			 u32 clock, u32 prescaler);
+struct mpc_i2c_data {
+	void (*setup)(struct device_node *node, struct mpc_i2c *i2c,
+		      u32 clock, u32 prescaler);
 	u32 prescaler;
 };
 
@@ -164,8 +166,8 @@
 	return 0;
 }
 
-#ifdef CONFIG_PPC_MPC52xx
-static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = {
+#if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x)
+static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = {
 	{20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23},
 	{28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02},
 	{36, 0x26}, {40, 0x27}, {44, 0x04}, {48, 0x28},
@@ -186,14 +188,15 @@
 	{10240, 0x9d}, {12288, 0x9e}, {15360, 0x9f}
 };
 
-int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, int prescaler)
+static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
+					  int prescaler)
 {
 	const struct mpc_i2c_divider *div = NULL;
 	unsigned int pvr = mfspr(SPRN_PVR);
 	u32 divider;
 	int i;
 
-	if (!clock)
+	if (clock == MPC_I2C_CLOCK_LEGACY)
 		return -EINVAL;
 
 	/* Determine divider value */
@@ -215,12 +218,18 @@
 	return div ? (int)div->fdr : -EINVAL;
 }
 
-static void mpc_i2c_setclock_52xx(struct device_node *node,
-				  struct mpc_i2c *i2c,
-				  u32 clock, u32 prescaler)
+static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
+					 struct mpc_i2c *i2c,
+					 u32 clock, u32 prescaler)
 {
 	int ret, fdr;
 
+	if (clock == MPC_I2C_CLOCK_PRESERVE) {
+		dev_dbg(i2c->dev, "using fdr %d\n",
+			readb(i2c->base + MPC_I2C_FDR));
+		return;
+	}
+
 	ret = mpc_i2c_get_fdr_52xx(node, clock, prescaler);
 	fdr = (ret >= 0) ? ret : 0x3f; /* backward compatibility */
 
@@ -229,16 +238,52 @@
 	if (ret >= 0)
 		dev_info(i2c->dev, "clock %d Hz (fdr=%d)\n", clock, fdr);
 }
-#else /* !CONFIG_PPC_MPC52xx */
-static void mpc_i2c_setclock_52xx(struct device_node *node,
-				  struct mpc_i2c *i2c,
-				  u32 clock, u32 prescaler)
+#else /* !(CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x) */
+static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
+					 struct mpc_i2c *i2c,
+					 u32 clock, u32 prescaler)
 {
 }
-#endif /* CONFIG_PPC_MPC52xx*/
+#endif /* CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x */
+
+#ifdef CONFIG_PPC_MPC512x
+static void __devinit mpc_i2c_setup_512x(struct device_node *node,
+					 struct mpc_i2c *i2c,
+					 u32 clock, u32 prescaler)
+{
+	struct device_node *node_ctrl;
+	void __iomem *ctrl;
+	const u32 *pval;
+	u32 idx;
+
+	/* Enable I2C interrupts for mpc5121 */
+	node_ctrl = of_find_compatible_node(NULL, NULL,
+					    "fsl,mpc5121-i2c-ctrl");
+	if (node_ctrl) {
+		ctrl = of_iomap(node_ctrl, 0);
+		if (ctrl) {
+			/* Interrupt enable bits for i2c-0/1/2: bit 24/26/28 */
+			pval = of_get_property(node, "reg", NULL);
+			idx = (*pval & 0xff) / 0x20;
+			setbits32(ctrl, 1 << (24 + idx * 2));
+			iounmap(ctrl);
+		}
+		of_node_put(node_ctrl);
+	}
+
+	/* The clock setup for the 52xx works also fine for the 512x */
+	mpc_i2c_setup_52xx(node, i2c, clock, prescaler);
+}
+#else /* CONFIG_PPC_MPC512x */
+static void __devinit mpc_i2c_setup_512x(struct device_node *node,
+					 struct mpc_i2c *i2c,
+					 u32 clock, u32 prescaler)
+{
+}
+#endif /* CONFIG_PPC_MPC512x */
 
 #ifdef CONFIG_FSL_SOC
-static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
+static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] __devinitconst = {
 	{160, 0x0120}, {192, 0x0121}, {224, 0x0122}, {256, 0x0123},
 	{288, 0x0100}, {320, 0x0101}, {352, 0x0601}, {384, 0x0102},
 	{416, 0x0602}, {448, 0x0126}, {480, 0x0103}, {512, 0x0127},
@@ -258,7 +303,7 @@
 	{49152, 0x011e}, {61440, 0x011f}
 };
 
-u32 mpc_i2c_get_sec_cfg_8xxx(void)
+static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void)
 {
 	struct device_node *node = NULL;
 	u32 __iomem *reg;
@@ -287,13 +332,14 @@
 	return val;
 }
 
-int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, u32 prescaler)
+static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
+					  u32 prescaler)
 {
 	const struct mpc_i2c_divider *div = NULL;
 	u32 divider;
 	int i;
 
-	if (!clock)
+	if (clock == MPC_I2C_CLOCK_LEGACY)
 		return -EINVAL;
 
 	/* Determine proper divider value */
@@ -320,12 +366,19 @@
 	return div ? (int)div->fdr : -EINVAL;
 }
 
-static void mpc_i2c_setclock_8xxx(struct device_node *node,
-				  struct mpc_i2c *i2c,
-				  u32 clock, u32 prescaler)
+static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
+					 struct mpc_i2c *i2c,
+					 u32 clock, u32 prescaler)
 {
 	int ret, fdr;
 
+	if (clock == MPC_I2C_CLOCK_PRESERVE) {
+		dev_dbg(i2c->dev, "using dfsrr %d, fdr %d\n",
+			readb(i2c->base + MPC_I2C_DFSRR),
+			readb(i2c->base + MPC_I2C_FDR));
+		return;
+	}
+
 	ret = mpc_i2c_get_fdr_8xxx(node, clock, prescaler);
 	fdr = (ret >= 0) ? ret : 0x1031; /* backward compatibility */
 
@@ -338,9 +391,9 @@
 }
 
 #else /* !CONFIG_FSL_SOC */
-static void mpc_i2c_setclock_8xxx(struct device_node *node,
-				  struct mpc_i2c *i2c,
-				  u32 clock, u32 prescaler)
+static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
+					 struct mpc_i2c *i2c,
+					 u32 clock, u32 prescaler)
 {
 }
 #endif /* CONFIG_FSL_SOC */
@@ -494,7 +547,7 @@
 {
 	struct mpc_i2c *i2c;
 	const u32 *prop;
-	u32 clock = 0;
+	u32 clock = MPC_I2C_CLOCK_LEGACY;
 	int result = 0;
 	int plen;
 
@@ -523,21 +576,21 @@
 		}
 	}
 
-	if (!of_get_property(op->node, "fsl,preserve-clocking", NULL)) {
+	if (of_get_property(op->node, "fsl,preserve-clocking", NULL)) {
+		clock = MPC_I2C_CLOCK_PRESERVE;
+	} else {
 		prop = of_get_property(op->node, "clock-frequency", &plen);
 		if (prop && plen == sizeof(u32))
 			clock = *prop;
+	}
 
-		if (match->data) {
-			struct mpc_i2c_match_data *data =
-				(struct mpc_i2c_match_data *)match->data;
-			data->setclock(op->node, i2c, clock, data->prescaler);
-		} else {
-			/* Backwards compatibility */
-			if (of_get_property(op->node, "dfsrr", NULL))
-				mpc_i2c_setclock_8xxx(op->node, i2c,
-						      clock, 0);
-		}
+	if (match->data) {
+		struct mpc_i2c_data *data = match->data;
+		data->setup(op->node, i2c, clock, data->prescaler);
+	} else {
+		/* Backwards compatibility */
+		if (of_get_property(op->node, "dfsrr", NULL))
+			mpc_i2c_setup_8xxx(op->node, i2c, clock, 0);
 	}
 
 	dev_set_drvdata(&op->dev, i2c);
@@ -582,47 +635,42 @@
 	return 0;
 };
 
+static struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
+	.setup = mpc_i2c_setup_512x,
+};
+
+static struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = {
+	.setup = mpc_i2c_setup_52xx,
+};
+
+static struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = {
+	.setup = mpc_i2c_setup_8xxx,
+};
+
+static struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = {
+	.setup = mpc_i2c_setup_8xxx,
+	.prescaler = 2,
+};
+
+static struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = {
+	.setup = mpc_i2c_setup_8xxx,
+	.prescaler = 3,
+};
+
 static const struct of_device_id mpc_i2c_of_match[] = {
-	{.compatible = "mpc5200-i2c",
-	 .data = &(struct mpc_i2c_match_data) {
-			.setclock = mpc_i2c_setclock_52xx,
-		},
-	},
-	{.compatible = "fsl,mpc5200b-i2c",
-	 .data = &(struct mpc_i2c_match_data) {
-			.setclock = mpc_i2c_setclock_52xx,
-		},
-	},
-	{.compatible = "fsl,mpc5200-i2c",
-	 .data = &(struct mpc_i2c_match_data) {
-			.setclock = mpc_i2c_setclock_52xx,
-		},
-	},
-	{.compatible = "fsl,mpc8313-i2c",
-	 .data = &(struct mpc_i2c_match_data) {
-			.setclock = mpc_i2c_setclock_8xxx,
-		},
-	},
-	{.compatible = "fsl,mpc8543-i2c",
-	 .data = &(struct mpc_i2c_match_data) {
-			.setclock = mpc_i2c_setclock_8xxx,
-			.prescaler = 2,
-		},
-	},
-	{.compatible = "fsl,mpc8544-i2c",
-	 .data = &(struct mpc_i2c_match_data) {
-			.setclock = mpc_i2c_setclock_8xxx,
-			.prescaler = 3,
-		},
+	{.compatible = "mpc5200-i2c", .data = &mpc_i2c_data_52xx, },
+	{.compatible = "fsl,mpc5200b-i2c", .data = &mpc_i2c_data_52xx, },
+	{.compatible = "fsl,mpc5200-i2c", .data = &mpc_i2c_data_52xx, },
+	{.compatible = "fsl,mpc5121-i2c", .data = &mpc_i2c_data_512x, },
+	{.compatible = "fsl,mpc8313-i2c", .data = &mpc_i2c_data_8313, },
+	{.compatible = "fsl,mpc8543-i2c", .data = &mpc_i2c_data_8543, },
+	{.compatible = "fsl,mpc8544-i2c", .data = &mpc_i2c_data_8544, },
 	/* Backward compatibility */
-	},
 	{.compatible = "fsl-i2c", },
 	{},
 };
-
 MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
 
-
 /* Structure for a device driver */
 static struct of_platform_driver mpc_i2c_driver = {
 	.match_table	= mpc_i2c_of_match,
@@ -655,5 +703,5 @@
 
 MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
 MODULE_DESCRIPTION("I2C-Bus adapter for MPC107 bridge and "
-		   "MPC824x/85xx/52xx processors");
+		   "MPC824x/83xx/85xx/86xx/512x/52xx processors");
 MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index ec11d1c..4a70058 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -308,7 +308,7 @@
 };
 
 
-static struct pci_device_id nforce2_ids[] = {
+static const struct pci_device_id nforce2_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) },
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
new file mode 100644
index 0000000..a15f731
--- /dev/null
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -0,0 +1,959 @@
+/*
+ * Copyright (C) 2009 ST-Ericsson
+ * Copyright (C) 2009 STMicroelectronics
+ *
+ * I2C master mode controller driver, used in Nomadik 8815
+ * and Ux500 platforms.
+ *
+ * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
+ * Author: Sachin Verma <sachin.verma@st.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/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/i2c.h>
+
+#define DRIVER_NAME "nmk-i2c"
+
+/* I2C Controller register offsets */
+#define I2C_CR		(0x000)
+#define I2C_SCR		(0x004)
+#define I2C_HSMCR	(0x008)
+#define I2C_MCR		(0x00C)
+#define I2C_TFR		(0x010)
+#define I2C_SR		(0x014)
+#define I2C_RFR		(0x018)
+#define I2C_TFTR	(0x01C)
+#define I2C_RFTR	(0x020)
+#define I2C_DMAR	(0x024)
+#define I2C_BRCR	(0x028)
+#define I2C_IMSCR	(0x02C)
+#define I2C_RISR	(0x030)
+#define I2C_MISR	(0x034)
+#define I2C_ICR		(0x038)
+
+/* Control registers */
+#define I2C_CR_PE		(0x1 << 0)	/* Peripheral Enable */
+#define I2C_CR_OM		(0x3 << 1)	/* Operating mode */
+#define I2C_CR_SAM		(0x1 << 3)	/* Slave addressing mode */
+#define I2C_CR_SM		(0x3 << 4)	/* Speed mode */
+#define I2C_CR_SGCM		(0x1 << 6)	/* Slave general call mode */
+#define I2C_CR_FTX		(0x1 << 7)	/* Flush Transmit */
+#define I2C_CR_FRX		(0x1 << 8)	/* Flush Receive */
+#define I2C_CR_DMA_TX_EN	(0x1 << 9)	/* DMA Tx enable */
+#define I2C_CR_DMA_RX_EN	(0x1 << 10)	/* DMA Rx Enable */
+#define I2C_CR_DMA_SLE		(0x1 << 11)	/* DMA sync. logic enable */
+#define I2C_CR_LM		(0x1 << 12)	/* Loopback mode */
+#define I2C_CR_FON		(0x3 << 13)	/* Filtering on */
+#define I2C_CR_FS		(0x3 << 15)	/* Force stop enable */
+
+/* Master controller (MCR) register */
+#define I2C_MCR_OP		(0x1 << 0)	/* Operation */
+#define I2C_MCR_A7		(0x7f << 1)	/* 7-bit address */
+#define I2C_MCR_EA10		(0x7 << 8) 	/* 10-bit Extended address */
+#define I2C_MCR_SB		(0x1 << 11)	/* Extended address */
+#define I2C_MCR_AM		(0x3 << 12)	/* Address type */
+#define I2C_MCR_STOP		(0x1 << 14) 	/* Stop condition */
+#define I2C_MCR_LENGTH		(0x7ff << 15) 	/* Transaction length */
+
+/* Status register (SR) */
+#define I2C_SR_OP		(0x3 << 0)	/* Operation */
+#define I2C_SR_STATUS		(0x3 << 2)	/* controller status */
+#define I2C_SR_CAUSE		(0x7 << 4)	/* Abort cause */
+#define I2C_SR_TYPE		(0x3 << 7)	/* Receive type */
+#define I2C_SR_LENGTH		(0x7ff << 9)	/* Transfer length */
+
+/* Interrupt mask set/clear (IMSCR) bits */
+#define I2C_IT_TXFE 		(0x1 << 0)
+#define I2C_IT_TXFNE		(0x1 << 1)
+#define I2C_IT_TXFF		(0x1 << 2)
+#define I2C_IT_TXFOVR		(0x1 << 3)
+#define I2C_IT_RXFE		(0x1 << 4)
+#define I2C_IT_RXFNF		(0x1 << 5)
+#define I2C_IT_RXFF		(0x1 << 6)
+#define I2C_IT_RFSR		(0x1 << 16)
+#define I2C_IT_RFSE		(0x1 << 17)
+#define I2C_IT_WTSR		(0x1 << 18)
+#define I2C_IT_MTD		(0x1 << 19)
+#define I2C_IT_STD		(0x1 << 20)
+#define I2C_IT_MAL		(0x1 << 24)
+#define I2C_IT_BERR		(0x1 << 25)
+#define I2C_IT_MTDWS		(0x1 << 28)
+
+#define GEN_MASK(val, mask, sb)  (((val) << (sb)) & (mask))
+
+/* some bits in ICR are reserved */
+#define I2C_CLEAR_ALL_INTS	0x131f007f
+
+/* first three msb bits are reserved */
+#define IRQ_MASK(mask)		(mask & 0x1fffffff)
+
+/* maximum threshold value */
+#define MAX_I2C_FIFO_THRESHOLD	15
+
+enum i2c_status {
+	I2C_NOP,
+	I2C_ON_GOING,
+	I2C_OK,
+	I2C_ABORT
+};
+
+/* operation */
+enum i2c_operation {
+	I2C_NO_OPERATION = 0xff,
+	I2C_WRITE = 0x00,
+	I2C_READ = 0x01
+};
+
+/* controller response timeout in ms */
+#define I2C_TIMEOUT_MS	500
+
+/**
+ * struct i2c_nmk_client - client specific data
+ * @slave_adr: 7-bit slave address
+ * @count: no. bytes to be transfered
+ * @buffer: client data buffer
+ * @xfer_bytes: bytes transfered till now
+ * @operation: current I2C operation
+ */
+struct i2c_nmk_client {
+	unsigned short		slave_adr;
+	unsigned long		count;
+	unsigned char		*buffer;
+	unsigned long		xfer_bytes;
+	enum i2c_operation	operation;
+};
+
+/**
+ * struct nmk_i2c_dev - private data structure of the controller
+ * @pdev: parent platform device
+ * @adap: corresponding I2C adapter
+ * @irq: interrupt line for the controller
+ * @virtbase: virtual io memory area
+ * @clk: hardware i2c block clock
+ * @cfg: machine provided controller configuration
+ * @cli: holder of client specific data
+ * @stop: stop condition
+ * @xfer_complete: acknowledge completion for a I2C message
+ * @result: controller propogated result
+ */
+struct nmk_i2c_dev {
+	struct platform_device		*pdev;
+	struct i2c_adapter 		adap;
+	int 				irq;
+	void __iomem			*virtbase;
+	struct clk			*clk;
+	struct nmk_i2c_controller	cfg;
+	struct i2c_nmk_client		cli;
+	int 				stop;
+	struct completion		xfer_complete;
+	int 				result;
+};
+
+/* controller's abort causes */
+static const char *abort_causes[] = {
+	"no ack received after address transmission",
+	"no ack received during data phase",
+	"ack received after xmission of master code",
+	"master lost arbitration",
+	"slave restarts",
+	"slave reset",
+	"overflow, maxsize is 2047 bytes",
+};
+
+static inline void i2c_set_bit(void __iomem *reg, u32 mask)
+{
+	writel(readl(reg) | mask, reg);
+}
+
+static inline void i2c_clr_bit(void __iomem *reg, u32 mask)
+{
+	writel(readl(reg) & ~mask, reg);
+}
+
+/**
+ * flush_i2c_fifo() - This function flushes the I2C FIFO
+ * @dev: private data of I2C Driver
+ *
+ * This function flushes the I2C Tx and Rx FIFOs. It returns
+ * 0 on successful flushing of FIFO
+ */
+static int flush_i2c_fifo(struct nmk_i2c_dev *dev)
+{
+#define LOOP_ATTEMPTS 10
+	int i;
+	unsigned long timeout;
+
+	/*
+	 * flush the transmit and receive FIFO. The flushing
+	 * operation takes several cycles before to be completed.
+	 * On the completion, the I2C internal logic clears these
+	 * bits, until then no one must access Tx, Rx FIFO and
+	 * should poll on these bits waiting for the completion.
+	 */
+	writel((I2C_CR_FTX | I2C_CR_FRX), dev->virtbase + I2C_CR);
+
+	for (i = 0; i < LOOP_ATTEMPTS; i++) {
+		timeout = jiffies + msecs_to_jiffies(I2C_TIMEOUT_MS);
+
+		while (!time_after(jiffies, timeout)) {
+			if ((readl(dev->virtbase + I2C_CR) &
+				(I2C_CR_FTX | I2C_CR_FRX)) == 0)
+					return 0;
+		}
+	}
+
+	dev_err(&dev->pdev->dev, "flushing operation timed out "
+		"giving up after %d attempts", LOOP_ATTEMPTS);
+
+	return -ETIMEDOUT;
+}
+
+/**
+ * disable_all_interrupts() - Disable all interrupts of this I2c Bus
+ * @dev: private data of I2C Driver
+ */
+static void disable_all_interrupts(struct nmk_i2c_dev *dev)
+{
+	u32 mask = IRQ_MASK(0);
+	writel(mask, dev->virtbase + I2C_IMSCR);
+}
+
+/**
+ * clear_all_interrupts() - Clear all interrupts of I2C Controller
+ * @dev: private data of I2C Driver
+ */
+static void clear_all_interrupts(struct nmk_i2c_dev *dev)
+{
+	u32 mask;
+	mask = IRQ_MASK(I2C_CLEAR_ALL_INTS);
+	writel(mask, dev->virtbase + I2C_ICR);
+}
+
+/**
+ * init_hw() - initialize the I2C hardware
+ * @dev: private data of I2C Driver
+ */
+static int init_hw(struct nmk_i2c_dev *dev)
+{
+	int stat;
+
+	stat = flush_i2c_fifo(dev);
+	if (stat)
+		return stat;
+
+	/* disable the controller */
+	i2c_clr_bit(dev->virtbase + I2C_CR , I2C_CR_PE);
+
+	disable_all_interrupts(dev);
+
+	clear_all_interrupts(dev);
+
+	dev->cli.operation = I2C_NO_OPERATION;
+
+	return 0;
+}
+
+/* enable peripheral, master mode operation */
+#define DEFAULT_I2C_REG_CR 	((1 << 1) | I2C_CR_PE)
+
+/**
+ * load_i2c_mcr_reg() - load the MCR register
+ * @dev: private data of controller
+ */
+static u32 load_i2c_mcr_reg(struct nmk_i2c_dev *dev)
+{
+	u32 mcr = 0;
+
+	/* 7-bit address transaction */
+	mcr |= GEN_MASK(1, I2C_MCR_AM, 12);
+	mcr |= GEN_MASK(dev->cli.slave_adr, I2C_MCR_A7, 1);
+
+	/* start byte procedure not applied */
+	mcr |= GEN_MASK(0, I2C_MCR_SB, 11);
+
+	/* check the operation, master read/write? */
+	if (dev->cli.operation == I2C_WRITE)
+		mcr |= GEN_MASK(I2C_WRITE, I2C_MCR_OP, 0);
+	else
+		mcr |= GEN_MASK(I2C_READ, I2C_MCR_OP, 0);
+
+	/* stop or repeated start? */
+	if (dev->stop)
+		mcr |= GEN_MASK(1, I2C_MCR_STOP, 14);
+	else
+		mcr &= ~(GEN_MASK(1, I2C_MCR_STOP, 14));
+
+	mcr |= GEN_MASK(dev->cli.count, I2C_MCR_LENGTH, 15);
+
+	return mcr;
+}
+
+/**
+ * setup_i2c_controller() - setup the controller
+ * @dev: private data of controller
+ */
+static void setup_i2c_controller(struct nmk_i2c_dev *dev)
+{
+	u32 brcr1, brcr2;
+	u32 i2c_clk, div;
+
+	writel(0x0, dev->virtbase + I2C_CR);
+	writel(0x0, dev->virtbase + I2C_HSMCR);
+	writel(0x0, dev->virtbase + I2C_TFTR);
+	writel(0x0, dev->virtbase + I2C_RFTR);
+	writel(0x0, dev->virtbase + I2C_DMAR);
+
+	/*
+	 * set the slsu:
+	 *
+	 * slsu defines the data setup time after SCL clock
+	 * stretching in terms of i2c clk cycles. The
+	 * needed setup time for the three modes are 250ns,
+	 * 100ns, 10ns repectively thus leading to the values
+	 * of 14, 6, 2 for a 48 MHz i2c clk.
+	 */
+	writel(dev->cfg.slsu << 16, dev->virtbase + I2C_SCR);
+
+	i2c_clk = clk_get_rate(dev->clk);
+
+	/* fallback to std. mode if machine has not provided it */
+	if (dev->cfg.clk_freq == 0)
+		dev->cfg.clk_freq = 100000;
+
+	/*
+	 * The spec says, in case of std. mode the divider is
+	 * 2 whereas it is 3 for fast and fastplus mode of
+	 * operation. TODO - high speed support.
+	 */
+	div = (dev->cfg.clk_freq > 100000) ? 3 : 2;
+
+	/*
+	 * generate the mask for baud rate counters. The controller
+	 * has two baud rate counters. One is used for High speed
+	 * operation, and the other is for std, fast mode, fast mode
+	 * plus operation. Currently we do not supprt high speed mode
+	 * so set brcr1 to 0.
+	 */
+	brcr1 = 0 << 16;
+	brcr2 = (i2c_clk/(dev->cfg.clk_freq * div)) & 0xffff;
+
+	/* set the baud rate counter register */
+	writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
+
+	/*
+	 * set the speed mode. Currently we support
+	 * only standard and fast mode of operation
+	 * TODO - support for fast mode plus (upto 1Mb/s)
+	 * and high speed (up to 3.4 Mb/s)
+	 */
+	if (dev->cfg.sm > I2C_FREQ_MODE_FAST) {
+		dev_err(&dev->pdev->dev, "do not support this mode "
+			"defaulting to std. mode\n");
+		brcr2 = i2c_clk/(100000 * 2) & 0xffff;
+		writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
+		writel(I2C_FREQ_MODE_STANDARD << 4,
+				dev->virtbase + I2C_CR);
+	}
+	writel(dev->cfg.sm << 4, dev->virtbase + I2C_CR);
+
+	/* set the Tx and Rx FIFO threshold */
+	writel(dev->cfg.tft, dev->virtbase + I2C_TFTR);
+	writel(dev->cfg.rft, dev->virtbase + I2C_RFTR);
+}
+
+/**
+ * read_i2c() - Read from I2C client device
+ * @dev: private data of I2C Driver
+ *
+ * This function reads from i2c client device when controller is in
+ * master mode. There is a completion timeout. If there is no transfer
+ * before timeout error is returned.
+ */
+static int read_i2c(struct nmk_i2c_dev *dev)
+{
+	u32 status = 0;
+	u32 mcr;
+	u32 irq_mask = 0;
+	int timeout;
+
+	mcr = load_i2c_mcr_reg(dev);
+	writel(mcr, dev->virtbase + I2C_MCR);
+
+	/* load the current CR value */
+	writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR,
+			dev->virtbase + I2C_CR);
+
+	/* enable the controller */
+	i2c_set_bit(dev->virtbase + I2C_CR, I2C_CR_PE);
+
+	init_completion(&dev->xfer_complete);
+
+	/* enable interrupts by setting the mask */
+	irq_mask = (I2C_IT_RXFNF | I2C_IT_RXFF |
+			I2C_IT_MAL | I2C_IT_BERR);
+
+	if (dev->stop)
+		irq_mask |= I2C_IT_MTD;
+	else
+		irq_mask |= I2C_IT_MTDWS;
+
+	irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask);
+
+	writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask,
+			dev->virtbase + I2C_IMSCR);
+
+	timeout = wait_for_completion_interruptible_timeout(
+		&dev->xfer_complete, msecs_to_jiffies(I2C_TIMEOUT_MS));
+
+	if (timeout < 0) {
+		dev_err(&dev->pdev->dev,
+			"wait_for_completion_interruptible_timeout"
+			"returned %d waiting for event\n", timeout);
+		status = timeout;
+	}
+
+	if (timeout == 0) {
+		/* controler has timedout, re-init the h/w */
+		dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n");
+		(void) init_hw(dev);
+		status = -ETIMEDOUT;
+	}
+
+	return status;
+}
+
+/**
+ * write_i2c() - Write data to I2C client.
+ * @dev: private data of I2C Driver
+ *
+ * This function writes data to I2C client
+ */
+static int write_i2c(struct nmk_i2c_dev *dev)
+{
+	u32 status = 0;
+	u32 mcr;
+	u32 irq_mask = 0;
+	int timeout;
+
+	mcr = load_i2c_mcr_reg(dev);
+
+	writel(mcr, dev->virtbase + I2C_MCR);
+
+	/* load the current CR value */
+	writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR,
+			dev->virtbase + I2C_CR);
+
+	/* enable the controller */
+	i2c_set_bit(dev->virtbase + I2C_CR , I2C_CR_PE);
+
+	init_completion(&dev->xfer_complete);
+
+	/* enable interrupts by settings the masks */
+	irq_mask = (I2C_IT_TXFNE | I2C_IT_TXFOVR |
+			I2C_IT_MAL | I2C_IT_BERR);
+
+	/*
+	 * check if we want to transfer a single or multiple bytes, if so
+	 * set the MTDWS bit (Master Transaction Done Without Stop)
+	 * to start repeated start operation
+	 */
+	if (dev->stop)
+		irq_mask |= I2C_IT_MTD;
+	else
+		irq_mask |= I2C_IT_MTDWS;
+
+	irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask);
+
+	writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask,
+			dev->virtbase + I2C_IMSCR);
+
+	timeout = wait_for_completion_interruptible_timeout(
+		&dev->xfer_complete, msecs_to_jiffies(I2C_TIMEOUT_MS));
+
+	if (timeout < 0) {
+		dev_err(&dev->pdev->dev,
+			"wait_for_completion_interruptible_timeout"
+			"returned %d waiting for event\n", timeout);
+		status = timeout;
+	}
+
+	if (timeout == 0) {
+		/* controler has timedout, re-init the h/w */
+		dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n");
+		(void) init_hw(dev);
+		status = -ETIMEDOUT;
+	}
+
+	return status;
+}
+
+/**
+ * nmk_i2c_xfer() - I2C transfer function used by kernel framework
+ * @i2c_adap 	- Adapter pointer to the controller
+ * @msgs[] - Pointer to data to be written.
+ * @num_msgs - Number of messages to be executed
+ *
+ * This is the function called by the generic kernel i2c_transfer()
+ * or i2c_smbus...() API calls. Note that this code is protected by the
+ * semaphore set in the kernel i2c_transfer() function.
+ *
+ * NOTE:
+ * READ TRANSFER : We impose a restriction of the first message to be the
+ * 		index message for any read transaction.
+ * 		- a no index is coded as '0',
+ * 		- 2byte big endian index is coded as '3'
+ * 		!!! msg[0].buf holds the actual index.
+ * 		This is compatible with generic messages of smbus emulator
+ * 		that send a one byte index.
+ * 		eg. a I2C transation to read 2 bytes from index 0
+ *			idx = 0;
+ *			msg[0].addr = client->addr;
+ *			msg[0].flags = 0x0;
+ *			msg[0].len = 1;
+ *			msg[0].buf = &idx;
+ *
+ *			msg[1].addr = client->addr;
+ *			msg[1].flags = I2C_M_RD;
+ *			msg[1].len = 2;
+ *			msg[1].buf = rd_buff
+ *			i2c_transfer(adap, msg, 2);
+ *
+ * WRITE TRANSFER : The I2C standard interface interprets all data as payload.
+ *		If you want to emulate an SMBUS write transaction put the
+ *		index as first byte(or first and second) in the payload.
+ *		eg. a I2C transation to write 2 bytes from index 1
+ *			wr_buff[0] = 0x1;
+ *			wr_buff[1] = 0x23;
+ *			wr_buff[2] = 0x46;
+ *			msg[0].flags = 0x0;
+ *			msg[0].len = 3;
+ *			msg[0].buf = wr_buff;
+ *			i2c_transfer(adap, msg, 1);
+ *
+ * To read or write a block of data (multiple bytes) using SMBUS emulation
+ * please use the i2c_smbus_read_i2c_block_data()
+ * or i2c_smbus_write_i2c_block_data() API
+ */
+static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
+		struct i2c_msg msgs[], int num_msgs)
+{
+	int status;
+	int i;
+	u32 cause;
+	struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap);
+
+	status = init_hw(dev);
+	if (status)
+		return status;
+
+	/* setup the i2c controller */
+	setup_i2c_controller(dev);
+
+	for (i = 0; i < num_msgs; i++) {
+		if (unlikely(msgs[i].flags & I2C_M_TEN)) {
+			dev_err(&dev->pdev->dev, "10 bit addressing"
+					"not supported\n");
+			return -EINVAL;
+		}
+		dev->cli.slave_adr	= msgs[i].addr;
+		dev->cli.buffer		= msgs[i].buf;
+		dev->cli.count		= msgs[i].len;
+		dev->stop = (i < (num_msgs - 1)) ? 0 : 1;
+		dev->result = 0;
+
+		if (msgs[i].flags & I2C_M_RD) {
+			/* it is a read operation */
+			dev->cli.operation = I2C_READ;
+			status = read_i2c(dev);
+		} else {
+			/* write operation */
+			dev->cli.operation = I2C_WRITE;
+			status = write_i2c(dev);
+		}
+		if (status || (dev->result)) {
+			/* get the abort cause */
+			cause =	(readl(dev->virtbase + I2C_SR) >> 4) & 0x7;
+			dev_err(&dev->pdev->dev, "error during I2C"
+					"message xfer: %d\n", cause);
+			dev_err(&dev->pdev->dev, "%s\n",
+				cause >= ARRAY_SIZE(abort_causes)
+				? "unknown reason" : abort_causes[cause]);
+			return status;
+		}
+		mdelay(1);
+	}
+	/* return the no. messages processed */
+	if (status)
+		return status;
+	else
+		return num_msgs;
+}
+
+/**
+ * disable_interrupts() - disable the interrupts
+ * @dev: private data of controller
+ */
+static int disable_interrupts(struct nmk_i2c_dev *dev, u32 irq)
+{
+	irq = IRQ_MASK(irq);
+	writel(readl(dev->virtbase + I2C_IMSCR) & ~(I2C_CLEAR_ALL_INTS & irq),
+			dev->virtbase + I2C_IMSCR);
+	return 0;
+}
+
+/**
+ * i2c_irq_handler() - interrupt routine
+ * @irq: interrupt number
+ * @arg: data passed to the handler
+ *
+ * This is the interrupt handler for the i2c driver. Currently
+ * it handles the major interrupts like Rx & Tx FIFO management
+ * interrupts, master transaction interrupts, arbitration and
+ * bus error interrupts. The rest of the interrupts are treated as
+ * unhandled.
+ */
+static irqreturn_t i2c_irq_handler(int irq, void *arg)
+{
+	struct nmk_i2c_dev *dev = arg;
+	u32 tft, rft;
+	u32 count;
+	u32 misr;
+	u32 src = 0;
+
+	/* load Tx FIFO and Rx FIFO threshold values */
+	tft = readl(dev->virtbase + I2C_TFTR);
+	rft = readl(dev->virtbase + I2C_RFTR);
+
+	/* read interrupt status register */
+	misr = readl(dev->virtbase + I2C_MISR);
+
+	src = __ffs(misr);
+	switch ((1 << src)) {
+
+	/* Transmit FIFO nearly empty interrupt */
+	case I2C_IT_TXFNE:
+	{
+		if (dev->cli.operation == I2C_READ) {
+			/*
+			 * in read operation why do we care for writing?
+			 * so disable the Transmit FIFO interrupt
+			 */
+			disable_interrupts(dev, I2C_IT_TXFNE);
+		} else {
+			for (count = (MAX_I2C_FIFO_THRESHOLD - tft - 2);
+					(count > 0) &&
+					(dev->cli.count != 0);
+					count--) {
+				/* write to the Tx FIFO */
+				writeb(*dev->cli.buffer,
+					dev->virtbase + I2C_TFR);
+				dev->cli.buffer++;
+				dev->cli.count--;
+				dev->cli.xfer_bytes++;
+			}
+			/*
+			 * if done, close the transfer by disabling the
+			 * corresponding TXFNE interrupt
+			 */
+			if (dev->cli.count == 0)
+				disable_interrupts(dev,	I2C_IT_TXFNE);
+		}
+	}
+	break;
+
+	/*
+	 * Rx FIFO nearly full interrupt.
+	 * This is set when the numer of entries in Rx FIFO is
+	 * greater or equal than the threshold value programmed
+	 * in RFT
+	 */
+	case I2C_IT_RXFNF:
+		for (count = rft; count > 0; count--) {
+			/* Read the Rx FIFO */
+			*dev->cli.buffer = readb(dev->virtbase + I2C_RFR);
+			dev->cli.buffer++;
+		}
+		dev->cli.count -= rft;
+		dev->cli.xfer_bytes += rft;
+		break;
+
+	/* Rx FIFO full */
+	case I2C_IT_RXFF:
+		for (count = MAX_I2C_FIFO_THRESHOLD; count > 0; count--) {
+			*dev->cli.buffer = readb(dev->virtbase + I2C_RFR);
+			dev->cli.buffer++;
+		}
+		dev->cli.count -= MAX_I2C_FIFO_THRESHOLD;
+		dev->cli.xfer_bytes += MAX_I2C_FIFO_THRESHOLD;
+		break;
+
+	/* Master Transaction Done with/without stop */
+	case I2C_IT_MTD:
+	case I2C_IT_MTDWS:
+		if (dev->cli.operation == I2C_READ) {
+			while (!readl(dev->virtbase + I2C_RISR) & I2C_IT_RXFE) {
+				if (dev->cli.count == 0)
+					break;
+				*dev->cli.buffer =
+					readb(dev->virtbase + I2C_RFR);
+				dev->cli.buffer++;
+				dev->cli.count--;
+				dev->cli.xfer_bytes++;
+			}
+		}
+
+		i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_MTD);
+		i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_MTDWS);
+
+		disable_interrupts(dev,
+				(I2C_IT_TXFNE | I2C_IT_TXFE | I2C_IT_TXFF
+					| I2C_IT_TXFOVR | I2C_IT_RXFNF
+					| I2C_IT_RXFF | I2C_IT_RXFE));
+
+		if (dev->cli.count) {
+			dev->result = -1;
+			dev_err(&dev->pdev->dev, "%lu bytes still remain to be"
+					"xfered\n", dev->cli.count);
+			(void) init_hw(dev);
+		}
+		complete(&dev->xfer_complete);
+
+		break;
+
+	/* Master Arbitration lost interrupt */
+	case I2C_IT_MAL:
+		dev->result = -1;
+		(void) init_hw(dev);
+
+		i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_MAL);
+		complete(&dev->xfer_complete);
+
+		break;
+
+	/*
+	 * Bus Error interrupt.
+	 * This happens when an unexpected start/stop condition occurs
+	 * during the transaction.
+	 */
+	case I2C_IT_BERR:
+		dev->result = -1;
+		/* get the status */
+		if (((readl(dev->virtbase + I2C_SR) >> 2) & 0x3) == I2C_ABORT)
+			(void) init_hw(dev);
+
+		i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_BERR);
+		complete(&dev->xfer_complete);
+
+		break;
+
+	/*
+	 * Tx FIFO overrun interrupt.
+	 * This is set when a write operation in Tx FIFO is performed and
+	 * the Tx FIFO is full.
+	 */
+	case I2C_IT_TXFOVR:
+		dev->result = -1;
+		(void) init_hw(dev);
+
+		dev_err(&dev->pdev->dev, "Tx Fifo Over run\n");
+		complete(&dev->xfer_complete);
+
+		break;
+
+	/* unhandled interrupts by this driver - TODO*/
+	case I2C_IT_TXFE:
+	case I2C_IT_TXFF:
+	case I2C_IT_RXFE:
+	case I2C_IT_RFSR:
+	case I2C_IT_RFSE:
+	case I2C_IT_WTSR:
+	case I2C_IT_STD:
+		dev_err(&dev->pdev->dev, "unhandled Interrupt\n");
+		break;
+	default:
+		dev_err(&dev->pdev->dev, "spurious Interrupt..\n");
+		break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C
+		| I2C_FUNC_SMBUS_BYTE_DATA
+		| I2C_FUNC_SMBUS_WORD_DATA
+		| I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+
+static const struct i2c_algorithm nmk_i2c_algo = {
+	.master_xfer	= nmk_i2c_xfer,
+	.functionality	= nmk_i2c_functionality
+};
+
+static int __devinit nmk_i2c_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct resource *res;
+	struct nmk_i2c_controller *pdata =
+			pdev->dev.platform_data;
+	struct nmk_i2c_dev	*dev;
+	struct i2c_adapter *adap;
+
+	dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		dev_err(&pdev->dev, "cannot allocate memory\n");
+		ret = -ENOMEM;
+		goto err_no_mem;
+	}
+
+	dev->pdev = pdev;
+	platform_set_drvdata(pdev, dev);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENOENT;
+		goto err_no_resource;
+	}
+
+	if (request_mem_region(res->start, resource_size(res),
+		DRIVER_NAME "I/O region") == 	NULL)	{
+		ret = -EBUSY;
+		goto err_no_region;
+	}
+
+	dev->virtbase = ioremap(res->start, resource_size(res));
+	if (!dev->virtbase) {
+		ret = -ENOMEM;
+		goto err_no_ioremap;
+	}
+
+	dev->irq = platform_get_irq(pdev, 0);
+	ret = request_irq(dev->irq, i2c_irq_handler, IRQF_DISABLED,
+				DRIVER_NAME, dev);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot claim the irq %d\n", dev->irq);
+		goto err_irq;
+	}
+
+	dev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk)) {
+		dev_err(&pdev->dev, "could not get i2c clock\n");
+		ret = PTR_ERR(dev->clk);
+		goto err_no_clk;
+	}
+
+	clk_enable(dev->clk);
+
+	adap = &dev->adap;
+	adap->dev.parent = &pdev->dev;
+	adap->owner	= THIS_MODULE;
+	adap->class	= I2C_CLASS_HWMON | I2C_CLASS_SPD;
+	adap->algo	= &nmk_i2c_algo;
+
+	/* fetch the controller id */
+	adap->nr	= pdev->id;
+
+	/* fetch the controller configuration from machine */
+	dev->cfg.clk_freq = pdata->clk_freq;
+	dev->cfg.slsu	= pdata->slsu;
+	dev->cfg.tft	= pdata->tft;
+	dev->cfg.rft	= pdata->rft;
+	dev->cfg.sm	= pdata->sm;
+
+	i2c_set_adapdata(adap, dev);
+
+	ret = init_hw(dev);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "error in initializing i2c hardware\n");
+		goto err_init_hw;
+	}
+
+	dev_dbg(&pdev->dev, "initialize I2C%d bus on virtual "
+		"base %p\n", pdev->id, dev->virtbase);
+
+	ret = i2c_add_numbered_adapter(adap);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add adapter\n");
+		goto err_add_adap;
+	}
+
+	return 0;
+
+ err_init_hw:
+	clk_disable(dev->clk);
+ err_add_adap:
+	clk_put(dev->clk);
+ err_no_clk:
+	free_irq(dev->irq, dev);
+ err_irq:
+	iounmap(dev->virtbase);
+ err_no_ioremap:
+	release_mem_region(res->start, resource_size(res));
+ err_no_region:
+	platform_set_drvdata(pdev, NULL);
+ err_no_resource:
+	kfree(dev);
+ err_no_mem:
+
+	return ret;
+}
+
+static int __devexit nmk_i2c_remove(struct platform_device *pdev)
+{
+	struct nmk_i2c_dev *dev = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&dev->adap);
+	flush_i2c_fifo(dev);
+	disable_all_interrupts(dev);
+	clear_all_interrupts(dev);
+	/* disable the controller */
+	i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE);
+	free_irq(dev->irq, dev);
+	iounmap(dev->virtbase);
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	platform_set_drvdata(pdev, NULL);
+	kfree(dev);
+
+	return 0;
+}
+
+static struct platform_driver nmk_i2c_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = DRIVER_NAME,
+	},
+	.probe = nmk_i2c_probe,
+	.remove = __devexit_p(nmk_i2c_remove),
+};
+
+static int __init nmk_i2c_init(void)
+{
+	return platform_driver_register(&nmk_i2c_driver);
+}
+
+static void __exit nmk_i2c_exit(void)
+{
+	platform_driver_unregister(&nmk_i2c_driver);
+}
+
+subsys_initcall(nmk_i2c_init);
+module_exit(nmk_i2c_exit);
+
+MODULE_AUTHOR("Sachin Verma, Srinidhi KASAGAR");
+MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 0037e31..c7c23753 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -49,24 +49,24 @@
 #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
 
 #define OMAP_I2C_REV_REG		0x00
-#define OMAP_I2C_IE_REG			0x04
-#define OMAP_I2C_STAT_REG		0x08
-#define OMAP_I2C_IV_REG			0x0c
+#define OMAP_I2C_IE_REG			0x01
+#define OMAP_I2C_STAT_REG		0x02
+#define OMAP_I2C_IV_REG			0x03
 /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
-#define OMAP_I2C_WE_REG			0x0c
-#define OMAP_I2C_SYSS_REG		0x10
-#define OMAP_I2C_BUF_REG		0x14
-#define OMAP_I2C_CNT_REG		0x18
-#define OMAP_I2C_DATA_REG		0x1c
-#define OMAP_I2C_SYSC_REG		0x20
-#define OMAP_I2C_CON_REG		0x24
-#define OMAP_I2C_OA_REG			0x28
-#define OMAP_I2C_SA_REG			0x2c
-#define OMAP_I2C_PSC_REG		0x30
-#define OMAP_I2C_SCLL_REG		0x34
-#define OMAP_I2C_SCLH_REG		0x38
-#define OMAP_I2C_SYSTEST_REG		0x3c
-#define OMAP_I2C_BUFSTAT_REG		0x40
+#define OMAP_I2C_WE_REG			0x03
+#define OMAP_I2C_SYSS_REG		0x04
+#define OMAP_I2C_BUF_REG		0x05
+#define OMAP_I2C_CNT_REG		0x06
+#define OMAP_I2C_DATA_REG		0x07
+#define OMAP_I2C_SYSC_REG		0x08
+#define OMAP_I2C_CON_REG		0x09
+#define OMAP_I2C_OA_REG			0x0a
+#define OMAP_I2C_SA_REG			0x0b
+#define OMAP_I2C_PSC_REG		0x0c
+#define OMAP_I2C_SCLL_REG		0x0d
+#define OMAP_I2C_SCLH_REG		0x0e
+#define OMAP_I2C_SYSTEST_REG		0x0f
+#define OMAP_I2C_BUFSTAT_REG		0x10
 
 /* I2C Interrupt Enable Register (OMAP_I2C_IE): */
 #define OMAP_I2C_IE_XDR		(1 << 14)	/* TX Buffer drain int enable */
@@ -161,6 +161,7 @@
 	struct device		*dev;
 	void __iomem		*base;		/* virtual */
 	int			irq;
+	int			reg_shift;      /* bit shift for I2C register addresses */
 	struct clk		*iclk;		/* Interface clock */
 	struct clk		*fclk;		/* Functional clock */
 	struct completion	cmd_complete;
@@ -189,12 +190,12 @@
 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
 				      int reg, u16 val)
 {
-	__raw_writew(val, i2c_dev->base + reg);
+	__raw_writew(val, i2c_dev->base + (reg << i2c_dev->reg_shift));
 }
 
 static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
 {
-	return __raw_readw(i2c_dev->base + reg);
+	return __raw_readw(i2c_dev->base + (reg << i2c_dev->reg_shift));
 }
 
 static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
@@ -849,7 +850,7 @@
 	.functionality	= omap_i2c_func,
 };
 
-static int __init
+static int __devinit
 omap_i2c_probe(struct platform_device *pdev)
 {
 	struct omap_i2c_dev	*dev;
@@ -924,6 +925,11 @@
 		dev->b_hw = 1; /* Enable hardware fixes */
 	}
 
+	if (cpu_is_omap7xx())
+		dev->reg_shift = 1;
+	else
+		dev->reg_shift = 2;
+
 	/* reset ASAP, clearing any IRQs */
 	omap_i2c_init(dev);
 
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index 322c569..5f41ec0 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport-light.c I2C bus over parallel port                           *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org>
    
    Based on older i2c-velleman.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -27,10 +27,12 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/i2c-smbus.h>
 #include <asm/io.h>
 #include "i2c-parport.h"
 
@@ -43,6 +45,10 @@
 module_param(base, ushort, 0);
 MODULE_PARM_DESC(base, "Base I/O address");
 
+static int irq;
+module_param(irq, int, 0);
+MODULE_PARM_DESC(irq, "IRQ (optional)");
+
 /* ----- Low-level parallel port access ----------------------------------- */
 
 static inline void port_write(unsigned char p, unsigned char d)
@@ -119,6 +125,16 @@
 	.name		= "Parallel port adapter (light)",
 };
 
+/* SMBus alert support */
+static struct i2c_smbus_alert_setup alert_data = {
+	.alert_edge_triggered	= 1,
+};
+static struct i2c_client *ara;
+static struct lineop parport_ctrl_irq = {
+	.val		= (1 << 4),
+	.port		= CTRL,
+};
+
 static int __devinit i2c_parport_probe(struct platform_device *pdev)
 {
 	int err;
@@ -127,18 +143,39 @@
 	parport_setsda(NULL, 1);
 	parport_setscl(NULL, 1);
 	/* Other init if needed (power on...) */
-	if (adapter_parm[type].init.val)
+	if (adapter_parm[type].init.val) {
 		line_set(1, &adapter_parm[type].init);
+		/* Give powered devices some time to settle */
+		msleep(100);
+	}
 
 	parport_adapter.dev.parent = &pdev->dev;
 	err = i2c_bit_add_bus(&parport_adapter);
-	if (err)
+	if (err) {
 		dev_err(&pdev->dev, "Unable to register with I2C\n");
-	return err;
+		return err;
+	}
+
+	/* Setup SMBus alert if supported */
+	if (adapter_parm[type].smbus_alert && irq) {
+		alert_data.irq = irq;
+		ara = i2c_setup_smbus_alert(&parport_adapter, &alert_data);
+		if (ara)
+			line_set(1, &parport_ctrl_irq);
+		else
+			dev_warn(&pdev->dev, "Failed to register ARA client\n");
+	}
+
+	return 0;
 }
 
 static int __devexit i2c_parport_remove(struct platform_device *pdev)
 {
+	if (ara) {
+		line_set(0, &parport_ctrl_irq);
+		i2c_unregister_device(ara);
+		ara = NULL;
+	}
 	i2c_del_adapter(&parport_adapter);
 
 	/* Un-init if needed (power off...) */
@@ -205,6 +242,9 @@
 	if (!request_region(base, 3, DRVNAME))
 		return -EBUSY;
 
+	if (irq != 0)
+		pr_info(DRVNAME ": using irq %d\n", irq);
+
         if (!adapter_parm[type].getscl.val)
 		parport_algo_data.getscl = NULL;
 
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 0d89986..220fca7 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport.c I2C bus over parallel port                                 *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org>
    
    Based on older i2c-philips-par.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -27,9 +27,11 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <linux/parport.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/i2c-smbus.h>
 #include "i2c-parport.h"
 
 /* ----- Device list ------------------------------------------------------ */
@@ -38,6 +40,8 @@
 	struct pardevice *pdev;
 	struct i2c_adapter adapter;
 	struct i2c_algo_bit_data algo_data;
+	struct i2c_smbus_alert_setup alert_data;
+	struct i2c_client *ara;
 	struct i2c_par *next;
 };
 
@@ -143,6 +147,19 @@
 
 /* ----- I2c and parallel port call-back functions and structures --------- */
 
+void i2c_parport_irq(void *data)
+{
+	struct i2c_par *adapter = data;
+	struct i2c_client *ara = adapter->ara;
+
+	if (ara) {
+		dev_dbg(&ara->dev, "SMBus alert received\n");
+		i2c_handle_smbus_alert(ara);
+	} else
+		dev_dbg(&adapter->adapter.dev,
+			"SMBus alert received but no ARA client!\n");
+}
+
 static void i2c_parport_attach (struct parport *port)
 {
 	struct i2c_par *adapter;
@@ -154,8 +171,9 @@
 	}
 
 	pr_debug("i2c-parport: attaching to %s\n", port->name);
+	parport_disable_irq(port);
 	adapter->pdev = parport_register_device(port, "i2c-parport",
-		NULL, NULL, NULL, PARPORT_FLAG_EXCL, NULL);
+		NULL, NULL, i2c_parport_irq, PARPORT_FLAG_EXCL, adapter);
 	if (!adapter->pdev) {
 		printk(KERN_ERR "i2c-parport: Unable to register with parport\n");
 		goto ERROR0;
@@ -185,14 +203,29 @@
 	parport_setsda(port, 1);
 	parport_setscl(port, 1);
 	/* Other init if needed (power on...) */
-	if (adapter_parm[type].init.val)
+	if (adapter_parm[type].init.val) {
 		line_set(port, 1, &adapter_parm[type].init);
+		/* Give powered devices some time to settle */
+		msleep(100);
+	}
 
 	if (i2c_bit_add_bus(&adapter->adapter) < 0) {
 		printk(KERN_ERR "i2c-parport: Unable to register with I2C\n");
 		goto ERROR1;
 	}
 
+	/* Setup SMBus alert if supported */
+	if (adapter_parm[type].smbus_alert) {
+		adapter->alert_data.alert_edge_triggered = 1;
+		adapter->ara = i2c_setup_smbus_alert(&adapter->adapter,
+						     &adapter->alert_data);
+		if (adapter->ara)
+			parport_enable_irq(port);
+		else
+			printk(KERN_WARNING "i2c-parport: Failed to register "
+			       "ARA client\n");
+	}
+
 	/* Add the new adapter to the list */
 	adapter->next = adapter_list;
 	adapter_list = adapter;
@@ -213,6 +246,10 @@
 	for (prev = NULL, adapter = adapter_list; adapter;
 	     prev = adapter, adapter = adapter->next) {
 		if (adapter->pdev->port == port) {
+			if (adapter->ara) {
+				parport_disable_irq(port);
+				i2c_unregister_device(adapter->ara);
+			}
 			i2c_del_adapter(&adapter->adapter);
 
 			/* Un-init if needed (power off...) */
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
index ed69d84..a9f6681 100644
--- a/drivers/i2c/busses/i2c-parport.h
+++ b/drivers/i2c/busses/i2c-parport.h
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport.h I2C bus over parallel port                                 *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.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
@@ -38,6 +38,7 @@
 	struct lineop getsda;
 	struct lineop getscl;
 	struct lineop init;
+	unsigned int smbus_alert:1;
 };
 
 static struct adapter_parm adapter_parm[] = {
@@ -73,6 +74,7 @@
 		.setscl	= { 0x01, DATA, 1 },
 		.getsda	= { 0x10, STAT, 1 },
 		.init	= { 0xf0, DATA, 0 },
+		.smbus_alert = 1,
 	},
 	/* type 5: ADM1025, ADM1030 and ADM1031 evaluation boards */
 	{
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index adf0fbb..0d20ff4 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -400,7 +400,7 @@
 	kfree(smbus);
 }
 
-static struct pci_device_id pasemi_smb_ids[] = {
+static const struct pci_device_id pasemi_smb_ids[] = {
 	{ PCI_DEVICE(0x1959, 0xa003) },
 	{ 0, }
 };
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index e56e4b6..ee9da6f 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -472,7 +472,7 @@
 	.algo		= &smbus_algorithm,
 };
 
-static struct pci_device_id piix4_ids[] = {
+static const struct pci_device_id piix4_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3) },
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index 2b0bd0b..9532dee 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -172,12 +172,6 @@
 		/* We still have something to talk about... */
 		val = *alg_data->mif.buf++;
 
-		if (alg_data->mif.len == 1) {
-			val |= stop_bit;
-			if (!alg_data->last)
-				val |= start_bit;
-		}
-
 		alg_data->mif.len--;
 		iowrite32(val, I2C_REG_TX(alg_data));
 
@@ -251,11 +245,6 @@
 			__func__);
 
 		if (alg_data->mif.len == 1) {
-			/* Last byte, do not acknowledge next rcv. */
-			val |= stop_bit;
-			if (!alg_data->last)
-				val |= start_bit;
-
 			/*
 			 * Enable interrupt RFDAIE (data in Rx fifo),
 			 * and disable DRMIE (need data for Tx)
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 7647a20..90ffbf6 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -12,7 +12,7 @@
  *
  *  History:
  *    Apr 2002: Initial version [CS]
- *    Jun 2002: Properly seperated algo/adap [FB]
+ *    Jun 2002: Properly separated algo/adap [FB]
  *    Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem]
  *    Jan 2003: added limited signal handling [Kai-Uwe Bloem]
  *    Sep 2004: Major rework to ensure efficient bus handling [RMK]
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 844569f..55a7137 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -369,7 +369,7 @@
 	.algo		= &smbus_algorithm,
 };
 
-static struct pci_device_id sis5595_ids[] __devinitdata = {
+static const struct pci_device_id sis5595_ids[] __devinitconst = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, 
 	{ 0, }
 };
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index 68cff7a..2309c7f 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -468,7 +468,7 @@
 	.algo		= &smbus_algorithm,
 };
 
-static struct pci_device_id sis630_ids[] __devinitdata = {
+static const struct pci_device_id sis630_ids[] __devinitconst = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
 	{ 0, }
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 1649963..d43d8f8 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -245,7 +245,7 @@
 	.algo		= &smbus_algorithm,
 };
 
-static struct pci_device_id sis96x_ids[] = {
+static const struct pci_device_id sis96x_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) },
 	{ 0, }
 };
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c
index e29b6d5..b5b1bbf 100644
--- a/drivers/i2c/busses/i2c-tiny-usb.c
+++ b/drivers/i2c/busses/i2c-tiny-usb.c
@@ -31,11 +31,13 @@
 #define CMD_I2C_IO_BEGIN	(1<<0)
 #define CMD_I2C_IO_END		(1<<1)
 
-/* i2c bit delay, default is 10us -> 100kHz */
+/* i2c bit delay, default is 10us -> 100kHz max
+   (in practice, due to additional delays in the i2c bitbanging
+   code this results in a i2c clock of about 50kHz) */
 static unsigned short delay = 10;
 module_param(delay, ushort, 0);
-MODULE_PARM_DESC(delay, "bit delay in microseconds, "
-		 "e.g. 10 for 100kHz (default is 100kHz)");
+MODULE_PARM_DESC(delay, "bit delay in microseconds "
+		 "(default is 10us for 100kHz max)");
 
 static int usb_read(struct i2c_adapter *adapter, int cmd,
 		    int value, int index, void *data, int len);
@@ -137,7 +139,7 @@
  * Future Technology Devices International Ltd., later a pair was
  * bought from EZPrototypes
  */
-static struct usb_device_id i2c_tiny_usb_table [] = {
+static const struct usb_device_id i2c_tiny_usb_table[] = {
 	{ USB_DEVICE(0x0403, 0xc631) },   /* FTDI */
 	{ USB_DEVICE(0x1c40, 0x0534) },   /* EZPrototypes */
 	{ }                               /* Terminating entry */
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 8b24f19..de78283 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -89,7 +89,7 @@
 };
 
 
-static struct pci_device_id vt586b_ids[] __devinitdata = {
+static const struct pci_device_id vt586b_ids[] __devinitconst = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3) },
 	{ 0, }
 };
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index a84a909..d57292e 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -444,7 +444,7 @@
 	return error;
 }
 
-static struct pci_device_id vt596_ids[] = {
+static const struct pci_device_id vt596_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3),
 	  .driver_data = SMBBA1 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3),
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
new file mode 100644
index 0000000..eece39a
--- /dev/null
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -0,0 +1,824 @@
+/*
+ * i2c-xiic.c
+ * Copyright (c) 2002-2007 Xilinx Inc.
+ * 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.
+ *
+ *
+ * This code was implemented by Mocean Laboratories AB when porting linux
+ * to the automotive development board Russellville. The copyright holder
+ * as seen in the header is Intel corporation.
+ * Mocean Laboratories forked off the GNU/Linux platform work into a
+ * separate company called Pelagicore AB, which commited the code to the
+ * kernel.
+ */
+
+/* Supports:
+ * Xilinx IIC
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/i2c-xiic.h>
+#include <linux/io.h>
+
+#define DRIVER_NAME "xiic-i2c"
+
+enum xilinx_i2c_state {
+	STATE_DONE,
+	STATE_ERROR,
+	STATE_START
+};
+
+/**
+ * struct xiic_i2c - Internal representation of the XIIC I2C bus
+ * @base:	Memory base of the HW registers
+ * @wait:	Wait queue for callers
+ * @adap:	Kernel adapter representation
+ * @tx_msg:	Messages from above to be sent
+ * @lock:	Mutual exclusion
+ * @tx_pos:	Current pos in TX message
+ * @nmsgs:	Number of messages in tx_msg
+ * @state:	See STATE_
+ * @rx_msg:	Current RX message
+ * @rx_pos:	Position within current RX message
+ */
+struct xiic_i2c {
+	void __iomem		*base;
+	wait_queue_head_t	wait;
+	struct i2c_adapter	adap;
+	struct i2c_msg		*tx_msg;
+	spinlock_t		lock;
+	unsigned int 		tx_pos;
+	unsigned int		nmsgs;
+	enum xilinx_i2c_state	state;
+	struct i2c_msg		*rx_msg;
+	int			rx_pos;
+};
+
+
+#define XIIC_MSB_OFFSET 0
+#define XIIC_REG_OFFSET (0x100+XIIC_MSB_OFFSET)
+
+/*
+ * Register offsets in bytes from RegisterBase. Three is added to the
+ * base offset to access LSB (IBM style) of the word
+ */
+#define XIIC_CR_REG_OFFSET   (0x00+XIIC_REG_OFFSET)	/* Control Register   */
+#define XIIC_SR_REG_OFFSET   (0x04+XIIC_REG_OFFSET)	/* Status Register    */
+#define XIIC_DTR_REG_OFFSET  (0x08+XIIC_REG_OFFSET)	/* Data Tx Register   */
+#define XIIC_DRR_REG_OFFSET  (0x0C+XIIC_REG_OFFSET)	/* Data Rx Register   */
+#define XIIC_ADR_REG_OFFSET  (0x10+XIIC_REG_OFFSET)	/* Address Register   */
+#define XIIC_TFO_REG_OFFSET  (0x14+XIIC_REG_OFFSET)	/* Tx FIFO Occupancy  */
+#define XIIC_RFO_REG_OFFSET  (0x18+XIIC_REG_OFFSET)	/* Rx FIFO Occupancy  */
+#define XIIC_TBA_REG_OFFSET  (0x1C+XIIC_REG_OFFSET)	/* 10 Bit Address reg */
+#define XIIC_RFD_REG_OFFSET  (0x20+XIIC_REG_OFFSET)	/* Rx FIFO Depth reg  */
+#define XIIC_GPO_REG_OFFSET  (0x24+XIIC_REG_OFFSET)	/* Output Register    */
+
+/* Control Register masks */
+#define XIIC_CR_ENABLE_DEVICE_MASK        0x01	/* Device enable = 1      */
+#define XIIC_CR_TX_FIFO_RESET_MASK        0x02	/* Transmit FIFO reset=1  */
+#define XIIC_CR_MSMS_MASK                 0x04	/* Master starts Txing=1  */
+#define XIIC_CR_DIR_IS_TX_MASK            0x08	/* Dir of tx. Txing=1     */
+#define XIIC_CR_NO_ACK_MASK               0x10	/* Tx Ack. NO ack = 1     */
+#define XIIC_CR_REPEATED_START_MASK       0x20	/* Repeated start = 1     */
+#define XIIC_CR_GENERAL_CALL_MASK         0x40	/* Gen Call enabled = 1   */
+
+/* Status Register masks */
+#define XIIC_SR_GEN_CALL_MASK             0x01	/* 1=a mstr issued a GC   */
+#define XIIC_SR_ADDR_AS_SLAVE_MASK        0x02	/* 1=when addr as slave   */
+#define XIIC_SR_BUS_BUSY_MASK             0x04	/* 1 = bus is busy        */
+#define XIIC_SR_MSTR_RDING_SLAVE_MASK     0x08	/* 1=Dir: mstr <-- slave  */
+#define XIIC_SR_TX_FIFO_FULL_MASK         0x10	/* 1 = Tx FIFO full       */
+#define XIIC_SR_RX_FIFO_FULL_MASK         0x20	/* 1 = Rx FIFO full       */
+#define XIIC_SR_RX_FIFO_EMPTY_MASK        0x40	/* 1 = Rx FIFO empty      */
+#define XIIC_SR_TX_FIFO_EMPTY_MASK        0x80	/* 1 = Tx FIFO empty      */
+
+/* Interrupt Status Register masks    Interrupt occurs when...       */
+#define XIIC_INTR_ARB_LOST_MASK           0x01	/* 1 = arbitration lost   */
+#define XIIC_INTR_TX_ERROR_MASK           0x02	/* 1=Tx error/msg complete */
+#define XIIC_INTR_TX_EMPTY_MASK           0x04	/* 1 = Tx FIFO/reg empty  */
+#define XIIC_INTR_RX_FULL_MASK            0x08	/* 1=Rx FIFO/reg=OCY level */
+#define XIIC_INTR_BNB_MASK                0x10	/* 1 = Bus not busy       */
+#define XIIC_INTR_AAS_MASK                0x20	/* 1 = when addr as slave */
+#define XIIC_INTR_NAAS_MASK               0x40	/* 1 = not addr as slave  */
+#define XIIC_INTR_TX_HALF_MASK            0x80	/* 1 = TX FIFO half empty */
+
+/* The following constants specify the depth of the FIFOs */
+#define IIC_RX_FIFO_DEPTH         16	/* Rx fifo capacity               */
+#define IIC_TX_FIFO_DEPTH         16	/* Tx fifo capacity               */
+
+/* The following constants specify groups of interrupts that are typically
+ * enabled or disables at the same time
+ */
+#define XIIC_TX_INTERRUPTS                           \
+(XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)
+
+#define XIIC_TX_RX_INTERRUPTS (XIIC_INTR_RX_FULL_MASK | XIIC_TX_INTERRUPTS)
+
+/* The following constants are used with the following macros to specify the
+ * operation, a read or write operation.
+ */
+#define XIIC_READ_OPERATION  1
+#define XIIC_WRITE_OPERATION 0
+
+/*
+ * Tx Fifo upper bit masks.
+ */
+#define XIIC_TX_DYN_START_MASK            0x0100 /* 1 = Set dynamic start */
+#define XIIC_TX_DYN_STOP_MASK             0x0200 /* 1 = Set dynamic stop */
+
+/*
+ * The following constants define the register offsets for the Interrupt
+ * registers. There are some holes in the memory map for reserved addresses
+ * to allow other registers to be added and still match the memory map of the
+ * interrupt controller registers
+ */
+#define XIIC_DGIER_OFFSET    0x1C /* Device Global Interrupt Enable Register */
+#define XIIC_IISR_OFFSET     0x20 /* Interrupt Status Register */
+#define XIIC_IIER_OFFSET     0x28 /* Interrupt Enable Register */
+#define XIIC_RESETR_OFFSET   0x40 /* Reset Register */
+
+#define XIIC_RESET_MASK             0xAUL
+
+/*
+ * The following constant is used for the device global interrupt enable
+ * register, to enable all interrupts for the device, this is the only bit
+ * in the register
+ */
+#define XIIC_GINTR_ENABLE_MASK      0x80000000UL
+
+#define xiic_tx_space(i2c) ((i2c)->tx_msg->len - (i2c)->tx_pos)
+#define xiic_rx_space(i2c) ((i2c)->rx_msg->len - (i2c)->rx_pos)
+
+static void xiic_start_xfer(struct xiic_i2c *i2c);
+static void __xiic_start_xfer(struct xiic_i2c *i2c);
+
+static inline void xiic_setreg8(struct xiic_i2c *i2c, int reg, u8 value)
+{
+	iowrite8(value, i2c->base + reg);
+}
+
+static inline u8 xiic_getreg8(struct xiic_i2c *i2c, int reg)
+{
+	return ioread8(i2c->base + reg);
+}
+
+static inline void xiic_setreg16(struct xiic_i2c *i2c, int reg, u16 value)
+{
+	iowrite16(value, i2c->base + reg);
+}
+
+static inline void xiic_setreg32(struct xiic_i2c *i2c, int reg, int value)
+{
+	iowrite32(value, i2c->base + reg);
+}
+
+static inline int xiic_getreg32(struct xiic_i2c *i2c, int reg)
+{
+	return ioread32(i2c->base + reg);
+}
+
+static inline void xiic_irq_dis(struct xiic_i2c *i2c, u32 mask)
+{
+	u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
+	xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier & ~mask);
+}
+
+static inline void xiic_irq_en(struct xiic_i2c *i2c, u32 mask)
+{
+	u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
+	xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier | mask);
+}
+
+static inline void xiic_irq_clr(struct xiic_i2c *i2c, u32 mask)
+{
+	u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET);
+	xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask);
+}
+
+static inline void xiic_irq_clr_en(struct xiic_i2c *i2c, u32 mask)
+{
+	xiic_irq_clr(i2c, mask);
+	xiic_irq_en(i2c, mask);
+}
+
+static void xiic_clear_rx_fifo(struct xiic_i2c *i2c)
+{
+	u8 sr;
+	for (sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET);
+		!(sr & XIIC_SR_RX_FIFO_EMPTY_MASK);
+		sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET))
+		xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
+}
+
+static void xiic_reinit(struct xiic_i2c *i2c)
+{
+	xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK);
+
+	/* Set receive Fifo depth to maximum (zero based). */
+	xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1);
+
+	/* Reset Tx Fifo. */
+	xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK);
+
+	/* Enable IIC Device, remove Tx Fifo reset & disable general call. */
+	xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK);
+
+	/* make sure RX fifo is empty */
+	xiic_clear_rx_fifo(i2c);
+
+	/* Enable interrupts */
+	xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
+
+	xiic_irq_clr_en(i2c, XIIC_INTR_AAS_MASK | XIIC_INTR_ARB_LOST_MASK);
+}
+
+static void xiic_deinit(struct xiic_i2c *i2c)
+{
+	u8 cr;
+
+	xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK);
+
+	/* Disable IIC Device. */
+	cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+	xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK);
+}
+
+static void xiic_read_rx(struct xiic_i2c *i2c)
+{
+	u8 bytes_in_fifo;
+	int i;
+
+	bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1;
+
+	dev_dbg(i2c->adap.dev.parent, "%s entry, bytes in fifo: %d, msg: %d"
+		", SR: 0x%x, CR: 0x%x\n",
+		__func__, bytes_in_fifo, xiic_rx_space(i2c),
+		xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
+		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
+
+	if (bytes_in_fifo > xiic_rx_space(i2c))
+		bytes_in_fifo = xiic_rx_space(i2c);
+
+	for (i = 0; i < bytes_in_fifo; i++)
+		i2c->rx_msg->buf[i2c->rx_pos++] =
+			xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
+
+	xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET,
+		(xiic_rx_space(i2c) > IIC_RX_FIFO_DEPTH) ?
+		IIC_RX_FIFO_DEPTH - 1 :  xiic_rx_space(i2c) - 1);
+}
+
+static int xiic_tx_fifo_space(struct xiic_i2c *i2c)
+{
+	/* return the actual space left in the FIFO */
+	return IIC_TX_FIFO_DEPTH - xiic_getreg8(i2c, XIIC_TFO_REG_OFFSET) - 1;
+}
+
+static void xiic_fill_tx_fifo(struct xiic_i2c *i2c)
+{
+	u8 fifo_space = xiic_tx_fifo_space(i2c);
+	int len = xiic_tx_space(i2c);
+
+	len = (len > fifo_space) ? fifo_space : len;
+
+	dev_dbg(i2c->adap.dev.parent, "%s entry, len: %d, fifo space: %d\n",
+		__func__, len, fifo_space);
+
+	while (len--) {
+		u16 data = i2c->tx_msg->buf[i2c->tx_pos++];
+		if ((xiic_tx_space(i2c) == 0) && (i2c->nmsgs == 1)) {
+			/* last message in transfer -> STOP */
+			data |= XIIC_TX_DYN_STOP_MASK;
+			dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__);
+
+			xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
+		} else
+			xiic_setreg8(i2c, XIIC_DTR_REG_OFFSET, data);
+	}
+}
+
+static void xiic_wakeup(struct xiic_i2c *i2c, int code)
+{
+	i2c->tx_msg = NULL;
+	i2c->rx_msg = NULL;
+	i2c->nmsgs = 0;
+	i2c->state = code;
+	wake_up(&i2c->wait);
+}
+
+static void xiic_process(struct xiic_i2c *i2c)
+{
+	u32 pend, isr, ier;
+	u32 clr = 0;
+
+	/* Get the interrupt Status from the IPIF. There is no clearing of
+	 * interrupts in the IPIF. Interrupts must be cleared at the source.
+	 * To find which interrupts are pending; AND interrupts pending with
+	 * interrupts masked.
+	 */
+	isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET);
+	ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
+	pend = isr & ier;
+
+	dev_dbg(i2c->adap.dev.parent, "%s entry, IER: 0x%x, ISR: 0x%x, "
+		"pend: 0x%x, SR: 0x%x, msg: %p, nmsgs: %d\n",
+		__func__, ier, isr, pend, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
+		i2c->tx_msg, i2c->nmsgs);
+
+	/* Do not processes a devices interrupts if the device has no
+	 * interrupts pending
+	 */
+	if (!pend)
+		return;
+
+	/* Service requesting interrupt */
+	if ((pend & XIIC_INTR_ARB_LOST_MASK) ||
+		((pend & XIIC_INTR_TX_ERROR_MASK) &&
+		!(pend & XIIC_INTR_RX_FULL_MASK))) {
+		/* bus arbritration lost, or...
+		 * Transmit error _OR_ RX completed
+		 * if this happens when RX_FULL is not set
+		 * this is probably a TX error
+		 */
+
+		dev_dbg(i2c->adap.dev.parent, "%s error\n", __func__);
+
+		/* dynamic mode seem to suffer from problems if we just flushes
+		 * fifos and the next message is a TX with len 0 (only addr)
+		 * reset the IP instead of just flush fifos
+		 */
+		xiic_reinit(i2c);
+
+		if (i2c->tx_msg)
+			xiic_wakeup(i2c, STATE_ERROR);
+
+	} else if (pend & XIIC_INTR_RX_FULL_MASK) {
+		/* Receive register/FIFO is full */
+
+		clr = XIIC_INTR_RX_FULL_MASK;
+		if (!i2c->rx_msg) {
+			dev_dbg(i2c->adap.dev.parent,
+				"%s unexpexted RX IRQ\n", __func__);
+			xiic_clear_rx_fifo(i2c);
+			goto out;
+		}
+
+		xiic_read_rx(i2c);
+		if (xiic_rx_space(i2c) == 0) {
+			/* this is the last part of the message */
+			i2c->rx_msg = NULL;
+
+			/* also clear TX error if there (RX complete) */
+			clr |= (isr & XIIC_INTR_TX_ERROR_MASK);
+
+			dev_dbg(i2c->adap.dev.parent,
+				"%s end of message, nmsgs: %d\n",
+				__func__, i2c->nmsgs);
+
+			/* send next message if this wasn't the last,
+			 * otherwise the transfer will be finialise when
+			 * receiving the bus not busy interrupt
+			 */
+			if (i2c->nmsgs > 1) {
+				i2c->nmsgs--;
+				i2c->tx_msg++;
+				dev_dbg(i2c->adap.dev.parent,
+					"%s will start next...\n", __func__);
+
+				__xiic_start_xfer(i2c);
+			}
+		}
+	} else if (pend & XIIC_INTR_BNB_MASK) {
+		/* IIC bus has transitioned to not busy */
+		clr = XIIC_INTR_BNB_MASK;
+
+		/* The bus is not busy, disable BusNotBusy interrupt */
+		xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK);
+
+		if (!i2c->tx_msg)
+			goto out;
+
+		if ((i2c->nmsgs == 1) && !i2c->rx_msg &&
+			xiic_tx_space(i2c) == 0)
+			xiic_wakeup(i2c, STATE_DONE);
+		else
+			xiic_wakeup(i2c, STATE_ERROR);
+
+	} else if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) {
+		/* Transmit register/FIFO is empty or ½ empty */
+
+		clr = pend &
+			(XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK);
+
+		if (!i2c->tx_msg) {
+			dev_dbg(i2c->adap.dev.parent,
+				"%s unexpexted TX IRQ\n", __func__);
+			goto out;
+		}
+
+		xiic_fill_tx_fifo(i2c);
+
+		/* current message sent and there is space in the fifo */
+		if (!xiic_tx_space(i2c) && xiic_tx_fifo_space(i2c) >= 2) {
+			dev_dbg(i2c->adap.dev.parent,
+				"%s end of message sent, nmsgs: %d\n",
+				__func__, i2c->nmsgs);
+			if (i2c->nmsgs > 1) {
+				i2c->nmsgs--;
+				i2c->tx_msg++;
+				__xiic_start_xfer(i2c);
+			} else {
+				xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
+
+				dev_dbg(i2c->adap.dev.parent,
+					"%s Got TX IRQ but no more to do...\n",
+					__func__);
+			}
+		} else if (!xiic_tx_space(i2c) && (i2c->nmsgs == 1))
+			/* current frame is sent and is last,
+			 * make sure to disable tx half
+			 */
+			xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
+	} else {
+		/* got IRQ which is not acked */
+		dev_err(i2c->adap.dev.parent, "%s Got unexpected IRQ\n",
+			__func__);
+		clr = pend;
+	}
+out:
+	dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr);
+
+	xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr);
+}
+
+static int xiic_bus_busy(struct xiic_i2c *i2c)
+{
+	u8 sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET);
+
+	return (sr & XIIC_SR_BUS_BUSY_MASK) ? -EBUSY : 0;
+}
+
+static int xiic_busy(struct xiic_i2c *i2c)
+{
+	int tries = 3;
+	int err;
+
+	if (i2c->tx_msg)
+		return -EBUSY;
+
+	/* for instance if previous transfer was terminated due to TX error
+	 * it might be that the bus is on it's way to become available
+	 * give it at most 3 ms to wake
+	 */
+	err = xiic_bus_busy(i2c);
+	while (err && tries--) {
+		mdelay(1);
+		err = xiic_bus_busy(i2c);
+	}
+
+	return err;
+}
+
+static void xiic_start_recv(struct xiic_i2c *i2c)
+{
+	u8 rx_watermark;
+	struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg;
+
+	/* Clear and enable Rx full interrupt. */
+	xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK);
+
+	/* we want to get all but last byte, because the TX_ERROR IRQ is used
+	 * to inidicate error ACK on the address, and negative ack on the last
+	 * received byte, so to not mix them receive all but last.
+	 * In the case where there is only one byte to receive
+	 * we can check if ERROR and RX full is set at the same time
+	 */
+	rx_watermark = msg->len;
+	if (rx_watermark > IIC_RX_FIFO_DEPTH)
+		rx_watermark = IIC_RX_FIFO_DEPTH;
+	xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1);
+
+	if (!(msg->flags & I2C_M_NOSTART))
+		/* write the address */
+		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
+			(msg->addr << 1) | XIIC_READ_OPERATION |
+			XIIC_TX_DYN_START_MASK);
+
+	xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
+
+	xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
+		msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0));
+	if (i2c->nmsgs == 1)
+		/* very last, enable bus not busy as well */
+		xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
+
+	/* the message is tx:ed */
+	i2c->tx_pos = msg->len;
+}
+
+static void xiic_start_send(struct xiic_i2c *i2c)
+{
+	struct i2c_msg *msg = i2c->tx_msg;
+
+	xiic_irq_clr(i2c, XIIC_INTR_TX_ERROR_MASK);
+
+	dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d, "
+		"ISR: 0x%x, CR: 0x%x\n",
+		__func__, msg, msg->len, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
+		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
+
+	if (!(msg->flags & I2C_M_NOSTART)) {
+		/* write the address */
+		u16 data = ((msg->addr << 1) & 0xfe) | XIIC_WRITE_OPERATION |
+			XIIC_TX_DYN_START_MASK;
+		if ((i2c->nmsgs == 1) && msg->len == 0)
+			/* no data and last message -> add STOP */
+			data |= XIIC_TX_DYN_STOP_MASK;
+
+		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
+	}
+
+	xiic_fill_tx_fifo(i2c);
+
+	/* Clear any pending Tx empty, Tx Error and then enable them. */
+	xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK |
+		XIIC_INTR_BNB_MASK);
+}
+
+static irqreturn_t xiic_isr(int irq, void *dev_id)
+{
+	struct xiic_i2c *i2c = dev_id;
+
+	spin_lock(&i2c->lock);
+	/* disable interrupts globally */
+	xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0);
+
+	dev_dbg(i2c->adap.dev.parent, "%s entry\n", __func__);
+
+	xiic_process(i2c);
+
+	xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
+	spin_unlock(&i2c->lock);
+
+	return IRQ_HANDLED;
+}
+
+static void __xiic_start_xfer(struct xiic_i2c *i2c)
+{
+	int first = 1;
+	int fifo_space = xiic_tx_fifo_space(i2c);
+	dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, fifos space: %d\n",
+		__func__, i2c->tx_msg, fifo_space);
+
+	if (!i2c->tx_msg)
+		return;
+
+	i2c->rx_pos = 0;
+	i2c->tx_pos = 0;
+	i2c->state = STATE_START;
+	while ((fifo_space >= 2) && (first || (i2c->nmsgs > 1))) {
+		if (!first) {
+			i2c->nmsgs--;
+			i2c->tx_msg++;
+			i2c->tx_pos = 0;
+		} else
+			first = 0;
+
+		if (i2c->tx_msg->flags & I2C_M_RD) {
+			/* we dont date putting several reads in the FIFO */
+			xiic_start_recv(i2c);
+			return;
+		} else {
+			xiic_start_send(i2c);
+			if (xiic_tx_space(i2c) != 0) {
+				/* the message could not be completely sent */
+				break;
+			}
+		}
+
+		fifo_space = xiic_tx_fifo_space(i2c);
+	}
+
+	/* there are more messages or the current one could not be completely
+	 * put into the FIFO, also enable the half empty interrupt
+	 */
+	if (i2c->nmsgs > 1 || xiic_tx_space(i2c))
+		xiic_irq_clr_en(i2c, XIIC_INTR_TX_HALF_MASK);
+
+}
+
+static void xiic_start_xfer(struct xiic_i2c *i2c)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&i2c->lock, flags);
+	xiic_reinit(i2c);
+	/* disable interrupts globally */
+	xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0);
+	spin_unlock_irqrestore(&i2c->lock, flags);
+
+	__xiic_start_xfer(i2c);
+	xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
+}
+
+static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+	struct xiic_i2c *i2c = i2c_get_adapdata(adap);
+	int err;
+
+	dev_dbg(adap->dev.parent, "%s entry SR: 0x%x\n", __func__,
+		xiic_getreg8(i2c, XIIC_SR_REG_OFFSET));
+
+	err = xiic_busy(i2c);
+	if (err)
+		return err;
+
+	i2c->tx_msg = msgs;
+	i2c->nmsgs = num;
+
+	xiic_start_xfer(i2c);
+
+	if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
+		(i2c->state == STATE_DONE), HZ))
+		return (i2c->state == STATE_DONE) ? num : -EIO;
+	else {
+		i2c->tx_msg = NULL;
+		i2c->rx_msg = NULL;
+		i2c->nmsgs = 0;
+		return -ETIMEDOUT;
+	}
+}
+
+static u32 xiic_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm xiic_algorithm = {
+	.master_xfer	= xiic_xfer,
+	.functionality	= xiic_func,
+};
+
+static struct i2c_adapter xiic_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= DRIVER_NAME,
+	.class		= I2C_CLASS_HWMON | I2C_CLASS_SPD,
+	.algo		= &xiic_algorithm,
+};
+
+
+static int __devinit xiic_i2c_probe(struct platform_device *pdev)
+{
+	struct xiic_i2c *i2c;
+	struct xiic_i2c_platform_data *pdata;
+	struct resource *res;
+	int ret, irq;
+	u8 i;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto resource_missing;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		goto resource_missing;
+
+	pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data;
+	if (!pdata)
+		return -EINVAL;
+
+	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+	if (!i2c)
+		return -ENOMEM;
+
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "Memory region busy\n");
+		ret = -EBUSY;
+		goto request_mem_failed;
+	}
+
+	i2c->base = ioremap(res->start, resource_size(res));
+	if (!i2c->base) {
+		dev_err(&pdev->dev, "Unable to map registers\n");
+		ret = -EIO;
+		goto map_failed;
+	}
+
+	/* hook up driver to tree */
+	platform_set_drvdata(pdev, i2c);
+	i2c->adap = xiic_adapter;
+	i2c_set_adapdata(&i2c->adap, i2c);
+	i2c->adap.dev.parent = &pdev->dev;
+
+	xiic_reinit(i2c);
+
+	spin_lock_init(&i2c->lock);
+	init_waitqueue_head(&i2c->wait);
+	ret = request_irq(irq, xiic_isr, 0, pdev->name, i2c);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot claim IRQ\n");
+		goto request_irq_failed;
+	}
+
+	/* add i2c adapter to i2c tree */
+	ret = i2c_add_adapter(&i2c->adap);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add adapter\n");
+		goto add_adapter_failed;
+	}
+
+	/* add in known devices to the bus */
+	for (i = 0; i < pdata->num_devices; i++)
+		i2c_new_device(&i2c->adap, pdata->devices + i);
+
+	return 0;
+
+add_adapter_failed:
+	free_irq(irq, i2c);
+request_irq_failed:
+	xiic_deinit(i2c);
+	iounmap(i2c->base);
+map_failed:
+	release_mem_region(res->start, resource_size(res));
+request_mem_failed:
+	kfree(i2c);
+
+	return ret;
+resource_missing:
+	dev_err(&pdev->dev, "IRQ or Memory resource is missing\n");
+	return -ENOENT;
+}
+
+static int __devexit xiic_i2c_remove(struct platform_device* pdev)
+{
+	struct xiic_i2c *i2c = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	/* remove adapter & data */
+	i2c_del_adapter(&i2c->adap);
+
+	xiic_deinit(i2c);
+
+	platform_set_drvdata(pdev, NULL);
+
+	free_irq(platform_get_irq(pdev, 0), i2c);
+
+	iounmap(i2c->base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res)
+		release_mem_region(res->start, resource_size(res));
+
+	kfree(i2c);
+
+	return 0;
+}
+
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
+static struct platform_driver xiic_i2c_driver = {
+	.probe   = xiic_i2c_probe,
+	.remove  = __devexit_p(xiic_i2c_remove),
+	.driver  = {
+		.owner = THIS_MODULE,
+		.name = DRIVER_NAME,
+	},
+};
+
+static int __init xiic_i2c_init(void)
+{
+	return platform_driver_register(&xiic_i2c_driver);
+}
+
+static void __exit xiic_i2c_exit(void)
+{
+	platform_driver_unregister(&xiic_i2c_driver);
+}
+
+module_init(xiic_i2c_init);
+module_exit(xiic_i2c_exit);
+
+MODULE_AUTHOR("info@mocean-labs.com");
+MODULE_DESCRIPTION("Xilinx I2C bus driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 10be7b5..3202a86 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -34,6 +34,7 @@
 #include <linux/hardirq.h>
 #include <linux/irqflags.h>
 #include <linux/rwsem.h>
+#include <linux/pm_runtime.h>
 #include <asm/uaccess.h>
 
 #include "i2c-core.h"
@@ -184,6 +185,52 @@
 #define i2c_device_pm_resume	NULL
 #endif
 
+#ifdef CONFIG_PM_RUNTIME
+static int i2c_device_runtime_suspend(struct device *dev)
+{
+	const struct dev_pm_ops *pm;
+
+	if (!dev->driver)
+		return 0;
+	pm = dev->driver->pm;
+	if (!pm || !pm->runtime_suspend)
+		return 0;
+	return pm->runtime_suspend(dev);
+}
+
+static int i2c_device_runtime_resume(struct device *dev)
+{
+	const struct dev_pm_ops *pm;
+
+	if (!dev->driver)
+		return 0;
+	pm = dev->driver->pm;
+	if (!pm || !pm->runtime_resume)
+		return 0;
+	return pm->runtime_resume(dev);
+}
+
+static int i2c_device_runtime_idle(struct device *dev)
+{
+	const struct dev_pm_ops *pm = NULL;
+	int ret;
+
+	if (dev->driver)
+		pm = dev->driver->pm;
+	if (pm && pm->runtime_idle) {
+		ret = pm->runtime_idle(dev);
+		if (ret)
+			return ret;
+	}
+
+	return pm_runtime_suspend(dev);
+}
+#else
+#define i2c_device_runtime_suspend	NULL
+#define i2c_device_runtime_resume	NULL
+#define i2c_device_runtime_idle		NULL
+#endif
+
 static int i2c_device_suspend(struct device *dev, pm_message_t mesg)
 {
 	struct i2c_client *client = i2c_verify_client(dev);
@@ -251,6 +298,9 @@
 static const struct dev_pm_ops i2c_device_pm_ops = {
 	.suspend = i2c_device_pm_suspend,
 	.resume = i2c_device_pm_resume,
+	.runtime_suspend = i2c_device_runtime_suspend,
+	.runtime_resume = i2c_device_runtime_resume,
+	.runtime_idle = i2c_device_runtime_idle,
 };
 
 struct bus_type i2c_bus_type = {
@@ -1133,7 +1183,7 @@
  * i2c_master_send - issue a single I2C message in master transmit mode
  * @client: Handle to slave device
  * @buf: Data that will be written to the slave
- * @count: How many bytes to write
+ * @count: How many bytes to write, must be less than 64k since msg.len is u16
  *
  * Returns negative errno, or else the number of bytes written.
  */
@@ -1160,7 +1210,7 @@
  * i2c_master_recv - issue a single I2C message in master receive mode
  * @client: Handle to slave device
  * @buf: Where to store data read from slave
- * @count: How many bytes to read
+ * @count: How many bytes to read, must be less than 64k since msg.len is u16
  *
  * Returns negative errno, or else the number of bytes read.
  */
diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
new file mode 100644
index 0000000..4212782
--- /dev/null
+++ b/drivers/i2c/i2c-smbus.c
@@ -0,0 +1,263 @@
+/*
+ * i2c-smbus.c - SMBus extensions to the I2C protocol
+ *
+ * Copyright (C) 2008 David Brownell
+ * Copyright (C) 2010 Jean Delvare <khali@linux-fr.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/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/semaphore.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
+
+struct i2c_smbus_alert {
+	unsigned int		alert_edge_triggered:1;
+	int			irq;
+	struct work_struct	alert;
+	struct i2c_client	*ara;		/* Alert response address */
+};
+
+struct alert_data {
+	unsigned short		addr;
+	u8			flag:1;
+};
+
+/* If this is the alerting device, notify its driver */
+static int smbus_do_alert(struct device *dev, void *addrp)
+{
+	struct i2c_client *client = i2c_verify_client(dev);
+	struct alert_data *data = addrp;
+
+	if (!client || client->addr != data->addr)
+		return 0;
+	if (client->flags & I2C_CLIENT_TEN)
+		return 0;
+
+	/*
+	 * Drivers should either disable alerts, or provide at least
+	 * a minimal handler.  Lock so client->driver won't change.
+	 */
+	down(&dev->sem);
+	if (client->driver) {
+		if (client->driver->alert)
+			client->driver->alert(client, data->flag);
+		else
+			dev_warn(&client->dev, "no driver alert()!\n");
+	} else
+		dev_dbg(&client->dev, "alert with no driver\n");
+	up(&dev->sem);
+
+	/* Stop iterating after we find the device */
+	return -EBUSY;
+}
+
+/*
+ * The alert IRQ handler needs to hand work off to a task which can issue
+ * SMBus calls, because those sleeping calls can't be made in IRQ context.
+ */
+static void smbus_alert(struct work_struct *work)
+{
+	struct i2c_smbus_alert *alert;
+	struct i2c_client *ara;
+	unsigned short prev_addr = 0;	/* Not a valid address */
+
+	alert = container_of(work, struct i2c_smbus_alert, alert);
+	ara = alert->ara;
+
+	for (;;) {
+		s32 status;
+		struct alert_data data;
+
+		/*
+		 * Devices with pending alerts reply in address order, low
+		 * to high, because of slave transmit arbitration.  After
+		 * responding, an SMBus device stops asserting SMBALERT#.
+		 *
+		 * Note that SMBus 2.0 reserves 10-bit addresess for future
+		 * use.  We neither handle them, nor try to use PEC here.
+		 */
+		status = i2c_smbus_read_byte(ara);
+		if (status < 0)
+			break;
+
+		data.flag = status & 1;
+		data.addr = status >> 1;
+
+		if (data.addr == prev_addr) {
+			dev_warn(&ara->dev, "Duplicate SMBALERT# from dev "
+				"0x%02x, skipping\n", data.addr);
+			break;
+		}
+		dev_dbg(&ara->dev, "SMBALERT# from dev 0x%02x, flag %d\n",
+			data.addr, data.flag);
+
+		/* Notify driver for the device which issued the alert */
+		device_for_each_child(&ara->adapter->dev, &data,
+				      smbus_do_alert);
+		prev_addr = data.addr;
+	}
+
+	/* We handled all alerts; re-enable level-triggered IRQs */
+	if (!alert->alert_edge_triggered)
+		enable_irq(alert->irq);
+}
+
+static irqreturn_t smbalert_irq(int irq, void *d)
+{
+	struct i2c_smbus_alert *alert = d;
+
+	/* Disable level-triggered IRQs until we handle them */
+	if (!alert->alert_edge_triggered)
+		disable_irq_nosync(irq);
+
+	schedule_work(&alert->alert);
+	return IRQ_HANDLED;
+}
+
+/* Setup SMBALERT# infrastructure */
+static int smbalert_probe(struct i2c_client *ara,
+			  const struct i2c_device_id *id)
+{
+	struct i2c_smbus_alert_setup *setup = ara->dev.platform_data;
+	struct i2c_smbus_alert *alert;
+	struct i2c_adapter *adapter = ara->adapter;
+	int res;
+
+	alert = kzalloc(sizeof(struct i2c_smbus_alert), GFP_KERNEL);
+	if (!alert)
+		return -ENOMEM;
+
+	alert->alert_edge_triggered = setup->alert_edge_triggered;
+	alert->irq = setup->irq;
+	INIT_WORK(&alert->alert, smbus_alert);
+	alert->ara = ara;
+
+	if (setup->irq > 0) {
+		res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq,
+				       0, "smbus_alert", alert);
+		if (res) {
+			kfree(alert);
+			return res;
+		}
+	}
+
+	i2c_set_clientdata(ara, alert);
+	dev_info(&adapter->dev, "supports SMBALERT#, %s trigger\n",
+		 setup->alert_edge_triggered ? "edge" : "level");
+
+	return 0;
+}
+
+/* IRQ resource is managed so it is freed automatically */
+static int smbalert_remove(struct i2c_client *ara)
+{
+	struct i2c_smbus_alert *alert = i2c_get_clientdata(ara);
+
+	cancel_work_sync(&alert->alert);
+
+	i2c_set_clientdata(ara, NULL);
+	kfree(alert);
+	return 0;
+}
+
+static const struct i2c_device_id smbalert_ids[] = {
+	{ "smbus_alert", 0 },
+	{ /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, smbalert_ids);
+
+static struct i2c_driver smbalert_driver = {
+	.driver = {
+		.name	= "smbus_alert",
+	},
+	.probe		= smbalert_probe,
+	.remove		= smbalert_remove,
+	.id_table	= smbalert_ids,
+};
+
+/**
+ * i2c_setup_smbus_alert - Setup SMBus alert support
+ * @adapter: the target adapter
+ * @setup: setup data for the SMBus alert handler
+ * Context: can sleep
+ *
+ * Setup handling of the SMBus alert protocol on a given I2C bus segment.
+ *
+ * Handling can be done either through our IRQ handler, or by the
+ * adapter (from its handler, periodic polling, or whatever).
+ *
+ * NOTE that if we manage the IRQ, we *MUST* know if it's level or
+ * edge triggered in order to hand it to the workqueue correctly.
+ * If triggering the alert seems to wedge the system, you probably
+ * should have said it's level triggered.
+ *
+ * This returns the ara client, which should be saved for later use with
+ * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL
+ * to indicate an error.
+ */
+struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
+					 struct i2c_smbus_alert_setup *setup)
+{
+	struct i2c_board_info ara_board_info = {
+		I2C_BOARD_INFO("smbus_alert", 0x0c),
+		.platform_data = setup,
+	};
+
+	return i2c_new_device(adapter, &ara_board_info);
+}
+EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);
+
+/**
+ * i2c_handle_smbus_alert - Handle an SMBus alert
+ * @ara: the ARA client on the relevant adapter
+ * Context: can't sleep
+ *
+ * Helper function to be called from an I2C bus driver's interrupt
+ * handler. It will schedule the alert work, in turn calling the
+ * corresponding I2C device driver's alert function.
+ *
+ * It is assumed that ara is a valid i2c client previously returned by
+ * i2c_setup_smbus_alert().
+ */
+int i2c_handle_smbus_alert(struct i2c_client *ara)
+{
+	struct i2c_smbus_alert *alert = i2c_get_clientdata(ara);
+
+	return schedule_work(&alert->alert);
+}
+EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert);
+
+static int __init i2c_smbus_init(void)
+{
+	return i2c_add_driver(&smbalert_driver);
+}
+
+static void __exit i2c_smbus_exit(void)
+{
+	i2c_del_driver(&smbalert_driver);
+}
+
+module_init(i2c_smbus_init);
+module_exit(i2c_smbus_exit);
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("SMBus protocol extensions support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
index 878f8ec..57d00ca 100644
--- a/drivers/ide/aec62xx.c
+++ b/drivers/ide/aec62xx.c
@@ -81,15 +81,15 @@
 	return chipset_table->ultra_settings;
 }
 
-static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
+static void aec6210_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	struct ide_host *host	= pci_get_drvdata(dev);
 	struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
 	u16 d_conf		= 0;
 	u8 ultra = 0, ultra_conf = 0;
 	u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
+	const u8 speed = drive->dma_mode;
 	unsigned long flags;
 
 	local_irq_save(flags);
@@ -109,15 +109,15 @@
 	local_irq_restore(flags);
 }
 
-static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
+static void aec6260_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	struct ide_host *host	= pci_get_drvdata(dev);
 	struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
 	u8 unit			= drive->dn & 1;
 	u8 tmp1 = 0, tmp2 = 0;
 	u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
+	const u8 speed = drive->dma_mode;
 	unsigned long flags;
 
 	local_irq_save(flags);
@@ -134,9 +134,10 @@
 	local_irq_restore(flags);
 }
 
-static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void aec_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
+	drive->dma_mode = drive->pio_mode;
+	hwif->port_ops->set_dma_mode(hwif, drive);
 }
 
 static int init_chipset_aec62xx(struct pci_dev *dev)
diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c
index 90da1f9..25b9fe3 100644
--- a/drivers/ide/ali14xx.c
+++ b/drivers/ide/ali14xx.c
@@ -109,13 +109,14 @@
  * This function computes timing parameters
  * and sets controller registers accordingly.
  */
-static void ali14xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void ali14xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	int driveNum;
 	int time1, time2;
 	u8 param1, param2, param3, param4;
 	unsigned long flags;
 	int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 	struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
 
 	/* calculate timing, according to PIO mode */
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index 0abc43f..2c8016a 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -8,7 +8,7 @@
  *  Copyright (C) 2002 Alan Cox
  *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
  *  Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
- *  Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+ *  Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
  *
  *  (U)DMA capable version of ali 1533/1543(C), 1535(D)
  *
@@ -48,61 +48,84 @@
 static u8 chip_is_1543c_e;
 static struct pci_dev *isa_dev;
 
+static void ali_fifo_control(ide_hwif_t *hwif, ide_drive_t *drive, int on)
+{
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
+	int pio_fifo = 0x54 + hwif->channel;
+	u8 fifo;
+	int shift = 4 * (drive->dn & 1);
+
+	pci_read_config_byte(pdev, pio_fifo, &fifo);
+	fifo &= ~(0x0F << shift);
+	fifo |= (on << shift);
+	pci_write_config_byte(pdev, pio_fifo, fifo);
+}
+
+static void ali_program_timings(ide_hwif_t *hwif, ide_drive_t *drive,
+				struct ide_timing *t, u8 ultra)
+{
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+	int port = hwif->channel ? 0x5c : 0x58;
+	int udmat = 0x56 + hwif->channel;
+	u8 unit = drive->dn & 1, udma;
+	int shift = 4 * unit;
+
+	/* Set up the UDMA */
+	pci_read_config_byte(dev, udmat, &udma);
+	udma &= ~(0x0F << shift);
+	udma |= ultra << shift;
+	pci_write_config_byte(dev, udmat, udma);
+
+	if (t == NULL)
+		return;
+
+	t->setup = clamp_val(t->setup, 1, 8) & 7;
+	t->act8b = clamp_val(t->act8b, 1, 8) & 7;
+	t->rec8b = clamp_val(t->rec8b, 1, 16) & 15;
+	t->active = clamp_val(t->active, 1, 8) & 7;
+	t->recover = clamp_val(t->recover, 1, 16) & 15;
+
+	pci_write_config_byte(dev, port, t->setup);
+	pci_write_config_byte(dev, port + 1, (t->act8b << 4) | t->rec8b);
+	pci_write_config_byte(dev, port + unit + 2,
+			      (t->active << 4) | t->recover);
+}
+
 /**
  *	ali_set_pio_mode	-	set host controller for PIO mode
+ *	@hwif: port
  *	@drive: drive
- *	@pio: PIO mode number
  *
  *	Program the controller for the given PIO mode.
  */
 
-static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void ali_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
-	struct pci_dev *dev = to_pci_dev(hwif->dev);
-	struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
-	int s_time = t->setup, a_time = t->active, c_time = t->cycle;
-	u8 s_clc, a_clc, r_clc;
-	unsigned long flags;
+	ide_drive_t *pair = ide_get_pair_dev(drive);
 	int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
-	int port = hwif->channel ? 0x5c : 0x58;
-	int portFIFO = hwif->channel ? 0x55 : 0x54;
-	u8 cd_dma_fifo = 0, unit = drive->dn & 1;
+	unsigned long T =  1000000 / bus_speed; /* PCI clock based */
+	struct ide_timing t;
 
-	if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
-		s_clc = 0;
-	if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)
-		a_clc = 0;
+	ide_timing_compute(drive, drive->pio_mode, &t, T, 1);
+	if (pair) {
+		struct ide_timing p;
 
-	if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {
-		r_clc = 1;
-	} else {
-		if (r_clc >= 16)
-			r_clc = 0;
+		ide_timing_compute(pair, pair->pio_mode, &p, T, 1);
+		ide_timing_merge(&p, &t, &t,
+			IDE_TIMING_SETUP | IDE_TIMING_8BIT);
+		if (pair->dma_mode) {
+			ide_timing_compute(pair, pair->dma_mode, &p, T, 1);
+			ide_timing_merge(&p, &t, &t,
+				IDE_TIMING_SETUP | IDE_TIMING_8BIT);
+		}
 	}
-	local_irq_save(flags);
-	
+
 	/* 
 	 * PIO mode => ATA FIFO on, ATAPI FIFO off
 	 */
-	pci_read_config_byte(dev, portFIFO, &cd_dma_fifo);
-	if (drive->media==ide_disk) {
-		if (unit) {
-			pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50);
-		} else {
-			pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05);
-		}
-	} else {
-		if (unit) {
-			pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F);
-		} else {
-			pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0);
-		}
-	}
-	
-	pci_write_config_byte(dev, port, s_clc);
-	pci_write_config_byte(dev, port + unit + 2, (a_clc << 4) | r_clc);
-	local_irq_restore(flags);
+	ali_fifo_control(hwif, drive, (drive->media == ide_disk) ? 0x05 : 0x00);
+
+	ali_program_timings(hwif, drive, &t, 0);
 }
 
 /**
@@ -132,44 +155,42 @@
 
 /**
  *	ali_set_dma_mode	-	set host controller for DMA mode
+ *	@hwif: port
  *	@drive: drive
- *	@speed: DMA mode
  *
  *	Configure the hardware for the desired IDE transfer mode.
  */
 
-static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void ali_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
+	static u8 udma_timing[7] = { 0xC, 0xB, 0xA, 0x9, 0x8, 0xF, 0xD };
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
-	u8 speed1		= speed;
-	u8 unit			= drive->dn & 1;
+	ide_drive_t *pair	= ide_get_pair_dev(drive);
+	int bus_speed		= ide_pci_clk ? ide_pci_clk : 33;
+	unsigned long T		=  1000000 / bus_speed; /* PCI clock based */
+	const u8 speed		= drive->dma_mode;
 	u8 tmpbyte		= 0x00;
-	int m5229_udma		= (hwif->channel) ? 0x57 : 0x56;
-
-	if (speed == XFER_UDMA_6)
-		speed1 = 0x47;
+	struct ide_timing t;
 
 	if (speed < XFER_UDMA_0) {
-		u8 ultra_enable	= (unit) ? 0x7f : 0xf7;
-		/*
-		 * clear "ultra enable" bit
-		 */
-		pci_read_config_byte(dev, m5229_udma, &tmpbyte);
-		tmpbyte &= ultra_enable;
-		pci_write_config_byte(dev, m5229_udma, tmpbyte);
+		ide_timing_compute(drive, drive->dma_mode, &t, T, 1);
+		if (pair) {
+			struct ide_timing p;
 
-		/*
-		 * FIXME: Oh, my... DMA timings are never set.
-		 */
+			ide_timing_compute(pair, pair->pio_mode, &p, T, 1);
+			ide_timing_merge(&p, &t, &t,
+				IDE_TIMING_SETUP | IDE_TIMING_8BIT);
+			if (pair->dma_mode) {
+				ide_timing_compute(pair, pair->dma_mode,
+						&p, T, 1);
+				ide_timing_merge(&p, &t, &t,
+					IDE_TIMING_SETUP | IDE_TIMING_8BIT);
+			}
+		}
+		ali_program_timings(hwif, drive, &t, 0);
 	} else {
-		pci_read_config_byte(dev, m5229_udma, &tmpbyte);
-		tmpbyte &= (0x0f << ((1-unit) << 2));
-		/*
-		 * enable ultra dma and set timing
-		 */
-		tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2));
-		pci_write_config_byte(dev, m5229_udma, tmpbyte);
+		ali_program_timings(hwif, drive, NULL,
+				udma_timing[speed - XFER_UDMA_0]);
 		if (speed >= XFER_UDMA_3) {
 			pci_read_config_byte(dev, 0x4b, &tmpbyte);
 			tmpbyte |= 1;
@@ -355,19 +376,13 @@
  *
  *	This checks if the controller and the cable are capable
  *	of UDMA66 transfers. It doesn't check the drives.
- *	But see note 2 below!
- *
- *	FIXME: frobs bits that are not defined on newer ALi devicea
  */
 
 static u8 ali_cable_detect(ide_hwif_t *hwif)
 {
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
-	unsigned long flags;
 	u8 cbl = ATA_CBL_PATA40, tmpbyte;
 
-	local_irq_save(flags);
-
 	if (m5229_revision >= 0xC2) {
 		/*
 		 * m5229 80-pin cable detection (from Host View)
@@ -387,8 +402,6 @@
 		}
 	}
 
-	local_irq_restore(flags);
-
 	return cbl;
 }
 
@@ -584,6 +597,6 @@
 module_init(ali15x3_ide_init);
 module_exit(ali15x3_ide_exit);
 
-MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox");
+MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index 628cd2e..3747b25 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -3,7 +3,7 @@
  * IDE driver for Linux.
  *
  * Copyright (c) 2000-2002 Vojtech Pavlik
- * Copyright (c) 2007-2008 Bartlomiej Zolnierkiewicz
+ * Copyright (c) 2007-2010 Bartlomiej Zolnierkiewicz
  *
  * Based on the work of:
  *      Andre Hedrick
@@ -70,7 +70,8 @@
 	default: return;
 	}
 
-	pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + (3 - dn), t);
+	if (timing->udma)
+		pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + 3 - dn, t);
 }
 
 /*
@@ -78,14 +79,14 @@
  * to a desired transfer mode.  It also can be called by upper layers.
  */
 
-static void amd_set_drive(ide_drive_t *drive, const u8 speed)
+static void amd_set_drive(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	ide_drive_t *peer = ide_get_pair_dev(drive);
 	struct ide_timing t, p;
 	int T, UT;
 	u8 udma_mask = hwif->ultra_mask;
+	const u8 speed = drive->dma_mode;
 
 	T = 1000000000 / amd_clock;
 	UT = (udma_mask == ATA_UDMA2) ? T : (T / 2);
@@ -93,7 +94,7 @@
 	ide_timing_compute(drive, speed, &t, T, UT);
 
 	if (peer) {
-		ide_timing_compute(peer, peer->current_speed, &p, T, UT);
+		ide_timing_compute(peer, peer->pio_mode, &p, T, UT);
 		ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
 	}
 
@@ -107,9 +108,10 @@
  * amd_set_pio_mode() is a callback from upper layers for PIO-only tuning.
  */
 
-static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void amd_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	amd_set_drive(drive, XFER_PIO_0 + pio);
+	drive->dma_mode = drive->pio_mode;
+	amd_set_drive(hwif, drive);
 }
 
 static void amd7409_cable_detect(struct pci_dev *dev)
@@ -340,6 +342,6 @@
 module_init(amd74xx_ide_init);
 module_exit(amd74xx_ide_exit);
 
-MODULE_AUTHOR("Vojtech Pavlik");
+MODULE_AUTHOR("Vojtech Pavlik, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("AMD PCI IDE driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c
index 248219a..000a78e 100644
--- a/drivers/ide/at91_ide.c
+++ b/drivers/ide/at91_ide.c
@@ -172,11 +172,12 @@
 	leave_16bit(chipselect, mode);
 }
 
-static void at91_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void at91_ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	struct ide_timing *timing;
-	u8 chipselect = drive->hwif->select_data;
+	u8 chipselect = hwif->select_data;
 	int use_iordy = 0;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	pdbg("chipselect %u pio %u\n", chipselect, pio);
 
diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c
index 837322b..15f0ead 100644
--- a/drivers/ide/atiixp.c
+++ b/drivers/ide/atiixp.c
@@ -42,19 +42,20 @@
 
 /**
  *	atiixp_set_pio_mode	-	set host controller for PIO mode
+ *	@hwif: port
  *	@drive: drive
- *	@pio: PIO mode number
  *
  *	Set the interface PIO mode.
  */
 
-static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void atiixp_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned long flags;
 	int timing_shift = (drive->dn ^ 1) * 8;
 	u32 pio_timing_data;
 	u16 pio_mode_data;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	spin_lock_irqsave(&atiixp_lock, flags);
 
@@ -74,21 +75,22 @@
 
 /**
  *	atiixp_set_dma_mode	-	set host controller for DMA mode
+ *	@hwif: port
  *	@drive: drive
- *	@speed: DMA mode
  *
  *	Set a ATIIXP host controller to the desired DMA mode.  This involves
  *	programming the right timing data into the PCI configuration space.
  */
 
-static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void atiixp_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned long flags;
 	int timing_shift = (drive->dn ^ 1) * 8;
 	u32 tmp32;
 	u16 tmp16;
 	u16 udma_ctl = 0;
+	const u8 speed = drive->dma_mode;
 
 	spin_lock_irqsave(&atiixp_lock, flags);
 
diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c
index 349a67b..b26c234 100644
--- a/drivers/ide/au1xxx-ide.c
+++ b/drivers/ide/au1xxx-ide.c
@@ -99,12 +99,11 @@
 }
 #endif
 
-static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void au1xxx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2);
 
-	/* set pio mode! */
-	switch(pio) {
+	switch (drive->pio_mode - XFER_PIO_0) {
 	case 0:
 		mem_sttime = SBC_IDE_TIMING(PIO0);
 
@@ -161,11 +160,11 @@
 	au_writel(mem_stcfg,MEM_STCFG2);
 }
 
-static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void auide_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2);
 
-	switch(speed) {
+	switch (drive->dma_mode) {
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 	case XFER_MW_DMA_2:
 		mem_sttime = SBC_IDE_TIMING(MDMA2);
@@ -297,8 +296,8 @@
 	 */
 	drive->waiting_for_dma++;
 	if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
-		printk(KERN_WARNING "%s: timeout waiting for ddma to \
-                                     complete\n", drive->name);
+		printk(KERN_WARNING "%s: timeout waiting for ddma to complete\n",
+		       drive->name);
 		return 1;
 	}
 	udelay(10);
diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
index 1a32d62..d2b8b27 100644
--- a/drivers/ide/cmd640.c
+++ b/drivers/ide/cmd640.c
@@ -572,9 +572,10 @@
 	program_drive_counts(drive, index);
 }
 
-static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void cmd640_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	unsigned int index = 0, cycle_time;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 	u8 b;
 
 	switch (pio) {
@@ -605,7 +606,7 @@
 }
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 
-static void cmd640_init_dev(ide_drive_t *drive)
+static void __init cmd640_init_dev(ide_drive_t *drive)
 {
 	unsigned int i = drive->hwif->channel * 2 + (drive->dn & 1);
 
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index f2500c8..5f80312 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -7,6 +7,7 @@
  * Copyright (C) 1998		David S. Miller (davem@redhat.com)
  *
  * Copyright (C) 1999-2002	Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2007-2010	Bartlomiej Zolnierkiewicz
  * Copyright (C) 2007,2009	MontaVista Software, Inc. <source@mvista.com>
  */
 
@@ -50,72 +51,42 @@
 #define UDIDETCR1	0x7B
 #define DTPR1		0x7C
 
-static u8 quantize_timing(int timing, int quant)
+static void cmd64x_program_timings(ide_drive_t *drive, u8 mode)
 {
-	return (timing + quant - 1) / quant;
-}
-
-/*
- * This routine calculates active/recovery counts and then writes them into
- * the chipset registers.
- */
-static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
-{
+	ide_hwif_t *hwif = drive->hwif;
 	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-	int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33);
-	u8  cycle_count, active_count, recovery_count, drwtim;
+	int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
+	const unsigned long T = 1000000 / bus_speed;
 	static const u8 recovery_values[] =
 		{15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
+	static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
+	static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
 	static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};
+	struct ide_timing t;
+	u8 arttim = 0;
 
-	cycle_count	= quantize_timing( cycle_time, clock_time);
-	active_count	= quantize_timing(active_time, clock_time);
-	recovery_count	= cycle_count - active_count;
+	ide_timing_compute(drive, mode, &t, T, 0);
 
 	/*
 	 * In case we've got too long recovery phase, try to lengthen
 	 * the active phase
 	 */
-	if (recovery_count > 16) {
-		active_count += recovery_count - 16;
-		recovery_count = 16;
+	if (t.recover > 16) {
+		t.active += t.recover - 16;
+		t.recover = 16;
 	}
-	if (active_count > 16)		/* shouldn't actually happen... */
-	 	active_count = 16;
+	if (t.active > 16)		/* shouldn't actually happen... */
+		t.active = 16;
 
 	/*
 	 * Convert values to internal chipset representation
 	 */
-	recovery_count = recovery_values[recovery_count];
- 	active_count  &= 0x0f;
+	t.recover = recovery_values[t.recover];
+	t.active &= 0x0f;
 
 	/* Program the active/recovery counts into the DRWTIM register */
-	drwtim = (active_count << 4) | recovery_count;
-	(void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim);
-}
-
-/*
- * This routine writes into the chipset registers
- * PIO setup/active/recovery timings.
- */
-static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
-{
-	ide_hwif_t *hwif	= drive->hwif;
-	struct pci_dev *dev	= to_pci_dev(hwif->dev);
-	struct ide_timing *t	= ide_timing_find_mode(XFER_PIO_0 + pio);
-	unsigned long setup_count;
-	unsigned int cycle_time;
-	u8 arttim = 0;
-
-	static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
-	static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
-
-	cycle_time = ide_pio_cycle_time(drive, pio);
-
-	program_cycle_times(drive, cycle_time, t->active);
-
-	setup_count = quantize_timing(t->setup,
-			1000 / (ide_pci_clk ? ide_pci_clk : 33));
+	pci_write_config_byte(dev, drwtim_regs[drive->dn],
+			      (t.active << 4) | t.recover);
 
 	/*
 	 * The primary channel has individual address setup timing registers
@@ -126,15 +97,21 @@
 	if (hwif->channel) {
 		ide_drive_t *pair = ide_get_pair_dev(drive);
 
-		ide_set_drivedata(drive, (void *)setup_count);
+		if (pair) {
+			struct ide_timing tp;
 
-		if (pair)
-			setup_count = max_t(u8, setup_count,
-					(unsigned long)ide_get_drivedata(pair));
+			ide_timing_compute(pair, pair->pio_mode, &tp, T, 0);
+			ide_timing_merge(&t, &tp, &t, IDE_TIMING_SETUP);
+			if (pair->dma_mode) {
+				ide_timing_compute(pair, pair->dma_mode,
+						&tp, T, 0);
+				ide_timing_merge(&tp, &t, &t, IDE_TIMING_SETUP);
+			}
+		}
 	}
 
-	if (setup_count > 5)		/* shouldn't actually happen... */
-		setup_count = 5;
+	if (t.setup > 5)		/* shouldn't actually happen... */
+		t.setup = 5;
 
 	/*
 	 * Program the address setup clocks into the ARTTIM registers.
@@ -144,7 +121,7 @@
 	if (hwif->channel)
 		arttim &= ~ARTTIM23_INTR_CH1;
 	arttim &= ~0xc0;
-	arttim |= setup_values[setup_count];
+	arttim |= setup_values[t.setup];
 	(void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
 }
 
@@ -153,8 +130,10 @@
  * Special cases are 8: prefetch off, 9: prefetch on (both never worked)
  */
 
-static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void cmd64x_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
+
 	/*
 	 * Filter out the prefetch control values
 	 * to prevent PIO5 from being programmed
@@ -162,20 +141,18 @@
 	if (pio == 8 || pio == 9)
 		return;
 
-	cmd64x_tune_pio(drive, pio);
+	cmd64x_program_timings(drive, XFER_PIO_0 + pio);
 }
 
-static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void cmd64x_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 unit			= drive->dn & 0x01;
 	u8 regU = 0, pciU	= hwif->channel ? UDIDETCR1 : UDIDETCR0;
+	const u8 speed		= drive->dma_mode;
 
-	if (speed >= XFER_SW_DMA_0) {
-		(void) pci_read_config_byte(dev, pciU, &regU);
-		regU &= ~(unit ? 0xCA : 0x35);
-	}
+	pci_read_config_byte(dev, pciU, &regU);
+	regU &= ~(unit ? 0xCA : 0x35);
 
 	switch(speed) {
 	case XFER_UDMA_5:
@@ -197,18 +174,13 @@
 		regU |= unit ? 0xC2 : 0x31;
 		break;
 	case XFER_MW_DMA_2:
-		program_cycle_times(drive, 120, 70);
-		break;
 	case XFER_MW_DMA_1:
-		program_cycle_times(drive, 150, 80);
-		break;
 	case XFER_MW_DMA_0:
-		program_cycle_times(drive, 480, 215);
+		cmd64x_program_timings(drive, speed);
 		break;
 	}
 
-	if (speed >= XFER_SW_DMA_0)
-		(void) pci_write_config_byte(dev, pciU, regU);
+	pci_write_config_byte(dev, pciU, regU);
 }
 
 static void cmd648_clear_irq(ide_drive_t *drive)
@@ -471,6 +443,6 @@
 module_init(cmd64x_ide_init);
 module_exit(cmd64x_ide_exit);
 
-MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");
+MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c
index 09f98ed..2c1e5f7 100644
--- a/drivers/ide/cs5520.c
+++ b/drivers/ide/cs5520.c
@@ -57,11 +57,11 @@
 	{1, 2, 1}
 };
 
-static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void cs5520_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 	int controller = drive->dn > 1 ? 1 : 0;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	/* 8bit CAT/CRT - 8bit command timing for channel */
 	pci_write_config_byte(pdev, 0x62 + controller, 
@@ -81,11 +81,12 @@
 		(cs5520_pio_clocks[pio].assert));
 }
 
-static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void cs5520_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	printk(KERN_ERR "cs55x0: bad ide timing.\n");
 
-	cs5520_set_pio_mode(drive, 0);
+	drive->pio_mode = XFER_PIO_0 + 0;
+	cs5520_set_pio_mode(hwif, drive);
 }
 
 static const struct ide_port_ops cs5520_port_ops = {
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
index 40bf05e..4dc4eb9 100644
--- a/drivers/ide/cs5530.c
+++ b/drivers/ide/cs5530.c
@@ -41,8 +41,8 @@
 
 /**
  *	cs5530_set_pio_mode	-	set host controller for PIO mode
+ *	@hwif: port
  *	@drive: drive
- *	@pio: PIO mode number
  *
  *	Handles setting of PIO mode for the chipset.
  *
@@ -50,10 +50,11 @@
  *	will have valid default PIO timings set up before we get here.
  */
 
-static void cs5530_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void cs5530_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	unsigned long basereg = CS5530_BASEREG(drive->hwif);
+	unsigned long basereg = CS5530_BASEREG(hwif);
 	unsigned int format = (inl(basereg + 4) >> 31) & 1;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
 }
@@ -99,12 +100,12 @@
 	return mask;
 }
 
-static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
+static void cs5530_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	unsigned long basereg;
 	unsigned int reg, timings = 0;
 
-	switch (mode) {
+	switch (drive->dma_mode) {
 		case XFER_UDMA_0:	timings = 0x00921250; break;
 		case XFER_UDMA_1:	timings = 0x00911140; break;
 		case XFER_UDMA_2:	timings = 0x00911030; break;
@@ -112,7 +113,7 @@
 		case XFER_MW_DMA_1:	timings = 0x00012121; break;
 		case XFER_MW_DMA_2:	timings = 0x00002020; break;
 	}
-	basereg = CS5530_BASEREG(drive->hwif);
+	basereg = CS5530_BASEREG(hwif);
 	reg = inl(basereg + 4);			/* get drive0 config register */
 	timings |= reg & 0x80000000;		/* preserve PIO format bit */
 	if ((drive-> dn & 1) == 0) {		/* are we configuring drive0? */
diff --git a/drivers/ide/cs5535.c b/drivers/ide/cs5535.c
index b883838..5059faf 100644
--- a/drivers/ide/cs5535.c
+++ b/drivers/ide/cs5535.c
@@ -86,7 +86,7 @@
 		cmd = pioa = speed - XFER_PIO_0;
 
 		if (pair) {
-			u8 piob = ide_get_best_pio_mode(pair, 255, 4);
+			u8 piob = pair->pio_mode - XFER_PIO_0;
 
 			if (piob < cmd)
 				cmd = piob;
@@ -129,28 +129,28 @@
 
 /**
  *	cs5535_set_dma_mode	-	set host controller for DMA mode
+ *	@hwif: port
  *	@drive: drive
- *	@speed: DMA mode
  *
  *	Programs the chipset for DMA mode.
  */
 
-static void cs5535_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void cs5535_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	cs5535_set_speed(drive, speed);
+	cs5535_set_speed(drive, drive->dma_mode);
 }
 
 /**
  *	cs5535_set_pio_mode	-	set host controller for PIO mode
+ *	@hwif: port
  *	@drive: drive
- *	@pio: PIO mode number
  *
  *	A callback from the upper layers for PIO-only tuning.
  */
 
-static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void cs5535_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	cs5535_set_speed(drive, XFER_PIO_0 + pio);
+	cs5535_set_speed(drive, drive->pio_mode);
 }
 
 static u8 cs5535_cable_detect(ide_hwif_t *hwif)
diff --git a/drivers/ide/cs5536.c b/drivers/ide/cs5536.c
index 9623b85..24214ab 100644
--- a/drivers/ide/cs5536.c
+++ b/drivers/ide/cs5536.c
@@ -125,11 +125,11 @@
 
 /**
  *	cs5536_set_pio_mode		-	PIO timing setup
+ *	@hwif: ATA port
  *	@drive: ATA device
- *	@pio: PIO mode number
  */
 
-static void cs5536_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void cs5536_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	static const u8 drv_timings[5] = {
 		0x98, 0x55, 0x32, 0x21, 0x20,
@@ -143,15 +143,16 @@
 		0x99, 0x92, 0x90, 0x22, 0x20,
 	};
 
-	struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 	ide_drive_t *pair = ide_get_pair_dev(drive);
 	int cshift = (drive->dn & 1) ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
 	unsigned long timings = (unsigned long)ide_get_drivedata(drive);
 	u32 cast;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 	u8 cmd_pio = pio;
 
 	if (pair)
-		cmd_pio = min(pio, ide_get_best_pio_mode(pair, 255, 4));
+		cmd_pio = min_t(u8, pio, pair->pio_mode - XFER_PIO_0);
 
 	timings &= (IDE_DRV_MASK << 8);
 	timings |= drv_timings[pio];
@@ -172,11 +173,11 @@
 
 /**
  *	cs5536_set_dma_mode		-	DMA timing setup
+ *	@hwif: ATA port
  *	@drive: ATA device
- *	@mode: DMA mode
  */
 
-static void cs5536_set_dma_mode(ide_drive_t *drive, const u8 mode)
+static void cs5536_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	static const u8 udma_timings[6] = {
 		0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6,
@@ -186,10 +187,11 @@
 		0x67, 0x21, 0x20,
 	};
 
-	struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 	int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT;
 	unsigned long timings = (unsigned long)ide_get_drivedata(drive);
 	u32 etc;
+	const u8 mode = drive->dma_mode;
 
 	cs5536_read(pdev, ETC, &etc);
 
diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c
index d6e2cbb..9383f67 100644
--- a/drivers/ide/cy82c693.c
+++ b/drivers/ide/cy82c693.c
@@ -1,43 +1,11 @@
 /*
  *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
  *  Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
+ *  Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
  *
  * CYPRESS CY82C693 chipset IDE controller
  *
  * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
- * Writing the driver was quite simple, since most of the job is
- * done by the generic pci-ide support.
- * The hard part was finding the CY82C693's datasheet on Cypress's
- * web page :-(. But Altavista solved this problem :-).
- *
- *
- * Notes:
- * - I recently got a 16.8G IBM DTTA, so I was able to test it with
- *   a large and fast disk - the results look great, so I'd say the
- *   driver is working fine :-)
- *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA
- * - this is my first linux driver, so there's probably a lot  of room
- *   for optimizations and bug fixing, so feel free to do it.
- * - if using PIO mode it's a good idea to set the PIO mode and
- *   32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda
- * - I had some problems with my IBM DHEA with PIO modes < 2
- *   (lost interrupts) ?????
- * - first tests with DMA look okay, they seem to work, but there is a
- *   problem with sound - the BusMaster IDE TimeOut should fixed this
- *
- * Ancient History:
- * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693
- * ASK@1999-01-23: v0.33 made a few minor code clean ups
- *                       removed DMA clock speed setting by default
- *                       added boot message
- * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut
- *                       added support to set DMA Controller Clock Speed
- * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes
- *                       on some drives.
- * ASK@1998-10-29: v0.3 added support to set DMA modes
- * ASK@1998-10-28: v0.2 added support to set PIO modes
- * ASK@1998-10-27: v0.1 first version - chipset detection
- *
  */
 
 #include <linux/module.h>
@@ -81,87 +49,13 @@
 #define CY82_INDEX_CHANNEL1	0x31
 #define CY82_INDEX_TIMEOUT	0x32
 
-/* the min and max PCI bus speed in MHz - from datasheet */
-#define CY82C963_MIN_BUS_SPEED	25
-#define CY82C963_MAX_BUS_SPEED	33
-
-/* the struct for the PIO mode timings */
-typedef struct pio_clocks_s {
-	u8	address_time;	/* Address setup (clocks) */
-	u8	time_16r;	/* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */
-	u8	time_16w;	/* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */
-	u8	time_8;		/* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */
-} pio_clocks_t;
-
-/*
- * calc clocks using bus_speed
- * returns (rounded up) time in bus clocks for time in ns
- */
-static int calc_clk(int time, int bus_speed)
-{
-	int clocks;
-
-	clocks = (time*bus_speed+999)/1000 - 1;
-
-	if (clocks < 0)
-		clocks = 0;
-
-	if (clocks > 0x0F)
-		clocks = 0x0F;
-
-	return clocks;
-}
-
-/*
- * compute the values for the clock registers for PIO
- * mode and pci_clk [MHz] speed
- *
- * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
- *       for mode 3 and 4 drives 8 and 16-bit timings are the same
- *
- */
-static void compute_clocks(u8 pio, pio_clocks_t *p_pclk)
-{
-	struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
-	int clk1, clk2;
-	int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
-
-	/* we don't check against CY82C693's min and max speed,
-	 * so you can play with the idebus=xx parameter
-	 */
-
-	/* let's calc the address setup time clocks */
-	p_pclk->address_time = (u8)calc_clk(t->setup, bus_speed);
-
-	/* let's calc the active and recovery time clocks */
-	clk1 = calc_clk(t->active, bus_speed);
-
-	/* calc recovery timing */
-	clk2 = t->cycle - t->active - t->setup;
-
-	clk2 = calc_clk(clk2, bus_speed);
-
-	clk1 = (clk1<<4)|clk2;	/* combine active and recovery clocks */
-
-	/* note: we use the same values for 16bit IOR and IOW
-	 *	those are all the same, since I don't have other
-	 *	timings than those from ide-lib.c
-	 */
-
-	p_pclk->time_16r = (u8)clk1;
-	p_pclk->time_16w = (u8)clk1;
-
-	/* what are good values for 8bit ?? */
-	p_pclk->time_8 = (u8)clk1;
-}
-
 /*
  * set DMA mode a specific channel for CY82C693
  */
 
-static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
+static void cy82c693_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
+	const u8 mode = drive->dma_mode;
 	u8 single = (mode & 0x10) >> 4, index = 0, data = 0;
 
 	index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
@@ -186,12 +80,14 @@
 	outb(data, CY82_DATA_PORT);
 }
 
-static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
-	pio_clocks_t pclk;
+	int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
+	const unsigned long T = 1000000 / bus_speed;
 	unsigned int addrCtrl;
+	struct ide_timing t;
+	u8 time_16, time_8;
 
 	/* select primary or secondary channel */
 	if (hwif->index > 0) {  /* drive is on the secondary channel */
@@ -204,8 +100,12 @@
 		}
 	}
 
-	/* let's calc the values for this PIO mode */
-	compute_clocks(pio, &pclk);
+	ide_timing_compute(drive, drive->pio_mode, &t, T, 1);
+
+	time_16 = clamp_val(t.recover - 1, 0, 15) |
+		  (clamp_val(t.active - 1, 0, 15) << 4);
+	time_8 = clamp_val(t.act8b - 1, 0, 15) |
+		 (clamp_val(t.rec8b - 1, 0, 15) << 4);
 
 	/* now let's write  the clocks registers */
 	if ((drive->dn & 1) == 0) {
@@ -217,13 +117,13 @@
 		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
 
 		addrCtrl &= (~0xF);
-		addrCtrl |= (unsigned int)pclk.address_time;
+		addrCtrl |= clamp_val(t.setup - 1, 0, 15);
 		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
 
 		/* now let's set the remaining registers */
-		pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
-		pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
-		pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
+		pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, time_16);
+		pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, time_16);
+		pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, time_8);
 	} else {
 		/*
 		 * set slave drive
@@ -233,13 +133,13 @@
 		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
 
 		addrCtrl &= (~0xF0);
-		addrCtrl |= ((unsigned int)pclk.address_time<<4);
+		addrCtrl |= (clamp_val(t.setup - 1, 0, 15) << 4);
 		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
 
 		/* now let's set the remaining registers */
-		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r);
-		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w);
-		pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8);
+		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, time_16);
+		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16);
+		pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8);
 	}
 }
 
@@ -325,6 +225,6 @@
 module_init(cy82c693_ide_init);
 module_exit(cy82c693_ide_exit);
 
-MODULE_AUTHOR("Andreas Krebs, Andre Hedrick");
+MODULE_AUTHOR("Andreas Krebs, Andre Hedrick, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("PCI driver module for the Cypress CY82C693 IDE");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
index c6b1381..6929f7f 100644
--- a/drivers/ide/dtc2278.c
+++ b/drivers/ide/dtc2278.c
@@ -68,11 +68,11 @@
 
 static DEFINE_SPINLOCK(dtc2278_lock);
 
-static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void dtc2278_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	unsigned long flags;
 
-	if (pio >= 3) {
+	if (drive->pio_mode >= XFER_PIO_3) {
 		spin_lock_irqsave(&dtc2278_lock, flags);
 		/*
 		 * This enables PIO mode4 (3?) on the first interface
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index 4d90ac2..b885c1d 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -627,14 +627,14 @@
 	return info->timings->clock_table[info->clock][i];
 }
 
-static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
+static void hpt3xx_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	struct hpt_info *info	= hpt3xx_get_info(hwif->dev);
 	struct hpt_timings *t	= info->timings;
 	u8  itr_addr		= 0x40 + (drive->dn * 4);
 	u32 old_itr		= 0;
+	const u8 speed		= drive->dma_mode;
 	u32 new_itr		= get_speed_setting(speed, info);
 	u32 itr_mask		= speed < XFER_MW_DMA_0 ? t->pio_mask :
 				 (speed < XFER_UDMA_0   ? t->dma_mask :
@@ -651,9 +651,10 @@
 	pci_write_config_dword(dev, itr_addr, new_itr);
 }
 
-static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void hpt3xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	hpt3xx_set_mode(drive, XFER_PIO_0 + pio);
+	drive->dma_mode = drive->pio_mode;
+	hpt3xx_set_mode(hwif, drive);
 }
 
 static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c
index aafed80..d81e496 100644
--- a/drivers/ide/ht6560b.c
+++ b/drivers/ide/ht6560b.c
@@ -279,9 +279,10 @@
 #endif
 }
 
-static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void ht6560b_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	unsigned long flags, config;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 	u8 timing;
 	
 	switch (pio) {
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index 0f67f1a..4a697a2 100644
--- a/drivers/ide/icside.c
+++ b/drivers/ide/icside.c
@@ -65,6 +65,8 @@
 };
 
 struct icside_state {
+	unsigned int channel;
+	unsigned int enabled;
 	void __iomem *irq_port;
 	void __iomem *ioc_base;
 	unsigned int sel;
@@ -114,11 +116,18 @@
 	struct icside_state *state = ec->irq_data;
 	void __iomem *base = state->irq_port;
 
-	writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
-	readb(base + ICS_ARCIN_V6_INTROFFSET_2);
+	state->enabled = 1;
 
-	writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
-	readb(base + ICS_ARCIN_V6_INTROFFSET_1);
+	switch (state->channel) {
+	case 0:
+		writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
+		readb(base + ICS_ARCIN_V6_INTROFFSET_2);
+		break;
+	case 1:
+		writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
+		readb(base + ICS_ARCIN_V6_INTROFFSET_1);
+		break;
+	}
 }
 
 /* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
@@ -128,6 +137,8 @@
 {
 	struct icside_state *state = ec->irq_data;
 
+	state->enabled = 0;
+
 	readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
 	readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
 }
@@ -149,6 +160,44 @@
 	.irqpending	= icside_irqpending_arcin_v6,
 };
 
+/*
+ * Handle routing of interrupts.  This is called before
+ * we write the command to the drive.
+ */
+static void icside_maskproc(ide_drive_t *drive, int mask)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct expansion_card *ec = ECARD_DEV(hwif->dev);
+	struct icside_state *state = ecard_get_drvdata(ec);
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	state->channel = hwif->channel;
+
+	if (state->enabled && !mask) {
+		switch (hwif->channel) {
+		case 0:
+			writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+			readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+			break;
+		case 1:
+			writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+			readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+			break;
+		}
+	} else {
+		readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+		readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+	}
+
+	local_irq_restore(flags);
+}
+
+static const struct ide_port_ops icside_v6_no_dma_port_ops = {
+	.maskproc		= icside_maskproc,
+};
+
 #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
 /*
  * SG-DMA support.
@@ -185,10 +234,11 @@
  *	MW1	80	50	50	150	C
  *	MW2	70	25	25	120	C
  */
-static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
+static void icside_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	unsigned long cycle_time;
 	int use_dma_info = 0;
+	const u8 xfer_mode = drive->dma_mode;
 
 	switch (xfer_mode) {
 	case XFER_MW_DMA_2:
@@ -228,6 +278,7 @@
 
 static const struct ide_port_ops icside_v6_port_ops = {
 	.set_dma_mode		= icside_set_dma_mode,
+	.maskproc		= icside_maskproc,
 };
 
 static void icside_dma_host_set(ide_drive_t *drive, int on)
@@ -272,6 +323,11 @@
 	BUG_ON(dma_channel_active(ec->dma));
 
 	/*
+	 * Ensure that we have the right interrupt routed.
+	 */
+	icside_maskproc(drive, 0);
+
+	/*
 	 * Route the DMA signals to the correct interface.
 	 */
 	writeb(state->sel | hwif->channel, state->ioc_base);
@@ -399,6 +455,7 @@
 
 static const struct ide_port_info icside_v6_port_info __initdata = {
 	.init_dma		= icside_dma_off_init,
+	.port_ops		= &icside_v6_no_dma_port_ops,
 	.dma_ops		= &icside_v6_dma_ops,
 	.host_flags		= IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
 	.mwdma_mask		= ATA_MWDMA2,
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index dd63963..ab87e4f 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -121,19 +121,11 @@
 static void ide_detach(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
-    ide_hwif_t *hwif = info->host->ports[0];
-    unsigned long data_addr, ctl_addr;
 
     dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);
 
-    data_addr = hwif->io_ports.data_addr;
-    ctl_addr  = hwif->io_ports.ctl_addr;
-
     ide_release(link);
 
-    release_region(ctl_addr, 1);
-    release_region(data_addr, 8);
-
     kfree(info);
 } /* ide_detach */
 
@@ -354,12 +346,19 @@
 
     dev_dbg(&link->dev, "ide_release(0x%p)\n", link);
 
-    if (info->ndev)
-	/* FIXME: if this fails we need to queue the cleanup somehow
-	   -- need to investigate the required PCMCIA magic */
-	ide_host_remove(host);
+    if (info->ndev) {
+	ide_hwif_t *hwif = host->ports[0];
+	unsigned long data_addr, ctl_addr;
 
-    info->ndev = 0;
+	data_addr = hwif->io_ports.data_addr;
+	ctl_addr = hwif->io_ports.ctl_addr;
+
+	ide_host_remove(host);
+	info->ndev = 0;
+
+	release_region(ctl_addr, 1);
+	release_region(data_addr, 8);
+    }
 
     pcmcia_disable_device(link);
 } /* ide_release */
diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c
index 1099bf7..c6935c7 100644
--- a/drivers/ide/ide-devsets.c
+++ b/drivers/ide/ide-devsets.c
@@ -105,15 +105,17 @@
 		return -ENOSYS;
 
 	if (set_pio_mode_abuse(drive->hwif, arg)) {
+		drive->pio_mode = arg + XFER_PIO_0;
+
 		if (arg == 8 || arg == 9) {
 			unsigned long flags;
 
 			/* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
 			spin_lock_irqsave(&hwif->lock, flags);
-			port_ops->set_pio_mode(drive, arg);
+			port_ops->set_pio_mode(hwif, drive);
 			spin_unlock_irqrestore(&hwif->lock, flags);
 		} else
-			port_ops->set_pio_mode(drive, arg);
+			port_ops->set_pio_mode(hwif, drive);
 	} else {
 		int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
 
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 222c1ef..376f2dc 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -231,7 +231,7 @@
 	u16 *id = drive->id;
 	int ivb = ide_in_drive_list(id, ivb_list);
 
-	if (hwif->cbl == ATA_CBL_PATA40_SHORT)
+	if (hwif->cbl == ATA_CBL_SATA || hwif->cbl == ATA_CBL_PATA40_SHORT)
 		return 1;
 
 	if (ivb)
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index f8c1ae6..fbedd35 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1042,6 +1042,8 @@
 		if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
 			drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
 
+		drive->pio_mode = XFER_PIO_0;
+
 		if (port_ops && port_ops->init_dev)
 			port_ops->init_dev(drive);
 	}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 6a0e625..b072328 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1365,7 +1365,7 @@
  * supported here, and not in the corresponding block interface. Our own
  * ide-tape ioctls are supported on both interfaces.
  */
-static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
+static long do_idetape_chrdev_ioctl(struct file *file,
 				unsigned int cmd, unsigned long arg)
 {
 	struct ide_tape_obj *tape = file->private_data;
@@ -1420,6 +1420,16 @@
 	}
 }
 
+static long idetape_chrdev_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	long ret;
+	lock_kernel();
+	ret = do_idetape_chrdev_ioctl(file, cmd, arg);
+	unlock_kernel();
+	return ret;
+}
+
 /*
  * Do a mode sense page 0 with block descriptor and if it succeeds set the tape
  * block size with the reported value.
@@ -1888,7 +1898,7 @@
 	.owner		= THIS_MODULE,
 	.read		= idetape_chrdev_read,
 	.write		= idetape_chrdev_write,
-	.ioctl		= idetape_chrdev_ioctl,
+	.unlocked_ioctl	= idetape_chrdev_ioctl,
 	.open		= idetape_chrdev_open,
 	.release	= idetape_chrdev_release,
 };
diff --git a/drivers/ide/ide-timings.c b/drivers/ide/ide-timings.c
index 001a563..0e05f75 100644
--- a/drivers/ide/ide-timings.c
+++ b/drivers/ide/ide-timings.c
@@ -166,12 +166,13 @@
 	if (id[ATA_ID_FIELD_VALID] & 2) {	/* EIDE drive */
 		memset(&p, 0, sizeof(p));
 
-		if (speed <= XFER_PIO_2)
-			p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
-		else if ((speed <= XFER_PIO_4) ||
-			 (speed == XFER_PIO_5 && !ata_id_is_cfa(id)))
-			p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
-		else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
+		if (speed >= XFER_PIO_0 && speed < XFER_SW_DMA_0) {
+			if (speed <= XFER_PIO_2)
+				p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO];
+			else if ((speed <= XFER_PIO_4) ||
+				 (speed == XFER_PIO_5 && !ata_id_is_cfa(id)))
+				p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY];
+		} else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
 			p.cycle = id[ATA_ID_EIDE_DMA_MIN];
 
 		ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B);
@@ -185,11 +186,10 @@
 	/*
 	 * Even in DMA/UDMA modes we still use PIO access for IDENTIFY,
 	 * S.M.A.R.T and some other commands. We have to ensure that the
-	 * DMA cycle timing is slower/equal than the fastest PIO timing.
+	 * DMA cycle timing is slower/equal than the current PIO timing.
 	 */
 	if (speed >= XFER_SW_DMA_0) {
-		u8 pio = ide_get_best_pio_mode(drive, 255, 5);
-		ide_timing_compute(drive, XFER_PIO_0 + pio, &p, T, UT);
+		ide_timing_compute(drive, drive->pio_mode, &p, T, UT);
 		ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
 	}
 
diff --git a/drivers/ide/ide-xfer-mode.c b/drivers/ide/ide-xfer-mode.c
index 46d203c..5fc8d5c 100644
--- a/drivers/ide/ide-xfer-mode.c
+++ b/drivers/ide/ide-xfer-mode.c
@@ -58,7 +58,7 @@
  *	This is used by most chipset support modules when "auto-tuning".
  */
 
-u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
+static u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
 {
 	u16 *id = drive->id;
 	int pio_mode = -1, overridden = 0;
@@ -105,7 +105,6 @@
 
 	return pio_mode;
 }
-EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
 
 int ide_pio_need_iordy(ide_drive_t *drive, const u8 pio)
 {
@@ -135,17 +134,20 @@
 	 * set transfer mode on the device in ->set_pio_mode method...
 	 */
 	if (port_ops->set_dma_mode == NULL) {
-		port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+		drive->pio_mode = mode;
+		port_ops->set_pio_mode(hwif, drive);
 		return 0;
 	}
 
 	if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
 		if (ide_config_drive_speed(drive, mode))
 			return -1;
-		port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+		drive->pio_mode = mode;
+		port_ops->set_pio_mode(hwif, drive);
 		return 0;
 	} else {
-		port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+		drive->pio_mode = mode;
+		port_ops->set_pio_mode(hwif, drive);
 		return ide_config_drive_speed(drive, mode);
 	}
 }
@@ -164,10 +166,12 @@
 	if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
 		if (ide_config_drive_speed(drive, mode))
 			return -1;
-		port_ops->set_dma_mode(drive, mode);
+		drive->dma_mode = mode;
+		port_ops->set_dma_mode(hwif, drive);
 		return 0;
 	} else {
-		port_ops->set_dma_mode(drive, mode);
+		drive->dma_mode = mode;
+		port_ops->set_dma_mode(hwif, drive);
 		return ide_config_drive_speed(drive, mode);
 	}
 }
diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c
index 0d266a5..560e66d 100644
--- a/drivers/ide/it8172.c
+++ b/drivers/ide/it8172.c
@@ -37,12 +37,12 @@
 
 #define DRV_NAME "IT8172"
 
-static void it8172_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void it8172_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u16 drive_enables;
 	u32 drive_timing;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	/*
 	 * The highest value of DIOR/DIOW pulse width and recovery time
@@ -77,14 +77,14 @@
 	pci_write_config_dword(dev, 0x44, drive_timing);
 }
 
-static void it8172_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void it8172_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int a_speed		= 3 << (drive->dn * 4);
 	int u_flag		= 1 << drive->dn;
 	int u_speed		= 0;
 	u8 reg48, reg4a;
+	const u8 speed		= drive->dma_mode;
 
 	pci_read_config_byte(dev, 0x48, &reg48);
 	pci_read_config_byte(dev, 0x4a, &reg4a);
@@ -98,14 +98,14 @@
 		pci_write_config_byte(dev, 0x4a, reg4a | u_speed);
 	} else {
 		const u8 mwdma_to_pio[] = { 0, 3, 4 };
-		u8 pio;
 
 		pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
 		pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed);
 
-		pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+		drive->pio_mode =
+			mwdma_to_pio[speed - XFER_MW_DMA_0] + XFER_PIO_0;
 
-		it8172_set_pio_mode(drive, pio);
+		it8172_set_pio_mode(hwif, drive);
 	}
 }
 
diff --git a/drivers/ide/it8213.c b/drivers/ide/it8213.c
index 4797616..46816ba 100644
--- a/drivers/ide/it8213.c
+++ b/drivers/ide/it8213.c
@@ -17,15 +17,14 @@
 
 /**
  *	it8213_set_pio_mode	-	set host controller for PIO mode
+ *	@hwif: port
  *	@drive: drive
- *	@pio: PIO mode number
  *
  *	Set the interface PIO mode.
  */
 
-static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void it8213_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int is_slave		= drive->dn & 1;
 	int master_port		= 0x40;
@@ -35,6 +34,7 @@
 	u8 slave_data;
 	static DEFINE_SPINLOCK(tune_lock);
 	int control = 0;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	static const u8 timings[][2] = {
 					{ 0, 0 },
@@ -74,15 +74,14 @@
 
 /**
  *	it8213_set_dma_mode	-	set host controller for DMA mode
+ *	@hwif: port
  *	@drive: drive
- *	@speed: DMA mode
  *
  *	Tune the ITE chipset for the DMA mode.
  */
 
-static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void it8213_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 maslave		= 0x40;
 	int a_speed		= 3 << (drive->dn * 4);
@@ -92,6 +91,7 @@
 	int u_speed		= 0;
 	u16			reg4042, reg4a;
 	u8			reg48, reg54, reg55;
+	const u8 speed		= drive->dma_mode;
 
 	pci_read_config_word(dev, maslave, &reg4042);
 	pci_read_config_byte(dev, 0x48, &reg48);
@@ -120,7 +120,6 @@
 			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
 	} else {
 		const u8 mwdma_to_pio[] = { 0, 3, 4 };
-		u8 pio;
 
 		if (reg48 & u_flag)
 			pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
@@ -132,11 +131,12 @@
 			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
 
 		if (speed >= XFER_MW_DMA_0)
-			pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+			drive->pio_mode =
+				mwdma_to_pio[speed - XFER_MW_DMA_0] + XFER_PIO_0;
 		else
-			pio = 2; /* only SWDMA2 is allowed */
+			drive->pio_mode = XFER_PIO_2; /* for SWDMA2 */
 
-		it8213_set_pio_mode(drive, pio);
+		it8213_set_pio_mode(hwif, drive);
 	}
 }
 
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c
index 51aa745..b2709c7 100644
--- a/drivers/ide/it821x.c
+++ b/drivers/ide/it821x.c
@@ -228,18 +228,18 @@
 
 /**
  *	it821x_set_pio_mode	-	set host controller for PIO mode
+ *	@hwif: port
  *	@drive: drive
- *	@pio: PIO mode number
  *
  *	Tune the host to the desired PIO mode taking into the consideration
  *	the maximum PIO mode supported by the other device on the cable.
  */
 
-static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void it821x_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
 	ide_drive_t *pair = ide_get_pair_dev(drive);
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 	u8 unit = drive->dn & 1, set_pio = pio;
 
 	/* Spec says 89 ref driver uses 88 */
@@ -252,7 +252,7 @@
 	 * on the cable.
 	 */
 	if (pair) {
-		u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4);
+		u8 pair_pio = pair->pio_mode - XFER_PIO_0;
 		/* trim PIO to the slowest of the master/slave */
 		if (pair_pio < set_pio)
 			set_pio = pair_pio;
@@ -393,14 +393,16 @@
 
 /**
  *	it821x_set_dma_mode	-	set host controller for DMA mode
+ *	@hwif: port
  *	@drive: drive
- *	@speed: DMA mode
  *
  *	Tune the ITE chipset for the desired DMA mode.
  */
 
-static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void it821x_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
+	const u8 speed = drive->dma_mode;
+
 	/*
 	 * MWDMA tuning is really hard because our MWDMA and PIO
 	 * timings are kept in the same place.  We can switch in the
diff --git a/drivers/ide/jmicron.c b/drivers/ide/jmicron.c
index bf2be64..74c2c4a 100644
--- a/drivers/ide/jmicron.c
+++ b/drivers/ide/jmicron.c
@@ -80,19 +80,19 @@
 	return ATA_CBL_PATA80;
 }
 
-static void jmicron_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void jmicron_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 }
 
 /**
  *	jmicron_set_dma_mode	-	set host controller for DMA mode
+ *	@hwif: port
  *	@drive: drive
- *	@mode: DMA mode
  *
  *	As the JMicron snoops for timings we don't need to do anything here.
  */
 
-static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode)
+static void jmicron_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 }
 
diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c
index f1d70d6..1a53a4c 100644
--- a/drivers/ide/opti621.c
+++ b/drivers/ide/opti621.c
@@ -8,77 +8,6 @@
  * Jan Harkes <jaharkes@cwi.nl>,
  * Mark Lord <mlord@pobox.com>
  * Some parts of code are from ali14xx.c and from rz1000.c.
- *
- * OPTi is trademark of OPTi, Octek is trademark of Octek.
- *
- * I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps
- * and disassembled/traced setupvic.exe (DOS program).
- * It increases kernel code about 2 kB.
- * I don't have this card no more, but I hope I can get some in case
- * of needed development.
- * My card is Octek PIDE 1.01 (on card) or OPTiViC (program).
- * It has a place for a secondary connector in circuit, but nothing
- * is there. Also BIOS says no address for
- * secondary controller (see bellow in ide_init_opti621).
- * I've only tested this on my system, which only has one disk.
- * It's Western Digital WDAC2850, with PIO mode 3. The PCI bus
- * is at 20 MHz (I have DX2/80, I tried PCI at 40, but I got random
- * lockups). I tried the OCTEK double speed CD-ROM and
- * it does not work! But I can't boot DOS also, so it's probably
- * hardware fault. I have connected Conner 80MB, the Seagate 850MB (no
- * problems) and Seagate 1GB (as slave, WD as master). My experiences
- * with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes
- * it slows to about 100kB/s! I don't know why and I have
- * not this drive now, so I can't try it again.
- * I write this driver because I lost the paper ("manual") with
- * settings of jumpers on the card and I have to boot Linux with
- * Loadlin except LILO, cause I have to run the setupvic.exe program
- * already or I get disk errors (my test: rpm -Vf
- * /usr/X11R6/bin/XF86_SVGA - or any big file).
- * Some numbers from hdparm -t /dev/hda:
- * Timing buffer-cache reads:   32 MB in  3.02 seconds =10.60 MB/sec
- * Timing buffered disk reads:  16 MB in  5.52 seconds = 2.90 MB/sec
- * I have 4 Megs/s before, but I don't know why (maybe changes
- * in hdparm test).
- * After release of 0.1, I got some successful reports, so it might work.
- *
- * The main problem with OPTi is that some timings for master
- * and slave must be the same. For example, if you have master
- * PIO 3 and slave PIO 0, driver have to set some timings of
- * master for PIO 0. Second problem is that opti621_set_pio_mode
- * got only one drive to set, but have to set both drives.
- * This is solved in compute_pios. If you don't set
- * the second drive, compute_pios use ide_get_best_pio_mode
- * for autoselect mode (you can change it to PIO 0, if you want).
- * If you then set the second drive to another PIO, the old value
- * (automatically selected) will be overrided by yours.
- * There is a 25/33MHz switch in configuration
- * register, but driver is written for use at any frequency.
- *
- * Version 0.1, Nov 8, 1996
- * by Jaromir Koutek, for 2.1.8.
- * Initial version of driver.
- *
- * Version 0.2
- * Number 0.2 skipped.
- *
- * Version 0.3, Nov 29, 1997
- * by Mark Lord (probably), for 2.1.68
- * Updates for use with new IDE block driver.
- *
- * Version 0.4, Dec 14, 1997
- * by Jan Harkes
- * Fixed some errors and cleaned the code.
- *
- * Version 0.5, Jan 2, 1998
- * by Jaromir Koutek
- * Updates for use with (again) new IDE block driver.
- * Update of documentation.
- *
- * Version 0.6, Jan 2, 1999
- * by Jaromir Koutek
- * Reversed to version 0.3 of the driver, because
- * 0.5 doesn't work.
  */
 
 #include <linux/types.h>
@@ -133,12 +62,12 @@
 	return ret;
 }
 
-static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void opti621_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	ide_drive_t *pair = ide_get_pair_dev(drive);
 	unsigned long flags;
-	unsigned long mode = XFER_PIO_0 + pio, pair_mode;
+	unsigned long mode = drive->pio_mode, pair_mode;
+	const u8 pio = mode - XFER_PIO_0;
 	u8 tim, misc, addr_pio = pio, clk;
 
 	/* DRDY is default 2 (by OPTi Databook) */
diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c
index f8eddf0..9e8f4e1 100644
--- a/drivers/ide/palm_bk3710.c
+++ b/drivers/ide/palm_bk3710.c
@@ -166,7 +166,7 @@
 	writel(val32, base + BK3710_DATRCVR);
 
 	if (mate) {
-		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
+		u8 mode2 = mate->pio_mode - XFER_PIO_0;
 
 		if (mode2 < mode)
 			mode = mode2;
@@ -188,10 +188,11 @@
 	writel(val32, base + BK3710_REGRCVR);
 }
 
-static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
+static void palm_bk3710_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	int is_slave = drive->dn & 1;
-	void __iomem *base = (void *)drive->hwif->dma_base;
+	void __iomem *base = (void *)hwif->dma_base;
+	const u8 xferspeed = drive->dma_mode;
 
 	if (xferspeed >= XFER_UDMA_0) {
 		palm_bk3710_setudmamode(base, is_slave,
@@ -203,12 +204,13 @@
 	}
 }
 
-static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
+static void palm_bk3710_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	unsigned int cycle_time;
 	int is_slave = drive->dn & 1;
 	ide_drive_t *mate;
-	void __iomem *base = (void *)drive->hwif->dma_base;
+	void __iomem *base = (void *)hwif->dma_base;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	/*
 	 * Obtain the drive PIO data for tuning the Palm Chip registers
diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c
index 65ba823..9546fe2 100644
--- a/drivers/ide/pdc202xx_new.c
+++ b/drivers/ide/pdc202xx_new.c
@@ -129,11 +129,11 @@
 	{ 0x1a, 0x01, 0xcb },	/* UDMA mode 6 */
 };
 
-static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void pdcnew_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 adj			= (drive->dn & 1) ? 0x08 : 0x00;
+	const u8 speed		= drive->dma_mode;
 
 	/*
 	 * IDE core issues SETFEATURES_XFER to the drive first (thanks to
@@ -167,11 +167,11 @@
  	}
 }
 
-static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void pdcnew_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	if (max_dma_rate(dev) == 4) {
 		set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c);
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c
index 35161dd..c5f3841 100644
--- a/drivers/ide/pdc202xx_old.c
+++ b/drivers/ide/pdc202xx_old.c
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1998-2002		Andre Hedrick <andre@linux-ide.org>
  *  Copyright (C) 2006-2007, 2009	MontaVista Software, Inc.
- *  Copyright (C) 2007			Bartlomiej Zolnierkiewicz
+ *  Copyright (C) 2007-2010		Bartlomiej Zolnierkiewicz
  *
  *  Portions Copyright (C) 1999 Promise Technology, Inc.
  *  Author: Frank Tiernan (frankt@promise.com)
@@ -21,23 +21,15 @@
 
 #define DRV_NAME "pdc202xx_old"
 
-static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
-
-static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
+static void pdc202xx_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 drive_pci		= 0x60 + (drive->dn << 2);
+	const u8 speed		= drive->dma_mode;
 
 	u8			AP = 0, BP = 0, CP = 0;
 	u8			TA = 0, TB = 0, TC = 0;
 
-	/*
-	 * TODO: do this once per channel
-	 */
-	if (dev->device != PCI_DEVICE_ID_PROMISE_20246)
-		pdc_old_disable_66MHz_clock(hwif);
-
 	pci_read_config_byte(dev, drive_pci,     &AP);
 	pci_read_config_byte(dev, drive_pci + 1, &BP);
 	pci_read_config_byte(dev, drive_pci + 2, &CP);
@@ -84,9 +76,10 @@
 	}
 }
 
-static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void pdc202xx_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
+	drive->dma_mode = drive->pio_mode;
+	pdc202xx_set_mode(hwif, drive);
 }
 
 static int pdc202xx_test_irq(ide_hwif_t *hwif)
@@ -100,13 +93,13 @@
 		 * bit 7: error, bit 6: interrupting,
 		 * bit 5: FIFO full, bit 4: FIFO empty
 		 */
-		return ((sc1d & 0x50) == 0x40) ? 1 : 0;
+		return ((sc1d & 0x50) == 0x50) ? 1 : 0;
 	} else	{
 		/*
 		 * bit 3: error, bit 2: interrupting,
 		 * bit 1: FIFO full, bit 0: FIFO empty
 		 */
-		return ((sc1d & 0x05) == 0x04) ? 1 : 0;
+		return ((sc1d & 0x05) == 0x05) ? 1 : 0;
 	}
 }
 
@@ -145,6 +138,11 @@
 	outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
 }
 
+static void pdc2026x_init_hwif(ide_hwif_t *hwif)
+{
+	pdc_old_disable_66MHz_clock(hwif);
+}
+
 static void pdc202xx_dma_start(ide_drive_t *drive)
 {
 	if (drive->current_speed > XFER_UDMA_2)
@@ -261,6 +259,7 @@
 	{ \
 		.name		= DRV_NAME, \
 		.init_chipset	= init_chipset_pdc202xx, \
+		.init_hwif	= pdc2026x_init_hwif, \
 		.port_ops	= &pdc2026x_port_ops, \
 		.dma_ops	= &pdc2026x_dma_ops, \
 		.host_flags	= IDE_HFLAGS_PDC202XX, \
@@ -356,6 +355,6 @@
 module_init(pdc202xx_ide_init);
 module_exit(pdc202xx_ide_exit);
 
-MODULE_AUTHOR("Andre Hedrick, Frank Tiernan");
+MODULE_AUTHOR("Andre Hedrick, Frank Tiernan, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("PCI driver module for older Promise IDE");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
index bf14f39..1bdca49 100644
--- a/drivers/ide/piix.c
+++ b/drivers/ide/piix.c
@@ -59,15 +59,14 @@
 
 /**
  *	piix_set_pio_mode	-	set host controller for PIO mode
+ *	@port: port
  *	@drive: drive
- *	@pio: PIO mode number
  *
  *	Set the interface PIO mode based upon the settings done by AMI BIOS.
  */
 
-static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void piix_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int is_slave		= drive->dn & 1;
 	int master_port		= hwif->channel ? 0x42 : 0x40;
@@ -77,6 +76,7 @@
 	u8 slave_data;
 	static DEFINE_SPINLOCK(tune_lock);
 	int control = 0;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 				     /* ISP  RTC */
 	static const u8 timings[][2]= {
@@ -127,16 +127,15 @@
 
 /**
  *	piix_set_dma_mode	-	set host controller for DMA mode
+ *	@hwif: port
  *	@drive: drive
- *	@speed: DMA mode
  *
  *	Set a PIIX host controller to the desired DMA mode.  This involves
  *	programming the right timing data into the PCI configuration space.
  */
 
-static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void piix_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 maslave		= hwif->channel ? 0x42 : 0x40;
 	int a_speed		= 3 << (drive->dn * 4);
@@ -147,6 +146,7 @@
 	int			sitre;
 	u16			reg4042, reg4a;
 	u8			reg48, reg54, reg55;
+	const u8 speed		= drive->dma_mode;
 
 	pci_read_config_word(dev, maslave, &reg4042);
 	sitre = (reg4042 & 0x4000) ? 1 : 0;
@@ -176,7 +176,6 @@
 			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
 	} else {
 		const u8 mwdma_to_pio[] = { 0, 3, 4 };
-		u8 pio;
 
 		if (reg48 & u_flag)
 			pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
@@ -188,11 +187,12 @@
 			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
 
 		if (speed >= XFER_MW_DMA_0)
-			pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+			drive->pio_mode =
+				mwdma_to_pio[speed - XFER_MW_DMA_0] + XFER_PIO_0;
 		else
-			pio = 2; /* only SWDMA2 is allowed */
+			drive->pio_mode = XFER_PIO_2; /* for SWDMA2 */
 
-		piix_set_pio_mode(drive, pio);
+		piix_set_pio_mode(hwif, drive);
 	}
 }
 
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c
index 7a4e788..850ee45 100644
--- a/drivers/ide/pmac.c
+++ b/drivers/ide/pmac.c
@@ -496,12 +496,11 @@
 /*
  * Old tuning functions (called on hdparm -p), sets up drive PIO timings
  */
-static void
-pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void pmac_ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	pmac_ide_hwif_t *pmif =
 		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 	struct ide_timing *tim = ide_timing_find_mode(XFER_PIO_0 + pio);
 	u32 *timings, t;
 	unsigned accessTicks, recTicks;
@@ -778,14 +777,14 @@
 #endif	
 }
 
-static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void pmac_ide_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	pmac_ide_hwif_t *pmif =
 		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	int ret = 0;
 	u32 *timings, *timings2, tl[2];
 	u8 unit = drive->dn & 1;
+	const u8 speed = drive->dma_mode;
 
 	timings = &pmif->timings[unit];
 	timings2 = &pmif->timings[unit+2];
@@ -1651,8 +1650,8 @@
 		if ((status & FLUSH) == 0)
 			break;
 		if (++timeout > 100) {
-			printk(KERN_WARNING "ide%d, ide_dma_test_irq \
-			timeout flushing channel\n", hwif->index);
+			printk(KERN_WARNING "ide%d, ide_dma_test_irq timeout flushing channel\n",
+			       hwif->index);
 			break;
 		}
 	}	
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
index 74696ed..3f0244f 100644
--- a/drivers/ide/qd65xx.c
+++ b/drivers/ide/qd65xx.c
@@ -189,15 +189,13 @@
 	printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
 }
 
-static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void qd6500_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	u16 *id = drive->id;
 	int active_time   = 175;
 	int recovery_time = 415; /* worst case values from the dos driver */
 
-	/*
-	 * FIXME: use "pio" value
-	 */
+	/* FIXME: use drive->pio_mode value */
 	if (!qd_find_disk_type(drive, &active_time, &recovery_time) &&
 	    (id[ATA_ID_OLD_PIO_MODES] & 0xff) && (id[ATA_ID_FIELD_VALID] & 2) &&
 	    id[ATA_ID_EIDE_PIO] >= 240) {
@@ -211,9 +209,9 @@
 				active_time, recovery_time));
 }
 
-static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void qd6580_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 	struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
 	unsigned int cycle_time;
 	int active_time   = 175;
diff --git a/drivers/ide/sc1200.c b/drivers/ide/sc1200.c
index d467478..134f1fd 100644
--- a/drivers/ide/sc1200.c
+++ b/drivers/ide/sc1200.c
@@ -122,13 +122,13 @@
 	return mask;
 }
 
-static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
+static void sc1200_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t		*hwif = drive->hwif;
 	struct pci_dev		*dev = to_pci_dev(hwif->dev);
 	unsigned int		reg, timings;
 	unsigned short		pci_clock;
 	unsigned int		basereg = hwif->channel ? 0x50 : 0x40;
+	const u8		mode = drive->dma_mode;
 
 	static const u32 udma_timing[3][3] = {
 		{ 0x00921250, 0x00911140, 0x00911030 },
@@ -193,10 +193,10 @@
  * will have valid default PIO timings set up before we get here.
  */
 
-static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void sc1200_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t	*hwif = drive->hwif;
 	int		mode = -1;
+	const u8	pio = drive->pio_mode - XFER_PIO_0;
 
 	/*
 	 * bad abuse of ->set_pio_mode interface
diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c
index 1104bb3..b7f5b0c 100644
--- a/drivers/ide/scc_pata.c
+++ b/drivers/ide/scc_pata.c
@@ -199,16 +199,15 @@
 
 /**
  *	scc_set_pio_mode	-	set host controller for PIO mode
+ *	@hwif: port
  *	@drive: drive
- *	@pio: PIO mode number
  *
  *	Load the timing settings for this device mode into the
  *	controller.
  */
 
-static void scc_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void scc_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	struct scc_ports *ports = ide_get_hwifdata(hwif);
 	unsigned long ctl_base = ports->ctl;
 	unsigned long cckctrl_port = ctl_base + 0xff0;
@@ -216,6 +215,7 @@
 	unsigned long pioct_port = ctl_base + 0x004;
 	unsigned long reg;
 	int offset;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	reg = in_be32((void __iomem *)cckctrl_port);
 	if (reg & CCKCTRL_ATACLKOEN) {
@@ -231,16 +231,15 @@
 
 /**
  *	scc_set_dma_mode	-	set host controller for DMA mode
+ *	@hwif: port
  *	@drive: drive
- *	@speed: DMA mode
  *
  *	Load the timing settings for this device mode into the
  *	controller.
  */
 
-static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void scc_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	struct scc_ports *ports = ide_get_hwifdata(hwif);
 	unsigned long ctl_base = ports->ctl;
 	unsigned long cckctrl_port = ctl_base + 0xff0;
@@ -254,6 +253,7 @@
 	int offset, idx;
 	unsigned long reg;
 	unsigned long jcactsel;
+	const u8 speed = drive->dma_mode;
 
 	reg = in_be32((void __iomem *)cckctrl_port);
 	if (reg & CCKCTRL_ATACLKOEN) {
@@ -872,20 +872,18 @@
 	.remove = __devexit_p(scc_remove),
 };
 
-static int scc_ide_init(void)
+static int __init scc_ide_init(void)
 {
 	return ide_pci_register_driver(&scc_pci_driver);
 }
 
-module_init(scc_ide_init);
-/* -- No exit code?
-static void scc_ide_exit(void)
+static void __exit scc_ide_exit(void)
 {
-	ide_pci_unregister_driver(&scc_pci_driver);
+	pci_unregister_driver(&scc_pci_driver);
 }
-module_exit(scc_ide_exit);
- */
 
+module_init(scc_ide_init);
+module_exit(scc_ide_exit);
 
 MODULE_DESCRIPTION("PCI driver module for Toshiba SCC IDE");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
index b6554ef..35fb8da 100644
--- a/drivers/ide/serverworks.c
+++ b/drivers/ide/serverworks.c
@@ -2,7 +2,7 @@
  * Copyright (C) 1998-2000 Michel Aubry
  * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
  * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
+ * Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
  * Portions copyright (c) 2001 Sun Microsystems
  *
  *
@@ -52,8 +52,6 @@
 	NULL
 };
 
-static struct pci_dev *isa_dev;
-
 static int check_in_drive_lists (ide_drive_t *drive, const char **list)
 {
 	char *m = (char *)&drive->id[ATA_ID_PROD];
@@ -67,26 +65,14 @@
 static u8 svwks_udma_filter(ide_drive_t *drive)
 {
 	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-	u8 mask = 0;
 
-	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
+	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) {
 		return 0x1f;
-	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
-		u32 reg = 0;
-		if (isa_dev)
-			pci_read_config_dword(isa_dev, 0x64, &reg);
-			
-		/*
-		 *	Don't enable UDMA on disk devices for the moment
-		 */
-		if(drive->media == ide_disk)
-			return 0;
-		/* Check the OSB4 DMA33 enable bit */
-		return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0;
 	} else if (dev->revision < SVWKS_CSB5_REVISION_NEW) {
 		return 0x07;
-	} else if (dev->revision >= SVWKS_CSB5_REVISION_NEW) {
-		u8 btr = 0, mode;
+	} else {
+		u8 btr = 0, mode, mask;
+
 		pci_read_config_byte(dev, 0x5A, &btr);
 		mode = btr & 0x3;
 
@@ -101,13 +87,9 @@
 		case 1:	 mask = 0x07; break;
 		default: mask = 0x00; break;
 		}
-	}
-	if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
-	     (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) &&
-	    (!(PCI_FUNC(dev->devfn) & 1)))
-		mask = 0x1f;
 
-	return mask;
+		return mask;
+	}
 }
 
 static u8 svwks_csb_check (struct pci_dev *dev)
@@ -124,12 +106,13 @@
 	return 0;
 }
 
-static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void svwks_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
 	static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 };
 
-	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]);
 
@@ -145,14 +128,14 @@
 	}
 }
 
-static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void svwks_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	static const u8 udma_modes[]		= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
 	static const u8 dma_modes[]		= { 0x77, 0x21, 0x20 };
 	static const u8 drive_pci2[]		= { 0x45, 0x44, 0x47, 0x46 };
 
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+	const u8 speed		= drive->dma_mode;
 	u8 unit			= drive->dn & 1;
 
 	u8 ultra_enable	 = 0, ultra_timing = 0, dma_timing = 0;
@@ -185,8 +168,9 @@
 
 	/* OSB4 : South Bridge and IDE */
 	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
-		isa_dev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
-			  PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
+		struct pci_dev *isa_dev =
+			pci_get_device(PCI_VENDOR_ID_SERVERWORKS,
+					PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
 		if (isa_dev) {
 			pci_read_config_dword(isa_dev, 0x64, &reg);
 			reg &= ~0x00002000; /* disable 600ns interrupt mask */
@@ -195,6 +179,7 @@
 					"enabled.\n", pci_name(dev));
 			reg |=  0x00004000; /* enable UDMA/33 support */
 			pci_write_config_dword(isa_dev, 0x64, reg);
+			pci_dev_put(isa_dev);
 		}
 	}
 
@@ -343,7 +328,6 @@
 static const struct ide_port_ops osb4_port_ops = {
 	.set_pio_mode		= svwks_set_pio_mode,
 	.set_dma_mode		= svwks_set_dma_mode,
-	.udma_filter		= svwks_udma_filter,
 };
 
 static const struct ide_port_ops svwks_port_ops = {
@@ -460,6 +444,6 @@
 module_init(svwks_ide_init);
 module_exit(svwks_ide_exit);
 
-MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick");
+MODULE_AUTHOR("Michael Aubry. Andrzej Krzysztofowicz, Andre Hedrick, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("PCI driver module for Serverworks OSB4/CSB5/CSB6 IDE");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c
index b7d61dc..e3ea591 100644
--- a/drivers/ide/sgiioc4.c
+++ b/drivers/ide/sgiioc4.c
@@ -255,7 +255,7 @@
 	return dma_stat;
 }
 
-static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void sgiioc4_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 }
 
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c
index d95df52..ddeda44 100644
--- a/drivers/ide/siimage.c
+++ b/drivers/ide/siimage.c
@@ -229,19 +229,18 @@
 
 /**
  *	sil_set_pio_mode	-	set host controller for PIO mode
+ *	@hwif: port
  *	@drive: drive
- *	@pio: PIO mode number
  *
  *	Load the timing settings for this device mode into the
  *	controller.
  */
 
-static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
+static void sil_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	static const u16 tf_speed[]   = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
 	static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
 
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	ide_drive_t *pair	= ide_get_pair_dev(drive);
 	u32 speedt		= 0;
@@ -249,6 +248,7 @@
 	unsigned long addr	= siimage_seldev(drive, 0x04);
 	unsigned long tfaddr	= siimage_selreg(hwif,	0x02);
 	unsigned long base	= (unsigned long)hwif->hwif_data;
+	const u8 pio		= drive->pio_mode - XFER_PIO_0;
 	u8 tf_pio		= pio;
 	u8 mmio			= (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
 	u8 addr_mask		= hwif->channel ? (mmio ? 0xF4 : 0x84)
@@ -258,7 +258,7 @@
 
 	/* trim *taskfile* PIO to the slowest of the master/slave */
 	if (pair) {
-		u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4);
+		u8 pair_pio = pair->pio_mode - XFER_PIO_0;
 
 		if (pair_pio < tf_pio)
 			tf_pio = pair_pio;
@@ -289,19 +289,18 @@
 
 /**
  *	sil_set_dma_mode	-	set host controller for DMA mode
+ *	@hwif: port
  *	@drive: drive
- *	@speed: DMA mode
  *
  *	Tune the SiI chipset for the desired DMA mode.
  */
 
-static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void sil_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	static const u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 };
 	static const u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 };
 	static const u16 dma[]	 = { 0x2208, 0x10C2, 0x10C1 };
 
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	unsigned long base	= (unsigned long)hwif->hwif_data;
 	u16 ultra = 0, multi	= 0;
@@ -311,6 +310,7 @@
 						: (mmio ? 0xB4 : 0x80);
 	unsigned long ma	= siimage_seldev(drive, 0x08);
 	unsigned long ua	= siimage_seldev(drive, 0x0C);
+	const u8 speed		= drive->dma_mode;
 
 	scsc  = sil_ioread8 (dev, base + (mmio ? 0x4A : 0x8A));
 	mode  = sil_ioread8 (dev, base + addr_mask);
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
index 4687060..db7f4e7 100644
--- a/drivers/ide/sis5513.c
+++ b/drivers/ide/sis5513.c
@@ -290,10 +290,10 @@
 		pci_write_config_byte(dev, 0x4b, rw_prefetch);
 }
 
-static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void sis_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	config_drive_art_rwp(drive);
-	sis_program_timings(drive, XFER_PIO_0 + pio);
+	sis_program_timings(drive, drive->pio_mode);
 }
 
 static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
@@ -340,8 +340,10 @@
 		sis_ata33_program_udma_timings(drive, mode);
 }
 
-static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void sis_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
+	const u8 speed = drive->dma_mode;
+
 	if (speed >= XFER_UDMA_0)
 		sis_program_udma_timings(drive, speed);
 	else
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
index 3c2bbf0..f21dc2a 100644
--- a/drivers/ide/sl82c105.c
+++ b/drivers/ide/sl82c105.c
@@ -63,12 +63,13 @@
 /*
  * Configure the chipset for PIO mode.
  */
-static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void sl82c105_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	unsigned long timings	= (unsigned long)ide_get_drivedata(drive);
 	int reg			= 0x44 + drive->dn * 4;
 	u16 drv_ctrl;
+	const u8 pio		= drive->pio_mode - XFER_PIO_0;
 
 	drv_ctrl = get_pio_timings(drive, pio);
 
@@ -91,11 +92,12 @@
 /*
  * Configure the chipset for DMA mode.
  */
-static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void sl82c105_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200};
 	unsigned long timings = (unsigned long)ide_get_drivedata(drive);
 	u16 drv_ctrl;
+	const u8 speed = drive->dma_mode;
 
 	drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
 
diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c
index 1ccfb40..864ffe0 100644
--- a/drivers/ide/slc90e66.c
+++ b/drivers/ide/slc90e66.c
@@ -18,9 +18,8 @@
 
 static DEFINE_SPINLOCK(slc90e66_lock);
 
-static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void slc90e66_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	int is_slave		= drive->dn & 1;
 	int master_port		= hwif->channel ? 0x42 : 0x40;
@@ -29,6 +28,8 @@
 	u16 master_data;
 	u8 slave_data;
 	int control = 0;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
+
 				     /* ISP  RTC */
 	static const u8 timings[][2] = {
 					{ 0, 0 },
@@ -71,14 +72,14 @@
 	spin_unlock_irqrestore(&slc90e66_lock, flags);
 }
 
-static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void slc90e66_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	struct pci_dev *dev	= to_pci_dev(hwif->dev);
 	u8 maslave		= hwif->channel ? 0x42 : 0x40;
 	int sitre = 0, a_speed	= 7 << (drive->dn * 4);
 	int u_speed = 0, u_flag = 1 << drive->dn;
 	u16			reg4042, reg44, reg48, reg4a;
+	const u8 speed		= drive->dma_mode;
 
 	pci_read_config_word(dev, maslave, &reg4042);
 	sitre = (reg4042 & 0x4000) ? 1 : 0;
@@ -98,7 +99,6 @@
 		}
 	} else {
 		const u8 mwdma_to_pio[] = { 0, 3, 4 };
-		u8 pio;
 
 		if (reg48 & u_flag)
 			pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
@@ -106,11 +106,12 @@
 			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
 
 		if (speed >= XFER_MW_DMA_0)
-			pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+			drive->pio_mode =
+				mwdma_to_pio[speed - XFER_MW_DMA_0] + XFER_PIO_0;
 		else
-			pio = 2; /* only SWDMA2 is allowed */
+			drive->pio_mode = XFER_PIO_2; /* for SWDMA2 */
 
-		slc90e66_set_pio_mode(drive, pio);
+		slc90e66_set_pio_mode(hwif, drive);
 	}
 }
 
diff --git a/drivers/ide/tc86c001.c b/drivers/ide/tc86c001.c
index 05a93d6b..e444d24 100644
--- a/drivers/ide/tc86c001.c
+++ b/drivers/ide/tc86c001.c
@@ -13,11 +13,11 @@
 
 #define DRV_NAME "tc86c001"
 
-static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
+static void tc86c001_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= drive->hwif;
 	unsigned long scr_port	= hwif->config_data + (drive->dn ? 0x02 : 0x00);
 	u16 mode, scr		= inw(scr_port);
+	const u8 speed		= drive->dma_mode;
 
 	switch (speed) {
 	case XFER_UDMA_4:	mode = 0x00c0; break;
@@ -41,9 +41,10 @@
 	outw(scr, scr_port);
 }
 
-static void tc86c001_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void tc86c001_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	tc86c001_set_mode(drive, XFER_PIO_0 + pio);
+	drive->dma_mode = drive->pio_mode;
+	tc86c001_set_mode(hwif, drive);
 }
 
 /*
diff --git a/drivers/ide/triflex.c b/drivers/ide/triflex.c
index 8773c3b..7953447 100644
--- a/drivers/ide/triflex.c
+++ b/drivers/ide/triflex.c
@@ -34,9 +34,8 @@
 
 #define DRV_NAME "triflex"
 
-static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
+static void triflex_set_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	u32 triflex_timings = 0;
 	u16 timing = 0;
@@ -44,7 +43,7 @@
 
 	pci_read_config_dword(dev, channel_offset, &triflex_timings);
 
-	switch(speed) {
+	switch (drive->dma_mode) {
 		case XFER_MW_DMA_2:
 			timing = 0x0103; 
 			break;
@@ -82,9 +81,10 @@
 	pci_write_config_dword(dev, channel_offset, triflex_timings);
 }
 
-static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void triflex_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	triflex_set_mode(drive, XFER_PIO_0 + pio);
+	drive->dma_mode = drive->pio_mode;
+	triflex_set_mode(hwif, drive);
 }
 
 static const struct ide_port_ops triflex_port_ops = {
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c
index fd59c0d..1d80f1f 100644
--- a/drivers/ide/tx4938ide.c
+++ b/drivers/ide/tx4938ide.c
@@ -56,16 +56,15 @@
 		     &tx4938_ebuscptr->cr[ebus_ch]);
 }
 
-static void tx4938ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void tx4938ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	struct tx4938ide_platform_info *pdata = hwif->dev->platform_data;
-	u8 safe = pio;
+	u8 safe = drive->pio_mode - XFER_PIO_0;
 	ide_drive_t *pair;
 
 	pair = ide_get_pair_dev(drive);
 	if (pair)
-		safe = min(safe, ide_get_best_pio_mode(pair, 255, 5));
+		safe = min(safe, pair->pio_mode - XFER_PIO_0);
 	tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, safe);
 }
 
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c
index 64b58ec..3c73677 100644
--- a/drivers/ide/tx4939ide.c
+++ b/drivers/ide/tx4939ide.c
@@ -104,17 +104,17 @@
 
 #define TX4939IDE_BASE(hwif)	((void __iomem *)(hwif)->extra_base)
 
-static void tx4939ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void tx4939ide_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	int is_slave = drive->dn;
 	u32 mask, val;
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 	u8 safe = pio;
 	ide_drive_t *pair;
 
 	pair = ide_get_pair_dev(drive);
 	if (pair)
-		safe = min(safe, ide_get_best_pio_mode(pair, 255, 4));
+		safe = min(safe, pair->pio_mode - XFER_PIO_0);
 	/*
 	 * Update Command Transfer Mode for master/slave and Data
 	 * Transfer Mode for this drive.
@@ -125,10 +125,10 @@
 	/* tx4939ide_tf_load_fixup() will set the Sys_Ctl register */
 }
 
-static void tx4939ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
+static void tx4939ide_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	u32 mask, val;
+	const u8 mode = drive->dma_mode;
 
 	/* Update Data Transfer Mode for this drive. */
 	if (mode >= XFER_UDMA_0)
diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c
index 60f936e..47adcd0 100644
--- a/drivers/ide/umc8672.c
+++ b/drivers/ide/umc8672.c
@@ -104,10 +104,11 @@
 		speeds[0], speeds[1], speeds[2], speeds[3]);
 }
 
-static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void umc_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif, *mate = hwif->mate;
+	ide_hwif_t *mate = hwif->mate;
 	unsigned long uninitialized_var(flags);
+	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
 		drive->name, pio, pio_to_umc[pio]);
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index 028de26..e65d010 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -6,7 +6,7 @@
  *   vt8235, vt8237, vt8237a
  *
  * Copyright (c) 2000-2002 Vojtech Pavlik
- * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
+ * Copyright (c) 2007-2010 Bartlomiej Zolnierkiewicz
  *
  * Based on the work of:
  *	Michel Aubry
@@ -54,6 +54,11 @@
 #define VIA_NO_UNMASK		0x08 /* Doesn't work with IRQ unmasking on */
 #define VIA_BAD_ID		0x10 /* Has wrong vendor ID (0x1107) */
 #define VIA_BAD_AST		0x20 /* Don't touch Address Setup Timing */
+#define VIA_SATA_PATA		0x80 /* SATA/PATA combined configuration */
+
+enum {
+	VIA_IDFLAG_SINGLE = (1 << 1), /* single channel controller */
+};
 
 /*
  * VIA SouthBridge chips.
@@ -67,11 +72,13 @@
 	u8 udma_mask;
 	u8 flags;
 } via_isa_bridges[] = {
-	{ "vx855",	PCI_DEVICE_ID_VIA_VX855,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-	{ "vx800",	PCI_DEVICE_ID_VIA_VX800,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
-	{ "cx700",	PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vx855",	PCI_DEVICE_ID_VIA_VX855,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST | VIA_SATA_PATA },
+	{ "vx800",	PCI_DEVICE_ID_VIA_VX800,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST | VIA_SATA_PATA },
+	{ "cx700",	PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST | VIA_SATA_PATA },
+	{ "vt8261",	PCI_DEVICE_ID_VIA_8261,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
 	{ "vt8237s",	PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
 	{ "vt6410",	PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+	{ "vt6415",	PCI_DEVICE_ID_VIA_6410,     0x00, 0xff, ATA_UDMA6, VIA_BAD_AST },
 	{ "vt8251",	PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
 	{ "vt8237",	PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
 	{ "vt8237a",	PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
@@ -92,6 +99,7 @@
 	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f,      0x00, VIA_SET_FIFO },
 	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f,      0x00, VIA_SET_FIFO | VIA_NO_UNMASK },
 	{ "vt82c576",	PCI_DEVICE_ID_VIA_82C576,   0x00, 0x2f,      0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
+	{ "vtxxxx",	PCI_DEVICE_ID_VIA_ANON,     0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
 	{ NULL }
 };
 
@@ -102,6 +110,7 @@
 {
 	struct via_isa_bridge *via_config;
 	unsigned int via_80w;
+	u8 cached_device[2];
 };
 
 /**
@@ -137,30 +146,45 @@
 	case ATA_UDMA4: t = timing->udma ? (0xe8 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x0f; break;
 	case ATA_UDMA5: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break;
 	case ATA_UDMA6: t = timing->udma ? (0xe0 | (clamp_val(timing->udma, 2, 9) - 2)) : 0x07; break;
-	default: return;
 	}
 
-	pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t);
+	/* Set UDMA unless device is not UDMA capable */
+	if (vdev->via_config->udma_mask) {
+		u8 udma_etc;
+
+		pci_read_config_byte(dev, VIA_UDMA_TIMING + 3 - dn, &udma_etc);
+
+		/* clear transfer mode bit */
+		udma_etc &= ~0x20;
+
+		if (timing->udma) {
+			/* preserve 80-wire cable detection bit */
+			udma_etc &= 0x10;
+			udma_etc |= t;
+		}
+
+		pci_write_config_byte(dev, VIA_UDMA_TIMING + 3 - dn, udma_etc);
+	}
 }
 
 /**
  *	via_set_drive		-	configure transfer mode
+ *	@hwif: port
  *	@drive: Drive to set up
- *	@speed: desired speed
  *
  *	via_set_drive() computes timing values configures the chipset to
  *	a desired transfer mode.  It also can be called by upper layers.
  */
 
-static void via_set_drive(ide_drive_t *drive, const u8 speed)
+static void via_set_drive(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	ide_drive_t *peer = ide_get_pair_dev(drive);
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	struct ide_host *host = pci_get_drvdata(dev);
 	struct via82cxxx_dev *vdev = host->host_priv;
 	struct ide_timing t, p;
 	unsigned int T, UT;
+	const u8 speed = drive->dma_mode;
 
 	T = 1000000000 / via_clock;
 
@@ -175,7 +199,7 @@
 	ide_timing_compute(drive, speed, &t, T, UT);
 
 	if (peer) {
-		ide_timing_compute(peer, peer->current_speed, &p, T, UT);
+		ide_timing_compute(peer, peer->pio_mode, &p, T, UT);
 		ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
 	}
 
@@ -184,22 +208,24 @@
 
 /**
  *	via_set_pio_mode	-	set host controller for PIO mode
+ *	@hwif: port
  *	@drive: drive
- *	@pio: PIO mode number
  *
  *	A callback from the upper layers for PIO-only tuning.
  */
 
-static void via_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void via_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-	via_set_drive(drive, XFER_PIO_0 + pio);
+	drive->dma_mode = drive->pio_mode;
+	via_set_drive(hwif, drive);
 }
 
 static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
 {
 	struct via_isa_bridge *via_config;
 
-	for (via_config = via_isa_bridges; via_config->id; via_config++)
+	for (via_config = via_isa_bridges;
+	     via_config->id != PCI_DEVICE_ID_VIA_ANON; via_config++)
 		if ((*isa = pci_get_device(PCI_VENDOR_ID_VIA +
 			!!(via_config->flags & VIA_BAD_ID),
 			via_config->id, NULL))) {
@@ -362,6 +388,9 @@
 	if (via_cable_override(pdev))
 		return ATA_CBL_PATA40_SHORT;
 
+	if ((vdev->via_config->flags & VIA_SATA_PATA) && hwif->channel == 0)
+		return ATA_CBL_SATA;
+
 	if ((vdev->via_80w >> hwif->channel) & 1)
 		return ATA_CBL_PATA80;
 	else
@@ -374,10 +403,66 @@
 	.cable_detect		= via82cxxx_cable_detect,
 };
 
+static void via_write_devctl(ide_hwif_t *hwif, u8 ctl)
+{
+	struct via82cxxx_dev *vdev = hwif->host->host_priv;
+
+	outb(ctl, hwif->io_ports.ctl_addr);
+	outb(vdev->cached_device[hwif->channel], hwif->io_ports.device_addr);
+}
+
+static void __via_dev_select(ide_drive_t *drive, u8 select)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct via82cxxx_dev *vdev = hwif->host->host_priv;
+
+	outb(select, hwif->io_ports.device_addr);
+	vdev->cached_device[hwif->channel] = select;
+}
+
+static void via_dev_select(ide_drive_t *drive)
+{
+	__via_dev_select(drive, drive->select | ATA_DEVICE_OBS);
+}
+
+static void via_tf_load(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct ide_io_ports *io_ports = &hwif->io_ports;
+
+	if (valid & IDE_VALID_FEATURE)
+		outb(tf->feature, io_ports->feature_addr);
+	if (valid & IDE_VALID_NSECT)
+		outb(tf->nsect, io_ports->nsect_addr);
+	if (valid & IDE_VALID_LBAL)
+		outb(tf->lbal, io_ports->lbal_addr);
+	if (valid & IDE_VALID_LBAM)
+		outb(tf->lbam, io_ports->lbam_addr);
+	if (valid & IDE_VALID_LBAH)
+		outb(tf->lbah, io_ports->lbah_addr);
+	if (valid & IDE_VALID_DEVICE)
+		__via_dev_select(drive, tf->device);
+}
+
+const struct ide_tp_ops via_tp_ops = {
+	.exec_command		= ide_exec_command,
+	.read_status		= ide_read_status,
+	.read_altstatus		= ide_read_altstatus,
+	.write_devctl		= via_write_devctl,
+
+	.dev_select		= via_dev_select,
+	.tf_load		= via_tf_load,
+	.tf_read		= ide_tf_read,
+
+	.input_data		= ide_input_data,
+	.output_data		= ide_output_data,
+};
+
 static const struct ide_port_info via82cxxx_chipset __devinitdata = {
 	.name		= DRV_NAME,
 	.init_chipset	= init_chipset_via82cxxx,
 	.enablebits	= { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
+	.tp_ops		= &via_tp_ops,
 	.port_ops	= &via_port_ops,
 	.host_flags	= IDE_HFLAG_PIO_NO_BLACKLIST |
 			  IDE_HFLAG_POST_SET_MODE |
@@ -402,11 +487,6 @@
 	 * Find the ISA bridge and check we know what it is.
 	 */
 	via_config = via_config_find(&isa);
-	if (!via_config->id) {
-		printk(KERN_WARNING DRV_NAME " %s: unknown chipset, skipping\n",
-			pci_name(dev));
-		return -ENODEV;
-	}
 
 	/*
 	 * Print the boot message.
@@ -436,10 +516,13 @@
 		via_clock = 33333;
 	}
 
-	if (idx == 0)
-		d.host_flags |= IDE_HFLAG_NO_AUTODMA;
-	else
+	if (idx == 1)
 		d.enablebits[1].reg = d.enablebits[0].reg = 0;
+	else
+		d.host_flags |= IDE_HFLAG_NO_AUTODMA;
+
+	if (idx == VIA_IDFLAG_SINGLE)
+		d.host_flags |= IDE_HFLAG_SINGLE;
 
 	if ((via_config->flags & VIA_NO_UNMASK) == 0)
 		d.host_flags |= IDE_HFLAG_UNMASK_IRQS;
@@ -475,8 +558,9 @@
 	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1),  0 },
 	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1),  0 },
 	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_CX700_IDE), 0 },
-	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_VX855_IDE), 0 },
+	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_VX855_IDE), VIA_IDFLAG_SINGLE },
 	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410),      1 },
+	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6415),      1 },
 	{ PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), 1 },
 	{ 0, },
 };
@@ -504,6 +588,6 @@
 module_init(via_ide_init);
 module_exit(via_ide_exit);
 
-MODULE_AUTHOR("Vojtech Pavlik, Michel Aubry, Jeff Garzik, Andre Hedrick");
+MODULE_AUTHOR("Vojtech Pavlik, Bartlomiej Zolnierkiewicz, Michel Aubry, Jeff Garzik, Andre Hedrick");
 MODULE_DESCRIPTION("PCI driver module for VIA IDE");
 MODULE_LICENSE("GPL");
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 5122b5a..1835021 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -19,7 +19,6 @@
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <linux/freezer.h>
-#include <linux/semaphore.h>
 #include <asm/atomic.h>
 
 #include "csr.h"
@@ -1397,9 +1396,9 @@
 			pdrv = container_of(drv, struct hpsb_protocol_driver,
 					    driver);
 			if (pdrv->update) {
-				down(&ud->device.sem);
+				device_lock(&ud->device);
 				error = pdrv->update(ud);
-				up(&ud->device.sem);
+				device_unlock(&ud->device);
 			}
 			if (error)
 				device_release_driver(&ud->device);
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 9555fd2..bf47fee 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1452,7 +1452,7 @@
                                 PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c");
                         } else {
                                 PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom");
-				/* FIXME: probably we shoud rewrite the max_rec, max_ROM(1394a),
+				/* FIXME: probably we should rewrite the max_rec, max_ROM(1394a),
 				 * generation(1394a) and link_spd(1394a) field and recalculate
 				 * the CRC */
 
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index dd0db67..975adce 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -20,6 +20,7 @@
 
 config INFINIBAND_USER_ACCESS
 	tristate "InfiniBand userspace access (verbs and CM)"
+	select ANON_INODES
 	---help---
 	  Userspace InfiniBand access support.  This enables the
 	  kernel side of userspace verbs and the userspace
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 5130fc5..764787e 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3597,7 +3597,7 @@
 		       atomic_long_read(&group->counter[cm_attr->index]));
 }
 
-static struct sysfs_ops cm_counter_ops = {
+static const struct sysfs_ops cm_counter_ops = {
 	.show = cm_show_counter
 };
 
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 7522008..e351b15 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -1193,10 +1193,7 @@
 {
 	int i;
 
-	for (i = find_first_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS);
-	     i < IB_MGMT_MAX_METHODS;
-	     i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS,
-			       1+i)) {
+	for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS) {
 		if ((*method)->agent[i]) {
 			printk(KERN_ERR PFX "Method %d already in use\n", i);
 			return -EINVAL;
@@ -1330,13 +1327,9 @@
 		goto error3;
 
 	/* Finally, add in methods being registered */
-	for (i = find_first_bit(mad_reg_req->method_mask,
-				IB_MGMT_MAX_METHODS);
-	     i < IB_MGMT_MAX_METHODS;
-	     i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS,
-			       1+i)) {
+	for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS)
 		(*method)->agent[i] = agent_priv;
-	}
+
 	return 0;
 
 error3:
@@ -1429,13 +1422,9 @@
 		goto error4;
 
 	/* Finally, add in methods being registered */
-	for (i = find_first_bit(mad_reg_req->method_mask,
-				IB_MGMT_MAX_METHODS);
-	     i < IB_MGMT_MAX_METHODS;
-	     i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS,
-			       1+i)) {
+	for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS)
 		(*method)->agent[i] = agent_priv;
-	}
+
 	return 0;
 
 error4:
@@ -2964,6 +2953,9 @@
 {
 	int i, num_ports, cur_port;
 
+	if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+		return;
+
 	if (device->node_type == RDMA_NODE_IB_SWITCH) {
 		num_ports = 1;
 		cur_port = 0;
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 158a214..1558bb7 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -79,7 +79,7 @@
 	return port_attr->show(p, port_attr, buf);
 }
 
-static struct sysfs_ops port_sysfs_ops = {
+static const struct sysfs_ops port_sysfs_ops = {
 	.show = port_attr_show
 };
 
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index f504c9b..017d6e2 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1215,15 +1215,18 @@
 
 	ucm_dev = container_of(dev, struct ib_ucm_device, dev);
 	cdev_del(&ucm_dev->cdev);
-	clear_bit(ucm_dev->devnum, dev_map);
+	if (ucm_dev->devnum < IB_UCM_MAX_DEVICES)
+		clear_bit(ucm_dev->devnum, dev_map);
+	else
+		clear_bit(ucm_dev->devnum - IB_UCM_MAX_DEVICES, dev_map);
 	kfree(ucm_dev);
 }
 
 static const struct file_operations ucm_fops = {
-	.owner 	 = THIS_MODULE,
-	.open 	 = ib_ucm_open,
+	.owner	 = THIS_MODULE,
+	.open	 = ib_ucm_open,
 	.release = ib_ucm_close,
-	.write 	 = ib_ucm_write,
+	.write	 = ib_ucm_write,
 	.poll    = ib_ucm_poll,
 };
 
@@ -1237,8 +1240,32 @@
 }
 static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
 
+static dev_t overflow_maj;
+static DECLARE_BITMAP(overflow_map, IB_UCM_MAX_DEVICES);
+static int find_overflow_devnum(void)
+{
+	int ret;
+
+	if (!overflow_maj) {
+		ret = alloc_chrdev_region(&overflow_maj, 0, IB_UCM_MAX_DEVICES,
+					  "infiniband_cm");
+		if (ret) {
+			printk(KERN_ERR "ucm: couldn't register dynamic device number\n");
+			return ret;
+		}
+	}
+
+	ret = find_first_zero_bit(overflow_map, IB_UCM_MAX_DEVICES);
+	if (ret >= IB_UCM_MAX_DEVICES)
+		return -1;
+
+	return ret;
+}
+
 static void ib_ucm_add_one(struct ib_device *device)
 {
+	int devnum;
+	dev_t base;
 	struct ib_ucm_device *ucm_dev;
 
 	if (!device->alloc_ucontext ||
@@ -1251,16 +1278,25 @@
 
 	ucm_dev->ib_dev = device;
 
-	ucm_dev->devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES);
-	if (ucm_dev->devnum >= IB_UCM_MAX_DEVICES)
-		goto err;
+	devnum = find_first_zero_bit(dev_map, IB_UCM_MAX_DEVICES);
+	if (devnum >= IB_UCM_MAX_DEVICES) {
+		devnum = find_overflow_devnum();
+		if (devnum < 0)
+			goto err;
 
-	set_bit(ucm_dev->devnum, dev_map);
+		ucm_dev->devnum = devnum + IB_UCM_MAX_DEVICES;
+		base = devnum + overflow_maj;
+		set_bit(devnum, overflow_map);
+	} else {
+		ucm_dev->devnum = devnum;
+		base = devnum + IB_UCM_BASE_DEV;
+		set_bit(devnum, dev_map);
+	}
 
 	cdev_init(&ucm_dev->cdev, &ucm_fops);
 	ucm_dev->cdev.owner = THIS_MODULE;
 	kobject_set_name(&ucm_dev->cdev.kobj, "ucm%d", ucm_dev->devnum);
-	if (cdev_add(&ucm_dev->cdev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
+	if (cdev_add(&ucm_dev->cdev, base, 1))
 		goto err;
 
 	ucm_dev->dev.class = &cm_class;
@@ -1281,7 +1317,10 @@
 	device_unregister(&ucm_dev->dev);
 err_cdev:
 	cdev_del(&ucm_dev->cdev);
-	clear_bit(ucm_dev->devnum, dev_map);
+	if (ucm_dev->devnum < IB_UCM_MAX_DEVICES)
+		clear_bit(devnum, dev_map);
+	else
+		clear_bit(devnum, overflow_map);
 err:
 	kfree(ucm_dev);
 	return;
@@ -1297,11 +1336,8 @@
 	device_unregister(&ucm_dev->dev);
 }
 
-static ssize_t show_abi_version(struct class *class, char *buf)
-{
-	return sprintf(buf, "%d\n", IB_USER_CM_ABI_VERSION);
-}
-static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
+static CLASS_ATTR_STRING(abi_version, S_IRUGO,
+			 __stringify(IB_USER_CM_ABI_VERSION));
 
 static int __init ib_ucm_init(void)
 {
@@ -1314,7 +1350,7 @@
 		goto error1;
 	}
 
-	ret = class_create_file(&cm_class, &class_attr_abi_version);
+	ret = class_create_file(&cm_class, &class_attr_abi_version.attr);
 	if (ret) {
 		printk(KERN_ERR "ucm: couldn't create abi_version attribute\n");
 		goto error2;
@@ -1328,7 +1364,7 @@
 	return 0;
 
 error3:
-	class_remove_file(&cm_class, &class_attr_abi_version);
+	class_remove_file(&cm_class, &class_attr_abi_version.attr);
 error2:
 	unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
 error1:
@@ -1338,8 +1374,10 @@
 static void __exit ib_ucm_cleanup(void)
 {
 	ib_unregister_client(&ucm_client);
-	class_remove_file(&cm_class, &class_attr_abi_version);
+	class_remove_file(&cm_class, &class_attr_abi_version.attr);
 	unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
+	if (overflow_maj)
+		unregister_chrdev_region(overflow_maj, IB_UCM_MAX_DEVICES);
 	idr_destroy(&ctx_id_table);
 }
 
diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c
index 8ec7876..650b501 100644
--- a/drivers/infiniband/core/ud_header.c
+++ b/drivers/infiniband/core/ud_header.c
@@ -181,6 +181,7 @@
  * ib_ud_header_init - Initialize UD header structure
  * @payload_bytes:Length of packet payload
  * @grh_present:GRH flag (if non-zero, GRH will be included)
+ * @immediate_present: specify if immediate data should be used
  * @header:Structure to initialize
  *
  * ib_ud_header_init() initializes the lrh.link_version, lrh.link_next_header,
@@ -191,21 +192,13 @@
  */
 void ib_ud_header_init(int     		    payload_bytes,
 		       int    		    grh_present,
+		       int		    immediate_present,
 		       struct ib_ud_header *header)
 {
-	int header_len;
 	u16 packet_length;
 
 	memset(header, 0, sizeof *header);
 
-	header_len =
-		IB_LRH_BYTES  +
-		IB_BTH_BYTES  +
-		IB_DETH_BYTES;
-	if (grh_present) {
-		header_len += IB_GRH_BYTES;
-	}
-
 	header->lrh.link_version     = 0;
 	header->lrh.link_next_header =
 		grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
@@ -231,7 +224,8 @@
 
 	header->lrh.packet_length = cpu_to_be16(packet_length);
 
-	if (header->immediate_present)
+	header->immediate_present	     = immediate_present;
+	if (immediate_present)
 		header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
 	else
 		header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY;
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index 6f7c096..4f906f0 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -136,7 +136,7 @@
 	down_write(&current->mm->mmap_sem);
 
 	locked     = npages + current->mm->locked_vm;
-	lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
+	lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
 
 	if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
 		ret = -ENOMEM;
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 7de0296..04b585e 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -65,12 +65,9 @@
 };
 
 /*
- * Our lifetime rules for these structs are the following: each time a
- * device special file is opened, we look up the corresponding struct
- * ib_umad_port by minor in the umad_port[] table while holding the
- * port_lock.  If this lookup succeeds, we take a reference on the
- * ib_umad_port's struct ib_umad_device while still holding the
- * port_lock; if the lookup fails, we fail the open().  We drop these
+ * Our lifetime rules for these structs are the following:
+ * device special file is opened, we take a reference on the
+ * ib_umad_port's struct ib_umad_device. We drop these
  * references in the corresponding close().
  *
  * In addition to references coming from open character devices, there
@@ -78,19 +75,14 @@
  * module's reference taken when allocating the ib_umad_device in
  * ib_umad_add_one().
  *
- * When destroying an ib_umad_device, we clear all of its
- * ib_umad_ports from umad_port[] while holding port_lock before
- * dropping the module's reference to the ib_umad_device.  This is
- * always safe because any open() calls will either succeed and obtain
- * a reference before we clear the umad_port[] entries, or fail after
- * we clear the umad_port[] entries.
+ * When destroying an ib_umad_device, we drop the module's reference.
  */
 
 struct ib_umad_port {
-	struct cdev           *cdev;
+	struct cdev           cdev;
 	struct device	      *dev;
 
-	struct cdev           *sm_cdev;
+	struct cdev           sm_cdev;
 	struct device	      *sm_dev;
 	struct semaphore       sm_sem;
 
@@ -136,7 +128,6 @@
 static const dev_t base_dev = MKDEV(IB_UMAD_MAJOR, IB_UMAD_MINOR_BASE);
 
 static DEFINE_SPINLOCK(port_lock);
-static struct ib_umad_port *umad_port[IB_UMAD_MAX_PORTS];
 static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS);
 
 static void ib_umad_add_one(struct ib_device *device);
@@ -496,8 +487,8 @@
 		ah_attr.ah_flags = IB_AH_GRH;
 		memcpy(ah_attr.grh.dgid.raw, packet->mad.hdr.gid, 16);
 		ah_attr.grh.sgid_index	   = packet->mad.hdr.gid_index;
-		ah_attr.grh.flow_label 	   = be32_to_cpu(packet->mad.hdr.flow_label);
-		ah_attr.grh.hop_limit  	   = packet->mad.hdr.hop_limit;
+		ah_attr.grh.flow_label	   = be32_to_cpu(packet->mad.hdr.flow_label);
+		ah_attr.grh.hop_limit	   = packet->mad.hdr.hop_limit;
 		ah_attr.grh.traffic_class  = packet->mad.hdr.traffic_class;
 	}
 
@@ -528,9 +519,9 @@
 		goto err_ah;
 	}
 
-	packet->msg->ah 	= ah;
+	packet->msg->ah		= ah;
 	packet->msg->timeout_ms = packet->mad.hdr.timeout_ms;
-	packet->msg->retries 	= packet->mad.hdr.retries;
+	packet->msg->retries	= packet->mad.hdr.retries;
 	packet->msg->context[0] = packet;
 
 	/* Copy MAD header.  Any RMPP header is already in place. */
@@ -779,15 +770,11 @@
 /*
  * ib_umad_open() does not need the BKL:
  *
- *  - umad_port[] accesses are protected by port_lock, the
- *    ib_umad_port structures are properly reference counted, and
+ *  - the ib_umad_port structures are properly reference counted, and
  *    everything else is purely local to the file being created, so
  *    races against other open calls are not a problem;
  *  - the ioctl method does not affect any global state outside of the
  *    file structure being operated on;
- *  - the port is added to umad_port[] as the last part of module
- *    initialization so the open method will either immediately run
- *    -ENXIO, or all required initialization will be done.
  */
 static int ib_umad_open(struct inode *inode, struct file *filp)
 {
@@ -795,13 +782,10 @@
 	struct ib_umad_file *file;
 	int ret = 0;
 
-	spin_lock(&port_lock);
-	port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE];
+	port = container_of(inode->i_cdev, struct ib_umad_port, cdev);
 	if (port)
 		kref_get(&port->umad_dev->ref);
-	spin_unlock(&port_lock);
-
-	if (!port)
+	else
 		return -ENXIO;
 
 	mutex_lock(&port->file_mutex);
@@ -872,16 +856,16 @@
 }
 
 static const struct file_operations umad_fops = {
-	.owner 	 	= THIS_MODULE,
-	.read 	 	= ib_umad_read,
-	.write 	 	= ib_umad_write,
-	.poll 	 	= ib_umad_poll,
+	.owner		= THIS_MODULE,
+	.read		= ib_umad_read,
+	.write		= ib_umad_write,
+	.poll		= ib_umad_poll,
 	.unlocked_ioctl = ib_umad_ioctl,
 #ifdef CONFIG_COMPAT
-	.compat_ioctl 	= ib_umad_compat_ioctl,
+	.compat_ioctl	= ib_umad_compat_ioctl,
 #endif
-	.open 	 	= ib_umad_open,
-	.release 	= ib_umad_close
+	.open		= ib_umad_open,
+	.release	= ib_umad_close
 };
 
 static int ib_umad_sm_open(struct inode *inode, struct file *filp)
@@ -892,13 +876,10 @@
 	};
 	int ret;
 
-	spin_lock(&port_lock);
-	port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE - IB_UMAD_MAX_PORTS];
+	port = container_of(inode->i_cdev, struct ib_umad_port, sm_cdev);
 	if (port)
 		kref_get(&port->umad_dev->ref);
-	spin_unlock(&port_lock);
-
-	if (!port)
+	else
 		return -ENXIO;
 
 	if (filp->f_flags & O_NONBLOCK) {
@@ -949,8 +930,8 @@
 }
 
 static const struct file_operations umad_sm_fops = {
-	.owner 	 = THIS_MODULE,
-	.open 	 = ib_umad_sm_open,
+	.owner	 = THIS_MODULE,
+	.open	 = ib_umad_sm_open,
 	.release = ib_umad_sm_close
 };
 
@@ -984,22 +965,54 @@
 }
 static DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
 
-static ssize_t show_abi_version(struct class *class, char *buf)
+static CLASS_ATTR_STRING(abi_version, S_IRUGO,
+			 __stringify(IB_USER_MAD_ABI_VERSION));
+
+static dev_t overflow_maj;
+static DECLARE_BITMAP(overflow_map, IB_UMAD_MAX_PORTS);
+static int find_overflow_devnum(void)
 {
-	return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION);
+	int ret;
+
+	if (!overflow_maj) {
+		ret = alloc_chrdev_region(&overflow_maj, 0, IB_UMAD_MAX_PORTS * 2,
+					  "infiniband_mad");
+		if (ret) {
+			printk(KERN_ERR "user_mad: couldn't register dynamic device number\n");
+			return ret;
+		}
+	}
+
+	ret = find_first_zero_bit(overflow_map, IB_UMAD_MAX_PORTS);
+	if (ret >= IB_UMAD_MAX_PORTS)
+		return -1;
+
+	return ret;
 }
-static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
 
 static int ib_umad_init_port(struct ib_device *device, int port_num,
 			     struct ib_umad_port *port)
 {
+	int devnum;
+	dev_t base;
+
 	spin_lock(&port_lock);
-	port->dev_num = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
-	if (port->dev_num >= IB_UMAD_MAX_PORTS) {
+	devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);
+	if (devnum >= IB_UMAD_MAX_PORTS) {
 		spin_unlock(&port_lock);
-		return -1;
+		devnum = find_overflow_devnum();
+		if (devnum < 0)
+			return -1;
+
+		spin_lock(&port_lock);
+		port->dev_num = devnum + IB_UMAD_MAX_PORTS;
+		base = devnum + overflow_maj;
+		set_bit(devnum, overflow_map);
+	} else {
+		port->dev_num = devnum;
+		base = devnum + base_dev;
+		set_bit(devnum, dev_map);
 	}
-	set_bit(port->dev_num, dev_map);
 	spin_unlock(&port_lock);
 
 	port->ib_dev   = device;
@@ -1008,17 +1021,14 @@
 	mutex_init(&port->file_mutex);
 	INIT_LIST_HEAD(&port->file_list);
 
-	port->cdev = cdev_alloc();
-	if (!port->cdev)
-		return -1;
-	port->cdev->owner = THIS_MODULE;
-	port->cdev->ops   = &umad_fops;
-	kobject_set_name(&port->cdev->kobj, "umad%d", port->dev_num);
-	if (cdev_add(port->cdev, base_dev + port->dev_num, 1))
+	cdev_init(&port->cdev, &umad_fops);
+	port->cdev.owner = THIS_MODULE;
+	kobject_set_name(&port->cdev.kobj, "umad%d", port->dev_num);
+	if (cdev_add(&port->cdev, base, 1))
 		goto err_cdev;
 
 	port->dev = device_create(umad_class, device->dma_device,
-				  port->cdev->dev, port,
+				  port->cdev.dev, port,
 				  "umad%d", port->dev_num);
 	if (IS_ERR(port->dev))
 		goto err_cdev;
@@ -1028,17 +1038,15 @@
 	if (device_create_file(port->dev, &dev_attr_port))
 		goto err_dev;
 
-	port->sm_cdev = cdev_alloc();
-	if (!port->sm_cdev)
-		goto err_dev;
-	port->sm_cdev->owner = THIS_MODULE;
-	port->sm_cdev->ops   = &umad_sm_fops;
-	kobject_set_name(&port->sm_cdev->kobj, "issm%d", port->dev_num);
-	if (cdev_add(port->sm_cdev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
+	base += IB_UMAD_MAX_PORTS;
+	cdev_init(&port->sm_cdev, &umad_sm_fops);
+	port->sm_cdev.owner = THIS_MODULE;
+	kobject_set_name(&port->sm_cdev.kobj, "issm%d", port->dev_num);
+	if (cdev_add(&port->sm_cdev, base, 1))
 		goto err_sm_cdev;
 
 	port->sm_dev = device_create(umad_class, device->dma_device,
-				     port->sm_cdev->dev, port,
+				     port->sm_cdev.dev, port,
 				     "issm%d", port->dev_num);
 	if (IS_ERR(port->sm_dev))
 		goto err_sm_cdev;
@@ -1048,24 +1056,23 @@
 	if (device_create_file(port->sm_dev, &dev_attr_port))
 		goto err_sm_dev;
 
-	spin_lock(&port_lock);
-	umad_port[port->dev_num] = port;
-	spin_unlock(&port_lock);
-
 	return 0;
 
 err_sm_dev:
-	device_destroy(umad_class, port->sm_cdev->dev);
+	device_destroy(umad_class, port->sm_cdev.dev);
 
 err_sm_cdev:
-	cdev_del(port->sm_cdev);
+	cdev_del(&port->sm_cdev);
 
 err_dev:
-	device_destroy(umad_class, port->cdev->dev);
+	device_destroy(umad_class, port->cdev.dev);
 
 err_cdev:
-	cdev_del(port->cdev);
-	clear_bit(port->dev_num, dev_map);
+	cdev_del(&port->cdev);
+	if (port->dev_num < IB_UMAD_MAX_PORTS)
+		clear_bit(devnum, dev_map);
+	else
+		clear_bit(devnum, overflow_map);
 
 	return -1;
 }
@@ -1079,15 +1086,11 @@
 	dev_set_drvdata(port->dev,    NULL);
 	dev_set_drvdata(port->sm_dev, NULL);
 
-	device_destroy(umad_class, port->cdev->dev);
-	device_destroy(umad_class, port->sm_cdev->dev);
+	device_destroy(umad_class, port->cdev.dev);
+	device_destroy(umad_class, port->sm_cdev.dev);
 
-	cdev_del(port->cdev);
-	cdev_del(port->sm_cdev);
-
-	spin_lock(&port_lock);
-	umad_port[port->dev_num] = NULL;
-	spin_unlock(&port_lock);
+	cdev_del(&port->cdev);
+	cdev_del(&port->sm_cdev);
 
 	mutex_lock(&port->file_mutex);
 
@@ -1106,7 +1109,10 @@
 
 	mutex_unlock(&port->file_mutex);
 
-	clear_bit(port->dev_num, dev_map);
+	if (port->dev_num < IB_UMAD_MAX_PORTS)
+		clear_bit(port->dev_num, dev_map);
+	else
+		clear_bit(port->dev_num - IB_UMAD_MAX_PORTS, overflow_map);
 }
 
 static void ib_umad_add_one(struct ib_device *device)
@@ -1185,7 +1191,7 @@
 		goto out_chrdev;
 	}
 
-	ret = class_create_file(umad_class, &class_attr_abi_version);
+	ret = class_create_file(umad_class, &class_attr_abi_version.attr);
 	if (ret) {
 		printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n");
 		goto out_class;
@@ -1214,6 +1220,8 @@
 	ib_unregister_client(&umad_client);
 	class_destroy(umad_class);
 	unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);
+	if (overflow_maj)
+		unregister_chrdev_region(overflow_maj, IB_UMAD_MAX_PORTS * 2);
 }
 
 module_init(ib_umad_init);
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index b3ea958..a078e56 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -41,6 +41,7 @@
 #include <linux/idr.h>
 #include <linux/mutex.h>
 #include <linux/completion.h>
+#include <linux/cdev.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_umem.h>
@@ -69,23 +70,23 @@
 
 struct ib_uverbs_device {
 	struct kref				ref;
+	int					num_comp_vectors;
 	struct completion			comp;
-	int					devnum;
-	struct cdev			       *cdev;
 	struct device			       *dev;
 	struct ib_device		       *ib_dev;
-	int					num_comp_vectors;
+	int					devnum;
+	struct cdev			        cdev;
 };
 
 struct ib_uverbs_event_file {
 	struct kref				ref;
+	int					is_async;
 	struct ib_uverbs_file		       *uverbs_file;
 	spinlock_t				lock;
+	int					is_closed;
 	wait_queue_head_t			poll_wait;
 	struct fasync_struct		       *async_queue;
 	struct list_head			event_list;
-	int					is_async;
-	int					is_closed;
 };
 
 struct ib_uverbs_file {
@@ -145,7 +146,7 @@
 void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
 
 struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
-					int is_async, int *fd);
+					int is_async);
 struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd);
 
 void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 112d397..f71cf13 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -301,10 +301,15 @@
 
 	resp.num_comp_vectors = file->device->num_comp_vectors;
 
-	filp = ib_uverbs_alloc_event_file(file, 1, &resp.async_fd);
+	ret = get_unused_fd();
+	if (ret < 0)
+		goto err_free;
+	resp.async_fd = ret;
+
+	filp = ib_uverbs_alloc_event_file(file, 1);
 	if (IS_ERR(filp)) {
 		ret = PTR_ERR(filp);
-		goto err_free;
+		goto err_fd;
 	}
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -332,9 +337,11 @@
 	return in_len;
 
 err_file:
-	put_unused_fd(resp.async_fd);
 	fput(filp);
 
+err_fd:
+	put_unused_fd(resp.async_fd);
+
 err_free:
 	ibdev->dealloc_ucontext(ucontext);
 
@@ -715,6 +722,7 @@
 	struct ib_uverbs_create_comp_channel	   cmd;
 	struct ib_uverbs_create_comp_channel_resp  resp;
 	struct file				  *filp;
+	int ret;
 
 	if (out_len < sizeof resp)
 		return -ENOSPC;
@@ -722,9 +730,16 @@
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	filp = ib_uverbs_alloc_event_file(file, 0, &resp.fd);
-	if (IS_ERR(filp))
+	ret = get_unused_fd();
+	if (ret < 0)
+		return ret;
+	resp.fd = ret;
+
+	filp = ib_uverbs_alloc_event_file(file, 0);
+	if (IS_ERR(filp)) {
+		put_unused_fd(resp.fd);
 		return PTR_ERR(filp);
+	}
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 5f284ff..d805cf3 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -42,8 +42,8 @@
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/file.h>
-#include <linux/mount.h>
 #include <linux/cdev.h>
+#include <linux/anon_inodes.h>
 
 #include <asm/uaccess.h>
 
@@ -53,8 +53,6 @@
 MODULE_DESCRIPTION("InfiniBand userspace verbs access");
 MODULE_LICENSE("Dual BSD/GPL");
 
-#define INFINIBANDEVENTFS_MAGIC	0x49426576	/* "IBev" */
-
 enum {
 	IB_UVERBS_MAJOR       = 231,
 	IB_UVERBS_BASE_MINOR  = 192,
@@ -75,44 +73,41 @@
 DEFINE_IDR(ib_uverbs_srq_idr);
 
 static DEFINE_SPINLOCK(map_lock);
-static struct ib_uverbs_device *dev_table[IB_UVERBS_MAX_DEVICES];
 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
 
 static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
 				     const char __user *buf, int in_len,
 				     int out_len) = {
-	[IB_USER_VERBS_CMD_GET_CONTEXT]   	= ib_uverbs_get_context,
-	[IB_USER_VERBS_CMD_QUERY_DEVICE]  	= ib_uverbs_query_device,
-	[IB_USER_VERBS_CMD_QUERY_PORT]    	= ib_uverbs_query_port,
-	[IB_USER_VERBS_CMD_ALLOC_PD]      	= ib_uverbs_alloc_pd,
-	[IB_USER_VERBS_CMD_DEALLOC_PD]    	= ib_uverbs_dealloc_pd,
-	[IB_USER_VERBS_CMD_REG_MR]        	= ib_uverbs_reg_mr,
-	[IB_USER_VERBS_CMD_DEREG_MR]      	= ib_uverbs_dereg_mr,
+	[IB_USER_VERBS_CMD_GET_CONTEXT]		= ib_uverbs_get_context,
+	[IB_USER_VERBS_CMD_QUERY_DEVICE]	= ib_uverbs_query_device,
+	[IB_USER_VERBS_CMD_QUERY_PORT]		= ib_uverbs_query_port,
+	[IB_USER_VERBS_CMD_ALLOC_PD]		= ib_uverbs_alloc_pd,
+	[IB_USER_VERBS_CMD_DEALLOC_PD]		= ib_uverbs_dealloc_pd,
+	[IB_USER_VERBS_CMD_REG_MR]		= ib_uverbs_reg_mr,
+	[IB_USER_VERBS_CMD_DEREG_MR]		= ib_uverbs_dereg_mr,
 	[IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,
-	[IB_USER_VERBS_CMD_CREATE_CQ]     	= ib_uverbs_create_cq,
-	[IB_USER_VERBS_CMD_RESIZE_CQ]     	= ib_uverbs_resize_cq,
-	[IB_USER_VERBS_CMD_POLL_CQ]     	= ib_uverbs_poll_cq,
-	[IB_USER_VERBS_CMD_REQ_NOTIFY_CQ]     	= ib_uverbs_req_notify_cq,
-	[IB_USER_VERBS_CMD_DESTROY_CQ]    	= ib_uverbs_destroy_cq,
-	[IB_USER_VERBS_CMD_CREATE_QP]     	= ib_uverbs_create_qp,
-	[IB_USER_VERBS_CMD_QUERY_QP]     	= ib_uverbs_query_qp,
-	[IB_USER_VERBS_CMD_MODIFY_QP]     	= ib_uverbs_modify_qp,
-	[IB_USER_VERBS_CMD_DESTROY_QP]    	= ib_uverbs_destroy_qp,
-	[IB_USER_VERBS_CMD_POST_SEND]    	= ib_uverbs_post_send,
-	[IB_USER_VERBS_CMD_POST_RECV]    	= ib_uverbs_post_recv,
-	[IB_USER_VERBS_CMD_POST_SRQ_RECV]    	= ib_uverbs_post_srq_recv,
-	[IB_USER_VERBS_CMD_CREATE_AH]    	= ib_uverbs_create_ah,
-	[IB_USER_VERBS_CMD_DESTROY_AH]    	= ib_uverbs_destroy_ah,
-	[IB_USER_VERBS_CMD_ATTACH_MCAST]  	= ib_uverbs_attach_mcast,
-	[IB_USER_VERBS_CMD_DETACH_MCAST]  	= ib_uverbs_detach_mcast,
-	[IB_USER_VERBS_CMD_CREATE_SRQ]    	= ib_uverbs_create_srq,
-	[IB_USER_VERBS_CMD_MODIFY_SRQ]    	= ib_uverbs_modify_srq,
-	[IB_USER_VERBS_CMD_QUERY_SRQ]     	= ib_uverbs_query_srq,
-	[IB_USER_VERBS_CMD_DESTROY_SRQ]   	= ib_uverbs_destroy_srq,
+	[IB_USER_VERBS_CMD_CREATE_CQ]		= ib_uverbs_create_cq,
+	[IB_USER_VERBS_CMD_RESIZE_CQ]		= ib_uverbs_resize_cq,
+	[IB_USER_VERBS_CMD_POLL_CQ]		= ib_uverbs_poll_cq,
+	[IB_USER_VERBS_CMD_REQ_NOTIFY_CQ]	= ib_uverbs_req_notify_cq,
+	[IB_USER_VERBS_CMD_DESTROY_CQ]		= ib_uverbs_destroy_cq,
+	[IB_USER_VERBS_CMD_CREATE_QP]		= ib_uverbs_create_qp,
+	[IB_USER_VERBS_CMD_QUERY_QP]		= ib_uverbs_query_qp,
+	[IB_USER_VERBS_CMD_MODIFY_QP]		= ib_uverbs_modify_qp,
+	[IB_USER_VERBS_CMD_DESTROY_QP]		= ib_uverbs_destroy_qp,
+	[IB_USER_VERBS_CMD_POST_SEND]		= ib_uverbs_post_send,
+	[IB_USER_VERBS_CMD_POST_RECV]		= ib_uverbs_post_recv,
+	[IB_USER_VERBS_CMD_POST_SRQ_RECV]	= ib_uverbs_post_srq_recv,
+	[IB_USER_VERBS_CMD_CREATE_AH]		= ib_uverbs_create_ah,
+	[IB_USER_VERBS_CMD_DESTROY_AH]		= ib_uverbs_destroy_ah,
+	[IB_USER_VERBS_CMD_ATTACH_MCAST]	= ib_uverbs_attach_mcast,
+	[IB_USER_VERBS_CMD_DETACH_MCAST]	= ib_uverbs_detach_mcast,
+	[IB_USER_VERBS_CMD_CREATE_SRQ]		= ib_uverbs_create_srq,
+	[IB_USER_VERBS_CMD_MODIFY_SRQ]		= ib_uverbs_modify_srq,
+	[IB_USER_VERBS_CMD_QUERY_SRQ]		= ib_uverbs_query_srq,
+	[IB_USER_VERBS_CMD_DESTROY_SRQ]		= ib_uverbs_destroy_srq,
 };
 
-static struct vfsmount *uverbs_event_mnt;
-
 static void ib_uverbs_add_one(struct ib_device *device);
 static void ib_uverbs_remove_one(struct ib_device *device);
 
@@ -370,7 +365,7 @@
 
 static const struct file_operations uverbs_event_fops = {
 	.owner	 = THIS_MODULE,
-	.read 	 = ib_uverbs_event_read,
+	.read	 = ib_uverbs_event_read,
 	.poll    = ib_uverbs_event_poll,
 	.release = ib_uverbs_event_close,
 	.fasync  = ib_uverbs_event_fasync
@@ -489,12 +484,10 @@
 }
 
 struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
-					int is_async, int *fd)
+					int is_async)
 {
 	struct ib_uverbs_event_file *ev_file;
-	struct path path;
 	struct file *filp;
-	int ret;
 
 	ev_file = kmalloc(sizeof *ev_file, GFP_KERNEL);
 	if (!ev_file)
@@ -509,38 +502,12 @@
 	ev_file->is_async    = is_async;
 	ev_file->is_closed   = 0;
 
-	*fd = get_unused_fd();
-	if (*fd < 0) {
-		ret = *fd;
-		goto err;
-	}
-
-	/*
-	 * fops_get() can't fail here, because we're coming from a
-	 * system call on a uverbs file, which will already have a
-	 * module reference.
-	 */
-	path.mnt = uverbs_event_mnt;
-	path.dentry = uverbs_event_mnt->mnt_root;
-	path_get(&path);
-	filp = alloc_file(&path, FMODE_READ, fops_get(&uverbs_event_fops));
-	if (!filp) {
-		ret = -ENFILE;
-		goto err_fd;
-	}
-
-	filp->private_data = ev_file;
+	filp = anon_inode_getfile("[infinibandevent]", &uverbs_event_fops,
+				  ev_file, O_RDONLY);
+	if (IS_ERR(filp))
+		kfree(ev_file);
 
 	return filp;
-
-err_fd:
-	fops_put(&uverbs_event_fops);
-	path_put(&path);
-	put_unused_fd(*fd);
-
-err:
-	kfree(ev_file);
-	return ERR_PTR(ret);
 }
 
 /*
@@ -617,14 +584,12 @@
 /*
  * ib_uverbs_open() does not need the BKL:
  *
- *  - dev_table[] accesses are protected by map_lock, the
- *    ib_uverbs_device structures are properly reference counted, and
+ *  - the ib_uverbs_device structures are properly reference counted and
  *    everything else is purely local to the file being created, so
  *    races against other open calls are not a problem;
  *  - there is no ioctl method to race against;
- *  - the device is added to dev_table[] as the last part of module
- *    initialization, the open method will either immediately run
- *    -ENXIO, or all required initialization will be done.
+ *  - the open method will either immediately run -ENXIO, or all
+ *    required initialization will be done.
  */
 static int ib_uverbs_open(struct inode *inode, struct file *filp)
 {
@@ -632,13 +597,10 @@
 	struct ib_uverbs_file *file;
 	int ret;
 
-	spin_lock(&map_lock);
-	dev = dev_table[iminor(inode) - IB_UVERBS_BASE_MINOR];
+	dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev);
 	if (dev)
 		kref_get(&dev->ref);
-	spin_unlock(&map_lock);
-
-	if (!dev)
+	else
 		return -ENXIO;
 
 	if (!try_module_get(dev->ib_dev->owner)) {
@@ -685,17 +647,17 @@
 }
 
 static const struct file_operations uverbs_fops = {
-	.owner 	 = THIS_MODULE,
-	.write 	 = ib_uverbs_write,
-	.open 	 = ib_uverbs_open,
+	.owner	 = THIS_MODULE,
+	.write	 = ib_uverbs_write,
+	.open	 = ib_uverbs_open,
 	.release = ib_uverbs_close
 };
 
 static const struct file_operations uverbs_mmap_fops = {
-	.owner 	 = THIS_MODULE,
-	.write 	 = ib_uverbs_write,
+	.owner	 = THIS_MODULE,
+	.write	 = ib_uverbs_write,
 	.mmap    = ib_uverbs_mmap,
-	.open 	 = ib_uverbs_open,
+	.open	 = ib_uverbs_open,
 	.release = ib_uverbs_close
 };
 
@@ -729,14 +691,41 @@
 }
 static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
 
-static ssize_t show_abi_version(struct class *class, char *buf)
+static CLASS_ATTR_STRING(abi_version, S_IRUGO,
+			 __stringify(IB_USER_VERBS_ABI_VERSION));
+
+static dev_t overflow_maj;
+static DECLARE_BITMAP(overflow_map, IB_UVERBS_MAX_DEVICES);
+
+/*
+ * If we have more than IB_UVERBS_MAX_DEVICES, dynamically overflow by
+ * requesting a new major number and doubling the number of max devices we
+ * support. It's stupid, but simple.
+ */
+static int find_overflow_devnum(void)
 {
-	return sprintf(buf, "%d\n", IB_USER_VERBS_ABI_VERSION);
+	int ret;
+
+	if (!overflow_maj) {
+		ret = alloc_chrdev_region(&overflow_maj, 0, IB_UVERBS_MAX_DEVICES,
+					  "infiniband_verbs");
+		if (ret) {
+			printk(KERN_ERR "user_verbs: couldn't register dynamic device number\n");
+			return ret;
+		}
+	}
+
+	ret = find_first_zero_bit(overflow_map, IB_UVERBS_MAX_DEVICES);
+	if (ret >= IB_UVERBS_MAX_DEVICES)
+		return -1;
+
+	return ret;
 }
-static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
 
 static void ib_uverbs_add_one(struct ib_device *device)
 {
+	int devnum;
+	dev_t base;
 	struct ib_uverbs_device *uverbs_dev;
 
 	if (!device->alloc_ucontext)
@@ -750,28 +739,36 @@
 	init_completion(&uverbs_dev->comp);
 
 	spin_lock(&map_lock);
-	uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
-	if (uverbs_dev->devnum >= IB_UVERBS_MAX_DEVICES) {
+	devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
+	if (devnum >= IB_UVERBS_MAX_DEVICES) {
 		spin_unlock(&map_lock);
-		goto err;
+		devnum = find_overflow_devnum();
+		if (devnum < 0)
+			goto err;
+
+		spin_lock(&map_lock);
+		uverbs_dev->devnum = devnum + IB_UVERBS_MAX_DEVICES;
+		base = devnum + overflow_maj;
+		set_bit(devnum, overflow_map);
+	} else {
+		uverbs_dev->devnum = devnum;
+		base = devnum + IB_UVERBS_BASE_DEV;
+		set_bit(devnum, dev_map);
 	}
-	set_bit(uverbs_dev->devnum, dev_map);
 	spin_unlock(&map_lock);
 
 	uverbs_dev->ib_dev           = device;
 	uverbs_dev->num_comp_vectors = device->num_comp_vectors;
 
-	uverbs_dev->cdev = cdev_alloc();
-	if (!uverbs_dev->cdev)
-		goto err;
-	uverbs_dev->cdev->owner = THIS_MODULE;
-	uverbs_dev->cdev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
-	kobject_set_name(&uverbs_dev->cdev->kobj, "uverbs%d", uverbs_dev->devnum);
-	if (cdev_add(uverbs_dev->cdev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
+	cdev_init(&uverbs_dev->cdev, NULL);
+	uverbs_dev->cdev.owner = THIS_MODULE;
+	uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
+	kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
+	if (cdev_add(&uverbs_dev->cdev, base, 1))
 		goto err_cdev;
 
 	uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
-					uverbs_dev->cdev->dev, uverbs_dev,
+					uverbs_dev->cdev.dev, uverbs_dev,
 					"uverbs%d", uverbs_dev->devnum);
 	if (IS_ERR(uverbs_dev->dev))
 		goto err_cdev;
@@ -781,20 +778,19 @@
 	if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
 		goto err_class;
 
-	spin_lock(&map_lock);
-	dev_table[uverbs_dev->devnum] = uverbs_dev;
-	spin_unlock(&map_lock);
-
 	ib_set_client_data(device, &uverbs_client, uverbs_dev);
 
 	return;
 
 err_class:
-	device_destroy(uverbs_class, uverbs_dev->cdev->dev);
+	device_destroy(uverbs_class, uverbs_dev->cdev.dev);
 
 err_cdev:
-	cdev_del(uverbs_dev->cdev);
-	clear_bit(uverbs_dev->devnum, dev_map);
+	cdev_del(&uverbs_dev->cdev);
+	if (uverbs_dev->devnum < IB_UVERBS_MAX_DEVICES)
+		clear_bit(devnum, dev_map);
+	else
+		clear_bit(devnum, overflow_map);
 
 err:
 	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
@@ -811,35 +807,19 @@
 		return;
 
 	dev_set_drvdata(uverbs_dev->dev, NULL);
-	device_destroy(uverbs_class, uverbs_dev->cdev->dev);
-	cdev_del(uverbs_dev->cdev);
+	device_destroy(uverbs_class, uverbs_dev->cdev.dev);
+	cdev_del(&uverbs_dev->cdev);
 
-	spin_lock(&map_lock);
-	dev_table[uverbs_dev->devnum] = NULL;
-	spin_unlock(&map_lock);
-
-	clear_bit(uverbs_dev->devnum, dev_map);
+	if (uverbs_dev->devnum < IB_UVERBS_MAX_DEVICES)
+		clear_bit(uverbs_dev->devnum, dev_map);
+	else
+		clear_bit(uverbs_dev->devnum - IB_UVERBS_MAX_DEVICES, overflow_map);
 
 	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
 	wait_for_completion(&uverbs_dev->comp);
 	kfree(uverbs_dev);
 }
 
-static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
-			       const char *dev_name, void *data,
-			       struct vfsmount *mnt)
-{
-	return get_sb_pseudo(fs_type, "infinibandevent:", NULL,
-			     INFINIBANDEVENTFS_MAGIC, mnt);
-}
-
-static struct file_system_type uverbs_event_fs = {
-	/* No owner field so module can be unloaded */
-	.name    = "infinibandeventfs",
-	.get_sb  = uverbs_event_get_sb,
-	.kill_sb = kill_litter_super
-};
-
 static int __init ib_uverbs_init(void)
 {
 	int ret;
@@ -858,39 +838,20 @@
 		goto out_chrdev;
 	}
 
-	ret = class_create_file(uverbs_class, &class_attr_abi_version);
+	ret = class_create_file(uverbs_class, &class_attr_abi_version.attr);
 	if (ret) {
 		printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n");
 		goto out_class;
 	}
 
-	ret = register_filesystem(&uverbs_event_fs);
-	if (ret) {
-		printk(KERN_ERR "user_verbs: couldn't register infinibandeventfs\n");
-		goto out_class;
-	}
-
-	uverbs_event_mnt = kern_mount(&uverbs_event_fs);
-	if (IS_ERR(uverbs_event_mnt)) {
-		ret = PTR_ERR(uverbs_event_mnt);
-		printk(KERN_ERR "user_verbs: couldn't mount infinibandeventfs\n");
-		goto out_fs;
-	}
-
 	ret = ib_register_client(&uverbs_client);
 	if (ret) {
 		printk(KERN_ERR "user_verbs: couldn't register client\n");
-		goto out_mnt;
+		goto out_class;
 	}
 
 	return 0;
 
-out_mnt:
-	mntput(uverbs_event_mnt);
-
-out_fs:
-	unregister_filesystem(&uverbs_event_fs);
-
 out_class:
 	class_destroy(uverbs_class);
 
@@ -904,10 +865,10 @@
 static void __exit ib_uverbs_cleanup(void)
 {
 	ib_unregister_client(&uverbs_client);
-	mntput(uverbs_event_mnt);
-	unregister_filesystem(&uverbs_event_fs);
 	class_destroy(uverbs_class);
 	unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
+	if (overflow_maj)
+		unregister_chrdev_region(overflow_maj, IB_UVERBS_MAX_DEVICES);
 	idr_destroy(&ib_uverbs_pd_idr);
 	idr_destroy(&ib_uverbs_mr_idr);
 	idr_destroy(&ib_uverbs_mw_idr);
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
index 0677fc7..a28e862 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -109,7 +109,6 @@
 		while (!CQ_VLD_ENTRY(rptr, cq->size_log2, cqe)) {
 			udelay(1);
 			if (i++ > 1000000) {
-				BUG_ON(1);
 				printk(KERN_ERR "%s: stalled rnic\n",
 				       rdev_p->dev_name);
 				return -EIO;
@@ -155,7 +154,7 @@
 	return iwch_cxgb3_ofld_send(rdev_p->t3cdev_p, skb);
 }
 
-int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
+int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq, int kernel)
 {
 	struct rdma_cq_setup setup;
 	int size = (1UL << (cq->size_log2)) * sizeof(struct t3_cqe);
@@ -163,12 +162,12 @@
 	cq->cqid = cxio_hal_get_cqid(rdev_p->rscp);
 	if (!cq->cqid)
 		return -ENOMEM;
-	cq->sw_queue = kzalloc(size, GFP_KERNEL);
-	if (!cq->sw_queue)
-		return -ENOMEM;
-	cq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev),
-					     (1UL << (cq->size_log2)) *
-					     sizeof(struct t3_cqe),
+	if (kernel) {
+		cq->sw_queue = kzalloc(size, GFP_KERNEL);
+		if (!cq->sw_queue)
+			return -ENOMEM;
+	}
+	cq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev), size,
 					     &(cq->dma_addr), GFP_KERNEL);
 	if (!cq->queue) {
 		kfree(cq->sw_queue);
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h
index f3d440c..073373c 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.h
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h
@@ -53,7 +53,7 @@
 #define T3_MAX_PBL_SIZE 256
 #define T3_MAX_RQ_SIZE 1024
 #define T3_MAX_QP_DEPTH (T3_MAX_RQ_SIZE-1)
-#define T3_MAX_CQ_DEPTH 8192
+#define T3_MAX_CQ_DEPTH 262144
 #define T3_MAX_NUM_STAG (1<<15)
 #define T3_MAX_MR_SIZE 0x100000000ULL
 #define T3_PAGESIZE_MASK 0xffff000  /* 4KB-128MB */
@@ -157,7 +157,7 @@
 void cxio_rdev_close(struct cxio_rdev *rdev);
 int cxio_hal_cq_op(struct cxio_rdev *rdev, struct t3_cq *cq,
 		   enum t3_cq_opcode op, u32 credit);
-int cxio_create_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
+int cxio_create_cq(struct cxio_rdev *rdev, struct t3_cq *cq, int kernel);
 int cxio_destroy_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
 int cxio_resize_cq(struct cxio_rdev *rdev, struct t3_cq *cq);
 void cxio_release_ucontext(struct cxio_rdev *rdev, struct cxio_ucontext *uctx);
diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h
index a197a5b..15073b2 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_wr.h
+++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h
@@ -730,7 +730,22 @@
 
 static inline void cxio_set_wq_in_error(struct t3_wq *wq)
 {
-	wq->queue->wq_in_err.err = 1;
+	wq->queue->wq_in_err.err |= 1;
+}
+
+static inline void cxio_disable_wq_db(struct t3_wq *wq)
+{
+	wq->queue->wq_in_err.err |= 2;
+}
+
+static inline void cxio_enable_wq_db(struct t3_wq *wq)
+{
+	wq->queue->wq_in_err.err &= ~2;
+}
+
+static inline int cxio_wq_db_enabled(struct t3_wq *wq)
+{
+	return !(wq->queue->wq_in_err.err & 2);
 }
 
 static inline struct t3_cqe *cxio_next_hw_cqe(struct t3_cq *cq)
diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c
index b0ea010..63f975f 100644
--- a/drivers/infiniband/hw/cxgb3/iwch.c
+++ b/drivers/infiniband/hw/cxgb3/iwch.c
@@ -65,6 +65,46 @@
 static LIST_HEAD(dev_list);
 static DEFINE_MUTEX(dev_mutex);
 
+static int disable_qp_db(int id, void *p, void *data)
+{
+	struct iwch_qp *qhp = p;
+
+	cxio_disable_wq_db(&qhp->wq);
+	return 0;
+}
+
+static int enable_qp_db(int id, void *p, void *data)
+{
+	struct iwch_qp *qhp = p;
+
+	if (data)
+		ring_doorbell(qhp->rhp->rdev.ctrl_qp.doorbell, qhp->wq.qpid);
+	cxio_enable_wq_db(&qhp->wq);
+	return 0;
+}
+
+static void disable_dbs(struct iwch_dev *rnicp)
+{
+	spin_lock_irq(&rnicp->lock);
+	idr_for_each(&rnicp->qpidr, disable_qp_db, NULL);
+	spin_unlock_irq(&rnicp->lock);
+}
+
+static void enable_dbs(struct iwch_dev *rnicp, int ring_db)
+{
+	spin_lock_irq(&rnicp->lock);
+	idr_for_each(&rnicp->qpidr, enable_qp_db,
+		     (void *)(unsigned long)ring_db);
+	spin_unlock_irq(&rnicp->lock);
+}
+
+static void iwch_db_drop_task(struct work_struct *work)
+{
+	struct iwch_dev *rnicp = container_of(work, struct iwch_dev,
+					      db_drop_task.work);
+	enable_dbs(rnicp, 1);
+}
+
 static void rnic_init(struct iwch_dev *rnicp)
 {
 	PDBG("%s iwch_dev %p\n", __func__,  rnicp);
@@ -72,6 +112,7 @@
 	idr_init(&rnicp->qpidr);
 	idr_init(&rnicp->mmidr);
 	spin_lock_init(&rnicp->lock);
+	INIT_DELAYED_WORK(&rnicp->db_drop_task, iwch_db_drop_task);
 
 	rnicp->attr.max_qps = T3_MAX_NUM_QP - 32;
 	rnicp->attr.max_wrs = T3_MAX_QP_DEPTH;
@@ -147,6 +188,9 @@
 	mutex_lock(&dev_mutex);
 	list_for_each_entry_safe(dev, tmp, &dev_list, entry) {
 		if (dev->rdev.t3cdev_p == tdev) {
+			dev->rdev.flags = CXIO_ERROR_FATAL;
+			synchronize_net();
+			cancel_delayed_work_sync(&dev->db_drop_task);
 			list_del(&dev->entry);
 			iwch_unregister_device(dev);
 			cxio_rdev_close(&dev->rdev);
@@ -165,7 +209,8 @@
 	struct cxio_rdev *rdev = tdev->ulp;
 	struct iwch_dev *rnicp;
 	struct ib_event event;
-	u32    portnum = port_id + 1;
+	u32 portnum = port_id + 1;
+	int dispatch = 0;
 
 	if (!rdev)
 		return;
@@ -173,22 +218,51 @@
 	switch (evt) {
 	case OFFLOAD_STATUS_DOWN: {
 		rdev->flags = CXIO_ERROR_FATAL;
+		synchronize_net();
 		event.event  = IB_EVENT_DEVICE_FATAL;
+		dispatch = 1;
 		break;
 		}
 	case OFFLOAD_PORT_DOWN: {
 		event.event  = IB_EVENT_PORT_ERR;
+		dispatch = 1;
 		break;
 		}
 	case OFFLOAD_PORT_UP: {
 		event.event  = IB_EVENT_PORT_ACTIVE;
+		dispatch = 1;
+		break;
+		}
+	case OFFLOAD_DB_FULL: {
+		disable_dbs(rnicp);
+		break;
+		}
+	case OFFLOAD_DB_EMPTY: {
+		enable_dbs(rnicp, 1);
+		break;
+		}
+	case OFFLOAD_DB_DROP: {
+		unsigned long delay = 1000;
+		unsigned short r;
+
+		disable_dbs(rnicp);
+		get_random_bytes(&r, 2);
+		delay += r & 1023;
+
+		/*
+		 * delay is between 1000-2023 usecs.
+		 */
+		schedule_delayed_work(&rnicp->db_drop_task,
+			usecs_to_jiffies(delay));
 		break;
 		}
 	}
 
-	event.device = &rnicp->ibdev;
-	event.element.port_num = portnum;
-	ib_dispatch_event(&event);
+	if (dispatch) {
+		event.device = &rnicp->ibdev;
+		event.element.port_num = portnum;
+		ib_dispatch_event(&event);
+	}
 
 	return;
 }
diff --git a/drivers/infiniband/hw/cxgb3/iwch.h b/drivers/infiniband/hw/cxgb3/iwch.h
index 8473550..a1c4457 100644
--- a/drivers/infiniband/hw/cxgb3/iwch.h
+++ b/drivers/infiniband/hw/cxgb3/iwch.h
@@ -36,6 +36,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/idr.h>
+#include <linux/workqueue.h>
 
 #include <rdma/ib_verbs.h>
 
@@ -110,6 +111,7 @@
 	struct idr mmidr;
 	spinlock_t lock;
 	struct list_head entry;
+	struct delayed_work db_drop_task;
 };
 
 static inline struct iwch_dev *to_iwch_dev(struct ib_device *ibdev)
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index ed71755..47b35c6 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -187,7 +187,7 @@
 	entries = roundup_pow_of_two(entries);
 	chp->cq.size_log2 = ilog2(entries);
 
-	if (cxio_create_cq(&rhp->rdev, &chp->cq)) {
+	if (cxio_create_cq(&rhp->rdev, &chp->cq, !ucontext)) {
 		kfree(chp);
 		return ERR_PTR(-ENOMEM);
 	}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index 3eb8cec..b4d893d 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -452,7 +452,8 @@
 		++(qhp->wq.sq_wptr);
 	}
 	spin_unlock_irqrestore(&qhp->lock, flag);
-	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+	if (cxio_wq_db_enabled(&qhp->wq))
+		ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
 
 out:
 	if (err)
@@ -514,7 +515,8 @@
 		num_wrs--;
 	}
 	spin_unlock_irqrestore(&qhp->lock, flag);
-	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+	if (cxio_wq_db_enabled(&qhp->wq))
+		ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
 
 out:
 	if (err)
@@ -597,7 +599,8 @@
 	++(qhp->wq.sq_wptr);
 	spin_unlock_irqrestore(&qhp->lock, flag);
 
-	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+	if (cxio_wq_db_enabled(&qhp->wq))
+		ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
 
 	return err;
 }
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 42be0b1..b2b6fea 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -548,11 +548,10 @@
 	struct ehca_eq *eq = &shca->eq;
 	struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache;
 	u64 eqe_value, ret;
-	unsigned long flags;
 	int eqe_cnt, i;
 	int eq_empty = 0;
 
-	spin_lock_irqsave(&eq->irq_spinlock, flags);
+	spin_lock(&eq->irq_spinlock);
 	if (is_irq) {
 		const int max_query_cnt = 100;
 		int query_cnt = 0;
@@ -643,7 +642,7 @@
 	} while (1);
 
 unlock_irq_spinlock:
-	spin_unlock_irqrestore(&eq->irq_spinlock, flags);
+	spin_unlock(&eq->irq_spinlock);
 }
 
 void ehca_tasklet_eq(unsigned long data)
diff --git a/drivers/infiniband/hw/ehca/ehca_qes.h b/drivers/infiniband/hw/ehca/ehca_qes.h
index 5d28e3e..90c4efa 100644
--- a/drivers/infiniband/hw/ehca/ehca_qes.h
+++ b/drivers/infiniband/hw/ehca/ehca_qes.h
@@ -46,7 +46,7 @@
 
 #include "ehca_tools.h"
 
-/* virtual scatter gather entry to specify remote adresses with length */
+/* virtual scatter gather entry to specify remote addresses with length */
 struct ehca_vsgentry {
 	u64 vaddr;
 	u32 lkey;
@@ -148,7 +148,7 @@
 	u32 immediate_data;
 	union {
 		struct {
-			u64 remote_virtual_adress;
+			u64 remote_virtual_address;
 			u32 rkey;
 			u32 reserved;
 			u64 atomic_1st_op_dma_len;
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 0338f1f..b105f66 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -55,9 +55,7 @@
 /*
  * attributes not supported by query qp
  */
-#define QP_ATTR_QUERY_NOT_SUPPORTED (IB_QP_MAX_DEST_RD_ATOMIC | \
-				     IB_QP_MAX_QP_RD_ATOMIC   | \
-				     IB_QP_ACCESS_FLAGS       | \
+#define QP_ATTR_QUERY_NOT_SUPPORTED (IB_QP_ACCESS_FLAGS       | \
 				     IB_QP_EN_SQD_ASYNC_NOTIFY)
 
 /*
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index e3ec7fd..9a3fbfc 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -269,7 +269,7 @@
 		/* no break is intentional here */
 	case IB_QPT_RC:
 		/* TODO: atomic not implemented */
-		wqe_p->u.nud.remote_virtual_adress =
+		wqe_p->u.nud.remote_virtual_address =
 			send_wr->wr.rdma.remote_addr;
 		wqe_p->u.nud.rkey = send_wr->wr.rdma.rkey;
 
diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c
index 8c1213f..dba8f9f 100644
--- a/drivers/infiniband/hw/ehca/ehca_sqp.c
+++ b/drivers/infiniband/hw/ehca/ehca_sqp.c
@@ -222,7 +222,7 @@
 {
 	int ret;
 
-	if (!port_num || port_num > ibdev->phys_port_cnt)
+	if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc)
 		return IB_MAD_RESULT_FAILURE;
 
 	/* accept only pma request */
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c
index 82878e3..eb7d59a 100644
--- a/drivers/infiniband/hw/ipath/ipath_user_pages.c
+++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c
@@ -59,8 +59,7 @@
 	size_t got;
 	int ret;
 
-	lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >>
-		PAGE_SHIFT;
+	lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
 
 	if (num_pages > lock_limit) {
 		ret = -ENOMEM;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 2a97c96..ae75389 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1214,7 +1214,7 @@
 static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
 			    void *wqe, unsigned *mlx_seg_len)
 {
-	struct ib_device *ib_dev = &to_mdev(sqp->qp.ibqp.device)->ib_dev;
+	struct ib_device *ib_dev = sqp->qp.ibqp.device;
 	struct mlx4_wqe_mlx_seg *mlx = wqe;
 	struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx;
 	struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
@@ -1228,7 +1228,7 @@
 	for (i = 0; i < wr->num_sge; ++i)
 		send_size += wr->sg_list[i].length;
 
-	ib_ud_header_init(send_size, mlx4_ib_ah_grh_present(ah), &sqp->ud_header);
+	ib_ud_header_init(send_size, mlx4_ib_ah_grh_present(ah), 0, &sqp->ud_header);
 
 	sqp->ud_header.lrh.service_level   =
 		be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 28;
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index c10576f..d2d172e 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1494,7 +1494,7 @@
 	u16 pkey;
 
 	ib_ud_header_init(256, /* assume a MAD */
-			  mthca_ah_grh_present(to_mah(wr->wr.ud.ah)),
+			  mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), 0,
 			  &sqp->ud_header);
 
 	err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header);
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index b9d09ba..4272c52 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -110,6 +110,7 @@
 
 static struct pci_device_id nes_pci_table[] = {
 	{PCI_VENDOR_ID_NETEFFECT, PCI_DEVICE_ID_NETEFFECT_NE020, PCI_ANY_ID, PCI_ANY_ID},
+	{PCI_VENDOR_ID_NETEFFECT, PCI_DEVICE_ID_NETEFFECT_NE020_KR, PCI_ANY_ID, PCI_ANY_ID},
 	{0}
 };
 
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index 9884056..cc78fee 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -64,8 +64,9 @@
  * NetEffect PCI vendor id and NE010 PCI device id.
  */
 #ifndef PCI_VENDOR_ID_NETEFFECT	/* not in pci.ids yet */
-#define PCI_VENDOR_ID_NETEFFECT       0x1678
-#define PCI_DEVICE_ID_NETEFFECT_NE020 0x0100
+#define PCI_VENDOR_ID_NETEFFECT          0x1678
+#define PCI_DEVICE_ID_NETEFFECT_NE020    0x0100
+#define PCI_DEVICE_ID_NETEFFECT_NE020_KR 0x0110
 #endif
 
 #define NE020_REV   4
@@ -193,8 +194,8 @@
 extern u32 cm_packets_received;
 extern u32 cm_packets_dropped;
 extern u32 cm_packets_retrans;
-extern u32 cm_listens_created;
-extern u32 cm_listens_destroyed;
+extern atomic_t cm_listens_created;
+extern atomic_t cm_listens_destroyed;
 extern u32 cm_backlog_drops;
 extern atomic_t cm_loopbacks;
 extern atomic_t cm_nodes_created;
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 39468c27..2a49ee4 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -67,8 +67,8 @@
 u32 cm_packets_retrans;
 u32 cm_packets_created;
 u32 cm_packets_received;
-u32 cm_listens_created;
-u32 cm_listens_destroyed;
+atomic_t cm_listens_created;
+atomic_t cm_listens_destroyed;
 u32 cm_backlog_drops;
 atomic_t cm_loopbacks;
 atomic_t cm_nodes_created;
@@ -1011,9 +1011,10 @@
 					event.cm_info.loc_port =
 							 loopback->loc_port;
 					event.cm_info.cm_id = loopback->cm_id;
+					add_ref_cm_node(loopback);
+					loopback->state = NES_CM_STATE_CLOSED;
 					cm_event_connect_error(&event);
 					cm_node->state = NES_CM_STATE_LISTENER_DESTROYED;
-					loopback->state = NES_CM_STATE_CLOSED;
 
 					rem_ref_cm_node(cm_node->cm_core,
 							 cm_node);
@@ -1042,7 +1043,7 @@
 		kfree(listener);
 		listener = NULL;
 		ret = 0;
-		cm_listens_destroyed++;
+		atomic_inc(&cm_listens_destroyed);
 	} else {
 		spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 	}
@@ -3172,7 +3173,7 @@
 			g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node);
 			return err;
 		}
-		cm_listens_created++;
+		atomic_inc(&cm_listens_created);
 	}
 
 	cm_id->add_ref(cm_id);
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index b1c2cbb..9250755 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -748,16 +748,28 @@
 
 	if (hw_rev != NE020_REV) {
 		/* init serdes 0 */
-		if (wide_ppm_offset && (nesadapter->phy_type[0] == NES_PHY_TYPE_CX4))
-			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000FFFAA);
-		else
+		switch (nesadapter->phy_type[0]) {
+		case NES_PHY_TYPE_CX4:
+			if (wide_ppm_offset)
+				nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000FFFAA);
+			else
+				nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);
+			break;
+		case NES_PHY_TYPE_KR:
 			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);
-
-		if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) {
+			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x00000000);
+			break;
+		case NES_PHY_TYPE_PUMA_1G:
+			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);
 			sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0);
 			sds |= 0x00000100;
 			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds);
+			break;
+		default:
+			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);
+			break;
 		}
+
 		if (!OneG_Mode)
 			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000);
 
@@ -778,6 +790,9 @@
 			if (wide_ppm_offset)
 				nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000FFFAA);
 			break;
+		case NES_PHY_TYPE_KR:
+			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x00000000);
+			break;
 		case NES_PHY_TYPE_PUMA_1G:
 			sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
 			sds |= 0x000000100;
@@ -1279,115 +1294,100 @@
 
 
 /**
- * nes_init_phy
+ * nes_init_1g_phy
  */
-int nes_init_phy(struct nes_device *nesdev)
+int nes_init_1g_phy(struct nes_device *nesdev, u8 phy_type, u8 phy_index)
 {
-	struct nes_adapter *nesadapter = nesdev->nesadapter;
+	u32 counter = 0;
+	u16 phy_data;
+	int ret = 0;
+
+	nes_read_1G_phy_reg(nesdev, 1, phy_index, &phy_data);
+	nes_write_1G_phy_reg(nesdev, 23, phy_index, 0xb000);
+
+	/* Reset the PHY */
+	nes_write_1G_phy_reg(nesdev, 0, phy_index, 0x8000);
+	udelay(100);
+	counter = 0;
+	do {
+		nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
+		if (counter++ > 100) {
+			ret = -1;
+			break;
+		}
+	} while (phy_data & 0x8000);
+
+	/* Setting no phy loopback */
+	phy_data &= 0xbfff;
+	phy_data |= 0x1140;
+	nes_write_1G_phy_reg(nesdev, 0, phy_index,  phy_data);
+	nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
+	nes_read_1G_phy_reg(nesdev, 0x17, phy_index, &phy_data);
+	nes_read_1G_phy_reg(nesdev, 0x1e, phy_index, &phy_data);
+
+	/* Setting the interrupt mask */
+	nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);
+	nes_write_1G_phy_reg(nesdev, 0x19, phy_index, 0xffee);
+	nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);
+
+	/* turning on flow control */
+	nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);
+	nes_write_1G_phy_reg(nesdev, 4, phy_index, (phy_data & ~(0x03E0)) | 0xc00);
+	nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);
+
+	/* Clear Half duplex */
+	nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);
+	nes_write_1G_phy_reg(nesdev, 9, phy_index, phy_data & ~(0x0100));
+	nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);
+
+	nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
+	nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data | 0x0300);
+
+	return ret;
+}
+
+
+/**
+ * nes_init_2025_phy
+ */
+int nes_init_2025_phy(struct nes_device *nesdev, u8 phy_type, u8 phy_index)
+{
+	u32 temp_phy_data = 0;
+	u32 temp_phy_data2 = 0;
 	u32 counter = 0;
 	u32 sds;
 	u32 mac_index = nesdev->mac_index;
-	u32 tx_config = 0;
-	u16 phy_data;
-	u32 temp_phy_data = 0;
-	u32 temp_phy_data2 = 0;
-	u8  phy_type = nesadapter->phy_type[mac_index];
-	u8  phy_index = nesadapter->phy_index[mac_index];
+	int ret = 0;
+	unsigned int first_attempt = 1;
 
-	if ((nesadapter->OneG_Mode) &&
-	    (phy_type != NES_PHY_TYPE_PUMA_1G)) {
-		nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index);
-		if (phy_type == NES_PHY_TYPE_1G) {
-			tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
-			tx_config &= 0xFFFFFFE3;
-			tx_config |= 0x04;
-			nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
-		}
+	/* Check firmware heartbeat */
+	nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
+	temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+	udelay(1500);
+	nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
+	temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
 
-		nes_read_1G_phy_reg(nesdev, 1, phy_index, &phy_data);
-		nes_write_1G_phy_reg(nesdev, 23, phy_index, 0xb000);
-
-		/* Reset the PHY */
-		nes_write_1G_phy_reg(nesdev, 0, phy_index, 0x8000);
-		udelay(100);
-		counter = 0;
-		do {
-			nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
-			if (counter++ > 100)
-				break;
-		} while (phy_data & 0x8000);
-
-		/* Setting no phy loopback */
-		phy_data &= 0xbfff;
-		phy_data |= 0x1140;
-		nes_write_1G_phy_reg(nesdev, 0, phy_index,  phy_data);
-		nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
-		nes_read_1G_phy_reg(nesdev, 0x17, phy_index, &phy_data);
-		nes_read_1G_phy_reg(nesdev, 0x1e, phy_index, &phy_data);
-
-		/* Setting the interrupt mask */
-		nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);
-		nes_write_1G_phy_reg(nesdev, 0x19, phy_index, 0xffee);
-		nes_read_1G_phy_reg(nesdev, 0x19, phy_index, &phy_data);
-
-		/* turning on flow control */
-		nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);
-		nes_write_1G_phy_reg(nesdev, 4, phy_index, (phy_data & ~(0x03E0)) | 0xc00);
-		nes_read_1G_phy_reg(nesdev, 4, phy_index, &phy_data);
-
-		/* Clear Half duplex */
-		nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);
-		nes_write_1G_phy_reg(nesdev, 9, phy_index, phy_data & ~(0x0100));
-		nes_read_1G_phy_reg(nesdev, 9, phy_index, &phy_data);
-
-		nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
-		nes_write_1G_phy_reg(nesdev, 0, phy_index, phy_data | 0x0300);
-
-		return 0;
-	}
-
-	if ((phy_type == NES_PHY_TYPE_IRIS) ||
-	    (phy_type == NES_PHY_TYPE_ARGUS) ||
-	    (phy_type == NES_PHY_TYPE_SFP_D)) {
-		/* setup 10G MDIO operation */
-		tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
-		tx_config &= 0xFFFFFFE3;
-		tx_config |= 0x15;
-		nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
-	}
-	if ((phy_type == NES_PHY_TYPE_ARGUS) ||
-	    (phy_type == NES_PHY_TYPE_SFP_D)) {
-		u32 first_time = 1;
-
-		/* Check firmware heartbeat */
-		nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
+	if (temp_phy_data != temp_phy_data2) {
+		nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);
 		temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
-		udelay(1500);
-		nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
-		temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+		if ((temp_phy_data & 0xff) > 0x20)
+			return 0;
+		printk(PFX "Reinitialize external PHY\n");
+	}
 
-		if (temp_phy_data != temp_phy_data2) {
-			nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);
-			temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
-			if ((temp_phy_data & 0xff) > 0x20)
-				return 0;
-			printk(PFX "Reinitializing PHY\n");
-		}
+	/* no heartbeat, configure the PHY */
+	nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0x0000, 0x8000);
+	nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0000);
+	nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);
+	nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);
 
-		/* no heartbeat, configure the PHY */
-		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0x0000, 0x8000);
-		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0000);
+	switch (phy_type) {
+	case NES_PHY_TYPE_ARGUS:
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);
-		if (phy_type == NES_PHY_TYPE_ARGUS) {
-			nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x000C);
-			nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0008);
-			nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0001);
-		} else {
-			nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x0004);
-			nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0038);
-			nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0013);
-		}
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x000C);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0008);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0001);
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0098);
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00);
 
@@ -1395,71 +1395,151 @@
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x0007);
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd007, 0x000A);
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd008, 0x0009);
+		break;
 
-		nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0028, 0xA528);
+	case NES_PHY_TYPE_SFP_D:
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x0004);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0038);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0013);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0098);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00);
 
-		/* Bring PHY out of reset */
-		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0002);
+		/* setup LEDs */
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x0007);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd007, 0x000A);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd008, 0x0009);
+		break;
 
-		/* Check for heartbeat */
-		counter = 0;
-		mdelay(690);
+	case NES_PHY_TYPE_KR:
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc316, 0x000A);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc318, 0x0052);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc302, 0x000C);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc319, 0x0010);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0027, 0x0013);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc31a, 0x0080);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0026, 0x0E00);
+
+		/* setup LEDs */
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd006, 0x000B);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd007, 0x0003);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd008, 0x0004);
+
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0022, 0x406D);
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0023, 0x0020);
+		break;
+	}
+
+	nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0x0028, 0xA528);
+
+	/* Bring PHY out of reset */
+	nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc300, 0x0002);
+
+	/* Check for heartbeat */
+	counter = 0;
+	mdelay(690);
+	nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
+	temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+	do {
+		if (counter++ > 150) {
+			printk(PFX "No PHY heartbeat\n");
+			break;
+		}
+		mdelay(1);
 		nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
+		temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+	} while ((temp_phy_data2 == temp_phy_data));
+
+	/* wait for tracking */
+	counter = 0;
+	do {
+		nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);
 		temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
-		do {
-			if (counter++ > 150) {
-				printk(PFX "No PHY heartbeat\n");
+		if (counter++ > 300) {
+			if (((temp_phy_data & 0xff) == 0x0) && first_attempt) {
+				first_attempt = 0;
+				counter = 0;
+				/* reset AMCC PHY and try again */
+				nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0xe854, 0x00c0);
+				nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0xe854, 0x0040);
+				continue;
+			} else {
+				ret = 1;
 				break;
 			}
-			mdelay(1);
-			nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
-			temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
-		} while ((temp_phy_data2 == temp_phy_data));
+		}
+		mdelay(10);
+	} while ((temp_phy_data & 0xff) < 0x30);
 
-		/* wait for tracking */
-		counter = 0;
-		do {
-			nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);
-			temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
-			if (counter++ > 300) {
-				if (((temp_phy_data & 0xff) == 0x0) && first_time) {
-					first_time = 0;
-					counter = 0;
-					/* reset AMCC PHY and try again */
-					nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0xe854, 0x00c0);
-					nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0xe854, 0x0040);
-					continue;
-				} else {
-					printk(PFX "PHY did not track\n");
-					break;
-				}
-			}
-			mdelay(10);
-		} while ((temp_phy_data & 0xff) < 0x30);
-
-		/* setup signal integrity */
-		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd003, 0x0000);
-		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00D, 0x00FE);
-		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00E, 0x0032);
+	/* setup signal integrity */
+	nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd003, 0x0000);
+	nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00D, 0x00FE);
+	nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00E, 0x0032);
+	if (phy_type == NES_PHY_TYPE_KR) {
+		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00F, 0x000C);
+	} else {
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xF00F, 0x0002);
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xc314, 0x0063);
-
-		/* reset serdes */
-		sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
-				       mac_index * 0x200);
-		sds |= 0x1;
-		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
-				  mac_index * 0x200, sds);
-		sds &= 0xfffffffe;
-		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 +
-				  mac_index * 0x200, sds);
-
-		counter = 0;
-		while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040)
-				&& (counter++ < 5000))
-			;
 	}
-	return 0;
+
+	/* reset serdes */
+	sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 + mac_index * 0x200);
+	sds |= 0x1;
+	nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 + mac_index * 0x200, sds);
+	sds &= 0xfffffffe;
+	nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0 + mac_index * 0x200, sds);
+
+	counter = 0;
+	while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040)
+			&& (counter++ < 5000))
+		;
+
+	return ret;
+}
+
+
+/**
+ * nes_init_phy
+ */
+int nes_init_phy(struct nes_device *nesdev)
+{
+	struct nes_adapter *nesadapter = nesdev->nesadapter;
+	u32 mac_index = nesdev->mac_index;
+	u32 tx_config = 0;
+	unsigned long flags;
+	u8  phy_type = nesadapter->phy_type[mac_index];
+	u8  phy_index = nesadapter->phy_index[mac_index];
+	int ret = 0;
+
+	tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
+	if (phy_type == NES_PHY_TYPE_1G) {
+		/* setup 1G MDIO operation */
+		tx_config &= 0xFFFFFFE3;
+		tx_config |= 0x04;
+	} else {
+		/* setup 10G MDIO operation */
+		tx_config &= 0xFFFFFFE3;
+		tx_config |= 0x15;
+	}
+	nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
+
+	spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
+
+	switch (phy_type) {
+	case NES_PHY_TYPE_1G:
+		ret = nes_init_1g_phy(nesdev, phy_type, phy_index);
+		break;
+	case NES_PHY_TYPE_ARGUS:
+	case NES_PHY_TYPE_SFP_D:
+	case NES_PHY_TYPE_KR:
+		ret = nes_init_2025_phy(nesdev, phy_type, phy_index);
+		break;
+	}
+
+	spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
+
+	return ret;
 }
 
 
@@ -1819,9 +1899,14 @@
 	u16  wqe_fragment_index;
 	u64 wqe_frag;
 	u32 cqp_head;
+	u32 wqm_cfg0;
 	unsigned long flags;
 	int ret;
 
+	/* clear wqe stall before destroying NIC QP */
+	wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0);
+	nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF);
+
 	/* Free remaining NIC receive buffers */
 	while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
 		nic_rqe   = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
@@ -1940,6 +2025,9 @@
 
 	pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,
 			nesvnic->nic_pbase);
+
+	/* restore old wqm_cfg0 value */
+	nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0);
 }
 
 /**
@@ -2460,23 +2548,9 @@
 			}
 		} else {
 			switch (nesadapter->phy_type[mac_index]) {
-			case NES_PHY_TYPE_IRIS:
-				nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
-				temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
-				u32temp = 20;
-				do {
-					nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
-					phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
-					if ((phy_data == temp_phy_data) || (!(--u32temp)))
-						break;
-					temp_phy_data = phy_data;
-				} while (1);
-				nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
-					__func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
-				break;
-
 			case NES_PHY_TYPE_ARGUS:
 			case NES_PHY_TYPE_SFP_D:
+			case NES_PHY_TYPE_KR:
 				/* clear the alarms */
 				nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0x0008);
 				nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc001);
@@ -3352,8 +3426,6 @@
 	u16 async_event_id;
 	u8 tcp_state;
 	u8 iwarp_state;
-	int must_disconn = 1;
-	int must_terminate = 0;
 	struct ib_event ibevent;
 
 	nes_debug(NES_DBG_AEQ, "\n");
@@ -3367,6 +3439,8 @@
 		BUG_ON(!context);
 	}
 
+	/* context is nesqp unless async_event_id == CQ ERROR */
+	nesqp = (struct nes_qp *)(unsigned long)context;
 	async_event_id = (u16)aeq_info;
 	tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
 	iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
@@ -3378,8 +3452,6 @@
 
 	switch (async_event_id) {
 		case NES_AEQE_AEID_LLP_FIN_RECEIVED:
-			nesqp = (struct nes_qp *)(unsigned long)context;
-
 			if (nesqp->term_flags)
 				return; /* Ignore it, wait for close complete */
 
@@ -3394,79 +3466,48 @@
 						async_event_id, nesqp->last_aeq, tcp_state);
 			}
 
-			if ((tcp_state != NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
-					(nesqp->ibqp_state != IB_QPS_RTS)) {
-				/* FIN Received but tcp state or IB state moved on,
-						should expect a	close complete */
-				return;
-			}
-
+			break;
 		case NES_AEQE_AEID_LLP_CLOSE_COMPLETE:
-			nesqp = (struct nes_qp *)(unsigned long)context;
 			if (nesqp->term_flags) {
 				nes_terminate_done(nesqp, 0);
 				return;
 			}
+			spin_lock_irqsave(&nesqp->lock, flags);
+			nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
+			spin_unlock_irqrestore(&nesqp->lock, flags);
+			nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_CLOSING, 0, 0);
+			nes_cm_disconn(nesqp);
+			break;
 
-		case NES_AEQE_AEID_LLP_CONNECTION_RESET:
 		case NES_AEQE_AEID_RESET_SENT:
-			nesqp = (struct nes_qp *)(unsigned long)context;
-			if (async_event_id == NES_AEQE_AEID_RESET_SENT) {
-				tcp_state = NES_AEQE_TCP_STATE_CLOSED;
-			}
+			tcp_state = NES_AEQE_TCP_STATE_CLOSED;
 			spin_lock_irqsave(&nesqp->lock, flags);
 			nesqp->hw_iwarp_state = iwarp_state;
 			nesqp->hw_tcp_state = tcp_state;
 			nesqp->last_aeq = async_event_id;
-
-			if ((tcp_state == NES_AEQE_TCP_STATE_CLOSED) ||
-					(tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT)) {
-				nesqp->hte_added = 0;
-				next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE;
-			}
-
-			if ((nesqp->ibqp_state == IB_QPS_RTS) &&
-					((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
-					(async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
-				switch (nesqp->hw_iwarp_state) {
-					case NES_AEQE_IWARP_STATE_RTS:
-						next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
-						nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
-						break;
-					case NES_AEQE_IWARP_STATE_TERMINATE:
-						must_disconn = 0; /* terminate path takes care of disconn */
-						if (nesqp->term_flags == 0)
-							must_terminate = 1;
-						break;
-				}
-			} else {
-				if (async_event_id ==  NES_AEQE_AEID_LLP_FIN_RECEIVED) {
-					/* FIN Received but ib state not RTS,
-							close complete will be on its way */
-					must_disconn = 0;
-				}
-			}
+			nesqp->hte_added = 0;
 			spin_unlock_irqrestore(&nesqp->lock, flags);
+			next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE;
+			nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0);
+			nes_cm_disconn(nesqp);
+			break;
 
-			if (must_terminate)
-				nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
-			else if (must_disconn) {
-				if (next_iwarp_state) {
-					nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X\n",
-						  nesqp->hwqp.qp_id, next_iwarp_state);
-					nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0);
-				}
-				nes_cm_disconn(nesqp);
-			}
+		case NES_AEQE_AEID_LLP_CONNECTION_RESET:
+			if (atomic_read(&nesqp->close_timer_started))
+				return;
+			spin_lock_irqsave(&nesqp->lock, flags);
+			nesqp->hw_iwarp_state = iwarp_state;
+			nesqp->hw_tcp_state = tcp_state;
+			nesqp->last_aeq = async_event_id;
+			spin_unlock_irqrestore(&nesqp->lock, flags);
+			nes_cm_disconn(nesqp);
 			break;
 
 		case NES_AEQE_AEID_TERMINATE_SENT:
-			nesqp = (struct nes_qp *)(unsigned long)context;
 			nes_terminate_send_fin(nesdev, nesqp, aeqe);
 			break;
 
 		case NES_AEQE_AEID_LLP_TERMINATE_RECEIVED:
-			nesqp = (struct nes_qp *)(unsigned long)context;
 			nes_terminate_received(nesdev, nesqp, aeqe);
 			break;
 
@@ -3480,7 +3521,8 @@
 		case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
 		case NES_AEQE_AEID_AMP_BOUNDS_VIOLATION:
 		case NES_AEQE_AEID_AMP_TO_WRAP:
-			nesqp = (struct nes_qp *)(unsigned long)context;
+			printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_ACCESS_ERR\n",
+					nesqp->hwqp.qp_id, async_event_id);
 			nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_ACCESS_ERR);
 			break;
 
@@ -3488,7 +3530,6 @@
 		case NES_AEQE_AEID_LLP_SEGMENT_TOO_SMALL:
 		case NES_AEQE_AEID_DDP_UBE_INVALID_MO:
 		case NES_AEQE_AEID_DDP_UBE_INVALID_QN:
-			nesqp = (struct nes_qp *)(unsigned long)context;
 			if (iwarp_opcode(nesqp, aeq_info) > IWARP_OPCODE_TERM) {
 				aeq_info &= 0xffff0000;
 				aeq_info |= NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE;
@@ -3530,7 +3571,8 @@
 		case NES_AEQE_AEID_STAG_ZERO_INVALID:
 		case NES_AEQE_AEID_ROE_INVALID_RDMA_READ_REQUEST:
 		case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
-			nesqp = (struct nes_qp *)(unsigned long)context;
+			printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_FATAL\n",
+					nesqp->hwqp.qp_id, async_event_id);
 			nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
 			break;
 
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 084be0e..bbbfe9f 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -37,12 +37,12 @@
 
 #define NES_PHY_TYPE_CX4       1
 #define NES_PHY_TYPE_1G        2
-#define NES_PHY_TYPE_IRIS      3
 #define NES_PHY_TYPE_ARGUS     4
 #define NES_PHY_TYPE_PUMA_1G   5
 #define NES_PHY_TYPE_PUMA_10G  6
 #define NES_PHY_TYPE_GLADIUS   7
 #define NES_PHY_TYPE_SFP_D     8
+#define NES_PHY_TYPE_KR	       9
 
 #define NES_MULTICAST_PF_MAX 8
 
@@ -160,6 +160,7 @@
 	NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI = 0x7004,
 	NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO = 0x7008,
 	NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI = 0x700c,
+	NES_IDX_WQM_CONFIG0 = 0x5000,
 	NES_IDX_WQM_CONFIG1 = 0x5004,
 	NES_IDX_CM_CONFIG = 0x5100,
 	NES_IDX_NIC_LOGPORT_TO_PHYPORT = 0x6000,
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 9384f5d..91fdde3 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -1243,8 +1243,8 @@
 	target_stat_values[++index] = cm_packets_received;
 	target_stat_values[++index] = cm_packets_dropped;
 	target_stat_values[++index] = cm_packets_retrans;
-	target_stat_values[++index] = cm_listens_created;
-	target_stat_values[++index] = cm_listens_destroyed;
+	target_stat_values[++index] = atomic_read(&cm_listens_created);
+	target_stat_values[++index] = atomic_read(&cm_listens_destroyed);
 	target_stat_values[++index] = cm_backlog_drops;
 	target_stat_values[++index] = atomic_read(&cm_loopbacks);
 	target_stat_values[++index] = atomic_read(&cm_nodes_created);
@@ -1474,9 +1474,9 @@
 		}
 		return 0;
 	}
-	if ((phy_type == NES_PHY_TYPE_IRIS) ||
-	    (phy_type == NES_PHY_TYPE_ARGUS) ||
-	    (phy_type == NES_PHY_TYPE_SFP_D)) {
+	if ((phy_type == NES_PHY_TYPE_ARGUS) ||
+	    (phy_type == NES_PHY_TYPE_SFP_D) ||
+	    (phy_type == NES_PHY_TYPE_KR)) {
 		et_cmd->transceiver = XCVR_EXTERNAL;
 		et_cmd->port        = PORT_FIBRE;
 		et_cmd->supported   = SUPPORTED_FIBRE;
@@ -1595,9 +1595,7 @@
 	struct nes_vnic *nesvnic;
 	struct net_device *netdev;
 	struct nic_qp_map *curr_qp_map;
-	u32 u32temp;
-	u16 phy_data;
-	u16 temp_phy_data;
+	u8 phy_type = nesdev->nesadapter->phy_type[nesdev->mac_index];
 
 	netdev = alloc_etherdev(sizeof(struct nes_vnic));
 	if (!netdev) {
@@ -1705,66 +1703,51 @@
 
 	if ((nesdev->netdev_count == 0) &&
 	    ((PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index) ||
-	     ((nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) &&
+	     ((phy_type == NES_PHY_TYPE_PUMA_1G) &&
 	      (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) ||
 	       ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) {
-		/*
-		 * nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n",
-		 *		NES_IDX_PHY_PCS_CONTROL_STATUS0 + (0x200 * (nesvnic->logical_port & 1)));
-		 */
+		u32 u32temp;
+		u32 link_mask;
+		u32 link_val;
+
 		u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
 				(0x200 * (nesdev->mac_index & 1)));
-		if (nesdev->nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_PUMA_1G) {
+		if (phy_type != NES_PHY_TYPE_PUMA_1G) {
 			u32temp |= 0x00200000;
 			nes_write_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
 				(0x200 * (nesdev->mac_index & 1)), u32temp);
 		}
 
-		u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
-				(0x200 * (nesdev->mac_index & 1)));
-
-		if ((u32temp&0x0f1f0000) == 0x0f0f0000) {
-			if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_IRIS) {
-				nes_init_phy(nesdev);
-				nes_read_10G_phy_reg(nesdev, nesdev->nesadapter->phy_index[nesdev->mac_index], 1, 1);
-				temp_phy_data = (u16)nes_read_indexed(nesdev,
-									NES_IDX_MAC_MDIO_CONTROL);
-				u32temp = 20;
-				do {
-					nes_read_10G_phy_reg(nesdev, nesdev->nesadapter->phy_index[nesdev->mac_index], 1, 1);
-					phy_data = (u16)nes_read_indexed(nesdev,
-									NES_IDX_MAC_MDIO_CONTROL);
-					if ((phy_data == temp_phy_data) || (!(--u32temp)))
-						break;
-					temp_phy_data = phy_data;
-				} while (1);
-				if (phy_data & 4) {
-					nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
-					nesvnic->linkup = 1;
-				} else {
-					nes_debug(NES_DBG_INIT, "The Link is DOWN!!.\n");
-				}
+		/* Check and set linkup here.  This is for back to back */
+		/* configuration where second port won't get link interrupt */
+		switch (phy_type) {
+		case NES_PHY_TYPE_PUMA_1G:
+			if (nesdev->mac_index < 2) {
+				link_mask = 0x01010000;
+				link_val = 0x01010000;
 			} else {
-				nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
-				nesvnic->linkup = 1;
+				link_mask = 0x02020000;
+				link_val = 0x02020000;
 			}
-		} else if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) {
-			nes_debug(NES_DBG_INIT, "mac_index=%d, logical_port=%d, u32temp=0x%04X, PCI_FUNC=%d\n",
-				nesdev->mac_index, nesvnic->logical_port, u32temp, PCI_FUNC(nesdev->pcidev->devfn));
-			if (((nesdev->mac_index < 2) && ((u32temp&0x01010000) == 0x01010000)) ||
-			    ((nesdev->mac_index > 1) && ((u32temp&0x02020000) == 0x02020000)))  {
-				nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
-				nesvnic->linkup = 1;
-			}
+			break;
+		default:
+			link_mask = 0x0f1f0000;
+			link_val = 0x0f0f0000;
+			break;
 		}
+
+		u32temp = nes_read_indexed(nesdev,
+					   NES_IDX_PHY_PCS_CONTROL_STATUS0 +
+					   (0x200 * (nesdev->mac_index & 1)));
+		if ((u32temp & link_mask) == link_val)
+			nesvnic->linkup = 1;
+
 		/* clear the MAC interrupt status, assumes direct logical to physical mapping */
 		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index));
 		nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp);
 		nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index), u32temp);
 
-		if (nesdev->nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_IRIS)
-			nes_init_phy(nesdev);
-
+		nes_init_phy(nesdev);
 	}
 
 	return netdev;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 64d3136..6992829 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -228,7 +228,7 @@
 	/* Check for SQ overflow */
 	if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) {
 		spin_unlock_irqrestore(&nesqp->lock, flags);
-		return -EINVAL;
+		return -ENOMEM;
 	}
 
 	wqe = &nesqp->hwqp.sq_vbase[head];
@@ -1323,6 +1323,7 @@
 			nesqp->nesqp_context->aeq_token_low =  cpu_to_le32((u32)((unsigned long)(nesqp)));
 			nesqp->nesqp_context->aeq_token_high =  cpu_to_le32((u32)(upper_32_bits((unsigned long)(nesqp))));
 			nesqp->nesqp_context->ird_ord_sizes = cpu_to_le32(NES_QPCONTEXT_ORDIRD_ALSMM |
+					NES_QPCONTEXT_ORDIRD_AAH |
 					((((u32)nesadapter->max_irrq_wr) <<
 					NES_QPCONTEXT_ORDIRD_IRDSIZE_SHIFT) & NES_QPCONTEXT_ORDIRD_IRDSIZE_MASK));
 			if (disable_mpa_crc) {
@@ -3294,7 +3295,7 @@
 
 		/* Check for SQ overflow */
 		if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) {
-			err = -EINVAL;
+			err = -ENOMEM;
 			break;
 		}
 
@@ -3577,7 +3578,7 @@
 		}
 		/* Check for RQ overflow */
 		if (((head + (2 * qsize) - nesqp->hwqp.rq_tail) % qsize) == (qsize - 1)) {
-			err = -EINVAL;
+			err = -ENOMEM;
 			break;
 		}
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 83a7751..bc65837 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -708,6 +708,7 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_cm_tx_buf *tx_req;
 	u64 addr;
+	int rc;
 
 	if (unlikely(skb->len > tx->mtu)) {
 		ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n",
@@ -739,9 +740,10 @@
 
 	tx_req->mapping = addr;
 
-	if (unlikely(post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1),
-			       addr, skb->len))) {
-		ipoib_warn(priv, "post_send failed\n");
+	rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1),
+		       addr, skb->len);
+	if (unlikely(rc)) {
+		ipoib_warn(priv, "post_send failed, error %d\n", rc);
 		++dev->stats.tx_errors;
 		ib_dma_unmap_single(priv->ca, addr, skb->len, DMA_TO_DEVICE);
 		dev_kfree_skb_any(skb);
@@ -752,6 +754,8 @@
 		if (++priv->tx_outstanding == ipoib_sendq_size) {
 			ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
 				  tx->qp->qp_num);
+			if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP))
+				ipoib_warn(priv, "request notify on send CQ failed\n");
 			netif_stop_queue(dev);
 		}
 	}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
index e9795f6..d10b4ec 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
@@ -55,9 +55,7 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
 	coal->rx_coalesce_usecs = priv->ethtool.coalesce_usecs;
-	coal->tx_coalesce_usecs = priv->ethtool.coalesce_usecs;
 	coal->rx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
-	coal->tx_max_coalesced_frames = priv->ethtool.max_coalesced_frames;
 
 	return 0;
 }
@@ -69,10 +67,8 @@
 	int ret;
 
 	/*
-	 * Since IPoIB uses a single CQ for both rx and tx, we assume
-	 * that rx params dictate the configuration.  These values are
-	 * saved in the private data and returned when ipoib_get_coalesce()
-	 * is called.
+	 * These values are saved in the private data and returned
+	 * when ipoib_get_coalesce() is called
 	 */
 	if (coal->rx_coalesce_usecs       > 0xffff ||
 	    coal->rx_max_coalesced_frames > 0xffff)
@@ -85,8 +81,6 @@
 		return ret;
 	}
 
-	coal->tx_coalesce_usecs       = coal->rx_coalesce_usecs;
-	coal->tx_max_coalesced_frames = coal->rx_max_coalesced_frames;
 	priv->ethtool.coalesce_usecs       = coal->rx_coalesce_usecs;
 	priv->ethtool.max_coalesced_frames = coal->rx_max_coalesced_frames;
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 8c91d9f..5df40b1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -529,7 +529,7 @@
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_tx_buf *tx_req;
-	int hlen;
+	int hlen, rc;
 	void *phead;
 
 	if (skb_is_gso(skb)) {
@@ -585,9 +585,10 @@
 		netif_stop_queue(dev);
 	}
 
-	if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
-			       address->ah, qpn, tx_req, phead, hlen))) {
-		ipoib_warn(priv, "post_send failed\n");
+	rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
+		       address->ah, qpn, tx_req, phead, hlen);
+	if (unlikely(rc)) {
+		ipoib_warn(priv, "post_send failed, error %d\n", rc);
 		++dev->stats.tx_errors;
 		--priv->tx_outstanding;
 		ipoib_dma_unmap_tx(priv->ca, tx_req);
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 5f7a6fc..71237f8f 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -128,6 +128,28 @@
 	return 0;
 }
 
+int iser_initialize_task_headers(struct iscsi_task *task,
+						struct iser_tx_desc *tx_desc)
+{
+	struct iscsi_iser_conn *iser_conn = task->conn->dd_data;
+	struct iser_device     *device    = iser_conn->ib_conn->device;
+	struct iscsi_iser_task *iser_task = task->dd_data;
+	u64 dma_addr;
+
+	dma_addr = ib_dma_map_single(device->ib_device, (void *)tx_desc,
+				ISER_HEADERS_LEN, DMA_TO_DEVICE);
+	if (ib_dma_mapping_error(device->ib_device, dma_addr))
+		return -ENOMEM;
+
+	tx_desc->dma_addr = dma_addr;
+	tx_desc->tx_sg[0].addr   = tx_desc->dma_addr;
+	tx_desc->tx_sg[0].length = ISER_HEADERS_LEN;
+	tx_desc->tx_sg[0].lkey   = device->mr->lkey;
+
+	iser_task->headers_initialized	= 1;
+	iser_task->iser_conn		= iser_conn;
+	return 0;
+}
 /**
  * iscsi_iser_task_init - Initialize task
  * @task: iscsi task
@@ -137,17 +159,17 @@
 static int
 iscsi_iser_task_init(struct iscsi_task *task)
 {
-	struct iscsi_iser_conn *iser_conn  = task->conn->dd_data;
 	struct iscsi_iser_task *iser_task = task->dd_data;
 
+	if (!iser_task->headers_initialized)
+		if (iser_initialize_task_headers(task, &iser_task->desc))
+			return -ENOMEM;
+
 	/* mgmt task */
-	if (!task->sc) {
-		iser_task->desc.data = task->data;
+	if (!task->sc)
 		return 0;
-	}
 
 	iser_task->command_sent = 0;
-	iser_task->iser_conn    = iser_conn;
 	iser_task_rdma_init(iser_task);
 	return 0;
 }
@@ -168,7 +190,7 @@
 {
 	int error = 0;
 
-	iser_dbg("task deq [cid %d itt 0x%x]\n", conn->id, task->itt);
+	iser_dbg("mtask xmit [cid %d itt 0x%x]\n", conn->id, task->itt);
 
 	error = iser_send_control(conn, task);
 
@@ -178,9 +200,6 @@
 	 * - if yes, the task is recycled at iscsi_complete_pdu
 	 * - if no,  the task is recycled at iser_snd_completion
 	 */
-	if (error && error != -ENOBUFS)
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-
 	return error;
 }
 
@@ -232,7 +251,7 @@
 			   task->imm_count, task->unsol_r2t.data_length);
 	}
 
-	iser_dbg("task deq [cid %d itt 0x%x]\n",
+	iser_dbg("ctask xmit [cid %d itt 0x%x]\n",
 		   conn->id, task->itt);
 
 	/* Send the cmd PDU */
@@ -248,8 +267,6 @@
 		error = iscsi_iser_task_xmit_unsol_data(conn, task);
 
  iscsi_iser_task_xmit_exit:
-	if (error && error != -ENOBUFS)
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 	return error;
 }
 
@@ -283,7 +300,7 @@
 	 * due to issues with the login code re iser sematics
 	 * this not set in iscsi_conn_setup - FIXME
 	 */
-	conn->max_recv_dlength = 128;
+	conn->max_recv_dlength = ISER_RECV_DATA_SEG_LEN;
 
 	iser_conn = conn->dd_data;
 	conn->dd_data = iser_conn;
@@ -401,7 +418,7 @@
 	struct Scsi_Host *shost;
 	struct iser_conn *ib_conn;
 
-	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, 1);
+	shost = iscsi_host_alloc(&iscsi_iser_sht, 0, 0);
 	if (!shost)
 		return NULL;
 	shost->transportt = iscsi_iser_scsi_transport;
@@ -675,7 +692,7 @@
 	memset(&ig, 0, sizeof(struct iser_global));
 
 	ig.desc_cache = kmem_cache_create("iser_descriptors",
-					  sizeof (struct iser_desc),
+					  sizeof(struct iser_tx_desc),
 					  0, SLAB_HWCACHE_ALIGN,
 					  NULL);
 	if (ig.desc_cache == NULL)
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 9d529ca..036934c 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -102,9 +102,9 @@
 #define ISER_MAX_TX_MISC_PDUS		6 /* NOOP_OUT(2), TEXT(1),         *
 					   * SCSI_TMFUNC(2), LOGOUT(1) */
 
-#define ISER_QP_MAX_RECV_DTOS		(ISCSI_DEF_XMIT_CMDS_MAX + \
-					ISER_MAX_RX_MISC_PDUS    +  \
-					ISER_MAX_TX_MISC_PDUS)
+#define ISER_QP_MAX_RECV_DTOS		(ISCSI_DEF_XMIT_CMDS_MAX)
+
+#define ISER_MIN_POSTED_RX		(ISCSI_DEF_XMIT_CMDS_MAX >> 2)
 
 /* the max TX (send) WR supported by the iSER QP is defined by                 *
  * max_send_wr = T * (1 + D) + C ; D is how many inflight dataouts we expect   *
@@ -132,6 +132,12 @@
 	__be64  read_va;
 } __attribute__((packed));
 
+/* Constant PDU lengths calculations */
+#define ISER_HEADERS_LEN  (sizeof(struct iser_hdr) + sizeof(struct iscsi_hdr))
+
+#define ISER_RECV_DATA_SEG_LEN	128
+#define ISER_RX_PAYLOAD_SIZE	(ISER_HEADERS_LEN + ISER_RECV_DATA_SEG_LEN)
+#define ISER_RX_LOGIN_SIZE	(ISER_HEADERS_LEN + ISCSI_DEF_MAX_RECV_SEG_LEN)
 
 /* Length of an object name string */
 #define ISER_OBJECT_NAME_SIZE		    64
@@ -187,51 +193,43 @@
 	struct iser_mem_reg     reg;        /* memory registration info        */
 	void                    *virt_addr;
 	struct iser_device      *device;    /* device->device for dma_unmap    */
-	u64                     dma_addr;   /* if non zero, addr for dma_unmap */
 	enum dma_data_direction direction;  /* direction for dma_unmap	       */
 	unsigned int            data_size;
-	atomic_t                ref_count;  /* refcount, freed when dec to 0   */
-};
-
-#define MAX_REGD_BUF_VECTOR_LEN	2
-
-struct iser_dto {
-	struct iscsi_iser_task *task;
-	struct iser_conn *ib_conn;
-	int                        notify_enable;
-
-	/* vector of registered buffers */
-	unsigned int               regd_vector_len;
-	struct iser_regd_buf       *regd[MAX_REGD_BUF_VECTOR_LEN];
-
-	/* offset into the registered buffer may be specified */
-	unsigned int               offset[MAX_REGD_BUF_VECTOR_LEN];
-
-	/* a smaller size may be specified, if 0, then full size is used */
-	unsigned int               used_sz[MAX_REGD_BUF_VECTOR_LEN];
 };
 
 enum iser_desc_type {
-	ISCSI_RX,
 	ISCSI_TX_CONTROL ,
 	ISCSI_TX_SCSI_COMMAND,
 	ISCSI_TX_DATAOUT
 };
 
-struct iser_desc {
+struct iser_tx_desc {
 	struct iser_hdr              iser_header;
 	struct iscsi_hdr             iscsi_header;
-	struct iser_regd_buf         hdr_regd_buf;
-	void                         *data;         /* used by RX & TX_CONTROL */
-	struct iser_regd_buf         data_regd_buf; /* used by RX & TX_CONTROL */
 	enum   iser_desc_type        type;
-	struct iser_dto              dto;
+	u64		             dma_addr;
+	/* sg[0] points to iser/iscsi headers, sg[1] optionally points to either
+	of immediate data, unsolicited data-out or control (login,text) */
+	struct ib_sge		     tx_sg[2];
+	int                          num_sge;
 };
 
+#define ISER_RX_PAD_SIZE	(256 - (ISER_RX_PAYLOAD_SIZE + \
+					sizeof(u64) + sizeof(struct ib_sge)))
+struct iser_rx_desc {
+	struct iser_hdr              iser_header;
+	struct iscsi_hdr             iscsi_header;
+	char		             data[ISER_RECV_DATA_SEG_LEN];
+	u64		             dma_addr;
+	struct ib_sge		     rx_sg;
+	char		             pad[ISER_RX_PAD_SIZE];
+} __attribute__((packed));
+
 struct iser_device {
 	struct ib_device             *ib_device;
 	struct ib_pd	             *pd;
-	struct ib_cq	             *cq;
+	struct ib_cq	             *rx_cq;
+	struct ib_cq	             *tx_cq;
 	struct ib_mr	             *mr;
 	struct tasklet_struct	     cq_tasklet;
 	struct list_head             ig_list; /* entry in ig devices list */
@@ -250,15 +248,18 @@
 	struct ib_fmr_pool           *fmr_pool;     /* pool of IB FMRs         */
 	int                          disc_evt_flag; /* disconn event delivered */
 	wait_queue_head_t	     wait;          /* waitq for conn/disconn  */
-	atomic_t                     post_recv_buf_count; /* posted rx count   */
+	int                          post_recv_buf_count; /* posted rx count  */
 	atomic_t                     post_send_buf_count; /* posted tx count   */
-	atomic_t                     unexpected_pdu_count;/* count of received *
-							   * unexpected pdus   *
-							   * not yet retired   */
 	char 			     name[ISER_OBJECT_NAME_SIZE];
 	struct iser_page_vec         *page_vec;     /* represents SG to fmr maps*
 						     * maps serialized as tx is*/
 	struct list_head	     conn_list;       /* entry in ig conn list */
+
+	char  			     *login_buf;
+	u64 			     login_dma;
+	unsigned int 		     rx_desc_head;
+	struct iser_rx_desc	     *rx_descs;
+	struct ib_recv_wr	     rx_wr[ISER_MIN_POSTED_RX];
 };
 
 struct iscsi_iser_conn {
@@ -267,7 +268,7 @@
 };
 
 struct iscsi_iser_task {
-	struct iser_desc             desc;
+	struct iser_tx_desc          desc;
 	struct iscsi_iser_conn	     *iser_conn;
 	enum iser_task_status 	     status;
 	int                          command_sent;  /* set if command  sent  */
@@ -275,6 +276,7 @@
 	struct iser_regd_buf         rdma_regd[ISER_DIRS_NUM];/* regd rdma buf */
 	struct iser_data_buf         data[ISER_DIRS_NUM];     /* orig. data des*/
 	struct iser_data_buf         data_copy[ISER_DIRS_NUM];/* contig. copy  */
+	int                          headers_initialized;
 };
 
 struct iser_page_vec {
@@ -322,22 +324,17 @@
 
 void iser_conn_terminate(struct iser_conn *ib_conn);
 
-void iser_rcv_completion(struct iser_desc *desc,
-			 unsigned long    dto_xfer_len);
+void iser_rcv_completion(struct iser_rx_desc *desc,
+			 unsigned long    dto_xfer_len,
+			struct iser_conn *ib_conn);
 
-void iser_snd_completion(struct iser_desc *desc);
+void iser_snd_completion(struct iser_tx_desc *desc, struct iser_conn *ib_conn);
 
 void iser_task_rdma_init(struct iscsi_iser_task *task);
 
 void iser_task_rdma_finalize(struct iscsi_iser_task *task);
 
-void iser_dto_buffs_release(struct iser_dto *dto);
-
-int  iser_regd_buff_release(struct iser_regd_buf *regd_buf);
-
-void iser_reg_single(struct iser_device      *device,
-		     struct iser_regd_buf    *regd_buf,
-		     enum dma_data_direction direction);
+void iser_free_rx_descriptors(struct iser_conn *ib_conn);
 
 void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *task,
 				     enum iser_data_dir         cmd_dir);
@@ -356,11 +353,9 @@
 
 void iser_unreg_mem(struct iser_mem_reg *mem_reg);
 
-int  iser_post_recv(struct iser_desc *rx_desc);
-int  iser_post_send(struct iser_desc *tx_desc);
-
-int iser_conn_state_comp(struct iser_conn *ib_conn,
-			 enum iser_ib_conn_state comp);
+int  iser_post_recvl(struct iser_conn *ib_conn);
+int  iser_post_recvm(struct iser_conn *ib_conn, int count);
+int  iser_post_send(struct iser_conn *ib_conn, struct iser_tx_desc *tx_desc);
 
 int iser_dma_map_task_data(struct iscsi_iser_task *iser_task,
 			    struct iser_data_buf       *data,
@@ -368,4 +363,6 @@
 			    enum   dma_data_direction  dma_dir);
 
 void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task);
+int  iser_initialize_task_headers(struct iscsi_task *task,
+			struct iser_tx_desc *tx_desc);
 #endif
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 9de6402..0b9ef07 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -39,29 +39,6 @@
 
 #include "iscsi_iser.h"
 
-/* Constant PDU lengths calculations */
-#define ISER_TOTAL_HEADERS_LEN  (sizeof (struct iser_hdr) + \
-				 sizeof (struct iscsi_hdr))
-
-/* iser_dto_add_regd_buff - increments the reference count for *
- * the registered buffer & adds it to the DTO object           */
-static void iser_dto_add_regd_buff(struct iser_dto *dto,
-				   struct iser_regd_buf *regd_buf,
-				   unsigned long use_offset,
-				   unsigned long use_size)
-{
-	int add_idx;
-
-	atomic_inc(&regd_buf->ref_count);
-
-	add_idx = dto->regd_vector_len;
-	dto->regd[add_idx] = regd_buf;
-	dto->used_sz[add_idx] = use_size;
-	dto->offset[add_idx] = use_offset;
-
-	dto->regd_vector_len++;
-}
-
 /* Register user buffer memory and initialize passive rdma
  *  dto descriptor. Total data size is stored in
  *  iser_task->data[ISER_DIR_IN].data_len
@@ -122,9 +99,9 @@
 	struct iscsi_iser_task *iser_task = task->dd_data;
 	struct iser_regd_buf *regd_buf;
 	int err;
-	struct iser_dto *send_dto = &iser_task->desc.dto;
 	struct iser_hdr *hdr = &iser_task->desc.iser_header;
 	struct iser_data_buf *buf_out = &iser_task->data[ISER_DIR_OUT];
+	struct ib_sge *tx_dsg = &iser_task->desc.tx_sg[1];
 
 	err = iser_dma_map_task_data(iser_task,
 				     buf_out,
@@ -163,135 +140,100 @@
 	if (imm_sz > 0) {
 		iser_dbg("Cmd itt:%d, WRITE, adding imm.data sz: %d\n",
 			 task->itt, imm_sz);
-		iser_dto_add_regd_buff(send_dto,
-				       regd_buf,
-				       0,
-				       imm_sz);
+		tx_dsg->addr   = regd_buf->reg.va;
+		tx_dsg->length = imm_sz;
+		tx_dsg->lkey   = regd_buf->reg.lkey;
+		iser_task->desc.num_sge = 2;
 	}
 
 	return 0;
 }
 
-/**
- * iser_post_receive_control - allocates, initializes and posts receive DTO.
- */
-static int iser_post_receive_control(struct iscsi_conn *conn)
-{
-	struct iscsi_iser_conn *iser_conn = conn->dd_data;
-	struct iser_desc     *rx_desc;
-	struct iser_regd_buf *regd_hdr;
-	struct iser_regd_buf *regd_data;
-	struct iser_dto      *recv_dto = NULL;
-	struct iser_device  *device = iser_conn->ib_conn->device;
-	int rx_data_size, err;
-	int posts, outstanding_unexp_pdus;
-
-	/* for the login sequence we must support rx of upto 8K; login is done
-	 * after conn create/bind (connect) and conn stop/bind (reconnect),
-	 * what's common for both schemes is that the connection is not started
-	 */
-	if (conn->c_stage != ISCSI_CONN_STARTED)
-		rx_data_size = ISCSI_DEF_MAX_RECV_SEG_LEN;
-	else /* FIXME till user space sets conn->max_recv_dlength correctly */
-		rx_data_size = 128;
-
-	outstanding_unexp_pdus =
-		atomic_xchg(&iser_conn->ib_conn->unexpected_pdu_count, 0);
-
-	/*
-	 * in addition to the response buffer, replace those consumed by
-	 * unexpected pdus.
-	 */
-	for (posts = 0; posts < 1 + outstanding_unexp_pdus; posts++) {
-		rx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO);
-		if (rx_desc == NULL) {
-			iser_err("Failed to alloc desc for post recv %d\n",
-				 posts);
-			err = -ENOMEM;
-			goto post_rx_cache_alloc_failure;
-		}
-		rx_desc->type = ISCSI_RX;
-		rx_desc->data = kmalloc(rx_data_size, GFP_NOIO);
-		if (rx_desc->data == NULL) {
-			iser_err("Failed to alloc data buf for post recv %d\n",
-				 posts);
-			err = -ENOMEM;
-			goto post_rx_kmalloc_failure;
-		}
-
-		recv_dto = &rx_desc->dto;
-		recv_dto->ib_conn = iser_conn->ib_conn;
-		recv_dto->regd_vector_len = 0;
-
-		regd_hdr = &rx_desc->hdr_regd_buf;
-		memset(regd_hdr, 0, sizeof(struct iser_regd_buf));
-		regd_hdr->device  = device;
-		regd_hdr->virt_addr  = rx_desc; /* == &rx_desc->iser_header */
-		regd_hdr->data_size  = ISER_TOTAL_HEADERS_LEN;
-
-		iser_reg_single(device, regd_hdr, DMA_FROM_DEVICE);
-
-		iser_dto_add_regd_buff(recv_dto, regd_hdr, 0, 0);
-
-		regd_data = &rx_desc->data_regd_buf;
-		memset(regd_data, 0, sizeof(struct iser_regd_buf));
-		regd_data->device  = device;
-		regd_data->virt_addr  = rx_desc->data;
-		regd_data->data_size  = rx_data_size;
-
-		iser_reg_single(device, regd_data, DMA_FROM_DEVICE);
-
-		iser_dto_add_regd_buff(recv_dto, regd_data, 0, 0);
-
-		err = iser_post_recv(rx_desc);
-		if (err) {
-			iser_err("Failed iser_post_recv for post %d\n", posts);
-			goto post_rx_post_recv_failure;
-		}
-	}
-	/* all posts successful */
-	return 0;
-
-post_rx_post_recv_failure:
-	iser_dto_buffs_release(recv_dto);
-	kfree(rx_desc->data);
-post_rx_kmalloc_failure:
-	kmem_cache_free(ig.desc_cache, rx_desc);
-post_rx_cache_alloc_failure:
-	if (posts > 0) {
-		/*
-		 * response buffer posted, but did not replace all unexpected
-		 * pdu recv bufs. Ignore error, retry occurs next send
-		 */
-		outstanding_unexp_pdus -= (posts - 1);
-		err = 0;
-	}
-	atomic_add(outstanding_unexp_pdus,
-		   &iser_conn->ib_conn->unexpected_pdu_count);
-
-	return err;
-}
-
 /* creates a new tx descriptor and adds header regd buffer */
-static void iser_create_send_desc(struct iscsi_iser_conn *iser_conn,
-				  struct iser_desc       *tx_desc)
+static void iser_create_send_desc(struct iser_conn	*ib_conn,
+				  struct iser_tx_desc	*tx_desc)
 {
-	struct iser_regd_buf *regd_hdr = &tx_desc->hdr_regd_buf;
-	struct iser_dto      *send_dto = &tx_desc->dto;
+	struct iser_device *device = ib_conn->device;
 
-	memset(regd_hdr, 0, sizeof(struct iser_regd_buf));
-	regd_hdr->device  = iser_conn->ib_conn->device;
-	regd_hdr->virt_addr  = tx_desc; /* == &tx_desc->iser_header */
-	regd_hdr->data_size  = ISER_TOTAL_HEADERS_LEN;
-
-	send_dto->ib_conn         = iser_conn->ib_conn;
-	send_dto->notify_enable   = 1;
-	send_dto->regd_vector_len = 0;
+	ib_dma_sync_single_for_cpu(device->ib_device,
+		tx_desc->dma_addr, ISER_HEADERS_LEN, DMA_TO_DEVICE);
 
 	memset(&tx_desc->iser_header, 0, sizeof(struct iser_hdr));
 	tx_desc->iser_header.flags = ISER_VER;
 
-	iser_dto_add_regd_buff(send_dto, regd_hdr, 0, 0);
+	tx_desc->num_sge = 1;
+
+	if (tx_desc->tx_sg[0].lkey != device->mr->lkey) {
+		tx_desc->tx_sg[0].lkey = device->mr->lkey;
+		iser_dbg("sdesc %p lkey mismatch, fixing\n", tx_desc);
+	}
+}
+
+
+int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
+{
+	int i, j;
+	u64 dma_addr;
+	struct iser_rx_desc *rx_desc;
+	struct ib_sge       *rx_sg;
+	struct iser_device  *device = ib_conn->device;
+
+	ib_conn->rx_descs = kmalloc(ISER_QP_MAX_RECV_DTOS *
+				sizeof(struct iser_rx_desc), GFP_KERNEL);
+	if (!ib_conn->rx_descs)
+		goto rx_desc_alloc_fail;
+
+	rx_desc = ib_conn->rx_descs;
+
+	for (i = 0; i < ISER_QP_MAX_RECV_DTOS; i++, rx_desc++)  {
+		dma_addr = ib_dma_map_single(device->ib_device, (void *)rx_desc,
+					ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+		if (ib_dma_mapping_error(device->ib_device, dma_addr))
+			goto rx_desc_dma_map_failed;
+
+		rx_desc->dma_addr = dma_addr;
+
+		rx_sg = &rx_desc->rx_sg;
+		rx_sg->addr   = rx_desc->dma_addr;
+		rx_sg->length = ISER_RX_PAYLOAD_SIZE;
+		rx_sg->lkey   = device->mr->lkey;
+	}
+
+	ib_conn->rx_desc_head = 0;
+	return 0;
+
+rx_desc_dma_map_failed:
+	rx_desc = ib_conn->rx_descs;
+	for (j = 0; j < i; j++, rx_desc++)
+		ib_dma_unmap_single(device->ib_device, rx_desc->dma_addr,
+			ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+	kfree(ib_conn->rx_descs);
+	ib_conn->rx_descs = NULL;
+rx_desc_alloc_fail:
+	iser_err("failed allocating rx descriptors / data buffers\n");
+	return -ENOMEM;
+}
+
+void iser_free_rx_descriptors(struct iser_conn *ib_conn)
+{
+	int i;
+	struct iser_rx_desc *rx_desc;
+	struct iser_device *device = ib_conn->device;
+
+	if (ib_conn->login_buf) {
+		ib_dma_unmap_single(device->ib_device, ib_conn->login_dma,
+			ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
+		kfree(ib_conn->login_buf);
+	}
+
+	if (!ib_conn->rx_descs)
+		return;
+
+	rx_desc = ib_conn->rx_descs;
+	for (i = 0; i < ISER_QP_MAX_RECV_DTOS; i++, rx_desc++)
+		ib_dma_unmap_single(device->ib_device, rx_desc->dma_addr,
+			ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+	kfree(ib_conn->rx_descs);
 }
 
 /**
@@ -301,46 +243,23 @@
 {
 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
 
-	int i;
-	/*
-	 * FIXME this value should be declared to the target during login with
-	 * the MaxOutstandingUnexpectedPDUs key when supported
-	 */
-	int initial_post_recv_bufs_num = ISER_MAX_RX_MISC_PDUS;
-
-	iser_dbg("Initially post: %d\n", initial_post_recv_bufs_num);
+	iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
 
 	/* Check that there is no posted recv or send buffers left - */
 	/* they must be consumed during the login phase */
-	BUG_ON(atomic_read(&iser_conn->ib_conn->post_recv_buf_count) != 0);
+	BUG_ON(iser_conn->ib_conn->post_recv_buf_count != 0);
 	BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
 
+	if (iser_alloc_rx_descriptors(iser_conn->ib_conn))
+		return -ENOMEM;
+
 	/* Initial post receive buffers */
-	for (i = 0; i < initial_post_recv_bufs_num; i++) {
-		if (iser_post_receive_control(conn) != 0) {
-			iser_err("Failed to post recv bufs at:%d conn:0x%p\n",
-				 i, conn);
-			return -ENOMEM;
-		}
-	}
-	iser_dbg("Posted %d post recv bufs, conn:0x%p\n", i, conn);
+	if (iser_post_recvm(iser_conn->ib_conn, ISER_MIN_POSTED_RX))
+		return -ENOMEM;
+
 	return 0;
 }
 
-static int
-iser_check_xmit(struct iscsi_conn *conn, void *task)
-{
-	struct iscsi_iser_conn *iser_conn = conn->dd_data;
-
-	if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
-	    ISER_QP_MAX_REQ_DTOS) {
-		iser_dbg("%ld can't xmit task %p\n",jiffies,task);
-		return -ENOBUFS;
-	}
-	return 0;
-}
-
-
 /**
  * iser_send_command - send command PDU
  */
@@ -349,27 +268,18 @@
 {
 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
 	struct iscsi_iser_task *iser_task = task->dd_data;
-	struct iser_dto *send_dto = NULL;
 	unsigned long edtl;
-	int err = 0;
+	int err;
 	struct iser_data_buf *data_buf;
 	struct iscsi_cmd *hdr =  (struct iscsi_cmd *)task->hdr;
 	struct scsi_cmnd *sc  =  task->sc;
-
-	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
-		iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
-		return -EPERM;
-	}
-	if (iser_check_xmit(conn, task))
-		return -ENOBUFS;
+	struct iser_tx_desc *tx_desc = &iser_task->desc;
 
 	edtl = ntohl(hdr->data_length);
 
 	/* build the tx desc regd header and add it to the tx desc dto */
-	iser_task->desc.type = ISCSI_TX_SCSI_COMMAND;
-	send_dto = &iser_task->desc.dto;
-	send_dto->task = iser_task;
-	iser_create_send_desc(iser_conn, &iser_task->desc);
+	tx_desc->type = ISCSI_TX_SCSI_COMMAND;
+	iser_create_send_desc(iser_conn->ib_conn, tx_desc);
 
 	if (hdr->flags & ISCSI_FLAG_CMD_READ)
 		data_buf = &iser_task->data[ISER_DIR_IN];
@@ -398,23 +308,13 @@
 			goto send_command_error;
 	}
 
-	iser_reg_single(iser_conn->ib_conn->device,
-			send_dto->regd[0], DMA_TO_DEVICE);
-
-	if (iser_post_receive_control(conn) != 0) {
-		iser_err("post_recv failed!\n");
-		err = -ENOMEM;
-		goto send_command_error;
-	}
-
 	iser_task->status = ISER_TASK_STATUS_STARTED;
 
-	err = iser_post_send(&iser_task->desc);
+	err = iser_post_send(iser_conn->ib_conn, tx_desc);
 	if (!err)
 		return 0;
 
 send_command_error:
-	iser_dto_buffs_release(send_dto);
 	iser_err("conn %p failed task->itt %d err %d\n",conn, task->itt, err);
 	return err;
 }
@@ -428,20 +328,13 @@
 {
 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
 	struct iscsi_iser_task *iser_task = task->dd_data;
-	struct iser_desc *tx_desc = NULL;
-	struct iser_dto *send_dto = NULL;
+	struct iser_tx_desc *tx_desc = NULL;
+	struct iser_regd_buf *regd_buf;
 	unsigned long buf_offset;
 	unsigned long data_seg_len;
 	uint32_t itt;
 	int err = 0;
-
-	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
-		iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
-		return -EPERM;
-	}
-
-	if (iser_check_xmit(conn, task))
-		return -ENOBUFS;
+	struct ib_sge *tx_dsg;
 
 	itt = (__force uint32_t)hdr->itt;
 	data_seg_len = ntoh24(hdr->dlength);
@@ -450,28 +343,25 @@
 	iser_dbg("%s itt %d dseg_len %d offset %d\n",
 		 __func__,(int)itt,(int)data_seg_len,(int)buf_offset);
 
-	tx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO);
+	tx_desc = kmem_cache_zalloc(ig.desc_cache, GFP_ATOMIC);
 	if (tx_desc == NULL) {
 		iser_err("Failed to alloc desc for post dataout\n");
 		return -ENOMEM;
 	}
 
 	tx_desc->type = ISCSI_TX_DATAOUT;
+	tx_desc->iser_header.flags = ISER_VER;
 	memcpy(&tx_desc->iscsi_header, hdr, sizeof(struct iscsi_hdr));
 
-	/* build the tx desc regd header and add it to the tx desc dto */
-	send_dto = &tx_desc->dto;
-	send_dto->task = iser_task;
-	iser_create_send_desc(iser_conn, tx_desc);
+	/* build the tx desc */
+	iser_initialize_task_headers(task, tx_desc);
 
-	iser_reg_single(iser_conn->ib_conn->device,
-			send_dto->regd[0], DMA_TO_DEVICE);
-
-	/* all data was registered for RDMA, we can use the lkey */
-	iser_dto_add_regd_buff(send_dto,
-			       &iser_task->rdma_regd[ISER_DIR_OUT],
-			       buf_offset,
-			       data_seg_len);
+	regd_buf = &iser_task->rdma_regd[ISER_DIR_OUT];
+	tx_dsg = &tx_desc->tx_sg[1];
+	tx_dsg->addr    = regd_buf->reg.va + buf_offset;
+	tx_dsg->length  = data_seg_len;
+	tx_dsg->lkey    = regd_buf->reg.lkey;
+	tx_desc->num_sge = 2;
 
 	if (buf_offset + data_seg_len > iser_task->data[ISER_DIR_OUT].data_len) {
 		iser_err("Offset:%ld & DSL:%ld in Data-Out "
@@ -485,12 +375,11 @@
 		 itt, buf_offset, data_seg_len);
 
 
-	err = iser_post_send(tx_desc);
+	err = iser_post_send(iser_conn->ib_conn, tx_desc);
 	if (!err)
 		return 0;
 
 send_data_out_error:
-	iser_dto_buffs_release(send_dto);
 	kmem_cache_free(ig.desc_cache, tx_desc);
 	iser_err("conn %p failed err %d\n",conn, err);
 	return err;
@@ -501,64 +390,44 @@
 {
 	struct iscsi_iser_conn *iser_conn = conn->dd_data;
 	struct iscsi_iser_task *iser_task = task->dd_data;
-	struct iser_desc *mdesc = &iser_task->desc;
-	struct iser_dto *send_dto = NULL;
+	struct iser_tx_desc *mdesc = &iser_task->desc;
 	unsigned long data_seg_len;
 	int err = 0;
-	struct iser_regd_buf *regd_buf;
 	struct iser_device *device;
-	unsigned char opcode;
-
-	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
-		iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
-		return -EPERM;
-	}
-
-	if (iser_check_xmit(conn, task))
-		return -ENOBUFS;
 
 	/* build the tx desc regd header and add it to the tx desc dto */
 	mdesc->type = ISCSI_TX_CONTROL;
-	send_dto = &mdesc->dto;
-	send_dto->task = NULL;
-	iser_create_send_desc(iser_conn, mdesc);
+	iser_create_send_desc(iser_conn->ib_conn, mdesc);
 
 	device = iser_conn->ib_conn->device;
 
-	iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE);
-
 	data_seg_len = ntoh24(task->hdr->dlength);
 
 	if (data_seg_len > 0) {
-		regd_buf = &mdesc->data_regd_buf;
-		memset(regd_buf, 0, sizeof(struct iser_regd_buf));
-		regd_buf->device = device;
-		regd_buf->virt_addr = task->data;
-		regd_buf->data_size = task->data_count;
-		iser_reg_single(device, regd_buf,
-				DMA_TO_DEVICE);
-		iser_dto_add_regd_buff(send_dto, regd_buf,
-				       0,
-				       data_seg_len);
-	}
-
-	opcode = task->hdr->opcode & ISCSI_OPCODE_MASK;
-
-	/* post recv buffer for response if one is expected */
-	if (!(opcode == ISCSI_OP_NOOP_OUT && task->hdr->itt == RESERVED_ITT)) {
-		if (iser_post_receive_control(conn) != 0) {
-			iser_err("post_rcv_buff failed!\n");
-			err = -ENOMEM;
+		struct ib_sge *tx_dsg = &mdesc->tx_sg[1];
+		if (task != conn->login_task) {
+			iser_err("data present on non login task!!!\n");
 			goto send_control_error;
 		}
+		memcpy(iser_conn->ib_conn->login_buf, task->data,
+							task->data_count);
+		tx_dsg->addr    = iser_conn->ib_conn->login_dma;
+		tx_dsg->length  = data_seg_len;
+		tx_dsg->lkey    = device->mr->lkey;
+		mdesc->num_sge = 2;
 	}
 
-	err = iser_post_send(mdesc);
+	if (task == conn->login_task) {
+		err = iser_post_recvl(iser_conn->ib_conn);
+		if (err)
+			goto send_control_error;
+	}
+
+	err = iser_post_send(iser_conn->ib_conn, mdesc);
 	if (!err)
 		return 0;
 
 send_control_error:
-	iser_dto_buffs_release(send_dto);
 	iser_err("conn %p failed err %d\n",conn, err);
 	return err;
 }
@@ -566,104 +435,71 @@
 /**
  * iser_rcv_dto_completion - recv DTO completion
  */
-void iser_rcv_completion(struct iser_desc *rx_desc,
-			 unsigned long dto_xfer_len)
+void iser_rcv_completion(struct iser_rx_desc *rx_desc,
+			 unsigned long rx_xfer_len,
+			 struct iser_conn *ib_conn)
 {
-	struct iser_dto *dto = &rx_desc->dto;
-	struct iscsi_iser_conn *conn = dto->ib_conn->iser_conn;
-	struct iscsi_task *task;
-	struct iscsi_iser_task *iser_task;
+	struct iscsi_iser_conn *conn = ib_conn->iser_conn;
 	struct iscsi_hdr *hdr;
-	char   *rx_data = NULL;
-	int     rx_data_len = 0;
-	unsigned char opcode;
+	u64 rx_dma;
+	int rx_buflen, outstanding, count, err;
+
+	/* differentiate between login to all other PDUs */
+	if ((char *)rx_desc == ib_conn->login_buf) {
+		rx_dma = ib_conn->login_dma;
+		rx_buflen = ISER_RX_LOGIN_SIZE;
+	} else {
+		rx_dma = rx_desc->dma_addr;
+		rx_buflen = ISER_RX_PAYLOAD_SIZE;
+	}
+
+	ib_dma_sync_single_for_cpu(ib_conn->device->ib_device, rx_dma,
+			rx_buflen, DMA_FROM_DEVICE);
 
 	hdr = &rx_desc->iscsi_header;
 
-	iser_dbg("op 0x%x itt 0x%x\n", hdr->opcode,hdr->itt);
+	iser_dbg("op 0x%x itt 0x%x dlen %d\n", hdr->opcode,
+			hdr->itt, (int)(rx_xfer_len - ISER_HEADERS_LEN));
 
-	if (dto_xfer_len > ISER_TOTAL_HEADERS_LEN) { /* we have data */
-		rx_data_len = dto_xfer_len - ISER_TOTAL_HEADERS_LEN;
-		rx_data     = dto->regd[1]->virt_addr;
-		rx_data    += dto->offset[1];
-	}
+	iscsi_iser_recv(conn->iscsi_conn, hdr,
+		rx_desc->data, rx_xfer_len - ISER_HEADERS_LEN);
 
-	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
-
-	if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
-		spin_lock(&conn->iscsi_conn->session->lock);
-		task = iscsi_itt_to_ctask(conn->iscsi_conn, hdr->itt);
-		if (task)
-			__iscsi_get_task(task);
-		spin_unlock(&conn->iscsi_conn->session->lock);
-
-		if (!task)
-			iser_err("itt can't be matched to task!!! "
-				 "conn %p opcode %d itt %d\n",
-				 conn->iscsi_conn, opcode, hdr->itt);
-		else {
-			iser_task = task->dd_data;
-			iser_dbg("itt %d task %p\n",hdr->itt, task);
-			iser_task->status = ISER_TASK_STATUS_COMPLETED;
-			iser_task_rdma_finalize(iser_task);
-			iscsi_put_task(task);
-		}
-	}
-	iser_dto_buffs_release(dto);
-
-	iscsi_iser_recv(conn->iscsi_conn, hdr, rx_data, rx_data_len);
-
-	kfree(rx_desc->data);
-	kmem_cache_free(ig.desc_cache, rx_desc);
+	ib_dma_sync_single_for_device(ib_conn->device->ib_device, rx_dma,
+			rx_buflen, DMA_FROM_DEVICE);
 
 	/* decrementing conn->post_recv_buf_count only --after-- freeing the   *
 	 * task eliminates the need to worry on tasks which are completed in   *
 	 * parallel to the execution of iser_conn_term. So the code that waits *
 	 * for the posted rx bufs refcount to become zero handles everything   */
-	atomic_dec(&conn->ib_conn->post_recv_buf_count);
+	conn->ib_conn->post_recv_buf_count--;
 
-	/*
-	 * if an unexpected PDU was received then the recv wr consumed must
-	 * be replaced, this is done in the next send of a control-type PDU
-	 */
-	if (opcode == ISCSI_OP_NOOP_IN && hdr->itt == RESERVED_ITT) {
-		/* nop-in with itt = 0xffffffff */
-		atomic_inc(&conn->ib_conn->unexpected_pdu_count);
+	if (rx_dma == ib_conn->login_dma)
+		return;
+
+	outstanding = ib_conn->post_recv_buf_count;
+	if (outstanding + ISER_MIN_POSTED_RX <= ISER_QP_MAX_RECV_DTOS) {
+		count = min(ISER_QP_MAX_RECV_DTOS - outstanding,
+						ISER_MIN_POSTED_RX);
+		err = iser_post_recvm(ib_conn, count);
+		if (err)
+			iser_err("posting %d rx bufs err %d\n", count, err);
 	}
-	else if (opcode == ISCSI_OP_ASYNC_EVENT) {
-		/* asyncronous message */
-		atomic_inc(&conn->ib_conn->unexpected_pdu_count);
-	}
-	/* a reject PDU consumes the recv buf posted for the response */
 }
 
-void iser_snd_completion(struct iser_desc *tx_desc)
+void iser_snd_completion(struct iser_tx_desc *tx_desc,
+			struct iser_conn *ib_conn)
 {
-	struct iser_dto        *dto = &tx_desc->dto;
-	struct iser_conn       *ib_conn = dto->ib_conn;
-	struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn;
-	struct iscsi_conn      *conn = iser_conn->iscsi_conn;
 	struct iscsi_task *task;
-	int resume_tx = 0;
+	struct iser_device *device = ib_conn->device;
 
-	iser_dbg("Initiator, Data sent dto=0x%p\n", dto);
-
-	iser_dto_buffs_release(dto);
-
-	if (tx_desc->type == ISCSI_TX_DATAOUT)
+	if (tx_desc->type == ISCSI_TX_DATAOUT) {
+		ib_dma_unmap_single(device->ib_device, tx_desc->dma_addr,
+					ISER_HEADERS_LEN, DMA_TO_DEVICE);
 		kmem_cache_free(ig.desc_cache, tx_desc);
-
-	if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
-	    ISER_QP_MAX_REQ_DTOS)
-		resume_tx = 1;
+	}
 
 	atomic_dec(&ib_conn->post_send_buf_count);
 
-	if (resume_tx) {
-		iser_dbg("%ld resuming tx\n",jiffies);
-		iscsi_conn_queue_work(conn);
-	}
-
 	if (tx_desc->type == ISCSI_TX_CONTROL) {
 		/* this arithmetic is legal by libiscsi dd_data allocation */
 		task = (void *) ((long)(void *)tx_desc -
@@ -692,7 +528,6 @@
 
 void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task)
 {
-	int deferred;
 	int is_rdma_aligned = 1;
 	struct iser_regd_buf *regd;
 
@@ -710,32 +545,17 @@
 
 	if (iser_task->dir[ISER_DIR_IN]) {
 		regd = &iser_task->rdma_regd[ISER_DIR_IN];
-		deferred = iser_regd_buff_release(regd);
-		if (deferred) {
-			iser_err("%d references remain for BUF-IN rdma reg\n",
-				 atomic_read(&regd->ref_count));
-		}
+		if (regd->reg.is_fmr)
+			iser_unreg_mem(&regd->reg);
 	}
 
 	if (iser_task->dir[ISER_DIR_OUT]) {
 		regd = &iser_task->rdma_regd[ISER_DIR_OUT];
-		deferred = iser_regd_buff_release(regd);
-		if (deferred) {
-			iser_err("%d references remain for BUF-OUT rdma reg\n",
-				 atomic_read(&regd->ref_count));
-		}
+		if (regd->reg.is_fmr)
+			iser_unreg_mem(&regd->reg);
 	}
 
        /* if the data was unaligned, it was already unmapped and then copied */
        if (is_rdma_aligned)
 		iser_dma_unmap_task_data(iser_task);
 }
-
-void iser_dto_buffs_release(struct iser_dto *dto)
-{
-	int i;
-
-	for (i = 0; i < dto->regd_vector_len; i++)
-		iser_regd_buff_release(dto->regd[i]);
-}
-
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index 274c883..fb88d68 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -41,62 +41,6 @@
 #define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */
 
 /**
- * Decrements the reference count for the
- * registered buffer & releases it
- *
- * returns 0 if released, 1 if deferred
- */
-int iser_regd_buff_release(struct iser_regd_buf *regd_buf)
-{
-	struct ib_device *dev;
-
-	if ((atomic_read(&regd_buf->ref_count) == 0) ||
-	    atomic_dec_and_test(&regd_buf->ref_count)) {
-		/* if we used the dma mr, unreg is just NOP */
-		if (regd_buf->reg.is_fmr)
-			iser_unreg_mem(&regd_buf->reg);
-
-		if (regd_buf->dma_addr) {
-			dev = regd_buf->device->ib_device;
-			ib_dma_unmap_single(dev,
-					 regd_buf->dma_addr,
-					 regd_buf->data_size,
-					 regd_buf->direction);
-		}
-		/* else this regd buf is associated with task which we */
-		/* dma_unmap_single/sg later */
-		return 0;
-	} else {
-		iser_dbg("Release deferred, regd.buff: 0x%p\n", regd_buf);
-		return 1;
-	}
-}
-
-/**
- * iser_reg_single - fills registered buffer descriptor with
- *		     registration information
- */
-void iser_reg_single(struct iser_device *device,
-		     struct iser_regd_buf *regd_buf,
-		     enum dma_data_direction direction)
-{
-	u64 dma_addr;
-
-	dma_addr = ib_dma_map_single(device->ib_device,
-				     regd_buf->virt_addr,
-				     regd_buf->data_size, direction);
-	BUG_ON(ib_dma_mapping_error(device->ib_device, dma_addr));
-
-	regd_buf->reg.lkey = device->mr->lkey;
-	regd_buf->reg.len  = regd_buf->data_size;
-	regd_buf->reg.va   = dma_addr;
-	regd_buf->reg.is_fmr = 0;
-
-	regd_buf->dma_addr  = dma_addr;
-	regd_buf->direction = direction;
-}
-
-/**
  * iser_start_rdma_unaligned_sg
  */
 static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
@@ -109,10 +53,10 @@
 	unsigned long  cmd_data_len = data->data_len;
 
 	if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
-		mem = (void *)__get_free_pages(GFP_NOIO,
+		mem = (void *)__get_free_pages(GFP_ATOMIC,
 		      ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
 	else
-		mem = kmalloc(cmd_data_len, GFP_NOIO);
+		mem = kmalloc(cmd_data_len, GFP_ATOMIC);
 
 	if (mem == NULL) {
 		iser_err("Failed to allocate mem size %d %d for copying sglist\n",
@@ -474,9 +418,5 @@
 			return err;
 		}
 	}
-
-	/* take a reference on this regd buf such that it will not be released *
-	 * (eg in send dto completion) before we get the scsi response         */
-	atomic_inc(&regd_buf->ref_count);
 	return 0;
 }
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
index 8579f32..308d17b 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -37,9 +37,8 @@
 #include "iscsi_iser.h"
 
 #define ISCSI_ISER_MAX_CONN	8
-#define ISER_MAX_CQ_LEN		((ISER_QP_MAX_RECV_DTOS + \
-				ISER_QP_MAX_REQ_DTOS) *   \
-				 ISCSI_ISER_MAX_CONN)
+#define ISER_MAX_RX_CQ_LEN	(ISER_QP_MAX_RECV_DTOS * ISCSI_ISER_MAX_CONN)
+#define ISER_MAX_TX_CQ_LEN	(ISER_QP_MAX_REQ_DTOS  * ISCSI_ISER_MAX_CONN)
 
 static void iser_cq_tasklet_fn(unsigned long data);
 static void iser_cq_callback(struct ib_cq *cq, void *cq_context);
@@ -67,15 +66,23 @@
 	if (IS_ERR(device->pd))
 		goto pd_err;
 
-	device->cq = ib_create_cq(device->ib_device,
+	device->rx_cq = ib_create_cq(device->ib_device,
 				  iser_cq_callback,
 				  iser_cq_event_callback,
 				  (void *)device,
-				  ISER_MAX_CQ_LEN, 0);
-	if (IS_ERR(device->cq))
-		goto cq_err;
+				  ISER_MAX_RX_CQ_LEN, 0);
+	if (IS_ERR(device->rx_cq))
+		goto rx_cq_err;
 
-	if (ib_req_notify_cq(device->cq, IB_CQ_NEXT_COMP))
+	device->tx_cq = ib_create_cq(device->ib_device,
+				  NULL, iser_cq_event_callback,
+				  (void *)device,
+				  ISER_MAX_TX_CQ_LEN, 0);
+
+	if (IS_ERR(device->tx_cq))
+		goto tx_cq_err;
+
+	if (ib_req_notify_cq(device->rx_cq, IB_CQ_NEXT_COMP))
 		goto cq_arm_err;
 
 	tasklet_init(&device->cq_tasklet,
@@ -93,8 +100,10 @@
 dma_mr_err:
 	tasklet_kill(&device->cq_tasklet);
 cq_arm_err:
-	ib_destroy_cq(device->cq);
-cq_err:
+	ib_destroy_cq(device->tx_cq);
+tx_cq_err:
+	ib_destroy_cq(device->rx_cq);
+rx_cq_err:
 	ib_dealloc_pd(device->pd);
 pd_err:
 	iser_err("failed to allocate an IB resource\n");
@@ -112,11 +121,13 @@
 	tasklet_kill(&device->cq_tasklet);
 
 	(void)ib_dereg_mr(device->mr);
-	(void)ib_destroy_cq(device->cq);
+	(void)ib_destroy_cq(device->tx_cq);
+	(void)ib_destroy_cq(device->rx_cq);
 	(void)ib_dealloc_pd(device->pd);
 
 	device->mr = NULL;
-	device->cq = NULL;
+	device->tx_cq = NULL;
+	device->rx_cq = NULL;
 	device->pd = NULL;
 }
 
@@ -129,13 +140,23 @@
 {
 	struct iser_device	*device;
 	struct ib_qp_init_attr	init_attr;
-	int			ret;
+	int			ret = -ENOMEM;
 	struct ib_fmr_pool_param params;
 
 	BUG_ON(ib_conn->device == NULL);
 
 	device = ib_conn->device;
 
+	ib_conn->login_buf = kmalloc(ISER_RX_LOGIN_SIZE, GFP_KERNEL);
+	if (!ib_conn->login_buf) {
+		goto alloc_err;
+		ret = -ENOMEM;
+	}
+
+	ib_conn->login_dma = ib_dma_map_single(ib_conn->device->ib_device,
+				(void *)ib_conn->login_buf, ISER_RX_LOGIN_SIZE,
+				DMA_FROM_DEVICE);
+
 	ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) +
 				    (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)),
 				    GFP_KERNEL);
@@ -169,12 +190,12 @@
 
 	init_attr.event_handler = iser_qp_event_callback;
 	init_attr.qp_context	= (void *)ib_conn;
-	init_attr.send_cq	= device->cq;
-	init_attr.recv_cq	= device->cq;
+	init_attr.send_cq	= device->tx_cq;
+	init_attr.recv_cq	= device->rx_cq;
 	init_attr.cap.max_send_wr  = ISER_QP_MAX_REQ_DTOS;
 	init_attr.cap.max_recv_wr  = ISER_QP_MAX_RECV_DTOS;
-	init_attr.cap.max_send_sge = MAX_REGD_BUF_VECTOR_LEN;
-	init_attr.cap.max_recv_sge = 2;
+	init_attr.cap.max_send_sge = 2;
+	init_attr.cap.max_recv_sge = 1;
 	init_attr.sq_sig_type	= IB_SIGNAL_REQ_WR;
 	init_attr.qp_type	= IB_QPT_RC;
 
@@ -192,6 +213,7 @@
 	(void)ib_destroy_fmr_pool(ib_conn->fmr_pool);
 fmr_pool_err:
 	kfree(ib_conn->page_vec);
+	kfree(ib_conn->login_buf);
 alloc_err:
 	iser_err("unable to alloc mem or create resource, err %d\n", ret);
 	return ret;
@@ -278,17 +300,6 @@
 	mutex_unlock(&ig.device_list_mutex);
 }
 
-int iser_conn_state_comp(struct iser_conn *ib_conn,
-			enum iser_ib_conn_state comp)
-{
-	int ret;
-
-	spin_lock_bh(&ib_conn->lock);
-	ret = (ib_conn->state == comp);
-	spin_unlock_bh(&ib_conn->lock);
-	return ret;
-}
-
 static int iser_conn_state_comp_exch(struct iser_conn *ib_conn,
 				     enum iser_ib_conn_state comp,
 				     enum iser_ib_conn_state exch)
@@ -314,7 +325,7 @@
 	mutex_lock(&ig.connlist_mutex);
 	list_del(&ib_conn->conn_list);
 	mutex_unlock(&ig.connlist_mutex);
-
+	iser_free_rx_descriptors(ib_conn);
 	iser_free_ib_conn_res(ib_conn);
 	ib_conn->device = NULL;
 	/* on EVENT_ADDR_ERROR there's no device yet for this conn */
@@ -442,7 +453,7 @@
 				   ISCSI_ERR_CONN_FAILED);
 
 	/* Complete the termination process if no posts are pending */
-	if ((atomic_read(&ib_conn->post_recv_buf_count) == 0) &&
+	if (ib_conn->post_recv_buf_count == 0 &&
 	    (atomic_read(&ib_conn->post_send_buf_count) == 0)) {
 		ib_conn->state = ISER_CONN_DOWN;
 		wake_up_interruptible(&ib_conn->wait);
@@ -489,9 +500,8 @@
 {
 	ib_conn->state = ISER_CONN_INIT;
 	init_waitqueue_head(&ib_conn->wait);
-	atomic_set(&ib_conn->post_recv_buf_count, 0);
+	ib_conn->post_recv_buf_count = 0;
 	atomic_set(&ib_conn->post_send_buf_count, 0);
-	atomic_set(&ib_conn->unexpected_pdu_count, 0);
 	atomic_set(&ib_conn->refcount, 1);
 	INIT_LIST_HEAD(&ib_conn->conn_list);
 	spin_lock_init(&ib_conn->lock);
@@ -626,136 +636,97 @@
 	reg->mem_h = NULL;
 }
 
-/**
- * iser_dto_to_iov - builds IOV from a dto descriptor
- */
-static void iser_dto_to_iov(struct iser_dto *dto, struct ib_sge *iov, int iov_len)
+int iser_post_recvl(struct iser_conn *ib_conn)
 {
-	int		     i;
-	struct ib_sge	     *sge;
-	struct iser_regd_buf *regd_buf;
+	struct ib_recv_wr rx_wr, *rx_wr_failed;
+	struct ib_sge	  sge;
+	int ib_ret;
 
-	if (dto->regd_vector_len > iov_len) {
-		iser_err("iov size %d too small for posting dto of len %d\n",
-			 iov_len, dto->regd_vector_len);
-		BUG();
-	}
+	sge.addr   = ib_conn->login_dma;
+	sge.length = ISER_RX_LOGIN_SIZE;
+	sge.lkey   = ib_conn->device->mr->lkey;
 
-	for (i = 0; i < dto->regd_vector_len; i++) {
-		sge	    = &iov[i];
-		regd_buf  = dto->regd[i];
+	rx_wr.wr_id   = (unsigned long)ib_conn->login_buf;
+	rx_wr.sg_list = &sge;
+	rx_wr.num_sge = 1;
+	rx_wr.next    = NULL;
 
-		sge->addr   = regd_buf->reg.va;
-		sge->length = regd_buf->reg.len;
-		sge->lkey   = regd_buf->reg.lkey;
-
-		if (dto->used_sz[i] > 0)  /* Adjust size */
-			sge->length = dto->used_sz[i];
-
-		/* offset and length should not exceed the regd buf length */
-		if (sge->length + dto->offset[i] > regd_buf->reg.len) {
-			iser_err("Used len:%ld + offset:%d, exceed reg.buf.len:"
-				 "%ld in dto:0x%p [%d], va:0x%08lX\n",
-				 (unsigned long)sge->length, dto->offset[i],
-				 (unsigned long)regd_buf->reg.len, dto, i,
-				 (unsigned long)sge->addr);
-			BUG();
-		}
-
-		sge->addr += dto->offset[i]; /* Adjust offset */
-	}
-}
-
-/**
- * iser_post_recv - Posts a receive buffer.
- *
- * returns 0 on success, -1 on failure
- */
-int iser_post_recv(struct iser_desc *rx_desc)
-{
-	int		  ib_ret, ret_val = 0;
-	struct ib_recv_wr recv_wr, *recv_wr_failed;
-	struct ib_sge	  iov[2];
-	struct iser_conn  *ib_conn;
-	struct iser_dto   *recv_dto = &rx_desc->dto;
-
-	/* Retrieve conn */
-	ib_conn = recv_dto->ib_conn;
-
-	iser_dto_to_iov(recv_dto, iov, 2);
-
-	recv_wr.next	= NULL;
-	recv_wr.sg_list = iov;
-	recv_wr.num_sge = recv_dto->regd_vector_len;
-	recv_wr.wr_id	= (unsigned long)rx_desc;
-
-	atomic_inc(&ib_conn->post_recv_buf_count);
-	ib_ret	= ib_post_recv(ib_conn->qp, &recv_wr, &recv_wr_failed);
+	ib_conn->post_recv_buf_count++;
+	ib_ret	= ib_post_recv(ib_conn->qp, &rx_wr, &rx_wr_failed);
 	if (ib_ret) {
 		iser_err("ib_post_recv failed ret=%d\n", ib_ret);
-		atomic_dec(&ib_conn->post_recv_buf_count);
-		ret_val = -1;
+		ib_conn->post_recv_buf_count--;
+	}
+	return ib_ret;
+}
+
+int iser_post_recvm(struct iser_conn *ib_conn, int count)
+{
+	struct ib_recv_wr *rx_wr, *rx_wr_failed;
+	int i, ib_ret;
+	unsigned int my_rx_head = ib_conn->rx_desc_head;
+	struct iser_rx_desc *rx_desc;
+
+	for (rx_wr = ib_conn->rx_wr, i = 0; i < count; i++, rx_wr++) {
+		rx_desc		= &ib_conn->rx_descs[my_rx_head];
+		rx_wr->wr_id	= (unsigned long)rx_desc;
+		rx_wr->sg_list	= &rx_desc->rx_sg;
+		rx_wr->num_sge	= 1;
+		rx_wr->next	= rx_wr + 1;
+		my_rx_head = (my_rx_head + 1) & (ISER_QP_MAX_RECV_DTOS - 1);
 	}
 
-	return ret_val;
+	rx_wr--;
+	rx_wr->next = NULL; /* mark end of work requests list */
+
+	ib_conn->post_recv_buf_count += count;
+	ib_ret	= ib_post_recv(ib_conn->qp, ib_conn->rx_wr, &rx_wr_failed);
+	if (ib_ret) {
+		iser_err("ib_post_recv failed ret=%d\n", ib_ret);
+		ib_conn->post_recv_buf_count -= count;
+	} else
+		ib_conn->rx_desc_head = my_rx_head;
+	return ib_ret;
 }
 
+
 /**
  * iser_start_send - Initiate a Send DTO operation
  *
  * returns 0 on success, -1 on failure
  */
-int iser_post_send(struct iser_desc *tx_desc)
+int iser_post_send(struct iser_conn *ib_conn, struct iser_tx_desc *tx_desc)
 {
-	int		  ib_ret, ret_val = 0;
+	int		  ib_ret;
 	struct ib_send_wr send_wr, *send_wr_failed;
-	struct ib_sge	  iov[MAX_REGD_BUF_VECTOR_LEN];
-	struct iser_conn  *ib_conn;
-	struct iser_dto   *dto = &tx_desc->dto;
 
-	ib_conn = dto->ib_conn;
-
-	iser_dto_to_iov(dto, iov, MAX_REGD_BUF_VECTOR_LEN);
+	ib_dma_sync_single_for_device(ib_conn->device->ib_device,
+		tx_desc->dma_addr, ISER_HEADERS_LEN, DMA_TO_DEVICE);
 
 	send_wr.next	   = NULL;
 	send_wr.wr_id	   = (unsigned long)tx_desc;
-	send_wr.sg_list	   = iov;
-	send_wr.num_sge	   = dto->regd_vector_len;
+	send_wr.sg_list	   = tx_desc->tx_sg;
+	send_wr.num_sge	   = tx_desc->num_sge;
 	send_wr.opcode	   = IB_WR_SEND;
-	send_wr.send_flags = dto->notify_enable ? IB_SEND_SIGNALED : 0;
+	send_wr.send_flags = IB_SEND_SIGNALED;
 
 	atomic_inc(&ib_conn->post_send_buf_count);
 
 	ib_ret = ib_post_send(ib_conn->qp, &send_wr, &send_wr_failed);
 	if (ib_ret) {
-		iser_err("Failed to start SEND DTO, dto: 0x%p, IOV len: %d\n",
-			 dto, dto->regd_vector_len);
 		iser_err("ib_post_send failed, ret:%d\n", ib_ret);
 		atomic_dec(&ib_conn->post_send_buf_count);
-		ret_val = -1;
 	}
-
-	return ret_val;
+	return ib_ret;
 }
 
-static void iser_handle_comp_error(struct iser_desc *desc)
+static void iser_handle_comp_error(struct iser_tx_desc *desc,
+				struct iser_conn *ib_conn)
 {
-	struct iser_dto  *dto     = &desc->dto;
-	struct iser_conn *ib_conn = dto->ib_conn;
-
-	iser_dto_buffs_release(dto);
-
-	if (desc->type == ISCSI_RX) {
-		kfree(desc->data);
+	if (desc && desc->type == ISCSI_TX_DATAOUT)
 		kmem_cache_free(ig.desc_cache, desc);
-		atomic_dec(&ib_conn->post_recv_buf_count);
-	} else { /* type is TX control/command/dataout */
-		if (desc->type == ISCSI_TX_DATAOUT)
-			kmem_cache_free(ig.desc_cache, desc);
-		atomic_dec(&ib_conn->post_send_buf_count);
-	}
 
-	if (atomic_read(&ib_conn->post_recv_buf_count) == 0 &&
+	if (ib_conn->post_recv_buf_count == 0 &&
 	    atomic_read(&ib_conn->post_send_buf_count) == 0) {
 		/* getting here when the state is UP means that the conn is *
 		 * being terminated asynchronously from the iSCSI layer's   *
@@ -774,32 +745,74 @@
 	}
 }
 
+static int iser_drain_tx_cq(struct iser_device  *device)
+{
+	struct ib_cq  *cq = device->tx_cq;
+	struct ib_wc  wc;
+	struct iser_tx_desc *tx_desc;
+	struct iser_conn *ib_conn;
+	int completed_tx = 0;
+
+	while (ib_poll_cq(cq, 1, &wc) == 1) {
+		tx_desc	= (struct iser_tx_desc *) (unsigned long) wc.wr_id;
+		ib_conn = wc.qp->qp_context;
+		if (wc.status == IB_WC_SUCCESS) {
+			if (wc.opcode == IB_WC_SEND)
+				iser_snd_completion(tx_desc, ib_conn);
+			else
+				iser_err("expected opcode %d got %d\n",
+					IB_WC_SEND, wc.opcode);
+		} else {
+			iser_err("tx id %llx status %d vend_err %x\n",
+				wc.wr_id, wc.status, wc.vendor_err);
+			atomic_dec(&ib_conn->post_send_buf_count);
+			iser_handle_comp_error(tx_desc, ib_conn);
+		}
+		completed_tx++;
+	}
+	return completed_tx;
+}
+
+
 static void iser_cq_tasklet_fn(unsigned long data)
 {
 	 struct iser_device  *device = (struct iser_device *)data;
-	 struct ib_cq	     *cq = device->cq;
+	 struct ib_cq	     *cq = device->rx_cq;
 	 struct ib_wc	     wc;
-	 struct iser_desc    *desc;
+	 struct iser_rx_desc *desc;
 	 unsigned long	     xfer_len;
+	struct iser_conn *ib_conn;
+	int completed_tx, completed_rx;
+	completed_tx = completed_rx = 0;
 
 	while (ib_poll_cq(cq, 1, &wc) == 1) {
-		desc	 = (struct iser_desc *) (unsigned long) wc.wr_id;
+		desc	 = (struct iser_rx_desc *) (unsigned long) wc.wr_id;
 		BUG_ON(desc == NULL);
-
+		ib_conn = wc.qp->qp_context;
 		if (wc.status == IB_WC_SUCCESS) {
-			if (desc->type == ISCSI_RX) {
+			if (wc.opcode == IB_WC_RECV) {
 				xfer_len = (unsigned long)wc.byte_len;
-				iser_rcv_completion(desc, xfer_len);
-			} else /* type == ISCSI_TX_CONTROL/SCSI_CMD/DOUT */
-				iser_snd_completion(desc);
+				iser_rcv_completion(desc, xfer_len, ib_conn);
+			} else
+				iser_err("expected opcode %d got %d\n",
+					IB_WC_RECV, wc.opcode);
 		} else {
-			iser_err("comp w. error op %d status %d\n",desc->type,wc.status);
-			iser_handle_comp_error(desc);
+			if (wc.status != IB_WC_WR_FLUSH_ERR)
+				iser_err("rx id %llx status %d vend_err %x\n",
+					wc.wr_id, wc.status, wc.vendor_err);
+			ib_conn->post_recv_buf_count--;
+			iser_handle_comp_error(NULL, ib_conn);
 		}
+		completed_rx++;
+		if (!(completed_rx & 63))
+			completed_tx += iser_drain_tx_cq(device);
 	}
 	/* #warning "it is assumed here that arming CQ only once its empty" *
 	 * " would not cause interrupts to be missed"                       */
 	ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
+
+	completed_tx += iser_drain_tx_cq(device);
+	iser_dbg("got %d rx %d tx completions\n", completed_rx, completed_tx);
 }
 
 static void iser_cq_callback(struct ib_cq *cq, void *cq_context)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 54c8fe2..ed3f9eb 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -80,7 +80,8 @@
 
 static void srp_add_one(struct ib_device *device);
 static void srp_remove_one(struct ib_device *device);
-static void srp_completion(struct ib_cq *cq, void *target_ptr);
+static void srp_recv_completion(struct ib_cq *cq, void *target_ptr);
+static void srp_send_completion(struct ib_cq *cq, void *target_ptr);
 static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event);
 
 static struct scsi_transport_template *ib_srp_transport_template;
@@ -227,14 +228,21 @@
 	if (!init_attr)
 		return -ENOMEM;
 
-	target->cq = ib_create_cq(target->srp_host->srp_dev->dev,
-				  srp_completion, NULL, target, SRP_CQ_SIZE, 0);
-	if (IS_ERR(target->cq)) {
-		ret = PTR_ERR(target->cq);
-		goto out;
+	target->recv_cq = ib_create_cq(target->srp_host->srp_dev->dev,
+				       srp_recv_completion, NULL, target, SRP_RQ_SIZE, 0);
+	if (IS_ERR(target->recv_cq)) {
+		ret = PTR_ERR(target->recv_cq);
+		goto err;
 	}
 
-	ib_req_notify_cq(target->cq, IB_CQ_NEXT_COMP);
+	target->send_cq = ib_create_cq(target->srp_host->srp_dev->dev,
+				       srp_send_completion, NULL, target, SRP_SQ_SIZE, 0);
+	if (IS_ERR(target->send_cq)) {
+		ret = PTR_ERR(target->send_cq);
+		goto err_recv_cq;
+	}
+
+	ib_req_notify_cq(target->recv_cq, IB_CQ_NEXT_COMP);
 
 	init_attr->event_handler       = srp_qp_event;
 	init_attr->cap.max_send_wr     = SRP_SQ_SIZE;
@@ -243,24 +251,32 @@
 	init_attr->cap.max_send_sge    = 1;
 	init_attr->sq_sig_type         = IB_SIGNAL_ALL_WR;
 	init_attr->qp_type             = IB_QPT_RC;
-	init_attr->send_cq             = target->cq;
-	init_attr->recv_cq             = target->cq;
+	init_attr->send_cq             = target->send_cq;
+	init_attr->recv_cq             = target->recv_cq;
 
 	target->qp = ib_create_qp(target->srp_host->srp_dev->pd, init_attr);
 	if (IS_ERR(target->qp)) {
 		ret = PTR_ERR(target->qp);
-		ib_destroy_cq(target->cq);
-		goto out;
+		goto err_send_cq;
 	}
 
 	ret = srp_init_qp(target, target->qp);
-	if (ret) {
-		ib_destroy_qp(target->qp);
-		ib_destroy_cq(target->cq);
-		goto out;
-	}
+	if (ret)
+		goto err_qp;
 
-out:
+	kfree(init_attr);
+	return 0;
+
+err_qp:
+	ib_destroy_qp(target->qp);
+
+err_send_cq:
+	ib_destroy_cq(target->send_cq);
+
+err_recv_cq:
+	ib_destroy_cq(target->recv_cq);
+
+err:
 	kfree(init_attr);
 	return ret;
 }
@@ -270,7 +286,8 @@
 	int i;
 
 	ib_destroy_qp(target->qp);
-	ib_destroy_cq(target->cq);
+	ib_destroy_cq(target->send_cq);
+	ib_destroy_cq(target->recv_cq);
 
 	for (i = 0; i < SRP_RQ_SIZE; ++i)
 		srp_free_iu(target->srp_host, target->rx_ring[i]);
@@ -568,7 +585,9 @@
 	if (ret)
 		goto err;
 
-	while (ib_poll_cq(target->cq, 1, &wc) > 0)
+	while (ib_poll_cq(target->recv_cq, 1, &wc) > 0)
+		; /* nothing */
+	while (ib_poll_cq(target->send_cq, 1, &wc) > 0)
 		; /* nothing */
 
 	spin_lock_irq(target->scsi_host->host_lock);
@@ -851,7 +870,7 @@
 	struct srp_iu *iu;
 	u8 opcode;
 
-	iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV];
+	iu = target->rx_ring[wc->wr_id];
 
 	dev = target->srp_host->srp_dev->dev;
 	ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_ti_iu_len,
@@ -898,7 +917,7 @@
 				      DMA_FROM_DEVICE);
 }
 
-static void srp_completion(struct ib_cq *cq, void *target_ptr)
+static void srp_recv_completion(struct ib_cq *cq, void *target_ptr)
 {
 	struct srp_target_port *target = target_ptr;
 	struct ib_wc wc;
@@ -907,17 +926,31 @@
 	while (ib_poll_cq(cq, 1, &wc) > 0) {
 		if (wc.status) {
 			shost_printk(KERN_ERR, target->scsi_host,
-				     PFX "failed %s status %d\n",
-				     wc.wr_id & SRP_OP_RECV ? "receive" : "send",
+				     PFX "failed receive status %d\n",
 				     wc.status);
 			target->qp_in_error = 1;
 			break;
 		}
 
-		if (wc.wr_id & SRP_OP_RECV)
-			srp_handle_recv(target, &wc);
-		else
-			++target->tx_tail;
+		srp_handle_recv(target, &wc);
+	}
+}
+
+static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
+{
+	struct srp_target_port *target = target_ptr;
+	struct ib_wc wc;
+
+	while (ib_poll_cq(cq, 1, &wc) > 0) {
+		if (wc.status) {
+			shost_printk(KERN_ERR, target->scsi_host,
+				     PFX "failed send status %d\n",
+				     wc.status);
+			target->qp_in_error = 1;
+			break;
+		}
+
+		++target->tx_tail;
 	}
 }
 
@@ -930,7 +963,7 @@
 	int ret;
 
 	next 	 = target->rx_head & (SRP_RQ_SIZE - 1);
-	wr.wr_id = next | SRP_OP_RECV;
+	wr.wr_id = next;
 	iu 	 = target->rx_ring[next];
 
 	list.addr   = iu->dma;
@@ -970,6 +1003,8 @@
 {
 	s32 min = (req_type == SRP_REQ_TASK_MGMT) ? 1 : 2;
 
+	srp_send_completion(target->send_cq, target);
+
 	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
 		return NULL;
 
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index e185b90..5a80eac 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -60,7 +60,6 @@
 	SRP_RQ_SHIFT    	= 6,
 	SRP_RQ_SIZE		= 1 << SRP_RQ_SHIFT,
 	SRP_SQ_SIZE		= SRP_RQ_SIZE - 1,
-	SRP_CQ_SIZE		= SRP_SQ_SIZE + SRP_RQ_SIZE,
 
 	SRP_TAG_TSK_MGMT	= 1 << (SRP_RQ_SHIFT + 1),
 
@@ -69,8 +68,6 @@
 	SRP_FMR_DIRTY_SIZE	= SRP_FMR_POOL_SIZE / 4
 };
 
-#define SRP_OP_RECV		(1 << 31)
-
 enum srp_target_state {
 	SRP_TARGET_LIVE,
 	SRP_TARGET_CONNECTING,
@@ -133,7 +130,8 @@
 	int			path_query_id;
 
 	struct ib_cm_id	       *cm_id;
-	struct ib_cq	       *cq;
+	struct ib_cq	       *recv_cq;
+	struct ib_cq	       *send_cq;
 	struct ib_qp	       *qp;
 
 	int			max_ti_iu_len;
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
index 9caed30..b1ab298 100644
--- a/drivers/input/keyboard/locomokbd.c
+++ b/drivers/input/keyboard/locomokbd.c
@@ -192,11 +192,18 @@
 static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
 {
 	struct locomokbd *locomokbd = dev_id;
+	u16 r;
+
+	r = locomo_readl(locomokbd->base + LOCOMO_KIC);
+	if ((r & 0x0001) == 0)
+		return IRQ_HANDLED;
+
+	locomo_writel(r & ~0x0100, locomokbd->base + LOCOMO_KIC); /* Ack */
+
 	/** wait chattering delay **/
 	udelay(100);
 
 	locomokbd_scankeyboard(locomokbd);
-
 	return IRQ_HANDLED;
 }
 
@@ -210,6 +217,25 @@
 	locomokbd_scankeyboard(locomokbd);
 }
 
+static int locomokbd_open(struct input_dev *dev)
+{
+	struct locomokbd *locomokbd = input_get_drvdata(dev);
+	u16 r;
+	
+	r = locomo_readl(locomokbd->base + LOCOMO_KIC) | 0x0010;
+	locomo_writel(r, locomokbd->base + LOCOMO_KIC);
+	return 0;
+}
+
+static void locomokbd_close(struct input_dev *dev)
+{
+	struct locomokbd *locomokbd = input_get_drvdata(dev);
+	u16 r;
+	
+	r = locomo_readl(locomokbd->base + LOCOMO_KIC) & ~0x0010;
+	locomo_writel(r, locomokbd->base + LOCOMO_KIC);
+}
+
 static int __devinit locomokbd_probe(struct locomo_dev *dev)
 {
 	struct locomokbd *locomokbd;
@@ -253,6 +279,8 @@
 	input_dev->id.vendor = 0x0001;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
+	input_dev->open = locomokbd_open;
+	input_dev->close = locomokbd_close;
 	input_dev->dev.parent = &dev->dev;
 
 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
@@ -261,6 +289,8 @@
 	input_dev->keycodesize = sizeof(locomokbd_keycode[0]);
 	input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode);
 
+	input_set_drvdata(input_dev, locomokbd);
+
 	memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
 	for (i = 0; i < LOCOMOKBD_NUMKEYS; i++)
 		set_bit(locomokbd->keycode[i], input_dev->keybit);
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
new file mode 100644
index 0000000..69a48e8
--- /dev/null
+++ b/drivers/input/misc/88pm860x_onkey.c
@@ -0,0 +1,155 @@
+/*
+ * 88pm860x_onkey.c - Marvell 88PM860x ONKEY driver
+ *
+ * Copyright (C) 2009-2010 Marvell International Ltd.
+ *      Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/88pm860x.h>
+
+#define PM8607_WAKEUP		0x0b
+
+#define LONG_ONKEY_EN		(1 << 1)
+#define ONKEY_STATUS		(1 << 0)
+
+struct pm860x_onkey_info {
+	struct input_dev	*idev;
+	struct pm860x_chip	*chip;
+	struct i2c_client	*i2c;
+	struct device		*dev;
+	int			irq;
+};
+
+/* 88PM860x gives us an interrupt when ONKEY is held */
+static irqreturn_t pm860x_onkey_handler(int irq, void *data)
+{
+	struct pm860x_onkey_info *info = data;
+	int ret;
+
+	ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2);
+	ret &= ONKEY_STATUS;
+	input_report_key(info->idev, KEY_POWER, ret);
+	input_sync(info->idev);
+
+	/* Enable 8-second long onkey detection */
+	pm860x_set_bits(info->i2c, PM8607_WAKEUP, 3, LONG_ONKEY_EN);
+	return IRQ_HANDLED;
+}
+
+static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
+{
+	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pm860x_onkey_info *info;
+	int irq, ret;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "No IRQ resource!\n");
+		return -EINVAL;
+	}
+
+	info = kzalloc(sizeof(struct pm860x_onkey_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+	info->chip = chip;
+	info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+	info->dev = &pdev->dev;
+	info->irq = irq + chip->irq_base;
+
+	info->idev = input_allocate_device();
+	if (!info->idev) {
+		dev_err(chip->dev, "Failed to allocate input dev\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	info->idev->name = "88pm860x_on";
+	info->idev->phys = "88pm860x_on/input0";
+	info->idev->id.bustype = BUS_I2C;
+	info->idev->dev.parent = &pdev->dev;
+	info->irq = irq;
+	info->idev->evbit[0] = BIT_MASK(EV_KEY);
+	info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
+
+	ret = input_register_device(info->idev);
+	if (ret) {
+		dev_err(chip->dev, "Can't register input device: %d\n", ret);
+		goto out_reg;
+	}
+
+	ret = request_threaded_irq(info->irq, NULL, pm860x_onkey_handler,
+				   IRQF_ONESHOT, "onkey", info);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
+			info->irq, ret);
+		goto out_irq;
+	}
+
+	platform_set_drvdata(pdev, info);
+	return 0;
+
+out_irq:
+	input_unregister_device(info->idev);
+	kfree(info);
+	return ret;
+
+out_reg:
+	input_free_device(info->idev);
+out:
+	kfree(info);
+	return ret;
+}
+
+static int __devexit pm860x_onkey_remove(struct platform_device *pdev)
+{
+	struct pm860x_onkey_info *info = platform_get_drvdata(pdev);
+
+	free_irq(info->irq, info);
+	input_unregister_device(info->idev);
+	kfree(info);
+	return 0;
+}
+
+static struct platform_driver pm860x_onkey_driver = {
+	.driver		= {
+		.name	= "88pm860x-onkey",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pm860x_onkey_probe,
+	.remove		= __devexit_p(pm860x_onkey_remove),
+};
+
+static int __init pm860x_onkey_init(void)
+{
+	return platform_driver_register(&pm860x_onkey_driver);
+}
+module_init(pm860x_onkey_init);
+
+static void __exit pm860x_onkey_exit(void)
+{
+	platform_driver_unregister(&pm860x_onkey_driver);
+}
+module_exit(pm860x_onkey_exit);
+
+MODULE_DESCRIPTION("Marvell 88PM860x ONKEY driver");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 16ec523..7097bfe 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -12,6 +12,16 @@
 
 if INPUT_MISC
 
+config INPUT_88PM860X_ONKEY
+	tristate "88PM860x ONKEY support"
+	depends on MFD_88PM860X
+	help
+	  Support the ONKEY of Marvell 88PM860x PMICs as an input device
+	  reporting power button status.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called 88pm860x_onkey.
+
 config INPUT_PCSPKR
 	tristate "PC Speaker support"
 	depends on PCSPKR_PLATFORM
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index a8b8485..b611615 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -4,6 +4,7 @@
 
 # Each configuration option enables a list of files.
 
+obj-$(CONFIG_INPUT_88PM860X_ONKEY)	+= 88pm860x_onkey.o
 obj-$(CONFIG_INPUT_APANEL)		+= apanel.o
 obj-$(CONFIG_INPUT_ATI_REMOTE)		+= ati_remote.o
 obj-$(CONFIG_INPUT_ATI_REMOTE2)		+= ati_remote2.o
diff --git a/drivers/input/misc/yealink.h b/drivers/input/misc/yealink.h
index 48af0be..1e0f523 100644
--- a/drivers/input/misc/yealink.h
+++ b/drivers/input/misc/yealink.h
@@ -127,7 +127,7 @@
  * yld_status struct.
  */
 
-/* LCD, each segment must be driven seperately.
+/* LCD, each segment must be driven separately.
  *
  * Layout:
  *
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index b54aee7..ff4d77c 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -430,7 +430,7 @@
 	}
 
 	if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) {
-		dbg("Filtered out by platfrom filter\n");
+		dbg("Filtered out by platform filter\n");
 		return true;
 	}
 
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index 7d005a3..4be039d 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -362,7 +362,7 @@
 };
 
 /***********************************************************************
- * Map values to strings and back. Every map shoudl have the following
+ * Map values to strings and back. Every map should have the following
  * as its last element: { NULL, AIPTEK_INVALID_VALUE }.
  */
 #define AIPTEK_INVALID_VALUE	-1
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
new file mode 100644
index 0000000..286bb49
--- /dev/null
+++ b/drivers/input/touchscreen/88pm860x-ts.c
@@ -0,0 +1,236 @@
+/*
+ * Touchscreen driver for Marvell 88PM860x
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * 	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/mfd/88pm860x.h>
+
+#define MEAS_LEN		(8)
+#define ACCURATE_BIT		(12)
+
+/* touch register */
+#define MEAS_EN3		(0x52)
+
+#define MEAS_TSIX_1		(0x8D)
+#define MEAS_TSIX_2		(0x8E)
+#define MEAS_TSIY_1		(0x8F)
+#define MEAS_TSIY_2		(0x90)
+#define MEAS_TSIZ1_1		(0x91)
+#define MEAS_TSIZ1_2		(0x92)
+#define MEAS_TSIZ2_1		(0x93)
+#define MEAS_TSIZ2_2		(0x94)
+
+/* bit definitions of touch */
+#define MEAS_PD_EN		(1 << 3)
+#define MEAS_TSIX_EN		(1 << 4)
+#define MEAS_TSIY_EN		(1 << 5)
+#define MEAS_TSIZ1_EN		(1 << 6)
+#define MEAS_TSIZ2_EN		(1 << 7)
+
+struct pm860x_touch {
+	struct input_dev *idev;
+	struct i2c_client *i2c;
+	struct pm860x_chip *chip;
+	int irq;
+	int res_x;		/* resistor of Xplate */
+};
+
+static irqreturn_t pm860x_touch_handler(int irq, void *data)
+{
+	struct pm860x_touch *touch = data;
+	struct pm860x_chip *chip = touch->chip;
+	unsigned char buf[MEAS_LEN];
+	int x, y, pen_down;
+	int z1, z2, rt = 0;
+	int ret;
+
+	ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
+	if (ret < 0)
+		goto out;
+
+	pen_down = buf[1] & (1 << 6);
+	x = ((buf[0] & 0xFF) << 4) | (buf[1] & 0x0F);
+	y = ((buf[2] & 0xFF) << 4) | (buf[3] & 0x0F);
+	z1 = ((buf[4] & 0xFF) << 4) | (buf[5] & 0x0F);
+	z2 = ((buf[6] & 0xFF) << 4) | (buf[7] & 0x0F);
+
+	if (pen_down) {
+		if ((x != 0) && (z1 != 0) && (touch->res_x != 0)) {
+			rt = z2 / z1 - 1;
+			rt = (rt * touch->res_x * x) >> ACCURATE_BIT;
+			dev_dbg(chip->dev, "z1:%d, z2:%d, rt:%d\n",
+				z1, z2, rt);
+		}
+		input_report_abs(touch->idev, ABS_X, x);
+		input_report_abs(touch->idev, ABS_Y, y);
+		input_report_abs(touch->idev, ABS_PRESSURE, rt);
+		input_report_key(touch->idev, BTN_TOUCH, 1);
+		dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y);
+	} else {
+		input_report_abs(touch->idev, ABS_PRESSURE, 0);
+		input_report_key(touch->idev, BTN_TOUCH, 0);
+		dev_dbg(chip->dev, "pen release\n");
+	}
+	input_sync(touch->idev);
+
+out:
+	return IRQ_HANDLED;
+}
+
+static int pm860x_touch_open(struct input_dev *dev)
+{
+	struct pm860x_touch *touch = input_get_drvdata(dev);
+	int data, ret;
+
+	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
+		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
+	ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
+	if (ret < 0)
+		goto out;
+	return 0;
+out:
+	return ret;
+}
+
+static void pm860x_touch_close(struct input_dev *dev)
+{
+	struct pm860x_touch *touch = input_get_drvdata(dev);
+	int data;
+
+	data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
+		| MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
+	pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
+}
+
+static int __devinit pm860x_touch_probe(struct platform_device *pdev)
+{
+	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pm860x_platform_data *pm860x_pdata =		\
+				pdev->dev.parent->platform_data;
+	struct pm860x_touch_pdata *pdata = NULL;
+	struct pm860x_touch *touch;
+	int irq, ret;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "No IRQ resource!\n");
+		return -EINVAL;
+	}
+
+	if (!pm860x_pdata) {
+		dev_err(&pdev->dev, "platform data is missing\n");
+		return -EINVAL;
+	}
+
+	pdata = pm860x_pdata->touch;
+	if (!pdata) {
+		dev_err(&pdev->dev, "touchscreen data is missing\n");
+		return -EINVAL;
+	}
+
+	touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL);
+	if (touch == NULL)
+		return -ENOMEM;
+	dev_set_drvdata(&pdev->dev, touch);
+
+	touch->idev = input_allocate_device();
+	if (touch->idev == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate input device!\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	touch->idev->name = "88pm860x-touch";
+	touch->idev->phys = "88pm860x/input0";
+	touch->idev->id.bustype = BUS_I2C;
+	touch->idev->dev.parent = &pdev->dev;
+	touch->idev->open = pm860x_touch_open;
+	touch->idev->close = pm860x_touch_close;
+	touch->chip = chip;
+	touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+	touch->irq = irq + chip->irq_base;
+	touch->res_x = pdata->res_x;
+	input_set_drvdata(touch->idev, touch);
+
+	ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
+				   IRQF_ONESHOT, "touch", touch);
+	if (ret < 0)
+		goto out_irq;
+
+	__set_bit(EV_ABS, touch->idev->evbit);
+	__set_bit(ABS_X, touch->idev->absbit);
+	__set_bit(ABS_Y, touch->idev->absbit);
+	__set_bit(ABS_PRESSURE, touch->idev->absbit);
+	__set_bit(EV_SYN, touch->idev->evbit);
+	__set_bit(EV_KEY, touch->idev->evbit);
+	__set_bit(BTN_TOUCH, touch->idev->keybit);
+
+	input_set_abs_params(touch->idev, ABS_X, 0, 1 << ACCURATE_BIT, 0, 0);
+	input_set_abs_params(touch->idev, ABS_Y, 0, 1 << ACCURATE_BIT, 0, 0);
+	input_set_abs_params(touch->idev, ABS_PRESSURE, 0, 1 << ACCURATE_BIT,
+				0, 0);
+
+	ret = input_register_device(touch->idev);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to register touch!\n");
+		goto out_rg;
+	}
+
+	platform_set_drvdata(pdev, touch);
+	return 0;
+out_rg:
+	free_irq(touch->irq, touch);
+out_irq:
+	input_free_device(touch->idev);
+out:
+	kfree(touch);
+	return ret;
+}
+
+static int __devexit pm860x_touch_remove(struct platform_device *pdev)
+{
+	struct pm860x_touch *touch = platform_get_drvdata(pdev);
+
+	input_unregister_device(touch->idev);
+	free_irq(touch->irq, touch);
+	platform_set_drvdata(pdev, NULL);
+	kfree(touch);
+	return 0;
+}
+
+static struct platform_driver pm860x_touch_driver = {
+	.driver	= {
+		.name	= "88pm860x-touch",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= pm860x_touch_probe,
+	.remove	= __devexit_p(pm860x_touch_remove),
+};
+
+static int __init pm860x_touch_init(void)
+{
+	return platform_driver_register(&pm860x_touch_driver);
+}
+module_init(pm860x_touch_init);
+
+static void __exit pm860x_touch_exit(void)
+{
+	platform_driver_unregister(&pm860x_touch_driver);
+}
+module_exit(pm860x_touch_exit);
+
+MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:88pm860x-touch");
+
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6457e06..7208654 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -11,6 +11,18 @@
 
 if INPUT_TOUCHSCREEN
 
+config TOUCHSCREEN_88PM860X
+	tristate "Marvell 88PM860x touchscreen"
+	depends on MFD_88PM860X
+	help
+	  Say Y here if you have a 88PM860x PMIC and want to enable
+	  support for the built-in touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called 88pm860x-ts.
+
 config TOUCHSCREEN_ADS7846
 	tristate "ADS7846/TSC2046 and ADS7843 based touchscreens"
 	depends on SPI_MASTER
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index d61a3b4..7fef7d5 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -6,6 +6,7 @@
 
 wm97xx-ts-y := wm97xx-core.o
 
+obj-$(CONFIG_TOUCHSCREEN_88PM860X)	+= 88pm860x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_AD7877)	+= ad7877.o
 obj-$(CONFIG_TOUCHSCREEN_AD7879)	+= ad7879.o
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
index be115b3..be54fd6 100644
--- a/drivers/input/touchscreen/mc13783_ts.c
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -44,7 +44,7 @@
 {
 	struct mc13783_ts_priv *priv = data;
 
-	mc13783_ackirq(priv->mc13783, irq);
+	mc13783_irq_ack(priv->mc13783, irq);
 
 	/*
 	 * Kick off reading coordinates. Note that if work happens already
@@ -135,7 +135,7 @@
 
 	mc13783_lock(priv->mc13783);
 
-	mc13783_ackirq(priv->mc13783, MC13783_IRQ_TS);
+	mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TS);
 
 	ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS,
 		mc13783_ts_handler, MC13783_TS_NAME, priv);
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index 09095c7..f0bc6fa 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -1712,13 +1712,13 @@
 }
 EXPORT_SYMBOL(mISDNisar_init);
 
-static int isar_mod_init(void)
+static int __init isar_mod_init(void)
 {
 	pr_notice("mISDN: ISAR driver Rev. %s\n", ISAR_REV);
 	return 0;
 }
 
-static void isar_mod_cleanup(void)
+static void __exit isar_mod_cleanup(void)
 {
 	pr_notice("mISDN: ISAR module unloaded\n");
 }
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index adb1e8c..00c60e2 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1347,7 +1347,7 @@
 /*
  * isdn net devices manage lots of configuration variables as linked lists.
  * Those lists must only be manipulated from user space. Some of the ioctl's
- * service routines access user space and are not atomic. Therefor, ioctl's
+ * service routines access user space and are not atomic. Therefore, ioctl's
  * manipulating the lists and ioctl's sleeping while accessing the lists
  * are serialized by means of a semaphore.
  */
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
index 43ff4d3..6eac588 100644
--- a/drivers/isdn/mISDN/dsp_core.c
+++ b/drivers/isdn/mISDN/dsp_core.c
@@ -1114,7 +1114,7 @@
 	.create = dspcreate
 };
 
-static int dsp_init(void)
+static int __init dsp_init(void)
 {
 	int err;
 	int tics;
@@ -1212,7 +1212,7 @@
 }
 
 
-static void dsp_cleanup(void)
+static void __exit dsp_cleanup(void)
 {
 	mISDN_unregister_Bprotocol(&DSP);
 
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
index f1e8af5..325b1ad 100644
--- a/drivers/isdn/mISDN/l1oip_core.c
+++ b/drivers/isdn/mISDN/l1oip_core.c
@@ -477,7 +477,7 @@
 		printk(KERN_DEBUG "%s: received frame, parsing... (%d)\n",
 			__func__, len);
 
-	/* check lenght */
+	/* check length */
 	if (len < 1+1+2) {
 		printk(KERN_WARNING "%s: packet error - length %d below "
 			"4 bytes\n", __func__, len);
@@ -1509,7 +1509,7 @@
 			printk(KERN_DEBUG "%s: interface %d is %s with %s.\n",
 			    __func__, l1oip_cnt, pri ? "PRI" : "BRI",
 			    bundle ? "bundled IP packet for all B-channels" :
-			    "seperate IP packets for every B-channel");
+			    "separate IP packets for every B-channel");
 
 		hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC);
 		if (!hc) {
diff --git a/drivers/isdn/sc/hardware.h b/drivers/isdn/sc/hardware.h
index 9e6d530..6273248 100644
--- a/drivers/isdn/sc/hardware.h
+++ b/drivers/isdn/sc/hardware.h
@@ -87,7 +87,7 @@
 #define BRI_CHANNELS	2		/* Number of B channels */
 #define BRI_BASEPG_VAL	0x98
 #define BRI_MAGIC	0x60000		/* Magic Number */
-#define BRI_MEMSIZE	0x10000		/* Ammount of RAM (64K) */
+#define BRI_MEMSIZE	0x10000		/* Amount of RAM (64K) */
 #define BRI_PARTNO	"72-029"
 #define BRI_FEATURES	ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS;
 /*
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 8a0e1ec..e0b6431 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -17,6 +17,13 @@
 
 comment "LED drivers"
 
+config LEDS_88PM860X
+	tristate "LED Support for Marvell 88PM860x PMIC"
+	depends on LEDS_CLASS && MFD_88PM860X
+	help
+	  This option enables support for on-chip LED drivers found on Marvell
+	  Semiconductor 88PM8606 PMIC.
+
 config LEDS_ATMEL_PWM
 	tristate "LED Support using Atmel PWM outputs"
 	depends on LEDS_CLASS && ATMEL_PWM
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 9e63869..d76fb32 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -5,6 +5,7 @@
 obj-$(CONFIG_LEDS_TRIGGERS)		+= led-triggers.o
 
 # LED Platform Drivers
+obj-$(CONFIG_LEDS_88PM860X)		+= leds-88pm860x.o
 obj-$(CONFIG_LEDS_ATMEL_PWM)		+= leds-atmel-pwm.o
 obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
new file mode 100644
index 0000000..d196073
--- /dev/null
+++ b/drivers/leds/leds-88pm860x.c
@@ -0,0 +1,325 @@
+/*
+ * LED driver for Marvell 88PM860x
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ *	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#include <linux/mfd/88pm860x.h>
+
+#define LED_PWM_SHIFT		(3)
+#define LED_PWM_MASK		(0x1F)
+#define LED_CURRENT_MASK	(0x07 << 5)
+
+#define LED_BLINK_ON_MASK	(0x07)
+#define LED_BLINK_PERIOD_MASK	(0x0F << 3)
+#define LED_BLINK_MASK		(0x7F)
+
+#define LED_BLINK_ON(x)		((x & 0x7) * 66 + 66)
+#define LED_BLINK_PERIOD(x)	((x & 0xF) * 530 + 930)
+#define LED_BLINK_ON_MIN	LED_BLINK_ON(0)
+#define LED_BLINK_ON_MAX	LED_BLINK_ON(0x7)
+#define LED_BLINK_PERIOD_MIN	LED_BLINK_PERIOD(0)
+#define LED_BLINK_PERIOD_MAX	LED_BLINK_PERIOD(0xE)
+#define LED_TO_ON(x)		((x - 66) / 66)
+#define LED_TO_PERIOD(x)	((x - 930) / 530)
+
+#define LED1_BLINK_EN		(1 << 1)
+#define LED2_BLINK_EN		(1 << 2)
+
+enum {
+	SET_BRIGHTNESS,
+	SET_BLINK,
+};
+
+struct pm860x_led {
+	struct led_classdev cdev;
+	struct i2c_client *i2c;
+	struct work_struct work;
+	struct pm860x_chip *chip;
+	struct mutex lock;
+	char name[MFD_NAME_SIZE];
+
+	int port;
+	int iset;
+	int command;
+	int offset;
+	unsigned char brightness;
+	unsigned char current_brightness;
+
+	int blink_data;
+	int blink_time;
+	int blink_on;
+	int blink_off;
+};
+
+/* return offset of color register */
+static inline int __led_off(int port)
+{
+	int ret = -EINVAL;
+
+	switch (port) {
+	case PM8606_LED1_RED:
+	case PM8606_LED1_GREEN:
+	case PM8606_LED1_BLUE:
+		ret = port - PM8606_LED1_RED + PM8606_RGB1B;
+		break;
+	case PM8606_LED2_RED:
+	case PM8606_LED2_GREEN:
+	case PM8606_LED2_BLUE:
+		ret = port - PM8606_LED2_RED + PM8606_RGB2B;
+		break;
+	}
+	return ret;
+}
+
+/* return offset of blink register */
+static inline int __blink_off(int port)
+{
+	int ret = -EINVAL;
+
+	switch (port) {
+	case PM8606_LED1_RED:
+	case PM8606_LED1_GREEN:
+	case PM8606_LED1_BLUE:
+		ret = PM8606_RGB1A;
+	case PM8606_LED2_RED:
+	case PM8606_LED2_GREEN:
+	case PM8606_LED2_BLUE:
+		ret = PM8606_RGB2A;
+	}
+	return ret;
+}
+
+static inline int __blink_ctl_mask(int port)
+{
+	int ret = -EINVAL;
+
+	switch (port) {
+	case PM8606_LED1_RED:
+	case PM8606_LED1_GREEN:
+	case PM8606_LED1_BLUE:
+		ret = LED1_BLINK_EN;
+		break;
+	case PM8606_LED2_RED:
+	case PM8606_LED2_GREEN:
+	case PM8606_LED2_BLUE:
+		ret = LED2_BLINK_EN;
+		break;
+	}
+	return ret;
+}
+
+static int __led_set(struct pm860x_led *led, int command)
+{
+	struct pm860x_chip *chip = led->chip;
+	int mask, ret;
+
+	mutex_lock(&led->lock);
+	switch (command) {
+	case SET_BRIGHTNESS:
+		if ((led->current_brightness == 0) && led->brightness) {
+			if (led->iset) {
+				ret = pm860x_set_bits(led->i2c, led->offset,
+						LED_CURRENT_MASK, led->iset);
+				if (ret < 0)
+					goto out;
+			}
+		} else if (led->brightness == 0) {
+			ret = pm860x_set_bits(led->i2c, led->offset,
+						LED_CURRENT_MASK, 0);
+			if (ret < 0)
+				goto out;
+		}
+		ret = pm860x_set_bits(led->i2c, led->offset, LED_PWM_MASK,
+					led->brightness);
+		if (ret < 0)
+			goto out;
+		led->current_brightness = led->brightness;
+		dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
+			led->offset, led->brightness);
+		break;
+	case SET_BLINK:
+		ret = pm860x_set_bits(led->i2c, led->offset,
+				LED_BLINK_MASK, led->blink_data);
+		if (ret < 0)
+			goto out;
+
+		mask = __blink_ctl_mask(led->port);
+		ret = pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
+		if (ret < 0)
+			goto out;
+		dev_dbg(chip->dev, "LED blink delay on:%dms, delay off:%dms\n",
+			led->blink_on, led->blink_off);
+		break;
+	}
+out:
+	mutex_unlock(&led->lock);
+	return 0;
+}
+
+static void pm860x_led_work(struct work_struct *work)
+{
+	struct pm860x_led *led;
+
+	led = container_of(work, struct pm860x_led, work);
+	__led_set(led, led->command);
+}
+
+static void pm860x_led_set(struct led_classdev *cdev,
+			   enum led_brightness value)
+{
+	struct pm860x_led *data = container_of(cdev, struct pm860x_led, cdev);
+
+	data->offset = __led_off(data->port);
+	data->brightness = value >> 3;
+	data->command = SET_BRIGHTNESS;
+	schedule_work(&data->work);
+}
+
+static int pm860x_led_blink(struct led_classdev *cdev,
+			    unsigned long *delay_on,
+			    unsigned long *delay_off)
+{
+	struct pm860x_led *data = container_of(cdev, struct pm860x_led, cdev);
+	int period, on;
+
+	on = *delay_on;
+	if ((on < LED_BLINK_ON_MIN) || (on > LED_BLINK_ON_MAX))
+		return -EINVAL;
+
+	on = LED_TO_ON(on);
+	on = LED_BLINK_ON(on);
+
+	period = on + *delay_off;
+	if ((period < LED_BLINK_PERIOD_MIN) || (period > LED_BLINK_PERIOD_MAX))
+		return -EINVAL;
+	period = LED_TO_PERIOD(period);
+	period = LED_BLINK_PERIOD(period);
+
+	data->offset = __blink_off(data->port);
+	data->blink_on = on;
+	data->blink_off = period - data->blink_on;
+	data->blink_data = (period << 3) | data->blink_on;
+	data->command = SET_BLINK;
+	schedule_work(&data->work);
+
+	return 0;
+}
+
+static int __check_device(struct pm860x_led_pdata *pdata, char *name)
+{
+	struct pm860x_led_pdata *p = pdata;
+	int ret = -EINVAL;
+
+	while (p && p->id) {
+		if ((p->id != PM8606_ID_LED) || (p->flags < 0))
+			break;
+
+		if (!strncmp(name, pm860x_led_name[p->flags],
+			MFD_NAME_SIZE)) {
+			ret = (int)p->flags;
+			break;
+		}
+		p++;
+	}
+	return ret;
+}
+
+static int pm860x_led_probe(struct platform_device *pdev)
+{
+	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pm860x_platform_data *pm860x_pdata;
+	struct pm860x_led_pdata *pdata;
+	struct pm860x_led *data;
+	struct resource *res;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "No I/O resource!\n");
+		return -EINVAL;
+	}
+
+	if (pdev->dev.parent->platform_data) {
+		pm860x_pdata = pdev->dev.parent->platform_data;
+		pdata = pm860x_pdata->led;
+	} else
+		pdata = NULL;
+
+	data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+	strncpy(data->name, res->name, MFD_NAME_SIZE);
+	dev_set_drvdata(&pdev->dev, data);
+	data->chip = chip;
+	data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
+	data->iset = pdata->iset;
+	data->port = __check_device(pdata, data->name);
+	if (data->port < 0)
+		return -EINVAL;
+
+	data->current_brightness = 0;
+	data->cdev.name = data->name;
+	data->cdev.brightness_set = pm860x_led_set;
+	data->cdev.blink_set = pm860x_led_blink;
+	mutex_init(&data->lock);
+	INIT_WORK(&data->work, pm860x_led_work);
+
+	ret = led_classdev_register(chip->dev, &data->cdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
+		goto out;
+	}
+	return 0;
+out:
+	kfree(data);
+	return ret;
+}
+
+static int pm860x_led_remove(struct platform_device *pdev)
+{
+	struct pm860x_led *data = platform_get_drvdata(pdev);
+
+	led_classdev_unregister(&data->cdev);
+	kfree(data);
+
+	return 0;
+}
+
+static struct platform_driver pm860x_led_driver = {
+	.driver	= {
+		.name	= "88pm860x-led",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= pm860x_led_probe,
+	.remove	= pm860x_led_remove,
+};
+
+static int __devinit pm860x_led_init(void)
+{
+	return platform_driver_register(&pm860x_led_driver);
+}
+module_init(pm860x_led_init);
+
+static void __devexit pm860x_led_exit(void)
+{
+	platform_driver_unregister(&pm860x_led_driver);
+}
+module_exit(pm860x_led_exit);
+
+MODULE_DESCRIPTION("LED driver for Marvell PM860x");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:88pm860x-led");
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 5738d8b..921373e 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -948,10 +948,16 @@
 		printk(KERN_WARNING "Warning ! Temperature way above maximum (%d) !\n",
 		       temp_combi >> 16);
 		state0->overtemp += CPU_MAX_OVERTEMP / 4;
-	} else if (temp_combi > (state0->mpu.tmax << 16))
+	} else if (temp_combi > (state0->mpu.tmax << 16)) {
 		state0->overtemp++;
-	else
+		printk(KERN_WARNING "Temperature %d above max %d. overtemp %d\n",
+		       temp_combi >> 16, state0->mpu.tmax, state0->overtemp);
+	} else {
+		if (state0->overtemp)
+			printk(KERN_WARNING "Temperature back down to %d\n",
+			       temp_combi >> 16);
 		state0->overtemp = 0;
+	}
 	if (state0->overtemp >= CPU_MAX_OVERTEMP)
 		critical_state = 1;
 	if (state0->overtemp > 0) {
@@ -1023,10 +1029,16 @@
 		       " (%d) !\n",
 		       state->index, temp >> 16);
 		state->overtemp += CPU_MAX_OVERTEMP / 4;
-	} else if (temp > (state->mpu.tmax << 16))
+	} else if (temp > (state->mpu.tmax << 16)) {
 		state->overtemp++;
-	else
+		printk(KERN_WARNING "CPU %d temperature %d above max %d. overtemp %d\n",
+		       state->index, temp >> 16, state->mpu.tmax, state->overtemp);
+	} else {
+		if (state->overtemp)
+			printk(KERN_WARNING "CPU %d temperature back down to %d\n",
+			       state->index, temp >> 16);
 		state->overtemp = 0;
+	}
 	if (state->overtemp >= CPU_MAX_OVERTEMP)
 		critical_state = 1;
 	if (state->overtemp > 0) {
@@ -1085,10 +1097,16 @@
 		       " (%d) !\n",
 		       state->index, temp >> 16);
 		state->overtemp = CPU_MAX_OVERTEMP / 4;
-	} else if (temp > (state->mpu.tmax << 16))
+	} else if (temp > (state->mpu.tmax << 16)) {
 		state->overtemp++;
-	else
+		printk(KERN_WARNING "CPU %d temperature %d above max %d. overtemp %d\n",
+		       state->index, temp >> 16, state->mpu.tmax, state->overtemp);
+	} else {
+		if (state->overtemp)
+			printk(KERN_WARNING "CPU %d temperature back down to %d\n",
+			       state->index, temp >> 16);
 		state->overtemp = 0;
+	}
 	if (state->overtemp >= CPU_MAX_OVERTEMP)
 		critical_state = 1;
 	if (state->overtemp > 0) {
diff --git a/drivers/macintosh/therm_pm72.h b/drivers/macintosh/therm_pm72.h
index 393cc9d..df3680e 100644
--- a/drivers/macintosh/therm_pm72.h
+++ b/drivers/macintosh/therm_pm72.h
@@ -269,7 +269,7 @@
 #define CPU_TEMP_HISTORY_SIZE		2
 #define CPU_POWER_HISTORY_SIZE		10
 #define CPU_PID_INTERVAL		1
-#define CPU_MAX_OVERTEMP		30
+#define CPU_MAX_OVERTEMP		90
 
 #define CPUA_PUMP_RPM_INDEX		7
 #define CPUB_PUMP_RPM_INDEX		8
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 437f55c..419795f 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -321,6 +321,7 @@
 	kref_init(&new_sr->ref);
 	list_add(&new_sr->link, &wf_sensors);
 
+	sysfs_attr_init(&new_sr->attr.attr);
 	new_sr->attr.attr.name = new_sr->name;
 	new_sr->attr.attr.mode = 0444;
 	new_sr->attr.show = wf_show_sensor;
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index 6c68b9e..43137b4 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -173,6 +173,7 @@
 
 	fct->fan_type = pwm_fan;
 	fct->ctrl.type = pwm_fan ? WF_CONTROL_PWM_FAN : WF_CONTROL_RPM_FAN;
+	sysfs_attr_init(&fct->ctrl.attr.attr);
 
 	/* We use the name & location here the same way we do for SMU sensors,
 	 * see the comment in windfarm_smu_sensors.c. The locations are a bit
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index a936372..3bdbb61 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1160,8 +1160,7 @@
 	}
 	cc->start = tmpll;
 
-	if (dm_get_device(ti, argv[3], cc->start, ti->len,
-			  dm_table_get_mode(ti->table), &cc->dev)) {
+	if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev)) {
 		ti->error = "Device lookup failed";
 		goto bad_device;
 	}
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index ebe7381..8520528 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -156,8 +156,8 @@
 		goto bad;
 	}
 
-	if (dm_get_device(ti, argv[0], dc->start_read, ti->len,
-			  dm_table_get_mode(ti->table), &dc->dev_read)) {
+	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
+			  &dc->dev_read)) {
 		ti->error = "Device lookup failed";
 		goto bad;
 	}
@@ -177,8 +177,8 @@
 		goto bad_dev_read;
 	}
 
-	if (dm_get_device(ti, argv[3], dc->start_write, ti->len,
-			  dm_table_get_mode(ti->table), &dc->dev_write)) {
+	if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table),
+			  &dc->dev_write)) {
 		ti->error = "Write device lookup failed";
 		goto bad_dev_read;
 	}
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 1d66932..d7500e1 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -285,7 +285,8 @@
 	up_write(&_hash_lock);
 }
 
-static int dm_hash_rename(uint32_t cookie, const char *old, const char *new)
+static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old,
+			  const char *new)
 {
 	char *new_name, *old_name;
 	struct hash_cell *hc;
@@ -344,7 +345,8 @@
 		dm_table_put(table);
 	}
 
-	dm_kobject_uevent(hc->md, KOBJ_CHANGE, cookie);
+	if (!dm_kobject_uevent(hc->md, KOBJ_CHANGE, cookie))
+		*flags |= DM_UEVENT_GENERATED_FLAG;
 
 	dm_put(hc->md);
 	up_write(&_hash_lock);
@@ -736,10 +738,10 @@
 	__hash_remove(hc);
 	up_write(&_hash_lock);
 
-	dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr);
+	if (!dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr))
+		param->flags |= DM_UEVENT_GENERATED_FLAG;
 
 	dm_put(md);
-	param->data_size = 0;
 	return 0;
 }
 
@@ -773,7 +775,9 @@
 		return r;
 
 	param->data_size = 0;
-	return dm_hash_rename(param->event_nr, param->name, new_name);
+
+	return dm_hash_rename(param->event_nr, &param->flags, param->name,
+			      new_name);
 }
 
 static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
@@ -897,16 +901,17 @@
 			set_disk_ro(dm_disk(md), 1);
 	}
 
-	if (dm_suspended_md(md))
+	if (dm_suspended_md(md)) {
 		r = dm_resume(md);
+		if (!r && !dm_kobject_uevent(md, KOBJ_CHANGE, param->event_nr))
+			param->flags |= DM_UEVENT_GENERATED_FLAG;
+	}
 
 	if (old_map)
 		dm_table_destroy(old_map);
 
-	if (!r) {
-		dm_kobject_uevent(md, KOBJ_CHANGE, param->event_nr);
+	if (!r)
 		r = __dev_status(md, param);
-	}
 
 	dm_put(md);
 	return r;
@@ -1476,6 +1481,7 @@
 {
 	/* Always clear this flag */
 	param->flags &= ~DM_BUFFER_FULL_FLAG;
+	param->flags &= ~DM_UEVENT_GENERATED_FLAG;
 
 	/* Ignores parameters */
 	if (cmd == DM_REMOVE_ALL_CMD ||
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 82f7d6e..9200dbf 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -47,8 +47,7 @@
 	}
 	lc->start = tmp;
 
-	if (dm_get_device(ti, argv[0], lc->start, ti->len,
-			  dm_table_get_mode(ti->table), &lc->dev)) {
+	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev)) {
 		ti->error = "dm-linear: Device lookup failed";
 		goto bad;
 	}
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 7035582..5a08be0 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -543,8 +543,7 @@
 		return -EINVAL;
 	}
 
-	r = dm_get_device(ti, argv[0], 0, 0 /* FIXME */,
-			  FMODE_READ | FMODE_WRITE, &dev);
+	r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &dev);
 	if (r)
 		return r;
 
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index e81345a..826bce7 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -69,6 +69,7 @@
 	struct list_head priority_groups;
 	unsigned pg_init_required;	/* pg_init needs calling? */
 	unsigned pg_init_in_progress;	/* Only one pg_init allowed at once */
+	wait_queue_head_t pg_init_wait;	/* Wait for pg_init completion */
 
 	unsigned nr_valid_paths;	/* Total number of usable paths */
 	struct pgpath *current_pgpath;
@@ -95,8 +96,6 @@
 	mempool_t *mpio_pool;
 
 	struct mutex work_mutex;
-
-	unsigned suspended;	/* Don't create new I/O internally when set. */
 };
 
 /*
@@ -202,6 +201,7 @@
 		m->queue_io = 1;
 		INIT_WORK(&m->process_queued_ios, process_queued_ios);
 		INIT_WORK(&m->trigger_event, trigger_event);
+		init_waitqueue_head(&m->pg_init_wait);
 		mutex_init(&m->work_mutex);
 		m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
 		if (!m->mpio_pool) {
@@ -235,6 +235,21 @@
  * Path selection
  *-----------------------------------------------*/
 
+static void __pg_init_all_paths(struct multipath *m)
+{
+	struct pgpath *pgpath;
+
+	m->pg_init_count++;
+	m->pg_init_required = 0;
+	list_for_each_entry(pgpath, &m->current_pg->pgpaths, list) {
+		/* Skip failed paths */
+		if (!pgpath->is_active)
+			continue;
+		if (queue_work(kmpath_handlerd, &pgpath->activate_path))
+			m->pg_init_in_progress++;
+	}
+}
+
 static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
 {
 	m->current_pg = pgpath->pg;
@@ -439,7 +454,7 @@
 {
 	struct multipath *m =
 		container_of(work, struct multipath, process_queued_ios);
-	struct pgpath *pgpath = NULL, *tmp;
+	struct pgpath *pgpath = NULL;
 	unsigned must_queue = 1;
 	unsigned long flags;
 
@@ -457,14 +472,9 @@
 	    (!pgpath && !m->queue_if_no_path))
 		must_queue = 0;
 
-	if (m->pg_init_required && !m->pg_init_in_progress && pgpath) {
-		m->pg_init_count++;
-		m->pg_init_required = 0;
-		list_for_each_entry(tmp, &pgpath->pg->pgpaths, list) {
-			if (queue_work(kmpath_handlerd, &tmp->activate_path))
-				m->pg_init_in_progress++;
-		}
-	}
+	if (m->pg_init_required && !m->pg_init_in_progress && pgpath)
+		__pg_init_all_paths(m);
+
 out:
 	spin_unlock_irqrestore(&m->lock, flags);
 	if (!must_queue)
@@ -597,8 +607,8 @@
 	if (!p)
 		return ERR_PTR(-ENOMEM);
 
-	r = dm_get_device(ti, shift(as), ti->begin, ti->len,
-			  dm_table_get_mode(ti->table), &p->path.dev);
+	r = dm_get_device(ti, shift(as), dm_table_get_mode(ti->table),
+			  &p->path.dev);
 	if (r) {
 		ti->error = "error getting device";
 		goto bad;
@@ -890,9 +900,34 @@
 	return r;
 }
 
-static void flush_multipath_work(void)
+static void multipath_wait_for_pg_init_completion(struct multipath *m)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+
+	add_wait_queue(&m->pg_init_wait, &wait);
+
+	while (1) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+
+		spin_lock_irqsave(&m->lock, flags);
+		if (!m->pg_init_in_progress) {
+			spin_unlock_irqrestore(&m->lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&m->lock, flags);
+
+		io_schedule();
+	}
+	set_current_state(TASK_RUNNING);
+
+	remove_wait_queue(&m->pg_init_wait, &wait);
+}
+
+static void flush_multipath_work(struct multipath *m)
 {
 	flush_workqueue(kmpath_handlerd);
+	multipath_wait_for_pg_init_completion(m);
 	flush_workqueue(kmultipathd);
 	flush_scheduled_work();
 }
@@ -901,7 +936,7 @@
 {
 	struct multipath *m = ti->private;
 
-	flush_multipath_work();
+	flush_multipath_work(m);
 	free_multipath(m);
 }
 
@@ -1128,8 +1163,7 @@
 
 static void pg_init_done(void *data, int errors)
 {
-	struct dm_path *path = data;
-	struct pgpath *pgpath = path_to_pgpath(path);
+	struct pgpath *pgpath = data;
 	struct priority_group *pg = pgpath->pg;
 	struct multipath *m = pg->m;
 	unsigned long flags;
@@ -1143,8 +1177,8 @@
 			errors = 0;
 			break;
 		}
-		DMERR("Cannot failover device because scsi_dh_%s was not "
-		      "loaded.", m->hw_handler_name);
+		DMERR("Could not failover the device: Handler scsi_dh_%s "
+		      "Error %d.", m->hw_handler_name, errors);
 		/*
 		 * Fail path for now, so we do not ping pong
 		 */
@@ -1181,14 +1215,24 @@
 			m->current_pgpath = NULL;
 			m->current_pg = NULL;
 		}
-	} else if (!m->pg_init_required) {
-		m->queue_io = 0;
+	} else if (!m->pg_init_required)
 		pg->bypassed = 0;
-	}
 
-	m->pg_init_in_progress--;
-	if (!m->pg_init_in_progress)
-		queue_work(kmultipathd, &m->process_queued_ios);
+	if (--m->pg_init_in_progress)
+		/* Activations of other paths are still on going */
+		goto out;
+
+	if (!m->pg_init_required)
+		m->queue_io = 0;
+
+	queue_work(kmultipathd, &m->process_queued_ios);
+
+	/*
+	 * Wake up any thread waiting to suspend.
+	 */
+	wake_up(&m->pg_init_wait);
+
+out:
 	spin_unlock_irqrestore(&m->lock, flags);
 }
 
@@ -1198,7 +1242,7 @@
 		container_of(work, struct pgpath, activate_path);
 
 	scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev),
-				pg_init_done, &pgpath->path);
+				pg_init_done, pgpath);
 }
 
 /*
@@ -1276,8 +1320,7 @@
 	struct multipath *m = ti->private;
 
 	mutex_lock(&m->work_mutex);
-	m->suspended = 1;
-	flush_multipath_work();
+	flush_multipath_work(m);
 	mutex_unlock(&m->work_mutex);
 }
 
@@ -1289,10 +1332,6 @@
 	struct multipath *m = (struct multipath *) ti->private;
 	unsigned long flags;
 
-	mutex_lock(&m->work_mutex);
-	m->suspended = 0;
-	mutex_unlock(&m->work_mutex);
-
 	spin_lock_irqsave(&m->lock, flags);
 	m->queue_if_no_path = m->saved_queue_if_no_path;
 	spin_unlock_irqrestore(&m->lock, flags);
@@ -1428,11 +1467,6 @@
 
 	mutex_lock(&m->work_mutex);
 
-	if (m->suspended) {
-		r = -EBUSY;
-		goto out;
-	}
-
 	if (dm_suspended(ti)) {
 		r = -EBUSY;
 		goto out;
@@ -1471,8 +1505,7 @@
 		goto out;
 	}
 
-	r = dm_get_device(ti, argv[1], ti->begin, ti->len,
-			  dm_table_get_mode(ti->table), &dev);
+	r = dm_get_device(ti, argv[1], dm_table_get_mode(ti->table), &dev);
 	if (r) {
 		DMWARN("message: error getting device %s",
 		       argv[1]);
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 6c1046d..ddda531 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -465,9 +465,17 @@
 static void hold_bio(struct mirror_set *ms, struct bio *bio)
 {
 	/*
-	 * If device is suspended, complete the bio.
+	 * Lock is required to avoid race condition during suspend
+	 * process.
 	 */
+	spin_lock_irq(&ms->lock);
+
 	if (atomic_read(&ms->suspend)) {
+		spin_unlock_irq(&ms->lock);
+
+		/*
+		 * If device is suspended, complete the bio.
+		 */
 		if (dm_noflush_suspending(ms->ti))
 			bio_endio(bio, DM_ENDIO_REQUEUE);
 		else
@@ -478,7 +486,6 @@
 	/*
 	 * Hold bio until the suspend is complete.
 	 */
-	spin_lock_irq(&ms->lock);
 	bio_list_add(&ms->holds, bio);
 	spin_unlock_irq(&ms->lock);
 }
@@ -737,9 +744,12 @@
 		dm_rh_delay(ms->rh, bio);
 
 	while ((bio = bio_list_pop(&nosync))) {
-		if (unlikely(ms->leg_failure) && errors_handled(ms))
-			hold_bio(ms, bio);
-		else {
+		if (unlikely(ms->leg_failure) && errors_handled(ms)) {
+			spin_lock_irq(&ms->lock);
+			bio_list_add(&ms->failures, bio);
+			spin_unlock_irq(&ms->lock);
+			wakeup_mirrord(ms);
+		} else {
 			map_bio(get_default_mirror(ms), bio);
 			generic_make_request(bio);
 		}
@@ -917,8 +927,7 @@
 		return -EINVAL;
 	}
 
-	if (dm_get_device(ti, argv[0], offset, ti->len,
-			  dm_table_get_mode(ti->table),
+	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
 			  &ms->mirror[mirror].dev)) {
 		ti->error = "Device lookup failure";
 		return -ENXIO;
@@ -1259,6 +1268,20 @@
 	atomic_set(&ms->suspend, 1);
 
 	/*
+	 * Process bios in the hold list to start recovery waiting
+	 * for bios in the hold list. After the process, no bio has
+	 * a chance to be added in the hold list because ms->suspend
+	 * is set.
+	 */
+	spin_lock_irq(&ms->lock);
+	holds = ms->holds;
+	bio_list_init(&ms->holds);
+	spin_unlock_irq(&ms->lock);
+
+	while ((bio = bio_list_pop(&holds)))
+		hold_bio(ms, bio);
+
+	/*
 	 * We must finish up all the work that we've
 	 * generated (i.e. recovery work).
 	 */
@@ -1278,22 +1301,6 @@
 	 * we know that all of our I/O has been pushed.
 	 */
 	flush_workqueue(ms->kmirrord_wq);
-
-	/*
-	 * Now set ms->suspend is set and the workqueue flushed, no more
-	 * entries can be added to ms->hold list, so process it.
-	 *
-	 * Bios can still arrive concurrently with or after this
-	 * presuspend function, but they cannot join the hold list
-	 * because ms->suspend is set.
-	 */
-	spin_lock_irq(&ms->lock);
-	holds = ms->holds;
-	bio_list_init(&ms->holds);
-	spin_unlock_irq(&ms->lock);
-
-	while ((bio = bio_list_pop(&holds)))
-		hold_bio(ms, bio);
 }
 
 static void mirror_postsuspend(struct dm_target *ti)
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index ee8eb28..5485377 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -83,10 +83,10 @@
 	/* Whether or not owning mapped_device is suspended */
 	int suspended;
 
-	mempool_t *pending_pool;
-
 	atomic_t pending_exceptions_count;
 
+	mempool_t *pending_pool;
+
 	struct dm_exception_table pending;
 	struct dm_exception_table complete;
 
@@ -96,6 +96,11 @@
 	 */
 	spinlock_t pe_lock;
 
+	/* Chunks with outstanding reads */
+	spinlock_t tracked_chunk_lock;
+	mempool_t *tracked_chunk_pool;
+	struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
+
 	/* The on disk metadata handler */
 	struct dm_exception_store *store;
 
@@ -105,10 +110,12 @@
 	struct bio_list queued_bios;
 	struct work_struct queued_bios_work;
 
-	/* Chunks with outstanding reads */
-	mempool_t *tracked_chunk_pool;
-	spinlock_t tracked_chunk_lock;
-	struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
+	/* Wait for events based on state_bits */
+	unsigned long state_bits;
+
+	/* Range of chunks currently being merged. */
+	chunk_t first_merging_chunk;
+	int num_merging_chunks;
 
 	/*
 	 * The merge operation failed if this flag is set.
@@ -125,13 +132,6 @@
 	 */
 	int merge_failed;
 
-	/* Wait for events based on state_bits */
-	unsigned long state_bits;
-
-	/* Range of chunks currently being merged. */
-	chunk_t first_merging_chunk;
-	int num_merging_chunks;
-
 	/*
 	 * Incoming bios that overlap with chunks being merged must wait
 	 * for them to be committed.
@@ -1081,8 +1081,7 @@
 	argv++;
 	argc--;
 
-	r = dm_get_device(ti, cow_path, 0, 0,
-			  FMODE_READ | FMODE_WRITE, &s->cow);
+	r = dm_get_device(ti, cow_path, FMODE_READ | FMODE_WRITE, &s->cow);
 	if (r) {
 		ti->error = "Cannot get COW device";
 		goto bad_cow;
@@ -1098,7 +1097,7 @@
 	argv += args_used;
 	argc -= args_used;
 
-	r = dm_get_device(ti, origin_path, 0, ti->len, origin_mode, &s->origin);
+	r = dm_get_device(ti, origin_path, origin_mode, &s->origin);
 	if (r) {
 		ti->error = "Cannot get origin device";
 		goto bad_origin;
@@ -2100,8 +2099,7 @@
 		return -EINVAL;
 	}
 
-	r = dm_get_device(ti, argv[0], 0, ti->len,
-			  dm_table_get_mode(ti->table), &dev);
+	r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &dev);
 	if (r) {
 		ti->error = "Cannot get target device";
 		return r;
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index bd58703..e610725 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -80,8 +80,7 @@
 	if (sscanf(argv[1], "%llu", &start) != 1)
 		return -EINVAL;
 
-	if (dm_get_device(ti, argv[0], start, sc->stripe_width,
-			  dm_table_get_mode(ti->table),
+	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
 			  &sc->stripe[stripe].dev))
 		return -ENXIO;
 
diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c
index f91b409..84d2b91 100644
--- a/drivers/md/dm-sysfs.c
+++ b/drivers/md/dm-sysfs.c
@@ -75,7 +75,7 @@
 	NULL,
 };
 
-static struct sysfs_ops dm_sysfs_ops = {
+static const struct sysfs_ops dm_sysfs_ops = {
 	.show	= dm_attr_show,
 };
 
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 4b22feb..9924ea2 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -429,8 +429,7 @@
  * it's already present.
  */
 static int __table_get_device(struct dm_table *t, struct dm_target *ti,
-			      const char *path, sector_t start, sector_t len,
-			      fmode_t mode, struct dm_dev **result)
+		      const char *path, fmode_t mode, struct dm_dev **result)
 {
 	int r;
 	dev_t uninitialized_var(dev);
@@ -527,11 +526,10 @@
 }
 EXPORT_SYMBOL_GPL(dm_set_device_limits);
 
-int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
-		  sector_t len, fmode_t mode, struct dm_dev **result)
+int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
+		  struct dm_dev **result)
 {
-	return __table_get_device(ti->table, ti, path,
-				  start, len, mode, result);
+	return __table_get_device(ti->table, ti, path, mode, result);
 }
 
 
@@ -1231,8 +1229,6 @@
 
 struct mapped_device *dm_table_get_md(struct dm_table *t)
 {
-	dm_get(t->md);
-
 	return t->md;
 }
 
diff --git a/drivers/md/dm-uevent.c b/drivers/md/dm-uevent.c
index c7c555a..6b1e3b6 100644
--- a/drivers/md/dm-uevent.c
+++ b/drivers/md/dm-uevent.c
@@ -187,7 +187,7 @@
 
 	if (event_type >= ARRAY_SIZE(_dm_uevent_type_names)) {
 		DMERR("%s: Invalid event_type %d", __func__, event_type);
-		goto out;
+		return;
 	}
 
 	event = dm_build_path_uevent(md, ti,
@@ -195,12 +195,9 @@
 				     _dm_uevent_type_names[event_type].name,
 				     path, nr_valid_paths);
 	if (IS_ERR(event))
-		goto out;
+		return;
 
 	dm_uevent_add(md, &event->elist);
-
-out:
-	dm_put(md);
 }
 EXPORT_SYMBOL_GPL(dm_path_uevent);
 
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index aa4e2aa..d21e128 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -635,8 +635,10 @@
 			if (!md->barrier_error && io_error != -EOPNOTSUPP)
 				md->barrier_error = io_error;
 			end_io_acct(io);
+			free_io(md, io);
 		} else {
 			end_io_acct(io);
+			free_io(md, io);
 
 			if (io_error != DM_ENDIO_REQUEUE) {
 				trace_block_bio_complete(md->queue, bio);
@@ -644,8 +646,6 @@
 				bio_endio(bio, io_error);
 			}
 		}
-
-		free_io(md, io);
 	}
 }
 
@@ -2618,18 +2618,19 @@
 /*-----------------------------------------------------------------
  * Event notification.
  *---------------------------------------------------------------*/
-void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
+int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
 		       unsigned cookie)
 {
 	char udev_cookie[DM_COOKIE_LENGTH];
 	char *envp[] = { udev_cookie, NULL };
 
 	if (!cookie)
-		kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
+		return kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
 	else {
 		snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u",
 			 DM_COOKIE_ENV_VAR_NAME, cookie);
-		kobject_uevent_env(&disk_to_dev(md->disk)->kobj, action, envp);
+		return kobject_uevent_env(&disk_to_dev(md->disk)->kobj,
+					  action, envp);
 	}
 }
 
@@ -2699,23 +2700,13 @@
 
 int dm_suspended(struct dm_target *ti)
 {
-	struct mapped_device *md = dm_table_get_md(ti->table);
-	int r = dm_suspended_md(md);
-
-	dm_put(md);
-
-	return r;
+	return dm_suspended_md(dm_table_get_md(ti->table));
 }
 EXPORT_SYMBOL_GPL(dm_suspended);
 
 int dm_noflush_suspending(struct dm_target *ti)
 {
-	struct mapped_device *md = dm_table_get_md(ti->table);
-	int r = __noflush_suspending(md);
-
-	dm_put(md);
-
-	return r;
+	return __noflush_suspending(dm_table_get_md(ti->table));
 }
 EXPORT_SYMBOL_GPL(dm_noflush_suspending);
 
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 8dadaa5..bad1724 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -125,8 +125,8 @@
 int dm_open_count(struct mapped_device *md);
 int dm_lock_for_deletion(struct mapped_device *md);
 
-void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
-		       unsigned cookie);
+int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
+		      unsigned cookie);
 
 int dm_io_init(void);
 void dm_io_exit(void);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index a20a71e..fdc1890 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2642,7 +2642,7 @@
 	mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj);
 	kfree(rdev);
 }
-static struct sysfs_ops rdev_sysfs_ops = {
+static const struct sysfs_ops rdev_sysfs_ops = {
 	.show		= rdev_attr_show,
 	.store		= rdev_attr_store,
 };
@@ -4059,7 +4059,7 @@
 	kfree(mddev);
 }
 
-static struct sysfs_ops md_sysfs_ops = {
+static const struct sysfs_ops md_sysfs_ops = {
 	.show	= md_attr_show,
 	.store	= md_attr_store,
 };
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 509c8f3..70ffbd0 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4680,7 +4680,7 @@
 {
 	unsigned long cpu;
 	struct page *spare_page;
-	struct raid5_percpu *allcpus;
+	struct raid5_percpu __percpu *allcpus;
 	void *scribble;
 	int err;
 
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index dd70835..0f86f5e 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -405,7 +405,7 @@
 					      * lists and performing address
 					      * conversions
 					      */
-	} *percpu;
+	} __percpu *percpu;
 	size_t			scribble_len; /* size of scribble region must be
 					       * associated with conf to handle
 					       * cpu hotplug while reshaping
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 52e4ce4..80dda30 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -214,14 +214,14 @@
 	int (*get_status)(struct dvb_frontend *fe, u32 *status);
 	int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
 
-	/** These are provided seperately from set_params in order to facilitate silicon
-	 * tuners which require sophisticated tuning loops, controlling each parameter seperately. */
+	/** These are provided separately from set_params in order to facilitate silicon
+	 * tuners which require sophisticated tuning loops, controlling each parameter separately. */
 	int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
 	int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
 
 	/*
-	 * These are provided seperately from set_params in order to facilitate silicon
-	 * tuners which require sophisticated tuning loops, controlling each parameter seperately.
+	 * These are provided separately from set_params in order to facilitate silicon
+	 * tuners which require sophisticated tuning loops, controlling each parameter separately.
 	 */
 	int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
 	int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c
index 7a3de16..75afe4f 100644
--- a/drivers/media/dvb/firewire/firedtv-fw.c
+++ b/drivers/media/dvb/firewire/firedtv-fw.c
@@ -239,47 +239,18 @@
 };
 
 /* Adjust the template string if models with longer names appear. */
-#define MAX_MODEL_NAME_LEN ((int)DIV_ROUND_UP(sizeof("FireDTV ????"), 4))
-
-static size_t model_name(u32 *directory, __be32 *buffer)
-{
-	struct fw_csr_iterator ci;
-	int i, length, key, value, last_key = 0;
-	u32 *block = NULL;
-
-	fw_csr_iterator_init(&ci, directory);
-	while (fw_csr_iterator_next(&ci, &key, &value)) {
-		if (last_key == CSR_MODEL &&
-		    key == (CSR_DESCRIPTOR | CSR_LEAF))
-			block = ci.p - 1 + value;
-		last_key = key;
-	}
-
-	if (block == NULL)
-		return 0;
-
-	length = min((int)(block[0] >> 16) - 2, MAX_MODEL_NAME_LEN);
-	if (length <= 0)
-		return 0;
-
-	/* fast-forward to text string */
-	block += 3;
-
-	for (i = 0; i < length; i++)
-		buffer[i] = cpu_to_be32(block[i]);
-
-	return length * 4;
-}
+#define MAX_MODEL_NAME_LEN sizeof("FireDTV ????")
 
 static int node_probe(struct device *dev)
 {
 	struct firedtv *fdtv;
-	__be32 name[MAX_MODEL_NAME_LEN];
+	char name[MAX_MODEL_NAME_LEN];
 	int name_len, err;
 
-	name_len = model_name(fw_unit(dev)->directory, name);
+	name_len = fw_csr_string(fw_unit(dev)->directory, CSR_MODEL,
+				 name, sizeof(name));
 
-	fdtv = fdtv_alloc(dev, &backend, (char *)name, name_len);
+	fdtv = fdtv_alloc(dev, &backend, name, name_len >= 0 ? name_len : 0);
 	if (!fdtv)
 		return -ENOMEM;
 
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index 12279f6..716870a 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -4404,7 +4404,7 @@
 /* Tibet Systems 'Progress DVR' CS16 muxsel helper [Chris Fanning]
  *
  * The CS16 (available on eBay cheap) is a PCI board with four Fusion
- * 878A chips, a PCI bridge, an Atmel microcontroller, four sync seperator
+ * 878A chips, a PCI bridge, an Atmel microcontroller, four sync separator
  * chips, ten eight input analog multiplexors, a not chip and a few
  * other components.
  *
@@ -4426,7 +4426,7 @@
  *
  * There is an ATMEL microcontroller with an 8031 core on board.  I have not
  * determined what function (if any) it provides.  With the microcontroller
- * and sync seperator chips a guess is that it might have to do with video
+ * and sync separator chips a guess is that it might have to do with video
  * switching and maybe some digital I/O.
  */
 static void tibetCS16_muxsel(struct bttv *btv, unsigned int input)
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index 9b413a3..0f50508 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -616,10 +616,12 @@
 {
 	int devnum = iminor(inode);
 	pdabusb_t s;
+	int r;
 
 	if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB))
 		return -EIO;
 
+	lock_kernel();
 	s = &dabusb[devnum - DABUSB_MINOR];
 
 	dbg("dabusb_open");
@@ -634,6 +636,7 @@
 		msleep_interruptible(500);
 
 		if (signal_pending (current)) {
+			unlock_kernel();
 			return -EAGAIN;
 		}
 		mutex_lock(&s->mutex);
@@ -641,6 +644,7 @@
 	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
 		mutex_unlock(&s->mutex);
 		dev_err(&s->usbdev->dev, "set_interface failed\n");
+		unlock_kernel();
 		return -EINVAL;
 	}
 	s->opened = 1;
@@ -649,7 +653,9 @@
 	file->f_pos = 0;
 	file->private_data = s;
 
-	return nonseekable_open(inode, file);
+	r = nonseekable_open(inode, file);
+	unlock_kernel();
+	return r;
 }
 
 static int dabusb_release (struct inode *inode, struct file *file)
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index bc4ced6..f36e11a 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -512,7 +512,7 @@
 /*
  * The FX2 chip does not give us a zero length read at end of frame.
  * It does, however, give a short read at the end of a frame, if
- * neccessary, rather than run two frames together.
+ * necessary, rather than run two frames together.
  *
  * By choosing the right bulk transfer size, we are guaranteed to always
  * get a short read for the last read of each frame.  Frame sizes are
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c
index 7400eac..142c327 100644
--- a/drivers/media/video/omap24xxcam.c
+++ b/drivers/media/video/omap24xxcam.c
@@ -1735,7 +1735,7 @@
  *
  */
 
-static int __init omap24xxcam_probe(struct platform_device *pdev)
+static int __devinit omap24xxcam_probe(struct platform_device *pdev)
 {
 	struct omap24xxcam_device *cam;
 	struct resource *mem;
diff --git a/drivers/media/video/pwc/philips.txt b/drivers/media/video/pwc/philips.txt
index f9f3584..d38dd79 100644
--- a/drivers/media/video/pwc/philips.txt
+++ b/drivers/media/video/pwc/philips.txt
@@ -33,7 +33,7 @@
 contains decompression routines that allow you to use higher image sizes and
 framerates; in addition the webcam uses less bandwidth on the USB bus (handy
 if you want to run more than 1 camera simultaneously). These routines fall
-under a NDA, and may therefor not be distributed as source; however, its use
+under a NDA, and may therefore not be distributed as source; however, its use
 is completely optional.
 
 You can build this code either into your kernel, or as a module. I recommend
diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h
index 4af7382..494957b 100644
--- a/drivers/media/video/sn9c102/sn9c102_sensor.h
+++ b/drivers/media/video/sn9c102/sn9c102_sensor.h
@@ -120,7 +120,7 @@
 /*
    Write multiple registers with constant values. For example:
    sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
-   Register adresses must be < 256.
+   Register addresses must be < 256.
 */
 #define sn9c102_write_const_regs(sn9c102_device, data...)                     \
 	({ static const u8 _valreg[][2] = {data};                             \
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 0446524..6bf6bc7 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -6,7 +6,7 @@
 
     The tea6420 is a bus controlled audio-matrix with 5 stereo inputs,
     4 stereo outputs and gain control for each output.
-    It is cascadable, i.e. it can be found at the adresses 0x98
+    It is cascadable, i.e. it can be found at the addresses 0x98
     and 0x9a on the i2c-bus.
 
     For detailed informations download the specifications directly
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index e5ab621..ef5ce26 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -539,7 +539,7 @@
 		 * which is indeterminate. We need to wait until the IOP has
 		 * rebooted before we can let the system talk to it. We read
 		 * the inbound Free_List until a message is available. If we
-		 * can't read one in the given ammount of time, we assume the
+		 * can't read one in the given amount of time, we assume the
 		 * IOP could not reboot properly.
 		 */
 		osm_debug("%s: Reset in progress, waiting for reboot...\n",
diff --git a/drivers/mfd/88pm8607.c b/drivers/mfd/88pm8607.c
deleted file mode 100644
index 7e3f659..0000000
--- a/drivers/mfd/88pm8607.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Base driver for Marvell 88PM8607
- *
- * Copyright (C) 2009 Marvell International Ltd.
- * 	Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/88pm8607.h>
-
-
-#define PM8607_REG_RESOURCE(_start, _end)		\
-{							\
-	.start	= PM8607_##_start,			\
-	.end	= PM8607_##_end,			\
-	.flags	= IORESOURCE_IO,			\
-}
-
-static struct resource pm8607_regulator_resources[] = {
-	PM8607_REG_RESOURCE(BUCK1, BUCK1),
-	PM8607_REG_RESOURCE(BUCK2, BUCK2),
-	PM8607_REG_RESOURCE(BUCK3, BUCK3),
-	PM8607_REG_RESOURCE(LDO1,  LDO1),
-	PM8607_REG_RESOURCE(LDO2,  LDO2),
-	PM8607_REG_RESOURCE(LDO3,  LDO3),
-	PM8607_REG_RESOURCE(LDO4,  LDO4),
-	PM8607_REG_RESOURCE(LDO5,  LDO5),
-	PM8607_REG_RESOURCE(LDO6,  LDO6),
-	PM8607_REG_RESOURCE(LDO7,  LDO7),
-	PM8607_REG_RESOURCE(LDO8,  LDO8),
-	PM8607_REG_RESOURCE(LDO9,  LDO9),
-	PM8607_REG_RESOURCE(LDO10, LDO10),
-	PM8607_REG_RESOURCE(LDO12, LDO12),
-	PM8607_REG_RESOURCE(LDO14, LDO14),
-};
-
-#define PM8607_REG_DEVS(_name, _id)					\
-{									\
-	.name		= "88pm8607-" #_name,				\
-	.num_resources	= 1,						\
-	.resources	= &pm8607_regulator_resources[PM8607_ID_##_id],	\
-}
-
-static struct mfd_cell pm8607_devs[] = {
-	PM8607_REG_DEVS(buck1, BUCK1),
-	PM8607_REG_DEVS(buck2, BUCK2),
-	PM8607_REG_DEVS(buck3, BUCK3),
-	PM8607_REG_DEVS(ldo1,  LDO1),
-	PM8607_REG_DEVS(ldo2,  LDO2),
-	PM8607_REG_DEVS(ldo3,  LDO3),
-	PM8607_REG_DEVS(ldo4,  LDO4),
-	PM8607_REG_DEVS(ldo5,  LDO5),
-	PM8607_REG_DEVS(ldo6,  LDO6),
-	PM8607_REG_DEVS(ldo7,  LDO7),
-	PM8607_REG_DEVS(ldo8,  LDO8),
-	PM8607_REG_DEVS(ldo9,  LDO9),
-	PM8607_REG_DEVS(ldo10, LDO10),
-	PM8607_REG_DEVS(ldo12, LDO12),
-	PM8607_REG_DEVS(ldo14, LDO14),
-};
-
-static inline int pm8607_read_device(struct pm8607_chip *chip,
-				     int reg, int bytes, void *dest)
-{
-	struct i2c_client *i2c = chip->client;
-	unsigned char data;
-	int ret;
-
-	data = (unsigned char)reg;
-	ret = i2c_master_send(i2c, &data, 1);
-	if (ret < 0)
-		return ret;
-
-	ret = i2c_master_recv(i2c, dest, bytes);
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
-static inline int pm8607_write_device(struct pm8607_chip *chip,
-				      int reg, int bytes, void *src)
-{
-	struct i2c_client *i2c = chip->client;
-	unsigned char buf[bytes + 1];
-	int ret;
-
-	buf[0] = (unsigned char)reg;
-	memcpy(&buf[1], src, bytes);
-
-	ret = i2c_master_send(i2c, buf, bytes + 1);
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
-int pm8607_reg_read(struct pm8607_chip *chip, int reg)
-{
-	unsigned char data;
-	int ret;
-
-	mutex_lock(&chip->io_lock);
-	ret = chip->read(chip, reg, 1, &data);
-	mutex_unlock(&chip->io_lock);
-
-	if (ret < 0)
-		return ret;
-	else
-		return (int)data;
-}
-EXPORT_SYMBOL(pm8607_reg_read);
-
-int pm8607_reg_write(struct pm8607_chip *chip, int reg,
-		     unsigned char data)
-{
-	int ret;
-
-	mutex_lock(&chip->io_lock);
-	ret = chip->write(chip, reg, 1, &data);
-	mutex_unlock(&chip->io_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL(pm8607_reg_write);
-
-int pm8607_bulk_read(struct pm8607_chip *chip, int reg,
-		     int count, unsigned char *buf)
-{
-	int ret;
-
-	mutex_lock(&chip->io_lock);
-	ret = chip->read(chip, reg, count, buf);
-	mutex_unlock(&chip->io_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL(pm8607_bulk_read);
-
-int pm8607_bulk_write(struct pm8607_chip *chip, int reg,
-		      int count, unsigned char *buf)
-{
-	int ret;
-
-	mutex_lock(&chip->io_lock);
-	ret = chip->write(chip, reg, count, buf);
-	mutex_unlock(&chip->io_lock);
-
-	return ret;
-}
-EXPORT_SYMBOL(pm8607_bulk_write);
-
-int pm8607_set_bits(struct pm8607_chip *chip, int reg,
-		    unsigned char mask, unsigned char data)
-{
-	unsigned char value;
-	int ret;
-
-	mutex_lock(&chip->io_lock);
-	ret = chip->read(chip, reg, 1, &value);
-	if (ret < 0)
-		goto out;
-	value &= ~mask;
-	value |= data;
-	ret = chip->write(chip, reg, 1, &value);
-out:
-	mutex_unlock(&chip->io_lock);
-	return ret;
-}
-EXPORT_SYMBOL(pm8607_set_bits);
-
-
-static const struct i2c_device_id pm8607_id_table[] = {
-	{ "88PM8607", 0 },
-	{}
-};
-MODULE_DEVICE_TABLE(i2c, pm8607_id_table);
-
-
-static int __devinit pm8607_probe(struct i2c_client *client,
-				  const struct i2c_device_id *id)
-{
-	struct pm8607_platform_data *pdata = client->dev.platform_data;
-	struct pm8607_chip *chip;
-	int i, count;
-	int ret;
-
-	chip = kzalloc(sizeof(struct pm8607_chip), GFP_KERNEL);
-	if (chip == NULL)
-		return -ENOMEM;
-
-	chip->client = client;
-	chip->dev = &client->dev;
-	chip->read = pm8607_read_device;
-	chip->write = pm8607_write_device;
-	i2c_set_clientdata(client, chip);
-
-	mutex_init(&chip->io_lock);
-	dev_set_drvdata(chip->dev, chip);
-
-	ret = pm8607_reg_read(chip, PM8607_CHIP_ID);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
-		goto out;
-	}
-	if ((ret & CHIP_ID_MASK) == CHIP_ID)
-		dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n",
-			 ret);
-	else {
-		dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
-			"Chip ID: %02x\n", ret);
-		goto out;
-	}
-	chip->chip_id = ret;
-
-	ret = pm8607_reg_read(chip, PM8607_BUCK3);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret);
-		goto out;
-	}
-	if (ret & PM8607_BUCK3_DOUBLE)
-		chip->buck3_double = 1;
-
-	ret = pm8607_reg_read(chip, PM8607_MISC1);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret);
-		goto out;
-	}
-	if (pdata->i2c_port == PI2C_PORT)
-		ret |= PM8607_MISC1_PI2C;
-	else
-		ret &= ~PM8607_MISC1_PI2C;
-	ret = pm8607_reg_write(chip, PM8607_MISC1, ret);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to write MISC1 register: %d\n", ret);
-		goto out;
-	}
-
-
-	count = ARRAY_SIZE(pm8607_devs);
-	for (i = 0; i < count; i++) {
-		ret = mfd_add_devices(chip->dev, i, &pm8607_devs[i],
-				      1, NULL, 0);
-		if (ret != 0) {
-			dev_err(chip->dev, "Failed to add subdevs\n");
-			goto out;
-		}
-	}
-
-	return 0;
-
-out:
-	i2c_set_clientdata(client, NULL);
-	kfree(chip);
-	return ret;
-}
-
-static int __devexit pm8607_remove(struct i2c_client *client)
-{
-	struct pm8607_chip *chip = i2c_get_clientdata(client);
-
-	mfd_remove_devices(chip->dev);
-	kfree(chip);
-	return 0;
-}
-
-static struct i2c_driver pm8607_driver = {
-	.driver	= {
-		.name	= "88PM8607",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= pm8607_probe,
-	.remove		= __devexit_p(pm8607_remove),
-	.id_table	= pm8607_id_table,
-};
-
-static int __init pm8607_init(void)
-{
-	int ret;
-	ret = i2c_add_driver(&pm8607_driver);
-	if (ret != 0)
-		pr_err("Failed to register 88PM8607 I2C driver: %d\n", ret);
-	return ret;
-}
-subsys_initcall(pm8607_init);
-
-static void __exit pm8607_exit(void)
-{
-	i2c_del_driver(&pm8607_driver);
-}
-module_exit(pm8607_exit);
-
-MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM8607");
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
new file mode 100644
index 0000000..6a14d2b
--- /dev/null
+++ b/drivers/mfd/88pm860x-core.c
@@ -0,0 +1,740 @@
+/*
+ * Base driver for Marvell 88PM8607
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * 	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/88pm860x.h>
+
+#define INT_STATUS_NUM			3
+
+char pm860x_backlight_name[][MFD_NAME_SIZE] = {
+	"backlight-0",
+	"backlight-1",
+	"backlight-2",
+};
+EXPORT_SYMBOL(pm860x_backlight_name);
+
+char pm860x_led_name[][MFD_NAME_SIZE] = {
+	"led0-red",
+	"led0-green",
+	"led0-blue",
+	"led1-red",
+	"led1-green",
+	"led1-blue",
+};
+EXPORT_SYMBOL(pm860x_led_name);
+
+#define PM8606_BACKLIGHT_RESOURCE(_i, _x)		\
+{							\
+	.name	= pm860x_backlight_name[_i],		\
+	.start	= PM8606_##_x,				\
+	.end	= PM8606_##_x,				\
+	.flags	= IORESOURCE_IO,			\
+}
+
+static struct resource backlight_resources[] = {
+	PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT1, WLED1A),
+	PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT2, WLED2A),
+	PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT3, WLED3A),
+};
+
+#define PM8606_BACKLIGHT_DEVS(_i)			\
+{							\
+	.name		= "88pm860x-backlight",		\
+	.num_resources	= 1,				\
+	.resources	= &backlight_resources[_i],	\
+	.id		= _i,				\
+}
+
+static struct mfd_cell backlight_devs[] = {
+	PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT1),
+	PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT2),
+	PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT3),
+};
+
+#define PM8606_LED_RESOURCE(_i, _x)			\
+{							\
+	.name	= pm860x_led_name[_i],			\
+	.start	= PM8606_##_x,				\
+	.end	= PM8606_##_x,				\
+	.flags	= IORESOURCE_IO,			\
+}
+
+static struct resource led_resources[] = {
+	PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB2B),
+	PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB2C),
+	PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB2D),
+	PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB1B),
+	PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB1C),
+	PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB1D),
+};
+
+#define PM8606_LED_DEVS(_i)				\
+{							\
+	.name		= "88pm860x-led",		\
+	.num_resources	= 1,				\
+	.resources	= &led_resources[_i],		\
+	.id		= _i,				\
+}
+
+static struct mfd_cell led_devs[] = {
+	PM8606_LED_DEVS(PM8606_LED1_RED),
+	PM8606_LED_DEVS(PM8606_LED1_GREEN),
+	PM8606_LED_DEVS(PM8606_LED1_BLUE),
+	PM8606_LED_DEVS(PM8606_LED2_RED),
+	PM8606_LED_DEVS(PM8606_LED2_GREEN),
+	PM8606_LED_DEVS(PM8606_LED2_BLUE),
+};
+
+static struct resource touch_resources[] = {
+	{
+		.start	= PM8607_IRQ_PEN,
+		.end	= PM8607_IRQ_PEN,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell touch_devs[] = {
+	{
+		.name		= "88pm860x-touch",
+		.num_resources	= 1,
+		.resources	= &touch_resources[0],
+	},
+};
+
+#define PM8607_REG_RESOURCE(_start, _end)		\
+{							\
+	.start	= PM8607_##_start,			\
+	.end	= PM8607_##_end,			\
+	.flags	= IORESOURCE_IO,			\
+}
+
+static struct resource power_supply_resources[] = {
+	{
+		.name		= "88pm860x-power",
+		.start		= PM8607_IRQ_CHG,
+		.end		= PM8607_IRQ_CHG,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell power_devs[] = {
+	{
+		.name		= "88pm860x-power",
+		.num_resources	= 1,
+		.resources	= &power_supply_resources[0],
+		.id		= -1,
+	},
+};
+
+static struct resource onkey_resources[] = {
+	{
+		.name		= "88pm860x-onkey",
+		.start		= PM8607_IRQ_ONKEY,
+		.end		= PM8607_IRQ_ONKEY,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell onkey_devs[] = {
+	{
+		.name		= "88pm860x-onkey",
+		.num_resources	= 1,
+		.resources	= &onkey_resources[0],
+		.id		= -1,
+	},
+};
+
+static struct resource regulator_resources[] = {
+	PM8607_REG_RESOURCE(BUCK1, BUCK1),
+	PM8607_REG_RESOURCE(BUCK2, BUCK2),
+	PM8607_REG_RESOURCE(BUCK3, BUCK3),
+	PM8607_REG_RESOURCE(LDO1,  LDO1),
+	PM8607_REG_RESOURCE(LDO2,  LDO2),
+	PM8607_REG_RESOURCE(LDO3,  LDO3),
+	PM8607_REG_RESOURCE(LDO4,  LDO4),
+	PM8607_REG_RESOURCE(LDO5,  LDO5),
+	PM8607_REG_RESOURCE(LDO6,  LDO6),
+	PM8607_REG_RESOURCE(LDO7,  LDO7),
+	PM8607_REG_RESOURCE(LDO8,  LDO8),
+	PM8607_REG_RESOURCE(LDO9,  LDO9),
+	PM8607_REG_RESOURCE(LDO10, LDO10),
+	PM8607_REG_RESOURCE(LDO12, LDO12),
+	PM8607_REG_RESOURCE(LDO14, LDO14),
+};
+
+#define PM8607_REG_DEVS(_name, _id)					\
+{									\
+	.name		= "88pm8607-" #_name,				\
+	.num_resources	= 1,						\
+	.resources	= &regulator_resources[PM8607_ID_##_id],	\
+	.id		= PM8607_ID_##_id,				\
+}
+
+static struct mfd_cell regulator_devs[] = {
+	PM8607_REG_DEVS(buck1, BUCK1),
+	PM8607_REG_DEVS(buck2, BUCK2),
+	PM8607_REG_DEVS(buck3, BUCK3),
+	PM8607_REG_DEVS(ldo1,  LDO1),
+	PM8607_REG_DEVS(ldo2,  LDO2),
+	PM8607_REG_DEVS(ldo3,  LDO3),
+	PM8607_REG_DEVS(ldo4,  LDO4),
+	PM8607_REG_DEVS(ldo5,  LDO5),
+	PM8607_REG_DEVS(ldo6,  LDO6),
+	PM8607_REG_DEVS(ldo7,  LDO7),
+	PM8607_REG_DEVS(ldo8,  LDO8),
+	PM8607_REG_DEVS(ldo9,  LDO9),
+	PM8607_REG_DEVS(ldo10, LDO10),
+	PM8607_REG_DEVS(ldo12, LDO12),
+	PM8607_REG_DEVS(ldo14, LDO14),
+};
+
+struct pm860x_irq_data {
+	int	reg;
+	int	mask_reg;
+	int	enable;		/* enable or not */
+	int	offs;		/* bit offset in mask register */
+};
+
+static struct pm860x_irq_data pm860x_irqs[] = {
+	[PM8607_IRQ_ONKEY] = {
+		.reg		= PM8607_INT_STATUS1,
+		.mask_reg	= PM8607_INT_MASK_1,
+		.offs		= 1 << 0,
+	},
+	[PM8607_IRQ_EXTON] = {
+		.reg		= PM8607_INT_STATUS1,
+		.mask_reg	= PM8607_INT_MASK_1,
+		.offs		= 1 << 1,
+	},
+	[PM8607_IRQ_CHG] = {
+		.reg		= PM8607_INT_STATUS1,
+		.mask_reg	= PM8607_INT_MASK_1,
+		.offs		= 1 << 2,
+	},
+	[PM8607_IRQ_BAT] = {
+		.reg		= PM8607_INT_STATUS1,
+		.mask_reg	= PM8607_INT_MASK_1,
+		.offs		= 1 << 3,
+	},
+	[PM8607_IRQ_RTC] = {
+		.reg		= PM8607_INT_STATUS1,
+		.mask_reg	= PM8607_INT_MASK_1,
+		.offs		= 1 << 4,
+	},
+	[PM8607_IRQ_CC] = {
+		.reg		= PM8607_INT_STATUS1,
+		.mask_reg	= PM8607_INT_MASK_1,
+		.offs		= 1 << 5,
+	},
+	[PM8607_IRQ_VBAT] = {
+		.reg		= PM8607_INT_STATUS2,
+		.mask_reg	= PM8607_INT_MASK_2,
+		.offs		= 1 << 0,
+	},
+	[PM8607_IRQ_VCHG] = {
+		.reg		= PM8607_INT_STATUS2,
+		.mask_reg	= PM8607_INT_MASK_2,
+		.offs		= 1 << 1,
+	},
+	[PM8607_IRQ_VSYS] = {
+		.reg		= PM8607_INT_STATUS2,
+		.mask_reg	= PM8607_INT_MASK_2,
+		.offs		= 1 << 2,
+	},
+	[PM8607_IRQ_TINT] = {
+		.reg		= PM8607_INT_STATUS2,
+		.mask_reg	= PM8607_INT_MASK_2,
+		.offs		= 1 << 3,
+	},
+	[PM8607_IRQ_GPADC0] = {
+		.reg		= PM8607_INT_STATUS2,
+		.mask_reg	= PM8607_INT_MASK_2,
+		.offs		= 1 << 4,
+	},
+	[PM8607_IRQ_GPADC1] = {
+		.reg		= PM8607_INT_STATUS2,
+		.mask_reg	= PM8607_INT_MASK_2,
+		.offs		= 1 << 5,
+	},
+	[PM8607_IRQ_GPADC2] = {
+		.reg		= PM8607_INT_STATUS2,
+		.mask_reg	= PM8607_INT_MASK_2,
+		.offs		= 1 << 6,
+	},
+	[PM8607_IRQ_GPADC3] = {
+		.reg		= PM8607_INT_STATUS2,
+		.mask_reg	= PM8607_INT_MASK_2,
+		.offs		= 1 << 7,
+	},
+	[PM8607_IRQ_AUDIO_SHORT] = {
+		.reg		= PM8607_INT_STATUS3,
+		.mask_reg	= PM8607_INT_MASK_3,
+		.offs		= 1 << 0,
+	},
+	[PM8607_IRQ_PEN] = {
+		.reg		= PM8607_INT_STATUS3,
+		.mask_reg	= PM8607_INT_MASK_3,
+		.offs		= 1 << 1,
+	},
+	[PM8607_IRQ_HEADSET] = {
+		.reg		= PM8607_INT_STATUS3,
+		.mask_reg	= PM8607_INT_MASK_3,
+		.offs		= 1 << 2,
+	},
+	[PM8607_IRQ_HOOK] = {
+		.reg		= PM8607_INT_STATUS3,
+		.mask_reg	= PM8607_INT_MASK_3,
+		.offs		= 1 << 3,
+	},
+	[PM8607_IRQ_MICIN] = {
+		.reg		= PM8607_INT_STATUS3,
+		.mask_reg	= PM8607_INT_MASK_3,
+		.offs		= 1 << 4,
+	},
+	[PM8607_IRQ_CHG_FAIL] = {
+		.reg		= PM8607_INT_STATUS3,
+		.mask_reg	= PM8607_INT_MASK_3,
+		.offs		= 1 << 5,
+	},
+	[PM8607_IRQ_CHG_DONE] = {
+		.reg		= PM8607_INT_STATUS3,
+		.mask_reg	= PM8607_INT_MASK_3,
+		.offs		= 1 << 6,
+	},
+	[PM8607_IRQ_CHG_FAULT] = {
+		.reg		= PM8607_INT_STATUS3,
+		.mask_reg	= PM8607_INT_MASK_3,
+		.offs		= 1 << 7,
+	},
+};
+
+static inline struct pm860x_irq_data *irq_to_pm860x(struct pm860x_chip *chip,
+						    int irq)
+{
+	return &pm860x_irqs[irq - chip->irq_base];
+}
+
+static irqreturn_t pm860x_irq(int irq, void *data)
+{
+	struct pm860x_chip *chip = data;
+	struct pm860x_irq_data *irq_data;
+	struct i2c_client *i2c;
+	int read_reg = -1, value = 0;
+	int i;
+
+	i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
+		irq_data = &pm860x_irqs[i];
+		if (read_reg != irq_data->reg) {
+			read_reg = irq_data->reg;
+			value = pm860x_reg_read(i2c, irq_data->reg);
+		}
+		if (value & irq_data->enable)
+			handle_nested_irq(chip->irq_base + i);
+	}
+	return IRQ_HANDLED;
+}
+
+static void pm860x_irq_lock(unsigned int irq)
+{
+	struct pm860x_chip *chip = get_irq_chip_data(irq);
+
+	mutex_lock(&chip->irq_lock);
+}
+
+static void pm860x_irq_sync_unlock(unsigned int irq)
+{
+	struct pm860x_chip *chip = get_irq_chip_data(irq);
+	struct pm860x_irq_data *irq_data;
+	struct i2c_client *i2c;
+	static unsigned char cached[3] = {0x0, 0x0, 0x0};
+	unsigned char mask[3];
+	int i;
+
+	i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+	/* Load cached value. In initial, all IRQs are masked */
+	for (i = 0; i < 3; i++)
+		mask[i] = cached[i];
+	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
+		irq_data = &pm860x_irqs[i];
+		switch (irq_data->mask_reg) {
+		case PM8607_INT_MASK_1:
+			mask[0] &= ~irq_data->offs;
+			mask[0] |= irq_data->enable;
+			break;
+		case PM8607_INT_MASK_2:
+			mask[1] &= ~irq_data->offs;
+			mask[1] |= irq_data->enable;
+			break;
+		case PM8607_INT_MASK_3:
+			mask[2] &= ~irq_data->offs;
+			mask[2] |= irq_data->enable;
+			break;
+		default:
+			dev_err(chip->dev, "wrong IRQ\n");
+			break;
+		}
+	}
+	/* update mask into registers */
+	for (i = 0; i < 3; i++) {
+		if (mask[i] != cached[i]) {
+			cached[i] = mask[i];
+			pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]);
+		}
+	}
+
+	mutex_unlock(&chip->irq_lock);
+}
+
+static void pm860x_irq_enable(unsigned int irq)
+{
+	struct pm860x_chip *chip = get_irq_chip_data(irq);
+	pm860x_irqs[irq - chip->irq_base].enable
+		= pm860x_irqs[irq - chip->irq_base].offs;
+}
+
+static void pm860x_irq_disable(unsigned int irq)
+{
+	struct pm860x_chip *chip = get_irq_chip_data(irq);
+	pm860x_irqs[irq - chip->irq_base].enable = 0;
+}
+
+static struct irq_chip pm860x_irq_chip = {
+	.name		= "88pm860x",
+	.bus_lock	= pm860x_irq_lock,
+	.bus_sync_unlock = pm860x_irq_sync_unlock,
+	.enable		= pm860x_irq_enable,
+	.disable	= pm860x_irq_disable,
+};
+
+static int __devinit device_gpadc_init(struct pm860x_chip *chip,
+				       struct pm860x_platform_data *pdata)
+{
+	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+				: chip->companion;
+	int use_gpadc = 0, data, ret;
+
+	/* initialize GPADC without activating it */
+
+	if (pdata && pdata->touch) {
+		/* set GPADC MISC1 register */
+		data = 0;
+		data |= (pdata->touch->gpadc_prebias << 1)
+			& PM8607_GPADC_PREBIAS_MASK;
+		data |= (pdata->touch->slot_cycle << 3)
+			& PM8607_GPADC_SLOT_CYCLE_MASK;
+		data |= (pdata->touch->off_scale << 5)
+			& PM8607_GPADC_OFF_SCALE_MASK;
+		data |= (pdata->touch->sw_cal << 7)
+			& PM8607_GPADC_SW_CAL_MASK;
+		if (data) {
+			ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
+			if (ret < 0)
+				goto out;
+		}
+		/* set tsi prebias time */
+		if (pdata->touch->tsi_prebias) {
+			data = pdata->touch->tsi_prebias;
+			ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
+			if (ret < 0)
+				goto out;
+		}
+		/* set prebias & prechg time of pen detect */
+		data = 0;
+		data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK;
+		data |= (pdata->touch->pen_prechg << 5)
+			& PM8607_PD_PRECHG_MASK;
+		if (data) {
+			ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
+			if (ret < 0)
+				goto out;
+		}
+
+		use_gpadc = 1;
+	}
+
+	/* turn on GPADC */
+	if (use_gpadc) {
+		ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
+				      PM8607_GPADC_EN, PM8607_GPADC_EN);
+	}
+out:
+	return ret;
+}
+
+static int __devinit device_irq_init(struct pm860x_chip *chip,
+				     struct pm860x_platform_data *pdata)
+{
+	struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+				: chip->companion;
+	unsigned char status_buf[INT_STATUS_NUM];
+	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+	struct irq_desc *desc;
+	int i, data, mask, ret = -EINVAL;
+	int __irq;
+
+	if (!pdata || !pdata->irq_base) {
+		dev_warn(chip->dev, "No interrupt support on IRQ base\n");
+		return -EINVAL;
+	}
+
+	mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
+		| PM8607_B0_MISC1_INT_MASK;
+	data = 0;
+	chip->irq_mode = 0;
+	if (pdata && pdata->irq_mode) {
+		/*
+		 * irq_mode defines the way of clearing interrupt. If it's 1,
+		 * clear IRQ by write. Otherwise, clear it by read.
+		 * This control bit is valid from 88PM8607 B0 steping.
+		 */
+		data |= PM8607_B0_MISC1_INT_CLEAR;
+		chip->irq_mode = 1;
+	}
+	ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, mask, data);
+	if (ret < 0)
+		goto out;
+
+	/* mask all IRQs */
+	memset(status_buf, 0, INT_STATUS_NUM);
+	ret = pm860x_bulk_write(i2c, PM8607_INT_MASK_1,
+				INT_STATUS_NUM, status_buf);
+	if (ret < 0)
+		goto out;
+
+	if (chip->irq_mode) {
+		/* clear interrupt status by write */
+		memset(status_buf, 0xFF, INT_STATUS_NUM);
+		ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1,
+					INT_STATUS_NUM, status_buf);
+	} else {
+		/* clear interrupt status by read */
+		ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1,
+					INT_STATUS_NUM, status_buf);
+	}
+	if (ret < 0)
+		goto out;
+
+	mutex_init(&chip->irq_lock);
+	chip->irq_base = pdata->irq_base;
+	chip->core_irq = i2c->irq;
+	if (!chip->core_irq)
+		goto out;
+
+	desc = irq_to_desc(chip->core_irq);
+
+	/* register IRQ by genirq */
+	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
+		__irq = i + chip->irq_base;
+		set_irq_chip_data(__irq, chip);
+		set_irq_chip_and_handler(__irq, &pm860x_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
+	}
+
+	ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags,
+				   "88pm860x", chip);
+	if (ret) {
+		dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
+		chip->core_irq = 0;
+	}
+
+	return 0;
+out:
+	chip->core_irq = 0;
+	return ret;
+}
+
+static void __devexit device_irq_exit(struct pm860x_chip *chip)
+{
+	if (chip->core_irq)
+		free_irq(chip->core_irq, chip);
+}
+
+static void __devinit device_8606_init(struct pm860x_chip *chip,
+				       struct i2c_client *i2c,
+				       struct pm860x_platform_data *pdata)
+{
+	int ret;
+
+	if (pdata && pdata->backlight) {
+		ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
+				      ARRAY_SIZE(backlight_devs),
+				      &backlight_resources[0], 0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to add backlight "
+				"subdev\n");
+			goto out_dev;
+		}
+	}
+
+	if (pdata && pdata->led) {
+		ret = mfd_add_devices(chip->dev, 0, &led_devs[0],
+				      ARRAY_SIZE(led_devs),
+				      &led_resources[0], 0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to add led "
+				"subdev\n");
+			goto out_dev;
+		}
+	}
+	return;
+out_dev:
+	mfd_remove_devices(chip->dev);
+	device_irq_exit(chip);
+}
+
+static void __devinit device_8607_init(struct pm860x_chip *chip,
+				       struct i2c_client *i2c,
+				       struct pm860x_platform_data *pdata)
+{
+	int data, ret;
+
+	ret = pm860x_reg_read(i2c, PM8607_CHIP_ID);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
+		goto out;
+	}
+	if ((ret & PM8607_VERSION_MASK) == PM8607_VERSION)
+		dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n",
+			 ret);
+	else {
+		dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
+			"Chip ID: %02x\n", ret);
+		goto out;
+	}
+
+	ret = pm860x_reg_read(i2c, PM8607_BUCK3);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret);
+		goto out;
+	}
+	if (ret & PM8607_BUCK3_DOUBLE)
+		chip->buck3_double = 1;
+
+	ret = pm860x_reg_read(i2c, PM8607_B0_MISC1);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret);
+		goto out;
+	}
+
+	if (pdata && (pdata->i2c_port == PI2C_PORT))
+		data = PM8607_B0_MISC1_PI2C;
+	else
+		data = 0;
+	ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to access MISC1:%d\n", ret);
+		goto out;
+	}
+
+	ret = device_gpadc_init(chip, pdata);
+	if (ret < 0)
+		goto out;
+
+	ret = device_irq_init(chip, pdata);
+	if (ret < 0)
+		goto out;
+
+	ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
+			      ARRAY_SIZE(regulator_devs),
+			      &regulator_resources[0], 0);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to add regulator subdev\n");
+		goto out_dev;
+	}
+
+	if (pdata && pdata->touch) {
+		ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
+				      ARRAY_SIZE(touch_devs),
+				      &touch_resources[0], 0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to add touch "
+				"subdev\n");
+			goto out_dev;
+		}
+	}
+
+	if (pdata && pdata->power) {
+		ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
+				      ARRAY_SIZE(power_devs),
+				      &power_supply_resources[0], 0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to add power supply "
+				"subdev\n");
+			goto out_dev;
+		}
+	}
+
+	ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
+			      ARRAY_SIZE(onkey_devs),
+			      &onkey_resources[0], 0);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to add onkey subdev\n");
+		goto out_dev;
+	}
+
+	return;
+out_dev:
+	mfd_remove_devices(chip->dev);
+	device_irq_exit(chip);
+out:
+	return;
+}
+
+int pm860x_device_init(struct pm860x_chip *chip,
+		       struct pm860x_platform_data *pdata)
+{
+	chip->core_irq = 0;
+
+	switch (chip->id) {
+	case CHIP_PM8606:
+		device_8606_init(chip, chip->client, pdata);
+		break;
+	case CHIP_PM8607:
+		device_8607_init(chip, chip->client, pdata);
+		break;
+	}
+
+	if (chip->companion) {
+		switch (chip->id) {
+		case CHIP_PM8607:
+			device_8606_init(chip, chip->companion, pdata);
+			break;
+		case CHIP_PM8606:
+			device_8607_init(chip, chip->companion, pdata);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+void pm860x_device_exit(struct pm860x_chip *chip)
+{
+	device_irq_exit(chip);
+	mfd_remove_devices(chip->dev);
+}
+
+MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
new file mode 100644
index 0000000..c37e12b
--- /dev/null
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -0,0 +1,236 @@
+/*
+ * I2C driver for Marvell 88PM860x
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * 	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/mfd/88pm860x.h>
+
+static inline int pm860x_read_device(struct i2c_client *i2c,
+				     int reg, int bytes, void *dest)
+{
+	unsigned char data;
+	int ret;
+
+	data = (unsigned char)reg;
+	ret = i2c_master_send(i2c, &data, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_master_recv(i2c, dest, bytes);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static inline int pm860x_write_device(struct i2c_client *i2c,
+				      int reg, int bytes, void *src)
+{
+	unsigned char buf[bytes + 1];
+	int ret;
+
+	buf[0] = (unsigned char)reg;
+	memcpy(&buf[1], src, bytes);
+
+	ret = i2c_master_send(i2c, buf, bytes + 1);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+int pm860x_reg_read(struct i2c_client *i2c, int reg)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+	unsigned char data;
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	ret = pm860x_read_device(i2c, reg, 1, &data);
+	mutex_unlock(&chip->io_lock);
+
+	if (ret < 0)
+		return ret;
+	else
+		return (int)data;
+}
+EXPORT_SYMBOL(pm860x_reg_read);
+
+int pm860x_reg_write(struct i2c_client *i2c, int reg,
+		     unsigned char data)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	ret = pm860x_write_device(i2c, reg, 1, &data);
+	mutex_unlock(&chip->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(pm860x_reg_write);
+
+int pm860x_bulk_read(struct i2c_client *i2c, int reg,
+		     int count, unsigned char *buf)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	ret = pm860x_read_device(i2c, reg, count, buf);
+	mutex_unlock(&chip->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(pm860x_bulk_read);
+
+int pm860x_bulk_write(struct i2c_client *i2c, int reg,
+		      int count, unsigned char *buf)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	ret = pm860x_write_device(i2c, reg, count, buf);
+	mutex_unlock(&chip->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(pm860x_bulk_write);
+
+int pm860x_set_bits(struct i2c_client *i2c, int reg,
+		    unsigned char mask, unsigned char data)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+	unsigned char value;
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	ret = pm860x_read_device(i2c, reg, 1, &value);
+	if (ret < 0)
+		goto out;
+	value &= ~mask;
+	value |= data;
+	ret = pm860x_write_device(i2c, reg, 1, &value);
+out:
+	mutex_unlock(&chip->io_lock);
+	return ret;
+}
+EXPORT_SYMBOL(pm860x_set_bits);
+
+
+static const struct i2c_device_id pm860x_id_table[] = {
+	{ "88PM860x", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, pm860x_id_table);
+
+static int verify_addr(struct i2c_client *i2c)
+{
+	unsigned short addr_8607[] = {0x30, 0x34};
+	unsigned short addr_8606[] = {0x10, 0x11};
+	int size, i;
+
+	if (i2c == NULL)
+		return 0;
+	size = ARRAY_SIZE(addr_8606);
+	for (i = 0; i < size; i++) {
+		if (i2c->addr == *(addr_8606 + i))
+			return CHIP_PM8606;
+	}
+	size = ARRAY_SIZE(addr_8607);
+	for (i = 0; i < size; i++) {
+		if (i2c->addr == *(addr_8607 + i))
+			return CHIP_PM8607;
+	}
+	return 0;
+}
+
+static int __devinit pm860x_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	struct pm860x_platform_data *pdata = client->dev.platform_data;
+	struct pm860x_chip *chip;
+
+	if (!pdata) {
+		pr_info("No platform data in %s!\n", __func__);
+		return -EINVAL;
+	}
+
+	chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	chip->id = verify_addr(client);
+	chip->client = client;
+	i2c_set_clientdata(client, chip);
+	chip->dev = &client->dev;
+	mutex_init(&chip->io_lock);
+	dev_set_drvdata(chip->dev, chip);
+
+	/*
+	 * Both client and companion client shares same platform driver.
+	 * Driver distinguishes them by pdata->companion_addr.
+	 * pdata->companion_addr is only assigned if companion chip exists.
+	 * At the same time, the companion_addr shouldn't equal to client
+	 * address.
+	 */
+	if (pdata->companion_addr && (pdata->companion_addr != client->addr)) {
+		chip->companion_addr = pdata->companion_addr;
+		chip->companion = i2c_new_dummy(chip->client->adapter,
+						chip->companion_addr);
+		i2c_set_clientdata(chip->companion, chip);
+	}
+
+	pm860x_device_init(chip, pdata);
+	return 0;
+}
+
+static int __devexit pm860x_remove(struct i2c_client *client)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+	pm860x_device_exit(chip);
+	i2c_unregister_device(chip->companion);
+	i2c_set_clientdata(chip->companion, NULL);
+	i2c_set_clientdata(chip->client, NULL);
+	kfree(chip);
+	return 0;
+}
+
+static struct i2c_driver pm860x_driver = {
+	.driver	= {
+		.name	= "88PM860x",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pm860x_probe,
+	.remove		= __devexit_p(pm860x_remove),
+	.id_table	= pm860x_id_table,
+};
+
+static int __init pm860x_i2c_init(void)
+{
+	int ret;
+	ret = i2c_add_driver(&pm860x_driver);
+	if (ret != 0)
+		pr_err("Failed to register 88PM860x I2C driver: %d\n", ret);
+	return ret;
+}
+subsys_initcall(pm860x_i2c_init);
+
+static void __exit pm860x_i2c_exit(void)
+{
+	i2c_del_driver(&pm860x_driver);
+}
+module_exit(pm860x_i2c_exit);
+
+MODULE_DESCRIPTION("I2C Driver for Marvell 88PM860x");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b670d10..2a5a0b7 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -9,6 +9,16 @@
 	tristate
 	default n
 
+config MFD_88PM860X
+	bool "Support Marvell 88PM8606/88PM8607"
+	depends on I2C=y && GENERIC_HARDIRQS
+	select MFD_CORE
+	help
+	  This supports for Marvell 88PM8606/88PM8607 Power Management IC.
+	  This includes the I2C driver and the core APIs _only_, you have to
+	  select individual components like voltage regulators, RTC and
+	  battery-charger under the corresponding menus.
+
 config MFD_SM501
 	tristate "Support for Silicon Motion SM501"
 	 ---help---
@@ -37,7 +47,7 @@
 
 config MFD_SH_MOBILE_SDHI
 	bool "Support for SuperH Mobile SDHI"
-	depends on SUPERH
+	depends on SUPERH || ARCH_SHMOBILE
 	select MFD_CORE
 	 ---help---
 	  This driver supports the SDHI hardware block found in many
@@ -68,6 +78,15 @@
 	  HTC Magician devices, respectively. Actual functionality is
 	  handled by the leds-pasic3 and ds1wm drivers.
 
+config HTC_I2CPLD
+	bool "HTC I2C PLD chip support"
+	depends on I2C=y && GPIOLIB
+	help
+	  If you say yes here you get support for the supposed CPLD
+	  found on omap850 HTC devices like the HTC Wizard and HTC Herald.
+	  This device provides input and output GPIOs through an I2C
+	  interface to one or more sub-chips.
+
 config UCB1400_CORE
 	tristate "Philips UCB1400 Core driver"
 	depends on AC97_BUS
@@ -184,6 +203,16 @@
 	  individual components like LCD backlight, LEDs, GPIOs and Kepad
 	  under the corresponding menus.
 
+config MFD_MAX8925
+	bool "Maxim Semiconductor MAX8925 PMIC Support"
+	depends on I2C=y && GENERIC_HARDIRQS
+	select MFD_CORE
+	help
+	  Say yes here to support for Maxim Semiconductor MAX8925. This is
+	  a Power Management IC. This driver provies common support for
+	  accessing the device, additional drivers must be enabled in order
+	  to use the functionality of the device.
+
 config MFD_WM8400
 	tristate "Support Wolfson Microelectronics WM8400"
 	select MFD_CORE
@@ -197,7 +226,7 @@
 config MFD_WM831X
 	bool "Support Wolfson Microelectronics WM831x/2x PMICs"
 	select MFD_CORE
-	depends on I2C=y
+	depends on I2C=y && GENERIC_HARDIRQS
 	help
 	  Support for the Wolfson Microelecronics WM831x and WM832x PMICs.
 	  This driver provides common support for accessing the device,
@@ -205,7 +234,8 @@
 	  functionality of the device.
 
 config MFD_WM8350
-	tristate
+	bool
+	depends on GENERIC_HARDIRQS
 
 config MFD_WM8350_CONFIG_MODE_0
 	bool
@@ -256,9 +286,9 @@
 	depends on MFD_WM8350
 
 config MFD_WM8350_I2C
-	tristate "Support Wolfson Microelectronics WM8350 with I2C"
+	bool "Support Wolfson Microelectronics WM8350 with I2C"
 	select MFD_WM8350
-	depends on I2C
+	depends on I2C=y && GENERIC_HARDIRQS
 	help
 	  The WM8350 is an integrated audio and power management
 	  subsystem with watchdog and RTC functionality for embedded
@@ -266,6 +296,18 @@
 	  I2C as the control interface.  Additional options must be
 	  selected to enable support for the functionality of the chip.
 
+config MFD_WM8994
+	tristate "Support Wolfson Microelectronics WM8994"
+	select MFD_CORE
+	depends on I2C
+	help
+	  The WM8994 is a highly integrated hi-fi CODEC designed for
+	  smartphone applicatiosn.  As well as audio functionality it
+	  has on board GPIO and regulator functionality which is
+	  supported via the relevant subsystems.  This driver provides
+	  core support for the WM8994, in order to use the actual
+	  functionaltiy of the device other drivers must be enabled.
+
 config MFD_PCF50633
 	tristate "Support for NXP PCF50633"
 	depends on I2C
@@ -300,8 +342,8 @@
 	 the PCF50633 chip.
 
 config AB3100_CORE
-	tristate "ST-Ericsson AB3100 Mixed Signal Circuit core functions"
-	depends on I2C
+	bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions"
+	depends on I2C=y
 	default y if ARCH_U300
 	help
 	  Select this to enable the AB3100 Mixed Signal IC core
@@ -329,16 +371,6 @@
 	  This enables the PCAP ASIC present on EZX Phones. This is
 	  needed for MMC, TouchScreen, Sound, USB, etc..
 
-config MFD_88PM8607
-	bool "Support Marvell 88PM8607"
-	depends on I2C=y
-	select MFD_CORE
-	help
-	  This supports for Marvell 88PM8607 Power Management IC. This includes
-	  the I2C driver and the core APIs _only_, you have to select
-	  individual components like voltage regulators, RTC and
-	  battery-charger under the corresponding menus.
-
 config AB4500_CORE
 	tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip"
 	depends on SPI
@@ -358,6 +390,15 @@
 
 	The timberdale FPGA can be found on the Intel Atom development board
 	for in-vehicle infontainment, called Russellville.
+
+config LPC_SCH
+	tristate "Intel SCH LPC"
+	depends on PCI
+	select MFD_CORE
+	help
+	  LPC bridge function of the Intel SCH provides support for
+	  System Management Bus and General Purpose I/O.
+
 endmenu
 
 menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 78295d6..22715ad 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -2,12 +2,15 @@
 # Makefile for multifunction miscellaneous devices
 #
 
+88pm860x-objs			:= 88pm860x-core.o 88pm860x-i2c.o
+obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
 obj-$(CONFIG_MFD_SH_MOBILE_SDHI)		+= sh_mobile_sdhi.o
 
 obj-$(CONFIG_HTC_EGPIO)		+= htc-egpio.o
 obj-$(CONFIG_HTC_PASIC3)	+= htc-pasic3.o
+obj-$(CONFIG_HTC_I2CPLD)	+= htc-i2cpld.o
 
 obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
 
@@ -22,6 +25,7 @@
 wm8350-objs			+= wm8350-irq.o
 obj-$(CONFIG_MFD_WM8350)	+= wm8350.o
 obj-$(CONFIG_MFD_WM8350_I2C)	+= wm8350-i2c.o
+obj-$(CONFIG_MFD_WM8994)	+= wm8994-core.o
 
 obj-$(CONFIG_TPS65010)		+= tps65010.o
 obj-$(CONFIG_MENELAUS)		+= menelaus.o
@@ -47,6 +51,8 @@
 obj-$(CONFIG_UCB1400_CORE)	+= ucb1400_core.o
 
 obj-$(CONFIG_PMIC_DA903X)	+= da903x.o
+max8925-objs			:= max8925-core.o max8925-i2c.o
+obj-$(CONFIG_MFD_MAX8925)	+= max8925.o
 
 obj-$(CONFIG_MFD_PCF50633)	+= pcf50633-core.o
 obj-$(CONFIG_PCF50633_ADC)	+= pcf50633-adc.o
@@ -55,5 +61,5 @@
 obj-$(CONFIG_AB3100_OTP)	+= ab3100-otp.o
 obj-$(CONFIG_AB4500_CORE)	+= ab4500-core.o
 obj-$(CONFIG_MFD_TIMBERDALE)    += timberdale.o
-obj-$(CONFIG_MFD_88PM8607)	+= 88pm8607.o
 obj-$(CONFIG_PMIC_ADP5520)	+= adp5520.o
+obj-$(CONFIG_LPC_SCH)		+= lpc_sch.o
\ No newline at end of file
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index fd42a80..a2ce3b6 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009 ST-Ericsson
+ * Copyright (C) 2007-2010 ST-Ericsson
  * License terms: GNU General Public License (GPL) version 2
  * Low-level core for exclusive access to the AB3100 IC on the I2C bus
  * and some basic chip-configuration.
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
+#include <linux/random.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
@@ -365,18 +366,23 @@
 }
 EXPORT_SYMBOL(ab3100_event_registers_startup_state_get);
 
-/* Interrupt handling worker */
-static void ab3100_work(struct work_struct *work)
+/*
+ * This is a threaded interrupt handler so we can make some
+ * I2C calls etc.
+ */
+static irqreturn_t ab3100_irq_handler(int irq, void *data)
 {
-	struct ab3100 *ab3100 = container_of(work, struct ab3100, work);
+	struct ab3100 *ab3100 = data;
 	u8 event_regs[3];
 	u32 fatevent;
 	int err;
 
+	add_interrupt_randomness(irq);
+
 	err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1,
 				       event_regs, 3);
 	if (err)
-		goto err_event_wq;
+		goto err_event;
 
 	fatevent = (event_regs[0] << 16) |
 		(event_regs[1] << 8) |
@@ -398,29 +404,11 @@
 	dev_dbg(ab3100->dev,
 		"IRQ Event: 0x%08x\n", fatevent);
 
-	/* By now the IRQ should be acked and deasserted so enable it again */
-	enable_irq(ab3100->i2c_client->irq);
-	return;
+	return IRQ_HANDLED;
 
- err_event_wq:
+ err_event:
 	dev_dbg(ab3100->dev,
-		"error in event workqueue\n");
-	/* Enable the IRQ anyway, what choice do we have? */
-	enable_irq(ab3100->i2c_client->irq);
-	return;
-}
-
-static irqreturn_t ab3100_irq_handler(int irq, void *data)
-{
-	struct ab3100 *ab3100 = data;
-	/*
-	 * Disable the IRQ and dispatch a worker to handle the
-	 * event. Since the chip resides on I2C this is slow
-	 * stuff and we will re-enable the interrupts once th
-	 * worker has finished.
-	 */
-	disable_irq_nosync(irq);
-	schedule_work(&ab3100->work);
+		"error reading event status\n");
 	return IRQ_HANDLED;
 }
 
@@ -735,10 +723,7 @@
 	.id		= -1,					\
 }
 
-/*
- * This lists all the subdevices and corresponding register
- * ranges.
- */
+/* This lists all the subdevices */
 AB3100_DEVICE(dac, "ab3100-dac");
 AB3100_DEVICE(leds, "ab3100-leds");
 AB3100_DEVICE(power, "ab3100-power");
@@ -904,12 +889,11 @@
 	if (err)
 		goto exit_no_setup;
 
-	INIT_WORK(&ab3100->work, ab3100_work);
-
+	err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler,
+				IRQF_ONESHOT, "ab3100-core", ab3100);
 	/* This real unpredictable IRQ is of course sampled for entropy */
-	err = request_irq(client->irq, ab3100_irq_handler,
-			  IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
-			  "AB3100 IRQ", ab3100);
+	rand_initialize_irq(client->irq);
+
 	if (err)
 		goto exit_no_irq;
 
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c
index 0499b20..b603469 100644
--- a/drivers/mfd/ab3100-otp.c
+++ b/drivers/mfd/ab3100-otp.c
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/ab3100.h>
 #include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 /* The OTP registers */
 #define AB3100_OTP0		0xb0
@@ -95,11 +96,10 @@
  * This is a simple debugfs human-readable file that dumps out
  * the contents of the OTP.
  */
-#ifdef CONFIG_DEBUGFS
-static int show_otp(struct seq_file *s, void *v)
+#ifdef CONFIG_DEBUG_FS
+static int ab3100_show_otp(struct seq_file *s, void *v)
 {
 	struct ab3100_otp *otp = s->private;
-	int err;
 
 	seq_printf(s, "OTP is %s\n", otp->locked ? "LOCKED" : "UNLOCKED");
 	seq_printf(s, "OTP clock switch startup is %uHz\n", otp->freq);
@@ -113,7 +113,7 @@
 
 static int ab3100_otp_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ab3100_otp_show, inode->i_private);
+	return single_open(file, ab3100_show_otp, inode->i_private);
 }
 
 static const struct file_operations ab3100_otp_operations = {
@@ -131,13 +131,14 @@
 					   &ab3100_otp_operations);
 	if (!otp->debugfs) {
 		dev_err(dev, "AB3100 debugfs OTP file registration failed!\n");
-		return err;
+		return -ENOENT;
 	}
+	return 0;
 }
 
 static void __exit ab3100_otp_exit_debugfs(struct ab3100_otp *otp)
 {
-	debugfs_remove_file(otp->debugfs);
+	debugfs_remove(otp->debugfs);
 }
 #else
 /* Compile this out if debugfs not selected */
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
index aa266e1..addb846 100644
--- a/drivers/mfd/htc-egpio.c
+++ b/drivers/mfd/htc-egpio.c
@@ -108,7 +108,7 @@
 	ack_irqs(ei);
 	/* Process all set pins. */
 	readval &= ei->irqs_enabled;
-	for_each_bit(irqpin, &readval, ei->nirqs) {
+	for_each_set_bit(irqpin, &readval, ei->nirqs) {
 		/* Run irq handler */
 		pr_debug("got IRQ %d\n", irqpin);
 		irq = ei->irq_start + irqpin;
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
new file mode 100644
index 0000000..37b9fda
--- /dev/null
+++ b/drivers/mfd/htc-i2cpld.c
@@ -0,0 +1,710 @@
+/*
+ *  htc-i2cpld.c
+ *  Chip driver for an unknown CPLD chip found on omap850 HTC devices like
+ *  the HTC Wizard and HTC Herald.
+ *  The cpld is located on the i2c bus and acts as an input/output GPIO
+ *  extender.
+ *
+ *  Copyright (C) 2009 Cory Maccarrone <darkstar6262@gmail.com>
+ *
+ *  Based on work done in the linwizard project
+ *  Copyright (C) 2008-2009 Angelo Arrifano <miknix@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <linux/htcpld.h>
+#include <linux/gpio.h>
+
+struct htcpld_chip {
+	spinlock_t              lock;
+
+	/* chip info */
+	u8                      reset;
+	u8                      addr;
+	struct device           *dev;
+	struct i2c_client	*client;
+
+	/* Output details */
+	u8                      cache_out;
+	struct gpio_chip        chip_out;
+
+	/* Input details */
+	u8                      cache_in;
+	struct gpio_chip        chip_in;
+
+	u16                     irqs_enabled;
+	uint                    irq_start;
+	int                     nirqs;
+
+	/*
+	 * Work structure to allow for setting values outside of any
+	 * possible interrupt context
+	 */
+	struct work_struct set_val_work;
+};
+
+struct htcpld_data {
+	/* irq info */
+	u16                irqs_enabled;
+	uint               irq_start;
+	int                nirqs;
+	uint               chained_irq;
+	unsigned int       int_reset_gpio_hi;
+	unsigned int       int_reset_gpio_lo;
+
+	/* htcpld info */
+	struct htcpld_chip *chip;
+	unsigned int       nchips;
+};
+
+/* There does not appear to be a way to proactively mask interrupts
+ * on the htcpld chip itself.  So, we simply ignore interrupts that
+ * aren't desired. */
+static void htcpld_mask(unsigned int irq)
+{
+	struct htcpld_chip *chip = get_irq_chip_data(irq);
+	chip->irqs_enabled &= ~(1 << (irq - chip->irq_start));
+	pr_debug("HTCPLD mask %d %04x\n", irq, chip->irqs_enabled);
+}
+static void htcpld_unmask(unsigned int irq)
+{
+	struct htcpld_chip *chip = get_irq_chip_data(irq);
+	chip->irqs_enabled |= 1 << (irq - chip->irq_start);
+	pr_debug("HTCPLD unmask %d %04x\n", irq, chip->irqs_enabled);
+}
+
+static int htcpld_set_type(unsigned int irq, unsigned int flags)
+{
+	struct irq_desc *d = irq_to_desc(irq);
+
+	if (!d) {
+		pr_err("HTCPLD invalid IRQ: %d\n", irq);
+		return -EINVAL;
+	}
+
+	if (flags & ~IRQ_TYPE_SENSE_MASK)
+		return -EINVAL;
+
+	/* We only allow edge triggering */
+	if (flags & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))
+		return -EINVAL;
+
+	d->status &= ~IRQ_TYPE_SENSE_MASK;
+	d->status |= flags;
+
+	return 0;
+}
+
+static struct irq_chip htcpld_muxed_chip = {
+	.name     = "htcpld",
+	.mask     = htcpld_mask,
+	.unmask   = htcpld_unmask,
+	.set_type = htcpld_set_type,
+};
+
+/* To properly dispatch IRQ events, we need to read from the
+ * chip.  This is an I2C action that could possibly sleep
+ * (which is bad in interrupt context) -- so we use a threaded
+ * interrupt handler to get around that.
+ */
+static irqreturn_t htcpld_handler(int irq, void *dev)
+{
+	struct htcpld_data *htcpld = dev;
+	unsigned int i;
+	unsigned long flags;
+	int irqpin;
+	struct irq_desc *desc;
+
+	if (!htcpld) {
+		pr_debug("htcpld is null in ISR\n");
+		return IRQ_HANDLED;
+	}
+
+	/*
+	 * For each chip, do a read of the chip and trigger any interrupts
+	 * desired.  The interrupts will be triggered from LSB to MSB (i.e.
+	 * bit 0 first, then bit 1, etc.)
+	 *
+	 * For chips that have no interrupt range specified, just skip 'em.
+	 */
+	for (i = 0; i < htcpld->nchips; i++) {
+		struct htcpld_chip *chip = &htcpld->chip[i];
+		struct i2c_client *client;
+		int val;
+		unsigned long uval, old_val;
+
+		if (!chip) {
+			pr_debug("chip %d is null in ISR\n", i);
+			continue;
+		}
+
+		if (chip->nirqs == 0)
+			continue;
+
+		client = chip->client;
+		if (!client) {
+			pr_debug("client %d is null in ISR\n", i);
+			continue;
+		}
+
+		/* Scan the chip */
+		val = i2c_smbus_read_byte_data(client, chip->cache_out);
+		if (val < 0) {
+			/* Throw a warning and skip this chip */
+			dev_warn(chip->dev, "Unable to read from chip: %d\n",
+				 val);
+			continue;
+		}
+
+		uval = (unsigned long)val;
+
+		spin_lock_irqsave(&chip->lock, flags);
+
+		/* Save away the old value so we can compare it */
+		old_val = chip->cache_in;
+
+		/* Write the new value */
+		chip->cache_in = uval;
+
+		spin_unlock_irqrestore(&chip->lock, flags);
+
+		/*
+		 * For each bit in the data (starting at bit 0), trigger
+		 * associated interrupts.
+		 */
+		for (irqpin = 0; irqpin < chip->nirqs; irqpin++) {
+			unsigned oldb, newb;
+			int flags;
+
+			irq = chip->irq_start + irqpin;
+			desc = irq_to_desc(irq);
+			flags = desc->status;
+
+			/* Run the IRQ handler, but only if the bit value
+			 * changed, and the proper flags are set */
+			oldb = (old_val >> irqpin) & 1;
+			newb = (uval >> irqpin) & 1;
+
+			if ((!oldb && newb && (flags & IRQ_TYPE_EDGE_RISING)) ||
+			    (oldb && !newb &&
+			     (flags & IRQ_TYPE_EDGE_FALLING))) {
+				pr_debug("fire IRQ %d\n", irqpin);
+				desc->handle_irq(irq, desc);
+			}
+		}
+	}
+
+	/*
+	 * In order to continue receiving interrupts, the int_reset_gpio must
+	 * be asserted.
+	 */
+	if (htcpld->int_reset_gpio_hi)
+		gpio_set_value(htcpld->int_reset_gpio_hi, 1);
+	if (htcpld->int_reset_gpio_lo)
+		gpio_set_value(htcpld->int_reset_gpio_lo, 0);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * The GPIO set routines can be called from interrupt context, especially if,
+ * for example they're attached to the led-gpio framework and a trigger is
+ * enabled.  As such, we declared work above in the htcpld_chip structure,
+ * and that work is scheduled in the set routine.  The kernel can then run
+ * the I2C functions, which will sleep, in process context.
+ */
+void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct i2c_client *client;
+	struct htcpld_chip *chip_data;
+	unsigned long flags;
+
+	chip_data = container_of(chip, struct htcpld_chip, chip_out);
+	if (!chip_data)
+		return;
+
+	client = chip_data->client;
+	if (client == NULL)
+		return;
+
+	spin_lock_irqsave(&chip_data->lock, flags);
+	if (val)
+		chip_data->cache_out |= (1 << offset);
+	else
+		chip_data->cache_out &= ~(1 << offset);
+	spin_unlock_irqrestore(&chip_data->lock, flags);
+
+	schedule_work(&(chip_data->set_val_work));
+}
+
+void htcpld_chip_set_ni(struct work_struct *work)
+{
+	struct htcpld_chip *chip_data;
+	struct i2c_client *client;
+
+	chip_data = container_of(work, struct htcpld_chip, set_val_work);
+	client = chip_data->client;
+	i2c_smbus_read_byte_data(client, chip_data->cache_out);
+}
+
+int htcpld_chip_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct htcpld_chip *chip_data;
+	int val = 0;
+	int is_input = 0;
+
+	/* Try out first */
+	chip_data = container_of(chip, struct htcpld_chip, chip_out);
+	if (!chip_data) {
+		/* Try in */
+		is_input = 1;
+		chip_data = container_of(chip, struct htcpld_chip, chip_in);
+		if (!chip_data)
+			return -EINVAL;
+	}
+
+	/* Determine if this is an input or output GPIO */
+	if (!is_input)
+		/* Use the output cache */
+		val = (chip_data->cache_out >> offset) & 1;
+	else
+		/* Use the input cache */
+		val = (chip_data->cache_in >> offset) & 1;
+
+	if (val)
+		return 1;
+	else
+		return 0;
+}
+
+static int htcpld_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	htcpld_chip_set(chip, offset, value);
+	return 0;
+}
+
+static int htcpld_direction_input(struct gpio_chip *chip,
+					unsigned offset)
+{
+	/*
+	 * No-op: this function can only be called on the input chip.
+	 * We do however make sure the offset is within range.
+	 */
+	return (offset < chip->ngpio) ? 0 : -EINVAL;
+}
+
+int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct htcpld_chip *chip_data;
+
+	chip_data = container_of(chip, struct htcpld_chip, chip_in);
+
+	if (offset < chip_data->nirqs)
+		return chip_data->irq_start + offset;
+	else
+		return -EINVAL;
+}
+
+void htcpld_chip_reset(struct i2c_client *client)
+{
+	struct htcpld_chip *chip_data = i2c_get_clientdata(client);
+	if (!chip_data)
+		return;
+
+	i2c_smbus_read_byte_data(
+		client, (chip_data->cache_out = chip_data->reset));
+}
+
+static int __devinit htcpld_setup_chip_irq(
+		struct platform_device *pdev,
+		int chip_index)
+{
+	struct htcpld_data *htcpld;
+	struct device *dev = &pdev->dev;
+	struct htcpld_core_platform_data *pdata;
+	struct htcpld_chip *chip;
+	struct htcpld_chip_platform_data *plat_chip_data;
+	unsigned int irq, irq_end;
+	int ret = 0;
+
+	/* Get the platform and driver data */
+	pdata = dev->platform_data;
+	htcpld = platform_get_drvdata(pdev);
+	chip = &htcpld->chip[chip_index];
+	plat_chip_data = &pdata->chip[chip_index];
+
+	/* Setup irq handlers */
+	irq_end = chip->irq_start + chip->nirqs;
+	for (irq = chip->irq_start; irq < irq_end; irq++) {
+		set_irq_chip(irq, &htcpld_muxed_chip);
+		set_irq_chip_data(irq, chip);
+		set_irq_handler(irq, handle_simple_irq);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+#else
+		set_irq_probe(irq);
+#endif
+	}
+
+	return ret;
+}
+
+static int __devinit htcpld_register_chip_i2c(
+		struct platform_device *pdev,
+		int chip_index)
+{
+	struct htcpld_data *htcpld;
+	struct device *dev = &pdev->dev;
+	struct htcpld_core_platform_data *pdata;
+	struct htcpld_chip *chip;
+	struct htcpld_chip_platform_data *plat_chip_data;
+	struct i2c_adapter *adapter;
+	struct i2c_client *client;
+	struct i2c_board_info info;
+
+	/* Get the platform and driver data */
+	pdata = dev->platform_data;
+	htcpld = platform_get_drvdata(pdev);
+	chip = &htcpld->chip[chip_index];
+	plat_chip_data = &pdata->chip[chip_index];
+
+	adapter = i2c_get_adapter(pdata->i2c_adapter_id);
+	if (adapter == NULL) {
+		/* Eek, no such I2C adapter!  Bail out. */
+		dev_warn(dev, "Chip at i2c address 0x%x: Invalid i2c adapter %d\n",
+			 plat_chip_data->addr, pdata->i2c_adapter_id);
+		return -ENODEV;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
+		dev_warn(dev, "i2c adapter %d non-functional\n",
+			 pdata->i2c_adapter_id);
+		return -EINVAL;
+	}
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	info.addr = plat_chip_data->addr;
+	strlcpy(info.type, "htcpld-chip", I2C_NAME_SIZE);
+	info.platform_data = chip;
+
+	/* Add the I2C device.  This calls the probe() function. */
+	client = i2c_new_device(adapter, &info);
+	if (!client) {
+		/* I2C device registration failed, contineu with the next */
+		dev_warn(dev, "Unable to add I2C device for 0x%x\n",
+			 plat_chip_data->addr);
+		return -ENODEV;
+	}
+
+	i2c_set_clientdata(client, chip);
+	snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%d", client->addr);
+	chip->client = client;
+
+	/* Reset the chip */
+	htcpld_chip_reset(client);
+	chip->cache_in = i2c_smbus_read_byte_data(client, chip->cache_out);
+
+	return 0;
+}
+
+static void __devinit htcpld_unregister_chip_i2c(
+		struct platform_device *pdev,
+		int chip_index)
+{
+	struct htcpld_data *htcpld;
+	struct htcpld_chip *chip;
+
+	/* Get the platform and driver data */
+	htcpld = platform_get_drvdata(pdev);
+	chip = &htcpld->chip[chip_index];
+
+	if (chip->client)
+		i2c_unregister_device(chip->client);
+}
+
+static int __devinit htcpld_register_chip_gpio(
+		struct platform_device *pdev,
+		int chip_index)
+{
+	struct htcpld_data *htcpld;
+	struct device *dev = &pdev->dev;
+	struct htcpld_core_platform_data *pdata;
+	struct htcpld_chip *chip;
+	struct htcpld_chip_platform_data *plat_chip_data;
+	struct gpio_chip *gpio_chip;
+	int ret = 0;
+
+	/* Get the platform and driver data */
+	pdata = dev->platform_data;
+	htcpld = platform_get_drvdata(pdev);
+	chip = &htcpld->chip[chip_index];
+	plat_chip_data = &pdata->chip[chip_index];
+
+	/* Setup the GPIO chips */
+	gpio_chip = &(chip->chip_out);
+	gpio_chip->label           = "htcpld-out";
+	gpio_chip->dev             = dev;
+	gpio_chip->owner           = THIS_MODULE;
+	gpio_chip->get             = htcpld_chip_get;
+	gpio_chip->set             = htcpld_chip_set;
+	gpio_chip->direction_input = NULL;
+	gpio_chip->direction_output = htcpld_direction_output;
+	gpio_chip->base            = plat_chip_data->gpio_out_base;
+	gpio_chip->ngpio           = plat_chip_data->num_gpios;
+
+	gpio_chip = &(chip->chip_in);
+	gpio_chip->label           = "htcpld-in";
+	gpio_chip->dev             = dev;
+	gpio_chip->owner           = THIS_MODULE;
+	gpio_chip->get             = htcpld_chip_get;
+	gpio_chip->set             = NULL;
+	gpio_chip->direction_input = htcpld_direction_input;
+	gpio_chip->direction_output = NULL;
+	gpio_chip->to_irq          = htcpld_chip_to_irq;
+	gpio_chip->base            = plat_chip_data->gpio_in_base;
+	gpio_chip->ngpio           = plat_chip_data->num_gpios;
+
+	/* Add the GPIO chips */
+	ret = gpiochip_add(&(chip->chip_out));
+	if (ret) {
+		dev_warn(dev, "Unable to register output GPIOs for 0x%x: %d\n",
+			 plat_chip_data->addr, ret);
+		return ret;
+	}
+
+	ret = gpiochip_add(&(chip->chip_in));
+	if (ret) {
+		int error;
+
+		dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n",
+			 plat_chip_data->addr, ret);
+
+		error = gpiochip_remove(&(chip->chip_out));
+		if (error)
+			dev_warn(dev, "Error while trying to unregister gpio chip: %d\n", error);
+
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __devinit htcpld_setup_chips(struct platform_device *pdev)
+{
+	struct htcpld_data *htcpld;
+	struct device *dev = &pdev->dev;
+	struct htcpld_core_platform_data *pdata;
+	int i;
+
+	/* Get the platform and driver data */
+	pdata = dev->platform_data;
+	htcpld = platform_get_drvdata(pdev);
+
+	/* Setup each chip's output GPIOs */
+	htcpld->nchips = pdata->num_chip;
+	htcpld->chip = kzalloc(sizeof(struct htcpld_chip) * htcpld->nchips,
+			       GFP_KERNEL);
+	if (!htcpld->chip) {
+		dev_warn(dev, "Unable to allocate memory for chips\n");
+		return -ENOMEM;
+	}
+
+	/* Add the chips as best we can */
+	for (i = 0; i < htcpld->nchips; i++) {
+		int ret;
+
+		/* Setup the HTCPLD chips */
+		htcpld->chip[i].reset = pdata->chip[i].reset;
+		htcpld->chip[i].cache_out = pdata->chip[i].reset;
+		htcpld->chip[i].cache_in = 0;
+		htcpld->chip[i].dev = dev;
+		htcpld->chip[i].irq_start = pdata->chip[i].irq_base;
+		htcpld->chip[i].nirqs = pdata->chip[i].num_irqs;
+
+		INIT_WORK(&(htcpld->chip[i].set_val_work), &htcpld_chip_set_ni);
+		spin_lock_init(&(htcpld->chip[i].lock));
+
+		/* Setup the interrupts for the chip */
+		if (htcpld->chained_irq) {
+			ret = htcpld_setup_chip_irq(pdev, i);
+			if (ret)
+				continue;
+		}
+
+		/* Register the chip with I2C */
+		ret = htcpld_register_chip_i2c(pdev, i);
+		if (ret)
+			continue;
+
+
+		/* Register the chips with the GPIO subsystem */
+		ret = htcpld_register_chip_gpio(pdev, i);
+		if (ret) {
+			/* Unregister the chip from i2c and continue */
+			htcpld_unregister_chip_i2c(pdev, i);
+			continue;
+		}
+
+		dev_info(dev, "Registered chip at 0x%x\n", pdata->chip[i].addr);
+	}
+
+	return 0;
+}
+
+static int __devinit htcpld_core_probe(struct platform_device *pdev)
+{
+	struct htcpld_data *htcpld;
+	struct device *dev = &pdev->dev;
+	struct htcpld_core_platform_data *pdata;
+	struct resource *res;
+	int ret = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	pdata = dev->platform_data;
+	if (!pdata) {
+		dev_warn(dev, "Platform data not found for htcpld core!\n");
+		return -ENXIO;
+	}
+
+	htcpld = kzalloc(sizeof(struct htcpld_data), GFP_KERNEL);
+	if (!htcpld)
+		return -ENOMEM;
+
+	/* Find chained irq */
+	ret = -EINVAL;
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res) {
+		int flags;
+		htcpld->chained_irq = res->start;
+
+		/* Setup the chained interrupt handler */
+		flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
+		ret = request_threaded_irq(htcpld->chained_irq,
+					   NULL, htcpld_handler,
+					   flags, pdev->name, htcpld);
+		if (ret) {
+			dev_warn(dev, "Unable to setup chained irq handler: %d\n", ret);
+			goto fail;
+		} else
+			device_init_wakeup(dev, 0);
+	}
+
+	/* Set the driver data */
+	platform_set_drvdata(pdev, htcpld);
+
+	/* Setup the htcpld chips */
+	ret = htcpld_setup_chips(pdev);
+	if (ret)
+		goto fail;
+
+	/* Request the GPIO(s) for the int reset and set them up */
+	if (pdata->int_reset_gpio_hi) {
+		ret = gpio_request(pdata->int_reset_gpio_hi, "htcpld-core");
+		if (ret) {
+			/*
+			 * If it failed, that sucks, but we can probably
+			 * continue on without it.
+			 */
+			dev_warn(dev, "Unable to request int_reset_gpio_hi -- interrupts may not work\n");
+			htcpld->int_reset_gpio_hi = 0;
+		} else {
+			htcpld->int_reset_gpio_hi = pdata->int_reset_gpio_hi;
+			gpio_set_value(htcpld->int_reset_gpio_hi, 1);
+		}
+	}
+
+	if (pdata->int_reset_gpio_lo) {
+		ret = gpio_request(pdata->int_reset_gpio_lo, "htcpld-core");
+		if (ret) {
+			/*
+			 * If it failed, that sucks, but we can probably
+			 * continue on without it.
+			 */
+			dev_warn(dev, "Unable to request int_reset_gpio_lo -- interrupts may not work\n");
+			htcpld->int_reset_gpio_lo = 0;
+		} else {
+			htcpld->int_reset_gpio_lo = pdata->int_reset_gpio_lo;
+			gpio_set_value(htcpld->int_reset_gpio_lo, 0);
+		}
+	}
+
+	dev_info(dev, "Initialized successfully\n");
+	return 0;
+
+fail:
+	kfree(htcpld);
+	return ret;
+}
+
+/* The I2C Driver -- used internally */
+static const struct i2c_device_id htcpld_chip_id[] = {
+	{ "htcpld-chip", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, htcpld_chip_id);
+
+
+static struct i2c_driver htcpld_chip_driver = {
+	.driver = {
+		.name	= "htcpld-chip",
+	},
+	.id_table = htcpld_chip_id,
+};
+
+/* The Core Driver */
+static struct platform_driver htcpld_core_driver = {
+	.driver = {
+		.name = "i2c-htcpld",
+	},
+};
+
+static int __init htcpld_core_init(void)
+{
+	int ret;
+
+	/* Register the I2C Chip driver */
+	ret = i2c_add_driver(&htcpld_chip_driver);
+	if (ret)
+		return ret;
+
+	/* Probe for our chips */
+	return platform_driver_probe(&htcpld_core_driver, htcpld_core_probe);
+}
+
+static void __exit htcpld_core_exit(void)
+{
+	i2c_del_driver(&htcpld_chip_driver);
+	platform_driver_unregister(&htcpld_core_driver);
+}
+
+module_init(htcpld_core_init);
+module_exit(htcpld_core_exit);
+
+MODULE_AUTHOR("Cory Maccarrone <darkstar6262@gmail.com>");
+MODULE_DESCRIPTION("I2C HTC PLD Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
new file mode 100644
index 0000000..51b2f60
--- /dev/null
+++ b/drivers/mfd/lpc_sch.c
@@ -0,0 +1,133 @@
+/*
+ *  lpc_sch.c - LPC interface for Intel Poulsbo SCH
+ *
+ *  LPC bridge function of the Intel SCH contains many other
+ *  functional units, such as Interrupt controllers, Timers,
+ *  Power Management, System Management, GPIO, RTC, and LPC
+ *  Configuration Registers.
+ *
+ *  Copyright (c) 2010 CompuLab Ltd
+ *  Author: Denis Turischev <denis@compulab.co.il>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License 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; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/acpi.h>
+#include <linux/pci.h>
+#include <linux/mfd/core.h>
+
+#define SMBASE		0x40
+#define SMBUS_IO_SIZE	64
+
+#define GPIOBASE	0x44
+#define GPIO_IO_SIZE	64
+
+static struct resource smbus_sch_resource = {
+		.flags = IORESOURCE_IO,
+};
+
+
+static struct resource gpio_sch_resource = {
+		.flags = IORESOURCE_IO,
+};
+
+static struct mfd_cell lpc_sch_cells[] = {
+	{
+		.name = "isch_smbus",
+		.num_resources = 1,
+		.resources = &smbus_sch_resource,
+	},
+	{
+		.name = "sch_gpio",
+		.num_resources = 1,
+		.resources = &gpio_sch_resource,
+	},
+};
+
+static struct pci_device_id lpc_sch_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
+
+static int __devinit lpc_sch_probe(struct pci_dev *dev,
+				const struct pci_device_id *id)
+{
+	unsigned int base_addr_cfg;
+	unsigned short base_addr;
+
+	pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
+	if (!(base_addr_cfg & (1 << 31))) {
+		dev_err(&dev->dev, "Decode of the SMBus I/O range disabled\n");
+		return -ENODEV;
+	}
+	base_addr = (unsigned short)base_addr_cfg;
+	if (base_addr == 0) {
+		dev_err(&dev->dev, "I/O space for SMBus uninitialized\n");
+		return -ENODEV;
+	}
+
+	smbus_sch_resource.start = base_addr;
+	smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1;
+
+	pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg);
+	if (!(base_addr_cfg & (1 << 31))) {
+		dev_err(&dev->dev, "Decode of the GPIO I/O range disabled\n");
+		return -ENODEV;
+	}
+	base_addr = (unsigned short)base_addr_cfg;
+	if (base_addr == 0) {
+		dev_err(&dev->dev, "I/O space for GPIO uninitialized\n");
+		return -ENODEV;
+	}
+
+	gpio_sch_resource.start = base_addr;
+	gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1;
+
+	return mfd_add_devices(&dev->dev, -1,
+			lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0);
+}
+
+static void __devexit lpc_sch_remove(struct pci_dev *dev)
+{
+	mfd_remove_devices(&dev->dev);
+}
+
+static struct pci_driver lpc_sch_driver = {
+	.name		= "lpc_sch",
+	.id_table	= lpc_sch_ids,
+	.probe		= lpc_sch_probe,
+	.remove		= __devexit_p(lpc_sch_remove),
+};
+
+static int __init lpc_sch_init(void)
+{
+	return pci_register_driver(&lpc_sch_driver);
+}
+
+static void __exit lpc_sch_exit(void)
+{
+	pci_unregister_driver(&lpc_sch_driver);
+}
+
+module_init(lpc_sch_init);
+module_exit(lpc_sch_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("LPC interface for Intel Poulsbo SCH");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
new file mode 100644
index 0000000..85d63c0
--- /dev/null
+++ b/drivers/mfd/max8925-core.c
@@ -0,0 +1,656 @@
+/*
+ * Base driver for Maxim MAX8925
+ *
+ * Copyright (C) 2009-2010 Marvell International Ltd.
+ *	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max8925.h>
+
+static struct resource backlight_resources[] = {
+	{
+		.name	= "max8925-backlight",
+		.start	= MAX8925_WLED_MODE_CNTL,
+		.end	= MAX8925_WLED_CNTL,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static struct mfd_cell backlight_devs[] = {
+	{
+		.name		= "max8925-backlight",
+		.num_resources	= 1,
+		.resources	= &backlight_resources[0],
+		.id		= -1,
+	},
+};
+
+static struct resource touch_resources[] = {
+	{
+		.name	= "max8925-tsc",
+		.start	= MAX8925_TSC_IRQ,
+		.end	= MAX8925_ADC_RES_END,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static struct mfd_cell touch_devs[] = {
+	{
+		.name		= "max8925-touch",
+		.num_resources	= 1,
+		.resources	= &touch_resources[0],
+		.id		= -1,
+	},
+};
+
+static struct resource power_supply_resources[] = {
+	{
+		.name	= "max8925-power",
+		.start	= MAX8925_CHG_IRQ1,
+		.end	= MAX8925_CHG_IRQ1_MASK,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static struct mfd_cell power_devs[] = {
+	{
+		.name		= "max8925-power",
+		.num_resources	= 1,
+		.resources	= &power_supply_resources[0],
+		.id		= -1,
+	},
+};
+
+static struct resource rtc_resources[] = {
+	{
+		.name	= "max8925-rtc",
+		.start	= MAX8925_RTC_IRQ,
+		.end	= MAX8925_RTC_IRQ_MASK,
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static struct mfd_cell rtc_devs[] = {
+	{
+		.name		= "max8925-rtc",
+		.num_resources	= 1,
+		.resources	= &rtc_resources[0],
+		.id		= -1,
+	},
+};
+
+#define MAX8925_REG_RESOURCE(_start, _end)	\
+{						\
+	.start	= MAX8925_##_start,		\
+	.end	= MAX8925_##_end,		\
+	.flags	= IORESOURCE_IO,		\
+}
+
+static struct resource regulator_resources[] = {
+	MAX8925_REG_RESOURCE(SDCTL1, SDCTL1),
+	MAX8925_REG_RESOURCE(SDCTL2, SDCTL2),
+	MAX8925_REG_RESOURCE(SDCTL3, SDCTL3),
+	MAX8925_REG_RESOURCE(LDOCTL1, LDOCTL1),
+	MAX8925_REG_RESOURCE(LDOCTL2, LDOCTL2),
+	MAX8925_REG_RESOURCE(LDOCTL3, LDOCTL3),
+	MAX8925_REG_RESOURCE(LDOCTL4, LDOCTL4),
+	MAX8925_REG_RESOURCE(LDOCTL5, LDOCTL5),
+	MAX8925_REG_RESOURCE(LDOCTL6, LDOCTL6),
+	MAX8925_REG_RESOURCE(LDOCTL7, LDOCTL7),
+	MAX8925_REG_RESOURCE(LDOCTL8, LDOCTL8),
+	MAX8925_REG_RESOURCE(LDOCTL9, LDOCTL9),
+	MAX8925_REG_RESOURCE(LDOCTL10, LDOCTL10),
+	MAX8925_REG_RESOURCE(LDOCTL11, LDOCTL11),
+	MAX8925_REG_RESOURCE(LDOCTL12, LDOCTL12),
+	MAX8925_REG_RESOURCE(LDOCTL13, LDOCTL13),
+	MAX8925_REG_RESOURCE(LDOCTL14, LDOCTL14),
+	MAX8925_REG_RESOURCE(LDOCTL15, LDOCTL15),
+	MAX8925_REG_RESOURCE(LDOCTL16, LDOCTL16),
+	MAX8925_REG_RESOURCE(LDOCTL17, LDOCTL17),
+	MAX8925_REG_RESOURCE(LDOCTL18, LDOCTL18),
+	MAX8925_REG_RESOURCE(LDOCTL19, LDOCTL19),
+	MAX8925_REG_RESOURCE(LDOCTL20, LDOCTL20),
+};
+
+#define MAX8925_REG_DEVS(_id)						\
+{									\
+	.name		= "max8925-regulator",				\
+	.num_resources	= 1,						\
+	.resources	= &regulator_resources[MAX8925_ID_##_id],	\
+	.id		= MAX8925_ID_##_id,				\
+}
+
+static struct mfd_cell regulator_devs[] = {
+	MAX8925_REG_DEVS(SD1),
+	MAX8925_REG_DEVS(SD2),
+	MAX8925_REG_DEVS(SD3),
+	MAX8925_REG_DEVS(LDO1),
+	MAX8925_REG_DEVS(LDO2),
+	MAX8925_REG_DEVS(LDO3),
+	MAX8925_REG_DEVS(LDO4),
+	MAX8925_REG_DEVS(LDO5),
+	MAX8925_REG_DEVS(LDO6),
+	MAX8925_REG_DEVS(LDO7),
+	MAX8925_REG_DEVS(LDO8),
+	MAX8925_REG_DEVS(LDO9),
+	MAX8925_REG_DEVS(LDO10),
+	MAX8925_REG_DEVS(LDO11),
+	MAX8925_REG_DEVS(LDO12),
+	MAX8925_REG_DEVS(LDO13),
+	MAX8925_REG_DEVS(LDO14),
+	MAX8925_REG_DEVS(LDO15),
+	MAX8925_REG_DEVS(LDO16),
+	MAX8925_REG_DEVS(LDO17),
+	MAX8925_REG_DEVS(LDO18),
+	MAX8925_REG_DEVS(LDO19),
+	MAX8925_REG_DEVS(LDO20),
+};
+
+enum {
+	FLAGS_ADC = 1,	/* register in ADC component */
+	FLAGS_RTC,	/* register in RTC component */
+};
+
+struct max8925_irq_data {
+	int	reg;
+	int	mask_reg;
+	int	enable;		/* enable or not */
+	int	offs;		/* bit offset in mask register */
+	int	flags;
+	int	tsc_irq;
+};
+
+static struct max8925_irq_data max8925_irqs[] = {
+	[MAX8925_IRQ_VCHG_DC_OVP] = {
+		.reg		= MAX8925_CHG_IRQ1,
+		.mask_reg	= MAX8925_CHG_IRQ1_MASK,
+		.offs		= 1 << 0,
+	},
+	[MAX8925_IRQ_VCHG_DC_F] = {
+		.reg		= MAX8925_CHG_IRQ1,
+		.mask_reg	= MAX8925_CHG_IRQ1_MASK,
+		.offs		= 1 << 1,
+	},
+	[MAX8925_IRQ_VCHG_DC_R] = {
+		.reg		= MAX8925_CHG_IRQ1,
+		.mask_reg	= MAX8925_CHG_IRQ1_MASK,
+		.offs		= 1 << 2,
+	},
+	[MAX8925_IRQ_VCHG_USB_OVP] = {
+		.reg		= MAX8925_CHG_IRQ1,
+		.mask_reg	= MAX8925_CHG_IRQ1_MASK,
+		.offs		= 1 << 3,
+	},
+	[MAX8925_IRQ_VCHG_USB_F] =  {
+		.reg		= MAX8925_CHG_IRQ1,
+		.mask_reg	= MAX8925_CHG_IRQ1_MASK,
+		.offs		= 1 << 4,
+	},
+	[MAX8925_IRQ_VCHG_USB_R] = {
+		.reg		= MAX8925_CHG_IRQ1,
+		.mask_reg	= MAX8925_CHG_IRQ1_MASK,
+		.offs		= 1 << 5,
+	},
+	[MAX8925_IRQ_VCHG_THM_OK_R] = {
+		.reg		= MAX8925_CHG_IRQ2,
+		.mask_reg	= MAX8925_CHG_IRQ2_MASK,
+		.offs		= 1 << 0,
+	},
+	[MAX8925_IRQ_VCHG_THM_OK_F] = {
+		.reg		= MAX8925_CHG_IRQ2,
+		.mask_reg	= MAX8925_CHG_IRQ2_MASK,
+		.offs		= 1 << 1,
+	},
+	[MAX8925_IRQ_VCHG_SYSLOW_F] = {
+		.reg		= MAX8925_CHG_IRQ2,
+		.mask_reg	= MAX8925_CHG_IRQ2_MASK,
+		.offs		= 1 << 2,
+	},
+	[MAX8925_IRQ_VCHG_SYSLOW_R] = {
+		.reg		= MAX8925_CHG_IRQ2,
+		.mask_reg	= MAX8925_CHG_IRQ2_MASK,
+		.offs		= 1 << 3,
+	},
+	[MAX8925_IRQ_VCHG_RST] = {
+		.reg		= MAX8925_CHG_IRQ2,
+		.mask_reg	= MAX8925_CHG_IRQ2_MASK,
+		.offs		= 1 << 4,
+	},
+	[MAX8925_IRQ_VCHG_DONE] = {
+		.reg		= MAX8925_CHG_IRQ2,
+		.mask_reg	= MAX8925_CHG_IRQ2_MASK,
+		.offs		= 1 << 5,
+	},
+	[MAX8925_IRQ_VCHG_TOPOFF] = {
+		.reg		= MAX8925_CHG_IRQ2,
+		.mask_reg	= MAX8925_CHG_IRQ2_MASK,
+		.offs		= 1 << 6,
+	},
+	[MAX8925_IRQ_VCHG_TMR_FAULT] = {
+		.reg		= MAX8925_CHG_IRQ2,
+		.mask_reg	= MAX8925_CHG_IRQ2_MASK,
+		.offs		= 1 << 7,
+	},
+	[MAX8925_IRQ_GPM_RSTIN] = {
+		.reg		= MAX8925_ON_OFF_IRQ1,
+		.mask_reg	= MAX8925_ON_OFF_IRQ1_MASK,
+		.offs		= 1 << 0,
+	},
+	[MAX8925_IRQ_GPM_MPL] = {
+		.reg		= MAX8925_ON_OFF_IRQ1,
+		.mask_reg	= MAX8925_ON_OFF_IRQ1_MASK,
+		.offs		= 1 << 1,
+	},
+	[MAX8925_IRQ_GPM_SW_3SEC] = {
+		.reg		= MAX8925_ON_OFF_IRQ1,
+		.mask_reg	= MAX8925_ON_OFF_IRQ1_MASK,
+		.offs		= 1 << 2,
+	},
+	[MAX8925_IRQ_GPM_EXTON_F] = {
+		.reg		= MAX8925_ON_OFF_IRQ1,
+		.mask_reg	= MAX8925_ON_OFF_IRQ1_MASK,
+		.offs		= 1 << 3,
+	},
+	[MAX8925_IRQ_GPM_EXTON_R] = {
+		.reg		= MAX8925_ON_OFF_IRQ1,
+		.mask_reg	= MAX8925_ON_OFF_IRQ1_MASK,
+		.offs		= 1 << 4,
+	},
+	[MAX8925_IRQ_GPM_SW_1SEC] = {
+		.reg		= MAX8925_ON_OFF_IRQ1,
+		.mask_reg	= MAX8925_ON_OFF_IRQ1_MASK,
+		.offs		= 1 << 5,
+	},
+	[MAX8925_IRQ_GPM_SW_F] = {
+		.reg		= MAX8925_ON_OFF_IRQ1,
+		.mask_reg	= MAX8925_ON_OFF_IRQ1_MASK,
+		.offs		= 1 << 6,
+	},
+	[MAX8925_IRQ_GPM_SW_R] = {
+		.reg		= MAX8925_ON_OFF_IRQ1,
+		.mask_reg	= MAX8925_ON_OFF_IRQ1_MASK,
+		.offs		= 1 << 7,
+	},
+	[MAX8925_IRQ_GPM_SYSCKEN_F] = {
+		.reg		= MAX8925_ON_OFF_IRQ2,
+		.mask_reg	= MAX8925_ON_OFF_IRQ2_MASK,
+		.offs		= 1 << 0,
+	},
+	[MAX8925_IRQ_GPM_SYSCKEN_R] = {
+		.reg		= MAX8925_ON_OFF_IRQ2,
+		.mask_reg	= MAX8925_ON_OFF_IRQ2_MASK,
+		.offs		= 1 << 1,
+	},
+	[MAX8925_IRQ_RTC_ALARM1] = {
+		.reg		= MAX8925_RTC_IRQ,
+		.mask_reg	= MAX8925_RTC_IRQ_MASK,
+		.offs		= 1 << 2,
+		.flags		= FLAGS_RTC,
+	},
+	[MAX8925_IRQ_RTC_ALARM0] = {
+		.reg		= MAX8925_RTC_IRQ,
+		.mask_reg	= MAX8925_RTC_IRQ_MASK,
+		.offs		= 1 << 3,
+		.flags		= FLAGS_RTC,
+	},
+	[MAX8925_IRQ_TSC_STICK] = {
+		.reg		= MAX8925_TSC_IRQ,
+		.mask_reg	= MAX8925_TSC_IRQ_MASK,
+		.offs		= 1 << 0,
+		.flags		= FLAGS_ADC,
+		.tsc_irq	= 1,
+	},
+	[MAX8925_IRQ_TSC_NSTICK] = {
+		.reg		= MAX8925_TSC_IRQ,
+		.mask_reg	= MAX8925_TSC_IRQ_MASK,
+		.offs		= 1 << 1,
+		.flags		= FLAGS_ADC,
+		.tsc_irq	= 1,
+	},
+};
+
+static inline struct max8925_irq_data *irq_to_max8925(struct max8925_chip *chip,
+						      int irq)
+{
+	return &max8925_irqs[irq - chip->irq_base];
+}
+
+static irqreturn_t max8925_irq(int irq, void *data)
+{
+	struct max8925_chip *chip = data;
+	struct max8925_irq_data *irq_data;
+	struct i2c_client *i2c;
+	int read_reg = -1, value = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
+		irq_data = &max8925_irqs[i];
+		/* TSC IRQ should be serviced in max8925_tsc_irq() */
+		if (irq_data->tsc_irq)
+			continue;
+		if (irq_data->flags == FLAGS_RTC)
+			i2c = chip->rtc;
+		else if (irq_data->flags == FLAGS_ADC)
+			i2c = chip->adc;
+		else
+			i2c = chip->i2c;
+		if (read_reg != irq_data->reg) {
+			read_reg = irq_data->reg;
+			value = max8925_reg_read(i2c, irq_data->reg);
+		}
+		if (value & irq_data->enable)
+			handle_nested_irq(chip->irq_base + i);
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t max8925_tsc_irq(int irq, void *data)
+{
+	struct max8925_chip *chip = data;
+	struct max8925_irq_data *irq_data;
+	struct i2c_client *i2c;
+	int read_reg = -1, value = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
+		irq_data = &max8925_irqs[i];
+		/* non TSC IRQ should be serviced in max8925_irq() */
+		if (!irq_data->tsc_irq)
+			continue;
+		if (irq_data->flags == FLAGS_RTC)
+			i2c = chip->rtc;
+		else if (irq_data->flags == FLAGS_ADC)
+			i2c = chip->adc;
+		else
+			i2c = chip->i2c;
+		if (read_reg != irq_data->reg) {
+			read_reg = irq_data->reg;
+			value = max8925_reg_read(i2c, irq_data->reg);
+		}
+		if (value & irq_data->enable)
+			handle_nested_irq(chip->irq_base + i);
+	}
+	return IRQ_HANDLED;
+}
+
+static void max8925_irq_lock(unsigned int irq)
+{
+	struct max8925_chip *chip = get_irq_chip_data(irq);
+
+	mutex_lock(&chip->irq_lock);
+}
+
+static void max8925_irq_sync_unlock(unsigned int irq)
+{
+	struct max8925_chip *chip = get_irq_chip_data(irq);
+	struct max8925_irq_data *irq_data;
+	static unsigned char cache_chg[2] = {0xff, 0xff};
+	static unsigned char cache_on[2] = {0xff, 0xff};
+	static unsigned char cache_rtc = 0xff, cache_tsc = 0xff;
+	unsigned char irq_chg[2], irq_on[2];
+	unsigned char irq_rtc, irq_tsc;
+	int i;
+
+	/* Load cached value. In initial, all IRQs are masked */
+	irq_chg[0] = cache_chg[0];
+	irq_chg[1] = cache_chg[1];
+	irq_on[0] = cache_on[0];
+	irq_on[1] = cache_on[1];
+	irq_rtc = cache_rtc;
+	irq_tsc = cache_tsc;
+	for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
+		irq_data = &max8925_irqs[i];
+		switch (irq_data->mask_reg) {
+		case MAX8925_CHG_IRQ1_MASK:
+			irq_chg[0] &= irq_data->enable;
+			break;
+		case MAX8925_CHG_IRQ2_MASK:
+			irq_chg[1] &= irq_data->enable;
+			break;
+		case MAX8925_ON_OFF_IRQ1_MASK:
+			irq_on[0] &= irq_data->enable;
+			break;
+		case MAX8925_ON_OFF_IRQ2_MASK:
+			irq_on[1] &= irq_data->enable;
+			break;
+		case MAX8925_RTC_IRQ_MASK:
+			irq_rtc &= irq_data->enable;
+			break;
+		case MAX8925_TSC_IRQ_MASK:
+			irq_tsc &= irq_data->enable;
+			break;
+		default:
+			dev_err(chip->dev, "wrong IRQ\n");
+			break;
+		}
+	}
+	/* update mask into registers */
+	if (cache_chg[0] != irq_chg[0]) {
+		cache_chg[0] = irq_chg[0];
+		max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK,
+			irq_chg[0]);
+	}
+	if (cache_chg[1] != irq_chg[1]) {
+		cache_chg[1] = irq_chg[1];
+		max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK,
+			irq_chg[1]);
+	}
+	if (cache_on[0] != irq_on[0]) {
+		cache_on[0] = irq_on[0];
+		max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK,
+				irq_on[0]);
+	}
+	if (cache_on[1] != irq_on[1]) {
+		cache_on[1] = irq_on[1];
+		max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK,
+				irq_on[1]);
+	}
+	if (cache_rtc != irq_rtc) {
+		cache_rtc = irq_rtc;
+		max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, irq_rtc);
+	}
+	if (cache_tsc != irq_tsc) {
+		cache_tsc = irq_tsc;
+		max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, irq_tsc);
+	}
+
+	mutex_unlock(&chip->irq_lock);
+}
+
+static void max8925_irq_enable(unsigned int irq)
+{
+	struct max8925_chip *chip = get_irq_chip_data(irq);
+	max8925_irqs[irq - chip->irq_base].enable
+		= max8925_irqs[irq - chip->irq_base].offs;
+}
+
+static void max8925_irq_disable(unsigned int irq)
+{
+	struct max8925_chip *chip = get_irq_chip_data(irq);
+	max8925_irqs[irq - chip->irq_base].enable = 0;
+}
+
+static struct irq_chip max8925_irq_chip = {
+	.name		= "max8925",
+	.bus_lock	= max8925_irq_lock,
+	.bus_sync_unlock = max8925_irq_sync_unlock,
+	.enable		= max8925_irq_enable,
+	.disable	= max8925_irq_disable,
+};
+
+static int max8925_irq_init(struct max8925_chip *chip, int irq,
+			    struct max8925_platform_data *pdata)
+{
+	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+	struct irq_desc *desc;
+	int i, ret;
+	int __irq;
+
+	if (!pdata || !pdata->irq_base) {
+		dev_warn(chip->dev, "No interrupt support on IRQ base\n");
+		return -EINVAL;
+	}
+	/* clear all interrupts */
+	max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1);
+	max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2);
+	max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ1);
+	max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2);
+	max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ);
+	max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
+	/* mask all interrupts */
+	max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0);
+	max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0);
+	max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff);
+	max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK, 0xff);
+	max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff);
+	max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff);
+	max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff);
+	max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0xff);
+
+	mutex_init(&chip->irq_lock);
+	chip->core_irq = irq;
+	chip->irq_base = pdata->irq_base;
+	desc = irq_to_desc(chip->core_irq);
+
+	/* register with genirq */
+	for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
+		__irq = i + chip->irq_base;
+		set_irq_chip_data(__irq, chip);
+		set_irq_chip_and_handler(__irq, &max8925_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
+	}
+	if (!irq) {
+		dev_warn(chip->dev, "No interrupt support on core IRQ\n");
+		goto tsc_irq;
+	}
+
+	ret = request_threaded_irq(irq, NULL, max8925_irq, flags,
+				   "max8925", chip);
+	if (ret) {
+		dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
+		chip->core_irq = 0;
+	}
+tsc_irq:
+	if (!pdata->tsc_irq) {
+		dev_warn(chip->dev, "No interrupt support on TSC IRQ\n");
+		return 0;
+	}
+	chip->tsc_irq = pdata->tsc_irq;
+
+	ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq,
+				   flags, "max8925-tsc", chip);
+	if (ret) {
+		dev_err(chip->dev, "Failed to request TSC IRQ: %d\n", ret);
+		chip->tsc_irq = 0;
+	}
+	return 0;
+}
+
+int __devinit max8925_device_init(struct max8925_chip *chip,
+				  struct max8925_platform_data *pdata)
+{
+	int ret;
+
+	max8925_irq_init(chip, chip->i2c->irq, pdata);
+
+	if (pdata && (pdata->power || pdata->touch)) {
+		/* enable ADC to control internal reference */
+		max8925_set_bits(chip->i2c, MAX8925_RESET_CNFG, 1, 1);
+		/* enable internal reference for ADC */
+		max8925_set_bits(chip->adc, MAX8925_TSC_CNFG1, 3, 2);
+		/* check for internal reference IRQ */
+		do {
+			ret = max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
+		} while (ret & MAX8925_NREF_OK);
+		/* enaable ADC scheduler, interval is 1 second */
+		max8925_set_bits(chip->adc, MAX8925_ADC_SCHED, 3, 2);
+	}
+
+	/* enable Momentary Power Loss */
+	max8925_set_bits(chip->rtc, MAX8925_MPL_CNTL, 1 << 4, 1 << 4);
+
+	ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
+			      ARRAY_SIZE(rtc_devs),
+			      &rtc_resources[0], 0);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to add rtc subdev\n");
+		goto out;
+	}
+	if (pdata && pdata->regulator[0]) {
+		ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
+				      ARRAY_SIZE(regulator_devs),
+				      &regulator_resources[0], 0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to add regulator subdev\n");
+			goto out_dev;
+		}
+	}
+
+	if (pdata && pdata->backlight) {
+		ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
+				      ARRAY_SIZE(backlight_devs),
+				      &backlight_resources[0], 0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to add backlight subdev\n");
+			goto out_dev;
+		}
+	}
+
+	if (pdata && pdata->power) {
+		ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
+					ARRAY_SIZE(power_devs),
+					&power_supply_resources[0], 0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to add power supply "
+				"subdev\n");
+			goto out_dev;
+		}
+	}
+
+	if (pdata && pdata->touch) {
+		ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
+				      ARRAY_SIZE(touch_devs),
+				      &touch_resources[0], 0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to add touch subdev\n");
+			goto out_dev;
+		}
+	}
+
+	return 0;
+out_dev:
+	mfd_remove_devices(chip->dev);
+out:
+	return ret;
+}
+
+void __devexit max8925_device_exit(struct max8925_chip *chip)
+{
+	if (chip->core_irq)
+		free_irq(chip->core_irq, chip);
+	if (chip->tsc_irq)
+		free_irq(chip->tsc_irq, chip);
+	mfd_remove_devices(chip->dev);
+}
+
+
+MODULE_DESCRIPTION("PMIC Driver for Maxim MAX8925");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
new file mode 100644
index 0000000..c0b883c
--- /dev/null
+++ b/drivers/mfd/max8925-i2c.c
@@ -0,0 +1,211 @@
+/*
+ * I2C driver for Maxim MAX8925
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ *	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/mfd/max8925.h>
+
+#define RTC_I2C_ADDR		0x68
+#define ADC_I2C_ADDR		0x47
+
+static inline int max8925_read_device(struct i2c_client *i2c,
+				      int reg, int bytes, void *dest)
+{
+	int ret;
+
+	if (bytes > 1)
+		ret = i2c_smbus_read_i2c_block_data(i2c, reg, bytes, dest);
+	else {
+		ret = i2c_smbus_read_byte_data(i2c, reg);
+		if (ret < 0)
+			return ret;
+		*(unsigned char *)dest = (unsigned char)ret;
+	}
+	return ret;
+}
+
+static inline int max8925_write_device(struct i2c_client *i2c,
+				       int reg, int bytes, void *src)
+{
+	unsigned char buf[bytes + 1];
+	int ret;
+
+	buf[0] = (unsigned char)reg;
+	memcpy(&buf[1], src, bytes);
+
+	ret = i2c_master_send(i2c, buf, bytes + 1);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+int max8925_reg_read(struct i2c_client *i2c, int reg)
+{
+	struct max8925_chip *chip = i2c_get_clientdata(i2c);
+	unsigned char data = 0;
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	ret = max8925_read_device(i2c, reg, 1, &data);
+	mutex_unlock(&chip->io_lock);
+
+	if (ret < 0)
+		return ret;
+	else
+		return (int)data;
+}
+EXPORT_SYMBOL(max8925_reg_read);
+
+int max8925_reg_write(struct i2c_client *i2c, int reg,
+		unsigned char data)
+{
+	struct max8925_chip *chip = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	ret = max8925_write_device(i2c, reg, 1, &data);
+	mutex_unlock(&chip->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(max8925_reg_write);
+
+int max8925_bulk_read(struct i2c_client *i2c, int reg,
+		int count, unsigned char *buf)
+{
+	struct max8925_chip *chip = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	ret = max8925_read_device(i2c, reg, count, buf);
+	mutex_unlock(&chip->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(max8925_bulk_read);
+
+int max8925_bulk_write(struct i2c_client *i2c, int reg,
+		int count, unsigned char *buf)
+{
+	struct max8925_chip *chip = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	ret = max8925_write_device(i2c, reg, count, buf);
+	mutex_unlock(&chip->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(max8925_bulk_write);
+
+int max8925_set_bits(struct i2c_client *i2c, int reg,
+		unsigned char mask, unsigned char data)
+{
+	struct max8925_chip *chip = i2c_get_clientdata(i2c);
+	unsigned char value;
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	ret = max8925_read_device(i2c, reg, 1, &value);
+	if (ret < 0)
+		goto out;
+	value &= ~mask;
+	value |= data;
+	ret = max8925_write_device(i2c, reg, 1, &value);
+out:
+	mutex_unlock(&chip->io_lock);
+	return ret;
+}
+EXPORT_SYMBOL(max8925_set_bits);
+
+
+static const struct i2c_device_id max8925_id_table[] = {
+	{ "max8925", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, max8925_id_table);
+
+static int __devinit max8925_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	struct max8925_platform_data *pdata = client->dev.platform_data;
+	static struct max8925_chip *chip;
+
+	if (!pdata) {
+		pr_info("%s: platform data is missing\n", __func__);
+		return -EINVAL;
+	}
+
+	chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+	chip->i2c = client;
+	chip->dev = &client->dev;
+	i2c_set_clientdata(client, chip);
+	dev_set_drvdata(chip->dev, chip);
+	mutex_init(&chip->io_lock);
+
+	chip->rtc = i2c_new_dummy(chip->i2c->adapter, RTC_I2C_ADDR);
+	i2c_set_clientdata(chip->rtc, chip);
+
+	chip->adc = i2c_new_dummy(chip->i2c->adapter, ADC_I2C_ADDR);
+	i2c_set_clientdata(chip->adc, chip);
+
+	max8925_device_init(chip, pdata);
+
+	return 0;
+}
+
+static int __devexit max8925_remove(struct i2c_client *client)
+{
+	struct max8925_chip *chip = i2c_get_clientdata(client);
+
+	max8925_device_exit(chip);
+	i2c_unregister_device(chip->adc);
+	i2c_unregister_device(chip->rtc);
+	i2c_set_clientdata(chip->adc, NULL);
+	i2c_set_clientdata(chip->rtc, NULL);
+	i2c_set_clientdata(chip->i2c, NULL);
+	kfree(chip);
+	return 0;
+}
+
+static struct i2c_driver max8925_driver = {
+	.driver	= {
+		.name	= "max8925",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= max8925_probe,
+	.remove		= __devexit_p(max8925_remove),
+	.id_table	= max8925_id_table,
+};
+
+static int __init max8925_i2c_init(void)
+{
+	int ret;
+
+	ret = i2c_add_driver(&max8925_driver);
+	if (ret != 0)
+		pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
+	return ret;
+}
+subsys_initcall(max8925_i2c_init);
+
+static void __exit max8925_i2c_exit(void)
+{
+	i2c_del_driver(&max8925_driver);
+}
+module_exit(max8925_i2c_exit);
+
+MODULE_DESCRIPTION("I2C Driver for Maxim 8925");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c
index 735c8a4..62a847e 100644
--- a/drivers/mfd/mc13783-core.c
+++ b/drivers/mfd/mc13783-core.c
@@ -225,7 +225,7 @@
 }
 EXPORT_SYMBOL(mc13783_reg_rmw);
 
-int mc13783_mask(struct mc13783 *mc13783, int irq)
+int mc13783_irq_mask(struct mc13783 *mc13783, int irq)
 {
 	int ret;
 	unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1;
@@ -245,9 +245,9 @@
 
 	return mc13783_reg_write(mc13783, offmask, mask | irqbit);
 }
-EXPORT_SYMBOL(mc13783_mask);
+EXPORT_SYMBOL(mc13783_irq_mask);
 
-int mc13783_unmask(struct mc13783 *mc13783, int irq)
+int mc13783_irq_unmask(struct mc13783 *mc13783, int irq)
 {
 	int ret;
 	unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1;
@@ -267,7 +267,53 @@
 
 	return mc13783_reg_write(mc13783, offmask, mask & ~irqbit);
 }
-EXPORT_SYMBOL(mc13783_unmask);
+EXPORT_SYMBOL(mc13783_irq_unmask);
+
+int mc13783_irq_status(struct mc13783 *mc13783, int irq,
+		int *enabled, int *pending)
+{
+	int ret;
+	unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1;
+	unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1;
+	u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
+
+	if (irq < 0 || irq >= MC13783_NUM_IRQ)
+		return -EINVAL;
+
+	if (enabled) {
+		u32 mask;
+
+		ret = mc13783_reg_read(mc13783, offmask, &mask);
+		if (ret)
+			return ret;
+
+		*enabled = mask & irqbit;
+	}
+
+	if (pending) {
+		u32 stat;
+
+		ret = mc13783_reg_read(mc13783, offstat, &stat);
+		if (ret)
+			return ret;
+
+		*pending = stat & irqbit;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(mc13783_irq_status);
+
+int mc13783_irq_ack(struct mc13783 *mc13783, int irq)
+{
+	unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1;
+	unsigned int val = 1 << (irq < 24 ? irq : irq - 24);
+
+	BUG_ON(irq < 0 || irq >= MC13783_NUM_IRQ);
+
+	return mc13783_reg_write(mc13783, offstat, val);
+}
+EXPORT_SYMBOL(mc13783_irq_ack);
 
 int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq,
 		irq_handler_t handler, const char *name, void *dev)
@@ -297,7 +343,7 @@
 	if (ret)
 		return ret;
 
-	ret = mc13783_unmask(mc13783, irq);
+	ret = mc13783_irq_unmask(mc13783, irq);
 	if (ret) {
 		mc13783->irqhandler[irq] = NULL;
 		mc13783->irqdata[irq] = NULL;
@@ -317,7 +363,7 @@
 			mc13783->irqdata[irq] != dev)
 		return -EINVAL;
 
-	ret = mc13783_mask(mc13783, irq);
+	ret = mc13783_irq_mask(mc13783, irq);
 	if (ret)
 		return ret;
 
@@ -333,17 +379,6 @@
 	return mc13783->irqhandler[irq](irq, mc13783->irqdata[irq]);
 }
 
-int mc13783_ackirq(struct mc13783 *mc13783, int irq)
-{
-	unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1;
-	unsigned int val = 1 << (irq < 24 ? irq : irq - 24);
-
-	BUG_ON(irq < 0 || irq >= MC13783_NUM_IRQ);
-
-	return mc13783_reg_write(mc13783, offstat, val);
-}
-EXPORT_SYMBOL(mc13783_ackirq);
-
 /*
  * returns: number of handled irqs or negative error
  * locking: holds mc13783->lock
@@ -422,7 +457,7 @@
 {
 	struct mc13783_adcdone_data *adcdone_data = data;
 
-	mc13783_ackirq(adcdone_data->mc13783, irq);
+	mc13783_irq_ack(adcdone_data->mc13783, irq);
 
 	complete_all(&adcdone_data->done);
 
@@ -486,7 +521,7 @@
 	dev_dbg(&mc13783->spidev->dev, "%s: request irq\n", __func__);
 	mc13783_irq_request(mc13783, MC13783_IRQ_ADCDONE,
 			mc13783_handler_adcdone, __func__, &adcdone_data);
-	mc13783_ackirq(mc13783, MC13783_IRQ_ADCDONE);
+	mc13783_irq_ack(mc13783, MC13783_IRQ_ADCDONE);
 
 	mc13783_reg_write(mc13783, MC13783_REG_ADC_0, adc0);
 	mc13783_reg_write(mc13783, MC13783_REG_ADC_1, adc1);
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index ae15e49..aa17f4b 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/acpi.h>
 #include <linux/mfd/core.h>
 
 static int mfd_add_device(struct device *parent, int id,
@@ -62,6 +63,10 @@
 			res[r].start = cell->resources[r].start;
 			res[r].end   = cell->resources[r].end;
 		}
+
+		ret = acpi_check_resource_conflict(res);
+		if (ret)
+			goto fail_res;
 	}
 
 	platform_device_add_resources(pdev, res, cell->num_resources);
diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c
index 03efae8..468fd36 100644
--- a/drivers/mfd/sh_mobile_sdhi.c
+++ b/drivers/mfd/sh_mobile_sdhi.c
@@ -21,7 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
-
+#include <linux/mmc/host.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mfd/sh_mobile_sdhi.h>
@@ -95,9 +95,9 @@
 
 	clk_enable(priv->clk);
 
-	/* FIXME: silly const unsigned int hclk */
-	*(unsigned int *)&priv->mmc_data.hclk = clk_get_rate(priv->clk);
+	priv->mmc_data.hclk = clk_get_rate(priv->clk);
 	priv->mmc_data.set_pwr = sh_mobile_sdhi_set_pwr;
+	priv->mmc_data.capabilities = MMC_CAP_MMC_HIGHSPEED;
 
 	memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
 	priv->cell_mmc.driver_data = &priv->mmc_data;
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 0cc5eef..7b6652f 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -523,7 +523,7 @@
 	unsigned long clock = readl(sm->regs + SM501_CURRENT_CLOCK);
 	unsigned char reg;
 	unsigned int pll_reg = 0;
-	unsigned long sm501_freq; /* the actual frequency acheived */
+	unsigned long sm501_freq; /* the actual frequency achieved */
 
 	struct sm501_clock to;
 
@@ -533,7 +533,7 @@
 
 	switch (clksrc) {
 	case SM501_CLOCK_P2XCLK:
-		/* This clock is divided in half so to achive the
+		/* This clock is divided in half so to achieve the
 		 * requested frequency the value must be multiplied by
 		 * 2. This clock also has an additional pre divisor */
 
@@ -562,7 +562,7 @@
 		break;
 
 	case SM501_CLOCK_V2XCLK:
-		/* This clock is divided in half so to achive the
+		/* This clock is divided in half so to achieve the
 		 * requested frequency the value must be multiplied by 2. */
 
 		sm501_freq = (sm501_select_clock(2 * req_freq, &to, 3) / 2);
@@ -648,7 +648,7 @@
 			       unsigned long req_freq)
 {
 	struct sm501_devdata *sm = dev_get_drvdata(dev);
-	unsigned long sm501_freq; /* the frequency achiveable by the 501 */
+	unsigned long sm501_freq; /* the frequency achieveable by the 501 */
 	struct sm501_clock to;
 
 	switch (clksrc) {
@@ -1440,8 +1440,7 @@
 
 	platform_set_drvdata(dev, sm);
 
-	sm->regs = ioremap(sm->io_res->start,
-			   (sm->io_res->end - sm->io_res->start) - 1);
+	sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res));
 
 	if (sm->regs == NULL) {
 		dev_err(&dev->dev, "cannot remap registers\n");
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index bcf4687..26d9176 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -360,7 +360,7 @@
 	if (ret)
 		goto err_request_scr;
 
-	t7l66xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
+	t7l66xb->scr = ioremap(rscr->start, resource_size(rscr));
 	if (!t7l66xb->scr) {
 		ret = -ENOMEM;
 		goto err_ioremap;
@@ -403,12 +403,12 @@
 err_ioremap:
 	release_resource(&t7l66xb->rscr);
 err_request_scr:
-	kfree(t7l66xb);
 	clk_put(t7l66xb->clk48m);
 err_clk48m_get:
 	clk_put(t7l66xb->clk32k);
 err_clk32k_get:
 err_noirq:
+	kfree(t7l66xb);
 	return ret;
 }
 
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 4bc5a08..c59e5c5 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -647,7 +647,7 @@
 	if (ret)
 		goto err_request_scr;
 
-	tc6393xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
+	tc6393xb->scr = ioremap(rscr->start, resource_size(rscr));
 	if (!tc6393xb->scr) {
 		ret = -ENOMEM;
 		goto err_ioremap;
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 19a930d..562cd49 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -58,13 +58,6 @@
 
 #define DRIVER_NAME			"twl"
 
-#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
-	defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
-#define twl_has_bci()		true
-#else
-#define twl_has_bci()		false
-#endif
-
 #if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
 #define twl_has_keypad()	true
 #else
@@ -130,7 +123,7 @@
 #define TWL_NUM_SLAVES		4
 
 #if defined(CONFIG_INPUT_TWL4030_PWRBUTTON) \
-	|| defined(CONFIG_INPUT_TWL4030_PWBUTTON_MODULE)
+	|| defined(CONFIG_INPUT_TWL4030_PWRBUTTON_MODULE)
 #define twl_has_pwrbutton()	true
 #else
 #define twl_has_pwrbutton()	false
@@ -205,6 +198,7 @@
 /* subchip/slave 3 0x4B - AUDIO */
 #define TWL6030_BASEADD_AUDIO		0x0000
 #define TWL6030_BASEADD_RSV		0x0000
+#define TWL6030_BASEADD_ZERO		0x0000
 
 /* Few power values */
 #define R_CFG_BOOT			0x05
@@ -320,9 +314,11 @@
 	{ SUB_CHIP_ID1, TWL6030_BASEADD_CHARGER },
 	{ SUB_CHIP_ID1, TWL6030_BASEADD_GASGAUGE },
 	{ SUB_CHIP_ID1, TWL6030_BASEADD_PWM },
-	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
-	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
+	{ SUB_CHIP_ID0, TWL6030_BASEADD_ZERO },
+	{ SUB_CHIP_ID1, TWL6030_BASEADD_ZERO },
 
+	{ SUB_CHIP_ID2, TWL6030_BASEADD_ZERO },
+	{ SUB_CHIP_ID2, TWL6030_BASEADD_ZERO },
 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
 	{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
@@ -588,18 +584,6 @@
 	struct device	*child;
 	unsigned sub_chip_id;
 
-	if (twl_has_bci() && pdata->bci &&
-	    !(features & (TPS_SUBSET | TWL5031))) {
-		child = add_child(3, "twl4030_bci",
-				pdata->bci, sizeof(*pdata->bci),
-				false,
-				/* irq0 = CHG_PRES, irq1 = BCI */
-				pdata->irq_base + BCI_PRES_INTR_OFFSET,
-				pdata->irq_base + BCI_INTR_OFFSET);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
 	if (twl_has_gpio() && pdata->gpio) {
 		child = add_child(SUB_CHIP_ID1, "twl4030_gpio",
 				pdata->gpio, sizeof(*pdata->gpio),
@@ -977,6 +961,7 @@
 	int				status;
 	unsigned			i;
 	struct twl4030_platform_data	*pdata = client->dev.platform_data;
+	u8 temp;
 
 	if (!pdata) {
 		dev_dbg(&client->dev, "no platform data?\n");
@@ -1044,6 +1029,18 @@
 			goto fail;
 	}
 
+	/* Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
+	 * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0,
+	 * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0.
+	 */
+
+	if (twl_class_is_4030()) {
+		twl_i2c_read_u8(TWL4030_MODULE_INTBR, &temp, REG_GPPUPDCTR1);
+		temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \
+		I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
+		twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
+	}
+
 	status = add_children(pdata, id->driver_data);
 fail:
 	if (status < 0)
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index 0815292..7efa878 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -405,7 +405,7 @@
 
 	if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
 		remap &= ~SLEEP_STATE_MASK;
-		remap |= rconfig->remap_off << SLEEP_STATE_SHIFT;
+		remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
 	}
 
 	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
@@ -461,6 +461,56 @@
 	return err;
 }
 
+int twl4030_remove_script(u8 flags)
+{
+	int err = 0;
+
+	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_1,
+			R_PROTECT_KEY);
+	if (err) {
+		pr_err("twl4030: unable to unlock PROTECT_KEY\n");
+		return err;
+	}
+
+	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_2,
+			R_PROTECT_KEY);
+	if (err) {
+		pr_err("twl4030: unable to unlock PROTECT_KEY\n");
+		return err;
+	}
+
+	if (flags & TWL4030_WRST_SCRIPT) {
+		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
+				R_SEQ_ADD_WARM);
+		if (err)
+			return err;
+	}
+	if (flags & TWL4030_WAKEUP12_SCRIPT) {
+		if (err)
+		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
+				R_SEQ_ADD_S2A12);
+			return err;
+	}
+	if (flags & TWL4030_WAKEUP3_SCRIPT) {
+		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
+				R_SEQ_ADD_S2A3);
+		if (err)
+			return err;
+	}
+	if (flags & TWL4030_SLEEP_SCRIPT) {
+		err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
+				R_SEQ_ADD_A2S);
+		if (err)
+			return err;
+	}
+
+	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY);
+	if (err)
+		pr_err("TWL4030 Unable to relock registers\n");
+
+	return err;
+}
+
 void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
 {
 	int err = 0;
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index 252b741..b281217 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -27,6 +27,7 @@
 #include <linux/mutex.h>
 #include <linux/mfd/ucb1x00.h>
 #include <linux/gpio.h>
+#include <linux/semaphore.h>
 
 #include <mach/dma.h>
 #include <mach/hardware.h>
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 4b2021a..07101e9 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -321,7 +321,6 @@
  */
 int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
 {
-	int tries = 10;
 	int ret, src;
 
 	mutex_lock(&wm831x->auxadc_lock);
@@ -349,13 +348,14 @@
 		goto disable;
 	}
 
-	do {
-		msleep(1);
+	/* Ignore the result to allow us to soldier on without IRQ hookup */
+	wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5));
 
-		ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL);
-		if (ret < 0)
-			ret = WM831X_AUX_CVT_ENA;
-	} while ((ret & WM831X_AUX_CVT_ENA) && --tries);
+	ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "AUXADC status read failed: %d\n", ret);
+		goto disable;
+	}
 
 	if (ret & WM831X_AUX_CVT_ENA) {
 		dev_err(wm831x->dev, "Timed out reading AUXADC\n");
@@ -390,6 +390,15 @@
 }
 EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
 
+static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
+{
+	struct wm831x *wm831x = irq_data;
+
+	complete(&wm831x->auxadc_done);
+
+	return IRQ_HANDLED;
+}
+
 /**
  * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
  *
@@ -1411,6 +1420,7 @@
 	mutex_init(&wm831x->io_lock);
 	mutex_init(&wm831x->key_lock);
 	mutex_init(&wm831x->auxadc_lock);
+	init_completion(&wm831x->auxadc_done);
 	dev_set_drvdata(wm831x->dev, wm831x);
 
 	ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
@@ -1449,18 +1459,33 @@
 	case WM8310:
 		parent = WM8310;
 		wm831x->num_gpio = 16;
+		if (rev > 0) {
+			wm831x->has_gpio_ena = 1;
+			wm831x->has_cs_sts = 1;
+		}
+
 		dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
 		break;
 
 	case WM8311:
 		parent = WM8311;
 		wm831x->num_gpio = 16;
+		if (rev > 0) {
+			wm831x->has_gpio_ena = 1;
+			wm831x->has_cs_sts = 1;
+		}
+
 		dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev);
 		break;
 
 	case WM8312:
 		parent = WM8312;
 		wm831x->num_gpio = 16;
+		if (rev > 0) {
+			wm831x->has_gpio_ena = 1;
+			wm831x->has_cs_sts = 1;
+		}
+
 		dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev);
 		break;
 
@@ -1508,6 +1533,16 @@
 	if (ret != 0)
 		goto err;
 
+	if (wm831x->irq_base) {
+		ret = request_threaded_irq(wm831x->irq_base +
+					   WM831X_IRQ_AUXADC_DATA,
+					   NULL, wm831x_auxadc_irq, 0,
+					   "auxadc", wm831x);
+		if (ret < 0)
+			dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
+				ret);
+	}
+
 	/* The core device is up, instantiate the subdevices. */
 	switch (parent) {
 	case WM8310:
@@ -1578,6 +1613,8 @@
 {
 	wm831x_otp_exit(wm831x);
 	mfd_remove_devices(wm831x->dev);
+	if (wm831x->irq_base)
+		free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
 	wm831x_irq_exit(wm831x);
 	kfree(wm831x);
 }
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index 9a970bd..bd75807 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -339,7 +339,6 @@
 int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
 {
 	u16 reg, result = 0;
-	int tries = 5;
 
 	if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP)
 		return -EINVAL;
@@ -363,12 +362,13 @@
 	reg |= 1 << channel | WM8350_AUXADC_POLL;
 	wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg);
 
-	do {
-		schedule_timeout_interruptible(1);
-		reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
-	} while ((reg & WM8350_AUXADC_POLL) && --tries);
+	/* We ignore the result of the completion and just check for a
+	 * conversion result, allowing us to soldier on if the IRQ
+	 * infrastructure is not set up for the chip. */
+	wait_for_completion_timeout(&wm8350->auxadc_done, msecs_to_jiffies(5));
 
-	if (!tries)
+	reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
+	if (reg & WM8350_AUXADC_POLL)
 		dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
 	else
 		result = wm8350_reg_read(wm8350,
@@ -385,6 +385,15 @@
 }
 EXPORT_SYMBOL_GPL(wm8350_read_auxadc);
 
+static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data)
+{
+	struct wm8350 *wm8350 = irq_data;
+
+	complete(&wm8350->auxadc_done);
+
+	return IRQ_HANDLED;
+}
+
 /*
  * Cache is always host endian.
  */
@@ -682,11 +691,22 @@
 	}
 
 	mutex_init(&wm8350->auxadc_mutex);
+	init_completion(&wm8350->auxadc_done);
 
 	ret = wm8350_irq_init(wm8350, irq, pdata);
 	if (ret < 0)
 		goto err;
 
+	if (wm8350->irq_base) {
+		ret = request_threaded_irq(wm8350->irq_base +
+					   WM8350_IRQ_AUXADC_DATARDY,
+					   NULL, wm8350_auxadc_irq, 0,
+					   "auxadc", wm8350);
+		if (ret < 0)
+			dev_warn(wm8350->dev,
+				 "Failed to request AUXADC IRQ: %d\n", ret);
+	}
+
 	if (pdata && pdata->init) {
 		ret = pdata->init(wm8350);
 		if (ret != 0) {
@@ -736,6 +756,9 @@
 	platform_device_unregister(wm8350->gpio.pdev);
 	platform_device_unregister(wm8350->codec.pdev);
 
+	if (wm8350->irq_base)
+		free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350);
+
 	wm8350_irq_exit(wm8350);
 
 	kfree(wm8350->reg_cache);
diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c
index 9025f29..f56c9ad 100644
--- a/drivers/mfd/wm8350-irq.c
+++ b/drivers/mfd/wm8350-irq.c
@@ -18,7 +18,7 @@
 #include <linux/bug.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
-#include <linux/workqueue.h>
+#include <linux/irq.h>
 
 #include <linux/mfd/wm8350/core.h>
 #include <linux/mfd/wm8350/audio.h>
@@ -29,8 +29,6 @@
 #include <linux/mfd/wm8350/supply.h>
 #include <linux/mfd/wm8350/wdt.h>
 
-#define WM8350_NUM_IRQ_REGS 7
-
 #define WM8350_INT_OFFSET_1                     0
 #define WM8350_INT_OFFSET_2                     1
 #define WM8350_POWER_UP_INT_OFFSET              2
@@ -366,19 +364,10 @@
 	},
 };
 
-static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq)
+static inline struct wm8350_irq_data *irq_to_wm8350_irq(struct wm8350 *wm8350,
+							int irq)
 {
-	mutex_lock(&wm8350->irq_mutex);
-
-	if (wm8350->irq[irq].handler)
-		wm8350->irq[irq].handler(irq, wm8350->irq[irq].data);
-	else {
-		dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n",
-			irq);
-		wm8350_mask_irq(wm8350, irq);
-	}
-
-	mutex_unlock(&wm8350->irq_mutex);
+	return &wm8350_irqs[irq - wm8350->irq_base];
 }
 
 /*
@@ -386,7 +375,9 @@
  * interrupts are clear on read the IRQ line will be reasserted and
  * the physical IRQ will be handled again if another interrupt is
  * asserted while we run - in the normal course of events this is a
- * rare occurrence so we save I2C/SPI reads.
+ * rare occurrence so we save I2C/SPI reads.  We're also assuming that
+ * it's rare to get lots of interrupts firing simultaneously so try to
+ * minimise I/O.
  */
 static irqreturn_t wm8350_irq(int irq, void *irq_data)
 {
@@ -397,7 +388,6 @@
 	struct wm8350_irq_data *data;
 	int i;
 
-	/* TODO: Use block reads to improve performance? */
 	level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS)
 		& ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK);
 
@@ -416,93 +406,101 @@
 			sub_reg[data->reg] =
 				wm8350_reg_read(wm8350, WM8350_INT_STATUS_1 +
 						data->reg);
-			sub_reg[data->reg] &=
-				~wm8350_reg_read(wm8350,
-						 WM8350_INT_STATUS_1_MASK +
-						 data->reg);
+			sub_reg[data->reg] &= ~wm8350->irq_masks[data->reg];
 			read_done[data->reg] = 1;
 		}
 
 		if (sub_reg[data->reg] & data->mask)
-			wm8350_irq_call_handler(wm8350, i);
+			handle_nested_irq(wm8350->irq_base + i);
 	}
 
 	return IRQ_HANDLED;
 }
 
-int wm8350_register_irq(struct wm8350 *wm8350, int irq,
-			irq_handler_t handler, unsigned long flags,
-			const char *name, void *data)
+static void wm8350_irq_lock(unsigned int irq)
 {
-	if (irq < 0 || irq >= WM8350_NUM_IRQ || !handler)
-		return -EINVAL;
+	struct wm8350 *wm8350 = get_irq_chip_data(irq);
 
-	if (wm8350->irq[irq].handler)
-		return -EBUSY;
-
-	mutex_lock(&wm8350->irq_mutex);
-	wm8350->irq[irq].handler = handler;
-	wm8350->irq[irq].data = data;
-	mutex_unlock(&wm8350->irq_mutex);
-
-	wm8350_unmask_irq(wm8350, irq);
-
-	return 0;
+	mutex_lock(&wm8350->irq_lock);
 }
-EXPORT_SYMBOL_GPL(wm8350_register_irq);
 
-int wm8350_free_irq(struct wm8350 *wm8350, int irq)
+static void wm8350_irq_sync_unlock(unsigned int irq)
 {
-	if (irq < 0 || irq >= WM8350_NUM_IRQ)
-		return -EINVAL;
+	struct wm8350 *wm8350 = get_irq_chip_data(irq);
+	int i;
 
-	wm8350_mask_irq(wm8350, irq);
+	for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) {
+		/* If there's been a change in the mask write it back
+		 * to the hardware. */
+		if (wm8350->irq_masks[i] !=
+		    wm8350->reg_cache[WM8350_INT_STATUS_1_MASK + i])
+			WARN_ON(wm8350_reg_write(wm8350,
+					 WM8350_INT_STATUS_1_MASK + i,
+						 wm8350->irq_masks[i]));
+	}
 
-	mutex_lock(&wm8350->irq_mutex);
-	wm8350->irq[irq].handler = NULL;
-	mutex_unlock(&wm8350->irq_mutex);
-	return 0;
+	mutex_unlock(&wm8350->irq_lock);
 }
-EXPORT_SYMBOL_GPL(wm8350_free_irq);
 
-int wm8350_mask_irq(struct wm8350 *wm8350, int irq)
+static void wm8350_irq_enable(unsigned int irq)
 {
-	return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK +
-			       wm8350_irqs[irq].reg,
-			       wm8350_irqs[irq].mask);
-}
-EXPORT_SYMBOL_GPL(wm8350_mask_irq);
+	struct wm8350 *wm8350 = get_irq_chip_data(irq);
+	struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq);
 
-int wm8350_unmask_irq(struct wm8350 *wm8350, int irq)
-{
-	return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK +
-				 wm8350_irqs[irq].reg,
-				 wm8350_irqs[irq].mask);
+	wm8350->irq_masks[irq_data->reg] &= ~irq_data->mask;
 }
-EXPORT_SYMBOL_GPL(wm8350_unmask_irq);
+
+static void wm8350_irq_disable(unsigned int irq)
+{
+	struct wm8350 *wm8350 = get_irq_chip_data(irq);
+	struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq);
+
+	wm8350->irq_masks[irq_data->reg] |= irq_data->mask;
+}
+
+static struct irq_chip wm8350_irq_chip = {
+	.name = "wm8350",
+	.bus_lock = wm8350_irq_lock,
+	.bus_sync_unlock = wm8350_irq_sync_unlock,
+	.disable = wm8350_irq_disable,
+	.enable = wm8350_irq_enable,
+};
 
 int wm8350_irq_init(struct wm8350 *wm8350, int irq,
 		    struct wm8350_platform_data *pdata)
 {
-	int ret;
+	int ret, cur_irq, i;
 	int flags = IRQF_ONESHOT;
 
 	if (!irq) {
-		dev_err(wm8350->dev, "No IRQ configured\n");
-		return -EINVAL;
+		dev_warn(wm8350->dev, "No interrupt support, no core IRQ\n");
+		return 0;
 	}
 
+	if (!pdata || !pdata->irq_base) {
+		dev_warn(wm8350->dev, "No interrupt support, no IRQ base\n");
+		return 0;
+	}
+
+	/* Mask top level interrupts */
 	wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF);
-	wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF);
-	wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF);
-	wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF);
-	wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF);
-	wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF);
 
-	mutex_init(&wm8350->irq_mutex);
+	/* Mask all individual interrupts by default and cache the
+	 * masks.  We read the masks back since there are unwritable
+	 * bits in the mask registers. */
+	for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) {
+		wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK + i,
+				 0xFFFF);
+		wm8350->irq_masks[i] =
+			wm8350_reg_read(wm8350,
+					WM8350_INT_STATUS_1_MASK + i);
+	}
+
+	mutex_init(&wm8350->irq_lock);
 	wm8350->chip_irq = irq;
+	wm8350->irq_base = pdata->irq_base;
 
-	if (pdata && pdata->irq_high) {
+	if (pdata->irq_high) {
 		flags |= IRQF_TRIGGER_HIGH;
 
 		wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1,
@@ -514,11 +512,32 @@
 				  WM8350_IRQ_POL);
 	}
 
+	/* Register with genirq */
+	for (cur_irq = wm8350->irq_base;
+	     cur_irq < ARRAY_SIZE(wm8350_irqs) + wm8350->irq_base;
+	     cur_irq++) {
+		set_irq_chip_data(cur_irq, wm8350);
+		set_irq_chip_and_handler(cur_irq, &wm8350_irq_chip,
+					 handle_edge_irq);
+		set_irq_nested_thread(cur_irq, 1);
+
+		/* ARM needs us to explicitly flag the IRQ as valid
+		 * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+		set_irq_flags(cur_irq, IRQF_VALID);
+#else
+		set_irq_noprobe(cur_irq);
+#endif
+	}
+
 	ret = request_threaded_irq(irq, NULL, wm8350_irq, flags,
 				   "wm8350", wm8350);
 	if (ret != 0)
 		dev_err(wm8350->dev, "Failed to request IRQ: %d\n", ret);
 
+	/* Allow interrupts to fire */
+	wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0);
+
 	return ret;
 }
 
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
new file mode 100644
index 0000000..844e1c1
--- /dev/null
+++ b/drivers/mfd/wm8994-core.c
@@ -0,0 +1,537 @@
+/*
+ * wm8994-core.c  --  Device access for Wolfson WM8994
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/mfd/core.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/pdata.h>
+#include <linux/mfd/wm8994/registers.h>
+
+static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
+		       int bytes, void *dest)
+{
+	int ret, i;
+	u16 *buf = dest;
+
+	BUG_ON(bytes % 2);
+	BUG_ON(bytes <= 0);
+
+	ret = wm8994->read_dev(wm8994, reg, bytes, dest);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < bytes / 2; i++) {
+		buf[i] = be16_to_cpu(buf[i]);
+
+		dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n",
+			 buf[i], reg + i, reg + i);
+	}
+
+	return 0;
+}
+
+/**
+ * wm8994_reg_read: Read a single WM8994 register.
+ *
+ * @wm8994: Device to read from.
+ * @reg: Register to read.
+ */
+int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
+{
+	unsigned short val;
+	int ret;
+
+	mutex_lock(&wm8994->io_lock);
+
+	ret = wm8994_read(wm8994, reg, 2, &val);
+
+	mutex_unlock(&wm8994->io_lock);
+
+	if (ret < 0)
+		return ret;
+	else
+		return val;
+}
+EXPORT_SYMBOL_GPL(wm8994_reg_read);
+
+/**
+ * wm8994_bulk_read: Read multiple WM8994 registers
+ *
+ * @wm8994: Device to read from
+ * @reg: First register
+ * @count: Number of registers
+ * @buf: Buffer to fill.
+ */
+int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
+		     int count, u16 *buf)
+{
+	int ret;
+
+	mutex_lock(&wm8994->io_lock);
+
+	ret = wm8994_read(wm8994, reg, count * 2, buf);
+
+	mutex_unlock(&wm8994->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8994_bulk_read);
+
+static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
+			int bytes, void *src)
+{
+	u16 *buf = src;
+	int i;
+
+	BUG_ON(bytes % 2);
+	BUG_ON(bytes <= 0);
+
+	for (i = 0; i < bytes / 2; i++) {
+		dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n",
+			 buf[i], reg + i, reg + i);
+
+		buf[i] = cpu_to_be16(buf[i]);
+	}
+
+	return wm8994->write_dev(wm8994, reg, bytes, src);
+}
+
+/**
+ * wm8994_reg_write: Write a single WM8994 register.
+ *
+ * @wm8994: Device to write to.
+ * @reg: Register to write to.
+ * @val: Value to write.
+ */
+int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
+		     unsigned short val)
+{
+	int ret;
+
+	mutex_lock(&wm8994->io_lock);
+
+	ret = wm8994_write(wm8994, reg, 2, &val);
+
+	mutex_unlock(&wm8994->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8994_reg_write);
+
+/**
+ * wm8994_set_bits: Set the value of a bitfield in a WM8994 register
+ *
+ * @wm8994: Device to write to.
+ * @reg: Register to write to.
+ * @mask: Mask of bits to set.
+ * @val: Value to set (unshifted)
+ */
+int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
+		    unsigned short mask, unsigned short val)
+{
+	int ret;
+	u16 r;
+
+	mutex_lock(&wm8994->io_lock);
+
+	ret = wm8994_read(wm8994, reg, 2, &r);
+	if (ret < 0)
+		goto out;
+
+	r &= ~mask;
+	r |= val;
+
+	ret = wm8994_write(wm8994, reg, 2, &r);
+
+out:
+	mutex_unlock(&wm8994->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8994_set_bits);
+
+static struct mfd_cell wm8994_regulator_devs[] = {
+	{ .name = "wm8994-ldo", .id = 1 },
+	{ .name = "wm8994-ldo", .id = 2 },
+};
+
+static struct mfd_cell wm8994_devs[] = {
+	{ .name = "wm8994-codec" },
+	{ .name = "wm8994-gpio" },
+};
+
+/*
+ * Supplies for the main bulk of CODEC; the LDO supplies are ignored
+ * and should be handled via the standard regulator API supply
+ * management.
+ */
+static const char *wm8994_main_supplies[] = {
+	"DBVDD",
+	"DCVDD",
+	"AVDD1",
+	"AVDD2",
+	"CPVDD",
+	"SPKVDD1",
+	"SPKVDD2",
+};
+
+#ifdef CONFIG_PM
+static int wm8994_device_suspend(struct device *dev)
+{
+	struct wm8994 *wm8994 = dev_get_drvdata(dev);
+	int ret;
+
+	/* GPIO configuration state is saved here since we may be configuring
+	 * the GPIO alternate functions even if we're not using the gpiolib
+	 * driver for them.
+	 */
+	ret = wm8994_read(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
+			  &wm8994->gpio_regs);
+	if (ret < 0)
+		dev_err(dev, "Failed to save GPIO registers: %d\n", ret);
+
+	/* For similar reasons we also stash the regulator states */
+	ret = wm8994_read(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
+			  &wm8994->ldo_regs);
+	if (ret < 0)
+		dev_err(dev, "Failed to save LDO registers: %d\n", ret);
+
+	ret = regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
+				     wm8994->supplies);
+	if (ret != 0) {
+		dev_err(dev, "Failed to disable supplies: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int wm8994_device_resume(struct device *dev)
+{
+	struct wm8994 *wm8994 = dev_get_drvdata(dev);
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies),
+				    wm8994->supplies);
+	if (ret != 0) {
+		dev_err(dev, "Failed to enable supplies: %d\n", ret);
+		return ret;
+	}
+
+	ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
+			   &wm8994->ldo_regs);
+	if (ret < 0)
+		dev_err(dev, "Failed to restore LDO registers: %d\n", ret);
+
+	ret = wm8994_write(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
+			   &wm8994->gpio_regs);
+	if (ret < 0)
+		dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_REGULATOR
+static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
+{
+	struct wm8994_ldo_pdata *ldo_pdata;
+
+	if (!pdata)
+		return 0;
+
+	ldo_pdata = &pdata->ldo[ldo];
+
+	if (!ldo_pdata->init_data)
+		return 0;
+
+	return ldo_pdata->init_data->num_consumer_supplies != 0;
+}
+#else
+static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
+{
+	return 0;
+}
+#endif
+
+/*
+ * Instantiate the generic non-control parts of the device.
+ */
+static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
+{
+	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+	int ret, i;
+
+	mutex_init(&wm8994->io_lock);
+	dev_set_drvdata(wm8994->dev, wm8994);
+
+	/* Add the on-chip regulators first for bootstrapping */
+	ret = mfd_add_devices(wm8994->dev, -1,
+			      wm8994_regulator_devs,
+			      ARRAY_SIZE(wm8994_regulator_devs),
+			      NULL, 0);
+	if (ret != 0) {
+		dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
+		goto err;
+	}
+
+	wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
+				   ARRAY_SIZE(wm8994_main_supplies),
+				   GFP_KERNEL);
+	if (!wm8994->supplies)
+		goto err;
+
+	for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
+		wm8994->supplies[i].supply = wm8994_main_supplies[i];
+
+	ret = regulator_bulk_get(wm8994->dev, ARRAY_SIZE(wm8994_main_supplies),
+				 wm8994->supplies);
+	if (ret != 0) {
+		dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret);
+		goto err_supplies;
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies),
+				    wm8994->supplies);
+	if (ret != 0) {
+		dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret);
+		goto err_get;
+	}
+
+	ret = wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET);
+	if (ret < 0) {
+		dev_err(wm8994->dev, "Failed to read ID register\n");
+		goto err_enable;
+	}
+	if (ret != 0x8994) {
+		dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n",
+			ret);
+		ret = -EINVAL;
+		goto err_enable;
+	}
+
+	ret = wm8994_reg_read(wm8994, WM8994_CHIP_REVISION);
+	if (ret < 0) {
+		dev_err(wm8994->dev, "Failed to read revision register: %d\n",
+			ret);
+		goto err_enable;
+	}
+
+	switch (ret) {
+	case 0:
+	case 1:
+		dev_warn(wm8994->dev, "revision %c not fully supported\n",
+			'A' + ret);
+		break;
+	default:
+		dev_info(wm8994->dev, "revision %c\n", 'A' + ret);
+		break;
+	}
+
+
+	if (pdata) {
+		wm8994->gpio_base = pdata->gpio_base;
+
+		/* GPIO configuration is only applied if it's non-zero */
+		for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
+			if (pdata->gpio_defaults[i]) {
+				wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
+						0xffff,
+						pdata->gpio_defaults[i]);
+			}
+		}
+	}
+
+	/* In some system designs where the regulators are not in use,
+	 * we can achieve a small reduction in leakage currents by
+	 * floating LDO outputs.  This bit makes no difference if the
+	 * LDOs are enabled, it only affects cases where the LDOs were
+	 * in operation and are then disabled.
+	 */
+	for (i = 0; i < WM8994_NUM_LDO_REGS; i++) {
+		if (wm8994_ldo_in_use(pdata, i))
+			wm8994_set_bits(wm8994, WM8994_LDO_1 + i,
+					WM8994_LDO1_DISCH, WM8994_LDO1_DISCH);
+		else
+			wm8994_set_bits(wm8994, WM8994_LDO_1 + i,
+					WM8994_LDO1_DISCH, 0);
+	}
+
+	ret = mfd_add_devices(wm8994->dev, -1,
+			      wm8994_devs, ARRAY_SIZE(wm8994_devs),
+			      NULL, 0);
+	if (ret != 0) {
+		dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
+		goto err_enable;
+	}
+
+	return 0;
+
+err_enable:
+	regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
+			       wm8994->supplies);
+err_get:
+	regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
+err_supplies:
+	kfree(wm8994->supplies);
+err:
+	mfd_remove_devices(wm8994->dev);
+	kfree(wm8994);
+	return ret;
+}
+
+static void wm8994_device_exit(struct wm8994 *wm8994)
+{
+	mfd_remove_devices(wm8994->dev);
+	regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
+			       wm8994->supplies);
+	regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
+	kfree(wm8994->supplies);
+	kfree(wm8994);
+}
+
+static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg,
+				  int bytes, void *dest)
+{
+	struct i2c_client *i2c = wm8994->control_data;
+	int ret;
+	u16 r = cpu_to_be16(reg);
+
+	ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
+	if (ret < 0)
+		return ret;
+	if (ret != 2)
+		return -EIO;
+
+	ret = i2c_master_recv(i2c, dest, bytes);
+	if (ret < 0)
+		return ret;
+	if (ret != bytes)
+		return -EIO;
+	return 0;
+}
+
+/* Currently we allocate the write buffer on the stack; this is OK for
+ * small writes - if we need to do large writes this will need to be
+ * revised.
+ */
+static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg,
+				   int bytes, void *src)
+{
+	struct i2c_client *i2c = wm8994->control_data;
+	unsigned char msg[bytes + 2];
+	int ret;
+
+	reg = cpu_to_be16(reg);
+	memcpy(&msg[0], &reg, 2);
+	memcpy(&msg[2], src, bytes);
+
+	ret = i2c_master_send(i2c, msg, bytes + 2);
+	if (ret < 0)
+		return ret;
+	if (ret < bytes + 2)
+		return -EIO;
+
+	return 0;
+}
+
+static int wm8994_i2c_probe(struct i2c_client *i2c,
+			    const struct i2c_device_id *id)
+{
+	struct wm8994 *wm8994;
+
+	wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
+	if (wm8994 == NULL) {
+		kfree(i2c);
+		return -ENOMEM;
+	}
+
+	i2c_set_clientdata(i2c, wm8994);
+	wm8994->dev = &i2c->dev;
+	wm8994->control_data = i2c;
+	wm8994->read_dev = wm8994_i2c_read_device;
+	wm8994->write_dev = wm8994_i2c_write_device;
+
+	return wm8994_device_init(wm8994, id->driver_data, i2c->irq);
+}
+
+static int wm8994_i2c_remove(struct i2c_client *i2c)
+{
+	struct wm8994 *wm8994 = i2c_get_clientdata(i2c);
+
+	wm8994_device_exit(wm8994);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8994_i2c_suspend(struct i2c_client *i2c, pm_message_t state)
+{
+	return wm8994_device_suspend(&i2c->dev);
+}
+
+static int wm8994_i2c_resume(struct i2c_client *i2c)
+{
+	return wm8994_device_resume(&i2c->dev);
+}
+#else
+#define wm8994_i2c_suspend NULL
+#define wm8994_i2c_resume NULL
+#endif
+
+static const struct i2c_device_id wm8994_i2c_id[] = {
+	{ "wm8994", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
+
+static struct i2c_driver wm8994_i2c_driver = {
+	.driver = {
+		   .name = "wm8994",
+		   .owner = THIS_MODULE,
+	},
+	.probe = wm8994_i2c_probe,
+	.remove = wm8994_i2c_remove,
+	.suspend = wm8994_i2c_suspend,
+	.resume = wm8994_i2c_resume,
+	.id_table = wm8994_i2c_id,
+};
+
+static int __init wm8994_i2c_init(void)
+{
+	int ret;
+
+	ret = i2c_add_driver(&wm8994_i2c_driver);
+	if (ret != 0)
+		pr_err("Failed to register wm8994 I2C driver: %d\n", ret);
+
+	return ret;
+}
+module_init(wm8994_i2c_init);
+
+static void __exit wm8994_i2c_exit(void)
+{
+	i2c_del_driver(&wm8994_i2c_driver);
+}
+module_exit(wm8994_i2c_exit);
+
+MODULE_DESCRIPTION("Core support for the WM8994 audio CODEC");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index e3551d2..d16af6a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -212,6 +212,15 @@
 	  want to use a different IRQ by default.  This is here for
 	  architectures to set as necessary.
 
+config CS5535_CLOCK_EVENT_SRC
+	tristate "CS5535/CS5536 high-res timer (MFGPT) events"
+	depends on GENERIC_TIME && GENERIC_CLOCKEVENTS && CS5535_MFGPT
+	help
+	  This driver provides a clock event source based on the MFGPT
+	  timer(s) in the CS5535 and CS5536 companion chips.
+	  MFGPTs have a better resolution and max interval than the
+	  generic PIT, and are suitable for use as high-res timers.
+
 config HP_ILO
 	tristate "Channel interface driver for HP iLO/iLO2 processor"
 	depends on PCI
diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c
index dd0a391..3b7292a 100644
--- a/drivers/misc/iwmc3200top/main.c
+++ b/drivers/misc/iwmc3200top/main.c
@@ -597,8 +597,6 @@
 	struct iwmct_work_struct *read_req;
 	struct iwmct_priv *priv = sdio_get_drvdata(func);
 
-	priv = sdio_get_drvdata(func);
-
 	LOG_INFO(priv, INIT, "enter\n");
 
 	sdio_claim_host(func);
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 3648b23..4a06483 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -26,21 +26,9 @@
  * It is adapted from the Linux Kernel Dump Test Tool by
  * Fernando Luis Vazquez Cao <http://lkdtt.sourceforge.net>
  *
- * Usage :  insmod lkdtm.ko [recur_count={>0}] cpoint_name=<> cpoint_type=<>
- *							[cpoint_count={>0}]
+ * Debugfs support added by Simon Kagstrom <simon.kagstrom@netinsight.net>
  *
- * recur_count : Recursion level for the stack overflow test. Default is 10.
- *
- * cpoint_name : Crash point where the kernel is to be crashed. It can be
- *		 one of INT_HARDWARE_ENTRY, INT_HW_IRQ_EN, INT_TASKLET_ENTRY,
- *		 FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_DISPATCH_CMD,
- *		 IDE_CORE_CP
- *
- * cpoint_type : Indicates the action to be taken on hitting the crash point.
- *		 It can be one of PANIC, BUG, EXCEPTION, LOOP, OVERFLOW
- *
- * cpoint_count : Indicates the number of times the crash point is to be hit
- *		  to trigger an action. The default is 10.
+ * See Documentation/fault-injection/provoke-crashes.txt for instructions
  */
 
 #include <linux/kernel.h>
@@ -53,13 +41,12 @@
 #include <linux/interrupt.h>
 #include <linux/hrtimer.h>
 #include <scsi/scsi_cmnd.h>
+#include <linux/debugfs.h>
 
 #ifdef CONFIG_IDE
 #include <linux/ide.h>
 #endif
 
-#define NUM_CPOINTS 8
-#define NUM_CPOINT_TYPES 5
 #define DEFAULT_COUNT 10
 #define REC_NUM_DEFAULT 10
 
@@ -72,7 +59,8 @@
 	MEM_SWAPOUT,
 	TIMERADD,
 	SCSI_DISPATCH_CMD,
-	IDE_CORE_CP
+	IDE_CORE_CP,
+	DIRECT,
 };
 
 enum ctype {
@@ -81,7 +69,11 @@
 	BUG,
 	EXCEPTION,
 	LOOP,
-	OVERFLOW
+	OVERFLOW,
+	CORRUPT_STACK,
+	UNALIGNED_LOAD_STORE_WRITE,
+	OVERWRITE_ALLOCATION,
+	WRITE_AFTER_FREE,
 };
 
 static char* cp_name[] = {
@@ -92,7 +84,8 @@
 	"MEM_SWAPOUT",
 	"TIMERADD",
 	"SCSI_DISPATCH_CMD",
-	"IDE_CORE_CP"
+	"IDE_CORE_CP",
+	"DIRECT",
 };
 
 static char* cp_type[] = {
@@ -100,7 +93,11 @@
 	"BUG",
 	"EXCEPTION",
 	"LOOP",
-	"OVERFLOW"
+	"OVERFLOW",
+	"CORRUPT_STACK",
+	"UNALIGNED_LOAD_STORE_WRITE",
+	"OVERWRITE_ALLOCATION",
+	"WRITE_AFTER_FREE",
 };
 
 static struct jprobe lkdtm;
@@ -193,34 +190,66 @@
 }
 #endif
 
+/* Return the crashpoint number or NONE if the name is invalid */
+static enum ctype parse_cp_type(const char *what, size_t count)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cp_type); i++) {
+		if (!strcmp(what, cp_type[i]))
+			return i + 1;
+	}
+
+	return NONE;
+}
+
+static const char *cp_type_to_str(enum ctype type)
+{
+	if (type == NONE || type < 0 || type > ARRAY_SIZE(cp_type))
+		return "None";
+
+	return cp_type[type - 1];
+}
+
+static const char *cp_name_to_str(enum cname name)
+{
+	if (name == INVALID || name < 0 || name > ARRAY_SIZE(cp_name))
+		return "INVALID";
+
+	return cp_name[name - 1];
+}
+
+
 static int lkdtm_parse_commandline(void)
 {
 	int i;
 
-	if (cpoint_name == NULL || cpoint_type == NULL ||
-					cpoint_count < 1 || recur_count < 1)
+	if (cpoint_count < 1 || recur_count < 1)
 		return -EINVAL;
 
-	for (i = 0; i < NUM_CPOINTS; ++i) {
-		if (!strcmp(cpoint_name, cp_name[i])) {
-			cpoint = i + 1;
-			break;
-		}
-	}
-
-	for (i = 0; i < NUM_CPOINT_TYPES; ++i) {
-		if (!strcmp(cpoint_type, cp_type[i])) {
-			cptype = i + 1;
-			break;
-		}
-	}
-
-	if (cpoint == INVALID || cptype == NONE)
-                return -EINVAL;
-
 	count = cpoint_count;
 
-	return 0;
+	/* No special parameters */
+	if (!cpoint_type && !cpoint_name)
+		return 0;
+
+	/* Neither or both of these need to be set */
+	if (!cpoint_type || !cpoint_name)
+		return -EINVAL;
+
+	cptype = parse_cp_type(cpoint_type, strlen(cpoint_type));
+	if (cptype == NONE)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(cp_name); i++) {
+		if (!strcmp(cpoint_name, cp_name[i])) {
+			cpoint = i + 1;
+			return 0;
+		}
+	}
+
+	/* Could not find a valid crash point */
+	return -EINVAL;
 }
 
 static int recursive_loop(int a)
@@ -235,53 +264,92 @@
         	return recursive_loop(a);
 }
 
-void lkdtm_handler(void)
+static void lkdtm_do_action(enum ctype which)
 {
-	printk(KERN_INFO "lkdtm : Crash point %s of type %s hit\n",
-					 cpoint_name, cpoint_type);
-	--count;
+	switch (which) {
+	case PANIC:
+		panic("dumptest");
+		break;
+	case BUG:
+		BUG();
+		break;
+	case EXCEPTION:
+		*((int *) 0) = 0;
+		break;
+	case LOOP:
+		for (;;)
+			;
+		break;
+	case OVERFLOW:
+		(void) recursive_loop(0);
+		break;
+	case CORRUPT_STACK: {
+		volatile u32 data[8];
+		volatile u32 *p = data;
+
+		p[12] = 0x12345678;
+		break;
+	}
+	case UNALIGNED_LOAD_STORE_WRITE: {
+		static u8 data[5] __attribute__((aligned(4))) = {1, 2,
+				3, 4, 5};
+		u32 *p;
+		u32 val = 0x12345678;
+
+		p = (u32 *)(data + 1);
+		if (*p == 0)
+			val = 0x87654321;
+		*p = val;
+		 break;
+	}
+	case OVERWRITE_ALLOCATION: {
+		size_t len = 1020;
+		u32 *data = kmalloc(len, GFP_KERNEL);
+
+		data[1024 / sizeof(u32)] = 0x12345678;
+		kfree(data);
+		break;
+	}
+	case WRITE_AFTER_FREE: {
+		size_t len = 1024;
+		u32 *data = kmalloc(len, GFP_KERNEL);
+
+		kfree(data);
+		schedule();
+		memset(data, 0x78, len);
+		break;
+	}
+	case NONE:
+	default:
+		break;
+	}
+
+}
+
+static void lkdtm_handler(void)
+{
+	count--;
+	printk(KERN_INFO "lkdtm: Crash point %s of type %s hit, trigger in %d rounds\n",
+			cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
 
 	if (count == 0) {
-		switch (cptype) {
-		case NONE:
-			break;
-		case PANIC:
-			printk(KERN_INFO "lkdtm : PANIC\n");
-			panic("dumptest");
-			break;
-		case BUG:
-			printk(KERN_INFO "lkdtm : BUG\n");
-			BUG();
-			break;
-		case EXCEPTION:
-			printk(KERN_INFO "lkdtm : EXCEPTION\n");
-			*((int *) 0) = 0;
-			break;
-		case LOOP:
-			printk(KERN_INFO "lkdtm : LOOP\n");
-			for (;;);
-			break;
-		case OVERFLOW:
-			printk(KERN_INFO "lkdtm : OVERFLOW\n");
-			(void) recursive_loop(0);
-			break;
-		default:
-			break;
-		}
+		lkdtm_do_action(cptype);
 		count = cpoint_count;
 	}
 }
 
-static int __init lkdtm_module_init(void)
+static int lkdtm_register_cpoint(enum cname which)
 {
 	int ret;
 
-	if (lkdtm_parse_commandline() == -EINVAL) {
-		printk(KERN_INFO "lkdtm : Invalid command\n");
-		return -EINVAL;
-	}
+	cpoint = INVALID;
+	if (lkdtm.entry != NULL)
+		unregister_jprobe(&lkdtm);
 
-	switch (cpoint) {
+	switch (which) {
+	case DIRECT:
+		lkdtm_do_action(cptype);
+		return 0;
 	case INT_HARDWARE_ENTRY:
 		lkdtm.kp.symbol_name = "do_IRQ";
 		lkdtm.entry = (kprobe_opcode_t*) jp_do_irq;
@@ -315,28 +383,268 @@
 		lkdtm.kp.symbol_name = "generic_ide_ioctl";
 		lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl;
 #else
-		printk(KERN_INFO "lkdtm : Crash point not available\n");
+		printk(KERN_INFO "lkdtm: Crash point not available\n");
+		return -EINVAL;
 #endif
 		break;
 	default:
-		printk(KERN_INFO "lkdtm : Invalid Crash Point\n");
-		break;
+		printk(KERN_INFO "lkdtm: Invalid Crash Point\n");
+		return -EINVAL;
 	}
 
+	cpoint = which;
 	if ((ret = register_jprobe(&lkdtm)) < 0) {
-                printk(KERN_INFO "lkdtm : Couldn't register jprobe\n");
-                return ret;
+		printk(KERN_INFO "lkdtm: Couldn't register jprobe\n");
+		cpoint = INVALID;
 	}
 
-	printk(KERN_INFO "lkdtm : Crash point %s of type %s registered\n",
-						cpoint_name, cpoint_type);
+	return ret;
+}
+
+static ssize_t do_register_entry(enum cname which, struct file *f,
+		const char __user *user_buf, size_t count, loff_t *off)
+{
+	char *buf;
+	int err;
+
+	if (count >= PAGE_SIZE)
+		return -EINVAL;
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	if (copy_from_user(buf, user_buf, count)) {
+		free_page((unsigned long) buf);
+		return -EFAULT;
+	}
+	/* NULL-terminate and remove enter */
+	buf[count] = '\0';
+	strim(buf);
+
+	cptype = parse_cp_type(buf, count);
+	free_page((unsigned long) buf);
+
+	if (cptype == NONE)
+		return -EINVAL;
+
+	err = lkdtm_register_cpoint(which);
+	if (err < 0)
+		return err;
+
+	*off += count;
+
+	return count;
+}
+
+/* Generic read callback that just prints out the available crash types */
+static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
+		size_t count, loff_t *off)
+{
+	char *buf;
+	int i, n, out;
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+
+	n = snprintf(buf, PAGE_SIZE, "Available crash types:\n");
+	for (i = 0; i < ARRAY_SIZE(cp_type); i++)
+		n += snprintf(buf + n, PAGE_SIZE - n, "%s\n", cp_type[i]);
+	buf[n] = '\0';
+
+	out = simple_read_from_buffer(user_buf, count, off,
+				      buf, n);
+	free_page((unsigned long) buf);
+
+	return out;
+}
+
+static int lkdtm_debugfs_open(struct inode *inode, struct file *file)
+{
 	return 0;
 }
 
+
+static ssize_t int_hardware_entry(struct file *f, const char __user *buf,
+		size_t count, loff_t *off)
+{
+	return do_register_entry(INT_HARDWARE_ENTRY, f, buf, count, off);
+}
+
+static ssize_t int_hw_irq_en(struct file *f, const char __user *buf,
+		size_t count, loff_t *off)
+{
+	return do_register_entry(INT_HW_IRQ_EN, f, buf, count, off);
+}
+
+static ssize_t int_tasklet_entry(struct file *f, const char __user *buf,
+		size_t count, loff_t *off)
+{
+	return do_register_entry(INT_TASKLET_ENTRY, f, buf, count, off);
+}
+
+static ssize_t fs_devrw_entry(struct file *f, const char __user *buf,
+		size_t count, loff_t *off)
+{
+	return do_register_entry(FS_DEVRW, f, buf, count, off);
+}
+
+static ssize_t mem_swapout_entry(struct file *f, const char __user *buf,
+		size_t count, loff_t *off)
+{
+	return do_register_entry(MEM_SWAPOUT, f, buf, count, off);
+}
+
+static ssize_t timeradd_entry(struct file *f, const char __user *buf,
+		size_t count, loff_t *off)
+{
+	return do_register_entry(TIMERADD, f, buf, count, off);
+}
+
+static ssize_t scsi_dispatch_cmd_entry(struct file *f,
+		const char __user *buf, size_t count, loff_t *off)
+{
+	return do_register_entry(SCSI_DISPATCH_CMD, f, buf, count, off);
+}
+
+static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf,
+		size_t count, loff_t *off)
+{
+	return do_register_entry(IDE_CORE_CP, f, buf, count, off);
+}
+
+/* Special entry to just crash directly. Available without KPROBEs */
+static ssize_t direct_entry(struct file *f, const char __user *user_buf,
+		size_t count, loff_t *off)
+{
+	enum ctype type;
+	char *buf;
+
+	if (count >= PAGE_SIZE)
+		return -EINVAL;
+	if (count < 1)
+		return -EINVAL;
+
+	buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	if (copy_from_user(buf, user_buf, count)) {
+		free_page((unsigned long) buf);
+		return -EFAULT;
+	}
+	/* NULL-terminate and remove enter */
+	buf[count] = '\0';
+	strim(buf);
+
+	type = parse_cp_type(buf, count);
+	free_page((unsigned long) buf);
+	if (type == NONE)
+		return -EINVAL;
+
+	printk(KERN_INFO "lkdtm: Performing direct entry %s\n",
+			cp_type_to_str(type));
+	lkdtm_do_action(type);
+	*off += count;
+
+	return count;
+}
+
+struct crash_entry {
+	const char *name;
+	const struct file_operations fops;
+};
+
+static const struct crash_entry crash_entries[] = {
+	{"DIRECT", {.read = lkdtm_debugfs_read,
+			.open = lkdtm_debugfs_open,
+			.write = direct_entry} },
+	{"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read,
+			.open = lkdtm_debugfs_open,
+			.write = int_hardware_entry} },
+	{"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read,
+			.open = lkdtm_debugfs_open,
+			.write = int_hw_irq_en} },
+	{"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read,
+			.open = lkdtm_debugfs_open,
+			.write = int_tasklet_entry} },
+	{"FS_DEVRW", {.read = lkdtm_debugfs_read,
+			.open = lkdtm_debugfs_open,
+			.write = fs_devrw_entry} },
+	{"MEM_SWAPOUT", {.read = lkdtm_debugfs_read,
+			.open = lkdtm_debugfs_open,
+			.write = mem_swapout_entry} },
+	{"TIMERADD", {.read = lkdtm_debugfs_read,
+			.open = lkdtm_debugfs_open,
+			.write = timeradd_entry} },
+	{"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read,
+			.open = lkdtm_debugfs_open,
+			.write = scsi_dispatch_cmd_entry} },
+	{"IDE_CORE_CP",	{.read = lkdtm_debugfs_read,
+			.open = lkdtm_debugfs_open,
+			.write = ide_core_cp_entry} },
+};
+
+static struct dentry *lkdtm_debugfs_root;
+
+static int __init lkdtm_module_init(void)
+{
+	int ret = -EINVAL;
+	int n_debugfs_entries = 1; /* Assume only the direct entry */
+	int i;
+
+	/* Register debugfs interface */
+	lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
+	if (!lkdtm_debugfs_root) {
+		printk(KERN_ERR "lkdtm: creating root dir failed\n");
+		return -ENODEV;
+	}
+
+#ifdef CONFIG_KPROBES
+	n_debugfs_entries = ARRAY_SIZE(crash_entries);
+#endif
+
+	for (i = 0; i < n_debugfs_entries; i++) {
+		const struct crash_entry *cur = &crash_entries[i];
+		struct dentry *de;
+
+		de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root,
+				NULL, &cur->fops);
+		if (de == NULL) {
+			printk(KERN_ERR "lkdtm: could not create %s\n",
+					cur->name);
+			goto out_err;
+		}
+	}
+
+	if (lkdtm_parse_commandline() == -EINVAL) {
+		printk(KERN_INFO "lkdtm: Invalid command\n");
+		goto out_err;
+	}
+
+	if (cpoint != INVALID && cptype != NONE) {
+		ret = lkdtm_register_cpoint(cpoint);
+		if (ret < 0) {
+			printk(KERN_INFO "lkdtm: Invalid crash point %d\n",
+					cpoint);
+			goto out_err;
+		}
+		printk(KERN_INFO "lkdtm: Crash point %s of type %s registered\n",
+				cpoint_name, cpoint_type);
+	} else {
+		printk(KERN_INFO "lkdtm: No crash points registered, enable through debugfs\n");
+	}
+
+	return 0;
+
+out_err:
+	debugfs_remove_recursive(lkdtm_debugfs_root);
+	return ret;
+}
+
 static void __exit lkdtm_module_exit(void)
 {
-        unregister_jprobe(&lkdtm);
-        printk(KERN_INFO "lkdtm : Crash point unregistered\n");
+	debugfs_remove_recursive(lkdtm_debugfs_root);
+
+	unregister_jprobe(&lkdtm);
+	printk(KERN_INFO "lkdtm: Crash point unregistered\n");
 }
 
 module_init(lkdtm_module_init);
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 04c2726..779aa8e 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -497,12 +497,7 @@
 	.resume = phantom_resume
 };
 
-static ssize_t phantom_show_version(struct class *cls, char *buf)
-{
-	return sprintf(buf, PHANTOM_VERSION "\n");
-}
-
-static CLASS_ATTR(version, 0444, phantom_show_version, NULL);
+static CLASS_ATTR_STRING(version, 0444, PHANTOM_VERSION);
 
 static int __init phantom_init(void)
 {
@@ -515,7 +510,7 @@
 		printk(KERN_ERR "phantom: can't register phantom class\n");
 		goto err;
 	}
-	retval = class_create_file(phantom_class, &class_attr_version);
+	retval = class_create_file(phantom_class, &class_attr_version.attr);
 	if (retval) {
 		printk(KERN_ERR "phantom: can't create sysfs version file\n");
 		goto err_class;
@@ -541,7 +536,7 @@
 err_unchr:
 	unregister_chrdev_region(dev, PHANTOM_MAX_MINORS);
 err_attr:
-	class_remove_file(phantom_class, &class_attr_version);
+	class_remove_file(phantom_class, &class_attr_version.attr);
 err_class:
 	class_destroy(phantom_class);
 err:
@@ -554,7 +549,7 @@
 
 	unregister_chrdev_region(MKDEV(phantom_major, 0), PHANTOM_MAX_MINORS);
 
-	class_remove_file(phantom_class, &class_attr_version);
+	class_remove_file(phantom_class, &class_attr_version.attr);
 	class_destroy(phantom_class);
 
 	pr_debug("phantom: module successfully removed\n");
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h
index 02a77b8..7a8b906 100644
--- a/drivers/misc/sgi-gru/grutables.h
+++ b/drivers/misc/sgi-gru/grutables.h
@@ -516,8 +516,7 @@
 
 /* Scan all active GRUs in a GRU bitmap */
 #define for_each_gru_in_bitmap(gid, map)				\
-	for ((gid) = find_first_bit((map), GRU_MAX_GRUS); (gid) < GRU_MAX_GRUS;\
-		(gid)++, (gid) = find_next_bit((map), GRU_MAX_GRUS, (gid)))
+	for_each_set_bit((gid), (map), GRU_MAX_GRUS)
 
 /* Scan all active GRUs on a specific blade */
 #define for_each_gru_on_blade(gru, nid, i)				\
@@ -536,23 +535,17 @@
 
 /* Scan each CBR whose bit is set in a TFM (or copy of) */
 #define for_each_cbr_in_tfm(i, map)					\
-	for ((i) = find_first_bit(map, GRU_NUM_CBE);			\
-			(i) < GRU_NUM_CBE;				\
-			(i)++, (i) = find_next_bit(map, GRU_NUM_CBE, i))
+	for_each_set_bit((i), (map), GRU_NUM_CBE)
 
 /* Scan each CBR in a CBR bitmap. Note: multiple CBRs in an allocation unit */
 #define for_each_cbr_in_allocation_map(i, map, k)			\
-	for ((k) = find_first_bit(map, GRU_CBR_AU); (k) < GRU_CBR_AU;	\
-			(k) = find_next_bit(map, GRU_CBR_AU, (k) + 1)) 	\
+	for_each_set_bit((k), (map), GRU_CBR_AU)			\
 		for ((i) = (k)*GRU_CBR_AU_SIZE;				\
 				(i) < ((k) + 1) * GRU_CBR_AU_SIZE; (i)++)
 
 /* Scan each DSR in a DSR bitmap. Note: multiple DSRs in an allocation unit */
 #define for_each_dsr_in_allocation_map(i, map, k)			\
-	for ((k) = find_first_bit((const unsigned long *)map, GRU_DSR_AU);\
-			(k) < GRU_DSR_AU;				\
-			(k) = find_next_bit((const unsigned long *)map,	\
-					  GRU_DSR_AU, (k) + 1))		\
+	for_each_set_bit((k), (const unsigned long *)(map), GRU_DSR_AU)	\
 		for ((i) = (k) * GRU_DSR_AU_CL;				\
 				(i) < ((k) + 1) * GRU_DSR_AU_CL; (i)++)
 
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 16f0abd..57b152f 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -475,7 +475,7 @@
 
 	if (skb->data[0] == 0xff) {
 		/* we are being asked to broadcast to all partitions */
-		for_each_bit(dest_partid, xpnet_broadcast_partitions,
+		for_each_set_bit(dest_partid, xpnet_broadcast_partitions,
 			     xp_max_npartitions) {
 
 			xpnet_send(skb, queued_msg, start_addr, end_addr,
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index f537555..723e508 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -37,6 +37,7 @@
 #include <linux/gfp.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
+#include <linux/kfifo.h>
 
 #include <linux/mmc/core.h>
 #include <linux/mmc/card.h>
@@ -47,19 +48,9 @@
 #define UART_NR		8	/* Number of UARTs this driver can handle */
 
 
-#define UART_XMIT_SIZE	PAGE_SIZE
+#define FIFO_SIZE	PAGE_SIZE
 #define WAKEUP_CHARS	256
 
-#define circ_empty(circ)	((circ)->head == (circ)->tail)
-#define circ_clear(circ)	((circ)->head = (circ)->tail = 0)
-
-#define circ_chars_pending(circ) \
-		(CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-
-#define circ_chars_free(circ) \
-		(CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
-
-
 struct uart_icount {
 	__u32	cts;
 	__u32	dsr;
@@ -82,7 +73,7 @@
 	struct mutex		func_lock;
 	struct task_struct	*in_sdio_uart_irq;
 	unsigned int		regs_offset;
-	struct circ_buf		xmit;
+	struct kfifo		xmit_fifo;
 	spinlock_t		write_lock;
 	struct uart_icount	icount;
 	unsigned int		uartclk;
@@ -105,6 +96,8 @@
 	kref_init(&port->kref);
 	mutex_init(&port->func_lock);
 	spin_lock_init(&port->write_lock);
+	if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL))
+		return -ENOMEM;
 
 	spin_lock(&sdio_uart_table_lock);
 	for (index = 0; index < UART_NR; index++) {
@@ -140,6 +133,7 @@
 {
 	struct sdio_uart_port *port =
 		container_of(kref, struct sdio_uart_port, kref);
+	kfifo_free(&port->xmit_fifo);
 	kfree(port);
 }
 
@@ -456,9 +450,11 @@
 
 static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
 {
-	struct circ_buf *xmit = &port->xmit;
+	struct kfifo *xmit = &port->xmit_fifo;
 	int count;
 	struct tty_struct *tty;
+	u8 iobuf[16];
+	int len;
 
 	if (port->x_char) {
 		sdio_out(port, UART_TX, port->x_char);
@@ -469,27 +465,25 @@
 
 	tty = tty_port_tty_get(&port->port);
 
-	if (tty == NULL || circ_empty(xmit) ||
+	if (tty == NULL || !kfifo_len(xmit) ||
 				tty->stopped || tty->hw_stopped) {
 		sdio_uart_stop_tx(port);
 		tty_kref_put(tty);
 		return;
 	}
 
-	count = 16;
-	do {
-		sdio_out(port, UART_TX, xmit->buf[xmit->tail]);
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+	len = kfifo_out_locked(xmit, iobuf, 16, &port->write_lock);
+	for (count = 0; count < len; count++) {
+		sdio_out(port, UART_TX, iobuf[count]);
 		port->icount.tx++;
-		if (circ_empty(xmit))
-			break;
-	} while (--count > 0);
+	}
 
-	if (circ_chars_pending(xmit) < WAKEUP_CHARS)
+	len = kfifo_len(xmit);
+	if (len < WAKEUP_CHARS) {
 		tty_wakeup(tty);
-
-	if (circ_empty(xmit))
-		sdio_uart_stop_tx(port);
+		if (len == 0)
+			sdio_uart_stop_tx(port);
+	}
 	tty_kref_put(tty);
 }
 
@@ -581,7 +575,7 @@
 	struct sdio_uart_port *port =
 			container_of(tport, struct sdio_uart_port, port);
 	unsigned int ret = sdio_uart_claim_func(port);
-	if (ret)	/* Missing hardware shoudn't block for carrier */
+	if (ret)	/* Missing hardware shouldn't block for carrier */
 		return 1;
 	ret = sdio_uart_get_mctrl(port);
 	sdio_uart_release_func(port);
@@ -632,7 +626,6 @@
 {
 	struct sdio_uart_port *port =
 			container_of(tport, struct sdio_uart_port, port);
-	unsigned long page;
 	int ret;
 
 	/*
@@ -641,22 +634,17 @@
 	 */
 	set_bit(TTY_IO_ERROR, &tty->flags);
 
-	/* Initialise and allocate the transmit buffer. */
-	page = __get_free_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-	port->xmit.buf = (unsigned char *)page;
-	circ_clear(&port->xmit);
+	kfifo_reset(&port->xmit_fifo);
 
 	ret = sdio_uart_claim_func(port);
 	if (ret)
-		goto err1;
+		return ret;
 	ret = sdio_enable_func(port->func);
 	if (ret)
-		goto err2;
+		goto err1;
 	ret = sdio_claim_irq(port->func, sdio_uart_irq);
 	if (ret)
-		goto err3;
+		goto err2;
 
 	/*
 	 * Clear the FIFO buffers and disable them.
@@ -700,12 +688,10 @@
 	sdio_uart_release_func(port);
 	return 0;
 
-err3:
-	sdio_disable_func(port->func);
 err2:
-	sdio_uart_release_func(port);
+	sdio_disable_func(port->func);
 err1:
-	free_page((unsigned long)port->xmit.buf);
+	sdio_uart_release_func(port);
 	return ret;
 }
 
@@ -727,7 +713,7 @@
 
 	ret = sdio_uart_claim_func(port);
 	if (ret)
-		goto skip;
+		return;
 
 	sdio_uart_stop_rx(port);
 
@@ -749,10 +735,6 @@
 	sdio_disable_func(port->func);
 
 	sdio_uart_release_func(port);
-
-skip:
-	/* Free the transmit buffer page. */
-	free_page((unsigned long)port->xmit.buf);
 }
 
 /**
@@ -822,27 +804,12 @@
 			   int count)
 {
 	struct sdio_uart_port *port = tty->driver_data;
-	struct circ_buf *circ = &port->xmit;
-	int c, ret = 0;
+	int ret;
 
 	if (!port->func)
 		return -ENODEV;
 
-	spin_lock(&port->write_lock);
-	while (1) {
-		c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
-		if (count < c)
-			c = count;
-		if (c <= 0)
-			break;
-		memcpy(circ->buf + circ->head, buf, c);
-		circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1);
-		buf += c;
-		count -= c;
-		ret += c;
-	}
-	spin_unlock(&port->write_lock);
-
+	ret = kfifo_in_locked(&port->xmit_fifo, buf, count, &port->write_lock);
 	if (!(port->ier & UART_IER_THRI)) {
 		int err = sdio_uart_claim_func(port);
 		if (!err) {
@@ -859,13 +826,13 @@
 static int sdio_uart_write_room(struct tty_struct *tty)
 {
 	struct sdio_uart_port *port = tty->driver_data;
-	return port ? circ_chars_free(&port->xmit) : 0;
+	return FIFO_SIZE - kfifo_len(&port->xmit_fifo);
 }
 
 static int sdio_uart_chars_in_buffer(struct tty_struct *tty)
 {
 	struct sdio_uart_port *port = tty->driver_data;
-	return port ? circ_chars_pending(&port->xmit) : 0;
+	return kfifo_len(&port->xmit_fifo);
 }
 
 static void sdio_uart_send_xchar(struct tty_struct *tty, char ch)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 30acd52..3168ebd 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1089,6 +1089,7 @@
 	mmc_claim_host(host);
 
 	mmc_power_up(host);
+	sdio_reset(host);
 	mmc_go_idle(host);
 
 	mmc_send_if_cond(host, host->ocr_avail);
@@ -1151,6 +1152,9 @@
 	cancel_delayed_work(&host->detect);
 	mmc_flush_scheduled_work();
 
+	/* clear pm flags now and let card drivers set them as needed */
+	host->pm_flags = 0;
+
 	mmc_bus_get(host);
 	if (host->bus_ops && !host->bus_dead) {
 		if (host->bus_ops->remove)
@@ -1273,12 +1277,13 @@
 			mmc_claim_host(host);
 			mmc_detach_bus(host);
 			mmc_release_host(host);
+			host->pm_flags = 0;
 			err = 0;
 		}
 	}
 	mmc_bus_put(host);
 
-	if (!err)
+	if (!err && !(host->pm_flags & MMC_PM_KEEP_POWER))
 		mmc_power_off(host);
 
 	return err;
@@ -1296,8 +1301,10 @@
 
 	mmc_bus_get(host);
 	if (host->bus_ops && !host->bus_dead) {
-		mmc_power_up(host);
-		mmc_select_voltage(host, host->ocr);
+		if (!(host->pm_flags & MMC_PM_KEEP_POWER)) {
+			mmc_power_up(host);
+			mmc_select_voltage(host, host->ocr);
+		}
 		BUG_ON(!host->bus_ops->resume);
 		err = host->bus_ops->resume(host);
 		if (err) {
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 06b6408..2dd4cfe 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -188,6 +188,40 @@
 }
 
 /*
+ * Devices that remain active during a system suspend are
+ * put back into 1-bit mode.
+ */
+static int sdio_disable_wide(struct mmc_card *card)
+{
+	int ret;
+	u8 ctrl;
+
+	if (!(card->host->caps & MMC_CAP_4_BIT_DATA))
+		return 0;
+
+	if (card->cccr.low_speed && !card->cccr.wide_bus)
+		return 0;
+
+	ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
+	if (ret)
+		return ret;
+
+	if (!(ctrl & SDIO_BUS_WIDTH_4BIT))
+		return 0;
+
+	ctrl &= ~SDIO_BUS_WIDTH_4BIT;
+	ctrl |= SDIO_BUS_ASYNC_INT;
+
+	ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
+	if (ret)
+		return ret;
+
+	mmc_set_bus_width(card->host, MMC_BUS_WIDTH_1);
+
+	return 0;
+}
+
+/*
  * Test if the card supports high-speed mode and, if so, switch to it.
  */
 static int sdio_enable_hs(struct mmc_card *card)
@@ -224,7 +258,7 @@
  * we're trying to reinitialise.
  */
 static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
-			      struct mmc_card *oldcard)
+			      struct mmc_card *oldcard, int powered_resume)
 {
 	struct mmc_card *card;
 	int err;
@@ -235,9 +269,11 @@
 	/*
 	 * Inform the card of the voltage
 	 */
-	err = mmc_send_io_op_cond(host, host->ocr, &ocr);
-	if (err)
-		goto err;
+	if (!powered_resume) {
+		err = mmc_send_io_op_cond(host, host->ocr, &ocr);
+		if (err)
+			goto err;
+	}
 
 	/*
 	 * For SPI, enable CRC as appropriate.
@@ -262,7 +298,7 @@
 	/*
 	 * For native busses:  set card RCA and quit open drain mode.
 	 */
-	if (!mmc_host_is_spi(host)) {
+	if (!powered_resume && !mmc_host_is_spi(host)) {
 		err = mmc_send_relative_addr(host, &card->rca);
 		if (err)
 			goto remove;
@@ -273,7 +309,7 @@
 	/*
 	 * Select card, as all following commands rely on that.
 	 */
-	if (!mmc_host_is_spi(host)) {
+	if (!powered_resume && !mmc_host_is_spi(host)) {
 		err = mmc_select_card(card);
 		if (err)
 			goto remove;
@@ -425,6 +461,12 @@
 		}
 	}
 
+	if (!err && host->pm_flags & MMC_PM_KEEP_POWER) {
+		mmc_claim_host(host);
+		sdio_disable_wide(host->card);
+		mmc_release_host(host);
+	}
+
 	return err;
 }
 
@@ -437,7 +479,13 @@
 
 	/* Basic card reinitialization. */
 	mmc_claim_host(host);
-	err = mmc_sdio_init_card(host, host->ocr, host->card);
+	err = mmc_sdio_init_card(host, host->ocr, host->card,
+				 (host->pm_flags & MMC_PM_KEEP_POWER));
+	if (!err)
+		/* We may have switched to 1-bit mode during suspend. */
+		err = sdio_enable_wide(host->card);
+	if (!err && host->sdio_irqs)
+		mmc_signal_sdio_irq(host);
 	mmc_release_host(host);
 
 	/*
@@ -507,7 +555,7 @@
 	/*
 	 * Detect and init the card.
 	 */
-	err = mmc_sdio_init_card(host, host->ocr, NULL);
+	err = mmc_sdio_init_card(host, host->ocr, NULL, 0);
 	if (err)
 		goto err;
 	card = host->card;
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index f9aa8a7..ff27c8c 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -189,7 +189,12 @@
 {
 	unsigned mval =	min(func->card->host->max_seg_size,
 			    func->card->host->max_blk_size);
-	mval = min(mval, func->max_blksize);
+
+	if (mmc_blksz_for_byte_mode(func->card))
+		mval = min(mval, func->cur_blksize);
+	else
+		mval = min(mval, func->max_blksize);
+
 	return min(mval, 512u); /* maximum size for byte mode */
 }
 
@@ -635,3 +640,52 @@
 		*err_ret = ret;
 }
 EXPORT_SYMBOL_GPL(sdio_f0_writeb);
+
+/**
+ *	sdio_get_host_pm_caps - get host power management capabilities
+ *	@func: SDIO function attached to host
+ *
+ *	Returns a capability bitmask corresponding to power management
+ *	features supported by the host controller that the card function
+ *	might rely upon during a system suspend.  The host doesn't need
+ *	to be claimed, nor the function active, for this information to be
+ *	obtained.
+ */
+mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func)
+{
+	BUG_ON(!func);
+	BUG_ON(!func->card);
+
+	return func->card->host->pm_caps;
+}
+EXPORT_SYMBOL_GPL(sdio_get_host_pm_caps);
+
+/**
+ *	sdio_set_host_pm_flags - set wanted host power management capabilities
+ *	@func: SDIO function attached to host
+ *
+ *	Set a capability bitmask corresponding to wanted host controller
+ *	power management features for the upcoming suspend state.
+ *	This must be called, if needed, each time the suspend method of
+ *	the function driver is called, and must contain only bits that
+ *	were returned by sdio_get_host_pm_caps().
+ *	The host doesn't need to be claimed, nor the function active,
+ *	for this information to be set.
+ */
+int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags)
+{
+	struct mmc_host *host;
+
+	BUG_ON(!func);
+	BUG_ON(!func->card);
+
+	host = func->card->host;
+
+	if (flags & ~host->pm_caps)
+		return -EINVAL;
+
+	/* function suspend methods are serialized, hence no lock needed */
+	host->pm_flags |= flags;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sdio_set_host_pm_flags);
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c
index 4eb7825f..dea36d9 100644
--- a/drivers/mmc/core/sdio_ops.c
+++ b/drivers/mmc/core/sdio_ops.c
@@ -67,13 +67,13 @@
 	return err;
 }
 
-int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
-	unsigned addr, u8 in, u8* out)
+static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn,
+	unsigned addr, u8 in, u8 *out)
 {
 	struct mmc_command cmd;
 	int err;
 
-	BUG_ON(!card);
+	BUG_ON(!host);
 	BUG_ON(fn > 7);
 
 	/* sanity check */
@@ -90,11 +90,11 @@
 	cmd.arg |= in;
 	cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;
 
-	err = mmc_wait_for_cmd(card->host, &cmd, 0);
+	err = mmc_wait_for_cmd(host, &cmd, 0);
 	if (err)
 		return err;
 
-	if (mmc_host_is_spi(card->host)) {
+	if (mmc_host_is_spi(host)) {
 		/* host driver already reported errors */
 	} else {
 		if (cmd.resp[0] & R5_ERROR)
@@ -106,7 +106,7 @@
 	}
 
 	if (out) {
-		if (mmc_host_is_spi(card->host))
+		if (mmc_host_is_spi(host))
 			*out = (cmd.resp[0] >> 8) & 0xFF;
 		else
 			*out = cmd.resp[0] & 0xFF;
@@ -115,6 +115,13 @@
 	return 0;
 }
 
+int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,
+	unsigned addr, u8 in, u8 *out)
+{
+	BUG_ON(!card);
+	return mmc_io_rw_direct_host(card->host, write, fn, addr, in, out);
+}
+
 int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
 	unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
 {
@@ -182,3 +189,20 @@
 	return 0;
 }
 
+int sdio_reset(struct mmc_host *host)
+{
+	int ret;
+	u8 abort;
+
+	/* SDIO Simplified Specification V2.0, 4.4 Reset for SDIO */
+
+	ret = mmc_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort);
+	if (ret)
+		abort = 0x08;
+	else
+		abort |= 0x08;
+
+	ret = mmc_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL);
+	return ret;
+}
+
diff --git a/drivers/mmc/core/sdio_ops.h b/drivers/mmc/core/sdio_ops.h
index e2e74b0..12a4d3a 100644
--- a/drivers/mmc/core/sdio_ops.h
+++ b/drivers/mmc/core/sdio_ops.h
@@ -17,6 +17,7 @@
 	unsigned addr, u8 in, u8* out);
 int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
 	unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz);
+int sdio_reset(struct mmc_host *host);
 
 #endif
 
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index ce1d288..2e13b94 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -69,20 +69,16 @@
 	  If unsure, say N.
 
 config MMC_RICOH_MMC
-	tristate "Ricoh MMC Controller Disabler  (EXPERIMENTAL)"
+	bool "Ricoh MMC Controller Disabler  (EXPERIMENTAL)"
 	depends on MMC_SDHCI_PCI
 	help
-	  This selects the disabler for the Ricoh MMC Controller. This
+	  This adds a pci quirk to disable Ricoh MMC Controller. This
 	  proprietary controller is unnecessary because the SDHCI driver
 	  supports MMC cards on the SD controller, but if it is not
 	  disabled, it will steal the MMC cards away - rendering them
-	  useless. It is safe to select this driver even if you don't
+	  useless. It is safe to select this even if you don't
 	  have a Ricoh based card reader.
 
-
-	  To compile this driver as a module, choose M here:
-	  the module will be called ricoh_mmc.
-
 	  If unsure, say Y.
 
 config MMC_SDHCI_OF
@@ -193,6 +189,7 @@
 
 choice
 	prompt "Atmel SD/MMC Driver"
+	depends on AVR32 || ARCH_AT91
 	default MMC_ATMELMCI if AVR32
 	help
 	  Choose which driver to use for the Atmel MCI Silicon
@@ -368,7 +365,7 @@
 
 config MMC_TMIO
 	tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
-	depends on MFD_TMIO || MFD_ASIC3 || SUPERH
+	depends on MFD_TMIO || MFD_ASIC3 || MFD_SH_MOBILE_SDHI
 	help
 	  This provides support for the SD/MMC cell found in TC6393XB,
 	  T7L66XB and also HTC ASIC3
@@ -399,7 +396,7 @@
 
 config SDH_BFIN
 	tristate "Blackfin Secure Digital Host support"
-	depends on MMC && ((BF54x && !BF544) || (BF51x && !BF512))
+	depends on (BF54x && !BF544) || (BF51x && !BF512)
 	help
 	  If you say yes here you will get support for the Blackfin on-chip
 	  Secure Digital Host interface.  This includes support for MMC and
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3d253dd..f480397 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -12,7 +12,6 @@
 obj-$(CONFIG_MMC_MXC)		+= mxcmmc.o
 obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
-obj-$(CONFIG_MMC_RICOH_MMC)	+= ricoh_mmc.o
 obj-$(CONFIG_MMC_SDHCI_PLTFM)	+= sdhci-pltfm.o
 obj-$(CONFIG_MMC_SDHCI_S3C)	+= sdhci-s3c.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 63924e0..91dc60c 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -78,6 +78,17 @@
 
 #define DRIVER_NAME "at91_mci"
 
+static inline int at91mci_is_mci1rev2xx(void)
+{
+	return (   cpu_is_at91sam9260()
+		|| cpu_is_at91sam9263()
+		|| cpu_is_at91cap9()
+		|| cpu_is_at91sam9rl()
+		|| cpu_is_at91sam9g10()
+		|| cpu_is_at91sam9g20()
+		);
+}
+
 #define FL_SENT_COMMAND	(1 << 0)
 #define FL_SENT_STOP	(1 << 1)
 
@@ -88,6 +99,10 @@
 #define at91_mci_read(host, reg)	__raw_readl((host)->baseaddr + (reg))
 #define at91_mci_write(host, reg, val)	__raw_writel((val), (host)->baseaddr + (reg))
 
+#define MCI_BLKSIZE 		512
+#define MCI_MAXBLKSIZE 		4095
+#define MCI_BLKATONCE 		256
+#define MCI_BUFSIZE 		(MCI_BLKSIZE * MCI_BLKATONCE)
 
 /*
  * Low level type for this driver
@@ -200,8 +215,8 @@
 	size = data->blksz * data->blocks;
 	len = data->sg_len;
 
-	/* AT91SAM926[0/3] Data Write Operation and number of bytes erratum */
-	if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+	/* MCI1 rev2xx Data Write Operation and number of bytes erratum */
+	if (at91mci_is_mci1rev2xx())
 		if (host->total_length == 12)
 			memset(dmabuf, 0, 12);
 
@@ -227,8 +242,10 @@
 			for (index = 0; index < (amount / 4); index++)
 				*dmabuf++ = swab32(sgbuffer[index]);
 		} else {
-			memcpy(dmabuf, sgbuffer, amount);
-			dmabuf += amount;
+			char *tmpv = (char *)dmabuf;
+			memcpy(tmpv, sgbuffer, amount);
+			tmpv += amount;
+			dmabuf = (unsigned *)tmpv;
 		}
 
 		kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
@@ -245,80 +262,14 @@
 }
 
 /*
- * Prepare a dma read
- */
-static void at91_mci_pre_dma_read(struct at91mci_host *host)
-{
-	int i;
-	struct scatterlist *sg;
-	struct mmc_command *cmd;
-	struct mmc_data *data;
-
-	pr_debug("pre dma read\n");
-
-	cmd = host->cmd;
-	if (!cmd) {
-		pr_debug("no command\n");
-		return;
-	}
-
-	data = cmd->data;
-	if (!data) {
-		pr_debug("no data\n");
-		return;
-	}
-
-	for (i = 0; i < 2; i++) {
-		/* nothing left to transfer */
-		if (host->transfer_index >= data->sg_len) {
-			pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index);
-			break;
-		}
-
-		/* Check to see if this needs filling */
-		if (i == 0) {
-			if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
-				pr_debug("Transfer active in current\n");
-				continue;
-			}
-		}
-		else {
-			if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
-				pr_debug("Transfer active in next\n");
-				continue;
-			}
-		}
-
-		/* Setup the next transfer */
-		pr_debug("Using transfer index %d\n", host->transfer_index);
-
-		sg = &data->sg[host->transfer_index++];
-		pr_debug("sg = %p\n", sg);
-
-		sg->dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE);
-
-		pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
-
-		if (i == 0) {
-			at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
-			at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
-		}
-		else {
-			at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
-			at91_mci_write(host, ATMEL_PDC_RNCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
-		}
-	}
-
-	pr_debug("pre dma read done\n");
-}
-
-/*
  * Handle after a dma read
  */
 static void at91_mci_post_dma_read(struct at91mci_host *host)
 {
 	struct mmc_command *cmd;
 	struct mmc_data *data;
+	unsigned int len, i, size;
+	unsigned *dmabuf = host->buffer;
 
 	pr_debug("post dma read\n");
 
@@ -334,42 +285,39 @@
 		return;
 	}
 
-	while (host->in_use_index < host->transfer_index) {
+	size = data->blksz * data->blocks;
+	len = data->sg_len;
+
+	at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
+	at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
+
+	for (i = 0; i < len; i++) {
 		struct scatterlist *sg;
+		int amount;
+		unsigned int *sgbuffer;
 
-		pr_debug("finishing index %d\n", host->in_use_index);
+		sg = &data->sg[i];
 
-		sg = &data->sg[host->in_use_index++];
-
-		pr_debug("Unmapping page %08X\n", sg->dma_address);
-
-		dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
+		sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
+		amount = min(size, sg->length);
+		size -= amount;
 
 		if (cpu_is_at91rm9200()) {	/* AT91RM9200 errata */
-			unsigned int *buffer;
 			int index;
-
-			/* Swap the contents of the buffer */
-			buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
-			pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
-
-			for (index = 0; index < (sg->length / 4); index++)
-				buffer[index] = swab32(buffer[index]);
-
-			kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
+			for (index = 0; index < (amount / 4); index++)
+				sgbuffer[index] = swab32(*dmabuf++);
+		} else {
+			char *tmpv = (char *)dmabuf;
+			memcpy(sgbuffer, tmpv, amount);
+			tmpv += amount;
+			dmabuf = (unsigned *)tmpv;
 		}
 
-		flush_dcache_page(sg_page(sg));
-
-		data->bytes_xfered += sg->length;
-	}
-
-	/* Is there another transfer to trigger? */
-	if (host->transfer_index < data->sg_len)
-		at91_mci_pre_dma_read(host);
-	else {
-		at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
-		at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
+		kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
+		dmac_flush_range((void *)sgbuffer, ((void *)sgbuffer) + amount);
+		data->bytes_xfered += amount;
+		if (size == 0)
+			break;
 	}
 
 	pr_debug("post dma read done\n");
@@ -461,7 +409,7 @@
 	at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
 	mr = AT91_MCI_PDCMODE | 0x34a;
 
-	if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+	if (at91mci_is_mci1rev2xx())
 		mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
 
 	at91_mci_write(host, AT91_MCI_MR, mr);
@@ -602,10 +550,14 @@
 				/*
 				 * Handle a read
 				 */
-				host->buffer = NULL;
 				host->total_length = 0;
 
-				at91_mci_pre_dma_read(host);
+				at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address);
+				at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ?
+					(blocks * block_length) : (blocks * block_length) / 4);
+				at91_mci_write(host, ATMEL_PDC_RNPR, 0);
+				at91_mci_write(host, ATMEL_PDC_RNCR, 0);
+
 				ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
 			}
 			else {
@@ -614,27 +566,15 @@
 				 */
 				host->total_length = block_length * blocks;
 				/*
-				 * AT91SAM926[0/3] Data Write Operation and
+				 * MCI1 rev2xx Data Write Operation and
 				 * number of bytes erratum
 				 */
-				if (cpu_is_at91sam9260 () || cpu_is_at91sam9263())
+				if (at91mci_is_mci1rev2xx())
 					if (host->total_length < 12)
 						host->total_length = 12;
 
-				host->buffer = kmalloc(host->total_length, GFP_KERNEL);
-				if (!host->buffer) {
-					pr_debug("Can't alloc tx buffer\n");
-					cmd->error = -ENOMEM;
-					mmc_request_done(host->mmc, host->request);
-					return;
-				}
-
 				at91_mci_sg_to_dma(host, data);
 
-				host->physical_address = dma_map_single(NULL,
-						host->buffer, host->total_length,
-						DMA_TO_DEVICE);
-
 				pr_debug("Transmitting %d bytes\n", host->total_length);
 
 				at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
@@ -701,14 +641,6 @@
 	cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
 	cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
 
-	if (host->buffer) {
-		dma_unmap_single(NULL,
-				host->physical_address, host->total_length,
-				DMA_TO_DEVICE);
-		kfree(host->buffer);
-		host->buffer = NULL;
-	}
-
 	pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
 		 status, at91_mci_read(host, AT91_MCI_SR),
 		 cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
@@ -754,7 +686,8 @@
 	host->request = mrq;
 	host->flags = 0;
 
-	mod_timer(&host->timer, jiffies +  HZ);
+	/* more than 1s timeout needed with slow SD cards */
+	mod_timer(&host->timer, jiffies +  msecs_to_jiffies(2000));
 
 	at91_mci_process_next(host);
 }
@@ -942,7 +875,8 @@
 			pr_debug("****** Resetting SD-card bus width ******\n");
 			at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
 		}
-		mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+		/* 0.5s needed because of early card detect switch firing */
+		mmc_detect_change(host->mmc, msecs_to_jiffies(500));
 	}
 	return IRQ_HANDLED;
 }
@@ -1006,24 +940,42 @@
 	mmc->f_min = 375000;
 	mmc->f_max = 25000000;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-	mmc->caps = MMC_CAP_SDIO_IRQ;
+	mmc->caps = 0;
 
-	mmc->max_blk_size = 4095;
-	mmc->max_blk_count = mmc->max_req_size;
+	mmc->max_blk_size  = MCI_MAXBLKSIZE;
+	mmc->max_blk_count = MCI_BLKATONCE;
+	mmc->max_req_size  = MCI_BUFSIZE;
+	mmc->max_phys_segs = MCI_BLKATONCE;
+	mmc->max_hw_segs   = MCI_BLKATONCE;
+	mmc->max_seg_size  = MCI_BUFSIZE;
 
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
-	host->buffer = NULL;
 	host->bus_mode = 0;
 	host->board = pdev->dev.platform_data;
 	if (host->board->wire4) {
-		if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+		if (at91mci_is_mci1rev2xx())
 			mmc->caps |= MMC_CAP_4_BIT_DATA;
 		else
 			dev_warn(&pdev->dev, "4 wire bus mode not supported"
 				" - using 1 wire\n");
 	}
 
+	host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE,
+					&host->physical_address, GFP_KERNEL);
+	if (!host->buffer) {
+		ret = -ENOMEM;
+		dev_err(&pdev->dev, "Can't allocate transmit buffer\n");
+		goto fail5;
+	}
+
+	/* Add SDIO capability when available */
+	if (at91mci_is_mci1rev2xx()) {
+		/* at91mci MCI1 rev2xx sdio interrupt erratum */
+		if (host->board->wire4 || !host->board->slot_b)
+			mmc->caps |= MMC_CAP_SDIO_IRQ;
+	}
+
 	/*
 	 * Reserve GPIOs ... board init code makes sure these pins are set
 	 * up as GPIOs with the right direction (input, except for vcc)
@@ -1032,7 +984,7 @@
 		ret = gpio_request(host->board->det_pin, "mmc_detect");
 		if (ret < 0) {
 			dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
-			goto fail5;
+			goto fail4b;
 		}
 	}
 	if (host->board->wp_pin) {
@@ -1132,6 +1084,10 @@
 fail4:
 	if (host->board->det_pin)
 		gpio_free(host->board->det_pin);
+fail4b:
+	if (host->buffer)
+		dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
+				host->buffer, host->physical_address);
 fail5:
 	mmc_free_host(mmc);
 fail6:
@@ -1154,6 +1110,10 @@
 
 	host = mmc_priv(mmc);
 
+	if (host->buffer)
+		dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
+				host->buffer, host->physical_address);
+
 	if (host->board->det_pin) {
 		if (device_can_wakeup(&pdev->dev))
 			free_irq(gpio_to_irq(host->board->det_pin), host);
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c
index 3343a57..56f7b44 100644
--- a/drivers/mmc/host/bfin_sdh.c
+++ b/drivers/mmc/host/bfin_sdh.c
@@ -115,7 +115,7 @@
 	unsigned int length;
 	unsigned int data_ctl;
 	unsigned int dma_cfg;
-	struct scatterlist *sg;
+	unsigned int cycle_ns, timeout;
 
 	dev_dbg(mmc_dev(host->mmc), "%s enter flags: 0x%x\n", __func__, data->flags);
 	host->data = data;
@@ -136,8 +136,11 @@
 	data_ctl |= ((ffs(data->blksz) - 1) << 4);
 
 	bfin_write_SDH_DATA_CTL(data_ctl);
-
-	bfin_write_SDH_DATA_TIMER(0xFFFF);
+	/* the time of a host clock period in ns */
+	cycle_ns = 1000000000 / (get_sclk() / (2 * (host->clk_div + 1)));
+	timeout = data->timeout_ns / cycle_ns;
+	timeout += data->timeout_clks;
+	bfin_write_SDH_DATA_TIMER(timeout);
 	SSYNC();
 
 	if (data->flags & MMC_DATA_READ) {
@@ -151,6 +154,7 @@
 #if defined(CONFIG_BF54x)
 	dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN;
 	{
+		struct scatterlist *sg;
 		int i;
 		for_each_sg(data->sg, sg, host->dma_len, i) {
 			host->sg_cpu[i].start_addr = sg_dma_address(sg);
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index dd45e7c3..3bd0ba2 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -73,6 +73,7 @@
 /* DAVINCI_MMCCTL definitions */
 #define MMCCTL_DATRST         (1 << 0)
 #define MMCCTL_CMDRST         (1 << 1)
+#define MMCCTL_WIDTH_8_BIT    (1 << 8)
 #define MMCCTL_WIDTH_4_BIT    (1 << 2)
 #define MMCCTL_DATEG_DISABLED (0 << 6)
 #define MMCCTL_DATEG_RISING   (1 << 6)
@@ -791,22 +792,42 @@
 
 static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
-	unsigned int mmc_pclk = 0;
 	struct mmc_davinci_host *host = mmc_priv(mmc);
 
-	mmc_pclk = host->mmc_input_clk;
 	dev_dbg(mmc_dev(host->mmc),
 		"clock %dHz busmode %d powermode %d Vdd %04x\n",
 		ios->clock, ios->bus_mode, ios->power_mode,
 		ios->vdd);
-	if (ios->bus_width == MMC_BUS_WIDTH_4) {
+
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_8:
+		dev_dbg(mmc_dev(host->mmc), "Enabling 8 bit mode\n");
+		writel((readl(host->base + DAVINCI_MMCCTL) &
+			~MMCCTL_WIDTH_4_BIT) | MMCCTL_WIDTH_8_BIT,
+			host->base + DAVINCI_MMCCTL);
+		break;
+	case MMC_BUS_WIDTH_4:
 		dev_dbg(mmc_dev(host->mmc), "Enabling 4 bit mode\n");
-		writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_WIDTH_4_BIT,
-			host->base + DAVINCI_MMCCTL);
-	} else {
-		dev_dbg(mmc_dev(host->mmc), "Disabling 4 bit mode\n");
-		writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_WIDTH_4_BIT,
-			host->base + DAVINCI_MMCCTL);
+		if (host->version == MMC_CTLR_VERSION_2)
+			writel((readl(host->base + DAVINCI_MMCCTL) &
+				~MMCCTL_WIDTH_8_BIT) | MMCCTL_WIDTH_4_BIT,
+				host->base + DAVINCI_MMCCTL);
+		else
+			writel(readl(host->base + DAVINCI_MMCCTL) |
+				MMCCTL_WIDTH_4_BIT,
+				host->base + DAVINCI_MMCCTL);
+		break;
+	case MMC_BUS_WIDTH_1:
+		dev_dbg(mmc_dev(host->mmc), "Enabling 1 bit mode\n");
+		if (host->version == MMC_CTLR_VERSION_2)
+			writel(readl(host->base + DAVINCI_MMCCTL) &
+				~(MMCCTL_WIDTH_8_BIT | MMCCTL_WIDTH_4_BIT),
+				host->base + DAVINCI_MMCCTL);
+		else
+			writel(readl(host->base + DAVINCI_MMCCTL) &
+				~MMCCTL_WIDTH_4_BIT,
+				host->base + DAVINCI_MMCCTL);
+		break;
 	}
 
 	calculate_clk_divider(mmc, ios);
@@ -1189,10 +1210,14 @@
 
 	/* REVISIT:  someday, support IRQ-driven card detection.  */
 	mmc->caps |= MMC_CAP_NEEDS_POLL;
+	mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
 
-	if (!pdata || pdata->wires == 4 || pdata->wires == 0)
+	if (pdata && (pdata->wires == 4 || pdata->wires == 0))
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
 
+	if (pdata && (pdata->wires == 8))
+		mmc->caps |= (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA);
+
 	host->version = pdata->version;
 
 	mmc->ops = &mmc_davinci_ops;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index b31946e..4c068e5 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1250,9 +1250,7 @@
 
 		if (mmc->card && mmc->card->type != MMC_TYPE_SDIO)
 			mmc_resume_host(mmc);
-			if (host->stat_irq)
-				enable_irq(host->stat_irq);
-		else if (host->stat_irq)
+		if (host->stat_irq)
 			enable_irq(host->stat_irq);
 	}
 	return 0;
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 60a2b69..2df9041 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -4,7 +4,7 @@
  *  This is a driver for the SDHC controller found in Freescale MX2/MX3
  *  SoCs. It is basically the same hardware as found on MX1 (imxmmc.c).
  *  Unlike the hardware found on MX1, this hardware just works and does
- *  not need all the quirks found in imxmmc.c, hence the seperate driver.
+ *  not need all the quirks found in imxmmc.c, hence the separate driver.
  *
  *  Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
  *  Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
@@ -708,7 +708,7 @@
 	mmc->max_blk_size = 2048;
 	mmc->max_blk_count = 65535;
 	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-	mmc->max_seg_size = mmc->max_seg_size;
+	mmc->max_seg_size = mmc->max_req_size;
 
 	host = mmc_priv(mmc);
 	host->base = ioremap(r->start, resource_size(r));
diff --git a/drivers/mmc/host/ricoh_mmc.c b/drivers/mmc/host/ricoh_mmc.c
deleted file mode 100644
index f627905..0000000
--- a/drivers/mmc/host/ricoh_mmc.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- *  ricoh_mmc.c - Dummy driver to disable the Rioch MMC controller.
- *
- *  Copyright (C) 2007 Philip Langdale, 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 is a conceptually ridiculous driver, but it is required by the way
- * the Ricoh multi-function chips (R5CXXX) work. These chips implement
- * the four main memory card controllers (SD, MMC, MS, xD) and one or both
- * of cardbus or firewire. It happens that they implement SD and MMC
- * support as separate controllers (and PCI functions). The linux SDHCI
- * driver supports MMC cards but the chip detects MMC cards in hardware
- * and directs them to the MMC controller - so the SDHCI driver never sees
- * them. To get around this, we must disable the useless MMC controller.
- * At that point, the SDHCI controller will start seeing them. As a bonus,
- * a detection event occurs immediately, even if the MMC card is already
- * in the reader.
- *
- * It seems to be the case that the relevant PCI registers to deactivate the
- * MMC controller live on PCI function 0, which might be the cardbus controller
- * or the firewire controller, depending on the particular chip in question. As
- * such, it makes what this driver has to do unavoidably ugly. Such is life.
- */
-
-#include <linux/pci.h>
-
-#define DRIVER_NAME "ricoh-mmc"
-
-static const struct pci_device_id pci_ids[] __devinitdata = {
-	{
-		.vendor		= PCI_VENDOR_ID_RICOH,
-		.device		= PCI_DEVICE_ID_RICOH_R5C843,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-	},
-	{ /* end: all zeroes */ },
-};
-
-MODULE_DEVICE_TABLE(pci, pci_ids);
-
-static int ricoh_mmc_disable(struct pci_dev *fw_dev)
-{
-	u8 write_enable;
-	u8 write_target;
-	u8 disable;
-
-	if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) {
-		/* via RL5C476 */
-
-		pci_read_config_byte(fw_dev, 0xB7, &disable);
-		if (disable & 0x02) {
-			printk(KERN_INFO DRIVER_NAME
-				": Controller already disabled. " \
-				"Nothing to do.\n");
-			return -ENODEV;
-		}
-
-		pci_read_config_byte(fw_dev, 0x8E, &write_enable);
-		pci_write_config_byte(fw_dev, 0x8E, 0xAA);
-		pci_read_config_byte(fw_dev, 0x8D, &write_target);
-		pci_write_config_byte(fw_dev, 0x8D, 0xB7);
-		pci_write_config_byte(fw_dev, 0xB7, disable | 0x02);
-		pci_write_config_byte(fw_dev, 0x8E, write_enable);
-		pci_write_config_byte(fw_dev, 0x8D, write_target);
-	} else {
-		/* via R5C832 */
-
-		pci_read_config_byte(fw_dev, 0xCB, &disable);
-		if (disable & 0x02) {
-			printk(KERN_INFO DRIVER_NAME
-			       ": Controller already disabled. " \
-				"Nothing to do.\n");
-			return -ENODEV;
-		}
-
-		pci_read_config_byte(fw_dev, 0xCA, &write_enable);
-		pci_write_config_byte(fw_dev, 0xCA, 0x57);
-		pci_write_config_byte(fw_dev, 0xCB, disable | 0x02);
-		pci_write_config_byte(fw_dev, 0xCA, write_enable);
-	}
-
-	printk(KERN_INFO DRIVER_NAME
-	       ": Controller is now disabled.\n");
-
-	return 0;
-}
-
-static int ricoh_mmc_enable(struct pci_dev *fw_dev)
-{
-	u8 write_enable;
-	u8 write_target;
-	u8 disable;
-
-	if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) {
-		/* via RL5C476 */
-
-		pci_read_config_byte(fw_dev, 0x8E, &write_enable);
-		pci_write_config_byte(fw_dev, 0x8E, 0xAA);
-		pci_read_config_byte(fw_dev, 0x8D, &write_target);
-		pci_write_config_byte(fw_dev, 0x8D, 0xB7);
-		pci_read_config_byte(fw_dev, 0xB7, &disable);
-		pci_write_config_byte(fw_dev, 0xB7, disable & ~0x02);
-		pci_write_config_byte(fw_dev, 0x8E, write_enable);
-		pci_write_config_byte(fw_dev, 0x8D, write_target);
-	} else {
-		/* via R5C832 */
-
-		pci_read_config_byte(fw_dev, 0xCA, &write_enable);
-		pci_read_config_byte(fw_dev, 0xCB, &disable);
-		pci_write_config_byte(fw_dev, 0xCA, 0x57);
-		pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02);
-		pci_write_config_byte(fw_dev, 0xCA, write_enable);
-	}
-
-	printk(KERN_INFO DRIVER_NAME
-	       ": Controller is now re-enabled.\n");
-
-	return 0;
-}
-
-static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
-				     const struct pci_device_id *ent)
-{
-	u8 rev;
-	u8 ctrlfound = 0;
-
-	struct pci_dev *fw_dev = NULL;
-
-	BUG_ON(pdev == NULL);
-	BUG_ON(ent == NULL);
-
-	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
-
-	printk(KERN_INFO DRIVER_NAME
-		": Ricoh MMC controller found at %s [%04x:%04x] (rev %x)\n",
-		pci_name(pdev), (int)pdev->vendor, (int)pdev->device,
-		(int)rev);
-
-	while ((fw_dev =
-		pci_get_device(PCI_VENDOR_ID_RICOH,
-			PCI_DEVICE_ID_RICOH_RL5C476, fw_dev))) {
-		if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
-		    PCI_FUNC(fw_dev->devfn) == 0 &&
-		    pdev->bus == fw_dev->bus) {
-			if (ricoh_mmc_disable(fw_dev) != 0)
-				return -ENODEV;
-
-			pci_set_drvdata(pdev, fw_dev);
-
-			++ctrlfound;
-			break;
-		}
-	}
-
-	fw_dev = NULL;
-
-	while (!ctrlfound &&
-	    (fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH,
-					PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
-		if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
-		    PCI_FUNC(fw_dev->devfn) == 0 &&
-		    pdev->bus == fw_dev->bus) {
-			if (ricoh_mmc_disable(fw_dev) != 0)
-				return -ENODEV;
-
-			pci_set_drvdata(pdev, fw_dev);
-
-			++ctrlfound;
-		}
-	}
-
-	if (!ctrlfound) {
-		printk(KERN_WARNING DRIVER_NAME
-		       ": Main Ricoh function not found. Cannot disable controller.\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void __devexit ricoh_mmc_remove(struct pci_dev *pdev)
-{
-	struct pci_dev *fw_dev = NULL;
-
-	fw_dev = pci_get_drvdata(pdev);
-	BUG_ON(fw_dev == NULL);
-
-	ricoh_mmc_enable(fw_dev);
-
-	pci_set_drvdata(pdev, NULL);
-}
-
-static int ricoh_mmc_suspend_late(struct pci_dev *pdev, pm_message_t state)
-{
-	struct pci_dev *fw_dev = NULL;
-
-	fw_dev = pci_get_drvdata(pdev);
-	BUG_ON(fw_dev == NULL);
-
-	printk(KERN_INFO DRIVER_NAME ": Suspending.\n");
-
-	ricoh_mmc_enable(fw_dev);
-
-	return 0;
-}
-
-static int ricoh_mmc_resume_early(struct pci_dev *pdev)
-{
-	struct pci_dev *fw_dev = NULL;
-
-	fw_dev = pci_get_drvdata(pdev);
-	BUG_ON(fw_dev == NULL);
-
-	printk(KERN_INFO DRIVER_NAME ": Resuming.\n");
-
-	ricoh_mmc_disable(fw_dev);
-
-	return 0;
-}
-
-static struct pci_driver ricoh_mmc_driver = {
-	.name = 	DRIVER_NAME,
-	.id_table =	pci_ids,
-	.probe = 	ricoh_mmc_probe,
-	.remove =	__devexit_p(ricoh_mmc_remove),
-	.suspend_late =	ricoh_mmc_suspend_late,
-	.resume_early =	ricoh_mmc_resume_early,
-};
-
-/*****************************************************************************\
- *                                                                           *
- * Driver init/exit                                                          *
- *                                                                           *
-\*****************************************************************************/
-
-static int __init ricoh_mmc_drv_init(void)
-{
-	printk(KERN_INFO DRIVER_NAME
-		": Ricoh MMC Controller disabling driver\n");
-	printk(KERN_INFO DRIVER_NAME ": Copyright(c) Philip Langdale\n");
-
-	return pci_register_driver(&ricoh_mmc_driver);
-}
-
-static void __exit ricoh_mmc_drv_exit(void)
-{
-	pci_unregister_driver(&ricoh_mmc_driver);
-}
-
-module_init(ricoh_mmc_drv_init);
-module_exit(ricoh_mmc_drv_exit);
-
-MODULE_AUTHOR("Philip Langdale <philipl@alumni.utexas.net>");
-MODULE_DESCRIPTION("Ricoh MMC Controller disabling driver");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index d96e1ab..2fdf768 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1179,7 +1179,7 @@
 	struct s3c24xx_mci_pdata *pdata = host->pdata;
 	int ret;
 
-	if (pdata->gpio_detect == 0)
+	if (pdata->no_detect)
 		return -ENOSYS;
 
 	ret = gpio_get_value(pdata->gpio_detect) ? 0 : 1;
@@ -1360,6 +1360,8 @@
 static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
 	/* This is currently here to avoid a number of if (host->pdata)
 	 * checks. Any zero fields to ensure reasonable defaults are picked. */
+	 .no_wprotect = 1,
+	 .no_detect = 1,
 };
 
 #ifdef CONFIG_CPU_FREQ
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 5c3a176..8e1020c 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -80,9 +80,6 @@
 
 static int ricoh_probe(struct sdhci_pci_chip *chip)
 {
-	if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
-		chip->quirks |= SDHCI_QUIRK_CLOCK_BEFORE_RESET;
-
 	if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG ||
 	    chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SONY)
 		chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET;
@@ -92,7 +89,9 @@
 
 static const struct sdhci_pci_fixes sdhci_ricoh = {
 	.probe		= ricoh_probe,
-	.quirks		= SDHCI_QUIRK_32BIT_DMA_ADDR,
+	.quirks		= SDHCI_QUIRK_32BIT_DMA_ADDR |
+			  SDHCI_QUIRK_FORCE_DMA |
+			  SDHCI_QUIRK_CLOCK_BEFORE_RESET,
 };
 
 static const struct sdhci_pci_fixes sdhci_ene_712 = {
@@ -501,6 +500,7 @@
 {
 	struct sdhci_pci_chip *chip;
 	struct sdhci_pci_slot *slot;
+	mmc_pm_flag_t pm_flags = 0;
 	int i, ret;
 
 	chip = pci_get_drvdata(pdev);
@@ -519,6 +519,8 @@
 				sdhci_resume_host(chip->slots[i]->host);
 			return ret;
 		}
+
+		pm_flags |= slot->host->mmc->pm_flags;
 	}
 
 	if (chip->fixes && chip->fixes->suspend) {
@@ -531,9 +533,15 @@
 	}
 
 	pci_save_state(pdev);
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	if (pm_flags & MMC_PM_KEEP_POWER) {
+		if (pm_flags & MMC_PM_WAKE_SDIO_IRQ)
+			pci_enable_wake(pdev, PCI_D3hot, 1);
+		pci_set_power_state(pdev, PCI_D3hot);
+	} else {
+		pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+		pci_disable_device(pdev);
+		pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	}
 
 	return 0;
 }
@@ -653,6 +661,8 @@
 			goto unmap;
 	}
 
+	host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
+
 	ret = sdhci_add_host(host);
 	if (ret)
 		goto remove;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c279fbc..d6ab62d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -174,20 +174,31 @@
 		sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
 }
 
-static void sdhci_init(struct sdhci_host *host)
+static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
+
+static void sdhci_init(struct sdhci_host *host, int soft)
 {
-	sdhci_reset(host, SDHCI_RESET_ALL);
+	if (soft)
+		sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
+	else
+		sdhci_reset(host, SDHCI_RESET_ALL);
 
 	sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
 		SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
 		SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
 		SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
 		SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
+
+	if (soft) {
+		/* force clock reconfiguration */
+		host->clock = 0;
+		sdhci_set_ios(host->mmc, &host->mmc->ios);
+	}
 }
 
 static void sdhci_reinit(struct sdhci_host *host)
 {
-	sdhci_init(host);
+	sdhci_init(host, 0);
 	sdhci_enable_card_detection(host);
 }
 
@@ -376,6 +387,20 @@
 	local_irq_restore(*flags);
 }
 
+static void sdhci_set_adma_desc(u8 *desc, u32 addr, int len, unsigned cmd)
+{
+	__le32 *dataddr = (__le32 __force *)(desc + 4);
+	__le16 *cmdlen = (__le16 __force *)desc;
+
+	/* SDHCI specification says ADMA descriptors should be 4 byte
+	 * aligned, so using 16 or 32bit operations should be safe. */
+
+	cmdlen[0] = cpu_to_le16(cmd);
+	cmdlen[1] = cpu_to_le16(len);
+
+	dataddr[0] = cpu_to_le32(addr);
+}
+
 static int sdhci_adma_table_pre(struct sdhci_host *host,
 	struct mmc_data *data)
 {
@@ -443,19 +468,11 @@
 				sdhci_kunmap_atomic(buffer, &flags);
 			}
 
-			desc[7] = (align_addr >> 24) & 0xff;
-			desc[6] = (align_addr >> 16) & 0xff;
-			desc[5] = (align_addr >> 8) & 0xff;
-			desc[4] = (align_addr >> 0) & 0xff;
+			/* tran, valid */
+			sdhci_set_adma_desc(desc, align_addr, offset, 0x21);
 
 			BUG_ON(offset > 65536);
 
-			desc[3] = (offset >> 8) & 0xff;
-			desc[2] = (offset >> 0) & 0xff;
-
-			desc[1] = 0x00;
-			desc[0] = 0x21; /* tran, valid */
-
 			align += 4;
 			align_addr += 4;
 
@@ -465,19 +482,10 @@
 			len -= offset;
 		}
 
-		desc[7] = (addr >> 24) & 0xff;
-		desc[6] = (addr >> 16) & 0xff;
-		desc[5] = (addr >> 8) & 0xff;
-		desc[4] = (addr >> 0) & 0xff;
-
 		BUG_ON(len > 65536);
 
-		desc[3] = (len >> 8) & 0xff;
-		desc[2] = (len >> 0) & 0xff;
-
-		desc[1] = 0x00;
-		desc[0] = 0x21; /* tran, valid */
-
+		/* tran, valid */
+		sdhci_set_adma_desc(desc, addr, len, 0x21);
 		desc += 8;
 
 		/*
@@ -490,16 +498,9 @@
 	/*
 	 * Add a terminating entry.
 	 */
-	desc[7] = 0;
-	desc[6] = 0;
-	desc[5] = 0;
-	desc[4] = 0;
 
-	desc[3] = 0;
-	desc[2] = 0;
-
-	desc[1] = 0x00;
-	desc[0] = 0x03; /* nop, end, valid */
+	/* nop, end, valid */
+	sdhci_set_adma_desc(desc, 0, 0, 0x3);
 
 	/*
 	 * Resync align buffer as we might have changed it.
@@ -1610,16 +1611,13 @@
 	if (ret)
 		return ret;
 
-	sdhci_init(host);
+	sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
 	mmiowb();
 
 	ret = mmc_resume_host(host->mmc);
-	if (ret)
-		return ret;
-
 	sdhci_enable_card_detection(host);
 
-	return 0;
+	return ret;
 }
 
 EXPORT_SYMBOL_GPL(sdhci_resume_host);
@@ -1874,7 +1872,7 @@
 	if (ret)
 		goto untasklet;
 
-	sdhci_init(host);
+	sdhci_init(host, 0);
 
 #ifdef CONFIG_MMC_DEBUG
 	sdhci_dumpregs(host);
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index e22c3fa..b2b577f 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -323,7 +323,7 @@
 		if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
 			ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
 				TMIO_STAT_CARD_REMOVE);
-			mmc_detect_change(host->mmc, 0);
+			mmc_detect_change(host->mmc, msecs_to_jiffies(100));
 		}
 
 		/* CRC and other errors */
@@ -550,6 +550,7 @@
 
 	mmc->ops = &tmio_mmc_ops;
 	mmc->caps = MMC_CAP_4_BIT_DATA;
+	mmc->caps |= pdata->capabilities;
 	mmc->f_max = pdata->hclk;
 	mmc->f_min = mmc->f_max / 512;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
@@ -568,14 +569,14 @@
 	if (ret >= 0)
 		host->irq = ret;
 	else
-		goto unmap_ctl;
+		goto cell_disable;
 
 	disable_mmc_irqs(host, TMIO_MASK_ALL);
 
 	ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
 		IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
 	if (ret)
-		goto unmap_ctl;
+		goto cell_disable;
 
 	mmc_add_host(mmc);
 
@@ -587,6 +588,9 @@
 
 	return 0;
 
+cell_disable:
+	if (cell->disable)
+		cell->disable(dev);
 unmap_ctl:
 	iounmap(host->ctl);
 host_free:
@@ -597,6 +601,7 @@
 
 static int __devexit tmio_mmc_remove(struct platform_device *dev)
 {
+	struct mfd_cell	*cell = (struct mfd_cell *)dev->dev.platform_data;
 	struct mmc_host *mmc = platform_get_drvdata(dev);
 
 	platform_set_drvdata(dev, NULL);
@@ -605,6 +610,8 @@
 		struct tmio_mmc_host *host = mmc_priv(mmc);
 		mmc_remove_host(mmc);
 		free_irq(host->irq, host);
+		if (cell->disable)
+			cell->disable(dev);
 		iounmap(host->ctl);
 		mmc_free_host(mmc);
 	}
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 692dc23..dafecfb 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -55,10 +55,8 @@
 /* Define some IRQ masks */
 /* This is the mask used at reset by the chip */
 #define TMIO_MASK_ALL           0x837f031d
-#define TMIO_MASK_READOP  (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND | \
-		TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
-#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND | \
-		TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
+#define TMIO_MASK_READOP  (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)
+#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)
 #define TMIO_MASK_CMD     (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
 		TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
 #define TMIO_MASK_IRQ     (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
old mode 100755
new mode 100644
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index 1bec5e1..8db1148 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -226,7 +226,7 @@
  * exists, but is for MTD_UADDR_NOT_SUPPORTED - and, therefore,
  * should not be used.  The  problem is that structures with
  * initializers have extra fields initialized to 0.  It is _very_
- * desireable to have the unlock address entries for unsupported
+ * desirable to have the unlock address entries for unsupported
  * data widths automatically initialized - that means that
  * MTD_UADDR_NOT_SUPPORTED must be 0 and the first entry here
  * must go unused.
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
old mode 100755
new mode 100644
diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c
index c48cad2..30e12c8 100644
--- a/drivers/mtd/maps/pismo.c
+++ b/drivers/mtd/maps/pismo.c
@@ -118,7 +118,7 @@
 {
 	struct platform_device *dev;
 	struct resource res = { };
-	phys_addr_t base = region.base;
+	phys_addr_t base = region->base;
 	int ret;
 
 	if (base == ~0)
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index dafb919..76a76be 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -4,7 +4,7 @@
  *	http://www.simtec.co.uk/products/SWLINUX/
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * Generic platfrom device based RAM map
+ * Generic platform device based RAM map
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index bb64656..1157d56 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -444,7 +444,7 @@
 
 config MTD_NAND_MXC
 	tristate "MXC NAND support"
-	depends on ARCH_MX2 || ARCH_MX3
+	depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3
 	help
 	  This enables the driver for the NAND flash controller on the
 	  MXC processors.
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index 087bcd7..7d1cca7a 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -381,7 +381,7 @@
 	if (!r)
 		return -ENXIO;
 
-	/* map physical adress */
+	/* map physical address */
 	bcm_umi_io_base = ioremap(r->start, r->end - r->start + 1);
 
 	if (!bcm_umi_io_base) {
@@ -525,7 +525,7 @@
 	/* Release resources, unregister device */
 	nand_release(board_mtd);
 
-	/* unmap physical adress */
+	/* unmap physical address */
 	iounmap(bcm_umi_io_base);
 
 	/* Free the MTD device structure */
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 45dec57..b2900d8 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -507,7 +507,7 @@
 		 * MXC NANDFC can only perform full page+spare or
 		 * spare-only read/write.  When the upper layers
 		 * layers perform a read/write buf operation,
-		 * we will used the saved column adress to index into
+		 * we will used the saved column address to index into
 		 * the full page.
 		 */
 		send_addr(host, 0, page_addr == -1);
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 14cec04..fad40aa 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -37,6 +37,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/stringify.h>
+#include <linux/namei.h>
 #include <linux/stat.h>
 #include <linux/miscdevice.h>
 #include <linux/log2.h>
@@ -50,7 +51,8 @@
 
 /**
  * struct mtd_dev_param - MTD device parameter description data structure.
- * @name: MTD device name or number string
+ * @name: MTD character device node path, MTD device name, or MTD device number
+ *        string
  * @vid_hdr_offs: VID header offset
  */
 struct mtd_dev_param {
@@ -59,10 +61,10 @@
 };
 
 /* Numbers of elements set in the @mtd_dev_param array */
-static int mtd_devs;
+static int __initdata mtd_devs;
 
 /* MTD devices specification parameters */
-static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES];
+static struct mtd_dev_param __initdata mtd_dev_param[UBI_MAX_DEVICES];
 
 /* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */
 struct class *ubi_class;
@@ -87,7 +89,8 @@
 static DEFINE_SPINLOCK(ubi_devices_lock);
 
 /* "Show" method for files in '/<sysfs>/class/ubi/' */
-static ssize_t ubi_version_show(struct class *class, char *buf)
+static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr,
+				char *buf)
 {
 	return sprintf(buf, "%d\n", UBI_VERSION);
 }
@@ -363,11 +366,13 @@
 /**
  * ubi_sysfs_init - initialize sysfs for an UBI device.
  * @ubi: UBI device description object
+ * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
+ *       taken
  *
  * This function returns zero in case of success and a negative error code in
  * case of failure.
  */
-static int ubi_sysfs_init(struct ubi_device *ubi)
+static int ubi_sysfs_init(struct ubi_device *ubi, int *ref)
 {
 	int err;
 
@@ -379,6 +384,7 @@
 	if (err)
 		return err;
 
+	*ref = 1;
 	err = device_create_file(&ubi->dev, &dev_eraseblock_size);
 	if (err)
 		return err;
@@ -434,7 +440,7 @@
 }
 
 /**
- * kill_volumes - destroy all volumes.
+ * kill_volumes - destroy all user volumes.
  * @ubi: UBI device description object
  */
 static void kill_volumes(struct ubi_device *ubi)
@@ -447,36 +453,29 @@
 }
 
 /**
- * free_user_volumes - free all user volumes.
- * @ubi: UBI device description object
- *
- * Normally the volumes are freed at the release function of the volume device
- * objects. However, on error paths the volumes have to be freed before the
- * device objects have been initialized.
- */
-static void free_user_volumes(struct ubi_device *ubi)
-{
-	int i;
-
-	for (i = 0; i < ubi->vtbl_slots; i++)
-		if (ubi->volumes[i]) {
-			kfree(ubi->volumes[i]->eba_tbl);
-			kfree(ubi->volumes[i]);
-		}
-}
-
-/**
  * uif_init - initialize user interfaces for an UBI device.
  * @ubi: UBI device description object
+ * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
+ *       taken, otherwise set to %0
+ *
+ * This function initializes various user interfaces for an UBI device. If the
+ * initialization fails at an early stage, this function frees all the
+ * resources it allocated, returns an error, and @ref is set to %0. However,
+ * if the initialization fails after the UBI device was registered in the
+ * driver core subsystem, this function takes a reference to @ubi->dev, because
+ * otherwise the release function ('dev_release()') would free whole @ubi
+ * object. The @ref argument is set to %1 in this case. The caller has to put
+ * this reference.
  *
  * This function returns zero in case of success and a negative error code in
- * case of failure. Note, this function destroys all volumes if it fails.
+ * case of failure.
  */
-static int uif_init(struct ubi_device *ubi)
+static int uif_init(struct ubi_device *ubi, int *ref)
 {
 	int i, err;
 	dev_t dev;
 
+	*ref = 0;
 	sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
 
 	/*
@@ -504,7 +503,7 @@
 		goto out_unreg;
 	}
 
-	err = ubi_sysfs_init(ubi);
+	err = ubi_sysfs_init(ubi, ref);
 	if (err)
 		goto out_sysfs;
 
@@ -522,6 +521,8 @@
 out_volumes:
 	kill_volumes(ubi);
 out_sysfs:
+	if (*ref)
+		get_device(&ubi->dev);
 	ubi_sysfs_close(ubi);
 	cdev_del(&ubi->cdev);
 out_unreg:
@@ -875,7 +876,7 @@
 int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 {
 	struct ubi_device *ubi;
-	int i, err, do_free = 1;
+	int i, err, ref = 0;
 
 	/*
 	 * Check if we already have the same MTD device attached.
@@ -975,9 +976,9 @@
 			goto out_detach;
 	}
 
-	err = uif_init(ubi);
+	err = uif_init(ubi, &ref);
 	if (err)
-		goto out_nofree;
+		goto out_detach;
 
 	ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
 	if (IS_ERR(ubi->bgt_thread)) {
@@ -1025,12 +1026,8 @@
 
 out_uif:
 	uif_close(ubi);
-out_nofree:
-	do_free = 0;
 out_detach:
 	ubi_wl_close(ubi);
-	if (do_free)
-		free_user_volumes(ubi);
 	free_internal_volumes(ubi);
 	vfree(ubi->vtbl);
 out_free:
@@ -1039,7 +1036,10 @@
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
 	vfree(ubi->dbg_peb_buf);
 #endif
-	kfree(ubi);
+	if (ref)
+		put_device(&ubi->dev);
+	else
+		kfree(ubi);
 	return err;
 }
 
@@ -1096,7 +1096,7 @@
 
 	/*
 	 * Get a reference to the device in order to prevent 'dev_release()'
-	 * from freeing @ubi object.
+	 * from freeing the @ubi object.
 	 */
 	get_device(&ubi->dev);
 
@@ -1116,13 +1116,50 @@
 }
 
 /**
- * find_mtd_device - open an MTD device by its name or number.
- * @mtd_dev: name or number of the device
+ * open_mtd_by_chdev - open an MTD device by its character device node path.
+ * @mtd_dev: MTD character device node path
+ *
+ * This helper function opens an MTD device by its character node device path.
+ * Returns MTD device description object in case of success and a negative
+ * error code in case of failure.
+ */
+static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev)
+{
+	int err, major, minor, mode;
+	struct path path;
+
+	/* Probably this is an MTD character device node path */
+	err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path);
+	if (err)
+		return ERR_PTR(err);
+
+	/* MTD device number is defined by the major / minor numbers */
+	major = imajor(path.dentry->d_inode);
+	minor = iminor(path.dentry->d_inode);
+	mode = path.dentry->d_inode->i_mode;
+	path_put(&path);
+	if (major != MTD_CHAR_MAJOR || !S_ISCHR(mode))
+		return ERR_PTR(-EINVAL);
+
+	if (minor & 1)
+		/*
+		 * Just do not think the "/dev/mtdrX" devices support is need,
+		 * so do not support them to avoid doing extra work.
+		 */
+		return ERR_PTR(-EINVAL);
+
+	return get_mtd_device(NULL, minor / 2);
+}
+
+/**
+ * open_mtd_device - open MTD device by name, character device path, or number.
+ * @mtd_dev: name, character device node path, or MTD device device number
  *
  * This function tries to open and MTD device described by @mtd_dev string,
- * which is first treated as an ASCII number, and if it is not true, it is
- * treated as MTD device name. Returns MTD device description object in case of
- * success and a negative error code in case of failure.
+ * which is first treated as ASCII MTD device number, and if it is not true, it
+ * is treated as MTD device name, and if that is also not true, it is treated
+ * as MTD character device node path. Returns MTD device description object in
+ * case of success and a negative error code in case of failure.
  */
 static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
 {
@@ -1137,6 +1174,9 @@
 		 * MTD device name.
 		 */
 		mtd = get_mtd_device_nm(mtd_dev);
+		if (IS_ERR(mtd) && PTR_ERR(mtd) == -ENODEV)
+			/* Probably this is an MTD character device node path */
+			mtd = open_mtd_by_chdev(mtd_dev);
 	} else
 		mtd = get_mtd_device(NULL, mtd_num);
 
@@ -1352,13 +1392,15 @@
 
 module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000);
 MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: "
-		      "mtd=<name|num>[,<vid_hdr_offs>].\n"
+		      "mtd=<name|num|path>[,<vid_hdr_offs>].\n"
 		      "Multiple \"mtd\" parameters may be specified.\n"
-		      "MTD devices may be specified by their number or name.\n"
+		      "MTD devices may be specified by their number, name, or "
+		      "path to the MTD character device node.\n"
 		      "Optional \"vid_hdr_offs\" parameter specifies UBI VID "
-		      "header position and data starting position to be used "
-		      "by UBI.\n"
-		      "Example: mtd=content,1984 mtd=4 - attach MTD device"
+		      "header position to be used by UBI.\n"
+		      "Example 1: mtd=/dev/mtd0 - attach MTD device "
+		      "/dev/mtd0.\n"
+		      "Example 2: mtd=content,1984 mtd=4 - attach MTD device "
 		      "with name \"content\" using VID header offset 1984, and "
 		      "MTD device number 4 with default VID header offset.");
 
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index f30bcb3..17a1071 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -96,8 +96,11 @@
 
 #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
 int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
+int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
+			int offset, int len);
 #else
 #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
+#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0
 #endif
 
 #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
@@ -176,6 +179,7 @@
 #define ubi_dbg_is_write_failure() 0
 #define ubi_dbg_is_erase_failure() 0
 #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
+#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0
 
 #endif /* !CONFIG_MTD_UBI_DEBUG */
 #endif /* !__UBI_DEBUG_H__ */
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 8aa51e7..b4ecc84 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -143,7 +143,7 @@
 
 	err = paranoid_check_not_bad(ubi, pnum);
 	if (err)
-		return err > 0 ? -EINVAL : err;
+		return err;
 
 	addr = (loff_t)pnum * ubi->peb_size + offset;
 retry:
@@ -236,12 +236,12 @@
 
 	err = paranoid_check_not_bad(ubi, pnum);
 	if (err)
-		return err > 0 ? -EINVAL : err;
+		return err;
 
 	/* The area we are writing to has to contain all 0xFF bytes */
 	err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
 	if (err)
-		return err > 0 ? -EINVAL : err;
+		return err;
 
 	if (offset >= ubi->leb_start) {
 		/*
@@ -250,10 +250,10 @@
 		 */
 		err = paranoid_check_peb_ec_hdr(ubi, pnum);
 		if (err)
-			return err > 0 ? -EINVAL : err;
+			return err;
 		err = paranoid_check_peb_vid_hdr(ubi, pnum);
 		if (err)
-			return err > 0 ? -EINVAL : err;
+			return err;
 	}
 
 	if (ubi_dbg_is_write_failure()) {
@@ -273,6 +273,21 @@
 	} else
 		ubi_assert(written == len);
 
+	if (!err) {
+		err = ubi_dbg_check_write(ubi, buf, pnum, offset, len);
+		if (err)
+			return err;
+
+		/*
+		 * Since we always write sequentially, the rest of the PEB has
+		 * to contain only 0xFF bytes.
+		 */
+		offset += len;
+		len = ubi->peb_size - offset;
+		if (len)
+			err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
+	}
+
 	return err;
 }
 
@@ -348,7 +363,7 @@
 
 	err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size);
 	if (err)
-		return err > 0 ? -EINVAL : err;
+		return err;
 
 	if (ubi_dbg_is_erase_failure() && !err) {
 		dbg_err("cannot erase PEB %d (emulated)", pnum);
@@ -542,7 +557,7 @@
 
 	err = paranoid_check_not_bad(ubi, pnum);
 	if (err != 0)
-		return err > 0 ? -EINVAL : err;
+		return err;
 
 	if (ubi->ro_mode) {
 		ubi_err("read-only mode");
@@ -819,7 +834,7 @@
 
 	err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);
 	if (err)
-		return -EINVAL;
+		return err;
 
 	err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize);
 	return err;
@@ -1083,7 +1098,7 @@
 
 	err = paranoid_check_peb_ec_hdr(ubi, pnum);
 	if (err)
-		return err > 0 ? -EINVAL : err;
+		return err;
 
 	vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
 	vid_hdr->version = UBI_VERSION;
@@ -1092,7 +1107,7 @@
 
 	err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);
 	if (err)
-		return -EINVAL;
+		return err;
 
 	p = (char *)vid_hdr - ubi->vid_hdr_shift;
 	err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
@@ -1107,8 +1122,8 @@
  * @ubi: UBI device description object
  * @pnum: physical eraseblock number to check
  *
- * This function returns zero if the physical eraseblock is good, a positive
- * number if it is bad and a negative error code if an error occurred.
+ * This function returns zero if the physical eraseblock is good, %-EINVAL if
+ * it is bad and a negative error code if an error occurred.
  */
 static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
 {
@@ -1120,7 +1135,7 @@
 
 	ubi_err("paranoid check failed for PEB %d", pnum);
 	ubi_dbg_dump_stack();
-	return err;
+	return err > 0 ? -EINVAL : err;
 }
 
 /**
@@ -1130,7 +1145,7 @@
  * @ec_hdr: the erase counter header to check
  *
  * This function returns zero if the erase counter header contains valid
- * values, and %1 if not.
+ * values, and %-EINVAL if not.
  */
 static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
 				 const struct ubi_ec_hdr *ec_hdr)
@@ -1156,7 +1171,7 @@
 fail:
 	ubi_dbg_dump_ec_hdr(ec_hdr);
 	ubi_dbg_dump_stack();
-	return 1;
+	return -EINVAL;
 }
 
 /**
@@ -1164,8 +1179,8 @@
  * @ubi: UBI device description object
  * @pnum: the physical eraseblock number to check
  *
- * This function returns zero if the erase counter header is all right, %1 if
- * not, and a negative error code if an error occurred.
+ * This function returns zero if the erase counter header is all right and and
+ * a negative error code if not or if an error occurred.
  */
 static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
 {
@@ -1188,7 +1203,7 @@
 		ubi_err("paranoid check failed for PEB %d", pnum);
 		ubi_dbg_dump_ec_hdr(ec_hdr);
 		ubi_dbg_dump_stack();
-		err = 1;
+		err = -EINVAL;
 		goto exit;
 	}
 
@@ -1206,7 +1221,7 @@
  * @vid_hdr: the volume identifier header to check
  *
  * This function returns zero if the volume identifier header is all right, and
- * %1 if not.
+ * %-EINVAL if not.
  */
 static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
 				  const struct ubi_vid_hdr *vid_hdr)
@@ -1233,7 +1248,7 @@
 	ubi_err("paranoid check failed for PEB %d", pnum);
 	ubi_dbg_dump_vid_hdr(vid_hdr);
 	ubi_dbg_dump_stack();
-	return 1;
+	return -EINVAL;
 
 }
 
@@ -1243,7 +1258,7 @@
  * @pnum: the physical eraseblock number to check
  *
  * This function returns zero if the volume identifier header is all right,
- * %1 if not, and a negative error code if an error occurred.
+ * and a negative error code if not or if an error occurred.
  */
 static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
 {
@@ -1270,7 +1285,7 @@
 		ubi_err("paranoid check failed for PEB %d", pnum);
 		ubi_dbg_dump_vid_hdr(vid_hdr);
 		ubi_dbg_dump_stack();
-		err = 1;
+		err = -EINVAL;
 		goto exit;
 	}
 
@@ -1282,6 +1297,61 @@
 }
 
 /**
+ * ubi_dbg_check_write - make sure write succeeded.
+ * @ubi: UBI device description object
+ * @buf: buffer with data which were written
+ * @pnum: physical eraseblock number the data were written to
+ * @offset: offset within the physical eraseblock the data were written to
+ * @len: how many bytes were written
+ *
+ * This functions reads data which were recently written and compares it with
+ * the original data buffer - the data have to match. Returns zero if the data
+ * match and a negative error code if not or in case of failure.
+ */
+int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
+			int offset, int len)
+{
+	int err, i;
+
+	mutex_lock(&ubi->dbg_buf_mutex);
+	err = ubi_io_read(ubi, ubi->dbg_peb_buf, pnum, offset, len);
+	if (err)
+		goto out_unlock;
+
+	for (i = 0; i < len; i++) {
+		uint8_t c = ((uint8_t *)buf)[i];
+		uint8_t c1 = ((uint8_t *)ubi->dbg_peb_buf)[i];
+		int dump_len;
+
+		if (c == c1)
+			continue;
+
+		ubi_err("paranoid check failed for PEB %d:%d, len %d",
+			pnum, offset, len);
+		ubi_msg("data differ at position %d", i);
+		dump_len = max_t(int, 128, len - i);
+		ubi_msg("hex dump of the original buffer from %d to %d",
+			i, i + dump_len);
+		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+			       buf + i, dump_len, 1);
+		ubi_msg("hex dump of the read buffer from %d to %d",
+			i, i + dump_len);
+		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+			       ubi->dbg_peb_buf + i, dump_len, 1);
+		ubi_dbg_dump_stack();
+		err = -EINVAL;
+		goto out_unlock;
+	}
+	mutex_unlock(&ubi->dbg_buf_mutex);
+
+	return 0;
+
+out_unlock:
+	mutex_unlock(&ubi->dbg_buf_mutex);
+	return err;
+}
+
+/**
  * ubi_dbg_check_all_ff - check that a region of flash is empty.
  * @ubi: UBI device description object
  * @pnum: the physical eraseblock number to check
@@ -1289,8 +1359,8 @@
  * @len: the length of the region to check
  *
  * This function returns zero if only 0xFF bytes are present at offset
- * @offset of the physical eraseblock @pnum, %1 if not, and a negative error
- * code if an error occurred.
+ * @offset of the physical eraseblock @pnum, and a negative error code if not
+ * or if an error occurred.
  */
 int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
 {
@@ -1321,7 +1391,7 @@
 	ubi_msg("hex dump of the %d-%d region", offset, offset + len);
 	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
 		       ubi->dbg_peb_buf, len, 1);
-	err = 1;
+	err = -EINVAL;
 error:
 	ubi_dbg_dump_stack();
 	mutex_unlock(&ubi->dbg_buf_mutex);
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 90af61a..594184b 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -974,11 +974,8 @@
 			seb->ec = si->mean_ec;
 
 	err = paranoid_check_si(ubi, si);
-	if (err) {
-		if (err > 0)
-			err = -EINVAL;
+	if (err)
 		goto out_vidh;
-	}
 
 	ubi_free_vid_hdr(ubi, vidh);
 	kfree(ech);
@@ -1086,8 +1083,8 @@
  * @ubi: UBI device description object
  * @si: scanning information
  *
- * This function returns zero if the scanning information is all right, %1 if
- * not and a negative error code if an error occurred.
+ * This function returns zero if the scanning information is all right, and a
+ * negative error code if not or if an error occurred.
  */
 static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
 {
@@ -1346,7 +1343,7 @@
 
 out:
 	ubi_dbg_dump_stack();
-	return 1;
+	return -EINVAL;
 }
 
 #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 600c722..f64ddab 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -464,7 +464,7 @@
 				   ubi->peb_size - ubi->vid_hdr_aloffset);
 	if (err) {
 		ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
-		return err > 0 ? -EINVAL : err;
+		return err;
 	}
 
 	return e->pnum;
@@ -513,7 +513,7 @@
 	dbg_wl("erase PEB %d, old EC %llu", e->pnum, ec);
 
 	err = paranoid_check_ec(ubi, e->pnum, e->ec);
-	if (err > 0)
+	if (err)
 		return -EINVAL;
 
 	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1572,8 +1572,7 @@
  * @ec: the erase counter to check
  *
  * This function returns zero if the erase counter of physical eraseblock @pnum
- * is equivalent to @ec, %1 if not, and a negative error code if an error
- * occurred.
+ * is equivalent to @ec, and a negative error code if not or if an error occurred.
  */
 static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
 {
@@ -1611,8 +1610,8 @@
  * @e: the wear-leveling entry to check
  * @root: the root of the tree
  *
- * This function returns zero if @e is in the @root RB-tree and %1 if it is
- * not.
+ * This function returns zero if @e is in the @root RB-tree and %-EINVAL if it
+ * is not.
  */
 static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
 				     struct rb_root *root)
@@ -1623,7 +1622,7 @@
 	ubi_err("paranoid check failed for PEB %d, EC %d, RB-tree %p ",
 		e->pnum, e->ec, root);
 	ubi_dbg_dump_stack();
-	return 1;
+	return -EINVAL;
 }
 
 /**
@@ -1632,7 +1631,7 @@
  * @ubi: UBI device description object
  * @e: the wear-leveling entry to check
  *
- * This function returns zero if @e is in @ubi->pq and %1 if it is not.
+ * This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not.
  */
 static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
 {
@@ -1647,6 +1646,6 @@
 	ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue",
 		e->pnum, e->ec);
 	ubi_dbg_dump_stack();
-	return 1;
+	return -EINVAL;
 }
 #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
diff --git a/drivers/net/atlx/atl2.h b/drivers/net/atlx/atl2.h
index d918bbe..927e4de 100644
--- a/drivers/net/atlx/atl2.h
+++ b/drivers/net/atlx/atl2.h
@@ -442,7 +442,7 @@
 struct atl2_ring_header {
     /* pointer to the descriptor ring memory */
     void *desc;
-    /* physical adress of the descriptor ring */
+    /* physical address of the descriptor ring */
     dma_addr_t dma;
     /* length of descriptor ring in bytes */
     unsigned int size;
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 5acd557..b8bec08 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -51,7 +51,9 @@
  * "show" function for the bond_masters attribute.
  * The class parameter is ignored.
  */
-static ssize_t bonding_show_bonds(struct class *cls, char *buf)
+static ssize_t bonding_show_bonds(struct class *cls,
+				  struct class_attribute *attr,
+				  char *buf)
 {
 	struct net *net = current->nsproxy->net_ns;
 	struct bond_net *bn = net_generic(net, bond_net_id);
@@ -98,6 +100,7 @@
  */
 
 static ssize_t bonding_store_bonds(struct class *cls,
+				   struct class_attribute *attr,
 				   const char *buffer, size_t count)
 {
 	struct net *net = current->nsproxy->net_ns;
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 7138411..55d99ca 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -248,7 +248,7 @@
  *
  * Interrupts are handled by a single CPU and it is likely that on a MP system
  * the application is migrated to another CPU. In that scenario, we try to
- * seperate the RX(in irq context) and TX state in order to decrease memory
+ * separate the RX(in irq context) and TX state in order to decrease memory
  * contention.
  */
 struct sge {
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 1462401..b0208e4 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -580,7 +580,7 @@
 	}
 
 #ifdef CONFIG_SH_HICOSH4
-	/* truely reset the chip */
+	/* truly reset the chip */
 	writeword(ioaddr, ADD_PORT, 0x0114);
 	writeword(ioaddr, DATA_PORT, 0x0040);
 #endif
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 3e8618b..4cd7f420 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -264,6 +264,10 @@
 	struct work_struct fatal_error_handler_task;
 	struct work_struct link_fault_handler_task;
 
+	struct work_struct db_full_task;
+	struct work_struct db_empty_task;
+	struct work_struct db_drop_task;
+
 	struct dentry *debugfs_root;
 
 	struct mutex mdio_lock;
@@ -335,6 +339,7 @@
 int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx,
 		unsigned char *data);
 irqreturn_t t3_sge_intr_msix(int irq, void *cookie);
+extern struct workqueue_struct *cxgb3_wq;
 
 int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size);
 
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index cecdec1..9e3e875 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -45,6 +45,7 @@
 #include <linux/firmware.h>
 #include <linux/log2.h>
 #include <linux/stringify.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 
 #include "common.h"
@@ -140,7 +141,7 @@
  * will block keventd as it needs the rtnl lock, and we'll deadlock waiting
  * for our work to complete.  Get our own work queue to solve this.
  */
-static struct workqueue_struct *cxgb3_wq;
+struct workqueue_struct *cxgb3_wq;
 
 /**
  *	link_report - show link status and link speed/duplex
@@ -586,6 +587,19 @@
 		      V_RRCPLCPUSIZE(6) | F_HASHTOEPLITZ, cpus, rspq_map);
 }
 
+static void ring_dbs(struct adapter *adap)
+{
+	int i, j;
+
+	for (i = 0; i < SGE_QSETS; i++) {
+		struct sge_qset *qs = &adap->sge.qs[i];
+
+		if (qs->adap)
+			for (j = 0; j < SGE_TXQ_PER_SET; j++)
+				t3_write_reg(adap, A_SG_KDOORBELL, F_SELEGRCNTX | V_EGRCNTX(qs->txq[j].cntxt_id));
+	}
+}
+
 static void init_napi(struct adapter *adap)
 {
 	int i;
@@ -2751,6 +2765,42 @@
 	spin_unlock_irq(&adapter->work_lock);
 }
 
+static void db_full_task(struct work_struct *work)
+{
+	struct adapter *adapter = container_of(work, struct adapter,
+					       db_full_task);
+
+	cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_FULL, 0);
+}
+
+static void db_empty_task(struct work_struct *work)
+{
+	struct adapter *adapter = container_of(work, struct adapter,
+					       db_empty_task);
+
+	cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_EMPTY, 0);
+}
+
+static void db_drop_task(struct work_struct *work)
+{
+	struct adapter *adapter = container_of(work, struct adapter,
+					       db_drop_task);
+	unsigned long delay = 1000;
+	unsigned short r;
+
+	cxgb3_event_notify(&adapter->tdev, OFFLOAD_DB_DROP, 0);
+
+	/*
+	 * Sleep a while before ringing the driver qset dbs.
+	 * The delay is between 1000-2023 usecs.
+	 */
+	get_random_bytes(&r, 2);
+	delay += r & 1023;
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(usecs_to_jiffies(delay));
+	ring_dbs(adapter);
+}
+
 /*
  * Processes external (PHY) interrupts in process context.
  */
@@ -3219,6 +3269,11 @@
 	INIT_LIST_HEAD(&adapter->adapter_list);
 	INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task);
 	INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task);
+
+	INIT_WORK(&adapter->db_full_task, db_full_task);
+	INIT_WORK(&adapter->db_empty_task, db_empty_task);
+	INIT_WORK(&adapter->db_drop_task, db_drop_task);
+
 	INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task);
 
 	for (i = 0; i < ai->nports0 + ai->nports1; ++i) {
diff --git a/drivers/net/cxgb3/cxgb3_offload.h b/drivers/net/cxgb3/cxgb3_offload.h
index 670aa62..929c298 100644
--- a/drivers/net/cxgb3/cxgb3_offload.h
+++ b/drivers/net/cxgb3/cxgb3_offload.h
@@ -73,7 +73,10 @@
 	OFFLOAD_STATUS_UP,
 	OFFLOAD_STATUS_DOWN,
 	OFFLOAD_PORT_DOWN,
-	OFFLOAD_PORT_UP
+	OFFLOAD_PORT_UP,
+	OFFLOAD_DB_FULL,
+	OFFLOAD_DB_EMPTY,
+	OFFLOAD_DB_DROP
 };
 
 struct cxgb3_client {
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index 1b5327b..cb42353 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -254,6 +254,22 @@
 #define V_LOPIODRBDROPERR(x) ((x) << S_LOPIODRBDROPERR)
 #define F_LOPIODRBDROPERR    V_LOPIODRBDROPERR(1U)
 
+#define S_HIPRIORITYDBFULL    7
+#define V_HIPRIORITYDBFULL(x) ((x) << S_HIPRIORITYDBFULL)
+#define F_HIPRIORITYDBFULL    V_HIPRIORITYDBFULL(1U)
+
+#define S_HIPRIORITYDBEMPTY   6
+#define V_HIPRIORITYDBEMPTY(x) ((x) << S_HIPRIORITYDBEMPTY)
+#define F_HIPRIORITYDBEMPTY    V_HIPRIORITYDBEMPTY(1U)
+
+#define S_LOPRIORITYDBFULL    5
+#define V_LOPRIORITYDBFULL(x) ((x) << S_LOPRIORITYDBFULL)
+#define F_LOPRIORITYDBFULL    V_LOPRIORITYDBFULL(1U)
+
+#define S_LOPRIORITYDBEMPTY   4
+#define V_LOPRIORITYDBEMPTY(x) ((x) << S_LOPRIORITYDBEMPTY)
+#define F_LOPRIORITYDBEMPTY    V_LOPRIORITYDBEMPTY(1U)
+
 #define S_RSPQDISABLED    3
 #define V_RSPQDISABLED(x) ((x) << S_RSPQDISABLED)
 #define F_RSPQDISABLED    V_RSPQDISABLED(1U)
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 0482059..67e61b2 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -42,6 +42,7 @@
 #include "sge_defs.h"
 #include "t3_cpl.h"
 #include "firmware_exports.h"
+#include "cxgb3_offload.h"
 
 #define USE_GTS 0
 
@@ -196,13 +197,13 @@
 /**
  *	need_skb_unmap - does the platform need unmapping of sk_buffs?
  *
- *	Returns true if the platfrom needs sk_buff unmapping.  The compiler
+ *	Returns true if the platform needs sk_buff unmapping.  The compiler
  *	optimizes away unecessary code if this returns true.
  */
 static inline int need_skb_unmap(void)
 {
 	/*
-	 * This structure is used to tell if the platfrom needs buffer
+	 * This structure is used to tell if the platform needs buffer
 	 * unmapping by checking if DECLARE_PCI_UNMAP_ADDR defines anything.
 	 */
 	struct dummy {
@@ -2841,8 +2842,13 @@
 	}
 
 	if (status & (F_HIPIODRBDROPERR | F_LOPIODRBDROPERR))
-		CH_ALERT(adapter, "SGE dropped %s priority doorbell\n",
-			 status & F_HIPIODRBDROPERR ? "high" : "lo");
+		queue_work(cxgb3_wq, &adapter->db_drop_task);
+
+	if (status & (F_HIPRIORITYDBFULL | F_LOPRIORITYDBFULL))
+		queue_work(cxgb3_wq, &adapter->db_full_task);
+
+	if (status & (F_HIPRIORITYDBEMPTY | F_LOPRIORITYDBEMPTY))
+		queue_work(cxgb3_wq, &adapter->db_empty_task);
 
 	t3_write_reg(adapter, A_SG_INT_CAUSE, status);
 	if (status &  SGE_FATALERR)
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index 3ab9f51..95a8ba0 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -1433,7 +1433,10 @@
 		       F_IRPARITYERROR | V_ITPARITYERROR(M_ITPARITYERROR) | \
 		       V_FLPARITYERROR(M_FLPARITYERROR) | F_LODRBPARITYERROR | \
 		       F_HIDRBPARITYERROR | F_LORCQPARITYERROR | \
-		       F_HIRCQPARITYERROR)
+		       F_HIRCQPARITYERROR | F_LOPRIORITYDBFULL | \
+		       F_HIPRIORITYDBFULL | F_LOPRIORITYDBEMPTY | \
+		       F_HIPRIORITYDBEMPTY | F_HIPIODRBDROPERR | \
+		       F_LOPIODRBDROPERR)
 #define MC5_INTR_MASK (F_PARITYERR | F_ACTRGNFULL | F_UNKNOWNCMD | \
 		       F_REQQPARERR | F_DISPQPARERR | F_DELACTEMPTY | \
 		       F_NFASRCHFAIL)
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 32960b9..8bd086a 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -2658,7 +2658,7 @@
 
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
-		printk(KERN_ERR "DaVinci EMAC: No platfrom data\n");
+		printk(KERN_ERR "DaVinci EMAC: No platform data\n");
 		return -ENODEV;
 	}
 
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index 3c95acb..712ccc6 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -1346,7 +1346,7 @@
  *
  *  1) down
  *  2) autoneg_progress
- *  3) autoneg_complete (the link sucessfully autonegotiated)
+ *  3) autoneg_complete (the link successfully autonegotiated)
  *  4) forced_up (the link has been forced up, it did not autonegotiate)
  *
  **/
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index 2425ed1..a8b2c0d 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -647,7 +647,7 @@
 				if (!(rxcw & E1000_RXCW_IV)) {
 					mac->serdes_has_link = true;
 					e_dbg("SERDES: Link up - autoneg "
-					   "completed sucessfully.\n");
+					   "completed successfully.\n");
 				} else {
 					mac->serdes_has_link = false;
 					e_dbg("SERDES: Link down - invalid"
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index c3f0619..b671555 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -998,7 +998,7 @@
 	}
 
 	/* Need to reverse the bit maps as  bit_map's MSB is q0
-	 * but, for_each_bit parses from right to left, which
+	 * but, for_each_set_bit parses from right to left, which
 	 * basically reverses the queue numbers */
 	for (i = 0; i< priv->num_grps; i++) {
 		priv->gfargrp[i].tx_bit_map = reverse_bitmap(
@@ -1011,7 +1011,7 @@
 	 * also assign queues to groups */
 	for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) {
 		priv->gfargrp[grp_idx].num_rx_queues = 0x0;
-		for_each_bit(i, &priv->gfargrp[grp_idx].rx_bit_map,
+		for_each_set_bit(i, &priv->gfargrp[grp_idx].rx_bit_map,
 				priv->num_rx_queues) {
 			priv->gfargrp[grp_idx].num_rx_queues++;
 			priv->rx_queue[i]->grp = &priv->gfargrp[grp_idx];
@@ -1019,7 +1019,7 @@
 			rqueue = rqueue | ((RQUEUE_EN0 | RQUEUE_EX0) >> i);
 		}
 		priv->gfargrp[grp_idx].num_tx_queues = 0x0;
-		for_each_bit (i, &priv->gfargrp[grp_idx].tx_bit_map,
+		for_each_set_bit(i, &priv->gfargrp[grp_idx].tx_bit_map,
 				priv->num_tx_queues) {
 			priv->gfargrp[grp_idx].num_tx_queues++;
 			priv->tx_queue[i]->grp = &priv->gfargrp[grp_idx];
@@ -1709,7 +1709,7 @@
 
 	if (priv->mode == MQ_MG_MODE) {
 		baddr = &regs->txic0;
-		for_each_bit (i, &tx_mask, priv->num_tx_queues) {
+		for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
 			if (likely(priv->tx_queue[i]->txcoalescing)) {
 				gfar_write(baddr + i, 0);
 				gfar_write(baddr + i, priv->tx_queue[i]->txic);
@@ -1717,7 +1717,7 @@
 		}
 
 		baddr = &regs->rxic0;
-		for_each_bit (i, &rx_mask, priv->num_rx_queues) {
+		for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
 			if (likely(priv->rx_queue[i]->rxcoalescing)) {
 				gfar_write(baddr + i, 0);
 				gfar_write(baddr + i, priv->rx_queue[i]->rxic);
@@ -2610,7 +2610,7 @@
 		budget_per_queue = left_over_budget/num_queues;
 		left_over_budget = 0;
 
-		for_each_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
+		for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
 			if (test_bit(i, &serviced_queues))
 				continue;
 			rx_queue = priv->rx_queue[i];
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index f2b93796..0bc777ba 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -1577,7 +1577,7 @@
 	NULL,
 };
 
-static struct sysfs_ops veth_pool_ops = {
+static const struct sysfs_ops veth_pool_ops = {
 	.show   = veth_pool_show,
 	.store  = veth_pool_store,
 };
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 583a21c..0ed25f0 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -688,7 +688,7 @@
 	/* start with one vector for every rx queue */
 	numvecs = adapter->num_rx_queues;
 
-	/* if tx handler is seperate add 1 for every tx queue */
+	/* if tx handler is separate add 1 for every tx queue */
 	if (!(adapter->flags & IGB_FLAG_QUEUE_PAIRS))
 		numvecs += adapter->num_tx_queues;
 
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index c412e80..1dcdce0 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -331,7 +331,7 @@
 		 * If we missed a speed change, initialise at the new speed
 		 * directly.  It is debatable whether this is actually
 		 * required, but in the interests of continuing from where
-		 * we left off it is desireable.  The converse argument is
+		 * we left off it is desirable.  The converse argument is
 		 * that we should re-negotiate at 9600 baud again.
 		 */
 		if (si->newspeed) {
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 966de5d..e6e972d 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -384,7 +384,7 @@
 	NULL
 };
 
-static struct sysfs_ops veth_cnx_sysfs_ops = {
+static const struct sysfs_ops veth_cnx_sysfs_ops = {
 		.show = veth_cnx_attribute_show
 };
 
@@ -441,7 +441,7 @@
 	NULL
 };
 
-static struct sysfs_ops veth_port_sysfs_ops = {
+static const struct sysfs_ops veth_port_sysfs_ops = {
 	.show = veth_port_attribute_show
 };
 
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 45e3532..684af37 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1050,7 +1050,7 @@
 	 */
 	for (v_idx = 0; v_idx < q_vectors; v_idx++) {
 		q_vector = adapter->q_vector[v_idx];
-		/* XXX for_each_bit(...) */
+		/* XXX for_each_set_bit(...) */
 		r_idx = find_first_bit(q_vector->rxr_idx,
 		                       adapter->num_rx_queues);
 
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index 235b5fd..ca653c4 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -751,7 +751,7 @@
 	 */
 	for (v_idx = 0; v_idx < q_vectors; v_idx++) {
 		q_vector = adapter->q_vector[v_idx];
-		/* XXX for_each_bit(...) */
+		/* XXX for_each_set_bit(...) */
 		r_idx = find_first_bit(q_vector->rxr_idx,
 				       adapter->num_rx_queues);
 
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
index b5219cc..0573e0b 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ks8851.c
@@ -407,7 +407,7 @@
  * @buff: The buffer address
  * @len: The length of the data to read
  *
- * Issue an RXQ FIFO read command and read the @len ammount of data from
+ * Issue an RXQ FIFO read command and read the @len amount of data from
  * the FIFO into the buffer specified by @buff.
  */
 static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len)
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
index 05b8bde..7dbff87 100644
--- a/drivers/net/qlge/qlge_ethtool.c
+++ b/drivers/net/qlge/qlge_ethtool.c
@@ -405,7 +405,7 @@
 		u32 wol = 0;
 		status = ql_mb_wol_mode(qdev, wol);
 		netif_err(qdev, drv, qdev->ndev, "WOL %s (wol code 0x%x)\n",
-			  status == 0 ? "cleared sucessfully" : "clear failed",
+			  status == 0 ? "cleared successfully" : "clear failed",
 			  wol);
 	}
 
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index c26ec5d..fd34f26 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -3855,7 +3855,7 @@
 		status = ql_mb_wol_mode(qdev, wol);
 		netif_err(qdev, drv, qdev->ndev,
 			  "WOL %s (wol code 0x%x) on %s\n",
-			  (status == 0) ? "Sucessfully set" : "Failed",
+			  (status == 0) ? "Successfully set" : "Failed",
 			  wol, qdev->ndev->name);
 	}
 
diff --git a/drivers/net/sfc/regs.h b/drivers/net/sfc/regs.h
index 89d606f..18a3be4 100644
--- a/drivers/net/sfc/regs.h
+++ b/drivers/net/sfc/regs.h
@@ -95,7 +95,7 @@
 #define	FRF_AA_INT_ACK_KER_FIELD_LBN 0
 #define	FRF_AA_INT_ACK_KER_FIELD_WIDTH 32
 
-/* INT_ISR0_REG: Function 0 Interrupt Acknowlege Status register */
+/* INT_ISR0_REG: Function 0 Interrupt Acknowledge Status register */
 #define	FR_BZ_INT_ISR0 0x00000090
 #define	FRF_BZ_INT_ISR_REG_LBN 0
 #define	FRF_BZ_INT_ISR_REG_WIDTH 64
diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c
index a85efcf..e8387d2 100644
--- a/drivers/net/skfp/ess.c
+++ b/drivers/net/skfp/ess.c
@@ -557,7 +557,7 @@
 
 	/*
 	 * send never allocation request where the requested payload and
-	 * overhead is zero or deallocate bandwidht when no bandwidth is
+	 * overhead is zero or deallocate bandwidth when no bandwidth is
 	 * parsed
 	 */
 	if (!smc->mib.fddiESSPayload) {
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c
index 30110a1..34fa10d 100644
--- a/drivers/net/smsc9420.c
+++ b/drivers/net/smsc9420.c
@@ -1347,7 +1347,7 @@
 
 	netif_carrier_off(dev);
 
-	/* disable, mask and acknowlege all interrupts */
+	/* disable, mask and acknowledge all interrupts */
 	spin_lock_irqsave(&pd->int_lock, flags);
 	int_cfg = smsc9420_reg_read(pd, INT_CFG) & (~INT_CFG_IRQ_EN_);
 	smsc9420_reg_write(pd, INT_CFG, int_cfg);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 2f8a8c3..5ba9d98 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -474,7 +474,7 @@
  * spider_net_enable_rxchtails - sets RX dmac chain tail addresses
  * @card: card structure
  *
- * spider_net_enable_rxchtails sets the RX DMAC chain tail adresses in the
+ * spider_net_enable_rxchtails sets the RX DMAC chain tail addresses in the
  * chip by writing to the appropriate register. DMA is enabled in
  * spider_net_enable_rxdmac.
  */
@@ -1820,7 +1820,7 @@
 
 	spider_net_write_reg(card, SPIDER_NET_ECMODE, SPIDER_NET_ECMODE_VALUE);
 
-	/* set chain tail adress for RX chains and
+	/* set chain tail address for RX chains and
 	 * enable DMA */
 	spider_net_enable_rxchtails(card);
 	spider_net_enable_rxdmac(card);
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 4344017..70196bc 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -782,7 +782,7 @@
 			break;
 
 		/* When writing back RX descriptor, GEM writes status
-		 * then buffer address, possibly in seperate transactions.
+		 * then buffer address, possibly in separate transactions.
 		 * If we don't wait for the chip to write both, we could
 		 * post a new buffer to this descriptor then have GEM spam
 		 * on the buffer address.  We sync on the RX completion
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 0c97802..f549309 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -1851,7 +1851,7 @@
  * @data - desc's data
  * @size - desc's size
  *
- * NOTE: this func does check for available space and, if neccessary, waits for
+ * NOTE: this func does check for available space and, if necessary, waits for
  *   NIC to read existing data before writing new one.
  */
 static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int size)
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index 21a0175..ee71bcf 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -693,7 +693,7 @@
  * NOTE: This function should be used whenever the status of any TPL must be
  * modified by the driver, because the compiler may otherwise change the
  * order of instructions such that writing the TPL status may be executed at
- * an undesireable time. When this function is used, the status is always
+ * an undesirable time. When this function is used, the status is always
  * written when the function is called.
  */
 static void tms380tr_write_tpl_status(TPL *tpl, unsigned int Status)
@@ -2264,7 +2264,7 @@
  * This function should be used whenever the status of any RPL must be
  * modified by the driver, because the compiler may otherwise change the
  * order of instructions such that writing the RPL status may be executed
- * at an undesireable time. When this function is used, the status is
+ * at an undesirable time. When this function is used, the status is
  * always written when the function is called.
  */
 static void tms380tr_write_rpl_status(RPL *rpl, unsigned int Status)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index ce1efa4..96c39bd 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1437,7 +1437,7 @@
 
 		__tun_detach(tun);
 
-		/* If desireable, unregister the netdevice. */
+		/* If desirable, unregister the netdevice. */
 		if (!(tun->flags & TUN_PERSIST)) {
 			rtnl_lock();
 			if (dev->reg_state == NETREG_REGISTERED)
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 1cf012d..cd24e5f 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -2098,7 +2098,7 @@
 
 	if(typhoon_reset(tp->ioaddr, WaitNoSleep) < 0) {
 		netdev_warn(dev, "could not reset in tx timeout\n");
-		goto truely_dead;
+		goto truly_dead;
 	}
 
 	/* If we ever start using the Hi ring, it will need cleaning too */
@@ -2107,13 +2107,13 @@
 
 	if(typhoon_start_runtime(tp) < 0) {
 		netdev_err(dev, "could not start runtime in tx timeout\n");
-		goto truely_dead;
+		goto truly_dead;
         }
 
 	netif_wake_queue(dev);
 	return;
 
-truely_dead:
+truly_dead:
 	/* Reset the hardware, and turn off carrier to avoid more timeouts */
 	typhoon_reset(tp->ioaddr, NoWait);
 	netif_carrier_off(dev);
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 23a9751..1b0aef3 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -430,7 +430,7 @@
 	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
 
 	/* Ethernet frames are defined in Little Endian mode,
-	therefor to insert */
+	therefore to insert */
 	/* the address to the hash (Big Endian mode), we reverse the bytes.*/
 
 	set_mac_addr(&p_82xx_addr_filt->taddr.h, p_enet_addr);
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index b36bf96..f0bd70f 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -811,7 +811,7 @@
 	cosa_enable_rx(chan);
 	spin_lock_irqsave(&cosa->lock, flags);
 	add_wait_queue(&chan->rxwaitq, &wait);
-	while(!chan->rx_status) {
+	while (!chan->rx_status) {
 		current->state = TASK_INTERRUPTIBLE;
 		spin_unlock_irqrestore(&cosa->lock, flags);
 		schedule();
@@ -896,7 +896,7 @@
 
 	spin_lock_irqsave(&cosa->lock, flags);
 	add_wait_queue(&chan->txwaitq, &wait);
-	while(!chan->tx_status) {
+	while (!chan->tx_status) {
 		current->state = TASK_INTERRUPTIBLE;
 		spin_unlock_irqrestore(&cosa->lock, flags);
 		schedule();
@@ -1153,7 +1153,7 @@
 	struct channel_data *channel, unsigned int cmd, unsigned long arg)
 {
 	void __user *argp = (void __user *)arg;
-	switch(cmd) {
+	switch (cmd) {
 	case COSAIORSET:	/* Reset the device */
 		if (!capable(CAP_NET_ADMIN))
 			return -EACCES;
@@ -1704,7 +1704,7 @@
 			spin_unlock_irqrestore(&cosa->lock, flags);
 			return;
 		}
-		while(1) {
+		while (1) {
 			cosa->txchan++;
 			i++;
 			if (cosa->txchan >= cosa->nchannels)
@@ -2010,7 +2010,7 @@
 static void debug_status_in(struct cosa_data *cosa, int status)
 {
 	char *s;
-	switch(status & SR_CMD_FROM_SRP_MASK) {
+	switch (status & SR_CMD_FROM_SRP_MASK) {
 	case SR_UP_REQUEST:
 		s = "RX_REQ";
 		break;
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index f1bff98..1ceccf1 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -141,7 +141,7 @@
 	    data->address != CISCO_UNICAST)
 		return cpu_to_be16(ETH_P_HDLC);
 
-	switch(data->protocol) {
+	switch (data->protocol) {
 	case cpu_to_be16(ETH_P_IP):
 	case cpu_to_be16(ETH_P_IPX):
 	case cpu_to_be16(ETH_P_IPV6):
@@ -190,7 +190,7 @@
 		cisco_data = (struct cisco_packet*)(skb->data + sizeof
 						    (struct hdlc_header));
 
-		switch(ntohl (cisco_data->type)) {
+		switch (ntohl (cisco_data->type)) {
 		case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
 			in_dev = dev->ip_ptr;
 			addr = 0;
@@ -245,8 +245,8 @@
 
 			dev_kfree_skb_any(skb);
 			return NET_RX_SUCCESS;
-		} /* switch(keepalive type) */
-	} /* switch(protocol) */
+		} /* switch (keepalive type) */
+	} /* switch (protocol) */
 
 	printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name,
 	       ntohs(data->protocol));
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
index aa9248f..6e1ca25 100644
--- a/drivers/net/wan/hdlc_x25.c
+++ b/drivers/net/wan/hdlc_x25.c
@@ -202,10 +202,10 @@
 		return 0; /* return protocol only, no settable parameters */
 
 	case IF_PROTO_X25:
-		if(!capable(CAP_NET_ADMIN))
+		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
-		if(dev->flags & IFF_UP)
+		if (dev->flags & IFF_UP)
 			return -EBUSY;
 
 		result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
index e803a7d..25c24f0 100644
--- a/drivers/net/wimax/i2400m/fw.c
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -612,7 +612,7 @@
 		goto error_wait_for_ack;
 	}
 	rx_bytes = result;
-	/* verify the ack and read more if neccessary [result is the
+	/* verify the ack and read more if necessary [result is the
 	 * final amount of bytes we get in the ack]  */
 	result = __i2400m_bm_ack_verify(i2400m, opcode, ack, ack_size, flags);
 	if (result < 0)
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index 04df9bb..820b128 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -627,7 +627,7 @@
  * @I2400M_BRI_NO_REBOOT: Do not reboot the device and proceed
  *     directly to wait for a reboot barker from the device.
  * @I2400M_BRI_MAC_REINIT: We need to reinitialize the boot
- *     rom after reading the MAC adress. This is quite a dirty hack,
+ *     rom after reading the MAC address. This is quite a dirty hack,
  *     if you ask me -- the device requires the bootrom to be
  *     intialized after reading the MAC address.
  */
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
index 76a50ac..14f876b 100644
--- a/drivers/net/wimax/i2400m/sdio.c
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -304,7 +304,7 @@
  *
  * The device will be fully reset internally, but won't be
  * disconnected from the bus (so no reenumeration will
- * happen). Firmware upload will be neccessary.
+ * happen). Firmware upload will be necessary.
  *
  * The device will send a reboot barker that will trigger the driver
  * to reinitialize the state via __i2400m_dev_reset_handle.
@@ -314,7 +314,7 @@
  *
  * The device will be fully reset internally, disconnected from the
  * bus an a reenumeration will happen. Firmware upload will be
- * neccessary. Thus, we don't do any locking or struct
+ * necessary. Thus, we don't do any locking or struct
  * reinitialization, as we are going to be fully disconnected and
  * reenumerated.
  *
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index 98f4f8c5..99f04c4 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -246,7 +246,7 @@
  *
  * The device will be fully reset internally, but won't be
  * disconnected from the USB bus (so no reenumeration will
- * happen). Firmware upload will be neccessary.
+ * happen). Firmware upload will be necessary.
  *
  * The device will send a reboot barker in the notification endpoint
  * that will trigger the driver to reinitialize the state
@@ -257,7 +257,7 @@
  *
  * The device will be fully reset internally, disconnected from the
  * USB bus an a reenumeration will happen. Firmware upload will be
- * neccessary. Thus, we don't do any locking or struct
+ * necessary. Thus, we don't do any locking or struct
  * reinitialization, as we are going to be fully disconnected and
  * reenumerated.
  *
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index f4650fc..257c734 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -394,7 +394,7 @@
 		ieee80211_tx_status_irqsafe(ar->hw, skb);
 	}
 
-	for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) {
+	for_each_set_bit(i, &queue_bitmap, BITS_PER_BYTE) {
 #ifdef AR9170_QUEUE_STOP_DEBUG
 		printk(KERN_DEBUG "%s: wake queue %d\n",
 		       wiphy_name(ar->hw->wiphy), i);
@@ -2512,7 +2512,7 @@
 	/*
 	 * this buffer is used for rx stream reconstruction.
 	 * Under heavy load this device (or the transport layer?)
-	 * tends to split the streams into seperate rx descriptors.
+	 * tends to split the streams into separate rx descriptors.
 	 */
 
 	skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL);
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
index be992ca..c29c994 100644
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c
@@ -89,7 +89,7 @@
 	for (i = 0; i < __IWM_DM_NR; i++)
 		iwm->dbg.dbg_module[i] = 0;
 
-	for_each_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR)
+	for_each_set_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR)
 		iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level;
 
 	return 0;
diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h
index a3a79b5..a855a99 100644
--- a/drivers/net/wireless/iwmc3200wifi/lmac.h
+++ b/drivers/net/wireless/iwmc3200wifi/lmac.h
@@ -262,7 +262,7 @@
 
 /* Power Management */
 #define POWER_TABLE_CMD			0x77
-#define SAVE_RESTORE_ADRESS_CMD		0x78
+#define SAVE_RESTORE_ADDRESS_CMD		0x78
 #define REPLY_WATERMARK_CMD		0x79
 #define PM_DEBUG_STATISTIC_NOTIFIC	0x7B
 #define PD_FLUSH_N_NOTIFICATION		0x7C
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index ad8f7ea..8456b4d 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -1116,7 +1116,7 @@
 		return -EINVAL;
 	}
 
-	for_each_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
+	for_each_set_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
 		tid_info = &sta_info->tid_info[bit];
 
 		mutex_lock(&tid_info->mutex);
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index ee34c13..9b04964 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -368,7 +368,7 @@
 
 		/*
 		 * The encryption key doesn't fit within the CSR cache,
-		 * this means we should allocate it seperately and use
+		 * this means we should allocate it separately and use
 		 * rt2x00usb_vendor_request() to send the key to the hardware.
 		 */
 		reg = KEY_ENTRY(key->hw_key_idx);
@@ -382,7 +382,7 @@
 		/*
 		 * The driver does not support the IV/EIV generation
 		 * in hardware. However it demands the data to be provided
-		 * both seperately as well as inside the frame.
+		 * both separately as well as inside the frame.
 		 * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib
 		 * to ensure rt2x00lib will not strip the data from the
 		 * frame after the copy, now we must tell mac80211
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 5e4ee20..d27d7d5 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -99,7 +99,7 @@
 	 * There are 2 variations of the rt2870 firmware.
 	 * a) size: 4kb
 	 * b) size: 8kb
-	 * Note that (b) contains 2 seperate firmware blobs of 4k
+	 * Note that (b) contains 2 separate firmware blobs of 4k
 	 * within the file. The first blob is the same firmware as (a),
 	 * but the second blob is for the additional chipsets.
 	 */
@@ -117,7 +117,7 @@
 
 	/*
 	 * 8kb firmware files must be checked as if it were
-	 * 2 seperate firmware files.
+	 * 2 separate firmware files.
 	 */
 	while (offset < len) {
 		if (!rt2800usb_check_crc(data + offset, 4096))
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 70c04c2..28a1c46 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -109,7 +109,7 @@
 
 	/*
 	 * HW crypto statistics.
-	 * All statistics are stored seperately per cipher type.
+	 * All statistics are stored separately per cipher type.
 	 */
 	struct rt2x00debug_crypto crypto_stats[CIPHER_MAX];
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index b93731b..dd5ab8f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -394,7 +394,7 @@
 	/*
 	 * Hardware might have stripped the IV/EIV/ICV data,
 	 * in that case it is possible that the data was
-	 * provided seperately (through hardware descriptor)
+	 * provided separately (through hardware descriptor)
 	 * in which case we should reinsert the data into the frame.
 	 */
 	if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) &&
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 0b4801a..5b6b789 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -497,7 +497,7 @@
 	/*
 	 * When hardware encryption is supported, and this frame
 	 * is to be encrypted, we should strip the IV/EIV data from
-	 * the frame so we can provide it to the driver seperately.
+	 * the frame so we can provide it to the driver separately.
 	 */
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
 	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index e2da928..1774727 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -476,7 +476,7 @@
 		 * The driver does not support the IV/EIV generation
 		 * in hardware. However it doesn't support the IV/EIV
 		 * inside the ieee80211 frame either, but requires it
-		 * to be provided seperately for the descriptor.
+		 * to be provided separately for the descriptor.
 		 * rt2x00lib will cut the IV/EIV data out of all frames
 		 * given to us by mac80211, but we must tell mac80211
 		 * to generate the IV/EIV data.
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 47f3e4a..290d70b 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -339,7 +339,7 @@
 		 * The driver does not support the IV/EIV generation
 		 * in hardware. However it doesn't support the IV/EIV
 		 * inside the ieee80211 frame either, but requires it
-		 * to be provided seperately for the descriptor.
+		 * to be provided separately for the descriptor.
 		 * rt2x00lib will cut the IV/EIV data out of all frames
 		 * given to us by mac80211, but we must tell mac80211
 		 * to generate the IV/EIV data.
@@ -439,7 +439,7 @@
 		 * The driver does not support the IV/EIV generation
 		 * in hardware. However it doesn't support the IV/EIV
 		 * inside the ieee80211 frame either, but requires it
-		 * to be provided seperately for the descriptor.
+		 * to be provided separately for the descriptor.
 		 * rt2x00lib will cut the IV/EIV data out of all frames
 		 * given to us by mac80211, but we must tell mac80211
 		 * to generate the IV/EIV data.
@@ -1661,7 +1661,7 @@
 
 		/*
 		 * Hardware has stripped IV/EIV data from 802.11 frame during
-		 * decryption. It has provided the data seperately but rt2x00lib
+		 * decryption. It has provided the data separately but rt2x00lib
 		 * should decide if it should be reinserted.
 		 */
 		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index e240996..00e09e2 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -374,7 +374,7 @@
  * zd_mac_tx_failed - callback for failed frames
  * @dev: the mac80211 wireless device
  *
- * This function is called if a frame couldn't be successfully be
+ * This function is called if a frame couldn't be successfully
  * transferred. The first frame from the tx queue, will be selected and
  * reported as error to the upper layers.
  */
diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c
index 0be1d50..caa1531 100644
--- a/drivers/parisc/eisa_enumerator.c
+++ b/drivers/parisc/eisa_enumerator.c
@@ -460,7 +460,7 @@
 			       slot, id_string);
 			
 			print_eisa_id(id_string, es->eisa_slot_id);
-			printk(" expected %s \n", id_string);
+			printk(" expected %s\n", id_string);
 		
 			return -1;	
 			
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 0bc5d47..1062b8f 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -481,7 +481,7 @@
 	return ret;
 }
 
-static struct sysfs_ops pdcspath_attr_ops = {
+static const struct sysfs_ops pdcspath_attr_ops = {
 	.show = pdcspath_attr_show,
 	.store = pdcspath_attr_store,
 };
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index a35c9c5..f7806d8 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -169,7 +169,7 @@
 	/* ...then properly fixup the USB to point at suckyio PIC */
 	sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev);
 
-	printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
+	printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i)\n",
 	       pci_name(pdev), pdev->irq);
 
 	pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base);
diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog
deleted file mode 100644
index 8565bbb..0000000
--- a/drivers/parport/ChangeLog
+++ /dev/null
@@ -1,583 +0,0 @@
-2001-10-11  Tim Waugh  <twaugh@redhat.com>
-	* parport_pc.c, parport_serial.c: Support for NetMos cards.
-	+ Patch originally from Michael Reinelt <reinelt@eunet.at>.
-
-2002-04-25  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_serial.c, parport_pc.c: Move some SIIG cards around.
-	Patch from Andrey Panin.
-
-2002-01-20  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_compat_write_block_pio,
-	parport_pc_ecp_write_block_pio, parport_pc_ecp_read_block_pio):
-	Use the default implementations if the caller wants to use
-	O_NONBLOCK.
-
-2002-02-25  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c: Make sure that priv->ctr_writable includes IntEn
-	even if IRQ is given as a parameter.
-
-2002-01-21  Tim Waugh  <twaugh@redhat.com>
-
-	* daisy.c: Apply patch from Max Vorobiev to make parport_daisy_select
-	work for ECP/EPP modes.
-
-2002-01-13  Niels Kristian Bech Jensen  <nkbj@image.dk>
-
-	* parport_pc.c: Change some occurrences of frob_set_mode to
-	ECR_WRITE.  This fixes PLIP.
-
-2002-01-04  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (parport_claim_or_block): Sleep interruptibly to prevent
-	a possible deadlock.
-
-2001-12-07  Damian Gruszka  <damian.gruszka@VisionSystems.de>
-
-	* parport_pc.c (ECR_WRITE): Define.  If there are forbidden bits
-	in the ECR register for some chips, this will be a useful place to
-	put that knowledge.
-	(change_mode): Use ECR_WRITE.
-	(parport_pc_restore_state): Likewise.
-	(parport_ECPPS2_supported): Likewise.
-	(parport_ECPEPP_supported): Likewise.
-	(irq_probe_EPP): Likewise.
-	(programmable_irq_support): Likewise.
-	(programmable_dma_support): Likewise.
-	(parport_pc_probe_port): Likewise.
-
-	(frob_set_mode): New function.  Set the mode bits of the ECR.
-	(get_fifo_residue): Use frob_set_mode.
-	(parport_pc_ecpepp_read_data): Likewise.
-	(parport_pc_ecpepp_write_data): Likewise.
-	(parport_pc_ecpepp_read_addr): Likewise.
-	(parport_pc_ecpepp_write_addr): Likewise.
-	(parport_pc_compat_write_block_pio): Likewise.
-	(parport_pc_ecp_write_block_pio): Likewise.
-	(parport_ECR_present): Likewise.
-	(parport_ECP_supported): Likewise.
-	(parport_EPP_supported): Likewise.
-	(parport_ECPEPP_supported): Likewise.
-	(programmable_irq_support): Likewise.
-	(irq_probe_ECP): Likewise.
-	(programmable_dma_support): Likewise.
-
-	(parport_pc_enable_irq): Only enable interrupts if we know which
-	IRQ line they will come from.
-	(parport_pc_init_state): Set nErrIntrEn at initialisation.
-	(parport_pc_restore_state): Only write writable bits of CTR.
-	(parport_irq_probe): If no IRQ is found, take ackIntEn out of the
-	writable bit set.
-
-2001-12-07  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_fifo_write_block_pio): Correct typo.
-	(parport_pc_init_state): Only set ackIntEn if we know which IRQ
-	line the interrupts will come from.
-
-2001-12-07  Tim Waugh  <twaugh@redhat.com>
-
-	* ieee1284_ops.c (parport_ieee1284_epp_write_addr,
-	parport_ieee1284_epp_read_addr): Actually do something useful.
-
-2001-12-07  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (dmaval): Don't use DMA by default.  It seems to be
-	too buggy at the moment.  Use 'dma=auto' to restore the previous
-	behaviour.
-
-2001-12-07  Tim Waugh  <twaugh@redhat.com>
-
-	* daisy.c (DEBUG): Undefine.
-
-2001-12-06  Tim Waugh  <twaugh@redhat.com>
-
-	* ieee1284_ops.c (parport_ieee1284_ecp_read_data): Mask off
-	PARPORT_CONTROL_AUTOFD as well.  Bug spotted by Joe
-	<joeja@mindspring.com>.
-
-2001-12-03  Rich Liu  <Rich.Liu@ite.com.tw>
-
-	* parport_pc.c (sio_ite_8872_probe): ITE8873 is a single-port
-	serial board, not a serial+parallel.
-
-2001-11-30  Niels Kristian Bech Jensen  <nkbj@image.dk>
-
-	* parport_pc.c: Fix compiler warning.
-
-2001-11-14  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_pci_probe): Hooks for PCI cards before
-	and after probing for ports.
-	* parport_serial.c (parport_register): Likewise.
-
-2001-11-12  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (init_module): Warn when parameters are ignored.
-
-2001-11-01  Damian Gruszka  <damian.gruszka@VisionSystems.de>
-
-	* parport_serial.c (serial_register): Set base_baud before
-	calling register_serial.
-
-2001-10-26  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_irq_probe): When ECR programmable IRQ
-	support fails, generate interrupts using the FIFO even if we don't
-	want to use the FIFO for real data transfers.
-	(parport_pc_probe_port): Display the ECR address if we have an
-	ECR, not just if we will use the FIFO.
-
-2001-10-24  Dave Strauss  <D.Strauss@motorola.com>
-
-	* parport_pc.c (parport_pc_compat_write_block_pio,
-	parport_pc_ecp_write_block_pio): Allow a few seconds for an ECP
-	transfer to finish up.
-
-2001-10-11  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc (sio_ite_8872_probe): New function, submitted by Rich
-	Liu from ITE.  Cleaned up, removed bogus phys_to_virt calls.
-
-2001-10-24  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c: Support for AKS AladdinCARD.  Patch from
-	Aladdin Knowledge Systems (Christian Groessler).
-
-2001-10-24  Tim Waugh  <twaugh@redhat.com>
-	
-	* ieee1284_ops.c (parport_ieee1284_ecp_read_data): Try to minimise
-	turnaround time.
-
-	* ieee1284.c (parport_poll_peripheral): Try a couple of times
-	first without delaying.
-
-2001-10-10  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c: Support for OX16PCI954 PCI card.
-
-2001-10-10  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c: Support for OX12PCI840 PCI card (reported by
-	mk@daveg.com).  Lock-ups diagnosed by Ronnie Arosa (and now we
-	just don't trust its ECR).
-
-2001-10-10  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
-
-	* parport_pc.c: Support for AVLAB cards.
-
-2001-10-10  Tim Waugh  <twaugh@redhat.com>
-
-	* ieee1284_ops.c (ecp_forward_to_reverse, ecp_reverse_to_forward):
-	Remember to retry direction switch if it fails.  Patch from David
-	Lambert.
-
-2001-10-08  David C. Hansen  <haveblue@us.ibm.com>
-
-	* share.c: Make driverlist_lock and parportlist_lock static.
-
-2001-10-08  Philip Blundell  <philb@gnu.org>
-
-	* parport_pc.c: New modular parameter verbose_logging.
-	Make port->modes indicate the modes that we are prepared to use,
-	rather than the modes that are available.
-
-2001-10-07  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_probe_port): Fix memory leak spotted by
-	Kipp Cannon.
-
-2001-10-07  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_serial.c: Remove NetMos support, since it causes problems
-	for some people.
-
-2001-08-30  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_serial.c (parport_serial_pci_probe): Clean-up on partial
-	registration failure.
-
-2001-08-14  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_init_superio): Allow for more than one
-	SuperIO device.  Patch from Rich Lio (ITE).
-
-2001-08-11  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c: Support for Titan Electronics cards.
-
-2001-08-08  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (parport_unregister_device): Remove device from wait list
-	too.
-
-2001-06-20  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c: Make 'io_hi=0' work.
-
-2001-05-31  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_serial.c: New file.
-
-2001-06-05  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_unregister_port): New exported function.
-	Do the opposite of parport_pc_probe_port.
-	(cleanup_module): Use it.
-
-2001-05-22  Juan Quintela  <quintela@mandrakesoft.com>
-
-	* parport_amiga.c: Set printk levels.
-	* parport_gsc.c: Likewise.
-	* parport_mfc3.c: Likewise.
-	* parport_pc.c: Likewise.
-	* parport_sunbpp.c: Likewise.
-	* probe.c: Likewise.
-	* share.c: Likewise.
-
-2001-05-10  Fred Barnes  <frmb2@ukc.ac.uk>
-
-       * parport_pc.c (parport_pc_epp_read_data): added support for
-       reading from a w91284pic peripheral, flag is PARPORT_W91284PIC.
-
-2001-05-07  Fred Barnes  <frmb2@ukc.ac.uk>
- 
- 	* parport_pc.c (parport_pc_epp_read_data,
-	parport_pc_epp_write_data, parport_pc_epp_read_addr,
-	parport_pc_epp_write_addr): support for fast reads/writes using
-	the PARPORT_EPP_FAST flag.
- 
- 	* ieee1284.c (parport_read, parport_write): added code to handle
-	software EPP mode (IEEE1284_MODE_EPPSWE).  Added code to allow
-	BYTE mode reverse transfers (previously always went for NIBBLE
-	mode).
- 
- 	* ieee1284_ops.c (parport_ieee1284_epp_read_data,
-	parport_ieee1284_epp_write_data): fixed various polarity problems.
-	Also (theoretically) fixed address versions (.._addr), but no
-	hardware to test this on.
- 
- 	* parport_pc.h: added parport_dump_state() function for debugging.
- 	Needs to have DEBUG_PARPORT to be defined for it to be included.
- 
-2001-05-03  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c: Fix the compile problem I introduce from the last
-	change.
-
-2001-04-20  Paul Gortmaker  <p_gortmaker@yahoo.com>
-
-	* parport_pc.c: Cut down the size quite a bit (more than 4k off
-	the object, about 1k off the zImage) for the older non-PCI
-	machines which are typically resource starved anyway...
-
-2001-03-26  R Horn  <rjh@world.std.com>
-
-	* parport_pc.c: Some commentary changes.
-
-2001-04-19  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_probe_port): Remove __devinit
-	attribute.  Export unconditionally.
-
-2001-04-14  Jeff Garzik  <jgarzik@pobox.com>
-
-	Merged:  2001-03-30  Tim Waugh  <twaugh@redhat.com>
-
-        * drivers/parport/parport_pc.c: Make Via SuperIO chipsets behave
-        like everything else with respect to irq= and dma= parameters.
-
-2001-04-08  Tim Waugh  <twaugh@redhat.com>
-
-      * parport_pc.c (parport_pc_save_state): Read from the soft copy of
-      the control port.
-      (parport_pc_restore_state): Update the soft copy of the control
-      port.
-
-2001-03-26  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (parport_find_number, parport_find_base): Trigger
-	a lowlevel driver load if there are no ports yet.
-
-2001-03-26  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_ECP_supported): Remove the IRQ conflict
-	check since it seems totally unreliable.
-
-2001-03-02  Tim Waugh  <twaugh@redhat.com>
-
-	* ieee1284_ops.c (parport_ieee1284_read_nibble): Reset nAutoFd
-	on timeout.  Matches 2.2.x behaviour.
-
-2001-03-02  Andrew Morton
-
-	* parport_pc.c (registered_parport): New static variable.
-	(parport_pc_find_ports): Set it when we register PCI driver.
-	(init_module): Unregister PCI driver if necessary when we
-	fail.
-
-2001-03-02  Tim Waugh  <twaugh@redhat.com>
-
-	* ieee1284_ops.c (parport_ieee1284_write_compat): Don't use
-	down_trylock to reset the IRQ count.  Don't even use sema_init,
-	because it's not even necessary to reset the count.  I can't
-	remember why we ever did.
-
-2001-01-04  Peter Osterlund  <peter.osterlund@mailbox.swipnet.se>
-
-	* ieee1284.c (parport_negotiate): Fix missing printk argument.
-
-2001-01-03  Paul Schleger  <Paul.Schleger@t-online.de>
-
-	* probe.c (parse_data): Get rid of trailing blanks in values.
-	Needed for XEROX XJ8C printer.
-
-2001-01-03  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_probe_port): Say something when probes
-	are omitted.
-
-2001-01-03  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (sio_via_686a_probe): Correct dma=255 fix.
-
-2000-11-21  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_ecp_write_block_pio): Fix
-	reverse-to-forward logic.  Spotted by Roland Kuck
-	<rci@cityweb.de>.
-
-2000-09-16  Cesar Eduardo Barros  <cesarb@nitnet.com.br>
-
-	* parport_pc.c (sio_via_686a_probe): Handle case
-	where hardware returns 255 for IRQ or DMA.
-
-2000-07-20  Eddie C. Dost  <ecd@skynet.be>
-
-	* share.c (attach_driver_chain): attach[i](port) needs to be
-	replaced by attach[count](port).
-
-2000-07-20  Eddie C. Dost  <ecd@skynet.be>
-
-	* daisy.c (add_dev): kmalloc args are in wrong order.
-
-2000-07-12  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c: Documentation for parport_{get,port}_port,
-	parport_find_{number,base}.
-
-2000-07-12  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (parport_unregister_device): Remove unneeded locking
-	(test cad==dev).
-	(parport_claim): Likewise.
-	(parport_find_number): New function.
-
-2000-07-12  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (parport_register_port): Hold the parportlist_lock while
-	looking for a free parport number.
-	(parport_register_driver): Make sure that attach can block.
-	(attach_driver_chain): Likewise.
-
-2000-07-12  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (call_driver_chain): Do reference counting things.
-	(parport_get_port): New function.
-	(parport_put_port): New function.
-	(parport_register_port): Initialise reference count to zero.
-	(parport_unregister_port): Check reference count rather than
-	driver list to see if we can free the port.
-
-2000-07-12  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c: Clarifications in doc comments.
-
-2000-07-12  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (parport_unregister_port): Fix typo in comment.
-
-2000-07-11  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
-
-	* parport_pc.c: Support for the full range of Timedia cards.
-
-2000-07-08  Tim Waugh  <twaugh@redhat.com>
-
-	* daisy.c: License block comments as part of parportbook.
-	* ieee1284.c: Likewise.
-	* share.c: Likewise.
-
-2000-06-30  Petr Vandrovec  <vandrove@vc.cvut.cz>
-
-	* procfs.c (do_hardware_modes): Generated string can be up to 34
-	chars long.
-
-2000-06-20  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
-
-	* parport_pc.c (parport_pc_compat_write_block_pio): Warn about
-	change_mode failures.
-	(parport_pc_ecp_write_block_pio): Likewise.
-	(parport_pc_ecp_read_block_pio): Likewise.
-
-2000-06-20  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
-
-	* parport_pc.c (parport_SPP_supported): Warn more about possibly
-	incorrect parameters.
-
-2000-06-15  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_ECP_supported): Set PARPORT_MODE_COMPAT
-	for ECP ports, since they can all do hardware accelerated
-	compatibility mode (I assume).
-
-2000-06-13  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (cleanup_module): Remark about possible bugs.
-
-2000-06-13  Tim Waugh  <twaugh@redhat.com>
-
-	* procfs.c: Break 'hardware' out into separate files.
-
-2000-05-28  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
-
-	* Fix PCI ID printk for non-superio PCI cards.
-
-2000-05-28  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (call_driver_chain): Get the driverlist_lock.
-	(parport_register_device): Make sure that port->devices always
-	looks consistent.
-	(parport_register_driver): Ensure that parport drivers are given
-	parameters that are valid for the duration of the callback by
-	locking the portlist against changes.
-	(parport_unregister_driver): Likewise.
-	(parport_claim): Don't overwrite flags.
-
-2000-05-28  Tim Waugh  <twaugh@redhat.com>
-
-	* daisy.c (assign_addrs): Avoid double-probing daisy-chain devices
-	if the first probe succeeds.
-
-2000-05-16  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (parport_claim): Fix SMP race.
-
-2000-05-15  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
-
-	* parport_pc.c (parport_pc_compat_write_block_pio): Check for
-	timeouts.
-	(parport_pc_ecp_write_block_pio): Likewise.
-	(parport_pc_ecp_read_block_pio): Likewise.
-
-2000-05-02  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
-
-	* parport_pc.c: PCI SYBA patch and verbose PCI detection.
-
-2000-05-02  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
-
-	* parport_pc.c (decode_smsc): Fix SMSC 665/666 identification.
-
-2000-04-28  Tim Waugh  <twaugh@redhat.com>
-
-	* ieee1284.c: Short function descriptions can't be multiline.
-
-	* daisy.c: Short function descriptions can't be multiline.
-
-2000-04-19  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_fifo_write_block_dma): Make maxlen
-	calculation a bit clearer.
-
-	* ieee1284.c (parport_negotiate): Turn on data line drivers.
-
-	* ieee1284_ops.c (parport_ieee1284_read_byte): Turn off data line
-	drivers.
-	(parport_ieee1284_write_compat): Turn on data line drivers.
-
-	* daisy.c (assign_addrs): Turn on data line drivers.
-	(cpp_mux): Likewise.
-	(cpp_daisy): Likewise.
-
-2000-04-04  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c: Add support for another PCI card.
-
-2000-04-04  Tim Waugh  <twaugh@redhat.com>
-
-	* daisy.c: Documentation in kernel-doc format.
-
-	* ieee1284.c: Likewise.
-
-	* share.c: Likewise.
-
-2000-04-01  Tim Waugh  <twaugh@redhat.com>
-
-	* share.c (parport_register_device): Need to hold the module
-	reference counts before sleeping.
-
-2000-03-27  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_ecp_read_block_pio): Correct operation
-	when peripheral is trying to send data when we stop listening.
-
-2000-03-22  Tim Waugh  <twaugh@redhat.com>
-
-	* init.c (parport_setup): Fix return value.
-
-2000-03-21  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_pci_probe): Fix return value; call
-	pci_enable_device.
-
-2000-03-16  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_ECP_supported): This seems to trigger on
-	machines that don't have an IRQ conflict; toned down the warning
-	message accordingly.
-
-2000-03-16  Gunther Mayer  <gunther.mayer@braunschweig.netsurf.de>
-
-	* parport_pc.c (show_parconfig_smsc37c669): Fix typo.
-	(decode_winbond): More IDs.
-	(winbond_check): Protect against false positives.
-	(winbond_check2): Likewise.
-	(smsc_check): Likewise.
-
-2000-03-15  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (cleanup_module): Don't call pci_unregister_driver
-	if we didn't call pci_register_driver first.
-
-2000-03-13  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (parport_pc_init): Moved from asm/parport.h.
-
-	* Config.in: CONFIG_PARPORT_PC_SUPERIO: new option.
-
-	* parport_pc.c (show_parconfig_smsc37c669): Make __devinit.
-	(show_parconfig_winbond): Likewise.
-	(decode_winbond): Likewise.
-	(decode_smsc): Likewise.
-	(winbond_check): Likewise.
-	(winbond_check2): Likewise.
-	(smsc_check): Likewise.
-	(detect_and_report_winbond): Likewise.
-	(detect_and_report_smsc): Likewise.
-	(get_superio_dma): Likewise.
-	(get_superio_irq): Likewise.
-	(parport_pc_find_isa_ports): New function.
-	(parport_pc_find_ports): New function.
-	(init_module): Make superio a config option, not a parameter.
-
-2000-03-10  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c (decode_winbond): Use correct 83877ATF chip ID.
-	(decode_winbond): Fix typo.
-
-2000-03-09  Tim Waugh  <twaugh@redhat.com>
-
-	* parport_pc.c: Integrate SuperIO PCI probe with normal PCI card
-	probe, so that the MODULE_DEVICE_TABLE is complete.
-
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index ad113b0..0950fa4 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2908,6 +2908,7 @@
 	netmos_9805,
 	netmos_9815,
 	netmos_9901,
+	netmos_9865,
 	quatech_sppxp100,
 };
 
@@ -2989,6 +2990,7 @@
 	/* netmos_9805 */               { 1, { { 0, -1 }, } },
 	/* netmos_9815 */               { 2, { { 0, -1 }, { 2, -1 }, } },
 	/* netmos_9901 */               { 1, { { 0, -1 }, } },
+	/* netmos_9865 */               { 1, { { 0, -1 }, } },
 	/* quatech_sppxp100 */		{ 1, { { 0, 1 }, } },
 };
 
@@ -3092,6 +3094,10 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
 	  0xA000, 0x2000, 0, 0, netmos_9901 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+	  0xA000, 0x1000, 0, 0, netmos_9865 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+	  0xA000, 0x2000, 0, 0, netmos_9865 },
 	/* Quatech SPPXP-100 Parallel port PCI ExpressCard */
 	{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 },
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 712250f..26301cb 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -288,9 +288,9 @@
 			next = dev->bus_list.next;
 
 		/* Run device routines with the device locked */
-		down(&dev->dev.sem);
+		device_lock(&dev->dev);
 		retval = cb(dev, userdata);
-		up(&dev->dev.sem);
+		device_unlock(&dev->dev);
 		if (retval)
 			break;
 	}
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 6151389..0a894ef 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -73,7 +73,7 @@
 }
 
 static struct kobj_type legacy_ktype = {
-	.sysfs_ops = &(struct sysfs_ops){
+	.sysfs_ops = &(const struct sysfs_ops){
 		.store = legacy_store, .show = legacy_show
 	},
 	.release = &legacy_release,
diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c
index ec73294..e2dc289 100644
--- a/drivers/pci/hotplug/ibmphp_res.c
+++ b/drivers/pci/hotplug/ibmphp_res.c
@@ -40,7 +40,7 @@
 static int once_over (void);
 static int remove_ranges (struct bus_node *, struct bus_node *);
 static int update_bridge_ranges (struct bus_node **);
-static int add_range (int type, struct range_node *, struct bus_node *);
+static int add_bus_range (int type, struct range_node *, struct bus_node *);
 static void fix_resources (struct bus_node *);
 static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8);
 
@@ -133,7 +133,7 @@
 		newrange->rangeno = 1;
 	else {
 		/* need to insert our range */
-		add_range (flag, newrange, newbus);
+		add_bus_range (flag, newrange, newbus);
 		debug ("%d resource Primary Bus inserted on bus %x [%x - %x]\n", flag, newbus->busno, newrange->start, newrange->end);
 	}
 
@@ -384,7 +384,7 @@
  * Input: type of the resource, range to add, current bus
  * Output: 0 or -1, bus and range ptrs 
  ********************************************************************************/
-static int add_range (int type, struct range_node *range, struct bus_node *bus_cur)
+static int add_bus_range (int type, struct range_node *range, struct bus_node *bus_cur)
 {
 	struct range_node *range_cur = NULL;
 	struct range_node *range_prev;
@@ -455,7 +455,7 @@
 
 /*******************************************************************************
  * This routine goes through the list of resources of type 'type' and updates
- * the range numbers that they correspond to.  It was called from add_range fnc
+ * the range numbers that they correspond to.  It was called from add_bus_range fnc
  *
  * Input: bus, type of the resource, the rangeno starting from which to update
  ******************************************************************************/
@@ -1999,7 +1999,7 @@
 
 							if (bus_sec->noIORanges > 0) {
 								if (!range_exists_already (range, bus_sec, IO)) {
-									add_range (IO, range, bus_sec);
+									add_bus_range (IO, range, bus_sec);
 									++bus_sec->noIORanges;
 								} else {
 									kfree (range);
@@ -2048,7 +2048,7 @@
 
 							if (bus_sec->noMemRanges > 0) {
 								if (!range_exists_already (range, bus_sec, MEM)) {
-									add_range (MEM, range, bus_sec);
+									add_bus_range (MEM, range, bus_sec);
 									++bus_sec->noMemRanges;
 								} else {
 									kfree (range);
@@ -2102,7 +2102,7 @@
 
 							if (bus_sec->noPFMemRanges > 0) {
 								if (!range_exists_already (range, bus_sec, PFMEM)) {
-									add_range (PFMEM, range, bus_sec);
+									add_bus_range (PFMEM, range, bus_sec);
 									++bus_sec->noPFMemRanges;
 								} else {
 									kfree (range);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 807224e..de29645 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -642,6 +642,7 @@
 	if (!b->legacy_io)
 		goto kzalloc_err;
 
+	sysfs_bin_attr_init(b->legacy_io);
 	b->legacy_io->attr.name = "legacy_io";
 	b->legacy_io->size = 0xffff;
 	b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
@@ -654,6 +655,7 @@
 		goto legacy_io_err;
 
 	/* Allocated above after the legacy_io struct */
+	sysfs_bin_attr_init(b->legacy_mem);
 	b->legacy_mem = b->legacy_io + 1;
 	b->legacy_mem->attr.name = "legacy_mem";
 	b->legacy_mem->size = 1024*1024;
@@ -800,6 +802,7 @@
 	if (res_attr) {
 		char *res_attr_name = (char *)(res_attr + 1);
 
+		sysfs_bin_attr_init(res_attr);
 		if (write_combine) {
 			pdev->res_attr_wc[num] = res_attr;
 			sprintf(res_attr_name, "resource%d_wc", num);
@@ -972,6 +975,7 @@
 		if (!attr)
 			return -ENOMEM;
 
+		sysfs_bin_attr_init(attr);
 		attr->size = dev->vpd->len;
 		attr->attr.name = "vpd";
 		attr->attr.mode = S_IRUSR | S_IWUSR;
@@ -1038,6 +1042,7 @@
 			retval = -ENOMEM;
 			goto err_resource_files;
 		}
+		sysfs_bin_attr_init(attr);
 		attr->size = rom_size;
 		attr->attr.name = "rom";
 		attr->attr.mode = S_IRUSR;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 5b548ae..cb1dd5f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -303,6 +303,49 @@
 }
 EXPORT_SYMBOL_GPL(pci_find_ext_capability);
 
+/**
+ * pci_bus_find_ext_capability - find an extended capability
+ * @bus:   the PCI bus to query
+ * @devfn: PCI device to query
+ * @cap:   capability code
+ *
+ * Like pci_find_ext_capability() but works for pci devices that do not have a
+ * pci_dev structure set up yet.
+ *
+ * Returns the address of the requested capability structure within the
+ * device's PCI configuration space or 0 in case the device does not
+ * support it.
+ */
+int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
+				int cap)
+{
+	u32 header;
+	int ttl;
+	int pos = PCI_CFG_SPACE_SIZE;
+
+	/* minimum 8 bytes per capability */
+	ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
+
+	if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
+		return 0;
+	if (header == 0xffffffff || header == 0)
+		return 0;
+
+	while (ttl-- > 0) {
+		if (PCI_EXT_CAP_ID(header) == cap)
+			return pos;
+
+		pos = PCI_EXT_CAP_NEXT(header);
+		if (pos < PCI_CFG_SPACE_SIZE)
+			break;
+
+		if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
+			break;
+	}
+
+	return 0;
+}
+
 static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
 {
 	int rc, ttl = PCI_FIND_CAP_TTL;
@@ -1540,8 +1583,10 @@
 	int pm;
 	u16 pmc;
 
+	pm_runtime_forbid(&dev->dev);
 	device_enable_async_suspend(&dev->dev);
 	dev->wakeup_prepared = false;
+
 	dev->pm_cap = 0;
 
 	/* find PCI PM capability in list */
@@ -2253,35 +2298,6 @@
 	}
 }
 
-#ifndef HAVE_ARCH_PCI_SET_DMA_MASK
-/*
- * These can be overridden by arch-specific implementations
- */
-int
-pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	if (!pci_dma_supported(dev, mask))
-		return -EIO;
-
-	dev->dma_mask = mask;
-	dev_dbg(&dev->dev, "using %dbit DMA mask\n", fls64(mask));
-
-	return 0;
-}
-    
-int
-pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
-	if (!pci_dma_supported(dev, mask))
-		return -EIO;
-
-	dev->dev.coherent_dma_mask = mask;
-	dev_dbg(&dev->dev, "using %dbit consistent DMA mask\n", fls64(mask));
-
-	return 0;
-}
-#endif
-
 #ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE
 int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
 {
@@ -2443,7 +2459,7 @@
 	if (!probe) {
 		pci_block_user_cfg_access(dev);
 		/* block PM suspend, driver probe, etc. */
-		down(&dev->dev.sem);
+		device_lock(&dev->dev);
 	}
 
 	rc = pci_dev_specific_reset(dev, probe);
@@ -2465,7 +2481,7 @@
 	rc = pci_parent_bus_reset(dev, probe);
 done:
 	if (!probe) {
-		up(&dev->dev.sem);
+		device_unlock(&dev->dev);
 		pci_unblock_user_cfg_access(dev);
 	}
 
@@ -3023,8 +3039,6 @@
 EXPORT_SYMBOL(pci_try_set_mwi);
 EXPORT_SYMBOL(pci_clear_mwi);
 EXPORT_SYMBOL_GPL(pci_intx);
-EXPORT_SYMBOL(pci_set_dma_mask);
-EXPORT_SYMBOL(pci_set_consistent_dma_mask);
 EXPORT_SYMBOL(pci_assign_resource);
 EXPORT_SYMBOL(pci_find_parent_resource);
 EXPORT_SYMBOL(pci_select_bars);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 039e87b..81d19d5 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2533,6 +2533,91 @@
 
 #endif	/* CONFIG_PCI_IOV */
 
+/*
+ * This is a quirk for the Ricoh MMC controller found as a part of
+ * some mulifunction chips.
+
+ * This is very similiar and based on the ricoh_mmc driver written by
+ * Philip Langdale. Thank you for these magic sequences.
+ *
+ * These chips implement the four main memory card controllers (SD, MMC, MS, xD)
+ * and one or both of cardbus or firewire.
+ *
+ * It happens that they implement SD and MMC
+ * support as separate controllers (and PCI functions). The linux SDHCI
+ * driver supports MMC cards but the chip detects MMC cards in hardware
+ * and directs them to the MMC controller - so the SDHCI driver never sees
+ * them.
+ *
+ * To get around this, we must disable the useless MMC controller.
+ * At that point, the SDHCI controller will start seeing them
+ * It seems to be the case that the relevant PCI registers to deactivate the
+ * MMC controller live on PCI function 0, which might be the cardbus controller
+ * or the firewire controller, depending on the particular chip in question
+ *
+ * This has to be done early, because as soon as we disable the MMC controller
+ * other pci functions shift up one level, e.g. function #2 becomes function
+ * #1, and this will confuse the pci core.
+ */
+
+#ifdef CONFIG_MMC_RICOH_MMC
+static void ricoh_mmc_fixup_rl5c476(struct pci_dev *dev)
+{
+	/* disable via cardbus interface */
+	u8 write_enable;
+	u8 write_target;
+	u8 disable;
+
+	/* disable must be done via function #0 */
+	if (PCI_FUNC(dev->devfn))
+		return;
+
+	pci_read_config_byte(dev, 0xB7, &disable);
+	if (disable & 0x02)
+		return;
+
+	pci_read_config_byte(dev, 0x8E, &write_enable);
+	pci_write_config_byte(dev, 0x8E, 0xAA);
+	pci_read_config_byte(dev, 0x8D, &write_target);
+	pci_write_config_byte(dev, 0x8D, 0xB7);
+	pci_write_config_byte(dev, 0xB7, disable | 0x02);
+	pci_write_config_byte(dev, 0x8E, write_enable);
+	pci_write_config_byte(dev, 0x8D, write_target);
+
+	dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via cardbus function)\n");
+	dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n");
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, ricoh_mmc_fixup_rl5c476);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, ricoh_mmc_fixup_rl5c476);
+
+static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
+{
+	/* disable via firewire interface */
+	u8 write_enable;
+	u8 disable;
+
+	/* disable must be done via function #0 */
+	if (PCI_FUNC(dev->devfn))
+		return;
+
+	pci_read_config_byte(dev, 0xCB, &disable);
+
+	if (disable & 0x02)
+		return;
+
+	pci_read_config_byte(dev, 0xCA, &write_enable);
+	pci_write_config_byte(dev, 0xCA, 0x57);
+	pci_write_config_byte(dev, 0xCB, disable | 0x02);
+	pci_write_config_byte(dev, 0xCA, write_enable);
+
+	dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n");
+	dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n");
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
+#endif /*CONFIG_MMC_RICOH_MMC*/
+
+
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
 			  struct pci_fixup *end)
 {
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 49c9e6c..f75a44d 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -29,7 +29,7 @@
 	return attribute->store ? attribute->store(slot, buf, len) : -EIO;
 }
 
-static struct sysfs_ops pci_slot_sysfs_ops = {
+static const struct sysfs_ops pci_slot_sysfs_ops = {
 	.show = pci_slot_attr_show,
 	.store = pci_slot_attr_store,
 };
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 0a6601c..d189e47 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -51,17 +51,23 @@
 
 config PCMCIA_IOCTL
 	bool "PCMCIA control ioctl (obsolete)"
-	depends on PCMCIA
+	depends on PCMCIA && ARM && !SMP && !PREEMPT
 	default y
 	help
 	  If you say Y here, the deprecated ioctl interface to the PCMCIA
-	  subsystem will be built. It is needed by cardmgr and cardctl
-	  (pcmcia-cs) to function properly.
+	  subsystem will be built. It is needed by the deprecated pcmcia-cs
+	  tools (cardmgr, cardctl) to function properly.
 
 	  You should use the new pcmciautils package instead (see
 	  <file:Documentation/Changes> for location and details).
 
-	  If unsure, say Y.
+	  This config option will most likely be removed from kernel 2.6.35,
+	  the associated code from kernel 2.6.36.
+
+	  As the PCMCIA ioctl is not locking safe, it depends on !SMP and
+	  !PREEMPT.
+
+	  If unsure, say N.
 
 config CARDBUS
 	bool "32-bit CardBus support"
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index ac0686e..e6ab2a4 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -71,7 +71,7 @@
 	unsigned int max, pass;
 
 	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
-	pci_fixup_cardbus(bus); 
+	pci_fixup_cardbus(bus);
 
 	max = bus->secondary;
 	for (pass = 0; pass < 2; pass++)
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 2f3622d..f230f65 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -54,46 +54,44 @@
 /* Upper limit on reasonable # of tuples */
 #define MAX_TUPLES		200
 
-/*====================================================================*/
-
-/* Parameters that can be set with 'insmod' */
-
 /* 16-bit CIS? */
 static int cis_width;
 module_param(cis_width, int, 0444);
 
 void release_cis_mem(struct pcmcia_socket *s)
 {
-    mutex_lock(&s->ops_mutex);
-    if (s->cis_mem.flags & MAP_ACTIVE) {
-	s->cis_mem.flags &= ~MAP_ACTIVE;
-	s->ops->set_mem_map(s, &s->cis_mem);
-	if (s->cis_mem.res) {
-	    release_resource(s->cis_mem.res);
-	    kfree(s->cis_mem.res);
-	    s->cis_mem.res = NULL;
+	mutex_lock(&s->ops_mutex);
+	if (s->cis_mem.flags & MAP_ACTIVE) {
+		s->cis_mem.flags &= ~MAP_ACTIVE;
+		s->ops->set_mem_map(s, &s->cis_mem);
+		if (s->cis_mem.res) {
+			release_resource(s->cis_mem.res);
+			kfree(s->cis_mem.res);
+			s->cis_mem.res = NULL;
+		}
+		iounmap(s->cis_virt);
+		s->cis_virt = NULL;
 	}
-	iounmap(s->cis_virt);
-	s->cis_virt = NULL;
-    }
-    mutex_unlock(&s->ops_mutex);
+	mutex_unlock(&s->ops_mutex);
 }
 
-/*
- * Map the card memory at "card_offset" into virtual space.
+/**
+ * set_cis_map() - map the card memory at "card_offset" into virtual space.
+ *
  * If flags & MAP_ATTRIB, map the attribute space, otherwise
  * map the memory space.
  *
  * Must be called with ops_mutex held.
  */
-static void __iomem *
-set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
+static void __iomem *set_cis_map(struct pcmcia_socket *s,
+				unsigned int card_offset, unsigned int flags)
 {
 	pccard_mem_map *mem = &s->cis_mem;
 	int ret;
 
 	if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) {
-		mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s);
+		mem->res = pcmcia_find_mem_region(0, s->map_size,
+						s->map_size, 0, s);
 		if (mem->res == NULL) {
 			dev_printk(KERN_NOTICE, &s->dev,
 				   "cs: unable to map card memory!\n");
@@ -124,165 +122,170 @@
 	return s->cis_virt;
 }
 
-/*======================================================================
-
-    Low-level functions to read and write CIS memory.  I think the
-    write routine is only useful for writing one-byte registers.
-
-======================================================================*/
 
 /* Bits in attr field */
 #define IS_ATTR		1
 #define IS_INDIRECT	8
 
+/**
+ * pcmcia_read_cis_mem() - low-level function to read CIS memory
+ */
 int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 		 u_int len, void *ptr)
 {
-    void __iomem *sys, *end;
-    unsigned char *buf = ptr;
+	void __iomem *sys, *end;
+	unsigned char *buf = ptr;
 
-    dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
+	dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
 
-    mutex_lock(&s->ops_mutex);
-    if (attr & IS_INDIRECT) {
-	/* Indirect accesses use a bunch of special registers at fixed
-	   locations in common memory */
-	u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
-	if (attr & IS_ATTR) {
-	    addr *= 2;
-	    flags = ICTRL0_AUTOINC;
+	mutex_lock(&s->ops_mutex);
+	if (attr & IS_INDIRECT) {
+		/* Indirect accesses use a bunch of special registers at fixed
+		   locations in common memory */
+		u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
+		if (attr & IS_ATTR) {
+			addr *= 2;
+			flags = ICTRL0_AUTOINC;
+		}
+
+		sys = set_cis_map(s, 0, MAP_ACTIVE |
+				((cis_width) ? MAP_16BIT : 0));
+		if (!sys) {
+			dev_dbg(&s->dev, "could not map memory\n");
+			memset(ptr, 0xff, len);
+			mutex_unlock(&s->ops_mutex);
+			return -1;
+		}
+
+		writeb(flags, sys+CISREG_ICTRL0);
+		writeb(addr & 0xff, sys+CISREG_IADDR0);
+		writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
+		writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
+		writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
+		for ( ; len > 0; len--, buf++)
+			*buf = readb(sys+CISREG_IDATA0);
+	} else {
+		u_int inc = 1, card_offset, flags;
+
+		if (addr > CISTPL_MAX_CIS_SIZE)
+			dev_dbg(&s->dev,
+				"attempt to read CIS mem at addr %#x", addr);
+
+		flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
+		if (attr) {
+			flags |= MAP_ATTRIB;
+			inc++;
+			addr *= 2;
+		}
+
+		card_offset = addr & ~(s->map_size-1);
+		while (len) {
+			sys = set_cis_map(s, card_offset, flags);
+			if (!sys) {
+				dev_dbg(&s->dev, "could not map memory\n");
+				memset(ptr, 0xff, len);
+				mutex_unlock(&s->ops_mutex);
+				return -1;
+			}
+			end = sys + s->map_size;
+			sys = sys + (addr & (s->map_size-1));
+			for ( ; len > 0; len--, buf++, sys += inc) {
+				if (sys == end)
+					break;
+				*buf = readb(sys);
+			}
+			card_offset += s->map_size;
+			addr = 0;
+		}
 	}
-
-	sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
-	if (!sys) {
-	    dev_dbg(&s->dev, "could not map memory\n");
-	    memset(ptr, 0xff, len);
-	    mutex_unlock(&s->ops_mutex);
-	    return -1;
-	}
-
-	writeb(flags, sys+CISREG_ICTRL0);
-	writeb(addr & 0xff, sys+CISREG_IADDR0);
-	writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
-	writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
-	writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
-	for ( ; len > 0; len--, buf++)
-	    *buf = readb(sys+CISREG_IDATA0);
-    } else {
-	u_int inc = 1, card_offset, flags;
-
-	if (addr > CISTPL_MAX_CIS_SIZE)
-		dev_dbg(&s->dev, "attempt to read CIS mem at addr %#x", addr);
-
-	flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
-	if (attr) {
-	    flags |= MAP_ATTRIB;
-	    inc++;
-	    addr *= 2;
-	}
-
-	card_offset = addr & ~(s->map_size-1);
-	while (len) {
-	    sys = set_cis_map(s, card_offset, flags);
-	    if (!sys) {
-		dev_dbg(&s->dev, "could not map memory\n");
-		memset(ptr, 0xff, len);
-		mutex_unlock(&s->ops_mutex);
-		return -1;
-	    }
-	    end = sys + s->map_size;
-	    sys = sys + (addr & (s->map_size-1));
-	    for ( ; len > 0; len--, buf++, sys += inc) {
-		if (sys == end)
-		    break;
-		*buf = readb(sys);
-	    }
-	    card_offset += s->map_size;
-	    addr = 0;
-	}
-    }
-    mutex_unlock(&s->ops_mutex);
-    dev_dbg(&s->dev, "  %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
-	  *(u_char *)(ptr+0), *(u_char *)(ptr+1),
-	  *(u_char *)(ptr+2), *(u_char *)(ptr+3));
-    return 0;
+	mutex_unlock(&s->ops_mutex);
+	dev_dbg(&s->dev, "  %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
+		*(u_char *)(ptr+0), *(u_char *)(ptr+1),
+		*(u_char *)(ptr+2), *(u_char *)(ptr+3));
+	return 0;
 }
 
 
+/**
+ * pcmcia_write_cis_mem() - low-level function to write CIS memory
+ *
+ * Probably only useful for writing one-byte registers.
+ */
 void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 		   u_int len, void *ptr)
 {
-    void __iomem *sys, *end;
-    unsigned char *buf = ptr;
+	void __iomem *sys, *end;
+	unsigned char *buf = ptr;
 
-    dev_dbg(&s->dev, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
+	dev_dbg(&s->dev,
+		"pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
 
-    mutex_lock(&s->ops_mutex);
-    if (attr & IS_INDIRECT) {
-	/* Indirect accesses use a bunch of special registers at fixed
-	   locations in common memory */
-	u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
-	if (attr & IS_ATTR) {
-	    addr *= 2;
-	    flags = ICTRL0_AUTOINC;
+	mutex_lock(&s->ops_mutex);
+	if (attr & IS_INDIRECT) {
+		/* Indirect accesses use a bunch of special registers at fixed
+		   locations in common memory */
+		u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
+		if (attr & IS_ATTR) {
+			addr *= 2;
+			flags = ICTRL0_AUTOINC;
+		}
+
+		sys = set_cis_map(s, 0, MAP_ACTIVE |
+				((cis_width) ? MAP_16BIT : 0));
+		if (!sys) {
+			dev_dbg(&s->dev, "could not map memory\n");
+			mutex_unlock(&s->ops_mutex);
+			return; /* FIXME: Error */
+		}
+
+		writeb(flags, sys+CISREG_ICTRL0);
+		writeb(addr & 0xff, sys+CISREG_IADDR0);
+		writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
+		writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
+		writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
+		for ( ; len > 0; len--, buf++)
+			writeb(*buf, sys+CISREG_IDATA0);
+	} else {
+		u_int inc = 1, card_offset, flags;
+
+		flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
+		if (attr & IS_ATTR) {
+			flags |= MAP_ATTRIB;
+			inc++;
+			addr *= 2;
+		}
+
+		card_offset = addr & ~(s->map_size-1);
+		while (len) {
+			sys = set_cis_map(s, card_offset, flags);
+			if (!sys) {
+				dev_dbg(&s->dev, "could not map memory\n");
+				mutex_unlock(&s->ops_mutex);
+				return; /* FIXME: error */
+			}
+
+			end = sys + s->map_size;
+			sys = sys + (addr & (s->map_size-1));
+			for ( ; len > 0; len--, buf++, sys += inc) {
+				if (sys == end)
+					break;
+				writeb(*buf, sys);
+			}
+			card_offset += s->map_size;
+			addr = 0;
+		}
 	}
-
-	sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
-	if (!sys) {
-		dev_dbg(&s->dev, "could not map memory\n");
-		mutex_unlock(&s->ops_mutex);
-		return; /* FIXME: Error */
-	}
-
-	writeb(flags, sys+CISREG_ICTRL0);
-	writeb(addr & 0xff, sys+CISREG_IADDR0);
-	writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
-	writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
-	writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
-	for ( ; len > 0; len--, buf++)
-	    writeb(*buf, sys+CISREG_IDATA0);
-    } else {
-	u_int inc = 1, card_offset, flags;
-
-	flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
-	if (attr & IS_ATTR) {
-	    flags |= MAP_ATTRIB;
-	    inc++;
-	    addr *= 2;
-	}
-
-	card_offset = addr & ~(s->map_size-1);
-	while (len) {
-	    sys = set_cis_map(s, card_offset, flags);
-	    if (!sys) {
-		dev_dbg(&s->dev, "could not map memory\n");
-		mutex_unlock(&s->ops_mutex);
-		return; /* FIXME: error */
-	    }
-
-	    end = sys + s->map_size;
-	    sys = sys + (addr & (s->map_size-1));
-	    for ( ; len > 0; len--, buf++, sys += inc) {
-		if (sys == end)
-		    break;
-		writeb(*buf, sys);
-	    }
-	    card_offset += s->map_size;
-	    addr = 0;
-	}
-    }
-    mutex_unlock(&s->ops_mutex);
+	mutex_unlock(&s->ops_mutex);
 }
 
 
-/*======================================================================
-
-    This is a wrapper around read_cis_mem, with the same interface,
-    but which caches information, for cards whose CIS may not be
-    readable all the time.
-
-======================================================================*/
-
+/**
+ * read_cis_cache() - read CIS memory or its associated cache
+ *
+ * This is a wrapper around read_cis_mem, with the same interface,
+ * but which caches information, for cards whose CIS may not be
+ * readable all the time.
+ */
 static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
 			size_t len, void *ptr)
 {
@@ -353,7 +356,6 @@
  * This destroys the CIS cache but keeps any fake CIS alive. Must be
  * called with ops_mutex held.
  */
-
 void destroy_cis_cache(struct pcmcia_socket *s)
 {
 	struct list_head *l, *n;
@@ -366,13 +368,9 @@
 	}
 }
 
-/*======================================================================
-
-    This verifies if the CIS of a card matches what is in the CIS
-    cache.
-
-======================================================================*/
-
+/**
+ * verify_cis_cache() - does the CIS match what is in the CIS cache?
+ */
 int verify_cis_cache(struct pcmcia_socket *s)
 {
 	struct cis_cache_entry *cis;
@@ -404,13 +402,12 @@
 	return 0;
 }
 
-/*======================================================================
-
-    For really bad cards, we provide a facility for uploading a
-    replacement CIS.
-
-======================================================================*/
-
+/**
+ * pcmcia_replace_cis() - use a replacement CIS instead of the card's CIS
+ *
+ * For really bad cards, we provide a facility for uploading a
+ * replacement CIS.
+ */
 int pcmcia_replace_cis(struct pcmcia_socket *s,
 		       const u8 *data, const size_t len)
 {
@@ -433,17 +430,13 @@
 	return 0;
 }
 
-/*======================================================================
-
-    The high-level CIS tuple services
-
-======================================================================*/
+/* The high-level CIS tuple services */
 
 typedef struct tuple_flags {
-    u_int		link_space:4;
-    u_int		has_link:1;
-    u_int		mfc_fn:3;
-    u_int		space:4;
+	u_int		link_space:4;
+	u_int		has_link:1;
+	u_int		mfc_fn:3;
+	u_int		space:4;
 } tuple_flags;
 
 #define LINK_SPACE(f)	(((tuple_flags *)(&(f)))->link_space)
@@ -451,982 +444,961 @@
 #define MFC_FN(f)	(((tuple_flags *)(&(f)))->mfc_fn)
 #define SPACE(f)	(((tuple_flags *)(&(f)))->space)
 
-int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple)
+int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function,
+			tuple_t *tuple)
 {
-    if (!s)
-	return -EINVAL;
+	if (!s)
+		return -EINVAL;
 
-    if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
-	return -ENODEV;
-    tuple->TupleLink = tuple->Flags = 0;
+	if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
+		return -ENODEV;
+	tuple->TupleLink = tuple->Flags = 0;
 
-    /* Assume presence of a LONGLINK_C to address 0 */
-    tuple->CISOffset = tuple->LinkOffset = 0;
-    SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
+	/* Assume presence of a LONGLINK_C to address 0 */
+	tuple->CISOffset = tuple->LinkOffset = 0;
+	SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
 
-    if ((s->functions > 1) && !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
-	cisdata_t req = tuple->DesiredTuple;
-	tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
-	if (pccard_get_next_tuple(s, function, tuple) == 0) {
-	    tuple->DesiredTuple = CISTPL_LINKTARGET;
-	    if (pccard_get_next_tuple(s, function, tuple) != 0)
-		return -ENOSPC;
-	} else
-	    tuple->CISOffset = tuple->TupleLink = 0;
-	tuple->DesiredTuple = req;
-    }
-    return pccard_get_next_tuple(s, function, tuple);
+	if ((s->functions > 1) && !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
+		cisdata_t req = tuple->DesiredTuple;
+		tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
+		if (pccard_get_next_tuple(s, function, tuple) == 0) {
+			tuple->DesiredTuple = CISTPL_LINKTARGET;
+			if (pccard_get_next_tuple(s, function, tuple) != 0)
+				return -ENOSPC;
+		} else
+			tuple->CISOffset = tuple->TupleLink = 0;
+		tuple->DesiredTuple = req;
+	}
+	return pccard_get_next_tuple(s, function, tuple);
 }
 
 static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
 {
-    u_char link[5];
-    u_int ofs;
-    int ret;
+	u_char link[5];
+	u_int ofs;
+	int ret;
 
-    if (MFC_FN(tuple->Flags)) {
-	/* Get indirect link from the MFC tuple */
-	ret = read_cis_cache(s, LINK_SPACE(tuple->Flags),
-		       tuple->LinkOffset, 5, link);
-	if (ret)
+	if (MFC_FN(tuple->Flags)) {
+		/* Get indirect link from the MFC tuple */
+		ret = read_cis_cache(s, LINK_SPACE(tuple->Flags),
+				tuple->LinkOffset, 5, link);
+		if (ret)
+			return -1;
+		ofs = get_unaligned_le32(link + 1);
+		SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
+		/* Move to the next indirect link */
+		tuple->LinkOffset += 5;
+		MFC_FN(tuple->Flags)--;
+	} else if (HAS_LINK(tuple->Flags)) {
+		ofs = tuple->LinkOffset;
+		SPACE(tuple->Flags) = LINK_SPACE(tuple->Flags);
+		HAS_LINK(tuple->Flags) = 0;
+	} else
 		return -1;
-	ofs = get_unaligned_le32(link + 1);
-	SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
-	/* Move to the next indirect link */
-	tuple->LinkOffset += 5;
-	MFC_FN(tuple->Flags)--;
-    } else if (HAS_LINK(tuple->Flags)) {
-	ofs = tuple->LinkOffset;
-	SPACE(tuple->Flags) = LINK_SPACE(tuple->Flags);
-	HAS_LINK(tuple->Flags) = 0;
-    } else {
-	return -1;
-    }
-    if (SPACE(tuple->Flags)) {
-	/* This is ugly, but a common CIS error is to code the long
-	   link offset incorrectly, so we check the right spot... */
+
+	if (SPACE(tuple->Flags)) {
+		/* This is ugly, but a common CIS error is to code the long
+		   link offset incorrectly, so we check the right spot... */
+		ret = read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
+		if (ret)
+			return -1;
+		if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
+			(strncmp(link+2, "CIS", 3) == 0))
+			return ofs;
+		remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
+		/* Then, we try the wrong spot... */
+		ofs = ofs >> 1;
+	}
 	ret = read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
 	if (ret)
 		return -1;
 	if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
-	    (strncmp(link+2, "CIS", 3) == 0))
-	    return ofs;
+		(strncmp(link+2, "CIS", 3) == 0))
+		return ofs;
 	remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
-	/* Then, we try the wrong spot... */
-	ofs = ofs >> 1;
-    }
-    ret = read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
-    if (ret)
-	    return -1;
-    if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
-	(strncmp(link+2, "CIS", 3) == 0))
-	return ofs;
-    remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
-    return -1;
+	return -1;
 }
 
-int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple)
+int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function,
+			tuple_t *tuple)
 {
-    u_char link[2], tmp;
-    int ofs, i, attr;
-    int ret;
+	u_char link[2], tmp;
+	int ofs, i, attr;
+	int ret;
 
-    if (!s)
-	return -EINVAL;
-    if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
-	return -ENODEV;
+	if (!s)
+		return -EINVAL;
+	if (!(s->state & SOCKET_PRESENT) || (s->state & SOCKET_CARDBUS))
+		return -ENODEV;
 
-    link[1] = tuple->TupleLink;
-    ofs = tuple->CISOffset + tuple->TupleLink;
-    attr = SPACE(tuple->Flags);
+	link[1] = tuple->TupleLink;
+	ofs = tuple->CISOffset + tuple->TupleLink;
+	attr = SPACE(tuple->Flags);
 
-    for (i = 0; i < MAX_TUPLES; i++) {
-	if (link[1] == 0xff) {
-	    link[0] = CISTPL_END;
-	} else {
-	    ret = read_cis_cache(s, attr, ofs, 2, link);
-	    if (ret)
-		    return -1;
-	    if (link[0] == CISTPL_NULL) {
-		ofs++; continue;
-	    }
-	}
-
-	/* End of chain?  Follow long link if possible */
-	if (link[0] == CISTPL_END) {
-	    ofs = follow_link(s, tuple);
-	    if (ofs < 0)
-		return -ENOSPC;
-	    attr = SPACE(tuple->Flags);
-	    ret = read_cis_cache(s, attr, ofs, 2, link);
-	    if (ret)
-		    return -1;
-	}
-
-	/* Is this a link tuple?  Make a note of it */
-	if ((link[0] == CISTPL_LONGLINK_A) ||
-	    (link[0] == CISTPL_LONGLINK_C) ||
-	    (link[0] == CISTPL_LONGLINK_MFC) ||
-	    (link[0] == CISTPL_LINKTARGET) ||
-	    (link[0] == CISTPL_INDIRECT) ||
-	    (link[0] == CISTPL_NO_LINK)) {
-	    switch (link[0]) {
-	    case CISTPL_LONGLINK_A:
-		HAS_LINK(tuple->Flags) = 1;
-		LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
-		ret = read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
-		if (ret)
-			return -1;
-		break;
-	    case CISTPL_LONGLINK_C:
-		HAS_LINK(tuple->Flags) = 1;
-		LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
-		ret = read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
-		if (ret)
-			return -1;
-		break;
-	    case CISTPL_INDIRECT:
-		HAS_LINK(tuple->Flags) = 1;
-		LINK_SPACE(tuple->Flags) = IS_ATTR | IS_INDIRECT;
-		tuple->LinkOffset = 0;
-		break;
-	    case CISTPL_LONGLINK_MFC:
-		tuple->LinkOffset = ofs + 3;
-		LINK_SPACE(tuple->Flags) = attr;
-		if (function == BIND_FN_ALL) {
-		    /* Follow all the MFC links */
-		    ret = read_cis_cache(s, attr, ofs+2, 1, &tmp);
-		    if (ret)
-			    return -1;
-		    MFC_FN(tuple->Flags) = tmp;
-		} else {
-		    /* Follow exactly one of the links */
-		    MFC_FN(tuple->Flags) = 1;
-		    tuple->LinkOffset += function * 5;
+	for (i = 0; i < MAX_TUPLES; i++) {
+		if (link[1] == 0xff)
+			link[0] = CISTPL_END;
+		else {
+			ret = read_cis_cache(s, attr, ofs, 2, link);
+			if (ret)
+				return -1;
+			if (link[0] == CISTPL_NULL) {
+				ofs++;
+				continue;
+			}
 		}
-		break;
-	    case CISTPL_NO_LINK:
-		HAS_LINK(tuple->Flags) = 0;
-		break;
-	    }
-	    if ((tuple->Attributes & TUPLE_RETURN_LINK) &&
-		(tuple->DesiredTuple == RETURN_FIRST_TUPLE))
-		break;
-	} else
-	    if (tuple->DesiredTuple == RETURN_FIRST_TUPLE)
-		break;
 
-	if (link[0] == tuple->DesiredTuple)
-	    break;
-	ofs += link[1] + 2;
-    }
-    if (i == MAX_TUPLES) {
-	dev_dbg(&s->dev, "cs: overrun in pcmcia_get_next_tuple\n");
-	return -ENOSPC;
-    }
+		/* End of chain?  Follow long link if possible */
+		if (link[0] == CISTPL_END) {
+			ofs = follow_link(s, tuple);
+			if (ofs < 0)
+				return -ENOSPC;
+			attr = SPACE(tuple->Flags);
+			ret = read_cis_cache(s, attr, ofs, 2, link);
+			if (ret)
+				return -1;
+		}
 
-    tuple->TupleCode = link[0];
-    tuple->TupleLink = link[1];
-    tuple->CISOffset = ofs + 2;
-    return 0;
+		/* Is this a link tuple?  Make a note of it */
+		if ((link[0] == CISTPL_LONGLINK_A) ||
+			(link[0] == CISTPL_LONGLINK_C) ||
+			(link[0] == CISTPL_LONGLINK_MFC) ||
+			(link[0] == CISTPL_LINKTARGET) ||
+			(link[0] == CISTPL_INDIRECT) ||
+			(link[0] == CISTPL_NO_LINK)) {
+			switch (link[0]) {
+			case CISTPL_LONGLINK_A:
+				HAS_LINK(tuple->Flags) = 1;
+				LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
+				ret = read_cis_cache(s, attr, ofs+2, 4,
+						&tuple->LinkOffset);
+				if (ret)
+					return -1;
+				break;
+			case CISTPL_LONGLINK_C:
+				HAS_LINK(tuple->Flags) = 1;
+				LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
+				ret = read_cis_cache(s, attr, ofs+2, 4,
+						&tuple->LinkOffset);
+				if (ret)
+					return -1;
+				break;
+			case CISTPL_INDIRECT:
+				HAS_LINK(tuple->Flags) = 1;
+				LINK_SPACE(tuple->Flags) = IS_ATTR |
+					IS_INDIRECT;
+				tuple->LinkOffset = 0;
+				break;
+			case CISTPL_LONGLINK_MFC:
+				tuple->LinkOffset = ofs + 3;
+				LINK_SPACE(tuple->Flags) = attr;
+				if (function == BIND_FN_ALL) {
+					/* Follow all the MFC links */
+					ret = read_cis_cache(s, attr, ofs+2,
+							1, &tmp);
+					if (ret)
+						return -1;
+					MFC_FN(tuple->Flags) = tmp;
+				} else {
+					/* Follow exactly one of the links */
+					MFC_FN(tuple->Flags) = 1;
+					tuple->LinkOffset += function * 5;
+				}
+				break;
+			case CISTPL_NO_LINK:
+				HAS_LINK(tuple->Flags) = 0;
+				break;
+			}
+			if ((tuple->Attributes & TUPLE_RETURN_LINK) &&
+				(tuple->DesiredTuple == RETURN_FIRST_TUPLE))
+				break;
+		} else
+			if (tuple->DesiredTuple == RETURN_FIRST_TUPLE)
+				break;
+
+		if (link[0] == tuple->DesiredTuple)
+			break;
+		ofs += link[1] + 2;
+	}
+	if (i == MAX_TUPLES) {
+		dev_dbg(&s->dev, "cs: overrun in pcmcia_get_next_tuple\n");
+		return -ENOSPC;
+	}
+
+	tuple->TupleCode = link[0];
+	tuple->TupleLink = link[1];
+	tuple->CISOffset = ofs + 2;
+	return 0;
 }
 
-/*====================================================================*/
-
-#define _MIN(a, b)		(((a) < (b)) ? (a) : (b))
-
 int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple)
 {
-    u_int len;
-    int ret;
+	u_int len;
+	int ret;
 
-    if (!s)
-	return -EINVAL;
+	if (!s)
+		return -EINVAL;
 
-    if (tuple->TupleLink < tuple->TupleOffset)
-	return -ENOSPC;
-    len = tuple->TupleLink - tuple->TupleOffset;
-    tuple->TupleDataLen = tuple->TupleLink;
-    if (len == 0)
+	if (tuple->TupleLink < tuple->TupleOffset)
+		return -ENOSPC;
+	len = tuple->TupleLink - tuple->TupleOffset;
+	tuple->TupleDataLen = tuple->TupleLink;
+	if (len == 0)
+		return 0;
+	ret = read_cis_cache(s, SPACE(tuple->Flags),
+			tuple->CISOffset + tuple->TupleOffset,
+			min(len, (u_int) tuple->TupleDataMax),
+			tuple->TupleData);
+	if (ret)
+		return -1;
 	return 0;
-    ret = read_cis_cache(s, SPACE(tuple->Flags),
-		   tuple->CISOffset + tuple->TupleOffset,
-		   _MIN(len, tuple->TupleDataMax), tuple->TupleData);
-    if (ret)
-	    return -1;
-    return 0;
 }
 
 
-/*======================================================================
-
-    Parsing routines for individual tuples
-
-======================================================================*/
+/* Parsing routines for individual tuples */
 
 static int parse_device(tuple_t *tuple, cistpl_device_t *device)
 {
-    int i;
-    u_char scale;
-    u_char *p, *q;
+	int i;
+	u_char scale;
+	u_char *p, *q;
 
-    p = (u_char *)tuple->TupleData;
-    q = p + tuple->TupleDataLen;
+	p = (u_char *)tuple->TupleData;
+	q = p + tuple->TupleDataLen;
 
-    device->ndev = 0;
-    for (i = 0; i < CISTPL_MAX_DEVICES; i++) {
+	device->ndev = 0;
+	for (i = 0; i < CISTPL_MAX_DEVICES; i++) {
 
-	if (*p == 0xff)
-		break;
-	device->dev[i].type = (*p >> 4);
-	device->dev[i].wp = (*p & 0x08) ? 1 : 0;
-	switch (*p & 0x07) {
-	case 0:
-		device->dev[i].speed = 0;
-		break;
-	case 1:
-		device->dev[i].speed = 250;
-		break;
-	case 2:
-		device->dev[i].speed = 200;
-		break;
-	case 3:
-		device->dev[i].speed = 150;
-		break;
-	case 4:
-		device->dev[i].speed = 100;
-		break;
-	case 7:
-		if (++p == q)
-			return -EINVAL;
-		device->dev[i].speed = SPEED_CVT(*p);
-		while (*p & 0x80)
+		if (*p == 0xff)
+			break;
+		device->dev[i].type = (*p >> 4);
+		device->dev[i].wp = (*p & 0x08) ? 1 : 0;
+		switch (*p & 0x07) {
+		case 0:
+			device->dev[i].speed = 0;
+			break;
+		case 1:
+			device->dev[i].speed = 250;
+			break;
+		case 2:
+			device->dev[i].speed = 200;
+			break;
+		case 3:
+			device->dev[i].speed = 150;
+			break;
+		case 4:
+			device->dev[i].speed = 100;
+			break;
+		case 7:
 			if (++p == q)
 				return -EINVAL;
-		break;
-	default:
-		return -EINVAL;
+			device->dev[i].speed = SPEED_CVT(*p);
+			while (*p & 0x80)
+				if (++p == q)
+					return -EINVAL;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		if (++p == q)
+			return -EINVAL;
+		if (*p == 0xff)
+			break;
+		scale = *p & 7;
+		if (scale == 7)
+			return -EINVAL;
+		device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
+		device->ndev++;
+		if (++p == q)
+			break;
 	}
 
-	if (++p == q)
-		return -EINVAL;
-	if (*p == 0xff)
-		break;
-	scale = *p & 7;
-	if (scale == 7)
-		return -EINVAL;
-	device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
-	device->ndev++;
-	if (++p == q)
-		break;
-    }
-
-    return 0;
+	return 0;
 }
 
-/*====================================================================*/
 
 static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
 {
-    u_char *p;
-    if (tuple->TupleDataLen < 5)
-	return -EINVAL;
-    p = (u_char *) tuple->TupleData;
-    csum->addr = tuple->CISOffset + get_unaligned_le16(p) - 2;
-    csum->len = get_unaligned_le16(p + 2);
-    csum->sum = *(p + 4);
-    return 0;
+	u_char *p;
+	if (tuple->TupleDataLen < 5)
+		return -EINVAL;
+	p = (u_char *) tuple->TupleData;
+	csum->addr = tuple->CISOffset + get_unaligned_le16(p) - 2;
+	csum->len = get_unaligned_le16(p + 2);
+	csum->sum = *(p + 4);
+	return 0;
 }
 
-/*====================================================================*/
 
 static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
 {
-    if (tuple->TupleDataLen < 4)
-	return -EINVAL;
-    link->addr = get_unaligned_le32(tuple->TupleData);
-    return 0;
+	if (tuple->TupleDataLen < 4)
+		return -EINVAL;
+	link->addr = get_unaligned_le32(tuple->TupleData);
+	return 0;
 }
 
-/*====================================================================*/
 
-static int parse_longlink_mfc(tuple_t *tuple,
-			      cistpl_longlink_mfc_t *link)
+static int parse_longlink_mfc(tuple_t *tuple, cistpl_longlink_mfc_t *link)
 {
-    u_char *p;
-    int i;
+	u_char *p;
+	int i;
 
-    p = (u_char *)tuple->TupleData;
+	p = (u_char *)tuple->TupleData;
 
-    link->nfn = *p; p++;
-    if (tuple->TupleDataLen <= link->nfn*5)
-	return -EINVAL;
-    for (i = 0; i < link->nfn; i++) {
-	link->fn[i].space = *p; p++;
-	link->fn[i].addr = get_unaligned_le32(p);
-	p += 4;
-    }
-    return 0;
+	link->nfn = *p; p++;
+	if (tuple->TupleDataLen <= link->nfn*5)
+		return -EINVAL;
+	for (i = 0; i < link->nfn; i++) {
+		link->fn[i].space = *p; p++;
+		link->fn[i].addr = get_unaligned_le32(p);
+		p += 4;
+	}
+	return 0;
 }
 
-/*====================================================================*/
 
 static int parse_strings(u_char *p, u_char *q, int max,
 			 char *s, u_char *ofs, u_char *found)
 {
-    int i, j, ns;
+	int i, j, ns;
 
-    if (p == q)
-	    return -EINVAL;
-    ns = 0; j = 0;
-    for (i = 0; i < max; i++) {
-	if (*p == 0xff)
-		break;
-	ofs[i] = j;
-	ns++;
-	for (;;) {
-	    s[j++] = (*p == 0xff) ? '\0' : *p;
-	    if ((*p == '\0') || (*p == 0xff))
-		    break;
-	    if (++p == q)
-		    return -EINVAL;
+	if (p == q)
+		return -EINVAL;
+	ns = 0; j = 0;
+	for (i = 0; i < max; i++) {
+		if (*p == 0xff)
+			break;
+		ofs[i] = j;
+		ns++;
+		for (;;) {
+			s[j++] = (*p == 0xff) ? '\0' : *p;
+			if ((*p == '\0') || (*p == 0xff))
+				break;
+			if (++p == q)
+				return -EINVAL;
+		}
+		if ((*p == 0xff) || (++p == q))
+			break;
 	}
-	if ((*p == 0xff) || (++p == q))
-		break;
-    }
-    if (found) {
-	*found = ns;
-	return 0;
-    } else {
+	if (found) {
+		*found = ns;
+		return 0;
+	}
+
 	return (ns == max) ? 0 : -EINVAL;
-    }
 }
 
-/*====================================================================*/
 
 static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
 {
-    u_char *p, *q;
+	u_char *p, *q;
 
-    p = (u_char *)tuple->TupleData;
-    q = p + tuple->TupleDataLen;
+	p = (u_char *)tuple->TupleData;
+	q = p + tuple->TupleDataLen;
 
-    vers_1->major = *p; p++;
-    vers_1->minor = *p; p++;
-    if (p >= q)
-	    return -EINVAL;
+	vers_1->major = *p; p++;
+	vers_1->minor = *p; p++;
+	if (p >= q)
+		return -EINVAL;
 
-    return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
-			 vers_1->str, vers_1->ofs, &vers_1->ns);
+	return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
+			vers_1->str, vers_1->ofs, &vers_1->ns);
 }
 
-/*====================================================================*/
 
 static int parse_altstr(tuple_t *tuple, cistpl_altstr_t *altstr)
 {
-    u_char *p, *q;
+	u_char *p, *q;
 
-    p = (u_char *)tuple->TupleData;
-    q = p + tuple->TupleDataLen;
+	p = (u_char *)tuple->TupleData;
+	q = p + tuple->TupleDataLen;
 
-    return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS,
-			 altstr->str, altstr->ofs, &altstr->ns);
+	return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS,
+			altstr->str, altstr->ofs, &altstr->ns);
 }
 
-/*====================================================================*/
 
 static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
 {
-    u_char *p, *q;
-    int nid;
+	u_char *p, *q;
+	int nid;
 
-    p = (u_char *)tuple->TupleData;
-    q = p + tuple->TupleDataLen;
+	p = (u_char *)tuple->TupleData;
+	q = p + tuple->TupleDataLen;
 
-    for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) {
-	if (p > q-2)
-		break;
-	jedec->id[nid].mfr = p[0];
-	jedec->id[nid].info = p[1];
-	p += 2;
-    }
-    jedec->nid = nid;
-    return 0;
+	for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) {
+		if (p > q-2)
+			break;
+		jedec->id[nid].mfr = p[0];
+		jedec->id[nid].info = p[1];
+		p += 2;
+	}
+	jedec->nid = nid;
+	return 0;
 }
 
-/*====================================================================*/
 
 static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
 {
-    if (tuple->TupleDataLen < 4)
-	return -EINVAL;
-    m->manf = get_unaligned_le16(tuple->TupleData);
-    m->card = get_unaligned_le16(tuple->TupleData + 2);
-    return 0;
+	if (tuple->TupleDataLen < 4)
+		return -EINVAL;
+	m->manf = get_unaligned_le16(tuple->TupleData);
+	m->card = get_unaligned_le16(tuple->TupleData + 2);
+	return 0;
 }
 
-/*====================================================================*/
 
 static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
 {
-    u_char *p;
-    if (tuple->TupleDataLen < 2)
-	return -EINVAL;
-    p = (u_char *)tuple->TupleData;
-    f->func = p[0];
-    f->sysinit = p[1];
-    return 0;
+	u_char *p;
+	if (tuple->TupleDataLen < 2)
+		return -EINVAL;
+	p = (u_char *)tuple->TupleData;
+	f->func = p[0];
+	f->sysinit = p[1];
+	return 0;
 }
 
-/*====================================================================*/
 
 static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
 {
-    u_char *p;
-    int i;
-    if (tuple->TupleDataLen < 1)
-	return -EINVAL;
-    p = (u_char *)tuple->TupleData;
-    f->type = p[0];
-    for (i = 1; i < tuple->TupleDataLen; i++)
-	f->data[i-1] = p[i];
-    return 0;
+	u_char *p;
+	int i;
+	if (tuple->TupleDataLen < 1)
+		return -EINVAL;
+	p = (u_char *)tuple->TupleData;
+	f->type = p[0];
+	for (i = 1; i < tuple->TupleDataLen; i++)
+		f->data[i-1] = p[i];
+	return 0;
 }
 
-/*====================================================================*/
 
 static int parse_config(tuple_t *tuple, cistpl_config_t *config)
 {
-    int rasz, rmsz, i;
-    u_char *p;
+	int rasz, rmsz, i;
+	u_char *p;
 
-    p = (u_char *)tuple->TupleData;
-    rasz = *p & 0x03;
-    rmsz = (*p & 0x3c) >> 2;
-    if (tuple->TupleDataLen < rasz+rmsz+4)
-	return -EINVAL;
-    config->last_idx = *(++p);
-    p++;
-    config->base = 0;
-    for (i = 0; i <= rasz; i++)
-	config->base += p[i] << (8*i);
-    p += rasz+1;
-    for (i = 0; i < 4; i++)
-	config->rmask[i] = 0;
-    for (i = 0; i <= rmsz; i++)
-	config->rmask[i>>2] += p[i] << (8*(i%4));
-    config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
-    return 0;
+	p = (u_char *)tuple->TupleData;
+	rasz = *p & 0x03;
+	rmsz = (*p & 0x3c) >> 2;
+	if (tuple->TupleDataLen < rasz+rmsz+4)
+		return -EINVAL;
+	config->last_idx = *(++p);
+	p++;
+	config->base = 0;
+	for (i = 0; i <= rasz; i++)
+		config->base += p[i] << (8*i);
+	p += rasz+1;
+	for (i = 0; i < 4; i++)
+		config->rmask[i] = 0;
+	for (i = 0; i <= rmsz; i++)
+		config->rmask[i>>2] += p[i] << (8*(i%4));
+	config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
+	return 0;
 }
 
-/*======================================================================
+/* The following routines are all used to parse the nightmarish
+ * config table entries.
+ */
 
-    The following routines are all used to parse the nightmarish
-    config table entries.
-
-======================================================================*/
-
-static u_char *parse_power(u_char *p, u_char *q,
-			   cistpl_power_t *pwr)
+static u_char *parse_power(u_char *p, u_char *q, cistpl_power_t *pwr)
 {
-    int i;
-    u_int scale;
+	int i;
+	u_int scale;
 
-    if (p == q)
-	    return NULL;
-    pwr->present = *p;
-    pwr->flags = 0;
-    p++;
-    for (i = 0; i < 7; i++)
-	if (pwr->present & (1<<i)) {
-	    if (p == q)
-		    return NULL;
-	    pwr->param[i] = POWER_CVT(*p);
-	    scale = POWER_SCALE(*p);
-	    while (*p & 0x80) {
+	if (p == q)
+		return NULL;
+	pwr->present = *p;
+	pwr->flags = 0;
+	p++;
+	for (i = 0; i < 7; i++)
+		if (pwr->present & (1<<i)) {
+			if (p == q)
+				return NULL;
+			pwr->param[i] = POWER_CVT(*p);
+			scale = POWER_SCALE(*p);
+			while (*p & 0x80) {
+				if (++p == q)
+					return NULL;
+				if ((*p & 0x7f) < 100)
+					pwr->param[i] +=
+						(*p & 0x7f) * scale / 100;
+				else if (*p == 0x7d)
+					pwr->flags |= CISTPL_POWER_HIGHZ_OK;
+				else if (*p == 0x7e)
+					pwr->param[i] = 0;
+				else if (*p == 0x7f)
+					pwr->flags |= CISTPL_POWER_HIGHZ_REQ;
+				else
+					return NULL;
+			}
+			p++;
+		}
+	return p;
+}
+
+
+static u_char *parse_timing(u_char *p, u_char *q, cistpl_timing_t *timing)
+{
+	u_char scale;
+
+	if (p == q)
+		return NULL;
+	scale = *p;
+	if ((scale & 3) != 3) {
 		if (++p == q)
 			return NULL;
-		if ((*p & 0x7f) < 100)
-		    pwr->param[i] += (*p & 0x7f) * scale / 100;
-		else if (*p == 0x7d)
-		    pwr->flags |= CISTPL_POWER_HIGHZ_OK;
-		else if (*p == 0x7e)
-		    pwr->param[i] = 0;
-		else if (*p == 0x7f)
-		    pwr->flags |= CISTPL_POWER_HIGHZ_REQ;
-		else
-		    return NULL;
-	    }
-	    p++;
-	}
-    return p;
+		timing->wait = SPEED_CVT(*p);
+		timing->waitscale = exponent[scale & 3];
+	} else
+		timing->wait = 0;
+	scale >>= 2;
+	if ((scale & 7) != 7) {
+		if (++p == q)
+			return NULL;
+		timing->ready = SPEED_CVT(*p);
+		timing->rdyscale = exponent[scale & 7];
+	} else
+		timing->ready = 0;
+	scale >>= 3;
+	if (scale != 7) {
+		if (++p == q)
+			return NULL;
+		timing->reserved = SPEED_CVT(*p);
+		timing->rsvscale = exponent[scale];
+	} else
+		timing->reserved = 0;
+	p++;
+	return p;
 }
 
-/*====================================================================*/
-
-static u_char *parse_timing(u_char *p, u_char *q,
-			    cistpl_timing_t *timing)
-{
-    u_char scale;
-
-    if (p == q)
-	    return NULL;
-    scale = *p;
-    if ((scale & 3) != 3) {
-	if (++p == q)
-		return NULL;
-	timing->wait = SPEED_CVT(*p);
-	timing->waitscale = exponent[scale & 3];
-    } else
-	timing->wait = 0;
-    scale >>= 2;
-    if ((scale & 7) != 7) {
-	if (++p == q)
-		return NULL;
-	timing->ready = SPEED_CVT(*p);
-	timing->rdyscale = exponent[scale & 7];
-    } else
-	timing->ready = 0;
-    scale >>= 3;
-    if (scale != 7) {
-	if (++p == q)
-		return NULL;
-	timing->reserved = SPEED_CVT(*p);
-	timing->rsvscale = exponent[scale];
-    } else
-	timing->reserved = 0;
-    p++;
-    return p;
-}
-
-/*====================================================================*/
 
 static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io)
 {
-    int i, j, bsz, lsz;
+	int i, j, bsz, lsz;
 
-    if (p == q)
-	    return NULL;
-    io->flags = *p;
+	if (p == q)
+		return NULL;
+	io->flags = *p;
 
-    if (!(*p & 0x80)) {
-	io->nwin = 1;
-	io->win[0].base = 0;
-	io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK));
-	return p+1;
-    }
-
-    if (++p == q)
-	    return NULL;
-    io->nwin = (*p & 0x0f) + 1;
-    bsz = (*p & 0x30) >> 4;
-    if (bsz == 3)
-	    bsz++;
-    lsz = (*p & 0xc0) >> 6;
-    if (lsz == 3)
-	    lsz++;
-    p++;
-
-    for (i = 0; i < io->nwin; i++) {
-	io->win[i].base = 0;
-	io->win[i].len = 1;
-	for (j = 0; j < bsz; j++, p++) {
-	    if (p == q)
-		    return NULL;
-	    io->win[i].base += *p << (j*8);
+	if (!(*p & 0x80)) {
+		io->nwin = 1;
+		io->win[0].base = 0;
+		io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK));
+		return p+1;
 	}
-	for (j = 0; j < lsz; j++, p++) {
-	    if (p == q)
-		    return NULL;
-	    io->win[i].len += *p << (j*8);
+
+	if (++p == q)
+		return NULL;
+	io->nwin = (*p & 0x0f) + 1;
+	bsz = (*p & 0x30) >> 4;
+	if (bsz == 3)
+		bsz++;
+	lsz = (*p & 0xc0) >> 6;
+	if (lsz == 3)
+		lsz++;
+	p++;
+
+	for (i = 0; i < io->nwin; i++) {
+		io->win[i].base = 0;
+		io->win[i].len = 1;
+		for (j = 0; j < bsz; j++, p++) {
+			if (p == q)
+				return NULL;
+			io->win[i].base += *p << (j*8);
+		}
+		for (j = 0; j < lsz; j++, p++) {
+			if (p == q)
+				return NULL;
+			io->win[i].len += *p << (j*8);
+		}
 	}
-    }
-    return p;
+	return p;
 }
 
-/*====================================================================*/
 
 static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem)
 {
-    int i, j, asz, lsz, has_ha;
-    u_int len, ca, ha;
+	int i, j, asz, lsz, has_ha;
+	u_int len, ca, ha;
 
-    if (p == q)
-	    return NULL;
+	if (p == q)
+		return NULL;
 
-    mem->nwin = (*p & 0x07) + 1;
-    lsz = (*p & 0x18) >> 3;
-    asz = (*p & 0x60) >> 5;
-    has_ha = (*p & 0x80);
-    if (++p == q)
-	    return NULL;
+	mem->nwin = (*p & 0x07) + 1;
+	lsz = (*p & 0x18) >> 3;
+	asz = (*p & 0x60) >> 5;
+	has_ha = (*p & 0x80);
+	if (++p == q)
+		return NULL;
 
-    for (i = 0; i < mem->nwin; i++) {
-	len = ca = ha = 0;
-	for (j = 0; j < lsz; j++, p++) {
-	    if (p == q)
-		    return NULL;
-	    len += *p << (j*8);
+	for (i = 0; i < mem->nwin; i++) {
+		len = ca = ha = 0;
+		for (j = 0; j < lsz; j++, p++) {
+			if (p == q)
+				return NULL;
+			len += *p << (j*8);
+		}
+		for (j = 0; j < asz; j++, p++) {
+			if (p == q)
+				return NULL;
+			ca += *p << (j*8);
+		}
+		if (has_ha)
+			for (j = 0; j < asz; j++, p++) {
+				if (p == q)
+					return NULL;
+				ha += *p << (j*8);
+			}
+		mem->win[i].len = len << 8;
+		mem->win[i].card_addr = ca << 8;
+		mem->win[i].host_addr = ha << 8;
 	}
-	for (j = 0; j < asz; j++, p++) {
-	    if (p == q)
-		    return NULL;
-	    ca += *p << (j*8);
-	}
-	if (has_ha)
-	    for (j = 0; j < asz; j++, p++) {
-		if (p == q)
-			return NULL;
-		ha += *p << (j*8);
-	    }
-	mem->win[i].len = len << 8;
-	mem->win[i].card_addr = ca << 8;
-	mem->win[i].host_addr = ha << 8;
-    }
-    return p;
+	return p;
 }
 
-/*====================================================================*/
 
 static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
 {
-    if (p == q)
-	    return NULL;
-    irq->IRQInfo1 = *p; p++;
-    if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
-	if (p+2 > q)
+	if (p == q)
 		return NULL;
-	irq->IRQInfo2 = (p[1]<<8) + p[0];
-	p += 2;
-    }
-    return p;
+	irq->IRQInfo1 = *p; p++;
+	if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
+		if (p+2 > q)
+			return NULL;
+		irq->IRQInfo2 = (p[1]<<8) + p[0];
+		p += 2;
+	}
+	return p;
 }
 
-/*====================================================================*/
 
 static int parse_cftable_entry(tuple_t *tuple,
 			       cistpl_cftable_entry_t *entry)
 {
-    u_char *p, *q, features;
+	u_char *p, *q, features;
 
-    p = tuple->TupleData;
-    q = p + tuple->TupleDataLen;
-    entry->index = *p & 0x3f;
-    entry->flags = 0;
-    if (*p & 0x40)
-	entry->flags |= CISTPL_CFTABLE_DEFAULT;
-    if (*p & 0x80) {
+	p = tuple->TupleData;
+	q = p + tuple->TupleDataLen;
+	entry->index = *p & 0x3f;
+	entry->flags = 0;
+	if (*p & 0x40)
+		entry->flags |= CISTPL_CFTABLE_DEFAULT;
+	if (*p & 0x80) {
+		if (++p == q)
+			return -EINVAL;
+		if (*p & 0x10)
+			entry->flags |= CISTPL_CFTABLE_BVDS;
+		if (*p & 0x20)
+			entry->flags |= CISTPL_CFTABLE_WP;
+		if (*p & 0x40)
+			entry->flags |= CISTPL_CFTABLE_RDYBSY;
+		if (*p & 0x80)
+			entry->flags |= CISTPL_CFTABLE_MWAIT;
+		entry->interface = *p & 0x0f;
+	} else
+		entry->interface = 0;
+
+	/* Process optional features */
 	if (++p == q)
 		return -EINVAL;
-	if (*p & 0x10)
-	    entry->flags |= CISTPL_CFTABLE_BVDS;
-	if (*p & 0x20)
-	    entry->flags |= CISTPL_CFTABLE_WP;
-	if (*p & 0x40)
-	    entry->flags |= CISTPL_CFTABLE_RDYBSY;
-	if (*p & 0x80)
-	    entry->flags |= CISTPL_CFTABLE_MWAIT;
-	entry->interface = *p & 0x0f;
-    } else
-	entry->interface = 0;
+	features = *p; p++;
 
-    /* Process optional features */
-    if (++p == q)
-	    return -EINVAL;
-    features = *p; p++;
+	/* Power options */
+	if ((features & 3) > 0) {
+		p = parse_power(p, q, &entry->vcc);
+		if (p == NULL)
+			return -EINVAL;
+	} else
+		entry->vcc.present = 0;
+	if ((features & 3) > 1) {
+		p = parse_power(p, q, &entry->vpp1);
+		if (p == NULL)
+			return -EINVAL;
+	} else
+		entry->vpp1.present = 0;
+	if ((features & 3) > 2) {
+		p = parse_power(p, q, &entry->vpp2);
+		if (p == NULL)
+			return -EINVAL;
+	} else
+		entry->vpp2.present = 0;
 
-    /* Power options */
-    if ((features & 3) > 0) {
-	p = parse_power(p, q, &entry->vcc);
-	if (p == NULL)
-		return -EINVAL;
-    } else
-	entry->vcc.present = 0;
-    if ((features & 3) > 1) {
-	p = parse_power(p, q, &entry->vpp1);
-	if (p == NULL)
-		return -EINVAL;
-    } else
-	entry->vpp1.present = 0;
-    if ((features & 3) > 2) {
-	p = parse_power(p, q, &entry->vpp2);
-	if (p == NULL)
-		return -EINVAL;
-    } else
-	entry->vpp2.present = 0;
+	/* Timing options */
+	if (features & 0x04) {
+		p = parse_timing(p, q, &entry->timing);
+		if (p == NULL)
+			return -EINVAL;
+	} else {
+		entry->timing.wait = 0;
+		entry->timing.ready = 0;
+		entry->timing.reserved = 0;
+	}
 
-    /* Timing options */
-    if (features & 0x04) {
-	p = parse_timing(p, q, &entry->timing);
-	if (p == NULL)
-		return -EINVAL;
-    } else {
-	entry->timing.wait = 0;
-	entry->timing.ready = 0;
-	entry->timing.reserved = 0;
-    }
+	/* I/O window options */
+	if (features & 0x08) {
+		p = parse_io(p, q, &entry->io);
+		if (p == NULL)
+			return -EINVAL;
+	} else
+		entry->io.nwin = 0;
 
-    /* I/O window options */
-    if (features & 0x08) {
-	p = parse_io(p, q, &entry->io);
-	if (p == NULL)
-		return -EINVAL;
-    } else
-	entry->io.nwin = 0;
+	/* Interrupt options */
+	if (features & 0x10) {
+		p = parse_irq(p, q, &entry->irq);
+		if (p == NULL)
+			return -EINVAL;
+	} else
+		entry->irq.IRQInfo1 = 0;
 
-    /* Interrupt options */
-    if (features & 0x10) {
-	p = parse_irq(p, q, &entry->irq);
-	if (p == NULL)
-		return -EINVAL;
-    } else
-	entry->irq.IRQInfo1 = 0;
+	switch (features & 0x60) {
+	case 0x00:
+		entry->mem.nwin = 0;
+		break;
+	case 0x20:
+		entry->mem.nwin = 1;
+		entry->mem.win[0].len = get_unaligned_le16(p) << 8;
+		entry->mem.win[0].card_addr = 0;
+		entry->mem.win[0].host_addr = 0;
+		p += 2;
+		if (p > q)
+			return -EINVAL;
+		break;
+	case 0x40:
+		entry->mem.nwin = 1;
+		entry->mem.win[0].len = get_unaligned_le16(p) << 8;
+		entry->mem.win[0].card_addr = get_unaligned_le16(p + 2) << 8;
+		entry->mem.win[0].host_addr = 0;
+		p += 4;
+		if (p > q)
+			return -EINVAL;
+		break;
+	case 0x60:
+		p = parse_mem(p, q, &entry->mem);
+		if (p == NULL)
+			return -EINVAL;
+		break;
+	}
 
-    switch (features & 0x60) {
-    case 0x00:
-	entry->mem.nwin = 0;
-	break;
-    case 0x20:
-	entry->mem.nwin = 1;
-	entry->mem.win[0].len = get_unaligned_le16(p) << 8;
-	entry->mem.win[0].card_addr = 0;
-	entry->mem.win[0].host_addr = 0;
-	p += 2;
-	if (p > q)
-		return -EINVAL;
-	break;
-    case 0x40:
-	entry->mem.nwin = 1;
-	entry->mem.win[0].len = get_unaligned_le16(p) << 8;
-	entry->mem.win[0].card_addr = get_unaligned_le16(p + 2) << 8;
-	entry->mem.win[0].host_addr = 0;
-	p += 4;
-	if (p > q)
-		return -EINVAL;
-	break;
-    case 0x60:
-	p = parse_mem(p, q, &entry->mem);
-	if (p == NULL)
-		return -EINVAL;
-	break;
-    }
+	/* Misc features */
+	if (features & 0x80) {
+		if (p == q)
+			return -EINVAL;
+		entry->flags |= (*p << 8);
+		while (*p & 0x80)
+			if (++p == q)
+				return -EINVAL;
+		p++;
+	}
 
-    /* Misc features */
-    if (features & 0x80) {
-	if (p == q)
-		return -EINVAL;
-	entry->flags |= (*p << 8);
-	while (*p & 0x80)
-	    if (++p == q)
-		    return -EINVAL;
-	p++;
-    }
+	entry->subtuples = q-p;
 
-    entry->subtuples = q-p;
-
-    return 0;
+	return 0;
 }
 
-/*====================================================================*/
 
 static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
 {
-    u_char *p, *q;
-    int n;
+	u_char *p, *q;
+	int n;
 
-    p = (u_char *)tuple->TupleData;
-    q = p + tuple->TupleDataLen;
+	p = (u_char *)tuple->TupleData;
+	q = p + tuple->TupleDataLen;
 
-    for (n = 0; n < CISTPL_MAX_DEVICES; n++) {
-	if (p > q-6)
-		break;
-	geo->geo[n].buswidth = p[0];
-	geo->geo[n].erase_block = 1 << (p[1]-1);
-	geo->geo[n].read_block  = 1 << (p[2]-1);
-	geo->geo[n].write_block = 1 << (p[3]-1);
-	geo->geo[n].partition   = 1 << (p[4]-1);
-	geo->geo[n].interleave  = 1 << (p[5]-1);
-	p += 6;
-    }
-    geo->ngeo = n;
-    return 0;
+	for (n = 0; n < CISTPL_MAX_DEVICES; n++) {
+		if (p > q-6)
+			break;
+		geo->geo[n].buswidth = p[0];
+		geo->geo[n].erase_block = 1 << (p[1]-1);
+		geo->geo[n].read_block  = 1 << (p[2]-1);
+		geo->geo[n].write_block = 1 << (p[3]-1);
+		geo->geo[n].partition   = 1 << (p[4]-1);
+		geo->geo[n].interleave  = 1 << (p[5]-1);
+		p += 6;
+	}
+	geo->ngeo = n;
+	return 0;
 }
 
-/*====================================================================*/
 
 static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
 {
-    u_char *p, *q;
+	u_char *p, *q;
 
-    if (tuple->TupleDataLen < 10)
-	return -EINVAL;
+	if (tuple->TupleDataLen < 10)
+		return -EINVAL;
 
-    p = tuple->TupleData;
-    q = p + tuple->TupleDataLen;
+	p = tuple->TupleData;
+	q = p + tuple->TupleDataLen;
 
-    v2->vers = p[0];
-    v2->comply = p[1];
-    v2->dindex = get_unaligned_le16(p + 2);
-    v2->vspec8 = p[6];
-    v2->vspec9 = p[7];
-    v2->nhdr = p[8];
-    p += 9;
-    return parse_strings(p, q, 2, v2->str, &v2->vendor, NULL);
+	v2->vers = p[0];
+	v2->comply = p[1];
+	v2->dindex = get_unaligned_le16(p + 2);
+	v2->vspec8 = p[6];
+	v2->vspec9 = p[7];
+	v2->nhdr = p[8];
+	p += 9;
+	return parse_strings(p, q, 2, v2->str, &v2->vendor, NULL);
 }
 
-/*====================================================================*/
 
 static int parse_org(tuple_t *tuple, cistpl_org_t *org)
 {
-    u_char *p, *q;
-    int i;
+	u_char *p, *q;
+	int i;
 
-    p = tuple->TupleData;
-    q = p + tuple->TupleDataLen;
-    if (p == q)
-	    return -EINVAL;
-    org->data_org = *p;
-    if (++p == q)
-	    return -EINVAL;
-    for (i = 0; i < 30; i++) {
-	org->desc[i] = *p;
-	if (*p == '\0')
-		break;
+	p = tuple->TupleData;
+	q = p + tuple->TupleDataLen;
+	if (p == q)
+		return -EINVAL;
+	org->data_org = *p;
 	if (++p == q)
 		return -EINVAL;
-    }
-    return 0;
+	for (i = 0; i < 30; i++) {
+		org->desc[i] = *p;
+		if (*p == '\0')
+			break;
+		if (++p == q)
+			return -EINVAL;
+	}
+	return 0;
 }
 
-/*====================================================================*/
 
 static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
 {
-    u_char *p;
+	u_char *p;
 
-    if (tuple->TupleDataLen < 10)
-	return -EINVAL;
+	if (tuple->TupleDataLen < 10)
+		return -EINVAL;
 
-    p = tuple->TupleData;
+	p = tuple->TupleData;
 
-    fmt->type = p[0];
-    fmt->edc = p[1];
-    fmt->offset = get_unaligned_le32(p + 2);
-    fmt->length = get_unaligned_le32(p + 6);
+	fmt->type = p[0];
+	fmt->edc = p[1];
+	fmt->offset = get_unaligned_le32(p + 2);
+	fmt->length = get_unaligned_le32(p + 6);
 
-    return 0;
+	return 0;
 }
 
-/*====================================================================*/
 
 int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse)
 {
-    int ret = 0;
+	int ret = 0;
 
-    if (tuple->TupleDataLen > tuple->TupleDataMax)
-	return -EINVAL;
-    switch (tuple->TupleCode) {
-    case CISTPL_DEVICE:
-    case CISTPL_DEVICE_A:
-	ret = parse_device(tuple, &parse->device);
-	break;
-    case CISTPL_CHECKSUM:
-	ret = parse_checksum(tuple, &parse->checksum);
-	break;
-    case CISTPL_LONGLINK_A:
-    case CISTPL_LONGLINK_C:
-	ret = parse_longlink(tuple, &parse->longlink);
-	break;
-    case CISTPL_LONGLINK_MFC:
-	ret = parse_longlink_mfc(tuple, &parse->longlink_mfc);
-	break;
-    case CISTPL_VERS_1:
-	ret = parse_vers_1(tuple, &parse->version_1);
-	break;
-    case CISTPL_ALTSTR:
-	ret = parse_altstr(tuple, &parse->altstr);
-	break;
-    case CISTPL_JEDEC_A:
-    case CISTPL_JEDEC_C:
-	ret = parse_jedec(tuple, &parse->jedec);
-	break;
-    case CISTPL_MANFID:
-	ret = parse_manfid(tuple, &parse->manfid);
-	break;
-    case CISTPL_FUNCID:
-	ret = parse_funcid(tuple, &parse->funcid);
-	break;
-    case CISTPL_FUNCE:
-	ret = parse_funce(tuple, &parse->funce);
-	break;
-    case CISTPL_CONFIG:
-	ret = parse_config(tuple, &parse->config);
-	break;
-    case CISTPL_CFTABLE_ENTRY:
-	ret = parse_cftable_entry(tuple, &parse->cftable_entry);
-	break;
-    case CISTPL_DEVICE_GEO:
-    case CISTPL_DEVICE_GEO_A:
-	ret = parse_device_geo(tuple, &parse->device_geo);
-	break;
-    case CISTPL_VERS_2:
-	ret = parse_vers_2(tuple, &parse->vers_2);
-	break;
-    case CISTPL_ORG:
-	ret = parse_org(tuple, &parse->org);
-	break;
-    case CISTPL_FORMAT:
-    case CISTPL_FORMAT_A:
-	ret = parse_format(tuple, &parse->format);
-	break;
-    case CISTPL_NO_LINK:
-    case CISTPL_LINKTARGET:
-	ret = 0;
-	break;
-    default:
-	ret = -EINVAL;
-	break;
-    }
-    if (ret)
-	    pr_debug("parse_tuple failed %d\n", ret);
-    return ret;
+	if (tuple->TupleDataLen > tuple->TupleDataMax)
+		return -EINVAL;
+	switch (tuple->TupleCode) {
+	case CISTPL_DEVICE:
+	case CISTPL_DEVICE_A:
+		ret = parse_device(tuple, &parse->device);
+		break;
+	case CISTPL_CHECKSUM:
+		ret = parse_checksum(tuple, &parse->checksum);
+		break;
+	case CISTPL_LONGLINK_A:
+	case CISTPL_LONGLINK_C:
+		ret = parse_longlink(tuple, &parse->longlink);
+		break;
+	case CISTPL_LONGLINK_MFC:
+		ret = parse_longlink_mfc(tuple, &parse->longlink_mfc);
+		break;
+	case CISTPL_VERS_1:
+		ret = parse_vers_1(tuple, &parse->version_1);
+		break;
+	case CISTPL_ALTSTR:
+		ret = parse_altstr(tuple, &parse->altstr);
+		break;
+	case CISTPL_JEDEC_A:
+	case CISTPL_JEDEC_C:
+		ret = parse_jedec(tuple, &parse->jedec);
+		break;
+	case CISTPL_MANFID:
+		ret = parse_manfid(tuple, &parse->manfid);
+		break;
+	case CISTPL_FUNCID:
+		ret = parse_funcid(tuple, &parse->funcid);
+		break;
+	case CISTPL_FUNCE:
+		ret = parse_funce(tuple, &parse->funce);
+		break;
+	case CISTPL_CONFIG:
+		ret = parse_config(tuple, &parse->config);
+		break;
+	case CISTPL_CFTABLE_ENTRY:
+		ret = parse_cftable_entry(tuple, &parse->cftable_entry);
+		break;
+	case CISTPL_DEVICE_GEO:
+	case CISTPL_DEVICE_GEO_A:
+		ret = parse_device_geo(tuple, &parse->device_geo);
+		break;
+	case CISTPL_VERS_2:
+		ret = parse_vers_2(tuple, &parse->vers_2);
+		break;
+	case CISTPL_ORG:
+		ret = parse_org(tuple, &parse->org);
+		break;
+	case CISTPL_FORMAT:
+	case CISTPL_FORMAT_A:
+		ret = parse_format(tuple, &parse->format);
+		break;
+	case CISTPL_NO_LINK:
+	case CISTPL_LINKTARGET:
+		ret = 0;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	if (ret)
+		pr_debug("parse_tuple failed %d\n", ret);
+	return ret;
 }
 EXPORT_SYMBOL(pcmcia_parse_tuple);
 
-/*======================================================================
 
-    This is used internally by Card Services to look up CIS stuff.
-
-======================================================================*/
-
-int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse)
+/**
+ * pccard_read_tuple() - internal CIS tuple access
+ * @s:		the struct pcmcia_socket where the card is inserted
+ * @function:	the device function we loop for
+ * @code:	which CIS code shall we look for?
+ * @parse:	buffer where the tuple shall be parsed (or NULL, if no parse)
+ *
+ * pccard_read_tuple() reads out one tuple and attempts to parse it
+ */
+int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
+		cisdata_t code, void *parse)
 {
-    tuple_t tuple;
-    cisdata_t *buf;
-    int ret;
+	tuple_t tuple;
+	cisdata_t *buf;
+	int ret;
 
-    buf = kmalloc(256, GFP_KERNEL);
-    if (buf == NULL) {
-	    dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n");
-	    return -ENOMEM;
-    }
-    tuple.DesiredTuple = code;
-    tuple.Attributes = 0;
-    if (function == BIND_FN_ALL)
-	    tuple.Attributes = TUPLE_RETURN_COMMON;
-    ret = pccard_get_first_tuple(s, function, &tuple);
-    if (ret != 0)
-	    goto done;
-    tuple.TupleData = buf;
-    tuple.TupleOffset = 0;
-    tuple.TupleDataMax = 255;
-    ret = pccard_get_tuple_data(s, &tuple);
-    if (ret != 0)
-	    goto done;
-    ret = pcmcia_parse_tuple(&tuple, parse);
+	buf = kmalloc(256, GFP_KERNEL);
+	if (buf == NULL) {
+		dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n");
+		return -ENOMEM;
+	}
+	tuple.DesiredTuple = code;
+	tuple.Attributes = 0;
+	if (function == BIND_FN_ALL)
+		tuple.Attributes = TUPLE_RETURN_COMMON;
+	ret = pccard_get_first_tuple(s, function, &tuple);
+	if (ret != 0)
+		goto done;
+	tuple.TupleData = buf;
+	tuple.TupleOffset = 0;
+	tuple.TupleDataMax = 255;
+	ret = pccard_get_tuple_data(s, &tuple);
+	if (ret != 0)
+		goto done;
+	ret = pcmcia_parse_tuple(&tuple, parse);
 done:
-    kfree(buf);
-    return ret;
+	kfree(buf);
+	return ret;
 }
 
 
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
index 3889cf07..9254ab0 100644
--- a/drivers/pcmcia/db1xxx_ss.c
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -42,7 +42,6 @@
 	int		nr;		/* socket number */
 	void		*virt_io;
 
-	/* the "pseudo" addresses of the PCMCIA space. */
 	phys_addr_t	phys_io;
 	phys_addr_t	phys_attr;
 	phys_addr_t	phys_mem;
@@ -437,7 +436,7 @@
 	 * This includes IRQs for Carddetection/ejection, the card
 	 *  itself and optional status change detection.
 	 * Also, the memory areas covered by a socket.  For these
-	 *  we require the 32bit "pseudo" addresses (see the au1000.h
+	 *  we require the real 36bit addresses (see the au1000.h
 	 *  header for more information).
 	 */
 
@@ -459,11 +458,7 @@
 
 	ret = -ENODEV;
 
-	/*
-	 * pseudo-attr:  The 32bit address of the PCMCIA attribute space
-	 * for this socket (usually the 36bit address shifted 4 to the
-	 * right).
-	 */
+	/* 36bit PCMCIA Attribute area address */
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
 	if (!r) {
 		printk(KERN_ERR "pcmcia%d has no 'pseudo-attr' resource!\n",
@@ -472,10 +467,7 @@
 	}
 	sock->phys_attr = r->start;
 
-	/*
-	 * pseudo-mem:  The 32bit address of the PCMCIA memory space for
-	 * this socket (usually the 36bit address shifted 4 to the right)
-	 */
+	/* 36bit PCMCIA Memory area address */
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
 	if (!r) {
 		printk(KERN_ERR "pcmcia%d has no 'pseudo-mem' resource!\n",
@@ -484,10 +476,7 @@
 	}
 	sock->phys_mem = r->start;
 
-	/*
-	 * pseudo-io:  The 32bit address of the PCMCIA IO space for this
-	 * socket (usually the 36bit address shifted 4 to the right).
-	 */
+	/* 36bit PCMCIA IO area address */
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
 	if (!r) {
 		printk(KERN_ERR "pcmcia%d has no 'pseudo-io' resource!\n",
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 0f98be4..ad93ebd 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -971,9 +971,9 @@
 {
 	int rc;
 
-	down(&dev->sem);
+	device_lock(dev);
 	rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND);
-	up(&dev->sem);
+	device_unlock(dev);
 	return rc;
 }
 
@@ -981,9 +981,9 @@
 {
 	int rc;
 
-	down(&dev->sem);
+	device_lock(dev);
 	rc = pcmcia_dev_resume(dev);
-	up(&dev->sem);
+	device_unlock(dev);
 	return rc;
 }
 
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index e1741cd..7c20491 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -48,23 +48,13 @@
  *     Specifies the interrupt delivery mode.  The default (1) is to use PCI
  *     interrupts; a value of 0 selects ISA interrupts. This must be set for
  *     correct operation of PCI card readers.
- *
- *  irq_list=i,j,...
- *     This list limits the set of interrupts that can be used by PCMCIA
- *     cards.
- *     The default list is 3,4,5,7,9,10,11.
- *     (irq_list parameter is not used, if irq_mode = 1)
  */
 
 static int irq_mode = 1; /* 0 = ISA interrupt, 1 = PCI interrupt */
-static int irq_list[16];
-static unsigned int irq_list_count = 0;
 
 module_param(irq_mode, int, 0444);
-module_param_array(irq_list, int, &irq_list_count, 0444);
 MODULE_PARM_DESC(irq_mode,
 		"interrupt delivery mode. 0 = ISA, 1 = PCI. default is 1");
-MODULE_PARM_DESC(irq_list, "interrupts that can be used by PCMCIA cards");
 
 static DEFINE_SPINLOCK(port_lock);
 
@@ -605,13 +595,7 @@
 		return 0;
 	}
 
-	if (irq_list_count == 0)
-		mask0 = 0xffff;
-	else
-		for (i = mask0 = 0; i < irq_list_count; i++)
-			mask0 |= (1<<irq_list[i]);
-
-	mask0 &= PD67_MASK;
+	mask0 = PD67_MASK;
 
 	/* just find interrupts that aren't in use */
 	for (i = 0; i < 16; i++)
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index e6f7d41..452c83b 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -79,9 +79,8 @@
 
 #ifdef CONFIG_X86
 	if (res->flags & IORESOURCE_IO) {
-		if (start & 0x300) {
+		if (start & 0x300)
 			start = (start + 0x3ff) & ~0x3ff;
-		}
 	}
 #endif
 
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index de6bc33..db79ca6 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -21,11 +21,18 @@
 
 #include "sa1111_generic.h"
 
+#define IDX_IRQ_S0_READY_NINT	(0)
+#define IDX_IRQ_S0_CD_VALID	(1)
+#define IDX_IRQ_S0_BVD1_STSCHG	(2)
+#define IDX_IRQ_S1_READY_NINT	(3)
+#define IDX_IRQ_S1_CD_VALID	(4)
+#define IDX_IRQ_S1_BVD1_STSCHG	(5)
+
 static struct pcmcia_irqs irqs[] = {
-	{ 0, IRQ_S0_CD_VALID,    "SA1111 PCMCIA card detect" },
-	{ 0, IRQ_S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1"        },
-	{ 1, IRQ_S1_CD_VALID,    "SA1111 CF card detect"     },
-	{ 1, IRQ_S1_BVD1_STSCHG, "SA1111 CF BVD1"            },
+	{ 0, NO_IRQ, "SA1111 PCMCIA card detect" },
+	{ 0, NO_IRQ, "SA1111 PCMCIA BVD1"        },
+	{ 1, NO_IRQ, "SA1111 CF card detect"     },
+	{ 1, NO_IRQ, "SA1111 CF BVD1"            },
 };
 
 static int sa1111_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
@@ -136,7 +143,9 @@
 		s->soc.ops = ops;
 		s->soc.socket.owner = ops->owner;
 		s->soc.socket.dev.parent = &dev->dev;
-		s->soc.socket.pci_irq = s->soc.nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT;
+		s->soc.socket.pci_irq = s->soc.nr ?
+				dev->irq[IDX_IRQ_S0_READY_NINT] :
+				dev->irq[IDX_IRQ_S1_READY_NINT];
 		s->dev = dev;
 
 		ret = add(&s->soc);
@@ -162,6 +171,12 @@
 
 	base = dev->mapbase;
 
+	/* Initialize PCMCIA IRQs */
+	irqs[0].irq = dev->irq[IDX_IRQ_S0_CD_VALID];
+	irqs[1].irq = dev->irq[IDX_IRQ_S0_BVD1_STSCHG];
+	irqs[2].irq = dev->irq[IDX_IRQ_S1_CD_VALID];
+	irqs[3].irq = dev->irq[IDX_IRQ_S1_BVD1_STSCHG];
+
 	/*
 	 * Initialise the suspend state.
 	 */
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
index 61560cd..f9009d3 100644
--- a/drivers/pcmcia/xxs1500_ss.c
+++ b/drivers/pcmcia/xxs1500_ss.c
@@ -218,11 +218,7 @@
 
 	ret = -ENODEV;
 
-	/*
-	 * pseudo-attr:  The 32bit address of the PCMCIA attribute space
-	 * for this socket (usually the 36bit address shifted 4 to the
-	 * right).
-	 */
+	/* 36bit PCMCIA Attribute area address */
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
 	if (!r) {
 		dev_err(&pdev->dev, "missing 'pcmcia-attr' resource!\n");
@@ -230,10 +226,7 @@
 	}
 	sock->phys_attr = r->start;
 
-	/*
-	 * pseudo-mem:  The 32bit address of the PCMCIA memory space for
-	 * this socket (usually the 36bit address shifted 4 to the right)
-	 */
+	/* 36bit PCMCIA Memory area address */
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
 	if (!r) {
 		dev_err(&pdev->dev, "missing 'pcmcia-mem' resource!\n");
@@ -241,10 +234,7 @@
 	}
 	sock->phys_mem = r->start;
 
-	/*
-	 * pseudo-io:  The 32bit address of the PCMCIA IO space for this
-	 * socket (usually the 36bit address shifted 4 to the right).
-	 */
+	/* 36bit PCMCIA IO area address */
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
 	if (!r) {
 		dev_err(&pdev->dev, "missing 'pcmcia-io' resource!\n");
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index b85375f..967c766 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1408,10 +1408,10 @@
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX),
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX),
 
-	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, TI12XX),
-	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, TI12XX),
-	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, TI12XX),
-	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, TI12XX),
+	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, ENE),
+	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, ENE),
+	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, ENE),
+	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, ENE),
 	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE),
 	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
 	CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 6848f21..e631dbe 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -59,6 +59,8 @@
 	select NEW_LEDS
 	select BACKLIGHT_CLASS_DEVICE
 	depends on INPUT
+	depends on RFKILL || RFKILL = n
+	select INPUT_SPARSEKMAP
 	---help---
 	  This is the new Linux driver for Asus laptops. It may also support some
 	  MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
@@ -148,6 +150,7 @@
 	tristate "MSI Laptop Extras"
 	depends on ACPI
 	depends on BACKLIGHT_CLASS_DEVICE
+	depends on RFKILL
 	---help---
 	  This is a driver for laptops built by MSI (MICRO-STAR
 	  INTERNATIONAL):
@@ -177,6 +180,7 @@
 	tristate "Compal Laptop Extras"
 	depends on ACPI
 	depends on BACKLIGHT_CLASS_DEVICE
+	depends on RFKILL
 	---help---
 	  This is a driver for laptops built by Compal:
 
@@ -320,9 +324,15 @@
 	  server running, phase of the moon, and the current mood of
 	  Schroedinger's cat.  If you can use X.org's RandR to control
 	  your ThinkPad's video output ports instead of this feature,
-	  don't think twice: do it and say N here to save some memory.
+	  don't think twice: do it and say N here to save memory and avoid
+	  bad interactions with X.org.
 
-	  If you are not sure, say Y here.
+	  NOTE: access to this feature is limited to processes with the
+	  CAP_SYS_ADMIN capability, to avoid local DoS issues in platforms
+	  where it interacts badly with X.org.
+
+	  If you are not sure, say Y here but do try to check if you could
+	  be using X.org RandR instead.
 
 config THINKPAD_ACPI_HOTKEY_POLL
 	bool "Support NVRAM polling for hot keys"
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 61a1c75..791fcf3 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -45,58 +45,23 @@
 #include <linux/fb.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/rfkill.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
-#include <asm/uaccess.h>
-#include <linux/input.h>
 
-#define ASUS_LAPTOP_VERSION "0.42"
+#define ASUS_LAPTOP_VERSION	"0.42"
 
-#define ASUS_HOTK_NAME          "Asus Laptop Support"
-#define ASUS_HOTK_CLASS         "hotkey"
-#define ASUS_HOTK_DEVICE_NAME   "Hotkey"
-#define ASUS_HOTK_FILE          KBUILD_MODNAME
-#define ASUS_HOTK_PREFIX        "\\_SB.ATKD."
-
-
-/*
- * Some events we use, same for all Asus
- */
-#define ATKD_BR_UP       0x10
-#define ATKD_BR_DOWN     0x20
-#define ATKD_LCD_ON      0x33
-#define ATKD_LCD_OFF     0x34
-
-/*
- * Known bits returned by \_SB.ATKD.HWRS
- */
-#define WL_HWRS     0x80
-#define BT_HWRS     0x100
-
-/*
- * Flags for hotk status
- * WL_ON and BT_ON are also used for wireless_status()
- */
-#define WL_ON       0x01	/* internal Wifi */
-#define BT_ON       0x02	/* internal Bluetooth */
-#define MLED_ON     0x04	/* mail LED */
-#define TLED_ON     0x08	/* touchpad LED */
-#define RLED_ON     0x10	/* Record LED */
-#define PLED_ON     0x20	/* Phone LED */
-#define GLED_ON     0x40	/* Gaming LED */
-#define LCD_ON      0x80	/* LCD backlight */
-#define GPS_ON      0x100	/* GPS */
-#define KEY_ON      0x200	/* Keyboard backlight */
-
-#define ASUS_LOG    ASUS_HOTK_FILE ": "
-#define ASUS_ERR    KERN_ERR    ASUS_LOG
-#define ASUS_WARNING    KERN_WARNING    ASUS_LOG
-#define ASUS_NOTICE KERN_NOTICE ASUS_LOG
-#define ASUS_INFO   KERN_INFO   ASUS_LOG
-#define ASUS_DEBUG  KERN_DEBUG  ASUS_LOG
+#define ASUS_LAPTOP_NAME	"Asus Laptop Support"
+#define ASUS_LAPTOP_CLASS	"hotkey"
+#define ASUS_LAPTOP_DEVICE_NAME	"Hotkey"
+#define ASUS_LAPTOP_FILE	KBUILD_MODNAME
+#define ASUS_LAPTOP_PREFIX	"\\_SB.ATKD."
 
 MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary");
-MODULE_DESCRIPTION(ASUS_HOTK_NAME);
+MODULE_DESCRIPTION(ASUS_LAPTOP_NAME);
 MODULE_LICENSE("GPL");
 
 /*
@@ -113,225 +78,209 @@
 module_param(wapf, uint, 0644);
 MODULE_PARM_DESC(wapf, "WAPF value");
 
-#define ASUS_HANDLE(object, paths...)					\
-	static acpi_handle  object##_handle = NULL;			\
-	static char *object##_paths[] = { paths }
+static uint wlan_status = 1;
+static uint bluetooth_status = 1;
+
+module_param(wlan_status, uint, 0644);
+MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot "
+		 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
+		 "default is 1");
+
+module_param(bluetooth_status, uint, 0644);
+MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot "
+		 "(0 = disabled, 1 = enabled, -1 = don't do anything). "
+		 "default is 1");
+
+/*
+ * Some events we use, same for all Asus
+ */
+#define ATKD_BR_UP	0x10	/* (event & ~ATKD_BR_UP) = brightness level */
+#define ATKD_BR_DOWN	0x20	/* (event & ~ATKD_BR_DOWN) = britghness level */
+#define ATKD_BR_MIN	ATKD_BR_UP
+#define ATKD_BR_MAX	(ATKD_BR_DOWN | 0xF)	/* 0x2f */
+#define ATKD_LCD_ON	0x33
+#define ATKD_LCD_OFF	0x34
+
+/*
+ * Known bits returned by \_SB.ATKD.HWRS
+ */
+#define WL_HWRS		0x80
+#define BT_HWRS		0x100
+
+/*
+ * Flags for hotk status
+ * WL_ON and BT_ON are also used for wireless_status()
+ */
+#define WL_RSTS		0x01	/* internal Wifi */
+#define BT_RSTS		0x02	/* internal Bluetooth */
 
 /* LED */
-ASUS_HANDLE(mled_set, ASUS_HOTK_PREFIX "MLED");
-ASUS_HANDLE(tled_set, ASUS_HOTK_PREFIX "TLED");
-ASUS_HANDLE(rled_set, ASUS_HOTK_PREFIX "RLED");	/* W1JC */
-ASUS_HANDLE(pled_set, ASUS_HOTK_PREFIX "PLED");	/* A7J */
-ASUS_HANDLE(gled_set, ASUS_HOTK_PREFIX "GLED");	/* G1, G2 (probably) */
+#define METHOD_MLED		"MLED"
+#define METHOD_TLED		"TLED"
+#define METHOD_RLED		"RLED"	/* W1JC */
+#define METHOD_PLED		"PLED"	/* A7J */
+#define METHOD_GLED		"GLED"	/* G1, G2 (probably) */
 
 /* LEDD */
-ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM");
+#define METHOD_LEDD		"SLCM"
 
 /*
  * Bluetooth and WLAN
  * WLED and BLED are not handled like other XLED, because in some dsdt
  * they also control the WLAN/Bluetooth device.
  */
-ASUS_HANDLE(wl_switch, ASUS_HOTK_PREFIX "WLED");
-ASUS_HANDLE(bt_switch, ASUS_HOTK_PREFIX "BLED");
-ASUS_HANDLE(wireless_status, ASUS_HOTK_PREFIX "RSTS");	/* All new models */
+#define METHOD_WLAN		"WLED"
+#define METHOD_BLUETOOTH	"BLED"
+#define METHOD_WL_STATUS	"RSTS"
 
 /* Brightness */
-ASUS_HANDLE(brightness_set, ASUS_HOTK_PREFIX "SPLV");
-ASUS_HANDLE(brightness_get, ASUS_HOTK_PREFIX "GPLV");
+#define METHOD_BRIGHTNESS_SET	"SPLV"
+#define METHOD_BRIGHTNESS_GET	"GPLV"
 
 /* Backlight */
-ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10",	/* All new models */
-	    "\\_SB.PCI0.ISA.EC0._Q10",	/* A1x */
-	    "\\_SB.PCI0.PX40.ECD0._Q10",	/* L3C */
-	    "\\_SB.PCI0.PX40.EC0.Q10",	/* M1A */
-	    "\\_SB.PCI0.LPCB.EC0._Q10",	/* P30 */
-	    "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */
-	    "\\_SB.PCI0.PX40.Q10",	/* S1x */
-	    "\\Q10");		/* A2x, L2D, L3D, M2E */
+static acpi_handle lcd_switch_handle;
+static const char *lcd_switch_paths[] = {
+  "\\_SB.PCI0.SBRG.EC0._Q10",	/* All new models */
+  "\\_SB.PCI0.ISA.EC0._Q10",	/* A1x */
+  "\\_SB.PCI0.PX40.ECD0._Q10",	/* L3C */
+  "\\_SB.PCI0.PX40.EC0.Q10",	/* M1A */
+  "\\_SB.PCI0.LPCB.EC0._Q10",	/* P30 */
+  "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */
+  "\\_SB.PCI0.PX40.Q10",	/* S1x */
+  "\\Q10"};		/* A2x, L2D, L3D, M2E */
 
 /* Display */
-ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP");
-ASUS_HANDLE(display_get,
-	    /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
-	    "\\_SB.PCI0.P0P1.VGA.GETD",
-	    /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */
-	    "\\_SB.PCI0.P0P2.VGA.GETD",
-	    /* A6V A6Q */
-	    "\\_SB.PCI0.P0P3.VGA.GETD",
-	    /* A6T, A6M */
-	    "\\_SB.PCI0.P0PA.VGA.GETD",
-	    /* L3C */
-	    "\\_SB.PCI0.PCI1.VGAC.NMAP",
-	    /* Z96F */
-	    "\\_SB.PCI0.VGA.GETD",
-	    /* A2D */
-	    "\\ACTD",
-	    /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
-	    "\\ADVG",
-	    /* P30 */
-	    "\\DNXT",
-	    /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
-	    "\\INFB",
-	    /* A3F A6F A3N A3L M6N W3N W6A */
-	    "\\SSTE");
+#define METHOD_SWITCH_DISPLAY	"SDSP"
 
-ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */
-ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL");	 /* Z71A Z71V */
+static acpi_handle display_get_handle;
+static const char *display_get_paths[] = {
+  /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
+  "\\_SB.PCI0.P0P1.VGA.GETD",
+  /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */
+  "\\_SB.PCI0.P0P2.VGA.GETD",
+  /* A6V A6Q */
+  "\\_SB.PCI0.P0P3.VGA.GETD",
+  /* A6T, A6M */
+  "\\_SB.PCI0.P0PA.VGA.GETD",
+  /* L3C */
+  "\\_SB.PCI0.PCI1.VGAC.NMAP",
+  /* Z96F */
+  "\\_SB.PCI0.VGA.GETD",
+  /* A2D */
+  "\\ACTD",
+  /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
+  "\\ADVG",
+  /* P30 */
+  "\\DNXT",
+  /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
+  "\\INFB",
+  /* A3F A6F A3N A3L M6N W3N W6A */
+  "\\SSTE"};
+
+#define METHOD_ALS_CONTROL	"ALSC" /* Z71A Z71V */
+#define METHOD_ALS_LEVEL	"ALSL" /* Z71A Z71V */
 
 /* GPS */
 /* R2H use different handle for GPS on/off */
-ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON");	/* R2H */
-ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF");	/* R2H */
-ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST");
+#define METHOD_GPS_ON		"SDON"
+#define METHOD_GPS_OFF		"SDOF"
+#define METHOD_GPS_STATUS	"GPST"
 
 /* Keyboard light */
-ASUS_HANDLE(kled_set, ASUS_HOTK_PREFIX "SLKB");
-ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB");
+#define METHOD_KBD_LIGHT_SET	"SLKB"
+#define METHOD_KBD_LIGHT_GET	"GLKB"
+
+/*
+ * Define a specific led structure to keep the main structure clean
+ */
+struct asus_led {
+	int wk;
+	struct work_struct work;
+	struct led_classdev led;
+	struct asus_laptop *asus;
+	const char *method;
+};
 
 /*
  * This is the main structure, we can use it to store anything interesting
  * about the hotk device
  */
-struct asus_hotk {
+struct asus_laptop {
 	char *name;		/* laptop name */
-	struct acpi_device *device;	/* the device we are in */
+
+	struct acpi_table_header *dsdt_info;
+	struct platform_device *platform_device;
+	struct acpi_device *device;		/* the device we are in */
+	struct backlight_device *backlight_device;
+
+	struct input_dev *inputdev;
+	struct key_entry *keymap;
+
+	struct asus_led mled;
+	struct asus_led tled;
+	struct asus_led rled;
+	struct asus_led pled;
+	struct asus_led gled;
+	struct asus_led kled;
+	struct workqueue_struct *led_workqueue;
+
+	int wireless_status;
+	bool have_rsts;
+	int lcd_state;
+
+	struct rfkill *gps_rfkill;
+
 	acpi_handle handle;	/* the handle of the hotk device */
-	char status;		/* status of the hotk, for LEDs, ... */
 	u32 ledd_status;	/* status of the LED display */
 	u8 light_level;		/* light sensor level */
 	u8 light_switch;	/* light sensor switch value */
 	u16 event_count[128];	/* count for each event TODO make this better */
-	struct input_dev *inputdev;
 	u16 *keycode_map;
 };
 
-/*
- * This header is made available to allow proper configuration given model,
- * revision number , ... this info cannot go in struct asus_hotk because it is
- * available before the hotk
- */
-static struct acpi_table_header *asus_info;
-
-/* The actual device the driver binds to */
-static struct asus_hotk *hotk;
-
-/*
- * The hotkey driver declaration
- */
-static const struct acpi_device_id asus_device_ids[] = {
-	{"ATK0100", 0},
-	{"ATK0101", 0},
-	{"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, asus_device_ids);
-
-static int asus_hotk_add(struct acpi_device *device);
-static int asus_hotk_remove(struct acpi_device *device, int type);
-static void asus_hotk_notify(struct acpi_device *device, u32 event);
-
-static struct acpi_driver asus_hotk_driver = {
-	.name = ASUS_HOTK_NAME,
-	.class = ASUS_HOTK_CLASS,
-	.owner = THIS_MODULE,
-	.ids = asus_device_ids,
-	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-	.ops = {
-		.add = asus_hotk_add,
-		.remove = asus_hotk_remove,
-		.notify = asus_hotk_notify,
-		},
-};
-
-/* The backlight device /sys/class/backlight */
-static struct backlight_device *asus_backlight_device;
-
-/*
- * The backlight class declaration
- */
-static int read_brightness(struct backlight_device *bd);
-static int update_bl_status(struct backlight_device *bd);
-static struct backlight_ops asusbl_ops = {
-	.get_brightness = read_brightness,
-	.update_status = update_bl_status,
-};
-
-/*
- * These functions actually update the LED's, and are called from a
- * workqueue. By doing this as separate work rather than when the LED
- * subsystem asks, we avoid messing with the Asus ACPI stuff during a
- * potentially bad time, such as a timer interrupt.
- */
-static struct workqueue_struct *led_workqueue;
-
-#define ASUS_LED(object, ledname, max)					\
-	static void object##_led_set(struct led_classdev *led_cdev,	\
-				     enum led_brightness value);	\
-	static enum led_brightness object##_led_get(			\
-		struct led_classdev *led_cdev);				\
-	static void object##_led_update(struct work_struct *ignored);	\
-	static int object##_led_wk;					\
-	static DECLARE_WORK(object##_led_work, object##_led_update);	\
-	static struct led_classdev object##_led = {			\
-		.name           = "asus::" ledname,			\
-		.brightness_set = object##_led_set,			\
-		.brightness_get = object##_led_get,			\
-		.max_brightness = max					\
-	}
-
-ASUS_LED(mled, "mail", 1);
-ASUS_LED(tled, "touchpad", 1);
-ASUS_LED(rled, "record", 1);
-ASUS_LED(pled, "phone", 1);
-ASUS_LED(gled, "gaming", 1);
-ASUS_LED(kled, "kbd_backlight", 3);
-
-struct key_entry {
-	char type;
-	u8 code;
-	u16 keycode;
-};
-
-enum { KE_KEY, KE_END };
-
-static struct key_entry asus_keymap[] = {
-	{KE_KEY, 0x02, KEY_SCREENLOCK},
-	{KE_KEY, 0x05, KEY_WLAN},
-	{KE_KEY, 0x08, KEY_F13},
-	{KE_KEY, 0x17, KEY_ZOOM},
-	{KE_KEY, 0x1f, KEY_BATTERY},
-	{KE_KEY, 0x30, KEY_VOLUMEUP},
-	{KE_KEY, 0x31, KEY_VOLUMEDOWN},
-	{KE_KEY, 0x32, KEY_MUTE},
-	{KE_KEY, 0x33, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x34, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x40, KEY_PREVIOUSSONG},
-	{KE_KEY, 0x41, KEY_NEXTSONG},
-	{KE_KEY, 0x43, KEY_STOPCD},
-	{KE_KEY, 0x45, KEY_PLAYPAUSE},
-	{KE_KEY, 0x4c, KEY_MEDIA},
-	{KE_KEY, 0x50, KEY_EMAIL},
-	{KE_KEY, 0x51, KEY_WWW},
-	{KE_KEY, 0x55, KEY_CALC},
-	{KE_KEY, 0x5C, KEY_SCREENLOCK},  /* Screenlock */
-	{KE_KEY, 0x5D, KEY_WLAN},
-	{KE_KEY, 0x5E, KEY_WLAN},
-	{KE_KEY, 0x5F, KEY_WLAN},
-	{KE_KEY, 0x60, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x62, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x63, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x6B, KEY_F13}, /* Lock Touchpad */
-	{KE_KEY, 0x82, KEY_CAMERA},
-	{KE_KEY, 0x88, KEY_WLAN },
-	{KE_KEY, 0x8A, KEY_PROG1},
-	{KE_KEY, 0x95, KEY_MEDIA},
-	{KE_KEY, 0x99, KEY_PHONE},
-	{KE_KEY, 0xc4, KEY_KBDILLUMUP},
-	{KE_KEY, 0xc5, KEY_KBDILLUMDOWN},
+static const struct key_entry asus_keymap[] = {
+	/* Lenovo SL Specific keycodes */
+	{KE_KEY, 0x02, { KEY_SCREENLOCK } },
+	{KE_KEY, 0x05, { KEY_WLAN } },
+	{KE_KEY, 0x08, { KEY_F13 } },
+	{KE_KEY, 0x17, { KEY_ZOOM } },
+	{KE_KEY, 0x1f, { KEY_BATTERY } },
+	/* End of Lenovo SL Specific keycodes */
+	{KE_KEY, 0x30, { KEY_VOLUMEUP } },
+	{KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
+	{KE_KEY, 0x32, { KEY_MUTE } },
+	{KE_KEY, 0x33, { KEY_SWITCHVIDEOMODE } },
+	{KE_KEY, 0x34, { KEY_SWITCHVIDEOMODE } },
+	{KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
+	{KE_KEY, 0x41, { KEY_NEXTSONG } },
+	{KE_KEY, 0x43, { KEY_STOPCD } },
+	{KE_KEY, 0x45, { KEY_PLAYPAUSE } },
+	{KE_KEY, 0x4c, { KEY_MEDIA } },
+	{KE_KEY, 0x50, { KEY_EMAIL } },
+	{KE_KEY, 0x51, { KEY_WWW } },
+	{KE_KEY, 0x55, { KEY_CALC } },
+	{KE_KEY, 0x5C, { KEY_SCREENLOCK } },  /* Screenlock */
+	{KE_KEY, 0x5D, { KEY_WLAN } },
+	{KE_KEY, 0x5E, { KEY_WLAN } },
+	{KE_KEY, 0x5F, { KEY_WLAN } },
+	{KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
+	{KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
+	{KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
+	{KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
+	{KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */
+	{KE_KEY, 0x7E, { KEY_BLUETOOTH } },
+	{KE_KEY, 0x7D, { KEY_BLUETOOTH } },
+	{KE_KEY, 0x82, { KEY_CAMERA } },
+	{KE_KEY, 0x88, { KEY_WLAN  } },
+	{KE_KEY, 0x8A, { KEY_PROG1 } },
+	{KE_KEY, 0x95, { KEY_MEDIA } },
+	{KE_KEY, 0x99, { KEY_PHONE } },
+	{KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
+	{KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
 	{KE_END, 0},
 };
 
+
 /*
  * This function evaluates an ACPI method, given an int as parameter, the
  * method is searched within the scope of the handle, can be NULL. The output
@@ -339,8 +288,8 @@
  *
  * returns 0 if write is successful, -1 else.
  */
-static int write_acpi_int(acpi_handle handle, const char *method, int val,
-			  struct acpi_buffer *output)
+static int write_acpi_int_ret(acpi_handle handle, const char *method, int val,
+			      struct acpi_buffer *output)
 {
 	struct acpi_object_list params;	/* list of input parameters (an int) */
 	union acpi_object in_obj;	/* the only param we use */
@@ -361,102 +310,82 @@
 		return -1;
 }
 
-static int read_wireless_status(int mask)
+static int write_acpi_int(acpi_handle handle, const char *method, int val)
 {
-	unsigned long long status;
-	acpi_status rv = AE_OK;
-
-	if (!wireless_status_handle)
-		return (hotk->status & mask) ? 1 : 0;
-
-	rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status);
-	if (ACPI_FAILURE(rv))
-		pr_warning("Error reading Wireless status\n");
-	else
-		return (status & mask) ? 1 : 0;
-
-	return (hotk->status & mask) ? 1 : 0;
+	return write_acpi_int_ret(handle, method, val, NULL);
 }
 
-static int read_gps_status(void)
+static int acpi_check_handle(acpi_handle handle, const char *method,
+			     acpi_handle *ret)
 {
-	unsigned long long status;
-	acpi_status rv = AE_OK;
+	acpi_status status;
 
-	rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status);
-	if (ACPI_FAILURE(rv))
-		pr_warning("Error reading GPS status\n");
-	else
-		return status ? 1 : 0;
+	if (method == NULL)
+		return -ENODEV;
 
-	return (hotk->status & GPS_ON) ? 1 : 0;
-}
+	if (ret)
+		status = acpi_get_handle(handle, (char *)method,
+					 ret);
+	else {
+		acpi_handle dummy;
 
-/* Generic LED functions */
-static int read_status(int mask)
-{
-	/* There is a special method for both wireless devices */
-	if (mask == BT_ON || mask == WL_ON)
-		return read_wireless_status(mask);
-	else if (mask == GPS_ON)
-		return read_gps_status();
-
-	return (hotk->status & mask) ? 1 : 0;
-}
-
-static void write_status(acpi_handle handle, int out, int mask)
-{
-	hotk->status = (out) ? (hotk->status | mask) : (hotk->status & ~mask);
-
-	switch (mask) {
-	case MLED_ON:
-		out = !(out & 0x1);
-		break;
-	case GLED_ON:
-		out = (out & 0x1) + 1;
-		break;
-	case GPS_ON:
-		handle = (out) ? gps_on_handle : gps_off_handle;
-		out = 0x02;
-		break;
-	default:
-		out &= 0x1;
-		break;
+		status = acpi_get_handle(handle, (char *)method,
+					 &dummy);
 	}
 
-	if (write_acpi_int(handle, NULL, out, NULL))
-		pr_warning(" write failed %x\n", mask);
+	if (status != AE_OK) {
+		if (ret)
+			pr_warning("Error finding %s\n", method);
+		return -ENODEV;
+	}
+	return 0;
 }
 
-/* /sys/class/led handlers */
-#define ASUS_LED_HANDLER(object, mask)					\
-	static void object##_led_set(struct led_classdev *led_cdev,	\
-				     enum led_brightness value)		\
-	{								\
-		object##_led_wk = (value > 0) ? 1 : 0;			\
-		queue_work(led_workqueue, &object##_led_work);		\
-	}								\
-	static void object##_led_update(struct work_struct *ignored)	\
-	{								\
-		int value = object##_led_wk;				\
-		write_status(object##_set_handle, value, (mask));	\
-	}								\
-	static enum led_brightness object##_led_get(			\
-		struct led_classdev *led_cdev)				\
-	{								\
-		return led_cdev->brightness;				\
-	}
+/* Generic LED function */
+static int asus_led_set(struct asus_laptop *asus, const char *method,
+			 int value)
+{
+	if (!strcmp(method, METHOD_MLED))
+		value = !value;
+	else if (!strcmp(method, METHOD_GLED))
+		value = !value + 1;
+	else
+		value = !!value;
 
-ASUS_LED_HANDLER(mled, MLED_ON);
-ASUS_LED_HANDLER(pled, PLED_ON);
-ASUS_LED_HANDLER(rled, RLED_ON);
-ASUS_LED_HANDLER(tled, TLED_ON);
-ASUS_LED_HANDLER(gled, GLED_ON);
+	return write_acpi_int(asus->handle, method, value);
+}
 
 /*
- * Keyboard backlight
+ * LEDs
  */
-static int get_kled_lvl(void)
+/* /sys/class/led handlers */
+static void asus_led_cdev_set(struct led_classdev *led_cdev,
+			 enum led_brightness value)
+{
+	struct asus_led *led = container_of(led_cdev, struct asus_led, led);
+	struct asus_laptop *asus = led->asus;
+
+	led->wk = !!value;
+	queue_work(asus->led_workqueue, &led->work);
+}
+
+static void asus_led_cdev_update(struct work_struct *work)
+{
+	struct asus_led *led = container_of(work, struct asus_led, work);
+	struct asus_laptop *asus = led->asus;
+
+	asus_led_set(asus, led->method, led->wk);
+}
+
+static enum led_brightness asus_led_cdev_get(struct led_classdev *led_cdev)
+{
+	return led_cdev->brightness;
+}
+
+/*
+ * Keyboard backlight (also a LED)
+ */
+static int asus_kled_lvl(struct asus_laptop *asus)
 {
 	unsigned long long kblv;
 	struct acpi_object_list params;
@@ -468,75 +397,183 @@
 	in_obj.type = ACPI_TYPE_INTEGER;
 	in_obj.integer.value = 2;
 
-	rv = acpi_evaluate_integer(kled_get_handle, NULL, &params, &kblv);
+	rv = acpi_evaluate_integer(asus->handle, METHOD_KBD_LIGHT_GET,
+				   &params, &kblv);
 	if (ACPI_FAILURE(rv)) {
 		pr_warning("Error reading kled level\n");
-		return 0;
+		return -ENODEV;
 	}
 	return kblv;
 }
 
-static int set_kled_lvl(int kblv)
+static int asus_kled_set(struct asus_laptop *asus, int kblv)
 {
 	if (kblv > 0)
 		kblv = (1 << 7) | (kblv & 0x7F);
 	else
 		kblv = 0;
 
-	if (write_acpi_int(kled_set_handle, NULL, kblv, NULL)) {
+	if (write_acpi_int(asus->handle, METHOD_KBD_LIGHT_SET, kblv)) {
 		pr_warning("Keyboard LED display write failed\n");
 		return -EINVAL;
 	}
 	return 0;
 }
 
-static void kled_led_set(struct led_classdev *led_cdev,
-			 enum led_brightness value)
+static void asus_kled_cdev_set(struct led_classdev *led_cdev,
+			      enum led_brightness value)
 {
-	kled_led_wk = value;
-	queue_work(led_workqueue, &kled_led_work);
+	struct asus_led *led = container_of(led_cdev, struct asus_led, led);
+	struct asus_laptop *asus = led->asus;
+
+	led->wk = value;
+	queue_work(asus->led_workqueue, &led->work);
 }
 
-static void kled_led_update(struct work_struct *ignored)
+static void asus_kled_cdev_update(struct work_struct *work)
 {
-	set_kled_lvl(kled_led_wk);
+	struct asus_led *led = container_of(work, struct asus_led, work);
+	struct asus_laptop *asus = led->asus;
+
+	asus_kled_set(asus, led->wk);
 }
 
-static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
+static enum led_brightness asus_kled_cdev_get(struct led_classdev *led_cdev)
 {
-	return get_kled_lvl();
+	struct asus_led *led = container_of(led_cdev, struct asus_led, led);
+	struct asus_laptop *asus = led->asus;
+
+	return asus_kled_lvl(asus);
 }
 
-static int get_lcd_state(void)
+static void asus_led_exit(struct asus_laptop *asus)
 {
-	return read_status(LCD_ON);
+	if (asus->mled.led.dev)
+		led_classdev_unregister(&asus->mled.led);
+	if (asus->tled.led.dev)
+		led_classdev_unregister(&asus->tled.led);
+	if (asus->pled.led.dev)
+		led_classdev_unregister(&asus->pled.led);
+	if (asus->rled.led.dev)
+		led_classdev_unregister(&asus->rled.led);
+	if (asus->gled.led.dev)
+		led_classdev_unregister(&asus->gled.led);
+	if (asus->kled.led.dev)
+		led_classdev_unregister(&asus->kled.led);
+	if (asus->led_workqueue) {
+		destroy_workqueue(asus->led_workqueue);
+		asus->led_workqueue = NULL;
+	}
 }
 
-static int set_lcd_state(int value)
+/*  Ugly macro, need to fix that later */
+static int asus_led_register(struct asus_laptop *asus,
+			     struct asus_led *led,
+			     const char *name, const char *method)
+{
+	struct led_classdev *led_cdev = &led->led;
+
+	if (!method || acpi_check_handle(asus->handle, method, NULL))
+		return 0; /* Led not present */
+
+	led->asus = asus;
+	led->method = method;
+
+	INIT_WORK(&led->work, asus_led_cdev_update);
+	led_cdev->name = name;
+	led_cdev->brightness_set = asus_led_cdev_set;
+	led_cdev->brightness_get = asus_led_cdev_get;
+	led_cdev->max_brightness = 1;
+	return led_classdev_register(&asus->platform_device->dev, led_cdev);
+}
+
+static int asus_led_init(struct asus_laptop *asus)
+{
+	int r;
+
+	/*
+	 * Functions that actually update the LED's are called from a
+	 * workqueue. By doing this as separate work rather than when the LED
+	 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
+	 * potentially bad time, such as a timer interrupt.
+	 */
+	asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
+	if (!asus->led_workqueue)
+		return -ENOMEM;
+
+	r = asus_led_register(asus, &asus->mled, "asus::mail", METHOD_MLED);
+	if (r)
+		goto error;
+	r = asus_led_register(asus, &asus->tled, "asus::touchpad", METHOD_TLED);
+	if (r)
+		goto error;
+	r = asus_led_register(asus, &asus->rled, "asus::record", METHOD_RLED);
+	if (r)
+		goto error;
+	r = asus_led_register(asus, &asus->pled, "asus::phone", METHOD_PLED);
+	if (r)
+		goto error;
+	r = asus_led_register(asus, &asus->gled, "asus::gaming", METHOD_GLED);
+	if (r)
+		goto error;
+	if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL) &&
+	    !acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_GET, NULL)) {
+		struct asus_led *led = &asus->kled;
+		struct led_classdev *cdev = &led->led;
+
+		led->asus = asus;
+
+		INIT_WORK(&led->work, asus_kled_cdev_update);
+		cdev->name = "asus::kbd_backlight";
+		cdev->brightness_set = asus_kled_cdev_set;
+		cdev->brightness_get = asus_kled_cdev_get;
+		cdev->max_brightness = 3;
+		r = led_classdev_register(&asus->platform_device->dev, cdev);
+	}
+error:
+	if (r)
+		asus_led_exit(asus);
+	return r;
+}
+
+/*
+ * Backlight device
+ */
+static int asus_lcd_status(struct asus_laptop *asus)
+{
+	return asus->lcd_state;
+}
+
+static int asus_lcd_set(struct asus_laptop *asus, int value)
 {
 	int lcd = 0;
 	acpi_status status = 0;
 
-	lcd = value ? 1 : 0;
+	lcd = !!value;
 
-	if (lcd == get_lcd_state())
+	if (lcd == asus_lcd_status(asus))
 		return 0;
 
-	if (lcd_switch_handle) {
-		status = acpi_evaluate_object(lcd_switch_handle,
-					      NULL, NULL, NULL);
+	if (!lcd_switch_handle)
+		return -ENODEV;
 
-		if (ACPI_FAILURE(status))
-			pr_warning("Error switching LCD\n");
+	status = acpi_evaluate_object(lcd_switch_handle,
+				      NULL, NULL, NULL);
+
+	if (ACPI_FAILURE(status)) {
+		pr_warning("Error switching LCD\n");
+		return -ENODEV;
 	}
 
-	write_status(NULL, lcd, LCD_ON);
+	asus->lcd_state = lcd;
 	return 0;
 }
 
-static void lcd_blank(int blank)
+static void lcd_blank(struct asus_laptop *asus, int blank)
 {
-	struct backlight_device *bd = asus_backlight_device;
+	struct backlight_device *bd = asus->backlight_device;
+
+	asus->lcd_state = (blank == FB_BLANK_UNBLANK);
 
 	if (bd) {
 		bd->props.power = blank;
@@ -544,44 +581,91 @@
 	}
 }
 
-static int read_brightness(struct backlight_device *bd)
+static int asus_read_brightness(struct backlight_device *bd)
 {
+	struct asus_laptop *asus = bl_get_data(bd);
 	unsigned long long value;
 	acpi_status rv = AE_OK;
 
-	rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value);
+	rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET,
+				   NULL, &value);
 	if (ACPI_FAILURE(rv))
 		pr_warning("Error reading brightness\n");
 
 	return value;
 }
 
-static int set_brightness(struct backlight_device *bd, int value)
+static int asus_set_brightness(struct backlight_device *bd, int value)
 {
-	int ret = 0;
+	struct asus_laptop *asus = bl_get_data(bd);
 
-	value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
-	/* 0 <= value <= 15 */
-
-	if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) {
+	if (write_acpi_int(asus->handle, METHOD_BRIGHTNESS_SET, value)) {
 		pr_warning("Error changing brightness\n");
-		ret = -EIO;
+		return -EIO;
 	}
-
-	return ret;
+	return 0;
 }
 
 static int update_bl_status(struct backlight_device *bd)
 {
+	struct asus_laptop *asus = bl_get_data(bd);
 	int rv;
 	int value = bd->props.brightness;
 
-	rv = set_brightness(bd, value);
+	rv = asus_set_brightness(bd, value);
 	if (rv)
 		return rv;
 
 	value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
-	return set_lcd_state(value);
+	return asus_lcd_set(asus, value);
+}
+
+static struct backlight_ops asusbl_ops = {
+	.get_brightness = asus_read_brightness,
+	.update_status = update_bl_status,
+};
+
+static int asus_backlight_notify(struct asus_laptop *asus)
+{
+	struct backlight_device *bd = asus->backlight_device;
+	int old = bd->props.brightness;
+
+	backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
+
+	return old;
+}
+
+static int asus_backlight_init(struct asus_laptop *asus)
+{
+	struct backlight_device *bd;
+	struct device *dev = &asus->platform_device->dev;
+
+	if (!acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) &&
+	    !acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) &&
+	    lcd_switch_handle) {
+		bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
+					       asus, &asusbl_ops);
+		if (IS_ERR(bd)) {
+			pr_err("Could not register asus backlight device\n");
+			asus->backlight_device = NULL;
+			return PTR_ERR(bd);
+		}
+
+		asus->backlight_device = bd;
+
+		bd->props.max_brightness = 15;
+		bd->props.power = FB_BLANK_UNBLANK;
+		bd->props.brightness = asus_read_brightness(bd);
+		backlight_update_status(bd);
+	}
+	return 0;
+}
+
+static void asus_backlight_exit(struct asus_laptop *asus)
+{
+	if (asus->backlight_device)
+		backlight_device_unregister(asus->backlight_device);
+	asus->backlight_device = NULL;
 }
 
 /*
@@ -596,25 +680,26 @@
 static ssize_t show_infos(struct device *dev,
 			  struct device_attribute *attr, char *page)
 {
+	struct asus_laptop *asus = dev_get_drvdata(dev);
 	int len = 0;
 	unsigned long long temp;
 	char buf[16];		/* enough for all info */
 	acpi_status rv = AE_OK;
 
 	/*
-	 * We use the easy way, we don't care of off and count, so we don't set eof
-	 * to 1
+	 * We use the easy way, we don't care of off and count,
+	 * so we don't set eof to 1
 	 */
 
-	len += sprintf(page, ASUS_HOTK_NAME " " ASUS_LAPTOP_VERSION "\n");
-	len += sprintf(page + len, "Model reference    : %s\n", hotk->name);
+	len += sprintf(page, ASUS_LAPTOP_NAME " " ASUS_LAPTOP_VERSION "\n");
+	len += sprintf(page + len, "Model reference    : %s\n", asus->name);
 	/*
 	 * The SFUN method probably allows the original driver to get the list
 	 * of features supported by a given model. For now, 0x0100 or 0x0800
 	 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
 	 * The significance of others is yet to be found.
 	 */
-	rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp);
+	rv = acpi_evaluate_integer(asus->handle, "SFUN", NULL, &temp);
 	if (!ACPI_FAILURE(rv))
 		len += sprintf(page + len, "SFUN value         : %#x\n",
 			       (uint) temp);
@@ -624,7 +709,7 @@
 	 * The significance of others is yet to be found.
 	 * If we don't find the method, we assume the device are present.
 	 */
-	rv = acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &temp);
+	rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp);
 	if (!ACPI_FAILURE(rv))
 		len += sprintf(page + len, "HRWS value         : %#x\n",
 			       (uint) temp);
@@ -635,26 +720,26 @@
 	 * Note: since not all the laptops provide this method, errors are
 	 * silently ignored.
 	 */
-	rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp);
+	rv = acpi_evaluate_integer(asus->handle, "ASYM", NULL, &temp);
 	if (!ACPI_FAILURE(rv))
 		len += sprintf(page + len, "ASYM value         : %#x\n",
 			       (uint) temp);
-	if (asus_info) {
-		snprintf(buf, 16, "%d", asus_info->length);
+	if (asus->dsdt_info) {
+		snprintf(buf, 16, "%d", asus->dsdt_info->length);
 		len += sprintf(page + len, "DSDT length        : %s\n", buf);
-		snprintf(buf, 16, "%d", asus_info->checksum);
+		snprintf(buf, 16, "%d", asus->dsdt_info->checksum);
 		len += sprintf(page + len, "DSDT checksum      : %s\n", buf);
-		snprintf(buf, 16, "%d", asus_info->revision);
+		snprintf(buf, 16, "%d", asus->dsdt_info->revision);
 		len += sprintf(page + len, "DSDT revision      : %s\n", buf);
-		snprintf(buf, 7, "%s", asus_info->oem_id);
+		snprintf(buf, 7, "%s", asus->dsdt_info->oem_id);
 		len += sprintf(page + len, "OEM id             : %s\n", buf);
-		snprintf(buf, 9, "%s", asus_info->oem_table_id);
+		snprintf(buf, 9, "%s", asus->dsdt_info->oem_table_id);
 		len += sprintf(page + len, "OEM table id       : %s\n", buf);
-		snprintf(buf, 16, "%x", asus_info->oem_revision);
+		snprintf(buf, 16, "%x", asus->dsdt_info->oem_revision);
 		len += sprintf(page + len, "OEM revision       : 0x%s\n", buf);
-		snprintf(buf, 5, "%s", asus_info->asl_compiler_id);
+		snprintf(buf, 5, "%s", asus->dsdt_info->asl_compiler_id);
 		len += sprintf(page + len, "ASL comp vendor id : %s\n", buf);
-		snprintf(buf, 16, "%x", asus_info->asl_compiler_revision);
+		snprintf(buf, 16, "%x", asus->dsdt_info->asl_compiler_revision);
 		len += sprintf(page + len, "ASL comp revision  : 0x%s\n", buf);
 	}
 
@@ -672,8 +757,9 @@
 	return count;
 }
 
-static ssize_t store_status(const char *buf, size_t count,
-			    acpi_handle handle, int mask)
+static ssize_t sysfs_acpi_set(struct asus_laptop *asus,
+			      const char *buf, size_t count,
+			      const char *method)
 {
 	int rv, value;
 	int out = 0;
@@ -682,8 +768,8 @@
 	if (rv > 0)
 		out = value ? 1 : 0;
 
-	write_status(handle, out, mask);
-
+	if (write_acpi_int(asus->handle, method, value))
+		return -ENODEV;
 	return rv;
 }
 
@@ -693,67 +779,116 @@
 static ssize_t show_ledd(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "0x%08x\n", hotk->ledd_status);
+	struct asus_laptop *asus = dev_get_drvdata(dev);
+
+	return sprintf(buf, "0x%08x\n", asus->ledd_status);
 }
 
 static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count)
 {
+	struct asus_laptop *asus = dev_get_drvdata(dev);
 	int rv, value;
 
 	rv = parse_arg(buf, count, &value);
 	if (rv > 0) {
-		if (write_acpi_int(ledd_set_handle, NULL, value, NULL))
+		if (write_acpi_int(asus->handle, METHOD_LEDD, value))
 			pr_warning("LED display write failed\n");
 		else
-			hotk->ledd_status = (u32) value;
+			asus->ledd_status = (u32) value;
 	}
 	return rv;
 }
 
 /*
+ * Wireless
+ */
+static int asus_wireless_status(struct asus_laptop *asus, int mask)
+{
+	unsigned long long status;
+	acpi_status rv = AE_OK;
+
+	if (!asus->have_rsts)
+		return (asus->wireless_status & mask) ? 1 : 0;
+
+	rv = acpi_evaluate_integer(asus->handle, METHOD_WL_STATUS,
+				   NULL, &status);
+	if (ACPI_FAILURE(rv)) {
+		pr_warning("Error reading Wireless status\n");
+		return -EINVAL;
+	}
+	return !!(status & mask);
+}
+
+/*
  * WLAN
  */
+static int asus_wlan_set(struct asus_laptop *asus, int status)
+{
+	if (write_acpi_int(asus->handle, METHOD_WLAN, !!status)) {
+		pr_warning("Error setting wlan status to %d", status);
+		return -EIO;
+	}
+	return 0;
+}
+
 static ssize_t show_wlan(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", read_status(WL_ON));
+	struct asus_laptop *asus = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", asus_wireless_status(asus, WL_RSTS));
 }
 
 static ssize_t store_wlan(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count)
 {
-	return store_status(buf, count, wl_switch_handle, WL_ON);
+	struct asus_laptop *asus = dev_get_drvdata(dev);
+
+	return sysfs_acpi_set(asus, buf, count, METHOD_WLAN);
 }
 
 /*
  * Bluetooth
  */
+static int asus_bluetooth_set(struct asus_laptop *asus, int status)
+{
+	if (write_acpi_int(asus->handle, METHOD_BLUETOOTH, !!status)) {
+		pr_warning("Error setting bluetooth status to %d", status);
+		return -EIO;
+	}
+	return 0;
+}
+
 static ssize_t show_bluetooth(struct device *dev,
 			      struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", read_status(BT_ON));
+	struct asus_laptop *asus = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", asus_wireless_status(asus, BT_RSTS));
 }
 
 static ssize_t store_bluetooth(struct device *dev,
 			       struct device_attribute *attr, const char *buf,
 			       size_t count)
 {
-	return store_status(buf, count, bt_switch_handle, BT_ON);
+	struct asus_laptop *asus = dev_get_drvdata(dev);
+
+	return sysfs_acpi_set(asus, buf, count, METHOD_BLUETOOTH);
 }
 
 /*
  * Display
  */
-static void set_display(int value)
+static void asus_set_display(struct asus_laptop *asus, int value)
 {
 	/* no sanity check needed for now */
-	if (write_acpi_int(display_set_handle, NULL, value, NULL))
+	if (write_acpi_int(asus->handle, METHOD_SWITCH_DISPLAY, value))
 		pr_warning("Error setting display\n");
 	return;
 }
 
-static int read_display(void)
+static int read_display(struct asus_laptop *asus)
 {
 	unsigned long long value = 0;
 	acpi_status rv = AE_OK;
@@ -769,7 +904,7 @@
 			pr_warning("Error reading display status\n");
 	}
 
-	value &= 0x0F;		/* needed for some models, shouldn't hurt others */
+	value &= 0x0F; /* needed for some models, shouldn't hurt others */
 
 	return value;
 }
@@ -781,7 +916,11 @@
 static ssize_t show_disp(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", read_display());
+	struct asus_laptop *asus = dev_get_drvdata(dev);
+
+	if (!display_get_handle)
+		return -ENODEV;
+	return sprintf(buf, "%d\n", read_display(asus));
 }
 
 /*
@@ -794,65 +933,72 @@
 static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count)
 {
+	struct asus_laptop *asus = dev_get_drvdata(dev);
 	int rv, value;
 
 	rv = parse_arg(buf, count, &value);
 	if (rv > 0)
-		set_display(value);
+		asus_set_display(asus, value);
 	return rv;
 }
 
 /*
  * Light Sens
  */
-static void set_light_sens_switch(int value)
+static void asus_als_switch(struct asus_laptop *asus, int value)
 {
-	if (write_acpi_int(ls_switch_handle, NULL, value, NULL))
+	if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value))
 		pr_warning("Error setting light sensor switch\n");
-	hotk->light_switch = value;
+	asus->light_switch = value;
 }
 
 static ssize_t show_lssw(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", hotk->light_switch);
+	struct asus_laptop *asus = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", asus->light_switch);
 }
 
 static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count)
 {
+	struct asus_laptop *asus = dev_get_drvdata(dev);
 	int rv, value;
 
 	rv = parse_arg(buf, count, &value);
 	if (rv > 0)
-		set_light_sens_switch(value ? 1 : 0);
+		asus_als_switch(asus, value ? 1 : 0);
 
 	return rv;
 }
 
-static void set_light_sens_level(int value)
+static void asus_als_level(struct asus_laptop *asus, int value)
 {
-	if (write_acpi_int(ls_level_handle, NULL, value, NULL))
+	if (write_acpi_int(asus->handle, METHOD_ALS_LEVEL, value))
 		pr_warning("Error setting light sensor level\n");
-	hotk->light_level = value;
+	asus->light_level = value;
 }
 
 static ssize_t show_lslvl(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", hotk->light_level);
+	struct asus_laptop *asus = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", asus->light_level);
 }
 
 static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
+	struct asus_laptop *asus = dev_get_drvdata(dev);
 	int rv, value;
 
 	rv = parse_arg(buf, count, &value);
 	if (rv > 0) {
 		value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
 		/* 0 <= value <= 15 */
-		set_light_sens_level(value);
+		asus_als_level(asus, value);
 	}
 
 	return rv;
@@ -861,197 +1007,309 @@
 /*
  * GPS
  */
+static int asus_gps_status(struct asus_laptop *asus)
+{
+	unsigned long long status;
+	acpi_status rv = AE_OK;
+
+	rv = acpi_evaluate_integer(asus->handle, METHOD_GPS_STATUS,
+				   NULL, &status);
+	if (ACPI_FAILURE(rv)) {
+		pr_warning("Error reading GPS status\n");
+		return -ENODEV;
+	}
+	return !!status;
+}
+
+static int asus_gps_switch(struct asus_laptop *asus, int status)
+{
+	const char *meth = status ? METHOD_GPS_ON : METHOD_GPS_OFF;
+
+	if (write_acpi_int(asus->handle, meth, 0x02))
+		return -ENODEV;
+	return 0;
+}
+
 static ssize_t show_gps(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", read_status(GPS_ON));
+	struct asus_laptop *asus = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", asus_gps_status(asus));
 }
 
 static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
 			 const char *buf, size_t count)
 {
-	return store_status(buf, count, NULL, GPS_ON);
+	struct asus_laptop *asus = dev_get_drvdata(dev);
+	int rv, value;
+	int ret;
+
+	rv = parse_arg(buf, count, &value);
+	if (rv <= 0)
+		return -EINVAL;
+	ret = asus_gps_switch(asus, !!value);
+	if (ret)
+		return ret;
+	rfkill_set_sw_state(asus->gps_rfkill, !value);
+	return rv;
 }
 
 /*
- * Hotkey functions
+ * rfkill
  */
-static struct key_entry *asus_get_entry_by_scancode(int code)
+static int asus_gps_rfkill_set(void *data, bool blocked)
 {
-	struct key_entry *key;
+	acpi_handle handle = data;
 
-	for (key = asus_keymap; key->type != KE_END; key++)
-		if (code == key->code)
-			return key;
-
-	return NULL;
+	return asus_gps_switch(handle, !blocked);
 }
 
-static struct key_entry *asus_get_entry_by_keycode(int code)
+static const struct rfkill_ops asus_gps_rfkill_ops = {
+	.set_block = asus_gps_rfkill_set,
+};
+
+static void asus_rfkill_exit(struct asus_laptop *asus)
 {
-	struct key_entry *key;
-
-	for (key = asus_keymap; key->type != KE_END; key++)
-		if (code == key->keycode && key->type == KE_KEY)
-			return key;
-
-	return NULL;
-}
-
-static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)
-{
-	struct key_entry *key = asus_get_entry_by_scancode(scancode);
-
-	if (key && key->type == KE_KEY) {
-		*keycode = key->keycode;
-		return 0;
+	if (asus->gps_rfkill) {
+		rfkill_unregister(asus->gps_rfkill);
+		rfkill_destroy(asus->gps_rfkill);
+		asus->gps_rfkill = NULL;
 	}
-
-	return -EINVAL;
 }
 
-static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
+static int asus_rfkill_init(struct asus_laptop *asus)
 {
-	struct key_entry *key;
-	int old_keycode;
+	int result;
 
-	if (keycode < 0 || keycode > KEY_MAX)
+	if (acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) ||
+	    acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) ||
+	    acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL))
+		return 0;
+
+	asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev,
+					RFKILL_TYPE_GPS,
+					&asus_gps_rfkill_ops, NULL);
+	if (!asus->gps_rfkill)
 		return -EINVAL;
 
-	key = asus_get_entry_by_scancode(scancode);
-	if (key && key->type == KE_KEY) {
-		old_keycode = key->keycode;
-		key->keycode = keycode;
-		set_bit(keycode, dev->keybit);
-		if (!asus_get_entry_by_keycode(old_keycode))
-			clear_bit(old_keycode, dev->keybit);
-		return 0;
+	result = rfkill_register(asus->gps_rfkill);
+	if (result) {
+		rfkill_destroy(asus->gps_rfkill);
+		asus->gps_rfkill = NULL;
 	}
 
-	return -EINVAL;
+	return result;
 }
 
-static void asus_hotk_notify(struct acpi_device *device, u32 event)
+/*
+ * Input device (i.e. hotkeys)
+ */
+static void asus_input_notify(struct asus_laptop *asus, int event)
 {
-	static struct key_entry *key;
-	u16 count;
+	if (asus->inputdev)
+		sparse_keymap_report_event(asus->inputdev, event, 1, true);
+}
 
-	/* TODO Find a better way to handle events count. */
-	if (!hotk)
-		return;
+static int asus_input_init(struct asus_laptop *asus)
+{
+	struct input_dev *input;
+	int error;
+
+	input = input_allocate_device();
+	if (!input) {
+		pr_info("Unable to allocate input device\n");
+		return 0;
+	}
+	input->name = "Asus Laptop extra buttons";
+	input->phys = ASUS_LAPTOP_FILE "/input0";
+	input->id.bustype = BUS_HOST;
+	input->dev.parent = &asus->platform_device->dev;
+	input_set_drvdata(input, asus);
+
+	error = sparse_keymap_setup(input, asus_keymap, NULL);
+	if (error) {
+		pr_err("Unable to setup input device keymap\n");
+		goto err_keymap;
+	}
+	error = input_register_device(input);
+	if (error) {
+		pr_info("Unable to register input device\n");
+		goto err_device;
+	}
+
+	asus->inputdev = input;
+	return 0;
+
+err_keymap:
+	sparse_keymap_free(input);
+err_device:
+	input_free_device(input);
+	return error;
+}
+
+static void asus_input_exit(struct asus_laptop *asus)
+{
+	if (asus->inputdev) {
+		sparse_keymap_free(asus->inputdev);
+		input_unregister_device(asus->inputdev);
+	}
+}
+
+/*
+ * ACPI driver
+ */
+static void asus_acpi_notify(struct acpi_device *device, u32 event)
+{
+	struct asus_laptop *asus = acpi_driver_data(device);
+	u16 count;
 
 	/*
 	 * We need to tell the backlight device when the backlight power is
 	 * switched
 	 */
-	if (event == ATKD_LCD_ON) {
-		write_status(NULL, 1, LCD_ON);
-		lcd_blank(FB_BLANK_UNBLANK);
-	} else if (event == ATKD_LCD_OFF) {
-		write_status(NULL, 0, LCD_ON);
-		lcd_blank(FB_BLANK_POWERDOWN);
-	}
+	if (event == ATKD_LCD_ON)
+		lcd_blank(asus, FB_BLANK_UNBLANK);
+	else if (event == ATKD_LCD_OFF)
+		lcd_blank(asus, FB_BLANK_POWERDOWN);
 
-	count = hotk->event_count[event % 128]++;
-	acpi_bus_generate_proc_event(hotk->device, event, count);
-	acpi_bus_generate_netlink_event(hotk->device->pnp.device_class,
-					dev_name(&hotk->device->dev), event,
+	/* TODO Find a better way to handle events count. */
+	count = asus->event_count[event % 128]++;
+	acpi_bus_generate_proc_event(asus->device, event, count);
+	acpi_bus_generate_netlink_event(asus->device->pnp.device_class,
+					dev_name(&asus->device->dev), event,
 					count);
 
-	if (hotk->inputdev) {
-		key = asus_get_entry_by_scancode(event);
-		if (!key)
-			return ;
+	/* Brightness events are special */
+	if (event >= ATKD_BR_MIN && event <= ATKD_BR_MAX) {
 
-		switch (key->type) {
-		case KE_KEY:
-			input_report_key(hotk->inputdev, key->keycode, 1);
-			input_sync(hotk->inputdev);
-			input_report_key(hotk->inputdev, key->keycode, 0);
-			input_sync(hotk->inputdev);
-			break;
+		/* Ignore them completely if the acpi video driver is used */
+		if (asus->backlight_device != NULL) {
+			/* Update the backlight device. */
+			asus_backlight_notify(asus);
 		}
+		return ;
 	}
+	asus_input_notify(asus, event);
 }
 
-#define ASUS_CREATE_DEVICE_ATTR(_name)					\
-	struct device_attribute dev_attr_##_name = {			\
-		.attr = {						\
-			.name = __stringify(_name),			\
-			.mode = 0 },					\
-		.show   = NULL,						\
-		.store  = NULL,						\
-	}
+static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
+static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
+static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth,
+		   store_bluetooth);
+static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
+static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
+static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
+static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
+static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
 
-#define ASUS_SET_DEVICE_ATTR(_name, _mode, _show, _store)		\
-	do {								\
-		dev_attr_##_name.attr.mode = _mode;			\
-		dev_attr_##_name.show = _show;				\
-		dev_attr_##_name.store = _store;			\
-	} while(0)
-
-static ASUS_CREATE_DEVICE_ATTR(infos);
-static ASUS_CREATE_DEVICE_ATTR(wlan);
-static ASUS_CREATE_DEVICE_ATTR(bluetooth);
-static ASUS_CREATE_DEVICE_ATTR(display);
-static ASUS_CREATE_DEVICE_ATTR(ledd);
-static ASUS_CREATE_DEVICE_ATTR(ls_switch);
-static ASUS_CREATE_DEVICE_ATTR(ls_level);
-static ASUS_CREATE_DEVICE_ATTR(gps);
-
-static struct attribute *asuspf_attributes[] = {
-	&dev_attr_infos.attr,
-	&dev_attr_wlan.attr,
-	&dev_attr_bluetooth.attr,
-	&dev_attr_display.attr,
-	&dev_attr_ledd.attr,
-	&dev_attr_ls_switch.attr,
-	&dev_attr_ls_level.attr,
-	&dev_attr_gps.attr,
-	NULL
-};
-
-static struct attribute_group asuspf_attribute_group = {
-	.attrs = asuspf_attributes
-};
-
-static struct platform_driver asuspf_driver = {
-	.driver = {
-		   .name = ASUS_HOTK_FILE,
-		   .owner = THIS_MODULE,
-		   }
-};
-
-static struct platform_device *asuspf_device;
-
-static void asus_hotk_add_fs(void)
+static void asus_sysfs_exit(struct asus_laptop *asus)
 {
-	ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL);
+	struct platform_device *device = asus->platform_device;
 
-	if (wl_switch_handle)
-		ASUS_SET_DEVICE_ATTR(wlan, 0644, show_wlan, store_wlan);
+	device_remove_file(&device->dev, &dev_attr_infos);
+	device_remove_file(&device->dev, &dev_attr_wlan);
+	device_remove_file(&device->dev, &dev_attr_bluetooth);
+	device_remove_file(&device->dev, &dev_attr_display);
+	device_remove_file(&device->dev, &dev_attr_ledd);
+	device_remove_file(&device->dev, &dev_attr_ls_switch);
+	device_remove_file(&device->dev, &dev_attr_ls_level);
+	device_remove_file(&device->dev, &dev_attr_gps);
+}
 
-	if (bt_switch_handle)
-		ASUS_SET_DEVICE_ATTR(bluetooth, 0644,
-				     show_bluetooth, store_bluetooth);
+static int asus_sysfs_init(struct asus_laptop *asus)
+{
+	struct platform_device *device = asus->platform_device;
+	int err;
 
-	if (display_set_handle && display_get_handle)
-		ASUS_SET_DEVICE_ATTR(display, 0644, show_disp, store_disp);
-	else if (display_set_handle)
-		ASUS_SET_DEVICE_ATTR(display, 0200, NULL, store_disp);
+	err = device_create_file(&device->dev, &dev_attr_infos);
+	if (err)
+		return err;
 
-	if (ledd_set_handle)
-		ASUS_SET_DEVICE_ATTR(ledd, 0644, show_ledd, store_ledd);
-
-	if (ls_switch_handle && ls_level_handle) {
-		ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl);
-		ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw);
+	if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) {
+		err = device_create_file(&device->dev, &dev_attr_wlan);
+		if (err)
+			return err;
 	}
 
-	if (gps_status_handle && gps_on_handle && gps_off_handle)
-		ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps);
+	if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) {
+		err = device_create_file(&device->dev, &dev_attr_bluetooth);
+		if (err)
+			return err;
+	}
+
+	if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) {
+		err = device_create_file(&device->dev, &dev_attr_display);
+		if (err)
+			return err;
+	}
+
+	if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) {
+		err = device_create_file(&device->dev, &dev_attr_ledd);
+		if (err)
+			return err;
+	}
+
+	if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
+	    !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
+		err = device_create_file(&device->dev, &dev_attr_ls_switch);
+		if (err)
+			return err;
+		err = device_create_file(&device->dev, &dev_attr_ls_level);
+		if (err)
+			return err;
+	}
+
+	if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) &&
+	    !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) &&
+	    !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) {
+		err = device_create_file(&device->dev, &dev_attr_gps);
+		if (err)
+			return err;
+	}
+
+	return err;
 }
 
+static int asus_platform_init(struct asus_laptop *asus)
+{
+	int err;
+
+	asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1);
+	if (!asus->platform_device)
+		return -ENOMEM;
+	platform_set_drvdata(asus->platform_device, asus);
+
+	err = platform_device_add(asus->platform_device);
+	if (err)
+		goto fail_platform_device;
+
+	err = asus_sysfs_init(asus);
+	if (err)
+		goto fail_sysfs;
+	return 0;
+
+fail_sysfs:
+	asus_sysfs_exit(asus);
+	platform_device_del(asus->platform_device);
+fail_platform_device:
+	platform_device_put(asus->platform_device);
+	return err;
+}
+
+static void asus_platform_exit(struct asus_laptop *asus)
+{
+	asus_sysfs_exit(asus);
+	platform_device_unregister(asus->platform_device);
+}
+
+static struct platform_driver platform_driver = {
+	.driver = {
+		.name = ASUS_LAPTOP_FILE,
+		.owner = THIS_MODULE,
+	}
+};
+
 static int asus_handle_init(char *name, acpi_handle * handle,
 			    char **paths, int num_paths)
 {
@@ -1073,10 +1331,11 @@
 			 ARRAY_SIZE(object##_paths))
 
 /*
- * This function is used to initialize the hotk with right values. In this
- * method, we can make all the detection we want, and modify the hotk struct
+ * This function is used to initialize the context with right values. In this
+ * method, we can make all the detection we want, and modify the asus_laptop
+ * struct
  */
-static int asus_hotk_get_info(void)
+static int asus_laptop_get_info(struct asus_laptop *asus)
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *model = NULL;
@@ -1089,22 +1348,21 @@
 	 * models, but late enough to allow acpi_bus_register_driver() to fail
 	 * before doing anything ACPI-specific. Should we encounter a machine,
 	 * which needs special handling (i.e. its hotkey device has a different
-	 * HID), this bit will be moved. A global variable asus_info contains
-	 * the DSDT header.
+	 * HID), this bit will be moved.
 	 */
-	status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info);
+	status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info);
 	if (ACPI_FAILURE(status))
 		pr_warning("Couldn't get the DSDT table header\n");
 
 	/* We have to write 0 on init this far for all ASUS models */
-	if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
+	if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) {
 		pr_err("Hotkey initialization failed\n");
 		return -ENODEV;
 	}
 
 	/* This needs to be called for some laptops to init properly */
 	status =
-	    acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result);
+	    acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result);
 	if (ACPI_FAILURE(status))
 		pr_warning("Error calling BSTS\n");
 	else if (bsts_result)
@@ -1112,8 +1370,8 @@
 		       (uint) bsts_result);
 
 	/* This too ... */
-	write_acpi_int(hotk->handle, "CWAP", wapf, NULL);
-
+	if (write_acpi_int(asus->handle, "CWAP", wapf))
+		pr_err("Error calling CWAP(%d)\n", wapf);
 	/*
 	 * Try to match the object returned by INIT to the specific model.
 	 * Handle every possible object (or the lack of thereof) the DSDT
@@ -1134,397 +1392,210 @@
 			break;
 		}
 	}
-	hotk->name = kstrdup(string, GFP_KERNEL);
-	if (!hotk->name)
+	asus->name = kstrdup(string, GFP_KERNEL);
+	if (!asus->name)
 		return -ENOMEM;
 
 	if (*string)
 		pr_notice("  %s model detected\n", string);
 
-	ASUS_HANDLE_INIT(mled_set);
-	ASUS_HANDLE_INIT(tled_set);
-	ASUS_HANDLE_INIT(rled_set);
-	ASUS_HANDLE_INIT(pled_set);
-	ASUS_HANDLE_INIT(gled_set);
-
-	ASUS_HANDLE_INIT(ledd_set);
-
-	ASUS_HANDLE_INIT(kled_set);
-	ASUS_HANDLE_INIT(kled_get);
-
 	/*
 	 * The HWRS method return informations about the hardware.
 	 * 0x80 bit is for WLAN, 0x100 for Bluetooth.
 	 * The significance of others is yet to be found.
-	 * If we don't find the method, we assume the device are present.
 	 */
 	status =
-	    acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &hwrs_result);
-	if (ACPI_FAILURE(status))
-		hwrs_result = WL_HWRS | BT_HWRS;
+	    acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result);
+	if (!ACPI_FAILURE(status))
+		pr_notice("  HRWS returned %x", (int)hwrs_result);
 
-	if (hwrs_result & WL_HWRS)
-		ASUS_HANDLE_INIT(wl_switch);
-	if (hwrs_result & BT_HWRS)
-		ASUS_HANDLE_INIT(bt_switch);
+	if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
+		asus->have_rsts = true;
 
-	ASUS_HANDLE_INIT(wireless_status);
-
-	ASUS_HANDLE_INIT(brightness_set);
-	ASUS_HANDLE_INIT(brightness_get);
-
+	/* Scheduled for removal */
 	ASUS_HANDLE_INIT(lcd_switch);
-
-	ASUS_HANDLE_INIT(display_set);
 	ASUS_HANDLE_INIT(display_get);
 
-	/*
-	 * There is a lot of models with "ALSL", but a few get
-	 * a real light sens, so we need to check it.
-	 */
-	if (!ASUS_HANDLE_INIT(ls_switch))
-		ASUS_HANDLE_INIT(ls_level);
-
-	ASUS_HANDLE_INIT(gps_on);
-	ASUS_HANDLE_INIT(gps_off);
-	ASUS_HANDLE_INIT(gps_status);
-
 	kfree(model);
 
 	return AE_OK;
 }
 
-static int asus_input_init(void)
-{
-	const struct key_entry *key;
-	int result;
+static bool asus_device_present;
 
-	hotk->inputdev = input_allocate_device();
-	if (!hotk->inputdev) {
-		pr_info("Unable to allocate input device\n");
-		return 0;
-	}
-	hotk->inputdev->name = "Asus Laptop extra buttons";
-	hotk->inputdev->phys = ASUS_HOTK_FILE "/input0";
-	hotk->inputdev->id.bustype = BUS_HOST;
-	hotk->inputdev->getkeycode = asus_getkeycode;
-	hotk->inputdev->setkeycode = asus_setkeycode;
-
-	for (key = asus_keymap; key->type != KE_END; key++) {
-		switch (key->type) {
-		case KE_KEY:
-			set_bit(EV_KEY, hotk->inputdev->evbit);
-			set_bit(key->keycode, hotk->inputdev->keybit);
-			break;
-		}
-	}
-	result = input_register_device(hotk->inputdev);
-	if (result) {
-		pr_info("Unable to register input device\n");
-		input_free_device(hotk->inputdev);
-	}
-	return result;
-}
-
-static int asus_hotk_check(void)
+static int __devinit asus_acpi_init(struct asus_laptop *asus)
 {
 	int result = 0;
 
-	result = acpi_bus_get_status(hotk->device);
+	result = acpi_bus_get_status(asus->device);
+	if (result)
+		return result;
+	if (!asus->device->status.present) {
+		pr_err("Hotkey device not present, aborting\n");
+		return -ENODEV;
+	}
+
+	result = asus_laptop_get_info(asus);
 	if (result)
 		return result;
 
-	if (hotk->device->status.present) {
-		result = asus_hotk_get_info();
-	} else {
-		pr_err("Hotkey device not present, aborting\n");
-		return -EINVAL;
+	/* WLED and BLED are on by default */
+	if (bluetooth_status >= 0)
+		asus_bluetooth_set(asus, !!bluetooth_status);
+
+	if (wlan_status >= 0)
+		asus_wlan_set(asus, !!wlan_status);
+
+	/* Keyboard Backlight is on by default */
+	if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
+		asus_kled_set(asus, 1);
+
+	/* LED display is off by default */
+	asus->ledd_status = 0xFFF;
+
+	/* Set initial values of light sensor and level */
+	asus->light_switch = 0;	/* Default to light sensor disabled */
+	asus->light_level = 5;	/* level 5 for sensor sensitivity */
+
+	if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
+	    !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
+		asus_als_switch(asus, asus->light_switch);
+		asus_als_level(asus, asus->light_level);
 	}
 
+	asus->lcd_state = 1; /* LCD should be on when the module load */
 	return result;
 }
 
-static int asus_hotk_found;
-
-static int asus_hotk_add(struct acpi_device *device)
+static int __devinit asus_acpi_add(struct acpi_device *device)
 {
+	struct asus_laptop *asus;
 	int result;
 
 	pr_notice("Asus Laptop Support version %s\n",
-	       ASUS_LAPTOP_VERSION);
-
-	hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
-	if (!hotk)
+		  ASUS_LAPTOP_VERSION);
+	asus = kzalloc(sizeof(struct asus_laptop), GFP_KERNEL);
+	if (!asus)
 		return -ENOMEM;
+	asus->handle = device->handle;
+	strcpy(acpi_device_name(device), ASUS_LAPTOP_DEVICE_NAME);
+	strcpy(acpi_device_class(device), ASUS_LAPTOP_CLASS);
+	device->driver_data = asus;
+	asus->device = device;
 
-	hotk->handle = device->handle;
-	strcpy(acpi_device_name(device), ASUS_HOTK_DEVICE_NAME);
-	strcpy(acpi_device_class(device), ASUS_HOTK_CLASS);
-	device->driver_data = hotk;
-	hotk->device = device;
-
-	result = asus_hotk_check();
+	result = asus_acpi_init(asus);
 	if (result)
-		goto end;
+		goto fail_platform;
 
-	asus_hotk_add_fs();
+	/*
+	 * Register the platform device first.  It is used as a parent for the
+	 * sub-devices below.
+	 */
+	result = asus_platform_init(asus);
+	if (result)
+		goto fail_platform;
 
-	asus_hotk_found = 1;
+	if (!acpi_video_backlight_support()) {
+		result = asus_backlight_init(asus);
+		if (result)
+			goto fail_backlight;
+	} else
+		pr_info("Backlight controlled by ACPI video driver\n");
 
-	/* WLED and BLED are on by default */
-	write_status(bt_switch_handle, 1, BT_ON);
-	write_status(wl_switch_handle, 1, WL_ON);
+	result = asus_input_init(asus);
+	if (result)
+		goto fail_input;
 
-	/* If the h/w switch is off, we need to check the real status */
-	write_status(NULL, read_status(BT_ON), BT_ON);
-	write_status(NULL, read_status(WL_ON), WL_ON);
+	result = asus_led_init(asus);
+	if (result)
+		goto fail_led;
 
-	/* LCD Backlight is on by default */
-	write_status(NULL, 1, LCD_ON);
+	result = asus_rfkill_init(asus);
+	if (result)
+		goto fail_rfkill;
 
-	/* Keyboard Backlight is on by default */
-	if (kled_set_handle)
-		set_kled_lvl(1);
+	asus_device_present = true;
+	return 0;
 
-	/* LED display is off by default */
-	hotk->ledd_status = 0xFFF;
-
-	/* Set initial values of light sensor and level */
-	hotk->light_switch = 0;	/* Default to light sensor disabled */
-	hotk->light_level = 5;	/* level 5 for sensor sensitivity */
-
-	if (ls_switch_handle)
-		set_light_sens_switch(hotk->light_switch);
-
-	if (ls_level_handle)
-		set_light_sens_level(hotk->light_level);
-
-	/* GPS is on by default */
-	write_status(NULL, 1, GPS_ON);
-
-end:
-	if (result) {
-		kfree(hotk->name);
-		kfree(hotk);
-	}
+fail_rfkill:
+	asus_led_exit(asus);
+fail_led:
+	asus_input_exit(asus);
+fail_input:
+	asus_backlight_exit(asus);
+fail_backlight:
+	asus_platform_exit(asus);
+fail_platform:
+	kfree(asus->name);
+	kfree(asus);
 
 	return result;
 }
 
-static int asus_hotk_remove(struct acpi_device *device, int type)
+static int asus_acpi_remove(struct acpi_device *device, int type)
 {
-	kfree(hotk->name);
-	kfree(hotk);
+	struct asus_laptop *asus = acpi_driver_data(device);
 
+	asus_backlight_exit(asus);
+	asus_rfkill_exit(asus);
+	asus_led_exit(asus);
+	asus_input_exit(asus);
+	asus_platform_exit(asus);
+
+	kfree(asus->name);
+	kfree(asus);
 	return 0;
 }
 
-static void asus_backlight_exit(void)
-{
-	if (asus_backlight_device)
-		backlight_device_unregister(asus_backlight_device);
-}
+static const struct acpi_device_id asus_device_ids[] = {
+	{"ATK0100", 0},
+	{"ATK0101", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, asus_device_ids);
 
-#define  ASUS_LED_UNREGISTER(object)				\
-	if (object##_led.dev)					\
-		led_classdev_unregister(&object##_led)
-
-static void asus_led_exit(void)
-{
-	destroy_workqueue(led_workqueue);
-	ASUS_LED_UNREGISTER(mled);
-	ASUS_LED_UNREGISTER(tled);
-	ASUS_LED_UNREGISTER(pled);
-	ASUS_LED_UNREGISTER(rled);
-	ASUS_LED_UNREGISTER(gled);
-	ASUS_LED_UNREGISTER(kled);
-}
-
-static void asus_input_exit(void)
-{
-	if (hotk->inputdev)
-		input_unregister_device(hotk->inputdev);
-}
-
-static void __exit asus_laptop_exit(void)
-{
-	asus_backlight_exit();
-	asus_led_exit();
-	asus_input_exit();
-
-	acpi_bus_unregister_driver(&asus_hotk_driver);
-	sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
-	platform_device_unregister(asuspf_device);
-	platform_driver_unregister(&asuspf_driver);
-}
-
-static int asus_backlight_init(struct device *dev)
-{
-	struct backlight_device *bd;
-
-	if (brightness_set_handle && lcd_switch_handle) {
-		bd = backlight_device_register(ASUS_HOTK_FILE, dev,
-					       NULL, &asusbl_ops);
-		if (IS_ERR(bd)) {
-			pr_err("Could not register asus backlight device\n");
-			asus_backlight_device = NULL;
-			return PTR_ERR(bd);
-		}
-
-		asus_backlight_device = bd;
-
-		bd->props.max_brightness = 15;
-		bd->props.brightness = read_brightness(NULL);
-		bd->props.power = FB_BLANK_UNBLANK;
-		backlight_update_status(bd);
-	}
-	return 0;
-}
-
-static int asus_led_register(acpi_handle handle,
-			     struct led_classdev *ldev, struct device *dev)
-{
-	if (!handle)
-		return 0;
-
-	return led_classdev_register(dev, ldev);
-}
-
-#define ASUS_LED_REGISTER(object, device)				\
-	asus_led_register(object##_set_handle, &object##_led, device)
-
-static int asus_led_init(struct device *dev)
-{
-	int rv;
-
-	rv = ASUS_LED_REGISTER(mled, dev);
-	if (rv)
-		goto out;
-
-	rv = ASUS_LED_REGISTER(tled, dev);
-	if (rv)
-		goto out1;
-
-	rv = ASUS_LED_REGISTER(rled, dev);
-	if (rv)
-		goto out2;
-
-	rv = ASUS_LED_REGISTER(pled, dev);
-	if (rv)
-		goto out3;
-
-	rv = ASUS_LED_REGISTER(gled, dev);
-	if (rv)
-		goto out4;
-
-	if (kled_set_handle && kled_get_handle)
-		rv = ASUS_LED_REGISTER(kled, dev);
-	if (rv)
-		goto out5;
-
-	led_workqueue = create_singlethread_workqueue("led_workqueue");
-	if (!led_workqueue)
-		goto out6;
-
-	return 0;
-out6:
-	rv = -ENOMEM;
-	ASUS_LED_UNREGISTER(kled);
-out5:
-	ASUS_LED_UNREGISTER(gled);
-out4:
-	ASUS_LED_UNREGISTER(pled);
-out3:
-	ASUS_LED_UNREGISTER(rled);
-out2:
-	ASUS_LED_UNREGISTER(tled);
-out1:
-	ASUS_LED_UNREGISTER(mled);
-out:
-	return rv;
-}
+static struct acpi_driver asus_acpi_driver = {
+	.name = ASUS_LAPTOP_NAME,
+	.class = ASUS_LAPTOP_CLASS,
+	.owner = THIS_MODULE,
+	.ids = asus_device_ids,
+	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
+	.ops = {
+		.add = asus_acpi_add,
+		.remove = asus_acpi_remove,
+		.notify = asus_acpi_notify,
+		},
+};
 
 static int __init asus_laptop_init(void)
 {
 	int result;
 
-	result = acpi_bus_register_driver(&asus_hotk_driver);
+	result = platform_driver_register(&platform_driver);
 	if (result < 0)
 		return result;
 
-	/*
-	 * This is a bit of a kludge.  We only want this module loaded
-	 * for ASUS systems, but there's currently no way to probe the
-	 * ACPI namespace for ASUS HIDs.  So we just return failure if
-	 * we didn't find one, which will cause the module to be
-	 * unloaded.
-	 */
-	if (!asus_hotk_found) {
-		acpi_bus_unregister_driver(&asus_hotk_driver);
-		return -ENODEV;
+	result = acpi_bus_register_driver(&asus_acpi_driver);
+	if (result < 0)
+		goto fail_acpi_driver;
+	if (!asus_device_present) {
+		result = -ENODEV;
+		goto fail_no_device;
 	}
-
-	result = asus_input_init();
-	if (result)
-		goto fail_input;
-
-	/* Register platform stuff */
-	result = platform_driver_register(&asuspf_driver);
-	if (result)
-		goto fail_platform_driver;
-
-	asuspf_device = platform_device_alloc(ASUS_HOTK_FILE, -1);
-	if (!asuspf_device) {
-		result = -ENOMEM;
-		goto fail_platform_device1;
-	}
-
-	result = platform_device_add(asuspf_device);
-	if (result)
-		goto fail_platform_device2;
-
-	result = sysfs_create_group(&asuspf_device->dev.kobj,
-				    &asuspf_attribute_group);
-	if (result)
-		goto fail_sysfs;
-
-	result = asus_led_init(&asuspf_device->dev);
-	if (result)
-		goto fail_led;
-
-	if (!acpi_video_backlight_support()) {
-		result = asus_backlight_init(&asuspf_device->dev);
-		if (result)
-			goto fail_backlight;
-	} else
-		pr_info("Brightness ignored, must be controlled by "
-		       "ACPI video driver\n");
-
 	return 0;
 
-fail_backlight:
-       asus_led_exit();
-
-fail_led:
-       sysfs_remove_group(&asuspf_device->dev.kobj,
-			  &asuspf_attribute_group);
-
-fail_sysfs:
-	platform_device_del(asuspf_device);
-
-fail_platform_device2:
-	platform_device_put(asuspf_device);
-
-fail_platform_device1:
-	platform_driver_unregister(&asuspf_driver);
-
-fail_platform_driver:
-	asus_input_exit();
-
-fail_input:
-
+fail_no_device:
+	acpi_bus_unregister_driver(&asus_acpi_driver);
+fail_acpi_driver:
+	platform_driver_unregister(&platform_driver);
 	return result;
 }
 
+static void __exit asus_laptop_exit(void)
+{
+	acpi_bus_unregister_driver(&asus_acpi_driver);
+	platform_driver_unregister(&platform_driver);
+}
+
 module_init(asus_laptop_init);
 module_exit(asus_laptop_exit);
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index c1d2aee..1381430 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -1225,9 +1225,8 @@
 	else if (strncmp(model, "M2N", 3) == 0 ||
 		 strncmp(model, "M3N", 3) == 0 ||
 		 strncmp(model, "M5N", 3) == 0 ||
-		 strncmp(model, "M6N", 3) == 0 ||
 		 strncmp(model, "S1N", 3) == 0 ||
-		 strncmp(model, "S5N", 3) == 0 || strncmp(model, "W1N", 3) == 0)
+		 strncmp(model, "S5N", 3) == 0)
 		return xxN;
 	else if (strncmp(model, "M1", 2) == 0)
 		return M1A;
diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c
index 8cb20e4..035a7dd 100644
--- a/drivers/platform/x86/classmate-laptop.c
+++ b/drivers/platform/x86/classmate-laptop.c
@@ -507,6 +507,10 @@
 	KEY_BRIGHTNESSDOWN,
 	KEY_BRIGHTNESSUP,
 	KEY_VENDOR,
+	KEY_UNKNOWN,
+	KEY_CAMERA,
+	KEY_BACK,
+	KEY_FORWARD,
 	KEY_MAX
 };
 
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index b7f4d27..ef61497 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -132,8 +132,8 @@
 };
 
 static struct calling_interface_buffer *buffer;
-struct page *bufferpage;
-DEFINE_MUTEX(buffer_mutex);
+static struct page *bufferpage;
+static DEFINE_MUTEX(buffer_mutex);
 
 static int hwswitch_state;
 
@@ -580,6 +580,7 @@
 
 fail_backlight:
 	i8042_remove_filter(dell_laptop_i8042_filter);
+	cancel_delayed_work_sync(&dell_rfkill_work);
 fail_filter:
 	dell_cleanup_rfkill();
 fail_rfkill:
@@ -597,12 +598,12 @@
 
 static void __exit dell_exit(void)
 {
-	cancel_delayed_work_sync(&dell_rfkill_work);
 	i8042_remove_filter(dell_laptop_i8042_filter);
+	cancel_delayed_work_sync(&dell_rfkill_work);
 	backlight_device_unregister(dell_backlight_device);
 	dell_cleanup_rfkill();
 	if (platform_device) {
-		platform_device_del(platform_device);
+		platform_device_unregister(platform_device);
 		platform_driver_unregister(&platform_driver);
 	}
 	kfree(da_tokens);
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index e2be6bb..9a844ca 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -578,6 +578,8 @@
 	struct pci_dev *dev;
 	struct pci_bus *bus;
 	bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
+	bool absent;
+	u32 l;
 
 	if (eeepc->wlan_rfkill)
 		rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
@@ -591,6 +593,22 @@
 			goto out_unlock;
 		}
 
+		if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
+			pr_err("Unable to read PCI config space?\n");
+			goto out_unlock;
+		}
+		absent = (l == 0xffffffff);
+
+		if (blocked != absent) {
+			pr_warning("BIOS says wireless lan is %s, "
+					"but the pci device is %s\n",
+				blocked ? "blocked" : "unblocked",
+				absent ? "absent" : "present");
+			pr_warning("skipped wireless hotplug as probably "
+					"inappropriate for this model\n");
+			goto out_unlock;
+		}
+
 		if (!blocked) {
 			dev = pci_get_slot(bus, 0);
 			if (dev) {
@@ -1277,7 +1295,8 @@
 	 * hotplug code. In fact, current hotplug code seems to unplug another
 	 * device...
 	 */
-	if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) {
+	if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0 ||
+	    strcmp(model, "1005PE") == 0) {
 		eeepc->hotplug_disabled = true;
 		pr_info("wlan hotplug disabled\n");
 	}
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index 3aa57da..7ccf33c 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -57,7 +57,7 @@
 	HPWMI_WWAN = 2,
 };
 
-static int __init hp_wmi_bios_setup(struct platform_device *device);
+static int __devinit hp_wmi_bios_setup(struct platform_device *device);
 static int __exit hp_wmi_bios_remove(struct platform_device *device);
 static int hp_wmi_resume_handler(struct device *device);
 
@@ -447,7 +447,7 @@
 	device_remove_file(&device->dev, &dev_attr_tablet);
 }
 
-static int __init hp_wmi_bios_setup(struct platform_device *device)
+static int __devinit hp_wmi_bios_setup(struct platform_device *device)
 {
 	int err;
 	int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 759763d..c2b05da 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -58,6 +58,7 @@
 #include <linux/dmi.h>
 #include <linux/backlight.h>
 #include <linux/platform_device.h>
+#include <linux/rfkill.h>
 
 #define MSI_DRIVER_VERSION "0.5"
 
@@ -66,6 +67,20 @@
 #define MSI_EC_COMMAND_WIRELESS 0x10
 #define MSI_EC_COMMAND_LCD_LEVEL 0x11
 
+#define MSI_STANDARD_EC_COMMAND_ADDRESS	0x2e
+#define MSI_STANDARD_EC_BLUETOOTH_MASK	(1 << 0)
+#define MSI_STANDARD_EC_WEBCAM_MASK	(1 << 1)
+#define MSI_STANDARD_EC_WLAN_MASK	(1 << 3)
+#define MSI_STANDARD_EC_3G_MASK		(1 << 4)
+
+/* For set SCM load flag to disable BIOS fn key */
+#define MSI_STANDARD_EC_SCM_LOAD_ADDRESS	0x2d
+#define MSI_STANDARD_EC_SCM_LOAD_MASK		(1 << 0)
+
+static int msi_laptop_resume(struct platform_device *device);
+
+#define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS	0x2f
+
 static int force;
 module_param(force, bool, 0);
 MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
@@ -74,6 +89,23 @@
 module_param(auto_brightness, int, 0);
 MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)");
 
+static bool old_ec_model;
+static int wlan_s, bluetooth_s, threeg_s;
+static int threeg_exists;
+
+/* Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G,
+ * those netbook will load the SCM (windows app) to disable the original
+ * Wlan/Bluetooth control by BIOS when user press fn key, then control
+ * Wlan/Bluetooth/3G by SCM (software control by OS). Without SCM, user
+ * cann't on/off 3G module on those 3G netbook.
+ * On Linux, msi-laptop driver will do the same thing to disable the
+ * original BIOS control, then might need use HAL or other userland
+ * application to do the software control that simulate with SCM.
+ * e.g. MSI N034 netbook
+ */
+static bool load_scm_model;
+static struct rfkill *rfk_wlan, *rfk_bluetooth, *rfk_threeg;
+
 /* Hardware access */
 
 static int set_lcd_level(int level)
@@ -130,6 +162,35 @@
 	return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1);
 }
 
+static ssize_t set_device_state(const char *buf, size_t count, u8 mask)
+{
+	int status;
+	u8 wdata = 0, rdata;
+	int result;
+
+	if (sscanf(buf, "%i", &status) != 1 || (status < 0 || status > 1))
+		return -EINVAL;
+
+	/* read current device state */
+	result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
+	if (result < 0)
+		return -EINVAL;
+
+	if (!!(rdata & mask) != status) {
+		/* reverse device bit */
+		if (rdata & mask)
+			wdata = rdata & ~mask;
+		else
+			wdata = rdata | mask;
+
+		result = ec_write(MSI_STANDARD_EC_COMMAND_ADDRESS, wdata);
+		if (result < 0)
+			return -EINVAL;
+	}
+
+	return count;
+}
+
 static int get_wireless_state(int *wlan, int *bluetooth)
 {
 	u8 wdata = 0, rdata;
@@ -148,6 +209,38 @@
 	return 0;
 }
 
+static int get_wireless_state_ec_standard(void)
+{
+	u8 rdata;
+	int result;
+
+	result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
+	if (result < 0)
+		return -1;
+
+	wlan_s = !!(rdata & MSI_STANDARD_EC_WLAN_MASK);
+
+	bluetooth_s = !!(rdata & MSI_STANDARD_EC_BLUETOOTH_MASK);
+
+	threeg_s = !!(rdata & MSI_STANDARD_EC_3G_MASK);
+
+	return 0;
+}
+
+static int get_threeg_exists(void)
+{
+	u8 rdata;
+	int result;
+
+	result = ec_read(MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS, &rdata);
+	if (result < 0)
+		return -1;
+
+	threeg_exists = !!(rdata & MSI_STANDARD_EC_3G_MASK);
+
+	return 0;
+}
+
 /* Backlight device stuff */
 
 static int bl_get_brightness(struct backlight_device *b)
@@ -176,26 +269,71 @@
 
 	int ret, enabled;
 
-	ret = get_wireless_state(&enabled, NULL);
+	if (old_ec_model) {
+		ret = get_wireless_state(&enabled, NULL);
+	} else {
+		ret = get_wireless_state_ec_standard();
+		enabled = wlan_s;
+	}
 	if (ret < 0)
 		return ret;
 
 	return sprintf(buf, "%i\n", enabled);
 }
 
+static ssize_t store_wlan(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	return set_device_state(buf, count, MSI_STANDARD_EC_WLAN_MASK);
+}
+
 static ssize_t show_bluetooth(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 
 	int ret, enabled;
 
-	ret = get_wireless_state(NULL, &enabled);
+	if (old_ec_model) {
+		ret = get_wireless_state(NULL, &enabled);
+	} else {
+		ret = get_wireless_state_ec_standard();
+		enabled = bluetooth_s;
+	}
 	if (ret < 0)
 		return ret;
 
 	return sprintf(buf, "%i\n", enabled);
 }
 
+static ssize_t store_bluetooth(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	return set_device_state(buf, count, MSI_STANDARD_EC_BLUETOOTH_MASK);
+}
+
+static ssize_t show_threeg(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+
+	int ret;
+
+	/* old msi ec not support 3G */
+	if (old_ec_model)
+		return -1;
+
+	ret = get_wireless_state_ec_standard();
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%i\n", threeg_s);
+}
+
+static ssize_t store_threeg(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	return set_device_state(buf, count, MSI_STANDARD_EC_3G_MASK);
+}
+
 static ssize_t show_lcd_level(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
@@ -258,6 +396,7 @@
 static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness);
 static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL);
 static DEVICE_ATTR(wlan, 0444, show_wlan, NULL);
+static DEVICE_ATTR(threeg, 0444, show_threeg, NULL);
 
 static struct attribute *msipf_attributes[] = {
 	&dev_attr_lcd_level.attr,
@@ -275,7 +414,8 @@
 	.driver = {
 		.name = "msi-laptop-pf",
 		.owner = THIS_MODULE,
-	}
+	},
+	.resume = msi_laptop_resume,
 };
 
 static struct platform_device *msipf_device;
@@ -332,6 +472,192 @@
 	{ }
 };
 
+static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = {
+	{
+		.ident = "MSI N034",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+				"MICRO-STAR INTERNATIONAL CO., LTD"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MS-N034"),
+			DMI_MATCH(DMI_CHASSIS_VENDOR,
+			"MICRO-STAR INTERNATIONAL CO., LTD")
+		},
+		.callback = dmi_check_cb
+	},
+	{ }
+};
+
+static int rfkill_bluetooth_set(void *data, bool blocked)
+{
+	/* Do something with blocked...*/
+	/*
+	 * blocked == false is on
+	 * blocked == true is off
+	 */
+	if (blocked)
+		set_device_state("0", 0, MSI_STANDARD_EC_BLUETOOTH_MASK);
+	else
+		set_device_state("1", 0, MSI_STANDARD_EC_BLUETOOTH_MASK);
+
+	return 0;
+}
+
+static int rfkill_wlan_set(void *data, bool blocked)
+{
+	if (blocked)
+		set_device_state("0", 0, MSI_STANDARD_EC_WLAN_MASK);
+	else
+		set_device_state("1", 0, MSI_STANDARD_EC_WLAN_MASK);
+
+	return 0;
+}
+
+static int rfkill_threeg_set(void *data, bool blocked)
+{
+	if (blocked)
+		set_device_state("0", 0, MSI_STANDARD_EC_3G_MASK);
+	else
+		set_device_state("1", 0, MSI_STANDARD_EC_3G_MASK);
+
+	return 0;
+}
+
+static struct rfkill_ops rfkill_bluetooth_ops = {
+	.set_block = rfkill_bluetooth_set
+};
+
+static struct rfkill_ops rfkill_wlan_ops = {
+	.set_block = rfkill_wlan_set
+};
+
+static struct rfkill_ops rfkill_threeg_ops = {
+	.set_block = rfkill_threeg_set
+};
+
+static void rfkill_cleanup(void)
+{
+	if (rfk_bluetooth) {
+		rfkill_unregister(rfk_bluetooth);
+		rfkill_destroy(rfk_bluetooth);
+	}
+
+	if (rfk_threeg) {
+		rfkill_unregister(rfk_threeg);
+		rfkill_destroy(rfk_threeg);
+	}
+
+	if (rfk_wlan) {
+		rfkill_unregister(rfk_wlan);
+		rfkill_destroy(rfk_wlan);
+	}
+}
+
+static int rfkill_init(struct platform_device *sdev)
+{
+	/* add rfkill */
+	int retval;
+
+	rfk_bluetooth = rfkill_alloc("msi-bluetooth", &sdev->dev,
+				RFKILL_TYPE_BLUETOOTH,
+				&rfkill_bluetooth_ops, NULL);
+	if (!rfk_bluetooth) {
+		retval = -ENOMEM;
+		goto err_bluetooth;
+	}
+	retval = rfkill_register(rfk_bluetooth);
+	if (retval)
+		goto err_bluetooth;
+
+	rfk_wlan = rfkill_alloc("msi-wlan", &sdev->dev, RFKILL_TYPE_WLAN,
+				&rfkill_wlan_ops, NULL);
+	if (!rfk_wlan) {
+		retval = -ENOMEM;
+		goto err_wlan;
+	}
+	retval = rfkill_register(rfk_wlan);
+	if (retval)
+		goto err_wlan;
+
+	if (threeg_exists) {
+		rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev,
+				RFKILL_TYPE_WWAN, &rfkill_threeg_ops, NULL);
+		if (!rfk_threeg) {
+			retval = -ENOMEM;
+			goto err_threeg;
+		}
+		retval = rfkill_register(rfk_threeg);
+		if (retval)
+			goto err_threeg;
+	}
+
+	return 0;
+
+err_threeg:
+	rfkill_destroy(rfk_threeg);
+	if (rfk_wlan)
+		rfkill_unregister(rfk_wlan);
+err_wlan:
+	rfkill_destroy(rfk_wlan);
+	if (rfk_bluetooth)
+		rfkill_unregister(rfk_bluetooth);
+err_bluetooth:
+	rfkill_destroy(rfk_bluetooth);
+
+	return retval;
+}
+
+static int msi_laptop_resume(struct platform_device *device)
+{
+	u8 data;
+	int result;
+
+	if (!load_scm_model)
+		return 0;
+
+	/* set load SCM to disable hardware control by fn key */
+	result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data);
+	if (result < 0)
+		return result;
+
+	result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS,
+		data | MSI_STANDARD_EC_SCM_LOAD_MASK);
+	if (result < 0)
+		return result;
+
+	return 0;
+}
+
+static int load_scm_model_init(struct platform_device *sdev)
+{
+	u8 data;
+	int result;
+
+	/* allow userland write sysfs file  */
+	dev_attr_bluetooth.store = store_bluetooth;
+	dev_attr_wlan.store = store_wlan;
+	dev_attr_threeg.store = store_threeg;
+	dev_attr_bluetooth.attr.mode |= S_IWUSR;
+	dev_attr_wlan.attr.mode |= S_IWUSR;
+	dev_attr_threeg.attr.mode |= S_IWUSR;
+
+	/* disable hardware control by fn key */
+	result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data);
+	if (result < 0)
+		return result;
+
+	result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS,
+		data | MSI_STANDARD_EC_SCM_LOAD_MASK);
+	if (result < 0)
+		return result;
+
+	/* initial rfkill */
+	result = rfkill_init(sdev);
+	if (result < 0)
+		return result;
+
+	return 0;
+}
+
 static int __init msi_init(void)
 {
 	int ret;
@@ -339,8 +665,14 @@
 	if (acpi_disabled)
 		return -ENODEV;
 
-	if (!force && !dmi_check_system(msi_dmi_table))
-		return -ENODEV;
+	if (force || dmi_check_system(msi_dmi_table))
+		old_ec_model = 1;
+
+	if (!old_ec_model)
+		get_threeg_exists();
+
+	if (!old_ec_model && dmi_check_system(msi_load_scm_models_dmi_table))
+		load_scm_model = 1;
 
 	if (auto_brightness < 0 || auto_brightness > 2)
 		return -EINVAL;
@@ -374,10 +706,23 @@
 	if (ret)
 		goto fail_platform_device1;
 
+	if (load_scm_model && (load_scm_model_init(msipf_device) < 0)) {
+		ret = -EINVAL;
+		goto fail_platform_device1;
+	}
+
 	ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group);
 	if (ret)
 		goto fail_platform_device2;
 
+	if (!old_ec_model) {
+		if (threeg_exists)
+			ret = device_create_file(&msipf_device->dev,
+						&dev_attr_threeg);
+		if (ret)
+			goto fail_platform_device2;
+	}
+
 	/* Disable automatic brightness control by default because
 	 * this module was probably loaded to do brightness control in
 	 * software. */
@@ -412,10 +757,14 @@
 {
 
 	sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group);
+	if (!old_ec_model && threeg_exists)
+		device_remove_file(&msipf_device->dev, &dev_attr_threeg);
 	platform_device_unregister(msipf_device);
 	platform_driver_unregister(&msipf_driver);
 	backlight_device_unregister(msibl_device);
 
+	rfkill_cleanup();
+
 	/* Enable automatic brightness control again */
 	if (auto_brightness != 2)
 		set_auto_brightness(1);
@@ -435,3 +784,4 @@
 MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*");
 MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
 MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
+MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N034:*");
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index eb603f1d5..c64e352 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -286,6 +286,7 @@
 	char param[32];
 
 	int (*init) (struct ibm_init_struct *);
+	mode_t base_procfs_mode;
 	struct ibm_struct *data;
 };
 
@@ -1667,7 +1668,7 @@
  * Table of recommended minimum BIOS versions
  *
  * Reasons for listing:
- *    1. Stable BIOS, listed because the unknown ammount of
+ *    1. Stable BIOS, listed because the unknown amount of
  *       bugs and bad ACPI behaviour on older versions
  *
  *    2. BIOS or EC fw with known bugs that trigger on Linux
@@ -2082,6 +2083,7 @@
 
 static void tpacpi_driver_event(const unsigned int hkey_event);
 static void hotkey_driver_event(const unsigned int scancode);
+static void hotkey_poll_setup(const bool may_warn);
 
 /* HKEY.MHKG() return bits */
 #define TP_HOTKEY_TABLET_MASK (1 << 3)
@@ -2264,6 +2266,8 @@
 
 	rc = hotkey_mask_set((hotkey_acpi_mask | hotkey_driver_mask) &
 							~hotkey_source_mask);
+	hotkey_poll_setup(true);
+
 	mutex_unlock(&hotkey_mutex);
 
 	return rc;
@@ -2548,7 +2552,7 @@
 }
 
 /* call with hotkey_mutex held */
-static void hotkey_poll_setup(bool may_warn)
+static void hotkey_poll_setup(const bool may_warn)
 {
 	const u32 poll_driver_mask = hotkey_driver_mask & hotkey_source_mask;
 	const u32 poll_user_mask = hotkey_user_mask & hotkey_source_mask;
@@ -2579,7 +2583,7 @@
 	}
 }
 
-static void hotkey_poll_setup_safe(bool may_warn)
+static void hotkey_poll_setup_safe(const bool may_warn)
 {
 	mutex_lock(&hotkey_mutex);
 	hotkey_poll_setup(may_warn);
@@ -2597,7 +2601,11 @@
 
 #else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
 
-static void hotkey_poll_setup_safe(bool __unused)
+static void hotkey_poll_setup(const bool __unused)
+{
+}
+
+static void hotkey_poll_setup_safe(const bool __unused)
 {
 }
 
@@ -2607,16 +2615,11 @@
 {
 	switch (tpacpi_lifecycle) {
 	case TPACPI_LIFE_INIT:
-		/*
-		 * hotkey_init will call hotkey_poll_setup_safe
-		 * at the appropriate moment
-		 */
-		return 0;
-	case TPACPI_LIFE_EXITING:
-		return -EBUSY;
 	case TPACPI_LIFE_RUNNING:
 		hotkey_poll_setup_safe(false);
 		return 0;
+	case TPACPI_LIFE_EXITING:
+		return -EBUSY;
 	}
 
 	/* Should only happen if tpacpi_lifecycle is corrupt */
@@ -2627,7 +2630,7 @@
 static void hotkey_inputdev_close(struct input_dev *dev)
 {
 	/* disable hotkey polling when possible */
-	if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING &&
+	if (tpacpi_lifecycle != TPACPI_LIFE_EXITING &&
 	    !(hotkey_source_mask & hotkey_driver_mask))
 		hotkey_poll_setup_safe(false);
 }
@@ -3655,13 +3658,19 @@
 			break;
 		case 3:
 			/* 0x3000-0x3FFF: bay-related wakeups */
-			if (hkey == TP_HKEY_EV_BAYEJ_ACK) {
+			switch (hkey) {
+			case TP_HKEY_EV_BAYEJ_ACK:
 				hotkey_autosleep_ack = 1;
 				printk(TPACPI_INFO
 				       "bay ejected\n");
 				hotkey_wakeup_hotunplug_complete_notify_change();
 				known_ev = true;
-			} else {
+				break;
+			case TP_HKEY_EV_OPTDRV_EJ:
+				/* FIXME: kick libata if SATA link offline */
+				known_ev = true;
+				break;
+			default:
 				known_ev = false;
 			}
 			break;
@@ -3870,7 +3879,7 @@
 	TP_ACPI_BLUETOOTH_HWPRESENT	= 0x01,	/* Bluetooth hw available */
 	TP_ACPI_BLUETOOTH_RADIOSSW	= 0x02,	/* Bluetooth radio enabled */
 	TP_ACPI_BLUETOOTH_RESUMECTRL	= 0x04,	/* Bluetooth state at resume:
-						   off / last state */
+						   0 = disable, 1 = enable */
 };
 
 enum {
@@ -3916,10 +3925,11 @@
 	}
 #endif
 
-	/* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
-	status = TP_ACPI_BLUETOOTH_RESUMECTRL;
 	if (state == TPACPI_RFK_RADIO_ON)
-		status |= TP_ACPI_BLUETOOTH_RADIOSSW;
+		status = TP_ACPI_BLUETOOTH_RADIOSSW
+			  | TP_ACPI_BLUETOOTH_RESUMECTRL;
+	else
+		status = 0;
 
 	if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
 		return -EIO;
@@ -4070,7 +4080,7 @@
 	TP_ACPI_WANCARD_HWPRESENT	= 0x01,	/* Wan hw available */
 	TP_ACPI_WANCARD_RADIOSSW	= 0x02,	/* Wan radio enabled */
 	TP_ACPI_WANCARD_RESUMECTRL	= 0x04,	/* Wan state at resume:
-						   off / last state */
+						   0 = disable, 1 = enable */
 };
 
 #define TPACPI_RFK_WWAN_SW_NAME		"tpacpi_wwan_sw"
@@ -4107,10 +4117,11 @@
 	}
 #endif
 
-	/* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */
-	status = TP_ACPI_WANCARD_RESUMECTRL;
 	if (state == TPACPI_RFK_RADIO_ON)
-		status |= TP_ACPI_WANCARD_RADIOSSW;
+		status = TP_ACPI_WANCARD_RADIOSSW
+			 | TP_ACPI_WANCARD_RESUMECTRL;
+	else
+		status = 0;
 
 	if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
 		return -EIO;
@@ -4619,6 +4630,10 @@
 		return 0;
 	}
 
+	/* Even reads can crash X.org, so... */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	status = video_outputsw_get();
 	if (status < 0)
 		return status;
@@ -4652,6 +4667,10 @@
 	if (video_supported == TPACPI_VIDEO_NONE)
 		return -ENODEV;
 
+	/* Even reads can crash X.org, let alone writes... */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	enable = 0;
 	disable = 0;
 
@@ -6133,13 +6152,13 @@
 	TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC),	/* T43/p ATI */
 
 	/* Models with ATI GPUs that can use ECNVRAM */
-	TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC),
+	TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC),	/* R50,51 T40-42 */
 	TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
-	TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+	TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_EC),	/* R52 */
 	TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
 
 	/* Models with Intel Extreme Graphics 2 */
-	TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
+	TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),	/* X40 */
 	TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
 	TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
 
@@ -6522,7 +6541,8 @@
 	return volume_set_status_ec(status);
 }
 
-static int volume_set_mute_ec(const bool mute)
+/* returns < 0 on error, 0 on no change, 1 on change */
+static int __volume_set_mute_ec(const bool mute)
 {
 	int rc;
 	u8 s, n;
@@ -6537,22 +6557,37 @@
 	n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK :
 		     s & ~TP_EC_AUDIO_MUTESW_MSK;
 
-	if (n != s)
+	if (n != s) {
 		rc = volume_set_status_ec(n);
+		if (!rc)
+			rc = 1;
+	}
 
 unlock:
 	mutex_unlock(&volume_mutex);
 	return rc;
 }
 
-static int volume_set_mute(const bool mute)
+static int volume_alsa_set_mute(const bool mute)
 {
-	dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
+	dbg_printk(TPACPI_DBG_MIXER, "ALSA: trying to %smute\n",
 		   (mute) ? "" : "un");
-	return volume_set_mute_ec(mute);
+	return __volume_set_mute_ec(mute);
 }
 
-static int volume_set_volume_ec(const u8 vol)
+static int volume_set_mute(const bool mute)
+{
+	int rc;
+
+	dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
+		   (mute) ? "" : "un");
+
+	rc = __volume_set_mute_ec(mute);
+	return (rc < 0) ? rc : 0;
+}
+
+/* returns < 0 on error, 0 on no change, 1 on change */
+static int __volume_set_volume_ec(const u8 vol)
 {
 	int rc;
 	u8 s, n;
@@ -6569,19 +6604,22 @@
 
 	n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol;
 
-	if (n != s)
+	if (n != s) {
 		rc = volume_set_status_ec(n);
+		if (!rc)
+			rc = 1;
+	}
 
 unlock:
 	mutex_unlock(&volume_mutex);
 	return rc;
 }
 
-static int volume_set_volume(const u8 vol)
+static int volume_alsa_set_volume(const u8 vol)
 {
 	dbg_printk(TPACPI_DBG_MIXER,
-		   "trying to set volume level to %hu\n", vol);
-	return volume_set_volume_ec(vol);
+		   "ALSA: trying to set volume level to %hu\n", vol);
+	return __volume_set_volume_ec(vol);
 }
 
 static void volume_alsa_notify_change(void)
@@ -6628,7 +6666,7 @@
 static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	return volume_set_volume(ucontrol->value.integer.value[0]);
+	return volume_alsa_set_volume(ucontrol->value.integer.value[0]);
 }
 
 #define volume_alsa_mute_info snd_ctl_boolean_mono_info
@@ -6651,7 +6689,7 @@
 static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
-	return volume_set_mute(!ucontrol->value.integer.value[0]);
+	return volume_alsa_set_mute(!ucontrol->value.integer.value[0]);
 }
 
 static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
@@ -7070,7 +7108,7 @@
  *
  * 	Fan speed changes of any sort (including those caused by the
  * 	disengaged mode) are usually done slowly by the firmware as the
- * 	maximum ammount of fan duty cycle change per second seems to be
+ * 	maximum amount of fan duty cycle change per second seems to be
  * 	limited.
  *
  * 	Reading is not available if GFAN exists.
@@ -8477,9 +8515,10 @@
 		"%s installed\n", ibm->name);
 
 	if (ibm->read) {
-		mode_t mode;
+		mode_t mode = iibm->base_procfs_mode;
 
-		mode = S_IRUGO;
+		if (!mode)
+			mode = S_IRUGO;
 		if (ibm->write)
 			mode |= S_IWUSR;
 		entry = proc_create_data(ibm->name, mode, proc_dir,
@@ -8670,6 +8709,7 @@
 #ifdef CONFIG_THINKPAD_ACPI_VIDEO
 	{
 		.init = video_init,
+		.base_procfs_mode = S_IRUSR,
 		.data = &video_driver_data,
 	},
 #endif
@@ -9032,6 +9072,9 @@
 			return ret;
 		}
 	}
+
+	tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
+
 	ret = input_register_device(tpacpi_inputdev);
 	if (ret < 0) {
 		printk(TPACPI_ERR "unable to register input device\n");
@@ -9041,7 +9084,6 @@
 		tp_features.input_device_registered = 1;
 	}
 
-	tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
 	return 0;
 }
 
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 26c2117..405b969 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -814,21 +814,23 @@
 		if (hci_result == HCI_SUCCESS) {
 			if (value == 0x100)
 				continue;
-			else if (value & 0x80) {
-				key = toshiba_acpi_get_entry_by_scancode
-					(value & ~0x80);
-				if (!key) {
-					printk(MY_INFO "Unknown key %x\n",
-					       value & ~0x80);
-					continue;
-				}
-				input_report_key(toshiba_acpi.hotkey_dev,
-						 key->keycode, 1);
-				input_sync(toshiba_acpi.hotkey_dev);
-				input_report_key(toshiba_acpi.hotkey_dev,
-						 key->keycode, 0);
-				input_sync(toshiba_acpi.hotkey_dev);
+			/* act on key press; ignore key release */
+			if (value & 0x80)
+				continue;
+
+			key = toshiba_acpi_get_entry_by_scancode
+				(value);
+			if (!key) {
+				printk(MY_INFO "Unknown key %x\n",
+				       value);
+				continue;
 			}
+			input_report_key(toshiba_acpi.hotkey_dev,
+					 key->keycode, 1);
+			input_sync(toshiba_acpi.hotkey_dev);
+			input_report_key(toshiba_acpi.hotkey_dev,
+					 key->keycode, 0);
+			input_sync(toshiba_acpi.hotkey_dev);
 		} else if (hci_result == HCI_NOT_SUPPORTED) {
 			/* This is a workaround for an unresolved issue on
 			 * some machines where system events sporadically
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index d4b3d67..faaa9b4 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -29,6 +29,13 @@
 	  Say Y here to enable support APM status emulation using
 	  battery class devices.
 
+config MAX8925_POWER
+	tristate "MAX8925 battery charger support"
+	depends on MFD_MAX8925
+	help
+	  Say Y here to enable support for the battery charger in the Maxim
+	  MAX8925 PMIC.
+
 config WM831X_BACKUP
 	tristate "WM831X backup battery charger support"
 	depends on MFD_WM831X
@@ -98,10 +105,10 @@
 	  Say Y to enable support for battery measured by WM97xx aux port.
 
 config BATTERY_BQ27x00
-	tristate "BQ27200 battery driver"
+	tristate "BQ27x00 battery driver"
 	depends on I2C
 	help
-	  Say Y here to enable support for batteries with BQ27200(I2C) chip.
+	  Say Y here to enable support for batteries with BQ27x00 (I2C) chips.
 
 config BATTERY_DA9030
 	tristate "DA9030 battery driver"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 573597c..a2ba7c85 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -16,6 +16,7 @@
 
 obj-$(CONFIG_PDA_POWER)		+= pda_power.o
 obj-$(CONFIG_APM_POWER)		+= apm_power.o
+obj-$(CONFIG_MAX8925_POWER)	+= max8925_power.o
 obj-$(CONFIG_WM831X_BACKUP)	+= wm831x_backup.o
 obj-$(CONFIG_WM831X_POWER)	+= wm831x_power.o
 obj-$(CONFIG_WM8350_POWER)	+= wm8350_power.o
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 62bb981..bece33e 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -26,13 +26,22 @@
 #include <linux/i2c.h>
 #include <asm/unaligned.h>
 
-#define DRIVER_VERSION			"1.0.0"
+#define DRIVER_VERSION			"1.1.0"
 
 #define BQ27x00_REG_TEMP		0x06
 #define BQ27x00_REG_VOLT		0x08
-#define BQ27x00_REG_RSOC		0x0B /* Relative State-of-Charge */
 #define BQ27x00_REG_AI			0x14
 #define BQ27x00_REG_FLAGS		0x0A
+#define BQ27x00_REG_TTE			0x16
+#define BQ27x00_REG_TTF			0x18
+#define BQ27x00_REG_TTECP		0x26
+
+#define BQ27000_REG_RSOC		0x0B /* Relative State-of-Charge */
+#define BQ27000_FLAG_CHGS		BIT(7)
+
+#define BQ27500_REG_SOC			0x2c
+#define BQ27500_FLAG_DSC		BIT(0)
+#define BQ27500_FLAG_FC			BIT(9)
 
 /* If the system has several batteries we need a different name for each
  * of them...
@@ -46,25 +55,28 @@
 		struct bq27x00_device_info *di);
 };
 
+enum bq27x00_chip { BQ27000, BQ27500 };
+
 struct bq27x00_device_info {
 	struct device 		*dev;
 	int			id;
-	int			voltage_uV;
-	int			current_uA;
-	int			temp_C;
-	int			charge_rsoc;
 	struct bq27x00_access_methods	*bus;
 	struct power_supply	bat;
+	enum bq27x00_chip	chip;
 
 	struct i2c_client	*client;
 };
 
 static enum power_supply_property bq27x00_battery_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
 };
 
 /*
@@ -74,16 +86,11 @@
 static int bq27x00_read(u8 reg, int *rt_value, int b_single,
 			struct bq27x00_device_info *di)
 {
-	int ret;
-
-	ret = di->bus->read(reg, rt_value, b_single, di);
-	*rt_value = be16_to_cpu(*rt_value);
-
-	return ret;
+	return di->bus->read(reg, rt_value, b_single, di);
 }
 
 /*
- * Return the battery temperature in Celsius degrees
+ * Return the battery temperature in tenths of degree Celsius
  * Or < 0 if something fails.
  */
 static int bq27x00_battery_temperature(struct bq27x00_device_info *di)
@@ -97,7 +104,10 @@
 		return ret;
 	}
 
-	return (temp >> 2) - 273;
+	if (di->chip == BQ27500)
+		return temp - 2731;
+	else
+		return ((temp >> 2) - 273) * 10;
 }
 
 /*
@@ -115,7 +125,7 @@
 		return ret;
 	}
 
-	return volt;
+	return volt * 1000;
 }
 
 /*
@@ -134,16 +144,23 @@
 		dev_err(di->dev, "error reading current\n");
 		return 0;
 	}
-	ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
-	if (ret < 0) {
-		dev_err(di->dev, "error reading flags\n");
-		return 0;
+
+	if (di->chip == BQ27500) {
+		/* bq27500 returns signed value */
+		curr = (int)(s16)curr;
+	} else {
+		ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
+		if (ret < 0) {
+			dev_err(di->dev, "error reading flags\n");
+			return 0;
+		}
+		if (flags & BQ27000_FLAG_CHGS) {
+			dev_dbg(di->dev, "negative current!\n");
+			curr = -curr;
+		}
 	}
-	if ((flags & (1 << 7)) != 0) {
-		dev_dbg(di->dev, "negative current!\n");
-		return -curr;
-	}
-	return curr;
+
+	return curr * 1000;
 }
 
 /*
@@ -155,13 +172,70 @@
 	int ret;
 	int rsoc = 0;
 
-	ret = bq27x00_read(BQ27x00_REG_RSOC, &rsoc, 1, di);
+	if (di->chip == BQ27500)
+		ret = bq27x00_read(BQ27500_REG_SOC, &rsoc, 0, di);
+	else
+		ret = bq27x00_read(BQ27000_REG_RSOC, &rsoc, 1, di);
 	if (ret) {
 		dev_err(di->dev, "error reading relative State-of-Charge\n");
 		return ret;
 	}
 
-	return rsoc >> 8;
+	return rsoc;
+}
+
+static int bq27x00_battery_status(struct bq27x00_device_info *di,
+				  union power_supply_propval *val)
+{
+	int flags = 0;
+	int status;
+	int ret;
+
+	ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
+	if (ret < 0) {
+		dev_err(di->dev, "error reading flags\n");
+		return ret;
+	}
+
+	if (di->chip == BQ27500) {
+		if (flags & BQ27500_FLAG_FC)
+			status = POWER_SUPPLY_STATUS_FULL;
+		else if (flags & BQ27500_FLAG_DSC)
+			status = POWER_SUPPLY_STATUS_DISCHARGING;
+		else
+			status = POWER_SUPPLY_STATUS_CHARGING;
+	} else {
+		if (flags & BQ27000_FLAG_CHGS)
+			status = POWER_SUPPLY_STATUS_CHARGING;
+		else
+			status = POWER_SUPPLY_STATUS_DISCHARGING;
+	}
+
+	val->intval = status;
+	return 0;
+}
+
+/*
+ * Read a time register.
+ * Return < 0 if something fails.
+ */
+static int bq27x00_battery_time(struct bq27x00_device_info *di, int reg,
+				union power_supply_propval *val)
+{
+	int tval = 0;
+	int ret;
+
+	ret = bq27x00_read(reg, &tval, 0, di);
+	if (ret) {
+		dev_err(di->dev, "error reading register %02x\n", reg);
+		return ret;
+	}
+
+	if (tval == 65535)
+		return -ENODATA;
+
+	val->intval = tval * 60;
+	return 0;
 }
 
 #define to_bq27x00_device_info(x) container_of((x), \
@@ -171,9 +245,13 @@
 					enum power_supply_property psp,
 					union power_supply_propval *val)
 {
+	int ret = 0;
 	struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
 
 	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		ret = bq27x00_battery_status(di, val);
+		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = bq27x00_battery_voltage(di);
@@ -189,11 +267,20 @@
 	case POWER_SUPPLY_PROP_TEMP:
 		val->intval = bq27x00_battery_temperature(di);
 		break;
+	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+		ret = bq27x00_battery_time(di, BQ27x00_REG_TTE, val);
+		break;
+	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+		ret = bq27x00_battery_time(di, BQ27x00_REG_TTECP, val);
+		break;
+	case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
+		ret = bq27x00_battery_time(di, BQ27x00_REG_TTF, val);
+		break;
 	default:
 		return -EINVAL;
 	}
 
-	return 0;
+	return ret;
 }
 
 static void bq27x00_powersupply_init(struct bq27x00_device_info *di)
@@ -206,10 +293,10 @@
 }
 
 /*
- * BQ27200 specific code
+ * i2c specific code
  */
 
-static int bq27200_read(u8 reg, int *rt_value, int b_single,
+static int bq27x00_read_i2c(u8 reg, int *rt_value, int b_single,
 			struct bq27x00_device_info *di)
 {
 	struct i2c_client *client = di->client;
@@ -238,7 +325,7 @@
 		err = i2c_transfer(client->adapter, msg, 1);
 		if (err >= 0) {
 			if (!b_single)
-				*rt_value = get_unaligned_be16(data);
+				*rt_value = get_unaligned_le16(data);
 			else
 				*rt_value = data[0];
 
@@ -248,7 +335,7 @@
 	return err;
 }
 
-static int bq27200_battery_probe(struct i2c_client *client,
+static int bq27x00_battery_probe(struct i2c_client *client,
 				 const struct i2c_device_id *id)
 {
 	char *name;
@@ -267,7 +354,7 @@
 	if (retval < 0)
 		return retval;
 
-	name = kasprintf(GFP_KERNEL, "bq27200-%d", num);
+	name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);
 	if (!name) {
 		dev_err(&client->dev, "failed to allocate device name\n");
 		retval = -ENOMEM;
@@ -281,6 +368,7 @@
 		goto batt_failed_2;
 	}
 	di->id = num;
+	di->chip = id->driver_data;
 
 	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
 	if (!bus) {
@@ -293,7 +381,7 @@
 	i2c_set_clientdata(client, di);
 	di->dev = &client->dev;
 	di->bat.name = name;
-	bus->read = &bq27200_read;
+	bus->read = &bq27x00_read_i2c;
 	di->bus = bus;
 	di->client = client;
 
@@ -323,7 +411,7 @@
 	return retval;
 }
 
-static int bq27200_battery_remove(struct i2c_client *client)
+static int bq27x00_battery_remove(struct i2c_client *client)
 {
 	struct bq27x00_device_info *di = i2c_get_clientdata(client);
 
@@ -344,27 +432,28 @@
  * Module stuff
  */
 
-static const struct i2c_device_id bq27200_id[] = {
-	{ "bq27200", 0 },
+static const struct i2c_device_id bq27x00_id[] = {
+	{ "bq27200", BQ27000 },	/* bq27200 is same as bq27000, but with i2c */
+	{ "bq27500", BQ27500 },
 	{},
 };
 
-static struct i2c_driver bq27200_battery_driver = {
+static struct i2c_driver bq27x00_battery_driver = {
 	.driver = {
-		.name = "bq27200-battery",
+		.name = "bq27x00-battery",
 	},
-	.probe = bq27200_battery_probe,
-	.remove = bq27200_battery_remove,
-	.id_table = bq27200_id,
+	.probe = bq27x00_battery_probe,
+	.remove = bq27x00_battery_remove,
+	.id_table = bq27x00_id,
 };
 
 static int __init bq27x00_battery_init(void)
 {
 	int ret;
 
-	ret = i2c_add_driver(&bq27200_battery_driver);
+	ret = i2c_add_driver(&bq27x00_battery_driver);
 	if (ret)
-		printk(KERN_ERR "Unable to register BQ27200 driver\n");
+		printk(KERN_ERR "Unable to register BQ27x00 driver\n");
 
 	return ret;
 }
@@ -372,7 +461,7 @@
 
 static void __exit bq27x00_battery_exit(void)
 {
-	i2c_del_driver(&bq27200_battery_driver);
+	i2c_del_driver(&bq27x00_battery_driver);
 }
 module_exit(bq27x00_battery_exit);
 
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
index 3364198..a2e71f7 100644
--- a/drivers/power/da9030_battery.c
+++ b/drivers/power/da9030_battery.c
@@ -509,7 +509,7 @@
 
 	charger->master = pdev->dev.parent;
 
-	/* 10 seconds between monotor runs unless platfrom defines other
+	/* 10 seconds between monitor runs unless platform defines other
 	   interval */
 	charger->interval = msecs_to_jiffies(
 		(pdata->batmon_interval ? : 10) * 1000);
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
new file mode 100644
index 0000000..a1b4410
--- /dev/null
+++ b/drivers/power/max8925_power.c
@@ -0,0 +1,534 @@
+/*
+ * Battery driver for Maxim MAX8925
+ *
+ * Copyright (c) 2009-2010 Marvell International Ltd.
+ *	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/max8925.h>
+
+/* registers in GPM */
+#define MAX8925_OUT5VEN			0x54
+#define MAX8925_OUT3VEN			0x58
+#define MAX8925_CHG_CNTL1		0x7c
+
+/* bits definition */
+#define MAX8925_CHG_STAT_VSYSLOW	(1 << 0)
+#define MAX8925_CHG_STAT_MODE_MASK	(3 << 2)
+#define MAX8925_CHG_STAT_EN_MASK	(1 << 4)
+#define MAX8925_CHG_MBDET		(1 << 1)
+#define MAX8925_CHG_AC_RANGE_MASK	(3 << 6)
+
+/* registers in ADC */
+#define MAX8925_ADC_RES_CNFG1		0x06
+#define MAX8925_ADC_AVG_CNFG1		0x07
+#define MAX8925_ADC_ACQ_CNFG1		0x08
+#define MAX8925_ADC_ACQ_CNFG2		0x09
+/* 2 bytes registers in below. MSB is 1st, LSB is 2nd. */
+#define MAX8925_ADC_AUX2		0x62
+#define MAX8925_ADC_VCHG		0x64
+#define MAX8925_ADC_VBBATT		0x66
+#define MAX8925_ADC_VMBATT		0x68
+#define MAX8925_ADC_ISNS		0x6a
+#define MAX8925_ADC_THM			0x6c
+#define MAX8925_ADC_TDIE		0x6e
+#define MAX8925_CMD_AUX2		0xc8
+#define MAX8925_CMD_VCHG		0xd0
+#define MAX8925_CMD_VBBATT		0xd8
+#define MAX8925_CMD_VMBATT		0xe0
+#define MAX8925_CMD_ISNS		0xe8
+#define MAX8925_CMD_THM			0xf0
+#define MAX8925_CMD_TDIE		0xf8
+
+enum {
+	MEASURE_AUX2,
+	MEASURE_VCHG,
+	MEASURE_VBBATT,
+	MEASURE_VMBATT,
+	MEASURE_ISNS,
+	MEASURE_THM,
+	MEASURE_TDIE,
+	MEASURE_MAX,
+};
+
+struct max8925_power_info {
+	struct max8925_chip	*chip;
+	struct i2c_client	*gpm;
+	struct i2c_client	*adc;
+
+	struct power_supply	ac;
+	struct power_supply	usb;
+	struct power_supply	battery;
+	int			irq_base;
+	unsigned		ac_online:1;
+	unsigned		usb_online:1;
+	unsigned		bat_online:1;
+	unsigned		chg_mode:2;
+	unsigned		batt_detect:1;	/* detecing MB by ID pin */
+	unsigned		topoff_threshold:2;
+	unsigned		fast_charge:3;
+
+	int (*set_charger) (int);
+};
+
+static int __set_charger(struct max8925_power_info *info, int enable)
+{
+	struct max8925_chip *chip = info->chip;
+	if (enable) {
+		/* enable charger in platform */
+		if (info->set_charger)
+			info->set_charger(1);
+		/* enable charger */
+		max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 0);
+	} else {
+		/* disable charge */
+		max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
+		if (info->set_charger)
+			info->set_charger(0);
+	}
+	dev_dbg(chip->dev, "%s\n", (enable) ? "Enable charger"
+		: "Disable charger");
+	return 0;
+}
+
+static irqreturn_t max8925_charger_handler(int irq, void *data)
+{
+	struct max8925_power_info *info = (struct max8925_power_info *)data;
+	struct max8925_chip *chip = info->chip;
+
+	switch (irq - chip->irq_base) {
+	case MAX8925_IRQ_VCHG_DC_R:
+		info->ac_online = 1;
+		__set_charger(info, 1);
+		dev_dbg(chip->dev, "Adapter inserted\n");
+		break;
+	case MAX8925_IRQ_VCHG_DC_F:
+		info->ac_online = 0;
+		__set_charger(info, 0);
+		dev_dbg(chip->dev, "Adapter is removal\n");
+		break;
+	case MAX8925_IRQ_VCHG_USB_R:
+		info->usb_online = 1;
+		__set_charger(info, 1);
+		dev_dbg(chip->dev, "USB inserted\n");
+		break;
+	case MAX8925_IRQ_VCHG_USB_F:
+		info->usb_online = 0;
+		__set_charger(info, 0);
+		dev_dbg(chip->dev, "USB is removal\n");
+		break;
+	case MAX8925_IRQ_VCHG_THM_OK_F:
+		/* Battery is not ready yet */
+		dev_dbg(chip->dev, "Battery temperature is out of range\n");
+	case MAX8925_IRQ_VCHG_DC_OVP:
+		dev_dbg(chip->dev, "Error detection\n");
+		__set_charger(info, 0);
+		break;
+	case MAX8925_IRQ_VCHG_THM_OK_R:
+		/* Battery is ready now */
+		dev_dbg(chip->dev, "Battery temperature is in range\n");
+		break;
+	case MAX8925_IRQ_VCHG_SYSLOW_R:
+		/* VSYS is low */
+		dev_info(chip->dev, "Sys power is too low\n");
+		break;
+	case MAX8925_IRQ_VCHG_SYSLOW_F:
+		dev_dbg(chip->dev, "Sys power is above low threshold\n");
+		break;
+	case MAX8925_IRQ_VCHG_DONE:
+		__set_charger(info, 0);
+		dev_dbg(chip->dev, "Charging is done\n");
+		break;
+	case MAX8925_IRQ_VCHG_TOPOFF:
+		dev_dbg(chip->dev, "Charging in top-off mode\n");
+		break;
+	case MAX8925_IRQ_VCHG_TMR_FAULT:
+		__set_charger(info, 0);
+		dev_dbg(chip->dev, "Safe timer is expired\n");
+		break;
+	case MAX8925_IRQ_VCHG_RST:
+		__set_charger(info, 0);
+		dev_dbg(chip->dev, "Charger is reset\n");
+		break;
+	}
+	return IRQ_HANDLED;
+}
+
+static int start_measure(struct max8925_power_info *info, int type)
+{
+	unsigned char buf[2] = {0, 0};
+	int meas_reg = 0, ret;
+
+	switch (type) {
+	case MEASURE_VCHG:
+		meas_reg = MAX8925_ADC_VCHG;
+		break;
+	case MEASURE_VBBATT:
+		meas_reg = MAX8925_ADC_VBBATT;
+		break;
+	case MEASURE_VMBATT:
+		meas_reg = MAX8925_ADC_VMBATT;
+		break;
+	case MEASURE_ISNS:
+		meas_reg = MAX8925_ADC_ISNS;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	max8925_bulk_read(info->adc, meas_reg, 2, buf);
+	ret = (buf[0] << 4) | (buf[1] >> 4);
+
+	return ret;
+}
+
+static int max8925_ac_get_prop(struct power_supply *psy,
+			       enum power_supply_property psp,
+			       union power_supply_propval *val)
+{
+	struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
+	int ret = 0;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = info->ac_online;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		if (info->ac_online) {
+			ret = start_measure(info, MEASURE_VCHG);
+			if (ret >= 0) {
+				val->intval = ret << 1;	/* unit is mV */
+				goto out;
+			}
+		}
+		ret = -ENODATA;
+		break;
+	default:
+		ret = -ENODEV;
+		break;
+	}
+out:
+	return ret;
+}
+
+static enum power_supply_property max8925_ac_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+static int max8925_usb_get_prop(struct power_supply *psy,
+				enum power_supply_property psp,
+				union power_supply_propval *val)
+{
+	struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
+	int ret = 0;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = info->usb_online;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		if (info->usb_online) {
+			ret = start_measure(info, MEASURE_VCHG);
+			if (ret >= 0) {
+				val->intval = ret << 1;	/* unit is mV */
+				goto out;
+			}
+		}
+		ret = -ENODATA;
+		break;
+	default:
+		ret = -ENODEV;
+		break;
+	}
+out:
+	return ret;
+}
+
+static enum power_supply_property max8925_usb_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+static int max8925_bat_get_prop(struct power_supply *psy,
+				enum power_supply_property psp,
+				union power_supply_propval *val)
+{
+	struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
+	long long int tmp = 0;
+	int ret = 0;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = info->bat_online;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		if (info->bat_online) {
+			ret = start_measure(info, MEASURE_VMBATT);
+			if (ret >= 0) {
+				val->intval = ret << 1;	/* unit is mV */
+				ret = 0;
+				break;
+			}
+		}
+		ret = -ENODATA;
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		if (info->bat_online) {
+			ret = start_measure(info, MEASURE_ISNS);
+			if (ret >= 0) {
+				tmp = (long long int)ret * 6250 / 4096 - 3125;
+				ret = (int)tmp;
+				val->intval = 0;
+				if (ret > 0)
+					val->intval = ret; /* unit is mA */
+				ret = 0;
+				break;
+			}
+		}
+		ret = -ENODATA;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_TYPE:
+		if (!info->bat_online) {
+			ret = -ENODATA;
+			break;
+		}
+		ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
+		ret = (ret & MAX8925_CHG_STAT_MODE_MASK) >> 2;
+		switch (ret) {
+		case 1:
+			val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+			break;
+		case 0:
+		case 2:
+			val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+			break;
+		case 3:
+			val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+			break;
+		}
+		ret = 0;
+		break;
+	case POWER_SUPPLY_PROP_STATUS:
+		if (!info->bat_online) {
+			ret = -ENODATA;
+			break;
+		}
+		ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
+		if (info->usb_online || info->ac_online) {
+			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+			if (ret & MAX8925_CHG_STAT_EN_MASK)
+				val->intval = POWER_SUPPLY_STATUS_CHARGING;
+		} else
+			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+		ret = 0;
+		break;
+	default:
+		ret = -ENODEV;
+		break;
+	}
+	return ret;
+}
+
+static enum power_supply_property max8925_battery_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
+	POWER_SUPPLY_PROP_STATUS,
+};
+
+#define REQUEST_IRQ(_irq, _name)					\
+do {									\
+	ret = request_threaded_irq(chip->irq_base + _irq, NULL,		\
+				    max8925_charger_handler,		\
+				    IRQF_ONESHOT, _name, info);		\
+	if (ret)							\
+		dev_err(chip->dev, "Failed to request IRQ #%d: %d\n",	\
+			_irq, ret);					\
+} while (0)
+
+static __devinit int max8925_init_charger(struct max8925_chip *chip,
+					  struct max8925_power_info *info)
+{
+	int ret;
+
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_OVP, "usb-ovp");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_F, "usb-remove");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_R, "usb-insert");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_DONE, "charger-done");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff");
+	REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire");
+
+	info->ac_online = 0;
+	info->usb_online = 0;
+	info->bat_online = 0;
+	ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
+	if (ret >= 0) {
+		/*
+		 * If battery detection is enabled, ID pin of battery is
+		 * connected to MBDET pin of MAX8925. It could be used to
+		 * detect battery presence.
+		 * Otherwise, we have to assume that battery is always on.
+		 */
+		if (info->batt_detect)
+			info->bat_online = (ret & MAX8925_CHG_MBDET) ? 0 : 1;
+		else
+			info->bat_online = 1;
+		if (ret & MAX8925_CHG_AC_RANGE_MASK)
+			info->ac_online = 1;
+		else
+			info->ac_online = 0;
+	}
+	/* disable charge */
+	max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
+	/* set charging current in charge topoff mode */
+	max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 3 << 5,
+			 info->topoff_threshold << 5);
+	/* set charing current in fast charge mode */
+	max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 7, info->fast_charge);
+
+	return 0;
+}
+
+static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
+{
+	struct max8925_chip *chip = info->chip;
+	int irq;
+
+	irq = chip->irq_base + MAX8925_IRQ_VCHG_DC_OVP;
+	for (; irq <= chip->irq_base + MAX8925_IRQ_VCHG_TMR_FAULT; irq++)
+		free_irq(irq, info);
+
+	return 0;
+}
+
+static __devinit int max8925_power_probe(struct platform_device *pdev)
+{
+	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct max8925_platform_data *max8925_pdata;
+	struct max8925_power_pdata *pdata = NULL;
+	struct max8925_power_info *info;
+	int ret;
+
+	if (pdev->dev.parent->platform_data) {
+		max8925_pdata = pdev->dev.parent->platform_data;
+		pdata = max8925_pdata->power;
+	}
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform data isn't assigned to "
+			"power supply\n");
+		return -EINVAL;
+	}
+
+	info = kzalloc(sizeof(struct max8925_power_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+	info->chip = chip;
+	info->gpm = chip->i2c;
+	info->adc = chip->adc;
+
+	info->ac.name = "max8925-ac";
+	info->ac.type = POWER_SUPPLY_TYPE_MAINS;
+	info->ac.properties = max8925_ac_props;
+	info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
+	info->ac.get_property = max8925_ac_get_prop;
+	ret = power_supply_register(&pdev->dev, &info->ac);
+	if (ret)
+		goto out;
+	info->ac.dev->parent = &pdev->dev;
+
+	info->usb.name = "max8925-usb";
+	info->usb.type = POWER_SUPPLY_TYPE_USB;
+	info->usb.properties = max8925_usb_props;
+	info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
+	info->usb.get_property = max8925_usb_get_prop;
+	ret = power_supply_register(&pdev->dev, &info->usb);
+	if (ret)
+		goto out_usb;
+	info->usb.dev->parent = &pdev->dev;
+
+	info->battery.name = "max8925-battery";
+	info->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+	info->battery.properties = max8925_battery_props;
+	info->battery.num_properties = ARRAY_SIZE(max8925_battery_props);
+	info->battery.get_property = max8925_bat_get_prop;
+	ret = power_supply_register(&pdev->dev, &info->battery);
+	if (ret)
+		goto out_battery;
+	info->battery.dev->parent = &pdev->dev;
+
+	info->batt_detect = pdata->batt_detect;
+	info->topoff_threshold = pdata->topoff_threshold;
+	info->fast_charge = pdata->fast_charge;
+	info->set_charger = pdata->set_charger;
+	dev_set_drvdata(&pdev->dev, info);
+	platform_set_drvdata(pdev, info);
+
+	max8925_init_charger(chip, info);
+	return 0;
+out_battery:
+	power_supply_unregister(&info->battery);
+out_usb:
+	power_supply_unregister(&info->ac);
+out:
+	kfree(info);
+	return ret;
+}
+
+static __devexit int max8925_power_remove(struct platform_device *pdev)
+{
+	struct max8925_power_info *info = platform_get_drvdata(pdev);
+
+	if (info) {
+		power_supply_unregister(&info->ac);
+		power_supply_unregister(&info->usb);
+		power_supply_unregister(&info->battery);
+		max8925_deinit_charger(info);
+		kfree(info);
+	}
+	return 0;
+}
+
+static struct platform_driver max8925_power_driver = {
+	.probe	= max8925_power_probe,
+	.remove	= __devexit_p(max8925_power_remove),
+	.driver	= {
+		.name	= "max8925-power",
+	},
+};
+
+static int __init max8925_power_init(void)
+{
+	return platform_driver_register(&max8925_power_driver);
+}
+module_init(max8925_power_init);
+
+static void __exit max8925_power_exit(void)
+{
+	platform_driver_unregister(&max8925_power_driver);
+}
+module_exit(max8925_power_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Power supply driver for MAX8925");
+MODULE_ALIAS("platform:max8925-power");
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index ad4f071..0693902 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -190,7 +190,7 @@
 	struct wm8350_power *power = &wm8350->power;
 	struct wm8350_charger_policy *policy = power->policy;
 
-	switch (irq) {
+	switch (irq - wm8350->irq_base) {
 	case WM8350_IRQ_CHG_BAT_FAIL:
 		dev_err(wm8350->dev, "battery failed\n");
 		break;
@@ -428,18 +428,18 @@
 
 static void free_charger_irq(struct wm8350 *wm8350)
 {
-	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
-	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
-	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
-	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO);
-	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END);
-	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START);
-	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
-	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
-	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
-	wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
-	wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
-	wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350);
 }
 
 static __devinit int wm8350_power_probe(struct platform_device *pdev)
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
index 6ea3cb5..23eed35 100644
--- a/drivers/power/wm97xx_battery.c
+++ b/drivers/power/wm97xx_battery.c
@@ -26,7 +26,7 @@
 
 static DEFINE_MUTEX(bat_lock);
 static struct work_struct bat_work;
-struct mutex work_lock;
+static struct mutex work_lock;
 static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
 static struct wm97xx_batt_info *gpdata;
 static enum power_supply_property *prop;
@@ -203,7 +203,7 @@
 			goto err2;
 		ret = request_irq(gpio_to_irq(pdata->charge_gpio),
 				wm97xx_chrg_irq, IRQF_DISABLED,
-				"AC Detect", 0);
+				"AC Detect", dev);
 		if (ret)
 			goto err2;
 		props++;	/* POWER_SUPPLY_PROP_STATUS */
diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig
index cc2eb8e..1afe4e0 100644
--- a/drivers/pps/Kconfig
+++ b/drivers/pps/Kconfig
@@ -30,4 +30,6 @@
 	  messages to the system log.  Select this if you are having a
 	  problem with PPS support and want to see more of what is going on.
 
+source drivers/pps/clients/Kconfig
+
 endmenu
diff --git a/drivers/pps/Makefile b/drivers/pps/Makefile
index 19ea582..98960dd 100644
--- a/drivers/pps/Makefile
+++ b/drivers/pps/Makefile
@@ -4,5 +4,6 @@
 
 pps_core-y			:= pps.o kapi.o sysfs.o
 obj-$(CONFIG_PPS)		:= pps_core.o
+obj-y				+= clients/
 
 ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig
new file mode 100644
index 0000000..4e801bd7
--- /dev/null
+++ b/drivers/pps/clients/Kconfig
@@ -0,0 +1,25 @@
+#
+# PPS clients configuration
+#
+
+if PPS
+
+comment "PPS clients support"
+
+config PPS_CLIENT_KTIMER
+	tristate "Kernel timer client (Testing client, use for debug)"
+	help
+	  If you say yes here you get support for a PPS debugging client
+	  which uses a kernel timer to generate the PPS signal.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called pps-ktimer.
+
+config PPS_CLIENT_LDISC
+	tristate "PPS line discipline"
+	depends on PPS
+	help
+	  If you say yes here you get support for a PPS source connected
+	  with the CD (Carrier Detect) pin of your serial port.
+
+endif
diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile
new file mode 100644
index 0000000..812c9b1
--- /dev/null
+++ b/drivers/pps/clients/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for PPS clients.
+#
+
+obj-$(CONFIG_PPS_CLIENT_KTIMER)	+= pps-ktimer.o
+obj-$(CONFIG_PPS_CLIENT_LDISC)	+= pps-ldisc.o
+
+ifeq ($(CONFIG_PPS_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/pps/clients/pps-ktimer.c b/drivers/pps/clients/pps-ktimer.c
new file mode 100644
index 0000000..e7ef5b8
--- /dev/null
+++ b/drivers/pps/clients/pps-ktimer.c
@@ -0,0 +1,123 @@
+/*
+ * pps-ktimer.c -- kernel timer test client
+ *
+ *
+ * Copyright (C) 2005-2006   Rodolfo Giometti <giometti@linux.it>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/pps_kernel.h>
+
+/*
+ * Global variables
+ */
+
+static int source;
+static struct timer_list ktimer;
+
+/*
+ * The kernel timer
+ */
+
+static void pps_ktimer_event(unsigned long ptr)
+{
+	struct timespec __ts;
+	struct pps_ktime ts;
+
+	/* First of all we get the time stamp... */
+	getnstimeofday(&__ts);
+
+	pr_info("PPS event at %lu\n", jiffies);
+
+	/* ... and translate it to PPS time data struct */
+	ts.sec = __ts.tv_sec;
+	ts.nsec = __ts.tv_nsec;
+
+	pps_event(source, &ts, PPS_CAPTUREASSERT, NULL);
+
+	mod_timer(&ktimer, jiffies + HZ);
+}
+
+/*
+ * The echo function
+ */
+
+static void pps_ktimer_echo(int source, int event, void *data)
+{
+	pr_info("echo %s %s for source %d\n",
+		event & PPS_CAPTUREASSERT ? "assert" : "",
+		event & PPS_CAPTURECLEAR ? "clear" : "",
+		source);
+}
+
+/*
+ * The PPS info struct
+ */
+
+static struct pps_source_info pps_ktimer_info = {
+	.name		= "ktimer",
+	.path		= "",
+	.mode		= PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
+			  PPS_ECHOASSERT |
+			  PPS_CANWAIT | PPS_TSFMT_TSPEC,
+	.echo		= pps_ktimer_echo,
+	.owner		= THIS_MODULE,
+};
+
+/*
+ * Module staff
+ */
+
+static void __exit pps_ktimer_exit(void)
+{
+	del_timer_sync(&ktimer);
+	pps_unregister_source(source);
+
+	pr_info("ktimer PPS source unregistered\n");
+}
+
+static int __init pps_ktimer_init(void)
+{
+	int ret;
+
+	ret = pps_register_source(&pps_ktimer_info,
+				PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
+	if (ret < 0) {
+		printk(KERN_ERR "cannot register ktimer source\n");
+		return ret;
+	}
+	source = ret;
+
+	setup_timer(&ktimer, pps_ktimer_event, 0);
+	mod_timer(&ktimer, jiffies + HZ);
+
+	pr_info("ktimer PPS source registered at %d\n", source);
+
+	return  0;
+}
+
+module_init(pps_ktimer_init);
+module_exit(pps_ktimer_exit);
+
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("dummy PPS source by using a kernel timer (just for debug)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pps/clients/pps-ldisc.c b/drivers/pps/clients/pps-ldisc.c
new file mode 100644
index 0000000..8e1932d
--- /dev/null
+++ b/drivers/pps/clients/pps-ldisc.c
@@ -0,0 +1,154 @@
+/*
+ * pps-ldisc.c -- PPS line discipline
+ *
+ *
+ * Copyright (C) 2008	Rodolfo Giometti <giometti@linux.it>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/serial_core.h>
+#include <linux/tty.h>
+#include <linux/pps_kernel.h>
+
+#define PPS_TTY_MAGIC		0x0001
+
+static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status,
+				struct timespec *ts)
+{
+	int id = (long)tty->disc_data;
+	struct timespec __ts;
+	struct pps_ktime pps_ts;
+
+	/* First of all we get the time stamp... */
+	getnstimeofday(&__ts);
+
+	/* Does caller give us a timestamp? */
+	if (ts) {	/* Yes. Let's use it! */
+		pps_ts.sec = ts->tv_sec;
+		pps_ts.nsec = ts->tv_nsec;
+	} else {	/* No. Do it ourself! */
+		pps_ts.sec = __ts.tv_sec;
+		pps_ts.nsec = __ts.tv_nsec;
+	}
+
+	/* Now do the PPS event report */
+	pps_event(id, &pps_ts, status ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR,
+			NULL);
+
+	pr_debug("PPS %s at %lu on source #%d\n",
+			status ? "assert" : "clear", jiffies, id);
+}
+
+static int (*alias_n_tty_open)(struct tty_struct *tty);
+
+static int pps_tty_open(struct tty_struct *tty)
+{
+	struct pps_source_info info;
+	struct tty_driver *drv = tty->driver;
+	int index = tty->index + drv->name_base;
+	int ret;
+
+	info.owner = THIS_MODULE;
+	info.dev = NULL;
+	snprintf(info.name, PPS_MAX_NAME_LEN, "%s%d", drv->driver_name, index);
+	snprintf(info.path, PPS_MAX_NAME_LEN, "/dev/%s%d", drv->name, index);
+	info.mode = PPS_CAPTUREBOTH | \
+			PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \
+			PPS_CANWAIT | PPS_TSFMT_TSPEC;
+
+	ret = pps_register_source(&info, PPS_CAPTUREBOTH | \
+				PPS_OFFSETASSERT | PPS_OFFSETCLEAR);
+	if (ret < 0) {
+		pr_err("cannot register PPS source \"%s\"\n", info.path);
+		return ret;
+	}
+	tty->disc_data = (void *)(long)ret;
+
+	/* Should open N_TTY ldisc too */
+	ret = alias_n_tty_open(tty);
+	if (ret < 0)
+		pps_unregister_source((long)tty->disc_data);
+
+	pr_info("PPS source #%d \"%s\" added\n", ret, info.path);
+
+	return 0;
+}
+
+static void (*alias_n_tty_close)(struct tty_struct *tty);
+
+static void pps_tty_close(struct tty_struct *tty)
+{
+	int id = (long)tty->disc_data;
+
+	pps_unregister_source(id);
+	alias_n_tty_close(tty);
+
+	pr_info("PPS source #%d removed\n", id);
+}
+
+static struct tty_ldisc_ops pps_ldisc_ops;
+
+/*
+ * Module stuff
+ */
+
+static int __init pps_tty_init(void)
+{
+	int err;
+
+	/* Inherit the N_TTY's ops */
+	n_tty_inherit_ops(&pps_ldisc_ops);
+
+	/* Save N_TTY's open()/close() methods */
+	alias_n_tty_open = pps_ldisc_ops.open;
+	alias_n_tty_close = pps_ldisc_ops.close;
+
+	/* Init PPS_TTY data */
+	pps_ldisc_ops.owner = THIS_MODULE;
+	pps_ldisc_ops.magic = PPS_TTY_MAGIC;
+	pps_ldisc_ops.name = "pps_tty";
+	pps_ldisc_ops.dcd_change = pps_tty_dcd_change;
+	pps_ldisc_ops.open = pps_tty_open;
+	pps_ldisc_ops.close = pps_tty_close;
+
+	err = tty_register_ldisc(N_PPS, &pps_ldisc_ops);
+	if (err)
+		pr_err("can't register PPS line discipline\n");
+	else
+		pr_info("PPS line discipline registered\n");
+
+	return err;
+}
+
+static void __exit pps_tty_cleanup(void)
+{
+	int err;
+
+	err = tty_unregister_ldisc(N_PPS);
+	if (err)
+		pr_err("can't unregister PPS line discipline\n");
+	else
+		pr_info("PPS line discipline removed\n");
+}
+
+module_init(pps_tty_init);
+module_exit(pps_tty_cleanup);
+
+MODULE_ALIAS_LDISC(N_PPS);
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("PPS TTY device driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 0471955..5fb83e2 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -11,15 +11,17 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
-#include <linux/mfd/88pm8607.h>
+#include <linux/mfd/88pm860x.h>
 
 struct pm8607_regulator_info {
 	struct regulator_desc	desc;
-	struct pm8607_chip	*chip;
+	struct pm860x_chip	*chip;
 	struct regulator_dev	*regulator;
+	struct i2c_client	*i2c;
 
 	int	min_uV;
 	int	max_uV;
@@ -46,7 +48,6 @@
 static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
 {
 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-	uint8_t chip_id = info->chip->chip_id;
 	int ret = -EINVAL;
 
 	switch (info->desc.id) {
@@ -88,79 +89,29 @@
 	case PM8607_ID_LDO2:
 	case PM8607_ID_LDO3:
 	case PM8607_ID_LDO9:
-		switch (chip_id) {
-		case PM8607_CHIP_A0:
-		case PM8607_CHIP_A1:
-			ret = (index < 3) ? (index * 50000 + 1800000) :
-				((index < 8) ? (index * 50000 + 2550000) :
-				 -EINVAL);
-			break;
-		case PM8607_CHIP_B0:
-			ret = (index < 3) ? (index * 50000 + 1800000) :
-				((index < 7) ? (index * 50000 + 2550000) :
-				3300000);
-			break;
-		}
+		ret = (index < 3) ? (index * 50000 + 1800000) :
+			((index < 7) ? (index * 50000 + 2550000) :
+			3300000);
 		break;
 	case PM8607_ID_LDO4:
-		switch (chip_id) {
-		case PM8607_CHIP_A0:
-		case PM8607_CHIP_A1:
-			ret = (index < 3) ? (index * 50000 + 1800000) :
-				((index < 8) ? (index * 50000 + 2550000) :
-				 -EINVAL);
-			break;
-		case PM8607_CHIP_B0:
-			ret = (index < 3) ? (index * 50000 + 1800000) :
-				((index < 6) ? (index * 50000 + 2550000) :
-				((index == 6) ? 2900000 : 3300000));
-			break;
-		}
+		ret = (index < 3) ? (index * 50000 + 1800000) :
+			((index < 6) ? (index * 50000 + 2550000) :
+			((index == 6) ? 2900000 : 3300000));
 		break;
 	case PM8607_ID_LDO6:
-		switch (chip_id) {
-		case PM8607_CHIP_A0:
-		case PM8607_CHIP_A1:
-			ret = (index < 3) ? (index * 50000 + 1800000) :
-				((index < 8) ? (index * 50000 + 2450000) :
-				-EINVAL);
-			break;
-		case PM8607_CHIP_B0:
-			ret = (index < 2) ? (index * 50000 + 1800000) :
-				((index < 7) ? (index * 50000 + 2500000) :
-				3300000);
-			break;
-		}
+		ret = (index < 2) ? (index * 50000 + 1800000) :
+			((index < 7) ? (index * 50000 + 2500000) :
+			3300000);
 		break;
 	case PM8607_ID_LDO10:
-		switch (chip_id) {
-		case PM8607_CHIP_A0:
-		case PM8607_CHIP_A1:
-			ret = (index < 3) ? (index * 50000 + 1800000) :
-				((index < 8) ? (index * 50000 + 2550000) :
-				1200000);
-			break;
-		case PM8607_CHIP_B0:
-			ret = (index < 3) ? (index * 50000 + 1800000) :
-				((index < 7) ? (index * 50000 + 2550000) :
-				((index == 7) ? 3300000 : 1200000));
-			break;
-		}
+		ret = (index < 3) ? (index * 50000 + 1800000) :
+			((index < 7) ? (index * 50000 + 2550000) :
+			((index == 7) ? 3300000 : 1200000));
 		break;
 	case PM8607_ID_LDO14:
-		switch (chip_id) {
-		case PM8607_CHIP_A0:
-		case PM8607_CHIP_A1:
-			ret = (index < 3) ? (index * 50000 + 1800000) :
-				((index < 8) ? (index * 50000 + 2550000) :
-				 -EINVAL);
-			break;
-		case PM8607_CHIP_B0:
-			ret = (index < 2) ? (index * 50000 + 1800000) :
-				((index < 7) ? (index * 50000 + 2600000) :
-				3300000);
-			break;
-		}
+		ret = (index < 2) ? (index * 50000 + 1800000) :
+			((index < 7) ? (index * 50000 + 2600000) :
+			3300000);
 		break;
 	}
 	return ret;
@@ -169,7 +120,6 @@
 static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
 {
 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-	uint8_t chip_id = info->chip->chip_id;
 	int val = -ENOENT;
 	int ret;
 
@@ -254,161 +204,77 @@
 	case PM8607_ID_LDO2:
 	case PM8607_ID_LDO3:
 	case PM8607_ID_LDO9:
-		switch (chip_id) {
-		case PM8607_CHIP_A0:
-		case PM8607_CHIP_A1:
-			if (min_uV < 2700000)	/* 1800mV ~ 1900mV / 50mV */
-				if (min_uV <= 1800000)
-					val = 0;
-				else if (min_uV <= 1900000)
-					val = (min_uV - 1750001) / 50000;
-				else
-					val = 3;	/* 2700mV */
-			else {			/* 2700mV ~ 2900mV / 50mV */
-				if (min_uV <= 2900000) {
-					val = (min_uV - 2650001) / 50000;
-					val += 3;
-				} else
-					val = -EINVAL;
-			}
-			break;
-		case PM8607_CHIP_B0:
-			if (min_uV < 2700000) {	/* 1800mV ~ 1900mV / 50mV */
-				if (min_uV <= 1800000)
-					val = 0;
-				else if (min_uV <= 1900000)
-					val = (min_uV - 1750001) / 50000;
-				else
-					val = 3;	/* 2700mV */
-			} else {		 /* 2700mV ~ 2850mV / 50mV */
-				if (min_uV <= 2850000) {
-					val = (min_uV - 2650001) / 50000;
-					val += 3;
-				} else if (min_uV <= 3300000)
-					val = 7;
-				else
-					val = -EINVAL;
-			}
-			break;
+		if (min_uV < 2700000) {	/* 1800mV ~ 1900mV / 50mV */
+			if (min_uV <= 1800000)
+				val = 0;
+			else if (min_uV <= 1900000)
+				val = (min_uV - 1750001) / 50000;
+			else
+				val = 3;	/* 2700mV */
+		} else {		 /* 2700mV ~ 2850mV / 50mV */
+			if (min_uV <= 2850000) {
+				val = (min_uV - 2650001) / 50000;
+				val += 3;
+			} else if (min_uV <= 3300000)
+				val = 7;
+			else
+				val = -EINVAL;
 		}
 		break;
 	case PM8607_ID_LDO4:
-		switch (chip_id) {
-		case PM8607_CHIP_A0:
-		case PM8607_CHIP_A1:
-			if (min_uV < 2700000)	/* 1800mV ~ 1900mV / 50mV */
-				if (min_uV <= 1800000)
-					val = 0;
-				else if (min_uV <= 1900000)
-					val = (min_uV - 1750001) / 50000;
-				else
-					val = 3;	/* 2700mV */
-			else {			/* 2700mV ~ 2900mV / 50mV */
-				if (min_uV <= 2900000) {
-					val = (min_uV - 2650001) / 50000;
-					val += 3;
-				} else
-					val = -EINVAL;
-			}
-			break;
-		case PM8607_CHIP_B0:
-			if (min_uV < 2700000) {	/* 1800mV ~ 1900mV / 50mV */
-				if (min_uV <= 1800000)
-					val = 0;
-				else if (min_uV <= 1900000)
-					val = (min_uV - 1750001) / 50000;
-				else
-					val = 3;	/* 2700mV */
-			} else {		 /* 2700mV ~ 2800mV / 50mV */
-				if (min_uV <= 2850000) {
-					val = (min_uV - 2650001) / 50000;
-					val += 3;
-				} else if (min_uV <= 2900000)
-					val = 6;
-				else if (min_uV <= 3300000)
-					val = 7;
-				else
-					val = -EINVAL;
-			}
-			break;
+		if (min_uV < 2700000) {	/* 1800mV ~ 1900mV / 50mV */
+			if (min_uV <= 1800000)
+				val = 0;
+			else if (min_uV <= 1900000)
+				val = (min_uV - 1750001) / 50000;
+			else
+				val = 3;	/* 2700mV */
+		} else {		 /* 2700mV ~ 2800mV / 50mV */
+			if (min_uV <= 2850000) {
+				val = (min_uV - 2650001) / 50000;
+				val += 3;
+			} else if (min_uV <= 2900000)
+				val = 6;
+			else if (min_uV <= 3300000)
+				val = 7;
+			else
+				val = -EINVAL;
 		}
 		break;
 	case PM8607_ID_LDO6:
-		switch (chip_id) {
-		case PM8607_CHIP_A0:
-		case PM8607_CHIP_A1:
-			if (min_uV < 2600000) {	/* 1800mV ~ 1900mV / 50mV */
-				if (min_uV <= 1800000)
-					val = 0;
-				else if (min_uV <= 1900000)
-					val = (min_uV - 1750001) / 50000;
-				else
-					val = 3;	/* 2600mV */
-			} else {		/* 2600mV ~ 2800mV / 50mV */
-				if (min_uV <= 2800000) {
-					val = (min_uV - 2550001) / 50000;
-					val += 3;
-				} else
-					val = -EINVAL;
-			}
-			break;
-		case PM8607_CHIP_B0:
-			if (min_uV < 2600000) {	/* 1800mV ~ 1850mV / 50mV */
-				if (min_uV <= 1800000)
-					val = 0;
-				else if (min_uV <= 1850000)
-					val = (min_uV - 1750001) / 50000;
-				else
-					val = 2;	/* 2600mV */
-			} else {		/* 2600mV ~ 2800mV / 50mV */
-				if (min_uV <= 2800000) {
-					val = (min_uV - 2550001) / 50000;
-					val += 2;
-				} else if (min_uV <= 3300000)
-					val = 7;
-				else
-					val = -EINVAL;
-			}
-			break;
+		if (min_uV < 2600000) {	/* 1800mV ~ 1850mV / 50mV */
+			if (min_uV <= 1800000)
+				val = 0;
+			else if (min_uV <= 1850000)
+				val = (min_uV - 1750001) / 50000;
+			else
+				val = 2;	/* 2600mV */
+		} else {		/* 2600mV ~ 2800mV / 50mV */
+			if (min_uV <= 2800000) {
+				val = (min_uV - 2550001) / 50000;
+				val += 2;
+			} else if (min_uV <= 3300000)
+				val = 7;
+			else
+				val = -EINVAL;
 		}
 		break;
 	case PM8607_ID_LDO14:
-		switch (chip_id) {
-		case PM8607_CHIP_A0:
-		case PM8607_CHIP_A1:
-			if (min_uV < 2700000) {	/* 1800mV ~ 1900mV / 50mV */
-				if (min_uV <= 1800000)
-					val = 0;
-				else if (min_uV <= 1900000)
-					val = (min_uV - 1750001) / 50000;
-				else
-					val = 3;	/* 2700mV */
-			} else {		 /* 2700mV ~ 2900mV / 50mV */
-				if (min_uV <= 2900000) {
-					val = (min_uV - 2650001) / 50000;
-					val += 3;
-				} else
-					val = -EINVAL;
-			}
-			break;
-		case PM8607_CHIP_B0:
-			if (min_uV < 2700000) {	/* 1800mV ~ 1850mV / 50mV */
-				if (min_uV <= 1800000)
-					val = 0;
-				else if (min_uV <= 1850000)
-					val = (min_uV - 1750001) / 50000;
-				else
-					val = 2;	/* 2700mV */
-			} else {		 /* 2700mV ~ 2900mV / 50mV */
-				if (min_uV <= 2900000) {
-					val = (min_uV - 2650001) / 50000;
-					val += 2;
-				} else if (min_uV <= 3300000)
-					val = 7;
-				else
-					val = -EINVAL;
-			}
-			break;
+		if (min_uV < 2700000) {	/* 1800mV ~ 1850mV / 50mV */
+			if (min_uV <= 1800000)
+				val = 0;
+			else if (min_uV <= 1850000)
+				val = (min_uV - 1750001) / 50000;
+			else
+				val = 2;	/* 2700mV */
+		} else {		 /* 2700mV ~ 2900mV / 50mV */
+			if (min_uV <= 2900000) {
+				val = (min_uV - 2650001) / 50000;
+				val += 2;
+			} else if (min_uV <= 3300000)
+				val = 7;
+			else
+				val = -EINVAL;
 		}
 		break;
 	}
@@ -428,7 +294,6 @@
 			      int min_uV, int max_uV)
 {
 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-	struct pm8607_chip *chip = info->chip;
 	uint8_t val, mask;
 	int ret;
 
@@ -443,13 +308,13 @@
 	val = (uint8_t)(ret << info->vol_shift);
 	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
 
-	ret = pm8607_set_bits(chip, info->vol_reg, mask, val);
+	ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, val);
 	if (ret)
 		return ret;
 	switch (info->desc.id) {
 	case PM8607_ID_BUCK1:
 	case PM8607_ID_BUCK3:
-		ret = pm8607_set_bits(chip, info->update_reg,
+		ret = pm860x_set_bits(info->i2c, info->update_reg,
 				      1 << info->update_bit,
 				      1 << info->update_bit);
 		break;
@@ -460,11 +325,10 @@
 static int pm8607_get_voltage(struct regulator_dev *rdev)
 {
 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-	struct pm8607_chip *chip = info->chip;
 	uint8_t val, mask;
 	int ret;
 
-	ret = pm8607_reg_read(chip, info->vol_reg);
+	ret = pm860x_reg_read(info->i2c, info->vol_reg);
 	if (ret < 0)
 		return ret;
 
@@ -477,9 +341,8 @@
 static int pm8607_enable(struct regulator_dev *rdev)
 {
 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-	struct pm8607_chip *chip = info->chip;
 
-	return pm8607_set_bits(chip, info->enable_reg,
+	return pm860x_set_bits(info->i2c, info->enable_reg,
 			       1 << info->enable_bit,
 			       1 << info->enable_bit);
 }
@@ -487,19 +350,17 @@
 static int pm8607_disable(struct regulator_dev *rdev)
 {
 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-	struct pm8607_chip *chip = info->chip;
 
-	return pm8607_set_bits(chip, info->enable_reg,
+	return pm860x_set_bits(info->i2c, info->enable_reg,
 			       1 << info->enable_bit, 0);
 }
 
 static int pm8607_is_enabled(struct regulator_dev *rdev)
 {
 	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
-	struct pm8607_chip *chip = info->chip;
 	int ret;
 
-	ret = pm8607_reg_read(chip, info->enable_reg);
+	ret = pm860x_reg_read(info->i2c, info->enable_reg);
 	if (ret < 0)
 		return ret;
 
@@ -589,8 +450,8 @@
 
 static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
 {
-	struct pm8607_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct pm8607_platform_data *pdata = chip->dev->platform_data;
+	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pm860x_platform_data *pdata = chip->dev->platform_data;
 	struct pm8607_regulator_info *info = NULL;
 
 	info = find_regulator_info(pdev->id);
@@ -599,6 +460,7 @@
 		return -EINVAL;
 	}
 
+	info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
 	info->chip = chip;
 
 	info->regulator = regulator_register(&info->desc, &pdev->dev,
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 262f62e..04f2e08 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -27,6 +27,17 @@
 	help
 	  Say yes here to enable debugging support.
 
+config REGULATOR_DUMMY
+	bool "Provide a dummy regulator if regulator lookups fail"
+	help
+	  If this option is enabled then when a regulator lookup fails
+	  and the board has not specified that it has provided full
+	  constraints then the regulator core will provide an always
+	  enabled dummy regulator will be provided, allowing consumer
+	  drivers to continue.
+
+	  A warning will be generated when this substitution is done.
+
 config REGULATOR_FIXED_VOLTAGE
 	tristate "Fixed voltage regulator support"
 	help
@@ -69,6 +80,13 @@
 	  regulator via I2C bus. The provided regulator is suitable
 	  for PXA27x chips to control VCC_CORE and VCC_USIM voltages.
 
+config REGULATOR_MAX8649
+	tristate "Maxim 8649 voltage regulator"
+	depends on I2C
+	help
+	  This driver controls a Maxim 8649 voltage output regulator via
+	  I2C bus.
+
 config REGULATOR_MAX8660
 	tristate "Maxim 8660/8661 voltage regulator"
 	depends on I2C
@@ -76,6 +94,12 @@
 	  This driver controls a Maxim 8660/8661 voltage output
 	  regulator via I2C bus.
 
+config REGULATOR_MAX8925
+	tristate "Maxim MAX8925 Power Management IC"
+	depends on MFD_MAX8925
+	help
+	  Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC.
+
 config REGULATOR_TWL4030
 	bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC"
 	depends on TWL4030_CORE
@@ -91,19 +115,26 @@
 	  of PMIC devices.
 
 config REGULATOR_WM8350
-	tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC"
+	tristate "Wolfson Microelectronics WM8350 AudioPlus PMIC"
 	depends on MFD_WM8350
 	help
 	  This driver provides support for the voltage and current regulators
           of the WM8350 AudioPlus PMIC.
 
 config REGULATOR_WM8400
-	tristate "Wolfson Microelectroncis WM8400 AudioPlus PMIC"
+	tristate "Wolfson Microelectronics WM8400 AudioPlus PMIC"
 	depends on MFD_WM8400
 	help
 	  This driver provides support for the voltage regulators of the
 	  WM8400 AudioPlus PMIC.
 
+config REGULATOR_WM8994
+	tristate "Wolfson Microelectronics WM8994 CODEC"
+	depends on MFD_WM8994
+	help
+	  This driver provides support for the voltage regulators on the
+	  WM8994 CODEC.
+
 config REGULATOR_DA903X
 	tristate "Support regulators on Dialog Semiconductor DA9030/DA9034 PMIC"
 	depends on PMIC_DA903X
@@ -166,7 +197,7 @@
 
 config REGULATOR_88PM8607
 	bool "Marvell 88PM8607 Power regulators"
-	depends on MFD_88PM8607=y
+	depends on MFD_88PM860X=y
 	help
 	  This driver supports 88PM8607 voltage regulator chips.
 
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index b3c806c..4e7feec 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -9,15 +9,19 @@
 obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
 
 obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
+obj-$(CONFIG_REGULATOR_DUMMY) += dummy.o
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
 obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_MAX8649)	+= max8649.o
 obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
+obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
 obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
 obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
+obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index b349db4..7de9509 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -561,7 +561,7 @@
  * for all the different regulators.
  */
 
-static int __init ab3100_regulators_probe(struct platform_device *pdev)
+static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
 {
 	struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
 	struct ab3100 *ab3100 = platform_get_drvdata(pdev);
@@ -641,7 +641,7 @@
 	return 0;
 }
 
-static int __exit ab3100_regulators_remove(struct platform_device *pdev)
+static int __devexit ab3100_regulators_remove(struct platform_device *pdev)
 {
 	int i;
 
@@ -659,7 +659,7 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = ab3100_regulators_probe,
-	.remove = __exit_p(ab3100_regulators_remove),
+	.remove = __devexit_p(ab3100_regulators_remove),
 };
 
 static __init int ab3100_regulators_init(void)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index b60a4c9..c7bbe30 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -19,10 +19,13 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/suspend.h>
+#include <linux/delay.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 
+#include "dummy.h"
+
 #define REGULATOR_VERSION "0.5"
 
 static DEFINE_MUTEX(regulator_list_mutex);
@@ -1084,6 +1087,13 @@
 	return NULL;
 }
 
+static int _regulator_get_enable_time(struct regulator_dev *rdev)
+{
+	if (!rdev->desc->ops->enable_time)
+		return 0;
+	return rdev->desc->ops->enable_time(rdev);
+}
+
 /* Internal regulator request function */
 static struct regulator *_regulator_get(struct device *dev, const char *id,
 					int exclusive)
@@ -1115,6 +1125,22 @@
 			goto found;
 		}
 	}
+
+#ifdef CONFIG_REGULATOR_DUMMY
+	if (!devname)
+		devname = "deviceless";
+
+	/* If the board didn't flag that it was fully constrained then
+	 * substitute in a dummy regulator so consumers can continue.
+	 */
+	if (!has_full_constraints) {
+		pr_warning("%s supply %s not found, using dummy regulator\n",
+			   devname, id);
+		rdev = dummy_regulator_rdev;
+		goto found;
+	}
+#endif
+
 	mutex_unlock(&regulator_list_mutex);
 	return regulator;
 
@@ -1251,7 +1277,7 @@
 /* locks held by regulator_enable() */
 static int _regulator_enable(struct regulator_dev *rdev)
 {
-	int ret;
+	int ret, delay;
 
 	/* do we need to enable the supply regulator first */
 	if (rdev->supply) {
@@ -1275,13 +1301,34 @@
 			if (!_regulator_can_change_status(rdev))
 				return -EPERM;
 
-			if (rdev->desc->ops->enable) {
-				ret = rdev->desc->ops->enable(rdev);
-				if (ret < 0)
-					return ret;
-			} else {
+			if (!rdev->desc->ops->enable)
 				return -EINVAL;
+
+			/* Query before enabling in case configuration
+			 * dependant.  */
+			ret = _regulator_get_enable_time(rdev);
+			if (ret >= 0) {
+				delay = ret;
+			} else {
+				printk(KERN_WARNING
+					"%s: enable_time() failed for %s: %d\n",
+					__func__, rdev_get_name(rdev),
+					ret);
+				delay = 0;
 			}
+
+			/* Allow the regulator to ramp; it would be useful
+			 * to extend this for bulk operations so that the
+			 * regulators can ramp together.  */
+			ret = rdev->desc->ops->enable(rdev);
+			if (ret < 0)
+				return ret;
+
+			if (delay >= 1000)
+				mdelay(delay / 1000);
+			else if (delay)
+				udelay(delay);
+
 		} else if (ret < 0) {
 			printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n",
 			       __func__, rdev_get_name(rdev), ret);
@@ -1341,6 +1388,9 @@
 				       __func__, rdev_get_name(rdev));
 				return ret;
 			}
+
+			_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
+					     NULL);
 		}
 
 		/* decrease our supplies ref count and disable if required */
@@ -1399,8 +1449,8 @@
 			return ret;
 		}
 		/* notify other consumers that power has been forced off */
-		_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE,
-			NULL);
+		_notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE |
+			REGULATOR_EVENT_DISABLE, NULL);
 	}
 
 	/* decrease our supplies ref count and disable if required */
@@ -1434,9 +1484,9 @@
 
 static int _regulator_is_enabled(struct regulator_dev *rdev)
 {
-	/* sanity check */
+	/* If we don't know then assume that the regulator is always on */
 	if (!rdev->desc->ops->is_enabled)
-		return -EINVAL;
+		return 1;
 
 	return rdev->desc->ops->is_enabled(rdev);
 }
@@ -2451,8 +2501,15 @@
 
 static int __init regulator_init(void)
 {
+	int ret;
+
 	printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION);
-	return class_register(&regulator_class);
+
+	ret = class_register(&regulator_class);
+
+	regulator_dummy_init();
+
+	return ret;
 }
 
 /* init early to allow our consumers to complete system booting */
diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c
new file mode 100644
index 0000000..c7410bd
--- /dev/null
+++ b/drivers/regulator/dummy.c
@@ -0,0 +1,66 @@
+/*
+ * dummy.c
+ *
+ * Copyright 2010 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This is useful for systems with mixed controllable and
+ * non-controllable regulators, as well as for allowing testing on
+ * systems with no controllable regulators.
+ */
+
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include "dummy.h"
+
+struct regulator_dev *dummy_regulator_rdev;
+
+static struct regulator_init_data dummy_initdata;
+
+static struct regulator_ops dummy_ops;
+
+static struct regulator_desc dummy_desc = {
+	.name = "dummy",
+	.id = -1,
+	.type = REGULATOR_VOLTAGE,
+	.owner = THIS_MODULE,
+	.ops = &dummy_ops,
+};
+
+static struct platform_device *dummy_pdev;
+
+void __init regulator_dummy_init(void)
+{
+	int ret;
+
+	dummy_pdev = platform_device_alloc("reg-dummy", -1);
+	if (!dummy_pdev) {
+		pr_err("Failed to allocate dummy regulator device\n");
+		return;
+	}
+
+	ret = platform_device_add(dummy_pdev);
+	if (ret != 0) {
+		pr_err("Failed to register dummy regulator device: %d\n", ret);
+		platform_device_put(dummy_pdev);
+		return;
+	}
+
+	dummy_regulator_rdev = regulator_register(&dummy_desc, NULL,
+						  &dummy_initdata, NULL);
+	if (IS_ERR(dummy_regulator_rdev)) {
+		ret = PTR_ERR(dummy_regulator_rdev);
+		pr_err("Failed to register regulator: %d\n", ret);
+		platform_device_unregister(dummy_pdev);
+		return;
+	}
+}
diff --git a/drivers/regulator/dummy.h b/drivers/regulator/dummy.h
new file mode 100644
index 0000000..3921c0e
--- /dev/null
+++ b/drivers/regulator/dummy.h
@@ -0,0 +1,31 @@
+/*
+ * dummy.h
+ *
+ * Copyright 2010 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This is useful for systems with mixed controllable and
+ * non-controllable regulators, as well as for allowing testing on
+ * systems with no controllable regulators.
+ */
+
+#ifndef _DUMMY_H
+#define _DUMMY_H
+
+struct regulator_dev;
+
+extern struct regulator_dev *dummy_regulator_rdev;
+
+#ifdef CONFIG_REGULATOR_DUMMY
+void __init regulator_dummy_init(void);
+#else
+static inline void regulator_dummy_init(void) { }
+#endif
+
+#endif
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index f9f516a..d11f762 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -24,14 +24,16 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/fixed.h>
 #include <linux/gpio.h>
+#include <linux/delay.h>
 
 struct fixed_voltage_data {
 	struct regulator_desc desc;
 	struct regulator_dev *dev;
 	int microvolts;
 	int gpio;
-	unsigned enable_high:1;
-	unsigned is_enabled:1;
+	unsigned startup_delay;
+	bool enable_high;
+	bool is_enabled;
 };
 
 static int fixed_voltage_is_enabled(struct regulator_dev *dev)
@@ -47,7 +49,7 @@
 
 	if (gpio_is_valid(data->gpio)) {
 		gpio_set_value_cansleep(data->gpio, data->enable_high);
-		data->is_enabled = 1;
+		data->is_enabled = true;
 	}
 
 	return 0;
@@ -59,12 +61,19 @@
 
 	if (gpio_is_valid(data->gpio)) {
 		gpio_set_value_cansleep(data->gpio, !data->enable_high);
-		data->is_enabled = 0;
+		data->is_enabled = false;
 	}
 
 	return 0;
 }
 
+static int fixed_voltage_enable_time(struct regulator_dev *dev)
+{
+	struct fixed_voltage_data *data = rdev_get_drvdata(dev);
+
+	return data->startup_delay;
+}
+
 static int fixed_voltage_get_voltage(struct regulator_dev *dev)
 {
 	struct fixed_voltage_data *data = rdev_get_drvdata(dev);
@@ -87,11 +96,12 @@
 	.is_enabled = fixed_voltage_is_enabled,
 	.enable = fixed_voltage_enable,
 	.disable = fixed_voltage_disable,
+	.enable_time = fixed_voltage_enable_time,
 	.get_voltage = fixed_voltage_get_voltage,
 	.list_voltage = fixed_voltage_list_voltage,
 };
 
-static int regulator_fixed_voltage_probe(struct platform_device *pdev)
+static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
 {
 	struct fixed_voltage_config *config = pdev->dev.platform_data;
 	struct fixed_voltage_data *drvdata;
@@ -117,6 +127,7 @@
 
 	drvdata->microvolts = config->microvolts;
 	drvdata->gpio = config->gpio;
+	drvdata->startup_delay = config->startup_delay;
 
 	if (gpio_is_valid(config->gpio)) {
 		drvdata->enable_high = config->enable_high;
@@ -163,7 +174,7 @@
 		/* Regulator without GPIO control is considered
 		 * always enabled
 		 */
-		drvdata->is_enabled = 1;
+		drvdata->is_enabled = true;
 	}
 
 	drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
@@ -191,7 +202,7 @@
 	return ret;
 }
 
-static int regulator_fixed_voltage_remove(struct platform_device *pdev)
+static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
 {
 	struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
 
@@ -205,10 +216,11 @@
 }
 
 static struct platform_driver regulator_fixed_voltage_driver = {
-	.probe		= regulator_fixed_voltage_probe,
-	.remove		= regulator_fixed_voltage_remove,
+	.probe		= reg_fixed_voltage_probe,
+	.remove		= __devexit_p(reg_fixed_voltage_remove),
 	.driver		= {
 		.name		= "reg-fixed-voltage",
+		.owner		= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 4f33a0f..f5532ed 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -54,7 +54,7 @@
 #define LP3971_BUCK2_BASE 0x29
 #define LP3971_BUCK3_BASE 0x32
 
-const static int buck_base_addr[] = {
+static const int buck_base_addr[] = {
 	LP3971_BUCK1_BASE,
 	LP3971_BUCK2_BASE,
 	LP3971_BUCK3_BASE,
@@ -63,7 +63,7 @@
 #define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])
 #define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1)
 
-const static int buck_voltage_map[] = {
+static const int buck_voltage_map[] = {
 	   0,  800,  850,  900,  950, 1000, 1050, 1100,
 	1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
 	1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
@@ -96,17 +96,17 @@
 #define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2)
 #define LDO_VOL_CONTR_MASK 0x0f
 
-const static int ldo45_voltage_map[] = {
+static const int ldo45_voltage_map[] = {
 	1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
 	1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
 };
 
-const static int ldo123_voltage_map[] = {
+static const int ldo123_voltage_map[] = {
 	1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
 	2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
 };
 
-const static int *ldo_voltage_map[] = {
+static const int *ldo_voltage_map[] = {
 	ldo123_voltage_map, /* LDO1 */
 	ldo123_voltage_map, /* LDO2 */
 	ldo123_voltage_map, /* LDO3 */
@@ -431,20 +431,20 @@
 	return ret;
 }
 
-static int setup_regulators(struct lp3971 *lp3971,
-	struct lp3971_platform_data *pdata)
+static int __devinit setup_regulators(struct lp3971 *lp3971,
+				      struct lp3971_platform_data *pdata)
 {
 	int i, err;
-	int num_regulators = pdata->num_regulators;
-	lp3971->num_regulators = num_regulators;
-	lp3971->rdev = kzalloc(sizeof(struct regulator_dev *) * num_regulators,
-		GFP_KERNEL);
+
+	lp3971->num_regulators = pdata->num_regulators;
+	lp3971->rdev = kcalloc(pdata->num_regulators,
+				sizeof(struct regulator_dev *), GFP_KERNEL);
 
 	/* Instantiate the regulators */
-	for (i = 0; i < num_regulators; i++) {
-		int id = pdata->regulators[i].id;
-		lp3971->rdev[i] = regulator_register(&regulators[id],
-			lp3971->dev, pdata->regulators[i].initdata, lp3971);
+	for (i = 0; i < pdata->num_regulators; i++) {
+		struct lp3971_regulator_subdev *reg = &pdata->regulators[i];
+		lp3971->rdev[i] = regulator_register(&regulators[reg->id],
+					lp3971->dev, reg->initdata, lp3971);
 
 		if (IS_ERR(lp3971->rdev[i])) {
 			err = PTR_ERR(lp3971->rdev[i]);
@@ -455,10 +455,10 @@
 	}
 
 	return 0;
+
 error:
-	for (i = 0; i < num_regulators; i++)
-		if (lp3971->rdev[i])
-			regulator_unregister(lp3971->rdev[i]);
+	while (--i >= 0)
+		regulator_unregister(lp3971->rdev[i]);
 	kfree(lp3971->rdev);
 	lp3971->rdev = NULL;
 	return err;
@@ -472,15 +472,17 @@
 	int ret;
 	u16 val;
 
-	lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL);
-	if (lp3971 == NULL) {
-		ret = -ENOMEM;
-		goto err;
+	if (!pdata) {
+		dev_dbg(&i2c->dev, "No platform init data supplied\n");
+		return -ENODEV;
 	}
 
+	lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL);
+	if (lp3971 == NULL)
+		return -ENOMEM;
+
 	lp3971->i2c = i2c;
 	lp3971->dev = &i2c->dev;
-	i2c_set_clientdata(i2c, lp3971);
 
 	mutex_init(&lp3971->io_lock);
 
@@ -493,19 +495,15 @@
 		goto err_detect;
 	}
 
-	if (pdata) {
-		ret = setup_regulators(lp3971, pdata);
-		if (ret < 0)
-			goto err_detect;
-	} else
-		dev_warn(lp3971->dev, "No platform init data supplied\n");
+	ret = setup_regulators(lp3971, pdata);
+	if (ret < 0)
+		goto err_detect;
 
+	i2c_set_clientdata(i2c, lp3971);
 	return 0;
 
 err_detect:
-	i2c_set_clientdata(i2c, NULL);
 	kfree(lp3971);
-err:
 	return ret;
 }
 
@@ -513,11 +511,13 @@
 {
 	struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
 	int i;
-	for (i = 0; i < lp3971->num_regulators; i++)
-		if (lp3971->rdev[i])
-			regulator_unregister(lp3971->rdev[i]);
-	kfree(lp3971->rdev);
+
 	i2c_set_clientdata(i2c, NULL);
+
+	for (i = 0; i < lp3971->num_regulators; i++)
+		regulator_unregister(lp3971->rdev[i]);
+
+	kfree(lp3971->rdev);
 	kfree(lp3971);
 
 	return 0;
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 2c082d3..a49fc95 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -179,8 +179,8 @@
 	},
 };
 
-static int max1586_pmic_probe(struct i2c_client *client,
-			      const struct i2c_device_id *i2c_id)
+static int __devinit max1586_pmic_probe(struct i2c_client *client,
+					const struct i2c_device_id *i2c_id)
 {
 	struct regulator_dev **rdev;
 	struct max1586_platform_data *pdata = client->dev.platform_data;
@@ -235,7 +235,7 @@
 	return ret;
 }
 
-static int max1586_pmic_remove(struct i2c_client *client)
+static int __devexit max1586_pmic_remove(struct i2c_client *client)
 {
 	struct regulator_dev **rdev = i2c_get_clientdata(client);
 	int i;
@@ -257,9 +257,10 @@
 
 static struct i2c_driver max1586_pmic_driver = {
 	.probe = max1586_pmic_probe,
-	.remove = max1586_pmic_remove,
+	.remove = __devexit_p(max1586_pmic_remove),
 	.driver		= {
 		.name	= "max1586",
+		.owner	= THIS_MODULE,
 	},
 	.id_table	= max1586_id,
 };
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
new file mode 100644
index 0000000..3ebdf69
--- /dev/null
+++ b/drivers/regulator/max8649.c
@@ -0,0 +1,408 @@
+/*
+ * Regulators driver for Maxim max8649
+ *
+ * Copyright (C) 2009-2010 Marvell International Ltd.
+ *      Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/max8649.h>
+
+#define MAX8649_DCDC_VMIN	750000		/* uV */
+#define MAX8649_DCDC_VMAX	1380000		/* uV */
+#define MAX8649_DCDC_STEP	10000		/* uV */
+#define MAX8649_VOL_MASK	0x3f
+
+/* Registers */
+#define MAX8649_MODE0		0x00
+#define MAX8649_MODE1		0x01
+#define MAX8649_MODE2		0x02
+#define MAX8649_MODE3		0x03
+#define MAX8649_CONTROL		0x04
+#define MAX8649_SYNC		0x05
+#define MAX8649_RAMP		0x06
+#define MAX8649_CHIP_ID1	0x08
+#define MAX8649_CHIP_ID2	0x09
+
+/* Bits */
+#define MAX8649_EN_PD		(1 << 7)
+#define MAX8649_VID0_PD		(1 << 6)
+#define MAX8649_VID1_PD		(1 << 5)
+#define MAX8649_VID_MASK	(3 << 5)
+
+#define MAX8649_FORCE_PWM	(1 << 7)
+#define MAX8649_SYNC_EXTCLK	(1 << 6)
+
+#define MAX8649_EXT_MASK	(3 << 6)
+
+#define MAX8649_RAMP_MASK	(7 << 5)
+#define MAX8649_RAMP_DOWN	(1 << 1)
+
+struct max8649_regulator_info {
+	struct regulator_dev	*regulator;
+	struct i2c_client	*i2c;
+	struct device		*dev;
+	struct mutex		io_lock;
+
+	int		vol_reg;
+	unsigned	mode:2;	/* bit[1:0] = VID1, VID0 */
+	unsigned	extclk_freq:2;
+	unsigned	extclk:1;
+	unsigned	ramp_timing:3;
+	unsigned	ramp_down:1;
+};
+
+/* I2C operations */
+
+static inline int max8649_read_device(struct i2c_client *i2c,
+				      int reg, int bytes, void *dest)
+{
+	unsigned char data;
+	int ret;
+
+	data = (unsigned char)reg;
+	ret = i2c_master_send(i2c, &data, 1);
+	if (ret < 0)
+		return ret;
+	ret = i2c_master_recv(i2c, dest, bytes);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static inline int max8649_write_device(struct i2c_client *i2c,
+				       int reg, int bytes, void *src)
+{
+	unsigned char buf[bytes + 1];
+	int ret;
+
+	buf[0] = (unsigned char)reg;
+	memcpy(&buf[1], src, bytes);
+
+	ret = i2c_master_send(i2c, buf, bytes + 1);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int max8649_reg_read(struct i2c_client *i2c, int reg)
+{
+	struct max8649_regulator_info *info = i2c_get_clientdata(i2c);
+	unsigned char data;
+	int ret;
+
+	mutex_lock(&info->io_lock);
+	ret = max8649_read_device(i2c, reg, 1, &data);
+	mutex_unlock(&info->io_lock);
+
+	if (ret < 0)
+		return ret;
+	return (int)data;
+}
+
+static int max8649_set_bits(struct i2c_client *i2c, int reg,
+			    unsigned char mask, unsigned char data)
+{
+	struct max8649_regulator_info *info = i2c_get_clientdata(i2c);
+	unsigned char value;
+	int ret;
+
+	mutex_lock(&info->io_lock);
+	ret = max8649_read_device(i2c, reg, 1, &value);
+	if (ret < 0)
+		goto out;
+	value &= ~mask;
+	value |= data;
+	ret = max8649_write_device(i2c, reg, 1, &value);
+out:
+	mutex_unlock(&info->io_lock);
+	return ret;
+}
+
+static inline int check_range(int min_uV, int max_uV)
+{
+	if ((min_uV < MAX8649_DCDC_VMIN) || (max_uV > MAX8649_DCDC_VMAX)
+		|| (min_uV > max_uV))
+		return -EINVAL;
+	return 0;
+}
+
+static int max8649_list_voltage(struct regulator_dev *rdev, unsigned index)
+{
+	return (MAX8649_DCDC_VMIN + index * MAX8649_DCDC_STEP);
+}
+
+static int max8649_get_voltage(struct regulator_dev *rdev)
+{
+	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
+	unsigned char data;
+	int ret;
+
+	ret = max8649_reg_read(info->i2c, info->vol_reg);
+	if (ret < 0)
+		return ret;
+	data = (unsigned char)ret & MAX8649_VOL_MASK;
+	return max8649_list_voltage(rdev, data);
+}
+
+static int max8649_set_voltage(struct regulator_dev *rdev,
+			       int min_uV, int max_uV)
+{
+	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
+	unsigned char data, mask;
+
+	if (check_range(min_uV, max_uV)) {
+		dev_err(info->dev, "invalid voltage range (%d, %d) uV\n",
+			min_uV, max_uV);
+		return -EINVAL;
+	}
+	data = (min_uV - MAX8649_DCDC_VMIN + MAX8649_DCDC_STEP - 1)
+		/ MAX8649_DCDC_STEP;
+	mask = MAX8649_VOL_MASK;
+
+	return max8649_set_bits(info->i2c, info->vol_reg, mask, data);
+}
+
+/* EN_PD means pulldown on EN input */
+static int max8649_enable(struct regulator_dev *rdev)
+{
+	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
+	return max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_EN_PD, 0);
+}
+
+/*
+ * Applied internal pulldown resistor on EN input pin.
+ * If pulldown EN pin outside, it would be better.
+ */
+static int max8649_disable(struct regulator_dev *rdev)
+{
+	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
+	return max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_EN_PD,
+				MAX8649_EN_PD);
+}
+
+static int max8649_is_enabled(struct regulator_dev *rdev)
+{
+	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = max8649_reg_read(info->i2c, MAX8649_CONTROL);
+	if (ret < 0)
+		return ret;
+	return !((unsigned char)ret & MAX8649_EN_PD);
+}
+
+static int max8649_enable_time(struct regulator_dev *rdev)
+{
+	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
+	int voltage, rate, ret;
+
+	/* get voltage */
+	ret = max8649_reg_read(info->i2c, info->vol_reg);
+	if (ret < 0)
+		return ret;
+	ret &= MAX8649_VOL_MASK;
+	voltage = max8649_list_voltage(rdev, (unsigned char)ret); /* uV */
+
+	/* get rate */
+	ret = max8649_reg_read(info->i2c, MAX8649_RAMP);
+	if (ret < 0)
+		return ret;
+	ret = (ret & MAX8649_RAMP_MASK) >> 5;
+	rate = (32 * 1000) >> ret;	/* uV/uS */
+
+	return (voltage / rate);
+}
+
+static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		max8649_set_bits(info->i2c, info->vol_reg, MAX8649_FORCE_PWM,
+				 MAX8649_FORCE_PWM);
+		break;
+	case REGULATOR_MODE_NORMAL:
+		max8649_set_bits(info->i2c, info->vol_reg,
+				 MAX8649_FORCE_PWM, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static unsigned int max8649_get_mode(struct regulator_dev *rdev)
+{
+	struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = max8649_reg_read(info->i2c, info->vol_reg);
+	if (ret & MAX8649_FORCE_PWM)
+		return REGULATOR_MODE_FAST;
+	return REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops max8649_dcdc_ops = {
+	.set_voltage	= max8649_set_voltage,
+	.get_voltage	= max8649_get_voltage,
+	.list_voltage	= max8649_list_voltage,
+	.enable		= max8649_enable,
+	.disable	= max8649_disable,
+	.is_enabled	= max8649_is_enabled,
+	.enable_time	= max8649_enable_time,
+	.set_mode	= max8649_set_mode,
+	.get_mode	= max8649_get_mode,
+
+};
+
+static struct regulator_desc dcdc_desc = {
+	.name		= "max8649",
+	.ops		= &max8649_dcdc_ops,
+	.type		= REGULATOR_VOLTAGE,
+	.n_voltages	= 1 << 6,
+	.owner		= THIS_MODULE,
+};
+
+static int __devinit max8649_regulator_probe(struct i2c_client *client,
+					     const struct i2c_device_id *id)
+{
+	struct max8649_platform_data *pdata = client->dev.platform_data;
+	struct max8649_regulator_info *info = NULL;
+	unsigned char data;
+	int ret;
+
+	info = kzalloc(sizeof(struct max8649_regulator_info), GFP_KERNEL);
+	if (!info) {
+		dev_err(&client->dev, "No enough memory\n");
+		return -ENOMEM;
+	}
+
+	info->i2c = client;
+	info->dev = &client->dev;
+	mutex_init(&info->io_lock);
+	i2c_set_clientdata(client, info);
+
+	info->mode = pdata->mode;
+	switch (info->mode) {
+	case 0:
+		info->vol_reg = MAX8649_MODE0;
+		break;
+	case 1:
+		info->vol_reg = MAX8649_MODE1;
+		break;
+	case 2:
+		info->vol_reg = MAX8649_MODE2;
+		break;
+	case 3:
+		info->vol_reg = MAX8649_MODE3;
+		break;
+	default:
+		break;
+	}
+
+	ret = max8649_reg_read(info->i2c, MAX8649_CHIP_ID1);
+	if (ret < 0) {
+		dev_err(info->dev, "Failed to detect ID of MAX8649:%d\n",
+			ret);
+		goto out;
+	}
+	dev_info(info->dev, "Detected MAX8649 (ID:%x)\n", ret);
+
+	/* enable VID0 & VID1 */
+	max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_VID_MASK, 0);
+
+	/* enable/disable external clock synchronization */
+	info->extclk = pdata->extclk;
+	data = (info->extclk) ? MAX8649_SYNC_EXTCLK : 0;
+	max8649_set_bits(info->i2c, info->vol_reg, MAX8649_SYNC_EXTCLK, data);
+	if (info->extclk) {
+		/* set external clock frequency */
+		info->extclk_freq = pdata->extclk_freq;
+		max8649_set_bits(info->i2c, MAX8649_SYNC, MAX8649_EXT_MASK,
+				 info->extclk_freq);
+	}
+
+	if (pdata->ramp_timing) {
+		info->ramp_timing = pdata->ramp_timing;
+		max8649_set_bits(info->i2c, MAX8649_RAMP, MAX8649_RAMP_MASK,
+				 info->ramp_timing << 5);
+	}
+
+	info->ramp_down = pdata->ramp_down;
+	if (info->ramp_down) {
+		max8649_set_bits(info->i2c, MAX8649_RAMP, MAX8649_RAMP_DOWN,
+				 MAX8649_RAMP_DOWN);
+	}
+
+	info->regulator = regulator_register(&dcdc_desc, &client->dev,
+					     pdata->regulator, info);
+	if (IS_ERR(info->regulator)) {
+		dev_err(info->dev, "failed to register regulator %s\n",
+			dcdc_desc.name);
+		ret = PTR_ERR(info->regulator);
+		goto out;
+	}
+
+	dev_info(info->dev, "Max8649 regulator device is detected.\n");
+	return 0;
+out:
+	kfree(info);
+	return ret;
+}
+
+static int __devexit max8649_regulator_remove(struct i2c_client *client)
+{
+	struct max8649_regulator_info *info = i2c_get_clientdata(client);
+
+	if (info) {
+		if (info->regulator)
+			regulator_unregister(info->regulator);
+		kfree(info);
+	}
+	i2c_set_clientdata(client, NULL);
+
+	return 0;
+}
+
+static const struct i2c_device_id max8649_id[] = {
+	{ "max8649", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max8649_id);
+
+static struct i2c_driver max8649_driver = {
+	.probe		= max8649_regulator_probe,
+	.remove		= __devexit_p(max8649_regulator_remove),
+	.driver		= {
+		.name	= "max8649",
+	},
+	.id_table	= max8649_id,
+};
+
+static int __init max8649_init(void)
+{
+	return i2c_add_driver(&max8649_driver);
+}
+subsys_initcall(max8649_init);
+
+static void __exit max8649_exit(void)
+{
+	i2c_del_driver(&max8649_driver);
+}
+module_exit(max8649_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("MAXIM 8649 voltage regulator driver");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index acc2fb7..f12f1bb 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -345,8 +345,8 @@
 	},
 };
 
-static int max8660_probe(struct i2c_client *client,
-			      const struct i2c_device_id *i2c_id)
+static int __devinit max8660_probe(struct i2c_client *client,
+				   const struct i2c_device_id *i2c_id)
 {
 	struct regulator_dev **rdev;
 	struct max8660_platform_data *pdata = client->dev.platform_data;
@@ -354,7 +354,7 @@
 	int boot_on, i, id, ret = -EINVAL;
 
 	if (pdata->num_subdevs > MAX8660_V_END) {
-		dev_err(&client->dev, "Too much regulators found!\n");
+		dev_err(&client->dev, "Too many regulators found!\n");
 		goto out;
 	}
 
@@ -462,7 +462,7 @@
 	return ret;
 }
 
-static int max8660_remove(struct i2c_client *client)
+static int __devexit max8660_remove(struct i2c_client *client)
 {
 	struct regulator_dev **rdev = i2c_get_clientdata(client);
 	int i;
@@ -485,9 +485,10 @@
 
 static struct i2c_driver max8660_driver = {
 	.probe = max8660_probe,
-	.remove = max8660_remove,
+	.remove = __devexit_p(max8660_remove),
 	.driver		= {
 		.name	= "max8660",
+		.owner	= THIS_MODULE,
 	},
 	.id_table	= max8660_id,
 };
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
new file mode 100644
index 0000000..67873f0
--- /dev/null
+++ b/drivers/regulator/max8925-regulator.c
@@ -0,0 +1,306 @@
+/*
+ * Regulators driver for Maxim max8925
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ *      Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/max8925.h>
+
+#define SD1_DVM_VMIN		850000
+#define SD1_DVM_VMAX		1000000
+#define SD1_DVM_STEP		50000
+#define SD1_DVM_SHIFT		5		/* SDCTL1 bit5 */
+#define SD1_DVM_EN		6		/* SDV1 bit 6 */
+
+struct max8925_regulator_info {
+	struct regulator_desc	desc;
+	struct regulator_dev	*regulator;
+	struct i2c_client	*i2c;
+	struct max8925_chip	*chip;
+
+	int	min_uV;
+	int	max_uV;
+	int	step_uV;
+	int	vol_reg;
+	int	vol_shift;
+	int	vol_nbits;
+	int	enable_bit;
+	int	enable_reg;
+};
+
+static inline int check_range(struct max8925_regulator_info *info,
+			      int min_uV, int max_uV)
+{
+	if (min_uV < info->min_uV || min_uV > info->max_uV)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int max8925_list_voltage(struct regulator_dev *rdev, unsigned index)
+{
+	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+	return info->min_uV + index * info->step_uV;
+}
+
+static int max8925_set_voltage(struct regulator_dev *rdev,
+			       int min_uV, int max_uV)
+{
+	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+	unsigned char data, mask;
+
+	if (check_range(info, min_uV, max_uV)) {
+		dev_err(info->chip->dev, "invalid voltage range (%d, %d) uV\n",
+			min_uV, max_uV);
+		return -EINVAL;
+	}
+	data = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+	data <<= info->vol_shift;
+	mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+
+	return max8925_set_bits(info->i2c, info->vol_reg, mask, data);
+}
+
+static int max8925_get_voltage(struct regulator_dev *rdev)
+{
+	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+	unsigned char data, mask;
+	int ret;
+
+	ret = max8925_reg_read(info->i2c, info->vol_reg);
+	if (ret < 0)
+		return ret;
+	mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+	data = (ret & mask) >> info->vol_shift;
+
+	return max8925_list_voltage(rdev, data);
+}
+
+static int max8925_enable(struct regulator_dev *rdev)
+{
+	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+
+	return max8925_set_bits(info->i2c, info->enable_reg,
+				1 << info->enable_bit,
+				1 << info->enable_bit);
+}
+
+static int max8925_disable(struct regulator_dev *rdev)
+{
+	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+
+	return max8925_set_bits(info->i2c, info->enable_reg,
+				1 << info->enable_bit, 0);
+}
+
+static int max8925_is_enabled(struct regulator_dev *rdev)
+{
+	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = max8925_reg_read(info->i2c, info->vol_reg);
+	if (ret < 0)
+		return ret;
+
+	return ret & (1 << info->enable_bit);
+}
+
+static int max8925_set_dvm_voltage(struct regulator_dev *rdev, int uV)
+{
+	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+	unsigned char data, mask;
+
+	if (uV < SD1_DVM_VMIN || uV > SD1_DVM_VMAX)
+		return -EINVAL;
+
+	data = (uV - SD1_DVM_VMIN + SD1_DVM_STEP - 1) / SD1_DVM_STEP;
+	data <<= SD1_DVM_SHIFT;
+	mask = 3 << SD1_DVM_SHIFT;
+
+	return max8925_set_bits(info->i2c, info->enable_reg, mask, data);
+}
+
+static int max8925_set_dvm_enable(struct regulator_dev *rdev)
+{
+	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+
+	return max8925_set_bits(info->i2c, info->vol_reg, 1 << SD1_DVM_EN,
+				1 << SD1_DVM_EN);
+}
+
+static int max8925_set_dvm_disable(struct regulator_dev *rdev)
+{
+	struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+
+	return max8925_set_bits(info->i2c, info->vol_reg, 1 << SD1_DVM_EN, 0);
+}
+
+static struct regulator_ops max8925_regulator_sdv_ops = {
+	.set_voltage		= max8925_set_voltage,
+	.get_voltage		= max8925_get_voltage,
+	.enable			= max8925_enable,
+	.disable		= max8925_disable,
+	.is_enabled		= max8925_is_enabled,
+	.set_suspend_voltage	= max8925_set_dvm_voltage,
+	.set_suspend_enable	= max8925_set_dvm_enable,
+	.set_suspend_disable	= max8925_set_dvm_disable,
+};
+
+static struct regulator_ops max8925_regulator_ldo_ops = {
+	.set_voltage		= max8925_set_voltage,
+	.get_voltage		= max8925_get_voltage,
+	.enable			= max8925_enable,
+	.disable		= max8925_disable,
+	.is_enabled		= max8925_is_enabled,
+};
+
+#define MAX8925_SDV(_id, min, max, step)			\
+{								\
+	.desc	= {						\
+		.name	= "SDV" #_id,				\
+		.ops	= &max8925_regulator_sdv_ops,		\
+		.type	= REGULATOR_VOLTAGE,			\
+		.id	= MAX8925_ID_SD##_id,			\
+		.owner	= THIS_MODULE,				\
+	},							\
+	.min_uV		= min * 1000,				\
+	.max_uV		= max * 1000,				\
+	.step_uV	= step * 1000,				\
+	.vol_reg	= MAX8925_SDV##_id,			\
+	.vol_shift	= 0,					\
+	.vol_nbits	= 6,					\
+	.enable_reg	= MAX8925_SDCTL##_id,			\
+	.enable_bit	= 0,					\
+}
+
+#define MAX8925_LDO(_id, min, max, step)			\
+{								\
+	.desc	= {						\
+		.name	= "LDO" #_id,				\
+		.ops	= &max8925_regulator_ldo_ops,		\
+		.type	= REGULATOR_VOLTAGE,			\
+		.id	= MAX8925_ID_LDO##_id,			\
+		.owner	= THIS_MODULE,				\
+	},							\
+	.min_uV		= min * 1000,				\
+	.max_uV		= max * 1000,				\
+	.step_uV	= step * 1000,				\
+	.vol_reg	= MAX8925_LDOVOUT##_id,			\
+	.vol_shift	= 0,					\
+	.vol_nbits	= 6,					\
+	.enable_reg	= MAX8925_LDOCTL##_id,			\
+	.enable_bit	= 0,					\
+}
+
+static struct max8925_regulator_info max8925_regulator_info[] = {
+	MAX8925_SDV(1, 637.5, 1425, 12.5),
+	MAX8925_SDV(2,   650, 2225,   25),
+	MAX8925_SDV(3,   750, 3900,   50),
+
+	MAX8925_LDO(1,  750, 3900, 50),
+	MAX8925_LDO(2,  650, 2250, 25),
+	MAX8925_LDO(3,  650, 2250, 25),
+	MAX8925_LDO(4,  750, 3900, 50),
+	MAX8925_LDO(5,  750, 3900, 50),
+	MAX8925_LDO(6,  750, 3900, 50),
+	MAX8925_LDO(7,  750, 3900, 50),
+	MAX8925_LDO(8,  750, 3900, 50),
+	MAX8925_LDO(9,  750, 3900, 50),
+	MAX8925_LDO(10, 750, 3900, 50),
+	MAX8925_LDO(11, 750, 3900, 50),
+	MAX8925_LDO(12, 750, 3900, 50),
+	MAX8925_LDO(13, 750, 3900, 50),
+	MAX8925_LDO(14, 750, 3900, 50),
+	MAX8925_LDO(15, 750, 3900, 50),
+	MAX8925_LDO(16, 750, 3900, 50),
+	MAX8925_LDO(17, 650, 2250, 25),
+	MAX8925_LDO(18, 650, 2250, 25),
+	MAX8925_LDO(19, 750, 3900, 50),
+	MAX8925_LDO(20, 750, 3900, 50),
+};
+
+static inline struct max8925_regulator_info *find_regulator_info(int id)
+{
+	struct max8925_regulator_info *ri;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
+		ri = &max8925_regulator_info[i];
+		if (ri->desc.id == id)
+			return ri;
+	}
+	return NULL;
+}
+
+static int __devinit max8925_regulator_probe(struct platform_device *pdev)
+{
+	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct max8925_platform_data *pdata = chip->dev->platform_data;
+	struct max8925_regulator_info *ri = NULL;
+	struct regulator_dev *rdev;
+
+	ri = find_regulator_info(pdev->id);
+	if (ri == NULL) {
+		dev_err(&pdev->dev, "invalid regulator ID specified\n");
+		return -EINVAL;
+	}
+	ri->i2c = chip->i2c;
+	ri->chip = chip;
+
+	rdev = regulator_register(&ri->desc, &pdev->dev,
+				  pdata->regulator[pdev->id], ri);
+	if (IS_ERR(rdev)) {
+		dev_err(&pdev->dev, "failed to register regulator %s\n",
+				ri->desc.name);
+		return PTR_ERR(rdev);
+	}
+
+	platform_set_drvdata(pdev, rdev);
+	return 0;
+}
+
+static int __devexit max8925_regulator_remove(struct platform_device *pdev)
+{
+	struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+	regulator_unregister(rdev);
+	return 0;
+}
+
+static struct platform_driver max8925_regulator_driver = {
+	.driver		= {
+		.name	= "max8925-regulator",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= max8925_regulator_probe,
+	.remove		= __devexit_p(max8925_regulator_remove),
+};
+
+static int __init max8925_regulator_init(void)
+{
+	return platform_driver_register(&max8925_regulator_driver);
+}
+subsys_initcall(max8925_regulator_init);
+
+static void __exit max8925_regulator_exit(void)
+{
+	platform_driver_unregister(&max8925_regulator_driver);
+}
+module_exit(max8925_regulator_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_DESCRIPTION("Regulator Driver for Maxim 8925 PMIC");
+MODULE_ALIAS("platform:max8925-regulator");
+
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
index 39c4953..f7b8184 100644
--- a/drivers/regulator/mc13783-regulator.c
+++ b/drivers/regulator/mc13783-regulator.c
@@ -2,6 +2,7 @@
  * Regulator Driver for Freescale MC13783 PMIC
  *
  * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@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
@@ -16,11 +17,44 @@
 #include <linux/init.h>
 #include <linux/err.h>
 
-#define MC13783_REG_SWITCHERS4			28
-#define MC13783_REG_SWITCHERS4_PLLEN			(1 << 18)
-
 #define MC13783_REG_SWITCHERS5			29
 #define MC13783_REG_SWITCHERS5_SW3EN			(1 << 20)
+#define MC13783_REG_SWITCHERS5_SW3VSEL			18
+#define MC13783_REG_SWITCHERS5_SW3VSEL_M		(3 << 18)
+
+#define MC13783_REG_REGULATORSETTING0		30
+#define MC13783_REG_REGULATORSETTING0_VIOLOVSEL		2
+#define MC13783_REG_REGULATORSETTING0_VDIGVSEL		4
+#define MC13783_REG_REGULATORSETTING0_VGENVSEL		6
+#define MC13783_REG_REGULATORSETTING0_VRFDIGVSEL	9
+#define MC13783_REG_REGULATORSETTING0_VRFREFVSEL	11
+#define MC13783_REG_REGULATORSETTING0_VRFCPVSEL		13
+#define MC13783_REG_REGULATORSETTING0_VSIMVSEL		14
+#define MC13783_REG_REGULATORSETTING0_VESIMVSEL		15
+#define MC13783_REG_REGULATORSETTING0_VCAMVSEL		16
+
+#define MC13783_REG_REGULATORSETTING0_VIOLOVSEL_M	(3 << 2)
+#define MC13783_REG_REGULATORSETTING0_VDIGVSEL_M	(3 << 4)
+#define MC13783_REG_REGULATORSETTING0_VGENVSEL_M	(7 << 6)
+#define MC13783_REG_REGULATORSETTING0_VRFDIGVSEL_M	(3 << 9)
+#define MC13783_REG_REGULATORSETTING0_VRFREFVSEL_M	(3 << 11)
+#define MC13783_REG_REGULATORSETTING0_VRFCPVSEL_M	(1 << 13)
+#define MC13783_REG_REGULATORSETTING0_VSIMVSEL_M	(1 << 14)
+#define MC13783_REG_REGULATORSETTING0_VESIMVSEL_M	(1 << 15)
+#define MC13783_REG_REGULATORSETTING0_VCAMVSEL_M	(7 << 16)
+
+#define MC13783_REG_REGULATORSETTING1		31
+#define MC13783_REG_REGULATORSETTING1_VVIBVSEL		0
+#define MC13783_REG_REGULATORSETTING1_VRF1VSEL		2
+#define MC13783_REG_REGULATORSETTING1_VRF2VSEL		4
+#define MC13783_REG_REGULATORSETTING1_VMMC1VSEL		6
+#define MC13783_REG_REGULATORSETTING1_VMMC2VSEL		9
+
+#define MC13783_REG_REGULATORSETTING1_VVIBVSEL_M	(3 << 0)
+#define MC13783_REG_REGULATORSETTING1_VRF1VSEL_M	(3 << 2)
+#define MC13783_REG_REGULATORSETTING1_VRF2VSEL_M	(3 << 4)
+#define MC13783_REG_REGULATORSETTING1_VMMC1VSEL_M	(7 << 6)
+#define MC13783_REG_REGULATORSETTING1_VMMC2VSEL_M	(7 << 9)
 
 #define MC13783_REG_REGULATORMODE0		32
 #define MC13783_REG_REGULATORMODE0_VAUDIOEN		(1 << 0)
@@ -48,19 +82,107 @@
 #define MC13783_REG_POWERMISC_GPO2EN			(1 << 8)
 #define MC13783_REG_POWERMISC_GPO3EN			(1 << 10)
 #define MC13783_REG_POWERMISC_GPO4EN			(1 << 12)
+#define MC13783_REG_POWERMISC_PWGT1SPIEN		(1 << 15)
+#define MC13783_REG_POWERMISC_PWGT2SPIEN		(1 << 16)
+
+#define MC13783_REG_POWERMISC_PWGTSPI_M			(3 << 15)
+
 
 struct mc13783_regulator {
 	struct regulator_desc desc;
 	int reg;
 	int enable_bit;
+	int vsel_reg;
+	int vsel_shift;
+	int vsel_mask;
+	int const *voltages;
+};
+
+/* Voltage Values */
+static const int const mc13783_sw3_val[] = {
+	5000000, 5000000, 5000000, 5500000,
+};
+
+static const int const mc13783_vaudio_val[] = {
+	2775000,
+};
+
+static const int const mc13783_viohi_val[] = {
+	2775000,
+};
+
+static const int const mc13783_violo_val[] = {
+	1200000, 1300000, 1500000, 1800000,
+};
+
+static const int const mc13783_vdig_val[] = {
+	1200000, 1300000, 1500000, 1800000,
+};
+
+static const int const mc13783_vgen_val[] = {
+	1200000, 1300000, 1500000, 1800000,
+	1100000, 2000000, 2775000, 2400000,
+};
+
+static const int const mc13783_vrfdig_val[] = {
+	1200000, 1500000, 1800000, 1875000,
+};
+
+static const int const mc13783_vrfref_val[] = {
+	2475000, 2600000, 2700000, 2775000,
+};
+
+static const int const mc13783_vrfcp_val[] = {
+	2700000, 2775000,
+};
+
+static const int const mc13783_vsim_val[] = {
+	1800000, 2900000, 3000000,
+};
+
+static const int const mc13783_vesim_val[] = {
+	1800000, 2900000,
+};
+
+static const int const mc13783_vcam_val[] = {
+	1500000, 1800000, 2500000, 2550000,
+	2600000, 2750000, 2800000, 3000000,
+};
+
+static const int const mc13783_vrfbg_val[] = {
+	1250000,
+};
+
+static const int const mc13783_vvib_val[] = {
+	1300000, 1800000, 2000000, 3000000,
+};
+
+static const int const mc13783_vmmc_val[] = {
+	1600000, 1800000, 2000000, 2600000,
+	2700000, 2800000, 2900000, 3000000,
+};
+
+static const int const mc13783_vrf_val[] = {
+	1500000, 1875000, 2700000, 2775000,
+};
+
+static const int const mc13783_gpo_val[] = {
+	3100000,
+};
+
+static const int const mc13783_pwgtdrv_val[] = {
+	5500000,
 };
 
 static struct regulator_ops mc13783_regulator_ops;
+static struct regulator_ops mc13783_fixed_regulator_ops;
+static struct regulator_ops mc13783_gpo_regulator_ops;
 
-#define MC13783_DEFINE(prefix, _name, _reg)				\
+#define MC13783_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages)	\
 	[MC13783_ ## prefix ## _ ## _name] = {				\
 		.desc = {						\
 			.name = #prefix "_" #_name,			\
+			.n_voltages = ARRAY_SIZE(_voltages),		\
 			.ops = &mc13783_regulator_ops,			\
 			.type = REGULATOR_VOLTAGE,			\
 			.id = MC13783_ ## prefix ## _ ## _name,		\
@@ -68,40 +190,92 @@
 		},							\
 		.reg = MC13783_REG_ ## _reg,				\
 		.enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN,	\
+		.vsel_reg = MC13783_REG_ ## _vsel_reg,			\
+		.vsel_shift = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL,\
+		.vsel_mask = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL_M,\
+		.voltages =  _voltages,					\
 	}
 
-#define MC13783_DEFINE_SW(_name, _reg) MC13783_DEFINE(SW, _name, _reg)
-#define MC13783_DEFINE_REGU(_name, _reg) MC13783_DEFINE(REGU, _name, _reg)
+#define MC13783_FIXED_DEFINE(prefix, _name, _reg, _voltages)		\
+	[MC13783_ ## prefix ## _ ## _name] = {				\
+		.desc = {						\
+			.name = #prefix "_" #_name,			\
+			.n_voltages = ARRAY_SIZE(_voltages),		\
+			.ops = &mc13783_fixed_regulator_ops,		\
+			.type = REGULATOR_VOLTAGE,			\
+			.id = MC13783_ ## prefix ## _ ## _name,		\
+			.owner = THIS_MODULE,				\
+		},							\
+		.reg = MC13783_REG_ ## _reg,				\
+		.enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN,	\
+		.voltages =  _voltages,					\
+	}
+
+#define MC13783_GPO_DEFINE(prefix, _name, _reg,  _voltages)		\
+	[MC13783_ ## prefix ## _ ## _name] = {				\
+		.desc = {						\
+			.name = #prefix "_" #_name,			\
+			.n_voltages = ARRAY_SIZE(_voltages),		\
+			.ops = &mc13783_gpo_regulator_ops,		\
+			.type = REGULATOR_VOLTAGE,			\
+			.id = MC13783_ ## prefix ## _ ## _name,		\
+			.owner = THIS_MODULE,				\
+		},							\
+		.reg = MC13783_REG_ ## _reg,				\
+		.enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN,	\
+		.voltages =  _voltages,					\
+	}
+
+#define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages)		\
+	MC13783_DEFINE(SW, _name, _reg, _vsel_reg, _voltages)
+#define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages)		\
+	MC13783_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages)
 
 static struct mc13783_regulator mc13783_regulators[] = {
-	MC13783_DEFINE_SW(SW3, SWITCHERS5),
-	MC13783_DEFINE_SW(PLL, SWITCHERS4),
+	MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val),
 
-	MC13783_DEFINE_REGU(VAUDIO, REGULATORMODE0),
-	MC13783_DEFINE_REGU(VIOHI, REGULATORMODE0),
-	MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0),
-	MC13783_DEFINE_REGU(VDIG, REGULATORMODE0),
-	MC13783_DEFINE_REGU(VGEN, REGULATORMODE0),
-	MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0),
-	MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0),
-	MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0),
-	MC13783_DEFINE_REGU(VSIM, REGULATORMODE1),
-	MC13783_DEFINE_REGU(VESIM, REGULATORMODE1),
-	MC13783_DEFINE_REGU(VCAM, REGULATORMODE1),
-	MC13783_DEFINE_REGU(VRFBG, REGULATORMODE1),
-	MC13783_DEFINE_REGU(VVIB, REGULATORMODE1),
-	MC13783_DEFINE_REGU(VRF1, REGULATORMODE1),
-	MC13783_DEFINE_REGU(VRF2, REGULATORMODE1),
-	MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1),
-	MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1),
-	MC13783_DEFINE_REGU(GPO1, POWERMISC),
-	MC13783_DEFINE_REGU(GPO2, POWERMISC),
-	MC13783_DEFINE_REGU(GPO3, POWERMISC),
-	MC13783_DEFINE_REGU(GPO4, POWERMISC),
+	MC13783_FIXED_DEFINE(REGU, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
+	MC13783_FIXED_DEFINE(REGU, VIOHI, REGULATORMODE0, mc13783_viohi_val),
+	MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0,	\
+			    mc13783_violo_val),
+	MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0,	\
+			    mc13783_vdig_val),
+	MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0,	\
+			    mc13783_vgen_val),
+	MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0,	\
+			    mc13783_vrfdig_val),
+	MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0,	\
+			    mc13783_vrfref_val),
+	MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0,	\
+			    mc13783_vrfcp_val),
+	MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0,	\
+			    mc13783_vsim_val),
+	MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0,	\
+			    mc13783_vesim_val),
+	MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0,	\
+			    mc13783_vcam_val),
+	MC13783_FIXED_DEFINE(REGU, VRFBG, REGULATORMODE1, mc13783_vrfbg_val),
+	MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1,	\
+			    mc13783_vvib_val),
+	MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1,	\
+			    mc13783_vrf_val),
+	MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1,	\
+			    mc13783_vrf_val),
+	MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1,	\
+			    mc13783_vmmc_val),
+	MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1,	\
+			    mc13783_vmmc_val),
+	MC13783_GPO_DEFINE(REGU, GPO1, POWERMISC, mc13783_gpo_val),
+	MC13783_GPO_DEFINE(REGU, GPO2, POWERMISC, mc13783_gpo_val),
+	MC13783_GPO_DEFINE(REGU, GPO3, POWERMISC, mc13783_gpo_val),
+	MC13783_GPO_DEFINE(REGU, GPO4, POWERMISC, mc13783_gpo_val),
+	MC13783_GPO_DEFINE(REGU, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val),
+	MC13783_GPO_DEFINE(REGU, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val),
 };
 
 struct mc13783_regulator_priv {
 	struct mc13783 *mc13783;
+	u32 powermisc_pwgt_state;
 	struct regulator_dev *regulators[];
 };
 
@@ -154,10 +328,241 @@
 	return (val & mc13783_regulators[id].enable_bit) != 0;
 }
 
+static int mc13783_regulator_list_voltage(struct regulator_dev *rdev,
+						unsigned selector)
+{
+	int id = rdev_get_id(rdev);
+
+	if (selector >= mc13783_regulators[id].desc.n_voltages)
+		return -EINVAL;
+
+	return mc13783_regulators[id].voltages[selector];
+}
+
+static int mc13783_get_best_voltage_index(struct regulator_dev *rdev,
+						int min_uV, int max_uV)
+{
+	int reg_id = rdev_get_id(rdev);
+	int i;
+	int bestmatch;
+	int bestindex;
+
+	/*
+	 * Locate the minimum voltage fitting the criteria on
+	 * this regulator. The switchable voltages are not
+	 * in strict falling order so we need to check them
+	 * all for the best match.
+	 */
+	bestmatch = INT_MAX;
+	bestindex = -1;
+	for (i = 0; i < mc13783_regulators[reg_id].desc.n_voltages; i++) {
+		if (mc13783_regulators[reg_id].voltages[i] >= min_uV &&
+		    mc13783_regulators[reg_id].voltages[i] < bestmatch) {
+			bestmatch = mc13783_regulators[reg_id].voltages[i];
+			bestindex = i;
+		}
+	}
+
+	if (bestindex < 0 || bestmatch > max_uV) {
+		dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n",
+				min_uV, max_uV);
+		return -EINVAL;
+	}
+	return bestindex;
+}
+
+static int mc13783_regulator_set_voltage(struct regulator_dev *rdev,
+						int min_uV, int max_uV)
+{
+	struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+	int value, id = rdev_get_id(rdev);
+	int ret;
+
+	dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
+		__func__, id, min_uV, max_uV);
+
+	/* Find the best index */
+	value = mc13783_get_best_voltage_index(rdev, min_uV, max_uV);
+	dev_dbg(rdev_get_dev(rdev), "%s best value: %d \n", __func__, value);
+	if (value < 0)
+		return value;
+
+	mc13783_lock(priv->mc13783);
+	ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].vsel_reg,
+			mc13783_regulators[id].vsel_mask,
+			value << mc13783_regulators[id].vsel_shift);
+	mc13783_unlock(priv->mc13783);
+
+	return ret;
+}
+
+static int mc13783_regulator_get_voltage(struct regulator_dev *rdev)
+{
+	struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+	int ret, id = rdev_get_id(rdev);
+	unsigned int val;
+
+	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
+
+	mc13783_lock(priv->mc13783);
+	ret = mc13783_reg_read(priv->mc13783,
+				mc13783_regulators[id].vsel_reg, &val);
+	mc13783_unlock(priv->mc13783);
+
+	if (ret)
+		return ret;
+
+	val = (val & mc13783_regulators[id].vsel_mask)
+		>> mc13783_regulators[id].vsel_shift;
+
+	dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val);
+
+	BUG_ON(val < 0 || val > mc13783_regulators[id].desc.n_voltages);
+
+	return mc13783_regulators[id].voltages[val];
+}
+
 static struct regulator_ops mc13783_regulator_ops = {
 	.enable = mc13783_regulator_enable,
 	.disable = mc13783_regulator_disable,
 	.is_enabled = mc13783_regulator_is_enabled,
+	.list_voltage = mc13783_regulator_list_voltage,
+	.set_voltage = mc13783_regulator_set_voltage,
+	.get_voltage = mc13783_regulator_get_voltage,
+};
+
+static int mc13783_fixed_regulator_set_voltage(struct regulator_dev *rdev,
+						int min_uV, int max_uV)
+{
+	int id = rdev_get_id(rdev);
+
+	dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
+		__func__, id, min_uV, max_uV);
+
+	if (min_uV > mc13783_regulators[id].voltages[0] &&
+	    max_uV < mc13783_regulators[id].voltages[0])
+		return 0;
+	else
+		return -EINVAL;
+}
+
+static int mc13783_fixed_regulator_get_voltage(struct regulator_dev *rdev)
+{
+	int id = rdev_get_id(rdev);
+
+	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
+
+	return mc13783_regulators[id].voltages[0];
+}
+
+static struct regulator_ops mc13783_fixed_regulator_ops = {
+	.enable = mc13783_regulator_enable,
+	.disable = mc13783_regulator_disable,
+	.is_enabled = mc13783_regulator_is_enabled,
+	.list_voltage = mc13783_regulator_list_voltage,
+	.set_voltage = mc13783_fixed_regulator_set_voltage,
+	.get_voltage = mc13783_fixed_regulator_get_voltage,
+};
+
+int mc13783_powermisc_rmw(struct mc13783_regulator_priv *priv, u32 mask,
+									u32 val)
+{
+	struct mc13783 *mc13783 = priv->mc13783;
+	int ret;
+	u32 valread;
+
+	BUG_ON(val & ~mask);
+
+	ret = mc13783_reg_read(mc13783, MC13783_REG_POWERMISC, &valread);
+	if (ret)
+		return ret;
+
+	/* Update the stored state for Power Gates. */
+	priv->powermisc_pwgt_state =
+				(priv->powermisc_pwgt_state & ~mask) | val;
+	priv->powermisc_pwgt_state &= MC13783_REG_POWERMISC_PWGTSPI_M;
+
+	/* Construct the new register value */
+	valread = (valread & ~mask) | val;
+	/* Overwrite the PWGTxEN with the stored version */
+	valread = (valread & ~MC13783_REG_POWERMISC_PWGTSPI_M) |
+						priv->powermisc_pwgt_state;
+
+	return mc13783_reg_write(mc13783, MC13783_REG_POWERMISC, valread);
+}
+
+static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev)
+{
+	struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+	int id = rdev_get_id(rdev);
+	int ret;
+	u32 en_val = mc13783_regulators[id].enable_bit;
+
+	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
+
+	/* Power Gate enable value is 0 */
+	if (id == MC13783_REGU_PWGT1SPI ||
+	    id == MC13783_REGU_PWGT2SPI)
+		en_val = 0;
+
+	mc13783_lock(priv->mc13783);
+	ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit,
+					en_val);
+	mc13783_unlock(priv->mc13783);
+
+	return ret;
+}
+
+static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev)
+{
+	struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+	int id = rdev_get_id(rdev);
+	int ret;
+	u32 dis_val = 0;
+
+	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
+
+	/* Power Gate disable value is 1 */
+	if (id == MC13783_REGU_PWGT1SPI ||
+	    id == MC13783_REGU_PWGT2SPI)
+		dis_val = mc13783_regulators[id].enable_bit;
+
+	mc13783_lock(priv->mc13783);
+	ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit,
+					dis_val);
+	mc13783_unlock(priv->mc13783);
+
+	return ret;
+}
+
+static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev)
+{
+	struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+	int ret, id = rdev_get_id(rdev);
+	unsigned int val;
+
+	mc13783_lock(priv->mc13783);
+	ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val);
+	mc13783_unlock(priv->mc13783);
+
+	if (ret)
+		return ret;
+
+	/* Power Gates state is stored in powermisc_pwgt_state
+	 * where the meaning of bits is negated */
+	val = (val & ~MC13783_REG_POWERMISC_PWGTSPI_M) |
+	      (priv->powermisc_pwgt_state ^ MC13783_REG_POWERMISC_PWGTSPI_M);
+
+	return (val & mc13783_regulators[id].enable_bit) != 0;
+}
+
+static struct regulator_ops mc13783_gpo_regulator_ops = {
+	.enable = mc13783_gpo_regulator_enable,
+	.disable = mc13783_gpo_regulator_disable,
+	.is_enabled = mc13783_gpo_regulator_is_enabled,
+	.list_voltage = mc13783_regulator_list_voltage,
+	.set_voltage = mc13783_fixed_regulator_set_voltage,
+	.get_voltage = mc13783_fixed_regulator_get_voltage,
 };
 
 static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c
index 33d7d89..29d0566 100644
--- a/drivers/regulator/pcap-regulator.c
+++ b/drivers/regulator/pcap-regulator.c
@@ -288,16 +288,18 @@
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
 	regulator_unregister(rdev);
+	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
 
 static struct platform_driver pcap_regulator_driver = {
 	.driver = {
-		.name = "pcap-regulator",
+		.name	= "pcap-regulator",
+		.owner	= THIS_MODULE,
 	},
-	.probe = pcap_regulator_probe,
-	.remove = __devexit_p(pcap_regulator_remove),
+	.probe	= pcap_regulator_probe,
+	.remove	= __devexit_p(pcap_regulator_remove),
 };
 
 static int __init pcap_regulator_init(void)
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 07fda0a..1f18354 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -457,8 +457,8 @@
 	.list_voltage = tps65023_ldo_list_voltage,
 };
 
-static
-int tps_65023_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int __devinit tps_65023_probe(struct i2c_client *client,
+				     const struct i2c_device_id *id)
 {
 	static int desc_id;
 	const struct tps_info *info = (void *)id->driver_data;
@@ -466,6 +466,7 @@
 	struct regulator_dev *rdev;
 	struct tps_pmic *tps;
 	int i;
+	int error;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -EIO;
@@ -475,7 +476,6 @@
 	 * coming from the board-evm file.
 	 */
 	init_data = client->dev.platform_data;
-
 	if (!init_data)
 		return -EIO;
 
@@ -502,21 +502,12 @@
 
 		/* Register the regulators */
 		rdev = regulator_register(&tps->desc[i], &client->dev,
-								init_data, tps);
+					  init_data, tps);
 		if (IS_ERR(rdev)) {
 			dev_err(&client->dev, "failed to register %s\n",
 				id->name);
-
-			/* Unregister */
-			while (i)
-				regulator_unregister(tps->rdev[--i]);
-
-			tps->client = NULL;
-
-			/* clear the client data in i2c */
-			i2c_set_clientdata(client, NULL);
-			kfree(tps);
-			return PTR_ERR(rdev);
+			error = PTR_ERR(rdev);
+			goto fail;
 		}
 
 		/* Save regulator for cleanup */
@@ -526,6 +517,13 @@
 	i2c_set_clientdata(client, tps);
 
 	return 0;
+
+ fail:
+	while (--i >= 0)
+		regulator_unregister(tps->rdev[i]);
+
+	kfree(tps);
+	return error;
 }
 
 /**
@@ -539,13 +537,12 @@
 	struct tps_pmic *tps = i2c_get_clientdata(client);
 	int i;
 
+	/* clear the client data in i2c */
+	i2c_set_clientdata(client, NULL);
+
 	for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
 		regulator_unregister(tps->rdev[i]);
 
-	tps->client = NULL;
-
-	/* clear the client data in i2c */
-	i2c_set_clientdata(client, NULL);
 	kfree(tps);
 
 	return 0;
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index f8a6dfb..c2a9539 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -538,8 +538,8 @@
 	.list_voltage = tps6507x_ldo_list_voltage,
 };
 
-static
-int tps_6507x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int __devinit tps_6507x_probe(struct i2c_client *client,
+				     const struct i2c_device_id *id)
 {
 	static int desc_id;
 	const struct tps_info *info = (void *)id->driver_data;
@@ -547,6 +547,7 @@
 	struct regulator_dev *rdev;
 	struct tps_pmic *tps;
 	int i;
+	int error;
 
 	if (!i2c_check_functionality(client->adapter,
 				I2C_FUNC_SMBUS_BYTE_DATA))
@@ -557,7 +558,6 @@
 	 * coming from the board-evm file.
 	 */
 	init_data = client->dev.platform_data;
-
 	if (!init_data)
 		return -EIO;
 
@@ -586,18 +586,8 @@
 		if (IS_ERR(rdev)) {
 			dev_err(&client->dev, "failed to register %s\n",
 				id->name);
-
-			/* Unregister */
-			while (i)
-				regulator_unregister(tps->rdev[--i]);
-
-			tps->client = NULL;
-
-			/* clear the client data in i2c */
-			i2c_set_clientdata(client, NULL);
-
-			kfree(tps);
-			return PTR_ERR(rdev);
+			error = PTR_ERR(rdev);
+			goto fail;
 		}
 
 		/* Save regulator for cleanup */
@@ -607,6 +597,13 @@
 	i2c_set_clientdata(client, tps);
 
 	return 0;
+
+fail:
+	while (--i >= 0)
+		regulator_unregister(tps->rdev[i]);
+
+	kfree(tps);
+	return error;
 }
 
 /**
@@ -620,13 +617,12 @@
 	struct tps_pmic *tps = i2c_get_clientdata(client);
 	int i;
 
+	/* clear the client data in i2c */
+	i2c_set_clientdata(client, NULL);
+
 	for (i = 0; i < TPS6507X_NUM_REGULATOR; i++)
 		regulator_unregister(tps->rdev[i]);
 
-	tps->client = NULL;
-
-	/* clear the client data in i2c */
-	i2c_set_clientdata(client, NULL);
 	kfree(tps);
 
 	return 0;
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 7e67485..9729d76 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -519,19 +519,19 @@
 	/* 6030 REG with base as PMC Slave Misc : 0x0030 */
 	/* Turnon-delay and remap configuration values for 6030 are not
 	   verified since the specification is not public */
-	TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1, 0, 0x08),
-	TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2, 0, 0x08),
-	TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3, 0, 0x08),
-	TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4, 0, 0x08),
-	TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5, 0, 0x08),
-	TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7, 0, 0x08),
-	TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x08),
-	TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x08),
-	TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x08),
-	TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x08)
+	TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1, 0, 0x21),
+	TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2, 0, 0x21),
+	TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3, 0, 0x21),
+	TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4, 0, 0x21),
+	TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5, 0, 0x21),
+	TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7, 0, 0x21),
+	TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x21),
+	TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x21),
+	TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x21),
+	TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x21)
 };
 
-static int twlreg_probe(struct platform_device *pdev)
+static int __devinit twlreg_probe(struct platform_device *pdev)
 {
 	int				i;
 	struct twlreg_info		*info;
diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c
index addc032..d96ceca 100644
--- a/drivers/regulator/virtual.c
+++ b/drivers/regulator/virtual.c
@@ -19,7 +19,7 @@
 struct virtual_consumer_data {
 	struct mutex lock;
 	struct regulator *regulator;
-	int enabled;
+	bool enabled;
 	int min_uV;
 	int max_uV;
 	int min_uA;
@@ -49,7 +49,7 @@
 		dev_dbg(dev, "Enabling regulator\n");
 		ret = regulator_enable(data->regulator);
 		if (ret == 0)
-			data->enabled = 1;
+			data->enabled = true;
 		else
 			dev_err(dev, "regulator_enable() failed: %d\n",
 				ret);
@@ -59,7 +59,7 @@
 		dev_dbg(dev, "Disabling regulator\n");
 		ret = regulator_disable(data->regulator);
 		if (ret == 0)
-			data->enabled = 0;
+			data->enabled = false;
 		else
 			dev_err(dev, "regulator_disable() failed: %d\n",
 				ret);
@@ -89,7 +89,7 @@
 		dev_dbg(dev, "Enabling regulator\n");
 		ret = regulator_enable(data->regulator);
 		if (ret == 0)
-			data->enabled = 1;
+			data->enabled = true;
 		else
 			dev_err(dev, "regulator_enable() failed: %d\n",
 				ret);
@@ -99,7 +99,7 @@
 		dev_dbg(dev, "Disabling regulator\n");
 		ret = regulator_disable(data->regulator);
 		if (ret == 0)
-			data->enabled = 0;
+			data->enabled = false;
 		else
 			dev_err(dev, "regulator_disable() failed: %d\n",
 				ret);
@@ -270,24 +270,28 @@
 static DEVICE_ATTR(max_microamps, 0666, show_max_uA, set_max_uA);
 static DEVICE_ATTR(mode, 0666, show_mode, set_mode);
 
-static struct device_attribute *attributes[] = {
-	&dev_attr_min_microvolts,
-	&dev_attr_max_microvolts,
-	&dev_attr_min_microamps,
-	&dev_attr_max_microamps,
-	&dev_attr_mode,
+static struct attribute *regulator_virtual_attributes[] = {
+	&dev_attr_min_microvolts.attr,
+	&dev_attr_max_microvolts.attr,
+	&dev_attr_min_microamps.attr,
+	&dev_attr_max_microamps.attr,
+	&dev_attr_mode.attr,
+	NULL
 };
 
-static int regulator_virtual_consumer_probe(struct platform_device *pdev)
+static const struct attribute_group regulator_virtual_attr_group = {
+	.attrs	= regulator_virtual_attributes,
+};
+
+static int __devinit regulator_virtual_probe(struct platform_device *pdev)
 {
 	char *reg_id = pdev->dev.platform_data;
 	struct virtual_consumer_data *drvdata;
-	int ret, i;
+	int ret;
 
 	drvdata = kzalloc(sizeof(struct virtual_consumer_data), GFP_KERNEL);
-	if (drvdata == NULL) {
+	if (drvdata == NULL)
 		return -ENOMEM;
-	}
 
 	mutex_init(&drvdata->lock);
 
@@ -299,13 +303,12 @@
 		goto err;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(attributes); i++) {
-		ret = device_create_file(&pdev->dev, attributes[i]);
-		if (ret != 0) {
-			dev_err(&pdev->dev, "Failed to create attr %d: %d\n",
-				i, ret);
-			goto err_regulator;
-		}
+	ret = sysfs_create_group(&pdev->dev.kobj,
+				 &regulator_virtual_attr_group);
+	if (ret != 0) {
+		dev_err(&pdev->dev,
+			"Failed to create attribute group: %d\n", ret);
+		goto err_regulator;
 	}
 
 	drvdata->mode = regulator_get_mode(drvdata->regulator);
@@ -317,37 +320,36 @@
 err_regulator:
 	regulator_put(drvdata->regulator);
 err:
-	for (i = 0; i < ARRAY_SIZE(attributes); i++)
-		device_remove_file(&pdev->dev, attributes[i]);
 	kfree(drvdata);
 	return ret;
 }
 
-static int regulator_virtual_consumer_remove(struct platform_device *pdev)
+static int __devexit regulator_virtual_remove(struct platform_device *pdev)
 {
 	struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
-	int i;
 
-	for (i = 0; i < ARRAY_SIZE(attributes); i++)
-		device_remove_file(&pdev->dev, attributes[i]);
+	sysfs_remove_group(&pdev->dev.kobj, &regulator_virtual_attr_group);
+
 	if (drvdata->enabled)
 		regulator_disable(drvdata->regulator);
 	regulator_put(drvdata->regulator);
 
 	kfree(drvdata);
 
+	platform_set_drvdata(pdev, NULL);
+
 	return 0;
 }
 
 static struct platform_driver regulator_virtual_consumer_driver = {
-	.probe		= regulator_virtual_consumer_probe,
-	.remove		= regulator_virtual_consumer_remove,
+	.probe		= regulator_virtual_probe,
+	.remove		= __devexit_p(regulator_virtual_remove),
 	.driver		= {
 		.name		= "reg-virt-consumer",
+		.owner		= THIS_MODULE,
 	},
 };
 
-
 static int __init regulator_virtual_consumer_init(void)
 {
 	return platform_driver_register(&regulator_virtual_consumer_driver);
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 0a65775..6e18e56 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -600,6 +600,8 @@
 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 	struct wm831x *wm831x = dcdc->wm831x;
 
+	platform_set_drvdata(pdev, NULL);
+
 	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "HC"), dcdc);
 	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
 	regulator_unregister(dcdc->regulator);
@@ -615,6 +617,7 @@
 	.remove = __devexit_p(wm831x_buckv_remove),
 	.driver		= {
 		.name	= "wm831x-buckv",
+		.owner	= THIS_MODULE,
 	},
 };
 
@@ -769,6 +772,8 @@
 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 	struct wm831x *wm831x = dcdc->wm831x;
 
+	platform_set_drvdata(pdev, NULL);
+
 	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
 	regulator_unregister(dcdc->regulator);
 	kfree(dcdc);
@@ -781,6 +786,7 @@
 	.remove = __devexit_p(wm831x_buckp_remove),
 	.driver		= {
 		.name	= "wm831x-buckp",
+		.owner	= THIS_MODULE,
 	},
 };
 
@@ -895,6 +901,8 @@
 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 	struct wm831x *wm831x = dcdc->wm831x;
 
+	platform_set_drvdata(pdev, NULL);
+
 	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
 	regulator_unregister(dcdc->regulator);
 	kfree(dcdc);
@@ -907,6 +915,7 @@
 	.remove = __devexit_p(wm831x_boostp_remove),
 	.driver		= {
 		.name	= "wm831x-boostp",
+		.owner	= THIS_MODULE,
 	},
 };
 
@@ -979,6 +988,8 @@
 {
 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
+	platform_set_drvdata(pdev, NULL);
+
 	regulator_unregister(dcdc->regulator);
 	kfree(dcdc);
 
@@ -990,6 +1001,7 @@
 	.remove = __devexit_p(wm831x_epe_remove),
 	.driver		= {
 		.name	= "wm831x-epe",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
index 4885700..ca0f6b6 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -222,6 +222,8 @@
 	struct wm831x_isink *isink = platform_get_drvdata(pdev);
 	struct wm831x *wm831x = isink->wm831x;
 
+	platform_set_drvdata(pdev, NULL);
+
 	wm831x_free_irq(wm831x, platform_get_irq(pdev, 0), isink);
 
 	regulator_unregister(isink->regulator);
@@ -235,6 +237,7 @@
 	.remove = __devexit_p(wm831x_isink_remove),
 	.driver		= {
 		.name	= "wm831x-isink",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 61e02ac..d2406c1 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -371,6 +371,8 @@
 	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 	struct wm831x *wm831x = ldo->wm831x;
 
+	platform_set_drvdata(pdev, NULL);
+
 	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), ldo);
 	regulator_unregister(ldo->regulator);
 	kfree(ldo);
@@ -383,6 +385,7 @@
 	.remove = __devexit_p(wm831x_gp_ldo_remove),
 	.driver		= {
 		.name	= "wm831x-ldo",
+		.owner	= THIS_MODULE,
 	},
 };
 
@@ -640,6 +643,7 @@
 	.remove = __devexit_p(wm831x_aldo_remove),
 	.driver		= {
 		.name	= "wm831x-aldo",
+		.owner	= THIS_MODULE,
 	},
 };
 
@@ -811,6 +815,7 @@
 	.remove = __devexit_p(wm831x_alive_ldo_remove),
 	.driver		= {
 		.name	= "wm831x-alive-ldo",
+		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index e7b89e7..723cd1f 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -290,6 +290,51 @@
 	return -EINVAL;
 }
 
+static int wm8350_isink_enable_time(struct regulator_dev *rdev)
+{
+	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
+	int isink = rdev_get_id(rdev);
+	int reg;
+
+	switch (isink) {
+	case WM8350_ISINK_A:
+		reg = wm8350_reg_read(wm8350, WM8350_CSA_FLASH_CONTROL);
+		break;
+	case WM8350_ISINK_B:
+		reg = wm8350_reg_read(wm8350, WM8350_CSB_FLASH_CONTROL);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (reg & WM8350_CS1_FLASH_MODE) {
+		switch (reg & WM8350_CS1_ON_RAMP_MASK) {
+		case 0:
+			return 0;
+		case 1:
+			return 1950;
+		case 2:
+			return 3910;
+		case 3:
+			return 7800;
+		}
+	} else {
+		switch (reg & WM8350_CS1_ON_RAMP_MASK) {
+		case 0:
+			return 0;
+		case 1:
+			return 250000;
+		case 2:
+			return 500000;
+		case 3:
+			return 1000000;
+		}
+	}
+
+	return -EINVAL;
+}
+
+
 int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
 			   u16 trigger, u16 duration, u16 on_ramp, u16 off_ramp,
 			   u16 drive)
@@ -1221,6 +1266,7 @@
 	.enable = wm8350_isink_enable,
 	.disable = wm8350_isink_disable,
 	.is_enabled = wm8350_isink_is_enabled,
+	.enable_time = wm8350_isink_enable_time,
 };
 
 static struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
@@ -1407,7 +1453,7 @@
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 	struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
 
-	wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq);
+	wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev);
 
 	regulator_unregister(rdev);
 
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index d9a2c98..924c7eb 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -317,14 +317,17 @@
 
 static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
 {
+	struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
 	struct regulator_dev *rdev;
 
 	rdev = regulator_register(&regulators[pdev->id], &pdev->dev,
-		pdev->dev.platform_data, dev_get_drvdata(&pdev->dev));
+				  pdev->dev.platform_data, wm8400);
 
 	if (IS_ERR(rdev))
 		return PTR_ERR(rdev);
 
+	platform_set_drvdata(pdev, rdev);
+
 	return 0;
 }
 
@@ -332,6 +335,7 @@
 {
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
+	platform_set_drvdata(pdev, NULL);
 	regulator_unregister(rdev);
 
 	return 0;
@@ -370,7 +374,6 @@
 	wm8400->regulators[reg].id = reg;
 	wm8400->regulators[reg].dev.parent = dev;
 	wm8400->regulators[reg].dev.platform_data = initdata;
-	dev_set_drvdata(&wm8400->regulators[reg].dev, wm8400);
 
 	return platform_device_register(&wm8400->regulators[reg]);
 }
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
new file mode 100644
index 0000000..95454a4
--- /dev/null
+++ b/drivers/regulator/wm8994-regulator.c
@@ -0,0 +1,307 @@
+/*
+ * wm8994-regulator.c  --  Regulator driver for the WM8994
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/gpio.h>
+
+#include <linux/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/registers.h>
+#include <linux/mfd/wm8994/pdata.h>
+
+struct wm8994_ldo {
+	int enable;
+	bool is_enabled;
+	struct regulator_dev *regulator;
+	struct wm8994 *wm8994;
+};
+
+#define WM8994_LDO1_MAX_SELECTOR 0x7
+#define WM8994_LDO2_MAX_SELECTOR 0x3
+
+static int wm8994_ldo_enable(struct regulator_dev *rdev)
+{
+	struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
+
+	/* If we have no soft control assume that the LDO is always enabled. */
+	if (!ldo->enable)
+		return 0;
+
+	gpio_set_value(ldo->enable, 1);
+	ldo->is_enabled = true;
+
+	return 0;
+}
+
+static int wm8994_ldo_disable(struct regulator_dev *rdev)
+{
+	struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
+
+	/* If we have no soft control assume that the LDO is always enabled. */
+	if (!ldo->enable)
+		return -EINVAL;
+
+	gpio_set_value(ldo->enable, 0);
+	ldo->is_enabled = false;
+
+	return 0;
+}
+
+static int wm8994_ldo_is_enabled(struct regulator_dev *rdev)
+{
+	struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
+
+	return ldo->is_enabled;
+}
+
+static int wm8994_ldo_enable_time(struct regulator_dev *rdev)
+{
+	/* 3ms is fairly conservative but this shouldn't be too performance
+	 * critical; can be tweaked per-system if required. */
+	return 3000;
+}
+
+static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev,
+				    unsigned int selector)
+{
+	if (selector > WM8994_LDO1_MAX_SELECTOR)
+		return -EINVAL;
+
+	return (selector * 100000) + 2400000;
+}
+
+static int wm8994_ldo1_get_voltage(struct regulator_dev *rdev)
+{
+	struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
+	int val;
+
+	val = wm8994_reg_read(ldo->wm8994, WM8994_LDO_1);
+	if (val < 0)
+		return val;
+
+	val = (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT;
+
+	return wm8994_ldo1_list_voltage(rdev, val);
+}
+
+static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev,
+				   int min_uV, int max_uV)
+{
+	struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
+	int selector, v;
+
+	selector = (min_uV - 2400000) / 100000;
+	v = wm8994_ldo1_list_voltage(rdev, selector);
+	if (v < 0 || v > max_uV)
+		return -EINVAL;
+
+	selector <<= WM8994_LDO1_VSEL_SHIFT;
+
+	return wm8994_set_bits(ldo->wm8994, WM8994_LDO_1,
+			       WM8994_LDO1_VSEL_MASK, selector);
+}
+
+static struct regulator_ops wm8994_ldo1_ops = {
+	.enable = wm8994_ldo_enable,
+	.disable = wm8994_ldo_disable,
+	.is_enabled = wm8994_ldo_is_enabled,
+	.enable_time = wm8994_ldo_enable_time,
+
+	.list_voltage = wm8994_ldo1_list_voltage,
+	.get_voltage = wm8994_ldo1_get_voltage,
+	.set_voltage = wm8994_ldo1_set_voltage,
+};
+
+static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
+				    unsigned int selector)
+{
+	if (selector > WM8994_LDO2_MAX_SELECTOR)
+		return -EINVAL;
+
+	return (selector * 100000) + 900000;
+}
+
+static int wm8994_ldo2_get_voltage(struct regulator_dev *rdev)
+{
+	struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
+	int val;
+
+	val = wm8994_reg_read(ldo->wm8994, WM8994_LDO_2);
+	if (val < 0)
+		return val;
+
+	val = (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT;
+
+	return wm8994_ldo2_list_voltage(rdev, val);
+}
+
+static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev,
+				   int min_uV, int max_uV)
+{
+	struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
+	int selector, v;
+
+	selector = (min_uV - 900000) / 100000;
+	v = wm8994_ldo2_list_voltage(rdev, selector);
+	if (v < 0 || v > max_uV)
+		return -EINVAL;
+
+	selector <<= WM8994_LDO2_VSEL_SHIFT;
+
+	return wm8994_set_bits(ldo->wm8994, WM8994_LDO_2,
+			       WM8994_LDO2_VSEL_MASK, selector);
+}
+
+static struct regulator_ops wm8994_ldo2_ops = {
+	.enable = wm8994_ldo_enable,
+	.disable = wm8994_ldo_disable,
+	.is_enabled = wm8994_ldo_is_enabled,
+	.enable_time = wm8994_ldo_enable_time,
+
+	.list_voltage = wm8994_ldo2_list_voltage,
+	.get_voltage = wm8994_ldo2_get_voltage,
+	.set_voltage = wm8994_ldo2_set_voltage,
+};
+
+static struct regulator_desc wm8994_ldo_desc[] = {
+	{
+		.name = "LDO1",
+		.id = 1,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = WM8994_LDO1_MAX_SELECTOR + 1,
+		.ops = &wm8994_ldo1_ops,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "LDO2",
+		.id = 2,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = WM8994_LDO2_MAX_SELECTOR + 1,
+		.ops = &wm8994_ldo2_ops,
+		.owner = THIS_MODULE,
+	},
+};
+
+static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
+{
+	struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
+	struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+	int id = pdev->id % ARRAY_SIZE(pdata->ldo);
+	struct wm8994_ldo *ldo;
+	int ret;
+
+	dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
+
+	if (!pdata)
+		return -ENODEV;
+
+	ldo = kzalloc(sizeof(struct wm8994_ldo), GFP_KERNEL);
+	if (ldo == NULL) {
+		dev_err(&pdev->dev, "Unable to allocate private data\n");
+		return -ENOMEM;
+	}
+
+	ldo->wm8994 = wm8994;
+
+	ldo->is_enabled = true;
+
+	if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) {
+		ldo->enable = pdata->ldo[id].enable;
+
+		ret = gpio_request(ldo->enable, "WM8994 LDO enable");
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n",
+				ret);
+			goto err;
+		}
+
+		ret = gpio_direction_output(ldo->enable, ldo->is_enabled);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Failed to set GPIO up: %d\n",
+				ret);
+			goto err_gpio;
+		}
+	}
+
+	ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev,
+					     pdata->ldo[id].init_data, ldo);
+	if (IS_ERR(ldo->regulator)) {
+		ret = PTR_ERR(ldo->regulator);
+		dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
+			id + 1, ret);
+		goto err_gpio;
+	}
+
+	platform_set_drvdata(pdev, ldo);
+
+	return 0;
+
+err_gpio:
+	if (gpio_is_valid(ldo->enable))
+		gpio_free(ldo->enable);
+err:
+	kfree(ldo);
+	return ret;
+}
+
+static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
+{
+	struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	regulator_unregister(ldo->regulator);
+	if (gpio_is_valid(ldo->enable))
+		gpio_free(ldo->enable);
+	kfree(ldo);
+
+	return 0;
+}
+
+static struct platform_driver wm8994_ldo_driver = {
+	.probe = wm8994_ldo_probe,
+	.remove = __devexit_p(wm8994_ldo_remove),
+	.driver		= {
+		.name	= "wm8994-ldo",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init wm8994_ldo_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&wm8994_ldo_driver);
+	if (ret != 0)
+		pr_err("Failed to register Wm8994 GP LDO driver: %d\n", ret);
+
+	return ret;
+}
+subsys_initcall(wm8994_ldo_init);
+
+static void __exit wm8994_ldo_exit(void)
+{
+	platform_driver_unregister(&wm8994_ldo_driver);
+}
+module_exit(wm8994_ldo_exit);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM8994 LDO driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8994-ldo");
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2bb8a8b..6a13037 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -175,6 +175,16 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-max6900.
 
+config RTC_DRV_MAX8925
+	tristate "Maxim MAX8925"
+	depends on MFD_MAX8925
+	help
+	  If you say yes here you will get support for the
+	  RTC of Maxim MAX8925 PMIC.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-max8925.
+
 config RTC_DRV_RS5C372
 	tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
 	help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index b7148af..44ef194 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -52,6 +52,7 @@
 obj-$(CONFIG_RTC_DRV_M48T86)	+= rtc-m48t86.o
 obj-$(CONFIG_RTC_MXC)		+= rtc-mxc.o
 obj-$(CONFIG_RTC_DRV_MAX6900)	+= rtc-max6900.o
+obj-$(CONFIG_RTC_DRV_MAX8925)	+= rtc-max8925.o
 obj-$(CONFIG_RTC_DRV_MAX6902)	+= rtc-max6902.o
 obj-$(CONFIG_RTC_DRV_MC13783)	+= rtc-mc13783.o
 obj-$(CONFIG_RTC_DRV_MSM6242)	+= rtc-msm6242.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index be5a6b7..40845c7 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -226,6 +226,7 @@
 {
 	rtc_dev_exit();
 	class_destroy(rtc_class);
+	idr_destroy(&rtc_idr);
 }
 
 subsys_initcall(rtc_init);
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
index 33c0e98..bc90b09 100644
--- a/drivers/rtc/hctosys.c
+++ b/drivers/rtc/hctosys.c
@@ -22,48 +22,57 @@
  * the best guess is to add 0.5s.
  */
 
+int rtc_hctosys_ret = -ENODEV;
+
 static int __init rtc_hctosys(void)
 {
-	int err;
+	int err = -ENODEV;
 	struct rtc_time tm;
+	struct timespec tv = {
+		.tv_nsec = NSEC_PER_SEC >> 1,
+	};
 	struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
 
 	if (rtc == NULL) {
-		printk("%s: unable to open rtc device (%s)\n",
+		pr_err("%s: unable to open rtc device (%s)\n",
 			__FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
-		return -ENODEV;
+		goto err_open;
 	}
 
 	err = rtc_read_time(rtc, &tm);
-	if (err == 0) {
-		err = rtc_valid_tm(&tm);
-		if (err == 0) {
-			struct timespec tv;
-
-			tv.tv_nsec = NSEC_PER_SEC >> 1;
-
-			rtc_tm_to_time(&tm, &tv.tv_sec);
-
-			do_settimeofday(&tv);
-
-			dev_info(rtc->dev.parent,
-				"setting system clock to "
-				"%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
-				tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-				tm.tm_hour, tm.tm_min, tm.tm_sec,
-				(unsigned int) tv.tv_sec);
-		}
-		else
-			dev_err(rtc->dev.parent,
-				"hctosys: invalid date/time\n");
-	}
-	else
+	if (err) {
 		dev_err(rtc->dev.parent,
 			"hctosys: unable to read the hardware clock\n");
+		goto err_read;
 
+	}
+
+	err = rtc_valid_tm(&tm);
+	if (err) {
+		dev_err(rtc->dev.parent,
+			"hctosys: invalid date/time\n");
+		goto err_invalid;
+	}
+
+	rtc_tm_to_time(&tm, &tv.tv_sec);
+
+	do_settimeofday(&tv);
+
+	dev_info(rtc->dev.parent,
+		"setting system clock to "
+		"%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
+		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+		tm.tm_hour, tm.tm_min, tm.tm_sec,
+		(unsigned int) tv.tv_sec);
+
+err_invalid:
+err_read:
 	rtc_class_close(rtc);
 
-	return 0;
+err_open:
+	rtc_hctosys_ret = err;
+
+	return err;
 }
 
 late_initcall(rtc_hctosys);
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 86c61f1..78a018b 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -161,7 +161,7 @@
 	if (offset == 0)
 		return -EILSEQ;
 
-	memset(alrm, 0, sizeof(alrm));
+	memset(alrm, 0, sizeof(*alrm));
 	if (alarm != ALARM_DISABLED && offset != 0) {
 		rtc_time_to_tm(offset + alarm, tm);
 
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c
index 03ea530..44c4399 100644
--- a/drivers/rtc/rtc-coh901331.c
+++ b/drivers/rtc/rtc-coh901331.c
@@ -271,12 +271,13 @@
 {
 	struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev);
 
-	if (device_may_wakeup(&pdev->dev))
+	if (device_may_wakeup(&pdev->dev)) {
 		disable_irq_wake(rtap->irq);
-	else
+	} else {
 		clk_enable(rtap->clk);
 		writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK);
 		clk_disable(rtap->clk);
+	}
 	return 0;
 }
 #else
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
index 9da02d1..91bde97 100644
--- a/drivers/rtc/rtc-ep93xx.c
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -115,6 +115,15 @@
 }
 static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL);
 
+static struct attribute *ep93xx_rtc_attrs[] = {
+	&dev_attr_comp_preload.attr,
+	&dev_attr_comp_delete.attr,
+	NULL
+};
+
+static const struct attribute_group ep93xx_rtc_sysfs_files = {
+	.attrs	= ep93xx_rtc_attrs,
+};
 
 static int __init ep93xx_rtc_probe(struct platform_device *pdev)
 {
@@ -123,27 +132,22 @@
 	struct rtc_device *rtc;
 	int err;
 
-	ep93xx_rtc = kzalloc(sizeof(struct ep93xx_rtc), GFP_KERNEL);
-	if (ep93xx_rtc == NULL)
+	ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL);
+	if (!ep93xx_rtc)
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
-		err = -ENXIO;
-		goto fail_free;
-	}
+	if (!res)
+		return -ENXIO;
 
-	res = request_mem_region(res->start, resource_size(res), pdev->name);
-	if (res == NULL) {
-		err = -EBUSY;
-		goto fail_free;
-	}
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res), pdev->name))
+		return -EBUSY;
 
-	ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res));
-	if (ep93xx_rtc->mmio_base == NULL) {
-		err = -ENXIO;
-		goto fail;
-	}
+	ep93xx_rtc->mmio_base = devm_ioremap(&pdev->dev, res->start,
+					     resource_size(res));
+	if (!ep93xx_rtc->mmio_base)
+		return -ENXIO;
 
 	pdev->dev.platform_data = ep93xx_rtc;
 
@@ -151,52 +155,33 @@
 				&pdev->dev, &ep93xx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
 		err = PTR_ERR(rtc);
-		goto fail;
+		goto exit;
 	}
 
 	platform_set_drvdata(pdev, rtc);
 
-	err = device_create_file(&pdev->dev, &dev_attr_comp_preload);
+	err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
 	if (err)
 		goto fail;
-	err = device_create_file(&pdev->dev, &dev_attr_comp_delete);
-	if (err) {
-		device_remove_file(&pdev->dev, &dev_attr_comp_preload);
-		goto fail;
-	}
 
 	return 0;
 
 fail:
-	if (ep93xx_rtc->mmio_base) {
-		iounmap(ep93xx_rtc->mmio_base);
-		pdev->dev.platform_data = NULL;
-	}
-	release_mem_region(res->start, resource_size(res));
-fail_free:
-	kfree(ep93xx_rtc);
+	platform_set_drvdata(pdev, NULL);
+	rtc_device_unregister(rtc);
+exit:
+	pdev->dev.platform_data = NULL;
 	return err;
 }
 
 static int __exit ep93xx_rtc_remove(struct platform_device *pdev)
 {
 	struct rtc_device *rtc = platform_get_drvdata(pdev);
-	struct ep93xx_rtc *ep93xx_rtc = pdev->dev.platform_data;
-	struct resource *res;
 
-	/* cleanup sysfs */
-	device_remove_file(&pdev->dev, &dev_attr_comp_delete);
-	device_remove_file(&pdev->dev, &dev_attr_comp_preload);
-
-	rtc_device_unregister(rtc);
-
-	iounmap(ep93xx_rtc->mmio_base);
-	pdev->dev.platform_data = NULL;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
+	sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
 	platform_set_drvdata(pdev, NULL);
+	rtc_device_unregister(rtc);
+	pdev->dev.platform_data = NULL;
 
 	return 0;
 }
diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c
new file mode 100644
index 0000000..acdbb17
--- /dev/null
+++ b/drivers/rtc/rtc-max8925.c
@@ -0,0 +1,314 @@
+/*
+ * RTC driver for Maxim MAX8925
+ *
+ * Copyright (C) 2009-2010 Marvell International Ltd.
+ *	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/max8925.h>
+
+enum {
+	RTC_SEC = 0,
+	RTC_MIN,
+	RTC_HOUR,
+	RTC_WEEKDAY,
+	RTC_DATE,
+	RTC_MONTH,
+	RTC_YEAR1,
+	RTC_YEAR2,
+};
+
+#define MAX8925_RTC_SEC			0x00
+#define MAX8925_RTC_MIN			0x01
+#define MAX8925_RTC_HOUR		0x02
+#define MAX8925_RTC_WEEKDAY		0x03
+#define MAX8925_RTC_DATE		0x04
+#define MAX8925_RTC_MONTH		0x05
+#define MAX8925_RTC_YEAR1		0x06
+#define MAX8925_RTC_YEAR2		0x07
+#define MAX8925_ALARM0_SEC		0x08
+#define MAX8925_ALARM0_MIN		0x09
+#define MAX8925_ALARM0_HOUR		0x0a
+#define MAX8925_ALARM0_WEEKDAY		0x0b
+#define MAX8925_ALARM0_DATE		0x0c
+#define MAX8925_ALARM0_MON		0x0d
+#define MAX8925_ALARM0_YEAR1		0x0e
+#define MAX8925_ALARM0_YEAR2		0x0f
+#define MAX8925_ALARM1_SEC		0x10
+#define MAX8925_ALARM1_MIN		0x11
+#define MAX8925_ALARM1_HOUR		0x12
+#define MAX8925_ALARM1_WEEKDAY		0x13
+#define MAX8925_ALARM1_DATE		0x14
+#define MAX8925_ALARM1_MON		0x15
+#define MAX8925_ALARM1_YEAR1		0x16
+#define MAX8925_ALARM1_YEAR2		0x17
+#define MAX8925_RTC_CNTL		0x1b
+#define MAX8925_RTC_STATUS		0x20
+
+#define TIME_NUM			8
+#define ALARM_1SEC			(1 << 7)
+#define HOUR_12				(1 << 7)
+#define HOUR_AM_PM			(1 << 5)
+#define ALARM0_IRQ			(1 << 3)
+#define ALARM1_IRQ			(1 << 2)
+#define ALARM0_STATUS			(1 << 2)
+#define ALARM1_STATUS			(1 << 1)
+
+
+struct max8925_rtc_info {
+	struct rtc_device	*rtc_dev;
+	struct max8925_chip	*chip;
+	struct i2c_client	*rtc;
+	struct device		*dev;
+};
+
+static irqreturn_t rtc_update_handler(int irq, void *data)
+{
+	struct max8925_rtc_info *info = (struct max8925_rtc_info *)data;
+
+	/* disable ALARM0 except for 1SEC alarm */
+	max8925_set_bits(info->rtc, MAX8925_ALARM0_CNTL, 0x7f, 0);
+	rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
+	return IRQ_HANDLED;
+}
+
+static int tm_calc(struct rtc_time *tm, unsigned char *buf, int len)
+{
+	if (len < TIME_NUM)
+		return -EINVAL;
+	tm->tm_year = (buf[RTC_YEAR2] >> 4) * 1000
+			+ (buf[RTC_YEAR2] & 0xf) * 100
+			+ (buf[RTC_YEAR1] >> 4) * 10
+			+ (buf[RTC_YEAR1] & 0xf);
+	tm->tm_year -= 1900;
+	tm->tm_mon = ((buf[RTC_MONTH] >> 4) & 0x01) * 10
+			+ (buf[RTC_MONTH] & 0x0f);
+	tm->tm_mday = ((buf[RTC_DATE] >> 4) & 0x03) * 10
+			+ (buf[RTC_DATE] & 0x0f);
+	tm->tm_wday = buf[RTC_WEEKDAY] & 0x07;
+	if (buf[RTC_HOUR] & HOUR_12) {
+		tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x1) * 10
+				+ (buf[RTC_HOUR] & 0x0f);
+		if (buf[RTC_HOUR] & HOUR_AM_PM)
+			tm->tm_hour += 12;
+	} else
+		tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x03) * 10
+				+ (buf[RTC_HOUR] & 0x0f);
+	tm->tm_min = ((buf[RTC_MIN] >> 4) & 0x7) * 10
+			+ (buf[RTC_MIN] & 0x0f);
+	tm->tm_sec = ((buf[RTC_SEC] >> 4) & 0x7) * 10
+			+ (buf[RTC_SEC] & 0x0f);
+	return 0;
+}
+
+static int data_calc(unsigned char *buf, struct rtc_time *tm, int len)
+{
+	unsigned char high, low;
+
+	if (len < TIME_NUM)
+		return -EINVAL;
+
+	high = (tm->tm_year + 1900) / 1000;
+	low = (tm->tm_year + 1900) / 100;
+	low = low - high * 10;
+	buf[RTC_YEAR2] = (high << 4) + low;
+	high = (tm->tm_year + 1900) / 10;
+	low = tm->tm_year + 1900;
+	low = low - high * 10;
+	high = high - (high / 10) * 10;
+	buf[RTC_YEAR1] = (high << 4) + low;
+	high = tm->tm_mon / 10;
+	low = tm->tm_mon;
+	low = low - high * 10;
+	buf[RTC_MONTH] = (high << 4) + low;
+	high = tm->tm_mday / 10;
+	low = tm->tm_mday;
+	low = low - high * 10;
+	buf[RTC_DATE] = (high << 4) + low;
+	buf[RTC_WEEKDAY] = tm->tm_wday;
+	high = tm->tm_hour / 10;
+	low = tm->tm_hour;
+	low = low - high * 10;
+	buf[RTC_HOUR] = (high << 4) + low;
+	high = tm->tm_min / 10;
+	low = tm->tm_min;
+	low = low - high * 10;
+	buf[RTC_MIN] = (high << 4) + low;
+	high = tm->tm_sec / 10;
+	low = tm->tm_sec;
+	low = low - high * 10;
+	buf[RTC_SEC] = (high << 4) + low;
+	return 0;
+}
+
+static int max8925_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct max8925_rtc_info *info = dev_get_drvdata(dev);
+	unsigned char buf[TIME_NUM];
+	int ret;
+
+	ret = max8925_bulk_read(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf);
+	if (ret < 0)
+		goto out;
+	ret = tm_calc(tm, buf, TIME_NUM);
+out:
+	return ret;
+}
+
+static int max8925_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct max8925_rtc_info *info = dev_get_drvdata(dev);
+	unsigned char buf[TIME_NUM];
+	int ret;
+
+	ret = data_calc(buf, tm, TIME_NUM);
+	if (ret < 0)
+		goto out;
+	ret = max8925_bulk_write(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf);
+out:
+	return ret;
+}
+
+static int max8925_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct max8925_rtc_info *info = dev_get_drvdata(dev);
+	unsigned char buf[TIME_NUM];
+	int ret;
+
+	ret = max8925_bulk_read(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf);
+	if (ret < 0)
+		goto out;
+	ret = tm_calc(&alrm->time, buf, TIME_NUM);
+	if (ret < 0)
+		goto out;
+	ret = max8925_reg_read(info->rtc, MAX8925_RTC_IRQ_MASK);
+	if (ret < 0)
+		goto out;
+	if ((ret & ALARM0_IRQ) == 0)
+		alrm->enabled = 1;
+	else
+		alrm->enabled = 0;
+	ret = max8925_reg_read(info->rtc, MAX8925_RTC_STATUS);
+	if (ret < 0)
+		goto out;
+	if (ret & ALARM0_STATUS)
+		alrm->pending = 1;
+	else
+		alrm->pending = 0;
+out:
+	return ret;
+}
+
+static int max8925_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct max8925_rtc_info *info = dev_get_drvdata(dev);
+	unsigned char buf[TIME_NUM];
+	int ret;
+
+	ret = data_calc(buf, &alrm->time, TIME_NUM);
+	if (ret < 0)
+		goto out;
+	ret = max8925_bulk_write(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf);
+	if (ret < 0)
+		goto out;
+	/* only enable alarm on year/month/day/hour/min/sec */
+	ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77);
+	if (ret < 0)
+		goto out;
+out:
+	return ret;
+}
+
+static const struct rtc_class_ops max8925_rtc_ops = {
+	.read_time	= max8925_rtc_read_time,
+	.set_time	= max8925_rtc_set_time,
+	.read_alarm	= max8925_rtc_read_alarm,
+	.set_alarm	= max8925_rtc_set_alarm,
+};
+
+static int __devinit max8925_rtc_probe(struct platform_device *pdev)
+{
+	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct max8925_rtc_info *info;
+	int irq, ret;
+
+	info = kzalloc(sizeof(struct max8925_rtc_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+	info->chip = chip;
+	info->rtc = chip->rtc;
+	info->dev = &pdev->dev;
+	irq = chip->irq_base + MAX8925_IRQ_RTC_ALARM0;
+
+	ret = request_threaded_irq(irq, NULL, rtc_update_handler,
+				   IRQF_ONESHOT, "rtc-alarm0", info);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
+			irq, ret);
+		goto out_irq;
+	}
+
+	info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev,
+					&max8925_rtc_ops, THIS_MODULE);
+	ret = PTR_ERR(info->rtc_dev);
+	if (IS_ERR(info->rtc_dev)) {
+		dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
+		goto out_rtc;
+	}
+
+	dev_set_drvdata(&pdev->dev, info);
+	platform_set_drvdata(pdev, info);
+
+	return 0;
+out_rtc:
+	free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
+out_irq:
+	kfree(info);
+	return ret;
+}
+
+static int __devexit max8925_rtc_remove(struct platform_device *pdev)
+{
+	struct max8925_rtc_info *info = platform_get_drvdata(pdev);
+
+	if (info) {
+		free_irq(info->chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
+		rtc_device_unregister(info->rtc_dev);
+		kfree(info);
+	}
+	return 0;
+}
+
+static struct platform_driver max8925_rtc_driver = {
+	.driver		= {
+		.name	= "max8925-rtc",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= max8925_rtc_probe,
+	.remove		= __devexit_p(max8925_rtc_remove),
+};
+
+static int __init max8925_rtc_init(void)
+{
+	return platform_driver_register(&max8925_rtc_driver);
+}
+module_init(max8925_rtc_init);
+
+static void __exit max8925_rtc_exit(void)
+{
+	platform_driver_unregister(&max8925_rtc_driver);
+}
+module_exit(max8925_rtc_exit);
+
+MODULE_DESCRIPTION("Maxim MAX8925 RTC driver");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c
index 850f983..d60c81b 100644
--- a/drivers/rtc/rtc-mc13783.c
+++ b/drivers/rtc/rtc-mc13783.c
@@ -28,6 +28,34 @@
 	int valid;
 };
 
+static int mc13783_rtc_irq_enable_unlocked(struct device *dev,
+		unsigned int enabled, int irq)
+{
+	struct mc13783_rtc *priv = dev_get_drvdata(dev);
+	int (*func)(struct mc13783 *mc13783, int irq);
+
+	if (!priv->valid)
+		return -ENODATA;
+
+	func = enabled ? mc13783_irq_unmask : mc13783_irq_mask;
+	return func(priv->mc13783, irq);
+}
+
+static int mc13783_rtc_irq_enable(struct device *dev,
+		unsigned int enabled, int irq)
+{
+	struct mc13783_rtc *priv = dev_get_drvdata(dev);
+	int ret;
+
+	mc13783_lock(priv->mc13783);
+
+	ret = mc13783_rtc_irq_enable_unlocked(dev, enabled, irq);
+
+	mc13783_unlock(priv->mc13783);
+
+	return ret;
+}
+
 static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	struct mc13783_rtc *priv = dev_get_drvdata(dev);
@@ -78,6 +106,7 @@
 {
 	struct mc13783_rtc *priv = dev_get_drvdata(dev);
 	unsigned int seconds, days;
+	unsigned int alarmseconds;
 	int ret;
 
 	seconds = secs % 86400;
@@ -86,7 +115,22 @@
 	mc13783_lock(priv->mc13783);
 
 	/*
-	 * first write seconds=0 to prevent a day switch between writing days
+	 * temporarily invalidate alarm to prevent triggering it when the day is
+	 * already updated while the time isn't yet.
+	 */
+	ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &alarmseconds);
+	if (unlikely(ret))
+		goto out;
+
+	if (alarmseconds < 86400) {
+		ret = mc13783_reg_write(priv->mc13783,
+				MC13783_RTCTODA, 0x1ffff);
+		if (unlikely(ret))
+			goto out;
+	}
+
+	/*
+	 * write seconds=0 to prevent a day switch between writing days
 	 * and seconds below
 	 */
 	ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0);
@@ -101,11 +145,19 @@
 	if (unlikely(ret))
 		goto out;
 
-	ret = mc13783_ackirq(priv->mc13783, MC13783_IRQ_RTCRST);
+	/* restore alarm */
+	if (alarmseconds < 86400) {
+		ret = mc13783_reg_write(priv->mc13783,
+				MC13783_RTCTODA, alarmseconds);
+		if (unlikely(ret))
+			goto out;
+	}
+
+	ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_RTCRST);
 	if (unlikely(ret))
 		goto out;
 
-	ret = mc13783_unmask(priv->mc13783, MC13783_IRQ_RTCRST);
+	ret = mc13783_irq_unmask(priv->mc13783, MC13783_IRQ_RTCRST);
 out:
 	priv->valid = !ret;
 
@@ -114,6 +166,107 @@
 	return ret;
 }
 
+static int mc13783_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct mc13783_rtc *priv = dev_get_drvdata(dev);
+	unsigned seconds, days;
+	unsigned long s1970;
+	int enabled, pending;
+	int ret;
+
+	mc13783_lock(priv->mc13783);
+
+	ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &seconds);
+	if (unlikely(ret))
+		goto out;
+	if (seconds >= 86400) {
+		ret = -ENODATA;
+		goto out;
+	}
+
+	ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days);
+	if (unlikely(ret))
+		goto out;
+
+	ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_TODA,
+			&enabled, &pending);
+
+out:
+	mc13783_unlock(priv->mc13783);
+
+	if (ret)
+		return ret;
+
+	alarm->enabled = enabled;
+	alarm->pending = pending;
+
+	s1970 = days * 86400 + seconds;
+
+	rtc_time_to_tm(s1970, &alarm->time);
+	dev_dbg(dev, "%s: %lu\n", __func__, s1970);
+
+	return 0;
+}
+
+static int mc13783_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct mc13783_rtc *priv = dev_get_drvdata(dev);
+	unsigned long s1970;
+	unsigned seconds, days;
+	int ret;
+
+	mc13783_lock(priv->mc13783);
+
+	/* disable alarm to prevent false triggering */
+	ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, 0x1ffff);
+	if (unlikely(ret))
+		goto out;
+
+	ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TODA);
+	if (unlikely(ret))
+		goto out;
+
+	ret = rtc_tm_to_time(&alarm->time, &s1970);
+	if (unlikely(ret))
+		goto out;
+
+	dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff",
+			s1970);
+
+	ret = mc13783_rtc_irq_enable_unlocked(dev, alarm->enabled,
+			MC13783_IRQ_TODA);
+	if (unlikely(ret))
+		goto out;
+
+	seconds = s1970 % 86400;
+	days = s1970 / 86400;
+
+	ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAYA, days);
+	if (unlikely(ret))
+		goto out;
+
+	ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, seconds);
+
+out:
+	mc13783_unlock(priv->mc13783);
+
+	return ret;
+}
+
+static irqreturn_t mc13783_rtc_alarm_handler(int irq, void *dev)
+{
+	struct mc13783_rtc *priv = dev;
+	struct mc13783 *mc13783 = priv->mc13783;
+
+	dev_dbg(&priv->rtc->dev, "Alarm\n");
+
+	rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF);
+
+	mc13783_irq_ack(mc13783, irq);
+
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev)
 {
 	struct mc13783_rtc *priv = dev;
@@ -123,7 +276,7 @@
 
 	rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF);
 
-	mc13783_ackirq(mc13783, irq);
+	mc13783_irq_ack(mc13783, irq);
 
 	return IRQ_HANDLED;
 }
@@ -131,24 +284,21 @@
 static int mc13783_rtc_update_irq_enable(struct device *dev,
 		unsigned int enabled)
 {
-	struct mc13783_rtc *priv = dev_get_drvdata(dev);
-	int ret = -ENODATA;
+	return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_1HZ);
+}
 
-	mc13783_lock(priv->mc13783);
-	if (!priv->valid)
-		goto out;
-
-	ret = (enabled ? mc13783_unmask : mc13783_mask)(priv->mc13783,
-			MC13783_IRQ_1HZ);
-out:
-	mc13783_unlock(priv->mc13783);
-
-	return ret;
+static int mc13783_rtc_alarm_irq_enable(struct device *dev,
+		unsigned int enabled)
+{
+	return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_TODA);
 }
 
 static const struct rtc_class_ops mc13783_rtc_ops = {
 	.read_time = mc13783_rtc_read_time,
 	.set_mmss = mc13783_rtc_set_mmss,
+	.read_alarm = mc13783_rtc_read_alarm,
+	.set_alarm = mc13783_rtc_set_alarm,
+	.alarm_irq_enable = mc13783_rtc_alarm_irq_enable,
 	.update_irq_enable = mc13783_rtc_update_irq_enable,
 };
 
@@ -160,7 +310,7 @@
 	dev_dbg(&priv->rtc->dev, "RTCRST\n");
 	priv->valid = 0;
 
-	mc13783_mask(mc13783, irq);
+	mc13783_irq_mask(mc13783, irq);
 
 	return IRQ_HANDLED;
 }
@@ -169,6 +319,7 @@
 {
 	int ret;
 	struct mc13783_rtc *priv;
+	int rtcrst_pending;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -177,8 +328,6 @@
 	priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
 	platform_set_drvdata(pdev, priv);
 
-	priv->valid = 1;
-
 	mc13783_lock(priv->mc13783);
 
 	ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST,
@@ -186,33 +335,45 @@
 	if (ret)
 		goto err_reset_irq_request;
 
+	ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_RTCRST,
+			NULL, &rtcrst_pending);
+	if (ret)
+		goto err_reset_irq_status;
+
+	priv->valid = !rtcrst_pending;
+
 	ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ,
 			mc13783_rtc_update_handler, DRIVER_NAME, priv);
 	if (ret)
 		goto err_update_irq_request;
 
-	mc13783_unlock(priv->mc13783);
+	ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_TODA,
+			mc13783_rtc_alarm_handler, DRIVER_NAME, priv);
+	if (ret)
+		goto err_alarm_irq_request;
 
 	priv->rtc = rtc_device_register(pdev->name,
 			&pdev->dev, &mc13783_rtc_ops, THIS_MODULE);
-
 	if (IS_ERR(priv->rtc)) {
 		ret = PTR_ERR(priv->rtc);
 
-		mc13783_lock(priv->mc13783);
+		mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv);
+err_alarm_irq_request:
 
 		mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
 err_update_irq_request:
 
+err_reset_irq_status:
+
 		mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
 err_reset_irq_request:
 
-		mc13783_unlock(priv->mc13783);
-
 		platform_set_drvdata(pdev, NULL);
 		kfree(priv);
 	}
 
+	mc13783_unlock(priv->mc13783);
+
 	return ret;
 }
 
@@ -220,10 +381,11 @@
 {
 	struct mc13783_rtc *priv = platform_get_drvdata(pdev);
 
-	rtc_device_unregister(priv->rtc);
-
 	mc13783_lock(priv->mc13783);
 
+	rtc_device_unregister(priv->rtc);
+
+	mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv);
 	mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
 	mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
 
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index 6bd5072..8710f94 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -396,8 +396,11 @@
 	pdata->ioaddr = ioremap(res->start, resource_size(res));
 
 	clk = clk_get(&pdev->dev, "ckil");
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	if (IS_ERR(clk)) {
+		iounmap(pdata->ioaddr);
+		ret = PTR_ERR(clk);
+		goto exit_free_pdata;
+	}
 
 	rate = clk_get_rate(clk);
 	clk_put(clk);
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index e75df9d..2ceb365 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -315,7 +315,7 @@
 	return ret;
 }
 
-static int pcf2123_remove(struct spi_device *spi)
+static int __devexit pcf2123_remove(struct spi_device *spi)
 {
 	struct pcf2123_plat_data *pdata = spi->dev.platform_data;
 	int i;
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 7dd23a6..380083c 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -107,8 +107,9 @@
 		char *buf)
 {
 #ifdef CONFIG_RTC_HCTOSYS_DEVICE
-	if (strcmp(dev_name(&to_rtc_device(dev)->dev),
-		   CONFIG_RTC_HCTOSYS_DEVICE) == 0)
+	if (rtc_hctosys_ret == 0 &&
+			strcmp(dev_name(&to_rtc_device(dev)->dev),
+				CONFIG_RTC_HCTOSYS_DEVICE) == 0)
 		return sprintf(buf, "1\n");
 	else
 #endif
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index c6a83a2..ed1b868 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -57,7 +57,7 @@
 	REG_RTC_COMP_LSB_REG,
 	REG_RTC_COMP_MSB_REG,
 };
-const static u8 twl4030_rtc_reg_map[] = {
+static const u8 twl4030_rtc_reg_map[] = {
 	[REG_SECONDS_REG] = 0x00,
 	[REG_MINUTES_REG] = 0x01,
 	[REG_HOURS_REG] = 0x02,
@@ -80,7 +80,7 @@
 	[REG_RTC_COMP_LSB_REG] = 0x10,
 	[REG_RTC_COMP_MSB_REG] = 0x11,
 };
-const static u8 twl6030_rtc_reg_map[] = {
+static const u8 twl6030_rtc_reg_map[] = {
 	[REG_SECONDS_REG] = 0x00,
 	[REG_MINUTES_REG] = 0x01,
 	[REG_HOURS_REG] = 0x02,
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
index f1e44052..3d0dc76 100644
--- a/drivers/rtc/rtc-wm8350.c
+++ b/drivers/rtc/rtc-wm8350.c
@@ -307,11 +307,18 @@
 {
 	struct wm8350 *wm8350 = dev_get_drvdata(dev);
 
+	/* Suppress duplicate changes since genirq nests enable and
+	 * disable calls. */
+	if (enabled == wm8350->rtc.update_enabled)
+		return 0;
+
 	if (enabled)
 		wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC);
 	else
 		wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
 
+	wm8350->rtc.update_enabled = enabled;
+
 	return 0;
 }
 
@@ -478,8 +485,8 @@
 	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
 	struct wm8350_rtc *wm_rtc = &wm8350->rtc;
 
-	wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC);
-	wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM);
+	wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350);
 
 	rtc_device_unregister(wm_rtc->rtc);
 
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 4951aa8..bbea90b 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -26,6 +26,7 @@
 #include <asm/ebcdic.h>
 #include <asm/idals.h>
 #include <asm/itcw.h>
+#include <asm/diag.h>
 
 /* This is ugly... */
 #define PRINTK_HEADER "dasd:"
@@ -2212,6 +2213,13 @@
 		goto out;
 	}
 
+	if ((mode & FMODE_WRITE) &&
+	    (test_bit(DASD_FLAG_DEVICE_RO, &base->flags) ||
+	     (base->features & DASD_FEATURE_READONLY))) {
+		rc = -EROFS;
+		goto out;
+	}
+
 	return 0;
 
 out:
@@ -2289,6 +2297,34 @@
  * SECTION: common functions for ccw_driver use
  */
 
+/*
+ * Is the device read-only?
+ * Note that this function does not report the setting of the
+ * readonly device attribute, but how it is configured in z/VM.
+ */
+int dasd_device_is_ro(struct dasd_device *device)
+{
+	struct ccw_dev_id dev_id;
+	struct diag210 diag_data;
+	int rc;
+
+	if (!MACHINE_IS_VM)
+		return 0;
+	ccw_device_get_id(device->cdev, &dev_id);
+	memset(&diag_data, 0, sizeof(diag_data));
+	diag_data.vrdcdvno = dev_id.devno;
+	diag_data.vrdclen = sizeof(diag_data);
+	rc = diag210(&diag_data);
+	if (rc == 0 || rc == 2) {
+		return diag_data.vrdcvfla & 0x80;
+	} else {
+		DBF_EVENT(DBF_WARNING, "diag210 failed for dev=%04x with rc=%d",
+			  dev_id.devno, rc);
+		return 0;
+	}
+}
+EXPORT_SYMBOL_GPL(dasd_device_is_ro);
+
 static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
 {
 	struct ccw_device *cdev = data;
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 44796ba..51224f7 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -1045,6 +1045,10 @@
 
 		erp->retries = 5;
 
+	} else if (sense[1] & SNS1_WRITE_INHIBITED) {
+		dev_err(&device->cdev->dev, "An I/O request was rejected"
+			" because writing is inhibited\n");
+		erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
 	} else {
 		/* fatal error -  set status to FAILED
 		   internal error 09 - Command Reject */
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index d49766f..8e23919 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -742,6 +742,7 @@
 	      const char *buf, size_t count)
 {
 	struct dasd_devmap *devmap;
+	struct dasd_device *device;
 	int val;
 	char *endp;
 
@@ -758,12 +759,14 @@
 		devmap->features |= DASD_FEATURE_READONLY;
 	else
 		devmap->features &= ~DASD_FEATURE_READONLY;
-	if (devmap->device)
-		devmap->device->features = devmap->features;
-	if (devmap->device && devmap->device->block
-	    && devmap->device->block->gdp)
-		set_disk_ro(devmap->device->block->gdp, val);
+	device = devmap->device;
+	if (device) {
+		device->features = devmap->features;
+		val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags);
+	}
 	spin_unlock(&dasd_devmap_lock);
+	if (device && device->block && device->block->gdp)
+		set_disk_ro(device->block->gdp, val);
 	return count;
 }
 
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 6e14863..687f323 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -145,12 +145,10 @@
 	mdsk_term_io(device);
 	rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);
 	if (rc == 4) {
-		if (!(device->features & DASD_FEATURE_READONLY)) {
+		if (!(test_and_set_bit(DASD_FLAG_DEVICE_RO, &device->flags)))
 			pr_warning("%s: The access mode of a DIAG device "
 				   "changed to read-only\n",
 				   dev_name(&device->cdev->dev));
-			device->features |= DASD_FEATURE_READONLY;
-		}
 		rc = 0;
 	}
 	if (rc)
@@ -449,7 +447,7 @@
 		rc = -EIO;
 	} else {
 		if (rc == 4)
-			device->features |= DASD_FEATURE_READONLY;
+			set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
 		pr_info("%s: New DASD with %ld byte/block, total size %ld "
 			"KB%s\n", dev_name(&device->cdev->dev),
 			(unsigned long) block->bp_block,
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 1cca21a..01f4e7a 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1089,6 +1089,7 @@
 	struct dasd_eckd_private *private;
 	struct dasd_block *block;
 	int is_known, rc;
+	int readonly;
 
 	if (!ccw_device_is_pathgroup(device->cdev)) {
 		dev_warn(&device->cdev->dev,
@@ -1182,15 +1183,20 @@
 	else
 		private->real_cyl = private->rdc_data.no_cyl;
 
+	readonly = dasd_device_is_ro(device);
+	if (readonly)
+		set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
+
 	dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) "
-		 "with %d cylinders, %d heads, %d sectors\n",
+		 "with %d cylinders, %d heads, %d sectors%s\n",
 		 private->rdc_data.dev_type,
 		 private->rdc_data.dev_model,
 		 private->rdc_data.cu_type,
 		 private->rdc_data.cu_model.model,
 		 private->real_cyl,
 		 private->rdc_data.trk_per_cyl,
-		 private->rdc_data.sec_per_trk);
+		 private->rdc_data.sec_per_trk,
+		 readonly ? ", read-only device" : "");
 	return 0;
 
 out_err3:
@@ -2839,8 +2845,13 @@
 	char *psf_data, *rssd_result;
 	struct dasd_ccw_req *cqr;
 	struct ccw1 *ccw;
+	char psf0, psf1;
 	int rc;
 
+	if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
+		return -EACCES;
+	psf0 = psf1 = 0;
+
 	/* Copy parms from caller */
 	rc = -EFAULT;
 	if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
@@ -2869,12 +2880,8 @@
 			   (void __user *)(unsigned long) usrparm.psf_data,
 			   usrparm.psf_data_len))
 		goto out_free;
-
-	/* sanity check on syscall header */
-	if (psf_data[0] != 0x17 && psf_data[1] != 0xce) {
-		rc = -EINVAL;
-		goto out_free;
-	}
+	psf0 = psf_data[0];
+	psf1 = psf_data[1];
 
 	/* setup CCWs for PSF + RSSD */
 	cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 , 0, device);
@@ -2925,7 +2932,9 @@
 	kfree(rssd_result);
 	kfree(psf_data);
 out:
-	DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc);
+	DBF_DEV_EVENT(DBF_WARNING, device,
+		      "Symmetrix ioctl (0x%02x 0x%02x): rc=%d",
+		      (int) psf0, (int) psf1, rc);
 	return rc;
 }
 
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 0f15244..37282b9 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -124,6 +124,7 @@
 	struct dasd_fba_private *private;
 	struct ccw_device *cdev = device->cdev;
 	int rc;
+	int readonly;
 
 	private = (struct dasd_fba_private *) device->private;
 	if (!private) {
@@ -162,16 +163,21 @@
 		return rc;
 	}
 
+	readonly = dasd_device_is_ro(device);
+	if (readonly)
+		set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
+
 	dev_info(&device->cdev->dev,
 		 "New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB "
-		 "and %d B/blk\n",
+		 "and %d B/blk%s\n",
 		 cdev->id.dev_type,
 		 cdev->id.dev_model,
 		 cdev->id.cu_type,
 		 cdev->id.cu_model,
 		 ((private->rdc_data.blk_bdsa *
 		   (private->rdc_data.blk_size >> 9)) >> 11),
-		 private->rdc_data.blk_size);
+		 private->rdc_data.blk_size,
+		 readonly ? ", read-only device" : "");
 	return 0;
 }
 
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 94f92a1..30a1ca3 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -70,7 +70,8 @@
 	}
 	len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26));
 
-	if (block->base->features & DASD_FEATURE_READONLY)
+	if (base->features & DASD_FEATURE_READONLY ||
+	    test_bit(DASD_FLAG_DEVICE_RO, &base->flags))
 		set_disk_ro(gdp, 1);
 	gdp->private_data = block;
 	gdp->queue = block->request_queue;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index ed73ce5..a91d4a9 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -436,6 +436,10 @@
 #define DASD_FLAG_OFFLINE	3	/* device is in offline processing */
 #define DASD_FLAG_EER_SNSS	4	/* A SNSS is required */
 #define DASD_FLAG_EER_IN_USE	5	/* A SNSS request is running */
+#define DASD_FLAG_DEVICE_RO	6	/* The device itself is read-only. Don't
+					 * confuse this with the user specified
+					 * read-only feature.
+					 */
 
 void dasd_put_device_wake(struct dasd_device *);
 
@@ -609,6 +613,9 @@
 void dasd_device_set_stop_bits(struct dasd_device *, int);
 void dasd_device_remove_stop_bits(struct dasd_device *, int);
 
+int dasd_device_is_ro(struct dasd_device *);
+
+
 /* externals in dasd_devmap.c */
 extern int dasd_max_devindex;
 extern int dasd_probeonly;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 7039d9c..3479f81 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -199,7 +199,8 @@
 	if (!argp)
 		return -EINVAL;
 
-	if (block->base->features & DASD_FEATURE_READONLY)
+	if (block->base->features & DASD_FEATURE_READONLY ||
+	    test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
 		return -EROFS;
 	if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
 		return -EFAULT;
@@ -349,7 +350,8 @@
 		return -EINVAL;
 	if (get_user(intval, (int __user *)argp))
 		return -EFAULT;
-
+	if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
+		return -EROFS;
 	set_disk_ro(bdev->bd_disk, intval);
 	return dasd_set_feature(block->base->cdev, DASD_FEATURE_READONLY, intval);
 }
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 62ddf52..2a4c566 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -373,7 +373,7 @@
 		rq->rc = ccw_device_start(rp->cdev, &rq->ccw,
 					  (unsigned long) rq, 0, 0);
 		if (rq->rc == 0)
-			return;	/* Sucessfully restarted. */
+			return;	/* Successfully restarted. */
 		break;
 	case RAW3270_IO_STOP:
 		if (!rq)
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index ec88c59..f6d72e1 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -196,7 +196,7 @@
 	req->start_count++;
 
 	if (rc == 0) {
-		/* Sucessfully started request */
+		/* Successfully started request */
 		req->status = SCLP_REQ_RUNNING;
 		sclp_running_state = sclp_running_state_running;
 		__sclp_set_request_timer(SCLP_RETRY_INTERVAL * HZ,
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index c6abb75..6d229f3 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -764,7 +764,7 @@
 static void io_subchannel_register(struct ccw_device *cdev)
 {
 	struct subchannel *sch;
-	int ret;
+	int ret, adjust_init_count = 1;
 	unsigned long flags;
 
 	sch = to_subchannel(cdev->dev.parent);
@@ -793,6 +793,7 @@
 					      cdev->private->dev_id.ssid,
 					      cdev->private->dev_id.devno);
 		}
+		adjust_init_count = 0;
 		goto out;
 	}
 	/*
@@ -818,7 +819,7 @@
 	cdev->private->flags.recog_done = 1;
 	wake_up(&cdev->private->wait_q);
 out_err:
-	if (atomic_dec_and_test(&ccw_device_init_count))
+	if (adjust_init_count && atomic_dec_and_test(&ccw_device_init_count))
 		wake_up(&ccw_device_init_wq);
 }
 
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index c94eb2a..6ce83f5 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -33,7 +33,6 @@
 	DBF_HEX(&init_data->input_handler, sizeof(void *));
 	DBF_HEX(&init_data->output_handler, sizeof(void *));
 	DBF_HEX(&init_data->int_parm, sizeof(long));
-	DBF_HEX(&init_data->flags, sizeof(long));
 	DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
 	DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
 	DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 232ef04..4f8f743 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -588,10 +588,11 @@
 	if (q->is_input_q) {
 		qperf_inc(q, inbound_handler);
 		DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count);
-	} else
+	} else {
 		qperf_inc(q, outbound_handler);
 		DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x",
 			      start, count);
+	}
 
 	q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count,
 		   q->irq_ptr->int_parm);
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index cb909a5..977bb4d 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -43,6 +43,16 @@
 	  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)"
+	depends on SMSGIUCV
+	help
+	  Select this option to deliver CP special messages (SMSGs) as
+	  uevents.  The driver handles only those special messages that
+	  start with "APP".
+
+	  To compile as a module, choose M. The module name is "smsgiucv_app".
+
 config CLAW
 	tristate "CLAW device support"
 	depends on CCW && NETDEVICES
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 6cab5a6..4dfe8c1 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_CTCM) += ctcm.o fsm.o
 obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
 obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
+obj-$(CONFIG_SMSGIUCV_EVENT) += smsgiucv_app.o
 obj-$(CONFIG_LCS) += lcs.o
 obj-$(CONFIG_CLAW) += claw.o
 qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index c9f5af5..3bd4206 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -3804,9 +3804,6 @@
 	init_data.input_handler          = card->discipline.input_handler;
 	init_data.output_handler         = card->discipline.output_handler;
 	init_data.int_parm               = (unsigned long) card;
-	init_data.flags                  = QDIO_INBOUND_0COPY_SBALS |
-					   QDIO_OUTBOUND_0COPY_SBALS |
-					   QDIO_USE_OUTBOUND_PCIS;
 	init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
 	init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
 
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index 67f2485..ecef1ed 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -31,9 +31,9 @@
 
 struct smsg_callback {
 	struct list_head list;
-	char *prefix;
+	const char *prefix;
 	int len;
-	void (*callback)(char *from, char *str);
+	void (*callback)(const char *from, char *str);
 };
 
 MODULE_AUTHOR
@@ -100,8 +100,8 @@
 	kfree(buffer);
 }
 
-int smsg_register_callback(char *prefix,
-			   void (*callback)(char *from, char *str))
+int smsg_register_callback(const char *prefix,
+			   void (*callback)(const char *from, char *str))
 {
 	struct smsg_callback *cb;
 
@@ -117,8 +117,9 @@
 	return 0;
 }
 
-void smsg_unregister_callback(char *prefix,
-			      void (*callback)(char *from, char *str))
+void smsg_unregister_callback(const char *prefix,
+			      void (*callback)(const char *from,
+					       char *str))
 {
 	struct smsg_callback *cb, *tmp;
 
@@ -176,7 +177,7 @@
 
 static struct device_driver smsg_driver = {
 	.owner = THIS_MODULE,
-	.name = "SMSGIUCV",
+	.name = SMSGIUCV_DRV_NAME,
 	.bus  = &iucv_bus,
 	.pm = &smsg_pm_ops,
 };
diff --git a/drivers/s390/net/smsgiucv.h b/drivers/s390/net/smsgiucv.h
index 67f5d4f..149a115 100644
--- a/drivers/s390/net/smsgiucv.h
+++ b/drivers/s390/net/smsgiucv.h
@@ -5,6 +5,10 @@
  * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
-int  smsg_register_callback(char *, void (*)(char *, char *));
-void smsg_unregister_callback(char *, void (*)(char *, char *));
+#define SMSGIUCV_DRV_NAME     "SMSGIUCV"
+
+int  smsg_register_callback(const char *,
+			    void (*)(const char *, char *));
+void smsg_unregister_callback(const char *,
+			      void (*)(const char *, char *));
 
diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c
new file mode 100644
index 0000000..91579dc
--- /dev/null
+++ b/drivers/s390/net/smsgiucv_app.c
@@ -0,0 +1,211 @@
+/*
+ * Deliver z/VM CP special messages (SMSG) as uevents.
+ *
+ * The driver registers for z/VM CP special messages with the
+ * "APP" prefix. Incoming messages are delivered to user space
+ * as uevents.
+ *
+ * Copyright IBM Corp. 2010
+ * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+ *
+ */
+#define KMSG_COMPONENT		"smsgiucv_app"
+#define pr_fmt(fmt)		KMSG_COMPONENT ": " fmt
+
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <net/iucv/iucv.h>
+#include "smsgiucv.h"
+
+/* prefix used for SMSG registration */
+#define SMSG_PREFIX		"APP"
+
+/* SMSG related uevent environment variables */
+#define ENV_SENDER_STR		"SMSG_SENDER="
+#define ENV_SENDER_LEN		(strlen(ENV_SENDER_STR) + 8 + 1)
+#define ENV_PREFIX_STR		"SMSG_ID="
+#define ENV_PREFIX_LEN		(strlen(ENV_PREFIX_STR) + \
+				 strlen(SMSG_PREFIX) + 1)
+#define ENV_TEXT_STR		"SMSG_TEXT="
+#define ENV_TEXT_LEN(msg)	(strlen(ENV_TEXT_STR) + strlen((msg)) + 1)
+
+/* z/VM user ID which is permitted to send SMSGs
+ * If the value is undefined or empty (""), special messages are
+ * accepted from any z/VM user ID. */
+static char *sender;
+module_param(sender, charp, 0400);
+MODULE_PARM_DESC(sender, "z/VM user ID from which CP SMSGs are accepted");
+
+/* SMSG device representation */
+static struct device *smsg_app_dev;
+
+/* list element for queuing received messages for delivery */
+struct smsg_app_event {
+	struct list_head list;
+	char *buf;
+	char *envp[4];
+};
+
+/* queue for outgoing uevents */
+static LIST_HEAD(smsg_event_queue);
+static DEFINE_SPINLOCK(smsg_event_queue_lock);
+
+static void smsg_app_event_free(struct smsg_app_event *ev)
+{
+	kfree(ev->buf);
+	kfree(ev);
+}
+
+static struct smsg_app_event *smsg_app_event_alloc(const char *from,
+						   const char *msg)
+{
+	struct smsg_app_event *ev;
+
+	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev)
+		return NULL;
+
+	ev->buf = kzalloc(ENV_SENDER_LEN + ENV_PREFIX_LEN +
+			  ENV_TEXT_LEN(msg), GFP_ATOMIC);
+	if (!ev->buf) {
+		kfree(ev);
+		return NULL;
+	}
+
+	/* setting up environment pointers into buf */
+	ev->envp[0] = ev->buf;
+	ev->envp[1] = ev->envp[0] + ENV_SENDER_LEN;
+	ev->envp[2] = ev->envp[1] + ENV_PREFIX_LEN;
+	ev->envp[3] = NULL;
+
+	/* setting up environment: sender, prefix name, and message text */
+	snprintf(ev->envp[0], ENV_SENDER_LEN, ENV_SENDER_STR "%s", from);
+	snprintf(ev->envp[1], ENV_PREFIX_LEN, ENV_PREFIX_STR "%s", SMSG_PREFIX);
+	snprintf(ev->envp[2], ENV_TEXT_LEN(msg), ENV_TEXT_STR "%s", msg);
+
+	return ev;
+}
+
+static void smsg_event_work_fn(struct work_struct *work)
+{
+	LIST_HEAD(event_queue);
+	struct smsg_app_event *p, *n;
+	struct device *dev;
+
+	dev = get_device(smsg_app_dev);
+	if (!dev)
+		return;
+
+	spin_lock_bh(&smsg_event_queue_lock);
+	list_splice_init(&smsg_event_queue, &event_queue);
+	spin_unlock_bh(&smsg_event_queue_lock);
+
+	list_for_each_entry_safe(p, n, &event_queue, list) {
+		list_del(&p->list);
+		kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, p->envp);
+		smsg_app_event_free(p);
+	}
+
+	put_device(dev);
+}
+static DECLARE_WORK(smsg_event_work, smsg_event_work_fn);
+
+static void smsg_app_callback(const char *from, char *msg)
+{
+	struct smsg_app_event *se;
+
+	/* check if the originating z/VM user ID matches
+	 * the configured sender. */
+	if (sender && strlen(sender) > 0 && strcmp(from, sender) != 0)
+		return;
+
+	/* get start of message text (skip prefix and leading blanks) */
+	msg += strlen(SMSG_PREFIX);
+	while (*msg && isspace(*msg))
+		msg++;
+	if (*msg == '\0')
+		return;
+
+	/* allocate event list element and its environment */
+	se = smsg_app_event_alloc(from, msg);
+	if (!se)
+		return;
+
+	/* queue event and schedule work function */
+	spin_lock(&smsg_event_queue_lock);
+	list_add_tail(&se->list, &smsg_event_queue);
+	spin_unlock(&smsg_event_queue_lock);
+
+	schedule_work(&smsg_event_work);
+	return;
+}
+
+static int __init smsgiucv_app_init(void)
+{
+	struct device_driver *smsgiucv_drv;
+	int rc;
+
+	if (!MACHINE_IS_VM)
+		return -ENODEV;
+
+	smsg_app_dev = kzalloc(sizeof(*smsg_app_dev), GFP_KERNEL);
+	if (!smsg_app_dev)
+		return -ENOMEM;
+
+	smsgiucv_drv = driver_find(SMSGIUCV_DRV_NAME, &iucv_bus);
+	if (!smsgiucv_drv) {
+		kfree(smsg_app_dev);
+		return -ENODEV;
+	}
+
+	rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT);
+	if (rc) {
+		kfree(smsg_app_dev);
+		goto fail_put_driver;
+	}
+	smsg_app_dev->bus = &iucv_bus;
+	smsg_app_dev->parent = iucv_root;
+	smsg_app_dev->release = (void (*)(struct device *)) kfree;
+	smsg_app_dev->driver = smsgiucv_drv;
+	rc = device_register(smsg_app_dev);
+	if (rc) {
+		put_device(smsg_app_dev);
+		goto fail_put_driver;
+	}
+
+	/* register with the smsgiucv device driver */
+	rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback);
+	if (rc) {
+		device_unregister(smsg_app_dev);
+		goto fail_put_driver;
+	}
+
+	rc = 0;
+fail_put_driver:
+	put_driver(smsgiucv_drv);
+	return rc;
+}
+module_init(smsgiucv_app_init);
+
+static void __exit smsgiucv_app_exit(void)
+{
+	/* unregister callback */
+	smsg_unregister_callback(SMSG_PREFIX, smsg_app_callback);
+
+	/* cancel pending work and flush any queued event work */
+	cancel_work_sync(&smsg_event_work);
+	smsg_event_work_fn(&smsg_event_work);
+
+	device_unregister(smsg_app_dev);
+}
+module_exit(smsgiucv_app_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Deliver z/VM CP SMSG as uevents");
+MODULE_AUTHOR("Hendrik Brueckner <brueckner@linux.vnet.ibm.com>");
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 71b97ff..6479273 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -319,8 +319,6 @@
 	id->input_handler = zfcp_qdio_int_resp;
 	id->output_handler = zfcp_qdio_int_req;
 	id->int_parm = (unsigned long) qdio;
-	id->flags = QDIO_INBOUND_0COPY_SBALS |
-		    QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS;
 	id->input_sbal_addr_array = (void **) (qdio->resp_q.sbal);
 	id->output_sbal_addr_array = (void **) (qdio->req_q.sbal);
 
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 208d6df..ff5716d 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -492,7 +492,7 @@
  *	init_orchid		-	initialise the host adapter
  *	@host:host adapter to initialise
  *
- *	Initialise the controller and if neccessary load the firmware.
+ *	Initialise the controller and if necessary load the firmware.
  *
  *	Returns -1 if the initialisation fails.
  */
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 89a5948..a771416 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -531,7 +531,7 @@
  *	initio_stop_bm		-	stop bus master
  *	@host: InitIO we are stopping
  *
- *	Stop any pending DMA operation, aborting the DMA if neccessary
+ *	Stop any pending DMA operation, aborting the DMA if necessary
  */
 
 static void initio_stop_bm(struct initio_host * host)
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 6fde2fab..774e7ac 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -48,7 +48,7 @@
 #define FC_SRB_CMD_SENT		(1 << 0)	/* cmd has been sent */
 #define FC_SRB_RCV_STATUS	(1 << 1)	/* response has arrived */
 #define FC_SRB_ABORT_PENDING	(1 << 2)	/* cmd abort sent to device */
-#define FC_SRB_ABORTED		(1 << 3)	/* abort acknowleged */
+#define FC_SRB_ABORTED		(1 << 3)	/* abort acknowledged */
 #define FC_SRB_DISCONTIG	(1 << 4)	/* non-sequential data recvd */
 #define FC_SRB_COMPL		(1 << 5)	/* fc_io_compl has been run */
 #define FC_SRB_FCP_PROCESSING_TMO (1 << 6)	/* timer function processing */
@@ -519,7 +519,7 @@
  *
  * Called after receiving a Transfer Ready data descriptor.
  * If the LLD is capable of sequence offload then send down the
- * seq_blen ammount of data in single frame, otherwise send
+ * seq_blen amount of data in single frame, otherwise send
  * multiple frames of the maximum frame payload supported by
  * the target port.
  */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 08b6634..2a40a6e 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -981,7 +981,7 @@
  * function returns, it does not guarantee all the IOCBs are actually aborted.
  *
  * Return code
- *   0 - Sucessfully issued abort iocb on all outstanding flogis (Always 0)
+ *   0 - Successfully issued abort iocb on all outstanding flogis (Always 0)
  **/
 int
 lpfc_els_abort_flogi(struct lpfc_hba *phba)
@@ -3129,7 +3129,7 @@
 	if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
 	    (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) {
 		/* A LS_RJT associated with Default RPI cleanup has its own
-		 * seperate code path.
+		 * separate code path.
 		 */
 		if (!(ndlp->nlp_flag & NLP_RM_DFLT_RPI))
 			ls_rjt = 1;
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 7f21b47..483fb74 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -1575,7 +1575,7 @@
 		case LPFC_PG_TYPE_NO_DIF:
 			num_bde = lpfc_bg_setup_bpl(phba, scsi_cmnd, bpl,
 					datasegcnt);
-			/* we shoud have 2 or more entries in buffer list */
+			/* we should have 2 or more entries in buffer list */
 			if (num_bde < 2)
 				goto err;
 			break;
@@ -1612,7 +1612,7 @@
 
 			num_bde = lpfc_bg_setup_bpl_prot(phba, scsi_cmnd, bpl,
 					datasegcnt, protsegcnt);
-			/* we shoud have 3 or more entries in buffer list */
+			/* we should have 3 or more entries in buffer list */
 			if (num_bde < 3)
 				goto err;
 			break;
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index 7db28cd..8c61a4f 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -187,7 +187,7 @@
 #define S_IO		BIT(1)    /* Input/Output line from SCSI bus */
 #define S_CD		BIT(2)    /* Command/Data line from SCSI bus */
 #define S_BUSY		BIT(3)    /* Busy line from SCSI bus         */
-#define S_ACK		BIT(4)    /* Acknowlege line from SCSI bus   */
+#define S_ACK		BIT(4)    /* Acknowledge line from SCSI bus  */
 #define S_REQUEST	BIT(5)    /* Request line from SCSI bus      */
 #define S_SELECT	BIT(6)	  /*                                 */
 #define S_ATN		BIT(7)	  /*                                 */
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 9b44c6f..7985ae4 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -2924,7 +2924,7 @@
 		break;
 	default:
 		PM8001_MSG_DBG(pm8001_ha,
-			pm8001_printk("unkown device type(%x)\n", deviceType));
+			pm8001_printk("unknown device type(%x)\n", deviceType));
 		break;
 	}
 	phy->phy_type |= PORT_TYPE_SAS;
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 7f9c83a..3b2c98f 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -600,7 +600,7 @@
   * by the command "OPC_INB_REG_DEV", after that the HBA will assign a
   * device ID(according to device's sas address) and returned it to LLDD. From
   * now on, we communicate with HBA FW with the device ID which HBA assigned
-  * rather than sas address. it is the neccessary step for our HBA but it is
+  * rather than sas address. it is the necessary step for our HBA but it is
   * the optional for other HBA driver.
   */
 static int pm8001_dev_found_notify(struct domain_device *dev)
diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h
index 92f89d5..b8ad07c 100644
--- a/drivers/scsi/pmcraid.h
+++ b/drivers/scsi/pmcraid.h
@@ -938,7 +938,7 @@
 
 /*
  * pmcraid_ioctl_header - definition of header structure that preceeds all the
- * buffers given as ioctl arguements.
+ * buffers given as ioctl arguments.
  *
  * .signature           : always ASCII string, "PMCRAID"
  * .reserved            : not used
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 1dd4d84..83881df 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2111,7 +2111,7 @@
  *	which is followed by sdaaa.
  *
  *	This is basically 26 base counting with one extra 'nil' entry
- *	at the beggining from the second digit on and can be
+ *	at the beginning from the second digit on and can be
  *	determined using similar method as 26 base conversion with the
  *	index shifted -1 after each digit is computed.
  *
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index 1d7a878..0d9d6f7 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -595,8 +595,6 @@
 		ses_dev->page10_len = len;
 		buf = NULL;
 	}
-	kfree(hdr_buf);
-
 	scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL);
 	if (!scomp)
 		goto err_free;
@@ -608,6 +606,8 @@
 		goto err_free;
 	}
 
+	kfree(hdr_buf);
+
 	edev->scratch = ses_dev;
 	for (i = 0; i < components; i++)
 		edev->component[i].scratch = scomp + i;
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index 0807b26..fef0e3c 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -226,7 +226,7 @@
 	.use_clustering		= DISABLE_CLUSTERING,
 };
 
-static int __init sgiwd93_probe(struct platform_device *pdev)
+static int __devinit sgiwd93_probe(struct platform_device *pdev)
 {
 	struct sgiwd93_platform_data *pd = pdev->dev.platform_data;
 	unsigned char *wdregs = pd->wdregs;
diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c
index 37b3359..56cf0bb 100644
--- a/drivers/scsi/sni_53c710.c
+++ b/drivers/scsi/sni_53c710.c
@@ -64,7 +64,7 @@
 	.module		= THIS_MODULE,
 };
 
-static int __init snirm710_probe(struct platform_device *dev)
+static int __devinit snirm710_probe(struct platform_device *dev)
 {
 	unsigned long base;
 	struct NCR_700_Host_Parameters *hostdata;
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index d935b2d..ae0251e 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -153,8 +153,6 @@
 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
 	9600, 19200, 38400, 57600, 115200, 0 };
 
-#define BAUD_TABLE_SIZE (sizeof(baud_table)/sizeof(baud_table[0]))
-
 /* Sets or clears DTR/RTS on the requested line */
 static inline void m68k_rtsdtr(struct m68k_serial *ss, int set)
 {
@@ -1406,10 +1404,10 @@
 	USTCNT = ustcnt & ~USTCNT_TXEN;
 
 again:
-	for (i = 0; i < sizeof(baud_table) / sizeof(baud_table[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(baud_table); i++)
 		if (baud_table[i] == m68328_console_baud)
 			break;
-	if (i >= sizeof(baud_table) / sizeof(baud_table[0])) {
+	if (i >= ARRAY_SIZE(baud_table)) {
 		m68328_console_baud = 9600;
 		goto again;
 	}
@@ -1435,7 +1433,7 @@
 	if (arg)
 		n = simple_strtoul(arg,NULL,0);
 
-	for (i = 0; i < BAUD_TABLE_SIZE; i++)
+	for (i = 0; i < ARRAY_SIZE(baud_table); i++)
 		if (baud_table[i] == n)
 			break;
 	if (i < BAUD_TABLE_SIZE) {
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index a81ff7b..c3db16b 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2408,6 +2408,21 @@
 }
 
 static void
+serial8250_set_ldisc(struct uart_port *port)
+{
+	int line = port->line;
+
+	if (line >= port->state->port.tty->driver->num)
+		return;
+
+	if (port->state->port.tty->ldisc->ops->num == N_PPS) {
+		port->flags |= UPF_HARDPPS_CD;
+		serial8250_enable_ms(port);
+	} else
+		port->flags &= ~UPF_HARDPPS_CD;
+}
+
+static void
 serial8250_pm(struct uart_port *port, unsigned int state,
 	      unsigned int oldstate)
 {
@@ -2628,6 +2643,7 @@
 	.startup	= serial8250_startup,
 	.shutdown	= serial8250_shutdown,
 	.set_termios	= serial8250_set_termios,
+	.set_ldisc	= serial8250_set_ldisc,
 	.pm		= serial8250_pm,
 	.type		= serial8250_type,
 	.release_port	= serial8250_release_port,
@@ -2690,6 +2706,15 @@
 	}
 }
 
+static void
+serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
+{
+	up->port.type = type;
+	up->port.fifosize = uart_config[type].fifo_size;
+	up->capabilities = uart_config[type].flags;
+	up->tx_loadsz = uart_config[type].tx_loadsz;
+}
+
 static void __init
 serial8250_register_ports(struct uart_driver *drv, struct device *dev)
 {
@@ -2706,6 +2731,10 @@
 		struct uart_8250_port *up = &serial8250_ports[i];
 
 		up->port.dev = dev;
+
+		if (up->port.flags & UPF_FIXED_TYPE)
+			serial8250_init_fixed_type_port(up, up->port.type);
+
 		uart_add_one_port(drv, &up->port);
 	}
 }
@@ -3118,12 +3147,8 @@
 		if (port->dev)
 			uart->port.dev = port->dev;
 
-		if (port->flags & UPF_FIXED_TYPE) {
-			uart->port.type = port->type;
-			uart->port.fifosize = uart_config[port->type].fifo_size;
-			uart->capabilities = uart_config[port->type].flags;
-			uart->tx_loadsz = uart_config[port->type].tx_loadsz;
-		}
+		if (port->flags & UPF_FIXED_TYPE)
+			serial8250_init_fixed_type_port(uart, port->type);
 
 		set_io_from_upio(&uart->port);
 		/* Possibly override default I/O functions.  */
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index b28af13..01c012d 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -760,7 +760,8 @@
 	/* subdevice 0x00PS means <P> parallel, <S> serial */
 	unsigned int num_serial = dev->subsystem_device & 0xf;
 
-	if (dev->device == PCI_DEVICE_ID_NETMOS_9901)
+	if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
+		(dev->device == PCI_DEVICE_ID_NETMOS_9865))
 		return 0;
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
 			dev->subsystem_device == 0x0299)
@@ -1479,6 +1480,7 @@
 
 	pbn_b0_bt_1_115200,
 	pbn_b0_bt_2_115200,
+	pbn_b0_bt_4_115200,
 	pbn_b0_bt_8_115200,
 
 	pbn_b0_bt_1_460800,
@@ -1703,6 +1705,12 @@
 		.base_baud	= 115200,
 		.uart_offset	= 8,
 	},
+	[pbn_b0_bt_4_115200] = {
+		.flags		= FL_BASE0|FL_BASE_BARS,
+		.num_ports	= 4,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
 	[pbn_b0_bt_8_115200] = {
 		.flags		= FL_BASE0|FL_BASE_BARS,
 		.num_ports	= 8,
@@ -3191,6 +3199,15 @@
 		0x1208, 0x0004, 0, 0,
 		pbn_b0_4_921600 },
 
+	{	PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
+		0x1204, 0x0004, 0, 0,
+		pbn_b0_4_921600 },
+	{	PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2,
+		0x1208, 0x0004, 0, 0,
+		pbn_b0_4_921600 },
+	{	PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF3,
+		0x1208, 0x0004, 0, 0,
+		pbn_b0_4_921600 },
 	/*
 	 * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com
 	 */
@@ -3649,6 +3666,18 @@
 		0, 0, pbn_b0_1_115200 },
 
 	/*
+	 * Best Connectivity PCI Multi I/O cards
+	 */
+
+	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+		0xA000, 0x1000,
+		0, 0, pbn_b0_1_115200 },
+
+	{	PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
+		0xA000, 0x3004,
+		0, 0, pbn_b0_bt_4_115200 },
+
+	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
 	 */
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 888a0ce..f55c494 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -447,7 +447,7 @@
 
 config SERIAL_SAMSUNG
 	tristate "Samsung SoC serial support"
-	depends on ARM && PLAT_S3C
+	depends on ARM && PLAT_SAMSUNG
 	select SERIAL_CORE
 	help
 	  Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
@@ -455,11 +455,18 @@
 	  provide all of these ports, depending on how the serial port
 	  pins are configured.
 
+config SERIAL_SAMSUNG_UARTS_4
+	bool
+	depends on ARM && PLAT_SAMSUNG
+	default y if CPU_S3C2443
+	help
+	  Internal node for the common case of 4 Samsung compatible UARTs
+
 config SERIAL_SAMSUNG_UARTS
 	int
-	depends on ARM && PLAT_S3C
+	depends on ARM && PLAT_SAMSUNG
 	default 2 if ARCH_S3C2400
-	default 4 if ARCH_S5PC1XX || ARCH_S3C64XX || CPU_S3C2443
+	default 4 if SERIAL_SAMSUNG_UARTS_4
 	default 3
 	help
 	  Select the number of available UART ports for the Samsung S3C
@@ -526,20 +533,30 @@
 	  Serial port support for the Samsung S3C24A0 SoC
 
 config SERIAL_S3C6400
-	tristate "Samsung S3C6400/S3C6410 Serial port support"
-	depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410)
+	tristate "Samsung S3C6400/S3C6410/S5P6440 Seria port support"
+	depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440)
+	select SERIAL_SAMSUNG_UARTS_4
 	default y
 	help
-	  Serial port support for the Samsung S3C6400 and S3C6410
+	  Serial port support for the Samsung S3C6400, S3C6410 and S5P6440
 	  SoCs
 
 config SERIAL_S5PC100
 	tristate "Samsung S5PC100 Serial port support"
 	depends on SERIAL_SAMSUNG && CPU_S5PC100
+	select SERIAL_SAMSUNG_UARTS_4
 	default y
 	help
 	  Serial port support for the Samsung S5PC100 SoCs
 
+config SERIAL_S5PV210
+	tristate "Samsung S5PV210 Serial port support"
+	depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442)
+	select SERIAL_SAMSUNG_UARTS_4 if CPU_S5PV210
+	default y
+	help
+	  Serial port support for Samsung's S5P Family of SoC's
+
 config SERIAL_MAX3100
 	tristate "MAX3100 support"
 	depends on SPI
@@ -996,7 +1013,7 @@
 
 config SERIAL_SH_SCI
 	tristate "SuperH SCI(F) serial port support"
-	depends on HAVE_CLK && (SUPERH || H8300)
+	depends on HAVE_CLK && (SUPERH || H8300 || ARCH_SHMOBILE)
 	select SERIAL_CORE
 
 config SERIAL_SH_SCI_NR_UARTS
@@ -1009,6 +1026,10 @@
 	depends on SERIAL_SH_SCI=y
 	select SERIAL_CORE_CONSOLE
 
+config SERIAL_SH_SCI_DMA
+	bool "DMA support"
+	depends on SERIAL_SH_SCI && SH_DMAE && EXPERIMENTAL
+
 config SERIAL_PNX8XXX
 	bool "Enable PNX8XXX SoCs' UART Support"
 	depends on MIPS && (SOC_PNX8550 || SOC_PNX833X)
@@ -1418,42 +1439,37 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called bfin_sport_uart.
 
-choice
-	prompt "Baud rate for Blackfin SPORT UART"
-	depends on SERIAL_BFIN_SPORT
-	default SERIAL_SPORT_BAUD_RATE_57600
+config SERIAL_BFIN_SPORT_CONSOLE
+	bool "Console on Blackfin sport emulated uart"
+	depends on SERIAL_BFIN_SPORT=y
+	select SERIAL_CORE_CONSOLE
+
+config SERIAL_BFIN_SPORT0_UART
+	bool "Enable UART over SPORT0"
+	depends on SERIAL_BFIN_SPORT && !(BF542 || BF542M || BF544 || BF544M)
 	help
-	  Choose a baud rate for the SPORT UART, other uart settings are
-	  8 bit, 1 stop bit, no parity, no flow control.
+	  Enable UART over SPORT0
 
-config SERIAL_SPORT_BAUD_RATE_115200
-	bool "115200"
-
-config SERIAL_SPORT_BAUD_RATE_57600
-	bool "57600"
-
-config SERIAL_SPORT_BAUD_RATE_38400
-	bool "38400"
-
-config SERIAL_SPORT_BAUD_RATE_19200
-	bool "19200"
-
-config SERIAL_SPORT_BAUD_RATE_9600
-	bool "9600"
-endchoice
-
-config SPORT_BAUD_RATE
-	int
+config SERIAL_BFIN_SPORT1_UART
+	bool "Enable UART over SPORT1"
 	depends on SERIAL_BFIN_SPORT
-	default 115200 if (SERIAL_SPORT_BAUD_RATE_115200)
-	default 57600 if (SERIAL_SPORT_BAUD_RATE_57600)
-	default 38400 if (SERIAL_SPORT_BAUD_RATE_38400)
-	default 19200 if (SERIAL_SPORT_BAUD_RATE_19200)
-	default 9600 if (SERIAL_SPORT_BAUD_RATE_9600)
+	help
+	  Enable UART over SPORT1
+
+config SERIAL_BFIN_SPORT2_UART
+	bool "Enable UART over SPORT2"
+	depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
+	help
+	  Enable UART over SPORT2
+
+config SERIAL_BFIN_SPORT3_UART
+	bool "Enable UART over SPORT3"
+	depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539)
+	help
+	  Enable UART over SPORT3
 
 config SERIAL_TIMBERDALE
 	tristate "Support for timberdale UART"
-	depends on MFD_TIMBERDALE
 	select SERIAL_CORE
 	---help---
 	Add support for UART controller on timberdale.
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 5548fe7..6aa4723 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -45,6 +45,7 @@
 obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o
 obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
 obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o
+obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
 obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
 obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
 obj-$(CONFIG_SERIAL_MUX) += mux.o
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 429a8ae..e4b3c2c 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -471,6 +471,20 @@
 	spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
+static void pl010_set_ldisc(struct uart_port *port)
+{
+	int line = port->line;
+
+	if (line >= port->state->port.tty->driver->num)
+		return;
+
+	if (port->state->port.tty->ldisc->ops->num == N_PPS) {
+		port->flags |= UPF_HARDPPS_CD;
+		pl010_enable_ms(port);
+	} else
+		port->flags &= ~UPF_HARDPPS_CD;
+}
+
 static const char *pl010_type(struct uart_port *port)
 {
 	return port->type == PORT_AMBA ? "AMBA" : NULL;
@@ -531,6 +545,7 @@
 	.startup	= pl010_startup,
 	.shutdown	= pl010_shutdown,
 	.set_termios	= pl010_set_termios,
+	.set_ldisc	= pl010_set_ldisc,
 	.type		= pl010_type,
 	.release_port	= pl010_release_port,
 	.request_port	= pl010_request_port,
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 9d948bc..2c9bf9b 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -1213,6 +1213,24 @@
 	return ret;
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+static int atmel_poll_get_char(struct uart_port *port)
+{
+	while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
+		cpu_relax();
+
+	return UART_GET_CHAR(port);
+}
+
+static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
+{
+	while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+		cpu_relax();
+
+	UART_PUT_CHAR(port, ch);
+}
+#endif
+
 static struct uart_ops atmel_pops = {
 	.tx_empty	= atmel_tx_empty,
 	.set_mctrl	= atmel_set_mctrl,
@@ -1232,6 +1250,10 @@
 	.config_port	= atmel_config_port,
 	.verify_port	= atmel_verify_port,
 	.pm		= atmel_serial_pm,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char	= atmel_poll_get_char,
+	.poll_put_char	= atmel_poll_put_char,
+#endif
 };
 
 /*
diff --git a/drivers/serial/bcm63xx_uart.c b/drivers/serial/bcm63xx_uart.c
index 37ad0c4..a1a0e55 100644
--- a/drivers/serial/bcm63xx_uart.c
+++ b/drivers/serial/bcm63xx_uart.c
@@ -35,7 +35,7 @@
 #include <bcm63xx_regs.h>
 #include <bcm63xx_io.h>
 
-#define BCM63XX_NR_UARTS	1
+#define BCM63XX_NR_UARTS	2
 
 static struct uart_port ports[BCM63XX_NR_UARTS];
 
@@ -784,7 +784,7 @@
 	.dev_name	= "ttyS",
 	.major		= TTY_MAJOR,
 	.minor		= 64,
-	.nr		= 1,
+	.nr		= BCM63XX_NR_UARTS,
 	.cons		= BCM63XX_CONSOLE,
 };
 
@@ -826,11 +826,12 @@
 	port->dev = &pdev->dev;
 	port->fifosize = 16;
 	port->uartclk = clk_get_rate(clk) / 2;
+	port->line = pdev->id;
 	clk_put(clk);
 
 	ret = uart_add_one_port(&bcm_uart_driver, port);
 	if (ret) {
-		kfree(port);
+		ports[pdev->id].membase = 0;
 		return ret;
 	}
 	platform_set_drvdata(pdev, port);
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 50abb7e..fcf273e 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -14,6 +14,7 @@
 
 #include <linux/module.h>
 #include <linux/ioport.h>
+#include <linux/io.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
@@ -237,7 +238,8 @@
 
 #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
 	defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
-	if (kgdb_connected && kgdboc_port_line == uart->port.line)
+	if (kgdb_connected && kgdboc_port_line == uart->port.line
+		&& kgdboc_break_enabled)
 		if (ch == 0x3) {/* Ctrl + C */
 			kgdb_breakpoint();
 			return;
@@ -488,6 +490,7 @@
 {
 	int x_pos, pos;
 
+	dma_disable_irq(uart->tx_dma_channel);
 	dma_disable_irq(uart->rx_dma_channel);
 	spin_lock_bh(&uart->port.lock);
 
@@ -521,6 +524,7 @@
 	}
 
 	spin_unlock_bh(&uart->port.lock);
+	dma_enable_irq(uart->tx_dma_channel);
 	dma_enable_irq(uart->rx_dma_channel);
 
 	mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
@@ -746,15 +750,6 @@
 			Status interrupt.\n");
 	}
 
-	if (uart->cts_pin >= 0) {
-		gpio_request(uart->cts_pin, DRIVER_NAME);
-		gpio_direction_output(uart->cts_pin, 1);
-	}
-	if (uart->rts_pin >= 0) {
-		gpio_request(uart->rts_pin, DRIVER_NAME);
-		gpio_direction_output(uart->rts_pin, 0);
-	}
-
 	/* CTS RTS PINs are negative assertive. */
 	UART_PUT_MCR(uart, ACTS);
 	UART_SET_IER(uart, EDSSI);
@@ -801,10 +796,6 @@
 		gpio_free(uart->rts_pin);
 #endif
 #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
-	if (uart->cts_pin >= 0)
-		gpio_free(uart->cts_pin);
-	if (uart->rts_pin >= 0)
-		gpio_free(uart->rts_pin);
 	if (UART_GET_IER(uart) && EDSSI)
 		free_irq(uart->status_irq, uart);
 #endif
@@ -1409,8 +1400,7 @@
 			continue;
 		uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port);
 		bfin_serial_ports[i].port.dev = NULL;
-#if defined(CONFIG_SERIAL_BFIN_CTSRTS) || \
-	defined(CONFIG_SERIAL_BFIN_HARD_CTSRTS)
+#if defined(CONFIG_SERIAL_BFIN_CTSRTS)
 		gpio_free(bfin_serial_ports[i].cts_pin);
 		gpio_free(bfin_serial_ports[i].rts_pin);
 #endif
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
index 088bb35..7c72888 100644
--- a/drivers/serial/bfin_sport_uart.c
+++ b/drivers/serial/bfin_sport_uart.c
@@ -1,27 +1,11 @@
 /*
- * File:	linux/drivers/serial/bfin_sport_uart.c
+ * Blackfin On-Chip Sport Emulated UART Driver
  *
- * Based on:	drivers/serial/bfin_5xx.c by Aubrey Li.
- * Author:	Roy Huang <roy.huang@analog.com>
+ * Copyright 2006-2009 Analog Devices Inc.
  *
- * Created:	Nov 22, 2006
- * Copyright:	(c) 2006-2007 Analog Devices Inc.
- * Description: this driver enable SPORTs on Blackfin emulate UART.
+ * Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
 /*
@@ -29,39 +13,18 @@
  * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf
  * This application note describe how to implement a UART on a Sharc DSP,
  * but this driver is implemented on Blackfin Processor.
+ * Transmit Frame Sync is not used by this driver to transfer data out.
  */
 
-/* After reset, there is a prelude of low level pulse when transmit data first
- * time. No addtional pulse in following transmit.
- * According to document:
- * The SPORTs are ready to start transmitting or receiving data no later than
- * three serial clock cycles after they are enabled in the SPORTx_TCR1 or
- * SPORTx_RCR1 register. No serial clock cycles are lost from this point on.
- * The first internal frame sync will occur one frame sync delay after the
- * SPORTs are ready. External frame syncs can occur as soon as the SPORT is
- * ready.
- */
+/* #define DEBUG */
 
-/* Thanks to Axel Alatalo <axel@rubico.se> for fixing sport rx bug. Sometimes
- * sport receives data incorrectly. The following is Axel's words.
- * As EE-191, sport rx samples 3 times of the UART baudrate and takes the
- * middle smaple of every 3 samples as the data bit. For a 8-N-1 UART setting,
- * 30 samples will be required for a byte. If transmitter sends a 1/3 bit short
- * byte due to buadrate drift, then the 30th sample of a byte, this sample is
- * also the third sample of the stop bit, will happens on the immediately
- * following start bit which will be thrown away and missed. Thus since parts
- * of the startbit will be missed and the receiver will begin to drift, the
- * effect accumulates over time until synchronization is lost.
- * If only require 2 samples of the stopbit (by sampling in total 29 samples),
- * then a to short byte as in the case above will be tolerated. Then the 1/3
- * early startbit will trigger a framesync since the last read is complete
- * after only 2/3 stopbit and framesync is active during the last 1/3 looking
- * for a possible early startbit. */
-
-//#define DEBUG
+#define DRV_NAME "bfin-sport-uart"
+#define DEVICE_NAME	"ttySS"
+#define pr_fmt(fmt) DRV_NAME ": " fmt
 
 #include <linux/module.h>
 #include <linux/ioport.h>
+#include <linux/io.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
@@ -75,23 +38,36 @@
 
 #include "bfin_sport_uart.h"
 
+#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
 unsigned short bfin_uart_pin_req_sport0[] =
 	{P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \
 	 P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0};
-
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
 unsigned short bfin_uart_pin_req_sport1[] =
 	{P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \
 	P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0};
-
-#define DRV_NAME "bfin-sport-uart"
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT2_UART
+unsigned short bfin_uart_pin_req_sport2[] =
+	{P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS, \
+	P_SPORT2_DRPRI, P_SPORT2_RSCLK, P_SPORT2_DRSEC, P_SPORT2_DTSEC, 0};
+#endif
+#ifdef CONFIG_SERIAL_BFIN_SPORT3_UART
+unsigned short bfin_uart_pin_req_sport3[] =
+	{P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS, \
+	P_SPORT3_DRPRI, P_SPORT3_RSCLK, P_SPORT3_DRSEC, P_SPORT3_DTSEC, 0};
+#endif
 
 struct sport_uart_port {
 	struct uart_port	port;
-	char			*name;
-
-	int			tx_irq;
-	int			rx_irq;
 	int			err_irq;
+	unsigned short		csize;
+	unsigned short		rxmask;
+	unsigned short		txmask1;
+	unsigned short		txmask2;
+	unsigned char		stopb;
+/*	unsigned char		parib; */
 };
 
 static void sport_uart_tx_chars(struct sport_uart_port *up);
@@ -99,36 +75,42 @@
 
 static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
 {
-	pr_debug("%s value:%x\n", __func__, value);
-	/* Place a Start and Stop bit */
+	pr_debug("%s value:%x, mask1=0x%x, mask2=0x%x\n", __func__, value,
+		up->txmask1, up->txmask2);
+
+	/* Place Start and Stop bits */
 	__asm__ __volatile__ (
-		"R2 = b#01111111100;"
-		"R3 = b#10000000001;"
-		"%0 <<= 2;"
-		"%0 = %0 & R2;"
-		"%0 = %0 | R3;"
-		: "=d"(value)
-		: "d"(value)
-		: "ASTAT", "R2", "R3"
+		"%[val] <<= 1;"
+		"%[val] = %[val] & %[mask1];"
+		"%[val] = %[val] | %[mask2];"
+		: [val]"+d"(value)
+		: [mask1]"d"(up->txmask1), [mask2]"d"(up->txmask2)
+		: "ASTAT"
 	);
 	pr_debug("%s value:%x\n", __func__, value);
 
 	SPORT_PUT_TX(up, value);
 }
 
-static inline unsigned int rx_one_byte(struct sport_uart_port *up)
+static inline unsigned char rx_one_byte(struct sport_uart_port *up)
 {
-	unsigned int value, extract;
+	unsigned int value;
+	unsigned char extract;
 	u32 tmp_mask1, tmp_mask2, tmp_shift, tmp;
 
-	value = SPORT_GET_RX32(up);
-	pr_debug("%s value:%x\n", __func__, value);
+	if ((up->csize + up->stopb) > 7)
+		value = SPORT_GET_RX32(up);
+	else
+		value = SPORT_GET_RX(up);
 
-	/* Extract 8 bits data */
+	pr_debug("%s value:%x, cs=%d, mask=0x%x\n", __func__, value,
+		up->csize, up->rxmask);
+
+	/* Extract data */
 	__asm__ __volatile__ (
 		"%[extr] = 0;"
-		"%[mask1] = 0x1801(Z);"
-		"%[mask2] = 0x0300(Z);"
+		"%[mask1] = %[rxmask];"
+		"%[mask2] = 0x0200(Z);"
 		"%[shift] = 0;"
 		"LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];"
 		".Lloop_s:"
@@ -138,9 +120,9 @@
 		"%[mask1] = %[mask1] - %[mask2];"
 		".Lloop_e:"
 		"%[shift] += 1;"
-		: [val]"=d"(value), [extr]"=d"(extract), [shift]"=d"(tmp_shift), [tmp]"=d"(tmp),
-		  [mask1]"=d"(tmp_mask1), [mask2]"=d"(tmp_mask2)
-		: "d"(value), [lc]"a"(8)
+		: [extr]"=&d"(extract), [shift]"=&d"(tmp_shift), [tmp]"=&d"(tmp),
+		  [mask1]"=&d"(tmp_mask1), [mask2]"=&d"(tmp_mask2)
+		: [val]"d"(value), [rxmask]"d"(up->rxmask), [lc]"a"(up->csize)
 		: "ASTAT", "LB0", "LC0", "LT0"
 	);
 
@@ -148,29 +130,28 @@
 	return extract;
 }
 
-static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate)
+static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate)
 {
-	int tclkdiv, tfsdiv, rclkdiv;
+	int tclkdiv, rclkdiv;
+	unsigned int sclk = get_sclk();
 
-	/* Set TCR1 and TCR2 */
-	SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK));
-	SPORT_PUT_TCR2(up, 10);
+	/* Set TCR1 and TCR2, TFSR is not enabled for uart */
+	SPORT_PUT_TCR1(up, (ITFS | TLSBIT | ITCLK));
+	SPORT_PUT_TCR2(up, size + 1);
 	pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up));
 
 	/* Set RCR1 and RCR2 */
 	SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK));
-	SPORT_PUT_RCR2(up, 28);
+	SPORT_PUT_RCR2(up, (size + 1) * 2 - 1);
 	pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
 
-	tclkdiv = sclk/(2 * baud_rate) - 1;
-	tfsdiv = 12;
-	rclkdiv = sclk/(2 * baud_rate * 3) - 1;
+	tclkdiv = sclk / (2 * baud_rate) - 1;
+	rclkdiv = sclk / (2 * baud_rate * 2) - 1;
 	SPORT_PUT_TCLKDIV(up, tclkdiv);
-	SPORT_PUT_TFSDIV(up, tfsdiv);
 	SPORT_PUT_RCLKDIV(up, rclkdiv);
 	SSYNC();
-	pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, tfsdiv:%d, rclkdiv:%d\n",
-			__func__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv);
+	pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, rclkdiv:%d\n",
+			__func__, sclk, baud_rate, tclkdiv, rclkdiv);
 
 	return 0;
 }
@@ -181,23 +162,29 @@
 	struct tty_struct *tty = up->port.state->port.tty;
 	unsigned int ch;
 
-	do {
+	spin_lock(&up->port.lock);
+
+	while (SPORT_GET_STAT(up) & RXNE) {
 		ch = rx_one_byte(up);
 		up->port.icount.rx++;
 
-		if (uart_handle_sysrq_char(&up->port, ch))
-			;
-		else
+		if (!uart_handle_sysrq_char(&up->port, ch))
 			tty_insert_flip_char(tty, ch, TTY_NORMAL);
-	} while (SPORT_GET_STAT(up) & RXNE);
+	}
 	tty_flip_buffer_push(tty);
 
+	spin_unlock(&up->port.lock);
+
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id)
 {
-	sport_uart_tx_chars(dev_id);
+	struct sport_uart_port *up = dev_id;
+
+	spin_lock(&up->port.lock);
+	sport_uart_tx_chars(up);
+	spin_unlock(&up->port.lock);
 
 	return IRQ_HANDLED;
 }
@@ -208,6 +195,8 @@
 	struct tty_struct *tty = up->port.state->port.tty;
 	unsigned int stat = SPORT_GET_STAT(up);
 
+	spin_lock(&up->port.lock);
+
 	/* Overflow in RX FIFO */
 	if (stat & ROVF) {
 		up->port.icount.overrun++;
@@ -216,15 +205,16 @@
 	}
 	/* These should not happen */
 	if (stat & (TOVF | TUVF | RUVF)) {
-		printk(KERN_ERR "SPORT Error:%s %s %s\n",
-				(stat & TOVF)?"TX overflow":"",
-				(stat & TUVF)?"TX underflow":"",
-				(stat & RUVF)?"RX underflow":"");
+		pr_err("SPORT Error:%s %s %s\n",
+		       (stat & TOVF) ? "TX overflow" : "",
+		       (stat & TUVF) ? "TX underflow" : "",
+		       (stat & RUVF) ? "RX underflow" : "");
 		SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
 		SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
 	}
 	SSYNC();
 
+	spin_unlock(&up->port.lock);
 	return IRQ_HANDLED;
 }
 
@@ -232,60 +222,37 @@
 static int sport_startup(struct uart_port *port)
 {
 	struct sport_uart_port *up = (struct sport_uart_port *)port;
-	char buffer[20];
-	int retval;
+	int ret;
 
 	pr_debug("%s enter\n", __func__);
-	snprintf(buffer, 20, "%s rx", up->name);
-	retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
-	if (retval) {
-		printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
-		return retval;
+	ret = request_irq(up->port.irq, sport_uart_rx_irq, 0,
+		"SPORT_UART_RX", up);
+	if (ret) {
+		dev_err(port->dev, "unable to request SPORT RX interrupt\n");
+		return ret;
 	}
 
-	snprintf(buffer, 20, "%s tx", up->name);
-	retval = request_irq(up->tx_irq, sport_uart_tx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
-	if (retval) {
-		printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
+	ret = request_irq(up->port.irq+1, sport_uart_tx_irq, 0,
+		"SPORT_UART_TX", up);
+	if (ret) {
+		dev_err(port->dev, "unable to request SPORT TX interrupt\n");
 		goto fail1;
 	}
 
-	snprintf(buffer, 20, "%s err", up->name);
-	retval = request_irq(up->err_irq, sport_uart_err_irq, IRQF_SAMPLE_RANDOM, buffer, up);
-	if (retval) {
-		printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
+	ret = request_irq(up->err_irq, sport_uart_err_irq, 0,
+		"SPORT_UART_STATUS", up);
+	if (ret) {
+		dev_err(port->dev, "unable to request SPORT status interrupt\n");
 		goto fail2;
 	}
 
-	if (port->line) {
-		if (peripheral_request_list(bfin_uart_pin_req_sport1, DRV_NAME))
-			goto fail3;
-	} else {
-		if (peripheral_request_list(bfin_uart_pin_req_sport0, DRV_NAME))
-			goto fail3;
-	}
-
-	sport_uart_setup(up, get_sclk(), port->uartclk);
-
-	/* Enable receive interrupt */
-	SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) | RSPEN));
-	SSYNC();
-
 	return 0;
+ fail2:
+	free_irq(up->port.irq+1, up);
+ fail1:
+	free_irq(up->port.irq, up);
 
-
-fail3:
-	printk(KERN_ERR DRV_NAME
-		": Requesting Peripherals failed\n");
-
-	free_irq(up->err_irq, up);
-fail2:
-	free_irq(up->tx_irq, up);
-fail1:
-	free_irq(up->rx_irq, up);
-
-	return retval;
-
+	return ret;
 }
 
 static void sport_uart_tx_chars(struct sport_uart_port *up)
@@ -344,20 +311,17 @@
 static void sport_stop_tx(struct uart_port *port)
 {
 	struct sport_uart_port *up = (struct sport_uart_port *)port;
-	unsigned int stat;
 
 	pr_debug("%s enter\n", __func__);
 
-	stat = SPORT_GET_STAT(up);
-	while(!(stat & TXHRE)) {
-		udelay(1);
-		stat = SPORT_GET_STAT(up);
-	}
 	/* Although the hold register is empty, last byte is still in shift
-	 * register and not sent out yet. If baud rate is lower than default,
-	 * delay should be longer. For example, if the baud rate is 9600,
-	 * the delay must be at least 2ms by experience */
-	udelay(500);
+	 * register and not sent out yet. So, put a dummy data into TX FIFO.
+	 * Then, sport tx stops when last byte is shift out and the dummy
+	 * data is moved into the shift register.
+	 */
+	SPORT_PUT_TX(up, 0xffff);
+	while (!(SPORT_GET_STAT(up) & TXHRE))
+		cpu_relax();
 
 	SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
 	SSYNC();
@@ -370,6 +334,7 @@
 	struct sport_uart_port *up = (struct sport_uart_port *)port;
 
 	pr_debug("%s enter\n", __func__);
+
 	/* Write data into SPORT FIFO before enable SPROT to transmit */
 	sport_uart_tx_chars(up);
 
@@ -403,37 +368,24 @@
 {
 	struct sport_uart_port *up = (struct sport_uart_port *)port;
 
-	pr_debug("%s enter\n", __func__);
+	dev_dbg(port->dev, "%s enter\n", __func__);
 
 	/* Disable sport */
 	SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
 	SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
 	SSYNC();
 
-	if (port->line) {
-		peripheral_free_list(bfin_uart_pin_req_sport1);
-	} else {
-		peripheral_free_list(bfin_uart_pin_req_sport0);
-	}
-
-	free_irq(up->rx_irq, up);
-	free_irq(up->tx_irq, up);
+	free_irq(up->port.irq, up);
+	free_irq(up->port.irq+1, up);
 	free_irq(up->err_irq, up);
 }
 
-static void sport_set_termios(struct uart_port *port,
-		struct ktermios *termios, struct ktermios *old)
-{
-	pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
-	uart_update_timeout(port, CS8 ,port->uartclk);
-}
-
 static const char *sport_type(struct uart_port *port)
 {
 	struct sport_uart_port *up = (struct sport_uart_port *)port;
 
 	pr_debug("%s enter\n", __func__);
-	return up->name;
+	return up->port.type == PORT_BFIN_SPORT ? "BFIN-SPORT-UART" : NULL;
 }
 
 static void sport_release_port(struct uart_port *port)
@@ -461,6 +413,110 @@
 	return 0;
 }
 
+static void sport_set_termios(struct uart_port *port,
+		struct ktermios *termios, struct ktermios *old)
+{
+	struct sport_uart_port *up = (struct sport_uart_port *)port;
+	unsigned long flags;
+	int i;
+
+	pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS8:
+		up->csize = 8;
+		break;
+	case CS7:
+		up->csize = 7;
+		break;
+	case CS6:
+		up->csize = 6;
+		break;
+	case CS5:
+		up->csize = 5;
+		break;
+	default:
+		pr_warning("requested word length not supported\n");
+	}
+
+	if (termios->c_cflag & CSTOPB) {
+		up->stopb = 1;
+	}
+	if (termios->c_cflag & PARENB) {
+		pr_warning("PAREN bits is not supported yet\n");
+		/* up->parib = 1; */
+	}
+
+	port->read_status_mask = OE;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= (FE | PE);
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		port->read_status_mask |= BI;
+
+	/*
+	 * Characters to ignore
+	 */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= FE | PE;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= BI;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			port->ignore_status_mask |= OE;
+	}
+
+	/* RX extract mask */
+	up->rxmask = 0x01 | (((up->csize + up->stopb) * 2 - 1) << 0x8);
+	/* TX masks, 8 bit data and 1 bit stop for example:
+	 * mask1 = b#0111111110
+	 * mask2 = b#1000000000
+	 */
+	for (i = 0, up->txmask1 = 0; i < up->csize; i++)
+		up->txmask1 |= (1<<i);
+	up->txmask2 = (1<<i);
+	if (up->stopb) {
+		++i;
+		up->txmask2 |= (1<<i);
+	}
+	up->txmask1 <<= 1;
+	up->txmask2 <<= 1;
+	/* uart baud rate */
+	port->uartclk = uart_get_baud_rate(port, termios, old, 0, get_sclk()/16);
+
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	/* Disable UART */
+	SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
+	SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
+
+	sport_uart_setup(up, up->csize + up->stopb, port->uartclk);
+
+	/* driver TX line high after config, one dummy data is
+	 * necessary to stop sport after shift one byte
+	 */
+	SPORT_PUT_TX(up, 0xffff);
+	SPORT_PUT_TX(up, 0xffff);
+	SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
+	SSYNC();
+	while (!(SPORT_GET_STAT(up) & TXHRE))
+		cpu_relax();
+	SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
+	SSYNC();
+
+	/* Port speed changed, update the per-port timeout. */
+	uart_update_timeout(port, termios->c_cflag, port->uartclk);
+
+	/* Enable sport rx */
+	SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) | RSPEN);
+	SSYNC();
+
+	spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
 struct uart_ops sport_uart_ops = {
 	.tx_empty	= sport_tx_empty,
 	.set_mctrl	= sport_set_mctrl,
@@ -480,138 +536,319 @@
 	.verify_port	= sport_verify_port,
 };
 
-static struct sport_uart_port sport_uart_ports[] = {
-	{ /* SPORT 0 */
-		.name	= "SPORT0",
-		.tx_irq = IRQ_SPORT0_TX,
-		.rx_irq = IRQ_SPORT0_RX,
-		.err_irq= IRQ_SPORT0_ERROR,
-		.port	= {
-			.type		= PORT_BFIN_SPORT,
-			.iotype		= UPIO_MEM,
-			.membase	= (void __iomem *)SPORT0_TCR1,
-			.mapbase	= SPORT0_TCR1,
-			.irq		= IRQ_SPORT0_RX,
-			.uartclk	= CONFIG_SPORT_BAUD_RATE,
-			.fifosize	= 8,
-			.ops		= &sport_uart_ops,
-			.line		= 0,
-		},
-	}, { /* SPORT 1 */
-		.name	= "SPORT1",
-		.tx_irq = IRQ_SPORT1_TX,
-		.rx_irq = IRQ_SPORT1_RX,
-		.err_irq= IRQ_SPORT1_ERROR,
-		.port	= {
-			.type		= PORT_BFIN_SPORT,
-			.iotype		= UPIO_MEM,
-			.membase	= (void __iomem *)SPORT1_TCR1,
-			.mapbase	= SPORT1_TCR1,
-			.irq		= IRQ_SPORT1_RX,
-			.uartclk	= CONFIG_SPORT_BAUD_RATE,
-			.fifosize	= 8,
-			.ops		= &sport_uart_ops,
-			.line		= 1,
-		},
+#define BFIN_SPORT_UART_MAX_PORTS 4
+
+static struct sport_uart_port *bfin_sport_uart_ports[BFIN_SPORT_UART_MAX_PORTS];
+
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
+static int __init
+sport_uart_console_setup(struct console *co, char *options)
+{
+	struct sport_uart_port *up;
+	int baud = 57600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	/* Check whether an invalid uart number has been specified */
+	if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS)
+		return -ENODEV;
+
+	up = bfin_sport_uart_ports[co->index];
+	if (!up)
+		return -ENODEV;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(&up->port, co, baud, parity, bits, flow);
+}
+
+static void sport_uart_console_putchar(struct uart_port *port, int ch)
+{
+	struct sport_uart_port *up = (struct sport_uart_port *)port;
+
+	while (SPORT_GET_STAT(up) & TXF)
+		barrier();
+
+	tx_one_byte(up, ch);
+}
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void
+sport_uart_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct sport_uart_port *up = bfin_sport_uart_ports[co->index];
+	unsigned long flags;
+
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	if (SPORT_GET_TCR1(up) & TSPEN)
+		uart_console_write(&up->port, s, count, sport_uart_console_putchar);
+	else {
+		/* dummy data to start sport */
+		while (SPORT_GET_STAT(up) & TXF)
+			barrier();
+		SPORT_PUT_TX(up, 0xffff);
+		/* Enable transmit, then an interrupt will generated */
+		SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
+		SSYNC();
+
+		uart_console_write(&up->port, s, count, sport_uart_console_putchar);
+
+		/* Although the hold register is empty, last byte is still in shift
+		 * register and not sent out yet. So, put a dummy data into TX FIFO.
+		 * Then, sport tx stops when last byte is shift out and the dummy
+		 * data is moved into the shift register.
+		 */
+		while (SPORT_GET_STAT(up) & TXF)
+			barrier();
+		SPORT_PUT_TX(up, 0xffff);
+		while (!(SPORT_GET_STAT(up) & TXHRE))
+			barrier();
+
+		/* Stop sport tx transfer */
+		SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
+		SSYNC();
 	}
+
+	spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static struct uart_driver sport_uart_reg;
+
+static struct console sport_uart_console = {
+	.name		= DEVICE_NAME,
+	.write		= sport_uart_console_write,
+	.device		= uart_console_device,
+	.setup		= sport_uart_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &sport_uart_reg,
 };
 
+#define SPORT_UART_CONSOLE	(&sport_uart_console)
+#else
+#define SPORT_UART_CONSOLE	NULL
+#endif /* CONFIG_SERIAL_BFIN_SPORT_CONSOLE */
+
+
 static struct uart_driver sport_uart_reg = {
 	.owner		= THIS_MODULE,
-	.driver_name	= "SPORT-UART",
-	.dev_name	= "ttySS",
+	.driver_name	= DRV_NAME,
+	.dev_name	= DEVICE_NAME,
 	.major		= 204,
 	.minor		= 84,
-	.nr		= ARRAY_SIZE(sport_uart_ports),
-	.cons		= NULL,
+	.nr		= BFIN_SPORT_UART_MAX_PORTS,
+	.cons		= SPORT_UART_CONSOLE,
 };
 
-static int sport_uart_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef CONFIG_PM
+static int sport_uart_suspend(struct device *dev)
 {
-	struct sport_uart_port *sport = platform_get_drvdata(dev);
+	struct sport_uart_port *sport = dev_get_drvdata(dev);
 
-	pr_debug("%s enter\n", __func__);
+	dev_dbg(dev, "%s enter\n", __func__);
 	if (sport)
 		uart_suspend_port(&sport_uart_reg, &sport->port);
 
 	return 0;
 }
 
-static int sport_uart_resume(struct platform_device *dev)
+static int sport_uart_resume(struct device *dev)
 {
-	struct sport_uart_port *sport = platform_get_drvdata(dev);
+	struct sport_uart_port *sport = dev_get_drvdata(dev);
 
-	pr_debug("%s enter\n", __func__);
+	dev_dbg(dev, "%s enter\n", __func__);
 	if (sport)
 		uart_resume_port(&sport_uart_reg, &sport->port);
 
 	return 0;
 }
 
-static int sport_uart_probe(struct platform_device *dev)
-{
-	pr_debug("%s enter\n", __func__);
-	sport_uart_ports[dev->id].port.dev = &dev->dev;
-	uart_add_one_port(&sport_uart_reg, &sport_uart_ports[dev->id].port);
-	platform_set_drvdata(dev, &sport_uart_ports[dev->id]);
+static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = {
+	.suspend	= sport_uart_suspend,
+	.resume		= sport_uart_resume,
+};
+#endif
 
-	return 0;
+static int __devinit sport_uart_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct sport_uart_port *sport;
+	int ret = 0;
+
+	dev_dbg(&pdev->dev, "%s enter\n", __func__);
+
+	if (pdev->id < 0 || pdev->id >= BFIN_SPORT_UART_MAX_PORTS) {
+		dev_err(&pdev->dev, "Wrong sport uart platform device id.\n");
+		return -ENOENT;
+	}
+
+	if (bfin_sport_uart_ports[pdev->id] == NULL) {
+		bfin_sport_uart_ports[pdev->id] =
+			kmalloc(sizeof(struct sport_uart_port), GFP_KERNEL);
+		sport = bfin_sport_uart_ports[pdev->id];
+		if (!sport) {
+			dev_err(&pdev->dev,
+				"Fail to kmalloc sport_uart_port\n");
+			return -ENOMEM;
+		}
+
+		ret = peripheral_request_list(
+			(unsigned short *)pdev->dev.platform_data, DRV_NAME);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Fail to request SPORT peripherals\n");
+			goto out_error_free_mem;
+		}
+
+		spin_lock_init(&sport->port.lock);
+		sport->port.fifosize  = SPORT_TX_FIFO_SIZE,
+		sport->port.ops       = &sport_uart_ops;
+		sport->port.line      = pdev->id;
+		sport->port.iotype    = UPIO_MEM;
+		sport->port.flags     = UPF_BOOT_AUTOCONF;
+
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (res == NULL) {
+			dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
+			ret = -ENOENT;
+			goto out_error_free_peripherals;
+		}
+
+		sport->port.membase = ioremap(res->start,
+			res->end - res->start);
+		if (!sport->port.membase) {
+			dev_err(&pdev->dev, "Cannot map sport IO\n");
+			ret = -ENXIO;
+			goto out_error_free_peripherals;
+		}
+
+		sport->port.irq = platform_get_irq(pdev, 0);
+		if (sport->port.irq < 0) {
+			dev_err(&pdev->dev, "No sport RX/TX IRQ specified\n");
+			ret = -ENOENT;
+			goto out_error_unmap;
+		}
+
+		sport->err_irq = platform_get_irq(pdev, 1);
+		if (sport->err_irq < 0) {
+			dev_err(&pdev->dev, "No sport status IRQ specified\n");
+			ret = -ENOENT;
+			goto out_error_unmap;
+		}
+	}
+
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
+	if (!is_early_platform_device(pdev)) {
+#endif
+		sport = bfin_sport_uart_ports[pdev->id];
+		sport->port.dev = &pdev->dev;
+		dev_set_drvdata(&pdev->dev, sport);
+		ret = uart_add_one_port(&sport_uart_reg, &sport->port);
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
+	}
+#endif
+	if (!ret)
+		return 0;
+
+	if (sport) {
+out_error_unmap:
+		iounmap(sport->port.membase);
+out_error_free_peripherals:
+		peripheral_free_list(
+			(unsigned short *)pdev->dev.platform_data);
+out_error_free_mem:
+		kfree(sport);
+		bfin_sport_uart_ports[pdev->id] = NULL;
+	}
+
+	return ret;
 }
 
-static int sport_uart_remove(struct platform_device *dev)
+static int __devexit sport_uart_remove(struct platform_device *pdev)
 {
-	struct sport_uart_port *sport = platform_get_drvdata(dev);
+	struct sport_uart_port *sport = platform_get_drvdata(pdev);
 
-	pr_debug("%s enter\n", __func__);
-	platform_set_drvdata(dev, NULL);
+	dev_dbg(&pdev->dev, "%s enter\n", __func__);
+	dev_set_drvdata(&pdev->dev, NULL);
 
-	if (sport)
+	if (sport) {
 		uart_remove_one_port(&sport_uart_reg, &sport->port);
+		iounmap(sport->port.membase);
+		peripheral_free_list(
+			(unsigned short *)pdev->dev.platform_data);
+		kfree(sport);
+		bfin_sport_uart_ports[pdev->id] = NULL;
+	}
 
 	return 0;
 }
 
 static struct platform_driver sport_uart_driver = {
 	.probe		= sport_uart_probe,
-	.remove		= sport_uart_remove,
-	.suspend	= sport_uart_suspend,
-	.resume		= sport_uart_resume,
+	.remove		= __devexit_p(sport_uart_remove),
 	.driver		= {
 		.name	= DRV_NAME,
+#ifdef CONFIG_PM
+		.pm	= &bfin_sport_uart_dev_pm_ops,
+#endif
 	},
 };
 
+#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
+static __initdata struct early_platform_driver early_sport_uart_driver = {
+	.class_str = DRV_NAME,
+	.pdrv = &sport_uart_driver,
+	.requested_id = EARLY_PLATFORM_ID_UNSET,
+};
+
+static int __init sport_uart_rs_console_init(void)
+{
+	early_platform_driver_register(&early_sport_uart_driver, DRV_NAME);
+
+	early_platform_driver_probe(DRV_NAME, BFIN_SPORT_UART_MAX_PORTS, 0);
+
+	register_console(&sport_uart_console);
+
+	return 0;
+}
+console_initcall(sport_uart_rs_console_init);
+#endif
+
 static int __init sport_uart_init(void)
 {
 	int ret;
 
-	pr_debug("%s enter\n", __func__);
+	pr_info("Serial: Blackfin uart over sport driver\n");
+
 	ret = uart_register_driver(&sport_uart_reg);
-	if (ret != 0) {
-		printk(KERN_ERR "Failed to register %s:%d\n",
+	if (ret) {
+		pr_err("failed to register %s:%d\n",
 				sport_uart_reg.driver_name, ret);
 		return ret;
 	}
 
 	ret = platform_driver_register(&sport_uart_driver);
-	if (ret != 0) {
-		printk(KERN_ERR "Failed to register sport uart driver:%d\n", ret);
+	if (ret) {
+		pr_err("failed to register sport uart driver:%d\n", ret);
 		uart_unregister_driver(&sport_uart_reg);
 	}
 
-
-	pr_debug("%s exit\n", __func__);
 	return ret;
 }
+module_init(sport_uart_init);
 
 static void __exit sport_uart_exit(void)
 {
-	pr_debug("%s enter\n", __func__);
 	platform_driver_unregister(&sport_uart_driver);
 	uart_unregister_driver(&sport_uart_reg);
 }
-
-module_init(sport_uart_init);
 module_exit(sport_uart_exit);
 
+MODULE_AUTHOR("Sonic Zhang, Roy Huang");
+MODULE_DESCRIPTION("Blackfin serial over SPORT driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/serial/bfin_sport_uart.h b/drivers/serial/bfin_sport_uart.h
index 671d41c..abe0361 100644
--- a/drivers/serial/bfin_sport_uart.h
+++ b/drivers/serial/bfin_sport_uart.h
@@ -1,29 +1,23 @@
 /*
- * File:	linux/drivers/serial/bfin_sport_uart.h
+ * Blackfin On-Chip Sport Emulated UART Driver
  *
- * Based on:	include/asm-blackfin/mach-533/bfin_serial_5xx.h
- * Author:	Roy Huang <roy.huang>analog.com>
+ * Copyright 2006-2008 Analog Devices Inc.
  *
- * Created:	Nov 22, 2006
- * Copyright:	(C) Analog Device Inc.
- * Description: this driver enable SPORTs on Blackfin emulate UART.
+ * Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * Licensed under the GPL-2 or later.
  */
 
+/*
+ * This driver and the hardware supported are in term of EE-191 of ADI.
+ * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf
+ * This application note describe how to implement a UART on a Sharc DSP,
+ * but this driver is implemented on Blackfin Processor.
+ * Transmit Frame Sync is not used by this driver to transfer data out.
+ */
+
+#ifndef _BFIN_SPORT_UART_H
+#define _BFIN_SPORT_UART_H
 
 #define OFFSET_TCR1		0x00	/* Transmit Configuration 1 Register */
 #define OFFSET_TCR2		0x04	/* Transmit Configuration 2 Register */
@@ -61,3 +55,7 @@
 #define SPORT_PUT_RCLKDIV(sport, v)	bfin_write16(((sport)->port.membase + OFFSET_RCLKDIV), v)
 #define SPORT_PUT_RFSDIV(sport, v)	bfin_write16(((sport)->port.membase + OFFSET_RFSDIV), v)
 #define SPORT_PUT_STAT(sport, v)	bfin_write16(((sport)->port.membase + OFFSET_STAT), v)
+
+#define SPORT_TX_FIFO_SIZE	8
+
+#endif /* _BFIN_SPORT_UART_H */
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index 0028b6f..53a4682 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -751,7 +751,6 @@
 		trace(icom_port, "FID_STATUS", status);
 		count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
 
-                count = tty_buffer_request_room(tty, count);
 		trace(icom_port, "RCV_COUNT", count);
 
 		trace(icom_port, "REAL_COUNT", count);
@@ -1654,4 +1653,6 @@
 MODULE_SUPPORTED_DEVICE
     ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters");
 MODULE_LICENSE("GPL");
-
+MODULE_FIRMWARE("icom_call_setup.bin");
+MODULE_FIRMWARE("icom_res_dce.bin");
+MODULE_FIRMWARE("icom_asc.bin");
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 60d665a..e579d7a 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -440,7 +440,7 @@
 
 		temp = readl(sport->port.membase + USR2);
 		if (temp & USR2_BRCD) {
-			writel(temp | USR2_BRCD, sport->port.membase + USR2);
+			writel(USR2_BRCD, sport->port.membase + USR2);
 			if (uart_handle_break(&sport->port))
 				continue;
 		}
@@ -1279,7 +1279,7 @@
 		sport->use_irda = 1;
 #endif
 
-	if (pdata->init) {
+	if (pdata && pdata->init) {
 		ret = pdata->init(pdev);
 		if (ret)
 			goto clkput;
@@ -1292,7 +1292,7 @@
 
 	return 0;
 deinit:
-	if (pdata->exit)
+	if (pdata && pdata->exit)
 		pdata->exit(pdev);
 clkput:
 	clk_put(sport->clk);
@@ -1321,7 +1321,7 @@
 
 	clk_disable(sport->clk);
 
-	if (pdata->exit)
+	if (pdata && pdata->exit)
 		pdata->exit(pdev);
 
 	iounmap(sport->port.membase);
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c
index 85dc041..23ba6b4 100644
--- a/drivers/serial/ioc3_serial.c
+++ b/drivers/serial/ioc3_serial.c
@@ -1411,8 +1411,7 @@
 	read_count = do_read(the_port, ch, MAX_CHARS);
 	if (read_count > 0) {
 		flip = 1;
-		read_room = tty_buffer_request_room(tty, read_count);
-		tty_insert_flip_string(tty, ch, read_room);
+		read_room = tty_insert_flip_string(tty, ch, read_count);
 		the_port->icount.rx += read_count;
 	}
 	spin_unlock_irqrestore(&the_port->lock, pflags);
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index 108c3e0..12cb5e4 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -179,6 +179,7 @@
 
 	return 0;
  out_free_irq:
+	jsm_remove_uart_port(brd);
 	free_irq(brd->irq, brd);
  out_iounmap:
 	iounmap(brd->re_map_membase);
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index cd95e21..5673ca9 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -432,7 +432,7 @@
 
 int jsm_uart_port_init(struct jsm_board *brd)
 {
-	int i;
+	int i, rc;
 	unsigned int line;
 	struct jsm_channel *ch;
 
@@ -467,8 +467,11 @@
 		} else
 			set_bit(line, linemap);
 		brd->channels[i]->uart_port.line = line;
-		if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port))
-			printk(KERN_INFO "jsm: add device failed\n");
+		rc = uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port);
+		if (rc){
+			printk(KERN_INFO "jsm: Port %d failed. Aborting...\n", i);
+			return rc;
+		}
 		else
 			printk(KERN_INFO "jsm: Port %d added\n", i);
 	}
diff --git a/drivers/serial/msm_serial.c b/drivers/serial/msm_serial.c
index b05c5aa..ecdc0fa 100644
--- a/drivers/serial/msm_serial.c
+++ b/drivers/serial/msm_serial.c
@@ -691,6 +691,7 @@
 	struct msm_port *msm_port;
 	struct resource *resource;
 	struct uart_port *port;
+	int irq;
 
 	if (unlikely(pdev->id < 0 || pdev->id >= UART_NR))
 		return -ENXIO;
@@ -711,9 +712,10 @@
 		return -ENXIO;
 	port->mapbase = resource->start;
 
-	port->irq = platform_get_irq(pdev, 0);
-	if (unlikely(port->irq < 0))
+	irq = platform_get_irq(pdev, 0);
+	if (unlikely(irq < 0))
 		return -ENXIO;
+	port->irq = irq;
 
 	platform_set_drvdata(pdev, port);
 
diff --git a/drivers/serial/s3c2412.c b/drivers/serial/s3c2412.c
index ce75e28..1700b1a 100644
--- a/drivers/serial/s3c2412.c
+++ b/drivers/serial/s3c2412.c
@@ -102,6 +102,7 @@
 	.name		= "Samsung S3C2412 UART",
 	.type		= PORT_S3C2412,
 	.fifosize	= 64,
+	.has_divslot	= 1,
 	.rx_fifomask	= S3C2440_UFSTAT_RXMASK,
 	.rx_fifoshift	= S3C2440_UFSTAT_RXSHIFT,
 	.rx_fifofull	= S3C2440_UFSTAT_RXFULL,
diff --git a/drivers/serial/s5pv210.c b/drivers/serial/s5pv210.c
new file mode 100644
index 0000000..8dc0383
--- /dev/null
+++ b/drivers/serial/s5pv210.c
@@ -0,0 +1,154 @@
+/* linux/drivers/serial/s5pv210.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Based on drivers/serial/s3c6400.c
+ *
+ * Driver for Samsung S5PV210 SoC UARTs.
+ *
+ * This program is free software; you can redistribute it 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/ioport.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <plat/regs-serial.h>
+#include "samsung.h"
+
+static int s5pv210_serial_setsource(struct uart_port *port,
+					struct s3c24xx_uart_clksrc *clk)
+{
+	unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+	if (strcmp(clk->name, "pclk") == 0)
+		ucon &= ~S5PV210_UCON_CLKMASK;
+	else if (strcmp(clk->name, "uclk1") == 0)
+		ucon |= S5PV210_UCON_CLKMASK;
+	else {
+		printk(KERN_ERR "unknown clock source %s\n", clk->name);
+		return -EINVAL;
+	}
+
+	wr_regl(port, S3C2410_UCON, ucon);
+	return 0;
+}
+
+
+static int s5pv210_serial_getsource(struct uart_port *port,
+					struct s3c24xx_uart_clksrc *clk)
+{
+	u32 ucon = rd_regl(port, S3C2410_UCON);
+
+	clk->divisor = 1;
+
+	switch (ucon & S5PV210_UCON_CLKMASK) {
+	case S5PV210_UCON_PCLK:
+		clk->name = "pclk";
+		break;
+	case S5PV210_UCON_UCLK:
+		clk->name = "uclk1";
+		break;
+	}
+
+	return 0;
+}
+
+static int s5pv210_serial_resetport(struct uart_port *port,
+					struct s3c2410_uartcfg *cfg)
+{
+	unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+	ucon &= S5PV210_UCON_CLKMASK;
+	wr_regl(port, S3C2410_UCON,  ucon | cfg->ucon);
+	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+	/* reset both fifos */
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+	return 0;
+}
+
+#define S5PV210_UART_DEFAULT_INFO(fifo_size)			\
+		.name		= "Samsung S5PV210 UART0",	\
+		.type		= PORT_S3C6400,			\
+		.fifosize	= fifo_size,			\
+		.has_divslot	= 1,				\
+		.rx_fifomask	= S5PV210_UFSTAT_RXMASK,	\
+		.rx_fifoshift	= S5PV210_UFSTAT_RXSHIFT,	\
+		.rx_fifofull	= S5PV210_UFSTAT_RXFULL,	\
+		.tx_fifofull	= S5PV210_UFSTAT_TXFULL,	\
+		.tx_fifomask	= S5PV210_UFSTAT_TXMASK,	\
+		.tx_fifoshift	= S5PV210_UFSTAT_TXSHIFT,	\
+		.get_clksrc	= s5pv210_serial_getsource,	\
+		.set_clksrc	= s5pv210_serial_setsource,	\
+		.reset_port	= s5pv210_serial_resetport
+
+static struct s3c24xx_uart_info s5p_port_fifo256 = {
+	S5PV210_UART_DEFAULT_INFO(256),
+};
+
+static struct s3c24xx_uart_info s5p_port_fifo64 = {
+	S5PV210_UART_DEFAULT_INFO(64),
+};
+
+static struct s3c24xx_uart_info s5p_port_fifo16 = {
+	S5PV210_UART_DEFAULT_INFO(16),
+};
+
+static struct s3c24xx_uart_info *s5p_uart_inf[] = {
+	[0] = &s5p_port_fifo256,
+	[1] = &s5p_port_fifo64,
+	[2] = &s5p_port_fifo16,
+	[3] = &s5p_port_fifo16,
+};
+
+/* device management */
+static int s5p_serial_probe(struct platform_device *pdev)
+{
+	return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]);
+}
+
+static struct platform_driver s5p_serial_drv = {
+	.probe		= s5p_serial_probe,
+	.remove		= __devexit_p(s3c24xx_serial_remove),
+	.driver		= {
+		.name	= "s5pv210-uart",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init s5pv210_serial_console_init(void)
+{
+	return s3c24xx_serial_initconsole(&s5p_serial_drv, s5p_uart_inf);
+}
+
+console_initcall(s5pv210_serial_console_init);
+
+static int __init s5p_serial_init(void)
+{
+	return s3c24xx_serial_init(&s5p_serial_drv, *s5p_uart_inf);
+}
+
+static void __exit s5p_serial_exit(void)
+{
+	platform_driver_unregister(&s5p_serial_drv);
+}
+
+module_init(s5p_serial_init);
+module_exit(s5p_serial_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s5pv210-uart");
+MODULE_DESCRIPTION("Samsung S5PV210 UART Driver support");
+MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c
index 52e3df1..a9d6c56 100644
--- a/drivers/serial/samsung.c
+++ b/drivers/serial/samsung.c
@@ -1271,7 +1271,7 @@
 	unsigned long ufstat, utrstat;
 
 	if (ufcon & S3C2410_UFCON_FIFOMODE) {
-		/* fifo mode - check ammount of data in fifo registers... */
+		/* fifo mode - check amount of data in fifo registers... */
 
 		ufstat = rd_regl(port, S3C2410_UFSTAT);
 		return (ufstat & info->tx_fifofull) ? 0 : 1;
@@ -1374,7 +1374,7 @@
  * data.
 */
 
-static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info *info)
+static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info **info)
 {
 	struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports;
 	struct platform_device **platdev_ptr;
@@ -1385,7 +1385,7 @@
 	platdev_ptr = s3c24xx_uart_devs;
 
 	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) {
-		s3c24xx_serial_init_port(ptr, info, *platdev_ptr);
+		s3c24xx_serial_init_port(ptr, info[i], *platdev_ptr);
 	}
 
 	return 0;
@@ -1451,7 +1451,7 @@
 };
 
 int s3c24xx_serial_initconsole(struct platform_driver *drv,
-			       struct s3c24xx_uart_info *info)
+			       struct s3c24xx_uart_info **info)
 
 {
 	struct platform_device *dev = s3c24xx_uart_devs[0];
diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h
index 1fb2234..0ac06a0 100644
--- a/drivers/serial/samsung.h
+++ b/drivers/serial/samsung.h
@@ -75,19 +75,24 @@
 extern int __devexit s3c24xx_serial_remove(struct platform_device *dev);
 
 extern int s3c24xx_serial_initconsole(struct platform_driver *drv,
-				      struct s3c24xx_uart_info *uart);
+				      struct s3c24xx_uart_info **uart);
 
 extern int s3c24xx_serial_init(struct platform_driver *drv,
 			       struct s3c24xx_uart_info *info);
 
 #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
 
-#define s3c24xx_console_init(__drv, __inf)			\
-static int __init s3c_serial_console_init(void)			\
-{								\
-	return s3c24xx_serial_initconsole(__drv, __inf);	\
-}								\
-								\
+#define s3c24xx_console_init(__drv, __inf)				\
+static int __init s3c_serial_console_init(void)				\
+{									\
+	struct s3c24xx_uart_info *uinfo[CONFIG_SERIAL_SAMSUNG_UARTS];	\
+	int i;								\
+									\
+	for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)		\
+		uinfo[i] = __inf;					\
+	return s3c24xx_serial_initconsole(__drv, uinfo);		\
+}									\
+									\
 console_initcall(s3c_serial_console_init)
 
 #else
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 42f3333..980f394 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -48,6 +48,9 @@
 #include <linux/ctype.h>
 #include <linux/err.h>
 #include <linux/list.h>
+#include <linux/dmaengine.h>
+#include <linux/scatterlist.h>
+#include <linux/timer.h>
 
 #ifdef CONFIG_SUPERH
 #include <asm/sh_bios.h>
@@ -84,6 +87,27 @@
 	struct clk		*dclk;
 
 	struct list_head	node;
+	struct dma_chan			*chan_tx;
+	struct dma_chan			*chan_rx;
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	struct device			*dma_dev;
+	enum sh_dmae_slave_chan_id	slave_tx;
+	enum sh_dmae_slave_chan_id	slave_rx;
+	struct dma_async_tx_descriptor	*desc_tx;
+	struct dma_async_tx_descriptor	*desc_rx[2];
+	dma_cookie_t			cookie_tx;
+	dma_cookie_t			cookie_rx[2];
+	dma_cookie_t			active_rx;
+	struct scatterlist		sg_tx;
+	unsigned int			sg_len_tx;
+	struct scatterlist		sg_rx[2];
+	size_t				buf_len_rx;
+	struct sh_dmae_slave		param_tx;
+	struct sh_dmae_slave		param_rx;
+	struct work_struct		work_tx;
+	struct work_struct		work_rx;
+	struct timer_list		rx_timer;
+#endif
 };
 
 struct sh_sci_priv {
@@ -269,29 +293,44 @@
     defined(CONFIG_CPU_SUBTYPE_SH7780) || \
     defined(CONFIG_CPU_SUBTYPE_SH7785) || \
     defined(CONFIG_CPU_SUBTYPE_SH7786)
-static inline int scif_txroom(struct uart_port *port)
+static int scif_txfill(struct uart_port *port)
 {
-	return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff);
+	return sci_in(port, SCTFDR) & 0xff;
 }
 
-static inline int scif_rxroom(struct uart_port *port)
+static int scif_txroom(struct uart_port *port)
+{
+	return SCIF_TXROOM_MAX - scif_txfill(port);
+}
+
+static int scif_rxfill(struct uart_port *port)
 {
 	return sci_in(port, SCRFDR) & 0xff;
 }
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-static inline int scif_txroom(struct uart_port *port)
+static int scif_txfill(struct uart_port *port)
 {
-	if ((port->mapbase == 0xffe00000) ||
-	    (port->mapbase == 0xffe08000)) {
+	if (port->mapbase == 0xffe00000 ||
+	    port->mapbase == 0xffe08000)
 		/* SCIF0/1*/
-		return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff);
-	} else {
+		return sci_in(port, SCTFDR) & 0xff;
+	else
 		/* SCIF2 */
-		return SCIF2_TXROOM_MAX - (sci_in(port, SCFDR) >> 8);
-	}
+		return sci_in(port, SCFDR) >> 8;
 }
 
-static inline int scif_rxroom(struct uart_port *port)
+static int scif_txroom(struct uart_port *port)
+{
+	if (port->mapbase == 0xffe00000 ||
+	    port->mapbase == 0xffe08000)
+		/* SCIF0/1*/
+		return SCIF_TXROOM_MAX - scif_txfill(port);
+	else
+		/* SCIF2 */
+		return SCIF2_TXROOM_MAX - scif_txfill(port);
+}
+
+static int scif_rxfill(struct uart_port *port)
 {
 	if ((port->mapbase == 0xffe00000) ||
 	    (port->mapbase == 0xffe08000)) {
@@ -303,23 +342,33 @@
 	}
 }
 #else
-static inline int scif_txroom(struct uart_port *port)
+static int scif_txfill(struct uart_port *port)
 {
-	return SCIF_TXROOM_MAX - (sci_in(port, SCFDR) >> 8);
+	return sci_in(port, SCFDR) >> 8;
 }
 
-static inline int scif_rxroom(struct uart_port *port)
+static int scif_txroom(struct uart_port *port)
+{
+	return SCIF_TXROOM_MAX - scif_txfill(port);
+}
+
+static int scif_rxfill(struct uart_port *port)
 {
 	return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
 }
 #endif
 
-static inline int sci_txroom(struct uart_port *port)
+static int sci_txfill(struct uart_port *port)
 {
-	return (sci_in(port, SCxSR) & SCI_TDRE) != 0;
+	return !(sci_in(port, SCxSR) & SCI_TDRE);
 }
 
-static inline int sci_rxroom(struct uart_port *port)
+static int sci_txroom(struct uart_port *port)
+{
+	return !sci_txfill(port);
+}
+
+static int sci_rxfill(struct uart_port *port)
 {
 	return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
 }
@@ -406,9 +455,9 @@
 
 	while (1) {
 		if (port->type == PORT_SCI)
-			count = sci_rxroom(port);
+			count = sci_rxfill(port);
 		else
-			count = scif_rxroom(port);
+			count = scif_rxfill(port);
 
 		/* Don't copy more bytes than there is room for in the buffer */
 		count = tty_buffer_request_room(tty, count);
@@ -453,10 +502,10 @@
 				}
 
 				/* Store data and status */
-				if (status&SCxSR_FER(port)) {
+				if (status & SCxSR_FER(port)) {
 					flag = TTY_FRAME;
 					dev_notice(port->dev, "frame error\n");
-				} else if (status&SCxSR_PER(port)) {
+				} else if (status & SCxSR_PER(port)) {
 					flag = TTY_PARITY;
 					dev_notice(port->dev, "parity error\n");
 				} else
@@ -618,13 +667,39 @@
 	return copied;
 }
 
-static irqreturn_t sci_rx_interrupt(int irq, void *port)
+static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
 {
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	struct uart_port *port = ptr;
+	struct sci_port *s = to_sci_port(port);
+
+	if (s->chan_rx) {
+		unsigned long tout;
+		u16 scr = sci_in(port, SCSCR);
+		u16 ssr = sci_in(port, SCxSR);
+
+		/* Disable future Rx interrupts */
+		sci_out(port, SCSCR, scr & ~SCI_CTRL_FLAGS_RIE);
+		/* Clear current interrupt */
+		sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
+		/* Calculate delay for 1.5 DMA buffers */
+		tout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
+			port->fifosize / 2;
+		dev_dbg(port->dev, "Rx IRQ: setup timeout in %lu ms\n",
+			tout * 1000 / HZ);
+		if (tout < 2)
+			tout = 2;
+		mod_timer(&s->rx_timer, jiffies + tout);
+
+		return IRQ_HANDLED;
+	}
+#endif
+
 	/* I think sci_receive_chars has to be called irrespective
 	 * of whether the I_IXOFF is set, otherwise, how is the interrupt
 	 * to be disabled?
 	 */
-	sci_receive_chars(port);
+	sci_receive_chars(ptr);
 
 	return IRQ_HANDLED;
 }
@@ -680,6 +755,7 @@
 {
 	unsigned short ssr_status, scr_status, err_enabled;
 	struct uart_port *port = ptr;
+	struct sci_port *s = to_sci_port(port);
 	irqreturn_t ret = IRQ_NONE;
 
 	ssr_status = sci_in(port, SCxSR);
@@ -687,10 +763,15 @@
 	err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE);
 
 	/* Tx Interrupt */
-	if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE))
+	if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE) &&
+	    !s->chan_tx)
 		ret = sci_tx_interrupt(irq, ptr);
-	/* Rx Interrupt */
-	if ((ssr_status & SCxSR_RDxF(port)) && (scr_status & SCI_CTRL_FLAGS_RIE))
+	/*
+	 * Rx Interrupt: if we're using DMA, the DMA controller clears RDF /
+	 * DR flags
+	 */
+	if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) &&
+	    (scr_status & SCI_CTRL_FLAGS_RIE))
 		ret = sci_rx_interrupt(irq, ptr);
 	/* Error Interrupt */
 	if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled)
@@ -699,6 +780,10 @@
 	if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
 		ret = sci_br_interrupt(irq, ptr);
 
+	WARN_ONCE(ret == IRQ_NONE,
+		  "%s: %d IRQ %d, status %x, control %x\n", __func__,
+		  irq, port->line, ssr_status, scr_status);
+
 	return ret;
 }
 
@@ -800,7 +885,9 @@
 static unsigned int sci_tx_empty(struct uart_port *port)
 {
 	unsigned short status = sci_in(port, SCxSR);
-	return status & SCxSR_TEND(port) ? TIOCSER_TEMT : 0;
+	unsigned short in_tx_fifo = scif_txfill(port);
+
+	return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
 }
 
 static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
@@ -812,16 +899,297 @@
 
 static unsigned int sci_get_mctrl(struct uart_port *port)
 {
-	/* This routine is used for geting signals of: DTR, DCD, DSR, RI,
+	/* This routine is used for getting signals of: DTR, DCD, DSR, RI,
 	   and CTS/RTS */
 
 	return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR;
 }
 
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+static void sci_dma_tx_complete(void *arg)
+{
+	struct sci_port *s = arg;
+	struct uart_port *port = &s->port;
+	struct circ_buf *xmit = &port->state->xmit;
+	unsigned long flags;
+
+	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	xmit->tail += s->sg_tx.length;
+	xmit->tail &= UART_XMIT_SIZE - 1;
+
+	port->icount.tx += s->sg_tx.length;
+
+	async_tx_ack(s->desc_tx);
+	s->cookie_tx = -EINVAL;
+	s->desc_tx = NULL;
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_chars_pending(xmit))
+		schedule_work(&s->work_tx);
+}
+
+/* Locking: called with port lock held */
+static int sci_dma_rx_push(struct sci_port *s, struct tty_struct *tty,
+			   size_t count)
+{
+	struct uart_port *port = &s->port;
+	int i, active, room;
+
+	room = tty_buffer_request_room(tty, count);
+
+	if (s->active_rx == s->cookie_rx[0]) {
+		active = 0;
+	} else if (s->active_rx == s->cookie_rx[1]) {
+		active = 1;
+	} else {
+		dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
+		return 0;
+	}
+
+	if (room < count)
+		dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
+			 count - room);
+	if (!room)
+		return room;
+
+	for (i = 0; i < room; i++)
+		tty_insert_flip_char(tty, ((u8 *)sg_virt(&s->sg_rx[active]))[i],
+				     TTY_NORMAL);
+
+	port->icount.rx += room;
+
+	return room;
+}
+
+static void sci_dma_rx_complete(void *arg)
+{
+	struct sci_port *s = arg;
+	struct uart_port *port = &s->port;
+	struct tty_struct *tty = port->state->port.tty;
+	unsigned long flags;
+	int count;
+
+	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	count = sci_dma_rx_push(s, tty, s->buf_len_rx);
+
+	mod_timer(&s->rx_timer, jiffies + msecs_to_jiffies(5));
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if (count)
+		tty_flip_buffer_push(tty);
+
+	schedule_work(&s->work_rx);
+}
+
+static void sci_start_rx(struct uart_port *port);
+static void sci_start_tx(struct uart_port *port);
+
+static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
+{
+	struct dma_chan *chan = s->chan_rx;
+	struct uart_port *port = &s->port;
+
+	s->chan_rx = NULL;
+	s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
+	dma_release_channel(chan);
+	dma_free_coherent(port->dev, s->buf_len_rx * 2,
+			  sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0]));
+	if (enable_pio)
+		sci_start_rx(port);
+}
+
+static void sci_tx_dma_release(struct sci_port *s, bool enable_pio)
+{
+	struct dma_chan *chan = s->chan_tx;
+	struct uart_port *port = &s->port;
+
+	s->chan_tx = NULL;
+	s->cookie_tx = -EINVAL;
+	dma_release_channel(chan);
+	if (enable_pio)
+		sci_start_tx(port);
+}
+
+static void sci_submit_rx(struct sci_port *s)
+{
+	struct dma_chan *chan = s->chan_rx;
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		struct scatterlist *sg = &s->sg_rx[i];
+		struct dma_async_tx_descriptor *desc;
+
+		desc = chan->device->device_prep_slave_sg(chan,
+			sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT);
+
+		if (desc) {
+			s->desc_rx[i] = desc;
+			desc->callback = sci_dma_rx_complete;
+			desc->callback_param = s;
+			s->cookie_rx[i] = desc->tx_submit(desc);
+		}
+
+		if (!desc || s->cookie_rx[i] < 0) {
+			if (i) {
+				async_tx_ack(s->desc_rx[0]);
+				s->cookie_rx[0] = -EINVAL;
+			}
+			if (desc) {
+				async_tx_ack(desc);
+				s->cookie_rx[i] = -EINVAL;
+			}
+			dev_warn(s->port.dev,
+				 "failed to re-start DMA, using PIO\n");
+			sci_rx_dma_release(s, true);
+			return;
+		}
+	}
+
+	s->active_rx = s->cookie_rx[0];
+
+	dma_async_issue_pending(chan);
+}
+
+static void work_fn_rx(struct work_struct *work)
+{
+	struct sci_port *s = container_of(work, struct sci_port, work_rx);
+	struct uart_port *port = &s->port;
+	struct dma_async_tx_descriptor *desc;
+	int new;
+
+	if (s->active_rx == s->cookie_rx[0]) {
+		new = 0;
+	} else if (s->active_rx == s->cookie_rx[1]) {
+		new = 1;
+	} else {
+		dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
+		return;
+	}
+	desc = s->desc_rx[new];
+
+	if (dma_async_is_tx_complete(s->chan_rx, s->active_rx, NULL, NULL) !=
+	    DMA_SUCCESS) {
+		/* Handle incomplete DMA receive */
+		struct tty_struct *tty = port->state->port.tty;
+		struct dma_chan *chan = s->chan_rx;
+		struct sh_desc *sh_desc = container_of(desc, struct sh_desc,
+						       async_tx);
+		unsigned long flags;
+		int count;
+
+		chan->device->device_terminate_all(chan);
+		dev_dbg(port->dev, "Read %u bytes with cookie %d\n",
+			sh_desc->partial, sh_desc->cookie);
+
+		spin_lock_irqsave(&port->lock, flags);
+		count = sci_dma_rx_push(s, tty, sh_desc->partial);
+		spin_unlock_irqrestore(&port->lock, flags);
+
+		if (count)
+			tty_flip_buffer_push(tty);
+
+		sci_submit_rx(s);
+
+		return;
+	}
+
+	s->cookie_rx[new] = desc->tx_submit(desc);
+	if (s->cookie_rx[new] < 0) {
+		dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n");
+		sci_rx_dma_release(s, true);
+		return;
+	}
+
+	dev_dbg(port->dev, "%s: cookie %d #%d\n", __func__,
+		s->cookie_rx[new], new);
+
+	s->active_rx = s->cookie_rx[!new];
+}
+
+static void work_fn_tx(struct work_struct *work)
+{
+	struct sci_port *s = container_of(work, struct sci_port, work_tx);
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *chan = s->chan_tx;
+	struct uart_port *port = &s->port;
+	struct circ_buf *xmit = &port->state->xmit;
+	struct scatterlist *sg = &s->sg_tx;
+
+	/*
+	 * DMA is idle now.
+	 * Port xmit buffer is already mapped, and it is one page... Just adjust
+	 * offsets and lengths. Since it is a circular buffer, we have to
+	 * transmit till the end, and then the rest. Take the port lock to get a
+	 * consistent xmit buffer state.
+	 */
+	spin_lock_irq(&port->lock);
+	sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
+	sg->dma_address = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
+		sg->offset;
+	sg->length = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
+		CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
+	sg->dma_length = sg->length;
+	spin_unlock_irq(&port->lock);
+
+	BUG_ON(!sg->length);
+
+	desc = chan->device->device_prep_slave_sg(chan,
+			sg, s->sg_len_tx, DMA_TO_DEVICE,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		/* switch to PIO */
+		sci_tx_dma_release(s, true);
+		return;
+	}
+
+	dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
+
+	spin_lock_irq(&port->lock);
+	s->desc_tx = desc;
+	desc->callback = sci_dma_tx_complete;
+	desc->callback_param = s;
+	spin_unlock_irq(&port->lock);
+	s->cookie_tx = desc->tx_submit(desc);
+	if (s->cookie_tx < 0) {
+		dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n");
+		/* switch to PIO */
+		sci_tx_dma_release(s, true);
+		return;
+	}
+
+	dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", __func__,
+		xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
+
+	dma_async_issue_pending(chan);
+}
+#endif
+
 static void sci_start_tx(struct uart_port *port)
 {
 	unsigned short ctrl;
 
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	struct sci_port *s = to_sci_port(port);
+
+	if (s->chan_tx) {
+		if (!uart_circ_empty(&s->port.state->xmit) && s->cookie_tx < 0)
+			schedule_work(&s->work_tx);
+
+		return;
+	}
+#endif
+
 	/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
 	ctrl = sci_in(port, SCSCR);
 	ctrl |= SCI_CTRL_FLAGS_TIE;
@@ -838,13 +1206,12 @@
 	sci_out(port, SCSCR, ctrl);
 }
 
-static void sci_start_rx(struct uart_port *port, unsigned int tty_start)
+static void sci_start_rx(struct uart_port *port)
 {
-	unsigned short ctrl;
+	unsigned short ctrl = SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE;
 
 	/* Set RIE (Receive Interrupt Enable) bit in SCSCR */
-	ctrl = sci_in(port, SCSCR);
-	ctrl |= SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE;
+	ctrl |= sci_in(port, SCSCR);
 	sci_out(port, SCSCR, ctrl);
 }
 
@@ -868,16 +1235,154 @@
 	/* Nothing here yet .. */
 }
 
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+static bool filter(struct dma_chan *chan, void *slave)
+{
+	struct sh_dmae_slave *param = slave;
+
+	dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__,
+		param->slave_id);
+
+	if (param->dma_dev == chan->device->dev) {
+		chan->private = param;
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static void rx_timer_fn(unsigned long arg)
+{
+	struct sci_port *s = (struct sci_port *)arg;
+	struct uart_port *port = &s->port;
+
+	u16 scr = sci_in(port, SCSCR);
+	sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE);
+	dev_dbg(port->dev, "DMA Rx timed out\n");
+	schedule_work(&s->work_rx);
+}
+
+static void sci_request_dma(struct uart_port *port)
+{
+	struct sci_port *s = to_sci_port(port);
+	struct sh_dmae_slave *param;
+	struct dma_chan *chan;
+	dma_cap_mask_t mask;
+	int nent;
+
+	dev_dbg(port->dev, "%s: port %d DMA %p\n", __func__,
+		port->line, s->dma_dev);
+
+	if (!s->dma_dev)
+		return;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	param = &s->param_tx;
+
+	/* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
+	param->slave_id = s->slave_tx;
+	param->dma_dev = s->dma_dev;
+
+	s->cookie_tx = -EINVAL;
+	chan = dma_request_channel(mask, filter, param);
+	dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
+	if (chan) {
+		s->chan_tx = chan;
+		sg_init_table(&s->sg_tx, 1);
+		/* UART circular tx buffer is an aligned page. */
+		BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
+		sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf),
+			    UART_XMIT_SIZE, (int)port->state->xmit.buf & ~PAGE_MASK);
+		nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE);
+		if (!nent)
+			sci_tx_dma_release(s, false);
+		else
+			dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
+				sg_dma_len(&s->sg_tx),
+				port->state->xmit.buf, sg_dma_address(&s->sg_tx));
+
+		s->sg_len_tx = nent;
+
+		INIT_WORK(&s->work_tx, work_fn_tx);
+	}
+
+	param = &s->param_rx;
+
+	/* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
+	param->slave_id = s->slave_rx;
+	param->dma_dev = s->dma_dev;
+
+	chan = dma_request_channel(mask, filter, param);
+	dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
+	if (chan) {
+		dma_addr_t dma[2];
+		void *buf[2];
+		int i;
+
+		s->chan_rx = chan;
+
+		s->buf_len_rx = 2 * max(16, (int)port->fifosize);
+		buf[0] = dma_alloc_coherent(port->dev, s->buf_len_rx * 2,
+					    &dma[0], GFP_KERNEL);
+
+		if (!buf[0]) {
+			dev_warn(port->dev,
+				 "failed to allocate dma buffer, using PIO\n");
+			sci_rx_dma_release(s, true);
+			return;
+		}
+
+		buf[1] = buf[0] + s->buf_len_rx;
+		dma[1] = dma[0] + s->buf_len_rx;
+
+		for (i = 0; i < 2; i++) {
+			struct scatterlist *sg = &s->sg_rx[i];
+
+			sg_init_table(sg, 1);
+			sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx,
+				    (int)buf[i] & ~PAGE_MASK);
+			sg->dma_address = dma[i];
+			sg->dma_length = sg->length;
+		}
+
+		INIT_WORK(&s->work_rx, work_fn_rx);
+		setup_timer(&s->rx_timer, rx_timer_fn, (unsigned long)s);
+
+		sci_submit_rx(s);
+	}
+}
+
+static void sci_free_dma(struct uart_port *port)
+{
+	struct sci_port *s = to_sci_port(port);
+
+	if (!s->dma_dev)
+		return;
+
+	if (s->chan_tx)
+		sci_tx_dma_release(s, false);
+	if (s->chan_rx)
+		sci_rx_dma_release(s, false);
+}
+#endif
+
 static int sci_startup(struct uart_port *port)
 {
 	struct sci_port *s = to_sci_port(port);
 
+	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
 	if (s->enable)
 		s->enable(port);
 
 	sci_request_irq(s);
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	sci_request_dma(port);
+#endif
 	sci_start_tx(port);
-	sci_start_rx(port, 1);
+	sci_start_rx(port);
 
 	return 0;
 }
@@ -886,8 +1391,13 @@
 {
 	struct sci_port *s = to_sci_port(port);
 
+	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
 	sci_stop_rx(port);
 	sci_stop_tx(port);
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	sci_free_dma(port);
+#endif
 	sci_free_irq(s);
 
 	if (s->disable)
@@ -937,6 +1447,9 @@
 
 	sci_out(port, SCSMR, smr_val);
 
+	dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
+		SCSCR_INIT(port));
+
 	if (t > 0) {
 		if (t >= 256) {
 			sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1);
@@ -954,7 +1467,7 @@
 	sci_out(port, SCSCR, SCSCR_INIT(port));
 
 	if ((termios->c_cflag & CREAD) != 0)
-		sci_start_rx(port, 0);
+		sci_start_rx(port);
 }
 
 static const char *sci_type(struct uart_port *port)
@@ -1049,19 +1562,21 @@
 				      unsigned int index,
 				      struct plat_sci_port *p)
 {
-	sci_port->port.ops	= &sci_uart_ops;
-	sci_port->port.iotype	= UPIO_MEM;
-	sci_port->port.line	= index;
+	struct uart_port *port = &sci_port->port;
+
+	port->ops	= &sci_uart_ops;
+	port->iotype	= UPIO_MEM;
+	port->line	= index;
 
 	switch (p->type) {
 	case PORT_SCIFA:
-		sci_port->port.fifosize = 64;
+		port->fifosize = 64;
 		break;
 	case PORT_SCIF:
-		sci_port->port.fifosize = 16;
+		port->fifosize = 16;
 		break;
 	default:
-		sci_port->port.fifosize = 1;
+		port->fifosize = 1;
 		break;
 	}
 
@@ -1070,19 +1585,28 @@
 		sci_port->dclk = clk_get(&dev->dev, "peripheral_clk");
 		sci_port->enable = sci_clk_enable;
 		sci_port->disable = sci_clk_disable;
-		sci_port->port.dev = &dev->dev;
+		port->dev = &dev->dev;
 	}
 
 	sci_port->break_timer.data = (unsigned long)sci_port;
 	sci_port->break_timer.function = sci_break_timer;
 	init_timer(&sci_port->break_timer);
 
-	sci_port->port.mapbase	= p->mapbase;
-	sci_port->port.membase	= p->membase;
+	port->mapbase	= p->mapbase;
+	port->membase	= p->membase;
 
-	sci_port->port.irq	= p->irqs[SCIx_TXI_IRQ];
-	sci_port->port.flags	= p->flags;
-	sci_port->type		= sci_port->port.type = p->type;
+	port->irq	= p->irqs[SCIx_TXI_IRQ];
+	port->flags	= p->flags;
+	sci_port->type	= port->type = p->type;
+
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	sci_port->dma_dev	= p->dma_dev;
+	sci_port->slave_tx	= p->dma_slave_tx;
+	sci_port->slave_rx	= p->dma_slave_rx;
+
+	dev_dbg(port->dev, "%s: DMA device %p, tx %d, rx %d\n", __func__,
+		p->dma_dev, p->dma_slave_tx, p->dma_slave_rx);
+#endif
 
 	memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
 }
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index f7d2589..fad67d3 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -30,7 +30,8 @@
  */
 # define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0
 #elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7721)
+      defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+      defined(CONFIG_ARCH_SHMOBILE)
 # define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define PORT_PTCR	   0xA405011EUL
 # define PORT_PVCR	   0xA4050122UL
@@ -228,7 +229,8 @@
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
+    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+    defined(CONFIG_ARCH_SHMOBILE)
 # define SCIF_ORER    0x0200
 # define SCIF_ERRORS ( SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER)
 # define SCIF_RFDC_MASK 0x007f
@@ -261,7 +263,8 @@
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
+    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+    defined(CONFIG_ARCH_SHMOBILE)
 # define SCxSR_RDxF_CLEAR(port)	 (sci_in(port, SCxSR) & 0xfffc)
 # define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73)
 # define SCxSR_TDxE_CLEAR(port)	 (sci_in(port, SCxSR) & 0xffdf)
@@ -356,7 +359,7 @@
     SCI_OUT(sci_size, sci_offset, value);				\
   }
 
-#ifdef CONFIG_CPU_SH3
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_ARCH_SHMOBILE)
 #if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
 #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \
 		                sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \
@@ -366,7 +369,8 @@
 	  CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7721)
+      defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+      defined(CONFIG_ARCH_SHMOBILE)
 #define SCIF_FNS(name, scif_offset, scif_size) \
   CPU_SCIF_FNS(name, scif_offset, scif_size)
 #else
@@ -401,7 +405,8 @@
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
     defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
+    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+    defined(CONFIG_ARCH_SHMOBILE)
 
 SCIF_FNS(SCSMR,  0x00, 16)
 SCIF_FNS(SCBRR,  0x04,  8)
@@ -413,7 +418,7 @@
 SCIF_FNS(SCFDR,  0x1c, 16)
 SCIF_FNS(SCxTDR, 0x20,  8)
 SCIF_FNS(SCxRDR, 0x24,  8)
-SCIF_FNS(SCLSR,  0x24, 16)
+SCIF_FNS(SCLSR,  0x00,  0)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
       defined(CONFIG_CPU_SUBTYPE_SH7724)
 SCIx_FNS(SCSMR,  0x00, 16, 0x00, 16)
@@ -583,7 +588,8 @@
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7721)
+      defined(CONFIG_CPU_SUBTYPE_SH7721) || \
+      defined(CONFIG_ARCH_SHMOBILE)
 #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\
       defined(CONFIG_CPU_SUBTYPE_SH7724)
diff --git a/drivers/serial/timbuart.c b/drivers/serial/timbuart.c
index 34b31da0..7bf1026 100644
--- a/drivers/serial/timbuart.c
+++ b/drivers/serial/timbuart.c
@@ -421,7 +421,7 @@
 
 static int timbuart_probe(struct platform_device *dev)
 {
-	int err;
+	int err, irq;
 	struct timbuart_port *uart;
 	struct resource *iomem;
 
@@ -453,11 +453,12 @@
 	uart->port.mapbase = iomem->start;
 	uart->port.membase = NULL;
 
-	uart->port.irq = platform_get_irq(dev, 0);
-	if (uart->port.irq < 0) {
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
 		err = -EINVAL;
 		goto err_register;
 	}
+	uart->port.irq = irq;
 
 	tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart);
 
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 3a5a17d..c275039 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -762,6 +762,10 @@
 
 	if (desc->hw.ack_regs)
 		ack_handle[irq] = intc_ack_data(desc, d, enum_id);
+
+#ifdef CONFIG_ARM
+	set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */
+#endif
 }
 
 static unsigned int __init save_reg(struct intc_desc_int *d,
@@ -1024,8 +1028,12 @@
 out_unlock:
 	spin_unlock_irqrestore(&vector_lock, flags);
 
-	if (irq > 0)
+	if (irq > 0) {
 		dynamic_irq_init(irq);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */
+#endif
+	}
 
 	return irq;
 }
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index c010733..1fabede 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -275,7 +275,7 @@
  * Claim the FIQ handler (only one can be active at any one time) and
  * then setup the correct transfer code for this transfer.
  *
- * This call updates all the necessary state information if sucessful,
+ * This call updates all the necessary state information if successful,
  * so the caller does not need to do anything more than start the transfer
  * as normal, since the IRQ will have been re-routed to the FIQ handler.
 */
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index fc2e963..7696a66 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -71,8 +71,6 @@
 
 source "drivers/staging/panel/Kconfig"
 
-source "drivers/staging/altpciechdma/Kconfig"
-
 source "drivers/staging/rtl8187se/Kconfig"
 
 source "drivers/staging/rtl8192su/Kconfig"
@@ -81,20 +79,14 @@
 
 source "drivers/staging/rtl8192e/Kconfig"
 
-source "drivers/staging/mimio/Kconfig"
-
 source "drivers/staging/frontier/Kconfig"
 
 source "drivers/staging/dream/Kconfig"
 
 source "drivers/staging/pohmelfs/Kconfig"
 
-source "drivers/staging/b3dfg/Kconfig"
-
 source "drivers/staging/phison/Kconfig"
 
-source "drivers/staging/p9auth/Kconfig"
-
 source "drivers/staging/line6/Kconfig"
 
 source "drivers/gpu/drm/vmwgfx/Kconfig"
@@ -117,7 +109,7 @@
 
 source "drivers/staging/vme/Kconfig"
 
-source "drivers/staging/rar/Kconfig"
+source "drivers/staging/rar_register/Kconfig"
 
 source "drivers/staging/sep/Kconfig"
 
@@ -143,5 +135,9 @@
 
 source "drivers/staging/sm7xx/Kconfig"
 
+source "drivers/staging/dt3155/Kconfig"
+
+source "drivers/staging/crystalhd/Kconfig"
+
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index b5e67b8..ea2e70e 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -18,18 +18,14 @@
 obj-$(CONFIG_COMEDI)		+= comedi/
 obj-$(CONFIG_ASUS_OLED)		+= asus_oled/
 obj-$(CONFIG_PANEL)		+= panel/
-obj-$(CONFIG_ALTERA_PCIE_CHDMA)	+= altpciechdma/
 obj-$(CONFIG_R8187SE)		+= rtl8187se/
 obj-$(CONFIG_RTL8192SU)		+= rtl8192su/
 obj-$(CONFIG_RTL8192U)		+= rtl8192u/
 obj-$(CONFIG_RTL8192E)		+= rtl8192e/
-obj-$(CONFIG_INPUT_MIMIO)	+= mimio/
 obj-$(CONFIG_TRANZPORT)		+= frontier/
 obj-$(CONFIG_DREAM)		+= dream/
 obj-$(CONFIG_POHMELFS)		+= pohmelfs/
-obj-$(CONFIG_B3DFG)		+= b3dfg/
 obj-$(CONFIG_IDE_PHISON)	+= phison/
-obj-$(CONFIG_PLAN9AUTH)		+= p9auth/
 obj-$(CONFIG_LINE6_USB)		+= line6/
 obj-$(CONFIG_USB_SERIAL_QUATECH2)	+= serqt_usb2/
 obj-$(CONFIG_USB_SERIAL_QUATECH_USB2)	+= quatech_usb2/
@@ -39,7 +35,7 @@
 obj-$(CONFIG_FB_UDL)		+= udlfb/
 obj-$(CONFIG_HYPERV)		+= hv/
 obj-$(CONFIG_VME_BUS)		+= vme/
-obj-$(CONFIG_RAR_REGISTER)	+= rar/
+obj-$(CONFIG_RAR_REGISTER)	+= rar_register/
 obj-$(CONFIG_DX_SEP)		+= sep/
 obj-$(CONFIG_IIO)		+= iio/
 obj-$(CONFIG_RAMZSWAP)		+= ramzswap/
@@ -53,3 +49,5 @@
 obj-$(CONFIG_PCMCIA_WAVELAN)	+= wavelan/
 obj-$(CONFIG_PCMCIA_NETWAVE)	+= netwave/
 obj-$(CONFIG_FB_SM7XX)		+= sm7xx/
+obj-$(CONFIG_DT3155)		+= dt3155/
+obj-$(CONFIG_CRYSTALHD)		+= crystalhd/
diff --git a/drivers/staging/altpciechdma/Kconfig b/drivers/staging/altpciechdma/Kconfig
deleted file mode 100644
index 0f4bf92..0000000
--- a/drivers/staging/altpciechdma/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config ALTERA_PCIE_CHDMA
-	tristate "Altera PCI Express Chaining DMA driver"
-	depends on PCI
-	default N
-	---help---
-	  A reference driver that exercises the Chaining DMA logic reference
-	  design generated along the Altera FPGA PCI Express soft or hard core,
-	  only if instantiated using the MegaWizard, not the SOPC builder, of
-	  Quartus 8.1.
-
diff --git a/drivers/staging/altpciechdma/Makefile b/drivers/staging/altpciechdma/Makefile
deleted file mode 100644
index c08c843..0000000
--- a/drivers/staging/altpciechdma/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_ALTERA_PCIE_CHDMA)	+= altpciechdma.o
-
diff --git a/drivers/staging/altpciechdma/TODO b/drivers/staging/altpciechdma/TODO
deleted file mode 100644
index 12c945f..0000000
--- a/drivers/staging/altpciechdma/TODO
+++ /dev/null
@@ -1,15 +0,0 @@
-DONE:
-    - functionality similar to logic testbench
-
-TODO:
-	- checkpatch.pl cleanups.
-	- keep state of DMA engines.
-	- keep data structure that keeps state of each transfer.
-	- interrupt handler should iterate over outstanding descriptor tables.
-	- complete userspace cdev to read/write using the DMA engines.
-	- split off the DMA support functions in a module, re-usable by custom
-	  drivers.
-
-Please coordinate work with, and send patches to
-Leon Woestenberg <leon@sidebranch.com>
-
diff --git a/drivers/staging/altpciechdma/altpciechdma.c b/drivers/staging/altpciechdma/altpciechdma.c
deleted file mode 100644
index 2f07dd4..0000000
--- a/drivers/staging/altpciechdma/altpciechdma.c
+++ /dev/null
@@ -1,1182 +0,0 @@
-/**
- * Driver for Altera PCIe core chaining DMA reference design.
- *
- * Copyright (C) 2008 Leon Woestenberg  <leon.woestenberg@axon.tv>
- * Copyright (C) 2008 Nickolas Heppermann  <heppermannwdt@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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *
- * Rationale: This driver exercises the chaining DMA read and write engine
- * in the reference design. It is meant as a complementary reference
- * driver that can be used for testing early designs as well as a basis to
- * write your custom driver.
- *
- * Status: Test results from Leon Woestenberg  <leon.woestenberg@axon.tv>:
- *
- * Sendero Board w/ Cyclone II EP2C35F672C6N, PX1011A PCIe x1 PHY on a
- * Dell Precision 370 PC, x86, kernel 2.6.20 from Ubuntu 7.04.
- *
- * Sendero Board w/ Cyclone II EP2C35F672C6N, PX1011A PCIe x1 PHY on a
- * Freescale MPC8313E-RDB board, PowerPC, 2.6.24 w/ Freescale patches.
- *
- * Driver tests passed with PCIe Compiler 8.1. With PCIe 8.0 the DMA
- * loopback test had reproducable compare errors. I assume a change
- * in the compiler or reference design, but could not find evidence nor
- * documentation on a change or fix in that direction.
- *
- * The reference design does not have readable locations and thus a
- * dummy read, used to flush PCI posted writes, cannot be performed.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/cdev.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-
-/* by default do not build the character device interface */
-/* XXX It is non-functional yet */
-#ifndef ALTPCIECHDMA_CDEV
-#  define ALTPCIECHDMA_CDEV 0
-#endif
-
-/* build the character device interface? */
-#if ALTPCIECHDMA_CDEV
-#  define MAX_CHDMA_SIZE (8 * 1024 * 1024)
-#  include "mapper_user_to_sg.h"
-#endif
-
-/** driver name, mimicks Altera naming of the reference design */
-#define DRV_NAME "altpciechdma"
-/** number of BARs on the device */
-#define APE_BAR_NUM (6)
-/** BAR number where the RCSLAVE memory sits */
-#define APE_BAR_RCSLAVE (0)
-/** BAR number where the Descriptor Header sits */
-#define APE_BAR_HEADER (2)
-
-/** maximum size in bytes of the descriptor table, chdma logic limit */
-#define APE_CHDMA_TABLE_SIZE (4096)
-/* single transfer must not exceed 255 table entries. worst case this can be
- * achieved by 255 scattered pages, with only a single byte in the head and
- * tail pages. 253 * PAGE_SIZE is a safe upper bound for the transfer size.
- */
-#define APE_CHDMA_MAX_TRANSFER_LEN (253 * PAGE_SIZE)
-
-/**
- * Specifies those BARs to be mapped and the length of each mapping.
- *
- * Zero (0) means do not map, otherwise specifies the BAR lengths to be mapped.
- * If the actual BAR length is less, this is considered an error; then
- * reconfigure your PCIe core.
- *
- * @see ug_pci_express 8.0, table 7-2 at page 7-13.
- */
-static const unsigned long bar_min_len[APE_BAR_NUM] =
-	{ 32768, 0, 256, 0, 32768, 0 };
-
-/**
- * Descriptor Header, controls the DMA read engine or write engine.
- *
- * The descriptor header is the main data structure for starting DMA transfers.
- *
- * It sits in End Point (FPGA) memory BAR[2] for 32-bit or BAR[3:2] for 64-bit.
- * It references a descriptor table which exists in Root Complex (PC) memory.
- * Writing the rclast field starts the DMA operation, thus all other structures
- * and fields must be setup before doing so.
- *
- * @see ug_pci_express 8.0, tables 7-3, 7-4 and 7-5 at page 7-14.
- * @note This header must be written in four 32-bit (PCI DWORD) writes.
- */
-struct ape_chdma_header {
-	/**
-	 * w0 consists of two 16-bit fields:
-	 * lsb u16 number; number of descriptors in ape_chdma_table
-	 * msb u16 control; global control flags
-	 */
-	u32 w0;
-	/* bus address to ape_chdma_table in Root Complex memory */
-	u32 bdt_addr_h;
-	u32 bdt_addr_l;
-	/**
-	 * w3 consists of two 16-bit fields:
-	 * - lsb u16 rclast; last descriptor number available in Root Complex
-	 *    - zero (0) means the first descriptor is ready,
-	 *    - one (1) means two descriptors are ready, etc.
-	 * - msb u16 reserved;
-	 *
-	 * @note writing to this memory location starts the DMA operation!
-	 */
-	u32 w3;
-} __attribute__ ((packed));
-
-/**
- * Descriptor Entry, describing a (non-scattered) single memory block transfer.
- *
- * There is one descriptor for each memory block involved in the transfer, a
- * block being a contiguous address range on the bus.
- *
- * Multiple descriptors are chained by means of the ape_chdma_table data
- * structure.
- *
- * @see ug_pci_express 8.0, tables 7-6, 7-7 and 7-8 at page 7-14 and page 7-15.
- */
-struct ape_chdma_desc {
-	/**
-	 * w0 consists of two 16-bit fields:
-	 * number of DWORDS to transfer
-	 * - lsb u16 length;
-	 * global control
-	 * - msb u16 control;
-	 */
-	u32 w0;
-	/* address of memory in the End Point */
-	u32 ep_addr;
-	/* bus address of source or destination memory in the Root Complex */
-	u32 rc_addr_h;
-	u32 rc_addr_l;
-} __attribute__ ((packed));
-
-/**
- * Descriptor Table, an array of descriptors describing a chained transfer.
- *
- * An array of descriptors, preceded by workspace for the End Point.
- * It exists in Root Complex memory.
- *
- * The End Point can update its last completed descriptor number in the
- * eplast field if requested by setting the EPLAST_ENA bit either
- * globally in the header's or locally in any descriptor's control field.
- *
- * @note this structure may not exceed 4096 bytes. This results in a
- * maximum of 4096 / (4 * 4) - 1 = 255 descriptors per chained transfer.
- *
- * @see ug_pci_express 8.0, tables 7-9, 7-10 and 7-11 at page 7-17 and page 7-18.
- */
-struct ape_chdma_table {
-	/* workspace 0x00-0x0b, reserved */
-	u32 reserved1[3];
-	/* workspace 0x0c-0x0f, last descriptor handled by End Point */
-	u32 w3;
-	/* the actual array of descriptors
-    * 0x10-0x1f, 0x20-0x2f, ... 0xff0-0xfff (255 entries)
-    */
-	struct ape_chdma_desc desc[255];
-} __attribute__ ((packed));
-
-/**
- * Altera PCI Express ('ape') board specific book keeping data
- *
- * Keeps state of the PCIe core and the Chaining DMA controller
- * application.
- */
-struct ape_dev {
-	/** the kernel pci device data structure provided by probe() */
-	struct pci_dev *pci_dev;
-	/**
-	 * kernel virtual address of the mapped BAR memory and IO regions of
-	 * the End Point. Used by map_bars()/unmap_bars().
-	 */
-	void * __iomem bar[APE_BAR_NUM];
-	/** kernel virtual address for Descriptor Table in Root Complex memory */
-	struct ape_chdma_table *table_virt;
-	/**
-	 * bus address for the Descriptor Table in Root Complex memory, in
-	 * CPU-native endianess
-	 */
-	dma_addr_t table_bus;
-	/* if the device regions could not be allocated, assume and remember it
-	 * is in use by another driver; this driver must not disable the device.
-	 */
-	int in_use;
-	/* whether this driver enabled msi for the device */
-	int msi_enabled;
-	/* whether this driver could obtain the regions */
-	int got_regions;
-	/* irq line successfully requested by this driver, -1 otherwise */
-	int irq_line;
-	/* board revision */
-	u8 revision;
-	/* interrupt count, incremented by the interrupt handler */
-	int irq_count;
-#if ALTPCIECHDMA_CDEV
-	/* character device */
-	dev_t cdevno;
-	struct cdev cdev;
-	/* user space scatter gather mapper */
-	struct sg_mapping_t *sgm;
-#endif
-};
-
-/**
- * Using the subsystem vendor id and subsystem id, it is possible to
- * distinguish between different cards bases around the same
- * (third-party) logic core.
- *
- * Default Altera vendor and device ID's, and some (non-reserved)
- * ID's are now used here that are used amongst the testers/developers.
- */
-static const struct pci_device_id ids[] = {
-	{ PCI_DEVICE(0x1172, 0xE001), },
-	{ PCI_DEVICE(0x2071, 0x2071), },
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, ids);
-
-#if ALTPCIECHDMA_CDEV
-/* prototypes for character device */
-static int sg_init(struct ape_dev *ape);
-static void sg_exit(struct ape_dev *ape);
-#endif
-
-/**
- * altpciechdma_isr() - Interrupt handler
- *
- */
-static irqreturn_t altpciechdma_isr(int irq, void *dev_id)
-{
-	struct ape_dev *ape = (struct ape_dev *)dev_id;
-	if (!ape)
-		return IRQ_NONE;
-	ape->irq_count++;
-	return IRQ_HANDLED;
-}
-
-static int __devinit scan_bars(struct ape_dev *ape, struct pci_dev *dev)
-{
-	int i;
-	for (i = 0; i < APE_BAR_NUM; i++) {
-		unsigned long bar_start = pci_resource_start(dev, i);
-		if (bar_start) {
-			unsigned long bar_end = pci_resource_end(dev, i);
-			unsigned long bar_flags = pci_resource_flags(dev, i);
-			printk(KERN_DEBUG "BAR%d 0x%08lx-0x%08lx flags 0x%08lx\n",
-			  i, bar_start, bar_end, bar_flags);
-		}
-	}
-	return 0;
-}
-
-/**
- * Unmap the BAR regions that had been mapped earlier using map_bars()
- */
-static void unmap_bars(struct ape_dev *ape, struct pci_dev *dev)
-{
-	int i;
-	for (i = 0; i < APE_BAR_NUM; i++) {
-	  /* is this BAR mapped? */
-		if (ape->bar[i]) {
-			/* unmap BAR */
-			pci_iounmap(dev, ape->bar[i]);
-			ape->bar[i] = NULL;
-		}
-	}
-}
-
-/**
- * Map the device memory regions into kernel virtual address space after
- * verifying their sizes respect the minimum sizes needed, given by the
- * bar_min_len[] array.
- */
-static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev)
-{
-	int rc;
-	int i;
-	/* iterate through all the BARs */
-	for (i = 0; i < APE_BAR_NUM; i++) {
-		unsigned long bar_start = pci_resource_start(dev, i);
-		unsigned long bar_end = pci_resource_end(dev, i);
-		unsigned long bar_length = bar_end - bar_start + 1;
-		ape->bar[i] = NULL;
-		/* do not map, and skip, BARs with length 0 */
-		if (!bar_min_len[i])
-			continue;
-		/* do not map BARs with address 0 */
-		if (!bar_start || !bar_end) {
-			printk(KERN_DEBUG "BAR #%d is not present?!\n", i);
-			rc = -1;
-			goto fail;
-		}
-		bar_length = bar_end - bar_start + 1;
-		/* BAR length is less than driver requires? */
-		if (bar_length < bar_min_len[i]) {
-			printk(KERN_DEBUG "BAR #%d length = %lu bytes but driver "
-			"requires at least %lu bytes\n",
-			i, bar_length, bar_min_len[i]);
-			rc = -1;
-			goto fail;
-		}
-		/* map the device memory or IO region into kernel virtual
-		 * address space */
-		ape->bar[i] = pci_iomap(dev, i, bar_min_len[i]);
-		if (!ape->bar[i]) {
-			printk(KERN_DEBUG "Could not map BAR #%d.\n", i);
-			rc = -1;
-			goto fail;
-		}
-		printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i,
-		ape->bar[i], bar_min_len[i], bar_length);
-	}
-	/* successfully mapped all required BAR regions */
-	rc = 0;
-	goto success;
-fail:
-	/* unmap any BARs that we did map */
-	unmap_bars(ape, dev);
-success:
-	return rc;
-}
-
-#if 0 /* not yet implemented fully FIXME add opcode */
-static void __devinit rcslave_test(struct ape_dev *ape, struct pci_dev *dev)
-{
-	u32 *rcslave_mem = (u32 *)ape->bar[APE_BAR_RCSLAVE];
-	u32 result = 0;
-	/** this number is assumed to be different each time this test runs */
-	u32 seed = (u32)jiffies;
-	u32 value = seed;
-	int i;
-
-	/* write loop */
-	value = seed;
-	for (i = 1024; i < 32768 / 4 ; i++) {
-		printk(KERN_DEBUG "Writing 0x%08x to 0x%p.\n",
-			(u32)value, (void *)rcslave_mem + i);
-		iowrite32(value, rcslave_mem + i);
-		value++;
-	}
-	/* read-back loop */
-	value = seed;
-	for (i = 1024; i < 32768 / 4; i++) {
-		result = ioread32(rcslave_mem + i);
-		if (result != value) {
-			printk(KERN_DEBUG "Wrote 0x%08x to 0x%p, but read back 0x%08x.\n",
-				(u32)value, (void *)rcslave_mem + i, (u32)result);
-			break;
-		}
-		value++;
-	}
-}
-#endif
-
-/* obtain the 32 most significant (high) bits of a 32-bit or 64-bit address */
-#define pci_dma_h(addr) ((addr >> 16) >> 16)
-/* obtain the 32 least significant (low) bits of a 32-bit or 64-bit address */
-#define pci_dma_l(addr) (addr & 0xffffffffUL)
-
-/* ape_fill_chdma_desc() - Fill a Altera PCI Express Chaining DMA descriptor
- *
- * @desc pointer to descriptor to be filled
- * @addr root complex address
- * @ep_addr end point address
- * @len number of bytes, must be a multiple of 4.
- */
-static inline void ape_chdma_desc_set(struct ape_chdma_desc *desc, dma_addr_t addr, u32 ep_addr, int len)
-{
-  BUG_ON(len & 3);
-	desc->w0 = cpu_to_le32(len / 4);
-	desc->ep_addr = cpu_to_le32(ep_addr);
-	desc->rc_addr_h = cpu_to_le32(pci_dma_h(addr));
-	desc->rc_addr_l = cpu_to_le32(pci_dma_l(addr));
-}
-
-#if ALTPCIECHDMA_CDEV
-/*
- * ape_sg_to_chdma_table() - Create a device descriptor table from a scatterlist.
- *
- * The scatterlist must have been mapped by pci_map_sg(sgm->sgl).
- *
- * @sgl scatterlist.
- * @nents Number of entries in the scatterlist.
- * @first Start index in the scatterlist sgm->sgl.
- * @ep_addr End Point address for the scatter/gather transfer.
- * @desc pointer to first descriptor
- *
- * Returns Number of entries in the table on success, -1 on error.
- */
-static int ape_sg_to_chdma_table(struct scatterlist *sgl, int nents, int first, struct ape_chdma_desc *desc, u32 ep_addr)
-{
-	int i = first, j = 0;
-	/* inspect first entry */
-	dma_addr_t addr = sg_dma_address(&sgl[i]);
-	unsigned int len = sg_dma_len(&sgl[i]);
-	/* contiguous block */
-	dma_addr_t cont_addr = addr;
-	unsigned int cont_len = len;
-	/* iterate over remaining entries */
-	for (; j < 25 && i < nents - 1; i++) {
-		/* bus address of next entry i + 1 */
-		dma_addr_t next = sg_dma_address(&sgl[i + 1]);
-		/* length of this entry i */
-		len = sg_dma_len(&sgl[i]);
-		printk(KERN_DEBUG "%04d: addr=0x%Lx length=0x%08x\n", i,
-			(unsigned long long)addr, len);
-		/* entry i + 1 is non-contiguous with entry i? */
-		if (next != addr + len) {
-			/* TODO create entry here (we could overwrite i) */
-			printk(KERN_DEBUG "%4d: cont_addr=0x%Lx cont_len=0x%08x\n", j,
-				(unsigned long long)cont_addr, cont_len);
-			/* set descriptor for contiguous transfer */
-			ape_chdma_desc_set(&desc[j], cont_addr, ep_addr, cont_len);
-			/* next end point memory address */
-			ep_addr += cont_len;
-			/* start new contiguous block */
-			cont_addr = next;
-			cont_len = 0;
-			j++;
-		}
-		/* add entry i + 1 to current contiguous block */
-		cont_len += len;
-		/* goto entry i + 1 */
-		addr = next;
-	}
-	/* TODO create entry here  (we could overwrite i) */
-	printk(KERN_DEBUG "%04d: addr=0x%Lx length=0x%08x\n", i,
-		(unsigned long long)addr, len);
-	printk(KERN_DEBUG "%4d: cont_addr=0x%Lx length=0x%08x\n", j,
-		(unsigned long long)cont_addr, cont_len);
-	j++;
-	return j;
-}
-#endif
-
-/* compare buffers */
-static inline int compare(u32 *p, u32 *q, int len)
-{
-	int result = -1;
-	int fail = 0;
-	int i;
-	for (i = 0; i < len / 4; i++) {
-		if (*p == *q) {
-			/* every so many u32 words, show equals */
-			if ((i & 255) == 0)
-				printk(KERN_DEBUG "[%p] = 0x%08x    [%p] = 0x%08x\n", p, *p, q, *q);
-		} else {
-			fail++;
-			/* show the first few miscompares */
-			if (fail < 10)
-				printk(KERN_DEBUG "[%p] = 0x%08x != [%p] = 0x%08x ?!\n", p, *p, q, *q);
-				/* but stop after a while */
-			else if (fail == 10)
-				printk(KERN_DEBUG "---more errors follow! not printed---\n");
-			else
-				/* stop compare after this many errors */
-			break;
-		}
-		p++;
-		q++;
-	}
-	if (!fail)
-		result = 0;
-	return result;
-}
-
-/* dma_test() - Perform DMA loop back test to end point and back to root complex.
- *
- * Allocate a cache-coherent buffer in host memory, consisting of four pages.
- *
- * Fill the four memory pages such that each 32-bit word contains its own address.
- *
- * Now perform a loop back test, have the end point device copy the first buffer
- * half to end point memory, then have it copy back into the second half.
- *
- *   Create a descriptor table to copy the first buffer half into End Point
- *   memory. Instruct the End Point to do a DMA read using that table.
- *
- *   Create a descriptor table to copy End Point memory to the second buffer
- *   half. Instruct the End Point to do a DMA write using that table.
- *
- * Compare results, fail or pass.
- *
- */
-static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
-{
-	/* test result; guilty until proven innocent */
-	int result = -1;
-	/* the DMA read header sits at address 0x00 of the DMA engine BAR */
-	struct ape_chdma_header *write_header = (struct ape_chdma_header *)ape->bar[APE_BAR_HEADER];
-	/* the write DMA header sits after the read header at address 0x10 */
-	struct ape_chdma_header *read_header = write_header + 1;
-	/* virtual address of the allocated buffer */
-	u8 *buffer_virt = 0;
-	/* bus address of the allocated buffer */
-	dma_addr_t buffer_bus = 0;
-	int i, n = 0, irq_count;
-
-	/* temporary value used to construct 32-bit data words */
-	u32 w;
-
-	printk(KERN_DEBUG "bar_tests(), PAGE_SIZE = 0x%0x\n", (int)PAGE_SIZE);
-	printk(KERN_DEBUG "write_header = 0x%p.\n", write_header);
-	printk(KERN_DEBUG "read_header = 0x%p.\n", read_header);
-	printk(KERN_DEBUG "&write_header->w3 = 0x%p\n", &write_header->w3);
-	printk(KERN_DEBUG "&read_header->w3 = 0x%p\n", &read_header->w3);
-	printk(KERN_DEBUG "ape->table_virt = 0x%p.\n", ape->table_virt);
-
-	if (!write_header || !read_header || !ape->table_virt)
-		goto fail;
-
-	/* allocate and map coherently-cached memory for a DMA-able buffer */
-	/* @see Documentation/PCI/PCI-DMA-mapping.txt, near line 318 */
-	buffer_virt = (u8 *)pci_alloc_consistent(dev, PAGE_SIZE * 4, &buffer_bus);
-	if (!buffer_virt) {
-		printk(KERN_DEBUG "Could not allocate coherent DMA buffer.\n");
-		goto fail;
-	}
-	printk(KERN_DEBUG "Allocated cache-coherent DMA buffer (virtual address = %p, bus address = 0x%016llx).\n",
-	       buffer_virt, (u64)buffer_bus);
-
-	/* fill first half of buffer with its virtual address as data */
-	for (i = 0; i < 4 * PAGE_SIZE; i += 4)
-#if 0
-		*(u32 *)(buffer_virt + i) = i / PAGE_SIZE + 1;
-#else
-		*(u32 *)(buffer_virt + i) = (u32)(unsigned long)(buffer_virt + i);
-#endif
-#if 0
-  compare((u32 *)buffer_virt, (u32 *)(buffer_virt + 2 * PAGE_SIZE), 8192);
-#endif
-
-#if 0
-	/* fill second half of buffer with zeroes */
-	for (i = 2 * PAGE_SIZE; i < 4 * PAGE_SIZE; i += 4)
-		*(u32 *)(buffer_virt + i) = 0;
-#endif
-
-	/* invalidate EPLAST, outside 0-255, 0xFADE is from the testbench */
-	ape->table_virt->w3 = cpu_to_le32(0x0000FADE);
-
-	/* fill in first descriptor */
-	n = 0;
-	/* read 8192 bytes from RC buffer to EP address 4096 */
-	ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus, 4096, 2 * PAGE_SIZE);
-#if 1
-	for (i = 0; i < 255; i++)
-		ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus, 4096, 2 * PAGE_SIZE);
-	/* index of last descriptor */
-	n = i - 1;
-#endif
-#if 0
-	/* fill in next descriptor */
-	n++;
-	/* read 1024 bytes from RC buffer to EP address 4096 + 1024 */
-	ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 1024, 4096 + 1024, 1024);
-#endif
-
-#if 1
-	/* enable MSI after the last descriptor is completed */
-	if (ape->msi_enabled)
-		ape->table_virt->desc[n].w0 |= cpu_to_le32(1UL << 16)/*local MSI*/;
-#endif
-#if 0
-	/* dump descriptor table for debugging */
-	printk(KERN_DEBUG "Descriptor Table (Read, in Root Complex Memory, # = %d)\n", n + 1);
-	for (i = 0; i < 4 + (n + 1) * 4; i += 4) {
-		u32 *p = (u32 *)ape->table_virt;
-		p += i;
-		printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (LEN=0x%x)\n", (u32)p, (u32)p & 15, *p, 4 * le32_to_cpu(*p));
-		p++;
-		printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (EPA=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-		p++;
-		printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCH=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-		p++;
-		printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCL=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-	}
-#endif
-	/* set available number of descriptors in table */
-	w = (u32)(n + 1);
-	w |= (1UL << 18)/*global EPLAST_EN*/;
-#if 0
-	if (ape->msi_enabled)
-		w |= (1UL << 17)/*global MSI*/;
-#endif
-	printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", w, (void *)&read_header->w0);
-	iowrite32(w, &read_header->w0);
-
-	/* write table address (higher 32-bits) */
-	printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)((ape->table_bus >> 16) >> 16), (void *)&read_header->bdt_addr_h);
-	iowrite32(pci_dma_h(ape->table_bus), &read_header->bdt_addr_h);
-
-	/* write table address (lower 32-bits) */
-	printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)(ape->table_bus & 0xffffffffUL), (void *)&read_header->bdt_addr_l);
-	iowrite32(pci_dma_l(ape->table_bus), &read_header->bdt_addr_l);
-
-	/* memory write barrier */
-	wmb();
-	printk(KERN_DEBUG "Flush posted writes\n");
-	/** FIXME Add dummy read to flush posted writes but need a readable location! */
-#if 0
-	(void)ioread32();
-#endif
-
-	/* remember IRQ count before the transfer */
-	irq_count = ape->irq_count;
-	/* write number of descriptors - this starts the DMA */
-	printk(KERN_DEBUG "\nStart DMA read\n");
-	printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)n, (void *)&read_header->w3);
-	iowrite32(n, &read_header->w3);
-	printk(KERN_DEBUG "EPLAST = %lu\n", le32_to_cpu(*(u32 *)&ape->table_virt->w3) & 0xffffUL);
-
-	/** memory write barrier */
-	wmb();
-	/* dummy read to flush posted writes */
-	/* FIXME Need a readable location! */
-#if 0
-	(void)ioread32();
-#endif
-	printk(KERN_DEBUG "POLL FOR READ:\n");
-	/* poll for chain completion, 1000 times 1 millisecond */
-	for (i = 0; i < 100; i++) {
-		volatile u32 *p = &ape->table_virt->w3;
-		u32 eplast = le32_to_cpu(*p) & 0xffffUL;
-		printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n);
-		if (eplast == n) {
-			printk(KERN_DEBUG "DONE\n");
-			/* print IRQ count before the transfer */
-			printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count);
-			break;
-		}
-		udelay(100);
-	}
-
-	/* invalidate EPLAST, outside 0-255, 0xFADE is from the testbench */
-	ape->table_virt->w3 = cpu_to_le32(0x0000FADE);
-
-	/* setup first descriptor */
-	n = 0;
-	ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
-#if 1
-	for (i = 0; i < 255; i++)
-		ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
-
-	/* index of last descriptor */
-	n = i - 1;
-#endif
-#if 1 /* test variable, make a module option later */
-	if (ape->msi_enabled)
-		ape->table_virt->desc[n].w0 |= cpu_to_le32(1UL << 16)/*local MSI*/;
-#endif
-#if 0
-	/* dump descriptor table for debugging */
-	printk(KERN_DEBUG "Descriptor Table (Write, in Root Complex Memory, # = %d)\n", n + 1);
-	for (i = 0; i < 4 + (n + 1) * 4; i += 4) {
-		u32 *p = (u32 *)ape->table_virt;
-		p += i;
-		printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (LEN=0x%x)\n", (u32)p, (u32)p & 15, *p, 4 * le32_to_cpu(*p));
-		p++;
-		printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (EPA=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-		p++;
-		printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCH=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-		p++;
-		printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCL=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
-	}
-#endif
-
-	/* set number of available descriptors in the table */
-	w = (u32)(n + 1);
-	/* enable updates of eplast for each descriptor completion */
-	w |= (u32)(1UL << 18)/*global EPLAST_EN*/;
-#if 0   /* test variable, make a module option later */
-	/* enable MSI for each descriptor completion */
-	if (ape->msi_enabled)
-		w |= (1UL << 17)/*global MSI*/;
-#endif
-	iowrite32(w, &write_header->w0);
-	iowrite32(pci_dma_h(ape->table_bus), &write_header->bdt_addr_h);
-	iowrite32(pci_dma_l(ape->table_bus), &write_header->bdt_addr_l);
-
-	/** memory write barrier and flush posted writes */
-	wmb();
-	/* dummy read to flush posted writes */
-	/* FIXME Need a readable location! */
-#if 0
-	(void)ioread32();
-#endif
-	irq_count = ape->irq_count;
-
-	printk(KERN_DEBUG "\nStart DMA write\n");
-	iowrite32(n, &write_header->w3);
-
-	/** memory write barrier */
-	wmb();
-	/** dummy read to flush posted writes */
-	/* (void) ioread32(); */
-
-	printk(KERN_DEBUG "POLL FOR WRITE:\n");
-	/* poll for completion, 1000 times 1 millisecond */
-	for (i = 0; i < 100; i++) {
-		volatile u32 *p = &ape->table_virt->w3;
-		u32 eplast = le32_to_cpu(*p) & 0xffffUL;
-		printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n);
-		if (eplast == n) {
-			printk(KERN_DEBUG "DONE\n");
-			/* print IRQ count before the transfer */
-			printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count);
-			break;
-		}
-		udelay(100);
-	}
-	/* soft-reset DMA write engine */
-	iowrite32(0x0000ffffUL, &write_header->w0);
-	/* soft-reset DMA read engine */
-	iowrite32(0x0000ffffUL, &read_header->w0);
-
-	/** memory write barrier */
-	wmb();
-	/* dummy read to flush posted writes */
-	/* FIXME Need a readable location! */
-#if 0
-	(void)ioread32();
-#endif
-	/* compare first half of buffer with second half, should be identical */
-	result = compare((u32 *)buffer_virt, (u32 *)(buffer_virt + 2 * PAGE_SIZE), 8192);
-	printk(KERN_DEBUG "DMA loop back test %s.\n", result ? "FAILED" : "PASSED");
-
-	pci_free_consistent(dev, 4 * PAGE_SIZE, buffer_virt, buffer_bus);
-fail:
-	printk(KERN_DEBUG "bar_tests() end, result %d\n", result);
-	return result;
-}
-
-/* Called when the PCI sub system thinks we can control the given device.
- * Inspect if we can support the device and if so take control of it.
- *
- * Return 0 when we have taken control of the given device.
- *
- * - allocate board specific bookkeeping
- * - allocate coherently-mapped memory for the descriptor table
- * - enable the board
- * - verify board revision
- * - request regions
- * - query DMA mask
- * - obtain and request irq
- * - map regions into kernel address space
- */
-static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-	int rc = 0;
-	struct ape_dev *ape = NULL;
-	u8 irq_pin, irq_line;
-	printk(KERN_DEBUG "probe(dev = 0x%p, pciid = 0x%p)\n", dev, id);
-
-	/* allocate memory for per-board book keeping */
-	ape = kzalloc(sizeof(struct ape_dev), GFP_KERNEL);
-	if (!ape) {
-		printk(KERN_DEBUG "Could not kzalloc()ate memory.\n");
-		goto err_ape;
-	}
-	ape->pci_dev = dev;
-	dev_set_drvdata(&dev->dev, ape);
-	printk(KERN_DEBUG "probe() ape = 0x%p\n", ape);
-
-	printk(KERN_DEBUG "sizeof(struct ape_chdma_table) = %d.\n",
-		(int)sizeof(struct ape_chdma_table));
-	/* the reference design has a size restriction on the table size */
-	BUG_ON(sizeof(struct ape_chdma_table) > APE_CHDMA_TABLE_SIZE);
-
-	/* allocate and map coherently-cached memory for a descriptor table */
-	/* @see LDD3 page 446 */
-	ape->table_virt = (struct ape_chdma_table *)pci_alloc_consistent(dev,
-		APE_CHDMA_TABLE_SIZE, &ape->table_bus);
-	/* could not allocate table? */
-	if (!ape->table_virt) {
-		printk(KERN_DEBUG "Could not dma_alloc()ate_coherent memory.\n");
-		goto err_table;
-	}
-
-	printk(KERN_DEBUG "table_virt = %p, table_bus = 0x%16llx.\n",
-		ape->table_virt, (u64)ape->table_bus);
-
-	/* enable device */
-	rc = pci_enable_device(dev);
-	if (rc) {
-		printk(KERN_DEBUG "pci_enable_device() failed\n");
-		goto err_enable;
-	}
-
-	/* enable bus master capability on device */
-	pci_set_master(dev);
-	/* enable message signaled interrupts */
-	rc = pci_enable_msi(dev);
-	/* could not use MSI? */
-	if (rc) {
-		/* resort to legacy interrupts */
-		printk(KERN_DEBUG "Could not enable MSI interrupting.\n");
-		ape->msi_enabled = 0;
-	/* MSI enabled, remember for cleanup */
-	} else {
-		printk(KERN_DEBUG "Enabled MSI interrupting.\n");
-		ape->msi_enabled = 1;
-	}
-
-	pci_read_config_byte(dev, PCI_REVISION_ID, &ape->revision);
-#if 0 /* example */
-	/* (for example) this driver does not support revision 0x42 */
-    if (ape->revision == 0x42) {
-		printk(KERN_DEBUG "Revision 0x42 is not supported by this driver.\n");
-		rc = -ENODEV;
-		goto err_rev;
-	}
-#endif
-	/** XXX check for native or legacy PCIe endpoint? */
-
-	rc = pci_request_regions(dev, DRV_NAME);
-	/* could not request all regions? */
-	if (rc) {
-		/* assume device is in use (and do not disable it later!) */
-		ape->in_use = 1;
-		goto err_regions;
-	}
-	ape->got_regions = 1;
-
-#if 1   /* @todo For now, disable 64-bit, because I do not understand the implications (DAC!) */
-	/* query for DMA transfer */
-	/* @see Documentation/PCI/PCI-DMA-mapping.txt */
-	if (!pci_set_dma_mask(dev, DMA_BIT_MASK(64))) {
-		pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64));
-		/* use 64-bit DMA */
-		printk(KERN_DEBUG "Using a 64-bit DMA mask.\n");
-	} else
-#endif
-	if (!pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
-		printk(KERN_DEBUG "Could not set 64-bit DMA mask.\n");
-		pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(32));
-		/* use 32-bit DMA */
-		printk(KERN_DEBUG "Using a 32-bit DMA mask.\n");
-	} else {
-		printk(KERN_DEBUG "No suitable DMA possible.\n");
-		/** @todo Choose proper error return code */
-		rc = -1;
-		goto err_mask;
-	}
-
-	rc = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
-	/* could not read? */
-	if (rc)
-		goto err_irq;
-	printk(KERN_DEBUG "IRQ pin #%d (0=none, 1=INTA#...4=INTD#).\n", irq_pin);
-
-	/* @see LDD3, page 318 */
-	rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq_line);
-	/* could not read? */
-	if (rc) {
-		printk(KERN_DEBUG "Could not query PCI_INTERRUPT_LINE, error %d\n", rc);
-		goto err_irq;
-	}
-	printk(KERN_DEBUG "IRQ line #%d.\n", irq_line);
-#if 1
-	irq_line = dev->irq;
-	/* @see LDD3, page 259 */
-	rc = request_irq(irq_line, altpciechdma_isr, IRQF_SHARED, DRV_NAME, (void *)ape);
-	if (rc) {
-		printk(KERN_DEBUG "Could not request IRQ #%d, error %d\n", irq_line, rc);
-		ape->irq_line = -1;
-		goto err_irq;
-	}
-	/* remember which irq we allocated */
-	ape->irq_line = (int)irq_line;
-	printk(KERN_DEBUG "Succesfully requested IRQ #%d with dev_id 0x%p\n", irq_line, ape);
-#endif
-	/* show BARs */
-	scan_bars(ape, dev);
-	/* map BARs */
-	rc = map_bars(ape, dev);
-	if (rc)
-		goto err_map;
-#if ALTPCIECHDMA_CDEV
-	/* initialize character device */
-	rc = sg_init(ape);
-	if (rc)
-		goto err_cdev;
-#endif
-	/* perform DMA engines loop back test */
-	rc = dma_test(ape, dev);
-	(void)rc;
-	/* successfully took the device */
-	rc = 0;
-	printk(KERN_DEBUG "probe() successful.\n");
-	goto end;
-#if ALTPCIECHDMA_CDEV
-err_cdev:
-	/* unmap the BARs */
-	unmap_bars(ape, dev);
-#endif
-err_map:
-	/* free allocated irq */
-	if (ape->irq_line >= 0)
-		free_irq(ape->irq_line, (void *)ape);
-err_irq:
-	if (ape->msi_enabled)
-		pci_disable_msi(dev);
-	/* disable the device iff it is not in use */
-	if (!ape->in_use)
-		pci_disable_device(dev);
-	if (ape->got_regions)
-		pci_release_regions(dev);
-err_mask:
-err_regions:
-/*err_rev:*/
-/* clean up everything before device enable() */
-err_enable:
-	if (ape->table_virt)
-		pci_free_consistent(dev, APE_CHDMA_TABLE_SIZE, ape->table_virt, ape->table_bus);
-/* clean up everything before allocating descriptor table */
-err_table:
-	if (ape)
-		kfree(ape);
-err_ape:
-end:
-	return rc;
-}
-
-static void __devexit remove(struct pci_dev *dev)
-{
-	struct ape_dev *ape = dev_get_drvdata(&dev->dev);
-
-	printk(KERN_DEBUG "remove(0x%p)\n", dev);
-	printk(KERN_DEBUG "remove(dev = 0x%p) where ape = 0x%p\n", dev, ape);
-
-	/* remove character device */
-#if ALTPCIECHDMA_CDEV
-	sg_exit(ape);
-#endif
-
-	if (ape->table_virt)
-		pci_free_consistent(dev, APE_CHDMA_TABLE_SIZE, ape->table_virt, ape->table_bus);
-
-	/* free IRQ
-	 * @see LDD3 page 279
-	 */
-	if (ape->irq_line >= 0) {
-		printk(KERN_DEBUG "Freeing IRQ #%d for dev_id 0x%08lx.\n",
-		ape->irq_line, (unsigned long)ape);
-		free_irq(ape->irq_line, (void *)ape);
-	}
-	/* MSI was enabled? */
-	if (ape->msi_enabled) {
-		/* Disable MSI @see Documentation/MSI-HOWTO.txt */
-		pci_disable_msi(dev);
-		ape->msi_enabled = 0;
-	}
-	/* unmap the BARs */
-	unmap_bars(ape, dev);
-	if (!ape->in_use)
-		pci_disable_device(dev);
-	if (ape->got_regions)
-		/* to be called after device disable */
-		pci_release_regions(dev);
-}
-
-#if ALTPCIECHDMA_CDEV
-
-/*
- * Called when the device goes from unused to used.
- */
-static int sg_open(struct inode *inode, struct file *file)
-{
-	struct ape_dev *ape;
-	printk(KERN_DEBUG DRV_NAME "_open()\n");
-	/* pointer to containing data structure of the character device inode */
-	ape = container_of(inode->i_cdev, struct ape_dev, cdev);
-	/* create a reference to our device state in the opened file */
-	file->private_data = ape;
-	/* create virtual memory mapper */
-	ape->sgm = sg_create_mapper(MAX_CHDMA_SIZE);
-	return 0;
-}
-
-/*
- * Called when the device goes from used to unused.
- */
-static int sg_close(struct inode *inode, struct file *file)
-{
-	/* fetch device specific data stored earlier during open */
-	struct ape_dev *ape = (struct ape_dev *)file->private_data;
-	printk(KERN_DEBUG DRV_NAME "_close()\n");
-	/* destroy virtual memory mapper */
-	sg_destroy_mapper(ape->sgm);
-	return 0;
-}
-
-static ssize_t sg_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
-{
-	/* fetch device specific data stored earlier during open */
-	struct ape_dev *ape = (struct ape_dev *)file->private_data;
-	(void)ape;
-	printk(KERN_DEBUG DRV_NAME "_read(buf=0x%p, count=%lld, pos=%llu)\n", buf, (s64)count, (u64)*pos);
-	return count;
-}
-
-/* sg_write() - Write to the device
- *
- * @buf userspace buffer
- * @count number of bytes in the userspace buffer
- *
- * Iterate over the userspace buffer, taking at most 255 * PAGE_SIZE bytes for
- * each DMA transfer.
- *   For each transfer, get the user pages, build a sglist, map, build a
- *   descriptor table. submit the transfer. wait for the interrupt handler
- *   to wake us on completion.
- */
-static ssize_t sg_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
-{
-	int hwnents, tents;
-	size_t transfer_len, remaining = count, done = 0;
-	u64 transfer_addr = (u64)buf;
-	/* fetch device specific data stored earlier during open */
-	struct ape_dev *ape = (struct ape_dev *)file->private_data;
-	printk(KERN_DEBUG DRV_NAME "_write(buf=0x%p, count=%lld, pos=%llu)\n",
-		buf, (s64)count, (u64)*pos);
-	/* TODO transfer boundaries at PAGE_SIZE granularity */
-	while (remaining > 0) {
-		/* limit DMA transfer size */
-		transfer_len = (remaining < APE_CHDMA_MAX_TRANSFER_LEN) ? remaining :
-			APE_CHDMA_MAX_TRANSFER_LEN;
-		/* get all user space buffer pages and create a scattergather list */
-		sgm_map_user_pages(ape->sgm, transfer_addr, transfer_len, 0/*read from userspace*/);
-		printk(KERN_DEBUG DRV_NAME "mapped_pages=%d\n", ape->sgm->mapped_pages);
-		/* map all entries in the scattergather list */
-		hwnents = pci_map_sg(ape->pci_dev, ape->sgm->sgl, ape->sgm->mapped_pages, DMA_TO_DEVICE);
-		printk(KERN_DEBUG DRV_NAME "hwnents=%d\n", hwnents);
-		/* build device descriptor tables and submit them to the DMA engine */
-		tents = ape_sg_to_chdma_table(ape->sgm->sgl, hwnents, 0, &ape->table_virt->desc[0], 4096);
-		printk(KERN_DEBUG DRV_NAME "tents=%d\n", hwnents);
-#if 0
-		while (tables) {
-			/* TODO build table */
-			/* TODO submit table to the device */
-			/* if engine stopped and unfinished work then start engine */
-		}
-		put ourselves on wait queue
-#endif
-
-		dma_unmap_sg(NULL, ape->sgm->sgl, ape->sgm->mapped_pages, DMA_TO_DEVICE);
-		/* dirty and free the pages */
-		sgm_unmap_user_pages(ape->sgm, 1/*dirtied*/);
-		/* book keeping */
-		transfer_addr += transfer_len;
-		remaining -= transfer_len;
-		done += transfer_len;
-	}
-	return done;
-}
-
-/*
- * character device file operations
- */
-static const struct file_operations sg_fops = {
-	.owner = THIS_MODULE,
-	.open = sg_open,
-	.release = sg_close,
-	.read = sg_read,
-	.write = sg_write,
-};
-
-/* sg_init() - Initialize character device
- *
- * XXX Should ideally be tied to the device, on device probe, not module init.
- */
-static int sg_init(struct ape_dev *ape)
-{
-	int rc;
-	printk(KERN_DEBUG DRV_NAME " sg_init()\n");
-	/* allocate a dynamically allocated character device node */
-	rc = alloc_chrdev_region(&ape->cdevno, 0/*requested minor*/, 1/*count*/, DRV_NAME);
-	/* allocation failed? */
-	if (rc < 0) {
-		printk("alloc_chrdev_region() = %d\n", rc);
-		goto fail_alloc;
-	}
-	/* couple the device file operations to the character device */
-	cdev_init(&ape->cdev, &sg_fops);
-	ape->cdev.owner = THIS_MODULE;
-	/* bring character device live */
-	rc = cdev_add(&ape->cdev, ape->cdevno, 1/*count*/);
-	if (rc < 0) {
-		printk("cdev_add() = %d\n", rc);
-		goto fail_add;
-	}
-	printk(KERN_DEBUG "altpciechdma = %d:%d\n", MAJOR(ape->cdevno), MINOR(ape->cdevno));
-	return 0;
-fail_add:
-	/* free the dynamically allocated character device node */
-    unregister_chrdev_region(ape->cdevno, 1/*count*/);
-fail_alloc:
-	return -1;
-}
-
-/* sg_exit() - Cleanup character device
- *
- * XXX Should ideally be tied to the device, on device remove, not module exit.
- */
-
-static void sg_exit(struct ape_dev *ape)
-{
-	printk(KERN_DEBUG DRV_NAME " sg_exit()\n");
-	/* remove the character device */
-	cdev_del(&ape->cdev);
-	/* free the dynamically allocated character device node */
-	unregister_chrdev_region(ape->cdevno, 1/*count*/);
-}
-
-#endif /* ALTPCIECHDMA_CDEV */
-
-/* used to register the driver with the PCI kernel sub system
- * @see LDD3 page 311
- */
-static struct pci_driver pci_driver = {
-	.name = DRV_NAME,
-	.id_table = ids,
-	.probe = probe,
-	.remove = __devexit_p(remove),
-	/* resume, suspend are optional */
-};
-
-/**
- * alterapciechdma_init() - Module initialization, registers devices.
- */
-static int __init alterapciechdma_init(void)
-{
-	int rc = 0;
-	printk(KERN_DEBUG DRV_NAME " init(), built at " __DATE__ " " __TIME__ "\n");
-	/* register this driver with the PCI bus driver */
-	rc = pci_register_driver(&pci_driver);
-	if (rc < 0)
-		return rc;
-	return 0;
-}
-
-/**
- * alterapciechdma_init() - Module cleanup, unregisters devices.
- */
-static void __exit alterapciechdma_exit(void)
-{
-	printk(KERN_DEBUG DRV_NAME " exit(), built at " __DATE__ " " __TIME__ "\n");
-	/* unregister this driver from the PCI bus driver */
-	pci_unregister_driver(&pci_driver);
-}
-
-MODULE_LICENSE("GPL");
-
-module_init(alterapciechdma_init);
-module_exit(alterapciechdma_exit);
-
diff --git a/drivers/staging/arlan/Makefile b/drivers/staging/arlan/Makefile
index 9e58e5f..5a84d44 100644
--- a/drivers/staging/arlan/Makefile
+++ b/drivers/staging/arlan/Makefile
@@ -1,3 +1,3 @@
-obj-$(CONFIG_ARLAN) += arlan.o 
+obj-$(CONFIG_ARLAN) += arlan.o
 
 arlan-objs := arlan-main.o arlan-proc.o
diff --git a/drivers/staging/arlan/arlan.h b/drivers/staging/arlan/arlan.h
index fb3ad51..ffcd3ea 100644
--- a/drivers/staging/arlan/arlan.h
+++ b/drivers/staging/arlan/arlan.h
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1997 Cullen Jennings
- *  Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500	
+ *  Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500
  *  GNU General Public License applies
  */
 
@@ -20,14 +20,14 @@
 #include <linux/init.h>
 #include <linux/bitops.h>
 #include <asm/system.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 
 
-//#define ARLAN_DEBUGGING 1
+/* #define ARLAN_DEBUGGING 1 */
 
 #define ARLAN_PROC_INTERFACE
 #define MAX_ARLANS 4 /* not more than 4 ! */
@@ -51,8 +51,8 @@
 extern int	arlan_entry_debug;
 extern int	arlan_exit_debug;
 extern int	testMemory;
-extern int     arlan_command(struct net_device * dev, int command);
- 
+extern int     arlan_command(struct net_device *dev, int command);
+
 #define SIDUNKNOWN -1
 #define radioNodeIdUNKNOWN -1
 #define irqUNKNOWN 0
@@ -65,22 +65,21 @@
 #define registrationModeUNKNOWN -1
 
 
-#define IFDEBUG( L ) if ( (L) & arlan_debug ) 
-#define ARLAN_FAKE_HDR_LEN 12 
+#define IFDEBUG(L) if ((L) & arlan_debug)
+#define ARLAN_FAKE_HDR_LEN 12
 
 #ifdef ARLAN_DEBUGGING
 	#define DEBUG 1
 	#define ARLAN_ENTRY_EXIT_DEBUGGING 1
-	#define ARLAN_DEBUG(a,b) printk(KERN_DEBUG a, b)
+	#define ARLAN_DEBUG(a, b) printk(KERN_DEBUG a, b)
 #else
-	#define ARLAN_DEBUG(a,b) 
+	#define ARLAN_DEBUG(a, b)
 #endif
 
 #define ARLAN_SHMEM_SIZE	0x2000
 
-struct arlan_shmem
-{
-      /* Header Signature */ 
+struct arlan_shmem {
+      /* Header Signature */
       volatile	char textRegion[48];
       volatile	u_char resetFlag;
       volatile	u_char  diagnosticInfo;
@@ -91,10 +90,10 @@
       volatile	u_char hardwareType;
       volatile	u_char majorHardwareVersion;
       volatile	u_char minorHardwareVersion;
-      volatile	u_char radioModule;// shows EEPROM, can be overridden at 0x111
-      volatile	u_char defaultChannelSet; // shows EEProm, can be overriiden at 0x10A
+      volatile	u_char radioModule;/* shows EEPROM, can be overridden at 0x111 */
+      volatile	u_char defaultChannelSet; /* shows EEProm, can be overriiden at 0x10A */
       volatile	u_char _2[47];
-      
+
       /* Control/Status Block - 0x0080 */
       volatile	u_char interruptInProgress; /* not used by lancpu */
       volatile	u_char cntrlRegImage; /* not used by lancpu */
@@ -113,7 +112,7 @@
       volatile	u_char rxQuality;
       volatile	u_char scrambled;
       volatile	u_char _4[1];
-      
+
       /* Transmit Status - 0x00b0 */
       volatile	u_char txStatus;
       volatile	u_char txAckQuality;
@@ -151,7 +150,7 @@
       volatile	u_short routerId;
       volatile	u_char _10[9];
       volatile	u_char txAttenuation;
-      volatile	u_char systemId[4]; 
+      volatile	u_char systemId[4];
       volatile	u_short globalChecksum;
       volatile	u_char _11[4];
       volatile	u_short maxDatagramSize;
@@ -207,19 +206,19 @@
       volatile	u_char hostcpuLock;
       volatile	u_char lancpuLock;
       volatile	u_char resetTime[18];
-      
+
       volatile	u_char numDatagramsTransmitted[4];
       volatile	u_char numReTransmissions[4];
       volatile	u_char numFramesDiscarded[4];
       volatile	u_char numDatagramsReceived[4];
       volatile	u_char numDuplicateReceivedFrames[4];
       volatile	u_char numDatagramsDiscarded[4];
-      
+
       volatile	u_short maxNumReTransmitDatagram;
       volatile	u_short maxNumReTransmitFrames;
       volatile	u_short maxNumConsecutiveDuplicateFrames;
       /* misaligned here so we have to go to characters */
-     
+
       volatile	u_char numBytesTransmitted[4];
       volatile	u_char numBytesReceived[4];
       volatile	u_char numCRCErrors[4];
@@ -259,7 +258,7 @@
       int channelNumber;
       int scramblingDisable;
       int txAttenuation;
-      int systemId; 
+      int systemId;
       int maxDatagramSize;
       int maxFrameSize;
       int maxRetries;
@@ -316,8 +315,7 @@
 
 extern struct arlan_conf_stru arlan_conf[MAX_ARLANS];
 
-struct TxParam
-{
+struct TxParam {
       volatile	short 		offset;
       volatile 	short 		length;
       volatile	u_char 		dest[6];
@@ -330,12 +328,12 @@
 #define TX_RING_SIZE 2
 /* Information that need to be kept for each board. */
 struct arlan_private {
-      struct arlan_shmem __iomem * card;
-      struct arlan_shmem * conf;
+      struct arlan_shmem __iomem *card;
+      struct arlan_shmem *conf;
 
-      struct arlan_conf_stru * Conf;	     
+      struct arlan_conf_stru *Conf;
       int	bad;
-      int 	reset;
+      int	reset;
       unsigned long lastReset;
       struct timer_list timer;
       struct timer_list tx_delay_timer;
@@ -407,38 +405,38 @@
 
 #define TXBuffStart(dev) offsetof(struct arlan_shmem, txBuffer)
 #define TXBuffEnd(dev) offsetof(struct arlan_shmem, xxBuffer)
- 
-#define READSHM(to,from,atype) {\
+
+#define READSHM(to, from, atype) {\
 	atype tmp;\
-	memcpy_fromio(&(tmp),&(from),sizeof(atype));\
+	memcpy_fromio(&(tmp), &(from), sizeof(atype));\
 	to = tmp;\
 	}
 
-#define READSHMEM(from,atype)\
+#define READSHMEM(from, atype)\
 	atype from; \
 	READSHM(from, arlan->from, atype);
 
-#define WRITESHM(to,from,atype) \
+#define WRITESHM(to, from, atype) \
 	{ atype tmpSHM = from;\
-	memcpy_toio(&(to),&tmpSHM,sizeof(atype));\
+	memcpy_toio(&(to), &tmpSHM, sizeof(atype));\
 	}
 
-#define DEBUGSHM(levelSHM,stringSHM,stuff,atype) \
+#define DEBUGSHM(levelSHM, stringSHM, stuff, atype) \
 	{	atype tmpSHM; \
-		memcpy_fromio(&tmpSHM,&(stuff),sizeof(atype));\
-		IFDEBUG(levelSHM) printk(stringSHM,tmpSHM);\
+		memcpy_fromio(&tmpSHM, &(stuff), sizeof(atype));\
+		IFDEBUG(levelSHM) printk(stringSHM, tmpSHM);\
 	}
 
 #define WRITESHMB(to, val) \
-	writeb(val,&(to))
+	writeb(val, &(to))
 #define READSHMB(to) \
 	readb(&(to))
 #define WRITESHMS(to, val) \
-	writew(val,&(to))
+	writew(val, &(to))
 #define READSHMS(to) \
 	readw(&(to))
 #define WRITESHMI(to, val) \
-	writel(val,&(to))
+	writel(val, &(to))
 #define READSHMI(to) \
 	readl(&(to))
 
@@ -447,51 +445,51 @@
 
 
 #define registrationBad(dev)\
-   ( (   READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationMode)    > 0) && \
-     (   READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationStatus) == 0)    )
+    ((   READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationMode)    > 0) && \
+     (   READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationStatus) == 0))
 
 
 #define readControlRegister(dev)\
- 	READSHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage)
+	READSHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage)
 
-#define writeControlRegister(dev, v){\
-   WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage	,((v) &0xF) );\
-   WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->controlRegister	,(v) 	);}
+#define writeControlRegister(dev, v) {\
+   WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage, ((v) & 0xF));\
+   WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->controlRegister, (v)); }
 
 
 #define arlan_interrupt_lancpu(dev) {\
    int cr;   \
    \
    cr = readControlRegister(dev);\
-   if (cr & ARLAN_CHANNEL_ATTENTION){ \
+   if (cr & ARLAN_CHANNEL_ATTENTION) { \
       writeControlRegister(dev, (cr & ~ARLAN_CHANNEL_ATTENTION));\
-   }else  \
+   } else  \
       writeControlRegister(dev, (cr | ARLAN_CHANNEL_ATTENTION));\
 }
 
-#define clearChannelAttention(dev){ \
-   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CHANNEL_ATTENTION);}
+#define clearChannelAttention(dev) { \
+   writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_CHANNEL_ATTENTION); }
 #define setHardwareReset(dev) {\
-   writeControlRegister(dev,readControlRegister(dev) | ARLAN_RESET);}
+   writeControlRegister(dev, readControlRegister(dev) | ARLAN_RESET); }
 #define clearHardwareReset(dev) {\
-   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_RESET);}
-#define setInterruptEnable(dev){\
-   writeControlRegister(dev,readControlRegister(dev) | ARLAN_INTERRUPT_ENABLE)  ;}
-#define clearInterruptEnable(dev){\
-   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_INTERRUPT_ENABLE)  ;}
-#define setClearInterrupt(dev){\
-   writeControlRegister(dev,readControlRegister(dev) | ARLAN_CLEAR_INTERRUPT)   ;}
-#define clearClearInterrupt(dev){\
-   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CLEAR_INTERRUPT);}
-#define setPowerOff(dev){\
-   writeControlRegister(dev,readControlRegister(dev) | (ARLAN_POWER && ARLAN_ACCESS));\
-   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);}
-#define setPowerOn(dev){\
-   writeControlRegister(dev,readControlRegister(dev) & ~(ARLAN_POWER));   }
-#define arlan_lock_card_access(dev){\
-   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);}
-#define arlan_unlock_card_access(dev){\
-   writeControlRegister(dev,readControlRegister(dev) | ARLAN_ACCESS ); }  
+   writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_RESET); }
+#define setInterruptEnable(dev) {\
+   writeControlRegister(dev, readControlRegister(dev) | ARLAN_INTERRUPT_ENABLE)  ; }
+#define clearInterruptEnable(dev) {\
+   writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_INTERRUPT_ENABLE)  ; }
+#define setClearInterrupt(dev) {\
+   writeControlRegister(dev, readControlRegister(dev) | ARLAN_CLEAR_INTERRUPT)   ; }
+#define clearClearInterrupt(dev) {\
+   writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_CLEAR_INTERRUPT); }
+#define setPowerOff(dev) {\
+   writeControlRegister(dev, readControlRegister(dev) | (ARLAN_POWER && ARLAN_ACCESS));\
+   writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_ACCESS); }
+#define setPowerOn(dev) {\
+   writeControlRegister(dev, readControlRegister(dev) & ~(ARLAN_POWER)); }
+#define arlan_lock_card_access(dev) {\
+   writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_ACCESS); }
+#define arlan_unlock_card_access(dev) {\
+   writeControlRegister(dev, readControlRegister(dev) | ARLAN_ACCESS); }
 
 
 
@@ -525,7 +523,6 @@
 					| ARLAN_COMMAND_RESET)
 
 
- 
 #define ARLAN_DEBUG_CHAIN_LOCKS		0x00001
 #define ARLAN_DEBUG_RESET		0x00002
 #define ARLAN_DEBUG_TIMING		0x00004
@@ -536,4 +533,3 @@
 #define ARLAN_DEBUG_INTERRUPT		0x00080
 #define ARLAN_DEBUG_STARTUP		0x00100
 #define ARLAN_DEBUG_SHUTDOWN		0x00200
- 
diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c
index 43c57b7..7ebecc9 100644
--- a/drivers/staging/asus_oled/asus_oled.c
+++ b/drivers/staging/asus_oled/asus_oled.c
@@ -52,6 +52,10 @@
 #define ASUS_OLED_DISP_HEIGHT		32
 #define ASUS_OLED_PACKET_BUF_SIZE	256
 
+#define USB_VENDOR_ID_ASUS      0x0b05
+#define USB_DEVICE_ID_ASUS_LCM      0x1726
+#define USB_DEVICE_ID_ASUS_LCM2     0x175b
+
 MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com");
 MODULE_DESCRIPTION("Asus OLED Driver v" ASUS_OLED_VERSION);
 MODULE_LICENSE("GPL");
@@ -83,18 +87,20 @@
 };
 
 /* table of devices that work with this driver */
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
 	/* Asus G1/G2 (and variants)*/
-	{ USB_DEVICE(0x0b05, 0x1726) },
+	{ USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM) },
 	/* Asus G50V (and possibly others - G70? G71?)*/
-	{ USB_DEVICE(0x0b05, 0x175b) },
+	{ USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2) },
 	{ },
 };
 
 /* parameters of specific devices */
 static struct oled_dev_desc_str oled_dev_desc_table[] = {
-	{ 0x0b05, 0x1726, 128, PACK_MODE_G1, "G1/G2" },
-	{ 0x0b05, 0x175b, 256, PACK_MODE_G50, "G50" },
+	{ USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, 128, PACK_MODE_G1,
+		"G1/G2" },
+	{ USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2, 256, PACK_MODE_G50,
+		"G50" },
 	{ },
 };
 
@@ -424,6 +430,11 @@
 
 		kfree(odev->buf);
 		odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
+		if (odev->buf == NULL) {
+			odev->buf_size = 0;
+			printk(ASUS_OLED_ERROR "Out of memory!\n");
+			return -ENOMEM;
+		}
 
 		memset(odev->buf, 0xff, odev->buf_size);
 
@@ -759,13 +770,8 @@
 	.id_table =	id_table,
 };
 
-static ssize_t version_show(struct class *dev, char *buf)
-{
-	return sprintf(buf, ASUS_OLED_UNDERSCORE_NAME " %s\n",
-		       ASUS_OLED_VERSION);
-}
-
-static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
+static CLASS_ATTR_STRING(version, S_IRUGO,
+		 	ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION);
 
 static int __init asus_oled_init(void)
 {
@@ -777,7 +783,7 @@
 		return PTR_ERR(oled_class);
 	}
 
-	retval = class_create_file(oled_class, &class_attr_version);
+	retval = class_create_file(oled_class, &class_attr_version.attr);
 	if (retval) {
 		err("Error creating class version file");
 		goto error;
@@ -799,7 +805,7 @@
 
 static void __exit asus_oled_exit(void)
 {
-	class_remove_file(oled_class, &class_attr_version);
+	class_remove_file(oled_class, &class_attr_version.attr);
 	class_destroy(oled_class);
 
 	usb_deregister(&oled_driver);
diff --git a/drivers/staging/b3dfg/Kconfig b/drivers/staging/b3dfg/Kconfig
deleted file mode 100644
index 9e6573c..0000000
--- a/drivers/staging/b3dfg/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config B3DFG
-       tristate "Brontes 3d Frame Framegrabber"
-       depends on PCI
-       default n
-       ---help---
-         This driver provides support for the Brontes 3d Framegrabber
-         PCI card.
-
-         To compile this driver as a module, choose M here. The module
-         will be called b3dfg.
diff --git a/drivers/staging/b3dfg/Makefile b/drivers/staging/b3dfg/Makefile
deleted file mode 100644
index 91f439f..0000000
--- a/drivers/staging/b3dfg/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_B3DFG) += b3dfg.o
diff --git a/drivers/staging/b3dfg/TODO b/drivers/staging/b3dfg/TODO
deleted file mode 100644
index f5a9298..0000000
--- a/drivers/staging/b3dfg/TODO
+++ /dev/null
@@ -1,4 +0,0 @@
-
- - queue/wait buffer presents filltime results for each frame?
- - counting of dropped frames
- - review endianness
diff --git a/drivers/staging/b3dfg/b3dfg.c b/drivers/staging/b3dfg/b3dfg.c
deleted file mode 100644
index 4a43c51..0000000
--- a/drivers/staging/b3dfg/b3dfg.c
+++ /dev/null
@@ -1,1100 +0,0 @@
- /*
- * Brontes PCI frame grabber driver
- *
- * Copyright (C) 2008 3M Company
- * Contact: Justin Bronder <jsbronder@brontes3d.com>
- * Original Authors: Daniel Drake <ddrake@brontes3d.com>
- *                   Duane Griffin <duaneg@dghda.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/fs.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/ioctl.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <linux/cdev.h>
-#include <linux/list.h>
-#include <linux/poll.h>
-#include <linux/wait.h>
-#include <linux/mm.h>
-#include <linux/uaccess.h>
-#include <linux/sched.h>
-
-static unsigned int b3dfg_nbuf = 2;
-
-module_param_named(buffer_count, b3dfg_nbuf, uint, 0444);
-
-MODULE_PARM_DESC(buffer_count, "Number of buffers (min 2, default 2)");
-
-MODULE_AUTHOR("Daniel Drake <ddrake@brontes3d.com>");
-MODULE_DESCRIPTION("Brontes frame grabber driver");
-MODULE_LICENSE("GPL");
-
-#define DRIVER_NAME "b3dfg"
-#define B3DFG_MAX_DEVS 4
-#define B3DFG_FRAMES_PER_BUFFER 3
-
-#define B3DFG_BAR_REGS	0
-#define B3DFG_REGS_LENGTH 0x10000
-
-#define B3DFG_IOC_MAGIC		0xb3 /* dfg :-) */
-#define B3DFG_IOCGFRMSZ		_IOR(B3DFG_IOC_MAGIC, 1, int)
-#define B3DFG_IOCTNUMBUFS	_IO(B3DFG_IOC_MAGIC, 2)
-#define B3DFG_IOCTTRANS		_IO(B3DFG_IOC_MAGIC, 3)
-#define B3DFG_IOCTQUEUEBUF	_IO(B3DFG_IOC_MAGIC, 4)
-#define B3DFG_IOCTPOLLBUF	_IOWR(B3DFG_IOC_MAGIC, 5, struct b3dfg_poll)
-#define B3DFG_IOCTWAITBUF	_IOWR(B3DFG_IOC_MAGIC, 6, struct b3dfg_wait)
-#define B3DFG_IOCGWANDSTAT	_IOR(B3DFG_IOC_MAGIC, 7, int)
-
-enum {
-	/* number of 4kb pages per frame */
-	B3D_REG_FRM_SIZE = 0x0,
-
-	/* bit 0: set to enable interrupts
-	 * bit 1: set to enable cable status change interrupts */
-	B3D_REG_HW_CTRL = 0x4,
-
-	/* bit 0-1 - 1-based ID of next pending frame transfer (0 = none)
-	 * bit 2 indicates the previous DMA transfer has completed
-	 * bit 3 indicates wand cable status change
-	 * bit 8:15 - counter of number of discarded triplets */
-	B3D_REG_DMA_STS = 0x8,
-
-	/* bit 0: wand status (1 = present, 0 = disconnected) */
-	B3D_REG_WAND_STS = 0xc,
-
-	/* bus address for DMA transfers. lower 2 bits must be zero because DMA
-	 * works with 32 bit word size. */
-	B3D_REG_EC220_DMA_ADDR = 0x8000,
-
-	/* bit 20:0 - number of 32 bit words to be transferred
-	 * bit 21:31 - reserved */
-	B3D_REG_EC220_TRF_SIZE = 0x8004,
-
-	/* bit 0 - error bit
-	 * bit 1 - interrupt bit (set to generate interrupt at end of transfer)
-	 * bit 2 - start bit (set to start transfer)
-	 * bit 3 - direction (0 = DMA_TO_DEVICE, 1 = DMA_FROM_DEVICE
-	 * bit 4:31 - reserved */
-	B3D_REG_EC220_DMA_STS = 0x8008,
-};
-
-enum b3dfg_buffer_state {
-	B3DFG_BUFFER_POLLED = 0,
-	B3DFG_BUFFER_PENDING,
-	B3DFG_BUFFER_POPULATED,
-};
-
-struct b3dfg_buffer {
-	unsigned char *frame[B3DFG_FRAMES_PER_BUFFER];
-	struct list_head list;
-	u8 state;
-};
-
-struct b3dfg_dev {
-
-	/* no protection needed: all finalized at initialization time */
-	struct pci_dev *pdev;
-	struct cdev chardev;
-	struct device *dev;
-	void __iomem *regs;
-	unsigned int frame_size;
-
-	/*
-	 * Protects buffer state, including buffer_queue, triplet_ready,
-	 * cur_dma_frame_idx & cur_dma_frame_addr.
-	 */
-	spinlock_t buffer_lock;
-	struct b3dfg_buffer *buffers;
-	struct list_head buffer_queue;
-
-	/* Last frame in triplet transferred (-1 if none). */
-	int cur_dma_frame_idx;
-
-	/* Current frame's address for DMA. */
-	dma_addr_t cur_dma_frame_addr;
-
-	/*
-	 * Protects cstate_tstamp.
-	 * Nests inside buffer_lock.
-	 */
-	spinlock_t cstate_lock;
-	unsigned long cstate_tstamp;
-
-	/*
-	 * Protects triplets_dropped.
-	 * Nests inside buffers_lock.
-	 */
-	spinlock_t triplets_dropped_lock;
-	unsigned int triplets_dropped;
-
-	wait_queue_head_t buffer_waitqueue;
-
-	unsigned int transmission_enabled:1;
-	unsigned int triplet_ready:1;
-};
-
-static u8 b3dfg_devices[B3DFG_MAX_DEVS];
-
-static struct class *b3dfg_class;
-static dev_t b3dfg_devt;
-
-static const struct pci_device_id b3dfg_ids[] __devinitdata = {
-	{ PCI_DEVICE(0x0b3d, 0x0001) },
-	{ },
-};
-
-MODULE_DEVICE_TABLE(pci, b3dfg_ids);
-
-/***** user-visible types *****/
-
-struct b3dfg_poll {
-	int buffer_idx;
-	unsigned int triplets_dropped;
-};
-
-struct b3dfg_wait {
-	int buffer_idx;
-	unsigned int timeout;
-	unsigned int triplets_dropped;
-};
-
-/**** register I/O ****/
-
-static u32 b3dfg_read32(struct b3dfg_dev *fgdev, u16 reg)
-{
-	return ioread32(fgdev->regs + reg);
-}
-
-static void b3dfg_write32(struct b3dfg_dev *fgdev, u16 reg, u32 value)
-{
-	iowrite32(value, fgdev->regs + reg);
-}
-
-/**** buffer management ****/
-
-/*
- * Program EC220 for transfer of a specific frame.
- * Called with buffer_lock held.
- */
-static int setup_frame_transfer(struct b3dfg_dev *fgdev,
-	struct b3dfg_buffer *buf, int frame)
-{
-	unsigned char *frm_addr;
-	dma_addr_t frm_addr_dma;
-	unsigned int frm_size = fgdev->frame_size;
-
-	frm_addr = buf->frame[frame];
-	frm_addr_dma = pci_map_single(fgdev->pdev, frm_addr,
-					  frm_size, PCI_DMA_FROMDEVICE);
-	if (pci_dma_mapping_error(fgdev->pdev, frm_addr_dma))
-		return -ENOMEM;
-
-	fgdev->cur_dma_frame_addr = frm_addr_dma;
-	fgdev->cur_dma_frame_idx = frame;
-
-	b3dfg_write32(fgdev, B3D_REG_EC220_DMA_ADDR,
-					cpu_to_le32(frm_addr_dma));
-	b3dfg_write32(fgdev, B3D_REG_EC220_TRF_SIZE,
-					cpu_to_le32(frm_size >> 2));
-	b3dfg_write32(fgdev, B3D_REG_EC220_DMA_STS, 0xf);
-
-	return 0;
-}
-
-/* Caller should hold buffer lock */
-static void dequeue_all_buffers(struct b3dfg_dev *fgdev)
-{
-	int i;
-	for (i = 0; i < b3dfg_nbuf; i++) {
-		struct b3dfg_buffer *buf = &fgdev->buffers[i];
-		buf->state = B3DFG_BUFFER_POLLED;
-		list_del_init(&buf->list);
-	}
-}
-
-/* queue a buffer to receive data */
-static int queue_buffer(struct b3dfg_dev *fgdev, int bufidx)
-{
-	struct device *dev = &fgdev->pdev->dev;
-	struct b3dfg_buffer *buf;
-	unsigned long flags;
-	int r = 0;
-
-	spin_lock_irqsave(&fgdev->buffer_lock, flags);
-	if (bufidx < 0 || bufidx >= b3dfg_nbuf) {
-		dev_dbg(dev, "Invalid buffer index, %d\n", bufidx);
-		r = -ENOENT;
-		goto out;
-	}
-	buf = &fgdev->buffers[bufidx];
-
-	if (unlikely(buf->state == B3DFG_BUFFER_PENDING)) {
-		dev_dbg(dev, "buffer %d is already queued\n", bufidx);
-		r = -EINVAL;
-		goto out;
-	}
-
-	buf->state = B3DFG_BUFFER_PENDING;
-	list_add_tail(&buf->list, &fgdev->buffer_queue);
-
-	if (fgdev->transmission_enabled && fgdev->triplet_ready) {
-		dev_dbg(dev, "triplet is ready, pushing immediately\n");
-		fgdev->triplet_ready = 0;
-		r = setup_frame_transfer(fgdev, buf, 0);
-		if (r)
-			dev_err(dev, "unable to map DMA buffer\n");
-	}
-
-out:
-	spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-	return r;
-}
-
-/* non-blocking buffer poll. returns 1 if data is present in the buffer,
- * 0 otherwise */
-static int poll_buffer(struct b3dfg_dev *fgdev, void __user *arg)
-{
-	struct device *dev = &fgdev->pdev->dev;
-	struct b3dfg_poll p;
-	struct b3dfg_buffer *buf;
-	unsigned long flags;
-	int r = 1;
-	int arg_out = 0;
-
-	if (copy_from_user(&p, arg, sizeof(p)))
-		return -EFAULT;
-
-	if (unlikely(!fgdev->transmission_enabled)) {
-		dev_dbg(dev, "cannot poll, transmission disabled\n");
-		return -EINVAL;
-	}
-
-	if (p.buffer_idx < 0 || p.buffer_idx >= b3dfg_nbuf)
-		return -ENOENT;
-
-	buf = &fgdev->buffers[p.buffer_idx];
-
-	spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
-	if (likely(buf->state == B3DFG_BUFFER_POPULATED)) {
-		arg_out = 1;
-		buf->state = B3DFG_BUFFER_POLLED;
-
-		/* IRQs already disabled by spin_lock_irqsave above. */
-		spin_lock(&fgdev->triplets_dropped_lock);
-		p.triplets_dropped = fgdev->triplets_dropped;
-		fgdev->triplets_dropped = 0;
-		spin_unlock(&fgdev->triplets_dropped_lock);
-	} else {
-		r = 0;
-	}
-
-	spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-	if (arg_out && copy_to_user(arg, &p, sizeof(p)))
-		r = -EFAULT;
-
-	return r;
-}
-
-static unsigned long get_cstate_change(struct b3dfg_dev *fgdev)
-{
-	unsigned long flags, when;
-
-	spin_lock_irqsave(&fgdev->cstate_lock, flags);
-	when = fgdev->cstate_tstamp;
-	spin_unlock_irqrestore(&fgdev->cstate_lock, flags);
-	return when;
-}
-
-static int is_event_ready(struct b3dfg_dev *fgdev, struct b3dfg_buffer *buf,
-			  unsigned long when)
-{
-	int result;
-	unsigned long flags;
-
-	spin_lock_irqsave(&fgdev->buffer_lock, flags);
-	spin_lock(&fgdev->cstate_lock);
-	result = (!fgdev->transmission_enabled ||
-		  buf->state == B3DFG_BUFFER_POPULATED ||
-		  when != fgdev->cstate_tstamp);
-	spin_unlock(&fgdev->cstate_lock);
-	spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-	return result;
-}
-
-/* sleep until a specific buffer becomes populated */
-static int wait_buffer(struct b3dfg_dev *fgdev, void __user *arg)
-{
-	struct device *dev = &fgdev->pdev->dev;
-	struct b3dfg_wait w;
-	struct b3dfg_buffer *buf;
-	unsigned long flags, when;
-	int r;
-
-	if (copy_from_user(&w, arg, sizeof(w)))
-		return -EFAULT;
-
-	if (!fgdev->transmission_enabled) {
-		dev_dbg(dev, "cannot wait, transmission disabled\n");
-		return -EINVAL;
-	}
-
-	if (w.buffer_idx < 0 || w.buffer_idx >= b3dfg_nbuf)
-		return -ENOENT;
-
-	buf = &fgdev->buffers[w.buffer_idx];
-
-	spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
-	if (buf->state == B3DFG_BUFFER_POPULATED) {
-		r = w.timeout;
-		goto out_triplets_dropped;
-	}
-
-	spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-	when = get_cstate_change(fgdev);
-	if (w.timeout > 0) {
-		r = wait_event_interruptible_timeout(fgdev->buffer_waitqueue,
-			is_event_ready(fgdev, buf, when),
-			(w.timeout * HZ) / 1000);
-
-		if (unlikely(r < 0))
-			goto out;
-
-		w.timeout = r * 1000 / HZ;
-	} else {
-		r = wait_event_interruptible(fgdev->buffer_waitqueue,
-			is_event_ready(fgdev, buf, when));
-
-		if (unlikely(r)) {
-			r = -ERESTARTSYS;
-			goto out;
-		}
-	}
-
-	/* TODO: Inform the user via field(s) in w? */
-	if (!fgdev->transmission_enabled || when != get_cstate_change(fgdev)) {
-		r = -EINVAL;
-		goto out;
-	}
-
-	spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
-	if (buf->state != B3DFG_BUFFER_POPULATED) {
-		r = -ETIMEDOUT;
-		goto out_unlock;
-	}
-
-	buf->state = B3DFG_BUFFER_POLLED;
-
-out_triplets_dropped:
-
-	/* IRQs already disabled by spin_lock_irqsave above. */
-	spin_lock(&fgdev->triplets_dropped_lock);
-	w.triplets_dropped = fgdev->triplets_dropped;
-	fgdev->triplets_dropped = 0;
-	spin_unlock(&fgdev->triplets_dropped_lock);
-
-out_unlock:
-	spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-	if (copy_to_user(arg, &w, sizeof(w)))
-		r = -EFAULT;
-out:
-	return r;
-}
-
-/* mmap page fault handler */
-static int b3dfg_vma_fault(struct vm_area_struct *vma,
-	struct vm_fault *vmf)
-{
-	struct b3dfg_dev *fgdev = vma->vm_file->private_data;
-	unsigned long off = vmf->pgoff << PAGE_SHIFT;
-	unsigned int frame_size = fgdev->frame_size;
-	unsigned int buf_size = frame_size * B3DFG_FRAMES_PER_BUFFER;
-	unsigned char *addr;
-
-	/* determine which buffer the offset lies within */
-	unsigned int buf_idx = off / buf_size;
-	/* and the offset into the buffer */
-	unsigned int buf_off = off % buf_size;
-
-	/* determine which frame inside the buffer the offset lies in */
-	unsigned int frm_idx = buf_off / frame_size;
-	/* and the offset into the frame */
-	unsigned int frm_off = buf_off % frame_size;
-
-	if (unlikely(buf_idx >= b3dfg_nbuf))
-		return VM_FAULT_SIGBUS;
-
-	addr = fgdev->buffers[buf_idx].frame[frm_idx] + frm_off;
-	vm_insert_pfn(vma, (unsigned long)vmf->virtual_address,
-			  virt_to_phys(addr) >> PAGE_SHIFT);
-
-	return VM_FAULT_NOPAGE;
-}
-
-static struct vm_operations_struct b3dfg_vm_ops = {
-	.fault = b3dfg_vma_fault,
-};
-
-static int get_wand_status(struct b3dfg_dev *fgdev, int __user *arg)
-{
-	u32 wndstat = b3dfg_read32(fgdev, B3D_REG_WAND_STS);
-	dev_dbg(&fgdev->pdev->dev, "wand status %x\n", wndstat);
-	return __put_user(wndstat & 0x1, arg);
-}
-
-static int enable_transmission(struct b3dfg_dev *fgdev)
-{
-	unsigned long flags;
-	struct device *dev = &fgdev->pdev->dev;
-
-	dev_dbg(dev, "enable transmission\n");
-
-	/* check the cable is plugged in. */
-	if (!b3dfg_read32(fgdev, B3D_REG_WAND_STS)) {
-		dev_dbg(dev, "cannot start transmission without wand\n");
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
-	/* Handle racing enable_transmission calls. */
-	if (fgdev->transmission_enabled) {
-		spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-		goto out;
-	}
-
-	spin_lock(&fgdev->triplets_dropped_lock);
-	fgdev->triplets_dropped = 0;
-	spin_unlock(&fgdev->triplets_dropped_lock);
-
-	fgdev->triplet_ready = 0;
-	fgdev->cur_dma_frame_idx = -1;
-	fgdev->transmission_enabled = 1;
-
-	spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-	/* Enable DMA and cable status interrupts. */
-	b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0x03);
-
-out:
-	return 0;
-}
-
-static void disable_transmission(struct b3dfg_dev *fgdev)
-{
-	struct device *dev = &fgdev->pdev->dev;
-	unsigned long flags;
-	u32 tmp;
-
-	dev_dbg(dev, "disable transmission\n");
-
-	/* guarantee that no more interrupts will be serviced */
-	spin_lock_irqsave(&fgdev->buffer_lock, flags);
-	fgdev->transmission_enabled = 0;
-
-	b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0);
-
-	/* FIXME: temporary debugging only. if the board stops transmitting,
-	 * hitting ctrl+c and seeing this message is useful for determining
-	 * the state of the board. */
-	tmp = b3dfg_read32(fgdev, B3D_REG_DMA_STS);
-	dev_dbg(dev, "DMA_STS reads %x after TX stopped\n", tmp);
-
-	dequeue_all_buffers(fgdev);
-	spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-	wake_up_interruptible(&fgdev->buffer_waitqueue);
-}
-
-static int set_transmission(struct b3dfg_dev *fgdev, int enabled)
-{
-	int res = 0;
-
-	if (enabled && !fgdev->transmission_enabled)
-		res = enable_transmission(fgdev);
-	else if (!enabled && fgdev->transmission_enabled)
-		disable_transmission(fgdev);
-
-	return res;
-}
-
-/* Called in interrupt context. */
-static void handle_cstate_unplug(struct b3dfg_dev *fgdev)
-{
-	/* Disable all interrupts. */
-	b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0);
-
-	/* Stop transmission. */
-	spin_lock(&fgdev->buffer_lock);
-	fgdev->transmission_enabled = 0;
-
-	fgdev->cur_dma_frame_idx = -1;
-	fgdev->triplet_ready = 0;
-	if (fgdev->cur_dma_frame_addr) {
-		pci_unmap_single(fgdev->pdev, fgdev->cur_dma_frame_addr,
-				 fgdev->frame_size, PCI_DMA_FROMDEVICE);
-		fgdev->cur_dma_frame_addr = 0;
-	}
-	dequeue_all_buffers(fgdev);
-	spin_unlock(&fgdev->buffer_lock);
-}
-
-/* Called in interrupt context. */
-static void handle_cstate_change(struct b3dfg_dev *fgdev)
-{
-	u32 cstate = b3dfg_read32(fgdev, B3D_REG_WAND_STS);
-	unsigned long when;
-	struct device *dev = &fgdev->pdev->dev;
-
-	dev_dbg(dev, "cable state change: %u\n", cstate);
-
-	/*
-	 * When the wand is unplugged we reset our state. The hardware will
-	 * have done the same internally.
-	 *
-	 * Note we should never see a cable *plugged* event, as interrupts
-	 * should only be enabled when transmitting, which requires the cable
-	 * to be plugged. If we do see one it probably means the cable has been
-	 * unplugged and re-plugged very rapidly. Possibly because it has a
-	 * broken wire and is momentarily losing contact.
-	 *
-	 * TODO: At the moment if you plug in the cable then enable transmission
-	 * the hardware will raise a couple of spurious interrupts, so
-	 * just ignore them for now.
-	 *
-	 * Once the hardware is fixed we should complain and treat it as an
-	 * unplug. Or at least track how frequently it is happening and do
-	 * so if too many come in.
-	 */
-	if (cstate) {
-		dev_warn(dev, "ignoring unexpected plug event\n");
-		return;
-	}
-	handle_cstate_unplug(fgdev);
-
-	/*
-	 * Record cable state change timestamp & wake anyone waiting
-	 * on a cable state change. Be paranoid about ensuring events
-	 * are not missed if we somehow get two interrupts in a jiffy.
-	 */
-	spin_lock(&fgdev->cstate_lock);
-	when = jiffies_64;
-	if (when <= fgdev->cstate_tstamp)
-		when = fgdev->cstate_tstamp + 1;
-	fgdev->cstate_tstamp = when;
-	wake_up_interruptible(&fgdev->buffer_waitqueue);
-	spin_unlock(&fgdev->cstate_lock);
-}
-
-/* Called with buffer_lock held. */
-static void transfer_complete(struct b3dfg_dev *fgdev)
-{
-	struct b3dfg_buffer *buf;
-	struct device *dev = &fgdev->pdev->dev;
-
-	pci_unmap_single(fgdev->pdev, fgdev->cur_dma_frame_addr,
-			 fgdev->frame_size, PCI_DMA_FROMDEVICE);
-	fgdev->cur_dma_frame_addr = 0;
-
-	buf = list_entry(fgdev->buffer_queue.next, struct b3dfg_buffer, list);
-
-	dev_dbg(dev, "handle frame completion\n");
-	if (fgdev->cur_dma_frame_idx == B3DFG_FRAMES_PER_BUFFER - 1) {
-
-		/* last frame of that triplet completed */
-		dev_dbg(dev, "triplet completed\n");
-		buf->state = B3DFG_BUFFER_POPULATED;
-		list_del_init(&buf->list);
-		wake_up_interruptible(&fgdev->buffer_waitqueue);
-	}
-}
-
-/*
- * Called with buffer_lock held.
- *
- * Note that idx is the (1-based) *next* frame to be transferred, while
- * cur_dma_frame_idx is the (0-based) *last* frame to have been transferred (or
- * -1 if none). Thus there should be a difference of 2 between them.
- */
-static bool setup_next_frame_transfer(struct b3dfg_dev *fgdev, int idx)
-{
-	struct b3dfg_buffer *buf;
-	struct device *dev = &fgdev->pdev->dev;
-	bool need_ack = 1;
-
-	dev_dbg(dev, "program DMA transfer for next frame: %d\n", idx);
-
-	buf = list_entry(fgdev->buffer_queue.next, struct b3dfg_buffer, list);
-	if (idx == fgdev->cur_dma_frame_idx + 2) {
-		if (setup_frame_transfer(fgdev, buf, idx - 1))
-			dev_err(dev, "unable to map DMA buffer\n");
-		need_ack = 0;
-	} else {
-		dev_err(dev, "frame mismatch, got %d, expected %d\n",
-			idx, fgdev->cur_dma_frame_idx + 2);
-
-		/* FIXME: handle dropped triplets here */
-	}
-
-	return need_ack;
-}
-
-static irqreturn_t b3dfg_intr(int irq, void *dev_id)
-{
-	struct b3dfg_dev *fgdev = dev_id;
-	struct device *dev = &fgdev->pdev->dev;
-	u32 sts;
-	u8 dropped;
-	bool need_ack = 1;
-	irqreturn_t res = IRQ_HANDLED;
-
-	sts = b3dfg_read32(fgdev, B3D_REG_DMA_STS);
-	if (unlikely(sts == 0)) {
-		dev_warn(dev, "ignore interrupt, DMA status is 0\n");
-		res = IRQ_NONE;
-		goto out;
-	}
-
-	if (unlikely(!fgdev->transmission_enabled)) {
-		dev_warn(dev, "ignore interrupt, TX disabled\n");
-		res = IRQ_HANDLED;
-		goto out;
-	}
-
-	/* Handle dropped frames, as reported by the hardware. */
-	dropped = (sts >> 8) & 0xff;
-	dev_dbg(dev, "intr: DMA_STS=%08x (drop=%d comp=%d next=%d)\n",
-		sts, dropped, !!(sts & 0x4), sts & 0x3);
-	if (unlikely(dropped > 0)) {
-		spin_lock(&fgdev->triplets_dropped_lock);
-		fgdev->triplets_dropped += dropped;
-		spin_unlock(&fgdev->triplets_dropped_lock);
-	}
-
-	/* Handle a cable state change (i.e. the wand being unplugged). */
-	if (sts & 0x08) {
-		handle_cstate_change(fgdev);
-		goto out;
-	}
-
-	spin_lock(&fgdev->buffer_lock);
-	if (unlikely(list_empty(&fgdev->buffer_queue))) {
-
-		/* FIXME need more sanity checking here */
-		dev_info(dev, "buffer not ready for next transfer\n");
-		fgdev->triplet_ready = 1;
-		goto out_unlock;
-	}
-
-	/* Has a frame transfer been completed? */
-	if (sts & 0x4) {
-		u32 dma_status = b3dfg_read32(fgdev, B3D_REG_EC220_DMA_STS);
-
-		/* Check for DMA errors reported by the hardware. */
-		if (unlikely(dma_status & 0x1)) {
-			dev_err(dev, "EC220 error: %08x\n", dma_status);
-
-			/* FIXME flesh out error handling */
-			goto out_unlock;
-		}
-
-		/* Sanity check, we should have a frame index at this point. */
-		if (unlikely(fgdev->cur_dma_frame_idx == -1)) {
-			dev_err(dev, "completed but no last idx?\n");
-
-			/* FIXME flesh out error handling */
-			goto out_unlock;
-		}
-
-		transfer_complete(fgdev);
-	}
-
-	/* Is there another frame transfer pending? */
-	if (sts & 0x3)
-		need_ack = setup_next_frame_transfer(fgdev, sts & 0x3);
-	else
-		fgdev->cur_dma_frame_idx = -1;
-
-out_unlock:
-	spin_unlock(&fgdev->buffer_lock);
-out:
-	if (need_ack) {
-		dev_dbg(dev, "acknowledging interrupt\n");
-		b3dfg_write32(fgdev, B3D_REG_EC220_DMA_STS, 0x0b);
-	}
-	return res;
-}
-
-static int b3dfg_open(struct inode *inode, struct file *filp)
-{
-	struct b3dfg_dev *fgdev =
-		container_of(inode->i_cdev, struct b3dfg_dev, chardev);
-
-	dev_dbg(&fgdev->pdev->dev, "open\n");
-	filp->private_data = fgdev;
-	return 0;
-}
-
-static int b3dfg_release(struct inode *inode, struct file *filp)
-{
-	struct b3dfg_dev *fgdev = filp->private_data;
-	dev_dbg(&fgdev->pdev->dev, "release\n");
-	disable_transmission(fgdev);
-	return 0;
-}
-
-static long b3dfg_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	struct b3dfg_dev *fgdev = filp->private_data;
-
-	switch (cmd) {
-	case B3DFG_IOCGFRMSZ:
-		return __put_user(fgdev->frame_size, (int __user *) arg);
-	case B3DFG_IOCGWANDSTAT:
-		return get_wand_status(fgdev, (int __user *) arg);
-	case B3DFG_IOCTTRANS:
-		return set_transmission(fgdev, (int) arg);
-	case B3DFG_IOCTQUEUEBUF:
-		return queue_buffer(fgdev, (int) arg);
-	case B3DFG_IOCTPOLLBUF:
-		return poll_buffer(fgdev, (void __user *) arg);
-	case B3DFG_IOCTWAITBUF:
-		return wait_buffer(fgdev, (void __user *) arg);
-	default:
-		dev_dbg(&fgdev->pdev->dev, "unrecognised ioctl %x\n", cmd);
-		return -EINVAL;
-	}
-}
-
-static unsigned int b3dfg_poll(struct file *filp, poll_table *poll_table)
-{
-	struct b3dfg_dev *fgdev = filp->private_data;
-	unsigned long flags, when;
-	int i;
-	int r = 0;
-
-	when = get_cstate_change(fgdev);
-	poll_wait(filp, &fgdev->buffer_waitqueue, poll_table);
-
-	spin_lock_irqsave(&fgdev->buffer_lock, flags);
-	for (i = 0; i < b3dfg_nbuf; i++) {
-		if (fgdev->buffers[i].state == B3DFG_BUFFER_POPULATED) {
-			r = POLLIN | POLLRDNORM;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
-	/* TODO: Confirm this is how we want to communicate the change. */
-	if (!fgdev->transmission_enabled || when != get_cstate_change(fgdev))
-		r = POLLERR;
-
-	return r;
-}
-
-static int b3dfg_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-	struct b3dfg_dev *fgdev = filp->private_data;
-	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	unsigned long vsize = vma->vm_end - vma->vm_start;
-	unsigned long bufdatalen = b3dfg_nbuf * fgdev->frame_size * 3;
-	unsigned long psize = bufdatalen - offset;
-	int r = 0;
-
-	if (vsize <= psize) {
-		vma->vm_flags |= VM_IO | VM_RESERVED | VM_CAN_NONLINEAR |
-				 VM_PFNMAP;
-		vma->vm_ops = &b3dfg_vm_ops;
-	} else {
-		r = -EINVAL;
-	}
-
-	return r;
-}
-
-static struct file_operations b3dfg_fops = {
-	.owner = THIS_MODULE,
-	.open = b3dfg_open,
-	.release = b3dfg_release,
-	.unlocked_ioctl = b3dfg_ioctl,
-	.poll = b3dfg_poll,
-	.mmap = b3dfg_mmap,
-};
-
-static void free_all_frame_buffers(struct b3dfg_dev *fgdev)
-{
-	int i, j;
-	for (i = 0; i < b3dfg_nbuf; i++)
-		for (j = 0; j < B3DFG_FRAMES_PER_BUFFER; j++)
-			kfree(fgdev->buffers[i].frame[j]);
-	kfree(fgdev->buffers);
-}
-
-/* initialize device and any data structures. called before any interrupts
- * are enabled. */
-static int b3dfg_init_dev(struct b3dfg_dev *fgdev)
-{
-	int i, j;
-	u32 frm_size = b3dfg_read32(fgdev, B3D_REG_FRM_SIZE);
-
-	/* Disable interrupts. In abnormal circumstances (e.g. after a crash)
-	 * the board may still be transmitting from the previous session. If we
-	 * ensure that interrupts are disabled before we later enable them, we
-	 * are sure to capture a triplet from the start, rather than starting
-	 * from frame 2 or 3. Disabling interrupts causes the FG to throw away
-	 * all buffered data and stop buffering more until interrupts are
-	 * enabled again.
-	 */
-	b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0);
-
-	fgdev->frame_size = frm_size * 4096;
-	fgdev->buffers = kzalloc(sizeof(struct b3dfg_buffer) * b3dfg_nbuf,
-				 GFP_KERNEL);
-	if (!fgdev->buffers)
-		goto err_no_buf;
-	for (i = 0; i < b3dfg_nbuf; i++) {
-		struct b3dfg_buffer *buf = &fgdev->buffers[i];
-		for (j = 0; j < B3DFG_FRAMES_PER_BUFFER; j++) {
-			buf->frame[j] = kmalloc(fgdev->frame_size, GFP_KERNEL);
-			if (!buf->frame[j])
-				goto err_no_mem;
-		}
-		INIT_LIST_HEAD(&buf->list);
-	}
-
-	INIT_LIST_HEAD(&fgdev->buffer_queue);
-	init_waitqueue_head(&fgdev->buffer_waitqueue);
-	spin_lock_init(&fgdev->buffer_lock);
-	spin_lock_init(&fgdev->cstate_lock);
-	spin_lock_init(&fgdev->triplets_dropped_lock);
-	return 0;
-
-err_no_mem:
-	free_all_frame_buffers(fgdev);
-err_no_buf:
-	return -ENOMEM;
-}
-
-/* find next free minor number, returns -1 if none are availabile */
-static int get_free_minor(void)
-{
-	int i;
-	for (i = 0; i < B3DFG_MAX_DEVS; i++) {
-		if (b3dfg_devices[i] == 0)
-			return i;
-	}
-	return -1;
-}
-
-static int __devinit b3dfg_probe(struct pci_dev *pdev,
-	const struct pci_device_id *id)
-{
-	struct b3dfg_dev *fgdev = kzalloc(sizeof(*fgdev), GFP_KERNEL);
-	int r = 0;
-	int minor = get_free_minor();
-	dev_t devno = MKDEV(MAJOR(b3dfg_devt), minor);
-	unsigned long res_len;
-	resource_size_t res_base;
-
-	if (fgdev == NULL)
-		return -ENOMEM;
-
-	if (minor < 0) {
-		dev_err(&pdev->dev, "too many devices found!\n");
-		r = -EIO;
-		goto err_free;
-	}
-
-	b3dfg_devices[minor] = 1;
-	dev_info(&pdev->dev, "probe device with IRQ %d\n", pdev->irq);
-
-	cdev_init(&fgdev->chardev, &b3dfg_fops);
-	fgdev->chardev.owner = THIS_MODULE;
-
-	r = cdev_add(&fgdev->chardev, devno, 1);
-	if (r) {
-		dev_err(&pdev->dev, "cannot add char device\n");
-		goto err_release_minor;
-	}
-
-	fgdev->dev = device_create(
-		b3dfg_class,
-		&pdev->dev,
-		devno,
-		dev_get_drvdata(&pdev->dev),
-		DRIVER_NAME "%d", minor);
-
-	if (IS_ERR(fgdev->dev)) {
-		dev_err(&pdev->dev, "cannot create device\n");
-		r = PTR_ERR(fgdev->dev);
-		goto err_del_cdev;
-	}
-
-	r = pci_enable_device(pdev);
-	if (r) {
-		dev_err(&pdev->dev, "cannot enable PCI device\n");
-		goto err_dev_unreg;
-	}
-
-	res_len = pci_resource_len(pdev, B3DFG_BAR_REGS);
-	if (res_len != B3DFG_REGS_LENGTH) {
-		dev_err(&pdev->dev, "invalid register resource size\n");
-		r = -EIO;
-		goto err_disable;
-	}
-
-	if (pci_resource_flags(pdev, B3DFG_BAR_REGS)
-				!= (IORESOURCE_MEM | IORESOURCE_SIZEALIGN)) {
-		dev_err(&pdev->dev, "invalid resource flags\n");
-		r = -EIO;
-		goto err_disable;
-	}
-	r = pci_request_regions(pdev, DRIVER_NAME);
-	if (r) {
-		dev_err(&pdev->dev, "cannot obtain PCI resources\n");
-		goto err_disable;
-	}
-
-	pci_set_master(pdev);
-
-	r = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (r) {
-		dev_err(&pdev->dev, "no usable DMA configuration\n");
-		goto err_free_res;
-	}
-
-	res_base = pci_resource_start(pdev, B3DFG_BAR_REGS);
-	fgdev->regs = ioremap_nocache(res_base, res_len);
-	if (!fgdev->regs) {
-		dev_err(&pdev->dev, "regs ioremap failed\n");
-		r = -EIO;
-		goto err_free_res;
-	}
-
-	fgdev->pdev = pdev;
-	pci_set_drvdata(pdev, fgdev);
-	r = b3dfg_init_dev(fgdev);
-	if (r < 0) {
-		dev_err(&pdev->dev, "failed to initalize device\n");
-		goto err_unmap;
-	}
-
-	r = request_irq(pdev->irq, b3dfg_intr, IRQF_SHARED, DRIVER_NAME, fgdev);
-	if (r) {
-		dev_err(&pdev->dev, "couldn't request irq %d\n", pdev->irq);
-		goto err_free_bufs;
-	}
-
-	return 0;
-
-err_free_bufs:
-	free_all_frame_buffers(fgdev);
-err_unmap:
-	iounmap(fgdev->regs);
-err_free_res:
-	pci_release_regions(pdev);
-err_disable:
-	pci_disable_device(pdev);
-err_dev_unreg:
-	device_destroy(b3dfg_class, devno);
-err_del_cdev:
-	cdev_del(&fgdev->chardev);
-err_release_minor:
-	b3dfg_devices[minor] = 0;
-err_free:
-	kfree(fgdev);
-	return r;
-}
-
-static void __devexit b3dfg_remove(struct pci_dev *pdev)
-{
-	struct b3dfg_dev *fgdev = pci_get_drvdata(pdev);
-	unsigned int minor = MINOR(fgdev->chardev.dev);
-
-	dev_dbg(&pdev->dev, "remove\n");
-
-	free_irq(pdev->irq, fgdev);
-	iounmap(fgdev->regs);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	device_destroy(b3dfg_class, MKDEV(MAJOR(b3dfg_devt), minor));
-	cdev_del(&fgdev->chardev);
-	free_all_frame_buffers(fgdev);
-	kfree(fgdev);
-	b3dfg_devices[minor] = 0;
-}
-
-static struct pci_driver b3dfg_driver = {
-	.name = DRIVER_NAME,
-	.id_table = b3dfg_ids,
-	.probe = b3dfg_probe,
-	.remove = __devexit_p(b3dfg_remove),
-};
-
-static int __init b3dfg_module_init(void)
-{
-	int r;
-
-	if (b3dfg_nbuf < 2) {
-		printk(KERN_ERR DRIVER_NAME
-			   ": buffer_count is out of range (must be >= 2)");
-		return -EINVAL;
-	}
-
-	printk(KERN_INFO DRIVER_NAME ": loaded\n");
-
-	b3dfg_class = class_create(THIS_MODULE, DRIVER_NAME);
-	if (IS_ERR(b3dfg_class))
-		return PTR_ERR(b3dfg_class);
-
-	r = alloc_chrdev_region(&b3dfg_devt, 0, B3DFG_MAX_DEVS, DRIVER_NAME);
-	if (r)
-		goto err1;
-
-	r = pci_register_driver(&b3dfg_driver);
-	if (r)
-		goto err2;
-
-	return r;
-
-err2:
-	unregister_chrdev_region(b3dfg_devt, B3DFG_MAX_DEVS);
-err1:
-	class_destroy(b3dfg_class);
-	return r;
-}
-
-static void __exit b3dfg_module_exit(void)
-{
-	printk(KERN_INFO DRIVER_NAME ": unloaded\n");
-	pci_unregister_driver(&b3dfg_driver);
-	unregister_chrdev_region(b3dfg_devt, B3DFG_MAX_DEVS);
-	class_destroy(b3dfg_class);
-}
-
-module_init(b3dfg_module_init);
-module_exit(b3dfg_module_exit);
diff --git a/drivers/staging/batman-adv/Kconfig b/drivers/staging/batman-adv/Kconfig
index 1d74dab..1e7e0a8 100644
--- a/drivers/staging/batman-adv/Kconfig
+++ b/drivers/staging/batman-adv/Kconfig
@@ -4,7 +4,7 @@
 
 config BATMAN_ADV
 	tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
-	depends on PROC_FS && PACKET
+	depends on PROC_FS && NET
         default n
 	---help---
 
@@ -14,10 +14,10 @@
         http://www.open-mesh.org/ for more information and user space
         tools.
 
-config BATMAN_DEBUG
+config BATMAN_ADV_DEBUG
 	bool "B.A.T.M.A.N. debugging"
 	depends on BATMAN_ADV != n
-	help
+	---help---
 
 	  This is an option for use by developers; most people should
 	  say N here. This enables compilation of support for
diff --git a/drivers/staging/batman-adv/Makefile b/drivers/staging/batman-adv/Makefile
index 02da871..42b4e63 100644
--- a/drivers/staging/batman-adv/Makefile
+++ b/drivers/staging/batman-adv/Makefile
@@ -19,4 +19,4 @@
 #
 
 obj-m += batman-adv.o
-batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o log.o
+batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o
diff --git a/drivers/staging/batman-adv/README b/drivers/staging/batman-adv/README
index 3aaf393..7d666ad 100644
--- a/drivers/staging/batman-adv/README
+++ b/drivers/staging/batman-adv/README
@@ -1,4 +1,4 @@
-[state: 07-11-2009]
+[state: 06-01-2010]
 
 BATMAN-ADV
 ----------
@@ -15,19 +15,6 @@
 This is batman-advanced implemented as Linux kernel driver. It does not depend
 on any network (other) driver, and can be used on wifi as well as ethernet,
 vpn, etc ... (anything with ethernet-style layer 2).
-It compiles against and should work with Linux 2.6.20 - 2.6.31. Supporting older
-versions is not planned, but it's probably easy to backport it. If you work on a
-backport, feel free to contact us.  :-)
-
-COMPILE
--------
-To compile against your currently installed kernel, just type:
-
-# make
-
-if you want to compile against some other kernel, use:
-
-# make KERNELPATH=/path/to/kernel
 
 USAGE
 -----
@@ -73,16 +60,9 @@
 
 # cat /proc/net/batman-adv/vis
 
-This output format is a graphviz formatted text file which can be
-processed with graphviz-tools like dot.
-The labels are similar/compatible to the ETX metric, 1.0 means perfect
-connection (100%), 2.0 means 50%, 3.0 means 33% and so on.
-
-Alternatively, a JSON output format is available. The format can be set
-using by writing either "dot_draw" or "json" into the vis_format file.
-"dot_draw" is selected by default.
-
-echo "json" > /proc/net/batman-adv/vis_format
+The output is in a generic raw format. Use the batctl tool (See below)
+to convert this to other formats more suitable for graphing, eg
+graphviz dot, or JSON data-interchange format.
 
 In very mobile scenarios, you might want to adjust the originator
 interval to a lower value. This will make the mesh more responsive to
@@ -96,15 +76,59 @@
 
 # echo "" > /proc/net/batman-adv/interfaces
 
+LOGGING/DEBUGGING
+-----------------
+
+All error messages, warnings and information messages are sent to the
+kernel log. Depending on your operating system distribution this can be
+read in one of a number of ways. Try using the commands: dmesg,
+logread, or looking in the files /var/log/kern.log or
+/var/log/syslog. All batman-adv messages are prefixed with
+"batman-adv:" So to see just these messages try
+
+dmesg | grep batman-adv
+
+When investigating problems with your mesh network it is sometimes
+necessary to see more detail debug messages. This must be enabled when
+compiling the batman-adv module. Use "make menuconfig" and enable the
+option "B.A.T.M.A.N. debugging".
+
+The additional debug output is by default disabled. It can be enabled
+either at kernel module load time or during run time. To enable debug
+output at module load time, add the module parameter debug=<value>.
+<value> can take one of four values.
+
+0 - All debug output disabled
+1 - Enable messages related to routing / flooding / broadcasting
+2 - Enable route or hna added / changed / deleted
+3 - Enable all messages
+
+e.g.
+
+modprobe batman-adv debug=2
+
+will load the module and enable debug messages for when routes or HNAs
+change.
+
+The debug output can also be changed at runtime using the file
+/sys/module/batman-adv/parameters/debug. e.g.
+
+echo 2 > /sys/module/batman-adv/parameters/debug
+
+enables debug messages for when routes or HNAs
+
+The debug output is sent to the kernel logs. So try dmesg, logread etc
+to see the debug messages.
+
 BATCTL
 ------
 
-B.A.T.M.A.N.  advanced  operates on layer 2 and thus all hosts partici-
-pating in the virtual switch are completely transparent for all  proto-
-cols above layer 2. Therefore the common diagnosis tools do not work as
-expected. To overcome these problems batctl was created. At the  moment
-the  batctl contains ping, traceroute, tcpdump and interfaces to the
-kernel module settings.
+B.A.T.M.A.N.  advanced operates on layer 2 and thus all hosts
+participating in the virtual switch are completely transparent for all
+protocols above layer 2. Therefore the common diagnosis tools do not
+work as expected. To overcome these problems batctl was created. At
+the moment the batctl contains ping, traceroute, tcpdump and
+interfaces to the kernel module settings.
 
 For more information, please see the manpage (man batctl).
 
diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO
index ea6dcf9..2f15136 100644
--- a/drivers/staging/batman-adv/TODO
+++ b/drivers/staging/batman-adv/TODO
@@ -17,30 +17,6 @@
 -> transtable_global (read-only) [outputs the global translation table]
 -> transtable_local (read-only) [outputs the local translation table]
 
-=> vis "raw" data output
-* the raw format shall replace dot draw / json to offer a neutral that can
-* be converted
-* the format (comma seperated entries):
--> "mac" -> mac address of an originator (each line begins with it)
--> "TQ mac value" -> src mac's link quality towards mac address
--> "HNA mac" -> HNA announced by source mac
--> "PRIMARY" -> this is a primary interface
--> "SEC mac" -> secondary mac address of source (requires preceeding
--> PRIMARY)
-
-=> logging
-* the log level LOG_TYPE_CRIT, LOG_TYPE_WARN & LOG_TYPE_NOTICE will be
-* unified to use printk
-* LOG_TYPE_BATMAN & LOG_TYPE_ROUTES will also use printk but only after the
-* internal debug level has been raised
-* the internal debug level can be modified using a module parameter (debug)
-* or at run time via /sys/module/batman-adv/parameters/debug
-* make use of printk %pM support instead of converting mac addresses
-* manually
-
-=> strip out all backward compatibility support to older kernels
-   (only found in compat.h)
-
 => fix checkpatch.pl errors
 
 Please send all patches to:
diff --git a/drivers/staging/batman-adv/aggregation.c b/drivers/staging/batman-adv/aggregation.c
index 9c6e681..7917322 100644
--- a/drivers/staging/batman-adv/aggregation.c
+++ b/drivers/staging/batman-adv/aggregation.c
@@ -96,6 +96,7 @@
 			   int own_packet)
 {
 	struct forw_packet *forw_packet_aggr;
+	unsigned long flags;
 
 	forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
 	if (!forw_packet_aggr)
@@ -115,6 +116,7 @@
 	       packet_buff,
 	       forw_packet_aggr->packet_len);
 
+	forw_packet_aggr->skb = NULL;
 	forw_packet_aggr->own = own_packet;
 	forw_packet_aggr->if_incoming = if_incoming;
 	forw_packet_aggr->num_packets = 0;
@@ -126,9 +128,9 @@
 		forw_packet_aggr->direct_link_flags |= 1;
 
 	/* add new packet to packet list */
-	spin_lock(&forw_bat_list_lock);
+	spin_lock_irqsave(&forw_bat_list_lock, flags);
 	hlist_add_head(&forw_packet_aggr->list, &forw_bat_list);
-	spin_unlock(&forw_bat_list_lock);
+	spin_unlock_irqrestore(&forw_bat_list_lock, flags);
 
 	/* start timer for this packet */
 	INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
@@ -168,9 +170,10 @@
 	struct batman_packet *batman_packet =
 		(struct batman_packet *)packet_buff;
 	bool direct_link = batman_packet->flags & DIRECTLINK ? 1 : 0;
+	unsigned long flags;
 
 	/* find position for the packet in the forward queue */
-	spin_lock(&forw_bat_list_lock);
+	spin_lock_irqsave(&forw_bat_list_lock, flags);
 	/* own packets are not to be aggregated */
 	if ((atomic_read(&aggregation_enabled)) && (!own_packet)) {
 		hlist_for_each_entry(forw_packet_pos, tmp_node, &forw_bat_list,
@@ -191,7 +194,7 @@
 	 * suitable aggregation packet found */
 	if (forw_packet_aggr == NULL) {
 		/* the following section can run without the lock */
-		spin_unlock(&forw_bat_list_lock);
+		spin_unlock_irqrestore(&forw_bat_list_lock, flags);
 		new_aggregated_packet(packet_buff, packet_len,
 				      send_time, direct_link,
 				      if_incoming, own_packet);
@@ -199,7 +202,7 @@
 		aggregate(forw_packet_aggr,
 			  packet_buff, packet_len,
 			  direct_link);
-		spin_unlock(&forw_bat_list_lock);
+		spin_unlock_irqrestore(&forw_bat_list_lock, flags);
 	}
 }
 
diff --git a/drivers/staging/batman-adv/bitarray.c b/drivers/staging/batman-adv/bitarray.c
index 3c67f5f..212eef9 100644
--- a/drivers/staging/batman-adv/bitarray.c
+++ b/drivers/staging/batman-adv/bitarray.c
@@ -21,7 +21,6 @@
 
 #include "main.h"
 #include "bitarray.h"
-#include "log.h"
 
 /* returns true if the corresponding bit in the given seq_bits indicates true
  * and curr_seqno is within range of last_seqno */
@@ -80,8 +79,8 @@
 		 * from.
 		 *
 		 * left is high, right is low: FEDC BA98 7654 3210
-		 *	                                  ^^ ^^
-		 *                             vvvv
+		 *					  ^^ ^^
+		 *			       vvvv
 		 * ^^^^ = from, vvvvv =to, we'd have word_num==1 and
 		 * word_offset==WORD_BIT_SIZE/2 ????? in this example.
 		 * (=24 bits)
@@ -133,13 +132,13 @@
 	    (seq_num_diff < -TQ_LOCAL_WINDOW_SIZE)) {
 
 		if (seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
-			debug_log(LOG_TYPE_BATMAN,
-				  "We missed a lot of packets (%i) !\n",
-				  seq_num_diff-1);
+			bat_dbg(DBG_BATMAN,
+				"We missed a lot of packets (%i) !\n",
+				seq_num_diff-1);
 
 		if (-seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
-			debug_log(LOG_TYPE_BATMAN,
-				  "Other host probably restarted !\n");
+			bat_dbg(DBG_BATMAN,
+				"Other host probably restarted !\n");
 
 		for (i = 0; i < NUM_WORDS; i++)
 			seq_bits[i] = 0;
diff --git a/drivers/staging/batman-adv/compat.h b/drivers/staging/batman-adv/compat.h
deleted file mode 100644
index f4e0a45..0000000
--- a/drivers/staging/batman-adv/compat.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
- *
- * Marek Lindner, Simon Wunderlich
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- *
- *
- * This file contains macros for maintaining compatibility with older versions
- * of the Linux kernel.
- */
-
-#include <linux/version.h>	/* LINUX_VERSION_CODE */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
-
-#define skb_set_network_header(_skb, _offset) \
-	do { (_skb)->nh.raw = (_skb)->data + (_offset); } while (0)
-
-#define skb_reset_mac_header(_skb) \
-	do { (_skb)->mac.raw = (_skb)->data; } while (0)
-
-#define list_first_entry(ptr, type, member) \
-	list_entry((ptr)->next, type, member)
-
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) */
-
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
-
-#define device_create(_cls, _parent, _devt, _device, _fmt) \
-	class_device_create(_cls, _parent, _devt, _device, _fmt)
-
-#define device_destroy(_cls, _device) \
-	class_device_destroy(_cls, _device)
-
-#else
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
-
-#define device_create(_cls, _parent, _devt, _device, _fmt) \
-	device_create_drvdata(_cls, _parent, _devt, _device, _fmt)
-
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) */
-
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
-
-#define cancel_delayed_work_sync(wq) cancel_rearming_delayed_work(wq)
-
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
-#define strict_strtoul(cp, base, res) \
-	({ \
-	int ret = 0; \
-	char *endp; \
-	*res = simple_strtoul(cp, &endp, base); \
-	if (cp == endp) \
-		ret = -EINVAL; \
-	ret; \
-})
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c
index 1e7d1f8..e7f4421 100644
--- a/drivers/staging/batman-adv/device.c
+++ b/drivers/staging/batman-adv/device.c
@@ -19,14 +19,13 @@
  *
  */
 
+#include <linux/device.h>
 #include "main.h"
 #include "device.h"
-#include "log.h"
 #include "send.h"
 #include "types.h"
 #include "hash.h"
-
-#include "compat.h"
+#include "hard-interface.h"
 
 static struct class *batman_class;
 
@@ -60,7 +59,7 @@
 	/* register our device - kernel assigns a free major number */
 	tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops);
 	if (tmp_major < 0) {
-		debug_log(LOG_TYPE_WARN, "Registering the character device failed with %d\n",
+		printk(KERN_ERR "batman-adv:Registering the character device failed with %d\n",
 			  tmp_major);
 		return 0;
 	}
@@ -68,7 +67,7 @@
 	batman_class = class_create(THIS_MODULE, "batman-adv");
 
 	if (IS_ERR(batman_class)) {
-		debug_log(LOG_TYPE_WARN, "Could not register class 'batman-adv' \n");
+		printk(KERN_ERR "batman-adv:Could not register class 'batman-adv' \n");
 		return 0;
 	}
 
@@ -111,7 +110,7 @@
 	}
 
 	if (device_client_hash[i] != device_client) {
-		debug_log(LOG_TYPE_WARN, "Error - can't add another packet client: maximum number of clients reached \n");
+		printk(KERN_ERR "batman-adv:Error - can't add another packet client: maximum number of clients reached \n");
 		kfree(device_client);
 		return -EXFULL;
 	}
@@ -119,7 +118,7 @@
 	INIT_LIST_HEAD(&device_client->queue_list);
 	device_client->queue_len = 0;
 	device_client->index = i;
-	device_client->lock = __SPIN_LOCK_UNLOCKED(device_client->lock);
+	spin_lock_init(&device_client->lock);
 	init_waitqueue_head(&device_client->queue_wait);
 
 	file->private_data = device_client;
@@ -134,8 +133,9 @@
 		(struct device_client *)file->private_data;
 	struct device_packet *device_packet;
 	struct list_head *list_pos, *list_pos_tmp;
+	unsigned long flags;
 
-	spin_lock(&device_client->lock);
+	spin_lock_irqsave(&device_client->lock, flags);
 
 	/* for all packets in the queue ... */
 	list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) {
@@ -147,7 +147,7 @@
 	}
 
 	device_client_hash[device_client->index] = NULL;
-	spin_unlock(&device_client->lock);
+	spin_unlock_irqrestore(&device_client->lock, flags);
 
 	kfree(device_client);
 	dec_module_count();
@@ -162,6 +162,7 @@
 		(struct device_client *)file->private_data;
 	struct device_packet *device_packet;
 	int error;
+	unsigned long flags;
 
 	if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0))
 		return -EAGAIN;
@@ -178,14 +179,14 @@
 	if (error)
 		return error;
 
-	spin_lock(&device_client->lock);
+	spin_lock_irqsave(&device_client->lock, flags);
 
 	device_packet = list_first_entry(&device_client->queue_list,
 					 struct device_packet, list);
 	list_del(&device_packet->list);
 	device_client->queue_len--;
 
-	spin_unlock(&device_client->lock);
+	spin_unlock_irqrestore(&device_client->lock, flags);
 
 	error = __copy_to_user(buf, &device_packet->icmp_packet,
 			       sizeof(struct icmp_packet));
@@ -206,9 +207,11 @@
 	struct icmp_packet icmp_packet;
 	struct orig_node *orig_node;
 	struct batman_if *batman_if;
+	uint8_t dstaddr[ETH_ALEN];
+	unsigned long flags;
 
 	if (len < sizeof(struct icmp_packet)) {
-		debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: invalid packet size\n");
+		bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: invalid packet size\n");
 		return -EINVAL;
 	}
 
@@ -219,12 +222,12 @@
 		return -EFAULT;
 
 	if (icmp_packet.packet_type != BAT_ICMP) {
-		debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
+		bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
 		return -EINVAL;
 	}
 
 	if (icmp_packet.msg_type != ECHO_REQUEST) {
-		debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n");
+		bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n");
 		return -EINVAL;
 	}
 
@@ -240,7 +243,7 @@
 	if (atomic_read(&module_state) != MODULE_ACTIVE)
 		goto dst_unreach;
 
-	spin_lock(&orig_hash_lock);
+	spin_lock_irqsave(&orig_hash_lock, flags);
 	orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst));
 
 	if (!orig_node)
@@ -250,9 +253,15 @@
 		goto unlock;
 
 	batman_if = orig_node->batman_if;
+	memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
 
 	if (!batman_if)
-		goto unlock;
+		goto dst_unreach;
+
+	if (batman_if->if_active != IF_ACTIVE)
+		goto dst_unreach;
 
 	memcpy(icmp_packet.orig,
 	       batman_if->net_dev->dev_addr,
@@ -260,13 +269,12 @@
 
 	send_raw_packet((unsigned char *)&icmp_packet,
 			sizeof(struct icmp_packet),
-			batman_if, orig_node->router->addr);
+			batman_if, dstaddr);
 
-	spin_unlock(&orig_hash_lock);
 	goto out;
 
 unlock:
-	spin_unlock(&orig_hash_lock);
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
 dst_unreach:
 	icmp_packet.msg_type = DESTINATION_UNREACHABLE;
 	bat_device_add_packet(device_client, &icmp_packet);
@@ -291,6 +299,7 @@
 			   struct icmp_packet *icmp_packet)
 {
 	struct device_packet *device_packet;
+	unsigned long flags;
 
 	device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL);
 
@@ -301,12 +310,12 @@
 	memcpy(&device_packet->icmp_packet, icmp_packet,
 	       sizeof(struct icmp_packet));
 
-	spin_lock(&device_client->lock);
+	spin_lock_irqsave(&device_client->lock, flags);
 
 	/* while waiting for the lock the device_client could have been
 	 * deleted */
 	if (!device_client_hash[icmp_packet->uid]) {
-		spin_unlock(&device_client->lock);
+		spin_unlock_irqrestore(&device_client->lock, flags);
 		kfree(device_packet);
 		return;
 	}
@@ -323,7 +332,7 @@
 		device_client->queue_len--;
 	}
 
-	spin_unlock(&device_client->lock);
+	spin_unlock_irqrestore(&device_client->lock, flags);
 
 	wake_up(&device_client->queue_wait);
 }
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c
index 5ea35da..befd488 100644
--- a/drivers/staging/batman-adv/hard-interface.c
+++ b/drivers/staging/batman-adv/hard-interface.c
@@ -21,13 +21,11 @@
 
 #include "main.h"
 #include "hard-interface.h"
-#include "log.h"
 #include "soft-interface.h"
 #include "send.h"
 #include "translation-table.h"
 #include "routing.h"
 #include "hash.h"
-#include "compat.h"
 
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
 
@@ -75,7 +73,6 @@
 static void check_known_mac_addr(uint8_t *addr)
 {
 	struct batman_if *batman_if;
-	char mac_string[ETH_STR_LEN];
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(batman_if, &if_list, list) {
@@ -86,10 +83,9 @@
 		if (!compare_orig(batman_if->net_dev->dev_addr, addr))
 			continue;
 
-		addr_to_string(mac_string, addr);
-		debug_log(LOG_TYPE_WARN, "The newly added mac address (%s) already exists on: %s\n",
-		          mac_string, batman_if->dev);
-		debug_log(LOG_TYPE_WARN, "It is strongly recommended to keep mac addresses unique to avoid problems!\n");
+		printk(KERN_WARNING "batman-adv:The newly added mac address (%pM) already exists on: %s\n",
+		       addr, batman_if->dev);
+		printk(KERN_WARNING "batman-adv:It is strongly recommended to keep mac addresses unique to avoid problems!\n");
 	}
 	rcu_read_unlock();
 }
@@ -154,9 +150,6 @@
 	if (batman_if->if_active != IF_ACTIVE)
 		return;
 
-	if (batman_if->raw_sock)
-		sock_release(batman_if->raw_sock);
-
 	/**
 	 * batman_if->net_dev has been acquired by dev_get_by_name() in
 	 * proc_interfaces_write() and has to be unreferenced.
@@ -165,22 +158,16 @@
 	if (batman_if->net_dev)
 		dev_put(batman_if->net_dev);
 
-	batman_if->raw_sock = NULL;
-	batman_if->net_dev = NULL;
-
 	batman_if->if_active = IF_INACTIVE;
 	active_ifs--;
 
-	debug_log(LOG_TYPE_NOTICE, "Interface deactivated: %s\n",
-	          batman_if->dev);
+	printk(KERN_INFO "batman-adv:Interface deactivated: %s\n",
+		  batman_if->dev);
 }
 
 /* (re)activate given interface. */
 static void hardif_activate_interface(struct batman_if *batman_if)
 {
-	struct sockaddr_ll bind_addr;
-	int retval;
-
 	if (batman_if->if_active != IF_INACTIVE)
 		return;
 
@@ -192,35 +179,8 @@
 	if (!batman_if->net_dev)
 		goto dev_err;
 
-	retval = sock_create_kern(PF_PACKET, SOCK_RAW,
-				  __constant_htons(ETH_P_BATMAN),
-				  &batman_if->raw_sock);
-
-	if (retval < 0) {
-		debug_log(LOG_TYPE_WARN, "Can't create raw socket: %i\n",
-			  retval);
-		goto sock_err;
-	}
-
-	bind_addr.sll_family = AF_PACKET;
-	bind_addr.sll_ifindex = batman_if->net_dev->ifindex;
-	bind_addr.sll_protocol = 0;	/* is set by the kernel */
-
-	retval = kernel_bind(batman_if->raw_sock,
-			     (struct sockaddr *)&bind_addr, sizeof(bind_addr));
-
-	if (retval < 0) {
-		debug_log(LOG_TYPE_WARN, "Can't create bind raw socket: %i\n",
-			  retval);
-		goto bind_err;
-	}
-
 	check_known_mac_addr(batman_if->net_dev->dev_addr);
 
-	batman_if->raw_sock->sk->sk_user_data =
-		batman_if->raw_sock->sk->sk_data_ready;
-	batman_if->raw_sock->sk->sk_data_ready = batman_data_ready;
-
 	addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
 
 	memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
@@ -235,17 +195,12 @@
 	if (batman_if->if_num == 0)
 		set_main_if_addr(batman_if->net_dev->dev_addr);
 
-	debug_log(LOG_TYPE_NOTICE, "Interface activated: %s\n",
-	          batman_if->dev);
+	printk(KERN_INFO "batman-adv:Interface activated: %s\n",
+		  batman_if->dev);
 
 	return;
 
-bind_err:
-	sock_release(batman_if->raw_sock);
-sock_err:
-	dev_put(batman_if->net_dev);
 dev_err:
-	batman_if->raw_sock = NULL;
 	batman_if->net_dev = NULL;
 }
 
@@ -290,7 +245,7 @@
 	data_ptr = kmalloc((if_num + 1) * sizeof(TYPE_OF_WORD) * NUM_WORDS,
 			   GFP_ATOMIC);
 	if (!data_ptr) {
-		debug_log(LOG_TYPE_WARN, "Can't resize orig: out of memory\n");
+		printk(KERN_ERR "batman-adv:Can't resize orig: out of memory\n");
 		return -1;
 	}
 
@@ -301,7 +256,7 @@
 
 	data_ptr = kmalloc((if_num + 1) * sizeof(uint8_t), GFP_ATOMIC);
 	if (!data_ptr) {
-		debug_log(LOG_TYPE_WARN, "Can't resize orig: out of memory\n");
+		printk(KERN_ERR "batman-adv:Can't resize orig: out of memory\n");
 		return -1;
 	}
 
@@ -319,16 +274,16 @@
 	struct batman_if *batman_if;
 	struct batman_packet *batman_packet;
 	struct orig_node *orig_node;
-	struct hash_it_t *hashit = NULL;
+	unsigned long flags;
+	HASHIT(hashit);
 
 	batman_if = kmalloc(sizeof(struct batman_if), GFP_KERNEL);
 
 	if (!batman_if) {
-		debug_log(LOG_TYPE_WARN, "Can't add interface (%s): out of memory\n", dev);
+		printk(KERN_ERR "batman-adv:Can't add interface (%s): out of memory\n", dev);
 		return -1;
 	}
 
-	batman_if->raw_sock = NULL;
 	batman_if->net_dev = NULL;
 
 	if ((if_num == 0) && (num_hna > 0))
@@ -339,7 +294,7 @@
 	batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_KERNEL);
 
 	if (!batman_if->packet_buff) {
-		debug_log(LOG_TYPE_WARN, "Can't add interface packet (%s): out of memory\n", dev);
+		printk(KERN_ERR "batman-adv:Can't add interface packet (%s): out of memory\n", dev);
 		goto out;
 	}
 
@@ -348,7 +303,7 @@
 	batman_if->if_active = IF_INACTIVE;
 	INIT_RCU_HEAD(&batman_if->rcu);
 
-	debug_log(LOG_TYPE_NOTICE, "Adding interface: %s\n", dev);
+	printk(KERN_INFO "batman-adv:Adding interface: %s\n", dev);
 	avail_ifs++;
 
 	INIT_LIST_HEAD(&batman_if->list);
@@ -376,20 +331,20 @@
 
 	/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
 	 * if_num */
-	spin_lock(&orig_hash_lock);
+	spin_lock_irqsave(&orig_hash_lock, flags);
 
-	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
-		orig_node = hashit->bucket->data;
+	while (hash_iterate(orig_hash, &hashit)) {
+		orig_node = hashit.bucket->data;
 		if (resize_orig(orig_node, if_num) == -1) {
-			spin_unlock(&orig_hash_lock);
+			spin_unlock_irqrestore(&orig_hash_lock, flags);
 			goto out;
 		}
 	}
 
-	spin_unlock(&orig_hash_lock);
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
 
 	if (!hardif_is_interface_up(batman_if->dev))
-		debug_log(LOG_TYPE_WARN, "Not using interface %s (retrying later): interface not active\n", batman_if->dev);
+		printk(KERN_ERR "batman-adv:Not using interface %s (retrying later): interface not active\n", batman_if->dev);
 	else
 		hardif_activate_interface(batman_if);
 
@@ -400,8 +355,7 @@
 	return 1;
 
 out:
-	if (batman_if->packet_buff)
-		kfree(batman_if->packet_buff);
+	kfree(batman_if->packet_buff);
 	kfree(batman_if);
 	kfree(dev);
 	return -1;
@@ -413,7 +367,7 @@
 }
 
 static int hard_if_event(struct notifier_block *this,
-                            unsigned long event, void *ptr)
+			    unsigned long event, void *ptr)
 {
 	struct net_device *dev = (struct net_device *)ptr;
 	struct batman_if *batman_if = get_batman_if_by_name(dev->name);
@@ -436,7 +390,6 @@
 		break;
 	/* NETDEV_CHANGEADDR - mac address change - what are we doing here ? */
 	default:
-		/* debug_log(LOG_TYPE_CRIT, "hard_if_event: %s %i\n", dev->name, event); */
 		break;
 	};
 
@@ -446,6 +399,122 @@
 	return NOTIFY_DONE;
 }
 
+/* find batman interface by netdev. assumes rcu_read_lock on */
+static struct batman_if *find_batman_if(struct net_device *dev)
+{
+	struct batman_if *batman_if;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(batman_if, &if_list, list) {
+		if (batman_if->net_dev == dev) {
+			rcu_read_unlock();
+			return batman_if;
+		}
+	}
+	rcu_read_unlock();
+	return NULL;
+}
+
+
+/* receive a packet with the batman ethertype coming on a hard
+ * interface */
+int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
+	struct packet_type *ptype, struct net_device *orig_dev)
+{
+	struct batman_packet *batman_packet;
+	struct batman_if *batman_if;
+	struct net_device_stats *stats;
+	int ret;
+
+	skb = skb_share_check(skb, GFP_ATOMIC);
+
+	/* skb was released by skb_share_check() */
+	if (!skb)
+		goto err_out;
+
+	if (atomic_read(&module_state) != MODULE_ACTIVE)
+		goto err_free;
+
+	/* packet should hold at least type and version */
+	if (unlikely(skb_headlen(skb) < 2))
+		goto err_free;
+
+	/* expect a valid ethernet header here. */
+	if (unlikely(skb->mac_len != sizeof(struct ethhdr)
+				|| !skb_mac_header(skb)))
+		goto err_free;
+
+	batman_if = find_batman_if(skb->dev);
+	if (!batman_if)
+		goto err_free;
+
+	/* discard frames on not active interfaces */
+	if (batman_if->if_active != IF_ACTIVE)
+		goto err_free;
+
+	stats = (struct net_device_stats *)dev_get_stats(skb->dev);
+	if (stats) {
+		stats->rx_packets++;
+		stats->rx_bytes += skb->len;
+	}
+
+	batman_packet = (struct batman_packet *)skb->data;
+
+	if (batman_packet->version != COMPAT_VERSION) {
+		bat_dbg(DBG_BATMAN,
+			"Drop packet: incompatible batman version (%i)\n",
+			batman_packet->version);
+		goto err_free;
+	}
+
+	/* all receive handlers return whether they received or reused
+	 * the supplied skb. if not, we have to free the skb. */
+
+	switch (batman_packet->packet_type) {
+		/* batman originator packet */
+	case BAT_PACKET:
+		ret = recv_bat_packet(skb, batman_if);
+		break;
+
+		/* batman icmp packet */
+	case BAT_ICMP:
+		ret = recv_icmp_packet(skb);
+		break;
+
+		/* unicast packet */
+	case BAT_UNICAST:
+		ret = recv_unicast_packet(skb);
+		break;
+
+		/* broadcast packet */
+	case BAT_BCAST:
+		ret = recv_bcast_packet(skb);
+		break;
+
+		/* vis packet */
+	case BAT_VIS:
+		ret = recv_vis_packet(skb);
+		break;
+	default:
+		ret = NET_RX_DROP;
+	}
+
+	if (ret == NET_RX_DROP)
+		kfree_skb(skb);
+
+	/* return NET_RX_SUCCESS in any case as we
+	 * most probably dropped the packet for
+	 * routing-logical reasons. */
+
+	return NET_RX_SUCCESS;
+
+err_free:
+	kfree_skb(skb);
+err_out:
+	return NET_RX_DROP;
+}
+
+
 struct notifier_block hard_if_notifier = {
-        .notifier_call = hard_if_event,
+	.notifier_call = hard_if_event,
 };
diff --git a/drivers/staging/batman-adv/hard-interface.h b/drivers/staging/batman-adv/hard-interface.h
index 742358c..97c6ecb 100644
--- a/drivers/staging/batman-adv/hard-interface.h
+++ b/drivers/staging/batman-adv/hard-interface.h
@@ -32,5 +32,9 @@
 char hardif_get_active_if_num(void);
 void hardif_check_interfaces_status(void);
 void hardif_check_interfaces_status_wq(struct work_struct *work);
+int batman_skb_recv(struct sk_buff *skb,
+				struct net_device *dev,
+				struct packet_type *ptype,
+				struct net_device *orig_dev);
 int hardif_min_mtu(void);
 void update_min_mtu(void);
diff --git a/drivers/staging/batman-adv/hash.c b/drivers/staging/batman-adv/hash.c
index 61cb4a2..5a2018d 100644
--- a/drivers/staging/batman-adv/hash.c
+++ b/drivers/staging/batman-adv/hash.c
@@ -64,24 +64,18 @@
 	kfree(hash);
 }
 
-/* iterate though the hash. first element is selected with iter_in NULL.  use
- * the returned iterator to access the elements until hash_it_t returns NULL. */
-struct hash_it_t *hash_iterate(struct hashtable_t *hash,
-			       struct hash_it_t *iter_in)
-{
-	struct hash_it_t *iter;
+/* iterate though the hash. First element is selected if an iterator
+ * initialized with HASHIT() is supplied as iter. Use the returned
+ * (or supplied) iterator to access the elements until hash_iterate returns
+ * NULL. */
 
+struct hash_it_t *hash_iterate(struct hashtable_t *hash,
+			       struct hash_it_t *iter)
+{
 	if (!hash)
 		return NULL;
-
-	if (iter_in == NULL) {
-		iter = kmalloc(sizeof(struct hash_it_t), GFP_ATOMIC);
-		iter->index = -1;
-		iter->bucket = NULL;
-		iter->prev_bucket = NULL;
-	} else {
-		iter = iter_in;
-	}
+	if (!iter)
+		return NULL;
 
 	/* sanity checks first (if our bucket got deleted in the last
 	 * iteration): */
@@ -139,7 +133,6 @@
 	}
 
 	/* nothing to iterate over anymore */
-	kfree(iter);
 	return NULL;
 }
 
diff --git a/drivers/staging/batman-adv/hash.h b/drivers/staging/batman-adv/hash.h
index bb60f08..a70d6d6 100644
--- a/drivers/staging/batman-adv/hash.h
+++ b/drivers/staging/batman-adv/hash.h
@@ -21,6 +21,11 @@
 
 #ifndef _BATMAN_HASH_H
 #define _BATMAN_HASH_H
+#define HASHIT(name) struct hash_it_t name = { \
+		.index = -1, .bucket = NULL, \
+		.prev_bucket = NULL, \
+		.first_bucket = NULL }
+
 
 typedef int (*hashdata_compare_cb)(void *, void *);
 typedef int (*hashdata_choose_cb)(void *, int);
diff --git a/drivers/staging/batman-adv/log.c b/drivers/staging/batman-adv/log.c
deleted file mode 100644
index f37c7f0..0000000
--- a/drivers/staging/batman-adv/log.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
- *
- * Marek Lindner, Simon Wunderlich
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- *
- */
-
-#include "main.h"
-#include "log.h"
-
-#define LOG_BUF_MASK (log_buf_len-1)
-#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
-
-static char log_buf[LOG_BUF_LEN];
-static int log_buf_len = LOG_BUF_LEN;
-static unsigned long log_start;
-static unsigned long log_end;
-uint8_t log_level;
-
-static DEFINE_SPINLOCK(logbuf_lock);
-
-const struct file_operations proc_log_operations = {
-	.open           = log_open,
-	.release        = log_release,
-	.read           = log_read,
-	.write          = log_write,
-	.poll           = log_poll,
-};
-
-static DECLARE_WAIT_QUEUE_HEAD(log_wait);
-
-static void emit_log_char(char c)
-{
-	LOG_BUF(log_end) = c;
-	log_end++;
-
-	if (log_end - log_start > log_buf_len)
-		log_start = log_end - log_buf_len;
-}
-
-static int fdebug_log(char *fmt, ...)
-{
-	int printed_len;
-	char *p;
-	va_list args;
-	static char debug_log_buf[256];
-	unsigned long flags;
-
-	spin_lock_irqsave(&logbuf_lock, flags);
-	va_start(args, fmt);
-	printed_len = vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt,
-				 args);
-	va_end(args);
-
-	for (p = debug_log_buf; *p != 0; p++)
-		emit_log_char(*p);
-
-	spin_unlock_irqrestore(&logbuf_lock, flags);
-
-	wake_up(&log_wait);
-
-	return 0;
-}
-
-int debug_log(int type, char *fmt, ...)
-{
-	va_list args;
-	int retval = 0;
-	char tmp_log_buf[256];
-
-	/* only critical information get into the official kernel log */
-	if (type == LOG_TYPE_CRIT) {
-		va_start(args, fmt);
-		vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
-		printk(KERN_ERR "batman-adv: %s", tmp_log_buf);
-		va_end(args);
-	}
-
-	if ((type == LOG_TYPE_CRIT) || (log_level & type)) {
-		va_start(args, fmt);
-		vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
-		fdebug_log("[%10u] %s", (jiffies / HZ), tmp_log_buf);
-		va_end(args);
-	}
-
-	return retval;
-}
-
-int log_open(struct inode *inode, struct file *file)
-{
-	inc_module_count();
-	return 0;
-}
-
-int log_release(struct inode *inode, struct file *file)
-{
-	dec_module_count();
-	return 0;
-}
-
-ssize_t log_read(struct file *file, char __user *buf, size_t count,
-		 loff_t *ppos)
-{
-	int error, i = 0;
-	char c;
-	unsigned long flags;
-
-	if ((file->f_flags & O_NONBLOCK) && !(log_end - log_start))
-		return -EAGAIN;
-
-	if ((!buf) || (count < 0))
-		return -EINVAL;
-
-	if (count == 0)
-		return 0;
-
-	if (!access_ok(VERIFY_WRITE, buf, count))
-		return -EFAULT;
-
-	error = wait_event_interruptible(log_wait, (log_start - log_end));
-
-	if (error)
-		return error;
-
-	spin_lock_irqsave(&logbuf_lock, flags);
-
-	while ((!error) && (log_start != log_end) && (i < count)) {
-		c = LOG_BUF(log_start);
-
-		log_start++;
-
-		spin_unlock_irqrestore(&logbuf_lock, flags);
-
-		error = __put_user(c, buf);
-
-		spin_lock_irqsave(&logbuf_lock, flags);
-
-		buf++;
-		i++;
-
-	}
-
-	spin_unlock_irqrestore(&logbuf_lock, flags);
-
-	if (!error)
-		return i;
-
-	return error;
-}
-
-ssize_t log_write(struct file *file, const char __user *buf, size_t count,
-		  loff_t *ppos)
-{
-	return count;
-}
-
-unsigned int log_poll(struct file *file, poll_table *wait)
-{
-	poll_wait(file, &log_wait, wait);
-
-	if (log_end - log_start)
-		return POLLIN | POLLRDNORM;
-
-	return 0;
-}
diff --git a/drivers/staging/batman-adv/log.h b/drivers/staging/batman-adv/log.h
deleted file mode 100644
index 780e3ab..0000000
--- a/drivers/staging/batman-adv/log.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
- *
- * Marek Lindner, Simon Wunderlich
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- *
- */
-
-extern const struct file_operations proc_log_operations;
-extern uint8_t log_level;
-
-int debug_log(int type, char *fmt, ...);
-int log_open(struct inode *inode, struct file *file);
-int log_release(struct inode *inode, struct file *file);
-ssize_t log_read(struct file *file, char __user *buf, size_t count,
-		 loff_t *ppos);
-ssize_t log_write(struct file *file, const char __user *buf, size_t count,
-		  loff_t *ppos);
-unsigned int log_poll(struct file *file, poll_table *wait);
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c
index bb89bfc..2e0b482 100644
--- a/drivers/staging/batman-adv/main.c
+++ b/drivers/staging/batman-adv/main.c
@@ -21,9 +21,9 @@
 
 #include "main.h"
 #include "proc.h"
-#include "log.h"
 #include "routing.h"
 #include "send.h"
+#include "originator.h"
 #include "soft-interface.h"
 #include "device.h"
 #include "translation-table.h"
@@ -31,7 +31,6 @@
 #include "types.h"
 #include "vis.h"
 #include "hash.h"
-#include "compat.h"
 
 struct list_head if_list;
 struct hlist_head forw_bat_list;
@@ -44,19 +43,34 @@
 
 atomic_t originator_interval;
 atomic_t vis_interval;
+atomic_t vis_mode;
 atomic_t aggregation_enabled;
 int16_t num_hna;
 int16_t num_ifs;
 
 struct net_device *soft_device;
 
-static struct task_struct *kthread_task;
-
 unsigned char broadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 atomic_t module_state;
 
+static struct packet_type batman_adv_packet_type __read_mostly = {
+	.type = __constant_htons(ETH_P_BATMAN),
+	.func = batman_skb_recv,
+};
+
 struct workqueue_struct *bat_event_workqueue;
 
+#ifdef CONFIG_BATMAN_ADV_DEBUG
+int debug;
+
+module_param(debug, int, 0644);
+
+int bat_debug_type(int type)
+{
+	return debug & type;
+}
+#endif
+
 int init_module(void)
 {
 	int retval;
@@ -70,6 +84,7 @@
 	atomic_set(&originator_interval, 1000);
 	atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only
 					 * for debugging now. */
+	atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE);
 	atomic_set(&aggregation_enabled, 1);
 
 	/* the name should not be longer than 10 chars - see
@@ -90,21 +105,22 @@
 				   interface_setup);
 
 	if (!soft_device) {
-		debug_log(LOG_TYPE_CRIT, "Unable to allocate the batman interface\n");
+		printk(KERN_ERR "batman-adv:Unable to allocate the batman interface\n");
 		goto end;
 	}
 
 	retval = register_netdev(soft_device);
 
 	if (retval < 0) {
-		debug_log(LOG_TYPE_CRIT, "Unable to register the batman interface: %i\n", retval);
+		printk(KERN_ERR "batman-adv:Unable to register the batman interface: %i\n", retval);
 		goto free_soft_device;
 	}
 
 	register_netdevice_notifier(&hard_if_notifier);
+	dev_add_pack(&batman_adv_packet_type);
 
-	debug_log(LOG_TYPE_CRIT, "B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n",
-	          SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
+	printk(KERN_INFO "batman-adv:B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n",
+		  SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
 
 	return 0;
 
@@ -124,6 +140,8 @@
 		soft_device = NULL;
 	}
 
+	dev_remove_pack(&batman_adv_packet_type);
+
 	unregister_netdevice_notifier(&hard_if_notifier);
 	cleanup_procfs();
 
@@ -151,22 +169,12 @@
 	if (vis_init() < 1)
 		goto err;
 
-	/* (re)start kernel thread for packet processing */
-	if (!kthread_task) {
-		kthread_task = kthread_run(packet_recv_thread, NULL, "batman-adv");
-
-		if (IS_ERR(kthread_task)) {
-			debug_log(LOG_TYPE_CRIT, "Unable to start packet receive thread\n");
-			kthread_task = NULL;
-		}
-	}
-
 	update_min_mtu();
 	atomic_set(&module_state, MODULE_ACTIVE);
 	goto end;
 
 err:
-	debug_log(LOG_TYPE_CRIT, "Unable to allocate memory for mesh information structures: out of mem ?\n");
+	printk(KERN_ERR "batman-adv:Unable to allocate memory for mesh information structures: out of mem ?\n");
 	shutdown_module();
 end:
 	return;
@@ -182,14 +190,7 @@
 
 	vis_quit();
 
-	/* deactivate kernel thread for packet processing (if running) */
-	if (kthread_task) {
-		atomic_set(&exit_cond, 1);
-		wake_up_interruptible(&thread_wait);
-		kthread_stop(kthread_task);
-
-		kthread_task = NULL;
-	}
+	/* TODO: unregister BATMAN pack */
 
 	originator_free();
 
diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h
index facb6b7..deb41f5 100644
--- a/drivers/staging/batman-adv/main.h
+++ b/drivers/staging/batman-adv/main.h
@@ -33,16 +33,16 @@
 
 #define TQ_MAX_VALUE 255
 #define JITTER 20
-#define TTL 50		          /* Time To Live of broadcast messages */
-#define MAX_ADDR 16	          /* number of interfaces which can be added to
+#define TTL 50			  /* Time To Live of broadcast messages */
+#define MAX_ADDR 16		  /* number of interfaces which can be added to
 				   * batman. */
 
-#define PURGE_TIMEOUT 200000      /* purge originators after time in ms if no
+#define PURGE_TIMEOUT 200000	  /* purge originators after time in ms if no
 				   * valid packet comes in -> TODO: check
 				   * influence on TQ_LOCAL_WINDOW_SIZE */
 #define LOCAL_HNA_TIMEOUT 3600000
 
-#define TQ_LOCAL_WINDOW_SIZE 64   /* sliding packet range of received originator
+#define TQ_LOCAL_WINDOW_SIZE 64	  /* sliding packet range of received originator
 				   * messages in squence numbers (should be a
 				   * multiple of our word size) */
 #define TQ_GLOBAL_WINDOW_SIZE 5
@@ -69,24 +69,27 @@
 
 
 /*
- * Logging
+ * Debug Messages
  */
 
-#define LOG_TYPE_CRIT 0		/* highest priority for fatal errors such as
-				 * blocked sockets / failed packet delivery /
-				 * programming errors */
-#define LOG_TYPE_WARN 1		/* warnings for small errors like wrong user
-				 * input / damaged packets / etc */
-#define LOG_TYPE_NOTICE 2	/* notice information for new interfaces /
-				 * changed settings / new originators / etc */
-#define LOG_TYPE_BATMAN 4	/* all messages related to routing / flooding /
-				 * broadcasting / etc */
-#define LOG_TYPE_ROUTES 8	/* route or hna added / changed / deleted */
-#define LOG_TYPE_CRIT_NAME	"critical"
-#define LOG_TYPE_WARN_NAME	"warnings"
-#define LOG_TYPE_NOTICE_NAME	"notices"
-#define LOG_TYPE_BATMAN_NAME	"batman"
-#define LOG_TYPE_ROUTES_NAME	"routes"
+#define DBG_BATMAN 1	/* all messages related to routing / flooding /
+			 * broadcasting / etc */
+#define DBG_ROUTES 2	/* route or hna added / changed / deleted */
+
+#ifdef CONFIG_BATMAN_ADV_DEBUG
+extern int debug;
+
+extern int bat_debug_type(int type);
+#define bat_dbg(type, fmt, arg...) do {					\
+		if (bat_debug_type(type))				\
+			printk(KERN_DEBUG "batman-adv:" fmt, ## arg);	\
+	}								\
+	while (0)
+#else /* !CONFIG_BATMAN_ADV_DEBUG */
+#define bat_dbg(type, fmt, arg...) do {		\
+	}					\
+	while (0)
+#endif
 
 /*
  *  Vis
@@ -127,6 +130,7 @@
 
 extern atomic_t originator_interval;
 extern atomic_t vis_interval;
+extern atomic_t vis_mode;
 extern atomic_t aggregation_enabled;
 extern int16_t num_hna;
 extern int16_t num_ifs;
@@ -147,5 +151,3 @@
 int is_my_mac(uint8_t *addr);
 int is_bcast(uint8_t *addr);
 int is_mcast(uint8_t *addr);
-
-
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c
new file mode 100644
index 0000000..29c2411
--- /dev/null
+++ b/drivers/staging/batman-adv/originator.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+/* increase the reference counter for this originator */
+
+#include "main.h"
+#include "originator.h"
+#include "hash.h"
+#include "translation-table.h"
+#include "routing.h"
+
+static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
+
+static void start_purge_timer(void)
+{
+	queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ);
+}
+
+int originator_init(void)
+{
+	unsigned long flags;
+	if (orig_hash)
+		return 1;
+
+	spin_lock_irqsave(&orig_hash_lock, flags);
+	orig_hash = hash_new(128, compare_orig, choose_orig);
+
+	if (!orig_hash)
+		goto err;
+
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
+	start_purge_timer();
+	return 1;
+
+err:
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
+	return 0;
+}
+
+void originator_free(void)
+{
+	unsigned long flags;
+
+	if (!orig_hash)
+		return;
+
+	cancel_delayed_work_sync(&purge_orig_wq);
+
+	spin_lock_irqsave(&orig_hash_lock, flags);
+	hash_delete(orig_hash, free_orig_node);
+	orig_hash = NULL;
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
+}
+
+struct neigh_node *
+create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
+		uint8_t *neigh, struct batman_if *if_incoming)
+{
+	struct neigh_node *neigh_node;
+
+	bat_dbg(DBG_BATMAN, "Creating new last-hop neighbor of originator\n");
+
+	neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC);
+	if (!neigh_node)
+		return NULL;
+
+	INIT_LIST_HEAD(&neigh_node->list);
+
+	memcpy(neigh_node->addr, neigh, ETH_ALEN);
+	neigh_node->orig_node = orig_neigh_node;
+	neigh_node->if_incoming = if_incoming;
+
+	list_add_tail(&neigh_node->list, &orig_node->neigh_list);
+	return neigh_node;
+}
+
+void free_orig_node(void *data)
+{
+	struct list_head *list_pos, *list_pos_tmp;
+	struct neigh_node *neigh_node;
+	struct orig_node *orig_node = (struct orig_node *)data;
+
+	/* for all neighbors towards this originator ... */
+	list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
+		neigh_node = list_entry(list_pos, struct neigh_node, list);
+
+		list_del(list_pos);
+		kfree(neigh_node);
+	}
+
+	hna_global_del_orig(orig_node, "originator timed out");
+
+	kfree(orig_node->bcast_own);
+	kfree(orig_node->bcast_own_sum);
+	kfree(orig_node);
+}
+
+/* this function finds or creates an originator entry for the given
+ * address if it does not exits */
+struct orig_node *get_orig_node(uint8_t *addr)
+{
+	struct orig_node *orig_node;
+	struct hashtable_t *swaphash;
+	int size;
+
+	orig_node = ((struct orig_node *)hash_find(orig_hash, addr));
+
+	if (orig_node != NULL)
+		return orig_node;
+
+	bat_dbg(DBG_BATMAN, "Creating new originator: %pM \n", addr);
+
+	orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
+	if (!orig_node)
+		return NULL;
+
+	INIT_LIST_HEAD(&orig_node->neigh_list);
+
+	memcpy(orig_node->orig, addr, ETH_ALEN);
+	orig_node->router = NULL;
+	orig_node->batman_if = NULL;
+	orig_node->hna_buff = NULL;
+
+	size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS;
+
+	orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
+	if (!orig_node->bcast_own)
+		goto free_orig_node;
+
+	size = num_ifs * sizeof(uint8_t);
+	orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
+	if (!orig_node->bcast_own_sum)
+		goto free_bcast_own;
+
+	if (hash_add(orig_hash, orig_node) < 0)
+		goto free_bcast_own_sum;
+
+	if (orig_hash->elements * 4 > orig_hash->size) {
+		swaphash = hash_resize(orig_hash, orig_hash->size * 2);
+
+		if (swaphash == NULL)
+			printk(KERN_ERR
+			       "batman-adv:Couldn't resize orig hash table \n");
+		else
+			orig_hash = swaphash;
+	}
+
+	return orig_node;
+free_bcast_own_sum:
+	kfree(orig_node->bcast_own_sum);
+free_bcast_own:
+	kfree(orig_node->bcast_own);
+free_orig_node:
+	kfree(orig_node);
+	return NULL;
+}
+
+static bool purge_orig_neighbors(struct orig_node *orig_node,
+				 struct neigh_node **best_neigh_node)
+{
+	struct list_head *list_pos, *list_pos_tmp;
+	struct neigh_node *neigh_node;
+	bool neigh_purged = false;
+
+	*best_neigh_node = NULL;
+
+
+	/* for all neighbors towards this originator ... */
+	list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
+		neigh_node = list_entry(list_pos, struct neigh_node, list);
+
+		if (time_after(jiffies,
+			       (neigh_node->last_valid +
+				((PURGE_TIMEOUT * HZ) / 1000)))) {
+
+			bat_dbg(DBG_BATMAN, "neighbor timeout: originator %pM, neighbor: %pM, last_valid %lu\n", orig_node->orig, neigh_node->addr, (neigh_node->last_valid / HZ));
+
+			neigh_purged = true;
+			list_del(list_pos);
+			kfree(neigh_node);
+		} else {
+			if ((*best_neigh_node == NULL) ||
+			    (neigh_node->tq_avg > (*best_neigh_node)->tq_avg))
+				*best_neigh_node = neigh_node;
+		}
+	}
+	return neigh_purged;
+}
+
+
+static bool purge_orig_node(struct orig_node *orig_node)
+{
+	struct neigh_node *best_neigh_node;
+
+	if (time_after(jiffies,
+		       (orig_node->last_valid +
+			((2 * PURGE_TIMEOUT * HZ) / 1000)))) {
+
+		bat_dbg(DBG_BATMAN,
+			"Originator timeout: originator %pM, last_valid %lu\n",
+			orig_node->orig, (orig_node->last_valid / HZ));
+		return true;
+	} else {
+		if (purge_orig_neighbors(orig_node, &best_neigh_node))
+			update_routes(orig_node, best_neigh_node,
+				      orig_node->hna_buff,
+				      orig_node->hna_buff_len);
+	}
+	return false;
+}
+
+void purge_orig(struct work_struct *work)
+{
+	HASHIT(hashit);
+	struct orig_node *orig_node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&orig_hash_lock, flags);
+
+	/* for all origins... */
+	while (hash_iterate(orig_hash, &hashit)) {
+		orig_node = hashit.bucket->data;
+		if (purge_orig_node(orig_node)) {
+			hash_remove_bucket(orig_hash, &hashit);
+			free_orig_node(orig_node);
+		}
+	}
+
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+	start_purge_timer();
+}
+
+
diff --git a/drivers/staging/batman-adv/originator.h b/drivers/staging/batman-adv/originator.h
new file mode 100644
index 0000000..6ef7a05
--- /dev/null
+++ b/drivers/staging/batman-adv/originator.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+int originator_init(void);
+void free_orig_node(void *data);
+void originator_free(void);
+void purge_orig(struct work_struct *work);
+struct orig_node *orig_find(char *mac);
+struct orig_node *get_orig_node(uint8_t *addr);
+struct neigh_node *
+create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
+		uint8_t *neigh, struct batman_if *if_incoming);
+
diff --git a/drivers/staging/batman-adv/packet.h b/drivers/staging/batman-adv/packet.h
index 5627ca3..ad006ce 100644
--- a/drivers/staging/batman-adv/packet.h
+++ b/drivers/staging/batman-adv/packet.h
@@ -90,7 +90,7 @@
 	uint8_t  entries;	 /* number of entries behind this struct */
 	uint8_t  ttl;		 /* TTL */
 	uint8_t  vis_orig[6];	 /* originator that informs about its
-				  * neighbours */
+				  * neighbors */
 	uint8_t  target_orig[6]; /* who should receive this packet */
 	uint8_t  sender_orig[6]; /* who sent or rebroadcasted this packet */
 } __attribute__((packed));
diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c
index aac3df7..7de60e84 100644
--- a/drivers/staging/batman-adv/proc.c
+++ b/drivers/staging/batman-adv/proc.c
@@ -21,23 +21,18 @@
 
 #include "main.h"
 #include "proc.h"
-#include "log.h"
 #include "routing.h"
 #include "translation-table.h"
 #include "hard-interface.h"
 #include "types.h"
 #include "hash.h"
 #include "vis.h"
-#include "compat.h"
-
-static uint8_t vis_format = DOT_DRAW;
 
 static struct proc_dir_entry *proc_batman_dir, *proc_interface_file;
 static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file;
-static struct proc_dir_entry *proc_log_file, *proc_log_level_file;
 static struct proc_dir_entry *proc_transt_local_file;
 static struct proc_dir_entry *proc_transt_global_file;
-static struct proc_dir_entry *proc_vis_file, *proc_vis_format_file;
+static struct proc_dir_entry *proc_vis_srv_file, *proc_vis_data_file;
 static struct proc_dir_entry *proc_aggr_file;
 
 static int proc_interfaces_read(struct seq_file *seq, void *offset)
@@ -68,7 +63,7 @@
 				     size_t count, loff_t *data)
 {
 	char *if_string, *colon_ptr = NULL, *cr_ptr = NULL;
-	int not_copied = 0, if_num = 0;
+	int not_copied = 0, if_num = 0, add_success;
 	struct batman_if *batman_if = NULL;
 
 	if_string = kmalloc(count, GFP_KERNEL);
@@ -77,8 +72,7 @@
 		return -ENOMEM;
 
 	if (count > IFNAMSIZ - 1) {
-		debug_log(LOG_TYPE_WARN,
-			  "Can't add interface: device name is too long\n");
+		printk(KERN_WARNING "batman-adv:Can't add interface: device name is too long\n");
 		goto end;
 	}
 
@@ -105,7 +99,7 @@
 	rcu_read_lock();
 	list_for_each_entry_rcu(batman_if, &if_list, list) {
 		if (strncmp(batman_if->dev, if_string, count) == 0) {
-			debug_log(LOG_TYPE_WARN, "Given interface is already active: %s\n", if_string);
+			printk(KERN_ERR "batman-adv:Given interface is already active: %s\n", if_string);
 			rcu_read_unlock();
 			goto end;
 
@@ -115,22 +109,17 @@
 	}
 	rcu_read_unlock();
 
-	hardif_add_interface(if_string, if_num);
+	add_success = hardif_add_interface(if_string, if_num);
+	if (add_success < 0)
+		goto end;
+
+	num_ifs = if_num + 1;
 
 	if ((atomic_read(&module_state) == MODULE_INACTIVE) &&
 	    (hardif_get_active_if_num() > 0))
 		activate_module();
 
-	rcu_read_lock();
-	if (list_empty(&if_list)) {
-		rcu_read_unlock();
-		goto end;
-	}
-	rcu_read_unlock();
-
-	num_ifs = if_num + 1;
 	return count;
-
 end:
 	kfree(if_string);
 	return count;
@@ -162,20 +151,18 @@
 
 	retval = strict_strtoul(interval_string, 10, &originator_interval_tmp);
 	if (retval) {
-		debug_log(LOG_TYPE_WARN, "New originator interval invalid\n");
+		printk(KERN_ERR "batman-adv:New originator interval invalid\n");
 		goto end;
 	}
 
 	if (originator_interval_tmp <= JITTER * 2) {
-		debug_log(LOG_TYPE_WARN,
-			  "New originator interval too small: %i (min: %i)\n",
-			  originator_interval_tmp, JITTER * 2);
+		printk(KERN_WARNING "batman-adv:New originator interval too small: %li (min: %i)\n",
+		       originator_interval_tmp, JITTER * 2);
 		goto end;
 	}
 
-	debug_log(LOG_TYPE_NOTICE,
-		  "Changing originator interval from: %i to: %i\n",
-		  atomic_read(&originator_interval), originator_interval_tmp);
+	printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li\n",
+	       atomic_read(&originator_interval), originator_interval_tmp);
 
 	atomic_set(&originator_interval, originator_interval_tmp);
 
@@ -191,11 +178,12 @@
 
 static int proc_originators_read(struct seq_file *seq, void *offset)
 {
-	struct hash_it_t *hashit = NULL;
+	HASHIT(hashit);
 	struct orig_node *orig_node;
 	struct neigh_node *neigh_node;
 	int batman_count = 0;
 	char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
+	unsigned long flags;
 
 	rcu_read_lock();
 	if (list_empty(&if_list)) {
@@ -218,11 +206,11 @@
 		   ((struct batman_if *)if_list.next)->addr_str);
 
 	rcu_read_unlock();
-	spin_lock(&orig_hash_lock);
+	spin_lock_irqsave(&orig_hash_lock, flags);
 
-	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
+	while (hash_iterate(orig_hash, &hashit)) {
 
-		orig_node = hashit->bucket->data;
+		orig_node = hashit.bucket->data;
 
 		if (!orig_node->router)
 			continue;
@@ -249,7 +237,7 @@
 
 	}
 
-	spin_unlock(&orig_hash_lock);
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
 
 	if (batman_count == 0)
 		seq_printf(seq, "No batman nodes in range ... \n");
@@ -263,84 +251,6 @@
 	return single_open(file, proc_originators_read, NULL);
 }
 
-static int proc_log_level_read(struct seq_file *seq, void *offset)
-{
-
-	seq_printf(seq, "[x] %s (%d)\n", LOG_TYPE_CRIT_NAME, LOG_TYPE_CRIT);
-	seq_printf(seq, "[%c] %s (%d)\n",
-		   (LOG_TYPE_WARN & log_level) ? 'x' : ' ',
-		   LOG_TYPE_WARN_NAME, LOG_TYPE_WARN);
-	seq_printf(seq, "[%c] %s (%d)\n",
-		   (LOG_TYPE_NOTICE & log_level) ? 'x' : ' ',
-		   LOG_TYPE_NOTICE_NAME, LOG_TYPE_NOTICE);
-	seq_printf(seq, "[%c] %s (%d)\n",
-		   (LOG_TYPE_BATMAN & log_level) ? 'x' : ' ',
-		   LOG_TYPE_BATMAN_NAME, LOG_TYPE_BATMAN);
-	seq_printf(seq, "[%c] %s (%d)\n",
-		   (LOG_TYPE_ROUTES & log_level) ? 'x' : ' ',
-		   LOG_TYPE_ROUTES_NAME, LOG_TYPE_ROUTES);
-	return 0;
-}
-
-static int proc_log_level_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, proc_log_level_read, NULL);
-}
-
-static ssize_t proc_log_level_write(struct file *instance,
-				    const char __user *userbuffer,
-				    size_t count, loff_t *data)
-{
-	char *log_level_string, *tokptr, *cp;
-	int finished, not_copied = 0;
-	unsigned long log_level_tmp = 0;
-
-	log_level_string = kmalloc(count, GFP_KERNEL);
-
-	if (!log_level_string)
-		return -ENOMEM;
-
-	not_copied = copy_from_user(log_level_string, userbuffer, count);
-	log_level_string[count - not_copied - 1] = 0;
-
-	if (strict_strtoul(log_level_string, 10, &log_level_tmp) < 0) {
-		/* was not a number, doing textual parsing */
-		log_level_tmp = 0;
-		tokptr = log_level_string;
-
-		for (cp = log_level_string, finished = 0; !finished; cp++) {
-			switch (*cp) {
-			case 0:
-				finished = 1;
-			case ' ':
-			case '\n':
-			case '\t':
-				*cp = 0;
-				/* compare */
-				if (strcmp(tokptr, LOG_TYPE_WARN_NAME) == 0)
-					log_level_tmp |= LOG_TYPE_WARN;
-				if (strcmp(tokptr, LOG_TYPE_NOTICE_NAME) == 0)
-					log_level_tmp |= LOG_TYPE_NOTICE;
-				if (strcmp(tokptr, LOG_TYPE_BATMAN_NAME) == 0)
-					log_level_tmp |= LOG_TYPE_BATMAN;
-				if (strcmp(tokptr, LOG_TYPE_ROUTES_NAME) == 0)
-					log_level_tmp |= LOG_TYPE_ROUTES;
-				tokptr = cp + 1;
-				break;
-			default:
-				;
-			}
-		}
-	}
-
-	debug_log(LOG_TYPE_CRIT, "Changing log_level from: %i to: %i\n",
-		  log_level, log_level_tmp);
-	log_level = log_level_tmp;
-
-	kfree(log_level_string);
-	return count;
-}
-
 static int proc_transt_local_read(struct seq_file *seq, void *offset)
 {
 	char *buf;
@@ -405,172 +315,8 @@
 	return single_open(file, proc_transt_global_read, NULL);
 }
 
-/* insert interface to the list of interfaces of one originator */
-
-static void proc_vis_insert_interface(const uint8_t *interface,
-				      struct vis_if_list **if_entry,
-				      bool primary)
-{
-	/* Did we get an empty list? (then insert imediately) */
-	if(*if_entry == NULL) {
-		*if_entry = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL);
-		if (*if_entry == NULL)
-			return;
-
-		(*if_entry)->primary = primary;
-		(*if_entry)->next = NULL;
-		memcpy((*if_entry)->addr, interface, ETH_ALEN);
-	} else {
-		struct vis_if_list *head_if_entry = *if_entry;
-		/* Do we already have this interface in our list? */
-		while (!compare_orig((*if_entry)->addr, (void *)interface)) {
-
-			/* Or did we reach the end (then append the interface) */
-			if ((*if_entry)->next == NULL) {
-				(*if_entry)->next = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL);
-				if ((*if_entry)->next == NULL)
-					return;
-
-				memcpy((*if_entry)->next->addr, interface, ETH_ALEN);
-				(*if_entry)->next->primary = primary;
-				(*if_entry)->next->next = NULL;
-				break;
-			}
-			*if_entry = (*if_entry)->next;
-		}
-		/* Rewind the list to its head */
-		*if_entry = head_if_entry;
-	}
-}
-/* read an entry  */
-
-static void proc_vis_read_entry(struct seq_file *seq,
-				struct vis_info_entry *entry,
-				struct vis_if_list **if_entry,
-				uint8_t *vis_orig,
-				uint8_t current_format,
-				uint8_t first_line)
-{
-	char from[40];
-	char to[40];
-	int int_part, frac_part;
-
-	addr_to_string(to, entry->dest);
-	if (entry->quality == 0) {
-#ifndef VIS_SUBCLUSTERS_DISABLED
-		proc_vis_insert_interface(vis_orig, if_entry, true);
-#endif /* VIS_SUBCLUSTERS_DISABLED */
-		addr_to_string(from, vis_orig);
-		if (current_format == DOT_DRAW) {
-			seq_printf(seq, "\t\"%s\" -> \"%s\" [label=\"HNA\"]\n",
-				   from, to);
-		} else {
-			seq_printf(seq,
-				   "%s\t{ router : \"%s\", gateway   : \"%s\", label : \"HNA\" }",
-				   (first_line ? "" : ",\n"), from, to);
-		}
-	} else {
-#ifndef VIS_SUBCLUSTERS_DISABLED
-		proc_vis_insert_interface(entry->src, if_entry, compare_orig(entry->src, vis_orig));
-#endif /* VIS_SUBCLUSTERS_DISABLED */
-		addr_to_string(from, entry->src);
-
-		/* kernel has no printf-support for %f? it'd be better to return
-		 * this in float. */
-
-		int_part = TQ_MAX_VALUE / entry->quality;
-		frac_part = 1000 * TQ_MAX_VALUE / entry->quality - int_part * 1000;
-
-		if (current_format == DOT_DRAW) {
-			seq_printf(seq,
-				   "\t\"%s\" -> \"%s\" [label=\"%d.%d\"]\n",
-				   from, to, int_part, frac_part);
-		} else {
-			seq_printf(seq,
-				   "%s\t{ router : \"%s\", neighbour : \"%s\", label : %d.%d }",
-				   (first_line ? "" : ",\n"), from, to, int_part, frac_part);
-		}
-	}
-}
-
-
-static int proc_vis_read(struct seq_file *seq, void *offset)
-{
-	struct hash_it_t *hashit = NULL;
-	struct vis_info *info;
-	struct vis_info_entry *entries;
-	struct vis_if_list *if_entries = NULL;
-	int i;
-	uint8_t current_format, first_line = 1;
-#ifndef VIS_SUBCLUSTERS_DISABLED
-	char tmp_addr_str[ETH_STR_LEN];
-	struct vis_if_list *tmp_if_next;
-#endif /* VIS_SUBCLUSTERS_DISABLED */
-
-	current_format = vis_format;
-
-	rcu_read_lock();
-	if (list_empty(&if_list) || (!is_vis_server())) {
-		rcu_read_unlock();
-		if (current_format == DOT_DRAW)
-			seq_printf(seq, "digraph {\n}\n");
-		goto end;
-	}
-
-	rcu_read_unlock();
-
-	if (current_format == DOT_DRAW)
-		seq_printf(seq, "digraph {\n");
-
-	spin_lock(&vis_hash_lock);
-	while (NULL != (hashit = hash_iterate(vis_hash, hashit))) {
-		info = hashit->bucket->data;
-		entries = (struct vis_info_entry *)
-			((char *)info + sizeof(struct vis_info));
-
-		for (i = 0; i < info->packet.entries; i++) {
-			proc_vis_read_entry(seq, &entries[i], &if_entries,
-					    info->packet.vis_orig,
-					    current_format, first_line);
-			if (first_line)
-				first_line = 0;
-		}
-
-#ifndef VIS_SUBCLUSTERS_DISABLED
-		/* Generate subgraphs from the collected items */
-		if (current_format == DOT_DRAW) {
-
-			addr_to_string(tmp_addr_str, info->packet.vis_orig);
-			seq_printf(seq, "\tsubgraph \"cluster_%s\" {\n", tmp_addr_str);
-			while (if_entries != NULL) {
-
-				addr_to_string(tmp_addr_str, if_entries->addr);
-				if (if_entries->primary)
-					seq_printf(seq, "\t\t\"%s\" [peripheries=2]\n", tmp_addr_str);
-				else
-					seq_printf(seq, "\t\t\"%s\"\n", tmp_addr_str);
-
-				/* ... and empty the list while doing this */
-				tmp_if_next = if_entries->next;
-				kfree(if_entries);
-				if_entries = tmp_if_next;
-			}
-			seq_printf(seq, "\t}\n");
-		}
-#endif /* VIS_SUBCLUSTERS_DISABLED */
-	}
-	spin_unlock(&vis_hash_lock);
-
-	if (current_format == DOT_DRAW)
-		seq_printf(seq, "}\n");
-	else
-		seq_printf(seq, "\n");
-end:
-	return 0;
-}
-
 /* setting the mode of the vis server by the user */
-static ssize_t proc_vis_write(struct file *file, const char __user * buffer,
+static ssize_t proc_vis_srv_write(struct file *file, const char __user * buffer,
 			      size_t count, loff_t *ppos)
 {
 	char *vis_mode_string;
@@ -584,72 +330,84 @@
 	not_copied = copy_from_user(vis_mode_string, buffer, count);
 	vis_mode_string[count - not_copied - 1] = 0;
 
-	if (strcmp(vis_mode_string, "client") == 0) {
-		debug_log(LOG_TYPE_NOTICE, "Setting VIS mode to client\n");
-		vis_set_mode(VIS_TYPE_CLIENT_UPDATE);
-	} else if (strcmp(vis_mode_string, "server") == 0) {
-		debug_log(LOG_TYPE_NOTICE, "Setting VIS mode to server\n");
-		vis_set_mode(VIS_TYPE_SERVER_SYNC);
+	if ((strcmp(vis_mode_string, "client") == 0) ||
+			(strcmp(vis_mode_string, "disabled") == 0)) {
+		printk(KERN_INFO "batman-adv:Setting VIS mode to client (disabling vis server)\n");
+		atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE);
+	} else if ((strcmp(vis_mode_string, "server") == 0) ||
+			(strcmp(vis_mode_string, "enabled") == 0)) {
+		printk(KERN_INFO "batman-adv:Setting VIS mode to server (enabling vis server)\n");
+		atomic_set(&vis_mode, VIS_TYPE_SERVER_SYNC);
 	} else
-		debug_log(LOG_TYPE_WARN, "Unknown VIS mode: %s\n",
-			  vis_mode_string);
+		printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n",
+		       vis_mode_string);
 
 	kfree(vis_mode_string);
 	return count;
 }
 
-static int proc_vis_open(struct inode *inode, struct file *file)
+static int proc_vis_srv_read(struct seq_file *seq, void *offset)
 {
-	return single_open(file, proc_vis_read, NULL);
-}
+	int vis_server = atomic_read(&vis_mode);
 
-static int proc_vis_format_read(struct seq_file *seq, void *offset)
-{
-	uint8_t current_format = vis_format;
+	seq_printf(seq, "[%c] client mode (server disabled) \n",
+			(vis_server == VIS_TYPE_CLIENT_UPDATE) ? 'x' : ' ');
+	seq_printf(seq, "[%c] server mode (server enabled) \n",
+			(vis_server == VIS_TYPE_SERVER_SYNC) ? 'x' : ' ');
 
-	seq_printf(seq, "[%c] %s\n",
-		   (current_format == DOT_DRAW) ? 'x' : ' ',
-		   VIS_FORMAT_DD_NAME);
-	seq_printf(seq, "[%c] %s\n",
-		   (current_format == JSON) ? 'x' : ' ',
-		   VIS_FORMAT_JSON_NAME);
 	return 0;
 }
 
-static int proc_vis_format_open(struct inode *inode, struct file *file)
+static int proc_vis_srv_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, proc_vis_format_read, NULL);
+	return single_open(file, proc_vis_srv_read, NULL);
 }
 
-static ssize_t proc_vis_format_write(struct file *file,
-				     const char __user *buffer,
-				     size_t count, loff_t *ppos)
+static int proc_vis_data_read(struct seq_file *seq, void *offset)
 {
-	char *vis_format_string;
-	int not_copied = 0;
+	HASHIT(hashit);
+	struct vis_info *info;
+	struct vis_info_entry *entries;
+	HLIST_HEAD(vis_if_list);
+	int i;
+	char tmp_addr_str[ETH_STR_LEN];
+	unsigned long flags;
+	int vis_server = atomic_read(&vis_mode);
 
-	vis_format_string = kmalloc(count, GFP_KERNEL);
+	rcu_read_lock();
+	if (list_empty(&if_list) || (vis_server == VIS_TYPE_CLIENT_UPDATE)) {
+		rcu_read_unlock();
+		goto end;
+	}
 
-	if (!vis_format_string)
-		return -ENOMEM;
+	rcu_read_unlock();
 
-	not_copied = copy_from_user(vis_format_string, buffer, count);
-	vis_format_string[count - not_copied - 1] = 0;
+	spin_lock_irqsave(&vis_hash_lock, flags);
+	while (hash_iterate(vis_hash, &hashit)) {
+		info = hashit.bucket->data;
+		entries = (struct vis_info_entry *)
+			((char *)info + sizeof(struct vis_info));
+		addr_to_string(tmp_addr_str, info->packet.vis_orig);
+		seq_printf(seq, "%s,", tmp_addr_str);
 
-	if (strcmp(vis_format_string, VIS_FORMAT_DD_NAME) == 0) {
-		debug_log(LOG_TYPE_NOTICE, "Setting VIS output format to: %s\n",
-			  VIS_FORMAT_DD_NAME);
-		vis_format = DOT_DRAW;
-	} else if (strcmp(vis_format_string, VIS_FORMAT_JSON_NAME) == 0) {
-		debug_log(LOG_TYPE_NOTICE, "Setting VIS output format to: %s\n",
-			  VIS_FORMAT_JSON_NAME);
-		vis_format = JSON;
-	} else
-		debug_log(LOG_TYPE_WARN, "Unknown VIS output format: %s\n",
-			  vis_format_string);
+		for (i = 0; i < info->packet.entries; i++) {
+			proc_vis_read_entry(seq, &entries[i], &vis_if_list,
+					    info->packet.vis_orig);
+		}
 
-	kfree(vis_format_string);
-	return count;
+		/* add primary/secondary records */
+		proc_vis_read_prim_sec(seq, &vis_if_list);
+		seq_printf(seq, "\n");
+	}
+	spin_unlock_irqrestore(&vis_hash_lock, flags);
+
+end:
+	return 0;
+}
+
+static int proc_vis_data_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_vis_data_read, NULL);
 }
 
 static int proc_aggr_read(struct seq_file *seq, void *offset)
@@ -665,6 +423,7 @@
 	char *aggr_string;
 	int not_copied = 0;
 	unsigned long aggregation_enabled_tmp;
+	int retval;
 
 	aggr_string = kmalloc(count, GFP_KERNEL);
 
@@ -674,22 +433,21 @@
 	not_copied = copy_from_user(aggr_string, buffer, count);
 	aggr_string[count - not_copied - 1] = 0;
 
-	strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp);
+	retval = strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp);
 
-	if ((aggregation_enabled_tmp != 0) && (aggregation_enabled_tmp != 1)) {
-		debug_log(LOG_TYPE_WARN, "Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp);
-		goto end;
+	if (retval || aggregation_enabled_tmp > 1) {
+		printk(KERN_ERR "batman-adv:Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp);
+	} else {
+		printk(KERN_INFO "batman-adv:Changing aggregation from: %s (%i) to: %s (%li)\n",
+		       (atomic_read(&aggregation_enabled) == 1 ?
+			"enabled" : "disabled"),
+		       atomic_read(&aggregation_enabled),
+		       (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"),
+		       aggregation_enabled_tmp);
+		atomic_set(&aggregation_enabled,
+			   (unsigned)aggregation_enabled_tmp);
 	}
 
-	debug_log(LOG_TYPE_NOTICE, "Changing aggregation from: %s (%i) to: %s (%li)\n",
-		  (atomic_read(&aggregation_enabled) == 1 ?
-		   "enabled" : "disabled"),
-		  atomic_read(&aggregation_enabled),
-		  (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"),
-		  aggregation_enabled_tmp);
-
-	atomic_set(&aggregation_enabled, (unsigned)aggregation_enabled_tmp);
-end:
 	kfree(aggr_string);
 	return count;
 }
@@ -715,20 +473,20 @@
 	.release	= single_release,
 };
 
-static const struct file_operations proc_vis_format_fops = {
+static const struct file_operations proc_vis_srv_fops = {
 	.owner		= THIS_MODULE,
-	.open		= proc_vis_format_open,
+	.open		= proc_vis_srv_open,
 	.read		= seq_read,
-	.write		= proc_vis_format_write,
+	.write		= proc_vis_srv_write,
 	.llseek		= seq_lseek,
 	.release	= single_release,
 };
 
-static const struct file_operations proc_vis_fops = {
+static const struct file_operations proc_vis_data_fops = {
 	.owner		= THIS_MODULE,
-	.open		= proc_vis_open,
+	.open		= proc_vis_data_open,
 	.read		= seq_read,
-	.write		= proc_vis_write,
+	.write		= proc_dummy_write,
 	.llseek		= seq_lseek,
 	.release	= single_release,
 };
@@ -760,15 +518,6 @@
 	.release	= single_release,
 };
 
-static const struct file_operations proc_log_level_fops = {
-	.owner		= THIS_MODULE,
-	.open		= proc_log_level_open,
-	.read		= seq_read,
-	.write		= proc_log_level_write,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
 static const struct file_operations proc_interfaces_fops = {
 	.owner		= THIS_MODULE,
 	.open		= proc_interfaces_open,
@@ -795,12 +544,6 @@
 	if (proc_transt_local_file)
 		remove_proc_entry(PROC_FILE_TRANST_LOCAL, proc_batman_dir);
 
-	if (proc_log_file)
-		remove_proc_entry(PROC_FILE_LOG, proc_batman_dir);
-
-	if (proc_log_level_file)
-		remove_proc_entry(PROC_FILE_LOG_LEVEL, proc_batman_dir);
-
 	if (proc_originators_file)
 		remove_proc_entry(PROC_FILE_ORIGINATORS, proc_batman_dir);
 
@@ -810,11 +553,11 @@
 	if (proc_interface_file)
 		remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir);
 
-	if (proc_vis_file)
-		remove_proc_entry(PROC_FILE_VIS, proc_batman_dir);
+	if (proc_vis_data_file)
+		remove_proc_entry(PROC_FILE_VIS_DATA, proc_batman_dir);
 
-	if (proc_vis_format_file)
-		remove_proc_entry(PROC_FILE_VIS_FORMAT, proc_batman_dir);
+	if (proc_vis_srv_file)
+		remove_proc_entry(PROC_FILE_VIS_SRV, proc_batman_dir);
 
 	if (proc_aggr_file)
 		remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir);
@@ -862,17 +605,6 @@
 		return -EFAULT;
 	}
 
-	proc_log_level_file = create_proc_entry(PROC_FILE_LOG_LEVEL,
-						S_IWUSR | S_IRUGO,
-						proc_batman_dir);
-	if (proc_log_level_file) {
-		proc_log_level_file->proc_fops = &proc_log_level_fops;
-	} else {
-		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_LOG_LEVEL);
-		cleanup_procfs();
-		return -EFAULT;
-	}
-
 	proc_originators_file = create_proc_entry(PROC_FILE_ORIGINATORS,
 						  S_IRUGO, proc_batman_dir);
 	if (proc_originators_file) {
@@ -883,16 +615,6 @@
 		return -EFAULT;
 	}
 
-	proc_log_file = create_proc_entry(PROC_FILE_LOG,
-					  S_IRUGO, proc_batman_dir);
-	if (proc_log_file) {
-		proc_log_file->proc_fops = &proc_log_operations;
-	} else {
-		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_FILE_LOG, PROC_FILE_GATEWAYS);
-		cleanup_procfs();
-		return -EFAULT;
-	}
-
 	proc_transt_local_file = create_proc_entry(PROC_FILE_TRANST_LOCAL,
 						   S_IRUGO, proc_batman_dir);
 	if (proc_transt_local_file) {
@@ -913,23 +635,23 @@
 		return -EFAULT;
 	}
 
-	proc_vis_file = create_proc_entry(PROC_FILE_VIS, S_IWUSR | S_IRUGO,
-					  proc_batman_dir);
-	if (proc_vis_file) {
-		proc_vis_file->proc_fops = &proc_vis_fops;
+	proc_vis_srv_file = create_proc_entry(PROC_FILE_VIS_SRV,
+						S_IWUSR | S_IRUGO,
+						proc_batman_dir);
+	if (proc_vis_srv_file) {
+		proc_vis_srv_file->proc_fops = &proc_vis_srv_fops;
 	} else {
-		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS);
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_SRV);
 		cleanup_procfs();
 		return -EFAULT;
 	}
 
-	proc_vis_format_file = create_proc_entry(PROC_FILE_VIS_FORMAT,
-						 S_IWUSR | S_IRUGO,
-						 proc_batman_dir);
-	if (proc_vis_format_file) {
-		proc_vis_format_file->proc_fops = &proc_vis_format_fops;
+	proc_vis_data_file = create_proc_entry(PROC_FILE_VIS_DATA, S_IRUGO,
+					  proc_batman_dir);
+	if (proc_vis_data_file) {
+		proc_vis_data_file->proc_fops = &proc_vis_data_fops;
 	} else {
-		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_FORMAT);
+		printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_DATA);
 		cleanup_procfs();
 		return -EFAULT;
 	}
@@ -946,5 +668,3 @@
 
 	return 0;
 }
-
-
diff --git a/drivers/staging/batman-adv/proc.h b/drivers/staging/batman-adv/proc.h
index 16d3efd..cd690e0 100644
--- a/drivers/staging/batman-adv/proc.h
+++ b/drivers/staging/batman-adv/proc.h
@@ -31,19 +31,10 @@
 #define PROC_FILE_LOG_LEVEL "log_level"
 #define PROC_FILE_TRANST_LOCAL "transtable_local"
 #define PROC_FILE_TRANST_GLOBAL "transtable_global"
-#define PROC_FILE_VIS "vis"
-#define PROC_FILE_VIS_FORMAT "vis_format"
+#define PROC_FILE_VIS_SRV "vis_server"
+#define PROC_FILE_VIS_DATA "vis_data"
 #define PROC_FILE_AGGR "aggregate_ogm"
 
 void cleanup_procfs(void);
 int setup_procfs(void);
 
-/* While scanning for vis-entries of a particular vis-originator
- * this list collects its interfaces to create a subgraph/cluster
- * out of them later
- */
-struct vis_if_list {
-	uint8_t addr[ETH_ALEN];
-	bool primary;
-	struct vis_if_list *next;
-};
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c
index 4a14c36..d89048b 100644
--- a/drivers/staging/batman-adv/routing.c
+++ b/drivers/staging/batman-adv/routing.c
@@ -19,304 +19,226 @@
  *
  */
 
-
-
-
-
 #include "main.h"
 #include "routing.h"
-#include "log.h"
 #include "send.h"
+#include "hash.h"
 #include "soft-interface.h"
 #include "hard-interface.h"
 #include "device.h"
 #include "translation-table.h"
+#include "originator.h"
 #include "types.h"
-#include "hash.h"
 #include "ring_buffer.h"
 #include "vis.h"
 #include "aggregation.h"
-#include "compat.h"
-
-
 
 DECLARE_WAIT_QUEUE_HEAD(thread_wait);
-static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
-
-static atomic_t data_ready_cond;
-atomic_t exit_cond;
-
-static void start_purge_timer(void)
-{
-	queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ);
-}
-
-int originator_init(void)
-{
-	if (orig_hash)
-		return 1;
-
-	spin_lock(&orig_hash_lock);
-	orig_hash = hash_new(128, compare_orig, choose_orig);
-
-	if (!orig_hash)
-		goto err;
-
-	spin_unlock(&orig_hash_lock);
-	start_purge_timer();
-	return 1;
-
-err:
-	spin_unlock(&orig_hash_lock);
-	return 0;
-}
-
-void originator_free(void)
-{
-	if (!orig_hash)
-		return;
-
-	cancel_delayed_work_sync(&purge_orig_wq);
-
-	spin_lock(&orig_hash_lock);
-	hash_delete(orig_hash, free_orig_node);
-	orig_hash = NULL;
-	spin_unlock(&orig_hash_lock);
-}
-
-static struct neigh_node *create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming)
-{
-	struct neigh_node *neigh_node;
-
-	debug_log(LOG_TYPE_BATMAN, "Creating new last-hop neighbour of originator\n");
-
-	neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC);
-	memset(neigh_node, 0, sizeof(struct neigh_node));
-	INIT_LIST_HEAD(&neigh_node->list);
-
-	memcpy(neigh_node->addr, neigh, ETH_ALEN);
-	neigh_node->orig_node = orig_neigh_node;
-	neigh_node->if_incoming = if_incoming;
-
-	list_add_tail(&neigh_node->list, &orig_node->neigh_list);
-	return neigh_node;
-}
-
-void free_orig_node(void *data)
-{
-	struct list_head *list_pos, *list_pos_tmp;
-	struct neigh_node *neigh_node;
-	struct orig_node *orig_node = (struct orig_node *)data;
-
-	/* for all neighbours towards this originator ... */
-	list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
-		neigh_node = list_entry(list_pos, struct neigh_node, list);
-
-		list_del(list_pos);
-		kfree(neigh_node);
-	}
-
-	hna_global_del_orig(orig_node, "originator timed out");
-
-	kfree(orig_node->bcast_own);
-	kfree(orig_node->bcast_own_sum);
-	kfree(orig_node);
-}
-
-/* this function finds or creates an originator entry for the given address if it does not exits */
-static struct orig_node *get_orig_node(uint8_t *addr)
-{
-	struct orig_node *orig_node;
-	struct hashtable_t *swaphash;
-	char orig_str[ETH_STR_LEN];
-
-	orig_node = ((struct orig_node *)hash_find(orig_hash, addr));
-
-	if (orig_node != NULL)
-		return orig_node;
-
-	addr_to_string(orig_str, addr);
-	debug_log(LOG_TYPE_BATMAN, "Creating new originator: %s \n", orig_str);
-
-	orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC);
-	memset(orig_node, 0, sizeof(struct orig_node));
-	INIT_LIST_HEAD(&orig_node->neigh_list);
-
-	memcpy(orig_node->orig, addr, ETH_ALEN);
-	orig_node->router = NULL;
-	orig_node->batman_if = NULL;
-	orig_node->hna_buff = NULL;
-
-	orig_node->bcast_own = kmalloc(num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS, GFP_ATOMIC);
-	memset(orig_node->bcast_own, 0, num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS);
-
-	orig_node->bcast_own_sum = kmalloc(num_ifs * sizeof(uint8_t), GFP_ATOMIC);
-	memset(orig_node->bcast_own_sum, 0, num_ifs * sizeof(uint8_t));
-
-	hash_add(orig_hash, orig_node);
-
-	if (orig_hash->elements * 4 > orig_hash->size) {
-		swaphash = hash_resize(orig_hash, orig_hash->size * 2);
-
-		if (swaphash == NULL)
-			debug_log(LOG_TYPE_CRIT, "Couldn't resize orig hash table \n");
-		else
-			orig_hash = swaphash;
-	}
-
-	return orig_node;
-}
 
 void slide_own_bcast_window(struct batman_if *batman_if)
 {
-	struct hash_it_t *hashit = NULL;
+	HASHIT(hashit);
 	struct orig_node *orig_node;
+	TYPE_OF_WORD *word;
+	unsigned long flags;
 
-	spin_lock(&orig_hash_lock);
+	spin_lock_irqsave(&orig_hash_lock, flags);
 
-	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
-		orig_node = hashit->bucket->data;
+	while (hash_iterate(orig_hash, &hashit)) {
+		orig_node = hashit.bucket->data;
+		word = &(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]);
 
-		bit_get_packet((TYPE_OF_WORD *)&(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]), 1, 0);
-		orig_node->bcast_own_sum[batman_if->if_num] = bit_packet_count((TYPE_OF_WORD *)&(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]));
+		bit_get_packet(word, 1, 0);
+		orig_node->bcast_own_sum[batman_if->if_num] =
+			bit_packet_count(word);
 	}
 
-	spin_unlock(&orig_hash_lock);
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
 }
 
-static void update_routes(struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len)
+static void update_HNA(struct orig_node *orig_node,
+		       unsigned char *hna_buff, int hna_buff_len)
 {
-	char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
+	if ((hna_buff_len != orig_node->hna_buff_len) ||
+	    ((hna_buff_len > 0) &&
+	     (orig_node->hna_buff_len > 0) &&
+	     (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) {
+
+		if (orig_node->hna_buff_len > 0)
+			hna_global_del_orig(orig_node,
+					    "originator changed hna");
+
+		if ((hna_buff_len > 0) && (hna_buff != NULL))
+			hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
+	}
+}
+
+static void update_route(struct orig_node *orig_node,
+			 struct neigh_node *neigh_node,
+			 unsigned char *hna_buff, int hna_buff_len)
+{
+	/* route deleted */
+	if ((orig_node->router != NULL) && (neigh_node == NULL)) {
+
+		bat_dbg(DBG_ROUTES, "Deleting route towards: %pM\n",
+			orig_node->orig);
+		hna_global_del_orig(orig_node, "originator timed out");
+
+		/* route added */
+	} else if ((orig_node->router == NULL) && (neigh_node != NULL)) {
+
+		bat_dbg(DBG_ROUTES,
+			"Adding route towards: %pM (via %pM)\n",
+			orig_node->orig, neigh_node->addr);
+		hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
+
+		/* route changed */
+	} else {
+		bat_dbg(DBG_ROUTES, "Changing route towards: %pM (now via %pM - was via %pM)\n", orig_node->orig, neigh_node->addr, orig_node->router->addr);
+	}
+
+	if (neigh_node != NULL)
+		orig_node->batman_if = neigh_node->if_incoming;
+	else
+		orig_node->batman_if = NULL;
+
+	orig_node->router = neigh_node;
+}
+
+
+void update_routes(struct orig_node *orig_node,
+			  struct neigh_node *neigh_node,
+			  unsigned char *hna_buff, int hna_buff_len)
+{
 
 	if (orig_node == NULL)
 		return;
 
-	if (orig_node->router != neigh_node) {
-		addr_to_string(orig_str, orig_node->orig);
-
-		/* route deleted */
-		if ((orig_node->router != NULL) && (neigh_node == NULL)) {
-
-			debug_log(LOG_TYPE_ROUTES, "Deleting route towards: %s\n", orig_str);
-			hna_global_del_orig(orig_node, "originator timed out");
-
-		/* route added */
-		} else if ((orig_node->router == NULL) && (neigh_node != NULL)) {
-
-			addr_to_string(neigh_str, neigh_node->addr);
-			debug_log(LOG_TYPE_ROUTES, "Adding route towards: %s (via %s)\n", orig_str, neigh_str);
-			hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
-
-		/* route changed */
-		} else {
-
-			addr_to_string(neigh_str, neigh_node->addr);
-			addr_to_string(router_str, orig_node->router->addr);
-			debug_log(LOG_TYPE_ROUTES, "Changing route towards: %s (now via %s - was via %s)\n", orig_str, neigh_str, router_str);
-
-		}
-
-		if (neigh_node != NULL)
-			orig_node->batman_if = neigh_node->if_incoming;
-		else
-			orig_node->batman_if = NULL;
-
-		orig_node->router = neigh_node;
-
+	if (orig_node->router != neigh_node)
+		update_route(orig_node, neigh_node, hna_buff, hna_buff_len);
 	/* may be just HNA changed */
-	} else {
-
-		if ((hna_buff_len != orig_node->hna_buff_len) || ((hna_buff_len > 0) && (orig_node->hna_buff_len > 0) && (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) {
-
-			if (orig_node->hna_buff_len > 0)
-				hna_global_del_orig(orig_node, "originator changed hna");
-
-			if ((hna_buff_len > 0) && (hna_buff != NULL))
-				hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
-
-		}
-
-	}
+	else
+		update_HNA(orig_node, hna_buff, hna_buff_len);
 }
 
-static int isBidirectionalNeigh(struct orig_node *orig_node, struct orig_node *orig_neigh_node, struct batman_packet *batman_packet, struct batman_if *if_incoming)
+static int isBidirectionalNeigh(struct orig_node *orig_node,
+				struct orig_node *orig_neigh_node,
+				struct batman_packet *batman_packet,
+				struct batman_if *if_incoming)
 {
 	struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
-	char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN];
 	unsigned char total_count;
 
-	addr_to_string(orig_str, orig_node->orig);
-	addr_to_string(neigh_str, orig_neigh_node->orig);
-
 	if (orig_node == orig_neigh_node) {
-		list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
+		list_for_each_entry(tmp_neigh_node,
+				    &orig_node->neigh_list,
+				    list) {
 
-			if (compare_orig(tmp_neigh_node->addr, orig_neigh_node->orig) && (tmp_neigh_node->if_incoming == if_incoming))
+			if (compare_orig(tmp_neigh_node->addr,
+					 orig_neigh_node->orig) &&
+			    (tmp_neigh_node->if_incoming == if_incoming))
 				neigh_node = tmp_neigh_node;
 		}
 
-		if (neigh_node == NULL)
-			neigh_node = create_neighbor(orig_node, orig_neigh_node, orig_neigh_node->orig, if_incoming);
+		if (!neigh_node)
+			neigh_node = create_neighbor(orig_node,
+						     orig_neigh_node,
+						     orig_neigh_node->orig,
+						     if_incoming);
+		/* create_neighbor failed, return 0 */
+		if (!neigh_node)
+			return 0;
 
 		neigh_node->last_valid = jiffies;
 	} else {
 		/* find packet count of corresponding one hop neighbor */
-		list_for_each_entry(tmp_neigh_node, &orig_neigh_node->neigh_list, list) {
+		list_for_each_entry(tmp_neigh_node,
+				    &orig_neigh_node->neigh_list, list) {
 
-			if (compare_orig(tmp_neigh_node->addr, orig_neigh_node->orig) && (tmp_neigh_node->if_incoming == if_incoming))
+			if (compare_orig(tmp_neigh_node->addr,
+					 orig_neigh_node->orig) &&
+			    (tmp_neigh_node->if_incoming == if_incoming))
 				neigh_node = tmp_neigh_node;
 		}
 
-		if (neigh_node == NULL)
-			neigh_node = create_neighbor(orig_neigh_node, orig_neigh_node, orig_neigh_node->orig, if_incoming);
+		if (!neigh_node)
+			neigh_node = create_neighbor(orig_neigh_node,
+						     orig_neigh_node,
+						     orig_neigh_node->orig,
+						     if_incoming);
+		/* create_neighbor failed, return 0 */
+		if (!neigh_node)
+			return 0;
 	}
 
 	orig_node->last_valid = jiffies;
 
 	/* pay attention to not get a value bigger than 100 % */
-	total_count = (orig_neigh_node->bcast_own_sum[if_incoming->if_num] > neigh_node->real_packet_count ? neigh_node->real_packet_count : orig_neigh_node->bcast_own_sum[if_incoming->if_num]);
+	total_count = (orig_neigh_node->bcast_own_sum[if_incoming->if_num] >
+		       neigh_node->real_packet_count ?
+		       neigh_node->real_packet_count :
+		       orig_neigh_node->bcast_own_sum[if_incoming->if_num]);
 
 	/* if we have too few packets (too less data) we set tq_own to zero */
 	/* if we receive too few packets it is not considered bidirectional */
-	if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) || (neigh_node->real_packet_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
+	if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) ||
+	    (neigh_node->real_packet_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
 		orig_neigh_node->tq_own = 0;
 	else
-		/* neigh_node->real_packet_count is never zero as we only purge old information when getting new information */
-		orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) / neigh_node->real_packet_count;
+		/* neigh_node->real_packet_count is never zero as we
+		 * only purge old information when getting new
+		 * information */
+		orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) /
+			neigh_node->real_packet_count;
 
 	/*
-	 * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE
-	 * this does affect the nearly-symmetric links only a little,
-	 * but punishes asymmetric links more.
-	 * this will give a value between 0 and TQ_MAX_VALUE
+	 * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does
+	 * affect the nearly-symmetric links only a little, but
+	 * punishes asymmetric links more.  This will give a value
+	 * between 0 and TQ_MAX_VALUE
 	 */
-	orig_neigh_node->tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE *
-			(TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
-			(TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
-			(TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count)) /
-			(TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE);
+	orig_neigh_node->tq_asym_penalty =
+		TQ_MAX_VALUE -
+		(TQ_MAX_VALUE *
+		 (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
+		 (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
+		 (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count)) /
+		(TQ_LOCAL_WINDOW_SIZE *
+		 TQ_LOCAL_WINDOW_SIZE *
+		 TQ_LOCAL_WINDOW_SIZE);
 
-	batman_packet->tq = ((batman_packet->tq * orig_neigh_node->tq_own * orig_neigh_node->tq_asym_penalty) / (TQ_MAX_VALUE *  TQ_MAX_VALUE));
+	batman_packet->tq = ((batman_packet->tq *
+			      orig_neigh_node->tq_own *
+			      orig_neigh_node->tq_asym_penalty) /
+			     (TQ_MAX_VALUE *	 TQ_MAX_VALUE));
 
-	debug_log(LOG_TYPE_BATMAN, "bidirectional: orig = %-15s neigh = %-15s => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i \n",
-		  orig_str, neigh_str, total_count, neigh_node->real_packet_count, orig_neigh_node->tq_own, orig_neigh_node->tq_asym_penalty, batman_packet->tq);
+	bat_dbg(DBG_BATMAN, "bidirectional: orig = %-15pM neigh = %-15pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i \n",
+		orig_node->orig, orig_neigh_node->orig, total_count,
+		neigh_node->real_packet_count, orig_neigh_node->tq_own,
+		orig_neigh_node->tq_asym_penalty, batman_packet->tq);
 
-	/* if link has the minimum required transmission quality consider it bidirectional */
+	/* if link has the minimum required transmission quality
+	 * consider it bidirectional */
 	if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT)
 		return 1;
 
 	return 0;
 }
 
-static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct batman_if *if_incoming, unsigned char *hna_buff, int hna_buff_len, char is_duplicate)
+static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr,
+			struct batman_packet *batman_packet,
+			struct batman_if *if_incoming,
+			unsigned char *hna_buff, int hna_buff_len,
+			char is_duplicate)
 {
 	struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
 	int tmp_hna_buff_len;
 
-	debug_log(LOG_TYPE_BATMAN, "update_originator(): Searching and updating originator entry of received packet \n");
+	bat_dbg(DBG_BATMAN, "update_originator(): Searching and updating originator entry of received packet \n");
 
 	list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
-		if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming)) {
+		if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
+		    (tmp_neigh_node->if_incoming == if_incoming)) {
 			neigh_node = tmp_neigh_node;
 			continue;
 		}
@@ -324,19 +246,34 @@
 		if (is_duplicate)
 			continue;
 
-		ring_buffer_set(tmp_neigh_node->tq_recv, &tmp_neigh_node->tq_index, 0);
-		tmp_neigh_node->tq_avg = ring_buffer_avg(tmp_neigh_node->tq_recv);
+		ring_buffer_set(tmp_neigh_node->tq_recv,
+				&tmp_neigh_node->tq_index, 0);
+		tmp_neigh_node->tq_avg =
+			ring_buffer_avg(tmp_neigh_node->tq_recv);
 	}
 
-	if (neigh_node == NULL)
-		neigh_node = create_neighbor(orig_node, get_orig_node(ethhdr->h_source), ethhdr->h_source, if_incoming);
-	else
-		debug_log(LOG_TYPE_BATMAN, "Updating existing last-hop neighbour of originator\n");
+	if (!neigh_node) {
+		struct orig_node *orig_tmp;
+
+		orig_tmp = get_orig_node(ethhdr->h_source);
+		if (!orig_tmp)
+			return;
+
+		neigh_node = create_neighbor(orig_node,
+					     orig_tmp,
+					     ethhdr->h_source, if_incoming);
+		if (!neigh_node)
+			return;
+	} else
+		bat_dbg(DBG_BATMAN,
+			"Updating existing last-hop neighbor of originator\n");
 
 	orig_node->flags = batman_packet->flags;
 	neigh_node->last_valid = jiffies;
 
-	ring_buffer_set(neigh_node->tq_recv, &neigh_node->tq_index, batman_packet->tq);
+	ring_buffer_set(neigh_node->tq_recv,
+			&neigh_node->tq_index,
+			batman_packet->tq);
 	neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
 
 	if (!is_duplicate) {
@@ -344,9 +281,11 @@
 		neigh_node->last_ttl = batman_packet->ttl;
 	}
 
-	tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ? batman_packet->num_hna * ETH_ALEN : hna_buff_len);
+	tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ?
+			    batman_packet->num_hna * ETH_ALEN : hna_buff_len);
 
-	/* if this neighbor already is our next hop there is nothing to change */
+	/* if this neighbor already is our next hop there is nothing
+	 * to change */
 	if (orig_node->router == neigh_node)
 		goto update_hna;
 
@@ -355,11 +294,12 @@
 	    (orig_node->router->tq_avg > neigh_node->tq_avg))
 		goto update_hna;
 
-	/* if the TQ is the same and the link not more symetric we won't consider it either */
+	/* if the TQ is the same and the link not more symetric we
+	 * won't consider it either */
 	if ((orig_node->router) &&
 	     ((neigh_node->tq_avg == orig_node->router->tq_avg) &&
-	     (orig_node->router->orig_node->bcast_own_sum[if_incoming->if_num] >=
-	      neigh_node->orig_node->bcast_own_sum[if_incoming->if_num])))
+	     (orig_node->router->orig_node->bcast_own_sum[if_incoming->if_num]
+	      >= neigh_node->orig_node->bcast_own_sum[if_incoming->if_num])))
 		goto update_hna;
 
 	update_routes(orig_node, neigh_node, hna_buff, tmp_hna_buff_len);
@@ -367,60 +307,72 @@
 
 update_hna:
 	update_routes(orig_node, orig_node->router, hna_buff, tmp_hna_buff_len);
-	return;
 }
 
-static char count_real_packets(struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct batman_if *if_incoming)
+static char count_real_packets(struct ethhdr *ethhdr,
+			       struct batman_packet *batman_packet,
+			       struct batman_if *if_incoming)
 {
 	struct orig_node *orig_node;
 	struct neigh_node *tmp_neigh_node;
 	char is_duplicate = 0;
-
+	uint16_t seq_diff;
 
 	orig_node = get_orig_node(batman_packet->orig);
 	if (orig_node == NULL)
 		return 0;
 
-
 	list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
 
 		if (!is_duplicate)
-			is_duplicate = get_bit_status(tmp_neigh_node->real_bits, orig_node->last_real_seqno, batman_packet->seqno);
-
-		if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming))
-			bit_get_packet(tmp_neigh_node->real_bits, batman_packet->seqno - orig_node->last_real_seqno, 1);
+			is_duplicate =
+				get_bit_status(tmp_neigh_node->real_bits,
+					       orig_node->last_real_seqno,
+					       batman_packet->seqno);
+		seq_diff = batman_packet->seqno - orig_node->last_real_seqno;
+		if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
+		    (tmp_neigh_node->if_incoming == if_incoming))
+			bit_get_packet(tmp_neigh_node->real_bits, seq_diff, 1);
 		else
-			bit_get_packet(tmp_neigh_node->real_bits, batman_packet->seqno - orig_node->last_real_seqno, 0);
+			bit_get_packet(tmp_neigh_node->real_bits, seq_diff, 0);
 
-		tmp_neigh_node->real_packet_count = bit_packet_count(tmp_neigh_node->real_bits);
+		tmp_neigh_node->real_packet_count =
+			bit_packet_count(tmp_neigh_node->real_bits);
 	}
 
 	if (!is_duplicate) {
-		debug_log(LOG_TYPE_BATMAN, "updating last_seqno: old %d, new %d \n", orig_node->last_real_seqno, batman_packet->seqno);
+		bat_dbg(DBG_BATMAN, "updating last_seqno: old %d, new %d \n",
+			orig_node->last_real_seqno, batman_packet->seqno);
 		orig_node->last_real_seqno = batman_packet->seqno;
 	}
 
 	return is_duplicate;
 }
 
-void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming)
+void receive_bat_packet(struct ethhdr *ethhdr,
+				struct batman_packet *batman_packet,
+				unsigned char *hna_buff, int hna_buff_len,
+				struct batman_if *if_incoming)
 {
 	struct batman_if *batman_if;
 	struct orig_node *orig_neigh_node, *orig_node;
-	char orig_str[ETH_STR_LEN], prev_sender_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN];
 	char has_directlink_flag;
-	char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0, is_broadcast = 0, is_bidirectional, is_single_hop_neigh, is_duplicate;
+	char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
+	char is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
+	char is_duplicate;
 	unsigned short if_incoming_seqno;
 
-	/* Silently drop when the batman packet is actually not a correct packet.
+	/* Silently drop when the batman packet is actually not a
+	 * correct packet.
 	 *
 	 * This might happen if a packet is padded (e.g. Ethernet has a
 	 * minimum frame length of 64 byte) and the aggregation interprets
 	 * it as an additional length.
 	 *
-	 * TODO: A more sane solution would be to have a bit in the batman_packet
-	 * to detect whether the packet is the last packet in an aggregation.
-	 * Here we expect that the padding is always zero (or not 0x01)
+	 * TODO: A more sane solution would be to have a bit in the
+	 * batman_packet to detect whether the packet is the last
+	 * packet in an aggregation.  Here we expect that the padding
+	 * is always zero (or not 0x01)
 	 */
 	if (batman_packet->packet_type != BAT_PACKET)
 		return;
@@ -428,27 +380,31 @@
 	/* could be changed by schedule_own_packet() */
 	if_incoming_seqno = atomic_read(&if_incoming->seqno);
 
-	addr_to_string(orig_str, batman_packet->orig);
-	addr_to_string(prev_sender_str, batman_packet->prev_sender);
-	addr_to_string(neigh_str, ethhdr->h_source);
-
 	has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0);
 
-	is_single_hop_neigh = (compare_orig(ethhdr->h_source, batman_packet->orig) ? 1 : 0);
+	is_single_hop_neigh = (compare_orig(ethhdr->h_source,
+					    batman_packet->orig) ? 1 : 0);
 
-	debug_log(LOG_TYPE_BATMAN, "Received BATMAN packet via NB: %s, IF: %s [%s] (from OG: %s, via prev OG: %s, seqno %d, tq %d, TTL %d, V %d, IDF %d) \n", neigh_str, if_incoming->dev, if_incoming->addr_str, orig_str, prev_sender_str, batman_packet->seqno, batman_packet->tq, batman_packet->ttl, batman_packet->version, has_directlink_flag);
+	bat_dbg(DBG_BATMAN, "Received BATMAN packet via NB: %pM, IF: %s [%s] (from OG: %pM, via prev OG: %pM, seqno %d, tq %d, TTL %d, V %d, IDF %d) \n",
+		ethhdr->h_source, if_incoming->dev, if_incoming->addr_str,
+		batman_packet->orig, batman_packet->prev_sender,
+		batman_packet->seqno, batman_packet->tq, batman_packet->ttl,
+		batman_packet->version, has_directlink_flag);
 
 	list_for_each_entry_rcu(batman_if, &if_list, list) {
 		if (batman_if->if_active != IF_ACTIVE)
 			continue;
 
-		if (compare_orig(ethhdr->h_source, batman_if->net_dev->dev_addr))
+		if (compare_orig(ethhdr->h_source,
+				 batman_if->net_dev->dev_addr))
 			is_my_addr = 1;
 
-		if (compare_orig(batman_packet->orig, batman_if->net_dev->dev_addr))
+		if (compare_orig(batman_packet->orig,
+				 batman_if->net_dev->dev_addr))
 			is_my_orig = 1;
 
-		if (compare_orig(batman_packet->prev_sender, batman_if->net_dev->dev_addr))
+		if (compare_orig(batman_packet->prev_sender,
+				 batman_if->net_dev->dev_addr))
 			is_my_oldorig = 1;
 
 		if (compare_orig(ethhdr->h_source, broadcastAddr))
@@ -456,44 +412,61 @@
 	}
 
 	if (batman_packet->version != COMPAT_VERSION) {
-		debug_log(LOG_TYPE_BATMAN, "Drop packet: incompatible batman version (%i) \n", batman_packet->version);
+		bat_dbg(DBG_BATMAN,
+			"Drop packet: incompatible batman version (%i)\n",
+			batman_packet->version);
 		return;
 	}
 
 	if (is_my_addr) {
-		debug_log(LOG_TYPE_BATMAN, "Drop packet: received my own broadcast (sender: %s) \n", neigh_str);
+		bat_dbg(DBG_BATMAN,
+			"Drop packet: received my own broadcast (sender: %pM)\n",
+			ethhdr->h_source);
 		return;
 	}
 
 	if (is_broadcast) {
-		debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all packets with broadcast source addr (sender: %s) \n", neigh_str);
+		bat_dbg(DBG_BATMAN, "Drop packet: ignoring all packets with broadcast source addr (sender: %pM) \n", ethhdr->h_source);
 		return;
 	}
 
 	if (is_my_orig) {
+		TYPE_OF_WORD *word;
+		int offset;
+
 		orig_neigh_node = get_orig_node(ethhdr->h_source);
 
-		/* neighbour has to indicate direct link and it has to come via the corresponding interface */
-		/* if received seqno equals last send seqno save new seqno for bidirectional check */
-		if (has_directlink_flag && compare_orig(if_incoming->net_dev->dev_addr, batman_packet->orig) &&
-				  (batman_packet->seqno - if_incoming_seqno + 2 == 0)) {
-			bit_mark((TYPE_OF_WORD *)&(orig_neigh_node->bcast_own[if_incoming->if_num * NUM_WORDS]), 0);
-			orig_neigh_node->bcast_own_sum[if_incoming->if_num] = bit_packet_count((TYPE_OF_WORD *)&(orig_neigh_node->bcast_own[if_incoming->if_num * NUM_WORDS]));
+		if (!orig_neigh_node)
+			return;
+
+		/* neighbor has to indicate direct link and it has to
+		 * come via the corresponding interface */
+		/* if received seqno equals last send seqno save new
+		 * seqno for bidirectional check */
+		if (has_directlink_flag &&
+		    compare_orig(if_incoming->net_dev->dev_addr,
+				 batman_packet->orig) &&
+		    (batman_packet->seqno - if_incoming_seqno + 2 == 0)) {
+			offset = if_incoming->if_num * NUM_WORDS;
+			word = &(orig_neigh_node->bcast_own[offset]);
+			bit_mark(word, 0);
+			orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
+				bit_packet_count(word);
 		}
 
-		debug_log(LOG_TYPE_BATMAN, "Drop packet: originator packet from myself (via neighbour) \n");
+		bat_dbg(DBG_BATMAN, "Drop packet: originator packet from myself (via neighbor) \n");
 		return;
 	}
 
 	if (batman_packet->tq == 0) {
 		count_real_packets(ethhdr, batman_packet, if_incoming);
 
-		debug_log(LOG_TYPE_BATMAN, "Drop packet: originator packet with tq equal 0 \n");
+		bat_dbg(DBG_BATMAN, "Drop packet: originator packet with tq equal 0 \n");
 		return;
 	}
 
 	if (is_my_oldorig) {
-		debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all rebroadcast echos (sender: %s) \n", neigh_str);
+		bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast echos (sender: %pM) \n", ethhdr->h_source);
 		return;
 	}
 
@@ -504,507 +477,502 @@
 		return;
 
 	/* avoid temporary routing loops */
-	if ((orig_node->router) && (orig_node->router->orig_node->router) &&
-	    (compare_orig(orig_node->router->addr, batman_packet->prev_sender)) &&
+	if ((orig_node->router) &&
+	    (orig_node->router->orig_node->router) &&
+	    (compare_orig(orig_node->router->addr,
+			  batman_packet->prev_sender)) &&
 	    !(compare_orig(batman_packet->orig, batman_packet->prev_sender)) &&
-	    (compare_orig(orig_node->router->addr, orig_node->router->orig_node->router->addr))) {
-		debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %s) \n", neigh_str);
+	    (compare_orig(orig_node->router->addr,
+			  orig_node->router->orig_node->router->addr))) {
+		bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %pM) \n", ethhdr->h_source);
 		return;
 	}
 
-	/* if sender is a direct neighbor the sender mac equals originator mac */
-	orig_neigh_node = (is_single_hop_neigh ? orig_node : get_orig_node(ethhdr->h_source));
+	/* if sender is a direct neighbor the sender mac equals
+	 * originator mac */
+	orig_neigh_node = (is_single_hop_neigh ?
+			   orig_node : get_orig_node(ethhdr->h_source));
 	if (orig_neigh_node == NULL)
 		return;
 
-	/* drop packet if sender is not a direct neighbor and if we don't route towards it */
-	if (!is_single_hop_neigh && (orig_neigh_node->router == NULL)) {
-		debug_log(LOG_TYPE_BATMAN, "Drop packet: OGM via unknown neighbor! \n");
+	/* drop packet if sender is not a direct neighbor and if we
+	 * don't route towards it */
+	if (!is_single_hop_neigh &&
+	    (orig_neigh_node->router == NULL)) {
+		bat_dbg(DBG_BATMAN, "Drop packet: OGM via unknown neighbor!\n");
 		return;
 	}
 
-	is_bidirectional = isBidirectionalNeigh(orig_node, orig_neigh_node, batman_packet, if_incoming);
+	is_bidirectional = isBidirectionalNeigh(orig_node, orig_neigh_node,
+						batman_packet, if_incoming);
 
-	/* update ranking if it is not a duplicate or has the same seqno and similar ttl as the non-duplicate */
-	if (is_bidirectional && (!is_duplicate ||
-		((orig_node->last_real_seqno == batman_packet->seqno) &&
-			(orig_node->last_ttl - 3 <= batman_packet->ttl))))
-		update_orig(orig_node, ethhdr, batman_packet, if_incoming, hna_buff, hna_buff_len, is_duplicate);
+	/* update ranking if it is not a duplicate or has the same
+	 * seqno and similar ttl as the non-duplicate */
+	if (is_bidirectional &&
+	    (!is_duplicate ||
+	     ((orig_node->last_real_seqno == batman_packet->seqno) &&
+	      (orig_node->last_ttl - 3 <= batman_packet->ttl))))
+		update_orig(orig_node, ethhdr, batman_packet,
+			    if_incoming, hna_buff, hna_buff_len, is_duplicate);
 
-	/* is single hop (direct) neighbour */
+	/* is single hop (direct) neighbor */
 	if (is_single_hop_neigh) {
 
 		/* mark direct link on incoming interface */
-		schedule_forward_packet(orig_node, ethhdr, batman_packet, 1, hna_buff_len, if_incoming);
+		schedule_forward_packet(orig_node, ethhdr, batman_packet,
+					1, hna_buff_len, if_incoming);
 
-		debug_log(LOG_TYPE_BATMAN, "Forwarding packet: rebroadcast neighbour packet with direct link flag \n");
+		bat_dbg(DBG_BATMAN, "Forwarding packet: rebroadcast neighbor packet with direct link flag\n");
 		return;
 	}
 
 	/* multihop originator */
 	if (!is_bidirectional) {
-		debug_log(LOG_TYPE_BATMAN, "Drop packet: not received via bidirectional link\n");
+		bat_dbg(DBG_BATMAN,
+			"Drop packet: not received via bidirectional link\n");
 		return;
 	}
 
 	if (is_duplicate) {
-		debug_log(LOG_TYPE_BATMAN, "Drop packet: duplicate packet received\n");
+		bat_dbg(DBG_BATMAN, "Drop packet: duplicate packet received\n");
 		return;
 	}
 
-	debug_log(LOG_TYPE_BATMAN, "Forwarding packet: rebroadcast originator packet \n");
-	schedule_forward_packet(orig_node, ethhdr, batman_packet, 0, hna_buff_len, if_incoming);
+	bat_dbg(DBG_BATMAN,
+		"Forwarding packet: rebroadcast originator packet\n");
+	schedule_forward_packet(orig_node, ethhdr, batman_packet,
+				0, hna_buff_len, if_incoming);
 }
 
-void purge_orig(struct work_struct *work)
+int recv_bat_packet(struct sk_buff *skb,
+				struct batman_if *batman_if)
 {
-	struct list_head *list_pos, *list_pos_tmp;
-	struct hash_it_t *hashit = NULL;
-	struct orig_node *orig_node;
-	struct neigh_node *neigh_node, *best_neigh_node;
-	char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN], neigh_purged;
-
-	spin_lock(&orig_hash_lock);
-
-	/* for all origins... */
-	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
-
-		orig_node = hashit->bucket->data;
-		addr_to_string(orig_str, orig_node->orig);
-
-		if (time_after(jiffies, orig_node->last_valid + ((2 * PURGE_TIMEOUT * HZ) / 1000))) {
-
-			debug_log(LOG_TYPE_BATMAN, "Originator timeout: originator %s, last_valid %u \n", orig_str, (orig_node->last_valid / HZ));
-
-			hash_remove_bucket(orig_hash, hashit);
-			free_orig_node(orig_node);
-
-		} else {
-
-			best_neigh_node = NULL;
-			neigh_purged = 0;
-
-			/* for all neighbours towards this originator ... */
-			list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
-				neigh_node = list_entry(list_pos, struct neigh_node, list);
-
-				if (time_after(jiffies, neigh_node->last_valid + ((PURGE_TIMEOUT * HZ) / 1000))) {
-
-					addr_to_string(neigh_str, neigh_node->addr);
-					debug_log(LOG_TYPE_BATMAN, "Neighbour timeout: originator %s, neighbour: %s, last_valid %u \n", orig_str, neigh_str, (neigh_node->last_valid / HZ));
-
-					neigh_purged = 1;
-					list_del(list_pos);
-					kfree(neigh_node);
-
-				} else {
-
-					if ((best_neigh_node == NULL) || (neigh_node->tq_avg > best_neigh_node->tq_avg))
-						best_neigh_node = neigh_node;
-
-				}
-
-			}
-
-			if (neigh_purged)
-				update_routes(orig_node, best_neigh_node, orig_node->hna_buff, orig_node->hna_buff_len);
-
-		}
-
-	}
-
-	spin_unlock(&orig_hash_lock);
-
-	start_purge_timer();
-}
-
-static int receive_raw_packet(struct socket *raw_sock, unsigned char *packet_buff, int packet_buff_len)
-{
-	struct kvec iov;
-	struct msghdr msg;
-
-	iov.iov_base = packet_buff;
-	iov.iov_len = packet_buff_len;
-
-	msg.msg_flags = MSG_DONTWAIT;	/* non-blocking */
-	msg.msg_name = NULL;
-	msg.msg_namelen = 0;
-	msg.msg_control = NULL;
-
-	return kernel_recvmsg(raw_sock, &msg, &iov, 1, packet_buff_len, MSG_DONTWAIT);
-}
-
-int packet_recv_thread(void *data)
-{
-	struct batman_if *batman_if;
 	struct ethhdr *ethhdr;
-	struct batman_packet *batman_packet;
-	struct unicast_packet *unicast_packet;
-	struct bcast_packet *bcast_packet;
-	struct icmp_packet *icmp_packet;
-	struct vis_packet *vis_packet;
-	struct orig_node *orig_node;
-	unsigned char *packet_buff, src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN];
-	int vis_info_len;
-	int result;
+	unsigned long flags;
 
-	atomic_set(&data_ready_cond, 0);
-	atomic_set(&exit_cond, 0);
-	packet_buff = kmalloc(PACKBUFF_SIZE, GFP_KERNEL);
-	if (!packet_buff) {
-		debug_log(LOG_TYPE_CRIT, "Could allocate memory for the packet buffer. :(\n");
-		return -1;
-	}
+	/* drop packet if it has not necessary minimum size */
+	if (skb_headlen(skb) < sizeof(struct batman_packet))
+		return NET_RX_DROP;
 
-	while ((!kthread_should_stop()) && (!atomic_read(&exit_cond))) {
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 
-		wait_event_interruptible(thread_wait, (atomic_read(&data_ready_cond) || atomic_read(&exit_cond)));
+	/* packet with broadcast indication but unicast recipient */
+	if (!is_bcast(ethhdr->h_dest))
+		return NET_RX_DROP;
 
-		atomic_set(&data_ready_cond, 0);
+	/* packet with broadcast sender address */
+	if (is_bcast(ethhdr->h_source))
+		return NET_RX_DROP;
 
-		if (kthread_should_stop() || atomic_read(&exit_cond))
-			break;
+	spin_lock_irqsave(&orig_hash_lock, flags);
+	/* TODO: we use headlen instead of "length", because
+	 * only this data is paged in. */
+	/* TODO: is another skb_copy needed here? there will be
+	 * written on the data, but nobody (?) should further use
+	 * this data */
+	receive_aggr_bat_packet(ethhdr,
+				skb->data,
+				skb_headlen(skb),
+				batman_if);
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
 
-		/* we only want to safely traverse the list, hard-interfaces
-		 * won't be deleted anyway as long as this thread runs. */
-
-		rcu_read_lock();
-		list_for_each_entry_rcu(batman_if, &if_list, list) {
-			rcu_read_unlock();
-
-			result = -1;
-
-			while (1) {
-				if (batman_if->if_active != IF_ACTIVE) {
-					if (batman_if->if_active != IF_TO_BE_ACTIVATED)
-						debug_log(LOG_TYPE_NOTICE,
-						          "Could not read from deactivated interface %s!\n",
-						          batman_if->dev);
-
-					if (batman_if->raw_sock)
-						receive_raw_packet(batman_if->raw_sock, packet_buff, PACKBUFF_SIZE);
-					result = 0;
-					break;
-				}
-
-				result = receive_raw_packet(batman_if->raw_sock, packet_buff, PACKBUFF_SIZE);
-				if (result <= 0)
-					break;
-
-				if (result < sizeof(struct ethhdr) + 2)
-					continue;
-
-				ethhdr = (struct ethhdr *)packet_buff;
-				batman_packet = (struct batman_packet *)(packet_buff + sizeof(struct ethhdr));
-
-				if (batman_packet->version != COMPAT_VERSION) {
-					debug_log(LOG_TYPE_BATMAN, "Drop packet: incompatible batman version (%i) \n", batman_packet->version);
-					continue;
-				}
-
-				switch (batman_packet->packet_type) {
-				/* batman originator packet */
-				case BAT_PACKET:
-					/* packet with broadcast indication but unicast recipient */
-					if (!is_bcast(ethhdr->h_dest))
-						continue;
-
-					/* packet with broadcast sender address */
-					if (is_bcast(ethhdr->h_source))
-						continue;
-
-					/* drop packet if it has not at least one batman packet as payload */
-					if (result < sizeof(struct ethhdr) + sizeof(struct batman_packet))
-						continue;
-
-					spin_lock(&orig_hash_lock);
-					receive_aggr_bat_packet(ethhdr,
-					                        packet_buff + sizeof(struct ethhdr),
-					                        result - sizeof(struct ethhdr),
-					                        batman_if);
-					spin_unlock(&orig_hash_lock);
-
-					break;
-
-				/* batman icmp packet */
-				case BAT_ICMP:
-					/* packet with unicast indication but broadcast recipient */
-					if (is_bcast(ethhdr->h_dest))
-						continue;
-
-					/* packet with broadcast sender address */
-					if (is_bcast(ethhdr->h_source))
-						continue;
-
-					/* not for me */
-					if (!is_my_mac(ethhdr->h_dest))
-						continue;
-
-					/* drop packet if it has not necessary minimum size */
-					if (result < sizeof(struct ethhdr) + sizeof(struct icmp_packet))
-						continue;
-
-					icmp_packet = (struct icmp_packet *)(packet_buff + sizeof(struct ethhdr));
-
-					/* packet for me */
-					if (is_my_mac(icmp_packet->dst)) {
-
-						/* add data to device queue */
-						if (icmp_packet->msg_type != ECHO_REQUEST) {
-							bat_device_receive_packet(icmp_packet);
-							continue;
-						}
-
-						/* answer echo request (ping) */
-						/* get routing information */
-						spin_lock(&orig_hash_lock);
-						orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->orig));
-
-						if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
-
-							memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
-							memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
-							icmp_packet->msg_type = ECHO_REPLY;
-							icmp_packet->ttl = TTL;
-
-							send_raw_packet(packet_buff + sizeof(struct ethhdr),
-							                result - sizeof(struct ethhdr),
-							                orig_node->batman_if,
-							                orig_node->router->addr);
-
-						}
-
-						spin_unlock(&orig_hash_lock);
-						continue;
-
-					}
-
-					/* TTL exceeded */
-					if (icmp_packet->ttl < 2) {
-
-						addr_to_string(src_str, icmp_packet->orig);
-						addr_to_string(dst_str, icmp_packet->dst);
-
-						debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str);
-
-						/* send TTL exceeded if packet is an echo request (traceroute) */
-						if (icmp_packet->msg_type != ECHO_REQUEST)
-							continue;
-
-						/* get routing information */
-						spin_lock(&orig_hash_lock);
-						orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->orig));
-
-						if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
-
-							memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
-							memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
-							icmp_packet->msg_type = TTL_EXCEEDED;
-							icmp_packet->ttl = TTL;
-
-							send_raw_packet(packet_buff + sizeof(struct ethhdr),
-							                result - sizeof(struct ethhdr),
-							                orig_node->batman_if,
-							                orig_node->router->addr);
-
-						}
-
-						spin_unlock(&orig_hash_lock);
-						continue;
-
-					}
-
-					/* get routing information */
-					spin_lock(&orig_hash_lock);
-					orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->dst));
-
-					if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
-
-						/* decrement ttl */
-						icmp_packet->ttl--;
-
-						/* route it */
-						send_raw_packet(packet_buff + sizeof(struct ethhdr),
-						                result - sizeof(struct ethhdr),
-						                orig_node->batman_if,
-						                orig_node->router->addr);
-					}
-
-					spin_unlock(&orig_hash_lock);
-					break;
-
-				/* unicast packet */
-				case BAT_UNICAST:
-					/* packet with unicast indication but broadcast recipient */
-					if (is_bcast(ethhdr->h_dest))
-						continue;
-
-					/* packet with broadcast sender address */
-					if (is_bcast(ethhdr->h_source))
-						continue;
-
-					/* not for me */
-					if (!is_my_mac(ethhdr->h_dest))
-						continue;
-
-					/* drop packet if it has not necessary minimum size */
-					if (result < sizeof(struct ethhdr) + sizeof(struct unicast_packet))
-						continue;
-
-					unicast_packet = (struct unicast_packet *)(packet_buff + sizeof(struct ethhdr));
-
-					/* packet for me */
-					if (is_my_mac(unicast_packet->dest)) {
-
-						interface_rx(soft_device, packet_buff + sizeof(struct ethhdr) + sizeof(struct unicast_packet), result - sizeof(struct ethhdr) - sizeof(struct unicast_packet));
-						continue;
-
-					}
-
-					/* TTL exceeded */
-					if (unicast_packet->ttl < 2) {
-						addr_to_string(src_str, ((struct ethhdr *)(unicast_packet + 1))->h_source);
-						addr_to_string(dst_str, unicast_packet->dest);
-
-						debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str);
-						continue;
-					}
-
-					/* get routing information */
-					spin_lock(&orig_hash_lock);
-					orig_node = ((struct orig_node *)hash_find(orig_hash, unicast_packet->dest));
-
-					if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
-						/* decrement ttl */
-						unicast_packet->ttl--;
-
-						/* route it */
-						send_raw_packet(packet_buff + sizeof(struct ethhdr),
-						                result - sizeof(struct ethhdr),
-						                orig_node->batman_if,
-						                orig_node->router->addr);
-					}
-
-					spin_unlock(&orig_hash_lock);
-					break;
-
-				/* broadcast packet */
-				case BAT_BCAST:
-					/* packet with broadcast indication but unicast recipient */
-					if (!is_bcast(ethhdr->h_dest))
-						continue;
-
-					/* packet with broadcast sender address */
-					if (is_bcast(ethhdr->h_source))
-						continue;
-
-					/* drop packet if it has not necessary minimum size */
-					if (result < sizeof(struct ethhdr) + sizeof(struct bcast_packet))
-						continue;
-
-					/* ignore broadcasts sent by myself */
-					if (is_my_mac(ethhdr->h_source))
-						continue;
-
-					bcast_packet = (struct bcast_packet *)(packet_buff + sizeof(struct ethhdr));
-
-					/* ignore broadcasts originated by myself */
-					if (is_my_mac(bcast_packet->orig))
-						continue;
-
-					spin_lock(&orig_hash_lock);
-					orig_node = ((struct orig_node *)hash_find(orig_hash, bcast_packet->orig));
-
-					if (orig_node == NULL) {
-						spin_unlock(&orig_hash_lock);
-						continue;
-					}
-
-					/* check flood history */
-					if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, ntohs(bcast_packet->seqno))) {
-						spin_unlock(&orig_hash_lock);
-						continue;
-					}
-
-					/* mark broadcast in flood history */
-					if (bit_get_packet(orig_node->bcast_bits, ntohs(bcast_packet->seqno) - orig_node->last_bcast_seqno, 1))
-						orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno);
-
-					spin_unlock(&orig_hash_lock);
-
-					/* broadcast for me */
-					interface_rx(soft_device, packet_buff + sizeof(struct ethhdr) + sizeof(struct bcast_packet), result - sizeof(struct ethhdr) - sizeof(struct bcast_packet));
-
-					/* rebroadcast packet */
-					add_bcast_packet_to_list(packet_buff + sizeof(struct ethhdr),
-									result - sizeof(struct ethhdr));
-
-					break;
-
-				/* vis packet */
-				case BAT_VIS:
-					/* drop if too short. */
-					if (result < sizeof(struct ethhdr) + sizeof(struct vis_packet))
-						continue;
-
-					/* not for me */
-					if (!is_my_mac(ethhdr->h_dest))
-						continue;
-
-					vis_packet = (struct vis_packet *)(packet_buff + sizeof(struct ethhdr));
-					vis_info_len = result  - sizeof(struct ethhdr) - sizeof(struct vis_packet);
-
-					/* ignore own packets */
-					if (is_my_mac(vis_packet->vis_orig))
-						continue;
-
-					if (is_my_mac(vis_packet->sender_orig))
-						continue;
-
-					switch (vis_packet->vis_type) {
-					case VIS_TYPE_SERVER_SYNC:
-						receive_server_sync_packet(vis_packet, vis_info_len);
-						break;
-
-					case VIS_TYPE_CLIENT_UPDATE:
-						receive_client_update_packet(vis_packet, vis_info_len);
-						break;
-
-					default:	/* ignore unknown packet */
-						break;
-					}
-
-					break;
-				}
-
-			}
-
-			if ((result < 0) && (result != -EAGAIN))
-				debug_log(LOG_TYPE_CRIT, "Could not receive packet from interface %s: %i\n", batman_if->dev, result);
-
-			/* lock for the next iteration */
-			rcu_read_lock();
-		}
-		rcu_read_unlock();
-
-	}
-	kfree(packet_buff);
-
-	/* do not exit until kthread_stop() is actually called, otherwise it will wait for us
-	 * forever. */
-	while (!kthread_should_stop())
-		schedule();
-
-	return 0;
+	kfree_skb(skb);
+	return NET_RX_SUCCESS;
 }
 
-void batman_data_ready(struct sock *sk, int len)
+static int recv_my_icmp_packet(struct sk_buff *skb)
 {
-	void (*data_ready)(struct sock *, int) = sk->sk_user_data;
+	struct orig_node *orig_node;
+	struct icmp_packet *icmp_packet;
+	struct ethhdr *ethhdr;
+	struct sk_buff *skb_old;
+	struct batman_if *batman_if;
+	int ret;
+	unsigned long flags;
+	uint8_t dstaddr[ETH_ALEN];
 
-	data_ready(sk, len);
+	icmp_packet = (struct icmp_packet *) skb->data;
+	ethhdr = (struct ethhdr *) skb_mac_header(skb);
 
-	atomic_set(&data_ready_cond, 1);
-	wake_up_interruptible(&thread_wait);
+	/* add data to device queue */
+	if (icmp_packet->msg_type != ECHO_REQUEST) {
+		bat_device_receive_packet(icmp_packet);
+		return NET_RX_DROP;
+	}
+
+	/* answer echo request (ping) */
+	/* get routing information */
+	spin_lock_irqsave(&orig_hash_lock, flags);
+	orig_node = ((struct orig_node *)hash_find(orig_hash,
+						   icmp_packet->orig));
+	ret = NET_RX_DROP;
+
+	if ((orig_node != NULL) &&
+	    (orig_node->batman_if != NULL) &&
+	    (orig_node->router != NULL)) {
+
+		/* don't lock while sending the packets ... we therefore
+		 * copy the required data before sending */
+		batman_if = orig_node->batman_if;
+		memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+		/* create a copy of the skb, if needed, to modify it. */
+		skb_old = NULL;
+		if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
+			skb_old = skb;
+			skb = skb_copy(skb, GFP_ATOMIC);
+			if (!skb)
+				return NET_RX_DROP;
+			icmp_packet = (struct icmp_packet *) skb->data;
+			kfree_skb(skb_old);
+		}
+
+		memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+		memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
+		icmp_packet->msg_type = ECHO_REPLY;
+		icmp_packet->ttl = TTL;
+
+		send_skb_packet(skb, batman_if, dstaddr);
+		ret = NET_RX_SUCCESS;
+
+	} else
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+	return ret;
 }
 
+static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
+{
+	struct orig_node *orig_node;
+	struct icmp_packet *icmp_packet;
+	struct ethhdr *ethhdr;
+	struct sk_buff *skb_old;
+	struct batman_if *batman_if;
+	int ret;
+	unsigned long flags;
+	uint8_t dstaddr[ETH_ALEN];
+
+	icmp_packet = (struct icmp_packet *)skb->data;
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+	/* send TTL exceeded if packet is an echo request (traceroute) */
+	if (icmp_packet->msg_type != ECHO_REQUEST) {
+		printk(KERN_WARNING "batman-adv:Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
+			icmp_packet->orig, icmp_packet->dst);
+		return NET_RX_DROP;
+	}
+
+	/* get routing information */
+	spin_lock_irqsave(&orig_hash_lock, flags);
+	orig_node = ((struct orig_node *)
+		     hash_find(orig_hash, icmp_packet->orig));
+	ret = NET_RX_DROP;
+
+	if ((orig_node != NULL) &&
+	    (orig_node->batman_if != NULL) &&
+	    (orig_node->router != NULL)) {
+
+		/* don't lock while sending the packets ... we therefore
+		 * copy the required data before sending */
+		batman_if = orig_node->batman_if;
+		memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+		/* create a copy of the skb, if needed, to modify it. */
+		if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
+			skb_old = skb;
+			skb = skb_copy(skb, GFP_ATOMIC);
+			if (!skb)
+				return NET_RX_DROP;
+			icmp_packet = (struct icmp_packet *) skb->data;
+			kfree_skb(skb_old);
+		}
+
+		memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+		memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
+		icmp_packet->msg_type = TTL_EXCEEDED;
+		icmp_packet->ttl = TTL;
+
+		send_skb_packet(skb, batman_if, dstaddr);
+		ret = NET_RX_SUCCESS;
+
+	} else
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+	return ret;
+}
+
+
+int recv_icmp_packet(struct sk_buff *skb)
+{
+	struct icmp_packet *icmp_packet;
+	struct ethhdr *ethhdr;
+	struct orig_node *orig_node;
+	struct sk_buff *skb_old;
+	struct batman_if *batman_if;
+	int hdr_size = sizeof(struct icmp_packet);
+	int ret;
+	unsigned long flags;
+	uint8_t dstaddr[ETH_ALEN];
+
+	/* drop packet if it has not necessary minimum size */
+	if (skb_headlen(skb) < hdr_size)
+		return NET_RX_DROP;
+
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+	/* packet with unicast indication but broadcast recipient */
+	if (is_bcast(ethhdr->h_dest))
+		return NET_RX_DROP;
+
+	/* packet with broadcast sender address */
+	if (is_bcast(ethhdr->h_source))
+		return NET_RX_DROP;
+
+	/* not for me */
+	if (!is_my_mac(ethhdr->h_dest))
+		return NET_RX_DROP;
+
+	icmp_packet = (struct icmp_packet *) skb->data;
+
+	/* packet for me */
+	if (is_my_mac(icmp_packet->dst))
+		return recv_my_icmp_packet(skb);
+
+	/* TTL exceeded */
+	if (icmp_packet->ttl < 2)
+		return recv_icmp_ttl_exceeded(skb);
+
+	ret = NET_RX_DROP;
+
+	/* get routing information */
+	spin_lock_irqsave(&orig_hash_lock, flags);
+	orig_node = ((struct orig_node *)
+		     hash_find(orig_hash, icmp_packet->dst));
+
+	if ((orig_node != NULL) &&
+	    (orig_node->batman_if != NULL) &&
+	    (orig_node->router != NULL)) {
+
+		/* don't lock while sending the packets ... we therefore
+		 * copy the required data before sending */
+		batman_if = orig_node->batman_if;
+		memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+		/* create a copy of the skb, if needed, to modify it. */
+		if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
+			skb_old = skb;
+			skb = skb_copy(skb, GFP_ATOMIC);
+			if (!skb)
+				return NET_RX_DROP;
+			icmp_packet = (struct icmp_packet *) skb->data;
+			kfree_skb(skb_old);
+		}
+
+		/* decrement ttl */
+		icmp_packet->ttl--;
+
+		/* route it */
+		send_skb_packet(skb, batman_if, dstaddr);
+		ret = NET_RX_SUCCESS;
+
+	} else
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+	return ret;
+}
+
+int recv_unicast_packet(struct sk_buff *skb)
+{
+	struct unicast_packet *unicast_packet;
+	struct orig_node *orig_node;
+	struct ethhdr *ethhdr;
+	struct batman_if *batman_if;
+	struct sk_buff *skb_old;
+	uint8_t dstaddr[ETH_ALEN];
+	int hdr_size = sizeof(struct unicast_packet);
+	int ret;
+	unsigned long flags;
+
+	/* drop packet if it has not necessary minimum size */
+	if (skb_headlen(skb) < hdr_size)
+		return NET_RX_DROP;
+
+	ethhdr = (struct ethhdr *) skb_mac_header(skb);
+
+	/* packet with unicast indication but broadcast recipient */
+	if (is_bcast(ethhdr->h_dest))
+		return NET_RX_DROP;
+
+	/* packet with broadcast sender address */
+	if (is_bcast(ethhdr->h_source))
+		return NET_RX_DROP;
+
+	/* not for me */
+	if (!is_my_mac(ethhdr->h_dest))
+		return NET_RX_DROP;
+
+	unicast_packet = (struct unicast_packet *) skb->data;
+
+	/* packet for me */
+	if (is_my_mac(unicast_packet->dest)) {
+		interface_rx(skb, hdr_size);
+		return NET_RX_SUCCESS;
+	}
+
+	/* TTL exceeded */
+	if (unicast_packet->ttl < 2) {
+		printk(KERN_WARNING "batman-adv:Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n",
+		       ethhdr->h_source, unicast_packet->dest);
+		return NET_RX_DROP;
+	}
+
+	ret = NET_RX_DROP;
+	/* get routing information */
+	spin_lock_irqsave(&orig_hash_lock, flags);
+	orig_node = ((struct orig_node *)
+		     hash_find(orig_hash, unicast_packet->dest));
+
+	if ((orig_node != NULL) &&
+	    (orig_node->batman_if != NULL) &&
+	    (orig_node->router != NULL)) {
+
+		/* don't lock while sending the packets ... we therefore
+		 * copy the required data before sending */
+		batman_if = orig_node->batman_if;
+		memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+		/* create a copy of the skb, if needed, to modify it. */
+		if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) {
+			skb_old = skb;
+			skb = skb_copy(skb, GFP_ATOMIC);
+			if (!skb)
+				return NET_RX_DROP;
+			unicast_packet = (struct unicast_packet *) skb->data;
+			kfree_skb(skb_old);
+		}
+		/* decrement ttl */
+		unicast_packet->ttl--;
+
+		/* route it */
+		send_skb_packet(skb, batman_if, dstaddr);
+		ret = NET_RX_SUCCESS;
+
+	} else
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+	return ret;
+}
+
+
+int recv_bcast_packet(struct sk_buff *skb)
+{
+	struct orig_node *orig_node;
+	struct bcast_packet *bcast_packet;
+	struct ethhdr *ethhdr;
+	int hdr_size = sizeof(struct bcast_packet);
+	unsigned long flags;
+
+	/* drop packet if it has not necessary minimum size */
+	if (skb_headlen(skb) < hdr_size)
+		return NET_RX_DROP;
+
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+	/* packet with broadcast indication but unicast recipient */
+	if (!is_bcast(ethhdr->h_dest))
+		return NET_RX_DROP;
+
+	/* packet with broadcast sender address */
+	if (is_bcast(ethhdr->h_source))
+		return NET_RX_DROP;
+
+	/* ignore broadcasts sent by myself */
+	if (is_my_mac(ethhdr->h_source))
+		return NET_RX_DROP;
+
+	bcast_packet = (struct bcast_packet *) skb->data;
+
+	/* ignore broadcasts originated by myself */
+	if (is_my_mac(bcast_packet->orig))
+		return NET_RX_DROP;
+
+	spin_lock_irqsave(&orig_hash_lock, flags);
+	orig_node = ((struct orig_node *)
+		     hash_find(orig_hash, bcast_packet->orig));
+
+	if (orig_node == NULL) {
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+		return NET_RX_DROP;
+	}
+
+	/* check flood history */
+	if (get_bit_status(orig_node->bcast_bits,
+			   orig_node->last_bcast_seqno,
+			   ntohs(bcast_packet->seqno))) {
+		spin_unlock_irqrestore(&orig_hash_lock, flags);
+		return NET_RX_DROP;
+	}
+
+	/* mark broadcast in flood history */
+	if (bit_get_packet(orig_node->bcast_bits,
+			   ntohs(bcast_packet->seqno) -
+			   orig_node->last_bcast_seqno, 1))
+		orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno);
+
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+	/* rebroadcast packet */
+	add_bcast_packet_to_list(skb);
+
+	/* broadcast for me */
+	interface_rx(skb, hdr_size);
+
+	return NET_RX_SUCCESS;
+}
+
+int recv_vis_packet(struct sk_buff *skb)
+{
+	struct vis_packet *vis_packet;
+	struct ethhdr *ethhdr;
+	int hdr_size = sizeof(struct vis_packet);
+
+	if (skb_headlen(skb) < hdr_size)
+		return NET_RX_DROP;
+
+	vis_packet = (struct vis_packet *) skb->data;
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+	/* not for me */
+	if (!is_my_mac(ethhdr->h_dest))
+		return NET_RX_DROP;
+
+	/* ignore own packets */
+	if (is_my_mac(vis_packet->vis_orig))
+		return NET_RX_DROP;
+
+	if (is_my_mac(vis_packet->sender_orig))
+		return NET_RX_DROP;
+
+	switch (vis_packet->vis_type) {
+	case VIS_TYPE_SERVER_SYNC:
+		/* TODO: handle fragmented skbs properly */
+		receive_server_sync_packet(vis_packet, skb_headlen(skb));
+		break;
+
+	case VIS_TYPE_CLIENT_UPDATE:
+		/* TODO: handle fragmented skbs properly */
+		receive_client_update_packet(vis_packet, skb_headlen(skb));
+		break;
+
+	default:	/* ignore unknown packet */
+		break;
+	}
+
+	/* We take a copy of the data in the packet, so we should
+	   always free the skbuf. */
+	return NET_RX_DROP;
+}
diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h
index 0123ea8..939b8d4 100644
--- a/drivers/staging/batman-adv/routing.h
+++ b/drivers/staging/batman-adv/routing.h
@@ -22,13 +22,18 @@
 #include "types.h"
 
 extern wait_queue_head_t thread_wait;
-extern atomic_t exit_cond;
 
-int originator_init(void);
-void free_orig_node(void *data);
-void originator_free(void);
 void slide_own_bcast_window(struct batman_if *batman_if);
-void batman_data_ready(struct sock *sk, int len);
-void purge_orig(struct work_struct *work);
-int packet_recv_thread(void *data);
-void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming);
+void receive_bat_packet(struct ethhdr *ethhdr,
+				struct batman_packet *batman_packet,
+				unsigned char *hna_buff, int hna_buff_len,
+				struct batman_if *if_incoming);
+void update_routes(struct orig_node *orig_node,
+				struct neigh_node *neigh_node,
+				unsigned char *hna_buff, int hna_buff_len);
+int recv_icmp_packet(struct sk_buff *skb);
+int recv_unicast_packet(struct sk_buff *skb);
+int recv_bcast_packet(struct sk_buff *skb);
+int recv_vis_packet(struct sk_buff *skb);
+int recv_bat_packet(struct sk_buff *skb,
+				struct batman_if *batman_if);
diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c
index eb61750..2a9fac8 100644
--- a/drivers/staging/batman-adv/send.c
+++ b/drivers/staging/batman-adv/send.c
@@ -21,16 +21,14 @@
 
 #include "main.h"
 #include "send.h"
-#include "log.h"
 #include "routing.h"
 #include "translation-table.h"
+#include "soft-interface.h"
 #include "hard-interface.h"
 #include "types.h"
 #include "vis.h"
 #include "aggregation.h"
 
-#include "compat.h"
-
 /* apply hop penalty for a normal link */
 static uint8_t hop_penalty(const uint8_t tq)
 {
@@ -59,51 +57,69 @@
 	return send_time;
 }
 
-/* sends a raw packet. */
-void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
-		     struct batman_if *batman_if, uint8_t *dst_addr)
+/* send out an already prepared packet to the given address via the
+ * specified batman interface */
+int send_skb_packet(struct sk_buff *skb,
+				struct batman_if *batman_if,
+				uint8_t *dst_addr)
 {
 	struct ethhdr *ethhdr;
-	struct sk_buff *skb;
-	int retval;
-	char *data;
 
 	if (batman_if->if_active != IF_ACTIVE)
-		return;
+		goto send_skb_err;
+
+	if (unlikely(!batman_if->net_dev))
+		goto send_skb_err;
 
 	if (!(batman_if->net_dev->flags & IFF_UP)) {
-		debug_log(LOG_TYPE_WARN,
-		         "Interface %s is not up - can't send packet via that interface (IF_TO_BE_DEACTIVATED was here) !\n",
-		          batman_if->dev);
-		return;
+		printk(KERN_WARNING
+		       "batman-adv:Interface %s is not up - can't send packet via that interface!\n",
+		       batman_if->dev);
+		goto send_skb_err;
 	}
 
-	skb = dev_alloc_skb(pack_buff_len + sizeof(struct ethhdr));
-	if (!skb)
-		return;
-	data = skb_put(skb, pack_buff_len + sizeof(struct ethhdr));
+	/* push to the ethernet header. */
+	if (my_skb_push(skb, sizeof(struct ethhdr)) < 0)
+		goto send_skb_err;
 
-	memcpy(data + sizeof(struct ethhdr), pack_buff, pack_buff_len);
+	skb_reset_mac_header(skb);
 
-	ethhdr = (struct ethhdr *) data;
+	ethhdr = (struct ethhdr *) skb_mac_header(skb);
 	memcpy(ethhdr->h_source, batman_if->net_dev->dev_addr, ETH_ALEN);
 	memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN);
 	ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);
 
-	skb_reset_mac_header(skb);
 	skb_set_network_header(skb, ETH_HLEN);
 	skb->priority = TC_PRIO_CONTROL;
 	skb->protocol = __constant_htons(ETH_P_BATMAN);
+
 	skb->dev = batman_if->net_dev;
 
 	/* dev_queue_xmit() returns a negative result on error.	 However on
 	 * congestion and traffic shaping, it drops and returns NET_XMIT_DROP
 	 * (which is > 0). This will not be treated as an error. */
-	retval = dev_queue_xmit(skb);
-	if (retval < 0)
-		debug_log(LOG_TYPE_CRIT,
-		          "Can't write to raw socket (IF_TO_BE_DEACTIVATED was here): %i\n",
-		          retval);
+
+	return dev_queue_xmit(skb);
+send_skb_err:
+	kfree_skb(skb);
+	return NET_XMIT_DROP;
+}
+
+/* sends a raw packet. */
+void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
+		     struct batman_if *batman_if, uint8_t *dst_addr)
+{
+	struct sk_buff *skb;
+	char *data;
+
+	skb = dev_alloc_skb(pack_buff_len + sizeof(struct ethhdr));
+	if (!skb)
+		return;
+	data = skb_put(skb, pack_buff_len + sizeof(struct ethhdr));
+	memcpy(data + sizeof(struct ethhdr), pack_buff, pack_buff_len);
+	/* pull back to the batman "network header" */
+	skb_pull(skb, sizeof(struct ethhdr));
+	send_skb_packet(skb, batman_if, dst_addr);
 }
 
 /* Send a packet to a given interface */
@@ -114,7 +130,6 @@
 	uint8_t packet_num;
 	int16_t buff_pos;
 	struct batman_packet *batman_packet;
-	char orig_str[ETH_STR_LEN];
 
 	if (batman_if->if_active != IF_ACTIVE)
 		return;
@@ -136,19 +151,18 @@
 		else
 			batman_packet->flags &= ~DIRECTLINK;
 
-		addr_to_string(orig_str, batman_packet->orig);
 		fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ?
 							    "Sending own" :
 							    "Forwarding"));
-		debug_log(LOG_TYPE_BATMAN,
-			  "%s %spacket (originator %s, seqno %d, TQ %d, TTL %d, IDF %s) on interface %s [%s]\n",
-			  fwd_str,
-			  (packet_num > 0 ? "aggregated " : ""),
-			  orig_str, ntohs(batman_packet->seqno),
-			  batman_packet->tq, batman_packet->ttl,
-			  (batman_packet->flags & DIRECTLINK ?
-			   "on" : "off"),
-			  batman_if->dev, batman_if->addr_str);
+		bat_dbg(DBG_BATMAN,
+			"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d, IDF %s) on interface %s [%s]\n",
+			fwd_str,
+			(packet_num > 0 ? "aggregated " : ""),
+			batman_packet->orig, ntohs(batman_packet->seqno),
+			batman_packet->tq, batman_packet->ttl,
+			(batman_packet->flags & DIRECTLINK ?
+			 "on" : "off"),
+			batman_if->dev, batman_if->addr_str);
 
 		buff_pos += sizeof(struct batman_packet) +
 			(batman_packet->num_hna * ETH_ALEN);
@@ -168,32 +182,28 @@
 	struct batman_if *batman_if;
 	struct batman_packet *batman_packet =
 		(struct batman_packet *)(forw_packet->packet_buff);
-	char orig_str[ETH_STR_LEN];
 	unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
 
 	if (!forw_packet->if_incoming) {
-		debug_log(LOG_TYPE_CRIT,
-			  "Error - can't forward packet: incoming iface not specified\n");
+		printk(KERN_ERR "batman-adv: Error - can't forward packet: incoming iface not specified\n");
 		return;
 	}
 
 	if (forw_packet->if_incoming->if_active != IF_ACTIVE)
 		return;
 
-	addr_to_string(orig_str, batman_packet->orig);
-
 	/* multihomed peer assumed */
 	/* non-primary OGMs are only broadcasted on their interface */
 	if ((directlink && (batman_packet->ttl == 1)) ||
 	    (forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
 
 		/* FIXME: what about aggregated packets ? */
-		debug_log(LOG_TYPE_BATMAN,
-			  "%s packet (originator %s, seqno %d, TTL %d) on interface %s [%s]\n",
-			  (forw_packet->own ? "Sending own" : "Forwarding"),
-			  orig_str, ntohs(batman_packet->seqno),
-			  batman_packet->ttl, forw_packet->if_incoming->dev,
-			  forw_packet->if_incoming->addr_str);
+		bat_dbg(DBG_BATMAN,
+			"%s packet (originator %pM, seqno %d, TTL %d) on interface %s [%s]\n",
+			(forw_packet->own ? "Sending own" : "Forwarding"),
+			batman_packet->orig, ntohs(batman_packet->seqno),
+			batman_packet->ttl, forw_packet->if_incoming->dev,
+			forw_packet->if_incoming->addr_str);
 
 		send_raw_packet(forw_packet->packet_buff,
 				forw_packet->packet_len,
@@ -238,6 +248,7 @@
 {
 	unsigned long send_time;
 	struct batman_packet *batman_packet;
+	int vis_server = atomic_read(&vis_mode);
 
 	/**
 	 * the interface gets activated here to avoid race conditions between
@@ -262,7 +273,7 @@
 	/* change sequence number to network order */
 	batman_packet->seqno = htons((uint16_t)atomic_read(&batman_if->seqno));
 
-	if (is_vis_server())
+	if (vis_server == VIS_TYPE_SERVER_SYNC)
 		batman_packet->flags = VIS_SERVER;
 	else
 		batman_packet->flags = 0;
@@ -286,7 +297,7 @@
 	unsigned long send_time;
 
 	if (batman_packet->ttl <= 1) {
-		debug_log(LOG_TYPE_BATMAN, "ttl exceeded \n");
+		bat_dbg(DBG_BATMAN, "ttl exceeded \n");
 		return;
 	}
 
@@ -314,9 +325,9 @@
 	/* apply hop penalty */
 	batman_packet->tq = hop_penalty(batman_packet->tq);
 
-	debug_log(LOG_TYPE_BATMAN, "Forwarding packet: tq_orig: %i, tq_avg: %i, tq_forw: %i, ttl_orig: %i, ttl_forw: %i \n",
-		  in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
-		  batman_packet->ttl);
+	bat_dbg(DBG_BATMAN, "Forwarding packet: tq_orig: %i, tq_avg: %i, tq_forw: %i, ttl_orig: %i, ttl_forw: %i \n",
+		in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
+		batman_packet->ttl);
 
 	batman_packet->seqno = htons(batman_packet->seqno);
 
@@ -333,6 +344,8 @@
 
 static void forw_packet_free(struct forw_packet *forw_packet)
 {
+	if (forw_packet->skb)
+		kfree_skb(forw_packet->skb);
 	kfree(forw_packet->packet_buff);
 	kfree(forw_packet);
 }
@@ -340,12 +353,13 @@
 static void _add_bcast_packet_to_list(struct forw_packet *forw_packet,
 				      unsigned long send_time)
 {
+	unsigned long flags;
 	INIT_HLIST_NODE(&forw_packet->list);
 
 	/* add new packet to packet list */
-	spin_lock(&forw_bcast_list_lock);
+	spin_lock_irqsave(&forw_bcast_list_lock, flags);
 	hlist_add_head(&forw_packet->list, &forw_bcast_list);
-	spin_unlock(&forw_bcast_list_lock);
+	spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
 
 	/* start timer for this packet */
 	INIT_DELAYED_WORK(&forw_packet->delayed_work,
@@ -354,7 +368,7 @@
 			   send_time);
 }
 
-void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len)
+void add_bcast_packet_to_list(struct sk_buff *skb)
 {
 	struct forw_packet *forw_packet;
 
@@ -362,14 +376,16 @@
 	if (!forw_packet)
 		return;
 
-	forw_packet->packet_buff = kmalloc(packet_len, GFP_ATOMIC);
-	if (!forw_packet->packet_buff) {
+	skb = skb_copy(skb, GFP_ATOMIC);
+	if (!skb) {
 		kfree(forw_packet);
 		return;
 	}
 
-	forw_packet->packet_len = packet_len;
-	memcpy(forw_packet->packet_buff, packet_buff, forw_packet->packet_len);
+	skb_reset_mac_header(skb);
+
+	forw_packet->skb = skb;
+	forw_packet->packet_buff = NULL;
 
 	/* how often did we send the bcast packet ? */
 	forw_packet->num_packets = 0;
@@ -384,16 +400,20 @@
 		container_of(work, struct delayed_work, work);
 	struct forw_packet *forw_packet =
 		container_of(delayed_work, struct forw_packet, delayed_work);
+	unsigned long flags;
+	struct sk_buff *skb1;
 
-	spin_lock(&forw_bcast_list_lock);
+	spin_lock_irqsave(&forw_bcast_list_lock, flags);
 	hlist_del(&forw_packet->list);
-	spin_unlock(&forw_bcast_list_lock);
+	spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
 
 	/* rebroadcast packet */
 	rcu_read_lock();
 	list_for_each_entry_rcu(batman_if, &if_list, list) {
-		send_raw_packet(forw_packet->packet_buff,
-				forw_packet->packet_len,
+		/* send a copy of the saved skb */
+		skb1 = skb_copy(forw_packet->skb, GFP_ATOMIC);
+		if (skb1)
+			send_skb_packet(skb1,
 				batman_if, broadcastAddr);
 	}
 	rcu_read_unlock();
@@ -415,10 +435,11 @@
 		container_of(work, struct delayed_work, work);
 	struct forw_packet *forw_packet =
 		container_of(delayed_work, struct forw_packet, delayed_work);
+	unsigned long flags;
 
-	spin_lock(&forw_bat_list_lock);
+	spin_lock_irqsave(&forw_bat_list_lock, flags);
 	hlist_del(&forw_packet->list);
-	spin_unlock(&forw_bat_list_lock);
+	spin_unlock_irqrestore(&forw_bat_list_lock, flags);
 
 	send_packet(forw_packet);
 
@@ -438,38 +459,39 @@
 {
 	struct forw_packet *forw_packet;
 	struct hlist_node *tmp_node, *safe_tmp_node;
+	unsigned long flags;
 
-	debug_log(LOG_TYPE_BATMAN, "purge_outstanding_packets()\n");
+	bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n");
 
 	/* free bcast list */
-	spin_lock(&forw_bcast_list_lock);
+	spin_lock_irqsave(&forw_bcast_list_lock, flags);
 	hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
 				  &forw_bcast_list, list) {
 
-		spin_unlock(&forw_bcast_list_lock);
+		spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
 
 		/**
 		 * send_outstanding_bcast_packet() will lock the list to
 		 * delete the item from the list
 		 */
 		cancel_delayed_work_sync(&forw_packet->delayed_work);
-		spin_lock(&forw_bcast_list_lock);
+		spin_lock_irqsave(&forw_bcast_list_lock, flags);
 	}
-	spin_unlock(&forw_bcast_list_lock);
+	spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
 
 	/* free batman packet list */
-	spin_lock(&forw_bat_list_lock);
+	spin_lock_irqsave(&forw_bat_list_lock, flags);
 	hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
 				  &forw_bat_list, list) {
 
-		spin_unlock(&forw_bat_list_lock);
+		spin_unlock_irqrestore(&forw_bat_list_lock, flags);
 
 		/**
 		 * send_outstanding_bat_packet() will lock the list to
 		 * delete the item from the list
 		 */
 		cancel_delayed_work_sync(&forw_packet->delayed_work);
-		spin_lock(&forw_bat_list_lock);
+		spin_lock_irqsave(&forw_bat_list_lock, flags);
 	}
-	spin_unlock(&forw_bat_list_lock);
+	spin_unlock_irqrestore(&forw_bat_list_lock, flags);
 }
diff --git a/drivers/staging/batman-adv/send.h b/drivers/staging/batman-adv/send.h
index 59d5009..5fc6f34 100644
--- a/drivers/staging/batman-adv/send.h
+++ b/drivers/staging/batman-adv/send.h
@@ -22,6 +22,9 @@
 #include "types.h"
 
 void send_own_packet_work(struct work_struct *work);
+int send_skb_packet(struct sk_buff *skb,
+				struct batman_if *batman_if,
+				uint8_t *dst_addr);
 void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
 		     struct batman_if *batman_if, uint8_t *dst_addr);
 void schedule_own_packet(struct batman_if *batman_if);
@@ -30,7 +33,7 @@
 			     struct batman_packet *batman_packet,
 			     uint8_t directlink, int hna_buff_len,
 			     struct batman_if *if_outgoing);
-void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len);
+void add_bcast_packet_to_list(struct sk_buff *skb);
 void send_outstanding_bcast_packet(struct work_struct *work);
 void send_outstanding_bat_packet(struct work_struct *work);
 void purge_outstanding_packets(void);
diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c
index d543f50..c9b35d9f 100644
--- a/drivers/staging/batman-adv/soft-interface.c
+++ b/drivers/staging/batman-adv/soft-interface.c
@@ -24,18 +24,15 @@
 #include "hard-interface.h"
 #include "send.h"
 #include "translation-table.h"
-#include "log.h"
 #include "types.h"
 #include "hash.h"
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
-#include "compat.h"
 
 static uint16_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid
 				  * broadcast storms */
 static int32_t skb_packets;
 static int32_t skb_bad_packets;
-static int32_t lock_dropped;
 
 unsigned char mainIfAddr[ETH_ALEN];
 static unsigned char mainIfAddr_default[ETH_ALEN];
@@ -68,12 +65,12 @@
 	return (memcmp(mainIfAddr, mainIfAddr_default, ETH_ALEN) != 0 ? 1 : 0);
 }
 
-static int my_skb_push(struct sk_buff *skb, unsigned int len)
+int my_skb_push(struct sk_buff *skb, unsigned int len)
 {
 	int result = 0;
 
 	skb_packets++;
-	if (skb->data - len < skb->head) {
+	if (skb_headroom(skb) < len) {
 		skb_bad_packets++;
 		result = pskb_expand_head(skb, len, 0, GFP_ATOMIC);
 
@@ -122,7 +119,7 @@
 
 	/* generate random address */
 	random_ether_addr(dev_addr);
-	memcpy(dev->dev_addr, dev_addr, sizeof(dev->dev_addr));
+	memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
 
 	SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
 
@@ -147,9 +144,18 @@
 	return &priv->stats;
 }
 
-int interface_set_mac_addr(struct net_device *dev, void *addr)
+int interface_set_mac_addr(struct net_device *dev, void *p)
 {
-	return -EBUSY;
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	hna_local_remove(dev->dev_addr, "mac address changed");
+	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+	hna_local_add(dev->dev_addr);
+
+	return 0;
 }
 
 int interface_change_mtu(struct net_device *dev, int new_mtu)
@@ -170,7 +176,10 @@
 	struct orig_node *orig_node;
 	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
 	struct bat_priv *priv = netdev_priv(dev);
+	struct batman_if *batman_if;
+	uint8_t dstaddr[6];
 	int data_len = skb->len;
+	unsigned long flags;
 
 	if (atomic_read(&module_state) != MODULE_ACTIVE)
 		goto dropped;
@@ -186,7 +195,6 @@
 			goto dropped;
 
 		bcast_packet = (struct bcast_packet *)skb->data;
-
 		bcast_packet->version = COMPAT_VERSION;
 
 		/* batman packet type: broadcast */
@@ -195,27 +203,21 @@
 		/* hw address of first interface is the orig mac because only
 		 * this mac is known throughout the mesh */
 		memcpy(bcast_packet->orig, mainIfAddr, ETH_ALEN);
+
 		/* set broadcast sequence number */
 		bcast_packet->seqno = htons(bcast_seqno);
 
 		bcast_seqno++;
 
 		/* broadcast packet */
-		add_bcast_packet_to_list(skb->data, skb->len);
+		add_bcast_packet_to_list(skb);
+		/* a copy is stored in the bcast list, therefore removing
+		 * the original skb. */
+		kfree_skb(skb);
 
 	/* unicast packet */
 	} else {
-
-		/* simply spin_lock()ing can deadlock when the lock is already
-		 * hold. */
-		/* TODO: defer the work in a working queue instead of
-		 * dropping */
-		if (!spin_trylock(&orig_hash_lock)) {
-			lock_dropped++;
-			debug_log(LOG_TYPE_NOTICE, "%d packets dropped because lock was hold\n", lock_dropped);
-			goto dropped;
-		}
-
+		spin_lock_irqsave(&orig_hash_lock, flags);
 		/* get routing information */
 		orig_node = ((struct orig_node *)hash_find(orig_hash,
 							   ethhdr->h_dest));
@@ -244,14 +246,17 @@
 			if (orig_node->batman_if->if_active != IF_ACTIVE)
 				goto unlock;
 
-			send_raw_packet(skb->data, skb->len,
-					orig_node->batman_if,
-					orig_node->router->addr);
+			/* don't lock while sending the packets ... we therefore
+			 * copy the required data before sending */
+
+			batman_if = orig_node->batman_if;
+			memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+			spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+			send_skb_packet(skb, batman_if, dstaddr);
 		} else {
 			goto unlock;
 		}
-
-		spin_unlock(&orig_hash_lock);
 	}
 
 	priv->stats.tx_packets++;
@@ -259,42 +264,44 @@
 	goto end;
 
 unlock:
-	spin_unlock(&orig_hash_lock);
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
 dropped:
 	priv->stats.tx_dropped++;
 end:
-	kfree_skb(skb);
-	return 0;
+	return NETDEV_TX_OK;
 }
 
-void interface_rx(struct net_device *dev, void *packet, int packet_len)
+void interface_rx(struct sk_buff *skb, int hdr_size)
 {
-	struct sk_buff *skb;
+	struct net_device *dev = soft_device;
 	struct bat_priv *priv = netdev_priv(dev);
 
-	skb = dev_alloc_skb(packet_len);
-
-	if (!skb) {
-		priv->stats.rx_dropped++;
-		goto out;
+	/* check if enough space is available for pulling, and pull */
+	if (!pskb_may_pull(skb, hdr_size)) {
+		kfree_skb(skb);
+		return;
 	}
+	skb_pull_rcsum(skb, hdr_size);
+/*	skb_set_mac_header(skb, -sizeof(struct ethhdr));*/
 
-	memcpy(skb_put(skb, packet_len), packet, packet_len);
-
-	/* Write metadata, and then pass to the receive level */
 	skb->dev = dev;
 	skb->protocol = eth_type_trans(skb, dev);
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	/* should not be neccesary anymore as we use skb_pull_rcsum()
+	 * TODO: please verify this and remove this TODO
+	 * -- Dec 21st 2009, Simon Wunderlich */
+
+/*	skb->ip_summed = CHECKSUM_UNNECESSARY;*/
+
+	/* TODO: set skb->pkt_type to PACKET_BROADCAST, PACKET_MULTICAST,
+	 * PACKET_OTHERHOST or PACKET_HOST */
 
 	priv->stats.rx_packets++;
-	priv->stats.rx_bytes += packet_len;
+	priv->stats.rx_bytes += skb->len;
 
 	dev->last_rx = jiffies;
 
 	netif_rx(skb);
-
-out:
-	return;
 }
 
 /* ethtool */
@@ -330,7 +337,6 @@
 
 static void bat_set_msglevel(struct net_device *dev, u32 value)
 {
-	return;
 }
 
 static u32 bat_get_link(struct net_device *dev)
diff --git a/drivers/staging/batman-adv/soft-interface.h b/drivers/staging/batman-adv/soft-interface.h
index 515e276..c0cad81 100644
--- a/drivers/staging/batman-adv/soft-interface.h
+++ b/drivers/staging/batman-adv/soft-interface.h
@@ -28,6 +28,7 @@
 int interface_set_mac_addr(struct net_device *dev, void *addr);
 int interface_change_mtu(struct net_device *dev, int new_mtu);
 int interface_tx(struct sk_buff *skb, struct net_device *dev);
-void interface_rx(struct net_device *dev, void *packet, int packet_len);
+void interface_rx(struct sk_buff *skb, int hdr_size);
+int my_skb_push(struct sk_buff *skb, unsigned int len);
 
 extern unsigned char mainIfAddr[];
diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c
index c2190e1..d56f665 100644
--- a/drivers/staging/batman-adv/translation-table.c
+++ b/drivers/staging/batman-adv/translation-table.c
@@ -21,11 +21,9 @@
 
 #include "main.h"
 #include "translation-table.h"
-#include "log.h"
 #include "soft-interface.h"
 #include "types.h"
 #include "hash.h"
-#include "compat.h"
 
 struct hashtable_t *hna_local_hash;
 static struct hashtable_t *hna_global_hash;
@@ -62,7 +60,6 @@
 	struct hna_local_entry *hna_local_entry;
 	struct hna_global_entry *hna_global_entry;
 	struct hashtable_t *swaphash;
-	char hna_str[ETH_STR_LEN];
 	unsigned long flags;
 
 	spin_lock_irqsave(&hna_local_hash_lock, flags);
@@ -75,19 +72,17 @@
 		return;
 	}
 
-	addr_to_string(hna_str, addr);
-
 	/* only announce as many hosts as possible in the batman-packet and
 	   space in batman_packet->num_hna That also should give a limit to
 	   MAC-flooding. */
 	if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) ||
 	    (num_hna + 1 > 255)) {
-		debug_log(LOG_TYPE_ROUTES, "Can't add new local hna entry (%s): number of local hna entries exceeds packet size \n", hna_str);
+		bat_dbg(DBG_ROUTES, "Can't add new local hna entry (%pM): number of local hna entries exceeds packet size \n", addr);
 		return;
 	}
 
-	debug_log(LOG_TYPE_ROUTES, "Creating new local hna entry: %s \n",
-		  hna_str);
+	bat_dbg(DBG_ROUTES, "Creating new local hna entry: %pM \n",
+		addr);
 
 	hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC);
 	if (!hna_local_entry)
@@ -113,7 +108,7 @@
 				       hna_local_hash->size * 2);
 
 		if (swaphash == NULL)
-			debug_log(LOG_TYPE_CRIT, "Couldn't resize local hna hash table \n");
+			printk(KERN_ERR "batman-adv:Couldn't resize local hna hash table \n");
 		else
 			hna_local_hash = swaphash;
 	}
@@ -135,18 +130,18 @@
 int hna_local_fill_buffer(unsigned char *buff, int buff_len)
 {
 	struct hna_local_entry *hna_local_entry;
-	struct hash_it_t *hashit = NULL;
+	HASHIT(hashit);
 	int i = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hna_local_hash_lock, flags);
 
-	while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
+	while (hash_iterate(hna_local_hash, &hashit)) {
 
 		if (buff_len < (i + 1) * ETH_ALEN)
 			break;
 
-		hna_local_entry = hashit->bucket->data;
+		hna_local_entry = hashit.bucket->data;
 		memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN);
 
 		i++;
@@ -164,18 +159,18 @@
 int hna_local_fill_buffer_text(unsigned char *buff, int buff_len)
 {
 	struct hna_local_entry *hna_local_entry;
-	struct hash_it_t *hashit = NULL;
+	HASHIT(hashit);
 	int bytes_written = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hna_local_hash_lock, flags);
 
-	while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
+	while (hash_iterate(hna_local_hash, &hashit)) {
 
 		if (buff_len < bytes_written + ETH_STR_LEN + 4)
 			break;
 
-		hna_local_entry = hashit->bucket->data;
+		hna_local_entry = hashit.bucket->data;
 
 		bytes_written += snprintf(buff + bytes_written, ETH_STR_LEN + 4,
 					  " * %02x:%02x:%02x:%02x:%02x:%02x\n",
@@ -202,27 +197,39 @@
 static void hna_local_del(struct hna_local_entry *hna_local_entry,
 			  char *message)
 {
-	char hna_str[ETH_STR_LEN];
-
-	addr_to_string(hna_str, hna_local_entry->addr);
-	debug_log(LOG_TYPE_ROUTES, "Deleting local hna entry (%s): %s \n",
-		  hna_str, message);
+	bat_dbg(DBG_ROUTES, "Deleting local hna entry (%pM): %s \n",
+		hna_local_entry->addr, message);
 
 	hash_remove(hna_local_hash, hna_local_entry->addr);
 	_hna_local_del(hna_local_entry);
 }
 
+void hna_local_remove(uint8_t *addr, char *message)
+{
+	struct hna_local_entry *hna_local_entry;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hna_local_hash_lock, flags);
+
+	hna_local_entry = (struct hna_local_entry *)
+		hash_find(hna_local_hash, addr);
+	if (hna_local_entry)
+		hna_local_del(hna_local_entry, message);
+
+	spin_unlock_irqrestore(&hna_local_hash_lock, flags);
+}
+
 void hna_local_purge(struct work_struct *work)
 {
 	struct hna_local_entry *hna_local_entry;
-	struct hash_it_t *hashit = NULL;
+	HASHIT(hashit);
 	unsigned long flags;
 	unsigned long timeout;
 
 	spin_lock_irqsave(&hna_local_hash_lock, flags);
 
-	while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
-		hna_local_entry = hashit->bucket->data;
+	while (hash_iterate(hna_local_hash, &hashit)) {
+		hna_local_entry = hashit.bucket->data;
 
 		timeout = hna_local_entry->last_seen +
 			((LOCAL_HNA_TIMEOUT / 1000) * HZ);
@@ -264,13 +271,10 @@
 	struct hna_global_entry *hna_global_entry;
 	struct hna_local_entry *hna_local_entry;
 	struct hashtable_t *swaphash;
-	char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN];
 	int hna_buff_count = 0;
 	unsigned long flags;
 	unsigned char *hna_ptr;
 
-	addr_to_string(orig_str, orig_node->orig);
-
 	while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) {
 		spin_lock_irqsave(&hna_global_hash_lock, flags);
 
@@ -290,8 +294,9 @@
 
 			memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN);
 
-			addr_to_string(hna_str, hna_global_entry->addr);
-			debug_log(LOG_TYPE_ROUTES, "Creating new global hna entry: %s (via %s)\n", hna_str, orig_str);
+			bat_dbg(DBG_ROUTES,
+				"Creating new global hna entry: %pM (via %pM)\n",
+				hna_global_entry->addr, orig_node->orig);
 
 			spin_lock_irqsave(&hna_global_hash_lock, flags);
 			hash_add(hna_global_hash, hna_global_entry);
@@ -316,14 +321,16 @@
 		hna_buff_count++;
 	}
 
-	orig_node->hna_buff_len = hna_buff_len;
+	/* initialize, and overwrite if malloc succeeds */
+	orig_node->hna_buff = NULL;
+	orig_node->hna_buff_len = 0;
 
-	if (orig_node->hna_buff_len > 0) {
-		orig_node->hna_buff = kmalloc(orig_node->hna_buff_len,
-					      GFP_ATOMIC);
-		memcpy(orig_node->hna_buff, hna_buff, orig_node->hna_buff_len);
-	} else {
-		orig_node->hna_buff = NULL;
+	if (hna_buff_len > 0) {
+		orig_node->hna_buff = kmalloc(hna_buff_len, GFP_ATOMIC);
+		if (orig_node->hna_buff) {
+			memcpy(orig_node->hna_buff, hna_buff, hna_buff_len);
+			orig_node->hna_buff_len = hna_buff_len;
+		}
 	}
 
 	spin_lock_irqsave(&hna_global_hash_lock, flags);
@@ -333,7 +340,7 @@
 				       hna_global_hash->size * 2);
 
 		if (swaphash == NULL)
-			debug_log(LOG_TYPE_CRIT, "Couldn't resize global hna hash table \n");
+			printk(KERN_ERR "batman-adv:Couldn't resize global hna hash table \n");
 		else
 			hna_global_hash = swaphash;
 	}
@@ -344,17 +351,17 @@
 int hna_global_fill_buffer_text(unsigned char *buff, int buff_len)
 {
 	struct hna_global_entry *hna_global_entry;
-	struct hash_it_t *hashit = NULL;
+	HASHIT(hashit);
 	int bytes_written = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hna_global_hash_lock, flags);
 
-	while (NULL != (hashit = hash_iterate(hna_global_hash, hashit))) {
+	while (hash_iterate(hna_global_hash, &hashit)) {
 		if (buff_len < bytes_written + (2 * ETH_STR_LEN) + 10)
 			break;
 
-		hna_global_entry = hashit->bucket->data;
+		hna_global_entry = hashit.bucket->data;
 
 		bytes_written += snprintf(buff + bytes_written,
 					  (2 * ETH_STR_LEN) + 10,
@@ -381,12 +388,9 @@
 void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
 			  char *message)
 {
-	char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN];
-
-	addr_to_string(orig_str, hna_global_entry->orig_node->orig);
-	addr_to_string(hna_str, hna_global_entry->addr);
-
-	debug_log(LOG_TYPE_ROUTES, "Deleting global hna entry %s (via %s): %s \n", hna_str, orig_str, message);
+	bat_dbg(DBG_ROUTES, "Deleting global hna entry %pM (via %pM): %s \n",
+		hna_global_entry->addr, hna_global_entry->orig_node->orig,
+		message);
 
 	hash_remove(hna_global_hash, hna_global_entry->addr);
 	kfree(hna_global_entry);
diff --git a/drivers/staging/batman-adv/translation-table.h b/drivers/staging/batman-adv/translation-table.h
index f7da811..281125b 100644
--- a/drivers/staging/batman-adv/translation-table.h
+++ b/drivers/staging/batman-adv/translation-table.h
@@ -23,6 +23,7 @@
 
 int hna_local_init(void);
 void hna_local_add(uint8_t *addr);
+void hna_local_remove(uint8_t *addr, char *message);
 int hna_local_fill_buffer(unsigned char *buff, int buff_len);
 int hna_local_fill_buffer_text(unsigned char *buff, int buff_len);
 void hna_local_purge(struct work_struct *work);
diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h
index 3a0ef0c..dec1b54 100644
--- a/drivers/staging/batman-adv/types.h
+++ b/drivers/staging/batman-adv/types.h
@@ -39,7 +39,6 @@
 	char if_active;
 	char addr_str[ETH_STR_LEN];
 	struct net_device *net_dev;
-	struct socket *raw_sock;
 	atomic_t seqno;
 	unsigned char *packet_buff;
 	int packet_len;
@@ -75,7 +74,7 @@
 	uint8_t tq_index;
 	uint8_t tq_avg;
 	uint8_t last_ttl;
-	unsigned long last_valid;            /* when last packet via this neighbour was received */
+	unsigned long last_valid;            /* when last packet via this neighbor was received */
 	TYPE_OF_WORD real_bits[NUM_WORDS];
 	struct orig_node *orig_node;
 	struct batman_if *if_incoming;
@@ -113,6 +112,7 @@
 	struct hlist_node list;
 	unsigned long send_time;
 	uint8_t own;
+	struct sk_buff *skb;
 	unsigned char *packet_buff;
 	uint16_t packet_len;
 	uint32_t direct_link_flags;
@@ -121,4 +121,14 @@
 	struct batman_if *if_incoming;
 };
 
+/* While scanning for vis-entries of a particular vis-originator
+ * this list collects its interfaces to create a subgraph/cluster
+ * out of them later
+ */
+struct if_list_entry {
+	uint8_t addr[ETH_ALEN];
+	bool primary;
+	struct hlist_node list;
+};
+
 #endif
diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c
index f6c9acb..fedec1b 100644
--- a/drivers/staging/batman-adv/vis.c
+++ b/drivers/staging/batman-adv/vis.c
@@ -23,11 +23,9 @@
 #include "send.h"
 #include "translation-table.h"
 #include "vis.h"
-#include "log.h"
 #include "soft-interface.h"
 #include "hard-interface.h"
 #include "hash.h"
-#include "compat.h"
 
 struct hashtable_t *vis_hash;
 DEFINE_SPINLOCK(vis_hash_lock);
@@ -50,39 +48,6 @@
 	kfree(info);
 }
 
-/* set the mode of the visualization to client or server */
-void vis_set_mode(int mode)
-{
-	spin_lock(&vis_hash_lock);
-
-	if (my_vis_info != NULL)
-		my_vis_info->packet.vis_type = mode;
-
-	spin_unlock(&vis_hash_lock);
-}
-
-/* is_vis_server(), locked outside */
-static int is_vis_server_locked(void)
-{
-	if (my_vis_info != NULL)
-		if (my_vis_info->packet.vis_type == VIS_TYPE_SERVER_SYNC)
-			return 1;
-
-	return 0;
-}
-
-/* get the current set mode */
-int is_vis_server(void)
-{
-	int ret = 0;
-
-	spin_lock(&vis_hash_lock);
-	ret = is_vis_server_locked();
-	spin_unlock(&vis_hash_lock);
-
-	return ret;
-}
-
 /* Compare two vis packets, used by the hashing algorithm */
 static int vis_info_cmp(void *data1, void *data2)
 {
@@ -115,6 +80,68 @@
 	return hash % size;
 }
 
+/* insert interface to the list of interfaces of one originator, if it
+ * does not already exist in the list */
+static void proc_vis_insert_interface(const uint8_t *interface,
+				      struct hlist_head *if_list,
+				      bool primary)
+{
+	struct if_list_entry *entry;
+	struct hlist_node *pos;
+
+	hlist_for_each_entry(entry, pos, if_list, list) {
+		if (compare_orig(entry->addr, (void *)interface))
+			return;
+	}
+
+	/* its a new address, add it to the list */
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return;
+	memcpy(entry->addr, interface, ETH_ALEN);
+	entry->primary = primary;
+	hlist_add_head(&entry->list, if_list);
+}
+
+void proc_vis_read_prim_sec(struct seq_file *seq,
+			    struct hlist_head *if_list)
+{
+	struct if_list_entry *entry;
+	struct hlist_node *pos, *n;
+	char tmp_addr_str[ETH_STR_LEN];
+
+	hlist_for_each_entry_safe(entry, pos, n, if_list, list) {
+		if (entry->primary) {
+			seq_printf(seq, "PRIMARY, ");
+		} else {
+			addr_to_string(tmp_addr_str, entry->addr);
+			seq_printf(seq, "SEC %s, ", tmp_addr_str);
+		}
+
+		hlist_del(&entry->list);
+		kfree(entry);
+	}
+}
+
+/* read an entry  */
+void proc_vis_read_entry(struct seq_file *seq,
+				struct vis_info_entry *entry,
+				struct hlist_head *if_list,
+				uint8_t *vis_orig)
+{
+	char to[40];
+
+	addr_to_string(to, entry->dest);
+	if (entry->quality == 0) {
+		proc_vis_insert_interface(vis_orig, if_list, true);
+		seq_printf(seq, "HNA %s, ", to);
+	} else {
+		proc_vis_insert_interface(entry->src, if_list,
+					  compare_orig(entry->src, vis_orig));
+		seq_printf(seq, "TQ %s %d, ", to, entry->quality);
+	}
+}
+
 /* tries to add one entry to the receive list. */
 static void recv_list_add(struct list_head *recv_list, char *mac)
 {
@@ -208,21 +235,23 @@
 {
 	struct vis_info *info;
 	int is_new;
+	unsigned long flags;
+	int vis_server = atomic_read(&vis_mode);
 
-	spin_lock(&vis_hash_lock);
+	spin_lock_irqsave(&vis_hash_lock, flags);
 	info = add_packet(vis_packet, vis_info_len, &is_new);
 	if (info == NULL)
 		goto end;
 
 	/* only if we are server ourselves and packet is newer than the one in
 	 * hash.*/
-	if (is_vis_server_locked() && is_new) {
+	if (vis_server == VIS_TYPE_SERVER_SYNC && is_new) {
 		memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
 		if (list_empty(&info->send_list))
 			list_add_tail(&info->send_list, &send_list);
 	}
 end:
-	spin_unlock(&vis_hash_lock);
+	spin_unlock_irqrestore(&vis_hash_lock, flags);
 }
 
 /* handle an incoming client update packet and schedule forward if needed. */
@@ -231,12 +260,14 @@
 {
 	struct vis_info *info;
 	int is_new;
+	unsigned long flags;
+	int vis_server = atomic_read(&vis_mode);
 
 	/* clients shall not broadcast. */
 	if (is_bcast(vis_packet->target_orig))
 		return;
 
-	spin_lock(&vis_hash_lock);
+	spin_lock_irqsave(&vis_hash_lock, flags);
 	info = add_packet(vis_packet, vis_info_len, &is_new);
 	if (info == NULL)
 		goto end;
@@ -244,7 +275,7 @@
 
 
 	/* send only if we're the target server or ... */
-	if (is_vis_server_locked() &&
+	if (vis_server == VIS_TYPE_SERVER_SYNC  &&
 	    is_my_mac(info->packet.target_orig) &&
 	    is_new) {
 		info->packet.vis_type = VIS_TYPE_SERVER_SYNC;	/* upgrade! */
@@ -258,7 +289,7 @@
 			list_add_tail(&info->send_list, &send_list);
 	}
 end:
-	spin_unlock(&vis_hash_lock);
+	spin_unlock_irqrestore(&vis_hash_lock, flags);
 }
 
 /* Walk the originators and find the VIS server with the best tq. Set the packet
@@ -267,12 +298,12 @@
  * Must be called with the originator hash locked */
 static int find_best_vis_server(struct vis_info *info)
 {
-	struct hash_it_t *hashit = NULL;
+	HASHIT(hashit);
 	struct orig_node *orig_node;
 	int best_tq = -1;
 
-	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
-		orig_node = hashit->bucket->data;
+	while (hash_iterate(orig_hash, &hashit)) {
+		orig_node = hashit.bucket->data;
 		if ((orig_node != NULL) &&
 		    (orig_node->router != NULL) &&
 		    (orig_node->flags & VIS_SERVER) &&
@@ -298,7 +329,8 @@
  * returns 0 on success, -1 if no packet could be generated */
 static int generate_vis_packet(void)
 {
-	struct hash_it_t *hashit = NULL;
+	HASHIT(hashit_local);
+	HASHIT(hashit_global);
 	struct orig_node *orig_node;
 	struct vis_info *info = (struct vis_info *)my_vis_info;
 	struct vis_info_entry *entry, *entry_array;
@@ -307,27 +339,27 @@
 	unsigned long flags;
 
 	info->first_seen = jiffies;
+	info->packet.vis_type = atomic_read(&vis_mode);
 
-	spin_lock(&orig_hash_lock);
+	spin_lock_irqsave(&orig_hash_lock, flags);
 	memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
 	info->packet.ttl = TTL;
 	info->packet.seqno++;
 	info->packet.entries = 0;
 
-	if (!is_vis_server_locked()) {
+	if (info->packet.vis_type == VIS_TYPE_CLIENT_UPDATE) {
 		best_tq = find_best_vis_server(info);
 		if (best_tq < 0) {
-			spin_unlock(&orig_hash_lock);
+			spin_unlock_irqrestore(&orig_hash_lock, flags);
 			return -1;
 		}
 	}
-	hashit = NULL;
 
 	entry_array = (struct vis_info_entry *)
 		((char *)info + sizeof(struct vis_info));
 
-	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
-		orig_node = hashit->bucket->data;
+	while (hash_iterate(orig_hash, &hashit_global)) {
+		orig_node = hashit_global.bucket->data;
 		if (orig_node->router != NULL
 			&& compare_orig(orig_node->router->addr, orig_node->orig)
 			&& orig_node->batman_if
@@ -342,18 +374,17 @@
 			info->packet.entries++;
 
 			if (vis_packet_full(info)) {
-				spin_unlock(&orig_hash_lock);
+				spin_unlock_irqrestore(&orig_hash_lock, flags);
 				return 0;
 			}
 		}
 	}
 
-	spin_unlock(&orig_hash_lock);
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
 
-	hashit = NULL;
 	spin_lock_irqsave(&hna_local_hash_lock, flags);
-	while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
-		hna_local_entry = hashit->bucket->data;
+	while (hash_iterate(hna_local_hash, &hashit_local)) {
+		hna_local_entry = hashit_local.bucket->data;
 		entry = &entry_array[info->packet.entries];
 		memset(entry->src, 0, ETH_ALEN);
 		memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN);
@@ -371,16 +402,16 @@
 
 static void purge_vis_packets(void)
 {
-	struct hash_it_t *hashit = NULL;
+	HASHIT(hashit);
 	struct vis_info *info;
 
-	while (NULL != (hashit = hash_iterate(vis_hash, hashit))) {
-		info = hashit->bucket->data;
+	while (hash_iterate(vis_hash, &hashit)) {
+		info = hashit.bucket->data;
 		if (info == my_vis_info)	/* never purge own data. */
 			continue;
 		if (time_after(jiffies,
-			       info->first_seen + (VIS_TIMEOUT/1000)*HZ)) {
-			hash_remove_bucket(vis_hash, hashit);
+			       info->first_seen + (VIS_TIMEOUT*HZ)/1000)) {
+			hash_remove_bucket(vis_hash, &hashit);
 			free_info(info);
 		}
 	}
@@ -388,14 +419,15 @@
 
 static void broadcast_vis_packet(struct vis_info *info, int packet_length)
 {
-	struct hash_it_t *hashit = NULL;
+	HASHIT(hashit);
 	struct orig_node *orig_node;
+	unsigned long flags;
 
-	spin_lock(&orig_hash_lock);
+	spin_lock_irqsave(&orig_hash_lock, flags);
 
 	/* send to all routers in range. */
-	while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
-		orig_node = hashit->bucket->data;
+	while (hash_iterate(orig_hash, &hashit)) {
+		orig_node = hashit.bucket->data;
 
 		/* if it's a vis server and reachable, send it. */
 		if (orig_node &&
@@ -418,14 +450,15 @@
 		}
 	}
 	memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
-	spin_unlock(&orig_hash_lock);
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
 }
 
 static void unicast_vis_packet(struct vis_info *info, int packet_length)
 {
 	struct orig_node *orig_node;
+	unsigned long flags;
 
-	spin_lock(&orig_hash_lock);
+	spin_lock_irqsave(&orig_hash_lock, flags);
 	orig_node = ((struct orig_node *)
 		     hash_find(orig_hash, info->packet.target_orig));
 
@@ -436,7 +469,7 @@
 				orig_node->batman_if,
 				orig_node->router->addr);
 	}
-	spin_unlock(&orig_hash_lock);
+	spin_unlock_irqrestore(&orig_hash_lock, flags);
 }
 
 /* only send one vis packet. called from send_vis_packets() */
@@ -445,8 +478,7 @@
 	int packet_length;
 
 	if (info->packet.ttl < 2) {
-		debug_log(LOG_TYPE_NOTICE,
-			  "Error - can't send vis packet: ttl exceeded\n");
+		printk(KERN_WARNING "batman-adv: Error - can't send vis packet: ttl exceeded\n");
 		return;
 	}
 
@@ -467,8 +499,9 @@
 static void send_vis_packets(struct work_struct *work)
 {
 	struct vis_info *info, *temp;
+	unsigned long flags;
 
-	spin_lock(&vis_hash_lock);
+	spin_lock_irqsave(&vis_hash_lock, flags);
 	purge_vis_packets();
 
 	if (generate_vis_packet() == 0)
@@ -479,7 +512,7 @@
 		list_del_init(&info->send_list);
 		send_vis_packet(info);
 	}
-	spin_unlock(&vis_hash_lock);
+	spin_unlock_irqrestore(&vis_hash_lock, flags);
 	start_vis_timer();
 }
 static DECLARE_DELAYED_WORK(vis_timer_wq, send_vis_packets);
@@ -488,20 +521,21 @@
  * initialized (e.g. bat0 is initialized, interfaces have been added) */
 int vis_init(void)
 {
+	unsigned long flags;
 	if (vis_hash)
 		return 1;
 
-	spin_lock(&vis_hash_lock);
+	spin_lock_irqsave(&vis_hash_lock, flags);
 
 	vis_hash = hash_new(256, vis_info_cmp, vis_info_choose);
 	if (!vis_hash) {
-		debug_log(LOG_TYPE_CRIT, "Can't initialize vis_hash\n");
+		printk(KERN_ERR "batman-adv:Can't initialize vis_hash\n");
 		goto err;
 	}
 
 	my_vis_info = kmalloc(1000, GFP_ATOMIC);
 	if (!my_vis_info) {
-		debug_log(LOG_TYPE_CRIT, "Can't initialize vis packet\n");
+		printk(KERN_ERR "batman-adv:Can't initialize vis packet\n");
 		goto err;
 	}
 
@@ -511,7 +545,6 @@
 	INIT_LIST_HEAD(&my_vis_info->send_list);
 	my_vis_info->packet.version = COMPAT_VERSION;
 	my_vis_info->packet.packet_type = BAT_VIS;
-	my_vis_info->packet.vis_type = VIS_TYPE_CLIENT_UPDATE;
 	my_vis_info->packet.ttl = TTL;
 	my_vis_info->packet.seqno = 0;
 	my_vis_info->packet.entries = 0;
@@ -522,19 +555,19 @@
 	memcpy(my_vis_info->packet.sender_orig, mainIfAddr, ETH_ALEN);
 
 	if (hash_add(vis_hash, my_vis_info) < 0) {
-		debug_log(LOG_TYPE_CRIT,
-			  "Can't add own vis packet into hash\n");
+		printk(KERN_ERR
+			  "batman-adv:Can't add own vis packet into hash\n");
 		free_info(my_vis_info);	/* not in hash, need to remove it
 					 * manually. */
 		goto err;
 	}
 
-	spin_unlock(&vis_hash_lock);
+	spin_unlock_irqrestore(&vis_hash_lock, flags);
 	start_vis_timer();
 	return 1;
 
 err:
-	spin_unlock(&vis_hash_lock);
+	spin_unlock_irqrestore(&vis_hash_lock, flags);
 	vis_quit();
 	return 0;
 }
@@ -542,23 +575,23 @@
 /* shutdown vis-server */
 void vis_quit(void)
 {
+	unsigned long flags;
 	if (!vis_hash)
 		return;
 
 	cancel_delayed_work_sync(&vis_timer_wq);
 
-	spin_lock(&vis_hash_lock);
+	spin_lock_irqsave(&vis_hash_lock, flags);
 	/* properly remove, kill timers ... */
 	hash_delete(vis_hash, free_info);
 	vis_hash = NULL;
 	my_vis_info = NULL;
-	spin_unlock(&vis_hash_lock);
+	spin_unlock_irqrestore(&vis_hash_lock, flags);
 }
 
 /* schedule packets for (re)transmission */
 static void start_vis_timer(void)
 {
 	queue_delayed_work(bat_event_workqueue, &vis_timer_wq,
-			   (atomic_read(&vis_interval)/1000) * HZ);
+			   (atomic_read(&vis_interval) * HZ) / 1000);
 }
-
diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h
index 276faba..0cdafde 100644
--- a/drivers/staging/batman-adv/vis.h
+++ b/drivers/staging/batman-adv/vis.h
@@ -45,16 +45,15 @@
 	uint8_t mac[ETH_ALEN];
 };
 
-enum vis_formats {
-	DOT_DRAW,
-	JSON,
-};
-
 extern struct hashtable_t *vis_hash;
 extern spinlock_t vis_hash_lock;
 
-void vis_set_mode(int mode);
-int is_vis_server(void);
+void proc_vis_read_entry(struct seq_file *seq,
+				struct vis_info_entry *entry,
+				struct hlist_head *if_list,
+				uint8_t *vis_orig);
+void proc_vis_read_prim_sec(struct seq_file *seq,
+			    struct hlist_head *if_list);
 void receive_server_sync_packet(struct vis_packet *vis_packet,
 				int vis_info_len);
 void receive_client_update_packet(struct vis_packet *vis_packet,
diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
index a9fdcda..581aa5f 100644
--- a/drivers/staging/comedi/comedi_compat32.c
+++ b/drivers/staging/comedi/comedi_compat32.c
@@ -26,7 +26,6 @@
 
 #define __NO_VERSION__
 #include "comedi.h"
-#include <linux/smp_lock.h>
 #include <linux/uaccess.h>
 
 #include "comedi_compat32.h"
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 8117748..aca9674 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -63,7 +63,7 @@
 int comedi_autoconfig = 1;
 module_param(comedi_autoconfig, bool, 0444);
 
-int comedi_num_legacy_minors = 0;
+int comedi_num_legacy_minors;
 module_param(comedi_num_legacy_minors, int, 0444);
 
 static DEFINE_SPINLOCK(comedi_file_info_table_lock);
@@ -1510,7 +1510,7 @@
 }
 
 static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
-			    loff_t * offset)
+				loff_t *offset)
 {
 	struct comedi_subdevice *s;
 	struct comedi_async *async;
@@ -1612,7 +1612,7 @@
 }
 
 static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
-			   loff_t * offset)
+				loff_t *offset)
 {
 	struct comedi_subdevice *s;
 	struct comedi_async *async;
@@ -2004,12 +2004,10 @@
 	if (async->cb_mask & s->async->events) {
 		if (comedi_get_subdevice_runflags(s) & SRF_USER) {
 			wake_up_interruptible(&async->wait_head);
-			if (s->subdev_flags & SDF_CMD_READ) {
+			if (s->subdev_flags & SDF_CMD_READ)
 				kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
-			}
-			if (s->subdev_flags & SDF_CMD_WRITE) {
+			if (s->subdev_flags & SDF_CMD_WRITE)
 				kill_fasync(&dev->async_queue, SIGIO, POLL_OUT);
-			}
 		} else {
 			if (async->cb_func)
 				async->cb_func(s->async->events, async->cb_arg);
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index c2a632d..44d6b62 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -44,7 +44,7 @@
 #include <linux/cdev.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/system.h>
 
 static int postconfig(struct comedi_device *dev);
@@ -99,11 +99,10 @@
 static void __comedi_device_detach(struct comedi_device *dev)
 {
 	dev->attached = 0;
-	if (dev->driver) {
+	if (dev->driver)
 		dev->driver->detach(dev);
-	} else {
+	else
 		printk("BUG: dev->driver=NULL in comedi_device_detach()\n");
-	}
 	cleanup_device(dev);
 }
 
@@ -380,9 +379,8 @@
 	if (ret < 0)
 		return ret;
 
-	if (insn->insn == INSN_READ) {
+	if (insn->insn == INSN_READ)
 		data[0] = (new_data[1] >> (chan - base_bitfield_channel)) & 1;
-	}
 
 	return 1;
 }
@@ -429,9 +427,9 @@
 	new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
 
 	/* if no change is required, do nothing */
-	if (async->prealloc_buf && async->prealloc_bufsz == new_size) {
+	if (async->prealloc_buf && async->prealloc_bufsz == new_size)
 		return 0;
-	}
+
 	/*  deallocate old buffer */
 	if (async->prealloc_buf) {
 		vunmap(async->prealloc_buf);
@@ -494,9 +492,9 @@
 					    (void *)
 					    get_zeroed_page(GFP_KERNEL);
 				}
-				if (async->buf_page_list[i].virt_addr == NULL) {
+				if (async->buf_page_list[i].virt_addr == NULL)
 					break;
-				}
+
 				mem_map_reserve(virt_to_page
 						(async->buf_page_list[i].
 						 virt_addr));
@@ -619,9 +617,9 @@
 {
 	unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
 
-	if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0) {
+	if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0)
 		nbytes = free_end - async->buf_write_alloc_count;
-	}
+
 	async->buf_write_alloc_count += nbytes;
 	/* barrier insures the read of buf_read_count above occurs before
 	   we write data to the write-alloc'ed buffer space */
@@ -635,9 +633,9 @@
 {
 	unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
 
-	if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0) {
+	if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0)
 		nbytes = 0;
-	}
+
 	async->buf_write_alloc_count += nbytes;
 	/* barrier insures the read of buf_read_count above occurs before
 	   we write data to the write-alloc'ed buffer space */
@@ -657,9 +655,9 @@
 	async->buf_write_count += nbytes;
 	async->buf_write_ptr += nbytes;
 	comedi_buf_munge(async, async->buf_write_count - async->munge_count);
-	if (async->buf_write_ptr >= async->prealloc_bufsz) {
+	if (async->buf_write_ptr >= async->prealloc_bufsz)
 		async->buf_write_ptr %= async->prealloc_bufsz;
-	}
+
 	return nbytes;
 }
 
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
index 0af12fd..fbc26a0 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
index f3e47e5..a6898e4 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
index a15c952..0e498e9 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
index 0fc2285..204d798 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
index 138a84f..148ce6f 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
index a445dab..6360de5 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
index 7e12544..344df94 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
index d3d78d3..de6f772 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
index 6e9e7ed..97c10aa 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
@@ -173,11 +173,10 @@
 			} while (dw_eeprom_busy == EEPROM_BUSY);
 
 			/* Select the upper address part */
-			if (i_Counter == 0) {
+			if (i_Counter == 0)
 				b_ReadLowByte = pb_ReadByte[0];
-			} else {
+			else
 				b_ReadHighByte = pb_ReadByte[0];
-			}
 
 			/* Sleep */
 			msleep(1);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index a56535f..8db5ab6 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
index 3ab27cf..caeb6fd 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
@@ -77,8 +77,8 @@
 	int i_NbrAoChannel;	/*  num of D/A chans */
 	int i_AiMaxdata;	/*  resolution of A/D */
 	int i_AoMaxdata;	/*  resolution of D/A */
-        const struct comedi_lrange *pr_AiRangelist;	/* rangelist for A/D */
-        const struct comedi_lrange *pr_AoRangelist;	/* rangelist for D/A */
+	const struct comedi_lrange *pr_AiRangelist;	/* rangelist for A/D */
+	const struct comedi_lrange *pr_AoRangelist;	/* rangelist for D/A */
 
 	int i_NbrDiChannel;	/*  Number of DI channels */
 	int i_NbrDoChannel;	/*  Number of DO channels */
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
index 69b4273..bea329f 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
index 47517a9..d7d768e 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
index 016721e..7912972 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
index 723a97b..fe06789 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
@@ -54,7 +54,7 @@
 #include "hwdrv_apci1032.h"
 #include <linux/delay.h>
 /* Global variables */
-unsigned int ui_InterruptStatus = 0;
+unsigned int ui_InterruptStatus;
 
 /*
 +----------------------------------------------------------------------------+
@@ -108,9 +108,9 @@
 			ui_TmpValue =
 				inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
 		}		/* if (data[1] == ADDIDATA_OR) */
-		else {
+		else
 			outl(0x6, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
-		}		/* else if(data[1] == ADDIDATA_OR) */
+				/* else if(data[1] == ADDIDATA_OR) */
 	}			/*  if( data[0] == ADDIDATA_ENABLE) */
 	else {
 		ul_Command1 = ul_Command1 & 0xFFFF0000;
@@ -221,9 +221,9 @@
 		}		/* switch(ui_NoOfChannels) */
 	}			/* if(data[1]==0) */
 	else {
-		if (data[1] == 1) {
+		if (data[1] == 1)
 			*data = ui_InterruptStatus;
-		}		/* if(data[1]==1) */
+				/* if(data[1]==1) */
 	}			/* else if(data[1]==0) */
 	return insn->n;
 }
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
index 36b929f..d5e06ad 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
index 866eb8d..7948c41 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index 3ae663b..4413279 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
index 988e3fc..8bc88ad 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
index d348cd5..89783b1eb 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
index ec81708..2d32516 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
index aa159dc..e01889c3 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
index 172fba8..f93ddd4 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
@@ -45,7 +45,7 @@
 */
 
 #include "hwdrv_apci3120.h"
-static unsigned int ui_Temp = 0;
+static unsigned int ui_Temp;
 
 /* FUNCTION DEFINITIONS */
 
@@ -98,25 +98,22 @@
 
 		devpriv->b_InterruptMode = APCI3120_EOS_MODE;
 
-		if (data[1]) {
+		if (data[1])
 			devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
-		} else
+		else
 			devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
 		/*  Copy channel list and Range List to devpriv */
 
 		devpriv->ui_AiNbrofChannels = data[3];
-		for (i = 0; i < devpriv->ui_AiNbrofChannels; i++) {
+		for (i = 0; i < devpriv->ui_AiNbrofChannels; i++)
 			devpriv->ui_AiChannelList[i] = data[4 + i];
-		}
 
-	} else			/*  EOC */
-	{
+	} else {			/*  EOC */
 		devpriv->b_InterruptMode = APCI3120_EOC_MODE;
-		if (data[1]) {
+		if (data[1])
 			devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
-		} else {
+		else
 			devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
-		}
 	}
 
 	return insn->n;
@@ -166,13 +163,9 @@
 	devpriv->us_OutputRegister = 0;
 /* devpriv->b_DigitalOutputRegister=0; */
 
-	if (insn->unused[0] == 222)	/*  second insn read */
-	{
-
-		for (i = 0; i < insn->n; i++) {
+	if (insn->unused[0] == 222) {	/*  second insn read */
+		for (i = 0; i < insn->n; i++)
 			data[i] = devpriv->ui_AiReadData[i];
-		}
-
 	} else {
 		devpriv->tsk_Current = current;	/*  Save the current process task structure */
 /*
@@ -519,9 +512,8 @@
 
 	/* step 2: make sure trigger sources are unique and mutually compatible */
 
-	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
+	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
 		err++;
-	}
 
 	if (cmd->scan_begin_src != TRIG_TIMER &&
 		cmd->scan_begin_src != TRIG_FOLLOW)
@@ -548,16 +540,14 @@
 		err++;
 	}
 
-	if (cmd->scan_begin_src == TRIG_TIMER)	/*  Test Delay timing */
-	{
+	if (cmd->scan_begin_src == TRIG_TIMER) {	/*  Test Delay timing */
 		if (cmd->scan_begin_arg < this_board->ui_MinDelaytimeNs) {
 			cmd->scan_begin_arg = this_board->ui_MinDelaytimeNs;
 			err++;
 		}
 	}
 
-	if (cmd->convert_src == TRIG_TIMER)	/*  Test Acquisition timing */
-	{
+	if (cmd->convert_src == TRIG_TIMER) {	/*  Test Acquisition timing */
 		if (cmd->scan_begin_src == TRIG_TIMER) {
 			if ((cmd->convert_arg)
 				&& (cmd->convert_arg <
@@ -653,11 +643,10 @@
 	/* UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len; */
 	devpriv->ui_AiDataLength = s->async->prealloc_bufsz;
 
-	if (cmd->stop_src == TRIG_COUNT) {
+	if (cmd->stop_src == TRIG_COUNT)
 		devpriv->ui_AiNbrofScans = cmd->stop_arg;
-	} else {
+	else
 		devpriv->ui_AiNbrofScans = 0;
-	}
 
 	devpriv->ui_AiTimer0 = 0;	/*  variables changed to timer0,timer1 */
 	devpriv->ui_AiTimer1 = 0;
@@ -849,9 +838,8 @@
 	}
 /*** EL241003 End ******************************************************************************/
 
-	if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) {
+	if (devpriv->b_ExttrigEnable == APCI3120_ENABLE)
 		i_APCI3120_ExttrigEnable(dev);	/*  activate EXT trigger */
-	}
 	switch (mode) {
 	case 1:
 		/*  init timer0 in mode 2 */
@@ -1049,12 +1037,10 @@
 					dmalen1 = 4;
 			}
 		} else {	/*  isn't output buff smaller that our DMA buff? */
-			if (dmalen0 > (devpriv->ui_AiDataLength)) {
+			if (dmalen0 > (devpriv->ui_AiDataLength))
 				dmalen0 = devpriv->ui_AiDataLength;
-			}
-			if (dmalen1 > (devpriv->ui_AiDataLength)) {
+			if (dmalen1 > (devpriv->ui_AiDataLength))
 				dmalen1 = devpriv->ui_AiDataLength;
-			}
 		}
 		devpriv->ui_DmaBufferUsesize[0] = dmalen0;
 		devpriv->ui_DmaBufferUsesize[1] = dmalen1;
@@ -1356,11 +1342,10 @@
 		/*  store range list to card */
 		us_TmpValue = CR_CHAN(chanlist[i]);	/*  get channel number; */
 
-		if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES) {
+		if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES)
 			us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff);	/*  set bipolar */
-		} else {
+		else
 			us_TmpValue |= APCI3120_UNIPOLAR;	/*  enable unipolar...... */
-		}
 
 		gain = CR_RANGE(chanlist[i]);	/*  get gain number */
 		us_TmpValue |= ((gain & 0x03) << 4);	/* <<4 for G0 and G1 bit in RAM */
@@ -1514,8 +1499,7 @@
 	/*  Check If EOS interrupt */
 	if ((int_daq & 0x2) && (devpriv->b_InterruptMode == APCI3120_EOS_MODE)) {
 
-		if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE)	/*  enable this in without DMA ??? */
-		{
+		if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {	/*  enable this in without DMA ??? */
 
 			if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
 				ui_Check = 0;
@@ -1966,8 +1950,7 @@
 		APCI3120_DISABLE_EOS_INT;
 	outb(devpriv->b_ModeSelectRegister,
 		devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
-	if (data[0] == APCI3120_TIMER)	/* initialize timer */
-	{
+	if (data[0] == APCI3120_TIMER) {	/* initialize timer */
 		/* devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister |
 		 * APCI3120_ENABLE_TIMER_INT; */
 
@@ -2006,8 +1989,7 @@
 		/*  timer2 in Timer mode enabled */
 		devpriv->b_Timer2Mode = APCI3120_TIMER;
 
-	} else			/*  Initialize Watch dog */
-	{
+	} else {			/*  Initialize Watch dog */
 
 		/* Set the Timer 2 in mode 5(Watchdog) */
 
@@ -2092,8 +2074,7 @@
 		return -EINVAL;
 	}
 
-	if (data[0] == 2)	/*  write new value */
-	{
+	if (data[0] == 2) {	/*  write new value */
 		if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
 			comedi_error(dev,
 				"write :timer2  not configured  in TIMER MODE");
@@ -2113,13 +2094,11 @@
 
 		/*  Reset FC_TIMER BIT */
 		inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
-		if (devpriv->b_Timer2Mode == APCI3120_TIMER)	/* start timer */
-		{
+		if (devpriv->b_Timer2Mode == APCI3120_TIMER) {	/* start timer */
 			/* Enable Timer */
 			devpriv->b_ModeSelectRegister =
 				devpriv->b_ModeSelectRegister & 0x0B;
-		} else		/* start watch dog */
-		{
+		} else {		/* start watch dog */
 			/* Enable WatchDog */
 			devpriv->b_ModeSelectRegister =
 				(devpriv->
@@ -2146,8 +2125,7 @@
 		outb(devpriv->b_ModeSelectRegister,
 			devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
 
-		if (devpriv->b_Timer2Mode == APCI3120_TIMER)	/* start timer */
-		{
+		if (devpriv->b_Timer2Mode == APCI3120_TIMER) {	/* start timer */
 			/* For Timer mode is  Gate2 must be activated   **timer started */
 			devpriv->us_OutputRegister =
 				devpriv->
@@ -2299,8 +2277,7 @@
 		/*  combining both words */
 		data[0] = (unsigned int) ((us_TmpValue) | ((us_TmpValue_2) << 16));
 
-	} else			/*  Read watch dog status */
-	{
+	} else {			/*  Read watch dog status */
 
 		us_StatusValue = inw(devpriv->iobase + APCI3120_RD_STATUS);
 		us_StatusValue =
@@ -2441,10 +2418,9 @@
 		devpriv->b_OutputMemoryStatus = APCI3120_DISABLE;
 		devpriv->b_DigitalOutputRegister = 0;
 	}
-	if (!devpriv->b_OutputMemoryStatus) {
+	if (!devpriv->b_OutputMemoryStatus)
 		ui_Temp = 0;
-
-	}			/* if(!devpriv->b_OutputMemoryStatus ) */
+				/* if(!devpriv->b_OutputMemoryStatus ) */
 
 	return insn->n;
 }
@@ -2504,23 +2480,23 @@
 
 /*
 +----------------------------------------------------------------------------+
-| Function name     :int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,|
-|struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) 			             |
-|                                            						         |
+| Function name		:int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,|
+|struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)	|
+|										|
 +----------------------------------------------------------------------------+
-| Task              : Write digiatl output								     |
-|                     										                 |
+| Task			: Write digiatl output					|
+| 										|
 +----------------------------------------------------------------------------+
-| Input Parameters  : struct comedi_device *dev								 	 |
-|                     struct comedi_subdevice *s									 |
-|                     struct comedi_insn *insn                                      |
-|                     unsigned int *data 										 |
-                      data[0]     Value to be written
-                      data[1]    :1 Set digital o/p ON
-                      data[1]     2 Set digital o/p OFF with memory ON
+| Input Parameters	: struct comedi_device *dev				|
+|			struct comedi_subdevice *s			 	|
+|			struct comedi_insn *insn				|
+|			unsigned int *data					|
+			data[0]     Value to be written
+			data[1]    :1 Set digital o/p ON
+			data[1]     2 Set digital o/p OFF with memory ON
 +----------------------------------------------------------------------------+
-| Return Value      :              					                         |
-|                    													     |
+| Return Value		:							|
+|										|
 +----------------------------------------------------------------------------+
 */
 
@@ -2615,8 +2591,7 @@
 	ui_Channel = CR_CHAN(insn->chanspec);
 
 	/* this_board->i_hwdrv_InsnWriteAnalogOutput(dev, ui_Range, ui_Channel,data[0]); */
-	if (ui_Range)		/*  if 1 then unipolar */
-	{
+	if (ui_Range) {		/*  if 1 then unipolar */
 
 		if (data[0] != 0)
 			data[0] =
@@ -2627,8 +2602,7 @@
 				((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
 					13) | 8192);
 
-	} else			/*  if 0 then   bipolar */
-	{
+	} else {			/*  if 0 then   bipolar */
 		data[0] =
 			((((ui_Channel & 0x03) << 14) & 0xC000) | (0 << 13) |
 			data[0]);
@@ -2639,8 +2613,7 @@
  * out put n values at the given channel. printk("\nwaiting for
  * DA_READY BIT");
  */
-	do			/* Waiting of DA_READY BIT */
-	{
+	do {			/* Waiting of DA_READY BIT */
 		us_TmpValue =
 			((unsigned short) inw(devpriv->iobase +
 				APCI3120_RD_STATUS)) & 0x0001;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
index 98c2387..560c848 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
index 7b38d17..4ed441a 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
index 1d1e5fc..3692326 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
@@ -17,7 +17,7 @@
 
 You 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
 
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
 
 @endverbatim
 */
@@ -1206,7 +1206,7 @@
 
 		if (b_Channel < 8) {
 	      /*****************************************************************************/
-			/* Read port 0 (first digital output port) and set/reset the selcted channel */
+			/* Read port 0 (first digital output port) and set/reset the selected channel */
 	      /*****************************************************************************/
 
 			dw_Status = inl(devpriv->iobase + 80);
@@ -1228,7 +1228,7 @@
 				if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF)
 					== 0xFF) {
 		    /*****************************************************************************/
-					/* Read port 2 (first digital output port) and set/reset the selcted channel */
+					/* Read port 2 (first digital output port) and set/reset the selected channel */
 		    /*****************************************************************************/
 
 					dw_Status = inl(devpriv->iobase + 112);
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index 791ea83..9934a3c 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -88,9 +88,9 @@
 #define IORANGE_9118 	64	/* I hope */
 #define PCI9118_CHANLEN	255	/* len of chanlist, some source say 256, but reality looks like 255 :-( */
 
-#define PCI9118_CNT0	0x00	/* R/W: 8254 couter 0 */
-#define PCI9118_CNT1	0x04	/* R/W: 8254 couter 0 */
-#define PCI9118_CNT2	0x08	/* R/W: 8254 couter 0 */
+#define PCI9118_CNT0	0x00	/* R/W: 8254 counter 0 */
+#define PCI9118_CNT1	0x04	/* R/W: 8254 counter 0 */
+#define PCI9118_CNT2	0x08	/* R/W: 8254 counter 0 */
 #define PCI9118_CNTCTRL	0x0c	/* W:   8254 counter control */
 #define PCI9118_AD_DATA	0x10	/* R:   A/D data */
 #define PCI9118_DA1	0x10	/* W:   D/A registers */
diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
index c5ed8bb..f3ba645 100644
--- a/drivers/staging/comedi/drivers/adq12b.c
+++ b/drivers/staging/comedi/drivers/adq12b.c
@@ -42,23 +42,23 @@
   option 1: I/O base address. The following table is provided as a help
    of the hardware jumpers.
 
-         address            jumper JADR
-          0x300                 1 (factory default)
-          0x320                 2
-          0x340                 3
-          0x360                 4
-          0x380                 5
-          0x3A0                 6
+	 address            jumper JADR
+	  0x300                 1 (factory default)
+	  0x320                 2
+	  0x340                 3
+	  0x360                 4
+	  0x380                 5
+	  0x3A0                 6
 
   option 2: unipolar/bipolar ADC selection: 0 -> bipolar, 1 -> unipolar
 
-        selection         comedi_config option            JUB
-         bipolar                0                         2-3 (factory default)
-         unipolar               1                         1-2
+	selection         comedi_config option            JUB
+	 bipolar                0                         2-3 (factory default)
+	 unipolar               1                         1-2
 
   option 3: single-ended/differential AI selection: 0 -> SE, 1 -> differential
 
-        selection         comedi_config option     JCHA    JCHB
+	selection         comedi_config option     JCHA    JCHB
        single-ended             0                  1-2     1-2 (factory default)
        differential             1                  2-3     2-3
 
@@ -140,7 +140,7 @@
 	.ai_bits = 12,
 	.di_chans = 8,
 	.do_chans = 5
-        }*/
+	}*/
 };
 
 #define thisboard ((const struct adq12b_board *)dev->board_ptr)
@@ -164,14 +164,15 @@
 static int adq12b_attach(struct comedi_device *dev,
 			 struct comedi_devconfig *it);
 static int adq12b_detach(struct comedi_device *dev);
+
 static struct comedi_driver driver_adq12b = {
-driver_name:"adq12b",
-module:THIS_MODULE,
-attach:adq12b_attach,
-detach:adq12b_detach,
-board_name:&adq12b_boards[0].name,
-offset:sizeof(struct adq12b_board),
-num_names:ARRAY_SIZE(adq12b_boards),
+	.driver_name = "adq12b",
+	.module = THIS_MODULE,
+	.attach = adq12b_attach,
+	.detach = adq12b_detach,
+	.board_name = &adq12b_boards[0].name,
+	.offset = sizeof(struct adq12b_board),
+	.num_names = ARRAY_SIZE(adq12b_boards),
 };
 
 static int adq12b_ai_rinsn(struct comedi_device *dev,
@@ -200,15 +201,16 @@
 	unipolar = it->options[1];
 	differential = it->options[2];
 
-	printk("comedi%d: adq12b called with options base=0x%03lx, %s and %s\n",
-	       dev->minor, iobase, (unipolar == 1) ? "unipolar" : "bipolar",
+	printk(KERN_INFO "comedi%d: adq12b called with options base=0x%03lx, "
+	       "%s and %s\n", dev->minor, iobase,
+	       (unipolar == 1) ? "unipolar" : "bipolar",
 	       (differential == 1) ? "differential" : "single-ended");
 
 	/* if no address was specified, try the default 0x300 */
 	if (iobase == 0) {
-		printk
-		    ("comedi%d: adq12b warning: I/O base address not specified. Trying the default 0x300.\n",
-		     dev->minor);
+		printk(KERN_WARNING "comedi%d: adq12b warning: I/O base "
+		       "address not specified. Trying the default 0x300.\n",
+		       dev->minor);
 		iobase = 0x300;
 	}
 
@@ -259,11 +261,10 @@
 		s->n_chan = thisboard->ai_se_chans;
 	}
 
-	if (unipolar) {
+	if (unipolar)
 		s->range_table = &range_adq12b_ai_unipolar;
-	} else {
+	else
 		s->range_table = &range_adq12b_ai_bipolar;
-	}
 
 	s->maxdata = (1 << thisboard->ai_bits) - 1;
 
@@ -289,7 +290,7 @@
 	s->range_table = &range_digital;
 	s->insn_bits = adq12b_do_insn_bits;
 
-	printk("attached\n");
+	printk(KERN_INFO "attached\n");
 
 	return 0;
 }
@@ -309,7 +310,7 @@
 
 	kfree(devpriv);
 
-	printk("comedi%d: adq12b: removed\n", dev->minor);
+	printk(KERN_INFO "comedi%d: adq12b: removed\n", dev->minor);
 
 	return 0;
 }
@@ -344,17 +345,18 @@
 		/* wait for end of convertion */
 		i = 0;
 		do {
-/* udelay(1); */
+			/* udelay(1); */
 			status = inb(dev->iobase + ADQ12B_STINR);
 			status = status & ADQ12B_EOC;
 		} while (status == 0 && ++i < TIMEOUT);
-/* } while (++i < 10); */
+		/* } while (++i < 10); */
 
 		/* read data */
 		hi = inb(dev->iobase + ADQ12B_ADHIG);
 		lo = inb(dev->iobase + ADQ12B_ADLOW);
 
-		/* printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n", channel, range, status,  hi, lo); */
+		/* printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n",
+		       channel, range, status,  hi, lo); */
 		data[n] = (hi << 8) | lo;
 
 	}
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index 951e579..394d2ea 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -84,9 +84,9 @@
 #define PCI171x_DAREF	14	/* W:   D/A reference control */
 #define PCI171x_DI	16	/* R:   digi inputs */
 #define PCI171x_DO	16	/* R:   digi inputs */
-#define PCI171x_CNT0	24	/* R/W: 8254 couter 0 */
-#define PCI171x_CNT1	26	/* R/W: 8254 couter 1 */
-#define PCI171x_CNT2	28	/* R/W: 8254 couter 2 */
+#define PCI171x_CNT0	24	/* R/W: 8254 counter 0 */
+#define PCI171x_CNT1	26	/* R/W: 8254 counter 1 */
+#define PCI171x_CNT2	28	/* R/W: 8254 counter 2 */
 #define PCI171x_CNTCTRL	30	/* W:   8254 counter control */
 
 /* upper bits from status register (PCI171x_STATUS) (lower is same woth control reg) */
@@ -724,6 +724,7 @@
 			devpriv->ai_act_scan++;
 		}
 	}
+	s->async->cur_chan = j;
 	DPRINTK("adv_pci1710 EDBG: END: move_block_from_fifo(...)\n");
 	return 0;
 }
@@ -1034,14 +1035,6 @@
 		}
 	}
 
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->chanlist_len > this_board->n_aichan) {
-		cmd->chanlist_len = this_board->n_aichan;
-		err++;
-	}
 	if (cmd->scan_end_arg != cmd->chanlist_len) {
 		cmd->scan_end_arg = cmd->chanlist_len;
 		err++;
@@ -1230,6 +1223,12 @@
 		DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
 			devpriv->act_chanlist[i]);
 	}
+#ifdef PCI171x_PARANOIDCHECK
+	for ( ; i < n_chan; i++) { /* store remainder of channel list */
+		devpriv->act_chanlist[i] =
+		    (CR_CHAN(chanlist[i]) << 12) & 0xf000;
+	}
+#endif
 
 	devpriv->ai_et_MuxVal =
 	    CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
index 3857fd5..4baef9f 100644
--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
+++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
@@ -98,7 +98,7 @@
 	int iobase;
 	struct comedi_subdevice *s;
 
-	printk("comedi%d: aio_iiro_16: ", dev->minor);
+	printk(KERN_INFO "comedi%d: aio_iiro_16: ", dev->minor);
 
 	dev->board_name = thisboard->name;
 
@@ -140,7 +140,7 @@
 
 static int aio_iiro_16_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: aio_iiro_16: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: aio_iiro_16: remove\n", dev->minor);
 
 	if (dev->iobase)
 		release_region(dev->iobase, AIO_IIRO_16_SIZE);
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 69ab281..204f30e 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -48,8 +48,8 @@
 
 SUBDEVICES
 
-                    PC218E         PC212E      PC215E/PCI215
-                 -------------  -------------  -------------
+		    PC218E         PC212E      PC215E/PCI215
+		 -------------  -------------  -------------
   Subdevices           7              6              5
    0                 CTR-X1         PPI-X          PPI-X
    1                 CTR-X2         CTR-Y1         PPI-Y
@@ -59,8 +59,8 @@
    5                 CTR-Z2       INTERRUPT
    6               INTERRUPT
 
-                    PC214E      PC272E/PCI272
-                 -------------  -------------
+		    PC214E      PC272E/PCI272
+		 -------------  -------------
   Subdevices           4              4
    0                 PPI-X          PPI-X
    1                 PPI-Y          PPI-Y
@@ -96,8 +96,8 @@
     0 to 7 as follows:
 
       0.  CLK n, the counter channel's dedicated CLK input from the SK1
-        connector.  (N.B. for other values, the counter channel's CLKn
-        pin on the SK1 connector is an output!)
+	connector.  (N.B. for other values, the counter channel's CLKn
+	pin on the SK1 connector is an output!)
       1.  Internal 10 MHz clock.
       2.  Internal 1 MHz clock.
       3.  Internal 100 kHz clock.
@@ -105,8 +105,8 @@
       5.  Internal 1 kHz clock.
       6.  OUT n-1, the output of counter channel n-1 (see note 1 below).
       7.  Ext Clock, the counter chip's dedicated Ext Clock input from
-        the SK1 connector.  This pin is shared by all three counter
-        channels on the chip.
+	the SK1 connector.  This pin is shared by all three counter
+	channels on the chip.
 
   INSN_CONFIG_GET_CLOCK_SRC.  Returns the counter channel's current
     clock source in data[1].  For internal clock sources, data[2] is set
@@ -120,10 +120,10 @@
       0.  VCC (internal +5V d.c.), i.e. gate permanently enabled.
       1.  GND (internal 0V d.c.), i.e. gate permanently disabled.
       2.  GAT n, the counter channel's dedicated GAT input from the SK1
-        connector.  (N.B. for other values, the counter channel's GATn
-        pin on the SK1 connector is an output!)
+	connector.  (N.B. for other values, the counter channel's GATn
+	pin on the SK1 connector is an output!)
       3.  /OUT n-2, the inverted output of counter channel n-2 (see note
-        2 below).
+	2 below).
       4.  Reserved.
       5.  Reserved.
       6.  Reserved.
@@ -153,8 +153,8 @@
 
 INTERRUPT SOURCES
 
-                    PC218E         PC212E      PC215E/PCI215
-                 -------------  -------------  -------------
+		    PC218E         PC212E      PC215E/PCI215
+		 -------------  -------------  -------------
   Sources              6              6              6
    0              CTR-X1-OUT      PPI-X-C0       PPI-X-C0
    1              CTR-X2-OUT      PPI-X-C3       PPI-X-C3
@@ -163,8 +163,8 @@
    4              CTR-Z1-OUT     CTR-Z1-OUT     CTR-Z1-OUT
    5              CTR-Z2-OUT     CTR-Z2-OUT     CTR-Z2-OUT
 
-                    PC214E      PC272E/PCI272
-                 -------------  -------------
+		    PC214E      PC272E/PCI272
+		 -------------  -------------
   Sources              1              6
    0               JUMPER-J5      PPI-X-C0
    1                              PPI-X-C3
@@ -435,11 +435,13 @@
  * Useful for shorthand access to the particular board structure
  */
 #define thisboard ((const struct dio200_board *)dev->board_ptr)
-#define thislayout (&dio200_layouts[((struct dio200_board *)dev->board_ptr)->layout])
+#define thislayout (&dio200_layouts[((struct dio200_board *) \
+		    dev->board_ptr)->layout])
 
 /* this structure is for data unique to this hardware driver.  If
    several hardware drivers keep similar information in this structure,
-   feel free to suggest moving the variable to the struct comedi_device struct.  */
+   feel free to suggest moving the variable to the struct comedi_device struct.
+ */
 struct dio200_private {
 #ifdef CONFIG_COMEDI_PCI
 	struct pci_dev *pci_dev;	/* PCI device */
@@ -603,9 +605,8 @@
 
 	subpriv->active = 0;
 	subpriv->enabled_isns = 0;
-	if (subpriv->has_int_sce) {
+	if (subpriv->has_int_sce)
 		outb(0, subpriv->iobase);
-	}
 }
 
 /*
@@ -629,16 +630,14 @@
 		/* Determine interrupt sources to enable. */
 		isn_bits = 0;
 		if (cmd->chanlist) {
-			for (n = 0; n < cmd->chanlist_len; n++) {
+			for (n = 0; n < cmd->chanlist_len; n++)
 				isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
-			}
 		}
 		isn_bits &= subpriv->valid_isns;
 		/* Enable interrupt sources. */
 		subpriv->enabled_isns = isn_bits;
-		if (subpriv->has_int_sce) {
+		if (subpriv->has_int_sce)
 			outb(isn_bits, subpriv->iobase);
-		}
 	}
 
 	return retval;
@@ -662,14 +661,13 @@
 
 	spin_lock_irqsave(&subpriv->spinlock, flags);
 	s->async->inttrig = 0;
-	if (subpriv->active) {
+	if (subpriv->active)
 		event = dio200_start_intr(dev, s);
-	}
+
 	spin_unlock_irqrestore(&subpriv->spinlock, flags);
 
-	if (event) {
+	if (event)
 		comedi_event(dev, s);
-	}
 
 	return 1;
 }
@@ -726,9 +724,8 @@
 		 * Reenable them NOW to minimize the time they are disabled.
 		 */
 		cur_enabled = subpriv->enabled_isns;
-		if (subpriv->has_int_sce) {
+		if (subpriv->has_int_sce)
 			outb(cur_enabled, subpriv->iobase);
-		}
 
 		if (subpriv->active) {
 			/*
@@ -747,9 +744,8 @@
 				len = s->async->cmd.chanlist_len;
 				for (n = 0; n < len; n++) {
 					ch = CR_CHAN(s->async->cmd.chanlist[n]);
-					if (triggered & (1U << ch)) {
+					if (triggered & (1U << ch))
 						val |= (1U << n);
-					}
 				}
 				/* Write the scan to the buffer. */
 				if (comedi_buf_put(s->async, val)) {
@@ -781,9 +777,8 @@
 	}
 	spin_unlock_irqrestore(&subpriv->spinlock, flags);
 
-	if (oldevents != s->async->events) {
+	if (oldevents != s->async->events)
 		comedi_event(dev, s);
-	}
 
 	return (triggered != 0);
 }
@@ -798,9 +793,9 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&subpriv->spinlock, flags);
-	if (subpriv->active) {
+	if (subpriv->active)
 		dio200_stop_intr(dev, s);
-	}
+
 	spin_unlock_irqrestore(&subpriv->spinlock, flags);
 
 	return 0;
@@ -846,7 +841,8 @@
 	if (err)
 		return 1;
 
-	/* step 2: make sure trigger sources are unique and mutually compatible */
+	/* step 2: make sure trigger sources are unique and mutually
+		   compatible */
 
 	/* these tests are true if more than one _src bit is set */
 	if ((cmd->start_src & (cmd->start_src - 1)) != 0)
@@ -952,9 +948,8 @@
 	}
 	spin_unlock_irqrestore(&subpriv->spinlock, flags);
 
-	if (event) {
+	if (event)
 		comedi_event(dev, s);
-	}
 
 	return 0;
 }
@@ -980,9 +975,8 @@
 	subpriv->valid_isns = valid_isns;
 	spin_lock_init(&subpriv->spinlock);
 
-	if (has_int_sce) {
+	if (has_int_sce)
 		outb(0, subpriv->iobase);	/* Disable interrupt sources. */
-	}
 
 	s->private = subpriv;
 	s->type = COMEDI_SUBD_DI;
@@ -1013,10 +1007,7 @@
 			   struct comedi_subdevice *s)
 {
 	struct dio200_subdev_intr *subpriv = s->private;
-
-	if (subpriv) {
-		kfree(subpriv);
-	}
+	kfree(subpriv);
 }
 
 /*
@@ -1027,9 +1018,8 @@
 	struct comedi_device *dev = d;
 	int handled;
 
-	if (!dev->attached) {
+	if (!dev->attached)
 		return IRQ_NONE;
-	}
 
 	if (devpriv->intr_sd >= 0) {
 		handled = dio200_handle_read_intr(dev,
@@ -1266,10 +1256,7 @@
 			   struct comedi_subdevice *s)
 {
 	struct dio200_subdev_intr *subpriv = s->private;
-
-	if (subpriv) {
-		kfree(subpriv);
-	}
+	kfree(subpriv);
 }
 
 /*
@@ -1348,9 +1335,8 @@
 #endif
 	{
 		ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
-		if (ret < 0) {
+		if (ret < 0)
 			return ret;
-		}
 	}
 	dev->iobase = iobase;
 
@@ -1371,17 +1357,17 @@
 			ret = dio200_subdev_8254_init(dev, s, iobase,
 						      layout->sdinfo[n],
 						      layout->has_clk_gat_sce);
-			if (ret < 0) {
+			if (ret < 0)
 				return ret;
-			}
+
 			break;
 		case sd_8255:
 			/* digital i/o subdevice (8255) */
 			ret = subdev_8255_init(dev, s, 0,
 					       iobase + layout->sdinfo[n]);
-			if (ret < 0) {
+			if (ret < 0)
 				return ret;
-			}
+
 			break;
 		case sd_intr:
 			/* 'INTERRUPT' subdevice */
@@ -1392,9 +1378,9 @@
 							      layout->sdinfo[n],
 							      layout->
 							      has_int_sce);
-				if (ret < 0) {
+				if (ret < 0)
 					return ret;
-				}
+
 				devpriv->intr_sd = n;
 			} else {
 				s->type = COMEDI_SUBD_UNUSED;
@@ -1407,9 +1393,8 @@
 	}
 
 	sdx = devpriv->intr_sd;
-	if (sdx >= 0 && sdx < dev->n_subdevices) {
+	if (sdx >= 0 && sdx < dev->n_subdevices)
 		dev->read_subdev = &dev->subdevices[sdx];
-	}
 
 	dev->board_name = thisboard->name;
 
@@ -1434,11 +1419,10 @@
 		printk("(pci %s) ", pci_name(pci_dev));
 #endif
 	}
-	if (irq) {
+	if (irq)
 		printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
-	} else {
+	else
 		printk("(no irq) ");
-	}
 
 	printk("attached\n");
 
@@ -1461,9 +1445,8 @@
 	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
 	       DIO200_DRIVER_NAME);
 
-	if (dev->irq) {
+	if (dev->irq)
 		free_irq(dev->irq, dev);
-	}
 	if (dev->subdevices) {
 		layout = thislayout;
 		for (n = 0; n < dev->n_subdevices; n++) {
@@ -1486,22 +1469,19 @@
 	if (devpriv) {
 #ifdef CONFIG_COMEDI_PCI
 		if (devpriv->pci_dev) {
-			if (dev->iobase) {
+			if (dev->iobase)
 				comedi_pci_disable(devpriv->pci_dev);
-			}
 			pci_dev_put(devpriv->pci_dev);
 		} else
 #endif
 		{
-			if (dev->iobase) {
+			if (dev->iobase)
 				release_region(dev->iobase, DIO200_IO_SIZE);
-			}
 		}
 	}
-	if (dev->board_name) {
+	if (dev->board_name)
 		printk(KERN_INFO "comedi%d: %s removed\n",
 		       dev->minor, dev->board_name);
-	}
 
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 1032a81..a307d68 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -78,18 +78,18 @@
  */
 /* Disable interrupt, also clear any interrupt there */
 #define PCI236_INTR_DISABLE (PLX9052_INTCSR_LI1ENAB_DISABLED \
-        | PLX9052_INTCSR_LI1POL_HIGH \
-        | PLX9052_INTCSR_LI2POL_HIGH \
-        | PLX9052_INTCSR_PCIENAB_DISABLED \
-        | PLX9052_INTCSR_LI1SEL_EDGE \
-        | PLX9052_INTCSR_LI1CLRINT_ASSERTED)
+	| PLX9052_INTCSR_LI1POL_HIGH \
+	| PLX9052_INTCSR_LI2POL_HIGH \
+	| PLX9052_INTCSR_PCIENAB_DISABLED \
+	| PLX9052_INTCSR_LI1SEL_EDGE \
+	| PLX9052_INTCSR_LI1CLRINT_ASSERTED)
 /* Enable interrupt, also clear any interrupt there. */
 #define PCI236_INTR_ENABLE (PLX9052_INTCSR_LI1ENAB_ENABLED \
-        | PLX9052_INTCSR_LI1POL_HIGH \
-        | PLX9052_INTCSR_LI2POL_HIGH \
-        | PLX9052_INTCSR_PCIENAB_ENABLED \
-        | PLX9052_INTCSR_LI1SEL_EDGE \
-        | PLX9052_INTCSR_LI1CLRINT_ASSERTED)
+	| PLX9052_INTCSR_LI1POL_HIGH \
+	| PLX9052_INTCSR_LI2POL_HIGH \
+	| PLX9052_INTCSR_PCIENAB_ENABLED \
+	| PLX9052_INTCSR_LI1SEL_EDGE \
+	| PLX9052_INTCSR_LI1CLRINT_ASSERTED)
 
 /*
  * Board descriptions for Amplicon PC36AT and PCI236.
@@ -150,12 +150,13 @@
 
 /* this structure is for data unique to this hardware driver.  If
    several hardware drivers keep similar information in this structure,
-   feel free to suggest moving the variable to the struct comedi_device struct.  */
+   feel free to suggest moving the variable to the struct comedi_device struct.
+ */
 struct pc236_private {
 #ifdef CONFIG_COMEDI_PCI
 	/* PCI device */
 	struct pci_dev *pci_dev;
-	unsigned long lcr_iobase;	/* PLX PCI9052 config registers in PCIBAR1 */
+	unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */
 #endif
 	int enable_irq;
 };
@@ -345,9 +346,8 @@
 #endif
 	{
 		ret = pc236_request_region(dev->minor, iobase, PC236_IO_SIZE);
-		if (ret < 0) {
+		if (ret < 0)
 			return ret;
-		}
 	}
 	dev->iobase = iobase;
 
@@ -399,11 +399,10 @@
 		printk("(pci %s) ", pci_name(pci_dev));
 #endif
 	}
-	if (irq) {
+	if (irq)
 		printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
-	} else {
+	else
 		printk("(no irq) ");
-	}
 
 	printk("attached\n");
 
@@ -422,27 +421,24 @@
 {
 	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
 	       PC236_DRIVER_NAME);
-	if (devpriv) {
+	if (devpriv)
 		pc236_intr_disable(dev);
-	}
+
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (dev->subdevices) {
+	if (dev->subdevices)
 		subdev_8255_cleanup(dev, dev->subdevices + 0);
-	}
 	if (devpriv) {
 #ifdef CONFIG_COMEDI_PCI
 		if (devpriv->pci_dev) {
-			if (dev->iobase) {
+			if (dev->iobase)
 				comedi_pci_disable(devpriv->pci_dev);
-			}
 			pci_dev_put(devpriv->pci_dev);
 		} else
 #endif
 		{
-			if (dev->iobase) {
+			if (dev->iobase)
 				release_region(dev->iobase, PC236_IO_SIZE);
-			}
 		}
 	}
 	if (dev->board_name) {
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index d983687..b41e5e59 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -1536,20 +1536,12 @@
 
 		s = dev->subdevices + 0;
 		/* AO subdevice */
-		if (s->range_table_list) {
-			kfree(s->range_table_list);
-		}
+		kfree(s->range_table_list);
 	}
 	if (devpriv) {
-		if (devpriv->ao_readback) {
-			kfree(devpriv->ao_readback);
-		}
-		if (devpriv->ao_scan_vals) {
-			kfree(devpriv->ao_scan_vals);
-		}
-		if (devpriv->ao_scan_order) {
-			kfree(devpriv->ao_scan_order);
-		}
+		kfree(devpriv->ao_readback);
+		kfree(devpriv->ao_scan_vals);
+		kfree(devpriv->ao_scan_order);
 		if (devpriv->pci_dev) {
 			if (dev->iobase) {
 				comedi_pci_disable(devpriv->pci_dev);
diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
index abb0532..fb0d5fa 100644
--- a/drivers/staging/comedi/drivers/c6xdigio.c
+++ b/drivers/staging/comedi/drivers/c6xdigio.c
@@ -45,7 +45,7 @@
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/timer.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/pnp.h>
 
 #include "../comedidev.h"
@@ -220,11 +220,11 @@
 	/* printk("Inside C6X_encInput\n"); */
 
 	enc.value = 0;
-	if (channel == 0) {
+	if (channel == 0)
 		ppcmd = 0x48;
-	} else {
+	else
 		ppcmd = 0x50;
-	}
+
 	WriteByteToHwPort(baseAddr, ppcmd);
 	tmp = ReadByteFromHwPort(baseAddr + 1);
 	while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) {
@@ -391,9 +391,8 @@
 	int n;
 	int chan = CR_CHAN(insn->chanspec);
 
-	for (n = 0; n < insn->n; n++) {
+	for (n = 0; n < insn->n; n++)
 		data[n] = (C6X_encInput(dev->iobase, chan) & 0xffffff);
-	}
 
 	return n;
 }
@@ -420,9 +419,9 @@
 
 static const struct pnp_device_id c6xdigio_pnp_tbl[] = {
 	/* Standard LPT Printer Port */
-	{.id = "PNP0400",.driver_data = 0},
+	{.id = "PNP0400", .driver_data = 0},
 	/* ECP Printer Port */
-	{.id = "PNP0401",.driver_data = 0},
+	{.id = "PNP0401", .driver_data = 0},
 	{}
 };
 
@@ -452,15 +451,14 @@
 	if (result < 0)
 		return result;
 
-	/*  Make sure that PnP ports gets activated */
+	/*  Make sure that PnP ports get activated */
 	pnp_register_driver(&c6xdigio_pnp_driver);
 
 	irq = it->options[1];
-	if (irq > 0) {
+	if (irq > 0)
 		printk("comedi%d: irq = %u ignored\n", dev->minor, irq);
-	} else if (irq == 0) {
+	else if (irq == 0)
 		printk("comedi%d: no irq\n", dev->minor);
-	}
 
 	s = dev->subdevices + 0;
 	/* pwm output subdevice */
@@ -483,19 +481,19 @@
 	s->maxdata = 0xffffff;
 	s->range_table = &range_unknown;
 
-	/*           s = dev->subdevices + 2; */
+	/*	s = dev->subdevices + 2; */
 	/* pwm output subdevice */
-	/*       s->type = COMEDI_SUBD_COUNTER;  // Not sure what to put here */
-	/*       s->subdev_flags = SDF_WRITEABLE; */
-	/*       s->n_chan = 1; */
-	/*       s->trig[0] = c6xdigio_ei_init; */
-	/*       s->insn_read = c6xdigio_ei_init_insn_read; */
-	/*       s->insn_write = c6xdigio_ei_init_insn_write; */
-	/*       s->maxdata = 0xFFFF;  // Really just a don't care */
-	/*       s->range_table = &range_unknown; // Not sure what to put here */
+	/*	s->type = COMEDI_SUBD_COUNTER;  // Not sure what to put here */
+	/*	s->subdev_flags = SDF_WRITEABLE; */
+	/*	s->n_chan = 1; */
+	/*	s->trig[0] = c6xdigio_ei_init; */
+	/*	s->insn_read = c6xdigio_ei_init_insn_read; */
+	/*	s->insn_write = c6xdigio_ei_init_insn_write; */
+	/*	s->maxdata = 0xFFFF;  // Really just a don't care */
+	/*	s->range_table = &range_unknown; // Not sure what to put here */
 
-	/*  I will call this init anyway but more than likely the DSP board will not be connect */
-	/*  when device driver is loaded. */
+	/*  I will call this init anyway but more than likely the DSP board */
+	/*  will not be connected when device driver is loaded. */
 	board_init(dev);
 
 	return 0;
@@ -503,16 +501,17 @@
 
 static int c6xdigio_detach(struct comedi_device *dev)
 {
-/* board_halt(dev);  may not need this */
+	/* board_halt(dev);  may not need this */
 
 	printk("comedi%d: c6xdigio: remove\n", dev->minor);
 
-	if (dev->iobase) {
+	if (dev->iobase)
 		release_region(dev->iobase, C6XDIGIO_SIZE);
-	}
-	if (dev->irq) {
+
+	/*  Not using IRQ so I am not sure if I need this */
+	if (dev->irq)
 		free_irq(dev->irq, dev);
-	}			/*  Not using IRQ so I am not sure if I need this */
+
 	pnp_unregister_driver(&c6xdigio_pnp_driver);
 
 	return 0;
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index f3e66c4..434591d 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -518,7 +518,7 @@
 static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
 			      uint8_t value);
 static int nvram_read(struct comedi_device *dev, unsigned int address,
-		      uint8_t * data);
+		      uint8_t *data);
 
 static inline unsigned int cal_enable_bits(struct comedi_device *dev)
 {
@@ -760,9 +760,8 @@
 	if (dev->subdevices)
 		subdev_8255_cleanup(dev, dev->subdevices + 2);
 	if (devpriv && devpriv->pci_dev) {
-		if (devpriv->s5933_config) {
+		if (devpriv->s5933_config)
 			comedi_pci_disable(devpriv->pci_dev);
-		}
 		pci_dev_put(devpriv->pci_dev);
 	}
 
@@ -1248,9 +1247,8 @@
 					cmd->flags & TRIG_ROUND_MASK);
 
 	/*  set number of conversions */
-	if (cmd->stop_src == TRIG_COUNT) {
+	if (cmd->stop_src == TRIG_COUNT)
 		devpriv->count = cmd->chanlist_len * cmd->stop_arg;
-	}
 	/*  enable interrupts */
 	spin_lock_irqsave(&dev->spinlock, flags);
 	devpriv->adc_fifo_bits |= INTE;
@@ -1449,9 +1447,8 @@
 			   devpriv->ao_divisor2, 2);
 	}
 	/*  set number of conversions */
-	if (cmd->stop_src == TRIG_COUNT) {
+	if (cmd->stop_src == TRIG_COUNT)
 		devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
-	}
 	/*  set pacer source */
 	spin_lock_irqsave(&dev->spinlock, flags);
 	switch (cmd->scan_begin_src) {
@@ -1494,9 +1491,8 @@
 					       num_points * sizeof(short));
 	num_points = num_bytes / sizeof(short);
 
-	if (cmd->stop_src == TRIG_COUNT) {
+	if (cmd->stop_src == TRIG_COUNT)
 		devpriv->ao_count -= num_points;
-	}
 	/*  write data to board's fifo */
 	outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
 
@@ -1534,9 +1530,8 @@
 	static const int timeout = 10000;
 	unsigned long flags;
 
-	if (dev->attached == 0) {
+	if (dev->attached == 0)
 		return IRQ_NONE;
-	}
 
 	async = s->async;
 	async->events = 0;
@@ -1558,15 +1553,13 @@
 
 	status = inw(devpriv->control_status + INT_ADCFIFO);
 #ifdef CB_PCIDAS_DEBUG
-	if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0) {
+	if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0)
 		comedi_error(dev, "spurious interrupt");
-	}
 #endif
 
 	/*  check for analog output interrupt */
-	if (status & (DAHFI | DAEMI)) {
+	if (status & (DAHFI | DAEMI))
 		handle_ao_interrupt(dev, status);
-	}
 	/*  check for analog input interrupts */
 	/*  if fifo half-full */
 	if (status & ADHFI) {
@@ -1675,9 +1668,8 @@
 					       num_points * sizeof(short));
 		num_points = num_bytes / sizeof(short);
 
-		if (async->cmd.stop_src == TRIG_COUNT) {
+		if (async->cmd.stop_src == TRIG_COUNT)
 			devpriv->ao_count -= num_points;
-		}
 		/*  write data to board's fifo */
 		outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
 		      num_points);
@@ -1852,7 +1844,7 @@
 }
 
 static int nvram_read(struct comedi_device *dev, unsigned int address,
-		      uint8_t * data)
+			uint8_t *data)
 {
 	unsigned long iobase = devpriv->s5933_config;
 
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index 7823577..81829d6 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -410,9 +410,8 @@
  */
 	if (devpriv) {
 		if (devpriv->pci_dev) {
-			if (devpriv->dac) {
+			if (devpriv->dac)
 				comedi_pci_disable(devpriv->pci_dev);
-			}
 			pci_dev_put(devpriv->pci_dev);
 		}
 	}
@@ -677,9 +676,8 @@
 
 	for (i = 1; i <= value_width; i++) {
 		/*  read bits most significant bit first */
-		if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT) {
+		if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT)
 			value |= 1 << (value_width - i);
-		}
 	}
 
 	return value;
@@ -716,9 +714,8 @@
 	/*  send serial output stream to eeprom */
 	cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT;
 	/*  deactivate caldacs (one caldac for every two channels) */
-	for (i = 0; i < max_num_caldacs; i++) {
+	for (i = 0; i < max_num_caldacs; i++)
 		cal2_bits |= DESELECT_CALDAC_BIT(i);
-	}
 	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
 
 	/*  tell eeprom we want to read */
@@ -756,9 +753,8 @@
 */
 	cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT;
 	/*  deactivate caldacs (one caldac for every two channels) */
-	for (i = 0; i < max_num_caldacs; i++) {
+	for (i = 0; i < max_num_caldacs; i++)
 		cal2_bits |= DESELECT_CALDAC_BIT(i);
-	}
 	/*  activate the caldac we want */
 	cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
 	outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
index 7daad0a..38ccd10 100644
--- a/drivers/staging/comedi/drivers/cb_pcidio.c
+++ b/drivers/staging/comedi/drivers/cb_pcidio.c
@@ -283,17 +283,15 @@
 	printk("comedi%d: cb_pcidio: remove\n", dev->minor);
 	if (devpriv) {
 		if (devpriv->pci_dev) {
-			if (devpriv->dio_reg_base) {
+			if (devpriv->dio_reg_base)
 				comedi_pci_disable(devpriv->pci_dev);
-			}
 			pci_dev_put(devpriv->pci_dev);
 		}
 	}
 	if (dev->subdevices) {
 		int i;
-		for (i = 0; i < thisboard->n_8255; i++) {
+		for (i = 0; i < thisboard->n_8255; i++)
 			subdev_8255_cleanup(dev, dev->subdevices + i);
-		}
 	}
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index cbbca05..2e61727 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -330,11 +330,10 @@
 
 	s = dev->subdevices + 2;
 	/* digital i/o subdevice */
-	if (thisboard->has_dio) {
+	if (thisboard->has_dio)
 		subdev_8255_init(dev, s, NULL, devpriv->BADR4);
-	} else {
+	else
 		s->type = COMEDI_SUBD_UNUSED;
-	}
 
 	printk("attached\n");
 
@@ -365,9 +364,8 @@
 		free_irq(dev->irq, dev);
 	if (devpriv) {
 		if (devpriv->pci_dev) {
-			if (devpriv->BADR0) {
+			if (devpriv->BADR0)
 				comedi_pci_disable(devpriv->pci_dev);
-			}
 			pci_dev_put(devpriv->pci_dev);
 		}
 	}
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index 980fa0a..e32a317 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -284,11 +284,10 @@
 	s->n_chan = thisboard->ao_chans;
 	s->maxdata = figure_out_maxdata(thisboard->ao_bits);
 	/* this is hard-coded here */
-	if (it->options[2]) {
+	if (it->options[2])
 		s->range_table = &range_bipolar10;
-	} else {
+	else
 		s->range_table = &range_bipolar5;
-	}
 	s->insn_write = &ao_winsn;
 	s->insn_read = &ao_rinsn;
 
@@ -337,9 +336,8 @@
 		}
 
 		if (devpriv->pci_dev) {
-			if (devpriv->registers) {
+			if (devpriv->registers)
 				comedi_pci_disable(devpriv->pci_dev);
-			}
 			pci_dev_put(devpriv->pci_dev);
 		}
 
diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
index cf39a24..d7260cc 100644
--- a/drivers/staging/comedi/drivers/comedi_bond.c
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -417,7 +417,7 @@
 		int sdev = -1, nchans, tmp;
 		struct BondedDevice *bdev = NULL;
 
-		if (minor < 0 || minor > COMEDI_NUM_BOARD_MINORS) {
+		if (minor < 0 || minor >= COMEDI_NUM_BOARD_MINORS) {
 			ERROR("Minor %d is invalid!\n", minor);
 			return 0;
 		}
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index b16d652..9511814 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -173,9 +173,8 @@
 	printk("comedi%d: contec: remove\n", dev->minor);
 
 	if (devpriv && devpriv->pci_dev) {
-		if (dev->iobase) {
+		if (dev->iobase)
 			comedi_pci_disable(devpriv->pci_dev);
-		}
 		pci_dev_put(devpriv->pci_dev);
 	}
 
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 9b945e5..f12ef1c 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -34,7 +34,7 @@
 das08 driver.
 
 Options (for pcm-das08):
-        NONE
+	NONE
 
 Command support does not exist, but could be added for this board.
 */
@@ -52,7 +52,7 @@
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
-static struct pcmcia_device *cur_dev = NULL;
+static struct pcmcia_device *cur_dev;
 
 #define thisboard ((const struct das08_board_struct *)dev->board_ptr)
 
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index 92487f5..a404a18 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -45,7 +45,7 @@
 
 #define DAS6402_SIZE 16
 
-#define N_WORDS 3000*64
+#define N_WORDS (3000*64)
 
 #define STOP    0
 #define START   1
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index ecb97cd..aadc497 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -399,9 +399,8 @@
 		} else {
 			fifo_empty = 0;	/*  cio-das802/16 has no fifo empty status bit */
 		}
-		if (fifo_empty) {
+		if (fifo_empty)
 			break;
-		}
 		/* strip off extraneous bits for 12 bit cards */
 		if (thisboard->resolution == 12)
 			dataPoint = (dataPoint >> 4) & 0xfff;
@@ -457,9 +456,8 @@
 	int board;
 
 	printk("comedi%d: das800: io 0x%lx", dev->minor, iobase);
-	if (irq) {
+	if (irq)
 		printk(", irq %u", irq);
-	}
 	printk("\n");
 
 	/* allocate and initialize dev->private */
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 9db9a46..d5cbd51 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -1048,11 +1048,10 @@
 	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
 
 	/* if output clear the bit, otherwise set it */
-	if (data[0] == COMEDI_OUTPUT) {
+	if (data[0] == COMEDI_OUTPUT)
 		devpriv->dio_config &= ~chanbit;
-	} else {
+	else
 		devpriv->dio_config |= chanbit;
-	}
 	/* get access to the DIO regs */
 	dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC);
 	/* set the DIO's to the new configuration setting */
diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
index 7b9af5d..3f365ae 100644
--- a/drivers/staging/comedi/drivers/dt2801.c
+++ b/drivers/staging/comedi/drivers/dt2801.c
@@ -18,10 +18,10 @@
   [1] - unused
   [2] - A/D reference 0=differential, 1=single-ended
   [3] - A/D range
-          0 = [-10,10]
+	  0 = [-10, 10]
 	  1 = [0,10]
   [4] - D/A 0 range
-          0 = [-10,10]
+	  0 = [-10, 10]
 	  1 = [-5,5]
 	  2 = [-2.5,2.5]
 	  3 = [0,10]
@@ -279,9 +279,8 @@
 
 	do {
 		stat = inb_p(dev->iobase + DT2801_STATUS);
-		if (stat & (DT_S_COMPOSITE_ERROR | DT_S_READY)) {
+		if (stat & (DT_S_COMPOSITE_ERROR | DT_S_READY))
 			return stat;
-		}
 		if (stat & DT_S_DATA_OUT_READY) {
 			*data = inb_p(dev->iobase + DT2801_DATA);
 			return 0;
@@ -315,9 +314,8 @@
 	do {
 		stat = inb_p(dev->iobase + DT2801_STATUS);
 
-		if (stat & DT_S_COMPOSITE_ERROR) {
+		if (stat & DT_S_COMPOSITE_ERROR)
 			return stat;
-		}
 		if (!(stat & DT_S_DATA_IN_FULL)) {
 			outb_p(data & 0xff, dev->iobase + DT2801_DATA);
 			return 0;
@@ -354,18 +352,15 @@
 	int stat;
 
 	stat = inb_p(dev->iobase + DT2801_STATUS);
-	if (stat & DT_S_READY) {
+	if (stat & DT_S_READY)
 		return 0;
-	}
 	do {
 		stat = inb_p(dev->iobase + DT2801_STATUS);
 
-		if (stat & DT_S_COMPOSITE_ERROR) {
+		if (stat & DT_S_COMPOSITE_ERROR)
 			return stat;
-		}
-		if (stat & DT_S_READY) {
+		if (stat & DT_S_READY)
 			return 0;
-		}
 	} while (--timeout > 0);
 
 	return -ETIME;
@@ -382,9 +377,8 @@
 		printk
 		    ("dt2801: composite-error in dt2801_writecmd(), ignoring\n");
 	}
-	if (!(stat & DT_S_READY)) {
+	if (!(stat & DT_S_READY))
 		printk("dt2801: !ready in dt2801_writecmd(), ignoring\n");
-	}
 	outb_p(command, dev->iobase + DT2801_CMD);
 
 	return 0;
@@ -418,9 +412,8 @@
 		if (stat & DT_S_READY)
 			break;
 	} while (timeout--);
-	if (!timeout) {
+	if (!timeout)
 		printk("dt2801: timeout 1 status=0x%02x\n", stat);
-	}
 
 	/* printk("dt2801: reading dummy\n"); */
 	/* dt2801_readdata(dev,&board_code); */
@@ -436,9 +429,8 @@
 		if (stat & DT_S_READY)
 			break;
 	} while (timeout--);
-	if (!timeout) {
+	if (!timeout)
 		printk("dt2801: timeout 2 status=0x%02x\n", stat);
-	}
 
 	DPRINTK("dt2801: reading code\n");
 	dt2801_readdata(dev, &board_code);
@@ -623,11 +615,10 @@
 static int dt2801_error(struct comedi_device *dev, int stat)
 {
 	if (stat < 0) {
-		if (stat == -ETIME) {
+		if (stat == -ETIME)
 			printk("dt2801: timeout\n");
-		} else {
+		else
 			printk("dt2801: error %d\n", stat);
-		}
 		return stat;
 	}
 	printk("dt2801: error status 0x%02x, resetting...\n", stat);
diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
index d1db93c..d1a4f78 100644
--- a/drivers/staging/comedi/drivers/dt2815.c
+++ b/drivers/staging/comedi/drivers/dt2815.c
@@ -34,19 +34,19 @@
   [0] - I/O port base base address
   [1] - IRQ (unused)
   [2] - Voltage unipolar/bipolar configuration
-          0 == unipolar 5V  (0V -- +5V)
-	  1 == bipolar 5V  (-5V -- +5V)
+	0 == unipolar 5V  (0V -- +5V)
+	1 == bipolar 5V  (-5V -- +5V)
   [3] - Current offset configuration
-          0 == disabled  (0mA -- +32mAV)
-          1 == enabled  (+4mA -- +20mAV)
+	0 == disabled  (0mA -- +32mAV)
+	1 == enabled  (+4mA -- +20mAV)
   [4] - Firmware program configuration
-          0 == program 1 (see manual table 5-4)
-          1 == program 2 (see manual table 5-4)
-          2 == program 3 (see manual table 5-4)
-          3 == program 4 (see manual table 5-4)
+	0 == program 1 (see manual table 5-4)
+	1 == program 2 (see manual table 5-4)
+	2 == program 3 (see manual table 5-4)
+	3 == program 4 (see manual table 5-4)
   [5] - Analog output 0 range configuration
-          0 == voltage
-          1 == current
+	0 == voltage
+	1 == current
   [6] - Analog output 1 range configuration (same options)
   [7] - Analog output 2 range configuration (same options)
   [8] - Analog output 3 range configuration (same options)
@@ -61,17 +61,11 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 
-static const struct comedi_lrange range_dt2815_ao_32_current = { 1, {
-								     RANGE_mA(0,
-									      32)
-								     }
-};
+static const struct comedi_lrange
+	range_dt2815_ao_32_current = {1, {RANGE_mA(0, 32)} };
 
-static const struct comedi_lrange range_dt2815_ao_20_current = { 1, {
-								     RANGE_mA(4,
-									      20)
-								     }
-};
+static const struct comedi_lrange
+	range_dt2815_ao_20_current = {1, {RANGE_mA(4, 20)} };
 
 #define DT2815_SIZE 2
 
@@ -118,9 +112,8 @@
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
-	for (i = 0; i < insn->n; i++) {
+	for (i = 0; i < insn->n; i++)
 		data[i] = devpriv->ao_readback[chan];
-	}
 
 	return i;
 }
@@ -139,9 +132,8 @@
 
 		status = dt2815_wait_for_status(dev, 0x00);
 		if (status != 0) {
-			printk
-			    ("dt2815: failed to write low byte on %d reason %x\n",
-			     chan, status);
+			printk(KERN_WARNING "dt2815: failed to write low byte "
+			       "on %d reason %x\n", chan, status);
 			return -EBUSY;
 		}
 
@@ -149,9 +141,8 @@
 
 		status = dt2815_wait_for_status(dev, 0x10);
 		if (status != 0x10) {
-			printk
-			    ("dt2815: failed to write high byte on %d reason %x\n",
-			     chan, status);
+			printk(KERN_WARNING "dt2815: failed to write high byte "
+			       "on %d reason %x\n", chan, status);
 			return -EBUSY;
 		}
 		devpriv->ao_readback[chan] = data[i];
@@ -163,24 +154,24 @@
   options[0]   Board base address
   options[1]   IRQ (not applicable)
   options[2]   Voltage unipolar/bipolar configuration
-                 0 == unipolar 5V  (0V -- +5V)
-		 1 == bipolar 5V  (-5V -- +5V)
+		0 == unipolar 5V  (0V -- +5V)
+		1 == bipolar 5V  (-5V -- +5V)
   options[3]   Current offset configuration
-                 0 == disabled  (0mA -- +32mAV)
-                 1 == enabled  (+4mA -- +20mAV)
+		0 == disabled  (0mA -- +32mAV)
+		1 == enabled  (+4mA -- +20mAV)
   options[4]   Firmware program configuration
-                 0 == program 1 (see manual table 5-4)
-                 1 == program 2 (see manual table 5-4)
-                 2 == program 3 (see manual table 5-4)
-                 3 == program 4 (see manual table 5-4)
+		0 == program 1 (see manual table 5-4)
+		1 == program 2 (see manual table 5-4)
+		2 == program 3 (see manual table 5-4)
+		3 == program 4 (see manual table 5-4)
   options[5]   Analog output 0 range configuration
-                 0 == voltage
-                 1 == current
+		0 == voltage
+		1 == current
   options[6]   Analog output 1 range configuration
   ...
   options[12]   Analog output 7 range configuration
-                 0 == voltage
-                 1 == current
+		0 == voltage
+		1 == current
  */
 
 static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
@@ -191,9 +182,9 @@
 	unsigned long iobase;
 
 	iobase = it->options[0];
-	printk("comedi%d: dt2815: 0x%04lx ", dev->minor, iobase);
+	printk(KERN_INFO "comedi%d: dt2815: 0x%04lx ", dev->minor, iobase);
 	if (!request_region(iobase, DT2815_SIZE, "dt2815")) {
-		printk("I/O port conflict\n");
+		printk(KERN_WARNING "I/O port conflict\n");
 		return -EIO;
 	}
 
@@ -236,19 +227,17 @@
 			unsigned int program;
 			program = (it->options[4] & 0x3) << 3 | 0x7;
 			outb(program, dev->iobase + DT2815_DATA);
-			printk(", program: 0x%x (@t=%d)\n", program, i);
+			printk(KERN_INFO ", program: 0x%x (@t=%d)\n",
+			       program, i);
 			break;
 		} else if (status != 0x00) {
-			printk("dt2815: unexpected status 0x%x (@t=%d)\n",
-			       status, i);
-			if (status & 0x60) {
+			printk(KERN_WARNING "dt2815: unexpected status 0x%x "
+			       "(@t=%d)\n", status, i);
+			if (status & 0x60)
 				outb(0x00, dev->iobase + DT2815_STATUS);
-			}
 		}
 	}
 
-	printk("\n");
-
 	return 0;
 }
 
@@ -260,7 +249,7 @@
 
 static int dt2815_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: dt2815: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: dt2815: remove\n", dev->minor);
 
 	dt2815_free_resources(dev);
 
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index 312f4f2..96caae3 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -264,7 +264,7 @@
 
 static DECLARE_MUTEX(dt9812_mutex);
 
-static struct usb_device_id dt9812_table[] = {
+static const struct usb_device_id dt9812_table[] = {
 	{USB_DEVICE(0x0867, 0x9812)},
 	{}			/* Terminating entry */
 };
diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
index 8fca180..a10a2b0 100644
--- a/drivers/staging/comedi/drivers/fl512.c
+++ b/drivers/staging/comedi/drivers/fl512.c
@@ -76,14 +76,14 @@
 	unsigned long iobase = dev->iobase;
 
 	for (n = 0; n < insn->n; n++) {	/* sample n times on selected channel */
-		/* XXX probably can move next step out of for() loop -- will make
-		 * AI a little bit faster. */
+		/* XXX probably can move next step out of for() loop -- will
+		 * make AI a little bit faster. */
 		outb(chan, iobase + 2);	/* select chan */
 		outb(0, iobase + 3);	/* start conversion */
 		/* XXX should test "done" flag instead of delay */
 		udelay(30);	/* sleep 30 usec */
 		lo_byte = inb(iobase + 2);	/* low 8 byte */
-		hi_byte = inb(iobase + 3) & 0xf;	/* high 4 bit and mask */
+		hi_byte = inb(iobase + 3) & 0xf; /* high 4 bit and mask */
 		data[n] = lo_byte + (hi_byte << 8);
 	}
 	return n;
@@ -101,8 +101,10 @@
 	unsigned long iobase = dev->iobase;	/* get base address  */
 
 	for (n = 0; n < insn->n; n++) {	/* write n data set */
-		outb(data[n] & 0x0ff, iobase + 4 + 2 * chan);	/* write low byte   */
-		outb((data[n] & 0xf00) >> 8, iobase + 4 + 2 * chan);	/* write high byte  */
+		/* write low byte   */
+		outb(data[n] & 0x0ff, iobase + 4 + 2 * chan);
+		/* write high byte  */
+		outb((data[n] & 0xf00) >> 8, iobase + 4 + 2 * chan);
 		inb(iobase + 4 + 2 * chan);	/* trig */
 
 		devpriv->ao_readback[chan] = data[n];
@@ -121,9 +123,8 @@
 	int n;
 	int chan = CR_CHAN(insn->chanspec);
 
-	for (n = 0; n < insn->n; n++) {
+	for (n = 0; n < insn->n; n++)
 		data[n] = devpriv->ao_readback[chan];
-	}
 
 	return n;
 }
@@ -134,13 +135,15 @@
 static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	unsigned long iobase;
-	struct comedi_subdevice *s;	/* pointer to the subdevice:
-					   Analog in, Analog out, ( not made ->and Digital IO) */
+
+	/* pointer to the subdevice: Analog in, Analog out,
+	   (not made ->and Digital IO) */
+	struct comedi_subdevice *s;
 
 	iobase = it->options[0];
-	printk("comedi:%d fl512: 0x%04lx", dev->minor, iobase);
+	printk(KERN_INFO "comedi:%d fl512: 0x%04lx", dev->minor, iobase);
 	if (!request_region(iobase, FL512_SIZE, "fl512")) {
-		printk(" I/O port conflict\n");
+		printk(KERN_WARNING " I/O port conflict\n");
 		return -EIO;
 	}
 	dev->iobase = iobase;
@@ -149,7 +152,7 @@
 		return -ENOMEM;
 
 #if DEBUG
-	printk("malloc ok\n");
+	printk(KERN_DEBUG "malloc ok\n");
 #endif
 
 	if (alloc_subdevices(dev, 2) < 0)
@@ -160,24 +163,37 @@
 	 */
 	/* Analog indput */
 	s = dev->subdevices + 0;
-	s->type = COMEDI_SUBD_AI;	/* define subdevice as Analog In   */
-	s->subdev_flags = SDF_READABLE | SDF_GROUND;	/* you can read it from userspace  */
-	s->n_chan = 16;		/* Number of Analog input channels */
-	s->maxdata = 0x0fff;	/* accept only 12 bits of data     */
-	s->range_table = &range_fl512;	/* device use one of the ranges    */
-	s->insn_read = fl512_ai_insn;	/* function to call when read AD   */
-	printk("comedi: fl512: subdevice 0 initialized\n");
+	/* define subdevice as Analog In */
+	s->type = COMEDI_SUBD_AI;
+	/* you can read it from userspace */
+	s->subdev_flags = SDF_READABLE | SDF_GROUND;
+	/* Number of Analog input channels */
+	s->n_chan = 16;
+	/* accept only 12 bits of data */
+	s->maxdata = 0x0fff;
+	/* device use one of the ranges */
+	s->range_table = &range_fl512;
+	/* function to call when read AD */
+	s->insn_read = fl512_ai_insn;
+	printk(KERN_INFO "comedi: fl512: subdevice 0 initialized\n");
 
 	/* Analog output */
 	s = dev->subdevices + 1;
-	s->type = COMEDI_SUBD_AO;	/* define subdevice as Analog OUT   */
-	s->subdev_flags = SDF_WRITABLE;	/* you can write it from userspace  */
-	s->n_chan = 2;		/* Number of Analog output channels */
-	s->maxdata = 0x0fff;	/* accept only 12 bits of data      */
-	s->range_table = &range_fl512;	/* device use one of the ranges     */
-	s->insn_write = fl512_ao_insn;	/* function to call when write DA   */
-	s->insn_read = fl512_ao_insn_readback;	/* function to call when reading DA   */
-	printk("comedi: fl512: subdevice 1 initialized\n");
+	/* define subdevice as Analog OUT */
+	s->type = COMEDI_SUBD_AO;
+	/* you can write it from userspace */
+	s->subdev_flags = SDF_WRITABLE;
+	/* Number of Analog output channels */
+	s->n_chan = 2;
+	/* accept only 12 bits of data */
+	s->maxdata = 0x0fff;
+	/* device use one of the ranges */
+	s->range_table = &range_fl512;
+	/* function to call when write DA */
+	s->insn_write = fl512_ao_insn;
+	/* function to call when reading DA */
+	s->insn_read = fl512_ao_insn_readback;
+	printk(KERN_INFO "comedi: fl512: subdevice 1 initialized\n");
 
 	return 1;
 }
@@ -186,6 +202,6 @@
 {
 	if (dev->iobase)
 		release_region(dev->iobase, FL512_SIZE);
-	printk("comedi%d: fl512: dummy i detach\n", dev->minor);
+	printk(KERN_INFO "comedi%d: fl512: dummy i detach\n", dev->minor);
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index bd39784..fe5b4953 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -954,6 +954,8 @@
 	return result;
 }
 
+MODULE_FIRMWARE("comedi/jr3pci.idm");
+
 static int jr3_pci_detach(struct comedi_device *dev)
 {
 	int i;
diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
index cb4da2a..12e72c8 100644
--- a/drivers/staging/comedi/drivers/mpc624.c
+++ b/drivers/staging/comedi/drivers/mpc624.c
@@ -284,7 +284,7 @@
 	outb(insn->chanspec, dev->iobase + MPC624_GNMUXCH);
 /* printk("Channel %d: \n", insn->chanspec); */
 	if (!insn->n) {
-		printk("MPC624: Warning, no data to aquire\n");
+		printk("MPC624: Warning, no data to acquire\n");
 		return 0;
 	}
 
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index bbf75eb..c223f76 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -26,12 +26,13 @@
 /*
 Driver: ni_65xx
 Description: National Instruments 65xx static dio boards
-Author: Jon Grierson <jd@renko.co.uk>, Frank Mori Hess <fmhess@users.sourceforge.net>
+Author: Jon Grierson <jd@renko.co.uk>,
+	Frank Mori Hess <fmhess@users.sourceforge.net>
 Status: testing
-Devices: [National Instruments] PCI-6509 (ni_65xx), PXI-6509, PCI-6510, PCI-6511,
-  PXI-6511, PCI-6512, PXI-6512, PCI-6513, PXI-6513, PCI-6514, PXI-6514, PCI-6515,
-  PXI-6515, PCI-6516, PCI-6517, PCI-6518, PCI-6519, PCI-6520, PCI-6521, PXI-6521,
-  PCI-6528, PXI-6528
+Devices: [National Instruments] PCI-6509 (ni_65xx), PXI-6509, PCI-6510,
+  PCI-6511, PXI-6511, PCI-6512, PXI-6512, PCI-6513, PXI-6513, PCI-6514,
+  PXI-6514, PCI-6515, PXI-6515, PCI-6516, PCI-6517, PCI-6518, PCI-6519,
+  PCI-6520, PCI-6521, PXI-6521, PCI-6528, PXI-6528
 Updated: Wed Oct 18 08:59:11 EDT 2006
 
 Based on the PCI-6527 driver by ds.
@@ -418,9 +419,10 @@
 		return -EINVAL;
 	base_bitfield_channel = CR_CHAN(insn->chanspec);
 	for (j = 0; j < max_ports_per_bitfield; ++j) {
-		const unsigned port_offset = ni_65xx_port_by_channel(base_bitfield_channel) + j;
+		const unsigned port_offset =
+			ni_65xx_port_by_channel(base_bitfield_channel) + j;
 		const unsigned port =
-		    sprivate(s)->base_port + port_offset;
+			sprivate(s)->base_port + port_offset;
 		unsigned base_port_channel;
 		unsigned port_mask, port_data, port_read_bits;
 		int bitshift;
@@ -463,11 +465,11 @@
 			 * subdevice.) */
 			port_read_bits ^= 0xFF;
 		}
-		if (bitshift > 0) {
+		if (bitshift > 0)
 			port_read_bits <<= bitshift;
-		} else {
+		else
 			port_read_bits >>= -bitshift;
-		}
+
 		read_bits |= port_read_bits;
 	}
 	data[1] = read_bits;
@@ -532,7 +534,8 @@
 	if (err)
 		return 1;
 
-	/* step 2: make sure trigger sources are unique and mutually compatible */
+	/* step 2: make sure trigger sources are unique and mutually
+	compatible */
 
 	if (err)
 		return 2;
@@ -652,7 +655,7 @@
 	unsigned i;
 	int ret;
 
-	printk("comedi%d: ni_65xx:", dev->minor);
+	printk(KERN_INFO "comedi%d: ni_65xx:", dev->minor);
 
 	ret = alloc_private(dev, sizeof(struct ni_65xx_private));
 	if (ret < 0)
@@ -664,15 +667,15 @@
 
 	ret = mite_setup(private(dev)->mite);
 	if (ret < 0) {
-		printk("error setting up mite\n");
+		printk(KERN_WARNING "error setting up mite\n");
 		return ret;
 	}
 
 	dev->board_name = board(dev)->name;
 	dev->irq = mite_irq(private(dev)->mite);
-	printk(" %s", dev->board_name);
+	printk(KERN_INFO " %s", dev->board_name);
 
-	printk(" ID=0x%02x",
+	printk(KERN_INFO " ID=0x%02x",
 	       readb(private(dev)->mite->daq_io_addr + ID_Register));
 
 	ret = alloc_subdevices(dev, 4);
@@ -773,7 +776,7 @@
 			  "ni_65xx", dev);
 	if (ret < 0) {
 		dev->irq = 0;
-		printk(" irq not available");
+		printk(KERN_WARNING " irq not available");
 	}
 
 	printk("\n");
@@ -790,21 +793,17 @@
 		       Master_Interrupt_Control);
 	}
 
-	if (dev->irq) {
+	if (dev->irq)
 		free_irq(dev->irq, dev);
-	}
 
 	if (private(dev)) {
 		unsigned i;
 		for (i = 0; i < dev->n_subdevices; ++i) {
-			if (dev->subdevices[i].private) {
-				kfree(dev->subdevices[i].private);
-				dev->subdevices[i].private = NULL;
-			}
+			kfree(dev->subdevices[i].private);
+			dev->subdevices[i].private = NULL;
 		}
-		if (private(dev)->mite) {
+		if (private(dev)->mite)
 			mite_unsetup(private(dev)->mite);
-		}
 	}
 	return 0;
 }
@@ -830,7 +829,7 @@
 			}
 		}
 	}
-	printk("no device found\n");
+	printk(KERN_WARNING "no device found\n");
 	mite_list_devices();
 	return -EIO;
 }
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index 404d3c5..017630f 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -52,7 +52,8 @@
 };
 
 #define NUM_PFI_CHANNELS 40
-/* really there are only up to 3 dma channels, but the register layout allows for 4 */
+/* really there are only up to 3 dma channels, but the register layout allows
+for 4 */
 #define MAX_DMA_CHANNEL 4
 
 /* See Register-Level Programmer Manual page 3.1 */
@@ -198,7 +199,7 @@
 	const char *name;	/*  Register Name */
 	int offset;		/*  Offset from base address from GPCT chip */
 	enum ni_660x_register_direction direction;
-	enum ni_660x_register_width size;	/*  1 byte, 2 bytes, or 4 bytes */
+	enum ni_660x_register_width size; /* 1 byte, 2 bytes, or 4 bytes */
 };
 
 static const struct NI_660xRegisterData registerData[NumRegisters] = {
@@ -382,8 +383,8 @@
 };
 
 /* Offset of the GPCT chips from the base-adress of the card */
-static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 };	/* First chip is at base-address +
-							   0x00, etc. */
+/* First chip is at base-address + 0x00, etc. */
+static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 };
 
 /* Board description*/
 struct ni_660x_board {
@@ -691,13 +692,13 @@
 		ni_660x_register = G0StatusRegister;
 		break;
 	case NITIO_G1_Status_Reg:
-		ni_660x_register = G0StatusRegister;
+		ni_660x_register = G1StatusRegister;
 		break;
 	case NITIO_G2_Status_Reg:
-		ni_660x_register = G0StatusRegister;
+		ni_660x_register = G2StatusRegister;
 		break;
 	case NITIO_G3_Status_Reg:
-		ni_660x_register = G0StatusRegister;
+		ni_660x_register = G3StatusRegister;
 		break;
 	case NITIO_G0_Interrupt_Enable_Reg:
 		ni_660x_register = G0InterruptEnable;
@@ -712,7 +713,7 @@
 		ni_660x_register = G3InterruptEnable;
 		break;
 	default:
-		printk("%s: unhandled register 0x%x in switch.\n",
+		printk(KERN_WARNING "%s: unhandled register 0x%x in switch.\n",
 		       __func__, reg);
 		BUG();
 		return 0;
@@ -737,7 +738,7 @@
 		writel(bits, write_address);
 		break;
 	default:
-		printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
+		printk(KERN_WARNING "%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
 		       __FILE__, __func__, reg);
 		BUG();
 		break;
@@ -760,7 +761,7 @@
 		return readl(read_address);
 		break;
 	default:
-		printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
+		printk(KERN_WARNING "%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
 		       __FILE__, __func__, reg);
 		BUG();
 		break;
@@ -993,9 +994,9 @@
 	spin_lock_init(&private(dev)->mite_channel_lock);
 	spin_lock_init(&private(dev)->interrupt_lock);
 	spin_lock_init(&private(dev)->soft_reg_copy_lock);
-	for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
+	for (i = 0; i < NUM_PFI_CHANNELS; ++i)
 		private(dev)->pfi_output_selects[i] = pfi_output_select_counter;
-	}
+
 	return 0;
 }
 
@@ -1008,9 +1009,8 @@
 		for (j = 0; j < counters_per_chip; ++j) {
 			private(dev)->mite_rings[i][j] =
 			    mite_alloc_ring(private(dev)->mite);
-			if (private(dev)->mite_rings[i][j] == NULL) {
+			if (private(dev)->mite_rings[i][j] == NULL)
 				return -ENOMEM;
-			}
 		}
 	}
 	return 0;
@@ -1022,9 +1022,8 @@
 	unsigned j;
 
 	for (i = 0; i < board(dev)->n_chips; ++i) {
-		for (j = 0; j < counters_per_chip; ++j) {
+		for (j = 0; j < counters_per_chip; ++j)
 			mite_free_ring(private(dev)->mite_rings[i][j]);
-		}
 	}
 }
 
@@ -1036,7 +1035,7 @@
 	unsigned i;
 	unsigned global_interrupt_config_bits;
 
-	printk("comedi%d: ni_660x: ", dev->minor);
+	printk(KERN_INFO "comedi%d: ni_660x: ", dev->minor);
 
 	ret = ni_660x_allocate_private(dev);
 	if (ret < 0)
@@ -1049,7 +1048,7 @@
 
 	ret = mite_setup2(private(dev)->mite, 1);
 	if (ret < 0) {
-		printk("error setting up mite\n");
+		printk(KERN_WARNING "error setting up mite\n");
 		return ret;
 	}
 	comedi_set_hw_dev(dev, &private(dev)->mite->pcidev->dev);
@@ -1057,7 +1056,7 @@
 	if (ret < 0)
 		return ret;
 
-	printk(" %s ", dev->board_name);
+	printk(KERN_INFO " %s ", dev->board_name);
 
 	dev->n_subdevices = 2 + NI_660X_MAX_NUM_COUNTERS;
 
@@ -1078,15 +1077,16 @@
 	s->insn_bits = ni_660x_dio_insn_bits;
 	s->insn_config = ni_660x_dio_insn_config;
 	s->io_bits = 0;		/* all bits default to input */
-	/*  we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg */
+	/*  we use the ioconfig registers to control dio direction, so zero
+	output enables in stc dio control reg */
 	ni_660x_write_register(dev, 0, 0, STCDIOControl);
 
 	private(dev)->counter_dev = ni_gpct_device_construct(dev,
-							     &ni_gpct_write_register,
-							     &ni_gpct_read_register,
-							     ni_gpct_variant_660x,
-							     ni_660x_num_counters
-							     (dev));
+						     &ni_gpct_write_register,
+						     &ni_gpct_read_register,
+						     ni_gpct_variant_660x,
+						     ni_660x_num_counters
+						     (dev));
 	if (private(dev)->counter_dev == NULL)
 		return -ENOMEM;
 	for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) {
@@ -1118,12 +1118,12 @@
 			s->type = COMEDI_SUBD_UNUSED;
 		}
 	}
-	for (i = 0; i < board(dev)->n_chips; ++i) {
+	for (i = 0; i < board(dev)->n_chips; ++i)
 		init_tio_chip(dev, i);
-	}
-	for (i = 0; i < ni_660x_num_counters(dev); ++i) {
+
+	for (i = 0; i < ni_660x_num_counters(dev); ++i)
 		ni_tio_init_counter(&private(dev)->counter_dev->counters[i]);
-	}
+
 	for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
 		if (i < min_counter_pfi_chan)
 			ni_660x_set_pfi_routing(dev, i, pfi_output_select_do);
@@ -1134,13 +1134,13 @@
 	}
 	/* to be safe, set counterswap bits on tio chips after all the counter
 	   outputs have been set to high impedance mode */
-	for (i = 0; i < board(dev)->n_chips; ++i) {
+	for (i = 0; i < board(dev)->n_chips; ++i)
 		set_tio_counterswap(dev, i);
-	}
+
 	ret = request_irq(mite_irq(private(dev)->mite), ni_660x_interrupt,
 			  IRQF_SHARED, "ni_660x", dev);
 	if (ret < 0) {
-		printk(" irq not available\n");
+		printk(KERN_WARNING " irq not available\n");
 		return ret;
 	}
 	dev->irq = mite_irq(private(dev)->mite);
@@ -1149,13 +1149,13 @@
 		global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
 	ni_660x_write_register(dev, 0, global_interrupt_config_bits,
 			       GlobalInterruptConfigRegister);
-	printk("attached\n");
+	printk(KERN_INFO "attached\n");
 	return 0;
 }
 
 static int ni_660x_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: ni_660x: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: ni_660x: remove\n", dev->minor);
 
 	/* Free irq */
 	if (dev->irq)
@@ -1193,9 +1193,8 @@
 			       private(dev)->
 			       dma_configuration_soft_copies[chipset],
 			       DMAConfigRegister);
-	for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
+	for (i = 0; i < NUM_PFI_CHANNELS; ++i)
 		ni_660x_write_register(dev, chipset, 0, IOConfigReg(i));
-	}
 }
 
 static int
@@ -1234,7 +1233,7 @@
 			}
 		}
 	}
-	printk("no device found\n");
+	printk(KERN_WARNING "no device found\n");
 	mite_list_devices();
 	return -EIO;
 }
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index 9b43547..1e792d5 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -93,7 +93,7 @@
 	{
 	PCI_VENDOR_ID_NATINST, 0x2c90, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 	PCI_VENDOR_ID_NATINST, 0x1920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	    /* { PCI_VENDOR_ID_NATINST, 0x0000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
+	/*{ PCI_VENDOR_ID_NATINST, 0x0000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },*/
 	{
 	0}
 };
@@ -151,7 +151,7 @@
 	int ret;
 	int i;
 
-	printk("comedi%d: ni_670x: ", dev->minor);
+	printk(KERN_INFO "comedi%d: ni_670x: ", dev->minor);
 
 	ret = alloc_private(dev, sizeof(struct ni_670x_private));
 	if (ret < 0)
@@ -163,12 +163,12 @@
 
 	ret = mite_setup(devpriv->mite);
 	if (ret < 0) {
-		printk("error setting up mite\n");
+		printk(KERN_WARNING "error setting up mite\n");
 		return ret;
 	}
 	dev->board_name = thisboard->name;
 	dev->irq = mite_irq(devpriv->mite);
-	printk(" %s", dev->board_name);
+	printk(KERN_INFO " %s", dev->board_name);
 
 	if (alloc_subdevices(dev, 2) < 0)
 		return -ENOMEM;
@@ -207,21 +207,22 @@
 	s->insn_bits = ni_670x_dio_insn_bits;
 	s->insn_config = ni_670x_dio_insn_config;
 
-	writel(0x10, devpriv->mite->daq_io_addr + MISC_CONTROL_OFFSET);	/* Config of misc registers */
-	writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET);	/* Config of ao registers */
+	/* Config of misc registers */
+	writel(0x10, devpriv->mite->daq_io_addr + MISC_CONTROL_OFFSET);
+	/* Config of ao registers */
+	writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET);
 
-	printk("attached\n");
+	printk(KERN_INFO "attached\n");
 
 	return 1;
 }
 
 static int ni_670x_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: ni_670x: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: ni_670x: remove\n", dev->minor);
 
-	if (dev->subdevices[0].range_table_list) {
-		kfree(dev->subdevices[0].range_table_list);
-	}
+	kfree(dev->subdevices[0].range_table_list);
+
 	if (dev->private && devpriv->mite)
 		mite_unsetup(devpriv->mite);
 
@@ -250,8 +251,11 @@
 	   vch(15)      :       30      | ich(31)       :       31      */
 
 	for (i = 0; i < insn->n; i++) {
-		writel(((chan & 15) << 1) | ((chan & 16) >> 4), devpriv->mite->daq_io_addr + AO_CHAN_OFFSET);	/* First write in channel register which channel to use */
-		writel(data[i], devpriv->mite->daq_io_addr + AO_VALUE_OFFSET);	/* write channel value */
+		/* First write in channel register which channel to use */
+		writel(((chan & 15) << 1) | ((chan & 16) >> 4),
+		       devpriv->mite->daq_io_addr + AO_CHAN_OFFSET);
+		/* write channel value */
+		writel(data[i], devpriv->mite->daq_io_addr + AO_VALUE_OFFSET);
 		devpriv->ao_readback[chan] = data[i];
 	}
 
@@ -344,7 +348,7 @@
 			}
 		}
 	}
-	printk("no device found\n");
+	printk(KERN_INFO "no device found\n");
 	mite_list_devices();
 	return -EIO;
 }
diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
index 8ead311..003d00b 100644
--- a/drivers/staging/comedi/drivers/ni_atmio.c
+++ b/drivers/staging/comedi/drivers/ni_atmio.c
@@ -329,11 +329,11 @@
 }
 
 static struct pnp_device_id device_ids[] = {
-	{.id = "NIC1900",.driver_data = 0},
-	{.id = "NIC2400",.driver_data = 0},
-	{.id = "NIC2500",.driver_data = 0},
-	{.id = "NIC2600",.driver_data = 0},
-	{.id = "NIC2700",.driver_data = 0},
+	{.id = "NIC1900", .driver_data = 0},
+	{.id = "NIC2400", .driver_data = 0},
+	{.id = "NIC2500", .driver_data = 0},
+	{.id = "NIC2600", .driver_data = 0},
+	{.id = "NIC2700", .driver_data = 0},
 	{.id = ""}
 };
 
@@ -362,9 +362,9 @@
 
 	if (dev->iobase)
 		release_region(dev->iobase, NI_SIZE);
-	if (dev->irq) {
+	if (dev->irq)
 		free_irq(dev->irq, dev);
-	}
+
 	if (devpriv->isapnp_dev)
 		pnp_device_detach(devpriv->isapnp_dev);
 
@@ -387,8 +387,8 @@
 
 		if (pnp_device_attach(isapnp_dev) < 0) {
 			printk
-			    ("ni_atmio: %s found but already active, skipping.\n",
-			     ni_boards[i].name);
+			 ("ni_atmio: %s found but already active, skipping.\n",
+			  ni_boards[i].name);
 			continue;
 		}
 		if (pnp_activate_dev(isapnp_dev) < 0) {
@@ -496,9 +496,9 @@
 	/* generic E series stuff in ni_mio_common.c */
 
 	ret = ni_E_init(dev, it);
-	if (ret < 0) {
+	if (ret < 0)
 		return ret;
-	}
+
 
 	return 0;
 }
@@ -509,16 +509,16 @@
 	int i;
 
 	for (i = 0; i < n_ni_boards; i++) {
-		if (ni_boards[i].device_id == device_id) {
+		if (ni_boards[i].device_id == device_id)
 			return i;
-		}
+
 	}
-	if (device_id == 255) {
+	if (device_id == 255)
 		printk(" can't find board\n");
-	} else if (device_id == 0) {
+	 else if (device_id == 0)
 		printk(" EEPROM read error (?) or device not found\n");
-	} else {
+	 else
 		printk(" unknown device ID %d -- contact author\n", device_id);
-	}
+
 	return -1;
 }
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index ef5e118..c9b0395 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -76,13 +76,15 @@
 static const struct dio700_board dio700_boards[] = {
 	{
 	 .name = "daqcard-700",
-	 .device_id = 0x4743,	/*  0x10b is manufacturer id, 0x4743 is device id */
+	  /*  0x10b is manufacturer id, 0x4743 is device id */
+	 .device_id = 0x4743,
 	 .bustype = pcmcia_bustype,
 	 .have_dio = 1,
 	 },
 	{
 	 .name = "ni_daq_700",
-	 .device_id = 0x4743,	/*  0x10b is manufacturer id, 0x4743 is device id */
+	  /*  0x10b is manufacturer id, 0x4743 is device id */
+	 .device_id = 0x4743,
 	 .bustype = pcmcia_bustype,
 	 .have_dio = 1,
 	 },
@@ -309,11 +311,11 @@
 		return -ENOMEM;
 
 	CALLBACK_ARG = arg;
-	if (cb == NULL) {
+	if (cb == NULL)
 		CALLBACK_FUNC = subdev_700_cb;
-	} else {
+	 else
 		CALLBACK_FUNC = cb;
-	}
+
 	s->insn_bits = subdev_700_insn;
 	s->insn_config = subdev_700_insn_config;
 
@@ -345,12 +347,10 @@
 
 void subdev_700_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	if (s->private) {
-		if (subdevpriv->have_irq) {
-		}
+	if (s->private)
+		if (subdevpriv->have_irq)
 
-		kfree(s->private);
-	}
+			kfree(s->private);
 }
 
 EXPORT_SYMBOL(subdev_700_init);
@@ -390,9 +390,9 @@
 	printk("comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
 	       thisboard->name, iobase);
 #ifdef incomplete
-	if (irq) {
+	if (irq)
 		printk(", irq %u", irq);
-	}
+
 #endif
 
 	printk("\n");
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index dc3f398..3c88caa 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -90,8 +90,10 @@
 
 #define DRV_NAME "ni_labpc"
 
-#define LABPC_SIZE           32	/*  size of io region used by board */
-#define LABPC_TIMER_BASE            500	/*  2 MHz master clock */
+/* size of io region used by board */
+#define LABPC_SIZE           32
+/* 2 MHz master clock */
+#define LABPC_TIMER_BASE            500
 
 /* Registers for the lab-pc+ */
 
@@ -99,69 +101,110 @@
 #define COMMAND1_REG	0x0
 #define   ADC_GAIN_MASK	(0x7 << 4)
 #define   ADC_CHAN_BITS(x)	((x) & 0x7)
-#define   ADC_SCAN_EN_BIT	0x80	/*  enables multi channel scans */
+/* enables multi channel scans */
+#define   ADC_SCAN_EN_BIT	0x80
 #define COMMAND2_REG	0x1
-#define   PRETRIG_BIT	0x1	/*  enable pretriggering (used in conjunction with SWTRIG) */
-#define   HWTRIG_BIT	0x2	/*  enable paced conversions on external trigger */
-#define   SWTRIG_BIT	0x4	/*  enable paced conversions */
-#define   CASCADE_BIT	0x8	/*  use two cascaded counters for pacing */
+/* enable pretriggering (used in conjunction with SWTRIG) */
+#define   PRETRIG_BIT	0x1
+/* enable paced conversions on external trigger */
+#define   HWTRIG_BIT	0x2
+/* enable paced conversions */
+#define   SWTRIG_BIT	0x4
+/* use two cascaded counters for pacing */
+#define   CASCADE_BIT	0x8
 #define   DAC_PACED_BIT(channel)	(0x40 << ((channel) & 0x1))
 #define COMMAND3_REG	0x2
-#define   DMA_EN_BIT	0x1	/*  enable dma transfers */
-#define   DIO_INTR_EN_BIT	0x2	/*  enable interrupts for 8255 */
-#define   DMATC_INTR_EN_BIT	0x4	/*  enable dma terminal count interrupt */
-#define   TIMER_INTR_EN_BIT	0x8	/*  enable timer interrupt */
-#define   ERR_INTR_EN_BIT	0x10	/*  enable error interrupt */
-#define   ADC_FNE_INTR_EN_BIT	0x20	/*  enable fifo not empty interrupt */
+/* enable dma transfers */
+#define   DMA_EN_BIT	0x1
+/* enable interrupts for 8255 */
+#define   DIO_INTR_EN_BIT	0x2
+/* enable dma terminal count interrupt */
+#define   DMATC_INTR_EN_BIT	0x4
+/* enable timer interrupt */
+#define   TIMER_INTR_EN_BIT	0x8
+/* enable error interrupt */
+#define   ERR_INTR_EN_BIT	0x10
+/* enable fifo not empty interrupt */
+#define   ADC_FNE_INTR_EN_BIT	0x20
 #define ADC_CONVERT_REG	0x3
 #define DAC_LSB_REG(channel)	(0x4 + 2 * ((channel) & 0x1))
 #define DAC_MSB_REG(channel)	(0x5 + 2 * ((channel) & 0x1))
 #define ADC_CLEAR_REG	0x8
 #define DMATC_CLEAR_REG	0xa
 #define TIMER_CLEAR_REG	0xc
-#define COMMAND6_REG	0xe	/*  1200 boards only */
-#define   ADC_COMMON_BIT	0x1	/*  select ground or common-mode reference */
-#define   ADC_UNIP_BIT	0x2	/*  adc unipolar */
-#define   DAC_UNIP_BIT(channel)	(0x4 << ((channel) & 0x1))	/*  dac unipolar */
-#define   ADC_FHF_INTR_EN_BIT	0x20	/*  enable fifo half full interrupt */
-#define   A1_INTR_EN_BIT	0x40	/*  enable interrupt on end of hardware count */
-#define   ADC_SCAN_UP_BIT 0x80	/*  scan up from channel zero instead of down to zero */
+/* 1200 boards only */
+#define COMMAND6_REG	0xe
+/* select ground or common-mode reference */
+#define   ADC_COMMON_BIT	0x1
+/*  adc unipolar */
+#define   ADC_UNIP_BIT	0x2
+/*  dac unipolar */
+#define   DAC_UNIP_BIT(channel)	(0x4 << ((channel) & 0x1))
+/* enable fifo half full interrupt */
+#define   ADC_FHF_INTR_EN_BIT	0x20
+/* enable interrupt on end of hardware count */
+#define   A1_INTR_EN_BIT	0x40
+/* scan up from channel zero instead of down to zero */
+#define   ADC_SCAN_UP_BIT 0x80
 #define COMMAND4_REG	0xf
-#define   INTERVAL_SCAN_EN_BIT	0x1	/*  enables 'interval' scanning */
-#define   EXT_SCAN_EN_BIT	0x2	/*  enables external signal on counter b1 output to trigger scan */
-#define   EXT_CONVERT_OUT_BIT	0x4	/*  chooses direction (output or input) for EXTCONV* line */
-#define   ADC_DIFF_BIT	0x8	/*  chooses differential inputs for adc (in conjunction with board jumper) */
+/* enables 'interval' scanning */
+#define   INTERVAL_SCAN_EN_BIT	0x1
+/* enables external signal on counter b1 output to trigger scan */
+#define   EXT_SCAN_EN_BIT	0x2
+/* chooses direction (output or input) for EXTCONV* line */
+#define   EXT_CONVERT_OUT_BIT	0x4
+/* chooses differential inputs for adc (in conjunction with board jumper) */
+#define   ADC_DIFF_BIT	0x8
 #define   EXT_CONVERT_DISABLE_BIT	0x10
-#define COMMAND5_REG	0x1c	/*  1200 boards only, calibration stuff */
-#define   EEPROM_WRITE_UNPROTECT_BIT	0x4	/*  enable eeprom for write */
-#define   DITHER_EN_BIT	0x8	/*  enable dithering */
-#define   CALDAC_LOAD_BIT	0x10	/*  load calibration dac */
-#define   SCLOCK_BIT	0x20	/*  serial clock - rising edge writes, falling edge reads */
-#define   SDATA_BIT	0x40	/*  serial data bit for writing to eeprom or calibration dacs */
-#define   EEPROM_EN_BIT	0x80	/*  enable eeprom for read/write */
+/* 1200 boards only, calibration stuff */
+#define COMMAND5_REG	0x1c
+/* enable eeprom for write */
+#define   EEPROM_WRITE_UNPROTECT_BIT	0x4
+/* enable dithering */
+#define   DITHER_EN_BIT	0x8
+/* load calibration dac */
+#define   CALDAC_LOAD_BIT	0x10
+/* serial clock - rising edge writes, falling edge reads */
+#define   SCLOCK_BIT	0x20
+/* serial data bit for writing to eeprom or calibration dacs */
+#define   SDATA_BIT	0x40
+/* enable eeprom for read/write */
+#define   EEPROM_EN_BIT	0x80
 #define INTERVAL_COUNT_REG	0x1e
 #define INTERVAL_LOAD_REG	0x1f
 #define   INTERVAL_LOAD_BITS	0x1
 
 /* read-only registers */
 #define STATUS1_REG	0x0
-#define   DATA_AVAIL_BIT	0x1	/*  data is available in fifo */
-#define   OVERRUN_BIT	0x2	/*  overrun has occurred */
-#define   OVERFLOW_BIT	0x4	/*  fifo overflow */
-#define   TIMER_BIT	0x8	/*  timer interrupt has occured */
-#define   DMATC_BIT	0x10	/*  dma terminal count has occured */
-#define   EXT_TRIG_BIT	0x40	/*  external trigger has occured */
-#define STATUS2_REG	0x1d	/*  1200 boards only */
-#define   EEPROM_OUT_BIT	0x1	/*  programmable eeprom serial output */
-#define   A1_TC_BIT	0x2	/*  counter A1 terminal count */
-#define   FNHF_BIT	0x4	/*  fifo not half full */
+/* data is available in fifo */
+#define   DATA_AVAIL_BIT	0x1
+/* overrun has occurred */
+#define   OVERRUN_BIT	0x2
+/* fifo overflow */
+#define   OVERFLOW_BIT	0x4
+/* timer interrupt has occured */
+#define   TIMER_BIT	0x8
+/* dma terminal count has occured */
+#define   DMATC_BIT	0x10
+/* external trigger has occured */
+#define   EXT_TRIG_BIT	0x40
+/* 1200 boards only */
+#define STATUS2_REG	0x1d
+/* programmable eeprom serial output */
+#define   EEPROM_OUT_BIT	0x1
+/* counter A1 terminal count */
+#define   A1_TC_BIT	0x2
+/* fifo not half full */
+#define   FNHF_BIT	0x4
 #define ADC_FIFO_REG	0xa
 
 #define DIO_BASE_REG	0x10
 #define COUNTER_A_BASE_REG	0x14
 #define COUNTER_A_CONTROL_REG	(COUNTER_A_BASE_REG + 0x3)
-#define   INIT_A0_BITS	0x14	/*  check modes put conversion pacer output in harmless state (a0 mode 2) */
-#define   INIT_A1_BITS	0x70	/*  put hardware conversion counter output in harmless state (a1 mode 0) */
+/* check modes put conversion pacer output in harmless state (a0 mode 2) */
+#define   INIT_A0_BITS	0x14
+/* put hardware conversion counter output in harmless state (a1 mode 0) */
+#define   INIT_A1_BITS	0x70
 #define COUNTER_B_BASE_REG	0x18
 
 static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
@@ -423,7 +466,7 @@
 	 .ai_scan_up = 1,
 	 .memory_mapped_io = 1,
 	 },
-	/*  dummy entry so pci board works when comedi_config is passed driver name */
+/* dummy entry so pci board works when comedi_config is passed driver name */
 	{
 	 .name = DRV_NAME,
 	 .bustype = pci_bustype,
@@ -436,8 +479,10 @@
  */
 #define thisboard ((struct labpc_board_struct *)dev->board_ptr)
 
-static const int dma_buffer_size = 0xff00;	/*  size in bytes of dma buffer */
-static const int sample_size = 2;	/*  2 bytes per sample */
+/* size in bytes of dma buffer */
+static const int dma_buffer_size = 0xff00;
+/* 2 bytes per sample */
+static const int sample_size = 2;
 
 #define devpriv ((struct labpc_private *)dev->private)
 
@@ -483,12 +528,10 @@
 
 	printk("comedi%d: ni_labpc: %s, io 0x%lx", dev->minor, thisboard->name,
 	       iobase);
-	if (irq) {
+	if (irq)
 		printk(", irq %u", irq);
-	}
-	if (dma_chan) {
+	if (dma_chan)
 		printk(", dma %u", dma_chan);
-	}
 	printk("\n");
 
 	if (iobase == 0) {
@@ -513,7 +556,7 @@
 		devpriv->read_byte = labpc_inb;
 		devpriv->write_byte = labpc_outb;
 	}
-	/*  initialize board's command registers */
+	/* initialize board's command registers */
 	devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
 	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
 	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
@@ -538,12 +581,12 @@
 	}
 	dev->irq = irq;
 
-	/*  grab dma channel */
+	/* grab dma channel */
 	if (dma_chan > 3) {
 		printk(" invalid dma channel %u\n", dma_chan);
 		return -EINVAL;
 	} else if (dma_chan) {
-		/*  allocate dma buffer */
+		/* allocate dma buffer */
 		devpriv->dma_buffer =
 		    kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA);
 		if (devpriv->dma_buffer == NULL) {
@@ -575,7 +618,7 @@
 	    SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ;
 	s->n_chan = 8;
 	s->len_chanlist = 8;
-	s->maxdata = (1 << 12) - 1;	/*  12 bit resolution */
+	s->maxdata = (1 << 12) - 1;	/* 12 bit resolution */
 	s->range_table = thisboard->ai_range_table;
 	s->do_cmd = labpc_ai_cmd;
 	s->do_cmdtest = labpc_ai_cmdtest;
@@ -585,8 +628,11 @@
 	/* analog output */
 	s = dev->subdevices + 1;
 	if (thisboard->has_ao) {
-/* Could provide command support, except it only has a one sample
- * hardware buffer for analog output and no underrun flag. */
+		/*
+		 * Could provide command support, except it only has a
+		 * one sample hardware buffer for analog output and no
+		 * underrun flag.
+		 */
 		s->type = COMEDI_SUBD_AO;
 		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
 		s->n_chan = NUM_AO_CHAN;
@@ -608,7 +654,8 @@
 
 	/* 8255 dio */
 	s = dev->subdevices + 2;
-	/*  if board uses io memory we have to give a custom callback function to the 8255 driver */
+	/*  if board uses io memory we have to give a custom callback
+	 * function to the 8255 driver */
 	if (thisboard->memory_mapped_io)
 		subdev_8255_init(dev, s, labpc_dio_mem_callback,
 				 (unsigned long)(dev->iobase + DIO_BASE_REG));
@@ -640,14 +687,12 @@
 		s->insn_read = labpc_eeprom_read_insn;
 		s->insn_write = labpc_eeprom_write_insn;
 
-		for (i = 0; i < EEPROM_SIZE; i++) {
+		for (i = 0; i < EEPROM_SIZE; i++)
 			devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i);
-		}
 #ifdef LABPC_DEBUG
 		printk(" eeprom:");
-		for (i = 0; i < EEPROM_SIZE; i++) {
+		for (i = 0; i < EEPROM_SIZE; i++)
 			printk(" %i:0x%x ", i, devpriv->eeprom_data[i]);
-		}
 		printk("\n");
 #endif
 	} else
@@ -669,7 +714,7 @@
 	if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
 		return -ENOMEM;
 
-	/*  get base address, irq etc. based on bustype */
+	/* get base address, irq etc. based on bustype */
 	switch (thisboard->bustype) {
 	case isa_bustype:
 		iobase = it->options[0];
@@ -679,9 +724,8 @@
 	case pci_bustype:
 #ifdef CONFIG_COMEDI_PCI
 		retval = labpc_find_device(dev, it->options[0], it->options[1]);
-		if (retval < 0) {
+		if (retval < 0)
 			return retval;
-		}
 		retval = mite_setup(devpriv->mite);
 		if (retval < 0)
 			return retval;
@@ -715,7 +759,7 @@
 	for (mite = mite_devices; mite; mite = mite->next) {
 		if (mite->used)
 			continue;
-		/*  if bus/slot are specified then make sure we have the right bus/slot */
+/* if bus/slot are specified then make sure we have the right bus/slot */
 		if (bus || slot) {
 			if (bus != mite->pcidev->bus->number
 			    || slot != PCI_SLOT(mite->pcidev->devfn))
@@ -726,7 +770,7 @@
 				continue;
 			if (mite_device_id(mite) == labpc_boards[i].device_id) {
 				devpriv->mite = mite;
-				/*  fixup board pointer, in case we were using the dummy "ni_labpc" entry */
+/* fixup board pointer, in case we were using the dummy "ni_labpc" entry */
 				dev->board_ptr = &labpc_boards[i];
 				return 0;
 			}
@@ -994,7 +1038,7 @@
 	    cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE)
 		err++;
 
-	/*  can't have external stop and start triggers at once */
+	/* can't have external stop and start triggers at once */
 	if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
 		err++;
 
@@ -1008,9 +1052,9 @@
 		err++;
 	}
 
-	if (!cmd->chanlist_len) {
+	if (!cmd->chanlist_len)
 		err++;
-	}
+
 	if (cmd->scan_end_arg != cmd->chanlist_len) {
 		cmd->scan_end_arg = cmd->chanlist_len;
 		err++;
@@ -1022,7 +1066,7 @@
 			err++;
 		}
 	}
-	/*  make sure scan timing is not too fast */
+	/* make sure scan timing is not too fast */
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		if (cmd->convert_src == TRIG_TIMER &&
 		    cmd->scan_begin_arg <
@@ -1038,7 +1082,7 @@
 			err++;
 		}
 	}
-	/*  stop source */
+	/* stop source */
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
 		if (!cmd->stop_arg) {
@@ -1095,7 +1139,7 @@
 	range = CR_RANGE(cmd->chanlist[0]);
 	aref = CR_AREF(cmd->chanlist[0]);
 
-	/*  make sure board is disabled before setting up aquisition */
+	/* make sure board is disabled before setting up aquisition */
 	spin_lock_irqsave(&dev->spinlock, flags);
 	devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;
 	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
@@ -1105,9 +1149,9 @@
 	devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
 
 	/*  initialize software conversion count */
-	if (cmd->stop_src == TRIG_COUNT) {
+	if (cmd->stop_src == TRIG_COUNT)
 		devpriv->count = cmd->stop_arg * cmd->chanlist_len;
-	}
+
 	/*  setup hardware conversion counter */
 	if (cmd->stop_src == TRIG_EXT) {
 		/*  load counter a1 with count of 3 (pc+ manual says this is minimum allowed) using mode 0 */
@@ -1176,17 +1220,18 @@
 		channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
 	else
 		channel = CR_CHAN(cmd->chanlist[0]);
-	/*  munge channel bits for differential / scan disabled mode */
+	/* munge channel bits for differential / scan disabled mode */
 	if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF)
 		channel *= 2;
 	devpriv->command1_bits |= ADC_CHAN_BITS(channel);
 	devpriv->command1_bits |= thisboard->ai_range_code[range];
 	devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
-	/*  manual says to set scan enable bit on second pass */
+	/* manual says to set scan enable bit on second pass */
 	if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP ||
 	    labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_DOWN) {
 		devpriv->command1_bits |= ADC_SCAN_EN_BIT;
-		/* need a brief delay before enabling scan, or scan list will get screwed when you switch
+		/* need a brief delay before enabling scan, or scan
+		 * list will get screwed when you switch
 		 * between scan up to scan down mode - dunno why */
 		udelay(1);
 		devpriv->write_byte(devpriv->command1_bits,
@@ -1338,7 +1383,7 @@
 	cmd = &async->cmd;
 	async->events = 0;
 
-	/*  read board status */
+	/* read board status */
 	devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG);
 	if (thisboard->register_layout == labpc_1200_layout)
 		devpriv->status2_bits =
@@ -1352,7 +1397,7 @@
 	}
 
 	if (devpriv->status1_bits & OVERRUN_BIT) {
-		/*  clear error interrupt */
+		/* clear error interrupt */
 		devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
 		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 		comedi_event(dev, s);
@@ -1361,7 +1406,10 @@
 	}
 
 	if (devpriv->current_transfer == isa_dma_transfer) {
-		/*  if a dma terminal count of external stop trigger has occurred */
+		/*
+		 * if a dma terminal count of external stop trigger
+		 * has occurred
+		 */
 		if (devpriv->status1_bits & DMATC_BIT ||
 		    (thisboard->register_layout == labpc_1200_layout
 		     && devpriv->status2_bits & A1_TC_BIT)) {
@@ -1479,9 +1527,9 @@
 	}
 
 	/* write data to comedi buffer */
-	for (i = 0; i < num_points; i++) {
+	for (i = 0; i < num_points; i++)
 		cfc_write_to_buffer(s, devpriv->dma_buffer[i]);
-	}
+
 	if (async->cmd.stop_src == TRIG_COUNT)
 		devpriv->count -= num_points;
 
@@ -1503,7 +1551,7 @@
 	devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG);
 }
 
-/* makes sure all data aquired by board is transfered to comedi (used
+/* makes sure all data acquired by board is transfered to comedi (used
  * when aquisition is terminated by stop_src == TRIG_EXT). */
 static void labpc_drain_dregs(struct comedi_device *dev)
 {
@@ -1537,41 +1585,41 @@
 	chan = CR_CHAN(insn->chanspec);
 	range = CR_RANGE(insn->chanspec);
 	devpriv->command1_bits |= thisboard->ai_range_code[range];
-	/*  munge channel bits for differential/scan disabled mode */
+	/* munge channel bits for differential/scan disabled mode */
 	if (CR_AREF(insn->chanspec) == AREF_DIFF)
 		chan *= 2;
 	devpriv->command1_bits |= ADC_CHAN_BITS(chan);
 	devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
 
-	/*  setup command6 register for 1200 boards */
+	/* setup command6 register for 1200 boards */
 	if (thisboard->register_layout == labpc_1200_layout) {
 		/*  reference inputs to ground or common? */
 		if (CR_AREF(insn->chanspec) != AREF_GROUND)
 			devpriv->command6_bits |= ADC_COMMON_BIT;
 		else
 			devpriv->command6_bits &= ~ADC_COMMON_BIT;
-		/*  bipolar or unipolar range? */
+		/* bipolar or unipolar range? */
 		if (thisboard->ai_range_is_unipolar[range])
 			devpriv->command6_bits |= ADC_UNIP_BIT;
 		else
 			devpriv->command6_bits &= ~ADC_UNIP_BIT;
-		/*  don't interrupt on fifo half full */
+		/* don't interrupt on fifo half full */
 		devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT;
-		/*  don't enable interrupt on counter a1 terminal count? */
+		/* don't enable interrupt on counter a1 terminal count? */
 		devpriv->command6_bits &= ~A1_INTR_EN_BIT;
-		/*  write to register */
+		/* write to register */
 		devpriv->write_byte(devpriv->command6_bits,
 				    dev->iobase + COMMAND6_REG);
 	}
-	/*  setup command4 register */
+	/* setup command4 register */
 	devpriv->command4_bits = 0;
 	devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;
-	/*  single-ended/differential */
+	/* single-ended/differential */
 	if (CR_AREF(insn->chanspec) == AREF_DIFF)
 		devpriv->command4_bits |= ADC_DIFF_BIT;
 	devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
 
-	/*  initialize pacer counter output to make sure it doesn't cause any problems */
+	/* initialize pacer counter output to make sure it doesn't cause any problems */
 	devpriv->write_byte(INIT_A0_BITS, dev->iobase + COUNTER_A_CONTROL_REG);
 
 	labpc_clear_adc_fifo(dev);
@@ -1608,7 +1656,7 @@
 
 	channel = CR_CHAN(insn->chanspec);
 
-	/*  turn off pacing of analog output channel */
+	/* turn off pacing of analog output channel */
 	/* note: hardware bug in daqcard-1200 means pacing cannot
 	 * be independently enabled/disabled for its the two channels */
 	spin_lock_irqsave(&dev->spinlock, flags);
@@ -1616,7 +1664,7 @@
 	devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 
-	/*  set range */
+	/* set range */
 	if (thisboard->register_layout == labpc_1200_layout) {
 		range = CR_RANGE(insn->chanspec);
 		if (range & AO_RANGE_IS_UNIPOLAR)
@@ -1627,13 +1675,13 @@
 		devpriv->write_byte(devpriv->command6_bits,
 				    dev->iobase + COMMAND6_REG);
 	}
-	/*  send data */
+	/* send data */
 	lsb = data[0] & 0xff;
 	msb = (data[0] >> 8) & 0xff;
 	devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(channel));
 	devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(channel));
 
-	/*  remember value for readback */
+	/* remember value for readback */
 	devpriv->ao_value[channel] = data[0];
 
 	return 1;
@@ -1705,14 +1753,14 @@
 
 	if (cmd.convert_src == TRIG_TIMER)
 		freq = 1000000000 / cmd.convert_arg;
-	/*  return some default value */
+	/* return some default value */
 	else
 		freq = 0xffffffff;
 
-	/*  make buffer fill in no more than 1/3 second */
+	/* make buffer fill in no more than 1/3 second */
 	size = (freq / 3) * sample_size;
 
-	/*  set a minimum and maximum size allowed */
+	/* set a minimum and maximum size allowed */
 	if (size > dma_buffer_size)
 		size = dma_buffer_size - dma_buffer_size % sample_size;
 	else if (size < sample_size)
@@ -1724,13 +1772,21 @@
 /* figures out what counter values to use based on command */
 static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
 {
-	const int max_counter_value = 0x10000;	/*  max value for 16 bit counter in mode 2 */
-	const int min_counter_value = 2;	/*  min value for 16 bit counter in mode 2 */
+	/* max value for 16 bit counter in mode 2 */
+	const int max_counter_value = 0x10000;
+	/* min value for 16 bit counter in mode 2 */
+	const int min_counter_value = 2;
 	unsigned int base_period;
 
-	/*  if both convert and scan triggers are TRIG_TIMER, then they both rely on counter b0 */
+	/*
+	 * if both convert and scan triggers are TRIG_TIMER, then they
+	 * both rely on counter b0
+	 */
 	if (labpc_ai_convert_period(cmd) && labpc_ai_scan_period(cmd)) {
-		/*  pick the lowest b0 divisor value we can (for maximum input clock speed on convert and scan counters) */
+		/*
+		 * pick the lowest b0 divisor value we can (for maximum input
+		 * clock speed on convert and scan counters)
+		 */
 		devpriv->divisor_b0 = (labpc_ai_scan_period(cmd) - 1) /
 		    (LABPC_TIMER_BASE * max_counter_value) + 1;
 		if (devpriv->divisor_b0 < min_counter_value)
@@ -1780,7 +1836,10 @@
 					    base_period * devpriv->divisor_a0);
 		labpc_set_ai_scan_period(cmd,
 					 base_period * devpriv->divisor_b1);
-		/*  if only one TRIG_TIMER is used, we can employ the generic cascaded timing functions */
+		/*
+		 * if only one TRIG_TIMER is used, we can employ the generic
+		 * cascaded timing functions
+		 */
 	} else if (labpc_ai_scan_period(cmd)) {
 		unsigned int scan_period;
 
@@ -1864,9 +1923,8 @@
 		udelay(1);
 		devpriv->status2_bits =
 		    devpriv->read_byte(dev->iobase + STATUS2_REG);
-		if (devpriv->status2_bits & EEPROM_OUT_BIT) {
+		if (devpriv->status2_bits & EEPROM_OUT_BIT)
 			value |= 1 << (value_width - i);
-		}
 	}
 
 	return value;
@@ -1876,8 +1934,10 @@
 				      unsigned int address)
 {
 	unsigned int value;
-	const int read_instruction = 0x3;	/*  bits to tell eeprom to expect a read */
-	const int write_length = 8;	/*  8 bit write lengths to eeprom */
+	/*  bits to tell eeprom to expect a read */
+	const int read_instruction = 0x3;
+	/*  8 bit write lengths to eeprom */
+	const int write_length = 8;
 
 	/*  enable read/write to eeprom */
 	devpriv->command5_bits &= ~EEPROM_EN_BIT;
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index d6d49c3..bd16f91 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -3795,7 +3795,7 @@
 #endif
 	int retval = 0;
 	unsigned i;
-	const unsigned timeout = 100;
+	const unsigned timeout = 1000;
 
 	s->async->inttrig = NULL;
 
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 2d88a5b..9d33751 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -1,8 +1,8 @@
 /*
     comedi/drivers/ni_pcidio.c
     driver for National Instruments PCI-DIO-96/PCI-6508
-               National Instruments PCI-DIO-32HS
-               National Instruments PCI-6503
+		National Instruments PCI-DIO-32HS
+		National Instruments PCI-6503
 
     COMEDI - Linux Control and Measurement Device Interface
     Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org>
@@ -518,7 +518,8 @@
 	ni_pcidio_print_status(status);
 
 	/* printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf); */
-	/* printk("buf[4096]=%08x\n",*(unsigned int *)(async->prealloc_buf+4096)); */
+	/* printk("buf[4096]=%08x\n",
+	       *(unsigned int *)(async->prealloc_buf+4096)); */
 
 	spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags);
 	if (devpriv->di_mite_chan)
@@ -526,7 +527,9 @@
 #ifdef MITE_DEBUG
 	mite_print_chsr(m_status);
 #endif
-	/* printk("mite_bytes_transferred: %d\n",mite_bytes_transferred(mite,DI_DMA_CHAN)); */
+	/* printk("mite_bytes_transferred: %d\n",
+	       mite_bytes_transferred(mite,DI_DMA_CHAN)); */
+
 	/* mite_dump_regs(mite); */
 	if (m_status & CHSR_INT) {
 		if (m_status & CHSR_LINKC) {
@@ -565,7 +568,8 @@
 					DPRINTK("too much work in interrupt\n");
 					writeb(0x00,
 					       devpriv->mite->daq_io_addr +
-					       Master_DMA_And_Interrupt_Control);
+					       Master_DMA_And_Interrupt_Control
+					      );
 					goto out;
 				}
 				AuxData =
@@ -579,8 +583,10 @@
 				flags = readb(devpriv->mite->daq_io_addr +
 					      Group_1_Flags);
 			}
-			/* DPRINTK("buf_int_count: %d\n",async->buf_int_count); */
-			/* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",IntEn,flags,status); */
+			/* DPRINTK("buf_int_count: %d\n",
+				async->buf_int_count); */
+			/* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",
+				IntEn,flags,status); */
 			/* ni_pcidio_print_flags(flags); */
 			/* ni_pcidio_print_status(status); */
 			async->events |= COMEDI_CB_BLOCK;
@@ -627,8 +633,8 @@
 		flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
 		status = readb(devpriv->mite->daq_io_addr +
 			       Interrupt_And_Window_Status);
-		/* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,status=0x%02x\n", */
-		/* IntEn,flags,status); */
+		/* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,"
+			"status=0x%02x\n", IntEn, flags, status); */
 		/* ni_pcidio_print_flags(flags); */
 		/* ni_pcidio_print_status(status); */
 	}
@@ -655,11 +661,10 @@
 {
 	int i;
 
-	printk("group_1_flags:");
+	printk(KERN_INFO "group_1_flags:");
 	for (i = 7; i >= 0; i--) {
-		if (flags & (1 << i)) {
+		if (flags & (1 << i))
 			printk(" %s", flags_strings[i]);
-		}
 	}
 	printk("\n");
 }
@@ -673,11 +678,10 @@
 {
 	int i;
 
-	printk("group_status:");
+	printk(KERN_INFO "group_status:");
 	for (i = 7; i >= 0; i--) {
-		if (flags & (1 << i)) {
+		if (flags & (1 << i))
 			printk(" %s", status_strings[i]);
-		}
 	}
 	printk("\n");
 }
@@ -793,7 +797,8 @@
 	if (err)
 		return 1;
 
-	/* step 2: make sure trigger sources are unique and mutually compatible */
+	/* step 2: make sure trigger sources are unique and mutually
+	compatible */
 
 	/* note that mutual compatibility is not an issue here */
 	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT)
@@ -974,7 +979,8 @@
 
 	/* clear and enable interrupts */
 	writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear);
-	/* writeb(ClearExpired,devpriv->mite->daq_io_addr+Group_1_Second_Clear); */
+	/* writeb(ClearExpired,
+	       devpriv->mite->daq_io_addr+Group_1_Second_Clear); */
 
 	writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control);
 	writeb(0x03,
@@ -1052,7 +1058,7 @@
 }
 
 static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
-			      u8 * data, int data_len)
+			      u8 *data, int data_len)
 {
 	static const int timeout = 1000;
 	int i, j;
@@ -1066,9 +1072,8 @@
 		udelay(1);
 	}
 	if (i == timeout) {
-		printk
-		    ("ni_pcidio: failed to load fpga %i, waiting for status 0x2\n",
-		     fpga_index);
+		printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
+		       "waiting for status 0x2\n", fpga_index);
 		return -EIO;
 	}
 	writew(0x80 | fpga_index,
@@ -1079,9 +1084,8 @@
 		udelay(1);
 	}
 	if (i == timeout) {
-		printk
-		    ("ni_pcidio: failed to load fpga %i, waiting for status 0x3\n",
-		     fpga_index);
+		printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
+		       "waiting for status 0x3\n", fpga_index);
 		return -EIO;
 	}
 	for (j = 0; j + 1 < data_len;) {
@@ -1174,9 +1178,10 @@
 	int n_subdevices;
 	unsigned int irq;
 
-	printk("comedi%d: nidio:", dev->minor);
+	printk(KERN_INFO "comedi%d: nidio:", dev->minor);
 
-	if ((ret = alloc_private(dev, sizeof(struct nidio96_private))) < 0)
+	ret = alloc_private(dev, sizeof(struct nidio96_private));
+	if (ret < 0)
 		return ret;
 	spin_lock_init(&devpriv->mite_channel_lock);
 
@@ -1186,7 +1191,7 @@
 
 	ret = mite_setup(devpriv->mite);
 	if (ret < 0) {
-		printk("error setting up mite\n");
+		printk(KERN_WARNING "error setting up mite\n");
 		return ret;
 	}
 	comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
@@ -1196,18 +1201,19 @@
 
 	dev->board_name = this_board->name;
 	irq = mite_irq(devpriv->mite);
-	printk(" %s", dev->board_name);
+	printk(KERN_INFO " %s", dev->board_name);
 	if (this_board->uses_firmware) {
 		ret = pci_6534_upload_firmware(dev, it->options);
 		if (ret < 0)
 			return ret;
 	}
-	if (!this_board->is_diodaq) {
+	if (!this_board->is_diodaq)
 		n_subdevices = this_board->n_8255;
-	} else {
+	else
 		n_subdevices = 1;
-	}
-	if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
+
+	ret = alloc_subdevices(dev, n_subdevices);
+	if (ret < 0)
 		return ret;
 
 	if (!this_board->is_diodaq) {
@@ -1220,7 +1226,7 @@
 		}
 	} else {
 
-		printk(" rev=%d",
+		printk(KERN_INFO " rev=%d",
 		       readb(devpriv->mite->daq_io_addr + Chip_Version));
 
 		s = dev->subdevices + 0;
@@ -1253,9 +1259,9 @@
 
 		ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
 				  "ni_pcidio", dev);
-		if (ret < 0) {
-			printk(" irq not available");
-		}
+		if (ret < 0)
+			printk(KERN_WARNING " irq not available");
+
 		dev->irq = irq;
 	}
 
@@ -1269,9 +1275,8 @@
 	int i;
 
 	if (this_board && !this_board->is_diodaq) {
-		for (i = 0; i < this_board->n_8255; i++) {
+		for (i = 0; i < this_board->n_8255; i++)
 			subdev_8255_cleanup(dev, dev->subdevices + i);
-		}
 	}
 
 	if (dev->irq)
@@ -1310,7 +1315,7 @@
 			}
 		}
 	}
-	printk("no device found\n");
+	printk(KERN_WARNING "no device found\n");
 	mite_list_devices();
 	return -EIO;
 }
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index 4914784..a499f70 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -207,11 +207,10 @@
 
 	/* FIXME! Nothing else sets ntrig! */
 	if (!(--devpriv->ntrig)) {
-		if (this_board->is_8112) {
+		if (this_board->is_8112)
 			outb(1, dev->iobase + PCL711_MODE);
-		} else {
+		else
 			outb(0, dev->iobase + PCL711_MODE);
-		}
 
 		s->async->events |= COMEDI_CB_EOA;
 	}
@@ -232,15 +231,15 @@
 		/*
 		 *  Set the correct channel.  The two channel banks are switched
 		 *  using the mask value.
-		 *  NB: To use differential channels, you should use mask = 0x30,
-		 *  but I haven't written the support for this yet. /JJ
+		 *  NB: To use differential channels, you should use
+		 *  mask = 0x30, but I haven't written the support for this
+		 *  yet. /JJ
 		 */
 
-		if (chan_register >= 8) {
+		if (chan_register >= 8)
 			chan_register = 0x20 | (chan_register & 0x7);
-		} else {
+		else
 			chan_register |= 0x10;
-		}
 	} else {
 		outb(chan_register, dev->iobase + PCL711_MUX);
 	}
@@ -256,15 +255,13 @@
 
 	for (n = 0; n < insn->n; n++) {
 		/*
-		 *  Write the correct mode (software polling) and start polling by writing
-		 *  to the trigger register
+		 *  Write the correct mode (software polling) and start polling
+		 *  by writing to the trigger register
 		 */
 		outb(1, dev->iobase + PCL711_MODE);
 
-		if (this_board->is_8112) {
-		} else {
+		if (!this_board->is_8112)
 			outb(0, dev->iobase + PCL711_SOFTTRIG);
-		}
 
 		i = PCL711_TIMEOUT;
 		while (--i) {
@@ -462,9 +459,8 @@
 	int n;
 	int chan = CR_CHAN(insn->chanspec);
 
-	for (n = 0; n < insn->n; n++) {
+	for (n = 0; n < insn->n; n++)
 		data[n] = devpriv->ao_readback[chan];
-	}
 
 	return n;
 
@@ -619,9 +615,8 @@
 	   this is the "base value" for the mode register, which is
 	   used for the irq on the PCL711
 	 */
-	if (this_board->is_pcl711b) {
+	if (this_board->is_pcl711b)
 		devpriv->mode = (dev->irq << 4);
-	}
 
 	/* clear DAC */
 	outb(0, dev->iobase + PCL711_DA0_LO);
diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
index df1f4ef..0f103c3 100644
--- a/drivers/staging/comedi/drivers/pcl724.c
+++ b/drivers/staging/comedi/drivers/pcl724.c
@@ -17,7 +17,7 @@
      [0] - IO Base
      [1] - IRQ (0=disable IRQ) IRQ isn't supported at this time!
      [2] -number of DIO:
-              0, 144: 144 DIO configuration
+	      0, 144: 144 DIO configuration
 	      1,  96:  96 DIO configuration
 */
 /*
@@ -137,8 +137,8 @@
 	iorange = this_board->io_range;
 	if ((this_board->can_have96) && ((it->options[1] == 1)
 					 || (it->options[1] == 96)))
-		iorange = PCL722_96_SIZE;	/*  PCL-724 in 96 DIO configuration */
-	printk("comedi%d: pcl724: board=%s, 0x%03lx ", dev->minor,
+		iorange = PCL722_96_SIZE; /* PCL-724 in 96 DIO configuration */
+	printk(KERN_INFO "comedi%d: pcl724: board=%s, 0x%03lx ", dev->minor,
 	       this_board->name, iobase);
 	if (!request_region(iobase, iorange, "pcl724")) {
 		printk("I/O port conflict\n");
@@ -155,16 +155,16 @@
 		irq = it->options[1];
 		if (irq) {	/* we want to use IRQ */
 			if (((1 << irq) & this_board->IRQbits) == 0) {
-				printk
-				    (", IRQ %u is out of allowed range, DISABLING IT",
-				     irq);
+				printk(KERN_WARNING
+				       ", IRQ %u is out of allowed range, "
+				       "DISABLING IT", irq);
 				irq = 0;	/* Bad IRQ */
 			} else {
 				if (request_irq
 				    (irq, interrupt_pcl724, 0, "pcl724", dev)) {
-					printk
-					    (", unable to allocate IRQ %u, DISABLING IT",
-					     irq);
+					printk(KERN_WARNING
+					       ", unable to allocate IRQ %u, "
+					       "DISABLING IT", irq);
 					irq = 0;	/* Can't use IRQ */
 				} else {
 					printk(", irq=%u", irq);
@@ -207,16 +207,14 @@
 {
 	int i;
 
-/* printk("comedi%d: pcl724: remove\n",dev->minor); */
+	/* printk("comedi%d: pcl724: remove\n",dev->minor); */
 
-	for (i = 0; i < dev->n_subdevices; i++) {
+	for (i = 0; i < dev->n_subdevices; i++)
 		subdev_8255_cleanup(dev, dev->subdevices + i);
-	}
 
 #ifdef PCL724_IRQ
-	if (dev->irq) {
+	if (dev->irq)
 		free_irq(dev->irq, dev);
-	}
 #endif
 
 	release_region(dev->iobase, this_board->io_range);
diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
index 1da4941..60261f4 100644
--- a/drivers/staging/comedi/drivers/pcl725.c
+++ b/drivers/staging/comedi/drivers/pcl725.c
@@ -66,7 +66,7 @@
 	unsigned long iobase;
 
 	iobase = it->options[0];
-	printk("comedi%d: pcl725: 0x%04lx ", dev->minor, iobase);
+	printk(KERN_INFO "comedi%d: pcl725: 0x%04lx ", dev->minor, iobase);
 	if (!request_region(iobase, PCL725_SIZE, "pcl725")) {
 		printk("I/O port conflict\n");
 		return -EIO;
@@ -96,14 +96,14 @@
 	s->insn_bits = pcl725_di_insn;
 	s->range_table = &range_digital;
 
-	printk("\n");
+	printk(KERN_INFO "\n");
 
 	return 0;
 }
 
 static int pcl725_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: pcl725: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: pcl725: remove\n", dev->minor);
 
 	if (dev->iobase)
 		release_region(dev->iobase, PCL725_SIZE);
diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
index c9859c9..e5e7bed 100644
--- a/drivers/staging/comedi/drivers/pcl730.c
+++ b/drivers/staging/comedi/drivers/pcl730.c
@@ -99,7 +99,7 @@
 
 	iobase = it->options[0];
 	iorange = this_board->io_range;
-	printk("comedi%d: pcl730: board=%s 0x%04lx ", dev->minor,
+	printk(KERN_INFO "comedi%d: pcl730: board=%s 0x%04lx ", dev->minor,
 	       this_board->name, iobase);
 	if (!request_region(iobase, iorange, "pcl730")) {
 		printk("I/O port conflict\n");
@@ -152,14 +152,14 @@
 	s->range_table = &range_digital;
 	s->private = (void *)PCL730_DIO_LO;
 
-	printk("\n");
+	printk(KERN_INFO "\n");
 
 	return 0;
 }
 
 static int pcl730_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: pcl730: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: pcl730: remove\n", dev->minor);
 
 	if (dev->iobase)
 		release_region(dev->iobase, this_board->io_range);
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 0a5bc3d..d4634c4 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -955,6 +955,7 @@
 	unsigned int mask, timeout;
 	struct comedi_device *dev = d;
 	struct comedi_subdevice *s = dev->subdevices + 0;
+	unsigned int next_chan;
 
 	s->async->events = 0;
 
@@ -993,9 +994,18 @@
 		       ((inb(dev->iobase + PCL812_AD_HI) << 8) |
 			inb(dev->iobase + PCL812_AD_LO)) & mask);
 
+	/* Set up next channel. Added by abbotti 2010-01-20, but untested. */
+	next_chan = s->async->cur_chan + 1;
+	if (next_chan >= devpriv->ai_n_chan)
+		next_chan = 0;
+	if (devpriv->ai_chanlist[s->async->cur_chan] !=
+			devpriv->ai_chanlist[next_chan])
+		setup_range_channel(dev, s, devpriv->ai_chanlist[next_chan], 0);
+
 	outb(0, dev->iobase + PCL812_CLRINT);	/* clear INT request */
 
-	if (s->async->cur_chan == 0) {	/* one scan done */
+	s->async->cur_chan = next_chan;
+	if (next_chan == 0) {	/* one scan done */
 		devpriv->ai_act_scan++;
 		if (!(devpriv->ai_neverending))
 			if (devpriv->ai_act_scan >= devpriv->ai_scans) {	/* all data sampled */
@@ -1021,7 +1031,9 @@
 	for (i = len; i; i--) {
 		comedi_buf_put(s->async, ptr[bufptr++]);	/*  get one sample */
 
-		if (s->async->cur_chan == 0) {
+		s->async->cur_chan++;
+		if (s->async->cur_chan >= devpriv->ai_n_chan) {
+			s->async->cur_chan = 0;
 			devpriv->ai_act_scan++;
 			if (!devpriv->ai_neverending)
 				if (devpriv->ai_act_scan >= devpriv->ai_scans) {	/* all data sampled */
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 852fe24..9820759 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -202,6 +202,7 @@
 	unsigned int ai_act_chanlist[16];	/*  MUX setting for actual AI operations */
 	unsigned int ai_act_chanlist_len;	/*  how long is actual MUX list */
 	unsigned int ai_act_chanlist_pos;	/*  actual position in MUX list */
+	unsigned int ai_n_chan;		/*  how many channels per scan */
 	unsigned int ai_poll_ptr;	/*  how many sampes transfer poll */
 	struct comedi_subdevice *sub_ai;	/*  ptr to AI subdevice */
 #ifdef unused
@@ -213,9 +214,12 @@
 /*
 ==============================================================================
 */
-static int check_and_setup_channel_list(struct comedi_device *dev,
-					struct comedi_subdevice *s,
-					unsigned int *chanlist, int chanlen);
+static int check_channel_list(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      unsigned int *chanlist, unsigned int chanlen);
+static void setup_channel_list(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       unsigned int *chanlist, unsigned int seglen);
 static int pcl816_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s);
 static void start_pacer(struct comedi_device *dev, int mode,
@@ -320,7 +324,9 @@
 	if (++devpriv->ai_act_chanlist_pos >= devpriv->ai_act_chanlist_len)
 		devpriv->ai_act_chanlist_pos = 0;
 
-	if (s->async->cur_chan == 0) {
+	s->async->cur_chan++;
+	if (s->async->cur_chan >= devpriv->ai_n_chan) {
+		s->async->cur_chan = 0;
 		devpriv->ai_act_scan++;
 	}
 
@@ -353,6 +359,11 @@
 		if (++devpriv->ai_act_chanlist_pos >=
 		    devpriv->ai_act_chanlist_len) {
 			devpriv->ai_act_chanlist_pos = 0;
+		}
+
+		s->async->cur_chan++;
+		if (s->async->cur_chan >= devpriv->ai_n_chan) {
+			s->async->cur_chan = 0;
 			devpriv->ai_act_scan++;
 		}
 
@@ -558,14 +569,6 @@
 		}
 	}
 
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->chanlist_len > this_board->n_aichan) {
-		cmd->chanlist_len = this_board->n_aichan;
-		err++;
-	}
 	if (cmd->scan_end_arg != cmd->chanlist_len) {
 		cmd->scan_end_arg = cmd->chanlist_len;
 		err++;
@@ -603,6 +606,14 @@
 		return 4;
 	}
 
+	/* step 5: complain about special chanlist considerations */
+
+	if (cmd->chanlist) {
+		if (!check_channel_list(dev, s, cmd->chanlist,
+					cmd->chanlist_len))
+			return 5;	/*  incorrect channels list */
+	}
+
 	return 0;
 }
 
@@ -610,6 +621,7 @@
 {
 	unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
 	struct comedi_cmd *cmd = &s->async->cmd;
+	unsigned int seglen;
 
 	if (cmd->start_src != TRIG_NOW)
 		return -EINVAL;
@@ -642,11 +654,13 @@
 
 	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
 
-	if (!check_and_setup_channel_list(dev, s, cmd->chanlist,
-					  cmd->chanlist_len))
+	seglen = check_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len);
+	if (seglen < 1)
 		return -EINVAL;
+	setup_channel_list(dev, s, cmd->chanlist, seglen);
 	udelay(1);
 
+	devpriv->ai_n_chan = cmd->chanlist_len;
 	devpriv->ai_act_scan = 0;
 	s->async->cur_chan = 0;
 	devpriv->irq_blocked = 1;
@@ -871,12 +885,12 @@
 /*
 ==============================================================================
  Check if channel list from user is builded correctly
- If it's ok, then program scan/gain logic
+ If it's ok, then return non-zero length of repeated segment of channel list
 */
 static int
-check_and_setup_channel_list(struct comedi_device *dev,
-			     struct comedi_subdevice *s, unsigned int *chanlist,
-			     int chanlen)
+check_channel_list(struct comedi_device *dev,
+		   struct comedi_subdevice *s, unsigned int *chanlist,
+		   unsigned int chanlen)
 {
 	unsigned int chansegment[16];
 	unsigned int i, nowmustbechan, seglen, segpos;
@@ -930,6 +944,20 @@
 		seglen = 1;
 	}
 
+	return seglen;	/*  we can serve this with MUX logic */
+}
+
+/*
+==============================================================================
+ Program scan/gain logic with channel list.
+*/
+static void
+setup_channel_list(struct comedi_device *dev,
+		   struct comedi_subdevice *s, unsigned int *chanlist,
+		   unsigned int seglen)
+{
+	unsigned int i;
+
 	devpriv->ai_act_chanlist_len = seglen;
 	devpriv->ai_act_chanlist_pos = 0;
 
@@ -942,8 +970,6 @@
 	udelay(1);
 
 	outb(devpriv->ai_act_chanlist[0] | (devpriv->ai_act_chanlist[seglen - 1] << 4), dev->iobase + PCL816_MUX);	/* select channel interval to scan */
-
-	return 1;		/*  we can serve this with MUX logic */
 }
 
 #ifdef unused
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index d048101..c9d7538 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -557,8 +557,14 @@
 		comedi_event(dev, s);
 		return IRQ_HANDLED;
 	}
-	if (s->async->cur_chan == 0) {
+	devpriv->act_chanlist_pos++;
+	if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
+		devpriv->act_chanlist_pos = 0;
+	}
+	s->async->cur_chan++;
+	if (s->async->cur_chan >= devpriv->ai_n_chan) {
 		/*  printk("E"); */
+		s->async->cur_chan = 0;
 		devpriv->ai_act_scan--;
 	}
 
@@ -627,9 +633,13 @@
 
 		devpriv->act_chanlist_pos++;
 		if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
-			devpriv->ai_act_scan--;
 			devpriv->act_chanlist_pos = 0;
 		}
+		s->async->cur_chan++;
+		if (s->async->cur_chan >= devpriv->ai_n_chan) {
+			s->async->cur_chan = 0;
+			devpriv->ai_act_scan--;
+		}
 
 		if (!devpriv->neverending_ai)
 			if (devpriv->ai_act_scan == 0) {	/* all data sampled */
@@ -717,7 +727,14 @@
 			comedi_buf_put(s->async, dmabuf[bufptr++] >> 4);	/*  get one sample */
 			bufptr &= (devpriv->dmasamplsize - 1);
 
-			if (s->async->cur_chan == 0) {
+			devpriv->act_chanlist_pos++;
+			if (devpriv->act_chanlist_pos >=
+					devpriv->act_chanlist_len) {
+				devpriv->act_chanlist_pos = 0;
+			}
+			s->async->cur_chan++;
+			if (s->async->cur_chan >= devpriv->ai_n_chan) {
+				s->async->cur_chan = 0;
 				devpriv->ai_act_scan--;
 			}
 
@@ -796,7 +813,13 @@
 
 		comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4));	/*  get one sample */
 
-		if (s->async->cur_chan == 0) {
+		devpriv->act_chanlist_pos++;
+		if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
+			devpriv->act_chanlist_pos = 0;
+		}
+		s->async->cur_chan++;
+		if (s->async->cur_chan >= devpriv->ai_n_chan) {
+			s->async->cur_chan = 0;
 			devpriv->ai_act_scan--;
 		}
 
@@ -1369,14 +1392,6 @@
 		}
 	}
 
-	if (!cmd->chanlist_len) {
-		cmd->chanlist_len = 1;
-		err++;
-	}
-	if (cmd->chanlist_len > s->n_chan) {
-		cmd->chanlist_len = s->n_chan;
-		err++;
-	}
 	if (cmd->scan_end_arg != cmd->chanlist_len) {
 		cmd->scan_end_arg = cmd->chanlist_len;
 		err++;
diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
index 5281182..ed61030 100644
--- a/drivers/staging/comedi/drivers/pcm3724.c
+++ b/drivers/staging/comedi/drivers/pcm3724.c
@@ -121,25 +121,22 @@
 {
 	/* 1 in io_bits indicates output */
 	if (s->io_bits & 0x0000ff) {
-		if (devno == 0) {
+		if (devno == 0)
 			config |= BUF_A0;
-		} else {
+		else
 			config |= BUF_A1;
-		}
 	}
 	if (s->io_bits & 0x00ff00) {
-		if (devno == 0) {
+		if (devno == 0)
 			config |= BUF_B0;
-		} else {
+		else
 			config |= BUF_B1;
-		}
 	}
 	if (s->io_bits & 0xff0000) {
-		if (devno == 0) {
+		if (devno == 0)
 			config |= BUF_C0;
-		} else {
+		else
 			config |= BUF_C1;
-		}
 	}
 	return config;
 }
@@ -155,26 +152,27 @@
 	buffer_config = 0;
 
 	/* 1 in io_bits indicates output, 1 in config indicates input */
-	if (!(s->io_bits & 0x0000ff)) {
+	if (!(s->io_bits & 0x0000ff))
 		config |= CR_A_IO;
-	}
-	if (!(s->io_bits & 0x00ff00)) {
+
+	if (!(s->io_bits & 0x00ff00))
 		config |= CR_B_IO;
-	}
-	if (!(s->io_bits & 0xff0000)) {
+
+	if (!(s->io_bits & 0xff0000))
 		config |= CR_C_IO;
-	}
 
 	buffer_config = compute_buffer(0, 0, dev->subdevices);
 	buffer_config = compute_buffer(buffer_config, 1, (dev->subdevices) + 1);
 
-	if (s == dev->subdevices) {
+	if (s == dev->subdevices)
 		port_8255_cfg = dev->iobase + _8255_CR;
-	} else {
+	else
 		port_8255_cfg = dev->iobase + SIZE_8255 + _8255_CR;
-	}
+
 	outb(buffer_config, dev->iobase + 8);	/* update buffer register */
-	/* printk("pcm3724 buffer_config (%lx) %d, %x\n", dev->iobase + _8255_CR, chanspec, buffer_config); */
+	/* printk("pcm3724 buffer_config (%lx) %d, %x\n",
+	       dev->iobase + _8255_CR, chanspec, buffer_config); */
+
 	outb(config, port_8255_cfg);
 }
 
@@ -189,29 +187,29 @@
 	priv = (struct priv_pcm3724 *)(dev->private);
 
 	mask = 1 << CR_CHAN(chanspec);
-	if (s == dev->subdevices) {	/*  subdev 0 */
+	if (s == dev->subdevices)	/*  subdev 0 */
 		priv->dio_1 |= mask;
-	} else {		/* subdev 1 */
+	else		/* subdev 1 */
 		priv->dio_2 |= mask;
-	}
-	if (priv->dio_1 & 0xff0000) {
+
+	if (priv->dio_1 & 0xff0000)
 		gatecfg |= GATE_C0;
-	}
-	if (priv->dio_1 & 0xff00) {
+
+	if (priv->dio_1 & 0xff00)
 		gatecfg |= GATE_B0;
-	}
-	if (priv->dio_1 & 0xff) {
+
+	if (priv->dio_1 & 0xff)
 		gatecfg |= GATE_A0;
-	}
-	if (priv->dio_2 & 0xff0000) {
+
+	if (priv->dio_2 & 0xff0000)
 		gatecfg |= GATE_C1;
-	}
-	if (priv->dio_2 & 0xff00) {
+
+	if (priv->dio_2 & 0xff00)
 		gatecfg |= GATE_B1;
-	}
-	if (priv->dio_2 & 0xff) {
+
+	if (priv->dio_2 & 0xff)
 		gatecfg |= GATE_A1;
-	}
+
 	/*       printk("gate control %x\n", gatecfg); */
 	outb(gatecfg, dev->iobase + 9);
 }
@@ -225,15 +223,14 @@
 	unsigned int bits;
 
 	mask = 1 << CR_CHAN(insn->chanspec);
-	if (mask & 0x0000ff) {
+	if (mask & 0x0000ff)
 		bits = 0x0000ff;
-	} else if (mask & 0x00ff00) {
+	else if (mask & 0x00ff00)
 		bits = 0x00ff00;
-	} else if (mask & 0x0f0000) {
+	else if (mask & 0x0f0000)
 		bits = 0x0f0000;
-	} else {
+	else
 		bits = 0xf00000;
-	}
 
 	switch (data[0]) {
 	case INSN_CONFIG_DIO_INPUT:
@@ -272,7 +269,7 @@
 	((struct priv_pcm3724 *)(dev->private))->dio_1 = 0;
 	((struct priv_pcm3724 *)(dev->private))->dio_2 = 0;
 
-	printk("comedi%d: pcm3724: board=%s, 0x%03lx ", dev->minor,
+	printk(KERN_INFO "comedi%d: pcm3724: board=%s, 0x%03lx ", dev->minor,
 	       this_board->name, iobase);
 	if (!iobase || !request_region(iobase, iorange, "pcm3724")) {
 		printk("I/O port conflict\n");
@@ -281,7 +278,7 @@
 
 	dev->iobase = iobase;
 	dev->board_name = this_board->name;
-	printk("\n");
+	printk(KERN_INFO "\n");
 
 	n_subdevices = this_board->numofports;
 
@@ -302,13 +299,11 @@
 	int i;
 
 	if (dev->subdevices) {
-		for (i = 0; i < dev->n_subdevices; i++) {
+		for (i = 0; i < dev->n_subdevices; i++)
 			subdev_8255_cleanup(dev, dev->subdevices + i);
-		}
 	}
-	if (dev->iobase) {
+	if (dev->iobase)
 		release_region(dev->iobase, this_board->io_range);
-	}
 
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
index 9e4adbd..22b7aae 100644
--- a/drivers/staging/comedi/drivers/pcm3730.c
+++ b/drivers/staging/comedi/drivers/pcm3730.c
@@ -73,7 +73,7 @@
 	unsigned long iobase;
 
 	iobase = it->options[0];
-	printk("comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase);
+	printk(KERN_INFO "comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase);
 	if (!request_region(iobase, PCM3730_SIZE, "pcm3730")) {
 		printk("I/O port conflict\n");
 		return -EIO;
@@ -140,14 +140,14 @@
 	s->range_table = &range_digital;
 	s->private = (void *)PCM3730_DIC;
 
-	printk("\n");
+	printk(KERN_INFO "\n");
 
 	return 0;
 }
 
 static int pcm3730_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: pcm3730: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: pcm3730: remove\n", dev->minor);
 
 	if (dev->iobase)
 		release_region(dev->iobase, PCM3730_SIZE);
diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index acac670..fab8092 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -34,11 +34,11 @@
   [0] - I/O port base
   [1] - unused
   [2] - Analog input reference
-          0 = single ended
-          1 = differential
+	0 = single ended
+	1 = differential
   [3] - Analog input encoding (must match jumpers)
-          0 = straight binary
-          1 = two's complement
+	0 = straight binary
+	1 = two's complement
 */
 
 #include <linux/interrupt.h>
@@ -113,9 +113,8 @@
 		data[n] = inb(dev->iobase + PCMAD_LSB);
 		data[n] |= (inb(dev->iobase + PCMAD_MSB) << 8);
 
-		if (devpriv->twos_comp) {
+		if (devpriv->twos_comp)
 			data[n] ^= (1 << (this_board->n_ai_bits - 1));
-		}
 	}
 
 	return n;
@@ -135,11 +134,12 @@
 	unsigned long iobase;
 
 	iobase = it->options[0];
-	printk("comedi%d: pcmad: 0x%04lx ", dev->minor, iobase);
+	printk(KERN_INFO "comedi%d: pcmad: 0x%04lx ", dev->minor, iobase);
 	if (!request_region(iobase, PCMAD_SIZE, "pcmad")) {
-		printk("I/O port conflict\n");
+		printk(KERN_CONT "I/O port conflict\n");
 		return -EIO;
 	}
+	printk(KERN_CONT "\n");
 	dev->iobase = iobase;
 
 	ret = alloc_subdevices(dev, 1);
@@ -166,11 +166,11 @@
 
 static int pcmad_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: pcmad: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: pcmad: remove\n", dev->minor);
 
-	if (dev->irq) {
+	if (dev->irq)
 		free_irq(dev->irq, dev);
-	}
+
 	if (dev->iobase)
 		release_region(dev->iobase, PCMAD_SIZE);
 
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index 35ba939..6ca4105 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -550,7 +550,7 @@
 
 	if (irq[0]) {
 		printk("irq: %u ", irq[0]);
-		if (irq[1] && thisboard->dio_num_asics == 2)
+		if (thisboard->dio_num_asics == 2 && irq[1])
 			printk("second ASIC irq: %u ", irq[1]);
 	} else {
 		printk("(IRQ mode disabled) ");
diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
index d23e588..1ebc356 100644
--- a/drivers/staging/comedi/drivers/poc.c
+++ b/drivers/staging/comedi/drivers/poc.c
@@ -122,22 +122,21 @@
 	unsigned int iosize;
 
 	iobase = it->options[0];
-	printk("comedi%d: poc: using %s iobase 0x%lx\n", dev->minor,
+	printk(KERN_INFO "comedi%d: poc: using %s iobase 0x%lx\n", dev->minor,
 	       this_board->name, iobase);
 
 	dev->board_name = this_board->name;
 
 	if (iobase == 0) {
-		printk("io base address required\n");
+		printk(KERN_ERR "io base address required\n");
 		return -EINVAL;
 	}
 
 	iosize = this_board->iosize;
 	/* check if io addresses are available */
 	if (!request_region(iobase, iosize, "dac02")) {
-		printk
-		    ("I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
-		     iobase, iobase + iosize - 1);
+		printk(KERN_ERR "I/O port conflict: failed to allocate ports "
+			"0x%lx to 0x%lx\n", iobase, iobase + iosize - 1);
 		return -EIO;
 	}
 	dev->iobase = iobase;
@@ -156,9 +155,8 @@
 	s->insn_write = this_board->winsn;
 	s->insn_read = this_board->rinsn;
 	s->insn_bits = this_board->insnbits;
-	if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO) {
+	if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO)
 		s->subdev_flags = SDF_WRITABLE;
-	}
 
 	return 0;
 }
@@ -169,7 +167,7 @@
 	if (dev->iobase)
 		release_region(dev->iobase, this_board->iosize);
 
-	printk("comedi%d: dac02: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: dac02: remove\n", dev->minor);
 
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index 2c9d05b..028ed6f 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -32,22 +32,22 @@
   [0] - I/O port base address
   [1] - IRQ
   [2] - A/D reference
-          0 = differential
-          1 = pseudodifferential (common)
-          2 = single-ended
+	0 = differential
+	1 = pseudodifferential (common)
+	2 = single-ended
   [3] - A/D range
-          0 = [-10,10]
-          1 = [-5,5]
-          2 = [0,10]
+	0 = [-10,10]
+	1 = [-5,5]
+	2 = [0,10]
   [4] - A/D encoding
-          0 = two's complement
-          1 = straight binary
+	0 = two's complement
+	1 = straight binary
   [5] - DAC 0 range
-          0 = [-10,10]
-          1 = [0,10]
+	0 = [-10,10]
+	1 = [0,10]
   [6] - DAC 0 encoding
-          0 = two's complement
-          1 = straight binary
+	0 = two's complement
+	1 = straight binary
   [7] - DAC 1 range (same as DAC 0)
   [8] - DAC 1 encoding (same as DAC 0)
 */
@@ -225,7 +225,7 @@
 		for (t = RTI800_TIMEOUT; t; t--) {
 			status = inb(dev->iobase + RTI800_CSR);
 			if (status & RTI800_OVERRUN) {
-				printk("rti800: a/d overrun\n");
+				printk(KERN_WARNING "rti800: a/d overrun\n");
 				outb(0, dev->iobase + RTI800_CLRFLAGS);
 				return -EIO;
 			}
@@ -234,15 +234,14 @@
 			udelay(1);
 		}
 		if (t == 0) {
-			printk("rti800: timeout\n");
+			printk(KERN_WARNING "rti800: timeout\n");
 			return -ETIME;
 		}
 		data[i] = inb(dev->iobase + RTI800_ADCLO);
 		data[i] |= (0xf & inb(dev->iobase + RTI800_ADCHI)) << 8;
 
-		if (devpriv->adc_coding == adc_2comp) {
+		if (devpriv->adc_coding == adc_2comp)
 			data[i] ^= 0x800;
-		}
 	}
 
 	return i;
@@ -271,9 +270,9 @@
 
 	for (i = 0; i < insn->n; i++) {
 		devpriv->ao_readback[chan] = d = data[i];
-		if (devpriv->dac0_coding == dac_2comp) {
+		if (devpriv->dac0_coding == dac_2comp)
 			d ^= 0x800;
-		}
+
 		outb(d & 0xff,
 		     dev->iobase + (chan ? RTI800_DAC1LO : RTI800_DAC0LO));
 		outb(d >> 8,
@@ -315,15 +314,15 @@
    options[0] - I/O port
    options[1] - irq
    options[2] - a/d mux
-   	0=differential, 1=pseudodiff, 2=single
+	0=differential, 1=pseudodiff, 2=single
    options[3] - a/d range
-   	0=bipolar10, 1=bipolar5, 2=unipolar10
+	0=bipolar10, 1=bipolar5, 2=unipolar10
    options[4] - a/d coding
-   	0=2's comp, 1=straight binary
+	0=2's comp, 1=straight binary
    options[5] - dac0 range
-   	0=bipolar10, 1=unipolar10
+	0=bipolar10, 1=unipolar10
    options[6] - dac0 coding
-   	0=2's comp, 1=straight binary
+	0=2's comp, 1=straight binary
    options[7] - dac1 range
    options[8] - dac1 coding
  */
@@ -336,15 +335,15 @@
 	struct comedi_subdevice *s;
 
 	iobase = it->options[0];
-	printk("comedi%d: rti800: 0x%04lx ", dev->minor, iobase);
+	printk(KERN_INFO "comedi%d: rti800: 0x%04lx\n", dev->minor, iobase);
 	if (!request_region(iobase, RTI800_SIZE, "rti800")) {
-		printk("I/O port conflict\n");
+		printk(KERN_WARNING "I/O port conflict\n");
 		return -EIO;
 	}
 	dev->iobase = iobase;
 
 #ifdef DEBUG
-	printk("fingerprint=%x,%x,%x,%x,%x ",
+	printk(KERN_DEBUG "fingerprint=%x,%x,%x,%x,%x ",
 	       inb(dev->iobase + 0),
 	       inb(dev->iobase + 1),
 	       inb(dev->iobase + 2),
@@ -357,15 +356,15 @@
 
 	irq = it->options[1];
 	if (irq) {
-		printk("( irq = %u )", irq);
+		printk(KERN_INFO "( irq = %u )\n", irq);
 		ret = request_irq(irq, rti800_interrupt, 0, "rti800", dev);
 		if (ret < 0) {
-			printk(" Failed to allocate IRQ\n");
+			printk(KERN_WARNING " Failed to allocate IRQ\n");
 			return ret;
 		}
 		dev->irq = irq;
 	} else {
-		printk("( no irq )");
+		printk(KERN_INFO "( no irq )\n");
 	}
 
 	dev->board_name = this_board->name;
@@ -461,14 +460,12 @@
 	s->type = COMEDI_SUBD_TIMER;
 #endif
 
-	printk("\n");
-
 	return 0;
 }
 
 static int rti800_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: rti800: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: rti800: remove\n", dev->minor);
 
 	if (dev->iobase)
 		release_region(dev->iobase, RTI800_SIZE);
diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
index 2f75c73..2157edc 100644
--- a/drivers/staging/comedi/drivers/rti802.c
+++ b/drivers/staging/comedi/drivers/rti802.c
@@ -106,9 +106,9 @@
 	unsigned long iobase;
 
 	iobase = it->options[0];
-	printk("comedi%d: rti802: 0x%04lx ", dev->minor, iobase);
+	printk(KERN_INFO "comedi%d: rti802: 0x%04lx ", dev->minor, iobase);
 	if (!request_region(iobase, RTI802_SIZE, "rti802")) {
-		printk("I/O port conflict\n");
+		printk(KERN_WARNING "I/O port conflict\n");
 		return -EIO;
 	}
 	dev->iobase = iobase;
@@ -138,14 +138,12 @@
 		    ? &range_unipolar10 : &range_bipolar10;
 	}
 
-	printk("\n");
-
 	return 0;
 }
 
 static int rti802_detach(struct comedi_device *dev)
 {
-	printk("comedi%d: rti802: remove\n", dev->minor);
+	printk(KERN_INFO "comedi%d: rti802: remove\n", dev->minor);
 
 	if (dev->iobase)
 		release_region(dev->iobase, RTI802_SIZE);
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index fdd7ab9..a3cc933 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -140,7 +140,7 @@
 	short allocatedBuf;
 	uint8_t ai_cmd_running;	/*  ai_cmd is running */
 	uint8_t ai_continous;	/*  continous aquisition */
-	int ai_sample_count;	/*  number of samples to aquire */
+	int ai_sample_count;	/*  number of samples to acquire */
 	unsigned int ai_sample_timer;
 	/*  time between samples in  units of the timer */
 	int ai_convert_count;	/*  conversion counter */
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index db37dcd..dd2b903 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -397,7 +397,7 @@
 	char port[20];
 
 	sprintf(port, "/dev/ttyS%d", devpriv->port);
-	devpriv->tty = filp_open(port, 0, O_RDWR);
+	devpriv->tty = filp_open(port, O_RDWR, 0);
 	if (IS_ERR(devpriv->tty)) {
 		printk("serial_2002: file open error = %ld\n",
 		       PTR_ERR(devpriv->tty));
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index 4918fbf..17c92a5 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -300,11 +300,11 @@
 
 	/* read 'old' direction of the port and set bits (out=1, in=0)             */
 	register_buffer = inb(CSCDR);
-	if (data[0] == COMEDI_OUTPUT) {
+	if (data[0] == COMEDI_OUTPUT)
 		register_buffer |= (1 << chan);
-	} else {
+	else
 		register_buffer &= ~(1 << chan);
-	}
+
 	outb(register_buffer, CSCDR);
 
 	return 1;
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 9a1b559..8942ae4 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -95,7 +95,6 @@
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/usb.h>
-#include <linux/smp_lock.h>
 #include <linux/fcntl.h>
 #include <linux/compiler.h>
 #include <linux/firmware.h>
@@ -289,7 +288,7 @@
 	/* continous aquisition */
 	short int ai_continous;
 	short int ao_continous;
-	/* number of samples to aquire */
+	/* number of samples to acquire */
 	int ai_sample_count;
 	int ao_sample_count;
 	/* time between samples in units of the timer */
@@ -2833,7 +2832,7 @@
 };
 
 /* Table with the USB-devices: just now only testing IDs */
-static struct usb_device_id usbduxsub_table[] = {
+static const struct usb_device_id usbduxsub_table[] = {
 	{USB_DEVICE(0x13d8, 0x0001)},
 	{USB_DEVICE(0x13d8, 0x0002)},
 	{}			/* Terminating entry */
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 2e675cc..e89b818 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -44,7 +44,6 @@
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/usb.h>
-#include <linux/smp_lock.h>
 #include <linux/fcntl.h>
 #include <linux/compiler.h>
 #include "comedi_fc.h"
@@ -182,7 +181,7 @@
 						   context */
 	short int ai_cmd_running;	/* asynchronous command is running */
 	short int ai_continous;	/* continous aquisition */
-	long int ai_sample_count;	/* number of samples to aquire */
+	long int ai_sample_count;	/* number of samples to acquire */
 	uint8_t *dux_commands;	/* commands */
 	int ignore;		/* counter which ignores the first
 				   buffers */
@@ -1769,7 +1768,7 @@
 /*
  * Table with the USB-devices: just now only testing IDs
  */
-static struct usb_device_id usbduxfastsub_table[] = {
+static const struct usb_device_id usbduxfastsub_table[] = {
 	/* { USB_DEVICE(0x4b4, 0x8613) }, testing */
 	{USB_DEVICE(0x13d8, 0x0010)},	/* real ID */
 	{USB_DEVICE(0x13d8, 0x0011)},	/* real ID */
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index c34a0b9..6479c38 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -75,7 +75,7 @@
 	DEVICE_VMK8061
 };
 
-static struct usb_device_id vmk80xx_id_table[] = {
+static const struct usb_device_id vmk80xx_id_table[] = {
 	{USB_DEVICE(0x10cf, 0x5500), .driver_info = DEVICE_VMK8055},
 	{USB_DEVICE(0x10cf, 0x5501), .driver_info = DEVICE_VMK8055},
 	{USB_DEVICE(0x10cf, 0x5502), .driver_info = DEVICE_VMK8055},
diff --git a/drivers/staging/crystalhd/Kconfig b/drivers/staging/crystalhd/Kconfig
new file mode 100644
index 0000000..56b414b
--- /dev/null
+++ b/drivers/staging/crystalhd/Kconfig
@@ -0,0 +1,6 @@
+config CRYSTALHD
+	tristate "Broadcom Crystal HD video decoder support"
+	depends on PCI
+	default n
+	help
+	  Support for the Broadcom Crystal HD video decoder chipset
diff --git a/drivers/staging/crystalhd/Makefile b/drivers/staging/crystalhd/Makefile
new file mode 100644
index 0000000..e2af0ce
--- /dev/null
+++ b/drivers/staging/crystalhd/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_CRYSTALHD)	+= crystalhd.o
+
+crystalhd-objs		:= crystalhd_cmds.o	\
+			   crystalhd_hw.o	\
+			   crystalhd_lnx.o	\
+			   crystalhd_misc.o
diff --git a/drivers/staging/crystalhd/TODO b/drivers/staging/crystalhd/TODO
new file mode 100644
index 0000000..69be5d0
--- /dev/null
+++ b/drivers/staging/crystalhd/TODO
@@ -0,0 +1,16 @@
+- Testing
+- Cleanup return codes
+- Cleanup typedefs
+- Cleanup all WIN* references
+- Allocate an Accelerator device class specific Major number,
+  since we don't have any other open sourced accelerators, it is the only
+  one in that category for now.
+  A somewhat similar device is the DXR2/3
+
+Please send patches to:
+Greg Kroah-Hartman <greg@kroah.com>
+Naren Sankar <nsankar@broadcom.com>
+Jarod Wilson <jarod@wilsonet.com>
+Scott Davilla <davilla@4pi.com>
+Manu Abraham <abraham.manu@gmail.com>
+
diff --git a/drivers/staging/crystalhd/bc_dts_defs.h b/drivers/staging/crystalhd/bc_dts_defs.h
new file mode 100644
index 0000000..c34cc07
--- /dev/null
+++ b/drivers/staging/crystalhd/bc_dts_defs.h
@@ -0,0 +1,498 @@
+/********************************************************************
+ * Copyright(c) 2006-2009 Broadcom Corporation.
+ *
+ *  Name: bc_dts_defs.h
+ *
+ *  Description: Common definitions for all components. Only types
+ *		 is allowed to be included from this file.
+ *
+ *  AU
+ *
+ *  HISTORY:
+ *
+ ********************************************************************
+ * This header is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 2.1 of the License.
+ *
+ * This header is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header.  If not, see <http://www.gnu.org/licenses/>.
+ *******************************************************************/
+
+#ifndef _BC_DTS_DEFS_H_
+#define _BC_DTS_DEFS_H_
+
+#include "bc_dts_types.h"
+
+/* BIT Mask */
+#define BC_BIT(_x)		(1 << (_x))
+
+typedef enum _BC_STATUS {
+	BC_STS_SUCCESS		= 0,
+	BC_STS_INV_ARG		= 1,
+	BC_STS_BUSY		= 2,
+	BC_STS_NOT_IMPL		= 3,
+	BC_STS_PGM_QUIT		= 4,
+	BC_STS_NO_ACCESS	= 5,
+	BC_STS_INSUFF_RES	= 6,
+	BC_STS_IO_ERROR		= 7,
+	BC_STS_NO_DATA		= 8,
+	BC_STS_VER_MISMATCH	= 9,
+	BC_STS_TIMEOUT		= 10,
+	BC_STS_FW_CMD_ERR	= 11,
+	BC_STS_DEC_NOT_OPEN	= 12,
+	BC_STS_ERR_USAGE	= 13,
+	BC_STS_IO_USER_ABORT	= 14,
+	BC_STS_IO_XFR_ERROR	= 15,
+	BC_STS_DEC_NOT_STARTED	= 16,
+	BC_STS_FWHEX_NOT_FOUND	= 17,
+	BC_STS_FMT_CHANGE	= 18,
+	BC_STS_HIF_ACCESS	= 19,
+	BC_STS_CMD_CANCELLED	= 20,
+	BC_STS_FW_AUTH_FAILED	= 21,
+	BC_STS_BOOTLOADER_FAILED = 22,
+	BC_STS_CERT_VERIFY_ERROR = 23,
+	BC_STS_DEC_EXIST_OPEN	= 24,
+	BC_STS_PENDING		= 25,
+	BC_STS_CLK_NOCHG	= 26,
+
+	/* Must be the last one.*/
+	BC_STS_ERROR		= -1
+} BC_STATUS;
+
+/*------------------------------------------------------*
+ *    Registry Key Definitions				*
+ *------------------------------------------------------*/
+#define BC_REG_KEY_MAIN_PATH	"Software\\Broadcom\\MediaPC\\70010"
+#define BC_REG_KEY_FWPATH		"FirmwareFilePath"
+#define BC_REG_KEY_SEC_OPT		"DbgOptions"
+
+/*
+ * Options:
+ *
+ *  b[5] = Enable RSA KEY in EEPROM Support
+ *  b[6] = Enable Old PIB scheme. (0 = Use PIB with video scheme)
+ *
+ *  b[12] = Enable send message to NotifyIcon
+ *
+ */
+
+typedef enum _BC_SW_OPTIONS {
+	BC_OPT_DOSER_OUT_ENCRYPT	= BC_BIT(3),
+	BC_OPT_LINK_OUT_ENCRYPT		= BC_BIT(29),
+} BC_SW_OPTIONS;
+
+typedef struct _BC_REG_CONFIG{
+	uint32_t		DbgOptions;
+} BC_REG_CONFIG;
+
+#if defined(__KERNEL__) || defined(__LINUX_USER__)
+#else
+/* Align data structures */
+#define ALIGN(x)	__declspec(align(x))
+#endif
+
+/* mode
+ * b[0]..b[7]	= _DtsDeviceOpenMode
+ * b[8]		=  Load new FW
+ * b[9]		=  Load file play back FW
+ * b[10]	=  Disk format (0 for HD DVD and 1 for BLU ray)
+ * b[11]-b[15]	=  default output resolution
+ * b[16]	=  Skip TX CPB Buffer Check
+ * b[17]	=  Adaptive Output Encrypt/Scramble Scheme
+ * b[18]-b[31]	=  reserved for future use
+ */
+
+/* To allow multiple apps to open the device. */
+enum _DtsDeviceOpenMode {
+	DTS_PLAYBACK_MODE = 0,
+	DTS_DIAG_MODE,
+	DTS_MONITOR_MODE,
+	DTS_HWINIT_MODE
+};
+
+/* To enable the filter to selectively enable/disable fixes or erratas */
+enum _DtsDeviceFixMode {
+	DTS_LOAD_NEW_FW		= BC_BIT(8),
+	DTS_LOAD_FILE_PLAY_FW	= BC_BIT(9),
+	DTS_DISK_FMT_BD		= BC_BIT(10),
+	/* b[11]-b[15] : Default output resolution */
+	DTS_SKIP_TX_CHK_CPB	= BC_BIT(16),
+	DTS_ADAPTIVE_OUTPUT_PER	= BC_BIT(17),
+	DTS_INTELLIMAP		= BC_BIT(18),
+	/* b[19]-b[21] : select clock frequency */
+	DTS_PLAYBACK_DROP_RPT_MODE = BC_BIT(22)
+};
+
+#define DTS_DFLT_RESOLUTION(x)	(x<<11)
+
+#define DTS_DFLT_CLOCK(x) (x<<19)
+
+/* F/W File Version corresponding to S/W Releases */
+enum _FW_FILE_VER {
+	/* S/W release: 02.04.02	F/W release 2.12.2.0 */
+	BC_FW_VER_020402 = ((12<<16) | (2<<8) | (0))
+};
+
+/*------------------------------------------------------*
+ *    Stream Types for DtsOpenDecoder()			*
+ *------------------------------------------------------*/
+enum _DtsOpenDecStreamTypes {
+	BC_STREAM_TYPE_ES		= 0,
+	BC_STREAM_TYPE_PES		= 1,
+	BC_STREAM_TYPE_TS		= 2,
+	BC_STREAM_TYPE_ES_TSTAMP	= 6,
+};
+
+/*------------------------------------------------------*
+ *    Video Algorithms for DtsSetVideoParams()		*
+ *------------------------------------------------------*/
+enum _DtsSetVideoParamsAlgo {
+	BC_VID_ALGO_H264		= 0,
+	BC_VID_ALGO_MPEG2		= 1,
+	BC_VID_ALGO_VC1			= 4,
+	BC_VID_ALGO_VC1MP		= 7,
+};
+
+/*------------------------------------------------------*
+ *    MPEG Extension to the PPB				*
+ *------------------------------------------------------*/
+#define BC_MPEG_VALID_PANSCAN		(1)
+
+typedef struct _BC_PIB_EXT_MPEG {
+	uint32_t	valid;
+	/* Always valid,  defaults to picture size if no
+	 * sequence display extension in the stream. */
+	uint32_t	display_horizontal_size;
+	uint32_t	display_vertical_size;
+
+	/* MPEG_VALID_PANSCAN
+	 * Offsets are a copy values from the MPEG stream. */
+	uint32_t	offset_count;
+	int32_t		horizontal_offset[3];
+	int32_t		vertical_offset[3];
+
+} BC_PIB_EXT_MPEG;
+
+/*------------------------------------------------------*
+ *    H.264 Extension to the PPB			*
+ *------------------------------------------------------*/
+/* Bit definitions for 'other.h264.valid' field */
+#define H264_VALID_PANSCAN		(1)
+#define H264_VALID_SPS_CROP		(2)
+#define H264_VALID_VUI			(4)
+
+typedef struct _BC_PIB_EXT_H264 {
+	/* 'valid' specifies which fields (or sets of
+	 * fields) below are valid.  If the corresponding
+	 * bit in 'valid' is NOT set then that field(s)
+	 * is (are) not initialized. */
+	uint32_t	valid;
+
+	/* H264_VALID_PANSCAN */
+	uint32_t	pan_scan_count;
+	int32_t		pan_scan_left[3];
+	int32_t		pan_scan_right[3];
+	int32_t		pan_scan_top[3];
+	int32_t		pan_scan_bottom[3];
+
+	/* H264_VALID_SPS_CROP */
+	int32_t		sps_crop_left;
+	int32_t		sps_crop_right;
+	int32_t		sps_crop_top;
+	int32_t		sps_crop_bottom;
+
+	/* H264_VALID_VUI */
+	uint32_t	chroma_top;
+	uint32_t	chroma_bottom;
+
+} BC_PIB_EXT_H264;
+
+/*------------------------------------------------------*
+ *    VC1 Extension to the PPB				*
+ *------------------------------------------------------*/
+#define VC1_VALID_PANSCAN		(1)
+
+typedef struct _BC_PIB_EXT_VC1 {
+	uint32_t	valid;
+
+	/* Always valid, defaults to picture size if no
+	 * sequence display extension in the stream. */
+	uint32_t	display_horizontal_size;
+	uint32_t	display_vertical_size;
+
+	/* VC1 pan scan windows */
+	uint32_t	num_panscan_windows;
+	int32_t		ps_horiz_offset[4];
+	int32_t		ps_vert_offset[4];
+	int32_t		ps_width[4];
+	int32_t		ps_height[4];
+
+} BC_PIB_EXT_VC1;
+
+
+/*------------------------------------------------------*
+ *    Picture Information Block				*
+ *------------------------------------------------------*/
+#if defined(_WIN32) || defined(_WIN64) || defined(__LINUX_USER__)
+/* Values for 'pulldown' field.  '0' means no pulldown information
+ * was present for this picture. */
+enum {
+	vdecNoPulldownInfo	= 0,
+	vdecTop			= 1,
+	vdecBottom		= 2,
+	vdecTopBottom		= 3,
+	vdecBottomTop		= 4,
+	vdecTopBottomTop	= 5,
+	vdecBottomTopBottom	= 6,
+	vdecFrame_X2		= 7,
+	vdecFrame_X3		= 8,
+	vdecFrame_X1		= 9,
+	vdecFrame_X4		= 10,
+};
+
+/* Values for the 'frame_rate' field. */
+enum {
+	vdecFrameRateUnknown = 0,
+	vdecFrameRate23_97,
+	vdecFrameRate24,
+	vdecFrameRate25,
+	vdecFrameRate29_97,
+	vdecFrameRate30,
+	vdecFrameRate50,
+	vdecFrameRate59_94,
+	vdecFrameRate60,
+};
+
+/* Values for the 'aspect_ratio' field. */
+enum {
+	vdecAspectRatioUnknown = 0,
+	vdecAspectRatioSquare,
+	vdecAspectRatio12_11,
+	vdecAspectRatio10_11,
+	vdecAspectRatio16_11,
+	vdecAspectRatio40_33,
+	vdecAspectRatio24_11,
+	vdecAspectRatio20_11,
+	vdecAspectRatio32_11,
+	vdecAspectRatio80_33,
+	vdecAspectRatio18_11,
+	vdecAspectRatio15_11,
+	vdecAspectRatio64_33,
+	vdecAspectRatio160_99,
+	vdecAspectRatio4_3,
+	vdecAspectRatio16_9,
+	vdecAspectRatio221_1,
+	vdecAspectRatioOther = 255,
+};
+
+/* Values for the 'colour_primaries' field. */
+enum {
+	vdecColourPrimariesUnknown = 0,
+	vdecColourPrimariesBT709,
+	vdecColourPrimariesUnspecified,
+	vdecColourPrimariesReserved,
+	vdecColourPrimariesBT470_2M = 4,
+	vdecColourPrimariesBT470_2BG,
+	vdecColourPrimariesSMPTE170M,
+	vdecColourPrimariesSMPTE240M,
+	vdecColourPrimariesGenericFilm,
+};
+
+enum {
+	vdecRESOLUTION_CUSTOM	= 0x00000000, /* custom */
+	vdecRESOLUTION_480i	= 0x00000001, /* 480i */
+	vdecRESOLUTION_1080i	= 0x00000002, /* 1080i (1920x1080, 60i) */
+	vdecRESOLUTION_NTSC	= 0x00000003, /* NTSC (720x483, 60i) */
+	vdecRESOLUTION_480p	= 0x00000004, /* 480p (720x480, 60p) */
+	vdecRESOLUTION_720p	= 0x00000005, /* 720p (1280x720, 60p) */
+	vdecRESOLUTION_PAL1	= 0x00000006, /* PAL_1 (720x576, 50i) */
+	vdecRESOLUTION_1080i25	= 0x00000007, /* 1080i25 (1920x1080, 50i) */
+	vdecRESOLUTION_720p50	= 0x00000008, /* 720p50 (1280x720, 50p) */
+	vdecRESOLUTION_576p	= 0x00000009, /* 576p (720x576, 50p) */
+	vdecRESOLUTION_1080i29_97 = 0x0000000A, /* 1080i (1920x1080, 59.94i) */
+	vdecRESOLUTION_720p59_94  = 0x0000000B, /* 720p (1280x720, 59.94p) */
+	vdecRESOLUTION_SD_DVD	= 0x0000000C, /* SD DVD (720x483, 60i) */
+	vdecRESOLUTION_480p656	= 0x0000000D, /* 480p (720x480, 60p), output bus width 8 bit, clock 74.25MHz */
+	vdecRESOLUTION_1080p23_976 = 0x0000000E, /* 1080p23_976 (1920x1080, 23.976p) */
+	vdecRESOLUTION_720p23_976  = 0x0000000F, /* 720p23_976 (1280x720p, 23.976p) */
+	vdecRESOLUTION_240p29_97   = 0x00000010, /* 240p (1440x240, 29.97p ) */
+	vdecRESOLUTION_240p30	= 0x00000011, /* 240p (1440x240, 30p) */
+	vdecRESOLUTION_288p25	= 0x00000012, /* 288p (1440x288p, 25p) */
+	vdecRESOLUTION_1080p29_97 = 0x00000013, /* 1080p29_97 (1920x1080, 29.97p) */
+	vdecRESOLUTION_1080p30	= 0x00000014, /* 1080p30 (1920x1080, 30p) */
+	vdecRESOLUTION_1080p24	= 0x00000015, /* 1080p24 (1920x1080, 24p) */
+	vdecRESOLUTION_1080p25	= 0x00000016, /* 1080p25 (1920x1080, 25p) */
+	vdecRESOLUTION_720p24	= 0x00000017, /* 720p24 (1280x720, 25p) */
+	vdecRESOLUTION_720p29_97  = 0x00000018, /* 720p29.97 (1280x720, 29.97p) */
+	vdecRESOLUTION_480p23_976 = 0x00000019, /* 480p23.976 (720*480, 23.976) */
+	vdecRESOLUTION_480p29_97  = 0x0000001A, /* 480p29.976 (720*480, 29.97p) */
+	vdecRESOLUTION_576p25	= 0x0000001B, /* 576p25 (720*576, 25p) */
+	/* For Zero Frame Rate */
+	vdecRESOLUTION_480p0	= 0x0000001C, /* 480p (720x480, 0p) */
+	vdecRESOLUTION_480i0	= 0x0000001D, /* 480i (720x480, 0i) */
+	vdecRESOLUTION_576p0	= 0x0000001E, /* 576p (720x576, 0p) */
+	vdecRESOLUTION_720p0	= 0x0000001F, /* 720p (1280x720, 0p) */
+	vdecRESOLUTION_1080p0	= 0x00000020, /* 1080p (1920x1080, 0p) */
+	vdecRESOLUTION_1080i0	= 0x00000021, /* 1080i (1920x1080, 0i) */
+};
+
+/* Bit definitions for 'flags' field */
+#define VDEC_FLAG_EOS				(0x0004)
+
+#define VDEC_FLAG_FRAME				(0x0000)
+#define VDEC_FLAG_FIELDPAIR			(0x0008)
+#define VDEC_FLAG_TOPFIELD			(0x0010)
+#define VDEC_FLAG_BOTTOMFIELD			(0x0018)
+
+#define VDEC_FLAG_PROGRESSIVE_SRC		(0x0000)
+#define VDEC_FLAG_INTERLACED_SRC		(0x0020)
+#define VDEC_FLAG_UNKNOWN_SRC			(0x0040)
+
+#define VDEC_FLAG_BOTTOM_FIRST			(0x0080)
+#define VDEC_FLAG_LAST_PICTURE			(0x0100)
+
+#define VDEC_FLAG_PICTURE_META_DATA_PRESENT	(0x40000)
+
+#endif /* _WIN32 || _WIN64 */
+
+enum _BC_OUTPUT_FORMAT {
+	MODE420				= 0x0,
+	MODE422_YUY2			= 0x1,
+	MODE422_UYVY			= 0x2,
+};
+
+typedef struct _BC_PIC_INFO_BLOCK {
+	/* Common fields. */
+	uint64_t	timeStamp;	/* Timestamp */
+	uint32_t	picture_number;	/* Ordinal display number  */
+	uint32_t	width;		/* pixels	    */
+	uint32_t	height;		/* pixels	    */
+	uint32_t	chroma_format;	/* 0x420, 0x422 or 0x444 */
+	uint32_t	pulldown;
+	uint32_t	flags;
+	uint32_t	frame_rate;
+	uint32_t	aspect_ratio;
+	uint32_t	colour_primaries;
+	uint32_t	picture_meta_payload;
+	uint32_t	sess_num;
+	uint32_t	ycom;
+	uint32_t	custom_aspect_ratio_width_height;
+	uint32_t	n_drop;	/* number of non-reference frames remaining to be dropped */
+
+	/* Protocol-specific extensions. */
+	union {
+		BC_PIB_EXT_H264	h264;
+		BC_PIB_EXT_MPEG	mpeg;
+		BC_PIB_EXT_VC1	 vc1;
+	} other;
+
+} BC_PIC_INFO_BLOCK, *PBC_PIC_INFO_BLOCK;
+
+/*------------------------------------------------------*
+ *    ProcOut Info					*
+ *------------------------------------------------------*/
+/* Optional flags for ProcOut Interface.*/
+enum _POUT_OPTIONAL_IN_FLAGS_{
+	/* Flags from App to Device */
+	BC_POUT_FLAGS_YV12	  = 0x01,	/* Copy Data in YV12 format */
+	BC_POUT_FLAGS_STRIDE	  = 0x02,	/* Stride size is valid. */
+	BC_POUT_FLAGS_SIZE	  = 0x04,	/* Take size information from Application */
+	BC_POUT_FLAGS_INTERLACED  = 0x08,	/* copy only half the bytes */
+	BC_POUT_FLAGS_INTERLEAVED = 0x10,	/* interleaved frame */
+
+	/* Flags from Device to APP */
+	BC_POUT_FLAGS_FMT_CHANGE  = 0x10000,	/* Data is not VALID when this flag is set */
+	BC_POUT_FLAGS_PIB_VALID	  = 0x20000,	/* PIB Information valid */
+	BC_POUT_FLAGS_ENCRYPTED	  = 0x40000,	/* Data is encrypted. */
+	BC_POUT_FLAGS_FLD_BOT	  = 0x80000,	/* Bottom Field data */
+};
+
+#if defined(__KERNEL__) || defined(__LINUX_USER__)
+typedef BC_STATUS(*dts_pout_callback)(void  *shnd, uint32_t width, uint32_t height, uint32_t stride, void *pOut);
+#else
+typedef BC_STATUS(*dts_pout_callback)(void  *shnd, uint32_t width, uint32_t height, uint32_t stride, struct _BC_DTS_PROC_OUT *pOut);
+#endif
+
+/* Line 21 Closed Caption */
+/* User Data */
+#define MAX_UD_SIZE		1792	/* 1920 - 128 */
+
+typedef struct _BC_DTS_PROC_OUT {
+	uint8_t		*Ybuff;			/* Caller Supplied buffer for Y data */
+	uint32_t	YbuffSz;		/* Caller Supplied Y buffer size */
+	uint32_t	YBuffDoneSz;		/* Transferred Y datasize */
+
+	uint8_t		*UVbuff;		/* Caller Supplied buffer for UV data */
+	uint32_t	UVbuffSz;		/* Caller Supplied UV buffer size */
+	uint32_t	UVBuffDoneSz;		/* Transferred UV data size */
+
+	uint32_t	StrideSz;		/* Caller supplied Stride Size */
+	uint32_t	PoutFlags;		/* Call IN Flags */
+
+	uint32_t	discCnt;		/* Picture discontinuity count */
+
+	BC_PIC_INFO_BLOCK PicInfo;		/* Picture Information Block Data */
+
+	/* Line 21 Closed Caption */
+	/* User Data */
+	uint32_t	UserDataSz;
+	uint8_t		UserData[MAX_UD_SIZE];
+
+	void		*hnd;
+	dts_pout_callback AppCallBack;
+	uint8_t		DropFrames;
+	uint8_t		b422Mode;		/* Picture output Mode */
+	uint8_t		bPibEnc;		/* PIB encrypted */
+	uint8_t		bRevertScramble;
+
+} BC_DTS_PROC_OUT;
+
+typedef struct _BC_DTS_STATUS {
+	uint8_t		ReadyListCount;	/* Number of frames in ready list (reported by driver) */
+	uint8_t		FreeListCount;	/* Number of frame buffers free.  (reported by driver) */
+	uint8_t		PowerStateChange; /* Number of active state power transitions (reported by driver) */
+	uint8_t		reserved_[1];
+
+	uint32_t	FramesDropped;	/* Number of frames dropped.  (reported by DIL) */
+	uint32_t	FramesCaptured;	/* Number of frames captured. (reported by DIL) */
+	uint32_t	FramesRepeated;	/* Number of frames repeated. (reported by DIL) */
+
+	uint32_t	InputCount;	/* Times compressed video has been sent to the HW.
+					 * i.e. Successful DtsProcInput() calls (reported by DIL) */
+	uint64_t	InputTotalSize;	/* Amount of compressed video that has been sent to the HW.
+					 * (reported by DIL) */
+	uint32_t	InputBusyCount;	/* Times compressed video has attempted to be sent to the HW
+					 * but the input FIFO was full. (reported by DIL) */
+
+	uint32_t	PIBMissCount;	/* Amount of times a PIB is invalid. (reported by DIL) */
+
+	uint32_t	cpbEmptySize;	/* supported only for H.264, specifically changed for
+					 * Adobe. Report size of CPB buffer available.
+					 * Reported by DIL */
+	uint64_t	NextTimeStamp;	/* TimeStamp of the next picture that will be returned
+					 * by a call to ProcOutput. Added for Adobe. Reported
+					 * back from the driver */
+	uint8_t		reserved__[16];
+
+} BC_DTS_STATUS;
+
+#define BC_SWAP32(_v)			\
+	((((_v) & 0xFF000000)>>24)|	\
+	  (((_v) & 0x00FF0000)>>8)|	\
+	  (((_v) & 0x0000FF00)<<8)|	\
+	  (((_v) & 0x000000FF)<<24))
+
+#define WM_AGENT_TRAYICON_DECODER_OPEN	10001
+#define WM_AGENT_TRAYICON_DECODER_CLOSE	10002
+#define WM_AGENT_TRAYICON_DECODER_START	10003
+#define WM_AGENT_TRAYICON_DECODER_STOP	10004
+#define WM_AGENT_TRAYICON_DECODER_RUN	10005
+#define WM_AGENT_TRAYICON_DECODER_PAUSE	10006
+
+
+#endif	/* _BC_DTS_DEFS_H_ */
diff --git a/drivers/staging/crystalhd/bc_dts_glob_lnx.h b/drivers/staging/crystalhd/bc_dts_glob_lnx.h
new file mode 100644
index 0000000..b3125e3
--- /dev/null
+++ b/drivers/staging/crystalhd/bc_dts_glob_lnx.h
@@ -0,0 +1,299 @@
+/********************************************************************
+ * Copyright(c) 2006-2009 Broadcom Corporation.
+ *
+ *  Name: bc_dts_glob_lnx.h
+ *
+ *  Description: Wrapper to Windows dts_glob.h for Link-Linux usage.
+ *		 The idea is to define additional Linux related defs
+ *		 in this file to avoid changes to existing Windows
+ *		 glob file.
+ *
+ *  AU
+ *
+ *  HISTORY:
+ *
+ ********************************************************************
+ * This header is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 2.1 of the License.
+ *
+ * This header is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header.  If not, see <http://www.gnu.org/licenses/>.
+ *******************************************************************/
+
+#ifndef _BC_DTS_GLOB_LNX_H_
+#define _BC_DTS_GLOB_LNX_H_
+
+#ifdef __LINUX_USER__
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <time.h>
+#include <arpa/inet.h>
+#include <asm/param.h>
+#include <linux/ioctl.h>
+#include <sys/select.h>
+
+#define DRVIFLIB_INT_API
+
+#endif
+
+#include "bc_dts_defs.h"
+#include "bcm_70012_regs.h"	/* Link Register defs */
+
+#define CRYSTALHD_API_NAME	"crystalhd"
+#define CRYSTALHD_API_DEV_NAME	"/dev/crystalhd"
+
+/*
+ * These are SW stack tunable parameters shared
+ * between the driver and the application.
+ */
+enum _BC_DTS_GLOBALS {
+	BC_MAX_FW_CMD_BUFF_SZ	= 0x40,		/* FW passthrough cmd/rsp buffer size */
+	PCI_CFG_SIZE		= 256,		/* PCI config size buffer */
+	BC_IOCTL_DATA_POOL_SIZE	= 8,		/* BC_IOCTL_DATA Pool size */
+	BC_LINK_MAX_OPENS	= 3,		/* Maximum simultaneous opens*/
+	BC_LINK_MAX_SGLS	= 1024,		/* Maximum SG elements 4M/4K */
+	BC_TX_LIST_CNT		= 2,		/* Max Tx DMA Rings */
+	BC_RX_LIST_CNT		= 8,		/* Max Rx DMA Rings*/
+	BC_PROC_OUTPUT_TIMEOUT	= 3000,		/* Milliseconds */
+	BC_INFIFO_THRESHOLD	= 0x10000,
+};
+
+typedef struct _BC_CMD_REG_ACC {
+	uint32_t		Offset;
+	uint32_t		Value;
+} BC_CMD_REG_ACC;
+
+typedef struct _BC_CMD_DEV_MEM {
+	uint32_t		StartOff;
+	uint32_t		NumDwords;
+	uint32_t		Rsrd;
+} BC_CMD_DEV_MEM;
+
+/* FW Passthrough command structure */
+enum _bc_fw_cmd_flags {
+	BC_FW_CMD_FLAGS_NONE	= 0,
+	BC_FW_CMD_PIB_QS	= 0x01,
+};
+
+typedef struct _BC_FW_CMD {
+	uint32_t		cmd[BC_MAX_FW_CMD_BUFF_SZ];
+	uint32_t		rsp[BC_MAX_FW_CMD_BUFF_SZ];
+	uint32_t		flags;
+	uint32_t		add_data;
+} BC_FW_CMD, *PBC_FW_CMD;
+
+typedef struct _BC_HW_TYPE {
+	uint16_t		PciDevId;
+	uint16_t		PciVenId;
+	uint8_t			HwRev;
+	uint8_t			Align[3];
+} BC_HW_TYPE;
+
+typedef struct _BC_PCI_CFG {
+	uint32_t		Size;
+	uint32_t		Offset;
+	uint8_t			pci_cfg_space[PCI_CFG_SIZE];
+} BC_PCI_CFG;
+
+typedef struct _BC_VERSION_INFO_ {
+	uint8_t			DriverMajor;
+	uint8_t			DriverMinor;
+	uint16_t		DriverRevision;
+} BC_VERSION_INFO;
+
+typedef struct _BC_START_RX_CAP_ {
+	uint32_t		Rsrd;
+	uint32_t		StartDeliveryThsh;
+	uint32_t		PauseThsh;
+	uint32_t		ResumeThsh;
+} BC_START_RX_CAP;
+
+typedef struct _BC_FLUSH_RX_CAP_ {
+	uint32_t		Rsrd;
+	uint32_t		bDiscardOnly;
+} BC_FLUSH_RX_CAP;
+
+typedef struct _BC_DTS_STATS {
+	uint8_t			drvRLL;
+	uint8_t			drvFLL;
+	uint8_t			eosDetected;
+	uint8_t			pwr_state_change;
+
+	/* Stats from App */
+	uint32_t		opFrameDropped;
+	uint32_t		opFrameCaptured;
+	uint32_t		ipSampleCnt;
+	uint64_t		ipTotalSize;
+	uint32_t		reptdFrames;
+	uint32_t		pauseCount;
+	uint32_t		pibMisses;
+	uint32_t		discCounter;
+
+	/* Stats from Driver */
+	uint32_t		TxFifoBsyCnt;
+	uint32_t		intCount;
+	uint32_t		DrvIgnIntrCnt;
+	uint32_t		DrvTotalFrmDropped;
+	uint32_t		DrvTotalHWErrs;
+	uint32_t		DrvTotalPIBFlushCnt;
+	uint32_t		DrvTotalFrmCaptured;
+	uint32_t		DrvPIBMisses;
+	uint32_t		DrvPauseTime;
+	uint32_t		DrvRepeatedFrms;
+	uint32_t		res1[13];
+
+} BC_DTS_STATS;
+
+typedef struct _BC_PROC_INPUT_ {
+	uint8_t			*pDmaBuff;
+	uint32_t		BuffSz;
+	uint8_t			Mapped;
+	uint8_t			Encrypted;
+	uint8_t			Rsrd[2];
+	uint32_t		DramOffset;	/* For debug use only */
+} BC_PROC_INPUT, *PBC_PROC_INPUT;
+
+typedef struct _BC_DEC_YUV_BUFFS {
+	uint32_t		b422Mode;
+	uint8_t			*YuvBuff;
+	uint32_t		YuvBuffSz;
+	uint32_t		UVbuffOffset;
+	uint32_t		YBuffDoneSz;
+	uint32_t		UVBuffDoneSz;
+	uint32_t		RefCnt;
+} BC_DEC_YUV_BUFFS;
+
+enum _DECOUT_COMPLETION_FLAGS{
+	COMP_FLAG_NO_INFO	= 0x00,
+	COMP_FLAG_FMT_CHANGE	= 0x01,
+	COMP_FLAG_PIB_VALID	= 0x02,
+	COMP_FLAG_DATA_VALID	= 0x04,
+	COMP_FLAG_DATA_ENC	= 0x08,
+	COMP_FLAG_DATA_BOT	= 0x10,
+};
+
+typedef struct _BC_DEC_OUT_BUFF{
+	BC_DEC_YUV_BUFFS	OutPutBuffs;
+	BC_PIC_INFO_BLOCK	PibInfo;
+	uint32_t		Flags;
+	uint32_t		BadFrCnt;
+} BC_DEC_OUT_BUFF;
+
+typedef struct _BC_NOTIFY_MODE {
+	uint32_t		Mode;
+	uint32_t		Rsvr[3];
+} BC_NOTIFY_MODE;
+
+typedef struct _BC_CLOCK {
+	uint32_t		clk;
+	uint32_t		Rsvr[3];
+} BC_CLOCK;
+
+typedef struct _BC_IOCTL_DATA {
+	BC_STATUS		RetSts;
+	uint32_t		IoctlDataSz;
+	uint32_t		Timeout;
+	union {
+		BC_CMD_REG_ACC		regAcc;
+		BC_CMD_DEV_MEM		devMem;
+		BC_FW_CMD		fwCmd;
+		BC_HW_TYPE		hwType;
+		BC_PCI_CFG		pciCfg;
+		BC_VERSION_INFO		VerInfo;
+		BC_PROC_INPUT		ProcInput;
+		BC_DEC_YUV_BUFFS	RxBuffs;
+		BC_DEC_OUT_BUFF		DecOutData;
+		BC_START_RX_CAP		RxCap;
+		BC_FLUSH_RX_CAP		FlushRxCap;
+		BC_DTS_STATS		drvStat;
+		BC_NOTIFY_MODE		NotifyMode;
+		BC_CLOCK			clockValue;
+	} u;
+	struct _BC_IOCTL_DATA	*next;
+} BC_IOCTL_DATA;
+
+typedef enum _BC_DRV_CMD{
+	DRV_CMD_VERSION = 0,	/* Get SW version */
+	DRV_CMD_GET_HWTYPE,	/* Get HW version and type Dozer/Tank */
+	DRV_CMD_REG_RD,		/* Read Device Register */
+	DRV_CMD_REG_WR,		/* Write Device Register */
+	DRV_CMD_FPGA_RD,	/* Read FPGA Register */
+	DRV_CMD_FPGA_WR,	/* Wrtie FPGA Reister */
+	DRV_CMD_MEM_RD,		/* Read Device Memory */
+	DRV_CMD_MEM_WR,		/* Write Device Memory */
+	DRV_CMD_RD_PCI_CFG,	/* Read PCI Config Space */
+	DRV_CMD_WR_PCI_CFG,	/* Write the PCI Configuration Space*/
+	DRV_CMD_FW_DOWNLOAD,	/* Download Firmware */
+	DRV_ISSUE_FW_CMD,	/* Issue FW Cmd (pass through mode) */
+	DRV_CMD_PROC_INPUT,	/* Process Input Sample */
+	DRV_CMD_ADD_RXBUFFS,	/* Add Rx side buffers to driver pool */
+	DRV_CMD_FETCH_RXBUFF,	/* Get Rx DMAed buffer */
+	DRV_CMD_START_RX_CAP,	/* Start Rx Buffer Capture */
+	DRV_CMD_FLUSH_RX_CAP,	/* Stop the capture for now...we will enhance this later*/
+	DRV_CMD_GET_DRV_STAT,	/* Get Driver Internal Statistics */
+	DRV_CMD_RST_DRV_STAT,	/* Reset Driver Internal Statistics */
+	DRV_CMD_NOTIFY_MODE,	/* Notify the Mode to driver in which the application is Operating*/
+	DRV_CMD_CHANGE_CLOCK,	/* Change the core clock to either save power or improve performance */
+
+	/* MUST be the last one.. */
+	DRV_CMD_END,			/* End of the List.. */
+} BC_DRV_CMD;
+
+#define BC_IOC_BASE		'b'
+#define BC_IOC_VOID		_IOC_NONE
+#define BC_IOC_IOWR(nr, type)	_IOWR(BC_IOC_BASE, nr, type)
+#define BC_IOCTL_MB		BC_IOCTL_DATA
+
+#define	BCM_IOC_GET_VERSION	BC_IOC_IOWR(DRV_CMD_VERSION, BC_IOCTL_MB)
+#define	BCM_IOC_GET_HWTYPE	BC_IOC_IOWR(DRV_CMD_GET_HWTYPE, BC_IOCTL_MB)
+#define	BCM_IOC_REG_RD		BC_IOC_IOWR(DRV_CMD_REG_RD, BC_IOCTL_MB)
+#define	BCM_IOC_REG_WR		BC_IOC_IOWR(DRV_CMD_REG_WR, BC_IOCTL_MB)
+#define	BCM_IOC_MEM_RD		BC_IOC_IOWR(DRV_CMD_MEM_RD, BC_IOCTL_MB)
+#define	BCM_IOC_MEM_WR		BC_IOC_IOWR(DRV_CMD_MEM_WR, BC_IOCTL_MB)
+#define BCM_IOC_FPGA_RD		BC_IOC_IOWR(DRV_CMD_FPGA_RD, BC_IOCTL_MB)
+#define BCM_IOC_FPGA_WR		BC_IOC_IOWR(DRV_CMD_FPGA_WR, BC_IOCTL_MB)
+#define	BCM_IOC_RD_PCI_CFG	BC_IOC_IOWR(DRV_CMD_RD_PCI_CFG, BC_IOCTL_MB)
+#define	BCM_IOC_WR_PCI_CFG	BC_IOC_IOWR(DRV_CMD_WR_PCI_CFG, BC_IOCTL_MB)
+#define BCM_IOC_PROC_INPUT	BC_IOC_IOWR(DRV_CMD_PROC_INPUT, BC_IOCTL_MB)
+#define BCM_IOC_ADD_RXBUFFS	BC_IOC_IOWR(DRV_CMD_ADD_RXBUFFS, BC_IOCTL_MB)
+#define BCM_IOC_FETCH_RXBUFF	BC_IOC_IOWR(DRV_CMD_FETCH_RXBUFF, BC_IOCTL_MB)
+#define	BCM_IOC_FW_CMD		BC_IOC_IOWR(DRV_ISSUE_FW_CMD, BC_IOCTL_MB)
+#define	BCM_IOC_START_RX_CAP	BC_IOC_IOWR(DRV_CMD_START_RX_CAP, BC_IOCTL_MB)
+#define BCM_IOC_FLUSH_RX_CAP	BC_IOC_IOWR(DRV_CMD_FLUSH_RX_CAP, BC_IOCTL_MB)
+#define BCM_IOC_GET_DRV_STAT	BC_IOC_IOWR(DRV_CMD_GET_DRV_STAT, BC_IOCTL_MB)
+#define BCM_IOC_RST_DRV_STAT	BC_IOC_IOWR(DRV_CMD_RST_DRV_STAT, BC_IOCTL_MB)
+#define BCM_IOC_NOTIFY_MODE	BC_IOC_IOWR(DRV_CMD_NOTIFY_MODE, BC_IOCTL_MB)
+#define	BCM_IOC_FW_DOWNLOAD	BC_IOC_IOWR(DRV_CMD_FW_DOWNLOAD, BC_IOCTL_MB)
+#define BCM_IOC_CHG_CLK		BC_IOC_IOWR(DRV_CMD_CHANGE_CLOCK, BC_IOCTL_MB)
+#define	BCM_IOC_END		BC_IOC_VOID
+
+/* Wrapper for main IOCTL data */
+typedef struct _crystalhd_ioctl_data {
+	BC_IOCTL_DATA		udata;		/* IOCTL from App..*/
+	uint32_t		u_id;		/* Driver specific user ID */
+	uint32_t		cmd;		/* Cmd ID for driver's use. */
+	void			*add_cdata;	/* Additional command specific data..*/
+	uint32_t		add_cdata_sz;	/* Additional command specific data size */
+	struct _crystalhd_ioctl_data *next;	/* List/Fifo management */
+} crystalhd_ioctl_data;
+
+
+enum _crystalhd_kmod_ver{
+	crystalhd_kmod_major	= 0,
+	crystalhd_kmod_minor	= 9,
+	crystalhd_kmod_rev	= 27,
+};
+
+#endif
diff --git a/drivers/staging/crystalhd/bc_dts_types.h b/drivers/staging/crystalhd/bc_dts_types.h
new file mode 100644
index 0000000..ac0c817
--- /dev/null
+++ b/drivers/staging/crystalhd/bc_dts_types.h
@@ -0,0 +1,121 @@
+/********************************************************************
+ * Copyright(c) 2006-2009 Broadcom Corporation.
+ *
+ *  Name: bc_dts_types.h
+ *
+ *  Description: Data types
+ *
+ *  AU
+ *
+ *  HISTORY:
+ *
+ ********************************************************************
+ * This header is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 2.1 of the License.
+ *
+ * This header is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header.  If not, see <http://www.gnu.org/licenses/>.
+ *******************************************************************/
+
+#ifndef _BC_DTS_TYPES_H_
+#define _BC_DTS_TYPES_H_
+
+#ifdef __LINUX_USER__  // Don't include these for KERNEL..
+#include <stdint.h>
+#endif
+
+#if defined(_WIN64) || defined(_WIN32)
+typedef uint32_t		U32;
+typedef int32_t			S32;
+typedef uint16_t		U16;
+typedef int16_t			S16;
+typedef unsigned char		U8;
+typedef char			S8;
+#endif
+
+#ifndef PVOID
+typedef void	*PVOID;
+#endif
+
+#ifndef BOOL
+typedef int	BOOL;
+#endif
+
+#ifdef WIN32
+    typedef unsigned __int64	U64;
+#elif defined(_WIN64)
+    typedef uint64_t U64;
+#endif
+
+#ifdef _WIN64
+#if !(defined(POINTER_32))
+#define POINTER_32	__ptr32
+#endif
+#else	/* _WIN32 */
+#define POINTER_32
+#endif
+
+#if defined(__KERNEL__) || defined(__LINUX_USER__)
+
+#ifdef __LINUX_USER__	/* Don't include these for KERNEL */
+typedef uint32_t	ULONG;
+typedef int32_t		LONG;
+typedef void		*HANDLE;
+#ifndef VOID
+typedef void		VOID;
+#endif
+typedef void		*LPVOID;
+typedef uint32_t	DWORD;
+typedef uint32_t	UINT32;
+typedef uint32_t	*LPDWORD;
+typedef unsigned char	*PUCHAR;
+
+#ifndef TRUE
+	#define TRUE		1
+#endif
+
+#ifndef FALSE
+	#define FALSE		0
+#endif
+
+#define TEXT
+
+#else
+
+/* For Kernel usage.. */
+typedef bool	bc_bool_t;
+#endif
+
+#else
+
+#ifndef uint64_t
+typedef struct _uint64_t {
+	uint32_t low_dw;
+	uint32_t hi_dw;
+} uint64_t;
+#endif
+
+#ifndef int32_t
+typedef signed long		int32_t;
+#endif
+
+#ifndef uint32_t
+typedef unsigned long	uint32_t;
+#endif
+
+#ifndef uint16_t
+typedef unsigned short	uint16_t;
+#endif
+
+#ifndef uint8_t
+typedef unsigned char	uint8_t;
+#endif
+#endif
+
+#endif
+
diff --git a/drivers/staging/crystalhd/bcm_70012_regs.h b/drivers/staging/crystalhd/bcm_70012_regs.h
new file mode 100644
index 0000000..6922f54
--- /dev/null
+++ b/drivers/staging/crystalhd/bcm_70012_regs.h
@@ -0,0 +1,757 @@
+/***************************************************************************
+ * Copyright (c) 1999-2009, Broadcom Corporation.
+ *
+ *  Name: bcm_70012_regs.h
+ *
+ *  Description: BCM70012 registers
+ *
+ ********************************************************************
+ * This header is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 2.1 of the License.
+ *
+ * This header is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header.  If not, see <http://www.gnu.org/licenses/>.
+ ***************************************************************************/
+
+#ifndef MACFILE_H__
+#define MACFILE_H__
+
+/**
+ * m = memory, c = core, r = register, f = field, d = data.
+ */
+#if !defined(GET_FIELD) && !defined(SET_FIELD)
+#define BRCM_ALIGN(c,r,f)   c##_##r##_##f##_ALIGN
+#define BRCM_BITS(c,r,f)    c##_##r##_##f##_BITS
+#define BRCM_MASK(c,r,f)    c##_##r##_##f##_MASK
+#define BRCM_SHIFT(c,r,f)   c##_##r##_##f##_SHIFT
+
+#define GET_FIELD(m,c,r,f) \
+	((((m) & BRCM_MASK(c,r,f)) >> BRCM_SHIFT(c,r,f)) << BRCM_ALIGN(c,r,f))
+
+#define SET_FIELD(m,c,r,f,d) \
+	((m) = (((m) & ~BRCM_MASK(c,r,f)) | ((((d) >> BRCM_ALIGN(c,r,f)) << \
+	 BRCM_SHIFT(c,r,f)) & BRCM_MASK(c,r,f))) \
+	)
+
+#define SET_TYPE_FIELD(m,c,r,f,d) SET_FIELD(m,c,r,f,c##_##d)
+#define SET_NAME_FIELD(m,c,r,f,d) SET_FIELD(m,c,r,f,c##_##r##_##f##_##d)
+#define SET_VALUE_FIELD(m,c,r,f,d) SET_FIELD(m,c,r,f,d)
+
+#endif /* GET & SET */
+
+/****************************************************************************
+ * Core Enums.
+ ***************************************************************************/
+/****************************************************************************
+ * Enums: AES_RGR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define AES_RGR_BRIDGE_RESET_CTRL_DEASSERT                 0
+#define AES_RGR_BRIDGE_RESET_CTRL_ASSERT                   1
+
+/****************************************************************************
+ * Enums: CCE_RGR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define CCE_RGR_BRIDGE_RESET_CTRL_DEASSERT                 0
+#define CCE_RGR_BRIDGE_RESET_CTRL_ASSERT                   1
+
+/****************************************************************************
+ * Enums: DBU_RGR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define DBU_RGR_BRIDGE_RESET_CTRL_DEASSERT                 0
+#define DBU_RGR_BRIDGE_RESET_CTRL_ASSERT                   1
+
+/****************************************************************************
+ * Enums: DCI_RGR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define DCI_RGR_BRIDGE_RESET_CTRL_DEASSERT                 0
+#define DCI_RGR_BRIDGE_RESET_CTRL_ASSERT                   1
+
+/****************************************************************************
+ * Enums: GISB_ARBITER_DEASSERT_ASSERT
+ ***************************************************************************/
+#define GISB_ARBITER_DEASSERT_ASSERT_DEASSERT              0
+#define GISB_ARBITER_DEASSERT_ASSERT_ASSERT                1
+
+/****************************************************************************
+ * Enums: GISB_ARBITER_UNMASK_MASK
+ ***************************************************************************/
+#define GISB_ARBITER_UNMASK_MASK_UNMASK                    0
+#define GISB_ARBITER_UNMASK_MASK_MASK                      1
+
+/****************************************************************************
+ * Enums: GISB_ARBITER_DISABLE_ENABLE
+ ***************************************************************************/
+#define GISB_ARBITER_DISABLE_ENABLE_DISABLE                0
+#define GISB_ARBITER_DISABLE_ENABLE_ENABLE                 1
+
+/****************************************************************************
+ * Enums: I2C_GR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define I2C_GR_BRIDGE_RESET_CTRL_DEASSERT                  0
+#define I2C_GR_BRIDGE_RESET_CTRL_ASSERT                    1
+
+/****************************************************************************
+ * Enums: MISC_GR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define MISC_GR_BRIDGE_RESET_CTRL_DEASSERT                 0
+#define MISC_GR_BRIDGE_RESET_CTRL_ASSERT                   1
+
+/****************************************************************************
+ * Enums: OTP_GR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define OTP_GR_BRIDGE_RESET_CTRL_DEASSERT                  0
+#define OTP_GR_BRIDGE_RESET_CTRL_ASSERT                    1
+
+/****************************************************************************
+ * BCM70012_TGT_TOP_PCIE_CFG
+ ***************************************************************************/
+#define PCIE_CFG_DEVICE_VENDOR_ID      0x00000000 /* DEVICE_VENDOR_ID Register */
+#define PCIE_CFG_STATUS_COMMAND        0x00000004 /* STATUS_COMMAND Register */
+#define PCIE_CFG_PCI_CLASSCODE_AND_REVISION_ID 0x00000008 /* PCI_CLASSCODE_AND_REVISION_ID Register */
+#define PCIE_CFG_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE_SIZE 0x0000000c /* BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE_SIZE Register */
+#define PCIE_CFG_BASE_ADDRESS_1        0x00000010 /* BASE_ADDRESS_1 Register */
+#define PCIE_CFG_BASE_ADDRESS_2        0x00000014 /* BASE_ADDRESS_2 Register */
+#define PCIE_CFG_BASE_ADDRESS_3        0x00000018 /* BASE_ADDRESS_3 Register */
+#define PCIE_CFG_BASE_ADDRESS_4        0x0000001c /* BASE_ADDRESS_4 Register */
+#define PCIE_CFG_CARDBUS_CIS_POINTER   0x00000028 /* CARDBUS_CIS_POINTER Register */
+#define PCIE_CFG_SUBSYSTEM_DEVICE_VENDOR_ID 0x0000002c /* SUBSYSTEM_DEVICE_VENDOR_ID Register */
+#define PCIE_CFG_EXPANSION_ROM_BASE_ADDRESS 0x00000030 /* EXPANSION_ROM_BASE_ADDRESS Register */
+#define PCIE_CFG_CAPABILITIES_POINTER  0x00000034 /* CAPABILITIES_POINTER Register */
+#define PCIE_CFG_INTERRUPT             0x0000003c /* INTERRUPT Register */
+#define PCIE_CFG_VPD_CAPABILITIES      0x00000040 /* VPD_CAPABILITIES Register */
+#define PCIE_CFG_VPD_DATA              0x00000044 /* VPD_DATA Register */
+#define PCIE_CFG_POWER_MANAGEMENT_CAPABILITY 0x00000048 /* POWER_MANAGEMENT_CAPABILITY Register */
+#define PCIE_CFG_POWER_MANAGEMENT_CONTROL_STATUS 0x0000004c /* POWER_MANAGEMENT_CONTROL_STATUS Register */
+#define PCIE_CFG_MSI_CAPABILITY_HEADER 0x00000050 /* MSI_CAPABILITY_HEADER Register */
+#define PCIE_CFG_MSI_LOWER_ADDRESS     0x00000054 /* MSI_LOWER_ADDRESS Register */
+#define PCIE_CFG_MSI_UPPER_ADDRESS_REGISTER 0x00000058 /* MSI_UPPER_ADDRESS_REGISTER Register */
+#define PCIE_CFG_MSI_DATA              0x0000005c /* MSI_DATA Register */
+#define PCIE_CFG_BROADCOM_VENDOR_SPECIFIC_CAPABILITY_HEADER 0x00000060 /* BROADCOM_VENDOR_SPECIFIC_CAPABILITY_HEADER Register */
+#define PCIE_CFG_RESET_COUNTERS_INITIAL_VALUES 0x00000064 /* RESET_COUNTERS_INITIAL_VALUES Register */
+#define PCIE_CFG_MISCELLANEOUS_HOST_CONTROL 0x00000068 /* MISCELLANEOUS_HOST_CONTROL Register */
+#define PCIE_CFG_SPARE                 0x0000006c /* SPARE Register */
+#define PCIE_CFG_PCI_STATE             0x00000070 /* PCI_STATE Register */
+#define PCIE_CFG_CLOCK_CONTROL         0x00000074 /* CLOCK_CONTROL Register */
+#define PCIE_CFG_REGISTER_BASE         0x00000078 /* REGISTER_BASE Register */
+#define PCIE_CFG_MEMORY_BASE           0x0000007c /* MEMORY_BASE Register */
+#define PCIE_CFG_REGISTER_DATA         0x00000080 /* REGISTER_DATA Register */
+#define PCIE_CFG_MEMORY_DATA           0x00000084 /* MEMORY_DATA Register */
+#define PCIE_CFG_EXPANSION_ROM_BAR_SIZE 0x00000088 /* EXPANSION_ROM_BAR_SIZE Register */
+#define PCIE_CFG_EXPANSION_ROM_ADDRESS 0x0000008c /* EXPANSION_ROM_ADDRESS Register */
+#define PCIE_CFG_EXPANSION_ROM_DATA    0x00000090 /* EXPANSION_ROM_DATA Register */
+#define PCIE_CFG_VPD_INTERFACE         0x00000094 /* VPD_INTERFACE Register */
+#define PCIE_CFG_UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_UPPER 0x00000098 /* UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_UPPER Register */
+#define PCIE_CFG_UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_LOWER 0x0000009c /* UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_LOWER Register */
+#define PCIE_CFG_UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_UPPER 0x000000a0 /* UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_UPPER Register */
+#define PCIE_CFG_UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_LOWER 0x000000a4 /* UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_LOWER Register */
+#define PCIE_CFG_UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_UPPER 0x000000a8 /* UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_UPPER Register */
+#define PCIE_CFG_UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_LOWER 0x000000ac /* UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_LOWER Register */
+#define PCIE_CFG_INT_MAILBOX_UPPER     0x000000b0 /* INT_MAILBOX_UPPER Register */
+#define PCIE_CFG_INT_MAILBOX_LOWER     0x000000b4 /* INT_MAILBOX_LOWER Register */
+#define PCIE_CFG_PRODUCT_ID_AND_ASIC_REVISION 0x000000bc /* PRODUCT_ID_AND_ASIC_REVISION Register */
+#define PCIE_CFG_FUNCTION_EVENT        0x000000c0 /* FUNCTION_EVENT Register */
+#define PCIE_CFG_FUNCTION_EVENT_MASK   0x000000c4 /* FUNCTION_EVENT_MASK Register */
+#define PCIE_CFG_FUNCTION_PRESENT      0x000000c8 /* FUNCTION_PRESENT Register */
+#define PCIE_CFG_PCIE_CAPABILITIES     0x000000cc /* PCIE_CAPABILITIES Register */
+#define PCIE_CFG_DEVICE_CAPABILITIES   0x000000d0 /* DEVICE_CAPABILITIES Register */
+#define PCIE_CFG_DEVICE_STATUS_CONTROL 0x000000d4 /* DEVICE_STATUS_CONTROL Register */
+#define PCIE_CFG_LINK_CAPABILITY       0x000000d8 /* LINK_CAPABILITY Register */
+#define PCIE_CFG_LINK_STATUS_CONTROL   0x000000dc /* LINK_STATUS_CONTROL Register */
+#define PCIE_CFG_DEVICE_CAPABILITIES_2 0x000000f0 /* DEVICE_CAPABILITIES_2 Register */
+#define PCIE_CFG_DEVICE_STATUS_CONTROL_2 0x000000f4 /* DEVICE_STATUS_CONTROL_2 Register */
+#define PCIE_CFG_LINK_CAPABILITIES_2   0x000000f8 /* LINK_CAPABILITIES_2 Register */
+#define PCIE_CFG_LINK_STATUS_CONTROL_2 0x000000fc /* LINK_STATUS_CONTROL_2 Register */
+#define PCIE_CFG_ADVANCED_ERROR_REPORTING_ENHANCED_CAPABILITY_HEADER 0x00000100 /* ADVANCED_ERROR_REPORTING_ENHANCED_CAPABILITY_HEADER Register */
+#define PCIE_CFG_UNCORRECTABLE_ERROR_STATUS 0x00000104 /* UNCORRECTABLE_ERROR_STATUS Register */
+#define PCIE_CFG_UNCORRECTABLE_ERROR_MASK 0x00000108 /* UNCORRECTABLE_ERROR_MASK Register */
+#define PCIE_CFG_UNCORRECTABLE_ERROR_SEVERITY 0x0000010c /* UNCORRECTABLE_ERROR_SEVERITY Register */
+#define PCIE_CFG_CORRECTABLE_ERROR_STATUS 0x00000110 /* CORRECTABLE_ERROR_STATUS Register */
+#define PCIE_CFG_CORRECTABLE_ERROR_MASK 0x00000114 /* CORRECTABLE_ERROR_MASK Register */
+#define PCIE_CFG_ADVANCED_ERROR_CAPABILITIES_AND_CONTROL 0x00000118 /* ADVANCED_ERROR_CAPABILITIES_AND_CONTROL Register */
+#define PCIE_CFG_HEADER_LOG_1          0x0000011c /* HEADER_LOG_1 Register */
+#define PCIE_CFG_HEADER_LOG_2          0x00000120 /* HEADER_LOG_2 Register */
+#define PCIE_CFG_HEADER_LOG_3          0x00000124 /* HEADER_LOG_3 Register */
+#define PCIE_CFG_HEADER_LOG_4          0x00000128 /* HEADER_LOG_4 Register */
+#define PCIE_CFG_VIRTUAL_CHANNEL_ENHANCED_CAPABILITY_HEADER 0x0000013c /* VIRTUAL_CHANNEL_ENHANCED_CAPABILITY_HEADER Register */
+#define PCIE_CFG_PORT_VC_CAPABILITY    0x00000140 /* PORT_VC_CAPABILITY Register */
+#define PCIE_CFG_PORT_VC_CAPABILITY_2  0x00000144 /* PORT_VC_CAPABILITY_2 Register */
+#define PCIE_CFG_PORT_VC_STATUS_CONTROL 0x00000148 /* PORT_VC_STATUS_CONTROL Register */
+#define PCIE_CFG_VC_RESOURCE_CAPABILITY 0x0000014c /* VC_RESOURCE_CAPABILITY Register */
+#define PCIE_CFG_VC_RESOURCE_CONTROL   0x00000150 /* VC_RESOURCE_CONTROL Register */
+#define PCIE_CFG_VC_RESOURCE_STATUS    0x00000154 /* VC_RESOURCE_STATUS Register */
+#define PCIE_CFG_DEVICE_SERIAL_NO_ENHANCED_CAPABILITY_HEADER 0x00000160 /* DEVICE_SERIAL_NO_ENHANCED_CAPABILITY_HEADER Register */
+#define PCIE_CFG_DEVICE_SERIAL_NO_LOWER_DW 0x00000164 /* DEVICE_SERIAL_NO_LOWER_DW Register */
+#define PCIE_CFG_DEVICE_SERIAL_NO_UPPER_DW 0x00000168 /* DEVICE_SERIAL_NO_UPPER_DW Register */
+#define PCIE_CFG_POWER_BUDGETING_ENHANCED_CAPABILITY_HEADER 0x0000016c /* POWER_BUDGETING_ENHANCED_CAPABILITY_HEADER Register */
+#define PCIE_CFG_POWER_BUDGETING_DATA_SELECT 0x00000170 /* POWER_BUDGETING_DATA_SELECT Register */
+#define PCIE_CFG_POWER_BUDGETING_DATA  0x00000174 /* POWER_BUDGETING_DATA Register */
+#define PCIE_CFG_POWER_BUDGETING_CAPABILITY 0x00000178 /* POWER_BUDGETING_CAPABILITY Register */
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_2_1 0x0000017c /* FIRMWARE_POWER_BUDGETING_2_1 Register */
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_4_3 0x00000180 /* FIRMWARE_POWER_BUDGETING_4_3 Register */
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_6_5 0x00000184 /* FIRMWARE_POWER_BUDGETING_6_5 Register */
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_8_7 0x00000188 /* FIRMWARE_POWER_BUDGETING_8_7 Register */
+#define PCIE_CFG_PCIE_1_1_ADVISORY_NON_FATAL_ERROR_MASKING 0x0000018c /* PCIE_1_1_ADVISORY_NON_FATAL_ERROR_MASKING Register */
+
+
+/****************************************************************************
+ * BCM70012_TGT_TOP_PCIE_TL
+ ***************************************************************************/
+#define PCIE_TL_TL_CONTROL             0x00000400 /* TL_CONTROL Register */
+#define PCIE_TL_TRANSACTION_CONFIGURATION 0x00000404 /* TRANSACTION_CONFIGURATION Register */
+
+
+/****************************************************************************
+ * BCM70012_TGT_TOP_PCIE_DLL
+ ***************************************************************************/
+#define PCIE_DLL_DATA_LINK_CONTROL     0x00000500 /* DATA_LINK_CONTROL Register */
+#define PCIE_DLL_DATA_LINK_STATUS      0x00000504 /* DATA_LINK_STATUS Register */
+
+
+/****************************************************************************
+ * BCM70012_TGT_TOP_INTR
+ ***************************************************************************/
+#define INTR_INTR_STATUS               0x00000700 /* Interrupt Status Register */
+#define INTR_INTR_SET                  0x00000704 /* Interrupt Set Register */
+#define INTR_INTR_CLR_REG              0x00000708 /* Interrupt Clear Register */
+#define INTR_INTR_MSK_STS_REG          0x0000070c /* Interrupt Mask Status Register */
+#define INTR_INTR_MSK_SET_REG          0x00000710 /* Interrupt Mask Set Register */
+#define INTR_INTR_MSK_CLR_REG          0x00000714 /* Interrupt Mask Clear Register */
+#define INTR_EOI_CTRL                  0x00000720 /* End of interrupt control register */
+
+
+/****************************************************************************
+ * BCM70012_MISC_TOP_MISC1
+ ***************************************************************************/
+#define MISC1_TX_FIRST_DESC_L_ADDR_LIST0 0x00000c00 /* Tx DMA Descriptor List0 First Descriptor lower Address */
+#define MISC1_TX_FIRST_DESC_U_ADDR_LIST0 0x00000c04 /* Tx DMA Descriptor List0 First Descriptor Upper Address */
+#define MISC1_TX_FIRST_DESC_L_ADDR_LIST1 0x00000c08 /* Tx DMA Descriptor List1 First Descriptor Lower Address */
+#define MISC1_TX_FIRST_DESC_U_ADDR_LIST1 0x00000c0c /* Tx DMA Descriptor List1 First Descriptor Upper Address */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS 0x00000c10 /* Tx DMA Software Descriptor List Control and Status */
+#define MISC1_TX_DMA_ERROR_STATUS      0x00000c18 /* Tx DMA Engine Error Status */
+#define MISC1_TX_DMA_LIST0_CUR_DESC_L_ADDR 0x00000c1c /* Tx DMA List0 Current Descriptor Lower Address */
+#define MISC1_TX_DMA_LIST0_CUR_DESC_U_ADDR 0x00000c20 /* Tx DMA List0 Current Descriptor Upper Address */
+#define MISC1_TX_DMA_LIST0_CUR_BYTE_CNT_REM 0x00000c24 /* Tx DMA List0 Current Descriptor Upper Address */
+#define MISC1_TX_DMA_LIST1_CUR_DESC_L_ADDR 0x00000c28 /* Tx DMA List1 Current Descriptor Lower Address */
+#define MISC1_TX_DMA_LIST1_CUR_DESC_U_ADDR 0x00000c2c /* Tx DMA List1 Current Descriptor Upper Address */
+#define MISC1_TX_DMA_LIST1_CUR_BYTE_CNT_REM 0x00000c30 /* Tx DMA List1 Current Descriptor Upper Address */
+#define MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0 0x00000c34 /* Y Rx Descriptor List0 First Descriptor Lower Address */
+#define MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST0 0x00000c38 /* Y Rx Descriptor List0 First Descriptor Upper Address */
+#define MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1 0x00000c3c /* Y Rx Descriptor List1 First Descriptor Lower Address */
+#define MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST1 0x00000c40 /* Y Rx Descriptor List1 First Descriptor Upper Address */
+#define MISC1_Y_RX_SW_DESC_LIST_CTRL_STS 0x00000c44 /* Y Rx Software Descriptor List Control and Status */
+#define MISC1_Y_RX_ERROR_STATUS        0x00000c4c /* Y Rx Engine Error Status */
+#define MISC1_Y_RX_LIST0_CUR_DESC_L_ADDR 0x00000c50 /* Y Rx List0 Current Descriptor Lower Address */
+#define MISC1_Y_RX_LIST0_CUR_DESC_U_ADDR 0x00000c54 /* Y Rx List0 Current Descriptor Upper Address */
+#define MISC1_Y_RX_LIST0_CUR_BYTE_CNT  0x00000c58 /* Y Rx List0 Current Descriptor Byte Count */
+#define MISC1_Y_RX_LIST1_CUR_DESC_L_ADDR 0x00000c5c /* Y Rx List1 Current Descriptor Lower address */
+#define MISC1_Y_RX_LIST1_CUR_DESC_U_ADDR 0x00000c60 /* Y Rx List1 Current Descriptor Upper address */
+#define MISC1_Y_RX_LIST1_CUR_BYTE_CNT  0x00000c64 /* Y Rx List1 Current Descriptor Byte Count */
+#define MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0 0x00000c68 /* UV Rx Descriptor List0 First Descriptor lower Address */
+#define MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST0 0x00000c6c /* UV Rx Descriptor List0 First Descriptor Upper Address */
+#define MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1 0x00000c70 /* UV Rx Descriptor List1 First Descriptor Lower Address */
+#define MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST1 0x00000c74 /* UV Rx Descriptor List1 First Descriptor Upper Address */
+#define MISC1_UV_RX_SW_DESC_LIST_CTRL_STS 0x00000c78 /* UV Rx Software Descriptor List Control and Status */
+#define MISC1_UV_RX_ERROR_STATUS       0x00000c7c /* UV Rx Engine Error Status */
+#define MISC1_UV_RX_LIST0_CUR_DESC_L_ADDR 0x00000c80 /* UV Rx List0 Current Descriptor Lower Address */
+#define MISC1_UV_RX_LIST0_CUR_DESC_U_ADDR 0x00000c84 /* UV Rx List0 Current Descriptor Upper Address */
+#define MISC1_UV_RX_LIST0_CUR_BYTE_CNT 0x00000c88 /* UV Rx List0 Current Descriptor Byte Count */
+#define MISC1_UV_RX_LIST1_CUR_DESC_L_ADDR 0x00000c8c /* UV Rx List1 Current Descriptor Lower Address */
+#define MISC1_UV_RX_LIST1_CUR_DESC_U_ADDR 0x00000c90 /* UV Rx List1 Current Descriptor Upper Address */
+#define MISC1_UV_RX_LIST1_CUR_BYTE_CNT 0x00000c94 /* UV Rx List1 Current Descriptor Byte Count */
+#define MISC1_DMA_DEBUG_OPTIONS_REG    0x00000c98 /* DMA Debug Options Register */
+#define MISC1_READ_CHANNEL_ERROR_STATUS 0x00000c9c /* Read Channel Error Status */
+#define MISC1_PCIE_DMA_CTRL            0x00000ca0 /* PCIE DMA Control Register */
+
+
+/****************************************************************************
+ * BCM70012_MISC_TOP_MISC2
+ ***************************************************************************/
+#define MISC2_GLOBAL_CTRL              0x00000d00 /* Global Control Register */
+#define MISC2_INTERNAL_STATUS          0x00000d04 /* Internal Status Register */
+#define MISC2_INTERNAL_STATUS_MUX_CTRL 0x00000d08 /* Internal Debug Mux Control */
+#define MISC2_DEBUG_FIFO_LENGTH        0x00000d0c /* Debug FIFO Length */
+
+
+/****************************************************************************
+ * BCM70012_MISC_TOP_MISC3
+ ***************************************************************************/
+#define MISC3_RESET_CTRL               0x00000e00 /* Reset Control Register */
+#define MISC3_BIST_CTRL                0x00000e04 /* BIST Control Register */
+#define MISC3_BIST_STATUS              0x00000e08 /* BIST Status Register */
+#define MISC3_RX_CHECKSUM              0x00000e0c /* Receive Checksum */
+#define MISC3_TX_CHECKSUM              0x00000e10 /* Transmit Checksum */
+#define MISC3_ECO_CTRL_CORE            0x00000e14 /* ECO Core Reset Control Register */
+#define MISC3_CSI_TEST_CTRL            0x00000e18 /* CSI Test Control Register */
+#define MISC3_HD_DVI_TEST_CTRL         0x00000e1c /* HD DVI Test Control Register */
+
+
+/****************************************************************************
+ * BCM70012_MISC_TOP_MISC_PERST
+ ***************************************************************************/
+#define MISC_PERST_ECO_CTRL_PERST      0x00000e80 /* ECO PCIE Reset Control Register */
+#define MISC_PERST_DECODER_CTRL        0x00000e84 /* Decoder Control Register */
+#define MISC_PERST_CCE_STATUS          0x00000e88 /* Config Copy Engine Status */
+#define MISC_PERST_PCIE_DEBUG          0x00000e8c /* PCIE Debug Control Register */
+#define MISC_PERST_PCIE_DEBUG_STATUS   0x00000e90 /* PCIE Debug Status Register */
+#define MISC_PERST_VREG_CTRL           0x00000e94 /* Voltage Regulator Control Register */
+#define MISC_PERST_MEM_CTRL            0x00000e98 /* Memory Control Register */
+#define MISC_PERST_CLOCK_CTRL          0x00000e9c /* Clock Control Register */
+
+
+/****************************************************************************
+ * BCM70012_MISC_TOP_GISB_ARBITER
+ ***************************************************************************/
+#define GISB_ARBITER_REVISION          0x00000f00 /* GISB ARBITER REVISION */
+#define GISB_ARBITER_SCRATCH           0x00000f04 /* GISB ARBITER Scratch Register */
+#define GISB_ARBITER_REQ_MASK          0x00000f08 /* GISB ARBITER Master Request Mask Register */
+#define GISB_ARBITER_TIMER             0x00000f0c /* GISB ARBITER Timer Value Register */
+
+
+/****************************************************************************
+ * BCM70012_OTP_TOP_OTP
+ ***************************************************************************/
+#define OTP_CONFIG_INFO                0x00001400 /* OTP Configuration Register */
+#define OTP_CMD                        0x00001404 /* OTP Command Register */
+#define OTP_STATUS                     0x00001408 /* OTP Status Register */
+#define OTP_CONTENT_MISC               0x0000140c /* Content : Miscellaneous Register */
+#define OTP_CONTENT_AES_0              0x00001410 /* Content : AES Key 0 Register */
+#define OTP_CONTENT_AES_1              0x00001414 /* Content : AES Key 1 Register */
+#define OTP_CONTENT_AES_2              0x00001418 /* Content : AES Key 2 Register */
+#define OTP_CONTENT_AES_3              0x0000141c /* Content : AES Key 3 Register */
+#define OTP_CONTENT_SHA_0              0x00001420 /* Content : SHA Key 0 Register */
+#define OTP_CONTENT_SHA_1              0x00001424 /* Content : SHA Key 1 Register */
+#define OTP_CONTENT_SHA_2              0x00001428 /* Content : SHA Key 2 Register */
+#define OTP_CONTENT_SHA_3              0x0000142c /* Content : SHA Key 3 Register */
+#define OTP_CONTENT_SHA_4              0x00001430 /* Content : SHA Key 4 Register */
+#define OTP_CONTENT_SHA_5              0x00001434 /* Content : SHA Key 5 Register */
+#define OTP_CONTENT_SHA_6              0x00001438 /* Content : SHA Key 6 Register */
+#define OTP_CONTENT_SHA_7              0x0000143c /* Content : SHA Key 7 Register */
+#define OTP_CONTENT_CHECKSUM           0x00001440 /* Content : Checksum  Register */
+#define OTP_PROG_CTRL                  0x00001444 /* Programming Control Register */
+#define OTP_PROG_STATUS                0x00001448 /* Programming Status Register */
+#define OTP_PROG_PULSE                 0x0000144c /* Program Pulse Width Register */
+#define OTP_VERIFY_PULSE               0x00001450 /* Verify Pulse Width Register */
+#define OTP_PROG_MASK                  0x00001454 /* Program Mask Register */
+#define OTP_DATA_INPUT                 0x00001458 /* Data Input Register */
+#define OTP_DATA_OUTPUT                0x0000145c /* Data Output Register */
+
+
+/****************************************************************************
+ * BCM70012_AES_TOP_AES
+ ***************************************************************************/
+#define AES_CONFIG_INFO                0x00001800 /* AES Configuration Information Register */
+#define AES_CMD                        0x00001804 /* AES Command Register */
+#define AES_STATUS                     0x00001808 /* AES Status Register */
+#define AES_EEPROM_CONFIG              0x0000180c /* AES EEPROM Configuration Register */
+#define AES_EEPROM_DATA_0              0x00001810 /* AES EEPROM Data Register 0 */
+#define AES_EEPROM_DATA_1              0x00001814 /* AES EEPROM Data Register 1 */
+#define AES_EEPROM_DATA_2              0x00001818 /* AES EEPROM Data Register 2 */
+#define AES_EEPROM_DATA_3              0x0000181c /* AES EEPROM Data Register 3 */
+
+
+/****************************************************************************
+ * BCM70012_DCI_TOP_DCI
+ ***************************************************************************/
+#define DCI_CMD                        0x00001c00 /* DCI Command Register */
+#define DCI_STATUS                     0x00001c04 /* DCI Status Register */
+#define DCI_DRAM_BASE_ADDR             0x00001c08 /* DRAM Base Address Register */
+#define DCI_FIRMWARE_ADDR              0x00001c0c /* Firmware Address Register */
+#define DCI_FIRMWARE_DATA              0x00001c10 /* Firmware Data Register */
+#define DCI_SIGNATURE_DATA_0           0x00001c14 /* Signature Data Register 0 */
+#define DCI_SIGNATURE_DATA_1           0x00001c18 /* Signature Data Register 1 */
+#define DCI_SIGNATURE_DATA_2           0x00001c1c /* Signature Data Register 2 */
+#define DCI_SIGNATURE_DATA_3           0x00001c20 /* Signature Data Register 3 */
+#define DCI_SIGNATURE_DATA_4           0x00001c24 /* Signature Data Register 4 */
+#define DCI_SIGNATURE_DATA_5           0x00001c28 /* Signature Data Register 5 */
+#define DCI_SIGNATURE_DATA_6           0x00001c2c /* Signature Data Register 6 */
+#define DCI_SIGNATURE_DATA_7           0x00001c30 /* Signature Data Register 7 */
+
+
+/****************************************************************************
+ * BCM70012_TGT_TOP_INTR
+ ***************************************************************************/
+/****************************************************************************
+ * INTR :: INTR_STATUS
+ ***************************************************************************/
+/* INTR :: INTR_STATUS :: reserved0 [31:26] */
+#define INTR_INTR_STATUS_reserved0_MASK                            0xfc000000
+#define INTR_INTR_STATUS_reserved0_ALIGN                           0
+#define INTR_INTR_STATUS_reserved0_BITS                            6
+#define INTR_INTR_STATUS_reserved0_SHIFT                           26
+
+/* INTR :: INTR_STATUS :: PCIE_TGT_CA_ATTN [25:25] */
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_MASK                     0x02000000
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_ALIGN                    0
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_BITS                     1
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_SHIFT                    25
+
+/* INTR :: INTR_STATUS :: PCIE_TGT_UR_ATTN [24:24] */
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_MASK                     0x01000000
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_ALIGN                    0
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_BITS                     1
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_SHIFT                    24
+
+/* INTR :: INTR_STATUS :: reserved1 [23:14] */
+#define INTR_INTR_STATUS_reserved1_MASK                            0x00ffc000
+#define INTR_INTR_STATUS_reserved1_ALIGN                           0
+#define INTR_INTR_STATUS_reserved1_BITS                            10
+#define INTR_INTR_STATUS_reserved1_SHIFT                           14
+
+/* INTR :: INTR_STATUS :: L1_UV_RX_DMA_ERR_INTR [13:13] */
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_MASK                0x00002000
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_ALIGN               0
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_BITS                1
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_SHIFT               13
+
+/* INTR :: INTR_STATUS :: L1_UV_RX_DMA_DONE_INTR [12:12] */
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK               0x00001000
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_ALIGN              0
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_BITS               1
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_SHIFT              12
+
+/* INTR :: INTR_STATUS :: L1_Y_RX_DMA_ERR_INTR [11:11] */
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_MASK                 0x00000800
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_ALIGN                0
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_BITS                 1
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_SHIFT                11
+
+/* INTR :: INTR_STATUS :: L1_Y_RX_DMA_DONE_INTR [10:10] */
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK                0x00000400
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_ALIGN               0
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_BITS                1
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_SHIFT               10
+
+/* INTR :: INTR_STATUS :: L1_TX_DMA_ERR_INTR [09:09] */
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_MASK                   0x00000200
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_ALIGN                  0
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_BITS                   1
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_SHIFT                  9
+
+/* INTR :: INTR_STATUS :: L1_TX_DMA_DONE_INTR [08:08] */
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_MASK                  0x00000100
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_ALIGN                 0
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_BITS                  1
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_SHIFT                 8
+
+/* INTR :: INTR_STATUS :: reserved2 [07:06] */
+#define INTR_INTR_STATUS_reserved2_MASK                            0x000000c0
+#define INTR_INTR_STATUS_reserved2_ALIGN                           0
+#define INTR_INTR_STATUS_reserved2_BITS                            2
+#define INTR_INTR_STATUS_reserved2_SHIFT                           6
+
+/* INTR :: INTR_STATUS :: L0_UV_RX_DMA_ERR_INTR [05:05] */
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_MASK                0x00000020
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_ALIGN               0
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_BITS                1
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_SHIFT               5
+
+/* INTR :: INTR_STATUS :: L0_UV_RX_DMA_DONE_INTR [04:04] */
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK               0x00000010
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_ALIGN              0
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_BITS               1
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_SHIFT              4
+
+/* INTR :: INTR_STATUS :: L0_Y_RX_DMA_ERR_INTR [03:03] */
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_MASK                 0x00000008
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_ALIGN                0
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_BITS                 1
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_SHIFT                3
+
+/* INTR :: INTR_STATUS :: L0_Y_RX_DMA_DONE_INTR [02:02] */
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK                0x00000004
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_ALIGN               0
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_BITS                1
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_SHIFT               2
+
+/* INTR :: INTR_STATUS :: L0_TX_DMA_ERR_INTR [01:01] */
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_MASK                   0x00000002
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_ALIGN                  0
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_BITS                   1
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_SHIFT                  1
+
+/* INTR :: INTR_STATUS :: L0_TX_DMA_DONE_INTR [00:00] */
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_MASK                  0x00000001
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_ALIGN                 0
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_BITS                  1
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_SHIFT                 0
+
+
+/****************************************************************************
+ * MISC1 :: TX_SW_DESC_LIST_CTRL_STS
+ ***************************************************************************/
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: reserved0 [31:04] */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_MASK              0xfffffff0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_ALIGN             0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_BITS              28
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_SHIFT             4
+
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: DMA_DATA_SERV_PTR [03:03] */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_MASK      0x00000008
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_ALIGN     0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_BITS      1
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_SHIFT     3
+
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: DESC_SERV_PTR [02:02] */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_MASK          0x00000004
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_ALIGN         0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_BITS          1
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_SHIFT         2
+
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: TX_DMA_HALT_ON_ERROR [01:01] */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_MASK   0x00000002
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_ALIGN  0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_BITS   1
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_SHIFT  1
+
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: TX_DMA_RUN_STOP [00:00] */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_MASK        0x00000001
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_ALIGN       0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_BITS        1
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_SHIFT       0
+
+
+/****************************************************************************
+ * MISC1 :: TX_DMA_ERROR_STATUS
+ ***************************************************************************/
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved0 [31:10] */
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_MASK                   0xfffffc00
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_ALIGN                  0
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_BITS                   22
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_SHIFT                  10
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_DESC_TX_ABORT_ERRORS [09:09] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_MASK  0x00000200
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_BITS  1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_SHIFT 9
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved1 [08:08] */
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_MASK                   0x00000100
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_ALIGN                  0
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_BITS                   1
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_SHIFT                  8
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_DESC_TX_ABORT_ERRORS [07:07] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_MASK  0x00000080
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_BITS  1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_SHIFT 7
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved2 [06:06] */
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_MASK                   0x00000040
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_ALIGN                  0
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_BITS                   1
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_SHIFT                  6
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_DMA_DATA_TX_ABORT_ERRORS [05:05] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_MASK 0x00000020
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_SHIFT 5
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_FIFO_FULL_ERRORS [04:04] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK      0x00000010
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_ALIGN     0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_BITS      1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_SHIFT     4
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved3 [03:03] */
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_MASK                   0x00000008
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_ALIGN                  0
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_BITS                   1
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_SHIFT                  3
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_DMA_DATA_TX_ABORT_ERRORS [02:02] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_MASK 0x00000004
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_SHIFT 2
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_FIFO_FULL_ERRORS [01:01] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK      0x00000002
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_ALIGN     0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_BITS      1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_SHIFT     1
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved4 [00:00] */
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_MASK                   0x00000001
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_ALIGN                  0
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_BITS                   1
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_SHIFT                  0
+
+
+/****************************************************************************
+ * MISC1 :: Y_RX_ERROR_STATUS
+ ***************************************************************************/
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved0 [31:14] */
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_MASK                     0xffffc000
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_ALIGN                    0
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_BITS                     18
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_SHIFT                    14
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_UNDERRUN_ERROR [13:13] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK          0x00002000
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_ALIGN         0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_BITS          1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_SHIFT         13
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_OVERRUN_ERROR [12:12] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK           0x00001000
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_ALIGN          0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_BITS           1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_SHIFT          12
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_UNDERRUN_ERROR [11:11] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK          0x00000800
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_ALIGN         0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_BITS          1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_SHIFT         11
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_OVERRUN_ERROR [10:10] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK           0x00000400
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_ALIGN          0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_BITS           1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_SHIFT          10
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_DESC_TX_ABORT_ERRORS [09:09] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK    0x00000200
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_ALIGN   0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_BITS    1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_SHIFT   9
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved1 [08:08] */
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_MASK                     0x00000100
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_ALIGN                    0
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_BITS                     1
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_SHIFT                    8
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_DESC_TX_ABORT_ERRORS [07:07] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK    0x00000080
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_ALIGN   0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_BITS    1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_SHIFT   7
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved2 [06:05] */
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_MASK                     0x00000060
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_ALIGN                    0
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_BITS                     2
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_SHIFT                    5
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_FIFO_FULL_ERRORS [04:04] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK        0x00000010
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_ALIGN       0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_BITS        1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_SHIFT       4
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved3 [03:02] */
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_MASK                     0x0000000c
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_ALIGN                    0
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_BITS                     2
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_SHIFT                    2
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_FIFO_FULL_ERRORS [01:01] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK        0x00000002
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_ALIGN       0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_BITS        1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_SHIFT       1
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved4 [00:00] */
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_MASK                     0x00000001
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_ALIGN                    0
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_BITS                     1
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_SHIFT                    0
+
+
+/****************************************************************************
+ * MISC1 :: UV_RX_ERROR_STATUS
+ ***************************************************************************/
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved0 [31:14] */
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_MASK                    0xffffc000
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_ALIGN                   0
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_BITS                    18
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_SHIFT                   14
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_UNDERRUN_ERROR [13:13] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK         0x00002000
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_ALIGN        0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_BITS         1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_SHIFT        13
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_OVERRUN_ERROR [12:12] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK          0x00001000
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_ALIGN         0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_BITS          1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_SHIFT         12
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_UNDERRUN_ERROR [11:11] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK         0x00000800
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_ALIGN        0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_BITS         1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_SHIFT        11
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_OVERRUN_ERROR [10:10] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK          0x00000400
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_ALIGN         0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_BITS          1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_SHIFT         10
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_DESC_TX_ABORT_ERRORS [09:09] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK   0x00000200
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_ALIGN  0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_BITS   1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_SHIFT  9
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved1 [08:08] */
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_MASK                    0x00000100
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_ALIGN                   0
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_BITS                    1
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_SHIFT                   8
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_DESC_TX_ABORT_ERRORS [07:07] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK   0x00000080
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_ALIGN  0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_BITS   1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_SHIFT  7
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved2 [06:05] */
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_MASK                    0x00000060
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_ALIGN                   0
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_BITS                    2
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_SHIFT                   5
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_FIFO_FULL_ERRORS [04:04] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK       0x00000010
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_ALIGN      0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_BITS       1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_SHIFT      4
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved3 [03:02] */
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_MASK                    0x0000000c
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_ALIGN                   0
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_BITS                    2
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_SHIFT                   2
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_FIFO_FULL_ERRORS [01:01] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK       0x00000002
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_ALIGN      0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_BITS       1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_SHIFT      1
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved4 [00:00] */
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_MASK                    0x00000001
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_ALIGN                   0
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_BITS                    1
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_SHIFT                   0
+
+/****************************************************************************
+ * Datatype Definitions.
+ ***************************************************************************/
+#endif /* #ifndef MACFILE_H__ */
+
+/* End of File */
+
diff --git a/drivers/staging/crystalhd/crystalhd_cmds.c b/drivers/staging/crystalhd/crystalhd_cmds.c
new file mode 100644
index 0000000..26145a8
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_cmds.c
@@ -0,0 +1,1058 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ *  Name: crystalhd_cmds . c
+ *
+ *  Description:
+ *		BCM70010 Linux driver user command interfaces.
+ *
+ *  HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * This driver is free software; 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 driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#include "crystalhd_cmds.h"
+#include "crystalhd_hw.h"
+
+static struct crystalhd_user *bc_cproc_get_uid(struct crystalhd_cmd *ctx)
+{
+	struct crystalhd_user *user = NULL;
+	int i;
+
+	for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
+		if (!ctx->user[i].in_use) {
+			user = &ctx->user[i];
+			break;
+		}
+	}
+
+	return user;
+}
+
+static int bc_cproc_get_user_count(struct crystalhd_cmd *ctx)
+{
+	int i, count = 0;
+
+	for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
+		if (ctx->user[i].in_use)
+			count++;
+	}
+
+	return count;
+}
+
+static void bc_cproc_mark_pwr_state(struct crystalhd_cmd *ctx)
+{
+	int i;
+
+	for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
+		if (!ctx->user[i].in_use)
+			continue;
+		if (ctx->user[i].mode == DTS_DIAG_MODE ||
+		    ctx->user[i].mode == DTS_PLAYBACK_MODE) {
+			ctx->pwr_state_change = 1;
+			break;
+		}
+	}
+}
+
+static BC_STATUS bc_cproc_notify_mode(struct crystalhd_cmd *ctx,
+				      crystalhd_ioctl_data *idata)
+{
+	int rc = 0, i = 0;
+
+	if (!ctx || !idata) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if (ctx->user[idata->u_id].mode != DTS_MODE_INV) {
+		BCMLOG_ERR("Close the handle first..\n");
+		return BC_STS_ERR_USAGE;
+	}
+	if (idata->udata.u.NotifyMode.Mode == DTS_MONITOR_MODE) {
+		ctx->user[idata->u_id].mode = idata->udata.u.NotifyMode.Mode;
+		return BC_STS_SUCCESS;
+	}
+	if (ctx->state != BC_LINK_INVALID) {
+		BCMLOG_ERR("Link invalid state %d \n", ctx->state);
+		return BC_STS_ERR_USAGE;
+	}
+	/* Check for duplicate playback sessions..*/
+	for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
+		if (ctx->user[i].mode == DTS_DIAG_MODE ||
+		    ctx->user[i].mode == DTS_PLAYBACK_MODE) {
+			BCMLOG_ERR("multiple playback sessions are not "
+				   "supported..\n");
+			return BC_STS_ERR_USAGE;
+		}
+	}
+	ctx->cin_wait_exit = 0;
+	ctx->user[idata->u_id].mode = idata->udata.u.NotifyMode.Mode;
+	/* Setup mmap pool for uaddr sgl mapping..*/
+	rc = crystalhd_create_dio_pool(ctx->adp, BC_LINK_MAX_SGLS);
+	if (rc)
+		return BC_STS_ERROR;
+
+	/* Setup Hardware DMA rings */
+	return crystalhd_hw_setup_dma_rings(&ctx->hw_ctx);
+}
+
+static BC_STATUS bc_cproc_get_version(struct crystalhd_cmd *ctx,
+				      crystalhd_ioctl_data *idata)
+{
+
+	if (!ctx || !idata) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+	idata->udata.u.VerInfo.DriverMajor = crystalhd_kmod_major;
+	idata->udata.u.VerInfo.DriverMinor = crystalhd_kmod_minor;
+	idata->udata.u.VerInfo.DriverRevision	= crystalhd_kmod_rev;
+	return BC_STS_SUCCESS;
+}
+
+
+static BC_STATUS bc_cproc_get_hwtype(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
+{
+	if (!ctx || !idata) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	crystalhd_pci_cfg_rd(ctx->adp, 0, 2,
+			   (uint32_t *)&idata->udata.u.hwType.PciVenId);
+	crystalhd_pci_cfg_rd(ctx->adp, 2, 2,
+			   (uint32_t *)&idata->udata.u.hwType.PciDevId);
+	crystalhd_pci_cfg_rd(ctx->adp, 8, 1,
+			   (uint32_t *)&idata->udata.u.hwType.HwRev);
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_reg_rd(struct crystalhd_cmd *ctx,
+				 crystalhd_ioctl_data *idata)
+{
+	if (!ctx || !idata)
+		return BC_STS_INV_ARG;
+	idata->udata.u.regAcc.Value = bc_dec_reg_rd(ctx->adp,
+					idata->udata.u.regAcc.Offset);
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_reg_wr(struct crystalhd_cmd *ctx,
+				 crystalhd_ioctl_data *idata)
+{
+	if (!ctx || !idata)
+		return BC_STS_INV_ARG;
+
+	bc_dec_reg_wr(ctx->adp, idata->udata.u.regAcc.Offset,
+		      idata->udata.u.regAcc.Value);
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_link_reg_rd(struct crystalhd_cmd *ctx,
+				      crystalhd_ioctl_data *idata)
+{
+	if (!ctx || !idata)
+		return BC_STS_INV_ARG;
+
+	idata->udata.u.regAcc.Value = crystalhd_reg_rd(ctx->adp,
+					idata->udata.u.regAcc.Offset);
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_link_reg_wr(struct crystalhd_cmd *ctx,
+				      crystalhd_ioctl_data *idata)
+{
+	if (!ctx || !idata)
+		return BC_STS_INV_ARG;
+
+	crystalhd_reg_wr(ctx->adp, idata->udata.u.regAcc.Offset,
+		       idata->udata.u.regAcc.Value);
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_mem_rd(struct crystalhd_cmd *ctx,
+				 crystalhd_ioctl_data *idata)
+{
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	if (!ctx || !idata || !idata->add_cdata)
+		return BC_STS_INV_ARG;
+
+	if (idata->udata.u.devMem.NumDwords > (idata->add_cdata_sz / 4)) {
+		BCMLOG_ERR("insufficient buffer\n");
+		return BC_STS_INV_ARG;
+	}
+	sts = crystalhd_mem_rd(ctx->adp, idata->udata.u.devMem.StartOff,
+			     idata->udata.u.devMem.NumDwords,
+			     (uint32_t *)idata->add_cdata);
+	return sts;
+
+}
+
+static BC_STATUS bc_cproc_mem_wr(struct crystalhd_cmd *ctx,
+				 crystalhd_ioctl_data *idata)
+{
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	if (!ctx || !idata || !idata->add_cdata)
+		return BC_STS_INV_ARG;
+
+	if (idata->udata.u.devMem.NumDwords > (idata->add_cdata_sz / 4)) {
+		BCMLOG_ERR("insufficient buffer\n");
+		return BC_STS_INV_ARG;
+	}
+
+	sts = crystalhd_mem_wr(ctx->adp, idata->udata.u.devMem.StartOff,
+			     idata->udata.u.devMem.NumDwords,
+			     (uint32_t *)idata->add_cdata);
+	return sts;
+}
+
+static BC_STATUS bc_cproc_cfg_rd(struct crystalhd_cmd *ctx,
+				 crystalhd_ioctl_data *idata)
+{
+	uint32_t ix, cnt, off, len;
+	BC_STATUS sts = BC_STS_SUCCESS;
+	uint32_t *temp;
+
+	if (!ctx || !idata)
+		return BC_STS_INV_ARG;
+
+	temp = (uint32_t *) idata->udata.u.pciCfg.pci_cfg_space;
+	off = idata->udata.u.pciCfg.Offset;
+	len = idata->udata.u.pciCfg.Size;
+
+	if (len <= 4)
+		return crystalhd_pci_cfg_rd(ctx->adp, off, len, temp);
+
+	/* Truncate to dword alignment..*/
+	len = 4;
+	cnt = idata->udata.u.pciCfg.Size / len;
+	for (ix = 0; ix < cnt; ix++) {
+		sts = crystalhd_pci_cfg_rd(ctx->adp, off, len, &temp[ix]);
+		if (sts != BC_STS_SUCCESS) {
+			BCMLOG_ERR("config read : %d\n", sts);
+			return sts;
+		}
+		off += len;
+	}
+
+	return sts;
+}
+
+static BC_STATUS bc_cproc_cfg_wr(struct crystalhd_cmd *ctx,
+				 crystalhd_ioctl_data *idata)
+{
+	uint32_t ix, cnt, off, len;
+	BC_STATUS sts = BC_STS_SUCCESS;
+	uint32_t *temp;
+
+	if (!ctx || !idata)
+		return BC_STS_INV_ARG;
+
+	temp = (uint32_t *) idata->udata.u.pciCfg.pci_cfg_space;
+	off = idata->udata.u.pciCfg.Offset;
+	len = idata->udata.u.pciCfg.Size;
+
+	if (len <= 4)
+		return crystalhd_pci_cfg_wr(ctx->adp, off, len, temp[0]);
+
+	/* Truncate to dword alignment..*/
+	len = 4;
+	cnt = idata->udata.u.pciCfg.Size / len;
+	for (ix = 0; ix < cnt; ix++) {
+		sts = crystalhd_pci_cfg_wr(ctx->adp, off, len, temp[ix]);
+		if (sts != BC_STS_SUCCESS) {
+			BCMLOG_ERR("config write : %d\n", sts);
+			return sts;
+		}
+		off += len;
+	}
+
+	return sts;
+}
+
+static BC_STATUS bc_cproc_download_fw(struct crystalhd_cmd *ctx,
+				      crystalhd_ioctl_data *idata)
+{
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	if (!ctx || !idata || !idata->add_cdata || !idata->add_cdata_sz) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if (ctx->state != BC_LINK_INVALID) {
+		BCMLOG_ERR("Link invalid state %d \n", ctx->state);
+		return BC_STS_ERR_USAGE;
+	}
+
+	sts = crystalhd_download_fw(ctx->adp, (uint8_t *)idata->add_cdata,
+				  idata->add_cdata_sz);
+
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG_ERR("Firmware Download Failure!! - %d\n", sts);
+	} else
+		ctx->state |= BC_LINK_INIT;
+
+	return sts;
+}
+
+/*
+ * We use the FW_CMD interface to sync up playback state with application
+ * and  firmware. This function will perform the required pre and post
+ * processing of the Firmware commands.
+ *
+ * Pause -
+ *	Disable capture after decoder pause.
+ * Resume -
+ *	First enable capture and issue decoder resume command.
+ * Flush -
+ *	Abort pending input transfers and issue decoder flush command.
+ *
+ */
+static BC_STATUS bc_cproc_do_fw_cmd(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
+{
+	BC_STATUS sts;
+	uint32_t *cmd;
+
+	if (!(ctx->state & BC_LINK_INIT)) {
+		BCMLOG_ERR("Link invalid state %d \n", ctx->state);
+		return BC_STS_ERR_USAGE;
+	}
+
+	cmd = idata->udata.u.fwCmd.cmd;
+
+	/* Pre-Process */
+	if (cmd[0] == eCMD_C011_DEC_CHAN_PAUSE) {
+		if (!cmd[3]) {
+			ctx->state &= ~BC_LINK_PAUSED;
+			crystalhd_hw_unpause(&ctx->hw_ctx);
+		}
+	} else if (cmd[0] == eCMD_C011_DEC_CHAN_FLUSH) {
+		BCMLOG(BCMLOG_INFO, "Flush issued\n");
+		if (cmd[3])
+			ctx->cin_wait_exit = 1;
+	}
+
+	sts = crystalhd_do_fw_cmd(&ctx->hw_ctx, &idata->udata.u.fwCmd);
+
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG(BCMLOG_INFO, "fw cmd %x failed\n", cmd[0]);
+		return sts;
+	}
+
+	/* Post-Process */
+	if (cmd[0] == eCMD_C011_DEC_CHAN_PAUSE) {
+		if (cmd[3]) {
+			ctx->state |= BC_LINK_PAUSED;
+			crystalhd_hw_pause(&ctx->hw_ctx);
+		}
+	}
+
+	return sts;
+}
+
+static void bc_proc_in_completion(crystalhd_dio_req *dio_hnd,
+				  wait_queue_head_t *event, BC_STATUS sts)
+{
+	if (!dio_hnd || !event) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return;
+	}
+	if (sts == BC_STS_IO_USER_ABORT)
+		 return;
+
+	dio_hnd->uinfo.comp_sts = sts;
+	dio_hnd->uinfo.ev_sts = 1;
+	crystalhd_set_event(event);
+}
+
+static BC_STATUS bc_cproc_codein_sleep(struct crystalhd_cmd *ctx)
+{
+	wait_queue_head_t sleep_ev;
+	int rc = 0;
+
+	if (ctx->state & BC_LINK_SUSPEND)
+		return BC_STS_IO_USER_ABORT;
+
+	if (ctx->cin_wait_exit) {
+		ctx->cin_wait_exit = 0;
+		return BC_STS_CMD_CANCELLED;
+	}
+	crystalhd_create_event(&sleep_ev);
+	crystalhd_wait_on_event(&sleep_ev, 0, 100, rc, 0);
+	if (rc == -EINTR)
+		return BC_STS_IO_USER_ABORT;
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_hw_txdma(struct crystalhd_cmd *ctx,
+				   crystalhd_ioctl_data *idata,
+				   crystalhd_dio_req *dio)
+{
+	uint32_t tx_listid = 0;
+	BC_STATUS sts = BC_STS_SUCCESS;
+	wait_queue_head_t event;
+	int rc = 0;
+
+	if (!ctx || !idata || !dio) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	crystalhd_create_event(&event);
+
+	ctx->tx_list_id = 0;
+	/* msleep_interruptible(2000); */
+	sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio, bc_proc_in_completion,
+				 &event, &tx_listid,
+				 idata->udata.u.ProcInput.Encrypted);
+
+	while (sts == BC_STS_BUSY) {
+		sts = bc_cproc_codein_sleep(ctx);
+		if (sts != BC_STS_SUCCESS)
+			break;
+		sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio,
+					 bc_proc_in_completion,
+					 &event, &tx_listid,
+					 idata->udata.u.ProcInput.Encrypted);
+	}
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG(BCMLOG_DBG, "_hw_txdma returning sts:%d\n", sts);
+		return sts;
+	}
+	if (ctx->cin_wait_exit)
+		ctx->cin_wait_exit = 0;
+
+	ctx->tx_list_id = tx_listid;
+
+	/* _post() succeeded.. wait for the completion. */
+	crystalhd_wait_on_event(&event, (dio->uinfo.ev_sts), 3000, rc, 0);
+	ctx->tx_list_id = 0;
+	if (!rc) {
+		return dio->uinfo.comp_sts;
+	} else if (rc == -EBUSY) {
+		BCMLOG(BCMLOG_DBG, "_tx_post() T/O \n");
+		sts = BC_STS_TIMEOUT;
+	} else if (rc == -EINTR) {
+		BCMLOG(BCMLOG_DBG, "Tx Wait Signal int.\n");
+		sts = BC_STS_IO_USER_ABORT;
+	} else {
+		sts = BC_STS_IO_ERROR;
+	}
+
+	/* We are cancelling the IO from the same context as the _post().
+	 * so no need to wait on the event again.. the return itself
+	 * ensures the release of our resources.
+	 */
+	crystalhd_hw_cancel_tx(&ctx->hw_ctx, tx_listid);
+
+	return sts;
+}
+
+/* Helper function to check on user buffers */
+static BC_STATUS bc_cproc_check_inbuffs(bool pin, void *ubuff, uint32_t ub_sz,
+					uint32_t uv_off, bool en_422)
+{
+	if (!ubuff || !ub_sz) {
+		BCMLOG_ERR("%s->Invalid Arg %p %x\n",
+			((pin) ? "TX" : "RX"), ubuff, ub_sz);
+		return BC_STS_INV_ARG;
+	}
+
+	/* Check for alignment */
+	if (((uintptr_t)ubuff) & 0x03) {
+		BCMLOG_ERR("%s-->Un-aligned address not implemented yet.. %p \n",
+				((pin) ? "TX" : "RX"), ubuff);
+		return BC_STS_NOT_IMPL;
+	}
+	if (pin)
+		return BC_STS_SUCCESS;
+
+	if (!en_422 && !uv_off) {
+		BCMLOG_ERR("Need UV offset for 420 mode.\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if (en_422 && uv_off) {
+		BCMLOG_ERR("UV offset in 422 mode ??\n");
+		return BC_STS_INV_ARG;
+	}
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_proc_input(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
+{
+	void *ubuff;
+	uint32_t ub_sz;
+	crystalhd_dio_req *dio_hnd = NULL;
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	if (!ctx || !idata) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	ubuff = idata->udata.u.ProcInput.pDmaBuff;
+	ub_sz = idata->udata.u.ProcInput.BuffSz;
+
+	sts = bc_cproc_check_inbuffs(1, ubuff, ub_sz, 0, 0);
+	if (sts != BC_STS_SUCCESS)
+		return sts;
+
+	sts = crystalhd_map_dio(ctx->adp, ubuff, ub_sz, 0, 0, 1, &dio_hnd);
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG_ERR("dio map - %d \n", sts);
+		return sts;
+	}
+
+	if (!dio_hnd)
+		return BC_STS_ERROR;
+
+	sts = bc_cproc_hw_txdma(ctx, idata, dio_hnd);
+
+	crystalhd_unmap_dio(ctx->adp, dio_hnd);
+
+	return sts;
+}
+
+static BC_STATUS bc_cproc_add_cap_buff(struct crystalhd_cmd *ctx,
+				       crystalhd_ioctl_data *idata)
+{
+	void *ubuff;
+	uint32_t ub_sz, uv_off;
+	bool en_422;
+	crystalhd_dio_req *dio_hnd = NULL;
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	if (!ctx || !idata) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	ubuff = idata->udata.u.RxBuffs.YuvBuff;
+	ub_sz = idata->udata.u.RxBuffs.YuvBuffSz;
+	uv_off = idata->udata.u.RxBuffs.UVbuffOffset;
+	en_422 = idata->udata.u.RxBuffs.b422Mode;
+
+	sts = bc_cproc_check_inbuffs(0, ubuff, ub_sz, uv_off, en_422);
+	if (sts != BC_STS_SUCCESS)
+		return sts;
+
+	sts = crystalhd_map_dio(ctx->adp, ubuff, ub_sz, uv_off,
+			      en_422, 0, &dio_hnd);
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG_ERR("dio map - %d \n", sts);
+		return sts;
+	}
+
+	if (!dio_hnd)
+		return BC_STS_ERROR;
+
+	sts = crystalhd_hw_add_cap_buffer(&ctx->hw_ctx, dio_hnd, (ctx->state == BC_LINK_READY));
+	if ((sts != BC_STS_SUCCESS) && (sts != BC_STS_BUSY)) {
+		crystalhd_unmap_dio(ctx->adp, dio_hnd);
+		return sts;
+	}
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_fmt_change(struct crystalhd_cmd *ctx,
+				     crystalhd_dio_req *dio)
+{
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	sts = crystalhd_hw_add_cap_buffer(&ctx->hw_ctx, dio, 0);
+	if (sts != BC_STS_SUCCESS)
+		return sts;
+
+	ctx->state |= BC_LINK_FMT_CHG;
+	if (ctx->state == BC_LINK_READY)
+		sts = crystalhd_hw_start_capture(&ctx->hw_ctx);
+
+	return sts;
+}
+
+static BC_STATUS bc_cproc_fetch_frame(struct crystalhd_cmd *ctx,
+				      crystalhd_ioctl_data *idata)
+{
+	crystalhd_dio_req *dio = NULL;
+	BC_STATUS sts = BC_STS_SUCCESS;
+	BC_DEC_OUT_BUFF *frame;
+
+	if (!ctx || !idata) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if (!(ctx->state & BC_LINK_CAP_EN)) {
+		BCMLOG(BCMLOG_DBG, "Capture not enabled..%x\n", ctx->state);
+		return BC_STS_ERR_USAGE;
+	}
+
+	frame = &idata->udata.u.DecOutData;
+
+	sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx, &frame->PibInfo, &dio);
+	if (sts != BC_STS_SUCCESS)
+		return (ctx->state & BC_LINK_SUSPEND) ? BC_STS_IO_USER_ABORT : sts;
+
+	frame->Flags = dio->uinfo.comp_flags;
+
+	if (frame->Flags & COMP_FLAG_FMT_CHANGE)
+		return bc_cproc_fmt_change(ctx, dio);
+
+	frame->OutPutBuffs.YuvBuff = dio->uinfo.xfr_buff;
+	frame->OutPutBuffs.YuvBuffSz = dio->uinfo.xfr_len;
+	frame->OutPutBuffs.UVbuffOffset = dio->uinfo.uv_offset;
+	frame->OutPutBuffs.b422Mode = dio->uinfo.b422mode;
+
+	frame->OutPutBuffs.YBuffDoneSz = dio->uinfo.y_done_sz;
+	frame->OutPutBuffs.UVBuffDoneSz = dio->uinfo.uv_done_sz;
+
+	crystalhd_unmap_dio(ctx->adp, dio);
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_start_capture(struct crystalhd_cmd *ctx,
+					crystalhd_ioctl_data *idata)
+{
+	ctx->state |= BC_LINK_CAP_EN;
+	if (ctx->state == BC_LINK_READY)
+		return crystalhd_hw_start_capture(&ctx->hw_ctx);
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_flush_cap_buffs(struct crystalhd_cmd *ctx,
+					  crystalhd_ioctl_data *idata)
+{
+	crystalhd_dio_req *dio = NULL;
+	BC_STATUS sts = BC_STS_SUCCESS;
+	BC_DEC_OUT_BUFF *frame;
+	uint32_t count;
+
+	if (!ctx || !idata) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if (!(ctx->state & BC_LINK_CAP_EN))
+		return BC_STS_ERR_USAGE;
+
+	/* We should ack flush even when we are in paused/suspend state */
+	if (!(ctx->state & BC_LINK_READY))
+		return crystalhd_hw_stop_capture(&ctx->hw_ctx);
+
+	ctx->state &= ~(BC_LINK_CAP_EN|BC_LINK_FMT_CHG);
+
+	frame = &idata->udata.u.DecOutData;
+	for (count = 0; count < BC_RX_LIST_CNT; count++) {
+
+		sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx, &frame->PibInfo, &dio);
+		if (sts != BC_STS_SUCCESS)
+			break;
+
+		crystalhd_unmap_dio(ctx->adp, dio);
+	}
+
+	return crystalhd_hw_stop_capture(&ctx->hw_ctx);
+}
+
+static BC_STATUS bc_cproc_get_stats(struct crystalhd_cmd *ctx,
+				    crystalhd_ioctl_data *idata)
+{
+	BC_DTS_STATS *stats;
+	struct crystalhd_hw_stats	hw_stats;
+
+	if (!ctx || !idata) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	crystalhd_hw_stats(&ctx->hw_ctx, &hw_stats);
+
+	stats = &idata->udata.u.drvStat;
+	stats->drvRLL = hw_stats.rdyq_count;
+	stats->drvFLL = hw_stats.freeq_count;
+	stats->DrvTotalFrmDropped = hw_stats.rx_errors;
+	stats->DrvTotalHWErrs = hw_stats.rx_errors + hw_stats.tx_errors;
+	stats->intCount = hw_stats.num_interrupts;
+	stats->DrvIgnIntrCnt = hw_stats.num_interrupts -
+				hw_stats.dev_interrupts;
+	stats->TxFifoBsyCnt = hw_stats.cin_busy;
+	stats->pauseCount = hw_stats.pause_cnt;
+
+	if (ctx->pwr_state_change)
+		stats->pwr_state_change = 1;
+	if (ctx->state & BC_LINK_PAUSED)
+		stats->DrvPauseTime = 1;
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_reset_stats(struct crystalhd_cmd *ctx,
+				      crystalhd_ioctl_data *idata)
+{
+	crystalhd_hw_stats(&ctx->hw_ctx, NULL);
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_chg_clk(struct crystalhd_cmd *ctx,
+				  crystalhd_ioctl_data *idata)
+{
+	BC_CLOCK *clock;
+	uint32_t oldClk;
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	if (!ctx || !idata) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	clock = &idata->udata.u.clockValue;
+	oldClk = ctx->hw_ctx.core_clock_mhz;
+	ctx->hw_ctx.core_clock_mhz = clock->clk;
+
+	if (ctx->state & BC_LINK_READY) {
+		sts = crystalhd_hw_set_core_clock(&ctx->hw_ctx);
+		if (sts == BC_STS_CLK_NOCHG)
+			ctx->hw_ctx.core_clock_mhz = oldClk;
+	}
+
+	clock->clk = ctx->hw_ctx.core_clock_mhz;
+
+	return sts;
+}
+
+/*=============== Cmd Proc Table.. ======================================*/
+static const crystalhd_cmd_tbl_t	g_crystalhd_cproc_tbl[] = {
+	{ BCM_IOC_GET_VERSION,		bc_cproc_get_version,	0},
+	{ BCM_IOC_GET_HWTYPE,		bc_cproc_get_hwtype,	0},
+	{ BCM_IOC_REG_RD,		bc_cproc_reg_rd,	0},
+	{ BCM_IOC_REG_WR,		bc_cproc_reg_wr,	0},
+	{ BCM_IOC_FPGA_RD,		bc_cproc_link_reg_rd,	0},
+	{ BCM_IOC_FPGA_WR,		bc_cproc_link_reg_wr,	0},
+	{ BCM_IOC_MEM_RD,		bc_cproc_mem_rd,	0},
+	{ BCM_IOC_MEM_WR,		bc_cproc_mem_wr,	0},
+	{ BCM_IOC_RD_PCI_CFG,		bc_cproc_cfg_rd,	0},
+	{ BCM_IOC_WR_PCI_CFG,		bc_cproc_cfg_wr,	1},
+	{ BCM_IOC_FW_DOWNLOAD,		bc_cproc_download_fw,	1},
+	{ BCM_IOC_FW_CMD,		bc_cproc_do_fw_cmd,	1},
+	{ BCM_IOC_PROC_INPUT,		bc_cproc_proc_input,	1},
+	{ BCM_IOC_ADD_RXBUFFS,		bc_cproc_add_cap_buff,	1},
+	{ BCM_IOC_FETCH_RXBUFF,		bc_cproc_fetch_frame,	1},
+	{ BCM_IOC_START_RX_CAP,		bc_cproc_start_capture,	1},
+	{ BCM_IOC_FLUSH_RX_CAP,		bc_cproc_flush_cap_buffs, 1},
+	{ BCM_IOC_GET_DRV_STAT,		bc_cproc_get_stats,	0},
+	{ BCM_IOC_RST_DRV_STAT,		bc_cproc_reset_stats,	0},
+	{ BCM_IOC_NOTIFY_MODE,		bc_cproc_notify_mode,	0},
+	{ BCM_IOC_CHG_CLK,		bc_cproc_chg_clk, 0},
+	{ BCM_IOC_END,			NULL},
+};
+
+/*=============== Cmd Proc Functions.. ===================================*/
+
+/**
+ * crystalhd_suspend - Power management suspend request.
+ * @ctx: Command layer context.
+ * @idata: Iodata - required for internal use.
+ *
+ * Return:
+ *	status
+ *
+ * 1. Set the state to Suspend.
+ * 2. Flush the Rx Buffers it will unmap all the buffers and
+ *    stop the RxDMA engine.
+ * 3. Cancel The TX Io and Stop Dma Engine.
+ * 4. Put the DDR in to deep sleep.
+ * 5. Stop the hardware putting it in to Reset State.
+ *
+ * Current gstreamer frame work does not provide any power management
+ * related notification to user mode decoder plug-in. As a work-around
+ * we pass on the power mangement notification to our plug-in by completing
+ * all outstanding requests with BC_STS_IO_USER_ABORT return code.
+ */
+BC_STATUS crystalhd_suspend(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
+{
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	if (!ctx || !idata) {
+		BCMLOG_ERR("Invalid Parameters\n");
+		return BC_STS_ERROR;
+	}
+
+	if (ctx->state & BC_LINK_SUSPEND)
+		return BC_STS_SUCCESS;
+
+	if (ctx->state == BC_LINK_INVALID) {
+		BCMLOG(BCMLOG_DBG, "Nothing To Do Suspend Success\n");
+		return BC_STS_SUCCESS;
+	}
+
+	ctx->state |= BC_LINK_SUSPEND;
+
+	bc_cproc_mark_pwr_state(ctx);
+
+	if (ctx->state & BC_LINK_CAP_EN) {
+		sts = bc_cproc_flush_cap_buffs(ctx, idata);
+		if (sts != BC_STS_SUCCESS)
+			return sts;
+	}
+
+	if (ctx->tx_list_id) {
+		sts = crystalhd_hw_cancel_tx(&ctx->hw_ctx, ctx->tx_list_id);
+		if (sts != BC_STS_SUCCESS)
+			return sts;
+	}
+
+	sts = crystalhd_hw_suspend(&ctx->hw_ctx);
+	if (sts != BC_STS_SUCCESS)
+		return sts;
+
+	BCMLOG(BCMLOG_DBG, "BCM70012 suspend success\n");
+
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_resume - Resume frame capture.
+ * @ctx: Command layer contextx.
+ *
+ * Return:
+ *	status
+ *
+ *
+ * Resume frame capture.
+ *
+ * PM_Resume can't resume the playback state back to pre-suspend state
+ * because we don't keep video clip related information within driver.
+ * To get back to the pre-suspend state App will re-open the device and
+ * start a new playback session from the pre-suspend clip position.
+ *
+ */
+BC_STATUS crystalhd_resume(struct crystalhd_cmd *ctx)
+{
+	BCMLOG(BCMLOG_DBG, "crystalhd_resume Success %x\n", ctx->state);
+
+	bc_cproc_mark_pwr_state(ctx);
+
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_user_open - Create application handle.
+ * @ctx: Command layer contextx.
+ * @user_ctx: User ID context.
+ *
+ * Return:
+ *	status
+ *
+ * Creates an application specific UID and allocates
+ * application specific resources. HW layer initialization
+ * is done for the first open request.
+ */
+BC_STATUS crystalhd_user_open(struct crystalhd_cmd *ctx,
+			    struct crystalhd_user **user_ctx)
+{
+	struct crystalhd_user *uc;
+
+	if (!ctx || !user_ctx) {
+		BCMLOG_ERR("Invalid arg..\n");
+		return BC_STS_INV_ARG;
+	}
+
+	uc = bc_cproc_get_uid(ctx);
+	if (!uc) {
+		BCMLOG(BCMLOG_INFO, "No free user context...\n");
+		return BC_STS_BUSY;
+	}
+
+	BCMLOG(BCMLOG_INFO, "Opening new user[%x] handle\n", uc->uid);
+
+	crystalhd_hw_open(&ctx->hw_ctx, ctx->adp);
+
+	uc->in_use = 1;
+
+	*user_ctx = uc;
+
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_user_close - Close application handle.
+ * @ctx: Command layer contextx.
+ * @uc: User ID context.
+ *
+ * Return:
+ *	status
+ *
+ * Closer aplication handle and release app specific
+ * resources.
+ */
+BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_user *uc)
+{
+	uint32_t mode = uc->mode;
+
+	ctx->user[uc->uid].mode = DTS_MODE_INV;
+	ctx->user[uc->uid].in_use = 0;
+	ctx->cin_wait_exit = 1;
+	ctx->pwr_state_change = 0;
+
+	BCMLOG(BCMLOG_INFO, "Closing user[%x] handle\n", uc->uid);
+
+	if ((mode == DTS_DIAG_MODE) || (mode == DTS_PLAYBACK_MODE)) {
+		crystalhd_hw_free_dma_rings(&ctx->hw_ctx);
+		crystalhd_destroy_dio_pool(ctx->adp);
+	} else if (bc_cproc_get_user_count(ctx)) {
+		return BC_STS_SUCCESS;
+	}
+
+	crystalhd_hw_close(&ctx->hw_ctx);
+
+	ctx->state = BC_LINK_INVALID;
+
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_setup_cmd_context - Setup Command layer resources.
+ * @ctx: Command layer contextx.
+ * @adp: Adapter context
+ *
+ * Return:
+ *	status
+ *
+ * Called at the time of driver load.
+ */
+BC_STATUS __devinit crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
+				    struct crystalhd_adp *adp)
+{
+	int i = 0;
+
+	if (!ctx || !adp) {
+		BCMLOG_ERR("Invalid arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if (ctx->adp)
+		BCMLOG(BCMLOG_DBG, "Resetting Cmd context delete missing..\n");
+
+	ctx->adp = adp;
+	for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
+		ctx->user[i].uid = i;
+		ctx->user[i].in_use = 0;
+		ctx->user[i].mode = DTS_MODE_INV;
+	}
+
+	/*Open and Close the Hardware to put it in to sleep state*/
+	crystalhd_hw_open(&ctx->hw_ctx, ctx->adp);
+	crystalhd_hw_close(&ctx->hw_ctx);
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_delete_cmd_context - Release Command layer resources.
+ * @ctx: Command layer contextx.
+ *
+ * Return:
+ *	status
+ *
+ * Called at the time of driver un-load.
+ */
+BC_STATUS __devexit crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx)
+{
+	BCMLOG(BCMLOG_DBG, "Deleting Command context..\n");
+
+	ctx->adp = NULL;
+
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_get_cmd_proc  - Cproc table lookup.
+ * @ctx: Command layer contextx.
+ * @cmd: IOCTL command code.
+ * @uc: User ID context.
+ *
+ * Return:
+ *	command proc function pointer
+ *
+ * This function checks the process context, application's
+ * mode of operation and returns the function pointer
+ * from the cproc table.
+ */
+crystalhd_cmd_proc crystalhd_get_cmd_proc(struct crystalhd_cmd *ctx, uint32_t cmd,
+				      struct crystalhd_user *uc)
+{
+	crystalhd_cmd_proc cproc = NULL;
+	unsigned int i, tbl_sz;
+
+	if (!ctx) {
+		BCMLOG_ERR("Invalid arg.. Cmd[%d]\n", cmd);
+		return NULL;
+	}
+
+	if ((cmd != BCM_IOC_GET_DRV_STAT) && (ctx->state & BC_LINK_SUSPEND)) {
+		BCMLOG_ERR("Invalid State [suspend Set].. Cmd[%d]\n", cmd);
+		return NULL;
+	}
+
+	tbl_sz = sizeof(g_crystalhd_cproc_tbl) / sizeof(crystalhd_cmd_tbl_t);
+	for (i = 0; i < tbl_sz; i++) {
+		if (g_crystalhd_cproc_tbl[i].cmd_id == cmd) {
+			if ((uc->mode == DTS_MONITOR_MODE) &&
+			    (g_crystalhd_cproc_tbl[i].block_mon)) {
+				BCMLOG(BCMLOG_INFO, "Blocking cmd %d \n", cmd);
+				break;
+			}
+			cproc = g_crystalhd_cproc_tbl[i].cmd_proc;
+			break;
+		}
+	}
+
+	return cproc;
+}
+
+/**
+ * crystalhd_cmd_interrupt - ISR entry point
+ * @ctx: Command layer contextx.
+ *
+ * Return:
+ *	TRUE: If interrupt from bcm70012 device.
+ *
+ *
+ * ISR entry point from OS layer.
+ */
+bool crystalhd_cmd_interrupt(struct crystalhd_cmd *ctx)
+{
+	if (!ctx) {
+		BCMLOG_ERR("Invalid arg..\n");
+		return 0;
+	}
+
+	return crystalhd_hw_interrupt(ctx->adp, &ctx->hw_ctx);
+}
diff --git a/drivers/staging/crystalhd/crystalhd_cmds.h b/drivers/staging/crystalhd/crystalhd_cmds.h
new file mode 100644
index 0000000..6b290ae
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_cmds.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ *  Name: crystalhd_cmds . h
+ *
+ *  Description:
+ *		BCM70010 Linux driver user command interfaces.
+ *
+ *  HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * This driver is free software; 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 driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#ifndef _CRYSTALHD_CMDS_H_
+#define _CRYSTALHD_CMDS_H_
+
+/*
+ * NOTE:: This is the main interface file between the Linux layer
+ *        and the harware layer. This file will use the definitions
+ *        from _dts_glob and dts_defs etc.. which are defined for
+ *        windows.
+ */
+#include "crystalhd_misc.h"
+#include "crystalhd_hw.h"
+
+enum _crystalhd_state{
+	BC_LINK_INVALID		= 0x00,
+	BC_LINK_INIT		= 0x01,
+	BC_LINK_CAP_EN		= 0x02,
+	BC_LINK_FMT_CHG		= 0x04,
+	BC_LINK_SUSPEND		= 0x10,
+	BC_LINK_PAUSED		= 0x20,
+	BC_LINK_READY	= (BC_LINK_INIT | BC_LINK_CAP_EN | BC_LINK_FMT_CHG),
+};
+
+struct crystalhd_user {
+	uint32_t	uid;
+	uint32_t	in_use;
+	uint32_t	mode;
+};
+
+#define DTS_MODE_INV	(-1)
+
+struct crystalhd_cmd {
+	uint32_t		state;
+	struct crystalhd_adp	*adp;
+	struct crystalhd_user	user[BC_LINK_MAX_OPENS];
+
+	spinlock_t		ctx_lock;
+	uint32_t		tx_list_id;
+	uint32_t		cin_wait_exit;
+	uint32_t		pwr_state_change;
+	struct crystalhd_hw	hw_ctx;
+};
+
+typedef BC_STATUS (*crystalhd_cmd_proc)(struct crystalhd_cmd *, crystalhd_ioctl_data *);
+
+typedef struct _crystalhd_cmd_tbl {
+	uint32_t		cmd_id;
+	const crystalhd_cmd_proc	cmd_proc;
+	uint32_t		block_mon;
+} crystalhd_cmd_tbl_t;
+
+
+BC_STATUS crystalhd_suspend(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata);
+BC_STATUS crystalhd_resume(struct crystalhd_cmd *ctx);
+crystalhd_cmd_proc crystalhd_get_cmd_proc(struct crystalhd_cmd *ctx, uint32_t cmd,
+				      struct crystalhd_user *uc);
+BC_STATUS crystalhd_user_open(struct crystalhd_cmd *ctx, struct crystalhd_user **user_ctx);
+BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_user *uc);
+BC_STATUS crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx, struct crystalhd_adp *adp);
+BC_STATUS crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx);
+bool crystalhd_cmd_interrupt(struct crystalhd_cmd *ctx);
+
+#endif
diff --git a/drivers/staging/crystalhd/crystalhd_fw_if.h b/drivers/staging/crystalhd/crystalhd_fw_if.h
new file mode 100644
index 0000000..261cd19
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_fw_if.h
@@ -0,0 +1,369 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ *  Name: crystalhd_fw_if . h
+ *
+ *  Description:
+ *		BCM70012 Firmware interface definitions.
+ *
+ *  HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * This driver is free software; 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 driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#ifndef _CRYSTALHD_FW_IF_H_
+#define _CRYSTALHD_FW_IF_H_
+
+/* TBD: Pull in only required defs into this file.. */
+
+
+
+/* User Data Header */
+typedef struct user_data {
+   struct user_data	*next;
+   uint32_t		type;
+   uint32_t		size;
+} UD_HDR;
+
+
+
+/*------------------------------------------------------*
+ *    MPEG Extension to the PPB			 *
+ *------------------------------------------------------*/
+typedef struct {
+   uint32_t		to_be_defined;
+   uint32_t		valid;
+
+   /* Always valid, defaults to picture size if no
+      sequence display extension in the stream. */
+   uint32_t		display_horizontal_size;
+   uint32_t		display_vertical_size;
+
+   /* MPEG_VALID_PANSCAN
+      Offsets are a copy values from the MPEG stream. */
+   uint32_t		offset_count;
+   int32_t		horizontal_offset[3];
+   int32_t		vertical_offset[3];
+
+   /* MPEG_VALID_USERDATA
+      User data is in the form of a linked list. */
+   int32_t		userDataSize;
+   UD_HDR		*userData;
+
+} PPB_MPEG;
+
+
+/*------------------------------------------------------*
+ *    VC1 Extension to the PPB			  *
+ *------------------------------------------------------*/
+typedef struct {
+   uint32_t		to_be_defined;
+   uint32_t		valid;
+
+   /* Always valid, defaults to picture size if no
+      sequence display extension in the stream. */
+   uint32_t		display_horizontal_size;
+   uint32_t		display_vertical_size;
+
+  /* VC1 pan scan windows */
+   uint32_t		num_panscan_windows;
+   int32_t		ps_horiz_offset[4];
+   int32_t		ps_vert_offset[4];
+   int32_t		ps_width[4];
+   int32_t		ps_height[4];
+
+   /* VC1_VALID_USERDATA
+      User data is in the form of a linked list. */
+   int32_t		userDataSize;
+   UD_HDR		*userData;
+
+} PPB_VC1;
+
+/*------------------------------------------------------*
+ *    H.264 Extension to the PPB			*
+ *------------------------------------------------------*/
+
+/**
+ * @brief Film grain SEI message.
+ *
+ * Content of the film grain SEI message.
+ */
+
+/* maximum number of model-values as for Thomson spec(standard says 5) */
+#define MAX_FGT_MODEL_VALUE	 (3)
+
+/* maximum number of intervals(as many as 256 intervals?) */
+#define MAX_FGT_VALUE_INTERVAL	(256)
+
+typedef struct FGT_SEI {
+    struct FGT_SEI *next;
+    unsigned char model_values[3][MAX_FGT_VALUE_INTERVAL][MAX_FGT_MODEL_VALUE];
+    unsigned char upper_bound[3][MAX_FGT_VALUE_INTERVAL];
+    unsigned char lower_bound[3][MAX_FGT_VALUE_INTERVAL];
+
+    unsigned char cancel_flag;	/* Cancel flag: 1 no film grain. */
+    unsigned char model_id;	/* Model id. */
+
+    /* +unused SE based on Thomson spec */
+    unsigned char color_desc_flag;	/* Separate color descrition flag. */
+    unsigned char bit_depth_luma;	/* Bit depth luma minus 8. */
+    unsigned char bit_depth_chroma;	/* Bit depth chroma minus 8. */
+    unsigned char full_range_flag;	/* Full range flag. */
+    unsigned char color_primaries;	/* Color primaries. */
+    unsigned char transfer_charact;	/* Transfer characteristics. */
+    unsigned char matrix_coeff;		/*< Matrix coefficients. */
+    /* -unused SE based on Thomson spec */
+
+    unsigned char blending_mode_id;	/* Blending mode. */
+    unsigned char log2_scale_factor;	/* Log2 scale factor (2-7). */
+    unsigned char comp_flag[3];		/* Components [0,2] parameters present flag. */
+    unsigned char num_intervals_minus1[3]; /* Number of intensity level intervals. */
+    unsigned char num_model_values[3];	/* Number of model values. */
+    uint16_t      repetition_period;	/* Repetition period (0-16384) */
+
+} FGT_SEI;
+
+typedef struct {
+   /* 'valid' specifies which fields (or sets of
+    * fields) below are valid.  If the corresponding
+    * bit in 'valid' is NOT set then that field(s)
+    * is (are) not initialized. */
+   uint32_t	valid;
+
+   int32_t		poc_top;	/* POC for Top Field/Frame */
+   int32_t		poc_bottom;	/* POC for Bottom Field    */
+   uint32_t		idr_pic_id;
+
+   /* H264_VALID_PANSCAN */
+   uint32_t		pan_scan_count;
+   int32_t		pan_scan_left[3];
+   int32_t		pan_scan_right[3];
+   int32_t		pan_scan_top[3];
+   int32_t		pan_scan_bottom[3];
+
+   /* H264_VALID_CT_TYPE */
+   uint32_t		ct_type_count;
+   uint32_t		ct_type[3];
+
+   /* H264_VALID_SPS_CROP */
+   int32_t		sps_crop_left;
+   int32_t		sps_crop_right;
+   int32_t		sps_crop_top;
+   int32_t		sps_crop_bottom;
+
+   /* H264_VALID_VUI */
+   uint32_t		chroma_top;
+   uint32_t		chroma_bottom;
+
+   /* H264_VALID_USER */
+   uint32_t		user_data_size;
+   UD_HDR		*user_data;
+
+   /* H264 VALID FGT */
+   FGT_SEI		*pfgt;
+
+} PPB_H264;
+
+typedef struct {
+   /* Common fields. */
+   uint32_t	picture_number;	/* Ordinal display number */
+   uint32_t	video_buffer;	/* Video (picbuf) number */
+   uint32_t	video_address;	/* Address of picbuf Y */
+   uint32_t	video_address_uv; /* Address of picbuf UV */
+   uint32_t	video_stripe;	/* Picbuf stripe */
+   uint32_t	video_width;	/* Picbuf width */
+   uint32_t	video_height;	/* Picbuf height */
+
+   uint32_t	channel_id;	/* Decoder channel ID */
+   uint32_t	status;		/* reserved */
+   uint32_t	width;		/* pixels */
+   uint32_t	height;		/* pixels */
+   uint32_t	chroma_format;	/* see above */
+   uint32_t	pulldown;	/* see above */
+   uint32_t	flags;		/* see above */
+   uint32_t	pts;		/* 32 LSBs of PTS */
+   uint32_t	protocol;	/* protocolXXX (above) */
+
+   uint32_t	frame_rate;	/* see above */
+   uint32_t	matrix_coeff;	/* see above */
+   uint32_t	aspect_ratio;	/* see above */
+   uint32_t	colour_primaries; /* see above */
+   uint32_t	transfer_char;	/* see above */
+   uint32_t	pcr_offset;	/* 45kHz if PCR type; else 27MHz */
+   uint32_t	n_drop;		/* Number of pictures to be dropped */
+
+   uint32_t	custom_aspect_ratio_width_height;
+			/* upper 16-bits is Y and lower 16-bits is X */
+
+   uint32_t	picture_tag;	/* Indexing tag from BUD packets */
+   uint32_t	picture_done_payload;
+   uint32_t	picture_meta_payload;
+   uint32_t	reserved[1];
+
+   /* Protocol-specific extensions. */
+   union {
+      PPB_H264	h264;
+      PPB_MPEG	mpeg;
+      PPB_VC1	 vc1;
+   } other;
+
+} PPB;
+
+typedef struct {
+   uint32_t	bFormatChange;
+   uint32_t	resolution;
+   uint32_t	channelId;
+   uint32_t	ppbPtr;
+   int32_t	ptsStcOffset;
+   uint32_t	zeroPanscanValid;
+   uint32_t	dramOutBufAddr;
+   uint32_t	yComponent;
+   PPB			ppb;
+
+} C011_PIB;
+
+
+
+typedef struct {
+    uint32_t	command;
+    uint32_t	sequence;
+    uint32_t	status;
+    uint32_t	picBuf;
+    uint32_t	picRelBuf;
+    uint32_t	picInfoDeliveryQ;
+    uint32_t	picInfoReleaseQ;
+    uint32_t	channelStatus;
+    uint32_t	userDataDeliveryQ;
+    uint32_t	userDataReleaseQ;
+    uint32_t	transportStreamCaptureAddr;
+    uint32_t	asyncEventQ;
+
+} DecRspChannelStartVideo;
+
+#define eCMD_C011_CMD_BASE	  (0x73763000)
+
+/* host commands */
+typedef enum {
+    eCMD_TS_GET_NEXT_PIC	= 0x7376F100, /* debug get next picture */
+    eCMD_TS_GET_LAST_PIC	= 0x7376F102, /* debug get last pic status */
+    eCMD_TS_READ_WRITE_MEM	= 0x7376F104, /* debug read write memory */
+
+    /* New API commands */
+    /* General commands */
+    eCMD_C011_INIT		= eCMD_C011_CMD_BASE + 0x01,
+    eCMD_C011_RESET		= eCMD_C011_CMD_BASE + 0x02,
+    eCMD_C011_SELF_TEST		= eCMD_C011_CMD_BASE + 0x03,
+    eCMD_C011_GET_VERSION	= eCMD_C011_CMD_BASE + 0x04,
+    eCMD_C011_GPIO		= eCMD_C011_CMD_BASE + 0x05,
+    eCMD_C011_DEBUG_SETUP	= eCMD_C011_CMD_BASE + 0x06,
+
+    /* Decoding commands */
+    eCMD_C011_DEC_CHAN_OPEN			= eCMD_C011_CMD_BASE + 0x100,
+    eCMD_C011_DEC_CHAN_CLOSE			= eCMD_C011_CMD_BASE + 0x101,
+    eCMD_C011_DEC_CHAN_ACTIVATE			= eCMD_C011_CMD_BASE + 0x102,
+    eCMD_C011_DEC_CHAN_STATUS			= eCMD_C011_CMD_BASE + 0x103,
+    eCMD_C011_DEC_CHAN_FLUSH			= eCMD_C011_CMD_BASE + 0x104,
+    eCMD_C011_DEC_CHAN_TRICK_PLAY		= eCMD_C011_CMD_BASE + 0x105,
+    eCMD_C011_DEC_CHAN_TS_PIDS			= eCMD_C011_CMD_BASE + 0x106,
+    eCMD_C011_DEC_CHAN_PS_STREAM_ID		= eCMD_C011_CMD_BASE + 0x107,
+    eCMD_C011_DEC_CHAN_INPUT_PARAMS		= eCMD_C011_CMD_BASE + 0x108,
+    eCMD_C011_DEC_CHAN_VIDEO_OUTPUT		= eCMD_C011_CMD_BASE + 0x109,
+    eCMD_C011_DEC_CHAN_OUTPUT_FORMAT		= eCMD_C011_CMD_BASE + 0x10A,
+    eCMD_C011_DEC_CHAN_SCALING_FILTERS		= eCMD_C011_CMD_BASE + 0x10B,
+    eCMD_C011_DEC_CHAN_OSD_MODE			= eCMD_C011_CMD_BASE + 0x10D,
+    eCMD_C011_DEC_CHAN_DROP			= eCMD_C011_CMD_BASE + 0x10E,
+    eCMD_C011_DEC_CHAN_RELEASE			= eCMD_C011_CMD_BASE + 0x10F,
+    eCMD_C011_DEC_CHAN_STREAM_SETTINGS		= eCMD_C011_CMD_BASE + 0x110,
+    eCMD_C011_DEC_CHAN_PAUSE_OUTPUT		= eCMD_C011_CMD_BASE + 0x111,
+    eCMD_C011_DEC_CHAN_CHANGE			= eCMD_C011_CMD_BASE + 0x112,
+    eCMD_C011_DEC_CHAN_SET_STC			= eCMD_C011_CMD_BASE + 0x113,
+    eCMD_C011_DEC_CHAN_SET_PTS			= eCMD_C011_CMD_BASE + 0x114,
+    eCMD_C011_DEC_CHAN_CC_MODE			= eCMD_C011_CMD_BASE + 0x115,
+    eCMD_C011_DEC_CREATE_AUDIO_CONTEXT		= eCMD_C011_CMD_BASE + 0x116,
+    eCMD_C011_DEC_COPY_AUDIO_CONTEXT		= eCMD_C011_CMD_BASE + 0x117,
+    eCMD_C011_DEC_DELETE_AUDIO_CONTEXT		= eCMD_C011_CMD_BASE + 0x118,
+    eCMD_C011_DEC_CHAN_SET_DECYPTION		= eCMD_C011_CMD_BASE + 0x119,
+    eCMD_C011_DEC_CHAN_START_VIDEO		= eCMD_C011_CMD_BASE + 0x11A,
+    eCMD_C011_DEC_CHAN_STOP_VIDEO		= eCMD_C011_CMD_BASE + 0x11B,
+    eCMD_C011_DEC_CHAN_PIC_CAPTURE		= eCMD_C011_CMD_BASE + 0x11C,
+    eCMD_C011_DEC_CHAN_PAUSE			= eCMD_C011_CMD_BASE + 0x11D,
+    eCMD_C011_DEC_CHAN_PAUSE_STATE		= eCMD_C011_CMD_BASE + 0x11E,
+    eCMD_C011_DEC_CHAN_SET_SLOWM_RATE		= eCMD_C011_CMD_BASE + 0x11F,
+    eCMD_C011_DEC_CHAN_GET_SLOWM_RATE		= eCMD_C011_CMD_BASE + 0x120,
+    eCMD_C011_DEC_CHAN_SET_FF_RATE		= eCMD_C011_CMD_BASE + 0x121,
+    eCMD_C011_DEC_CHAN_GET_FF_RATE		= eCMD_C011_CMD_BASE + 0x122,
+    eCMD_C011_DEC_CHAN_FRAME_ADVANCE		= eCMD_C011_CMD_BASE + 0x123,
+    eCMD_C011_DEC_CHAN_SET_SKIP_PIC_MODE	= eCMD_C011_CMD_BASE + 0x124,
+    eCMD_C011_DEC_CHAN_GET_SKIP_PIC_MODE	= eCMD_C011_CMD_BASE + 0x125,
+    eCMD_C011_DEC_CHAN_FILL_PIC_BUF		= eCMD_C011_CMD_BASE + 0x126,
+    eCMD_C011_DEC_CHAN_SET_CONTINUITY_CHECK	= eCMD_C011_CMD_BASE + 0x127,
+    eCMD_C011_DEC_CHAN_GET_CONTINUITY_CHECK	= eCMD_C011_CMD_BASE + 0x128,
+    eCMD_C011_DEC_CHAN_SET_BRCM_TRICK_MODE	= eCMD_C011_CMD_BASE + 0x129,
+    eCMD_C011_DEC_CHAN_GET_BRCM_TRICK_MODE	= eCMD_C011_CMD_BASE + 0x12A,
+    eCMD_C011_DEC_CHAN_REVERSE_FIELD_STATUS	= eCMD_C011_CMD_BASE + 0x12B,
+    eCMD_C011_DEC_CHAN_I_PICTURE_FOUND		= eCMD_C011_CMD_BASE + 0x12C,
+    eCMD_C011_DEC_CHAN_SET_PARAMETER		= eCMD_C011_CMD_BASE + 0x12D,
+    eCMD_C011_DEC_CHAN_SET_USER_DATA_MODE	= eCMD_C011_CMD_BASE + 0x12E,
+    eCMD_C011_DEC_CHAN_SET_PAUSE_DISPLAY_MODE	= eCMD_C011_CMD_BASE + 0x12F,
+    eCMD_C011_DEC_CHAN_SET_SLOW_DISPLAY_MODE	= eCMD_C011_CMD_BASE + 0x130,
+    eCMD_C011_DEC_CHAN_SET_FF_DISPLAY_MODE	= eCMD_C011_CMD_BASE + 0x131,
+    eCMD_C011_DEC_CHAN_SET_DISPLAY_TIMING_MODE	= eCMD_C011_CMD_BASE + 0x132,
+    eCMD_C011_DEC_CHAN_SET_DISPLAY_MODE		= eCMD_C011_CMD_BASE + 0x133,
+    eCMD_C011_DEC_CHAN_GET_DISPLAY_MODE		= eCMD_C011_CMD_BASE + 0x134,
+    eCMD_C011_DEC_CHAN_SET_REVERSE_FIELD	= eCMD_C011_CMD_BASE + 0x135,
+    eCMD_C011_DEC_CHAN_STREAM_OPEN		= eCMD_C011_CMD_BASE + 0x136,
+    eCMD_C011_DEC_CHAN_SET_PCR_PID		= eCMD_C011_CMD_BASE + 0x137,
+    eCMD_C011_DEC_CHAN_SET_VID_PID		= eCMD_C011_CMD_BASE + 0x138,
+    eCMD_C011_DEC_CHAN_SET_PAN_SCAN_MODE	= eCMD_C011_CMD_BASE + 0x139,
+    eCMD_C011_DEC_CHAN_START_DISPLAY_AT_PTS	= eCMD_C011_CMD_BASE + 0x140,
+    eCMD_C011_DEC_CHAN_STOP_DISPLAY_AT_PTS	= eCMD_C011_CMD_BASE + 0x141,
+    eCMD_C011_DEC_CHAN_SET_DISPLAY_ORDER	= eCMD_C011_CMD_BASE + 0x142,
+    eCMD_C011_DEC_CHAN_GET_DISPLAY_ORDER	= eCMD_C011_CMD_BASE + 0x143,
+    eCMD_C011_DEC_CHAN_SET_HOST_TRICK_MODE	= eCMD_C011_CMD_BASE + 0x144,
+    eCMD_C011_DEC_CHAN_SET_OPERATION_MODE	= eCMD_C011_CMD_BASE + 0x145,
+    eCMD_C011_DEC_CHAN_DISPLAY_PAUSE_UNTO_PTS	= eCMD_C011_CMD_BASE + 0x146,
+    eCMD_C011_DEC_CHAN_SET_PTS_STC_DIFF_THRESHOLD = eCMD_C011_CMD_BASE + 0x147,
+    eCMD_C011_DEC_CHAN_SEND_COMPRESSED_BUF	= eCMD_C011_CMD_BASE + 0x148,
+    eCMD_C011_DEC_CHAN_SET_CLIPPING		= eCMD_C011_CMD_BASE + 0x149,
+    eCMD_C011_DEC_CHAN_SET_PARAMETERS_FOR_HARD_RESET_INTERRUPT_TO_HOST
+						= eCMD_C011_CMD_BASE + 0x150,
+
+    /* Decoder RevD commands */
+    eCMD_C011_DEC_CHAN_SET_CSC	= eCMD_C011_CMD_BASE + 0x180, /* color space conversion */
+    eCMD_C011_DEC_CHAN_SET_RANGE_REMAP	= eCMD_C011_CMD_BASE + 0x181,
+    eCMD_C011_DEC_CHAN_SET_FGT		= eCMD_C011_CMD_BASE + 0x182,
+    /* Note: 0x183 not implemented yet in Rev D main */
+    eCMD_C011_DEC_CHAN_SET_LASTPICTURE_PADDING = eCMD_C011_CMD_BASE + 0x183,
+
+    /* Decoder 7412 commands (7412-only) */
+    eCMD_C011_DEC_CHAN_SET_CONTENT_KEY	= eCMD_C011_CMD_BASE + 0x190,
+    eCMD_C011_DEC_CHAN_SET_SESSION_KEY	= eCMD_C011_CMD_BASE + 0x191,
+    eCMD_C011_DEC_CHAN_FMT_CHANGE_ACK	= eCMD_C011_CMD_BASE + 0x192,
+
+    eCMD_C011_DEC_CHAN_CUSTOM_VIDOUT    = eCMD_C011_CMD_BASE + 0x1FF,
+
+    /* Encoding commands */
+    eCMD_C011_ENC_CHAN_OPEN		= eCMD_C011_CMD_BASE + 0x200,
+    eCMD_C011_ENC_CHAN_CLOSE		= eCMD_C011_CMD_BASE + 0x201,
+    eCMD_C011_ENC_CHAN_ACTIVATE		= eCMD_C011_CMD_BASE + 0x202,
+    eCMD_C011_ENC_CHAN_CONTROL		= eCMD_C011_CMD_BASE + 0x203,
+    eCMD_C011_ENC_CHAN_STATISTICS	= eCMD_C011_CMD_BASE + 0x204,
+
+    eNOTIFY_C011_ENC_CHAN_EVENT		= eCMD_C011_CMD_BASE + 0x210,
+
+} eC011_TS_CMD;
+
+#endif
diff --git a/drivers/staging/crystalhd/crystalhd_hw.c b/drivers/staging/crystalhd/crystalhd_hw.c
new file mode 100644
index 0000000..01819d3
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_hw.c
@@ -0,0 +1,2395 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ *  Name: crystalhd_hw . c
+ *
+ *  Description:
+ *		BCM70010 Linux driver HW layer.
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * This driver is free software; 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 driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include "crystalhd_hw.h"
+
+/* Functions internal to this file */
+
+static void crystalhd_enable_uarts(struct crystalhd_adp *adp)
+{
+	bc_dec_reg_wr(adp, UartSelectA, BSVS_UART_STREAM);
+	bc_dec_reg_wr(adp, UartSelectB, BSVS_UART_DEC_OUTER);
+}
+
+
+static void crystalhd_start_dram(struct crystalhd_adp *adp)
+{
+	bc_dec_reg_wr(adp, SDRAM_PARAM, ((40 / 5 - 1) <<  0) |
+	/* tras (40ns tras)/(5ns period) -1 ((15/5 - 1) <<  4) | // trcd */
+		      ((15 / 5 - 1) <<  7) |	/* trp */
+		      ((10 / 5 - 1) << 10) |	/* trrd */
+		      ((15 / 5 + 1) << 12) |	/* twr */
+		      ((2 + 1) << 16) |		/* twtr */
+		      ((70 / 5 - 2) << 19) |	/* trfc */
+		      (0 << 23));
+
+	bc_dec_reg_wr(adp, SDRAM_PRECHARGE, 0);
+	bc_dec_reg_wr(adp, SDRAM_EXT_MODE, 2);
+	bc_dec_reg_wr(adp, SDRAM_MODE, 0x132);
+	bc_dec_reg_wr(adp, SDRAM_PRECHARGE, 0);
+	bc_dec_reg_wr(adp, SDRAM_REFRESH, 0);
+	bc_dec_reg_wr(adp, SDRAM_REFRESH, 0);
+	bc_dec_reg_wr(adp, SDRAM_MODE, 0x32);
+	/* setting the refresh rate here */
+	bc_dec_reg_wr(adp, SDRAM_REF_PARAM, ((1 << 12) | 96));
+}
+
+
+static bool crystalhd_bring_out_of_rst(struct crystalhd_adp *adp)
+{
+	link_misc_perst_deco_ctrl rst_deco_cntrl;
+	link_misc_perst_clk_ctrl rst_clk_cntrl;
+	uint32_t temp;
+
+	/*
+	 * Link clocks: MISC_PERST_CLOCK_CTRL Clear PLL power down bit,
+	 * delay to allow PLL to lock Clear alternate clock, stop clock bits
+	 */
+	rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
+	rst_clk_cntrl.pll_pwr_dn = 0;
+	crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
+	msleep_interruptible(50);
+
+	rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
+	rst_clk_cntrl.stop_core_clk = 0;
+	rst_clk_cntrl.sel_alt_clk = 0;
+
+	crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
+	msleep_interruptible(50);
+
+	/*
+	 * Bus Arbiter Timeout: GISB_ARBITER_TIMER
+	 * Set internal bus arbiter timeout to 40us based on core clock speed
+	 * (63MHz * 40us = 0x9D8)
+	 */
+	crystalhd_reg_wr(adp, GISB_ARBITER_TIMER, 0x9D8);
+
+	/*
+	 * Decoder clocks: MISC_PERST_DECODER_CTRL
+	 * Enable clocks while 7412 reset is asserted, delay
+	 * De-assert 7412 reset
+	 */
+	rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_DECODER_CTRL);
+	rst_deco_cntrl.stop_bcm_7412_clk = 0;
+	rst_deco_cntrl.bcm7412_rst = 1;
+	crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL, rst_deco_cntrl.whole_reg);
+	msleep_interruptible(10);
+
+	rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_DECODER_CTRL);
+	rst_deco_cntrl.bcm7412_rst = 0;
+	crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL, rst_deco_cntrl.whole_reg);
+	msleep_interruptible(50);
+
+	/* Disable OTP_CONTENT_MISC to 0 to disable all secure modes */
+	crystalhd_reg_wr(adp, OTP_CONTENT_MISC, 0);
+
+	/* Clear bit 29 of 0x404 */
+	temp = crystalhd_reg_rd(adp, PCIE_TL_TRANSACTION_CONFIGURATION);
+	temp &= ~BC_BIT(29);
+	crystalhd_reg_wr(adp, PCIE_TL_TRANSACTION_CONFIGURATION, temp);
+
+	/* 2.5V regulator must be set to 2.6 volts (+6%) */
+	/* FIXME: jarod: what's the point of this reg read? */
+	temp = crystalhd_reg_rd(adp, MISC_PERST_VREG_CTRL);
+	crystalhd_reg_wr(adp, MISC_PERST_VREG_CTRL, 0xF3);
+
+	return true;
+}
+
+static bool crystalhd_put_in_reset(struct crystalhd_adp *adp)
+{
+	link_misc_perst_deco_ctrl rst_deco_cntrl;
+	link_misc_perst_clk_ctrl  rst_clk_cntrl;
+	uint32_t                  temp;
+
+	/*
+	 * Decoder clocks: MISC_PERST_DECODER_CTRL
+	 * Assert 7412 reset, delay
+	 * Assert 7412 stop clock
+	 */
+	rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_DECODER_CTRL);
+	rst_deco_cntrl.stop_bcm_7412_clk = 1;
+	crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL, rst_deco_cntrl.whole_reg);
+	msleep_interruptible(50);
+
+	/* Bus Arbiter Timeout: GISB_ARBITER_TIMER
+	 * Set internal bus arbiter timeout to 40us based on core clock speed
+	 * (6.75MHZ * 40us = 0x10E)
+	 */
+	crystalhd_reg_wr(adp, GISB_ARBITER_TIMER, 0x10E);
+
+	/* Link clocks: MISC_PERST_CLOCK_CTRL
+	 * Stop core clk, delay
+	 * Set alternate clk, delay, set PLL power down
+	 */
+	rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
+	rst_clk_cntrl.stop_core_clk = 1;
+	rst_clk_cntrl.sel_alt_clk = 1;
+	crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
+	msleep_interruptible(50);
+
+	rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
+	rst_clk_cntrl.pll_pwr_dn = 1;
+	crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
+
+	/*
+	 * Read and restore the Transaction Configuration Register
+	 * after core reset
+	 */
+	temp = crystalhd_reg_rd(adp, PCIE_TL_TRANSACTION_CONFIGURATION);
+
+	/*
+	 * Link core soft reset: MISC3_RESET_CTRL
+	 * - Write BIT[0]=1 and read it back for core reset to take place
+	 */
+	crystalhd_reg_wr(adp, MISC3_RESET_CTRL, 1);
+	rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC3_RESET_CTRL);
+	msleep_interruptible(50);
+
+	/* restore the transaction configuration register */
+	crystalhd_reg_wr(adp, PCIE_TL_TRANSACTION_CONFIGURATION, temp);
+
+	return true;
+}
+
+static void crystalhd_disable_interrupts(struct crystalhd_adp *adp)
+{
+	intr_mask_reg   intr_mask;
+	intr_mask.whole_reg = crystalhd_reg_rd(adp, INTR_INTR_MSK_STS_REG);
+	intr_mask.mask_pcie_err = 1;
+	intr_mask.mask_pcie_rbusmast_err = 1;
+	intr_mask.mask_pcie_rgr_bridge   = 1;
+	intr_mask.mask_rx_done = 1;
+	intr_mask.mask_rx_err  = 1;
+	intr_mask.mask_tx_done = 1;
+	intr_mask.mask_tx_err  = 1;
+	crystalhd_reg_wr(adp, INTR_INTR_MSK_SET_REG, intr_mask.whole_reg);
+
+	return;
+}
+
+static void crystalhd_enable_interrupts(struct crystalhd_adp *adp)
+{
+	intr_mask_reg   intr_mask;
+	intr_mask.whole_reg = crystalhd_reg_rd(adp, INTR_INTR_MSK_STS_REG);
+	intr_mask.mask_pcie_err = 1;
+	intr_mask.mask_pcie_rbusmast_err = 1;
+	intr_mask.mask_pcie_rgr_bridge   = 1;
+	intr_mask.mask_rx_done = 1;
+	intr_mask.mask_rx_err  = 1;
+	intr_mask.mask_tx_done = 1;
+	intr_mask.mask_tx_err  = 1;
+	crystalhd_reg_wr(adp, INTR_INTR_MSK_CLR_REG, intr_mask.whole_reg);
+
+	return;
+}
+
+static void crystalhd_clear_errors(struct crystalhd_adp *adp)
+{
+	uint32_t reg;
+
+	/* FIXME: jarod: wouldn't we want to write a 0 to the reg? Or does the write clear the bits specified? */
+	reg = crystalhd_reg_rd(adp, MISC1_Y_RX_ERROR_STATUS);
+	if (reg)
+		crystalhd_reg_wr(adp, MISC1_Y_RX_ERROR_STATUS, reg);
+
+	reg = crystalhd_reg_rd(adp, MISC1_UV_RX_ERROR_STATUS);
+	if (reg)
+		crystalhd_reg_wr(adp, MISC1_UV_RX_ERROR_STATUS, reg);
+
+	reg = crystalhd_reg_rd(adp, MISC1_TX_DMA_ERROR_STATUS);
+	if (reg)
+		crystalhd_reg_wr(adp, MISC1_TX_DMA_ERROR_STATUS, reg);
+}
+
+static void crystalhd_clear_interrupts(struct crystalhd_adp *adp)
+{
+	uint32_t intr_sts = crystalhd_reg_rd(adp, INTR_INTR_STATUS);
+
+	if (intr_sts) {
+		crystalhd_reg_wr(adp, INTR_INTR_CLR_REG, intr_sts);
+
+		/* Write End Of Interrupt for PCIE */
+		crystalhd_reg_wr(adp, INTR_EOI_CTRL, 1);
+	}
+}
+
+static void crystalhd_soft_rst(struct crystalhd_adp *adp)
+{
+	uint32_t val;
+
+	/* Assert c011 soft reset*/
+	bc_dec_reg_wr(adp, DecHt_HostSwReset, 0x00000001);
+	msleep_interruptible(50);
+
+	/* Release c011 soft reset*/
+	bc_dec_reg_wr(adp, DecHt_HostSwReset, 0x00000000);
+
+	/* Disable Stuffing..*/
+	val = crystalhd_reg_rd(adp, MISC2_GLOBAL_CTRL);
+	val |= BC_BIT(8);
+	crystalhd_reg_wr(adp, MISC2_GLOBAL_CTRL, val);
+}
+
+static bool crystalhd_load_firmware_config(struct crystalhd_adp *adp)
+{
+	uint32_t i = 0, reg;
+
+	crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (BC_DRAM_FW_CFG_ADDR >> 19));
+
+	crystalhd_reg_wr(adp, AES_CMD, 0);
+	crystalhd_reg_wr(adp, AES_CONFIG_INFO, (BC_DRAM_FW_CFG_ADDR & 0x7FFFF));
+	crystalhd_reg_wr(adp, AES_CMD, 0x1);
+
+	/* FIXME: jarod: I've seen this fail, and introducing extra delays helps... */
+	for (i = 0; i < 100; ++i) {
+		reg = crystalhd_reg_rd(adp, AES_STATUS);
+		if (reg & 0x1)
+			return true;
+		msleep_interruptible(10);
+	}
+
+	return false;
+}
+
+
+static bool crystalhd_start_device(struct crystalhd_adp *adp)
+{
+	uint32_t dbg_options, glb_cntrl = 0, reg_pwrmgmt = 0;
+
+	BCMLOG(BCMLOG_INFO, "Starting BCM70012 Device\n");
+
+	reg_pwrmgmt = crystalhd_reg_rd(adp, PCIE_DLL_DATA_LINK_CONTROL);
+	reg_pwrmgmt &= ~ASPM_L1_ENABLE;
+
+	crystalhd_reg_wr(adp, PCIE_DLL_DATA_LINK_CONTROL, reg_pwrmgmt);
+
+	if (!crystalhd_bring_out_of_rst(adp)) {
+		BCMLOG_ERR("Failed To Bring Link Out Of Reset\n");
+		return false;
+	}
+
+	crystalhd_disable_interrupts(adp);
+
+	crystalhd_clear_errors(adp);
+
+	crystalhd_clear_interrupts(adp);
+
+	crystalhd_enable_interrupts(adp);
+
+	/* Enable the option for getting the total no. of DWORDS
+	 * that have been transfered by the RXDMA engine
+	 */
+	dbg_options = crystalhd_reg_rd(adp, MISC1_DMA_DEBUG_OPTIONS_REG);
+	dbg_options |= 0x10;
+	crystalhd_reg_wr(adp, MISC1_DMA_DEBUG_OPTIONS_REG, dbg_options);
+
+	/* Enable PCI Global Control options */
+	glb_cntrl = crystalhd_reg_rd(adp, MISC2_GLOBAL_CTRL);
+	glb_cntrl |= 0x100;
+	glb_cntrl |= 0x8000;
+	crystalhd_reg_wr(adp, MISC2_GLOBAL_CTRL, glb_cntrl);
+
+	crystalhd_enable_interrupts(adp);
+
+	crystalhd_soft_rst(adp);
+	crystalhd_start_dram(adp);
+	crystalhd_enable_uarts(adp);
+
+	return true;
+}
+
+static bool crystalhd_stop_device(struct crystalhd_adp *adp)
+{
+	uint32_t reg;
+
+	BCMLOG(BCMLOG_INFO, "Stopping BCM70012 Device\n");
+	/* Clear and disable interrupts */
+	crystalhd_disable_interrupts(adp);
+	crystalhd_clear_errors(adp);
+	crystalhd_clear_interrupts(adp);
+
+	if (!crystalhd_put_in_reset(adp))
+		BCMLOG_ERR("Failed to Put Link To Reset State\n");
+
+	reg = crystalhd_reg_rd(adp, PCIE_DLL_DATA_LINK_CONTROL);
+	reg |= ASPM_L1_ENABLE;
+	crystalhd_reg_wr(adp, PCIE_DLL_DATA_LINK_CONTROL, reg);
+
+	/* Set PCI Clk Req */
+	reg = crystalhd_reg_rd(adp, PCIE_CLK_REQ_REG);
+	reg |= PCI_CLK_REQ_ENABLE;
+	crystalhd_reg_wr(adp, PCIE_CLK_REQ_REG, reg);
+
+	return true;
+}
+
+static crystalhd_rx_dma_pkt *crystalhd_hw_alloc_rx_pkt(struct crystalhd_hw *hw)
+{
+	unsigned long flags = 0;
+	crystalhd_rx_dma_pkt *temp = NULL;
+
+	if (!hw)
+		return NULL;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	temp = hw->rx_pkt_pool_head;
+	if (temp) {
+		hw->rx_pkt_pool_head = hw->rx_pkt_pool_head->next;
+		temp->dio_req = NULL;
+		temp->pkt_tag = 0;
+		temp->flags = 0;
+	}
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	return temp;
+}
+
+static void crystalhd_hw_free_rx_pkt(struct crystalhd_hw *hw,
+				   crystalhd_rx_dma_pkt *pkt)
+{
+	unsigned long flags = 0;
+
+	if (!hw || !pkt)
+		return;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	pkt->next = hw->rx_pkt_pool_head;
+	hw->rx_pkt_pool_head = pkt;
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+/*
+ * Call back from TX - IOQ deletion.
+ *
+ * This routine will release the TX DMA rings allocated
+ * druing setup_dma rings interface.
+ *
+ * Memory is allocated per DMA ring basis. This is just
+ * a place holder to be able to create the dio queues.
+ */
+static void crystalhd_tx_desc_rel_call_back(void *context, void *data)
+{
+}
+
+/*
+ * Rx Packet release callback..
+ *
+ * Release All user mapped capture buffers and Our DMA packets
+ * back to our free pool. The actual cleanup of the DMA
+ * ring descriptors happen during dma ring release.
+ */
+static void crystalhd_rx_pkt_rel_call_back(void *context, void *data)
+{
+	struct crystalhd_hw *hw = (struct crystalhd_hw *)context;
+	crystalhd_rx_dma_pkt *pkt = (crystalhd_rx_dma_pkt *)data;
+
+	if (!pkt || !hw) {
+		BCMLOG_ERR("Invalid arg - %p %p\n", hw, pkt);
+		return;
+	}
+
+	if (pkt->dio_req)
+		crystalhd_unmap_dio(hw->adp, pkt->dio_req);
+	else
+		BCMLOG_ERR("Missing dio_req: 0x%x\n", pkt->pkt_tag);
+
+	crystalhd_hw_free_rx_pkt(hw, pkt);
+}
+
+#define crystalhd_hw_delete_ioq(adp, q)		\
+	if (q) {				\
+		crystalhd_delete_dioq(adp, q);	\
+		q = NULL;			\
+	}
+
+static void crystalhd_hw_delete_ioqs(struct crystalhd_hw *hw)
+{
+	if (!hw)
+		return;
+
+	BCMLOG(BCMLOG_DBG, "Deleting IOQs \n");
+	crystalhd_hw_delete_ioq(hw->adp, hw->tx_actq);
+	crystalhd_hw_delete_ioq(hw->adp, hw->tx_freeq);
+	crystalhd_hw_delete_ioq(hw->adp, hw->rx_actq);
+	crystalhd_hw_delete_ioq(hw->adp, hw->rx_freeq);
+	crystalhd_hw_delete_ioq(hw->adp, hw->rx_rdyq);
+}
+
+#define crystalhd_hw_create_ioq(sts, hw, q, cb)			\
+do {								\
+	sts = crystalhd_create_dioq(hw->adp, &q, cb, hw);	\
+	if (sts != BC_STS_SUCCESS)				\
+		goto hw_create_ioq_err;				\
+} while (0)
+
+/*
+ * Create IOQs..
+ *
+ * TX - Active & Free
+ * RX - Active, Ready and Free.
+ */
+static BC_STATUS crystalhd_hw_create_ioqs(struct crystalhd_hw   *hw)
+{
+	BC_STATUS   sts = BC_STS_SUCCESS;
+
+	if (!hw) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	crystalhd_hw_create_ioq(sts, hw, hw->tx_freeq,
+			      crystalhd_tx_desc_rel_call_back);
+	crystalhd_hw_create_ioq(sts, hw, hw->tx_actq,
+			      crystalhd_tx_desc_rel_call_back);
+
+	crystalhd_hw_create_ioq(sts, hw, hw->rx_freeq,
+			      crystalhd_rx_pkt_rel_call_back);
+	crystalhd_hw_create_ioq(sts, hw, hw->rx_rdyq,
+			      crystalhd_rx_pkt_rel_call_back);
+	crystalhd_hw_create_ioq(sts, hw, hw->rx_actq,
+			      crystalhd_rx_pkt_rel_call_back);
+
+	return sts;
+
+hw_create_ioq_err:
+	crystalhd_hw_delete_ioqs(hw);
+
+	return sts;
+}
+
+
+static bool crystalhd_code_in_full(struct crystalhd_adp *adp, uint32_t needed_sz,
+				 bool b_188_byte_pkts,  uint8_t flags)
+{
+	uint32_t base, end, writep, readp;
+	uint32_t cpbSize, cpbFullness, fifoSize;
+
+	if (flags & 0x02) { /* ASF Bit is set */
+		base   = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Base);
+		end    = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2End);
+		writep = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Wrptr);
+		readp  = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Rdptr);
+	} else if (b_188_byte_pkts) { /*Encrypted 188 byte packets*/
+		base   = bc_dec_reg_rd(adp, REG_Dec_TsUser0Base);
+		end    = bc_dec_reg_rd(adp, REG_Dec_TsUser0End);
+		writep = bc_dec_reg_rd(adp, REG_Dec_TsUser0Wrptr);
+		readp  = bc_dec_reg_rd(adp, REG_Dec_TsUser0Rdptr);
+	} else {
+		base   = bc_dec_reg_rd(adp, REG_DecCA_RegCinBase);
+		end    = bc_dec_reg_rd(adp, REG_DecCA_RegCinEnd);
+		writep = bc_dec_reg_rd(adp, REG_DecCA_RegCinWrPtr);
+		readp  = bc_dec_reg_rd(adp, REG_DecCA_RegCinRdPtr);
+	}
+
+	cpbSize = end - base;
+	if (writep >= readp)
+		cpbFullness = writep - readp;
+	else
+		cpbFullness = (end - base) - (readp - writep);
+
+	fifoSize = cpbSize - cpbFullness;
+
+	if (fifoSize < BC_INFIFO_THRESHOLD)
+		return true;
+
+	if (needed_sz > (fifoSize - BC_INFIFO_THRESHOLD))
+		return true;
+
+	return false;
+}
+
+static BC_STATUS crystalhd_hw_tx_req_complete(struct crystalhd_hw *hw,
+					    uint32_t list_id, BC_STATUS cs)
+{
+	tx_dma_pkt *tx_req;
+
+	if (!hw || !list_id) {
+		BCMLOG_ERR("Invalid Arg..\n");
+		return BC_STS_INV_ARG;
+	}
+
+	hw->pwr_lock--;
+
+	tx_req = (tx_dma_pkt *)crystalhd_dioq_find_and_fetch(hw->tx_actq, list_id);
+	if (!tx_req) {
+		if (cs != BC_STS_IO_USER_ABORT)
+			BCMLOG_ERR("Find and Fetch Did not find req\n");
+		return BC_STS_NO_DATA;
+	}
+
+	if (tx_req->call_back) {
+		tx_req->call_back(tx_req->dio_req, tx_req->cb_event, cs);
+		tx_req->dio_req   = NULL;
+		tx_req->cb_event  = NULL;
+		tx_req->call_back = NULL;
+	} else {
+		BCMLOG(BCMLOG_DBG, "Missing Tx Callback - %X\n",
+		       tx_req->list_tag);
+	}
+
+	/* Now put back the tx_list back in FreeQ */
+	tx_req->list_tag = 0;
+
+	return crystalhd_dioq_add(hw->tx_freeq, tx_req, false, 0);
+}
+
+static bool crystalhd_tx_list0_handler(struct crystalhd_hw *hw, uint32_t err_sts)
+{
+	uint32_t err_mask, tmp;
+	unsigned long flags = 0;
+
+	err_mask = MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_MASK |
+		MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_MASK |
+		MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK;
+
+	if (!(err_sts & err_mask))
+		return false;
+
+	BCMLOG_ERR("Error on Tx-L0 %x \n", err_sts);
+
+	tmp = err_mask;
+
+	if (err_sts & MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK)
+		tmp &= ~MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK;
+
+	if (tmp) {
+		spin_lock_irqsave(&hw->lock, flags);
+		/* reset list index.*/
+		hw->tx_list_post_index = 0;
+		spin_unlock_irqrestore(&hw->lock, flags);
+	}
+
+	tmp = err_sts & err_mask;
+	crystalhd_reg_wr(hw->adp, MISC1_TX_DMA_ERROR_STATUS, tmp);
+
+	return true;
+}
+
+static bool crystalhd_tx_list1_handler(struct crystalhd_hw *hw, uint32_t err_sts)
+{
+	uint32_t err_mask, tmp;
+	unsigned long flags = 0;
+
+	err_mask = MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_MASK |
+		MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_MASK |
+		MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK;
+
+	if (!(err_sts & err_mask))
+		return false;
+
+	BCMLOG_ERR("Error on Tx-L1 %x \n", err_sts);
+
+	tmp = err_mask;
+
+	if (err_sts & MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK)
+		tmp &= ~MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK;
+
+	if (tmp) {
+		spin_lock_irqsave(&hw->lock, flags);
+		/* reset list index.*/
+		hw->tx_list_post_index = 0;
+		spin_unlock_irqrestore(&hw->lock, flags);
+	}
+
+	tmp = err_sts & err_mask;
+	crystalhd_reg_wr(hw->adp, MISC1_TX_DMA_ERROR_STATUS, tmp);
+
+	return true;
+}
+
+static void crystalhd_tx_isr(struct crystalhd_hw *hw, uint32_t int_sts)
+{
+	uint32_t err_sts;
+
+	if (int_sts & INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_MASK)
+		crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 0,
+					   BC_STS_SUCCESS);
+
+	if (int_sts & INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_MASK)
+		crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 1,
+					   BC_STS_SUCCESS);
+
+	if (!(int_sts & (INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_MASK |
+			 INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_MASK))) {
+			 /* No error mask set.. */
+			 return;
+	}
+
+	/* Handle Tx errors. */
+	err_sts = crystalhd_reg_rd(hw->adp, MISC1_TX_DMA_ERROR_STATUS);
+
+	if (crystalhd_tx_list0_handler(hw, err_sts))
+		crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 0,
+					   BC_STS_ERROR);
+
+	if (crystalhd_tx_list1_handler(hw, err_sts))
+		crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 1,
+					   BC_STS_ERROR);
+
+	hw->stats.tx_errors++;
+}
+
+static void crystalhd_hw_dump_desc(pdma_descriptor p_dma_desc,
+				 uint32_t ul_desc_index, uint32_t cnt)
+{
+	uint32_t ix, ll = 0;
+
+	if (!p_dma_desc || !cnt)
+		return;
+
+	/* FIXME: jarod: perhaps a modparam desc_debug to enable this, rather than
+	 * setting ll (log level, I presume) to non-zero? */
+	if (!ll)
+		return;
+
+	for (ix = ul_desc_index; ix < (ul_desc_index + cnt); ix++) {
+		BCMLOG(ll, "%s[%d] Buff[%x:%x] Next:[%x:%x] XferSz:%x Intr:%x,Last:%x\n",
+		       ((p_dma_desc[ul_desc_index].dma_dir) ? "TDesc" : "RDesc"),
+		       ul_desc_index,
+		       p_dma_desc[ul_desc_index].buff_addr_high,
+		       p_dma_desc[ul_desc_index].buff_addr_low,
+		       p_dma_desc[ul_desc_index].next_desc_addr_high,
+		       p_dma_desc[ul_desc_index].next_desc_addr_low,
+		       p_dma_desc[ul_desc_index].xfer_size,
+		       p_dma_desc[ul_desc_index].intr_enable,
+		       p_dma_desc[ul_desc_index].last_rec_indicator);
+	}
+
+}
+
+static BC_STATUS crystalhd_hw_fill_desc(crystalhd_dio_req *ioreq,
+				      dma_descriptor *desc,
+				      dma_addr_t desc_paddr_base,
+				      uint32_t sg_cnt, uint32_t sg_st_ix,
+				      uint32_t sg_st_off, uint32_t xfr_sz)
+{
+	uint32_t count = 0, ix = 0, sg_ix = 0, len = 0, last_desc_ix = 0;
+	dma_addr_t desc_phy_addr = desc_paddr_base;
+	addr_64 addr_temp;
+
+	if (!ioreq || !desc || !desc_paddr_base || !xfr_sz ||
+	    (!sg_cnt && !ioreq->uinfo.dir_tx)) {
+		BCMLOG_ERR("Invalid Args\n");
+		return BC_STS_INV_ARG;
+	}
+
+	for (ix = 0; ix < sg_cnt; ix++) {
+
+		/* Setup SGLE index. */
+		sg_ix = ix + sg_st_ix;
+
+		/* Get SGLE length */
+		len = crystalhd_get_sgle_len(ioreq, sg_ix);
+		if (len % 4) {
+			BCMLOG_ERR(" len in sg %d %d %d\n", len, sg_ix, sg_cnt);
+			return BC_STS_NOT_IMPL;
+		}
+		/* Setup DMA desc with Phy addr & Length at current index. */
+		addr_temp.full_addr = crystalhd_get_sgle_paddr(ioreq, sg_ix);
+		if (sg_ix == sg_st_ix) {
+			addr_temp.full_addr += sg_st_off;
+			len -= sg_st_off;
+		}
+		memset(&desc[ix], 0, sizeof(desc[ix]));
+		desc[ix].buff_addr_low  = addr_temp.low_part;
+		desc[ix].buff_addr_high = addr_temp.high_part;
+		desc[ix].dma_dir        = ioreq->uinfo.dir_tx;
+
+		/* Chain DMA descriptor.  */
+		addr_temp.full_addr = desc_phy_addr + sizeof(dma_descriptor);
+		desc[ix].next_desc_addr_low = addr_temp.low_part;
+		desc[ix].next_desc_addr_high = addr_temp.high_part;
+
+		if ((count + len) > xfr_sz)
+			len = xfr_sz - count;
+
+		/* Debug.. */
+		if ((!len) || (len > crystalhd_get_sgle_len(ioreq, sg_ix))) {
+			BCMLOG_ERR("inv-len(%x) Ix(%d) count:%x xfr_sz:%x sg_cnt:%d\n",
+				   len, ix, count, xfr_sz, sg_cnt);
+			return BC_STS_ERROR;
+		}
+		/* Length expects Multiple of 4 */
+		desc[ix].xfer_size = (len / 4);
+
+		crystalhd_hw_dump_desc(desc, ix, 1);
+
+		count += len;
+		desc_phy_addr += sizeof(dma_descriptor);
+	}
+
+	last_desc_ix = ix - 1;
+
+	if (ioreq->fb_size) {
+		memset(&desc[ix], 0, sizeof(desc[ix]));
+		addr_temp.full_addr     = ioreq->fb_pa;
+		desc[ix].buff_addr_low  = addr_temp.low_part;
+		desc[ix].buff_addr_high = addr_temp.high_part;
+		desc[ix].dma_dir        = ioreq->uinfo.dir_tx;
+		desc[ix].xfer_size	= 1;
+		desc[ix].fill_bytes	= 4 - ioreq->fb_size;
+		count += ioreq->fb_size;
+		last_desc_ix++;
+	}
+
+	/* setup last descriptor..*/
+	desc[last_desc_ix].last_rec_indicator  = 1;
+	desc[last_desc_ix].next_desc_addr_low  = 0;
+	desc[last_desc_ix].next_desc_addr_high = 0;
+	desc[last_desc_ix].intr_enable = 1;
+
+	crystalhd_hw_dump_desc(desc, last_desc_ix, 1);
+
+	if (count != xfr_sz) {
+		BCMLOG_ERR("interal error sz curr:%x exp:%x\n", count, xfr_sz);
+		return BC_STS_ERROR;
+	}
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS crystalhd_xlat_sgl_to_dma_desc(crystalhd_dio_req *ioreq,
+					      pdma_desc_mem pdesc_mem,
+					      uint32_t *uv_desc_index)
+{
+	dma_descriptor *desc = NULL;
+	dma_addr_t desc_paddr_base = 0;
+	uint32_t sg_cnt = 0, sg_st_ix = 0, sg_st_off = 0;
+	uint32_t xfr_sz = 0;
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	/* Check params.. */
+	if (!ioreq || !pdesc_mem || !uv_desc_index) {
+		BCMLOG_ERR("Invalid Args\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if (!pdesc_mem->sz || !pdesc_mem->pdma_desc_start ||
+	    !ioreq->sg || (!ioreq->sg_cnt && !ioreq->uinfo.dir_tx)) {
+		BCMLOG_ERR("Invalid Args\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if ((ioreq->uinfo.dir_tx) && (ioreq->uinfo.uv_offset)) {
+		BCMLOG_ERR("UV offset for TX??\n");
+		return BC_STS_INV_ARG;
+
+	}
+
+	desc = pdesc_mem->pdma_desc_start;
+	desc_paddr_base = pdesc_mem->phy_addr;
+
+	if (ioreq->uinfo.dir_tx || (ioreq->uinfo.uv_offset == 0)) {
+		sg_cnt = ioreq->sg_cnt;
+		xfr_sz = ioreq->uinfo.xfr_len;
+	} else {
+		sg_cnt = ioreq->uinfo.uv_sg_ix + 1;
+		xfr_sz = ioreq->uinfo.uv_offset;
+	}
+
+	sts = crystalhd_hw_fill_desc(ioreq, desc, desc_paddr_base, sg_cnt,
+				   sg_st_ix, sg_st_off, xfr_sz);
+
+	if ((sts != BC_STS_SUCCESS) || !ioreq->uinfo.uv_offset)
+		return sts;
+
+	/* Prepare for UV mapping.. */
+	desc = &pdesc_mem->pdma_desc_start[sg_cnt];
+	desc_paddr_base = pdesc_mem->phy_addr +
+			  (sg_cnt * sizeof(dma_descriptor));
+
+	/* Done with desc addr.. now update sg stuff.*/
+	sg_cnt    = ioreq->sg_cnt - ioreq->uinfo.uv_sg_ix;
+	xfr_sz    = ioreq->uinfo.xfr_len - ioreq->uinfo.uv_offset;
+	sg_st_ix  = ioreq->uinfo.uv_sg_ix;
+	sg_st_off = ioreq->uinfo.uv_sg_off;
+
+	sts = crystalhd_hw_fill_desc(ioreq, desc, desc_paddr_base, sg_cnt,
+				   sg_st_ix, sg_st_off, xfr_sz);
+	if (sts != BC_STS_SUCCESS)
+		return sts;
+
+	*uv_desc_index = sg_st_ix;
+
+	return sts;
+}
+
+static void crystalhd_start_tx_dma_engine(struct crystalhd_hw *hw)
+{
+	uint32_t dma_cntrl;
+
+	dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS);
+	if (!(dma_cntrl & DMA_START_BIT)) {
+		dma_cntrl |= DMA_START_BIT;
+		crystalhd_reg_wr(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS,
+			       dma_cntrl);
+	}
+
+	return;
+}
+
+/* _CHECK_THIS_
+ *
+ * Verify if the Stop generates a completion interrupt or not.
+ * if it does not generate an interrupt, then add polling here.
+ */
+static BC_STATUS crystalhd_stop_tx_dma_engine(struct crystalhd_hw *hw)
+{
+	uint32_t dma_cntrl, cnt = 30;
+	uint32_t l1 = 1, l2 = 1;
+	unsigned long flags = 0;
+
+	dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS);
+
+	BCMLOG(BCMLOG_DBG, "Stopping TX DMA Engine..\n");
+
+	/* FIXME: jarod: invert dma_ctrl and check bit? or are there missing parens? */
+	if (!dma_cntrl & DMA_START_BIT) {
+		BCMLOG(BCMLOG_DBG, "Already Stopped\n");
+		return BC_STS_SUCCESS;
+	}
+
+	crystalhd_disable_interrupts(hw->adp);
+
+	/* Issue stop to HW */
+	/* This bit when set gave problems. Please check*/
+	dma_cntrl &= ~DMA_START_BIT;
+	crystalhd_reg_wr(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+
+	BCMLOG(BCMLOG_DBG, "Cleared the DMA Start bit\n");
+
+	/* Poll for 3seconds (30 * 100ms) on both the lists..*/
+	while ((l1 || l2) && cnt) {
+
+		if (l1) {
+			l1 = crystalhd_reg_rd(hw->adp, MISC1_TX_FIRST_DESC_L_ADDR_LIST0);
+			l1 &= DMA_START_BIT;
+		}
+
+		if (l2) {
+			l2 = crystalhd_reg_rd(hw->adp, MISC1_TX_FIRST_DESC_L_ADDR_LIST1);
+			l2 &= DMA_START_BIT;
+		}
+
+		msleep_interruptible(100);
+
+		cnt--;
+	}
+
+	if (!cnt) {
+		BCMLOG_ERR("Failed to stop TX DMA.. l1 %d, l2 %d\n", l1, l2);
+		crystalhd_enable_interrupts(hw->adp);
+		return BC_STS_ERROR;
+	}
+
+	spin_lock_irqsave(&hw->lock, flags);
+	hw->tx_list_post_index = 0;
+	spin_unlock_irqrestore(&hw->lock, flags);
+	BCMLOG(BCMLOG_DBG, "stopped TX DMA..\n");
+	crystalhd_enable_interrupts(hw->adp);
+
+	return BC_STS_SUCCESS;
+}
+
+static uint32_t crystalhd_get_pib_avail_cnt(struct crystalhd_hw *hw)
+{
+	/*
+	* Position of the PIB Entries can be found at
+	* 0th and the 1st location of the Circular list.
+	*/
+	uint32_t Q_addr;
+	uint32_t pib_cnt, r_offset, w_offset;
+
+	Q_addr = hw->pib_del_Q_addr;
+
+	/* Get the Read Pointer */
+	crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
+
+	/* Get the Write Pointer */
+	crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
+
+	if (r_offset == w_offset)
+		return 0;	/* Queue is empty */
+
+	if (w_offset > r_offset)
+		pib_cnt = w_offset - r_offset;
+	else
+		pib_cnt = (w_offset + MAX_PIB_Q_DEPTH) -
+			  (r_offset + MIN_PIB_Q_DEPTH);
+
+	if (pib_cnt > MAX_PIB_Q_DEPTH) {
+		BCMLOG_ERR("Invalid PIB Count (%u)\n", pib_cnt);
+		return 0;
+	}
+
+	return pib_cnt;
+}
+
+static uint32_t crystalhd_get_addr_from_pib_Q(struct crystalhd_hw *hw)
+{
+	uint32_t Q_addr;
+	uint32_t addr_entry, r_offset, w_offset;
+
+	Q_addr = hw->pib_del_Q_addr;
+
+	/* Get the Read Pointer 0Th Location is Read Pointer */
+	crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
+
+	/* Get the Write Pointer 1st Location is Write pointer */
+	crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
+
+	/* Queue is empty */
+	if (r_offset == w_offset)
+		return 0;
+
+	if ((r_offset < MIN_PIB_Q_DEPTH) || (r_offset >= MAX_PIB_Q_DEPTH))
+		return 0;
+
+	/* Get the Actual Address of the PIB */
+	crystalhd_mem_rd(hw->adp, Q_addr + (r_offset * sizeof(uint32_t)),
+		       1, &addr_entry);
+
+	/* Increment the Read Pointer */
+	r_offset++;
+
+	if (MAX_PIB_Q_DEPTH == r_offset)
+		r_offset = MIN_PIB_Q_DEPTH;
+
+	/* Write back the read pointer to It's Location */
+	crystalhd_mem_wr(hw->adp, Q_addr, 1, &r_offset);
+
+	return addr_entry;
+}
+
+static bool crystalhd_rel_addr_to_pib_Q(struct crystalhd_hw *hw, uint32_t addr_to_rel)
+{
+	uint32_t Q_addr;
+	uint32_t r_offset, w_offset, n_offset;
+
+	Q_addr = hw->pib_rel_Q_addr;
+
+	/* Get the Read Pointer */
+	crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
+
+	/* Get the Write Pointer */
+	crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
+
+	if ((r_offset < MIN_PIB_Q_DEPTH) ||
+	    (r_offset >= MAX_PIB_Q_DEPTH))
+		return false;
+
+	n_offset = w_offset + 1;
+
+	if (MAX_PIB_Q_DEPTH == n_offset)
+		n_offset = MIN_PIB_Q_DEPTH;
+
+	if (r_offset == n_offset)
+		return false; /* should never happen */
+
+	/* Write the DRAM ADDR to the Queue at Next Offset */
+	crystalhd_mem_wr(hw->adp, Q_addr + (w_offset * sizeof(uint32_t)),
+		       1, &addr_to_rel);
+
+	/* Put the New value of the write pointer in Queue */
+	crystalhd_mem_wr(hw->adp, Q_addr + sizeof(uint32_t), 1, &n_offset);
+
+	return true;
+}
+
+static void cpy_pib_to_app(C011_PIB *src_pib, BC_PIC_INFO_BLOCK *dst_pib)
+{
+	if (!src_pib || !dst_pib) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return;
+	}
+
+	dst_pib->timeStamp           = 0;
+	dst_pib->picture_number      = src_pib->ppb.picture_number;
+	dst_pib->width               = src_pib->ppb.width;
+	dst_pib->height              = src_pib->ppb.height;
+	dst_pib->chroma_format       = src_pib->ppb.chroma_format;
+	dst_pib->pulldown            = src_pib->ppb.pulldown;
+	dst_pib->flags               = src_pib->ppb.flags;
+	dst_pib->sess_num            = src_pib->ptsStcOffset;
+	dst_pib->aspect_ratio        = src_pib->ppb.aspect_ratio;
+	dst_pib->colour_primaries     = src_pib->ppb.colour_primaries;
+	dst_pib->picture_meta_payload = src_pib->ppb.picture_meta_payload;
+	dst_pib->frame_rate		= src_pib->resolution ;
+	return;
+}
+
+static void crystalhd_hw_proc_pib(struct crystalhd_hw *hw)
+{
+	unsigned int cnt;
+	C011_PIB src_pib;
+	uint32_t pib_addr, pib_cnt;
+	BC_PIC_INFO_BLOCK *AppPib;
+	crystalhd_rx_dma_pkt *rx_pkt = NULL;
+
+	pib_cnt = crystalhd_get_pib_avail_cnt(hw);
+
+	if (!pib_cnt)
+		return;
+
+	for (cnt = 0; cnt < pib_cnt; cnt++) {
+
+		pib_addr = crystalhd_get_addr_from_pib_Q(hw);
+		crystalhd_mem_rd(hw->adp, pib_addr, sizeof(C011_PIB) / 4,
+			       (uint32_t *)&src_pib);
+
+		if (src_pib.bFormatChange) {
+			rx_pkt = (crystalhd_rx_dma_pkt *)crystalhd_dioq_fetch(hw->rx_freeq);
+			if (!rx_pkt)
+				return;
+			rx_pkt->flags = 0;
+			rx_pkt->flags |= COMP_FLAG_PIB_VALID | COMP_FLAG_FMT_CHANGE;
+			AppPib = &rx_pkt->pib;
+			cpy_pib_to_app(&src_pib, AppPib);
+
+			BCMLOG(BCMLOG_DBG,
+			       "App PIB:%x %x %x %x %x %x %x %x %x %x\n",
+			       rx_pkt->pib.picture_number,
+			       rx_pkt->pib.aspect_ratio,
+			       rx_pkt->pib.chroma_format,
+			       rx_pkt->pib.colour_primaries,
+			       rx_pkt->pib.frame_rate,
+			       rx_pkt->pib.height,
+			       rx_pkt->pib.height,
+			       rx_pkt->pib.n_drop,
+			       rx_pkt->pib.pulldown,
+			       rx_pkt->pib.ycom);
+
+			crystalhd_dioq_add(hw->rx_rdyq, (void *)rx_pkt, true, rx_pkt->pkt_tag);
+
+		}
+
+		crystalhd_rel_addr_to_pib_Q(hw, pib_addr);
+	}
+}
+
+static void crystalhd_start_rx_dma_engine(struct crystalhd_hw *hw)
+{
+	uint32_t        dma_cntrl;
+
+	dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
+	if (!(dma_cntrl & DMA_START_BIT)) {
+		dma_cntrl |= DMA_START_BIT;
+		crystalhd_reg_wr(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+	}
+
+	dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
+	if (!(dma_cntrl & DMA_START_BIT)) {
+		dma_cntrl |= DMA_START_BIT;
+		crystalhd_reg_wr(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+	}
+
+	return;
+}
+
+static void crystalhd_stop_rx_dma_engine(struct crystalhd_hw *hw)
+{
+	uint32_t dma_cntrl = 0, count = 30;
+	uint32_t l0y = 1, l0uv = 1, l1y = 1, l1uv = 1;
+
+	dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
+	if ((dma_cntrl & DMA_START_BIT)) {
+		dma_cntrl &= ~DMA_START_BIT;
+		crystalhd_reg_wr(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+	}
+
+	dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
+	if ((dma_cntrl & DMA_START_BIT)) {
+		dma_cntrl &= ~DMA_START_BIT;
+		crystalhd_reg_wr(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+	}
+
+	/* Poll for 3seconds (30 * 100ms) on both the lists..*/
+	while ((l0y || l0uv || l1y || l1uv) && count) {
+
+		if (l0y) {
+			l0y = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0);
+			l0y &= DMA_START_BIT;
+			if (!l0y) {
+				hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
+			}
+		}
+
+		if (l1y) {
+			l1y = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1);
+			l1y &= DMA_START_BIT;
+			if (!l1y) {
+				hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
+			}
+		}
+
+		if (l0uv) {
+			l0uv = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0);
+			l0uv &= DMA_START_BIT;
+			if (!l0uv) {
+				hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
+			}
+		}
+
+		if (l1uv) {
+			l1uv = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1);
+			l1uv &= DMA_START_BIT;
+			if (!l1uv) {
+				hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
+			}
+		}
+		msleep_interruptible(100);
+		count--;
+	}
+
+	hw->rx_list_post_index = 0;
+
+	BCMLOG(BCMLOG_SSTEP, "Capture Stop: %d List0:Sts:%x List1:Sts:%x\n",
+	       count, hw->rx_list_sts[0], hw->rx_list_sts[1]);
+}
+
+static BC_STATUS crystalhd_hw_prog_rxdma(struct crystalhd_hw *hw, crystalhd_rx_dma_pkt *rx_pkt)
+{
+	uint32_t y_low_addr_reg, y_high_addr_reg;
+	uint32_t uv_low_addr_reg, uv_high_addr_reg;
+	addr_64 desc_addr;
+	unsigned long flags;
+
+	if (!hw || !rx_pkt) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if (hw->rx_list_post_index >= DMA_ENGINE_CNT) {
+		BCMLOG_ERR("List Out Of bounds %x\n", hw->rx_list_post_index);
+		return BC_STS_INV_ARG;
+	}
+
+	spin_lock_irqsave(&hw->rx_lock, flags);
+	/* FIXME: jarod: sts_free is an enum for 0, in crystalhd_hw.h... yuk... */
+	if (sts_free != hw->rx_list_sts[hw->rx_list_post_index]) {
+		spin_unlock_irqrestore(&hw->rx_lock, flags);
+		return BC_STS_BUSY;
+	}
+
+	if (!hw->rx_list_post_index) {
+		y_low_addr_reg   = MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0;
+		y_high_addr_reg  = MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST0;
+		uv_low_addr_reg  = MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0;
+		uv_high_addr_reg = MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST0;
+	} else {
+		y_low_addr_reg   = MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1;
+		y_high_addr_reg  = MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST1;
+		uv_low_addr_reg  = MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1;
+		uv_high_addr_reg = MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST1;
+	}
+	rx_pkt->pkt_tag = hw->rx_pkt_tag_seed + hw->rx_list_post_index;
+	hw->rx_list_sts[hw->rx_list_post_index] |= rx_waiting_y_intr;
+	if (rx_pkt->uv_phy_addr)
+		hw->rx_list_sts[hw->rx_list_post_index] |= rx_waiting_uv_intr;
+	hw->rx_list_post_index = (hw->rx_list_post_index + 1) % DMA_ENGINE_CNT;
+	spin_unlock_irqrestore(&hw->rx_lock, flags);
+
+	crystalhd_dioq_add(hw->rx_actq, (void *)rx_pkt, false, rx_pkt->pkt_tag);
+
+	crystalhd_start_rx_dma_engine(hw);
+	/* Program the Y descriptor */
+	desc_addr.full_addr = rx_pkt->desc_mem.phy_addr;
+	crystalhd_reg_wr(hw->adp, y_high_addr_reg, desc_addr.high_part);
+	crystalhd_reg_wr(hw->adp, y_low_addr_reg, desc_addr.low_part | 0x01);
+
+	if (rx_pkt->uv_phy_addr) {
+		/* Program the UV descriptor */
+		desc_addr.full_addr = rx_pkt->uv_phy_addr;
+		crystalhd_reg_wr(hw->adp, uv_high_addr_reg, desc_addr.high_part);
+		crystalhd_reg_wr(hw->adp, uv_low_addr_reg, desc_addr.low_part | 0x01);
+	}
+
+	return BC_STS_SUCCESS;
+}
+
+static BC_STATUS crystalhd_hw_post_cap_buff(struct crystalhd_hw *hw,
+					  crystalhd_rx_dma_pkt *rx_pkt)
+{
+	BC_STATUS sts = crystalhd_hw_prog_rxdma(hw, rx_pkt);
+
+	if (sts == BC_STS_BUSY)
+		crystalhd_dioq_add(hw->rx_freeq, (void *)rx_pkt,
+				 false, rx_pkt->pkt_tag);
+
+	return sts;
+}
+
+static void crystalhd_get_dnsz(struct crystalhd_hw *hw, uint32_t list_index,
+			     uint32_t *y_dw_dnsz, uint32_t *uv_dw_dnsz)
+{
+	uint32_t y_dn_sz_reg, uv_dn_sz_reg;
+
+	if (!list_index) {
+		y_dn_sz_reg  = MISC1_Y_RX_LIST0_CUR_BYTE_CNT;
+		uv_dn_sz_reg = MISC1_UV_RX_LIST0_CUR_BYTE_CNT;
+	} else {
+		y_dn_sz_reg  = MISC1_Y_RX_LIST1_CUR_BYTE_CNT;
+		uv_dn_sz_reg = MISC1_UV_RX_LIST1_CUR_BYTE_CNT;
+	}
+
+	*y_dw_dnsz  = crystalhd_reg_rd(hw->adp, y_dn_sz_reg);
+	*uv_dw_dnsz = crystalhd_reg_rd(hw->adp, uv_dn_sz_reg);
+}
+
+/*
+ * This function should be called only after making sure that the two DMA
+ * lists are free. This function does not check if DMA's are active, before
+ * turning off the DMA.
+ */
+static void crystalhd_hw_finalize_pause(struct crystalhd_hw *hw)
+{
+	uint32_t dma_cntrl, aspm;
+
+	hw->stop_pending = 0;
+
+	dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
+	if (dma_cntrl & DMA_START_BIT) {
+		dma_cntrl &= ~DMA_START_BIT;
+		crystalhd_reg_wr(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+	}
+
+	dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
+	if (dma_cntrl & DMA_START_BIT) {
+		dma_cntrl &= ~DMA_START_BIT;
+		crystalhd_reg_wr(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+	}
+	hw->rx_list_post_index = 0;
+
+	aspm = crystalhd_reg_rd(hw->adp, PCIE_DLL_DATA_LINK_CONTROL);
+	aspm |= ASPM_L1_ENABLE;
+	/* NAREN BCMLOG(BCMLOG_INFO, "aspm on\n"); */
+	crystalhd_reg_wr(hw->adp, PCIE_DLL_DATA_LINK_CONTROL, aspm);
+}
+
+static BC_STATUS crystalhd_rx_pkt_done(struct crystalhd_hw *hw, uint32_t list_index,
+				     BC_STATUS comp_sts)
+{
+	crystalhd_rx_dma_pkt *rx_pkt = NULL;
+	uint32_t y_dw_dnsz, uv_dw_dnsz;
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	if (!hw || list_index >= DMA_ENGINE_CNT) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	rx_pkt = crystalhd_dioq_find_and_fetch(hw->rx_actq,
+					     hw->rx_pkt_tag_seed + list_index);
+	if (!rx_pkt) {
+		BCMLOG_ERR("Act-Q:PostIx:%x L0Sts:%x L1Sts:%x current L:%x tag:%x comp:%x\n",
+			   hw->rx_list_post_index, hw->rx_list_sts[0],
+			   hw->rx_list_sts[1], list_index,
+			   hw->rx_pkt_tag_seed + list_index, comp_sts);
+		return BC_STS_INV_ARG;
+	}
+
+	if (comp_sts == BC_STS_SUCCESS) {
+		crystalhd_get_dnsz(hw, list_index, &y_dw_dnsz, &uv_dw_dnsz);
+		rx_pkt->dio_req->uinfo.y_done_sz = y_dw_dnsz;
+		rx_pkt->flags = COMP_FLAG_DATA_VALID;
+		if (rx_pkt->uv_phy_addr)
+			rx_pkt->dio_req->uinfo.uv_done_sz = uv_dw_dnsz;
+		crystalhd_dioq_add(hw->rx_rdyq, rx_pkt, true,
+				hw->rx_pkt_tag_seed + list_index);
+		return sts;
+	}
+
+	/* Check if we can post this DIO again. */
+	return crystalhd_hw_post_cap_buff(hw, rx_pkt);
+}
+
+static bool crystalhd_rx_list0_handler(struct crystalhd_hw *hw, uint32_t int_sts,
+				     uint32_t y_err_sts, uint32_t uv_err_sts)
+{
+	uint32_t tmp;
+	list_sts tmp_lsts;
+
+	if (!(y_err_sts & GET_Y0_ERR_MSK) && !(uv_err_sts & GET_UV0_ERR_MSK))
+		return false;
+
+	tmp_lsts = hw->rx_list_sts[0];
+
+	/* Y0 - DMA */
+	tmp = y_err_sts & GET_Y0_ERR_MSK;
+	if (int_sts & INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK)
+		hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
+
+	if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK) {
+		hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
+		tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK;
+	}
+
+	if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK) {
+		hw->rx_list_sts[0] &= ~rx_y_mask;
+		hw->rx_list_sts[0] |= rx_y_error;
+		tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK;
+	}
+
+	if (tmp) {
+		hw->rx_list_sts[0] &= ~rx_y_mask;
+		hw->rx_list_sts[0] |= rx_y_error;
+		hw->rx_list_post_index = 0;
+	}
+
+	/* UV0 - DMA */
+	tmp = uv_err_sts & GET_UV0_ERR_MSK;
+	if (int_sts & INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK)
+		hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
+
+	if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK) {
+		hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
+		tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK;
+	}
+
+	if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK) {
+		hw->rx_list_sts[0] &= ~rx_uv_mask;
+		hw->rx_list_sts[0] |= rx_uv_error;
+		tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK;
+	}
+
+	if (tmp) {
+		hw->rx_list_sts[0] &= ~rx_uv_mask;
+		hw->rx_list_sts[0] |= rx_uv_error;
+		hw->rx_list_post_index = 0;
+	}
+
+	if (y_err_sts & GET_Y0_ERR_MSK) {
+		tmp = y_err_sts & GET_Y0_ERR_MSK;
+		crystalhd_reg_wr(hw->adp, MISC1_Y_RX_ERROR_STATUS, tmp);
+	}
+
+	if (uv_err_sts & GET_UV0_ERR_MSK) {
+		tmp = uv_err_sts & GET_UV0_ERR_MSK;
+		crystalhd_reg_wr(hw->adp, MISC1_UV_RX_ERROR_STATUS, tmp);
+	}
+
+	return (tmp_lsts != hw->rx_list_sts[0]);
+}
+
+static bool crystalhd_rx_list1_handler(struct crystalhd_hw *hw, uint32_t int_sts,
+				     uint32_t y_err_sts, uint32_t uv_err_sts)
+{
+	uint32_t tmp;
+	list_sts tmp_lsts;
+
+	if (!(y_err_sts & GET_Y1_ERR_MSK) && !(uv_err_sts & GET_UV1_ERR_MSK))
+		return false;
+
+	tmp_lsts = hw->rx_list_sts[1];
+
+	/* Y1 - DMA */
+	tmp = y_err_sts & GET_Y1_ERR_MSK;
+	if (int_sts & INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK)
+		hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
+
+	if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK) {
+		hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
+		tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK;
+	}
+
+	if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK) {
+		/* Add retry-support..*/
+		hw->rx_list_sts[1] &= ~rx_y_mask;
+		hw->rx_list_sts[1] |= rx_y_error;
+		tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK;
+	}
+
+	if (tmp) {
+		hw->rx_list_sts[1] &= ~rx_y_mask;
+		hw->rx_list_sts[1] |= rx_y_error;
+		hw->rx_list_post_index = 0;
+	}
+
+	/* UV1 - DMA */
+	tmp = uv_err_sts & GET_UV1_ERR_MSK;
+	if (int_sts & INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK) {
+		hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
+	}
+
+	if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK) {
+		hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
+		tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK;
+	}
+
+	if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK) {
+		/* Add retry-support*/
+		hw->rx_list_sts[1] &= ~rx_uv_mask;
+		hw->rx_list_sts[1] |= rx_uv_error;
+		tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK;
+	}
+
+	if (tmp) {
+		hw->rx_list_sts[1] &= ~rx_uv_mask;
+		hw->rx_list_sts[1] |= rx_uv_error;
+		hw->rx_list_post_index = 0;
+	}
+
+	if (y_err_sts & GET_Y1_ERR_MSK) {
+		tmp = y_err_sts & GET_Y1_ERR_MSK;
+		crystalhd_reg_wr(hw->adp, MISC1_Y_RX_ERROR_STATUS, tmp);
+	}
+
+	if (uv_err_sts & GET_UV1_ERR_MSK) {
+		tmp = uv_err_sts & GET_UV1_ERR_MSK;
+		crystalhd_reg_wr(hw->adp, MISC1_UV_RX_ERROR_STATUS, tmp);
+	}
+
+	return (tmp_lsts != hw->rx_list_sts[1]);
+}
+
+
+static void crystalhd_rx_isr(struct crystalhd_hw *hw, uint32_t intr_sts)
+{
+	unsigned long flags;
+	uint32_t i, list_avail = 0;
+	BC_STATUS comp_sts = BC_STS_NO_DATA;
+	uint32_t y_err_sts, uv_err_sts, y_dn_sz = 0, uv_dn_sz = 0;
+	bool ret = 0;
+
+	if (!hw) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return;
+	}
+
+	if (!(intr_sts & GET_RX_INTR_MASK))
+		return;
+
+	y_err_sts = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_ERROR_STATUS);
+	uv_err_sts = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_ERROR_STATUS);
+
+	for (i = 0; i < DMA_ENGINE_CNT; i++) {
+		/* Update States..*/
+		spin_lock_irqsave(&hw->rx_lock, flags);
+		if (i == 0)
+			ret = crystalhd_rx_list0_handler(hw, intr_sts, y_err_sts, uv_err_sts);
+		else
+			ret = crystalhd_rx_list1_handler(hw, intr_sts, y_err_sts, uv_err_sts);
+		if (ret) {
+			switch (hw->rx_list_sts[i]) {
+			case sts_free:
+				comp_sts = BC_STS_SUCCESS;
+				list_avail = 1;
+				break;
+			case rx_y_error:
+			case rx_uv_error:
+			case rx_sts_error:
+				/* We got error on both or Y or uv. */
+				hw->stats.rx_errors++;
+				crystalhd_get_dnsz(hw, i, &y_dn_sz, &uv_dn_sz);
+				/* FIXME: jarod: this is where my mini pci-e card is tripping up */
+				BCMLOG(BCMLOG_DBG, "list_index:%x rx[%d] Y:%x "
+				       "UV:%x Int:%x YDnSz:%x UVDnSz:%x\n",
+				       i, hw->stats.rx_errors, y_err_sts,
+				       uv_err_sts, intr_sts, y_dn_sz, uv_dn_sz);
+				hw->rx_list_sts[i] = sts_free;
+				comp_sts = BC_STS_ERROR;
+				break;
+			default:
+				/* Wait for completion..*/
+				comp_sts = BC_STS_NO_DATA;
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&hw->rx_lock, flags);
+
+		/* handle completion...*/
+		if (comp_sts != BC_STS_NO_DATA) {
+			crystalhd_rx_pkt_done(hw, i, comp_sts);
+			comp_sts = BC_STS_NO_DATA;
+		}
+	}
+
+	if (list_avail) {
+		if (hw->stop_pending) {
+			if ((hw->rx_list_sts[0] == sts_free) &&
+			    (hw->rx_list_sts[1] == sts_free))
+				crystalhd_hw_finalize_pause(hw);
+		} else {
+			crystalhd_hw_start_capture(hw);
+		}
+	}
+}
+
+static BC_STATUS crystalhd_fw_cmd_post_proc(struct crystalhd_hw *hw,
+					  BC_FW_CMD *fw_cmd)
+{
+	BC_STATUS sts = BC_STS_SUCCESS;
+	DecRspChannelStartVideo *st_rsp = NULL;
+
+	switch (fw_cmd->cmd[0]) {
+	case eCMD_C011_DEC_CHAN_START_VIDEO:
+		st_rsp = (DecRspChannelStartVideo *)fw_cmd->rsp;
+		hw->pib_del_Q_addr = st_rsp->picInfoDeliveryQ;
+		hw->pib_rel_Q_addr = st_rsp->picInfoReleaseQ;
+		BCMLOG(BCMLOG_DBG, "DelQAddr:%x RelQAddr:%x\n",
+		       hw->pib_del_Q_addr, hw->pib_rel_Q_addr);
+		break;
+	case eCMD_C011_INIT:
+		if (!(crystalhd_load_firmware_config(hw->adp))) {
+			BCMLOG_ERR("Invalid Params.\n");
+			sts = BC_STS_FW_AUTH_FAILED;
+		}
+		break;
+	default:
+		break;
+	}
+	return sts;
+}
+
+static BC_STATUS crystalhd_put_ddr2sleep(struct crystalhd_hw *hw)
+{
+	uint32_t reg;
+	link_misc_perst_decoder_ctrl rst_cntrl_reg;
+
+	/* Pulse reset pin of 7412 (MISC_PERST_DECODER_CTRL) */
+	rst_cntrl_reg.whole_reg = crystalhd_reg_rd(hw->adp, MISC_PERST_DECODER_CTRL);
+
+	rst_cntrl_reg.bcm_7412_rst = 1;
+	crystalhd_reg_wr(hw->adp, MISC_PERST_DECODER_CTRL, rst_cntrl_reg.whole_reg);
+	msleep_interruptible(50);
+
+	rst_cntrl_reg.bcm_7412_rst = 0;
+	crystalhd_reg_wr(hw->adp, MISC_PERST_DECODER_CTRL, rst_cntrl_reg.whole_reg);
+
+	/* Close all banks, put DDR in idle */
+	bc_dec_reg_wr(hw->adp, SDRAM_PRECHARGE, 0);
+
+	/* Set bit 25 (drop CKE pin of DDR) */
+	reg = bc_dec_reg_rd(hw->adp, SDRAM_PARAM);
+	reg |= 0x02000000;
+	bc_dec_reg_wr(hw->adp, SDRAM_PARAM, reg);
+
+	/* Reset the audio block */
+	bc_dec_reg_wr(hw->adp, AUD_DSP_MISC_SOFT_RESET, 0x1);
+
+	/* Power down Raptor PLL */
+	reg = bc_dec_reg_rd(hw->adp, DecHt_PllCCtl);
+	reg |= 0x00008000;
+	bc_dec_reg_wr(hw->adp, DecHt_PllCCtl, reg);
+
+	/* Power down all Audio PLL */
+	bc_dec_reg_wr(hw->adp, AIO_MISC_PLL_RESET, 0x1);
+
+	/* Power down video clock (75MHz) */
+	reg = bc_dec_reg_rd(hw->adp, DecHt_PllECtl);
+	reg |= 0x00008000;
+	bc_dec_reg_wr(hw->adp, DecHt_PllECtl, reg);
+
+	/* Power down video clock (75MHz) */
+	reg = bc_dec_reg_rd(hw->adp, DecHt_PllDCtl);
+	reg |= 0x00008000;
+	bc_dec_reg_wr(hw->adp, DecHt_PllDCtl, reg);
+
+	/* Power down core clock (200MHz) */
+	reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
+	reg |= 0x00008000;
+	bc_dec_reg_wr(hw->adp, DecHt_PllACtl, reg);
+
+	/* Power down core clock (200MHz) */
+	reg = bc_dec_reg_rd(hw->adp, DecHt_PllBCtl);
+	reg |= 0x00008000;
+	bc_dec_reg_wr(hw->adp, DecHt_PllBCtl, reg);
+
+	return BC_STS_SUCCESS;
+}
+
+/************************************************
+**
+*************************************************/
+
+BC_STATUS crystalhd_download_fw(struct crystalhd_adp *adp, void *buffer, uint32_t sz)
+{
+	uint32_t reg_data, cnt, *temp_buff;
+	uint32_t fw_sig_len = 36;
+	uint32_t dram_offset = BC_FWIMG_ST_ADDR, sig_reg;
+
+	BCMLOG_ENTER;
+
+	if (!adp || !buffer || !sz) {
+		BCMLOG_ERR("Invalid Params.\n");
+		return BC_STS_INV_ARG;
+	}
+
+	reg_data = crystalhd_reg_rd(adp, OTP_CMD);
+	if (!(reg_data & 0x02)) {
+		BCMLOG_ERR("Invalid hw config.. otp not programmed\n");
+		return BC_STS_ERROR;
+	}
+
+	reg_data = 0;
+	crystalhd_reg_wr(adp, DCI_CMD, 0);
+	reg_data |= BC_BIT(0);
+	crystalhd_reg_wr(adp, DCI_CMD, reg_data);
+
+	reg_data = 0;
+	cnt = 1000;
+	msleep_interruptible(10);
+
+	while (reg_data != BC_BIT(4)) {
+		reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
+		reg_data &= BC_BIT(4);
+		if (--cnt == 0) {
+			BCMLOG_ERR("Firmware Download RDY Timeout.\n");
+			return BC_STS_TIMEOUT;
+		}
+	}
+
+	msleep_interruptible(10);
+	/*  Load the FW to the FW_ADDR field in the DCI_FIRMWARE_ADDR */
+	crystalhd_reg_wr(adp, DCI_FIRMWARE_ADDR, dram_offset);
+	temp_buff = (uint32_t *)buffer;
+	for (cnt = 0; cnt < (sz - fw_sig_len); cnt += 4) {
+		crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (dram_offset >> 19));
+		crystalhd_reg_wr(adp, DCI_FIRMWARE_DATA, *temp_buff);
+		dram_offset += 4;
+		temp_buff++;
+	}
+	msleep_interruptible(10);
+
+	temp_buff++;
+
+	sig_reg = (uint32_t)DCI_SIGNATURE_DATA_7;
+	for (cnt = 0; cnt < 8; cnt++) {
+		uint32_t swapped_data = *temp_buff;
+		swapped_data = bswap_32_1(swapped_data);
+		crystalhd_reg_wr(adp, sig_reg, swapped_data);
+		sig_reg -= 4;
+		temp_buff++;
+	}
+	msleep_interruptible(10);
+
+	reg_data = 0;
+	reg_data |= BC_BIT(1);
+	crystalhd_reg_wr(adp, DCI_CMD, reg_data);
+	msleep_interruptible(10);
+
+	reg_data = 0;
+	reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
+
+	if ((reg_data & BC_BIT(9)) == BC_BIT(9)) {
+		cnt = 1000;
+		while ((reg_data & BC_BIT(0)) != BC_BIT(0)) {
+			reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
+			reg_data &= BC_BIT(0);
+			if (!(--cnt))
+				break;
+			msleep_interruptible(10);
+		}
+		reg_data = 0;
+		reg_data = crystalhd_reg_rd(adp, DCI_CMD);
+		reg_data |= BC_BIT(4);
+		crystalhd_reg_wr(adp, DCI_CMD, reg_data);
+
+	} else {
+		BCMLOG_ERR("F/w Signature mismatch\n");
+		return BC_STS_FW_AUTH_FAILED;
+	}
+
+	BCMLOG(BCMLOG_INFO, "Firmware Downloaded Successfully\n");
+	return BC_STS_SUCCESS;;
+}
+
+BC_STATUS crystalhd_do_fw_cmd(struct crystalhd_hw *hw, BC_FW_CMD *fw_cmd)
+{
+	uint32_t cnt = 0, cmd_res_addr;
+	uint32_t *cmd_buff, *res_buff;
+	wait_queue_head_t fw_cmd_event;
+	int rc = 0;
+	BC_STATUS sts;
+
+	crystalhd_create_event(&fw_cmd_event);
+
+	BCMLOG_ENTER;
+
+	if (!hw || !fw_cmd) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	cmd_buff = fw_cmd->cmd;
+	res_buff = fw_cmd->rsp;
+
+	if (!cmd_buff || !res_buff) {
+		BCMLOG_ERR("Invalid Parameters for F/W Command \n");
+		return BC_STS_INV_ARG;
+	}
+
+	hw->pwr_lock++;
+
+	hw->fwcmd_evt_sts = 0;
+	hw->pfw_cmd_event = &fw_cmd_event;
+
+	/*Write the command to the memory*/
+	crystalhd_mem_wr(hw->adp, TS_Host2CpuSnd, FW_CMD_BUFF_SZ, cmd_buff);
+
+	/*Memory Read for memory arbitrator flush*/
+	crystalhd_mem_rd(hw->adp, TS_Host2CpuSnd, 1, &cnt);
+
+	/* Write the command address to mailbox */
+	bc_dec_reg_wr(hw->adp, Hst2CpuMbx1, TS_Host2CpuSnd);
+	msleep_interruptible(50);
+
+	crystalhd_wait_on_event(&fw_cmd_event, hw->fwcmd_evt_sts, 20000, rc, 0);
+
+	if (!rc) {
+		sts = BC_STS_SUCCESS;
+	} else if (rc == -EBUSY) {
+		BCMLOG_ERR("Firmware command T/O\n");
+		sts = BC_STS_TIMEOUT;
+	} else if (rc == -EINTR) {
+		BCMLOG(BCMLOG_DBG, "FwCmd Wait Signal int.\n");
+		sts = BC_STS_IO_USER_ABORT;
+	} else {
+		BCMLOG_ERR("FwCmd IO Error.\n");
+		sts = BC_STS_IO_ERROR;
+	}
+
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG_ERR("FwCmd Failed.\n");
+		hw->pwr_lock--;
+		return sts;
+	}
+
+	/*Get the Responce Address*/
+	cmd_res_addr = bc_dec_reg_rd(hw->adp, Cpu2HstMbx1);
+
+	/*Read the Response*/
+	crystalhd_mem_rd(hw->adp, cmd_res_addr, FW_CMD_BUFF_SZ, res_buff);
+
+	hw->pwr_lock--;
+
+	if (res_buff[2] != C011_RET_SUCCESS) {
+		BCMLOG_ERR("res_buff[2] != C011_RET_SUCCESS\n");
+		return BC_STS_FW_CMD_ERR;
+	}
+
+	sts = crystalhd_fw_cmd_post_proc(hw, fw_cmd);
+	if (sts != BC_STS_SUCCESS)
+		BCMLOG_ERR("crystalhd_fw_cmd_post_proc Failed.\n");
+
+	return sts;
+}
+
+bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw)
+{
+	uint32_t intr_sts = 0;
+	uint32_t deco_intr = 0;
+	bool rc = 0;
+
+	if (!adp || !hw->dev_started)
+		return rc;
+
+	hw->stats.num_interrupts++;
+	hw->pwr_lock++;
+
+	deco_intr = bc_dec_reg_rd(adp, Stream2Host_Intr_Sts);
+	intr_sts  = crystalhd_reg_rd(adp, INTR_INTR_STATUS);
+
+	if (intr_sts) {
+		/* let system know we processed interrupt..*/
+		rc = 1;
+		hw->stats.dev_interrupts++;
+	}
+
+	if (deco_intr && (deco_intr != 0xdeaddead)) {
+
+		if (deco_intr & 0x80000000) {
+			/*Set the Event and the status flag*/
+			if (hw->pfw_cmd_event) {
+				hw->fwcmd_evt_sts = 1;
+				crystalhd_set_event(hw->pfw_cmd_event);
+			}
+		}
+
+		if (deco_intr & BC_BIT(1))
+			crystalhd_hw_proc_pib(hw);
+
+		bc_dec_reg_wr(adp, Stream2Host_Intr_Sts, deco_intr);
+		/* FIXME: jarod: No udelay? might this be the real reason mini pci-e cards were stalling out? */
+		bc_dec_reg_wr(adp, Stream2Host_Intr_Sts, 0);
+		rc = 1;
+	}
+
+	/* Rx interrupts */
+	crystalhd_rx_isr(hw, intr_sts);
+
+	/* Tx interrupts*/
+	crystalhd_tx_isr(hw, intr_sts);
+
+	/* Clear interrupts */
+	if (rc) {
+		if (intr_sts)
+			crystalhd_reg_wr(adp, INTR_INTR_CLR_REG, intr_sts);
+
+		crystalhd_reg_wr(adp, INTR_EOI_CTRL, 1);
+	}
+
+	hw->pwr_lock--;
+
+	return rc;
+}
+
+BC_STATUS crystalhd_hw_open(struct crystalhd_hw *hw, struct crystalhd_adp *adp)
+{
+	if (!hw || !adp) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if (hw->dev_started)
+		return BC_STS_SUCCESS;
+
+	memset(hw, 0, sizeof(struct crystalhd_hw));
+
+	hw->adp = adp;
+	spin_lock_init(&hw->lock);
+	spin_lock_init(&hw->rx_lock);
+	/* FIXME: jarod: what are these magic numbers?!? */
+	hw->tx_ioq_tag_seed = 0x70023070;
+	hw->rx_pkt_tag_seed = 0x70029070;
+
+	hw->stop_pending = 0;
+	crystalhd_start_device(hw->adp);
+	hw->dev_started = true;
+
+	/* set initial core clock  */
+	hw->core_clock_mhz = CLOCK_PRESET;
+	hw->prev_n = 0;
+	hw->pwr_lock = 0;
+	crystalhd_hw_set_core_clock(hw);
+
+	return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_close(struct crystalhd_hw *hw)
+{
+	if (!hw) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	if (!hw->dev_started)
+		return BC_STS_SUCCESS;
+
+	/* Stop and DDR sleep will happen in here */
+	crystalhd_hw_suspend(hw);
+	hw->dev_started = false;
+
+	return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *hw)
+{
+	unsigned int i;
+	void *mem;
+	size_t mem_len;
+	dma_addr_t phy_addr;
+	BC_STATUS sts = BC_STS_SUCCESS;
+	crystalhd_rx_dma_pkt *rpkt;
+
+	if (!hw || !hw->adp) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	sts = crystalhd_hw_create_ioqs(hw);
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG_ERR("Failed to create IOQs..\n");
+		return sts;
+	}
+
+	mem_len = BC_LINK_MAX_SGLS * sizeof(dma_descriptor);
+
+	for (i = 0; i < BC_TX_LIST_CNT; i++) {
+		mem = bc_kern_dma_alloc(hw->adp, mem_len, &phy_addr);
+		if (mem) {
+			memset(mem, 0, mem_len);
+		} else {
+			BCMLOG_ERR("Insufficient Memory For TX\n");
+			crystalhd_hw_free_dma_rings(hw);
+			return BC_STS_INSUFF_RES;
+		}
+		/* rx_pkt_pool -- static memory allocation  */
+		hw->tx_pkt_pool[i].desc_mem.pdma_desc_start = mem;
+		hw->tx_pkt_pool[i].desc_mem.phy_addr = phy_addr;
+		hw->tx_pkt_pool[i].desc_mem.sz = BC_LINK_MAX_SGLS *
+						 sizeof(dma_descriptor);
+		hw->tx_pkt_pool[i].list_tag = 0;
+
+		/* Add TX dma requests to Free Queue..*/
+		sts = crystalhd_dioq_add(hw->tx_freeq,
+				       &hw->tx_pkt_pool[i], false, 0);
+		if (sts != BC_STS_SUCCESS) {
+			crystalhd_hw_free_dma_rings(hw);
+			return sts;
+		}
+	}
+
+	for (i = 0; i < BC_RX_LIST_CNT; i++) {
+		rpkt = kzalloc(sizeof(*rpkt), GFP_KERNEL);
+		if (!rpkt) {
+			BCMLOG_ERR("Insufficient Memory For RX\n");
+			crystalhd_hw_free_dma_rings(hw);
+			return BC_STS_INSUFF_RES;
+		}
+
+		mem = bc_kern_dma_alloc(hw->adp, mem_len, &phy_addr);
+		if (mem) {
+			memset(mem, 0, mem_len);
+		} else {
+			BCMLOG_ERR("Insufficient Memory For RX\n");
+			crystalhd_hw_free_dma_rings(hw);
+			return BC_STS_INSUFF_RES;
+		}
+		rpkt->desc_mem.pdma_desc_start = mem;
+		rpkt->desc_mem.phy_addr = phy_addr;
+		rpkt->desc_mem.sz  = BC_LINK_MAX_SGLS * sizeof(dma_descriptor);
+		rpkt->pkt_tag = hw->rx_pkt_tag_seed + i;
+		crystalhd_hw_free_rx_pkt(hw, rpkt);
+	}
+
+	return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_free_dma_rings(struct crystalhd_hw *hw)
+{
+	unsigned int i;
+	crystalhd_rx_dma_pkt *rpkt = NULL;
+
+	if (!hw || !hw->adp) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	/* Delete all IOQs.. */
+	crystalhd_hw_delete_ioqs(hw);
+
+	for (i = 0; i < BC_TX_LIST_CNT; i++) {
+		if (hw->tx_pkt_pool[i].desc_mem.pdma_desc_start) {
+			bc_kern_dma_free(hw->adp,
+				hw->tx_pkt_pool[i].desc_mem.sz,
+				hw->tx_pkt_pool[i].desc_mem.pdma_desc_start,
+				hw->tx_pkt_pool[i].desc_mem.phy_addr);
+
+			hw->tx_pkt_pool[i].desc_mem.pdma_desc_start = NULL;
+		}
+	}
+
+	BCMLOG(BCMLOG_DBG, "Releasing RX Pkt pool\n");
+	do {
+		rpkt = crystalhd_hw_alloc_rx_pkt(hw);
+		if (!rpkt)
+			break;
+		bc_kern_dma_free(hw->adp, rpkt->desc_mem.sz,
+				 rpkt->desc_mem.pdma_desc_start,
+				 rpkt->desc_mem.phy_addr);
+		kfree(rpkt);
+	} while (rpkt);
+
+	return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_post_tx(struct crystalhd_hw *hw, crystalhd_dio_req *ioreq,
+			     hw_comp_callback call_back,
+			     wait_queue_head_t *cb_event, uint32_t *list_id,
+			     uint8_t data_flags)
+{
+	tx_dma_pkt *tx_dma_packet = NULL;
+	uint32_t first_desc_u_addr, first_desc_l_addr;
+	uint32_t low_addr, high_addr;
+	addr_64 desc_addr;
+	BC_STATUS sts, add_sts;
+	uint32_t dummy_index = 0;
+	unsigned long flags;
+	bool rc;
+
+	if (!hw || !ioreq || !call_back || !cb_event || !list_id) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	/*
+	 * Since we hit code in busy condition very frequently,
+	 * we will check the code in status first before
+	 * checking the availability of free elem.
+	 *
+	 * This will avoid the Q fetch/add in normal condition.
+	 */
+	rc = crystalhd_code_in_full(hw->adp, ioreq->uinfo.xfr_len,
+				  false, data_flags);
+	if (rc) {
+		hw->stats.cin_busy++;
+		return BC_STS_BUSY;
+	}
+
+	/* Get a list from TxFreeQ */
+	tx_dma_packet = (tx_dma_pkt *)crystalhd_dioq_fetch(hw->tx_freeq);
+	if (!tx_dma_packet) {
+		BCMLOG_ERR("No empty elements..\n");
+		return BC_STS_ERR_USAGE;
+	}
+
+	sts = crystalhd_xlat_sgl_to_dma_desc(ioreq,
+					   &tx_dma_packet->desc_mem,
+					   &dummy_index);
+	if (sts != BC_STS_SUCCESS) {
+		add_sts = crystalhd_dioq_add(hw->tx_freeq, tx_dma_packet,
+					   false, 0);
+		if (add_sts != BC_STS_SUCCESS)
+			BCMLOG_ERR("double fault..\n");
+
+		return sts;
+	}
+
+	hw->pwr_lock++;
+
+	desc_addr.full_addr = tx_dma_packet->desc_mem.phy_addr;
+	low_addr = desc_addr.low_part;
+	high_addr = desc_addr.high_part;
+
+	tx_dma_packet->call_back = call_back;
+	tx_dma_packet->cb_event  = cb_event;
+	tx_dma_packet->dio_req   = ioreq;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	if (hw->tx_list_post_index == 0) {
+		first_desc_u_addr = MISC1_TX_FIRST_DESC_U_ADDR_LIST0;
+		first_desc_l_addr = MISC1_TX_FIRST_DESC_L_ADDR_LIST0;
+	} else {
+		first_desc_u_addr = MISC1_TX_FIRST_DESC_U_ADDR_LIST1;
+		first_desc_l_addr = MISC1_TX_FIRST_DESC_L_ADDR_LIST1;
+	}
+
+	*list_id = tx_dma_packet->list_tag = hw->tx_ioq_tag_seed +
+					     hw->tx_list_post_index;
+
+	hw->tx_list_post_index = (hw->tx_list_post_index + 1) % DMA_ENGINE_CNT;
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+
+	/* Insert in Active Q..*/
+	crystalhd_dioq_add(hw->tx_actq, tx_dma_packet, false,
+			 tx_dma_packet->list_tag);
+
+	/*
+	 * Interrupt will come as soon as you write
+	 * the valid bit. So be ready for that. All
+	 * the initialization should happen before that.
+	 */
+	crystalhd_start_tx_dma_engine(hw);
+	crystalhd_reg_wr(hw->adp, first_desc_u_addr, desc_addr.high_part);
+
+	crystalhd_reg_wr(hw->adp, first_desc_l_addr, desc_addr.low_part | 0x01);
+					/* Be sure we set the valid bit ^^^^ */
+
+	return BC_STS_SUCCESS;
+}
+
+/*
+ * This is a force cancel and we are racing with ISR.
+ *
+ * Will try to remove the req from ActQ before ISR gets it.
+ * If ISR gets it first then the completion happens in the
+ * normal path and we will return _STS_NO_DATA from here.
+ *
+ * FIX_ME: Not Tested the actual condition..
+ */
+BC_STATUS crystalhd_hw_cancel_tx(struct crystalhd_hw *hw, uint32_t list_id)
+{
+	if (!hw || !list_id) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	crystalhd_stop_tx_dma_engine(hw);
+	crystalhd_hw_tx_req_complete(hw, list_id, BC_STS_IO_USER_ABORT);
+
+	return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_add_cap_buffer(struct crystalhd_hw *hw,
+				    crystalhd_dio_req *ioreq, bool en_post)
+{
+	crystalhd_rx_dma_pkt *rpkt;
+	uint32_t tag, uv_desc_ix = 0;
+	BC_STATUS sts;
+
+	if (!hw || !ioreq) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	rpkt = crystalhd_hw_alloc_rx_pkt(hw);
+	if (!rpkt) {
+		BCMLOG_ERR("Insufficient resources\n");
+		return BC_STS_INSUFF_RES;
+	}
+
+	rpkt->dio_req = ioreq;
+	tag = rpkt->pkt_tag;
+
+	sts = crystalhd_xlat_sgl_to_dma_desc(ioreq, &rpkt->desc_mem, &uv_desc_ix);
+	if (sts != BC_STS_SUCCESS)
+		return sts;
+
+	rpkt->uv_phy_addr = 0;
+
+	/* Store the address of UV in the rx packet for post*/
+	if (uv_desc_ix)
+		rpkt->uv_phy_addr = rpkt->desc_mem.phy_addr +
+				    (sizeof(dma_descriptor) * (uv_desc_ix + 1));
+
+	if (en_post)
+		sts = crystalhd_hw_post_cap_buff(hw, rpkt);
+	else
+		sts = crystalhd_dioq_add(hw->rx_freeq, rpkt, false, tag);
+
+	return sts;
+}
+
+BC_STATUS crystalhd_hw_get_cap_buffer(struct crystalhd_hw *hw,
+				    BC_PIC_INFO_BLOCK *pib,
+				    crystalhd_dio_req **ioreq)
+{
+	crystalhd_rx_dma_pkt *rpkt;
+	uint32_t timeout = BC_PROC_OUTPUT_TIMEOUT / 1000;
+	uint32_t sig_pending = 0;
+
+
+	if (!hw || !ioreq || !pib) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	rpkt = crystalhd_dioq_fetch_wait(hw->rx_rdyq, timeout, &sig_pending);
+	if (!rpkt) {
+		if (sig_pending) {
+			BCMLOG(BCMLOG_INFO, "wait on frame time out %d\n", sig_pending);
+			return BC_STS_IO_USER_ABORT;
+		} else {
+			return BC_STS_TIMEOUT;
+		}
+	}
+
+	rpkt->dio_req->uinfo.comp_flags = rpkt->flags;
+
+	if (rpkt->flags & COMP_FLAG_PIB_VALID)
+		memcpy(pib, &rpkt->pib, sizeof(*pib));
+
+	*ioreq = rpkt->dio_req;
+
+	crystalhd_hw_free_rx_pkt(hw, rpkt);
+
+	return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_start_capture(struct crystalhd_hw *hw)
+{
+	crystalhd_rx_dma_pkt *rx_pkt;
+	BC_STATUS sts;
+	uint32_t i;
+
+	if (!hw) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	/* This is start of capture.. Post to both the lists.. */
+	for (i = 0; i < DMA_ENGINE_CNT; i++) {
+		rx_pkt = crystalhd_dioq_fetch(hw->rx_freeq);
+		if (!rx_pkt)
+			return BC_STS_NO_DATA;
+		sts = crystalhd_hw_post_cap_buff(hw, rx_pkt);
+		if (BC_STS_SUCCESS != sts)
+			break;
+
+	}
+
+	return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_stop_capture(struct crystalhd_hw *hw)
+{
+	void *temp = NULL;
+
+	if (!hw) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	crystalhd_stop_rx_dma_engine(hw);
+
+	do {
+		temp = crystalhd_dioq_fetch(hw->rx_freeq);
+		if (temp)
+			crystalhd_rx_pkt_rel_call_back(hw, temp);
+	} while (temp);
+
+	return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_pause(struct crystalhd_hw *hw)
+{
+	hw->stats.pause_cnt++;
+	hw->stop_pending = 1;
+
+	if ((hw->rx_list_sts[0] == sts_free) &&
+	    (hw->rx_list_sts[1] == sts_free))
+		crystalhd_hw_finalize_pause(hw);
+
+	return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_unpause(struct crystalhd_hw *hw)
+{
+	BC_STATUS sts;
+	uint32_t aspm;
+
+	hw->stop_pending = 0;
+
+	aspm = crystalhd_reg_rd(hw->adp, PCIE_DLL_DATA_LINK_CONTROL);
+	aspm &= ~ASPM_L1_ENABLE;
+/* NAREN BCMLOG(BCMLOG_INFO, "aspm off\n"); */
+	crystalhd_reg_wr(hw->adp, PCIE_DLL_DATA_LINK_CONTROL, aspm);
+
+	sts = crystalhd_hw_start_capture(hw);
+	return sts;
+}
+
+BC_STATUS crystalhd_hw_suspend(struct crystalhd_hw *hw)
+{
+	BC_STATUS sts;
+
+	if (!hw) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	sts = crystalhd_put_ddr2sleep(hw);
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG_ERR("Failed to Put DDR To Sleep!!\n");
+		return BC_STS_ERROR;
+	}
+
+	if (!crystalhd_stop_device(hw->adp)) {
+		BCMLOG_ERR("Failed to Stop Device!!\n");
+		return BC_STS_ERROR;
+	}
+
+	return BC_STS_SUCCESS;
+}
+
+void crystalhd_hw_stats(struct crystalhd_hw *hw, struct crystalhd_hw_stats *stats)
+{
+	if (!hw) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return;
+	}
+
+	/* if called w/NULL stats, its a req to zero out the stats */
+	if (!stats) {
+		memset(&hw->stats, 0, sizeof(hw->stats));
+		return;
+	}
+
+	hw->stats.freeq_count = crystalhd_dioq_count(hw->rx_freeq);
+	hw->stats.rdyq_count  = crystalhd_dioq_count(hw->rx_rdyq);
+	memcpy(stats, &hw->stats, sizeof(*stats));
+}
+
+BC_STATUS crystalhd_hw_set_core_clock(struct crystalhd_hw *hw)
+{
+	uint32_t reg, n, i;
+	uint32_t vco_mg, refresh_reg;
+
+	if (!hw) {
+		BCMLOG_ERR("Invalid Arguments\n");
+		return BC_STS_INV_ARG;
+	}
+
+	/* FIXME: jarod: wha? */
+	/*n = (hw->core_clock_mhz * 3) / 20 + 1; */
+	n = hw->core_clock_mhz/5;
+
+	if (n == hw->prev_n)
+		return BC_STS_CLK_NOCHG;
+
+	if (hw->pwr_lock > 0) {
+		/* BCMLOG(BCMLOG_INFO,"pwr_lock is %u\n", hw->pwr_lock) */
+		return BC_STS_CLK_NOCHG;
+	}
+
+	i = n * 27;
+	if (i < 560)
+		vco_mg = 0;
+	else if (i < 900)
+		vco_mg = 1;
+	else if (i < 1030)
+		vco_mg = 2;
+	else
+		vco_mg = 3;
+
+	reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
+
+	reg &= 0xFFFFCFC0;
+	reg |= n;
+	reg |= vco_mg << 12;
+
+	BCMLOG(BCMLOG_INFO, "clock is moving to %d with n %d with vco_mg %d\n",
+	       hw->core_clock_mhz, n, vco_mg);
+
+	/* Change the DRAM refresh rate to accomodate the new frequency */
+	/* refresh reg = ((refresh_rate * clock_rate)/16) - 1; rounding up*/
+	refresh_reg = (7 * hw->core_clock_mhz / 16);
+	bc_dec_reg_wr(hw->adp, SDRAM_REF_PARAM, ((1 << 12) | refresh_reg));
+
+	bc_dec_reg_wr(hw->adp, DecHt_PllACtl, reg);
+
+	i = 0;
+
+	for (i = 0; i < 10; i++) {
+		reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
+
+		if (reg & 0x00020000) {
+			hw->prev_n = n;
+			/* FIXME: jarod: outputting a random "C" is... confusing... */
+			BCMLOG(BCMLOG_INFO, "C");
+			return BC_STS_SUCCESS;
+		} else {
+			msleep_interruptible(10);
+		}
+	}
+	BCMLOG(BCMLOG_INFO, "clk change failed\n");
+	return BC_STS_CLK_NOCHG;
+}
diff --git a/drivers/staging/crystalhd/crystalhd_hw.h b/drivers/staging/crystalhd/crystalhd_hw.h
new file mode 100644
index 0000000..1c6318e
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_hw.h
@@ -0,0 +1,398 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ *  Name: crystalhd_hw . h
+ *
+ *  Description:
+ *		BCM70012 Linux driver hardware layer.
+ *
+ *  HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * This driver is free software; 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 driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#ifndef _CRYSTALHD_HW_H_
+#define _CRYSTALHD_HW_H_
+
+#include "crystalhd_misc.h"
+#include "crystalhd_fw_if.h"
+
+/* HW constants..*/
+#define DMA_ENGINE_CNT		2
+#define MAX_PIB_Q_DEPTH		64
+#define MIN_PIB_Q_DEPTH		2
+#define WR_POINTER_OFF		4
+
+#define ASPM_L1_ENABLE		(BC_BIT(27))
+
+/*************************************************
+  7412 Decoder  Registers.
+**************************************************/
+#define FW_CMD_BUFF_SZ		64
+#define TS_Host2CpuSnd		0x00000100
+#define Hst2CpuMbx1		0x00100F00
+#define Cpu2HstMbx1		0x00100F04
+#define MbxStat1		0x00100F08
+#define Stream2Host_Intr_Sts	0x00100F24
+#define C011_RET_SUCCESS	0x0	/* Reutrn status of firmware command. */
+
+/* TS input status register */
+#define TS_StreamAFIFOStatus	0x0010044C
+#define TS_StreamBFIFOStatus	0x0010084C
+
+/*UART Selection definitions*/
+#define UartSelectA		0x00100300
+#define UartSelectB		0x00100304
+
+#define BSVS_UART_DEC_NONE	0x00
+#define BSVS_UART_DEC_OUTER	0x01
+#define BSVS_UART_DEC_INNER	0x02
+#define BSVS_UART_STREAM	0x03
+
+/* Code-In fifo */
+#define REG_DecCA_RegCinCTL	0xa00
+#define REG_DecCA_RegCinBase	0xa0c
+#define REG_DecCA_RegCinEnd	0xa10
+#define REG_DecCA_RegCinWrPtr	0xa04
+#define REG_DecCA_RegCinRdPtr	0xa08
+
+#define REG_Dec_TsUser0Base	0x100864
+#define REG_Dec_TsUser0Rdptr	0x100868
+#define REG_Dec_TsUser0Wrptr	0x10086C
+#define REG_Dec_TsUser0End	0x100874
+
+/* ASF Case ...*/
+#define REG_Dec_TsAudCDB2Base	0x10036c
+#define REG_Dec_TsAudCDB2Rdptr  0x100378
+#define REG_Dec_TsAudCDB2Wrptr  0x100374
+#define REG_Dec_TsAudCDB2End	0x100370
+
+/* DRAM bringup Registers */
+#define SDRAM_PARAM		0x00040804
+#define SDRAM_PRECHARGE		0x000408B0
+#define SDRAM_EXT_MODE		0x000408A4
+#define SDRAM_MODE		0x000408A0
+#define SDRAM_REFRESH		0x00040890
+#define SDRAM_REF_PARAM		0x00040808
+
+#define DecHt_PllACtl		0x34000C
+#define DecHt_PllBCtl		0x340010
+#define DecHt_PllCCtl		0x340014
+#define DecHt_PllDCtl		0x340034
+#define DecHt_PllECtl		0x340038
+#define AUD_DSP_MISC_SOFT_RESET	0x00240104
+#define AIO_MISC_PLL_RESET	0x0026000C
+#define PCIE_CLK_REQ_REG	0xDC
+#define	PCI_CLK_REQ_ENABLE	(BC_BIT(8))
+
+/*************************************************
+  F/W Copy engine definitions..
+**************************************************/
+#define BC_FWIMG_ST_ADDR	0x00000000
+/* FIXME: jarod: there's a kernel function that'll do this for us... */
+#define rotr32_1(x, n)		(((x) >> n) | ((x) << (32 - n)))
+#define bswap_32_1(x)		((rotr32_1((x), 24) & 0x00ff00ff) | (rotr32_1((x), 8) & 0xff00ff00))
+
+#define DecHt_HostSwReset	0x340000
+#define BC_DRAM_FW_CFG_ADDR	0x001c2000
+
+typedef union _addr_64_ {
+	struct {
+		uint32_t	low_part;
+		uint32_t	high_part;
+	};
+
+	uint64_t	full_addr;
+
+} addr_64;
+
+typedef union _intr_mask_reg_ {
+	struct {
+		uint32_t	mask_tx_done:1;
+		uint32_t	mask_tx_err:1;
+		uint32_t	mask_rx_done:1;
+		uint32_t	mask_rx_err:1;
+		uint32_t	mask_pcie_err:1;
+		uint32_t	mask_pcie_rbusmast_err:1;
+		uint32_t	mask_pcie_rgr_bridge:1;
+		uint32_t	reserved:25;
+	};
+
+	uint32_t	whole_reg;
+
+} intr_mask_reg;
+
+typedef union _link_misc_perst_deco_ctrl_ {
+	struct {
+		uint32_t	bcm7412_rst:1;		/* 1 -> BCM7412 is held in reset. Reset value 1.*/
+		uint32_t	reserved0:3;		/* Reserved.No Effect*/
+		uint32_t	stop_bcm_7412_clk:1;	/* 1 ->Stops branch of 27MHz clk used to clk BCM7412*/
+		uint32_t	reserved1:27;		/* Reseved. No Effect*/
+	};
+
+	uint32_t	whole_reg;
+
+} link_misc_perst_deco_ctrl;
+
+typedef union _link_misc_perst_clk_ctrl_ {
+	struct {
+		uint32_t	sel_alt_clk:1;	  /* When set, selects a 6.75MHz clock as the source of core_clk */
+		uint32_t	stop_core_clk:1;  /* When set, stops the branch of core_clk that is not needed for low power operation */
+		uint32_t	pll_pwr_dn:1;	  /* When set, powers down the main PLL. The alternate clock bit should be set
+						     to select an alternate clock before setting this bit.*/
+		uint32_t	reserved0:5;	  /* Reserved */
+		uint32_t	pll_mult:8;	  /* This setting controls the multiplier for the PLL. */
+		uint32_t	pll_div:4;	  /* This setting controls the divider for the PLL. */
+		uint32_t	reserved1:12;	  /* Reserved */
+	};
+
+	uint32_t	whole_reg;
+
+} link_misc_perst_clk_ctrl;
+
+
+typedef union _link_misc_perst_decoder_ctrl_ {
+	struct {
+		uint32_t	bcm_7412_rst:1; /* 1 -> BCM7412 is held in reset. Reset value 1.*/
+		uint32_t	res0:3; /* Reserved.No Effect*/
+		uint32_t	stop_7412_clk:1; /* 1 ->Stops branch of 27MHz clk used to clk BCM7412*/
+		uint32_t	res1:27; /* Reseved. No Effect */
+	};
+
+	uint32_t	whole_reg;
+
+} link_misc_perst_decoder_ctrl;
+
+
+typedef union _desc_low_addr_reg_ {
+	struct {
+		uint32_t	list_valid:1;
+		uint32_t	reserved:4;
+		uint32_t	low_addr:27;
+	};
+
+	uint32_t	whole_reg;
+
+} desc_low_addr_reg;
+
+typedef struct _dma_descriptor_ {	/* 8 32-bit values */
+	/* 0th u32 */
+	uint32_t sdram_buff_addr:28;	/* bits 0-27:  SDRAM Address */
+	uint32_t res0:4;		/* bits 28-31: Reserved */
+
+	/* 1st u32 */
+	uint32_t buff_addr_low;		/* 1 buffer address low */
+	uint32_t buff_addr_high;	/* 2 buffer address high */
+
+	/* 3rd u32 */
+	uint32_t res2:2;		/* 0-1 - Reserved */
+	uint32_t xfer_size:23;		/* 2-24 = Xfer size in words */
+	uint32_t res3:6;		/* 25-30 reserved */
+	uint32_t intr_enable:1;		/* 31 - Interrupt After this desc */
+
+	/* 4th u32 */
+	uint32_t endian_xlat_align:2;	/* 0-1 Endian Translation */
+	uint32_t next_desc_cont:1;	/* 2 - Next desc is in contig memory */
+	uint32_t res4:25;		/* 3 - 27 Reserved bits */
+	uint32_t fill_bytes:2;		/* 28-29 Bits Fill Bytes */
+	uint32_t dma_dir:1;		/* 30 bit DMA Direction */
+	uint32_t last_rec_indicator:1;	/* 31 bit Last Record Indicator */
+
+	/* 5th u32 */
+	uint32_t next_desc_addr_low;	/* 32-bits Next Desc Addr lower */
+
+	/* 6th u32 */
+	uint32_t next_desc_addr_high;	/* 32-bits Next Desc Addr Higher */
+
+	/* 7th u32 */
+	uint32_t res8;			/* Last 32bits reserved */
+
+} dma_descriptor, *pdma_descriptor;
+
+/*
+ * We will allocate the memory in 4K pages
+ * the linked list will be a list of 32 byte descriptors.
+ * The  virtual address will determine what should be freed.
+ */
+typedef struct _dma_desc_mem_ {
+	pdma_descriptor		pdma_desc_start; /* 32-bytes for dma descriptor. should be first element */
+	dma_addr_t		phy_addr;	/* physical address of each DMA desc */
+	uint32_t		sz;
+	struct _dma_desc_mem_	*Next;		/* points to Next Descriptor in chain */
+
+} dma_desc_mem, *pdma_desc_mem;
+
+
+
+typedef enum _list_sts_ {
+	sts_free = 0,
+
+	/* RX-Y Bits 0:7 */
+	rx_waiting_y_intr	= 0x00000001,
+	rx_y_error		= 0x00000004,
+
+	/* RX-UV Bits 8:16 */
+	rx_waiting_uv_intr	= 0x0000100,
+	rx_uv_error		= 0x0000400,
+
+	rx_sts_waiting		= (rx_waiting_y_intr|rx_waiting_uv_intr),
+	rx_sts_error		= (rx_y_error|rx_uv_error),
+
+	rx_y_mask		= 0x000000FF,
+	rx_uv_mask		= 0x0000FF00,
+
+} list_sts;
+
+typedef struct _tx_dma_pkt_ {
+	dma_desc_mem		desc_mem;
+	hw_comp_callback	call_back;
+	crystalhd_dio_req		*dio_req;
+	wait_queue_head_t	*cb_event;
+	uint32_t		list_tag;
+
+} tx_dma_pkt;
+
+typedef struct _crystalhd_rx_dma_pkt {
+	dma_desc_mem			desc_mem;
+	crystalhd_dio_req			*dio_req;
+	uint32_t			pkt_tag;
+	uint32_t			flags;
+	BC_PIC_INFO_BLOCK		pib;
+	dma_addr_t			uv_phy_addr;
+	struct  _crystalhd_rx_dma_pkt	*next;
+
+} crystalhd_rx_dma_pkt;
+
+struct crystalhd_hw_stats{
+	uint32_t	rx_errors;
+	uint32_t	tx_errors;
+	uint32_t	freeq_count;
+	uint32_t	rdyq_count;
+	uint32_t	num_interrupts;
+	uint32_t	dev_interrupts;
+	uint32_t	cin_busy;
+	uint32_t	pause_cnt;
+};
+
+struct crystalhd_hw {
+	tx_dma_pkt		tx_pkt_pool[DMA_ENGINE_CNT];
+	spinlock_t		lock;
+
+	uint32_t		tx_ioq_tag_seed;
+	uint32_t		tx_list_post_index;
+
+	crystalhd_rx_dma_pkt	*rx_pkt_pool_head;
+	uint32_t		rx_pkt_tag_seed;
+
+	bool			dev_started;
+	void			*adp;
+
+	wait_queue_head_t	*pfw_cmd_event;
+	int			fwcmd_evt_sts;
+
+	uint32_t		pib_del_Q_addr;
+	uint32_t		pib_rel_Q_addr;
+
+	crystalhd_dioq_t		*tx_freeq;
+	crystalhd_dioq_t		*tx_actq;
+
+	/* Rx DMA Engine Specific Locks */
+	spinlock_t		rx_lock;
+	uint32_t		rx_list_post_index;
+	list_sts		rx_list_sts[DMA_ENGINE_CNT];
+	crystalhd_dioq_t		*rx_rdyq;
+	crystalhd_dioq_t		*rx_freeq;
+	crystalhd_dioq_t		*rx_actq;
+	uint32_t		stop_pending;
+
+	/* HW counters.. */
+	struct crystalhd_hw_stats	stats;
+
+	/* Core clock in MHz */
+	uint32_t		core_clock_mhz;
+	uint32_t		prev_n;
+	uint32_t		pwr_lock;
+};
+
+/* Clock defines for power control */
+#define CLOCK_PRESET 175
+
+/* DMA engine register BIT mask wrappers.. */
+#define DMA_START_BIT		MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_MASK
+
+#define GET_RX_INTR_MASK (INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_MASK |		\
+			  INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK |	\
+			  INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_MASK |		\
+			  INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK |		\
+			  INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_MASK |		\
+			  INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK |	\
+			  INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_MASK |		\
+			  INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK)
+
+#define GET_Y0_ERR_MSK (MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK |		\
+			MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK |		\
+			MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK |	\
+			MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK)
+
+#define GET_UV0_ERR_MSK (MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK |		\
+			 MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK |		\
+			 MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK |	\
+			 MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK)
+
+#define GET_Y1_ERR_MSK (MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK |		\
+			MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK |		\
+			MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK |	\
+			MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK)
+
+#define GET_UV1_ERR_MSK	(MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK |		\
+			 MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK |		\
+			 MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK |	\
+			 MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK)
+
+
+/**** API Exposed to the other layers ****/
+BC_STATUS crystalhd_download_fw(struct crystalhd_adp *adp,
+			      void *buffer, uint32_t sz);
+BC_STATUS crystalhd_do_fw_cmd(struct crystalhd_hw *hw, BC_FW_CMD *fw_cmd);
+bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw);
+BC_STATUS crystalhd_hw_open(struct crystalhd_hw *, struct crystalhd_adp *);
+BC_STATUS crystalhd_hw_close(struct crystalhd_hw *);
+BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *);
+BC_STATUS crystalhd_hw_free_dma_rings(struct crystalhd_hw *);
+
+
+BC_STATUS crystalhd_hw_post_tx(struct crystalhd_hw *hw, crystalhd_dio_req *ioreq,
+			     hw_comp_callback call_back,
+			     wait_queue_head_t *cb_event,
+			     uint32_t *list_id, uint8_t data_flags);
+
+BC_STATUS crystalhd_hw_pause(struct crystalhd_hw *hw);
+BC_STATUS crystalhd_hw_unpause(struct crystalhd_hw *hw);
+BC_STATUS crystalhd_hw_suspend(struct crystalhd_hw *hw);
+BC_STATUS crystalhd_hw_cancel_tx(struct crystalhd_hw *hw, uint32_t list_id);
+BC_STATUS crystalhd_hw_add_cap_buffer(struct crystalhd_hw *hw,
+				    crystalhd_dio_req *ioreq, bool en_post);
+BC_STATUS crystalhd_hw_get_cap_buffer(struct crystalhd_hw *hw,
+				    BC_PIC_INFO_BLOCK *pib,
+				    crystalhd_dio_req **ioreq);
+BC_STATUS crystalhd_hw_stop_capture(struct crystalhd_hw *hw);
+BC_STATUS crystalhd_hw_start_capture(struct crystalhd_hw *hw);
+void crystalhd_hw_stats(struct crystalhd_hw *hw, struct crystalhd_hw_stats *stats);
+
+/* API to program the core clock on the decoder */
+BC_STATUS crystalhd_hw_set_core_clock(struct crystalhd_hw *);
+
+#endif
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
new file mode 100644
index 0000000..3eac70a
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_lnx.c
@@ -0,0 +1,765 @@
+/***************************************************************************
+  BCM70010 Linux driver
+  Copyright (c) 2005-2009, Broadcom Corporation.
+
+  This driver is free software; 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 driver is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this driver.  If not, see <http://www.gnu.org/licenses/>.
+***************************************************************************/
+
+#include <linux/version.h>
+
+#include "crystalhd_lnx.h"
+
+static struct class *crystalhd_class;
+
+static struct crystalhd_adp *g_adp_info;
+
+static irqreturn_t chd_dec_isr(int irq, void *arg)
+{
+	struct crystalhd_adp *adp = (struct crystalhd_adp *) arg;
+	int rc = 0;
+	if (adp)
+		rc = crystalhd_cmd_interrupt(&adp->cmds);
+
+	return IRQ_RETVAL(rc);
+}
+
+static int chd_dec_enable_int(struct crystalhd_adp *adp)
+{
+	int rc = 0;
+
+	if (!adp || !adp->pdev) {
+		BCMLOG_ERR("Invalid arg!!\n");
+		return -EINVAL;
+	}
+
+	if (adp->pdev->msi_enabled)
+		adp->msi = 1;
+	else
+		adp->msi = pci_enable_msi(adp->pdev);
+
+	rc = request_irq(adp->pdev->irq, chd_dec_isr, IRQF_SHARED,
+			 adp->name, (void *)adp);
+	if (rc) {
+		BCMLOG_ERR("Interrupt request failed.. \n");
+		pci_disable_msi(adp->pdev);
+	}
+
+	return rc;
+}
+
+static int chd_dec_disable_int(struct crystalhd_adp *adp)
+{
+	if (!adp || !adp->pdev) {
+		BCMLOG_ERR("Invalid arg!!\n");
+		return -EINVAL;
+	}
+
+	free_irq(adp->pdev->irq, adp);
+
+	if (adp->msi)
+		pci_disable_msi(adp->pdev);
+
+	return 0;
+}
+
+crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp, bool isr)
+{
+	unsigned long flags = 0;
+	crystalhd_ioctl_data *temp;
+
+	if (!adp)
+		return NULL;
+
+	spin_lock_irqsave(&adp->lock, flags);
+
+	temp = adp->idata_free_head;
+	if (temp) {
+		adp->idata_free_head = adp->idata_free_head->next;
+		memset(temp, 0, sizeof(*temp));
+	}
+
+	spin_unlock_irqrestore(&adp->lock, flags);
+	return temp;
+}
+
+void chd_dec_free_iodata(struct crystalhd_adp *adp, crystalhd_ioctl_data *iodata,
+			 bool isr)
+{
+	unsigned long flags = 0;
+
+	if (!adp || !iodata)
+		return;
+
+	spin_lock_irqsave(&adp->lock, flags);
+	iodata->next = adp->idata_free_head;
+	adp->idata_free_head = iodata;
+	spin_unlock_irqrestore(&adp->lock, flags);
+}
+
+static inline int crystalhd_user_data(unsigned long ud, void *dr, int size, int set)
+{
+	int rc;
+
+	if (!ud || !dr) {
+		BCMLOG_ERR("Invalid arg \n");
+		return -EINVAL;
+	}
+
+	if (set)
+		rc = copy_to_user((void *)ud, dr, size);
+	else
+		rc = copy_from_user(dr, (void *)ud, size);
+
+	if (rc) {
+		BCMLOG_ERR("Invalid args for command \n");
+		rc = -EFAULT;
+	}
+
+	return rc;
+}
+
+static int chd_dec_fetch_cdata(struct crystalhd_adp *adp, crystalhd_ioctl_data *io,
+			       uint32_t m_sz, unsigned long ua)
+{
+	unsigned long ua_off;
+	int rc = 0;
+
+	if (!adp || !io || !ua || !m_sz) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return -EINVAL;
+	}
+
+	io->add_cdata = vmalloc(m_sz);
+	if (!io->add_cdata) {
+		BCMLOG_ERR("kalloc fail for sz:%x\n", m_sz);
+		return -ENOMEM;
+	}
+
+	io->add_cdata_sz = m_sz;
+	ua_off = ua + sizeof(io->udata);
+	rc = crystalhd_user_data(ua_off, io->add_cdata, io->add_cdata_sz, 0);
+	if (rc) {
+		BCMLOG_ERR("failed to pull add_cdata sz:%x ua_off:%x\n",
+			   io->add_cdata_sz, (unsigned int)ua_off);
+		if (io->add_cdata) {
+			kfree(io->add_cdata);
+			io->add_cdata = NULL;
+		}
+		return -ENODATA;
+	}
+
+	return rc;
+}
+
+static int chd_dec_release_cdata(struct crystalhd_adp *adp,
+				 crystalhd_ioctl_data *io, unsigned long ua)
+{
+	unsigned long ua_off;
+	int rc;
+
+	if (!adp || !io || !ua) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return -EINVAL;
+	}
+
+	if (io->cmd != BCM_IOC_FW_DOWNLOAD) {
+		ua_off = ua + sizeof(io->udata);
+		rc = crystalhd_user_data(ua_off, io->add_cdata,
+					io->add_cdata_sz, 1);
+		if (rc) {
+			BCMLOG_ERR("failed to push add_cdata sz:%x ua_off:%x\n",
+				   io->add_cdata_sz, (unsigned int)ua_off);
+			return -ENODATA;
+		}
+	}
+
+	if (io->add_cdata) {
+		vfree(io->add_cdata);
+		io->add_cdata = NULL;
+	}
+
+	return 0;
+}
+
+static int chd_dec_proc_user_data(struct crystalhd_adp *adp,
+				  crystalhd_ioctl_data *io,
+				  unsigned long ua, int set)
+{
+	int rc;
+	uint32_t m_sz = 0;
+
+	if (!adp || !io || !ua) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return -EINVAL;
+	}
+
+	rc = crystalhd_user_data(ua, &io->udata, sizeof(io->udata), set);
+	if (rc) {
+		BCMLOG_ERR("failed to %s iodata \n", (set ? "set" : "get"));
+		return rc;
+	}
+
+	switch (io->cmd) {
+	case BCM_IOC_MEM_RD:
+	case BCM_IOC_MEM_WR:
+	case BCM_IOC_FW_DOWNLOAD:
+		m_sz = io->udata.u.devMem.NumDwords * 4;
+		if (set)
+			rc = chd_dec_release_cdata(adp, io, ua);
+		else
+			rc = chd_dec_fetch_cdata(adp, io, m_sz, ua);
+		break;
+	default:
+		break;
+	}
+
+	return rc;
+}
+
+static int chd_dec_api_cmd(struct crystalhd_adp *adp, unsigned long ua,
+			   uint32_t uid, uint32_t cmd, crystalhd_cmd_proc func)
+{
+	int rc;
+	crystalhd_ioctl_data *temp;
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	temp = chd_dec_alloc_iodata(adp, 0);
+	if (!temp) {
+		BCMLOG_ERR("Failed to get iodata..\n");
+		return -EINVAL;
+	}
+
+	temp->u_id = uid;
+	temp->cmd  = cmd;
+
+	rc = chd_dec_proc_user_data(adp, temp, ua, 0);
+	if (!rc) {
+		sts = func(&adp->cmds, temp);
+		if (sts == BC_STS_PENDING)
+			sts = BC_STS_NOT_IMPL;
+		temp->udata.RetSts = sts;
+		rc = chd_dec_proc_user_data(adp, temp, ua, 1);
+	}
+
+	if (temp) {
+		chd_dec_free_iodata(adp, temp, 0);
+		temp = NULL;
+	}
+
+	return rc;
+}
+
+/* API interfaces */
+static int chd_dec_ioctl(struct inode *in, struct file *fd,
+			 unsigned int cmd, unsigned long ua)
+{
+	struct crystalhd_adp *adp = chd_get_adp();
+	crystalhd_cmd_proc cproc;
+	struct crystalhd_user *uc;
+
+	if (!adp || !fd) {
+		BCMLOG_ERR("Invalid adp\n");
+		return -EINVAL;
+	}
+
+	uc = (struct crystalhd_user *)fd->private_data;
+	if (!uc) {
+		BCMLOG_ERR("Failed to get uc\n");
+		return -ENODATA;
+	}
+
+	cproc = crystalhd_get_cmd_proc(&adp->cmds, cmd, uc);
+	if (!cproc) {
+		BCMLOG_ERR("Unhandled command: %d\n", cmd);
+		return -EINVAL;
+	}
+
+	return chd_dec_api_cmd(adp, ua, uc->uid, cmd, cproc);
+}
+
+static int chd_dec_open(struct inode *in, struct file *fd)
+{
+	struct crystalhd_adp *adp = chd_get_adp();
+	int rc = 0;
+	BC_STATUS sts = BC_STS_SUCCESS;
+	struct crystalhd_user *uc = NULL;
+
+	BCMLOG_ENTER;
+	if (!adp) {
+		BCMLOG_ERR("Invalid adp\n");
+		return -EINVAL;
+	}
+
+	if (adp->cfg_users >= BC_LINK_MAX_OPENS) {
+		BCMLOG(BCMLOG_INFO, "Already in use.%d\n", adp->cfg_users);
+		return -EBUSY;
+	}
+
+	sts = crystalhd_user_open(&adp->cmds, &uc);
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG_ERR("cmd_user_open - %d \n", sts);
+		rc = -EBUSY;
+	}
+
+	adp->cfg_users++;
+
+	fd->private_data = uc;
+
+	return rc;
+}
+
+static int chd_dec_close(struct inode *in, struct file *fd)
+{
+	struct crystalhd_adp *adp = chd_get_adp();
+	struct crystalhd_user *uc;
+
+	BCMLOG_ENTER;
+	if (!adp) {
+		BCMLOG_ERR("Invalid adp \n");
+		return -EINVAL;
+	}
+
+	uc = (struct crystalhd_user *)fd->private_data;
+	if (!uc) {
+		BCMLOG_ERR("Failed to get uc\n");
+		return -ENODATA;
+	}
+
+	crystalhd_user_close(&adp->cmds, uc);
+
+	adp->cfg_users--;
+
+	return 0;
+}
+
+static const struct file_operations chd_dec_fops = {
+	.owner   = THIS_MODULE,
+	.ioctl   = chd_dec_ioctl,
+	.open    = chd_dec_open,
+	.release = chd_dec_close,
+};
+
+static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp)
+{
+	crystalhd_ioctl_data *temp;
+	struct device *dev;
+	int rc = -ENODEV, i = 0;
+
+	if (!adp)
+		goto fail;
+
+	adp->chd_dec_major = register_chrdev(0, CRYSTALHD_API_NAME,
+					     &chd_dec_fops);
+	if (adp->chd_dec_major < 0) {
+		BCMLOG_ERR("Failed to create config dev\n");
+		rc = adp->chd_dec_major;
+		goto fail;
+	}
+
+	/* register crystalhd class */
+	crystalhd_class = class_create(THIS_MODULE, "crystalhd");
+	if (IS_ERR(crystalhd_class)) {
+		BCMLOG_ERR("failed to create class\n");
+		goto fail;
+	}
+
+	dev = device_create(crystalhd_class, NULL, MKDEV(adp->chd_dec_major, 0),
+			    NULL, "crystalhd");
+	if (!dev) {
+		BCMLOG_ERR("failed to create device\n");
+		goto device_create_fail;
+	}
+
+	rc = crystalhd_create_elem_pool(adp, BC_LINK_ELEM_POOL_SZ);
+	if (rc) {
+		BCMLOG_ERR("failed to create device\n");
+		goto elem_pool_fail;
+	}
+
+	/* Allocate general purpose ioctl pool. */
+	for (i = 0; i < CHD_IODATA_POOL_SZ; i++) {
+		/* FIXME: jarod: why atomic? */
+		temp = kzalloc(sizeof(crystalhd_ioctl_data), GFP_ATOMIC);
+		if (!temp) {
+			BCMLOG_ERR("ioctl data pool kzalloc failed\n");
+			rc = -ENOMEM;
+			goto kzalloc_fail;
+		}
+		/* Add to global pool.. */
+		chd_dec_free_iodata(adp, temp, 0);
+	}
+
+	return 0;
+
+kzalloc_fail:
+	crystalhd_delete_elem_pool(adp);
+elem_pool_fail:
+	device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
+device_create_fail:
+	class_destroy(crystalhd_class);
+fail:
+	return rc;
+}
+
+static void __devexit chd_dec_release_chdev(struct crystalhd_adp *adp)
+{
+	crystalhd_ioctl_data *temp = NULL;
+	if (!adp)
+		return;
+
+	if (adp->chd_dec_major > 0) {
+		/* unregister crystalhd class */
+		device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
+		unregister_chrdev(adp->chd_dec_major, CRYSTALHD_API_NAME);
+		BCMLOG(BCMLOG_INFO, "released api device - %d\n",
+		       adp->chd_dec_major);
+		class_destroy(crystalhd_class);
+	}
+	adp->chd_dec_major = 0;
+
+	/* Clear iodata pool.. */
+	do {
+		temp = chd_dec_alloc_iodata(adp, 0);
+		if (temp)
+			kfree(temp);
+	} while (temp);
+
+	crystalhd_delete_elem_pool(adp);
+}
+
+static int __devinit chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
+{
+	int rc;
+	unsigned long bar2 = pci_resource_start(pinfo->pdev, 2);
+	uint32_t mem_len   = pci_resource_len(pinfo->pdev, 2);
+	unsigned long bar0 = pci_resource_start(pinfo->pdev, 0);
+	uint32_t i2o_len   = pci_resource_len(pinfo->pdev, 0);
+
+	BCMLOG(BCMLOG_SSTEP, "bar2:0x%lx-0x%08x  bar0:0x%lx-0x%08x\n",
+	       bar2, mem_len, bar0, i2o_len);
+
+	rc = check_mem_region(bar2, mem_len);
+	if (rc) {
+		BCMLOG_ERR("No valid mem region...\n");
+		return -ENOMEM;
+	}
+
+	pinfo->addr = ioremap_nocache(bar2, mem_len);
+	if (!pinfo->addr) {
+		BCMLOG_ERR("Failed to remap mem region...\n");
+		return -ENOMEM;
+	}
+
+	pinfo->pci_mem_start = bar2;
+	pinfo->pci_mem_len   = mem_len;
+
+	rc = check_mem_region(bar0, i2o_len);
+	if (rc) {
+		BCMLOG_ERR("No valid mem region...\n");
+		return -ENOMEM;
+	}
+
+	pinfo->i2o_addr = ioremap_nocache(bar0, i2o_len);
+	if (!pinfo->i2o_addr) {
+		BCMLOG_ERR("Failed to remap mem region...\n");
+		return -ENOMEM;
+	}
+
+	pinfo->pci_i2o_start = bar0;
+	pinfo->pci_i2o_len   = i2o_len;
+
+	rc = pci_request_regions(pinfo->pdev, pinfo->name);
+	if (rc < 0) {
+		BCMLOG_ERR("Region request failed: %d\n", rc);
+		return rc;
+	}
+
+	BCMLOG(BCMLOG_SSTEP, "Mapped addr:0x%08lx  i2o_addr:0x%08lx\n",
+	       (unsigned long)pinfo->addr, (unsigned long)pinfo->i2o_addr);
+
+	return 0;
+}
+
+static void __devexit chd_pci_release_mem(struct crystalhd_adp *pinfo)
+{
+	if (!pinfo)
+		return;
+
+	if (pinfo->addr)
+		iounmap(pinfo->addr);
+
+	if (pinfo->i2o_addr)
+		iounmap(pinfo->i2o_addr);
+
+	pci_release_regions(pinfo->pdev);
+}
+
+
+static void __devexit chd_dec_pci_remove(struct pci_dev *pdev)
+{
+	struct crystalhd_adp *pinfo;
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	BCMLOG_ENTER;
+
+	pinfo = (struct crystalhd_adp *) pci_get_drvdata(pdev);
+	if (!pinfo) {
+		BCMLOG_ERR("could not get adp\n");
+		return;
+	}
+
+	sts = crystalhd_delete_cmd_context(&pinfo->cmds);
+	if (sts != BC_STS_SUCCESS)
+		BCMLOG_ERR("cmd delete :%d \n", sts);
+
+	chd_dec_release_chdev(pinfo);
+
+	chd_dec_disable_int(pinfo);
+
+	chd_pci_release_mem(pinfo);
+	pci_disable_device(pinfo->pdev);
+
+	kfree(pinfo);
+	g_adp_info = NULL;
+}
+
+static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
+			     const struct pci_device_id *entry)
+{
+	struct crystalhd_adp *pinfo;
+	int rc;
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	BCMLOG(BCMLOG_DBG, "PCI_INFO: Vendor:0x%04x Device:0x%04x "
+	       "s_vendor:0x%04x s_device: 0x%04x\n",
+	       pdev->vendor, pdev->device, pdev->subsystem_vendor,
+	       pdev->subsystem_device);
+
+	/* FIXME: jarod: why atomic? */
+	pinfo = kzalloc(sizeof(struct crystalhd_adp), GFP_ATOMIC);
+	if (!pinfo) {
+		BCMLOG_ERR("Failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	pinfo->pdev = pdev;
+
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		BCMLOG_ERR("Failed to enable PCI device\n");
+		return rc;
+	}
+
+	snprintf(pinfo->name, 31, "crystalhd_pci_e:%d:%d:%d",
+		 pdev->bus->number, PCI_SLOT(pdev->devfn),
+		 PCI_FUNC(pdev->devfn));
+
+	rc = chd_pci_reserve_mem(pinfo);
+	if (rc) {
+		BCMLOG_ERR("Failed to setup memory regions.\n");
+		return -ENOMEM;
+	}
+
+	pinfo->present	= 1;
+	pinfo->drv_data = entry->driver_data;
+
+	/* Setup adapter level lock.. */
+	spin_lock_init(&pinfo->lock);
+
+	/* setup api stuff.. */
+	chd_dec_init_chdev(pinfo);
+	rc = chd_dec_enable_int(pinfo);
+	if (rc) {
+		BCMLOG_ERR("_enable_int err:%d \n", rc);
+		pci_disable_device(pdev);
+		return -ENODEV;
+	}
+
+	/* Set dma mask... */
+	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+		pinfo->dmabits = 64;
+	} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+		pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+		pinfo->dmabits = 32;
+	} else {
+		BCMLOG_ERR("Unabled to setup DMA %d\n", rc);
+		pci_disable_device(pdev);
+		return -ENODEV;
+	}
+
+	sts = crystalhd_setup_cmd_context(&pinfo->cmds, pinfo);
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG_ERR("cmd setup :%d \n", sts);
+		pci_disable_device(pdev);
+		return -ENODEV;
+	}
+
+	pci_set_master(pdev);
+
+	pci_set_drvdata(pdev, pinfo);
+
+	g_adp_info = pinfo;
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct crystalhd_adp *adp;
+	crystalhd_ioctl_data *temp;
+	BC_STATUS sts = BC_STS_SUCCESS;
+
+	adp = (struct crystalhd_adp *)pci_get_drvdata(pdev);
+	if (!adp) {
+		BCMLOG_ERR("could not get adp\n");
+		return -ENODEV;
+	}
+
+	temp = chd_dec_alloc_iodata(adp, false);
+	if (!temp) {
+		BCMLOG_ERR("could not get ioctl data\n");
+		return -ENODEV;
+	}
+
+	sts = crystalhd_suspend(&adp->cmds, temp);
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG_ERR("BCM70012 Suspend %d\n", sts);
+		return -ENODEV;
+	}
+
+	chd_dec_free_iodata(adp, temp, false);
+	chd_dec_disable_int(adp);
+	pci_save_state(pdev);
+
+	/* Disable IO/bus master/irq router */
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	return 0;
+}
+
+int chd_dec_pci_resume(struct pci_dev *pdev)
+{
+	struct crystalhd_adp *adp;
+	BC_STATUS sts = BC_STS_SUCCESS;
+	int rc;
+
+	adp = (struct crystalhd_adp *)pci_get_drvdata(pdev);
+	if (!adp) {
+		BCMLOG_ERR("could not get adp\n");
+		return -ENODEV;
+	}
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	/* device's irq possibly is changed, driver should take care */
+	if (pci_enable_device(pdev)) {
+		BCMLOG_ERR("Failed to enable PCI device\n");
+		return 1;
+	}
+
+	pci_set_master(pdev);
+
+	rc = chd_dec_enable_int(adp);
+	if (rc) {
+		BCMLOG_ERR("_enable_int err:%d \n", rc);
+		pci_disable_device(pdev);
+		return -ENODEV;
+	}
+
+	sts = crystalhd_resume(&adp->cmds);
+	if (sts != BC_STS_SUCCESS) {
+		BCMLOG_ERR("BCM70012 Resume %d\n", sts);
+		pci_disable_device(pdev);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+#endif
+
+static DEFINE_PCI_DEVICE_TABLE(chd_dec_pci_id_table) = {
+	{ PCI_VDEVICE(BROADCOM, 0x1612), 8 },
+	{ 0, },
+};
+MODULE_DEVICE_TABLE(pci, chd_dec_pci_id_table);
+
+static struct pci_driver bc_chd_70012_driver = {
+	.name     = "Broadcom 70012 Decoder",
+	.probe    = chd_dec_pci_probe,
+	.remove   = __devexit_p(chd_dec_pci_remove),
+	.id_table = chd_dec_pci_id_table,
+#ifdef CONFIG_PM
+	.suspend  = chd_dec_pci_suspend,
+	.resume   = chd_dec_pci_resume
+#endif
+};
+
+void chd_set_log_level(struct crystalhd_adp *adp, char *arg)
+{
+	if ((!arg) || (strlen(arg) < 3))
+		g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA;
+	else if (!strncmp(arg, "sstep", 5))
+		g_linklog_level = BCMLOG_INFO | BCMLOG_DATA | BCMLOG_DBG |
+				  BCMLOG_SSTEP | BCMLOG_ERROR;
+	else if (!strncmp(arg, "info", 4))
+		g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO;
+	else if (!strncmp(arg, "debug", 5))
+		g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO |
+				  BCMLOG_DBG;
+	else if (!strncmp(arg, "pball", 5))
+		g_linklog_level = 0xFFFFFFFF & ~(BCMLOG_SPINLOCK);
+	else if (!strncmp(arg, "silent", 6))
+		g_linklog_level = 0;
+	else
+		g_linklog_level = 0;
+}
+
+struct crystalhd_adp *chd_get_adp(void)
+{
+	return g_adp_info;
+}
+
+static int __init chd_dec_module_init(void)
+{
+	int rc;
+
+	chd_set_log_level(NULL, "debug");
+	BCMLOG(BCMLOG_DATA, "Loading crystalhd %d.%d.%d \n",
+	       crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
+
+	rc = pci_register_driver(&bc_chd_70012_driver);
+
+	if (rc < 0)
+		BCMLOG_ERR("Could not find any devices. err:%d \n", rc);
+
+	return rc;
+}
+module_init(chd_dec_module_init);
+
+static void __exit chd_dec_module_cleanup(void)
+{
+	BCMLOG(BCMLOG_DATA, "unloading crystalhd %d.%d.%d \n",
+	       crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
+
+	pci_unregister_driver(&bc_chd_70012_driver);
+}
+module_exit(chd_dec_module_cleanup);
+
+MODULE_AUTHOR("Naren Sankar <nsankar@broadcom.com>");
+MODULE_AUTHOR("Prasad Bolisetty <prasadb@broadcom.com>");
+MODULE_DESCRIPTION(CRYSTAL_HD_NAME);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("bcm70012");
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.h b/drivers/staging/crystalhd/crystalhd_lnx.h
new file mode 100644
index 0000000..d338ae9
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_lnx.h
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ *  Name: crystalhd_lnx . c
+ *
+ *  Description:
+ *		BCM70012 Linux driver
+ *
+ *  HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * This driver is free software; 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 driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#ifndef _CRYSTALHD_LNX_H_
+#define _CRYSTALHD_LNX_H_
+
+#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/pci.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "crystalhd_cmds.h"
+
+#define CRYSTAL_HD_NAME		"Broadcom Crystal HD Decoder (BCM70012) Driver"
+
+
+/* OS specific PCI information structure and adapter information. */
+struct crystalhd_adp {
+	/* Hardware borad/PCI specifics */
+	char			name[32];
+	struct pci_dev		*pdev;
+
+	unsigned long		pci_mem_start;
+	uint32_t		pci_mem_len;
+	void			*addr;
+
+	unsigned long		pci_i2o_start;
+	uint32_t		pci_i2o_len;
+	void			*i2o_addr;
+
+	unsigned int		drv_data;
+	unsigned int		dmabits;	/* 32 | 64 */
+	unsigned int		registered;
+	unsigned int		present;
+	unsigned int		msi;
+
+	spinlock_t		lock;
+
+	/* API Related */
+	unsigned int		chd_dec_major;
+	unsigned int		cfg_users;
+
+	crystalhd_ioctl_data	*idata_free_head;	/* ioctl data pool */
+	crystalhd_elem_t		*elem_pool_head;	/* Queue element pool */
+
+	struct crystalhd_cmd	cmds;
+
+	crystalhd_dio_req		*ua_map_free_head;
+	struct pci_pool		*fill_byte_pool;
+};
+
+
+struct crystalhd_adp *chd_get_adp(void);
+void chd_set_log_level(struct crystalhd_adp *adp, char *arg);
+
+#endif
+
diff --git a/drivers/staging/crystalhd/crystalhd_misc.c b/drivers/staging/crystalhd/crystalhd_misc.c
new file mode 100644
index 0000000..587dcc4
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_misc.c
@@ -0,0 +1,1030 @@
+/***************************************************************************
+ *	   Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ *  Name: crystalhd_misc . c
+ *
+ *  Description:
+ *		BCM70012 Linux driver misc routines.
+ *
+ *  HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * This driver is free software; 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 driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#include "crystalhd_misc.h"
+#include "crystalhd_lnx.h"
+
+uint32_t g_linklog_level;
+
+static inline uint32_t crystalhd_dram_rd(struct crystalhd_adp *adp, uint32_t mem_off)
+{
+	crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
+	return bc_dec_reg_rd(adp, (0x00380000 | (mem_off & 0x0007FFFF)));
+}
+
+static inline void crystalhd_dram_wr(struct crystalhd_adp *adp, uint32_t mem_off, uint32_t val)
+{
+	crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
+	bc_dec_reg_wr(adp, (0x00380000 | (mem_off & 0x0007FFFF)), val);
+}
+
+static inline BC_STATUS bc_chk_dram_range(struct crystalhd_adp *adp, uint32_t start_off, uint32_t cnt)
+{
+	return BC_STS_SUCCESS;
+}
+
+static crystalhd_dio_req *crystalhd_alloc_dio(struct crystalhd_adp *adp)
+{
+	unsigned long flags = 0;
+	crystalhd_dio_req *temp = NULL;
+
+	if (!adp) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return temp;
+	}
+
+	spin_lock_irqsave(&adp->lock, flags);
+	temp = adp->ua_map_free_head;
+	if (temp)
+		adp->ua_map_free_head = adp->ua_map_free_head->next;
+	spin_unlock_irqrestore(&adp->lock, flags);
+
+	return temp;
+}
+
+static void crystalhd_free_dio(struct crystalhd_adp *adp, crystalhd_dio_req *dio)
+{
+	unsigned long flags = 0;
+
+	if (!adp || !dio)
+		return;
+	spin_lock_irqsave(&adp->lock, flags);
+	dio->sig = crystalhd_dio_inv;
+	dio->page_cnt = 0;
+	dio->fb_size = 0;
+	memset(&dio->uinfo, 0, sizeof(dio->uinfo));
+	dio->next = adp->ua_map_free_head;
+	adp->ua_map_free_head = dio;
+	spin_unlock_irqrestore(&adp->lock, flags);
+}
+
+static crystalhd_elem_t *crystalhd_alloc_elem(struct crystalhd_adp *adp)
+{
+	unsigned long flags = 0;
+	crystalhd_elem_t *temp = NULL;
+
+	if (!adp)
+		return temp;
+	spin_lock_irqsave(&adp->lock, flags);
+	temp = adp->elem_pool_head;
+	if (temp) {
+		adp->elem_pool_head = adp->elem_pool_head->flink;
+		memset(temp, 0, sizeof(*temp));
+	}
+	spin_unlock_irqrestore(&adp->lock, flags);
+
+	return temp;
+}
+static void crystalhd_free_elem(struct crystalhd_adp *adp, crystalhd_elem_t *elem)
+{
+	unsigned long flags = 0;
+
+	if (!adp || !elem)
+		return;
+	spin_lock_irqsave(&adp->lock, flags);
+	elem->flink = adp->elem_pool_head;
+	adp->elem_pool_head = elem;
+	spin_unlock_irqrestore(&adp->lock, flags);
+}
+
+static inline void crystalhd_set_sg(struct scatterlist *sg, struct page *page,
+				  unsigned int len, unsigned int offset)
+{
+	sg_set_page(sg, page, len, offset);
+#ifdef CONFIG_X86_64
+	sg->dma_length = len;
+#endif
+}
+
+static inline void crystalhd_init_sg(struct scatterlist *sg, unsigned int entries)
+{
+	/* http://lkml.org/lkml/2007/11/27/68 */
+	sg_init_table(sg, entries);
+}
+
+/*========================== Extern ========================================*/
+/**
+ * bc_dec_reg_rd - Read 7412's device register.
+ * @adp: Adapter instance
+ * @reg_off: Register offset.
+ *
+ * Return:
+ *	32bit value read
+ *
+ * 7412's device register read routine. This interface use
+ * 7412's device access range mapped from BAR-2 (4M) of PCIe
+ * configuration space.
+ */
+uint32_t bc_dec_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
+{
+	if (!adp || (reg_off > adp->pci_mem_len)) {
+		BCMLOG_ERR("dec_rd_reg_off outof range: 0x%08x\n", reg_off);
+		return 0;
+	}
+
+	return readl(adp->addr + reg_off);
+}
+
+/**
+ * bc_dec_reg_wr - Write 7412's device register
+ * @adp: Adapter instance
+ * @reg_off: Register offset.
+ * @val: Dword value to be written.
+ *
+ * Return:
+ *	none.
+ *
+ * 7412's device register write routine. This interface use
+ * 7412's device access range mapped from BAR-2 (4M) of PCIe
+ * configuration space.
+ */
+void bc_dec_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
+{
+	if (!adp || (reg_off > adp->pci_mem_len)) {
+		BCMLOG_ERR("dec_wr_reg_off outof range: 0x%08x\n", reg_off);
+		return;
+	}
+	writel(val, adp->addr + reg_off);
+	udelay(8);
+}
+
+/**
+ * crystalhd_reg_rd - Read Link's device register.
+ * @adp: Adapter instance
+ * @reg_off: Register offset.
+ *
+ * Return:
+ *	32bit value read
+ *
+ * Link device register  read routine. This interface use
+ * Link's device access range mapped from BAR-1 (64K) of PCIe
+ * configuration space.
+ *
+ */
+uint32_t crystalhd_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
+{
+	if (!adp || (reg_off > adp->pci_i2o_len)) {
+		BCMLOG_ERR("link_rd_reg_off outof range: 0x%08x\n", reg_off);
+		return 0;
+	}
+	return readl(adp->i2o_addr + reg_off);
+}
+
+/**
+ * crystalhd_reg_wr - Write Link's device register
+ * @adp: Adapter instance
+ * @reg_off: Register offset.
+ * @val: Dword value to be written.
+ *
+ * Return:
+ *	none.
+ *
+ * Link device register  write routine. This interface use
+ * Link's device access range mapped from BAR-1 (64K) of PCIe
+ * configuration space.
+ *
+ */
+void crystalhd_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
+{
+	if (!adp || (reg_off > adp->pci_i2o_len)) {
+		BCMLOG_ERR("link_wr_reg_off outof range: 0x%08x\n", reg_off);
+		return;
+	}
+	writel(val, adp->i2o_addr + reg_off);
+}
+
+/**
+ * crystalhd_mem_rd - Read data from 7412's DRAM area.
+ * @adp: Adapter instance
+ * @start_off: Start offset.
+ * @dw_cnt: Count in dwords.
+ * @rd_buff: Buffer to copy the data from dram.
+ *
+ * Return:
+ *	Status.
+ *
+ * 7412's Dram read routine.
+ */
+BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *adp, uint32_t start_off,
+			 uint32_t dw_cnt, uint32_t *rd_buff)
+{
+	uint32_t ix = 0;
+
+	if (!adp || !rd_buff ||
+	    (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
+		BCMLOG_ERR("Invalid arg \n");
+		return BC_STS_INV_ARG;
+	}
+	for (ix = 0; ix < dw_cnt; ix++)
+		rd_buff[ix] = crystalhd_dram_rd(adp, (start_off + (ix * 4)));
+
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_mem_wr - Write data to 7412's DRAM area.
+ * @adp: Adapter instance
+ * @start_off: Start offset.
+ * @dw_cnt: Count in dwords.
+ * @wr_buff: Data Buffer to be written.
+ *
+ * Return:
+ *	Status.
+ *
+ * 7412's Dram write routine.
+ */
+BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *adp, uint32_t start_off,
+			 uint32_t dw_cnt, uint32_t *wr_buff)
+{
+	uint32_t ix = 0;
+
+	if (!adp || !wr_buff ||
+	    (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
+		BCMLOG_ERR("Invalid arg \n");
+		return BC_STS_INV_ARG;
+	}
+
+	for (ix = 0; ix < dw_cnt; ix++)
+		crystalhd_dram_wr(adp, (start_off + (ix * 4)), wr_buff[ix]);
+
+	return BC_STS_SUCCESS;
+}
+/**
+ * crystalhd_pci_cfg_rd - PCIe config read
+ * @adp: Adapter instance
+ * @off: PCI config space offset.
+ * @len: Size -- Byte, Word & dword.
+ * @val: Value read
+ *
+ * Return:
+ *	Status.
+ *
+ * Get value from Link's PCIe config space.
+ */
+BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *adp, uint32_t off,
+			     uint32_t len, uint32_t *val)
+{
+	BC_STATUS sts = BC_STS_SUCCESS;
+	int rc = 0;
+
+	if (!adp || !val) {
+		BCMLOG_ERR("Invalid arg \n");
+		return BC_STS_INV_ARG;
+	}
+
+	switch (len) {
+	case 1:
+		rc = pci_read_config_byte(adp->pdev, off, (u8 *)val);
+		break;
+	case 2:
+		rc = pci_read_config_word(adp->pdev, off, (u16 *)val);
+		break;
+	case 4:
+		rc = pci_read_config_dword(adp->pdev, off, (u32 *)val);
+		break;
+	default:
+		rc = -EINVAL;
+		sts = BC_STS_INV_ARG;
+		BCMLOG_ERR("Invalid len:%d\n", len);
+	};
+
+	if (rc && (sts == BC_STS_SUCCESS))
+		sts = BC_STS_ERROR;
+
+	return sts;
+}
+
+/**
+ * crystalhd_pci_cfg_wr - PCIe config write
+ * @adp: Adapter instance
+ * @off: PCI config space offset.
+ * @len: Size -- Byte, Word & dword.
+ * @val: Value to be written
+ *
+ * Return:
+ *	Status.
+ *
+ * Set value to Link's PCIe config space.
+ */
+BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *adp, uint32_t off,
+			     uint32_t len, uint32_t val)
+{
+	BC_STATUS sts = BC_STS_SUCCESS;
+	int rc = 0;
+
+	if (!adp || !val) {
+		BCMLOG_ERR("Invalid arg \n");
+		return BC_STS_INV_ARG;
+	}
+
+	switch (len) {
+	case 1:
+		rc = pci_write_config_byte(adp->pdev, off, (u8)val);
+		break;
+	case 2:
+		rc = pci_write_config_word(adp->pdev, off, (u16)val);
+		break;
+	case 4:
+		rc = pci_write_config_dword(adp->pdev, off, val);
+		break;
+	default:
+		rc = -EINVAL;
+		sts = BC_STS_INV_ARG;
+		BCMLOG_ERR("Invalid len:%d\n", len);
+	};
+
+	if (rc && (sts == BC_STS_SUCCESS))
+		sts = BC_STS_ERROR;
+
+	return sts;
+}
+
+/**
+ * bc_kern_dma_alloc - Allocate memory for Dma rings
+ * @adp: Adapter instance
+ * @sz: Size of the memory to allocate.
+ * @phy_addr: Physical address of the memory allocated.
+ *	   Typedef to system's dma_addr_t (u64)
+ *
+ * Return:
+ *  Pointer to allocated memory..
+ *
+ * Wrapper to Linux kernel interface.
+ *
+ */
+void *bc_kern_dma_alloc(struct crystalhd_adp *adp, uint32_t sz,
+			dma_addr_t *phy_addr)
+{
+	void *temp = NULL;
+
+	if (!adp || !sz || !phy_addr) {
+		BCMLOG_ERR("Invalide Arg..\n");
+		return temp;
+	}
+
+	temp = pci_alloc_consistent(adp->pdev, sz, phy_addr);
+	if (temp)
+		memset(temp, 0, sz);
+
+	return temp;
+}
+
+/**
+ * bc_kern_dma_free - Release Dma ring memory.
+ * @adp: Adapter instance
+ * @sz: Size of the memory to allocate.
+ * @ka: Kernel virtual address returned during _dio_alloc()
+ * @phy_addr: Physical address of the memory allocated.
+ *	   Typedef to system's dma_addr_t (u64)
+ *
+ * Return:
+ *     none.
+ */
+void bc_kern_dma_free(struct crystalhd_adp *adp, uint32_t sz, void *ka,
+		      dma_addr_t phy_addr)
+{
+	if (!adp || !ka || !sz || !phy_addr) {
+		BCMLOG_ERR("Invalide Arg..\n");
+		return;
+	}
+
+	pci_free_consistent(adp->pdev, sz, ka, phy_addr);
+}
+
+/**
+ * crystalhd_create_dioq - Create Generic DIO queue
+ * @adp: Adapter instance
+ * @dioq_hnd: Handle to the dio queue created
+ * @cb	: Optional - Call back To free the element.
+ * @cbctx: Context to pass to callback.
+ *
+ * Return:
+ *  status
+ *
+ * Initialize Generic DIO queue to hold any data. Callback
+ * will be used to free elements while deleting the queue.
+ */
+BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *adp,
+			      crystalhd_dioq_t **dioq_hnd,
+			      crystalhd_data_free_cb cb, void *cbctx)
+{
+	crystalhd_dioq_t *dioq = NULL;
+
+	if (!adp || !dioq_hnd) {
+		BCMLOG_ERR("Invalid arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	dioq = kzalloc(sizeof(*dioq), GFP_KERNEL);
+	if (!dioq)
+		return BC_STS_INSUFF_RES;
+
+	spin_lock_init(&dioq->lock);
+	dioq->sig = BC_LINK_DIOQ_SIG;
+	dioq->head = (crystalhd_elem_t *)&dioq->head;
+	dioq->tail = (crystalhd_elem_t *)&dioq->head;
+	crystalhd_create_event(&dioq->event);
+	dioq->adp = adp;
+	dioq->data_rel_cb = cb;
+	dioq->cb_context = cbctx;
+	*dioq_hnd = dioq;
+
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_delete_dioq - Delete Generic DIO queue
+ * @adp: Adapter instance
+ * @dioq: DIOQ instance..
+ *
+ * Return:
+ *  None.
+ *
+ * Release Generic DIO queue. This function will remove
+ * all the entries from the Queue and will release data
+ * by calling the call back provided during creation.
+ *
+ */
+void crystalhd_delete_dioq(struct crystalhd_adp *adp, crystalhd_dioq_t *dioq)
+{
+	void *temp;
+
+	if (!dioq || (dioq->sig != BC_LINK_DIOQ_SIG))
+		return;
+
+	do {
+		temp = crystalhd_dioq_fetch(dioq);
+		if (temp && dioq->data_rel_cb)
+			dioq->data_rel_cb(dioq->cb_context, temp);
+	} while (temp);
+	dioq->sig = 0;
+	kfree(dioq);
+}
+
+/**
+ * crystalhd_dioq_add - Add new DIO request element.
+ * @ioq: DIO queue instance
+ * @t: DIO request to be added.
+ * @wake: True - Wake up suspended process.
+ * @tag: Special tag to assign - For search and get.
+ *
+ * Return:
+ *  Status.
+ *
+ * Insert new element to Q tail.
+ */
+BC_STATUS crystalhd_dioq_add(crystalhd_dioq_t *ioq, void *data,
+			   bool wake, uint32_t tag)
+{
+	unsigned long flags = 0;
+	crystalhd_elem_t *tmp;
+
+	if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !data) {
+		BCMLOG_ERR("Invalid arg!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	tmp = crystalhd_alloc_elem(ioq->adp);
+	if (!tmp) {
+		BCMLOG_ERR("No free elements.\n");
+		return BC_STS_INSUFF_RES;
+	}
+
+	tmp->data = data;
+	tmp->tag = tag;
+	spin_lock_irqsave(&ioq->lock, flags);
+	tmp->flink = (crystalhd_elem_t *)&ioq->head;
+	tmp->blink = ioq->tail;
+	tmp->flink->blink = tmp;
+	tmp->blink->flink = tmp;
+	ioq->count++;
+	spin_unlock_irqrestore(&ioq->lock, flags);
+
+	if (wake)
+		crystalhd_set_event(&ioq->event);
+
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_dioq_fetch - Fetch element from head.
+ * @ioq: DIO queue instance
+ *
+ * Return:
+ *	data element from the head..
+ *
+ * Remove an element from Queue.
+ */
+void *crystalhd_dioq_fetch(crystalhd_dioq_t *ioq)
+{
+	unsigned long flags = 0;
+	crystalhd_elem_t *tmp;
+	crystalhd_elem_t *ret = NULL;
+	void *data = NULL;
+
+	if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
+		BCMLOG_ERR("Invalid arg!!\n");
+		return data;
+	}
+
+	spin_lock_irqsave(&ioq->lock, flags);
+	tmp = ioq->head;
+	if (tmp != (crystalhd_elem_t *)&ioq->head) {
+		ret = tmp;
+		tmp->flink->blink = tmp->blink;
+		tmp->blink->flink = tmp->flink;
+		ioq->count--;
+	}
+	spin_unlock_irqrestore(&ioq->lock, flags);
+	if (ret) {
+		data = ret->data;
+		crystalhd_free_elem(ioq->adp, ret);
+	}
+
+	return data;
+}
+/**
+ * crystalhd_dioq_find_and_fetch - Search the tag and Fetch element
+ * @ioq: DIO queue instance
+ * @tag: Tag to search for.
+ *
+ * Return:
+ *	element from the head..
+ *
+ * Search TAG and remove the element.
+ */
+void *crystalhd_dioq_find_and_fetch(crystalhd_dioq_t *ioq, uint32_t tag)
+{
+	unsigned long flags = 0;
+	crystalhd_elem_t *tmp;
+	crystalhd_elem_t *ret = NULL;
+	void *data = NULL;
+
+	if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
+		BCMLOG_ERR("Invalid arg!!\n");
+		return data;
+	}
+
+	spin_lock_irqsave(&ioq->lock, flags);
+	tmp = ioq->head;
+	while (tmp != (crystalhd_elem_t *)&ioq->head) {
+		if (tmp->tag == tag) {
+			ret = tmp;
+			tmp->flink->blink = tmp->blink;
+			tmp->blink->flink = tmp->flink;
+			ioq->count--;
+			break;
+		}
+		tmp = tmp->flink;
+	}
+	spin_unlock_irqrestore(&ioq->lock, flags);
+
+	if (ret) {
+		data = ret->data;
+		crystalhd_free_elem(ioq->adp, ret);
+	}
+
+	return data;
+}
+
+/**
+ * crystalhd_dioq_fetch_wait - Fetch element from Head.
+ * @ioq: DIO queue instance
+ * @to_secs: Wait timeout in seconds..
+ *
+ * Return:
+ *	element from the head..
+ *
+ * Return element from head if Q is not empty. Wait for new element
+ * if Q is empty for Timeout seconds.
+ */
+void *crystalhd_dioq_fetch_wait(crystalhd_dioq_t *ioq, uint32_t to_secs,
+			      uint32_t *sig_pend)
+{
+	unsigned long flags = 0;
+	int rc = 0, count;
+	void *tmp = NULL;
+
+	if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !to_secs || !sig_pend) {
+		BCMLOG_ERR("Invalid arg!!\n");
+		return tmp;
+	}
+
+	count = to_secs;
+	spin_lock_irqsave(&ioq->lock, flags);
+	while ((ioq->count == 0) && count) {
+		spin_unlock_irqrestore(&ioq->lock, flags);
+
+		crystalhd_wait_on_event(&ioq->event, (ioq->count > 0), 1000, rc, 0);
+		if (rc == 0) {
+			goto out;
+		} else if (rc == -EINTR) {
+			BCMLOG(BCMLOG_INFO, "Cancelling fetch wait\n");
+			*sig_pend = 1;
+			return tmp;
+		}
+		spin_lock_irqsave(&ioq->lock, flags);
+		count--;
+	}
+	spin_unlock_irqrestore(&ioq->lock, flags);
+
+out:
+	return crystalhd_dioq_fetch(ioq);
+}
+
+/**
+ * crystalhd_map_dio - Map user address for DMA
+ * @adp:	Adapter instance
+ * @ubuff:	User buffer to map.
+ * @ubuff_sz:	User buffer size.
+ * @uv_offset:	UV buffer offset.
+ * @en_422mode: TRUE:422 FALSE:420 Capture mode.
+ * @dir_tx:	TRUE for Tx (To device from host)
+ * @dio_hnd:	Handle to mapped DIO request.
+ *
+ * Return:
+ *	Status.
+ *
+ * This routine maps user address and lock pages for DMA.
+ *
+ */
+BC_STATUS crystalhd_map_dio(struct crystalhd_adp *adp, void *ubuff,
+			  uint32_t ubuff_sz, uint32_t uv_offset,
+			  bool en_422mode, bool dir_tx,
+			  crystalhd_dio_req **dio_hnd)
+{
+	crystalhd_dio_req	*dio;
+	/* FIXME: jarod: should some of these unsigned longs be uint32_t or uintptr_t? */
+	unsigned long start = 0, end = 0, uaddr = 0, count = 0;
+	unsigned long spsz = 0, uv_start = 0;
+	int i = 0, rw = 0, res = 0, nr_pages = 0, skip_fb_sg = 0;
+
+	if (!adp || !ubuff || !ubuff_sz || !dio_hnd) {
+		BCMLOG_ERR("Invalid arg \n");
+		return BC_STS_INV_ARG;
+	}
+	/* Compute pages */
+	uaddr = (unsigned long)ubuff;
+	count = (unsigned long)ubuff_sz;
+	end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	start = uaddr >> PAGE_SHIFT;
+	nr_pages = end - start;
+
+	if (!count || ((uaddr + count) < uaddr)) {
+		BCMLOG_ERR("User addr overflow!!\n");
+		return BC_STS_INV_ARG;
+	}
+
+	dio = crystalhd_alloc_dio(adp);
+	if (!dio) {
+		BCMLOG_ERR("dio pool empty..\n");
+		return BC_STS_INSUFF_RES;
+	}
+
+	if (dir_tx) {
+		rw = WRITE;
+		dio->direction = DMA_TO_DEVICE;
+	} else {
+		rw = READ;
+		dio->direction = DMA_FROM_DEVICE;
+	}
+
+	if (nr_pages > dio->max_pages) {
+		BCMLOG_ERR("max_pages(%d) exceeded(%d)!!\n",
+			   dio->max_pages, nr_pages);
+		crystalhd_unmap_dio(adp, dio);
+		return BC_STS_INSUFF_RES;
+	}
+
+	if (uv_offset) {
+		uv_start = (uaddr + (unsigned long)uv_offset)  >> PAGE_SHIFT;
+		dio->uinfo.uv_sg_ix = uv_start - start;
+		dio->uinfo.uv_sg_off = ((uaddr + (unsigned long)uv_offset) & ~PAGE_MASK);
+	}
+
+	dio->fb_size = ubuff_sz & 0x03;
+	if (dio->fb_size) {
+		res = copy_from_user(dio->fb_va,
+				     (void *)(uaddr + count - dio->fb_size),
+				     dio->fb_size);
+		if (res) {
+			BCMLOG_ERR("failed %d to copy %u fill bytes from %p\n",
+				   res, dio->fb_size,
+				   (void *)(uaddr + count-dio->fb_size));
+			crystalhd_unmap_dio(adp, dio);
+			return BC_STS_INSUFF_RES;
+		}
+	}
+
+	down_read(&current->mm->mmap_sem);
+	res = get_user_pages(current, current->mm, uaddr, nr_pages, rw == READ,
+			     0, dio->pages, NULL);
+	up_read(&current->mm->mmap_sem);
+
+	/* Save for release..*/
+	dio->sig = crystalhd_dio_locked;
+	if (res < nr_pages) {
+		BCMLOG_ERR("get pages failed: %d-%d\n", nr_pages, res);
+		dio->page_cnt = res;
+		crystalhd_unmap_dio(adp, dio);
+		return BC_STS_ERROR;
+	}
+
+	dio->page_cnt = nr_pages;
+	/* Get scatter/gather */
+	crystalhd_init_sg(dio->sg, dio->page_cnt);
+	crystalhd_set_sg(&dio->sg[0], dio->pages[0], 0, uaddr & ~PAGE_MASK);
+	if (nr_pages > 1) {
+		dio->sg[0].length = PAGE_SIZE - dio->sg[0].offset;
+
+#ifdef CONFIG_X86_64
+		dio->sg[0].dma_length = dio->sg[0].length;
+#endif
+		count -= dio->sg[0].length;
+		for (i = 1; i < nr_pages; i++) {
+			if (count < 4) {
+				spsz = count;
+				skip_fb_sg = 1;
+			} else {
+				spsz = (count < PAGE_SIZE) ?
+					(count & ~0x03) : PAGE_SIZE;
+			}
+			crystalhd_set_sg(&dio->sg[i], dio->pages[i], spsz, 0);
+			count -= spsz;
+		}
+	} else {
+		if (count < 4) {
+			dio->sg[0].length = count;
+			skip_fb_sg = 1;
+		} else {
+			dio->sg[0].length = count - dio->fb_size;
+		}
+#ifdef CONFIG_X86_64
+		dio->sg[0].dma_length = dio->sg[0].length;
+#endif
+	}
+	dio->sg_cnt = pci_map_sg(adp->pdev, dio->sg,
+				 dio->page_cnt, dio->direction);
+	if (dio->sg_cnt <= 0) {
+		BCMLOG_ERR("sg map %d-%d \n", dio->sg_cnt, dio->page_cnt);
+		crystalhd_unmap_dio(adp, dio);
+		return BC_STS_ERROR;
+	}
+	if (dio->sg_cnt && skip_fb_sg)
+		dio->sg_cnt -= 1;
+	dio->sig = crystalhd_dio_sg_mapped;
+	/* Fill in User info.. */
+	dio->uinfo.xfr_len   = ubuff_sz;
+	dio->uinfo.xfr_buff  = ubuff;
+	dio->uinfo.uv_offset = uv_offset;
+	dio->uinfo.b422mode  = en_422mode;
+	dio->uinfo.dir_tx    = dir_tx;
+
+	*dio_hnd = dio;
+
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_unmap_sgl - Release mapped resources
+ * @adp: Adapter instance
+ * @dio: DIO request instance
+ *
+ * Return:
+ *	Status.
+ *
+ * This routine is to unmap the user buffer pages.
+ */
+BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *adp, crystalhd_dio_req *dio)
+{
+	struct page *page = NULL;
+	int j = 0;
+
+	if (!adp || !dio) {
+		BCMLOG_ERR("Invalid arg \n");
+		return BC_STS_INV_ARG;
+	}
+
+	if ((dio->page_cnt > 0) && (dio->sig != crystalhd_dio_inv)) {
+		for (j = 0; j < dio->page_cnt; j++) {
+			page = dio->pages[j];
+			if (page) {
+				if (!PageReserved(page) &&
+				    (dio->direction == DMA_FROM_DEVICE))
+					SetPageDirty(page);
+				page_cache_release(page);
+			}
+		}
+	}
+	if (dio->sig == crystalhd_dio_sg_mapped)
+		pci_unmap_sg(adp->pdev, dio->sg, dio->page_cnt, dio->direction);
+
+	crystalhd_free_dio(adp, dio);
+
+	return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_create_dio_pool - Allocate mem pool for DIO management.
+ * @adp: Adapter instance
+ * @max_pages: Max pages for size calculation.
+ *
+ * Return:
+ *	system error.
+ *
+ * This routine creates a memory pool to hold dio context for
+ * for HW Direct IO operation.
+ */
+int crystalhd_create_dio_pool(struct crystalhd_adp *adp, uint32_t max_pages)
+{
+	uint32_t asz = 0, i = 0;
+	uint8_t	*temp;
+	crystalhd_dio_req *dio;
+
+	if (!adp || !max_pages) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return -EINVAL;
+	}
+
+	/* Get dma memory for fill byte handling..*/
+	adp->fill_byte_pool = pci_pool_create("crystalhd_fbyte",
+					      adp->pdev, 8, 8, 0);
+	if (!adp->fill_byte_pool) {
+		BCMLOG_ERR("failed to create fill byte pool\n");
+		return -ENOMEM;
+	}
+
+	/* Get the max size from user based on 420/422 modes */
+	asz =  (sizeof(*dio->pages) * max_pages) +
+	       (sizeof(*dio->sg) * max_pages) + sizeof(*dio);
+
+	BCMLOG(BCMLOG_DBG, "Initializing Dio pool %d %d %x %p\n",
+	       BC_LINK_SG_POOL_SZ, max_pages, asz, adp->fill_byte_pool);
+
+	for (i = 0; i < BC_LINK_SG_POOL_SZ; i++) {
+		temp = (uint8_t *)kzalloc(asz, GFP_KERNEL);
+		if ((temp) == NULL) {
+			BCMLOG_ERR("Failed to alloc %d mem\n", asz);
+			return -ENOMEM;
+		}
+
+		dio = (crystalhd_dio_req *)temp;
+		temp += sizeof(*dio);
+		dio->pages = (struct page **)temp;
+		temp += (sizeof(*dio->pages) * max_pages);
+		dio->sg = (struct scatterlist *)temp;
+		dio->max_pages = max_pages;
+		dio->fb_va = pci_pool_alloc(adp->fill_byte_pool, GFP_KERNEL,
+					    &dio->fb_pa);
+		if (!dio->fb_va) {
+			BCMLOG_ERR("fill byte alloc failed.\n");
+			return -ENOMEM;
+		}
+
+		crystalhd_free_dio(adp, dio);
+	}
+
+	return 0;
+}
+
+/**
+ * crystalhd_destroy_dio_pool - Release DIO mem pool.
+ * @adp: Adapter instance
+ *
+ * Return:
+ *	none.
+ *
+ * This routine releases dio memory pool during close.
+ */
+void crystalhd_destroy_dio_pool(struct crystalhd_adp *adp)
+{
+	crystalhd_dio_req *dio;
+	int count = 0;
+
+	if (!adp) {
+		BCMLOG_ERR("Invalid Arg!!\n");
+		return;
+	}
+
+	do {
+		dio = crystalhd_alloc_dio(adp);
+		if (dio) {
+			if (dio->fb_va)
+				pci_pool_free(adp->fill_byte_pool,
+					      dio->fb_va, dio->fb_pa);
+			count++;
+			kfree(dio);
+		}
+	} while (dio);
+
+	if (adp->fill_byte_pool) {
+		pci_pool_destroy(adp->fill_byte_pool);
+		adp->fill_byte_pool = NULL;
+	}
+
+	BCMLOG(BCMLOG_DBG, "Released dio pool %d \n", count);
+}
+
+/**
+ * crystalhd_create_elem_pool - List element pool creation.
+ * @adp: Adapter instance
+ * @pool_size: Number of elements in the pool.
+ *
+ * Return:
+ *	0 - success, <0 error
+ *
+ * Create general purpose list element pool to hold pending,
+ * and active requests.
+ */
+int __devinit crystalhd_create_elem_pool(struct crystalhd_adp *adp,
+		uint32_t pool_size)
+{
+	uint32_t i;
+	crystalhd_elem_t *temp;
+
+	if (!adp || !pool_size)
+		return -EINVAL;
+
+	for (i = 0; i < pool_size; i++) {
+		temp = kzalloc(sizeof(*temp), GFP_KERNEL);
+		if (!temp) {
+			BCMLOG_ERR("kalloc failed \n");
+			return -ENOMEM;
+		}
+		crystalhd_free_elem(adp, temp);
+	}
+	BCMLOG(BCMLOG_DBG, "allocated %d elem\n", pool_size);
+	return 0;
+}
+
+/**
+ * crystalhd_delete_elem_pool - List element pool deletion.
+ * @adp: Adapter instance
+ *
+ * Return:
+ *	none
+ *
+ * Delete general purpose list element pool.
+ */
+void crystalhd_delete_elem_pool(struct crystalhd_adp *adp)
+{
+	crystalhd_elem_t *temp;
+	int dbg_cnt = 0;
+
+	if (!adp)
+		return;
+
+	do {
+		temp = crystalhd_alloc_elem(adp);
+		if (temp) {
+			kfree(temp);
+			dbg_cnt++;
+		}
+	} while (temp);
+
+	BCMLOG(BCMLOG_DBG, "released %d elem\n", dbg_cnt);
+}
+
+/*================ Debug support routines.. ================================*/
+void crystalhd_show_buffer(uint32_t off, uint8_t *buff, uint32_t dwcount)
+{
+	uint32_t i, k = 1;
+
+	for (i = 0; i < dwcount; i++) {
+		if (k == 1)
+			BCMLOG(BCMLOG_DATA, "0x%08X : ", off);
+
+		BCMLOG(BCMLOG_DATA, " 0x%08X ", *((uint32_t *)buff));
+
+		buff += sizeof(uint32_t);
+		off  += sizeof(uint32_t);
+		k++;
+		if ((i == dwcount - 1) || (k > 4)) {
+			BCMLOG(BCMLOG_DATA, "\n");
+			k = 1;
+		}
+	}
+}
diff --git a/drivers/staging/crystalhd/crystalhd_misc.h b/drivers/staging/crystalhd/crystalhd_misc.h
new file mode 100644
index 0000000..a2aa6ad
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_misc.h
@@ -0,0 +1,229 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ *  Name: crystalhd_misc . h
+ *
+ *  Description:
+ *		BCM70012 Linux driver general purpose routines.
+ *		Includes reg/mem read and write routines.
+ *
+ *  HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * This driver is free software; 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 driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this driver.  If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#ifndef _CRYSTALHD_MISC_H_
+#define _CRYSTALHD_MISC_H_
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ioctl.h>
+#include <linux/dma-mapping.h>
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <asm/system.h>
+#include "bc_dts_glob_lnx.h"
+
+/* Global log level variable defined in crystal_misc.c file */
+extern uint32_t g_linklog_level;
+
+/* Global element pool for all Queue management.
+ * TX: Active = BC_TX_LIST_CNT, Free = BC_TX_LIST_CNT.
+ * RX: Free = BC_RX_LIST_CNT, Active = 2
+ * FW-CMD: 4
+ */
+#define	BC_LINK_ELEM_POOL_SZ	((BC_TX_LIST_CNT * 2) + BC_RX_LIST_CNT + 2 + 4)
+
+/* Driver's IODATA pool count */
+#define	CHD_IODATA_POOL_SZ    (BC_IOCTL_DATA_POOL_SIZE * BC_LINK_MAX_OPENS)
+
+/* Scatter Gather memory pool size for Tx and Rx */
+#define BC_LINK_SG_POOL_SZ    (BC_TX_LIST_CNT + BC_RX_LIST_CNT)
+
+enum _crystalhd_dio_sig {
+	crystalhd_dio_inv = 0,
+	crystalhd_dio_locked,
+	crystalhd_dio_sg_mapped,
+};
+
+struct crystalhd_dio_user_info {
+	void			*xfr_buff;
+	uint32_t		xfr_len;
+	uint32_t		uv_offset;
+	bool			dir_tx;
+
+	uint32_t		uv_sg_ix;
+	uint32_t		uv_sg_off;
+	int			comp_sts;
+	int			ev_sts;
+	uint32_t		y_done_sz;
+	uint32_t		uv_done_sz;
+	uint32_t		comp_flags;
+	bool			b422mode;
+};
+
+typedef struct _crystalhd_dio_req {
+	uint32_t			sig;
+	uint32_t			max_pages;
+	struct page			**pages;
+	struct scatterlist		*sg;
+	int				sg_cnt;
+	int				page_cnt;
+	int				direction;
+	struct crystalhd_dio_user_info	uinfo;
+	void				*fb_va;
+	uint32_t			fb_size;
+	dma_addr_t			fb_pa;
+	struct _crystalhd_dio_req		*next;
+} crystalhd_dio_req;
+
+#define BC_LINK_DIOQ_SIG	(0x09223280)
+
+typedef struct _crystalhd_elem_s {
+	struct _crystalhd_elem_s	*flink;
+	struct _crystalhd_elem_s	*blink;
+	void			*data;
+	uint32_t		tag;
+} crystalhd_elem_t;
+
+typedef void (*crystalhd_data_free_cb)(void *context, void *data);
+
+typedef struct _crystalhd_dioq_s {
+	uint32_t		sig;
+	struct crystalhd_adp	*adp;
+	crystalhd_elem_t		*head;
+	crystalhd_elem_t		*tail;
+	uint32_t		count;
+	spinlock_t		lock;
+	wait_queue_head_t	event;
+	crystalhd_data_free_cb	data_rel_cb;
+	void			*cb_context;
+} crystalhd_dioq_t;
+
+typedef void (*hw_comp_callback)(crystalhd_dio_req *,
+				 wait_queue_head_t *event, BC_STATUS sts);
+
+/*========= Decoder (7412) register access routines.================= */
+uint32_t bc_dec_reg_rd(struct crystalhd_adp *, uint32_t);
+void bc_dec_reg_wr(struct crystalhd_adp *, uint32_t, uint32_t);
+
+/*========= Link (70012) register access routines.. =================*/
+uint32_t crystalhd_reg_rd(struct crystalhd_adp *, uint32_t);
+void crystalhd_reg_wr(struct crystalhd_adp *, uint32_t, uint32_t);
+
+/*========= Decoder (7412) memory access routines..=================*/
+BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t *);
+BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t *);
+
+/*==========Link (70012) PCIe Config access routines.================*/
+BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t *);
+BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t);
+
+/*========= Linux Kernel Interface routines. ======================= */
+void *bc_kern_dma_alloc(struct crystalhd_adp *, uint32_t, dma_addr_t *);
+void bc_kern_dma_free(struct crystalhd_adp *, uint32_t,
+		      void *, dma_addr_t);
+#define crystalhd_create_event(_ev)	init_waitqueue_head(_ev)
+#define crystalhd_set_event(_ev)		wake_up_interruptible(_ev)
+#define crystalhd_wait_on_event(ev, condition, timeout, ret, nosig)	\
+do {									\
+	DECLARE_WAITQUEUE(entry, current);				\
+	unsigned long end = jiffies + ((timeout * HZ) / 1000);		\
+		ret = 0;						\
+	add_wait_queue(ev, &entry);					\
+	for (;;) {							\
+		__set_current_state(TASK_INTERRUPTIBLE);		\
+		if (condition) {					\
+			break;						\
+		}							\
+		if (time_after_eq(jiffies, end)) {			\
+			ret = -EBUSY;					\
+			break;						\
+		}							\
+		schedule_timeout((HZ / 100 > 1) ? HZ / 100 : 1);	\
+		if (!nosig && signal_pending(current)) {		\
+			ret = -EINTR;					\
+			break;						\
+		}							\
+	}								\
+	__set_current_state(TASK_RUNNING);				\
+	remove_wait_queue(ev, &entry);					\
+} while (0)
+
+/*================ Direct IO mapping routines ==================*/
+extern int crystalhd_create_dio_pool(struct crystalhd_adp *, uint32_t);
+extern void crystalhd_destroy_dio_pool(struct crystalhd_adp *);
+extern BC_STATUS crystalhd_map_dio(struct crystalhd_adp *, void *, uint32_t,
+				   uint32_t, bool, bool, crystalhd_dio_req**);
+
+extern BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *, crystalhd_dio_req*);
+#define crystalhd_get_sgle_paddr(_dio, _ix) (cpu_to_le64(sg_dma_address(&_dio->sg[_ix])))
+#define crystalhd_get_sgle_len(_dio, _ix) (cpu_to_le32(sg_dma_len(&_dio->sg[_ix])))
+
+/*================ General Purpose Queues ==================*/
+extern BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *, crystalhd_dioq_t **, crystalhd_data_free_cb , void *);
+extern void crystalhd_delete_dioq(struct crystalhd_adp *, crystalhd_dioq_t *);
+extern BC_STATUS crystalhd_dioq_add(crystalhd_dioq_t *ioq, void *data, bool wake, uint32_t tag);
+extern void *crystalhd_dioq_fetch(crystalhd_dioq_t *ioq);
+extern void *crystalhd_dioq_find_and_fetch(crystalhd_dioq_t *ioq, uint32_t tag);
+extern void *crystalhd_dioq_fetch_wait(crystalhd_dioq_t *ioq, uint32_t to_secs, uint32_t *sig_pend);
+
+#define crystalhd_dioq_count(_ioq)	((_ioq) ? _ioq->count : 0)
+
+extern int crystalhd_create_elem_pool(struct crystalhd_adp *, uint32_t);
+extern void crystalhd_delete_elem_pool(struct crystalhd_adp *);
+
+
+/*================ Debug routines/macros .. ================================*/
+extern void crystalhd_show_buffer(uint32_t off, uint8_t *buff, uint32_t dwcount);
+
+enum _chd_log_levels {
+	BCMLOG_ERROR		= 0x80000000,	/* Don't disable this option */
+	BCMLOG_DATA		= 0x40000000,	/* Data, enable by default */
+	BCMLOG_SPINLOCK		= 0x20000000,	/* Spcial case for Spin locks*/
+
+	/* Following are allowed only in debug mode */
+	BCMLOG_INFO		= 0x00000001,	/* Generic informational */
+	BCMLOG_DBG		= 0x00000002,	/* First level Debug info */
+	BCMLOG_SSTEP		= 0x00000004,	/* Stepping information */
+	BCMLOG_ENTER_LEAVE	= 0x00000008,	/* stack tracking */
+};
+
+#define BCMLOG_ENTER				\
+if (g_linklog_level & BCMLOG_ENTER_LEAVE) {	\
+	printk("Entered %s\n", __func__);	\
+}
+
+#define BCMLOG_LEAVE				\
+if (g_linklog_level & BCMLOG_ENTER_LEAVE) {	\
+	printk("Leaving %s\n", __func__);	\
+}
+
+#define BCMLOG(trace, fmt, args...)		\
+if (g_linklog_level & trace) {			\
+	printk(fmt, ##args);			\
+}
+
+#define BCMLOG_ERR(fmt, args...)					\
+do {									\
+	if (g_linklog_level & BCMLOG_ERROR) {				\
+		printk("*ERR*:%s:%d: "fmt, __FILE__, __LINE__, ##args);	\
+	}								\
+} while (0);
+
+#endif
diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c
index 89c8fe2..46c7f78 100644
--- a/drivers/staging/cx25821/cx25821-audups11.c
+++ b/drivers/staging/cx25821/cx25821-audups11.c
@@ -343,10 +343,11 @@
 			 struct v4l2_control *ctl)
 {
 	struct cx25821_fh *fh = priv;
-	struct cx25821_dev *dev = fh->dev;
+	struct cx25821_dev *dev;
 	int err;
 
 	if (fh) {
+		dev = fh->dev;
 		err = v4l2_prio_check(&dev->prio, &fh->prio);
 		if (0 != err)
 			return err;
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c
index 1eb079b..d601620 100644
--- a/drivers/staging/cx25821/cx25821-medusa-video.c
+++ b/drivers/staging/cx25821/cx25821-medusa-video.c
@@ -795,10 +795,8 @@
 	value &= 0xFFFFFFDF;
 	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
 
-	if (ret_val < 0) {
-		mutex_unlock(&dev->lock);
+	if (ret_val < 0)
 		return -EINVAL;
-	}
 
 	mutex_unlock(&dev->lock);
 
diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c
index c7c14c7..8cd3986 100644
--- a/drivers/staging/cx25821/cx25821-video.c
+++ b/drivers/staging/cx25821/cx25821-video.c
@@ -876,7 +876,7 @@
 	dprintk(1, "%s()\n", __func__);
 
 	n = i->index;
-	if (n > 2)
+	if (n >= 2)
 		return -EINVAL;
 
 	if (0 == INPUT(n)->type)
@@ -963,10 +963,11 @@
 int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f)
 {
 	struct cx25821_fh *fh = priv;
-	struct cx25821_dev *dev = fh->dev;
+	struct cx25821_dev *dev;
 	int err;
 
 	if (fh) {
+		dev = fh->dev;
 		err = v4l2_prio_check(&dev->prio, &fh->prio);
 		if (0 != err)
 			return err;
diff --git a/drivers/staging/dream/camera/Kconfig b/drivers/staging/dream/camera/Kconfig
index 0a3e903..bfb6d24 100644
--- a/drivers/staging/dream/camera/Kconfig
+++ b/drivers/staging/dream/camera/Kconfig
@@ -15,7 +15,7 @@
 
 config MSM_CAMERA_FLASH
 	bool "Qualcomm MSM camera flash support"
-	depends on MSM_CAMERA
+	depends on MSM_CAMERA && BROKEN
 	---help---
 	  Enable support for LED flash for msm camera
 
diff --git a/drivers/staging/dream/camera/Makefile b/drivers/staging/dream/camera/Makefile
index 4429ae5..db228d7 100644
--- a/drivers/staging/dream/camera/Makefile
+++ b/drivers/staging/dream/camera/Makefile
@@ -1,3 +1,4 @@
+EXTRA_CFLAGS=-Idrivers/staging/dream/include
 obj-$(CONFIG_MT9T013) += mt9t013.o mt9t013_reg.o
 obj-$(CONFIG_MT9D112) += mt9d112.o mt9d112_reg.o
 obj-$(CONFIG_MT9P012) += mt9p012_fox.o mt9p012_reg.o
diff --git a/drivers/staging/dream/camera/msm_camera.c b/drivers/staging/dream/camera/msm_camera.c
index 7d93877..dc7c603 100644
--- a/drivers/staging/dream/camera/msm_camera.c
+++ b/drivers/staging/dream/camera/msm_camera.c
@@ -2,7 +2,7 @@
  * Copyright (C) 2008-2009 QUALCOMM Incorporated.
  */
 
-//FIXME: most allocations need not be GFP_ATOMIC
+/* FIXME: most allocations need not be GFP_ATOMIC */
 /* FIXME: management of mutexes */
 /* FIXME: msm_pmem_region_lookup return values */
 /* FIXME: way too many copy to/from user */
@@ -76,14 +76,14 @@
 		list_del_init(&qcmd->list);			\
 		kfree(qcmd);					\
 	};							\
-} while(0)
+} while (0)
 
 #define MSM_DRAIN_QUEUE(sync, name) do {			\
 	unsigned long flags;					\
 	spin_lock_irqsave(&(sync)->name##_lock, flags);		\
 	MSM_DRAIN_QUEUE_NOSYNC(sync, name);			\
 	spin_unlock_irqrestore(&(sync)->name##_lock, flags);	\
-} while(0)
+} while (0)
 
 static int check_overlap(struct hlist_head *ptype,
 			unsigned long paddr,
@@ -361,7 +361,7 @@
 	if (!frame->buffer) {
 		pr_err("%s: cannot get frame, invalid lookup address "
 			"y=%x cbcr=%x offset=%d\n",
-			__FUNCTION__,
+			__func__,
 			pphy->y_phy,
 			pphy->cbcr_phy,
 			frame->y_off);
@@ -455,7 +455,7 @@
 	return rc;
 }
 
-static struct msm_queue_cmd* __msm_control(struct msm_sync *sync,
+static struct msm_queue_cmd *__msm_control(struct msm_sync *sync,
 		struct msm_control_device_queue *queue,
 		struct msm_queue_cmd *qcmd,
 		int timeout)
@@ -592,8 +592,7 @@
 	 * a result of a successful completion, we are freeing the qcmd that
 	 * we dequeued from queue->ctrl_status_q.
 	 */
-	if (qcmd)
-		kfree(qcmd);
+	kfree(qcmd);
 
 	CDBG("msm_control: end rc = %d\n", rc);
 	return rc;
@@ -670,7 +669,7 @@
 					&(stats.fd));
 			if (!stats.buffer) {
 				pr_err("%s: msm_pmem_stats_ptov_lookup error\n",
-					__FUNCTION__);
+					__func__);
 				rc = -EINVAL;
 				goto failure;
 			}
@@ -718,8 +717,7 @@
 					buf.fmain.buffer =
 						(unsigned long)region.vaddr;
 					buf.fmain.fd = region.fd;
-				}
-				else {
+				} else {
 					pr_err("%s: pmem lookup failed\n",
 						__func__);
 					rc = -EINVAL;
@@ -796,8 +794,7 @@
 	}
 
 failure:
-	if (qcmd)
-		kfree(qcmd);
+	kfree(qcmd);
 
 	CDBG("msm_get_stats: %d\n", rc);
 	return rc;
@@ -838,8 +835,8 @@
 			kfree(qcmd);
 			goto end;
 		}
-	}
-	else ctrlcmd->value = NULL;
+	} else
+		ctrlcmd->value = NULL;
 
 end:
 	CDBG("msm_ctrl_cmd_done: end rc = %d\n", rc);
@@ -869,14 +866,14 @@
 		return -EFAULT;
 	}
 
-	switch(cfgcmd.cmd_type) {
+	switch (cfgcmd.cmd_type) {
 	case CMD_STATS_ENABLE:
 		axi_data.bufnum1 =
 			msm_pmem_region_lookup(&sync->stats,
 					MSM_PMEM_AEC_AWB, &region[0],
 					NUM_WB_EXP_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
-			pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+			pr_err("%s: pmem region lookup error\n", __func__);
 			return -EINVAL;
 		}
 		axi_data.region = &region[0];
@@ -888,7 +885,7 @@
 					MSM_PMEM_AF, &region[0],
 					NUM_AF_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
-			pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+			pr_err("%s: pmem region lookup error\n", __func__);
 			return -EINVAL;
 		}
 		axi_data.region = &region[0];
@@ -899,7 +896,7 @@
 		break;
 	default:
 		pr_err("%s: unknown command type %d\n",
-			__FUNCTION__, cfgcmd.cmd_type);
+			__func__, cfgcmd.cmd_type);
 		return -EINVAL;
 	}
 
@@ -928,7 +925,7 @@
 			msm_pmem_region_lookup(&sync->frame, pmem_type,
 				&region[0], 8);
 		if (!axi_data.bufnum1) {
-			pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+			pr_err("%s: pmem region lookup error\n", __func__);
 			return -EINVAL;
 		}
 		break;
@@ -939,7 +936,7 @@
 			msm_pmem_region_lookup(&sync->frame, pmem_type,
 				&region[0], 8);
 		if (!axi_data.bufnum2) {
-			pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+			pr_err("%s: pmem region lookup error\n", __func__);
 			return -EINVAL;
 		}
 		break;
@@ -950,7 +947,7 @@
 			msm_pmem_region_lookup(&sync->frame, pmem_type,
 				&region[0], 8);
 		if (!axi_data.bufnum1) {
-			pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+			pr_err("%s: pmem region lookup error\n", __func__);
 			return -EINVAL;
 		}
 
@@ -959,7 +956,7 @@
 			msm_pmem_region_lookup(&sync->frame, pmem_type,
 				&region[axi_data.bufnum1], 8);
 		if (!axi_data.bufnum2) {
-			pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+			pr_err("%s: pmem region lookup error\n", __func__);
 			return -EINVAL;
 		}
 		break;
@@ -970,7 +967,7 @@
 			msm_pmem_region_lookup(&sync->frame, pmem_type,
 				&region[0], 8);
 		if (!axi_data.bufnum2) {
-			pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+			pr_err("%s: pmem region lookup error\n", __func__);
 			return -EINVAL;
 		}
 		break;
@@ -981,7 +978,7 @@
 
 	default:
 		pr_err("%s: unknown command type %d\n",
-			__FUNCTION__, cfgcmd->cmd_type);
+			__func__, cfgcmd->cmd_type);
 		return -EINVAL;
 	}
 
@@ -1047,7 +1044,7 @@
 			rc = sync->vfefn.vfe_config(&cfgcmd, &pphy);
 	} else {
 		pr_err("%s: msm_pmem_frame_vtop_lookup failed\n",
-			__FUNCTION__);
+			__func__);
 		rc = -EINVAL;
 	}
 
@@ -1131,7 +1128,7 @@
 		break;
 	default:
 		pr_err("%s: unknown command type %d\n",
-			__FUNCTION__, cfgcmd->cmd_type);
+			__func__, cfgcmd->cmd_type);
 		return -EINVAL;
 	}
 
@@ -1140,7 +1137,7 @@
 			msm_pmem_region_lookup(&sync->stats, pmem_type,
 				&region[0], NUM_WB_EXP_STAT_OUTPUT_BUFFERS);
 		if (!axi_data.bufnum1) {
-			pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+			pr_err("%s: pmem region lookup error\n", __func__);
 			return -EINVAL;
 		}
 		axi_data.region = &region[0];
@@ -1177,7 +1174,7 @@
 			cfgcmd.cmd_type = CMD_STATS_AF_BUF_RELEASE;
 		else {
 			pr_err("%s: invalid buf type %d\n",
-				__FUNCTION__,
+				__func__,
 				buf.type);
 			rc = -EINVAL;
 			goto put_done;
@@ -1223,7 +1220,7 @@
 
 	default:
 		pr_err("%s: unknown command type %d\n",
-			__FUNCTION__,
+			__func__,
 			cfgcmd.cmd_type);
 		return -EINVAL;
 	}
@@ -1622,7 +1619,8 @@
 	int rc;
 	struct msm_control_device *ctrl_pmsm = filep->private_data;
 	struct msm_device *pmsm = ctrl_pmsm->pmsm;
-	printk("msm_camera: RELEASE %s\n", filep->f_path.dentry->d_name.name);
+	printk(KERN_INFO "msm_camera: RELEASE %s\n",
+					filep->f_path.dentry->d_name.name);
 	rc = __msm_release(pmsm->sync);
 	if (!rc) {
 		MSM_DRAIN_QUEUE(&ctrl_pmsm->ctrl_q, ctrl_status_q);
@@ -1636,7 +1634,8 @@
 {
 	int rc;
 	struct msm_device *pmsm = filep->private_data;
-	printk("msm_camera: RELEASE %s\n", filep->f_path.dentry->d_name.name);
+	printk(KERN_INFO "msm_camera: RELEASE %s\n",
+					filep->f_path.dentry->d_name.name);
 	rc = __msm_release(pmsm->sync);
 	if (!rc) {
 		MSM_DRAIN_QUEUE(pmsm->sync, prev_frame_q);
@@ -1720,7 +1719,7 @@
 	qcmd->type = qtype;
 
 	if (qtype == MSM_CAM_Q_VFE_MSG) {
-		switch(vdata->type) {
+		switch (vdata->type) {
 		case VFE_MSG_OUTPUT1:
 		case VFE_MSG_OUTPUT2:
 			qcmd_frame =
@@ -1885,8 +1884,10 @@
 		return -ENOMEM;
 
 	rc = msm_open_common(inode, filep, 0);
-	if (rc < 0)
+	if (rc < 0) {
+		kfree(ctrl_pmsm);
 		return rc;
+	}
 
 	ctrl_pmsm->pmsm = filep->private_data;
 	filep->private_data = ctrl_pmsm;
@@ -1929,7 +1930,7 @@
 	memcpy(out->value, ctrl->value, ctrl->length);
 
 end:
-	if (rcmd) kfree(rcmd);
+	kfree(rcmd);
 	CDBG("__msm_v4l2_control: end rc = %d\n", rc);
 	return rc;
 }
diff --git a/drivers/staging/dream/camera/msm_vfe7x.c b/drivers/staging/dream/camera/msm_vfe7x.c
index 33ab3ac..62fd24d 100644
--- a/drivers/staging/dream/camera/msm_vfe7x.c
+++ b/drivers/staging/dream/camera/msm_vfe7x.c
@@ -255,8 +255,7 @@
 
 	extlen = sizeof(struct vfe_frame_extra);
 
-	extdata =
-		kmalloc(sizeof(extlen), GFP_ATOMIC);
+	extdata = kmalloc(extlen, GFP_ATOMIC);
 	if (!extdata) {
 		rc = -ENOMEM;
 		goto init_fail;
diff --git a/drivers/staging/dream/camera/s5k3e2fx.c b/drivers/staging/dream/camera/s5k3e2fx.c
index edba198..841792e 100644
--- a/drivers/staging/dream/camera/s5k3e2fx.c
+++ b/drivers/staging/dream/camera/s5k3e2fx.c
@@ -743,12 +743,12 @@
 	}
 
 	/* initialize AF */
-	if ((rc = s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr,
-			0x3146, 0x3A)) < 0)
+	rc = s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr, 0x3146, 0x3A);
+	if (rc < 0)
 		goto init_fail1;
 
-	if ((rc = s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr,
-			0x3130, 0x03)) < 0)
+	rc = s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr, 0x3130, 0x03);
+	if (rc < 0)
 		goto init_fail1;
 
 	goto init_done;
@@ -814,20 +814,20 @@
 
 static uint16_t s5k3e2fx_get_prev_pixels_pl(void)
 {
-	return (s5k3e2fx_reg_pat[S_RES_PREVIEW].size_w +
-		s5k3e2fx_reg_pat[S_RES_PREVIEW].blk_p);
+	return s5k3e2fx_reg_pat[S_RES_PREVIEW].size_w +
+		s5k3e2fx_reg_pat[S_RES_PREVIEW].blk_p;
 }
 
 static uint16_t s5k3e2fx_get_pict_lines_pf(void)
 {
-	return (s5k3e2fx_reg_pat[S_RES_CAPTURE].size_h +
-		s5k3e2fx_reg_pat[S_RES_CAPTURE].blk_l);
+	return s5k3e2fx_reg_pat[S_RES_CAPTURE].size_h +
+		s5k3e2fx_reg_pat[S_RES_CAPTURE].blk_l;
 }
 
 static uint16_t s5k3e2fx_get_pict_pixels_pl(void)
 {
-	return (s5k3e2fx_reg_pat[S_RES_CAPTURE].size_w +
-		s5k3e2fx_reg_pat[S_RES_CAPTURE].blk_p);
+	return s5k3e2fx_reg_pat[S_RES_CAPTURE].size_w +
+		s5k3e2fx_reg_pat[S_RES_CAPTURE].blk_p;
 }
 
 static uint32_t s5k3e2fx_get_pict_max_exp_lc(void)
@@ -1093,14 +1093,10 @@
 
 	actual_step = step_direction * (int16_t)num_steps;
 	pos_offset = init_code + s5k3e2fx_ctrl->curr_lens_pos;
-	gain = actual_step * 0x400 / 5;
+	gain = ((actual_step << 10) / 5) >> 10;
 
-	for (i = 0; i <= 4; i++) {
-		if (actual_step >= 0)
-			s_move[i] = ((((i+1)*gain+0x200) - (i*gain+0x200))/0x400);
-		else
-			s_move[i] = ((((i+1)*gain-0x200) - (i*gain-0x200))/0x400);
-	}
+	for (i = 0; i <= 4; i++)
+		s_move[i] = gain;
 
 	/* Ring Damping Code */
 	for (i = 0; i <= 4; i++) {
diff --git a/drivers/staging/dream/include/linux/android_pmem.h b/drivers/staging/dream/include/linux/android_pmem.h
new file mode 100644
index 0000000..2fc05d7
--- /dev/null
+++ b/drivers/staging/dream/include/linux/android_pmem.h
@@ -0,0 +1,80 @@
+/* drivers/staging/dream/include/linux/android_pmem.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ANDROID_PMEM_H_
+#define _ANDROID_PMEM_H_
+
+#define PMEM_IOCTL_MAGIC 'p'
+#define PMEM_GET_PHYS		_IOW(PMEM_IOCTL_MAGIC, 1, unsigned int)
+#define PMEM_MAP		_IOW(PMEM_IOCTL_MAGIC, 2, unsigned int)
+#define PMEM_GET_SIZE		_IOW(PMEM_IOCTL_MAGIC, 3, unsigned int)
+#define PMEM_UNMAP		_IOW(PMEM_IOCTL_MAGIC, 4, unsigned int)
+/* This ioctl will allocate pmem space, backing the file, it will fail
+ * if the file already has an allocation, pass it the len as the argument
+ * to the ioctl */
+#define PMEM_ALLOCATE		_IOW(PMEM_IOCTL_MAGIC, 5, unsigned int)
+/* This will connect a one pmem file to another, pass the file that is already
+ * backed in memory as the argument to the ioctl
+ */
+#define PMEM_CONNECT		_IOW(PMEM_IOCTL_MAGIC, 6, unsigned int)
+/* Returns the total size of the pmem region it is sent to as a pmem_region
+ * struct (with offset set to 0).
+ */
+#define PMEM_GET_TOTAL_SIZE	_IOW(PMEM_IOCTL_MAGIC, 7, unsigned int)
+/* Revokes gpu registers and resets the gpu.  Pass a pointer to the
+ * start of the mapped gpu regs (the vaddr returned by mmap) as the argument.
+ */
+#define HW3D_REVOKE_GPU		_IOW(PMEM_IOCTL_MAGIC, 8, unsigned int)
+#define HW3D_GRANT_GPU		_IOW(PMEM_IOCTL_MAGIC, 9, unsigned int)
+#define HW3D_WAIT_FOR_INTERRUPT	_IOW(PMEM_IOCTL_MAGIC, 10, unsigned int)
+
+int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
+		  unsigned long *end, struct file **filp);
+int get_pmem_user_addr(struct file *file, unsigned long *start,
+		       unsigned long *end);
+void put_pmem_file(struct file* file);
+void flush_pmem_file(struct file *file, unsigned long start, unsigned long len);
+
+struct android_pmem_platform_data
+{
+	const char* name;
+	/* starting physical address of memory region */
+	unsigned long start;
+	/* size of memory region */
+	unsigned long size;
+	/* set to indicate the region should not be managed with an allocator */
+	unsigned no_allocator;
+	/* set to indicate maps of this region should be cached, if a mix of
+	 * cached and uncached is desired, set this and open the device with
+	 * O_SYNC to get an uncached region */
+	unsigned cached;
+	/* The MSM7k has bits to enable a write buffer in the bus controller*/
+	unsigned buffered;
+};
+
+struct pmem_region {
+	unsigned long offset;
+	unsigned long len;
+};
+
+int pmem_setup(struct android_pmem_platform_data *pdata,
+	       long (*ioctl)(struct file *, unsigned int, unsigned long),
+	       int (*release)(struct inode *, struct file *));
+
+int pmem_remap(struct pmem_region *region, struct file *file,
+	       unsigned operation);
+
+#endif //_ANDROID_PPP_H_
+
diff --git a/drivers/staging/dream/include/linux/gpio_event.h b/drivers/staging/dream/include/linux/gpio_event.h
new file mode 100644
index 0000000..ffc5da3
--- /dev/null
+++ b/drivers/staging/dream/include/linux/gpio_event.h
@@ -0,0 +1,154 @@
+/* drivers/staging/dream/include/linux/gpio_event.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_GPIO_EVENT_H
+#define _LINUX_GPIO_EVENT_H
+
+#include <linux/input.h>
+
+enum {
+	GPIO_EVENT_FUNC_UNINIT  = 0x0,
+	GPIO_EVENT_FUNC_INIT    = 0x1,
+	GPIO_EVENT_FUNC_SUSPEND = 0x2,
+	GPIO_EVENT_FUNC_RESUME  = 0x3,
+};
+struct gpio_event_info {
+	int (*func)(struct input_dev *input_dev,
+		    struct gpio_event_info *info,
+		    void **data, int func);
+	int (*event)(struct input_dev *input_dev,
+		     struct gpio_event_info *info,
+		     void **data, unsigned int type,
+		     unsigned int code, int value); /* out events */
+};
+
+struct gpio_event_platform_data {
+	const char *name;
+	struct gpio_event_info **info;
+	size_t info_count;
+	int (*power)(const struct gpio_event_platform_data *pdata, bool on);
+};
+
+#define GPIO_EVENT_DEV_NAME "gpio-event"
+
+/* Key matrix */
+
+enum gpio_event_matrix_flags {
+	/* unset: drive active output low, set: drive active output high */
+	GPIOKPF_ACTIVE_HIGH              = 1U << 0,
+	GPIOKPF_DEBOUNCE                 = 1U << 1,
+	GPIOKPF_REMOVE_SOME_PHANTOM_KEYS = 1U << 2,
+	GPIOKPF_REMOVE_PHANTOM_KEYS      = GPIOKPF_REMOVE_SOME_PHANTOM_KEYS |
+					   GPIOKPF_DEBOUNCE,
+	GPIOKPF_DRIVE_INACTIVE           = 1U << 3,
+	GPIOKPF_LEVEL_TRIGGERED_IRQ      = 1U << 4,
+	GPIOKPF_PRINT_UNMAPPED_KEYS      = 1U << 16,
+	GPIOKPF_PRINT_MAPPED_KEYS        = 1U << 17,
+	GPIOKPF_PRINT_PHANTOM_KEYS       = 1U << 18,
+};
+
+extern int gpio_event_matrix_func(struct input_dev *input_dev,
+			struct gpio_event_info *info, void **data, int func);
+struct gpio_event_matrix_info {
+	/* initialize to gpio_event_matrix_func */
+	struct gpio_event_info info;
+	/* size must be ninputs * noutputs */
+	const unsigned short *keymap;
+	unsigned int *input_gpios;
+	unsigned int *output_gpios;
+	unsigned int ninputs;
+	unsigned int noutputs;
+	/* time to wait before reading inputs after driving each output */
+	ktime_t settle_time;
+	/* time to wait before scanning the keypad a second time */
+	ktime_t debounce_delay;
+	ktime_t poll_time;
+	unsigned flags;
+};
+
+/* Directly connected inputs and outputs */
+
+enum gpio_event_direct_flags {
+	GPIOEDF_ACTIVE_HIGH         = 1U << 0,
+/*	GPIOEDF_USE_DOWN_IRQ        = 1U << 1, */
+/*	GPIOEDF_USE_IRQ             = (1U << 2) | GPIOIDF_USE_DOWN_IRQ, */
+	GPIOEDF_PRINT_KEYS          = 1U << 8,
+	GPIOEDF_PRINT_KEY_DEBOUNCE  = 1U << 9,
+};
+
+struct gpio_event_direct_entry {
+	uint32_t gpio:23;
+	uint32_t code:9;
+};
+
+/* inputs */
+extern int gpio_event_input_func(struct input_dev *input_dev,
+			struct gpio_event_info *info, void **data, int func);
+struct gpio_event_input_info {
+	/* initialize to gpio_event_input_func */
+	struct gpio_event_info info;
+	ktime_t debounce_time;
+	ktime_t poll_time;
+	uint16_t flags;
+	uint16_t type;
+	const struct gpio_event_direct_entry *keymap;
+	size_t keymap_size;
+};
+
+/* outputs */
+extern int gpio_event_output_func(struct input_dev *input_dev,
+			struct gpio_event_info *info, void **data, int func);
+extern int gpio_event_output_event(struct input_dev *input_dev,
+			struct gpio_event_info *info, void **data,
+			unsigned int type, unsigned int code, int value);
+struct gpio_event_output_info {
+	/* initialize to gpio_event_output_func and gpio_event_output_event */
+	struct gpio_event_info info;
+	uint16_t flags;
+	uint16_t type;
+	const struct gpio_event_direct_entry *keymap;
+	size_t keymap_size;
+};
+
+
+/* axes */
+
+enum gpio_event_axis_flags {
+	GPIOEAF_PRINT_UNKNOWN_DIRECTION  = 1U << 16,
+	GPIOEAF_PRINT_RAW                = 1U << 17,
+	GPIOEAF_PRINT_EVENT              = 1U << 18,
+};
+
+extern int gpio_event_axis_func(struct input_dev *input_dev,
+			struct gpio_event_info *info, void **data, int func);
+struct gpio_event_axis_info {
+	/* initialize to gpio_event_axis_func */
+	struct gpio_event_info info;
+	uint8_t  count;
+	uint8_t  type; /* EV_REL or EV_ABS */
+	uint16_t code;
+	uint16_t decoded_size;
+	uint16_t (*map)(struct gpio_event_axis_info *info, uint16_t in);
+	uint32_t *gpio;
+	uint32_t flags;
+};
+#define gpio_axis_2bit_gray_map gpio_axis_4bit_gray_map
+#define gpio_axis_3bit_gray_map gpio_axis_4bit_gray_map
+uint16_t gpio_axis_4bit_gray_map(
+			struct gpio_event_axis_info *info, uint16_t in);
+uint16_t gpio_axis_5bit_singletrack_map(
+			struct gpio_event_axis_info *info, uint16_t in);
+
+#endif
diff --git a/drivers/staging/dream/include/linux/msm_adsp.h b/drivers/staging/dream/include/linux/msm_adsp.h
new file mode 100644
index 0000000..e775f3e
--- /dev/null
+++ b/drivers/staging/dream/include/linux/msm_adsp.h
@@ -0,0 +1,84 @@
+/* drivers/staging/dream/include/linux/msm_adsp.h
+ *
+ * Copyright (c) QUALCOMM Incorporated
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Iliyan Malchev <ibm@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __LINUX_MSM_ADSP_H
+#define __LINUX_MSM_ADSP_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define ADSP_IOCTL_MAGIC 'q'
+
+/* ADSP_IOCTL_WRITE_COMMAND */
+struct adsp_command_t {
+	uint16_t queue;
+	uint32_t len;		/* bytes */
+	uint8_t *data;
+};
+
+/* ADSP_IOCTL_GET_EVENT */
+struct adsp_event_t {
+	uint16_t type;		/* 1 == event (RPC), 0 == message (adsp) */
+	uint32_t timeout_ms;	/* -1 for infinite, 0 for immediate return */
+	uint16_t msg_id;
+	uint16_t flags;		/* 1 == 16--bit event, 0 == 32-bit event */
+	uint32_t len;		/* size in, number of bytes out */
+	uint8_t *data;
+};
+
+#define ADSP_IOCTL_ENABLE \
+	_IOR(ADSP_IOCTL_MAGIC, 1, unsigned)
+
+#define ADSP_IOCTL_DISABLE \
+	_IOR(ADSP_IOCTL_MAGIC, 2, unsigned)
+
+#define ADSP_IOCTL_DISABLE_ACK \
+	_IOR(ADSP_IOCTL_MAGIC, 3, unsigned)
+
+#define ADSP_IOCTL_WRITE_COMMAND \
+	_IOR(ADSP_IOCTL_MAGIC, 4, struct adsp_command_t *)
+
+#define ADSP_IOCTL_GET_EVENT \
+	_IOWR(ADSP_IOCTL_MAGIC, 5, struct adsp_event_data_t *)
+
+#define ADSP_IOCTL_SET_CLKRATE \
+	_IOR(ADSP_IOCTL_MAGIC, 6, unsigned)
+
+#define ADSP_IOCTL_DISABLE_EVENT_RSP \
+	_IOR(ADSP_IOCTL_MAGIC, 10, unsigned)
+
+struct adsp_pmem_info {
+        int fd;
+        void *vaddr;
+};
+
+#define ADSP_IOCTL_REGISTER_PMEM \
+	_IOW(ADSP_IOCTL_MAGIC, 13, unsigned)
+
+#define ADSP_IOCTL_UNREGISTER_PMEM \
+	_IOW(ADSP_IOCTL_MAGIC, 14, unsigned)
+
+/* Cause any further GET_EVENT ioctls to fail (-ENODEV)
+ * until the device is closed and reopened.  Useful for
+ * terminating event dispatch threads
+ */
+#define ADSP_IOCTL_ABORT_EVENT_READ \
+	_IOW(ADSP_IOCTL_MAGIC, 15, unsigned)
+
+#define ADSP_IOCTL_LINK_TASK \
+	_IOW(ADSP_IOCTL_MAGIC, 16, unsigned)
+
+#endif
diff --git a/drivers/staging/dream/include/linux/msm_audio.h b/drivers/staging/dream/include/linux/msm_audio.h
new file mode 100644
index 0000000..cfbdaa0
--- /dev/null
+++ b/drivers/staging/dream/include/linux/msm_audio.h
@@ -0,0 +1,115 @@
+/* drivers/staging/dream/include/linux/msm_audio.h
+ *
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __LINUX_MSM_AUDIO_H
+#define __LINUX_MSM_AUDIO_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/sizes.h>
+
+/* PCM Audio */
+
+#define AUDIO_IOCTL_MAGIC 'a'
+
+#define AUDIO_START        _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned)
+#define AUDIO_STOP         _IOW(AUDIO_IOCTL_MAGIC, 1, unsigned)
+#define AUDIO_FLUSH        _IOW(AUDIO_IOCTL_MAGIC, 2, unsigned)
+#define AUDIO_GET_CONFIG   _IOR(AUDIO_IOCTL_MAGIC, 3, unsigned)
+#define AUDIO_SET_CONFIG   _IOW(AUDIO_IOCTL_MAGIC, 4, unsigned)
+#define AUDIO_GET_STATS    _IOR(AUDIO_IOCTL_MAGIC, 5, unsigned)
+#define AUDIO_ENABLE_AUDPP _IOW(AUDIO_IOCTL_MAGIC, 6, unsigned)
+#define AUDIO_SET_ADRC     _IOW(AUDIO_IOCTL_MAGIC, 7, unsigned)
+#define AUDIO_SET_EQ       _IOW(AUDIO_IOCTL_MAGIC, 8, unsigned)
+#define AUDIO_SET_RX_IIR   _IOW(AUDIO_IOCTL_MAGIC, 9, unsigned)
+#define AUDIO_SET_VOLUME   _IOW(AUDIO_IOCTL_MAGIC, 10, unsigned)
+#define AUDIO_ENABLE_AUDPRE  _IOW(AUDIO_IOCTL_MAGIC, 11, unsigned)
+#define AUDIO_SET_AGC        _IOW(AUDIO_IOCTL_MAGIC, 12, unsigned)
+#define AUDIO_SET_NS         _IOW(AUDIO_IOCTL_MAGIC, 13, unsigned)
+#define AUDIO_SET_TX_IIR     _IOW(AUDIO_IOCTL_MAGIC, 14, unsigned)
+#define AUDIO_PAUSE	     _IOW(AUDIO_IOCTL_MAGIC, 15, unsigned)
+#define AUDIO_GET_PCM_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 30, unsigned)
+#define AUDIO_SET_PCM_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 31, unsigned)
+#define AUDIO_SWITCH_DEVICE  _IOW(AUDIO_IOCTL_MAGIC, 32, unsigned)
+
+#define	AUDIO_MAX_COMMON_IOCTL_NUM	100
+
+#define	AUDIO_MAX_COMMON_IOCTL_NUM	100
+
+struct msm_audio_config {
+	uint32_t buffer_size;
+	uint32_t buffer_count;
+	uint32_t channel_count;
+	uint32_t sample_rate;
+	uint32_t type;
+	uint32_t unused[3];
+};
+
+struct msm_audio_stats {
+	uint32_t byte_count;
+	uint32_t sample_count;
+	uint32_t unused[2];
+};
+
+/* Audio routing */
+
+#define SND_IOCTL_MAGIC 's'
+
+#define SND_MUTE_UNMUTED 0
+#define SND_MUTE_MUTED   1
+
+struct msm_snd_device_config {
+	uint32_t device;
+	uint32_t ear_mute;
+	uint32_t mic_mute;
+};
+
+#define SND_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_device_config *)
+
+#define SND_METHOD_VOICE 0
+
+struct msm_snd_volume_config {
+	uint32_t device;
+	uint32_t method;
+	uint32_t volume;
+};
+
+#define SND_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_snd_volume_config *)
+
+/* Returns the number of SND endpoints supported. */
+
+#define SND_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *)
+
+struct msm_snd_endpoint {
+	int id; /* input and output */
+	char name[64]; /* output only */
+};
+
+/* Takes an index between 0 and one less than the number returned by
+ * SND_GET_NUM_ENDPOINTS, and returns the SND index and name of a
+ * SND endpoint.  On input, the .id field contains the number of the
+ * endpoint, and on exit it contains the SND index, while .name contains
+ * the description of the endpoint.
+ */
+
+#define SND_GET_ENDPOINT _IOWR(SND_IOCTL_MAGIC, 5, struct msm_snd_endpoint *)
+
+struct msm_audio_pcm_config {
+	uint32_t pcm_feedback;	/* 0 - disable > 0 - enable */
+	uint32_t buffer_count;	/* Number of buffers to allocate */
+	uint32_t buffer_size;	/* Size of buffer for capturing of
+				   PCM samples */
+};
+#endif
diff --git a/drivers/staging/dream/include/linux/msm_rpcrouter.h b/drivers/staging/dream/include/linux/msm_rpcrouter.h
new file mode 100644
index 0000000..64845fb
--- /dev/null
+++ b/drivers/staging/dream/include/linux/msm_rpcrouter.h
@@ -0,0 +1,47 @@
+/* drivers/staging/dream/include/linux/msm_rpcrouter.h
+ *
+ * Copyright (c) QUALCOMM Incorporated
+ * Copyright (C) 2007 Google, Inc.
+ * Author: San Mehat <san@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __LINUX_MSM_RPCROUTER_H
+#define __LINUX_MSM_RPCROUTER_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define RPC_ROUTER_VERSION_V1 0x00010000
+
+struct rpcrouter_ioctl_server_args {
+	uint32_t prog;
+	uint32_t vers;
+};
+
+#define RPC_ROUTER_IOCTL_MAGIC (0xC1)
+
+#define RPC_ROUTER_IOCTL_GET_VERSION \
+	_IOR(RPC_ROUTER_IOCTL_MAGIC, 0, unsigned int)
+
+#define RPC_ROUTER_IOCTL_GET_MTU \
+	_IOR(RPC_ROUTER_IOCTL_MAGIC, 1, unsigned int)
+
+#define RPC_ROUTER_IOCTL_REGISTER_SERVER \
+	_IOWR(RPC_ROUTER_IOCTL_MAGIC, 2, unsigned int)
+
+#define RPC_ROUTER_IOCTL_UNREGISTER_SERVER \
+	_IOWR(RPC_ROUTER_IOCTL_MAGIC, 3, unsigned int)
+
+#define RPC_ROUTER_IOCTL_GET_MINOR_VERSION \
+	_IOW(RPC_ROUTER_IOCTL_MAGIC, 4, unsigned int)
+
+#endif
diff --git a/drivers/staging/dream/include/linux/wakelock.h b/drivers/staging/dream/include/linux/wakelock.h
new file mode 100644
index 0000000..93c31a4
--- /dev/null
+++ b/drivers/staging/dream/include/linux/wakelock.h
@@ -0,0 +1,91 @@
+/* drivers/staging/dream/include/linux/wakelock.h
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_WAKELOCK_H
+#define _LINUX_WAKELOCK_H
+
+#include <linux/list.h>
+#include <linux/ktime.h>
+
+/* A wake_lock prevents the system from entering suspend or other low power
+ * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock
+ * prevents a full system suspend. If the type is WAKE_LOCK_IDLE, low power
+ * states that cause large interrupt latencies or that disable a set of
+ * interrupts will not entered from idle until the wake_locks are released.
+ */
+
+enum {
+	WAKE_LOCK_SUSPEND, /* Prevent suspend */
+	WAKE_LOCK_IDLE,    /* Prevent low power idle */
+	WAKE_LOCK_TYPE_COUNT
+};
+
+struct wake_lock {
+#ifdef CONFIG_HAS_WAKELOCK
+	struct list_head    link;
+	int                 flags;
+	const char         *name;
+	unsigned long       expires;
+#ifdef CONFIG_WAKELOCK_STAT
+	struct {
+		int             count;
+		int             expire_count;
+		int             wakeup_count;
+		ktime_t         total_time;
+		ktime_t         prevent_suspend_time;
+		ktime_t         max_time;
+		ktime_t         last_time;
+	} stat;
+#endif
+#endif
+};
+
+#ifdef CONFIG_HAS_WAKELOCK
+
+void wake_lock_init(struct wake_lock *lock, int type, const char *name);
+void wake_lock_destroy(struct wake_lock *lock);
+void wake_lock(struct wake_lock *lock);
+void wake_lock_timeout(struct wake_lock *lock, long timeout);
+void wake_unlock(struct wake_lock *lock);
+
+/* wake_lock_active returns a non-zero value if the wake_lock is currently
+ * locked. If the wake_lock has a timeout, it does not check the timeout
+ * but if the timeout had aready been checked it will return 0.
+ */
+int wake_lock_active(struct wake_lock *lock);
+
+/* has_wake_lock returns 0 if no wake locks of the specified type are active,
+ * and non-zero if one or more wake locks are held. Specifically it returns
+ * -1 if one or more wake locks with no timeout are active or the
+ * number of jiffies until all active wake locks time out.
+ */
+long has_wake_lock(int type);
+
+#else
+
+static inline void wake_lock_init(struct wake_lock *lock, int type,
+					const char *name) {}
+static inline void wake_lock_destroy(struct wake_lock *lock) {}
+static inline void wake_lock(struct wake_lock *lock) {}
+static inline void wake_lock_timeout(struct wake_lock *lock, long timeout) {}
+static inline void wake_unlock(struct wake_lock *lock) {}
+
+static inline int wake_lock_active(struct wake_lock *lock) { return 0; }
+static inline long has_wake_lock(int type) { return 0; }
+
+#endif
+
+#endif
+
diff --git a/drivers/staging/dream/include/mach/camera.h b/drivers/staging/dream/include/mach/camera.h
new file mode 100644
index 0000000..c20f042
--- /dev/null
+++ b/drivers/staging/dream/include/mach/camera.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2008-2009 QUALCOMM Incorporated.
+ */
+
+#ifndef __ASM__ARCH_CAMERA_H
+#define __ASM__ARCH_CAMERA_H
+
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+#include "linux/types.h"
+
+#include <mach/board.h>
+#include <media/msm_camera.h>
+
+#ifdef CONFIG_MSM_CAMERA_DEBUG
+#define CDBG(fmt, args...) printk(KERN_INFO "msm_camera: " fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+#define MSM_CAMERA_MSG 0
+#define MSM_CAMERA_EVT 1
+#define NUM_WB_EXP_NEUTRAL_REGION_LINES 4
+#define NUM_WB_EXP_STAT_OUTPUT_BUFFERS  3
+#define NUM_AUTOFOCUS_MULTI_WINDOW_GRIDS 16
+#define NUM_AF_STAT_OUTPUT_BUFFERS      3
+
+enum msm_queue {
+	MSM_CAM_Q_CTRL,     /* control command or control command status */
+	MSM_CAM_Q_VFE_EVT,  /* adsp event */
+	MSM_CAM_Q_VFE_MSG,  /* adsp message */
+	MSM_CAM_Q_V4L2_REQ, /* v4l2 request */
+};
+
+enum vfe_resp_msg {
+	VFE_EVENT,
+	VFE_MSG_GENERAL,
+	VFE_MSG_SNAPSHOT,
+	VFE_MSG_OUTPUT1,
+	VFE_MSG_OUTPUT2,
+	VFE_MSG_STATS_AF,
+	VFE_MSG_STATS_WE,
+};
+
+struct msm_vfe_phy_info {
+	uint32_t sbuf_phy;
+	uint32_t y_phy;
+	uint32_t cbcr_phy;
+};
+
+struct msm_vfe_resp {
+	enum vfe_resp_msg type;
+	struct msm_vfe_evt_msg evt_msg;
+	struct msm_vfe_phy_info phy;
+	void    *extdata;
+	int32_t extlen;
+};
+
+struct msm_vfe_callback {
+	void (*vfe_resp)(struct msm_vfe_resp *,
+		enum msm_queue, void *syncdata);
+	void* (*vfe_alloc)(int, void *syncdata);
+};
+
+struct msm_camvfe_fn {
+	int (*vfe_init)(struct msm_vfe_callback *, struct platform_device *);
+	int (*vfe_enable)(struct camera_enable_cmd *);
+	int (*vfe_config)(struct msm_vfe_cfg_cmd *, void *);
+	int (*vfe_disable)(struct camera_enable_cmd *,
+		struct platform_device *dev);
+	void (*vfe_release)(struct platform_device *);
+};
+
+struct msm_sensor_ctrl {
+	int (*s_init)(const struct msm_camera_sensor_info *);
+	int (*s_release)(void);
+	int (*s_config)(void __user *);
+};
+
+struct msm_sync {
+	/* These two queues are accessed from a process context only. */
+	struct hlist_head frame; /* most-frequently accessed */
+	struct hlist_head stats;
+
+	/* The message queue is used by the control thread to send commands
+	 * to the config thread, and also by the DSP to send messages to the
+	 * config thread.  Thus it is the only queue that is accessed from
+	 * both interrupt and process context.
+	 */
+	spinlock_t msg_event_q_lock;
+	struct list_head msg_event_q;
+	wait_queue_head_t msg_event_wait;
+
+	/* This queue contains preview frames. It is accessed by the DSP (in
+	 * in interrupt context, and by the frame thread.
+	 */
+	spinlock_t prev_frame_q_lock;
+	struct list_head prev_frame_q;
+	wait_queue_head_t prev_frame_wait;
+	int unblock_poll_frame;
+
+	/* This queue contains snapshot frames.  It is accessed by the DSP (in
+	 * interrupt context, and by the control thread.
+	 */
+	spinlock_t pict_frame_q_lock;
+	struct list_head pict_frame_q;
+	wait_queue_head_t pict_frame_wait;
+
+	struct msm_camera_sensor_info *sdata;
+	struct msm_camvfe_fn vfefn;
+	struct msm_sensor_ctrl sctrl;
+	struct platform_device *pdev;
+	uint8_t opencnt;
+	void *cropinfo;
+	int  croplen;
+	unsigned pict_pp;
+
+	const char *apps_id;
+
+	struct mutex lock;
+	struct list_head list;
+};
+
+#define MSM_APPS_ID_V4L2 "msm_v4l2"
+#define MSM_APPS_ID_PROP "msm_qct"
+
+struct msm_device {
+	struct msm_sync *sync; /* most-frequently accessed */
+	struct device *device;
+	struct cdev cdev;
+	/* opened is meaningful only for the config and frame nodes,
+	 * which may be opened only once.
+	 */
+	atomic_t opened;
+};
+
+struct msm_control_device_queue {
+	spinlock_t ctrl_status_q_lock;
+	struct list_head ctrl_status_q;
+	wait_queue_head_t ctrl_status_wait;
+};
+
+struct msm_control_device {
+	struct msm_device *pmsm;
+
+	/* This queue used by the config thread to send responses back to the
+	 * control thread.  It is accessed only from a process context.
+	 */
+	struct msm_control_device_queue ctrl_q;
+};
+
+/* this structure is used in kernel */
+struct msm_queue_cmd {
+	struct list_head list;
+	enum msm_queue type;
+	void *command;
+};
+
+struct register_address_value_pair {
+	uint16_t register_address;
+	uint16_t register_value;
+};
+
+struct msm_pmem_region {
+	struct hlist_node list;
+	int type;
+	void *vaddr;
+	unsigned long paddr;
+	unsigned long len;
+	struct file *file;
+	uint32_t y_off;
+	uint32_t cbcr_off;
+	int fd;
+	uint8_t  active;
+};
+
+struct axidata {
+	uint32_t bufnum1;
+	uint32_t bufnum2;
+	struct msm_pmem_region *region;
+};
+
+#ifdef CONFIG_MSM_CAMERA_FLASH
+int msm_camera_flash_set_led_state(unsigned led_state);
+#else
+static inline int msm_camera_flash_set_led_state(unsigned led_state)
+{
+	return -ENOTSUPP;
+}
+#endif
+
+/* Below functions are added for V4L2 kernel APIs */
+struct msm_v4l2_driver {
+	struct msm_sync *sync;
+	int (*open)(struct msm_sync *, const char *apps_id);
+	int (*release)(struct msm_sync *);
+	int (*ctrl)(struct msm_sync *, struct msm_ctrl_cmd *);
+	int (*reg_pmem)(struct msm_sync *, struct msm_pmem_info *);
+	int (*get_frame) (struct msm_sync *, struct msm_frame *);
+	int (*put_frame) (struct msm_sync *, struct msm_frame *);
+	int (*get_pict) (struct msm_sync *, struct msm_ctrl_cmd *);
+	unsigned int (*drv_poll) (struct msm_sync *, struct file *,
+				struct poll_table_struct *);
+};
+
+int msm_v4l2_register(struct msm_v4l2_driver *);
+int msm_v4l2_unregister(struct msm_v4l2_driver *);
+
+void msm_camvfe_init(void);
+int msm_camvfe_check(void *);
+void msm_camvfe_fn_init(struct msm_camvfe_fn *, void *);
+int msm_camera_drv_start(struct platform_device *dev,
+		int (*sensor_probe)(const struct msm_camera_sensor_info *,
+					struct msm_sensor_ctrl *));
+
+enum msm_camio_clk_type {
+	CAMIO_VFE_MDC_CLK,
+	CAMIO_MDC_CLK,
+	CAMIO_VFE_CLK,
+	CAMIO_VFE_AXI_CLK,
+
+	CAMIO_MAX_CLK
+};
+
+enum msm_camio_clk_src_type {
+	MSM_CAMIO_CLK_SRC_INTERNAL,
+	MSM_CAMIO_CLK_SRC_EXTERNAL,
+	MSM_CAMIO_CLK_SRC_MAX
+};
+
+enum msm_s_test_mode {
+	S_TEST_OFF,
+	S_TEST_1,
+	S_TEST_2,
+	S_TEST_3
+};
+
+enum msm_s_resolution {
+	S_QTR_SIZE,
+	S_FULL_SIZE,
+	S_INVALID_SIZE
+};
+
+enum msm_s_reg_update {
+	/* Sensor egisters that need to be updated during initialization */
+	S_REG_INIT,
+	/* Sensor egisters that needs periodic I2C writes */
+	S_UPDATE_PERIODIC,
+	/* All the sensor Registers will be updated */
+	S_UPDATE_ALL,
+	/* Not valid update */
+	S_UPDATE_INVALID
+};
+
+enum msm_s_setting {
+	S_RES_PREVIEW,
+	S_RES_CAPTURE
+};
+
+int msm_camio_enable(struct platform_device *dev);
+
+int  msm_camio_clk_enable(enum msm_camio_clk_type clk);
+int  msm_camio_clk_disable(enum msm_camio_clk_type clk);
+int  msm_camio_clk_config(uint32_t freq);
+void msm_camio_clk_rate_set(int rate);
+void msm_camio_clk_axi_rate_set(int rate);
+
+void msm_camio_camif_pad_reg_reset(void);
+void msm_camio_camif_pad_reg_reset_2(void);
+
+void msm_camio_vfe_blk_reset(void);
+
+void msm_camio_clk_sel(enum msm_camio_clk_src_type);
+void msm_camio_disable(struct platform_device *);
+int msm_camio_probe_on(struct platform_device *);
+int msm_camio_probe_off(struct platform_device *);
+#endif
diff --git a/drivers/staging/dream/include/mach/msm_adsp.h b/drivers/staging/dream/include/mach/msm_adsp.h
new file mode 100644
index 0000000..a081683
--- /dev/null
+++ b/drivers/staging/dream/include/mach/msm_adsp.h
@@ -0,0 +1,112 @@
+/* include/asm-arm/arch-msm/msm_adsp.h
+ *
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM__ARCH_MSM_ADSP_H
+#define __ASM__ARCH_MSM_ADSP_H
+
+struct msm_adsp_module;
+
+struct msm_adsp_ops {
+	/* event is called from interrupt context when a message
+	 * arrives from the DSP.  Use the provided function pointer
+	 * to copy the message into a local buffer.  Do NOT call
+	 * it multiple times.
+	 */
+	void (*event)(void *driver_data, unsigned id, size_t len,
+		      void (*getevent)(void *ptr, size_t len));
+};
+
+/* Get, Put, Enable, and Disable are synchronous and must only
+ * be called from thread context.  Enable and Disable will block
+ * up to one second in the event of a fatal DSP error but are
+ * much faster otherwise.
+ */
+int msm_adsp_get(const char *name, struct msm_adsp_module **module,
+		 struct msm_adsp_ops *ops, void *driver_data);
+void msm_adsp_put(struct msm_adsp_module *module);
+int msm_adsp_enable(struct msm_adsp_module *module);
+int msm_adsp_disable(struct msm_adsp_module *module);
+int adsp_set_clkrate(struct msm_adsp_module *module, unsigned long clk_rate);
+
+/* Write is safe to call from interrupt context.
+ */
+int msm_adsp_write(struct msm_adsp_module *module,
+		   unsigned queue_id,
+		   void *data, size_t len);
+
+#if CONFIG_MSM_AMSS_VERSION >= 6350
+/* Command Queue Indexes */
+#define QDSP_lpmCommandQueue              0
+#define QDSP_mpuAfeQueue                  1
+#define QDSP_mpuGraphicsCmdQueue          2
+#define QDSP_mpuModmathCmdQueue           3
+#define QDSP_mpuVDecCmdQueue              4
+#define QDSP_mpuVDecPktQueue              5
+#define QDSP_mpuVEncCmdQueue              6
+#define QDSP_rxMpuDecCmdQueue             7
+#define QDSP_rxMpuDecPktQueue             8
+#define QDSP_txMpuEncQueue                9
+#define QDSP_uPAudPPCmd1Queue             10
+#define QDSP_uPAudPPCmd2Queue             11
+#define QDSP_uPAudPPCmd3Queue             12
+#define QDSP_uPAudPlay0BitStreamCtrlQueue 13
+#define QDSP_uPAudPlay1BitStreamCtrlQueue 14
+#define QDSP_uPAudPlay2BitStreamCtrlQueue 15
+#define QDSP_uPAudPlay3BitStreamCtrlQueue 16
+#define QDSP_uPAudPlay4BitStreamCtrlQueue 17
+#define QDSP_uPAudPreProcCmdQueue         18
+#define QDSP_uPAudRecBitStreamQueue       19
+#define QDSP_uPAudRecCmdQueue             20
+#define QDSP_uPDiagQueue                  21
+#define QDSP_uPJpegActionCmdQueue         22
+#define QDSP_uPJpegCfgCmdQueue            23
+#define QDSP_uPVocProcQueue               24
+#define QDSP_vfeCommandQueue              25
+#define QDSP_vfeCommandScaleQueue         26
+#define QDSP_vfeCommandTableQueue         27
+#define QDSP_MAX_NUM_QUEUES               28
+#else
+/* Command Queue Indexes */
+#define QDSP_lpmCommandQueue              0
+#define QDSP_mpuAfeQueue                  1
+#define QDSP_mpuGraphicsCmdQueue          2
+#define QDSP_mpuModmathCmdQueue           3
+#define QDSP_mpuVDecCmdQueue              4
+#define QDSP_mpuVDecPktQueue              5
+#define QDSP_mpuVEncCmdQueue              6
+#define QDSP_rxMpuDecCmdQueue             7
+#define QDSP_rxMpuDecPktQueue             8
+#define QDSP_txMpuEncQueue                9
+#define QDSP_uPAudPPCmd1Queue             10
+#define QDSP_uPAudPPCmd2Queue             11
+#define QDSP_uPAudPPCmd3Queue             12
+#define QDSP_uPAudPlay0BitStreamCtrlQueue 13
+#define QDSP_uPAudPlay1BitStreamCtrlQueue 14
+#define QDSP_uPAudPlay2BitStreamCtrlQueue 15
+#define QDSP_uPAudPlay3BitStreamCtrlQueue 16
+#define QDSP_uPAudPlay4BitStreamCtrlQueue 17
+#define QDSP_uPAudPreProcCmdQueue         18
+#define QDSP_uPAudRecBitStreamQueue       19
+#define QDSP_uPAudRecCmdQueue             20
+#define QDSP_uPJpegActionCmdQueue         21
+#define QDSP_uPJpegCfgCmdQueue            22
+#define QDSP_uPVocProcQueue               23
+#define QDSP_vfeCommandQueue              24
+#define QDSP_vfeCommandScaleQueue         25
+#define QDSP_vfeCommandTableQueue         26
+#define QDSP_QUEUE_MAX                    26
+#endif
+
+#endif
diff --git a/drivers/staging/dream/include/mach/msm_rpcrouter.h b/drivers/staging/dream/include/mach/msm_rpcrouter.h
new file mode 100644
index 0000000..9724ece
--- /dev/null
+++ b/drivers/staging/dream/include/mach/msm_rpcrouter.h
@@ -0,0 +1,179 @@
+/** include/asm-arm/arch-msm/msm_rpcrouter.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2009 QUALCOMM Incorporated
+ * Author: San Mehat <san@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM__ARCH_MSM_RPCROUTER_H
+#define __ASM__ARCH_MSM_RPCROUTER_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+
+#if CONFIG_MSM_AMSS_VERSION >= 6350
+/* RPC API version structure
+ * Version bit 31 : 1->hashkey versioning,
+ *                  0->major-minor (backward compatible) versioning
+ * hashkey versioning:
+ *   Version bits 31-0 hashkey
+ * major-minor (backward compatible) versioning
+ *   Version bits 30-28 reserved (no match)
+ *   Version bits 27-16 major (must match)
+ *   Version bits 15-0  minor (greater or equal)
+ */
+#define RPC_VERSION_MODE_MASK  0x80000000
+#define RPC_VERSION_MAJOR_MASK 0x0fff0000
+#define RPC_VERSION_MAJOR_OFFSET 16
+#define RPC_VERSION_MINOR_MASK 0x0000ffff
+
+#define MSM_RPC_VERS(major, minor)					\
+	((uint32_t)((((major) << RPC_VERSION_MAJOR_OFFSET) &		\
+		RPC_VERSION_MAJOR_MASK) |				\
+	((minor) & RPC_VERSION_MINOR_MASK)))
+#define MSM_RPC_GET_MAJOR(vers) (((vers) & RPC_VERSION_MAJOR_MASK) >>	\
+					RPC_VERSION_MAJOR_OFFSET)
+#define MSM_RPC_GET_MINOR(vers) ((vers) & RPC_VERSION_MINOR_MASK)
+#else
+#define MSM_RPC_VERS(major, minor) (major)
+#define MSM_RPC_GET_MAJOR(vers) (vers)
+#define MSM_RPC_GET_MINOR(vers) 0
+#endif
+
+struct msm_rpc_endpoint;
+
+struct rpcsvr_platform_device
+{
+	struct platform_device base;
+	uint32_t prog;
+	uint32_t vers;
+};
+
+#define RPC_DATA_IN	0
+/*
+ * Structures for sending / receiving direct RPC requests
+ * XXX: Any cred/verif lengths > 0 not supported
+ */
+
+struct rpc_request_hdr
+{
+	uint32_t xid;
+	uint32_t type;	/* 0 */
+	uint32_t rpc_vers; /* 2 */
+	uint32_t prog;
+	uint32_t vers;
+	uint32_t procedure;
+	uint32_t cred_flavor;
+	uint32_t cred_length;
+	uint32_t verf_flavor;
+	uint32_t verf_length;
+};
+
+typedef struct
+{
+	uint32_t low;
+	uint32_t high;
+} rpc_reply_progmismatch_data;
+
+typedef struct
+{
+} rpc_denied_reply_hdr;
+
+typedef struct
+{
+	uint32_t verf_flavor;
+	uint32_t verf_length;
+	uint32_t accept_stat;
+#define RPC_ACCEPTSTAT_SUCCESS 0
+#define RPC_ACCEPTSTAT_PROG_UNAVAIL 1
+#define RPC_ACCEPTSTAT_PROG_MISMATCH 2
+#define RPC_ACCEPTSTAT_PROC_UNAVAIL 3
+#define RPC_ACCEPTSTAT_GARBAGE_ARGS 4
+#define RPC_ACCEPTSTAT_SYSTEM_ERR 5
+#define RPC_ACCEPTSTAT_PROG_LOCKED 6
+	/*
+	 * Following data is dependant on accept_stat
+	 * If ACCEPTSTAT == PROG_MISMATCH then there is a
+	 * 'rpc_reply_progmismatch_data' structure following the header.
+	 * Otherwise the data is procedure specific
+	 */
+} rpc_accepted_reply_hdr;
+
+struct rpc_reply_hdr
+{
+	uint32_t xid;
+	uint32_t type;
+	uint32_t reply_stat;
+#define RPCMSG_REPLYSTAT_ACCEPTED 0
+#define RPCMSG_REPLYSTAT_DENIED 1
+	union {
+		rpc_accepted_reply_hdr acc_hdr;
+		rpc_denied_reply_hdr dny_hdr;
+	} data;
+};
+
+/* flags for msm_rpc_connect() */
+#define MSM_RPC_UNINTERRUPTIBLE 0x0001
+
+/* use IS_ERR() to check for failure */
+struct msm_rpc_endpoint *msm_rpc_open(void);
+/* Connect with the specified server version */
+struct msm_rpc_endpoint *msm_rpc_connect(uint32_t prog, uint32_t vers, unsigned flags);
+uint32_t msm_rpc_get_vers(struct msm_rpc_endpoint *ept);
+/* check if server version can handle client requested version */
+int msm_rpc_is_compatible_version(uint32_t server_version,
+				  uint32_t client_version);
+
+int msm_rpc_close(struct msm_rpc_endpoint *ept);
+int msm_rpc_write(struct msm_rpc_endpoint *ept,
+		  void *data, int len);
+int msm_rpc_read(struct msm_rpc_endpoint *ept,
+		 void **data, unsigned len, long timeout);
+void msm_rpc_setup_req(struct rpc_request_hdr *hdr,
+		       uint32_t prog, uint32_t vers, uint32_t proc);
+int msm_rpc_register_server(struct msm_rpc_endpoint *ept,
+			    uint32_t prog, uint32_t vers);
+int msm_rpc_unregister_server(struct msm_rpc_endpoint *ept,
+			      uint32_t prog, uint32_t vers);
+
+/* simple blocking rpc call
+ *
+ * request is mandatory and must have a rpc_request_hdr
+ * at the start.  The header will be filled out for you.
+ *
+ * reply provides a buffer for replies of reply_max_size
+ */
+int msm_rpc_call_reply(struct msm_rpc_endpoint *ept, uint32_t proc,
+		       void *request, int request_size,
+		       void *reply, int reply_max_size,
+		       long timeout);
+int msm_rpc_call(struct msm_rpc_endpoint *ept, uint32_t proc,
+		 void *request, int request_size,
+		 long timeout);
+
+struct msm_rpc_server
+{
+	struct list_head list;
+	uint32_t flags;
+
+	uint32_t prog;
+	uint32_t vers;
+
+	int (*rpc_call)(struct msm_rpc_server *server,
+			struct rpc_request_hdr *req, unsigned len);
+};
+
+int msm_rpc_create_server(struct msm_rpc_server *server);
+
+#endif
diff --git a/drivers/staging/dream/include/mach/msm_smd.h b/drivers/staging/dream/include/mach/msm_smd.h
new file mode 100644
index 0000000..bdf7731
--- /dev/null
+++ b/drivers/staging/dream/include/mach/msm_smd.h
@@ -0,0 +1,107 @@
+/* linux/include/asm-arm/arch-msm/msm_smd.h
+ *
+ * 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 __ASM_ARCH_MSM_SMD_H
+#define __ASM_ARCH_MSM_SMD_H
+
+typedef struct smd_channel smd_channel_t;
+
+/* warning: notify() may be called before open returns */
+int smd_open(const char *name, smd_channel_t **ch, void *priv,
+	     void (*notify)(void *priv, unsigned event));
+
+#define SMD_EVENT_DATA 1
+#define SMD_EVENT_OPEN 2
+#define SMD_EVENT_CLOSE 3
+
+int smd_close(smd_channel_t *ch);
+
+/* passing a null pointer for data reads and discards */
+int smd_read(smd_channel_t *ch, void *data, int len);
+
+/* Write to stream channels may do a partial write and return
+** the length actually written.
+** Write to packet channels will never do a partial write --
+** it will return the requested length written or an error.
+*/
+int smd_write(smd_channel_t *ch, const void *data, int len);
+
+int smd_write_avail(smd_channel_t *ch);
+int smd_read_avail(smd_channel_t *ch);
+
+/* Returns the total size of the current packet being read.
+** Returns 0 if no packets available or a stream channel.
+*/
+int smd_cur_packet_size(smd_channel_t *ch);
+
+/* used for tty unthrottling and the like -- causes the notify()
+** callback to be called from the same lock context as is used
+** when it is called from channel updates
+*/
+void smd_kick(smd_channel_t *ch);
+
+
+#if 0
+/* these are interruptable waits which will block you until the specified
+** number of bytes are readable or writable.
+*/
+int smd_wait_until_readable(smd_channel_t *ch, int bytes);
+int smd_wait_until_writable(smd_channel_t *ch, int bytes);
+#endif
+
+typedef enum
+{
+	SMD_PORT_DS = 0,
+	SMD_PORT_DIAG,
+	SMD_PORT_RPC_CALL,
+	SMD_PORT_RPC_REPLY,
+	SMD_PORT_BT,
+	SMD_PORT_CONTROL,
+	SMD_PORT_MEMCPY_SPARE1,
+	SMD_PORT_DATA1,
+	SMD_PORT_DATA2,
+	SMD_PORT_DATA3,
+	SMD_PORT_DATA4,
+	SMD_PORT_DATA5,
+	SMD_PORT_DATA6,
+	SMD_PORT_DATA7,
+	SMD_PORT_DATA8,
+	SMD_PORT_DATA9,
+	SMD_PORT_DATA10,
+	SMD_PORT_DATA11,
+	SMD_PORT_DATA12,
+	SMD_PORT_DATA13,
+	SMD_PORT_DATA14,
+	SMD_PORT_DATA15,
+	SMD_PORT_DATA16,
+	SMD_PORT_DATA17,
+	SMD_PORT_DATA18,
+	SMD_PORT_DATA19,
+	SMD_PORT_DATA20,
+	SMD_PORT_GPS_NMEA,
+	SMD_PORT_BRIDGE_1,
+	SMD_PORT_BRIDGE_2,
+	SMD_PORT_BRIDGE_3,
+	SMD_PORT_BRIDGE_4,
+	SMD_PORT_BRIDGE_5,
+	SMD_PORT_LOOPBACK,
+	SMD_PORT_CS_APPS_MODEM,
+	SMD_PORT_CS_APPS_DSP,
+	SMD_PORT_CS_MODEM_DSP,
+	SMD_NUM_PORTS,
+} smd_port_id_type;
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaycmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaycmdi.h
new file mode 100644
index 0000000..0b6a312
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaycmdi.h
@@ -0,0 +1,94 @@
+#ifndef QDSP5AUDPLAYCMDI_H
+#define QDSP5AUDPLAYCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+       Q D S P 5  A U D I O   P L A Y  T A S K   C O M M A N D S
+
+GENERAL DESCRIPTION
+  Command Interface for AUDPLAYTASK on QDSP5
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+
+  audplay_cmd_dec_data_avail
+    Send buffer to AUDPLAY task
+
+
+Copyright(c) 1992 - 2009 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audplaycmdi.h#2 $
+
+===========================================================================*/
+
+#define AUDPLAY_CMD_BITSTREAM_DATA_AVAIL		0x0000
+#define AUDPLAY_CMD_BITSTREAM_DATA_AVAIL_LEN	\
+	sizeof(audplay_cmd_bitstream_data_avail)
+
+/* Type specification of dec_data_avail message sent to AUDPLAYTASK
+*/
+typedef struct {
+	/*command ID*/
+	unsigned int cmd_id;
+
+	/* Decoder ID for which message is being sent */
+	unsigned int decoder_id;
+
+	/* Start address of data in ARM global memory */
+	unsigned int buf_ptr;
+
+	/* Number of 16-bit words of bit-stream data contiguously available at the
+	 * above-mentioned address. */
+	unsigned int buf_size;
+
+	/* Partition number used by audPlayTask to communicate with DSP's RTOS
+	 * kernel */
+	unsigned int partition_number;
+} __attribute__((packed)) audplay_cmd_bitstream_data_avail;
+
+#define AUDPLAY_CMD_HPCM_BUF_CFG 0x0003
+#define AUDPLAY_CMD_HPCM_BUF_CFG_LEN \
+	sizeof(struct audplay_cmd_hpcm_buf_cfg)
+
+struct audplay_cmd_hpcm_buf_cfg {
+	unsigned int cmd_id;
+	unsigned int hostpcm_config;
+	unsigned int feedback_frequency;
+	unsigned int byte_swap;
+	unsigned int max_buffers;
+	unsigned int partition_number;
+} __attribute__((packed));
+
+#define AUDPLAY_CMD_BUFFER_REFRESH 0x0004
+#define AUDPLAY_CMD_BUFFER_REFRESH_LEN \
+	sizeof(struct audplay_cmd_buffer_update)
+
+struct audplay_cmd_buffer_refresh {
+	unsigned int cmd_id;
+	unsigned int num_buffers;
+	unsigned int buf_read_count;
+	unsigned int buf0_address;
+	unsigned int buf0_length;
+	unsigned int buf1_address;
+	unsigned int buf1_length;
+} __attribute__((packed));
+#endif /* QDSP5AUDPLAYCMD_H */
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaymsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaymsg.h
new file mode 100644
index 0000000..c63034b
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaymsg.h
@@ -0,0 +1,70 @@
+#ifndef QDSP5AUDPLAYMSG_H
+#define QDSP5AUDPLAYMSG_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+       Q D S P 5  A U D I O   P L A Y  T A S K   M S G
+
+GENERAL DESCRIPTION
+  Message sent by AUDPLAY task
+
+REFERENCES
+  None
+
+
+Copyright(c) 1992 - 2009 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audplaymsg.h#3 $
+
+===========================================================================*/
+#define AUDPLAY_MSG_DEC_NEEDS_DATA		0x0001
+#define AUDPLAY_MSG_DEC_NEEDS_DATA_MSG_LEN	\
+	sizeof(audplay_msg_dec_needs_data)
+
+typedef struct{
+	/* reserved*/
+	unsigned int dec_id;
+
+	/* The read pointer offset of external memory until which the
+	 * bitstream has been DMAed in. */
+	unsigned int adecDataReadPtrOffset;
+
+	/* The buffer size of external memory. */
+	unsigned int adecDataBufSize;
+
+	unsigned int bitstream_free_len;
+	unsigned int bitstream_write_ptr;
+	unsigned int bitstarem_buf_start;
+	unsigned int bitstream_buf_len;
+} __attribute__((packed)) audplay_msg_dec_needs_data;
+
+#define AUDPLAY_MSG_BUFFER_UPDATE 0x0004
+#define AUDPLAY_MSG_BUFFER_UPDATE_LEN \
+	sizeof(struct audplay_msg_buffer_update)
+
+struct audplay_msg_buffer_update {
+	unsigned int buffer_write_count;
+	unsigned int num_of_buffer;
+	unsigned int buf0_address;
+	unsigned int buf0_length;
+	unsigned int buf1_address;
+	unsigned int buf1_length;
+} __attribute__((packed));
+#endif /* QDSP5AUDPLAYMSG_H */
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audppcmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audppcmdi.h
new file mode 100644
index 0000000..8bee9c6
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audppcmdi.h
@@ -0,0 +1,914 @@
+#ifndef QDSP5AUDPPCMDI_H
+#define QDSP5AUDPPCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    A U D I O   P O S T   P R O C E S S I N G  I N T E R N A L  C O M M A N D S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of commands
+  that are accepted by AUDPP Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audppcmdi.h#2 $
+
+===========================================================================*/
+
+/*
+ * ARM to AUDPPTASK Commands
+ *
+ * ARM uses three command queues to communicate with AUDPPTASK
+ * 1)uPAudPPCmd1Queue : Used for more frequent and shorter length commands
+ * 	Location : MEMA
+ * 	Buffer Size : 6 words
+ * 	No of buffers in a queue : 20 for gaming audio and 5 for other images
+ * 2)uPAudPPCmd2Queue : Used for commands which are not much lengthier
+ * 	Location : MEMA
+ * 	Buffer Size : 23
+ * 	No of buffers in a queue : 2
+ * 3)uPAudOOCmd3Queue : Used for lengthier and more frequent commands
+ * 	Location : MEMA
+ * 	Buffer Size : 145
+ * 	No of buffers in a queue : 3
+ */
+
+/*
+ * Commands Related to uPAudPPCmd1Queue
+ */
+
+/*
+ * Command Structure to enable or disable the active decoders
+ */
+
+#define AUDPP_CMD_CFG_DEC_TYPE 		0x0001
+#define AUDPP_CMD_CFG_DEC_TYPE_LEN 	sizeof(audpp_cmd_cfg_dec_type)
+
+/* Enable the decoder */
+#define AUDPP_CMD_DEC_TYPE_M           	0x000F
+
+#define AUDPP_CMD_ENA_DEC_V         	0x4000
+#define AUDPP_CMD_DIS_DEC_V        	0x0000
+#define AUDPP_CMD_DEC_STATE_M          	0x4000
+
+#define AUDPP_CMD_UPDATDE_CFG_DEC	0x8000
+#define AUDPP_CMD_DONT_UPDATE_CFG_DEC	0x0000
+
+
+/* Type specification of cmd_cfg_dec */
+
+typedef struct {
+	unsigned short cmd_id;
+	unsigned short dec0_cfg;
+	unsigned short dec1_cfg;
+	unsigned short dec2_cfg;
+	unsigned short dec3_cfg;
+	unsigned short dec4_cfg;
+} __attribute__((packed)) audpp_cmd_cfg_dec_type;
+
+/*
+ * Command Structure to Pause , Resume and flushes the selected audio decoders
+ */
+
+#define AUDPP_CMD_DEC_CTRL		0x0002
+#define AUDPP_CMD_DEC_CTRL_LEN		sizeof(audpp_cmd_dec_ctrl)
+
+/* Decoder control commands for pause, resume and flush */
+#define AUDPP_CMD_FLUSH_V         		0x2000
+
+#define AUDPP_CMD_PAUSE_V		        0x4000
+#define AUDPP_CMD_RESUME_V		        0x0000
+
+#define AUDPP_CMD_UPDATE_V		        0x8000
+#define AUDPP_CMD_IGNORE_V		        0x0000
+
+
+/* Type Spec for decoder control command*/
+
+typedef struct {
+	unsigned short cmd_id;
+	unsigned short dec0_ctrl;
+	unsigned short dec1_ctrl;
+	unsigned short dec2_ctrl;
+	unsigned short dec3_ctrl;
+	unsigned short dec4_ctrl;
+} __attribute__((packed)) audpp_cmd_dec_ctrl;
+
+/*
+ * Command Structure to Configure the AVSync FeedBack Mechanism
+ */
+
+#define AUDPP_CMD_AVSYNC	0x0003
+#define AUDPP_CMD_AVSYNC_LEN	sizeof(audpp_cmd_avsync)
+
+typedef struct {
+	unsigned short cmd_id;
+	unsigned short object_number;
+	unsigned short interrupt_interval_lsw;
+	unsigned short interrupt_interval_msw;
+} __attribute__((packed)) audpp_cmd_avsync;
+
+/*
+ * Command Structure to enable or disable(sleep) the   AUDPPTASK
+ */
+
+#define AUDPP_CMD_CFG	0x0004
+#define AUDPP_CMD_CFG_LEN	sizeof(audpp_cmd_cfg)
+
+#define AUDPP_CMD_CFG_SLEEP   				0x0000
+#define AUDPP_CMD_CFG_ENABLE  				0xFFFF
+
+typedef struct {
+	unsigned short cmd_id;
+	unsigned short cfg;
+} __attribute__((packed)) audpp_cmd_cfg;
+
+/*
+ * Command Structure to Inject or drop the specified no of samples
+ */
+
+#define AUDPP_CMD_ADJUST_SAMP		0x0005
+#define AUDPP_CMD_ADJUST_SAMP_LEN	sizeof(audpp_cmd_adjust_samp)
+
+#define AUDPP_CMD_SAMP_DROP		-1
+#define AUDPP_CMD_SAMP_INSERT		0x0001
+
+#define AUDPP_CMD_NUM_SAMPLES		0x0001
+
+typedef struct {
+	unsigned short cmd_id;
+	unsigned short object_no;
+	signed short sample_insert_or_drop;
+	unsigned short num_samples;
+} __attribute__((packed)) audpp_cmd_adjust_samp;
+
+/*
+ * Command Structure to Configure AVSync Feedback Mechanism
+ */
+
+#define AUDPP_CMD_AVSYNC_CMD_2		0x0006
+#define AUDPP_CMD_AVSYNC_CMD_2_LEN	sizeof(audpp_cmd_avsync_cmd_2)
+
+typedef struct {
+	unsigned short cmd_id;
+	unsigned short object_number;
+	unsigned short interrupt_interval_lsw;
+	unsigned short interrupt_interval_msw;
+	unsigned short sample_counter_dlsw;
+	unsigned short sample_counter_dmsw;
+	unsigned short sample_counter_msw;
+	unsigned short byte_counter_dlsw;
+	unsigned short byte_counter_dmsw;
+	unsigned short byte_counter_msw;
+} __attribute__((packed)) audpp_cmd_avsync_cmd_2;
+
+/*
+ * Command Structure to Configure AVSync Feedback Mechanism
+ */
+
+#define AUDPP_CMD_AVSYNC_CMD_3		0x0007
+#define AUDPP_CMD_AVSYNC_CMD_3_LEN	sizeof(audpp_cmd_avsync_cmd_3)
+
+typedef struct {
+	unsigned short cmd_id;
+	unsigned short object_number;
+	unsigned short interrupt_interval_lsw;
+	unsigned short interrupt_interval_msw;
+	unsigned short sample_counter_dlsw;
+	unsigned short sample_counter_dmsw;
+	unsigned short sample_counter_msw;
+	unsigned short byte_counter_dlsw;
+	unsigned short byte_counter_dmsw;
+	unsigned short byte_counter_msw;
+} __attribute__((packed)) audpp_cmd_avsync_cmd_3;
+
+#define AUDPP_CMD_ROUTING_MODE      0x0008
+#define AUDPP_CMD_ROUTING_MODE_LEN  \
+sizeof(struct audpp_cmd_routing_mode)
+
+struct audpp_cmd_routing_mode {
+	unsigned short cmd_id;
+	unsigned short object_number;
+	unsigned short routing_mode;
+} __attribute__((packed));
+
+/*
+ * Commands Related to uPAudPPCmd2Queue
+ */
+
+/*
+ * Command Structure to configure Per decoder Parameters (Common)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS 		0x0000
+#define AUDPP_CMD_CFG_ADEC_PARAMS_COMMON_LEN	\
+	sizeof(audpp_cmd_cfg_adec_params_common)
+
+#define AUDPP_CMD_STATUS_MSG_FLAG_ENA_FCM	0x4000
+#define AUDPP_CMD_STATUS_MSG_FLAG_DIS_FCM	0x0000
+
+#define AUDPP_CMD_STATUS_MSG_FLAG_ENA_DCM	0x8000
+#define AUDPP_CMD_STATUS_MSG_FLAG_DIS_DCM	0x0000
+
+/* Sampling frequency*/
+#define  AUDPP_CMD_SAMP_RATE_96000 	0x0000
+#define  AUDPP_CMD_SAMP_RATE_88200 	0x0001
+#define  AUDPP_CMD_SAMP_RATE_64000 	0x0002
+#define  AUDPP_CMD_SAMP_RATE_48000 	0x0003
+#define  AUDPP_CMD_SAMP_RATE_44100 	0x0004
+#define  AUDPP_CMD_SAMP_RATE_32000 	0x0005
+#define  AUDPP_CMD_SAMP_RATE_24000 	0x0006
+#define  AUDPP_CMD_SAMP_RATE_22050 	0x0007
+#define  AUDPP_CMD_SAMP_RATE_16000 	0x0008
+#define  AUDPP_CMD_SAMP_RATE_12000 	0x0009
+#define  AUDPP_CMD_SAMP_RATE_11025 	0x000A
+#define  AUDPP_CMD_SAMP_RATE_8000  	0x000B
+
+
+/*
+ * Type specification of cmd_adec_cfg sent to all decoder
+ */
+
+typedef struct {
+  unsigned short cmd_id;
+  unsigned short  length;
+  unsigned short  dec_id;
+  unsigned short  status_msg_flag;
+  unsigned short  decoder_frame_counter_msg_period;
+  unsigned short  input_sampling_frequency;
+} __attribute__((packed)) audpp_cmd_cfg_adec_params_common;
+
+/*
+ * Command Structure to configure Per decoder Parameters (Wav)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_WAV_LEN	\
+	sizeof(audpp_cmd_cfg_adec_params_wav)
+
+
+#define AUDPP_CMD_WAV_STEREO_CFG_MONO	0x0001
+#define AUDPP_CMD_WAV_STEREO_CFG_STEREO	0x0002
+
+#define AUDPP_CMD_WAV_PCM_WIDTH_8	0x0000
+#define AUDPP_CMD_WAV_PCM_WIDTH_16	0x0001
+#define AUDPP_CMD_WAV_PCM_WIDTH_32	0x0002
+
+typedef struct {
+	audpp_cmd_cfg_adec_params_common		common;
+	unsigned short					stereo_cfg;
+	unsigned short					pcm_width;
+	unsigned short 					sign;
+} __attribute__((packed)) audpp_cmd_cfg_adec_params_wav;
+
+/*
+ * Command Structure to configure Per decoder Parameters (ADPCM)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_ADPCM_LEN	\
+	sizeof(audpp_cmd_cfg_adec_params_adpcm)
+
+
+#define	AUDPP_CMD_ADPCM_STEREO_CFG_MONO		0x0001
+#define AUDPP_CMD_ADPCM_STEREO_CFG_STEREO	0x0002
+
+typedef struct {
+	audpp_cmd_cfg_adec_params_common		common;
+	unsigned short					stereo_cfg;
+	unsigned short 					block_size;
+} __attribute__((packed)) audpp_cmd_cfg_adec_params_adpcm;
+
+/*
+ * Command Structure to configure Per decoder Parameters (MP3)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_MP3_LEN	\
+	sizeof(audpp_cmd_cfg_adec_params_mp3)
+
+typedef struct {
+   audpp_cmd_cfg_adec_params_common    common;
+} __attribute__((packed)) audpp_cmd_cfg_adec_params_mp3;
+
+
+/*
+ * Command Structure to configure Per decoder Parameters (AAC)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_AAC_LEN	\
+	sizeof(audpp_cmd_cfg_adec_params_aac)
+
+
+#define AUDPP_CMD_AAC_FORMAT_ADTS		-1
+#define	AUDPP_CMD_AAC_FORMAT_RAW		0x0000
+#define	AUDPP_CMD_AAC_FORMAT_PSUEDO_RAW		0x0001
+#define	AUDPP_CMD_AAC_FORMAT_LOAS		0x0002
+
+#define AUDPP_CMD_AAC_AUDIO_OBJECT_LC		0x0002
+#define AUDPP_CMD_AAC_AUDIO_OBJECT_LTP		0x0004
+#define AUDPP_CMD_AAC_AUDIO_OBJECT_ERLC	0x0011
+
+#define AUDPP_CMD_AAC_SBR_ON_FLAG_ON		0x0001
+#define AUDPP_CMD_AAC_SBR_ON_FLAG_OFF		0x0000
+
+#define AUDPP_CMD_AAC_SBR_PS_ON_FLAG_ON		0x0001
+#define AUDPP_CMD_AAC_SBR_PS_ON_FLAG_OFF	0x0000
+
+typedef struct {
+  audpp_cmd_cfg_adec_params_common	common;
+  signed short				format;
+  unsigned short			audio_object;
+  unsigned short			ep_config;
+  unsigned short                        aac_section_data_resilience_flag;
+  unsigned short                        aac_scalefactor_data_resilience_flag;
+  unsigned short                        aac_spectral_data_resilience_flag;
+  unsigned short                        sbr_on_flag;
+  unsigned short                        sbr_ps_on_flag;
+  unsigned short                        dual_mono_mode;
+  unsigned short                        channel_configuration;
+} __attribute__((packed)) audpp_cmd_cfg_adec_params_aac;
+
+/*
+ * Command Structure to configure Per decoder Parameters (V13K)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_V13K_LEN	\
+	sizeof(struct audpp_cmd_cfg_adec_params_v13k)
+
+
+#define AUDPP_CMD_STEREO_CFG_MONO		0x0001
+#define AUDPP_CMD_STEREO_CFG_STEREO		0x0002
+
+struct audpp_cmd_cfg_adec_params_v13k {
+   audpp_cmd_cfg_adec_params_common    	common;
+   unsigned short			stereo_cfg;
+} __attribute__((packed));
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_EVRC_LEN \
+	sizeof(struct audpp_cmd_cfg_adec_params_evrc)
+
+struct audpp_cmd_cfg_adec_params_evrc {
+	audpp_cmd_cfg_adec_params_common common;
+	unsigned short stereo_cfg;
+} __attribute__ ((packed));
+
+/*
+ * Command Structure to configure the  HOST PCM interface
+ */
+
+#define AUDPP_CMD_PCM_INTF	0x0001
+#define AUDPP_CMD_PCM_INTF_2	0x0002
+#define AUDPP_CMD_PCM_INTF_LEN	sizeof(audpp_cmd_pcm_intf)
+
+#define AUDPP_CMD_PCM_INTF_MONO_V		        0x0001
+#define AUDPP_CMD_PCM_INTF_STEREO_V         	0x0002
+
+/* These two values differentiate the two types of commands that could be issued
+ * Interface configuration command and Buffer update command */
+
+#define AUDPP_CMD_PCM_INTF_CONFIG_CMD_V	       	0x0000
+#define AUDPP_CMD_PCM_INTF_BUFFER_CMD_V	        -1
+
+#define AUDPP_CMD_PCM_INTF_RX_ENA_M              0x000F
+#define AUDPP_CMD_PCM_INTF_RX_ENA_ARMTODSP_V     0x0008
+#define AUDPP_CMD_PCM_INTF_RX_ENA_DSPTOARM_V     0x0004
+
+/* These flags control the enabling and disabling of the interface together
+ *  with host interface bit mask. */
+
+#define AUDPP_CMD_PCM_INTF_ENA_V            -1
+#define AUDPP_CMD_PCM_INTF_DIS_V            0x0000
+
+
+#define  AUDPP_CMD_PCM_INTF_FULL_DUPLEX           0x0
+#define  AUDPP_CMD_PCM_INTF_HALF_DUPLEX_TODSP     0x1
+
+
+#define  AUDPP_CMD_PCM_INTF_OBJECT_NUM           0x5
+#define  AUDPP_CMD_PCM_INTF_COMMON_OBJECT_NUM    0x6
+
+
+typedef struct {
+	unsigned short  cmd_id;
+	unsigned short  object_num;
+	signed short  config;
+	unsigned short  intf_type;
+
+	/* DSP -> ARM Configuration */
+	unsigned short  read_buf1LSW;
+	unsigned short  read_buf1MSW;
+	unsigned short  read_buf1_len;
+
+	unsigned short  read_buf2LSW;
+	unsigned short  read_buf2MSW;
+	unsigned short  read_buf2_len;
+	/*   0:HOST_PCM_INTF disable
+	**  0xFFFF: HOST_PCM_INTF enable
+	*/
+	signed short  dsp_to_arm_flag;
+	unsigned short  partition_number;
+
+	/* ARM -> DSP Configuration */
+	unsigned short  write_buf1LSW;
+	unsigned short  write_buf1MSW;
+	unsigned short  write_buf1_len;
+
+	unsigned short  write_buf2LSW;
+	unsigned short  write_buf2MSW;
+	unsigned short  write_buf2_len;
+
+	/*   0:HOST_PCM_INTF disable
+	**  0xFFFF: HOST_PCM_INTF enable
+	*/
+	signed short  arm_to_rx_flag;
+	unsigned short  weight_decoder_to_rx;
+	unsigned short  weight_arm_to_rx;
+
+	unsigned short  partition_number_arm_to_dsp;
+	unsigned short  sample_rate;
+	unsigned short  channel_mode;
+} __attribute__((packed)) audpp_cmd_pcm_intf;
+
+/*
+ **  BUFFER UPDATE COMMAND
+ */
+#define AUDPP_CMD_PCM_INTF_SEND_BUF_PARAMS_LEN	\
+	sizeof(audpp_cmd_pcm_intf_send_buffer)
+
+typedef struct {
+  unsigned short  cmd_id;
+  unsigned short  host_pcm_object;
+  /* set config = 0xFFFF for configuration*/
+  signed short  config;
+  unsigned short  intf_type;
+  unsigned short  dsp_to_arm_buf_id;
+  unsigned short  arm_to_dsp_buf_id;
+  unsigned short  arm_to_dsp_buf_len;
+} __attribute__((packed)) audpp_cmd_pcm_intf_send_buffer;
+
+
+/*
+ * Commands Related to uPAudPPCmd3Queue
+ */
+
+/*
+ * Command Structure to configure post processing params (Commmon)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS		0x0000
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN		\
+	sizeof(audpp_cmd_cfg_object_params_common)
+
+#define AUDPP_CMD_OBJ0_UPDATE		0x8000
+#define AUDPP_CMD_OBJ0_DONT_UPDATE	0x0000
+
+#define AUDPP_CMD_OBJ1_UPDATE		0x8000
+#define AUDPP_CMD_OBJ1_DONT_UPDATE	0x0000
+
+#define AUDPP_CMD_OBJ2_UPDATE		0x8000
+#define AUDPP_CMD_OBJ2_DONT_UPDATE	0x0000
+
+#define AUDPP_CMD_OBJ3_UPDATE		0x8000
+#define AUDPP_CMD_OBJ3_DONT_UPDATE	0x0000
+
+#define AUDPP_CMD_OBJ4_UPDATE		0x8000
+#define AUDPP_CMD_OBJ4_DONT_UPDATE	0x0000
+
+#define AUDPP_CMD_HPCM_UPDATE		0x8000
+#define AUDPP_CMD_HPCM_DONT_UPDATE	0x0000
+
+#define AUDPP_CMD_COMMON_CFG_UPDATE		0x8000
+#define AUDPP_CMD_COMMON_CFG_DONT_UPDATE	0x0000
+
+typedef struct {
+	unsigned short  cmd_id;
+	unsigned short	obj0_cfg;
+	unsigned short	obj1_cfg;
+	unsigned short	obj2_cfg;
+	unsigned short	obj3_cfg;
+	unsigned short	obj4_cfg;
+	unsigned short	host_pcm_obj_cfg;
+	unsigned short	comman_cfg;
+	unsigned short  command_type;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_common;
+
+/*
+ * Command Structure to configure post processing params (Volume)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_VOLUME_LEN		\
+	sizeof(audpp_cmd_cfg_object_params_volume)
+
+typedef struct {
+	audpp_cmd_cfg_object_params_common 	common;
+	unsigned short					volume;
+	unsigned short					pan;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_volume;
+
+/*
+ * Command Structure to configure post processing params (PCM Filter) --DOUBT
+ */
+
+typedef struct {
+	unsigned short			numerator_b0_filter_lsw;
+	unsigned short			numerator_b0_filter_msw;
+	unsigned short			numerator_b1_filter_lsw;
+	unsigned short			numerator_b1_filter_msw;
+	unsigned short			numerator_b2_filter_lsw;
+	unsigned short			numerator_b2_filter_msw;
+} __attribute__((packed)) numerator;
+
+typedef struct {
+	unsigned short			denominator_a0_filter_lsw;
+	unsigned short			denominator_a0_filter_msw;
+	unsigned short			denominator_a1_filter_lsw;
+	unsigned short			denominator_a1_filter_msw;
+} __attribute__((packed)) denominator;
+
+typedef struct {
+	unsigned short			shift_factor_0;
+} __attribute__((packed)) shift_factor;
+
+typedef struct {
+	unsigned short			pan_filter_0;
+} __attribute__((packed)) pan;
+
+typedef struct {
+		numerator		numerator_filter;
+		denominator		denominator_filter;
+		shift_factor		shift_factor_filter;
+		pan			pan_filter;
+} __attribute__((packed)) filter_1;
+
+typedef struct {
+		numerator		numerator_filter[2];
+		denominator		denominator_filter[2];
+		shift_factor		shift_factor_filter[2];
+		pan			pan_filter[2];
+} __attribute__((packed)) filter_2;
+
+typedef struct {
+		numerator		numerator_filter[3];
+		denominator		denominator_filter[3];
+		shift_factor		shift_factor_filter[3];
+		pan			pan_filter[3];
+} __attribute__((packed)) filter_3;
+
+typedef struct {
+		numerator		numerator_filter[4];
+		denominator		denominator_filter[4];
+		shift_factor		shift_factor_filter[4];
+		pan			pan_filter[4];
+} __attribute__((packed)) filter_4;
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_PCM_LEN		\
+	sizeof(audpp_cmd_cfg_object_params_pcm)
+
+
+typedef struct {
+	audpp_cmd_cfg_object_params_common 	common;
+	unsigned short				active_flag;
+	unsigned short 				num_bands;
+	union {
+		filter_1			filter_1_params;
+		filter_2			filter_2_params;
+		filter_3			filter_3_params;
+		filter_4			filter_4_params;
+	} __attribute__((packed)) params_filter;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_pcm;
+
+
+/*
+ * Command Structure to configure post processing parameters (equalizer)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_EQALIZER_LEN		\
+	sizeof(audpp_cmd_cfg_object_params_eqalizer)
+
+typedef struct {
+	unsigned short			numerator_coeff_0_lsw;
+	unsigned short			numerator_coeff_0_msw;
+	unsigned short			numerator_coeff_1_lsw;
+	unsigned short			numerator_coeff_1_msw;
+	unsigned short			numerator_coeff_2_lsw;
+	unsigned short			numerator_coeff_2_msw;
+} __attribute__((packed)) eq_numerator;
+
+typedef struct {
+	unsigned short			denominator_coeff_0_lsw;
+	unsigned short			denominator_coeff_0_msw;
+	unsigned short			denominator_coeff_1_lsw;
+	unsigned short			denominator_coeff_1_msw;
+} __attribute__((packed)) eq_denominator;
+
+typedef struct {
+	unsigned short			shift_factor;
+} __attribute__((packed)) eq_shiftfactor;
+
+typedef struct {
+	eq_numerator	numerator;
+	eq_denominator	denominator;
+	eq_shiftfactor	shiftfactor;
+} __attribute__((packed)) eq_coeff_1;
+
+typedef struct {
+	eq_numerator	numerator[2];
+	eq_denominator	denominator[2];
+	eq_shiftfactor	shiftfactor[2];
+} __attribute__((packed)) eq_coeff_2;
+
+typedef struct {
+	eq_numerator	numerator[3];
+	eq_denominator	denominator[3];
+	eq_shiftfactor	shiftfactor[3];
+} __attribute__((packed)) eq_coeff_3;
+
+typedef struct {
+	eq_numerator	numerator[4];
+	eq_denominator	denominator[4];
+	eq_shiftfactor	shiftfactor[4];
+} __attribute__((packed)) eq_coeff_4;
+
+typedef struct {
+	eq_numerator	numerator[5];
+	eq_denominator	denominator[5];
+	eq_shiftfactor	shiftfactor[5];
+} __attribute__((packed)) eq_coeff_5;
+
+typedef struct {
+	eq_numerator	numerator[6];
+	eq_denominator	denominator[6];
+	eq_shiftfactor	shiftfactor[6];
+} __attribute__((packed)) eq_coeff_6;
+
+typedef struct {
+	eq_numerator	numerator[7];
+	eq_denominator	denominator[7];
+	eq_shiftfactor	shiftfactor[7];
+} __attribute__((packed)) eq_coeff_7;
+
+typedef struct {
+	eq_numerator	numerator[8];
+	eq_denominator	denominator[8];
+	eq_shiftfactor	shiftfactor[8];
+} __attribute__((packed)) eq_coeff_8;
+
+typedef struct {
+	eq_numerator	numerator[9];
+	eq_denominator	denominator[9];
+	eq_shiftfactor	shiftfactor[9];
+} __attribute__((packed)) eq_coeff_9;
+
+typedef struct {
+	eq_numerator	numerator[10];
+	eq_denominator	denominator[10];
+	eq_shiftfactor	shiftfactor[10];
+} __attribute__((packed)) eq_coeff_10;
+
+typedef struct {
+	eq_numerator	numerator[11];
+	eq_denominator	denominator[11];
+	eq_shiftfactor	shiftfactor[11];
+} __attribute__((packed)) eq_coeff_11;
+
+typedef struct {
+	eq_numerator	numerator[12];
+	eq_denominator	denominator[12];
+	eq_shiftfactor	shiftfactor[12];
+} __attribute__((packed)) eq_coeff_12;
+
+
+typedef struct {
+	audpp_cmd_cfg_object_params_common 	common;
+	unsigned short				eq_flag;
+	unsigned short				num_bands;
+	union {
+		eq_coeff_1	eq_coeffs_1;
+		eq_coeff_2	eq_coeffs_2;
+		eq_coeff_3	eq_coeffs_3;
+		eq_coeff_4	eq_coeffs_4;
+		eq_coeff_5	eq_coeffs_5;
+		eq_coeff_6	eq_coeffs_6;
+		eq_coeff_7	eq_coeffs_7;
+		eq_coeff_8	eq_coeffs_8;
+		eq_coeff_9	eq_coeffs_9;
+		eq_coeff_10	eq_coeffs_10;
+		eq_coeff_11	eq_coeffs_11;
+		eq_coeff_12	eq_coeffs_12;
+	} __attribute__((packed)) eq_coeff;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_eqalizer;
+
+
+/*
+ * Command Structure to configure post processing parameters (ADRC)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_ADRC_LEN		\
+	sizeof(audpp_cmd_cfg_object_params_adrc)
+
+
+#define AUDPP_CMD_ADRC_FLAG_DIS		0x0000
+#define AUDPP_CMD_ADRC_FLAG_ENA		-1
+
+typedef struct {
+	audpp_cmd_cfg_object_params_common 	common;
+	signed short				adrc_flag;
+	unsigned short				compression_th;
+	unsigned short				compression_slope;
+	unsigned short				rms_time;
+	unsigned short				attack_const_lsw;
+	unsigned short				attack_const_msw;
+	unsigned short				release_const_lsw;
+	unsigned short				release_const_msw;
+	unsigned short				adrc_system_delay;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_adrc;
+
+/*
+ * Command Structure to configure post processing parameters(Spectrum Analizer)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_SPECTRAM_LEN		\
+	sizeof(audpp_cmd_cfg_object_params_spectram)
+
+
+typedef struct {
+	audpp_cmd_cfg_object_params_common 	common;
+	unsigned short				sample_interval;
+	unsigned short				num_coeff;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_spectram;
+
+/*
+ * Command Structure to configure post processing parameters (QConcert)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_QCONCERT_LEN		\
+	sizeof(audpp_cmd_cfg_object_params_qconcert)
+
+
+#define AUDPP_CMD_QCON_ENA_FLAG_ENA		-1
+#define AUDPP_CMD_QCON_ENA_FLAG_DIS		0x0000
+
+#define AUDPP_CMD_QCON_OP_MODE_HEADPHONE	-1
+#define AUDPP_CMD_QCON_OP_MODE_SPEAKER_FRONT	0x0000
+#define AUDPP_CMD_QCON_OP_MODE_SPEAKER_SIDE	0x0001
+#define AUDPP_CMD_QCON_OP_MODE_SPEAKER_DESKTOP	0x0002
+
+#define AUDPP_CMD_QCON_GAIN_UNIT			0x7FFF
+#define AUDPP_CMD_QCON_GAIN_SIX_DB			0x4027
+
+
+#define AUDPP_CMD_QCON_EXPANSION_MAX		0x7FFF
+
+
+typedef struct {
+	audpp_cmd_cfg_object_params_common 	common;
+	signed short				enable_flag;
+	signed short				output_mode;
+	signed short				gain;
+	signed short				expansion;
+	signed short				delay;
+	unsigned short				stages_per_mode;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_qconcert;
+
+/*
+ * Command Structure to configure post processing parameters (Side Chain)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_SIDECHAIN_LEN		\
+	sizeof(audpp_cmd_cfg_object_params_sidechain)
+
+
+#define AUDPP_CMD_SIDECHAIN_ACTIVE_FLAG_DIS	0x0000
+#define AUDPP_CMD_SIDECHAIN_ACTIVE_FLAG_ENA	-1
+
+typedef struct {
+	audpp_cmd_cfg_object_params_common 	common;
+	signed short				active_flag;
+	unsigned short				num_bands;
+	union {
+		filter_1			filter_1_params;
+		filter_2			filter_2_params;
+		filter_3			filter_3_params;
+		filter_4			filter_4_params;
+	} __attribute__((packed)) params_filter;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_sidechain;
+
+
+/*
+ * Command Structure to configure post processing parameters (QAFX)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_QAFX_LEN		\
+	sizeof(audpp_cmd_cfg_object_params_qafx)
+
+#define AUDPP_CMD_QAFX_ENA_DISA		0x0000
+#define AUDPP_CMD_QAFX_ENA_ENA_CFG	-1
+#define AUDPP_CMD_QAFX_ENA_DIS_CFG	0x0001
+
+#define AUDPP_CMD_QAFX_CMD_TYPE_ENV	0x0100
+#define AUDPP_CMD_QAFX_CMD_TYPE_OBJ	0x0010
+#define AUDPP_CMD_QAFX_CMD_TYPE_QUERY	0x1000
+
+#define AUDPP_CMD_QAFX_CMDS_ENV_OP_MODE	0x0100
+#define AUDPP_CMD_QAFX_CMDS_ENV_LIS_POS	0x0101
+#define AUDPP_CMD_QAFX_CMDS_ENV_LIS_ORI	0x0102
+#define AUDPP_CMD_QAFX_CMDS_ENV_LIS_VEL	0X0103
+#define AUDPP_CMD_QAFX_CMDS_ENV_ENV_RES	0x0107
+
+#define AUDPP_CMD_QAFX_CMDS_OBJ_SAMP_FREQ	0x0010
+#define AUDPP_CMD_QAFX_CMDS_OBJ_VOL		0x0011
+#define AUDPP_CMD_QAFX_CMDS_OBJ_DIST		0x0012
+#define AUDPP_CMD_QAFX_CMDS_OBJ_POS		0x0013
+#define AUDPP_CMD_QAFX_CMDS_OBJ_VEL		0x0014
+
+
+typedef struct {
+	audpp_cmd_cfg_object_params_common 	common;
+	signed short				enable;
+	unsigned short				command_type;
+	unsigned short				num_commands;
+	unsigned short				commands;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_qafx;
+
+/*
+ * Command Structure to enable , disable or configure the reverberation effect
+ * (Common)
+ */
+
+#define AUDPP_CMD_REVERB_CONFIG		0x0001
+#define	AUDPP_CMD_REVERB_CONFIG_COMMON_LEN	\
+	sizeof(audpp_cmd_reverb_config_common)
+
+#define AUDPP_CMD_ENA_ENA	0xFFFF
+#define AUDPP_CMD_ENA_DIS	0x0000
+#define AUDPP_CMD_ENA_CFG	0x0001
+
+#define AUDPP_CMD_CMD_TYPE_ENV		0x0104
+#define AUDPP_CMD_CMD_TYPE_OBJ		0x0015
+#define AUDPP_CMD_CMD_TYPE_QUERY	0x1000
+
+
+typedef struct {
+	unsigned short			cmd_id;
+	unsigned short			enable;
+	unsigned short			cmd_type;
+} __attribute__((packed)) audpp_cmd_reverb_config_common;
+
+/*
+ * Command Structure to enable , disable or configure the reverberation effect
+ * (ENV-0x0104)
+ */
+
+#define	AUDPP_CMD_REVERB_CONFIG_ENV_104_LEN	\
+	sizeof(audpp_cmd_reverb_config_env_104)
+
+typedef struct {
+	audpp_cmd_reverb_config_common	common;
+	unsigned short			env_gain;
+	unsigned short			decay_msw;
+	unsigned short			decay_lsw;
+	unsigned short			decay_timeratio_msw;
+	unsigned short			decay_timeratio_lsw;
+	unsigned short			delay_time;
+	unsigned short			reverb_gain;
+	unsigned short			reverb_delay;
+} __attribute__((packed)) audpp_cmd_reverb_config_env_104;
+
+/*
+ * Command Structure to enable , disable or configure the reverberation effect
+ * (ENV-0x0015)
+ */
+
+#define	AUDPP_CMD_REVERB_CONFIG_ENV_15_LEN	\
+	sizeof(audpp_cmd_reverb_config_env_15)
+
+typedef struct {
+	audpp_cmd_reverb_config_common	common;
+	unsigned short			object_num;
+	unsigned short			absolute_gain;
+} __attribute__((packed)) audpp_cmd_reverb_config_env_15;
+
+
+#endif /* QDSP5AUDPPCMDI_H */
+
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audppmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audppmsg.h
new file mode 100644
index 0000000..44fea22
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audppmsg.h
@@ -0,0 +1,318 @@
+#ifndef QDSP5AUDPPMSG_H
+#define QDSP5AUDPPMSG_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+       Q D S P 5  A U D I O   P O S T   P R O C E S S I N G   M S G
+
+GENERAL DESCRIPTION
+  Messages sent by AUDPPTASK to ARM
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2009 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+ $Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audppmsg.h#4 $
+
+===========================================================================*/
+
+/*
+ * AUDPPTASK uses audPPuPRlist to send messages to the ARM
+ * Location : MEMA
+ * Buffer Size : 45
+ * No of Buffers in a queue : 5 for gaming audio and 1 for other images
+ */
+
+/*
+ * MSG to Informs the ARM os Success/Failure of bringing up the decoder
+ */
+
+#define AUDPP_MSG_STATUS_MSG		0x0001
+#define AUDPP_MSG_STATUS_MSG_LEN	\
+	sizeof(audpp_msg_status_msg)
+
+#define AUDPP_MSG_STATUS_SLEEP		0x0000
+#define AUDPP_MSG__STATUS_INIT		0x0001
+#define AUDPP_MSG_MSG_STATUS_CFG	0x0002
+#define AUDPP_MSG_STATUS_PLAY		0x0003
+
+#define AUDPP_MSG_REASON_MIPS	0x0000
+#define AUDPP_MSG_REASON_MEM	0x0001
+
+typedef struct{
+	unsigned short dec_id;
+	unsigned short status;
+	unsigned short reason;
+} __attribute__((packed)) audpp_msg_status_msg;
+
+/*
+ * MSG to communicate the spectrum analyzer output bands to the ARM
+ */
+#define AUDPP_MSG_SPA_BANDS		0x0002
+#define AUDPP_MSG_SPA_BANDS_LEN	\
+	sizeof(audpp_msg_spa_bands)
+
+typedef struct {
+	unsigned short			current_object;
+	unsigned short			spa_band_1;
+	unsigned short			spa_band_2;
+	unsigned short			spa_band_3;
+	unsigned short			spa_band_4;
+	unsigned short			spa_band_5;
+	unsigned short			spa_band_6;
+	unsigned short			spa_band_7;
+	unsigned short			spa_band_8;
+	unsigned short			spa_band_9;
+	unsigned short			spa_band_10;
+	unsigned short			spa_band_11;
+	unsigned short			spa_band_12;
+	unsigned short			spa_band_13;
+	unsigned short			spa_band_14;
+	unsigned short			spa_band_15;
+	unsigned short			spa_band_16;
+	unsigned short			spa_band_17;
+	unsigned short			spa_band_18;
+	unsigned short			spa_band_19;
+	unsigned short			spa_band_20;
+	unsigned short			spa_band_21;
+	unsigned short			spa_band_22;
+	unsigned short			spa_band_23;
+	unsigned short			spa_band_24;
+	unsigned short			spa_band_25;
+	unsigned short			spa_band_26;
+	unsigned short			spa_band_27;
+	unsigned short			spa_band_28;
+	unsigned short			spa_band_29;
+	unsigned short			spa_band_30;
+	unsigned short			spa_band_31;
+	unsigned short			spa_band_32;
+} __attribute__((packed)) audpp_msg_spa_bands;
+
+/*
+ * MSG to communicate the PCM I/O buffer status to ARM
+ */
+#define  AUDPP_MSG_HOST_PCM_INTF_MSG		0x0003
+#define  AUDPP_MSG_HOST_PCM_INTF_MSG_LEN	\
+	sizeof(audpp_msg_host_pcm_intf_msg)
+
+#define AUDPP_MSG_HOSTPCM_ID_TX_ARM	0x0000
+#define AUDPP_MSG_HOSTPCM_ID_ARM_TX	0x0001
+#define AUDPP_MSG_HOSTPCM_ID_RX_ARM	0x0002
+#define AUDPP_MSG_HOSTPCM_ID_ARM_RX	0x0003
+
+#define AUDPP_MSG_SAMP_FREQ_INDX_96000	0x0000
+#define AUDPP_MSG_SAMP_FREQ_INDX_88200	0x0001
+#define AUDPP_MSG_SAMP_FREQ_INDX_64000	0x0002
+#define AUDPP_MSG_SAMP_FREQ_INDX_48000	0x0003
+#define AUDPP_MSG_SAMP_FREQ_INDX_44100	0x0004
+#define AUDPP_MSG_SAMP_FREQ_INDX_32000	0x0005
+#define AUDPP_MSG_SAMP_FREQ_INDX_24000	0x0006
+#define AUDPP_MSG_SAMP_FREQ_INDX_22050	0x0007
+#define AUDPP_MSG_SAMP_FREQ_INDX_16000	0x0008
+#define AUDPP_MSG_SAMP_FREQ_INDX_12000	0x0009
+#define AUDPP_MSG_SAMP_FREQ_INDX_11025	0x000A
+#define AUDPP_MSG_SAMP_FREQ_INDX_8000	0x000B
+
+#define AUDPP_MSG_CHANNEL_MODE_MONO		0x0001
+#define AUDPP_MSG_CHANNEL_MODE_STEREO	0x0002
+
+typedef struct{
+	unsigned short obj_num;
+	unsigned short numbers_of_samples;
+	unsigned short host_pcm_id;
+	unsigned short buf_indx;
+	unsigned short samp_freq_indx;
+	unsigned short channel_mode;
+} __attribute__((packed)) audpp_msg_host_pcm_intf_msg;
+
+
+/*
+ * MSG to communicate 3D position of the source and listener , source volume
+ * source rolloff, source orientation
+ */
+
+#define AUDPP_MSG_QAFX_POS		0x0004
+#define AUDPP_MSG_QAFX_POS_LEN		\
+	sizeof(audpp_msg_qafx_pos)
+
+typedef struct {
+	unsigned short	current_object;
+	unsigned short	x_pos_lis_msw;
+	unsigned short	x_pos_lis_lsw;
+	unsigned short	y_pos_lis_msw;
+	unsigned short	y_pos_lis_lsw;
+	unsigned short	z_pos_lis_msw;
+	unsigned short	z_pos_lis_lsw;
+	unsigned short	x_fwd_msw;
+	unsigned short	x_fwd_lsw;
+	unsigned short	y_fwd_msw;
+	unsigned short	y_fwd_lsw;
+	unsigned short	z_fwd_msw;
+	unsigned short	z_fwd_lsw;
+	unsigned short 	x_up_msw;
+	unsigned short	x_up_lsw;
+	unsigned short 	y_up_msw;
+	unsigned short	y_up_lsw;
+	unsigned short 	z_up_msw;
+	unsigned short	z_up_lsw;
+	unsigned short 	x_vel_lis_msw;
+	unsigned short 	x_vel_lis_lsw;
+	unsigned short 	y_vel_lis_msw;
+	unsigned short 	y_vel_lis_lsw;
+	unsigned short 	z_vel_lis_msw;
+	unsigned short 	z_vel_lis_lsw;
+	unsigned short	threed_enable_flag;
+	unsigned short 	volume;
+	unsigned short	x_pos_source_msw;
+	unsigned short	x_pos_source_lsw;
+	unsigned short	y_pos_source_msw;
+	unsigned short	y_pos_source_lsw;
+	unsigned short	z_pos_source_msw;
+	unsigned short	z_pos_source_lsw;
+	unsigned short	max_dist_0_msw;
+	unsigned short	max_dist_0_lsw;
+	unsigned short	min_dist_0_msw;
+	unsigned short	min_dist_0_lsw;
+	unsigned short	roll_off_factor;
+	unsigned short	mute_after_max_flag;
+	unsigned short	x_vel_source_msw;
+	unsigned short	x_vel_source_lsw;
+	unsigned short	y_vel_source_msw;
+	unsigned short	y_vel_source_lsw;
+	unsigned short	z_vel_source_msw;
+	unsigned short	z_vel_source_lsw;
+} __attribute__((packed)) audpp_msg_qafx_pos;
+
+/*
+ * MSG to provide AVSYNC feedback from DSP to ARM
+ */
+
+#define AUDPP_MSG_AVSYNC_MSG		0x0005
+#define AUDPP_MSG_AVSYNC_MSG_LEN	\
+	sizeof(audpp_msg_avsync_msg)
+
+typedef struct {
+	unsigned short	active_flag;
+	unsigned short	num_samples_counter0_HSW;
+	unsigned short	num_samples_counter0_MSW;
+	unsigned short	num_samples_counter0_LSW;
+	unsigned short	num_bytes_counter0_HSW;
+	unsigned short	num_bytes_counter0_MSW;
+	unsigned short	num_bytes_counter0_LSW;
+	unsigned short	samp_freq_obj_0;
+	unsigned short	samp_freq_obj_1;
+	unsigned short	samp_freq_obj_2;
+	unsigned short	samp_freq_obj_3;
+	unsigned short	samp_freq_obj_4;
+	unsigned short	samp_freq_obj_5;
+	unsigned short	samp_freq_obj_6;
+	unsigned short	samp_freq_obj_7;
+	unsigned short	samp_freq_obj_8;
+	unsigned short	samp_freq_obj_9;
+	unsigned short	samp_freq_obj_10;
+	unsigned short	samp_freq_obj_11;
+	unsigned short	samp_freq_obj_12;
+	unsigned short	samp_freq_obj_13;
+	unsigned short	samp_freq_obj_14;
+	unsigned short	samp_freq_obj_15;
+	unsigned short	num_samples_counter4_HSW;
+	unsigned short	num_samples_counter4_MSW;
+	unsigned short	num_samples_counter4_LSW;
+	unsigned short	num_bytes_counter4_HSW;
+	unsigned short	num_bytes_counter4_MSW;
+	unsigned short	num_bytes_counter4_LSW;
+} __attribute__((packed)) audpp_msg_avsync_msg;
+
+/*
+ * MSG to provide PCM DMA Missed feedback from the DSP to ARM
+ */
+
+#define  AUDPP_MSG_PCMDMAMISSED	0x0006
+#define  AUDPP_MSG_PCMDMAMISSED_LEN	\
+	sizeof(audpp_msg_pcmdmamissed);
+
+typedef struct{
+	/*
+	** Bit 0	0 = PCM DMA not missed for object 0
+	**        1 = PCM DMA missed for object0
+	** Bit 1	0 = PCM DMA not missed for object 1
+	**        1 = PCM DMA missed for object1
+	** Bit 2	0 = PCM DMA not missed for object 2
+	**        1 = PCM DMA missed for object2
+	** Bit 3	0 = PCM DMA not missed for object 3
+	**        1 = PCM DMA missed for object3
+	** Bit 4	0 = PCM DMA not missed for object 4
+	**        1 = PCM DMA missed for object4
+	*/
+	unsigned short pcmdmamissed;
+} __attribute__((packed)) audpp_msg_pcmdmamissed;
+
+/*
+ * MSG to AUDPP enable or disable feedback form DSP to ARM
+ */
+
+#define AUDPP_MSG_CFG_MSG	0x0007
+#define AUDPP_MSG_CFG_MSG_LEN	\
+    sizeof(audpp_msg_cfg_msg)
+
+#define AUDPP_MSG_ENA_ENA	0xFFFF
+#define AUDPP_MSG_ENA_DIS	0x0000
+
+typedef struct{
+	/*   Enabled  - 0xffff
+	**  Disabled - 0
+	*/
+	unsigned short enabled;
+} __attribute__((packed)) audpp_msg_cfg_msg;
+
+/*
+ * MSG to communicate the reverb  per object volume
+ */
+
+#define AUDPP_MSG_QREVERB_VOLUME	0x0008
+#define AUDPP_MSG_QREVERB_VOLUME_LEN	\
+	sizeof(audpp_msg_qreverb_volume)
+
+
+typedef struct {
+	unsigned short	obj_0_gain;
+	unsigned short	obj_1_gain;
+	unsigned short	obj_2_gain;
+	unsigned short	obj_3_gain;
+	unsigned short	obj_4_gain;
+	unsigned short	hpcm_obj_volume;
+} __attribute__((packed)) audpp_msg_qreverb_volume;
+
+#define AUDPP_MSG_ROUTING_ACK 0x0009
+#define AUDPP_MSG_ROUTING_ACK_LEN \
+  sizeof(struct audpp_msg_routing_ack)
+
+struct audpp_msg_routing_ack {
+	unsigned short dec_id;
+	unsigned short routing_mode;
+} __attribute__((packed));
+
+#define AUDPP_MSG_FLUSH_ACK 0x000A
+
+#endif /* QDSP5AUDPPMSG_H */
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreproccmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreproccmdi.h
new file mode 100644
index 0000000..06d33d5
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreproccmdi.h
@@ -0,0 +1,256 @@
+#ifndef QDSP5AUDPREPROCCMDI_H
+#define QDSP5AUDPREPROCCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    A U D I O   P R E   P R O C E S S I N G  I N T E R N A L  C O M M A N D S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of commands
+  that are accepted by AUDPREPROC Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audpreproccmdi.h#2 $
+
+===========================================================================*/
+
+/*
+ * AUDIOPREPROC COMMANDS:
+ * ARM uses uPAudPreProcCmdQueue to communicate with AUDPREPROCTASK
+ * Location : MEMB
+ * Buffer size : 51
+ * Number of buffers in a queue : 3
+ */
+
+/*
+ * Command to configure the parameters of AGC
+ */
+
+#define	AUDPREPROC_CMD_CFG_AGC_PARAMS	0x0000
+#define	AUDPREPROC_CMD_CFG_AGC_PARAMS_LEN	\
+	sizeof(audpreproc_cmd_cfg_agc_params)
+
+#define	AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_SLOPE	0x0009
+#define	AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_TH	0x000A
+#define	AUDPREPROC_CMD_TX_AGC_PARAM_MASK_EXP_SLOPE	0x000B
+#define	AUDPREPROC_CMD_TX_AGC_PARAM_MASK_EXP_TH		0x000C
+#define	AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_AIG_FLAG		0x000D
+#define	AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_STATIC_GAIN	0x000E
+#define	AUDPREPROC_CMD_TX_AGC_PARAM_MASK_TX_AGC_ENA_FLAG	0x000F
+
+#define	AUDPREPROC_CMD_TX_AGC_ENA_FLAG_ENA	-1
+#define	AUDPREPROC_CMD_TX_AGC_ENA_FLAG_DIS	0x0000
+
+#define	AUDPREPROC_CMD_ADP_GAIN_FLAG_ENA_ADP_GAIN	-1
+#define	AUDPREPROC_CMD_ADP_GAIN_FLAG_ENA_STATIC_GAIN	0x0000
+
+#define	AUDPREPROC_CMD_PARAM_MASK_RMS_TAY	0x0004
+#define	AUDPREPROC_CMD_PARAM_MASK_RELEASEK	0x0005
+#define	AUDPREPROC_CMD_PARAM_MASK_DELAY		0x0006
+#define	AUDPREPROC_CMD_PARAM_MASK_ATTACKK	0x0007
+#define	AUDPREPROC_CMD_PARAM_MASK_LEAKRATE_SLOW	0x0008
+#define	AUDPREPROC_CMD_PARAM_MASK_LEAKRATE_FAST	0x0009
+#define	AUDPREPROC_CMD_PARAM_MASK_AIG_RELEASEK 	0x000A
+#define	AUDPREPROC_CMD_PARAM_MASK_AIG_MIN	0x000B
+#define	AUDPREPROC_CMD_PARAM_MASK_AIG_MAX	0x000C
+#define	AUDPREPROC_CMD_PARAM_MASK_LEAK_UP	0x000D
+#define	AUDPREPROC_CMD_PARAM_MASK_LEAK_DOWN	0x000E
+#define	AUDPREPROC_CMD_PARAM_MASK_AIG_ATTACKK	0x000F
+
+typedef struct {
+	unsigned short	cmd_id;
+	unsigned short	tx_agc_param_mask;
+	unsigned short	tx_agc_enable_flag;
+	unsigned short	static_gain;
+	signed short	adaptive_gain_flag;
+	unsigned short	expander_th;
+	unsigned short	expander_slope;
+	unsigned short	compressor_th;
+	unsigned short	compressor_slope;
+	unsigned short	param_mask;
+	unsigned short	aig_attackk;
+	unsigned short	aig_leak_down;
+	unsigned short	aig_leak_up;
+	unsigned short	aig_max;
+	unsigned short	aig_min;
+	unsigned short	aig_releasek;
+	unsigned short	aig_leakrate_fast;
+	unsigned short	aig_leakrate_slow;
+	unsigned short	attackk_msw;
+	unsigned short	attackk_lsw;
+	unsigned short	delay;
+	unsigned short	releasek_msw;
+	unsigned short	releasek_lsw;
+	unsigned short	rms_tav;
+} __attribute__((packed)) audpreproc_cmd_cfg_agc_params;
+
+
+/*
+ * Command to configure the params of Advanved AGC
+ */
+
+#define	AUDPREPROC_CMD_CFG_AGC_PARAMS_2		0x0001
+#define	AUDPREPROC_CMD_CFG_AGC_PARAMS_2_LEN		\
+	sizeof(audpreproc_cmd_cfg_agc_params_2)
+
+#define	AUDPREPROC_CMD_2_TX_AGC_ENA_FLAG_ENA	-1;
+#define	AUDPREPROC_CMD_2_TX_AGC_ENA_FLAG_DIS	0x0000;
+
+typedef struct {
+	unsigned short	cmd_id;
+	unsigned short	agc_param_mask;
+	signed short	tx_agc_enable_flag;
+	unsigned short	comp_static_gain;
+	unsigned short	exp_th;
+	unsigned short	exp_slope;
+	unsigned short	comp_th;
+	unsigned short	comp_slope;
+	unsigned short	comp_rms_tav;
+	unsigned short	comp_samp_mask;
+	unsigned short	comp_attackk_msw;
+	unsigned short	comp_attackk_lsw;
+	unsigned short	comp_releasek_msw;
+	unsigned short	comp_releasek_lsw;
+	unsigned short	comp_delay;
+	unsigned short	comp_makeup_gain;
+} __attribute__((packed)) audpreproc_cmd_cfg_agc_params_2;
+
+/*
+ * Command to configure params for ns
+ */
+
+#define	AUDPREPROC_CMD_CFG_NS_PARAMS		0x0002
+#define	AUDPREPROC_CMD_CFG_NS_PARAMS_LEN	\
+	sizeof(audpreproc_cmd_cfg_ns_params)
+
+#define	AUDPREPROC_CMD_EC_MODE_NEW_NLMS_ENA	0x0001
+#define	AUDPREPROC_CMD_EC_MODE_NEW_NLMS_DIS 	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_DES_ENA	0x0002
+#define	AUDPREPROC_CMD_EC_MODE_NEW_DES_DIS	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_NS_ENA	0x0004
+#define	AUDPREPROC_CMD_EC_MODE_NEW_NS_DIS	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_CNI_ENA	0x0008
+#define	AUDPREPROC_CMD_EC_MODE_NEW_CNI_DIS	0x0000
+
+#define	AUDPREPROC_CMD_EC_MODE_NEW_NLES_ENA	0x0010
+#define	AUDPREPROC_CMD_EC_MODE_NEW_NLES_DIS	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_HB_ENA	0x0020
+#define	AUDPREPROC_CMD_EC_MODE_NEW_HB_DIS	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_VA_ENA	0x0040
+#define	AUDPREPROC_CMD_EC_MODE_NEW_VA_DIS	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_PCD_ENA	0x0080
+#define	AUDPREPROC_CMD_EC_MODE_NEW_PCD_DIS	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_FEHI_ENA	0x0100
+#define	AUDPREPROC_CMD_EC_MODE_NEW_FEHI_DIS 	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_NEHI_ENA	0x0200
+#define	AUDPREPROC_CMD_EC_MODE_NEW_NEHI_DIS 	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_NLPP_ENA	0x0400
+#define	AUDPREPROC_CMD_EC_MODE_NEW_NLPP_DIS	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_FNE_ENA	0x0800
+#define	AUDPREPROC_CMD_EC_MODE_NEW_FNE_DIS	0x0000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_PRENLMS_ENA 	0x1000
+#define	AUDPREPROC_CMD_EC_MODE_NEW_PRENLMS_DIS 	0x0000
+
+typedef struct {
+	unsigned short	cmd_id;
+	unsigned short	ec_mode_new;
+	unsigned short	dens_gamma_n;
+	unsigned short	dens_nfe_block_size;
+	unsigned short	dens_limit_ns;
+	unsigned short	dens_limit_ns_d;
+	unsigned short	wb_gamma_e;
+	unsigned short	wb_gamma_n;
+} __attribute__((packed)) audpreproc_cmd_cfg_ns_params;
+
+/*
+ * Command to configure parameters for IIR tuning filter
+ */
+
+#define	AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS		0x0003
+#define	AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS_LEN	\
+	sizeof(audpreproc_cmd_cfg_iir_tuning_filter_params)
+
+#define	AUDPREPROC_CMD_IIR_ACTIVE_FLAG_DIS	0x0000
+#define	AUDPREPROC_CMD_IIR_ACTIVE_FLAG_ENA	0x0001
+
+typedef struct {
+	unsigned short	cmd_id;
+	unsigned short	active_flag;
+	unsigned short	num_bands;
+	unsigned short	numerator_coeff_b0_filter0_lsw;
+	unsigned short	numerator_coeff_b0_filter0_msw;
+	unsigned short	numerator_coeff_b1_filter0_lsw;
+	unsigned short	numerator_coeff_b1_filter0_msw;
+	unsigned short	numerator_coeff_b2_filter0_lsw;
+	unsigned short	numerator_coeff_b2_filter0_msw;
+	unsigned short	numerator_coeff_b0_filter1_lsw;
+	unsigned short	numerator_coeff_b0_filter1_msw;
+	unsigned short	numerator_coeff_b1_filter1_lsw;
+	unsigned short	numerator_coeff_b1_filter1_msw;
+	unsigned short	numerator_coeff_b2_filter1_lsw;
+	unsigned short	numerator_coeff_b2_filter1_msw;
+	unsigned short	numerator_coeff_b0_filter2_lsw;
+	unsigned short	numerator_coeff_b0_filter2_msw;
+	unsigned short	numerator_coeff_b1_filter2_lsw;
+	unsigned short	numerator_coeff_b1_filter2_msw;
+	unsigned short	numerator_coeff_b2_filter2_lsw;
+	unsigned short	numerator_coeff_b2_filter2_msw;
+	unsigned short	numerator_coeff_b0_filter3_lsw;
+	unsigned short	numerator_coeff_b0_filter3_msw;
+	unsigned short	numerator_coeff_b1_filter3_lsw;
+	unsigned short	numerator_coeff_b1_filter3_msw;
+	unsigned short	numerator_coeff_b2_filter3_lsw;
+	unsigned short	numerator_coeff_b2_filter3_msw;
+	unsigned short 	denominator_coeff_a0_filter0_lsw;
+	unsigned short 	denominator_coeff_a0_filter0_msw;
+	unsigned short 	denominator_coeff_a1_filter0_lsw;
+	unsigned short 	denominator_coeff_a1_filter0_msw;
+	unsigned short 	denominator_coeff_a0_filter1_lsw;
+	unsigned short 	denominator_coeff_a0_filter1_msw;
+	unsigned short 	denominator_coeff_a1_filter1_lsw;
+	unsigned short 	denominator_coeff_a1_filter1_msw;
+  unsigned short 	denominator_coeff_a0_filter2_lsw;
+	unsigned short 	denominator_coeff_a0_filter2_msw;
+	unsigned short 	denominator_coeff_a1_filter2_lsw;
+	unsigned short 	denominator_coeff_a1_filter2_msw;
+  unsigned short 	denominator_coeff_a0_filter3_lsw;
+	unsigned short 	denominator_coeff_a0_filter3_msw;
+	unsigned short 	denominator_coeff_a1_filter3_lsw;
+	unsigned short 	denominator_coeff_a1_filter3_msw;
+
+	unsigned short	shift_factor_filter0;
+	unsigned short	shift_factor_filter1;
+	unsigned short	shift_factor_filter2;
+	unsigned short	shift_factor_filter3;
+
+	unsigned short	channel_selected0;
+	unsigned short	channel_selected1;
+	unsigned short	channel_selected2;
+	unsigned short	channel_selected3;
+} __attribute__((packed))audpreproc_cmd_cfg_iir_tuning_filter_params;
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreprocmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreprocmsg.h
new file mode 100644
index 0000000..f40e41e
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreprocmsg.h
@@ -0,0 +1,85 @@
+#ifndef QDSP5AUDPREPROCMSG_H
+#define QDSP5AUDPREPROCMSG_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    A U D I O   P R E   P R O C E S S I N G  M E S S A G E S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of messages
+  that are rcvd by AUDPREPROC Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+ $Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audpreprocmsg.h#3 $
+
+===========================================================================*/
+
+/*
+ * ADSPREPROCTASK Messages
+ * AUDPREPROCTASK uses audPreProcUpRlist to communicate with ARM
+ * Location	: MEMA
+ * Message Length  : 2
+ */
+
+/*
+ * Message to indicate particular feature has been enabled or disabled
+ */
+
+
+#define	AUDPREPROC_MSG_CMD_CFG_DONE_MSG	0x0000
+#define	AUDPREPROC_MSG_CMD_CFG_DONE_MSG_LEN	\
+	sizeof(audpreproc_msg_cmd_cfg_done_msg)
+
+#define	AUDPREPROC_MSG_TYPE_AGC			0x0000
+#define	AUDPREPROC_MSG_TYPE_NOISE_REDUCTION	0x0001
+#define	AUDPREPROC_MSG_TYPE_IIR_FILTER		0x0002
+
+
+#define	AUDPREPROC_MSG_STATUS_FLAG_ENA		-1
+#define	AUDPREPROC_MSG_STATUS_FLAG_DIS		0x0000
+
+typedef struct {
+	unsigned short	type;
+	signed short	status_flag;
+} __attribute__((packed)) audpreproc_msg_cmd_cfg_done_msg;
+
+
+/*
+ * Message to indicate particular feature has selected for wrong samp freq
+ */
+
+#define	AUDPREPROC_MSG_ERROR_MSG_ID		0x0001
+#define	AUDPREPROC_MSG_ERROR_MSG_ID_LEN	\
+	sizeof(audpreproc_msg_error_msg_id)
+
+#define	AUDPREPROC_MSG_ERR_INDEX_NS		0x0000
+
+typedef struct {
+	 unsigned short	err_index;
+} __attribute__((packed)) audpreproc_msg_error_msg_id;
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audreccmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audreccmdi.h
new file mode 100644
index 0000000..d03ee02
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audreccmdi.h
@@ -0,0 +1,176 @@
+#ifndef QDSP5AUDRECCMDI_H
+#define QDSP5AUDRECCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    A U D I O   R E C O R D  I N T E R N A L  C O M M A N D S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of commands
+  that are accepted by AUDREC Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+ $Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audreccmdi.h#3 $
+
+============================================================================*/
+
+/*
+ * AUDRECTASK COMMANDS
+ * ARM uses 2 queues to communicate with the AUDRECTASK
+ * 1.uPAudRecCmdQueue
+ * Location :MEMC
+ * Buffer Size : 8
+ * No of Buffers in a queue : 3
+ * 2.audRecUpBitStreamQueue
+ * Location : MEMC
+ * Buffer Size : 4
+ * No of buffers in a queue : 2
+ */
+
+/*
+ * Commands on uPAudRecCmdQueue
+ */
+
+/*
+ * Command to initiate and terminate the audio recording section
+ */
+
+#define AUDREC_CMD_CFG		0x0000
+#define	AUDREC_CMD_CFG_LEN	sizeof(audrec_cmd_cfg)
+
+#define	AUDREC_CMD_TYPE_0_INDEX_WAV	0x0000
+#define	AUDREC_CMD_TYPE_0_INDEX_AAC	0x0001
+
+#define AUDREC_CMD_TYPE_0_ENA		0x4000
+#define AUDREC_CMD_TYPE_0_DIS		0x0000
+
+#define AUDREC_CMD_TYPE_0_NOUPDATE	0x0000
+#define AUDREC_CMD_TYPE_0_UPDATE	0x8000
+
+#define	AUDREC_CMD_TYPE_1_INDEX_SBC	0x0002
+
+#define AUDREC_CMD_TYPE_1_ENA		0x4000
+#define AUDREC_CMD_TYPE_1_DIS		0x0000
+
+#define AUDREC_CMD_TYPE_1_NOUPDATE	0x0000
+#define AUDREC_CMD_TYPE_1_UPDATE	0x8000
+
+typedef struct {
+	unsigned short 	cmd_id;
+	unsigned short	type_0;
+	unsigned short	type_1;
+} __attribute__((packed)) audrec_cmd_cfg;
+
+
+/*
+ * Command to configure the recording parameters for RecType0(AAC/WAV) encoder
+ */
+
+#define	AUDREC_CMD_AREC0PARAM_CFG	0x0001
+#define	AUDREC_CMD_AREC0PARAM_CFG_LEN	\
+	sizeof(audrec_cmd_arec0param_cfg)
+
+#define	AUDREC_CMD_SAMP_RATE_INDX_8000		0x000B
+#define	AUDREC_CMD_SAMP_RATE_INDX_11025		0x000A
+#define	AUDREC_CMD_SAMP_RATE_INDX_12000		0x0009
+#define	AUDREC_CMD_SAMP_RATE_INDX_16000		0x0008
+#define	AUDREC_CMD_SAMP_RATE_INDX_22050		0x0007
+#define	AUDREC_CMD_SAMP_RATE_INDX_24000		0x0006
+#define	AUDREC_CMD_SAMP_RATE_INDX_32000		0x0005
+#define	AUDREC_CMD_SAMP_RATE_INDX_44100		0x0004
+#define	AUDREC_CMD_SAMP_RATE_INDX_48000		0x0003
+
+#define AUDREC_CMD_STEREO_MODE_MONO		0x0000
+#define AUDREC_CMD_STEREO_MODE_STEREO		0x0001
+
+typedef struct {
+	unsigned short 	cmd_id;
+	unsigned short	ptr_to_extpkt_buffer_msw;
+	unsigned short	ptr_to_extpkt_buffer_lsw;
+	unsigned short	buf_len;
+	unsigned short	samp_rate_index;
+	unsigned short	stereo_mode;
+	unsigned short 	rec_quality;
+} __attribute__((packed)) audrec_cmd_arec0param_cfg;
+
+/*
+ * Command to configure the recording parameters for RecType1(SBC) encoder
+ */
+
+#define AUDREC_CMD_AREC1PARAM_CFG	0x0002
+#define AUDREC_CMD_AREC1PARAM_CFG_LEN	\
+	sizeof(audrec_cmd_arec1param_cfg)
+
+#define AUDREC_CMD_PARAM_BUF_BLOCKS_4	0x0000
+#define AUDREC_CMD_PARAM_BUF_BLOCKS_8	0x0001
+#define AUDREC_CMD_PARAM_BUF_BLOCKS_12	0x0002
+#define AUDREC_CMD_PARAM_BUF_BLOCKS_16	0x0003
+
+#define AUDREC_CMD_PARAM_BUF_SUB_BANDS_8	0x0010
+#define AUDREC_CMD_PARAM_BUF_MODE_MONO		0x0000
+#define AUDREC_CMD_PARAM_BUF_MODE_DUAL		0x0040
+#define AUDREC_CMD_PARAM_BUF_MODE_STEREO	0x0050
+#define AUDREC_CMD_PARAM_BUF_MODE_JSTEREO	0x0060
+#define AUDREC_CMD_PARAM_BUF_LOUDNESS		0x0000
+#define AUDREC_CMD_PARAM_BUF_SNR		0x0100
+#define AUDREC_CMD_PARAM_BUF_BASIC_VER		0x0000
+
+typedef struct {
+	unsigned short 	cmd_id;
+	unsigned short	ptr_to_extpkt_buffer_msw;
+	unsigned short	ptr_to_extpkt_buffer_lsw;
+	unsigned short	buf_len;
+	unsigned short	param_buf;
+	unsigned short	bit_rate_0;
+	unsigned short	bit_rate_1;
+} __attribute__((packed)) audrec_cmd_arec1param_cfg;
+
+
+/*
+ * Commands on audRecUpBitStreamQueue
+ */
+
+/*
+ * Command to indicate the current packet read count
+ */
+
+#define AUDREC_CMD_PACKET_EXT_PTR		0x0000
+#define AUDREC_CMD_PACKET_EXT_PTR_LEN	\
+	sizeof(audrec_cmd_packet_ext_ptr)
+
+#define AUDREC_CMD_TYPE_0	0x0000
+#define AUDREC_CMD_TYPE_1	0x0001
+
+typedef struct {
+	unsigned short  cmd_id;
+	unsigned short	type;
+	unsigned short 	curr_rec_count_msw;
+	unsigned short 	curr_rec_count_lsw;
+} __attribute__((packed)) audrec_cmd_packet_ext_ptr;
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audrecmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audrecmsg.h
new file mode 100644
index 0000000..bb6eb50
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audrecmsg.h
@@ -0,0 +1,127 @@
+#ifndef QDSP5AUDRECMSGI_H
+#define QDSP5AUDRECMSGI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    A U D I O   R E C O R D  M E S S A G E S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of messages
+  that are sent by AUDREC Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+ $Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audrecmsg.h#3 $
+
+============================================================================*/
+
+/*
+ * AUDRECTASK MESSAGES
+ * AUDRECTASK uses audRecUpRlist to communicate with ARM
+ * Location : MEMC
+ * Buffer size : 4
+ * No of buffers in a queue : 2
+ */
+
+/*
+ * Message to notify that config command is done
+ */
+
+#define AUDREC_MSG_CMD_CFG_DONE_MSG	0x0002
+#define AUDREC_MSG_CMD_CFG_DONE_MSG_LEN	\
+	sizeof(audrec_msg_cmd_cfg_done_msg)
+
+
+#define AUDREC_MSG_CFG_DONE_TYPE_0_ENA		0x4000
+#define AUDREC_MSG_CFG_DONE_TYPE_0_DIS		0x0000
+
+#define AUDREC_MSG_CFG_DONE_TYPE_0_NO_UPDATE	0x0000
+#define AUDREC_MSG_CFG_DONE_TYPE_0_UPDATE	0x8000
+
+#define AUDREC_MSG_CFG_DONE_TYPE_1_ENA		0x4000
+#define AUDREC_MSG_CFG_DONE_TYPE_1_DIS		0x0000
+
+#define AUDREC_MSG_CFG_DONE_TYPE_1_NO_UPDATE	0x0000
+#define AUDREC_MSG_CFG_DONE_TYPE_1_UPDATE	0x8000
+
+typedef struct {
+	unsigned short	type_0;
+	unsigned short	type_1;
+} __attribute__((packed))audrec_msg_cmd_cfg_done_msg;
+
+
+/*
+ * Message to notify arec0/1 cfg done and recording params revd by task
+ */
+
+#define	AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG		0x0003
+#define	AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG_LEN	\
+	sizeof(audrec_msg_cmd_arec_param_cfg_done_msg)
+
+#define	AUDREC_MSG_AREC_PARAM_TYPE_0	0x0000
+#define	AUDREC_MSG_AREC_PARAM_TYPE_1	0x0001
+
+typedef struct {
+	unsigned short	type;
+} __attribute__((packed))audrec_msg_cmd_arec_param_cfg_done_msg;
+
+
+/*
+ * Message to notify no more buffers are available in ext mem to DME
+ */
+
+#define AUDREC_MSG_FATAL_ERR_MSG		0x0004
+#define AUDREC_MSG_FATAL_ERR_MSG_LEN	\
+	sizeof(audrec_msg_fatal_err_msg)
+
+#define AUDREC_MSG_FATAL_ERR_TYPE_0	0x0000
+#define AUDREC_MSG_FATAL_ERR_TYPE_1	0x0001
+
+typedef struct {
+	unsigned short	type;
+} __attribute__((packed))audrec_msg_fatal_err_msg;
+
+/*
+ * Message to notify DME deliverd the encoded pkt to ext pkt buffer
+ */
+
+#define AUDREC_MSG_PACKET_READY_MSG		0x0005
+#define AUDREC_MSG_PACKET_READY_MSG_LEN	\
+	sizeof(audrec_msg_packet_ready_msg)
+
+#define AUDREC_MSG_PACKET_READY_TYPE_0	0x0000
+#define AUDREC_MSG_PACKET_READY_TYPE_1	0x0001
+
+typedef struct {
+	unsigned short	type;
+	unsigned short	pkt_counter_msw;
+	unsigned short	pkt_counter_lsw;
+	unsigned short	pkt_read_cnt_msw;
+	unsigned short	pkt_read_cnt_lsw;
+} __attribute__((packed))audrec_msg_packet_ready_msg;
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegcmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegcmdi.h
new file mode 100644
index 0000000..574ad6b
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegcmdi.h
@@ -0,0 +1,376 @@
+#ifndef QDSP5VIDJPEGCMDI_H
+#define QDSP5VIDJPEGCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    J P E G  I N T E R N A L  C O M M A N D S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of commands
+  that are accepted by JPEG Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5jpegcmdi.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+when       who     what, where, why
+--------   ---     ----------------------------------------------------------
+06/09/08   sv      initial version
+===========================================================================*/
+
+/*
+ * ARM to JPEG configuration commands are passed through the
+ * uPJpegCfgCmdQueue
+ */
+
+/*
+ * Command to configure JPEG Encoder
+ */
+
+#define	JPEG_CMD_ENC_CFG		0x0000
+#define	JPEG_CMD_ENC_CFG_LEN	sizeof(jpeg_cmd_enc_cfg)
+
+#define	JPEG_CMD_ENC_PROCESS_CFG_OP_ROTATION_0		0x0000
+#define	JPEG_CMD_ENC_PROCESS_CFG_OP_ROTATION_90		0x0100
+#define	JPEG_CMD_ENC_PROCESS_CFG_OP_ROTATION_180	0x0200
+#define	JPEG_CMD_ENC_PROCESS_CFG_OP_ROTATION_270	0x0300
+#define	JPEG_CMD_ENC_PROCESS_CFG_IP_DATA_FORMAT_M	0x0003
+#define	JPEG_CMD_ENC_PROCESS_CFG_IP_DATA_FORMAT_H2V2	0x0000
+#define	JPEG_CMD_ENC_PROCESS_CFG_IP_DATA_FORMAT_H2V1	0x0001
+#define	JPEG_CMD_ENC_PROCESS_CFG_IP_DATA_FORMAT_H1V2	0x0002
+
+#define	JPEG_CMD_IP_SIZE_CFG_LUMA_HEIGHT_M		0x0000FFFF
+#define	JPEG_CMD_IP_SIZE_CFG_LUMA_WIDTH_M		0xFFFF0000
+#define	JPEG_CMD_ENC_UPSAMP_IP_SIZE_CFG_ENA		0x0001
+#define	JPEG_CMD_ENC_UPSAMP_IP_SIZE_CFG_DIS		0x0000
+
+#define	JPEG_CMD_FRAG_SIZE_LUMA_HEIGHT_M		0xFFFF
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	process_cfg;
+	unsigned int	ip_size_cfg;
+	unsigned int	op_size_cfg;
+	unsigned int	frag_cfg;
+	unsigned int	frag_cfg_part[16];
+
+	unsigned int    part_num;
+
+	unsigned int	op_buf_0_cfg_part1;
+	unsigned int	op_buf_0_cfg_part2;
+	unsigned int	op_buf_1_cfg_part1;
+	unsigned int	op_buf_1_cfg_part2;
+
+	unsigned int	luma_qunt_table[32];
+	unsigned int	chroma_qunt_table[32];
+
+	unsigned int	upsamp_ip_size_cfg;
+	unsigned int	upsamp_ip_frame_off;
+	unsigned int	upsamp_pp_filter_coeff[64];
+} __attribute__((packed)) jpeg_cmd_enc_cfg;
+
+/*
+ * Command to configure JPEG Decoder
+ */
+
+#define	JPEG_CMD_DEC_CFG		0x0001
+#define	JPEG_CMD_DEC_CFG_LEN		sizeof(jpeg_cmd_dec_cfg)
+
+#define	JPEG_CMD_DEC_OP_DATA_FORMAT_M		0x0001
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_H2V2	0x0000
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_H2V1	0x0001
+
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_SCALE_FACTOR_8	0x000000
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_SCALE_FACTOR_4	0x010000
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_SCALE_FACTOR_2	0x020000
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_SCALE_FACTOR_1	0x030000
+
+#define	JPEG_CMD_DEC_IP_STREAM_BUF_CFG_PART3_NOT_FINAL	0x0000
+#define	JPEG_CMD_DEC_IP_STREAM_BUF_CFG_PART3_FINAL	0x0001
+
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	img_dimension_cfg;
+	unsigned int	op_data_format;
+	unsigned int	restart_interval;
+	unsigned int	ip_buf_partition_num;
+	unsigned int	ip_stream_buf_cfg_part1;
+	unsigned int	ip_stream_buf_cfg_part2;
+	unsigned int	ip_stream_buf_cfg_part3;
+	unsigned int	op_stream_buf_0_cfg_part1;
+	unsigned int	op_stream_buf_0_cfg_part2;
+	unsigned int	op_stream_buf_0_cfg_part3;
+	unsigned int	op_stream_buf_1_cfg_part1;
+	unsigned int	op_stream_buf_1_cfg_part2;
+	unsigned int	op_stream_buf_1_cfg_part3;
+	unsigned int	luma_qunt_table_0_3;
+	unsigned int	luma_qunt_table_4_7;
+	unsigned int	luma_qunt_table_8_11;
+	unsigned int	luma_qunt_table_12_15;
+	unsigned int	luma_qunt_table_16_19;
+	unsigned int	luma_qunt_table_20_23;
+	unsigned int	luma_qunt_table_24_27;
+	unsigned int	luma_qunt_table_28_31;
+	unsigned int	luma_qunt_table_32_35;
+	unsigned int	luma_qunt_table_36_39;
+	unsigned int	luma_qunt_table_40_43;
+	unsigned int	luma_qunt_table_44_47;
+	unsigned int	luma_qunt_table_48_51;
+	unsigned int	luma_qunt_table_52_55;
+	unsigned int	luma_qunt_table_56_59;
+	unsigned int	luma_qunt_table_60_63;
+	unsigned int	chroma_qunt_table_0_3;
+	unsigned int	chroma_qunt_table_4_7;
+	unsigned int	chroma_qunt_table_8_11;
+	unsigned int	chroma_qunt_table_12_15;
+	unsigned int	chroma_qunt_table_16_19;
+	unsigned int	chroma_qunt_table_20_23;
+	unsigned int	chroma_qunt_table_24_27;
+	unsigned int	chroma_qunt_table_28_31;
+	unsigned int	chroma_qunt_table_32_35;
+	unsigned int	chroma_qunt_table_36_39;
+	unsigned int	chroma_qunt_table_40_43;
+	unsigned int	chroma_qunt_table_44_47;
+	unsigned int	chroma_qunt_table_48_51;
+	unsigned int	chroma_qunt_table_52_55;
+	unsigned int	chroma_qunt_table_56_59;
+	unsigned int	chroma_qunt_table_60_63;
+	unsigned int	luma_dc_hm_code_cnt_table_0_3;
+	unsigned int	luma_dc_hm_code_cnt_table_4_7;
+	unsigned int	luma_dc_hm_code_cnt_table_8_11;
+	unsigned int	luma_dc_hm_code_cnt_table_12_15;
+	unsigned int	luma_dc_hm_code_val_table_0_3;
+	unsigned int	luma_dc_hm_code_val_table_4_7;
+	unsigned int	luma_dc_hm_code_val_table_8_11;
+	unsigned int	chroma_dc_hm_code_cnt_table_0_3;
+	unsigned int	chroma_dc_hm_code_cnt_table_4_7;
+	unsigned int	chroma_dc_hm_code_cnt_table_8_11;
+	unsigned int	chroma_dc_hm_code_cnt_table_12_15;
+	unsigned int	chroma_dc_hm_code_val_table_0_3;
+	unsigned int	chroma_dc_hm_code_val_table_4_7;
+	unsigned int	chroma_dc_hm_code_val_table_8_11;
+	unsigned int	luma_ac_hm_code_cnt_table_0_3;
+	unsigned int	luma_ac_hm_code_cnt_table_4_7;
+	unsigned int	luma_ac_hm_code_cnt_table_8_11;
+	unsigned int	luma_ac_hm_code_cnt_table_12_15;
+	unsigned int	luma_ac_hm_code_val_table_0_3;
+	unsigned int	luma_ac_hm_code_val_table_4_7;
+	unsigned int	luma_ac_hm_code_val_table_8_11;
+	unsigned int	luma_ac_hm_code_val_table_12_15;
+	unsigned int	luma_ac_hm_code_val_table_16_19;
+	unsigned int	luma_ac_hm_code_val_table_20_23;
+	unsigned int	luma_ac_hm_code_val_table_24_27;
+	unsigned int	luma_ac_hm_code_val_table_28_31;
+	unsigned int	luma_ac_hm_code_val_table_32_35;
+	unsigned int	luma_ac_hm_code_val_table_36_39;
+	unsigned int	luma_ac_hm_code_val_table_40_43;
+	unsigned int	luma_ac_hm_code_val_table_44_47;
+	unsigned int	luma_ac_hm_code_val_table_48_51;
+	unsigned int	luma_ac_hm_code_val_table_52_55;
+	unsigned int	luma_ac_hm_code_val_table_56_59;
+	unsigned int	luma_ac_hm_code_val_table_60_63;
+	unsigned int	luma_ac_hm_code_val_table_64_67;
+	unsigned int	luma_ac_hm_code_val_table_68_71;
+	unsigned int	luma_ac_hm_code_val_table_72_75;
+	unsigned int	luma_ac_hm_code_val_table_76_79;
+	unsigned int	luma_ac_hm_code_val_table_80_83;
+	unsigned int	luma_ac_hm_code_val_table_84_87;
+	unsigned int	luma_ac_hm_code_val_table_88_91;
+	unsigned int	luma_ac_hm_code_val_table_92_95;
+	unsigned int	luma_ac_hm_code_val_table_96_99;
+	unsigned int	luma_ac_hm_code_val_table_100_103;
+	unsigned int	luma_ac_hm_code_val_table_104_107;
+	unsigned int	luma_ac_hm_code_val_table_108_111;
+	unsigned int	luma_ac_hm_code_val_table_112_115;
+	unsigned int	luma_ac_hm_code_val_table_116_119;
+	unsigned int	luma_ac_hm_code_val_table_120_123;
+	unsigned int	luma_ac_hm_code_val_table_124_127;
+	unsigned int	luma_ac_hm_code_val_table_128_131;
+	unsigned int	luma_ac_hm_code_val_table_132_135;
+	unsigned int	luma_ac_hm_code_val_table_136_139;
+	unsigned int	luma_ac_hm_code_val_table_140_143;
+	unsigned int	luma_ac_hm_code_val_table_144_147;
+	unsigned int	luma_ac_hm_code_val_table_148_151;
+	unsigned int	luma_ac_hm_code_val_table_152_155;
+	unsigned int	luma_ac_hm_code_val_table_156_159;
+	unsigned int	luma_ac_hm_code_val_table_160_161;
+	unsigned int	chroma_ac_hm_code_cnt_table_0_3;
+	unsigned int	chroma_ac_hm_code_cnt_table_4_7;
+	unsigned int	chroma_ac_hm_code_cnt_table_8_11;
+	unsigned int	chroma_ac_hm_code_cnt_table_12_15;
+	unsigned int	chroma_ac_hm_code_val_table_0_3;
+	unsigned int	chroma_ac_hm_code_val_table_4_7;
+	unsigned int	chroma_ac_hm_code_val_table_8_11;
+	unsigned int	chroma_ac_hm_code_val_table_12_15;
+	unsigned int	chroma_ac_hm_code_val_table_16_19;
+	unsigned int	chroma_ac_hm_code_val_table_20_23;
+	unsigned int	chroma_ac_hm_code_val_table_24_27;
+	unsigned int	chroma_ac_hm_code_val_table_28_31;
+	unsigned int	chroma_ac_hm_code_val_table_32_35;
+	unsigned int	chroma_ac_hm_code_val_table_36_39;
+	unsigned int	chroma_ac_hm_code_val_table_40_43;
+	unsigned int	chroma_ac_hm_code_val_table_44_47;
+	unsigned int	chroma_ac_hm_code_val_table_48_51;
+	unsigned int	chroma_ac_hm_code_val_table_52_55;
+	unsigned int	chroma_ac_hm_code_val_table_56_59;
+	unsigned int	chroma_ac_hm_code_val_table_60_63;
+	unsigned int	chroma_ac_hm_code_val_table_64_67;
+	unsigned int	chroma_ac_hm_code_val_table_68_71;
+	unsigned int	chroma_ac_hm_code_val_table_72_75;
+	unsigned int	chroma_ac_hm_code_val_table_76_79;
+	unsigned int	chroma_ac_hm_code_val_table_80_83;
+	unsigned int	chroma_ac_hm_code_val_table_84_87;
+	unsigned int	chroma_ac_hm_code_val_table_88_91;
+	unsigned int	chroma_ac_hm_code_val_table_92_95;
+	unsigned int	chroma_ac_hm_code_val_table_96_99;
+	unsigned int	chroma_ac_hm_code_val_table_100_103;
+	unsigned int	chroma_ac_hm_code_val_table_104_107;
+	unsigned int	chroma_ac_hm_code_val_table_108_111;
+	unsigned int	chroma_ac_hm_code_val_table_112_115;
+	unsigned int	chroma_ac_hm_code_val_table_116_119;
+	unsigned int	chroma_ac_hm_code_val_table_120_123;
+	unsigned int	chroma_ac_hm_code_val_table_124_127;
+	unsigned int	chroma_ac_hm_code_val_table_128_131;
+	unsigned int	chroma_ac_hm_code_val_table_132_135;
+	unsigned int	chroma_ac_hm_code_val_table_136_139;
+	unsigned int	chroma_ac_hm_code_val_table_140_143;
+	unsigned int	chroma_ac_hm_code_val_table_144_147;
+	unsigned int	chroma_ac_hm_code_val_table_148_151;
+	unsigned int	chroma_ac_hm_code_val_table_152_155;
+	unsigned int	chroma_ac_hm_code_val_table_156_159;
+	unsigned int	chroma_ac_hm_code_val_table_160_161;
+} __attribute__((packed)) jpeg_cmd_dec_cfg;
+
+
+/*
+ * ARM to JPEG configuration commands are passed through the
+ * uPJpegActionCmdQueue
+ */
+
+/*
+ * Command to start the encode process
+ */
+
+#define	JPEG_CMD_ENC_ENCODE		0x0000
+#define	JPEG_CMD_ENC_ENCODE_LEN		sizeof(jpeg_cmd_enc_encode)
+
+
+typedef struct {
+	unsigned short	cmd_id;
+} __attribute__((packed)) jpeg_cmd_enc_encode;
+
+
+/*
+ * Command to transition from current state of encoder to IDLE state
+ */
+
+#define	JPEG_CMD_ENC_IDLE		0x0001
+#define	JPEG_CMD_ENC_IDLE_LEN		sizeof(jpeg_cmd_enc_idle)
+
+
+typedef struct {
+	unsigned short	cmd_id;
+} __attribute__((packed)) jpeg_cmd_enc_idle;
+
+
+/*
+ * Command to inform the encoder that another buffer is ready
+ */
+
+#define	JPEG_CMD_ENC_OP_CONSUMED	0x0002
+#define	JPEG_CMD_ENC_OP_CONSUMED_LEN	sizeof(jpeg_cmd_enc_op_consumed)
+
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	op_buf_addr;
+	unsigned int	op_buf_size;
+} __attribute__((packed)) jpeg_cmd_enc_op_consumed;
+
+
+/*
+ * Command to start the decoding process
+ */
+
+#define	JPEG_CMD_DEC_DECODE		0x0003
+#define	JPEG_CMD_DEC_DECODE_LEN	sizeof(jpeg_cmd_dec_decode)
+
+
+typedef struct {
+	unsigned short	cmd_id;
+} __attribute__((packed)) jpeg_cmd_dec_decode;
+
+
+/*
+ * Command to transition from the current state of decoder to IDLE
+ */
+
+#define	JPEG_CMD_DEC_IDLE	0x0004
+#define	JPEG_CMD_DEC_IDLE_LEN	sizeof(jpeg_cmd_dec_idle)
+
+
+typedef struct {
+	unsigned short	cmd_id;
+} __attribute__((packed)) jpeg_cmd_dec_idle;
+
+
+/*
+ * Command to inform that an op buffer is ready for use
+ */
+
+#define	JPEG_CMD_DEC_OP_CONSUMED	0x0005
+#define	JPEG_CMD_DEC_OP_CONSUMED_LEN	sizeof(jpeg_cmd_dec_op_consumed)
+
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	luma_op_buf_addr;
+	unsigned int	luma_op_buf_size;
+	unsigned int	chroma_op_buf_addr;
+} __attribute__((packed)) jpeg_cmd_dec_op_consumed;
+
+
+/*
+ * Command to pass a new ip buffer to the jpeg decoder
+ */
+
+#define	JPEG_CMD_DEC_IP	0x0006
+#define	JPEG_CMD_DEC_IP_LEN	sizeof(jpeg_cmd_dec_ip_len)
+
+#define	JPEG_CMD_EOI_INDICATOR_NOT_END	0x0000
+#define	JPEG_CMD_EOI_INDICATOR_END	0x0001
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	ip_buf_addr;
+	unsigned int	ip_buf_size;
+	unsigned int	eoi_indicator;
+} __attribute__((packed)) jpeg_cmd_dec_ip;
+
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegmsg.h
new file mode 100644
index 0000000..d11aa3f
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegmsg.h
@@ -0,0 +1,177 @@
+#ifndef QDSP5VIDJPEGMSGI_H
+#define QDSP5VIDJPEGMSGI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+   J P E G  I N T E R N A L  M E S S A G E S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of messages
+  that are sent by JPEG Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5jpegmsg.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when       who     what, where, why
+--------   ---     ----------------------------------------------------------
+05/10/08   sv      initial version
+===========================================================================*/
+
+/*
+ * Messages from JPEG task to ARM through jpeguPMsgQueue
+ */
+
+/*
+ * Message is ACK for CMD_JPEGE_ENCODE cmd
+ */
+
+#define	JPEG_MSG_ENC_ENCODE_ACK	0x0000
+#define	JPEG_MSG_ENC_ENCODE_ACK_LEN	\
+	sizeof(jpeg_msg_enc_encode_ack)
+
+typedef struct {
+} __attribute__((packed)) jpeg_msg_enc_encode_ack;
+
+
+/*
+ * Message informs the up when op buffer is ready for consumption and
+ * when encoding is complete or errors
+ */
+
+#define	JPEG_MSG_ENC_OP_PRODUCED	0x0001
+#define	JPEG_MSG_ENC_OP_PRODUCED_LEN	\
+	sizeof(jpeg_msg_enc_op_produced)
+
+#define	JPEG_MSGOP_OP_BUF_STATUS_ENC_DONE_PROGRESS	0x0000
+#define	JPEG_MSGOP_OP_BUF_STATUS_ENC_DONE_COMPLETE	0x0001
+#define	JPEG_MSGOP_OP_BUF_STATUS_ENC_ERR		0x10000
+
+typedef struct {
+	unsigned int	op_buf_addr;
+	unsigned int	op_buf_size;
+	unsigned int	op_buf_status;
+} __attribute__((packed)) jpeg_msg_enc_op_produced;
+
+
+/*
+ * Message to ack CMD_JPEGE_IDLE
+ */
+
+#define	JPEG_MSG_ENC_IDLE_ACK	0x0002
+#define	JPEG_MSG_ENC_IDLE_ACK_LEN	sizeof(jpeg_msg_enc_idle_ack)
+
+
+typedef struct {
+} __attribute__ ((packed)) jpeg_msg_enc_idle_ack;
+
+
+/*
+ * Message to indicate the illegal command
+ */
+
+#define	JPEG_MSG_ENC_ILLEGAL_COMMAND	0x0003
+#define	JPEG_MSG_ENC_ILLEGAL_COMMAND_LEN	\
+	sizeof(jpeg_msg_enc_illegal_command)
+
+typedef struct {
+	unsigned int	status;
+} __attribute__((packed)) jpeg_msg_enc_illegal_command;
+
+
+/*
+ * Message to ACK CMD_JPEGD_DECODE
+ */
+
+#define	JPEG_MSG_DEC_DECODE_ACK		0x0004
+#define	JPEG_MSG_DEC_DECODE_ACK_LEN	\
+	sizeof(jpeg_msg_dec_decode_ack)
+
+
+typedef struct {
+} __attribute__((packed)) jpeg_msg_dec_decode_ack;
+
+
+/*
+ * Message to inform up that an op buffer is ready for consumption and when
+ * decoding is complete or an error occurs
+ */
+
+#define	JPEG_MSG_DEC_OP_PRODUCED		0x0005
+#define	JPEG_MSG_DEC_OP_PRODUCED_LEN	\
+	sizeof(jpeg_msg_dec_op_produced)
+
+#define	JPEG_MSG_DEC_OP_BUF_STATUS_PROGRESS	0x0000
+#define	JPEG_MSG_DEC_OP_BUF_STATUS_DONE		0x0001
+
+typedef struct {
+	unsigned int	luma_op_buf_addr;
+	unsigned int	chroma_op_buf_addr;
+	unsigned int	num_mcus;
+	unsigned int	op_buf_status;
+} __attribute__((packed)) jpeg_msg_dec_op_produced;
+
+/*
+ * Message to ack CMD_JPEGD_IDLE cmd
+ */
+
+#define	JPEG_MSG_DEC_IDLE_ACK	0x0006
+#define	JPEG_MSG_DEC_IDLE_ACK_LEN	sizeof(jpeg_msg_dec_idle_ack)
+
+
+typedef struct {
+} __attribute__((packed)) jpeg_msg_dec_idle_ack;
+
+
+/*
+ * Message to indicate illegal cmd was received
+ */
+
+#define	JPEG_MSG_DEC_ILLEGAL_COMMAND	0x0007
+#define	JPEG_MSG_DEC_ILLEGAL_COMMAND_LEN	\
+	sizeof(jpeg_msg_dec_illegal_command)
+
+
+typedef struct {
+	unsigned int	status;
+} __attribute__((packed)) jpeg_msg_dec_illegal_command;
+
+/*
+ * Message to request up for the next segment of ip bit stream
+ */
+
+#define	JPEG_MSG_DEC_IP_REQUEST		0x0008
+#define	JPEG_MSG_DEC_IP_REQUEST_LEN	\
+	sizeof(jpeg_msg_dec_ip_request)
+
+
+typedef struct {
+} __attribute__((packed)) jpeg_msg_dec_ip_request;
+
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmcmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmcmdi.h
new file mode 100644
index 0000000..6c76e2c
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmcmdi.h
@@ -0,0 +1,82 @@
+#ifndef QDSP5LPMCMDI_H
+#define QDSP5LPMCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    L P M   I N T E R N A L   C O M M A N D S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of commands
+  that are accepted by LPM Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5lpmcmdi.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when       who     what, where, why
+--------   ---     ----------------------------------------------------------
+06/12/08   sv      initial version
+===========================================================================*/
+
+
+/*
+ * Command to start LPM processing based on the config params
+ */
+
+#define	LPM_CMD_START		0x0000
+#define	LPM_CMD_START_LEN	sizeof(lpm_cmd_start)
+
+#define	LPM_CMD_SPATIAL_FILTER_PART_OPMODE_0	0x00000000
+#define	LPM_CMD_SPATIAL_FILTER_PART_OPMODE_1	0x00010000
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	ip_data_cfg_part1;
+	unsigned int	ip_data_cfg_part2;
+	unsigned int	ip_data_cfg_part3;
+	unsigned int	ip_data_cfg_part4;
+	unsigned int	op_data_cfg_part1;
+	unsigned int	op_data_cfg_part2;
+	unsigned int	op_data_cfg_part3;
+	unsigned int	spatial_filter_part[32];
+} __attribute__((packed)) lpm_cmd_start;
+
+
+
+/*
+ * Command to stop LPM processing
+ */
+
+#define	LPM_CMD_IDLE		0x0001
+#define	LPM_CMD_IDLE_LEN	sizeof(lpm_cmd_idle)
+
+typedef struct {
+	unsigned int	cmd_id;
+} __attribute__((packed)) lpm_cmd_idle;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmmsg.h
new file mode 100644
index 0000000..3d1039d
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmmsg.h
@@ -0,0 +1,80 @@
+#ifndef QDSP5LPMMSGI_H
+#define QDSP5LPMMSGI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    L P M   I N T E R N A L   M E S S A G E S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of commands
+  that are accepted by LPM Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5lpmmsg.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when       who     what, where, why
+--------   ---     ----------------------------------------------------------
+06/12/08   sv      initial version
+===========================================================================*/
+
+/*
+ * Message to acknowledge CMD_LPM_IDLE command
+ */
+
+#define	LPM_MSG_IDLE_ACK	0x0000
+#define	LPM_MSG_IDLE_ACK_LEN	sizeof(lpm_msg_idle_ack)
+
+typedef struct {
+} __attribute__((packed)) lpm_msg_idle_ack;
+
+
+/*
+ * Message to acknowledge CMD_LPM_START command
+ */
+
+
+#define	LPM_MSG_START_ACK	0x0001
+#define	LPM_MSG_START_ACK_LEN	sizeof(lpm_msg_start_ack)
+
+
+typedef struct {
+} __attribute__((packed)) lpm_msg_start_ack;
+
+
+/*
+ * Message to notify the ARM that LPM processing is complete
+ */
+
+#define	LPM_MSG_DONE		0x0002
+#define	LPM_MSG_DONE_LEN	sizeof(lpm_msg_done)
+
+typedef struct {
+} __attribute__((packed)) lpm_msg_done;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5vdeccmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5vdeccmdi.h
new file mode 100644
index 0000000..3a32ee9
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5vdeccmdi.h
@@ -0,0 +1,235 @@
+#ifndef QDSP5VIDDECCMDI_H
+#define QDSP5VIDDECCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    V I D E O  D E C O D E R  I N T E R N A L  C O M M A N D S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of commands
+  that are accepted by VIDDEC Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5vdeccmdi.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when       who     what, where, why
+--------   ---     ----------------------------------------------------------
+05/10/08   ac      initial version
+===========================================================================*/
+
+
+/*
+ * Command to inform VIDDEC that new subframe packet is ready
+ */
+
+#define	VIDDEC_CMD_SUBFRAME_PKT		0x0000
+#define	VIDDEC_CMD_SUBFRAME_PKT_LEN \
+	sizeof(viddec_cmd_subframe_pkt)
+
+#define	VIDDEC_CMD_SF_INFO_1_DM_DMA_STATS_EXCHANGE_FLAG_DM		0x0000
+#define	VIDDEC_CMD_SF_INFO_1_DM_DMA_STATS_EXCHANGE_FLAG_DMA 	0x0001
+
+#define	VIDDEC_CMD_SF_INFO_0_SUBFRAME_CONTI		0x0000
+#define	VIDDEC_CMD_SF_INFO_0_SUBFRAME_FIRST		0x0001
+#define	VIDDEC_CMD_SF_INFO_0_SUBFRAME_LAST		0x0002
+#define	VIDDEC_CMD_SF_INFO_0_SUBFRAME_FIRST_AND_LAST 	0x0003
+
+#define	VIDDEC_CMD_CODEC_SELECTION_WORD_MPEG_4		0x0000
+#define	VIDDEC_CMD_CODEC_SELECTION_WORD_H_263_P0	0x0001
+#define	VIDDEC_CMD_CODEC_SELECTION_WORD_H_264		0x0002
+#define	VIDDEC_CMD_CODEC_SELECTION_WORD_H_263_p3	0x0003
+#define	VIDDEC_CMD_CODEC_SELECTION_WORD_RV9		0x0004
+#define	VIDDEC_CMD_CODEC_SELECTION_WORD_WMV9		0x0005
+#define	VIDDEC_CMD_CODEC_SELECTION_WORD_SMCDB		0x0006
+#define	VIDDEC_CMD_CODEC_SELECTION_WORD_QFRE		0x0007
+#define	VIDDEC_CMD_CODEC_SELECTION_WORD_VLD		0x0008
+
+typedef struct {
+	unsigned short	cmd_id;
+	unsigned short	packet_seq_number;
+	unsigned short	codec_instance_id;
+	unsigned short	subframe_packet_size_high;
+	unsigned short	subframe_packet_size_low;
+	unsigned short	subframe_packet_high;
+	unsigned short	subframe_packet_low;
+	unsigned short	subframe_packet_partition;
+	unsigned short	statistics_packet_size_high;
+	unsigned short	statistics_packet_size_low;
+	unsigned short	statistics_packet_high;
+	unsigned short	statistics_packet_low;
+	unsigned short	statistics_partition;
+	unsigned short	subframe_info_1;
+	unsigned short	subframe_info_0;
+	unsigned short	codec_selection_word;
+	unsigned short	num_mbs;
+} __attribute__((packed)) viddec_cmd_subframe_pkt;
+
+
+/*
+ * Command to inform VIDDEC task that post processing is required for the frame
+ */
+
+#define	VIDDEC_CMD_PP_ENABLE		0x0001
+#define	VIDDEC_CMD_PP_ENABLE_LEN \
+	sizeof(viddec_cmd_pp_enable)
+
+#define	VIDDEC_CMD_PP_INFO_0_DM_DMA_LS_EXCHANGE_FLAG_DM		0x0000
+#define	VIDDEC_CMD_PP_INFO_0_DM_DMA_LS_EXCHANGE_FLAG_DMA	0x0001
+
+typedef struct {
+	unsigned short	cmd_id;
+	unsigned short	packet_seq_num;
+	unsigned short	codec_instance_id;
+	unsigned short	postproc_info_0;
+	unsigned short	codec_selection_word;
+	unsigned short	pp_output_addr_high;
+	unsigned short	pp_output_addr_low;
+	unsigned short	postproc_info_1;
+	unsigned short	load_sharing_packet_size_high;
+	unsigned short	load_sharing_packet_size_low;
+	unsigned short	load_sharing_packet_high;
+	unsigned short	load_sharing_packet_low;
+	unsigned short	load_sharing_partition;
+	unsigned short	pp_param_0;
+	unsigned short	pp_param_1;
+	unsigned short	pp_param_2;
+	unsigned short	pp_param_3;
+} __attribute__((packed)) viddec_cmd_pp_enable;
+
+
+/*
+ * FRAME Header Packet : It is at the start of new frame
+ */
+
+#define	VIDDEC_CMD_FRAME_HEADER_PACKET	0x0002
+#define	VIDDEC_CMD_FRAME_HEADER_PACKET_LEN	\
+	sizeof(viddec_cmd_frame_header_packet)
+
+#define	VIDDEC_CMD_FRAME_INFO_0_ERROR_SKIP	0x0000
+#define	VIDDEC_CMD_FRAME_INFO_0_ERROR_BLACK	0x0800
+
+typedef struct {
+	unsigned short	packet_id;
+	unsigned short	x_dimension;
+	unsigned short	y_dimension;
+	unsigned short	line_width;
+	unsigned short	frame_info_0;
+	unsigned short	frame_buffer_0_high;
+	unsigned short	frame_buffer_0_low;
+	unsigned short	frame_buffer_1_high;
+	unsigned short	frame_buffer_1_low;
+	unsigned short	frame_buffer_2_high;
+	unsigned short	frame_buffer_2_low;
+	unsigned short	frame_buffer_3_high;
+	unsigned short	frame_buffer_3_low;
+	unsigned short	frame_buffer_4_high;
+	unsigned short	frame_buffer_4_low;
+	unsigned short	frame_buffer_5_high;
+	unsigned short	frame_buffer_5_low;
+	unsigned short	frame_buffer_6_high;
+	unsigned short	frame_buffer_6_low;
+	unsigned short	frame_buffer_7_high;
+	unsigned short	frame_buffer_7_low;
+	unsigned short	frame_buffer_8_high;
+	unsigned short	frame_buffer_8_low;
+	unsigned short	frame_buffer_9_high;
+	unsigned short	frame_buffer_9_low;
+	unsigned short	frame_buffer_10_high;
+	unsigned short	frame_buffer_10_low;
+	unsigned short	frame_buffer_11_high;
+	unsigned short	frame_buffer_11_low;
+	unsigned short	frame_buffer_12_high;
+	unsigned short	frame_buffer_12_low;
+	unsigned short	frame_buffer_13_high;
+	unsigned short	frame_buffer_13_low;
+	unsigned short	frame_buffer_14_high;
+	unsigned short	frame_buffer_14_low;
+	unsigned short	frame_buffer_15_high;
+	unsigned short	frame_buffer_15_low;
+	unsigned short	output_frame_buffer_high;
+	unsigned short	output_frame_buffer_low;
+	unsigned short	end_of_packet_marker;
+} __attribute__((packed)) viddec_cmd_frame_header_packet;
+
+
+/*
+ * SLICE HEADER PACKET
+ * I-Slice and P-Slice
+ */
+
+#define	VIDDEC_CMD_SLICE_HEADER_PKT_ISLICE		0x0003
+#define	VIDDEC_CMD_SLICE_HEADER_PKT_ISLICE_LEN	\
+	sizeof(viddec_cmd_slice_header_pkt_islice)
+
+#define	VIDDEC_CMD_ISLICE_INFO_1_MOD_SLICE_TYPE_PSLICE	0x0000
+#define	VIDDEC_CMD_ISLICE_INFO_1_MOD_SLICE_TYPE_BSLICE	0x0100
+#define	VIDDEC_CMD_ISLICE_INFO_1_MOD_SLICE_TYPE_ISLICE	0x0200
+#define	VIDDEC_CMD_ISLICE_INFO_1_MOD_SLICE_TYPE_SPSLICE	0x0300
+#define	VIDDEC_CMD_ISLICE_INFO_1_MOD_SLICE_TYPE_SISLICE	0x0400
+#define	VIDDEC_CMD_ISLICE_INFO_1_NOPADDING	0x0000
+#define	VIDDEC_CMD_ISLICE_INFO_1_PADDING	0x0800
+
+#define	VIDDEC_CMD_ISLICE_EOP_MARKER		0x7FFF
+
+typedef struct {
+	unsigned short	cmd_id;
+	unsigned short	packet_id;
+	unsigned short	slice_info_0;
+	unsigned short	slice_info_1;
+	unsigned short	slice_info_2;
+	unsigned short	num_bytes_in_rbsp_high;
+	unsigned short	num_bytes_in_rbsp_low;
+	unsigned short	num_bytes_in_rbsp_consumed;
+	unsigned short	end_of_packet_marker;
+} __attribute__((packed)) viddec_cmd_slice_header_pkt_islice;
+
+
+#define	VIDDEC_CMD_SLICE_HEADER_PKT_PSLICE		0x0003
+#define	VIDDEC_CMD_SLICE_HEADER_PKT_PSLICE_LEN	\
+	sizeof(viddec_cmd_slice_header_pkt_pslice)
+
+
+typedef struct {
+	unsigned short	cmd_id;
+	unsigned short	packet_id;
+	unsigned short	slice_info_0;
+	unsigned short	slice_info_1;
+	unsigned short	slice_info_2;
+	unsigned short	slice_info_3;
+	unsigned short	refidx_l0_map_tab_info_0;
+	unsigned short	refidx_l0_map_tab_info_1;
+	unsigned short	refidx_l0_map_tab_info_2;
+	unsigned short	refidx_l0_map_tab_info_3;
+	unsigned short	num_bytes_in_rbsp_high;
+	unsigned short	num_bytes_in_rbsp_low;
+	unsigned short	num_bytes_in_rbsp_consumed;
+	unsigned short	end_of_packet_marker;
+} __attribute__((packed)) viddec_cmd_slice_header_pkt_pslice;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5vdecmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5vdecmsg.h
new file mode 100644
index 0000000..c1744c1
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5vdecmsg.h
@@ -0,0 +1,107 @@
+#ifndef QDSP5VIDDECMSGI_H
+#define QDSP5VIDDECMSGI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    V I D E O  D E C O D E R   I N T E R N A L  M E S S A G E S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of messages
+  that are sent by VIDDEC Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5vdecmsg.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when       who     what, where, why
+--------   ---     ----------------------------------------------------------
+05/10/08   ac      initial version
+===========================================================================*/
+
+/*
+ * Message to inform ARM which VDEC_SUBFRAME_PKT_CMD processed by VIDDEC TASK
+ */
+
+#define	VIDDEC_MSG_SUBF_DONE	0x0000
+#define	VIDDEC_MSG_SUBF_DONE_LEN	\
+	sizeof(viddec_msg_subf_done)
+
+typedef struct {
+	unsigned short	packet_seq_number;
+	unsigned short	codec_instance_id;
+} __attribute__((packed)) viddec_msg_subf_done;
+
+
+/*
+ * Message to inform ARM one frame has been decoded
+ */
+
+#define	VIDDEC_MSG_FRAME_DONE	0x0001
+#define	VIDDEC_MSG_FRAME_DONE_LEN	\
+	sizeof(viddec_msg_frame_done)
+
+typedef struct {
+	unsigned short	packet_seq_number;
+	unsigned short	codec_instance_id;
+} __attribute__((packed)) viddec_msg_frame_done;
+
+
+/*
+ * Message to inform ARM that post processing frame has been decoded
+ */
+
+#define	VIDDEC_MSG_PP_ENABLE_CMD_DONE	0x0002
+#define	VIDDEC_MSG_PP_ENABLE_CMD_DONE_LEN	\
+	sizeof(viddec_msg_pp_enable_cmd_done)
+
+typedef struct {
+	unsigned short	packet_seq_number;
+	unsigned short	codec_instance_id;
+} __attribute__((packed)) viddec_msg_pp_enable_cmd_done;
+
+
+/*
+ * Message to inform ARM that one post processing frame has been decoded
+ */
+
+
+#define	VIDDEC_MSG_PP_FRAME_DONE		0x0003
+#define	VIDDEC_MSG_PP_FRAME_DONE_LEN	\
+	sizeof(viddec_msg_pp_frame_done)
+
+#define	VIDDEC_MSG_DISP_WORTHY_DISP		0x0000
+#define	VIDDEC_MSG_DISP_WORTHY_DISP_NONE	0xFFFF
+
+
+typedef struct {
+	unsigned short	packet_seq_number;
+	unsigned short	codec_instance_id;
+	unsigned short	display_worthy;
+} __attribute__((packed)) viddec_msg_pp_frame_done;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5venccmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5venccmdi.h
new file mode 100644
index 0000000..819544d
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5venccmdi.h
@@ -0,0 +1,212 @@
+#ifndef QDSP5VIDENCCMDI_H
+#define QDSP5VIDENCCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    V I D E O  E N C O D E R  I N T E R N A L  C O M M A N D S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of commands
+  that are accepted by VIDENC Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 2008 by QUALCOMM, Incorporated.
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+			EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+Revision History:
+
+when       who     what, where, why
+--------   ---     ----------------------------------------------------------
+09/25/08   umeshp      initial version
+===========================================================================*/
+
+  #define VIDENC_CMD_CFG           0x0000
+  #define VIDENC_CMD_ACTIVE        0x0001
+  #define VIDENC_CMD_IDLE          0x0002
+  #define VIDENC_CMD_FRAME_START   0x0003
+  #define VIDENC_CMD_STATUS_QUERY  0x0004
+  #define VIDENC_CMD_RC_CFG        0x0005
+  #define VIDENC_CMD_DIS_CFG       0x0006
+  #define VIDENC_CMD_DIS           0x0007
+  #define VIDENC_CMD_INTRA_REFRESH 0x0008
+  #define VIDENC_CMD_DIGITAL_ZOOM  0x0009
+
+
+/*
+ * Command to pass the frame message information to VIDENC
+ */
+
+
+#define VIDENC_CMD_FRAME_START_LEN \
+	sizeof(videnc_cmd_frame_start)
+
+typedef struct {
+	unsigned short  cmd_id;
+	unsigned short  frame_info;
+	unsigned short  frame_rho_budget_word_high;
+	unsigned short  frame_rho_budget_word_low;
+	unsigned short  input_luma_addr_high;
+	unsigned short  input_luma_addr_low;
+	unsigned short  input_chroma_addr_high;
+	unsigned short  input_chroma_addr_low;
+	unsigned short  ref_vop_buf_ptr_high;
+	unsigned short  ref_vop_buf_ptr_low;
+	unsigned short  enc_pkt_buf_ptr_high;
+	unsigned short  enc_pkt_buf_ptr_low;
+	unsigned short  enc_pkt_buf_size_high;
+	unsigned short  enc_pkt_buf_size_low;
+	unsigned short  unfilt_recon_vop_buf_ptr_high;
+	unsigned short  unfilt_recon_vop_buf_ptr_low;
+	unsigned short  filt_recon_vop_buf_ptr_high;
+	unsigned short  filt_recon_vop_buf_ptr_low;
+} __attribute__((packed)) videnc_cmd_frame_start;
+
+/*
+ * Command to pass the frame-level digital stabilization parameters to VIDENC
+ */
+
+
+#define VIDENC_CMD_DIS_LEN \
+    sizeof(videnc_cmd_dis)
+
+typedef struct {
+	unsigned short  cmd_id;
+	unsigned short  vfe_out_prev_luma_addr_high;
+	unsigned short  vfe_out_prev_luma_addr_low;
+	unsigned short  stabilization_info;
+} __attribute__((packed)) videnc_cmd_dis;
+
+/*
+ * Command to pass the codec related parameters to VIDENC
+ */
+
+
+#define VIDENC_CMD_CFG_LEN \
+    sizeof(videnc_cmd_cfg)
+
+typedef struct {
+	unsigned short  cmd_id;
+	unsigned short  cfg_info_0;
+	unsigned short  cfg_info_1;
+	unsigned short  four_mv_threshold;
+	unsigned short  ise_fse_mv_cost_fac;
+	unsigned short  venc_frame_dim;
+	unsigned short  venc_DM_partition;
+} __attribute__((packed)) videnc_cmd_cfg;
+
+/*
+ * Command to start the video encoding
+ */
+
+
+#define VIDENC_CMD_ACTIVE_LEN \
+    sizeof(videnc_cmd_active)
+
+typedef struct {
+    unsigned short  cmd_id;
+} __attribute__((packed)) videnc_cmd_active;
+
+/*
+ * Command to stop the video encoding
+ */
+
+
+#define VIDENC_CMD_IDLE_LEN \
+    sizeof(videnc_cmd_idle)
+
+typedef struct {
+	unsigned short  cmd_id;
+} __attribute__((packed)) videnc_cmd_idle;
+
+/*
+ * Command to query staus of VIDENC
+ */
+
+
+#define VIDENC_CMD_STATUS_QUERY_LEN \
+    sizeof(videnc_cmd_status_query)
+
+typedef struct {
+	unsigned short  cmd_id;
+} __attribute__((packed)) videnc_cmd_status_query;
+
+/*
+ * Command to set rate control for a frame
+ */
+
+
+#define VIDENC_CMD_RC_CFG_LEN \
+    sizeof(videnc_cmd_rc_cfg)
+
+typedef struct {
+	unsigned short  cmd_id;
+	unsigned short  max_frame_qp_delta;
+	unsigned short  max_min_frame_qp;
+} __attribute__((packed)) videnc_cmd_rc_cfg;
+
+/*
+ * Command to set intra-refreshing
+ */
+
+
+#define VIDENC_CMD_INTRA_REFRESH_LEN \
+    sizeof(videnc_cmd_intra_refresh)
+
+typedef struct {
+	unsigned short  cmd_id;
+	unsigned short  num_mb_refresh;
+	unsigned short  mb_index[15];
+} __attribute__((packed)) videnc_cmd_intra_refresh;
+
+/*
+ * Command to pass digital zoom information to the VIDENC
+ */
+#define VIDENC_CMD_DIGITAL_ZOOM_LEN \
+    sizeof(videnc_cmd_digital_zoom)
+
+typedef struct {
+	unsigned short  cmd_id;
+	unsigned short  digital_zoom_en;
+	unsigned short  luma_frame_shift_X;
+	unsigned short  luma_frame_shift_Y;
+	unsigned short  up_ip_luma_rows;
+	unsigned short  up_ip_luma_cols;
+	unsigned short  up_ip_chroma_rows;
+	unsigned short  up_ip_chroma_cols;
+	unsigned short  luma_ph_incr_V_low;
+	unsigned short  luma_ph_incr_V_high;
+	unsigned short  luma_ph_incr_H_low;
+	unsigned short  luma_ph_incr_H_high;
+	unsigned short  chroma_ph_incr_V_low;
+	unsigned short  chroma_ph_incr_V_high;
+	unsigned short  chroma_ph_incr_H_low;
+	unsigned short  chroma_ph_incr_H_high;
+} __attribute__((packed)) videnc_cmd_digital_zoom;
+
+/*
+ * Command to configure digital stabilization parameters
+ */
+
+#define VIDENC_CMD_DIS_CFG_LEN \
+    sizeof(videnc_cmd_dis_cfg)
+
+typedef struct {
+	unsigned short  cmd_id;
+	unsigned short  image_stab_subf_start_row_col;
+	unsigned short  image_stab_subf_dim;
+	unsigned short  image_stab_info_0;
+} __attribute__((packed)) videnc_cmd_dis_cfg;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5vfecmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5vfecmdi.h
new file mode 100644
index 0000000..55e8fc2
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5vfecmdi.h
@@ -0,0 +1,910 @@
+#ifndef QDSP5VFECMDI_H
+#define QDSP5VFECMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    V F E   I N T E R N A L   C O M M A N D S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of commands
+  that are accepted by VFE Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5vfecmdi.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when       who     what, where, why
+--------   ---     ----------------------------------------------------------
+06/12/08   sv      initial version
+===========================================================================*/
+
+/******************************************************************************
+ * Commands through vfeCommandScaleQueue
+ *****************************************************************************/
+
+/*
+ * Command to program scaler for op1 . max op of scaler is VGA
+ */
+
+
+#define	VFE_CMD_SCALE_OP1_CFG		0x0000
+#define	VFE_CMD_SCALE_OP1_CFG_LEN	\
+	sizeof(vfe_cmd_scale_op1_cfg)
+
+#define	VFE_CMD_SCALE_OP1_SEL_IP_SEL_Y_STANDARD	0x0000
+#define	VFE_CMD_SCALE_OP1_SEL_IP_SEL_Y_CASCADED	0x0001
+#define	VFE_CMD_SCALE_OP1_SEL_H_Y_SCALER_DIS	0x0000
+#define	VFE_CMD_SCALE_OP1_SEL_H_Y_SCALER_ENA	0x0002
+#define	VFE_CMD_SCALE_OP1_SEL_H_PP_Y_SCALER_DIS	0x0000
+#define	VFE_CMD_SCALE_OP1_SEL_H_PP_Y_SCALER_ENA	0x0004
+#define	VFE_CMD_SCALE_OP1_SEL_V_Y_SCALER_DIS	0x0000
+#define	VFE_CMD_SCALE_OP1_SEL_V_Y_SCALER_ENA	0x0008
+#define	VFE_CMD_SCALE_OP1_SEL_V_PP_Y_SCALER_DIS	0x0000
+#define	VFE_CMD_SCALE_OP1_SEL_V_PP_Y_SCALER_ENA	0x0010
+#define	VFE_CMD_SCALE_OP1_SEL_IP_SEL_CBCR_STANDARD	0x0000
+#define	VFE_CMD_SCALE_OP1_SEL_IP_SEL_CBCR_CASCADED	0x0020
+#define	VFE_CMD_SCALE_OP1_SEL_H_CBCR_SCALER_DIS		0x0000
+#define	VFE_CMD_SCALE_OP1_SEL_H_CBCR_SCALER_ENA		0x0040
+#define	VFE_CMD_SCALE_OP1_SEL_V_CBCR_SCALER_DIS		0x0000
+#define	VFE_CMD_SCALE_OP1_SEL_V_CBCR_SCALER_ENA		0x0080
+
+#define	VFE_CMD_OP1_PP_Y_SCALER_CFG_PART1_DONT_LOAD_COEFFS	0x80000000
+#define	VFE_CMD_OP1_PP_Y_SCALER_CFG_PART1_LOAD_COEFFS	0x80000000
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	scale_op1_sel;
+	unsigned int	y_scaler_cfg_part1;
+	unsigned int	y_scaler_cfg_part2;
+	unsigned int	cbcr_scaler_cfg_part1;
+	unsigned int	cbcr_scaler_cfg_part2;
+	unsigned int	cbcr_scaler_cfg_part3;
+	unsigned int	pp_y_scaler_cfg_part1;
+	unsigned int	pp_y_scaler_cfg_part2;
+	unsigned int	y_scaler_v_coeff_bank_part1[16];
+	unsigned int	y_scaler_v_coeff_bank_part2[16];
+	unsigned int	y_scaler_h_coeff_bank_part1[16];
+	unsigned int	y_scaler_h_coeff_bank_part2[16];
+} __attribute__((packed)) vfe_cmd_scale_op1_cfg;
+
+
+/*
+ * Command to program scaler for op2
+ */
+
+#define	VFE_CMD_SCALE_OP2_CFG		0x0001
+#define	VFE_CMD_SCALE_OP2_CFG_LEN	\
+	sizeof(vfe_cmd_scale_op2_cfg)
+
+#define	VFE_CMD_SCALE_OP2_SEL_IP_SEL_Y_STANDARD	0x0000
+#define	VFE_CMD_SCALE_OP2_SEL_IP_SEL_Y_CASCADED	0x0001
+#define	VFE_CMD_SCALE_OP2_SEL_H_Y_SCALER_DIS	0x0000
+#define	VFE_CMD_SCALE_OP2_SEL_H_Y_SCALER_ENA	0x0002
+#define	VFE_CMD_SCALE_OP2_SEL_H_PP_Y_SCALER_DIS	0x0000
+#define	VFE_CMD_SCALE_OP2_SEL_H_PP_Y_SCALER_ENA	0x0004
+#define	VFE_CMD_SCALE_OP2_SEL_V_Y_SCALER_DIS	0x0000
+#define	VFE_CMD_SCALE_OP2_SEL_V_Y_SCALER_ENA	0x0008
+#define	VFE_CMD_SCALE_OP2_SEL_V_PP_Y_SCALER_DIS	0x0000
+#define	VFE_CMD_SCALE_OP2_SEL_V_PP_Y_SCALER_ENA	0x0010
+#define	VFE_CMD_SCALE_OP2_SEL_IP_SEL_CBCR_STANDARD	0x0000
+#define	VFE_CMD_SCALE_OP2_SEL_IP_SEL_CBCR_CASCADED	0x0020
+#define	VFE_CMD_SCALE_OP2_SEL_H_CBCR_SCALER_DIS		0x0000
+#define	VFE_CMD_SCALE_OP2_SEL_H_CBCR_SCALER_ENA		0x0040
+#define	VFE_CMD_SCALE_OP2_SEL_V_CBCR_SCALER_DIS		0x0000
+#define	VFE_CMD_SCALE_OP2_SEL_V_CBCR_SCALER_ENA		0x0080
+
+#define	VFE_CMD_OP2_PP_Y_SCALER_CFG_PART1_DONT_LOAD_COEFFS	0x80000000
+#define	VFE_CMD_OP2_PP_Y_SCALER_CFG_PART1_LOAD_COEFFS		0x80000000
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	scale_op2_sel;
+	unsigned int	y_scaler_cfg_part1;
+	unsigned int	y_scaler_cfg_part2;
+	unsigned int	cbcr_scaler_cfg_part1;
+	unsigned int	cbcr_scaler_cfg_part2;
+	unsigned int	cbcr_scaler_cfg_part3;
+	unsigned int	pp_y_scaler_cfg_part1;
+	unsigned int	pp_y_scaler_cfg_part2;
+	unsigned int	y_scaler_v_coeff_bank_part1[16];
+	unsigned int	y_scaler_v_coeff_bank_part2[16];
+	unsigned int	y_scaler_h_coeff_bank_part1[16];
+	unsigned int	y_scaler_h_coeff_bank_part2[16];
+} __attribute__((packed)) vfe_cmd_scale_op2_cfg;
+
+
+/******************************************************************************
+ * Commands through vfeCommandTableQueue
+ *****************************************************************************/
+
+/*
+ * Command to program the AXI ip paths
+ */
+
+#define	VFE_CMD_AXI_IP_CFG		0x0000
+#define	VFE_CMD_AXI_IP_CFG_LEN		sizeof(vfe_cmd_axi_ip_cfg)
+
+#define	VFE_CMD_IP_SEL_IP_FORMAT_8	0x0000
+#define	VFE_CMD_IP_SEL_IP_FORMAT_10	0x0001
+#define	VFE_CMD_IP_SEL_IP_FORMAT_12	0x0002
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	ip_sel;
+	unsigned int	ip_cfg_part1;
+	unsigned int	ip_cfg_part2;
+	unsigned int	ip_unpack_cfg_part[6];
+	unsigned int	ip_buf_addr[8];
+} __attribute__ ((packed)) vfe_cmd_axi_ip_cfg;
+
+
+/*
+ * Command to program axi op paths
+ */
+
+#define	VFE_CMD_AXI_OP_CFG	0x0001
+#define	VFE_CMD_AXI_OP_CFG_LEN	sizeof(vfe_cmd_axi_op_cfg)
+
+#define	VFE_CMD_OP_SEL_OP1		0x0000
+#define	VFE_CMD_OP_SEL_OP2		0x0001
+#define	VFE_CMD_OP_SEL_OP1_OP2		0x0002
+#define	VFE_CMD_OP_SEL_CTOA		0x0003
+#define	VFE_CMD_OP_SEL_CTOA_OP1		0x0004
+#define	VFE_CMD_OP_SEL_CTOA_OP2		0x0005
+#define	VFE_CMD_OP_SEL_OP_FORMAT_8	0x0000
+#define	VFE_CMD_OP_SEL_OP_FORMAT_10	0x0008
+#define	VFE_CMD_OP_SEL_OP_FORMAT_12	0x0010
+
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	op_sel;
+	unsigned int	op1_y_cfg_part1;
+	unsigned int	op1_y_cfg_part2;
+	unsigned int	op1_cbcr_cfg_part1;
+	unsigned int	op1_cbcr_cfg_part2;
+	unsigned int	op2_y_cfg_part1;
+	unsigned int	op2_y_cfg_part2;
+	unsigned int	op2_cbcr_cfg_part1;
+	unsigned int	op2_cbcr_cfg_part2;
+	unsigned int	op1_buf1_addr[16];
+	unsigned int	op2_buf1_addr[16];
+} __attribute__((packed)) vfe_cmd_axi_op_cfg;
+
+
+
+
+/*
+ * Command to program the roll off correction module
+ */
+
+#define	VFE_CMD_ROLLOFF_CFG	0x0002
+#define	VFE_CMD_ROLLOFF_CFG_LEN	\
+	sizeof(vfe_cmd_rolloff_cfg)
+
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	correction_opt_center_pos;
+	unsigned int	radius_square_entry[32];
+	unsigned int	red_table_entry[32];
+	unsigned int	green_table_entry[32];
+	unsigned int	blue_table_entry[32];
+} __attribute__((packed)) vfe_cmd_rolloff_cfg;
+
+/*
+ * Command to program RGB gamma table
+ */
+
+#define	VFE_CMD_RGB_GAMMA_CFG		0x0003
+#define	VFE_CMD_RGB_GAMMA_CFG_LEN	\
+	sizeof(vfe_cmd_rgb_gamma_cfg)
+
+#define	VFE_CMD_RGB_GAMMA_SEL_LINEAR		0x0000
+#define	VFE_CMD_RGB_GAMMA_SEL_PW_LINEAR		0x0001
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	rgb_gamma_sel;
+	unsigned int	rgb_gamma_entry[256];
+} __attribute__((packed)) vfe_cmd_rgb_gamma_cfg;
+
+
+/*
+ * Command to program luma gamma table for the noise reduction path
+ */
+
+#define	VFE_CMD_Y_GAMMA_CFG		0x0004
+#define	VFE_CMD_Y_GAMMA_CFG_LEN		\
+	sizeof(vfe_cmd_y_gamma_cfg)
+
+#define	VFE_CMD_Y_GAMMA_SEL_LINEAR	0x0000
+#define	VFE_CMD_Y_GAMMA_SEL_PW_LINEAR	0x0001
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	y_gamma_sel;
+	unsigned int	y_gamma_entry[256];
+} __attribute__((packed)) vfe_cmd_y_gamma_cfg;
+
+
+
+/******************************************************************************
+ * Commands through vfeCommandQueue
+ *****************************************************************************/
+
+/*
+ * Command to reset the VFE to a known good state.All previously programmed
+ * Params will be lost
+ */
+
+
+#define	VFE_CMD_RESET		0x0000
+#define	VFE_CMD_RESET_LEN	sizeof(vfe_cmd_reset)
+
+
+typedef struct {
+	unsigned short	cmd_id;
+} __attribute__((packed)) vfe_cmd_reset;
+
+
+/*
+ * Command to start VFE processing based on the config params
+ */
+
+
+#define	VFE_CMD_START		0x0001
+#define	VFE_CMD_START_LEN	sizeof(vfe_cmd_start)
+
+#define	VFE_CMD_STARTUP_PARAMS_SRC_CAMIF	0x0000
+#define	VFE_CMD_STARTUP_PARAMS_SRC_AXI		0x0001
+#define	VFE_CMD_STARTUP_PARAMS_MODE_CONTINUOUS	0x0000
+#define	VFE_CMD_STARTUP_PARAMS_MODE_SNAPSHOT	0x0002
+
+#define	VFE_CMD_IMAGE_PL_BLACK_LVL_CORR_DIS	0x0000
+#define	VFE_CMD_IMAGE_PL_BLACK_LVL_CORR_ENA	0x0001
+#define	VFE_CMD_IMAGE_PL_ROLLOFF_CORR_DIS	0x0000
+#define	VFE_CMD_IMAGE_PL_ROLLOFF_CORR_ENA	0x0002
+#define	VFE_CMD_IMAGE_PL_WHITE_BAL_DIS		0x0000
+#define	VFE_CMD_IMAGE_PL_WHITE_BAL_ENA		0x0004
+#define	VFE_CMD_IMAGE_PL_RGB_GAMMA_DIS		0x0000
+#define	VFE_CMD_IMAGE_PL_RGB_GAMMA_ENA		0x0008
+#define	VFE_CMD_IMAGE_PL_LUMA_NOISE_RED_PATH_DIS	0x0000
+#define	VFE_CMD_IMAGE_PL_LUMA_NOISE_RED_PATH_ENA	0x0010
+#define	VFE_CMD_IMAGE_PL_ADP_FILTER_DIS		0x0000
+#define	VFE_CMD_IMAGE_PL_ADP_FILTER_ENA		0x0020
+#define	VFE_CMD_IMAGE_PL_CHROMA_SAMP_DIS	0x0000
+#define	VFE_CMD_IMAGE_PL_CHROMA_SAMP_ENA	0x0040
+
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	startup_params;
+	unsigned int	image_pipeline;
+	unsigned int	frame_dimension;
+} __attribute__((packed)) vfe_cmd_start;
+
+
+/*
+ * Command to halt all processing
+ */
+
+#define	VFE_CMD_STOP		0x0002
+#define	VFE_CMD_STOP_LEN	sizeof(vfe_cmd_stop)
+
+typedef struct {
+	unsigned short	cmd_id;
+} __attribute__((packed)) vfe_cmd_stop;
+
+
+/*
+ * Command to commit the params that have been programmed to take
+ * effect on the next frame
+ */
+
+#define	VFE_CMD_UPDATE		0x0003
+#define	VFE_CMD_UPDATE_LEN	sizeof(vfe_cmd_update)
+
+
+typedef struct {
+	unsigned short	cmd_id;
+} __attribute__((packed)) vfe_cmd_update;
+
+
+/*
+ * Command to program CAMIF module
+ */
+
+#define	VFE_CMD_CAMIF_CFG	0x0004
+#define	VFE_CMD_CAMIF_CFG_LEN	sizeof(vfe_cmd_camif_cfg)
+
+#define	VFE_CMD_CFG_VSYNC_SYNC_EDGE_HIGH	0x0000
+#define	VFE_CMD_CFG_VSYNC_SYNC_EDGE_LOW		0x0002
+#define	VFE_CMD_CFG_HSYNC_SYNC_EDGE_HIGH	0x0000
+#define	VFE_CMD_CFG_HSYNC_SYNC_EDGE_LOW		0x0004
+#define	VFE_CMD_CFG_SYNC_MODE_APS		0x0000
+#define	VFE_CMD_CFG_SYNC_MODE_EFS		0X0008
+#define	VFE_CMD_CFG_SYNC_MODE_ELS		0x0010
+#define	VFE_CMD_CFG_SYNC_MODE_RVD		0x0018
+#define	VFE_CMD_CFG_VFE_SUBSAMP_EN_DIS		0x0000
+#define	VFE_CMD_CFG_VFE_SUBSAMP_EN_ENA		0x0020
+#define	VFE_CMD_CFG_BUS_SUBSAMP_EN_DIS		0x0000
+#define	VFE_CMD_CFG_BUS_SUBSAMP_EN_ENA		0x0080
+#define	VFE_CMD_CFG_IRQ_SUBSAMP_EN_DIS		0x0000
+#define	VFE_CMD_CFG_IRQ_SUBSAMP_EN_ENA		0x0800
+
+#define	VFE_CMD_SUBSAMP2_CFG_PIXEL_SKIP_16	0x0000
+#define	VFE_CMD_SUBSAMP2_CFG_PIXEL_SKIP_12	0x0010
+
+#define	VFE_CMD_EPOCH_IRQ_1_DIS			0x0000
+#define	VFE_CMD_EPOCH_IRQ_1_ENA			0x4000
+#define	VFE_CMD_EPOCH_IRQ_2_DIS			0x0000
+#define	VFE_CMD_EPOCH_IRQ_2_ENA			0x8000
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	cfg;
+	unsigned int	efs_cfg;
+	unsigned int	frame_cfg;
+	unsigned int	window_width_cfg;
+	unsigned int	window_height_cfg;
+	unsigned int	subsamp1_cfg;
+	unsigned int	subsamp2_cfg;
+	unsigned int	epoch_irq;
+} __attribute__((packed)) vfe_cmd_camif_cfg;
+
+
+
+/*
+ * Command to program the black level module
+ */
+
+#define	VFE_CMD_BLACK_LVL_CFG		0x0005
+#define	VFE_CMD_BLACK_LVL_CFG_LEN	sizeof(vfe_cmd_black_lvl_cfg)
+
+#define	VFE_CMD_BL_SEL_MANUAL		0x0000
+#define	VFE_CMD_BL_SEL_AUTO		0x0001
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	black_lvl_sel;
+	unsigned int	cfg_part[3];
+} __attribute__((packed)) vfe_cmd_black_lvl_cfg;
+
+
+/*
+ * Command to program the active region by cropping the region of interest
+ */
+
+#define	VFE_CMD_ACTIVE_REGION_CFG	0x0006
+#define	VFE_CMD_ACTIVE_REGION_CFG_LEN	\
+	sizeof(vfe_cmd_active_region_cfg)
+
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	cfg_part1;
+	unsigned int	cfg_part2;
+} __attribute__((packed)) vfe_cmd_active_region_cfg;
+
+
+
+/*
+ * Command to program the defective pixel correction(DPC) ,
+ * adaptive bayer filter (ABF) and demosaic modules
+ */
+
+#define	VFE_CMD_DEMOSAIC_CFG		0x0007
+#define	VFE_CMD_DEMOSAIC_CFG_LEN	sizeof(vfe_cmd_demosaic_cfg)
+
+#define	VFE_CMD_DEMOSAIC_PART1_ABF_EN_DIS	0x0000
+#define	VFE_CMD_DEMOSAIC_PART1_ABF_EN_ENA	0x0001
+#define	VFE_CMD_DEMOSAIC_PART1_DPC_EN_DIS	0x0000
+#define	VFE_CMD_DEMOSAIC_PART1_DPC_EN_ENA	0x0002
+#define	VFE_CMD_DEMOSAIC_PART1_FORCE_ABF_OFF	0x0000
+#define	VFE_CMD_DEMOSAIC_PART1_FORCE_ABF_ON	0x0004
+#define	VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_1	0x00000000
+#define	VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_2	0x10000000
+#define	VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_4	0x20000000
+#define	VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_8	0x30000000
+#define	VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_1_2	0x50000000
+#define	VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_1_4	0x60000000
+#define	VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_1_8	0x70000000
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	demosaic_part1;
+	unsigned int	demosaic_part2;
+	unsigned int	demosaic_part3;
+	unsigned int	demosaic_part4;
+	unsigned int	demosaic_part5;
+} __attribute__((packed)) vfe_cmd_demosaic_cfg;
+
+
+/*
+ * Command to program the ip format
+ */
+
+#define	VFE_CMD_IP_FORMAT_CFG		0x0008
+#define	VFE_CMD_IP_FORMAT_CFG_LEN	\
+	sizeof(vfe_cmd_ip_format_cfg)
+
+#define	VFE_CMD_IP_FORMAT_SEL_RGRG	0x0000
+#define	VFE_CMD_IP_FORMAT_SEL_GRGR	0x0001
+#define	VFE_CMD_IP_FORMAT_SEL_BGBG	0x0002
+#define	VFE_CMD_IP_FORMAT_SEL_GBGB	0x0003
+#define	VFE_CMD_IP_FORMAT_SEL_YCBYCR	0x0004
+#define	VFE_CMD_IP_FORMAT_SEL_YCRYCB	0x0005
+#define	VFE_CMD_IP_FORMAT_SEL_CBYCRY	0x0006
+#define	VFE_CMD_IP_FORMAT_SEL_CRYCBY	0x0007
+#define	VFE_CMD_IP_FORMAT_SEL_NO_CHROMA	0x0000
+#define	VFE_CMD_IP_FORMAT_SEL_CHROMA	0x0008
+
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	ip_format_sel;
+	unsigned int	balance_gains_part1;
+	unsigned int	balance_gains_part2;
+} __attribute__((packed)) vfe_cmd_ip_format_cfg;
+
+
+
+/*
+ * Command to program max and min allowed op values
+ */
+
+#define	VFE_CMD_OP_CLAMP_CFG		0x0009
+#define	VFE_CMD_OP_CLAMP_CFG_LEN	\
+	sizeof(vfe_cmd_op_clamp_cfg)
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	op_clamp_max;
+	unsigned int	op_clamp_min;
+} __attribute__((packed)) vfe_cmd_op_clamp_cfg;
+
+
+/*
+ * Command to program chroma sub sample module
+ */
+
+#define	VFE_CMD_CHROMA_SUBSAMPLE_CFG		0x000A
+#define	VFE_CMD_CHROMA_SUBSAMPLE_CFG_LEN	\
+	sizeof(vfe_cmd_chroma_subsample_cfg)
+
+#define	VFE_CMD_CHROMA_SUBSAMP_SEL_H_INTERESTIAL_SAMPS	0x0000
+#define	VFE_CMD_CHROMA_SUBSAMP_SEL_H_COSITED_SAMPS	0x0001
+#define	VFE_CMD_CHROMA_SUBSAMP_SEL_V_INTERESTIAL_SAMPS	0x0000
+#define	VFE_CMD_CHROMA_SUBSAMP_SEL_V_COSITED_SAMPS	0x0002
+#define	VFE_CMD_CHROMA_SUBSAMP_SEL_H_SUBSAMP_DIS	0x0000
+#define	VFE_CMD_CHROMA_SUBSAMP_SEL_H_SUBSAMP_ENA	0x0004
+#define	VFE_CMD_CHROMA_SUBSAMP_SEL_V_SUBSAMP_DIS	0x0000
+#define	VFE_CMD_CHROMA_SUBSAMP_SEL_V_SUBSAMP_ENA	0x0008
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	chroma_subsamp_sel;
+} __attribute__((packed)) vfe_cmd_chroma_subsample_cfg;
+
+
+/*
+ * Command to program the white balance module
+ */
+
+#define	VFE_CMD_WHITE_BALANCE_CFG	0x000B
+#define	VFE_CMD_WHITE_BALANCE_CFG_LEN	\
+	sizeof(vfe_cmd_white_balance_cfg)
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	white_balance_gains;
+} __attribute__((packed)) vfe_cmd_white_balance_cfg;
+
+
+/*
+ * Command to program the color processing module
+ */
+
+#define	VFE_CMD_COLOR_PROCESS_CFG	0x000C
+#define	VFE_CMD_COLOR_PROCESS_CFG_LEN	\
+	sizeof(vfe_cmd_color_process_cfg)
+
+#define	VFE_CMD_COLOR_CORRE_PART7_Q7_FACTORS	0x0000
+#define	VFE_CMD_COLOR_CORRE_PART7_Q8_FACTORS	0x0001
+#define	VFE_CMD_COLOR_CORRE_PART7_Q9_FACTORS	0x0002
+#define	VFE_CMD_COLOR_CORRE_PART7_Q10_FACTORS	0x0003
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	color_correction_part1;
+	unsigned int	color_correction_part2;
+	unsigned int	color_correction_part3;
+	unsigned int	color_correction_part4;
+	unsigned int	color_correction_part5;
+	unsigned int	color_correction_part6;
+	unsigned int	color_correction_part7;
+	unsigned int	chroma_enhance_part1;
+	unsigned int	chroma_enhance_part2;
+	unsigned int	chroma_enhance_part3;
+	unsigned int	chroma_enhance_part4;
+	unsigned int	chroma_enhance_part5;
+	unsigned int	luma_calc_part1;
+	unsigned int	luma_calc_part2;
+} __attribute__((packed)) vfe_cmd_color_process_cfg;
+
+
+/*
+ * Command to program adaptive filter module
+ */
+
+#define	VFE_CMD_ADP_FILTER_CFG		0x000D
+#define	VFE_CMD_ADP_FILTER_CFG_LEN	\
+	sizeof(vfe_cmd_adp_filter_cfg)
+
+#define	VFE_CMD_ASF_CFG_PART_SMOOTH_FILTER_DIS		0x0000
+#define	VFE_CMD_ASF_CFG_PART_SMOOTH_FILTER_ENA		0x0001
+#define	VFE_CMD_ASF_CFG_PART_NO_SHARP_MODE		0x0000
+#define	VFE_CMD_ASF_CFG_PART_SINGLE_FILTER		0x0002
+#define	VFE_CMD_ASF_CFG_PART_DUAL_FILTER		0x0004
+#define	VFE_CMD_ASF_CFG_PART_SHARP_MODE			0x0007
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	asf_cfg_part[7];
+} __attribute__((packed)) vfe_cmd_adp_filter_cfg;
+
+
+/*
+ * Command to program for frame skip pattern for op1 and op2
+ */
+
+#define	VFE_CMD_FRAME_SKIP_CFG		0x000E
+#define	VFE_CMD_FRAME_SKIP_CFG_LEN	\
+	sizeof(vfe_cmd_frame_skip_cfg)
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	frame_skip_pattern_op1;
+	unsigned int	frame_skip_pattern_op2;
+} __attribute__((packed)) vfe_cmd_frame_skip_cfg;
+
+
+/*
+ * Command to program field-of-view crop for digital zoom
+ */
+
+#define	VFE_CMD_FOV_CROP	0x000F
+#define	VFE_CMD_FOV_CROP_LEN	sizeof(vfe_cmd_fov_crop)
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	fov_crop_part1;
+	unsigned int	fov_crop_part2;
+} __attribute__((packed)) vfe_cmd_fov_crop;
+
+
+
+/*
+ * Command to program auto focus(AF) statistics module
+ */
+
+#define	VFE_CMD_STATS_AUTOFOCUS_CFG	0x0010
+#define	VFE_CMD_STATS_AUTOFOCUS_CFG_LEN	\
+	sizeof(vfe_cmd_stats_autofocus_cfg)
+
+#define	VFE_CMD_AF_STATS_SEL_STATS_DIS	0x0000
+#define	VFE_CMD_AF_STATS_SEL_STATS_ENA	0x0001
+#define	VFE_CMD_AF_STATS_SEL_PRI_FIXED	0x0000
+#define	VFE_CMD_AF_STATS_SEL_PRI_VAR	0x0002
+#define	VFE_CMD_AF_STATS_CFG_PART_METRIC_SUM	0x00000000
+#define	VFE_CMD_AF_STATS_CFG_PART_METRIC_MAX	0x00200000
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	af_stats_sel;
+	unsigned int	af_stats_cfg_part[8];
+	unsigned int	af_stats_op_buf_hdr;
+	unsigned int	af_stats_op_buf[3];
+} __attribute__((packed)) vfe_cmd_stats_autofocus_cfg;
+
+
+/*
+ * Command to program White balance(wb) and exposure (exp)
+ * statistics module
+ */
+
+#define	VFE_CMD_STATS_WB_EXP_CFG	0x0011
+#define	VFE_CMD_STATS_WB_EXP_CFG_LEN	\
+	sizeof(vfe_cmd_stats_wb_exp_cfg)
+
+#define	VFE_CMD_WB_EXP_STATS_SEL_STATS_DIS	0x0000
+#define	VFE_CMD_WB_EXP_STATS_SEL_STATS_ENA	0x0001
+#define	VFE_CMD_WB_EXP_STATS_SEL_PRI_FIXED	0x0000
+#define	VFE_CMD_WB_EXP_STATS_SEL_PRI_VAR	0x0002
+
+#define	VFE_CMD_WB_EXP_STATS_CFG_PART1_EXP_REG_8_8	0x0000
+#define	VFE_CMD_WB_EXP_STATS_CFG_PART1_EXP_REG_16_16	0x0001
+#define	VFE_CMD_WB_EXP_STATS_CFG_PART1_EXP_SREG_8_8	0x0000
+#define	VFE_CMD_WB_EXP_STATS_CFG_PART1_EXP_SREG_4_4	0x0002
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	wb_exp_stats_sel;
+	unsigned int	wb_exp_stats_cfg_part1;
+	unsigned int	wb_exp_stats_cfg_part2;
+	unsigned int	wb_exp_stats_cfg_part3;
+	unsigned int	wb_exp_stats_cfg_part4;
+	unsigned int	wb_exp_stats_op_buf_hdr;
+	unsigned int	wb_exp_stats_op_buf[3];
+} __attribute__((packed)) vfe_cmd_stats_wb_exp_cfg;
+
+
+/*
+ * Command to program histogram(hg) stats module
+ */
+
+#define	VFE_CMD_STATS_HG_CFG		0x0012
+#define	VFE_CMD_STATS_HG_CFG_LEN	\
+	sizeof(vfe_cmd_stats_hg_cfg)
+
+#define	VFE_CMD_HG_STATS_SEL_PRI_FIXED	0x0000
+#define	VFE_CMD_HG_STATS_SEL_PRI_VAR	0x0002
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	hg_stats_sel;
+	unsigned int	hg_stats_cfg_part1;
+	unsigned int	hg_stats_cfg_part2;
+	unsigned int	hg_stats_op_buf_hdr;
+	unsigned int	hg_stats_op_buf;
+} __attribute__((packed)) vfe_cmd_stats_hg_cfg;
+
+
+/*
+ * Command to acknowledge last MSG_VFE_OP1 message
+ */
+
+#define	VFE_CMD_OP1_ACK		0x0013
+#define	VFE_CMD_OP1_ACK_LEN	sizeof(vfe_cmd_op1_ack)
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	op1_buf_y_addr;
+	unsigned int	op1_buf_cbcr_addr;
+} __attribute__((packed)) vfe_cmd_op1_ack;
+
+
+
+/*
+ * Command to acknowledge last MSG_VFE_OP2 message
+ */
+
+#define	VFE_CMD_OP2_ACK		0x0014
+#define	VFE_CMD_OP2_ACK_LEN	sizeof(vfe_cmd_op2_ack)
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	op2_buf_y_addr;
+	unsigned int	op2_buf_cbcr_addr;
+} __attribute__((packed)) vfe_cmd_op2_ack;
+
+
+
+/*
+ * Command to acknowledge MSG_VFE_STATS_AUTOFOCUS msg
+ */
+
+#define	VFE_CMD_STATS_AF_ACK		0x0015
+#define	VFE_CMD_STATS_AF_ACK_LEN	sizeof(vfe_cmd_stats_af_ack)
+
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	af_stats_op_buf;
+} __attribute__((packed)) vfe_cmd_stats_af_ack;
+
+
+/*
+ * Command to acknowledge MSG_VFE_STATS_WB_EXP msg
+ */
+
+#define	VFE_CMD_STATS_WB_EXP_ACK	0x0016
+#define	VFE_CMD_STATS_WB_EXP_ACK_LEN	sizeof(vfe_cmd_stats_wb_exp_ack)
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	wb_exp_stats_op_buf;
+} __attribute__((packed)) vfe_cmd_stats_wb_exp_ack;
+
+
+/*
+ * Command to acknowledge MSG_VFE_EPOCH1 message
+ */
+
+#define	VFE_CMD_EPOCH1_ACK	0x0017
+#define	VFE_CMD_EPOCH1_ACK_LEN	sizeof(vfe_cmd_epoch1_ack)
+
+typedef struct {
+	unsigned short cmd_id;
+} __attribute__((packed)) vfe_cmd_epoch1_ack;
+
+
+/*
+ * Command to acknowledge MSG_VFE_EPOCH2 message
+ */
+
+#define	VFE_CMD_EPOCH2_ACK	0x0018
+#define	VFE_CMD_EPOCH2_ACK_LEN	sizeof(vfe_cmd_epoch2_ack)
+
+typedef struct {
+	unsigned short cmd_id;
+} __attribute__((packed)) vfe_cmd_epoch2_ack;
+
+
+
+/*
+ * Command to configure, enable or disable synchronous timer1
+ */
+
+#define	VFE_CMD_SYNC_TIMER1_CFG		0x0019
+#define	VFE_CMD_SYNC_TIMER1_CFG_LEN	\
+	sizeof(vfe_cmd_sync_timer1_cfg)
+
+#define	VFE_CMD_SYNC_T1_CFG_PART1_TIMER_DIS	0x0000
+#define	VFE_CMD_SYNC_T1_CFG_PART1_TIMER_ENA	0x0001
+#define	VFE_CMD_SYNC_T1_CFG_PART1_POL_HIGH	0x0000
+#define	VFE_CMD_SYNC_T1_CFG_PART1_POL_LOW	0x0002
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	sync_t1_cfg_part1;
+	unsigned int	sync_t1_h_sync_countdown;
+	unsigned int	sync_t1_pclk_countdown;
+	unsigned int	sync_t1_duration;
+} __attribute__((packed)) vfe_cmd_sync_timer1_cfg;
+
+
+/*
+ * Command to configure, enable or disable synchronous timer1
+ */
+
+#define	VFE_CMD_SYNC_TIMER2_CFG		0x001A
+#define	VFE_CMD_SYNC_TIMER2_CFG_LEN	\
+	sizeof(vfe_cmd_sync_timer2_cfg)
+
+#define	VFE_CMD_SYNC_T2_CFG_PART1_TIMER_DIS	0x0000
+#define	VFE_CMD_SYNC_T2_CFG_PART1_TIMER_ENA	0x0001
+#define	VFE_CMD_SYNC_T2_CFG_PART1_POL_HIGH	0x0000
+#define	VFE_CMD_SYNC_T2_CFG_PART1_POL_LOW	0x0002
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	sync_t2_cfg_part1;
+	unsigned int	sync_t2_h_sync_countdown;
+	unsigned int	sync_t2_pclk_countdown;
+	unsigned int	sync_t2_duration;
+} __attribute__((packed)) vfe_cmd_sync_timer2_cfg;
+
+
+/*
+ * Command to configure and start asynchronous timer1
+ */
+
+#define	VFE_CMD_ASYNC_TIMER1_START	0x001B
+#define	VFE_CMD_ASYNC_TIMER1_START_LEN	\
+	sizeof(vfe_cmd_async_timer1_start)
+
+#define	VFE_CMD_ASYNC_T1_POLARITY_A_HIGH	0x0000
+#define	VFE_CMD_ASYNC_T1_POLARITY_A_LOW		0x0001
+#define	VFE_CMD_ASYNC_T1_POLARITY_B_HIGH	0x0000
+#define	VFE_CMD_ASYNC_T1_POLARITY_B_LOW		0x0002
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	async_t1a_cfg;
+	unsigned int	async_t1b_cfg;
+	unsigned int	async_t1_polarity;
+} __attribute__((packed)) vfe_cmd_async_timer1_start;
+
+
+/*
+ * Command to configure and start asynchronous timer2
+ */
+
+#define	VFE_CMD_ASYNC_TIMER2_START	0x001C
+#define	VFE_CMD_ASYNC_TIMER2_START_LEN	\
+	sizeof(vfe_cmd_async_timer2_start)
+
+#define	VFE_CMD_ASYNC_T2_POLARITY_A_HIGH	0x0000
+#define	VFE_CMD_ASYNC_T2_POLARITY_A_LOW		0x0001
+#define	VFE_CMD_ASYNC_T2_POLARITY_B_HIGH	0x0000
+#define	VFE_CMD_ASYNC_T2_POLARITY_B_LOW		0x0002
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	async_t2a_cfg;
+	unsigned int	async_t2b_cfg;
+	unsigned int	async_t2_polarity;
+} __attribute__((packed)) vfe_cmd_async_timer2_start;
+
+
+/*
+ * Command to program partial configurations of auto focus(af)
+ */
+
+#define	VFE_CMD_STATS_AF_UPDATE		0x001D
+#define	VFE_CMD_STATS_AF_UPDATE_LEN	\
+	sizeof(vfe_cmd_stats_af_update)
+
+#define	VFE_CMD_AF_UPDATE_PART1_WINDOW_ONE	0x00000000
+#define	VFE_CMD_AF_UPDATE_PART1_WINDOW_MULTI	0x80000000
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	af_update_part1;
+	unsigned int	af_update_part2;
+} __attribute__((packed)) vfe_cmd_stats_af_update;
+
+
+/*
+ * Command to program partial cfg of wb and exp
+ */
+
+#define	VFE_CMD_STATS_WB_EXP_UPDATE	0x001E
+#define	VFE_CMD_STATS_WB_EXP_UPDATE_LEN	\
+	sizeof(vfe_cmd_stats_wb_exp_update)
+
+#define	VFE_CMD_WB_EXP_UPDATE_PART1_REGIONS_8_8		0x0000
+#define	VFE_CMD_WB_EXP_UPDATE_PART1_REGIONS_16_16	0x0001
+#define	VFE_CMD_WB_EXP_UPDATE_PART1_SREGIONS_8_8	0x0000
+#define	VFE_CMD_WB_EXP_UPDATE_PART1_SREGIONS_4_4	0x0002
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	wb_exp_update_part1;
+	unsigned int	wb_exp_update_part2;
+	unsigned int	wb_exp_update_part3;
+	unsigned int	wb_exp_update_part4;
+} __attribute__((packed)) vfe_cmd_stats_wb_exp_update;
+
+
+
+/*
+ * Command to re program the CAMIF FRAME CONFIG settings
+ */
+
+#define	VFE_CMD_UPDATE_CAMIF_FRAME_CFG		0x001F
+#define	VFE_CMD_UPDATE_CAMIF_FRAME_CFG_LEN	\
+	sizeof(vfe_cmd_update_camif_frame_cfg)
+
+typedef struct {
+	unsigned int	cmd_id;
+	unsigned int	camif_frame_cfg;
+} __attribute__((packed)) vfe_cmd_update_camif_frame_cfg;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5vfemsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5vfemsg.h
new file mode 100644
index 0000000..0053cfb
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5vfemsg.h
@@ -0,0 +1,290 @@
+#ifndef QDSP5VFEMSGI_H
+#define QDSP5VFEMSGI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+    V F E   I N T E R N A L   M E S S A G E S
+
+GENERAL DESCRIPTION
+  This file contains defintions of format blocks of commands
+  that are sent by VFE Task
+
+REFERENCES
+  None
+
+EXTERNALIZED FUNCTIONS
+  None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+                      EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5vfemsg.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when       who     what, where, why
+--------   ---     ----------------------------------------------------------
+06/12/08   sv      initial version
+===========================================================================*/
+
+
+/*
+ * Message to acknowledge CMD_VFE_REST command
+ */
+
+#define	VFE_MSG_RESET_ACK	0x0000
+#define	VFE_MSG_RESET_ACK_LEN	sizeof(vfe_msg_reset_ack)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_reset_ack;
+
+
+/*
+ * Message to acknowledge CMD_VFE_START command
+ */
+
+#define	VFE_MSG_START_ACK	0x0001
+#define	VFE_MSG_START_ACK_LEN	sizeof(vfe_msg_start_ack)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_start_ack;
+
+/*
+ * Message to acknowledge CMD_VFE_STOP	command
+ */
+
+#define	VFE_MSG_STOP_ACK	0x0002
+#define	VFE_MSG_STOP_ACK_LEN	sizeof(vfe_msg_stop_ack)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_stop_ack;
+
+
+/*
+ * Message to acknowledge CMD_VFE_UPDATE command
+ */
+
+#define	VFE_MSG_UPDATE_ACK	0x0003
+#define	VFE_MSG_UPDATE_ACK_LEN	sizeof(vfe_msg_update_ack)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_update_ack;
+
+
+/*
+ * Message to notify the ARM that snapshot processing is complete
+ * and that the VFE is now STATE_VFE_IDLE
+ */
+
+#define	VFE_MSG_SNAPSHOT_DONE		0x0004
+#define	VFE_MSG_SNAPSHOT_DONE_LEN	\
+	sizeof(vfe_msg_snapshot_done)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_snapshot_done;
+
+
+
+/*
+ * Message to notify ARM that illegal cmd was received and
+ * system is in the IDLE state
+ */
+
+#define	VFE_MSG_ILLEGAL_CMD	0x0005
+#define	VFE_MSG_ILLEGAL_CMD_LEN	\
+	sizeof(vfe_msg_illegal_cmd)
+
+typedef struct {
+	unsigned int	status;
+} __attribute__((packed)) vfe_msg_illegal_cmd;
+
+
+/*
+ * Message to notify ARM that op1 buf is full and ready
+ */
+
+#define	VFE_MSG_OP1		0x0006
+#define	VFE_MSG_OP1_LEN		sizeof(vfe_msg_op1)
+
+typedef struct {
+	unsigned int	op1_buf_y_addr;
+	unsigned int	op1_buf_cbcr_addr;
+	unsigned int	black_level_even_col;
+	unsigned int	black_level_odd_col;
+	unsigned int	defect_pixels_detected;
+	unsigned int	asf_max_edge;
+} __attribute__((packed)) vfe_msg_op1;
+
+
+/*
+ * Message to notify ARM that op2 buf is full and ready
+ */
+
+#define	VFE_MSG_OP2		0x0007
+#define	VFE_MSG_OP2_LEN		sizeof(vfe_msg_op2)
+
+typedef struct {
+	unsigned int	op2_buf_y_addr;
+	unsigned int	op2_buf_cbcr_addr;
+	unsigned int	black_level_even_col;
+	unsigned int	black_level_odd_col;
+	unsigned int	defect_pixels_detected;
+	unsigned int	asf_max_edge;
+} __attribute__((packed)) vfe_msg_op2;
+
+
+/*
+ * Message to notify ARM that autofocus(af) stats are ready
+ */
+
+#define	VFE_MSG_STATS_AF	0x0008
+#define	VFE_MSG_STATS_AF_LEN	sizeof(vfe_msg_stats_af)
+
+typedef struct {
+	unsigned int	af_stats_op_buffer;
+} __attribute__((packed)) vfe_msg_stats_af;
+
+
+/*
+ * Message to notify ARM that white balance(wb) and exposure (exp)
+ * stats are ready
+ */
+
+#define	VFE_MSG_STATS_WB_EXP		0x0009
+#define	VFE_MSG_STATS_WB_EXP_LEN	\
+	sizeof(vfe_msg_stats_wb_exp)
+
+typedef struct {
+	unsigned int	wb_exp_stats_op_buf;
+} __attribute__((packed)) vfe_msg_stats_wb_exp;
+
+
+/*
+ * Message to notify the ARM that histogram(hg) stats are ready
+ */
+
+#define	VFE_MSG_STATS_HG	0x000A
+#define	VFE_MSG_STATS_HG_LEN	sizeof(vfe_msg_stats_hg)
+
+typedef struct {
+	unsigned int	hg_stats_op_buf;
+} __attribute__((packed)) vfe_msg_stats_hg;
+
+
+/*
+ * Message to notify the ARM that epoch1 event occurred in the CAMIF
+ */
+
+#define	VFE_MSG_EPOCH1		0x000B
+#define	VFE_MSG_EPOCH1_LEN	sizeof(vfe_msg_epoch1)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_epoch1;
+
+
+/*
+ * Message to notify the ARM that epoch2 event occurred in the CAMIF
+ */
+
+#define	VFE_MSG_EPOCH2		0x000C
+#define	VFE_MSG_EPOCH2_LEN	sizeof(vfe_msg_epoch2)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_epoch2;
+
+
+/*
+ * Message to notify the ARM that sync timer1 op is completed
+ */
+
+#define	VFE_MSG_SYNC_T1_DONE		0x000D
+#define	VFE_MSG_SYNC_T1_DONE_LEN	sizeof(vfe_msg_sync_t1_done)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_sync_t1_done;
+
+
+/*
+ * Message to notify the ARM that sync timer2 op is completed
+ */
+
+#define	VFE_MSG_SYNC_T2_DONE		0x000E
+#define	VFE_MSG_SYNC_T2_DONE_LEN	sizeof(vfe_msg_sync_t2_done)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_sync_t2_done;
+
+
+/*
+ * Message to notify the ARM that async t1 operation completed
+ */
+
+#define	VFE_MSG_ASYNC_T1_DONE		0x000F
+#define	VFE_MSG_ASYNC_T1_DONE_LEN	sizeof(vfe_msg_async_t1_done)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_async_t1_done;
+
+
+
+/*
+ * Message to notify the ARM that async t2 operation completed
+ */
+
+#define	VFE_MSG_ASYNC_T2_DONE		0x0010
+#define	VFE_MSG_ASYNC_T2_DONE_LEN	sizeof(vfe_msg_async_t2_done)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_async_t2_done;
+
+
+
+/*
+ * Message to notify the ARM that an error has occurred
+ */
+
+#define	VFE_MSG_ERROR		0x0011
+#define	VFE_MSG_ERROR_LEN	sizeof(vfe_msg_error)
+
+#define	VFE_MSG_ERR_COND_NO_CAMIF_ERR		0x0000
+#define	VFE_MSG_ERR_COND_CAMIF_ERR		0x0001
+#define	VFE_MSG_ERR_COND_OP1_Y_NO_BUS_OF	0x0000
+#define	VFE_MSG_ERR_COND_OP1_Y_BUS_OF		0x0002
+#define	VFE_MSG_ERR_COND_OP1_CBCR_NO_BUS_OF	0x0000
+#define	VFE_MSG_ERR_COND_OP1_CBCR_BUS_OF	0x0004
+#define	VFE_MSG_ERR_COND_OP2_Y_NO_BUS_OF	0x0000
+#define	VFE_MSG_ERR_COND_OP2_Y_BUS_OF		0x0008
+#define	VFE_MSG_ERR_COND_OP2_CBCR_NO_BUS_OF	0x0000
+#define	VFE_MSG_ERR_COND_OP2_CBCR_BUS_OF	0x0010
+#define	VFE_MSG_ERR_COND_AF_NO_BUS_OF		0x0000
+#define	VFE_MSG_ERR_COND_AF_BUS_OF		0x0020
+#define	VFE_MSG_ERR_COND_WB_EXP_NO_BUS_OF	0x0000
+#define	VFE_MSG_ERR_COND_WB_EXP_BUS_OF		0x0040
+#define	VFE_MSG_ERR_COND_NO_AXI_ERR		0x0000
+#define	VFE_MSG_ERR_COND_AXI_ERR		0x0080
+
+#define	VFE_MSG_CAMIF_STS_IDLE			0x0000
+#define	VFE_MSG_CAMIF_STS_CAPTURE_DATA		0x0001
+
+typedef struct {
+	unsigned int	err_cond;
+	unsigned int	camif_sts;
+} __attribute__((packed)) vfe_msg_error;
+
+
+#endif
diff --git a/drivers/staging/dream/include/media/msm_camera.h b/drivers/staging/dream/include/media/msm_camera.h
new file mode 100644
index 0000000..09812d6
--- /dev/null
+++ b/drivers/staging/dream/include/media/msm_camera.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2008-2009 QUALCOMM Incorporated.
+ */
+#ifndef __LINUX_MSM_CAMERA_H
+#define __LINUX_MSM_CAMERA_H
+
+#include <linux/types.h>
+#include <asm/sizes.h>
+#include <linux/ioctl.h>
+
+#define MSM_CAM_IOCTL_MAGIC 'm'
+
+#define MSM_CAM_IOCTL_GET_SENSOR_INFO \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 1, struct msm_camsensor_info *)
+
+#define MSM_CAM_IOCTL_REGISTER_PMEM \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 2, struct msm_pmem_info *)
+
+#define MSM_CAM_IOCTL_UNREGISTER_PMEM \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 3, unsigned)
+
+#define MSM_CAM_IOCTL_CTRL_COMMAND \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 4, struct msm_ctrl_cmd *)
+
+#define MSM_CAM_IOCTL_CONFIG_VFE  \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 5, struct msm_camera_vfe_cfg_cmd *)
+
+#define MSM_CAM_IOCTL_GET_STATS \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 6, struct msm_camera_stats_event_ctrl *)
+
+#define MSM_CAM_IOCTL_GETFRAME \
+	_IOR(MSM_CAM_IOCTL_MAGIC, 7, struct msm_camera_get_frame *)
+
+#define MSM_CAM_IOCTL_ENABLE_VFE \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 8, struct camera_enable_cmd *)
+
+#define MSM_CAM_IOCTL_CTRL_CMD_DONE \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 9, struct camera_cmd *)
+
+#define MSM_CAM_IOCTL_CONFIG_CMD \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 10, struct camera_cmd *)
+
+#define MSM_CAM_IOCTL_DISABLE_VFE \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 11, struct camera_enable_cmd *)
+
+#define MSM_CAM_IOCTL_PAD_REG_RESET2 \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 12, struct camera_enable_cmd *)
+
+#define MSM_CAM_IOCTL_VFE_APPS_RESET \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 13, struct camera_enable_cmd *)
+
+#define MSM_CAM_IOCTL_RELEASE_FRAME_BUFFER \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 14, struct camera_enable_cmd *)
+
+#define MSM_CAM_IOCTL_RELEASE_STATS_BUFFER \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 15, struct msm_stats_buf *)
+
+#define MSM_CAM_IOCTL_AXI_CONFIG \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 16, struct msm_camera_vfe_cfg_cmd *)
+
+#define MSM_CAM_IOCTL_GET_PICTURE \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 17, struct msm_camera_ctrl_cmd *)
+
+#define MSM_CAM_IOCTL_SET_CROP \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 18, struct crop_info *)
+
+#define MSM_CAM_IOCTL_PICT_PP \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 19, uint8_t *)
+
+#define MSM_CAM_IOCTL_PICT_PP_DONE \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 20, struct msm_snapshot_pp_status *)
+
+#define MSM_CAM_IOCTL_SENSOR_IO_CFG \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 21, struct sensor_cfg_data *)
+
+#define MSM_CAMERA_LED_OFF  0
+#define MSM_CAMERA_LED_LOW  1
+#define MSM_CAMERA_LED_HIGH 2
+
+#define MSM_CAM_IOCTL_FLASH_LED_CFG \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 22, unsigned *)
+
+#define MSM_CAM_IOCTL_UNBLOCK_POLL_FRAME \
+	_IO(MSM_CAM_IOCTL_MAGIC, 23)
+
+#define MSM_CAM_IOCTL_CTRL_COMMAND_2 \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 24, struct msm_ctrl_cmd *)
+
+#define MAX_SENSOR_NUM  3
+#define MAX_SENSOR_NAME 32
+
+#define MSM_CAM_CTRL_CMD_DONE  0
+#define MSM_CAM_SENSOR_VFE_CMD 1
+
+/*****************************************************
+ *  structure
+ *****************************************************/
+
+/* define five type of structures for userspace <==> kernel
+ * space communication:
+ * command 1 - 2 are from userspace ==> kernel
+ * command 3 - 4 are from kernel ==> userspace
+ *
+ * 1. control command: control command(from control thread),
+ *                     control status (from config thread);
+ */
+struct msm_ctrl_cmd {
+	uint16_t type;
+	uint16_t length;
+	void *value;
+	uint16_t status;
+	uint32_t timeout_ms;
+	int resp_fd; /* FIXME: to be used by the kernel, pass-through for now */
+};
+
+struct msm_vfe_evt_msg {
+	unsigned short type; /* 1 == event (RPC), 0 == message (adsp) */
+	unsigned short msg_id;
+	unsigned int len; /* size in, number of bytes out */
+	void *data;
+};
+
+#define MSM_CAM_RESP_CTRL         0
+#define MSM_CAM_RESP_STAT_EVT_MSG 1
+#define MSM_CAM_RESP_V4L2         2
+#define MSM_CAM_RESP_MAX          3
+
+/* this one is used to send ctrl/status up to config thread */
+struct msm_stats_event_ctrl {
+	/* 0 - ctrl_cmd from control thread,
+	 * 1 - stats/event kernel,
+	 * 2 - V4L control or read request */
+	int resptype;
+	int timeout_ms;
+	struct msm_ctrl_cmd ctrl_cmd;
+	/* struct  vfe_event_t  stats_event; */
+	struct msm_vfe_evt_msg stats_event;
+};
+
+/* 2. config command: config command(from config thread); */
+struct msm_camera_cfg_cmd {
+	/* what to config:
+	 * 1 - sensor config, 2 - vfe config */
+	uint16_t cfg_type;
+
+	/* sensor config type */
+	uint16_t cmd_type;
+	uint16_t queue;
+	uint16_t length;
+	void *value;
+};
+
+#define CMD_GENERAL			0
+#define CMD_AXI_CFG_OUT1		1
+#define CMD_AXI_CFG_SNAP_O1_AND_O2	2
+#define CMD_AXI_CFG_OUT2		3
+#define CMD_PICT_T_AXI_CFG		4
+#define CMD_PICT_M_AXI_CFG		5
+#define CMD_RAW_PICT_AXI_CFG		6
+#define CMD_STATS_AXI_CFG		7
+#define CMD_STATS_AF_AXI_CFG		8
+#define CMD_FRAME_BUF_RELEASE		9
+#define CMD_PREV_BUF_CFG		10
+#define CMD_SNAP_BUF_RELEASE		11
+#define CMD_SNAP_BUF_CFG		12
+#define CMD_STATS_DISABLE		13
+#define CMD_STATS_ENABLE		14
+#define CMD_STATS_AF_ENABLE		15
+#define CMD_STATS_BUF_RELEASE		16
+#define CMD_STATS_AF_BUF_RELEASE	17
+#define UPDATE_STATS_INVALID		18
+
+/* vfe config command: config command(from config thread)*/
+struct msm_vfe_cfg_cmd {
+	int cmd_type;
+	uint16_t length;
+	void *value;
+};
+
+#define MAX_CAMERA_ENABLE_NAME_LEN 32
+struct camera_enable_cmd {
+	char name[MAX_CAMERA_ENABLE_NAME_LEN];
+};
+
+#define MSM_PMEM_OUTPUT1		0
+#define MSM_PMEM_OUTPUT2		1
+#define MSM_PMEM_OUTPUT1_OUTPUT2	2
+#define MSM_PMEM_THUMBAIL		3
+#define MSM_PMEM_MAINIMG		4
+#define MSM_PMEM_RAW_MAINIMG		5
+#define MSM_PMEM_AEC_AWB		6
+#define MSM_PMEM_AF			7
+#define MSM_PMEM_MAX			8
+
+#define FRAME_PREVIEW_OUTPUT1		0
+#define FRAME_PREVIEW_OUTPUT2		1
+#define FRAME_SNAPSHOT			2
+#define FRAME_THUMBAIL			3
+#define FRAME_RAW_SNAPSHOT		4
+#define FRAME_MAX			5
+
+struct msm_pmem_info {
+	int type;
+	int fd;
+	void *vaddr;
+	uint32_t y_off;
+	uint32_t cbcr_off;
+	uint8_t active;
+};
+
+struct outputCfg {
+	uint32_t height;
+	uint32_t width;
+
+	uint32_t window_height_firstline;
+	uint32_t window_height_lastline;
+};
+
+#define OUTPUT_1	0
+#define OUTPUT_2	1
+#define OUTPUT_1_AND_2	2
+#define CAMIF_TO_AXI_VIA_OUTPUT_2		3
+#define OUTPUT_1_AND_CAMIF_TO_AXI_VIA_OUTPUT_2	4
+#define OUTPUT_2_AND_CAMIF_TO_AXI_VIA_OUTPUT_1	5
+#define LAST_AXI_OUTPUT_MODE_ENUM = OUTPUT_2_AND_CAMIF_TO_AXI_VIA_OUTPUT_1 6
+
+#define MSM_FRAME_PREV_1	0
+#define MSM_FRAME_PREV_2	1
+#define MSM_FRAME_ENC		2
+
+struct msm_frame {
+	int path;
+	unsigned long buffer;
+	uint32_t y_off;
+	uint32_t cbcr_off;
+	int fd;
+
+	void *cropinfo;
+	int croplen;
+};
+
+#define STAT_AEAW	0
+#define STAT_AF		1
+#define STAT_MAX	2
+
+struct msm_stats_buf {
+	int type;
+	unsigned long buffer;
+	int fd;
+};
+
+#define MSM_V4L2_VID_CAP_TYPE	0
+#define MSM_V4L2_STREAM_ON	1
+#define MSM_V4L2_STREAM_OFF	2
+#define MSM_V4L2_SNAPSHOT	3
+#define MSM_V4L2_QUERY_CTRL	4
+#define MSM_V4L2_GET_CTRL	5
+#define MSM_V4L2_SET_CTRL	6
+#define MSM_V4L2_QUERY		7
+#define MSM_V4L2_MAX		8
+
+struct crop_info {
+	void *info;
+	int len;
+};
+
+struct msm_postproc {
+	int ftnum;
+	struct msm_frame fthumnail;
+	int fmnum;
+	struct msm_frame fmain;
+};
+
+struct msm_snapshot_pp_status {
+	void *status;
+};
+
+#define CFG_SET_MODE			0
+#define CFG_SET_EFFECT			1
+#define CFG_START			2
+#define CFG_PWR_UP			3
+#define CFG_PWR_DOWN			4
+#define CFG_WRITE_EXPOSURE_GAIN		5
+#define CFG_SET_DEFAULT_FOCUS		6
+#define CFG_MOVE_FOCUS			7
+#define CFG_REGISTER_TO_REAL_GAIN	8
+#define CFG_REAL_TO_REGISTER_GAIN	9
+#define CFG_SET_FPS			10
+#define CFG_SET_PICT_FPS		11
+#define CFG_SET_BRIGHTNESS		12
+#define CFG_SET_CONTRAST		13
+#define CFG_SET_ZOOM			14
+#define CFG_SET_EXPOSURE_MODE		15
+#define CFG_SET_WB			16
+#define CFG_SET_ANTIBANDING		17
+#define CFG_SET_EXP_GAIN		18
+#define CFG_SET_PICT_EXP_GAIN		19
+#define CFG_SET_LENS_SHADING		20
+#define CFG_GET_PICT_FPS		21
+#define CFG_GET_PREV_L_PF		22
+#define CFG_GET_PREV_P_PL		23
+#define CFG_GET_PICT_L_PF		24
+#define CFG_GET_PICT_P_PL		25
+#define CFG_GET_AF_MAX_STEPS		26
+#define CFG_GET_PICT_MAX_EXP_LC		27
+#define CFG_MAX				28
+
+#define MOVE_NEAR	0
+#define MOVE_FAR	1
+
+#define SENSOR_PREVIEW_MODE		0
+#define SENSOR_SNAPSHOT_MODE		1
+#define SENSOR_RAW_SNAPSHOT_MODE	2
+
+#define SENSOR_QTR_SIZE			0
+#define SENSOR_FULL_SIZE		1
+#define SENSOR_INVALID_SIZE		2
+
+#define CAMERA_EFFECT_OFF		0
+#define CAMERA_EFFECT_MONO		1
+#define CAMERA_EFFECT_NEGATIVE		2
+#define CAMERA_EFFECT_SOLARIZE		3
+#define CAMERA_EFFECT_PASTEL		4
+#define CAMERA_EFFECT_MOSAIC		5
+#define CAMERA_EFFECT_RESIZE		6
+#define CAMERA_EFFECT_SEPIA		7
+#define CAMERA_EFFECT_POSTERIZE		8
+#define CAMERA_EFFECT_WHITEBOARD	9
+#define CAMERA_EFFECT_BLACKBOARD	10
+#define CAMERA_EFFECT_AQUA		11
+#define CAMERA_EFFECT_MAX		12
+
+struct sensor_pict_fps {
+	uint16_t prevfps;
+	uint16_t pictfps;
+};
+
+struct exp_gain_cfg {
+	uint16_t gain;
+	uint32_t line;
+};
+
+struct focus_cfg {
+	int32_t steps;
+	int dir;
+};
+
+struct fps_cfg {
+	uint16_t f_mult;
+	uint16_t fps_div;
+	uint32_t pict_fps_div;
+};
+
+struct sensor_cfg_data {
+	int cfgtype;
+	int mode;
+	int rs;
+	uint8_t max_steps;
+
+	union {
+		int8_t effect;
+		uint8_t lens_shading;
+		uint16_t prevl_pf;
+		uint16_t prevp_pl;
+		uint16_t pictl_pf;
+		uint16_t pictp_pl;
+		uint32_t pict_max_exp_lc;
+		uint16_t p_fps;
+		struct sensor_pict_fps gfps;
+		struct exp_gain_cfg exp_gain;
+		struct focus_cfg focus;
+		struct fps_cfg fps;
+	} cfg;
+};
+
+#define GET_NAME			0
+#define GET_PREVIEW_LINE_PER_FRAME	1
+#define GET_PREVIEW_PIXELS_PER_LINE	2
+#define GET_SNAPSHOT_LINE_PER_FRAME	3
+#define GET_SNAPSHOT_PIXELS_PER_LINE	4
+#define GET_SNAPSHOT_FPS		5
+#define GET_SNAPSHOT_MAX_EP_LINE_CNT	6
+
+struct msm_camsensor_info {
+	char name[MAX_SENSOR_NAME];
+	uint8_t flash_enabled;
+};
+#endif /* __LINUX_MSM_CAMERA_H */
diff --git a/drivers/staging/dream/pmem.c b/drivers/staging/dream/pmem.c
index def6468..503ba21 100644
--- a/drivers/staging/dream/pmem.c
+++ b/drivers/staging/dream/pmem.c
@@ -37,17 +37,17 @@
  * the file should not be released until put_pmem_file is called */
 #define PMEM_FLAGS_BUSY 0x1
 /* indicates that this is a suballocation of a larger master range */
-#define PMEM_FLAGS_CONNECTED 0x1 << 1
+#define PMEM_FLAGS_CONNECTED ( 0x1 << 1 )
 /* indicates this is a master and not a sub allocation and that it is mmaped */
-#define PMEM_FLAGS_MASTERMAP 0x1 << 2
+#define PMEM_FLAGS_MASTERMAP ( 0x1 << 2 )
 /* submap and unsubmap flags indicate:
  * 00: subregion has never been mmaped
  * 10: subregion has been mmaped, reference to the mm was taken
  * 11: subretion has ben released, refernece to the mm still held
  * 01: subretion has been released, reference to the mm has been released
  */
-#define PMEM_FLAGS_SUBMAP 0x1 << 3
-#define PMEM_FLAGS_UNSUBMAP 0x1 << 4
+#define PMEM_FLAGS_SUBMAP ( 0x1 << 3 )
+#define PMEM_FLAGS_UNSUBMAP ( 0x1 << 4 )
 
 
 struct pmem_data {
@@ -91,7 +91,7 @@
 
 #define PMEM_DEBUG_MSGS 0
 #if PMEM_DEBUG_MSGS
-#define DLOG(fmt,args...) \
+#define DLOG(fmt, args...) \
 	do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
 		    ##args); } \
 	while (0)
@@ -152,7 +152,7 @@
 static struct pmem_info pmem[PMEM_MAX_DEVICES];
 static int id_count;
 
-#define PMEM_IS_FREE(id, index) !(pmem[id].bitmap[index].allocated)
+#define PMEM_IS_FREE(id, index) ( !(pmem[id].bitmap[index].allocated) )
 #define PMEM_ORDER(id, index) pmem[id].bitmap[index].order
 #define PMEM_BUDDY_INDEX(id, index) (index ^ (1 << PMEM_ORDER(id, index)))
 #define PMEM_NEXT_INDEX(id, index) (index + (1 << PMEM_ORDER(id, index)))
@@ -708,9 +708,8 @@
 	struct pmem_data *data;
 	int id;
 
-	if (!is_pmem_file(file) || !has_allocation(file)) {
+	if (!is_pmem_file(file) || !has_allocation(file))
 		return -1;
-	}
 
 	data = (struct pmem_data *)file->private_data;
 	if (data->index == -1) {
@@ -789,9 +788,8 @@
 	struct list_head *elt;
 	void *flush_start, *flush_end;
 
-	if (!is_pmem_file(file) || !has_allocation(file)) {
+	if (!is_pmem_file(file) || !has_allocation(file))
 		return;
-	}
 
 	id = get_id(file);
 	data = (struct pmem_data *)file->private_data;
@@ -833,7 +831,7 @@
 	src_file = fget_light(connect, &put_needed);
 	DLOG("connect %p to %p\n", file, src_file);
 	if (!src_file) {
-		printk("pmem: src file not found!\n");
+		printk(KERN_INFO "pmem: src file not found!\n");
 		ret = -EINVAL;
 		goto err_no_file;
 	}
@@ -846,7 +844,7 @@
 	src_data = (struct pmem_data *)src_file->private_data;
 
 	if (has_allocation(file) && (data->index != src_data->index)) {
-		printk("pmem: file is already mapped but doesn't match this"
+		printk(KERN_INFO "pmem: file is already mapped but doesn't match this"
 		       " src_file!\n");
 		ret = -EINVAL;
 		goto err_bad_file;
@@ -885,7 +883,7 @@
 		mm = get_task_mm(data->task);
 		if (!mm) {
 #if PMEM_DEBUG
-			printk("pmem: can't remap task is gone!\n");
+			printk(KERN_DEBUG "pmem: can't remap task is gone!\n");
 #endif
 			up_read(&data->sem);
 			return -1;
@@ -936,7 +934,7 @@
 	if (unlikely(!PMEM_IS_PAGE_ALIGNED(region->offset) ||
 		 !PMEM_IS_PAGE_ALIGNED(region->len))) {
 #if PMEM_DEBUG
-		printk("pmem: request for unaligned pmem suballocation "
+		printk(KERN_DEBUG "pmem: request for unaligned pmem suballocation "
 		       "%lx %lx\n", region->offset, region->len);
 #endif
 		return -EINVAL;
diff --git a/drivers/staging/dream/qdsp5/Makefile b/drivers/staging/dream/qdsp5/Makefile
index 991d4a7..beedaaf 100644
--- a/drivers/staging/dream/qdsp5/Makefile
+++ b/drivers/staging/dream/qdsp5/Makefile
@@ -1,3 +1,4 @@
+EXTRA_CFLAGS=-Idrivers/staging/dream/include
 obj-y += adsp.o
 ifeq ($(CONFIG_MSM_AMSS_VERSION_6350),y)
 obj-y += adsp_info.o
diff --git a/drivers/staging/dream/qdsp5/audio_mp3.c b/drivers/staging/dream/qdsp5/audio_mp3.c
index b95574f..7ed6e26 100644
--- a/drivers/staging/dream/qdsp5/audio_mp3.c
+++ b/drivers/staging/dream/qdsp5/audio_mp3.c
@@ -650,8 +650,7 @@
 						       &audio->read_phys,
 						       GFP_KERNEL);
 				if (!audio->read_data) {
-					pr_err("audio_mp3: malloc pcm \
-					buf failed\n");
+					pr_err("audio_mp3: malloc pcm buf failed\n");
 					rc = -1;
 				} else {
 					uint8_t index;
diff --git a/drivers/staging/dream/smd/Makefile b/drivers/staging/dream/smd/Makefile
index 892c741..1c87618 100644
--- a/drivers/staging/dream/smd/Makefile
+++ b/drivers/staging/dream/smd/Makefile
@@ -1,3 +1,4 @@
+EXTRA_CFLAGS=-Idrivers/staging/dream/include
 obj-$(CONFIG_MSM_SMD) += smd.o smd_tty.o smd_qmi.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_device.o
diff --git a/drivers/staging/dream/smd/smd_rpcrouter.c b/drivers/staging/dream/smd/smd_rpcrouter.c
index 5ac2cd4..69911a7 100644
--- a/drivers/staging/dream/smd/smd_rpcrouter.c
+++ b/drivers/staging/dream/smd/smd_rpcrouter.c
@@ -38,8 +38,6 @@
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
 
-#include <asm/byteorder.h>
-
 #include <mach/msm_smd.h>
 #include "smd_rpcrouter.h"
 
diff --git a/drivers/staging/dt3155/Kconfig b/drivers/staging/dt3155/Kconfig
new file mode 100644
index 0000000..4a3293c
--- /dev/null
+++ b/drivers/staging/dt3155/Kconfig
@@ -0,0 +1,4 @@
+config DT3155
+	tristate "DT3155 Digitizer support"
+	depends on PCI
+
diff --git a/drivers/staging/dt3155/Makefile b/drivers/staging/dt3155/Makefile
new file mode 100644
index 0000000..136f21f
--- /dev/null
+++ b/drivers/staging/dt3155/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_DT3155)	+= dt3155.o
+dt3155-objs :=	\
+		dt3155_drv.o	\
+		dt3155_isr.o	\
+		dt3155_io.o	\
+		allocator.o
diff --git a/drivers/staging/dt3155/TODO b/drivers/staging/dt3155/TODO
new file mode 100644
index 0000000..3baa3b6
--- /dev/null
+++ b/drivers/staging/dt3155/TODO
@@ -0,0 +1,10 @@
+TODO:
+	- fix checkpatch.pl issues
+	- remove old kernel support, it is not needed
+	- convert to proper PCI device API
+	- fix sparse warnings
+	- audit for correct subsystem interaction
+	- review review review!
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com>
+and Scott Smedley <ss@aao.gov.au>
diff --git a/drivers/staging/dt3155/allocator.README b/drivers/staging/dt3155/allocator.README
new file mode 100644
index 0000000..05700b6
--- /dev/null
+++ b/drivers/staging/dt3155/allocator.README
@@ -0,0 +1,98 @@
+
+The allocator shown here  exploits high memory. This document explains
+how  a user can  deal   with drivers uses   this  allocator and how  a
+programmer can link in the module.
+
+The module is being used by my pxc and pxdrv device drivers (as well as
+other ones), available from ftp.systemy.it/pub/develop and
+ftp.linux.it/pub/People/Rubini
+
+	User's manual
+	=============
+
+
+One of the most compelling problems with any DMA-capable device is the
+allocation  of a suitable  memory buffer. The "allocator" module tries
+to deal with  the problem in  a clean way.  The module is  able to use
+high   memory  (above the  one   used in  normal   operation)  for DMA
+allocation.
+
+To prevent  the  kernel for using   high memory,  so  that it  remains
+available for  DMA, you should  pass a  command  line argument to  the
+kernel.  Command line arguments  can be passed to  Lilo, to Loadlin or
+to whichever loader  you are using  (unless it's very poor in design).
+For Lilo, either use  "append=" in  /etc/lilo.conf or add  commandline
+arguments to the  interactive prompt. For  example, I have a 32MB  box
+and reserve two megs for DMA:
+
+In lilo.conf:
+	image = /zImage
+	label = linux
+	append = "mem=30M"
+
+Or, interactively:
+	LILO: linux mem=30M
+
+Once  the kernel is booted  with the  right command-line argument, any
+driver  linked   with  the  allocator   module  will  be able   to get
+DMA-capable memory without  much  trouble (unless the  various drivers
+need more memory than available).
+
+The module implements an alloc/free  mechanism,  so that it can  serve
+multiple drivers  at the  same time. Note  however that  the allocator
+uses all of  high memory and assumes to  be the only piece of software
+using such memory.
+
+
+	Programmer's manual
+	===================
+
+The allocator,  as  released, is designed  to  be linked  to  a device
+driver.  In this  case, the driver  must call allocator_init()  before
+using   the  allocator   and  must  call   allocator_cleanup()  before
+unloading.  This is  usually  done   from within  init_module()    and
+cleanup_module(). If the allocator is linked to  a driver, it won't be
+possible for several drivers to allocate high DMA memory, as explained
+above.
+
+It is possible, on the other hand, to compile the module as a standalone
+module, so that several modules can rely on the allocator for they DMA
+buffers. To compile the allocator as a standalone module, do the
+following in this directory (or provide a suitable Makefile, or edit
+the source code):
+
+	make allocator.o CC="gcc -Dallocator_init=init_module -Dallocator_cleanup=cleanup_module -include /usr/include/linux/module.h"
+
+The previous commandline  tells   to include <linux/module.h>  in  the
+first place,  and to rename the init  and cleanup function to the ones
+needed for  module loading and  unloading.  Drivers using a standalone
+allocator won't need to call allocator_init() nor allocator_cleanup().
+
+The allocator exports the following functions (declared in allocator.h):
+
+   unsigned long allocator_allocate_dma (unsigned long kilobytes,
+					 int priority);
+
+	This function returns a physical address, over high_memory,
+	which corresponds to an area of at least "kilobytes" kilobytes.
+	The area will be owned by the module calling the function.
+	The returned address can be passed to device boards, to instruct
+	their DMA controllers, via phys_to_bus(). The address can be used
+	by C code after vremap()/ioremap(). The "priority" argument should
+	be GFP_KERNEL or GFP_ATOMIC, according to the context of the
+	caller; it is used to call kmalloc(), as the allocator must keep
+	track of any region it gives away. In case of error the function
+	returns 0, and the caller is expected to issue a -ENOMEM error.
+
+
+   void allocator_free_dma (unsigned long address);
+
+	This function is the reverse of the previous one. If a driver
+	doesn't free the DMA memory it allocated, the allocator will
+	consider such memory as busy. Note, however, that
+	allocator_cleanup() calls kfree() on every region it reclaimed,
+	so that a driver with the allocator linked in can avoid calling
+	allocator_free_dma() at unload time.
+
+
+
diff --git a/drivers/staging/dt3155/allocator.c b/drivers/staging/dt3155/allocator.c
new file mode 100644
index 0000000..c74234c
--- /dev/null
+++ b/drivers/staging/dt3155/allocator.c
@@ -0,0 +1,295 @@
+/*
+ * allocator.c -- allocate after high_memory, if available
+ *
+ * NOTE: this is different from my previous allocator, the one that
+ *       assembles pages, which revealed itself both slow and unreliable.
+ *
+ * Copyright (C) 1998   rubini@linux.it (Alessandro Rubini)
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You 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.
+ *
+
+-- Changes --
+
+  Date	      Programmer  Description of changes made
+  -------------------------------------------------------------------
+  02-Aug-2002 NJC         allocator now steps in 1MB increments, rather
+			  than doubling its size each time.
+			  Also, allocator_init(u32 *) now returns
+			  (in the first arg) the size of the free
+			  space.  This is no longer consistent with
+			  using the allocator as a module, and some changes
+			  may be necessary for that purpose.  This was
+			  designed to work with the DT3155 driver, in
+			  stand alone mode only!!!
+  26-Oct-2009 SS	  Port to 2.6.30 kernel.
+ */
+
+
+#ifndef __KERNEL__
+#  define __KERNEL__
+#endif
+#ifndef MODULE
+#  define MODULE
+#endif
+
+#include <linux/version.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/mm.h>	/* PAGE_ALIGN() */
+#include <linux/io.h>
+
+#include <asm/page.h>
+
+/*#define ALL_DEBUG*/
+#define ALL_MSG "allocator: "
+
+#undef PDEBUG             /* undef it, just in case */
+#ifdef ALL_DEBUG
+#  define __static
+#  define DUMP_LIST() dump_list()
+#  ifdef __KERNEL__
+     /* This one if debugging is on, and kernel space */
+#    define PDEBUG(fmt, args...) printk(KERN_DEBUG ALL_MSG fmt, ## args)
+#  else
+     /* This one for user space */
+#    define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
+#  endif
+#else
+#  define PDEBUG(fmt, args...) /* not debugging: nothing */
+#  define DUMP_LIST()
+#  define __static static
+#endif
+
+#undef PDEBUGG
+#define PDEBUGG(fmt, args...)
+/*#define PDEBUGG(fmt, args...) printk( KERN_DEBUG ALL_MSG fmt, ## args)*/
+
+
+int allocator_himem = 1; /* 0 = probe, pos. = megs, neg. = disable   */
+int allocator_step = 1;  /* This is the step size in MB              */
+int allocator_probe = 1; /* This is a flag -- 1=probe, 0=don't probe */
+
+static unsigned long allocator_buffer;		/* physical address */
+static unsigned long allocator_buffer_size;	/* kilobytes */
+
+/*
+ * The allocator keeps a list of DMA areas, so multiple devices
+ * can coexist. The list is kept sorted by address
+ */
+
+struct allocator_struct {
+	unsigned long address;
+	unsigned long size;
+	struct allocator_struct *next;
+};
+
+struct allocator_struct *allocator_list;
+
+
+#ifdef ALL_DEBUG
+static int dump_list(void)
+{
+	struct allocator_struct *ptr;
+
+	PDEBUG("Current list:\n");
+	for (ptr = allocator_list; ptr; ptr = ptr->next)
+		PDEBUG("0x%08lx (size %likB)\n", ptr->address, ptr->size>>10);
+	return 0;
+}
+#endif
+
+/* ========================================================================
+ * This function is the actual allocator.
+ *
+ * If space is available in high memory (as detected at load time), that
+ * one is returned. The return value is a physical address (i.e., it can
+ * be used straight ahead for DMA, but needs remapping for program use).
+ */
+
+unsigned long allocator_allocate_dma(unsigned long kilobytes, int prio)
+{
+	struct allocator_struct *ptr = allocator_list, *newptr;
+	unsigned long bytes = kilobytes << 10;
+
+	/* check if high memory is available */
+	if (!allocator_buffer)
+		return 0;
+
+	/* Round it to a multiple of the pagesize */
+	bytes = PAGE_ALIGN(bytes);
+	PDEBUG("request for %li bytes\n", bytes);
+
+	while (ptr && ptr->next) {
+		if (ptr->next->address - (ptr->address + ptr->size) >= bytes)
+			break; /* enough space */
+		ptr = ptr->next;
+	}
+	if (!ptr->next) {
+		DUMP_LIST();
+		PDEBUG("alloc failed\n");
+		return 0; /* end of list */
+	}
+	newptr = kmalloc(sizeof(struct allocator_struct), prio);
+	if (!newptr)
+		return 0;
+
+	/* ok, now stick it after ptr */
+	newptr->address = ptr->address + ptr->size;
+	newptr->size = bytes;
+	newptr->next = ptr->next;
+	ptr->next = newptr;
+
+	DUMP_LIST();
+	PDEBUG("returning 0x%08lx\n", newptr->address);
+	return newptr->address;
+}
+
+int allocator_free_dma(unsigned long address)
+{
+	struct allocator_struct *ptr = allocator_list, *prev;
+
+	while (ptr && ptr->next) {
+		if (ptr->next->address == address)
+			break;
+		ptr = ptr->next;
+	}
+	/* the one being freed is ptr->next */
+	prev = ptr; ptr = ptr->next;
+
+	if (!ptr) {
+		printk(KERN_ERR ALL_MSG
+			"free_dma(0x%08lx) but add. not allocated\n",
+			ptr->address);
+		return -EINVAL;
+	}
+	PDEBUGG("freeing: %08lx (%li) next %08lx\n", ptr->address, ptr->size,
+		ptr->next->address);
+	prev->next = ptr->next;
+	kfree(ptr);
+
+	/* dump_list(); */
+	return 0;
+}
+
+/* ========================================================================
+ * Init and cleanup
+ *
+ * On cleanup everything is released. If the list is not empty, that a
+ * problem of our clients
+ */
+int allocator_init(u32 *allocator_max)
+{
+	/* check how much free memory is there */
+	void *remapped;
+	unsigned long max;
+	unsigned long trial_size = allocator_himem<<20;
+	unsigned long last_trial = 0;
+	unsigned long step = allocator_step<<20;
+	unsigned long i = 0;
+	struct allocator_struct *head, *tail;
+	char test_string[] = "0123456789abcde"; /* 16 bytes */
+
+	PDEBUGG("himem = %i\n", allocator_himem);
+	if (allocator_himem < 0) /* don't even try */
+		return -EINVAL;
+
+	if (!trial_size)
+		trial_size = 1<<20; /* not specified: try one meg */
+
+	while (1) {
+		remapped = ioremap(__pa(high_memory), trial_size);
+		if (!remapped) {
+			PDEBUGG("%li megs failed!\n", trial_size>>20);
+			break;
+		}
+		PDEBUGG("Trying %li megs (at %p, %p)\n", trial_size>>20,
+			(void *)__pa(high_memory), remapped);
+		for (i = last_trial; i < trial_size; i += 16) {
+			strcpy((char *)(remapped)+i, test_string);
+			if (strcmp((char *)(remapped)+i, test_string))
+				break;
+			}
+		iounmap((void *)remapped);
+		schedule();
+		last_trial = trial_size;
+		if (i == trial_size)
+			trial_size += step; /* increment, if all went well */
+		else {
+			PDEBUGG("%li megs copy test failed!\n", trial_size>>20);
+			break;
+		}
+		if (!allocator_probe)
+			break;
+	}
+	PDEBUG("%li megs (%li k, %li b)\n", i>>20, i>>10, i);
+	allocator_buffer_size = i>>10; /* kilobytes */
+	allocator_buffer = __pa(high_memory);
+	if (!allocator_buffer_size) {
+		printk(KERN_WARNING ALL_MSG "no free high memory to use\n");
+		return -ENOMEM;
+	}
+
+	/*
+	* to simplify things, always have two cells in the list:
+	* the first and the last. This avoids some conditionals and
+	* extra code when allocating and deallocating: we only play
+	* in the middle of the list
+	*/
+	head = kmalloc(sizeof(struct allocator_struct), GFP_KERNEL);
+	if (!head)
+		return -ENOMEM;
+	tail = kmalloc(sizeof(struct allocator_struct), GFP_KERNEL);
+	if (!tail) {
+		kfree(head);
+		return -ENOMEM;
+	}
+
+	max = allocator_buffer_size<<10;
+
+	head->size = tail->size = 0;
+	head->address = allocator_buffer;
+	tail->address = allocator_buffer + max;
+	head->next = tail;
+	tail->next = NULL;
+	allocator_list = head;
+
+	/* Back to the user code, in KB */
+	*allocator_max = allocator_buffer_size;
+
+	return 0; /* ok, ready */
+}
+
+void allocator_cleanup(void)
+{
+	struct allocator_struct *ptr, *next;
+
+	for (ptr = allocator_list; ptr; ptr = next) {
+		next = ptr->next;
+		PDEBUG("freeing list: 0x%08lx\n", ptr->address);
+		kfree(ptr);
+	}
+
+	allocator_buffer      = 0;
+	allocator_buffer_size = 0;
+	allocator_list = NULL;
+}
+
+
diff --git a/drivers/staging/dt3155/allocator.h b/drivers/staging/dt3155/allocator.h
new file mode 100644
index 0000000..bdf3268
--- /dev/null
+++ b/drivers/staging/dt3155/allocator.h
@@ -0,0 +1,28 @@
+/*
+ * allocator.h -- prototypes for allocating high memory
+ *
+ * NOTE: this is different from my previous allocator, the one that
+ *       assembles pages, which revealed itself both slow and unreliable.
+ *
+ * Copyright (C) 1998   rubini@linux.it (Alessandro Rubini)
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You 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.
+ *
+ */
+
+void allocator_free_dma(unsigned long address);
+unsigned long allocator_allocate_dma(unsigned long kilobytes, int priority);
+int allocator_init(u32 *);
+void allocator_cleanup(void);
diff --git a/drivers/staging/dt3155/dt3155.h b/drivers/staging/dt3155/dt3155.h
new file mode 100644
index 0000000..1bf7863
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155.h
@@ -0,0 +1,171 @@
+/*
+
+Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+			 Jason Lapenta, Scott Smedley
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device Driver is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The DT3155 Device Driver is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+
+-- Changes --
+
+  Date     Programmer  Description of changes made
+  -------------------------------------------------------------------
+  03-Jul-2000 JML     n/a
+  10-Oct-2001 SS      port to 2.4 kernel.
+  24-Jul-2002 SS      remove unused code & added GPL licence.
+  05-Aug-2005 SS      port to 2.6 kernel; make CCIR mode default.
+
+*/
+
+#ifndef _DT3155_INC
+#define _DT3155_INC
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/time.h>		/* struct timeval */
+#else
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+
+#define TRUE  1
+#define FALSE 0
+
+/* Uncomment this for 50Hz CCIR */
+#define CCIR 1
+
+/* Can be 1 or 2 */
+#define MAXBOARDS 1
+
+#define BOARD_MAX_BUFFS	3
+#define MAXBUFFERS	(BOARD_MAX_BUFFS*MAXBOARDS)
+
+#define PCI_PAGE_SIZE	(1 << 12)
+
+#ifdef CCIR
+#define DT3155_MAX_ROWS	576
+#define DT3155_MAX_COLS	768
+#define FORMAT50HZ	TRUE
+#else
+#define DT3155_MAX_ROWS	480
+#define DT3155_MAX_COLS	640
+#define FORMAT50HZ	FALSE
+#endif
+
+/* Configuration structure */
+struct dt3155_config_s {
+	u32 acq_mode;
+	u32 cols, rows;
+	u32 continuous;
+};
+
+
+/* hold data for each frame */
+typedef struct {
+	u32 addr;		/* address of the buffer with the frame */
+	u32 tag;		/* unique number for the frame */
+	struct timeval time;	/* time that capture took place */
+} frame_info_t;
+
+/*
+ * Structure for interrupt and buffer handling.
+ * This is the setup for 1 card
+ */
+struct dt3155_fbuffer_s {
+	int    nbuffers;
+
+	frame_info_t frame_info[BOARD_MAX_BUFFS];
+
+	int empty_buffers[BOARD_MAX_BUFFS];	/* indexes empty frames */
+	int empty_len;				/* Number of empty buffers */
+						/* Zero means empty */
+
+	int active_buf;			/* Where data is currently dma'ing */
+	int locked_buf;			/* Buffers used by user */
+
+	int ready_que[BOARD_MAX_BUFFS];
+	u32 ready_head;	/* The most recent buffer located here */
+	u32 ready_len;	/* The number of ready buffers */
+
+	int even_happened;
+	int even_stopped;
+
+	int stop_acquire;	/* Flag to stop interrupts */
+	u32 frame_count;	/* Counter for frames acquired by this card */
+};
+
+
+
+#define DT3155_MODE_FRAME	1
+#define DT3155_MODE_FIELD	2
+
+#define DT3155_SNAP		1
+#define DT3155_ACQ		2
+
+/* There is one status structure for each card. */
+typedef struct dt3155_status_s {
+	int fixed_mode;		/* if 1, we are in fixed frame mode */
+	u32 reg_addr;	/* Register address for a single card */
+	u32 mem_addr;	/* Buffer start addr for this card */
+	u32 mem_size;	/* This is the amount of mem available  */
+	u32 irq;		/* this card's irq */
+	struct dt3155_config_s config;		/* configuration struct */
+	struct dt3155_fbuffer_s fbuffer;	/* frame buffer state struct */
+	u32 state;		/* this card's state */
+	u32 device_installed;	/* Flag if installed. 1=installed */
+} dt3155_status_t;
+
+/* Reference to global status structure */
+extern struct dt3155_status_s dt3155_status[MAXBOARDS];
+
+#define DT3155_STATE_IDLE	0x00
+#define DT3155_STATE_FRAME	0x01
+#define DT3155_STATE_FLD	0x02
+#define DT3155_STATE_STOP	0x100
+#define DT3155_STATE_ERROR	0x200
+#define DT3155_STATE_MODE	0x0ff
+
+#define DT3155_IOC_MAGIC	'!'
+
+#define DT3155_SET_CONFIG	_IOW(DT3155_IOC_MAGIC, 1, struct dt3155_config_s)
+#define DT3155_GET_CONFIG	_IOR(DT3155_IOC_MAGIC, 2, struct dt3155_status_s)
+#define DT3155_STOP		_IO(DT3155_IOC_MAGIC, 3)
+#define DT3155_START		_IO(DT3155_IOC_MAGIC, 4)
+#define DT3155_FLUSH		_IO(DT3155_IOC_MAGIC, 5)
+#define DT3155_IOC_MAXNR	5
+
+/* Error codes */
+
+#define DT_ERR_NO_BUFFERS	0x10000	/* not used but it might be one day */
+#define DT_ERR_CORRUPT		0x20000
+#define DT_ERR_OVERRUN		0x30000
+#define DT_ERR_I2C_TIMEOUT	0x40000
+#define DT_ERR_MASK		0xff0000/* not used but it might be one day */
+
+/* User code will probably want to declare one of these for each card */
+typedef struct dt3155_read_s {
+	u32 offset;
+	u32 frame_seq;
+	u32 state;
+
+	frame_info_t frame_info;
+} dt3155_read_t;
+
+#endif /* _DT3155_inc */
diff --git a/drivers/staging/dt3155/dt3155.sysvinit b/drivers/staging/dt3155/dt3155.sysvinit
new file mode 100644
index 0000000..92ec093
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155.sysvinit
@@ -0,0 +1,60 @@
+#! /bin/sh
+#
+# Module load/unload script for use with SysV-style /etc/init.d/ systems.
+# On a Debian system, copy this to /etc/init.d/dt3155 and then run
+# 	/usr/sbin/update-rc.d dt3155 defaults 55
+# to create the appropriate /etc/rc?.d/[SK]55dt3155 start/stop links.
+# (The "55" is arbitrary but is what I use to load this rather late.)
+#
+#    Andy Dougherty   Feb 22 2000	doughera@lafayette.edu
+#    Dept. of Physics
+#    Lafayette College, Easton PA 18042
+#
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+
+# Edit to point to your local copy.
+FILE=/usr/local/lib/modules/dt3155/dt3155.o
+NAME="dt3155"
+DESC="dt3155 Frame Grabber module"
+DEV="dt3155"
+
+if test ! -f $FILE; then
+    echo "Unable to locate $FILE"
+    exit 0
+fi
+
+set -e
+
+case "$1" in
+  start)
+    echo -n "Loading $DESC "
+    if /sbin/insmod -v -f $FILE; then
+	major=`grep $DEV /proc/devices | awk "{print \\$1}"`
+	rm -f /dev/dt3155?
+	mknod /dev/dt3155a c $major 0
+	mknod /dev/dt3155b c $major 1
+	chmod go+rw /dev/dt3155?
+	echo
+    else
+	echo "$FILE not loaded."
+    fi
+    ;;
+  stop)
+    echo -n "Unloading $DESC: "
+    if /sbin/rmmod $NAME ; then
+	echo
+    else
+	echo "$DEV not removed"
+	exit 0
+    fi
+    rm -f /dev/dt3155?
+    ;;
+  *)
+    echo "Usage: /etc/init.d/$NAME {start|stop}"
+    exit 1
+    ;;
+esac
+
+exit 0
+
diff --git a/drivers/staging/dt3155/dt3155_drv.c b/drivers/staging/dt3155/dt3155_drv.c
new file mode 100644
index 0000000..a67c622
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_drv.c
@@ -0,0 +1,1095 @@
+/*
+
+Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+                         Jason Lapenta, Scott Smedley, Greg Sharp
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device Driver is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The DT3155 Device Driver is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+
+-- Changes --
+
+  Date     Programmer	Description of changes made
+  -------------------------------------------------------------------
+  03-Jul-2000 JML       n/a
+  10-Oct-2001 SS        port to 2.4 kernel
+  02-Apr-2002 SS        Mods to use allocator as a standalone module;
+                        Merged John Roll's changes (john@cfa.harvard.edu)
+                        to make work with multiple boards.
+  02-Jul-2002 SS        Merged James Rose's chages (rosejr@purdue.edu) to:
+                         * fix successive interrupt-driven captures
+                         * add select/poll support.
+  10-Jul-2002 GCS       Add error check when ndevices > MAXBOARDS.
+  02-Aug-2002 GCS       Fix field mode so that odd (lower) field is stored
+                        in lower half of buffer.
+  05-Aug-2005 SS        port to 2.6 kernel.
+  26-Oct-2009 SS	port to 2.6.30 kernel.
+
+-- Notes --
+
+** appended "mem=124" in lilo.conf to allow for 4megs free on my 128meg system.
+ * using allocator.c and allocator.h from o'reilly book (alessandro rubini)
+    ftp://ftp.systemy.it/pub/develop (see README.allocator)
+
+ + might want to get rid of MAXboards for allocating initial buffer.
+    confusing and not necessary
+
+ + in cleanup_module the MOD_IN_USE looks like it is check after it should
+
+ * GFP_DMA should not be set with a PCI system (pg 291)
+
+ - NJC why are only two buffers allowed? (see isr, approx line 358)
+
+*/
+
+extern void printques(int);
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+
+MODULE_LICENSE("GPL");
+
+#endif
+
+#ifndef CONFIG_PCI
+#error  "DT3155 :  Kernel PCI support not enabled (DT3155 drive requires PCI)"
+#endif
+
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include "dt3155.h"
+#include "dt3155_drv.h"
+#include "dt3155_isr.h"
+#include "dt3155_io.h"
+#include "allocator.h"
+
+/* Error variable.  Zero means no error. */
+int dt3155_errno = 0;
+
+#ifndef PCI_DEVICE_ID_INTEL_7116
+#define PCI_DEVICE_ID_INTEL_7116 0x1223
+#endif
+
+#define DT3155_VENDORID    PCI_VENDOR_ID_INTEL
+#define DT3155_DEVICEID    PCI_DEVICE_ID_INTEL_7116
+#define MAXPCI    16
+
+#ifdef DT_DEBUG
+#define DT_3155_DEBUG_MSG(x,y) printk(x,y)
+#else
+#define DT_3155_DEBUG_MSG(x,y)
+#endif
+
+/* wait queue for interrupts */
+wait_queue_head_t dt3155_read_wait_queue[ MAXBOARDS ];
+
+#define DT_3155_SUCCESS 0
+#define DT_3155_FAILURE -EIO
+
+/* set to dynamicaly allocate, but it is tunable: */
+/* insmod DT_3155 dt3155 dt3155_major=XX */
+int dt3155_major = 0;
+
+/* The minor numbers are 0 and 1 ... they are not tunable.
+ * They are used as the indices for the structure vectors,
+ * and register address vectors
+ */
+
+/* Global structures and variables */
+
+/* Status of each device */
+struct dt3155_status_s dt3155_status[ MAXBOARDS ];
+
+/* kernel logical address of the board */
+u8 *dt3155_lbase[ MAXBOARDS ] = { NULL
+#if MAXBOARDS == 2
+				      , NULL
+#endif
+};
+/* DT3155 registers              */
+u8 *dt3155_bbase = NULL;		  /* kernel logical address of the *
+					   * buffer region                 */
+u32  dt3155_dev_open[ MAXBOARDS ] = {0
+#if MAXBOARDS == 2
+				       , 0
+#endif
+};
+
+u32  ndevices = 0;
+u32 unique_tag = 0;;
+
+
+/*
+ * Stops interrupt generation right away and resets the status
+ * to idle.  I don't know why this works and the other way doesn't.
+ * (James Rose)
+ */
+static void quick_stop (int minor)
+{
+  // TODO: scott was here
+#if 1
+  ReadMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg);
+  /* disable interrupts */
+  int_csr_r.fld.FLD_END_EVE_EN = 0;
+  int_csr_r.fld.FLD_END_ODD_EN = 0;
+  WriteMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
+
+  dt3155_status[ minor ].state &= ~(DT3155_STATE_STOP|0xff);
+  /* mark the system stopped: */
+  dt3155_status[ minor ].state |= DT3155_STATE_IDLE;
+  dt3155_fbuffer[ minor ]->stop_acquire = 0;
+  dt3155_fbuffer[ minor ]->even_stopped = 0;
+#else
+  dt3155_status[minor].state |= DT3155_STATE_STOP;
+  dt3155_status[minor].fbuffer.stop_acquire = 1;
+#endif
+
+}
+
+
+/*****************************************************
+ *  dt3155_isr() Interrupt service routien
+ *
+ * - looks like this isr supports IRQ sharing (or could) JML
+ * - Assumes irq's are disabled, via SA_INTERRUPT flag
+ * being set in request_irq() call from init_module()
+ *****************************************************/
+static inline void dt3155_isr( int irq, void *dev_id, struct pt_regs *regs )
+{
+  int    minor = -1;
+  int    index;
+  unsigned long flags;
+  u32 buffer_addr;
+
+  /* find out who issued the interrupt */
+  for ( index = 0; index < ndevices; index++ ) {
+    if( dev_id == (void*) &dt3155_status[ index ])
+      {
+	minor = index;
+	break;
+      }
+  }
+
+  /* hopefully we should not get here */
+  if ( minor < 0 || minor >= MAXBOARDS ) {
+    printk(KERN_ERR "dt3155_isr called with invalid dev_id\n");
+    return;
+  }
+
+  /* Check for corruption and set a flag if so */
+  ReadMReg( (dt3155_lbase[ minor ] + CSR1), csr1_r.reg );
+
+  if ( (csr1_r.fld.FLD_CRPT_EVE) || (csr1_r.fld.FLD_CRPT_ODD) )
+    {
+      /* TODO: this should probably stop acquisition */
+      /* and set some flags so that dt3155_read      */
+      /* returns an error next time it is called     */
+      dt3155_errno = DT_ERR_CORRUPT;
+      printk("dt3155:  corrupt field\n");
+      return;
+    }
+
+  ReadMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg);
+
+  /* Handle the even field ... */
+  if (int_csr_r.fld.FLD_END_EVE)
+    {
+      if ( (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
+	   DT3155_STATE_FLD )
+	{
+	  dt3155_fbuffer[ minor ]->frame_count++;
+	}
+
+      ReadI2C(dt3155_lbase[ minor ], EVEN_CSR, &i2c_even_csr.reg);
+
+      /* Clear the interrupt? */
+      int_csr_r.fld.FLD_END_EVE = 1;
+
+      /* disable the interrupt if last field */
+      if (dt3155_fbuffer[ minor ]->stop_acquire)
+	{
+	  printk("dt3155:  even stopped.\n");
+	  dt3155_fbuffer[ minor ]->even_stopped = 1;
+	  if (i2c_even_csr.fld.SNGL_EVE)
+	    {
+	      int_csr_r.fld.FLD_END_EVE_EN = 0;
+	    }
+	  else
+	    {
+	      i2c_even_csr.fld.SNGL_EVE  = 1;
+	    }
+	}
+
+      WriteMReg( (dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
+
+      /* Set up next DMA if we are doing FIELDS */
+      if ( (dt3155_status[ minor ].state & DT3155_STATE_MODE ) ==
+	   DT3155_STATE_FLD)
+	{
+	  /* GCS (Aug 2, 2002) -- In field mode, dma the odd field
+	     into the lower half of the buffer */
+	  const u32 stride =  dt3155_status[ minor ].config.cols;
+	  buffer_addr = dt3155_fbuffer[ minor ]->
+	    frame_info[ dt3155_fbuffer[ minor ]->active_buf ].addr
+	    + (DT3155_MAX_ROWS / 2) * stride;
+	  local_save_flags(flags);
+	  local_irq_disable();
+	  wake_up_interruptible( &dt3155_read_wait_queue[ minor ] );
+
+	  /* Set up the DMA address for the next field */
+	  local_irq_restore(flags);
+	  WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_START), buffer_addr);
+	}
+
+      /* Check for errors. */
+      i2c_even_csr.fld.DONE_EVE = 1;
+      if ( i2c_even_csr.fld.ERROR_EVE )
+	dt3155_errno = DT_ERR_OVERRUN;
+
+      WriteI2C( dt3155_lbase[ minor ], EVEN_CSR, i2c_even_csr.reg );
+
+      /* Note that we actually saw an even field meaning  */
+      /* that subsequent odd field complete the frame     */
+      dt3155_fbuffer[ minor ]->even_happened = 1;
+
+      /* recording the time that the even field finished, this should be */
+      /* about time in the middle of the frame */
+      do_gettimeofday( &(dt3155_fbuffer[ minor ]->
+			 frame_info[ dt3155_fbuffer[ minor ]->
+				     active_buf ].time) );
+      return;
+    }
+
+  /* ... now handle the odd field */
+  if ( int_csr_r.fld.FLD_END_ODD )
+    {
+      ReadI2C( dt3155_lbase[ minor ], ODD_CSR, &i2c_odd_csr.reg );
+
+      /* Clear the interrupt? */
+      int_csr_r.fld.FLD_END_ODD = 1;
+
+      if (dt3155_fbuffer[ minor ]->even_happened ||
+	  (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
+	  DT3155_STATE_FLD)
+	{
+	  dt3155_fbuffer[ minor ]->frame_count++;
+	}
+
+      if ( dt3155_fbuffer[ minor ]->stop_acquire &&
+	   dt3155_fbuffer[ minor ]->even_stopped )
+	{
+	  printk(KERN_DEBUG "dt3155:  stopping odd..\n");
+	  if ( i2c_odd_csr.fld.SNGL_ODD )
+	    {
+	      /* disable interrupts */
+	      int_csr_r.fld.FLD_END_ODD_EN = 0;
+	      dt3155_status[ minor ].state &= ~(DT3155_STATE_STOP|0xff);
+
+	      /* mark the system stopped: */
+	      dt3155_status[ minor ].state |= DT3155_STATE_IDLE;
+	      dt3155_fbuffer[ minor ]->stop_acquire = 0;
+	      dt3155_fbuffer[ minor ]->even_stopped = 0;
+
+	      printk(KERN_DEBUG "dt3155:  state is now %x\n",
+		     dt3155_status[minor].state);
+	    }
+	  else
+	    {
+	      i2c_odd_csr.fld.SNGL_ODD  = 1;
+	    }
+	}
+
+      WriteMReg( (dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
+
+      /* if the odd field has been acquired, then     */
+      /* change the next dma location for both fields */
+      /* and wake up the process if sleeping          */
+      if ( dt3155_fbuffer[ minor ]->even_happened ||
+	   (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
+	   DT3155_STATE_FLD )
+	{
+
+	  local_save_flags(flags);
+	  local_irq_disable();
+
+#ifdef DEBUG_QUES_B
+	  printques( minor );
+#endif
+	  if ( dt3155_fbuffer[ minor ]->nbuffers > 2 )
+	    {
+	      if ( !are_empty_buffers( minor ) )
+		{
+		  /* The number of active + locked buffers is
+		   * at most 2, and since there are none empty, there
+		   * must be at least nbuffers-2 ready buffers.
+		   * This is where we 'drop frames', oldest first. */
+		  push_empty( pop_ready( minor ),  minor );
+		}
+
+	      /* The ready_que can't be full, since we know
+	       * there is one active buffer right now, so it's safe
+	       * to push the active buf on the ready_que. */
+	      push_ready( minor, dt3155_fbuffer[ minor ]->active_buf );
+	      /* There's at least 1 empty -- make it active */
+	      dt3155_fbuffer[ minor ]->active_buf = pop_empty( minor );
+	      dt3155_fbuffer[ minor ]->
+		frame_info[ dt3155_fbuffer[ minor ]->
+			    active_buf ].tag = ++unique_tag;
+	    }
+	  else /* nbuffers == 2, special case */
+	    { /* There is 1 active buffer.
+	       * If there is a locked buffer, keep the active buffer
+	       * the same -- that means we drop a frame.
+	       */
+	      if ( dt3155_fbuffer[ minor ]->locked_buf < 0 )
+		{
+		  push_ready( minor,
+			      dt3155_fbuffer[ minor ]->active_buf );
+		  if (are_empty_buffers( minor ) )
+		    {
+		      dt3155_fbuffer[ minor ]->active_buf =
+			pop_empty( minor );
+		    }
+		  else
+		    { /* no empty or locked buffers, so use a readybuf */
+		      dt3155_fbuffer[ minor ]->active_buf =
+			pop_ready( minor );
+		    }
+		}
+	    }
+
+#ifdef DEBUG_QUES_B
+	  printques( minor );
+#endif
+
+	  dt3155_fbuffer[ minor ]->even_happened = 0;
+
+	  wake_up_interruptible( &dt3155_read_wait_queue[ minor ] );
+
+	  local_irq_restore(flags);
+	}
+
+
+      /* Set up the DMA address for the next frame/field */
+      buffer_addr = dt3155_fbuffer[ minor ]->
+	frame_info[ dt3155_fbuffer[ minor ]->active_buf ].addr;
+      if ( (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
+	   DT3155_STATE_FLD )
+	{
+	  WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START), buffer_addr);
+	}
+      else
+	{
+	  WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START), buffer_addr);
+
+	  WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_START), buffer_addr
+		    + dt3155_status[ minor ].config.cols);
+	}
+
+      /* Do error checking */
+      i2c_odd_csr.fld.DONE_ODD = 1;
+      if ( i2c_odd_csr.fld.ERROR_ODD )
+	dt3155_errno = DT_ERR_OVERRUN;
+
+      WriteI2C(dt3155_lbase[ minor ], ODD_CSR, i2c_odd_csr.reg );
+
+      return;
+    }
+  /* If we get here, the Odd Field wasn't it either... */
+  printk( "neither even nor odd.  shared perhaps?\n");
+}
+
+/*****************************************************
+ * init_isr(int minor)
+ *   turns on interupt generation for the card
+ *   designated by "minor".
+ *   It is called *only* from inside ioctl().
+ *****************************************************/
+static void dt3155_init_isr(int minor)
+{
+  const u32 stride =  dt3155_status[ minor ].config.cols;
+
+  switch (dt3155_status[ minor ].state & DT3155_STATE_MODE)
+    {
+    case DT3155_STATE_FLD:
+      {
+	even_dma_start_r  = dt3155_status[ minor ].
+	  fbuffer.frame_info[ dt3155_status[ minor ].fbuffer.active_buf ].addr;
+	even_dma_stride_r = 0;
+	odd_dma_stride_r  = 0;
+
+	WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START),
+		  even_dma_start_r);
+	WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_STRIDE),
+		  even_dma_stride_r);
+	WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_STRIDE),
+		  odd_dma_stride_r);
+	break;
+      }
+
+    case DT3155_STATE_FRAME:
+    default:
+      {
+	even_dma_start_r  = dt3155_status[ minor ].
+	  fbuffer.frame_info[ dt3155_status[ minor ].fbuffer.active_buf ].addr;
+	odd_dma_start_r   =  even_dma_start_r + stride;
+	even_dma_stride_r =  stride;
+	odd_dma_stride_r  =  stride;
+
+	WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START),
+		  even_dma_start_r);
+	WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_START),
+		  odd_dma_start_r);
+	WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_STRIDE),
+		  even_dma_stride_r);
+	WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_STRIDE),
+		  odd_dma_stride_r);
+	break;
+      }
+    }
+
+  /* 50/60 Hz should be set before this point but let's make sure it is */
+  /* right anyway */
+
+  ReadI2C(dt3155_lbase[ minor ], CONFIG, &i2c_csr2.reg);
+  i2c_csr2.fld.HZ50 = FORMAT50HZ;
+  WriteI2C(dt3155_lbase[ minor ], CONFIG, i2c_config.reg);
+
+  /* enable busmaster chip, clear flags */
+
+  /*
+   * TODO:
+   * shouldn't we be concered with continuous values of
+   * DT3155_SNAP & DT3155_ACQ here? (SS)
+   */
+
+  csr1_r.reg                = 0;
+  csr1_r.fld.CAP_CONT_EVE   = 1; /* use continuous capture bits to */
+  csr1_r.fld.CAP_CONT_ODD   = 1; /* enable */
+  csr1_r.fld.FLD_DN_EVE     = 1; /* writing a 1 clears flags */
+  csr1_r.fld.FLD_DN_ODD     = 1;
+  csr1_r.fld.SRST           = 1; /* reset        - must be 1 */
+  csr1_r.fld.FIFO_EN        = 1; /* fifo control - must be 1 */
+  csr1_r.fld.FLD_CRPT_EVE   = 1; /* writing a 1 clears flags */
+  csr1_r.fld.FLD_CRPT_ODD   = 1;
+
+  WriteMReg((dt3155_lbase[ minor ] + CSR1),csr1_r.reg);
+
+  /* Enable interrupts at the end of each field */
+
+  int_csr_r.reg = 0;
+  int_csr_r.fld.FLD_END_EVE_EN = 1;
+  int_csr_r.fld.FLD_END_ODD_EN = 1;
+  int_csr_r.fld.FLD_START_EN = 0;
+
+  WriteMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg);
+
+  /* start internal BUSY bits */
+
+  ReadI2C(dt3155_lbase[ minor ], CSR2, &i2c_csr2.reg);
+  i2c_csr2.fld.BUSY_ODD  = 1;
+  i2c_csr2.fld.BUSY_EVE  = 1;
+  WriteI2C(dt3155_lbase[ minor ], CSR2, i2c_csr2.reg);
+
+  /* Now its up to the interrupt routine!! */
+
+  return;
+}
+
+
+/*****************************************************
+ * ioctl()
+ *
+ *****************************************************/
+static int dt3155_ioctl(struct inode *inode,
+			struct file *file,
+			unsigned int cmd,
+			unsigned long arg)
+{
+  int minor = MINOR(inode->i_rdev); /* What device are we ioctl()'ing? */
+
+  if ( minor >= MAXBOARDS || minor < 0 )
+    return -ENODEV;
+
+  /* make sure it is valid command */
+  if (_IOC_NR(cmd) > DT3155_IOC_MAXNR)
+    {
+      printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
+      printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
+	     (unsigned int)DT3155_GET_CONFIG,
+	     (unsigned int)DT3155_SET_CONFIG,
+	     (unsigned int)DT3155_START,
+	     (unsigned int)DT3155_STOP,
+	     (unsigned int)DT3155_FLUSH);
+      return -EINVAL;
+    }
+
+  switch (cmd)
+    {
+    case DT3155_SET_CONFIG:
+      {
+	if (dt3155_status[minor].state != DT3155_STATE_IDLE)
+	  return -EBUSY;
+
+	{
+	  struct dt3155_config_s tmp;
+	  if (copy_from_user((void *)&tmp, (void *) arg, sizeof(tmp)))
+	      return -EFAULT;
+	  /* check for valid settings */
+	  if (tmp.rows > DT3155_MAX_ROWS ||
+	      tmp.cols > DT3155_MAX_COLS ||
+	      (tmp.acq_mode != DT3155_MODE_FRAME &&
+	       tmp.acq_mode != DT3155_MODE_FIELD) ||
+	      (tmp.continuous != DT3155_SNAP &&
+	       tmp.continuous != DT3155_ACQ))
+	    {
+	      return -EINVAL;
+	    }
+	  dt3155_status[minor].config = tmp;
+	}
+	return 0;
+      }
+    case DT3155_GET_CONFIG:
+      {
+	if (copy_to_user((void *) arg, (void *) &dt3155_status[minor],
+		     sizeof(dt3155_status_t) ))
+	    return -EFAULT;
+	return 0;
+      }
+    case DT3155_FLUSH: /* Flushes the buffers -- ensures fresh data */
+      {
+	if (dt3155_status[minor].state != DT3155_STATE_IDLE)
+	  return -EBUSY;
+	return dt3155_flush(minor);
+      }
+    case DT3155_STOP:
+      {
+	if (dt3155_status[minor].state & DT3155_STATE_STOP ||
+	    dt3155_status[minor].fbuffer.stop_acquire)
+	  return -EBUSY;
+
+	if (dt3155_status[minor].state == DT3155_STATE_IDLE)
+	  return 0;
+
+	quick_stop(minor);
+	if (copy_to_user((void *) arg, (void *) &dt3155_status[minor],
+		     sizeof(dt3155_status_t)))
+	    return -EFAULT;
+	return 0;
+      }
+    case DT3155_START:
+      {
+	if (dt3155_status[minor].state != DT3155_STATE_IDLE)
+	  return -EBUSY;
+
+	dt3155_status[minor].fbuffer.stop_acquire = 0;
+	dt3155_status[minor].fbuffer.frame_count = 0;
+
+	/* Set the MODE in the status -- we default to FRAME */
+	if (dt3155_status[minor].config.acq_mode == DT3155_MODE_FIELD)
+	  {
+	    dt3155_status[minor].state = DT3155_STATE_FLD;
+	  }
+	else
+	  {
+	    dt3155_status[minor].state = DT3155_STATE_FRAME;
+	  }
+
+	dt3155_init_isr(minor);
+	if (copy_to_user( (void *) arg, (void *) &dt3155_status[minor],
+		      sizeof(dt3155_status_t)))
+	    return -EFAULT;
+	return 0;
+      }
+    default:
+      {
+	printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
+      printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
+	     (unsigned int)DT3155_GET_CONFIG,
+	     (unsigned int)DT3155_SET_CONFIG,
+	     DT3155_START, DT3155_STOP, DT3155_FLUSH);
+	return -ENOSYS;
+      }
+    }
+  return -ENOSYS;
+}
+
+/*****************************************************
+ * mmap()
+ *
+ * only allow the user to mmap the registers and buffer
+ * It is quite possible that this is broken, since the
+ * addition of of the capacity for two cards!!!!!!!!
+ * It *looks* like it should work but since I'm not
+ * sure how to use it, I'm not actually sure. (NJC? ditto by SS)
+ *****************************************************/
+static int dt3155_mmap (struct file * file, struct vm_area_struct * vma)
+{
+  /* which device are we mmapping? */
+  int				minor = MINOR(file->f_dentry->d_inode->i_rdev);
+  unsigned long	offset;
+  offset = vma->vm_pgoff << PAGE_SHIFT;
+
+  if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
+    vma->vm_flags |= VM_IO;
+
+  /* Don't try to swap out physical pages.. */
+  vma->vm_flags |= VM_RESERVED;
+
+  /* they are mapping the registers or the buffer */
+  if ((offset == dt3155_status[minor].reg_addr &&
+       vma->vm_end - vma->vm_start == PCI_PAGE_SIZE) ||
+      (offset == dt3155_status[minor].mem_addr &&
+       vma->vm_end - vma->vm_start == dt3155_status[minor].mem_size))
+    {
+      if (remap_pfn_range(vma,
+			vma->vm_start,
+			offset >> PAGE_SHIFT,
+			vma->vm_end - vma->vm_start,
+			vma->vm_page_prot)) {
+	  printk("DT3155: remap_page_range() failed.\n");
+	  return -EAGAIN;
+	}
+    }
+  else
+    {
+      printk("DT3155: dt3155_mmap() bad call.\n");
+      return -ENXIO;
+    }
+
+  return 0;
+}
+
+
+/*****************************************************
+ * open()
+ *
+ * Our special open code.
+ * MOD_INC_USE_COUNT make sure that the driver memory is not freed
+ * while the device is in use.
+ *****************************************************/
+static int dt3155_open( struct inode* inode, struct file* filep)
+{
+  int minor = MINOR(inode->i_rdev); /* what device are we opening? */
+  if (dt3155_dev_open[ minor ]) {
+    printk ("DT3155:  Already opened by another process.\n");
+    return -EBUSY;
+  }
+
+  if (dt3155_status[ minor ].device_installed==0)
+    {
+      printk("DT3155 Open Error: No such device dt3155 minor number %d\n",
+	     minor);
+      return -EIO;
+    }
+
+  if (dt3155_status[ minor ].state != DT3155_STATE_IDLE) {
+    printk ("DT3155:  Not in idle state (state = %x)\n",
+	    dt3155_status[ minor ].state);
+    return -EBUSY;
+  }
+
+  printk("DT3155: Device opened.\n");
+
+  dt3155_dev_open[ minor ] = 1 ;
+
+  dt3155_flush( minor );
+
+  /* Disable ALL interrupts */
+  int_csr_r.reg = 0;
+  WriteMReg( (dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
+
+  init_waitqueue_head(&(dt3155_read_wait_queue[minor]));
+
+  return 0;
+}
+
+
+/*****************************************************
+ * close()
+ *
+ * Now decrement the use count.
+ *
+ *****************************************************/
+static int dt3155_close( struct inode *inode, struct file *filep)
+{
+  int minor;
+
+  minor = MINOR(inode->i_rdev); /* which device are we closing */
+  if (!dt3155_dev_open[ minor ])
+    {
+      printk("DT3155: attempt to CLOSE a not OPEN device\n");
+    }
+  else
+    {
+      dt3155_dev_open[ minor ] = 0;
+
+      if (dt3155_status[ minor ].state != DT3155_STATE_IDLE)
+	{
+	  quick_stop(minor);
+	}
+    }
+  return 0;
+}
+
+/*****************************************************
+ * read()
+ *
+ *****************************************************/
+static ssize_t dt3155_read(struct file *filep, char __user *buf,
+			   size_t count, loff_t *ppos)
+{
+  /* which device are we reading from? */
+  int		minor = MINOR(filep->f_dentry->d_inode->i_rdev);
+  u32		offset;
+  int		frame_index;
+  frame_info_t	*frame_info_p;
+
+  /* TODO: this should check the error flag and */
+  /*   return an error on hardware failures */
+  if (count != sizeof(dt3155_read_t))
+    {
+      printk("DT3155 ERROR (NJC): count is not right\n");
+      return -EINVAL;
+    }
+
+
+  /* Hack here -- I'm going to allow reading even when idle.
+   * this is so that the frames can be read after STOP has
+   * been called.  Leaving it here, commented out, as a reminder
+   * for a short while to make sure there are no problems.
+   * Note that if the driver is not opened in non_blocking mode,
+   * and the device is idle, then it could sit here forever! */
+
+  /*  if (dt3155_status[minor].state == DT3155_STATE_IDLE)*/
+  /*    return -EBUSY;*/
+
+  /* non-blocking reads should return if no data */
+  if (filep->f_flags & O_NDELAY)
+    {
+      if ((frame_index = dt3155_get_ready_buffer(minor)) < 0) {
+	/*printk( "dt3155:  no buffers available (?)\n");*/
+	/* 		printques(minor); */
+	return -EAGAIN;
+      }
+    }
+  else
+    {
+      /*
+       * sleep till data arrives , or we get interrupted.
+       * Note that wait_event_interruptible() does not actually
+       * sleep/wait if it's condition evaluates to true upon entry.
+       */
+      wait_event_interruptible(dt3155_read_wait_queue[minor],
+			       (frame_index = dt3155_get_ready_buffer(minor))
+			       >= 0);
+
+      if (frame_index < 0)
+	{
+	  printk ("DT3155: read: interrupted\n");
+	  quick_stop (minor);
+	  printques(minor);
+	  return -EINTR;
+	}
+    }
+
+  frame_info_p = &dt3155_status[minor].fbuffer.frame_info[frame_index];
+
+  /* make this an offset */
+  offset = frame_info_p->addr - dt3155_status[minor].mem_addr;
+
+  put_user(offset, (unsigned int *) buf);
+  buf += sizeof(u32);
+  put_user( dt3155_status[minor].fbuffer.frame_count, (unsigned int *) buf);
+  buf += sizeof(u32);
+  put_user(dt3155_status[minor].state, (unsigned int *) buf);
+  buf += sizeof(u32);
+  if (copy_to_user(buf, frame_info_p, sizeof(frame_info_t)))
+      return -EFAULT;
+
+  return sizeof(dt3155_read_t);
+}
+
+static unsigned int dt3155_poll (struct file * filp, poll_table *wait)
+{
+  int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
+
+  if (!is_ready_buf_empty(minor))
+    return POLLIN | POLLRDNORM;
+
+  poll_wait (filp, &dt3155_read_wait_queue[minor], wait);
+
+  return 0;
+}
+
+
+/*****************************************************
+ * file operations supported by DT3155 driver
+ *  needed by init_module
+ *  register_chrdev
+ *****************************************************/
+static struct file_operations dt3155_fops = {
+  read:		dt3155_read,
+  ioctl:		dt3155_ioctl,
+  mmap:		dt3155_mmap,
+  poll:           dt3155_poll,
+  open:		dt3155_open,
+  release:	dt3155_close
+};
+
+
+/*****************************************************
+ * find_PCI();
+ *
+ * PCI has been totally reworked in 2.1..
+ *****************************************************/
+static int find_PCI (void)
+{
+  struct pci_dev *pci_dev = NULL;
+  int error, pci_index = 0;
+  unsigned short rev_device;
+  unsigned long base;
+  unsigned char irq;
+
+  while ((pci_dev = pci_get_device
+	  (DT3155_VENDORID, DT3155_DEVICEID, pci_dev)) != NULL)
+    {
+      pci_index ++;
+
+      /* Is it really there? */
+      if ((error =
+	   pci_read_config_word(pci_dev, PCI_CLASS_DEVICE, &rev_device)))
+	continue;
+
+      /* Found a board */
+      DT_3155_DEBUG_MSG("DT3155: Device number %d \n", pci_index);
+
+      /* Make sure the driver was compiled with enough buffers to handle
+	 this many boards */
+      if (pci_index > MAXBOARDS) {
+	printk("DT3155: ERROR - found %d devices, but driver only configured "
+	       "for %d devices\n"
+	       "DT3155: Please change MAXBOARDS in dt3155.h\n",
+	       pci_index, MAXBOARDS);
+	goto err;
+      }
+
+      /* Now, just go out and make sure that this/these device(s) is/are
+	 actually mapped into the kernel address space */
+      if ((error = pci_read_config_dword( pci_dev, PCI_BASE_ADDRESS_0,
+					  (u32 *) &base)))
+	{
+	  printk("DT3155: Was not able to find device \n");
+	  goto err;
+	}
+
+      DT_3155_DEBUG_MSG("DT3155: Base address 0 for device is %lx \n", base);
+      dt3155_status[pci_index-1].reg_addr = base;
+
+      /* Remap the base address to a logical address through which we
+       * can access it. */
+      dt3155_lbase[ pci_index - 1 ] = ioremap(base,PCI_PAGE_SIZE);
+      dt3155_status[ pci_index - 1 ].reg_addr = base;
+      DT_3155_DEBUG_MSG("DT3155: New logical address is %p \n",
+			dt3155_lbase[pci_index-1]);
+      if ( !dt3155_lbase[pci_index-1] )
+	{
+	  printk("DT3155: Unable to remap control registers\n");
+	  goto err;
+	}
+
+      if ( (error = pci_read_config_byte( pci_dev, PCI_INTERRUPT_LINE, &irq)) )
+	{
+	  printk("DT3155: Was not able to find device \n");
+	  goto err;
+	}
+
+      DT_3155_DEBUG_MSG("DT3155: IRQ is %d \n",irq);
+      dt3155_status[ pci_index-1 ].irq = irq;
+      /* Set flag: kth device found! */
+      dt3155_status[ pci_index-1 ].device_installed = 1;
+      printk("DT3155: Installing device %d w/irq %d and address %p\n",
+	     pci_index,
+	     dt3155_status[pci_index-1].irq,
+	     dt3155_lbase[pci_index-1]);
+
+    }
+  ndevices = pci_index;
+
+  return DT_3155_SUCCESS;
+
+err:
+  pci_dev_put(pci_dev);
+  return DT_3155_FAILURE;
+}
+
+u32 allocatorAddr = 0;
+
+/*****************************************************
+ * init_module()
+ *****************************************************/
+int init_module(void)
+{
+  int index;
+  int rcode = 0;
+  char *devname[ MAXBOARDS ];
+
+  devname[ 0 ] = "dt3155a";
+#if MAXBOARDS == 2
+  devname[ 1 ] = "dt3155b";
+#endif
+
+  printk("DT3155: Loading module...\n");
+
+  /* Register the device driver */
+  rcode = register_chrdev( dt3155_major, "dt3155", &dt3155_fops );
+  if( rcode < 0 )
+    {
+      printk( KERN_INFO "DT3155: register_chrdev failed \n");
+      return rcode;
+    }
+
+  if( dt3155_major == 0 )
+    dt3155_major = rcode; /* dynamic */
+
+
+  /* init the status variables.                     */
+  /* DMA memory is taken care of in setup_buffers() */
+  for ( index = 0; index < MAXBOARDS; index++ )
+    {
+      dt3155_status[ index ].config.acq_mode   = DT3155_MODE_FRAME;
+      dt3155_status[ index ].config.continuous = DT3155_ACQ;
+      dt3155_status[ index ].config.cols       = DT3155_MAX_COLS;
+      dt3155_status[ index ].config.rows       = DT3155_MAX_ROWS;
+      dt3155_status[ index ].state = DT3155_STATE_IDLE;
+
+      /* find_PCI() will check if devices are installed; */
+      /* first assume they're not:                       */
+      dt3155_status[ index ].mem_addr          = 0;
+      dt3155_status[ index ].mem_size          = 0;
+      dt3155_status[ index ].state             = DT3155_STATE_IDLE;
+      dt3155_status[ index ].device_installed  = 0;
+    }
+
+  /* Now let's find the hardware.  find_PCI() will set ndevices to the
+   * number of cards found in this machine. */
+    {
+      if ( (rcode = find_PCI()) !=  DT_3155_SUCCESS )
+	{
+	  printk("DT3155 error: find_PCI() failed to find dt3155 board(s)\n");
+	  unregister_chrdev( dt3155_major, "dt3155" );
+	  return rcode;
+	}
+    }
+
+  /* Ok, time to setup the frame buffers */
+  if( (rcode = dt3155_setup_buffers(&allocatorAddr)) < 0 )
+    {
+      printk("DT3155: Error: setting up buffer not large enough.");
+      unregister_chrdev( dt3155_major, "dt3155" );
+      return rcode;
+    }
+
+  /* If we are this far, then there is enough RAM */
+  /* for the buffers: Print the configuration.    */
+  for(  index = 0;  index < ndevices;  index++ )
+    {
+      printk("DT3155: Device = %d; acq_mode = %d; "
+	     "continuous = %d; cols = %d; rows = %d;\n",
+	     index ,
+	     dt3155_status[ index ].config.acq_mode,
+	     dt3155_status[ index ].config.continuous,
+	     dt3155_status[ index ].config.cols,
+	     dt3155_status[ index ].config.rows);
+      printk("DT3155: m_addr = 0x%x; m_size = %ld; "
+	     "state = %d; device_installed = %d\n",
+	     dt3155_status[ index ].mem_addr,
+	     (long int)dt3155_status[ index ].mem_size,
+	     dt3155_status[ index ].state,
+	     dt3155_status[ index ].device_installed);
+    }
+
+  /* Disable ALL interrupts */
+  int_csr_r.reg = 0;
+  for(  index = 0;  index < ndevices;  index++ )
+    {
+      WriteMReg( (dt3155_lbase[ index ] + INT_CSR), int_csr_r.reg );
+      if( dt3155_status[ index ].device_installed )
+	{
+	  /*
+	   * This driver *looks* like it can handle sharing interrupts,
+	   * but I can't actually test myself. I've had reports that it
+	   * DOES work so I'll enable it for now. This comment will remain
+	   * as a reminder in case any problems arise. (SS)
+	   */
+	  /* in older kernels flags are: SA_SHIRQ | SA_INTERRUPT */
+	  rcode = request_irq( dt3155_status[ index ].irq, (void *)dt3155_isr,
+			       IRQF_SHARED | IRQF_DISABLED, devname[ index ],
+			       (void*) &dt3155_status[index]);
+	  if( rcode < 0 )
+	    {
+	      printk("DT3155: minor %d request_irq failed for IRQ %d\n",
+		     index, dt3155_status[index].irq);
+	      unregister_chrdev( dt3155_major, "dt3155" );
+	      return rcode;
+	    }
+	}
+    }
+
+  printk("DT3155: finished loading\n");
+
+  return 0;
+}
+
+/*****************************************************
+ * cleanup_module(void)
+ *
+ *****************************************************/
+void cleanup_module(void)
+{
+  int index;
+
+  printk("DT3155:  cleanup_module called\n");
+
+  /* removed DMA allocated with the allocator */
+#ifdef STANDALONE_ALLOCATOR
+  if (allocatorAddr != 0)
+    allocator_free_dma(allocatorAddr);
+#else
+  allocator_cleanup();
+#endif
+
+  unregister_chrdev( dt3155_major, "dt3155" );
+
+  for( index = 0; index < ndevices; index++ )
+    {
+      if( dt3155_status[ index ].device_installed == 1 )
+	{
+	  printk( "DT3155: Freeing irq %d for device %d\n",
+		  dt3155_status[ index ].irq, index );
+	  free_irq( dt3155_status[ index ].irq, (void*)&dt3155_status[index] );
+	}
+    }
+}
+
diff --git a/drivers/staging/dt3155/dt3155_drv.h b/drivers/staging/dt3155/dt3155_drv.h
new file mode 100644
index 0000000..95e68c3
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_drv.h
@@ -0,0 +1,45 @@
+/*
+
+Copyright 1996,2002 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+		    Scott Smedley
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device Driver is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The DT3155 Device Driver is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+*/
+
+#ifndef DT3155_DRV_INC
+#define DT3155_DRV_INC
+
+/* kernel logical address of the frame grabbers */
+extern u8 *dt3155_lbase[MAXBOARDS];
+
+/* kernel logical address of ram buffer */
+extern u8 *dt3155_bbase;
+
+#ifdef __KERNEL__
+#include <linux/wait.h>
+
+/* wait queue for reads */
+extern wait_queue_head_t dt3155_read_wait_queue[MAXBOARDS];
+#endif
+
+/* number of devices */
+extern u32 ndevices;
+
+extern int dt3155_errno;
+
+#endif
diff --git a/drivers/staging/dt3155/dt3155_io.c b/drivers/staging/dt3155/dt3155_io.c
new file mode 100644
index 0000000..6b9c685
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_io.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+ *			    Jason Lapenta, Scott Smedley
+ *
+ * This file is part of the DT3155 Device Driver.
+ *
+ * The DT3155 Device Driver is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * The DT3155 Device Driver is distributed in the hope that it will be useful,
+ * but WITHOUT 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 file provides some basic register io routines.  It is modified from
+ * demo code provided by Data Translations.
+ */
+
+#include <linux/delay.h>
+#include "dt3155.h"
+#include "dt3155_io.h"
+#include "dt3155_drv.h"
+
+
+/****** local copies of board's 32 bit registers ******/
+u32 even_dma_start_r;	/*  bit 0 should always be 0 */
+u32 odd_dma_start_r;	/*               .. */
+u32 even_dma_stride_r;	/*  bits 0&1 should always be 0 */
+u32 odd_dma_stride_r;	/*               .. */
+u32 even_pixel_fmt_r;
+u32 odd_pixel_fmt_r;
+
+FIFO_TRIGGER_R		fifo_trigger_r;
+XFER_MODE_R		xfer_mode_r;
+CSR1_R			csr1_r;
+RETRY_WAIT_CNT_R	retry_wait_cnt_r;
+INT_CSR_R		int_csr_r;
+
+u32 even_fld_mask_r;
+u32 odd_fld_mask_r;
+
+MASK_LENGTH_R		mask_length_r;
+FIFO_FLAG_CNT_R		fifo_flag_cnt_r;
+IIC_CLK_DUR_R		iic_clk_dur_r;
+IIC_CSR1_R		iic_csr1_r;
+IIC_CSR2_R		iic_csr2_r;
+DMA_UPPER_LMT_R		even_dma_upper_lmt_r;
+DMA_UPPER_LMT_R		odd_dma_upper_lmt_r;
+
+
+
+/******** local copies of board's 8 bit I2C registers ******/
+I2C_CSR2 i2c_csr2;
+I2C_EVEN_CSR i2c_even_csr;
+I2C_ODD_CSR i2c_odd_csr;
+I2C_CONFIG i2c_config;
+u8 i2c_dt_id;
+u8 i2c_x_clip_start;
+u8 i2c_y_clip_start;
+u8 i2c_x_clip_end;
+u8 i2c_y_clip_end;
+u8 i2c_ad_addr;
+u8 i2c_ad_lut;
+I2C_AD_CMD i2c_ad_cmd;
+u8 i2c_dig_out;
+u8 i2c_pm_lut_addr;
+u8 i2c_pm_lut_data;
+
+/*
+ * wait_ibsyclr()
+ *
+ * This function handles read/write timing and r/w timeout error
+ *
+ * Returns TRUE  if NEW_CYCLE clears
+ * Returns FALSE if NEW_CYCLE doesn't clear in roughly 3 msecs, otherwise
+ * returns 0
+ */
+static int wait_ibsyclr(u8 *lpReg)
+{
+	/* wait 100 microseconds */
+	udelay(100L);
+	/* __delay(loops_per_sec/10000); */
+	if (iic_csr2_r.fld.NEW_CYCLE) {
+		/* if NEW_CYCLE didn't clear */
+		/* TIMEOUT ERROR */
+		dt3155_errno = DT_ERR_I2C_TIMEOUT;
+		return FALSE;
+	} else
+		return TRUE;	/* no error */
+}
+
+/*
+ * WriteI2C()
+ *
+ * This function handles writing to 8-bit DT3155 registers
+ *
+ * 1st parameter is pointer to 32-bit register base address
+ * 2nd parameter is reg. index;
+ * 3rd is value to be written
+ *
+ * Returns TRUE   -  Successful completion
+ *         FALSE  -  Timeout error - cycle did not complete!
+ */
+int WriteI2C(u8 *lpReg, u_short wIregIndex, u8 byVal)
+{
+	int writestat;	/* status for return */
+
+	/* read 32 bit IIC_CSR2 register data into union */
+
+	ReadMReg((lpReg + IIC_CSR2), iic_csr2_r.reg);
+
+	/* for write operation */
+	iic_csr2_r.fld.DIR_RD      = 0;
+	/* I2C address of I2C register: */
+	iic_csr2_r.fld.DIR_ADDR    = wIregIndex;
+	/* 8 bit data to be written to I2C reg */
+	iic_csr2_r.fld.DIR_WR_DATA = byVal;
+	/* will start a direct I2C cycle: */
+	iic_csr2_r.fld.NEW_CYCLE   = 1;
+
+	/* xfer union data into 32 bit IIC_CSR2 register */
+	WriteMReg((lpReg + IIC_CSR2), iic_csr2_r.reg);
+
+	/* wait for IIC cycle to finish */
+	writestat = wait_ibsyclr(lpReg);
+	return writestat;
+}
+
+/*
+ * ReadI2C()
+ *
+ * This function handles reading from 8-bit DT3155 registers
+ *
+ * 1st parameter is pointer to 32-bit register base address
+ * 2nd parameter is reg. index;
+ * 3rd is adrs of value to be read
+ *
+ * Returns TRUE   -  Successful completion
+ *         FALSE  -  Timeout error - cycle did not complete!
+ */
+int ReadI2C(u8 *lpReg, u_short wIregIndex, u8 *byVal)
+{
+	int writestat;	/* status for return */
+
+	/*  read 32 bit IIC_CSR2 register data into union */
+	ReadMReg((lpReg + IIC_CSR2), iic_csr2_r.reg);
+
+	/*  for read operation */
+	iic_csr2_r.fld.DIR_RD     = 1;
+
+	/*  I2C address of I2C register: */
+	iic_csr2_r.fld.DIR_ADDR   = wIregIndex;
+
+	/*  will start a direct I2C cycle: */
+	iic_csr2_r.fld.NEW_CYCLE  = 1;
+
+	/*  xfer union's data into 32 bit IIC_CSR2 register */
+	WriteMReg((lpReg + IIC_CSR2), iic_csr2_r.reg);
+
+	/* wait for IIC cycle to finish */
+	writestat = wait_ibsyclr(lpReg);
+
+	/* Next 2 commands read 32 bit IIC_CSR1 register's data into union */
+	/* first read data is in IIC_CSR1 */
+	ReadMReg((lpReg + IIC_CSR1), iic_csr1_r.reg);
+
+	/* now get data u8 out of register */
+	*byVal = (u8) iic_csr1_r.fld.RD_DATA;
+
+	return writestat;
+}
diff --git a/drivers/staging/dt3155/dt3155_io.h b/drivers/staging/dt3155/dt3155_io.h
new file mode 100644
index 0000000..d1a2510
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_io.h
@@ -0,0 +1,358 @@
+/*
+
+Copyright 1996,2002 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+		    Jason Lapenta, Scott Smedley
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device Driver is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The DT3155 Device Driver is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+
+
+-- Changes --
+
+  Date     Programmer  Description of changes made
+  -------------------------------------------------------------------
+  24-Jul-2002 SS       GPL licence.
+
+*/
+
+/* This code is a modified version of examples provided by Data Translations.*/
+
+#ifndef DT3155_IO_INC
+#define DT3155_IO_INC
+
+/* macros to access registers */
+
+#define WriteMReg(Address, Data)	(*((u32 *)(Address)) = Data)
+#define ReadMReg(Address, Data)		(Data = *((u32 *)(Address)))
+
+/***************** 32 bit register globals  **************/
+
+/*  offsets for 32-bit memory mapped registers */
+
+#define EVEN_DMA_START		0x000
+#define ODD_DMA_START		0x00C
+#define EVEN_DMA_STRIDE		0x018
+#define ODD_DMA_STRIDE		0x024
+#define EVEN_PIXEL_FMT		0x030
+#define ODD_PIXEL_FMT		0x034
+#define FIFO_TRIGGER		0x038
+#define XFER_MODE		0x03C
+#define CSR1			0x040
+#define RETRY_WAIT_CNT		0x044
+#define INT_CSR			0x048
+#define EVEN_FLD_MASK		0x04C
+#define ODD_FLD_MASK		0x050
+#define MASK_LENGTH		0x054
+#define FIFO_FLAG_CNT		0x058
+#define IIC_CLK_DUR		0x05C
+#define IIC_CSR1		0x060
+#define IIC_CSR2		0x064
+#define EVEN_DMA_UPPR_LMT	0x08C
+#define ODD_DMA_UPPR_LMT	0x090
+
+#define CLK_DUR_VAL		0x01010101
+
+
+
+/******** Assignments and Typedefs for 32 bit Memory Mapped Registers ********/
+
+typedef union fifo_trigger_tag {
+	u32   reg;
+	struct {
+		u32 PACKED:6;
+		u32       :9;
+		u32 PLANER:7;
+		u32       :9;
+	} fld;
+} FIFO_TRIGGER_R;
+
+typedef union xfer_mode_tag {
+	u32   reg;
+	struct {
+		u32             :2;
+		u32 FIELD_TOGGLE:1;
+		u32             :5;
+		u32             :2;
+		u32             :22;
+	} fld;
+} XFER_MODE_R;
+
+typedef union csr1_tag {
+	u32   reg;
+	struct {
+		u32 CAP_CONT_EVE:1;
+		u32 CAP_CONT_ODD:1;
+		u32 CAP_SNGL_EVE:1;
+		u32 CAP_SNGL_ODD:1;
+		u32 FLD_DN_EVE  :1;
+		u32 FLD_DN_ODD  :1;
+		u32 SRST        :1;
+		u32 FIFO_EN     :1;
+		u32 FLD_CRPT_EVE:1;
+		u32 FLD_CRPT_ODD:1;
+		u32 ADDR_ERR_EVE:1;
+		u32 ADDR_ERR_ODD:1;
+		u32 CRPT_DIS    :1;
+		u32 RANGE_EN    :1;
+		u32             :16;
+	} fld;
+} CSR1_R;
+
+typedef union retry_wait_cnt_tag {
+	u32   reg;
+	struct {
+		u32 RTRY_WAIT_CNT:8;
+		u32              :24;
+	} fld;
+} RETRY_WAIT_CNT_R;
+
+typedef union int_csr_tag {
+	u32   reg;
+	struct {
+		u32 FLD_END_EVE   :1;
+		u32 FLD_END_ODD   :1;
+		u32 FLD_START     :1;
+		u32               :5;
+		u32 FLD_END_EVE_EN:1;
+		u32 FLD_END_ODD_EN:1;
+		u32 FLD_START_EN  :1;
+		u32               :21;
+	} fld;
+} INT_CSR_R;
+
+typedef union mask_length_tag {
+	u32   reg;
+	struct {
+		u32 MASK_LEN_EVE:5;
+		u32             :11;
+		u32 MASK_LEN_ODD:5;
+		u32             :11;
+	} fld;
+} MASK_LENGTH_R;
+
+typedef union fifo_flag_cnt_tag {
+	u32   reg;
+	struct {
+		u32 AF_COUNT:7;
+		u32         :9;
+		u32 AE_COUNT:7;
+		u32         :9;
+	} fld;
+} FIFO_FLAG_CNT_R;
+
+typedef union iic_clk_dur {
+	u32   reg;
+	struct {
+		u32 PHASE_1:8;
+		u32 PHASE_2:8;
+		u32 PHASE_3:8;
+		u32 PHASE_4:8;
+	} fld;
+} IIC_CLK_DUR_R;
+
+typedef union iic_csr1_tag {
+	u32   reg;
+	struct {
+		u32 AUTO_EN     :1;
+		u32 BYPASS      :1;
+		u32 SDA_OUT     :1;
+		u32 SCL_OUT     :1;
+		u32             :4;
+		u32 AUTO_ABORT  :1;
+		u32 DIRECT_ABORT:1;
+		u32 SDA_IN      :1;
+		u32 SCL_IN      :1;
+		u32             :4;
+		u32 AUTO_ADDR   :8;
+		u32 RD_DATA     :8;
+	} fld;
+} IIC_CSR1_R;
+
+/**********************************
+ * iic_csr2_tag
+ */
+typedef union iic_csr2_tag {
+	u32   reg;
+	struct {
+		u32 DIR_WR_DATA :8;
+		u32 DIR_SUB_ADDR:8;
+		u32 DIR_RD      :1;
+		u32 DIR_ADDR    :7;
+		u32 NEW_CYCLE   :1;
+		u32             :7;
+	} fld;
+}  IIC_CSR2_R;
+
+/* use for both EVEN and ODD DMA UPPER LIMITS */
+
+/*
+ * dma_upper_lmt_tag
+ */
+typedef union dma_upper_lmt_tag   {
+	u32 reg;
+	struct {
+		u32 DMA_UPPER_LMT_VAL:24;
+		u32                  :8;
+	} fld;
+} DMA_UPPER_LMT_R;
+
+
+/*
+ * Global declarations of local copies of boards' 32 bit registers
+ */
+extern u32 even_dma_start_r;		/*  bit 0 should always be 0 */
+extern u32 odd_dma_start_r;		/*               ..          */
+extern u32 even_dma_stride_r;	/*  bits 0&1 should always be 0 */
+extern u32 odd_dma_stride_r;		/*               ..             */
+extern u32 even_pixel_fmt_r;
+extern u32 odd_pixel_fmt_r;
+
+extern FIFO_TRIGGER_R		fifo_trigger_r;
+extern XFER_MODE_R		xfer_mode_r;
+extern CSR1_R			csr1_r;
+extern RETRY_WAIT_CNT_R		retry_wait_cnt_r;
+extern INT_CSR_R		int_csr_r;
+
+extern u32 even_fld_mask_r;
+extern u32 odd_fld_mask_r;
+
+extern MASK_LENGTH_R		mask_length_r;
+extern FIFO_FLAG_CNT_R		fifo_flag_cnt_r;
+extern IIC_CLK_DUR_R		iic_clk_dur_r;
+extern IIC_CSR1_R		iic_csr1_r;
+extern IIC_CSR2_R		iic_csr2_r;
+extern DMA_UPPER_LMT_R		even_dma_upper_lmt_r;
+extern DMA_UPPER_LMT_R		odd_dma_upper_lmt_r;
+
+
+
+/***************** 8 bit I2C register globals  ***********/
+#define CSR2		0x010	/* indices of 8-bit I2C mapped reg's*/
+#define EVEN_CSR	0x011
+#define ODD_CSR		0x012
+#define CONFIG		0x013
+#define DT_ID		0x01F
+#define X_CLIP_START	0x020
+#define Y_CLIP_START	0x022
+#define X_CLIP_END	0x024
+#define Y_CLIP_END	0x026
+#define AD_ADDR		0x030
+#define AD_LUT		0x031
+#define AD_CMD		0x032
+#define DIG_OUT		0x040
+#define PM_LUT_ADDR	0x050
+#define PM_LUT_DATA	0x051
+
+
+/******** Assignments and Typedefs for 8 bit I2C Registers********************/
+
+typedef union i2c_csr2_tag {
+	u8 reg;
+	struct {
+		u8 CHROM_FIL:1;
+		u8 SYNC_SNTL:1;
+		u8 HZ50:1;
+		u8 SYNC_PRESENT:1;
+		u8 BUSY_EVE:1;
+		u8 BUSY_ODD:1;
+		u8 DISP_PASS:1;
+	} fld;
+} I2C_CSR2;
+
+typedef union i2c_even_csr_tag {
+	u8    reg;
+	struct {
+		u8 DONE_EVE :1;
+		u8 SNGL_EVE :1;
+		u8 ERROR_EVE:1;
+		u8          :5;
+	} fld;
+} I2C_EVEN_CSR;
+
+typedef union i2c_odd_csr_tag {
+	u8 reg;
+	struct {
+		u8 DONE_ODD:1;
+		u8 SNGL_ODD:1;
+		u8 ERROR_ODD:1;
+		u8 :5;
+	} fld;
+} I2C_ODD_CSR;
+
+typedef union i2c_config_tag {
+	u8 reg;
+	struct {
+		u8 ACQ_MODE:2;
+		u8 EXT_TRIG_EN:1;
+		u8 EXT_TRIG_POL:1;
+		u8 H_SCALE:1;
+		u8 CLIP:1;
+		u8 PM_LUT_SEL:1;
+		u8 PM_LUT_PGM:1;
+	} fld;
+} I2C_CONFIG;
+
+
+typedef union i2c_ad_cmd_tag {
+	/* bits can have 3 different meanings depending on value of AD_ADDR */
+	u8 reg;
+	/* Bt252 Command Register if AD_ADDR = 00h */
+	struct {
+		u8             :2;
+		u8 SYNC_LVL_SEL:2;
+		u8 SYNC_CNL_SEL:2;
+		u8 DIGITIZE_CNL_SEL1:2;
+		} bt252_command;
+
+	/* Bt252 IOUT0 register if AD_ADDR = 01h */
+	struct {
+		u8 IOUT_DATA:8;
+	} bt252_iout0;
+
+	/* BT252 IOUT1 register if AD_ADDR = 02h */
+	struct {
+		u8 IOUT_DATA:8;
+	} bt252_iout1;
+} I2C_AD_CMD;
+
+
+/***** Global declarations of local copies of boards' 8 bit I2C registers ***/
+
+extern I2C_CSR2			i2c_csr2;
+extern I2C_EVEN_CSR		i2c_even_csr;
+extern I2C_ODD_CSR		i2c_odd_csr;
+extern I2C_CONFIG		i2c_config;
+extern u8			i2c_dt_id;
+extern u8			i2c_x_clip_start;
+extern u8			i2c_y_clip_start;
+extern u8			i2c_x_clip_end;
+extern u8			i2c_y_clip_end;
+extern u8			i2c_ad_addr;
+extern u8			i2c_ad_lut;
+extern I2C_AD_CMD		i2c_ad_cmd;
+extern u8			i2c_dig_out;
+extern u8			i2c_pm_lut_addr;
+extern u8			i2c_pm_lut_data;
+
+/* Functions for Global use */
+
+/* access 8-bit IIC registers */
+
+extern int ReadI2C(u8 *lpReg, u_short wIregIndex, u8 *byVal);
+extern int WriteI2C(u8 *lpReg, u_short wIregIndex, u8 byVal);
+
+#endif
diff --git a/drivers/staging/dt3155/dt3155_isr.c b/drivers/staging/dt3155/dt3155_isr.c
new file mode 100644
index 0000000..fd7f93d
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_isr.c
@@ -0,0 +1,516 @@
+/*
+
+Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+                         Jason Lapenta, Scott Smedley, Greg Sharp
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device Driver is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The DT3155 Device Driver is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+
+   File: dt3155_isr.c
+Purpose: Buffer management routines, and other routines for the ISR
+         (the actual isr is in dt3155_drv.c)
+
+-- Changes --
+
+  Date       Programmer  Description of changes made
+  -------------------------------------------------------------------
+  03-Jul-2000 JML       n/a
+  02-Apr-2002 SS        Mods to make work with separate allocator
+                        module; Merged John Roll's mods to make work with
+                        multiple boards.
+  10-Jul-2002 GCS       Complete rewrite of setup_buffers to disallow
+                        buffers which span a 4MB boundary.
+  24-Jul-2002 SS        GPL licence.
+  30-Jul-2002 NJC       Added support for buffer loop.
+  31-Jul-2002 NJC       Complete rewrite of buffer management
+  02-Aug-2002 NJC       Including slab.h instead of malloc.h (no warning).
+                        Also, allocator_init() now returns allocator_max
+                        so cleaned up allocate_buffers() accordingly.
+  08-Aug-2005 SS        port to 2.6 kernel.
+
+*/
+
+#include <asm/system.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+
+#include "dt3155.h"
+#include "dt3155_drv.h"
+#include "dt3155_io.h"
+#include "dt3155_isr.h"
+#include "allocator.h"
+
+#define FOUR_MB         (0x0400000)  /* Can't DMA accross a 4MB boundary!*/
+#define UPPER_10_BITS   (0x3FF<<22)  /* Can't DMA accross a 4MB boundary!*/
+
+
+/* Pointer into global structure for handling buffers */
+struct dt3155_fbuffer_s *dt3155_fbuffer[MAXBOARDS] = {NULL
+#if MAXBOARDS == 2
+						      , NULL
+#endif
+};
+
+/******************************************************************************
+ * Simple array based que struct
+ *
+ * Some handy functions using the buffering structure.
+ *****************************************************************************/
+
+
+/***************************
+ * are_empty_buffers
+ * m is minor # of device
+ ***************************/
+inline bool are_empty_buffers( int m )
+{
+  return ( dt3155_fbuffer[ m ]->empty_len );
+}
+
+/**************************
+ * push_empty
+ * m is minor # of device
+ *
+ * This is slightly confusing.  The number empty_len is the literal #
+ * of empty buffers.  After calling, empty_len-1 is the index into the
+ * empty buffer stack.  So, if empty_len == 1, there is one empty buffer,
+ * given by dt3155_fbuffer[m]->empty_buffers[0].
+ * empty_buffers should never fill up, though this is not checked.
+ **************************/
+inline void push_empty( int index, int m )
+{
+  dt3155_fbuffer[m]->empty_buffers[ dt3155_fbuffer[m]->empty_len ] = index;
+  dt3155_fbuffer[m]->empty_len++;
+}
+
+/**************************
+ * pop_empty( m )
+ * m is minor # of device
+ **************************/
+inline int pop_empty( int m )
+{
+  dt3155_fbuffer[m]->empty_len--;
+  return dt3155_fbuffer[m]->empty_buffers[ dt3155_fbuffer[m]->empty_len ];
+}
+
+/*************************
+ * is_ready_buf_empty( m )
+ * m is minor # of device
+ *************************/
+inline bool is_ready_buf_empty( int m )
+{
+  return ((dt3155_fbuffer[ m ]->ready_len) == 0);
+}
+
+/*************************
+ * is_ready_buf_full( m )
+ * m is minor # of device
+ * this should *never* be true if there are any active, locked or empty
+ * buffers, since it corresponds to nbuffers ready buffers!!
+ * 7/31/02: total rewrite. --NJC
+ *************************/
+inline bool is_ready_buf_full( int m )
+{
+  return ( dt3155_fbuffer[ m ]->ready_len == dt3155_fbuffer[ m ]->nbuffers );
+}
+
+/*****************************************************
+ * push_ready( m, buffer )
+ * m is minor # of device
+ *
+ *****************************************************/
+inline void push_ready( int m, int index )
+{
+  int head = dt3155_fbuffer[m]->ready_head;
+
+  dt3155_fbuffer[ m ]->ready_que[ head ] = index;
+  dt3155_fbuffer[ m ]->ready_head = ( (head + 1) %
+				      (dt3155_fbuffer[ m ]->nbuffers) );
+  dt3155_fbuffer[ m ]->ready_len++;
+
+}
+
+/*****************************************************
+ * get_tail()
+ * m is minor # of device
+ *
+ * Simply comptutes the tail given the head and the length.
+ *****************************************************/
+static inline int get_tail( int m )
+{
+  return ((dt3155_fbuffer[ m ]->ready_head -
+	   dt3155_fbuffer[ m ]->ready_len +
+	   dt3155_fbuffer[ m ]->nbuffers)%
+	  (dt3155_fbuffer[ m ]->nbuffers));
+}
+
+
+
+/*****************************************************
+ * pop_ready()
+ * m is minor # of device
+ *
+ * This assumes that there is a ready buffer ready... should
+ * be checked (e.g. with is_ready_buf_empty()  prior to call.
+ *****************************************************/
+inline int pop_ready( int m )
+{
+  int tail;
+  tail = get_tail(m);
+  dt3155_fbuffer[ m ]->ready_len--;
+  return dt3155_fbuffer[ m ]->ready_que[ tail ];
+}
+
+
+/*****************************************************
+ * printques
+ * m is minor # of device
+ *****************************************************/
+inline void printques( int m )
+{
+  int head = dt3155_fbuffer[ m ]->ready_head;
+  int tail;
+  int num = dt3155_fbuffer[ m ]->nbuffers;
+  int frame_index;
+  int index;
+
+  tail = get_tail(m);
+
+  printk("\n R:");
+  for ( index = tail; index != head; index++, index = index % (num) )
+    {
+      frame_index = dt3155_fbuffer[ m ]->ready_que[ index ];
+      printk(" %d ", frame_index );
+    }
+
+  printk("\n E:");
+  for ( index = 0; index < dt3155_fbuffer[ m ]->empty_len; index++ )
+    {
+      frame_index = dt3155_fbuffer[ m ]->empty_buffers[ index ];
+      printk(" %d ", frame_index );
+    }
+
+  frame_index = dt3155_fbuffer[ m ]->active_buf;
+  printk("\n A: %d", frame_index);
+
+  frame_index = dt3155_fbuffer[ m ]->locked_buf;
+  printk("\n L: %d \n", frame_index );
+
+}
+
+/*****************************************************
+ * adjust_4MB
+ *
+ *  If a buffer intersects the 4MB boundary, push
+ *  the start address up to the beginning of the
+ *  next 4MB chunk (assuming bufsize < 4MB).
+ *****************************************************/
+u32 adjust_4MB (u32 buf_addr, u32 bufsize) {
+  if (((buf_addr+bufsize) & UPPER_10_BITS) != (buf_addr & UPPER_10_BITS))
+    return (buf_addr+bufsize) & UPPER_10_BITS;
+  else
+    return buf_addr;
+}
+
+
+/*****************************************************
+ * allocate_buffers
+ *
+ *  Try to allocate enough memory for all requested
+ *  buffers.  If there is not enough free space
+ *  try for less memory.
+ *****************************************************/
+void allocate_buffers (u32 *buf_addr, u32* total_size_kbs,
+		       u32 bufsize)
+{
+  /* Compute the minimum amount of memory guaranteed to hold all
+     MAXBUFFERS such that no buffer crosses the 4MB boundary.
+     Store this value in the variable "full_size" */
+
+  u32 allocator_max;
+  u32 bufs_per_chunk = (FOUR_MB / bufsize);
+  u32 filled_chunks = (MAXBUFFERS-1) / bufs_per_chunk;
+  u32 leftover_bufs = MAXBUFFERS - filled_chunks * bufs_per_chunk;
+
+  u32 full_size = bufsize      /* possibly unusable part of 1st chunk */
+    + filled_chunks * FOUR_MB   /* max # of completely filled 4mb chunks */
+    + leftover_bufs * bufsize;  /* these buffs will be in a partly filled
+				   chunk at beginning or end */
+
+  u32 full_size_kbs = 1 + (full_size-1) / 1024;
+  u32 min_size_kbs = 2*ndevices*bufsize / 1024;
+  u32 size_kbs;
+
+  /* Now, try to allocate full_size.  If this fails, keep trying for
+     less & less memory until it succeeds. */
+#ifndef STANDALONE_ALLOCATOR
+  /* initialize the allocator            */
+  allocator_init(&allocator_max);
+#endif
+  size_kbs = full_size_kbs;
+  *buf_addr = 0;
+  printk("DT3155: We would like to get: %d KB\n", full_size_kbs);
+  printk("DT3155: ...but need at least: %d KB\n", min_size_kbs);
+  printk("DT3155: ...the allocator has: %d KB\n", allocator_max);
+  size_kbs = (full_size_kbs <= allocator_max ? full_size_kbs : allocator_max);
+  if (size_kbs > min_size_kbs) {
+    if ((*buf_addr = allocator_allocate_dma (size_kbs, GFP_KERNEL)) != 0) {
+      printk("DT3155:  Managed to allocate: %d KB\n", size_kbs);
+      *total_size_kbs = size_kbs;
+      return;
+    }
+  }
+  /* If we got here, the allocation failed */
+  printk ("DT3155: Allocator failed!\n");
+  *buf_addr = 0;
+  *total_size_kbs = 0;
+  return;
+
+}
+
+
+/*****************************************************
+ * dt3155_setup_buffers
+ *
+ *  setup_buffers just puts the buffering system into
+ *  a consistent state before the start of interrupts
+ *
+ * JML : it looks like all the buffers need to be
+ * continuous. So I'm going to try and allocate one
+ * continuous buffer.
+ *
+ * GCS : Fix DMA problems when buffer spans
+ * 4MB boundary.  Also, add error checking.  This
+ * function will return -ENOMEM when not enough memory.
+ *****************************************************/
+u32 dt3155_setup_buffers(u32 *allocatorAddr)
+
+{
+  u32 index;
+  u32 rambuff_addr; /* start of allocation */
+  u32 rambuff_size; /* total size allocated to driver */
+  u32 rambuff_acm;  /* accumlator, keep track of how much
+			  is left after being split up*/
+  u32 rambuff_end;  /* end of rambuff */
+  u32 numbufs;      /* number of useful buffers allocated (per device) */
+  u32 bufsize      = DT3155_MAX_ROWS * DT3155_MAX_COLS;
+  int m;               /* minor # of device, looped for all devs */
+
+  /* zero the fbuffer status and address structure */
+  for ( m = 0; m < ndevices; m++)
+    {
+      dt3155_fbuffer[ m ] = &(dt3155_status[ m ].fbuffer);
+
+      /* Make sure the buffering variables are consistent */
+      {
+	u8 *ptr = (u8 *) dt3155_fbuffer[ m ];
+	for( index = 0; index < sizeof(struct dt3155_fbuffer_s); index++)
+	  *(ptr++)=0;
+      }
+    }
+
+  /* allocate a large contiguous chunk of RAM */
+  allocate_buffers (&rambuff_addr, &rambuff_size, bufsize);
+  printk("DT3155: mem info\n");
+  printk("  - rambuf_addr = 0x%x \n", rambuff_addr);
+  printk("  - length (kb) = %u \n", rambuff_size);
+  if( rambuff_addr == 0 )
+    {
+      printk( KERN_INFO
+	      "DT3155: Error setup_buffers() allocator dma failed \n" );
+      return -ENOMEM;
+    }
+  *allocatorAddr = rambuff_addr;
+  rambuff_end = rambuff_addr + 1024 * rambuff_size;
+
+  /* after allocation, we need to count how many useful buffers there
+     are so we can give an equal number to each device */
+  rambuff_acm = rambuff_addr;
+  for ( index = 0; index < MAXBUFFERS; index++) {
+    rambuff_acm = adjust_4MB (rambuff_acm, bufsize);/*avoid spanning 4MB bdry*/
+    if (rambuff_acm + bufsize > rambuff_end)
+      break;
+    rambuff_acm += bufsize;
+  }
+  /* Following line is OK, will waste buffers if index
+   * not evenly divisible by ndevices -NJC*/
+  numbufs = index / ndevices;
+  printk("  - numbufs = %u\n", numbufs);
+  if (numbufs < 2) {
+    printk( KERN_INFO
+	    "DT3155: Error setup_buffers() couldn't allocate 2 bufs/board\n" );
+    return -ENOMEM;
+  }
+
+  /* now that we have board memory we spit it up */
+  /* between the boards and the buffers          */
+  rambuff_acm = rambuff_addr;
+  for ( m = 0; m < ndevices; m ++)
+    {
+      rambuff_acm = adjust_4MB (rambuff_acm, bufsize);
+
+      /* Save the start of this boards buffer space (for mmap).  */
+      dt3155_status[ m ].mem_addr = rambuff_acm;
+
+      for (index = 0; index < numbufs; index++)
+	{
+	  rambuff_acm = adjust_4MB (rambuff_acm, bufsize);
+	  if (rambuff_acm + bufsize > rambuff_end) {
+	    /* Should never happen */
+	    printk ("DT3155 PROGRAM ERROR (GCS)\n"
+		    "Error distributing allocated buffers\n");
+	    return -ENOMEM;
+	  }
+
+	  dt3155_fbuffer[ m ]->frame_info[ index ].addr = rambuff_acm;
+	  push_empty( index, m );
+	  /* printk("  - Buffer : %lx\n",
+	   * dt3155_fbuffer[ m ]->frame_info[ index ].addr );
+	   */
+	  dt3155_fbuffer[ m ]->nbuffers += 1;
+	  rambuff_acm += bufsize;
+	}
+
+      /* Make sure there is an active buffer there. */
+      dt3155_fbuffer[ m ]->active_buf    = pop_empty( m );
+      dt3155_fbuffer[ m ]->even_happened = 0;
+      dt3155_fbuffer[ m ]->even_stopped  = 0;
+
+      /* make sure there is no locked_buf JML 2/28/00 */
+      dt3155_fbuffer[ m ]->locked_buf = -1;
+
+      dt3155_status[ m ].mem_size =
+	rambuff_acm - dt3155_status[ m ].mem_addr;
+
+      /* setup the ready queue */
+      dt3155_fbuffer[ m ]->ready_head = 0;
+      dt3155_fbuffer[ m ]->ready_len = 0;
+      printk("Available buffers for device %d: %d\n",
+	     m, dt3155_fbuffer[ m ]->nbuffers);
+    }
+
+  return 1;
+}
+
+/*****************************************************
+ * internal_release_locked_buffer
+ *
+ * The internal function for releasing a locked buffer.
+ * It assumes interrupts are turned off.
+ *
+ * m is minor number of device
+ *****************************************************/
+static inline void internal_release_locked_buffer( int m )
+{
+  /* Pointer into global structure for handling buffers */
+  if ( dt3155_fbuffer[ m ]->locked_buf >= 0 )
+    {
+      push_empty( dt3155_fbuffer[ m ]->locked_buf, m );
+      dt3155_fbuffer[ m ]->locked_buf = -1;
+    }
+}
+
+
+/*****************************************************
+ * dt3155_release_locked_buffer()
+ * m is minor # of device
+ *
+ * The user function of the above.
+ *
+ *****************************************************/
+inline void dt3155_release_locked_buffer( int m )
+{
+	unsigned long int flags;
+	local_save_flags(flags);
+	local_irq_disable();
+	internal_release_locked_buffer(m);
+	local_irq_restore(flags);
+}
+
+
+/*****************************************************
+ * dt3155_flush()
+ * m is minor # of device
+ *
+ *****************************************************/
+inline int dt3155_flush( int m )
+{
+  int index;
+  unsigned long int flags;
+  local_save_flags(flags);
+  local_irq_disable();
+
+  internal_release_locked_buffer( m );
+  dt3155_fbuffer[ m ]->empty_len = 0;
+
+  for ( index = 0; index < dt3155_fbuffer[ m ]->nbuffers; index++ )
+    push_empty( index,  m );
+
+  /* Make sure there is an active buffer there. */
+  dt3155_fbuffer[ m ]->active_buf = pop_empty( m );
+
+  dt3155_fbuffer[ m ]->even_happened = 0;
+  dt3155_fbuffer[ m ]->even_stopped  = 0;
+
+  /* setup the ready queue  */
+  dt3155_fbuffer[ m ]->ready_head = 0;
+  dt3155_fbuffer[ m ]->ready_len = 0;
+
+  local_irq_restore(flags);
+
+  return 0;
+}
+
+/*****************************************************
+ * dt3155_get_ready_buffer()
+ * m is minor # of device
+ *
+ * get_ready_buffer will grab the next chunk of data
+ * if it is already there, otherwise it returns 0.
+ * If the user has a buffer locked it will unlock
+ * that buffer before returning the new one.
+ *****************************************************/
+inline int dt3155_get_ready_buffer( int m )
+{
+  int frame_index;
+  unsigned long int flags;
+  local_save_flags(flags);
+  local_irq_disable();
+
+#ifdef DEBUG_QUES_A
+  printques( m );
+#endif
+
+  internal_release_locked_buffer( m );
+
+  if (is_ready_buf_empty( m ))
+    frame_index = -1;
+  else
+    {
+      frame_index = pop_ready( m );
+      dt3155_fbuffer[ m ]->locked_buf = frame_index;
+    }
+
+#ifdef DEBUG_QUES_B
+  printques( m );
+#endif
+
+  local_irq_restore(flags);
+
+  return frame_index;
+}
diff --git a/drivers/staging/dt3155/dt3155_isr.h b/drivers/staging/dt3155/dt3155_isr.h
new file mode 100644
index 0000000..7595cb1
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_isr.h
@@ -0,0 +1,77 @@
+/*
+
+Copyright 1996,2002 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+		    Jason Lapenta, Scott Smedley
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device Driver is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The DT3155 Device Driver is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+
+
+-- Changes --
+
+  Date     Programmer   Description of changes made
+  -------------------------------------------------------------------
+  03-Jul-2000 JML       n/a
+  24-Jul-2002 SS        GPL licence.
+  26-Oct-2009 SS	Porting to 2.6.30 kernel.
+
+-- notes --
+
+*/
+
+#ifndef DT3155_ISR_H
+#define DT3155_ISR_H
+
+extern struct dt3155_fbuffer_s *dt3155_fbuffer[MAXBOARDS];
+
+/* User functions for buffering */
+/* Initialize the buffering system.  This should */
+/* be called prior to enabling interrupts */
+
+u32 dt3155_setup_buffers(u32 *allocatorAddr);
+
+/* Get the next frame of data if it is ready.  Returns */
+/* zero if no data is ready.  If there is data but */
+/* the user has a locked buffer, it will unlock that */
+/* buffer and return it to the free list. */
+
+int dt3155_get_ready_buffer(int minor);
+
+/* Return a locked buffer to the free list */
+
+void dt3155_release_locked_buffer(int minor);
+
+/* Flush the buffer system */
+int dt3155_flush(int minor);
+
+/**********************************
+ * Simple array based que struct
+ **********************************/
+
+bool are_empty_buffers(int minor);
+void push_empty(int index, int minor);
+
+int  pop_empty(int minor);
+
+bool is_ready_buf_empty(int minor);
+bool is_ready_buf_full(int minor);
+
+void push_ready(int minor, int index);
+int  pop_ready(int minor);
+
+
+#endif
diff --git a/drivers/staging/et131x/et1310_address_map.h b/drivers/staging/et131x/et1310_address_map.h
index e715e4d..ea746ba 100644
--- a/drivers/staging/et131x/et1310_address_map.h
+++ b/drivers/staging/et131x/et1310_address_map.h
@@ -149,7 +149,7 @@
  * GLOBAL Module of JAGCore Address Mapping
  * Located at address 0x0000
  */
-typedef struct _GLOBAL_t {			/* Location: */
+struct global_regs {			/* Location: */
 	u32 txq_start_addr;			/*  0x0000 */
 	u32 txq_end_addr;			/*  0x0004 */
 	u32 rxq_start_addr;			/*  0x0008 */
@@ -165,9 +165,7 @@
 	u32 msi_config;				/*  0x0030 */
 	u32 loopback;			/*  0x0034 */
 	u32 watchdog_timer;			/*  0x0038 */
-} GLOBAL_t, *PGLOBAL_t;
-
-/* END OF GLOBAL REGISTER ADDRESS MAP */
+};
 
 
 /* START OF TXDMA REGISTER ADDRESS MAP */
@@ -255,7 +253,7 @@
  * Tx DMA Module of JAGCore Address Mapping
  * Located at address 0x1000
  */
-typedef struct _TXDMA_t {		/* Location: */
+struct txdma_regs {			/* Location: */
 	u32 csr;			/*  0x1000 */
 	u32 pr_base_hi;			/*  0x1004 */
 	u32 pr_base_lo;			/*  0x1008 */
@@ -282,7 +280,7 @@
 	u32 DroppedTLPCount;		/*  0x105c */
 	u32 NewServiceComplete;		/*  0x1060 */
 	u32 EthernetPacketCount;	/*  0x1064 */
-} TXDMA_t, *PTXDMA_t;
+};
 
 /* END OF TXDMA REGISTER ADDRESS MAP */
 
@@ -292,45 +290,25 @@
 /*
  * structure for control status reg in rxdma address map
  * Located at address 0x2000
+ *
+ * CSR
+ * 0: halt
+ * 1-3: tc
+ * 4: fbr_big_endian
+ * 5: psr_big_endian
+ * 6: pkt_big_endian
+ * 7: dma_big_endian
+ * 8-9: fbr0_size
+ * 10: fbr0_enable
+ * 11-12: fbr1_size
+ * 13: fbr1_enable
+ * 14: unused
+ * 15: pkt_drop_disable
+ * 16: pkt_done_flush
+ * 17: halt_status
+ * 18-31: unused
  */
-typedef union _RXDMA_CSR_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 unused2:14;		/* bits 18-31 */
-		u32 halt_status:1;	/* bit 17 */
-		u32 pkt_done_flush:1;	/* bit 16 */
-		u32 pkt_drop_disable:1;	/* bit 15 */
-		u32 unused1:1;		/* bit 14 */
-		u32 fbr1_enable:1;	/* bit 13 */
-		u32 fbr1_size:2;	/* bits 11-12 */
-		u32 fbr0_enable:1;	/* bit 10 */
-		u32 fbr0_size:2;	/* bits 8-9 */
-		u32 dma_big_endian:1;	/* bit 7 */
-		u32 pkt_big_endian:1;	/* bit 6 */
-		u32 psr_big_endian:1;	/* bit 5 */
-		u32 fbr_big_endian:1;	/* bit 4 */
-		u32 tc:3;		/* bits 1-3 */
-		u32 halt:1;		/* bit 0 */
-#else
-		u32 halt:1;		/* bit 0 */
-		u32 tc:3;		/* bits 1-3 */
-		u32 fbr_big_endian:1;	/* bit 4 */
-		u32 psr_big_endian:1;	/* bit 5 */
-		u32 pkt_big_endian:1;	/* bit 6 */
-		u32 dma_big_endian:1;	/* bit 7 */
-		u32 fbr0_size:2;	/* bits 8-9 */
-		u32 fbr0_enable:1;	/* bit 10 */
-		u32 fbr1_size:2;	/* bits 11-12 */
-		u32 fbr1_enable:1;	/* bit 13 */
-		u32 unused1:1;		/* bit 14 */
-		u32 pkt_drop_disable:1;	/* bit 15 */
-		u32 pkt_done_flush:1;	/* bit 16 */
-		u32 halt_status:1;	/* bit 17 */
-		u32 unused2:14;		/* bits 18-31 */
-#endif
-	} bits;
-} RXDMA_CSR_t, *PRXDMA_CSR_t;
+
 
 /*
  * structure for dma writeback lo reg in rxdma address map
@@ -451,18 +429,6 @@
  * 31-10: unused
  * 9-0: fbr ndesc
  */
-typedef union _RXDMA_FBR_NUM_DES_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 unused:22;		/* bits 10-31 */
-		u32 fbr_ndesc:10;	/* bits 0-9 */
-#else
-		u32 fbr_ndesc:10;	/* bits 0-9 */
-		u32 unused:22;		/* bits 10-31 */
-#endif
-	} bits;
-} RXDMA_FBR_NUM_DES_t, *PRXDMA_FBR_NUM_DES_t;
 
 /*
  * structure for free buffer ring 0 available offset reg in rxdma address map
@@ -532,8 +498,8 @@
  * Rx DMA Module of JAGCore Address Mapping
  * Located at address 0x2000
  */
-typedef struct _RXDMA_t {				/* Location: */
-	RXDMA_CSR_t csr;				/*  0x2000 */
+struct rxdma_regs {					/* Location: */
+	u32 csr;					/*  0x2000 */
 	u32 dma_wb_base_lo;				/*  0x2004 */
 	u32 dma_wb_base_hi;				/*  0x2008 */
 	u32 num_pkt_done;				/*  0x200C */
@@ -562,7 +528,7 @@
 	u32 fbr1_full_offset;				/*  0x2068 */
 	u32 fbr1_rd_index;				/*  0x206C */
 	u32 fbr1_min_des;				/*  0x2070 */
-} RXDMA_t, *PRXDMA_t;
+};
 
 /* END OF RXDMA REGISTER ADDRESS MAP */
 
@@ -572,33 +538,18 @@
 /*
  * structure for control reg in txmac address map
  * located at address 0x3000
+ *
+ * bits
+ * 31-8: unused
+ * 7: cklseg_disable
+ * 6: ckbcnt_disable
+ * 5: cksegnum
+ * 4: async_disable
+ * 3: fc_disable
+ * 2: mcif_disable
+ * 1: mif_disable
+ * 0: txmac_en
  */
-typedef union _TXMAC_CTL_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 unused:24;		/* bits 8-31 */
-		u32 cklseg_diable:1;	/* bit 7 */
-		u32 ckbcnt_disable:1;	/* bit 6 */
-		u32 cksegnum:1;		/* bit 5 */
-		u32 async_disable:1;	/* bit 4 */
-		u32 fc_disable:1;	/* bit 3 */
-		u32 mcif_disable:1;	/* bit 2 */
-		u32 mif_disable:1;	/* bit 1 */
-		u32 txmac_en:1;		/* bit 0 */
-#else
-		u32 txmac_en:1;		/* bit 0 */
-		u32 mif_disable:1;	/* bit 1 mac interface */
-		u32 mcif_disable:1;	/* bit 2 mem. contr. interface */
-		u32 fc_disable:1;	/* bit 3 */
-		u32 async_disable:1;	/* bit 4 */
-		u32 cksegnum:1;		/* bit 5 */
-		u32 ckbcnt_disable:1;	/* bit 6 */
-		u32 cklseg_diable:1;	/* bit 7 */
-		u32 unused:24;		/* bits 8-31 */
-#endif
-	} bits;
-} TXMAC_CTL_t, *PTXMAC_CTL_t;
 
 /*
  * structure for shadow pointer reg in txmac address map
@@ -612,23 +563,12 @@
 /*
  * structure for error count reg in txmac address map
  * located at address 0x3008
+ *
+ * 31-12: unused
+ * 11-8: reserved
+ * 7-4: txq_underrun
+ * 3-0: fifo_underrun
  */
-typedef union _TXMAC_ERR_CNT_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 unused:20;		/* bits 12-31 */
-		u32 reserved:4;		/* bits 8-11 */
-		u32 txq_underrun:4;	/* bits 4-7 */
-		u32 fifo_underrun:4;	/* bits 0-3 */
-#else
-		u32 fifo_underrun:4;	/* bits 0-3 */
-		u32 txq_underrun:4;	/* bits 4-7 */
-		u32 reserved:4;		/* bits 8-11 */
-		u32 unused:20;		/* bits 12-31 */
-#endif
-	} bits;
-} TXMAC_ERR_CNT_t, *PTXMAC_ERR_CNT_t;
 
 /*
  * structure for max fill reg in txmac address map
@@ -657,64 +597,32 @@
 /*
  * structure for error reg in txmac address map
  * located at address 0x3018
+ *
+ * 31-9: unused
+ * 8: fifo_underrun
+ * 7-6: unused
+ * 5: ctrl2_err
+ * 4: txq_underrun
+ * 3: bcnt_err
+ * 2: lseg_err
+ * 1: segnum_err
+ * 0: seg0_err
  */
-typedef union _TXMAC_ERR_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 unused2:23;		/* bits 9-31 */
-		u32 fifo_underrun:1;	/* bit 8 */
-		u32 unused1:2;		/* bits 6-7 */
-		u32 ctrl2_err:1;	/* bit 5 */
-		u32 txq_underrun:1;	/* bit 4 */
-		u32 bcnt_err:1;		/* bit 3 */
-		u32 lseg_err:1;		/* bit 2 */
-		u32 segnum_err:1;	/* bit 1 */
-		u32 seg0_err:1;		/* bit 0 */
-#else
-		u32 seg0_err:1;		/* bit 0 */
-		u32 segnum_err:1;	/* bit 1 */
-		u32 lseg_err:1;		/* bit 2 */
-		u32 bcnt_err:1;		/* bit 3 */
-		u32 txq_underrun:1;	/* bit 4 */
-		u32 ctrl2_err:1;	/* bit 5 */
-		u32 unused1:2;		/* bits 6-7 */
-		u32 fifo_underrun:1;	/* bit 8 */
-		u32 unused2:23;		/* bits 9-31 */
-#endif
-	} bits;
-} TXMAC_ERR_t, *PTXMAC_ERR_t;
 
 /*
  * structure for error interrupt reg in txmac address map
  * located at address 0x301C
+ *
+ * 31-9: unused
+ * 8: fifo_underrun
+ * 7-6: unused
+ * 5: ctrl2_err
+ * 4: txq_underrun
+ * 3: bcnt_err
+ * 2: lseg_err
+ * 1: segnum_err
+ * 0: seg0_err
  */
-typedef union _TXMAC_ERR_INT_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 unused2:23;		/* bits 9-31 */
-		u32 fifo_underrun:1;	/* bit 8 */
-		u32 unused1:2;		/* bits 6-7 */
-		u32 ctrl2_err:1;	/* bit 5 */
-		u32 txq_underrun:1;	/* bit 4 */
-		u32 bcnt_err:1;		/* bit 3 */
-		u32 lseg_err:1;		/* bit 2 */
-		u32 segnum_err:1;	/* bit 1 */
-		u32 seg0_err:1;		/* bit 0 */
-#else
-		u32 seg0_err:1;		/* bit 0 */
-		u32 segnum_err:1;	/* bit 1 */
-		u32 lseg_err:1;		/* bit 2 */
-		u32 bcnt_err:1;		/* bit 3 */
-		u32 txq_underrun:1;	/* bit 4 */
-		u32 ctrl2_err:1;	/* bit 5 */
-		u32 unused1:2;		/* bits 6-7 */
-		u32 fifo_underrun:1;	/* bit 8 */
-		u32 unused2:23;		/* bits 9-31 */
-#endif
-	} bits;
-} TXMAC_ERR_INT_t, *PTXMAC_ERR_INT_t;
 
 /*
  * structure for error interrupt reg in txmac address map
@@ -728,17 +636,17 @@
 /*
  * Tx MAC Module of JAGCore Address Mapping
  */
-typedef struct _TXMAC_t {		/* Location: */
-	TXMAC_CTL_t ctl;		/*  0x3000 */
+struct txmac_regs {			/* Location: */
+	u32 ctl;			/*  0x3000 */
 	u32 shadow_ptr;			/*  0x3004 */
-	TXMAC_ERR_CNT_t err_cnt;	/*  0x3008 */
+	u32 err_cnt;			/*  0x3008 */
 	u32 max_fill;			/*  0x300C */
 	u32 cf_param;			/*  0x3010 */
 	u32 tx_test;			/*  0x3014 */
-	TXMAC_ERR_t err;		/*  0x3018 */
-	TXMAC_ERR_INT_t err_int;	/*  0x301C */
+	u32 err;			/*  0x3018 */
+	u32 err_int;			/*  0x301C */
 	u32 bp_ctrl;			/*  0x3020 */
-} TXMAC_t, *PTXMAC_t;
+};
 
 /* END OF TXMAC REGISTER ADDRESS MAP */
 
@@ -747,106 +655,47 @@
 /*
  * structure for rxmac control reg in rxmac address map
  * located at address 0x4000
+ *
+ * 31-7: reserved
+ * 6: rxmac_int_disable
+ * 5: async_disable
+ * 4: mif_disable
+ * 3: wol_disable
+ * 2: pkt_filter_disable
+ * 1: mcif_disable
+ * 0: rxmac_en
  */
-typedef union _RXMAC_CTRL_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 reserved:25;		/* bits 7-31 */
-		u32 rxmac_int_disable:1;	/* bit 6 */
-		u32 async_disable:1;		/* bit 5 */
-		u32 mif_disable:1;		/* bit 4 */
-		u32 wol_disable:1;		/* bit 3 */
-		u32 pkt_filter_disable:1;	/* bit 2 */
-		u32 mcif_disable:1;		/* bit 1 */
-		u32 rxmac_en:1;			/* bit 0 */
-#else
-		u32 rxmac_en:1;			/* bit 0 */
-		u32 mcif_disable:1;		/* bit 1 */
-		u32 pkt_filter_disable:1;	/* bit 2 */
-		u32 wol_disable:1;		/* bit 3 */
-		u32 mif_disable:1;		/* bit 4 */
-		u32 async_disable:1;		/* bit 5 */
-		u32 rxmac_int_disable:1;	/* bit 6 */
-		u32 reserved:25;		/* bits 7-31 */
-#endif
-	} bits;
-} RXMAC_CTRL_t, *PRXMAC_CTRL_t;
 
 /*
  * structure for Wake On Lan Control and CRC 0 reg in rxmac address map
  * located at address 0x4004
+ * 31-16: crc
+ * 15-12: reserved
+ * 11: ignore_pp
+ * 10: ignore_mp
+ * 9: clr_intr
+ * 8: ignore_link_chg
+ * 7: ignore_uni
+ * 6: ignore_multi
+ * 5: ignore_broad
+ * 4-0: valid_crc 4-0
  */
-typedef union _RXMAC_WOL_CTL_CRC0_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 crc0:16;		/* bits 16-31 */
-		u32 reserve:4;		/* bits 12-15 */
-		u32 ignore_pp:1;	/* bit 11 */
-		u32 ignore_mp:1;	/* bit 10 */
-		u32 clr_intr:1;		/* bit 9 */
-		u32 ignore_link_chg:1;	/* bit 8 */
-		u32 ignore_uni:1;	/* bit 7 */
-		u32 ignore_multi:1;	/* bit 6 */
-		u32 ignore_broad:1;	/* bit 5 */
-		u32 valid_crc4:1;	/* bit 4 */
-		u32 valid_crc3:1;	/* bit 3 */
-		u32 valid_crc2:1;	/* bit 2 */
-		u32 valid_crc1:1;	/* bit 1 */
-		u32 valid_crc0:1;	/* bit 0 */
-#else
-		u32 valid_crc0:1;	/* bit 0 */
-		u32 valid_crc1:1;	/* bit 1 */
-		u32 valid_crc2:1;	/* bit 2 */
-		u32 valid_crc3:1;	/* bit 3 */
-		u32 valid_crc4:1;	/* bit 4 */
-		u32 ignore_broad:1;	/* bit 5 */
-		u32 ignore_multi:1;	/* bit 6 */
-		u32 ignore_uni:1;	/* bit 7 */
-		u32 ignore_link_chg:1;	/* bit 8 */
-		u32 clr_intr:1;		/* bit 9 */
-		u32 ignore_mp:1;	/* bit 10 */
-		u32 ignore_pp:1;	/* bit 11 */
-		u32 reserve:4;		/* bits 12-15 */
-		u32 crc0:16;		/* bits 16-31 */
-#endif
-	} bits;
-} RXMAC_WOL_CTL_CRC0_t, *PRXMAC_WOL_CTL_CRC0_t;
 
 /*
  * structure for CRC 1 and CRC 2 reg in rxmac address map
  * located at address 0x4008
+ *
+ * 31-16: crc2
+ * 15-0: crc1
  */
-typedef union _RXMAC_WOL_CRC12_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 crc2:16;	/* bits 16-31 */
-		u32 crc1:16;	/* bits 0-15 */
-#else
-		u32 crc1:16;	/* bits 0-15 */
-		u32 crc2:16;	/* bits 16-31 */
-#endif
-	} bits;
-} RXMAC_WOL_CRC12_t, *PRXMAC_WOL_CRC12_t;
 
 /*
  * structure for CRC 3 and CRC 4 reg in rxmac address map
  * located at address 0x400C
+ *
+ * 31-16: crc4
+ * 15-0: crc3
  */
-typedef union _RXMAC_WOL_CRC34_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 crc4:16;	/* bits 16-31 */
-		u32 crc3:16;	/* bits 0-15 */
-#else
-		u32 crc3:16;	/* bits 0-15 */
-		u32 crc4:16;	/* bits 16-31 */
-#endif
-	} bits;
-} RXMAC_WOL_CRC34_t, *PRXMAC_WOL_CRC34_t;
 
 /*
  * structure for Wake On Lan Source Address Lo reg in rxmac address map
@@ -966,164 +815,84 @@
 /*
  * structure for Packet Filter Control reg in rxmac address map
  * located at address 0x4084
+ *
+ * 31-23: unused
+ * 22-16: min_pkt_size
+ * 15-4: unused
+ * 3: filter_frag_en
+ * 2: filter_uni_en
+ * 1: filter_multi_en
+ * 0: filter_broad_en
  */
-typedef union _RXMAC_PF_CTRL_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 unused2:9;		/* bits 23-31 */
-		u32 min_pkt_size:7;	/* bits 16-22 */
-		u32 unused1:12;		/* bits 4-15 */
-		u32 filter_frag_en:1;	/* bit 3 */
-		u32 filter_uni_en:1;	/* bit 2 */
-		u32 filter_multi_en:1;	/* bit 1 */
-		u32 filter_broad_en:1;	/* bit 0 */
-#else
-		u32 filter_broad_en:1;	/* bit 0 */
-		u32 filter_multi_en:1;	/* bit 1 */
-		u32 filter_uni_en:1;	/* bit 2 */
-		u32 filter_frag_en:1;	/* bit 3 */
-		u32 unused1:12;		/* bits 4-15 */
-		u32 min_pkt_size:7;	/* bits 16-22 */
-		u32 unused2:9;		/* bits 23-31 */
-#endif
-	} bits;
-} RXMAC_PF_CTRL_t, *PRXMAC_PF_CTRL_t;
 
 /*
  * structure for Memory Controller Interface Control Max Segment reg in rxmac
  * address map.  Located at address 0x4088
+ *
+ * 31-10: reserved
+ * 9-2: max_size
+ * 1: fc_en
+ * 0: seg_en
  */
-typedef union _RXMAC_MCIF_CTRL_MAX_SEG_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 reserved:22;	/* bits 10-31 */
-		u32 max_size:8;	/* bits 2-9 */
-		u32 fc_en:1;	/* bit 1 */
-		u32 seg_en:1;	/* bit 0 */
-#else
-		u32 seg_en:1;	/* bit 0 */
-		u32 fc_en:1;	/* bit 1 */
-		u32 max_size:8;	/* bits 2-9 */
-		u32 reserved:22;	/* bits 10-31 */
-#endif
-	} bits;
-} RXMAC_MCIF_CTRL_MAX_SEG_t, *PRXMAC_MCIF_CTRL_MAX_SEG_t;
 
 /*
  * structure for Memory Controller Interface Water Mark reg in rxmac address
  * map.  Located at address 0x408C
+ *
+ * 31-26: unused
+ * 25-16: mark_hi
+ * 15-10: unused
+ * 9-0: mark_lo
  */
-typedef union _RXMAC_MCIF_WATER_MARK_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 reserved2:6;	/* bits 26-31 */
-		u32 mark_hi:10;	/* bits 16-25 */
-		u32 reserved1:6;	/* bits 10-15 */
-		u32 mark_lo:10;	/* bits 0-9 */
-#else
-		u32 mark_lo:10;	/* bits 0-9 */
-		u32 reserved1:6;	/* bits 10-15 */
-		u32 mark_hi:10;	/* bits 16-25 */
-		u32 reserved2:6;	/* bits 26-31 */
-#endif
-	} bits;
-} RXMAC_MCIF_WATER_MARK_t, *PRXMAC_MCIF_WATER_MARK_t;
 
 /*
  * structure for Rx Queue Dialog reg in rxmac address map.
  * located at address 0x4090
+ *
+ * 31-26: reserved
+ * 25-16: rd_ptr
+ * 15-10: reserved
+ * 9-0: wr_ptr
  */
-typedef union _RXMAC_RXQ_DIAG_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 reserved2:6;	/* bits 26-31 */
-		u32 rd_ptr:10;	/* bits 16-25 */
-		u32 reserved1:6;	/* bits 10-15 */
-		u32 wr_ptr:10;	/* bits 0-9 */
-#else
-		u32 wr_ptr:10;	/* bits 0-9 */
-		u32 reserved1:6;	/* bits 10-15 */
-		u32 rd_ptr:10;	/* bits 16-25 */
-		u32 reserved2:6;	/* bits 26-31 */
-#endif
-	} bits;
-} RXMAC_RXQ_DIAG_t, *PRXMAC_RXQ_DIAG_t;
 
 /*
  * structure for space availiable reg in rxmac address map.
  * located at address 0x4094
+ *
+ * 31-17: reserved
+ * 16: space_avail_en
+ * 15-10: reserved
+ * 9-0: space_avail
  */
-typedef union _RXMAC_SPACE_AVAIL_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 reserved2:15;		/* bits 17-31 */
-		u32 space_avail_en:1;	/* bit 16 */
-		u32 reserved1:6;		/* bits 10-15 */
-		u32 space_avail:10;	/* bits 0-9 */
-#else
-		u32 space_avail:10;	/* bits 0-9 */
-		u32 reserved1:6;		/* bits 10-15 */
-		u32 space_avail_en:1;	/* bit 16 */
-		u32 reserved2:15;		/* bits 17-31 */
-#endif
-	} bits;
-} RXMAC_SPACE_AVAIL_t, *PRXMAC_SPACE_AVAIL_t;
 
 /*
  * structure for management interface reg in rxmac address map.
  * located at address 0x4098
+ *
+ * 31-18: reserved
+ * 17: drop_pkt_en
+ * 16-0: drop_pkt_mask
  */
-typedef union _RXMAC_MIF_CTL_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 reserve:14;		/* bits 18-31 */
-		u32 drop_pkt_en:1;		/* bit 17 */
-		u32 drop_pkt_mask:17;	/* bits 0-16 */
-#else
-		u32 drop_pkt_mask:17;	/* bits 0-16 */
-		u32 drop_pkt_en:1;		/* bit 17 */
-		u32 reserve:14;		/* bits 18-31 */
-#endif
-	} bits;
-} RXMAC_MIF_CTL_t, *PRXMAC_MIF_CTL_t;
 
 /*
  * structure for Error reg in rxmac address map.
  * located at address 0x409C
+ *
+ * 31-4: unused
+ * 3: mif
+ * 2: async
+ * 1: pkt_filter
+ * 0: mcif
  */
-typedef union _RXMAC_ERROR_REG_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 reserve:28;	/* bits 4-31 */
-		u32 mif:1;		/* bit 3 */
-		u32 async:1;	/* bit 2 */
-		u32 pkt_filter:1;	/* bit 1 */
-		u32 mcif:1;	/* bit 0 */
-#else
-		u32 mcif:1;	/* bit 0 */
-		u32 pkt_filter:1;	/* bit 1 */
-		u32 async:1;	/* bit 2 */
-		u32 mif:1;		/* bit 3 */
-		u32 reserve:28;	/* bits 4-31 */
-#endif
-	} bits;
-} RXMAC_ERROR_REG_t, *PRXMAC_ERROR_REG_t;
 
 /*
  * Rx MAC Module of JAGCore Address Mapping
  */
 typedef struct _RXMAC_t {				/* Location: */
-	RXMAC_CTRL_t ctrl;				/*  0x4000 */
-	RXMAC_WOL_CTL_CRC0_t crc0;			/*  0x4004 */
-	RXMAC_WOL_CRC12_t crc12;			/*  0x4008 */
-	RXMAC_WOL_CRC34_t crc34;			/*  0x400C */
+	u32 ctrl;					/*  0x4000 */
+	u32 crc0;					/*  0x4004 */
+	u32 crc12;					/*  0x4008 */
+	u32 crc34;					/*  0x400C */
 	RXMAC_WOL_SA_LO_t sa_lo;			/*  0x4010 */
 	RXMAC_WOL_SA_HI_t sa_hi;			/*  0x4014 */
 	u32 mask0_word0;				/*  0x4018 */
@@ -1153,17 +922,17 @@
 	u32 multi_hash2;				/*  0x4078 */
 	u32 multi_hash3;				/*  0x407C */
 	u32 multi_hash4;				/*  0x4080 */
-	RXMAC_PF_CTRL_t pf_ctrl;			/*  0x4084 */
-	RXMAC_MCIF_CTRL_MAX_SEG_t mcif_ctrl_max_seg;	/*  0x4088 */
-	RXMAC_MCIF_WATER_MARK_t mcif_water_mark;	/*  0x408C */
-	RXMAC_RXQ_DIAG_t rxq_diag;			/*  0x4090 */
-	RXMAC_SPACE_AVAIL_t space_avail;		/*  0x4094 */
+	u32 pf_ctrl;					/*  0x4084 */
+	u32 mcif_ctrl_max_seg;				/*  0x4088 */
+	u32 mcif_water_mark;				/*  0x408C */
+	u32 rxq_diag;					/*  0x4090 */
+	u32 space_avail;				/*  0x4094 */
 
-	RXMAC_MIF_CTL_t mif_ctrl;			/*  0x4098 */
-	RXMAC_ERROR_REG_t err_reg;			/*  0x409C */
+	u32 mif_ctrl;					/*  0x4098 */
+	u32 err_reg;					/*  0x409C */
 } RXMAC_t, *PRXMAC_t;
 
-/* END OF TXMAC REGISTER ADDRESS MAP */
+/* END OF RXMAC REGISTER ADDRESS MAP */
 
 
 /* START OF MAC REGISTER ADDRESS MAP */
@@ -1337,37 +1106,19 @@
 /*
  * structure for Interface Status reg in mac address map.
  * located at address 0x503C
+ *
+ * 31-10: reserved
+ * 9: excess_defer
+ * 8: clash
+ * 7: phy_jabber
+ * 6: phy_link_ok
+ * 5: phy_full_duplex
+ * 4: phy_speed
+ * 3: pe100x_link_fail
+ * 2: pe10t_loss_carrier
+ * 1: pe10t_sqe_error
+ * 0: pe10t_jabber
  */
-typedef union _MAC_IF_STAT_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 reserved:22;		/* bits 10-31 */
-		u32 excess_defer:1;	/* bit 9 */
-		u32 clash:1;		/* bit 8 */
-		u32 phy_jabber:1;		/* bit 7 */
-		u32 phy_link_ok:1;		/* bit 6 */
-		u32 phy_full_duplex:1;	/* bit 5 */
-		u32 phy_speed:1;		/* bit 4 */
-		u32 pe100x_link_fail:1;	/* bit 3 */
-		u32 pe10t_loss_carrie:1;	/* bit 2 */
-		u32 pe10t_sqe_error:1;	/* bit 1 */
-		u32 pe10t_jabber:1;	/* bit 0 */
-#else
-		u32 pe10t_jabber:1;	/* bit 0 */
-		u32 pe10t_sqe_error:1;	/* bit 1 */
-		u32 pe10t_loss_carrie:1;	/* bit 2 */
-		u32 pe100x_link_fail:1;	/* bit 3 */
-		u32 phy_speed:1;		/* bit 4 */
-		u32 phy_full_duplex:1;	/* bit 5 */
-		u32 phy_link_ok:1;		/* bit 6 */
-		u32 phy_jabber:1;		/* bit 7 */
-		u32 clash:1;		/* bit 8 */
-		u32 excess_defer:1;	/* bit 9 */
-		u32 reserved:22;		/* bits 10-31 */
-#endif
-	} bits;
-} MAC_IF_STAT_t, *PMAC_IF_STAT_t;
 
 /*
  * structure for Mac Station Address, Part 1 reg in mac address map.
@@ -1428,7 +1179,7 @@
 	u32 mii_mgmt_stat;				/*  0x5030 */
 	u32 mii_mgmt_indicator;				/*  0x5034 */
 	u32 if_ctrl;					/*  0x5038 */
-	MAC_IF_STAT_t if_stat;				/*  0x503C */
+	u32 if_stat;					/*  0x503C */
 	MAC_STATION_ADDR1_t station_addr_1;		/*  0x5040 */
 	MAC_STATION_ADDR2_t station_addr_2;		/*  0x5044 */
 } MAC_t, *PMAC_t;
@@ -1498,8 +1249,9 @@
 /*
  * MAC STATS Module of JAGCore Address Mapping
  */
-typedef struct _MAC_STAT_t {		/* Location: */
-	u32 pad[32];		/*  0x6000 - 607C */
+struct macstat_regs
+{					/* Location: */
+	u32 pad[32];			/*  0x6000 - 607C */
 
 	/* Tx/Rx 0-64 Byte Frame Counter */
 	u32 TR64;			/*  0x6080 */
@@ -1644,7 +1396,7 @@
 
 	/* Carry Register Two Mask Register */
 	u32 Carry2M;			/*  0x613C */
-} MAC_STAT_t, *PMAC_STAT_t;
+};
 
 /* END OF MAC STAT REGISTER ADDRESS MAP */
 
@@ -1682,70 +1434,49 @@
 /*
  * Memory Control Module of JAGCore Address Mapping
  */
-typedef struct _MMC_t {			/* Location: */
+struct mmc_regs {		/* Location: */
 	u32 mmc_ctrl;		/*  0x7000 */
 	u32 sram_access;	/*  0x7004 */
 	u32 sram_word1;		/*  0x7008 */
 	u32 sram_word2;		/*  0x700C */
 	u32 sram_word3;		/*  0x7010 */
 	u32 sram_word4;		/*  0x7014 */
-} MMC_t, *PMMC_t;
+};
 
 /* END OF MMC REGISTER ADDRESS MAP */
 
 
-/* START OF EXP ROM REGISTER ADDRESS MAP */
-
-/*
- * Expansion ROM Module of JAGCore Address Mapping
- */
-
-/* Take this out until it is not empty */
-#if 0
-typedef struct _EXP_ROM_t {
-
-} EXP_ROM_t, *PEXP_ROM_t;
-#endif
-
-/* END OF EXP ROM REGISTER ADDRESS MAP */
-
-
 /*
  * JAGCore Address Mapping
  */
 typedef struct _ADDRESS_MAP_t {
-	GLOBAL_t global;
+	struct global_regs global;
 	/* unused section of global address map */
-	u8 unused_global[4096 - sizeof(GLOBAL_t)];
-	TXDMA_t txdma;
+	u8 unused_global[4096 - sizeof(struct global_regs)];
+	struct txdma_regs txdma;
 	/* unused section of txdma address map */
-	u8 unused_txdma[4096 - sizeof(TXDMA_t)];
-	RXDMA_t rxdma;
+	u8 unused_txdma[4096 - sizeof(struct txdma_regs)];
+	struct rxdma_regs rxdma;
 	/* unused section of rxdma address map */
-	u8 unused_rxdma[4096 - sizeof(RXDMA_t)];
-	TXMAC_t txmac;
+	u8 unused_rxdma[4096 - sizeof(struct rxdma_regs)];
+	struct txmac_regs txmac;
 	/* unused section of txmac address map */
-	u8 unused_txmac[4096 - sizeof(TXMAC_t)];
+	u8 unused_txmac[4096 - sizeof(struct txmac_regs)];
 	RXMAC_t rxmac;
 	/* unused section of rxmac address map */
 	u8 unused_rxmac[4096 - sizeof(RXMAC_t)];
 	MAC_t mac;
 	/* unused section of mac address map */
 	u8 unused_mac[4096 - sizeof(MAC_t)];
-	MAC_STAT_t macStat;
+	struct macstat_regs macstat;
 	/* unused section of mac stat address map */
-	u8 unused_mac_stat[4096 - sizeof(MAC_STAT_t)];
-	MMC_t mmc;
+	u8 unused_mac_stat[4096 - sizeof(struct macstat_regs)];
+	struct mmc_regs mmc;
 	/* unused section of mmc address map */
-	u8 unused_mmc[4096 - sizeof(MMC_t)];
+	u8 unused_mmc[4096 - sizeof(struct mmc_regs)];
 	/* unused section of address map */
 	u8 unused_[1015808];
 
-/* Take this out until it is not empty */
-#if 0
-	EXP_ROM_t exp_rom;
-#endif
-
 	u8 unused_exp_rom[4096];	/* MGS-size TBD */
 	u8 unused__[524288];	/* unused section of address map */
 } ADDRESS_MAP_t, *PADDRESS_MAP_t;
diff --git a/drivers/staging/et131x/et1310_eeprom.c b/drivers/staging/et131x/et1310_eeprom.c
index bcca1f8..3ca2536 100644
--- a/drivers/staging/et131x/et1310_eeprom.c
+++ b/drivers/staging/et131x/et1310_eeprom.c
@@ -84,17 +84,42 @@
 #include <linux/ioport.h>
 
 #include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-#include "et1310_eeprom.h"
-
 #include "et131x_adapter.h"
-#include "et131x_initpci.h"
-#include "et131x_isr.h"
+#include "et131x.h"
 
-#include "et1310_tx.h"
+/*
+ * EEPROM Defines
+ */
 
+/* LBCIF Register Groups (addressed via 32-bit offsets) */
+#define LBCIF_DWORD0_GROUP       0xAC
+#define LBCIF_DWORD1_GROUP       0xB0
 
+/* LBCIF Registers (addressed via 8-bit offsets) */
+#define LBCIF_ADDRESS_REGISTER   0xAC
+#define LBCIF_DATA_REGISTER      0xB0
+#define LBCIF_CONTROL_REGISTER   0xB1
+#define LBCIF_STATUS_REGISTER    0xB2
+
+/* LBCIF Control Register Bits */
+#define LBCIF_CONTROL_SEQUENTIAL_READ   0x01
+#define LBCIF_CONTROL_PAGE_WRITE        0x02
+#define LBCIF_CONTROL_EEPROM_RELOAD     0x08
+#define LBCIF_CONTROL_TWO_BYTE_ADDR     0x20
+#define LBCIF_CONTROL_I2C_WRITE         0x40
+#define LBCIF_CONTROL_LBCIF_ENABLE      0x80
+
+/* LBCIF Status Register Bits */
+#define LBCIF_STATUS_PHY_QUEUE_AVAIL    0x01
+#define LBCIF_STATUS_I2C_IDLE           0x02
+#define LBCIF_STATUS_ACK_ERROR          0x04
+#define LBCIF_STATUS_GENERAL_ERROR      0x08
+#define LBCIF_STATUS_CHECKSUM_ERROR     0x40
+#define LBCIF_STATUS_EEPROM_PRESENT     0x80
+
+/* Miscellaneous Constraints */
+#define MAX_NUM_REGISTER_POLLS          1000
+#define MAX_NUM_WRITE_RETRIES           2
 
 static int eeprom_wait_ready(struct pci_dev *pdev, u32 *status)
 {
diff --git a/drivers/staging/et131x/et1310_eeprom.h b/drivers/staging/et131x/et1310_eeprom.h
deleted file mode 100644
index 6a6c6a6..0000000
--- a/drivers/staging/et131x/et1310_eeprom.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *   http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et1310_eeprom.h - Defines, structs, enums, prototypes, etc. used for EEPROM
- *                   access routines
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software.  Using this
- * software indicates your acceptance of these terms and conditions.  If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following Disclaimer as comments in the code as
- *    well as in the documentation and/or other materials provided with the
- *    distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following Disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET1310_EEPROM_H__
-#define __ET1310_EEPROM_H__
-
-#include "et1310_address_map.h"
-
-/*
- * EEPROM Defines
- */
-
-/* LBCIF Register Groups (addressed via 32-bit offsets) */
-#define LBCIF_DWORD0_GROUP       0xAC
-#define LBCIF_DWORD1_GROUP       0xB0
-
-/* LBCIF Registers (addressed via 8-bit offsets) */
-#define LBCIF_ADDRESS_REGISTER   0xAC
-#define LBCIF_DATA_REGISTER      0xB0
-#define LBCIF_CONTROL_REGISTER   0xB1
-#define LBCIF_STATUS_REGISTER    0xB2
-
-/* LBCIF Control Register Bits */
-#define LBCIF_CONTROL_SEQUENTIAL_READ   0x01
-#define LBCIF_CONTROL_PAGE_WRITE        0x02
-#define LBCIF_CONTROL_EEPROM_RELOAD     0x08
-#define LBCIF_CONTROL_TWO_BYTE_ADDR     0x20
-#define LBCIF_CONTROL_I2C_WRITE         0x40
-#define LBCIF_CONTROL_LBCIF_ENABLE      0x80
-
-/* LBCIF Status Register Bits */
-#define LBCIF_STATUS_PHY_QUEUE_AVAIL    0x01
-#define LBCIF_STATUS_I2C_IDLE           0x02
-#define LBCIF_STATUS_ACK_ERROR          0x04
-#define LBCIF_STATUS_GENERAL_ERROR      0x08
-#define LBCIF_STATUS_CHECKSUM_ERROR     0x40
-#define LBCIF_STATUS_EEPROM_PRESENT     0x80
-
-/* Miscellaneous Constraints */
-#define MAX_NUM_REGISTER_POLLS          1000
-#define MAX_NUM_WRITE_RETRIES           2
-
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-int et131x_init_eeprom(struct et131x_adapter *etdev);
-
-#endif /* _ET1310_EEPROM_H_ */
diff --git a/drivers/staging/et131x/et1310_jagcore.h b/drivers/staging/et131x/et1310_jagcore.h
deleted file mode 100644
index 0807a01..0000000
--- a/drivers/staging/et131x/et1310_jagcore.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *   http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et1310_jagcore.h - Defines, structs, enums, prototypes, etc. pertaining to
- *                    the JAGCore
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software.  Using this
- * software indicates your acceptance of these terms and conditions.  If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following Disclaimer as comments in the code as
- *    well as in the documentation and/or other materials provided with the
- *    distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following Disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET1310_JAGCORE_H__
-#define __ET1310_JAGCORE_H__
-
-#include "et1310_address_map.h"
-
-
-#define INTERNAL_MEM_SIZE       0x400	/* 1024 of internal memory */
-#define INTERNAL_MEM_RX_OFFSET  0x1FF	/* 50%   Tx, 50%   Rx */
-
-/*
- * For interrupts, normal running is:
- *       rxdma_xfr_done, phy_interrupt, mac_stat_interrupt,
- *       watchdog_interrupt & txdma_xfer_done
- *
- * In both cases, when flow control is enabled for either Tx or bi-direction,
- * we additional enable rx_fbr0_low and rx_fbr1_low, so we know when the
- * buffer rings are running low.
- */
-#define INT_MASK_DISABLE            0xffffffff
-
-/* NOTE: Masking out MAC_STAT Interrupt for now...
- * #define INT_MASK_ENABLE             0xfff6bf17
- * #define INT_MASK_ENABLE_NO_FLOW     0xfff6bfd7
- */
-#define INT_MASK_ENABLE             0xfffebf17
-#define INT_MASK_ENABLE_NO_FLOW     0xfffebfd7
-
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-void ConfigGlobalRegs(struct et131x_adapter *pAdapter);
-void ConfigMMCRegs(struct et131x_adapter *pAdapter);
-void et131x_enable_interrupts(struct et131x_adapter *adapter);
-void et131x_disable_interrupts(struct et131x_adapter *adapter);
-
-#endif /* __ET1310_JAGCORE_H__ */
diff --git a/drivers/staging/et131x/et1310_mac.c b/drivers/staging/et131x/et1310_mac.c
index b8a1f20..a292b1e 100644
--- a/drivers/staging/et131x/et1310_mac.c
+++ b/drivers/staging/et131x/et1310_mac.c
@@ -85,12 +85,19 @@
 #include <linux/crc32.h>
 
 #include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-#include "et1310_mac.h"
-
 #include "et131x_adapter.h"
-#include "et131x_initpci.h"
+#include "et131x.h"
+
+
+#define COUNTER_WRAP_28_BIT 0x10000000
+#define COUNTER_WRAP_22_BIT 0x400000
+#define COUNTER_WRAP_16_BIT 0x10000
+#define COUNTER_WRAP_12_BIT 0x1000
+
+#define COUNTER_MASK_28_BIT (COUNTER_WRAP_28_BIT - 1)
+#define COUNTER_MASK_22_BIT (COUNTER_WRAP_22_BIT - 1)
+#define COUNTER_MASK_16_BIT (COUNTER_WRAP_16_BIT - 1)
+#define COUNTER_MASK_12_BIT (COUNTER_WRAP_12_BIT - 1)
 
 /**
  * ConfigMacRegs1 - Initialize the first part of MAC regs
@@ -163,9 +170,9 @@
 	u32 cfg1;
 	u32 cfg2;
 	u32 ifctrl;
-	TXMAC_CTL_t ctl;
+	u32 ctl;
 
-	ctl.value = readl(&etdev->regs->txmac.ctl.value);
+	ctl = readl(&etdev->regs->txmac.ctl);
 	cfg1 = readl(&pMac->cfg1);
 	cfg2 = readl(&pMac->cfg2);
 	ifctrl = readl(&pMac->if_ctrl);
@@ -219,9 +226,8 @@
 	}
 
 	/* Enable TXMAC */
-	ctl.bits.txmac_en = 0x1;
-	ctl.bits.fc_disable = 0x1;
-	writel(ctl.value, &etdev->regs->txmac.ctl.value);
+	ctl |= 0x05;	/* TX mac enable, FC disable */
+	writel(ctl, &etdev->regs->txmac.ctl);
 
 	/* Ready to start the RXDMA/TXDMA engine */
 	if (etdev->Flags & fMP_ADAPTER_LOWER_POWER) {
@@ -235,15 +241,15 @@
 	struct _RXMAC_t __iomem *pRxMac = &etdev->regs->rxmac;
 	RXMAC_WOL_SA_LO_t sa_lo;
 	RXMAC_WOL_SA_HI_t sa_hi;
-	RXMAC_PF_CTRL_t pf_ctrl = { 0 };
+	u32 pf_ctrl = 0;
 
 	/* Disable the MAC while it is being configured (also disable WOL) */
-	writel(0x8, &pRxMac->ctrl.value);
+	writel(0x8, &pRxMac->ctrl);
 
 	/* Initialize WOL to disabled. */
-	writel(0, &pRxMac->crc0.value);
-	writel(0, &pRxMac->crc12.value);
-	writel(0, &pRxMac->crc34.value);
+	writel(0, &pRxMac->crc0);
+	writel(0, &pRxMac->crc12);
+	writel(0, &pRxMac->crc34);
 
 	/* We need to set the WOL mask0 - mask4 next.  We initialize it to
 	 * its default Values of 0x00000000 because there are not WOL masks
@@ -286,12 +292,12 @@
 	writel(sa_hi.value, &pRxMac->sa_hi.value);
 
 	/* Disable all Packet Filtering */
-	writel(0, &pRxMac->pf_ctrl.value);
+	writel(0, &pRxMac->pf_ctrl);
 
 	/* Let's initialize the Unicast Packet filtering address */
 	if (etdev->PacketFilter & ET131X_PACKET_TYPE_DIRECTED) {
 		SetupDeviceForUnicast(etdev);
-		pf_ctrl.bits.filter_uni_en = 1;
+		pf_ctrl |= 4;	/* Unicast filter */
 	} else {
 		writel(0, &pRxMac->uni_pf_addr1.value);
 		writel(0, &pRxMac->uni_pf_addr2.value);
@@ -299,20 +305,16 @@
 	}
 
 	/* Let's initialize the Multicast hash */
-	if (etdev->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST) {
-		pf_ctrl.bits.filter_multi_en = 0;
-	} else {
-		pf_ctrl.bits.filter_multi_en = 1;
+	if (!(etdev->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST)) {
+		pf_ctrl |= 2;	/* Multicast filter */
 		SetupDeviceForMulticast(etdev);
 	}
 
 	/* Runt packet filtering.  Didn't work in version A silicon. */
-	pf_ctrl.bits.min_pkt_size = NIC_MIN_PACKET_SIZE + 4;
-	pf_ctrl.bits.filter_frag_en = 1;
+	pf_ctrl |= (NIC_MIN_PACKET_SIZE + 4) << 16;
+	pf_ctrl |= 8;	/* Fragment filter */
 
-	if (etdev->RegistryJumboPacket > 8192) {
-		RXMAC_MCIF_CTRL_MAX_SEG_t mcif_ctrl_max_seg;
-
+	if (etdev->RegistryJumboPacket > 8192)
 		/* In order to transmit jumbo packets greater than 8k, the
 		 * FIFO between RxMAC and RxDMA needs to be reduced in size
 		 * to (16k - Jumbo packet size).  In order to implement this,
@@ -320,25 +322,21 @@
 		 * packets down into segments which are (max_size * 16).  In
 		 * this case we selected 256 bytes, since this is the size of
 		 * the PCI-Express TLP's that the 1310 uses.
+		 *
+		 * seg_en on, fc_en off, size 0x10
 		 */
-		mcif_ctrl_max_seg.bits.seg_en = 0x1;
-		mcif_ctrl_max_seg.bits.fc_en = 0x0;
-		mcif_ctrl_max_seg.bits.max_size = 0x10;
-
-		writel(mcif_ctrl_max_seg.value,
-		       &pRxMac->mcif_ctrl_max_seg.value);
-	} else {
-		writel(0, &pRxMac->mcif_ctrl_max_seg.value);
-	}
+		writel(0x41, &pRxMac->mcif_ctrl_max_seg);
+	else
+		writel(0, &pRxMac->mcif_ctrl_max_seg);
 
 	/* Initialize the MCIF water marks */
-	writel(0, &pRxMac->mcif_water_mark.value);
+	writel(0, &pRxMac->mcif_water_mark);
 
 	/*  Initialize the MIF control */
-	writel(0, &pRxMac->mif_ctrl.value);
+	writel(0, &pRxMac->mif_ctrl);
 
 	/* Initialize the Space Available Register */
-	writel(0, &pRxMac->space_avail.value);
+	writel(0, &pRxMac->space_avail);
 
 	/* Initialize the the mif_ctrl register
 	 * bit 3:  Receive code error. One or more nibbles were signaled as
@@ -354,9 +352,9 @@
 	 * bit 17: Drop packet enable
 	 */
 	if (etdev->linkspeed == TRUEPHY_SPEED_100MBPS)
-		writel(0x30038, &pRxMac->mif_ctrl.value);
+		writel(0x30038, &pRxMac->mif_ctrl);
 	else
-		writel(0x30030, &pRxMac->mif_ctrl.value);
+		writel(0x30030, &pRxMac->mif_ctrl);
 
 	/* Finally we initialize RxMac to be enabled & WOL disabled.  Packet
 	 * filter is always enabled since it is where the runt packets are
@@ -364,28 +362,28 @@
 	 * dropping doesn't work, so it is disabled in the pf_ctrl register,
 	 * but we still leave the packet filter on.
 	 */
-	writel(pf_ctrl.value, &pRxMac->pf_ctrl.value);
-	writel(0x9, &pRxMac->ctrl.value);
+	writel(pf_ctrl, &pRxMac->pf_ctrl);
+	writel(0x9, &pRxMac->ctrl);
 }
 
 void ConfigTxMacRegs(struct et131x_adapter *etdev)
 {
-	struct _TXMAC_t __iomem *pTxMac = &etdev->regs->txmac;
+	struct txmac_regs *txmac = &etdev->regs->txmac;
 
 	/* We need to update the Control Frame Parameters
 	 * cfpt - control frame pause timer set to 64 (0x40)
 	 * cfep - control frame extended pause timer set to 0x0
 	 */
 	if (etdev->FlowControl == None)
-		writel(0, &pTxMac->cf_param);
+		writel(0, &txmac->cf_param);
 	else
-		writel(0x40, &pTxMac->cf_param);
+		writel(0x40, &txmac->cf_param);
 }
 
 void ConfigMacStatRegs(struct et131x_adapter *etdev)
 {
-	struct _MAC_STAT_t __iomem *macstat =
-		&etdev->regs->macStat;
+	struct macstat_regs __iomem *macstat =
+		&etdev->regs->macstat;
 
 	/* Next we need to initialize all the MAC_STAT registers to zero on
 	 * the device.
@@ -456,8 +454,8 @@
 void UpdateMacStatHostCounters(struct et131x_adapter *etdev)
 {
 	struct _ce_stats_t *stats = &etdev->Stats;
-	struct _MAC_STAT_t __iomem *macstat =
-		&etdev->regs->macStat;
+	struct macstat_regs __iomem *macstat =
+		&etdev->regs->macstat;
 
 	stats->collisions += readl(&macstat->TNcl);
 	stats->first_collision += readl(&macstat->TScl);
@@ -493,11 +491,11 @@
 	/* Read the interrupt bits from the register(s).  These are Clear On
 	 * Write.
 	 */
-	Carry1 = readl(&etdev->regs->macStat.Carry1);
-	Carry2 = readl(&etdev->regs->macStat.Carry2);
+	Carry1 = readl(&etdev->regs->macstat.Carry1);
+	Carry2 = readl(&etdev->regs->macstat.Carry2);
 
-	writel(Carry1, &etdev->regs->macStat.Carry1);
-	writel(Carry2, &etdev->regs->macStat.Carry2);
+	writel(Carry1, &etdev->regs->macstat.Carry1);
+	writel(Carry2, &etdev->regs->macstat.Carry2);
 
 	/* We need to do update the host copy of all the MAC_STAT counters.
 	 * For each counter, check it's overflow bit.  If the overflow bit is
diff --git a/drivers/staging/et131x/et1310_mac.h b/drivers/staging/et131x/et1310_mac.h
deleted file mode 100644
index 2c38595..0000000
--- a/drivers/staging/et131x/et1310_mac.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *   http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et1310_mac.h -  Defines, structs, enums, prototypes, etc. pertaining to the
- *                 MAC.
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software.  Using this
- * software indicates your acceptance of these terms and conditions.  If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following Disclaimer as comments in the code as
- *    well as in the documentation and/or other materials provided with the
- *    distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following Disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef _ET1310_MAC_H_
-#define _ET1310_MAC_H_
-
-
-#include "et1310_address_map.h"
-
-
-#define COUNTER_WRAP_28_BIT 0x10000000
-#define COUNTER_WRAP_22_BIT 0x400000
-#define COUNTER_WRAP_16_BIT 0x10000
-#define COUNTER_WRAP_12_BIT 0x1000
-
-#define COUNTER_MASK_28_BIT (COUNTER_WRAP_28_BIT - 1)
-#define COUNTER_MASK_22_BIT (COUNTER_WRAP_22_BIT - 1)
-#define COUNTER_MASK_16_BIT (COUNTER_WRAP_16_BIT - 1)
-#define COUNTER_MASK_12_BIT (COUNTER_WRAP_12_BIT - 1)
-
-#define UPDATE_COUNTER(HostCnt, DevCnt) \
-    HostCnt = HostCnt + DevCnt;
-
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-void ConfigMACRegs1(struct et131x_adapter *adapter);
-void ConfigMACRegs2(struct et131x_adapter *adapter);
-void ConfigRxMacRegs(struct et131x_adapter *adapter);
-void ConfigTxMacRegs(struct et131x_adapter *adapter);
-void ConfigMacStatRegs(struct et131x_adapter *adapter);
-void ConfigFlowControl(struct et131x_adapter *adapter);
-void UpdateMacStatHostCounters(struct et131x_adapter *adapter);
-void HandleMacStatInterrupt(struct et131x_adapter *adapter);
-void SetupDeviceForMulticast(struct et131x_adapter *adapter);
-void SetupDeviceForUnicast(struct et131x_adapter *adapter);
-
-#endif /* _ET1310_MAC_H_ */
diff --git a/drivers/staging/et131x/et1310_phy.c b/drivers/staging/et131x/et1310_phy.c
index 6ecad61..4a55fbf 100644
--- a/drivers/staging/et131x/et1310_phy.c
+++ b/drivers/staging/et131x/et1310_phy.c
@@ -85,17 +85,14 @@
 #include <linux/random.h>
 
 #include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
 
 #include "et131x_adapter.h"
-#include "et131x_netdev.h"
-#include "et131x_initpci.h"
 
 #include "et1310_address_map.h"
 #include "et1310_tx.h"
 #include "et1310_rx.h"
-#include "et1310_mac.h"
+
+#include "et131x.h"
 
 /* Prototypes for functions with local scope */
 static void et131x_xcvr_init(struct et131x_adapter *etdev);
diff --git a/drivers/staging/et131x/et1310_phy.h b/drivers/staging/et131x/et1310_phy.h
index 758b9b2..47907ba 100644
--- a/drivers/staging/et131x/et1310_phy.h
+++ b/drivers/staging/et131x/et1310_phy.h
@@ -736,32 +736,8 @@
 
 /* MI Register 29 - 31: Reserved Reg(0x1D - 0x1E) */
 
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
 
 /* Prototypes for ET1310_phy.c */
-int et131x_xcvr_find(struct et131x_adapter *adapter);
-void et131x_setphy_normal(struct et131x_adapter *adapter);
-
-/* static inline function does not work because et131x_adapter is not always
- * defined
- */
-int PhyMiRead(struct et131x_adapter *adapter, u8 xcvrAddr,
-	      u8 xcvrReg, u16 *value);
-#define MiRead(adapter, xcvrReg, value) \
-	PhyMiRead((adapter), (adapter)->Stats.xcvr_addr, (xcvrReg), (value))
-
-int32_t MiWrite(struct et131x_adapter *adapter,
-		u8 xcvReg, u16 value);
-void et131x_Mii_check(struct et131x_adapter *pAdapter,
-		      MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints);
-
-/* This last is not strictly required (the driver could call the TPAL
- * version instead), but this sets the adapter up correctly, and calls the
- * access routine indirectly.  This protects the driver from changes in TPAL.
- */
-void SetPhy_10BaseTHalfDuplex(struct et131x_adapter *adapter);
-
 /* Defines for PHY access routines */
 
 /* Define bit operation flags */
@@ -843,14 +819,4 @@
 					/* #define TRU_VMI_LINK_CONTROL_REGISTER           29 */
 					/* #define TRU_VMI_TIMING_CONTROL_REGISTER */
 
-/* Prototypes for PHY access routines */
-void ET1310_PhyInit(struct et131x_adapter *adapter);
-void ET1310_PhyReset(struct et131x_adapter *adapter);
-void ET1310_PhyPowerDown(struct et131x_adapter *adapter, bool down);
-void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *adapter,
-				  u16 duplex);
-void ET1310_PhyAccessMiBit(struct et131x_adapter *adapter,
-			   u16 action,
-			   u16 regnum, u16 bitnum, u8 *value);
-
 #endif /* _ET1310_PHY_H_ */
diff --git a/drivers/staging/et131x/et1310_pm.c b/drivers/staging/et131x/et1310_pm.c
index 7d07723..41019e3 100644
--- a/drivers/staging/et131x/et1310_pm.c
+++ b/drivers/staging/et131x/et1310_pm.c
@@ -83,13 +83,9 @@
 #include <linux/ioport.h>
 
 #include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-#include "et1310_mac.h"
 #include "et1310_rx.h"
-
 #include "et131x_adapter.h"
-#include "et131x_initpci.h"
+#include "et131x.h"
 
 /**
  * EnablePhyComa - called when network cable is unplugged
diff --git a/drivers/staging/et131x/et1310_pm.h b/drivers/staging/et131x/et1310_pm.h
deleted file mode 100644
index 295f3ab..0000000
--- a/drivers/staging/et131x/et1310_pm.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *   http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et1310_pm.h - Defines, structs, enums, prototypes, etc. pertaining to power
- *               management.
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software.  Using this
- * software indicates your acceptance of these terms and conditions.  If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following Disclaimer as comments in the code as
- *    well as in the documentation and/or other materials provided with the
- *    distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following Disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef _ET1310_PM_H_
-#define _ET1310_PM_H_
-
-#include "et1310_address_map.h"
-
-typedef struct _MP_POWER_MGMT {
-	/* variable putting the phy into coma mode when boot up with no cable
-	 * plugged in after 5 seconds
-	 */
-	u8 TransPhyComaModeOnBoot;
-
-	/* Next two used to save power information at power down. This
-	 * information will be used during power up to set up parts of Power
-	 * Management in JAGCore
-	 */
-	u16 PowerDownSpeed;
-	u8 PowerDownDuplex;
-} MP_POWER_MGMT, *PMP_POWER_MGMT;
-
-/* Forward declaration of the private adapter structure
- */
-struct et131x_adapter;
-
-void EnablePhyComa(struct et131x_adapter *adapter);
-void DisablePhyComa(struct et131x_adapter *adapter);
-
-#endif /* _ET1310_PM_H_ */
diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c
index 81c1a74..54686e2 100644
--- a/drivers/staging/et131x/et1310_rx.c
+++ b/drivers/staging/et131x/et1310_rx.c
@@ -84,14 +84,9 @@
 #include <linux/ioport.h>
 
 #include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-
 #include "et131x_adapter.h"
-#include "et131x_initpci.h"
-
 #include "et1310_rx.h"
-
+#include "et131x.h"
 
 void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD pMpRfd);
 
@@ -109,17 +104,16 @@
 	u32 i, j;
 	u32 bufsize;
 	u32 pktStatRingSize, FBRChunkSize;
-	RX_RING_t *rx_ring;
+	struct rx_ring *rx_ring;
 
 	/* Setup some convenience pointers */
-	rx_ring = (RX_RING_t *) &adapter->RxRing;
+	rx_ring = &adapter->rx_ring;
 
 	/* Alloc memory for the lookup table */
 #ifdef USE_FBR0
-	rx_ring->Fbr[0] = kmalloc(sizeof(FBRLOOKUPTABLE), GFP_KERNEL);
+	rx_ring->fbr[0] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
 #endif
-
-	rx_ring->Fbr[1] = kmalloc(sizeof(FBRLOOKUPTABLE), GFP_KERNEL);
+	rx_ring->fbr[1] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
 
 	/* The first thing we will do is configure the sizes of the buffer
 	 * rings. These will change based on jumbo packet support.  Larger
@@ -163,14 +157,14 @@
 	}
 
 #ifdef USE_FBR0
-	adapter->RxRing.PsrNumEntries = adapter->RxRing.Fbr0NumEntries +
-	    adapter->RxRing.Fbr1NumEntries;
+	adapter->rx_ring.PsrNumEntries = adapter->rx_ring.Fbr0NumEntries +
+	    adapter->rx_ring.Fbr1NumEntries;
 #else
-	adapter->RxRing.PsrNumEntries = adapter->RxRing.Fbr1NumEntries;
+	adapter->rx_ring.PsrNumEntries = adapter->rx_ring.Fbr1NumEntries;
 #endif
 
 	/* Allocate an area of memory for Free Buffer Ring 1 */
-	bufsize = (sizeof(FBR_DESC_t) * rx_ring->Fbr1NumEntries) + 0xfff;
+	bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr1NumEntries) + 0xfff;
 	rx_ring->pFbr1RingVa = pci_alloc_consistent(adapter->pdev,
 						    bufsize,
 						    &rx_ring->pFbr1RingPa);
@@ -194,12 +188,12 @@
 				      &rx_ring->Fbr1Realpa,
 				      &rx_ring->Fbr1offset, 0x0FFF);
 
-	rx_ring->pFbr1RingVa = (void *)((uint8_t *) rx_ring->pFbr1RingVa +
+	rx_ring->pFbr1RingVa = (void *)((u8 *) rx_ring->pFbr1RingVa +
 					rx_ring->Fbr1offset);
 
 #ifdef USE_FBR0
 	/* Allocate an area of memory for Free Buffer Ring 0 */
-	bufsize = (sizeof(FBR_DESC_t) * rx_ring->Fbr0NumEntries) + 0xfff;
+	bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr0NumEntries) + 0xfff;
 	rx_ring->pFbr0RingVa = pci_alloc_consistent(adapter->pdev,
 						    bufsize,
 						    &rx_ring->pFbr0RingPa);
@@ -223,7 +217,7 @@
 				      &rx_ring->Fbr0Realpa,
 				      &rx_ring->Fbr0offset, 0x0FFF);
 
-	rx_ring->pFbr0RingVa = (void *)((uint8_t *) rx_ring->pFbr0RingVa +
+	rx_ring->pFbr0RingVa = (void *)((u8 *) rx_ring->pFbr0RingVa +
 					rx_ring->Fbr0offset);
 #endif
 
@@ -270,23 +264,23 @@
 			/* Save the Virtual address of this index for quick
 			 * access later
 			 */
-			rx_ring->Fbr[1]->Va[index] =
-			    (uint8_t *) rx_ring->Fbr1MemVa[i] +
+			rx_ring->fbr[1]->virt[index] =
+			    (u8 *) rx_ring->Fbr1MemVa[i] +
 			    (j * rx_ring->Fbr1BufferSize) + Fbr1Offset;
 
 			/* now store the physical address in the descriptor
 			 * so the device can access it
 			 */
-			rx_ring->Fbr[1]->PAHigh[index] =
+			rx_ring->fbr[1]->bus_high[index] =
 			    (u32) (Fbr1TempPa >> 32);
-			rx_ring->Fbr[1]->PALow[index] = (u32) Fbr1TempPa;
+			rx_ring->fbr[1]->bus_low[index] = (u32) Fbr1TempPa;
 
 			Fbr1TempPa += rx_ring->Fbr1BufferSize;
 
-			rx_ring->Fbr[1]->Buffer1[index] =
-			    rx_ring->Fbr[1]->Va[index];
-			rx_ring->Fbr[1]->Buffer2[index] =
-			    rx_ring->Fbr[1]->Va[index] - 4;
+			rx_ring->fbr[1]->buffer1[index] =
+			    rx_ring->fbr[1]->virt[index];
+			rx_ring->fbr[1]->buffer2[index] =
+			    rx_ring->fbr[1]->virt[index] - 4;
 		}
 	}
 
@@ -319,27 +313,27 @@
 		for (j = 0; j < FBR_CHUNKS; j++) {
 			u32 index = (i * FBR_CHUNKS) + j;
 
-			rx_ring->Fbr[0]->Va[index] =
-			    (uint8_t *) rx_ring->Fbr0MemVa[i] +
+			rx_ring->fbr[0]->virt[index] =
+			    (u8 *) rx_ring->Fbr0MemVa[i] +
 			    (j * rx_ring->Fbr0BufferSize) + Fbr0Offset;
 
-			rx_ring->Fbr[0]->PAHigh[index] =
+			rx_ring->fbr[0]->bus_high[index] =
 			    (u32) (Fbr0TempPa >> 32);
-			rx_ring->Fbr[0]->PALow[index] = (u32) Fbr0TempPa;
+			rx_ring->fbr[0]->bus_low[index] = (u32) Fbr0TempPa;
 
 			Fbr0TempPa += rx_ring->Fbr0BufferSize;
 
-			rx_ring->Fbr[0]->Buffer1[index] =
-			    rx_ring->Fbr[0]->Va[index];
-			rx_ring->Fbr[0]->Buffer2[index] =
-			    rx_ring->Fbr[0]->Va[index] - 4;
+			rx_ring->fbr[0]->buffer1[index] =
+			    rx_ring->fbr[0]->virt[index];
+			rx_ring->fbr[0]->buffer2[index] =
+			    rx_ring->fbr[0]->virt[index] - 4;
 		}
 	}
 #endif
 
 	/* Allocate an area of memory for FIFO of Packet Status ring entries */
 	pktStatRingSize =
-	    sizeof(PKT_STAT_DESC_t) * adapter->RxRing.PsrNumEntries;
+	    sizeof(struct pkt_stat_desc) * adapter->rx_ring.PsrNumEntries;
 
 	rx_ring->pPSRingVa = pci_alloc_consistent(adapter->pdev,
 						  pktStatRingSize,
@@ -360,16 +354,16 @@
 	 */
 
 	/* Allocate an area of memory for writeback of status information */
-	rx_ring->pRxStatusVa = pci_alloc_consistent(adapter->pdev,
-						    sizeof(RX_STATUS_BLOCK_t),
-						    &rx_ring->pRxStatusPa);
-	if (!rx_ring->pRxStatusVa) {
+	rx_ring->rx_status_block = pci_alloc_consistent(adapter->pdev,
+					    sizeof(struct rx_status_block),
+					    &rx_ring->rx_status_bus);
+	if (!rx_ring->rx_status_block) {
 		dev_err(&adapter->pdev->dev,
 			  "Cannot alloc memory for Status Block\n");
 		return -ENOMEM;
 	}
 	rx_ring->NumRfd = NIC_DEFAULT_NUM_RFD;
-	printk("PRS %lx\n", (unsigned long)rx_ring->pRxStatusPa);
+	printk("PRS %lx\n", (unsigned long)rx_ring->rx_status_bus);
 
 	/* Recv
 	 * pci_pool_create initializes a lookaside list. After successful
@@ -403,10 +397,10 @@
 	u32 bufsize;
 	u32 pktStatRingSize;
 	PMP_RFD rfd;
-	RX_RING_t *rx_ring;
+	struct rx_ring *rx_ring;
 
 	/* Setup some convenience pointers */
-	rx_ring = (RX_RING_t *) &adapter->RxRing;
+	rx_ring = &adapter->rx_ring;
 
 	/* Free RFDs and associated packet descriptors */
 	WARN_ON(rx_ring->nReadyRecv != rx_ring->NumRfd);
@@ -417,7 +411,7 @@
 
 		list_del(&rfd->list_node);
 		rfd->Packet = NULL;
-		kmem_cache_free(adapter->RxRing.RecvLookaside, rfd);
+		kmem_cache_free(adapter->rx_ring.RecvLookaside, rfd);
 	}
 
 	/* Free Free Buffer Ring 1 */
@@ -447,15 +441,14 @@
 		}
 
 		/* Now the FIFO itself */
-		rx_ring->pFbr1RingVa = (void *)((uint8_t *)
+		rx_ring->pFbr1RingVa = (void *)((u8 *)
 				rx_ring->pFbr1RingVa - rx_ring->Fbr1offset);
 
-		bufsize =
-		    (sizeof(FBR_DESC_t) * rx_ring->Fbr1NumEntries) + 0xfff;
+		bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr1NumEntries)
+	                                                        + 0xfff;
 
-		pci_free_consistent(adapter->pdev,
-				    bufsize,
-				    rx_ring->pFbr1RingVa, rx_ring->pFbr1RingPa);
+		pci_free_consistent(adapter->pdev, bufsize,
+                                rx_ring->pFbr1RingVa, rx_ring->pFbr1RingPa);
 
 		rx_ring->pFbr1RingVa = NULL;
 	}
@@ -481,11 +474,11 @@
 		}
 
 		/* Now the FIFO itself */
-		rx_ring->pFbr0RingVa = (void *)((uint8_t *)
+		rx_ring->pFbr0RingVa = (void *)((u8 *)
 				rx_ring->pFbr0RingVa - rx_ring->Fbr0offset);
 
-		bufsize =
-		    (sizeof(FBR_DESC_t) * rx_ring->Fbr0NumEntries) + 0xfff;
+		bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr0NumEntries)
+                                                                + 0xfff;
 
 		pci_free_consistent(adapter->pdev,
 				    bufsize,
@@ -498,7 +491,7 @@
 	/* Free Packet Status Ring */
 	if (rx_ring->pPSRingVa) {
 		pktStatRingSize =
-		    sizeof(PKT_STAT_DESC_t) * adapter->RxRing.PsrNumEntries;
+		    sizeof(struct pkt_stat_desc) * adapter->rx_ring.PsrNumEntries;
 
 		pci_free_consistent(adapter->pdev, pktStatRingSize,
 				    rx_ring->pPSRingVa, rx_ring->pPSRingPa);
@@ -507,12 +500,11 @@
 	}
 
 	/* Free area of memory for the writeback of status information */
-	if (rx_ring->pRxStatusVa) {
+	if (rx_ring->rx_status_block) {
 		pci_free_consistent(adapter->pdev,
-				sizeof(RX_STATUS_BLOCK_t),
-				rx_ring->pRxStatusVa, rx_ring->pRxStatusPa);
-
-		rx_ring->pRxStatusVa = NULL;
+			sizeof(struct rx_status_block),
+			rx_ring->rx_status_block, rx_ring->rx_status_bus);
+        	rx_ring->rx_status_block = NULL;
 	}
 
 	/* Free receive buffer pool */
@@ -527,10 +519,10 @@
 
 	/* Free the FBR Lookup Table */
 #ifdef USE_FBR0
-	kfree(rx_ring->Fbr[0]);
+	kfree(rx_ring->fbr[0]);
 #endif
 
-	kfree(rx_ring->Fbr[1]);
+	kfree(rx_ring->fbr[1]);
 
 	/* Reset Counters */
 	rx_ring->nReadyRecv = 0;
@@ -548,10 +540,10 @@
 	PMP_RFD rfd = NULL;
 	u32 rfdct;
 	u32 numrfd = 0;
-	RX_RING_t *rx_ring = NULL;
+	struct rx_ring *rx_ring;
 
 	/* Setup some convenience pointers */
-	rx_ring = (RX_RING_t *) &adapter->RxRing;
+	rx_ring = &adapter->rx_ring;
 
 	/* Setup each RFD */
 	for (rfdct = 0; rfdct < rx_ring->NumRfd; rfdct++) {
@@ -594,9 +586,9 @@
  */
 void ConfigRxDmaRegs(struct et131x_adapter *etdev)
 {
-	struct _RXDMA_t __iomem *rx_dma = &etdev->regs->rxdma;
-	struct _rx_ring_t *rx_local = &etdev->RxRing;
-	PFBR_DESC_t fbr_entry;
+	struct rxdma_regs __iomem *rx_dma = &etdev->regs->rxdma;
+	struct rx_ring *rx_local = &etdev->rx_ring;
+	struct fbr_desc *fbr_entry;
 	u32 entry;
 	u32 psr_num_des;
 	unsigned long flags;
@@ -611,11 +603,11 @@
 	 * are ever returned, make sure the high part is retrieved here
 	 * before storing the adjusted address.
 	 */
-	writel((u32) ((u64)rx_local->pRxStatusPa >> 32),
+	writel((u32) ((u64)rx_local->rx_status_bus >> 32),
 	       &rx_dma->dma_wb_base_hi);
-	writel((u32) rx_local->pRxStatusPa, &rx_dma->dma_wb_base_lo);
+	writel((u32) rx_local->rx_status_bus, &rx_dma->dma_wb_base_lo);
 
-	memset(rx_local->pRxStatusVa, 0, sizeof(RX_STATUS_BLOCK_t));
+	memset(rx_local->rx_status_block, 0, sizeof(struct rx_status_block));
 
 	/* Set the address and parameters of the packet status ring into the
 	 * 1310's registers
@@ -636,11 +628,11 @@
 	rx_local->local_psr_full = 0;
 
 	/* Now's the best time to initialize FBR1 contents */
-	fbr_entry = (PFBR_DESC_t) rx_local->pFbr1RingVa;
+	fbr_entry = (struct fbr_desc *) rx_local->pFbr1RingVa;
 	for (entry = 0; entry < rx_local->Fbr1NumEntries; entry++) {
-		fbr_entry->addr_hi = rx_local->Fbr[1]->PAHigh[entry];
-		fbr_entry->addr_lo = rx_local->Fbr[1]->PALow[entry];
-		fbr_entry->word2.bits.bi = entry;
+		fbr_entry->addr_hi = rx_local->fbr[1]->bus_high[entry];
+		fbr_entry->addr_lo = rx_local->fbr[1]->bus_low[entry];
+		fbr_entry->word2 = entry;
 		fbr_entry++;
 	}
 
@@ -661,11 +653,11 @@
 
 #ifdef USE_FBR0
 	/* Now's the best time to initialize FBR0 contents */
-	fbr_entry = (PFBR_DESC_t) rx_local->pFbr0RingVa;
+	fbr_entry = (struct fbr_desc *) rx_local->pFbr0RingVa;
 	for (entry = 0; entry < rx_local->Fbr0NumEntries; entry++) {
-		fbr_entry->addr_hi = rx_local->Fbr[0]->PAHigh[entry];
-		fbr_entry->addr_lo = rx_local->Fbr[0]->PALow[entry];
-		fbr_entry->word2.bits.bi = entry;
+		fbr_entry->addr_hi = rx_local->fbr[0]->bus_high[entry];
+		fbr_entry->addr_lo = rx_local->fbr[0]->bus_low[entry];
+		fbr_entry->word2 = entry;
 		fbr_entry++;
 	}
 
@@ -721,18 +713,17 @@
  */
 void et131x_rx_dma_disable(struct et131x_adapter *etdev)
 {
-	RXDMA_CSR_t csr;
-
+        u32 csr;
 	/* Setup the receive dma configuration register */
-	writel(0x00002001, &etdev->regs->rxdma.csr.value);
-	csr.value = readl(&etdev->regs->rxdma.csr.value);
-	if (csr.bits.halt_status != 1) {
+	writel(0x00002001, &etdev->regs->rxdma.csr);
+	csr = readl(&etdev->regs->rxdma.csr);
+	if ((csr & 0x00020000) != 1) {	/* Check halt status (bit 17) */
 		udelay(5);
-		csr.value = readl(&etdev->regs->rxdma.csr.value);
-		if (csr.bits.halt_status != 1)
+		csr = readl(&etdev->regs->rxdma.csr);
+		if ((csr & 0x00020000) != 1)
 			dev_err(&etdev->pdev->dev,
-				"RX Dma failed to enter halt state. CSR 0x%08x\n",
-				csr.value);
+			"RX Dma failed to enter halt state. CSR 0x%08x\n",
+				csr);
 	}
 }
 
@@ -743,34 +734,33 @@
 void et131x_rx_dma_enable(struct et131x_adapter *etdev)
 {
 	/* Setup the receive dma configuration register for normal operation */
-	RXDMA_CSR_t csr = { 0 };
+	u32 csr =  0x2000;	/* FBR1 enable */
 
-	csr.bits.fbr1_enable = 1;
-	if (etdev->RxRing.Fbr1BufferSize == 4096)
-		csr.bits.fbr1_size = 1;
-	else if (etdev->RxRing.Fbr1BufferSize == 8192)
-		csr.bits.fbr1_size = 2;
-	else if (etdev->RxRing.Fbr1BufferSize == 16384)
-		csr.bits.fbr1_size = 3;
+	if (etdev->rx_ring.Fbr1BufferSize == 4096)
+		csr |= 0x0800;
+	else if (etdev->rx_ring.Fbr1BufferSize == 8192)
+		csr |= 0x1000;
+	else if (etdev->rx_ring.Fbr1BufferSize == 16384)
+		csr |= 0x1800;
 #ifdef USE_FBR0
-	csr.bits.fbr0_enable = 1;
-	if (etdev->RxRing.Fbr0BufferSize == 256)
-		csr.bits.fbr0_size = 1;
-	else if (etdev->RxRing.Fbr0BufferSize == 512)
-		csr.bits.fbr0_size = 2;
-	else if (etdev->RxRing.Fbr0BufferSize == 1024)
-		csr.bits.fbr0_size = 3;
+        csr |= 0x0400;		/* FBR0 enable */
+	if (etdev->rx_ring.Fbr0BufferSize == 256)
+	        csr |= 0x0100;
+	else if (etdev->rx_ring.Fbr0BufferSize == 512)
+		csr |= 0x0200;
+	else if (etdev->rx_ring.Fbr0BufferSize == 1024)
+		csr |= 0x0300;
 #endif
-	writel(csr.value, &etdev->regs->rxdma.csr.value);
+	writel(csr, &etdev->regs->rxdma.csr);
 
-	csr.value = readl(&etdev->regs->rxdma.csr.value);
-	if (csr.bits.halt_status != 0) {
+	csr = readl(&etdev->regs->rxdma.csr);
+	if ((csr & 0x00020000) != 0) {
 		udelay(5);
-		csr.value = readl(&etdev->regs->rxdma.csr.value);
-		if (csr.bits.halt_status != 0) {
+		csr = readl(&etdev->regs->rxdma.csr);
+        	if ((csr & 0x00020000) != 0) {
 			dev_err(&etdev->pdev->dev,
 			    "RX Dma failed to exit halt state.  CSR 0x%08x\n",
-				csr.value);
+				csr);
 		}
 	}
 }
@@ -788,46 +778,44 @@
  */
 PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
 {
-	struct _rx_ring_t *rx_local = &etdev->RxRing;
-	PRX_STATUS_BLOCK_t status;
-	PPKT_STAT_DESC_t psr;
+	struct rx_ring *rx_local = &etdev->rx_ring;
+	struct rx_status_block *status;
+	struct pkt_stat_desc *psr;
 	PMP_RFD rfd;
 	u32 i;
-	uint8_t *buf;
+	u8 *buf;
 	unsigned long flags;
 	struct list_head *element;
-	uint8_t rindex;
-	uint16_t bindex;
+	u8 rindex;
+	u16 bindex;
 	u32 len;
-	PKT_STAT_DESC_WORD0_t Word0;
+	u32 word0;
+	u32 word1;
 
 	/* RX Status block is written by the DMA engine prior to every
 	 * interrupt. It contains the next to be used entry in the Packet
 	 * Status Ring, and also the two Free Buffer rings.
 	 */
-	status = (PRX_STATUS_BLOCK_t) rx_local->pRxStatusVa;
+	status = rx_local->rx_status_block;
+	word1 = status->Word1 >> 16;	/* Get the useful bits */
 
-	/* FIXME: tidy later when conversions complete */
-	if (status->Word1.bits.PSRoffset ==
-			(rx_local->local_psr_full & 0xFFF) &&
-			status->Word1.bits.PSRwrap ==
-			((rx_local->local_psr_full >> 12) & 1)) {
+	/* Check the PSR and wrap bits do not match */
+	if ((word1 & 0x1FFF) == (rx_local->local_psr_full & 0x1FFF))
 		/* Looks like this ring is not updated yet */
 		return NULL;
-	}
 
 	/* The packet status ring indicates that data is available. */
-	psr = (PPKT_STAT_DESC_t) (rx_local->pPSRingVa) +
+	psr = (struct pkt_stat_desc *) (rx_local->pPSRingVa) +
 			(rx_local->local_psr_full & 0xFFF);
 
 	/* Grab any information that is required once the PSR is
 	 * advanced, since we can no longer rely on the memory being
 	 * accurate
 	 */
-	len = psr->word1.bits.length;
-	rindex = (uint8_t) psr->word1.bits.ri;
-	bindex = (uint16_t) psr->word1.bits.bi;
-	Word0 = psr->word0;
+	len = psr->word1 & 0xFFFF;
+	rindex = (psr->word1 >> 26) & 0x03;
+	bindex = (psr->word1 >> 16) & 0x3FF;
+	word0 = psr->word0;
 
 	/* Indicate that we have used this PSR entry. */
 	/* FIXME wrap 12 */
@@ -842,9 +830,8 @@
 	       &etdev->regs->rxdma.psr_full_offset);
 
 #ifndef USE_FBR0
-	if (rindex != 1) {
+	if (rindex != 1)
 		return NULL;
-	}
 #endif
 
 #ifdef USE_FBR0
@@ -899,7 +886,7 @@
 
 	if (len) {
 		if (etdev->ReplicaPhyLoopbk == 1) {
-			buf = rx_local->Fbr[rindex]->Va[bindex];
+			buf = rx_local->fbr[rindex]->virt[bindex];
 
 			if (memcmp(&buf[6], &etdev->CurrentAddress[0],
 				   ETH_ALEN) == 0) {
@@ -911,8 +898,8 @@
 		}
 
 		/* Determine if this is a multicast packet coming in */
-		if ((Word0.value & ALCATEL_MULTICAST_PKT) &&
-		    !(Word0.value & ALCATEL_BROADCAST_PKT)) {
+		if ((word0 & ALCATEL_MULTICAST_PKT) &&
+		    !(word0 & ALCATEL_BROADCAST_PKT)) {
 			/* Promiscuous mode and Multicast mode are
 			 * not mutually exclusive as was first
 			 * thought.  I guess Promiscuous is just
@@ -923,8 +910,8 @@
 			if ((etdev->PacketFilter & ET131X_PACKET_TYPE_MULTICAST)
 			    && !(etdev->PacketFilter & ET131X_PACKET_TYPE_PROMISCUOUS)
 			    && !(etdev->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST)) {
-				buf = rx_local->Fbr[rindex]->
-						Va[bindex];
+				buf = rx_local->fbr[rindex]->
+						virt[bindex];
 
 				/* Loop through our list to see if the
 				 * destination address of this packet
@@ -963,7 +950,7 @@
 
 			if (len > 0)
 				etdev->Stats.multircv++;
-		} else if (Word0.value & ALCATEL_BROADCAST_PKT)
+		} else if (word0 & ALCATEL_BROADCAST_PKT)
 			etdev->Stats.brdcstrcv++;
 		else
 			/* Not sure what this counter measures in
@@ -990,7 +977,7 @@
 		etdev->net_stats.rx_bytes += rfd->PacketSize;
 
 		memcpy(skb_put(skb, rfd->PacketSize),
-		       rx_local->Fbr[rindex]->Va[bindex],
+		       rx_local->fbr[rindex]->virt[bindex],
 		       rfd->PacketSize);
 
 		skb->dev = etdev->netdev;
@@ -1014,7 +1001,7 @@
  */
 void et131x_reset_recv(struct et131x_adapter *etdev)
 {
-	WARN_ON(list_empty(&etdev->RxRing.RecvList));
+	WARN_ON(list_empty(&etdev->rx_ring.RecvList));
 
 }
 
@@ -1032,8 +1019,8 @@
 
 	/* Process up to available RFD's */
 	while (count < NUM_PACKETS_HANDLED) {
-		if (list_empty(&etdev->RxRing.RecvList)) {
-			WARN_ON(etdev->RxRing.nReadyRecv != 0);
+		if (list_empty(&etdev->rx_ring.RecvList)) {
+			WARN_ON(etdev->rx_ring.nReadyRecv != 0);
 			done = false;
 			break;
 		}
@@ -1058,7 +1045,7 @@
 		etdev->Stats.ipackets++;
 
 		/* Set the status on the packet, either resources or success */
-		if (etdev->RxRing.nReadyRecv < RFD_LOW_WATER_MARK) {
+		if (etdev->rx_ring.nReadyRecv < RFD_LOW_WATER_MARK) {
 			dev_warn(&etdev->pdev->dev,
 				    "RFD's are running out\n");
 		}
@@ -1066,12 +1053,12 @@
 	}
 
 	if (count == NUM_PACKETS_HANDLED || !done) {
-		etdev->RxRing.UnfinishedReceives = true;
+		etdev->rx_ring.UnfinishedReceives = true;
 		writel(PARM_TX_TIME_INT_DEF * NANO_IN_A_MICRO,
 		       &etdev->regs->global.watchdog_timer);
 	} else
 		/* Watchdog timer will disable itself if appropriate. */
-		etdev->RxRing.UnfinishedReceives = false;
+		etdev->rx_ring.UnfinishedReceives = false;
 }
 
 static inline u32 bump_fbr(u32 *fbr, u32 limit)
@@ -1099,10 +1086,10 @@
  */
 void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD rfd)
 {
-	struct _rx_ring_t *rx_local = &etdev->RxRing;
-	struct _RXDMA_t __iomem *rx_dma = &etdev->regs->rxdma;
-	uint16_t bi = rfd->bufferindex;
-	uint8_t ri = rfd->ringindex;
+	struct rx_ring *rx_local = &etdev->rx_ring;
+	struct rxdma_regs __iomem *rx_dma = &etdev->regs->rxdma;
+	u16 bi = rfd->bufferindex;
+	u8 ri = rfd->ringindex;
 	unsigned long flags;
 
 	/* We don't use any of the OOB data besides status. Otherwise, we
@@ -1116,17 +1103,17 @@
 		spin_lock_irqsave(&etdev->FbrLock, flags);
 
 		if (ri == 1) {
-			PFBR_DESC_t next =
-			    (PFBR_DESC_t) (rx_local->pFbr1RingVa) +
-			    INDEX10(rx_local->local_Fbr1_full);
+			struct fbr_desc *next =
+			    (struct fbr_desc *) (rx_local->pFbr1RingVa) +
+                		            INDEX10(rx_local->local_Fbr1_full);
 
 			/* Handle the Free Buffer Ring advancement here. Write
 			 * the PA / Buffer Index for the returned buffer into
 			 * the oldest (next to be freed)FBR entry
 			 */
-			next->addr_hi = rx_local->Fbr[1]->PAHigh[bi];
-			next->addr_lo = rx_local->Fbr[1]->PALow[bi];
-			next->word2.value = bi;
+			next->addr_hi = rx_local->fbr[1]->bus_high[bi];
+			next->addr_lo = rx_local->fbr[1]->bus_low[bi];
+			next->word2 = bi;
 
 			writel(bump_fbr(&rx_local->local_Fbr1_full,
 				rx_local->Fbr1NumEntries - 1),
@@ -1134,17 +1121,17 @@
 		}
 #ifdef USE_FBR0
 		else {
-			PFBR_DESC_t next =
-			    (PFBR_DESC_t) rx_local->pFbr0RingVa +
-			    INDEX10(rx_local->local_Fbr0_full);
+			struct fbr_desc *next = (struct fbr_desc *)
+				rx_local->pFbr0RingVa +
+					INDEX10(rx_local->local_Fbr0_full);
 
 			/* Handle the Free Buffer Ring advancement here. Write
 			 * the PA / Buffer Index for the returned buffer into
 			 * the oldest (next to be freed) FBR entry
 			 */
-			next->addr_hi = rx_local->Fbr[0]->PAHigh[bi];
-			next->addr_lo = rx_local->Fbr[0]->PALow[bi];
-			next->word2.value = bi;
+			next->addr_hi = rx_local->fbr[0]->bus_high[bi];
+			next->addr_lo = rx_local->fbr[0]->bus_low[bi];
+			next->word2 = bi;
 
 			writel(bump_fbr(&rx_local->local_Fbr0_full,
 					rx_local->Fbr0NumEntries - 1),
diff --git a/drivers/staging/et131x/et1310_rx.h b/drivers/staging/et131x/et1310_rx.h
index 6951459..ca84a91 100644
--- a/drivers/staging/et131x/et1310_rx.h
+++ b/drivers/staging/et131x/et1310_rx.h
@@ -91,120 +91,60 @@
 #define ALCATEL_BROADCAST_PKT	0x02000000
 
 /* typedefs for Free Buffer Descriptors */
-typedef union _FBR_WORD2_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 reserved:22;	/* bits 10-31 */
-		u32 bi:10;		/* bits 0-9(Buffer Index) */
-#else
-		u32 bi:10;		/* bits 0-9(Buffer Index) */
-		u32 reserved:22;	/* bit 10-31 */
-#endif
-	} bits;
-} FBR_WORD2_t, *PFBR_WORD2_t;
-
-typedef struct _FBR_DESC_t {
+struct fbr_desc
+{
 	u32 addr_lo;
 	u32 addr_hi;
-	FBR_WORD2_t word2;
-} FBR_DESC_t, *PFBR_DESC_t;
+	u32 word2;		/* Bits 10-31 reserved, 0-9 descriptor */
+};
 
-/* Typedefs for Packet Status Ring Descriptors */
-typedef union _PKT_STAT_DESC_WORD0_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		/* top 16 bits are from the Alcatel Status Word as enumerated in */
-		/* PE-MCXMAC Data Sheet IPD DS54 0210-1 (also IPD-DS80 0205-2) */
-#if 0
-		u32 asw_trunc:1;		/* bit 31(Rx frame truncated) */
-#endif
-		u32 asw_long_evt:1;	/* bit 31(Rx long event) */
-		u32 asw_VLAN_tag:1;	/* bit 30(VLAN tag detected) */
-		u32 asw_unsupported_op:1;	/* bit 29(unsupported OP code) */
-		u32 asw_pause_frame:1;	/* bit 28(is a pause frame) */
-		u32 asw_control_frame:1;	/* bit 27(is a control frame) */
-		u32 asw_dribble_nibble:1;	/* bit 26(spurious bits after EOP) */
-		u32 asw_broadcast:1;	/* bit 25(has a broadcast address) */
-		u32 asw_multicast:1;	/* bit 24(has a multicast address) */
-		u32 asw_OK:1;		/* bit 23(valid CRC + no code error) */
-		u32 asw_too_long:1;	/* bit 22(frame length > 1518 bytes) */
-		u32 asw_len_chk_err:1;	/* bit 21(frame length field incorrect) */
-		u32 asw_CRC_err:1;		/* bit 20(CRC error) */
-		u32 asw_code_err:1;	/* bit 19(one or more nibbles signalled as errors) */
-		u32 asw_false_carrier_event:1;	/* bit 18(bad carrier since last good packet) */
-		u32 asw_RX_DV_event:1;	/* bit 17(short receive event detected) */
-		u32 asw_prev_pkt_dropped:1;/* bit 16(e.g. IFG too small on previous) */
-		u32 unused:5;		/* bits 11-15 */
-		u32 vp:1;			/* bit 10(VLAN Packet) */
-		u32 jp:1;			/* bit 9(Jumbo Packet) */
-		u32 ft:1;			/* bit 8(Frame Truncated) */
-		u32 drop:1;		/* bit 7(Drop packet) */
-		u32 rxmac_error:1;		/* bit 6(RXMAC Error Indicator) */
-		u32 wol:1;			/* bit 5(WOL Event) */
-		u32 tcpp:1;		/* bit 4(TCP checksum pass) */
-		u32 tcpa:1;		/* bit 3(TCP checksum assist) */
-		u32 ipp:1;			/* bit 2(IP checksum pass) */
-		u32 ipa:1;			/* bit 1(IP checksum assist) */
-		u32 hp:1;			/* bit 0(hash pass) */
-#else
-		u32 hp:1;			/* bit 0(hash pass) */
-		u32 ipa:1;			/* bit 1(IP checksum assist) */
-		u32 ipp:1;			/* bit 2(IP checksum pass) */
-		u32 tcpa:1;		/* bit 3(TCP checksum assist) */
-		u32 tcpp:1;		/* bit 4(TCP checksum pass) */
-		u32 wol:1;			/* bit 5(WOL Event) */
-		u32 rxmac_error:1;		/* bit 6(RXMAC Error Indicator) */
-		u32 drop:1;		/* bit 7(Drop packet) */
-		u32 ft:1;			/* bit 8(Frame Truncated) */
-		u32 jp:1;			/* bit 9(Jumbo Packet) */
-		u32 vp:1;			/* bit 10(VLAN Packet) */
-		u32 unused:5;		/* bits 11-15 */
-		u32 asw_prev_pkt_dropped:1;/* bit 16(e.g. IFG too small on previous) */
-		u32 asw_RX_DV_event:1;	/* bit 17(short receive event detected) */
-		u32 asw_false_carrier_event:1;	/* bit 18(bad carrier since last good packet) */
-		u32 asw_code_err:1;	/* bit 19(one or more nibbles signalled as errors) */
-		u32 asw_CRC_err:1;		/* bit 20(CRC error) */
-		u32 asw_len_chk_err:1;	/* bit 21(frame length field incorrect) */
-		u32 asw_too_long:1;	/* bit 22(frame length > 1518 bytes) */
-		u32 asw_OK:1;		/* bit 23(valid CRC + no code error) */
-		u32 asw_multicast:1;	/* bit 24(has a multicast address) */
-		u32 asw_broadcast:1;	/* bit 25(has a broadcast address) */
-		u32 asw_dribble_nibble:1;	/* bit 26(spurious bits after EOP) */
-		u32 asw_control_frame:1;	/* bit 27(is a control frame) */
-		u32 asw_pause_frame:1;	/* bit 28(is a pause frame) */
-		u32 asw_unsupported_op:1;	/* bit 29(unsupported OP code) */
-		u32 asw_VLAN_tag:1;	/* bit 30(VLAN tag detected) */
-		u32 asw_long_evt:1;	/* bit 31(Rx long event) */
-#if 0
-		u32 asw_trunc:1;		/* bit 31(Rx frame truncated) */
-#endif
-#endif
-	} bits;
-} PKT_STAT_DESC_WORD0_t, *PPKT_STAT_WORD0_t;
+/* Packet Status Ring Descriptors
+ *
+ * Word 0:
+ *
+ * top 16 bits are from the Alcatel Status Word as enumerated in
+ * PE-MCXMAC Data Sheet IPD DS54 0210-1 (also IPD-DS80 0205-2)
+ *
+ * 0: hp			hash pass
+ * 1: ipa			IP checksum assist
+ * 2: ipp			IP checksum pass
+ * 3: tcpa			TCP checksum assist
+ * 4: tcpp			TCP checksum pass
+ * 5: wol			WOL Event
+ * 6: rxmac_error		RXMAC Error Indicator
+ * 7: drop			Drop packet
+ * 8: ft			Frame Truncated
+ * 9: jp			Jumbo Packet
+ * 10: vp			VLAN Packet
+ * 11-15: unused
+ * 16: asw_prev_pkt_dropped 	e.g. IFG too small on previous
+ * 17: asw_RX_DV_event		short receive event detected
+ * 18: asw_false_carrier_event	bad carrier since last good packet
+ * 19: asw_code_err		one or more nibbles signalled as errors
+ * 20: asw_CRC_err		CRC error
+ * 21: asw_len_chk_err		frame length field incorrect
+ * 22: asw_too_long		frame length > 1518 bytes
+ * 23: asw_OK			valid CRC + no code error
+ * 24: asw_multicast		has a multicast address
+ * 25: asw_broadcast		has a broadcast address
+ * 26: asw_dribble_nibble	spurious bits after EOP
+ * 27: asw_control_frame	is a control frame
+ * 28: asw_pause_frame		is a pause frame
+ * 29: asw_unsupported_op	unsupported OP code
+ * 30: asw_VLAN_tag		VLAN tag detected
+ * 31: asw_long_evt		Rx long event
+ *
+ * Word 1:
+ * 0-15: length			length in bytes
+ * 16-25: bi			Buffer Index
+ * 26-27: ri			Ring Index
+ * 28-31: reserved
+ */
 
-typedef union _PKT_STAT_DESC_WORD1_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 unused:4;	/* bits 28-31 */
-		u32 ri:2;		/* bits 26-27(Ring Index) */
-		u32 bi:10;		/* bits 16-25(Buffer Index) */
-		u32 length:16;	/* bit 0-15(length in bytes) */
-#else
-		u32 length:16;	/* bit 0-15(length in bytes) */
-		u32 bi:10;		/* bits 16-25(Buffer Index) */
-		u32 ri:2;		/* bits 26-27(Ring Index) */
-		u32 unused:4;	/* bits 28-31 */
-#endif
-	} bits;
-} PKT_STAT_DESC_WORD1_t, *PPKT_STAT_WORD1_t;
-
-typedef struct _PKT_STAT_DESC_t {
-	PKT_STAT_DESC_WORD0_t word0;
-	PKT_STAT_DESC_WORD1_t word1;
-} PKT_STAT_DESC_t, *PPKT_STAT_DESC_t;
+struct pkt_stat_desc {
+	u32 word0;
+	u32 word1;
+};
 
 /* Typedefs for the RX DMA status word */
 
@@ -223,59 +163,38 @@
  * RXSTAT_WORD1_t structure holds part of the status bits of the Rx DMA engine
  * that get copied out to memory by the ET-1310.  Word 3 is a 32 bit word
  * which contains the Packet Status Ring available offset.
+ *
+ * bit 0-15 reserved
+ * bit 16-27 PSRoffset
+ * bit 28 PSRwrap
+ * bit 29-31 unused
  */
 
-#define RXSTAT1_OFFSET	16
-#define RXSTAT1_MASK	0xFFF
-#define RXSTAT1_WRAP	0x10000000
-
-typedef union _rxstat_word1_t {
-	u32 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u32 PSRunused:3;	/* bits 29-31 */
-		u32 PSRwrap:1;	/* bit 28 */
-		u32 PSRoffset:12;	/* bits 16-27 */
-		u32 reserved:16;	/* bits 0-15 */
-#else
-		u32 reserved:16;	/* bits 0-15 */
-		u32 PSRoffset:12;	/* bits 16-27 */
-		u32 PSRwrap:1;	/* bit 28 */
-		u32 PSRunused:3;	/* bits 29-31 */
-#endif
-	} bits;
-} RXSTAT_WORD1_t, *PRXSTAT_WORD1_t;
-
 /*
- * RX_STATUS_BLOCK_t is sructure representing the status of the Rx DMA engine
- * it sits in free memory, and is pointed to by 0x101c / 0x1020
+ * struct rx_status_block is a structure representing the status of the Rx
+ * DMA engine it sits in free memory, and is pointed to by 0x101c / 0x1020
  */
-typedef struct _rx_status_block_t {
+struct rx_status_block {
 	u32 Word0;
-	RXSTAT_WORD1_t Word1;
-} RX_STATUS_BLOCK_t, *PRX_STATUS_BLOCK_t;
+	u32 Word1;
+};
 
 /*
  * Structure for look-up table holding free buffer ring pointers
  */
-typedef struct _FbrLookupTable {
-	void *Va[MAX_DESC_PER_RING_RX];
-	void *Buffer1[MAX_DESC_PER_RING_RX];
-	void *Buffer2[MAX_DESC_PER_RING_RX];
-	u32 PAHigh[MAX_DESC_PER_RING_RX];
-	u32 PALow[MAX_DESC_PER_RING_RX];
-} FBRLOOKUPTABLE, *PFBRLOOKUPTABLE;
-
-typedef enum {
-	ONE_PACKET_INTERRUPT,
-	FOUR_PACKET_INTERRUPT
-} eRX_INTERRUPT_STATE_t, *PeRX_INTERRUPT_STATE_t;
+struct fbr_lookup {
+	void *virt[MAX_DESC_PER_RING_RX];
+	void *buffer1[MAX_DESC_PER_RING_RX];
+	void *buffer2[MAX_DESC_PER_RING_RX];
+	u32 bus_high[MAX_DESC_PER_RING_RX];
+	u32 bus_low[MAX_DESC_PER_RING_RX];
+};
 
 /*
- * RX_RING_t is sructure representing the adaptor's local reference(s) to the
- * rings
+ * struct rx_ring is the ssructure representing the adaptor's local
+ * reference(s) to the rings
  */
-typedef struct _rx_ring_t {
+struct rx_ring {
 #ifdef USE_FBR0
 	void *pFbr0RingVa;
 	dma_addr_t pFbr0RingPa;
@@ -293,7 +212,7 @@
 	dma_addr_t Fbr1MemPa[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
 	uint64_t Fbr1Realpa;
 	uint64_t Fbr1offset;
-	FBRLOOKUPTABLE *Fbr[2];
+	struct fbr_lookup *fbr[2];	/* One per ring */
 	u32 local_Fbr1_full;
 	u32 Fbr1NumEntries;
 	u32 Fbr1BufferSize;
@@ -303,8 +222,8 @@
 	u32 local_psr_full;
 	u32 PsrNumEntries;
 
-	void *pRxStatusVa;
-	dma_addr_t pRxStatusPa;
+	struct rx_status_block *rx_status_block;
+	dma_addr_t rx_status_bus;
 
 	struct list_head RecvBufferPool;
 
@@ -320,30 +239,6 @@
 
 	/* lookaside lists */
 	struct kmem_cache *RecvLookaside;
-} RX_RING_t, *PRX_RING_t;
-
-/* Forward reference of RFD */
-struct _MP_RFD;
-
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-/* PROTOTYPES for Initialization */
-int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter);
-void et131x_rx_dma_memory_free(struct et131x_adapter *adapter);
-int et131x_rfd_resources_alloc(struct et131x_adapter *adapter,
-			       struct _MP_RFD *pMpRfd);
-void et131x_rfd_resources_free(struct et131x_adapter *adapter,
-			       struct _MP_RFD *pMpRfd);
-int et131x_init_recv(struct et131x_adapter *adapter);
-
-void ConfigRxDmaRegs(struct et131x_adapter *adapter);
-void SetRxDmaTimer(struct et131x_adapter *adapter);
-void et131x_rx_dma_disable(struct et131x_adapter *adapter);
-void et131x_rx_dma_enable(struct et131x_adapter *adapter);
-
-void et131x_reset_recv(struct et131x_adapter *adapter);
-
-void et131x_handle_recv_interrupt(struct et131x_adapter *adapter);
+};
 
 #endif /* __ET1310_RX_H__ */
diff --git a/drivers/staging/et131x/et1310_tx.c b/drivers/staging/et131x/et1310_tx.c
index 977e8b3..b6ff20f 100644
--- a/drivers/staging/et131x/et1310_tx.c
+++ b/drivers/staging/et131x/et1310_tx.c
@@ -84,15 +84,9 @@
 #include <linux/ioport.h>
 
 #include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-
 #include "et131x_adapter.h"
-#include "et131x_initpci.h"
-#include "et131x_isr.h"
-
 #include "et1310_tx.h"
-
+#include "et131x.h"
 
 static inline void et131x_free_send_packet(struct et131x_adapter *etdev,
 					   struct tcb *tcb);
@@ -200,7 +194,7 @@
  */
 void ConfigTxDmaRegs(struct et131x_adapter *etdev)
 {
-	struct _TXDMA_t __iomem *txdma = &etdev->regs->txdma;
+	struct txdma_regs __iomem *txdma = &etdev->regs->txdma;
 
 	/* Load the hardware with the start of the transmit descriptor ring. */
 	writel((u32) ((u64)etdev->tx_ring.tx_desc_ring_pa >> 32),
diff --git a/drivers/staging/et131x/et1310_tx.h b/drivers/staging/et131x/et1310_tx.h
index 4f0ea81..82d06e9 100644
--- a/drivers/staging/et131x/et1310_tx.h
+++ b/drivers/staging/et131x/et1310_tx.h
@@ -147,18 +147,4 @@
 	int since_irq;
 };
 
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-/* PROTOTYPES for et1310_tx.c */
-int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter);
-void et131x_tx_dma_memory_free(struct et131x_adapter *adapter);
-void ConfigTxDmaRegs(struct et131x_adapter *adapter);
-void et131x_init_send(struct et131x_adapter *adapter);
-void et131x_tx_dma_disable(struct et131x_adapter *adapter);
-void et131x_tx_dma_enable(struct et131x_adapter *adapter);
-void et131x_handle_send_interrupt(struct et131x_adapter *adapter);
-void et131x_free_busy_send_packets(struct et131x_adapter *adapter);
-int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev);
-
 #endif /* __ET1310_TX_H__ */
diff --git a/drivers/staging/et131x/et131x.h b/drivers/staging/et131x/et131x.h
new file mode 100644
index 0000000..a8abfe6
--- /dev/null
+++ b/drivers/staging/et131x/et131x.h
@@ -0,0 +1,153 @@
+/*
+ * Merged from files
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *   http://www.agere.com
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software.  Using this
+ * software indicates your acceptance of these terms and conditions.  If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following Disclaimer as comments in the code as
+ *    well as in the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following Disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ */
+
+/* et131x_eeprom.c */
+int et131x_init_eeprom(struct et131x_adapter *etdev);
+
+/* et131x_initpci.c */
+void ConfigGlobalRegs(struct et131x_adapter *pAdapter);
+void ConfigMMCRegs(struct et131x_adapter *pAdapter);
+void et131x_enable_interrupts(struct et131x_adapter *adapter);
+void et131x_disable_interrupts(struct et131x_adapter *adapter);
+void et131x_align_allocated_memory(struct et131x_adapter *adapter,
+				   u64 *phys_addr,
+				   u64 *offset, u64 mask);
+
+int et131x_adapter_setup(struct et131x_adapter *adapter);
+int et131x_adapter_memory_alloc(struct et131x_adapter *adapter);
+void et131x_adapter_memory_free(struct et131x_adapter *adapter);
+void et131x_hwaddr_init(struct et131x_adapter *adapter);
+void et131x_soft_reset(struct et131x_adapter *adapter);
+
+/* et131x_isr.c */
+irqreturn_t et131x_isr(int irq, void *dev_id);
+void et131x_isr_handler(struct work_struct *work);
+
+/* et1310_mac.c */
+void ConfigMACRegs1(struct et131x_adapter *adapter);
+void ConfigMACRegs2(struct et131x_adapter *adapter);
+void ConfigRxMacRegs(struct et131x_adapter *adapter);
+void ConfigTxMacRegs(struct et131x_adapter *adapter);
+void ConfigMacStatRegs(struct et131x_adapter *adapter);
+void ConfigFlowControl(struct et131x_adapter *adapter);
+void UpdateMacStatHostCounters(struct et131x_adapter *adapter);
+void HandleMacStatInterrupt(struct et131x_adapter *adapter);
+void SetupDeviceForMulticast(struct et131x_adapter *adapter);
+void SetupDeviceForUnicast(struct et131x_adapter *adapter);
+
+/* et131x_netdev.c */
+struct net_device *et131x_device_alloc(void);
+
+/* et131x_pm.c */
+void EnablePhyComa(struct et131x_adapter *adapter);
+void DisablePhyComa(struct et131x_adapter *adapter);
+
+/* et131x_phy.c */
+void ET1310_PhyInit(struct et131x_adapter *adapter);
+void ET1310_PhyReset(struct et131x_adapter *adapter);
+void ET1310_PhyPowerDown(struct et131x_adapter *adapter, bool down);
+void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *adapter,
+				  u16 duplex);
+void ET1310_PhyAccessMiBit(struct et131x_adapter *adapter,
+			   u16 action,
+			   u16 regnum, u16 bitnum, u8 *value);
+
+int et131x_xcvr_find(struct et131x_adapter *adapter);
+void et131x_setphy_normal(struct et131x_adapter *adapter);
+
+/* static inline function does not work because et131x_adapter is not always
+ * defined
+ */
+int PhyMiRead(struct et131x_adapter *adapter, u8 xcvrAddr,
+	      u8 xcvrReg, u16 *value);
+#define MiRead(adapter, xcvrReg, value) \
+	PhyMiRead((adapter), (adapter)->Stats.xcvr_addr, (xcvrReg), (value))
+
+int32_t MiWrite(struct et131x_adapter *adapter,
+		u8 xcvReg, u16 value);
+void et131x_Mii_check(struct et131x_adapter *pAdapter,
+		      MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints);
+
+/* This last is not strictly required (the driver could call the TPAL
+ * version instead), but this sets the adapter up correctly, and calls the
+ * access routine indirectly.  This protects the driver from changes in TPAL.
+ */
+void SetPhy_10BaseTHalfDuplex(struct et131x_adapter *adapter);
+
+
+/* et1310_rx.c */
+int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter);
+void et131x_rx_dma_memory_free(struct et131x_adapter *adapter);
+int et131x_rfd_resources_alloc(struct et131x_adapter *adapter,
+			       struct _MP_RFD *pMpRfd);
+void et131x_rfd_resources_free(struct et131x_adapter *adapter,
+			       struct _MP_RFD *pMpRfd);
+int et131x_init_recv(struct et131x_adapter *adapter);
+
+void ConfigRxDmaRegs(struct et131x_adapter *adapter);
+void SetRxDmaTimer(struct et131x_adapter *adapter);
+void et131x_rx_dma_disable(struct et131x_adapter *adapter);
+void et131x_rx_dma_enable(struct et131x_adapter *adapter);
+
+void et131x_reset_recv(struct et131x_adapter *adapter);
+
+void et131x_handle_recv_interrupt(struct et131x_adapter *adapter);
+
+/* et131x_tx.c */
+int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter);
+void et131x_tx_dma_memory_free(struct et131x_adapter *adapter);
+void ConfigTxDmaRegs(struct et131x_adapter *adapter);
+void et131x_init_send(struct et131x_adapter *adapter);
+void et131x_tx_dma_disable(struct et131x_adapter *adapter);
+void et131x_tx_dma_enable(struct et131x_adapter *adapter);
+void et131x_handle_send_interrupt(struct et131x_adapter *adapter);
+void et131x_free_busy_send_packets(struct et131x_adapter *adapter);
+int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev);
+
diff --git a/drivers/staging/et131x/et131x_adapter.h b/drivers/staging/et131x/et131x_adapter.h
index 3f7f37a..64a678f 100644
--- a/drivers/staging/et131x/et131x_adapter.h
+++ b/drivers/staging/et131x/et131x_adapter.h
@@ -77,38 +77,11 @@
  */
 #define NUM_TRAFFIC_CLASSES          1
 
-/*
- * There are three ways of counting errors - if there are more than X errors
- * in Y packets (represented by the "SAMPLE" macros), if there are more than
- * N errors in a S mSec time period (the "PERIOD" macros), or if there are
- * consecutive packets with errors (CONSEC_ERRORED_THRESH).  This last covers
- * for "Bursty" errors, and the errored packets may well not be contiguous,
- * but several errors where the packet counter has changed by less than a
- * small amount will cause this count to increment.
- */
-#define TX_PACKETS_IN_SAMPLE        10000
-#define TX_MAX_ERRORS_IN_SAMPLE     50
-
 #define TX_ERROR_PERIOD             1000
-#define TX_MAX_ERRORS_IN_PERIOD     10
-
-#define LINK_DETECTION_TIMER        5000
-
-#define TX_CONSEC_RANGE             5
-#define TX_CONSEC_ERRORED_THRESH    10
 
 #define LO_MARK_PERCENT_FOR_PSR     15
 #define LO_MARK_PERCENT_FOR_RX      15
 
-/* Counters for error rate monitoring */
-typedef struct _MP_ERR_COUNTERS {
-	u32 PktCountTxPackets;
-	u32 PktCountTxErrors;
-	u32 TimerBasedTxErrors;
-	u32 PktCountLastError;
-	u32 ErredConsecPackets;
-} MP_ERR_COUNTERS, *PMP_ERR_COUNTERS;
-
 /* RFD (Receive Frame Descriptor) */
 typedef struct _MP_RFD {
 	struct list_head list_node;
@@ -174,6 +147,20 @@
 	u32 InterruptStatus;
 } CE_STATS_t, *PCE_STATS_t;
 
+typedef struct _MP_POWER_MGMT {
+	/* variable putting the phy into coma mode when boot up with no cable
+	 * plugged in after 5 seconds
+	 */
+	u8 TransPhyComaModeOnBoot;
+
+	/* Next two used to save power information at power down. This
+	 * information will be used during power up to set up parts of Power
+	 * Management in JAGCore
+	 */
+	u16 PowerDownSpeed;
+	u8 PowerDownDuplex;
+} MP_POWER_MGMT, *PMP_POWER_MGMT;
+
 /* The private adapter structure */
 struct et131x_adapter {
 	struct net_device *netdev;
@@ -248,7 +235,7 @@
 	struct tx_ring tx_ring;
 
 	/* Rx Memory Variables */
-	RX_RING_t RxRing;
+	struct rx_ring rx_ring;
 
 	/* Loopback specifics */
 	u8 ReplicaPhyLoopbk;	/* Replica Enable */
diff --git a/drivers/staging/et131x/et131x_config.h b/drivers/staging/et131x/et131x_config.h
deleted file mode 100644
index 642c0f6..0000000
--- a/drivers/staging/et131x/et131x_config.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *   http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et131x_config.h - Defines, structs, enums, prototypes, etc. to support
- *                   et131x_config.c
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software.  Using this
- * software indicates your acceptance of these terms and conditions.  If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following Disclaimer as comments in the code as
- *    well as in the documentation and/or other materials provided with the
- *    distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following Disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET131X_CONFIG_H__
-#define __ET131X_CONFIG_H__
-
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-void et131x_config_parse(struct et131x_adapter *adapter);
-
-#endif /* __ET131X_CONFIG_H__ */
diff --git a/drivers/staging/et131x/et131x_initpci.c b/drivers/staging/et131x/et131x_initpci.c
index 0892b6a..5ad7e5a 100644
--- a/drivers/staging/et131x/et131x_initpci.c
+++ b/drivers/staging/et131x/et131x_initpci.c
@@ -87,20 +87,16 @@
 #include <linux/random.h>
 
 #include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
 
 #include "et131x_adapter.h"
-#include "et131x_netdev.h"
-#include "et131x_config.h"
-#include "et131x_isr.h"
 
 #include "et1310_address_map.h"
 #include "et1310_tx.h"
 #include "et1310_rx.h"
-#include "et1310_mac.h"
-#include "et1310_eeprom.h"
+#include "et131x.h"
 
+#define INTERNAL_MEM_SIZE       0x400	/* 1024 of internal memory */
+#define INTERNAL_MEM_RX_OFFSET  0x1FF	/* 50%   Tx, 50%   Rx */
 
 /* Defines for Parameter Default/Min/Max vaules */
 #define PARM_SPEED_DUPLEX_MIN   0
@@ -327,7 +323,7 @@
  */
 void ConfigGlobalRegs(struct et131x_adapter *etdev)
 {
-	struct _GLOBAL_t __iomem *regs = &etdev->regs->global;
+	struct global_regs __iomem *regs = &etdev->regs->global;
 
 	writel(0, &regs->rxq_start_addr);
 	writel(INTERNAL_MEM_SIZE - 1, &regs->txq_end_addr);
diff --git a/drivers/staging/et131x/et131x_initpci.h b/drivers/staging/et131x/et131x_initpci.h
deleted file mode 100644
index 7269569..0000000
--- a/drivers/staging/et131x/et131x_initpci.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *   http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et131x_initpci.h - Header which includes common data and function prototypes
- *                    related to the driver's PCI (and PCI Express) information.
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software.  Using this
- * software indicates your acceptance of these terms and conditions.  If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following Disclaimer as comments in the code as
- *    well as in the documentation and/or other materials provided with the
- *    distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following Disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET131X_INITPCI_H__
-#define __ET131X_INITPCI_H__
-
-/* Function Prototypes */
-void et131x_align_allocated_memory(struct et131x_adapter *adapter,
-				   u64 *phys_addr,
-				   u64 *offset, u64 mask);
-
-int et131x_adapter_setup(struct et131x_adapter *adapter);
-int et131x_adapter_memory_alloc(struct et131x_adapter *adapter);
-void et131x_adapter_memory_free(struct et131x_adapter *adapter);
-void et131x_hwaddr_init(struct et131x_adapter *adapter);
-void et131x_soft_reset(struct et131x_adapter *adapter);
-
-#endif /* __ET131X_INITPCI_H__ */
diff --git a/drivers/staging/et131x/et131x_isr.c b/drivers/staging/et131x/et131x_isr.c
index f6d452d..8b6e0b7 100644
--- a/drivers/staging/et131x/et131x_isr.c
+++ b/drivers/staging/et131x/et131x_isr.c
@@ -85,11 +85,27 @@
 #include <linux/ioport.h>
 
 #include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-#include "et1310_mac.h"
-
 #include "et131x_adapter.h"
+#include "et131x.h"
+
+/*
+ * For interrupts, normal running is:
+ *       rxdma_xfr_done, phy_interrupt, mac_stat_interrupt,
+ *       watchdog_interrupt & txdma_xfer_done
+ *
+ * In both cases, when flow control is enabled for either Tx or bi-direction,
+ * we additional enable rx_fbr0_low and rx_fbr1_low, so we know when the
+ * buffer rings are running low.
+ */
+#define INT_MASK_DISABLE            0xffffffff
+
+/* NOTE: Masking out MAC_STAT Interrupt for now...
+ * #define INT_MASK_ENABLE             0xfff6bf17
+ * #define INT_MASK_ENABLE_NO_FLOW     0xfff6bfd7
+ */
+#define INT_MASK_ENABLE             0xfffebf17
+#define INT_MASK_ENABLE_NO_FLOW     0xfffebfd7
+
 
 /**
  *	et131x_enable_interrupts	-	enable interrupt
@@ -185,7 +201,7 @@
 			if (++tcb->stale > 1)
 				status |= ET_INTR_TXDMA_ISR;
 
-		if (adapter->RxRing.UnfinishedReceives)
+		if (adapter->rx_ring.UnfinishedReceives)
 			status |= ET_INTR_RXDMA_XFR_DONE;
 		else if (tcb == NULL)
 			writel(0, &adapter->regs->global.watchdog_timer);
@@ -390,7 +406,7 @@
 
 		/* Let's move on to the TxMac */
 		if (status & ET_INTR_TXMAC) {
-			u32 err = readl(&iomem->txmac.err.value);
+			u32 err = readl(&iomem->txmac.err);
 
 			/*
 			 * When any of the errors occur and TXMAC generates
@@ -425,12 +441,12 @@
 
 			dev_warn(&etdev->pdev->dev,
 			  "RXMAC interrupt, error 0x%08x.  Requesting reset\n",
-				    readl(&iomem->rxmac.err_reg.value));
+				    readl(&iomem->rxmac.err_reg));
 
 			dev_warn(&etdev->pdev->dev,
 				    "Enable 0x%08x, Diag 0x%08x\n",
-				    readl(&iomem->rxmac.ctrl.value),
-				    readl(&iomem->rxmac.rxq_diag.value));
+				    readl(&iomem->rxmac.ctrl),
+				    readl(&iomem->rxmac.rxq_diag));
 
 			/*
 			 * If we are debugging, we want to see this error,
diff --git a/drivers/staging/et131x/et131x_isr.h b/drivers/staging/et131x/et131x_isr.h
deleted file mode 100644
index 906d577..0000000
--- a/drivers/staging/et131x/et131x_isr.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *   http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et131x_isr.h - Defines, structs, enums, prototypes, etc. pertaining to the
- *                ISR processing code.
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software.  Using this
- * software indicates your acceptance of these terms and conditions.  If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following Disclaimer as comments in the code as
- *    well as in the documentation and/or other materials provided with the
- *    distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following Disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET131X_ISR_H__
-#define __ET131X_ISR_H__
-
-irqreturn_t et131x_isr(int irq, void *dev_id);
-void et131x_isr_handler(struct work_struct *work);
-
-#endif /* __ET131X_ISR_H__ */
diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c
index edb78ae..40f8954 100644
--- a/drivers/staging/et131x/et131x_netdev.c
+++ b/drivers/staging/et131x/et131x_netdev.c
@@ -85,14 +85,9 @@
 #include <linux/ioport.h>
 
 #include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-#include "et1310_mac.h"
 #include "et1310_tx.h"
-
 #include "et131x_adapter.h"
-#include "et131x_isr.h"
-#include "et131x_initpci.h"
+#include "et131x.h"
 
 struct net_device_stats *et131x_stats(struct net_device *netdev);
 int et131x_open(struct net_device *netdev);
@@ -339,66 +334,64 @@
  * et131x_set_packet_filter - Configures the Rx Packet filtering on the device
  * @adapter: pointer to our private adapter structure
  *
+ * FIXME: lot of dups with MAC code
+ *
  * Returns 0 on success, errno on failure
  */
 int et131x_set_packet_filter(struct et131x_adapter *adapter)
 {
 	int status = 0;
 	uint32_t filter = adapter->PacketFilter;
-	RXMAC_CTRL_t ctrl;
-	RXMAC_PF_CTRL_t pf_ctrl;
+	u32 ctrl;
+	u32 pf_ctrl;
 
-	ctrl.value = readl(&adapter->regs->rxmac.ctrl.value);
-	pf_ctrl.value = readl(&adapter->regs->rxmac.pf_ctrl.value);
+	ctrl = readl(&adapter->regs->rxmac.ctrl);
+	pf_ctrl = readl(&adapter->regs->rxmac.pf_ctrl);
 
 	/* Default to disabled packet filtering.  Enable it in the individual
 	 * case statements that require the device to filter something
 	 */
-	ctrl.bits.pkt_filter_disable = 1;
+	ctrl |= 0x04;
 
 	/* Set us to be in promiscuous mode so we receive everything, this
 	 * is also true when we get a packet filter of 0
 	 */
-	if ((filter & ET131X_PACKET_TYPE_PROMISCUOUS) || filter == 0) {
-		pf_ctrl.bits.filter_broad_en = 0;
-		pf_ctrl.bits.filter_multi_en = 0;
-		pf_ctrl.bits.filter_uni_en = 0;
-	} else {
+	if ((filter & ET131X_PACKET_TYPE_PROMISCUOUS) || filter == 0)
+		pf_ctrl &= ~7;	/* Clear filter bits */
+	else {
 		/*
 		 * Set us up with Multicast packet filtering.  Three cases are
 		 * possible - (1) we have a multi-cast list, (2) we receive ALL
 		 * multicast entries or (3) we receive none.
 		 */
-		if (filter & ET131X_PACKET_TYPE_ALL_MULTICAST) {
-			pf_ctrl.bits.filter_multi_en = 0;
-		} else {
+		if (filter & ET131X_PACKET_TYPE_ALL_MULTICAST)
+			pf_ctrl &= ~2;	/* Multicast filter bit */
+		else {
 			SetupDeviceForMulticast(adapter);
-			pf_ctrl.bits.filter_multi_en = 1;
-			ctrl.bits.pkt_filter_disable = 0;
+			pf_ctrl |= 2;
+			ctrl &= ~0x04;
 		}
 
 		/* Set us up with Unicast packet filtering */
 		if (filter & ET131X_PACKET_TYPE_DIRECTED) {
 			SetupDeviceForUnicast(adapter);
-			pf_ctrl.bits.filter_uni_en = 1;
-			ctrl.bits.pkt_filter_disable = 0;
+			pf_ctrl |= 4;
+			ctrl &= ~0x04;
 		}
 
 		/* Set us up with Broadcast packet filtering */
 		if (filter & ET131X_PACKET_TYPE_BROADCAST) {
-			pf_ctrl.bits.filter_broad_en = 1;
-			ctrl.bits.pkt_filter_disable = 0;
-		} else {
-			pf_ctrl.bits.filter_broad_en = 0;
-		}
+			pf_ctrl |= 1;	/* Broadcast filter bit */
+			ctrl &= ~0x04;
+		} else
+			pf_ctrl &= ~1;
 
 		/* Setup the receive mac configuration registers - Packet
 		 * Filter control + the enable / disable for packet filter
 		 * in the control reg.
 		 */
-		writel(pf_ctrl.value,
-		       &adapter->regs->rxmac.pf_ctrl.value);
-		writel(ctrl.value, &adapter->regs->rxmac.ctrl.value);
+		writel(pf_ctrl, &adapter->regs->rxmac.pf_ctrl);
+		writel(ctrl, &adapter->regs->rxmac.ctrl);
 	}
 	return status;
 }
@@ -675,12 +668,8 @@
 
 	memcpy(netdev->dev_addr, address->sa_data, netdev->addr_len);
 
-	printk(KERN_INFO
-		"%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n",
-			netdev->name,
-			netdev->dev_addr[0], netdev->dev_addr[1],
-			netdev->dev_addr[2], netdev->dev_addr[3],
-			netdev->dev_addr[4], netdev->dev_addr[5]);
+	printk(KERN_INFO "%s: Setting MAC address to %pM\n",
+			netdev->name, netdev->dev_addr);
 
 	/* Free Rx DMA memory */
 	et131x_adapter_memory_free(adapter);
diff --git a/drivers/staging/et131x/et131x_netdev.h b/drivers/staging/et131x/et131x_netdev.h
deleted file mode 100644
index 1eb4a92..0000000
--- a/drivers/staging/et131x/et131x_netdev.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *   http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et131x_netdev.h - Defines, structs, enums, prototypes, etc. related to the
- *                   driver's net_device support.
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software.  Using this
- * software indicates your acceptance of these terms and conditions.  If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following Disclaimer as comments in the code as
- *    well as in the documentation and/or other materials provided with the
- *    distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following Disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET131X_NETDEV_H__
-#define __ET131X_NETDEV_H__
-
-struct net_device *et131x_device_alloc(void);
-
-#endif /* __ET131X_NETDEV_H__ */
diff --git a/drivers/staging/et131x/et131x_version.h b/drivers/staging/et131x/et131x_version.h
index 568f6c8..2aa9bda 100644
--- a/drivers/staging/et131x/et131x_version.h
+++ b/drivers/staging/et131x/et131x_version.h
@@ -62,20 +62,13 @@
 #define DRIVER_LICENSE		"Dual BSD/GPL"
 #define DRIVER_DEVICE_STRING	"ET1310"
 #define DRIVER_NAME		"et131x"
-#define DRIVER_MAJOR_VERSION	1
-#define DRIVER_MINOR_VERSION	2
-#define DRIVER_PATCH_VERSION	3
-#define DRIVER_VERSION_STRING	"1.2.3"
+#define DRIVER_VERSION_STRING	"1.2.3-lk"
 #define DRIVER_VENDOR		"Agere Systems, http://www.agere.com"
 #define DRIVER_DESC		"10/100/1000 Base-T Ethernet Driver"
 
-#define STRUCT_MODULE		"net"	/* blux: missed by the kernel */
-
 #define DRIVER_INFO		DRIVER_DESC " for the "\
 				DRIVER_DEVICE_STRING ", v" \
 				DRIVER_VERSION_STRING " by " \
 				DRIVER_VENDOR
 
-#define DRIVER_NAME_EXT		"et131x.ko"
-
 #endif /* __ET131X_VERSION_H__ */
diff --git a/drivers/staging/frontier/alphatrack.c b/drivers/staging/frontier/alphatrack.c
index 15aed87..a50a215 100644
--- a/drivers/staging/frontier/alphatrack.c
+++ b/drivers/staging/frontier/alphatrack.c
@@ -58,7 +58,7 @@
 #endif
 
 /* table of devices that work with this driver */
-static struct usb_device_id usb_alphatrack_table[] = {
+static const struct usb_device_id usb_alphatrack_table[] = {
 	{USB_DEVICE(VENDOR_ID, PRODUCT_ID)},
 	{}			/* Terminating entry */
 };
diff --git a/drivers/staging/frontier/tranzport.c b/drivers/staging/frontier/tranzport.c
index ef8fcc8..2f03f43 100644
--- a/drivers/staging/frontier/tranzport.c
+++ b/drivers/staging/frontier/tranzport.c
@@ -55,7 +55,7 @@
 #endif
 
 /* table of devices that work with this driver */
-static struct usb_device_id usb_tranzport_table[] = {
+static const struct usb_device_id usb_tranzport_table[] = {
 	{USB_DEVICE(VENDOR_ID, PRODUCT_ID)},
 	{}			/* Terminating entry */
 };
diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c
index fb1345f..d42ba16 100644
--- a/drivers/staging/go7007/go7007-driver.c
+++ b/drivers/staging/go7007/go7007-driver.c
@@ -128,6 +128,8 @@
 	return rv;
 }
 
+MODULE_FIRMWARE("go7007fw.bin");
+
 /*
  * Boot the encoder and register the I2C adapter if requested.  Do the
  * minimum initialization necessary, since the board-specific code may
diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c
index 1e89dc0..ee278f6 100644
--- a/drivers/staging/go7007/go7007-usb.c
+++ b/drivers/staging/go7007/go7007-usb.c
@@ -444,7 +444,9 @@
 	},
 };
 
-static struct usb_device_id go7007_usb_id_table[] = {
+MODULE_FIRMWARE("go7007tv.bin");
+
+static const struct usb_device_id go7007_usb_id_table[] = {
 	{
 		.match_flags	= USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
 					USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c
index c324f6e..dc89502 100644
--- a/drivers/staging/go7007/s2250-board.c
+++ b/drivers/staging/go7007/s2250-board.c
@@ -667,7 +667,7 @@
 	return 0;
 }
 
-static struct i2c_device_id s2250_id[] = {
+static const struct i2c_device_id s2250_id[] = {
 	{ "s2250", 0 },
 	{ }
 };
diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c
index c152ab9..1de2dfb 100644
--- a/drivers/staging/go7007/s2250-loader.c
+++ b/drivers/staging/go7007/s2250-loader.c
@@ -139,7 +139,7 @@
 
 static void s2250loader_disconnect(struct usb_interface *interface)
 {
-	pdevice_extension_t s = usb_get_intfdata(interface);
+	pdevice_extension_t s;
 	printk(KERN_INFO "s2250: disconnect\n");
 	lock_kernel();
 	s = usb_get_intfdata(interface);
@@ -148,7 +148,7 @@
 	unlock_kernel();
 }
 
-static struct usb_device_id s2250loader_ids[] = {
+static const struct usb_device_id s2250loader_ids[] = {
 	{USB_DEVICE(0x1943, 0xa250)},
 	{}                          /* Terminating entry */
 };
diff --git a/drivers/staging/go7007/saa7134-go7007.c b/drivers/staging/go7007/saa7134-go7007.c
index 665bbf5..b25d7d2 100644
--- a/drivers/staging/go7007/saa7134-go7007.c
+++ b/drivers/staging/go7007/saa7134-go7007.c
@@ -84,6 +84,7 @@
 		},
 	},
 };
+MODULE_FIRMWARE("go7007tv.bin");
 
 /********************* Driver for GPIO HPI interface *********************/
 
diff --git a/drivers/staging/go7007/wis-ov7640.c b/drivers/staging/go7007/wis-ov7640.c
index 04d6d3a..4f0cbdd 100644
--- a/drivers/staging/go7007/wis-ov7640.c
+++ b/drivers/staging/go7007/wis-ov7640.c
@@ -77,7 +77,7 @@
 	return 0;
 }
 
-static struct i2c_device_id wis_ov7640_id[] = {
+static const struct i2c_device_id wis_ov7640_id[] = {
 	{ "wis_ov7640", 0 },
 	{ }
 };
diff --git a/drivers/staging/go7007/wis-saa7113.c b/drivers/staging/go7007/wis-saa7113.c
index 9ab893b..d196e16f 100644
--- a/drivers/staging/go7007/wis-saa7113.c
+++ b/drivers/staging/go7007/wis-saa7113.c
@@ -304,7 +304,7 @@
 	return 0;
 }
 
-static struct i2c_device_id wis_saa7113_id[] = {
+static const struct i2c_device_id wis_saa7113_id[] = {
 	{ "wis_saa7113", 0 },
 	{ }
 };
diff --git a/drivers/staging/go7007/wis-saa7115.c b/drivers/staging/go7007/wis-saa7115.c
index 8687ad2..0f2b4a0 100644
--- a/drivers/staging/go7007/wis-saa7115.c
+++ b/drivers/staging/go7007/wis-saa7115.c
@@ -437,7 +437,7 @@
 	return 0;
 }
 
-static struct i2c_device_id wis_saa7115_id[] = {
+static const struct i2c_device_id wis_saa7115_id[] = {
 	{ "wis_saa7115", 0 },
 	{ }
 };
diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c
index 086896c..c723e4a 100644
--- a/drivers/staging/go7007/wis-sony-tuner.c
+++ b/drivers/staging/go7007/wis-sony-tuner.c
@@ -688,7 +688,7 @@
 	return 0;
 }
 
-static struct i2c_device_id wis_sony_tuner_id[] = {
+static const struct i2c_device_id wis_sony_tuner_id[] = {
 	{ "wis_sony_tuner", 0 },
 	{ }
 };
diff --git a/drivers/staging/go7007/wis-tw2804.c b/drivers/staging/go7007/wis-tw2804.c
index e15794a..1983839 100644
--- a/drivers/staging/go7007/wis-tw2804.c
+++ b/drivers/staging/go7007/wis-tw2804.c
@@ -327,7 +327,7 @@
 	return 0;
 }
 
-static struct i2c_device_id wis_tw2804_id[] = {
+static const struct i2c_device_id wis_tw2804_id[] = {
 	{ "wis_tw2804", 0 },
 	{ }
 };
diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c
index 506dca6..f97e2be 100644
--- a/drivers/staging/go7007/wis-tw9903.c
+++ b/drivers/staging/go7007/wis-tw9903.c
@@ -309,7 +309,7 @@
 	return 0;
 }
 
-static struct i2c_device_id wis_tw9903_id[] = {
+static const struct i2c_device_id wis_tw9903_id[] = {
 	{ "wis_tw9903", 0 },
 	{ }
 };
diff --git a/drivers/staging/go7007/wis-uda1342.c b/drivers/staging/go7007/wis-uda1342.c
index 739c7ae..5c4eb49 100644
--- a/drivers/staging/go7007/wis-uda1342.c
+++ b/drivers/staging/go7007/wis-uda1342.c
@@ -82,7 +82,7 @@
 	return 0;
 }
 
-static struct i2c_device_id wis_uda1342_id[] = {
+static const struct i2c_device_id wis_uda1342_id[] = {
 	{ "wis_uda1342", 0 },
 	{ }
 };
diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
index 746370e..d46eb14 100644
--- a/drivers/staging/hv/Channel.c
+++ b/drivers/staging/hv/Channel.c
@@ -991,9 +991,8 @@
 {
 	struct vmbus_channel *channel = (struct vmbus_channel *)data;
 
-	if (channel->OnChannelCallback) {
+	if (channel->OnChannelCallback)
 		channel->OnChannelCallback(channel->ChannelCallbackContext);
-	}
 }
 
 /**
diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c
index c2809f2..51149e6 100644
--- a/drivers/staging/hv/Hv.c
+++ b/drivers/staging/hv/Hv.c
@@ -208,50 +208,51 @@
 	/* HvQueryHypervisorFeatures(maxLeaf); */
 
 	/*
-	 * Determine if we are running on xenlinux (ie x2v shim) or native
-	 * linux
+	 * We only support running on top of Hyper-V
 	 */
 	rdmsrl(HV_X64_MSR_GUEST_OS_ID, gHvContext.GuestId);
-	if (gHvContext.GuestId == 0) {
-		/* Write our OS info */
-		wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
-		gHvContext.GuestId = HV_LINUX_GUEST_ID;
-	}
 
-	/* See if the hypercall page is already set */
-	rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
-	if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
-		/* Allocate the hypercall page memory */
-		/* virtAddr = osd_PageAlloc(1); */
-		virtAddr = osd_VirtualAllocExec(PAGE_SIZE);
-
-		if (!virtAddr) {
-			DPRINT_ERR(VMBUS,
-				   "unable to allocate hypercall page!!");
-			goto Cleanup;
-		}
-
-		hypercallMsr.Enable = 1;
-		/* hypercallMsr.GuestPhysicalAddress =
-		 * 		virt_to_phys(virtAddr) >> PAGE_SHIFT; */
-		hypercallMsr.GuestPhysicalAddress = vmalloc_to_pfn(virtAddr);
-		wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
-
-		/* Confirm that hypercall page did get setup. */
-		hypercallMsr.AsUINT64 = 0;
-		rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
-		if (!hypercallMsr.Enable) {
-			DPRINT_ERR(VMBUS, "unable to set hypercall page!!");
-			goto Cleanup;
-		}
-
-		gHvContext.HypercallPage = virtAddr;
-	} else {
+	if (gHvContext.GuestId != 0) {
 		DPRINT_ERR(VMBUS, "Unknown guest id (0x%llx)!!",
 				gHvContext.GuestId);
 		goto Cleanup;
 	}
 
+	/* Write our OS info */
+	wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
+	gHvContext.GuestId = HV_LINUX_GUEST_ID;
+
+	/* See if the hypercall page is already set */
+	rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+
+	/*
+	* Allocate the hypercall page memory
+	* virtAddr = osd_PageAlloc(1);
+	*/
+	virtAddr = osd_VirtualAllocExec(PAGE_SIZE);
+
+	if (!virtAddr) {
+		DPRINT_ERR(VMBUS,
+			   "unable to allocate hypercall page!!");
+		goto Cleanup;
+	}
+
+	hypercallMsr.Enable = 1;
+
+	hypercallMsr.GuestPhysicalAddress = vmalloc_to_pfn(virtAddr);
+	wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+
+	/* Confirm that hypercall page did get setup. */
+	hypercallMsr.AsUINT64 = 0;
+	rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+
+	if (!hypercallMsr.Enable) {
+		DPRINT_ERR(VMBUS, "unable to set hypercall page!!");
+		goto Cleanup;
+	}
+
+	gHvContext.HypercallPage = virtAddr;
+
 	DPRINT_INFO(VMBUS, "Hypercall page VA=%p, PA=0x%0llx",
 		    gHvContext.HypercallPage,
 		    (u64)hypercallMsr.GuestPhysicalAddress << PAGE_SHIFT);
@@ -273,8 +274,6 @@
 	gHvContext.SignalEventParam->FlagNumber = 0;
 	gHvContext.SignalEventParam->RsvdZ = 0;
 
-	/* DPRINT_DBG(VMBUS, "My id %llu", HvGetCurrentPartitionId()); */
-
 	DPRINT_EXIT(VMBUS);
 
 	return ret;
@@ -311,17 +310,14 @@
 		kfree(gHvContext.SignalEventBuffer);
 	}
 
-	if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
-		if (gHvContext.HypercallPage) {
-			hypercallMsr.AsUINT64 = 0;
-			wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
-			vfree(gHvContext.HypercallPage);
-			gHvContext.HypercallPage = NULL;
-		}
+	if (gHvContext.HypercallPage) {
+		hypercallMsr.AsUINT64 = 0;
+		wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+		vfree(gHvContext.HypercallPage);
+		gHvContext.HypercallPage = NULL;
 	}
 
 	DPRINT_EXIT(VMBUS);
-
 }
 
 /**
@@ -393,7 +389,7 @@
 	union hv_synic_siefp siefp;
 	union hv_synic_sint sharedSint;
 	union hv_synic_scontrol sctrl;
-	u64 guestID;
+
 	u32 irqVector = *((u32 *)(irqarg));
 	int cpu = smp_processor_id();
 
@@ -409,72 +405,42 @@
 
 	DPRINT_INFO(VMBUS, "SynIC version: %llx", version);
 
-	/* TODO: Handle SMP */
-	if (gHvContext.GuestId == HV_XENLINUX_GUEST_ID) {
-		DPRINT_INFO(VMBUS, "Skipping SIMP and SIEFP setup since "
-				"it is already set.");
+	gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
 
-		rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
-		rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
-
-		DPRINT_DBG(VMBUS, "Simp: %llx, Sifep: %llx",
-			   simp.AsUINT64, siefp.AsUINT64);
-
-		/*
-		 * Determine if we are running on xenlinux (ie x2v shim) or
-		 * native linux
-		 */
-		rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID);
-		if (guestID == HV_LINUX_GUEST_ID) {
-			gHvContext.synICMessagePage[cpu] =
-				phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT);
-			gHvContext.synICEventPage[cpu] =
-				phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT);
-		} else {
-			DPRINT_ERR(VMBUS, "unknown guest id!!");
-			goto Cleanup;
-		}
-		DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p",
-			   gHvContext.synICMessagePage[cpu],
-			   gHvContext.synICEventPage[cpu]);
-	} else {
-		gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
-		if (gHvContext.synICMessagePage[cpu] == NULL) {
-			DPRINT_ERR(VMBUS,
-				   "unable to allocate SYNIC message page!!");
-			goto Cleanup;
-		}
-
-		gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
-		if (gHvContext.synICEventPage[cpu] == NULL) {
-			DPRINT_ERR(VMBUS,
-				   "unable to allocate SYNIC event page!!");
-			goto Cleanup;
-		}
-
-		/* Setup the Synic's message page */
-		rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
-		simp.SimpEnabled = 1;
-		simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu])
-					>> PAGE_SHIFT;
-
-		DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx",
-				simp.AsUINT64);
-
-		wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
-
-		/* Setup the Synic's event page */
-		rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
-		siefp.SiefpEnabled = 1;
-		siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu])
-					>> PAGE_SHIFT;
-
-		DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx",
-				siefp.AsUINT64);
-
-		wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
+	if (gHvContext.synICMessagePage[cpu] == NULL) {
+		DPRINT_ERR(VMBUS,
+			   "unable to allocate SYNIC message page!!");
+		goto Cleanup;
 	}
 
+	gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
+
+	if (gHvContext.synICEventPage[cpu] == NULL) {
+		DPRINT_ERR(VMBUS,
+			   "unable to allocate SYNIC event page!!");
+		goto Cleanup;
+	}
+
+	/* Setup the Synic's message page */
+	rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
+	simp.SimpEnabled = 1;
+	simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu])
+		>> PAGE_SHIFT;
+
+	DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", simp.AsUINT64);
+
+	wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
+
+	/* Setup the Synic's event page */
+	rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
+	siefp.SiefpEnabled = 1;
+	siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu])
+		>> PAGE_SHIFT;
+
+	DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", siefp.AsUINT64);
+
+	wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
+
 	/* Setup the interception SINT. */
 	/* wrmsrl((HV_X64_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX), */
 	/*	  interceptionSint.AsUINT64); */
@@ -505,13 +471,11 @@
 	return;
 
 Cleanup:
-	if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
-		if (gHvContext.synICEventPage[cpu])
-			osd_PageFree(gHvContext.synICEventPage[cpu], 1);
+	if (gHvContext.synICEventPage[cpu])
+		osd_PageFree(gHvContext.synICEventPage[cpu], 1);
 
-		if (gHvContext.synICMessagePage[cpu])
-			osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
-	}
+	if (gHvContext.synICMessagePage[cpu])
+		osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
 
 	DPRINT_EXIT(VMBUS);
 	return;
@@ -542,27 +506,20 @@
 	/* Disable the interrupt */
 	wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
 
-	/*
-	 * Disable and free the resources only if we are running as
-	 * native linux since in xenlinux, we are sharing the
-	 * resources with the x2v shim
-	 */
-	if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
-		rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
-		simp.SimpEnabled = 0;
-		simp.BaseSimpGpa = 0;
+	rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
+	simp.SimpEnabled = 0;
+	simp.BaseSimpGpa = 0;
 
-		wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
+	wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
 
-		rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
-		siefp.SiefpEnabled = 0;
-		siefp.BaseSiefpGpa = 0;
+	rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
+	siefp.SiefpEnabled = 0;
+	siefp.BaseSiefpGpa = 0;
 
-		wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
+	wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
 
-		osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
-		osd_PageFree(gHvContext.synICEventPage[cpu], 1);
-	}
+	osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
+	osd_PageFree(gHvContext.synICEventPage[cpu], 1);
 
 	DPRINT_EXIT(VMBUS);
 }
diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h
index fce4b5c..41f5ebb 100644
--- a/drivers/staging/hv/Hv.h
+++ b/drivers/staging/hv/Hv.h
@@ -41,11 +41,6 @@
 
 #define HV_PRESENT_BIT			0x80000000
 
-#define HV_XENLINUX_GUEST_ID_LO		0x00000000
-#define HV_XENLINUX_GUEST_ID_HI		0x0B00B135
-#define HV_XENLINUX_GUEST_ID		(((u64)HV_XENLINUX_GUEST_ID_HI << 32) \
-					  | HV_XENLINUX_GUEST_ID_LO)
-
 #define HV_LINUX_GUEST_ID_LO		0x00000000
 #define HV_LINUX_GUEST_ID_HI		0xB16B00B5
 #define HV_LINUX_GUEST_ID		(((u64)HV_LINUX_GUEST_ID_HI << 32) | \
@@ -102,8 +97,9 @@
 };
 
 struct hv_context {
-	/* XenLinux or native Linux. If XenLinux, the hypercall and synic pages
-	 * has already been initialized */
+	/* We only support running on top of Hyper-V
+	* So at this point this really can only contain the Hyper-V ID
+	*/
 	u64 GuestId;
 
 	void *HypercallPage;
diff --git a/drivers/staging/hv/NetVscApi.h b/drivers/staging/hv/NetVscApi.h
index 1ce2b74..95d7a32 100644
--- a/drivers/staging/hv/NetVscApi.h
+++ b/drivers/staging/hv/NetVscApi.h
@@ -105,8 +105,6 @@
 	void (*OnLinkStatusChanged)(struct hv_device *dev, u32 Status);
 
 	/* Specific to this driver */
-	int (*OnOpen)(struct hv_device *dev);
-	int (*OnClose)(struct hv_device *dev);
 	int (*OnSend)(struct hv_device *dev, struct hv_netvsc_packet *packet);
 
 	void *Context;
@@ -119,5 +117,7 @@
 
 /* Interface */
 int NetVscInitialize(struct hv_driver *drv);
+int RndisFilterOnOpen(struct hv_device *Device);
+int RndisFilterOnClose(struct hv_device *Device);
 
 #endif /* _NETVSC_API_H_ */
diff --git a/drivers/staging/hv/RingBuffer.c b/drivers/staging/hv/RingBuffer.c
index f69ae33..80b8a2c 100644
--- a/drivers/staging/hv/RingBuffer.c
+++ b/drivers/staging/hv/RingBuffer.c
@@ -48,7 +48,7 @@
 static inline void
 GetRingBufferAvailBytes(RING_BUFFER_INFO *rbi, u32 *read, u32 *write)
 {
-	u32 read_loc,write_loc;
+	u32 read_loc, write_loc;
 
 	/* Capture the read/write indices before they changed */
 	read_loc = rbi->RingBuffer->ReadIndex;
@@ -68,7 +68,7 @@
 
 --*/
 static inline u32
-GetNextWriteLocation(RING_BUFFER_INFO* RingInfo)
+GetNextWriteLocation(RING_BUFFER_INFO *RingInfo)
 {
 	u32 next = RingInfo->RingBuffer->WriteIndex;
 
@@ -87,7 +87,7 @@
 
 --*/
 static inline void
-SetNextWriteLocation(RING_BUFFER_INFO* RingInfo, u32 NextWriteLocation)
+SetNextWriteLocation(RING_BUFFER_INFO *RingInfo, u32 NextWriteLocation)
 {
 	RingInfo->RingBuffer->WriteIndex = NextWriteLocation;
 }
@@ -102,7 +102,7 @@
 
 --*/
 static inline u32
-GetNextReadLocation(RING_BUFFER_INFO* RingInfo)
+GetNextReadLocation(RING_BUFFER_INFO *RingInfo)
 {
 	u32 next = RingInfo->RingBuffer->ReadIndex;
 
@@ -122,7 +122,7 @@
 
 --*/
 static inline u32
-GetNextReadLocationWithOffset(RING_BUFFER_INFO* RingInfo, u32 Offset)
+GetNextReadLocationWithOffset(RING_BUFFER_INFO *RingInfo, u32 Offset)
 {
 	u32 next = RingInfo->RingBuffer->ReadIndex;
 
@@ -143,7 +143,7 @@
 
 --*/
 static inline void
-SetNextReadLocation(RING_BUFFER_INFO* RingInfo, u32 NextReadLocation)
+SetNextReadLocation(RING_BUFFER_INFO *RingInfo, u32 NextReadLocation)
 {
 	RingInfo->RingBuffer->ReadIndex = NextReadLocation;
 }
@@ -159,7 +159,7 @@
 
 --*/
 static inline void *
-GetRingBuffer(RING_BUFFER_INFO* RingInfo)
+GetRingBuffer(RING_BUFFER_INFO *RingInfo)
 {
 	return (void *)RingInfo->RingBuffer->Buffer;
 }
@@ -175,7 +175,7 @@
 
 --*/
 static inline u32
-GetRingBufferSize(RING_BUFFER_INFO* RingInfo)
+GetRingBufferSize(RING_BUFFER_INFO *RingInfo)
 {
 	return RingInfo->RingDataSize;
 }
@@ -190,9 +190,10 @@
 
 --*/
 static inline u64
-GetRingBufferIndices(RING_BUFFER_INFO* RingInfo)
+GetRingBufferIndices(RING_BUFFER_INFO *RingInfo)
 {
-	return ((u64)RingInfo->RingBuffer->WriteIndex << 32) || RingInfo->RingBuffer->ReadIndex;
+	return ((u64)RingInfo->RingBuffer->WriteIndex << 32)
+	|| RingInfo->RingBuffer->ReadIndex;
 }
 
 
@@ -210,9 +211,14 @@
 	u32 bytesAvailToWrite;
 	u32 bytesAvailToRead;
 
-	GetRingBufferAvailBytes(RingInfo, &bytesAvailToRead, &bytesAvailToWrite);
+	GetRingBufferAvailBytes(RingInfo,
+	&bytesAvailToRead,
+	&bytesAvailToWrite);
 
-	DPRINT(VMBUS, DEBUG_RING_LVL, "%s <<ringinfo %p buffer %p avail write %u avail read %u read idx %u write idx %u>>",
+	DPRINT(VMBUS,
+		DEBUG_RING_LVL,
+		"%s <<ringinfo %p buffer %p avail write %u "
+		"avail read %u read idx %u write idx %u>>",
 		Prefix,
 		RingInfo,
 		RingInfo->RingBuffer->Buffer,
@@ -229,13 +235,13 @@
 CopyToRingBuffer(
 	RING_BUFFER_INFO	*RingInfo,
 	u32				StartWriteOffset,
-	void *				Src,
+	void				*Src,
 	u32				SrcLen);
 
 static u32
 CopyFromRingBuffer(
 	RING_BUFFER_INFO	*RingInfo,
-	void *				Dest,
+	void				*Dest,
 	u32				DestLen,
 	u32				StartReadOffset);
 
@@ -256,15 +262,15 @@
 	u32 bytesAvailToWrite;
 	u32 bytesAvailToRead;
 
-	if (RingInfo->RingBuffer)
-	{
-		GetRingBufferAvailBytes(RingInfo, &bytesAvailToRead, &bytesAvailToWrite);
+	if (RingInfo->RingBuffer) {
+		GetRingBufferAvailBytes(RingInfo,
+					&bytesAvailToRead,
+					&bytesAvailToWrite);
 
 		DebugInfo->BytesAvailToRead = bytesAvailToRead;
 		DebugInfo->BytesAvailToWrite = bytesAvailToWrite;
 		DebugInfo->CurrentReadIndex = RingInfo->RingBuffer->ReadIndex;
 		DebugInfo->CurrentWriteIndex = RingInfo->RingBuffer->WriteIndex;
-
 		DebugInfo->CurrentInterruptMask = RingInfo->RingBuffer->InterruptMask;
 	}
 }
@@ -299,7 +305,7 @@
 
 	memset(RingInfo, 0, sizeof(RING_BUFFER_INFO));
 
-	RingInfo->RingBuffer = (RING_BUFFER*)Buffer;
+	RingInfo->RingBuffer = (RING_BUFFER *)Buffer;
 	RingInfo->RingBuffer->ReadIndex = RingInfo->RingBuffer->WriteIndex = 0;
 
 	RingInfo->RingSize = BufferLen;
@@ -319,7 +325,7 @@
 	Cleanup the ring buffer
 
 --*/
-void RingBufferCleanup(RING_BUFFER_INFO* RingInfo)
+void RingBufferCleanup(RING_BUFFER_INFO *RingInfo)
 {
 }
 
@@ -335,14 +341,14 @@
 int RingBufferWrite(RING_BUFFER_INFO *OutRingInfo,
 		    struct scatterlist *sglist, u32 sgcount)
 {
-	int i=0;
+	int i = 0;
 	u32 byteAvailToWrite;
 	u32 byteAvailToRead;
-	u32 totalBytesToWrite=0;
+	u32 totalBytesToWrite = 0;
 
 	struct scatterlist *sg;
 	volatile u32 nextWriteLocation;
-	u64 prevIndices=0;
+	u64 prevIndices = 0;
 	unsigned long flags;
 
 	DPRINT_ENTER(VMBUS);
@@ -356,17 +362,23 @@
 
 	spin_lock_irqsave(&OutRingInfo->ring_lock, flags);
 
-	GetRingBufferAvailBytes(OutRingInfo, &byteAvailToRead, &byteAvailToWrite);
+	GetRingBufferAvailBytes(OutRingInfo,
+				&byteAvailToRead,
+				&byteAvailToWrite);
 
 	DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);
 
 	/* DumpRingInfo(OutRingInfo, "BEFORE "); */
 
-	/* If there is only room for the packet, assume it is full. Otherwise, the next time around, we think the ring buffer */
+	/* If there is only room for the packet, assume it is full. */
+	/* Otherwise, the next time around, we think the ring buffer */
 	/* is empty since the read index == write index */
-	if (byteAvailToWrite <= totalBytesToWrite)
-	{
-		DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer (needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite);
+	if (byteAvailToWrite <= totalBytesToWrite) {
+		DPRINT_DBG(VMBUS,
+			"No more space left on outbound ring buffer "
+			"(needed %u, avail %u)",
+			totalBytesToWrite,
+			byteAvailToWrite);
 
 		spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);
 
@@ -423,17 +435,22 @@
 {
 	u32 bytesAvailToWrite;
 	u32 bytesAvailToRead;
-	u32 nextReadLocation=0;
+	u32 nextReadLocation = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&InRingInfo->ring_lock, flags);
 
-	GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);
+	GetRingBufferAvailBytes(InRingInfo,
+				&bytesAvailToRead,
+				&bytesAvailToWrite);
 
 	/* Make sure there is something to read */
-	if (bytesAvailToRead < BufferLen )
-	{
-		/* DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen); */
+	if (bytesAvailToRead < BufferLen) {
+		/* DPRINT_DBG(VMBUS,
+			"got callback but not enough to read "
+			"<avail to read %d read size %d>!!",
+			bytesAvailToRead,
+			BufferLen); */
 
 		spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
 
@@ -444,9 +461,9 @@
 	nextReadLocation = GetNextReadLocation(InRingInfo);
 
 	nextReadLocation = CopyFromRingBuffer(InRingInfo,
-											Buffer,
-											BufferLen,
-											nextReadLocation);
+						Buffer,
+						BufferLen,
+						nextReadLocation);
 
 	spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
 
@@ -468,24 +485,29 @@
 {
 	u32 bytesAvailToWrite;
 	u32 bytesAvailToRead;
-	u32 nextReadLocation=0;
-	u64 prevIndices=0;
+	u32 nextReadLocation = 0;
+	u64 prevIndices = 0;
 	unsigned long flags;
 
 	ASSERT(BufferLen > 0);
 
 	spin_lock_irqsave(&InRingInfo->ring_lock, flags);
 
-	GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);
+	GetRingBufferAvailBytes(InRingInfo,
+				&bytesAvailToRead,
+				&bytesAvailToWrite);
 
 	DPRINT_DBG(VMBUS, "Reading %u bytes...", BufferLen);
 
 	/* DumpRingInfo(InRingInfo, "BEFORE "); */
 
 	/* Make sure there is something to read */
-	if (bytesAvailToRead < BufferLen )
-	{
-		DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen);
+	if (bytesAvailToRead < BufferLen) {
+		DPRINT_DBG(VMBUS,
+			"got callback but not enough to read "
+			"<avail to read %d read size %d>!!",
+			bytesAvailToRead,
+			BufferLen);
 
 		spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
 
@@ -495,17 +517,18 @@
 	nextReadLocation = GetNextReadLocationWithOffset(InRingInfo, Offset);
 
 	nextReadLocation = CopyFromRingBuffer(InRingInfo,
-											Buffer,
-											BufferLen,
-											nextReadLocation);
+						Buffer,
+						BufferLen,
+						nextReadLocation);
 
 	nextReadLocation = CopyFromRingBuffer(InRingInfo,
-											&prevIndices,
-											sizeof(u64),
-											nextReadLocation);
+						&prevIndices,
+						sizeof(u64),
+						nextReadLocation);
 
 	/* Make sure all reads are done before we update the read index since */
-	/* the writer may start writing to the read area once the read index is updated */
+	/* the writer may start writing to the read area once the read index */
+	/*is updated */
 	mb();
 
 	/* Update the read index */
@@ -533,25 +556,22 @@
 CopyToRingBuffer(
 	RING_BUFFER_INFO	*RingInfo,
 	u32				StartWriteOffset,
-	void *				Src,
+	void				*Src,
 	u32				SrcLen)
 {
-	void * ringBuffer=GetRingBuffer(RingInfo);
-	u32 ringBufferSize=GetRingBufferSize(RingInfo);
+	void *ringBuffer = GetRingBuffer(RingInfo);
+	u32 ringBufferSize = GetRingBufferSize(RingInfo);
 	u32 fragLen;
 
-	if (SrcLen > ringBufferSize - StartWriteOffset) /* wrap-around detected! */
-	{
+	/* wrap-around detected! */
+	if (SrcLen > ringBufferSize - StartWriteOffset) {
 		DPRINT_DBG(VMBUS, "wrap-around detected!");
 
 		fragLen = ringBufferSize - StartWriteOffset;
 		memcpy(ringBuffer + StartWriteOffset, Src, fragLen);
 		memcpy(ringBuffer, Src + fragLen, SrcLen - fragLen);
-	}
-	else
-	{
+	} else
 		memcpy(ringBuffer + StartWriteOffset, Src, SrcLen);
-	}
 
 	StartWriteOffset += SrcLen;
 	StartWriteOffset %= ringBufferSize;
@@ -573,28 +593,27 @@
 static u32
 CopyFromRingBuffer(
 	RING_BUFFER_INFO	*RingInfo,
-	void *				Dest,
+	void				*Dest,
 	u32				DestLen,
 	u32				StartReadOffset)
 {
-	void * ringBuffer=GetRingBuffer(RingInfo);
-	u32 ringBufferSize=GetRingBufferSize(RingInfo);
+	void *ringBuffer = GetRingBuffer(RingInfo);
+	u32 ringBufferSize = GetRingBufferSize(RingInfo);
 
 	u32 fragLen;
 
-	if (DestLen > ringBufferSize - StartReadOffset) /* wrap-around detected at the src */
-	{
+	/* wrap-around detected at the src */
+	if (DestLen > ringBufferSize - StartReadOffset) {
 		DPRINT_DBG(VMBUS, "src wrap-around detected!");
 
 		fragLen = ringBufferSize - StartReadOffset;
 
 		memcpy(Dest, ringBuffer + StartReadOffset, fragLen);
 		memcpy(Dest + fragLen, ringBuffer, DestLen - fragLen);
-	}
-	else
-	{
+	} else
+
 		memcpy(Dest, ringBuffer + StartReadOffset, DestLen);
-	}
+
 
 	StartReadOffset += DestLen;
 	StartReadOffset %= ringBufferSize;
diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
index 26d7997..1ab7fa9 100644
--- a/drivers/staging/hv/RndisFilter.c
+++ b/drivers/staging/hv/RndisFilter.c
@@ -85,10 +85,6 @@
 
 static void RndisFilterOnCleanup(struct hv_driver *Driver);
 
-static int RndisFilterOnOpen(struct hv_device *Device);
-
-static int RndisFilterOnClose(struct hv_device *Device);
-
 static int RndisFilterOnSend(struct hv_device *Device,
 			     struct hv_netvsc_packet *Packet);
 
@@ -654,8 +650,6 @@
 	Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
 	Driver->Base.OnCleanup = RndisFilterOnCleanup;
 	Driver->OnSend = RndisFilterOnSend;
-	Driver->OnOpen = RndisFilterOnOpen;
-	Driver->OnClose = RndisFilterOnClose;
 	/* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
 	Driver->OnReceiveCallback = RndisFilterOnReceive;
 
@@ -888,7 +882,7 @@
 	DPRINT_EXIT(NETVSC);
 }
 
-static int RndisFilterOnOpen(struct hv_device *Device)
+int RndisFilterOnOpen(struct hv_device *Device)
 {
 	int ret;
 	struct netvsc_device *netDevice = Device->Extension;
@@ -903,7 +897,7 @@
 	return ret;
 }
 
-static int RndisFilterOnClose(struct hv_device *Device)
+int RndisFilterOnClose(struct hv_device *Device)
 {
 	int ret;
 	struct netvsc_device *netDevice = Device->Extension;
diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
index 2f7c425..38ea140 100644
--- a/drivers/staging/hv/StorVsc.c
+++ b/drivers/staging/hv/StorVsc.c
@@ -625,7 +625,7 @@
 	return 0;
 }
 
-static int StorVscOnHostReset(struct hv_device *Device)
+int StorVscOnHostReset(struct hv_device *Device)
 {
 	struct storvsc_device *storDevice;
 	struct storvsc_request_extension *request;
@@ -842,7 +842,6 @@
 	storDriver->Base.OnCleanup	= StorVscOnCleanup;
 
 	storDriver->OnIORequest		= StorVscOnIORequest;
-	storDriver->OnHostReset		= StorVscOnHostReset;
 
 	DPRINT_EXIT(STORVSC);
 
diff --git a/drivers/staging/hv/StorVscApi.h b/drivers/staging/hv/StorVscApi.h
index 69c1406..126a858 100644
--- a/drivers/staging/hv/StorVscApi.h
+++ b/drivers/staging/hv/StorVscApi.h
@@ -91,13 +91,9 @@
 	/* Maximum # of requests in flight per channel/device */
 	u32 MaxOutstandingRequestsPerChannel;
 
-	/* Set by the caller to allow us to re-enumerate the bus on the host */
-	void (*OnHostRescan)(struct hv_device *Device);
-
 	/* Specific to this driver */
 	int (*OnIORequest)(struct hv_device *Device,
 			   struct hv_storvsc_request *Request);
-	int (*OnHostReset)(struct hv_device *Device);
 };
 
 struct storvsc_device_info {
@@ -108,6 +104,7 @@
 
 /* Interface */
 int StorVscInitialize(struct hv_driver *driver);
+int StorVscOnHostReset(struct hv_device *Device);
 int BlkVscInitialize(struct hv_driver *driver);
 
 #endif /* _STORVSC_API_H_ */
diff --git a/drivers/staging/hv/VersionInfo.h b/drivers/staging/hv/VersionInfo.h
index 9c3641d..10d7b19 100644
--- a/drivers/staging/hv/VersionInfo.h
+++ b/drivers/staging/hv/VersionInfo.h
@@ -24,8 +24,24 @@
 #ifndef __HV_VERSION_INFO
 #define __HV_VERSION_INFO
 
-static const char VersionDate[] = __DATE__;
-static const char VersionTime[] = __TIME__;
-static const char VersionDesc[] = "Version 2.0";
+/*
+ * We use the same version numbering for all Hyper-V modules.
+ *
+ * Definition of versioning is as follows;
+ *
+ * 	Major Number 	Changes for these scenarios;
+ *			1.	When a new version of Windows Hyper-V
+ *				is released.
+ *			2.	A Major change has occurred in the
+ *			       	Linux IC's.
+ *			(For example the merge for the first time
+ *			into the kernel) Every time the Major Number
+ *			changes, the Revision number is reset to 0.
+ *	Minor Number	Changes when new functionality is added
+ *			to the Linux IC's that is not a bug fix.
+ *
+ */
+#define HV_DRV_VERSION           "3.0"
+
 
 #endif
diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
index 35a023e..3d0a240 100644
--- a/drivers/staging/hv/Vmbus.c
+++ b/drivers/staging/hv/Vmbus.c
@@ -273,10 +273,8 @@
 
 	DPRINT_ENTER(VMBUS);
 
-	DPRINT_INFO(VMBUS, "+++++++ Build Date=%s %s +++++++",
-			VersionDate, VersionTime);
-	DPRINT_INFO(VMBUS, "+++++++ Build Description=%s +++++++",
-			VersionDesc);
+	DPRINT_INFO(VMBUS, "+++++++ HV Driver version = %s +++++++",
+		    HV_DRV_VERSION);
 	DPRINT_INFO(VMBUS, "+++++++ Vmbus supported version = %d +++++++",
 			VMBUS_REVISION_NUMBER);
 	DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++",
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index 45d9081..abeac12 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -31,6 +31,7 @@
 #include <scsi/scsi_dbg.h>
 #include "osd.h"
 #include "logging.h"
+#include "VersionInfo.h"
 #include "vmbus.h"
 #include "StorVscApi.h"
 
@@ -92,7 +93,7 @@
 /* Per device structure */
 struct block_device_context {
 	/* point back to our device context */
-	struct device_context *device_ctx;
+	struct vm_device *device_ctx;
 	struct kmem_cache *request_pool;
 	spinlock_t lock;
 	struct gendisk *gd;
@@ -254,7 +255,7 @@
 				(struct blkvsc_driver_context *)driver_ctx;
 	struct storvsc_driver_object *storvsc_drv_obj =
 				&blkvsc_drv_ctx->drv_obj;
-	struct device_context *device_ctx = device_to_device_context(device);
+	struct vm_device *device_ctx = device_to_vm_device(device);
 	struct hv_device *device_obj = &device_ctx->device_obj;
 
 	struct block_device_context *blkdev = NULL;
@@ -742,7 +743,7 @@
 				(struct blkvsc_driver_context *)driver_ctx;
 	struct storvsc_driver_object *storvsc_drv_obj =
 				&blkvsc_drv_ctx->drv_obj;
-	struct device_context *device_ctx = device_to_device_context(device);
+	struct vm_device *device_ctx = device_to_vm_device(device);
 	struct hv_device *device_obj = &device_ctx->device_obj;
 	struct block_device_context *blkdev = dev_get_drvdata(device);
 	unsigned long flags;
@@ -862,7 +863,7 @@
 			void (*request_completion)(struct hv_storvsc_request *))
 {
 	struct block_device_context *blkdev = blkvsc_req->dev;
-	struct device_context *device_ctx = blkdev->device_ctx;
+	struct vm_device *device_ctx = blkdev->device_ctx;
 	struct driver_context *driver_ctx =
 			driver_to_driver_context(device_ctx->device.driver);
 	struct blkvsc_driver_context *blkvsc_drv_ctx =
@@ -1504,6 +1505,7 @@
 }
 
 MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
 module_param(blkvsc_ringbuffer_size, int, S_IRUGO);
 module_init(blkvsc_init);
 module_exit(blkvsc_exit);
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 0d7459e..1af3dcb 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -35,14 +35,13 @@
 #include <net/pkt_sched.h>
 #include "osd.h"
 #include "logging.h"
+#include "VersionInfo.h"
 #include "vmbus.h"
 #include "NetVscApi.h"
 
-MODULE_LICENSE("GPL");
-
 struct net_device_context {
 	/* point back to our device context */
-	struct device_context *device_ctx;
+	struct vm_device *device_ctx;
 	struct net_device_stats stats;
 };
 
@@ -72,11 +71,6 @@
 static int netvsc_open(struct net_device *net)
 {
 	struct net_device_context *net_device_ctx = netdev_priv(net);
-	struct driver_context *driver_ctx =
-	    driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
-	struct netvsc_driver_context *net_drv_ctx =
-		(struct netvsc_driver_context *)driver_ctx;
-	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
 	struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
 	int ret = 0;
 
@@ -87,7 +81,7 @@
 		       sizeof(struct net_device_stats));
 
 		/* Open up the device */
-		ret = net_drv_obj->OnOpen(device_obj);
+		ret = RndisFilterOnOpen(device_obj);
 		if (ret != 0) {
 			DPRINT_ERR(NETVSC_DRV,
 				   "unable to open device (ret %d).", ret);
@@ -106,11 +100,6 @@
 static int netvsc_close(struct net_device *net)
 {
 	struct net_device_context *net_device_ctx = netdev_priv(net);
-	struct driver_context *driver_ctx =
-	    driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
-	struct netvsc_driver_context *net_drv_ctx =
-		(struct netvsc_driver_context *)driver_ctx;
-	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
 	struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
 	int ret;
 
@@ -118,7 +107,7 @@
 
 	netif_stop_queue(net);
 
-	ret = net_drv_obj->OnClose(device_obj);
+	ret = RndisFilterOnClose(device_obj);
 	if (ret != 0)
 		DPRINT_ERR(NETVSC_DRV, "unable to close device (ret %d).", ret);
 
@@ -282,7 +271,7 @@
 static void netvsc_linkstatus_callback(struct hv_device *device_obj,
 				       unsigned int status)
 {
-	struct device_context *device_ctx = to_device_context(device_obj);
+	struct vm_device *device_ctx = to_vm_device(device_obj);
 	struct net_device *net = dev_get_drvdata(&device_ctx->device);
 
 	DPRINT_ENTER(NETVSC_DRV);
@@ -309,7 +298,7 @@
 static int netvsc_recv_callback(struct hv_device *device_obj,
 				struct hv_netvsc_packet *packet)
 {
-	struct device_context *device_ctx = to_device_context(device_obj);
+	struct vm_device *device_ctx = to_vm_device(device_obj);
 	struct net_device *net = dev_get_drvdata(&device_ctx->device);
 	struct net_device_context *net_device_ctx;
 	struct sk_buff *skb;
@@ -401,7 +390,7 @@
 	struct netvsc_driver_context *net_drv_ctx =
 		(struct netvsc_driver_context *)driver_ctx;
 	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
-	struct device_context *device_ctx = device_to_device_context(device);
+	struct vm_device *device_ctx = device_to_vm_device(device);
 	struct hv_device *device_obj = &device_ctx->device_obj;
 	struct net_device *net = NULL;
 	struct net_device_context *net_device_ctx;
@@ -473,7 +462,7 @@
 	struct netvsc_driver_context *net_drv_ctx =
 		(struct netvsc_driver_context *)driver_ctx;
 	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
-	struct device_context *device_ctx = device_to_device_context(device);
+	struct vm_device *device_ctx = device_to_vm_device(device);
 	struct net_device *net = dev_get_drvdata(&device_ctx->device);
 	struct hv_device *device_obj = &device_ctx->device_obj;
 	int ret;
@@ -613,6 +602,8 @@
 	DPRINT_EXIT(NETVSC_DRV);
 }
 
+MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
 module_param(netvsc_ringbuffer_size, int, S_IRUGO);
 
 module_init(netvsc_init);
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index d49dc21..3988f4b 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -32,6 +32,7 @@
 #include <scsi/scsi_dbg.h>
 #include "osd.h"
 #include "logging.h"
+#include "VersionInfo.h"
 #include "vmbus.h"
 #include "StorVscApi.h"
 
@@ -39,10 +40,8 @@
 struct host_device_context {
 	/* must be 1st field
 	 * FIXME this is a bug */
-	struct work_struct host_rescan_work;
-
 	/* point back to our device context */
-	struct device_context *device_ctx;
+	struct vm_device *device_ctx;
 	struct kmem_cache *request_pool;
 	unsigned int port;
 	unsigned char path;
@@ -77,8 +76,6 @@
 static int storvsc_device_alloc(struct scsi_device *);
 static int storvsc_device_configure(struct scsi_device *);
 static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd);
-static void storvsc_host_rescan_callback(struct work_struct *work);
-static void storvsc_host_rescan(struct hv_device *device_obj);
 static int storvsc_remove(struct device *dev);
 
 static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
@@ -94,8 +91,6 @@
 					  struct scatterlist *bounce_sgl,
 					  unsigned int orig_sgl_count);
 
-static int storvsc_report_luns(struct scsi_device *sdev, unsigned int luns[],
-			       unsigned int *lun_count);
 static int storvsc_get_chs(struct scsi_device *sdev, struct block_device *bdev,
 			   sector_t capacity, int *info);
 
@@ -148,7 +143,6 @@
 	vmbus_get_interface(&storvsc_drv_obj->Base.VmbusChannelInterface);
 
 	storvsc_drv_obj->RingBufferSize = storvsc_ringbuffer_size;
-	storvsc_drv_obj->OnHostRescan = storvsc_host_rescan;
 
 	/* Callback to client driver to complete the initialization */
 	drv_init(&storvsc_drv_obj->Base);
@@ -240,7 +234,7 @@
 				(struct storvsc_driver_context *)driver_ctx;
 	struct storvsc_driver_object *storvsc_drv_obj =
 				&storvsc_drv_ctx->drv_obj;
-	struct device_context *device_ctx = device_to_device_context(device);
+	struct vm_device *device_ctx = device_to_vm_device(device);
 	struct hv_device *device_obj = &device_ctx->device_obj;
 	struct Scsi_Host *host;
 	struct host_device_context *host_device_ctx;
@@ -266,9 +260,6 @@
 	host_device_ctx->port = host->host_no;
 	host_device_ctx->device_ctx = device_ctx;
 
-	INIT_WORK(&host_device_ctx->host_rescan_work,
-		  storvsc_host_rescan_callback);
-
 	host_device_ctx->request_pool =
 				kmem_cache_create(dev_name(&device_ctx->device),
 					sizeof(struct storvsc_cmd_request) +
@@ -339,7 +330,7 @@
 			(struct storvsc_driver_context *)driver_ctx;
 	struct storvsc_driver_object *storvsc_drv_obj =
 			&storvsc_drv_ctx->drv_obj;
-	struct device_context *device_ctx = device_to_device_context(device);
+	struct vm_device *device_ctx = device_to_vm_device(device);
 	struct hv_device *device_obj = &device_ctx->device_obj;
 	struct Scsi_Host *host = dev_get_drvdata(device);
 	struct host_device_context *host_device_ctx =
@@ -640,7 +631,7 @@
 	int ret;
 	struct host_device_context *host_device_ctx =
 		(struct host_device_context *)scmnd->device->host->hostdata;
-	struct device_context *device_ctx = host_device_ctx->device_ctx;
+	struct vm_device *device_ctx = host_device_ctx->device_ctx;
 	struct driver_context *driver_ctx =
 		driver_to_driver_context(device_ctx->device.driver);
 	struct storvsc_driver_context *storvsc_drv_ctx =
@@ -879,14 +870,7 @@
 	int ret;
 	struct host_device_context *host_device_ctx =
 		(struct host_device_context *)scmnd->device->host->hostdata;
-	struct device_context *device_ctx = host_device_ctx->device_ctx;
-	struct driver_context *driver_ctx =
-			driver_to_driver_context(device_ctx->device.driver);
-	struct storvsc_driver_context *storvsc_drv_ctx =
-			(struct storvsc_driver_context *)driver_ctx;
-
-	struct storvsc_driver_object *storvsc_drv_obj =
-			&storvsc_drv_ctx->drv_obj;
+	struct vm_device *device_ctx = host_device_ctx->device_ctx;
 
 	DPRINT_ENTER(STORVSC_DRV);
 
@@ -894,8 +878,7 @@
 		    scmnd->device, &device_ctx->device_obj);
 
 	/* Invokes the vsc to reset the host/bus */
-	ASSERT(storvsc_drv_obj->OnHostReset);
-	ret = storvsc_drv_obj->OnHostReset(&device_ctx->device_obj);
+	ret = StorVscOnHostReset(&device_ctx->device_obj);
 	if (ret != 0) {
 		DPRINT_EXIT(STORVSC_DRV);
 		return ret;
@@ -909,201 +892,6 @@
 	return ret;
 }
 
-/**
- * storvsc_host_rescan - Rescan the scsi HBA
- */
-static void storvsc_host_rescan_callback(struct work_struct *work)
-{
-	struct hv_device *device_obj =
-	    &((struct host_device_context *)work)->device_ctx->device_obj;
-	struct device_context *device_ctx = to_device_context(device_obj);
-	struct Scsi_Host *host = dev_get_drvdata(&device_ctx->device);
-	struct scsi_device *sdev;
-	struct host_device_context *host_device_ctx;
-	struct scsi_device **sdevs_remove_list;
-	unsigned int sdevs_count = 0;
-	unsigned int found;
-	unsigned int i;
-	unsigned int lun_count = 0;
-	unsigned int *lun_list;
-
-	DPRINT_ENTER(STORVSC_DRV);
-
-	host_device_ctx = (struct host_device_context *)host->hostdata;
-	lun_list = kcalloc(STORVSC_MAX_LUNS_PER_TARGET, sizeof(unsigned int),
-			   GFP_ATOMIC);
-	if (!lun_list) {
-		DPRINT_ERR(STORVSC_DRV, "unable to allocate lun list");
-		return;
-	}
-
-	sdevs_remove_list = kcalloc(STORVSC_MAX_LUNS_PER_TARGET,
-				    sizeof(void *), GFP_ATOMIC);
-	if (!sdevs_remove_list) {
-		kfree(lun_list);
-		DPRINT_ERR(STORVSC_DRV, "unable to allocate lun remove list");
-		return;
-	}
-
-	DPRINT_INFO(STORVSC_DRV, "rescanning host for new scsi devices...");
-
-	/* Rescan for new device */
-	scsi_scan_target(&host->shost_gendev, host_device_ctx->path,
-			 host_device_ctx->target, SCAN_WILD_CARD, 1);
-
-	DPRINT_INFO(STORVSC_DRV, "rescanning host for removed scsi device...");
-
-	/* Use the 1st device to send the report luns cmd */
-	shost_for_each_device(sdev, host) {
-		lun_count = STORVSC_MAX_LUNS_PER_TARGET;
-		storvsc_report_luns(sdev, lun_list, &lun_count);
-
-		DPRINT_INFO(STORVSC_DRV,
-			    "report luns on scsi device (%p) found %u luns ",
-			    sdev, lun_count);
-		DPRINT_INFO(STORVSC_DRV,
-			    "existing luns on scsi device (%p) host (%d)",
-			    sdev, host->host_no);
-
-		scsi_device_put(sdev);
-		break;
-	}
-
-	for (i = 0; i < lun_count; i++)
-		DPRINT_INFO(STORVSC_DRV, "%d) lun %u", i, lun_list[i]);
-
-	/* Rescan for devices that may have been removed.
-	 * We do not have to worry that new devices may have been added since
-	 * this callback is serialized by the workqueue ie add/remove are done
-	 * here.
-	 */
-	shost_for_each_device(sdev, host) {
-		/* See if this device is still here */
-		found = 0;
-		for (i = 0; i < lun_count; i++) {
-			if (sdev->lun == lun_list[i]) {
-				found = 1;
-				break;
-			}
-		}
-		if (!found) {
-			DPRINT_INFO(STORVSC_DRV, "lun (%u) does not exists",
-				    sdev->lun);
-			sdevs_remove_list[sdevs_count++] = sdev;
-		}
-	}
-
-	/* Now remove the devices */
-	for (i = 0; i < sdevs_count; i++) {
-		DPRINT_INFO(STORVSC_DRV,
-			    "removing scsi device (%p) lun (%u)...",
-			    sdevs_remove_list[i], sdevs_remove_list[i]->lun);
-
-		/* make sure it is not removed from underneath us */
-		if (!scsi_device_get(sdevs_remove_list[i])) {
-			scsi_remove_device(sdevs_remove_list[i]);
-			scsi_device_put(sdevs_remove_list[i]);
-		}
-	}
-
-	DPRINT_INFO(STORVSC_DRV, "rescan completed on dev obj (%p) "
-		    "target (%u) bus (%u)", device_obj,
-		    host_device_ctx->target, host_device_ctx->path);
-
-	kfree(lun_list);
-	kfree(sdevs_remove_list);
-
-	DPRINT_EXIT(STORVSC_DRV);
-}
-
-static int storvsc_report_luns(struct scsi_device *sdev, unsigned int luns[],
-			       unsigned int *lun_count)
-{
-	int i, j;
-	unsigned int lun = 0;
-	unsigned int num_luns;
-	int result;
-	unsigned char *data;
-	struct scsi_sense_hdr sshdr;
-	unsigned char cmd[16] = {0};
-	/* Add 1 to cover the report_lun header */
-	unsigned int report_len = 8 * (STORVSC_MAX_LUNS_PER_TARGET+1);
-	unsigned long long *report_luns;
-	const unsigned int in_lun_count = *lun_count;
-
-	*lun_count = 0;
-
-	report_luns = kzalloc(report_len, GFP_ATOMIC);
-	if (!report_luns)
-		return -ENOMEM;
-
-	cmd[0] = REPORT_LUNS;
-
-	/* cmd length */
-	*(unsigned int *)&cmd[6] = cpu_to_be32(report_len);
-
-	result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE,
-				  (unsigned char *)report_luns, report_len,
-				  &sshdr, 30 * HZ, 3, NULL);
-	if (result != 0) {
-		kfree(report_luns);
-		return -EBUSY;
-	}
-
-	/* get the length from the first four bytes */
-	report_len = be32_to_cpu(*(unsigned int *)&report_luns[0]);
-
-	num_luns = (report_len / sizeof(unsigned long long));
-	if (num_luns > in_lun_count) {
-		kfree(report_luns);
-		return -EINVAL;
-	}
-
-	*lun_count = num_luns;
-
-	DPRINT_DBG(STORVSC_DRV,
-		   "report luns on scsi device (%p) found %u luns ",
-		   sdev, num_luns);
-
-	/* lun id starts at 1 */
-	for (i = 1; i < num_luns + 1; i++) {
-		lun = 0;
-		data = (unsigned char *)&report_luns[i];
-		for (j = 0; j < sizeof(lun); j += 2) {
-			lun = lun | (((data[j] << 8) | data[j + 1]) <<
-				(j * 8));
-		}
-
-		luns[i-1] = lun;
-	}
-
-	kfree(report_luns);
-	return 0;
-}
-
-static void storvsc_host_rescan(struct hv_device *device_obj)
-{
-	struct device_context *device_ctx = to_device_context(device_obj);
-	struct Scsi_Host *host = dev_get_drvdata(&device_ctx->device);
-	struct host_device_context *host_device_ctx;
-
-	DPRINT_ENTER(STORVSC_DRV);
-
-	host_device_ctx = (struct host_device_context *)host->hostdata;
-
-	DPRINT_INFO(STORVSC_DRV, "initiating rescan on dev obj (%p) "
-		    "target (%u) bus (%u)...", device_obj,
-		    host_device_ctx->target, host_device_ctx->path);
-
-	/*
-	 * We need to queue this since the scanning may block and the caller
-	 * may be in an intr context
-	 */
-	/* scsi_queue_work(host, &host_device_ctx->host_rescan_work); */
-	schedule_work(&host_device_ctx->host_rescan_work);
-	DPRINT_EXIT(STORVSC_DRV);
-}
-
 static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
 			   sector_t capacity, int *info)
 {
@@ -1203,6 +991,7 @@
 }
 
 MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
 module_param(storvsc_ringbuffer_size, int, S_IRUGO);
 module_init(storvsc_init);
 module_exit(storvsc_exit);
diff --git a/drivers/staging/hv/vmbus.h b/drivers/staging/hv/vmbus.h
index ae0a896..6404b84 100644
--- a/drivers/staging/hv/vmbus.h
+++ b/drivers/staging/hv/vmbus.h
@@ -43,23 +43,23 @@
 	void (*shutdown)(struct device *);
 };
 
-struct device_context {
+struct vm_device {
 	struct work_struct probe_failed_work_item;
 	struct hv_guid class_id;
 	struct hv_guid device_id;
 	int probe_error;
-	struct device device;
 	struct hv_device device_obj;
+	struct device device;
 };
 
-static inline struct device_context *to_device_context(struct hv_device *d)
+static inline struct vm_device *to_vm_device(struct hv_device *d)
 {
-	return container_of(d, struct device_context, device_obj);
+	return container_of(d, struct vm_device, device_obj);
 }
 
-static inline struct device_context *device_to_device_context(struct device *d)
+static inline struct vm_device *device_to_vm_device(struct device *d)
 {
-	return container_of(d, struct device_context, device);
+	return container_of(d, struct vm_device, device);
 }
 
 static inline struct driver_context *driver_to_driver_context(struct device_driver *d)
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index 894eecf..2c90619 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -24,6 +24,9 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
+#include <linux/pci.h>
+#include <linux/dmi.h>
+#include "VersionInfo.h"
 #include "osd.h"
 #include "logging.h"
 #include "vmbus.h"
@@ -47,7 +50,7 @@
 	struct tasklet_struct event_dpc;
 
 	/* The bus root device */
-	struct device_context device_ctx;
+	struct vm_device device_ctx;
 };
 
 static int vmbus_match(struct device *device, struct device_driver *driver);
@@ -135,7 +138,7 @@
 				      struct device_attribute *dev_attr,
 				      char *buf)
 {
-	struct device_context *device_ctx = device_to_device_context(dev);
+	struct vm_device *device_ctx = device_to_vm_device(dev);
 	struct hv_device_info device_info;
 
 	memset(&device_info, 0, sizeof(struct hv_device_info));
@@ -245,7 +248,7 @@
 {
 	struct vmbus_driver_context *vmbus_drv_ctx = &g_vmbus_drv;
 	struct vmbus_driver *vmbus_drv_obj = &g_vmbus_drv.drv_obj;
-	struct device_context *dev_ctx = &g_vmbus_drv.device_ctx;
+	struct vm_device *dev_ctx = &g_vmbus_drv.device_ctx;
 	int ret;
 	unsigned int vector;
 
@@ -307,7 +310,7 @@
 	DPRINT_INFO(VMBUS_DRV, "irq 0x%x vector 0x%x", vmbus_irq, vector);
 
 	/* Call to bus driver to add the root device */
-	memset(dev_ctx, 0, sizeof(struct device_context));
+	memset(dev_ctx, 0, sizeof(struct vm_device));
 
 	ret = vmbus_drv_obj->Base.OnDeviceAdd(&dev_ctx->device_obj, &vector);
 	if (ret != 0) {
@@ -368,7 +371,7 @@
 	struct vmbus_driver *vmbus_drv_obj = &g_vmbus_drv.drv_obj;
 	struct vmbus_driver_context *vmbus_drv_ctx = &g_vmbus_drv;
 
-	struct device_context *dev_ctx = &g_vmbus_drv.device_ctx;
+	struct vm_device *dev_ctx = &g_vmbus_drv.device_ctx;
 
 	DPRINT_ENTER(VMBUS_DRV);
 
@@ -471,13 +474,13 @@
 						   struct hv_guid *instance,
 						   void *context)
 {
-	struct device_context *child_device_ctx;
+	struct vm_device *child_device_ctx;
 	struct hv_device *child_device_obj;
 
 	DPRINT_ENTER(VMBUS_DRV);
 
 	/* Allocate the new child device */
-	child_device_ctx = kzalloc(sizeof(struct device_context), GFP_KERNEL);
+	child_device_ctx = kzalloc(sizeof(struct vm_device), GFP_KERNEL);
 	if (!child_device_ctx) {
 		DPRINT_ERR(VMBUS_DRV,
 			"unable to allocate device_context for child device");
@@ -526,10 +529,10 @@
 				       struct hv_device *child_device_obj)
 {
 	int ret = 0;
-	struct device_context *root_device_ctx =
-				to_device_context(root_device_obj);
-	struct device_context *child_device_ctx =
-				to_device_context(child_device_obj);
+	struct vm_device *root_device_ctx =
+				to_vm_device(root_device_obj);
+	struct vm_device *child_device_ctx =
+				to_vm_device(child_device_obj);
 	static atomic_t device_num = ATOMIC_INIT(0);
 
 	DPRINT_ENTER(VMBUS_DRV);
@@ -572,7 +575,7 @@
  */
 static void vmbus_child_device_unregister(struct hv_device *device_obj)
 {
-	struct device_context *device_ctx = to_device_context(device_obj);
+	struct vm_device *device_ctx = to_vm_device(device_obj);
 
 	DPRINT_ENTER(VMBUS_DRV);
 
@@ -610,7 +613,7 @@
  */
 static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
 {
-	struct device_context *device_ctx = device_to_device_context(device);
+	struct vm_device *device_ctx = device_to_vm_device(device);
 	int ret;
 
 	DPRINT_ENTER(VMBUS_DRV);
@@ -687,7 +690,7 @@
 {
 	int match = 0;
 	struct driver_context *driver_ctx = driver_to_driver_context(driver);
-	struct device_context *device_ctx = device_to_device_context(device);
+	struct vm_device *device_ctx = device_to_vm_device(device);
 
 	DPRINT_ENTER(VMBUS_DRV);
 
@@ -724,7 +727,7 @@
  */
 static void vmbus_probe_failed_cb(struct work_struct *context)
 {
-	struct device_context *device_ctx = (struct device_context *)context;
+	struct vm_device *device_ctx = (struct vm_device *)context;
 
 	DPRINT_ENTER(VMBUS_DRV);
 
@@ -746,8 +749,8 @@
 	int ret = 0;
 	struct driver_context *driver_ctx =
 			driver_to_driver_context(child_device->driver);
-	struct device_context *device_ctx =
-			device_to_device_context(child_device);
+	struct vm_device *device_ctx =
+			device_to_vm_device(child_device);
 
 	DPRINT_ENTER(VMBUS_DRV);
 
@@ -871,7 +874,7 @@
  */
 static void vmbus_device_release(struct device *device)
 {
-	struct device_context *device_ctx = device_to_device_context(device);
+	struct vm_device *device_ctx = device_to_vm_device(device);
 
 	DPRINT_ENTER(VMBUS_DRV);
 
@@ -946,6 +949,19 @@
 	}
 }
 
+static struct dmi_system_id __initdata microsoft_hv_dmi_table[] = {
+	{
+		.ident = "Hyper-V",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+			DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+		},
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(dmi, microsoft_hv_dmi_table);
+
 static int __init vmbus_init(void)
 {
 	int ret = 0;
@@ -957,6 +973,9 @@
 		vmbus_loglevel, HIWORD(vmbus_loglevel), LOWORD(vmbus_loglevel));
 	/* Todo: it is used for loglevel, to be ported to new kernel. */
 
+	if (!dmi_check_system(microsoft_hv_dmi_table))
+		return -ENODEV;
+
 	ret = vmbus_bus_init(VmbusInitialize);
 
 	DPRINT_EXIT(VMBUS_DRV);
@@ -973,7 +992,20 @@
 	return;
 }
 
+/*
+ * We use a PCI table to determine if we should autoload this driver  This is
+ * needed by distro tools to determine if the hyperv drivers should be
+ * installed and/or configured.  We don't do anything else with the table, but
+ * it needs to be present.
+ */
+const static struct pci_device_id microsoft_hv_pci_table[] = {
+	{ PCI_DEVICE(0x1414, 0x5353) },	/* VGA compatible controller */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
+
 MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
 module_param(vmbus_irq, int, S_IRUGO);
 module_param(vmbus_loglevel, int, S_IRUGO);
 
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 768f448..b456dfc 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -79,11 +79,14 @@
 	/* Does anyone care? */
 	mutex_lock(&ev_int->event_list_lock);
 	if (test_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags)) {
-		if (ev_int->current_events == ev_int->max_events)
+		if (ev_int->current_events == ev_int->max_events) {
+			mutex_unlock(&ev_int->event_list_lock);
 			return 0;
+		}
 		ev = kmalloc(sizeof(*ev), GFP_KERNEL);
 		if (ev == NULL) {
 			ret = -ENOMEM;
+			mutex_unlock(&ev_int->event_list_lock);
 			goto error_ret;
 		}
 		ev->ev.id = ev_code;
@@ -115,7 +118,7 @@
 EXPORT_SYMBOL(iio_push_event);
 
 /* Generic interrupt line interrupt handler */
-irqreturn_t iio_interrupt_handler(int irq, void *_int_info)
+static irqreturn_t iio_interrupt_handler(int irq, void *_int_info)
 {
 	struct iio_interrupt *int_info = _int_info;
 	struct iio_dev *dev_info = int_info->dev_info;
@@ -249,10 +252,10 @@
 }
 EXPORT_SYMBOL(iio_remove_event_from_list);
 
-ssize_t iio_event_chrdev_read(struct file *filep,
-			      char *buf,
-			      size_t count,
-			      loff_t *f_ps)
+static ssize_t iio_event_chrdev_read(struct file *filep,
+				     char __user *buf,
+				     size_t count,
+				     loff_t *f_ps)
 {
 	struct iio_event_interface *ev_int = filep->private_data;
 	struct iio_detected_event_list *el;
@@ -289,16 +292,16 @@
 	mutex_unlock(&ev_int->event_list_lock);
 	/*
 	 * Possible concurency issue if an update of this event is on its way
-	 * through. May lead to new even being removed whilst the reported event
-	 * was the unescalated event. In typical use case this is not a problem
-	 * as userspace will say read half the buffer due to a 50% full event
-	 * which would make the correct 100% full incorrect anyway.
+	 * through. May lead to new event being removed whilst the reported
+	 * event was the unescalated event. In typical use case this is not a
+	 * problem as userspace will say read half the buffer due to a 50%
+	 * full event which would make the correct 100% full incorrect anyway.
 	 */
-	spin_lock(&el->shared_pointer->lock);
-	if (el->shared_pointer)
+	if (el->shared_pointer) {
+		spin_lock(&el->shared_pointer->lock);
 		(el->shared_pointer->ev_p) = NULL;
-	spin_unlock(&el->shared_pointer->lock);
-
+		spin_unlock(&el->shared_pointer->lock);
+	}
 	kfree(el);
 
 	return len;
@@ -310,7 +313,7 @@
 	return ret;
 }
 
-int iio_event_chrdev_release(struct inode *inode, struct file *filep)
+static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
 {
 	struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev);
 	struct iio_event_interface *ev_int = hand->private;
@@ -332,7 +335,7 @@
 	return 0;
 }
 
-int iio_event_chrdev_open(struct inode *inode, struct file *filep)
+static int iio_event_chrdev_open(struct inode *inode, struct file *filep)
 {
 	struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev);
 	struct iio_event_interface *ev_int = hand->private;
diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h
index 93b91b2..09044ad 100644
--- a/drivers/staging/iio/ring_generic.h
+++ b/drivers/staging/iio/ring_generic.h
@@ -146,8 +146,7 @@
 	ring->length = length;
 	ring->loopcount = 0;
 	ring->shared_ev_pointer.ev_p = 0;
-	ring->shared_ev_pointer.lock =
-		__SPIN_LOCK_UNLOCKED(ring->shared_ev_pointer->loc);
+	spin_lock_init(&ring->shared_ev_pointer.lock);
 }
 
 /**
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index 359ff92..6f7f4d5 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -8,7 +8,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/device.h>
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/workqueue.h>
@@ -21,7 +20,7 @@
 		return -EINVAL;
 
 	__iio_init_ring_buffer(&ring->buf, bytes_per_datum, length);
-	ring->use_lock = __SPIN_LOCK_UNLOCKED((ring)->use_lock);
+	spin_lock_init(&ring->use_lock);
 	ring->data = kmalloc(length*ring->buf.bpd, GFP_KERNEL);
 	ring->read_p = 0;
 	ring->write_p = 0;
diff --git a/drivers/staging/iio/trigger_consumer.h b/drivers/staging/iio/trigger_consumer.h
index a02d70b..9d52d96 100644
--- a/drivers/staging/iio/trigger_consumer.h
+++ b/drivers/staging/iio/trigger_consumer.h
@@ -27,7 +27,7 @@
  * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers
  * @dev_info: iio_dev associated with the device that will consume the trigger
  **/
-int iio_device_register_trigger_consumer(struct iio_dev *dev_info)
+static int iio_device_register_trigger_consumer(struct iio_dev *dev_info)
 {
 	return 0;
 };
@@ -36,7 +36,7 @@
  * iio_device_unregister_trigger_consumer() - reverse the registration process
  * @dev_info: iio_dev associated with the device that consumed the trigger
  **/
-int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info)
+static int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info)
 {
 	return 0;
 };
diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c
index e4078a9..0392a4b 100644
--- a/drivers/staging/line6/driver.c
+++ b/drivers/staging/line6/driver.c
@@ -33,7 +33,7 @@
 
 
 /* table of devices that work with this driver */
-static struct usb_device_id line6_id_table[] = {
+static const struct usb_device_id line6_id_table[] = {
 	{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXT) },
 	{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTLIVE) },
 	{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTPRO) },
diff --git a/drivers/staging/line6/variax.c b/drivers/staging/line6/variax.c
index 48d834b..58fef82 100644
--- a/drivers/staging/line6/variax.c
+++ b/drivers/staging/line6/variax.c
@@ -254,7 +254,7 @@
 	if (ret)
 		return ret;
 
-	variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = value ? 1: 0;
+	variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = value ? 1 : 0;
 	line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
 				     sizeof(variax_activate));
 	return count;
diff --git a/drivers/staging/mimio/Kconfig b/drivers/staging/mimio/Kconfig
deleted file mode 100644
index 505dcb2..0000000
--- a/drivers/staging/mimio/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config INPUT_MIMIO
-	tristate "Mimio Xi interactive whiteboard support"
-	depends on USB && INPUT
-	default N
-	help
-	  Say Y here if you want to use a Mimio Xi interactive
-	  whiteboard device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called mimio.
diff --git a/drivers/staging/mimio/Makefile b/drivers/staging/mimio/Makefile
deleted file mode 100644
index 77807ee..0000000
--- a/drivers/staging/mimio/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_INPUT_MIMIO)	+= mimio.o
diff --git a/drivers/staging/mimio/mimio.c b/drivers/staging/mimio/mimio.c
deleted file mode 100644
index 1ba8103..0000000
--- a/drivers/staging/mimio/mimio.c
+++ /dev/null
@@ -1,914 +0,0 @@
-/*
- * Hardware event => input event mapping:
- *
- *
- *
- input.h:#define BTN_TOOL_PEN            0x140 black
- input.h:#define BTN_TOOL_RUBBER         0x141 blue
- input.h:#define BTN_TOOL_BRUSH          0x142 green
- input.h:#define BTN_TOOL_PENCIL         0x143 red
- input.h:#define BTN_TOOL_AIRBRUSH       0x144 eraser
- input.h:#define BTN_TOOL_FINGER         0x145 small eraser
- input.h:#define BTN_TOOL_MOUSE          0x146 mimio interactive
- input.h:#define BTN_TOOL_LENS           0x147 mimio interactive but1
- input.h:#define LOCALBTN_TOOL_EXTRA1    0x14a mimio interactive but2 == BTN_TOUCH
- input.h:#define LOCALBTN_TOOL_EXTRA2    0x14b mimio extra pens (orange, brown, yellow, purple) == BTN_STYLUS
- input.h:#define LOCALBTN_TOOL_EXTRA3    0x14c unused == BTN_STYLUS2
- input.h:#define BTN_TOOL_DOUBLETAP      0x14d unused
- input.h:#define BTN_TOOL_TRIPLETAP      0x14e unused
- *
- * MIMIO_EV_PENDOWN(MIMIO_PEN_K)     => EV_KEY BIT(BTN_TOOL_PEN)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_B)     => EV_KEY BIT(BTN_TOOL_RUBBER)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_G)     => EV_KEY BIT(BTN_TOOL_BRUSH)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_R)     => EV_KEY BIT(BTN_TOOL_PENCIL)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_E)     => EV_KEY BIT(BTN_TOOL_AIRBRUSH)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_ES)    => EV_KEY BIT(BTN_TOOL_FINGER)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_I)     => EV_KEY BIT(BTN_TOOL_MOUSE)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_IL)    => EV_KEY BIT(BTN_TOOL_LENS)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_IR)    => EV_KEY BIT(BTN_TOOL_DOUBLETAP)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_EX)    => EV_KEY BIT(BTN_TOOL_TRIPLETAP)
- * MIMIO_EV_PENDATA                 => EV_ABS BIT(ABS_X), BIT(ABS_Y)
- * MIMIO_EV_MEMRESET              => EV_KEY BIT(BTN_0)
- * MIMIO_EV_ACC(ACC_NEWPAGE)       => EV_KEY BIT(BTN_1)
- * MIMIO_EV_ACC(ACC_TAGPAGE)      => EV_KEY BIT(BTN_2)
- * MIMIO_EV_ACC(ACC_PRINTPAGE)      => EV_KEY BIT(BTN_3)
- * MIMIO_EV_ACC(ACC_MAXIMIZE)      => EV_KEY BIT(BTN_4)
- * MIMIO_EV_ACC(ACC_FINDCTLPNL)      => EV_KEY BIT(BTN_5)
- *
- *
- * open issues:
- *      - cold-load of data captured when mimio in standalone mode not yet
- *         supported; need to snoop Win32 box to see datastream for this.
- *       - mimio mouse not yet supported; need to snoop Win32 box to see the
- *         datastream for this.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-
-#define DRIVER_VERSION		"v0.031"
-#define DRIVER_AUTHOR		"mwilder@cs.nmsu.edu"
-#define DRIVER_DESC		"USB mimio-xi driver"
-
-enum {UPVALUE, DOWNVALUE, MOVEVALUE};
-
-#define MIMIO_XRANGE_MAX	9600
-#define MIMIO_YRANGE_MAX	4800
-
-#define LOCALBTN_TOOL_EXTRA1	BTN_TOUCH
-#define LOCALBTN_TOOL_EXTRA2	BTN_STYLUS
-#define LOCALBTN_TOOL_EXTRA3	BTN_STYLUS2
-
-#define MIMIO_VENDOR_ID		0x08d3
-#define MIMIO_PRODUCT_ID	0x0001
-#define MIMIO_MAXPAYLOAD	(8)
-#define MIMIO_MAXNAMELEN	(64)
-#define MIMIO_TXWAIT		(1)
-#define MIMIO_TXDONE		(2)
-
-#define MIMIO_EV_PENDOWN	(0x22)
-#define MIMIO_EV_PENDATA	(0x24)
-#define MIMIO_EV_PENUP		(0x51)
-#define MIMIO_EV_MEMRESET	(0x45)
-#define MIMIO_EV_ACC		(0xb2)
-
-#define MIMIO_PEN_K		(1)	/* black pen */
-#define MIMIO_PEN_B		(2)	/* blue pen */
-#define MIMIO_PEN_G		(3)	/* green pen */
-#define MIMIO_PEN_R		(4)	/* red pen */
-/* 5, 6, 7, 8 are extra pens */
-#define MIMIO_PEN_E		(9)	/* big eraser */
-#define MIMIO_PEN_ES		(10)	/* lil eraser */
-#define MIMIO_PENJUMP_START	(10)
-#define MIMIO_PENJUMP		(6)
-#define MIMIO_PEN_I		(17)	/* mimio interactive */
-#define MIMIO_PEN_IL		(18)	/* mimio interactive button 1 */
-#define MIMIO_PEN_IR		(19)	/* mimio interactive button 2 */
-
-#define MIMIO_PEN_MAX		(MIMIO_PEN_IR)
-
-#define ACC_DONE		(0)
-#define ACC_NEWPAGE		(1)
-#define ACC_TAGPAGE		(2)
-#define ACC_PRINTPAGE		(4)
-#define ACC_MAXIMIZE		(8)
-#define ACC_FINDCTLPNL		(16)
-
-#define isvalidtxsize(n)	((n) > 0 && (n) <= MIMIO_MAXPAYLOAD)
-
-
-struct pktbuf {
-	unsigned char instr;
-	unsigned char buf[16];
-	unsigned char *p;
-	unsigned char *q;
-};
-
-struct usbintendpt {
-	dma_addr_t dma;
-	struct urb *urb;
-	unsigned char *buf;
-	struct usb_endpoint_descriptor *desc;
-};
-
-struct mimio {
-	struct input_dev *idev;
-	struct usb_device *udev;
-	struct usb_interface *uifc;
-	int open;
-	int present;
-	int greeted;
-	int txflags;
-	char phys[MIMIO_MAXNAMELEN];
-	struct usbintendpt in;
-	struct usbintendpt out;
-	struct pktbuf pktbuf;
-	unsigned char minor;
-	wait_queue_head_t waitq;
-	spinlock_t txlock;
-	void (*rxhandler)(struct mimio *, unsigned char *, unsigned int);
-	int last_pen_down;
-};
-
-static void mimio_close(struct input_dev *);
-static void mimio_dealloc(struct mimio *);
-static void mimio_disconnect(struct usb_interface *);
-static int mimio_greet(struct mimio *);
-static void mimio_irq_in(struct urb *);
-static void mimio_irq_out(struct urb *);
-static int mimio_open(struct input_dev *);
-static int mimio_probe(struct usb_interface *, const struct usb_device_id *);
-static void mimio_rx_handler(struct mimio *, unsigned char *, unsigned int);
-static int mimio_tx(struct mimio *, const char *, int);
-
-static char mimio_name[] = "VirtualInk mimio-Xi";
-static struct usb_device_id mimio_table [] = {
-	{ USB_DEVICE(MIMIO_VENDOR_ID, MIMIO_PRODUCT_ID) },
-	{ USB_DEVICE(0x0525, 0xa4a0) }, /* gadget zero firmware */
-	{ }
-};
-
-MODULE_DEVICE_TABLE(usb, mimio_table);
-
-static struct usb_driver mimio_driver = {
-	.name = "mimio",
-	.probe = mimio_probe,
-	.disconnect = mimio_disconnect,
-	.id_table = mimio_table,
-};
-
-static DECLARE_MUTEX(disconnect_sem);
-
-static void mimio_close(struct input_dev *idev)
-{
-	struct mimio *mimio;
-
-	mimio = input_get_drvdata(idev);
-	if (!mimio) {
-		dev_err(&idev->dev, "null mimio attached to input device\n");
-		return;
-	}
-
-	if (mimio->open <= 0)
-		dev_err(&idev->dev, "mimio not open.\n");
-	else
-		mimio->open--;
-
-	if (mimio->present == 0 && mimio->open == 0)
-		mimio_dealloc(mimio);
-}
-
-static void mimio_dealloc(struct mimio *mimio)
-{
-	if (mimio == NULL)
-		return;
-
-	usb_kill_urb(mimio->in.urb);
-
-	usb_kill_urb(mimio->out.urb);
-
-	if (mimio->idev) {
-		input_unregister_device(mimio->idev);
-		if (mimio->idev->grab)
-			input_close_device(mimio->idev->grab);
-		else
-			dev_dbg(&mimio->idev->dev, "mimio->idev->grab == NULL"
-				" -- didn't call input_close_device\n");
-	}
-
-	usb_free_urb(mimio->in.urb);
-
-	usb_free_urb(mimio->out.urb);
-
-	if (mimio->in.buf) {
-		usb_buffer_free(mimio->udev, MIMIO_MAXPAYLOAD, mimio->in.buf,
-				mimio->in.dma);
-	}
-
-	if (mimio->out.buf)
-		usb_buffer_free(mimio->udev, MIMIO_MAXPAYLOAD, mimio->out.buf,
-				mimio->out.dma);
-
-	if (mimio->idev)
-		input_free_device(mimio->idev);
-
-	kfree(mimio);
-}
-
-static void mimio_disconnect(struct usb_interface *ifc)
-{
-	struct mimio *mimio;
-
-	down(&disconnect_sem);
-
-	mimio = usb_get_intfdata(ifc);
-	usb_set_intfdata(ifc, NULL);
-	dev_dbg(&mimio->idev->dev, "disconnect\n");
-
-	if (mimio) {
-		mimio->present = 0;
-
-		if (mimio->open <= 0)
-			mimio_dealloc(mimio);
-	}
-
-	up(&disconnect_sem);
-}
-
-static int mimio_greet(struct mimio *mimio)
-{
-	const struct grtpkt {
-		int nbytes;
-		unsigned delay;
-		char data[8];
-	} grtpkts[] = {
-		{ 3, 0, { 0x11, 0x55, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00 } },
-		{ 5, 0, { 0x53, 0x55, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 } },
-		{ 5, 0, { 0x43, 0x55, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00 } },
-		{ 5, 0, { 0x33, 0x55, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00 } },
-		{ 5, 0, { 0x13, 0x00, 0x5e, 0x02, 0x4f, 0x00, 0x00, 0x00 } },
-		{ 5, 0, { 0x13, 0x00, 0x04, 0x03, 0x14, 0x00, 0x00, 0x00 } },
-		{ 5, 2, { 0x13, 0x00, 0x00, 0x04, 0x17, 0x00, 0x00, 0x00 } },
-		{ 5, 0, { 0x13, 0x00, 0x0d, 0x08, 0x16, 0x00, 0x00, 0x00 } },
-		{ 5, 0, { 0x13, 0x00, 0x4d, 0x01, 0x5f, 0x00, 0x00, 0x00 } },
-		{ 3, 0, { 0xf1, 0x55, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00 } },
-		{ 7, 2, { 0x52, 0x55, 0x00, 0x07, 0x31, 0x55, 0x64, 0x00 } },
-		{ 0, 0, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	};
-	int rslt;
-	const struct grtpkt *pkt;
-
-	for (pkt = grtpkts; pkt->nbytes; pkt++) {
-		rslt = mimio_tx(mimio, pkt->data, pkt->nbytes);
-		if (rslt)
-			return rslt;
-		if (pkt->delay)
-			msleep(pkt->delay);
-	}
-
-	return 0;
-}
-
-static void mimio_irq_in(struct urb *urb)
-{
-	int rslt;
-	char *data;
-	const char *reason = "going down";
-	struct mimio *mimio;
-
-	mimio = urb->context;
-
-	if (mimio == NULL)
-		/* paranoia */
-		return;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ETIMEDOUT:
-		reason = "timeout -- unplugged?";
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		dev_dbg(&mimio->idev->dev, "%s.\n", reason);
-		return;
-	default:
-		dev_dbg(&mimio->idev->dev, "unknown urb-status: %d.\n",
-			urb->status);
-		goto exit;
-	}
-	data = mimio->in.buf;
-
-	if (mimio->rxhandler)
-		mimio->rxhandler(mimio, data, urb->actual_length);
-exit:
-	/*
-	 * Keep listening to device on same urb.
-	 */
-	rslt = usb_submit_urb(urb, GFP_ATOMIC);
-	if (rslt)
-		dev_err(&mimio->idev->dev, "usb_submit_urb failure: %d.\n",
-			rslt);
-}
-
-static void mimio_irq_out(struct urb *urb)
-{
-	unsigned long flags;
-	struct mimio *mimio;
-
-	mimio = urb->context;
-
-	if (urb->status)
-		dev_dbg(&mimio->idev->dev, "urb-status: %d.\n", urb->status);
-
-	spin_lock_irqsave(&mimio->txlock, flags);
-	mimio->txflags |= MIMIO_TXDONE;
-	spin_unlock_irqrestore(&mimio->txlock, flags);
-	wmb();
-	wake_up(&mimio->waitq);
-}
-
-static int mimio_open(struct input_dev *idev)
-{
-	int rslt;
-	struct mimio *mimio;
-
-	rslt = 0;
-	down(&disconnect_sem);
-	mimio = input_get_drvdata(idev);
-	dev_dbg(&idev->dev, "mimio_open\n");
-
-	if (mimio == NULL) {
-		dev_err(&idev->dev, "null mimio.\n");
-		rslt = -ENODEV;
-		goto exit;
-	}
-
-	if (mimio->open++)
-		goto exit;
-
-	if (mimio->present && !mimio->greeted) {
-		struct urb *urb = mimio->in.urb;
-		mimio->in.urb->dev = mimio->udev;
-		rslt = usb_submit_urb(mimio->in.urb, GFP_KERNEL);
-		if (rslt) {
-			dev_err(&idev->dev, "usb_submit_urb failure "
-				"(res = %d: %s). Not greeting.\n",
-				rslt,
-				(!urb ? "urb is NULL" :
-				 (urb->hcpriv ? "urb->hcpriv is non-NULL" :
-				  (!urb->complete ? "urb is not complete" :
-				   (urb->number_of_packets <= 0 ? "urb has no packets" :
-				    (urb->interval <= 0 ? "urb interval too small" :
-				     "urb interval too large or some other error"))))));
-			rslt = -EIO;
-			goto exit;
-		}
-		rslt = mimio_greet(mimio);
-		if (rslt == 0) {
-			dev_dbg(&idev->dev, "Mimio greeted OK.\n");
-			mimio->greeted = 1;
-		} else {
-			dev_dbg(&idev->dev, "Mimio greet Failure (%d)\n",
-				rslt);
-		}
-	}
-
-exit:
-	up(&disconnect_sem);
-	return rslt;
-}
-
-static int mimio_probe(struct usb_interface *ifc,
-		       const struct usb_device_id *id)
-{
-	char path[64];
-	int pipe, maxp;
-	struct mimio *mimio;
-	struct usb_device *udev;
-	struct usb_host_interface *hostifc;
-	struct input_dev *input_dev;
-	int res = 0;
-	int i;
-
-	udev = interface_to_usbdev(ifc);
-
-	mimio = kzalloc(sizeof(struct mimio), GFP_KERNEL);
-	if (!mimio)
-		return -ENOMEM;
-
-	input_dev = input_allocate_device();
-	if (!input_dev) {
-		mimio_dealloc(mimio);
-		return -ENOMEM;
-	}
-
-	mimio->uifc = ifc;
-	mimio->udev = udev;
-	mimio->pktbuf.p = mimio->pktbuf.buf;
-	mimio->pktbuf.q = mimio->pktbuf.buf;
-	/* init_input_dev(mimio->idev); */
-	mimio->idev = input_dev;
-	init_waitqueue_head(&mimio->waitq);
-	spin_lock_init(&mimio->txlock);
-	hostifc = ifc->cur_altsetting;
-
-	if (hostifc->desc.bNumEndpoints != 2) {
-		dev_err(&udev->dev, "Unexpected endpoint count: %d.\n",
-			hostifc->desc.bNumEndpoints);
-		mimio_dealloc(mimio);
-		return -ENODEV;
-	}
-
-	mimio->in.desc = &(hostifc->endpoint[0].desc);
-	mimio->out.desc = &(hostifc->endpoint[1].desc);
-
-	mimio->in.buf = usb_buffer_alloc(udev, MIMIO_MAXPAYLOAD, GFP_KERNEL,
-					 &mimio->in.dma);
-	mimio->out.buf = usb_buffer_alloc(udev, MIMIO_MAXPAYLOAD, GFP_KERNEL,
-					  &mimio->out.dma);
-
-	if (mimio->in.buf == NULL || mimio->out.buf == NULL) {
-		dev_err(&udev->dev, "usb_buffer_alloc failure.\n");
-		mimio_dealloc(mimio);
-		return -ENOMEM;
-	}
-
-	mimio->in.urb = usb_alloc_urb(0, GFP_KERNEL);
-	mimio->out.urb = usb_alloc_urb(0, GFP_KERNEL);
-
-	if (mimio->in.urb == NULL || mimio->out.urb == NULL) {
-		dev_err(&udev->dev, "usb_alloc_urb failure.\n");
-		mimio_dealloc(mimio);
-		return -ENOMEM;
-	}
-
-	/*
-	 * Build the input urb.
-	 */
-	pipe = usb_rcvintpipe(udev, mimio->in.desc->bEndpointAddress);
-	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
-	if (maxp > MIMIO_MAXPAYLOAD)
-		maxp = MIMIO_MAXPAYLOAD;
-	usb_fill_int_urb(mimio->in.urb, udev, pipe, mimio->in.buf, maxp,
-			 mimio_irq_in, mimio, mimio->in.desc->bInterval);
-	mimio->in.urb->transfer_dma = mimio->in.dma;
-	mimio->in.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	/*
-	 * Build the output urb.
-	 */
-	pipe = usb_sndintpipe(udev, mimio->out.desc->bEndpointAddress);
-	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
-	if (maxp > MIMIO_MAXPAYLOAD)
-		maxp = MIMIO_MAXPAYLOAD;
-	usb_fill_int_urb(mimio->out.urb, udev, pipe, mimio->out.buf, maxp,
-			 mimio_irq_out, mimio, mimio->out.desc->bInterval);
-	mimio->out.urb->transfer_dma = mimio->out.dma;
-	mimio->out.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	/*
-	 * Build input device info
-	 */
-	usb_make_path(udev, path, 64);
-	snprintf(mimio->phys, MIMIO_MAXNAMELEN, "%s/input0", path);
-	input_set_drvdata(input_dev, mimio);
-	/* input_dev->dev = &ifc->dev; */
-	input_dev->open = mimio_open;
-	input_dev->close = mimio_close;
-	input_dev->name = mimio_name;
-	input_dev->phys = mimio->phys;
-	input_dev->dev.parent = &ifc->dev;
-
-	input_dev->id.bustype = BUS_USB;
-	input_dev->id.vendor = le16_to_cpu(udev->descriptor.idVendor);
-	input_dev->id.product = le16_to_cpu(udev->descriptor.idProduct);
-	input_dev->id.version = le16_to_cpu(udev->descriptor.bcdDevice);
-
-	input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
-	for (i = BTN_TOOL_PEN; i <= LOCALBTN_TOOL_EXTRA2; ++i)
-		set_bit(i, input_dev->keybit);
-
-	input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
-						 BIT_MASK(BTN_1) |
-						 BIT_MASK(BTN_2) |
-						 BIT_MASK(BTN_3) |
-						 BIT_MASK(BTN_4) |
-						 BIT_MASK(BTN_5);
-	/*   input_dev->keybit[BTN_MOUSE] |= BIT(BTN_LEFT); */
-	input_dev->absbit[0] |= BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
-	input_set_abs_params(input_dev, ABS_X, 0, MIMIO_XRANGE_MAX, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, MIMIO_YRANGE_MAX, 0, 0);
-	input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
-
-#if 0
-	input_dev->absmin[ABS_X] = 0;
-	input_dev->absmin[ABS_Y] = 0;
-	input_dev->absmax[ABS_X] = 9600;
-	input_dev->absmax[ABS_Y] = 4800;
-	input_dev->absfuzz[ABS_X] = 0;
-	input_dev->absfuzz[ABS_Y] = 0;
-	input_dev->absflat[ABS_X] = 0;
-	input_dev->absflat[ABS_Y] = 0;
-#endif
-
-#if 0
-	/* this will just reduce the precision */
-	input_dev->absfuzz[ABS_X] = 8; /* experimental; may need to change */
-	input_dev->absfuzz[ABS_Y] = 8; /* experimental; may need to change */
-#endif
-
-	/*
-	 * Register the input device.
-	 */
-	res = input_register_device(mimio->idev);
-	if (res) {
-		dev_err(&udev->dev, "input_register_device failure (%d)\n",
-			res);
-		mimio_dealloc(mimio);
-		return -EIO;
-	}
-	dev_dbg(&mimio->idev->dev, "input: %s on %s (res = %d).\n",
-		input_dev->name, input_dev->phys, res);
-
-	usb_set_intfdata(ifc, mimio);
-	mimio->present = 1;
-
-	/*
-	 * Submit the input urb to the usb subsystem.
-	 */
-	mimio->in.urb->dev = mimio->udev;
-	res = usb_submit_urb(mimio->in.urb, GFP_KERNEL);
-	if (res) {
-		dev_err(&mimio->idev->dev, "usb_submit_urb failure (%d)\n",
-			res);
-		mimio_dealloc(mimio);
-		return -EIO;
-	}
-
-	/*
-	 * Attempt to greet the mimio after giving
-	 * it some post-init settling time.
-	 *
-	 * note: sometimes this sleep interval isn't
-	 * long enough to permit the device to re-init
-	 * after a hot-swap; maybe need to bump it up.
-	 *
-	 * As it is, this probably breaks module unloading support!
-	 */
-	msleep(1024);
-
-	res = mimio_greet(mimio);
-	if (res == 0) {
-		dev_dbg(&mimio->idev->dev, "Mimio greeted OK.\n");
-		mimio->greeted = 1;
-		mimio->rxhandler = mimio_rx_handler;
-	} else {
-		dev_dbg(&mimio->idev->dev, "Mimio greet Failure (%d)\n", res);
-	}
-
-	return 0;
-}
-
-static int handle_mimio_rx_penupdown(struct mimio *mimio,
-				     int down,
-				     const char *const instr[],
-				     const int instr_ofst[])
-{
-	int penid, x;
-	if (mimio->pktbuf.q - mimio->pktbuf.p < (down ? 4 : 3))
-		return 1; 		/* partial pkt */
-
-	if (down) {
-		x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
-			*(mimio->pktbuf.p + 2);
-		if (x != *(mimio->pktbuf.p + 3)) {
-			dev_dbg(&mimio->idev->dev, "EV_PEN%s: bad xsum.\n",
-				down ? "DOWN":"UP");
-			/* skip this event data */
-			mimio->pktbuf.p += 4;
-			/* decode any remaining events */
-			return 0;
-		}
-		penid = mimio->pktbuf.instr = *(mimio->pktbuf.p + 2);
-		if (penid > MIMIO_PEN_MAX) {
-			dev_dbg(&mimio->idev->dev,
-				"Unmapped penID (not in [0, %d]): %d\n",
-				MIMIO_PEN_MAX, (int)mimio->pktbuf.instr);
-			penid = mimio->pktbuf.instr = 0;
-		}
-		mimio->last_pen_down = penid;
-	} else {
-		penid = mimio->last_pen_down;
-	}
-	dev_dbg(&mimio->idev->dev, "%s (id %d, code %d) %s.\n", instr[penid],
-		instr_ofst[penid], penid, down ? "down" : "up");
-
-	if (instr_ofst[penid] >= 0) {
-		int code = BTN_TOOL_PEN + instr_ofst[penid];
-		int value = down ? DOWNVALUE : UPVALUE;
-		if (code > KEY_MAX)
-			dev_dbg(&mimio->idev->dev, "input_event will ignore "
-				"-- code (%d) > KEY_MAX\n", code);
-		if (!test_bit(code, mimio->idev->keybit))
-			dev_dbg(&mimio->idev->dev, "input_event will ignore "
-				"-- bit for code (%d) not enabled\n", code);
-		if (!!test_bit(code, mimio->idev->key) == value)
-			dev_dbg(&mimio->idev->dev, "input_event will ignore "
-				"-- bit for code (%d) already set to %d\n",
-				code, value);
-		if (value != DOWNVALUE) {
-			/* input_regs(mimio->idev, regs); */
-			input_report_key(mimio->idev, code, value);
-			input_sync(mimio->idev);
-		} else {
-			/* wait until we get some coordinates */
-		}
-	} else {
-		dev_dbg(&mimio->idev->dev, "penID offset[%d] == %d is < 0 "
-			"- not sending\n", penid, instr_ofst[penid]);
-	}
-	mimio->pktbuf.p += down ? 4 : 3; /* 3 for up, 4 for down */
-	return 0;
-}
-
-/*
- * Stay tuned for partial-packet excitement.
- *
- * This routine buffers data packets received from the mimio device
- * in the mimio's data space.  This buffering is necessary because
- * the mimio's in endpoint can serve us partial packets of data, and
- * we want the driver to support the servicing of multiple mimios.
- * Empirical evidence gathered so far suggests that the method of
- * buffering packet data in the mimio's data space works.  Previous
- * versions of this driver did not buffer packet data in each mimio's
- * data-space, and were therefore not able to service multiple mimios.
- * Note that since the caller of this routine is running in interrupt
- * context, care needs to be taken to ensure that this routine does not
- * become bloated, and it may be that another spinlock is needed in each
- * mimio to guard the buffered packet data properly.
- */
-static void mimio_rx_handler(struct mimio *mimio,
-			     unsigned char *data,
-			     unsigned int nbytes)
-{
-	struct device *dev = &mimio->idev->dev;
-	unsigned int x;
-	unsigned int y;
-	static const char * const instr[] = {
-		"?0",
-		"black pen", "blue pen", "green pen", "red pen",
-		"brown pen", "orange pen", "purple pen", "yellow pen",
-		"big eraser", "lil eraser",
-		"?11", "?12", "?13", "?14", "?15", "?16",
-		"mimio interactive", "interactive button1",
-		"interactive button2"
-	};
-
-	/* Mimio Interactive gives:
-	 * down: [0x22 0x01 0x11 0x32 0x24]
-	 * b1  : [0x22 0x01 0x12 0x31 0x24]
-	 * b2  : [0x22 0x01 0x13 0x30 0x24]
-	 */
-	static const int instr_ofst[] = {
-		-1,
-		0, 1, 2, 3,
-		9, 9, 9, 9,
-		4, 5,
-		-1, -1, -1, -1, -1, -1,
-		6, 7, 8,
-	};
-
-	memcpy(mimio->pktbuf.q, data, nbytes);
-	mimio->pktbuf.q += nbytes;
-
-	while (mimio->pktbuf.p < mimio->pktbuf.q) {
-		int t = *mimio->pktbuf.p;
-		switch (t) {
-		case MIMIO_EV_PENUP:
-		case MIMIO_EV_PENDOWN:
-			if (handle_mimio_rx_penupdown(mimio,
-						      t == MIMIO_EV_PENDOWN,
-						      instr, instr_ofst))
-				return; /* partial packet */
-			break;
-
-		case MIMIO_EV_PENDATA:
-			if (mimio->pktbuf.q - mimio->pktbuf.p < 6)
-				/* partial pkt */
-				return;
-			x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
-				*(mimio->pktbuf.p + 2) ^
-				*(mimio->pktbuf.p + 3) ^
-				*(mimio->pktbuf.p + 4);
-			if (x != *(mimio->pktbuf.p + 5)) {
-				dev_dbg(dev, "EV_PENDATA: bad xsum.\n");
-				mimio->pktbuf.p += 6; /* skip this event data */
-				break; /* decode any remaining events */
-			}
-			x = *(mimio->pktbuf.p + 1);
-			x <<= 8;
-			x |= *(mimio->pktbuf.p + 2);
-			y = *(mimio->pktbuf.p + 3);
-			y <<= 8;
-			y |= *(mimio->pktbuf.p + 4);
-			dev_dbg(dev, "coord: (%d, %d)\n", x, y);
-			if (instr_ofst[mimio->pktbuf.instr] >= 0) {
-				int code = BTN_TOOL_PEN +
-					   instr_ofst[mimio->last_pen_down];
-#if 0
-				/* Utter hack to ensure we get forwarded _AND_
-				 * so we can identify when a complete signal is
-				 * received */
-				mimio->idev->abs[ABS_Y] = -1;
-				mimio->idev->abs[ABS_X] = -1;
-#endif
-				/* input_regs(mimio->idev, regs); */
-				input_report_abs(mimio->idev, ABS_X, x);
-				input_report_abs(mimio->idev, ABS_Y, y);
-				/* fake a penup */
-				change_bit(code, mimio->idev->key);
-				input_report_key(mimio->idev,
-						 code,
-						 DOWNVALUE);
-				/* always sync here */
-				mimio->idev->sync = 0;
-				input_sync(mimio->idev);
-			}
-			mimio->pktbuf.p += 6;
-			break;
-		case MIMIO_EV_MEMRESET:
-			if (mimio->pktbuf.q - mimio->pktbuf.p < 7)
-				/* partial pkt */
-				return;
-			dev_dbg(dev, "mem-reset.\n");
-			/* input_regs(mimio->idev, regs); */
-			input_event(mimio->idev, EV_KEY, BTN_0, 1);
-			input_event(mimio->idev, EV_KEY, BTN_0, 0);
-			input_sync(mimio->idev);
-			mimio->pktbuf.p += 7;
-			break;
-		case MIMIO_EV_ACC:
-			if (mimio->pktbuf.q - mimio->pktbuf.p < 4)
-				/* partial pkt */
-				return;
-			x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
-				*(mimio->pktbuf.p + 2);
-			if (x != *(mimio->pktbuf.p + 3)) {
-				dev_dbg(dev, "EV_ACC: bad xsum.\n");
-				mimio->pktbuf.p += 4; /* skip this event data */
-				break; /* decode any remaining events */
-			}
-			switch (*(mimio->pktbuf.p + 2)) {
-			case ACC_NEWPAGE:
-				dev_dbg(&mimio->idev->dev, "new-page.\n");
-				/* input_regs(mimio->idev, regs); */
-				input_event(mimio->idev, EV_KEY, BTN_1, 1);
-				input_event(mimio->idev, EV_KEY, BTN_1, 0);
-				input_sync(mimio->idev);
-				break;
-			case ACC_TAGPAGE:
-				dev_dbg(&mimio->idev->dev, "tag-page.\n");
-				/* input_regs(mimio->idev, regs); */
-				input_event(mimio->idev, EV_KEY, BTN_2, 1);
-				input_event(mimio->idev, EV_KEY, BTN_2, 0);
-				input_sync(mimio->idev);
-				break;
-			case ACC_PRINTPAGE:
-				dev_dbg(&mimio->idev->dev, "print-page.\n");
-				/* input_regs(mimio->idev, regs);*/
-				input_event(mimio->idev, EV_KEY, BTN_3, 1);
-				input_event(mimio->idev, EV_KEY, BTN_3, 0);
-				input_sync(mimio->idev);
-				break;
-			case ACC_MAXIMIZE:
-				dev_dbg(&mimio->idev->dev,
-					"maximize-window.\n");
-				/* input_regs(mimio->idev, regs); */
-				input_event(mimio->idev, EV_KEY, BTN_4, 1);
-				input_event(mimio->idev, EV_KEY, BTN_4, 0);
-				input_sync(mimio->idev);
-				break;
-			case ACC_FINDCTLPNL:
-				dev_dbg(&mimio->idev->dev, "find-ctl-panel.\n");
-				/* input_regs(mimio->idev, regs); */
-				input_event(mimio->idev, EV_KEY, BTN_5, 1);
-				input_event(mimio->idev, EV_KEY, BTN_5, 0);
-				input_sync(mimio->idev);
-				break;
-			case ACC_DONE:
-				dev_dbg(&mimio->idev->dev, "acc-done.\n");
-				/* no event is dispatched to the input
-				 * subsystem for this device event.
-				 */
-				break;
-			default:
-				dev_dbg(dev, "unknown acc event.\n");
-				break;
-			}
-			mimio->pktbuf.p += 4;
-			break;
-		default:
-			mimio->pktbuf.p++;
-			break;
-		}
-	}
-
-	/*
-	 * No partial event was received, so reset mimio's pktbuf ptrs.
-	 */
-	mimio->pktbuf.p = mimio->pktbuf.q = mimio->pktbuf.buf;
-}
-
-static int mimio_tx(struct mimio *mimio, const char *buf, int nbytes)
-{
-	int rslt;
-	int timeout;
-	unsigned long flags;
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (!(isvalidtxsize(nbytes))) {
-		dev_err(&mimio->idev->dev, "invalid arg: nbytes: %d.\n",
-			nbytes);
-		return -EINVAL;
-	}
-
-	/*
-	 * Init the out urb and copy the data to send.
-	 */
-	mimio->out.urb->dev = mimio->udev;
-	mimio->out.urb->transfer_buffer_length = nbytes;
-	memcpy(mimio->out.urb->transfer_buffer, buf, nbytes);
-
-	/*
-	 * Send the data.
-	 */
-	spin_lock_irqsave(&mimio->txlock, flags);
-	mimio->txflags = MIMIO_TXWAIT;
-	rslt = usb_submit_urb(mimio->out.urb, GFP_ATOMIC);
-	spin_unlock_irqrestore(&mimio->txlock, flags);
-	dev_dbg(&mimio->idev->dev, "rslt: %d.\n", rslt);
-
-	if (rslt) {
-		dev_err(&mimio->idev->dev, "usb_submit_urb failure: %d.\n",
-			rslt);
-		return rslt;
-	}
-
-	/*
-	 * Wait for completion to be signalled (the mimio_irq_out
-	 * completion routine will or MIMIO_TXDONE in with txflags).
-	 */
-	timeout = HZ;
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&mimio->waitq, &wait);
-
-	while (timeout && ((mimio->txflags & MIMIO_TXDONE) == 0)) {
-		timeout = schedule_timeout(timeout);
-		rmb();
-	}
-
-	if ((mimio->txflags & MIMIO_TXDONE) == 0)
-		dev_dbg(&mimio->idev->dev, "tx timed out.\n");
-
-	/*
-	 * Now that completion has been signalled,
-	 * unlink the urb so that it can be recycled.
-	 */
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&mimio->waitq, &wait);
-	usb_unlink_urb(mimio->out.urb);
-
-	return rslt;
-}
-
-static int __init mimio_init(void)
-{
-	int rslt;
-
-	rslt = usb_register(&mimio_driver);
-	if (rslt != 0) {
-		err("%s: usb_register failure: %d", __func__, rslt);
-		return rslt;
-	}
-
-	printk(KERN_INFO KBUILD_MODNAME ":"
-	       DRIVER_DESC " " DRIVER_VERSION "\n");
-	return rslt;
-}
-
-static void __exit mimio_exit(void)
-{
-	usb_deregister(&mimio_driver);
-}
-
-module_init(mimio_init);
-module_exit(mimio_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/otus/80211core/cagg.c b/drivers/staging/otus/80211core/cagg.c
index dbd0a5f..f9514c0 100644
--- a/drivers/staging/otus/80211core/cagg.c
+++ b/drivers/staging/otus/80211core/cagg.c
@@ -1832,14 +1832,12 @@
 
 struct agg_tid_rx* zfAggRxEnabled(zdev_t* dev, zbuf_t* buf)
 {
-    u16_t   dst0, src[3], ac, aid, fragOff;
-    u8_t    up;
+    u16_t   dst0, src[3], aid;
     u16_t   offset = 0;
     u16_t   seq_no;
     u16_t frameType;
     u16_t frameCtrl;
     u16_t frameSubtype;
-    u32_t tcp_seq;
     //struct aggSta *agg_sta;
 #if ZM_AGG_FPGA_REORDERING
     struct agg_tid_rx *tid_rx;
@@ -1864,13 +1862,17 @@
         return NULL;
     }
 #ifdef ZM_ENABLE_PERFORMANCE_EVALUATION
-    tcp_seq = zmw_rx_buf_readb(dev, buf, 22+36) << 24;
-    tcp_seq += zmw_rx_buf_readb(dev, buf, 22+37) << 16;
-    tcp_seq += zmw_rx_buf_readb(dev, buf, 22+38) << 8;
-    tcp_seq += zmw_rx_buf_readb(dev, buf, 22+39);
+    {
+        u32_t tcp_seq;
+
+        tcp_seq = zmw_rx_buf_readb(dev, buf, 22+36) << 24;
+        tcp_seq += zmw_rx_buf_readb(dev, buf, 22+37) << 16;
+        tcp_seq += zmw_rx_buf_readb(dev, buf, 22+38) << 8;
+        tcp_seq += zmw_rx_buf_readb(dev, buf, 22+39);
+        ZM_SEQ_DEBUG("In                   %5d, %12u\n", seq_no, tcp_seq);
+    }
 #endif
 
-    ZM_SEQ_DEBUG("In                   %5d, %12u\n", seq_no, tcp_seq);
     dst0 = zmw_rx_buf_readh(dev, buf, offset+4);
 
     src[0] = zmw_rx_buf_readh(dev, buf, offset+10);
diff --git a/drivers/staging/otus/80211core/ccmd.c b/drivers/staging/otus/80211core/ccmd.c
index 8da28ee..3e3d9b5 100644
--- a/drivers/staging/otus/80211core/ccmd.c
+++ b/drivers/staging/otus/80211core/ccmd.c
@@ -1659,7 +1659,7 @@
 	if (setValue) {
 		/* write register for sniffer mode */
 		zfHpSetSnifferMode(dev, 1);
-		zm_msg0_mm(ZM_LV_1, "enalbe sniffer mode");
+		zm_msg0_mm(ZM_LV_1, "enable sniffer mode");
 	} else {
 		zfHpSetSnifferMode(dev, 0);
 		zm_msg0_mm(ZM_LV_0, "disalbe sniffer mode");
diff --git a/drivers/staging/otus/80211core/cfunc.c b/drivers/staging/otus/80211core/cfunc.c
index d7c49d7..e0a9f38 100644
--- a/drivers/staging/otus/80211core/cfunc.c
+++ b/drivers/staging/otus/80211core/cfunc.c
@@ -1194,8 +1194,6 @@
     u8_t   i;
     u16_t  tempMinIndex, tempMinValue;
 
-    zmw_get_wlan_dev(dev);
-
     i = 1;
     tempMinIndex = 0;
     tempMinValue = array[tempMinIndex];
diff --git a/drivers/staging/otus/80211core/cmm.c b/drivers/staging/otus/80211core/cmm.c
index a6c1b41..484e753 100644
--- a/drivers/staging/otus/80211core/cmm.c
+++ b/drivers/staging/otus/80211core/cmm.c
@@ -346,8 +346,6 @@
     u8_t super_feature;
     u8_t ouiSuperG[6] = {0x00,0x03,0x7f,0x01, 0x01, 0x00};
 
-    zmw_get_wlan_dev(dev);
-
     /* Get offset of first element */
     subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
     if ((offset = zgElementOffsetTable[subType]) == 0xff)
@@ -411,8 +409,6 @@
     u8_t id;
     u8_t ouixr[6] = {0x00,0x03,0x7f,0x03, 0x01, 0x00};
 
-    zmw_get_wlan_dev(dev);
-
     /* Get offset of first element */
     subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
     if ((offset = zgElementOffsetTable[subType]) == 0xff)
diff --git a/drivers/staging/otus/80211core/cmmsta.c b/drivers/staging/otus/80211core/cmmsta.c
index a11d559..c3fd475 100644
--- a/drivers/staging/otus/80211core/cmmsta.c
+++ b/drivers/staging/otus/80211core/cmmsta.c
@@ -2808,7 +2808,7 @@
     zmw_get_wlan_dev(dev);
 
     /* check mode : AP/IBSS */
-    if ((wd->wlanMode != ZM_MODE_AP) || (wd->wlanMode != ZM_MODE_IBSS))
+    if ((wd->wlanMode != ZM_MODE_AP) && (wd->wlanMode != ZM_MODE_IBSS))
     {
         zm_msg0_mm(ZM_LV_3, "Ignore probe req");
         return;
@@ -4848,8 +4848,6 @@
     u8_t MaxTxPower;
     u8_t MinTxPower;
 
-    zmw_get_wlan_dev(dev);
-
     /* Element ID */
     zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_POWER_CAPABILITY);
 
@@ -5276,7 +5274,6 @@
     u8_t   da0;
     //u16_t  sa[3];
     u16_t  ret;
-    u16_t  i;
     //u8_t    sa0;
 
     zmw_get_wlan_dev(dev);
@@ -5738,8 +5735,6 @@
 	u8_t  weightOfN40BelowThr = 16;
 	u8_t  weightOfN40UpThr    = 32;
 
-    zmw_get_wlan_dev(dev);
-
     if( isBMode == 0 )
         return (signalStrength + weightOfB);    // pure b mode , do not add the weight value for this AP !
     else
diff --git a/drivers/staging/otus/80211core/cpsmgr.c b/drivers/staging/otus/80211core/cpsmgr.c
index cf73cac..98e1f0c 100644
--- a/drivers/staging/otus/80211core/cpsmgr.c
+++ b/drivers/staging/otus/80211core/cpsmgr.c
@@ -381,8 +381,6 @@
 
 static void zfPowerSavingMgrDisconnectMain(zdev_t* dev)
 {
-    zmw_get_wlan_dev(dev);
-
 #ifdef ZM_ENABLE_DISCONNECT_PS
     switch(wd->sta.psMgr.state)
     {
diff --git a/drivers/staging/otus/80211core/cscanmgr.c b/drivers/staging/otus/80211core/cscanmgr.c
index b32835c..be7d8eb 100644
--- a/drivers/staging/otus/80211core/cscanmgr.c
+++ b/drivers/staging/otus/80211core/cscanmgr.c
@@ -289,8 +289,6 @@
 
 static void zfScanMgrEventScanCompleteCb(zdev_t* dev)
 {
-    zmw_get_wlan_dev(dev);
-
     if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
     {
         zfSendNullData(dev, 0);
diff --git a/drivers/staging/otus/80211core/ctkip.c b/drivers/staging/otus/80211core/ctkip.c
index be42f7a..ca07402 100644
--- a/drivers/staging/otus/80211core/ctkip.c
+++ b/drivers/staging/otus/80211core/ctkip.c
@@ -255,7 +255,8 @@
     zfMemoryCopy(pSeed->ta, ta, 6);
     zfMemoryCopy(pSeed->tk, key, 16);
 
-    iv16 = *initIv++;
+    iv16 = *initIv;
+    initIv++;
     iv16 += *initIv<<8;
     initIv++;
 
@@ -264,7 +265,7 @@
     for(i=0; i<4; i++)      // initiv is little endian
     {
         iv32 += *initIv<<(i*8);
-        *initIv++;
+        initIv++;
     }
 
     pSeed->iv32 = iv32+1; // Force Recalculating on Tkip Phase1
diff --git a/drivers/staging/otus/80211core/ctxrx.c b/drivers/staging/otus/80211core/ctxrx.c
index ac54d5a..4e7f4bd 100644
--- a/drivers/staging/otus/80211core/ctxrx.c
+++ b/drivers/staging/otus/80211core/ctxrx.c
@@ -536,8 +536,7 @@
         zm_msg2_rx(ZM_LV_2, "ip1=", dip[1]);
 
         //ARP request to 192.168.1.15
-        if ((arpOp == 0x0100) && (dip[0] == 0xa8c0) && (dip[1] == 0x0f01));
-        {
+        if ((arpOp == 0x0100) && (dip[0] == 0xa8c0) && (dip[1] == 0x0f01)) {
             zm_msg0_rx(ZM_LV_2, "ARP");
             /* ARP response */
             zmw_rx_buf_writeh(dev, buf, 20, 0x0200);
@@ -883,7 +882,6 @@
 /************************************************************************/
 u16_t zfTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port, u16_t bufType, u16_t flag)
 {
-    u16_t err;
     //u16_t addrTblSize;
     //struct zsAddrTbl addrTbl;
     u16_t removeLen;
@@ -905,7 +903,6 @@
     u8_t qosType, keyIdx = 0;
     u16_t fragOff;
     u16_t newFlag;
-    struct zsMicVar*  pMicKey;
     u8_t tkipFrameOffset = 0;
 
     zmw_get_wlan_dev(dev);
@@ -1693,8 +1690,6 @@
     u16_t  packetLen, keyInfo, keyLen, keyDataLen, length, Op_Code;
     u32_t  replayCounterH, replayCounterL, vendorId, VendorType;
 
-    zmw_get_wlan_dev(dev);
-
     zm_debug_msg1("EAPOL Packet size = ", zfwBufGetSize(dev, buf));
 
     /* EAPOL packet type */
@@ -2437,7 +2432,6 @@
                     u16_t IvOffset;
                     u8_t keyLen = 5;
                     u8_t iv[3];
-                    u8_t *wepKey;
                     u8_t keyIdx;
 
                     IvOffset = offset + ZM_SIZE_OF_WLAN_DATA_HEADER;
diff --git a/drivers/staging/otus/80211core/ledmgr.c b/drivers/staging/otus/80211core/ledmgr.c
index 1e104a9..eafce0b 100644
--- a/drivers/staging/otus/80211core/ledmgr.c
+++ b/drivers/staging/otus/80211core/ledmgr.c
@@ -187,7 +187,6 @@
 
 void zfLedCtrlType2(zdev_t* dev)
 {
-    u32_t ton, toff, tmp, period;
     u16_t OperateLED;
     zmw_get_wlan_dev(dev);
 
diff --git a/drivers/staging/otus/80211core/pub_zfi.h b/drivers/staging/otus/80211core/pub_zfi.h
index b7b7f45..5202e5a 100644
--- a/drivers/staging/otus/80211core/pub_zfi.h
+++ b/drivers/staging/otus/80211core/pub_zfi.h
@@ -814,7 +814,6 @@
 #define ZM_PERFORMANCE_RX_AMSDU(dev, buf, len)
 #define ZM_PERFORMANCE_RX_FLUSH(dev)
 #define ZM_PERFORMANCE_RX_CLEAR(dev)
-#define ZM_SEQ_DEBUG
 #define ZM_PERFORMANCE_RX_REORDER(dev)
 #endif
 /***** End of section 3 *****/
diff --git a/drivers/staging/otus/Kconfig b/drivers/staging/otus/Kconfig
index f6cc262..e918134 100644
--- a/drivers/staging/otus/Kconfig
+++ b/drivers/staging/otus/Kconfig
@@ -1,6 +1,8 @@
 config OTUS
 	tristate "Atheros OTUS 802.11n USB wireless support"
 	depends on USB && WLAN && MAC80211
+	select WIRELESS_EXT
+	select WEXT_PRIV
 	default N
 	---help---
 	  Enable support for Atheros 802.11n USB hardware:
diff --git a/drivers/staging/otus/apdbg.c b/drivers/staging/otus/apdbg.c
index 0eb93f1..b59028e 100644
--- a/drivers/staging/otus/apdbg.c
+++ b/drivers/staging/otus/apdbg.c
@@ -90,8 +90,27 @@
 
 #endif
 
-char hex(char);
-unsigned char asctohex(char *str);
+static char hex(char v)
+{
+	if (isdigit(v))
+		return v - '0';
+	else if (isxdigit(v))
+		return tolower(v) - 'a' + 10;
+	else
+		return 0;
+}
+
+static unsigned char asctohex(char *str)
+{
+	unsigned char value;
+
+	value = hex(*str) & 0x0f;
+	value = value << 4;
+	str++;
+	value |= hex(*str) & 0x0f;
+
+	return value;
+}
 
 char *prgname;
 
@@ -109,10 +128,10 @@
 
 int read_reg(int sock, struct ifreq *req)
 {
-	struct zdap_ioctl *zdreq = 0;
+	struct zdap_ioctl *zdreq = NULL;
 
 	if (!set_ioctl(sock, req))
-			return -1;
+		return -1;
 
 	/*
 	 * zdreq = (struct zdap_ioctl *)req->ifr_data;
@@ -125,7 +144,7 @@
 
 int read_mem(int sock, struct ifreq *req)
 {
-	struct zdap_ioctl *zdreq = 0;
+	struct zdap_ioctl *zdreq = NULL;
 	int i;
 
 	if (!set_ioctl(sock, req))
@@ -368,7 +387,7 @@
 
 		zdreq.addr = addr;
 		zdreq.cmd = ZM_IOCTL_SET_PIBSS_MODE;
-	} else 	{
+	} else {
 		fprintf(stderr, "error action\n");
 		exit(1);
 	}
@@ -380,25 +399,3 @@
 	exit(0);
 }
 
-unsigned char asctohex(char *str)
-{
-	unsigned char value;
-
-	value = hex(*str) & 0x0f;
-	value = value << 4;
-	str++;
-	value |= hex(*str) & 0x0f;
-
-	return value;
-}
-
-char hex(char v)
-{
-	if (isdigit(v))
-		return v - '0';
-	else if (isxdigit(v))
-		return tolower(v) - 'a' + 10;
-	else
-		return 0;
-}
-
diff --git a/drivers/staging/otus/hal/hpmain.c b/drivers/staging/otus/hal/hpmain.c
index 94f9cbb..8dff5b9 100644
--- a/drivers/staging/otus/hal/hpmain.c
+++ b/drivers/staging/otus/hal/hpmain.c
@@ -1316,7 +1316,6 @@
         u8_t extOffset, u8_t initRF)
 {
     u32_t cmd[9];
-    u32_t cmdB[3];
     u16_t ret;
     u8_t old_band;
     u8_t new_band;
@@ -3434,7 +3433,6 @@
     /* Write PHY regs 672-703 */
     for (i=0; i<128; i+=4)
     {
-        u32_t regAddr = 0x9800 + (672 * 4);
         u32_t val;
 
         val = ((u32_t)vpd_chain1[i+3]<<24) |
@@ -3485,7 +3483,6 @@
     /* Write PHY regs 672-703 + 0x1000 */
     for (i=0; i<128; i+=4)
     {
-        u32_t regAddr = 0x9800 + (672 * 4) + 0x1000;
         u32_t val;
 
         val = ((u32_t)vpd_chain3[i+3]<<24) |
@@ -4584,7 +4581,6 @@
 void zfHpSetTTSIFSTime(zdev_t* dev, u8_t sifs_time)
 {
     u32_t reg_value = 0;
-    zmw_get_wlan_dev(dev);
 
     sifs_time &= 0x3f;
     reg_value = 0x14400b | (((u32_t)sifs_time)<<24);
diff --git a/drivers/staging/otus/hal/hpreg.c b/drivers/staging/otus/hal/hpreg.c
index d9894fe..178777c 100644
--- a/drivers/staging/otus/hal/hpreg.c
+++ b/drivers/staging/otus/hal/hpreg.c
@@ -786,45 +786,6 @@
 	WT1_5760_5800,
 };
 
-static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = {
-	{ 5130, 5210, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T1_5130_5210 */
-	{ 5250, 5330, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0},	/* T1_5250_5330 */
-	{ 5370, 5490, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T1_5370_5490 */
-	{ 5530, 5650, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0},	/* T1_5530_5650 */
-
-	{ 5150, 5190, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T1_5150_5190 */
-	{ 5230, 5310, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0},	/* T1_5230_5310 */
-	{ 5350, 5470, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T1_5350_5470 */
-	{ 5510, 5670, 5,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0},	/* T1_5510_5670 */
-
-	{ 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T1_5200_5240 */
-	{ 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T2_5200_5240 */
-	{ 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T1_5210_5210 */
-	{ 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T2_5210_5210 */
-
-	{ 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0},	/* T1_5280_5280 */
-	{ 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0},	/* T2_5280_5280 */
-	{ 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0},	/* T1_5250_5250 */
-	{ 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0},	/* T1_5290_5290 */
-	{ 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0},	/* T1_5250_5290 */
-	{ 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0},	/* T2_5250_5290 */
-
-	{ 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0},	/* T1_5540_5660 */
-	{ 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T1_5760_5800 */
-	{ 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T2_5760_5800 */
-
-	{ 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* T1_5765_5805 */
-
-	/*
-	 * Below are the WWR frequencies
-	 */
-
-	{ 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0}, /* WT1_5210_5250 */
-	{ 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0}, /* WT1_5290_5290 */
-	{ 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0}, /* WT1_5540_5660 */
-	{ 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR, 0, 0},	/* WT1_5760_5800 */
-};
-
 /*
  * 2GHz 11b channel tags
  */
@@ -864,45 +825,6 @@
 	W2_2484_2484,
 };
 
-static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = {
-	{ 2312, 2372, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* F1_2312_2372 */
-	{ 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* F2_2312_2372 */
-
-	{ 2412, 2472, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* F1_2412_2472 */
-	{ 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0, 0},	/* F2_2412_2472 */
-	{ 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* F3_2412_2472 */
-
-	{ 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* F1_2412_2462 */
-	{ 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0, 0},	/* F2_2412_2462 */
-	{ 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* F1_2432_2442 */
-
-	{ 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* F1_2457_2472 */
-
-	{ 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0, 0}, /* F1_2467_2472 */
-
-	{ 2484, 2484, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* F1_2484_2484 */
-	{ 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0, 0},	/* F2_2484_2484 */
-
-	{ 2512, 2732, 5,  6, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* F1_2512_2732 */
-
-	/*
-	 * WWR have powers opened up to 20dBm.  Limits should often come from CTL/Max powers
-	 */
-
-	{ 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* W1_2312_2372 */
-	{ 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* W1_2412_2412 */
-	{ 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* W1_2417_2432 */
-	{ 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* W1_2437_2442 */
-	{ 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* W1_2447_2457 */
-	{ 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0},	/* W1_2462_2462 */
-	{ 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* W1_2467_2467 */
-	{ 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0},	/* W2_2467_2467 */
-	{ 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* W1_2472_2472 */
-	{ 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0},	/* W2_2472_2472 */
-	{ 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* W1_2484_2484 */
-	{ 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0},	/* W2_2484_2484 */
-};
-
 
 /*
  * 2GHz 11g channel tags
@@ -984,16 +906,6 @@
 	T1_2512_2732
 };
 
-static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = {
-	{ 2312, 2372, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},  /* T1_2312_2372 */
-	{ 2437, 2437, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},  /* T1_2437_2437 */
-	{ 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},  /* T2_2437_2437 */
-	{ 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR, 0, 0}, /* T3_2437_2437 */
-	{ 2512, 2732, 5,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},  /* T1_2512_2732 */
-};
-
-
-
 /*
  * 2GHz 11n frequency tags
  */
@@ -1005,15 +917,6 @@
     NG_DEMO_ALL_CHANNELS,
 };
 
-static REG_DMN_FREQ_BAND regDmn2Ghz11ngFreq[] = {
-    { 2422, 2452, 20, 0, 40, 5, NO_DFS, NO_PSCAN, 0, 0},    /* NG1_2422_2452 */
-    { 2422, 2452, 27, 0, 40, 5, NO_DFS, NO_PSCAN, 0, 0},    /* NG2_2422_2452 */
-    { 2422, 2452, 30, 0, 40, 5, NO_DFS, NO_PSCAN, 0, 0},    /* NG3_2422_2452 */
-
-	{ 2312, 2732, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0},    /* NG_DEMO_ALL_CHANNELS */
-};
-
-
 /*
  * 5GHz 11n frequency tags
  */
@@ -1050,42 +953,6 @@
     NA_DEMO_ALL_CHANNELS,
 };
 
-static REG_DMN_FREQ_BAND regDmn5Ghz11naFreq[] = {
-    /*
-     * ToDo: This table needs to be completely populated with 5GHz 11n properties
-     */
-	{ 5190, 5230, 15,  0, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	    /* NA1_5190_5230 */
-	{ 5190, 5230, 17,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* NA2_5190_5230 */
-	{ 5190, 5230, 18,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	    /* NA3_5190_5230 */
-	{ 5190, 5230, 20,  0, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* NA4_5190_5230 */
-	{ 5190, 5230, 23,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	    /* NA5_5190_5230 */
-
-	{ 5270, 5270, 23,  6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1},  /* NA1_5270_5270 */
-
-	{ 5270, 5310, 18,  6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1},  /* NA1_5270_5310 */
-	{ 5270, 5310, 20,  0, 40, 40, DFS_FCC3|DFS_ETSI|DFS_MKK4, NO_PSCAN, 0, 1},  /* NA2_5270_5310 */
-	{ 5270, 5310, 23,  6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1},  /* NA3_5270_5310 */
-	{ 5270, 5310, 30,  6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1},  /* NA4_5270_5310 */
-
-	{ 5310, 5310, 17,  6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1},  /* NA1_5310_5310 */
-
-	{ 5510, 5630, 30,  6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1},  /* NA1_5510_5630 */
-
-	{ 5510, 5670, 20,  6, 40, 40, DFS_FCC3|DFS_ETSI|DFS_MKK4, NO_PSCAN, 0, 1},  /* NA1_5510_5670 */
-	{ 5510, 5670, 27,  0, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1},  /* NA2_5510_5670 */
-	{ 5510, 5670, 30,  6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 1},   /* NA3_5510_5670 */
-
-	{ 5755, 5795, 17,  0, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	    /* NA1_5755_5795 */
-	{ 5755, 5795, 20,  6, 40, 40, DFS_ETSI, NO_PSCAN, 0, 0},	    /* NA2_5755_5795 */
-	{ 5755, 5795, 23,  0, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	    /* NA3_5755_5795 */
-	{ 5755, 5795, 30,  0, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* NA4_5755_5795 */
-	{ 5755, 5795, 30,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	    /* NA5_5755_5795 */
-
-	{ 5795, 5795, 30,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	    /* NA1_5795_5795 */
-
-    { 4920, 6100, 30,  6, 40, 40, NO_DFS, NO_PSCAN, 0, 0},	/* NA_DEMO_ALL_CHANNELS */
-};
-
 typedef struct regDomain {
 	u16_t regDmnEnum;	/* value from EnumRd table */
 	u8_t conformanceTestLimit;
diff --git a/drivers/staging/otus/hal/hprw.c b/drivers/staging/otus/hal/hprw.c
index d9fad47..4dbd5fb 100644
--- a/drivers/staging/otus/hal/hprw.c
+++ b/drivers/staging/otus/hal/hprw.c
@@ -282,7 +282,6 @@
     else if (src == ZM_OID_FLASH_READ)
     {
         u32_t  datalen;
-        u16_t i;
 
         datalen = (rsp[0] & 255);
 
diff --git a/drivers/staging/otus/ioctl.c b/drivers/staging/otus/ioctl.c
index 6808e69..8c47b1a 100644
--- a/drivers/staging/otus/ioctl.c
+++ b/drivers/staging/otus/ioctl.c
@@ -866,15 +866,15 @@
 	char *current_ev = extra;
 	char *end_buf;
 	int i;
-	/* struct zsBssList BssList; */
-	struct zsBssListV1 *pBssList = kmalloc(sizeof(struct zsBssListV1),
-								GFP_KERNEL);
 	/* BssList = wd->sta.pBssList; */
 	/* zmw_get_wlan_dev(dev); */
 
 	if (macp->DeviceOpened != 1)
 		return 0;
 
+	/* struct zsBssList BssList; */
+	struct zsBssListV1 *pBssList = kmalloc(sizeof(struct zsBssListV1),
+								GFP_KERNEL);
 	if (data->length == 0)
 		end_buf = extra + IW_SCAN_MAX_DATA;
 	else
@@ -930,7 +930,7 @@
 		return -EINVAL;
 
 	if (essid->flags == 1) {
-		if (essid->length > (IW_ESSID_MAX_SIZE + 1))
+		if (essid->length > IW_ESSID_MAX_SIZE)
 			return -E2BIG;
 
 		if (copy_from_user(&EssidBuf, essid->pointer, essid->length))
@@ -2227,7 +2227,8 @@
 	case ZD_CMD_SCAN_REQ:
 		printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SCAN_REQ\n");
 		break;
-	case ZD_CMD_SET_GENERIC_ELEMENT:
+	case ZD_CMD_SET_GENERIC_ELEMENT: {
+		u8_t len, *wpaie;
 		printk(KERN_ERR "usbdrv_wpa_ioctl:"
 					" ZD_CMD_SET_GENERIC_ELEMENT\n");
 
@@ -2250,8 +2251,8 @@
 		/* zfiWlanSetWpaIe(dev, zdparm->u.generic_elem.data,
 		* zdparm->u.generic_elem.len);
 		*/
-		u8_t len = zdparm->u.generic_elem.len;
-		u8_t *wpaie = (u8_t *)zdparm->u.generic_elem.data;
+		len = zdparm->u.generic_elem.len;
+		wpaie = zdparm->u.generic_elem.data;
 
 		printk(KERN_ERR "wd->ap.wpaLen : % d\n", len);
 
@@ -2273,6 +2274,7 @@
 		* #endif
 		*/
 		break;
+	}
 
 	/* #ifdef ZM_HOSTAPD_SUPPORT */
 	case ZD_CMD_GET_TSC:
diff --git a/drivers/staging/otus/usbdrv.c b/drivers/staging/otus/usbdrv.c
index b0adbc8..5e6a120 100644
--- a/drivers/staging/otus/usbdrv.c
+++ b/drivers/staging/otus/usbdrv.c
@@ -829,7 +829,7 @@
 {
     /* Allocate net device structure */
     vap[vapId].dev = alloc_etherdev(0);
-    printk("Register vap dev=%x\n", (u32_t)vap[vapId].dev);
+    printk("Register vap dev=%p\n", vap[vapId].dev);
 
     if(vap[vapId].dev == NULL) {
         printk("alloc_etherdev fail\n");
@@ -883,7 +883,7 @@
     printk("Unregister VAP dev : %s\n", vap[vapId].dev->name);
 
     if(vap[vapId].dev != NULL) {
-        printk("Unregister vap dev=%x\n", (u32_t)vap[vapId].dev);
+        printk("Unregister vap dev=%p\n", vap[vapId].dev);
         //
         //unregister_netdevice(wds[wdsId].dev);
         unregister_netdev(vap[vapId].dev);
diff --git a/drivers/staging/otus/wrap_pkt.c b/drivers/staging/otus/wrap_pkt.c
index 75bb952..a2f5cb1 100644
--- a/drivers/staging/otus/wrap_pkt.c
+++ b/drivers/staging/otus/wrap_pkt.c
@@ -58,7 +58,7 @@
 			skb1 = skb_copy(buf, GFP_ATOMIC);
 			if (skb1 != NULL) {
 				skb1->dev = dev;
-				skb1->mac_header = skb1->data;
+				skb_reset_mac_header(skb1);
 				skb1->ip_summed = CHECKSUM_NONE;
 				skb1->pkt_type = PACKET_OTHERHOST;
 				/* ETH_P_80211_RAW */
@@ -85,13 +85,7 @@
 	/* new_buf = dev_alloc_skb(2048);	*/
 	new_buf = dev_alloc_skb(buf->len);
 
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-	new_buf->tail = 0;
-	new_buf->len = 0;
-#else
-	new_buf->tail = new_buf->data;
-	new_buf->len = 0;
-#endif
+	skb_reset_tail_pointer(new_buf);
 
 	skb_put(new_buf, buf->len);
 	memcpy(new_buf->data, buf->data, buf->len);
diff --git a/drivers/staging/otus/zdusb.c b/drivers/staging/otus/zdusb.c
index 2a6d937..4cd9b7f 100644
--- a/drivers/staging/otus/zdusb.c
+++ b/drivers/staging/otus/zdusb.c
@@ -45,7 +45,7 @@
 static const char driver_name[] = "Otus";
 
 /* table of devices that work with this driver */
-static struct usb_device_id zd1221_ids [] = {
+static const struct usb_device_id zd1221_ids[] = {
 	{ USB_DEVICE(VENDOR_ATHR, PRODUCT_AR9170) },
         { USB_DEVICE(VENDOR_DLINK, PRODUCT_DWA160A) },
 	{ USB_DEVICE(VENDOR_NETGEAR, PRODUCT_WNDA3100) },
diff --git a/drivers/staging/p9auth/Kconfig b/drivers/staging/p9auth/Kconfig
deleted file mode 100644
index d1c66d2..0000000
--- a/drivers/staging/p9auth/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-config PLAN9AUTH
-	tristate "Plan 9 style capability device implementation"
-	default n
-	depends on CRYPTO
-	help
-	  This module implements the Plan 9 style capability device.
-
-	  To compile this driver as a module, choose
-	  M here: the module will be called p9auth.
diff --git a/drivers/staging/p9auth/Makefile b/drivers/staging/p9auth/Makefile
deleted file mode 100644
index 3ebf6ff..0000000
--- a/drivers/staging/p9auth/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_PLAN9AUTH)	+= p9auth.o
diff --git a/drivers/staging/p9auth/p9auth.c b/drivers/staging/p9auth/p9auth.c
deleted file mode 100644
index db79626..0000000
--- a/drivers/staging/p9auth/p9auth.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Plan 9 style capability device implementation for the Linux Kernel
- *
- * Copyright 2008, 2009 Ashwin Ganti <ashwin.ganti@gmail.com>
- *
- * Released under the GPLv2
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/cdev.h>
-#include <linux/uaccess.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/crypto.h>
-#include <linux/highmem.h>
-#include <linux/scatterlist.h>
-#include <linux/sched.h>
-#include <linux/cred.h>
-
-#ifndef CAP_MAJOR
-#define CAP_MAJOR 0
-#endif
-
-#ifndef CAP_NR_DEVS
-#define CAP_NR_DEVS 2		/* caphash and capuse */
-#endif
-
-#ifndef CAP_NODE_SIZE
-#define CAP_NODE_SIZE 20
-#endif
-
-#define MAX_DIGEST_SIZE  20
-
-struct cap_node {
-	char data[CAP_NODE_SIZE];
-	struct list_head list;
-};
-
-struct cap_dev {
-	struct cap_node *head;
-	int node_size;
-	unsigned long size;
-	struct semaphore sem;
-	struct cdev cdev;
-};
-
-static int cap_major = CAP_MAJOR;
-static int cap_minor;
-static int cap_nr_devs = CAP_NR_DEVS;
-static int cap_node_size = CAP_NODE_SIZE;
-
-module_param(cap_major, int, S_IRUGO);
-module_param(cap_minor, int, S_IRUGO);
-module_param(cap_nr_devs, int, S_IRUGO);
-
-MODULE_AUTHOR("Ashwin Ganti");
-MODULE_LICENSE("GPL");
-
-static struct cap_dev *cap_devices;
-
-static void hexdump(unsigned char *buf, unsigned int len)
-{
-	while (len--)
-		printk("%02x", *buf++);
-	printk("\n");
-}
-
-static char *cap_hash(char *plain_text, unsigned int plain_text_size,
-		      char *key, unsigned int key_size)
-{
-	struct scatterlist sg;
-	char *result;
-	struct crypto_hash *tfm;
-	struct hash_desc desc;
-	int ret;
-
-	tfm = crypto_alloc_hash("hmac(sha1)", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(tfm)) {
-		printk(KERN_ERR
-		       "failed to load transform for hmac(sha1): %ld\n",
-		       PTR_ERR(tfm));
-		return NULL;
-	}
-
-	desc.tfm = tfm;
-	desc.flags = 0;
-
-	result = kzalloc(MAX_DIGEST_SIZE, GFP_KERNEL);
-	if (!result) {
-		printk(KERN_ERR "out of memory!\n");
-		goto out;
-	}
-
-	sg_set_buf(&sg, plain_text, plain_text_size);
-
-	ret = crypto_hash_setkey(tfm, key, key_size);
-	if (ret) {
-		printk(KERN_ERR "setkey() failed ret=%d\n", ret);
-		kfree(result);
-		result = NULL;
-		goto out;
-	}
-
-	ret = crypto_hash_digest(&desc, &sg, plain_text_size, result);
-	if (ret) {
-		printk(KERN_ERR "digest () failed ret=%d\n", ret);
-		kfree(result);
-		result = NULL;
-		goto out;
-	}
-
-	printk(KERN_DEBUG "crypto hash digest size %d\n",
-	       crypto_hash_digestsize(tfm));
-	hexdump(result, MAX_DIGEST_SIZE);
-
-out:
-	crypto_free_hash(tfm);
-	return result;
-}
-
-static int cap_trim(struct cap_dev *dev)
-{
-	struct cap_node *tmp;
-	struct list_head *pos, *q;
-	if (dev->head != NULL) {
-		list_for_each_safe(pos, q, &(dev->head->list)) {
-			tmp = list_entry(pos, struct cap_node, list);
-			list_del(pos);
-			kfree(tmp);
-		}
-	}
-	return 0;
-}
-
-static int cap_open(struct inode *inode, struct file *filp)
-{
-	struct cap_dev *dev;
-	dev = container_of(inode->i_cdev, struct cap_dev, cdev);
-	filp->private_data = dev;
-
-	/* trim to 0 the length of the device if open was write-only */
-	if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
-		if (down_interruptible(&dev->sem))
-			return -ERESTARTSYS;
-		cap_trim(dev);
-		up(&dev->sem);
-	}
-	/* initialise the head if it is NULL */
-	if (dev->head == NULL) {
-		dev->head = kmalloc(sizeof(struct cap_node), GFP_KERNEL);
-		INIT_LIST_HEAD(&(dev->head->list));
-	}
-	return 0;
-}
-
-static int cap_release(struct inode *inode, struct file *filp)
-{
-	return 0;
-}
-
-static ssize_t cap_write(struct file *filp, const char __user *buf,
-			 size_t count, loff_t *f_pos)
-{
-	struct cap_node *node_ptr, *tmp;
-	struct list_head *pos;
-	struct cap_dev *dev = filp->private_data;
-	ssize_t retval = -ENOMEM;
-	struct cred *new;
-	int len, target_int, source_int, flag = 0;
-	char *user_buf, *user_buf_running, *source_user, *target_user,
-	    *rand_str, *hash_str, *result;
-
-	if (down_interruptible(&dev->sem))
-		return -ERESTARTSYS;
-
-	user_buf_running = NULL;
-	hash_str = NULL;
-	node_ptr = kmalloc(sizeof(struct cap_node), GFP_KERNEL);
-	user_buf = kzalloc(count+1, GFP_KERNEL);
-	if (!node_ptr || !user_buf)
-		goto out;
-
-	if (copy_from_user(user_buf, buf, count)) {
-		retval = -EFAULT;
-		goto out;
-	}
-
-	/*
-	 * If the minor number is 0 ( /dev/caphash ) then simply add the
-	 * hashed capability supplied by the user to the list of hashes
-	 */
-	if (0 == iminor(filp->f_dentry->d_inode)) {
-		if (count > CAP_NODE_SIZE) {
-			retval = -EINVAL;
-			goto out;
-		}
-		printk(KERN_INFO "Capability being written to /dev/caphash : \n");
-		hexdump(user_buf, count);
-		memcpy(node_ptr->data, user_buf, count);
-		list_add(&(node_ptr->list), &(dev->head->list));
-		node_ptr = NULL;
-	} else {
-		char *tmpu;
-		if (!cap_devices[0].head ||
-				list_empty(&(cap_devices[0].head->list))) {
-			retval = -EINVAL;
-			goto out;
-		}
-		/*
-		 * break the supplied string into tokens with @ as the
-		 * delimiter If the string is "user1@user2@randomstring" we
-		 * need to split it and hash 'user1@user2' using 'randomstring'
-		 * as the key.
-		 */
-		tmpu = user_buf_running = kstrdup(user_buf, GFP_KERNEL);
-		source_user = strsep(&tmpu, "@");
-		target_user = strsep(&tmpu, "@");
-		rand_str = tmpu;
-		if (!source_user || !target_user || !rand_str) {
-			retval = -EINVAL;
-			goto out;
-		}
-
-		/* hash the string user1@user2 with rand_str as the key */
-		len = strlen(source_user) + strlen(target_user) + 1;
-		/* src, @, len, \0 */
-		hash_str = kzalloc(len+1, GFP_KERNEL);
-		strcat(hash_str, source_user);
-		strcat(hash_str, "@");
-		strcat(hash_str, target_user);
-
-		printk(KERN_ALERT "the source user is %s \n", source_user);
-		printk(KERN_ALERT "the target user is %s \n", target_user);
-
-		result = cap_hash(hash_str, len, rand_str, strlen(rand_str));
-		if (NULL == result) {
-			retval = -EFAULT;
-			goto out;
-		}
-		memcpy(node_ptr->data, result, CAP_NODE_SIZE);  /* why? */
-		/* Change the process's uid if the hash is present in the
-		 * list of hashes
-		 */
-		list_for_each(pos, &(cap_devices->head->list)) {
-			/*
-			 * Change the user id of the process if the hashes
-			 * match
-			 */
-			if (0 ==
-			    memcmp(result,
-				   list_entry(pos, struct cap_node,
-					      list)->data,
-				   CAP_NODE_SIZE)) {
-				target_int = (unsigned int)
-				    simple_strtol(target_user, NULL, 0);
-				source_int = (unsigned int)
-				    simple_strtol(source_user, NULL, 0);
-				flag = 1;
-
-				/*
-				 * Check whether the process writing to capuse
-				 * is actually owned by the source owner
-				 */
-				if (source_int != current_uid()) {
-					printk(KERN_ALERT
-					       "Process is not owned by the source user of the capability.\n");
-					retval = -EFAULT;
-					goto out;
-				}
-				/*
-				 * What all id's need to be changed here? uid,
-				 * euid, fsid, savedids ??  Currently I am
-				 * changing the effective user id since most of
-				 * the authorisation decisions are based on it
-				 */
-				new = prepare_creds();
-				if (!new) {
-					retval = -ENOMEM;
-					goto out;
-				}
-				new->uid = (uid_t) target_int;
-				new->euid = (uid_t) target_int;
-				retval = commit_creds(new);
-				if (retval)
-					goto out;
-
-				/*
-				 * Remove the capability from the list and
-				 * break
-				 */
-				tmp = list_entry(pos, struct cap_node, list);
-				list_del(pos);
-				kfree(tmp);
-				break;
-			}
-		}
-		if (0 == flag) {
-			/*
-			 * The capability is not present in the list of the
-			 * hashes stored, hence return failure
-			 */
-			printk(KERN_ALERT
-			       "Invalid capabiliy written to /dev/capuse \n");
-			retval = -EFAULT;
-			goto out;
-		}
-	}
-	*f_pos += count;
-	retval = count;
-	/* update the size */
-	if (dev->size < *f_pos)
-		dev->size = *f_pos;
-
-out:
-	kfree(node_ptr);
-	kfree(user_buf);
-	kfree(user_buf_running);
-	kfree(hash_str);
-	up(&dev->sem);
-	return retval;
-}
-
-static const struct file_operations cap_fops = {
-	.owner = THIS_MODULE,
-	.write = cap_write,
-	.open = cap_open,
-	.release = cap_release,
-};
-
-/* no __exit here because it can be called by the init function */
-static void cap_cleanup_module(void)
-{
-	int i;
-	dev_t devno = MKDEV(cap_major, cap_minor);
-	if (cap_devices) {
-		for (i = 0; i < cap_nr_devs; i++) {
-			cap_trim(cap_devices + i);
-			cdev_del(&cap_devices[i].cdev);
-		}
-		kfree(cap_devices);
-	}
-	unregister_chrdev_region(devno, cap_nr_devs);
-
-}
-
-static void cap_setup_cdev(struct cap_dev *dev, int index)
-{
-	int err, devno = MKDEV(cap_major, cap_minor + index);
-	cdev_init(&dev->cdev, &cap_fops);
-	dev->cdev.owner = THIS_MODULE;
-	dev->cdev.ops = &cap_fops;
-	err = cdev_add(&dev->cdev, devno, 1);
-	if (err)
-		printk(KERN_NOTICE "Error %d adding cap%d", err, index);
-}
-
-static int __init cap_init_module(void)
-{
-	int result, i;
-	dev_t dev = 0;
-
-	if (cap_major) {
-		dev = MKDEV(cap_major, cap_minor);
-		result = register_chrdev_region(dev, cap_nr_devs, "cap");
-	} else {
-		result = alloc_chrdev_region(&dev, cap_minor, cap_nr_devs,
-					     "cap");
-		cap_major = MAJOR(dev);
-	}
-
-	if (result < 0) {
-		printk(KERN_WARNING "cap: can't get major %d\n",
-		       cap_major);
-		return result;
-	}
-
-	cap_devices = kzalloc(cap_nr_devs * sizeof(struct cap_dev),
-			      GFP_KERNEL);
-	if (!cap_devices) {
-		result = -ENOMEM;
-		goto fail;
-	}
-
-	/* Initialize each device. */
-	for (i = 0; i < cap_nr_devs; i++) {
-		cap_devices[i].node_size = cap_node_size;
-		init_MUTEX(&cap_devices[i].sem);
-		cap_setup_cdev(&cap_devices[i], i);
-	}
-
-	return 0;
-
-fail:
-	cap_cleanup_module();
-	return result;
-}
-
-module_init(cap_init_module);
-module_exit(cap_cleanup_module);
-
-
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index 95c93e8..377884f 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -41,7 +41,6 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
diff --git a/drivers/staging/phison/phison.c b/drivers/staging/phison/phison.c
index fcba78d..0c495ea 100644
--- a/drivers/staging/phison/phison.c
+++ b/drivers/staging/phison/phison.c
@@ -69,7 +69,7 @@
 	return ret;
 }
 
-static struct pci_device_id phison_pci_tbl[] = {
+static const struct pci_device_id phison_pci_tbl[] = {
 	{ PCI_VENDOR_ID_PHISON, PCI_DEVICE_ID_PS5000, PCI_ANY_ID, PCI_ANY_ID,
 	  PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 },
 	{ 0, },
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index f69b778..6327552 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -36,6 +36,7 @@
 #define POHMELFS_MAGIC_NUM	0x504f482e
 
 static struct kmem_cache *pohmelfs_inode_cache;
+static atomic_t psb_bdi_num = ATOMIC_INIT(0);
 
 /*
  * Removes inode from all trees, drops local name cache and removes all queued
@@ -322,7 +323,7 @@
 	t = netfs_trans_alloc(psb, err + 1, 0, 0);
 	if (!t) {
 		err = -ENOMEM;
-		goto err_out_put;
+		goto err_out_exit;
 	}
 	t->complete = pohmelfs_write_inode_complete;
 	t->private = igrab(inode);
@@ -395,7 +396,8 @@
 /*
  * Writeback for given inode.
  */
-static int pohmelfs_write_inode(struct inode *inode, int sync)
+static int pohmelfs_write_inode(struct inode *inode,
+				struct writeback_control *wbc)
 {
 	struct pohmelfs_inode *pi = POHMELFS_I(inode);
 
@@ -969,7 +971,7 @@
 
 	if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
 	    (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
-		err = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0;
+		err = dquot_transfer(inode, attr);
 		if (err)
 			goto err_out_exit;
 	}
@@ -1331,6 +1333,8 @@
 	pohmelfs_crypto_exit(psb);
 	pohmelfs_state_exit(psb);
 
+	bdi_destroy(&psb->bdi);
+
 	kfree(psb);
 	sb->s_fs_info = NULL;
 }
@@ -1767,8 +1771,7 @@
 		seq_printf(m, "%u ", ctl->idx);
 		if (ctl->addr.sa_family == AF_INET) {
 			struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr;
-			/* seq_printf(m, "%pi4:%u", &sin->sin_addr.s_addr, ntohs(sin->sin_port)); */
-			seq_printf(m, "%u.%u.%u.%u:%u", NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port));
+			seq_printf(m, "%pI4:%u", &sin->sin_addr.s_addr, ntohs(sin->sin_port));
 		} else if (ctl->addr.sa_family == AF_INET6) {
 			struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr;
 			seq_printf(m, "%pi6:%u", &sin->sin6_addr, ntohs(sin->sin6_port));
@@ -1815,11 +1818,22 @@
 	if (!psb)
 		goto err_out_exit;
 
+	err = bdi_init(&psb->bdi);
+	if (err)
+		goto err_out_free_sb;
+
+	err = bdi_register(&psb->bdi, NULL, "pfs-%d", atomic_inc_return(&psb_bdi_num));
+	if (err) {
+		bdi_destroy(&psb->bdi);
+		goto err_out_free_sb;
+	}
+
 	sb->s_fs_info = psb;
 	sb->s_op = &pohmelfs_sb_ops;
 	sb->s_magic = POHMELFS_MAGIC_NUM;
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
 	sb->s_blocksize = PAGE_SIZE;
+	sb->s_bdi = &psb->bdi;
 
 	psb->sb = sb;
 
@@ -1863,11 +1877,11 @@
 
 	err = pohmelfs_parse_options((char *) data, psb, 0);
 	if (err)
-		goto err_out_free_sb;
+		goto err_out_free_bdi;
 
 	err = pohmelfs_copy_crypto(psb);
 	if (err)
-		goto err_out_free_sb;
+		goto err_out_free_bdi;
 
 	err = pohmelfs_state_init(psb);
 	if (err)
@@ -1916,6 +1930,8 @@
 err_out_free_strings:
 	kfree(psb->cipher_string);
 	kfree(psb->hash_string);
+err_out_free_bdi:
+	bdi_destroy(&psb->bdi);
 err_out_free_sb:
 	kfree(psb);
 err_out_exit:
diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
index 623a07d..01cba00 100644
--- a/drivers/staging/pohmelfs/netfs.h
+++ b/drivers/staging/pohmelfs/netfs.h
@@ -18,6 +18,7 @@
 
 #include <linux/types.h>
 #include <linux/connector.h>
+#include <linux/backing-dev.h>
 
 #define POHMELFS_CN_IDX			5
 #define POHMELFS_CN_VAL			0
@@ -624,6 +625,8 @@
 
 	struct super_block	*sb;
 
+	struct backing_dev_info	bdi;
+
 	/*
 	 * Algorithm strings.
 	 */
diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c
index f7726f1..1561f74 100644
--- a/drivers/staging/quatech_usb2/quatech_usb2.c
+++ b/drivers/staging/quatech_usb2/quatech_usb2.c
@@ -116,7 +116,7 @@
 #define FOURTHCHAR	((unsigned char *)(urb->transfer_buffer))[i + 3]
 #define FIFTHCHAR	((unsigned char *)(urb->transfer_buffer))[i + 4]
 
-static struct usb_device_id quausb2_id_table[] = {
+static const struct usb_device_id quausb2_id_table[] = {
 	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU2_100)},
 	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_100)},
 	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_400)},
diff --git a/drivers/staging/ramzswap/Kconfig b/drivers/staging/ramzswap/Kconfig
index 24e2569..127b3c6 100644
--- a/drivers/staging/ramzswap/Kconfig
+++ b/drivers/staging/ramzswap/Kconfig
@@ -5,7 +5,7 @@
 	select LZO_DECOMPRESS
 	default n
 	help
-	  Creates virtual block devices which can be used (only) as a swap
+	  Creates virtual block devices which can (only) be used as swap
 	  disks. Pages swapped to these disks are compressed and stored in
 	  memory itself.
 
diff --git a/drivers/staging/ramzswap/ramzswap.txt b/drivers/staging/ramzswap/ramzswap.txt
index e9f1619..9694acf 100644
--- a/drivers/staging/ramzswap/ramzswap.txt
+++ b/drivers/staging/ramzswap/ramzswap.txt
@@ -5,9 +5,9 @@
 
 * Introduction
 
-It creates RAM based block devices which can be used (only) as swap disks.
-Pages swapped to these devices are compressed and stored in memory itself.
-See project home for use cases, performance numbers and a lot more.
+The ramzswap module creates RAM based block devices which can (only) be used as
+swap disks. Pages swapped to these devices are compressed and stored in memory
+itself. See project home for use cases, performance numbers and a lot more.
 
 Individual ramzswap devices are configured and initialized using rzscontrol
 userspace utility as shown in examples below. See rzscontrol man page for more
diff --git a/drivers/staging/ramzswap/ramzswap_drv.c b/drivers/staging/ramzswap/ramzswap_drv.c
index 989fac5..5e422e2 100644
--- a/drivers/staging/ramzswap/ramzswap_drv.c
+++ b/drivers/staging/ramzswap/ramzswap_drv.c
@@ -1,7 +1,7 @@
 /*
  * Compressed RAM based swap device
  *
- * Copyright (C) 2008, 2009  Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010  Nitin Gupta
  *
  * This code is released using a dual license strategy: BSD/GPL
  * You can choose the licence that better fits your requirements.
@@ -24,12 +24,10 @@
 #include <linux/genhd.h>
 #include <linux/highmem.h>
 #include <linux/lzo.h>
-#include <linux/mutex.h>
 #include <linux/string.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
 #include <linux/vmalloc.h>
-#include <linux/version.h>
 
 #include "ramzswap_drv.h"
 
@@ -222,7 +220,7 @@
 	return ret;
 }
 
-void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
+static void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
 			struct ramzswap_ioctl_stats *s)
 {
 	strncpy(s->backing_swap_name, rzs->backing_swap_name,
@@ -240,7 +238,8 @@
 
 	mem_used = xv_get_total_size_bytes(rzs->mem_pool)
 			+ (rs->pages_expand << PAGE_SHIFT);
-	succ_writes = rs->num_writes - rs->failed_writes;
+	succ_writes = rzs_stat64_read(rzs, &rs->num_writes) -
+			rzs_stat64_read(rzs, &rs->failed_writes);
 
 	if (succ_writes && rs->pages_stored) {
 		good_compress_perc = rs->good_compress * 100
@@ -249,11 +248,12 @@
 					/ rs->pages_stored;
 	}
 
-	s->num_reads = rs->num_reads;
-	s->num_writes = rs->num_writes;
-	s->failed_reads = rs->failed_reads;
-	s->failed_writes = rs->failed_writes;
-	s->invalid_io = rs->invalid_io;
+	s->num_reads = rzs_stat64_read(rzs, &rs->num_reads);
+	s->num_writes = rzs_stat64_read(rzs, &rs->num_writes);
+	s->failed_reads = rzs_stat64_read(rzs, &rs->failed_reads);
+	s->failed_writes = rzs_stat64_read(rzs, &rs->failed_writes);
+	s->invalid_io = rzs_stat64_read(rzs, &rs->invalid_io);
+	s->notify_free = rzs_stat64_read(rzs, &rs->notify_free);
 	s->pages_zero = rs->pages_zero;
 
 	s->good_compress_pct = good_compress_perc;
@@ -265,8 +265,8 @@
 	s->compr_data_size = rs->compr_size;
 	s->mem_used_total = mem_used;
 
-	s->bdev_num_reads = rs->bdev_num_reads;
-	s->bdev_num_writes = rs->bdev_num_writes;
+	s->bdev_num_reads = rzs_stat64_read(rzs, &rs->bdev_num_reads);
+	s->bdev_num_writes = rzs_stat64_read(rzs, &rs->bdev_num_writes);
 	}
 #endif /* CONFIG_RAMZSWAP_STATS */
 }
@@ -502,6 +502,14 @@
 			goto bad_param;
 		}
 		disksize = i_size_read(inode);
+		/*
+		 * Can happen if user gives an extended partition as
+		 * backing swap or simply a bad disk.
+		 */
+		if (!disksize) {
+			pr_err("Error reading backing swap size.\n");
+			goto bad_param;
+		}
 	} else if (S_ISREG(inode->i_mode)) {
 		bdev = inode->i_sb->s_bdev;
 		if (IS_SWAPFILE(inode)) {
@@ -519,7 +527,6 @@
 	rzs->swap_file = swap_file;
 	rzs->backing_swap = bdev;
 	rzs->disksize = disksize;
-	BUG_ON(!rzs->disksize);
 
 	return 0;
 
@@ -537,7 +544,7 @@
  * Map logical page number 'pagenum' to physical page number
  * on backing swap device. For block device, this is a nop.
  */
-u32 map_backing_swap_page(struct ramzswap *rzs, u32 pagenum)
+static u32 map_backing_swap_page(struct ramzswap *rzs, u32 pagenum)
 {
 	u32 skip_pages, entries_per_page;
 	size_t delta, se_offset, skipped;
@@ -593,9 +600,13 @@
 	u32 offset = rzs->table[index].offset;
 
 	if (unlikely(!page)) {
+		/*
+		 * No memory is allocated for zero filled pages.
+		 * Simply clear zero page flag.
+		 */
 		if (rzs_test_flag(rzs, index, RZS_ZERO)) {
 			rzs_clear_flag(rzs, index, RZS_ZERO);
-			stat_dec(rzs->stats.pages_zero);
+			rzs_stat_dec(&rzs->stats.pages_zero);
 		}
 		return;
 	}
@@ -604,7 +615,7 @@
 		clen = PAGE_SIZE;
 		__free_page(page);
 		rzs_clear_flag(rzs, index, RZS_UNCOMPRESSED);
-		stat_dec(rzs->stats.pages_expand);
+		rzs_stat_dec(&rzs->stats.pages_expand);
 		goto out;
 	}
 
@@ -614,11 +625,11 @@
 
 	xv_free(rzs->mem_pool, page, offset);
 	if (clen <= PAGE_SIZE / 2)
-		stat_dec(rzs->stats.good_compress);
+		rzs_stat_dec(&rzs->stats.good_compress);
 
 out:
 	rzs->stats.compr_size -= clen;
-	stat_dec(rzs->stats.pages_stored);
+	rzs_stat_dec(&rzs->stats.pages_stored);
 
 	rzs->table[index].page = NULL;
 	rzs->table[index].offset = 0;
@@ -664,7 +675,6 @@
 	return 0;
 }
 
-
 /*
  * Called when request page is not present in ramzswap.
  * Its either in backing swap device (if present) or
@@ -680,8 +690,8 @@
 	 */
 	if (rzs->backing_swap) {
 		u32 pagenum;
-		stat_dec(rzs->stats.num_reads);
-		stat_inc(rzs->stats.bdev_num_reads);
+		rzs_stat64_dec(rzs, &rzs->stats.num_reads);
+		rzs_stat64_inc(rzs, &rzs->stats.bdev_num_reads);
 		bio->bi_bdev = rzs->backing_swap;
 
 		/*
@@ -719,7 +729,7 @@
 	struct zobj_header *zheader;
 	unsigned char *user_mem, *cmem;
 
-	stat_inc(rzs->stats.num_reads);
+	rzs_stat64_inc(rzs, &rzs->stats.num_reads);
 
 	page = bio->bi_io_vec[0].bv_page;
 	index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
@@ -731,7 +741,7 @@
 	if (!rzs->table[index].page)
 		return handle_ramzswap_fault(rzs, bio);
 
-	/* Page is stored uncompressed since its incompressible */
+	/* Page is stored uncompressed since it's incompressible */
 	if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)))
 		return handle_uncompressed_page(rzs, bio);
 
@@ -753,7 +763,7 @@
 	if (unlikely(ret != LZO_E_OK)) {
 		pr_err("Decompression failed! err=%d, page=%u\n",
 			ret, index);
-		stat_inc(rzs->stats.failed_reads);
+		rzs_stat64_inc(rzs, &rzs->stats.failed_reads);
 		goto out;
 	}
 
@@ -777,7 +787,7 @@
 	struct page *page, *page_store;
 	unsigned char *user_mem, *cmem, *src;
 
-	stat_inc(rzs->stats.num_writes);
+	rzs_stat64_inc(rzs, &rzs->stats.num_writes);
 
 	page = bio->bi_io_vec[0].bv_page;
 	index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
@@ -789,25 +799,16 @@
 	 * is no longer referenced by any process. So, its now safe
 	 * to free the memory that was allocated for this page.
 	 */
-	if (rzs->table[index].page)
+	if (rzs->table[index].page || rzs_test_flag(rzs, index, RZS_ZERO))
 		ramzswap_free_page(rzs, index);
 
-	/*
-	 * No memory ia allocated for zero filled pages.
-	 * Simply clear zero page flag.
-	 */
-	if (rzs_test_flag(rzs, index, RZS_ZERO)) {
-		stat_dec(rzs->stats.pages_zero);
-		rzs_clear_flag(rzs, index, RZS_ZERO);
-	}
-
 	mutex_lock(&rzs->lock);
 
 	user_mem = kmap_atomic(page, KM_USER0);
 	if (page_zero_filled(user_mem)) {
 		kunmap_atomic(user_mem, KM_USER0);
 		mutex_unlock(&rzs->lock);
-		stat_inc(rzs->stats.pages_zero);
+		rzs_stat_inc(&rzs->stats.pages_zero);
 		rzs_set_flag(rzs, index, RZS_ZERO);
 
 		set_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -831,7 +832,7 @@
 	if (unlikely(ret != LZO_E_OK)) {
 		mutex_unlock(&rzs->lock);
 		pr_err("Compression failed! err=%d\n", ret);
-		stat_inc(rzs->stats.failed_writes);
+		rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
 		goto out;
 	}
 
@@ -854,13 +855,13 @@
 			mutex_unlock(&rzs->lock);
 			pr_info("Error allocating memory for incompressible "
 				"page: %u\n", index);
-			stat_inc(rzs->stats.failed_writes);
+			rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
 			goto out;
 		}
 
 		offset = 0;
 		rzs_set_flag(rzs, index, RZS_UNCOMPRESSED);
-		stat_inc(rzs->stats.pages_expand);
+		rzs_stat_inc(&rzs->stats.pages_expand);
 		rzs->table[index].page = page_store;
 		src = kmap_atomic(page, KM_USER0);
 		goto memstore;
@@ -872,7 +873,7 @@
 		mutex_unlock(&rzs->lock);
 		pr_info("Error allocating memory for compressed "
 			"page: %u, size=%zu\n", index, clen);
-		stat_inc(rzs->stats.failed_writes);
+		rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
 		if (rzs->backing_swap)
 			fwd_write_request = 1;
 		goto out;
@@ -901,9 +902,9 @@
 
 	/* Update stats */
 	rzs->stats.compr_size += clen;
-	stat_inc(rzs->stats.pages_stored);
+	rzs_stat_inc(&rzs->stats.pages_stored);
 	if (clen <= PAGE_SIZE / 2)
-		stat_inc(rzs->stats.good_compress);
+		rzs_stat_inc(&rzs->stats.good_compress);
 
 	mutex_unlock(&rzs->lock);
 
@@ -913,7 +914,7 @@
 
 out:
 	if (fwd_write_request) {
-		stat_inc(rzs->stats.bdev_num_writes);
+		rzs_stat64_inc(rzs, &rzs->stats.bdev_num_writes);
 		bio->bi_bdev = rzs->backing_swap;
 #if 0
 		/*
@@ -941,7 +942,6 @@
 	return 0;
 }
 
-
 /*
  * Check if request is within bounds and page aligned.
  */
@@ -975,7 +975,7 @@
 	}
 
 	if (!valid_swap_request(rzs, bio)) {
-		stat_inc(rzs->stats.invalid_io);
+		rzs_stat64_inc(rzs, &rzs->stats.invalid_io);
 		bio_io_error(bio);
 		return 0;
 	}
@@ -1000,6 +1000,9 @@
 	unsigned entries_per_page;
 	unsigned long num_table_pages, entry = 0;
 
+	/* Do not accept any new I/O request */
+	rzs->init_done = 0;
+
 	if (rzs->backing_swap && !rzs->num_extents)
 		is_backing_blkdev = 1;
 
@@ -1066,6 +1069,7 @@
 			bd_release(rzs->backing_swap);
 		filp_close(rzs->swap_file, NULL);
 		rzs->backing_swap = NULL;
+		memset(rzs->backing_swap_name, 0, MAX_SWAP_NAME_LEN);
 	}
 
 	/* Reset stats */
@@ -1073,9 +1077,6 @@
 
 	rzs->disksize = 0;
 	rzs->memlimit = 0;
-
-	/* Back to uninitialized state */
-	rzs->init_done = 0;
 }
 
 static int ramzswap_ioctl_init_device(struct ramzswap *rzs)
@@ -1276,6 +1277,11 @@
 			ret = -EBUSY;
 			goto out;
 		}
+
+		/* Make sure all pending I/O is finished */
+		if (bdev)
+			fsync_bdev(bdev);
+
 		ret = ramzswap_ioctl_reset_device(rzs);
 		break;
 
@@ -1293,16 +1299,20 @@
 	.owner = THIS_MODULE,
 };
 
-static void create_device(struct ramzswap *rzs, int device_id)
+static int create_device(struct ramzswap *rzs, int device_id)
 {
+	int ret = 0;
+
 	mutex_init(&rzs->lock);
+	spin_lock_init(&rzs->stat64_lock);
 	INIT_LIST_HEAD(&rzs->backing_swap_extent_list);
 
 	rzs->queue = blk_alloc_queue(GFP_KERNEL);
 	if (!rzs->queue) {
 		pr_err("Error allocating disk queue for device %d\n",
 			device_id);
-		return;
+		ret = -ENOMEM;
+		goto out;
 	}
 
 	blk_queue_make_request(rzs->queue, ramzswap_make_request);
@@ -1314,7 +1324,8 @@
 		blk_cleanup_queue(rzs->queue);
 		pr_warning("Error allocating disk structure for device %d\n",
 			device_id);
-		return;
+		ret = -ENOMEM;
+		goto out;
 	}
 
 	rzs->disk->major = ramzswap_major;
@@ -1329,9 +1340,16 @@
 	 * or set equal to backing swap device (if provided)
 	 */
 	set_capacity(rzs->disk, 0);
+
+	blk_queue_physical_block_size(rzs->disk->queue, PAGE_SIZE);
+	blk_queue_logical_block_size(rzs->disk->queue, PAGE_SIZE);
+
 	add_disk(rzs->disk);
 
 	rzs->init_done = 0;
+
+out:
+	return ret;
 }
 
 static void destroy_device(struct ramzswap *rzs)
@@ -1347,18 +1365,20 @@
 
 static int __init ramzswap_init(void)
 {
-	int i, ret;
+	int ret, dev_id;
 
 	if (num_devices > max_num_devices) {
 		pr_warning("Invalid value for num_devices: %u\n",
 				num_devices);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	ramzswap_major = register_blkdev(0, "ramzswap");
 	if (ramzswap_major <= 0) {
 		pr_warning("Unable to get major number\n");
-		return -EBUSY;
+		ret = -EBUSY;
+		goto out;
 	}
 
 	if (!num_devices) {
@@ -1371,15 +1391,23 @@
 	devices = kzalloc(num_devices * sizeof(struct ramzswap), GFP_KERNEL);
 	if (!devices) {
 		ret = -ENOMEM;
-		goto out;
+		goto unregister;
 	}
 
-	for (i = 0; i < num_devices; i++)
-		create_device(&devices[i], i);
+	for (dev_id = 0; dev_id < num_devices; dev_id++) {
+		ret = create_device(&devices[dev_id], dev_id);
+		if (ret)
+			goto free_devices;
+	}
 
 	return 0;
-out:
+
+free_devices:
+	while (dev_id)
+		destroy_device(&devices[--dev_id]);
+unregister:
 	unregister_blkdev(ramzswap_major, "ramzswap");
+out:
 	return ret;
 }
 
diff --git a/drivers/staging/ramzswap/ramzswap_drv.h b/drivers/staging/ramzswap/ramzswap_drv.h
index a6ea240..c7e0e76 100644
--- a/drivers/staging/ramzswap/ramzswap_drv.h
+++ b/drivers/staging/ramzswap/ramzswap_drv.h
@@ -1,7 +1,7 @@
 /*
  * Compressed RAM based swap device
  *
- * Copyright (C) 2008, 2009  Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010  Nitin Gupta
  *
  * This code is released using a dual license strategy: BSD/GPL
  * You can choose the licence that better fits your requirements.
@@ -15,6 +15,9 @@
 #ifndef _RAMZSWAP_DRV_H_
 #define _RAMZSWAP_DRV_H_
 
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+
 #include "ramzswap_ioctl.h"
 #include "xvmalloc.h"
 
@@ -71,15 +74,6 @@
 #define SECTORS_PER_PAGE_SHIFT	(PAGE_SHIFT - SECTOR_SHIFT)
 #define SECTORS_PER_PAGE	(1 << SECTORS_PER_PAGE_SHIFT)
 
-/* Debugging and Stats */
-#if defined(CONFIG_RAMZSWAP_STATS)
-#define stat_inc(stat)	((stat)++)
-#define stat_dec(stat)	((stat)--)
-#else
-#define stat_inc(x)
-#define stat_dec(x)
-#endif
-
 /* Flags for ramzswap pages (table[page_no].flags) */
 enum rzs_pageflags {
 	/* Page is stored uncompressed */
@@ -102,7 +96,7 @@
 	u16 offset;
 	u8 count;	/* object ref count (not yet used) */
 	u8 flags;
-} __attribute__((aligned(4)));;
+} __attribute__((aligned(4)));
 
 /*
  * Swap extent information in case backing swap is a regular
@@ -121,9 +115,10 @@
 #if defined(CONFIG_RAMZSWAP_STATS)
 	u64 num_reads;		/* failed + successful */
 	u64 num_writes;		/* --do-- */
-	u64 failed_reads;	/* can happen when memory is too low */
-	u64 failed_writes;	/* should NEVER! happen */
+	u64 failed_reads;	/* should NEVER! happen */
+	u64 failed_writes;	/* can happen when memory is too low */
 	u64 invalid_io;		/* non-swap I/O requests */
+	u64 notify_free;	/* no. of swap slot free notifications */
 	u32 pages_zero;		/* no. of zero filled pages */
 	u32 pages_stored;	/* no. of pages currently stored */
 	u32 good_compress;	/* % of pages with compression ratio<=50% */
@@ -138,6 +133,7 @@
 	void *compress_workmem;
 	void *compress_buffer;
 	struct table *table;
+	spinlock_t stat64_lock;	/* protect 64-bit stats */
 	struct mutex lock;
 	struct request_queue *queue;
 	struct gendisk *disk;
@@ -167,5 +163,48 @@
 
 /*-- */
 
-#endif
+/* Debugging and Stats */
+#if defined(CONFIG_RAMZSWAP_STATS)
+static void rzs_stat_inc(u32 *v)
+{
+	*v = *v + 1;
+}
 
+static void rzs_stat_dec(u32 *v)
+{
+	*v = *v - 1;
+}
+
+static void rzs_stat64_inc(struct ramzswap *rzs, u64 *v)
+{
+	spin_lock(&rzs->stat64_lock);
+	*v = *v + 1;
+	spin_unlock(&rzs->stat64_lock);
+}
+
+static void rzs_stat64_dec(struct ramzswap *rzs, u64 *v)
+{
+	spin_lock(&rzs->stat64_lock);
+	*v = *v - 1;
+	spin_unlock(&rzs->stat64_lock);
+}
+
+static u64 rzs_stat64_read(struct ramzswap *rzs, u64 *v)
+{
+	u64 val;
+
+	spin_lock(&rzs->stat64_lock);
+	val = *v;
+	spin_unlock(&rzs->stat64_lock);
+
+	return val;
+}
+#else
+#define rzs_stat_inc(v)
+#define rzs_stat_dec(v)
+#define rzs_stat64_inc(r, v)
+#define rzs_stat64_dec(r, v)
+#define rzs_stat64_read(r, v)
+#endif /* CONFIG_RAMZSWAP_STATS */
+
+#endif
diff --git a/drivers/staging/ramzswap/ramzswap_ioctl.h b/drivers/staging/ramzswap/ramzswap_ioctl.h
index c713a09..d26076d 100644
--- a/drivers/staging/ramzswap/ramzswap_ioctl.h
+++ b/drivers/staging/ramzswap/ramzswap_ioctl.h
@@ -1,7 +1,7 @@
 /*
  * Compressed RAM based swap device
  *
- * Copyright (C) 2008, 2009  Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010  Nitin Gupta
  *
  * This code is released using a dual license strategy: BSD/GPL
  * You can choose the licence that better fits your requirements.
@@ -24,9 +24,10 @@
 				 * size (if present) */
 	u64 num_reads;		/* failed + successful */
 	u64 num_writes;		/* --do-- */
-	u64 failed_reads;	/* can happen when memory is too low */
-	u64 failed_writes;	/* should NEVER! happen */
+	u64 failed_reads;	/* should NEVER! happen */
+	u64 failed_writes;	/* can happen when memory is too low */
 	u64 invalid_io;		/* non-swap I/O requests */
+	u64 notify_free;	/* no. of swap slot free notifications */
 	u32 pages_zero;		/* no. of zero filled pages */
 	u32 good_compress_pct;	/* no. of pages with compression ratio<=50% */
 	u32 pages_expand_pct;	/* no. of incompressible pages */
diff --git a/drivers/staging/ramzswap/xvmalloc.c b/drivers/staging/ramzswap/xvmalloc.c
index b3e986c..3fdbb8a 100644
--- a/drivers/staging/ramzswap/xvmalloc.c
+++ b/drivers/staging/ramzswap/xvmalloc.c
@@ -1,7 +1,7 @@
 /*
  * xvmalloc memory allocator
  *
- * Copyright (C) 2008, 2009  Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010  Nitin Gupta
  *
  * This code is released using a dual license strategy: BSD/GPL
  * You can choose the licence that better fits your requirements.
@@ -273,7 +273,7 @@
 }
 
 /*
- * Allocate a page and add it freelist of given pool.
+ * Allocate a page and add it to freelist of given pool.
  */
 static int grow_pool(struct xv_pool *pool, gfp_t flags)
 {
diff --git a/drivers/staging/ramzswap/xvmalloc.h b/drivers/staging/ramzswap/xvmalloc.h
index 010c6fe..5b1a81a 100644
--- a/drivers/staging/ramzswap/xvmalloc.h
+++ b/drivers/staging/ramzswap/xvmalloc.h
@@ -1,7 +1,7 @@
 /*
  * xvmalloc memory allocator
  *
- * Copyright (C) 2008, 2009  Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010  Nitin Gupta
  *
  * This code is released using a dual license strategy: BSD/GPL
  * You can choose the licence that better fits your requirements.
diff --git a/drivers/staging/ramzswap/xvmalloc_int.h b/drivers/staging/ramzswap/xvmalloc_int.h
index 03c1a65..e23ed5c 100644
--- a/drivers/staging/ramzswap/xvmalloc_int.h
+++ b/drivers/staging/ramzswap/xvmalloc_int.h
@@ -1,7 +1,7 @@
 /*
  * xvmalloc memory allocator
  *
- * Copyright (C) 2008, 2009  Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010  Nitin Gupta
  *
  * This code is released using a dual license strategy: BSD/GPL
  * You can choose the licence that better fits your requirements.
@@ -62,7 +62,7 @@
 
 struct block_header {
 	union {
-		/* This common header must be ALIGN bytes */
+		/* This common header must be XV_ALIGN bytes */
 		u8 common[XV_ALIGN];
 		struct {
 			u16 size;
diff --git a/drivers/staging/rar/Kconfig b/drivers/staging/rar/Kconfig
deleted file mode 100644
index 17f8bf3..0000000
--- a/drivers/staging/rar/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# RAR device configuration
-#
-
-menu "RAR Register Driver"
-#
-#	Restricted Access Register Manager
-#
-config RAR_REGISTER
-	tristate "Restricted Access Region Register Driver"
-	default n
-	---help---
-		This driver allows other kernel drivers access to the
-		contents of the restricted access region control
-		registers.
-
-endmenu
diff --git a/drivers/staging/rar/Makefile b/drivers/staging/rar/Makefile
deleted file mode 100644
index 5422ed0..0000000
--- a/drivers/staging/rar/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-EXTRA_CFLAGS += -DLITTLE__ENDIAN
-obj-$(CONFIG_RAR_REGISTER) += rar_driver.o
diff --git a/drivers/staging/rar/rar_driver.c b/drivers/staging/rar/rar_driver.c
deleted file mode 100644
index d85d189..0000000
--- a/drivers/staging/rar/rar_driver.c
+++ /dev/null
@@ -1,444 +0,0 @@
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/kdev_t.h>
-#include <linux/semaphore.h>
-#include <linux/mm.h>
-#include <linux/poll.h>
-#include <linux/wait.h>
-#include <linux/ioctl.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/pagemap.h>
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <linux/sched.h>
-#include "rar_driver.h"
-
-/* The following defines are for the IPC process to retrieve RAR in */
-
-/* === Lincroft Message Bus Interface === */
-/* Message Control Register */
-#define LNC_MCR_OFFSET 0xD0
-
-/* Message Data Register */
-#define LNC_MDR_OFFSET 0xD4
-
-/* Message Opcodes */
-#define LNC_MESSAGE_READ_OPCODE  0xD0
-#define LNC_MESSAGE_WRITE_OPCODE 0xE0
-
-/* Message Write Byte Enables */
-#define LNC_MESSAGE_BYTE_WRITE_ENABLES 0xF
-
-/* B-unit Port */
-#define LNC_BUNIT_PORT 0x3
-
-/* === Lincroft B-Unit Registers - Programmed by IA32 firmware === */
-#define LNC_BRAR0L  0x10
-#define LNC_BRAR0H  0x11
-#define LNC_BRAR1L  0x12
-#define LNC_BRAR1H  0x13
-
-/* Reserved for SeP */
-#define LNC_BRAR2L  0x14
-#define LNC_BRAR2H  0x15
-
-
-/* This structure is only used during module initialization. */
-struct RAR_offsets {
-	int low; /* Register offset for low RAR physical address. */
-	int high; /* Register offset for high RAR physical address. */
-};
-
-struct pci_dev *rar_dev;
-static uint32_t registered;
-
-/* Moorestown supports three restricted access regions. */
-#define MRST_NUM_RAR 3
-
-struct RAR_address_struct rar_addr[MRST_NUM_RAR];
-
-/* prototype for init */
-static int __init rar_init_handler(void);
-static void __exit rar_exit_handler(void);
-
-/*
-  function that is activated on the successfull probe of the RAR device
-*/
-static int __devinit rar_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-
-static struct pci_device_id rar_pci_id_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4110) },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl);
-
-/* field for registering driver to PCI device */
-static struct pci_driver rar_pci_driver = {
-	.name = "rar_driver",
-	.id_table = rar_pci_id_tbl,
-	.probe = rar_probe
-};
-
-/* This function is used to retrieved RAR info using the IPC message
-   bus interface */
-static int memrar_get_rar_addr(struct pci_dev* pdev,
-	                      int offset,
-	                      u32 *addr)
-{
-	/*
-	 * ======== The Lincroft Message Bus Interface ========
-	 * Lincroft registers may be obtained from the PCI
-	 * (the Host Bridge) using the Lincroft Message Bus
-	 * Interface.  That message bus interface is generally
-	 * comprised of two registers: a control register (MCR, 0xDO)
-	 * and a data register (MDR, 0xD4).
-	 *
-	 * The MCR (message control register) format is the following:
-	 *   1.  [31:24]: Opcode
-	 *   2.  [23:16]: Port
-	 *   3.  [15:8]: Register Offset
-	 *   4.  [7:4]: Byte Enables (use 0xF to set all of these bits
-	 *              to 1)
-	 *   5.  [3:0]: reserved
-	 *
-	 *  Read (0xD0) and write (0xE0) opcodes are written to the
-	 *  control register when reading and writing to Lincroft
-	 *  registers, respectively.
-	 *
-	 *  We're interested in registers found in the Lincroft
-	 *  B-unit.  The B-unit port is 0x3.
-	 *
-	 *  The six B-unit RAR register offsets we use are listed
-	 *  earlier in this file.
-	 *
-	 *  Lastly writing to the MCR register requires the "Byte
-	 *  enables" bits to be set to 1.  This may be achieved by
-	 *  writing 0xF at bit 4.
-	 *
-	 * The MDR (message data register) format is the following:
-	 *   1. [31:0]: Read/Write Data
-	 *
-	 *  Data being read from this register is only available after
-	 *  writing the appropriate control message to the MCR
-	 *  register.
-	 *
-	 *  Data being written to this register must be written before
-	 *  writing the appropriate control message to the MCR
-	 *  register.
-	 */
-
-	int result = 0; /* result */
-	/* Construct control message */
-	u32 const message =
-	       (LNC_MESSAGE_READ_OPCODE << 24)
-	       | (LNC_BUNIT_PORT << 16)
-	       | (offset << 8)
-	       | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4);
-
-	printk(KERN_WARNING "rar- offset to LNC MSG is %x\n",offset);
-
-	if (addr == 0)
-		return -EINVAL;
-
-	/* Send the control message */
-	result = pci_write_config_dword(pdev,
-	                          LNC_MCR_OFFSET,
-	                          message);
-
-	printk(KERN_WARNING "rar- result from send ctl register is %x\n"
-	  ,result);
-
-	if (!result)
-		result = pci_read_config_dword(pdev,
-		                              LNC_MDR_OFFSET,
-				              addr);
-
-	printk(KERN_WARNING "rar- result from read data register is %x\n",
-	  result);
-
-	printk(KERN_WARNING "rar- value read from data register is %x\n",
-	  *addr);
-
-	if (result)
-		return -1;
-	else
-		return 0;
-}
-
-static int memrar_set_rar_addr(struct pci_dev* pdev,
-	                      int offset,
-	                      u32 addr)
-{
-	/*
-	 * ======== The Lincroft Message Bus Interface ========
-	 * Lincroft registers may be obtained from the PCI
-	 * (the Host Bridge) using the Lincroft Message Bus
-	 * Interface.  That message bus interface is generally
-	 * comprised of two registers: a control register (MCR, 0xDO)
-	 * and a data register (MDR, 0xD4).
-	 *
-	 * The MCR (message control register) format is the following:
-	 *   1.  [31:24]: Opcode
-	 *   2.  [23:16]: Port
-	 *   3.  [15:8]: Register Offset
-	 *   4.  [7:4]: Byte Enables (use 0xF to set all of these bits
-	 *              to 1)
-	 *   5.  [3:0]: reserved
-	 *
-	 *  Read (0xD0) and write (0xE0) opcodes are written to the
-	 *  control register when reading and writing to Lincroft
-	 *  registers, respectively.
-	 *
-	 *  We're interested in registers found in the Lincroft
-	 *  B-unit.  The B-unit port is 0x3.
-	 *
-	 *  The six B-unit RAR register offsets we use are listed
-	 *  earlier in this file.
-	 *
-	 *  Lastly writing to the MCR register requires the "Byte
-	 *  enables" bits to be set to 1.  This may be achieved by
-	 *  writing 0xF at bit 4.
-	 *
-	 * The MDR (message data register) format is the following:
-	 *   1. [31:0]: Read/Write Data
-	 *
-	 *  Data being read from this register is only available after
-	 *  writing the appropriate control message to the MCR
-	 *  register.
-	 *
-	 *  Data being written to this register must be written before
-	 *  writing the appropriate control message to the MCR
-	 *  register.
-	 */
-
-	int result = 0; /* result */
-
-	/* Construct control message */
-	u32 const message =
-	       (LNC_MESSAGE_WRITE_OPCODE << 24)
-	       | (LNC_BUNIT_PORT << 16)
-	       | (offset << 8)
-	       | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4);
-
-	printk(KERN_WARNING "rar- offset to LNC MSG is %x\n",offset);
-
-	if (addr == 0)
-		return -EINVAL;
-
-	/* Send the control message */
-	result = pci_write_config_dword(pdev,
-	                          LNC_MDR_OFFSET,
-	                          addr);
-
-	printk(KERN_WARNING "rar- result from send ctl register is %x\n"
-	  ,result);
-
-	if (!result)
-		result = pci_write_config_dword(pdev,
-		                              LNC_MCR_OFFSET,
-				              message);
-
-	printk(KERN_WARNING "rar- result from write data register is %x\n",
-	  result);
-
-	printk(KERN_WARNING "rar- value read to data register is %x\n",
-	  addr);
-
-	if (result)
-		return -1;
-	else
-		return 0;
-}
-
-/*
-
- * Initialize RAR parameters, such as physical addresses, etc.
-
- */
-static int memrar_init_rar_params(struct pci_dev *pdev)
-{
-	struct RAR_offsets const offsets[] = {
-	       { LNC_BRAR0L, LNC_BRAR0H },
-	       { LNC_BRAR1L, LNC_BRAR1H },
-	       { LNC_BRAR2L, LNC_BRAR2H }
-	};
-
-	size_t const num_offsets = sizeof(offsets) / sizeof(offsets[0]);
-	struct RAR_offsets const *end = offsets + num_offsets;
-	struct RAR_offsets const *i;
-	unsigned int n = 0;
-	int result = 0;
-
-	/* Retrieve RAR start and end physical addresses. */
-
-	/*
-	 * Access the RAR registers through the Lincroft Message Bus
-	 * Interface on PCI device: 00:00.0 Host bridge.
-	 */
-
-	/* struct pci_dev *pdev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); */
-
-	if (pdev == NULL)
-	       return -ENODEV;
-
-	for (i = offsets; i != end; ++i, ++n) {
-	       if (memrar_get_rar_addr (pdev,
-		                       (*i).low,
-		                       &(rar_addr[n].low)) != 0
-		   || memrar_get_rar_addr (pdev,
-		                          (*i).high,
-		                          &(rar_addr[n].high)) != 0) {
-		       result = -1;
-		       break;
-	       }
-	}
-
-	/* Done accessing the device. */
-	/* pci_dev_put(pdev); */
-
-	if (result == 0) {
-	if(1) {
-	       size_t z;
-	       for (z = 0; z != MRST_NUM_RAR; ++z) {
-			printk(KERN_WARNING "rar - BRAR[%Zd] physical address low\n"
-			     "\tlow:  0x%08x\n"
-			     "\thigh: 0x%08x\n",
-			     z,
-			     rar_addr[z].low,
-			     rar_addr[z].high);
-			}
-	       }
-	}
-
-	return result;
-}
-
-/*
-  function that is activated on the successfull probe of the RAR device
-*/
-static int __devinit rar_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	/* error */
-	int error;
-
-	/*------------------------
-	CODE
-	---------------------------*/
-
-	DEBUG_PRINT_0(RAR_DEBUG_LEVEL_EXTENDED,
-	  "Rar pci probe starting\n");
-	error = 0;
-
-	/* enable the device */
-	error = pci_enable_device(pdev);
-	if (error) {
-		DEBUG_PRINT_0(RAR_DEBUG_LEVEL_EXTENDED,
-		  "error enabling pci device\n");
-		goto end_function;
-	}
-
-	rar_dev = pdev;
-	registered = 1;
-
-	/* Initialize the RAR parameters, which have to be retrieved */
-	/* via the message bus service */
-	error=memrar_init_rar_params(rar_dev);
-
-	if (error) {
-		DEBUG_PRINT_0(RAR_DEBUG_LEVEL_EXTENDED,
-		  "error getting RAR addresses device\n");
-		registered = 0;
-		goto end_function;
-		}
-
-end_function:
-
-	return error;
-}
-
-/*
-  this function registers th driver to
-  the device subsystem( either PCI, USB, etc)
-*/
-static int __init rar_init_handler(void)
-{
-	return pci_register_driver(&rar_pci_driver);
-}
-
-static void __exit rar_exit_handler(void)
-{
-	pci_unregister_driver(&rar_pci_driver);
-}
-
-module_init(rar_init_handler);
-module_exit(rar_exit_handler);
-
-MODULE_LICENSE("GPL");
-
-
-/* The get_rar_address function is used by other device drivers
- * to obtain RAR address information on a RAR. It takes two
- * parameter:
- *
- * int rar_index
- * The rar_index is an index to the rar for which you wish to retrieve
- * the address information.
- * Values can be 0,1, or 2.
- *
- * struct RAR_address_struct is a pointer to a place to which the function
- * can return the address structure for the RAR.
- *
- * The function returns a 0 upon success or a -1 if there is no RAR
- * facility on this system.
- */
-int get_rar_address(int rar_index,struct RAR_address_struct *addresses)
-{
-	if (registered && (rar_index < 3) && (rar_index >= 0)) {
-		*addresses=rar_addr[rar_index];
-		/* strip off lock bit information  */
-		addresses->low = addresses->low & 0xfffffff0;
-		addresses->high = addresses->high & 0xfffffff0;
-		return 0;
-		}
-
-	else {
-		return -ENODEV;
-		}
-}
-
-
-EXPORT_SYMBOL(get_rar_address);
-
-/* The lock_rar function is ued by other device drivers to lock an RAR.
- * once an RAR is locked, it stays locked until the next system reboot.
- * The function takes one parameter:
- *
- * int rar_index
- * The rar_index is an index to the rar that you want to lock.
- * Values can be 0,1, or 2.
- *
- * The function returns a 0 upon success or a -1 if there is no RAR
- * facility on this system.
- */
-int lock_rar(int rar_index)
-{
-	u32 working_addr;
-	int result;
-if (registered && (rar_index < 3) && (rar_index >= 0)) {
-	/* first make sure that lock bits are clear (this does lock) */
-	working_addr=rar_addr[rar_index].low & 0xfffffff0;
-
-	/* now send that value to the register using the IPC */
-        result=memrar_set_rar_addr(rar_dev,rar_index,working_addr);
-	return result;
-	}
-
-else {
-	return -ENODEV;
-	}
-}
diff --git a/drivers/staging/rar/rar_driver.h b/drivers/staging/rar/rar_driver.h
deleted file mode 100644
index 3690f98..0000000
--- a/drivers/staging/rar/rar_driver.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* === RAR Physical Addresses === */
-struct RAR_address_struct {
-        u32 low;
-        u32 high;
-};
-
-/* The get_rar_address function is used by other device drivers
- * to obtain RAR address information on a RAR. It takes two
- * parameter:
- *
- * int rar_index
- * The rar_index is an index to the rar for which you wish to retrieve
- * the address information.
- * Values can be 0,1, or 2.
- *
- * struct RAR_address_struct is a pointer to a place to which the function
- * can return the address structure for the RAR.
- *
- * The function returns a 0 upon success or a -1 if there is no RAR
- * facility on this system.
- */
-int get_rar_address(int rar_index,struct RAR_address_struct *addresses);
-
-
-/* The lock_rar function is ued by other device drivers to lock an RAR.
- * once an RAR is locked, it stays locked until the next system reboot.
- * The function takes one parameter:
- *
- * int rar_index
- * The rar_index is an index to the rar that you want to lock.
- * Values can be 0,1, or 2.
- *
- * The function returns a 0 upon success or a -1 if there is no RAR
- * facility on this system.
- */
-int lock_rar(int rar_index);
-
-
-/* DEBUG LEVEL MASKS */
-#define RAR_DEBUG_LEVEL_BASIC       0x1
-
-#define RAR_DEBUG_LEVEL_REGISTERS   0x2
-
-#define RAR_DEBUG_LEVEL_EXTENDED    0x4
-
-#define DEBUG_LEVEL	0x7
-
-/* FUNCTIONAL MACROS */
-
-/* debug macro without paramaters */
-#define DEBUG_PRINT_0(DEBUG_LEVEL , info) \
-do \
-{ \
-  if(DEBUG_LEVEL) \
-  { \
-    printk(KERN_WARNING info); \
-  } \
-}while(0)
-
-/* debug macro with 1 paramater */
-#define DEBUG_PRINT_1(DEBUG_LEVEL , info , param1) \
-do \
-{ \
-  if(DEBUG_LEVEL) \
-  { \
-    printk(KERN_WARNING info , param1); \
-  } \
-}while(0)
-
-/* debug macro with 2 paramaters */
-#define DEBUG_PRINT_2(DEBUG_LEVEL , info , param1, param2) \
-do \
-{ \
-  if(DEBUG_LEVEL) \
-  { \
-    printk(KERN_WARNING info , param1, param2); \
-  } \
-}while(0)
-
-/* debug macro with 3 paramaters */
-#define DEBUG_PRINT_3(DEBUG_LEVEL , info , param1, param2 , param3) \
-do \
-{ \
-  if(DEBUG_LEVEL) \
-  { \
-    printk(KERN_WARNING info , param1, param2 , param3); \
-  } \
-}while(0)
-
-/* debug macro with 4 paramaters */
-#define DEBUG_PRINT_4(DEBUG_LEVEL , info , param1, param2 , param3 , param4) \
-do \
-{ \
-  if(DEBUG_LEVEL) \
-  { \
-    printk(KERN_WARNING info , param1, param2 , param3 , param4); \
-  } \
-}while(0)
-
diff --git a/drivers/staging/rar_register/Kconfig b/drivers/staging/rar_register/Kconfig
new file mode 100644
index 0000000..3f73839
--- /dev/null
+++ b/drivers/staging/rar_register/Kconfig
@@ -0,0 +1,30 @@
+#
+# RAR device configuration
+#
+
+menu "RAR Register Driver"
+#
+#	Restricted Access Register Manager
+#
+config RAR_REGISTER
+	tristate "Restricted Access Region Register Driver"
+	default n
+	---help---
+		This driver allows other kernel drivers access to the
+		contents of the restricted access region control
+		registers.
+
+		The restricted access region control registers
+		(rar_registers) are used to pass address and
+		locking information on restricted access regions
+		to other drivers that use restricted access regions
+
+		The restricted access regions are regions of memory
+		on the Intel MID Platform that are not accessible to
+		the x86 processor, but are accessible to dedicated
+		processors on board peripheral devices.
+
+		The purpose of the restricted access regions is to
+		protect sensitive data from compromise by unauthorized
+		programs running on the x86 processor.
+endmenu
diff --git a/drivers/staging/rar_register/Makefile b/drivers/staging/rar_register/Makefile
new file mode 100644
index 0000000..d5954cc
--- /dev/null
+++ b/drivers/staging/rar_register/Makefile
@@ -0,0 +1,2 @@
+EXTRA_CFLAGS += -DLITTLE__ENDIAN
+obj-$(CONFIG_RAR_REGISTER) += rar_register.o
diff --git a/drivers/staging/rar_register/rar_register.c b/drivers/staging/rar_register/rar_register.c
new file mode 100644
index 0000000..bfc0e31
--- /dev/null
+++ b/drivers/staging/rar_register/rar_register.c
@@ -0,0 +1,615 @@
+/*
+ *  rar_register.c - An Intel Restricted Access Region register driver
+ *
+ *  Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation; either version 2 of the
+ *  License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ *  02111-1307, USA.
+ *
+ * -------------------------------------------------------------------
+ *  20091204 Mark Allyn <mark.a.allyn@intel.com>
+ *	     Ossama Othman <ossama.othman@intel.com>
+ *	Cleanup per feedback from Alan Cox and Arjan Van De Ven
+ *
+ *  20090806 Ossama Othman <ossama.othman@intel.com>
+ *      Return zero high address if upper 22 bits is zero.
+ *      Cleaned up checkpatch errors.
+ *      Clarified that driver is dealing with bus addresses.
+ *
+ *  20090702 Ossama Othman <ossama.othman@intel.com>
+ *      Removed unnecessary include directives
+ *      Cleaned up spinlocks.
+ *      Cleaned up logging.
+ *      Improved invalid parameter checks.
+ *      Fixed and simplified RAR address retrieval and RAR locking
+ *      code.
+ *
+ *  20090626 Mark Allyn <mark.a.allyn@intel.com>
+ *      Initial publish
+ */
+
+#define DEBUG 1
+
+#include "rar_register.h"
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+/* === Lincroft Message Bus Interface === */
+/* Message Control Register */
+#define LNC_MCR_OFFSET 0xD0
+
+/* Maximum number of clients (other drivers using this driver) */
+#define MAX_RAR_CLIENTS 10
+
+/* Message Data Register */
+#define LNC_MDR_OFFSET 0xD4
+
+/* Message Opcodes */
+#define LNC_MESSAGE_READ_OPCODE 0xD0
+#define LNC_MESSAGE_WRITE_OPCODE 0xE0
+
+/* Message Write Byte Enables */
+#define LNC_MESSAGE_BYTE_WRITE_ENABLES 0xF
+
+/* B-unit Port */
+#define LNC_BUNIT_PORT 0x3
+
+/* === Lincroft B-Unit Registers - Programmed by IA32 firmware === */
+#define LNC_BRAR0L 0x10
+#define LNC_BRAR0H 0x11
+#define LNC_BRAR1L 0x12
+#define LNC_BRAR1H 0x13
+
+/* Reserved for SeP */
+#define LNC_BRAR2L 0x14
+#define LNC_BRAR2H 0x15
+
+/* Moorestown supports three restricted access regions. */
+#define MRST_NUM_RAR 3
+
+
+/* RAR Bus Address Range */
+struct RAR_address_range {
+	dma_addr_t low;
+	dma_addr_t high;
+};
+
+/* Structure containing low and high RAR register offsets. */
+struct RAR_offsets {
+	u32 low;  /* Register offset for low  RAR bus address. */
+	u32 high; /* Register offset for high RAR bus address. */
+};
+
+struct client {
+	int (*client_callback)(void *client_data);
+	void *customer_data;
+	int client_called;
+	};
+
+static DEFINE_MUTEX(rar_mutex);
+static DEFINE_MUTEX(lnc_reg_mutex);
+
+struct RAR_device {
+	struct RAR_offsets const rar_offsets[MRST_NUM_RAR];
+	struct RAR_address_range rar_addr[MRST_NUM_RAR];
+	struct pci_dev *rar_dev;
+	bool registered;
+	};
+
+/* this platform has only one rar_device for 3 rar regions */
+static struct RAR_device my_rar_device = {
+	.rar_offsets = {
+		[0].low = LNC_BRAR0L,
+		[0].high = LNC_BRAR0H,
+		[1].low = LNC_BRAR1L,
+		[1].high = LNC_BRAR1H,
+		[2].low = LNC_BRAR2L,
+		[2].high = LNC_BRAR2H
+	}
+};
+
+/* this data is for handling requests from other drivers which arrive
+ * prior to this driver initializing
+ */
+
+static struct client clients[MAX_RAR_CLIENTS];
+static int num_clients;
+
+/*
+ * This function is used to retrieved RAR info using the Lincroft
+ * message bus interface.
+ */
+static int retrieve_rar_addr(struct pci_dev *pdev,
+	int offset,
+	dma_addr_t *addr)
+{
+	/*
+	 * ======== The Lincroft Message Bus Interface ========
+	 * Lincroft registers may be obtained from the PCI
+	 * (the Host Bridge) using the Lincroft Message Bus
+	 * Interface.  That message bus interface is generally
+	 * comprised of two registers: a control register (MCR, 0xDO)
+	 * and a data register (MDR, 0xD4).
+	 *
+	 * The MCR (message control register) format is the following:
+	 *   1.  [31:24]: Opcode
+	 *   2.  [23:16]: Port
+	 *   3.  [15:8]: Register Offset
+	 *   4.  [7:4]: Byte Enables (use 0xF to set all of these bits
+	 *              to 1)
+	 *   5.  [3:0]: reserved
+	 *
+	 *  Read (0xD0) and write (0xE0) opcodes are written to the
+	 *  control register when reading and writing to Lincroft
+	 *  registers, respectively.
+	 *
+	 *  We're interested in registers found in the Lincroft
+	 *  B-unit.  The B-unit port is 0x3.
+	 *
+	 *  The six B-unit RAR register offsets we use are listed
+	 *  earlier in this file.
+	 *
+	 *  Lastly writing to the MCR register requires the "Byte
+	 *  enables" bits to be set to 1.  This may be achieved by
+	 *  writing 0xF at bit 4.
+	 *
+	 * The MDR (message data register) format is the following:
+	 *   1. [31:0]: Read/Write Data
+	 *
+	 *  Data being read from this register is only available after
+	 *  writing the appropriate control message to the MCR
+	 *  register.
+	 *
+	 *  Data being written to this register must be written before
+	 *  writing the appropriate control message to the MCR
+	 *  register.
+	*/
+
+	int result;
+
+	/* Construct control message */
+	u32 const message =
+		 (LNC_MESSAGE_READ_OPCODE << 24)
+		 | (LNC_BUNIT_PORT << 16)
+		 | (offset << 8)
+		 | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4);
+
+	dev_dbg(&pdev->dev, "Offset for 'get' LNC MSG is %x\n", offset);
+
+	if (addr == 0) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	/*
+	* We synchronize access to the Lincroft MCR and MDR registers
+	* until BOTH the command is issued through the MCR register
+	* and the corresponding data is read from the MDR register.
+	* Otherwise a race condition would exist between accesses to
+	* both registers.
+	*/
+
+	mutex_lock(&lnc_reg_mutex);
+
+	/* Send the control message */
+	result = pci_write_config_dword(pdev, LNC_MCR_OFFSET, message);
+
+	dev_dbg(&pdev->dev, "Result from send ctl register is %x\n", result);
+
+	if (!result) {
+		result = pci_read_config_dword(pdev, LNC_MDR_OFFSET,
+			(u32 *)addr);
+		dev_dbg(&pdev->dev,
+			"Result from read data register is %x\n", result);
+
+		dev_dbg(&pdev->dev,
+			"Value read from data register is %lx\n",
+			 (unsigned long)*addr);
+	}
+
+	mutex_unlock(&lnc_reg_mutex);
+
+	return result;
+}
+
+static int set_rar_address(struct pci_dev *pdev,
+	int offset,
+	dma_addr_t addr)
+{
+	/*
+	* Data being written to this register must be written before
+	* writing the appropriate control message to the MCR
+	* register.
+	* @note See rar_get_address() for a description of the
+	* message bus interface being used here.
+	*/
+
+	int result = 0;
+
+	/* Construct control message */
+	u32 const message = (LNC_MESSAGE_WRITE_OPCODE << 24)
+		| (LNC_BUNIT_PORT << 16)
+		| (offset << 8)
+		| (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4);
+
+	if (addr == 0) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	dev_dbg(&pdev->dev, "Offset for 'set' LNC MSG is %x\n", offset);
+
+	/*
+	* We synchronize access to the Lincroft MCR and MDR registers
+	* until BOTH the command is issued through the MCR register
+	* and the corresponding data is read from the MDR register.
+	* Otherwise a race condition would exist between accesses to
+	* both registers.
+	*/
+
+	mutex_lock(&lnc_reg_mutex);
+
+	/* Send the control message */
+	result = pci_write_config_dword(pdev, LNC_MDR_OFFSET, addr);
+
+	dev_dbg(&pdev->dev, "Result from write data register is %x\n", result);
+
+	if (!result) {
+		dev_dbg(&pdev->dev,
+			"Value written to data register is %lx\n",
+			 (unsigned long)addr);
+
+		result = pci_write_config_dword(pdev, LNC_MCR_OFFSET, message);
+
+		dev_dbg(&pdev->dev, "Result from send ctl register is %x\n",
+			result);
+	}
+
+	mutex_unlock(&lnc_reg_mutex);
+
+	return result;
+}
+
+/*
+* Initialize RAR parameters, such as bus addresses, etc.
+*/
+static int init_rar_params(struct pci_dev *pdev)
+{
+	unsigned int i;
+	int result = 0;
+
+	/* Retrieve RAR start and end bus addresses.
+	* Access the RAR registers through the Lincroft Message Bus
+	* Interface on PCI device: 00:00.0 Host bridge.
+	*/
+
+	for (i = 0; i < MRST_NUM_RAR; ++i) {
+		struct RAR_offsets const *offset =
+			&my_rar_device.rar_offsets[i];
+		struct RAR_address_range *addr = &my_rar_device.rar_addr[i];
+
+	if ((retrieve_rar_addr(pdev, offset->low, &addr->low) != 0)
+		|| (retrieve_rar_addr(pdev, offset->high, &addr->high) != 0)) {
+		result = -1;
+		break;
+		}
+
+		/*
+		* Only the upper 22 bits of the RAR addresses are
+		* stored in their corresponding RAR registers so we
+		* must set the lower 10 bits accordingly.
+
+		* The low address has its lower 10 bits cleared, and
+		* the high address has all its lower 10 bits set,
+		* e.g.:
+		* low = 0x2ffffc00
+		*/
+
+		addr->low &= (dma_addr_t)0xfffffc00u;
+
+		/*
+		* Set bits 9:0 on uppser address if bits 31:10 are non
+		* zero; otherwize clear all bits
+		*/
+
+		if ((addr->high & 0xfffffc00u) == 0)
+			addr->high = 0;
+		else
+			addr->high |= 0x3ffu;
+	}
+	/* Done accessing the device. */
+
+	if (result == 0) {
+		int z;
+		for (z = 0; z != MRST_NUM_RAR; ++z) {
+			/*
+			* "BRAR" refers to the RAR registers in the
+			* Lincroft B-unit.
+			*/
+			dev_info(&pdev->dev, "BRAR[%u] bus address range = "
+			  "[%lx, %lx]\n", z,
+			  (unsigned long)my_rar_device.rar_addr[z].low,
+			  (unsigned long)my_rar_device.rar_addr[z].high);
+		}
+	}
+
+	return result;
+}
+
+/*
+ * The rar_get_address function is used by other device drivers
+ * to obtain RAR address information on a RAR. It takes three
+ * parameters:
+ *
+ * int rar_index
+ * The rar_index is an index to the rar for which you wish to retrieve
+ * the address information.
+ * Values can be 0,1, or 2.
+ *
+ * The function returns a 0 upon success or a -1 if there is no RAR
+ * facility on this system.
+ */
+int rar_get_address(int rar_index,
+	dma_addr_t *start_address,
+	dma_addr_t *end_address)
+{
+	int result = -ENODEV;
+
+	if (my_rar_device.registered) {
+		if (start_address == 0 || end_address == 0
+			|| rar_index >= MRST_NUM_RAR || rar_index < 0) {
+			result = -EINVAL;
+		} else {
+			*start_address =
+				my_rar_device.rar_addr[rar_index].low;
+			*end_address =
+				my_rar_device.rar_addr[rar_index].high;
+
+			result = 0;
+		}
+	}
+
+	return result;
+}
+EXPORT_SYMBOL(rar_get_address);
+
+/*
+ * The rar_lock function is ued by other device drivers to lock an RAR.
+ * once an RAR is locked, it stays locked until the next system reboot.
+ * The function takes one parameter:
+ *
+ * int rar_index
+ * The rar_index is an index to the rar that you want to lock.
+ * Values can be 0,1, or 2.
+ *
+ * The function returns a 0 upon success or a -1 if there is no RAR
+ * facility on this system.
+ */
+int rar_lock(int rar_index)
+{
+	int result = -ENODEV;
+
+	if (rar_index >= MRST_NUM_RAR || rar_index < 0) {
+		result = -EINVAL;
+		return result;
+	}
+
+	dev_dbg(&my_rar_device.rar_dev->dev, "rar_lock mutex locking\n");
+	mutex_lock(&rar_mutex);
+
+	if (my_rar_device.registered) {
+
+		dma_addr_t low = my_rar_device.rar_addr[rar_index].low &
+			0xfffffc00u;
+
+		dma_addr_t high = my_rar_device.rar_addr[rar_index].high &
+			0xfffffc00u;
+
+		/*
+		* Only allow I/O from the graphics and Langwell;
+		* Not from the x96 processor
+		*/
+		if (rar_index == (int)RAR_TYPE_VIDEO) {
+			low |= 0x00000009;
+			high |= 0x00000015;
+		}
+
+		else if (rar_index == (int)RAR_TYPE_AUDIO) {
+			/* Only allow I/O from Langwell; nothing from x86 */
+			low |= 0x00000008;
+			high |= 0x00000018;
+		}
+
+		else
+			/* Read-only from all agents */
+			high |= 0x00000018;
+
+		/*
+		* Now program the register using the Lincroft message
+		* bus interface.
+		*/
+		result = set_rar_address(my_rar_device.rar_dev,
+			my_rar_device.rar_offsets[rar_index].low,
+			low);
+
+		if (result == 0)
+			result = set_rar_address(
+			my_rar_device.rar_dev,
+			my_rar_device.rar_offsets[rar_index].high,
+			high);
+	}
+
+	dev_dbg(&my_rar_device.rar_dev->dev, "rar_lock mutex unlocking\n");
+	mutex_unlock(&rar_mutex);
+	return result;
+}
+EXPORT_SYMBOL(rar_lock);
+
+/* The register_rar function is to used by other device drivers
+ * to ensure that this driver is ready. As we cannot be sure of
+ * the compile/execute order of dirvers in ther kernel, it is
+ * best to give this driver a callback function to call when
+ * it is ready to give out addresses. The callback function
+ * would have those steps that continue the initialization of
+ * a driver that do require a valid RAR address. One of those
+ * steps would be to call rar_get_address()
+ * This function return 0 on success an -1 on failure.
+*/
+int register_rar(int (*callback)(void *yourparameter), void *yourparameter)
+{
+
+	int result = -ENODEV;
+
+	if (callback == NULL)
+		return -EINVAL;
+
+	mutex_lock(&rar_mutex);
+
+	if (my_rar_device.registered) {
+
+		mutex_unlock(&rar_mutex);
+		/*
+		* if the driver already registered, then we can simply
+		* call the callback right now
+		*/
+
+		return (*callback)(yourparameter);
+	}
+
+	if (num_clients < MRST_NUM_RAR) {
+
+		clients[num_clients].client_callback = callback;
+		clients[num_clients].customer_data = yourparameter;
+		num_clients += 1;
+		result = 0;
+	}
+
+	mutex_unlock(&rar_mutex);
+	return result;
+
+}
+EXPORT_SYMBOL(register_rar);
+
+/* Suspend - returns -ENOSYS */
+static int rar_suspend(struct pci_dev *dev, pm_message_t state)
+{
+	return -ENOSYS;
+}
+
+static int rar_resume(struct pci_dev *dev)
+{
+	return -ENOSYS;
+}
+
+/*
+ * This function registers the driver with the device subsystem (
+ * either PCI, USB, etc).
+ * Function that is activaed on the succesful probe of the RAR device
+ * (Moorestown host controller).
+ */
+static int rar_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int error;
+	int counter;
+
+	dev_dbg(&dev->dev, "PCI probe starting\n");
+
+	/* enable the device */
+	error = pci_enable_device(dev);
+	if (error) {
+		dev_err(&dev->dev,
+			"Error enabling RAR register PCI device\n");
+		goto end_function;
+	}
+
+	/* we have only one device; fill in the rar_device structure */
+	my_rar_device.rar_dev = dev;
+
+	/*
+	* Initialize the RAR parameters, which have to be retrieved
+	* via the message bus interface.
+	*/
+	error = init_rar_params(dev);
+	if (error) {
+		pci_disable_device(dev);
+
+		dev_err(&dev->dev,
+			"Error retrieving RAR addresses\n");
+
+		goto end_function;
+	}
+
+	dev_dbg(&dev->dev, "PCI probe locking\n");
+	mutex_lock(&rar_mutex);
+	my_rar_device.registered = 1;
+
+	/* now call anyone who has registered (using callbacks) */
+	for (counter = 0; counter < num_clients; counter += 1) {
+		if (clients[counter].client_callback) {
+			error = (*clients[counter].client_callback)(
+				clients[counter].customer_data);
+			/* set callback to NULL to indicate it has been done */
+			clients[counter].client_callback = NULL;
+				dev_dbg(&my_rar_device.rar_dev->dev,
+				"Callback called for %d\n",
+			counter);
+		}
+	}
+
+	dev_dbg(&dev->dev, "PCI probe unlocking\n");
+	mutex_unlock(&rar_mutex);
+
+end_function:
+
+	return error;
+}
+
+const struct pci_device_id rar_pci_id_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_RAR_DEVICE_ID) },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl);
+
+const struct pci_device_id *my_id_table = rar_pci_id_tbl;
+
+/* field for registering driver to PCI device */
+static struct pci_driver rar_pci_driver = {
+	.name = "rar_register_driver",
+	.id_table = rar_pci_id_tbl,
+	.probe = rar_probe,
+	.suspend = rar_suspend,
+	.resume = rar_resume
+};
+
+static int __init rar_init_handler(void)
+{
+	return pci_register_driver(&rar_pci_driver);
+}
+
+static void __exit rar_exit_handler(void)
+{
+	pci_unregister_driver(&rar_pci_driver);
+}
+
+module_init(rar_init_handler);
+module_exit(rar_exit_handler);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel Restricted Access Region Register Driver");
diff --git a/drivers/staging/rar_register/rar_register.h b/drivers/staging/rar_register/rar_register.h
new file mode 100644
index 0000000..29ade0f
--- /dev/null
+++ b/drivers/staging/rar_register/rar_register.h
@@ -0,0 +1,84 @@
+/*
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ * The full GNU General Public License is included in this
+ * distribution in the file called COPYING.
+ */
+
+
+#ifndef _RAR_REGISTER_H
+#define _RAR_REGISTER_H
+
+# include <linux/types.h>
+
+/* following are used both in drivers as well as user space apps */
+enum RAR_type {
+	RAR_TYPE_VIDEO = 0,
+	RAR_TYPE_AUDIO,
+	RAR_TYPE_IMAGE,
+	RAR_TYPE_DATA
+};
+
+#ifdef __KERNEL__
+
+/* PCI device id for controller */
+#define PCI_RAR_DEVICE_ID 0x4110
+
+/* The register_rar function is to used by other device drivers
+ * to ensure that this driver is ready. As we cannot be sure of
+ * the compile/execute order of dirvers in ther kernel, it is
+ * best to give this driver a callback function to call when
+ * it is ready to give out addresses. The callback function
+ * would have those steps that continue the initialization of
+ * a driver that do require a valid RAR address. One of those
+ * steps would be to call get_rar_address()
+ * This function return 0 on success an -1 on failure.
+ */
+int register_rar(int (*callback)(void *yourparameter), void *yourparameter);
+
+/* The get_rar_address function is used by other device drivers
+ * to obtain RAR address information on a RAR. It takes two
+ * parameter:
+ *
+ * int rar_index
+ * The rar_index is an index to the rar for which you wish to retrieve
+ * the address information.
+ * Values can be 0,1, or 2.
+ *
+ * struct RAR_address_struct is a pointer to a place to which the function
+ * can return the address structure for the RAR.
+ *
+ * The function returns a 0 upon success or a -1 if there is no RAR
+ * facility on this system.
+ */
+int rar_get_address(int rar_index,
+		dma_addr_t *start_address,
+		dma_addr_t *end_address);
+
+/* The lock_rar function is ued by other device drivers to lock an RAR.
+ * once an RAR is locked, it stays locked until the next system reboot.
+ * The function takes one parameter:
+ *
+ * int rar_index
+ * The rar_index is an index to the rar that you want to lock.
+ * Values can be 0,1, or 2.
+ *
+ * The function returns a 0 upon success or a -1 if there is no RAR
+ * facility on this system.
+ */
+int rar_lock(int rar_index);
+
+#endif  /* __KERNEL__ */
+#endif  /* _RAR_REGISTER_H */
diff --git a/drivers/staging/rt2860/Kconfig b/drivers/staging/rt2860/Kconfig
index f9962b6..f3a7e47 100644
--- a/drivers/staging/rt2860/Kconfig
+++ b/drivers/staging/rt2860/Kconfig
@@ -3,6 +3,8 @@
 	depends on PCI && X86 && WLAN
 	select WIRELESS_EXT
 	select WEXT_PRIV
+	select CRC_CCITT
+	select FW_LOADER
 	---help---
 	  This is an experimental driver for the Ralink 2860 and 3090
 	  wireless chips.
diff --git a/drivers/staging/rt2860/common/firmware.h b/drivers/staging/rt2860/common/firmware.h
deleted file mode 100644
index 2fecd32..0000000
--- a/drivers/staging/rt2860/common/firmware.h
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- Copyright (c) 2007, Ralink Technology Corporation
- All rights reserved.
-
- Redistribution.  Redistribution and use in binary form, without
- modification, are permitted provided that the following conditions are
- met:
-
- 	* Redistributions must reproduce the above copyright notice and the
- 	following disclaimer in the documentation and/or other materials
- 	provided with the distribution.
- 	* Neither the name of Ralink Technology Corporation nor the names of its
- 	suppliers may be used to endorse or promote products derived from this
- 	software without specific prior written permission.
- 	* No reverse engineering, decompilation, or disassembly of this software
- 	is permitted.
-
- Limited patent license. Ralink Technology Corporation grants a world-wide,
- royalty-free, non-exclusive license under patents it now or hereafter
- owns or controls to make, have made, use, import, offer to sell and
- sell ("Utilize") this software, but solely to the extent that any
- such patent is necessary to Utilize the software alone, or in
- combination with an operating system licensed under an approved Open
- Source license as listed by the Open Source Initiative at
- http://opensource.org/licenses.  The patent license shall not apply to
- any other combinations which include this software.  No hardware per
- se is licensed hereunder.
-
- DISCLAIMER.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- DAMAGE.
-*/
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-
-
-u8 FirmwareImage_2860 [] = {
-0x02, 0x03, 0x5e, 0x02, 0x02, 0xb1, 0x22, 0x22, 0xff, 0xff, 0xff, 0x02, 0x01, 0x82, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x02, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x01, 0x33, 0xc0, 0xe0,
-0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0xc2, 0xaf, 0x30, 0x45, 0x03,
-0x12, 0x10, 0x09, 0x90, 0x04, 0x16, 0xe0, 0x30, 0xe3, 0x03, 0x74, 0x08, 0xf0, 0x90, 0x04, 0x14,
-0xe0, 0x20, 0xe7, 0x03, 0x02, 0x00, 0xcb, 0x74, 0x80, 0xf0, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x2f,
-0x90, 0x04, 0x04, 0xe0, 0x24, 0xcf, 0x60, 0x30, 0x14, 0x60, 0x42, 0x24, 0xe2, 0x60, 0x47, 0x14,
-0x60, 0x55, 0x24, 0x21, 0x70, 0x60, 0xe5, 0x55, 0x24, 0xfe, 0x60, 0x07, 0x14, 0x60, 0x08, 0x24,
-0x02, 0x70, 0x08, 0x7d, 0x01, 0x80, 0x28, 0x7d, 0x02, 0x80, 0x24, 0x90, 0x70, 0x10, 0xe0, 0xf5,
-0x50, 0x85, 0x2f, 0x40, 0xd2, 0x01, 0x80, 0x3e, 0xe5, 0x55, 0x64, 0x03, 0x60, 0x04, 0xe5, 0x55,
-0x70, 0x04, 0x7d, 0x02, 0x80, 0x09, 0x85, 0x2f, 0x41, 0xd2, 0x02, 0x80, 0x29, 0xad, 0x55, 0xaf,
-0x2f, 0x12, 0x02, 0x8d, 0x80, 0x20, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x47, 0x90, 0x70, 0x11, 0xe0,
-0xf5, 0x44, 0x12, 0x10, 0x25, 0x80, 0x06, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x45, 0xe4, 0xfd, 0xaf,
-0x2f, 0x12, 0x02, 0x8d, 0xd2, 0x04, 0x90, 0x70, 0x13, 0xe4, 0xf0, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0,
-0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x53, 0xc2,
-0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d,
-0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x30, 0x90,
-0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10,
-0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a,
-0x0d, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x02, 0x2c, 0x74, 0xff, 0xf0, 0xc2, 0x05,
-0xd2, 0xaf, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0xe8, 0xc0, 0xe0,
-0xe9, 0xc0, 0xe0, 0xea, 0xc0, 0xe0, 0xeb, 0xc0, 0xe0, 0xec, 0xc0, 0xe0, 0xed, 0xc0, 0xe0, 0xee,
-0xc0, 0xe0, 0xef, 0xc0, 0xe0, 0xc2, 0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x12, 0xd2, 0xaf, 0xd0,
-0xe0, 0xff, 0xd0, 0xe0, 0xfe, 0xd0, 0xe0, 0xfd, 0xd0, 0xe0, 0xfc, 0xd0, 0xe0, 0xfb, 0xd0, 0xe0,
-0xfa, 0xd0, 0xe0, 0xf9, 0xd0, 0xe0, 0xf8, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0,
-0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0xc2,
-0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x0c, 0x30, 0x58, 0x0a, 0xe5, 0x54, 0x60, 0x04, 0x15, 0x54,
-0x80, 0x02, 0xc2, 0x58, 0x30, 0x59, 0x0a, 0xe5, 0x50, 0x60, 0x04, 0x15, 0x50, 0x80, 0x02, 0xc2,
-0x59, 0xd5, 0x53, 0x07, 0x30, 0x60, 0x04, 0x15, 0x46, 0xd2, 0x04, 0x30, 0x45, 0x03, 0x12, 0x10,
-0x0f, 0xc2, 0x8d, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32,
-0x12, 0x02, 0xd3, 0x30, 0x45, 0x03, 0x12, 0x10, 0x03, 0x30, 0x01, 0x06, 0x20, 0x09, 0x03, 0x12,
-0x10, 0x1c, 0x30, 0x02, 0x06, 0x20, 0x0a, 0x03, 0x12, 0x10, 0x1f, 0x30, 0x03, 0x06, 0x20, 0x0b,
-0x03, 0x12, 0x10, 0x1f, 0x30, 0x04, 0x06, 0x20, 0x0c, 0x03, 0x12, 0x10, 0x22, 0x20, 0x13, 0x09,
-0x20, 0x11, 0x06, 0xe5, 0x2b, 0x45, 0x2c, 0x60, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xa9, 0x12,
-0x02, 0xec, 0x80, 0xbf, 0xc2, 0x43, 0xd2, 0x45, 0xe4, 0xf5, 0x20, 0xf5, 0x21, 0xf5, 0x53, 0xf5,
-0x46, 0xf5, 0x2b, 0xf5, 0x2c, 0xc2, 0x42, 0xf5, 0x51, 0xf5, 0x52, 0xf5, 0x55, 0x90, 0x04, 0x18,
-0x74, 0x80, 0xf0, 0x90, 0x04, 0x1a, 0x74, 0x08, 0xf0, 0xc2, 0x19, 0xc2, 0x18, 0xc2, 0x1a, 0x22,
-0xc8, 0xef, 0xc8, 0xe6, 0xfa, 0x08, 0xe6, 0x4a, 0x60, 0x0c, 0xc8, 0xef, 0xc8, 0x08, 0xe6, 0x16,
-0x18, 0x70, 0x01, 0x16, 0xc3, 0x22, 0xed, 0x24, 0xff, 0xfd, 0xec, 0x34, 0xff, 0xc8, 0xef, 0xc8,
-0xf6, 0x08, 0xc6, 0xed, 0xc6, 0xd3, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12,
-0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83,
-0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0xef, 0xf4, 0x60,
-0x1f, 0xe4, 0xfe, 0x12, 0x03, 0x6a, 0xe0, 0xb4, 0xff, 0x12, 0x12, 0x03, 0x6a, 0xef, 0xf0, 0x74,
-0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xe3,
-0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0xc2, 0xaf,
-0x30, 0x45, 0x03, 0x12, 0x10, 0x06, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0,
-0xd0, 0xe0, 0x32, 0xc2, 0xaf, 0x12, 0x00, 0x06, 0x12, 0x02, 0x14, 0x12, 0x03, 0x1c, 0xe4, 0xf5,
-0x22, 0xf5, 0x47, 0x90, 0x04, 0x00, 0x74, 0x80, 0xf0, 0xd2, 0xaf, 0x22, 0x30, 0x45, 0x03, 0x12,
-0x10, 0x15, 0xe5, 0x20, 0x70, 0x03, 0x20, 0x10, 0x03, 0x30, 0x11, 0x03, 0x43, 0x87, 0x01, 0x22,
-0xc0, 0x2a, 0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x2a, 0x0a, 0x22, 0xc0, 0x2a,
-0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x2a, 0x18, 0x22, 0x75, 0x89, 0x02, 0xe4,
-0xf5, 0x8c, 0xf5, 0x8a, 0xf5, 0x88, 0xf5, 0xb8, 0xf5, 0xe8, 0x75, 0x90, 0x18, 0xd2, 0x8c, 0x75,
-0xa8, 0x05, 0x22, 0xce, 0xef, 0xce, 0xee, 0x60, 0x08, 0x7f, 0xff, 0x12, 0x03, 0x80, 0x1e, 0x80,
-0xf5, 0x22, 0xc8, 0xef, 0xc8, 0xe6, 0x60, 0x03, 0x16, 0xc3, 0x22, 0xed, 0x14, 0xf6, 0xd3, 0x22,
-0xc8, 0xef, 0xc8, 0xe6, 0x60, 0x06, 0x16, 0xe6, 0x24, 0xff, 0xb3, 0x22, 0xc3, 0x22, 0x78, 0x7f,
-0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x5f, 0x02, 0x01, 0xd0, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4,
-0x34, 0x70, 0xf5, 0x83, 0x22, 0xef, 0x90, 0x03, 0x7e, 0x93, 0x90, 0x03, 0x00, 0x73, 0x0a, 0x18,
-0xef, 0x60, 0x03, 0x1f, 0x80, 0xfa, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x3b, 0x02, 0x10, 0x3c, 0x02, 0x12, 0xb8, 0x02,
-0x12, 0xb9, 0x02, 0x13, 0x3e, 0x02, 0x13, 0x3f, 0xc3, 0x22, 0xff, 0xff, 0x02, 0x16, 0x56, 0x02,
-0x17, 0x6b, 0x02, 0x14, 0x2a, 0x02, 0x13, 0x40, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x00,
-0xd8, 0x30, 0x06, 0x06, 0x20, 0x0e, 0x03, 0x12, 0x18, 0x5e, 0x22, 0x22, 0x90, 0x04, 0x14, 0xe0,
-0x20, 0xe7, 0x03, 0x02, 0x12, 0xb7, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0,
-0x12, 0x02, 0x67, 0x11, 0x4e, 0x30, 0x11, 0x25, 0x31, 0x10, 0x87, 0x33, 0x10, 0xaa, 0x34, 0x10,
-0xc3, 0x35, 0x11, 0x57, 0x50, 0x11, 0x7b, 0x51, 0x11, 0x84, 0x52, 0x11, 0x84, 0x53, 0x11, 0x84,
-0x54, 0x11, 0xc5, 0x55, 0x11, 0xdc, 0x70, 0x12, 0x07, 0x71, 0x12, 0x34, 0x72, 0x12, 0x5e, 0x80,
-0x12, 0x81, 0x83, 0x00, 0x00, 0x12, 0xb7, 0x75, 0x24, 0x05, 0x75, 0x25, 0xdc, 0x90, 0x70, 0x9f,
-0x74, 0x12, 0xf0, 0xd2, 0x18, 0xd2, 0x61, 0x75, 0x35, 0x0d, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
-0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0xc2, 0x18, 0x90, 0x01, 0x14, 0xe0,
-0x54, 0xfd, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0xb7,
-0x02, 0x12, 0xaa, 0xe5, 0x55, 0x64, 0x02, 0x70, 0x37, 0x90, 0x70, 0x10, 0xe0, 0x60, 0x08, 0x90,
-0x01, 0x0d, 0x74, 0x09, 0xf0, 0x80, 0x25, 0xe5, 0x34, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14,
-0x60, 0x14, 0x24, 0x03, 0x70, 0x16, 0x90, 0x01, 0x0d, 0x74, 0x08, 0xf0, 0x80, 0x0e, 0x90, 0x01,
-0x0d, 0x74, 0x0b, 0xf0, 0x80, 0x06, 0x90, 0x01, 0x0d, 0x74, 0x1b, 0xf0, 0x7d, 0x01, 0x80, 0x02,
-0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x1b, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02,
-0x12, 0xb7, 0x02, 0x12, 0xaa, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf, 0x56, 0x12,
-0x02, 0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4,
-0x70, 0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22, 0x90, 0x70,
-0x11, 0xe0, 0x24, 0xff, 0x92, 0x1b, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60,
-0x03, 0x02, 0x12, 0xb7, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60,
-0x03, 0x02, 0x12, 0xb7, 0x75, 0x4e, 0x03, 0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24,
-0xff, 0x92, 0x47, 0x22, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70,
-0x10, 0xe0, 0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff,
-0x74, 0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02,
-0x12, 0xb7, 0x02, 0x12, 0xaa, 0xe5, 0x47, 0xb4, 0x07, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x07,
-0xf5, 0x26, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0xd2, 0x04, 0x22, 0x90, 0x70, 0x10, 0xe0,
-0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02,
-0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70,
-0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0,
-0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02,
-0x12, 0xb7, 0x80, 0x76, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x26, 0xff, 0xc2, 0x19, 0xc2, 0x18,
-0xc2, 0x1a, 0x75, 0x34, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x04, 0x14, 0x74,
-0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x5b, 0x80, 0x4c, 0x90, 0x70,
-0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x38, 0x80,
-0x29, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x34, 0xd3, 0x94, 0x00, 0x40, 0x07, 0x90, 0x01, 0x0d, 0xe0,
-0x54, 0xfb, 0xf0, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0,
-0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x0d, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01,
-0xf0, 0x90, 0x02, 0x2c, 0x74, 0xff, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x13, 0x3d,
-0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0xa2, 0x19,
-0xe4, 0x33, 0x90, 0x70, 0x90, 0xf0, 0xa2, 0x18, 0xe4, 0x33, 0xa3, 0xf0, 0x30, 0x19, 0x4d, 0x90,
-0x70, 0x98, 0x74, 0x23, 0xf0, 0xa3, 0xe5, 0x25, 0xf0, 0xe5, 0x24, 0xa3, 0xf0, 0x7f, 0x35, 0x7d,
-0x32, 0x12, 0x03, 0x42, 0x50, 0x09, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf7, 0xf0, 0xd2, 0x06, 0xe5,
-0x35, 0xd3, 0x94, 0x10, 0x40, 0x1e, 0x30, 0x1a, 0x1b, 0xc2, 0x1a, 0xa2, 0x18, 0x92, 0x19, 0x20,
-0x19, 0x12, 0x90, 0x04, 0x09, 0xe0, 0x54, 0xdd, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x08, 0xf0,
-0xc2, 0x61, 0xd2, 0x03, 0xe5, 0x35, 0xb4, 0x0b, 0x14, 0xd2, 0x03, 0x22, 0xe4, 0xf5, 0x35, 0xa2,
-0x18, 0x92, 0x19, 0x30, 0x19, 0x07, 0x90, 0x04, 0x09, 0xe0, 0x44, 0x22, 0xf0, 0x22, 0x22, 0x22,
-0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x02, 0x67, 0x13, 0x62, 0x00, 0x13, 0xf5, 0x04, 0x13,
-0xf1, 0x08, 0x13, 0xcc, 0x10, 0x13, 0x76, 0x20, 0x13, 0x96, 0x60, 0x13, 0xa7, 0xa0, 0x00, 0x00,
-0x13, 0xf7, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60,
-0x03, 0x02, 0x13, 0xf7, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4,
-0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70,
-0x66, 0x53, 0x43, 0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5,
-0x47, 0x64, 0x06, 0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b,
-0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06,
-0x70, 0x35, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04,
-0x06, 0x53, 0x5e, 0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75,
-0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80,
-0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x38, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff,
-0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3,
-0xe5, 0x4a, 0xf0, 0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3,
-0xe5, 0x42, 0xf0, 0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0,
-0x70, 0x03, 0x12, 0x16, 0x36, 0x12, 0x14, 0x3f, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2,
-0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x1c, 0x80, 0x08, 0xe5, 0x4e, 0x45,
-0x4f, 0x24, 0xff, 0x92, 0x1c, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x1d, 0x74,
-0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x38, 0x70, 0x13, 0x30, 0x1c, 0x05, 0xe5,
-0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x1d, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5,
-0x38, 0x70, 0x05, 0x75, 0x38, 0x0c, 0x80, 0x02, 0x15, 0x38, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f,
-0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5,
-0x47, 0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x38,
-0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x38, 0x70, 0x05, 0x75, 0x38, 0x07, 0x80, 0x02,
-0x15, 0x38, 0xd2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5, 0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5,
-0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a,
-0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0,
-0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x15, 0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2,
-0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x15, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2,
-0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, 0x15, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2,
-0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x71, 0x92, 0x70, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x46, 0x90,
-0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe,
-0x60, 0x1f, 0x24, 0x03, 0x60, 0x03, 0x02, 0x16, 0x35, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0d,
-0x80, 0x07, 0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x04, 0x54, 0xfe, 0xf0, 0x22, 0x44, 0x01, 0xf0,
-0x22, 0xe5, 0x46, 0x30, 0xe3, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02, 0x28, 0xe0,
-0x54, 0xfe, 0x4f, 0xf0, 0x22, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x03, 0x02, 0x16, 0x35, 0xf5, 0x27,
-0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x26, 0x14, 0x60, 0x26, 0x14, 0x60, 0x2e, 0x14,
-0x60, 0x36, 0x24, 0x03, 0x70, 0x5f, 0xe5, 0x46, 0x13, 0x13, 0x13, 0x54, 0x1f, 0x75, 0xf0, 0x03,
-0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff,
-0x80, 0x02, 0xa2, 0x47, 0x92, 0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x3f, 0xe5, 0x46, 0x30,
-0xe3, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe3, 0x0d, 0x54, 0x70, 0xc3,
-0x94, 0x60, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, 0x47,
-0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2, 0x47,
-0xb3, 0x92, 0x39, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90, 0x02, 0x28, 0xe0,
-0x54, 0xfc, 0x45, 0x27, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45,
-0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59,
-0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x30, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x4a,
-0x14, 0x60, 0x6a, 0x24, 0x02, 0x60, 0x03, 0x02, 0x17, 0x4c, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x20,
-0x19, 0x1c, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x20, 0xe1, 0x23, 0x90, 0x04, 0x34,
-0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3, 0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20,
-0x12, 0x16, 0x4c, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x02, 0x17, 0x4c,
-0xe5, 0x50, 0x70, 0x06, 0x75, 0x30, 0x03, 0x02, 0x17, 0x4c, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03,
-0x70, 0x15, 0x7f, 0x20, 0x12, 0x16, 0x4c, 0x20, 0x19, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfb,
-0xf0, 0x75, 0x51, 0x02, 0x02, 0x17, 0x4c, 0xe5, 0x50, 0x70, 0x02, 0x80, 0x7a, 0x20, 0x19, 0x0f,
-0x90, 0x02, 0x08, 0xe0, 0x20, 0xe3, 0x6c, 0x90, 0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x64, 0x90,
-0x12, 0x04, 0x74, 0x0a, 0xf0, 0x30, 0x1b, 0x11, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3,
-0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x20, 0x19, 0x07, 0x90, 0x04, 0x01, 0xe0,
-0x44, 0x10, 0xf0, 0xe5, 0x34, 0xf4, 0x90, 0x04, 0x01, 0x60, 0x06, 0xe0, 0x54, 0xfb, 0xf0, 0x80,
-0x04, 0xe0, 0x54, 0xf9, 0xf0, 0x20, 0x19, 0x07, 0x90, 0x12, 0x04, 0xe0, 0x44, 0x04, 0xf0, 0xe5,
-0x34, 0xf4, 0x60, 0x14, 0x90, 0x01, 0x0d, 0xe0, 0xf5, 0x33, 0xe5, 0x34, 0xd3, 0x94, 0x02, 0x40,
-0x07, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfd, 0xf0, 0x75, 0x30, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5,
-0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x30, 0x03, 0xf5, 0x51, 0xe5, 0x30, 0x60, 0x18,
-0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0x20, 0x19, 0x0e, 0xad, 0x30, 0xaf, 0x40, 0x12, 0x18,
-0x2a, 0xe5, 0x30, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x0e,
-0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x18, 0x2a, 0xe5, 0x52,
-0x14, 0x60, 0x55, 0x14, 0x60, 0x2f, 0x24, 0x02, 0x60, 0x03, 0x02, 0x18, 0x27, 0xe5, 0x34, 0xf4,
-0x60, 0x23, 0xe5, 0x34, 0xd3, 0x94, 0x02, 0x40, 0x16, 0x90, 0x12, 0x04, 0xe0, 0x44, 0x02, 0xf0,
-0x90, 0x01, 0x0d, 0xe0, 0x20, 0xe3, 0x03, 0x02, 0x18, 0x27, 0x7f, 0x50, 0x12, 0x16, 0x51, 0x75,
-0x52, 0x02, 0x75, 0x55, 0x03, 0xe5, 0x34, 0xf4, 0x60, 0x0a, 0xe5, 0x54, 0x70, 0x69, 0x90, 0x01,
-0x0d, 0xe5, 0x33, 0xf0, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfb, 0xf0, 0x7f, 0x20, 0x12, 0x16, 0x51,
-0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x80, 0x4f, 0xe5, 0x54, 0x70, 0x4b, 0x90, 0x04, 0x01, 0xe0,
-0x44, 0x0e, 0xf0, 0x20, 0x19, 0x04, 0xe0, 0x54, 0xef, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44, 0x0f,
-0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x03,
-0xf0, 0x20, 0x19, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44,
-0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41,
-0x12, 0x18, 0x2a, 0x80, 0x02, 0xc2, 0x03, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe,
-0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14,
-0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4,
-0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, 0x22, 0x20, 0x19,
-0x03, 0x02, 0x19, 0x0f, 0x90, 0x70, 0x80, 0xe0, 0x04, 0xf0, 0x90, 0x04, 0x37, 0xe0, 0x30, 0xe5,
-0x03, 0x02, 0x19, 0x0b, 0x90, 0x04, 0x28, 0xe0, 0xf5, 0x31, 0xa3, 0xe0, 0xf5, 0x30, 0xf5, 0x32,
-0xe4, 0xf5, 0x37, 0x90, 0x70, 0x81, 0xe0, 0x04, 0xf0, 0x90, 0x70, 0x82, 0xe0, 0x04, 0xf0, 0xe5,
-0x32, 0x75, 0xf0, 0x80, 0xa4, 0x24, 0x00, 0xff, 0xe5, 0xf0, 0x34, 0x80, 0xfe, 0xe5, 0x30, 0x65,
-0x32, 0x70, 0x05, 0xfc, 0x7d, 0x18, 0x80, 0x04, 0x7c, 0x00, 0x7d, 0x00, 0xef, 0x2d, 0xff, 0xee,
-0x3c, 0xfe, 0x12, 0x19, 0x10, 0x50, 0x25, 0x90, 0x70, 0x83, 0xe0, 0x04, 0xf0, 0x90, 0x01, 0x14,
-0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x30, 0xe1, 0x06, 0x90, 0x70, 0x92, 0x74, 0x45, 0xf0, 0x90, 0x70,
-0x93, 0xe0, 0x04, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x90, 0x70, 0x94, 0xf0, 0xe5, 0x32, 0x65, 0x31,
-0x60, 0x10, 0xe4, 0x25, 0x32, 0xff, 0xe4, 0x34, 0x80, 0x8f, 0x82, 0xf5, 0x83, 0xe0, 0xf5, 0x32,
-0x80, 0x97, 0x90, 0x04, 0x10, 0x74, 0x01, 0xf0, 0x90, 0x04, 0x28, 0xe5, 0x31, 0xf0, 0xa3, 0xe5,
-0x30, 0xf0, 0x90, 0x04, 0x11, 0x74, 0x01, 0xf0, 0x02, 0x18, 0x6a, 0xc2, 0x06, 0xd2, 0x1a, 0x22,
-0x90, 0x70, 0x84, 0xe5, 0x37, 0xf0, 0xc3, 0x94, 0x06, 0x50, 0x19, 0x8f, 0x82, 0x8e, 0x83, 0xe0,
-0xb4, 0xff, 0x07, 0x05, 0x37, 0xe4, 0xf5, 0x36, 0x80, 0x59, 0xe4, 0xf5, 0x37, 0x8f, 0x82, 0x8e,
-0x83, 0xf0, 0x80, 0x4f, 0xe5, 0x36, 0x75, 0xf0, 0x06, 0x84, 0x74, 0x08, 0x25, 0xf0, 0xf5, 0x82,
-0xe4, 0x34, 0x10, 0xf5, 0x83, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfc, 0x6d, 0x70, 0x30,
-0x90, 0x70, 0x88, 0xe0, 0x04, 0xf0, 0xa3, 0xe0, 0xfd, 0xd3, 0x95, 0x37, 0x40, 0x02, 0x80, 0x02,
-0xad, 0x37, 0x90, 0x70, 0x89, 0xed, 0xf0, 0x05, 0x37, 0x05, 0x36, 0xe5, 0x36, 0x75, 0xf0, 0x06,
-0x84, 0x74, 0x8a, 0x25, 0xf0, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xec, 0xf0, 0x80, 0x03,
-0xe4, 0xf5, 0x37, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0xef, 0x54, 0x7f, 0x60, 0x0a, 0xe5, 0x37, 0xc3,
-0x94, 0x4e, 0x50, 0x03, 0x02, 0x19, 0x10, 0xe5, 0x37, 0xb4, 0x4e, 0x03, 0xd3, 0x80, 0x01, 0xc3,
-0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x94, 0xeb, } ;
diff --git a/drivers/staging/rt2860/common/firmware_3070.h b/drivers/staging/rt2860/common/firmware_3070.h
deleted file mode 100644
index b710d40..0000000
--- a/drivers/staging/rt2860/common/firmware_3070.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-
-
-u8 FirmwareImage_3070 [] = {
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x13, 0x1f, 0x02,
-0x13, 0x20, 0x02, 0x13, 0x3f, 0x02, 0x13, 0x44, 0x12, 0x13, 0x40, 0x22, 0x02, 0x17, 0xae, 0x02,
-0x18, 0xd2, 0x02, 0x14, 0x3d, 0x02, 0x13, 0x78, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x19,
-0x95, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40,
-0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4,
-0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4,
-0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01,
-0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xc8, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02,
-0x13, 0x1e, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0x9d, 0x10,
-0xd9, 0x31, 0x10, 0xbd, 0x36, 0x11, 0x02, 0x50, 0x11, 0x39, 0x51, 0x11, 0x42, 0x52, 0x11, 0x42,
-0x53, 0x11, 0x42, 0x54, 0x11, 0x83, 0x55, 0x11, 0xd2, 0x56, 0x12, 0x25, 0x70, 0x12, 0x50, 0x71,
-0x12, 0x7e, 0x72, 0x12, 0xd5, 0x73, 0x12, 0xf6, 0x80, 0x00, 0x00, 0x13, 0x1e, 0x90, 0x70, 0x11,
-0xe0, 0xf5, 0x3c, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe5, 0x56,
-0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d,
-0x02, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13,
-0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x85, 0x56, 0x41, 0xd2,
-0x02, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff, 0xbf, 0x0a, 0x0d, 0x90, 0x70, 0x11, 0xe0,
-0xb4, 0x08, 0x06, 0x75, 0x4e, 0x01, 0x75, 0x4f, 0x84, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff,
-0xbf, 0x02, 0x12, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x04, 0xe0, 0xb4, 0x20, 0x06, 0x75,
-0x4e, 0x03, 0x75, 0x4f, 0x20, 0xe4, 0xf5, 0x27, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92,
-0x47, 0x22, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0,
-0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48,
-0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14,
-0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e,
-0x02, 0x13, 0x17, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x1d, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x17, 0xe5,
-0x47, 0x64, 0x09, 0x60, 0x11, 0xe5, 0x47, 0x64, 0x0a, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x0b, 0x60,
-0x05, 0xe5, 0x47, 0xb4, 0x0c, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47,
-0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03, 0x03, 0xe4, 0xf5, 0x46, 0xe5, 0x47, 0xb4, 0x0a, 0x08,
-0xe5, 0x3a, 0xb4, 0x01, 0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0xd2,
-0x04, 0x22, 0x90, 0x70, 0x11, 0xe0, 0xf4, 0xff, 0x90, 0x70, 0x10, 0xe0, 0x5f, 0xff, 0x90, 0x70,
-0x11, 0xe0, 0x55, 0x27, 0x4f, 0x90, 0x70, 0x18, 0xf0, 0x90, 0x70, 0x11, 0xe0, 0x90, 0x70, 0x19,
-0xf0, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x30, 0x15, 0x03, 0xd2, 0x14, 0x22, 0x90, 0x70,
-0x18, 0xe0, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, 0x5e,
-0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x90,
-0x02, 0x28, 0xef, 0xf0, 0x22, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed,
-0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0,
-0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17,
-0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0,
-0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90,
-0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x90, 0x10,
-0x00, 0xe0, 0xf5, 0x57, 0x90, 0x10, 0x02, 0xe0, 0xf5, 0x58, 0xa3, 0xe0, 0xf5, 0x59, 0xe5, 0x58,
-0xb4, 0x70, 0x1e, 0xe5, 0x59, 0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd,
-0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08,
-0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x3a, 0xff, 0x75, 0x3c, 0xff, 0xad, 0x57, 0xaf, 0x56,
-0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56,
-0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf,
-0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
-0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05,
-0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70,
-0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22,
-0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2, 0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04,
-0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22,
-0xc2, 0x42, 0xd3, 0x22, 0x30, 0x14, 0x30, 0x90, 0x70, 0x19, 0xe0, 0x55, 0x27, 0xff, 0x90, 0x70,
-0x18, 0xe0, 0x4f, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef,
-0x5e, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff,
-0x90, 0x02, 0x28, 0xef, 0xf0, 0xc2, 0x14, 0x22, 0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x0a,
-0x9d, 0x13, 0x9a, 0x00, 0x14, 0x28, 0x04, 0x14, 0x24, 0x08, 0x14, 0x04, 0x10, 0x13, 0xae, 0x20,
-0x13, 0xce, 0x60, 0x13, 0xdf, 0xa0, 0x00, 0x00, 0x14, 0x2a, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42,
-0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x14, 0x2a, 0x80, 0x1b, 0xe5, 0x48,
-0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54,
-0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x61, 0x53, 0x43, 0x0f, 0x80, 0x5c, 0x85, 0x49,
-0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4d, 0x80, 0x1b, 0xe5,
-0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4,
-0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x30, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10,
-0xf5, 0x43, 0x80, 0x26, 0xe5, 0x47, 0x64, 0x04, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43,
-0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30,
-0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4,
-0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0xd2, 0x60, 0x22, 0xd2, 0x15, 0xe5,
-0x47, 0x24, 0xf5, 0x60, 0x0b, 0x24, 0xcb, 0x60, 0x07, 0x24, 0x40, 0x70, 0x06, 0xc2, 0x15, 0x22,
-0x12, 0x17, 0x79, 0x12, 0x14, 0x5f, 0xc2, 0x15, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2,
-0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45,
-0x4f, 0x24, 0xff, 0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74,
-0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5,
-0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5,
-0x25, 0x70, 0x05, 0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f,
-0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5,
-0x47, 0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25,
-0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02,
-0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b,
-0xe5, 0x3a, 0x64, 0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0xe5,
-0x47, 0xb4, 0x0a, 0x13, 0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x08, 0xe5,
-0x3a, 0x70, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2,
-0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e,
-0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26, 0x30,
-0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80,
-0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e,
-0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x26,
-0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01,
-0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02,
-0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80,
-0x26, 0xe5, 0x47, 0x64, 0x0a, 0x70, 0x22, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x17,
-0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x34, 0xe5, 0x46, 0x20, 0xe4, 0x03,
-0x30, 0xe5, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2,
-0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54,
-0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92,
-0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3,
-0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92, 0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13,
-0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2, 0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47,
-0x64, 0x06, 0x70, 0x39, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f,
-0x14, 0x60, 0x0c, 0x24, 0xfe, 0x60, 0x0c, 0x24, 0x03, 0x70, 0x13, 0xc2, 0x38, 0x80, 0x0f, 0xd2,
-0x38, 0x80, 0x0b, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x38, 0x30, 0x47,
-0x05, 0xaf, 0x27, 0x02, 0x17, 0x73, 0xe5, 0x27, 0xf4, 0xff, 0x02, 0x17, 0x73, 0xe5, 0x47, 0x64,
-0x07, 0x60, 0x0f, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02,
-0x16, 0xf2, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x22, 0x14, 0x60,
-0x25, 0x14, 0x60, 0x2d, 0x24, 0xfc, 0x60, 0x49, 0x24, 0xf9, 0x60, 0x14, 0x24, 0x0e, 0x70, 0x50,
-0xe5, 0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x24, 0xff, 0x80, 0x3a,
-0xd2, 0x39, 0xc2, 0x38, 0x80, 0x3e, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x1d, 0xc3, 0x80,
-0x1a, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f,
-0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x38, 0xc2, 0x39, 0x80,
-0x13, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0xc2, 0x38, 0x80, 0x04,
-0xc2, 0x38, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x02,
-0x17, 0x73, 0xe5, 0x47, 0x64, 0x0c, 0x60, 0x06, 0xe5, 0x47, 0x64, 0x0b, 0x70, 0x7a, 0x90, 0x02,
-0x29, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x20, 0x14, 0x60, 0x21, 0x14, 0x60, 0x2b,
-0x24, 0xfc, 0x60, 0x45, 0x24, 0xf9, 0x60, 0x12, 0x24, 0x0e, 0x70, 0x4a, 0xe5, 0x46, 0x13, 0x13,
-0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x80, 0x29, 0xd2, 0x39, 0x80, 0x3a, 0xe5, 0x46,
-0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0x80, 0x2d, 0xe5, 0x46, 0x30, 0xe2, 0x0d,
-0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f,
-0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x39, 0x80, 0x0f, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80,
-0x01, 0xc3, 0x92, 0x39, 0x80, 0x02, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5,
-0x27, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0xe5, 0x47, 0xb4, 0x0b, 0x10, 0x90, 0x02,
-0x29, 0xe0, 0x54, 0xeb, 0xf0, 0xe5, 0x27, 0x54, 0xeb, 0x45, 0x45, 0xf5, 0x27, 0x22, 0xe4, 0x90,
-0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02,
-0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5,
-0x62, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x48, 0x14, 0x60, 0x66, 0x24, 0x02, 0x60, 0x03, 0x02,
-0x18, 0xb6, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0,
-0x20, 0xe7, 0x23, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3,
-0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0,
-0x75, 0x51, 0x01, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x06, 0x75, 0x62, 0x03, 0x02, 0x18, 0xb6,
-0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x02, 0xa2,
-0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x03, 0x02, 0x18,
-0xb1, 0x90, 0x02, 0xa3, 0xe0, 0x30, 0xe6, 0x03, 0x02, 0x18, 0xad, 0x90, 0x04, 0x37, 0xe0, 0x64,
-0x22, 0x70, 0x7a, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96, 0xf0, 0x90, 0x12, 0x04,
-0x74, 0x0a, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x15, 0xe5, 0x59, 0xb4, 0x35, 0x10, 0xe4, 0x90, 0x05,
-0x00, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, 0x12,
-0x0d, 0x2a, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xf0, 0xf0, 0xe5, 0x59,
-0xb4, 0x35, 0x14, 0xe5, 0x3c, 0xf4, 0x60, 0x06, 0xa3, 0xe0, 0x54, 0xf3, 0x80, 0x14, 0x90, 0x13,
-0x2a, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x14, 0xe5, 0x3c, 0xf4, 0x90, 0x13, 0x2a, 0x60, 0x08, 0xe0,
-0x54, 0xf2, 0x45, 0x3c, 0xf0, 0x80, 0x04, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54,
-0xfd, 0xf0, 0x75, 0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70,
-0x05, 0x75, 0x62, 0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2,
-0x59, 0xad, 0x62, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2,
-0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59,
-0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70,
-0x6d, 0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13,
-0x28, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90,
-0x12, 0x04, 0x74, 0x03, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x16, 0xe5, 0x59, 0xb4, 0x35, 0x11, 0x90,
-0x05, 0x00, 0x74, 0xe2, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0,
-0x7f, 0x01, 0x12, 0x0d, 0x2a, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0,
-0x44, 0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x09, 0xc2, 0x02, 0x7d, 0x01, 0xaf,
-0x41, 0x12, 0x19, 0x61, 0x30, 0x03, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf,
-0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5,
-0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef,
-0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe,
-0x04, 0xd5, 0x22, 0x22, 0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70,
-0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70,
-0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0,
-0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90,
-0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70,
-0x24, 0xe0, 0x44, 0x01, 0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x7b, 0xc4,
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x13, 0x1f, 0x02,
-0x13, 0x20, 0x02, 0x13, 0x3f, 0x02, 0x13, 0x44, 0x12, 0x13, 0x40, 0x22, 0x02, 0x17, 0xae, 0x02,
-0x18, 0xd2, 0x02, 0x14, 0x3d, 0x02, 0x13, 0x78, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x19,
-0x95, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40,
-0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4,
-0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4,
-0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01,
-0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xdd, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02,
-0x13, 0x1e, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0xb6, 0x10,
-0xd9, 0x31, 0x10, 0xbd, 0x36, 0x11, 0x02, 0x50, 0x11, 0x39, 0x51, 0x11, 0x42, 0x52, 0x11, 0x42,
-0x53, 0x11, 0x42, 0x54, 0x11, 0x83, 0x55, 0x11, 0xd2, 0x56, 0x12, 0x25, 0x70, 0x12, 0x50, 0x71,
-0x12, 0x7e, 0x72, 0x12, 0xd5, 0x73, 0x12, 0xf6, 0x80, 0x00, 0x00, 0x13, 0x1e, 0x90, 0x70, 0x11,
-0xe0, 0xf5, 0x3c, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe5, 0x56,
-0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d,
-0x02, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13,
-0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x85, 0x56, 0x41, 0xd2,
-0x02, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff, 0xbf, 0x0a, 0x0d, 0x90, 0x70, 0x11, 0xe0,
-0xb4, 0x08, 0x06, 0x75, 0x4e, 0x01, 0x75, 0x4f, 0x84, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff,
-0xbf, 0x02, 0x12, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x04, 0xe0, 0xb4, 0x20, 0x06, 0x75,
-0x4e, 0x03, 0x75, 0x4f, 0x20, 0xe4, 0xf5, 0x27, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92,
-0x47, 0x22, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0,
-0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48,
-0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14,
-0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e,
-0x02, 0x13, 0x17, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x1d, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x17, 0xe5,
-0x47, 0x64, 0x09, 0x60, 0x11, 0xe5, 0x47, 0x64, 0x0a, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x0b, 0x60,
-0x05, 0xe5, 0x47, 0xb4, 0x0c, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47,
-0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03, 0x03, 0xe4, 0xf5, 0x46, 0xe5, 0x47, 0xb4, 0x0a, 0x08,
-0xe5, 0x3a, 0xb4, 0x01, 0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0xd2,
-0x04, 0x22, 0x90, 0x70, 0x11, 0xe0, 0xf4, 0xff, 0x90, 0x70, 0x10, 0xe0, 0x5f, 0xff, 0x90, 0x70,
-0x11, 0xe0, 0x55, 0x27, 0x4f, 0x90, 0x70, 0x18, 0xf0, 0x90, 0x70, 0x11, 0xe0, 0x90, 0x70, 0x19,
-0xf0, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x30, 0x15, 0x03, 0xd2, 0x14, 0x22, 0x90, 0x70,
-0x18, 0xe0, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, 0x5e,
-0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x90,
-0x02, 0x28, 0xef, 0xf0, 0x22, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed,
-0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0,
-0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17,
-0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0,
-0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90,
-0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x90, 0x10,
-0x00, 0xe0, 0xf5, 0x57, 0x90, 0x10, 0x02, 0xe0, 0xf5, 0x58, 0xa3, 0xe0, 0xf5, 0x59, 0xe5, 0x58,
-0xb4, 0x70, 0x1e, 0xe5, 0x59, 0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd,
-0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08,
-0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x3a, 0xff, 0x75, 0x3c, 0xff, 0xad, 0x57, 0xaf, 0x56,
-0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56,
-0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf,
-0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
-0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05,
-0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70,
-0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22,
-0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2, 0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04,
-0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22,
-0xc2, 0x42, 0xd3, 0x22, 0x30, 0x14, 0x30, 0x90, 0x70, 0x19, 0xe0, 0x55, 0x27, 0xff, 0x90, 0x70,
-0x18, 0xe0, 0x4f, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef,
-0x5e, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff,
-0x90, 0x02, 0x28, 0xef, 0xf0, 0xc2, 0x14, 0x22, 0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x0a,
-0xb6, 0x13, 0x9a, 0x00, 0x14, 0x28, 0x04, 0x14, 0x24, 0x08, 0x14, 0x04, 0x10, 0x13, 0xae, 0x20,
-0x13, 0xce, 0x60, 0x13, 0xdf, 0xa0, 0x00, 0x00, 0x14, 0x2a, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42,
-0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x14, 0x2a, 0x80, 0x1b, 0xe5, 0x48,
-0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54,
-0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x61, 0x53, 0x43, 0x0f, 0x80, 0x5c, 0x85, 0x49,
-0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4d, 0x80, 0x1b, 0xe5,
-0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4,
-0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x30, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10,
-0xf5, 0x43, 0x80, 0x26, 0xe5, 0x47, 0x64, 0x04, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43,
-0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30,
-0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4,
-0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0xd2, 0x60, 0x22, 0xd2, 0x15, 0xe5,
-0x47, 0x24, 0xf5, 0x60, 0x0b, 0x24, 0xcb, 0x60, 0x07, 0x24, 0x40, 0x70, 0x06, 0xc2, 0x15, 0x22,
-0x12, 0x17, 0x79, 0x12, 0x14, 0x5f, 0xc2, 0x15, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2,
-0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45,
-0x4f, 0x24, 0xff, 0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74,
-0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5,
-0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5,
-0x25, 0x70, 0x05, 0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f,
-0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5,
-0x47, 0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25,
-0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02,
-0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b,
-0xe5, 0x3a, 0x64, 0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0xe5,
-0x47, 0xb4, 0x0a, 0x13, 0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x08, 0xe5,
-0x3a, 0x70, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2,
-0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e,
-0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26, 0x30,
-0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80,
-0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e,
-0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x26,
-0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01,
-0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02,
-0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80,
-0x26, 0xe5, 0x47, 0x64, 0x0a, 0x70, 0x22, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x17,
-0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x34, 0xe5, 0x46, 0x20, 0xe4, 0x03,
-0x30, 0xe5, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2,
-0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54,
-0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92,
-0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3,
-0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92, 0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13,
-0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2, 0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47,
-0x64, 0x06, 0x70, 0x39, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f,
-0x14, 0x60, 0x0c, 0x24, 0xfe, 0x60, 0x0c, 0x24, 0x03, 0x70, 0x13, 0xc2, 0x38, 0x80, 0x0f, 0xd2,
-0x38, 0x80, 0x0b, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x38, 0x30, 0x47,
-0x05, 0xaf, 0x27, 0x02, 0x17, 0x73, 0xe5, 0x27, 0xf4, 0xff, 0x02, 0x17, 0x73, 0xe5, 0x47, 0x64,
-0x07, 0x60, 0x0f, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02,
-0x16, 0xf2, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x22, 0x14, 0x60,
-0x25, 0x14, 0x60, 0x2d, 0x24, 0xfc, 0x60, 0x49, 0x24, 0xf9, 0x60, 0x14, 0x24, 0x0e, 0x70, 0x50,
-0xe5, 0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x24, 0xff, 0x80, 0x3a,
-0xd2, 0x39, 0xc2, 0x38, 0x80, 0x3e, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x1d, 0xc3, 0x80,
-0x1a, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f,
-0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x38, 0xc2, 0x39, 0x80,
-0x13, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0xc2, 0x38, 0x80, 0x04,
-0xc2, 0x38, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x02,
-0x17, 0x73, 0xe5, 0x47, 0x64, 0x0c, 0x60, 0x06, 0xe5, 0x47, 0x64, 0x0b, 0x70, 0x7a, 0x90, 0x02,
-0x29, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x20, 0x14, 0x60, 0x21, 0x14, 0x60, 0x2b,
-0x24, 0xfc, 0x60, 0x45, 0x24, 0xf9, 0x60, 0x12, 0x24, 0x0e, 0x70, 0x4a, 0xe5, 0x46, 0x13, 0x13,
-0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x80, 0x29, 0xd2, 0x39, 0x80, 0x3a, 0xe5, 0x46,
-0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0x80, 0x2d, 0xe5, 0x46, 0x30, 0xe2, 0x0d,
-0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f,
-0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x39, 0x80, 0x0f, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80,
-0x01, 0xc3, 0x92, 0x39, 0x80, 0x02, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5,
-0x27, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0xe5, 0x47, 0xb4, 0x0b, 0x10, 0x90, 0x02,
-0x29, 0xe0, 0x54, 0xeb, 0xf0, 0xe5, 0x27, 0x54, 0xeb, 0x45, 0x45, 0xf5, 0x27, 0x22, 0xe4, 0x90,
-0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02,
-0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5,
-0x62, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x48, 0x14, 0x60, 0x66, 0x24, 0x02, 0x60, 0x03, 0x02,
-0x18, 0xb6, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0,
-0x20, 0xe7, 0x23, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3,
-0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0,
-0x75, 0x51, 0x01, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x06, 0x75, 0x62, 0x03, 0x02, 0x18, 0xb6,
-0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x02, 0xa2,
-0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x03, 0x02, 0x18,
-0xb1, 0x90, 0x02, 0xa3, 0xe0, 0x30, 0xe6, 0x03, 0x02, 0x18, 0xad, 0x90, 0x04, 0x37, 0xe0, 0x64,
-0x22, 0x70, 0x7a, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96, 0xf0, 0x90, 0x12, 0x04,
-0x74, 0x0a, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x15, 0xe5, 0x59, 0xb4, 0x35, 0x10, 0xe4, 0x90, 0x05,
-0x00, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, 0x12,
-0x0d, 0x48, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xf0, 0xf0, 0xe5, 0x59,
-0xb4, 0x35, 0x14, 0xe5, 0x3c, 0xf4, 0x60, 0x06, 0xa3, 0xe0, 0x54, 0xf3, 0x80, 0x14, 0x90, 0x13,
-0x2a, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x14, 0xe5, 0x3c, 0xf4, 0x90, 0x13, 0x2a, 0x60, 0x08, 0xe0,
-0x54, 0xf2, 0x45, 0x3c, 0xf0, 0x80, 0x04, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54,
-0xfd, 0xf0, 0x75, 0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70,
-0x05, 0x75, 0x62, 0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2,
-0x59, 0xad, 0x62, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2,
-0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59,
-0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70,
-0x6d, 0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13,
-0x28, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90,
-0x12, 0x04, 0x74, 0x03, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x16, 0xe5, 0x59, 0xb4, 0x35, 0x11, 0x90,
-0x05, 0x00, 0x74, 0xe2, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0,
-0x7f, 0x01, 0x12, 0x0d, 0x48, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0,
-0x44, 0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x09, 0xc2, 0x02, 0x7d, 0x01, 0xaf,
-0x41, 0x12, 0x19, 0x61, 0x30, 0x03, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf,
-0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5,
-0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef,
-0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe,
-0x04, 0xd5, 0x22, 0x22, 0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70,
-0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70,
-0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0,
-0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90,
-0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70,
-0x24, 0xe0, 0x44, 0x01, 0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x65, 0xd3, } ;
diff --git a/drivers/staging/rt2860/common/rtmp_mcu.c b/drivers/staging/rt2860/common/rtmp_mcu.c
index 9f03901..844d4b9 100644
--- a/drivers/staging/rt2860/common/rtmp_mcu.c
+++ b/drivers/staging/rt2860/common/rtmp_mcu.c
@@ -37,35 +37,38 @@
 
 #include	"../rt_config.h"
 
-#if defined(RT2860) || defined(RT3090)
-#include "firmware.h"
-#include "../../rt3090/firmware.h"
-#endif
-#ifdef RT2870
-#include "../../rt3070/firmware.h"
-#include "firmware_3070.h"
-#endif
-
-#include <linux/bitrev.h>
+#include <linux/crc-ccitt.h>
+#include <linux/firmware.h>
 
 #ifdef RTMP_MAC_USB
-/* */
-/* RT2870 Firmware Spec only used 1 oct for version expression */
-/* */
-#define FIRMWARE_MINOR_VERSION	7
-#endif /* RTMP_MAC_USB // */
 
-/* New 8k byte firmware size for RT3071/RT3072 */
-#define FIRMWAREIMAGE_MAX_LENGTH	0x2000
-#define FIRMWAREIMAGE_LENGTH			(sizeof (FirmwareImage) / sizeof(u8))
-#define FIRMWARE_MAJOR_VERSION		0
+#define FIRMWAREIMAGE_LENGTH		0x1000
 
-#define FIRMWAREIMAGEV1_LENGTH		0x1000
-#define FIRMWAREIMAGEV2_LENGTH		0x1000
+#define FIRMWARE_2870_MIN_VERSION	12
+#define FIRMWARE_2870_FILENAME		"rt2870.bin"
+MODULE_FIRMWARE(FIRMWARE_2870_FILENAME);
 
-#ifdef RTMP_MAC_PCI
-#define FIRMWARE_MINOR_VERSION		2
-#endif /* RTMP_MAC_PCI // */
+#define FIRMWARE_3070_MIN_VERSION	17
+#define FIRMWARE_3070_FILENAME		"rt3070.bin"
+MODULE_FIRMWARE(FIRMWARE_3070_FILENAME);
+
+#define FIRMWARE_3071_MIN_VERSION	17
+#define FIRMWARE_3071_FILENAME		"rt3071.bin"	/* for RT3071/RT3072 */
+MODULE_FIRMWARE(FIRMWARE_3071_FILENAME);
+
+#else /* RTMP_MAC_PCI */
+
+#define FIRMWAREIMAGE_LENGTH		0x2000
+
+#define FIRMWARE_2860_MIN_VERSION	11
+#define FIRMWARE_2860_FILENAME		"rt2860.bin"
+MODULE_FIRMWARE(FIRMWARE_2860_FILENAME);
+
+#define FIRMWARE_3090_MIN_VERSION	19
+#define FIRMWARE_3090_FILENAME		"rt3090.bin"	/* for RT3090/RT3390 */
+MODULE_FIRMWARE(FIRMWARE_3090_FILENAME);
+
+#endif
 
 /*
 	========================================================================
@@ -90,6 +93,78 @@
 	return 0;
 }
 
+static const struct firmware *rtmp_get_firmware(struct rt_rtmp_adapter *adapter)
+{
+	const char *name;
+	const struct firmware *fw = NULL;
+	u8 min_version;
+	struct device *dev;
+	int err;
+
+	if (adapter->firmware)
+		return adapter->firmware;
+
+#ifdef RTMP_MAC_USB
+	if (IS_RT3071(adapter)) {
+		name = FIRMWARE_3071_FILENAME;
+		min_version = FIRMWARE_3071_MIN_VERSION;
+	} else if (IS_RT3070(adapter)) {
+		name = FIRMWARE_3070_FILENAME;
+		min_version = FIRMWARE_3070_MIN_VERSION;
+	} else {
+		name = FIRMWARE_2870_FILENAME;
+		min_version = FIRMWARE_2870_MIN_VERSION;
+	}
+	dev = &((struct os_cookie *)adapter->OS_Cookie)->pUsb_Dev->dev;
+#else /* RTMP_MAC_PCI */
+	if (IS_RT3090(adapter) || IS_RT3390(adapter)) {
+		name = FIRMWARE_3090_FILENAME;
+		min_version = FIRMWARE_3090_MIN_VERSION;
+	} else {
+		name = FIRMWARE_2860_FILENAME;
+		min_version = FIRMWARE_2860_MIN_VERSION;
+	}
+	dev = &((struct os_cookie *)adapter->OS_Cookie)->pci_dev->dev;
+#endif
+
+	err = request_firmware(&fw, name, dev);
+	if (err) {
+		dev_err(dev, "firmware file %s request failed (%d)\n",
+			name, err);
+		return NULL;
+	}
+
+	if (fw->size < FIRMWAREIMAGE_LENGTH) {
+		dev_err(dev, "firmware file %s size is invalid\n", name);
+		goto invalid;
+	}
+
+	/* is it new enough? */
+	adapter->FirmwareVersion = fw->data[FIRMWAREIMAGE_LENGTH - 3];
+	if (adapter->FirmwareVersion < min_version) {
+		dev_err(dev,
+			"firmware file %s is too old;"
+			" driver requires v%d or later\n",
+			name, min_version);
+		goto invalid;
+	}
+
+	/* is the internal CRC correct? */
+	if (crc_ccitt(0xffff, fw->data, FIRMWAREIMAGE_LENGTH - 2) !=
+	    (fw->data[FIRMWAREIMAGE_LENGTH - 2] |
+	     (fw->data[FIRMWAREIMAGE_LENGTH - 1] << 8))) {
+		dev_err(dev, "firmware file %s failed internal CRC\n", name);
+		goto invalid;
+	}
+
+	adapter->firmware = fw;
+	return fw;
+
+invalid:
+	release_firmware(fw);
+	return NULL;
+}
+
 /*
 	========================================================================
 
@@ -109,46 +184,16 @@
 */
 int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd)
 {
-
+	const struct firmware *fw;
 	int Status = NDIS_STATUS_SUCCESS;
-	u8 *pFirmwareImage = NULL;
-	unsigned long FileLength, Index;
+	unsigned long Index;
 	u32 MacReg = 0;
-#ifdef RTMP_MAC_USB
-	u32 Version = (pAd->MACVersion >> 16);
-#endif
 
-	/* New 8k byte firmware size for RT3071/RT3072 */
-	{
-#ifdef RTMP_MAC_PCI
-		if (IS_RT3090(pAd) || IS_RT3390(pAd)) {
-			pFirmwareImage = FirmwareImage_3090;
-			FileLength = FIRMWAREIMAGE_MAX_LENGTH;
-		} else {
-			pFirmwareImage = FirmwareImage_2860;
-			FileLength = FIRMWAREIMAGE_MAX_LENGTH;
-		}
-#endif /* RTMP_MAC_PCI // */
-#ifdef RTMP_MAC_USB
-		/* the firmware image consists of two parts */
-		if ((Version != 0x2860) && (Version != 0x2872) && (Version != 0x3070)) {	/* use the second part */
-			/*printk("KH:Use New Version,part2\n"); */
-			pFirmwareImage =
-			    (u8 *)&
-			    FirmwareImage_3070[FIRMWAREIMAGEV1_LENGTH];
-			FileLength = FIRMWAREIMAGEV2_LENGTH;
-		} else {
-			/*printk("KH:Use New Version,part1\n"); */
-			if (Version == 0x3070)
-				pFirmwareImage = FirmwareImage_3070;
-			else
-				pFirmwareImage = FirmwareImage_2870;
-			FileLength = FIRMWAREIMAGEV1_LENGTH;
-		}
-#endif /* RTMP_MAC_USB // */
-	}
+	fw = rtmp_get_firmware(pAd);
+	if (!fw)
+		return NDIS_STATUS_FAILURE;
 
-	RTMP_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength);
+	RTMP_WRITE_FIRMWARE(pAd, fw->data, FIRMWAREIMAGE_LENGTH);
 
 	/* check if MCU is ready */
 	Index = 0;
@@ -221,7 +266,7 @@
 				 ("AsicSendCommanToMcu::Mail box is busy\n"));
 		} while (i++ < 100);
 
-		if (i >= 100) {
+		if (i > 100) {
 			DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
 			return FALSE;
 		}
diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c
index 9357fb2..b5c78ae 100644
--- a/drivers/staging/rt2860/rt_linux.c
+++ b/drivers/staging/rt2860/rt_linux.c
@@ -25,6 +25,7 @@
  *************************************************************************
  */
 
+#include <linux/firmware.h>
 #include <linux/sched.h>
 #include "rt_config.h"
 
@@ -260,6 +261,8 @@
 
 	NdisFreeSpinLock(&pAd->irq_lock);
 
+	release_firmware(pAd->firmware);
+
 	vfree(pAd);		/* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */
 	if (os_cookie)
 		kfree(os_cookie);
@@ -462,9 +465,9 @@
 	if ((skb =
 	     __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) {
 		skb_reserve(skb, 2);
-		NdisMoveMemory(skb->tail, pHeader802_3, HdrLen);
+		NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen);
 		skb_put(skb, HdrLen);
-		NdisMoveMemory(skb->tail, pData, DataSize);
+		NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize);
 		skb_put(skb, DataSize);
 		skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
 		pPacket = OSPKT_TO_RTPKT(skb);
@@ -515,7 +518,7 @@
 		pClonedPkt->dev = pRxPkt->dev;
 		pClonedPkt->data = pData;
 		pClonedPkt->len = DataSize;
-		pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
+		skb_set_tail_pointer(pClonedPkt, DataSize)
 		ASSERT(DataSize < 1530);
 	}
 	return pClonedPkt;
@@ -535,7 +538,7 @@
 	pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
 	pOSPkt->data = pRxBlk->pData;
 	pOSPkt->len = pRxBlk->DataSize;
-	pOSPkt->tail = pOSPkt->data + pOSPkt->len;
+	skb_set_tail_pointer(pOSPkt, pOSPkt->len);
 }
 
 void wlan_802_11_to_802_3_packet(struct rt_rtmp_adapter *pAd,
@@ -553,7 +556,7 @@
 	pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
 	pOSPkt->data = pRxBlk->pData;
 	pOSPkt->len = pRxBlk->DataSize;
-	pOSPkt->tail = pOSPkt->data + pOSPkt->len;
+	skb_set_tail_pointer(pOSPkt, pOSPkt->len);
 
 	/* */
 	/* copy 802.3 header */
diff --git a/drivers/staging/rt2860/rt_linux.h b/drivers/staging/rt2860/rt_linux.h
index f85508d..a7c540f 100644
--- a/drivers/staging/rt2860/rt_linux.h
+++ b/drivers/staging/rt2860/rt_linux.h
@@ -658,9 +658,9 @@
 		(RTPKT_TO_OSPKT(_pkt)->len) = (_len)
 
 #define GET_OS_PKT_DATATAIL(_pkt) \
-		(RTPKT_TO_OSPKT(_pkt)->tail)
+		(skb_tail_pointer(RTPKT_TO_OSPKT(_pkt))
 #define SET_OS_PKT_DATATAIL(_pkt, _start, _len)	\
-		((RTPKT_TO_OSPKT(_pkt))->tail) = (u8 *)((_start) + (_len))
+		(skb_set_tail_pointer(RTPKT_TO_OSPKT(_pkt), _len))
 
 #define GET_OS_PKT_HEAD(_pkt) \
 		(RTPKT_TO_OSPKT(_pkt)->head)
diff --git a/drivers/staging/rt2860/rt_main_dev.c b/drivers/staging/rt2860/rt_main_dev.c
index c3d92802..fbddb00 100644
--- a/drivers/staging/rt2860/rt_main_dev.c
+++ b/drivers/staging/rt2860/rt_main_dev.c
@@ -216,7 +216,7 @@
 	u32 i = 0;
 
 #ifdef RTMP_MAC_USB
-	DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
+	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup);
 	DECLARE_WAITQUEUE(wait, current);
 #endif /* RTMP_MAC_USB // */
 
diff --git a/drivers/staging/rt2860/rtmp.h b/drivers/staging/rt2860/rtmp.h
index c50abf4..4401a55 100644
--- a/drivers/staging/rt2860/rtmp.h
+++ b/drivers/staging/rt2860/rtmp.h
@@ -1719,6 +1719,7 @@
 	void *OS_Cookie;	/* save specific structure relative to OS */
 	struct net_device *net_dev;
 	unsigned long VirtualIfCnt;
+	const struct firmware *firmware;
 
 	struct rt_rtmp_chip_op chipOps;
 	u16 ThisTbttNumToNextWakeUp;
@@ -4043,10 +4044,10 @@
 			u16 Offset, u8 *pData, u16 length);
 
 int RTUSBMultiWrite(struct rt_rtmp_adapter *pAd,
-			 u16 Offset, u8 *pData, u16 length);
+		    u16 Offset, const u8 *pData, u16 length);
 
 int RTUSBMultiWrite_OneByte(struct rt_rtmp_adapter *pAd,
-				 u16 Offset, u8 *pData);
+			    u16 Offset, const u8 *pData);
 
 int RTUSBReadBBPRegister(struct rt_rtmp_adapter *pAd,
 			      u8 Id, u8 *pValue);
@@ -4112,7 +4113,7 @@
 			  u16 Offset, u16 Value);
 
 int RTUSBFirmwareWrite(struct rt_rtmp_adapter *pAd,
-			    u8 *pFwImage, unsigned long FwLen);
+		       const u8 *pFwImage, unsigned long FwLen);
 
 int RTUSBVenderReset(struct rt_rtmp_adapter *pAd);
 
diff --git a/drivers/staging/rt2860/sta/connect.c b/drivers/staging/rt2860/sta/connect.c
index 17e59ba..55732b1 100644
--- a/drivers/staging/rt2860/sta/connect.c
+++ b/drivers/staging/rt2860/sta/connect.c
@@ -62,8 +62,8 @@
 u8 CipherSuiteWpaNoneAesLen =
     (sizeof(CipherSuiteWpaNoneAes) / sizeof(u8));
 
-/* The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS, */
-/* or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS */
+/* The following MACRO is called after 1. starting an new IBSS, 2. successfully JOIN an IBSS, */
+/* or 3. successfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS */
 /* All settings successfuly negotiated furing MLME state machines become final settings */
 /* and are copied to pAd->StaActive */
 #define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd)                                 \
diff --git a/drivers/staging/rt2860/sta_ioctl.c b/drivers/staging/rt2860/sta_ioctl.c
index d8fbe6c..de4b627 100644
--- a/drivers/staging/rt2860/sta_ioctl.c
+++ b/drivers/staging/rt2860/sta_ioctl.c
@@ -975,10 +975,7 @@
 		/*================================ */
 		memset(&iwe, 0, sizeof(iwe));
 		iwe.cmd = SIOCGIWFREQ;
-		if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
-			iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
-		else
-			iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
+		iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
 		iwe.u.freq.e = 0;
 		iwe.u.freq.i = 0;
 
diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c
index 925a236..1873a79 100644
--- a/drivers/staging/rt2860/usb_main_dev.c
+++ b/drivers/staging/rt2860/usb_main_dev.c
@@ -216,10 +216,6 @@
 static int rt2870_resume(struct usb_interface *intf);
 #endif /* CONFIG_PM // */
 
-static int rtusb_probe(struct usb_interface *intf,
-		       const struct usb_device_id *id);
-static void rtusb_disconnect(struct usb_interface *intf);
-
 static BOOLEAN USBDevConfigInit(IN struct usb_device *dev,
 				IN struct usb_interface *intf,
 				struct rt_rtmp_adapter *pAd)
@@ -296,7 +292,7 @@
 
 }
 
-static int rtusb_probe(struct usb_interface *intf,
+static int __devinit rtusb_probe(struct usb_interface *intf,
 		       const struct usb_device_id *id)
 {
 	struct rt_rtmp_adapter *pAd;
diff --git a/drivers/staging/rt2870/Kconfig b/drivers/staging/rt2870/Kconfig
index fd3ba3a..6ea172b 100644
--- a/drivers/staging/rt2870/Kconfig
+++ b/drivers/staging/rt2870/Kconfig
@@ -3,5 +3,7 @@
 	depends on USB && X86 && WLAN
 	select WIRELESS_EXT
 	select WEXT_PRIV
+	select CRC_CCITT
+	select FW_LOADER
 	---help---
 	  This is an experimental driver for the Ralink xx70 wireless chips.
diff --git a/drivers/staging/rt2870/common/rtusb_io.c b/drivers/staging/rt2870/common/rtusb_io.c
index 34443f2..cf0d2f5 100644
--- a/drivers/staging/rt2870/common/rtusb_io.c
+++ b/drivers/staging/rt2870/common/rtusb_io.c
@@ -84,7 +84,7 @@
 	========================================================================
 */
 int RTUSBFirmwareWrite(struct rt_rtmp_adapter *pAd,
-			    u8 *pFwImage, unsigned long FwLen)
+		       const u8 *pFwImage, unsigned long FwLen)
 {
 	u32 MacReg;
 	int Status;
@@ -167,7 +167,7 @@
 	========================================================================
 */
 int RTUSBMultiWrite_OneByte(struct rt_rtmp_adapter *pAd,
-				 u16 Offset, u8 *pData)
+			    u16 Offset, const u8 *pData)
 {
 	int Status;
 
@@ -175,18 +175,18 @@
 	Status = RTUSB_VendorRequest(pAd,
 				     USBD_TRANSFER_DIRECTION_OUT,
 				     DEVICE_VENDOR_REQUEST_OUT,
-				     0x6, 0, Offset, pData, 1);
+				     0x6, 0, Offset, (u8 *)pData, 1);
 
 	return Status;
 }
 
 int RTUSBMultiWrite(struct rt_rtmp_adapter *pAd,
-			 u16 Offset, u8 *pData, u16 length)
+		    u16 Offset, const u8 *pData, u16 length)
 {
 	int Status;
 
 	u16 index = 0, Value;
-	u8 *pSrc = pData;
+	const u8 *pSrc = pData;
 	u16 resude = 0;
 
 	resude = length % 2;
diff --git a/drivers/staging/rt3070/firmware.h b/drivers/staging/rt3070/firmware.h
deleted file mode 100644
index 5cf9cbc..0000000
--- a/drivers/staging/rt3070/firmware.h
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- Copyright (c) 2007, Ralink Technology Corporation
- All rights reserved.
-
- Redistribution.  Redistribution and use in binary form, without
- modification, are permitted provided that the following conditions are
- met:
-
- 	* Redistributions must reproduce the above copyright notice and the
- 	following disclaimer in the documentation and/or other materials
- 	provided with the distribution.
- 	* Neither the name of Ralink Technology Corporation nor the names of its
- 	suppliers may be used to endorse or promote products derived from this
- 	software without specific prior written permission.
- 	* No reverse engineering, decompilation, or disassembly of this software
- 	is permitted.
-
- Limited patent license. Ralink Technology Corporation grants a world-wide,
- royalty-free, non-exclusive license under patents it now or hereafter
- owns or controls to make, have made, use, import, offer to sell and
- sell ("Utilize") this software, but solely to the extent that any
- such patent is necessary to Utilize the software alone, or in
- combination with an operating system licensed under an approved Open
- Source license as listed by the Open Source Initiative at
- http://opensource.org/licenses.  The patent license shall not apply to
- any other combinations which include this software.  No hardware per
- se is licensed hereunder.
-
- DISCLAIMER.  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- DAMAGE.
-*/
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-
-
-u8 FirmwareImage_2870 [] = {
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x12, 0x67, 0x02,
-0x12, 0x68, 0x02, 0x12, 0x87, 0x02, 0x12, 0x8c, 0x12, 0x12, 0x88, 0x22, 0x02, 0x16, 0x49, 0x02,
-0x17, 0x1f, 0x02, 0x13, 0x77, 0x02, 0x12, 0x8d, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x17,
-0xc1, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40,
-0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4,
-0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4,
-0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01,
-0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xc8, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02,
-0x12, 0x66, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0x9d, 0x10,
-0xb7, 0x31, 0x10, 0xe0, 0x50, 0x11, 0x04, 0x51, 0x11, 0x0d, 0x52, 0x11, 0x0d, 0x53, 0x11, 0x0d,
-0x54, 0x11, 0x4e, 0x55, 0x11, 0x7e, 0x70, 0x11, 0xa9, 0x71, 0x11, 0xd7, 0x72, 0x12, 0x1d, 0x73,
-0x12, 0x3e, 0x80, 0x00, 0x00, 0x12, 0x66, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf,
-0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
-0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22,
-0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x12, 0x66, 0x90, 0x70, 0x11,
-0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, 0x03, 0x02, 0x12, 0x66, 0x75, 0x4e, 0x03,
-0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x47, 0x22, 0x90, 0x04, 0x04,
-0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x74, 0x47, 0x25, 0x57,
-0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef,
-0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90,
-0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0xe5, 0x47,
-0x64, 0x07, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0x90,
-0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03,
-0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0xd2, 0x04, 0x22, 0x90, 0x70,
-0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56,
-0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56,
-0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70,
-0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b,
-0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70,
-0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x10, 0x02, 0xe0, 0xb4, 0x70, 0x1e, 0xa3, 0xe0,
-0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54,
-0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5,
-0x4f, 0x75, 0x3a, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80,
-0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10,
-0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74,
-0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70,
-0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90,
-0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2,
-0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, 0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f,
-0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, 0xc2, 0x42, 0xd3, 0x22, 0x22, 0xc2, 0x4b, 0xc2,
-0x4c, 0xe5, 0x44, 0x12, 0x0a, 0x9d, 0x12, 0xaf, 0x00, 0x13, 0x42, 0x04, 0x13, 0x3e, 0x08, 0x13,
-0x19, 0x10, 0x12, 0xc3, 0x20, 0x12, 0xe3, 0x60, 0x12, 0xf4, 0xa0, 0x00, 0x00, 0x13, 0x44, 0x85,
-0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x13,
-0x44, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5,
-0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x66, 0x53, 0x43,
-0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06,
-0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f,
-0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x35, 0xe5,
-0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04, 0x06, 0x53, 0x5e,
-0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5,
-0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b,
-0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54,
-0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3, 0xe5, 0x4a, 0xf0,
-0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3, 0xe5, 0x42, 0xf0,
-0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0, 0x70, 0x03, 0x12,
-0x16, 0x29, 0x12, 0x13, 0x8c, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x90, 0x04,
-0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f, 0x24, 0xff,
-0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, 0x1e, 0xf0, 0xe5,
-0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, 0x5f, 0x20, 0xe5,
-0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, 0x25, 0x70, 0x05,
-0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5, 0x5f, 0x30,
-0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47, 0x64, 0x03,
-0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25, 0x70, 0x03, 0x30,
-0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02, 0x15, 0x25, 0xd2,
-0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5, 0x3a, 0x64,
-0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5,
-0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5,
-0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c,
-0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26,
-0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01,
-0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02,
-0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80,
-0x26, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f,
-0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80,
-0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c,
-0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04,
-0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01,
-0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0,
-0x90, 0x10, 0x2f, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, 0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92,
-0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13, 0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2,
-0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4c, 0x90, 0x02, 0x29,
-0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe, 0x60, 0x23,
-0x24, 0x03, 0x60, 0x03, 0x02, 0x16, 0x18, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0f, 0x80, 0x07,
-0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x06, 0x54, 0xfe, 0xf0, 0x02, 0x16, 0x18, 0x44, 0x01, 0xf0,
-0x02, 0x16, 0x18, 0xe5, 0x46, 0x30, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02,
-0x28, 0xe0, 0x54, 0xfe, 0x4f, 0xf0, 0x02, 0x16, 0x18, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5,
-0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, 0x16, 0x18, 0xe4, 0xf5,
-0x27, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x2e,
-0x14, 0x60, 0x36, 0x24, 0xfc, 0x60, 0x5f, 0x24, 0xf9, 0x60, 0x1f, 0x24, 0x0e, 0x70, 0x69, 0xe5,
-0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01,
-0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff, 0x80, 0x45, 0xa2, 0x47, 0x80, 0x41, 0xe5, 0x46,
-0x30, 0xe2, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38,
-0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20,
-0x47, 0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2,
-0x47, 0xb3, 0x92, 0x39, 0x80, 0x19, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90,
-0x02, 0x28, 0xe0, 0x54, 0xfc, 0x45, 0x27, 0xf0, 0x90, 0x70, 0x9c, 0xe5, 0x3a, 0xf0, 0xa3, 0xe5,
-0x47, 0xf0, 0x90, 0x70, 0x41, 0xe5, 0x3a, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47,
-0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f,
-0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x62, 0xc2, 0xaf, 0xe5, 0x51,
-0x14, 0x60, 0x46, 0x14, 0x60, 0x62, 0x24, 0x02, 0x60, 0x03, 0x02, 0x17, 0x03, 0xd2, 0x59, 0x75,
-0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0, 0x20, 0xe7, 0x22, 0x90, 0x04,
-0x34, 0xe0, 0xb4, 0x02, 0x1b, 0xa3, 0xe0, 0xb4, 0x02, 0x16, 0xa3, 0xe0, 0xb4, 0x02, 0x11, 0x7f,
-0x20, 0x12, 0x16, 0x3f, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x80, 0x73,
-0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, 0x03, 0x80, 0x6a, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70,
-0x11, 0x7f, 0x20, 0x12, 0x16, 0x3f, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02,
-0x80, 0x51, 0xe5, 0x50, 0x70, 0x02, 0x80, 0x46, 0x90, 0x02, 0xa3, 0xe0, 0x20, 0xe6, 0x3b, 0x90,
-0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x33, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96,
-0xf0, 0x90, 0x12, 0x04, 0x74, 0x0a, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0,
-0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54, 0xf9, 0xf0, 0x75,
-0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x62,
-0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xad, 0x62,
-0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2,
-0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d,
-0x02, 0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70, 0x4c, 0x75, 0x52,
-0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44,
-0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74,
-0x03, 0xf0, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x0c, 0xf0,
-0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, 0x12, 0x17,
-0x8d, 0x80, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60,
-0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff,
-0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e,
-0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22,
-0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10,
-0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10,
-0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90,
-0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90,
-0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01,
-0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x94, 0x3f,
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x12, 0x67, 0x02,
-0x12, 0x68, 0x02, 0x12, 0x87, 0x02, 0x12, 0x8c, 0x12, 0x12, 0x88, 0x22, 0x02, 0x16, 0x49, 0x02,
-0x17, 0x1f, 0x02, 0x13, 0x77, 0x02, 0x12, 0x8d, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x17,
-0xc1, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40,
-0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4,
-0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4,
-0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01,
-0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xdd, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02,
-0x12, 0x66, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0xb6, 0x10,
-0xb7, 0x31, 0x10, 0xe0, 0x50, 0x11, 0x04, 0x51, 0x11, 0x0d, 0x52, 0x11, 0x0d, 0x53, 0x11, 0x0d,
-0x54, 0x11, 0x4e, 0x55, 0x11, 0x7e, 0x70, 0x11, 0xa9, 0x71, 0x11, 0xd7, 0x72, 0x12, 0x1d, 0x73,
-0x12, 0x3e, 0x80, 0x00, 0x00, 0x12, 0x66, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf,
-0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
-0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22,
-0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x12, 0x66, 0x90, 0x70, 0x11,
-0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, 0x03, 0x02, 0x12, 0x66, 0x75, 0x4e, 0x03,
-0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x47, 0x22, 0x90, 0x04, 0x04,
-0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x74, 0x47, 0x25, 0x57,
-0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef,
-0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90,
-0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0xe5, 0x47,
-0x64, 0x07, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0x90,
-0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03,
-0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0xd2, 0x04, 0x22, 0x90, 0x70,
-0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56,
-0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56,
-0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70,
-0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b,
-0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70,
-0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x10, 0x02, 0xe0, 0xb4, 0x70, 0x1e, 0xa3, 0xe0,
-0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54,
-0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5,
-0x4f, 0x75, 0x3a, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80,
-0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10,
-0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74,
-0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70,
-0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90,
-0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2,
-0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, 0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f,
-0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, 0xc2, 0x42, 0xd3, 0x22, 0x22, 0xc2, 0x4b, 0xc2,
-0x4c, 0xe5, 0x44, 0x12, 0x0a, 0xb6, 0x12, 0xaf, 0x00, 0x13, 0x42, 0x04, 0x13, 0x3e, 0x08, 0x13,
-0x19, 0x10, 0x12, 0xc3, 0x20, 0x12, 0xe3, 0x60, 0x12, 0xf4, 0xa0, 0x00, 0x00, 0x13, 0x44, 0x85,
-0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x13,
-0x44, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5,
-0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x66, 0x53, 0x43,
-0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06,
-0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f,
-0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x35, 0xe5,
-0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04, 0x06, 0x53, 0x5e,
-0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5,
-0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b,
-0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54,
-0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3, 0xe5, 0x4a, 0xf0,
-0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3, 0xe5, 0x42, 0xf0,
-0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0, 0x70, 0x03, 0x12,
-0x16, 0x29, 0x12, 0x13, 0x8c, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x90, 0x04,
-0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f, 0x24, 0xff,
-0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, 0x1e, 0xf0, 0xe5,
-0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, 0x5f, 0x20, 0xe5,
-0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, 0x25, 0x70, 0x05,
-0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5, 0x5f, 0x30,
-0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47, 0x64, 0x03,
-0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25, 0x70, 0x03, 0x30,
-0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02, 0x15, 0x25, 0xd2,
-0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5, 0x3a, 0x64,
-0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5,
-0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5,
-0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c,
-0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26,
-0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01,
-0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02,
-0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80,
-0x26, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f,
-0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80,
-0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c,
-0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04,
-0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01,
-0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0,
-0x90, 0x10, 0x2f, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, 0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92,
-0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13, 0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2,
-0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4c, 0x90, 0x02, 0x29,
-0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe, 0x60, 0x23,
-0x24, 0x03, 0x60, 0x03, 0x02, 0x16, 0x18, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0f, 0x80, 0x07,
-0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x06, 0x54, 0xfe, 0xf0, 0x02, 0x16, 0x18, 0x44, 0x01, 0xf0,
-0x02, 0x16, 0x18, 0xe5, 0x46, 0x30, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02,
-0x28, 0xe0, 0x54, 0xfe, 0x4f, 0xf0, 0x02, 0x16, 0x18, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5,
-0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, 0x16, 0x18, 0xe4, 0xf5,
-0x27, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x2e,
-0x14, 0x60, 0x36, 0x24, 0xfc, 0x60, 0x5f, 0x24, 0xf9, 0x60, 0x1f, 0x24, 0x0e, 0x70, 0x69, 0xe5,
-0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01,
-0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff, 0x80, 0x45, 0xa2, 0x47, 0x80, 0x41, 0xe5, 0x46,
-0x30, 0xe2, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38,
-0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20,
-0x47, 0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2,
-0x47, 0xb3, 0x92, 0x39, 0x80, 0x19, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90,
-0x02, 0x28, 0xe0, 0x54, 0xfc, 0x45, 0x27, 0xf0, 0x90, 0x70, 0x9c, 0xe5, 0x3a, 0xf0, 0xa3, 0xe5,
-0x47, 0xf0, 0x90, 0x70, 0x41, 0xe5, 0x3a, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47,
-0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f,
-0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x62, 0xc2, 0xaf, 0xe5, 0x51,
-0x14, 0x60, 0x46, 0x14, 0x60, 0x62, 0x24, 0x02, 0x60, 0x03, 0x02, 0x17, 0x03, 0xd2, 0x59, 0x75,
-0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0, 0x20, 0xe7, 0x22, 0x90, 0x04,
-0x34, 0xe0, 0xb4, 0x02, 0x1b, 0xa3, 0xe0, 0xb4, 0x02, 0x16, 0xa3, 0xe0, 0xb4, 0x02, 0x11, 0x7f,
-0x20, 0x12, 0x16, 0x3f, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x80, 0x73,
-0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, 0x03, 0x80, 0x6a, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70,
-0x11, 0x7f, 0x20, 0x12, 0x16, 0x3f, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02,
-0x80, 0x51, 0xe5, 0x50, 0x70, 0x02, 0x80, 0x46, 0x90, 0x02, 0xa3, 0xe0, 0x20, 0xe6, 0x3b, 0x90,
-0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x33, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96,
-0xf0, 0x90, 0x12, 0x04, 0x74, 0x0a, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0,
-0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54, 0xf9, 0xf0, 0x75,
-0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x62,
-0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xad, 0x62,
-0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2,
-0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d,
-0x02, 0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70, 0x4c, 0x75, 0x52,
-0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44,
-0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74,
-0x03, 0xf0, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x0c, 0xf0,
-0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, 0x12, 0x17,
-0x8d, 0x80, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60,
-0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff,
-0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e,
-0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22,
-0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10,
-0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10,
-0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90,
-0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90,
-0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01,
-0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x9b, 0xc0, } ;
diff --git a/drivers/staging/rt3070/md4.h b/drivers/staging/rt3070/md4.h
index a9cc7b0..b3fb637 100644
--- a/drivers/staging/rt3070/md4.h
+++ b/drivers/staging/rt3070/md4.h
@@ -35,8 +35,8 @@
 	u8	buffer[64];      /* input buffer */
 }	MD4_CTX;
 
-void MD4Init (MD4_CTX *);
-void MD4Update (MD4_CTX *, u8 *, UINT);
-void MD4Final (u8 [16], MD4_CTX *);
+void MD4Init(MD4_CTX *);
+void MD4Update(MD4_CTX *, u8 *, UINT);
+void MD4Final(u8 [16], MD4_CTX *);
 
-#endif //__MD4_H__
\ No newline at end of file
+#endif /*__MD4_H__*/
diff --git a/drivers/staging/rt3090/firmware.h b/drivers/staging/rt3090/firmware.h
deleted file mode 100644
index 17056e2..0000000
--- a/drivers/staging/rt3090/firmware.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-
-
-u8 FirmwareImage_3090 [] = {
-0x02, 0x02, 0xf3, 0x02, 0x02, 0xa1, 0x22, 0x22, 0xff, 0xff, 0xff, 0x02, 0x01, 0x27, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x02, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0xd8, 0xc0, 0xe0,
-0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0xc2, 0xaf, 0x30, 0x45, 0x03,
-0x12, 0x10, 0x09, 0x90, 0x04, 0x16, 0xe0, 0x30, 0xe3, 0x03, 0x74, 0x08, 0xf0, 0x90, 0x04, 0x14,
-0xe0, 0x20, 0xe7, 0x03, 0x02, 0x00, 0xcb, 0x74, 0x80, 0xf0, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x36,
-0x90, 0x04, 0x04, 0xe0, 0x24, 0xcf, 0x60, 0x30, 0x14, 0x60, 0x42, 0x24, 0xe2, 0x60, 0x47, 0x14,
-0x60, 0x55, 0x24, 0x21, 0x70, 0x60, 0xe5, 0x55, 0x24, 0xfe, 0x60, 0x07, 0x14, 0x60, 0x08, 0x24,
-0x02, 0x70, 0x08, 0x7d, 0x01, 0x80, 0x28, 0x7d, 0x02, 0x80, 0x24, 0x90, 0x70, 0x10, 0xe0, 0xf5,
-0x50, 0x85, 0x36, 0x40, 0xd2, 0x01, 0x80, 0x3e, 0xe5, 0x55, 0x64, 0x03, 0x60, 0x04, 0xe5, 0x55,
-0x70, 0x04, 0x7d, 0x02, 0x80, 0x09, 0x85, 0x36, 0x41, 0xd2, 0x02, 0x80, 0x29, 0xad, 0x55, 0xaf,
-0x36, 0x12, 0x02, 0x7d, 0x80, 0x20, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x47, 0x90, 0x70, 0x11, 0xe0,
-0xf5, 0x44, 0x12, 0x10, 0x25, 0x80, 0x06, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x45, 0xe4, 0xfd, 0xaf,
-0x36, 0x12, 0x02, 0x7d, 0xd2, 0x04, 0x90, 0x70, 0x13, 0xe4, 0xf0, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0,
-0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82,
-0xc0, 0xd0, 0xe8, 0xc0, 0xe0, 0xe9, 0xc0, 0xe0, 0xea, 0xc0, 0xe0, 0xeb, 0xc0, 0xe0, 0xec, 0xc0,
-0xe0, 0xed, 0xc0, 0xe0, 0xee, 0xc0, 0xe0, 0xef, 0xc0, 0xe0, 0xc2, 0xaf, 0x30, 0x45, 0x03, 0x12,
-0x10, 0x12, 0xd2, 0xaf, 0xd0, 0xe0, 0xff, 0xd0, 0xe0, 0xfe, 0xd0, 0xe0, 0xfd, 0xd0, 0xe0, 0xfc,
-0xd0, 0xe0, 0xfb, 0xd0, 0xe0, 0xfa, 0xd0, 0xe0, 0xf9, 0xd0, 0xe0, 0xf8, 0xd0, 0xd0, 0xd0, 0x82,
-0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0,
-0xd0, 0x75, 0xd0, 0x10, 0xc2, 0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x0c, 0x30, 0x58, 0x0a, 0xe5,
-0x54, 0x60, 0x04, 0x15, 0x54, 0x80, 0x02, 0xc2, 0x58, 0x30, 0x59, 0x0a, 0xe5, 0x50, 0x60, 0x04,
-0x15, 0x50, 0x80, 0x02, 0xc2, 0x59, 0xd5, 0x53, 0x07, 0x30, 0x60, 0x04, 0x15, 0x46, 0xd2, 0x04,
-0x30, 0x45, 0x03, 0x12, 0x10, 0x0f, 0xc2, 0x8d, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83,
-0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x43, 0xc2, 0xaf, 0x90, 0x70,
-0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70,
-0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x37, 0x90, 0x10, 0x1e, 0xe0,
-0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90,
-0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22,
-0x12, 0x02, 0xc3, 0x30, 0x45, 0x03, 0x12, 0x10, 0x03, 0x30, 0x01, 0x06, 0x20, 0x09, 0x03, 0x12,
-0x10, 0x1c, 0x30, 0x02, 0x06, 0x20, 0x0a, 0x03, 0x12, 0x10, 0x1f, 0x30, 0x03, 0x06, 0x20, 0x0b,
-0x03, 0x12, 0x10, 0x1f, 0x30, 0x04, 0x06, 0x20, 0x0c, 0x03, 0x12, 0x10, 0x22, 0x20, 0x13, 0x09,
-0x20, 0x11, 0x06, 0xe5, 0x2b, 0x45, 0x2c, 0x60, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xa9, 0x12,
-0x03, 0x1c, 0x80, 0xbf, 0xc2, 0x43, 0xd2, 0x45, 0xe4, 0xf5, 0x20, 0xf5, 0x21, 0xf5, 0x53, 0xf5,
-0x46, 0xf5, 0x2b, 0xf5, 0x2c, 0xc2, 0x42, 0xf5, 0x51, 0xf5, 0x52, 0xf5, 0x55, 0x90, 0x04, 0x18,
-0x74, 0x80, 0xf0, 0x90, 0x04, 0x1a, 0x74, 0x08, 0xf0, 0xc2, 0x1a, 0xc2, 0x18, 0xc2, 0x1b, 0x22,
-0xc8, 0xef, 0xc8, 0xe6, 0xfa, 0x08, 0xe6, 0x4a, 0x60, 0x0c, 0xc8, 0xef, 0xc8, 0x08, 0xe6, 0x16,
-0x18, 0x70, 0x01, 0x16, 0xc3, 0x22, 0xed, 0x24, 0xff, 0xfd, 0xec, 0x34, 0xff, 0xc8, 0xef, 0xc8,
-0xf6, 0x08, 0xc6, 0xed, 0xc6, 0xd3, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12,
-0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83,
-0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0xef, 0xf4, 0x60,
-0x1f, 0xe4, 0xfe, 0x12, 0x03, 0x5b, 0xe0, 0xb4, 0xff, 0x12, 0x12, 0x03, 0x5b, 0xef, 0xf0, 0x74,
-0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xe3,
-0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0xc2, 0xaf,
-0x30, 0x45, 0x03, 0x12, 0x10, 0x06, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0,
-0xd0, 0xe0, 0x32, 0xc2, 0xaf, 0x12, 0x00, 0x06, 0x12, 0x02, 0x04, 0x12, 0x02, 0xdc, 0xe4, 0xf5,
-0x22, 0xf5, 0x47, 0x90, 0x04, 0x00, 0x74, 0x80, 0xf0, 0xd2, 0xaf, 0x22, 0x75, 0x89, 0x02, 0xe4,
-0xf5, 0x8c, 0xf5, 0x8a, 0xf5, 0x88, 0xf5, 0xb8, 0xf5, 0xe8, 0x75, 0x90, 0x18, 0xd2, 0x8c, 0x75,
-0xa8, 0x05, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x5f, 0x02, 0x01, 0xc0, 0xff,
-0xc0, 0x26, 0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x26, 0x0a, 0x22, 0xc0, 0x26,
-0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x26, 0x18, 0x22, 0x30, 0x45, 0x03, 0x12,
-0x10, 0x15, 0xe5, 0x20, 0x70, 0x03, 0x20, 0x10, 0x03, 0x30, 0x11, 0x03, 0x43, 0x87, 0x01, 0x22,
-0xce, 0xef, 0xce, 0xee, 0x60, 0x08, 0x7f, 0xff, 0x12, 0x03, 0x71, 0x1e, 0x80, 0xf5, 0x22, 0xc8,
-0xef, 0xc8, 0xe6, 0x60, 0x03, 0x16, 0xc3, 0x22, 0xed, 0x14, 0xf6, 0xd3, 0x22, 0xc8, 0xef, 0xc8,
-0xe6, 0x60, 0x06, 0x16, 0xe6, 0x24, 0xff, 0xb3, 0x22, 0xc3, 0x22, 0x74, 0x14, 0x2e, 0xf5, 0x82,
-0xe4, 0x34, 0x70, 0xf5, 0x83, 0x22, 0xef, 0x90, 0x03, 0x6f, 0x93, 0x90, 0x03, 0x00, 0x73, 0x0a,
-0x18, 0xef, 0x60, 0x03, 0x1f, 0x80, 0xfa, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x3b, 0x02, 0x10, 0x3c, 0x02, 0x13, 0x68, 0x02,
-0x13, 0x69, 0x02, 0x14, 0x1e, 0x02, 0x14, 0x1f, 0xc3, 0x22, 0xff, 0xff, 0x02, 0x19, 0xa1, 0x02,
-0x1b, 0x31, 0x02, 0x14, 0xea, 0x02, 0x14, 0x20, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x01,
-0x75, 0x30, 0x06, 0x06, 0x20, 0x0e, 0x03, 0x12, 0x1c, 0x4f, 0x22, 0x22, 0x90, 0x04, 0x14, 0xe0,
-0x20, 0xe7, 0x03, 0x02, 0x13, 0x67, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0,
-0x12, 0x02, 0x57, 0x11, 0x11, 0x30, 0x10, 0xe2, 0x31, 0x10, 0x90, 0x33, 0x10, 0xa0, 0x34, 0x10,
-0xbe, 0x35, 0x10, 0xac, 0x36, 0x11, 0x1f, 0x50, 0x11, 0x68, 0x51, 0x11, 0x71, 0x52, 0x11, 0x71,
-0x53, 0x11, 0x71, 0x54, 0x11, 0xb3, 0x55, 0x12, 0x16, 0x70, 0x12, 0x42, 0x71, 0x12, 0x71, 0x72,
-0x12, 0xda, 0x73, 0x12, 0xfe, 0x80, 0x13, 0x29, 0x83, 0x13, 0x47, 0x84, 0x00, 0x00, 0x13, 0x67,
-0xd2, 0x18, 0xd2, 0x61, 0x75, 0x35, 0x2a, 0x75, 0x32, 0x0b, 0x75, 0x33, 0xb8, 0x02, 0x13, 0x62,
-0xc2, 0x18, 0x90, 0x01, 0x14, 0xe0, 0x54, 0xfd, 0xf0, 0x02, 0x13, 0x62, 0x90, 0x70, 0x11, 0xe0,
-0xf5, 0x3c, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x22, 0xe5, 0x55,
-0xb4, 0x02, 0x0f, 0xe5, 0x59, 0xb4, 0x28, 0x06, 0x90, 0x01, 0x0d, 0x74, 0x08, 0xf0, 0x7d, 0x01,
-0x80, 0x02, 0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x02,
-0x13, 0x62, 0x20, 0x02, 0x03, 0x30, 0x03, 0x10, 0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0x02, 0x13, 0x62, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x0c, 0x90,
-0x01, 0x0c, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 0xe0, 0x44, 0x04, 0xf0, 0x85, 0x56, 0x41, 0xd2, 0x02,
-0x22, 0x90, 0x70, 0x11, 0xe0, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x67, 0xe0, 0xf5, 0x30, 0x22, 0xe5,
-0x34, 0xc3, 0x94, 0x03, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13, 0x67, 0x90, 0x70, 0x10,
-0xe0, 0x54, 0x7f, 0xff, 0xbf, 0x0a, 0x0d, 0x90, 0x70, 0x11, 0xe0, 0xb4, 0x08, 0x06, 0x75, 0x4e,
-0x01, 0x75, 0x4f, 0x84, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x13,
-0x67, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, 0x03, 0x02, 0x13,
-0x67, 0x75, 0x4e, 0x03, 0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x47,
-0x22, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13, 0x09, 0x90,
-0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x74, 0x47,
-0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, 0x57, 0xf8,
-0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0,
-0x02, 0x13, 0x62, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13,
-0x09, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x23, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x1d, 0xe5, 0x47, 0x64,
-0x09, 0x60, 0x17, 0xe5, 0x47, 0x64, 0x0a, 0x60, 0x11, 0xe5, 0x47, 0x64, 0x0b, 0x60, 0x0b, 0xe5,
-0x47, 0x64, 0x0d, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x0d, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f,
-0xf5, 0x3a, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03, 0x03, 0xe4, 0xf5, 0x46, 0xe5,
-0x47, 0xb4, 0x0a, 0x08, 0xe5, 0x3a, 0xb4, 0x01, 0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56,
-0x12, 0x02, 0x7d, 0xd2, 0x04, 0x22, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x07, 0xe5, 0x55, 0x60,
-0x03, 0x02, 0x13, 0x09, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8,
-0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x02,
-0x13, 0x62, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13, 0x09,
-0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0,
-0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x02, 0x13,
-0x62, 0x90, 0x10, 0x00, 0xe0, 0xf5, 0x57, 0x90, 0x10, 0x02, 0xe0, 0xf5, 0x58, 0xa3, 0xe0, 0xf5,
-0x59, 0xe5, 0x58, 0xb4, 0x70, 0x1e, 0xe5, 0x59, 0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44,
-0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe,
-0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x3a, 0xff, 0xc2, 0x1a, 0xc2, 0x18,
-0xc2, 0x1b, 0xf5, 0x34, 0x90, 0x05, 0xa4, 0x74, 0x11, 0xf0, 0xa3, 0x74, 0xff, 0xf0, 0xa3, 0x74,
-0x03, 0xf0, 0xe4, 0xf5, 0x30, 0xc2, 0x19, 0x75, 0x3c, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02,
-0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x02, 0x13, 0x62, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40,
-0x06, 0xe5, 0x55, 0x60, 0x02, 0x80, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4,
-0xfd, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x80, 0x64, 0xe5, 0x34,
-0xc3, 0x94, 0x03, 0x40, 0x0b, 0xe5, 0x55, 0x60, 0x07, 0x7d, 0x03, 0xaf, 0x56, 0x02, 0x02, 0x7d,
-0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02,
-0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x80, 0x39, 0xe4, 0xf5, 0x34, 0xf5, 0x30, 0x90, 0x70,
-0x10, 0xe0, 0xf4, 0x60, 0x03, 0xe0, 0xf5, 0x34, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0x80, 0x1b, 0xd2, 0x19, 0x05, 0x2f, 0xe5, 0x2f, 0xb4, 0x1a, 0x03,
-0xe4, 0xf5, 0x2f, 0xd2, 0x04, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74,
-0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0x22, 0x22, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x17,
-0xe5, 0x55, 0xb4, 0x02, 0x12, 0xe5, 0x30, 0x60, 0x0e, 0x30, 0x60, 0x0b, 0x74, 0xfd, 0x25, 0x46,
-0xf5, 0x46, 0xd2, 0x04, 0xe4, 0xf5, 0x53, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x14, 0x1d, 0x30, 0x60,
-0x21, 0xb2, 0x4d, 0x30, 0x4d, 0x1c, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x11, 0xe5, 0x55, 0xb4,
-0x02, 0x0c, 0xe5, 0x30, 0x60, 0x08, 0x74, 0x03, 0x25, 0x46, 0xf5, 0x46, 0x80, 0x02, 0x05, 0x46,
-0xc2, 0x04, 0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e,
-0x30, 0x1a, 0x49, 0x7f, 0x32, 0x7d, 0xb8, 0x7c, 0x0b, 0x12, 0x02, 0x30, 0x50, 0x06, 0x90, 0x04,
-0x10, 0x74, 0x40, 0xf0, 0x7f, 0x35, 0x7d, 0x32, 0x12, 0x03, 0x3f, 0x50, 0x09, 0x90, 0x10, 0x04,
-0xe0, 0x54, 0xf7, 0xf0, 0xd2, 0x06, 0xe5, 0x35, 0xd3, 0x94, 0x2d, 0x40, 0x30, 0x30, 0x1b, 0x2d,
-0xc2, 0x1b, 0xa2, 0x18, 0x92, 0x1a, 0x20, 0x1a, 0x24, 0x90, 0x04, 0x09, 0xe0, 0x54, 0xdd, 0xf0,
-0x90, 0x10, 0x04, 0xe0, 0x44, 0x08, 0xf0, 0xc2, 0x61, 0xd2, 0x03, 0x22, 0xe4, 0xf5, 0x35, 0xa2,
-0x18, 0x92, 0x1a, 0x30, 0x1a, 0x07, 0x90, 0x04, 0x09, 0xe0, 0x44, 0x22, 0xf0, 0x22, 0x22, 0x22,
-0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x02, 0x57, 0x14, 0x42, 0x00, 0x14, 0xd5, 0x04, 0x14,
-0xd1, 0x08, 0x14, 0xac, 0x10, 0x14, 0x56, 0x20, 0x14, 0x76, 0x60, 0x14, 0x87, 0xa0, 0x00, 0x00,
-0x14, 0xd7, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60,
-0x03, 0x02, 0x14, 0xd7, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4,
-0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70,
-0x66, 0x53, 0x43, 0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5,
-0x47, 0x64, 0x06, 0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b,
-0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06,
-0x70, 0x35, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04,
-0x06, 0x53, 0x5e, 0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75,
-0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80,
-0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x2a, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff,
-0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x1a, 0x24, 0xc0,
-0x60, 0x0a, 0x24, 0x35, 0x70, 0x09, 0x12, 0x19, 0x5f, 0x12, 0x15, 0x09, 0x12, 0x19, 0x5f, 0x12,
-0x15, 0x09, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54,
-0x0e, 0x60, 0x04, 0xd2, 0x1c, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f, 0x24, 0xff, 0x92, 0x1c, 0xd2,
-0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x1d, 0x74, 0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f,
-0xf5, 0x2d, 0xe5, 0x2a, 0x70, 0x13, 0x30, 0x1c, 0x05, 0xe5, 0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x1d,
-0x29, 0xe5, 0x5f, 0x54, 0x30, 0x64, 0x30, 0x70, 0x21, 0xe5, 0x2a, 0x70, 0x15, 0xe5, 0x34, 0xc3,
-0x94, 0x03, 0x40, 0x09, 0xe5, 0x30, 0x60, 0x05, 0x75, 0x2a, 0x05, 0x80, 0x07, 0x75, 0x2a, 0x0c,
-0x80, 0x02, 0x15, 0x2a, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2,
-0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47, 0x64, 0x03, 0x70, 0x21, 0x30,
-0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x2a, 0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2,
-0x4c, 0xe5, 0x2a, 0x70, 0x05, 0x75, 0x2a, 0x07, 0x80, 0x02, 0x15, 0x2a, 0xd2, 0x6c, 0xd2, 0x6d,
-0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5, 0x3a, 0x64, 0x02, 0x60, 0x05,
-0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x0a, 0x13, 0xe5, 0x3a,
-0xb4, 0x01, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x08, 0xe5, 0x3a, 0x70, 0x04, 0xd2, 0x6c, 0xc2,
-0x6d, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e,
-0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x75,
-0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x45, 0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2,
-0x80, 0x3c, 0x30, 0x19, 0x1c, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00,
-0xe5, 0x2f, 0xb4, 0x19, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x80,
-0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0,
-0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73,
-0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x45, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2,
-0x80, 0x3c, 0x30, 0x19, 0x1c, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00,
-0xe5, 0x2f, 0xb4, 0x19, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x80,
-0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0,
-0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75,
-0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, 0x64, 0xe5, 0x47, 0x64, 0x0a, 0x70, 0x19, 0xe5,
-0x3a, 0xb4, 0x01, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x53, 0xe5, 0x46, 0x20, 0xe4, 0x03, 0x30,
-0xe5, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x80, 0x45, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80,
-0x3c, 0x30, 0x19, 0x1c, 0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5,
-0x2f, 0xb4, 0x19, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x80, 0x1d,
-0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe,
-0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, 0x92,
-0x70, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, 0x94, 0x30,
-0x40, 0x14, 0xa2, 0x71, 0x92, 0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13, 0x54, 0x3f,
-0xf5, 0x2e, 0xc2, 0x77, 0xd2, 0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06,
-0x70, 0x46, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60,
-0x14, 0x24, 0xfe, 0x60, 0x1f, 0x24, 0x03, 0x60, 0x03, 0x02, 0x19, 0x5e, 0x90, 0x02, 0x28, 0xe0,
-0x30, 0x47, 0x0d, 0x80, 0x07, 0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x04, 0x54, 0xfe, 0xf0, 0x22,
-0x44, 0x01, 0xf0, 0x22, 0xe5, 0x46, 0x30, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90,
-0x02, 0x28, 0xe0, 0x54, 0xfe, 0x4f, 0xf0, 0x22, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5, 0x47,
-0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, 0x18, 0x27, 0xe4, 0xf5, 0x27,
-0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x2e, 0x14,
-0x60, 0x36, 0x24, 0xfc, 0x60, 0x5f, 0x24, 0xf9, 0x60, 0x1f, 0x24, 0x0e, 0x70, 0x69, 0xe5, 0x46,
-0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, 0x80,
-0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff, 0x80, 0x45, 0xa2, 0x47, 0x80, 0x41, 0xe5, 0x46, 0x30,
-0xe2, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3,
-0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, 0x47,
-0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2, 0x47,
-0xb3, 0x92, 0x39, 0x80, 0x19, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39,
-0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90, 0x02,
-0x28, 0xe0, 0x54, 0xfc, 0x02, 0x19, 0x5b, 0xe5, 0x47, 0x64, 0x0c, 0x60, 0x09, 0xe5, 0x47, 0x64,
-0x0b, 0x60, 0x03, 0x02, 0x18, 0xc6, 0xe4, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfd, 0xf0,
-0xe5, 0x3a, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x2e, 0x14, 0x60, 0x38, 0x24, 0xfc, 0x60, 0x5c, 0x24,
-0xf9, 0x60, 0x1d, 0x24, 0x0e, 0x70, 0x61, 0xe5, 0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03,
-0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x80, 0x35,
-0xa2, 0x47, 0x92, 0x39, 0x80, 0x47, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x39, 0x80, 0x3a, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e,
-0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, 0x47, 0x04, 0x7d, 0x01, 0x80, 0x02,
-0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x39, 0x80, 0x12, 0xe5, 0x46, 0x30, 0xe2, 0x03,
-0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0x80, 0x05, 0xa2, 0x47, 0xb3, 0x92, 0x39, 0x90, 0x02, 0x28,
-0xe0, 0x54, 0xfd, 0x02, 0x19, 0x5b, 0xe5, 0x47, 0x64, 0x0d, 0x60, 0x03, 0x02, 0x19, 0x5e, 0xf5,
-0x27, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xef, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x2e,
-0x14, 0x60, 0x38, 0x24, 0xfc, 0x60, 0x5c, 0x24, 0xf9, 0x60, 0x1d, 0x24, 0x0e, 0x70, 0x61, 0xe5,
-0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01,
-0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x80, 0x35, 0xa2, 0x47, 0x92, 0x3c, 0x80, 0x47, 0xe5, 0x46,
-0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x3c, 0x80, 0x3a, 0xe5, 0x46, 0x30, 0xe2, 0x0d,
-0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f,
-0x00, 0x20, 0x47, 0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92,
-0x3c, 0x80, 0x12, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x3c, 0x80, 0x05,
-0xa2, 0x47, 0xb3, 0x92, 0x3c, 0x90, 0x02, 0x28, 0xe0, 0x54, 0xef, 0x45, 0x27, 0xf0, 0x22, 0xe5,
-0x47, 0x64, 0x0b, 0x70, 0x1c, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xeb, 0xf0, 0x30, 0x47, 0x04, 0xaf,
-0x45, 0x80, 0x05, 0xe5, 0x45, 0x64, 0x14, 0xff, 0x90, 0x02, 0x28, 0xe0, 0x54, 0xeb, 0x4f, 0xf0,
-0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4,
-0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58,
-0x22, 0xe4, 0xf5, 0x37, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x4a, 0x14, 0x60, 0x6b, 0x24, 0x02,
-0x60, 0x03, 0x02, 0x1b, 0x12, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x20, 0x1a, 0x1c, 0x90, 0x02, 0x08,
-0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x20, 0xe1, 0x23, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1c, 0xa3,
-0xe0, 0xb4, 0x02, 0x17, 0xa3, 0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, 0x12, 0x19, 0x97, 0x90, 0x10,
-0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x02, 0x1b, 0x12, 0xe5, 0x50, 0x70, 0x06, 0x75,
-0x37, 0x03, 0x02, 0x1b, 0x12, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x15, 0x7f, 0x20, 0x12,
-0x19, 0x97, 0x20, 0x1a, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfb, 0xf0, 0x75, 0x51, 0x02, 0x02,
-0x1b, 0x12, 0xe5, 0x50, 0x70, 0x03, 0x02, 0x1b, 0x0d, 0x20, 0x1a, 0x15, 0x90, 0x02, 0x08, 0xe0,
-0x30, 0xe3, 0x03, 0x02, 0x1b, 0x09, 0x90, 0x04, 0x37, 0xe0, 0x64, 0x22, 0x60, 0x03, 0x02, 0x1b,
-0x09, 0x90, 0x12, 0x04, 0x74, 0x0a, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x15, 0xe5, 0x59, 0xb4, 0x35,
-0x10, 0xe4, 0x90, 0x05, 0x00, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03,
-0xf0, 0x7f, 0x01, 0x12, 0x03, 0x30, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54,
-0xf0, 0xf0, 0xe5, 0x59, 0xb4, 0x35, 0x14, 0xe5, 0x3c, 0xf4, 0x60, 0x06, 0xa3, 0xe0, 0x54, 0xf3,
-0x80, 0x14, 0x90, 0x13, 0x2a, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x14, 0xe5, 0x3c, 0xf4, 0x90, 0x13,
-0x2a, 0x60, 0x08, 0xe0, 0x54, 0xf2, 0x45, 0x3c, 0xf0, 0x80, 0x04, 0xe0, 0x54, 0xfa, 0xf0, 0x20,
-0x1a, 0x07, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x10, 0xf0, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x09,
-0xe5, 0x30, 0x70, 0x05, 0x75, 0x8c, 0x40, 0x80, 0x03, 0x75, 0x8c, 0x80, 0x90, 0x04, 0x01, 0xe0,
-0x54, 0xfd, 0xf0, 0x20, 0x1a, 0x07, 0x90, 0x12, 0x04, 0xe0, 0x44, 0x04, 0xf0, 0xe5, 0x59, 0xb4,
-0x28, 0x06, 0x90, 0x01, 0x0d, 0xe0, 0xf5, 0x31, 0xe5, 0x34, 0xc3, 0x94, 0x02, 0x40, 0x14, 0x90,
-0x01, 0x0d, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x59, 0x64, 0x35, 0x60, 0x07, 0x90, 0x12, 0x04, 0xe0,
-0x54, 0xfd, 0xf0, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x14, 0x20, 0x02, 0x11, 0x20, 0x03, 0x0e,
-0x90, 0x01, 0x0d, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0x01, 0x0c, 0xe0, 0x54, 0xfd, 0xf0, 0x75, 0x37,
-0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x37, 0x03,
-0xf5, 0x51, 0xe5, 0x37, 0x60, 0x18, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0x20, 0x1a, 0x0e,
-0xad, 0x37, 0xaf, 0x40, 0x12, 0x1c, 0x1b, 0xe5, 0x37, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf,
-0x22, 0xc2, 0xaf, 0x30, 0x01, 0x0e, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, 0x02, 0xaf,
-0x40, 0x12, 0x1c, 0x1b, 0xe5, 0x52, 0x14, 0x60, 0x5c, 0x14, 0x60, 0x3a, 0x24, 0x02, 0x60, 0x03,
-0x02, 0x1c, 0x18, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x0c, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x02,
-0xf0, 0xa3, 0xe0, 0x44, 0x04, 0xf0, 0xe5, 0x34, 0xc3, 0x94, 0x02, 0x40, 0x13, 0x90, 0x12, 0x04,
-0xe0, 0x44, 0x02, 0xf0, 0x7f, 0x32, 0x12, 0x03, 0x30, 0x90, 0x01, 0x0d, 0xe0, 0x54, 0xfe, 0xf0,
-0x75, 0x52, 0x02, 0x75, 0x55, 0x03, 0xe5, 0x59, 0xb4, 0x28, 0x06, 0x90, 0x01, 0x0d, 0xe5, 0x31,
-0xf0, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfb, 0xf0, 0x7f, 0x20, 0x12, 0x19, 0x9c, 0x75, 0x52, 0x01,
-0x75, 0x55, 0x03, 0x80, 0x73, 0xe5, 0x54, 0x70, 0x6f, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0,
-0x20, 0x1a, 0x04, 0xe0, 0x54, 0xef, 0xf0, 0xe4, 0xf5, 0x8c, 0x90, 0x13, 0x28, 0xe0, 0x44, 0x0f,
-0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x03,
-0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x16, 0xe5, 0x59, 0xb4, 0x35, 0x11, 0x90, 0x05, 0x00, 0x74, 0xe2,
-0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, 0x12, 0x03,
-0x30, 0x20, 0x1a, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44,
-0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x09, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41,
-0x12, 0x1c, 0x1b, 0x30, 0x03, 0x02, 0xc2, 0x03, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4,
-0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74,
-0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82,
-0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, 0x22, 0x30,
-0x1a, 0x77, 0x90, 0x04, 0x37, 0xe0, 0x20, 0xe5, 0x6c, 0x90, 0x04, 0x28, 0xe0, 0xf5, 0x38, 0xa3,
-0xe0, 0xf5, 0x37, 0xf5, 0x39, 0xe4, 0xf5, 0x25, 0xe5, 0x39, 0x75, 0xf0, 0x80, 0xa4, 0x24, 0x00,
-0xff, 0xe5, 0xf0, 0x34, 0x80, 0xfe, 0xe5, 0x37, 0x65, 0x39, 0x70, 0x05, 0xfc, 0x7d, 0x28, 0x80,
-0x04, 0x7c, 0x00, 0x7d, 0x00, 0xef, 0x2d, 0xff, 0xee, 0x3c, 0xfe, 0x12, 0x1c, 0xca, 0x50, 0x07,
-0x90, 0x01, 0x14, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x39, 0x65, 0x38, 0x60, 0x10, 0xe4, 0x25, 0x39,
-0xff, 0xe4, 0x34, 0x80, 0x8f, 0x82, 0xf5, 0x83, 0xe0, 0xf5, 0x39, 0x80, 0xbb, 0x90, 0x04, 0x10,
-0x74, 0x01, 0xf0, 0x90, 0x04, 0x28, 0xe5, 0x38, 0xf0, 0xa3, 0xe5, 0x37, 0xf0, 0x90, 0x04, 0x11,
-0x74, 0x01, 0xf0, 0x80, 0x8d, 0xc2, 0x06, 0xd2, 0x1b, 0x22, 0xe5, 0x25, 0xc3, 0x94, 0x06, 0x50,
-0x19, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xb4, 0xff, 0x07, 0x05, 0x25, 0xe4, 0xf5, 0x24, 0x80, 0x2e,
-0xe4, 0xf5, 0x25, 0x8f, 0x82, 0x8e, 0x83, 0xf0, 0x80, 0x24, 0xe5, 0x24, 0x75, 0xf0, 0x06, 0x84,
-0x74, 0x08, 0x25, 0xf0, 0xf5, 0x82, 0xe4, 0x34, 0x10, 0xf5, 0x83, 0xe0, 0xfd, 0x8f, 0x82, 0x8e,
-0x83, 0xe0, 0x6d, 0x70, 0x06, 0x05, 0x25, 0x05, 0x24, 0x80, 0x03, 0xe4, 0xf5, 0x25, 0x0f, 0xbf,
-0x00, 0x01, 0x0e, 0xef, 0x54, 0x7f, 0x60, 0x07, 0xe5, 0x25, 0xc3, 0x94, 0x2a, 0x40, 0xab, 0xe5,
-0x25, 0xb4, 0x2a, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xe3, 0x34, } ;
diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig
index e24a6f7..155a78e 100644
--- a/drivers/staging/rtl8187se/Kconfig
+++ b/drivers/staging/rtl8187se/Kconfig
@@ -3,6 +3,7 @@
 	depends on PCI && WLAN
 	select WIRELESS_EXT
 	select WEXT_PRIV
+	select EEPROM_93CX6
 	default N
 	---help---
 	  If built as a module, it will be called r8187se.ko.
diff --git a/drivers/staging/rtl8187se/Makefile b/drivers/staging/rtl8187se/Makefile
index b395acf..e6adf91 100644
--- a/drivers/staging/rtl8187se/Makefile
+++ b/drivers/staging/rtl8187se/Makefile
@@ -18,7 +18,6 @@
 
 r8187se-objs :=			\
 		r8180_core.o		\
-		r8180_93cx6.o		\
 		r8180_wx.o		\
 		r8180_rtl8225z2.o	\
 		r8185b_init.o		\
diff --git a/drivers/staging/rtl8187se/TODO b/drivers/staging/rtl8187se/TODO
index a762e79..704949a 100644
--- a/drivers/staging/rtl8187se/TODO
+++ b/drivers/staging/rtl8187se/TODO
@@ -5,7 +5,6 @@
 - switch to use shared "librtl" instead of private ieee80211 stack
 - switch to use LIB80211
 - switch to use MAC80211
-- switch to use EEPROM_93CX6
 - use kernel coding style
 - checkpatch.pl fixes
 - sparse fixes
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
index 9086047..4cd95c3 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -29,6 +29,7 @@
 #include <linux/jiffies.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
+#include <linux/semaphore.h>
 #include <linux/wireless.h>
 #include <linux/ieee80211.h>
 
@@ -161,10 +162,6 @@
 #define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
 #endif	/* CONFIG_IEEE80211_DEBUG */
 
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], \
-		   ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
-
 /*
  * To use the debug system;
  *
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
index 172e8f3..40f1b99 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
@@ -285,7 +285,7 @@
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "CCMP: received packet without ExtIV"
-			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			       " flag from %pM\n", hdr->addr2);
 		}
 		key->dot11RSNAStatsCCMPFormatErrors++;
 		return -2;
@@ -298,9 +298,9 @@
 	}
 	if (!key->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
+			printk(KERN_DEBUG "CCMP: received packet from %pM"
 			       " with keyid=%d that does not have a configured"
-			       " key\n", MAC_ARG(hdr->addr2), keyidx);
+			       " key\n", hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -315,11 +315,9 @@
 
 	if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
-			       " previous PN %02x%02x%02x%02x%02x%02x "
-			       "received PN %02x%02x%02x%02x%02x%02x\n",
-			       MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
-			       MAC_ARG(pn));
+			printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
+			       " previous PN %pm received PN %pm\n",
+			       hdr->addr2, key->rx_pn, pn);
 		}
 		key->dot11RSNAStatsCCMPReplays++;
 		return -4;
@@ -347,7 +345,7 @@
 	if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "CCMP: decrypt failed: STA="
-			       MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			       "%pM\n", hdr->addr2);
 		}
 		key->dot11RSNAStatsCCMPDecryptErrors++;
 		return -5;
@@ -423,11 +421,10 @@
 {
 	struct ieee80211_ccmp_data *ccmp = priv;
 	p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
-		     "tx_pn=%02x%02x%02x%02x%02x%02x "
-		     "rx_pn=%02x%02x%02x%02x%02x%02x "
+		     "tx_pn=%pm rx_pn=%pm "
 		     "format_errors=%d replays=%d decrypt_errors=%d\n",
 		     ccmp->key_idx, ccmp->key_set,
-		     MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
+		     ccmp->tx_pn, ccmp->rx_pn,
 		     ccmp->dot11RSNAStatsCCMPFormatErrors,
 		     ccmp->dot11RSNAStatsCCMPReplays,
 		     ccmp->dot11RSNAStatsCCMPDecryptErrors);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
index e6d8385..a525411 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
@@ -385,7 +385,7 @@
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "TKIP: received packet without ExtIV"
-			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			       " flag from %pM\n", hdr->addr2);
 		}
 		return -2;
 	}
@@ -397,9 +397,9 @@
 	}
 	if (!tkey->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
+			printk(KERN_DEBUG "TKIP: received packet from %pM"
 			       " with keyid=%d that does not have a configured"
-			       " key\n", MAC_ARG(hdr->addr2), keyidx);
+			       " key\n", hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -410,9 +410,9 @@
 	if (iv32 < tkey->rx_iv32 ||
 	    (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
+			printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
 			       " previous TSC %08x%04x received TSC "
-			       "%08x%04x\n", MAC_ARG(hdr->addr2),
+			       "%08x%04x\n", hdr->addr2,
 			       tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
 		}
 		tkey->dot11RSNAStatsTKIPReplays++;
@@ -431,8 +431,8 @@
 	if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG ": TKIP: failed to decrypt "
-			       "received packet from " MAC_FMT "\n",
-			       MAC_ARG(hdr->addr2));
+			       "received packet from %pM\n",
+			       hdr->addr2);
 		}
 		return -7;
 	}
@@ -450,7 +450,7 @@
 		}
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "TKIP: ICV error detected: STA="
-			       MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			       "%pM\n", hdr->addr2);
 		}
 		tkey->dot11RSNAStatsTKIPICVErrors++;
 		return -5;
@@ -604,8 +604,8 @@
 		struct ieee80211_hdr_4addr *hdr;
 		hdr = (struct ieee80211_hdr_4addr *)skb->data;
 		printk(KERN_DEBUG "%s: Michael MIC verification failed for "
-		       "MSDU from " MAC_FMT " keyidx=%d\n",
-		       skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
+		       "MSDU from %pM keyidx=%d\n",
+		       skb->dev ? skb->dev->name : "N/A", hdr->addr2,
 		       keyidx);
 		if (skb->dev)
 			ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
index 9128c18..2b7080c 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
@@ -311,8 +311,8 @@
 	    strcmp(crypt->ops->name, "TKIP") == 0) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "received packet from " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(hdr->addr2));
+			       "received packet from %pM\n",
+			       ieee->dev->name, hdr->addr2);
 		}
 		return -1;
 	}
@@ -323,8 +323,8 @@
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
 		IEEE80211_DEBUG_DROP(
-			"decryption failed (SA=" MAC_FMT
-			") res=%d\n", MAC_ARG(hdr->addr2), res);
+			"decryption failed (SA=%pM"
+			") res=%d\n", hdr->addr2, res);
 		if (res == -2)
 			IEEE80211_DEBUG_DROP("Decryption failed ICV "
 					     "mismatch (key %d)\n",
@@ -356,8 +356,8 @@
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
-		       " (SA=" MAC_FMT " keyidx=%d)\n",
-		       ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
+		       " (SA=%pM keyidx=%d)\n",
+		       ieee->dev->name, hdr->addr2, keyidx);
 		return -1;
 	}
 
@@ -550,8 +550,8 @@
 			 * frames silently instead of filling system log with
 			 * these reports. */
 			IEEE80211_DEBUG_DROP("Decryption failed (not set)"
-					     " (SA=" MAC_FMT ")\n",
-					     MAC_ARG(hdr->addr2));
+					     " (SA=%pM)\n",
+					     hdr->addr2);
 			ieee->ieee_stats.rx_discards_undecryptable++;
 			goto rx_dropped;
 		}
@@ -709,8 +709,8 @@
 		} else {
 			IEEE80211_DEBUG_DROP(
 				"encryption configured, but RX "
-				"frame not encrypted (SA=" MAC_FMT ")\n",
-				MAC_ARG(hdr->addr2));
+				"frame not encrypted (SA=%pM)\n",
+				hdr->addr2);
 			goto rx_dropped;
 		}
 	}
@@ -729,9 +729,9 @@
 	    !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
 		IEEE80211_DEBUG_DROP(
 			"dropped unencrypted RX data "
-			"frame from " MAC_FMT
+			"frame from %pM"
 			" (drop_unencrypted=1)\n",
-			MAC_ARG(hdr->addr2));
+			hdr->addr2);
 		goto rx_dropped;
 	}
 /*
@@ -1196,11 +1196,11 @@
 	}
 
 	if (network->mode == 0) {
-		IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
+		IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
 				     "network.\n",
 				     escape_essid(network->ssid,
 						  network->ssid_len),
-				     MAC_ARG(network->bssid));
+				     network->bssid);
 		return 1;
 	}
 
@@ -1341,9 +1341,9 @@
 	memset(&network, 0, sizeof(struct ieee80211_network));
 
 	IEEE80211_DEBUG_SCAN(
-		"'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+		"'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
 		escape_essid(info_element->data, info_element->len),
-		MAC_ARG(beacon->header.addr3),
+		beacon->header.addr3,
 		(beacon->capability & (1<<0xf)) ? '1' : '0',
 		(beacon->capability & (1<<0xe)) ? '1' : '0',
 		(beacon->capability & (1<<0xd)) ? '1' : '0',
@@ -1362,10 +1362,10 @@
 		(beacon->capability & (1<<0x0)) ? '1' : '0');
 
 	if (ieee80211_network_init(ieee, beacon, &network, stats)) {
-		IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
 				     escape_essid(info_element->data,
 						  info_element->len),
-				     MAC_ARG(beacon->header.addr3),
+				     beacon->header.addr3,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
@@ -1464,11 +1464,11 @@
 			/* If there are no more slots, expire the oldest */
 			list_del(&oldest->list);
 			target = oldest;
-			IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
+			IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
 					     "network list.\n",
 					     escape_essid(target->ssid,
 							  target->ssid_len),
-					     MAC_ARG(target->bssid));
+					     target->bssid);
 		} else {
 			/* Otherwise just pull from the free list */
 			target = list_entry(ieee->network_free_list.next,
@@ -1478,10 +1478,10 @@
 
 
 #ifdef CONFIG_IEEE80211_DEBUG
-		IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
 				     escape_essid(network.ssid,
 						  network.ssid_len),
-				     MAC_ARG(network.bssid),
+				     network.bssid,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
@@ -1492,10 +1492,10 @@
 		if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
 			ieee80211_softmac_new_net(ieee,&network);
 	} else {
-		IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
 				     escape_essid(target->ssid,
 						  target->ssid_len),
-				     MAC_ARG(target->bssid),
+				     target->bssid,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
index a215067..c2f472e 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -1573,7 +1573,7 @@
 		ieee80211_resp_to_assoc_rq(ieee, dest);
 	}
 
-	printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
+	printk(KERN_INFO"New client associated: %pM\n", dest);
 }
 
 
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
index f1d6cb4..ad42bcd 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
@@ -482,8 +482,7 @@
 		(!ieee->enter_sleep_state) ||
 		(!ieee->ps_is_queue_empty)){
 
-		printk("ERROR. PS mode is tryied to be use but\
-driver missed a callback\n\n");
+		printk("ERROR. PS mode tried to be use but driver missed a callback\n\n");
 
 		return -1;
 	}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
index 69bd021..6cb31e1 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
@@ -198,8 +198,8 @@
 		header = (struct ieee80211_hdr_4addr *)frag->data;
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "TX packet to " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(header->addr1));
+			       "TX packet to %pM\n",
+			       ieee->dev->name, header->addr1);
 		}
 		return -1;
 	}
@@ -407,7 +407,7 @@
 			memcpy(&header.addr2, src, ETH_ALEN);
 			memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
 		}
-	//	printk(KERN_WARNING "essid MAC address is "MAC_FMT, MAC_ARG(&header.addr1));
+	//	printk(KERN_WARNING "essid MAC address is %pM", &header.addr1);
 		header.frame_ctl = cpu_to_le16(fc);
 		//hdr_len = IEEE80211_3ADDR_LEN;
 
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
index 6aad48f..bd5e77b 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
@@ -234,10 +234,10 @@
 			else
 				IEEE80211_DEBUG_SCAN(
 					"Not showing network '%s ("
-					MAC_FMT ")' due to age (%lums).\n",
+					"%pM)' due to age (%lums).\n",
 					escape_essid(network->ssid,
 						     network->ssid_len),
-					MAC_ARG(network->bssid),
+					network->bssid,
 					(jiffies - network->last_scanned) / (HZ / 100));
 		}
 	}
@@ -694,7 +694,7 @@
 #if 1
 	case IW_AUTH_WPA_ENABLED:
 		ieee->wpa_enabled = (data->value)?1:0;
-		//printk("enalbe wpa:%d\n", ieee->wpa_enabled);
+		//printk("enable wpa:%d\n", ieee->wpa_enabled);
 		break;
 
 #endif
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index ce82888..d15bdf6 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -366,7 +366,6 @@
 	short diversity;
 	u8 cs_treshold;
 	short rcr_csense;
-	short rf_chip;
 	u32 key0[4];
 	short (*rf_set_sens)(struct net_device *dev,short sens);
 	void (*rf_set_chan)(struct net_device *dev,short ch);
@@ -479,9 +478,6 @@
 	u8 retry_rts;
 	u16 rts;
 
-//add for RF power on power off by lizhaoming 080512
-	u8	 RegThreeWireMode; // See "Three wire mode" defined above, 2006.05.31, by rcnjko.
-
 //by amy for led
 	LED_STRATEGY_8185 LedStrategy;
 //by amy for led
diff --git a/drivers/staging/rtl8187se/r8180_93cx6.c b/drivers/staging/rtl8187se/r8180_93cx6.c
deleted file mode 100644
index 7e4711f..0000000
--- a/drivers/staging/rtl8187se/r8180_93cx6.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-   This files contains card eeprom (93c46 or 93c56) programming routines,
-   memory is addressed by 16 bits words.
-
-   This is part of rtl8180 OpenSource driver.
-   Copyright (C) Andrea Merello 2004  <andreamrl@tiscali.it>
-   Released under the terms of GPL (General Public Licence)
-
-   Parts of this driver are based on the GPL part of the
-   official realtek driver.
-
-   Parts of this driver are based on the rtl8180 driver skeleton
-   from Patric Schenke & Andres Salomon.
-
-   Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
-
-   We want to tanks the Authors of those projects and the Ndiswrapper
-   project Authors.
-*/
-
-#include "r8180_93cx6.h"
-
-void eprom_cs(struct net_device *dev, short bit)
-{
-	if(bit)
-		write_nic_byte(dev, EPROM_CMD,
-			       (1<<EPROM_CS_SHIFT) | \
-			       read_nic_byte(dev, EPROM_CMD)); //enable EPROM
-	else
-		write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)\
-			       &~(1<<EPROM_CS_SHIFT)); //disable EPROM
-
-	force_pci_posting(dev);
-	udelay(EPROM_DELAY);
-}
-
-
-void eprom_ck_cycle(struct net_device *dev)
-{
-	write_nic_byte(dev, EPROM_CMD,
-		       (1<<EPROM_CK_SHIFT) | read_nic_byte(dev,EPROM_CMD));
-	force_pci_posting(dev);
-	udelay(EPROM_DELAY);
-	write_nic_byte(dev, EPROM_CMD,
-		       read_nic_byte(dev, EPROM_CMD) &~ (1<<EPROM_CK_SHIFT));
-	force_pci_posting(dev);
-	udelay(EPROM_DELAY);
-}
-
-
-void eprom_w(struct net_device *dev,short bit)
-{
-	if(bit)
-		write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) | \
-			       read_nic_byte(dev,EPROM_CMD));
-	else
-		write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev,EPROM_CMD)\
-			       &~(1<<EPROM_W_SHIFT));
-
-	force_pci_posting(dev);
-	udelay(EPROM_DELAY);
-}
-
-
-short eprom_r(struct net_device *dev)
-{
-	short bit;
-
-	bit=(read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT) );
-	udelay(EPROM_DELAY);
-
-	if(bit) return 1;
-	return 0;
-}
-
-
-void eprom_send_bits_string(struct net_device *dev, short b[], int len)
-{
-	int i;
-
-	for(i=0; i<len; i++){
-		eprom_w(dev, b[i]);
-		eprom_ck_cycle(dev);
-	}
-}
-
-
-u32 eprom_read(struct net_device *dev, u32 addr)
-{
-	struct r8180_priv *priv = ieee80211_priv(dev);
-	short read_cmd[]={1,1,0};
-	short addr_str[8];
-	int i;
-	int addr_len;
-	u32 ret;
-
-	ret=0;
-        //enable EPROM programming
-	write_nic_byte(dev, EPROM_CMD,
-		       (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT));
-	force_pci_posting(dev);
-	udelay(EPROM_DELAY);
-
-	if (priv->epromtype==EPROM_93c56){
-		addr_str[7]=addr & 1;
-		addr_str[6]=addr & (1<<1);
-		addr_str[5]=addr & (1<<2);
-		addr_str[4]=addr & (1<<3);
-		addr_str[3]=addr & (1<<4);
-		addr_str[2]=addr & (1<<5);
-		addr_str[1]=addr & (1<<6);
-		addr_str[0]=addr & (1<<7);
-		addr_len=8;
-	}else{
-		addr_str[5]=addr & 1;
-		addr_str[4]=addr & (1<<1);
-		addr_str[3]=addr & (1<<2);
-		addr_str[2]=addr & (1<<3);
-		addr_str[1]=addr & (1<<4);
-		addr_str[0]=addr & (1<<5);
-		addr_len=6;
-	}
-	eprom_cs(dev, 1);
-	eprom_ck_cycle(dev);
-	eprom_send_bits_string(dev, read_cmd, 3);
-	eprom_send_bits_string(dev, addr_str, addr_len);
-
-	//keep chip pin D to low state while reading.
-	//I'm unsure if it is necessary, but anyway shouldn't hurt
-	eprom_w(dev, 0);
-
-	for(i=0;i<16;i++){
-		//eeprom needs a clk cycle between writing opcode&adr
-		//and reading data. (eeprom outs a dummy 0)
-		eprom_ck_cycle(dev);
-		ret |= (eprom_r(dev)<<(15-i));
-	}
-
-	eprom_cs(dev, 0);
-	eprom_ck_cycle(dev);
-
-	//disable EPROM programming
-	write_nic_byte(dev, EPROM_CMD,
-		       (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
-	return ret;
-}
diff --git a/drivers/staging/rtl8187se/r8180_93cx6.h b/drivers/staging/rtl8187se/r8180_93cx6.h
index 36ae100..79e7391 100644
--- a/drivers/staging/rtl8187se/r8180_93cx6.h
+++ b/drivers/staging/rtl8187se/r8180_93cx6.h
@@ -45,13 +45,10 @@
 
 #define	EPROM_TXPW_OFDM_CH1_2 0x20
 
-//#define	EPROM_TXPW_CH1_2 0x10
-#define  EPROM_TXPW_CH1_2 0x30
-#define	EPROM_TXPW_CH3_4 0x11
-#define	EPROM_TXPW_CH5_6 0x12
-#define	EPROM_TXPW_CH7_8 0x13
-#define	EPROM_TXPW_CH9_10 0x14
-#define	EPROM_TXPW_CH11_12 0x15
-#define	EPROM_TXPW_CH13_14 0x16
+#define	EPROM_TXPW_CH1_2 0x30
 
-u32 eprom_read(struct net_device *dev,u32 addr); //reads a 16 bits word
+#define RTL818X_EEPROM_CMD_READ		(1 << 0)
+#define RTL818X_EEPROM_CMD_WRITE	(1 << 1)
+#define RTL818X_EEPROM_CMD_CK		(1 << 2)
+#define RTL818X_EEPROM_CMD_CS		(1 << 3)
+
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 1847f38..b1757ac 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -31,6 +31,7 @@
 #undef DUMMY_RX
 
 #include <linux/syscalls.h>
+#include <linux/eeprom_93cx6.h>
 
 #include "r8180_hw.h"
 #include "r8180.h"
@@ -41,13 +42,6 @@
 
 #include "ieee80211/dot11d.h"
 
-#ifndef PCI_VENDOR_ID_BELKIN
-	#define PCI_VENDOR_ID_BELKIN 0x1799
-#endif
-#ifndef PCI_VENDOR_ID_DLINK
-	#define PCI_VENDOR_ID_DLINK 0x1186
-#endif
-
 static struct pci_device_id rtl8180_pci_id_tbl[] __devinitdata = {
         {
                 .vendor = PCI_VENDOR_ID_REALTEK,
@@ -669,11 +663,8 @@
 
 void rtl8180_RSSI_calc(struct net_device *dev, u8 *rssi, u8 *qual)
 {
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	u32 temp;
 	u32 temp2;
-	u32 temp3;
-	u32 lsb;
 	u32 q;
 	u32 orig_qual;
 	u8  _rssi;
@@ -695,88 +686,6 @@
 	*qual = temp;
 	temp2 = *rssi;
 
-	switch(priv->rf_chip){
-	case RFCHIPID_RFMD:
-		lsb = temp2 & 1;
-		temp2 &= 0x7e;
-		if ( !lsb || !(temp2 <= 0x3c) ) {
-			temp2 = 0x64;
-		} else {
-			temp2 = 100 * temp2 / 0x3c;
-		}
-		*rssi = temp2 & 0xff;
-		_rssi = temp2 & 0xff;
-		break;
-	case RFCHIPID_INTERSIL:
-		lsb = temp2;
-		temp2 &= 0xfffffffe;
-		temp2 *= 251;
-		temp3 = temp2;
-		temp2 <<= 6;
-		temp3 += temp2;
-		temp3 <<= 1;
-		temp2 = 0x4950df;
-		temp2 -= temp3;
-		lsb &= 1;
-		if ( temp2 <= 0x3e0000 ) {
-			if ( temp2 < 0xffef0000 )
-				temp2 = 0xffef0000;
-		} else {
-			temp2 = 0x3e0000;
-		}
-		if ( !lsb ) {
-			temp2 -= 0xf0000;
-		} else {
-			temp2 += 0xf0000;
-		}
-
-		temp3 = 0x4d0000;
-		temp3 -= temp2;
-		temp3 *= 100;
-		temp3 = temp3 / 0x6d;
-		temp3 >>= 0x10;
-		_rssi = temp3 & 0xff;
-		*rssi = temp3 & 0xff;
-		break;
-	case RFCHIPID_GCT:
-	        lsb = temp2 & 1;
-		temp2 &= 0x7e;
-		if ( ! lsb || !(temp2 <= 0x3c) ){
-			temp2 = 0x64;
-		} else {
-			temp2 = (100 * temp2) / 0x3c;
-		}
-		*rssi = temp2 & 0xff;
-		_rssi = temp2 & 0xff;
-		break;
-	case RFCHIPID_PHILIPS:
-		if( orig_qual <= 0x4e ){
-			_rssi = STRENGTH_MAP[orig_qual];
-			*rssi = _rssi;
-		} else {
-			orig_qual -= 0x80;
-			if ( !orig_qual ){
-				_rssi = 1;
-				*rssi = 1;
-			} else {
-				_rssi = 0x32;
-				*rssi = 0x32;
-			}
-		}
-		break;
-	case RFCHIPID_MAXIM:
-		lsb = temp2 & 1;
-		temp2 &= 0x7e;
-		temp2 >>= 1;
-		temp2 += 0x42;
-		if( lsb != 0 ){
-			temp2 += 0xa;
-		}
-		*rssi = temp2 & 0xff;
-		_rssi = temp2 & 0xff;
-		break;
-	}
-
 	if ( _rssi < 0x64 ){
 		if ( _rssi == 0 ) {
 			*rssi = 1;
@@ -1421,11 +1330,9 @@
 	return N_DBPS;
 }
 
-//{by amy 080312
 //
 //	Description:
 // 	For Netgear case, they want good-looking singal strength.
-//		2004.12.05, by rcnjko.
 //
 long NetgearSignalStrengthTranslate(long LastSS, long CurrSS)
 {
@@ -1481,7 +1388,6 @@
 //		This is different with PerformSignalSmoothing8185 in smoothing fomula.
 //		No dramatic adjustion is apply because dynamic mechanism need some degree
 //		of correctness. Ported from 8187B.
-//	2007-02-26, by Bruce.
 //
 void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv,
 					   bool bCckRate)
@@ -1502,7 +1408,6 @@
 		priv->CurCCKRSSI = 0;
 }
 
-//by amy 080312}
 
 /* This is rough RX isr handling routine*/
 void rtl8180_rx(struct net_device *dev)
@@ -1638,7 +1543,7 @@
 		}
 
 		signal=(unsigned char)(((*(priv->rxringtail+3))& (0x00ff0000))>>16);
-		signal=(signal&0xfe)>>1;	// Modify by hikaru 6.6
+		signal = (signal & 0xfe) >> 1;
 
 		quality=(unsigned char)((*(priv->rxringtail+3)) & (0xff));
 
@@ -1652,7 +1557,6 @@
 
 		stats.rate = rtl8180_rate2rate(rate);
 		Antenna = (((*(priv->rxringtail +3))& (0x00008000)) == 0 )? 0:1 ;
-//by amy for antenna
 		if(!rtl8180_IsWirelessBMode(stats.rate))
 		{ // OFDM rate.
 
@@ -1691,11 +1595,10 @@
 			RXAGC=(95-RXAGC)*100/65;
 		}
 		priv->SignalStrength = (u8)RXAGC;
-		priv->RecvSignalPower = RxAGC_dBm ;  // It can use directly by SD3 CMLin
+		priv->RecvSignalPower = RxAGC_dBm;
 		priv->RxPower = rxpower;
 		priv->RSSI = RSSI;
-//{by amy 080312
-		// SQ translation formular is provided by SD3 DZ. 2006.06.27, by rcnjko.
+		/* SQ translation formula is provided by SD3 DZ. 2006.06.27 */
 		if(quality >= 127)
 			quality = 1;//0; //0 will cause epc to show signal zero , walk aroud now;
 		else if(quality < 27)
@@ -1712,7 +1615,6 @@
 	//	printk("==========================>rx : RXAGC is %d,signalstrength is %d\n",RXAGC,stats.signalstrength);
 		stats.rssi = priv->wstats.qual.qual = priv->SignalQuality;
 		stats.noise = priv->wstats.qual.noise = 100 - priv ->wstats.qual.qual;
-//by amy 080312}
 		bHwError = (((*(priv->rxringtail))& (0x00000fff)) == 4080)| (((*(priv->rxringtail))& (0x04000000)) != 0 )
 			| (((*(priv->rxringtail))& (0x08000000)) != 0 )| (((~(*(priv->rxringtail)))& (0x10000000)) != 0 )| (((~(*(priv->rxringtail)))& (0x20000000)) != 0 );
 		bCRC = ((*(priv->rxringtail)) & (0x00002000)) >> 13;
@@ -1725,11 +1627,12 @@
 				(eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
 				 && (!bHwError) && (!bCRC)&& (!bICV))
 			{
-//by amy 080312
-				// Perform signal smoothing for dynamic mechanism on demand.
-				// This is different with PerformSignalSmoothing8185 in smoothing fomula.
-				// No dramatic adjustion is apply because dynamic mechanism need some degree
-				// of correctness. 2007.01.23, by shien chang.
+				/* Perform signal smoothing for dynamic
+				 * mechanism on demand. This is different
+				 * with PerformSignalSmoothing8185 in smoothing
+				 * fomula. No dramatic adjustion is apply
+				 * because dynamic mechanism need some degree
+				 * of correctness. */
 				PerformUndecoratedSignalSmoothing8185(priv,bCckRate);
 				//
 				// For good-looking singal strength.
@@ -1749,12 +1652,9 @@
 
 		// Figure out which antenna that received the lasted packet.
 				priv->LastRxPktAntenna = Antenna ? 1 : 0; // 0: aux, 1: main.
-//by amy 080312
 			    SwAntennaDiversityRxOk8185(dev, priv->SignalStrength);
 			}
 
-//by amy for antenna
-#ifndef DUMMY_RX
 		if(first){
 			if(!priv->rx_skb_complete){
 				/* seems that HW sometimes fails to reiceve and
@@ -1810,19 +1710,12 @@
 		if(last && !priv->rx_skb_complete){
 			if(priv->rx_skb->len > 4)
 				skb_trim(priv->rx_skb,priv->rx_skb->len-4);
-#ifndef RX_DONT_PASS_UL
 			if(!ieee80211_rtl_rx(priv->ieee80211,
-					 priv->rx_skb, &stats)){
-#endif // RX_DONT_PASS_UL
-
+					 priv->rx_skb, &stats))
 				dev_kfree_skb_any(priv->rx_skb);
-#ifndef RX_DONT_PASS_UL
-			}
-#endif
 			priv->rx_skb_complete=1;
 		}
 
-#endif //DUMMY_RX
 		pci_dma_sync_single_for_device(priv->pdev,
 				    priv->rxbuffer->dma,
 				    priv->rxbuffersize * \
@@ -2056,7 +1949,7 @@
 	u16			RtsDur = 0;
 	u16			ThisFrameTime = 0;
 	u16			TxDescDuration = 0;
-	u8 			ownbit_flag = false; //added by david woo for sync Tx, 2007.12.14
+	u8 			ownbit_flag = false;
 
 	switch(priority) {
 	case MANAGE_PRIORITY:
@@ -2123,7 +2016,8 @@
 			//YJ,add,080828,for Keep alive
 			priv->NumTxUnicast++;
 
-			// Figure out ACK rate according to BSS basic rate and Tx rate, 2006.03.08 by rcnjko.
+			/* Figure out ACK rate according to BSS basic rate
+			 * and Tx rate. */
 			AckTime = ComputeTxTime(14, 10,0, 0);	// AckCTSLng = 14 use 1M bps send
 
 			if ( ((len + sCrcLng) > priv->rts) && priv->rts )
@@ -2206,7 +2100,7 @@
 		*tail |= (1<<15); /* no encrypt */
 
 		if(remain==len && !descfrag) {
-			ownbit_flag = false;	//added by david woo,2007.12.14
+			ownbit_flag = false;
 			*tail = *tail| (1<<29) ; //fist segment of the packet
 			*tail = *tail |(len);
 		} else {
@@ -2556,27 +2450,16 @@
 	}
 
 	// Tx High Power Mechanism.
-#ifdef HIGH_POWER
 	if(CheckHighPower((struct net_device *)data))
-	{
 		queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->tx_pw_wq);
-	}
-#endif
 
 	// Tx Power Tracking on 87SE.
-#ifdef TX_TRACK
-	//if( priv->bTxPowerTrack )	//lzm mod 080826
-	if( CheckTxPwrTracking((struct net_device *)data));
+	if (CheckTxPwrTracking((struct net_device *)data))
 		TxPwrTracking87SE((struct net_device *)data);
-#endif
 
 	// Perform DIG immediately.
-#ifdef SW_DIG
 	if(CheckDig((struct net_device *)data) == true)
-	{
 		queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_dig_wq);
-	}
-#endif
    	rtl8180_watch_dog((struct net_device *)data);
 
 	queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->GPIOChangeRFWorkItem);
@@ -2675,6 +2558,36 @@
 }
 //YJ,add,080828,end
 
+static void rtl8187se_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+	struct net_device *dev = eeprom->data;
+	u8 reg = read_nic_byte(dev, EPROM_CMD);
+
+	eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
+	eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
+	eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
+	eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
+}
+
+static void rtl8187se_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+	struct net_device *dev = eeprom->data;
+	u8 reg = 2 << 6;
+
+	if (eeprom->reg_data_in)
+		reg |= RTL818X_EEPROM_CMD_WRITE;
+	if (eeprom->reg_data_out)
+		reg |= RTL818X_EEPROM_CMD_READ;
+	if (eeprom->reg_data_clock)
+		reg |= RTL818X_EEPROM_CMD_CK;
+	if (eeprom->reg_chip_select)
+		reg |= RTL818X_EEPROM_CMD_CS;
+
+	write_nic_byte(dev, EPROM_CMD, reg);
+	read_nic_byte(dev, EPROM_CMD);
+	udelay(10);
+}
+
 short rtl8180_init(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
@@ -2683,8 +2596,16 @@
 	u32 usValue;
 	u16 tmpu16;
 	int i, j;
+	struct eeprom_93cx6 eeprom;
+	u16 eeprom_val;
 
-	priv->channel_plan = eprom_read(dev, EEPROM_COUNTRY_CODE>>1) & 0xFF;
+	eeprom.data = dev;
+	eeprom.register_read = rtl8187se_eeprom_register_read;
+	eeprom.register_write = rtl8187se_eeprom_register_write;
+	eeprom.width = PCI_EEPROM_WIDTH_93C46;
+
+	eeprom_93cx6_read(&eeprom, EEPROM_COUNTRY_CODE>>1, &eeprom_val);
+	priv->channel_plan = eeprom_val & 0xFF;
 	if(priv->channel_plan > COUNTRY_CODE_GLOBAL_DOMAIN){
 		printk("rtl8180_init:Error channel plan! Set to default.\n");
 		priv->channel_plan = 0;
@@ -2701,8 +2622,6 @@
 	priv->txbeaconcount = 2;
 	priv->rx_skb_complete = 1;
 
-	priv->RegThreeWireMode = HW_THREE_WIRE_SI;
-
 	priv->RFChangeInProgress = false;
 	priv->SetRFPowerStateInProgress = false;
 	priv->RFProgType = 0;
@@ -2747,10 +2666,8 @@
 	priv->TxPollingTimes = 0;//lzm add 080826
 	priv->bLeisurePs = true;
 	priv->dot11PowerSaveMode = eActive;
-//by amy for antenna
 	priv->AdMinCheckPeriod = 5;
 	priv->AdMaxCheckPeriod = 10;
-// Lower signal strength threshold to fit the HW participation in antenna diversity. +by amy 080312
 	priv->AdMaxRxSsThreshold = 30;//60->30
 	priv->AdRxSsThreshold = 20;//50->20
 	priv->AdCheckPeriod = priv->AdMinCheckPeriod;
@@ -2765,8 +2682,6 @@
 	init_timer(&priv->SwAntennaDiversityTimer);
 	priv->SwAntennaDiversityTimer.data = (unsigned long)dev;
 	priv->SwAntennaDiversityTimer.function = (void *)SwAntennaDiversityTimerCallback;
-//by amy for antenna
-//{by amy 080312
 	priv->bDigMechanism = 1;
 	priv->InitialGain = 6;
 	priv->bXtalCalibration = false;
@@ -2803,58 +2718,63 @@
 	priv->NumTxUnicast = 0;
 	priv->keepAliveLevel = DEFAULT_KEEP_ALIVE_LEVEL;
 	priv->PowerProfile = POWER_PROFILE_AC;
-    priv->CurrRetryCnt=0;
-    priv->LastRetryCnt=0;
-    priv->LastTxokCnt=0;
-    priv->LastRxokCnt=0;
-    priv->LastRetryRate=0;
-    priv->bTryuping=0;
-    priv->CurrTxRate=0;
-    priv->CurrRetryRate=0;
-    priv->TryupingCount=0;
-    priv->TryupingCountNoData=0;
-    priv->TryDownCountLowData=0;
-    priv->LastTxOKBytes=0;
-    priv->LastFailTxRate=0;
-    priv->LastFailTxRateSS=0;
-    priv->FailTxRateCount=0;
-    priv->LastTxThroughput=0;
-    priv->NumTxOkBytesTotal=0;
+	priv->CurrRetryCnt = 0;
+	priv->LastRetryCnt = 0;
+	priv->LastTxokCnt = 0;
+	priv->LastRxokCnt = 0;
+	priv->LastRetryRate = 0;
+	priv->bTryuping = 0;
+	priv->CurrTxRate = 0;
+	priv->CurrRetryRate = 0;
+	priv->TryupingCount = 0;
+	priv->TryupingCountNoData = 0;
+	priv->TryDownCountLowData = 0;
+	priv->LastTxOKBytes = 0;
+	priv->LastFailTxRate = 0;
+	priv->LastFailTxRateSS = 0;
+	priv->FailTxRateCount = 0;
+	priv->LastTxThroughput = 0;
+	priv->NumTxOkBytesTotal = 0;
 	priv->ForcedDataRate = 0;
 	priv->RegBModeGainStage = 1;
 
-	priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;
+	priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
 	spin_lock_init(&priv->irq_lock);
 	spin_lock_init(&priv->irq_th_lock);
 	spin_lock_init(&priv->tx_lock);
 	spin_lock_init(&priv->ps_lock);
 	spin_lock_init(&priv->rf_ps_lock);
-	sema_init(&priv->wx_sem,1);
-	sema_init(&priv->rf_state,1);
-	INIT_WORK(&priv->reset_wq,(void*) rtl8180_restart_wq);
-	INIT_WORK(&priv->tx_irq_wq,(void*) rtl8180_tx_irq_wq);
-	INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq,(void*) rtl8180_hw_wakeup_wq);
-	INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq,(void*) rtl8180_hw_sleep_wq);
-	INIT_WORK(&priv->ieee80211->wmm_param_update_wq,(void*) rtl8180_wmm_param_update);
-	INIT_DELAYED_WORK(&priv->ieee80211->rate_adapter_wq,(void*)rtl8180_rate_adapter);//+by amy 080312
-	INIT_DELAYED_WORK(&priv->ieee80211->hw_dig_wq,(void*)rtl8180_hw_dig_wq);//+by amy 080312
-	INIT_DELAYED_WORK(&priv->ieee80211->tx_pw_wq,(void*)rtl8180_tx_pw_wq);//+by amy 080312
-
-	INIT_DELAYED_WORK(&priv->ieee80211->GPIOChangeRFWorkItem,(void*) GPIOChangeRFWorkItemCallBack);
-
+	sema_init(&priv->wx_sem, 1);
+	sema_init(&priv->rf_state, 1);
+	INIT_WORK(&priv->reset_wq, (void *)rtl8180_restart_wq);
+	INIT_WORK(&priv->tx_irq_wq, (void *)rtl8180_tx_irq_wq);
+	INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq,
+			  (void *)rtl8180_hw_wakeup_wq);
+	INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq,
+			  (void *)rtl8180_hw_sleep_wq);
+	INIT_WORK(&priv->ieee80211->wmm_param_update_wq,
+		  (void *)rtl8180_wmm_param_update);
+	INIT_DELAYED_WORK(&priv->ieee80211->rate_adapter_wq,
+			  (void *)rtl8180_rate_adapter);
+	INIT_DELAYED_WORK(&priv->ieee80211->hw_dig_wq,
+			 (void *)rtl8180_hw_dig_wq);
+	INIT_DELAYED_WORK(&priv->ieee80211->tx_pw_wq,
+			 (void *)rtl8180_tx_pw_wq);
+	INIT_DELAYED_WORK(&priv->ieee80211->GPIOChangeRFWorkItem,
+			 (void *) GPIOChangeRFWorkItemCallBack);
 	tasklet_init(&priv->irq_rx_tasklet,
 		     (void(*)(unsigned long)) rtl8180_irq_rx_tasklet,
 		     (unsigned long)priv);
 
-    init_timer(&priv->watch_dog_timer);
+	init_timer(&priv->watch_dog_timer);
 	priv->watch_dog_timer.data = (unsigned long)dev;
 	priv->watch_dog_timer.function = watch_dog_adaptive;
 
-    init_timer(&priv->rateadapter_timer);
-        priv->rateadapter_timer.data = (unsigned long)dev;
-        priv->rateadapter_timer.function = timer_rate_adaptive;
-		priv->RateAdaptivePeriod= RATE_ADAPTIVE_TIMER_PERIOD;
-		priv->bEnhanceTxPwr=false;
+	init_timer(&priv->rateadapter_timer);
+	priv->rateadapter_timer.data = (unsigned long)dev;
+	priv->rateadapter_timer.function = timer_rate_adaptive;
+	priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD;
+	priv->bEnhanceTxPwr = false;
 
 	priv->ieee80211->softmac_hard_start_xmit = rtl8180_hard_start_xmit;
 	priv->ieee80211->set_chan = rtl8180_set_chan;
@@ -2877,30 +2797,28 @@
 
 	priv->CSMethod = (0x01 << 29);
 
-	priv->TransmitConfig	=
-									1<<TCR_DurProcMode_OFFSET |		//for RTL8185B, duration setting by HW
-									(7<<TCR_MXDMA_OFFSET) |	// Max DMA Burst Size per Tx DMA Burst, 7: reservied.
-									(priv->ShortRetryLimit<<TCR_SRL_OFFSET) |	// Short retry limit
-									(priv->LongRetryLimit<<TCR_LRL_OFFSET) |	// Long retry limit
-									(0 ? TCR_SAT : 0);	// FALSE: HW provies PLCP length and LENGEXT, TURE: SW proiveds them
+	priv->TransmitConfig =	TCR_DurProcMode_OFFSET |
+				(7<<TCR_MXDMA_OFFSET) |
+				(priv->ShortRetryLimit<<TCR_SRL_OFFSET) |
+				(priv->LongRetryLimit<<TCR_LRL_OFFSET) |
+				(0 ? TCR_SAT : 0);
 
-	priv->ReceiveConfig	=
-								RCR_AMF | RCR_ADF |				//accept management/data
-								RCR_ACF |						//accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
-								RCR_AB | RCR_AM | RCR_APM |		//accept BC/MC/UC
-								(7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
-								(priv->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
-								(priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT:0);
+	priv->ReceiveConfig =	RCR_AMF | RCR_ADF | RCR_ACF |
+				RCR_AB | RCR_AM | RCR_APM |
+				(7<<RCR_MXDMA_OFFSET) |
+				(priv->EarlyRxThreshold<<RCR_FIFO_OFFSET) |
+				(priv->EarlyRxThreshold == 7 ?
+					 RCR_ONLYERLPKT : 0);
 
 	priv->IntrMask		= IMR_TMGDOK | IMR_TBDER | IMR_THPDER |
-								IMR_THPDER | IMR_THPDOK |
-								IMR_TVODER | IMR_TVODOK |
-								IMR_TVIDER | IMR_TVIDOK |
-								IMR_TBEDER | IMR_TBEDOK |
-								IMR_TBKDER | IMR_TBKDOK |
-								IMR_RDU |						// To handle the defragmentation not enough Rx descriptors case. Annie, 2006-03-27.
-								IMR_RER | IMR_ROK |
-								IMR_RQoSOK; // <NOTE> ROK and RQoSOK are mutually exclusive, so, we must handle RQoSOK interrupt to receive QoS frames, 2005.12.09, by rcnjko.
+				  IMR_THPDER | IMR_THPDOK |
+				  IMR_TVODER | IMR_TVODOK |
+				  IMR_TVIDER | IMR_TVIDOK |
+				  IMR_TBEDER | IMR_TBEDOK |
+				  IMR_TBKDER | IMR_TBKDOK |
+				  IMR_RDU |
+				  IMR_RER | IMR_ROK |
+				  IMR_RQoSOK;
 
 	priv->InitialGain = 6;
 
@@ -2913,7 +2831,8 @@
 	// just for sync 85
 	priv->enable_gpio0 = 0;
 
-	usValue = eprom_read(dev, EEPROM_SW_REVD_OFFSET);
+	eeprom_93cx6_read(&eeprom, EEPROM_SW_REVD_OFFSET, &eeprom_val);
+	usValue = eeprom_val;
 	DMESG("usValue is 0x%x\n",usValue);
 	//3Read AntennaDiversity
 
@@ -2953,54 +2872,46 @@
 	else
 		priv->epromtype=EPROM_93c46;
 
-	dev->dev_addr[0]=eprom_read(dev,MAC_ADR) & 0xff;
-	dev->dev_addr[1]=(eprom_read(dev,MAC_ADR) & 0xff00)>>8;
-	dev->dev_addr[2]=eprom_read(dev,MAC_ADR+1) & 0xff;
-	dev->dev_addr[3]=(eprom_read(dev,MAC_ADR+1) & 0xff00)>>8;
-	dev->dev_addr[4]=eprom_read(dev,MAC_ADR+2) & 0xff;
-	dev->dev_addr[5]=(eprom_read(dev,MAC_ADR+2) & 0xff00)>>8;
+	eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)
+			       dev->dev_addr, 3);
 
 	for(i=1,j=0; i<14; i+=2,j++){
-		word = eprom_read(dev,EPROM_TXPW_CH1_2 + j);
+		eeprom_93cx6_read(&eeprom, EPROM_TXPW_CH1_2 + j, &word);
 		priv->chtxpwr[i]=word & 0xff;
 		priv->chtxpwr[i+1]=(word & 0xff00)>>8;
 	}
 	for (i = 1, j = 0; i < 14; i += 2, j++) {
-		word = eprom_read(dev, EPROM_TXPW_OFDM_CH1_2 + j);
+		eeprom_93cx6_read(&eeprom, EPROM_TXPW_OFDM_CH1_2 + j, &word);
 		priv->chtxpwr_ofdm[i] = word & 0xff;
-		priv->chtxpwr_ofdm[i+1] = (word & 0xff00)>>8;
+		priv->chtxpwr_ofdm[i+1] = (word & 0xff00) >> 8;
 	}
 
-	//3Read crystal calibtration and thermal meter indication on 87SE.
+	/* 3Read crystal calibtration and thermal meter indication on 87SE. */
+	eeprom_93cx6_read(&eeprom, EEPROM_RSV>>1, &tmpu16);
 
-	// By SD3 SY's request. Added by Roger, 2007.12.11.
+	/* Crystal calibration for Xin and Xout resp. */
+	priv->XtalCal_Xout = tmpu16 & EEPROM_XTAL_CAL_XOUT_MASK;
+	priv->XtalCal_Xin = (tmpu16 & EEPROM_XTAL_CAL_XIN_MASK) >> 4;
+	if ((tmpu16 & EEPROM_XTAL_CAL_ENABLE) >> 12)
+		priv->bXtalCalibration = true;
 
-	tmpu16 = eprom_read(dev, EEPROM_RSV>>1);
+	/* Thermal meter reference indication. */
+	priv->ThermalMeter =  (u8)((tmpu16 & EEPROM_THERMAL_METER_MASK) >> 8);
+	if ((tmpu16 & EEPROM_THERMAL_METER_ENABLE) >> 13)
+		priv->bTxPowerTrack = true;
 
-		// Crystal calibration for Xin and Xout resp.
-		priv->XtalCal_Xout = tmpu16 & EEPROM_XTAL_CAL_XOUT_MASK; // 0~7.5pF
-		priv->XtalCal_Xin = (tmpu16 & EEPROM_XTAL_CAL_XIN_MASK)>>4; // 0~7.5pF
-		if((tmpu16 & EEPROM_XTAL_CAL_ENABLE)>>12)
-			priv->bXtalCalibration = true;
-
-		// Thermal meter reference indication.
-		priv->ThermalMeter =  (u8)((tmpu16 & EEPROM_THERMAL_METER_MASK)>>8);
-		if((tmpu16 & EEPROM_THERMAL_METER_ENABLE)>>13)
-			priv->bTxPowerTrack = true;
-
-	word = eprom_read(dev,EPROM_TXPW_BASE);
+	eeprom_93cx6_read(&eeprom, EPROM_TXPW_BASE, &word);
 	priv->cck_txpwr_base = word & 0xf;
 	priv->ofdm_txpwr_base = (word>>4) & 0xf;
 
-	version = eprom_read(dev,EPROM_VERSION);
+	eeprom_93cx6_read(&eeprom, EPROM_VERSION, &version);
 	DMESG("EEPROM version %x",version);
 	priv->rcr_csense = 3;
 
-	priv->cs_treshold = (eprom_read(dev, ENERGY_TRESHOLD) & 0xff00) >> 8;
+	eeprom_93cx6_read(&eeprom, ENERGY_TRESHOLD, &eeprom_val);
+	priv->cs_treshold = (eeprom_val & 0xff00) >> 8;
 
-	priv->rf_chip = 0xff & eprom_read(dev, RFCHIPID);
-
-	priv->rf_chip = RF_ZEBRA4;
+	eeprom_93cx6_read(&eeprom, RFCHIPID, &eeprom_val);
 	priv->rf_sleep = rtl8225z4_rf_sleep;
 	priv->rf_wakeup = rtl8225z4_rf_wakeup;
 	DMESGW("**PLEASE** REPORT SUCCESSFUL/UNSUCCESSFUL TO Realtek!");
@@ -3010,7 +2921,6 @@
 	priv->rf_set_chan = rtl8225z2_rf_set_chan;
 	priv->rf_set_sens = NULL;
 
-
 	if (0!=alloc_rx_desc_ring(dev, priv->rxbuffersize, priv->rxringcount))
 		return -ENOMEM;
 
@@ -3042,11 +2952,7 @@
 				  TX_BEACON_RING_ADDR))
 		return -ENOMEM;
 
-#if !defined(SA_SHIRQ)
         if(request_irq(dev->irq, (void *)rtl8180_interrupt, IRQF_SHARED, dev->name, dev)){
-#else
-        if(request_irq(dev->irq, (void *)rtl8180_interrupt, SA_SHIRQ, dev->name, dev)){
-#endif
                 DMESGE("Error allocating IRQ %d",dev->irq);
                 return -1;
 	}else{
@@ -3169,43 +3075,6 @@
 	rtl8185_write_phy(dev, adr, data | 0x10000);
 }
 
-/* 70*3 = 210 ms
- * I hope this is enougth
- */
-#define MAX_PHY 70
-void write_phy(struct net_device *dev, u8 adr, u8 data)
-{
-	u32 phy;
-	int i;
-
-	phy = 0xff0000;
-	phy |= adr;
-	phy |= 0x80; /* this should enable writing */
-	phy |= (data<<8);
-
-	//PHY_ADR, PHY_R and PHY_W  are contig and treated as one dword
-	write_nic_dword(dev,PHY_ADR, phy);
-
-	phy= 0xffff00;
-	phy |= adr;
-
-	write_nic_dword(dev,PHY_ADR, phy);
-	for(i=0;i<MAX_PHY;i++){
-		phy=read_nic_dword(dev,PHY_ADR);
-		phy= phy & 0xff0000;
-		phy= phy >> 16;
-		if(phy == data){ //SUCCESS!
-			force_pci_posting(dev);
-			mdelay(3); //random value
-			return;
-		}else{
-			force_pci_posting(dev);
-			mdelay(3); //random value
-		}
-	}
-	DMESGW ("Phy writing %x %x failed!", adr,data);
-}
-
 void rtl8185_set_rate(struct net_device *dev)
 {
 	int i;
@@ -3335,7 +3204,6 @@
 }
 //
 // Change current and default preamble mode.
-// 2005.01.06, by rcnjko.
 //
 bool
 MgntActSet_802_11_PowerSaveMode(
@@ -3454,7 +3322,6 @@
 	MgntLinkKeepAlive(priv);
 
 	//YJ,add,080828,for LPS
-#ifdef ENABLE_LPS
 	if (priv->PowerProfile == POWER_PROFILE_BATTERY)
 		priv->bLeisurePs = true;
 	else if (priv->PowerProfile == POWER_PROFILE_AC) {
@@ -3464,7 +3331,6 @@
 
 	if(priv->ieee80211->state == IEEE80211_LINKED){
 		priv->link_detect.NumRxOkInPeriod = priv->ieee80211->NumRxDataInPeriod;
-		//printk("TxOk=%d RxOk=%d\n", priv->link_detect.NumTxOkInPeriod, priv->link_detect.NumRxOkInPeriod);
 		if(	priv->link_detect.NumRxOkInPeriod> 666 ||
 			priv->link_detect.NumTxOkInPeriod> 666 ) {
 			bBusyTraffic = true;
@@ -3481,7 +3347,6 @@
 			LeisurePSLeave(priv);
 	} else
 		LeisurePSLeave(priv);
-#endif
 	priv->link_detect.bBusyTraffic = bBusyTraffic;
 	priv->link_detect.NumRxOkInPeriod = 0;
 	priv->link_detect.NumTxOkInPeriod = 0;
@@ -3503,16 +3368,11 @@
 		if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
 			IPSLeave(dev);
 	}
-#ifdef RATE_ADAPT
        timer_rate_adaptive((unsigned long)dev);
-#endif
 	watch_dog_adaptive((unsigned long)dev);
-#ifdef SW_ANTE
         if(priv->bSwAntennaDiverity)
 			SwAntennaDiversityTimerCallback(dev);
-#endif
 	ieee80211_softmac_start_protocol(priv->ieee80211);
-
 	return 0;
 }
 
@@ -3748,7 +3608,7 @@
 	dev->wireless_handlers = &r8180_wx_handlers_def;
 
 	dev->type=ARPHRD_ETHER;
-	dev->watchdog_timeo = HZ*3; //added by david woo, 2007.12.13
+	dev->watchdog_timeo = HZ*3;
 
 	if (dev_alloc_name(dev, ifname) < 0){
                 DMESG("Oops: devname already taken! Trying wlan%%d...\n");
@@ -3864,8 +3724,7 @@
 		return ret;
 	}
 
-	printk(KERN_INFO "\nLinux kernel driver for RTL8180 \
-/ RTL8185 based WLAN cards\n");
+	printk(KERN_INFO "\nLinux kernel driver for RTL8180 / RTL8185 based WLAN cards\n");
 	printk(KERN_INFO "Copyright (c) 2004-2005, Andrea Merello\n");
 	DMESG("Initializing module");
 	DMESG("Wireless extensions version %d", WIRELESS_EXT);
@@ -4236,60 +4095,51 @@
         static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL};
 	static int readf_count = 0;
 
-#ifdef ENABLE_LPS
 	if(readf_count % 10 == 0)
 		priv->PowerProfile = read_acadapter_file("/proc/acpi/ac_adapter/AC0/state");
 
 	readf_count = (readf_count+1)%0xffff;
-#endif
-		{
-			// We should turn off LED before polling FF51[4].
+	/* We should turn off LED before polling FF51[4]. */
 
-			//Turn off LED.
-			btPSR = read_nic_byte(dev, PSR);
-			write_nic_byte(dev, PSR, (btPSR & ~BIT3));
+	/* Turn off LED. */
+	btPSR = read_nic_byte(dev, PSR);
+	write_nic_byte(dev, PSR, (btPSR & ~BIT3));
 
-			//It need to delay 4us suggested by Jong, 2008-01-16
-			udelay(4);
+	/* It need to delay 4us suggested by Jong, 2008-01-16 */
+	udelay(4);
 
-			//HW radio On/Off according to the value of FF51[4](config0)
-			btConfig0 = btPSR = read_nic_byte(dev, CONFIG0);
+	/* HW radio On/Off according to the value of FF51[4](config0) */
+	btConfig0 = btPSR = read_nic_byte(dev, CONFIG0);
 
-			//Turn on LED.
-			write_nic_byte(dev, PSR, btPSR| BIT3);
+	eRfPowerStateToSet = (btConfig0 & BIT4) ?  eRfOn : eRfOff;
 
-			eRfPowerStateToSet = (btConfig0 & BIT4) ?  eRfOn : eRfOff;
+	/* Turn LED back on when radio enabled */
+	if (eRfPowerStateToSet == eRfOn)
+		write_nic_byte(dev, PSR, btPSR | BIT3);
 
-			if((priv->ieee80211->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn))
-			{
-				priv->ieee80211->bHwRadioOff = false;
-				bActuallySet = true;
-			}
-			else if((priv->ieee80211->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff))
-			{
-				priv->ieee80211->bHwRadioOff = true;
-				bActuallySet = true;
-			}
+	if ((priv->ieee80211->bHwRadioOff == true) &&
+	   (eRfPowerStateToSet == eRfOn)) {
+		priv->ieee80211->bHwRadioOff = false;
+		bActuallySet = true;
+	} else if ((priv->ieee80211->bHwRadioOff == false) &&
+		  (eRfPowerStateToSet == eRfOff)) {
+		priv->ieee80211->bHwRadioOff = true;
+		bActuallySet = true;
+	}
 
-			if(bActuallySet)
-			{
-				MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
+	if (bActuallySet) {
+		MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
 
-				/* To update the UI status for Power status changed */
-                                if(priv->ieee80211->bHwRadioOff == true)
-                                        argv[1] = "RFOFF";
-                                else{
-                                        //if(!priv->RfOffReason)
-                                                argv[1] = "RFON";
-                                        //else
-                                        //      argv[1] = "RFOFF";
-                                }
-                                argv[0] = RadioPowerPath;
-                                argv[2] = NULL;
+		/* To update the UI status for Power status changed */
+		if (priv->ieee80211->bHwRadioOff == true)
+			argv[1] = "RFOFF";
+		else
+			argv[1] = "RFON";
+		argv[0] = RadioPowerPath;
+		argv[2] = NULL;
 
-                                call_usermodehelper(RadioPowerPath,argv,envp,1);
-			}
-		}
+		call_usermodehelper(RadioPowerPath, argv, envp, 1);
+	}
 }
 
 static u8 read_acadapter_file(char *filename)
diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c
index cbca58d..fc49078 100644
--- a/drivers/staging/rtl8187se/r8180_dm.c
+++ b/drivers/staging/rtl8187se/r8180_dm.c
@@ -282,30 +282,13 @@
 //		Dispatch DIG implementation according to RF.
 //
 void
-DynamicInitGain(
-	struct net_device *dev
-	)
+DynamicInitGain(struct net_device *dev)
 {
-	struct r8180_priv *priv = ieee80211_priv(dev);
-
-	switch(priv->rf_chip)
-	{
-		case RF_ZEBRA2:  // [AnnieWorkaround] For Zebra2, 2005-08-01.
-		case RF_ZEBRA4:
-			DIG_Zebra( dev );
-			break;
-
-		default:
-			printk("DynamicInitGain(): unknown RFChipID(%d) !!!\n", priv->rf_chip);
-			break;
-	}
+	DIG_Zebra(dev);
 }
 
 void rtl8180_hw_dig_wq (struct work_struct *work)
 {
-//      struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq);
-//      struct ieee80211_device * ieee = (struct ieee80211_device*)
-//                                             container_of(work, struct ieee80211_device, watch_dog_wq);
 	struct delayed_work *dwork = to_delayed_work(work);
         struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_dig_wq);
         struct net_device *dev = ieee->dev;
@@ -1310,44 +1293,24 @@
 	switch(u1bAntennaIndex)
 	{
 	case 0:
-		switch(priv->rf_chip)
-		{
-		case RF_ZEBRA2:
-		case RF_ZEBRA4:
-			// Mac register, main antenna
-			write_nic_byte(dev, ANTSEL, 0x03);
-			//base band
-			write_phy_cck(dev,0x11, 0x9b); // Config CCK RX antenna.
-			write_phy_ofdm(dev, 0x0d, 0x5c); // Config OFDM RX antenna.
+		/* Mac register, main antenna */
+		write_nic_byte(dev, ANTSEL, 0x03);
+		/* base band */
+		write_phy_cck(dev, 0x11, 0x9b); /* Config CCK RX antenna. */
+		write_phy_ofdm(dev, 0x0d, 0x5c); /* Config OFDM RX antenna. */
 
-
-			bAntennaSwitched = true;
-			break;
-
-		default:
-			printk("SetAntenna8185: unknown RFChipID(%d)\n", priv->rf_chip);
-			break;
-		}
+		bAntennaSwitched = true;
 		break;
 
 	case 1:
-		switch(priv->rf_chip)
-		{
-		case RF_ZEBRA2:
-		case RF_ZEBRA4:
-			// Mac register, aux antenna
-			write_nic_byte(dev, ANTSEL, 0x00);
-			//base band
-			write_phy_cck(dev, 0x11, 0xbb); // Config CCK RX antenna.
-			write_phy_ofdm(dev, 0x0d, 0x54); // Config OFDM RX antenna.
+		/* Mac register, aux antenna */
+		write_nic_byte(dev, ANTSEL, 0x00);
+		/* base band */
+		write_phy_cck(dev, 0x11, 0xbb); /* Config CCK RX antenna. */
+		write_phy_ofdm(dev, 0x0d, 0x54); /* Config OFDM RX antenna. */
 
-			bAntennaSwitched = true;
-			break;
+		bAntennaSwitched = true;
 
-		default:
-			printk("SetAntenna8185: unknown RFChipID(%d)\n", priv->rf_chip);
-			break;
-		}
 		break;
 
 	default:
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
index afe10f0..6edf5a4 100644
--- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c
+++ b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
@@ -854,134 +854,48 @@
 	btConfig3 = read_nic_byte(dev, CONFIG3);
 	write_nic_byte(dev, CONFIG3, (btConfig3 | CONFIG3_PARM_En));
 
-	switch (priv->rf_chip) {
-	case RF_ZEBRA2:
-		switch (eRFPowerState) {
-		case eRfOn:
-			RF_WriteReg(dev,0x4,0x9FF);
+	switch (eRFPowerState) {
+	case eRfOn:
+		write_nic_word(dev, 0x37C, 0x00EC);
 
-			write_nic_dword(dev, ANAPARAM, ANAPARM_ON);
-			write_nic_dword(dev, ANAPARAM2, ANAPARM2_ON);
+		/* turn on AFE */
+		write_nic_byte(dev, 0x54, 0x00);
+		write_nic_byte(dev, 0x62, 0x00);
 
-			write_nic_byte(dev, CONFIG4, priv->RFProgType);
+		/* turn on RF */
+		RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
+		RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
 
-			/* turn on CCK and OFDM */
-			u1bTmp = read_nic_byte(dev, 0x24E);
-			write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
-			break;
-		case eRfSleep:
-			break;
-		case eRfOff:
-			break;
-		default:
-			bResult = false;
-			break;
-		}
+		/* turn on RF again */
+		RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
+		RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
+
+		/* turn on BB */
+		write_phy_ofdm(dev, 0x10, 0x40);
+		write_phy_ofdm(dev, 0x12, 0x40);
+
+		/* Avoid power down at init time. */
+		write_nic_byte(dev, CONFIG4, priv->RFProgType);
+
+		u1bTmp = read_nic_byte(dev, 0x24E);
+		write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
 		break;
-	case RF_ZEBRA4:
-		switch (eRFPowerState) {
-		case eRfOn:
-			write_nic_word(dev, 0x37C, 0x00EC);
-
-			/* turn on AFE */
-			write_nic_byte(dev, 0x54, 0x00);
-			write_nic_byte(dev, 0x62, 0x00);
-
-			/* turn on RF */
-			RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
-			RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
-
-			/* turn on RF again */
-			RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
-			RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
-
-			/* turn on BB */
-			write_phy_ofdm(dev,0x10,0x40);
-			write_phy_ofdm(dev,0x12,0x40);
-
-			/* Avoid power down at init time. */
-			write_nic_byte(dev, CONFIG4, priv->RFProgType);
-
-			u1bTmp = read_nic_byte(dev, 0x24E);
-			write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
-			break;
-		case eRfSleep:
-			for (QueueID = 0, i = 0; QueueID < 6;) {
-				if (get_curr_tx_free_desc(dev, QueueID) == priv->txringcount) {
-					QueueID++;
-					continue;
-				} else {
-					priv->TxPollingTimes ++;
-					if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
-						bActionAllowed = false;
-						break;
-					} else
-						udelay(10);
-				}
-			}
-
-			if (bActionAllowed) {
-				/* turn off BB RXIQ matrix to cut off rx signal */
-				write_phy_ofdm(dev, 0x10, 0x00);
-				write_phy_ofdm(dev, 0x12, 0x00);
-
-				/* turn off RF */
-				RF_WriteReg(dev, 0x4, 0x0000);
-				RF_WriteReg(dev, 0x0, 0x0000);
-
-				/* turn off AFE except PLL */
-				write_nic_byte(dev, 0x62, 0xff);
-				write_nic_byte(dev, 0x54, 0xec);
-
-				mdelay(1);
-
-				{
-					int i = 0;
-					while (true) {
-						u8 tmp24F = read_nic_byte(dev, 0x24f);
-
-						if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
-							bTurnOffBB = true;
-							break;
-						} else {
-							udelay(10);
-							i++;
-							priv->TxPollingTimes++;
-
-							if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
-								bTurnOffBB = false;
-								break;
-							} else
-								udelay(10);
-						}
-					}
-				}
-
-				if (bTurnOffBB) {
-					/* turn off BB */
-					u1bTmp = read_nic_byte(dev, 0x24E);
-					write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
-
-					/* turn off AFE PLL */
-					write_nic_byte(dev, 0x54, 0xFC);
-					write_nic_word(dev, 0x37C, 0x00FC);
-				}
-			}
-			break;
-		case eRfOff:
-			for (QueueID = 0, i = 0; QueueID < 6;) {
-				if (get_curr_tx_free_desc(dev, QueueID) == priv->txringcount) {
-					QueueID++;
-					continue;
-				} else {
-					udelay(10);
-					i++;
-				}
-
-				if (i >= MAX_DOZE_WAITING_TIMES_85B)
+	case eRfSleep:
+		for (QueueID = 0, i = 0; QueueID < 6;) {
+			if (get_curr_tx_free_desc(dev, QueueID) == priv->txringcount) {
+				QueueID++;
+				continue;
+			} else {
+				priv->TxPollingTimes++;
+				if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
+					bActionAllowed = false;
 					break;
+				} else
+					udelay(10);
 			}
+		}
 
+		if (bActionAllowed) {
 			/* turn off BB RXIQ matrix to cut off rx signal */
 			write_phy_ofdm(dev, 0x10, 0x00);
 			write_phy_ofdm(dev, 0x12, 0x00);
@@ -998,22 +912,23 @@
 
 			{
 				int i = 0;
-
-				while (true)
-				{
+				while (true) {
 					u8 tmp24F = read_nic_byte(dev, 0x24f);
 
 					if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
 						bTurnOffBB = true;
 						break;
 					} else {
-						bTurnOffBB = false;
 						udelay(10);
 						i++;
-					}
+						priv->TxPollingTimes++;
 
-					if (i > MAX_POLLING_24F_TIMES_87SE)
-						break;
+						if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
+							bTurnOffBB = false;
+							break;
+						} else
+							udelay(10);
+					}
 				}
 			}
 
@@ -1022,15 +937,68 @@
 				u1bTmp = read_nic_byte(dev, 0x24E);
 				write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
 
-				/* turn off AFE PLL (80M) */
+				/* turn off AFE PLL */
 				write_nic_byte(dev, 0x54, 0xFC);
 				write_nic_word(dev, 0x37C, 0x00FC);
 			}
-			break;
-		default:
-			bResult = false;
-			printk("SetZebraRFPowerState8185(): unknown state to set: 0x%X!!!\n", eRFPowerState);
-			break;
+		}
+		break;
+	case eRfOff:
+		for (QueueID = 0, i = 0; QueueID < 6;) {
+			if (get_curr_tx_free_desc(dev, QueueID) == priv->txringcount) {
+				QueueID++;
+				continue;
+			} else {
+				udelay(10);
+				i++;
+			}
+
+			if (i >= MAX_DOZE_WAITING_TIMES_85B)
+				break;
+		}
+
+		/* turn off BB RXIQ matrix to cut off rx signal */
+		write_phy_ofdm(dev, 0x10, 0x00);
+		write_phy_ofdm(dev, 0x12, 0x00);
+
+		/* turn off RF */
+		RF_WriteReg(dev, 0x4, 0x0000);
+		RF_WriteReg(dev, 0x0, 0x0000);
+
+		/* turn off AFE except PLL */
+		write_nic_byte(dev, 0x62, 0xff);
+		write_nic_byte(dev, 0x54, 0xec);
+
+		mdelay(1);
+
+		{
+			int i = 0;
+
+			while (true) {
+				u8 tmp24F = read_nic_byte(dev, 0x24f);
+
+				if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
+					bTurnOffBB = true;
+					break;
+				} else {
+					bTurnOffBB = false;
+					udelay(10);
+					i++;
+				}
+
+				if (i > MAX_POLLING_24F_TIMES_87SE)
+					break;
+			}
+		}
+
+		if (bTurnOffBB) {
+			/* turn off BB */
+			u1bTmp = read_nic_byte(dev, 0x24E);
+			write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
+
+			/* turn off AFE PLL (80M) */
+			write_nic_byte(dev, 0x54, 0xFC);
+			write_nic_word(dev, 0x37C, 0x00FC);
 		}
 		break;
 	}
diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c
index 50309f2..a0ece1f 100644
--- a/drivers/staging/rtl8187se/r8185b_init.c
+++ b/drivers/staging/rtl8187se/r8185b_init.c
@@ -238,100 +238,12 @@
 	return data;
 }
 
-void
-SetOutputEnableOfRfPins(
-	struct net_device *dev
-	)
+void SetOutputEnableOfRfPins(struct net_device *dev)
 {
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-	switch(priv->rf_chip)
-	{
-	case RFCHIPID_RTL8225:
-	case RF_ZEBRA2:
-	case RF_ZEBRA4:
-		write_nic_word(dev, RFPinsEnable, 0x1bff);
-		//write_nic_word(dev, RFPinsEnable, 0x1fff);
-		break;
-	}
+	write_nic_word(dev, RFPinsEnable, 0x1bff);
 }
 
-void
-ZEBRA_RFSerialWrite(
-	struct net_device *dev,
-	u32			data2Write,
-	u8			totalLength,
-	u8			low2high
-	)
-{
-	ThreeWireReg		twreg;
-	int 				i;
-	u16				oval,oval2,oval3;
-	u32				mask;
-	u16				UshortBuffer;
-
-	u8			u1bTmp;
-	// RTL8187S HSSI Read/Write Function
-	u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
-	u1bTmp |=   RF_SW_CFG_SI;   //reg08[1]=1 Serial Interface(SI)
-	write_nic_byte(dev, RF_SW_CONFIG, u1bTmp);
-	UshortBuffer = read_nic_word(dev, RFPinsOutput);
-	oval = UshortBuffer & 0xfff8; // We shall clear bit0, 1, 2 first, 2005.10.28, by rcnjko.
-
-	oval2 = read_nic_word(dev, RFPinsEnable);
-	oval3 = read_nic_word(dev, RFPinsSelect);
-
-	// <RJ_NOTE> 3-wire should be controled by HW when we finish SW 3-wire programming. 2005.08.10, by rcnjko.
-	oval3 &= 0xfff8;
-
-	write_nic_word(dev, RFPinsEnable, (oval2|0x0007)); // Set To Output Enable
-	write_nic_word(dev, RFPinsSelect, (oval3|0x0007)); // Set To SW Switch
-	udelay(10);
-
-	// Add this to avoid hardware and software 3-wire conflict.
-	// 2005.03.01, by rcnjko.
-	twreg.longData = 0;
-	twreg.struc.enableB = 1;
-	write_nic_word(dev, RFPinsOutput, (twreg.longData|oval)); // Set SI_EN (RFLE)
-	udelay(2);
-	twreg.struc.enableB = 0;
-	write_nic_word(dev, RFPinsOutput, (twreg.longData|oval)); // Clear SI_EN (RFLE)
-	udelay(10);
-
-	mask = (low2high)?0x01:((u32)0x01<<(totalLength-1));
-
-	for(i=0; i<totalLength/2; i++)
-	{
-		twreg.struc.data = ((data2Write&mask)!=0) ? 1 : 0;
-		write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
-		twreg.struc.clk = 1;
-		write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
-		write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
-
-		mask = (low2high)?(mask<<1):(mask>>1);
-		twreg.struc.data = ((data2Write&mask)!=0) ? 1 : 0;
-		write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
-		write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
-		twreg.struc.clk = 0;
-		write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
-		mask = (low2high)?(mask<<1):(mask>>1);
-	}
-
-	twreg.struc.enableB = 1;
-	twreg.struc.clk = 0;
-	twreg.struc.data = 0;
-	write_nic_word(dev, RFPinsOutput, twreg.longData|oval);
-	udelay(10);
-
-	write_nic_word(dev, RFPinsOutput, oval|0x0004);
-	write_nic_word(dev, RFPinsSelect, oval3|0x0000);
-
-	SetOutputEnableOfRfPins(dev);
-}
-//by amy
-
-
-int
+static int
 HwHSSIThreeWire(
 	struct net_device *dev,
 	u8			*pDataBuf,
@@ -469,420 +381,30 @@
 
 	return bResult;
 }
-//by amy
-
-int
-HwThreeWire(
-	struct net_device *dev,
-	u8			*pDataBuf,
-	u8			nDataBufBitCnt,
-	int			bHold,
-	int			bWrite
-	)
-{
-	int	bResult = 1;
-	u8	TryCnt;
-	u8	u1bTmp;
-
-	do
-	{
-		// Check if WE and RE are cleared.
-		for(TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++)
-		{
-			u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
-			if( (u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0 )
-			{
-				break;
-			}
-			udelay(10);
-		}
-		if (TryCnt == TC_3W_POLL_MAX_TRY_CNT)
-			panic("HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n", u1bTmp);
-
-		// Fill up data buffer for write operation.
-		if(nDataBufBitCnt == 16)
-		{
-			write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
-		}
-		else if(nDataBufBitCnt == 64)
-		{
-			write_nic_dword(dev, SW_3W_DB0, *((u32 *)pDataBuf));
-			write_nic_dword(dev, SW_3W_DB1, *((u32 *)(pDataBuf + 4)));
-		}
-		else
-		{
-			int idx;
-			int ByteCnt = nDataBufBitCnt / 8;
-
-			if ((nDataBufBitCnt % 8) != 0)
-				panic("HwThreeWire(): nDataBufBitCnt(%d) should be multiple of 8!!!\n",
-				nDataBufBitCnt);
-
-			if (nDataBufBitCnt > 64)
-				panic("HwThreeWire(): nDataBufBitCnt(%d) should <= 64!!!\n",
-				nDataBufBitCnt);
-
-			for(idx = 0; idx < ByteCnt; idx++)
-			{
-				write_nic_byte(dev, (SW_3W_DB0+idx), *(pDataBuf+idx));
-			}
-		}
-
-		// Fill up length field.
-		u1bTmp = (u8)(nDataBufBitCnt - 1); // Number of bits - 1.
-		if(bHold)
-			u1bTmp |= SW_3W_CMD0_HOLD;
-		write_nic_byte(dev, SW_3W_CMD0, u1bTmp);
-
-		// Set up command: WE or RE.
-		if(bWrite)
-		{
-			write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_WE);
-		}
-		else
-		{
-			write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_RE);
-		}
-
-		// Check if WE and RE are cleared and DONE is set.
-		for(TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++)
-		{
-			u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
-			if( (u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0 &&
-				(u1bTmp & SW_3W_CMD1_DONE) != 0 )
-			{
-				break;
-			}
-			udelay(10);
-		}
-		if(TryCnt == TC_3W_POLL_MAX_TRY_CNT)
-		{
-			//RT_ASSERT(TryCnt != TC_3W_POLL_MAX_TRY_CNT,
-			//	("HwThreeWire(): CmdReg: %#X RE|WE bits are not clear or DONE is not set!!\n", u1bTmp));
-			// Workaround suggested by wcchu: clear WE here. 2006.07.07, by rcnjko.
-			write_nic_byte(dev, SW_3W_CMD1, 0);
-		}
-
-		// Read back data for read operation.
-		// <RJ_TODO> I am not sure if this is correct output format of a read operation.
-		if(bWrite == 0)
-		{
-			if(nDataBufBitCnt == 16)
-			{
-				*((u16 *)pDataBuf) = read_nic_word(dev, SW_3W_DB0);
-			}
-			else if(nDataBufBitCnt == 64)
-			{
-				*((u32 *)pDataBuf) = read_nic_dword(dev, SW_3W_DB0);
-				*((u32 *)(pDataBuf + 4)) = read_nic_dword(dev, SW_3W_DB1);
-			}
-			else
-			{
-				int idx;
-				int ByteCnt = nDataBufBitCnt / 8;
-
-				if ((nDataBufBitCnt % 8) != 0)
-					panic("HwThreeWire(): nDataBufBitCnt(%d) should be multiple of 8!!!\n",
-					nDataBufBitCnt);
-
-				if (nDataBufBitCnt > 64)
-					panic("HwThreeWire(): nDataBufBitCnt(%d) should <= 64!!!\n",
-					nDataBufBitCnt);
-
-				for(idx = 0; idx < ByteCnt; idx++)
-				{
-					*(pDataBuf+idx) = read_nic_byte(dev, (SW_3W_DB0+idx));
-				}
-			}
-		}
-
-	}while(0);
-
-	return bResult;
-}
-
 
 void
-RF_WriteReg(
-	struct net_device *dev,
-	u8		offset,
-	u32		data
-	)
+RF_WriteReg(struct net_device *dev, u8 offset, u32 data)
 {
-	//RFReg			reg;
-	u32			data2Write;
-	u8			len;
-	u8			low2high;
-	//u32			RF_Read = 0;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
+	u32 data2Write;
+	u8 len;
 
+	/* Pure HW 3-wire. */
+	data2Write = (data << 4) | (u32)(offset & 0x0f);
+	len = 16;
 
-	switch(priv->rf_chip)
-	{
-	case RFCHIPID_RTL8225:
-	case RF_ZEBRA2:		// Annie 2006-05-12.
-	case RF_ZEBRA4:        //by amy
-		switch(priv->RegThreeWireMode)
-		{
-		case SW_THREE_WIRE:
-			{ // Perform SW 3-wire programming by driver.
-				data2Write = (data << 4) | (u32)(offset & 0x0f);
-				len = 16;
-				low2high = 0;
-				ZEBRA_RFSerialWrite(dev, data2Write, len, low2high);
-       			}
-			break;
-
- 		case HW_THREE_WIRE:
-			{ // Pure HW 3-wire.
-				data2Write = (data << 4) | (u32)(offset & 0x0f);
-				len = 16;
-				HwThreeWire(
-					dev,
-					(u8 *)(&data2Write),	// pDataBuf,
-					len,				// nDataBufBitCnt,
-					0,					// bHold,
-					1);					// bWrite
-         		}
-			break;
-			case HW_THREE_WIRE_PI: //Parallel Interface
-			{ // Pure HW 3-wire.
-				data2Write = (data << 4) | (u32)(offset & 0x0f);
-				len = 16;
-					HwHSSIThreeWire(
-						dev,
-						(u8*)(&data2Write),	// pDataBuf,
-						len,						// nDataBufBitCnt,
-						0, 					// bSI
-						1); 					// bWrite
-
-                                //printk("33333\n");
-			}
-			break;
-
-			case HW_THREE_WIRE_SI: //Serial Interface
-			{ // Pure HW 3-wire.
-				data2Write = (data << 4) | (u32)(offset & 0x0f);
-				len = 16;
-//                                printk(" enter  ZEBRA_RFSerialWrite\n ");
-//                                low2high = 0;
-//                                ZEBRA_RFSerialWrite(dev, data2Write, len, low2high);
-
-				HwHSSIThreeWire(
-					dev,
-					(u8*)(&data2Write),	// pDataBuf,
-					len,						// nDataBufBitCnt,
-					1, 					// bSI
-					1); 					// bWrite
-
-//                                 printk(" exit ZEBRA_RFSerialWrite\n ");
-			}
-			break;
-
-
-		default:
-			DMESGE("RF_WriteReg(): invalid RegThreeWireMode(%d) !!!", priv->RegThreeWireMode);
-			break;
-		}
-		break;
-
-	default:
-		DMESGE("RF_WriteReg(): unknown RFChipID: %#X", priv->rf_chip);
-		break;
-	}
+	HwHSSIThreeWire(dev, (u8 *)(&data2Write), len, 1, 1);
 }
 
-
-void
-ZEBRA_RFSerialRead(
-	struct net_device *dev,
-	u32		data2Write,
-	u8		wLength,
-	u32		*data2Read,
-	u8		rLength,
-	u8		low2high
-	)
+u32 RF_ReadReg(struct net_device *dev, u8 offset)
 {
-	ThreeWireReg	twreg;
-	int				i;
-	u16			oval,oval2,oval3,tmp, wReg80;
-	u32			mask;
-	u8			u1bTmp;
-	ThreeWireReg	tdata;
-	//PHAL_DATA_8187	pHalData = GetHalData8187(pAdapter);
-	{ // RTL8187S HSSI Read/Write Function
-		u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
-		u1bTmp |=   RF_SW_CFG_SI;   //reg08[1]=1 Serial Interface(SI)
-		write_nic_byte(dev, RF_SW_CONFIG, u1bTmp);
-	}
+	u32 data2Write;
+	u8 wlen;
+	u32 dataRead;
 
-	wReg80 = oval = read_nic_word(dev, RFPinsOutput);
-	oval2 = read_nic_word(dev, RFPinsEnable);
-	oval3 = read_nic_word(dev, RFPinsSelect);
-
-	write_nic_word(dev, RFPinsEnable, oval2|0xf);
-	write_nic_word(dev, RFPinsSelect, oval3|0xf);
-
-	*data2Read = 0;
-
-	// We must clear BIT0-3 here, otherwise,
-	// SW_Enalbe will be true when we first call ZEBRA_RFSerialRead() after 8187MPVC open,
-	// which will cause the value read become 0. 2005.04.11, by rcnjko.
-	oval &= ~0xf;
-
-	// Avoid collision with hardware three-wire.
-	twreg.longData = 0;
-	twreg.struc.enableB = 1;
-	write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(4);
-
-	twreg.longData = 0;
-	twreg.struc.enableB = 0;
-	twreg.struc.clk = 0;
-	twreg.struc.read_write = 0;
-	write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(5);
-
-	mask = (low2high) ? 0x01 : ((u32)0x01<<(32-1));
-	for(i = 0; i < wLength/2; i++)
-	{
-		twreg.struc.data = ((data2Write&mask) != 0) ? 1 : 0;
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(1);
-		twreg.struc.clk = 1;
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-
-		mask = (low2high) ? (mask<<1): (mask>>1);
-
-		if(i == 2)
-		{
-			// Commented out by Jackie, 2004.08.26. <RJ_NOTE> We must comment out the following two lines for we cannot pull down VCOPDN during RF Serail Read.
-			//PlatformEFIOWrite2Byte(pAdapter, RFPinsEnable, 0xe);     // turn off data enable
-			//PlatformEFIOWrite2Byte(pAdapter, RFPinsSelect, 0xe);
-
-			twreg.struc.read_write=1;
-			write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-			twreg.struc.clk = 0;
-			write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-			break;
-		}
-		twreg.struc.data = ((data2Write&mask) != 0) ? 1: 0;
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-
-		twreg.struc.clk = 0;
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(1);
-
-		mask = (low2high) ? (mask<<1) : (mask>>1);
-	}
-
-	twreg.struc.clk = 0;
-	twreg.struc.data = 0;
-	write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-	mask = (low2high) ? 0x01 : ((u32)0x01 << (12-1));
-
-	//
-	// 061016, by rcnjko:
-	// We must set data pin to HW controled, otherwise RF can't driver it and
-	// value RF register won't be able to read back properly.
-	//
-	write_nic_word(dev, RFPinsEnable, ( ((oval2|0x0E) & (~0x01))) );
-
-	for(i = 0; i < rLength; i++)
-	{
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(1);
-		twreg.struc.clk = 1;
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-		tmp = read_nic_word(dev, RFPinsInput);
-		tdata.longData = tmp;
-		*data2Read |= tdata.struc.clk ? mask : 0;
-
-		twreg.struc.clk = 0;
-		write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-
-		mask = (low2high) ? (mask<<1) : (mask>>1);
-	}
-	twreg.struc.enableB = 1;
-	twreg.struc.clk = 0;
-	twreg.struc.data = 0;
-	twreg.struc.read_write = 1;
-	write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-
-	//PlatformEFIOWrite2Byte(pAdapter, RFPinsEnable, oval2|0x8);   // Set To Output Enable
-	write_nic_word(dev, RFPinsEnable, oval2);   // Set To Output Enable, <RJ_NOTE> We cannot enable BIT3 here, otherwise, we will failed to switch channel. 2005.04.12.
-	//PlatformEFIOWrite2Byte(pAdapter, RFPinsEnable, 0x1bff);
-	write_nic_word(dev, RFPinsSelect, oval3);   // Set To SW Switch
-	//PlatformEFIOWrite2Byte(pAdapter, RFPinsSelect, 0x0488);
-	write_nic_word(dev, RFPinsOutput, 0x3a0);
-	//PlatformEFIOWrite2Byte(pAdapter, RFPinsOutput, 0x0480);
-}
-
-
-u32
-RF_ReadReg(
-	struct net_device *dev,
-	u8		offset
-	)
-{
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	u32			data2Write;
-	u8			wlen;
-	u8			rlen;
-	u8			low2high;
-	u32			dataRead;
-
-	switch(priv->rf_chip)
-	{
-	case RFCHIPID_RTL8225:
-	case RF_ZEBRA2:
-	case RF_ZEBRA4:
-		switch(priv->RegThreeWireMode)
-		{
-			case HW_THREE_WIRE_PI: // For 87S  Parallel Interface.
-			{
-				data2Write = ((u32)(offset&0x0f));
-				wlen=16;
-				HwHSSIThreeWire(
-					dev,
-					(u8*)(&data2Write),	// pDataBuf,
-					wlen,					// nDataBufBitCnt,
-					0, 					// bSI
-					0); 					// bWrite
-				dataRead= data2Write;
-			}
-			break;
-
-			case HW_THREE_WIRE_SI: // For 87S Serial Interface.
-			{
-				data2Write = ((u32)(offset&0x0f)) ;
-				wlen=16;
-				HwHSSIThreeWire(
-					dev,
-					(u8*)(&data2Write),	// pDataBuf,
-					wlen,					// nDataBufBitCnt,
-					1, 					// bSI
-					0					// bWrite
-					);
-				dataRead= data2Write;
-			}
-			break;
-
-			// Perform SW 3-wire programming by driver.
-			default:
-			{
-				data2Write = ((u32)(offset&0x1f)) << 27; // For Zebra E-cut. 2005.04.11, by rcnjko.
-				wlen = 6;
-				rlen = 12;
-				low2high = 0;
-				ZEBRA_RFSerialRead(dev, data2Write, wlen,&dataRead,rlen, low2high);
-			}
-			break;
-		}
-		break;
-	default:
-		dataRead = 0;
-		break;
-	}
+	data2Write = ((u32)(offset & 0x0f));
+	wlen = 16;
+	HwHSSIThreeWire(dev, (u8 *)(&data2Write), wlen, 1, 0);
+	dataRead = data2Write;
 
 	return dataRead;
 }
@@ -1043,15 +565,12 @@
 
 	// Page0 : reg0-reg15
 
-//	RF_WriteReg(dev, 0x00, 0x003f);			mdelay(1);//1
 	RF_WriteReg(dev, 0x00, 0x009f);      	mdelay(1);// 1
 
 	RF_WriteReg(dev, 0x01, 0x06e0);			mdelay(1);
 
-//	RF_WriteReg(dev, 0x02, 0x004c);			mdelay(1);//2
 	RF_WriteReg(dev, 0x02, 0x004d);			mdelay(1);// 2
 
-//	RF_WriteReg(dev, 0x03, 0x0000);			mdelay(1);//3
 	RF_WriteReg(dev, 0x03, 0x07f1);			mdelay(1);// 3
 
 	RF_WriteReg(dev, 0x04, 0x0975);			mdelay(1);
@@ -1080,8 +599,6 @@
 
 	RF_WriteReg(dev, 0x07, 0x01A0);			mdelay(1);
 // Don't write RF23/RF24 to make a difference between 87S C cut and D cut. asked by SD3 stevenl.
-//	RF_WriteReg(dev, 0x08, 0x0597);			mdelay(1);
-//	RF_WriteReg(dev, 0x09, 0x050a);			mdelay(1);
 	RF_WriteReg(dev, 0x0a, 0x0001);			mdelay(1);
 	RF_WriteReg(dev, 0x0b, 0x0418);			mdelay(1);
 
@@ -1097,7 +614,6 @@
 
 	RF_WriteReg(dev, 0x0f, 0x0acc);			mdelay(1);
 
-//	RF_WriteReg(dev, 0x00, 0x017f);			mdelay(1);//6
 	RF_WriteReg(dev, 0x00, 0x01d7);			mdelay(1);// 6
 
 	RF_WriteReg(dev, 0x03, 0x0e00);			mdelay(1);
@@ -1106,20 +622,14 @@
 	{
 		RF_WriteReg(dev, 0x01, i);                     mdelay(1);
 		RF_WriteReg(dev, 0x02, ZEBRA_RF_RX_GAIN_TABLE[i]); mdelay(1);
-		//DbgPrint("RF - 0x%x = 0x%x", i, ZEBRA_RF_RX_GAIN_TABLE[i]);
 	}
 
 	RF_WriteReg(dev, 0x05, 0x0203);			mdelay(1); 	/// 203, 343
-	//RF_WriteReg(dev, 0x06, 0x0300);			mdelay(1);	// 400
 	RF_WriteReg(dev, 0x06, 0x0200);			mdelay(1);	// 400
 
 	RF_WriteReg(dev, 0x00, 0x0137);			mdelay(1);	// switch to reg16-reg30, and HSSI disable 137
 	mdelay(10); 	// Deay 10 ms. //0xfd
 
-//	RF_WriteReg(dev, 0x0c, 0x09be);			mdelay(1);	// 7
-	//RF_WriteReg(dev, 0x0c, 0x07be);			mdelay(1);
-	//mdelay(10); 	// Deay 10 ms. //0xfd
-
 	RF_WriteReg(dev, 0x0d, 0x0008);			mdelay(1);	// Z4 synthesizer loop filter setting, 392
 	mdelay(10); 	// Deay 10 ms. //0xfd
 
@@ -1165,10 +675,8 @@
 		RF_WriteReg(dev, 0x0f, 0x0acc);			mdelay(1);
 	}
 //by amy 080312
-//	RF_WriteReg(dev, 0x0f, 0x0acc);			mdelay(1);  //-by amy 080312
 
 	RF_WriteReg(dev, 0x00, 0x00bf);			mdelay(1); // switch to reg0-reg15, and HSSI enable
-//	RF_WriteReg(dev, 0x0d, 0x009f);			mdelay(1); // Rx BB start calibration, 00c//-edward
 	RF_WriteReg(dev, 0x0d, 0x08df);			mdelay(1); // Rx BB start calibration, 00c//+edward
 	RF_WriteReg(dev, 0x02, 0x004d);			mdelay(1); // temperature meter off
 	RF_WriteReg(dev, 0x04, 0x0975);			mdelay(1); // Rx mode
@@ -1217,13 +725,10 @@
 	// AGC.txt
 	//=============================================================================
 
-//	PlatformIOWrite4Byte( dev, PhyAddr, 0x00001280);	// Annie, 2006-05-05
 	write_phy_ofdm(dev, 0x00, 0x12);
-	//WriteBBPortUchar(dev, 0x00001280);
 
 	for (i=0; i<128; i++)
 	{
-		//DbgPrint("AGC - [%x+1] = 0x%x\n", i, ZEBRA_AGC[i+1]);
 
 		data = ZEBRA_AGC[i+1];
 		data = data << 8;
@@ -1239,7 +744,6 @@
 	}
 
 	PlatformIOWrite4Byte( dev, PhyAddr, 0x00001080);	// Annie, 2006-05-05
-	//WriteBBPortUchar(dev, 0x00001080);
 
 	//=============================================================================
 
@@ -1252,8 +756,6 @@
 		u4bRegOffset=i;
 		u4bRegValue=OFDM_CONFIG[i];
 
-		//DbgPrint("OFDM - 0x%x = 0x%x\n", u4bRegOffset, u4bRegValue);
-
 		WriteBBPortUchar(dev,
 						(0x00000080 |
 						(u4bRegOffset & 0x7f) |
@@ -1277,9 +779,6 @@
 	)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	//unsigned char* IGTable;
-	//u8			DIG_CurrentInitialGain = 4;
-	//unsigned char u1Tmp;
 
 	//lzm add 080826
 	if(priv->eRFPowerState != eRfOn)
@@ -1291,81 +790,59 @@
 		return;
 	}
 
-	switch(priv->rf_chip)
-	{
-	case RF_ZEBRA4:
-		// Dynamic set initial gain, follow 87B
-		switch(priv->InitialGain)
-		{
-			case 1: //m861dBm
-				//DMESG("RTL8187 + 8225 Initial Gain State 1: -82 dBm \n");
-				write_phy_ofdm(dev, 0x17, 0x26);	mdelay(1);
-				write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
-				write_phy_ofdm(dev, 0x05, 0xfa);	mdelay(1);
-				break;
-
-			case 2: //m862dBm
-				//DMESG("RTL8187 + 8225 Initial Gain State 2: -82 dBm \n");
-				write_phy_ofdm(dev, 0x17, 0x36);	mdelay(1);
-				write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
-				write_phy_ofdm(dev, 0x05, 0xfa);	mdelay(1);
-				break;
-
-			case 3: //m863dBm
-				//DMESG("RTL8187 + 8225 Initial Gain State 3: -82 dBm \n");
-				write_phy_ofdm(dev, 0x17, 0x36);	mdelay(1);
-				write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
-				write_phy_ofdm(dev, 0x05, 0xfb);	mdelay(1);
-				break;
-
-			case 4: //m864dBm
-				//DMESG("RTL8187 + 8225 Initial Gain State 4: -78 dBm \n");
-				write_phy_ofdm(dev, 0x17, 0x46);	mdelay(1);
-				write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
-				write_phy_ofdm(dev, 0x05, 0xfb);	mdelay(1);
-				break;
-
-			case 5: //m82dBm
-				//DMESG("RTL8187 + 8225 Initial Gain State 5: -74 dBm \n");
-				write_phy_ofdm(dev, 0x17, 0x46);	mdelay(1);
-				write_phy_ofdm(dev, 0x24, 0x96);	mdelay(1);
-				write_phy_ofdm(dev, 0x05, 0xfb);	mdelay(1);
-				break;
-
-			case 6: //m78dBm
-				//DMESG ("RTL8187 + 8225 Initial Gain State 6: -70 dBm \n");
-				write_phy_ofdm(dev, 0x17, 0x56);	mdelay(1);
-				write_phy_ofdm(dev, 0x24, 0x96);	mdelay(1);
-				write_phy_ofdm(dev, 0x05, 0xfc);	mdelay(1);
-				break;
-
-			case 7: //m74dBm
-				//DMESG("RTL8187 + 8225 Initial Gain State 7: -66 dBm \n");
-				write_phy_ofdm(dev, 0x17, 0x56);	mdelay(1);
-				write_phy_ofdm(dev, 0x24, 0xa6);	mdelay(1);
-				write_phy_ofdm(dev, 0x05, 0xfc);	mdelay(1);
-				break;
-
-			case 8:
-				//DMESG("RTL8187 + 8225 Initial Gain State 8:\n");
-				write_phy_ofdm(dev, 0x17, 0x66);	mdelay(1);
-				write_phy_ofdm(dev, 0x24, 0xb6);	mdelay(1);
-				write_phy_ofdm(dev, 0x05, 0xfc);	mdelay(1);
-				break;
-
-
-			default:	//MP
-				//DMESG("RTL8187 + 8225 Initial Gain State 1: -82 dBm (default)\n");
-				write_phy_ofdm(dev, 0x17, 0x26);	mdelay(1);
-				write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
-				write_phy_ofdm(dev, 0x05, 0xfa);	mdelay(1);
-				break;
-		}
+	switch (priv->InitialGain) {
+	case 1: /* m861dBm */
+		write_phy_ofdm(dev, 0x17, 0x26);	mdelay(1);
+		write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
+		write_phy_ofdm(dev, 0x05, 0xfa);	mdelay(1);
 		break;
 
+	case 2: /* m862dBm */
+		write_phy_ofdm(dev, 0x17, 0x36);	mdelay(1);
+		write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
+		write_phy_ofdm(dev, 0x05, 0xfa);	mdelay(1);
+		break;
 
-	default:
-		DMESG("UpdateInitialGain(): unknown RFChipID: %#X\n", priv->rf_chip);
+	case 3: /* m863dBm */
+		write_phy_ofdm(dev, 0x17, 0x36);	mdelay(1);
+		write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
+		write_phy_ofdm(dev, 0x05, 0xfb);	mdelay(1);
+		break;
+
+	case 4: /* m864dBm */
+		write_phy_ofdm(dev, 0x17, 0x46);	mdelay(1);
+		write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
+		write_phy_ofdm(dev, 0x05, 0xfb);	mdelay(1);
+		break;
+
+	case 5: /* m82dBm */
+		write_phy_ofdm(dev, 0x17, 0x46);	mdelay(1);
+		write_phy_ofdm(dev, 0x24, 0x96);	mdelay(1);
+		write_phy_ofdm(dev, 0x05, 0xfb);	mdelay(1);
+		break;
+
+	case 6: /* m78dBm */
+		write_phy_ofdm(dev, 0x17, 0x56);	mdelay(1);
+		write_phy_ofdm(dev, 0x24, 0x96);	mdelay(1);
+		write_phy_ofdm(dev, 0x05, 0xfc);	mdelay(1);
+		break;
+
+	case 7: /* m74dBm */
+		write_phy_ofdm(dev, 0x17, 0x56);	mdelay(1);
+		write_phy_ofdm(dev, 0x24, 0xa6);	mdelay(1);
+		write_phy_ofdm(dev, 0x05, 0xfc);	mdelay(1);
+		break;
+
+	case 8:
+		write_phy_ofdm(dev, 0x17, 0x66);	mdelay(1);
+		write_phy_ofdm(dev, 0x24, 0xb6);	mdelay(1);
+		write_phy_ofdm(dev, 0x05, 0xfc);	mdelay(1);
+		break;
+
+	default:	/* MP */
+		write_phy_ofdm(dev, 0x17, 0x26);	mdelay(1);
+		write_phy_ofdm(dev, 0x24, 0x86);	mdelay(1);
+		write_phy_ofdm(dev, 0x05, 0xfa);	mdelay(1);
 		break;
 	}
 }
@@ -1379,13 +856,11 @@
 	struct net_device *dev
 )
 {
-	//struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	u32	u4bRfReg;
 
 	u4bRfReg = RF_ReadReg(dev, 0x02);
 
 	// Enable Thermal meter indication.
-	//printk("InitTxPwrTracking87SE(): Enable thermal meter indication, Write RF[0x02] = %#x", u4bRfReg|PWR_METER_EN);
 	RF_WriteReg(dev, 0x02, u4bRfReg|PWR_METER_EN);			mdelay(1);
 }
 
@@ -1397,21 +872,14 @@
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
        write_nic_dword(dev, RCR, priv->ReceiveConfig);
 	   priv->RFProgType = read_nic_byte(dev, CONFIG4) & 0x03;
-     	// RF config
-	switch(priv->rf_chip)
-	{
-	case RF_ZEBRA2:
-	case RF_ZEBRA4:
-		ZEBRA_Config_85BASIC_HardCode( dev);
-		break;
-	}
+	/*  RF config */
+	ZEBRA_Config_85BASIC_HardCode(dev);
 //{by amy 080312
 	// Set default initial gain state to 4, approved by SD3 DZ, by Bruce, 2007-06-06.
 	if(priv->bDigMechanism)
 	{
 		if(priv->InitialGain == 0)
 			priv->InitialGain = 4;
-		//printk("PhyConfig8185(): DIG is enabled, set default initial gain index to %d\n", priv->InitialGain);
 	}
 
 	//
@@ -1429,34 +897,17 @@
 	return;
 }
 
-
-
-
 void
 HwConfigureRTL8185(
 		struct net_device *dev
 		)
 {
 	//RTL8185_TODO: Determine Retrylimit, TxAGC, AutoRateFallback control.
-//	u8		bUNIVERSAL_CONTROL_RL = 1;
         u8              bUNIVERSAL_CONTROL_RL = 0;
-
 	u8		bUNIVERSAL_CONTROL_AGC = 1;
 	u8		bUNIVERSAL_CONTROL_ANT = 1;
 	u8		bAUTO_RATE_FALLBACK_CTL = 1;
 	u8		val8;
-	//struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	//struct ieee80211_device *ieee = priv->ieee80211;
-      	//if(IS_WIRELESS_MODE_A(dev) || IS_WIRELESS_MODE_G(dev))
-//{by amy 080312	if((ieee->mode == IEEE_G)||(ieee->mode == IEEE_A))
-//	{
-//		write_nic_word(dev, BRSR, 0xffff);
-//	}
-//	else
-//	{
-//		write_nic_word(dev, BRSR, 0x000f);
-//	}
-//by amy 080312}
         write_nic_word(dev, BRSR, 0x0fff);
 	// Retry limit
 	val8 = read_nic_byte(dev, CW_CONF);
@@ -1507,20 +958,11 @@
 		val8 |= RATE_FALLBACK_CTL_ENABLE | RATE_FALLBACK_CTL_AUTO_STEP1;
 
 		// <RJ_TODO_8185B> We shall set up the ARFR according to user's setting.
-		//write_nic_word(dev, ARFR, 0x0fff); // set 1M ~ 54M
-//by amy
-	        // Aadded by Roger, 2007.11.15.
 	        PlatformIOWrite2Byte(dev, ARFR, 0x0fff); //set 1M ~ 54Mbps.
-//by amy
-	}
-	else
-	{
 	}
 	write_nic_byte(dev, RATE_FALLBACK, val8);
 }
 
-
-
 static void
 MacConfig_85BASIC_HardCode(
 	struct net_device *dev)
@@ -1548,14 +990,11 @@
                 {
                     u4bRegOffset |= (u4bPageIndex << 8);
                 }
-                //DbgPrint("MAC - 0x%x = 0x%x\n", u4bRegOffset, u4bRegValue);
 		write_nic_byte(dev, u4bRegOffset, (u8)u4bRegValue);
 	}
 	//============================================================================
 }
 
-
-
 static void
 MacConfig_85BASIC(
 	struct net_device *dev)
@@ -1578,8 +1017,6 @@
 	PlatformIOWrite1Byte(dev, 0x1F8, 0x00);
 
 	// Asked for by SD3 CM Lin, 2006.06.27, by rcnjko.
-	//PlatformIOWrite4Byte(dev, RFTiming, 0x00004001);
-//by amy
 	// power save parameter based on "87SE power save parameters 20071127.doc", as follow.
 
 	//Enable DA10 TX power saving
@@ -1598,35 +1035,18 @@
 	write_nic_word(dev, 0x378, 0x0560);
 	write_nic_word(dev, 0x37A, 0x0560);
 	write_nic_word(dev, 0x37C, 0x00EC);
-//	write_nic_word(dev, 0x37E, 0x00FE);//-edward
 	write_nic_word(dev, 0x37E, 0x00EC);//+edward
        write_nic_byte(dev, 0x24E,0x01);
-//by amy
-
 }
 
-
-
-
 u8
 GetSupportedWirelessMode8185(
 	struct net_device *dev
 )
 {
 	u8			btSupportedWirelessMode = 0;
-	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 
-	switch(priv->rf_chip)
-	{
-	case RF_ZEBRA2:
-	case RF_ZEBRA4:
-		btSupportedWirelessMode = (WIRELESS_MODE_B | WIRELESS_MODE_G);
-		break;
-	default:
-		btSupportedWirelessMode = WIRELESS_MODE_B;
-		break;
-	}
-
+	btSupportedWirelessMode = (WIRELESS_MODE_B | WIRELESS_MODE_G);
 	return btSupportedWirelessMode;
 }
 
@@ -1641,7 +1061,6 @@
 	struct ieee80211_device *ieee = priv->ieee80211;
 	AC_CODING	eACI;
 	AC_PARAM	AcParam;
-	//PSTA_QOS	pStaQos = Adapter->MgntInfo.pStaQos;
 	u8	bFollowLegacySetting = 0;
 	u8   u1bAIFS;
 
@@ -1663,40 +1082,14 @@
 	ChnlAccessSetting->CWmaxIndex = 7; // 2006.06.02, by rcnjko.
 
 	write_nic_byte(dev, SIFS, ChnlAccessSetting->SIFS_Timer);
-	//Adapter->HalFunc.SetHwRegHandler( Adapter, HW_VAR_SLOT_TIME, &ChnlAccessSetting->SlotTimeTimer );	// Rewrited from directly use PlatformEFIOWrite1Byte(), by Annie, 2006-03-29.
 	write_nic_byte(dev, SLOT, ChnlAccessSetting->SlotTimeTimer);	// Rewrited from directly use PlatformEFIOWrite1Byte(), by Annie, 2006-03-29.
 
 	u1bAIFS = aSifsTime + (2 * ChnlAccessSetting->SlotTimeTimer );
 
-	//write_nic_byte(dev, AC_VO_PARAM, u1bAIFS);
-	//write_nic_byte(dev, AC_VI_PARAM, u1bAIFS);
-	//write_nic_byte(dev, AC_BE_PARAM, u1bAIFS);
-	//write_nic_byte(dev, AC_BK_PARAM, u1bAIFS);
-
 	write_nic_byte(dev, EIFS, ChnlAccessSetting->EIFS_Timer);
 
 	write_nic_byte(dev, AckTimeOutReg, 0x5B); // <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS register, 2005.12.08.
 
-#ifdef TODO
-	// <RJ_TODO_NOW_8185B> Update ECWmin/ECWmax, AIFS, TXOP Limit of each AC to the value defined by SPEC.
-	if( pStaQos->CurrentQosMode > QOS_DISABLE )
-	{ // QoS mode.
-		if(pStaQos->QBssWirelessMode == WirelessMode)
-		{
-			// Follow AC Parameters of the QBSS.
-			for(eACI = 0; eACI < AC_MAX; eACI++)
-			{
-				Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_AC_PARAM, (pu1Byte)(&(pStaQos->WMMParamEle.AcParam[eACI])) );
-			}
-		}
-		else
-		{
-			// Follow Default WMM AC Parameters.
-			bFollowLegacySetting = 1;
-		}
-	}
-	else
-#endif
 	{ // Legacy 802.11.
 		bFollowLegacySetting = 1;
 
@@ -1719,14 +1112,12 @@
 		AcParam.f.TXOPLimit = 0;
 
 		//lzm reserved 080826
-#if 1
 		// For turbo mode setting. port from 87B by Isaiah 2008-08-01
 		if( ieee->current_network.Turbo_Enable == 1 )
 			AcParam.f.TXOPLimit = 0x01FF;
 		// For 87SE with Intel 4965  Ad-Hoc mode have poor throughput (19MB)
 		if (ieee->iw_mode == IW_MODE_ADHOC)
 			AcParam.f.TXOPLimit = 0x0020;
-#endif
 
 		for(eACI = 0; eACI < AC_MAX; eACI++)
 		{
@@ -1770,18 +1161,13 @@
 
 				// Cehck ACM bit.
 				// If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13.
-				//write_nic_byte(dev, ACM_CONTROL, pAcParam->f.AciAifsn);
 				{
 					PACI_AIFSN	pAciAifsn = (PACI_AIFSN)(&pAcParam->f.AciAifsn);
 					AC_CODING	eACI = pAciAifsn->f.ACI;
 
 					//modified Joseph
 					//for 8187B AsynIORead issue
-#ifdef TODO
-					u8	AcmCtrl = pHalData->AcmControl;
-#else
 					u8	AcmCtrl = 0;
-#endif
 					if( pAciAifsn->f.ACM )
 					{ // ACM bit is 1.
 						switch(eACI)
@@ -1823,19 +1209,10 @@
 								break;
 						}
 					}
-
-					//printk(KERN_WARNING "SetHwReg8185(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl);
-
-#ifdef TO_DO
-					pHalData->AcmControl = AcmCtrl;
-#endif
-					//write_nic_byte(dev, ACM_CONTROL, AcmCtrl);
 					write_nic_byte(dev, ACM_CONTROL, 0);
 				}
 			}
 		}
-
-
 	}
 }
 
@@ -1847,7 +1224,6 @@
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	struct ieee80211_device *ieee = priv->ieee80211;
-	//PMGNT_INFO		pMgntInfo = &(Adapter->MgntInfo);
 	u8	btSupportedWirelessMode = GetSupportedWirelessMode8185(dev);
 
 	if( (btWirelessMode & btSupportedWirelessMode) == 0 )
@@ -1880,24 +1256,11 @@
 		}
 	}
 
-
-	// 2. Swtich band: RF or BB specific actions,
-	// for example, refresh tables in omc8255, or change initial gain if necessary.
-	switch(priv->rf_chip)
-	{
-	case RF_ZEBRA2:
-	case RF_ZEBRA4:
-		{
-			// Nothing to do for Zebra to switch band.
-			// Update current wireless mode if we swtich to specified band successfully.
-			ieee->mode = (WIRELESS_MODE)btWirelessMode;
-		}
-		break;
-
-	default:
-		DMESGW("ActSetWirelessMode8185(): unsupported RF: 0x%X !!!\n", priv->rf_chip);
-		break;
-	}
+	/* 2. Swtich band: RF or BB specific actions,
+	 * for example, refresh tables in omc8255, or change initial gain if necessary.
+	 * Nothing to do for Zebra to switch band.
+	 * Update current wireless mode if we swtich to specified band successfully. */
+	ieee->mode = (WIRELESS_MODE)btWirelessMode;
 
 	// 3. Change related setting.
 	if( ieee->mode == WIRELESS_MODE_A ){
@@ -1909,7 +1272,6 @@
 	else if( ieee->mode == WIRELESS_MODE_G ){
 		DMESG("WIRELESS_MODE_G\n");
 	}
-
 	ActUpdateChannelAccessSetting( dev, ieee->mode, &priv->ChannelAccessSetting);
 }
 
@@ -1927,11 +1289,7 @@
 	u16			reason
 	)
 {
-	//printk("==> DrvIFIndicateDisassociation()\n");
-
 	// nothing is needed after disassociation request.
-
-	//printk("<== DrvIFIndicateDisassociation()\n");
 }
 void
 MgntDisconnectIBSS(
@@ -1941,11 +1299,7 @@
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	u8			i;
 
-	//printk("XXXXXXXXXX MgntDisconnect IBSS\n");
-
 	DrvIFIndicateDisassociation(dev, unspec_reason);
-
-//	PlatformZeroMemory( pMgntInfo->Bssid, 6 );
 	for(i=0;i<6;i++)  priv->ieee80211->current_network.bssid[i] = 0x55;
 
 	priv->ieee80211->state = IEEE80211_NOLINK;
@@ -1957,16 +1311,10 @@
 	// Because Bcn DMA isn't complete, mgnt queue would stuck until Bcn packet send.
 
 	// Disable Beacon Queue Own bit, suggested by jong
-//	Adapter->HalFunc.SetTxDescOWNHandler(Adapter, BEACON_QUEUE, 0, 0);
 	ieee80211_stop_send_beacons(priv->ieee80211);
 
 	priv->ieee80211->link_change(dev);
 	notify_wx_assoc_event(priv->ieee80211);
-
-	// Stop SW Beacon.Use hw beacon so do not need to do so.by amy
-
-//		MgntIndicateMediaStatus( Adapter, RT_MEDIA_DISCONNECT, GENERAL_INDICATE );
-
 }
 void
 MlmeDisassociateRequest(
@@ -1986,14 +1334,8 @@
 		DrvIFIndicateDisassociation(dev, unspec_reason);
 
 
-	//	pMgntInfo->AsocTimestamp = 0;
 		for(i=0;i<6;i++)  priv->ieee80211->current_network.bssid[i] = 0x22;
-//		pMgntInfo->mBrates.Length = 0;
-//		Adapter->HalFunc.SetHwRegHandler( Adapter, HW_VAR_BASIC_RATE, (pu1Byte)(&pMgntInfo->mBrates) );
-
 		ieee80211_disassociate(priv->ieee80211);
-
-
 	}
 
 }
@@ -2011,23 +1353,12 @@
 // I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE().
 //
 //	//2004/09/15, kcwu, the key should be cleared, or the new handshaking will not success
-//	SecClearAllKeys(Adapter);
 
 	// In WPA WPA2 need to Clear all key ... because new key will set after new handshaking.
-#ifdef TODO
-	if(   pMgntInfo->SecurityInfo.AuthMode > RT_802_11AuthModeAutoSwitch ||
-		(pMgntInfo->bAPSuportCCKM && pMgntInfo->bCCX8021xenable) )  // In CCKM mode will Clear key
-	{
-		SecClearAllKeys(Adapter);
-		RT_TRACE(COMP_SEC, DBG_LOUD,("======>CCKM clear key..."))
-	}
-#endif
 	// 2004.10.11, by rcnjko.
-	//MlmeDisassociateRequest( Adapter, pMgntInfo->Bssid, disas_lv_ss );
 	MlmeDisassociateRequest( dev, priv->ieee80211->current_network.bssid, asRsn );
 
 	priv->ieee80211->state = IEEE80211_NOLINK;
-//	pMgntInfo->AsocTimestamp = 0;
 }
 bool
 MgntDisconnect(
@@ -2039,20 +1370,7 @@
 	//
 	// Schedule an workitem to wake up for ps mode, 070109, by rcnjko.
 	//
-#ifdef TODO
-	if(pMgntInfo->mPss != eAwake)
-	{
-		//
-		// Using AwkaeTimer to prevent mismatch ps state.
-		// In the timer the state will be changed according to the RF is being awoke or not. By Bruce, 2007-10-31.
-		//
-		// PlatformScheduleWorkItem( &(pMgntInfo->AwakeWorkItem) );
-		PlatformSetTimer( Adapter, &(pMgntInfo->AwakeTimer), 0 );
-	}
-#endif
 
-	// Indication of disassociation event.
-	//DrvIFIndicateDisassociation(Adapter, asRsn);
 	if(IS_DOT11D_ENABLE(priv->ieee80211))
 		Dot11d_Reset(priv->ieee80211);
 	// In adhoc mode, update beacon frame.
@@ -2060,8 +1378,6 @@
 	{
 		if( priv->ieee80211->iw_mode == IW_MODE_ADHOC )
 		{
-//			RT_TRACE(COMP_MLME, DBG_LOUD, ("MgntDisconnect() ===> MgntDisconnectIBSS\n"));
-			//printk("MgntDisconnect() ===> MgntDisconnectIBSS\n");
 			MgntDisconnectIBSS(dev);
 		}
 		if( priv->ieee80211->iw_mode == IW_MODE_INFRA )
@@ -2071,17 +1387,10 @@
 			// e.g. OID_802_11_DISASSOCIATE in Windows while as MgntDisconnectAP() is
 			// used to handle disassociation related things to AP, e.g. send Disassoc
 			// frame to AP.  2005.01.27, by rcnjko.
-//			SecClearAllKeys(Adapter);
-
-//			RT_TRACE(COMP_MLME, DBG_LOUD, ("MgntDisconnect() ===> MgntDisconnectAP\n"));
-			//printk("MgntDisconnect() ===> MgntDisconnectAP\n");
 			MgntDisconnectAP(dev, asRsn);
 		}
-
 		// Inidicate Disconnect, 2005.02.23, by rcnjko.
-//		MgntIndicateMediaStatus( Adapter, RT_MEDIA_DISCONNECT, GENERAL_INDICATE);
 	}
-
 	return true;
 }
 //
@@ -2101,25 +1410,12 @@
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	bool			bResult = false;
 
-//	printk("---------> SetRFPowerState(): eRFPowerState(%d)\n", eRFPowerState);
 	if(eRFPowerState == priv->eRFPowerState)
 	{
-//		printk("<--------- SetRFPowerState(): discard the request for eRFPowerState(%d) is the same.\n", eRFPowerState);
 		return bResult;
 	}
 
-	switch(priv->rf_chip)
-	{
-		case RF_ZEBRA2:
-		case RF_ZEBRA4:
-			 bResult = SetZebraRFPowerState8185(dev, eRFPowerState);
-			break;
-
-		default:
-			printk("SetRFPowerState8185(): unknown RFChipID: 0x%X!!!\n", priv->rf_chip);
-			break;;
-}
-//	printk("<--------- SetRFPowerState(): bResult(%d)\n", bResult);
+	 bResult = SetZebraRFPowerState8185(dev, eRFPowerState);
 
 	return bResult;
 }
@@ -2149,33 +1445,25 @@
 	RT_RF_POWER_STATE 	rtState;
 	u16				RFWaitCounter = 0;
 	unsigned long flag;
-//	 printk("===>MgntActSet_RF_State(): StateToSet(%d), ChangeSource(0x%x)\n",StateToSet, ChangeSource);
 	//
 	// Prevent the race condition of RF state change. By Bruce, 2007-11-28.
 	// Only one thread can change the RF state at one time, and others should wait to be executed.
 	//
-#if 1
 	while(true)
 	{
-//		down(&priv->rf_state);
 		spin_lock_irqsave(&priv->rf_ps_lock,flag);
 		if(priv->RFChangeInProgress)
 		{
-//			printk("====================>haha111111111\n");
-//			up(&priv->rf_state);
-//			RT_TRACE(COMP_RF, DBG_LOUD, ("MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n", StateToSet));
 			spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
 			// Set RF after the previous action is done.
 			while(priv->RFChangeInProgress)
 			{
 				RFWaitCounter ++;
-//				RT_TRACE(COMP_RF, DBG_LOUD, ("MgntActSet_RF_State(): Wait 1 ms (%d times)...\n", RFWaitCounter));
 				udelay(1000); // 1 ms
 
 				// Wait too long, return FALSE to avoid to be stuck here.
 				if(RFWaitCounter > 1000) // 1sec
 				{
-//					RT_ASSERT(FALSE, ("MgntActSet_RF_State(): Wait too logn to set RF\n"));
 					printk("MgntActSet_RF_State(): Wait too long to set RF\n");
 					// TODO: Reset RF state?
 					return false;
@@ -2184,17 +1472,13 @@
 		}
 		else
 		{
-//			printk("========================>haha2\n");
 			priv->RFChangeInProgress = true;
-//			up(&priv->rf_state);
 			spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
 			break;
 		}
 	}
-#endif
 	rtState = priv->eRFPowerState;
 
-
 	switch(StateToSet)
 	{
 	case eRfOn:
@@ -2215,7 +1499,6 @@
 			}
 		}
 		else
-//			RT_TRACE(COMP_RF, DBG_LOUD, ("MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", pMgntInfo->RfOffReason, ChangeSource));
 			;
 		break;
 
@@ -2232,38 +1515,26 @@
 				//
 				// Calling MgntDisconnect() instead of MgntActSet_802_11_DISASSOCIATE(),
 				// because we do NOT need to set ssid to dummy ones.
-				// Revised by Roger, 2007.12.04.
 				//
 				MgntDisconnect( dev, disas_lv_ss );
 
 				// Clear content of bssDesc[] and bssDesc4Query[] to avoid reporting old bss to UI.
-				// 2007.05.28, by shien chang.
-//				PlatformZeroMemory( pMgntInfo->bssDesc, sizeof(RT_WLAN_BSS)*MAX_BSS_DESC );
-//				pMgntInfo->NumBssDesc = 0;
-//				PlatformZeroMemory( pMgntInfo->bssDesc4Query, sizeof(RT_WLAN_BSS)*MAX_BSS_DESC );
-//				pMgntInfo->NumBssDesc4Query = 0;
 			}
 
-
-
 		priv->RfOffReason |= ChangeSource;
 		bActionAllowed = true;
 		break;
-
 	case eRfSleep:
 		priv->RfOffReason |= ChangeSource;
 		bActionAllowed = true;
 		break;
-
 	default:
 		break;
 	}
 
 	if(bActionAllowed)
 	{
-//		RT_TRACE(COMP_RF, DBG_LOUD, ("MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, pMgntInfo->RfOffReason));
                 // Config HW to the specified mode.
-//		printk("MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, priv->RfOffReason);
 		SetRFPowerState(dev, StateToSet);
 
 		// Turn on RF.
@@ -2273,7 +1544,6 @@
 			if(bConnectBySSID)
 			{
 			// by amy not supported
-//				MgntActSet_802_11_SSID(Adapter, Adapter->MgntInfo.Ssid.Octet, Adapter->MgntInfo.Ssid.Length, TRUE );
 			}
 		}
 		// Turn off RF.
@@ -2282,18 +1552,11 @@
 			HalDisableRx8185Dummy(dev);
 		}
 	}
-	else
-	{
-	//	printk("MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", StateToSet, ChangeSource, priv->RfOffReason);
-	}
 
 	// Release RF spinlock
-//	down(&priv->rf_state);
 	spin_lock_irqsave(&priv->rf_ps_lock,flag);
 	priv->RFChangeInProgress = false;
-//	up(&priv->rf_state);
 	spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
-//	printk("<===MgntActSet_RF_State()\n");
 	return bActionAllowed;
 }
 void
@@ -2302,15 +1565,12 @@
 	)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-	//u8 index = 0;
-
 	//
 	// This flag "bSwRfProcessing", indicates the status of IPS procedure, should be set if the IPS workitem
 	// is really scheduled.
 	// The old code, sets this flag before scheduling the IPS workitem and however, at the same time the
 	// previous IPS workitem did not end yet, fails to schedule the current workitem. Thus, bSwRfProcessing
 	// blocks the IPS procedure of switching RF.
-	// By Bruce, 2007-12-25.
 	//
 	priv->bSwRfProcessing = true;
 
@@ -2326,7 +1586,6 @@
 //
 //	Description:
 //		Enter the inactive power save mode. RF will be off
-//	2007.08.17, by shien chang.
 //
 void
 IPSEnter(
@@ -2335,13 +1594,11 @@
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	RT_RF_POWER_STATE rtState;
-	//printk("==============================>enter IPS\n");
 	if (priv->bInactivePs)
 	{
 		rtState = priv->eRFPowerState;
 
 		//
-		// Added by Bruce, 2007-12-25.
 		// Do not enter IPS in the following conditions:
 		// (1) RF is already OFF or Sleep
 		// (2) bSwRfProcessing (indicates the IPS is still under going)
@@ -2352,12 +1609,10 @@
 		if (rtState == eRfOn && !priv->bSwRfProcessing
 			&& (priv->ieee80211->state != IEEE80211_LINKED ))
 		{
-	//		printk("IPSEnter(): Turn off RF.\n");
 			priv->eInactivePowerState = eRfOff;
 			InactivePowerSave(dev);
 		}
 	}
-//	printk("priv->eRFPowerState is %d\n",priv->eRFPowerState);
 }
 void
 IPSLeave(
@@ -2366,20 +1621,17 @@
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	RT_RF_POWER_STATE rtState;
-	//printk("===================================>leave IPS\n");
 	if (priv->bInactivePs)
 	{
 		rtState = priv->eRFPowerState;
 		if ((rtState == eRfOff || rtState == eRfSleep) && (!priv->bSwRfProcessing) && priv->RfOffReason <= RF_CHANGE_BY_IPS)
 		{
-//			printk("IPSLeave(): Turn on RF.\n");
 			priv->eInactivePowerState = eRfOn;
 			InactivePowerSave(dev);
 		}
 	}
-//	printk("priv->eRFPowerState is %d\n",priv->eRFPowerState);
 }
-//by amy for power save
+
 void rtl8185b_adapter_start(struct net_device *dev)
 {
       struct r8180_priv *priv = ieee80211_priv(dev);
@@ -2388,75 +1640,45 @@
 	u8 SupportedWirelessMode;
 	u8			InitWirelessMode;
 	u8			bInvalidWirelessMode = 0;
-	//int i;
 	u8 tmpu8;
-    	//u8 u1tmp,u2tmp;
 	u8 btCR9346;
 	u8 TmpU1b;
 	u8 btPSR;
 
-	//rtl8180_rtx_disable(dev);
-//{by amy 080312
 	write_nic_byte(dev,0x24e, (BIT5|BIT6|BIT0));
-//by amy 080312}
 	rtl8180_reset(dev);
 
 	priv->dma_poll_mask = 0;
 	priv->dma_poll_stop_mask = 0;
 
-	//rtl8180_beacon_tx_disable(dev);
-
 	HwConfigureRTL8185(dev);
-
 	write_nic_dword(dev, MAC0, ((u32*)dev->dev_addr)[0]);
 	write_nic_word(dev, MAC4, ((u32*)dev->dev_addr)[1] & 0xffff );
-
 	write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3);	// default network type to 'No	Link'
-
-	//write_nic_byte(dev, BRSR, 0x0);		// Set BRSR= 1M
-
 	write_nic_word(dev, BcnItv, 100);
 	write_nic_word(dev, AtimWnd, 2);
-
-	//PlatformEFIOWrite2Byte(dev, FEMR, 0xFFFF);
 	PlatformIOWrite2Byte(dev, FEMR, 0xFFFF);
-
 	write_nic_byte(dev, WPA_CONFIG, 0);
-
 	MacConfig_85BASIC(dev);
-
 	// Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07, by rcnjko.
 	// BT_DEMO_BOARD type
 	PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x569a);
-//by amy
-//#ifdef CONFIG_RTL818X_S
-		// for jong required
-//	PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x9a56);
-//#endif
-//by amy
-	//BT_QA_BOARD
-	//PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x9a56);
 
 	//-----------------------------------------------------------------------------
 	// Set up PHY related.
 	//-----------------------------------------------------------------------------
 	// Enable Config3.PARAM_En to revise AnaaParm.
 	write_nic_byte(dev, CR9346, 0xc0);	// enable config register write
-//by amy
 	tmpu8 = read_nic_byte(dev, CONFIG3);
 	write_nic_byte(dev, CONFIG3, (tmpu8 |CONFIG3_PARM_En) );
-//by amy
 	// Turn on Analog power.
 	// Asked for by William, otherwise, MAC 3-wire can't work, 2006.06.27, by rcnjko.
 	write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON);
 	write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON);
-//by amy
 	write_nic_word(dev, ANAPARAM3, 0x0010);
-//by amy
 
 	write_nic_byte(dev, CONFIG3, tmpu8);
 	write_nic_byte(dev, CR9346, 0x00);
-//{by amy 080312 for led
 	// enable EEM0 and EEM1 in 9346CR
 	btCR9346 = read_nic_byte(dev, CR9346);
 	write_nic_byte(dev, CR9346, (btCR9346|0xC0) );
@@ -2474,7 +1696,6 @@
 	// B-cut RF Radio on/off  5e[3]=0
 	btPSR = read_nic_byte(dev, PSR);
 	write_nic_byte(dev, PSR, (btPSR | BIT3));
-//by amy 080312 for led}
 	// setup initial timing for RFE.
 	write_nic_word(dev, RFPinsOutput, 0x0480);
 	SetOutputEnableOfRfPins(dev);
@@ -2537,55 +1758,19 @@
 		InitWirelessMode = ieee->mode;
 	}
 //by amy for power save
-//	printk("initialize ENABLE_IPS\n");
 	priv->eRFPowerState = eRfOff;
 	priv->RfOffReason = 0;
 	{
-	//	u32 tmp2;
-	//	u32 tmp = jiffies;
 		MgntActSet_RF_State(dev, eRfOn, 0);
-	//	tmp2 = jiffies;
-	//	printk("rf on cost jiffies:%lx\n", (tmp2-tmp)*1000/HZ);
 	}
-//	DrvIFIndicateCurrentPhyStatus(priv);
 		//
 		// If inactive power mode is enabled, disable rf while in disconnected state.
-		// 2007.07.16, by shien chang.
 		//
 	if (priv->bInactivePs)
 	{
-	//	u32 tmp2;
-	//	u32 tmp = jiffies;
 		MgntActSet_RF_State(dev,eRfOff, RF_CHANGE_BY_IPS);
-	//	tmp2 = jiffies;
-	//	printk("rf off cost jiffies:%lx\n", (tmp2-tmp)*1000/HZ);
-
 	}
-//	IPSEnter(dev);
 //by amy for power save
-#ifdef TODO
-	// Turn off RF if necessary. 2005.08.23, by rcnjko.
-	// We shall turn off RF after setting CMDR, otherwise,
-	// RF will be turnned on after we enable MAC Tx/Rx.
-	if(Adapter->MgntInfo.RegRfOff == TRUE)
-	{
-		SetRFPowerState8185(Adapter, RF_OFF);
-	}
-	else
-	{
-		SetRFPowerState8185(Adapter, RF_ON);
-	}
-#endif
-
-/*   //these is equal with above TODO.
-	write_nic_byte(dev, CR9346, 0xc0);	// enable config register write
-	write_nic_byte(dev, CONFIG3, read_nic_byte(dev, CONFIG3) | CONFIG3_PARM_En);
-	RF_WriteReg(dev, 0x4, 0x9FF);
-	write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON);
-	write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON);
-	write_nic_byte(dev, CONFIG3, (read_nic_byte(dev, CONFIG3)&(~CONFIG3_PARM_En)));
-	write_nic_byte(dev, CR9346, 0x00);
-*/
 
 	ActSetWirelessMode8185(dev, (u8)(InitWirelessMode));
 
@@ -2594,14 +1779,11 @@
 	rtl8185b_irq_enable(dev);
 
 	netif_start_queue(dev);
-
  }
 
-
 void rtl8185b_rx_enable(struct net_device *dev)
 {
 	u8 cmd;
-	//u32 rxconf;
 	/* for now we accept data, management & ctl frame*/
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 
@@ -2613,11 +1795,6 @@
 		priv->ReceiveConfig = priv->ReceiveConfig | RCR_AAP;
 	}
 
-	/*if(priv->ieee80211->iw_mode == IW_MODE_MASTER){
-		rxconf = rxconf | (1<<ACCEPT_ALLMAC_FRAME_SHIFT);
-		rxconf = rxconf | (1<<RX_CHECK_BSSID_SHIFT);
-	}*/
-
 	if(priv->ieee80211->iw_mode == IW_MODE_MONITOR){
 		priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACF | RCR_APWRMGT | RCR_AICV;
 	}
@@ -2629,9 +1806,6 @@
 
 	fix_rx_fifo(dev);
 
-#ifdef DEBUG_RX
-	DMESG("rxconf: %x %x",priv->ReceiveConfig ,read_nic_dword(dev,RCR));
-#endif
 	cmd=read_nic_byte(dev,CMD);
 	write_nic_byte(dev,CMD,cmd | (1<<CMD_RX_ENABLE_SHIFT));
 
@@ -2640,9 +1814,7 @@
 void rtl8185b_tx_enable(struct net_device *dev)
 {
 	u8 cmd;
-	//u8 tx_agc_ctl;
 	u8 byte;
-	//u32 txconf;
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 
 	write_nic_dword(dev, TCR, priv->TransmitConfig);
@@ -2652,21 +1824,7 @@
 
 	fix_tx_fifo(dev);
 
-#ifdef DEBUG_TX
-	DMESG("txconf: %x %x",priv->TransmitConfig,read_nic_dword(dev,TCR));
-#endif
-
 	cmd=read_nic_byte(dev,CMD);
 	write_nic_byte(dev,CMD,cmd | (1<<CMD_TX_ENABLE_SHIFT));
-
-	//write_nic_dword(dev,TX_CONF,txconf);
-
-
-/*
-	rtl8180_set_mode(dev,EPROM_CMD_CONFIG);
-	write_nic_byte(dev, TX_DMA_POLLING, priv->dma_poll_mask);
-	rtl8180_set_mode(dev,EPROM_CMD_NORMAL);
-	*/
 }
 
-
diff --git a/drivers/staging/rtl8192e/Makefile b/drivers/staging/rtl8192e/Makefile
index 5e4aa95..e032c3e 100644
--- a/drivers/staging/rtl8192e/Makefile
+++ b/drivers/staging/rtl8192e/Makefile
@@ -1,13 +1,15 @@
 NIC_SELECT = RTL8192E
 
-
 EXTRA_CFLAGS += -DRTL8192E
 EXTRA_CFLAGS += -std=gnu89
 EXTRA_CFLAGS += -O2
 EXTRA_CFLAGS += -DTHOMAS_TURBO
 EXTRA_CFLAGS += -DENABLE_DOT11D
 
-r8192_pci-objs :=		\
+EXTRA_CFLAGS += -DENABLE_IPS
+EXTRA_CFLAGS += -DENABLE_LPS
+
+r8192e_pci-objs :=		\
 	r8192E_core.o		\
 	r8180_93cx6.o		\
 	r8192E_wx.o		\
@@ -31,4 +33,5 @@
 	ieee80211/ieee80211_crypt_ccmp.o	\
 	ieee80211/ieee80211_crypt_wep.o
 
-obj-$(CONFIG_RTL8192E) += r8192_pci.o
+obj-$(CONFIG_RTL8192E) += r8192e_pci.o
+
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
index 15b7a4b..5b0e2db 100644
--- a/drivers/staging/rtl8192e/dot11d.h
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -1,102 +1,96 @@
-#ifndef __INC_DOT11D_H
-#define __INC_DOT11D_H
+#ifndef INC_DOT11D_H
+#define INC_DOT11D_H
 
 #ifdef ENABLE_DOT11D
 #include "ieee80211.h"
 
-//#define ENABLE_DOT11D
-
-//#define DOT11D_MAX_CHNL_NUM 83
-
 typedef struct _CHNL_TXPOWER_TRIPLE {
 	u8 FirstChnl;
 	u8  NumChnls;
 	u8  MaxTxPowerInDbm;
-}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
+} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
 
 typedef enum _DOT11D_STATE {
 	DOT11D_STATE_NONE = 0,
 	DOT11D_STATE_LEARNED,
 	DOT11D_STATE_DONE,
-}DOT11D_STATE;
+} DOT11D_STATE;
+
+/**
+ * struct _RT_DOT11D_INFO
+ * @CountryIeLen: value greater than 0 if @CountryIeBuf contains
+ * 	          valid country information element.
+ * @chanell_map: holds channel values
+ *		0 - invalid,
+ *		1 - valid (active scan),
+ *	 	2 - valid (passive scan)
+ * @CountryIeSrcAddr - Source AP of the country IE
+ */
 
 typedef struct _RT_DOT11D_INFO {
-	//DECLARE_RT_OBJECT(RT_DOT11D_INFO);
+	bool bEnabled;
 
-	bool bEnabled; // dot11MultiDomainCapabilityEnabled
+	u16 CountryIeLen;
+	u8 CountryIeBuf[MAX_IE_LEN];
+	u8 CountryIeSrcAddr[6];
+	u8 CountryIeWatchdog;
 
-	u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element.
-	u8  CountryIeBuf[MAX_IE_LEN];
-	u8  CountryIeSrcAddr[6]; // Source AP of the country IE.
-	u8  CountryIeWatchdog;
-
-	u8  channel_map[MAX_CHANNEL_NUMBER+1];  //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan)
-	//u8  ChnlListLen; // #Bytes valid in ChnlList[].
-	//u8  ChnlList[DOT11D_MAX_CHNL_NUM];
-	u8  MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
+	u8 channel_map[MAX_CHANNEL_NUMBER+1];
+	u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
 
 	DOT11D_STATE State;
-}RT_DOT11D_INFO, *PRT_DOT11D_INFO;
-#define eqMacAddr(a,b)		( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 )
-#define cpMacAddr(des,src)	      ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5])
-#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
+} RT_DOT11D_INFO, *PRT_DOT11D_INFO;
+
+#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == \
+			(b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && \
+			(a)[5] == (b)[5]) ? 1 : 0)
+
+#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], \
+			(des)[2] = (src)[2], (des)[3] = (src)[3], \
+			(des)[4] = (src)[4], (des)[5] = (src)[5])
+
+#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO) \
+			((__pIeeeDev)->pDot11dInfo))
 
 #define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
-#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
+#define IS_COUNTRY_IE_VALID(__pIeeeDev) \
+			(GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
 
-#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
-#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
+#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) \
+		eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
+
+#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) \
+		cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
 
 #define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
-	(((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
-	FALSE : \
-	(!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
+	(((__Ie).Length == 0 || (__Ie).Length != \
+	GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? FALSE : \
+	(!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, \
+	(__Ie).Octet, (__Ie).Length)))
 
 #define CIE_WATCHDOG_TH 1
 #define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
 #define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
 #define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
 
-#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
+#define IS_DOT11D_STATE_DONE(__pIeeeDev) \
+		(GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
 
 
-void
-Dot11d_Init(
-	struct ieee80211_device *dev
-	);
+void Dot11d_Init(struct ieee80211_device *dev);
 
-void
-Dot11d_Reset(
-	struct ieee80211_device *dev
-	);
+void Dot11d_Reset(struct ieee80211_device *dev);
 
-void
-Dot11d_UpdateCountryIe(
-	struct ieee80211_device *dev,
-	u8 *		pTaddr,
-	u16	CoutryIeLen,
-	u8 * pCoutryIe
-	);
+void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr,
+		u16 CoutryIeLen, u8 *pCoutryIe);
 
-u8
-DOT11D_GetMaxTxPwrInDbm(
-	struct ieee80211_device *dev,
-	u8 Channel
-	);
+u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 channel);
 
-void
-DOT11D_ScanComplete(
-	struct ieee80211_device * dev
-	);
+void DOT11D_ScanComplete(struct ieee80211_device *dev);
 
-int IsLegalChannel(
-	struct ieee80211_device * dev,
-	u8 channel
-);
+int IsLegalChannel(struct ieee80211_device *dev, u8 channel);
 
-int ToLegalChannel(
-	struct ieee80211_device * dev,
-	u8 channel
-);
-#endif //ENABLE_DOT11D
-#endif // #ifndef __INC_DOT11D_H
+int ToLegalChannel(struct ieee80211_device *dev, u8 channel);
+
+#endif /* ENABLE_DOT11D */
+#endif /* INC_DOT11D_H */
diff --git a/drivers/staging/rtl8192e/ieee80211.h b/drivers/staging/rtl8192e/ieee80211.h
index 3ba9e9e..c39249e 100644
--- a/drivers/staging/rtl8192e/ieee80211.h
+++ b/drivers/staging/rtl8192e/ieee80211.h
@@ -547,9 +547,6 @@
 
 /* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
 
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
-
 /*
  * To use the debug system;
  *
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211.h b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
index aa76390..1f613a2 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
@@ -35,6 +35,7 @@
 #endif
 #include <linux/timer.h>
 #include <linux/sched.h>
+#include <linux/semaphore.h>
 
 #include <linux/delay.h>
 #include <linux/wireless.h>
@@ -180,6 +181,8 @@
         u8 DrvAggrNum;
 	u16 pkt_size;
         u8 reserved12;
+
+	u8 bdhcp;
 }cb_desc, *pcb_desc;
 
 /*--------------------------Define -------------------------------------------*/
@@ -615,9 +618,6 @@
 
 /* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
 
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
-
 /*
  * To use the debug system;
  *
@@ -743,6 +743,8 @@
 #define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS)
 #define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
 #define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
+#define WLAN_FC_MORE_DATA(fc) ((fc) & IEEE80211_FCTL_MOREDATA)
+
 
 #define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & IEEE80211_FCTL_FRAMETYPE)
 #define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
@@ -1055,7 +1057,7 @@
 #define SEC_ALG_NONE            0
 #define SEC_ALG_WEP             1
 #define SEC_ALG_TKIP            2
-#define SEC_ALG_CCMP            3
+#define SEC_ALG_CCMP            4
 
 #define WEP_KEYS 		4
 #define WEP_KEY_LEN		13
@@ -1124,6 +1126,14 @@
 /* Minimal header; can be used for passing 802.11 frames with sufficient
  * information to determine what type of underlying data type is actually
  * stored in the data. */
+ struct ieee80211_pspoll_hdr {
+        __le16 frame_ctl;
+        __le16 aid;
+	u8 bssid[ETH_ALEN];
+        u8 ta[ETH_ALEN];
+        //u8 payload[0];
+} __attribute__ ((packed));
+
 struct ieee80211_hdr {
         __le16 frame_ctl;
         __le16 duration_id;
@@ -1660,6 +1670,7 @@
 	bool ralink_cap_exist;
 	bool atheros_cap_exist;
 	bool cisco_cap_exist;
+	bool marvell_cap_exist;
 	bool unknown_cap_exist;
 //	u8	berp_info;
 	bool	berp_info_valid;
@@ -1865,6 +1876,19 @@
 	// Leisre Poswer Save : Disable RF if connected but traffic is not busy
 	//
 	bool				bLeisurePs;
+	u32				PowerProfile;
+	u8				LpsIdleCount;
+	u8				RegMaxLPSAwakeIntvl;
+	u8				LPSAwakeIntvl;
+
+	u32				CurPsLevel;
+	u32				RegRfPsLevel;
+
+	bool				bFwCtrlLPS;
+	u8				FWCtrlPSMode;
+
+	bool				LinkReqInIPSRFOffPgs;
+	bool				BufConnectinfoBefore;
 
 }RT_POWER_SAVE_CONTROL,*PRT_POWER_SAVE_CONTROL;
 
@@ -1905,14 +1929,121 @@
 
 	u32				NumTxOkInPeriod;
 	u32				NumRxOkInPeriod;
+	u32				NumRxUnicastOkInPeriod;
 	bool				bBusyTraffic;
 }RT_LINK_DETECT_T, *PRT_LINK_DETECT_T;
 
+//added by amy 090330
+typedef enum _HW_VARIABLES{
+	HW_VAR_ETHER_ADDR,
+	HW_VAR_MULTICAST_REG,
+	HW_VAR_BASIC_RATE,
+	HW_VAR_BSSID,
+	HW_VAR_MEDIA_STATUS,
+	HW_VAR_SECURITY_CONF,
+	HW_VAR_BEACON_INTERVAL,
+	HW_VAR_ATIM_WINDOW,
+	HW_VAR_LISTEN_INTERVAL,
+	HW_VAR_CS_COUNTER,
+	HW_VAR_DEFAULTKEY0,
+	HW_VAR_DEFAULTKEY1,
+	HW_VAR_DEFAULTKEY2,
+	HW_VAR_DEFAULTKEY3,
+	HW_VAR_SIFS,
+	HW_VAR_DIFS,
+	HW_VAR_EIFS,
+	HW_VAR_SLOT_TIME,
+	HW_VAR_ACK_PREAMBLE,
+	HW_VAR_CW_CONFIG,
+	HW_VAR_CW_VALUES,
+	HW_VAR_RATE_FALLBACK_CONTROL,
+	HW_VAR_CONTENTION_WINDOW,
+	HW_VAR_RETRY_COUNT,
+	HW_VAR_TR_SWITCH,
+	HW_VAR_COMMAND,			// For Command Register, Annie, 2006-04-07.
+	HW_VAR_WPA_CONFIG,		//2004/08/23, kcwu, for 8187 Security config
+	HW_VAR_AMPDU_MIN_SPACE,	// The spacing between sub-frame. Roger, 2008.07.04.
+	HW_VAR_SHORTGI_DENSITY,	// The density for shortGI. Roger, 2008.07.04.
+	HW_VAR_AMPDU_FACTOR,
+	HW_VAR_MCS_RATE_AVAILABLE,
+	HW_VAR_AC_PARAM,			// For AC Parameters, 2005.12.01, by rcnjko.
+	HW_VAR_ACM_CTRL,			// For ACM Control, Annie, 2005-12-13.
+	HW_VAR_DIS_Req_Qsize,		// For DIS_Reg_Qsize, Joseph
+	HW_VAR_CCX_CHNL_LOAD,		// For CCX 2 channel load request, 2006.05.04.
+	HW_VAR_CCX_NOISE_HISTOGRAM,	// For CCX 2 noise histogram request, 2006.05.04.
+	HW_VAR_CCX_CLM_NHM,			// For CCX 2 parallel channel load request and noise histogram request, 2006.05.12.
+	HW_VAR_TxOPLimit,				// For turbo mode related settings, added by Roger, 2006.12.07
+	HW_VAR_TURBO_MODE,			// For turbo mode related settings, added by Roger, 2006.12.15.
+	HW_VAR_RF_STATE, 			// For change or query RF power state, 061214, rcnjko.
+	HW_VAR_RF_OFF_BY_HW,		// For UI to query if external HW signal disable RF, 061229, rcnjko.
+	HW_VAR_BUS_SPEED, 		// In unit of bps. 2006.07.03, by rcnjko.
+        HW_VAR_SET_DEV_POWER,	// Set to low power, added by LanHsin, 2007.
+
+	//1!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	//1Attention Please!!!<11n or 8190 specific code should be put below this line>
+	//1!!!!!!!!!!!!!!!!!!!!!!!!!!!
+	HW_VAR_RCR,				//for RCR, David 2006,05,11
+	HW_VAR_RATR_0,
+	HW_VAR_RRSR,
+	HW_VAR_CPU_RST,
+	HW_VAR_CECHK_BSSID,
+        HW_VAR_LBK_MODE,			// Set lookback mode, 2008.06.11. added by Roger.
+	// Set HW related setting for 11N AES bug.
+	HW_VAR_AES_11N_FIX,
+	// Set Usb Rx Aggregation
+	HW_VAR_USB_RX_AGGR,
+	HW_VAR_USER_CONTROL_TURBO_MODE,
+	HW_VAR_RETRY_LIMIT,
+#ifndef _RTL8192_EXT_PATCH_
+	HW_VAR_INIT_TX_RATE,  //Get Current Tx rate register. 2008.12.10. Added by tynli
+#endif
+	HW_VAR_TX_RATE_REG,  //Get Current Tx rate register. 2008.12.10. Added by tynli
+	HW_VAR_EFUSE_USAGE, //Get current EFUSE utilization. 2008.12.19. Added by Roger.
+	HW_VAR_EFUSE_BYTES,
+	HW_VAR_AUTOLOAD_STATUS, //Get current autoload status, 0: autoload success, 1: autoload fail. 2008.12.19. Added by Roger.
+	HW_VAR_RF_2R_DISABLE, // 2R disable
+	HW_VAR_SET_RPWM,
+	HW_VAR_H2C_FW_PWRMODE, // For setting FW related H2C cmd structure. by tynli. 2009.2.18
+	HW_VAR_H2C_FW_JOINBSSRPT, // For setting FW related H2C cmd structure. by tynli. 2009.2.18
+	HW_VAR_1X1_RECV_COMBINE,	// For 1T2R but only 1SS, Add by hpfan 2009.04.16 hpfan
+	HW_VAR_STOP_SEND_BEACON,
+	HW_VAR_TSF_TIMER,			// Read from TSF register to get the current TSF timer, by Bruce, 2009-07-22.
+	HW_VAR_IO_CMD,
+	HW_VAR_HANDLE_FW_C2H,		//Added by tynli. For handling FW C2H command. 2009.10.07.
+	HW_VAR_DL_FW_RSVD_PAGE, 		//Added by tynli. Download the packets that FW will use to RSVD page. 2009.10.14.
+	HW_VAR_AID,				//Added by tynli.
+	HW_VAR_HW_SEQ_ENABLE,		//Added by tynli. 2009.10.20.
+	HW_VAR_UPDATE_TSF,			//Added by tynli. 2009.10.22. For Hw count TBTT time.
+	HW_VAR_BCN_VALID,				//Added by tynli.
+	HW_VAR_FWLPS_RF_ON			//Added by tynli. 2009.11.09. For checking if Fw finishs RF on sequence.
+}HW_VARIABLES;
+
+#define RT_CHECK_FOR_HANG_PERIOD 2
 
 struct ieee80211_device {
 	struct net_device *dev;
         struct ieee80211_security sec;
 
+	bool	need_sw_enc;
+#ifdef ENABLE_LPS
+	bool bAwakePktSent;
+	u8  LPSDelayCnt;
+	bool bIsAggregateFrame;
+	bool polling;
+	void (*LeisurePSLeave)(struct net_device *dev);
+#endif
+
+#ifdef ENABLE_IPS
+	bool proto_stoppping;
+	bool wx_set_enc;
+	struct semaphore ips_sem;
+	struct work_struct ips_leave_wq;
+        void (*ieee80211_ips_leave_wq) (struct net_device *dev);
+        void (*ieee80211_ips_leave)(struct net_device *dev);
+#endif
+	void (*SetHwRegHandler)(struct net_device *dev,u8 variable,u8* val);
+	u8   (*rtllib_ap_sec_type)(struct ieee80211_device *ieee);
+
 	//hw security related
 //	u8 hwsec_support; //support?
 	u8 hwsec_active;  //hw security active.
@@ -2319,7 +2450,7 @@
 	 * stop_send_bacons is NOT guaranteed to be called only
 	 * after start_send_beacons.
 	 */
-	void (*start_send_beacons) (struct net_device *dev,u16 tx_rate);
+	void (*start_send_beacons) (struct net_device *dev);
 	void (*stop_send_beacons) (struct net_device *dev);
 
 	/* power save mode related */
@@ -2373,6 +2504,19 @@
 	u8 priv[0];
 };
 
+#define	RT_RF_OFF_LEVL_ASPM			BIT0	// PCI ASPM
+#define	RT_RF_OFF_LEVL_CLK_REQ		BIT1	// PCI clock request
+#define	RT_RF_OFF_LEVL_PCI_D3			BIT2	// PCI D3 mode
+#define	RT_RF_OFF_LEVL_HALT_NIC		BIT3	// NIC halt, re-initialize hw parameters
+#define	RT_RF_OFF_LEVL_FREE_FW		BIT4	// FW free, re-download the FW
+#define	RT_RF_OFF_LEVL_FW_32K		BIT5	// FW in 32k
+#define	RT_RF_PS_LEVEL_ALWAYS_ASPM	BIT6	// Always enable ASPM and Clock Req in initialization.
+#define	RT_RF_LPS_DISALBE_2R			BIT30	// When LPS is on, disable 2R if no packet is received or transmittd.
+#define	RT_RF_LPS_LEVEL_ASPM			BIT31	// LPS with ASPM
+#define	RT_IN_PS_LEVEL(pPSC, _PS_FLAG)	((pPSC->CurPsLevel & _PS_FLAG) ? true : false)
+#define	RT_CLEAR_PS_LEVEL(pPSC, _PS_FLAG)	(pPSC->CurPsLevel &= (~(_PS_FLAG)))
+#define	RT_SET_PS_LEVEL(pPSC, _PS_FLAG)	(pPSC->CurPsLevel |= _PS_FLAG)
+
 #define IEEE_A            (1<<0)
 #define IEEE_B            (1<<1)
 #define IEEE_G            (1<<2)
@@ -2609,9 +2753,9 @@
 extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
 extern void ieee80211_check_all_nets(struct ieee80211_device *ieee);
 extern void ieee80211_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
+extern void ieee80211_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
+extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
 extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
 extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
 extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
@@ -2798,5 +2942,7 @@
 		struct ieee80211_rx_stats *stats);
 
 void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8  index);
+void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr);
+void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee);
 #define RT_ASOC_RETRY_LIMIT	5
 #endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
index b1c5493..b3c9bf4 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
@@ -225,7 +225,7 @@
 }
 
 
-void __exit ieee80211_crypto_deinit(void)
+void ieee80211_crypto_deinit(void)
 {
 	struct list_head *ptr, *n;
 
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
index ab871b3..1776f7e 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
@@ -331,7 +331,7 @@
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "CCMP: received packet without ExtIV"
-			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			       " flag from %pM\n", hdr->addr2);
 		}
 		key->dot11RSNAStatsCCMPFormatErrors++;
 		return -2;
@@ -344,9 +344,9 @@
 	}
 	if (!key->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
+			printk(KERN_DEBUG "CCMP: received packet from %pM"
 			       " with keyid=%d that does not have a configured"
-			       " key\n", MAC_ARG(hdr->addr2), keyidx);
+			       " key\n", hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -361,11 +361,9 @@
 
 	if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
-			       " previous PN %02x%02x%02x%02x%02x%02x "
-			       "received PN %02x%02x%02x%02x%02x%02x\n",
-			       MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
-			       MAC_ARG(pn));
+			//printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
+			//       " previous PN %pm received PN %pm\n",
+			//       hdr->addr2, key->rx_pn, pn);
 		}
 		key->dot11RSNAStatsCCMPReplays++;
 		return -4;
@@ -402,7 +400,7 @@
 		if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG "CCMP: decrypt failed: STA="
-				MAC_FMT "\n", MAC_ARG(hdr->addr2));
+				"%pM\n", hdr->addr2);
 			}
 			key->dot11RSNAStatsCCMPDecryptErrors++;
 			return -5;
@@ -477,12 +475,19 @@
 static char * ieee80211_ccmp_print_stats(char *p, void *priv)
 {
 	struct ieee80211_ccmp_data *ccmp = priv;
-	p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
-		     "tx_pn=%02x%02x%02x%02x%02x%02x "
-		     "rx_pn=%02x%02x%02x%02x%02x%02x "
-		     "format_errors=%d replays=%d decrypt_errors=%d\n",
-		     ccmp->key_idx, ccmp->key_set,
-		     MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
+	int i;
+
+	p += sprintf(p, "key[%d] alg=CCMP key_set=%d tx_pn=",
+		     ccmp->key_idx, ccmp->key_set);
+
+	for (i = 0; i < ARRAY_SIZE(ccmp->tx_pn); i++)
+		p += sprintf(p, "%02x", ccmp->tx_pn[i]);
+
+	sprintf(p, " rx_pn=");
+	for (i = 0; i < ARRAY_SIZE(ccmp->rx_pn); i++)
+		p += sprintf(p, "%02x", ccmp->tx_pn[i]);
+
+	p += sprintf(p, " format_errors=%d replays=%d decrypt_errors=%d\n",
 		     ccmp->dot11RSNAStatsCCMPFormatErrors,
 		     ccmp->dot11RSNAStatsCCMPReplays,
 		     ccmp->dot11RSNAStatsCCMPDecryptErrors);
@@ -519,7 +524,7 @@
 }
 
 
-void __exit ieee80211_crypto_ccmp_exit(void)
+void ieee80211_crypto_ccmp_exit(void)
 {
 	ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
 }
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
index 7a1797e..03cb21e 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
@@ -520,7 +520,7 @@
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "TKIP: received packet without ExtIV"
-			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			       " flag from %pM\n", hdr->addr2);
 		}
 		return -2;
 	}
@@ -532,9 +532,9 @@
 	}
 	if (!tkey->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
+			printk(KERN_DEBUG "TKIP: received packet from %pM"
 			       " with keyid=%d that does not have a configured"
-			       " key\n", MAC_ARG(hdr->addr2), keyidx);
+			       " key\n", hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -547,9 +547,9 @@
 		if (iv32 < tkey->rx_iv32 ||
 		(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
 			if (net_ratelimit()) {
-				printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
+				printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
 				" previous TSC %08x%04x received TSC "
-				"%08x%04x\n", MAC_ARG(hdr->addr2),
+				"%08x%04x\n", hdr->addr2,
 				tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
 			}
 			tkey->dot11RSNAStatsTKIPReplays++;
@@ -582,8 +582,8 @@
 		if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG ": TKIP: failed to decrypt "
-						"received packet from " MAC_FMT "\n",
-						MAC_ARG(hdr->addr2));
+						"received packet from %pM\n",
+						hdr->addr2);
 			}
 			return -7;
 		}
@@ -606,8 +606,9 @@
 				tkey->rx_phase1_done = 0;
 			}
 			if (net_ratelimit()) {
-				printk(KERN_DEBUG "TKIP: ICV error detected: STA="
-				MAC_FMT "\n", MAC_ARG(hdr->addr2));
+				printk(KERN_DEBUG
+				       "TKIP: ICV error detected: STA=%pM\n",
+				       hdr->addr2);
 			}
 			tkey->dot11RSNAStatsTKIPICVErrors++;
 			return -5;
@@ -816,8 +817,8 @@
 
 	/* TODO: needed parameters: count, keyid, key type, TSC */
 	sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
-		MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
-		MAC_ARG(hdr->addr2));
+		"%pM)", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
+		hdr->addr2);
 	memset(&wrqu, 0, sizeof(wrqu));
 	wrqu.data.length = strlen(buf);
 	wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
@@ -862,8 +863,8 @@
 		struct ieee80211_hdr_4addr *hdr;
 		hdr = (struct ieee80211_hdr_4addr *) skb->data;
 		printk(KERN_DEBUG "%s: Michael MIC verification failed for "
-		       "MSDU from " MAC_FMT " keyidx=%d\n",
-		       skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
+		       "MSDU from %pM keyidx=%d\n",
+		       skb->dev ? skb->dev->name : "N/A", hdr->addr2,
 		       keyidx);
 		if (skb->dev)
 			ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
@@ -1011,7 +1012,7 @@
 }
 
 
-void __exit ieee80211_crypto_tkip_exit(void)
+void ieee80211_crypto_tkip_exit(void)
 {
 	ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
 }
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
index 06d9171..ce265ae 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
@@ -312,6 +312,17 @@
 	if (skb->len < 24)
 		return 0;
 
+#if 1
+        if (ieee->hwsec_active)
+        {
+                cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
+                tcb_desc->bHwSec = 1;
+
+                if(ieee->need_sw_enc)
+                        tcb_desc->bHwSec = 0;
+        }
+#endif
+
 	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 
@@ -366,8 +377,8 @@
 	    strcmp(crypt->ops->name, "TKIP") == 0) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "received packet from " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(hdr->addr2));
+			       "received packet from %pM\n",
+			       ieee->dev->name, hdr->addr2);
 		}
 		return -1;
 	}
@@ -378,8 +389,8 @@
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
 		IEEE80211_DEBUG_DROP(
-			"decryption failed (SA=" MAC_FMT
-			") res=%d\n", MAC_ARG(hdr->addr2), res);
+			"decryption failed (SA=%pM"
+			") res=%d\n", hdr->addr2, res);
 		if (res == -2)
 			IEEE80211_DEBUG_DROP("Decryption failed ICV "
 					     "mismatch (key %d)\n",
@@ -406,6 +417,10 @@
 	{
 		cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
 		tcb_desc->bHwSec = 1;
+
+                if(ieee->need_sw_enc)
+                        tcb_desc->bHwSec = 0;
+
 	}
 
 	hdr = (struct ieee80211_hdr_4addr *) skb->data;
@@ -416,8 +431,8 @@
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
-		       " (SA=" MAC_FMT " keyidx=%d)\n",
-		       ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
+		       " (SA=%pM keyidx=%d)\n",
+		       ieee->dev->name, hdr->addr2, keyidx);
 		return -1;
 	}
 
@@ -799,7 +814,7 @@
 #endif
 }
 
-u8 parse_subframe(struct sk_buff *skb,
+u8 parse_subframe(struct ieee80211_device* ieee,struct sk_buff *skb,
                   struct ieee80211_rx_stats *rx_stats,
 		  struct ieee80211_rxb *rxb,u8* src,u8* dst)
 {
@@ -839,6 +854,7 @@
 	}
 
 	skb_pull(skb, LLCOffset);
+	ieee->bIsAggregateFrame = bIsAggregateFrame;//added by amy for Leisure PS
 
 	if(!bIsAggregateFrame) {
 		rxb->nr_subframes = 1;
@@ -940,6 +956,7 @@
 	u8	TID = 0;
 	u16	SeqNum = 0;
 	PRX_TS_RECORD pTS = NULL;
+	bool unicast_packet = false;
 	//bool bIsAggregateFrame = false;
 	//added by amy for reorder
 #ifdef NOT_YET
@@ -1045,8 +1062,8 @@
 			 * frames silently instead of filling system log with
 			 * these reports. */
 			IEEE80211_DEBUG_DROP("Decryption failed (not set)"
-					     " (SA=" MAC_FMT ")\n",
-					     MAC_ARG(hdr->addr2));
+					     " (SA=%pM)\n",
+					     hdr->addr2);
 			ieee->ieee_stats.rx_discards_undecryptable++;
 			goto rx_dropped;
 		}
@@ -1114,8 +1131,8 @@
 		    (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0)
 		{
 			printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
-			       "from " MAC_FMT "\n", dev->name,
-			       MAC_ARG(hdr->addr2));
+			       "from %pM\n", dev->name,
+			       hdr->addr2);
 			/* TODO: could inform hostapd about this so that it
 			 * could send auth failure report */
 			goto rx_dropped;
@@ -1215,6 +1232,24 @@
         if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
                 goto rx_dropped;
 
+#ifdef ENABLE_LPS
+	if ((ieee->iw_mode == IW_MODE_INFRA)  && (ieee->sta_sleep == 1)
+		&& (ieee->polling)) {
+		if (WLAN_FC_MORE_DATA(fc)) {
+			/* more data bit is set, let's request a new frame from the AP */
+			ieee80211_sta_ps_send_pspoll_frame(ieee);
+		} else {
+			ieee->polling =  false;
+		}
+	}
+#endif
+
+	ieee->need_sw_enc = 0;
+
+        if((!rx_stats->Decrypted)){
+                ieee->need_sw_enc = 1;
+        }
+
 	/* skb: hdr + (possibly fragmented, possibly encrypted) payload */
 
 	if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
@@ -1296,6 +1331,9 @@
 	ieee->LinkDetectInfo.NumRxOkInPeriod++;
 
 	hdr = (struct ieee80211_hdr_4addr *) skb->data;
+	if((!is_multicast_ether_addr(hdr->addr1)) && (!is_broadcast_ether_addr(hdr->addr1)))
+		unicast_packet = true;
+
 	if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
 		if (/*ieee->ieee802_1x &&*/
 		    ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
@@ -1311,8 +1349,8 @@
 		} else {
 			IEEE80211_DEBUG_DROP(
 				"encryption configured, but RX "
-				"frame not encrypted (SA=" MAC_FMT ")\n",
-				MAC_ARG(hdr->addr2));
+				"frame not encrypted (SA=%pM)\n",
+				hdr->addr2);
 			goto rx_dropped;
 		}
 	}
@@ -1331,9 +1369,9 @@
 	    !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
 		IEEE80211_DEBUG_DROP(
 			"dropped unencrypted RX data "
-			"frame from " MAC_FMT
+			"frame from %pM"
 			" (drop_unencrypted=1)\n",
-			MAC_ARG(hdr->addr2));
+			hdr->addr2);
 		goto rx_dropped;
 	}
 /*
@@ -1367,7 +1405,7 @@
 	}
 	/* to parse amsdu packets */
 	/* qos data packets & reserved bit is 1 */
-	if(parse_subframe(skb,rx_stats,rxb,src,dst) == 0) {
+	if(parse_subframe(ieee, skb,rx_stats,rxb,src,dst) == 0) {
 		/* only to free rxb, and not submit the packets to upper layer */
 		for(i =0; i < rxb->nr_subframes; i++) {
 			dev_kfree_skb(rxb->subframes[i]);
@@ -1377,6 +1415,32 @@
 		goto rx_dropped;
 	}
 
+#ifdef ENABLE_LPS
+		if(unicast_packet)
+		{
+			if (type == IEEE80211_FTYPE_DATA)
+			{
+
+				if(ieee->bIsAggregateFrame)
+					ieee->LinkDetectInfo.NumRxUnicastOkInPeriod+=rxb->nr_subframes;
+				else
+					ieee->LinkDetectInfo.NumRxUnicastOkInPeriod++;
+
+				// 2009.03.03 Leave DC mode immediately when detect high traffic
+				// DbgPrint("ending Seq %d\n", Frame_SeqNum(pduOS));
+				if((ieee->state == IEEE80211_LINKED) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/)
+				{
+					if(	((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
+						(ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
+					{
+						if(ieee->LeisurePSLeave)
+							ieee->LeisurePSLeave(dev);
+					}
+				}
+			}
+		}
+#endif
+
 	ieee->last_rx_ps_time = jiffies;
 //added by amy for reorder
 	if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){
@@ -2013,12 +2077,22 @@
 				info_element->data[1] == 0x13 &&
 				info_element->data[2] == 0x74))
 			{
-				printk("========>%s(): athros AP is exist\n",__FUNCTION__);
+				//printk("========>%s(): athros AP is exist\n",__FUNCTION__);
 				network->atheros_cap_exist = true;
 			}
 			else
 				network->atheros_cap_exist = false;
 
+			if ((info_element->len >= 3 &&
+						info_element->data[0] == 0x00 &&
+						info_element->data[1] == 0x50 &&
+						info_element->data[2] == 0x43) )
+			{
+				network->marvell_cap_exist = true;
+				//printk("========>%s(): marvel AP is exist\n",__FUNCTION__);
+			}
+
+
 			if(info_element->len >= 3 &&
 				info_element->data[0] == 0x00 &&
 				info_element->data[1] == 0x40 &&
@@ -2219,7 +2293,8 @@
 	}
 
 	if(!network->atheros_cap_exist && !network->broadcom_cap_exist &&
-		!network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation)
+		!network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation &&
+		!network->marvell_cap_exist)
 	{
 		network->unknown_cap_exist = true;
 	}
@@ -2333,6 +2408,7 @@
         network->broadcom_cap_exist = false;
 	network->ralink_cap_exist = false;
 	network->atheros_cap_exist = false;
+	network->marvell_cap_exist = false;
 	network->cisco_cap_exist = false;
 	network->unknown_cap_exist = false;
 #ifdef THOMAS_TURBO
@@ -2369,11 +2445,11 @@
 	}
 
 	if (network->mode == 0) {
-		IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
+		IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
 				     "network.\n",
 				     escape_essid(network->ssid,
 						  network->ssid_len),
-				     MAC_ARG(network->bssid));
+				     network->bssid);
 		return 1;
 	}
 
@@ -2463,6 +2539,7 @@
 	dst->broadcom_cap_exist = src->broadcom_cap_exist;
 	dst->ralink_cap_exist = src->ralink_cap_exist;
 	dst->atheros_cap_exist = src->atheros_cap_exist;
+	dst->marvell_cap_exist = src->marvell_cap_exist;
 	dst->cisco_cap_exist = src->cisco_cap_exist;
 	dst->unknown_cap_exist = src->unknown_cap_exist;
 	memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
@@ -2557,9 +2634,9 @@
 
 	memset(&network, 0, sizeof(struct ieee80211_network));
 	IEEE80211_DEBUG_SCAN(
-		"'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+		"'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
 		escape_essid(info_element->data, info_element->len),
-		MAC_ARG(beacon->header.addr3),
+		beacon->header.addr3,
 		(beacon->capability & (1<<0xf)) ? '1' : '0',
 		(beacon->capability & (1<<0xe)) ? '1' : '0',
 		(beacon->capability & (1<<0xd)) ? '1' : '0',
@@ -2578,10 +2655,10 @@
 		(beacon->capability & (1<<0x0)) ? '1' : '0');
 
 	if (ieee80211_network_init(ieee, beacon, &network, stats)) {
-		IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
 				     escape_essid(info_element->data,
 						  info_element->len),
-				     MAC_ARG(beacon->header.addr3),
+				     beacon->header.addr3,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
@@ -2692,11 +2769,11 @@
 			/* If there are no more slots, expire the oldest */
 			list_del(&oldest->list);
 			target = oldest;
-			IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
+			IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
 					     "network list.\n",
 					     escape_essid(target->ssid,
 							  target->ssid_len),
-					     MAC_ARG(target->bssid));
+					     target->bssid);
 		} else {
 			/* Otherwise just pull from the free list */
 			target = list_entry(ieee->network_free_list.next,
@@ -2706,10 +2783,10 @@
 
 
 #ifdef CONFIG_IEEE80211_DEBUG
-		IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
 				     escape_essid(network.ssid,
 						  network.ssid_len),
-				     MAC_ARG(network.bssid),
+				     network.bssid,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
@@ -2719,10 +2796,10 @@
 		if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
 			ieee80211_softmac_new_net(ieee,&network);
 	} else {
-		IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
 				     escape_essid(target->ssid,
 						  target->ssid_len),
-				     MAC_ARG(target->bssid),
+				     target->bssid,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
@@ -2761,12 +2838,14 @@
 		      struct ieee80211_hdr_4addr *header,
 		      struct ieee80211_rx_stats *stats)
 {
+#if 0
 	if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
 				ieee->iw_mode == IW_MODE_INFRA &&
 				ieee->state == IEEE80211_LINKED))
 	{
 		tasklet_schedule(&ieee->ps_task);
 	}
+#endif
 
 	if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
 		WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
@@ -2780,6 +2859,15 @@
 		IEEE80211_DEBUG_SCAN("Beacon\n");
 		ieee80211_process_probe_response(
 			ieee, (struct ieee80211_probe_response *)header, stats);
+
+		//printk("----------->%s()\n", __func__);
+		if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
+					ieee->iw_mode == IW_MODE_INFRA &&
+					ieee->state == IEEE80211_LINKED))
+		{
+			tasklet_schedule(&ieee->ps_task);
+		}
+
 		break;
 
 	case IEEE80211_STYPE_PROBE_RESP:
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
index 6d1ddec..ea96c49 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
@@ -646,7 +646,7 @@
 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
 {
 	if(ieee->start_send_beacons)
-		ieee->start_send_beacons(ieee->dev,ieee->basic_rate);
+		ieee->start_send_beacons(ieee->dev);
 	if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
 		ieee80211_beacons_start(ieee);
 }
@@ -686,6 +686,11 @@
 /* called with ieee->lock held */
 void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
 {
+#ifdef ENABLE_IPS
+	if(ieee->ieee80211_ips_leave_wq != NULL)
+		ieee->ieee80211_ips_leave_wq(ieee->dev);
+#endif
+
 #ifdef ENABLE_DOT11D
 	if(IS_DOT11D_ENABLE(ieee) )
 	{
@@ -1093,6 +1098,40 @@
 
 }
 
+struct sk_buff* ieee80211_pspoll_func(struct ieee80211_device *ieee)
+{
+	struct sk_buff *skb;
+	struct ieee80211_pspoll_hdr* hdr;
+
+#ifdef USB_USE_ALIGNMENT
+        u32 Tmpaddr=0;
+        int alignment=0;
+        skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
+#else
+	skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr)+ieee->tx_headroom);
+#endif
+	if (!skb)
+		return NULL;
+
+#ifdef USB_USE_ALIGNMENT
+        Tmpaddr = (u32)skb->data;
+        alignment = Tmpaddr & 0x1ff;
+        skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+	skb_reserve(skb, ieee->tx_headroom);
+
+	hdr = (struct ieee80211_pspoll_hdr*)skb_put(skb,sizeof(struct ieee80211_pspoll_hdr));
+
+	memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN);
+	memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN);
+
+	hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000);
+	hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_CTL |IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM);
+
+	return skb;
+
+}
+
 
 void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
 {
@@ -1582,6 +1621,11 @@
 {
 #endif
 	ieee->sync_scan_hurryup = 1;
+#ifdef ENABLE_IPS
+	if(ieee->ieee80211_ips_leave != NULL)
+        	ieee->ieee80211_ips_leave(ieee->dev);
+#endif
+
 	down(&ieee->wx_sem);
 
 	if (ieee->data_hard_stop)
@@ -1592,6 +1636,17 @@
 	//ieee->set_chan(ieee->dev, ieee->current_network.channel);
 	HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
 
+#ifdef ENABLE_IPS
+	if(ieee->eRFPowerState == eRfOff)
+	{
+		if(ieee->ieee80211_ips_leave_wq != NULL)
+			ieee->ieee80211_ips_leave_wq(ieee->dev);
+
+		up(&ieee->wx_sem);
+		return;
+	}
+#endif
+
 	ieee->associate_seq = 1;
 	ieee80211_associate_step1(ieee);
 
@@ -1897,7 +1952,7 @@
 		ieee80211_resp_to_assoc_rq(ieee, dest);
 	}
 
-	printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
+	printk(KERN_INFO"New client associated: %pM\n", dest);
 	//FIXME
 	#if 0
 	spin_lock_irqsave(&ieee->lock,flags);
@@ -1918,43 +1973,92 @@
 
 }
 
+void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
+{
+
+	struct sk_buff *buf = ieee80211_pspoll_func(ieee);
+
+	if (buf)
+		softmac_ps_mgmt_xmit(buf, ieee);
+
+}
 
 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
 {
 	int timeout = ieee->ps_timeout;
 	u8 dtim;
-	/*if(ieee->ps == IEEE80211_PS_DISABLED ||
-		ieee->iw_mode != IW_MODE_INFRA ||
-		ieee->state != IEEE80211_LINKED)
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
 
+	if(ieee->LPSDelayCnt)
+	{
+		//printk("===============>Delay enter LPS for DHCP and ARP packets...\n");
+		ieee->LPSDelayCnt --;
 		return 0;
-	*/
+	}
+
 	dtim = ieee->current_network.dtim_data;
-	//printk("DTIM\n");
+//	printk("%s():DTIM:%d\n",__FUNCTION__,dtim);
 	if(!(dtim & IEEE80211_DTIM_VALID))
 		return 0;
 	timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
 	//printk("VALID\n");
 	ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
-
-	if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
+	/* there's no need to nofity AP that I find you buffered with broadcast packet */
+	if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
 		return 2;
 
-	if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
+	if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
+//		printk("%s():111Oh Oh ,it is not time out return 0\n",__FUNCTION__);
 		return 0;
-
-	if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
+	}
+	if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
+//		printk("%s():222Oh Oh ,it is not time out return 0\n",__FUNCTION__);
 		return 0;
-
+	}
 	if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
 		(ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
 		return 0;
 
 	if(time_l){
+		if(ieee->bAwakePktSent == true) {
+			pPSC->LPSAwakeIntvl = 1;//tx wake one beacon
+		} else {
+			u8		MaxPeriod = 1;
+
+			if(pPSC->LPSAwakeIntvl == 0)
+				pPSC->LPSAwakeIntvl = 1;
+			//pNdisCommon->RegLPSMaxIntvl /// 0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl
+			if(pPSC->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
+				MaxPeriod = 1; // 1 Beacon interval
+			else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
+				MaxPeriod = ieee->current_network.dtim_period;
+			else
+				MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
+			pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1);
+		}
+		{
+			u8 LPSAwakeIntvl_tmp = 0;
+			u8 period = ieee->current_network.dtim_period;
+			u8 count = ieee->current_network.tim.tim_count;
+			if(count == 0 ) {
+				if(pPSC->LPSAwakeIntvl > period)
+					LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period);
+				else
+					LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
+
+			} else {
+				if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
+					LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period);
+				else
+					LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;//ieee->current_network.tim.tim_count;//pPSC->LPSAwakeIntvl;
+			}
+			//printk("=========>%s()assoc_id:%d(%#x),bAwakePktSent:%d,DTIM:%d, sleep interval:%d, LPSAwakeIntvl_tmp:%d, count:%d\n",__func__,ieee->assoc_id,cpu_to_le16(ieee->assoc_id),ieee->bAwakePktSent,ieee->current_network.dtim_period,pPSC->LPSAwakeIntvl,LPSAwakeIntvl_tmp,count);
+
 		*time_l = ieee->current_network.last_dtim_sta_time[0]
-			+ (ieee->current_network.beacon_interval);
+			+ MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
 		//	* ieee->current_network.dtim_period) * 1000;
 	}
+	}
 
 	if(time_h){
 		*time_h = ieee->current_network.last_dtim_sta_time[1];
@@ -1982,6 +2086,8 @@
 		ieee->state != IEEE80211_LINKED)){
 
 	//	#warning CHECK_LOCK_HERE
+		printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
+			__FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
 		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
 
 		ieee80211_sta_wakeup(ieee, 1);
@@ -1991,27 +2097,27 @@
 
 	sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
 	/* 2 wake, 1 sleep, 0 do nothing */
-	if(sleep == 0)
+	if(sleep == 0)//it is not time out or dtim is not valid
+	{
+		//printk("===========>sleep is 0,do nothing\n");
 		goto out;
-
+	}
 	if(sleep == 1){
-
-		if(ieee->sta_sleep == 1)
+		//printk("===========>sleep is 1,to sleep\n");
+		if(ieee->sta_sleep == 1){
+			//printk("%s(1): sta_sleep = 1, sleep again ++++++++++ \n", __func__);
 			ieee->enter_sleep_state(ieee->dev,th,tl);
+		}
 
 		else if(ieee->sta_sleep == 0){
 		//	printk("send null 1\n");
 			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
 
 			if(ieee->ps_is_queue_empty(ieee->dev)){
-
-
 				ieee->sta_sleep = 2;
-
 				ieee->ack_tx_to_ieee = 1;
-
+				//printk("%s(2): sta_sleep = 0, notify AP we will sleeped ++++++++++ SendNullFunctionData\n", __func__);
 				ieee80211_sta_ps_send_null_frame(ieee,1);
-
 				ieee->ps_th = th;
 				ieee->ps_tl = tl;
 			}
@@ -2019,11 +2125,13 @@
 
 		}
 
+		ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
 
 	}else if(sleep == 2){
-//#warning CHECK_LOCK_HERE
+		//printk("==========>sleep is 2,to wakeup\n");
 		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
 
+		//printk("%s(3): pkt buffered in ap will awake ++++++++++ ieee80211_sta_wakeup\n", __func__);
 		ieee80211_sta_wakeup(ieee,1);
 
 		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
@@ -2038,9 +2146,19 @@
 {
 	if(ieee->sta_sleep == 0){
 		if(nl){
-			printk("Warning: driver is probably failing to report TX ps error\n");
-			ieee->ack_tx_to_ieee = 1;
-			ieee80211_sta_ps_send_null_frame(ieee, 0);
+			if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+			{
+				//printk("%s(1): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
+				//printk("Warning: driver is probably failing to report TX ps error\n");
+				ieee->ack_tx_to_ieee = 1;
+				ieee80211_sta_ps_send_null_frame(ieee, 0);
+			}
+			else
+			{
+				ieee->ack_tx_to_ieee = 1;
+				//printk("%s(2): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
+				ieee80211_sta_ps_send_pspoll_frame(ieee);
+			}
 		}
 		return;
 
@@ -2048,12 +2166,27 @@
 
 	if(ieee->sta_sleep == 1)
 		ieee->sta_wake_up(ieee->dev);
-
-	ieee->sta_sleep = 0;
-
 	if(nl){
-		ieee->ack_tx_to_ieee = 1;
-		ieee80211_sta_ps_send_null_frame(ieee, 0);
+
+			if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+			{
+				//printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
+				//printk("Warning: driver is probably failing to report TX ps error\n");
+				ieee->ack_tx_to_ieee = 1;
+				ieee80211_sta_ps_send_null_frame(ieee, 0);
+			}
+			else
+			{
+				ieee->ack_tx_to_ieee = 1;
+			ieee->polling = true;
+				//printk("%s(4): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
+				//ieee80211_sta_ps_send_null_frame(ieee, 0);
+				ieee80211_sta_ps_send_pspoll_frame(ieee);
+			}
+
+	} else {
+		ieee->sta_sleep = 0;
+		ieee->polling = false;
 	}
 }
 
@@ -2067,23 +2200,30 @@
 		/* Null frame with PS bit set */
 		if(success){
 			ieee->sta_sleep = 1;
+			//printk("notify AP we will sleep and send null ok, so sleep now++++++++++ enter_sleep_state\n");
 			ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
 		}
-		/* if the card report not success we can't be sure the AP
-		 * has not RXed so we can't assume the AP believe us awake
-		 */
-	}
-	/* 21112005 - tx again null without PS bit if lost */
-	else {
+	} else {/* 21112005 - tx again null without PS bit if lost */
 
 		if((ieee->sta_sleep == 0) && !success){
 			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
-			ieee80211_sta_ps_send_null_frame(ieee, 0);
+			//ieee80211_sta_ps_send_null_frame(ieee, 0);
+			if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+			{
+				//printk("notify AP we will sleep but send bull failed, so resend++++++++++ SendNullFunctionData\n");
+				ieee80211_sta_ps_send_null_frame(ieee, 0);
+			}
+			else
+			{
+				//printk("notify AP we are awaked but send pspoll failed, so resend++++++++++ Send PS-Poll\n");
+				ieee80211_sta_ps_send_pspoll_frame(ieee);
+			}
 			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
 		}
 	}
 	spin_unlock_irqrestore(&ieee->lock, flags);
 }
+
 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
 {
 	struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
@@ -2227,7 +2367,7 @@
 								{
 									if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
 									{
-												// WEP or TKIP encryption
+										// WEP or TKIP encryption
 										if(IsHTHalfNmodeAPs(ieee))
 										{
 											bSupportNmode = true;
@@ -2238,7 +2378,7 @@
 											bSupportNmode = false;
 											bHalfSupportNmode = false;
 										}
-									printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
+									printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
 									}
 								}
 								/* Dummy wirless mode setting to avoid encryption issue */
@@ -2574,6 +2714,7 @@
 		ieee->ssid_set = 1;
 	}
 
+	ieee->state = IEEE80211_NOLINK;
 	/* check if we have this cell in our network list */
 	ieee80211_softmac_check_all_nets(ieee);
 
@@ -2705,6 +2846,10 @@
 	spin_lock_irqsave(&ieee->lock, flags);
 
 	if (ieee->state == IEEE80211_NOLINK){
+#ifdef ENABLE_IPS
+		if(ieee->ieee80211_ips_leave_wq != NULL)
+			ieee->ieee80211_ips_leave_wq(ieee->dev);
+#endif
 		ieee->actscanning = true;
 		ieee80211_rtl_start_scan(ieee);
 	}
@@ -2823,21 +2968,23 @@
 	return skb;
 }
 
-void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
+void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
 {
 	ieee->sync_scan_hurryup = 1;
 	down(&ieee->wx_sem);
-	ieee80211_stop_protocol(ieee);
+	ieee80211_stop_protocol(ieee, shutdown);
 	up(&ieee->wx_sem);
 }
 
 
-void ieee80211_stop_protocol(struct ieee80211_device *ieee)
+void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
 {
 	if (!ieee->proto_started)
 		return;
 
-	ieee->proto_started = 0;
+	if(shutdown)
+		ieee->proto_started = 0;
+	ieee->proto_stoppping = 1;
 
 	ieee80211_stop_send_beacons(ieee);
 	del_timer_sync(&ieee->associate_timer);
@@ -2849,6 +2996,8 @@
 
 	ieee80211_disassociate(ieee);
 	RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
+
+	ieee->proto_stoppping = 0;
 }
 
 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
@@ -2894,6 +3043,8 @@
 
 	ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
 
+	ieee->state = IEEE80211_NOLINK;
+
 
 	/* if the user set the MAC of the ad-hoc cell and then
 	 * switch to managed mode, shall we  make sure that association
@@ -3013,7 +3164,9 @@
 #endif
 	sema_init(&ieee->wx_sem, 1);
 	sema_init(&ieee->scan_sem, 1);
-
+#ifdef ENABLE_IPS
+	sema_init(&ieee->ips_sem,1);
+#endif
 	spin_lock_init(&ieee->mgmt_tx_lock);
 	spin_lock_init(&ieee->beacon_lock);
 
@@ -3537,5 +3690,6 @@
 EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
 EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
+EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_null_frame);
+EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_pspoll_frame);
 #endif
-//EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame);
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
index 7c21aaa..1bbd49f 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
@@ -160,7 +160,7 @@
 	}
 
 	if (ifup)
-		ieee80211_stop_protocol(ieee);
+		ieee80211_stop_protocol(ieee,true);
 
 	/* just to avoid to give inconsistent infos in the
 	 * get wx method. not really needed otherwise
@@ -302,7 +302,7 @@
 	if (!ieee->proto_started){
 		ieee->iw_mode = wrqu->mode;
 	}else{
-		ieee80211_stop_protocol(ieee);
+		ieee80211_stop_protocol(ieee,true);
 		ieee->iw_mode = wrqu->mode;
 		ieee80211_start_protocol(ieee);
 	}
@@ -326,6 +326,17 @@
 	int b40M = 0;
 	static int count = 0;
 	chan = ieee->current_network.channel;
+
+#ifdef ENABLE_LPS
+	if (ieee->LeisurePSLeave) {
+		ieee->LeisurePSLeave(ieee->dev);
+	}
+
+	/* notify AP to be in PS mode */
+	ieee80211_sta_ps_send_null_frame(ieee, 1);
+	ieee80211_sta_ps_send_null_frame(ieee, 1);
+#endif
+
 	netif_carrier_off(ieee->dev);
 
 	if (ieee->data_hard_stop)
@@ -360,6 +371,12 @@
 	ieee->InitialGainHandler(ieee->dev,IG_Restore);
 	ieee->state = IEEE80211_LINKED;
 	ieee->link_change(ieee->dev);
+
+#ifdef ENABLE_LPS
+	/* Notify AP that I wake up again */
+	ieee80211_sta_ps_send_null_frame(ieee, 0);
+#endif
+
 	// To prevent the immediately calling watch_dog after scan.
 	if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
 	{
@@ -429,8 +446,9 @@
 		goto out;
 	}
 
-	if(proto_started)
-		ieee80211_stop_protocol(ieee);
+	if(proto_started){
+		ieee80211_stop_protocol(ieee,true);
+	}
 
 
 	/* this is just to be sure that the GET wx callback
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
index 798fb41..a75f366 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
@@ -200,8 +200,8 @@
 		header = (struct ieee80211_hdr *) frag->data;
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "TX packet to " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(header->addr1));
+			       "TX packet to %pM\n",
+			       ieee->dev->name, header->addr1);
 		}
 		return -1;
 	}
@@ -334,6 +334,13 @@
 	if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
 		return;
 #endif
+
+        if(tcb_desc->bdhcp)// || ieee->CntAfterLink<2)
+        {
+                return;
+        }
+
+
 #if 1
 	if(!ieee->GetNmodeSupportBySecCfg(ieee->dev))
 	{
@@ -628,6 +635,7 @@
 	int qos_actived = ieee->current_network.qos_data.active;
 
 	struct ieee80211_crypt_data* crypt;
+	bool    bdhcp =false;
 
 	cb_desc *tcb_desc;
 
@@ -672,6 +680,55 @@
 		}
 	#endif
 
+		// The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time
+		// to prevent DHCP protocol fail
+		if (skb->len > 282){//MINIMUM_DHCP_PACKET_SIZE) {
+			if (ETH_P_IP == ether_type) {// IP header
+				const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14);
+				if (IPPROTO_UDP == ip->protocol) {//FIXME windows is 11 but here UDP in linux kernel is 17.
+					struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
+					//if(((ntohs(udp->source) == 68) && (ntohs(udp->dest) == 67)) ||
+					///   ((ntohs(udp->source) == 67) && (ntohs(udp->dest) == 68))) {
+					if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) ||
+							((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) {
+						// 68 : UDP BOOTP client
+						// 67 : UDP BOOTP server
+						printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]);
+						// Use low rate to send DHCP packet.
+						//if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+						//{
+						//      tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m
+						//      tcb_desc->bTxDisableRateFallBack = false;
+						//}
+						//else
+						//pTcb->DataRate = Adapter->MgntInfo.LowestBasicRate;
+						//RTPRINT(FDM, WA_IOT, ("DHCP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate));
+
+						bdhcp = true;
+#ifdef _RTL8192_EXT_PATCH_
+						ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2; //AMY,090701
+#else
+						ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2;
+#endif
+					}
+				}
+				}else if(ETH_P_ARP == ether_type){// IP ARP packet
+					printk("=================>DHCP Protocol start tx ARP pkt!!\n");
+					bdhcp = true;
+					ieee->LPSDelayCnt = ieee->current_network.tim.tim_count;
+
+					//if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+					//{
+					//      tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(Adapter->MgntInfo.mBrates);//0xc;//ofdm 6m
+					//      tcb_desc->bTxDisableRateFallBack = FALSE;
+					//}
+					//else
+					//      tcb_desc->DataRate = Adapter->MgntInfo.LowestBasicRate;
+					//RTPRINT(FDM, WA_IOT, ("ARP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate));
+
+				}
+			}
+
 		/* Save source and destination addresses */
 		memcpy(&dest, skb->data, ETH_ALEN);
 		memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
@@ -895,6 +952,25 @@
 		else
 			//tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate);
 			tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
+
+		if(bdhcp == true){
+			// Use low rate to send DHCP packet.
+			//if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) {
+			//	tcb_desc->data_rate = MGN_1M;//MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m
+			//	tcb_desc->bTxDisableRateFallBack = false;
+			//}
+			//else
+			{
+				tcb_desc->data_rate = MGN_1M;
+				tcb_desc->bTxDisableRateFallBack = 1;
+			}
+
+			tcb_desc->RATRIndex = 7;
+			tcb_desc->bTxUseDriverAssingedRate = 1;
+			tcb_desc->bdhcp = 1;
+		}
+
+
 		ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc);
 		ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
 		ieee80211_query_HTCapShortGI(ieee, tcb_desc);
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
index 3441b72..a3302d5 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
@@ -386,10 +386,10 @@
 		else
 			IEEE80211_DEBUG_SCAN(
 				"Not showing network '%s ("
-				MAC_FMT ")' due to age (%lums).\n",
+				"%pM)' due to age (%lums).\n",
 				escape_essid(network->ssid,
 					     network->ssid_len),
-				MAC_ARG(network->bssid),
+				network->bssid,
 				(jiffies - network->last_scanned) / (HZ / 100));
 	}
 
@@ -933,7 +933,7 @@
 #if 1
 	case IW_AUTH_WPA_ENABLED:
 		ieee->wpa_enabled = (data->value)?1:0;
-		//printk("enalbe wpa:%d\n", ieee->wpa_enabled);
+		//printk("enable wpa:%d\n", ieee->wpa_enabled);
 		break;
 
 #endif
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
index e41e8a0..ae0e5b9 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
@@ -113,7 +113,7 @@
 	u16 tmp = 0;
 	u16 len = ieee->tx_headroom + 9;
 	//category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) +  BA Timeout Value(2) +  BA Start SeqCtrl(2)(or StatusCode(2))
-	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __FUNCTION__, type, MAC_ARG(Dst), ieee->dev);
+	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
 	if (pBA == NULL||ieee == NULL)
 	{
 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
@@ -243,7 +243,7 @@
 	u16 len = 6 + ieee->tx_headroom;
 
 	if (net_ratelimit())
-	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst));
+	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
 
 	memset(&DelbaParamSet, 0, 2);
 
@@ -397,7 +397,7 @@
 	pBaTimeoutVal = (u16*)(tag + 5);
 	pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
 
-	printk("====================>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst));
+	printk("====================>rx ADDBAREQ from :%pM\n", dst);
 //some other capability is not ready now.
 	if(	(ieee->current_network.qos_data.active == 0) ||
 		(ieee->pHTInfo->bCurrentHTSupport == false)) //||
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
index 992b718..f968817 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
@@ -458,7 +458,8 @@
 	HT_IOT_PEER_RALINK = 3,
 	HT_IOT_PEER_ATHEROS = 4,
 	HT_IOT_PEER_CISCO= 5,
-	HT_IOT_PEER_MAX = 6
+        HT_IOT_PEER_MARVELL=6,
+	HT_IOT_PEER_MAX = 7
 }HT_IOT_PEER_E, *PHTIOT_PEER_E;
 
 //
@@ -475,6 +476,7 @@
 	HT_IOT_ACT_CDD_FSYNC = 0x00000080,
 	HT_IOT_ACT_PURE_N_MODE = 0x00000100,
 	HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200,
+	HT_IOT_ACT_NULL_DATA_POWER_SAVING = 0x00800000,
 }HT_IOT_ACTION_E, *PHT_IOT_ACTION_E;
 
 #endif //_RTL819XU_HTTYPE_H_
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
index 1e392141..4c4b1df 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
@@ -32,7 +32,7 @@
 static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf};
 static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70};
 static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e};
-static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f};
+//static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f};
 static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f};	//cosa 03202008
 static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf};
 static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc};
@@ -40,8 +40,9 @@
 static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
 static u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0};
 static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
+static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
 
-// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Shoud we put the
+// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Should we put the
 // code in other place??
 //static u8 WIFI_CISCO_G_AP[3] = {0x00, 0x40, 0x96};
 /********************************************************************************************************************
@@ -349,12 +350,12 @@
 	bool			retValue = false;
 	struct ieee80211_network* net = &ieee->current_network;
 #if 0
-	if(pMgntInfo->bHalfNMode == false)
+	if(ieee->bHalfNMode == false)
 		retValue = false;
 	else
 #endif
 	if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
-		     (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
+	   	     (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
 		     (memcmp(net->bssid, PCI_RALINK, 3)==0) ||
 		     (memcmp(net->bssid, EDIMAX_RALINK, 3)==0) ||
 		     (memcmp(net->bssid, AIRLINK_RALINK, 3)==0) ||
@@ -363,7 +364,7 @@
 	else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
     		    (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
     		    (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
-    		    (memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ||
+    		    //(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ||
     		    (net->broadcom_cap_exist))
     		  retValue = true;
 	else if(net->bssht.bdRT2RTAggregation)
@@ -387,13 +388,15 @@
 	struct ieee80211_network* net = &ieee->current_network;
 	if(net->bssht.bdRT2RTAggregation)
 		pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK;
-	else if(net->broadcom_cap_exist)
+	else if(net->broadcom_cap_exist){
 		pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
+	}
 	else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
 			(memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
-			(memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
-			(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) )
+			(memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)){//||
+			//(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ){
 		pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
+	}
 	else if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
 			(memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
 			(memcmp(net->bssid, PCI_RALINK, 3)==0) ||
@@ -405,6 +408,10 @@
 		pHTInfo->IOTPeer = HT_IOT_PEER_ATHEROS;
 	else if(memcmp(net->bssid, CISCO_BROADCOM, 3)==0)
 		pHTInfo->IOTPeer = HT_IOT_PEER_CISCO;
+        else if ((memcmp(net->bssid, LINKSYS_MARVELL_4400N, 3) == 0) ||
+			net->marvell_cap_exist){
+		pHTInfo->IOTPeer = HT_IOT_PEER_MARVELL;
+	}
 	else
 		pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
 
@@ -442,6 +449,18 @@
 	return ret;
  }
 
+u8 HTIOTActIsForcedCTS2Self(struct ieee80211_device *ieee, struct ieee80211_network *network)
+{
+        u8      retValue = 0;
+        //if(network->marvell_cap_exist)
+        if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL)
+        {
+                retValue = 1;
+        }
+
+        return retValue;
+}
+
 
 /**
 * Function:	HTIOTActIsDisableMCS15
@@ -578,6 +597,23 @@
 	return retValue;
 }
 
+//
+//  Send null data for to tell AP that we are awake.
+//
+bool
+HTIOTActIsNullDataPowerSaving(struct ieee80211_device* ieee,struct ieee80211_network *network)
+{
+	bool	retValue = false;
+
+	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
+	{
+		if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) // ||(pBssDesc->Vender == HT_IOT_PEER_ATHEROS && pBssDesc->SubTypeOfVender == HT_IOT_PEER_ATHEROS_DIR635))
+			return true;
+
+	}
+	return retValue;
+}
+
 void HTResetIOTSetting(
 	PRT_HIGH_THROUGHPUT		pHTInfo
 )
@@ -1071,6 +1107,13 @@
 	// Config and configure A-MSDU setting
 	//
 	pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
+        if (ieee->rtllib_ap_sec_type &&
+           (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))){
+                if( (pHTInfo->IOTPeer== HT_IOT_PEER_ATHEROS) ||
+                                (pHTInfo->IOTPeer == HT_IOT_PEER_UNKNOWN) )
+                        pHTInfo->bCurrentAMPDUEnable = false;
+        }
+
 
 	nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize==0)?3839:7935;
 
@@ -1515,6 +1558,9 @@
 		bIOTAction = HTIOTActIsDisableMCS14(ieee, pNetwork->bssid);
 		if(bIOTAction)
 			pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS14;
+		bIOTAction = HTIOTActIsForcedCTS2Self(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
 
 		bIOTAction = HTIOTActIsDisableMCS15(ieee);
 		if(bIOTAction)
@@ -1537,6 +1583,9 @@
 		if(bIOTAction)
 			pHTInfo->IOTAction |= HT_IOT_ACT_CDD_FSYNC;
 
+		bIOTAction = HTIOTActIsNullDataPowerSaving(ieee, pNetwork);
+		if(bIOTAction)
+			pHTInfo->IOTAction |= HT_IOT_ACT_NULL_DATA_POWER_SAVING;
 
 	}
 	else
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
index 2816b60..e2cbfd3 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
@@ -304,7 +304,7 @@
 		if(search_dir[dir] ==false )
 			continue;
 		list_for_each_entry(pRet, psearch_list, List){
-	//		IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:"MAC_FMT", TID:%d, dir:%d\n", MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
+	//		IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
 			if (memcmp(pRet->Addr, Addr, 6) == 0)
 				if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
 					if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
@@ -466,7 +466,7 @@
 					ResetRxTsEntry(tmp);
 				}
 
-				IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT"\n", UP, Dir, MAC_ARG(Addr));
+				IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
 				// Prepare TS Info releated field
 				pTSInfo->field.ucTrafficType = 0;			// Traffic type: WMM is reserved in this field
 				pTSInfo->field.ucTSID = UP;			// TSID
@@ -552,7 +552,7 @@
 void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr)
 {
 	PTS_COMMON_INFO	pTS, pTmpTS;
-	printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr));
+	printk("===========>RemovePeerTS,%pM\n", Addr);
 #if 1
 	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
 	{
diff --git a/drivers/staging/rtl8192e/r8180_93cx6.c b/drivers/staging/rtl8192e/r8180_93cx6.c
index 79f7a0f..262ed5f 100644
--- a/drivers/staging/rtl8192e/r8180_93cx6.c
+++ b/drivers/staging/rtl8192e/r8180_93cx6.c
@@ -22,7 +22,7 @@
 
 static void eprom_cs(struct net_device *dev, short bit)
 {
-	if(bit)
+	if (bit)
 		write_nic_byte(dev, EPROM_CMD,
 			       (1<<EPROM_CS_SHIFT) | \
 			       read_nic_byte(dev, EPROM_CMD)); //enable EPROM
@@ -38,23 +38,23 @@
 static void eprom_ck_cycle(struct net_device *dev)
 {
 	write_nic_byte(dev, EPROM_CMD,
-		       (1<<EPROM_CK_SHIFT) | read_nic_byte(dev,EPROM_CMD));
+		       (1<<EPROM_CK_SHIFT) | read_nic_byte(dev, EPROM_CMD));
 	force_pci_posting(dev);
 	udelay(EPROM_DELAY);
 	write_nic_byte(dev, EPROM_CMD,
-		       read_nic_byte(dev, EPROM_CMD) &~ (1<<EPROM_CK_SHIFT));
+		       read_nic_byte(dev, EPROM_CMD) & ~(1<<EPROM_CK_SHIFT));
 	force_pci_posting(dev);
 	udelay(EPROM_DELAY);
 }
 
 
-static void eprom_w(struct net_device *dev,short bit)
+static void eprom_w(struct net_device *dev, short bit)
 {
-	if(bit)
+	if (bit)
 		write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) | \
-			       read_nic_byte(dev,EPROM_CMD));
+			       read_nic_byte(dev, EPROM_CMD));
 	else
-		write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev,EPROM_CMD)\
+		write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)\
 			       &~(1<<EPROM_W_SHIFT));
 
 	force_pci_posting(dev);
@@ -66,10 +66,11 @@
 {
 	short bit;
 
-	bit=(read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT) );
+	bit = (read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT));
 	udelay(EPROM_DELAY);
 
-	if(bit) return 1;
+	if (bit)
+		return 1;
 	return 0;
 }
 
@@ -78,7 +79,7 @@
 {
 	int i;
 
-	for(i=0; i<len; i++){
+	for (i = 0; i < len; i++) {
 		eprom_w(dev, b[i]);
 		eprom_ck_cycle(dev);
 	}
@@ -88,37 +89,37 @@
 u32 eprom_read(struct net_device *dev, u32 addr)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
-	short read_cmd[]={1,1,0};
+	short read_cmd[] = {1, 1, 0};
 	short addr_str[8];
 	int i;
 	int addr_len;
 	u32 ret;
 
-	ret=0;
+	ret = 0;
         //enable EPROM programming
 	write_nic_byte(dev, EPROM_CMD,
 		       (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT));
 	force_pci_posting(dev);
 	udelay(EPROM_DELAY);
 
-	if (priv->epromtype==EPROM_93c56){
-		addr_str[7]=addr & 1;
-		addr_str[6]=addr & (1<<1);
-		addr_str[5]=addr & (1<<2);
-		addr_str[4]=addr & (1<<3);
-		addr_str[3]=addr & (1<<4);
-		addr_str[2]=addr & (1<<5);
-		addr_str[1]=addr & (1<<6);
-		addr_str[0]=addr & (1<<7);
-		addr_len=8;
-	}else{
-		addr_str[5]=addr & 1;
-		addr_str[4]=addr & (1<<1);
-		addr_str[3]=addr & (1<<2);
-		addr_str[2]=addr & (1<<3);
-		addr_str[1]=addr & (1<<4);
-		addr_str[0]=addr & (1<<5);
-		addr_len=6;
+	if (priv->epromtype == EPROM_93c56) {
+		addr_str[7] = addr & 1;
+		addr_str[6] = addr & (1<<1);
+		addr_str[5] = addr & (1<<2);
+		addr_str[4] = addr & (1<<3);
+		addr_str[3] = addr & (1<<4);
+		addr_str[2] = addr & (1<<5);
+		addr_str[1] = addr & (1<<6);
+		addr_str[0] = addr & (1<<7);
+		addr_len = 8;
+	} else {
+		addr_str[5] = addr & 1;
+		addr_str[4] = addr & (1<<1);
+		addr_str[3] = addr & (1<<2);
+		addr_str[2] = addr & (1<<3);
+		addr_str[1] = addr & (1<<4);
+		addr_str[0] = addr & (1<<5);
+		addr_len = 6;
 	}
 	eprom_cs(dev, 1);
 	eprom_ck_cycle(dev);
@@ -129,7 +130,7 @@
 	//I'm unsure if it is necessary, but anyway shouldn't hurt
 	eprom_w(dev, 0);
 
-	for(i=0;i<16;i++){
+	for (i = 0; i < 16; i++) {
 		//eeprom needs a clk cycle between writing opcode&adr
 		//and reading data. (eeprom outs a dummy 0)
 		eprom_ck_cycle(dev);
diff --git a/drivers/staging/rtl8192e/r8180_93cx6.h b/drivers/staging/rtl8192e/r8180_93cx6.h
index 62e14c7..4c3f675 100644
--- a/drivers/staging/rtl8192e/r8180_93cx6.h
+++ b/drivers/staging/rtl8192e/r8180_93cx6.h
@@ -1,17 +1,18 @@
-/*
-	This is part of rtl8187 OpenSource driver
-	Copyright (C) Andrea Merello 2004-2005  <andreamrl@tiscali.it>
-	Released under the terms of GPL (General Public Licence)
-
-	Parts of this driver are based on the GPL part of the official realtek driver
-	Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
-	Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
-
-	We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
-*/
-
-/*This files contains card eeprom (93c46 or 93c56) programming routines*/
-/*memory is addressed by WORDS*/
+/* r8180_93cx6.h - 93c46 or 93c56 eeprom card programming routines
+ *
+ * This is part of rtl8187 OpenSource driver
+ * Copyright (C) Andrea Merello 2004-2005  <andreamrl@tiscali.it>
+ * Released under the terms of GPL (General Public Licence)
+ * Parts of this driver are based on the GPL part of the official realtek driver
+ *
+ * Parts of this driver are based on the rtl8180 driver skeleton from
+ * Patric Schenke & Andres Salomon.
+ *
+ * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
+ *
+ * We want to thank the authors of the above mentioned projects and to
+ * the authors of the Ndiswrapper project.
+ */
 
 #include "r8192E.h"
 #include "r8192E_hw.h"
@@ -36,5 +37,5 @@
 #define EPROM_TXPW2 0x1b
 #define EPROM_TXPW1 0x3d
 
-
-u32 eprom_read(struct net_device *dev,u32 addr); //reads a 16 bits word
+/* Reads a 16 bits word. */
+u32 eprom_read(struct net_device *dev, u32 addr);
diff --git a/drivers/staging/rtl8192e/r8190_rtl8256.c b/drivers/staging/rtl8192e/r8190_rtl8256.c
index 3d67fbb..1bd054d 100644
--- a/drivers/staging/rtl8192e/r8190_rtl8256.c
+++ b/drivers/staging/rtl8192e/r8190_rtl8256.c
@@ -429,11 +429,12 @@
 	bool bResult = true;
 	//u8 eRFPath;
 	u8	i = 0, QueueID = 0;
-	ptx_ring	head=NULL,tail=NULL;
+	//ptx_ring	head=NULL,tail=NULL;
+	struct rtl8192_tx_ring  *ring = NULL;
 
 	if(priv->SetRFPowerStateInProgress == true)
 		return false;
-	RT_TRACE(COMP_POWER, "===========> SetRFPowerState8190()!\n");
+	//RT_TRACE(COMP_PS, "===========> SetRFPowerState8190()!\n");
 	priv->SetRFPowerStateInProgress = true;
 
 	switch(priv->rf_chip)
@@ -442,11 +443,11 @@
 		switch( eRFPowerState )
 		{
 			case eRfOn:
-				RT_TRACE(COMP_POWER, "SetRFPowerState8190() eRfOn !\n");
+				//RT_TRACE(COMP_PS, "SetRFPowerState8190() eRfOn !\n");
 						//RXTX enable control: On
 					//for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
-					//	PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x2);
-				#ifdef RTL8190P
+					//	PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x2);
+#ifdef RTL8190P
 				if(priv->rf_type == RF_2T4R)
 				{
 					//enable RF-Chip A/B
@@ -479,36 +480,92 @@
 					//analog to digital part2 on
 					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1800, 0x3); // 0x880[12:11]
 				}
-				#else
-				write_nic_byte(dev, ANAPAR, 0x37);//160MHz
-				write_nic_byte(dev, MacBlkCtrl, 0x17); // 0x403
-				mdelay(1);
-				//enable clock 80/88 MHz
+				else if(priv->rf_type == RF_1T1R)	//RF-C
+				{
+					//enable RF-Chip C/D
+					rtl8192_setBBreg(dev, rFPGA0_XC_RFInterfaceOE, BIT4, 0x1); // 0x868[4]
+					//analog to digital on
+					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x400, 0x1);// 0x88c[10]
+					//digital to analog on
+					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x80, 0x1); // 0x880[7]
+					//rx antenna on
+					rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x4, 0x1);// 0xc04[2]
+					//rx antenna on
+					rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x4, 0x1);// 0xd04[2]
+					//analog to digital part2 on
+					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x800, 0x1); // 0x880[11]
+				}
 
-				priv->bHwRfOffAction = 0;
-				//}
+#elif defined RTL8192E
+				// turn on RF
+				if((priv->ieee80211->eRFPowerState == eRfOff) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
+				{ // The current RF state is OFF and the RF OFF level is halting the NIC, re-initialize the NIC.
+					bool rtstatus = true;
+					u32 InitilizeCount = 3;
+					do
+					{
+						InitilizeCount--;
+						priv->RegRfOff = false;
+						rtstatus = NicIFEnableNIC(dev);
+					}while( (rtstatus != true) &&(InitilizeCount >0) );
 
-				// Baseband reset 2008.09.30 add
-				write_nic_byte(dev, BB_RESET, (read_nic_byte(dev, BB_RESET)|BIT0));
+					if(rtstatus != true)
+					{
+						RT_TRACE(COMP_ERR,"%s():Initialize Adapter fail,return\n",__FUNCTION__);
+						priv->SetRFPowerStateInProgress = false;
+						return false;
+					}
 
-				//2 AFE
-				// 2008.09.30 add
-				rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, 0x20000000, 0x1); // 0x884
-				//analog to digital part2 on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3);		// 0x880[6:5]
-				//digital to analog on
-				rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x98, 0x13); // 0x880[4:3]
-				//analog to digital on
-				rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf03, 0xf03);// 0x88c[9:8]
-				//rx antenna on
-				//PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
-				//rx antenna on 2008.09.30 mark
-				//PHY_SetBBReg(Adapter, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
+					RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+				} else {
+					write_nic_byte(dev, ANAPAR, 0x37);//160MHz
+					//write_nic_byte(dev, MacBlkCtrl, 0x17); // 0x403
+					mdelay(1);
+					//enable clock 80/88 MHz
+					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x1); // 0x880[2]
+					priv->bHwRfOffAction = 0;
+					//}
 
-				//2 RF
-				//enable RF-Chip A/B
+					//RF-A, RF-B
+					//enable RF-Chip A/B
 					rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1);		// 0x860[4]
-				rtl8192_setBBreg(dev, rFPGA0_XB_RFInterfaceOE, BIT4, 0x1);		// 0x864[4]
+					//analog to digital on
+					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
+					//digital to analog on
+					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x3); // 0x880[4:3]
+					//rx antenna on
+					rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
+					//rx antenna on
+					rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
+					//analog to digital part2 on
+					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3); 	// 0x880[6:5]
+
+					// Baseband reset 2008.09.30 add
+					//write_nic_byte(dev, BB_RESET, (read_nic_byte(dev, BB_RESET)|BIT0));
+
+				//2 	AFE
+					// 2008.09.30 add
+					//rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, 0x20000000, 0x1); // 0x884
+					//analog to digital part2 on
+					//rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3);		// 0x880[6:5]
+
+
+					//digital to analog on
+					//rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x98, 0x13); // 0x880[4:3]
+					//analog to digital on
+					//rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf03, 0xf03);// 0x88c[9:8]
+					//rx antenna on
+					//PHY_SetBBReg(dev, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
+					//rx antenna on 2008.09.30 mark
+					//PHY_SetBBReg(dev, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
+
+				//2 	RF
+					//enable RF-Chip A/B
+					//rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1);		// 0x860[4]
+					//rtl8192_setBBreg(dev, rFPGA0_XB_RFInterfaceOE, BIT4, 0x1);		// 0x864[4]
+
+				}
+
 				#endif
 						break;
 
@@ -517,119 +574,137 @@
 				// By Bruce, 2008-01-16.
 				//
 			case eRfSleep:
-			case eRfOff:
-				RT_TRACE(COMP_POWER, "SetRFPowerState8190() eRfOff/Sleep !\n");
-				if (pPSC->bLeisurePs)
+			{
+				// HW setting had been configured with deeper mode.
+				if(priv->ieee80211->eRFPowerState == eRfOff)
+					break;
+
+				// Update current RF state variable.
+				//priv->ieee80211->eRFPowerState = eRFPowerState;
+
+				//if (pPSC->bLeisurePs)
 				{
 					for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
 					{
-						switch(QueueID) {
-							case MGNT_QUEUE:
-								tail=priv->txmapringtail;
-								head=priv->txmapringhead;
-								break;
+							ring = &priv->tx_ring[QueueID];
 
-							case BK_QUEUE:
-								tail=priv->txbkpringtail;
-								head=priv->txbkpringhead;
-								break;
+							if(skb_queue_len(&ring->queue) == 0)
+							{
+								QueueID++;
+								continue;
+							}
+							else
+							{
+								RT_TRACE((COMP_POWER|COMP_RF), "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
+								udelay(10);
+								i++;
+							}
 
-							case BE_QUEUE:
-								tail=priv->txbepringtail;
-								head=priv->txbepringhead;
+							if(i >= MAX_DOZE_WAITING_TIMES_9x)
+							{
+								RT_TRACE(COMP_POWER, "\n\n\n TimeOut!! SetRFPowerState8190(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
 								break;
-
-							case VI_QUEUE:
-								tail=priv->txvipringtail;
-								head=priv->txvipringhead;
-								break;
-
-							case VO_QUEUE:
-								tail=priv->txvopringtail;
-								head=priv->txvopringhead;
-								break;
-
-							default:
-								tail=head=NULL;
-								break;
+							}
 						}
-						if(tail == head)
+				}
+
+				//if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
+#ifdef RTL8190P
+				{
+					PHY_SetRtl8190pRfOff(dev);
+				}
+				//else if(Adapter->HardwareType == HARDWARE_TYPE_RTL8192E)
+#elif defined RTL8192E
+				{
+					PHY_SetRtl8192eRfOff(dev);
+				}
+#endif
+			}
+								break;
+
+			case eRfOff:
+				//RT_TRACE(COMP_PS, "SetRFPowerState8190() eRfOff/Sleep !\n");
+
+				// Update current RF state variable.
+				//priv->ieee80211->eRFPowerState = eRFPowerState;
+
+				//
+				// Disconnect with Any AP or STA.
+				//
+				for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
+				{
+					ring = &priv->tx_ring[QueueID];
+
+					if(skb_queue_len(&ring->queue) == 0)
 						{
-							//DbgPrint("QueueID = %d", QueueID);
 							QueueID++;
 							continue;
 						}
 						else
 						{
-							RT_TRACE(COMP_POWER, "eRf Off/Sleep: %d times BusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
+							RT_TRACE(COMP_POWER,
+							"eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
 							udelay(10);
 							i++;
 						}
 
 						if(i >= MAX_DOZE_WAITING_TIMES_9x)
 						{
-							RT_TRACE(COMP_POWER, "\n\n\n TimeOut!! SetRFPowerState8190(): eRfOff: %d times BusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
+							RT_TRACE(COMP_POWER, "\n\n\n SetZebraRFPowerState8185B(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
 							break;
 						}
 					}
-				}
-				#ifdef RTL8190P
-				if(priv->rf_type == RF_2T4R)
+
+				//if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
+#if defined RTL8190P
 				{
-					//disable RF-Chip A/B
-					rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);		// 0x860[4]
+					PHY_SetRtl8190pRfOff(dev);
 				}
-				//disable RF-Chip C/D
-				rtl8192_setBBreg(dev, rFPGA0_XC_RFInterfaceOE, BIT4, 0x0); // 0x868[4]
-				//analog to digital off, for power save
-				rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
-				//digital to analog off, for power save
-				rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1e0, 0x0); // 0x880[8:5]
-				//rx antenna off
-				rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);// 0xc04[3:0]
-				//rx antenna off
-				rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);// 0xd04[3:0]
-				//analog to digital part2 off, for power save
-				rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1e00, 0x0); // 0x880[12:9]
-#else //8192E
-					//2 RF
-				//disable RF-Chip A/B
-				rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);		// 0x860[4]
-					rtl8192_setBBreg(dev, rFPGA0_XB_RFInterfaceOE, BIT4, 0x0);		// 0x864[4]
-					//2 AFE
-				//analog to digital off, for power save
-					//PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf03, 0x0); //  2008.09.30 Modify
-				//digital to analog off, for power save
-					//PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter1, 0x18, 0x0); // 0x880[4:3]
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x98, 0x0); // 0x880 2008.09.30 Modify
-					//rx antenna off  2008.09.30 mark
-					//PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf, 0x0);// 0xc04[3:0]
-					//rx antenna off  2008.09.30 mark
-					//PHY_SetBBReg(Adapter, rOFDM1_TRxPathEnable, 0xf, 0x0);// 0xd04[3:0]
-				//analog to digital part2 off, for power save
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);		// 0x880[6:5]
-					// 2008.09.30 add
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, 0x20000000, 0x0); // 0x884
+				//else if(Adapter->HardwareType == HARDWARE_TYPE_RTL8192E)
+#elif defined RTL8192E
+				{
+					//if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC) && priv->ieee80211->RfOffReason > RF_CHANGE_BY_PS)
+					if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
+					{ // Disable all components.
+						//
+						// Note:
+						//	NicIFSetLinkStatus is a big problem when we indicate the status to OS,
+						//	the OS(XP) will reset. But now, we cnnot find why the NIC is hard to receive
+						//	packets after RF ON. Just keep this function here and still work to find out the root couse.
+						//	By Bruce, 2009-05-01.
+						//
+						//NicIFSetLinkStatus( Adapter, RT_MEDIA_DISCONNECT );
+						//if HW radio of , need to indicate scan complete first for not be reset.
+						//if(MgntScanInProgress(pMgntInfo))
+						//	MgntResetScanProcess( Adapter );
 
-
-					//disable clock 80/88 MHz 2008.09.30 mark
-					//PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter1, 0x4, 0x0); // 0x880[2]
-					//2 BB
-					// Baseband reset 2008.09.30 add
-					write_nic_byte(dev, BB_RESET, (read_nic_byte(dev, BB_RESET)|BIT0)); // 0x101
-					//MAC: off
-					write_nic_byte(dev, MacBlkCtrl, 0x0); // 0x403
-					//slow down cpu/lbus clock from 160MHz to Lower
-					write_nic_byte(dev, ANAPAR, 0x07); // 0x 17 40MHz
-				priv->bHwRfOffAction = 0;
-				//}
+						// <1> Disable Interrupt
+						//rtl8192_irq_disable(dev);
+						// <2> Stop all timer
+						//MgntCancelAllTimer(Adapter);
+						// <3> Disable Adapter
+						//NicIFHaltAdapter(Adapter, false);
+						NicIFDisableNIC(dev);
+						RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+					}
+					else if (!(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC))
+					{ // Normal case.
+				  		// IPS should go to this.
+						PHY_SetRtl8192eRfOff(dev);
+					}
+				}
+#else
+				else
+				{
+					RT_TRACE(COMP_DBG,DBG_TRACE,("It is not 8190Pci and 8192PciE \n"));
+				}
 				#endif
+
 					break;
 
 			default:
 					bResult = false;
-					RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknown state to set: 0x%X!!!\n", eRFPowerState);
+					RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknow state to set: 0x%X!!!\n", eRFPowerState);
 					break;
 		}
 
@@ -644,64 +719,11 @@
 	{
 		// Update current RF state variable.
 		priv->ieee80211->eRFPowerState = eRFPowerState;
-
-		switch(priv->rf_chip )
-		{
-			case RF_8256:
-			switch(priv->ieee80211->eRFPowerState)
-			{
-				case eRfOff:
-				//
-				//If Rf off reason is from IPS, Led should blink with no link, by Maddest 071015
-				//
-					if(priv->ieee80211->RfOffReason==RF_CHANGE_BY_IPS )
-					{
-						#ifdef TO_DO
-						Adapter->HalFunc.LedControlHandler(Adapter,LED_CTL_NO_LINK);
-						#endif
-					}
-					else
-					{
-					// Turn off LED if RF is not ON.
-						#ifdef TO_DO
-						Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_POWER_OFF);
-						#endif
-					}
-					break;
-
-				case eRfOn:
-				// Turn on RF we are still linked, which might happen when
-				// we quickly turn off and on HW RF. 2006.05.12, by rcnjko.
-					if( priv->ieee80211->state == IEEE80211_LINKED)
-					{
-						#ifdef TO_DO
-						Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_LINK);
-						#endif
-					}
-					else
-					{
-					// Turn off LED if RF is not ON.
-						#ifdef TO_DO
-						Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_NO_LINK);
-						#endif
-					}
-					break;
-
-				default:
-			// do nothing.
-					break;
-			}// Switch RF state
-
-			break;
-
-			default:
-				RT_TRACE(COMP_ERR, "SetRFPowerState8190(): Unknown RF type\n");
-				break;
-		}// Switch RFChipID
 	}
 
+	//printk("%s()priv->ieee80211->eRFPowerState:%s\n" ,__func__,priv->ieee80211->eRFPowerState == eRfOn ? "On" : "Off");
 	priv->SetRFPowerStateInProgress = false;
-	RT_TRACE(COMP_POWER, "<=========== SetRFPowerState8190() bResult = %d!\n", bResult);
+	//RT_TRACE(COMP_PS, "<=========== SetRFPowerState8190() bResult = %d!\n", bResult);
 	return bResult;
 }
 
diff --git a/drivers/staging/rtl8192e/r8190_rtl8256.h b/drivers/staging/rtl8192e/r8190_rtl8256.h
index 7d9095a..ce49c60 100644
--- a/drivers/staging/rtl8192e/r8190_rtl8256.h
+++ b/drivers/staging/rtl8192e/r8190_rtl8256.h
@@ -1,28 +1,33 @@
-/*
-  This is part of the rtl8180-sa2400 driver
-  released under the GPL (See file COPYING for details).
-  Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
+/* r8190_rtl8256.h - rtl8256 radio frontend
+ *
+ * This is part of the rtl8180-sa2400 driver
+ * released under the GPL (See file COPYING for details).
+ * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Many thanks to Realtek Corp. for their great support!
+ */
 
-  This files contains programming code for the rtl8256
-  radio frontend.
-
-  *Many* thanks to Realtek Corp. for their great support!
-
-*/
-
-#ifndef RTL8225H
-#define RTL8225H
+#ifndef RTL8225_H
+#define RTL8225_H
 
 #ifdef RTL8190P
-#define RTL819X_TOTAL_RF_PATH	4
+#define RTL819X_TOTAL_RF_PATH 4
 #else
-#define RTL819X_TOTAL_RF_PATH 2 //for 8192E
+#define RTL819X_TOTAL_RF_PATH 2 /* for 8192E */
 #endif
-extern void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth);
-extern RT_STATUS PHY_RF8256_Config(struct net_device* dev);
-extern RT_STATUS phy_RF8256_Config_ParaFile(struct net_device* dev);
-extern void PHY_SetRF8256CCKTxPower(struct net_device*	dev, u8	powerlevel);
-extern void PHY_SetRF8256OFDMTxPower(struct net_device* dev, u8 powerlevel);
-extern bool MgntActSet_RF_State(struct net_device* dev, RT_RF_POWER_STATE StateToSet, RT_RF_CHANGE_SOURCE ChangeSource);
 
-#endif
+extern void PHY_SetRF8256Bandwidth(struct net_device *dev,
+				   HT_CHANNEL_WIDTH Bandwidth);
+
+extern RT_STATUS PHY_RF8256_Config(struct net_device *dev);
+
+extern RT_STATUS phy_RF8256_Config_ParaFile(struct net_device *dev);
+
+extern void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel);
+extern void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel);
+
+extern bool MgntActSet_RF_State(struct net_device *dev,
+				RT_RF_POWER_STATE StateToSet,
+				RT_RF_CHANGE_SOURCE ChangeSource);
+
+#endif /* RTL8225_H */
diff --git a/drivers/staging/rtl8192e/r8192E.h b/drivers/staging/rtl8192e/r8192E.h
index 61b6f25..f4be9cc 100644
--- a/drivers/staging/rtl8192e/r8192E.h
+++ b/drivers/staging/rtl8192e/r8192E.h
@@ -39,7 +39,7 @@
 #include <linux/random.h>
 #include <linux/version.h>
 #include <asm/io.h>
-#include "ieee80211.h"
+#include "ieee80211/ieee80211.h"
 
 
 
@@ -1003,6 +1003,11 @@
 	int irq;
 	short irq_enabled;
 	struct ieee80211_device *ieee80211;
+#ifdef ENABLE_LPS
+	bool ps_force;
+	bool force_lps;
+	bool bdisable_nic;
+#endif
 	bool being_init_adapter;
 	u8 Rf_Mode;
 	short card_8192; /* O: rtl8192, 1:rtl8185 V B/C, 2:rtl8185 V D */
@@ -1477,7 +1482,7 @@
 void write_nic_dword(struct net_device *dev, int x,u32 y);
 void force_pci_posting(struct net_device *dev);
 
-void rtl8192_rtx_disable(struct net_device *);
+void rtl8192_halt_adapter(struct net_device *dev, bool reset);
 void rtl8192_rx_enable(struct net_device *);
 void rtl8192_tx_enable(struct net_device *);
 
@@ -1512,5 +1517,19 @@
 #ifdef ENABLE_IPS
 void IPSEnter(struct net_device *dev);
 void IPSLeave(struct net_device *dev);
+void InactivePsWorkItemCallback(struct net_device *dev);
+void IPSLeave_wq(void *data);
+void ieee80211_ips_leave_wq(struct net_device *dev);
+void ieee80211_ips_leave(struct net_device *dev);
 #endif
+#ifdef ENABLE_LPS
+void LeisurePSEnter(struct net_device *dev);
+void LeisurePSLeave(struct net_device *dev);
+#endif
+
+bool NicIFEnableNIC(struct net_device* dev);
+bool NicIFDisableNIC(struct net_device* dev);
+
+void rtl8192_irq_disable(struct net_device *dev);
+void PHY_SetRtl8192eRfOff(struct net_device* dev);
 #endif
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c
index 0ca5d8b..886105d 100644
--- a/drivers/staging/rtl8192e/r8192E_core.c
+++ b/drivers/staging/rtl8192e/r8192E_core.c
@@ -66,7 +66,7 @@
 #endif
 
 #ifdef ENABLE_DOT11D
-#include "dot11d.h"
+#include "ieee80211/dot11d.h"
 #endif
 
 //set here to open your trace code. //WB
@@ -75,7 +75,7 @@
 			//	COMP_EPROM   	|
 		//		COMP_PHY	|
 		//		COMP_RF		|
-				COMP_FIRMWARE	|
+//				COMP_FIRMWARE	|
 			//	COMP_TRACE	|
 		//		COMP_DOWN	|
 		//		COMP_SWBW	|
@@ -343,6 +343,141 @@
 
 #endif /* RTL_IO_MAP */
 
+u8 rtl8192e_ap_sec_type(struct ieee80211_device *ieee)
+{
+	//struct r8192_priv* priv = ieee80211_priv(dev);
+	//struct ieee80211_device *ieee = priv->ieee80211;
+
+	static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
+	static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
+	int wpa_ie_len= ieee->wpa_ie_len;
+	struct ieee80211_crypt_data* crypt;
+	int encrypt;
+
+	crypt = ieee->crypt[ieee->tx_keyidx];
+
+	encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY) ||\
+		  (ieee->host_encrypt && crypt && crypt->ops && \
+		   (0 == strcmp(crypt->ops->name,"WEP")));
+
+	/* simply judge  */
+	if(encrypt && (wpa_ie_len == 0)) {
+		// wep encryption, no N mode setting */
+		return SEC_ALG_WEP;
+	} else if((wpa_ie_len != 0)) {
+		// parse pairwise key type */
+		if (((ieee->wpa_ie[0] == 0xdd) && (!memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) ||
+				((ieee->wpa_ie[0] == 0x30) && (!memcmp(&ieee->wpa_ie[10],ccmp_rsn_ie, 4))))
+			return SEC_ALG_CCMP;
+		else
+			return SEC_ALG_TKIP;
+	} else {
+		return SEC_ALG_NONE;
+	}
+}
+
+void
+rtl8192e_SetHwReg(struct net_device *dev,u8 variable,u8* val)
+{
+	struct r8192_priv* priv = ieee80211_priv(dev);
+
+	switch(variable)
+	{
+
+		case HW_VAR_BSSID:
+			write_nic_dword(dev, BSSIDR, ((u32*)(val))[0]);
+			write_nic_word(dev, BSSIDR+2, ((u16*)(val+2))[0]);
+		break;
+
+		case HW_VAR_MEDIA_STATUS:
+		{
+			RT_OP_MODE	OpMode = *((RT_OP_MODE *)(val));
+			//LED_CTL_MODE	LedAction = LED_CTL_NO_LINK;
+			u8		btMsr = read_nic_byte(dev, MSR);
+
+			btMsr &= 0xfc;
+
+			switch(OpMode)
+			{
+			case RT_OP_MODE_INFRASTRUCTURE:
+				btMsr |= MSR_INFRA;
+				//LedAction = LED_CTL_LINK;
+				break;
+
+			case RT_OP_MODE_IBSS:
+				btMsr |= MSR_ADHOC;
+				// led link set seperate
+				break;
+
+			case RT_OP_MODE_AP:
+				btMsr |= MSR_AP;
+				//LedAction = LED_CTL_LINK;
+				break;
+
+			default:
+				btMsr |= MSR_NOLINK;
+				break;
+			}
+
+			write_nic_byte(dev, MSR, btMsr);
+
+			//priv->ieee80211->LedControlHandler(dev, LedAction);
+		}
+		break;
+
+		case HW_VAR_CECHK_BSSID:
+		{
+			u32	RegRCR, Type;
+
+			Type = ((u8*)(val))[0];
+			//priv->ieee80211->GetHwRegHandler(dev, HW_VAR_RCR, (u8*)(&RegRCR));
+			RegRCR = read_nic_dword(dev,RCR);
+			priv->ReceiveConfig = RegRCR;
+
+			if (Type == true)
+				RegRCR |= (RCR_CBSSID);
+			else if (Type == false)
+				RegRCR &= (~RCR_CBSSID);
+
+			//priv->ieee80211->SetHwRegHandler( dev, HW_VAR_RCR, (u8*)(&RegRCR) );
+			write_nic_dword(dev, RCR,RegRCR);
+			priv->ReceiveConfig = RegRCR;
+
+		}
+		break;
+
+		case HW_VAR_SLOT_TIME:
+		{
+			//PSTA_QOS	pStaQos = Adapter->MgntInfo.pStaQos;
+			//AC_CODING	eACI;
+
+			priv->slot_time = val[0];
+			write_nic_byte(dev, SLOT_TIME, val[0]);
+
+		}
+		break;
+
+		case HW_VAR_ACK_PREAMBLE:
+		{
+			u32 regTmp = 0;
+			priv->short_preamble = (bool)(*(u8*)val );
+			regTmp = priv->basic_rate;
+			if (priv->short_preamble)
+				regTmp |= BRSR_AckShortPmb;
+			write_nic_dword(dev, RRSR, regTmp);
+		}
+		break;
+
+		case HW_VAR_CPU_RST:
+			write_nic_dword(dev, CPU_GEN, ((u32*)(val))[0]);
+		break;
+
+		default:
+		break;
+	}
+
+}
+
 
 ///////////////////////////////////////////////////////////
 
@@ -365,11 +500,6 @@
 //void rtl8192_rq_tx_ack(struct work_struct *work);
 
 void watch_dog_timer_callback(unsigned long data);
-#ifdef ENABLE_IPS
-void IPSEnter(struct net_device *dev);
-void IPSLeave(struct net_device *dev);
-void InactivePsWorkItemCallback(struct net_device *dev);
-#endif
 /****************************************************************************
    -----------------------------PROCFS STUFF-------------------------
 *****************************************************************************/
@@ -707,7 +837,7 @@
 }
 
 
-static void rtl8192_irq_disable(struct net_device *dev)
+void rtl8192_irq_disable(struct net_device *dev)
 {
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 
@@ -717,6 +847,7 @@
 }
 
 
+#if 0
 static void rtl8192_set_mode(struct net_device *dev,int mode)
 {
 	u8 ecmd;
@@ -727,7 +858,7 @@
 	ecmd=ecmd &~ (1<<EPROM_CK_SHIFT);
 	write_nic_byte(dev, EPROM_CMD, ecmd);
 }
-
+#endif
 
 void rtl8192_update_msr(struct net_device *dev)
 {
@@ -861,7 +992,7 @@
     ring->desc = NULL;
 }
 
-
+#if 0
 static void rtl8192_beacon_disable(struct net_device *dev)
 {
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
@@ -873,38 +1004,116 @@
 	reg &= ~(IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER);
 	write_nic_dword(priv->ieee80211->dev, INTA_MASK, reg);
 }
+#endif
 
-void rtl8192_rtx_disable(struct net_device *dev)
+void PHY_SetRtl8192eRfOff(struct net_device* dev	)
 {
-	u8 cmd;
+	//struct r8192_priv *priv = ieee80211_priv(dev);
+
+	//disable RF-Chip A/B
+	rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
+	//analog to digital off, for power save
+	rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
+	//digital to analog off, for power save
+	rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
+	//rx antenna off
+	rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);
+	//rx antenna off
+	rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);
+	//analog to digital part2 off, for power save
+	rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
+	rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
+	// Analog parameter!!Change bias and Lbus control.
+	write_nic_byte(dev, ANAPAR_FOR_8192PciE, 0x07);
+
+}
+
+void rtl8192_halt_adapter(struct net_device *dev, bool reset)
+{
+	//u8 	cmd;
 	struct r8192_priv *priv = ieee80211_priv(dev);
-        int i;
+	int i;
+	u8	OpMode;
+	u8	u1bTmp;
+	u32	ulRegRead;
 
+	OpMode = RT_OP_MODE_NO_LINK;
+	priv->ieee80211->SetHwRegHandler(dev, HW_VAR_MEDIA_STATUS, &OpMode);
+
+#if 1
+	if(!priv->ieee80211->bSupportRemoteWakeUp)
+	{
+		u1bTmp = 0x0;	// disable tx/rx. In 8185 we write 0x10 (Reset bit), but here we make reference to WMAC and wirte 0x0. 2006.11.21 Emily
+		//priv->ieee80211->SetHwRegHandler(dev, HW_VAR_COMMAND, &u1bTmp );	// Using HW_VAR_COMMAND instead of writing CMDR directly. Rewrited by Annie, 2006-04-07.
+		write_nic_byte(dev, CMDR, u1bTmp);
+	}
+#else
 	cmd=read_nic_byte(dev,CMDR);
-//	if(!priv->ieee80211->bSupportRemoteWakeUp) {
-		write_nic_byte(dev, CMDR, cmd &~ \
-				(CR_TE|CR_RE));
-//	}
-	force_pci_posting(dev);
-	mdelay(30);
+	write_nic_byte(dev, CMDR, cmd &~ (CR_TE|CR_RE));
+#endif
 
-        for(i = 0; i < MAX_QUEUE_SIZE; i++) {
-                skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
-        }
-        for(i = 0; i < MAX_QUEUE_SIZE; i++) {
-                skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
-        }
+	mdelay(20);
 
+	if(!reset)
+	{
+		//PlatformStallExecution(150000);
+		mdelay(150);
+
+#ifdef RTL8192E
+			priv->bHwRfOffAction = 2;
+#endif
+
+		//
+		// Call MgntActSet_RF_State instead to prevent RF config race condition.
+		// By Bruce, 2008-01-17.
+		//
+		if(!priv->ieee80211->bSupportRemoteWakeUp)
+		{
+			//MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_INIT);
+			//MgntActSet_RF_State(Adapter, eRfOff, Adapter->MgntInfo.RfOffReason);
+			//if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
+
+			PHY_SetRtl8192eRfOff(dev);
+
+			// 2006.11.30. System reset bit
+			//priv->ieee80211->GetHwRegHandler(dev, HW_VAR_CPU_RST, (u32*)(&ulRegRead) );
+			ulRegRead = read_nic_dword(dev,CPU_GEN);
+			ulRegRead|=CPU_GEN_SYSTEM_RESET;
+			//priv->ieee80211->SetHwRegHandler(dev, HW_VAR_CPU_RST, &ulRegRead);
+			write_nic_dword(dev,CPU_GEN, ulRegRead);
+		}
+	 	else
+		{
+			//2008.06.03 for WOL
+			write_nic_dword(dev, WFCRC0, 0xffffffff);
+			write_nic_dword(dev, WFCRC1, 0xffffffff);
+			write_nic_dword(dev, WFCRC2, 0xffffffff);
+
+			//Write PMR register
+			write_nic_byte(dev, PMR, 0x5);
+			//Disable tx, enanble rx
+			write_nic_byte(dev, MacBlkCtrl, 0xa);
+		}
+	}
+
+	for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+		skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
+	}
+	for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+		skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
+	}
 
 	skb_queue_purge(&priv->skb_queue);
 	return;
 }
 
+#if 0
 static void rtl8192_reset(struct net_device *dev)
 {
     rtl8192_irq_disable(dev);
     printk("This is RTL819xP Reset procedure\n");
 }
+#endif
 
 static u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540};
 inline u16 rtl8192_rate2rate(short rate)
@@ -954,6 +1163,12 @@
 	/* shall not be referred by command packet */
 	assert(queue_index != TXCMD_QUEUE);
 
+	if((priv->bHwRadioOff == true)||(!priv->up))
+	{
+		kfree_skb(skb);
+		return;
+	}
+
 	//spin_lock_irqsave(&priv->tx_lock,flags);
 
         memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
@@ -996,6 +1211,13 @@
         cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
         u8 queue_index = tcb_desc->queue_index;
 
+        if(queue_index != TXCMD_QUEUE){
+		if((priv->bHwRadioOff == true)||(!priv->up))
+		{
+               	 	kfree_skb(skb);
+                	return 0;
+            	}
+        }
 
 	//spin_lock_irqsave(&priv->tx_lock,flags);
 
@@ -1379,6 +1601,15 @@
     u8*   pda_addr = NULL;
     int   idx;
 
+    if(priv->bdisable_nic){
+       	RT_TRACE(COMP_ERR,"%s: ERR!! Nic is disabled! Can't tx packet len=%d qidx=%d!!!\n", __FUNCTION__, skb->len, tcb_desc->queue_index);
+		return skb->len;
+    }
+
+#ifdef ENABLE_LPS
+	priv->ieee80211->bAwakePktSent = true;
+#endif
+
     mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
     /* collect the tx packets statitcs */
     pda_addr = ((u8*)skb->data) + sizeof(TX_FWINFO_8190PCI);
@@ -1481,6 +1712,7 @@
     if((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) {
 	    RT_TRACE(COMP_ERR,"No more TX desc@%d, ring->idx = %d,idx = %d,%x", \
 			    tcb_desc->queue_index,ring->idx, idx,skb->len);
+	    spin_unlock_irqrestore(&priv->irq_th_lock,flags);
 	    return skb->len;
     }
 
@@ -1575,7 +1807,7 @@
             return 0;
         priv->rx_buf[i] = skb;
         mapping = (dma_addr_t *)skb->cb;
-        *mapping = pci_map_single(priv->pdev, skb->tail,//skb_tail_pointer(skb),
+        *mapping = pci_map_single(priv->pdev, skb_tail_pointer(skb),
                 priv->rxbuffersize, PCI_DMA_FROMDEVICE);
 
         entry->BufferAddress = cpu_to_le32(*mapping);
@@ -1779,7 +2011,7 @@
 				(((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
 				(((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
 				((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
-		printk("===>u4bAcParam:%x, ", u4bAcParam);
+		//printk("===>u4bAcParam:%x, ", u4bAcParam);
 		write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
 		//write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
 	}
@@ -1964,11 +2196,24 @@
 	write_nic_byte(dev, UFWP, 1);
 }
 
+#if 0
 static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
 static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
+#endif
+
 static bool GetNmodeSupportBySecCfg8190Pci(struct net_device*dev)
 {
 #if 1
+
+	struct r8192_priv *priv = ieee80211_priv(dev);
+	struct ieee80211_device *ieee = priv->ieee80211;
+	if (ieee->rtllib_ap_sec_type &&
+	   (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))) {
+		return false;
+	} else {
+		return true;
+	}
+#else
 	struct r8192_priv* priv = ieee80211_priv(dev);
 	struct ieee80211_device* ieee = priv->ieee80211;
         int wpa_ie_len= ieee->wpa_ie_len;
@@ -1995,18 +2240,6 @@
 		return true;
 	}
 
-#if 0
-        //In here we discuss with SD4 David. He think we still can send TKIP in broadcast group key in MCS rate.
-        //We can't force in G mode if Pairwie key is AES and group key is TKIP
-        if((pSecInfo->GroupEncAlgorithm == WEP104_Encryption) || (pSecInfo->GroupEncAlgorithm == WEP40_Encryption)  ||
-           (pSecInfo->PairwiseEncAlgorithm == WEP104_Encryption) ||
-           (pSecInfo->PairwiseEncAlgorithm == WEP40_Encryption) || (pSecInfo->PairwiseEncAlgorithm == TKIP_Encryption))
-        {
-                return  false;
-        }
-        else
-                return true;
-#endif
 	return true;
 #endif
 }
@@ -2080,7 +2313,7 @@
 			wireless_mode = WIRELESS_MODE_B;
 		}
 	}
-#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we shoud wait for FPGA
+#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we should wait for FPGA
 	ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
 #endif
 	priv->ieee80211->mode = wireless_mode;
@@ -2127,7 +2360,19 @@
 }
 static void rtl8192_hw_sleep_down(struct net_device *dev)
 {
-	RT_TRACE(COMP_POWER, "%s()============>come to sleep down\n", __FUNCTION__);
+	struct r8192_priv *priv = ieee80211_priv(dev);
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&priv->rf_ps_lock,flags);
+	if (priv->RFChangeInProgress) {
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+		RT_TRACE(COMP_RF, "rtl8192_hw_sleep_down(): RF Change in progress! \n");
+		printk("rtl8192_hw_sleep_down(): RF Change in progress!\n");
+		return;
+	}
+	spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+	//RT_TRACE(COMP_PS, "%s()============>come to sleep down\n", __FUNCTION__);
+
 	MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS);
 }
 static void rtl8192_hw_sleep_wq (struct work_struct *work)
@@ -2138,21 +2383,29 @@
         struct delayed_work *dwork = container_of(work,struct delayed_work,work);
         struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_sleep_wq);
         struct net_device *dev = ieee->dev;
-	//printk("=========>%s()\n", __FUNCTION__);
+
         rtl8192_hw_sleep_down(dev);
 }
-//	printk("dev is %d\n",dev);
-//	printk("&*&(^*(&(&=========>%s()\n", __FUNCTION__);
+
 static void rtl8192_hw_wakeup(struct net_device* dev)
 {
-//	u32 flags = 0;
+	struct r8192_priv *priv = ieee80211_priv(dev);
+	unsigned long flags = 0;
 
-//	spin_lock_irqsave(&priv->ps_lock,flags);
-	RT_TRACE(COMP_POWER, "%s()============>come to wake up\n", __FUNCTION__);
+	spin_lock_irqsave(&priv->rf_ps_lock,flags);
+	if (priv->RFChangeInProgress) {
+		spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+		RT_TRACE(COMP_RF, "rtl8192_hw_wakeup(): RF Change in progress! \n");
+		printk("rtl8192_hw_wakeup(): RF Change in progress! schedule wake up task again\n");
+		queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->hw_wakeup_wq,MSECS(10));//PowerSave is not supported if kernel version is below 2.6.20
+		return;
+	}
+	spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+
+	//RT_TRACE(COMP_PS, "%s()============>come to wake up\n", __FUNCTION__);
 	MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS);
-	//FIXME: will we send package stored while nic is sleep?
-//	spin_unlock_irqrestore(&priv->ps_lock,flags);
 }
+
 void rtl8192_hw_wakeup_wq (struct work_struct *work)
 {
 //	struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq);
@@ -2169,7 +2422,6 @@
 #define MAX_SLEEP_TIME 10000
 static void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl)
 {
-
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
 	u32 rb = jiffies;
@@ -2177,58 +2429,55 @@
 
 	spin_lock_irqsave(&priv->ps_lock,flags);
 
-	/* Writing HW register with 0 equals to disable
-	 * the timer, that is not really what we want
-	 */
-	tl -= MSECS(4+16+7);
+	// Writing HW register with 0 equals to disable
+	// the timer, that is not really what we want
+	//
+	tl -= MSECS(8+16+7);
 
-	//if(tl == 0) tl = 1;
-
-	/* FIXME HACK FIXME HACK */
-//	force_pci_posting(dev);
-	//mdelay(1);
-
-//	rb = read_nic_dword(dev, TSFTR);
-
-	/* If the interval in witch we are requested to sleep is too
-	 * short then give up and remain awake
-	 */
+	// If the interval in witch we are requested to sleep is too
+	// short then give up and remain awake
+	// when we sleep after send null frame, the timer will be too short to sleep.
+	//
 	if(((tl>=rb)&& (tl-rb) <= MSECS(MIN_SLEEP_TIME))
-		||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
+			||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
 		spin_unlock_irqrestore(&priv->ps_lock,flags);
-		printk("too short to sleep\n");
+		printk("too short to sleep::%x, %x, %lx\n",tl, rb,  MSECS(MIN_SLEEP_TIME));
 		return;
 	}
 
-//	write_nic_dword(dev, TimerInt, tl);
-//	rb = read_nic_dword(dev, TSFTR);
-	{
-		u32 tmp = (tl>rb)?(tl-rb):(rb-tl);
-	//	if (tl<rb)
-		queue_delayed_work(priv->ieee80211->wq, &priv->ieee80211->hw_wakeup_wq, tmp); //as tl may be less than rb
-	}
-	/* if we suspect the TimerInt is gone beyond tl
-	 * while setting it, then give up
-	 */
-#if 1
 	if(((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME)))||
-		((tl < rb) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))) {
+			((tl < rb) && (tl>MSECS(69)) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))||
+			((tl<rb)&&(tl<MSECS(69))&&((tl+0xffffffff-rb)>MSECS(MAX_SLEEP_TIME)))) {
 		printk("========>too long to sleep:%x, %x, %lx\n", tl, rb,  MSECS(MAX_SLEEP_TIME));
 		spin_unlock_irqrestore(&priv->ps_lock,flags);
 		return;
 	}
-#endif
-//	if(priv->rf_sleep)
-//		priv->rf_sleep(dev);
-
-	//printk("<=========%s()\n", __FUNCTION__);
-	queue_delayed_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_sleep_wq,0);
+	{
+		u32 tmp = (tl>rb)?(tl-rb):(rb-tl);
+		queue_delayed_work(priv->ieee80211->wq,
+				&priv->ieee80211->hw_wakeup_wq,tmp);
+		//PowerSave not supported when kernel version less 2.6.20
+	}
+	queue_delayed_work(priv->ieee80211->wq,
+			(void *)&priv->ieee80211->hw_sleep_wq,0);
 	spin_unlock_irqrestore(&priv->ps_lock,flags);
+
 }
 static void rtl8192_init_priv_variable(struct net_device* dev)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8 i;
+	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+	// Default Halt the NIC if RF is OFF.
+	pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC;
+	pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_CLK_REQ;
+	pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM;
+	pPSC->RegRfPsLevel |= RT_RF_LPS_LEVEL_ASPM;
+	pPSC->bLeisurePs = true;
+	pPSC->RegMaxLPSAwakeIntvl = 5;
+	priv->bHwRadioOff = false;
+
 	priv->being_init_adapter = false;
 	priv->txbuffsize = 1600;//1024;
 	priv->txfwbuffersize = 4096;
@@ -2328,6 +2577,17 @@
 	//added by amy
 	priv->ieee80211->InitialGainHandler = InitialGain819xPci;
 
+#ifdef ENABLE_IPS
+	priv->ieee80211->ieee80211_ips_leave_wq = ieee80211_ips_leave_wq;
+	priv->ieee80211->ieee80211_ips_leave = ieee80211_ips_leave;
+#endif
+#ifdef ENABLE_LPS
+        priv->ieee80211->LeisurePSLeave            = LeisurePSLeave;
+#endif//ENABL
+
+	priv->ieee80211->SetHwRegHandler = rtl8192e_SetHwReg;
+	priv->ieee80211->rtllib_ap_sec_type = rtl8192e_ap_sec_type;
+
 	priv->card_type = USB;
 	{
 		priv->ShortRetryLimit = 0x30;
@@ -2400,6 +2660,10 @@
 	priv->priv_wq = create_workqueue(DRV_NAME);
 #endif
 
+#ifdef ENABLE_IPS
+	INIT_WORK(&priv->ieee80211->ips_leave_wq, (void*)IPSLeave_wq);
+#endif
+
 //	INIT_WORK(&priv->reset_wq, (void(*)(void*)) rtl8192_restart);
 	INIT_WORK(&priv->reset_wq,  rtl8192_restart);
 //	INIT_DELAYED_WORK(&priv->watch_dog_wq, hal_dm_watchdog);
@@ -2550,10 +2814,7 @@
 		memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
 	}
 
-	RT_TRACE(COMP_INIT, "Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
-			dev->dev_addr[0], dev->dev_addr[1],
-			dev->dev_addr[2], dev->dev_addr[3],
-			dev->dev_addr[4], dev->dev_addr[5]);
+	RT_TRACE(COMP_INIT, "Permanent Address = %pM\n", dev->dev_addr);
 
 		//2 TX Power Check EEPROM Fail or not
 	if(priv->card_8192_version > VERSION_8190_BD) {
@@ -2926,13 +3187,14 @@
 		#endif
 			break;
 	}
-/*
-	//2008.06.03, for WOL
+
+
 	if( priv->eeprom_vid == 0x1186 &&  priv->eeprom_did == 0x3304)
-		priv->ieee80211->bSupportRemoteWakeUp = TRUE;
+		priv->ieee80211->bSupportRemoteWakeUp = true;
 	else
-		priv->ieee80211->bSupportRemoteWakeUp = FALSE;
-*/
+		priv->ieee80211->bSupportRemoteWakeUp = false;
+
+
 	RT_TRACE(COMP_INIT, "RegChannelPlan(%d)\n", priv->RegChannelPlan);
 	RT_TRACE(COMP_INIT, "ChannelPlan = %d \n", priv->ChannelPlan);
 	RT_TRACE(COMP_INIT, "LedStrategy = %d \n", priv->LedStrategy);
@@ -4006,12 +4268,19 @@
 	struct ieee80211_device *ieee = priv->ieee80211;
 
 
+	return;
+
 	// 2007.07.20. If we need to check CCK stop, please uncomment this line.
 	//bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
 
 	if(priv->ResetProgress==RESET_TYPE_NORESET)
 	{
 RESET_START:
+#ifdef ENABLE_LPS
+                //LZM for PS-Poll AID issue. 090429
+                if(priv->ieee80211->state == IEEE80211_LINKED)
+                    LeisurePSLeave(dev);
+#endif
 
 		RT_TRACE(COMP_RESET,"=========>Reset progress!! \n");
 
@@ -4051,9 +4320,9 @@
 		}
 		else{
 			printk("ieee->state is NOT LINKED\n");
-			ieee80211_softmac_stop_protocol(priv->ieee80211);
+			ieee80211_softmac_stop_protocol(priv->ieee80211,true);
 		}
-		rtl8192_rtx_disable(dev);
+		rtl8192_halt_adapter(dev, true);
 		up(&priv->wx_sem);
 		RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);
 		RT_TRACE(COMP_RESET,"%s():===========>start to up the driver\n",__FUNCTION__);
@@ -4150,6 +4419,128 @@
 	RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() <--------- \n");
 }
 
+#ifdef ENABLE_LPS
+//
+// Change current and default preamble mode.
+// 2005.01.06, by rcnjko.
+//
+bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev,	u8 rtPsMode)
+{
+	struct r8192_priv *priv = ieee80211_priv(dev);
+	//PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+	//u8 RpwmVal, FwPwrMode;
+
+	// Currently, we do not change power save mode on IBSS mode.
+	if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
+	{
+		return false;
+	}
+
+	//
+	// <RJ_NOTE> If we make HW to fill up the PwrMgt bit for us,
+	// some AP will not response to our mgnt frames with PwrMgt bit set,
+	// e.g. cannot associate the AP.
+	// So I commented out it. 2005.02.16, by rcnjko.
+	//
+//	// Change device's power save mode.
+//	Adapter->HalFunc.SetPSModeHandler( Adapter, rtPsMode );
+
+	// Update power save mode configured.
+	//RT_TRACE(COMP_LPS,"%s(): set ieee->ps = %x\n",__FUNCTION__,rtPsMode);
+	if(!priv->ps_force) {
+		priv->ieee80211->ps = rtPsMode;
+	}
+
+	// Awake immediately
+	if(priv->ieee80211->sta_sleep != 0 && rtPsMode == IEEE80211_PS_DISABLED)
+	{
+                unsigned long flags;
+
+		//PlatformSetTimer(Adapter, &(pMgntInfo->AwakeTimer), 0);
+		// Notify the AP we awke.
+		rtl8192_hw_wakeup(dev);
+		priv->ieee80211->sta_sleep = 0;
+
+                spin_lock_irqsave(&(priv->ieee80211->mgmt_tx_lock), flags);
+		printk("LPS leave: notify AP we are awaked ++++++++++ SendNullFunctionData\n");
+		ieee80211_sta_ps_send_null_frame(priv->ieee80211, 0);
+                spin_unlock_irqrestore(&(priv->ieee80211->mgmt_tx_lock), flags);
+	}
+
+	return true;
+}
+
+//================================================================================
+// Leisure Power Save in linked state.
+//================================================================================
+
+//
+//	Description:
+//		Enter the leisure power save mode.
+//
+void LeisurePSEnter(struct net_device *dev)
+{
+	struct r8192_priv *priv = ieee80211_priv(dev);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+	//RT_TRACE(COMP_PS, "LeisurePSEnter()...\n");
+	//RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n",
+	//	pPSC->bLeisurePs, priv->ieee80211->ps,pPSC->LpsIdleCount,RT_CHECK_FOR_HANG_PERIOD);
+
+	if(!((priv->ieee80211->iw_mode == IW_MODE_INFRA) &&
+		(priv->ieee80211->state == IEEE80211_LINKED)) ||
+		(priv->ieee80211->iw_mode == IW_MODE_ADHOC) ||
+		(priv->ieee80211->iw_mode == IW_MODE_MASTER))
+		return;
+
+	if (pPSC->bLeisurePs)
+	{
+		// Idle for a while if we connect to AP a while ago.
+		if(pPSC->LpsIdleCount >= RT_CHECK_FOR_HANG_PERIOD) //  4 Sec
+		{
+
+			if(priv->ieee80211->ps == IEEE80211_PS_DISABLED)
+			{
+
+				//RT_TRACE(COMP_LPS, "LeisurePSEnter(): Enter 802.11 power save mode...\n");
+				MgntActSet_802_11_PowerSaveMode(dev, IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST);
+
+			}
+		}
+		else
+			pPSC->LpsIdleCount++;
+	}
+}
+
+
+//
+//	Description:
+//		Leave the leisure power save mode.
+//
+void LeisurePSLeave(struct net_device *dev)
+{
+	struct r8192_priv *priv = ieee80211_priv(dev);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+
+	//RT_TRACE(COMP_PS, "LeisurePSLeave()...\n");
+	//RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d\n",
+	//	pPSC->bLeisurePs, priv->ieee80211->ps);
+
+	if (pPSC->bLeisurePs)
+	{
+		if(priv->ieee80211->ps != IEEE80211_PS_DISABLED)
+		{
+			// move to lps_wakecomplete()
+			//RT_TRACE(COMP_LPS, "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n");
+			MgntActSet_802_11_PowerSaveMode(dev, IEEE80211_PS_DISABLED);
+
+		}
+	}
+}
+#endif
+
+
 //
 //	Description:
 //		Enter the inactive power save mode. RF will be off
@@ -4178,6 +4569,7 @@
 			&& (priv->ieee80211->state != IEEE80211_LINKED) )
 		{
 			RT_TRACE(COMP_RF,"IPSEnter(): Turn off RF.\n");
+			//printk("IPSEnter(): Turn off RF.\n");
 			pPSC->eInactivePowerState = eRfOff;
 //			queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
 			InactivePsWorkItemCallback(dev);
@@ -4203,12 +4595,53 @@
 		if (rtState != eRfOn  && !pPSC->bSwRfProcessing && priv->ieee80211->RfOffReason <= RF_CHANGE_BY_IPS)
 		{
 			RT_TRACE(COMP_POWER, "IPSLeave(): Turn on RF.\n");
+			//printk("IPSLeave(): Turn on RF.\n");
 			pPSC->eInactivePowerState = eRfOn;
 //			queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
 			InactivePsWorkItemCallback(dev);
 		}
 	}
 }
+
+void IPSLeave_wq(void *data)
+{
+	struct ieee80211_device *ieee = container_of(data,struct ieee80211_device,ips_leave_wq);
+	struct net_device *dev = ieee->dev;
+
+	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	down(&priv->ieee80211->ips_sem);
+	IPSLeave(dev);
+	up(&priv->ieee80211->ips_sem);
+}
+
+void ieee80211_ips_leave_wq(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	RT_RF_POWER_STATE	rtState;
+	rtState = priv->ieee80211->eRFPowerState;
+
+	if(priv->ieee80211->PowerSaveControl.bInactivePs){
+		if(rtState == eRfOff){
+			if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
+			{
+				RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
+				return;
+			}
+			else{
+				printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+				queue_work(priv->ieee80211->wq,&priv->ieee80211->ips_leave_wq);
+			}
+		}
+	}
+}
+//added by amy 090331 end
+void ieee80211_ips_leave(struct net_device *dev)
+{
+	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	down(&priv->ieee80211->ips_sem);
+	IPSLeave(dev);
+	up(&priv->ieee80211->ips_sem);
+}
 #endif
 
 static void rtl819x_update_rxcounts(
@@ -4244,15 +4677,23 @@
 	unsigned long flags;
 	bool bBusyTraffic = false;
 	static u8 last_time = 0;
+	bool bEnterPS = false;
+
+	if((!priv->up) || (priv->bHwRadioOff == true))
+		return;
+
 	if(!priv->up)
 		return;
 	hal_dm_watchdog(dev);
 #ifdef ENABLE_IPS
 //	printk("watch_dog ENABLE_IPS\n");
 	if(ieee->actscanning == false){
-		if((ieee->iw_mode != IW_MODE_ADHOC) && (ieee->state == IEEE80211_NOLINK) && (ieee->beinretry == false) && (ieee->eRFPowerState == eRfOn) && !ieee->is_set_key){
+		//printk("%d,%d,%d,%d\n", ieee->eRFPowerState, ieee->is_set_key, ieee->proto_stoppping, ieee->wx_set_enc);
+		if((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == IEEE80211_NOLINK) &&\
+		    (ieee->eRFPowerState == eRfOn)&&!ieee->is_set_key &&\
+		    (!ieee->proto_stoppping) && !ieee->wx_set_enc){
 			if(ieee->PowerSaveControl.ReturnPoint == IPS_CALLBACK_NONE){
-				printk("====================>haha:IPSEnter()\n");
+				//printk("====================>haha:IPSEnter()\n");
 				IPSEnter(dev);
 				//ieee80211_stop_scan(priv->ieee80211);
 			}
@@ -4262,14 +4703,49 @@
 	{//to get busy traffic condition
 		if(ieee->state == IEEE80211_LINKED)
 		{
-			if(	ieee->LinkDetectInfo.NumRxOkInPeriod> 666 ||
-				ieee->LinkDetectInfo.NumTxOkInPeriod> 666 ) {
+			if(	ieee->LinkDetectInfo.NumRxOkInPeriod> 100 ||
+				ieee->LinkDetectInfo.NumTxOkInPeriod> 100 ) {
 				bBusyTraffic = true;
 			}
 
+#ifdef ENABLE_LPS
+			//added by amy for Leisure PS
+			if(	((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod + ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
+				(ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
+			{
+				//printk("ieee->LinkDetectInfo.NumRxUnicastOkInPeriod is %d,ieee->LinkDetectInfo.NumTxOkInPeriod is %d\n",
+				//	ieee->LinkDetectInfo.NumRxUnicastOkInPeriod,ieee->LinkDetectInfo.NumTxOkInPeriod);
+				bEnterPS= false;
+			}
+			else
+			{
+				bEnterPS= true;
+			}
+
+			//printk("***bEnterPS = %d\n", bEnterPS);
+			// LeisurePS only work in infra mode.
+			if(bEnterPS)
+			{
+				LeisurePSEnter(dev);
+			}
+			else
+			{
+				LeisurePSLeave(dev);
+			}
+#endif
+
 		}
+		else
+		{
+#ifdef ENABLE_LPS
+			//RT_TRACE(COMP_LPS,"====>no link LPS leave\n");
+			LeisurePSLeave(dev);
+#endif
+		}
+
 	        ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
 	        ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
+		ieee->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
 		ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
 	}
 
@@ -4288,14 +4764,14 @@
 				if( ieee->eRFPowerState == eRfOff)
 					RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
 				printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__);
-		//		Dot11d_Reset(dev);
+				//		Dot11d_Reset(dev);
 				ieee->state = IEEE80211_ASSOCIATING;
 				notify_wx_assoc_event(priv->ieee80211);
-                                RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
+				RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
 				ieee->is_roaming = true;
 				ieee->is_set_key = false;
-                             ieee->link_change(dev);
-                                queue_work(ieee->wq, &ieee->associate_procedure_wq);
+				ieee->link_change(dev);
+				queue_work(ieee->wq, &ieee->associate_procedure_wq);
 			}
 		}
 	      ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
@@ -4348,6 +4824,7 @@
 	RT_STATUS init_status = RT_STATUS_SUCCESS;
 	priv->up=1;
 	priv->ieee80211->ieee_up=1;
+	priv->bdisable_nic = false;  //YJ,add,091111
 	RT_TRACE(COMP_INIT, "Bringing up iface");
 
 	init_status = rtl8192_adapter_start(dev);
@@ -4422,6 +4899,12 @@
 #endif
 	if (priv->up == 0) return -1;
 
+#ifdef ENABLE_LPS
+	//LZM for PS-Poll AID issue. 090429
+	if(priv->ieee80211->state == IEEE80211_LINKED)
+		LeisurePSLeave(dev);
+#endif
+
 	priv->up=0;
 	priv->ieee80211->ieee_up = 0;
 	RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
@@ -4459,11 +4942,9 @@
 	deinit_hal_dm(dev);
 	del_timer_sync(&priv->watch_dog_timer);
 
-	ieee80211_softmac_stop_protocol(priv->ieee80211);
-#ifdef ENABLE_IPS
-	MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT);
-#endif
-	rtl8192_rtx_disable(dev);
+	ieee80211_softmac_stop_protocol(priv->ieee80211,true);
+
+	rtl8192_halt_adapter(dev,false);
 	memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list));
 
 	RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
@@ -4479,10 +4960,10 @@
 	if (priv->up == 0) return ;
 
 
-	ieee80211_softmac_stop_protocol(priv->ieee80211);
+	ieee80211_softmac_stop_protocol(priv->ieee80211,true);
 
 	rtl8192_irq_disable(dev);
-	rtl8192_rtx_disable(dev);
+	rtl8192_halt_adapter(dev,true);
 	_rtl8192_up(dev);
 }
 
@@ -5806,8 +6287,7 @@
 
                 skb = new_skb;
                 priv->rx_buf[priv->rx_idx] = skb;
-                *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb->tail, priv->rxbuffersize, PCI_DMA_FROMDEVICE);
-//                *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
+                *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
             }
 
         }
@@ -6036,7 +6516,7 @@
 	/* call cancel_work_sync instead of cancel_delayed_work if and only if Linux_version_code
          * is  or is newer than 2.6.20 and work structure is defined to be struct work_struct.
          * Otherwise call cancel_delayed_work is enough.
-         * FIXME (2.6.20 shoud 2.6.22, work_struct shoud not cancel)
+         * FIXME (2.6.20 should 2.6.22, work_struct should not cancel)
          * */
 	cancel_delayed_work(&priv->watch_dog_wq);
 	cancel_delayed_work(&priv->update_beacon_wq);
@@ -6381,11 +6861,13 @@
 			if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
 			{
 				RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
-				up(&priv->wx_sem);
+				//up(&priv->wx_sem);
 				return ;
 			}
 			else{
+				down(&priv->ieee80211->ips_sem);
 				IPSLeave(dev);
+				up(&priv->ieee80211->ips_sem);
 			}
 		}
 	}
@@ -6394,7 +6876,7 @@
 	if (EntryNo >= TOTAL_CAM_ENTRY)
 		RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
 
-	RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex, KeyType, MAC_ARG(MacAddr));
+	RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", dev,EntryNo, KeyIndex, KeyType, MacAddr);
 
 	if (DefaultKey)
 		usConfig |= BIT15 | (KeyType<<2);
@@ -6455,6 +6937,65 @@
 	RT_TRACE(COMP_SEC, "WPA_Config=%x \n",ucValue);
 }
 
+bool NicIFEnableNIC(struct net_device* dev)
+{
+	RT_STATUS init_status = RT_STATUS_SUCCESS;
+	struct r8192_priv* priv = ieee80211_priv(dev);
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+	//YJ,add,091109
+	if (priv->up == 0){
+		RT_TRACE(COMP_ERR, "ERR!!! %s(): Driver is already down!\n",__FUNCTION__);
+		priv->bdisable_nic = false;  //YJ,add,091111
+		return false;
+	}
+	// <1> Reset memory: descriptor, buffer,..
+	//NicIFResetMemory(Adapter);
+
+	// <2> Enable Adapter
+	//printk("===========>%s()\n",__FUNCTION__);
+	//priv->bfirst_init = true;
+	init_status = rtl8192_adapter_start(dev);
+	if (init_status != RT_STATUS_SUCCESS) {
+		RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
+		priv->bdisable_nic = false;  //YJ,add,091111
+		return -1;
+	}
+	//printk("start adapter finished\n");
+	RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+	//priv->bfirst_init = false;
+
+	// <3> Enable Interrupt
+	rtl8192_irq_enable(dev);
+	priv->bdisable_nic = false;
+	//RT_TRACE(COMP_PS,"<===========%s()\n",__FUNCTION__);
+	return (init_status == RT_STATUS_SUCCESS) ? true:false;
+}
+bool NicIFDisableNIC(struct net_device* dev)
+{
+	bool	status = true;
+	struct r8192_priv* priv = ieee80211_priv(dev);
+	u8 tmp_state = 0;
+	// <1> Disable Interrupt
+	//RT_TRACE(COMP_PS, "=========>%s()\n",__FUNCTION__);
+	priv->bdisable_nic = true;	//YJ,move,091109
+	tmp_state = priv->ieee80211->state;
+
+	ieee80211_softmac_stop_protocol(priv->ieee80211, false);
+
+	priv->ieee80211->state = tmp_state;
+	rtl8192_cancel_deferred_work(priv);
+	rtl8192_irq_disable(dev);
+	// <2> Stop all timer
+
+	// <3> Disable Adapter
+	rtl8192_halt_adapter(dev, false);
+//	priv->bdisable_nic = true;
+	//RT_TRACE(COMP_PS, "<=========%s()\n",__FUNCTION__);
+
+	return status;
+}
+
 
 /***************************************************************************
      ------------------- module init / exit stubs ----------------
diff --git a/drivers/staging/rtl8192e/r8192E_dm.c b/drivers/staging/rtl8192e/r8192E_dm.c
index 5ffb4f7..a249f00 100644
--- a/drivers/staging/rtl8192e/r8192E_dm.c
+++ b/drivers/staging/rtl8192e/r8192E_dm.c
@@ -19,26 +19,28 @@
 #include "r819xE_phy.h"
 #include "r819xE_phyreg.h"
 #include "r8190_rtl8256.h"
+
+#define DRV_NAME "rtl819xE"
 /*---------------------------Define Local Constant---------------------------*/
 //
 // Indicate different AP vendor for IOT issue.
 //
 #ifdef  RTL8190P
 static u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 	0x5e4322, 	0x5e4322,  	0x604322, 	0xa44f, 	0x5e4322};
+{ 0x5e4322, 	0x5e4322, 	0x5e4322,  	0x604322, 	0xa44f, 	0x5e4322,	0x5e4322};
 static u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 	0xa44f, 	0x5e4322,  	0x604322, 	0x5e4322, 	0x5e4322};
+{ 0x5e4322, 	0xa44f, 	0x5e4322,  	0x604322, 	0x5e4322, 	0x5e4322,	0x5e4322};
 #else
 #ifdef RTL8192E
 static u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 	0x5e4322, 	0x5e4322, 	0x604322, 	0xa44f, 	0x5e4322};
+{ 0x5e4322, 	0x5e4322, 	0x5e4322, 	0x604322, 	0xa44f, 	0x5e4322,	0x5e4322};
 static u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 	0xa44f,		0x5e4322,  	0x604322, 	0x5e4322, 	0x5e4322};
+{ 0x5e4322, 	0xa44f,		0x5e4322,  	0x604322, 	0x5e4322, 	0x5e4322, 	0x5e4322};
 #else
 static u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 	0x5e4322, 	0x5e4322, 	0x604322, 	0xa44f, 	0x5ea44f};
+{ 0x5e4322, 	0x5e4322, 	0x5e4322, 	0x604322, 	0xa44f, 	0x5ea44f, 	0x5e4322};
 static u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 	0xa44f, 	0x5e4322, 	0x604322, 	0x5ea44f, 	0x5ea44f};
+{ 0x5e4322, 	0xa44f, 	0x5e4322, 	0x604322, 	0x5ea44f, 	0x5ea44f, 	0x5e4322};
 #endif
 #endif
 
@@ -275,6 +277,30 @@
 #endif
 
 
+// call the script file to enable
+void dm_check_ac_dc_power(struct net_device *dev)
+{
+	struct r8192_priv *priv = ieee80211_priv(dev);
+	static char *ac_dc_check_script_path = "/etc/acpi/wireless-rtl-ac-dc-power.sh";
+	char *argv[] = {ac_dc_check_script_path,DRV_NAME,NULL};
+	static char *envp[] = {"HOME=/",
+			"TERM=linux",
+			"PATH=/usr/bin:/bin",
+			 NULL};
+
+	if(priv->ResetProgress == RESET_TYPE_SILENT)
+	{
+		RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n");
+		return;
+	}
+
+	if(priv->ieee80211->state != IEEE80211_LINKED) {
+		return;
+	}
+	call_usermodehelper(ac_dc_check_script_path,argv,envp,1);
+
+	return;
+};
 
 void hal_dm_watchdog(struct net_device *dev)
 {
@@ -282,6 +308,8 @@
 
 	//static u8 	previous_bssid[6] ={0};
 
+	dm_check_ac_dc_power(dev);
+
 	/*Add by amy 2008/05/15 ,porting from windows code.*/
 	dm_check_rate_adaptive(dev);
 	dm_dynamic_txpower(dev);
diff --git a/drivers/staging/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/r8192E_hw.h
index 388908f..346bfb1 100644
--- a/drivers/staging/rtl8192e/r8192E_hw.h
+++ b/drivers/staging/rtl8192e/r8192E_hw.h
@@ -808,4 +808,12 @@
 #define GPI 0x108
 #define GPO 0x109
 #define GPE 0x10a
+
+#define	ANAPAR_FOR_8192PciE							0x17		// Analog parameter register
+
+#define	MSR_NOLINK					0x00
+#define	MSR_ADHOC					0x01
+#define	MSR_INFRA					0x02
+#define	MSR_AP						0x03
+
 #endif
diff --git a/drivers/staging/rtl8192e/r8192E_wx.c b/drivers/staging/rtl8192e/r8192E_wx.c
index d1eb892..0b0f39c 100644
--- a/drivers/staging/rtl8192e/r8192E_wx.c
+++ b/drivers/staging/rtl8192e/r8192E_wx.c
@@ -22,7 +22,7 @@
 #include "r8192E_hw.h"
 #include "r8192E_wx.h"
 #ifdef ENABLE_DOT11D
-#include "dot11d.h"
+#include "ieee80211/dot11d.h"
 #endif
 
 #define RATE_COUNT 12
@@ -70,6 +70,9 @@
 	int ret;
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 
 	ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra);
@@ -87,6 +90,9 @@
 	int ret;
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 
 	ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra);
@@ -111,6 +117,9 @@
 	int ret;
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 
 	ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra);
@@ -290,6 +299,9 @@
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	int ret;
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 
 	ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
@@ -325,6 +337,9 @@
 	int enable = (parms[0] > 0);
 	short prev = priv->crcmon;
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 
 	if(enable)
@@ -352,6 +367,9 @@
 	RT_RF_POWER_STATE	rtState;
 	int ret;
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	rtState = priv->ieee80211->eRFPowerState;
 	down(&priv->wx_sem);
 #ifdef ENABLE_IPS
@@ -366,8 +384,10 @@
 					return -1;
 				}
 				else{
-				printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+					RT_TRACE(COMP_ERR, "%s(): IPSLeave\n",__FUNCTION__);
+					down(&priv->ieee80211->ips_sem);
 					IPSLeave(dev);
+					up(&priv->ieee80211->ips_sem);
 				}
 			}
 		}
@@ -425,7 +445,7 @@
 	 */
 
 	/* ~5 Mb/s real (802.11b) */
-	range->throughput = 5 * 1000 * 1000;
+	range->throughput = 130 * 1000 * 1000;
 
 	// TODO: Not used in 802.11b?
 //	range->min_nwid;	/* Minimal NWID we are able to set */
@@ -468,7 +488,7 @@
 	range->pmt_flags = IW_POWER_TIMEOUT;
 	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
 	range->we_version_compiled = WIRELESS_EXT;
-	range->we_version_source = 16;
+	range->we_version_source = 18;
 
 //	range->retry_capa;	/* What retry options are supported */
 //	range->retry_flags;	/* How to decode max/min retry limit */
@@ -517,7 +537,12 @@
 	struct ieee80211_device* ieee = priv->ieee80211;
 	RT_RF_POWER_STATE	rtState;
 	int ret;
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	rtState = priv->ieee80211->eRFPowerState;
+
 	if(!priv->up) return -ENETDOWN;
 	if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
 		return -EAGAIN;
@@ -547,8 +572,10 @@
 					return -1;
 				}
 				else{
-					printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+					//RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__);
+					down(&priv->ieee80211->ips_sem);
 					IPSLeave(dev);
+					up(&priv->ieee80211->ips_sem);
 				}
 			}
 		}
@@ -580,6 +607,9 @@
 	int ret;
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	if(!priv->up) return -ENETDOWN;
 
 	down(&priv->wx_sem);
@@ -599,23 +629,16 @@
 	RT_RF_POWER_STATE	rtState;
 	int ret;
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	rtState = priv->ieee80211->eRFPowerState;
 	down(&priv->wx_sem);
+
 #ifdef ENABLE_IPS
-	if(priv->ieee80211->PowerSaveControl.bInactivePs){
-		if(rtState == eRfOff){
-			if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
-			{
-				RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
-				up(&priv->wx_sem);
-				return -1;
-			}
-			else{
-				printk("=========>%s(): IPSLeave\n",__FUNCTION__);
-				IPSLeave(dev);
-			}
-		}
-	}
+        down(&priv->ieee80211->ips_sem);
+        IPSLeave(dev);
+        up(&priv->ieee80211->ips_sem);
 #endif
 	ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
 
@@ -650,6 +673,9 @@
 	int ret;
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 
 	ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
@@ -673,6 +699,9 @@
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	if (wrqu->frag.disabled)
 		priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
 	else {
@@ -711,8 +740,16 @@
 	struct r8192_priv *priv = ieee80211_priv(dev);
 //        struct sockaddr *temp = (struct sockaddr *)awrq;
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 
+#ifdef ENABLE_IPS
+        down(&priv->ieee80211->ips_sem);
+        IPSLeave(dev);
+        up(&priv->ieee80211->ips_sem);
+#endif
 	ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
 
 	up(&priv->wx_sem);
@@ -753,14 +790,24 @@
 	u32 hwkey[4]={0,0,0,0};
 	u8 mask=0xff;
 	u32 key_idx=0;
-	u8 zero_addr[4][6] ={	{0x00,0x00,0x00,0x00,0x00,0x00},
+	u8 zero_addr[4][6] ={{0x00,0x00,0x00,0x00,0x00,0x00},
 				{0x00,0x00,0x00,0x00,0x00,0x01},
 				{0x00,0x00,0x00,0x00,0x00,0x02},
 				{0x00,0x00,0x00,0x00,0x00,0x03} };
 	int i;
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
        if(!priv->up) return -ENETDOWN;
 
+        priv->ieee80211->wx_set_enc = 1;
+#ifdef ENABLE_IPS
+        down(&priv->ieee80211->ips_sem);
+        IPSLeave(dev);
+        up(&priv->ieee80211->ips_sem);
+#endif
+
 	down(&priv->wx_sem);
 
 	RT_TRACE(COMP_SEC, "Setting SW wep key");
@@ -768,7 +815,6 @@
 
 	up(&priv->wx_sem);
 
-
 	//sometimes, the length is zero while we do not type key value
 	if(wrqu->encoding.length!=0){
 
@@ -868,6 +914,8 @@
 	}
 #endif
 
+	priv->ieee80211->wx_set_enc = 0;
+
 	return ret;
 }
 
@@ -893,6 +941,9 @@
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	int err = 0;
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 
 	if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
@@ -985,6 +1036,10 @@
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
 	short err = 0;
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 	//DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
 	if(priv->rf_set_sens == NULL) {
@@ -1011,7 +1066,19 @@
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_device* ieee = priv->ieee80211;
 
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
+
+	priv->ieee80211->wx_set_enc = 1;
+
+#ifdef ENABLE_IPS
+        down(&priv->ieee80211->ips_sem);
+        IPSLeave(dev);
+        up(&priv->ieee80211->ips_sem);
+#endif
+
 	ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
 
 	{
@@ -1091,6 +1158,7 @@
 	}
 
 end_hw_sec:
+	priv->ieee80211->wx_set_enc = 0;
 	up(&priv->wx_sem);
 	return ret;
 
@@ -1102,6 +1170,10 @@
 	int ret=0;
 	//printk("====>%s()\n", __FUNCTION__);
 	struct r8192_priv *priv = ieee80211_priv(dev);
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 	ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
 	up(&priv->wx_sem);
@@ -1116,6 +1188,10 @@
 
 	int ret=0;
 	struct r8192_priv *priv = ieee80211_priv(dev);
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+
 	down(&priv->wx_sem);
 	ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
 	up(&priv->wx_sem);
@@ -1129,6 +1205,10 @@
 	   //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
 	int ret=0;
         struct r8192_priv *priv = ieee80211_priv(dev);
+
+	if(priv->bHwRadioOff == true)
+		return 0;
+
         down(&priv->wx_sem);
         ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
         up(&priv->wx_sem);
@@ -1142,6 +1222,42 @@
 	return -1;
 }
 
+// check ac/dc status with the help of user space application */
+static int r8192_wx_adapter_power_status(struct net_device *dev,
+		struct iw_request_info *info,
+		union iwreq_data *wrqu, char *extra)
+{
+	struct r8192_priv *priv = ieee80211_priv(dev);
+#ifdef ENABLE_LPS
+	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+	struct ieee80211_device* ieee = priv->ieee80211;
+#endif
+	down(&priv->wx_sem);
+
+#ifdef ENABLE_LPS
+	RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra ==  6)?"DC power":"AC power");
+	// ieee->ps shall not be set under DC mode, otherwise it conflict
+	// with Leisure power save mode setting.
+	//
+	if(*extra || priv->force_lps) {
+		priv->ps_force = false;
+		pPSC->bLeisurePs = true;
+	} else {
+		//LZM for PS-Poll AID issue. 090429
+		if(priv->ieee80211->state == IEEE80211_LINKED)
+			LeisurePSLeave(dev);
+
+		priv->ps_force = true;
+		pPSC->bLeisurePs = false;
+		ieee->ps = *extra;
+	}
+
+#endif
+	up(&priv->wx_sem);
+	return 0;
+
+}
+
 
 static iw_handler r8192_wx_handlers[] =
 {
@@ -1231,72 +1347,28 @@
 		SIOCIWFIRSTPRIV + 0x2,
 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
 	}
-#ifdef JOHN_IOCTL
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x3,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readRF"
-	}
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x4,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeRF"
-	}
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x5,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readBB"
-	}
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x6,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeBB"
-	}
-        ,
-        {
-                SIOCIWFIRSTPRIV + 0x7,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readnicb"
-        }
-        ,
-        {
-                SIOCIWFIRSTPRIV + 0x8,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writenicb"
-        }
-        ,
-        {
-                SIOCIWFIRSTPRIV + 0x9,
-                IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
-        }
-
-#endif
 	,
 	{
 		SIOCIWFIRSTPRIV + 0x3,
 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
 
 	}
+	,
+	{
+		SIOCIWFIRSTPRIV + 0x4,
+		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
+		"set_power"
+	}
 
 };
 
 
 static iw_handler r8192_private_handler[] = {
-//	r8192_wx_set_monitor,  /* SIOCIWFIRSTPRIV */
 	r8192_wx_set_crcmon,   /*SIOCIWSECONDPRIV*/
-//	r8192_wx_set_forceassociate,
-//	r8192_wx_set_beaconinterval,
-//	r8192_wx_set_monitor_type,
 	r8192_wx_set_scan_type,
 	r8192_wx_set_rawtx,
-#ifdef JOHN_IOCTL
-	r8192_wx_read_regs,
-	r8192_wx_write_regs,
-	r8192_wx_read_bb,
-	r8192_wx_write_bb,
-        r8192_wx_read_nicb,
-        r8192_wx_write_nicb,
-	r8192_wx_get_ap_status
-#endif
 	r8192_wx_force_reset,
+	r8192_wx_adapter_power_status,
 };
 
 //#if WIRELESS_EXT >= 17
diff --git a/drivers/staging/rtl8192e/r8192E_wx.h b/drivers/staging/rtl8192e/r8192E_wx.h
index 79ebdb6..047030b 100644
--- a/drivers/staging/rtl8192e/r8192E_wx.h
+++ b/drivers/staging/rtl8192e/r8192E_wx.h
@@ -15,7 +15,6 @@
 #ifndef R8180_WX_H
 #define R8180_WX_H
 //#include <linux/wireless.h>
-//#include "ieee80211.h"
 extern struct iw_handler_def r8192_wx_handlers_def;
 /* Enable  the rtl819x_core.c to share this function, david 2008.9.22 */
 extern struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
diff --git a/drivers/staging/rtl8192e/r819xE_cmdpkt.c b/drivers/staging/rtl8192e/r819xE_cmdpkt.c
index 2aaa4e1..87c334f 100644
--- a/drivers/staging/rtl8192e/r819xE_cmdpkt.c
+++ b/drivers/staging/rtl8192e/r819xE_cmdpkt.c
@@ -135,7 +135,7 @@
              * Transform from little endian to big endian
              * and pending  zero
              */
-            seg_ptr = skb->tail;
+            seg_ptr = skb_tail_pointer(skb);
             for(i=0 ; i < frag_length; i+=4) {
                 *seg_ptr++ = ((i+0)<frag_length)?code_virtual_address[i+3]:0;
                 *seg_ptr++ = ((i+1)<frag_length)?code_virtual_address[i+2]:0;
diff --git a/drivers/staging/rtl8192e/r819xE_firmware.c b/drivers/staging/rtl8192e/r819xE_firmware.c
index 1f9e413..793a175 100644
--- a/drivers/staging/rtl8192e/r819xE_firmware.c
+++ b/drivers/staging/rtl8192e/r819xE_firmware.c
@@ -1,5 +1,5 @@
 /*
- * Procedure:    Init boot code/firmware code/data session
+ * Procedure: Init boot code/firmware code/data session
  *
  * Description: This routine will intialize firmware. If any error occurs
  *		during the initialization process, the routine shall terminate
@@ -7,19 +7,21 @@
  *		NdisOpenFile only from MiniportInitialize.
  *
  * Arguments:   The pointer of the adapter
-
+ *
  * Returns:
  *		NDIS_STATUS_FAILURE - the following initialization process
  *				      should be terminated
  *		NDIS_STATUS_SUCCESS - if firmware initialization process
  *				      success
  */
+
 #include "r8192E.h"
 #include "r8192E_hw.h"
+
 #include <linux/firmware.h>
 
 /* It should be double word alignment */
-#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v)	(4 * (v / 4) - 8)
+#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4 * (v / 4) - 8)
 
 enum firmware_init_step {
 	FW_INIT_STEP0_BOOT = 0,
@@ -47,17 +49,17 @@
 static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
 			     u32 buffer_len)
 {
-	struct r8192_priv   *priv = ieee80211_priv(dev);
-	bool 		    rt_status = true;
-	u16		    frag_threshold;
-	u16		    frag_length, frag_offset = 0;
-	int		    i;
+	struct r8192_priv *priv = ieee80211_priv(dev);
+	bool rt_status = true;
+	u16 frag_threshold;
+	u16 frag_length, frag_offset = 0;
+	int i;
 
-	rt_firmware	    *pfirmware = priv->pFirmware;
-	struct sk_buff	    *skb;
-	unsigned char	    *seg_ptr;
-	cb_desc		    *tcb_desc;
-	u8                  bLastIniPkt;
+	rt_firmware *pfirmware = priv->pFirmware;
+	struct sk_buff *skb;
+	unsigned char *seg_ptr;
+	cb_desc *tcb_desc;
+	u8 bLastIniPkt;
 
 	firmware_init_param(dev);
 
@@ -89,10 +91,17 @@
 		 * Transform from little endian to big endian and pending zero
 		 */
 		for (i = 0; i < frag_length; i += 4) {
-			*seg_ptr++ = ((i+0) < frag_length) ? code_virtual_address[i+3] : 0;
-			*seg_ptr++ = ((i+1) < frag_length) ? code_virtual_address[i+2] : 0;
-			*seg_ptr++ = ((i+2) < frag_length) ? code_virtual_address[i+1] : 0;
-			*seg_ptr++ = ((i+3) < frag_length) ? code_virtual_address[i+0] : 0;
+			*seg_ptr++ = ((i+0) < frag_length) ? \
+					code_virtual_address[i+3] : 0;
+
+			*seg_ptr++ = ((i+1) < frag_length) ? \
+					code_virtual_address[i+2] : 0;
+
+			*seg_ptr++ = ((i+2) < frag_length) ? \
+					code_virtual_address[i+1] : 0;
+
+			*seg_ptr++ = ((i+3) < frag_length) ? \
+					code_virtual_address[i+0] : 0;
 		}
 		tcb_desc->txbuf_size = (u16)i;
 		skb_put(skb, i);
@@ -204,16 +213,16 @@
 
 bool init_firmware(struct net_device *dev)
 {
-	struct r8192_priv 	*priv = ieee80211_priv(dev);
-	bool			rt_status = TRUE;
-	u32			file_length = 0;
-	u8			*mapped_file = NULL;
-	u32			init_step = 0;
-	enum opt_rst_type	rst_opt = OPT_SYSTEM_RESET;
+	struct r8192_priv *priv = ieee80211_priv(dev);
+	bool rt_status = true;
+	u32 file_length = 0;
+	u8 *mapped_file = NULL;
+	u32 init_step = 0;
+	enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
 	enum firmware_init_step	starting_state = FW_INIT_STEP0_BOOT;
 
-	rt_firmware		*pfirmware = priv->pFirmware;
-	const struct firmware 	*fw_entry;
+	rt_firmware *pfirmware = priv->pFirmware;
+	const struct firmware *fw_entry;
 	const char *fw_name[3] = { "RTL8192E/boot.img",
 				   "RTL8192E/main.img",
 				   "RTL8192E/data.img"};
@@ -240,31 +249,37 @@
 	 * Download boot, main, and data image for System reset.
 	 * Download data image for firmware reseta
 	 */
-	for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) {
+	for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; \
+			init_step++) {
 		/*
 		 * Open Image file, and map file to contineous memory if open file success.
 		 * or read image file from array. Default load from IMG file
 		 */
 		if (rst_opt == OPT_SYSTEM_RESET) {
 			if (pfirmware->firmware_buf_size[init_step] == 0) {
-				rc = request_firmware(&fw_entry, fw_name[init_step], &priv->pdev->dev);
+				rc = request_firmware(&fw_entry,
+					fw_name[init_step], &priv->pdev->dev);
+
 				if (rc < 0) {
 					RT_TRACE(COMP_FIRMWARE, "request firmware fail!\n");
 					goto download_firmware_fail;
 				}
 
 				if (fw_entry->size > sizeof(pfirmware->firmware_buf[init_step])) {
-					RT_TRACE(COMP_FIRMWARE, "img file size exceed the container buffer fail!\n");
+					RT_TRACE(COMP_FIRMWARE, \
+						"img file size exceed the container buffer fail!\n");
 					goto download_firmware_fail;
 				}
 
 				if (init_step != FW_INIT_STEP1_MAIN) {
-					memcpy(pfirmware->firmware_buf[init_step], fw_entry->data, fw_entry->size);
+					memcpy(pfirmware->firmware_buf[init_step],
+							fw_entry->data, fw_entry->size);
 					pfirmware->firmware_buf_size[init_step] = fw_entry->size;
 
 				} else {
 					memset(pfirmware->firmware_buf[init_step], 0, 128);
-					memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data, fw_entry->size);
+					memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data,
+									fw_entry->size);
 					pfirmware->firmware_buf_size[init_step] = fw_entry->size+128;
 				}
 
@@ -273,6 +288,7 @@
 			}
 			mapped_file = pfirmware->firmware_buf[init_step];
 			file_length = pfirmware->firmware_buf_size[init_step];
+
 		} else if (rst_opt == OPT_FIRMWARE_RESET) {
 			/* we only need to download data.img here */
 			mapped_file = pfirmware->firmware_buf[init_step];
@@ -346,7 +362,10 @@
 
 download_firmware_fail:
 	RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
-	rt_status = FALSE;
+	rt_status = false;
 	return rt_status;
-
 }
+
+MODULE_FIRMWARE("RTL8192E/boot.img");
+MODULE_FIRMWARE("RTL8192E/main.img");
+MODULE_FIRMWARE("RTL8192E/data.img");
diff --git a/drivers/staging/rtl8192e/r819xE_phy.c b/drivers/staging/rtl8192e/r819xE_phy.c
index c44059a..7bd4fae 100644
--- a/drivers/staging/rtl8192e/r819xE_phy.c
+++ b/drivers/staging/rtl8192e/r819xE_phy.c
@@ -5,7 +5,7 @@
 #include "r819xE_phy.h"
 #include "r8192E_dm.h"
 #ifdef ENABLE_DOT11D
-#include "dot11d.h"
+#include "ieee80211/dot11d.h"
 #endif
 static u32 RF_CHANNEL_TABLE_ZEBRA[] = {
 	0,
diff --git a/drivers/staging/rtl8192e/r819xE_phy.h b/drivers/staging/rtl8192e/r819xE_phy.h
index fa77abe..41e0d77 100644
--- a/drivers/staging/rtl8192e/r819xE_phy.h
+++ b/drivers/staging/rtl8192e/r819xE_phy.h
@@ -1,43 +1,46 @@
 #ifndef _R819XU_PHY_H
 #define _R819XU_PHY_H
-/* Channel switch:The size of command tables for switch channel*/
+
+/* Channel switch: the size of command tables for switch channel */
 #define MAX_PRECMD_CNT 16
 #define MAX_RFDEPENDCMD_CNT 16
 #define MAX_POSTCMD_CNT 16
 
 #ifdef RTL8190P
 #define MACPHY_Array_PGLength 21
-#define Rtl819XMACPHY_Array_PG			Rtl8190PciMACPHY_Array_PG
-#define Rtl819XMACPHY_Array				Rtl8190PciMACPHY_Array
+#define Rtl819XMACPHY_Array_PG Rtl8190PciMACPHY_Array_PG
+#define Rtl819XMACPHY_Array Rtl8190PciMACPHY_Array
 #define RadioC_ArrayLength 246
 #define RadioD_ArrayLength 78
-#define Rtl819XRadioA_Array					Rtl8190PciRadioA_Array
-#define Rtl819XRadioB_Array					Rtl8190PciRadioB_Array
-#define Rtl819XRadioC_Array					Rtl8190PciRadioC_Array
-#define Rtl819XRadioD_Array					Rtl8190PciRadioD_Array
-#define Rtl819XAGCTAB_Array				Rtl8190PciAGCTAB_Array
-#define PHY_REGArrayLength 				280
-#define Rtl819XPHY_REGArray				Rtl8190PciPHY_REGArray
-#define PHY_REG_1T2RArrayLength 		280
-#define Rtl819XPHY_REG_1T2RArray		Rtl8190PciPHY_REG_1T2RArray
+#define Rtl819XRadioA_Array Rtl8190PciRadioA_Array
+#define Rtl819XRadioB_Array Rtl8190PciRadioB_Array
+#define Rtl819XRadioC_Array Rtl8190PciRadioC_Array
+#define Rtl819XRadioD_Array Rtl8190PciRadioD_Array
+#define Rtl819XAGCTAB_Array Rtl8190PciAGCTAB_Array
+#define PHY_REGArrayLength 280
+#define Rtl819XPHY_REGArray Rtl8190PciPHY_REGArray
+#define PHY_REG_1T2RArrayLength 280
+#define Rtl819XPHY_REG_1T2RArray Rtl8190PciPHY_REG_1T2RArray
 #endif
 
-	#ifdef RTL8192E
-	#define MACPHY_Array_PGLength 30
-	#define Rtl819XMACPHY_Array_PG			Rtl8192PciEMACPHY_Array_PG
-	#define Rtl819XMACPHY_Array				Rtl8192PciEMACPHY_Array
-	#define RadioC_ArrayLength 1
-	#define RadioD_ArrayLength 1
-	#define Rtl819XRadioA_Array					Rtl8192PciERadioA_Array
-	#define Rtl819XRadioB_Array					Rtl8192PciERadioB_Array
-	#define Rtl819XRadioC_Array					Rtl8192PciERadioC_Array
-	#define Rtl819XRadioD_Array					Rtl8192PciERadioD_Array
-	#define Rtl819XAGCTAB_Array				Rtl8192PciEAGCTAB_Array
-	#define PHY_REGArrayLength 				1
-	#define Rtl819XPHY_REGArray				Rtl8192PciEPHY_REGArray
-	#define PHY_REG_1T2RArrayLength 		296
-	#define Rtl819XPHY_REG_1T2RArray		Rtl8192PciEPHY_REG_1T2RArray
-	#endif
+
+#ifdef RTL8192E
+#define MACPHY_Array_PGLength 30
+#define Rtl819XMACPHY_Array_PG Rtl8192PciEMACPHY_Array_PG
+#define Rtl819XMACPHY_Array Rtl8192PciEMACPHY_Array
+#define RadioC_ArrayLength 1
+#define RadioD_ArrayLength 1
+#define Rtl819XRadioA_Array Rtl8192PciERadioA_Array
+#define Rtl819XRadioB_Array Rtl8192PciERadioB_Array
+#define Rtl819XRadioC_Array Rtl8192PciERadioC_Array
+#define Rtl819XRadioD_Array Rtl8192PciERadioD_Array
+#define Rtl819XAGCTAB_Array Rtl8192PciEAGCTAB_Array
+#define PHY_REGArrayLength 1
+#define Rtl819XPHY_REGArray Rtl8192PciEPHY_REGArray
+#define PHY_REG_1T2RArrayLength 296
+#define Rtl819XPHY_REG_1T2RArray Rtl8192PciEPHY_REG_1T2RArray
+#endif
+
 #define AGCTAB_ArrayLength 384
 #define MACPHY_ArrayLength 18
 
@@ -45,7 +48,7 @@
 #define RadioB_ArrayLength 78
 
 
-typedef enum _SwChnlCmdID{
+typedef enum _SwChnlCmdID {
 	CmdID_End,
 	CmdID_SetTxPowerLevel,
 	CmdID_BBRegWrite10,
@@ -53,16 +56,15 @@
 	CmdID_WritePortUshort,
 	CmdID_WritePortUchar,
 	CmdID_RF_WriteReg,
-}SwChnlCmdID;
+} SwChnlCmdID;
 
-/*--------------------------------Define structure--------------------------------*/
-/* 1. Switch channel related */
-typedef struct _SwChnlCmd{
-	SwChnlCmdID	CmdID;
-	u32			Para1;
-	u32			Para2;
-	u32			msDelay;
-}__attribute__ ((packed)) SwChnlCmd;
+/* switch channel data structure */
+typedef struct _SwChnlCmd {
+	SwChnlCmdID CmdID;
+	u32 Para1;
+	u32 Para2;
+	u32 msDelay;
+} __attribute__ ((packed)) SwChnlCmd;
 
 extern u32 rtl819XMACPHY_Array_PG[];
 extern u32 rtl819XPHY_REG_1T2RArray[];
@@ -72,54 +74,90 @@
 extern u32 rtl819XRadioC_Array[];
 extern u32 rtl819XRadioD_Array[];
 
-typedef enum _HW90_BLOCK{
+typedef enum _HW90_BLOCK {
 	HW90_BLOCK_MAC = 0,
 	HW90_BLOCK_PHY0 = 1,
 	HW90_BLOCK_PHY1 = 2,
 	HW90_BLOCK_RF = 3,
-	HW90_BLOCK_MAXIMUM = 4, // Never use this
-}HW90_BLOCK_E, *PHW90_BLOCK_E;
+	/* Don't ever use this. */
+	HW90_BLOCK_MAXIMUM = 4,
+} HW90_BLOCK_E, *PHW90_BLOCK_E;
 
-typedef enum _RF90_RADIO_PATH{
-	RF90_PATH_A = 0,			//Radio Path A
-	RF90_PATH_B = 1,			//Radio Path B
-	RF90_PATH_C = 2,			//Radio Path C
-	RF90_PATH_D = 3,			//Radio Path D
-	RF90_PATH_MAX				//Max RF number 92 support
-}RF90_RADIO_PATH_E, *PRF90_RADIO_PATH_E;
+typedef enum _RF90_RADIO_PATH {
+	/* Radio paths */
+	RF90_PATH_A = 0,
+	RF90_PATH_B = 1,
+	RF90_PATH_C = 2,
+	RF90_PATH_D = 3,
 
-#define bMaskByte0                0xff
-#define bMaskByte1                0xff00
-#define bMaskByte2                0xff0000
-#define bMaskByte3                0xff000000
-#define bMaskHWord                0xffff0000
-#define bMaskLWord                0x0000ffff
-#define bMaskDWord                0xffffffff
+	/* Max RF number 92 support */
+	RF90_PATH_MAX
+} RF90_RADIO_PATH_E, *PRF90_RADIO_PATH_E;
 
-//extern u32 rtl8192_CalculateBitShift(u32 dwBitMask);
-extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev, u32 eRFPath);
-extern void rtl8192_setBBreg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask, u32 dwData);
-extern u32 rtl8192_QueryBBReg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask);
-//extern u32 rtl8192_phy_RFSerialRead(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset);
-//extern void rtl8192_phy_RFSerialWrite(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data);
-extern void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask, u32 Data);
-extern u32 rtl8192_phy_QueryRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask);
-extern void rtl8192_phy_configmac(struct net_device* dev);
-extern void rtl8192_phyConfigBB(struct net_device* dev, u8 ConfigType);
-//extern void rtl8192_InitBBRFRegDef(struct net_device* dev);
-extern RT_STATUS rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
-//extern RT_STATUS rtl8192_BB_Config_ParaFile(struct net_device* dev);
-extern RT_STATUS rtl8192_BBConfig(struct net_device* dev);
-extern void rtl8192_phy_getTxPower(struct net_device* dev);
-extern void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel);
+#define bMaskByte0 0xff
+#define bMaskByte1 0xff00
+#define bMaskByte2 0xff0000
+#define bMaskByte3 0xff000000
+#define bMaskHWord 0xffff0000
+#define bMaskLWord 0x0000ffff
+#define bMaskDWord 0xffffffff
+
+/*extern u32 rtl8192_CalculateBitShift(u32 dwBitMask);
+
+extern u32 rtl8192_phy_RFSerialRead(struct net_device *dev,
+			RF90_RADIO_PATH_E eRFPath, u32 Offset);
+
+extern void rtl8192_phy_RFSerialWrite(struct net_device *dev,
+		RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data);
+
+extern void rtl8192_InitBBRFRegDef(struct net_device *dev);
+
+extern RT_STATUS rtl8192_BB_Config_ParaFile(struct net_device *dev); */
+
+extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath);
+
+extern void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr,
+			     u32 dwBitMask, u32 dwData);
+
+extern u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr,
+			     u32 dwBitMask);
+
+extern void rtl8192_phy_SetRFReg(struct net_device *dev,
+		RF90_RADIO_PATH_E eRFPath, u32 RegAddr,
+		u32 BitMask, u32 Data);
+
+extern u32 rtl8192_phy_QueryRFReg(struct net_device *dev,
+		RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask);
+
+extern void rtl8192_phy_configmac(struct net_device *dev);
+
+extern void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType);
+
+extern RT_STATUS rtl8192_phy_checkBBAndRF(struct net_device *dev,
+		HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
+
+extern RT_STATUS rtl8192_BBConfig(struct net_device *dev);
+
+extern void rtl8192_phy_getTxPower(struct net_device *dev);
+
+extern void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
+
 extern RT_STATUS rtl8192_phy_RFConfig(struct net_device* dev);
-extern void rtl8192_phy_updateInitGain(struct net_device* dev);
-extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E	eRFPath);
 
-extern u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel);
-extern void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH	Bandwidth, HT_EXTCHNL_OFFSET Offset);
+extern void rtl8192_phy_updateInitGain(struct net_device* dev);
+
+extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
+					RF90_RADIO_PATH_E eRFPath);
+
+extern u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
+
+extern void rtl8192_SetBWMode(struct net_device *dev,
+		HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
+
 extern void rtl8192_SwChnl_WorkItem(struct net_device *dev);
+
 extern void rtl8192_SetBWModeWorkItem(struct net_device *dev);
+
 extern void InitialGain819xPci(struct net_device *dev, u8 Operation);
 
-#endif
+#endif /* _R819XU_PHY_H */
diff --git a/drivers/staging/rtl8192e/r819xE_phyreg.h b/drivers/staging/rtl8192e/r819xE_phyreg.h
index 37f0fee..d5de279 100644
--- a/drivers/staging/rtl8192e/r819xE_phyreg.h
+++ b/drivers/staging/rtl8192e/r819xE_phyreg.h
@@ -38,6 +38,8 @@
 #define	MCS_TXAGC				0x340	// MCS AGC
 #define	CCK_TXAGC				0x348	// CCK AGC
 
+#define	MacBlkCtrl				0x403					// Mac block on/off control register
+
 //page8
 #define rFPGA0_RFMOD              		0x800  //RF mode & CCK TxSC
 #define rFPGA0_TxInfo             		0x804
@@ -79,55 +81,70 @@
 #define rFPGA0_XB_LSSIReadBack    	0x8a4
 #define rFPGA0_XC_LSSIReadBack    	0x8a8
 #define rFPGA0_XD_LSSIReadBack    	0x8ac
-#define rFPGA0_PSDReport          		0x8b4
+#define rFPGA0_PSDReport		0x8b4
 #define rFPGA0_XAB_RFInterfaceRB  	0x8e0
 #define rFPGA0_XCD_RFInterfaceRB  	0x8e4
 
-//page 9
-#define rFPGA1_RFMOD              		0x900  //RF mode & OFDM TxSC
-#define rFPGA1_TxBlock            		0x904
-#define rFPGA1_DebugSelect        		0x908
-#define rFPGA1_TxInfo             		0x90c
+/* Page 9 - RF mode & OFDM TxSC */
+#define rFPGA1_RFMOD      		0x900
+#define rFPGA1_TxBlock            	0x904
+#define rFPGA1_DebugSelect        	0x908
+#define rFPGA1_TxInfo             	0x90c
 
-//page a
-#define rCCK0_System              		0xa00
-#define rCCK0_AFESetting          		0xa04
-#define rCCK0_CCA                 			0xa08
-#define rCCK0_RxAGC1              		0xa0c  //AGC default value, saturation level
-#define rCCK0_RxAGC2              		0xa10  //AGC & DAGC
-#define rCCK0_RxHP                		0xa14
-#define rCCK0_DSPParameter1       	0xa18  //Timing recovery & Channel estimation threshold
-#define rCCK0_DSPParameter2       	0xa1c  //SQ threshold
-#define rCCK0_TxFilter1           		0xa20
-#define rCCK0_TxFilter2           		0xa24
-#define rCCK0_DebugPort           		0xa28  //debug port and Tx filter3
-#define rCCK0_FalseAlarmReport    	0xa2c  //0xa2d
-#define rCCK0_TRSSIReport         		0xa50
-#define rCCK0_RxReport            		0xa54  //0xa57
-#define rCCK0_FACounterLower      	0xa5c  //0xa5b
-#define rCCK0_FACounterUpper      	0xa58  //0xa5c
+/* Page a */
+#define rCCK0_System              	0xa00
+#define rCCK0_AFESetting          	0xa04
+#define rCCK0_CCA                 	0xa08
+/* AGC default value, saturation level */
+#define rCCK0_RxAGC1              	0xa0c
+/* AGC & DAGC */
+#define rCCK0_RxAGC2              	0xa10
+#define rCCK0_RxHP                	0xa14
+/* Timing recovery & channel estimation threshold */
+#define rCCK0_DSPParameter1       	0xa18
+/* SQ threshold */
+#define rCCK0_DSPParameter2       	0xa1c
+#define rCCK0_TxFilter1           	0xa20
+#define rCCK0_TxFilter2           	0xa24
+/* Debug port and TX filter 3 */
+#define rCCK0_DebugPort           	0xa28
+#define rCCK0_FalseAlarmReport    	0xa2c
+#define rCCK0_TRSSIReport         	0xa50
+#define rCCK0_RxReport            	0xa54
+#define rCCK0_FACounterLower      	0xa5c
+#define rCCK0_FACounterUpper      	0xa58
 
-//page c
-#define rOFDM0_LSTF               		0xc00
+/* Page c */
+#define rOFDM0_LSTF              	0xc00
 #define rOFDM0_TRxPathEnable      	0xc04
-#define rOFDM0_TRMuxPar           		0xc08
-#define rOFDM0_TRSWIsolation      		0xc0c
-#define rOFDM0_XARxAFE            		0xc10  //RxIQ DC offset, Rx digital filter, DC notch filter
-#define rOFDM0_XARxIQImbalance    	0xc14  //RxIQ imblance matrix
-#define rOFDM0_XBRxAFE            		0xc18
+#define rOFDM0_TRMuxPar           	0xc08
+#define rOFDM0_TRSWIsolation      	0xc0c
+/* RxIQ DC offset, Rx digital filter, DC notch filter */
+#define rOFDM0_XARxAFE            	0xc10
+/* RxIQ imblance matrix */
+#define rOFDM0_XARxIQImbalance    	0xc14
+#define rOFDM0_XBRxAFE            	0xc18
 #define rOFDM0_XBRxIQImbalance    	0xc1c
-#define rOFDM0_XCRxAFE            		0xc20
+#define rOFDM0_XCRxAFE           	0xc20
 #define rOFDM0_XCRxIQImbalance    	0xc24
-#define rOFDM0_XDRxAFE            		0xc28
+#define rOFDM0_XDRxAFE            	0xc28
 #define rOFDM0_XDRxIQImbalance    	0xc2c
-#define rOFDM0_RxDetector1        		0xc30  //PD,BW & SBD
-#define rOFDM0_RxDetector2        		0xc34  //SBD & Fame Sync.
-#define rOFDM0_RxDetector3        		0xc38  //Frame Sync.
-#define rOFDM0_RxDetector4        		0xc3c  //PD, SBD, Frame Sync & Short-GI
-#define rOFDM0_RxDSP              		0xc40  //Rx Sync Path
-#define rOFDM0_CFOandDAGC         	0xc44  //CFO & DAGC
-#define rOFDM0_CCADropThreshold   	0xc48 //CCA Drop threshold
-#define rOFDM0_ECCAThreshold      	0xc4c // energy CCA
+/* PD, BW & SBD */
+#define rOFDM0_RxDetector1        	0xc30
+/* SBD */
+#define rOFDM0_RxDetector2		0xc34
+/* Frame Sync */
+#define rOFDM0_RxDetector3         	0xc38
+/* PD, SBD, Frame Sync & Short-GI */
+#define rOFDM0_RxDetector4        	0xc3c
+/* Rx Sync Path */
+#define rOFDM0_RxDSP			0xc40
+/* CFO & DAGC */
+#define rOFDM0_CFOandDAGC         	0xc44
+/* CCA Drop threshold */
+#define rOFDM0_CCADropThreshold   	0xc48
+/* Energy CCA */
+#define rOFDM0_ECCAThreshold      	0xc4c
 #define rOFDM0_XAAGCCore1         	0xc50
 #define rOFDM0_XAAGCCore2         	0xc54
 #define rOFDM0_XBAGCCore1         	0xc58
@@ -139,501 +156,517 @@
 #define rOFDM0_AGCParameter1      	0xc70
 #define rOFDM0_AGCParameter2      	0xc74
 #define rOFDM0_AGCRSSITable       	0xc78
-#define rOFDM0_HTSTFAGC           		0xc7c
+#define rOFDM0_HTSTFAGC           	0xc7c
 #define rOFDM0_XATxIQImbalance   	0xc80
-#define rOFDM0_XATxAFE            		0xc84
+#define rOFDM0_XATxAFE            	0xc84
 #define rOFDM0_XBTxIQImbalance    	0xc88
-#define rOFDM0_XBTxAFE            		0xc8c
+#define rOFDM0_XBTxAFE            	0xc8c
 #define rOFDM0_XCTxIQImbalance    	0xc90
-#define rOFDM0_XCTxAFE            		0xc94
+#define rOFDM0_XCTxAFE            	0xc94
 #define rOFDM0_XDTxIQImbalance    	0xc98
-#define rOFDM0_XDTxAFE            		0xc9c
+#define rOFDM0_XDTxAFE            	0xc9c
 #define rOFDM0_RxHPParameter      	0xce0
 #define rOFDM0_TxPseudoNoiseWgt   	0xce4
-#define rOFDM0_FrameSync          		0xcf0
-#define rOFDM0_DFSReport          		0xcf4
-#define rOFDM0_TxCoeff1           		0xca4
-#define rOFDM0_TxCoeff2           		0xca8
-#define rOFDM0_TxCoeff3           		0xcac
-#define rOFDM0_TxCoeff4           		0xcb0
-#define rOFDM0_TxCoeff5           		0xcb4
-#define rOFDM0_TxCoeff6           		0xcb8
+#define rOFDM0_FrameSync          	0xcf0
+#define rOFDM0_DFSReport          	0xcf4
+#define rOFDM0_TxCoeff1           	0xca4
+#define rOFDM0_TxCoeff2           	0xca8
+#define rOFDM0_TxCoeff3           	0xcac
+#define rOFDM0_TxCoeff4           	0xcb0
+#define rOFDM0_TxCoeff5           	0xcb4
+#define rOFDM0_TxCoeff6           	0xcb8
 
 
-//page d
-#define rOFDM1_LSTF               		0xd00
+/* Page d */
+#define rOFDM1_LSTF               	0xd00
 #define rOFDM1_TRxPathEnable      	0xd04
-#define rOFDM1_CFO                		0xd08
-#define rOFDM1_CSI1               		0xd10
-#define rOFDM1_SBD                		0xd14
-#define rOFDM1_CSI2               		0xd18
-#define rOFDM1_CFOTracking        		0xd2c
+#define rOFDM1_CFO                	0xd08
+#define rOFDM1_CSI1               	0xd10
+#define rOFDM1_SBD                	0xd14
+#define rOFDM1_CSI2               	0xd18
+#define rOFDM1_CFOTracking        	0xd2c
 #define rOFDM1_TRxMesaure1        	0xd34
-#define rOFDM1_IntfDet            		0xd3c
-#define rOFDM1_PseudoNoiseStateAB 0xd50
-#define rOFDM1_PseudoNoiseStateCD 0xd54
-#define rOFDM1_RxPseudoNoiseWgt   0xd58
-#define rOFDM_PHYCounter1         		0xda0  //cca, parity fail
-#define rOFDM_PHYCounter2         		0xda4  //rate illegal, crc8 fail
-#define rOFDM_PHYCounter3         		0xda8  //MCS not support
-#define rOFDM_ShortCFOAB          		0xdac
-#define rOFDM_ShortCFOCD          		0xdb0
-#define rOFDM_LongCFOAB           		0xdb4
-#define rOFDM_LongCFOCD           		0xdb8
-#define rOFDM_TailCFOAB           		0xdbc
-#define rOFDM_TailCFOCD           		0xdc0
+#define rOFDM1_IntfDet            	0xd3c
+#define rOFDM1_PseudoNoiseStateAB 	0xd50
+#define rOFDM1_PseudoNoiseStateCD 	0xd54
+#define rOFDM1_RxPseudoNoiseWgt   	0xd58
+/* cca, parity fail */
+#define rOFDM_PHYCounter1         	0xda0
+/* rate illegal, crc8 fail */
+#define rOFDM_PHYCounter2   		0xda4
+/* MCS not supported */
+#define rOFDM_PHYCounter3         	0xda8
+#define rOFDM_ShortCFOAB          	0xdac
+#define rOFDM_ShortCFOCD          	0xdb0
+#define rOFDM_LongCFOAB           	0xdb4
+#define rOFDM_LongCFOCD           	0xdb8
+#define rOFDM_TailCFOAB           	0xdbc
+#define rOFDM_TailCFOCD           	0xdc0
 #define rOFDM_PWMeasure1          	0xdc4
 #define rOFDM_PWMeasure2          	0xdc8
-#define rOFDM_BWReport            		0xdcc
-#define rOFDM_AGCReport           		0xdd0
-#define rOFDM_RxSNR               		0xdd4
-#define rOFDM_RxEVMCSI            		0xdd8
-#define rOFDM_SIGReport           		0xddc
+#define rOFDM_BWReport            	0xdcc
+#define rOFDM_AGCReport           	0xdd0
+#define rOFDM_RxSNR               	0xdd4
+#define rOFDM_RxEVMCSI            	0xdd8
+#define rOFDM_SIGReport           	0xddc
 
-//page e
-#define rTxAGC_Rate18_06			0xe00
-#define rTxAGC_Rate54_24			0xe04
-#define rTxAGC_CCK_Mcs32			0xe08
-#define rTxAGC_Mcs03_Mcs00			0xe10
-#define rTxAGC_Mcs07_Mcs04			0xe14
-#define rTxAGC_Mcs11_Mcs08			0xe18
-#define rTxAGC_Mcs15_Mcs12			0xe1c
+/* Page e */
+#define rTxAGC_Rate18_06		0xe00
+#define rTxAGC_Rate54_24		0xe04
+#define rTxAGC_CCK_Mcs32		0xe08
+#define rTxAGC_Mcs03_Mcs00		0xe10
+#define rTxAGC_Mcs07_Mcs04		0xe14
+#define rTxAGC_Mcs11_Mcs08		0xe18
+#define rTxAGC_Mcs15_Mcs12		0xe1c
 
 
-//RF
-//Zebra1
+/* RF Zebra 1 */
 #define rZebra1_HSSIEnable            	0x0
 #define rZebra1_TRxEnable1            	0x1
 #define rZebra1_TRxEnable2           	0x2
-#define rZebra1_AGC                   		0x4
+#define rZebra1_AGC                   	0x4
 #define rZebra1_ChargePump            	0x5
-#define rZebra1_Channel               		0x7
-#define rZebra1_TxGain               	 	0x8
-#define rZebra1_TxLPF                 		0x9
-#define rZebra1_RxLPF                 		0xb
+#define rZebra1_Channel               	0x7
+#define rZebra1_TxGain               	0x8
+#define rZebra1_TxLPF                 	0x9
+#define rZebra1_RxLPF                 	0xb
 #define rZebra1_RxHPFCorner           	0xc
 
-//Zebra4
-#define rGlobalCtrl                   		0
-#define rRTL8256_TxLPF                		19
-#define rRTL8256_RxLPF                		11
+/* Zebra 4 */
+#define rGlobalCtrl                   	0
+#define rRTL8256_TxLPF                	19
+#define rRTL8256_RxLPF                	11
 
-//RTL8258
-#define rRTL8258_TxLPF                		0x11
-#define rRTL8258_RxLPF                		0x13
+/* RTL8258 */
+#define rRTL8258_TxLPF                	0x11
+#define rRTL8258_RxLPF                  0x13
 #define rRTL8258_RSSILPF              	0xa
 
-//Bit Mask
-//page-1
-#define bBBResetB                 			0x100
-#define bGlobalResetB             		0x200
-#define bOFDMTxStart              		0x4
-#define bCCKTxStart               			0x8
-#define bCRC32Debug               		0x100
-#define bPMACLoopback             		0x10
-#define bTxLSIG                   			0xffffff
-#define bOFDMTxRate               		0xf
-#define bOFDMTxReserved           		0x10
-#define bOFDMTxLength             		0x1ffe0
-#define bOFDMTxParity             		0x20000
-#define bTxHTSIG1                 			0xffffff
-#define bTxHTMCSRate              		0x7f
-#define bTxHTBW                   			0x80
-#define bTxHTLength               		0xffff00
-#define bTxHTSIG2                 			0xffffff
-#define bTxHTSmoothing            		0x1
-#define bTxHTSounding             		0x2
-#define bTxHTReserved             		0x4
-#define bTxHTAggreation           		0x8
-#define bTxHTSTBC                 			0x30
-#define bTxHTAdvanceCoding        		0x40
-#define bTxHTShortGI              		0x80
-#define bTxHTNumberHT_LTF         		0x300
-#define bTxHTCRC8                 			0x3fc00
-#define bCounterReset             		0x10000
-#define bNumOfOFDMTx              		0xffff
-#define bNumOfCCKTx               		0xffff0000
-#define bTxIdleInterval           			0xffff
-#define bOFDMService              		0xffff0000
-#define bTxMACHeader              		0xffffffff
-#define bTxDataInit               			0xff
-#define bTxHTMode                 		0x100
-#define bTxDataType               		0x30000
-#define bTxRandomSeed             		0xffffffff
-#define bCCKTxPreamble           		0x1
-#define bCCKTxSFD                 			0xffff0000
-#define bCCKTxSIG                 			0xff
-#define bCCKTxService             		0xff00
-#define bCCKLengthExt             		0x8000
-#define bCCKTxLength              		0xffff0000
-#define bCCKTxCRC16               		0xffff
-#define bCCKTxStatus              		0x1
-#define bOFDMTxStatus             		0x2
+/* Bit Mask */
+/* Page 1 */
+#define bBBResetB                 	0x100
+#define bGlobalResetB             	0x200
+#define bOFDMTxStart              	0x4
+#define bCCKTxStart               	0x8
+#define bCRC32Debug               	0x100
+#define bPMACLoopback             	0x10
+#define bTxLSIG                   	0xffffff
+#define bOFDMTxRate               	0xf
+#define bOFDMTxReserved           	0x10
+#define bOFDMTxLength             	0x1ffe0
+#define bOFDMTxParity             	0x20000
+#define bTxHTSIG1                 	0xffffff
+#define bTxHTMCSRate              	0x7f
+#define bTxHTBW                   	0x80
+#define bTxHTLength               	0xffff00
+#define bTxHTSIG2                 	0xffffff
+#define bTxHTSmoothing            	0x1
+#define bTxHTSounding             	0x2
+#define bTxHTReserved             	0x4
+#define bTxHTAggreation           	0x8
+#define bTxHTSTBC                 	0x30
+#define bTxHTAdvanceCoding        	0x40
+#define bTxHTShortGI              	0x80
+#define bTxHTNumberHT_LTF         	0x300
+#define bTxHTCRC8                 	0x3fc00
+#define bCounterReset             	0x10000
+#define bNumOfOFDMTx              	0xffff
+#define bNumOfCCKTx               	0xffff0000
+#define bTxIdleInterval           	0xffff
+#define bOFDMService              	0xffff0000
+#define bTxMACHeader              	0xffffffff
+#define bTxDataInit               	0xff
+#define bTxHTMode                 	0x100
+#define bTxDataType               	0x30000
+#define bTxRandomSeed             	0xffffffff
+#define bCCKTxPreamble           	0x1
+#define bCCKTxSFD                 	0xffff0000
+#define bCCKTxSIG                 	0xff
+#define bCCKTxService             	0xff00
+#define bCCKLengthExt             	0x8000
+#define bCCKTxLength              	0xffff0000
+#define bCCKTxCRC16               	0xffff
+#define bCCKTxStatus              	0x1
+#define bOFDMTxStatus             	0x2
 
-//page-8
-#define bRFMOD                    			0x1
-#define bJapanMode                		0x2
-#define bCCKTxSC                  			0x30
-#define bCCKEn                    			0x1000000
-#define bOFDMEn                   			0x2000000
-#define bOFDMRxADCPhase           		0x10000
-#define bOFDMTxDACPhase           		0x40000
-#define bXATxAGC                  			0x3f
-#define bXBTxAGC                  			0xf00
-#define bXCTxAGC                  			0xf000
-#define bXDTxAGC                  			0xf0000
-#define bPAStart                  			0xf0000000
-#define bTRStart                  			0x00f00000
-#define bRFStart                  			0x0000f000
-#define bBBStart                  			0x000000f0
-#define bBBCCKStart               		0x0000000f
-#define bPAEnd                    			0xf          //Reg0x814
-#define bTREnd                    			0x0f000000
-#define bRFEnd                    			0x000f0000
-#define bCCAMask                  			0x000000f0   //T2R
-#define bR2RCCAMask               		0x00000f00
-#define bHSSI_R2TDelay            		0xf8000000
-#define bHSSI_T2RDelay            		0xf80000
-#define bContTxHSSI               		0x400     //channel gain at continue Tx
-#define bIGFromCCK                		0x200
-#define bAGCAddress               		0x3f
-#define bRxHPTx                   			0x7000
-#define bRxHPT2R                  			0x38000
-#define bRxHPCCKIni               		0xc0000
-#define bAGCTxCode                		0xc00000
-#define bAGCRxCode                		0x300000
-#define b3WireDataLength          		0x800
-#define b3WireAddressLength       		0x400
-#define b3WireRFPowerDown         		0x1
-//#define bHWSISelect               		0x8
-#define b5GPAPEPolarity           		0x40000000
-#define b2GPAPEPolarity           		0x80000000
-#define bRFSW_TxDefaultAnt        		0x3
-#define bRFSW_TxOptionAnt         		0x30
-#define bRFSW_RxDefaultAnt        		0x300
-#define bRFSW_RxOptionAnt         		0x3000
-#define bRFSI_3WireData           		0x1
-#define bRFSI_3WireClock          		0x2
-#define bRFSI_3WireLoad           		0x4
-#define bRFSI_3WireRW             		0x8
-#define bRFSI_3Wire               			0xf  //3-wire total control
-#define bRFSI_RFENV               		0x10
-#define bRFSI_TRSW                		0x20
-#define bRFSI_TRSWB               		0x40
-#define bRFSI_ANTSW               		0x100
-#define bRFSI_ANTSWB              		0x200
-#define bRFSI_PAPE                			0x400
-#define bRFSI_PAPE5G              		0x800
-#define bBandSelect               			0x1
-#define bHTSIG2_GI                			0x80
-#define bHTSIG2_Smoothing         		0x01
-#define bHTSIG2_Sounding          		0x02
-#define bHTSIG2_Aggreaton         		0x08
-#define bHTSIG2_STBC              		0x30
-#define bHTSIG2_AdvCoding         		0x40
+/* Page 8 */
+#define bRFMOD                    	0x1
+#define bJapanMode                	0x2
+#define bCCKTxSC                  	0x30
+#define bCCKEn                    	0x1000000
+#define bOFDMEn                   	0x2000000
+#define bOFDMRxADCPhase           	0x10000
+#define bOFDMTxDACPhase           	0x40000
+#define bXATxAGC                  	0x3f
+#define bXBTxAGC                  	0xf00
+#define bXCTxAGC                  	0xf000
+#define bXDTxAGC                  	0xf0000
+#define bPAStart                  	0xf0000000
+#define bTRStart                  	0x00f00000
+#define bRFStart                  	0x0000f000
+#define bBBStart                  	0x000000f0
+#define bBBCCKStart               	0x0000000f
+/* Reg)x814 */
+#define bPAEnd                    	0xf
+#define bTREnd                    	0x0f000000
+#define bRFEnd                    	0x000f0000
+/* T2R */
+#define bCCAMask                  	0x000000f0
+#define bR2RCCAMask               	0x00000f00
+#define bHSSI_R2TDelay            	0xf8000000
+#define bHSSI_T2RDelay            	0xf80000
+/* Channel gain at continue TX. */
+#define bContTxHSSI               	0x400
+#define bIGFromCCK                	0x200
+#define bAGCAddress               	0x3f
+#define bRxHPTx                   	0x7000
+#define bRxHPT2R                  	0x38000
+#define bRxHPCCKIni               	0xc0000
+#define bAGCTxCode                	0xc00000
+#define bAGCRxCode                	0x300000
+#define b3WireDataLength          	0x800
+#define b3WireAddressLength       	0x400
+#define b3WireRFPowerDown         	0x1
+/*#define bHWSISelect               	0x8 */
+#define b5GPAPEPolarity           	0x40000000
+#define b2GPAPEPolarity           	0x80000000
+#define bRFSW_TxDefaultAnt        	0x3
+#define bRFSW_TxOptionAnt         	0x30
+#define bRFSW_RxDefaultAnt        	0x300
+#define bRFSW_RxOptionAnt         	0x3000
+#define bRFSI_3WireData           	0x1
+#define bRFSI_3WireClock          	0x2
+#define bRFSI_3WireLoad           	0x4
+#define bRFSI_3WireRW             	0x8
+/* 3-wire total control */
+#define bRFSI_3Wire               	0xf
+#define bRFSI_RFENV               	0x10
+#define bRFSI_TRSW                	0x20
+#define bRFSI_TRSWB               	0x40
+#define bRFSI_ANTSW               	0x100
+#define bRFSI_ANTSWB              	0x200
+#define bRFSI_PAPE                	0x400
+#define bRFSI_PAPE5G              	0x800
+#define bBandSelect               	0x1
+#define bHTSIG2_GI                	0x80
+#define bHTSIG2_Smoothing         	0x01
+#define bHTSIG2_Sounding          	0x02
+#define bHTSIG2_Aggreaton         	0x08
+#define bHTSIG2_STBC              	0x30
+#define bHTSIG2_AdvCoding         	0x40
 #define bHTSIG2_NumOfHTLTF        	0x300
-#define bHTSIG2_CRC8              		0x3fc
-#define bHTSIG1_MCS               		0x7f
-#define bHTSIG1_BandWidth         		0x80
-#define bHTSIG1_HTLength          		0xffff
-#define bLSIG_Rate                			0xf
-#define bLSIG_Reserved            		0x10
-#define bLSIG_Length              		0x1fffe
-#define bLSIG_Parity              			0x20
-#define bCCKRxPhase               		0x4
-#define bLSSIReadAddress          		0x3f000000   //LSSI "Read" Address
-#define bLSSIReadEdge             		0x80000000   //LSSI "Read" edge signal
-#define bLSSIReadBackData         		0xfff
-#define bLSSIReadOKFlag           		0x1000
-#define bCCKSampleRate            		0x8       //0: 44MHz, 1:88MHz
+#define bHTSIG2_CRC8              	0x3fc
+#define bHTSIG1_MCS               	0x7f
+#define bHTSIG1_BandWidth         	0x80
+#define bHTSIG1_HTLength          	0xffff
+#define bLSIG_Rate                	0xf
+#define bLSIG_Reserved            	0x10
+#define bLSIG_Length              	0x1fffe
+#define bLSIG_Parity              	0x20
+#define bCCKRxPhase               	0x4
+/* LSSI "read" address */
+#define bLSSIReadAddress          	0x3f000000
+/* LSSI "read" edge signal */
+#define bLSSIReadEdge             	0x80000000
+#define bLSSIReadBackData         	0xfff
+#define bLSSIReadOKFlag           	0x1000
+/* 0: 44 MHz, 1: 88MHz */
+#define bCCKSampleRate            	0x8
 
-#define bRegulator0Standby        		0x1
-#define bRegulatorPLLStandby      		0x2
-#define bRegulator1Standby        		0x4
-#define bPLLPowerUp               		0x8
-#define bDPLLPowerUp              		0x10
-#define bDA10PowerUp              		0x20
-#define bAD7PowerUp               		0x200
-#define bDA6PowerUp               		0x2000
-#define bXtalPowerUp              		0x4000
-#define b40MDClkPowerUP           		0x8000
-#define bDA6DebugMode             		0x20000
-#define bDA6Swing                 			0x380000
-#define bADClkPhase               		0x4000000
-#define b80MClkDelay              		0x18000000
-#define bAFEWatchDogEnable        		0x20000000
-#define bXtalCap                			0x0f000000
-#define bXtalCap01                			0xc0000000
-#define bXtalCap23                			0x3
-#define bXtalCap92x					0x0f000000
-#define bIntDifClkEnable          		0x400
-#define bExtSigClkEnable         	 	0x800
+#define bRegulator0Standby        	0x1
+#define bRegulatorPLLStandby      	0x2
+#define bRegulator1Standby        	0x4
+#define bPLLPowerUp               	0x8
+#define bDPLLPowerUp              	0x10
+#define bDA10PowerUp              	0x20
+#define bAD7PowerUp               	0x200
+#define bDA6PowerUp               	0x2000
+#define bXtalPowerUp              	0x4000
+#define b40MDClkPowerUP           	0x8000
+#define bDA6DebugMode             	0x20000
+#define bDA6Swing                 	0x380000
+#define bADClkPhase               	0x4000000
+#define b80MClkDelay              	0x18000000
+#define bAFEWatchDogEnable        	0x20000000
+#define bXtalCap                	0x0f000000
+#define bXtalCap01                	0xc0000000
+#define bXtalCap23                	0x3
+#define bXtalCap92x			0x0f000000
+#define bIntDifClkEnable          	0x400
+#define bExtSigClkEnable         	0x800
 #define bBandgapMbiasPowerUp      	0x10000
-#define bAD11SHGain               		0xc0000
-#define bAD11InputRange           		0x700000
-#define bAD11OPCurrent            		0x3800000
-#define bIPathLoopback            		0x4000000
-#define bQPathLoopback            		0x8000000
-#define bAFELoopback              		0x10000000
-#define bDA10Swing                		0x7e0
-#define bDA10Reverse              		0x800
-#define bDAClkSource              		0x1000
-#define bAD7InputRange            		0x6000
-#define bAD7Gain                  			0x38000
-#define bAD7OutputCMMode          		0x40000
-#define bAD7InputCMMode           		0x380000
-#define bAD7Current               			0xc00000
-#define bRegulatorAdjust          		0x7000000
-#define bAD11PowerUpAtTx          		0x1
-#define bDA10PSAtTx               		0x10
-#define bAD11PowerUpAtRx          		0x100
-#define bDA10PSAtRx               		0x1000
+#define bAD11SHGain               	0xc0000
+#define bAD11InputRange           	0x700000
+#define bAD11OPCurrent            	0x3800000
+#define bIPathLoopback            	0x4000000
+#define bQPathLoopback            	0x8000000
+#define bAFELoopback              	0x10000000
+#define bDA10Swing                	0x7e0
+#define bDA10Reverse              	0x800
+#define bDAClkSource              	0x1000
+#define bAD7InputRange            	0x6000
+#define bAD7Gain                  	0x38000
+#define bAD7OutputCMMode          	0x40000
+#define bAD7InputCMMode           	0x380000
+#define bAD7Current               	0xc00000
+#define bRegulatorAdjust          	0x7000000
+#define bAD11PowerUpAtTx          	0x1
+#define bDA10PSAtTx               	0x10
+#define bAD11PowerUpAtRx          	0x100
+#define bDA10PSAtRx               	0x1000
 
-#define bCCKRxAGCFormat           		0x200
+#define bCCKRxAGCFormat           	0x200
 
-#define bPSDFFTSamplepPoint       		0xc000
-#define bPSDAverageNum            		0x3000
-#define bIQPathControl            		0xc00
-#define bPSDFreq                  			0x3ff
-#define bPSDAntennaPath           		0x30
-#define bPSDIQSwitch              		0x40
-#define bPSDRxTrigger             		0x400000
-#define bPSDTxTrigger             		0x80000000
-#define bPSDSineToneScale        		0x7f000000
-#define bPSDReport                			0xffff
+#define bPSDFFTSamplepPoint       	0xc000
+#define bPSDAverageNum            	0x3000
+#define bIQPathControl            	0xc00
+#define bPSDFreq                  	0x3ff
+#define bPSDAntennaPath           	0x30
+#define bPSDIQSwitch              	0x40
+#define bPSDRxTrigger             	0x400000
+#define bPSDTxTrigger             	0x80000000
+#define bPSDSineToneScale        	0x7f000000
+#define bPSDReport                	0xffff
 
-//page-9
-#define bOFDMTxSC                 		0x30000000
-#define bCCKTxOn                  			0x1
-#define bOFDMTxOn                 		0x2
-#define bDebugPage                		0xfff  //reset debug page and also HWord, LWord
-#define bDebugItem                		0xff   //reset debug page and LWord
-#define bAntL              	       		0x10
-#define bAntNonHT           	      			0x100
-#define bAntHT1               			0x1000
-#define bAntHT2                   			0x10000
-#define bAntHT1S1                 			0x100000
-#define bAntNonHTS1               		0x1000000
+/* Page 8 */
+#define bOFDMTxSC                 	0x30000000
+#define bCCKTxOn                  	0x1
+#define bOFDMTxOn                 	0x2
+/* Reset debug page and also HWord, LWord */
+#define bDebugPage                	0xfff
+/* Reset debug page and LWord */
+#define bDebugItem                	0xff
+#define bAntL              	       	0x10
+#define bAntNonHT           	      	0x100
+#define bAntHT1               		0x1000
+#define bAntHT2                   	0x10000
+#define bAntHT1S1                 	0x100000
+#define bAntNonHTS1               	0x1000000
 
-//page-a
-#define bCCKBBMode                		0x3
-#define bCCKTxPowerSaving         		0x80
-#define bCCKRxPowerSaving         		0x40
-#define bCCKSideBand              		0x10
-#define bCCKScramble              		0x8
-#define bCCKAntDiversity    		      	0x8000
+/* Page a */
+#define bCCKBBMode                	0x3
+#define bCCKTxPowerSaving         	0x80
+#define bCCKRxPowerSaving         	0x40
+#define bCCKSideBand              	0x10
+#define bCCKScramble              	0x8
+#define bCCKAntDiversity    		0x8000
 #define bCCKCarrierRecovery   	    	0x4000
-#define bCCKTxRate           		     	0x3000
-#define bCCKDCCancel             	 	0x0800
-#define bCCKISICancel             		0x0400
-#define bCCKMatchFilter           		0x0200
-#define bCCKEqualizer             		0x0100
-#define bCCKPreambleDetect       	 	0x800000
-#define bCCKFastFalseCCA          		0x400000
-#define bCCKChEstStart            		0x300000
-#define bCCKCCACount              		0x080000
-#define bCCKcs_lim                			0x070000
-#define bCCKBistMode              		0x80000000
-#define bCCKCCAMask             	  	0x40000000
+#define bCCKTxRate           		0x3000
+#define bCCKDCCancel             	0x0800
+#define bCCKISICancel             	0x0400
+#define bCCKMatchFilter           	0x0200
+#define bCCKEqualizer             	0x0100
+#define bCCKPreambleDetect       	0x800000
+#define bCCKFastFalseCCA          	0x400000
+#define bCCKChEstStart            	0x300000
+#define bCCKCCACount              	0x080000
+#define bCCKcs_lim                	0x070000
+#define bCCKBistMode              	0x80000000
+#define bCCKCCAMask             	0x40000000
 #define bCCKTxDACPhase         	   	0x4
-#define bCCKRxADCPhase         	   	0x20000000   //r_rx_clk
+/* r_rx_clk */
+#define bCCKRxADCPhase         	 	0x20000000
 #define bCCKr_cp_mode0         	   	0x0100
-#define bCCKTxDCOffset           	 	0xf0
-#define bCCKRxDCOffset           	 	0xf
-#define bCCKCCAMode              	 	0xc000
-#define bCCKFalseCS_lim           		0x3f00
-#define bCCKCS_ratio              		0xc00000
-#define bCCKCorgBit_sel           		0x300000
-#define bCCKPD_lim                			0x0f0000
-#define bCCKNewCCA                		0x80000000
-#define bCCKRxHPofIG              		0x8000
-#define bCCKRxIG                  			0x7f00
-#define bCCKLNAPolarity           		0x800000
-#define bCCKRx1stGain             		0x7f0000
-#define bCCKRFExtend              		0x20000000 //CCK Rx Iinital gain polarity
-#define bCCKRxAGCSatLevel        	 	0x1f000000
-#define bCCKRxAGCSatCount       	  	0xe0
-#define bCCKRxRFSettle            		0x1f       //AGCsamp_dly
-#define bCCKFixedRxAGC           	 	0x8000
-//#define bCCKRxAGCFormat         	 	0x4000   //remove to HSSI register 0x824
-#define bCCKAntennaPolarity      	 	0x2000
-#define bCCKTxFilterType          		0x0c00
+#define bCCKTxDCOffset           	0xf0
+#define bCCKRxDCOffset         		0xf
+#define bCCKCCAMode              	0xc000
+#define bCCKFalseCS_lim           	0x3f00
+#define bCCKCS_ratio              	0xc00000
+#define bCCKCorgBit_sel           	0x300000
+#define bCCKPD_lim                	0x0f0000
+#define bCCKNewCCA                	0x80000000
+#define bCCKRxHPofIG              	0x8000
+#define bCCKRxIG                  	0x7f00
+#define bCCKLNAPolarity           	0x800000
+#define bCCKRx1stGain             	0x7f0000
+/* CCK Rx Initial gain polarity */
+#define bCCKRFExtend              	0x20000000
+#define bCCKRxAGCSatLevel        	0x1f000000
+#define bCCKRxAGCSatCount       	0xe0
+/* AGCSAmp_dly */
+#define bCCKRxRFSettle            	0x1f
+#define bCCKFixedRxAGC           	0x8000
+/*#define bCCKRxAGCFormat         	0x4000  remove to HSSI register 0x824 */
+#define bCCKAntennaPolarity      	0x2000
+#define bCCKTxFilterType          	0x0c00
 #define bCCKRxAGCReportType   	   	0x0300
-#define bCCKRxDAGCEn              		0x80000000
-#define bCCKRxDAGCPeriod        	  	0x20000000
+#define bCCKRxDAGCEn              	0x80000000
+#define bCCKRxDAGCPeriod        	0x20000000
 #define bCCKRxDAGCSatLevel     	   	0x1f000000
-#define bCCKTimingRecovery       	 	0x800000
-#define bCCKTxC0                  			0x3f0000
-#define bCCKTxC1                  			0x3f000000
-#define bCCKTxC2                  			0x3f
-#define bCCKTxC3                  			0x3f00
-#define bCCKTxC4                  			0x3f0000
-#define bCCKTxC5                  			0x3f000000
-#define bCCKTxC6                  			0x3f
-#define bCCKTxC7                  			0x3f00
-#define bCCKDebugPort             		0xff0000
-#define bCCKDACDebug              		0x0f000000
-#define bCCKFalseAlarmEnable      		0x8000
-#define bCCKFalseAlarmRead        		0x4000
-#define bCCKTRSSI                 			0x7f
-#define bCCKRxAGCReport           		0xfe
-#define bCCKRxReport_AntSel       		0x80000000
-#define bCCKRxReport_MFOff        		0x40000000
+#define bCCKTimingRecovery       	0x800000
+#define bCCKTxC0                  	0x3f0000
+#define bCCKTxC1                  	0x3f000000
+#define bCCKTxC2                  	0x3f
+#define bCCKTxC3                  	0x3f00
+#define bCCKTxC4                  	0x3f0000
+#define bCCKTxC5                  	0x3f000000
+#define bCCKTxC6                  	0x3f
+#define bCCKTxC7                  	0x3f00
+#define bCCKDebugPort             	0xff0000
+#define bCCKDACDebug              	0x0f000000
+#define bCCKFalseAlarmEnable      	0x8000
+#define bCCKFalseAlarmRead        	0x4000
+#define bCCKTRSSI                 	0x7f
+#define bCCKRxAGCReport           	0xfe
+#define bCCKRxReport_AntSel       	0x80000000
+#define bCCKRxReport_MFOff        	0x40000000
 #define bCCKRxRxReport_SQLoss     	0x20000000
-#define bCCKRxReport_Pktloss      		0x10000000
+#define bCCKRxReport_Pktloss      	0x10000000
 #define bCCKRxReport_Lockedbit    	0x08000000
 #define bCCKRxReport_RateError    	0x04000000
-#define bCCKRxReport_RxRate       		0x03000000
+#define bCCKRxReport_RxRate       	0x03000000
 #define bCCKRxFACounterLower      	0xff
 #define bCCKRxFACounterUpper      	0xff000000
-#define bCCKRxHPAGCStart          		0xe000
-#define bCCKRxHPAGCFinal          		0x1c00
+#define bCCKRxHPAGCStart          	0xe000
+#define bCCKRxHPAGCFinal          	0x1c00
 
 #define bCCKRxFalseAlarmEnable    	0x8000
-#define bCCKFACounterFreeze       		0x4000
+#define bCCKFACounterFreeze       	0x4000
 
-#define bCCKTxPathSel             		0x10000000
-#define bCCKDefaultRxPath         		0xc000000
-#define bCCKOptionRxPath          		0x3000000
+#define bCCKTxPathSel             	0x10000000
+#define bCCKDefaultRxPath         	0xc000000
+#define bCCKOptionRxPath          	0x3000000
 
-//page c
-#define bNumOfSTF                			0x3
-#define bShift_L                 			0xc0
-#define bGI_TH                   			0xc
-#define bRxPathA                 			0x1
-#define bRxPathB                 			0x2
-#define bRxPathC                 			0x4
-#define bRxPathD                 			0x8
-#define bTxPathA                 			0x1
-#define bTxPathB                 			0x2
-#define bTxPathC                 			0x4
-#define bTxPathD                 			0x8
-#define bTRSSIFreq               			0x200
-#define bADCBackoff              			0x3000
-#define bDFIRBackoff             			0xc000
-#define bTRSSILatchPhase         		0x10000
-#define bRxIDCOffset             			0xff
-#define bRxQDCOffset             			0xff00
-#define bRxDFIRMode              		0x1800000
-#define bRxDCNFType              		0xe000000
-#define bRXIQImb_A               			0x3ff
-#define bRXIQImb_B               			0xfc00
-#define bRXIQImb_C               			0x3f0000
-#define bRXIQImb_D               			0xffc00000
-#define bDC_dc_Notch             		0x60000
-#define bRxNBINotch              			0x1f000000
-#define bPD_TH                   			0xf
-#define bPD_TH_Opt2              		0xc000
-#define bPWED_TH                 			0x700
-#define bIfMF_Win_L              			0x800
-#define bPD_Option               			0x1000
-#define bMF_Win_L                			0xe000
-#define bBW_Search_L             		0x30000
-#define bwin_enh_L               			0xc0000
-#define bBW_TH                   			0x700000
-#define bED_TH2                  			0x3800000
-#define bBW_option               			0x4000000
-#define bRatio_TH                			0x18000000
-#define bWindow_L                			0xe0000000
-#define bSBD_Option              			0x1
-#define bFrame_TH                			0x1c
-#define bFS_Option               			0x60
-#define bDC_Slope_check          		0x80
-#define bFGuard_Counter_DC_L     		0xe00
-#define bFrame_Weight_Short      		0x7000
-#define bSub_Tune                			0xe00000
-#define bFrame_DC_Length         		0xe000000
-#define bSBD_start_offset        		0x30000000
-#define bFrame_TH_2              		0x7
-#define bFrame_GI2_TH            		0x38
-#define bGI2_Sync_en             		0x40
-#define bSarch_Short_Early       		0x300
-#define bSarch_Short_Late        		0xc00
-#define bSarch_GI2_Late          		0x70000
-#define bCFOAntSum               		0x1
-#define bCFOAcc                  			0x2
-#define bCFOStartOffset          		0xc
-#define bCFOLookBack             		0x70
-#define bCFOSumWeight            		0x80
-#define bDAGCEnable              			0x10000
-#define bTXIQImb_A               			0x3ff
-#define bTXIQImb_B               			0xfc00
-#define bTXIQImb_C               			0x3f0000
-#define bTXIQImb_D               			0xffc00000
-#define bTxIDCOffset             			0xff
-#define bTxQDCOffset             			0xff00
-#define bTxDFIRMode              		0x10000
-#define bTxPesudoNoiseOn         		0x4000000
-#define bTxPesudoNoise_A         		0xff
-#define bTxPesudoNoise_B         		0xff00
-#define bTxPesudoNoise_C         		0xff0000
-#define bTxPesudoNoise_D         		0xff000000
-#define bCCADropOption           		0x20000
-#define bCCADropThres            		0xfff00000
-#define bEDCCA_H                 			0xf
-#define bEDCCA_L                 			0xf0
-#define bLambda_ED               0x300
-#define bRxInitialGain           0x7f
-#define bRxAntDivEn              0x80
-#define bRxAGCAddressForLNA      0x7f00
-#define bRxHighPowerFlow         0x8000
-#define bRxAGCFreezeThres        0xc0000
-#define bRxFreezeStep_AGC1       0x300000
-#define bRxFreezeStep_AGC2       0xc00000
-#define bRxFreezeStep_AGC3       0x3000000
-#define bRxFreezeStep_AGC0       0xc000000
-#define bRxRssi_Cmp_En           0x10000000
-#define bRxQuickAGCEn            0x20000000
-#define bRxAGCFreezeThresMode    0x40000000
-#define bRxOverFlowCheckType     0x80000000
-#define bRxAGCShift              0x7f
-#define bTRSW_Tri_Only           0x80
-#define bPowerThres              0x300
-#define bRxAGCEn                 0x1
-#define bRxAGCTogetherEn         0x2
-#define bRxAGCMin                0x4
-#define bRxHP_Ini                0x7
-#define bRxHP_TRLNA              0x70
-#define bRxHP_RSSI               0x700
-#define bRxHP_BBP1               0x7000
-#define bRxHP_BBP2               0x70000
-#define bRxHP_BBP3               0x700000
-#define bRSSI_H                  0x7f0000     //the threshold for high power
-#define bRSSI_Gen                0x7f000000   //the threshold for ant diversity
-#define bRxSettle_TRSW           0x7
-#define bRxSettle_LNA            0x38
-#define bRxSettle_RSSI           0x1c0
-#define bRxSettle_BBP            0xe00
-#define bRxSettle_RxHP           0x7000
-#define bRxSettle_AntSW_RSSI     0x38000
-#define bRxSettle_AntSW          0xc0000
-#define bRxProcessTime_DAGC      0x300000
-#define bRxSettle_HSSI           0x400000
-#define bRxProcessTime_BBPPW     0x800000
-#define bRxAntennaPowerShift     0x3000000
-#define bRSSITableSelect         0xc000000
-#define bRxHP_Final              0x7000000
-#define bRxHTSettle_BBP          0x7
-#define bRxHTSettle_HSSI         0x8
-#define bRxHTSettle_RxHP         0x70
-#define bRxHTSettle_BBPPW        0x80
-#define bRxHTSettle_Idle         0x300
-#define bRxHTSettle_Reserved     0x1c00
-#define bRxHTRxHPEn              0x8000
-#define bRxHTAGCFreezeThres      0x30000
-#define bRxHTAGCTogetherEn       0x40000
-#define bRxHTAGCMin              0x80000
-#define bRxHTAGCEn               0x100000
-#define bRxHTDAGCEn              0x200000
-#define bRxHTRxHP_BBP            0x1c00000
-#define bRxHTRxHP_Final          0xe0000000
-#define bRxPWRatioTH             0x3
-#define bRxPWRatioEn             0x4
-#define bRxMFHold                0x3800
-#define bRxPD_Delay_TH1          0x38
-#define bRxPD_Delay_TH2          0x1c0
-#define bRxPD_DC_COUNT_MAX       0x600
-//#define bRxMF_Hold               0x3800
+/* Page c */
+#define bNumOfSTF                	0x3
+#define bShift_L                 	0xc0
+#define bGI_TH                   	0xc
+#define bRxPathA                 	0x1
+#define bRxPathB                 	0x2
+#define bRxPathC                 	0x4
+#define bRxPathD                 	0x8
+#define bTxPathA                 	0x1
+#define bTxPathB                 	0x2
+#define bTxPathC                 	0x4
+#define bTxPathD                 	0x8
+#define bTRSSIFreq               	0x200
+#define bADCBackoff              	0x3000
+#define bDFIRBackoff             	0xc000
+#define bTRSSILatchPhase         	0x10000
+#define bRxIDCOffset             	0xff
+#define bRxQDCOffset             	0xff00
+#define bRxDFIRMode              	0x1800000
+#define bRxDCNFType              	0xe000000
+#define bRXIQImb_A               	0x3ff
+#define bRXIQImb_B               	0xfc00
+#define bRXIQImb_C               	0x3f0000
+#define bRXIQImb_D               	0xffc00000
+#define bDC_dc_Notch             	0x60000
+#define bRxNBINotch              	0x1f000000
+#define bPD_TH                   	0xf
+#define bPD_TH_Opt2              	0xc000
+#define bPWED_TH                 	0x700
+#define bIfMF_Win_L              	0x800
+#define bPD_Option               	0x1000
+#define bMF_Win_L                	0xe000
+#define bBW_Search_L             	0x30000
+#define bwin_enh_L               	0xc0000
+#define bBW_TH                   	0x700000
+#define bED_TH2                  	0x3800000
+#define bBW_option               	0x4000000
+#define bRatio_TH                	0x18000000
+#define bWindow_L                	0xe0000000
+#define bSBD_Option              	0x1
+#define bFrame_TH                	0x1c
+#define bFS_Option               	0x60
+#define bDC_Slope_check          	0x80
+#define bFGuard_Counter_DC_L     	0xe00
+#define bFrame_Weight_Short      	0x7000
+#define bSub_Tune                	0xe00000
+#define bFrame_DC_Length         	0xe000000
+#define bSBD_start_offset        	0x30000000
+#define bFrame_TH_2              	0x7
+#define bFrame_GI2_TH            	0x38
+#define bGI2_Sync_en             	0x40
+#define bSarch_Short_Early       	0x300
+#define bSarch_Short_Late        	0xc00
+#define bSarch_GI2_Late          	0x70000
+#define bCFOAntSum               	0x1
+#define bCFOAcc                  	0x2
+#define bCFOStartOffset          	0xc
+#define bCFOLookBack             	0x70
+#define bCFOSumWeight            	0x80
+#define bDAGCEnable              	0x10000
+#define bTXIQImb_A               	0x3ff
+#define bTXIQImb_B               	0xfc00
+#define bTXIQImb_C               	0x3f0000
+#define bTXIQImb_D               	0xffc00000
+#define bTxIDCOffset             	0xff
+#define bTxQDCOffset             	0xff00
+#define bTxDFIRMode              	0x10000
+#define bTxPesudoNoiseOn         	0x4000000
+#define bTxPesudoNoise_A         	0xff
+#define bTxPesudoNoise_B         	0xff00
+#define bTxPesudoNoise_C         	0xff0000
+#define bTxPesudoNoise_D         	0xff000000
+#define bCCADropOption           	0x20000
+#define bCCADropThres            	0xfff00000
+#define bEDCCA_H                 	0xf
+#define bEDCCA_L                 	0xf0
+#define bLambda_ED               	0x300
+#define bRxInitialGain           	0x7f
+#define bRxAntDivEn              	0x80
+#define bRxAGCAddressForLNA      	0x7f00
+#define bRxHighPowerFlow         	0x8000
+#define bRxAGCFreezeThres        	0xc0000
+#define bRxFreezeStep_AGC1       	0x300000
+#define bRxFreezeStep_AGC2       	0xc00000
+#define bRxFreezeStep_AGC3       	0x3000000
+#define bRxFreezeStep_AGC0       	0xc000000
+#define bRxRssi_Cmp_En           	0x10000000
+#define bRxQuickAGCEn            	0x20000000
+#define bRxAGCFreezeThresMode    	0x40000000
+#define bRxOverFlowCheckType     	0x80000000
+#define bRxAGCShift              	0x7f
+#define bTRSW_Tri_Only           	0x80
+#define bPowerThres              	0x300
+#define bRxAGCEn                	0x1
+#define bRxAGCTogetherEn         	0x2
+#define bRxAGCMin                	0x4
+#define bRxHP_Ini                	0x7
+#define bRxHP_TRLNA              	0x70
+#define bRxHP_RSSI               	0x700
+#define bRxHP_BBP1               	0x7000
+#define bRxHP_BBP2               	0x70000
+#define bRxHP_BBP3               	0x700000
+/* The threshold for high power */
+#define bRSSI_H                  	0x7f0000
+/* The threshold for ant diversity */
+#define bRSSI_Gen                	0x7f000000
+#define bRxSettle_TRSW           	0x7
+#define bRxSettle_LNA            	0x38
+#define bRxSettle_RSSI           	0x1c0
+#define bRxSettle_BBP            	0xe00
+#define bRxSettle_RxHP           	0x7000
+#define bRxSettle_AntSW_RSSI     	0x38000
+#define bRxSettle_AntSW          	0xc0000
+#define bRxProcessTime_DAGC      	0x300000
+#define bRxSettle_HSSI           	0x400000
+#define bRxProcessTime_BBPPW     	0x800000
+#define bRxAntennaPowerShift     	0x3000000
+#define bRSSITableSelect         	0xc000000
+#define bRxHP_Final              	0x7000000
+#define bRxHTSettle_BBP          	0x7
+#define bRxHTSettle_HSSI         	0x8
+#define bRxHTSettle_RxHP         	0x70
+#define bRxHTSettle_BBPPW        	0x80
+#define bRxHTSettle_Idle         	0x300
+#define bRxHTSettle_Reserved     	0x1c00
+#define bRxHTRxHPEn              	0x8000
+#define bRxHTAGCFreezeThres      	0x30000
+#define bRxHTAGCTogetherEn       	0x40000
+#define bRxHTAGCMin              	0x80000
+#define bRxHTAGCEn               	0x100000
+#define bRxHTDAGCEn              	0x200000
+#define bRxHTRxHP_BBP            	0x1c00000
+#define bRxHTRxHP_Final          	0xe0000000
+#define bRxPWRatioTH             	0x3
+#define bRxPWRatioEn             	0x4
+#define bRxMFHold                	0x3800
+#define bRxPD_Delay_TH1          	0x38
+#define bRxPD_Delay_TH2          	0x1c0
+#define bRxPD_DC_COUNT_MAX       	0x600
+/*#define bRxMF_Hold               	0x3800*/
 #define bRxPD_Delay_TH           0x8000
 #define bRxProcess_Delay         0xf0000
 #define bRxSearchrange_GI2_Early 0x700000
@@ -659,7 +692,7 @@
 
 #define bExtLNAGain              0x7c00
 
-//page d
+/* Page d */
 #define bSTBCEn                  0x4
 #define bAntennaMapping          0x10
 #define bNss                     0x20
@@ -669,12 +702,12 @@
 #define bOFDMContinueTx          0x10000000
 #define bOFDMSingleCarrier       0x20000000
 #define bOFDMSingleTone          0x40000000
-//#define bRxPath1                 0x01
-//#define bRxPath2                 0x02
-//#define bRxPath3                 0x04
-//#define bRxPath4                 0x08
-//#define bTxPath1                 0x10
-//#define bTxPath2                 0x20
+/*#define bRxPath1                 0x01
+#define bRxPath2                 0x02
+#define bRxPath3                 0x04
+#define bRxPath4                 0x08
+#define bTxPath1                 0x10
+#define bTxPath2                 0x20*/
 #define bHTDetect                0x100
 #define bCFOEn                   0x10000
 #define bCFOValue                0xfff00000
@@ -687,8 +720,10 @@
 #define bCounter_MCSNoSupport    0xffff
 #define bCounter_FastSync        0xffff
 #define bShortCFO                0xfff
-#define bShortCFOTLength         12   //total
-#define bShortCFOFLength         11   //fraction
+/* total */
+#define bShortCFOTLength         12
+/* fraction */
+#define bShortCFOFLength         11
 #define bLongCFO                 0x7ff
 #define bLongCFOTLength          11
 #define bLongCFOFLength          11
@@ -765,18 +800,18 @@
 #define bUChCfg                  0x7000000
 #define bUpdEqz                  0x8000000
 
-//page e
-#define bTxAGCRate18_06			0x7f7f7f7f
-#define bTxAGCRate54_24			0x7f7f7f7f
+/* Page e */
+#define bTxAGCRate18_06		0x7f7f7f7f
+#define bTxAGCRate54_24		0x7f7f7f7f
 #define bTxAGCRateMCS32		0x7f
-#define bTxAGCRateCCK			0x7f00
+#define bTxAGCRateCCK		0x7f00
 #define bTxAGCRateMCS3_MCS0	0x7f7f7f7f
 #define bTxAGCRateMCS7_MCS4	0x7f7f7f7f
 #define bTxAGCRateMCS11_MCS8	0x7f7f7f7f
 #define bTxAGCRateMCS15_MCS12	0x7f7f7f7f
 
 
-//Rx Pseduo noise
+/* Rx Pseduo noise */
 #define bRxPesudoNoiseOn         0x20000000
 #define bRxPesudoNoise_A         0xff
 #define bRxPesudoNoise_B         0xff00
@@ -787,8 +822,7 @@
 #define bPesudoNoiseState_C      0xffff
 #define bPesudoNoiseState_D      0xffff0000
 
-//RF
-//Zebra1
+/* RF Zebra 1 */
 #define bZebra1_HSSIEnable        0x8
 #define bZebra1_TRxControl        0xc00
 #define bZebra1_TRxGainSetting    0x07f
@@ -799,7 +833,7 @@
 #define bZebra1_TxLPFBW           0x400
 #define bZebra1_RxLPFBW           0x600
 
-//Zebra4
+/* Zebra4 */
 #define bRTL8256RegModeCtrl1      0x100
 #define bRTL8256RegModeCtrl0      0x40
 #define bRTL8256_TxLPFBW          0x18
@@ -810,7 +844,7 @@
 #define bRTL8258_RxLPFBW          0xc00
 #define bRTL8258_RSSILPFBW        0xc0
 
-//byte endable for sb_write
+/* byte endable for sb_write */
 #define bByte0                    0x1
 #define bByte1                    0x2
 #define bByte2                    0x4
@@ -819,7 +853,7 @@
 #define bWord1                    0xc
 #define bDWord                    0xf
 
-//for PutRegsetting & GetRegSetting BitMask
+/* for PutRegsetting & GetRegSetting BitMask */
 #define bMaskByte0                0xff
 #define bMaskByte1                0xff00
 #define bMaskByte2                0xff0000
@@ -828,7 +862,7 @@
 #define bMaskLWord                0x0000ffff
 #define bMaskDWord                0xffffffff
 
-//for PutRFRegsetting & GetRFRegSetting BitMask
+/* for PutRFRegsetting & GetRFRegSetting BitMask */
 #define bMask12Bits               0xfff
 
 #define bEnable                   0x1
@@ -837,14 +871,16 @@
 #define LeftAntenna               0x0
 #define RightAntenna              0x1
 
-#define tCheckTxStatus            500   //500ms
-#define tUpdateRxCounter          100   //100ms
+/* 500 ms */
+#define tCheckTxStatus            500
+/* 100 ms */
+#define tUpdateRxCounter          100
 
 #define rateCCK     0
 #define rateOFDM    1
 #define rateHT      2
 
-//define Register-End
+/* define Register-End */
 #define bPMAC_End                 0x1ff
 #define bFPGAPHY0_End             0x8ff
 #define bFPGAPHY1_End             0x9ff
@@ -852,12 +888,12 @@
 #define bOFDMPHY0_End             0xcff
 #define bOFDMPHY1_End             0xdff
 
-//define max debug item in each debug page
-//#define bMaxItem_FPGA_PHY0        0x9
-//#define bMaxItem_FPGA_PHY1        0x3
-//#define bMaxItem_PHY_11B          0x16
-//#define bMaxItem_OFDM_PHY0        0x29
-//#define bMaxItem_OFDM_PHY1        0x0
+/*#define max debug item in each debug page
+#define bMaxItem_FPGA_PHY0        0x9
+#define bMaxItem_FPGA_PHY1        0x3
+#define bMaxItem_PHY_11B          0x16
+#define bMaxItem_OFDM_PHY0        0x29
+#define bMaxItem_OFDM_PHY1        0x0 */
 
 #define bPMACControl              0x0
 #define bWMACControl              0x1
@@ -868,11 +904,12 @@
 #define PathC                     0x2
 #define PathD                     0x3
 
-#define	rRTL8256RxMixerPole		0xb
-#define 	bZebraRxMixerPole		0x6
-#define 	rRTL8256TxBBOPBias        0x9
-#define 	bRTL8256TxBBOPBias       0x400
-#define 	rRTL8256TxBBBW             19
-#define 	bRTL8256TxBBBW            	0x18
+#define rRTL8256RxMixerPole	0xb
+#define bZebraRxMixerPole	0x6
+#define rRTL8256TxBBOPBias	0x9
+#define bRTL8256TxBBOPBias	0x400
+#define rRTL8256TxBBBW		19
+#define bRTL8256TxBBBW		0x18
 
-#endif	//__INC_HAL8190PCIPHYREG_H
+
+#endif	/* __INC_HAL8190PCIPHYREG_H */
diff --git a/drivers/staging/rtl8192su/Kconfig b/drivers/staging/rtl8192su/Kconfig
index 123fa6d..b72a962 100644
--- a/drivers/staging/rtl8192su/Kconfig
+++ b/drivers/staging/rtl8192su/Kconfig
@@ -1,6 +1,7 @@
 config RTL8192SU
 	tristate "RealTek RTL8192SU Wireless LAN NIC driver"
 	depends on PCI && WLAN && USB
-	depends on WIRELESS_EXT
+	select WIRELESS_EXT
+	select WEXT_PRIV
 	default N
 	---help---
diff --git a/drivers/staging/rtl8192su/TODO b/drivers/staging/rtl8192su/TODO
index f11eec7..3c8da15 100644
--- a/drivers/staging/rtl8192su/TODO
+++ b/drivers/staging/rtl8192su/TODO
@@ -4,7 +4,6 @@
   - cleanup ieee80211.h
   - move rtl8192su's specific code out from ieee80211.h
   - abstract rtl819su's specific code
-  - use list_for_each_safe() in ieee80211_crypto_deinit
 - switch to use shared "librtl" instead of private ieee80211 stack
 - switch to use LIB80211
 - switch to use MAC80211
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211.h b/drivers/staging/rtl8192su/ieee80211/ieee80211.h
index 2b8c855..32b261d 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211.h
@@ -30,6 +30,7 @@
 #include <linux/jiffies.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
+#include <linux/semaphore.h>
 
 #include <linux/delay.h>
 #include <linux/wireless.h>
@@ -195,10 +196,6 @@
 #define IEEE80211_DEBUG_DATA(level, data, datalen) do {} while(0)
 #endif	/* CONFIG_IEEE80211_DEBUG */
 
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], \
-		   ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
-
 /*
  * To use the debug system;
  *
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c
index 521e7b9..c4640e6 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c
@@ -226,19 +226,20 @@
 void __exit ieee80211_crypto_deinit(void)
 {
 	struct list_head *ptr, *n;
+	struct ieee80211_crypto_alg *alg = NULL;
 
 	if (hcrypt == NULL)
 		return;
 
-	for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
-	     ptr = n, n = ptr->next) {
-		struct ieee80211_crypto_alg *alg =
-			(struct ieee80211_crypto_alg *) ptr;
-		list_del(ptr);
-		printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
-		       "'%s' (deinit)\n", alg->ops->name);
-		kfree(alg);
+	list_for_each_safe(ptr, n, &hcrypt->algs) {
+		alg = list_entry(ptr, struct ieee80211_crypto_alg, list);
+		if (alg) {
+			list_del(ptr);
+			printk(KERN_DEBUG
+			       "ieee80211_crypt: unregistered algorithm '%s' (deinit)\n",
+			       alg->ops->name);
+			kfree(alg);
+		}
 	}
-
 	kfree(hcrypt);
 }
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_ccmp.c
index 7bc956e..8a93f7d 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_ccmp.c
@@ -288,7 +288,7 @@
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "CCMP: received packet without ExtIV"
-			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			       " flag from %pM\n", hdr->addr2);
 		}
 		key->dot11RSNAStatsCCMPFormatErrors++;
 		return -2;
@@ -301,9 +301,9 @@
 	}
 	if (!key->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
+			printk(KERN_DEBUG "CCMP: received packet from %pM"
 			       " with keyid=%d that does not have a configured"
-			       " key\n", MAC_ARG(hdr->addr2), keyidx);
+			       " key\n", hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -318,11 +318,9 @@
 
 	if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
-			       " previous PN %02x%02x%02x%02x%02x%02x "
-			       "received PN %02x%02x%02x%02x%02x%02x\n",
-			       MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
-			       MAC_ARG(pn));
+			printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
+			       " previous PN %pm received PN %pm\n",
+			       hdr->addr2, key->rx_pn, pn);
 		}
 		key->dot11RSNAStatsCCMPReplays++;
 		return -4;
@@ -359,7 +357,7 @@
 		if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG "CCMP: decrypt failed: STA="
-				MAC_FMT "\n", MAC_ARG(hdr->addr2));
+				"%pM\n", hdr->addr2);
 			}
 			key->dot11RSNAStatsCCMPDecryptErrors++;
 			return -5;
@@ -435,11 +433,10 @@
 {
 	struct ieee80211_ccmp_data *ccmp = priv;
 	p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
-		     "tx_pn=%02x%02x%02x%02x%02x%02x "
-		     "rx_pn=%02x%02x%02x%02x%02x%02x "
+		     "tx_pn=%pm rx_pn=%pm "
 		     "format_errors=%d replays=%d decrypt_errors=%d\n",
 		     ccmp->key_idx, ccmp->key_set,
-		     MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
+		     ccmp->tx_pn, ccmp->rx_pn,
 		     ccmp->dot11RSNAStatsCCMPFormatErrors,
 		     ccmp->dot11RSNAStatsCCMPReplays,
 		     ccmp->dot11RSNAStatsCCMPDecryptErrors);
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_tkip.c
index 9b9438f..7e48748 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_tkip.c
@@ -410,7 +410,7 @@
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "TKIP: received packet without ExtIV"
-			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			       " flag from %pM\n", hdr->addr2);
 		}
 		return -2;
 	}
@@ -422,9 +422,9 @@
 	}
 	if (!tkey->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
+			printk(KERN_DEBUG "TKIP: received packet from %pM"
 			       " with keyid=%d that does not have a configured"
-			       " key\n", MAC_ARG(hdr->addr2), keyidx);
+			       " key\n", hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -437,9 +437,9 @@
 		if (iv32 < tkey->rx_iv32 ||
 		(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
 			if (net_ratelimit()) {
-				printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
+				printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
 				" previous TSC %08x%04x received TSC "
-				"%08x%04x\n", MAC_ARG(hdr->addr2),
+				"%08x%04x\n", hdr->addr2,
 				tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
 			}
 			tkey->dot11RSNAStatsTKIPReplays++;
@@ -460,8 +460,8 @@
 		if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG ": TKIP: failed to decrypt "
-						"received packet from " MAC_FMT "\n",
-						MAC_ARG(hdr->addr2));
+						"received packet from %pM\n",
+						hdr->addr2);
 			}
 			return -7;
 		}
@@ -480,7 +480,7 @@
 			}
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG "TKIP: ICV error detected: STA="
-				MAC_FMT "\n", MAC_ARG(hdr->addr2));
+				"%pM\n", hdr->addr2);
 			}
 			tkey->dot11RSNAStatsTKIPICVErrors++;
 			return -5;
@@ -635,8 +635,8 @@
 		struct ieee80211_hdr_4addr *hdr;
 		hdr = (struct ieee80211_hdr_4addr *) skb->data;
 		printk(KERN_DEBUG "%s: Michael MIC verification failed for "
-		       "MSDU from " MAC_FMT " keyidx=%d\n",
-		       skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
+		       "MSDU from %pM keyidx=%d\n",
+		       skb->dev ? skb->dev->name : "N/A", hdr->addr2,
 		       keyidx);
 		if (skb->dev)
 			ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
index e8c67d5..c024fa6 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
@@ -262,7 +262,7 @@
 			     unsigned long count, void *data)
 {
 	char buf[] = "0x00000000";
-	unsigned long len = min(sizeof(buf) - 1, count);
+	unsigned long len = min_t(unsigned long, sizeof(buf) - 1, count);
 	char *p = (char *)buf;
 	unsigned long val;
 
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
index 095b8c6..cc80faf 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
@@ -314,8 +314,8 @@
 	    strcmp(crypt->ops->name, "TKIP") == 0) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "received packet from " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(hdr->addr2));
+			       "received packet from %pM\n",
+			       ieee->dev->name, hdr->addr2);
 		}
 		return -1;
 	}
@@ -326,8 +326,8 @@
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
 		IEEE80211_DEBUG_DROP(
-			"decryption failed (SA=" MAC_FMT
-			") res=%d\n", MAC_ARG(hdr->addr2), res);
+			"decryption failed (SA=%pM"
+			") res=%d\n", hdr->addr2, res);
 		if (res == -2)
 			IEEE80211_DEBUG_DROP("Decryption failed ICV "
 					     "mismatch (key %d)\n",
@@ -364,8 +364,8 @@
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
-		       " (SA=" MAC_FMT " keyidx=%d)\n",
-		       ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
+		       " (SA=%pM keyidx=%d)\n",
+		       ieee->dev->name, hdr->addr2, keyidx);
 		return -1;
 	}
 
@@ -939,8 +939,8 @@
 			 * frames silently instead of filling system log with
 			 * these reports. */
 			IEEE80211_DEBUG_DROP("Decryption failed (not set)"
-					     " (SA=" MAC_FMT ")\n",
-					     MAC_ARG(hdr->addr2));
+					     " (SA=%pM)\n",
+					     hdr->addr2);
 			ieee->ieee_stats.rx_discards_undecryptable++;
 			goto rx_dropped;
 		}
@@ -1143,8 +1143,8 @@
 		} else {
 			IEEE80211_DEBUG_DROP(
 				"encryption configured, but RX "
-				"frame not encrypted (SA=" MAC_FMT ")\n",
-				MAC_ARG(hdr->addr2));
+				"frame not encrypted (SA=%pM)\n",
+				hdr->addr2);
 			goto rx_dropped;
 		}
 	}
@@ -1163,9 +1163,9 @@
 	    !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
 		IEEE80211_DEBUG_DROP(
 			"dropped unencrypted RX data "
-			"frame from " MAC_FMT
+			"frame from %pM"
 			" (drop_unencrypted=1)\n",
-			MAC_ARG(hdr->addr2));
+			hdr->addr2);
 		goto rx_dropped;
 	}
 /*
@@ -2159,11 +2159,11 @@
 	}
 
 	if (network->mode == 0) {
-		IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
+		IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
 				     "network.\n",
 				     escape_essid(network->ssid,
 						  network->ssid_len),
-				     MAC_ARG(network->bssid));
+				     network->bssid);
 		return 1;
 	}
 
@@ -2345,9 +2345,9 @@
 
 	memset(&network, 0, sizeof(struct ieee80211_network));
 	IEEE80211_DEBUG_SCAN(
-		"'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+		"'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
 		escape_essid(info_element->data, info_element->len),
-		MAC_ARG(beacon->header.addr3),
+		beacon->header.addr3,
 		(beacon->capability & (1<<0xf)) ? '1' : '0',
 		(beacon->capability & (1<<0xe)) ? '1' : '0',
 		(beacon->capability & (1<<0xd)) ? '1' : '0',
@@ -2366,10 +2366,10 @@
 		(beacon->capability & (1<<0x0)) ? '1' : '0');
 
 	if (ieee80211_network_init(ieee, beacon, &network, stats)) {
-		IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
 				     escape_essid(info_element->data,
 						  info_element->len),
-				     MAC_ARG(beacon->header.addr3),
+				     beacon->header.addr3,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
@@ -2478,11 +2478,11 @@
 			/* If there are no more slots, expire the oldest */
 			list_del(&oldest->list);
 			target = oldest;
-			IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
+			IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
 					     "network list.\n",
 					     escape_essid(target->ssid,
 							  target->ssid_len),
-					     MAC_ARG(target->bssid));
+					     target->bssid);
 		} else {
 			/* Otherwise just pull from the free list */
 			target = list_entry(ieee->network_free_list.next,
@@ -2492,10 +2492,10 @@
 
 
 #ifdef CONFIG_IEEE80211_DEBUG
-		IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
 				     escape_essid(network.ssid,
 						  network.ssid_len),
-				     MAC_ARG(network.bssid),
+				     network.bssid,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
@@ -2505,10 +2505,10 @@
 		if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
 			ieee80211_softmac_new_net(ieee,&network);
 	} else {
-		IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
 				     escape_essid(target->ssid,
 						  target->ssid_len),
-				     MAC_ARG(target->bssid),
+				     target->bssid,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
index 0ba2a01..9d8cb0e 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
@@ -1709,7 +1709,7 @@
 		ieee80211_resp_to_assoc_rq(ieee, dest);
 	}
 
-	printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
+	printk(KERN_INFO"New client associated: %pM\n", dest);
 	//FIXME
 }
 
@@ -2145,8 +2145,8 @@
 	ieee80211_sta_wakeup(ieee,0);
 
 	/* update the tx status */
-//	ieee->stats.tx_bytes += txb->payload_size;
-//	ieee->stats.tx_packets++;
+	ieee->stats.tx_bytes += txb->payload_size;
+	ieee->stats.tx_packets++;
 	tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
 	if(tcb_desc->bMulticast) {
 		ieee->stats.multicast++;
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c
index 4d54e1e..484c3ab 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c
@@ -199,8 +199,8 @@
 		header = (struct rtl_ieee80211_hdr *)frag->data;
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "TX packet to " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(header->addr1));
+			       "TX packet to %pM\n",
+			       ieee->dev->name, header->addr1);
 		}
 		return -1;
 	}
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
index 85c7e96..122f800 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
@@ -261,10 +261,10 @@
 		else
 			IEEE80211_DEBUG_SCAN(
 				"Not showing network '%s ("
-				MAC_FMT ")' due to age (%lums).\n",
+				"%pM)' due to age (%lums).\n",
 				escape_essid(network->ssid,
 					     network->ssid_len),
-				MAC_ARG(network->bssid),
+				network->bssid,
 				(jiffies - network->last_scanned) / (HZ / 100));
 	}
 
@@ -731,7 +731,7 @@
 #if 1
 	case IW_AUTH_WPA_ENABLED:
 		ieee->wpa_enabled = (data->value)?1:0;
-		//printk("enalbe wpa:%d\n", ieee->wpa_enabled);
+		//printk("enable wpa:%d\n", ieee->wpa_enabled);
 		break;
 
 #endif
diff --git a/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c
index c696245..8c37dd1 100644
--- a/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c
@@ -113,7 +113,7 @@
 	u16 tmp = 0;
 	u16 len = ieee->tx_headroom + 9;
 	//category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) +  BA Timeout Value(2) +  BA Start SeqCtrl(2)(or StatusCode(2))
-	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __FUNCTION__, type, MAC_ARG(Dst), ieee->dev);
+	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
 	if (pBA == NULL||ieee == NULL)
 	{
 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
@@ -200,7 +200,7 @@
 	u16 len = 6 + ieee->tx_headroom;
 
 	if (net_ratelimit())
-	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst));
+	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
 
 	memset(&DelbaParamSet, 0, 2);
 
@@ -339,7 +339,10 @@
 
 	if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
 	{
-		IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %ld)\n", skb->len, 	(sizeof( struct ieee80211_hdr_3addr) + 9));
+		IEEE80211_DEBUG(IEEE80211_DL_ERR,
+				" Invalid skb len in BAREQ(%d / %zd)\n",
+				skb->len,
+				sizeof(struct ieee80211_hdr_3addr) + 9);
 		return -1;
 	}
 
@@ -354,7 +357,7 @@
 	pBaTimeoutVal = (u16*)(tag + 5);
 	pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
 
-	printk("====================>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst));
+	printk("====================>rx ADDBAREQ from :%pM\n", dst);
 //some other capability is not ready now.
 	if(	(ieee->current_network.qos_data.active == 0) ||
 		(ieee->pHTInfo->bCurrentHTSupport == false) ||
@@ -440,7 +443,10 @@
 
 	if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
 	{
-		IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %ld)\n", skb->len, 	(sizeof( struct ieee80211_hdr_3addr) + 9));
+		IEEE80211_DEBUG(IEEE80211_DL_ERR,
+				" Invalid skb len in BARSP(%d / %zd)\n",
+				skb->len,
+				sizeof(struct ieee80211_hdr_3addr) + 9);
 		return -1;
 	}
 	rsp = ( struct ieee80211_hdr_3addr*)skb->data;
@@ -570,7 +576,10 @@
 
 	if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
 	{
-		IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %ld)\n", skb->len, 	(sizeof( struct ieee80211_hdr_3addr) + 6));
+		IEEE80211_DEBUG(IEEE80211_DL_ERR,
+				" Invalid skb len in DELBA(%d / %zd)\n",
+				skb->len,
+				sizeof(struct ieee80211_hdr_3addr) + 6);
 		return -1;
 	}
 
diff --git a/drivers/staging/rtl8192su/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192su/ieee80211/rtl819x_HTProc.c
index 33c7fa7..01114c5 100644
--- a/drivers/staging/rtl8192su/ieee80211/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192su/ieee80211/rtl819x_HTProc.c
@@ -42,7 +42,7 @@
 static u8 DLINK_ATHEROS_2[3] = {0x00, 0x21, 0x91};
 static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
 static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
-// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Shoud we put the
+// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Should we put the
 // code in other place??
 //static u8 WIFI_CISCO_G_AP[3] = {0x00, 0x40, 0x96};
 /********************************************************************************************************************
diff --git a/drivers/staging/rtl8192su/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192su/ieee80211/rtl819x_TSProc.c
index ad3bf35..60cf1f8 100644
--- a/drivers/staging/rtl8192su/ieee80211/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192su/ieee80211/rtl819x_TSProc.c
@@ -291,7 +291,7 @@
 		if(search_dir[dir] ==false )
 			continue;
 		list_for_each_entry(pRet, psearch_list, List){
-	//		IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:"MAC_FMT", TID:%d, dir:%d\n", MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
+	//		IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
 			if (memcmp(pRet->Addr, Addr, 6) == 0)
 				if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
 					if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
@@ -447,7 +447,7 @@
 					ResetRxTsEntry(tmp);
 				}
 
-				IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT"\n", UP, Dir, MAC_ARG(Addr));
+				IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
 				// Prepare TS Info releated field
 				pTSInfo->field.ucTrafficType = 0;			// Traffic type: WMM is reserved in this field
 				pTSInfo->field.ucTSID = UP;			// TSID
@@ -533,7 +533,7 @@
 void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr)
 {
 	PTS_COMMON_INFO	pTS, pTmpTS;
-	printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr));
+	printk("===========>RemovePeerTS,%pM\n", Addr);
 #if 1
 	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
 	{
diff --git a/drivers/staging/rtl8192su/r8192SU_HWImg.c b/drivers/staging/rtl8192su/r8192SU_HWImg.c
index cbb6579..ba8e12c 100644
--- a/drivers/staging/rtl8192su/r8192SU_HWImg.c
+++ b/drivers/staging/rtl8192su/r8192SU_HWImg.c
@@ -2,4282 +2,6 @@
 
 #include "r8192SU_HWImg.h"
 
-u8 Rtl8192SUFwImgArray[ImgArrayLength] = {
-0x92,0x81,0x2b,0x90,0x30,0x00,0x00,0x00,0x08,0x74,0x00,0x00,0x88,0x96,0x00,0x00,
-0x30,0x00,0x00,0x00,0x00,0x95,0x00,0x00,0x00,0x00,0x2b,0x00,0x03,0x03,0x23,0x00,
-0x92,0x81,0x02,0x01,0x00,0x00,0x12,0x04,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x00,
-0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x7f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x1f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x25,0xb0,0x1a,0x3c,0x80,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,0x80,0x00,0x7b,0x37,
-0x00,0x00,0x5b,0xaf,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,
-0x80,0x00,0x7b,0x37,0x00,0x00,0x5b,0xaf,0x00,0x80,0x1a,0x3c,0x10,0x6d,0x5a,0x27,
-0x08,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x04,0x00,0xa1,0xaf,0x08,0x00,0xa2,0xaf,0x0c,0x00,0xa3,0xaf,0x10,0x00,0xa4,0xaf,
-0x14,0x00,0xa5,0xaf,0x18,0x00,0xa6,0xaf,0x1c,0x00,0xa7,0xaf,0x20,0x00,0xa8,0xaf,
-0x24,0x00,0xa9,0xaf,0x28,0x00,0xaa,0xaf,0x2c,0x00,0xab,0xaf,0x30,0x00,0xac,0xaf,
-0x34,0x00,0xad,0xaf,0x38,0x00,0xae,0xaf,0x3c,0x00,0xaf,0xaf,0x12,0x40,0x00,0x00,
-0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0xb0,0xaf,0x44,0x00,0xb1,0xaf,
-0x48,0x00,0xb2,0xaf,0x4c,0x00,0xb3,0xaf,0x50,0x00,0xb4,0xaf,0x54,0x00,0xb5,0xaf,
-0x58,0x00,0xb6,0xaf,0x5c,0x00,0xb7,0xaf,0x60,0x00,0xb8,0xaf,0x64,0x00,0xb9,0xaf,
-0x68,0x00,0xbc,0xaf,0x6c,0x00,0xbd,0xaf,0x70,0x00,0xbe,0xaf,0x74,0x00,0xbf,0xaf,
-0x78,0x00,0xa8,0xaf,0x7c,0x00,0xa9,0xaf,0x80,0x00,0xaa,0xaf,0xdf,0x1a,0x00,0x08,
-0x21,0x20,0xa0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x25,0xb0,0x06,0x3c,0x00,0x80,0x02,0x3c,0xe8,0xff,0xbd,0x27,0x18,0x03,0xc3,0x34,
-0x00,0x03,0x42,0x24,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x42,0xb0,0x03,0x3c,
-0x03,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x02,0x80,0x0a,0x3c,0x02,0x80,0x10,0x3c,
-0xff,0x00,0x42,0x30,0x00,0x46,0x02,0x00,0x10,0x00,0x42,0x30,0x13,0x00,0x40,0x10,
-0x03,0x46,0x08,0x00,0xc4,0x7d,0x42,0x8d,0x68,0x15,0x05,0x26,0xd4,0x63,0xa4,0x94,
-0x01,0x00,0x47,0x24,0x10,0x00,0x02,0x24,0xb0,0x03,0xc9,0x34,0x00,0x00,0x62,0xa0,
-0x07,0x00,0x80,0x10,0x1c,0x03,0xc6,0x34,0xd8,0x63,0xa2,0x8c,0xd4,0x63,0xa0,0xa4,
-0xd8,0x63,0xa0,0xac,0x00,0x00,0x04,0x24,0x00,0x00,0xc2,0xac,0x00,0x00,0x20,0xad,
-0x01,0x00,0x82,0x24,0xc4,0x7d,0x47,0xad,0xd4,0x63,0xa2,0xa4,0x12,0x00,0x00,0x05,
-0x42,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x68,0x15,0x04,0x26,0x0c,0x4b,0x83,0x94,0x08,0x4b,0x85,0x94,
-0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,
-0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,
-0x08,0x00,0xe0,0x03,0x08,0x4b,0x83,0xa4,0x80,0xff,0x03,0x24,0x03,0x00,0x42,0x34,
-0x00,0x00,0x43,0xa0,0xc8,0x0e,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0x04,0x26,
-0x0c,0x4b,0x83,0x94,0x08,0x4b,0x85,0x94,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
-0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,
-0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,0x08,0x00,0xe0,0x03,0x08,0x4b,0x83,0xa4,
-0xff,0x00,0x84,0x30,0x0b,0x00,0x82,0x2c,0xff,0xff,0xe7,0x30,0x10,0x00,0xa8,0x93,
-0x19,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,
-0xc0,0x91,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,
-0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x43,0xb0,0x02,0x3c,0x78,0x00,0x44,0x34,
-0x07,0x00,0xe2,0x30,0x00,0x00,0x85,0xac,0x04,0x00,0x86,0xac,0x04,0x00,0x40,0x18,
-0x00,0x00,0x00,0x00,0xf8,0xff,0xe2,0x30,0x08,0x00,0x42,0x24,0xff,0xff,0x47,0x30,
-0x21,0x10,0xe8,0x00,0x00,0x80,0x03,0x3c,0x08,0x00,0x82,0xac,0x25,0x10,0x43,0x00,
-0x08,0x00,0x82,0xac,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x6c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,
-0x20,0x01,0x00,0x08,0x60,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,
-0x54,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x48,0x00,0x44,0x34,
-0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x3c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,
-0x20,0x01,0x00,0x08,0x30,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,
-0x24,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x18,0x00,0x44,0x34,
-0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x0c,0x00,0x44,0x34,0x20,0x01,0x00,0x08,
-0x43,0xb0,0x04,0x3c,0x01,0x00,0x02,0x24,0x25,0xb0,0x03,0x3c,0x04,0x20,0x82,0x00,
-0x18,0x03,0x67,0x34,0x00,0x80,0x02,0x3c,0x43,0xb0,0x03,0x3c,0x34,0x05,0x46,0x24,
-0x88,0x00,0x65,0x34,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0xff,0x42,0x30,
-0x05,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x00,0x00,0xe6,0xac,
-0x00,0x00,0xa2,0x94,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x30,0x24,0x10,0x44,0x00,
-0xf4,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x25,0xb0,0x08,0x3c,0x00,0x80,0x02,0x3c,0xc8,0xff,0xbd,0x27,0x18,0x03,0x03,0x35,
-0x90,0x05,0x42,0x24,0x00,0x00,0x62,0xac,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,
-0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0x0c,0x00,0xf2,0x84,0x08,0x00,0xf5,0x8c,
-0xff,0x00,0xc6,0x30,0x00,0x01,0x02,0x24,0x23,0x10,0x46,0x00,0xff,0xff,0x51,0x30,
-0xd0,0x03,0x08,0x35,0xff,0x00,0x96,0x30,0x00,0x00,0x12,0xad,0x21,0xa0,0xa0,0x00,
-0x21,0x30,0xc5,0x00,0x00,0x00,0x15,0xad,0x21,0x20,0xc0,0x02,0x21,0x28,0xa0,0x02,
-0x21,0x38,0x20,0x02,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x23,0x18,0x51,0x02,
-0xff,0xff,0x82,0x32,0x00,0x94,0x03,0x00,0x03,0x94,0x12,0x00,0xa6,0x01,0x00,0x08,
-0x02,0x9a,0x02,0x00,0x28,0xb0,0x03,0x3c,0xc0,0x10,0x13,0x00,0x21,0x10,0x43,0x00,
-0x00,0x00,0x44,0x90,0x25,0xb0,0x10,0x3c,0x20,0x10,0x02,0x3c,0xff,0x00,0x93,0x30,
-0x00,0x22,0x13,0x00,0xff,0xff,0x43,0x32,0x01,0x01,0x45,0x2a,0x21,0xa0,0x82,0x00,
-0x21,0xa8,0xb1,0x02,0xd0,0x03,0x02,0x36,0x00,0x01,0x11,0x24,0x0b,0x88,0x65,0x00,
-0x21,0x20,0xc0,0x02,0x00,0x00,0x53,0xac,0x4d,0x01,0x00,0x0c,0xb0,0x03,0x10,0x36,
-0x21,0x30,0x80,0x02,0x21,0x20,0xc0,0x02,0x21,0x28,0xa0,0x02,0x21,0x38,0x20,0x02,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x23,0x18,0x51,0x02,0x00,0x94,0x03,0x00,
-0x03,0x94,0x12,0x00,0x00,0x00,0x12,0xae,0xe2,0xff,0x40,0x1e,0x00,0x00,0x00,0x00,
-0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,
-0x25,0xb0,0x04,0x3c,0x20,0x00,0xb2,0xaf,0x68,0x15,0x52,0x24,0x00,0x80,0x02,0x3c,
-0x18,0x03,0x83,0x34,0xc8,0x06,0x42,0x24,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
-0x30,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x00,0x00,0x62,0xac,0xb0,0x03,0x93,0x34,0x21,0xa0,0x40,0x02,0x54,0x64,0x42,0x8e,
-0xc0,0x64,0x50,0x8e,0x21,0x20,0x00,0x00,0x00,0x00,0x62,0xae,0x58,0x64,0x42,0xae,
-0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x64,0x44,0x8e,
-0xc4,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,
-0x0a,0x18,0x82,0x00,0xc0,0x64,0x43,0xae,0xc0,0x64,0x85,0x8e,0x00,0x00,0x00,0x00,
-0x00,0x00,0x65,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,
-0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0xff,0x00,0x15,0x24,0x21,0x20,0x00,0x00,
-0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0x20,0x10,0x02,0x3c,0x20,0x00,0x07,0x24,
-0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,0x05,0x00,0x35,0x12,0x21,0x30,0x60,0x00,
-0x08,0x64,0x91,0xa2,0x54,0x64,0x83,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,
-0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,
-0x25,0x18,0x64,0x00,0xc0,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x08,0x00,0x03,0xae,
-0xc9,0x64,0x84,0x92,0x2a,0xb0,0x02,0x3c,0x01,0x00,0x03,0x24,0x01,0x00,0x84,0x24,
-0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0xc4,0xff,0x35,0x16,0xc9,0x64,0x84,0xa2,
-0xfc,0x4a,0x82,0x8e,0x41,0xb0,0x03,0x3c,0x30,0x00,0xbf,0x8f,0x00,0x38,0x42,0x34,
-0x00,0x00,0x62,0xac,0x2c,0x00,0xb5,0x8f,0xfc,0x4a,0x82,0xae,0x24,0x00,0xb3,0x8f,
-0x28,0x00,0xb4,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,
-0xc8,0xff,0xbd,0x27,0x18,0x03,0x83,0x34,0x38,0x08,0x42,0x24,0x34,0x00,0xbf,0xaf,
-0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
-0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c,
-0x68,0x15,0xd2,0x26,0xb0,0x03,0x93,0x34,0x2d,0x02,0x00,0x08,0x21,0xa8,0x40,0x02,
-0x2a,0xb0,0x02,0x3c,0x08,0x00,0x04,0xae,0x09,0x00,0x42,0x34,0x01,0x00,0x03,0x24,
-0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0,0x42,0x00,0x34,0x12,
-0x00,0x00,0x00,0x00,0x6c,0x64,0x42,0x8e,0xd8,0x64,0x50,0x8e,0x01,0x00,0x04,0x24,
-0x00,0x00,0x62,0xae,0x70,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xd8,0x64,0x44,0x8e,0xdc,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,
-0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xd8,0x64,0x43,0xae,
-0xd8,0x64,0xa5,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xae,0x02,0x80,0x02,0x3c,
-0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,
-0xff,0x00,0x14,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,
-0x20,0x10,0x02,0x3c,0x20,0x00,0x07,0x24,0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,
-0x05,0x00,0x34,0x12,0x21,0x30,0x60,0x00,0x6c,0x64,0xa3,0xae,0x10,0x64,0xb1,0xa2,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,
-0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,
-0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
-0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0xc0,0xff,0x05,0x24,
-0x82,0x11,0x03,0x00,0x24,0x20,0x65,0x00,0x01,0x00,0x42,0x30,0xc0,0xff,0x40,0x10,
-0x04,0x00,0x84,0x34,0x2a,0xb0,0x02,0x3c,0x08,0x00,0x03,0xae,0x09,0x00,0x42,0x34,
-0x01,0x00,0x03,0x24,0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0,
-0xc0,0xff,0x34,0x16,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xc2,0x26,0xfc,0x4a,0x43,0x8c,
-0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x00,0x38,0x63,0x34,0x41,0xb0,0x04,0x3c,0x38,0x00,0xbd,0x27,0x00,0x00,0x83,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0x43,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,
-0xc0,0xff,0xbd,0x27,0x18,0x03,0x83,0x34,0x08,0x0a,0x42,0x24,0x38,0x00,0xbf,0xaf,
-0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x02,0x80,0x17,0x3c,0x68,0x15,0xf2,0x26,0xb0,0x03,0x93,0x34,0x02,0x80,0x14,0x3c,
-0xab,0x02,0x00,0x08,0x21,0xb0,0x40,0x02,0x2a,0xb0,0x03,0x3c,0x08,0x00,0x04,0xae,
-0x05,0x00,0x63,0x34,0x01,0x00,0x02,0x24,0x02,0x00,0x04,0x24,0x00,0x00,0x62,0xa0,
-0x00,0x00,0x64,0xa0,0xca,0x7d,0x82,0x96,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
-0xca,0x7d,0x82,0xa6,0xca,0x7d,0x83,0x96,0x25,0xb0,0x02,0x3c,0x66,0x03,0x42,0x34,
-0x00,0x00,0x43,0xa4,0x4a,0x00,0x35,0x12,0x00,0x00,0x00,0x00,0x60,0x64,0x42,0x8e,
-0xcc,0x64,0x50,0x8e,0x01,0x00,0x04,0x24,0x00,0x00,0x62,0xae,0x64,0x64,0x42,0xae,
-0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0xcc,0x64,0x44,0x8e,
-0xd0,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,
-0x0a,0x18,0x82,0x00,0xcc,0x64,0x43,0xae,0xcc,0x64,0xc5,0x8e,0x00,0x00,0x00,0x00,
-0x00,0x00,0x65,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,
-0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0xff,0x00,0x15,0x24,0x01,0x00,0x04,0x24,
-0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0x20,0x10,0x02,0x3c,0x20,0x00,0x07,0x24,
-0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,0x05,0x00,0x35,0x12,0x21,0x30,0x60,0x00,
-0x60,0x64,0xc3,0xae,0x0c,0x64,0xd1,0xa2,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,
-0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,
-0x25,0x18,0x64,0x00,0xc0,0xff,0x05,0x24,0x82,0x11,0x03,0x00,0x24,0x20,0x65,0x00,
-0x01,0x00,0x42,0x30,0xb8,0xff,0x40,0x10,0x04,0x00,0x84,0x34,0x08,0x00,0x03,0xae,
-0x2a,0xb0,0x03,0x3c,0x05,0x00,0x63,0x34,0x01,0x00,0x02,0x24,0x02,0x00,0x04,0x24,
-0x00,0x00,0x62,0xa0,0x00,0x00,0x64,0xa0,0xca,0x7d,0x82,0x96,0x00,0x00,0x00,0x00,
-0x01,0x00,0x42,0x24,0xca,0x7d,0x82,0xa6,0xca,0x7d,0x83,0x96,0x25,0xb0,0x02,0x3c,
-0x66,0x03,0x42,0x34,0x00,0x00,0x43,0xa4,0xb8,0xff,0x35,0x16,0x00,0x00,0x00,0x00,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xe2,0x26,0xfc,0x4a,0x43,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x38,0x63,0x34,
-0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x83,0xac,0x08,0x00,0xe0,0x03,
-0xfc,0x4a,0x43,0xac,0xc0,0xff,0xbd,0x27,0x2c,0x00,0xb5,0xaf,0x38,0x00,0xbf,0xaf,
-0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
-0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c,
-0x7c,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
-0x24,0x0c,0x63,0x24,0x40,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,0x21,0xa8,0x00,0x00,
-0x03,0x00,0x80,0x10,0x7f,0x00,0xa2,0x30,0xbf,0x00,0xa2,0x30,0x01,0x00,0x15,0x24,
-0x7c,0x7e,0xc2,0xa0,0x7c,0x7e,0xc2,0x90,0x25,0xb0,0x04,0x3c,0x88,0x02,0x83,0x34,
-0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x02,0x80,0x16,0x3c,0x68,0x15,0xd2,0x26,0xb0,0x03,0x93,0x34,0x02,0x80,0x14,0x3c,
-0x43,0x03,0x00,0x08,0x21,0xb8,0x40,0x02,0x24,0x10,0xa2,0x00,0x04,0x00,0x42,0x34,
-0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,0x0d,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,
-0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,
-0x00,0x00,0x43,0xa0,0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,
-0x01,0x00,0x84,0x24,0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,0xff,0x00,0x03,0x24,
-0x00,0x00,0xa2,0xa4,0x5a,0x00,0x23,0x12,0x00,0x00,0x00,0x00,0x24,0x64,0x42,0x8e,
-0x90,0x64,0x50,0x8e,0x03,0x00,0x04,0x24,0x00,0x00,0x62,0xae,0x28,0x64,0x42,0xae,
-0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x90,0x64,0x44,0x8e,
-0x94,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,
-0x0a,0x18,0x82,0x00,0x90,0x64,0x43,0xae,0x90,0x64,0xe2,0x8e,0x00,0x00,0x00,0x00,
-0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,
-0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,
-0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00,
-0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x5a,0x00,0xa0,0x12,0x24,0x64,0xe2,0xae,
-0xec,0x63,0xf1,0xa2,0x68,0x15,0xc2,0x26,0x24,0x64,0x46,0x8c,0x90,0x64,0x45,0x8c,
-0x03,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0x04,0x00,0x04,0x8e,0x14,0x00,0x03,0x8e,0x08,0x00,0x05,0x8e,0xff,0xe0,0x02,0x3c,
-0x1f,0x00,0x84,0x30,0x42,0x1a,0x03,0x00,0xff,0xff,0x42,0x34,0x00,0x26,0x04,0x00,
-0x24,0x28,0xa2,0x00,0x3f,0x00,0x63,0x30,0x25,0x28,0xa4,0x00,0x0c,0x00,0x63,0x28,
-0x06,0x00,0x60,0x14,0x21,0x20,0xa0,0x00,0x00,0x00,0x02,0x96,0x00,0x00,0x00,0x00,
-0xfd,0x0f,0x42,0x28,0x08,0x00,0x40,0x14,0x82,0x11,0x05,0x00,0xff,0xdf,0x02,0x3c,
-0xff,0xff,0x42,0x34,0x24,0x28,0x82,0x00,0x00,0x40,0x03,0x3c,0x25,0x20,0xa3,0x00,
-0x21,0x28,0x80,0x00,0x82,0x11,0x05,0x00,0x01,0x00,0x42,0x30,0xa6,0xff,0x40,0x10,
-0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c,0x0d,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,
-0x08,0x00,0x04,0xae,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,
-0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,
-0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,
-0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0xa8,0xff,0x23,0x16,0x00,0x00,0x00,0x00,
-0x22,0x00,0xa0,0x12,0x68,0x15,0xc2,0x26,0xec,0x63,0x43,0x90,0x41,0x00,0xe4,0x34,
-0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa4,0x8c,
-0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,
-0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
-0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34,0x25,0x20,0x82,0x00,
-0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,
-0xfc,0x4a,0xa4,0xac,0x65,0x03,0x00,0x08,0xe8,0x63,0xf1,0xa2,0xe8,0x63,0x43,0x90,
-0x40,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xc5,0x26,
-0xfc,0x4a,0xa4,0x8c,0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34,
-0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa4,0xac,0xc0,0xff,0xbd,0x27,0x2c,0x00,0xb5,0xaf,
-0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x02,0x80,0x06,0x3c,0x7c,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x18,0x03,0x42,0x34,0x78,0x0f,0x63,0x24,0x10,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
-0x21,0xa8,0x00,0x00,0x03,0x00,0x80,0x10,0xdf,0x00,0xa2,0x30,0xef,0x00,0xa2,0x30,
-0x01,0x00,0x15,0x24,0x7c,0x7e,0xc2,0xa0,0x7c,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
-0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c,0x68,0x15,0xd2,0x26,
-0x21,0x98,0x40,0x00,0x02,0x80,0x14,0x3c,0x19,0x04,0x00,0x08,0x21,0xb8,0x40,0x02,
-0x24,0x10,0xa2,0x00,0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,
-0x15,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,
-0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xca,0x7d,0x84,0x96,
-0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xca,0x7d,0x84,0xa6,
-0xca,0x7d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x5a,0x00,0x23,0x12,
-0x00,0x00,0x00,0x00,0x30,0x64,0x42,0x8e,0x9c,0x64,0x50,0x8e,0x04,0x00,0x04,0x24,
-0x00,0x00,0x62,0xae,0x34,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x9c,0x64,0x44,0x8e,0xa0,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,
-0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x9c,0x64,0x43,0xae,
-0x9c,0x64,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,
-0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,
-0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,
-0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,
-0x59,0x00,0xa0,0x12,0x30,0x64,0xe2,0xae,0xf4,0x63,0xf1,0xa2,0x68,0x15,0xc2,0x26,
-0x30,0x64,0x46,0x8c,0x9c,0x64,0x45,0x8c,0x04,0x00,0x04,0x24,0x20,0x00,0x07,0x24,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x00,0x04,0x8e,0x14,0x00,0x03,0x8e,
-0x08,0x00,0x05,0x8e,0xff,0xe0,0x02,0x3c,0x1f,0x00,0x84,0x30,0x42,0x1a,0x03,0x00,
-0xff,0xff,0x42,0x34,0x00,0x26,0x04,0x00,0x24,0x28,0xa2,0x00,0x3f,0x00,0x63,0x30,
-0x25,0x28,0xa4,0x00,0x0c,0x00,0x63,0x28,0x06,0x00,0x60,0x14,0x21,0x20,0xa0,0x00,
-0x00,0x00,0x02,0x96,0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x08,0x00,0x40,0x14,
-0x82,0x11,0x05,0x00,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x28,0x82,0x00,
-0x00,0x40,0x03,0x3c,0x25,0x20,0xa3,0x00,0x21,0x28,0x80,0x00,0x82,0x11,0x05,0x00,
-0x01,0x00,0x42,0x30,0xa6,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c,
-0x15,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x08,0x00,0x04,0xae,0x0b,0x10,0x75,0x00,
-0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,
-0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,
-0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,
-0xa8,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x21,0x00,0xa0,0x12,0x68,0x15,0xc2,0x26,
-0xf4,0x63,0x43,0x90,0x43,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x3b,0x04,0x00,0x08,0xf0,0x63,0xf1,0xa2,
-0xf0,0x63,0x43,0x90,0x42,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x2c,0x00,0xb5,0xaf,
-0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x02,0x80,0x06,0x3c,0x7c,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x18,0x03,0x42,0x34,0xc8,0x12,0x63,0x24,0x01,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
-0x21,0xa8,0x00,0x00,0x03,0x00,0x80,0x10,0xf7,0x00,0xa2,0x30,0xfe,0x00,0xa2,0x30,
-0x01,0x00,0x15,0x24,0x7c,0x7e,0xc2,0xa0,0x7c,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
-0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c,0x68,0x15,0xd2,0x26,0x21,0x98,0x40,0x00,
-0x02,0x80,0x14,0x3c,0xf8,0x04,0x00,0x08,0x21,0xb8,0x40,0x02,0x00,0x00,0x02,0x96,
-0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x54,0x00,0x40,0x10,0xff,0xdf,0x02,0x3c,
-0x00,0x20,0x02,0x3c,0x25,0x28,0xa2,0x00,0x82,0x11,0x05,0x00,0x01,0x00,0x42,0x30,
-0x57,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,
-0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,0x1d,0x00,0xe2,0x34,
-0x04,0x00,0x43,0x24,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,
-0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,
-0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,
-0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x53,0x00,0x23,0x12,0x00,0x00,0x00,0x00,
-0x3c,0x64,0x42,0x8e,0xa8,0x64,0x50,0x8e,0x05,0x00,0x04,0x24,0x00,0x00,0x62,0xae,
-0x40,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xa8,0x64,0x44,0x8e,0xac,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,
-0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xa8,0x64,0x43,0xae,0xa8,0x64,0xe2,0x8e,
-0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,
-0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
-0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12,
-0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x52,0x00,0xa0,0x12,
-0x3c,0x64,0xe2,0xae,0x04,0x64,0xf1,0xa2,0x68,0x15,0xc2,0x26,0x3c,0x64,0x46,0x8c,
-0xa8,0x64,0x45,0x8c,0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xa0,0xaf,0x14,0x00,0x03,0x8e,0x04,0x00,0x04,0x8e,0x08,0x00,0x05,0x8e,
-0x42,0x1a,0x03,0x00,0xff,0xe0,0x02,0x3c,0x1f,0x00,0x84,0x30,0x3f,0x00,0x63,0x30,
-0xff,0xff,0x42,0x34,0x24,0x28,0xa2,0x00,0x00,0x26,0x04,0x00,0x0c,0x00,0x63,0x28,
-0xaa,0xff,0x60,0x10,0x25,0x28,0xa4,0x00,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x24,0x10,0xa2,0x00,0x00,0x40,0x03,0x3c,0x25,0x28,0x43,0x00,0x82,0x11,0x05,0x00,
-0x01,0x00,0x42,0x30,0xad,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c,
-0x1d,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,
-0x02,0x00,0x03,0x24,0x08,0x00,0x05,0xae,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,
-0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,
-0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,
-0xaf,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x21,0x00,0xa0,0x12,0x68,0x15,0xc2,0x26,
-0x04,0x64,0x43,0x90,0x45,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x1a,0x05,0x00,0x08,0xf8,0x63,0xf1,0xa2,
-0xf8,0x63,0x43,0x90,0x44,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x2c,0x00,0xb5,0xaf,
-0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x02,0x80,0x06,0x3c,0x7c,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x18,0x03,0x42,0x34,0x28,0x16,0x63,0x24,0x02,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
-0x21,0xa8,0x00,0x00,0x03,0x00,0x80,0x10,0xfb,0x00,0xa2,0x30,0xfd,0x00,0xa2,0x30,
-0x01,0x00,0x15,0x24,0x7c,0x7e,0xc2,0xa0,0x7c,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
-0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c,0x68,0x15,0xd2,0x26,0x21,0x98,0x40,0x00,
-0x02,0x80,0x14,0x3c,0xd0,0x05,0x00,0x08,0x21,0xb8,0x40,0x02,0x00,0x00,0x02,0x96,
-0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x54,0x00,0x40,0x10,0xff,0xdf,0x02,0x3c,
-0x00,0x20,0x02,0x3c,0x25,0x28,0xa2,0x00,0x82,0x11,0x05,0x00,0x01,0x00,0x42,0x30,
-0x57,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,
-0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,0x25,0x00,0xe2,0x34,
-0x04,0x00,0x43,0x24,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,
-0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,
-0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,
-0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x53,0x00,0x23,0x12,0x00,0x00,0x00,0x00,
-0x48,0x64,0x42,0x8e,0xb4,0x64,0x50,0x8e,0x06,0x00,0x04,0x24,0x00,0x00,0x62,0xae,
-0x4c,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xb4,0x64,0x44,0x8e,0xb8,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,
-0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xb4,0x64,0x43,0xae,0xb4,0x64,0xe2,0x8e,
-0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,
-0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
-0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12,
-0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x52,0x00,0xa0,0x12,
-0x48,0x64,0xe2,0xae,0x00,0x64,0xf1,0xa2,0x68,0x15,0xc2,0x26,0x48,0x64,0x46,0x8c,
-0xb4,0x64,0x45,0x8c,0x06,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xa0,0xaf,0x14,0x00,0x03,0x8e,0x04,0x00,0x04,0x8e,0x08,0x00,0x05,0x8e,
-0x42,0x1a,0x03,0x00,0xff,0xe0,0x02,0x3c,0x1f,0x00,0x84,0x30,0x3f,0x00,0x63,0x30,
-0xff,0xff,0x42,0x34,0x24,0x28,0xa2,0x00,0x00,0x26,0x04,0x00,0x0c,0x00,0x63,0x28,
-0xaa,0xff,0x60,0x10,0x25,0x28,0xa4,0x00,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x24,0x10,0xa2,0x00,0x00,0x40,0x03,0x3c,0x25,0x28,0x43,0x00,0x82,0x11,0x05,0x00,
-0x01,0x00,0x42,0x30,0xad,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c,
-0x25,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,
-0x02,0x00,0x03,0x24,0x08,0x00,0x05,0xae,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,
-0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,
-0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,
-0xaf,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x21,0x00,0xa0,0x12,0x68,0x15,0xc2,0x26,
-0x00,0x64,0x43,0x90,0x47,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x60,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0xf2,0x05,0x00,0x08,0xfc,0x63,0xf1,0xa2,
-0xfc,0x63,0x43,0x90,0x46,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x60,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x88,0x19,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x05,0x3c,0x68,0x15,0xa5,0x24,
-0x04,0x4b,0xa2,0x8c,0xfc,0x4a,0xa4,0x8c,0x00,0x08,0x03,0x3c,0x24,0x10,0x43,0x00,
-0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,
-0xfc,0x4a,0xa4,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27,
-0x18,0x03,0x83,0x34,0xe4,0x19,0x42,0x24,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,
-0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x02,0x80,0x02,0x3c,0x2a,0xb0,0x03,0x3c,0x68,0x15,0x51,0x24,0xb0,0x03,0x93,0x34,
-0x2c,0x00,0x77,0x34,0x02,0x80,0x15,0x3c,0x02,0x80,0x16,0x3c,0x9c,0x06,0x00,0x08,
-0x02,0x80,0x1e,0x3c,0x14,0x64,0x26,0x92,0xe4,0x64,0x25,0x8e,0x00,0x32,0x06,0x00,
-0x21,0x30,0xc2,0x00,0x78,0x64,0x26,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0xe4,0x64,0x30,0x8e,0x0a,0x00,0x04,0x24,0x21,0x90,0x00,0x00,0x00,0x00,0x70,0xae,
-0x4d,0x01,0x00,0x0c,0xff,0xff,0x10,0x32,0x02,0x80,0x02,0x3c,0x25,0x80,0x02,0x02,
-0x0c,0x00,0x05,0x92,0x02,0x00,0x04,0x92,0xff,0x00,0x02,0x24,0xff,0x00,0xa3,0x30,
-0x04,0x00,0x62,0x10,0x21,0x80,0x04,0x02,0x00,0x00,0x63,0xae,0x01,0x00,0x12,0x24,
-0x14,0x64,0x25,0xa2,0x88,0x96,0xb0,0xae,0x21,0x28,0x00,0x02,0x02,0x00,0xa2,0x90,
-0x08,0x00,0x10,0x26,0x21,0x20,0x00,0x02,0xff,0x00,0x42,0x30,0x00,0x00,0x62,0xae,
-0x03,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x63,0xae,
-0x00,0x00,0x72,0xae,0x03,0x00,0xa2,0x90,0x84,0x96,0xc3,0x92,0x02,0x00,0xa2,0x90,
-0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,0x2c,0x00,0x42,0x28,0x11,0x00,0x40,0x10,
-0x08,0x00,0x02,0x24,0x03,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,0x7f,0x00,0x42,0x30,
-0x84,0x96,0xc2,0xa2,0x02,0x00,0xa3,0x90,0x02,0x80,0x02,0x3c,0x74,0x84,0x42,0x24,
-0xff,0x00,0x63,0x30,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x04,0x00,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x09,0xf8,0x40,0x00,0x80,0x96,0xc2,0xaf,0x21,0xa0,0x40,0x00,
-0x08,0x00,0x02,0x24,0x0a,0x00,0x04,0x24,0x05,0x00,0x82,0x12,0x00,0x01,0x07,0x24,
-0x01,0x00,0x02,0x24,0x02,0x00,0x03,0x24,0x01,0x00,0xe2,0xa2,0x01,0x00,0xe3,0xa2,
-0xbc,0xff,0x40,0x16,0x20,0x10,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xfc,0x4a,0x22,0x8e,0x00,0x04,0x03,0x3c,
-0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x3c,0x00,0xbf,0x8f,
-0xfc,0x4a,0x22,0xae,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,
-0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
-0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,
-0xc8,0xff,0xbd,0x27,0xff,0xff,0xa8,0x30,0x02,0x80,0x02,0x3c,0x25,0x40,0x02,0x01,
-0x30,0x00,0xb6,0xaf,0x20,0x00,0xb2,0xaf,0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,
-0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x00,0x00,0x03,0x8d,0xff,0xff,0xd2,0x30,0x21,0xb0,0xa0,0x00,0x00,0xc0,0x02,0x24,
-0x08,0x00,0x45,0x26,0x04,0x00,0x06,0x8d,0x24,0x18,0x62,0x00,0xff,0x3f,0xa5,0x30,
-0xf0,0xff,0x02,0x3c,0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
-0x00,0x80,0x05,0x3c,0x25,0x18,0x65,0x00,0xff,0x01,0xc6,0x34,0x00,0x00,0x03,0xad,
-0x04,0x00,0x06,0xad,0x21,0x48,0x80,0x00,0xff,0xff,0xe7,0x30,0x18,0x00,0x12,0xa5,
-0x1a,0x00,0x07,0xa1,0x18,0x00,0x03,0x8d,0xff,0x7f,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x24,0x18,0x62,0x00,0x02,0x80,0x15,0x3c,0x18,0x00,0x03,0xad,0x68,0x15,0xa5,0x26,
-0xd6,0x63,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x24,0xd6,0x63,0xa2,0xa0,
-0x18,0x00,0x04,0x8d,0xff,0x80,0x02,0x3c,0x20,0x00,0x45,0x26,0xff,0xff,0x42,0x34,
-0x7f,0x00,0x63,0x30,0xff,0xff,0xb2,0x30,0x24,0x20,0x82,0x00,0x00,0x1e,0x03,0x00,
-0x25,0xb0,0x02,0x3c,0xc0,0x00,0x42,0x34,0x25,0x20,0x83,0x00,0x07,0x00,0x45,0x32,
-0x18,0x00,0x04,0xad,0x00,0x00,0x52,0xa4,0x03,0x00,0xa0,0x10,0xff,0xff,0x42,0x32,
-0x08,0x00,0x42,0x26,0xff,0xff,0x42,0x30,0x68,0x15,0xb4,0x26,0x54,0x65,0x86,0x8e,
-0x58,0x65,0x90,0x8e,0xf8,0xff,0x52,0x30,0x21,0x10,0xd2,0x00,0x2b,0x10,0x02,0x02,
-0x31,0x00,0x40,0x10,0xff,0x00,0x33,0x31,0x23,0x80,0x06,0x02,0x21,0x28,0xc0,0x02,
-0xff,0xff,0x07,0x32,0x01,0x00,0x11,0x24,0x21,0x20,0x60,0x02,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xb1,0xaf,0x23,0x18,0x50,0x02,0xff,0xff,0x72,0x30,0x22,0x10,0x02,0x3c,
-0x21,0x10,0x42,0x02,0x21,0x20,0x60,0x02,0x4d,0x01,0x00,0x0c,0x54,0x65,0x82,0xae,
-0x21,0x28,0xd0,0x02,0x21,0x38,0x40,0x02,0x21,0x20,0x60,0x02,0x10,0x00,0xb1,0xaf,
-0x22,0x10,0x06,0x3c,0x10,0x01,0x00,0x0c,0x68,0x15,0xb1,0x26,0x54,0x65,0x23,0x8e,
-0x25,0xb0,0x10,0x3c,0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,
-0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x54,0x65,0x25,0x8e,0xec,0x00,0x02,0x36,
-0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36,
-0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f,
-0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x21,0x28,0xc0,0x02,0x21,0x20,0x60,0x02,
-0x21,0x38,0x40,0x02,0x01,0x00,0x02,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa2,0xaf,
-0x54,0x65,0x83,0x8e,0x68,0x15,0xb1,0x26,0x25,0xb0,0x10,0x3c,0x21,0x18,0x72,0x00,
-0x54,0x65,0x83,0xae,0x54,0x65,0x23,0x8e,0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,
-0x00,0x00,0x43,0xac,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x54,0x65,0x25,0x8e,
-0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90,
-0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0,
-0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
-0x25,0xb0,0x02,0x3c,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
-0xbf,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x21,0x28,0x00,0x00,0x08,0x00,0x06,0x24,
-0x04,0x00,0x63,0x2c,0x12,0x00,0x60,0x14,0x21,0x88,0x80,0x00,0x00,0x60,0x02,0x40,
-0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,
-0x00,0x7b,0x63,0x24,0x04,0x00,0x64,0x8c,0x00,0x00,0x23,0xae,0x04,0x00,0x71,0xac,
-0x00,0x00,0x91,0xac,0x04,0x00,0x24,0xae,0x00,0x60,0x82,0x40,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0x08,0x00,0x82,0x94,0x02,0x80,0x04,0x3c,0x97,0x45,0x00,0x0c,0x25,0x20,0x44,0x00,
-0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x08,0x00,0x25,0x8e,0x0c,0x00,0x26,0x96,0x14,0x00,0x27,0x96,0xf0,0x06,0x00,0x0c,
-0x09,0x00,0x04,0x24,0x04,0x00,0x23,0x8e,0x00,0x00,0x22,0x8e,0x21,0x20,0x20,0x02,
-0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,0x00,0x00,0x31,0xae,0xbd,0x4e,0x00,0x0c,
-0x04,0x00,0x31,0xae,0x00,0x60,0x90,0x40,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x47,0x24,0x8c,0x64,0xe3,0x90,0xff,0xff,0xa5,0x30,0x09,0x00,0xa3,0x10,
-0x21,0x20,0xc0,0x00,0xfc,0x64,0xe2,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0xc2,0xac,
-0x06,0x65,0xe3,0x94,0x0e,0x00,0x02,0x24,0x14,0x00,0xc2,0xac,0x8b,0x07,0x00,0x08,
-0x0c,0x00,0xc3,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0xd0,0xff,0xbd,0x27,0x4c,0x1f,0x63,0x24,0x18,0x03,0x42,0x34,
-0x28,0x00,0xbf,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
-0x18,0x00,0xb0,0xaf,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x36,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
-0x02,0x80,0x13,0x3c,0x68,0x15,0x66,0x26,0xc0,0x18,0x03,0x00,0x5c,0x65,0xc5,0x8c,
-0x23,0xb0,0x04,0x3c,0xf0,0x07,0x63,0x30,0xff,0x1f,0x02,0x3c,0x21,0x18,0x64,0x00,
-0xff,0xff,0x42,0x34,0x24,0x20,0x62,0x00,0x23,0x88,0x85,0x00,0x2b,0x38,0x85,0x00,
-0x00,0x04,0x22,0x26,0x00,0x65,0xc3,0x8c,0x0b,0x88,0x47,0x00,0x01,0x04,0x25,0x2e,
-0xfc,0x64,0xc3,0xac,0x60,0x65,0xc4,0xac,0x06,0x65,0xc0,0xa4,0x11,0x00,0xa0,0x14,
-0x05,0x65,0xc0,0xa0,0x00,0xfc,0x83,0x24,0x23,0x10,0x02,0x3c,0x0b,0x18,0x87,0x00,
-0xff,0x03,0x42,0x34,0x2b,0x10,0x43,0x00,0x33,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
-0x23,0x88,0x83,0x00,0x2b,0x10,0x83,0x00,0x5c,0x65,0xc3,0xac,0x03,0x00,0x40,0x10,
-0x01,0x04,0x25,0x2e,0x00,0x04,0x31,0x26,0x01,0x04,0x25,0x2e,0x0e,0x00,0xa0,0x10,
-0x68,0x15,0x70,0x26,0x68,0x15,0x70,0x26,0x60,0x65,0x03,0x8e,0x5c,0x65,0x04,0x8e,
-0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x25,0x00,0x40,0x14,0x2b,0x10,0x64,0x00,
-0x51,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0x80,0x00,0x03,0x24,0xd0,0x03,0x42,0x34,
-0x00,0x00,0x43,0xac,0x68,0x15,0x70,0x26,0x5c,0x65,0x03,0x96,0x2a,0xb0,0x02,0x3c,
-0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,0x8f,0x10,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x06,0x65,0x03,0x96,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
-0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0xfc,0x4a,0x02,0x8e,0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,
-0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,0xfc,0x4a,0x02,0xae,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x00,0x08,0x00,0x08,0x00,0xfc,0x63,0x24,
-0xfc,0x64,0x05,0x8e,0x21,0x30,0x80,0x00,0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x64,0x03,0x8e,0x06,0x65,0x05,0x96,
-0x5c,0x65,0x02,0x8e,0x21,0x18,0x71,0x00,0x21,0x28,0x25,0x02,0x21,0x10,0x51,0x00,
-0x09,0x00,0x04,0x24,0x5c,0x65,0x02,0xae,0xfc,0x64,0x03,0xae,0x4d,0x01,0x00,0x0c,
-0x06,0x65,0x05,0xa6,0x68,0x15,0x70,0x26,0x5c,0x65,0x03,0x96,0x2a,0xb0,0x02,0x3c,
-0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,0x8f,0x10,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x06,0x65,0x03,0x96,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
-0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0xfc,0x4a,0x02,0x8e,0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,
-0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,0xfc,0x4a,0x02,0xae,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x64,0x65,0x02,0x8e,0xfc,0x64,0x05,0x8e,
-0x21,0x30,0x80,0x00,0x23,0x88,0x44,0x00,0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x64,0x03,0x8e,0x06,0x65,0x02,0x96,
-0x60,0x65,0x12,0x96,0x21,0x18,0x71,0x00,0x21,0x10,0x22,0x02,0x23,0x10,0x11,0x3c,
-0xfc,0x64,0x03,0xae,0x06,0x65,0x02,0xa6,0x06,0x00,0x40,0x16,0x5c,0x65,0x11,0xae,
-0x09,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,0x68,0x15,0x70,0x26,0x46,0x08,0x00,0x08,
-0x00,0x00,0x00,0x00,0x4d,0x01,0x00,0x0c,0x09,0x00,0x04,0x24,0xfc,0x64,0x05,0x8e,
-0x09,0x00,0x04,0x24,0x23,0x10,0x06,0x3c,0x21,0x38,0x40,0x02,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xa0,0xaf,0xfc,0x64,0x03,0x8e,0x06,0x65,0x02,0x96,0x21,0x20,0x51,0x02,
-0x21,0x18,0x72,0x00,0x21,0x10,0x42,0x02,0x5c,0x65,0x04,0xae,0x09,0x00,0x04,0x24,
-0xfc,0x64,0x03,0xae,0x75,0x08,0x00,0x08,0x06,0x65,0x02,0xa6,0x02,0x80,0x09,0x3c,
-0x68,0x15,0x28,0x25,0xdc,0x63,0x06,0x8d,0xff,0xff,0x02,0x34,0x3f,0x00,0xc2,0x10,
-0x21,0x38,0x80,0x00,0x2b,0x10,0xc7,0x00,0x30,0x00,0x40,0x10,0x02,0x19,0x06,0x00,
-0x21,0x10,0xc7,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0xdc,0x63,0x06,0xad,
-0x68,0x15,0x26,0x25,0x04,0x40,0xc4,0x8c,0xe0,0x63,0x02,0xad,0xff,0xff,0x02,0x34,
-0x2f,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x87,0x00,0x1f,0x00,0x40,0x10,
-0x02,0x19,0x04,0x00,0x21,0x10,0x87,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x44,0x24,
-0x04,0x40,0xc4,0xac,0xe0,0x63,0xc2,0xac,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x68,0x15,0x23,0x25,0x80,0x10,0x02,0x00,
-0x21,0x28,0x43,0x00,0x68,0x51,0xa6,0x8c,0x00,0x21,0x07,0x00,0xff,0xff,0xc2,0x38,
-0x0a,0x30,0x82,0x00,0x2b,0x18,0xc7,0x00,0x07,0x00,0x60,0x10,0x21,0x10,0xc7,0x00,
-0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0x68,0x51,0xa6,0xac,
-0x08,0x00,0xe0,0x03,0x6c,0x51,0xa2,0xac,0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,
-0x68,0x51,0xa2,0xac,0x08,0x00,0xe0,0x03,0x6c,0x51,0xa2,0xac,0x21,0x10,0x87,0x00,
-0x23,0x10,0x43,0x00,0xa5,0x08,0x00,0x08,0x04,0x40,0xc2,0xac,0x21,0x10,0xc7,0x00,
-0x68,0x15,0x26,0x25,0x04,0x40,0xc4,0x8c,0x23,0x10,0x43,0x00,0xdc,0x63,0x02,0xad,
-0xe0,0x63,0x02,0xad,0xff,0xff,0x02,0x34,0xd4,0xff,0x82,0x14,0x2b,0x10,0x87,0x00,
-0x00,0x21,0x07,0x00,0x9e,0x08,0x00,0x08,0x04,0x40,0xc4,0xac,0x00,0x31,0x04,0x00,
-0x91,0x08,0x00,0x08,0xdc,0x63,0x06,0xad,0x63,0x00,0x82,0x24,0x77,0x00,0x42,0x2c,
-0x00,0x00,0x85,0x28,0x04,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x64,0x00,0x82,0x24,
-0x64,0x00,0x03,0x24,0x0b,0x18,0x45,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0x0c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,
-0x17,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x24,0x08,0x42,0x34,0x00,0x00,0x43,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x02,0x63,0x30,0x16,0x00,0x60,0x14,0x01,0x00,0x02,0x24,
-0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x82,0x21,0x03,0x00,0x28,0x00,0x82,0x10,
-0xf5,0xff,0x02,0x24,0x02,0x00,0x82,0x28,0x39,0x00,0x40,0x14,0x02,0x00,0x02,0x24,
-0x2e,0x00,0x82,0x10,0xe9,0xff,0x02,0x24,0x03,0x00,0x02,0x24,0x24,0x00,0x82,0x10,
-0x3e,0x00,0x63,0x30,0x05,0x00,0xc4,0x24,0xd2,0x08,0x00,0x08,0x00,0x00,0x00,0x00,
-0x04,0x00,0xa4,0x90,0x00,0x00,0x00,0x00,0x42,0x20,0x04,0x00,0xd2,0x08,0x00,0x08,
-0x96,0xff,0x84,0x24,0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x60,0x00,0x64,0x30,
-0x42,0x21,0x04,0x00,0x0e,0x00,0x82,0x10,0x1f,0x00,0x62,0x30,0x02,0x00,0x82,0x28,
-0x1d,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x14,0x00,0x82,0x10,0x1f,0x00,0x62,0x30,
-0x03,0x00,0x02,0x24,0xeb,0xff,0x82,0x14,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00,
-0xdd,0xff,0x03,0x24,0x23,0x30,0x62,0x00,0xf6,0x08,0x00,0x08,0x05,0x00,0xc4,0x24,
-0x40,0x10,0x02,0x00,0xf5,0xff,0x03,0x24,0x0e,0x09,0x00,0x08,0x23,0x30,0x62,0x00,
-0x3e,0x00,0x63,0x30,0x23,0x30,0x43,0x00,0xf6,0x08,0x00,0x08,0x05,0x00,0xc4,0x24,
-0xdd,0xff,0x02,0x24,0x16,0x09,0x00,0x08,0x23,0x30,0x43,0x00,0x40,0x10,0x02,0x00,
-0xe9,0xff,0x03,0x24,0x0e,0x09,0x00,0x08,0x23,0x30,0x62,0x00,0x3e,0x00,0x63,0x30,
-0x16,0x09,0x00,0x08,0x23,0x30,0x43,0x00,0xd2,0xff,0x80,0x14,0x1f,0x00,0x62,0x30,
-0x40,0x10,0x02,0x00,0xf8,0xff,0x03,0x24,0x0e,0x09,0x00,0x08,0x23,0x30,0x62,0x00,
-0xcc,0xff,0x80,0x14,0x3e,0x00,0x63,0x30,0xf8,0xff,0x02,0x24,0x16,0x09,0x00,0x08,
-0x23,0x30,0x43,0x00,0xa0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x4c,0x00,0xb5,0xaf,
-0x5c,0x00,0xbf,0xaf,0x58,0x00,0xbe,0xaf,0x54,0x00,0xb7,0xaf,0x50,0x00,0xb6,0xaf,
-0x48,0x00,0xb4,0xaf,0x44,0x00,0xb3,0xaf,0x40,0x00,0xb2,0xaf,0x3c,0x00,0xb1,0xaf,
-0x38,0x00,0xb0,0xaf,0x68,0x15,0x55,0x24,0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34,
-0x00,0x00,0x43,0x8c,0x44,0x65,0xa7,0x8e,0x00,0x00,0x00,0x00,0x33,0x00,0xe3,0x10,
-0x48,0x65,0xa3,0xae,0x2b,0x10,0x67,0x00,0xa8,0x00,0x40,0x14,0x2b,0x10,0xe3,0x00,
-0xd1,0x00,0x40,0x14,0x02,0x80,0x02,0x3c,0x68,0x15,0x44,0x24,0x18,0x65,0x83,0x94,
-0x02,0x80,0x02,0x3c,0x21,0x88,0x00,0x00,0x19,0x00,0x40,0x1a,0x25,0x98,0x62,0x00,
-0x21,0xb8,0x80,0x00,0x21,0xb0,0x80,0x00,0x01,0x00,0x14,0x24,0x21,0x20,0x00,0x00,
-0x21,0x80,0x93,0x00,0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00,0x07,0x00,0xa0,0x10,
-0x01,0x00,0x22,0x26,0x04,0x00,0x02,0x8e,0x00,0xf0,0x03,0x3c,0x00,0x20,0x04,0x3c,
-0x24,0x10,0x43,0x00,0x1e,0x00,0x44,0x10,0x06,0x00,0x22,0x26,0xff,0xff,0x51,0x30,
-0x82,0x16,0x05,0x00,0x01,0x00,0x42,0x30,0x34,0x00,0x54,0x10,0x00,0x00,0x00,0x00,
-0x80,0x20,0x11,0x00,0x2a,0x10,0x92,0x00,0xed,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
-0xbd,0x4e,0x00,0x0c,0x21,0x20,0xc0,0x03,0x02,0x80,0x02,0x3c,0x08,0x04,0x44,0x24,
-0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0x31,0x1c,0x00,0x0c,0x21,0x38,0x00,0x00,
-0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34,0x00,0x00,0x43,0x8c,0x44,0x65,0xa7,0x8e,
-0x00,0x00,0x00,0x00,0xcf,0xff,0xe3,0x14,0x48,0x65,0xa3,0xae,0x25,0xb0,0x03,0x3c,
-0x00,0x01,0x62,0x34,0x00,0x00,0x47,0xac,0x66,0x09,0x00,0x08,0x44,0x65,0xa7,0xae,
-0xb0,0x4c,0xe2,0x8e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xb0,0x4c,0xe2,0xae,
-0x0c,0x00,0x04,0x8e,0x0c,0x00,0x02,0x24,0x3f,0x00,0x83,0x30,0x64,0x00,0x62,0x10,
-0x21,0x28,0xe0,0x02,0x3f,0x00,0x83,0x30,0x0d,0x00,0x02,0x24,0x59,0x00,0x62,0x10,
-0x00,0x00,0x00,0x00,0x3f,0x00,0x83,0x30,0x0e,0x00,0x02,0x24,0x04,0x00,0x62,0x10,
-0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x8e,0x5b,0x09,0x00,0x08,0x06,0x00,0x22,0x26,
-0xbc,0x4c,0xe2,0x8e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xbc,0x4c,0xe2,0xae,
-0x00,0x00,0x05,0x8e,0x5b,0x09,0x00,0x08,0x06,0x00,0x22,0x26,0x00,0x40,0xc2,0x8e,
-0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x42,0x30,0x05,0x00,0x54,0x10,
-0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,0x21,0x10,0x51,0x00,0x60,0x09,0x00,0x08,
-0xff,0xff,0x51,0x30,0x02,0x40,0xc2,0x92,0x00,0x00,0x00,0x00,0x1e,0x00,0x40,0x14,
-0x02,0x80,0x03,0x3c,0x04,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x03,0x00,
-0x0f,0x00,0x42,0x30,0x17,0x00,0x40,0x14,0x02,0x17,0x03,0x00,0x03,0x00,0x44,0x30,
-0x08,0x00,0x80,0x10,0x00,0xc0,0x02,0x3c,0x24,0x10,0x62,0x00,0x11,0x00,0x40,0x14,
-0x03,0x00,0x02,0x24,0x10,0x00,0x82,0x10,0x02,0x80,0x03,0x3c,0x0f,0x00,0x80,0x10,
-0x68,0x15,0x63,0x24,0x80,0x10,0x11,0x00,0x21,0x28,0x53,0x00,0xec,0xff,0xa3,0x8c,
-0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x20,0x00,0x02,0x00,0x00,0x43,0xac,
-0xdc,0x08,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0x8b,0x08,0x00,0x0c,
-0x21,0x28,0x00,0x00,0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0x02,0x40,0x62,0x90,
-0x00,0x00,0x00,0x00,0x85,0x00,0x54,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,
-0x68,0x15,0x84,0x24,0x02,0x40,0x83,0x90,0x02,0x00,0x02,0x24,0x68,0x00,0x62,0x10,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,0x4c,0x00,0x63,0x34,0x00,0x00,0x62,0x90,
-0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x08,0x00,0x54,0x10,0x02,0x80,0x04,0x3c,
-0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00,0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,
-0x21,0x10,0x51,0x00,0x60,0x09,0x00,0x08,0xff,0xff,0x51,0x30,0xd0,0x02,0x02,0x24,
-0x68,0x15,0x84,0x24,0xdc,0x63,0x82,0xac,0x00,0x00,0x05,0x8e,0xd3,0x09,0x00,0x08,
-0xc2,0x13,0x05,0x00,0xb8,0x4c,0xa2,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
-0xb8,0x4c,0xa2,0xac,0x0c,0x00,0x04,0x8e,0x86,0x09,0x00,0x08,0x3f,0x00,0x83,0x30,
-0xb4,0x4c,0xe2,0x8e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xb4,0x4c,0xe2,0xae,
-0x0c,0x00,0x04,0x8e,0x82,0x09,0x00,0x08,0x3f,0x00,0x83,0x30,0x4c,0x65,0xa2,0x8e,
-0xff,0xff,0x71,0x30,0x23,0x10,0x47,0x00,0xff,0xff,0x50,0x30,0x21,0x18,0x11,0x02,
-0xff,0xff,0x72,0x30,0xa1,0x4e,0x00,0x0c,0x21,0x20,0x40,0x02,0x76,0x00,0x40,0x10,
-0x21,0xf0,0x40,0x00,0x08,0x00,0x42,0x8c,0x44,0x65,0xa6,0x8e,0x21,0x38,0x00,0x02,
-0x21,0x18,0x52,0x00,0x21,0x28,0x40,0x00,0x08,0x00,0x04,0x24,0x14,0x65,0xa3,0xae,
-0x18,0x65,0xa2,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x4d,0x01,0x00,0x0c,
-0x08,0x00,0x04,0x24,0x18,0x65,0xa5,0x8e,0x25,0xb0,0x03,0x3c,0x24,0x10,0x02,0x3c,
-0x21,0x28,0xb0,0x00,0x00,0x01,0x70,0x34,0x00,0x00,0x02,0xae,0x21,0x38,0x20,0x02,
-0x08,0x00,0x04,0x24,0x24,0x10,0x06,0x3c,0x44,0x65,0xa2,0xae,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xa0,0xaf,0x48,0x65,0xa3,0x8e,0x08,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,
-0x44,0x65,0xa3,0xae,0x44,0x65,0xa2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xae,
-0x46,0x09,0x00,0x08,0x02,0x80,0x02,0x3c,0x23,0x10,0x67,0x00,0xff,0xff,0x52,0x30,
-0xa1,0x4e,0x00,0x0c,0x21,0x20,0x40,0x02,0x56,0x00,0x40,0x10,0x21,0xf0,0x40,0x00,
-0x08,0x00,0x42,0x8c,0x44,0x65,0xa6,0x8e,0x08,0x00,0x04,0x24,0x21,0x18,0x52,0x00,
-0x21,0x28,0x40,0x00,0x21,0x38,0x40,0x02,0x14,0x65,0xa3,0xae,0x18,0x65,0xa2,0xae,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x48,0x65,0xa3,0x8e,0x08,0x00,0x04,0x24,
-0x4d,0x01,0x00,0x0c,0x44,0x65,0xa3,0xae,0x44,0x65,0xa3,0x8e,0x25,0xb0,0x04,0x3c,
-0x00,0x01,0x82,0x34,0x00,0x00,0x43,0xac,0x46,0x09,0x00,0x08,0x02,0x80,0x02,0x3c,
-0x04,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x03,0x00,0x0f,0x00,0x42,0x30,
-0x08,0x00,0x42,0x28,0x93,0xff,0x40,0x10,0x02,0x17,0x03,0x00,0x03,0x00,0x42,0x30,
-0x90,0xff,0x40,0x14,0x80,0x10,0x11,0x00,0x21,0x28,0x53,0x00,0xec,0xff,0xa3,0x8c,
-0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x20,0x00,0x02,0x00,0x00,0x43,0xac,
-0xdc,0x08,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0x8b,0x08,0x00,0x0c,
-0x21,0x28,0x00,0x00,0xca,0x09,0x00,0x08,0x25,0xb0,0x03,0x3c,0x04,0x00,0x03,0x8e,
-0x00,0x00,0x00,0x00,0x02,0x14,0x03,0x00,0x0f,0x00,0x42,0x30,0x08,0x00,0x42,0x28,
-0x06,0x00,0x40,0x10,0x00,0xc0,0x02,0x3c,0x02,0x17,0x03,0x00,0x03,0x00,0x42,0x30,
-0x0c,0x00,0x40,0x10,0x80,0x10,0x11,0x00,0x00,0xc0,0x02,0x3c,0x24,0x10,0x62,0x00,
-0x6f,0xff,0x40,0x14,0x02,0x80,0x04,0x3c,0x02,0x17,0x03,0x00,0x03,0x00,0x42,0x30,
-0x03,0x00,0x03,0x24,0x6b,0xff,0x43,0x10,0x68,0x15,0x84,0x24,0x67,0xff,0x40,0x10,
-0x80,0x10,0x11,0x00,0x21,0x28,0x53,0x00,0xec,0xff,0xa3,0x8c,0x25,0xb0,0x02,0x3c,
-0xd4,0x02,0x42,0x34,0x21,0x20,0x00,0x02,0x00,0x00,0x43,0xac,0xdc,0x08,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0x8b,0x08,0x00,0x0c,0x21,0x28,0x00,0x00,
-0xc4,0x09,0x00,0x08,0x02,0x80,0x04,0x3c,0x25,0xb0,0x04,0x3c,0x44,0x44,0x02,0x3c,
-0xbc,0x02,0x83,0x34,0x44,0x44,0x42,0x34,0x00,0x00,0x62,0xac,0x67,0x09,0x00,0x08,
-0x02,0x80,0x02,0x3c,0x48,0x65,0xa5,0x8e,0x25,0xb0,0x04,0x3c,0x66,0x66,0x02,0x3c,
-0x00,0x01,0x83,0x34,0x66,0x66,0x42,0x34,0xbc,0x02,0x84,0x34,0x00,0x00,0x65,0xac,
-0x00,0x00,0x82,0xac,0x66,0x09,0x00,0x08,0x44,0x65,0xa5,0xae,0x00,0x60,0x02,0x40,
-0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,
-0xd8,0x8c,0x64,0xac,0x00,0x60,0x82,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x02,0x80,0x02,0x3c,0xd8,0x8c,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x18,0x03,0x42,0x34,0x10,0x2a,0x63,0x24,0x00,0x00,0x43,0xac,0x04,0x00,0x02,0x24,
-0x1e,0x00,0xa2,0x10,0x05,0x00,0xa2,0x2c,0x10,0x00,0x40,0x10,0x05,0x00,0x02,0x24,
-0x03,0x00,0x02,0x24,0x08,0x00,0xa2,0x10,0x00,0x19,0x04,0x00,0x80,0x10,0x04,0x00,
-0x21,0x10,0x44,0x00,0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,
-0x21,0x10,0x44,0x00,0x40,0x19,0x02,0x00,0xff,0xff,0x63,0x24,0xfe,0xff,0x60,0x14,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf3,0xff,0xa2,0x10,
-0x06,0x00,0x02,0x24,0xf2,0xff,0xa2,0x14,0x80,0x10,0x04,0x00,0x40,0x11,0x04,0x00,
-0x23,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x00,0x19,0x02,0x00,
-0x23,0x18,0x62,0x00,0x9a,0x0a,0x00,0x08,0x00,0x19,0x03,0x00,0x80,0x10,0x04,0x00,
-0x21,0x10,0x44,0x00,0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,
-0x21,0x10,0x44,0x00,0x9a,0x0a,0x00,0x08,0x00,0x19,0x02,0x00,0x02,0x80,0x02,0x3c,
-0xd8,0x8c,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
-0xcc,0x2a,0x63,0x24,0x00,0x00,0x43,0xac,0x05,0x00,0x02,0x24,0x10,0x00,0xa2,0x10,
-0x06,0x00,0xa2,0x2c,0x09,0x00,0x40,0x14,0x04,0x00,0x02,0x24,0x06,0x00,0x02,0x24,
-0x0f,0x00,0xa2,0x10,0x00,0x11,0x04,0x00,0xff,0xff,0x84,0x24,0xfe,0xff,0x80,0x14,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xfa,0xff,0xa2,0x14,
-0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0xc2,0x0a,0x00,0x08,0x40,0x20,0x02,0x00,
-0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0xc2,0x0a,0x00,0x08,0x80,0x20,0x02,0x00,
-0x23,0x10,0x44,0x00,0xc2,0x0a,0x00,0x08,0x40,0x20,0x02,0x00,0xff,0xff,0x85,0x30,
-0x21,0x30,0x00,0x00,0x25,0xb0,0x03,0x3c,0x2a,0xb0,0x04,0x3c,0xb4,0x00,0x63,0x34,
-0x01,0x00,0xa2,0x24,0x31,0x00,0x84,0x34,0x00,0x00,0x65,0xa0,0x00,0x00,0x85,0xa0,
-0xff,0xff,0x45,0x30,0x12,0x00,0xa0,0x10,0x01,0x00,0x03,0x24,0x28,0xb0,0x07,0x3c,
-0xe8,0x0a,0x00,0x08,0xff,0xff,0x08,0x24,0x00,0x00,0x83,0xa0,0x01,0x00,0x63,0x24,
-0xff,0xff,0x63,0x30,0x2b,0x10,0xa3,0x00,0x09,0x00,0x40,0x14,0x08,0x00,0xc6,0x24,
-0xf9,0xff,0x65,0x14,0x21,0x20,0xc7,0x00,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,
-0x2b,0x10,0xa3,0x00,0x00,0x00,0x88,0xa0,0xf9,0xff,0x40,0x10,0x08,0x00,0xc6,0x24,
-0x00,0x01,0xa2,0x2c,0x13,0x00,0x40,0x10,0x21,0x18,0xa0,0x00,0xff,0x00,0x08,0x24,
-0x28,0xb0,0x07,0x3c,0xfc,0x0a,0x00,0x08,0xff,0xff,0x09,0x24,0xff,0xff,0x43,0x30,
-0x00,0x00,0xa2,0xa0,0x00,0x01,0x62,0x2c,0x0a,0x00,0x40,0x10,0x08,0x00,0xc6,0x24,
-0x01,0x00,0x62,0x24,0xf9,0xff,0x68,0x14,0x21,0x28,0xc7,0x00,0x00,0x01,0x02,0x24,
-0xff,0xff,0x43,0x30,0x00,0x01,0x62,0x2c,0x00,0x00,0xa9,0xa0,0xf8,0xff,0x40,0x14,
-0x08,0x00,0xc6,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd8,0xff,0xbd,0x27,
-0x24,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
-0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x42,0x00,0x14,0x36,
-0xff,0xff,0x02,0x24,0x00,0x00,0x82,0xa2,0xd8,0x00,0x05,0x36,0x40,0x00,0x11,0x36,
-0xa8,0x00,0x13,0x36,0xa0,0x00,0x12,0x36,0x00,0x10,0x03,0x24,0xa4,0x00,0x10,0x36,
-0x00,0x80,0x02,0x3c,0x00,0x00,0x23,0xa6,0x00,0x00,0xa0,0xa0,0x00,0x00,0x40,0xae,
-0x00,0x00,0x00,0xae,0x00,0x00,0x62,0xae,0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,
-0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,0xfc,0x17,0x02,0x24,0x00,0x00,0xa3,0xa0,
-0x00,0x00,0x22,0xa6,0xd3,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x42,0x24,0x68,0x4b,0x45,0x8c,0x60,0x4b,0x43,0x8c,0x64,0x4b,0x44,0x8c,
-0xfc,0x37,0x02,0x24,0x00,0x00,0x43,0xae,0x00,0x00,0x04,0xae,0x00,0x00,0x65,0xae,
-0x00,0x00,0x22,0xa6,0x00,0x00,0x80,0xa2,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x24,0x00,0xbf,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
-0x28,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,
-0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
-0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x40,0x00,0x05,0x36,
-0x00,0x00,0xa2,0x94,0x24,0xfa,0x03,0x24,0xa8,0x00,0x13,0x36,0x24,0x10,0x43,0x00,
-0x00,0x00,0xa2,0xa4,0xa0,0x00,0x12,0x36,0xa4,0x00,0x10,0x36,0x00,0x00,0x55,0x8e,
-0x00,0x00,0x16,0x8e,0x00,0x00,0x71,0x8e,0x00,0x80,0x14,0x3c,0xfc,0x37,0x02,0x24,
-0x00,0x00,0x40,0xae,0xfd,0x00,0x04,0x24,0x00,0x00,0x00,0xae,0x21,0x88,0x34,0x02,
-0x00,0x00,0x74,0xae,0x00,0x00,0xa2,0xa4,0xd3,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x00,0x00,0x55,0xae,0x00,0x00,0x16,0xae,0x00,0x00,0x71,0xae,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,
-0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
-0xd0,0xff,0xbd,0x27,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,
-0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,
-0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x40,0x00,0x05,0x36,0x00,0x00,0xa2,0x94,
-0xaf,0xff,0x03,0x24,0xa8,0x00,0x13,0x36,0x24,0x10,0x43,0x00,0x00,0x00,0xa2,0xa4,
-0xa0,0x00,0x12,0x36,0xa4,0x00,0x10,0x36,0x00,0x00,0x55,0x8e,0x00,0x00,0x16,0x8e,
-0x00,0x00,0x71,0x8e,0x00,0x80,0x14,0x3c,0xfc,0x37,0x02,0x24,0x00,0x00,0x40,0xae,
-0xfd,0x00,0x04,0x24,0x00,0x00,0x00,0xae,0x21,0x88,0x34,0x02,0x00,0x00,0x74,0xae,
-0x00,0x00,0xa2,0xa4,0xd3,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xae,
-0x00,0x00,0x16,0xae,0x00,0x00,0x71,0xae,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,
-0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x04,0x3c,
-0x40,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0xd8,0xfd,0x03,0x24,0x24,0x10,0x43,0x00,
-0xfc,0x37,0x03,0x24,0x00,0x00,0x82,0xa4,0x00,0x00,0x83,0xa4,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x00,0x00,0x82,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x30,
-0x10,0x00,0x02,0x24,0x0c,0x00,0xc2,0x10,0x11,0x00,0xc3,0x28,0x06,0x00,0x60,0x10,
-0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x0d,0x00,0xc2,0x10,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x06,0x00,0xc2,0x10,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xa4,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x00,0x00,0x85,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x25,0xb0,0x02,0x3c,
-0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0xff,0xff,0xa5,0x24,0x00,0x2c,0x05,0x00,
-0xfd,0x00,0x63,0x30,0x03,0x2c,0x05,0x00,0xff,0xff,0x87,0x30,0x00,0x00,0x43,0xa0,
-0x1a,0x00,0xa0,0x04,0x00,0x00,0x00,0x00,0x21,0x30,0x40,0x00,0x07,0x10,0xa7,0x00,
-0x01,0x00,0x42,0x30,0xfd,0x00,0x64,0x30,0x00,0x00,0x42,0x38,0x02,0x00,0x63,0x34,
-0x0a,0x18,0x82,0x00,0x00,0x00,0xc3,0xa0,0x04,0x00,0x63,0x34,0x00,0x00,0xc3,0xa0,
-0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,
-0xfb,0x00,0x63,0x30,0x00,0x00,0xc3,0xa0,0x04,0x00,0x02,0x24,0xff,0xff,0x42,0x24,
-0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xff,0xff,0xa2,0x24,0x00,0x2c,0x02,0x00,
-0x03,0x2c,0x05,0x00,0xea,0xff,0xa1,0x04,0x07,0x10,0xa7,0x00,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
-0xff,0xff,0x84,0x24,0x00,0x24,0x04,0x00,0x03,0x24,0x04,0x00,0xff,0x00,0x65,0x30,
-0x1d,0x00,0x80,0x04,0x21,0x38,0x00,0x00,0x21,0x30,0x40,0x00,0x01,0x00,0x08,0x24,
-0x04,0x00,0xa5,0x34,0x00,0x00,0xc5,0xa0,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x45,0x30,0x01,0x00,0xa3,0x30,0x05,0x00,0x60,0x10,0x04,0x00,0x02,0x24,
-0x04,0x10,0x88,0x00,0x25,0x10,0x47,0x00,0xff,0xff,0x47,0x30,0x04,0x00,0x02,0x24,
-0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xfb,0x00,0xa5,0x30,
-0x00,0x00,0xc5,0xa0,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,
-0xff,0xff,0x42,0x24,0xff,0xff,0x82,0x24,0x00,0x24,0x02,0x00,0x03,0x24,0x04,0x00,
-0xe7,0xff,0x81,0x04,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,
-0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x25,0xb0,0x10,0x3c,0x0a,0x00,0x10,0x36,
-0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x00,0x00,0x02,0x92,0xff,0xff,0x91,0x30,
-0x03,0x00,0x05,0x24,0xc0,0x00,0x42,0x30,0x80,0x00,0x43,0x34,0x00,0x00,0x03,0xa2,
-0x04,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0xfb,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,
-0x08,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0x04,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,
-0xfb,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0xd7,0x0b,0x00,0x0c,0x06,0x00,0x04,0x24,
-0x42,0x20,0x11,0x00,0xd7,0x0b,0x00,0x0c,0x06,0x00,0x05,0x24,0xfd,0x0b,0x00,0x0c,
-0x10,0x00,0x04,0x24,0x00,0x00,0x03,0x92,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
-0xc0,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0xff,0xff,0xb1,0x30,
-0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x21,0x90,0xc0,0x00,
-0x0a,0x00,0x20,0x12,0xff,0xff,0x90,0x30,0x24,0x0c,0x00,0x0c,0x21,0x20,0x00,0x02,
-0xfe,0xff,0x23,0x26,0x02,0x00,0x04,0x26,0x00,0x00,0x42,0xa6,0xff,0xff,0x71,0x30,
-0xff,0xff,0x90,0x30,0xf8,0xff,0x20,0x16,0x02,0x00,0x52,0x26,0x1c,0x00,0xbf,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x0a,0x00,0x68,0x34,0x00,0x00,0x02,0x91,
-0xff,0xff,0xa5,0x30,0xff,0x00,0x84,0x30,0x1f,0x00,0xa0,0x10,0xff,0x00,0x47,0x30,
-0x21,0x48,0x00,0x01,0x0c,0x00,0x6c,0x34,0x0b,0x00,0x6b,0x34,0xc0,0xff,0x0a,0x24,
-0x21,0x68,0x00,0x01,0x25,0x10,0xea,0x00,0xff,0x00,0x47,0x30,0x00,0x00,0x64,0xa1,
-0x00,0x00,0x27,0xa1,0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00,0xff,0x00,0x47,0x30,
-0xc0,0x00,0xe3,0x30,0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x21,0x40,0xa0,0x01,
-0x00,0x00,0x02,0x91,0x00,0x00,0x00,0x00,0xff,0x00,0x47,0x30,0xc0,0x00,0xe3,0x30,
-0xfb,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x8d,0xfc,0xff,0xa3,0x24,
-0x04,0x00,0x84,0x24,0xff,0xff,0x65,0x30,0x00,0x00,0xc2,0xac,0xff,0x00,0x84,0x30,
-0xe8,0xff,0xa0,0x14,0x04,0x00,0xc6,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xff,0x00,0x84,0x30,0x21,0x68,0xe0,0x00,0xff,0xff,0xa5,0x30,0xc0,0x50,0x04,0x00,
-0x00,0x60,0x0c,0x40,0x01,0x00,0x81,0x35,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x00,0x00,0xc2,0x90,0x01,0x00,0xc3,0x90,0x25,0xb0,0x07,0x3c,0x00,0x14,0x02,0x00,
-0x25,0x28,0xa2,0x00,0x00,0x1e,0x03,0x00,0x01,0x80,0x08,0x3c,0x25,0x20,0xa3,0x00,
-0x40,0x02,0xe9,0x34,0x25,0x18,0x48,0x01,0x44,0x02,0xe7,0x34,0x00,0x00,0xe4,0xac,
-0x00,0x00,0x23,0xad,0x03,0x00,0xc2,0x90,0x02,0x00,0xc4,0x90,0x04,0x00,0xc3,0x90,
-0x05,0x00,0xc5,0x90,0x00,0x12,0x02,0x00,0x25,0x20,0x82,0x00,0x00,0x1c,0x03,0x00,
-0x01,0x00,0x4a,0x25,0x25,0x20,0x83,0x00,0x00,0x2e,0x05,0x00,0x25,0x40,0x48,0x01,
-0x25,0x20,0x85,0x00,0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25,0x00,0x00,0x28,0xad,
-0x01,0x80,0x0b,0x3c,0x21,0x40,0x00,0x00,0x21,0x10,0xa8,0x01,0x01,0x00,0x43,0x90,
-0x00,0x00,0x45,0x90,0x02,0x00,0x44,0x90,0x03,0x00,0x46,0x90,0x00,0x1a,0x03,0x00,
-0x25,0x28,0xa3,0x00,0x00,0x24,0x04,0x00,0x25,0x28,0xa4,0x00,0x00,0x36,0x06,0x00,
-0x04,0x00,0x08,0x25,0x25,0x10,0x4b,0x01,0x25,0x20,0xa6,0x00,0x10,0x00,0x03,0x2d,
-0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25,0x00,0x00,0x22,0xad,0xee,0xff,0x60,0x14,
-0x00,0x00,0x00,0x00,0x00,0x60,0x8c,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xff,0xff,0x84,0x30,0x42,0xb0,0x08,0x3c,0x80,0x10,0x04,0x00,0x21,0x10,0x48,0x00,
-0x04,0x00,0x46,0xac,0x00,0x00,0x07,0x91,0x40,0x18,0x04,0x00,0x03,0x00,0x06,0x24,
-0xff,0x00,0xe7,0x30,0x04,0x30,0x66,0x00,0x01,0x00,0x02,0x24,0x04,0x10,0x62,0x00,
-0x25,0x30,0xc7,0x00,0xff,0xff,0xa5,0x30,0x25,0x10,0x47,0x00,0x02,0x00,0xa0,0x14,
-0xff,0x00,0xc7,0x30,0xff,0x00,0x47,0x30,0x42,0xb0,0x02,0x3c,0x00,0x00,0x47,0xa0,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c,0x03,0x00,0x47,0x34,
-0x00,0x00,0xe3,0x90,0xff,0x00,0x84,0x30,0x04,0x00,0x84,0x24,0xff,0x00,0x65,0x30,
-0x01,0x00,0x02,0x24,0x04,0x30,0x82,0x00,0x07,0x18,0x85,0x00,0x25,0xb0,0x02,0x3c,
-0xe8,0x03,0x42,0x34,0x01,0x00,0x63,0x30,0x21,0x20,0xc0,0x00,0x00,0x00,0x45,0xa0,
-0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0xa0,0x08,0x00,0xe0,0x03,
-0x24,0x10,0x85,0x00,0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0xdc,0x8c,0x42,0x24,0x04,0x00,0x45,0x8c,
-0x00,0x00,0x82,0xac,0x04,0x00,0x44,0xac,0x00,0x00,0xa4,0xac,0x04,0x00,0x85,0xac,
-0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x14,0x00,0x83,0x90,
-0x01,0x00,0x02,0x24,0x08,0x00,0x86,0xac,0x18,0x00,0x85,0xac,0x00,0x00,0x84,0xac,
-0x03,0x00,0x62,0x10,0x04,0x00,0x84,0xac,0xed,0x0c,0x00,0x08,0x0c,0x00,0x80,0xac,
-0x0c,0x00,0x82,0x8c,0xed,0x0c,0x00,0x08,0x10,0x00,0x82,0xac,0x00,0x60,0x03,0x40,
-0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x04,0x00,0x85,0x8c,
-0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,0x04,0x00,0x45,0xac,
-0x00,0x00,0x84,0xac,0x04,0x00,0x84,0xac,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,
-0x20,0x00,0xb4,0xaf,0x14,0x00,0xb1,0xaf,0x2c,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,
-0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x80,0x16,0x3c,0x02,0x80,0x14,0x3c,
-0x02,0x80,0x11,0x3c,0x02,0x80,0x15,0x3c,0xc4,0x7d,0x24,0x8e,0x25,0xb0,0x02,0x3c,
-0x54,0x34,0xc3,0x26,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0xdc,0x8c,0x90,0x8e,
-0x18,0x00,0x80,0x10,0xdc,0x8c,0x82,0x26,0x15,0x00,0x02,0x12,0x00,0x00,0x00,0x00,
-0x21,0x98,0x40,0x00,0x01,0x00,0x12,0x24,0x14,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
-0x1d,0x00,0x52,0x10,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x03,0x8e,0xc4,0x7d,0x22,0x8e,0x00,0x00,0x00,0x00,0x23,0x20,0x62,0x00,
-0x2b,0x10,0x43,0x00,0x0e,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0xae,
-0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0xef,0xff,0x13,0x16,0x00,0x00,0x00,0x00,
-0xc4,0x7d,0x20,0xae,0x08,0x0c,0xa4,0x26,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,
-0x31,0x1c,0x00,0x0c,0x21,0x38,0x00,0x00,0x22,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,
-0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,0x00,0x00,0x00,0x00,
-0x3c,0x0d,0x00,0x08,0x0c,0x00,0x02,0xae,0x0c,0x00,0x03,0x8e,0xc4,0x7d,0x22,0x8e,
-0x00,0x00,0x00,0x00,0x23,0x20,0x62,0x00,0x2b,0x10,0x43,0x00,0xe7,0xff,0x40,0x14,
-0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,
-0x00,0x00,0x00,0x00,0x10,0x00,0x03,0x8e,0x3c,0x0d,0x00,0x08,0x0c,0x00,0x03,0xae,
-0xff,0x00,0xa5,0x30,0x25,0xb0,0x02,0x3c,0x21,0x28,0xa2,0x00,0xff,0x00,0x84,0x30,
-0x60,0x01,0xa4,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30,
-0x01,0x00,0x03,0x24,0x10,0x00,0x02,0x3c,0x04,0x18,0x83,0x00,0xf0,0x70,0x42,0x34,
-0x15,0x00,0x84,0x2c,0x06,0x00,0x80,0x10,0x24,0x28,0x62,0x00,0x0f,0x00,0x63,0x30,
-0x04,0x00,0xa0,0x14,0x01,0x00,0x02,0x24,0x02,0x00,0x60,0x14,0x02,0x00,0x02,0x24,
-0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0xa5,0x30,
-0x04,0x00,0xa2,0x2c,0x14,0x00,0x40,0x10,0xff,0x00,0x84,0x30,0x02,0x80,0x03,0x3c,
-0x8e,0x7d,0x62,0x90,0x00,0x00,0x00,0x00,0xef,0xff,0x42,0x24,0xff,0x00,0x42,0x30,
-0x02,0x00,0x42,0x2c,0x0e,0x00,0x40,0x10,0x02,0x00,0x03,0x24,0x24,0x00,0x83,0x10,
-0x0f,0x10,0x02,0x3c,0x03,0x00,0x82,0x28,0x14,0x00,0x40,0x10,0x03,0x00,0x02,0x24,
-0x01,0x00,0x02,0x24,0x2f,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x02,0x3c,
-0x08,0x00,0xe0,0x03,0xff,0xff,0x42,0x34,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x35,0x00,0x83,0x10,0x0f,0x1f,0x02,0x3c,0x03,0x00,0x82,0x28,0x16,0x00,0x40,0x10,
-0x03,0x00,0x02,0x24,0x01,0x00,0x02,0x24,0xf4,0xff,0x82,0x14,0x00,0x00,0x00,0x00,
-0x0f,0x1f,0x02,0x3c,0x08,0x00,0xe0,0x03,0x00,0x80,0x42,0x34,0xf0,0xff,0x82,0x14,
-0xff,0x1f,0x02,0x3c,0x01,0x00,0x02,0x24,0x29,0x00,0xa2,0x10,0x0f,0x10,0x02,0x3c,
-0x02,0x00,0xa2,0x28,0x1f,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x28,0x00,0xa3,0x10,
-0x00,0x00,0x00,0x00,0xe5,0xff,0xa4,0x14,0x00,0x00,0x00,0x00,0x0f,0x10,0x02,0x3c,
-0x08,0x00,0xe0,0x03,0x00,0xf0,0x42,0x34,0xe1,0xff,0x82,0x14,0xff,0x1f,0x02,0x3c,
-0x01,0x00,0x02,0x24,0x1c,0x00,0xa2,0x10,0x0f,0x00,0x02,0x3c,0x02,0x00,0xa2,0x28,
-0x0b,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x1c,0x00,0xa3,0x10,0x00,0x00,0x00,0x00,
-0xd6,0xff,0xa4,0x14,0x00,0x00,0x00,0x00,0x0f,0x00,0x02,0x3c,0x08,0x00,0xe0,0x03,
-0x00,0xf0,0x42,0x34,0x0f,0x10,0x02,0x3c,0x08,0x00,0xe0,0x03,0x00,0x80,0x42,0x34,
-0xce,0xff,0xa0,0x14,0x00,0x00,0x00,0x00,0x0f,0x00,0x02,0x3c,0x08,0x00,0xe0,0x03,
-0x15,0xf0,0x42,0x34,0xc9,0xff,0xa0,0x14,0x00,0x00,0x00,0x00,0x0f,0x10,0x02,0x3c,
-0x08,0x00,0xe0,0x03,0x15,0xf0,0x42,0x34,0x08,0x00,0xe0,0x03,0x00,0xf0,0x42,0x34,
-0x08,0x00,0xe0,0x03,0x10,0xf0,0x42,0x34,0x08,0x00,0xe0,0x03,0x10,0xf0,0x42,0x34,
-0x0f,0x10,0x02,0x3c,0x08,0x00,0xe0,0x03,0x05,0xf0,0x42,0x34,0x0f,0x00,0x02,0x3c,
-0x08,0x00,0xe0,0x03,0x05,0xf0,0x42,0x34,0xc0,0x40,0x04,0x00,0x21,0x18,0x04,0x01,
-0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,0x80,0x18,0x03,0x00,
-0x68,0x15,0x42,0x24,0x21,0x18,0x62,0x00,0x74,0x51,0x66,0x8c,0x21,0x38,0x60,0x00,
-0x7a,0x51,0x60,0xa0,0x7b,0x51,0x60,0xa0,0x1c,0x00,0x05,0x24,0xdf,0x0d,0x00,0x08,
-0x01,0x00,0x03,0x24,0x08,0x00,0xa0,0x04,0x21,0x10,0x04,0x01,0x04,0x10,0xa3,0x00,
-0x24,0x10,0xc2,0x00,0xfb,0xff,0x40,0x10,0xff,0xff,0xa5,0x24,0x01,0x00,0xa5,0x24,
-0x7a,0x51,0xe5,0xa0,0x21,0x10,0x04,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,
-0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x68,0x15,0x63,0x24,0x21,0x18,0x43,0x00,
-0x74,0x51,0x66,0x8c,0x21,0x28,0x00,0x00,0xf3,0x0d,0x00,0x08,0x01,0x00,0x07,0x24,
-0x1d,0x00,0xa2,0x28,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x04,0x10,0xa7,0x00,
-0x24,0x10,0xc2,0x00,0xfa,0xff,0x40,0x10,0x01,0x00,0xa5,0x24,0xff,0xff,0xa5,0x24,
-0x08,0x00,0xe0,0x03,0x7b,0x51,0x65,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xc8,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf,0x02,0x80,0x16,0x3c,0x30,0x00,0xbe,0xaf,
-0x2c,0x00,0xb7,0xaf,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x18,0x00,0xb2,0xaf,
-0x14,0x00,0xb1,0xaf,0x01,0x00,0x15,0x24,0x21,0x88,0x00,0x00,0x68,0x15,0xde,0x26,
-0x21,0xa0,0x00,0x00,0x21,0x90,0x00,0x00,0x25,0xb0,0x17,0x3c,0x34,0x00,0xbf,0xaf,
-0x1c,0x00,0xb3,0xaf,0x14,0x0e,0x00,0x08,0x10,0x00,0xb0,0xaf,0x01,0x00,0x31,0x26,
-0x20,0x00,0x22,0x2e,0x94,0x00,0x52,0x26,0x2e,0x00,0x40,0x10,0x94,0x00,0x94,0x26,
-0x68,0x15,0xc2,0x26,0x21,0x30,0x42,0x02,0x78,0x51,0xc5,0x8c,0x00,0x00,0x00,0x00,
-0x02,0x13,0x05,0x00,0x01,0x00,0x42,0x30,0xf4,0xff,0x55,0x14,0x42,0x1a,0x05,0x00,
-0x68,0x51,0xc2,0x8c,0x07,0x00,0x64,0x30,0x02,0x11,0x02,0x00,0x7f,0x00,0x43,0x30,
-0x2d,0x00,0x95,0x10,0x07,0x00,0xb3,0x30,0x02,0x00,0x82,0x28,0x3a,0x00,0x40,0x14,
-0x02,0x00,0x02,0x24,0x30,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0x3c,0x00,0x82,0x10,
-0x1a,0x00,0x62,0x2c,0x21,0x80,0x9e,0x02,0x78,0x51,0x02,0x8e,0x04,0x00,0x63,0x2e,
-0x42,0x12,0x02,0x00,0x0a,0x00,0x60,0x10,0x07,0x00,0x44,0x30,0x73,0x0d,0x00,0x0c,
-0x21,0x28,0x60,0x02,0x80,0x20,0x13,0x00,0x70,0x51,0x02,0xae,0x21,0x20,0x97,0x00,
-0x84,0x01,0x83,0x8c,0x00,0x00,0x00,0x00,0x24,0x18,0x62,0x00,0x74,0x51,0x03,0xae,
-0xce,0x0d,0x00,0x0c,0x21,0x20,0x20,0x02,0x21,0x10,0x37,0x02,0x01,0x00,0x31,0x26,
-0x60,0x01,0x43,0x90,0x20,0x00,0x22,0x2e,0x94,0x00,0x52,0x26,0xd4,0xff,0x40,0x14,
-0x94,0x00,0x94,0x26,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f,
-0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x32,0x00,0x62,0x2c,0xda,0xff,0x40,0x10,
-0x21,0x80,0x9e,0x02,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x04,0x42,0x34,
-0x29,0x0e,0x00,0x08,0x78,0x51,0xc2,0xac,0x38,0x00,0x62,0x2c,0x12,0x00,0x40,0x14,
-0x14,0x00,0x62,0x2c,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x02,0x42,0x34,
-0x29,0x0e,0x00,0x08,0x78,0x51,0xc2,0xac,0xcb,0xff,0x80,0x14,0x21,0x80,0x9e,0x02,
-0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x2a,0x0e,0x00,0x08,0x78,0x51,0xc2,0xac,
-0xc5,0xff,0x40,0x14,0x21,0x80,0x9e,0x02,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,
-0x54,0x0e,0x00,0x08,0x00,0x04,0x42,0x34,0xbf,0xff,0x40,0x10,0x21,0x80,0x9e,0x02,
-0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x06,0x42,0x34,0x2a,0x0e,0x00,0x08,
-0x78,0x51,0xc2,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd8,0xff,0xbd,0x27,
-0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,0x80,0x80,0x10,0x00,
-0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x80,0x80,0x10,0x00,
-0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x21,0x80,0x02,0x02,
-0x14,0x00,0xb1,0xaf,0x78,0x51,0x03,0x8e,0x25,0xb0,0x02,0x3c,0x80,0x01,0x53,0x34,
-0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x71,0x92,
-0x70,0x51,0x05,0x8e,0x84,0x01,0x62,0x8c,0x21,0x90,0x80,0x00,0xff,0x00,0x31,0x32,
-0x24,0x10,0x45,0x00,0xce,0x0d,0x00,0x0c,0x74,0x51,0x02,0xae,0x7a,0x51,0x04,0x92,
-0x5c,0x0d,0x00,0x0c,0xff,0x00,0x45,0x32,0x7a,0x51,0x04,0x92,0x63,0x0d,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x88,0x62,0x00,
-0x00,0x00,0x71,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
-0xff,0xff,0x84,0x30,0x00,0x02,0x82,0x30,0x07,0x00,0x03,0x24,0x0d,0x00,0x40,0x14,
-0x0b,0x00,0x84,0x30,0x0c,0x00,0x82,0x2c,0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,0xf0,0x91,0x63,0x24,0x21,0x10,0x43,0x00,
-0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,
-0x07,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x06,0x00,0x03,0x24,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x05,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x60,0x00,0x04,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0x03,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x02,0x00,0x03,0x24,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x60,0x00,0x21,0x18,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0xa0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x58,0x00,0xbe,0xaf,0x54,0x00,0xb7,0xaf,
-0x50,0x00,0xb6,0xaf,0x4c,0x00,0xb5,0xaf,0x48,0x00,0xb4,0xaf,0x40,0x00,0xb2,0xaf,
-0x3c,0x00,0xb1,0xaf,0x5c,0x00,0xbf,0xaf,0x44,0x00,0xb3,0xaf,0x38,0x00,0xb0,0xaf,
-0x20,0x92,0x42,0x24,0x00,0x00,0x53,0x8c,0x08,0x00,0x03,0x24,0x02,0x80,0x0b,0x3c,
-0x21,0x90,0x00,0x00,0x21,0xa0,0x00,0x00,0x21,0xb8,0x00,0x00,0x21,0xf0,0x00,0x00,
-0x21,0xa8,0x00,0x00,0x21,0xb0,0x00,0x00,0x21,0x88,0x60,0x02,0x10,0x00,0xa3,0xaf,
-0x14,0x00,0xa0,0xaf,0x18,0x00,0xa0,0xaf,0x1c,0x00,0xa0,0xaf,0x20,0x00,0xa0,0xaf,
-0x24,0x00,0xa0,0xaf,0x28,0x00,0xa0,0xaf,0x7a,0x0f,0x00,0x08,0x2c,0x00,0xa0,0xaf,
-0x44,0x51,0x22,0xae,0x60,0x51,0x24,0x8e,0x5c,0x51,0x27,0x8e,0x48,0x51,0x28,0x8e,
-0x4c,0x51,0x25,0x8e,0x54,0x51,0x26,0x8e,0x58,0x51,0x23,0x8e,0x21,0x38,0xe4,0x00,
-0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0x21,0x10,0x04,0x02,0x21,0x40,0x05,0x01,
-0x21,0x30,0xc3,0x00,0xca,0x44,0x42,0x90,0x44,0x51,0x2a,0x8e,0x0c,0x00,0xe0,0x10,
-0x21,0x48,0x00,0x00,0x2b,0x48,0x47,0x00,0x0b,0x00,0x20,0x15,0x02,0x80,0x02,0x3c,
-0x07,0x00,0x02,0x2e,0x59,0x01,0x40,0x14,0xc0,0x10,0x07,0x00,0x0c,0x00,0x02,0x24,
-0x55,0x01,0x02,0x12,0x0d,0x00,0x02,0x24,0x54,0x01,0x02,0x12,0xc0,0x10,0x07,0x00,
-0x92,0x00,0x20,0x11,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x80,0x18,0x10,0x00,
-0x21,0x18,0x62,0x00,0x21,0x20,0x30,0x02,0xb6,0x51,0x85,0x90,0xec,0x44,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x04,0x10,0xa2,0x00,0x2b,0x10,0x4a,0x00,0x87,0x00,0x40,0x10,
-0x00,0x00,0x00,0x00,0xd4,0x51,0x22,0x8e,0x01,0x00,0x07,0x24,0x04,0x18,0x07,0x02,
-0x24,0x10,0x43,0x00,0xf0,0x00,0x40,0x10,0x1c,0x00,0x02,0x2e,0x21,0x28,0x30,0x02,
-0x7c,0x51,0xa6,0x90,0xb6,0x51,0xa2,0x90,0x0a,0x00,0x04,0x24,0xff,0x00,0xc3,0x30,
-0x04,0x20,0x44,0x00,0x2a,0x18,0x64,0x00,0xe7,0x00,0x60,0x10,0x1c,0x00,0x02,0x2e,
-0x01,0x00,0xc2,0x24,0xff,0x00,0x43,0x30,0x56,0x01,0x64,0x10,0x7c,0x51,0xa2,0xa0,
-0x68,0x15,0x65,0x25,0x80,0x10,0x10,0x00,0x21,0x10,0x45,0x00,0x60,0x45,0x44,0x8c,
-0xec,0x44,0x43,0x8c,0x21,0x30,0xc5,0x02,0x40,0x10,0x04,0x00,0x21,0x10,0x44,0x00,
-0x21,0x18,0x62,0x00,0x82,0x50,0x03,0x00,0x44,0x51,0xca,0xac,0x8c,0x65,0xa3,0x8c,
-0xff,0xff,0x02,0x34,0x07,0x00,0x62,0x10,0x21,0x20,0x00,0x02,0x21,0x20,0x00,0x02,
-0xff,0x00,0x45,0x32,0x5c,0x0d,0x00,0x0c,0x30,0x00,0xab,0xaf,0x30,0x00,0xab,0x8f,
-0x21,0x20,0x00,0x02,0x63,0x0d,0x00,0x0c,0x30,0x00,0xab,0xaf,0x10,0x00,0xa4,0x8f,
-0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00,0x10,0x00,0xa4,0xaf,
-0x30,0x00,0xab,0x8f,0x11,0x00,0x40,0x16,0x68,0x15,0x62,0x25,0x58,0x51,0x47,0x8c,
-0x54,0x51,0x43,0x8c,0x4c,0x51,0x44,0x94,0x48,0x51,0x45,0x94,0x50,0x51,0x46,0x94,
-0x21,0x18,0x67,0x00,0x00,0x24,0x04,0x00,0x25,0xb0,0x02,0x3c,0x00,0x1c,0x03,0x00,
-0x21,0x28,0xa4,0x00,0x21,0x30,0xc3,0x00,0x6c,0x0c,0x44,0x34,0x68,0x0c,0x42,0x34,
-0x00,0x00,0x45,0xac,0x00,0x00,0x86,0xac,0x68,0x15,0x62,0x25,0x21,0x10,0x82,0x02,
-0x58,0x51,0x40,0xac,0x5c,0x51,0x40,0xac,0x60,0x51,0x40,0xac,0x48,0x51,0x40,0xac,
-0x4c,0x51,0x40,0xac,0x50,0x51,0x40,0xac,0x54,0x51,0x40,0xac,0x2c,0x00,0xa2,0x8f,
-0x28,0x00,0xa4,0x8f,0x01,0x00,0x52,0x26,0x94,0x00,0x42,0x24,0x2c,0x00,0xa2,0xaf,
-0x24,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24,0x28,0x00,0xa4,0xaf,0x94,0x00,0x42,0x24,
-0x20,0x00,0xa4,0x8f,0x24,0x00,0xa2,0xaf,0x1c,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24,
-0x20,0x00,0xa4,0xaf,0x94,0x00,0x42,0x24,0x18,0x00,0xa4,0x8f,0x1c,0x00,0xa2,0xaf,
-0x14,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24,0x20,0x00,0x43,0x2a,0x94,0x00,0x42,0x24,
-0x94,0x00,0x31,0x26,0x94,0x00,0xd6,0x26,0x94,0x00,0xb5,0x26,0x18,0x00,0xa4,0xaf,
-0x14,0x00,0xa2,0xaf,0x94,0x00,0xde,0x27,0x94,0x00,0x73,0x26,0x94,0x00,0xf7,0x26,
-0xe5,0x00,0x60,0x10,0x94,0x00,0x94,0x26,0x78,0x51,0x22,0x8e,0x00,0x00,0x00,0x00,
-0x02,0x13,0x02,0x00,0x01,0x00,0x42,0x30,0xd3,0xff,0x40,0x10,0x25,0xb0,0x02,0x3c,
-0x21,0x10,0x42,0x02,0x60,0x01,0x44,0x90,0x60,0x51,0x23,0x8e,0x5c,0x51,0x26,0x8e,
-0xff,0x00,0x90,0x30,0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0x21,0x10,0x04,0x02,
-0x73,0x44,0x44,0x90,0x56,0x44,0x45,0x90,0x44,0x51,0x27,0x8e,0x18,0x00,0x64,0x00,
-0x12,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xc5,0x00,
-0x12,0x30,0x00,0x00,0x21,0x30,0xc3,0x00,0x2b,0x10,0xe6,0x00,0x54,0xff,0x40,0x10,
-0x23,0x10,0xe6,0x00,0xe9,0x0e,0x00,0x08,0x44,0x51,0x20,0xae,0x62,0x00,0xe0,0x10,
-0x00,0x00,0x00,0x00,0x63,0x00,0x20,0x15,0x68,0x15,0x62,0x25,0x40,0x10,0x07,0x00,
-0x21,0x10,0x47,0x00,0x82,0x10,0x02,0x00,0x2b,0x10,0x46,0x00,0x99,0xff,0x40,0x10,
-0x21,0x20,0x00,0x02,0x68,0x15,0x68,0x25,0x21,0x20,0xa8,0x02,0x21,0x30,0x90,0x00,
-0xd4,0x51,0x83,0x8c,0x01,0x00,0x05,0x24,0x04,0x10,0x05,0x02,0x99,0x51,0xc7,0x90,
-0x27,0x10,0x02,0x00,0x24,0x18,0x62,0x00,0xd4,0x51,0x83,0xac,0x09,0x00,0xe5,0x10,
-0x7c,0x51,0xc0,0xa0,0x18,0x00,0xa2,0x8f,0x21,0x38,0x00,0x00,0x21,0x20,0x48,0x00,
-0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,0x1d,0x00,0xe2,0x28,0xfc,0xff,0x40,0x14,
-0xb6,0x51,0x60,0xa0,0x14,0x00,0xa4,0x8f,0x68,0x15,0x63,0x25,0x21,0x50,0x60,0x00,
-0x21,0x10,0x83,0x00,0x21,0x10,0x50,0x00,0x99,0x51,0x40,0xa0,0x02,0x80,0x03,0x3c,
-0x02,0x80,0x02,0x3c,0x4c,0x91,0x49,0x24,0xd8,0x90,0x68,0x24,0x21,0x38,0x00,0x00,
-0x80,0x18,0x07,0x00,0x21,0x10,0x69,0x00,0x21,0x20,0x68,0x00,0x00,0x00,0x46,0x8c,
-0x00,0x00,0x85,0x8c,0x01,0x00,0xe7,0x24,0x21,0x18,0x6a,0x00,0x1d,0x00,0xe2,0x28,
-0xec,0x44,0x65,0xac,0xf6,0xff,0x40,0x14,0x60,0x45,0x66,0xac,0x14,0x00,0x00,0x12,
-0x68,0x15,0x63,0x25,0x7b,0x51,0x62,0x92,0xff,0xff,0x07,0x26,0x2a,0x10,0xe2,0x00,
-0x0e,0x00,0x40,0x14,0x02,0x80,0x0b,0x3c,0x68,0x15,0x62,0x25,0x21,0x10,0xc2,0x03,
-0x7b,0x51,0x45,0x90,0x74,0x51,0x44,0x8c,0x01,0x00,0x06,0x24,0x04,0x18,0xe6,0x00,
-0x24,0x10,0x83,0x00,0xb3,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0xe7,0x24,
-0x2a,0x10,0xe5,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x68,0x15,0x63,0x25,
-0x80,0x10,0x10,0x00,0x21,0x10,0x43,0x00,0x60,0x45,0x45,0x8c,0xec,0x44,0x44,0x8c,
-0x02,0x80,0x03,0x3c,0x40,0x10,0x05,0x00,0x8e,0x7d,0x66,0x90,0x21,0x10,0x45,0x00,
-0x21,0x20,0x82,0x00,0x22,0x00,0x02,0x24,0x98,0x00,0xc2,0x10,0x82,0x50,0x04,0x00,
-0xd4,0x51,0x63,0x8e,0x01,0x00,0x02,0x24,0x04,0x10,0x02,0x02,0x25,0x18,0x62,0x00,
-0xd4,0x51,0x63,0xae,0x68,0x15,0x63,0x25,0x21,0x10,0xe3,0x02,0x44,0x51,0x4a,0xac,
-0x8c,0x65,0x64,0x8c,0xff,0xff,0x02,0x34,0x3c,0xff,0x82,0x14,0x21,0x20,0x00,0x02,
-0x39,0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x3e,0xff,0x20,0x11,0x21,0x20,0x00,0x02,
-0x68,0x15,0x62,0x25,0x80,0x18,0x10,0x00,0x21,0x18,0x62,0x00,0x60,0x45,0x64,0x8c,
-0x00,0x00,0x00,0x00,0x2b,0x20,0x44,0x01,0x36,0xff,0x80,0x10,0x21,0x20,0x00,0x02,
-0xa2,0x0f,0x00,0x08,0x68,0x15,0x68,0x25,0x1e,0xff,0x40,0x10,0x68,0x15,0x65,0x25,
-0x21,0x20,0x30,0x02,0x99,0x51,0x83,0x90,0x01,0x00,0x02,0x24,0x63,0x00,0x62,0x10,
-0x02,0x80,0x02,0x3c,0x2c,0x00,0xa3,0x8f,0x68,0x15,0x42,0x24,0x21,0x38,0x00,0x00,
-0x21,0x20,0x62,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,0x1d,0x00,0xe2,0x28,
-0xfc,0xff,0x40,0x14,0xb6,0x51,0x60,0xa0,0x28,0x00,0xa3,0x8f,0x02,0x80,0x0b,0x3c,
-0x68,0x15,0x65,0x25,0x21,0x30,0x65,0x00,0xd4,0x51,0xc2,0x8c,0x01,0x00,0x03,0x24,
-0x04,0x18,0x03,0x02,0x27,0x18,0x03,0x00,0x21,0x20,0xd0,0x00,0x24,0x10,0x43,0x00,
-0x99,0x51,0x80,0xa0,0xd4,0x51,0xc2,0xac,0x12,0x00,0x00,0x16,0x7c,0x51,0x80,0xa0,
-0x7a,0x51,0xc2,0x90,0x00,0x00,0x00,0x00,0x0e,0x00,0x40,0x10,0x01,0x00,0x07,0x24,
-0x24,0x00,0xa4,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x85,0x00,0x7a,0x51,0x44,0x90,
-0x74,0x51,0x45,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0xa3,0x00,0x5b,0x00,0x43,0x10,
-0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0x87,0x00,0xfa,0xff,0x40,0x10,
-0x04,0x18,0xe6,0x00,0x20,0x00,0xa2,0x8f,0x02,0x80,0x0b,0x3c,0x68,0x15,0x64,0x25,
-0x21,0x18,0x44,0x00,0x7a,0x51,0x62,0x90,0x01,0x00,0x07,0x26,0x2a,0x10,0x47,0x00,
-0x0e,0x00,0x40,0x14,0x01,0x00,0x06,0x24,0x1c,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,
-0x21,0x10,0x64,0x00,0x7a,0x51,0x45,0x90,0x74,0x51,0x44,0x8c,0x04,0x18,0xe6,0x00,
-0x24,0x10,0x83,0x00,0x42,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,
-0x2a,0x10,0xa7,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x02,0x3c,
-0x8e,0x7d,0x44,0x90,0x22,0x00,0x03,0x24,0xd6,0xfe,0x83,0x14,0x68,0x15,0x65,0x25,
-0xee,0xff,0x02,0x26,0xff,0x00,0x42,0x30,0x02,0x00,0x42,0x2c,0x18,0x00,0x03,0x24,
-0x25,0x0f,0x00,0x08,0x0b,0x80,0x62,0x00,0xc0,0x10,0x07,0x00,0x23,0x10,0x47,0x00,
-0xc2,0x10,0x02,0x00,0x2b,0x10,0x48,0x00,0xb6,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,
-0x04,0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x10,0x00,0xa3,0x8f,0x5c,0x00,0xbf,0x8f,
-0x58,0x00,0xbe,0x8f,0x54,0x00,0xb7,0x8f,0x50,0x00,0xb6,0x8f,0x4c,0x00,0xb5,0x8f,
-0x48,0x00,0xb4,0x8f,0x44,0x00,0xb3,0x8f,0x40,0x00,0xb2,0x8f,0x3c,0x00,0xb1,0x8f,
-0x38,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x60,0x00,0xbd,0x27,
-0x00,0x00,0x43,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x18,0x00,0x02,0x2e,
-0x0a,0x00,0x40,0x14,0x05,0x00,0x02,0x2e,0xb6,0x51,0x83,0x90,0x00,0x00,0x00,0x00,
-0x05,0x00,0x62,0x2c,0xa0,0xff,0x40,0x10,0x01,0x00,0x62,0x24,0x16,0x10,0x00,0x08,
-0xb6,0x51,0x82,0xa0,0x24,0x0f,0x00,0x08,0x99,0x51,0xa7,0xa0,0x04,0x00,0x40,0x10,
-0x00,0x00,0x00,0x00,0xb6,0x51,0x83,0x90,0x75,0x10,0x00,0x08,0x03,0x00,0x62,0x2c,
-0xb6,0x51,0x83,0x90,0x75,0x10,0x00,0x08,0x04,0x00,0x62,0x2c,0x13,0x00,0x02,0x24,
-0x67,0xff,0x02,0x16,0x68,0x15,0x63,0x25,0xf3,0x0f,0x00,0x08,0x21,0x10,0xe3,0x02,
-0xff,0x00,0xf0,0x30,0x4c,0x10,0x00,0x08,0x02,0x80,0x02,0x3c,0x35,0x10,0x00,0x08,
-0xff,0x00,0xf0,0x30,0xdf,0x0f,0x00,0x08,0xff,0x00,0xf0,0x30,0xd8,0xff,0xbd,0x27,
-0x02,0x80,0x02,0x3c,0x14,0x00,0xb1,0xaf,0x24,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf,
-0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x68,0x15,0x45,0x24,
-0x05,0x65,0xa4,0x90,0x00,0x65,0xa3,0x8c,0xfc,0x64,0xa2,0x8c,0x21,0x88,0x64,0x00,
-0x2b,0x10,0x22,0x02,0x60,0x00,0x40,0x10,0x21,0x80,0xa0,0x00,0x02,0x80,0x14,0x3c,
-0x21,0x98,0xa0,0x00,0xa8,0x10,0x00,0x08,0x21,0x90,0xa0,0x00,0xfc,0x64,0x42,0x8e,
-0x10,0x00,0x31,0x26,0x2b,0x10,0x22,0x02,0x57,0x00,0x40,0x10,0x21,0x80,0x40,0x02,
-0x05,0x65,0x02,0x92,0xff,0xff,0x23,0x32,0x02,0x80,0x05,0x3c,0x10,0x00,0x42,0x24,
-0x25,0x28,0x65,0x00,0x2c,0x79,0x84,0x26,0x10,0x00,0x06,0x24,0x9f,0x45,0x00,0x0c,
-0x05,0x65,0x02,0xa2,0xc8,0x63,0x06,0x8e,0x00,0x00,0x00,0x00,0x42,0x24,0x06,0x00,
-0x1f,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,
-0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x38,0x50,0x00,0x78,0x51,0xe3,0x8c,
-0x00,0x00,0x00,0x00,0x02,0x1b,0x03,0x00,0x01,0x00,0x63,0x30,0xe3,0xff,0x60,0x10,
-0x25,0xb0,0x02,0x3c,0xc4,0x63,0x05,0x8e,0x21,0x10,0x82,0x00,0x60,0x01,0x44,0x90,
-0x82,0x1d,0x05,0x00,0x3f,0x00,0x63,0x30,0x04,0x00,0x0a,0x24,0x05,0x00,0x62,0x28,
-0x21,0x40,0x40,0x01,0x0b,0x40,0x62,0x00,0x07,0x00,0xa0,0x04,0xff,0x00,0x89,0x30,
-0x64,0x51,0xe2,0x8c,0x04,0x00,0x08,0x24,0x01,0x00,0x42,0x24,0x64,0x51,0xe2,0xac,
-0xc8,0x63,0x66,0x8e,0x00,0x00,0x00,0x00,0x02,0x13,0x06,0x00,0x1f,0x00,0x42,0x30,
-0x08,0x00,0x42,0x28,0xcd,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xc4,0x63,0x62,0x8e,
-0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0xc8,0xff,0x49,0x14,0x00,0x00,0x00,0x00,
-0x29,0x00,0x00,0x11,0x01,0x00,0x02,0x24,0x2e,0x00,0x02,0x11,0x02,0x00,0x02,0x24,
-0x33,0x00,0x02,0x11,0x03,0x00,0x02,0x24,0x38,0x00,0x02,0x11,0x00,0x00,0x00,0x00,
-0x3b,0x00,0x0a,0x11,0x00,0x00,0x00,0x00,0x68,0x51,0xe2,0x8c,0x21,0x18,0x33,0x01,
-0x90,0x44,0x64,0x90,0x02,0x11,0x02,0x00,0x2b,0x10,0x44,0x00,0x3e,0x00,0x40,0x14,
-0x00,0x00,0x00,0x00,0x5c,0x51,0xe3,0x8c,0x80,0x10,0x09,0x00,0x21,0x10,0x49,0x00,
-0x01,0x00,0x63,0x24,0x21,0x10,0x53,0x00,0x5c,0x51,0xe3,0xac,0x21,0x10,0x48,0x00,
-0x34,0x43,0x44,0x90,0x44,0x51,0xe3,0x8c,0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00,
-0x44,0x51,0xe3,0xac,0xfc,0x64,0x42,0x8e,0x10,0x00,0x31,0x26,0x2b,0x10,0x22,0x02,
-0xab,0xff,0x40,0x14,0x21,0x80,0x40,0x02,0x24,0x00,0xbf,0x8f,0x20,0x00,0xb4,0x8f,
-0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x48,0x51,0xe2,0x8c,0x00,0x00,0x00,0x00,
-0x01,0x00,0x42,0x24,0x48,0x51,0xe2,0xac,0x01,0x00,0x02,0x24,0xd4,0xff,0x02,0x15,
-0x02,0x00,0x02,0x24,0x4c,0x51,0xe2,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
-0x4c,0x51,0xe2,0xac,0x02,0x00,0x02,0x24,0xcf,0xff,0x02,0x15,0x03,0x00,0x02,0x24,
-0x50,0x51,0xe2,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0x50,0x51,0xe2,0xac,
-0x03,0x00,0x02,0x24,0xca,0xff,0x02,0x15,0x00,0x00,0x00,0x00,0x54,0x51,0xe2,0x8c,
-0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xc7,0xff,0x0a,0x15,0x54,0x51,0xe2,0xac,
-0x58,0x51,0xe2,0x8c,0x21,0x18,0x33,0x01,0x01,0x00,0x42,0x24,0x58,0x51,0xe2,0xac,
-0x68,0x51,0xe2,0x8c,0x90,0x44,0x64,0x90,0x02,0x11,0x02,0x00,0x2b,0x10,0x44,0x00,
-0xc4,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x60,0x51,0xe3,0x8c,0x80,0x10,0x09,0x00,
-0x21,0x10,0x49,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x53,0x00,0x60,0x51,0xe3,0xac,
-0x21,0x10,0x48,0x00,0xc5,0x43,0x44,0x90,0x44,0x51,0xe3,0x8c,0x00,0x00,0x00,0x00,
-0x21,0x18,0x64,0x00,0xf9,0x10,0x00,0x08,0x44,0x51,0xe3,0xac,0x25,0xb0,0x02,0x3c,
-0x25,0xb0,0x05,0x3c,0x02,0x80,0x03,0x3c,0x58,0x00,0x4a,0x34,0x5c,0x00,0x4b,0x34,
-0x4c,0x00,0xa2,0x34,0x00,0x00,0x44,0x90,0x68,0x15,0x66,0x24,0xed,0x4a,0xc2,0x90,
-0x29,0xb0,0x07,0x3c,0x03,0x00,0x84,0x30,0x21,0x18,0xc0,0x00,0x0f,0x00,0x44,0x10,
-0x04,0x00,0xe8,0x34,0x07,0x00,0x80,0x14,0x58,0x0c,0xa9,0x34,0xe6,0x42,0xc2,0x90,
-0x1c,0x00,0x06,0x24,0x03,0x00,0x40,0x14,0x50,0x0c,0xa5,0x34,0x00,0x00,0xa6,0xa0,
-0x00,0x00,0x26,0xa1,0x00,0x00,0x42,0x8d,0xed,0x4a,0x64,0xa0,0x00,0x00,0xe2,0xac,
-0x00,0x00,0x62,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xad,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x00,0x00,0x25,0xb0,0x0d,0x3c,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,
-0x2d,0x0a,0xa7,0x35,0xa2,0x0d,0xa2,0x35,0xa4,0x0d,0xa3,0x35,0xa6,0x0d,0xa4,0x35,
-0xa8,0x0d,0xa5,0x35,0x00,0x00,0x48,0x94,0x00,0x00,0x69,0x94,0x00,0x00,0x8a,0x94,
-0x00,0x00,0xab,0x94,0x00,0x00,0xe3,0x90,0x5b,0x0a,0xa4,0x35,0x5c,0x0a,0xa6,0x35,
-0x00,0x2e,0x03,0x00,0x03,0x2e,0x05,0x00,0x40,0x00,0xa2,0x34,0x00,0x00,0xe2,0xa0,
-0x00,0x00,0x85,0x90,0x00,0x00,0xc3,0x90,0x02,0x80,0x0e,0x3c,0x68,0x15,0xcc,0x25,
-0xff,0xff,0x22,0x31,0xff,0x00,0xa5,0x30,0xff,0xff,0x04,0x31,0x21,0x20,0x82,0x00,
-0xff,0x00,0x63,0x30,0x00,0x40,0x87,0x8d,0x00,0x2a,0x05,0x00,0xff,0xff,0x46,0x31,
-0x21,0x28,0xa3,0x00,0xff,0xff,0x62,0x31,0x21,0x20,0x86,0x00,0x21,0x20,0x82,0x00,
-0xff,0xff,0xa3,0x30,0x64,0x0c,0xa2,0x35,0x00,0x00,0x45,0xa4,0x21,0x20,0x83,0x00,
-0x0f,0x00,0xe7,0x30,0x01,0x00,0x02,0x24,0xe0,0x42,0x84,0xad,0xd8,0x42,0x88,0xa5,
-0xda,0x42,0x89,0xa5,0xdc,0x42,0x8a,0xa5,0xde,0x42,0x8b,0xa5,0x07,0x00,0xe2,0x10,
-0xe4,0x42,0x85,0xa5,0xa8,0x56,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,
-0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x4c,0x00,0xa3,0x35,
-0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x67,0x00,0x47,0x10,
-0x68,0x15,0xc4,0x25,0xe6,0x42,0x82,0x90,0x00,0x00,0x00,0x00,0x2d,0x00,0x40,0x10,
-0x01,0x00,0x03,0x24,0x68,0x15,0xc5,0x25,0xe6,0x42,0xa3,0x90,0xff,0x00,0x02,0x24,
-0xec,0xff,0x62,0x14,0x25,0xb0,0x03,0x3c,0xc8,0x42,0xa2,0x94,0xe0,0x42,0xa6,0x8c,
-0x50,0x0c,0x63,0x34,0x00,0x00,0x64,0x90,0x2b,0x10,0xc2,0x00,0x5e,0x00,0x40,0x14,
-0x7f,0x00,0x84,0x30,0xca,0x42,0xa2,0x94,0x00,0x00,0x00,0x00,0x2b,0x10,0xc2,0x00,
-0x09,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xcc,0x42,0xa2,0x94,0x00,0x00,0x00,0x00,
-0x2b,0x10,0xc2,0x00,0x02,0x00,0x40,0x10,0x02,0x00,0x82,0x24,0x01,0x00,0x82,0x24,
-0xff,0x00,0x44,0x30,0x68,0x15,0xc5,0x25,0xd0,0x42,0xa3,0x90,0x00,0x00,0x00,0x00,
-0x2b,0x10,0x64,0x00,0x4e,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x21,0x20,0x60,0x00,
-0x68,0x15,0xc3,0x25,0xe0,0x42,0x62,0x8c,0x00,0x00,0x00,0x00,0xe9,0x03,0x42,0x2c,
-0x02,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0xd0,0x42,0x64,0x90,0x58,0x0c,0x43,0x34,
-0x50,0x0c,0x42,0x34,0x00,0x00,0x44,0xa0,0x00,0x00,0x64,0xa0,0x85,0x11,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0x40,0x82,0x8c,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,
-0x0f,0x00,0x42,0x30,0xd0,0xff,0x43,0x14,0x68,0x15,0xc5,0x25,0x25,0xb0,0x02,0x3c,
-0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,
-0xb8,0xff,0x60,0x10,0xff,0xff,0x02,0x34,0xdc,0x63,0x83,0x8c,0x00,0x00,0x00,0x00,
-0xb4,0xff,0x62,0x10,0x00,0x00,0x00,0x00,0xe0,0x42,0x83,0x8c,0x00,0x00,0x00,0x00,
-0x65,0x00,0x62,0x2c,0x3b,0x00,0x40,0x14,0x28,0x00,0x62,0x2c,0xd2,0x42,0x83,0x90,
-0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00,0xfe,0xff,0x42,0x24,
-0xfc,0xff,0x42,0x28,0x02,0x00,0x40,0x10,0xfe,0xff,0x62,0x24,0xfc,0xff,0x02,0x24,
-0xd2,0x42,0x82,0xa0,0x68,0x15,0xc4,0x25,0xdc,0x63,0x82,0x8c,0xd2,0x42,0x83,0x90,
-0xce,0x42,0x86,0x90,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,0x0a,0x00,0x45,0x24,
-0x23,0x18,0xa3,0x00,0x00,0x2e,0x03,0x00,0x03,0x2e,0x05,0x00,0xff,0x00,0xc2,0x30,
-0x2a,0x10,0x45,0x00,0x17,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x00,0x2e,0x06,0x00,
-0x03,0x2e,0x05,0x00,0x58,0x0c,0x43,0x34,0x50,0x0c,0x42,0x34,0x00,0x00,0x45,0xa0,
-0x00,0x00,0x65,0xa0,0x85,0x11,0x00,0x08,0x00,0x00,0x00,0x00,0xe6,0x42,0x82,0x91,
-0x00,0x00,0x00,0x00,0x97,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x24,
-0x91,0x11,0x00,0x08,0xe6,0x42,0x82,0xa1,0xac,0x11,0x00,0x08,0xff,0xff,0x82,0x24,
-0xd1,0x42,0xa3,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0xb4,0x11,0x00,0x08,
-0x0b,0x20,0x62,0x00,0xcf,0x42,0x83,0x80,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,
-0x2a,0x10,0xa2,0x00,0x0b,0x28,0x62,0x00,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x43,0x34,
-0x50,0x0c,0x42,0x34,0x00,0x00,0x45,0xa0,0x00,0x00,0x65,0xa0,0x85,0x11,0x00,0x08,
-0x00,0x00,0x00,0x00,0xcf,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xd2,0x42,0x83,0x90,
-0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00,0x02,0x00,0x42,0x24,
-0x0d,0x00,0x42,0x28,0x03,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xe0,0x11,0x00,0x08,
-0x0c,0x00,0x02,0x24,0xe0,0x11,0x00,0x08,0x02,0x00,0x62,0x24,0xc0,0xff,0xbd,0x27,
-0x18,0x00,0xb0,0xaf,0x25,0xb0,0x10,0x3c,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
-0x1c,0x00,0xb1,0xaf,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,
-0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x20,0x00,0xb2,0xaf,0xd8,0x00,0x06,0x36,
-0x00,0x00,0xc3,0x90,0x02,0x80,0x02,0x3c,0x68,0x15,0x54,0x24,0x2a,0xb0,0x11,0x3c,
-0xa0,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x34,0x00,0x25,0x36,0xfe,0xff,0x02,0x24,
-0xbc,0x42,0x92,0x92,0x40,0x00,0x04,0x24,0x00,0x00,0xc3,0xa0,0x00,0x00,0xa2,0xa0,
-0xa1,0x4e,0x00,0x0c,0x00,0x96,0x12,0x00,0x21,0x98,0x40,0x00,0x6b,0x00,0x60,0x12,
-0x00,0x40,0x02,0x3c,0x08,0x00,0x63,0x8e,0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,
-0x00,0x00,0x43,0xac,0x3a,0x45,0x00,0x0c,0x21,0xb8,0x80,0x02,0x01,0x00,0x1e,0x24,
-0x42,0x00,0x16,0x36,0x03,0x0c,0x11,0x36,0x17,0x0e,0x15,0x36,0x04,0x00,0x14,0x24,
-0x2a,0xb0,0x03,0x3c,0x06,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,
-0x00,0xff,0x42,0x30,0x0a,0x00,0x40,0x18,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,
-0xc8,0x94,0x84,0x24,0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x94,
-0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,0xfc,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,
-0x08,0x00,0x65,0x8e,0x20,0x10,0x06,0x3c,0x00,0xfe,0xc6,0x34,0x40,0x00,0x07,0x24,
-0x01,0x00,0x04,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xbe,0xaf,0x4d,0x01,0x00,0x0c,
-0x01,0x00,0x04,0x24,0x2a,0xb0,0x02,0x3c,0x05,0x00,0x42,0x34,0xff,0xff,0x03,0x24,
-0x00,0x00,0x5e,0xa0,0x00,0x00,0xc3,0xa2,0x00,0x00,0x22,0x92,0xc1,0x42,0xe5,0x92,
-0x2a,0xb0,0x04,0x3c,0x02,0x00,0x03,0x24,0x40,0x00,0x42,0x34,0x05,0x00,0x84,0x34,
-0x00,0x00,0x22,0xa2,0x00,0x00,0x83,0xa0,0xef,0xff,0x02,0x24,0x00,0x00,0xb0,0x92,
-0x64,0x00,0x04,0x24,0x00,0x00,0xa5,0xa2,0x00,0x00,0xc2,0xa2,0xb3,0x0a,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x92,0xbf,0xff,0x03,0x24,0x84,0x03,0x04,0x24,
-0x24,0x10,0x43,0x00,0x00,0x00,0x22,0xa2,0xb3,0x0a,0x00,0x0c,0xff,0x00,0x10,0x32,
-0x25,0xb0,0x02,0x3c,0xf4,0x08,0x42,0x34,0x00,0x00,0x44,0x8c,0x00,0x00,0xb0,0xa2,
-0x00,0x00,0xc0,0xa2,0x00,0x00,0x22,0x92,0xbe,0x42,0xe3,0x92,0x1f,0x00,0x85,0x30,
-0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2,0x00,0x80,0x02,0x3c,0xdf,0x07,0x42,0x34,
-0x2b,0x18,0xa3,0x00,0x09,0x00,0x60,0x10,0x24,0x20,0x82,0x00,0xbf,0x42,0xe2,0x92,
-0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00,0x05,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,
-0x01,0x00,0x02,0x3c,0x25,0x10,0xa2,0x00,0x21,0x90,0x42,0x02,0x02,0x80,0x02,0x3c,
-0x8e,0x7d,0x43,0x90,0x22,0x00,0x02,0x24,0x1c,0x00,0x62,0x10,0x92,0x00,0x02,0x24,
-0x1b,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,0xff,0xff,0x94,0x26,0xb3,0x0a,0x00,0x0c,
-0xf4,0x01,0x04,0x24,0xab,0xff,0x81,0x06,0x2a,0xb0,0x03,0x3c,0x04,0x00,0x60,0x12,
-0x25,0xb0,0x02,0x3c,0xbd,0x4e,0x00,0x0c,0x21,0x20,0x60,0x02,0x25,0xb0,0x02,0x3c,
-0xd8,0x02,0x42,0x34,0x00,0x00,0x52,0xac,0x21,0x10,0x40,0x02,0x3c,0x00,0xbf,0x8f,
-0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,
-0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
-0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,
-0x68,0x15,0x63,0x24,0xbe,0x42,0x62,0x90,0xc0,0x07,0x83,0x30,0x82,0x19,0x03,0x00,
-0x2b,0x10,0x62,0x00,0xe0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,
-0xbf,0x42,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00,0xda,0xff,0x40,0x10,
-0x00,0x12,0x03,0x00,0x10,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x9a,0x12,0x00,0x08,
-0x21,0x90,0x42,0x02,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,
-0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,0x14,0x00,0xbf,0xaf,0xba,0x44,0x00,0x0c,
-0x15,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,
-0x56,0x30,0x06,0x24,0xba,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0x02,0x80,0x0b,0x3c,0x68,0x15,0x64,0x25,0x04,0x43,0x83,0x90,
-0x04,0x00,0x02,0x24,0x19,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x14,0x43,0x8a,0x8c,
-0x18,0x43,0x88,0x8c,0x25,0xb0,0x02,0x3c,0x1c,0x0e,0x49,0x34,0x00,0x0e,0x43,0x34,
-0x04,0x0e,0x44,0x34,0x08,0x0e,0x45,0x34,0x10,0x0e,0x46,0x34,0x14,0x0e,0x47,0x34,
-0x18,0x0e,0x42,0x34,0x00,0x00,0x6a,0xac,0x00,0x00,0x8a,0xac,0x00,0x00,0xa8,0xac,
-0x00,0x00,0xca,0xac,0x00,0x00,0xea,0xac,0x00,0x00,0x4a,0xac,0x00,0x00,0x2a,0xad,
-0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x68,0x15,0x63,0x25,0x04,0x00,0x02,0x24,
-0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x04,0x43,0x62,0xa0,0x00,0x0e,0x42,0x34,
-0x00,0x00,0x43,0x8c,0x14,0x43,0x8a,0x8c,0x00,0x00,0x00,0x00,0xe4,0xff,0x6a,0x14,
-0x00,0x00,0x00,0x00,0xec,0x12,0x00,0x08,0x00,0x00,0x00,0x00,0xe8,0xff,0xbd,0x27,
-0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,
-0x14,0x00,0xbf,0xaf,0xba,0x44,0x00,0x0c,0x15,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24,0xba,0x44,0x00,0x0c,
-0x1a,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x02,0x80,0x04,0x3c,
-0x68,0x15,0x83,0x24,0x04,0x43,0x65,0x90,0x21,0x70,0x60,0x00,0x10,0x10,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x10,0x10,0x66,0x34,0x01,0x00,0x03,0x24,0x1c,0x0e,0x4d,0x34,
-0x00,0x0e,0x4a,0x34,0x04,0x0e,0x4b,0x34,0x08,0x0e,0x4c,0x34,0x10,0x0e,0x47,0x34,
-0x14,0x0e,0x48,0x34,0x0f,0x00,0xa3,0x10,0x18,0x0e,0x49,0x34,0x10,0x10,0x02,0x24,
-0x00,0x00,0x46,0xad,0x00,0x00,0x66,0xad,0x00,0x00,0x82,0xad,0x00,0x00,0xe6,0xac,
-0x00,0x00,0x06,0xad,0x00,0x00,0x26,0xad,0x00,0x00,0xa6,0xad,0x14,0x00,0xbf,0x8f,
-0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
-0x04,0x43,0xc2,0xa1,0x00,0x00,0x44,0x8d,0x00,0x00,0x00,0x00,0xf0,0xff,0x86,0x14,
-0x10,0x10,0x02,0x24,0x23,0x13,0x00,0x08,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,
-0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x01,0x00,0x11,0x3c,0x0f,0x00,0x10,0x3c,
-0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0x18,0x00,0xbf,0xaf,0xba,0x44,0x00,0x0c,
-0x15,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,
-0x56,0x30,0x26,0x36,0xba,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x02,0x80,0x10,0x3c,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x68,0x15,0x04,0x26,0x04,0x43,0x82,0x90,
-0x00,0x00,0x00,0x00,0x0d,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0x00,0x0e,0x42,0x34,
-0x00,0x00,0x43,0x8c,0xec,0x42,0x8f,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x6f,0x14,
-0x68,0x15,0x02,0x26,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
-0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x04,0x43,0x40,0xa0,0xec,0x42,0x8f,0x8c,
-0xe8,0x42,0x88,0x8c,0xf0,0x42,0x8a,0x8c,0xf4,0x42,0x8b,0x8c,0xf8,0x42,0x8c,0x8c,
-0xfc,0x42,0x8d,0x8c,0x25,0xb0,0x02,0x3c,0x00,0x43,0x8e,0x8c,0x1c,0x0e,0x49,0x34,
-0x08,0x0e,0x43,0x34,0x00,0x0e,0x44,0x34,0x04,0x0e,0x45,0x34,0x10,0x0e,0x46,0x34,
-0x14,0x0e,0x47,0x34,0x18,0x0e,0x42,0x34,0x00,0x00,0x68,0xac,0x18,0x00,0xbf,0x8f,
-0x00,0x00,0x8f,0xac,0x14,0x00,0xb1,0x8f,0x00,0x00,0xaa,0xac,0x00,0x00,0xcb,0xac,
-0x00,0x00,0xec,0xac,0x00,0x00,0x4d,0xac,0x68,0x15,0x02,0x26,0x10,0x00,0xb0,0x8f,
-0x20,0x00,0xbd,0x27,0x00,0x00,0x2e,0xad,0x08,0x00,0xe0,0x03,0x04,0x43,0x40,0xa0,
-0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x01,0x00,0x11,0x3c,
-0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0x18,0x00,0xbf,0xaf,
-0xba,0x44,0x00,0x0c,0x15,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,
-0xff,0xff,0x05,0x36,0x56,0x30,0x26,0x36,0xba,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x02,0x80,0x18,0x3c,0x68,0x15,0x05,0x27,
-0x04,0x43,0xa3,0x90,0x03,0x00,0x02,0x24,0x2a,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,
-0xec,0x42,0xaf,0x8c,0x08,0x43,0xa3,0x8c,0xe8,0x42,0xa2,0x8c,0xf0,0x42,0xac,0x8c,
-0xf4,0x42,0xad,0x8c,0xf8,0x42,0xa9,0x8c,0xfc,0x42,0xaa,0x8c,0x00,0x43,0xab,0x8c,
-0x21,0x70,0x43,0x00,0xff,0xff,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xff,0x00,0x42,0x34,
-0x00,0xff,0xc4,0x31,0x04,0x0e,0x65,0x34,0x10,0x0e,0x66,0x34,0x14,0x0e,0x67,0x34,
-0x18,0x0e,0x68,0x34,0x24,0x80,0xc2,0x01,0x08,0x0e,0x71,0x34,0x00,0x0e,0x62,0x34,
-0x01,0x3f,0x84,0x2c,0x1c,0x0e,0x63,0x34,0x00,0x00,0x4f,0xac,0x00,0x00,0xac,0xac,
-0x00,0x00,0xcd,0xac,0x00,0x00,0xe9,0xac,0x00,0x00,0x0a,0xad,0x00,0x00,0x6b,0xac,
-0x0a,0x00,0x80,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0xae,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x68,0x15,0x03,0x27,0x03,0x00,0x02,0x24,
-0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x04,0x43,0x62,0xa0,0xa6,0x13,0x00,0x08,
-0x00,0x3f,0x0e,0x36,0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c,0xec,0x42,0xaf,0x8c,
-0x00,0x00,0x00,0x00,0xd3,0xff,0x6f,0x14,0x00,0x00,0x00,0x00,0xa7,0x13,0x00,0x08,
-0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x02,0x80,0x12,0x3c,
-0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x28,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,
-0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x68,0x15,0x44,0x26,0x02,0x80,0x14,0x3c,
-0x00,0x40,0x85,0x8c,0xdc,0x63,0x83,0x8c,0x8e,0x7d,0x86,0x92,0x25,0xb0,0x02,0x3c,
-0x0f,0x0c,0x42,0x34,0x00,0x00,0x46,0xa0,0x02,0x19,0x03,0x00,0xf0,0xf0,0xa5,0x30,
-0x00,0x10,0x02,0x24,0x04,0x43,0x93,0x90,0x71,0x00,0xa2,0x10,0x7f,0x00,0x75,0x30,
-0x25,0xb0,0x09,0x3c,0x4c,0x00,0x23,0x35,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
-0x03,0x00,0x42,0x30,0x09,0x00,0x40,0x10,0x68,0x15,0x45,0x26,0x68,0x15,0x4a,0x26,
-0x00,0x40,0x42,0x8d,0x00,0x00,0x00,0x00,0x02,0x13,0x02,0x00,0x0f,0x00,0x42,0x30,
-0x33,0x00,0x40,0x10,0x00,0x0e,0x25,0x35,0x68,0x15,0x45,0x26,0x04,0x43,0xa2,0x8c,
-0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x40,0x14,0x68,0x15,0x4a,0x26,
-0x25,0xb0,0x02,0x3c,0x84,0x01,0x42,0x34,0x00,0x00,0x44,0x8c,0x0d,0x00,0x03,0x24,
-0x7e,0x00,0x83,0x10,0x3e,0x00,0x02,0x24,0x4a,0x00,0x03,0x24,0x1f,0x43,0xa2,0xa0,
-0x1c,0x43,0xa3,0xa0,0x45,0x00,0x02,0x24,0x43,0x00,0x03,0x24,0x1d,0x43,0xa2,0xa0,
-0x1e,0x43,0xa3,0xa0,0x68,0x15,0x4a,0x26,0xdc,0x63,0x4c,0x8d,0x04,0x40,0x42,0x8d,
-0x00,0x40,0x4b,0x8d,0x1e,0x43,0x4d,0x91,0x1c,0x43,0x4e,0x91,0x25,0xb0,0x09,0x3c,
-0x02,0x11,0x02,0x00,0x60,0x0c,0x27,0x35,0x02,0x19,0x0c,0x00,0x98,0x0c,0x24,0x35,
-0x00,0x00,0xe3,0xa0,0x66,0x0c,0x25,0x35,0x00,0x00,0x82,0xa0,0x67,0x0c,0x26,0x35,
-0xf0,0xf0,0x68,0x31,0x10,0x10,0x02,0x24,0x00,0x00,0xad,0xa0,0x00,0x00,0xce,0xa0,
-0x43,0x00,0x02,0x11,0xff,0xff,0x02,0x34,0x28,0x00,0xbf,0x8f,0x24,0x00,0xb5,0x8f,
-0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
-0x00,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x5d,0x00,0x40,0x10,0x10,0x0e,0x28,0x35,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x08,0x0e,0x22,0x35,0x04,0x0e,0x24,0x35,0x00,0x00,0x43,0x8c,0x00,0x00,0xa5,0x8c,
-0x00,0x00,0x82,0x8c,0xe8,0x42,0x43,0xad,0xec,0x42,0x45,0xad,0xf0,0x42,0x42,0xad,
-0x14,0x0e,0x24,0x35,0x18,0x0e,0x22,0x35,0x1c,0x0e,0x25,0x35,0x00,0x00,0x08,0x8d,
-0x8e,0x7d,0x8b,0x92,0x00,0x00,0x86,0x8c,0x00,0xff,0x63,0x30,0x00,0x00,0x47,0x8c,
-0x00,0x00,0xa4,0x8c,0x9a,0x0c,0x22,0x35,0x02,0x1a,0x03,0x00,0x00,0x00,0x43,0xa0,
-0x22,0x00,0x02,0x24,0xf4,0x42,0x48,0xad,0xf8,0x42,0x46,0xad,0xfc,0x42,0x47,0xad,
-0x58,0x00,0x62,0x11,0x00,0x43,0x44,0xad,0x92,0x00,0x02,0x24,0x56,0x00,0x62,0x11,
-0x0d,0x08,0x22,0x35,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x68,0x15,0x44,0x26,0x00,0x40,0x83,0x8c,0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,
-0x24,0x18,0x62,0x00,0x00,0x10,0x63,0x34,0xde,0x13,0x00,0x08,0x00,0x40,0x83,0xac,
-0x01,0x00,0x02,0x24,0x35,0x00,0x62,0x12,0x04,0x00,0x02,0x24,0x33,0x00,0x62,0x12,
-0x68,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0xd0,0x13,0x00,0x08,0x04,0x43,0x62,0xa0,
-0xbd,0xff,0x82,0x11,0x02,0x12,0x0b,0x00,0x0f,0x00,0x48,0x30,0x01,0x00,0x03,0x24,
-0xb9,0xff,0x03,0x15,0x4c,0x00,0x23,0x35,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
-0x03,0x00,0x42,0x30,0xb4,0xff,0x40,0x10,0x03,0x00,0x02,0x24,0x5f,0x00,0x62,0x12,
-0x04,0x00,0x62,0x2a,0x45,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x64,0x00,0x60,0x12,
-0xff,0x00,0xa2,0x31,0xac,0xff,0x68,0x16,0xff,0x00,0xc2,0x31,0x2b,0x10,0xa2,0x02,
-0x52,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x1f,0x43,0x42,0x91,0x00,0x00,0x00,0x00,
-0x2b,0x10,0x55,0x00,0x44,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x2f,0x13,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x06,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x3b,0x00,0x02,0x24,
-0x46,0x00,0x03,0x24,0x1f,0x43,0xa2,0xa0,0x1c,0x43,0xa3,0xa0,0x41,0x00,0x02,0x24,
-0x40,0x00,0x03,0x24,0x1d,0x43,0xa2,0xa0,0xf1,0x13,0x00,0x08,0x1e,0x43,0xa3,0xa0,
-0x00,0x00,0x03,0x8d,0x3f,0x3f,0x02,0x3c,0x3f,0x3f,0x42,0x34,0xa0,0xff,0x62,0x14,
-0x00,0x00,0x00,0x00,0xdf,0x13,0x00,0x08,0x68,0x15,0x45,0x26,0x0f,0x00,0x10,0x3c,
-0x01,0x00,0x11,0x3c,0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0xba,0x44,0x00,0x0c,
-0x15,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,
-0x56,0x30,0x26,0x36,0xba,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0x68,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0xd0,0x13,0x00,0x08,
-0x04,0x43,0x62,0xa0,0x0d,0x08,0x22,0x35,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,
-0x0f,0x00,0x63,0x30,0x08,0x00,0x62,0x2c,0x0f,0x00,0x63,0x38,0xa5,0xff,0x40,0x14,
-0x01,0x00,0x65,0x24,0x00,0x16,0x05,0x00,0x00,0x24,0x05,0x00,0x00,0x1a,0x05,0x00,
-0x25,0x10,0x44,0x00,0x25,0x10,0x43,0x00,0x25,0x10,0x45,0x00,0x25,0x18,0x65,0x00,
-0x18,0x43,0x43,0xad,0x35,0x14,0x00,0x08,0x14,0x43,0x42,0xad,0x04,0x00,0x02,0x24,
-0x0d,0x00,0x62,0x12,0xff,0x00,0x02,0x24,0x67,0xff,0x62,0x16,0xff,0x00,0xa2,0x31,
-0x2b,0x10,0xa2,0x02,0x1d,0x00,0x40,0x14,0xff,0x00,0xc2,0x31,0x2b,0x10,0xa2,0x02,
-0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xfb,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x06,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x1d,0x43,0x42,0x91,0x00,0x00,0x00,0x00,
-0x2b,0x10,0x55,0x00,0xf8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xc5,0x12,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x06,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x43,0x42,0x91,
-0x00,0x00,0x00,0x00,0x2b,0x10,0xa2,0x02,0xac,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
-0x70,0x13,0x00,0x0c,0x00,0x00,0x00,0x00,0x06,0x14,0x00,0x08,0x00,0x00,0x00,0x00,
-0x2b,0x10,0xa2,0x02,0xe8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x21,0x43,0x42,0x91,
-0x00,0x00,0x00,0x00,0x2b,0x10,0x55,0x00,0xa0,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
-0x70,0x13,0x00,0x0c,0x00,0x00,0x00,0x00,0x06,0x14,0x00,0x08,0x00,0x00,0x00,0x00,
-0x02,0x80,0x08,0x3c,0x68,0x15,0x05,0x25,0xdc,0x63,0xa4,0x8c,0xe6,0x42,0xa3,0x90,
-0x02,0x11,0x04,0x00,0x1f,0x00,0x60,0x14,0x7f,0x00,0x46,0x30,0x25,0xb0,0x07,0x3c,
-0x4c,0x00,0xe2,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x19,0x00,0x60,0x10,
-0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x16,0x00,0x82,0x10,0x00,0x00,0x00,0x00,
-0x00,0x08,0xe3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,
-0x12,0x00,0x40,0x10,0x4b,0x00,0xc2,0x2c,0x29,0x00,0x40,0x10,0x01,0x00,0x04,0x24,
-0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x2f,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,
-0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x00,0x00,0x00,0x00,0x29,0x00,0x40,0x10,
-0x25,0xb0,0x02,0x3c,0x20,0x00,0x03,0x24,0x87,0x0c,0x42,0x34,0x00,0x00,0x43,0xa0,
-0xd3,0x42,0x80,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x0f,0x00,0x40,0x10,
-0x01,0x00,0x04,0x24,0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x2c,0x00,0x40,0x10,
-0x23,0x00,0xc2,0x2c,0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x00,0x00,0x00,0x00,
-0x26,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x44,0x00,0x03,0x24,0x30,0x0c,0x42,0x34,
-0x00,0x00,0x43,0xa0,0xed,0x14,0x00,0x08,0xd3,0x42,0x80,0xa0,0xd3,0x42,0xa2,0x90,
-0x00,0x00,0x00,0x00,0xef,0xff,0x44,0x10,0x30,0x0c,0xe3,0x34,0x43,0x00,0x02,0x24,
-0xd3,0x42,0xa4,0xa0,0x00,0x00,0x62,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0xd3,0x42,0xa2,0x90,0x00,0x00,0x00,0x00,0xd5,0xff,0x44,0x10,0x87,0x0c,0xe3,0x34,
-0x10,0x00,0x02,0x24,0xd3,0x42,0xa4,0xa0,0x00,0x00,0x62,0xa0,0x06,0x15,0x00,0x08,
-0x00,0x00,0x00,0x00,0x23,0x00,0xc2,0x2c,0xda,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
-0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x02,0x00,0x03,0x24,0xd5,0xff,0x43,0x10,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34,0xd3,0x42,0x83,0xa0,
-0x00,0x00,0x40,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x23,0x00,0xc2,0x2c,
-0xcc,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,
-0x02,0x00,0x03,0x24,0xc7,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
-0xd3,0x42,0x83,0xa0,0x30,0x0c,0x42,0x34,0x42,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x02,0x80,0x02,0x3c,0x68,0x15,0x45,0x24,
-0xd5,0x42,0xa3,0x90,0x02,0x00,0x02,0x24,0x03,0x00,0x62,0x10,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xdc,0x63,0xa2,0x8c,0x25,0xb0,0x03,0x3c,
-0x0a,0x0a,0x68,0x34,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,0x1a,0x00,0x44,0x2c,
-0x14,0x00,0x42,0x2c,0x01,0x0a,0x66,0x34,0x0b,0x00,0x40,0x14,0x2e,0x0a,0x67,0x34,
-0xf3,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0xd4,0x42,0xa4,0x90,0x01,0x00,0x02,0x24,
-0x01,0x0a,0x67,0x34,0x0f,0x00,0x82,0x10,0x2e,0x0a,0x66,0x34,0xd4,0x42,0xa0,0xa0,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x40,0x00,0x02,0x24,0x00,0x00,0xc2,0xa0,
-0x01,0x00,0x03,0x24,0xdf,0xff,0x02,0x24,0xd4,0x42,0xa3,0xa0,0x00,0x00,0xe2,0xa0,
-0x03,0x00,0x03,0x24,0x21,0x10,0x00,0x00,0x00,0x00,0x03,0xa1,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x47,0x00,0x02,0x24,0x00,0x00,0xe2,0xa0,0xd3,0xff,0x03,0x24,
-0x83,0xff,0x02,0x24,0x00,0x00,0xc3,0xa0,0x00,0x00,0x02,0xa1,0x48,0x15,0x00,0x08,
-0xd4,0x42,0xa0,0xa0,0xd0,0xff,0xbd,0x27,0x1c,0x00,0xb1,0xaf,0x28,0x00,0xbf,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0xff,0xff,0x11,0x24,
-0x02,0x80,0x13,0x3c,0x41,0xb0,0x02,0x3c,0x68,0x15,0x66,0x26,0x04,0x00,0x42,0x34,
-0x00,0x00,0x47,0x8c,0x00,0x4b,0xc5,0x8c,0x02,0x80,0x03,0x3c,0x96,0x7d,0x64,0x90,
-0xfc,0x4a,0xc8,0x8c,0x02,0x80,0x02,0x3c,0xb8,0x7d,0x49,0x90,0x25,0xb0,0x0a,0x3c,
-0x25,0x90,0xa7,0x00,0xb0,0x03,0x42,0x35,0x00,0x00,0x52,0xac,0x00,0x24,0x04,0x00,
-0x00,0x00,0x48,0xac,0x84,0x02,0x43,0x35,0x8c,0x02,0x45,0x35,0x01,0x00,0x02,0x24,
-0x00,0x00,0x72,0xac,0x00,0x00,0xa4,0xac,0xb9,0x04,0x22,0x11,0x00,0x4b,0xd2,0xac,
-0x68,0x15,0x66,0x26,0xfc,0x4a,0xc2,0x8c,0x00,0x00,0x00,0x00,0x24,0x28,0x52,0x00,
-0x01,0x00,0xa3,0x30,0x09,0x00,0x60,0x10,0x04,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,
-0x25,0xb0,0x03,0x3c,0x01,0x00,0x04,0x24,0x01,0x00,0x42,0x38,0xb0,0x03,0x63,0x34,
-0x00,0x00,0x64,0xac,0x00,0x4b,0xc2,0xac,0x04,0x00,0xa2,0x30,0x09,0x00,0x40,0x10,
-0x08,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x25,0xb0,0x03,0x3c,0x04,0x00,0x04,0x24,
-0x04,0x00,0x42,0x38,0xb0,0x03,0x63,0x34,0x00,0x00,0x64,0xac,0x00,0x4b,0xc2,0xac,
-0x08,0x00,0xa2,0x30,0x0e,0x00,0x40,0x10,0x68,0x15,0x64,0x26,0xc9,0x64,0xc2,0x90,
-0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,
-0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0xc9,0x64,0xc0,0xa0,0x00,0x4b,0xc2,0x8c,
-0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x38,0x00,0x4b,0xc2,0xac,0x68,0x15,0x64,0x26,
-0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x10,0x00,0x42,0x30,
-0x0d,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,
-0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,
-0x00,0x00,0x43,0xa0,0xc9,0x64,0x80,0xa0,0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x10,0x00,0x42,0x38,0x00,0x4b,0x82,0xac,0x68,0x15,0x64,0x26,0xfc,0x4a,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x20,0x00,0x42,0x30,0x0e,0x00,0x40,0x10,
-0x00,0x00,0x00,0x00,0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,
-0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,
-0xc9,0x64,0x80,0xa0,0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x38,
-0x00,0x4b,0x82,0xac,0x68,0x15,0x64,0x26,0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x24,0x10,0x52,0x00,0x40,0x00,0x42,0x30,0x0d,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,
-0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0xc9,0x64,0x80,0xa0,
-0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x38,0x00,0x4b,0x82,0xac,
-0x68,0x15,0x64,0x26,0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,
-0x80,0x00,0x42,0x30,0x0e,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xc9,0x64,0x82,0x90,
-0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,
-0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0xc9,0x64,0x80,0xa0,0x00,0x4b,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x38,0x00,0x4b,0x82,0xac,0x68,0x15,0x64,0x26,
-0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x01,0x42,0x30,
-0x0d,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,
-0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,
-0x00,0x00,0x43,0xa0,0xc9,0x64,0x80,0xa0,0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x01,0x42,0x38,0x00,0x4b,0x82,0xac,0x68,0x15,0x64,0x26,0xfc,0x4a,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x02,0x42,0x30,0x0e,0x00,0x40,0x10,
-0x00,0x00,0x00,0x00,0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,
-0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,
-0xc9,0x64,0x80,0xa0,0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x38,
-0x00,0x4b,0x82,0xac,0x68,0x15,0x64,0x26,0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x24,0x10,0x52,0x00,0x00,0x04,0x42,0x30,0x0d,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,
-0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0xc9,0x64,0x80,0xa0,
-0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x04,0x42,0x38,0x00,0x4b,0x82,0xac,
-0x68,0x15,0x63,0x26,0xfc,0x4a,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,
-0x00,0x08,0x42,0x30,0x3a,0x00,0x40,0x10,0x2a,0xb0,0x05,0x3c,0x00,0x00,0xa8,0x8c,
-0xff,0x00,0x02,0x24,0xff,0x00,0x04,0x31,0x31,0x00,0x82,0x10,0x00,0x80,0x02,0x31,
-0x08,0x04,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,
-0x05,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xc9,0x64,0x62,0x90,0x00,0x00,0x00,0x00,
-0x0b,0x00,0x40,0x18,0xff,0x00,0x02,0x24,0x08,0x64,0x62,0x90,0x20,0xb0,0x03,0x3c,
-0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x48,0x8c,0x25,0xb0,0x03,0x3c,
-0xb0,0x03,0x63,0x34,0x00,0x00,0x68,0xac,0xff,0x00,0x04,0x31,0xff,0x00,0x02,0x24,
-0x1a,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,0xc0,0x64,0x05,0x8e,
-0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
-0x54,0x64,0x03,0xae,0x21,0x20,0x00,0x00,0x08,0x64,0x08,0xa2,0x20,0x00,0x07,0x24,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x4a,0x05,0x8e,0x02,0x80,0x06,0x3c,
-0x6c,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c,
-0x04,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,
-0x00,0x00,0x65,0xac,0x6c,0x7e,0xc4,0xac,0xfc,0x4a,0x05,0xae,0x68,0x15,0x63,0x26,
-0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x08,0x42,0x38,0x00,0x4b,0x62,0xac,
-0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,
-0x00,0x10,0x42,0x30,0x38,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,0x08,0x00,0x43,0x34,
-0x00,0x00,0x68,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x04,0x31,0x2c,0x00,0x82,0x10,
-0x00,0x80,0x02,0x31,0xca,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,
-0x24,0x10,0x02,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x10,0x64,0xa2,0x90,
-0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x48,0x8c,
-0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x68,0xac,0xff,0x00,0x04,0x31,
-0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,
-0xd8,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x21,0x30,0x60,0x00,0x6c,0x64,0x03,0xae,0x01,0x00,0x04,0x24,0x10,0x64,0x08,0xa2,
-0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x4a,0x05,0x8e,
-0x02,0x80,0x06,0x3c,0x6c,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,
-0x25,0xb0,0x02,0x3c,0x10,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,
-0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0x6c,0x7e,0xc4,0xac,0xfc,0x4a,0x05,0xae,
-0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,
-0x00,0x4b,0x62,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x00,0x00,0x00,0x00,
-0x24,0x10,0x52,0x00,0x00,0x20,0x42,0x30,0x37,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,
-0x04,0x00,0x43,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x04,0x31,
-0xab,0x03,0x82,0x10,0x00,0x80,0x02,0x31,0x90,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,
-0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
-0x0c,0x64,0xa2,0x90,0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,
-0x0c,0x00,0x48,0x8c,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x68,0xac,
-0xff,0x00,0x04,0x31,0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0xff,0x00,0x03,0x31,
-0x68,0x15,0x70,0x26,0xcc,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
-0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x60,0x64,0x03,0xae,0x01,0x00,0x04,0x24,
-0x0c,0x64,0x08,0xa2,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0xfc,0x4a,0x05,0x8e,0x02,0x80,0x06,0x3c,0x6c,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,
-0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c,0x20,0x00,0x84,0x34,0x80,0x03,0x42,0x34,
-0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0x6c,0x7e,0xc4,0xac,
-0xfc,0x4a,0x05,0xae,0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x20,0x42,0x38,0x00,0x4b,0x62,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,
-0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x80,0x42,0x30,0x59,0x00,0x40,0x10,
-0x2a,0xb0,0x06,0x3c,0x0c,0x00,0xc3,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x07,0x24,
-0xff,0x00,0x04,0x31,0x78,0x03,0x87,0x10,0x00,0x80,0x02,0x31,0x24,0x00,0x40,0x14,
-0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x22,0x00,0x40,0x10,
-0xff,0x00,0x02,0x24,0x40,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x44,0x30,0x0f,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0xe8,0x63,0xa4,0xa0,
-0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x09,0x00,0x83,0x10,
-0x68,0x15,0x62,0x26,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,
-0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0xe8,0x63,0xe3,0xa0,
-0x68,0x15,0x62,0x26,0xe8,0x63,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,
-0x21,0x18,0x62,0x00,0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
-0xff,0x00,0x04,0x31,0x00,0x00,0x48,0xac,0x16,0x17,0x00,0x08,0xff,0x00,0x02,0x24,
-0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x24,0x00,0x82,0x10,0x68,0x15,0x70,0x26,
-0xff,0x00,0x03,0x31,0x90,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
-0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xe8,0x63,0x08,0xa2,0x24,0x64,0x03,0xae,
-0x03,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0x02,0x80,0x0a,0x3c,0x7c,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,0x6c,0x7e,0x25,0x8d,
-0xfc,0x4a,0x06,0x8e,0x01,0x00,0x08,0x3c,0x80,0xff,0x02,0x24,0x25,0x38,0xe2,0x00,
-0x00,0x80,0x03,0x35,0x80,0x00,0xa5,0x34,0x27,0x18,0x03,0x00,0x00,0x26,0x07,0x00,
-0x25,0xb0,0x02,0x3c,0x24,0x30,0xc3,0x00,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,
-0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x27,0x88,0x08,0x00,0x00,0x00,0x66,0xac,
-0x6c,0x7e,0x25,0xad,0x7c,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x63,0x26,
-0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,0x00,0x4b,0x62,0xac,
-0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x01,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,
-0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x56,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,
-0x10,0x00,0xc3,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x04,0x31,
-0x23,0x03,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,
-0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,
-0xff,0x00,0x02,0x24,0x41,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0xec,0x63,0xa4,0xa0,
-0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
-0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
-0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0xec,0x63,0xe3,0xa0,0x68,0x15,0x62,0x26,
-0xec,0x63,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,
-0x00,0x00,0x48,0xac,0x75,0x17,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0xff,0x00,0x02,0x24,0x22,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,
-0x90,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x21,0x30,0x60,0x00,0xec,0x63,0x08,0xa2,0x24,0x64,0x03,0xae,0x03,0x00,0x04,0x24,
-0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,
-0x7c,0x7e,0x27,0x91,0x02,0x80,0x08,0x3c,0x6c,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,
-0x01,0x00,0x02,0x3c,0x00,0x80,0x42,0x34,0x40,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,
-0x24,0x30,0xc2,0x00,0x80,0x00,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,
-0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,
-0x00,0x00,0x66,0xac,0x6c,0x7e,0x05,0xad,0x7c,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,
-0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x01,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,
-0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x02,0x00,0x03,0x3c,
-0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,
-0x14,0x00,0xc3,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x04,0x31,
-0xcc,0x02,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,
-0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,
-0xff,0x00,0x02,0x24,0x42,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0xf0,0x63,0xa4,0xa0,
-0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
-0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
-0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0xf0,0x63,0xe3,0xa0,0x68,0x15,0x62,0x26,
-0xf0,0x63,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,
-0x00,0x00,0x48,0xac,0xd1,0x17,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,
-0x9c,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x21,0x30,0x60,0x00,0xf0,0x63,0x08,0xa2,0x30,0x64,0x03,0xae,0x04,0x00,0x04,0x24,
-0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,
-0x7c,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,0x6c,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,
-0x06,0x00,0x02,0x3c,0x20,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,
-0x00,0x01,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,
-0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,
-0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0x6c,0x7e,0x25,0xad,
-0x7c,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,0x00,0x00,0x11,0xad,0x68,0x15,0x62,0x26,
-0x00,0x4b,0x43,0x8c,0x02,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,
-0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x04,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,
-0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x58,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,
-0xb0,0x03,0x62,0x34,0x2a,0xb0,0x09,0x3c,0x00,0x00,0x51,0xac,0x18,0x00,0x26,0x35,
-0x00,0x00,0xc8,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x04,0x31,0x3a,0x02,0x87,0x10,
-0x04,0x00,0x02,0x24,0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,
-0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
-0x43,0x00,0x26,0x35,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,
-0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0xf4,0x63,0xa4,0xa0,0x00,0x00,0xc2,0x90,
-0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,
-0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,
-0xff,0x00,0x44,0x30,0xf4,0x63,0xe3,0xa0,0x68,0x15,0x62,0x26,0xf4,0x63,0x43,0x90,
-0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x68,0x8c,
-0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,0x00,0x00,0x48,0xac,
-0x34,0x18,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0xc2,0xac,0xff,0x00,0x02,0x24,
-0x21,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,0x9c,0x64,0x05,0x8e,
-0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
-0xf4,0x63,0x08,0xa2,0x30,0x64,0x03,0xae,0x04,0x00,0x04,0x24,0x20,0x00,0x07,0x24,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0x7c,0x7e,0x27,0x91,
-0x02,0x80,0x08,0x3c,0x6c,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,0x06,0x00,0x02,0x3c,
-0x10,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x01,0xa5,0x34,
-0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,
-0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,0x6c,0x7e,0x05,0xad,
-0x7c,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,
-0x04,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,
-0xfc,0x4a,0xa2,0x8c,0x08,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,
-0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x1c,0x00,0xc3,0x34,0x00,0x00,0x68,0x8c,
-0xff,0x00,0x07,0x24,0xff,0x00,0x04,0x31,0x13,0x02,0x87,0x10,0x25,0xb0,0x02,0x3c,
-0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,
-0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x44,0x00,0xc6,0x34,
-0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,
-0x68,0x15,0x62,0x26,0xf8,0x63,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,
-0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,
-0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,
-0xf8,0x63,0xe3,0xa0,0x68,0x15,0x62,0x26,0xf8,0x63,0x43,0x90,0x20,0xb0,0x02,0x3c,
-0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,
-0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,0x00,0x00,0x48,0xac,0x8f,0x18,0x00,0x08,
-0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,
-0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,0xa8,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,
-0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xf8,0x63,0x08,0xa2,
-0x3c,0x64,0x03,0xae,0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,0x7c,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,
-0x6c,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,0x18,0x00,0x02,0x3c,0x08,0x00,0xe7,0x34,
-0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x02,0xa5,0x34,0x25,0xb0,0x03,0x3c,
-0x10,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,
-0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,
-0x00,0x00,0x46,0xac,0x6c,0x7e,0x25,0xad,0x7c,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,
-0x00,0x00,0x11,0xad,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x08,0x00,0x04,0x3c,
-0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,
-0x10,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,
-0x58,0x00,0x40,0x10,0x25,0xb0,0x06,0x3c,0xb0,0x03,0xc2,0x34,0x2a,0xb0,0x09,0x3c,
-0x00,0x00,0x51,0xac,0x20,0x00,0x23,0x35,0x00,0x00,0x68,0x8c,0xff,0x00,0x07,0x24,
-0xff,0x00,0x04,0x31,0x80,0x01,0x87,0x10,0x90,0x03,0xc2,0x34,0x00,0x80,0x02,0x31,
-0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,
-0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x45,0x00,0x26,0x35,0x00,0x00,0xc2,0x90,
-0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,
-0x04,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,
-0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,
-0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x04,0x64,0xe3,0xa0,
-0x68,0x15,0x62,0x26,0x04,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,
-0x21,0x18,0x62,0x00,0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
-0xff,0x00,0x04,0x31,0x00,0x00,0x48,0xac,0xf2,0x18,0x00,0x08,0xff,0x00,0x02,0x24,
-0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,0x68,0x15,0x70,0x26,
-0xff,0x00,0x03,0x31,0xa8,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
-0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x04,0x64,0x08,0xa2,0x3c,0x64,0x03,0xae,
-0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0x02,0x80,0x09,0x3c,0x7c,0x7e,0x27,0x91,0x02,0x80,0x08,0x3c,0x6c,0x7e,0x05,0x8d,
-0xfc,0x4a,0x06,0x8e,0x18,0x00,0x02,0x3c,0x01,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,
-0x24,0x30,0xc2,0x00,0x00,0x02,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,
-0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,
-0x00,0x00,0x66,0xac,0x6c,0x7e,0x05,0xad,0x7c,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,
-0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x10,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,
-0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x20,0x00,0x03,0x3c,
-0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,
-0x24,0x00,0xc3,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x04,0x31,
-0x28,0x01,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,
-0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,
-0xff,0x00,0x02,0x24,0x46,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0xfc,0x63,0xa4,0xa0,
-0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
-0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
-0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0xfc,0x63,0xe3,0xa0,0x68,0x15,0x62,0x26,
-0xfc,0x63,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,
-0x00,0x00,0x48,0xac,0x4d,0x19,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,
-0xb4,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x21,0x30,0x60,0x00,0xfc,0x63,0x08,0xa2,0x48,0x64,0x03,0xae,0x06,0x00,0x04,0x24,
-0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,
-0x7c,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,0x6c,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,
-0x60,0x00,0x02,0x3c,0x04,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,
-0x00,0x04,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x40,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,
-0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,
-0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0x6c,0x7e,0x25,0xad,
-0x7c,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,0x00,0x00,0x11,0xad,0x68,0x15,0x62,0x26,
-0x00,0x4b,0x43,0x8c,0x20,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,
-0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x40,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,
-0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x68,0x15,0x70,0x26,
-0x25,0xb0,0x02,0x3c,0x2a,0xb0,0x07,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x51,0xac,
-0x28,0x00,0xe3,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x06,0x24,0xff,0x00,0x04,0x31,
-0xc9,0x00,0x86,0x10,0x25,0xbd,0x02,0x3c,0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,
-0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,
-0xff,0x00,0x02,0x24,0x47,0x00,0xe7,0x34,0x00,0x00,0xe2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x44,0x30,0x0e,0x00,0x86,0x10,0x68,0x15,0x62,0x26,0x00,0x64,0xa4,0xa0,
-0x00,0x00,0xe2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
-0x21,0x30,0xa0,0x00,0x21,0x28,0xe0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
-0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x00,0x64,0xc3,0xa0,0x68,0x15,0x62,0x26,
-0x00,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,
-0x00,0x00,0x48,0xac,0xb1,0x19,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,
-0xb4,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x21,0x30,0x60,0x00,0x00,0x64,0x08,0xa2,0x48,0x64,0x03,0xae,0x06,0x00,0x04,0x24,
-0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,
-0x7c,0x7e,0x27,0x91,0x02,0x80,0x08,0x3c,0x6c,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,
-0x60,0x00,0x02,0x3c,0x02,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,
-0x00,0x04,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,
-0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,
-0x6c,0x7e,0x05,0xad,0x7c,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26,
-0x00,0x4b,0x43,0x8c,0x40,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,
-0x68,0x15,0x70,0x26,0xfc,0x4a,0x06,0x8e,0x00,0x04,0x11,0x3c,0x24,0x10,0xd2,0x00,
-0x24,0x10,0x51,0x00,0x4c,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x24,0x28,0xd2,0x00,
-0x00,0x08,0x04,0x3c,0x24,0x10,0xa4,0x00,0x08,0x00,0x40,0x10,0x80,0x00,0x07,0x3c,
-0x00,0x4b,0x03,0x8e,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,
-0x00,0x00,0x44,0xac,0x00,0x4b,0x03,0xae,0x80,0x00,0x07,0x3c,0x24,0x10,0xa7,0x00,
-0x21,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x4b,0x03,0x8e,0x25,0xb0,0x08,0x3c,
-0xb0,0x03,0x09,0x35,0x2a,0xb0,0x02,0x3c,0x00,0x00,0x23,0xad,0x36,0x00,0x42,0x34,
-0x00,0x00,0x43,0x90,0x23,0xb0,0x04,0x3c,0xff,0x1f,0x02,0x3c,0xc0,0x18,0x03,0x00,
-0xf0,0x07,0x63,0x30,0x5c,0x65,0x05,0x8e,0x21,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
-0x24,0x18,0x62,0x00,0x59,0x00,0x65,0x10,0x60,0x65,0x03,0xae,0x02,0x80,0x05,0x3c,
-0x6c,0x7e,0xa3,0x8c,0x27,0x20,0x07,0x00,0x24,0x20,0xc4,0x00,0x00,0x08,0x63,0x34,
-0x41,0xb0,0x02,0x3c,0x00,0x00,0x23,0xad,0x00,0x00,0x44,0xac,0x6c,0x7e,0xa3,0xac,
-0xfc,0x4a,0x04,0xae,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x80,0x00,0x04,0x3c,
-0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x66,0x26,0xfc,0x4a,0xc3,0x8c,
-0x00,0x01,0x04,0x3c,0x24,0x28,0x72,0x00,0x24,0x10,0xa4,0x00,0x06,0x00,0x40,0x10,
-0x25,0xb0,0x02,0x3c,0x00,0x4b,0xc3,0x8c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,
-0x00,0x00,0x44,0xac,0x00,0x4b,0xc3,0xac,0x00,0x02,0x04,0x3c,0x24,0x10,0xa4,0x00,
-0x06,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0x00,0x4b,0xc2,0x8c,0xb0,0x03,0x63,0x34,
-0x26,0x10,0x44,0x00,0x00,0x4b,0xc2,0xac,0x00,0x00,0x64,0xac,0x28,0x00,0xbf,0x8f,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x5b,0x4e,0x00,0x0c,0x07,0x00,0x04,0x24,
-0x00,0x4b,0x03,0x8e,0xfc,0x4a,0x06,0x8e,0x25,0xb0,0x02,0x3c,0x26,0x18,0x71,0x00,
-0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0xdf,0x19,0x00,0x08,0x00,0x4b,0x03,0xae,
-0x56,0x01,0x42,0x35,0x00,0x00,0x43,0x94,0x00,0x00,0x00,0x00,0x44,0xfb,0x60,0x10,
-0x00,0x00,0x00,0x00,0x5b,0x4e,0x00,0x0c,0x07,0x00,0x04,0x24,0x7d,0x15,0x00,0x08,
-0x68,0x15,0x66,0x26,0x00,0x00,0xa2,0xac,0x48,0x16,0x00,0x08,0xff,0x00,0x02,0x24,
-0x00,0x00,0x62,0xac,0x85,0x16,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0xc2,0x16,0x00,0x08,0xff,0x00,0x02,0x24,0x90,0x03,0x63,0x34,0x00,0x00,0x62,0xac,
-0x57,0x18,0x00,0x08,0x68,0x15,0x62,0x26,0x00,0x00,0x40,0xac,0x15,0x19,0x00,0x08,
-0x68,0x15,0x62,0x26,0x02,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0x74,0x19,0x00,0x08,0x68,0x15,0x62,0x26,0x01,0x00,0x03,0x24,0x90,0x03,0x42,0x34,
-0x00,0x00,0x43,0xac,0xd4,0x19,0x00,0x08,0x68,0x15,0x62,0x26,0xd0,0x03,0x03,0x35,
-0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0x0a,0x1a,0x00,0x08,0x68,0x15,0x62,0x26,
-0x25,0xb0,0x02,0x3c,0x07,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x20,0x42,0x38,
-0xe2,0x16,0x00,0x08,0x00,0x4b,0x62,0xac,0x25,0xb0,0x02,0x3c,0x07,0x00,0x03,0x24,
-0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,0x40,0x17,0x00,0x08,0x00,0x4b,0x62,0xac,
-0x06,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x99,0x17,0x00,0x08,
-0x68,0x15,0x62,0x26,0x05,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0xf8,0x17,0x00,0x08,0x68,0x15,0x62,0x26,0x03,0x00,0x03,0x24,0x90,0x03,0x42,0x34,
-0x00,0x00,0x43,0xac,0xb6,0x18,0x00,0x08,0x68,0x15,0x62,0x26,0x25,0xb0,0x0d,0x3c,
-0x00,0x80,0x02,0x3c,0x18,0x03,0xa4,0x35,0xfc,0x69,0x42,0x24,0x02,0x80,0x03,0x3c,
-0x41,0xb0,0x08,0x3c,0x00,0x00,0x82,0xac,0x68,0x15,0x6a,0x24,0x0a,0x00,0x02,0x35,
-0x00,0x00,0x44,0x94,0x0a,0x4b,0x43,0x95,0x08,0x4b,0x4b,0x95,0x25,0x18,0x64,0x00,
-0xff,0xff,0x6c,0x30,0x24,0x10,0x8b,0x01,0x02,0x00,0x42,0x30,0x4d,0x00,0x40,0x10,
-0x02,0x00,0x64,0x38,0x02,0x00,0x02,0x24,0xc0,0x03,0xa3,0x35,0x00,0x00,0x62,0xac,
-0x0a,0x4b,0x44,0xa5,0x24,0x38,0x8b,0x01,0x04,0x00,0xe2,0x30,0x0a,0x00,0x40,0x10,
-0x08,0x00,0xe2,0x30,0x0a,0x4b,0x43,0x95,0x0c,0x00,0x04,0x35,0xc0,0x03,0xa5,0x35,
-0x04,0x00,0x63,0x38,0x04,0x00,0x02,0x24,0x00,0x00,0x86,0x8c,0x00,0x00,0xa2,0xac,
-0x0a,0x4b,0x43,0xa5,0x08,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,0x10,0x00,0xe2,0x30,
-0x0a,0x4b,0x42,0x95,0xc0,0x03,0xa4,0x35,0x08,0x00,0x03,0x24,0x08,0x00,0x42,0x38,
-0x00,0x00,0x83,0xac,0x0a,0x4b,0x42,0xa5,0x10,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,
-0x20,0x00,0xe2,0x30,0x0a,0x4b,0x42,0x95,0xc0,0x03,0xa4,0x35,0x10,0x00,0x03,0x24,
-0x10,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x0a,0x4b,0x42,0xa5,0x20,0x00,0xe2,0x30,
-0x08,0x00,0x40,0x10,0x80,0x00,0xe2,0x30,0x0a,0x4b,0x42,0x95,0xc0,0x03,0xa4,0x35,
-0x20,0x00,0x03,0x24,0x20,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x0a,0x4b,0x42,0xa5,
-0x80,0x00,0xe2,0x30,0x15,0x00,0x40,0x10,0x24,0x10,0x8b,0x01,0x02,0x80,0x09,0x3c,
-0x0a,0x4b,0x46,0x95,0x6c,0x7e,0x25,0x8d,0x08,0x00,0x02,0x3c,0x7f,0xff,0x04,0x24,
-0x24,0x20,0x64,0x01,0x25,0x28,0xa2,0x00,0x80,0x00,0xc6,0x38,0xb0,0x03,0xa7,0x35,
-0x08,0x00,0x08,0x35,0xc0,0x03,0xa3,0x35,0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0x21,0x58,0x80,0x00,0x00,0x00,0xe5,0xac,0x0a,0x4b,0x46,0xa5,0x6c,0x7e,0x25,0xad,
-0x00,0x00,0x04,0xa5,0x08,0x4b,0x44,0xa5,0x24,0x10,0x8b,0x01,0x00,0x30,0x42,0x30,
-0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x0a,0x4b,0x42,0x95,0x00,0x00,0x00,0x00,
-0x00,0x10,0x42,0x38,0x00,0x20,0x42,0x34,0x0a,0x4b,0x42,0xa5,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x95,0x1a,0x00,0x08,0x0a,0x4b,0x43,0xa5,0xf8,0xff,0xbd,0x27,
-0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0x00,0x40,0x02,0x40,0x00,0x68,0x08,0x40,
-0x00,0x70,0x02,0x40,0x00,0x60,0x09,0x40,0x25,0xb0,0x05,0x3c,0x00,0x80,0x02,0x3c,
-0x18,0x03,0xa3,0x34,0x7c,0x6b,0x42,0x24,0x00,0x00,0x62,0xac,0x80,0x00,0x87,0x8c,
-0x7c,0x02,0xa2,0x34,0x84,0x02,0xa3,0x34,0x88,0x02,0xa6,0x34,0x00,0x00,0x47,0xac,
-0x00,0x00,0x68,0xac,0x00,0x00,0xc9,0xac,0x74,0x00,0x83,0x8c,0x8c,0x02,0xa2,0x34,
-0x90,0x02,0xa7,0x34,0x00,0x00,0x43,0xac,0x08,0x00,0x86,0x8c,0x94,0x02,0xa8,0x34,
-0x98,0x02,0xa9,0x34,0x00,0x00,0xe6,0xac,0x0c,0x00,0x82,0x8c,0x9c,0x02,0xa6,0x34,
-0xa0,0x02,0xa7,0x34,0x00,0x00,0x02,0xad,0x10,0x00,0x83,0x8c,0xa4,0x02,0xa8,0x34,
-0xa8,0x02,0xaa,0x34,0x00,0x00,0x23,0xad,0x14,0x00,0x82,0x8c,0xac,0x02,0xa9,0x34,
-0xb0,0x02,0xab,0x34,0x00,0x00,0xc2,0xac,0x18,0x00,0x83,0x8c,0xb4,0x02,0xa6,0x34,
-0xb8,0x02,0xac,0x34,0x00,0x00,0xe3,0xac,0x1c,0x00,0x82,0x8c,0xbc,0x02,0xa7,0x34,
-0xc0,0x02,0xad,0x34,0x00,0x00,0x02,0xad,0x20,0x00,0x83,0x8c,0xc4,0x02,0xa8,0x34,
-0xc8,0x02,0xae,0x34,0x00,0x00,0x43,0xad,0x24,0x00,0x82,0x8c,0xcc,0x02,0xaa,0x34,
-0xd0,0x02,0xaf,0x34,0x00,0x00,0x22,0xad,0x28,0x00,0x83,0x8c,0xd4,0x02,0xa9,0x34,
-0xd8,0x02,0xb0,0x34,0x00,0x00,0x63,0xad,0x2c,0x00,0x82,0x8c,0x70,0x02,0xab,0x34,
-0x74,0x02,0xb1,0x34,0x00,0x00,0xc2,0xac,0x30,0x00,0x83,0x8c,0x78,0x02,0xa5,0x34,
-0x00,0x00,0x83,0xad,0x34,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0xac,
-0x38,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xad,0x3c,0x00,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xad,0x40,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc3,0xad,0x44,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0xad,
-0x48,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe3,0xad,0x4c,0x00,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xad,0x50,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x00,0x03,0xae,0x54,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xad,
-0x58,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xae,0x5c,0x00,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,0x42,0x1b,0x00,0x08,0x00,0x00,0x00,0x00,
-0x00,0x80,0x1b,0x3c,0x10,0x6d,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
-0x00,0x00,0x5b,0xaf,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,
-0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,0x0c,0x00,0x63,0xaf,
-0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,0x1c,0x00,0x67,0xaf,
-0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,0x2c,0x00,0x6b,0xaf,
-0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,0x3c,0x00,0x6f,0xaf,
-0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0x70,0xaf,
-0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,0x50,0x00,0x74,0xaf,
-0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,0x60,0x00,0x78,0xaf,
-0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,0x70,0x00,0x7e,0xaf,
-0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,0x80,0x00,0x6a,0xaf,
-0x00,0x68,0x1a,0x40,0x25,0xb0,0x1b,0x3c,0x1c,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,
-0x00,0x00,0x7a,0xaf,0x7f,0x00,0x5b,0x33,0x30,0x00,0x60,0x13,0x00,0x00,0x00,0x00,
-0x25,0xb0,0x1b,0x3c,0x30,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0xaf,
-0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,
-0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,0x0c,0x00,0x63,0xaf,
-0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,0x1c,0x00,0x67,0xaf,
-0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,0x2c,0x00,0x6b,0xaf,
-0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,0x3c,0x00,0x6f,0xaf,
-0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0x70,0xaf,
-0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,0x50,0x00,0x74,0xaf,
-0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,0x60,0x00,0x78,0xaf,
-0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,0x70,0x00,0x7e,0xaf,
-0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,0x80,0x00,0x6a,0xaf,
-0xdf,0x1a,0x00,0x08,0x21,0x20,0x60,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,
-0x20,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0xad,0x00,0x04,0x5b,0x33,
-0x0a,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0x3c,0x74,0x55,0x08,0x25,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,0x24,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,
-0x00,0x00,0x68,0xaf,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x08,0x5b,0x33,
-0x25,0xb0,0x08,0x3c,0x28,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,
-0x06,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0x3c,0xfc,0x69,0x08,0x25,
-0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x80,0x1a,0x3c,
-0x6c,0x7e,0x5a,0x27,0x04,0x00,0x5b,0x97,0x25,0xb0,0x08,0x3c,0x30,0x03,0x08,0x35,
-0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,0x18,0x00,0x60,0x13,0x00,0x00,0x00,0x00,
-0x08,0xec,0x9b,0x27,0x00,0x00,0x00,0x00,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,
-0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,
-0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,
-0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,
-0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,
-0x80,0x00,0x7b,0x8f,0x2f,0x1c,0x00,0x08,0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,
-0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x08,0x00,0x5b,0xaf,
-0xfc,0xef,0x9d,0x27,0x00,0x00,0x4a,0x8f,0x00,0x00,0x00,0x00,0x21,0x00,0x40,0x11,
-0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c,0xcc,0x7d,0x08,0x25,0x21,0x48,0x00,0x00,
-0x21,0x58,0x00,0x00,0x01,0x00,0x6b,0x25,0x1a,0x00,0x40,0x11,0x24,0x70,0x4b,0x01,
-0x14,0x00,0xc0,0x11,0x01,0x00,0x04,0x24,0x00,0x00,0x00,0x00,0x04,0x00,0x44,0xa3,
-0x26,0x50,0x4b,0x01,0x00,0x00,0x4a,0xaf,0x80,0x80,0x09,0x00,0x21,0x80,0x08,0x02,
-0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x02,0x00,0x00,0x00,0x00,
-0x00,0x80,0x1b,0x3c,0xe8,0x6f,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
-0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x6c,0x7e,0x5a,0x27,0xe1,0xff,0x00,0x10,
-0x00,0x00,0x00,0x00,0x01,0x00,0x29,0x25,0x40,0x58,0x0b,0x00,0xf2,0x1b,0x00,0x08,
-0x00,0x00,0x00,0x00,0x02,0x80,0x1b,0x3c,0x6c,0x7e,0x7b,0x27,0x21,0x60,0x00,0x00,
-0x04,0x00,0x6c,0xa7,0x08,0x00,0x7a,0x8f,0x00,0x00,0x00,0x00,0xf8,0xff,0x5a,0x27,
-0x00,0x00,0x5a,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x5a,0x27,0x84,0x00,0x44,0x8f,
-0x00,0x00,0x00,0x00,0xf9,0xff,0x80,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x41,0x8f,
-0xfc,0x03,0x50,0x7b,0x7c,0x00,0x42,0x7b,0xbc,0x00,0x44,0x7b,0xfc,0x00,0x46,0x7b,
-0x3c,0x01,0x48,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x4a,0x7b,
-0xbc,0x01,0x4c,0x7b,0xfc,0x01,0x4e,0x7b,0x3c,0x02,0x50,0x7b,0x7c,0x02,0x52,0x7b,
-0xbc,0x02,0x54,0x7b,0xfc,0x02,0x56,0x7b,0x3c,0x03,0x58,0x7b,0x7c,0x03,0x5c,0x7b,
-0xbc,0x03,0x5e,0x7b,0x80,0x00,0x5b,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,
-0x10,0x00,0x00,0x42,0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,
-0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,
-0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,
-0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,
-0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,
-0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac,0x54,0x00,0x95,0xac,
-0x58,0x00,0x96,0xac,0x5c,0x00,0x97,0xac,0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,
-0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac,0x74,0x00,0x9f,0xac,
-0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac,0xf8,0xff,0x84,0x24,
-0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,
-0x00,0x00,0x00,0x00,0xf9,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,0x21,0xd8,0x80,0x00,
-0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,
-0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,
-0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,
-0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,
-0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,
-0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,0x00,0x60,0x05,0x40,
-0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,
-0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,
-0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,
-0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,
-0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,
-0x50,0x00,0x94,0xac,0x54,0x00,0x94,0xac,0x58,0x00,0x96,0xac,0x5c,0x00,0x96,0xac,
-0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,
-0x70,0x00,0x9e,0xac,0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac,
-0x84,0x00,0x80,0xac,0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,
-0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,0xfa,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,
-0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,
-0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,
-0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,
-0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,
-0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,
-0x80,0x00,0x7b,0x8f,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xc6,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,0x00,0x00,0x7b,0x27,
-0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x00,0x00,0x05,0x24,
-0x03,0x00,0xa4,0x24,0x00,0xa0,0x80,0x40,0x00,0xa0,0x84,0x40,0x01,0x80,0x04,0x3c,
-0x98,0x03,0x84,0x24,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x80,0x1b,0x3c,0x98,0x03,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
-0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x00,0x00,0x5a,0x27,0xfc,0x03,0x5d,0x27,
-0x02,0x80,0x1c,0x3c,0x00,0x14,0x9c,0x27,0x00,0xf0,0x08,0x3c,0x00,0x0c,0x08,0x35,
-0x00,0x60,0x88,0x40,0x02,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,0xff,0x7f,0x05,0x3c,
-0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x20,0x84,0x4c,0xff,0xff,0x05,0x34,
-0x21,0x28,0xa4,0x00,0x00,0x28,0x85,0x4c,0x00,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,
-0xff,0x7f,0x05,0x3c,0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x00,0x84,0x4c,
-0xff,0x7f,0x06,0x24,0x21,0x30,0xc4,0x00,0x24,0x30,0xc5,0x00,0x00,0x08,0x86,0x4c,
-0x00,0xa0,0x04,0x40,0x10,0x00,0x84,0x34,0x00,0xa0,0x84,0x40,0x01,0x80,0x1b,0x3c,
-0x24,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x84,
-0x20,0x00,0x06,0x24,0x25,0x28,0xa6,0x00,0x00,0x00,0x85,0xa4,0x01,0x80,0x1b,0x3c,
-0x54,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
-0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x8c,0x00,0x00,0x00,0x00,
-0x10,0x00,0xa5,0x30,0xfc,0xff,0xa0,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x07,0x3c,
-0xff,0xff,0xe7,0x34,0x02,0x80,0x05,0x3c,0x88,0x7d,0xa5,0x24,0xff,0xff,0xa5,0x30,
-0x40,0xb0,0x04,0x3c,0x25,0x28,0xa4,0x00,0x24,0x28,0xa7,0x00,0x21,0x30,0x00,0x00,
-0x43,0xb0,0x02,0x3c,0x00,0x80,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x45,0xac,
-0x04,0x00,0x46,0xac,0x08,0x00,0x44,0xac,0x4e,0x58,0x00,0x08,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,
-0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x42,0x24,
-0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x21,0x18,0x40,0x00,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x44,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0x04,0x00,0x85,0x8c,0x00,0x80,0x03,0x3c,0x01,0x00,0x02,0x24,0x25,0x28,0xa3,0x00,
-0x00,0x00,0xa4,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x74,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0x04,0x00,0x82,0x8c,0x02,0x00,0x83,0x94,0x00,0x80,0x07,0x3c,0x25,0x28,0x47,0x00,
-0x00,0x00,0xa2,0x8c,0x10,0x00,0x02,0x24,0x13,0x00,0x62,0x10,0x11,0x00,0x66,0x28,
-0x06,0x00,0xc0,0x10,0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x17,0x00,0x62,0x10,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0xfd,0xff,0x62,0x14,
-0x00,0x00,0x00,0x00,0x08,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xac,
-0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x25,0x10,0x47,0x00,0x00,0x00,0x42,0x8c,
-0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x00,0xa2,0xa4,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x25,0x18,0x67,0x00,
-0x00,0x00,0x62,0x94,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xa0,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
-0x25,0x18,0x67,0x00,0x00,0x00,0x62,0x90,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x1c,0x00,0xbf,0xaf,
-0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x68,0x15,0x31,0x26,0xe4,0x64,0x30,0x96,
-0x02,0x80,0x02,0x3c,0x01,0x80,0x03,0x3c,0x25,0x80,0x02,0x02,0x25,0xb0,0x02,0x3c,
-0x38,0x06,0x63,0x24,0x18,0x03,0x42,0x34,0x60,0x00,0x04,0x26,0x80,0x00,0x05,0x26,
-0x00,0x00,0x43,0xac,0xab,0x45,0x00,0x0c,0x03,0x00,0x06,0x24,0x21,0x20,0x00,0x02,
-0x21,0x28,0x00,0x00,0x97,0x45,0x00,0x0c,0x08,0x00,0x06,0x24,0xe4,0x64,0x22,0x8e,
-0x0c,0x00,0x03,0x24,0x0c,0x00,0x43,0xae,0x08,0x00,0x42,0xae,0x12,0x00,0x02,0x24,
-0x14,0x00,0x42,0xae,0x21,0x20,0x40,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x8b,0x07,0x00,0x08,0x20,0x00,0xbd,0x27,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x02,0x80,0x02,0x3c,0x21,0x48,0x80,0x00,
-0x68,0x15,0x48,0x24,0x21,0x38,0x00,0x00,0x21,0x28,0x27,0x01,0x00,0x00,0xa2,0x90,
-0x21,0x20,0xe8,0x00,0x01,0x00,0xe7,0x24,0x38,0x4c,0x82,0xa0,0x1e,0x00,0xa3,0x90,
-0x1e,0x00,0xe6,0x28,0x56,0x4c,0x83,0xa0,0x3c,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,
-0x74,0x4c,0x82,0xa0,0x5a,0x00,0xa3,0x90,0xf3,0xff,0xc0,0x14,0x92,0x4c,0x83,0xa0,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0x20,0xbd,0x03,0x3c,0x58,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x0f,0x27,0x07,0x24,
-0x20,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0xff,0xff,0xe7,0x24,0xff,0xff,0xe1,0x04,
-0xff,0xff,0xe7,0x24,0x62,0xbd,0x04,0x3c,0x24,0x10,0x82,0x34,0x00,0x00,0x40,0xa0,
-0x28,0x10,0x83,0x34,0x0c,0x11,0x86,0x34,0x0e,0x00,0x02,0x24,0x00,0x00,0x60,0xa0,
-0x00,0x11,0x85,0x34,0x00,0x00,0xc2,0xa0,0x00,0x00,0xa7,0x8c,0xdf,0xff,0x02,0x24,
-0x10,0x00,0x86,0x34,0x24,0x38,0xe2,0x00,0x49,0x0c,0x03,0x24,0xcf,0xff,0x02,0x24,
-0x00,0x00,0xc3,0xac,0x04,0x00,0x84,0x34,0x00,0x00,0xa7,0xac,0x24,0x38,0xe2,0x00,
-0x41,0x0c,0x02,0x24,0x00,0x00,0xa7,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xc2,0xac,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd0,0xff,0xbd,0x27,0x25,0xb0,0x03,0x3c,
-0x01,0x80,0x02,0x3c,0xb0,0x03,0x68,0x34,0x1c,0x00,0xb1,0xaf,0x18,0x03,0x63,0x34,
-0xd8,0xff,0x91,0x24,0xa0,0x08,0x42,0x24,0x00,0x00,0x62,0xac,0x28,0x00,0xbf,0xaf,
-0x00,0x00,0x11,0xad,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,
-0x02,0x80,0x13,0x3c,0x00,0x00,0x23,0x96,0x68,0x15,0x73,0x26,0xff,0xff,0x32,0x32,
-0x40,0x10,0x02,0x3c,0x78,0x64,0x65,0x8e,0x25,0x90,0x42,0x02,0x02,0x80,0x10,0x3c,
-0x8c,0x96,0x10,0x26,0x20,0x00,0x42,0x26,0x00,0x00,0x03,0xad,0x20,0x00,0x06,0x24,
-0x00,0x00,0x02,0xad,0x21,0x38,0x00,0x02,0x0c,0x00,0x03,0xae,0x0a,0x00,0x04,0x24,
-0x64,0x01,0x00,0x0c,0x08,0x00,0x02,0xae,0x04,0x00,0x23,0x8e,0xff,0xe0,0x02,0x24,
-0x28,0x00,0x04,0x24,0x24,0x18,0x62,0x00,0x00,0x10,0x63,0x34,0x02,0x00,0x24,0xa2,
-0x04,0x00,0x23,0xae,0x0c,0x00,0x02,0x8e,0x0a,0x00,0x04,0x24,0xf8,0xff,0x42,0x24,
-0x4d,0x01,0x00,0x0c,0x00,0x00,0x22,0xa6,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0c,0x00,0x07,0x8e,0x20,0x10,0x06,0x3c,
-0x21,0x28,0x40,0x02,0x20,0x00,0xe7,0x24,0x00,0xfe,0xc6,0x34,0xff,0xff,0xe7,0x30,
-0x01,0x00,0x11,0x24,0x0a,0x00,0x04,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xb1,0xaf,
-0xd5,0x4a,0x63,0x92,0x2a,0xb0,0x10,0x3c,0x32,0x00,0x02,0x36,0x01,0x00,0x63,0x24,
-0x00,0x00,0x43,0xa0,0x4d,0x01,0x00,0x0c,0x0a,0x00,0x04,0x24,0xc9,0x64,0x62,0x92,
-0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xc9,0x64,0x62,0xa2,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x01,0x00,0x10,0x36,0x00,0x00,0x11,0xa2,
-0x28,0x00,0xbf,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
-0x18,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
-0x25,0xb0,0x05,0x3c,0x01,0x80,0x03,0x3c,0x21,0x38,0x80,0x00,0x18,0x03,0xa2,0x34,
-0xe8,0x09,0x63,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0x35,0x00,0xe4,0x10,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x10,0x20,0x08,0xa2,0x34,0x02,0x00,0x02,0x24,
-0x83,0x00,0xe2,0x10,0x03,0x00,0x02,0x24,0x5a,0x00,0xe2,0x10,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c,
-0x68,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x74,0x4b,0xc2,0xac,
-0x40,0x08,0x02,0x24,0x78,0x4b,0xc3,0xac,0x84,0x4b,0xc2,0xac,0x78,0x08,0x03,0x24,
-0x0c,0x08,0x02,0x24,0x88,0x4b,0xc3,0xac,0x8c,0x4b,0xc2,0xac,0x10,0x08,0x03,0x24,
-0x20,0x08,0x02,0x24,0x90,0x4b,0xc3,0xac,0x94,0x4b,0xc2,0xac,0x24,0x08,0x03,0x24,
-0x58,0x08,0x02,0x24,0x98,0x4b,0xc3,0xac,0x9c,0x4b,0xc2,0xac,0x50,0x0c,0x03,0x24,
-0x54,0x0c,0x02,0x24,0xa0,0x4b,0xc3,0xac,0xa4,0x4b,0xc2,0xac,0x14,0x0c,0x03,0x24,
-0x10,0x0c,0x02,0x24,0x60,0x08,0x05,0x24,0xa8,0x4b,0xc3,0xac,0xac,0x4b,0xc2,0xac,
-0x80,0x0c,0x03,0x24,0x84,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xb4,0x4b,0xc2,0xac,
-0x80,0x4b,0xc5,0xac,0xb0,0x4b,0xc3,0xac,0x71,0x4b,0xc0,0xa0,0x7c,0x4b,0xc5,0xac,
-0x02,0x00,0x80,0x10,0xa0,0x08,0x02,0x24,0xb8,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,
-0xb8,0x4b,0xc2,0xac,0x28,0x08,0xa2,0x34,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c,
-0x68,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x74,0x4b,0xc2,0xac,
-0x44,0x08,0x02,0x24,0x78,0x4b,0xc3,0xac,0x84,0x4b,0xc2,0xac,0x78,0x08,0x03,0x24,
-0x0c,0x08,0x02,0x24,0x88,0x4b,0xc3,0xac,0x8c,0x4b,0xc2,0xac,0x14,0x08,0x03,0x24,
-0x28,0x08,0x02,0x24,0x90,0x4b,0xc3,0xac,0x94,0x4b,0xc2,0xac,0x2c,0x08,0x03,0x24,
-0x58,0x08,0x02,0x24,0x98,0x4b,0xc3,0xac,0x9c,0x4b,0xc2,0xac,0x58,0x0c,0x03,0x24,
-0x5c,0x0c,0x02,0x24,0xa0,0x4b,0xc3,0xac,0xa4,0x4b,0xc2,0xac,0x1c,0x0c,0x03,0x24,
-0x18,0x0c,0x02,0x24,0x64,0x08,0x05,0x24,0xa8,0x4b,0xc3,0xac,0xac,0x4b,0xc2,0xac,
-0x88,0x0c,0x03,0x24,0x8c,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xb4,0x4b,0xc2,0xac,
-0x71,0x4b,0xc7,0xa0,0x80,0x4b,0xc5,0xac,0xb0,0x4b,0xc3,0xac,0x7c,0x4b,0xc5,0xac,
-0xd6,0xff,0x80,0x10,0xa4,0x08,0x02,0x24,0xbc,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,
-0xb8,0x4b,0xc2,0xac,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0xac,0x08,0x03,0x24,
-0xb8,0x4b,0x43,0xac,0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x74,0x4b,0x43,0xac,
-0x4c,0x08,0x03,0x24,0x78,0x4b,0x44,0xac,0x84,0x4b,0x43,0xac,0x7c,0x08,0x04,0x24,
-0x0c,0x08,0x03,0x24,0x88,0x4b,0x44,0xac,0x8c,0x4b,0x43,0xac,0x1c,0x08,0x04,0x24,
-0x38,0x08,0x03,0x24,0x90,0x4b,0x44,0xac,0x94,0x4b,0x43,0xac,0x3c,0x08,0x04,0x24,
-0x5c,0x08,0x03,0x24,0x98,0x4b,0x44,0xac,0x9c,0x4b,0x43,0xac,0x68,0x0c,0x04,0x24,
-0x6c,0x0c,0x03,0x24,0xa0,0x4b,0x44,0xac,0xa4,0x4b,0x43,0xac,0x2c,0x0c,0x04,0x24,
-0x28,0x0c,0x03,0x24,0x6c,0x08,0x05,0x24,0xa8,0x4b,0x44,0xac,0xac,0x4b,0x43,0xac,
-0x98,0x0c,0x04,0x24,0x9c,0x0c,0x03,0x24,0x71,0x4b,0x47,0xa0,0x80,0x4b,0x45,0xac,
-0xb0,0x4b,0x44,0xac,0xb4,0x4b,0x43,0xac,0x08,0x00,0xe0,0x03,0x7c,0x4b,0x45,0xac,
-0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0xa8,0x08,0x03,0x24,0xb8,0x4b,0x43,0xac,
-0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x74,0x4b,0x43,0xac,0x48,0x08,0x03,0x24,
-0x78,0x4b,0x44,0xac,0x84,0x4b,0x43,0xac,0x7c,0x08,0x04,0x24,0x0c,0x08,0x03,0x24,
-0x88,0x4b,0x44,0xac,0x8c,0x4b,0x43,0xac,0x18,0x08,0x04,0x24,0x30,0x08,0x03,0x24,
-0x90,0x4b,0x44,0xac,0x94,0x4b,0x43,0xac,0x34,0x08,0x04,0x24,0x5c,0x08,0x03,0x24,
-0x98,0x4b,0x44,0xac,0x9c,0x4b,0x43,0xac,0x60,0x0c,0x04,0x24,0x64,0x0c,0x03,0x24,
-0xa0,0x4b,0x44,0xac,0xa4,0x4b,0x43,0xac,0x24,0x0c,0x04,0x24,0x20,0x0c,0x03,0x24,
-0x68,0x08,0x05,0x24,0xa8,0x4b,0x44,0xac,0xac,0x4b,0x43,0xac,0x90,0x0c,0x04,0x24,
-0x94,0x0c,0x03,0x24,0x71,0x4b,0x47,0xa0,0x80,0x4b,0x45,0xac,0xb0,0x4b,0x44,0xac,
-0xb4,0x4b,0x43,0xac,0x08,0x00,0xe0,0x03,0x7c,0x4b,0x45,0xac,0x36,0x43,0x00,0x08,
-0x21,0x18,0x00,0x00,0x20,0x00,0x62,0x2c,0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0x06,0x10,0x64,0x00,0x01,0x00,0x42,0x30,0xfa,0xff,0x40,0x10,0x01,0x00,0x63,0x24,
-0xff,0xff,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xd8,0xff,0xbd,0x27,
-0x25,0xb0,0x02,0x3c,0x18,0x00,0xb2,0xaf,0x21,0x90,0x82,0x00,0xff,0xff,0x02,0x24,
-0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
-0x21,0x88,0xa0,0x00,0x21,0x20,0xa0,0x00,0x21,0x18,0x40,0x02,0x10,0x00,0xa2,0x10,
-0x21,0x98,0xc0,0x00,0x00,0x00,0x50,0x8e,0x31,0x43,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x04,0x10,0x53,0x00,0x27,0x18,0x11,0x00,0x25,0x18,0x62,0x00,0x24,0x18,0x70,0x00,
-0x00,0x00,0x43,0xae,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
-0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x28,0x00,0xbd,0x27,0x00,0x00,0x66,0xac,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x21,0x30,0x80,0x00,0xec,0x60,0x44,0x8c,
-0x3d,0x43,0x00,0x08,0xff,0xff,0x05,0x24,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,
-0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x20,0x82,0x00,
-0x00,0x00,0x90,0x8c,0x21,0x88,0xa0,0x00,0x31,0x43,0x00,0x0c,0x21,0x20,0xa0,0x00,
-0x24,0x80,0x11,0x02,0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,
-0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x28,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf,
-0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x24,0x00,0xb5,0xaf,0x10,0x00,0xb0,0xaf,
-0x68,0x15,0x31,0x26,0x98,0x4b,0x22,0x8e,0x25,0xb0,0x12,0x3c,0x24,0x08,0x53,0x36,
-0x21,0x10,0x52,0x00,0x00,0x00,0x70,0x8e,0x00,0x00,0x55,0x8c,0x7f,0x80,0x03,0x3c,
-0xff,0x7f,0x02,0x3c,0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34,0x24,0x10,0x02,0x02,
-0x24,0x18,0xa3,0x02,0xc0,0x25,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x14,0x3c,
-0x00,0x00,0x62,0xae,0x01,0x00,0x04,0x24,0x84,0x0a,0x00,0x0c,0x25,0xa8,0x74,0x00,
-0x98,0x4b,0x22,0x8e,0x25,0x80,0x14,0x02,0x01,0x00,0x04,0x24,0x21,0x10,0x52,0x00,
-0x00,0x00,0x55,0xac,0x84,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xae,
-0x84,0x0a,0x00,0x0c,0x01,0x00,0x04,0x24,0xb8,0x4b,0x24,0x8e,0x0f,0x00,0x05,0x3c,
-0x28,0x00,0xbf,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0xa5,0x34,
-0x68,0x43,0x00,0x08,0x30,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,
-0x02,0x80,0x11,0x3c,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x68,0x15,0x27,0x26,
-0x73,0x4b,0xe5,0x90,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xb0,0x0e,0x63,0x24,
-0x18,0x03,0x42,0x34,0x02,0x00,0x06,0x24,0x00,0x00,0x43,0xac,0x34,0x00,0xa6,0x10,
-0x21,0x80,0x80,0x00,0x03,0x00,0x03,0x24,0x3a,0x00,0xa3,0x10,0x2e,0x00,0x02,0x2e,
-0x10,0x00,0x02,0x2e,0x07,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0x00,0x04,0x32,
-0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x79,0x43,0x00,0x08,
-0x20,0x00,0xbd,0x27,0xfa,0xff,0xa6,0x14,0xff,0x00,0x04,0x32,0x71,0x4b,0xe4,0x90,
-0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,
-0x00,0x00,0x00,0x00,0x38,0x00,0x85,0x10,0x68,0x15,0x22,0x26,0x2e,0x00,0x83,0x10,
-0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,0x68,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,
-0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,
-0x3d,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0x68,0x15,0x22,0x26,0x71,0x4b,0x44,0x90,
-0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,
-0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0xdb,0xff,0x82,0x14,
-0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,
-0x3d,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,0xc2,0x43,0x00,0x08,0xff,0x00,0x04,0x32,
-0x25,0x00,0x82,0x2c,0xcc,0xff,0x40,0x14,0x03,0x00,0x03,0x24,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0xc7,0xff,0x40,0x14,0x10,0x00,0x02,0x2e,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0x68,0x15,0x22,0x26,0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,
-0x3d,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,0xd4,0x43,0x00,0x08,0x00,0x08,0x04,0x24,
-0xcc,0xff,0x80,0x14,0x68,0x15,0x22,0x26,0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,
-0x3d,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,0xd4,0x43,0x00,0x08,0x00,0x08,0x04,0x24,
-0xb2,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,0x74,0x4b,0x44,0x8c,
-0x0f,0x00,0x05,0x24,0x3d,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,0xc2,0x43,0x00,0x08,
-0xff,0x00,0x04,0x32,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,
-0x68,0x15,0x28,0x26,0x73,0x4b,0x06,0x91,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x5c,0x10,0x63,0x24,0x18,0x03,0x42,0x34,0x02,0x00,0x07,0x24,0x18,0x00,0xb2,0xaf,
-0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00,
-0x39,0x00,0xc7,0x10,0xff,0x00,0x90,0x30,0x03,0x00,0x03,0x24,0x3f,0x00,0xc3,0x10,
-0x2e,0x00,0x02,0x2e,0x10,0x00,0x02,0x2e,0x0c,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0x0f,0x00,0x04,0x3c,0xff,0xff,0x84,0x34,0x24,0x20,0x44,0x02,0x00,0x15,0x10,0x00,
-0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
-0x25,0x20,0x44,0x00,0x63,0x43,0x00,0x08,0x20,0x00,0xbd,0x27,0xf5,0xff,0xc7,0x14,
-0x0f,0x00,0x04,0x3c,0x71,0x4b,0x04,0x91,0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,
-0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x38,0x00,0x86,0x10,
-0x68,0x15,0x22,0x26,0x2e,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,
-0x68,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,
-0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,0x3d,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,
-0x68,0x15,0x22,0x26,0x71,0x4b,0x44,0x90,0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,
-0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,
-0x03,0x00,0x02,0x24,0xd6,0xff,0x82,0x14,0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,
-0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0x3d,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,
-0x2f,0x44,0x00,0x08,0x0f,0x00,0x04,0x3c,0x25,0x00,0x02,0x2e,0xc7,0xff,0x40,0x14,
-0x03,0x00,0x03,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xc1,0xff,0x40,0x14,
-0x00,0x00,0x00,0x00,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x68,0x15,0x22,0x26,
-0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0x3d,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,
-0x46,0x44,0x00,0x08,0x00,0x08,0x04,0x24,0xcc,0xff,0x80,0x14,0x68,0x15,0x22,0x26,
-0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,0x3d,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,
-0x46,0x44,0x00,0x08,0x00,0x08,0x04,0x24,0xad,0xff,0x80,0x14,0x00,0x00,0x00,0x00,
-0x68,0x15,0x22,0x26,0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,0x3d,0x43,0x00,0x0c,
-0x21,0x30,0x00,0x00,0x2f,0x44,0x00,0x08,0x0f,0x00,0x04,0x3c,0xe8,0xff,0xbd,0x27,
-0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00,0x14,0x00,0xbf,0xaf,0x79,0x43,0x00,0x0c,
-0x21,0x20,0x00,0x00,0x40,0x01,0x44,0x34,0x21,0x18,0x40,0x00,0x1f,0x00,0x02,0x2e,
-0x00,0x23,0x04,0x00,0x10,0x00,0x40,0x10,0x10,0x00,0x05,0x2e,0x00,0x01,0x64,0x34,
-0x06,0x00,0xa0,0x10,0x00,0x23,0x04,0x00,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x63,0x43,0x00,0x0c,
-0xf1,0xff,0x10,0x26,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x63,0x43,0x00,0x0c,0xe2,0xff,0x10,0x26,
-0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
-0x18,0x00,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x27,0x38,0x05,0x00,0x21,0x40,0x82,0x00,
-0xff,0xff,0x02,0x24,0x07,0x00,0xa2,0x10,0x25,0x38,0xe6,0x00,0x00,0x00,0x02,0x8d,
-0x00,0x00,0x00,0x00,0x24,0x10,0xe2,0x00,0x00,0x00,0x02,0xad,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xad,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xe8,0x12,0x42,0x24,0x18,0x03,0x63,0x34,
-0xd8,0xff,0xbd,0x27,0x00,0x00,0x62,0xac,0x0f,0x00,0x02,0x3c,0x14,0x00,0xb1,0xaf,
-0xff,0xff,0x42,0x34,0x21,0x88,0xa0,0x00,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
-0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x90,0xc0,0x00,0x21,0x28,0xc0,0x00,
-0x0a,0x00,0x22,0x12,0x21,0x98,0x80,0x00,0xac,0x43,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x21,0x20,0x20,0x02,0x31,0x43,0x00,0x0c,0x21,0x80,0x40,0x00,0x04,0x10,0x52,0x00,
-0x27,0x28,0x11,0x00,0x25,0x28,0xa2,0x00,0x24,0x28,0xb0,0x00,0xff,0x00,0x64,0x32,
-0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x17,0x44,0x00,0x08,0x28,0x00,0xbd,0x27,0x01,0x80,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x74,0x13,0x63,0x24,0x18,0x03,0x42,0x34,0xe0,0xff,0xbd,0x27,
-0x00,0x00,0x43,0xac,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
-0xac,0x43,0x00,0x0c,0x21,0x88,0xa0,0x00,0x21,0x80,0x40,0x00,0x31,0x43,0x00,0x0c,
-0x21,0x20,0x20,0x02,0x24,0x80,0x11,0x02,0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xc8,0xff,0xbd,0x27,0x2c,0x00,0xb1,0xaf,0xff,0xff,0x05,0x24,0x21,0x88,0x80,0x00,
-0x02,0x00,0x06,0x24,0x10,0x00,0xa4,0x27,0x34,0x00,0xbf,0xaf,0x30,0x00,0xb2,0xaf,
-0x97,0x45,0x00,0x0c,0x28,0x00,0xb0,0xaf,0x08,0x00,0x30,0x96,0x02,0x80,0x02,0x3c,
-0x21,0x28,0x00,0x00,0x25,0x80,0x02,0x02,0x21,0x20,0x00,0x02,0x97,0x45,0x00,0x0c,
-0x10,0x00,0x06,0x24,0x20,0x00,0x02,0x96,0x24,0x00,0x04,0x26,0x10,0x00,0xa5,0x27,
-0x03,0xff,0x42,0x30,0xc8,0x00,0x42,0x34,0x20,0x00,0x02,0xa6,0x9f,0x45,0x00,0x0c,
-0x06,0x00,0x06,0x24,0x25,0xb0,0x03,0x3c,0x50,0x00,0x62,0x34,0x00,0x00,0x44,0x8c,
-0x54,0x00,0x65,0x34,0x58,0x00,0x66,0x34,0x18,0x00,0xa4,0xaf,0x00,0x00,0xa2,0x8c,
-0x5c,0x00,0x63,0x34,0x2a,0x00,0x04,0x26,0x1c,0x00,0xa2,0xaf,0x00,0x00,0xc7,0x8c,
-0x18,0x00,0xa5,0x27,0x06,0x00,0x06,0x24,0x20,0x00,0xa7,0xaf,0x00,0x00,0x62,0x8c,
-0x1a,0x00,0x12,0x24,0x9f,0x45,0x00,0x0c,0x24,0x00,0xa2,0xaf,0x30,0x00,0x04,0x26,
-0x20,0x00,0xa5,0x27,0x9f,0x45,0x00,0x0c,0x06,0x00,0x06,0x24,0x13,0x00,0x03,0x24,
-0x14,0x00,0x23,0xae,0x0c,0x00,0x32,0xae,0x08,0x00,0x05,0x8e,0x04,0x00,0x04,0x8e,
-0xff,0xdf,0x02,0x3c,0x14,0x00,0x06,0x8e,0xff,0xff,0x42,0x34,0x10,0x00,0x07,0x8e,
-0xff,0xe0,0x03,0x24,0x24,0x28,0xa2,0x00,0x00,0x40,0x02,0x3c,0x24,0x20,0x83,0x00,
-0x25,0x28,0xa2,0x00,0xff,0x81,0x03,0x24,0xfe,0xff,0x02,0x3c,0x24,0x30,0xc3,0x00,
-0xff,0xff,0x42,0x34,0x00,0x12,0x84,0x34,0x00,0x80,0x03,0x3c,0x24,0x20,0x82,0x00,
-0x25,0x38,0xe3,0x00,0x00,0x26,0xc6,0x34,0x80,0x00,0xa5,0x34,0x20,0x00,0x02,0x24,
-0x00,0x00,0x12,0xa6,0x10,0x00,0x07,0xae,0x02,0x00,0x02,0xa2,0x14,0x00,0x06,0xae,
-0x04,0x00,0x04,0xae,0x08,0x00,0x05,0xae,0x34,0x00,0xbf,0x8f,0x30,0x00,0xb2,0x8f,
-0x2c,0x00,0xb1,0x8f,0x28,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,
-0x93,0x45,0x00,0x08,0xff,0x00,0xa5,0x30,0x00,0x00,0x85,0xa0,0xff,0xff,0xc6,0x24,
-0x01,0x00,0x84,0x24,0xfc,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x05,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,
-0xff,0xff,0xc6,0x24,0xfd,0xff,0xc0,0x14,0x04,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,
-0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,0x01,0x00,0xa5,0x24,
-0x00,0x00,0xe2,0xa0,0xfb,0xff,0x66,0x14,0x01,0x00,0xe7,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x80,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,
-0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x8c,0xff,0xff,0x63,0x24,0x04,0x00,0xa5,0x24,
-0x00,0x00,0xe2,0xac,0xfb,0xff,0x66,0x14,0x04,0x00,0xe7,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x80,0x00,0x2b,0x10,0xa4,0x00,0x0d,0x00,0x40,0x14,0xff,0xff,0x02,0x24,
-0xff,0xff,0xc6,0x24,0x08,0x00,0xc2,0x10,0x21,0x18,0x80,0x00,0xff,0xff,0x07,0x24,
-0x00,0x00,0xa2,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0xa5,0x24,0x00,0x00,0x62,0xa0,
-0xfb,0xff,0xc7,0x14,0x01,0x00,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,
-0x21,0x28,0xa6,0x00,0x21,0x18,0x86,0x00,0xff,0xff,0xc6,0x24,0xfa,0xff,0xc2,0x10,
-0x00,0x00,0x00,0x00,0xff,0xff,0x07,0x24,0xff,0xff,0xa5,0x24,0x00,0x00,0xa2,0x90,
-0xff,0xff,0x63,0x24,0xff,0xff,0xc6,0x24,0xfb,0xff,0xc7,0x14,0x00,0x00,0x62,0xa0,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x0c,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,
-0x00,0x00,0x82,0x90,0x00,0x00,0xa3,0x90,0x01,0x00,0x84,0x24,0x23,0x10,0x43,0x00,
-0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x04,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,
-0xff,0xff,0xc6,0x24,0xf6,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x21,0x10,0xc0,0x00,0xea,0x45,0x00,0x08,0x21,0x18,0x86,0x00,0x00,0x00,0x82,0x90,
-0x00,0x00,0x00,0x00,0x04,0x00,0x45,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,
-0xfa,0xff,0x83,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,
-0x09,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,0xff,0x00,0xa5,0x30,0xff,0xff,0x06,0x24,
-0x00,0x00,0x82,0x90,0xff,0xff,0x63,0x24,0x05,0x00,0x45,0x10,0x01,0x00,0x84,0x24,
-0xfb,0xff,0x66,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0xff,0xff,0x82,0x24,0x21,0x38,0x00,0x00,0x1f,0x00,0xc0,0x10,
-0x21,0x18,0x00,0x00,0x02,0x80,0x02,0x3c,0x80,0x95,0x4b,0x24,0x00,0x00,0x87,0x90,
-0x00,0x00,0xa3,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,0x21,0x10,0xeb,0x00,
-0x16,0x00,0xe0,0x10,0x01,0x00,0xa5,0x24,0x14,0x00,0x60,0x10,0x21,0x48,0x6b,0x00,
-0x10,0x00,0xe3,0x10,0x20,0x00,0xe8,0x24,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,
-0x01,0x00,0x42,0x30,0x02,0x00,0x40,0x10,0x20,0x00,0x6a,0x24,0xff,0x00,0x07,0x31,
-0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x02,0x00,0x40,0x10,
-0xff,0x00,0xe7,0x30,0xff,0x00,0x43,0x31,0xff,0x00,0x63,0x30,0x03,0x00,0xe3,0x14,
-0x00,0x00,0x00,0x00,0xe5,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x23,0x10,0xe3,0x00,0x21,0x18,0x80,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,
-0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x60,0x00,0x21,0x38,0x80,0x00,0xff,0xff,0x03,0x24,0xff,0xff,0xc6,0x24,
-0x06,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,
-0x00,0x00,0x82,0xa0,0xf9,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0xe0,0x00,0x00,0x00,0x82,0x80,0x39,0x46,0x00,0x08,0x21,0x18,0x80,0x00,
-0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,
-0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,
-0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0x12,0x00,0xc0,0x10,0x21,0x18,0x80,0x00,0x00,0x00,0x82,0x80,0x4a,0x46,0x00,0x08,
-0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,
-0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,
-0x00,0x00,0x82,0xa0,0x05,0x00,0x40,0x10,0x01,0x00,0x84,0x24,0xff,0xff,0xc6,0x24,
-0xf9,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xa0,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x60,0x00,0x00,0x00,0x83,0x90,0x00,0x00,0xa2,0x90,0x01,0x00,0x84,0x24,
-0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14,
-0x01,0x00,0xa5,0x24,0xf7,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x0b,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,
-0x00,0x00,0xa2,0x90,0x00,0x00,0x83,0x90,0xff,0xff,0xc6,0x24,0x23,0x10,0x62,0x00,
-0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,
-0xf5,0xff,0x60,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x00,0x00,0x83,0x80,0x00,0x2e,0x05,0x00,0x21,0x10,0x80,0x00,0x7b,0x46,0x00,0x08,
-0x03,0x2e,0x05,0x00,0x07,0x00,0x60,0x10,0x01,0x00,0x42,0x24,0x00,0x00,0x43,0x80,
-0x00,0x00,0x00,0x00,0xfb,0xff,0x65,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x00,0x00,0x82,0x80,
-0x87,0x46,0x00,0x08,0x21,0x18,0x80,0x00,0x01,0x00,0x63,0x24,0x00,0x00,0x62,0x80,
-0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x23,0x10,0x64,0x00,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x21,0x80,0xa0,0x00,
-0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,0x21,0x88,0x80,0x00,0x81,0x46,0x00,0x0c,
-0x00,0x86,0x10,0x00,0x21,0x18,0x51,0x00,0x03,0x86,0x10,0x00,0x00,0x00,0x62,0x80,
-0x00,0x00,0x00,0x00,0x0a,0x00,0x50,0x10,0x21,0x10,0x60,0x00,0xff,0xff,0x63,0x24,
-0x2b,0x10,0x71,0x00,0xf9,0xff,0x40,0x10,0x21,0x10,0x00,0x00,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0x21,0x30,0x80,0x00,0x0d,0x00,0xa0,0x10,0xff,0xff,0xa3,0x24,
-0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0xff,0xff,0x05,0x24,0xff,0xff,0x63,0x24,0x05,0x00,0x65,0x10,0x01,0x00,0xc6,0x24,
-0x00,0x00,0xc2,0x80,0x00,0x00,0x00,0x00,0xfa,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x23,0x10,0xc4,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,
-0x19,0x00,0x40,0x10,0x21,0x40,0x00,0x00,0x00,0x00,0xa9,0x80,0x00,0x00,0x00,0x00,
-0x17,0x00,0x20,0x11,0x21,0x30,0xa0,0x00,0x00,0x3e,0x02,0x00,0x03,0x3e,0x07,0x00,
-0x21,0x18,0x20,0x01,0x15,0x00,0xe3,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xc6,0x24,
-0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0x00,0x1e,0x02,0x00,0x03,0x1e,0x03,0x00,
-0xf8,0xff,0x60,0x14,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x06,0x00,0x40,0x10,
-0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,
-0xeb,0xff,0x40,0x14,0x01,0x00,0x08,0x25,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x01,
-0x00,0x00,0xa2,0x90,0xcc,0x46,0x00,0x08,0x00,0x16,0x02,0x00,0x00,0x00,0xc2,0x90,
-0xcc,0x46,0x00,0x08,0x00,0x16,0x02,0x00,0x00,0x00,0x87,0x90,0x00,0x00,0x00,0x00,
-0x14,0x00,0xe0,0x10,0x21,0x10,0x80,0x00,0x00,0x00,0xa4,0x90,0x00,0x00,0x00,0x00,
-0x00,0x1e,0x04,0x00,0x03,0x1e,0x03,0x00,0x09,0x00,0x60,0x10,0x21,0x30,0xa0,0x00,
-0x00,0x3e,0x07,0x00,0x03,0x3e,0x07,0x00,0x0b,0x00,0xe3,0x10,0x01,0x00,0xc6,0x24,
-0x00,0x00,0xc3,0x80,0x00,0x00,0x00,0x00,0xfb,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
-0x01,0x00,0x42,0x24,0x00,0x00,0x47,0x90,0x00,0x00,0x00,0x00,0xf0,0xff,0xe0,0x14,
-0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,
-0x21,0x80,0x80,0x00,0x1d,0x00,0x80,0x10,0x21,0x88,0xa0,0x00,0xb8,0x46,0x00,0x0c,
-0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,
-0x21,0x20,0x00,0x02,0x22,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0xdc,0x46,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x10,0x21,0x18,0x40,0x00,0x00,0x00,0x42,0x80,
-0x00,0x00,0x00,0x00,0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
-0xa8,0x96,0x43,0xac,0x21,0x18,0x00,0x02,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0x00,0x00,0x60,0xa0,0x0d,0x47,0x00,0x08,0x01,0x00,0x63,0x24,0x02,0x80,0x02,0x3c,
-0xa8,0x96,0x50,0x8c,0x00,0x00,0x00,0x00,0xf3,0xff,0x00,0x12,0x21,0x18,0x00,0x00,
-0xb8,0x46,0x00,0x0c,0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,
-0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0xe0,0xff,0x40,0x14,0x21,0x18,0x00,0x00,
-0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x80,0x02,0x3c,
-0xa8,0x96,0x40,0xac,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0xe0,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x1c,0x00,0xbf,0xaf,
-0x10,0x00,0xb0,0xaf,0x00,0x00,0x90,0x8c,0x21,0x90,0x80,0x00,0x21,0x88,0xa0,0x00,
-0x21,0x18,0x00,0x00,0x0f,0x00,0x00,0x12,0x21,0x20,0x00,0x02,0xb8,0x46,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,
-0x21,0x20,0x00,0x02,0x07,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0xdc,0x46,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x21,0x18,0x40,0x00,0x09,0x00,0x40,0x14,0x00,0x00,0x42,0xae,
-0x21,0x18,0x00,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,0xf5,0xff,0x40,0x10,0x01,0x00,0x64,0x24,
-0x00,0x00,0x60,0xa0,0x46,0x47,0x00,0x08,0x00,0x00,0x44,0xae,0xd8,0xff,0xbd,0x27,
-0x14,0x00,0xb1,0xaf,0x21,0x88,0x80,0x00,0x21,0x20,0xa0,0x00,0x1c,0x00,0xb3,0xaf,
-0x18,0x00,0xb2,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x81,0x46,0x00,0x0c,
-0x21,0x98,0xa0,0x00,0x21,0x90,0x40,0x00,0x08,0x00,0x40,0x16,0x21,0x10,0x20,0x02,
-0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x81,0x46,0x00,0x0c,
-0x21,0x20,0x20,0x02,0x21,0x80,0x40,0x00,0x2a,0x10,0x52,0x00,0x0a,0x00,0x40,0x14,
-0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x02,0x21,0x30,0x40,0x02,
-0xd4,0x45,0x00,0x0c,0xff,0xff,0x10,0x26,0x0b,0x00,0x40,0x10,0x2a,0x18,0x12,0x02,
-0xf8,0xff,0x60,0x10,0x01,0x00,0x31,0x26,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x62,0x47,0x00,0x08,0x21,0x10,0x20,0x02,
-0x01,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27,0x08,0x1e,0x44,0x24,0x25,0xb0,0x02,0x3c,
-0x28,0x00,0xb4,0xaf,0x02,0x80,0x03,0x3c,0x25,0xb0,0x14,0x3c,0x18,0x03,0x42,0x34,
-0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,
-0x24,0x00,0xb3,0xaf,0x3c,0x00,0xbf,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
-0x18,0x00,0xb0,0xaf,0x68,0x15,0x73,0x24,0x00,0x00,0x44,0xac,0x02,0x80,0x16,0x3c,
-0x02,0x80,0x15,0x3c,0xc4,0x02,0x9e,0x36,0x64,0x03,0x97,0x36,0x01,0x80,0x04,0x3c,
-0x08,0x1e,0x82,0x24,0x18,0x03,0x83,0x36,0x00,0x00,0x62,0xac,0xa0,0x02,0x87,0x36,
-0x00,0x00,0xe4,0x8c,0xd8,0x63,0x63,0x8e,0xff,0x0f,0x02,0x3c,0xff,0xff,0x46,0x34,
-0x24,0x80,0x86,0x00,0x01,0x00,0x05,0x3c,0x01,0x00,0x63,0x24,0x2b,0x10,0xb0,0x00,
-0x07,0x00,0x40,0x10,0xd8,0x63,0x63,0xae,0xa4,0x02,0x82,0x36,0x00,0x00,0x51,0x8c,
-0x00,0xb0,0x03,0x3c,0x25,0x80,0x03,0x02,0x00,0x00,0x11,0xae,0x00,0x00,0xe0,0xac,
-0xb0,0x02,0x84,0x36,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x80,0x46,0x00,
-0x2b,0x18,0xb0,0x00,0x08,0x00,0x60,0x10,0xc0,0x02,0x82,0x36,0x00,0xb0,0x02,0x3c,
-0x25,0x80,0x02,0x02,0x00,0x00,0x11,0x8e,0xb4,0x02,0x82,0x36,0x00,0x00,0x51,0xac,
-0x00,0x00,0x80,0xac,0xc0,0x02,0x82,0x36,0x00,0x00,0x50,0x8c,0xff,0x00,0x08,0x3c,
-0xff,0xff,0x02,0x35,0x2b,0x10,0x50,0x00,0x47,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0x00,0x00,0x82,0x8e,0x00,0xff,0x06,0x3c,0xac,0x02,0x84,0x36,0x01,0x00,0x45,0x24,
-0xbc,0x02,0x83,0x36,0xff,0x00,0xc2,0x34,0x00,0xfd,0x07,0x3c,0x00,0x00,0x85,0xac,
-0x00,0x00,0x70,0xac,0x24,0x18,0x02,0x02,0x07,0x00,0xe2,0x34,0x00,0x00,0x85,0x8c,
-0x52,0x03,0x62,0x10,0x25,0xb0,0x12,0x3c,0x2b,0x10,0x43,0x00,0xa2,0x00,0x40,0x14,
-0xa4,0x00,0xe2,0x34,0x00,0xf8,0x04,0x3c,0x15,0x00,0x82,0x34,0x57,0x03,0x62,0x10,
-0x2b,0x10,0x43,0x00,0xc8,0x00,0x40,0x14,0x00,0xf9,0x05,0x3c,0x00,0xf0,0x05,0x3c,
-0x20,0x00,0xa2,0x34,0x67,0x03,0x62,0x10,0x2b,0x10,0x43,0x00,0x20,0x01,0x40,0x14,
-0x10,0x00,0x82,0x34,0x70,0x03,0x65,0x10,0x2b,0x10,0xa3,0x00,0xc8,0x01,0x40,0x14,
-0x02,0x00,0xa2,0x34,0x00,0xd0,0x02,0x3c,0x2a,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,
-0xaf,0x02,0x40,0x14,0x00,0xe0,0x02,0x3c,0x00,0xc0,0x02,0x3c,0xbb,0x03,0x62,0x10,
-0xff,0x00,0x03,0x3c,0x00,0xf0,0x02,0x3c,0x24,0x30,0x02,0x02,0x18,0x00,0xc2,0x10,
-0x02,0x1d,0x10,0x00,0x00,0x70,0x05,0x3c,0x24,0x10,0x05,0x02,0x02,0x4f,0x02,0x00,
-0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34,0x00,0x50,0x07,0x3c,0xff,0x00,0x68,0x30,
-0xff,0x00,0x04,0x32,0x96,0x01,0xc7,0x10,0x24,0x18,0x02,0x02,0x2b,0x10,0xe6,0x00,
-0x8a,0x01,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0x20,0x02,0x3c,0x1a,0x03,0xc2,0x10,
-0x2b,0x10,0x46,0x00,0x82,0x02,0x40,0x14,0x00,0x30,0x02,0x3c,0x17,0x03,0xc0,0x10,
-0x80,0x10,0x08,0x00,0x00,0x10,0x02,0x3c,0x14,0x03,0xc2,0x10,0x80,0x10,0x08,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0x00,0xe2,0x92,0x25,0xb0,0x07,0x3c,
-0xc8,0x7d,0xc2,0xa2,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0xc8,0x7d,0xc2,0x92,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x4e,0x00,0x40,0x10,
-0x02,0x80,0x03,0x3c,0x00,0x40,0x62,0x8e,0xf0,0xff,0x03,0x24,0xd7,0x42,0x60,0xa2,
-0x24,0x10,0x43,0x00,0x01,0x00,0x42,0x34,0x00,0x40,0x62,0xae,0xc8,0x7d,0xc2,0x92,
-0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0x3d,0x00,0x40,0x10,0x0f,0xff,0x03,0x24,
-0x00,0x40,0x62,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,0x10,0x00,0x42,0x34,
-0x00,0x40,0x62,0xae,0xc8,0x7d,0xc2,0x92,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x30,
-0x30,0x00,0x40,0x10,0xff,0xf0,0x03,0x24,0x00,0x40,0x62,0x8e,0x00,0x00,0x00,0x00,
-0x24,0x10,0x43,0x00,0x00,0x01,0x42,0x34,0x25,0xb0,0x05,0x3c,0x00,0x40,0x62,0xae,
-0x4c,0x00,0xa3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,
-0x05,0x00,0x40,0x14,0xff,0xff,0x02,0x3c,0x00,0x40,0x63,0x8e,0xff,0x0f,0x42,0x34,
-0x24,0x18,0x62,0x00,0x00,0x40,0x63,0xae,0x00,0x7b,0xa4,0x8e,0x01,0x80,0x06,0x3c,
-0x08,0x1f,0xc2,0x24,0x18,0x03,0xa3,0x34,0x00,0x7b,0xa6,0x26,0x00,0x00,0x62,0xac,
-0x10,0x00,0x86,0x10,0x02,0x80,0x02,0x3c,0xbf,0x00,0xb2,0x34,0x68,0x15,0x51,0x24,
-0x21,0x80,0xc0,0x00,0x00,0x00,0x42,0x92,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x2c,
-0x09,0x00,0x40,0x10,0x02,0x80,0x07,0x3c,0x98,0x65,0x24,0x8e,0x8b,0x07,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x00,0x7b,0xa2,0x8e,0x00,0x00,0x00,0x00,0xf5,0xff,0x50,0x14,
-0x00,0x00,0x00,0x00,0x02,0x80,0x07,0x3c,0x08,0x08,0xe4,0x24,0x21,0x28,0x00,0x00,
-0x21,0x30,0x00,0x00,0x31,0x1c,0x00,0x0c,0x21,0x38,0x00,0x00,0x9a,0x47,0x00,0x08,
-0x01,0x80,0x04,0x3c,0x00,0x40,0x62,0x8e,0x30,0x48,0x00,0x08,0x24,0x10,0x43,0x00,
-0x00,0x40,0x62,0x8e,0x04,0x43,0x64,0x92,0x24,0x10,0x43,0x00,0x00,0x40,0x62,0xae,
-0x27,0x48,0x00,0x08,0x04,0x43,0x64,0xae,0x68,0x15,0x66,0x24,0x00,0x40,0xc2,0x8c,
-0xd7,0x42,0xc4,0x90,0xf0,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0xb3,0xff,0x80,0x14,
-0x00,0x40,0xc2,0xac,0x1c,0x00,0x04,0x24,0x58,0x0c,0xe5,0x34,0x50,0x0c,0xe3,0x34,
-0x01,0x00,0x02,0x24,0xd7,0x42,0xc2,0xa0,0x00,0x00,0x64,0xa0,0x00,0x00,0xa4,0xa0,
-0x1d,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xb2,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,
-0x3f,0x00,0x40,0x14,0xaf,0x00,0xe2,0x34,0x20,0x00,0xe2,0x34,0xc0,0x02,0x62,0x10,
-0x2b,0x10,0x43,0x00,0xe3,0x00,0x40,0x14,0x29,0x00,0xe2,0x34,0x15,0x00,0xe2,0x34,
-0x0c,0x03,0x62,0x10,0x2b,0x10,0x43,0x00,0x9d,0x01,0x40,0x14,0x17,0x00,0xe2,0x34,
-0x09,0x00,0xe2,0x34,0xd8,0x03,0x62,0x10,0x2b,0x10,0x62,0x00,0x81,0x02,0x40,0x14,
-0x14,0x00,0xe2,0x34,0x64,0xff,0x62,0x14,0x00,0xf0,0x02,0x3c,0xff,0x00,0x07,0x3c,
-0x00,0xff,0xe7,0x34,0x24,0x10,0x07,0x02,0x7a,0xff,0x40,0x10,0xc0,0x02,0x82,0x36,
-0x04,0x43,0x64,0x92,0xff,0x00,0x02,0x3c,0x24,0x10,0x02,0x02,0x00,0xff,0x03,0x32,
-0x02,0x14,0x02,0x00,0x02,0x1a,0x03,0x00,0xfb,0xff,0x45,0x24,0x1c,0x43,0x62,0xa2,
-0x00,0x01,0x84,0x34,0xfb,0xff,0x66,0x24,0xc0,0x02,0x82,0x36,0x04,0x43,0x64,0xae,
-0x1d,0x43,0x65,0xa2,0x1f,0x43,0x66,0xa2,0x1e,0x43,0x63,0xa2,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x05,0x00,0xa2,0x34,0x91,0x02,0x62,0x10,
-0x2b,0x10,0x43,0x00,0x8e,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xde,0x02,0x65,0x10,
-0x2b,0x10,0xa3,0x00,0x32,0x01,0x40,0x14,0x02,0x00,0xa2,0x34,0x17,0x00,0x82,0x34,
-0x61,0x04,0x62,0x10,0x2b,0x10,0x62,0x00,0xa9,0x03,0x40,0x14,0x18,0x00,0x82,0x34,
-0x3d,0xff,0x62,0x14,0x00,0xf0,0x02,0x3c,0x74,0x0b,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xa8,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,0x95,0x00,0x40,0x14,0x0c,0x00,0xc2,0x34,
-0xaa,0x00,0xe2,0x34,0xdc,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,0xd9,0x00,0x40,0x14,
-0xac,0x00,0xe2,0x34,0xa6,0x00,0xe2,0x34,0x1c,0x04,0x62,0x10,0x2b,0x10,0x62,0x00,
-0x69,0x03,0x40,0x14,0xa7,0x00,0xe2,0x34,0x27,0xff,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0x00,0xff,0x02,0x32,0xff,0x00,0x04,0x3c,0x02,0x8a,0x02,0x00,0x24,0x18,0x04,0x02,
-0x01,0x00,0x02,0x24,0xa6,0x04,0x22,0x12,0x02,0x1c,0x03,0x00,0x02,0x00,0x02,0x24,
-0xc9,0x04,0x22,0x12,0x03,0x00,0x02,0x24,0xdf,0x04,0x22,0x12,0x04,0x00,0x02,0x24,
-0xd1,0x04,0x22,0x12,0x08,0x00,0x02,0x24,0x2e,0x05,0x22,0x12,0x09,0x00,0x02,0x24,
-0x1e,0x05,0x22,0x12,0x0a,0x00,0x02,0x24,0x0e,0x05,0x22,0x12,0x0b,0x00,0x02,0x24,
-0xfe,0x04,0x22,0x12,0x0c,0x00,0x02,0x24,0x5e,0x05,0x22,0x12,0x0d,0x00,0x02,0x24,
-0x4e,0x05,0x22,0x12,0x0e,0x00,0x02,0x24,0x3e,0x05,0x22,0x12,0x0f,0x00,0x02,0x24,
-0x2e,0x05,0x22,0x12,0x10,0x00,0x02,0x24,0x22,0xff,0x22,0x16,0xc0,0x02,0x82,0x36,
-0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x53,0x00,0x4c,0x51,0x43,0x94,0x48,0x51,0x44,0x94,
-0x25,0xb0,0x06,0x3c,0x00,0x1c,0x03,0x00,0x21,0x20,0x83,0x00,0x00,0x00,0xc4,0xaf,
-0x58,0x51,0x45,0x8c,0x54,0x51,0x43,0x8c,0x50,0x51,0x44,0x94,0xc8,0x02,0xc6,0x34,
-0x21,0x18,0x65,0x00,0x00,0x1c,0x03,0x00,0x21,0x20,0x83,0x00,0xc0,0x02,0x82,0x36,
-0x00,0x00,0xc4,0xac,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x66,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,0xbf,0x00,0x40,0x14,0x12,0x00,0x82,0x34,
-0x00,0xf1,0x04,0x3c,0x01,0x00,0x82,0x34,0xc1,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,
-0xb7,0x01,0x40,0x14,0x02,0x00,0x82,0x34,0xe3,0xfe,0x64,0x14,0x00,0xf0,0x02,0x3c,
-0xff,0x00,0x04,0x3c,0x00,0xff,0x84,0x34,0x24,0x10,0x04,0x02,0x02,0x8a,0x02,0x00,
-0x80,0x1a,0x11,0x00,0x00,0xf4,0x63,0x24,0x94,0x00,0x82,0x36,0x00,0x00,0x51,0xa4,
-0x26,0xb0,0x04,0x3c,0x42,0x89,0x03,0x00,0x98,0x00,0x86,0x36,0xff,0x01,0x02,0x24,
-0x10,0x00,0x03,0x24,0x9a,0x00,0x85,0x36,0x00,0x00,0xa2,0xa4,0x7c,0x00,0x89,0x34,
-0x00,0x00,0xc3,0xa4,0x01,0x00,0x02,0x24,0x04,0x00,0x03,0x24,0x96,0x00,0x87,0x36,
-0x7a,0x00,0x84,0x34,0xb0,0x03,0x88,0x36,0x25,0xb0,0x06,0x3c,0x00,0x00,0xe2,0xa4,
-0x44,0x00,0xc6,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0x11,0xad,0x00,0x00,0x31,0xa5,
-0x00,0x00,0xc3,0x94,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,0x00,0x00,0xc3,0xa4,
-0x00,0x00,0xc2,0x94,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x34,0x00,0x00,0xc2,0xa4,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x65,0x01,0x67,0x10,0x2b,0x10,0xe3,0x00,0xc5,0x00,0x40,0x14,0x02,0x00,0xe2,0x34,
-0x07,0x00,0xa2,0x34,0xfc,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,0xa9,0x01,0x40,0x14,
-0x20,0x00,0xa2,0x34,0xb0,0xfe,0x62,0x14,0x00,0xf0,0x02,0x3c,0xff,0x00,0x03,0x3c,
-0x00,0xff,0x63,0x34,0x24,0x10,0x03,0x02,0x02,0x3a,0x02,0x00,0x80,0x04,0xe0,0x10,
-0x02,0x80,0x04,0x3c,0x05,0x00,0x02,0x24,0xc2,0xfe,0xe2,0x14,0xc0,0x02,0x82,0x36,
-0x02,0x80,0x06,0x3c,0x8f,0x7d,0xc2,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x2e,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,0x98,0x00,0x40,0x14,0x0e,0x00,0xc2,0x34,
-0x01,0x00,0xc2,0x34,0xab,0x03,0x62,0x10,0x2b,0x10,0x43,0x00,0x48,0x01,0x40,0x14,
-0x00,0xff,0x02,0x3c,0x94,0xfe,0x66,0x14,0x00,0xf0,0x02,0x3c,0x5b,0x4e,0x00,0x0c,
-0x21,0x20,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x4c,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,0xa6,0x00,0x40,0x14,
-0xa1,0x00,0xe2,0x34,0x22,0x00,0xe2,0x34,0xbd,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,
-0x88,0x01,0x40,0x14,0x00,0x20,0x02,0x3c,0x28,0x00,0xe2,0x34,0x82,0xfe,0x62,0x14,
-0x00,0xf0,0x02,0x3c,0x0f,0x00,0x04,0x3c,0xff,0xff,0x85,0x34,0x60,0x00,0x06,0x24,
-0xba,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0x84,0x0a,0x00,0x0c,0xe8,0x03,0x04,0x24,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x0f,0x00,0x06,0x3c,0x24,0x00,0x04,0x24,0xdd,0x44,0x00,0x0c,0xff,0xff,0xc5,0x34,
-0x1f,0x00,0x51,0x30,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,0x00,0x00,0xd1,0xa3,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x18,0x02,0xc2,0x10,
-0x2b,0x10,0x46,0x00,0x01,0x01,0x40,0x14,0x00,0xa0,0x02,0x3c,0x00,0x60,0x02,0x3c,
-0x04,0x00,0xc2,0x10,0x80,0x10,0x08,0x00,0x7a,0xfe,0xc5,0x14,0xc0,0x02,0x82,0x36,
-0x80,0x10,0x08,0x00,0x21,0x10,0x48,0x00,0x21,0x10,0x53,0x00,0x21,0x10,0x49,0x00,
-0xc1,0x43,0x44,0xa0,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x3f,0x03,0x62,0x10,0x2b,0x10,0x62,0x00,0xb6,0x02,0x40,0x14,
-0xad,0x00,0xe2,0x34,0xc7,0x03,0x62,0x10,0xae,0x00,0xe2,0x34,0x4e,0xfe,0x62,0x14,
-0x00,0xf0,0x02,0x3c,0xff,0x00,0x02,0x3c,0x24,0x20,0x02,0x02,0x00,0xff,0x05,0x32,
-0x02,0x24,0x04,0x00,0x69,0x4f,0x00,0x0c,0x02,0x2a,0x05,0x00,0x00,0x00,0xc2,0xa3,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x4b,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,0x17,0x01,0x40,0x14,0x03,0x00,0xa2,0x34,
-0x82,0x03,0x62,0x10,0x08,0x00,0xa2,0x34,0x3b,0xfe,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0x00,0xff,0x02,0x32,0x02,0x82,0x02,0x00,0xcc,0x02,0x83,0x36,0x00,0x00,0x70,0xac,
-0x12,0x04,0x00,0x12,0x01,0x00,0x02,0x24,0x9c,0x04,0x02,0x12,0x00,0x00,0x00,0x00,
-0x7a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x4e,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,
-0xe4,0x00,0x40,0x14,0x00,0xff,0x02,0x32,0x13,0x00,0x82,0x34,0x4c,0x03,0x62,0x10,
-0x14,0x00,0x82,0x34,0x24,0xfe,0x62,0x14,0x00,0xf0,0x02,0x3c,0xd3,0x0a,0x00,0x0c,
-0xfd,0x00,0x04,0x24,0x10,0x10,0x03,0x3c,0xa0,0x00,0x82,0x36,0x10,0x10,0x63,0x34,
-0x00,0xc0,0x07,0x3c,0x25,0xb0,0x06,0x3c,0x00,0x00,0x43,0xac,0xa4,0x00,0x84,0x36,
-0x00,0xa1,0xe7,0x34,0xa8,0x00,0xc6,0x34,0xc0,0x02,0x82,0x36,0x00,0x00,0x80,0xac,
-0x00,0x00,0xc7,0xac,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x60,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,0xf6,0x00,0x40,0x14,0x03,0x00,0xa2,0x34,
-0x4b,0x03,0x62,0x10,0x04,0x00,0xa2,0x34,0x0b,0xfe,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0xf4,0x63,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x61,0x02,0x62,0x10,
-0x2b,0x10,0x62,0x00,0xfe,0x00,0x40,0x14,0x01,0x00,0x02,0x24,0x0f,0x00,0xc2,0x34,
-0x63,0x03,0x62,0x10,0x10,0x00,0xc2,0x34,0xfb,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0x00,0xff,0x03,0x32,0x00,0xff,0x02,0x34,0x9d,0x03,0x62,0x10,0xc0,0x02,0x82,0x36,
-0x8c,0x65,0x60,0xae,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x47,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,0x02,0x01,0x40,0x14,0x03,0x00,0xe2,0x34,
-0x8d,0x03,0x62,0x10,0x04,0x00,0xe2,0x34,0xeb,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0x1e,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x9b,0x01,0x62,0x10,0x2b,0x10,0x43,0x00,
-0xcf,0x00,0x40,0x14,0xa2,0x00,0xe2,0x34,0xa0,0x00,0xe2,0x34,0xde,0xfd,0x62,0x14,
-0x00,0xf0,0x02,0x3c,0x00,0x0f,0x02,0x32,0x02,0x22,0x02,0x00,0x01,0x00,0x03,0x24,
-0x3c,0x04,0x83,0x10,0x02,0x00,0x02,0x24,0x34,0x04,0x82,0x10,0x03,0x00,0x02,0x24,
-0x46,0x03,0x82,0x10,0x00,0x00,0x00,0x00,0xde,0x4f,0x00,0x0c,0x21,0x20,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x46,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,0xe6,0xfd,0x40,0x14,0xc0,0x02,0x82,0x36,
-0x18,0x00,0xe2,0x34,0x45,0x03,0x62,0x10,0x19,0x00,0xe2,0x34,0xc6,0xfd,0x62,0x14,
-0x00,0xf0,0x02,0x3c,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x94,0x0e,0x83,0x36,
-0x9c,0x0e,0x82,0x36,0xa4,0x0e,0x84,0x36,0xac,0x0e,0x87,0x36,0x00,0x00,0x65,0x8c,
-0x00,0x00,0x48,0x8c,0x00,0x00,0x8a,0x8c,0x00,0x00,0xe6,0x8c,0x02,0x80,0x07,0x3c,
-0x68,0x15,0xed,0x24,0xb4,0x0e,0x82,0x36,0x00,0x00,0x47,0x8c,0x0c,0x40,0xa3,0x8d,
-0xff,0x03,0x02,0x3c,0x10,0x40,0xa4,0x8d,0x24,0x28,0xa2,0x00,0x24,0x30,0xc2,0x00,
-0xbc,0x0e,0x82,0x36,0x00,0x00,0x4b,0x8c,0x00,0xfc,0x02,0x24,0x02,0x2c,0x05,0x00,
-0x24,0x18,0x62,0x00,0x02,0x34,0x06,0x00,0x24,0x20,0x82,0x00,0xc4,0x0e,0x82,0x36,
-0x25,0x18,0x65,0x00,0x25,0x20,0x86,0x00,0x00,0x00,0x45,0x8c,0xff,0x03,0x06,0x3c,
-0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x24,0x38,0xe6,0x00,0x82,0x39,0x07,0x00,
-0x24,0x20,0x82,0x00,0x24,0x40,0x06,0x01,0x08,0x40,0xa9,0x8d,0x25,0x20,0x87,0x00,
-0xcc,0x0e,0x8c,0x36,0xff,0x03,0x07,0x3c,0x00,0x00,0x86,0x8d,0x24,0x18,0x62,0x00,
-0x24,0x50,0x47,0x01,0x24,0x58,0x67,0x01,0x82,0x41,0x08,0x00,0xff,0x9f,0x02,0x3c,
-0x0f,0xc0,0x07,0x3c,0xff,0xff,0xe7,0x34,0xff,0xff,0x42,0x34,0x25,0x18,0x68,0x00,
-0x24,0x48,0x22,0x01,0x24,0x18,0x67,0x00,0xff,0x03,0x02,0x3c,0x24,0x20,0x87,0x00,
-0xff,0x00,0x07,0x3c,0x24,0x28,0xa2,0x00,0x24,0x30,0xc2,0x00,0x00,0x51,0x0a,0x00,
-0x00,0x20,0x02,0x3c,0x00,0x59,0x0b,0x00,0x00,0xff,0xe7,0x34,0x25,0x48,0x22,0x01,
-0x25,0x18,0x6a,0x00,0x25,0x20,0x8b,0x00,0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,
-0x24,0x10,0x07,0x02,0x08,0x40,0xa9,0xad,0x0c,0x40,0xa3,0xad,0x10,0x40,0xa4,0xad,
-0x14,0x40,0xa5,0xa5,0x4e,0x03,0x40,0x10,0x16,0x40,0xa6,0xa5,0xff,0x00,0x02,0x3c,
-0x24,0x10,0x02,0x02,0x02,0x14,0x02,0x00,0x02,0x1a,0x10,0x00,0xc7,0x42,0xa2,0xa1,
-0xc3,0x42,0xa3,0xa1,0xc3,0x42,0x62,0x92,0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34,
-0x10,0x00,0xa4,0x27,0x00,0x00,0x62,0xa0,0x7a,0x54,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x95,0x00,0xc2,0x10,0x00,0x40,0x02,0x3c,0x09,0xff,0xc2,0x10,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x7b,0x02,0xc2,0x10,
-0x2b,0x10,0x46,0x00,0x83,0x00,0x40,0x14,0x00,0xb0,0x02,0x3c,0x00,0x90,0x02,0x3c,
-0x78,0xfd,0xc2,0x14,0xc0,0x02,0x82,0x36,0x21,0x10,0x13,0x01,0x73,0x44,0x44,0xa0,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x55,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,0x6a,0x56,0x00,0x0c,0x21,0x20,0x00,0x02,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x07,0x00,0x42,0x34,0x4c,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,0x5b,0x4e,0x00,0x0c,
-0x07,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x02,0x1a,0x02,0x00,0x21,0x88,0x00,0x00,0xaf,0x4a,0x00,0x08,
-0x27,0xb0,0x06,0x3c,0x01,0x00,0x31,0x26,0x00,0x01,0x22,0x2e,0x08,0x00,0x40,0x10,
-0xff,0x00,0x22,0x2e,0x00,0x00,0xc2,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,
-0xf8,0xff,0x43,0x14,0x08,0x00,0xc6,0x24,0x00,0x00,0xd1,0xa7,0xff,0x00,0x22,0x2e,
-0x50,0xfd,0x40,0x14,0xc0,0x02,0x82,0x36,0x12,0x87,0x02,0x3c,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x2d,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x03,0x3c,0x00,0xff,0x63,0x34,
-0x24,0x10,0x03,0x02,0x02,0x82,0x02,0x00,0xcc,0x02,0x83,0x36,0x00,0x00,0x70,0xac,
-0x00,0x00,0xd1,0x8f,0x21,0x10,0x14,0x02,0x00,0x00,0x51,0xac,0x00,0x00,0x51,0x8c,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xd1,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0x64,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xf4,0x02,0x62,0x10,0xa3,0x00,0xe2,0x34,0x0f,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0xc0,0x02,0x82,0x36,0x8c,0x65,0x60,0xae,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xec,0x63,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xe6,0x63,0x62,0xa6,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x08,0x40,0x63,0x8e,0xff,0x9f,0x07,0x3c,0xff,0xff,0xe7,0x34,
-0x02,0x2c,0x10,0x00,0x00,0x1f,0x04,0x32,0x24,0x18,0x67,0x00,0x25,0x18,0x62,0x00,
-0x02,0x8a,0x04,0x00,0x3f,0x00,0xa5,0x30,0xc0,0x02,0x82,0x36,0x08,0x40,0x63,0xae,
-0xbc,0x42,0x71,0xa2,0xc1,0x42,0x65,0xa2,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0x92,0x00,0x00,0x00,0x00,0xfa,0x00,0x42,0x30,
-0x00,0x00,0xe2,0xa2,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0x92,0x00,0x00,0x00,0x00,0xfd,0x00,0x42,0x30,
-0x00,0x00,0xe2,0xa2,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xf7,0xfc,0xc2,0x14,0xc0,0x02,0x82,0x36,0x80,0x10,0x08,0x00,
-0x21,0x10,0x53,0x00,0x60,0x45,0x43,0xac,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x80,0x10,0x08,0x00,0x21,0x10,0x48,0x00,
-0x21,0x10,0x53,0x00,0x21,0x10,0x49,0x00,0x34,0x43,0x44,0xa0,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x77,0x56,0x00,0x0c,
-0x21,0x20,0x00,0x02,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x8c,0x65,0x62,0xae,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x07,0x0b,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xf0,0x63,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x08,0x40,0x62,0x8e,0xff,0x9f,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,
-0x08,0x40,0x62,0xae,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x22,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x07,0x3c,0x00,0xff,0xe7,0x34,
-0x24,0x10,0x07,0x02,0x02,0x82,0x02,0x00,0xcc,0x02,0x43,0x36,0x00,0x00,0x70,0xac,
-0x21,0x10,0x12,0x02,0x00,0x00,0x51,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0xaf,
-0x00,0x00,0x51,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xb7,0x4f,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x21,0x88,0x00,0x00,
-0x6c,0x4b,0x00,0x08,0x27,0xb0,0x04,0x3c,0x01,0x00,0x31,0x26,0x00,0x01,0x22,0x2e,
-0x0a,0x00,0x40,0x10,0xff,0x00,0x22,0x2e,0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,
-0xff,0xff,0x67,0x30,0xff,0x00,0xe2,0x30,0xf0,0x00,0x42,0x28,0xf6,0xff,0x40,0x14,
-0x08,0x00,0x84,0x24,0x00,0x00,0xc7,0xa7,0xff,0x00,0x22,0x2e,0x91,0xfc,0x40,0x14,
-0xc0,0x02,0x82,0x36,0x12,0x87,0x02,0x3c,0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xe4,0x63,0x62,0x96,
-0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa7,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x04,0x64,0x62,0x92,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0xff,0x02,0x32,0x02,0x12,0x02,0x00,0x03,0x00,0x43,0x2c,
-0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x02,0x40,0x62,0xa2,0x02,0x40,0x63,0x92,
-0x90,0x0c,0x42,0x36,0x00,0x00,0x43,0xa0,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xd7,0x56,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x21,0x10,0x13,0x01,0x56,0x44,0x44,0xa0,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x03,0x3c,0x24,0x20,0x03,0x02,
-0x73,0x0e,0x00,0x0c,0x02,0x24,0x04,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x1c,0x10,0x00,0x00,0x1f,0x02,0x32,
-0x02,0x8a,0x02,0x00,0x3f,0x00,0x65,0x30,0xc1,0x42,0x65,0xa2,0xbc,0x42,0x71,0xa2,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x1f,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x03,0x40,0x62,0x92,0x0e,0x0c,0x44,0x36,
-0x01,0x00,0x42,0x24,0xff,0x00,0x43,0x30,0x00,0x00,0x83,0xa0,0x03,0x40,0x62,0xa2,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x00,0xff,0x02,0x32,0x02,0x3a,0x02,0x00,0x1a,0x01,0xe0,0x10,0x4f,0x00,0x82,0x36,
-0x94,0x00,0x42,0x36,0x00,0x00,0x43,0x94,0xff,0xff,0xe2,0x24,0xb0,0x03,0x45,0x36,
-0xff,0xff,0x71,0x30,0x1b,0x00,0x27,0x02,0x02,0x00,0xe0,0x14,0x00,0x00,0x00,0x00,
-0x0d,0x00,0x07,0x00,0xff,0xff,0x47,0x30,0x00,0x00,0xb1,0xac,0x80,0xff,0x02,0x24,
-0x00,0x19,0x07,0x00,0x25,0x18,0x62,0x00,0x4f,0x00,0x44,0x36,0x9e,0x00,0x46,0x36,
-0x00,0x00,0xa7,0xac,0x00,0x00,0x83,0xa0,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,
-0x12,0x88,0x00,0x00,0x80,0x12,0x11,0x00,0x00,0xfc,0x42,0x24,0x00,0x00,0xb1,0xac,
-0x00,0x00,0xd1,0xa4,0x42,0x89,0x02,0x00,0x26,0xb0,0x02,0x3c,0x7c,0x00,0x42,0x34,
-0x00,0x00,0xb1,0xac,0x00,0x00,0x51,0xa4,0x25,0xb0,0x02,0x3c,0x44,0x00,0x42,0x34,
-0x00,0x00,0x43,0x94,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4,
-0x00,0x00,0x82,0x94,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x24,0x10,0x08,0x02,0xcc,0x02,0x43,0x36,0x00,0xff,0x04,0x32,0x02,0x3c,0x02,0x00,
-0x00,0x00,0x70,0xac,0x04,0x00,0xe0,0x10,0x02,0x82,0x04,0x00,0x01,0x00,0x02,0x24,
-0x02,0x00,0xe2,0x10,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x7a,0x42,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x0f,0x00,0x06,0x3c,0x21,0x20,0x00,0x02,0xdd,0x44,0x00,0x0c,
-0xff,0xff,0xc5,0x34,0x0f,0x00,0x07,0x3c,0xff,0xff,0xe7,0x34,0x24,0x88,0x47,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xd1,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x28,0xb0,0x02,0x3c,0x00,0x00,0x43,0x90,0xff,0x00,0x02,0x24,
-0xff,0x00,0x70,0x30,0xf3,0xfb,0x02,0x12,0xc0,0x02,0x82,0x36,0x28,0xb0,0x05,0x3c,
-0xff,0x00,0x04,0x24,0xc0,0x10,0x10,0x00,0x21,0x10,0x45,0x00,0x00,0x00,0x43,0x90,
-0x00,0x00,0x00,0x00,0xff,0x00,0x70,0x30,0xfb,0xff,0x04,0x16,0xc0,0x10,0x10,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x00,0x1f,0x02,0x32,0x02,0x1c,0x10,0x00,0x02,0x8a,0x02,0x00,0x3f,0x00,0x65,0x30,
-0xc0,0x02,0x82,0x36,0xbc,0x42,0x71,0xa2,0xc1,0x42,0x65,0xa2,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x07,0x3c,0x24,0x20,0x07,0x02,
-0x15,0x51,0x00,0x0c,0x02,0x24,0x04,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xe8,0x63,0x62,0x92,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xfc,0x63,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x00,0x00,0xe2,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x51,0x30,0x05,0x00,0x23,0x36,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xe3,0xa2,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,0xe6,0x63,0x60,0xa6,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xbd,0x56,0x00,0x0c,0x21,0x20,0x00,0x02,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x41,0x0b,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0x92,0x00,0x00,0x00,0x00,
-0xff,0x00,0x51,0x30,0x02,0x00,0x23,0x36,0xc0,0x02,0x82,0x36,0x00,0x00,0xe3,0xa2,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
-0xec,0x91,0x42,0x24,0x00,0x00,0x47,0x8c,0xc0,0x02,0x43,0x36,0x25,0xb0,0x0c,0x3c,
-0x08,0x40,0xe4,0x8c,0x00,0x00,0x60,0xac,0x42,0x17,0x04,0x00,0x03,0x00,0x42,0x30,
-0x60,0x00,0x40,0x14,0x03,0x0d,0x42,0x36,0x00,0x00,0x45,0x90,0x10,0x40,0xe6,0x8c,
-0xff,0x9f,0x03,0x3c,0xff,0xff,0x63,0x34,0xff,0x3f,0x02,0x3c,0x24,0x20,0x83,0x00,
-0xff,0xff,0x42,0x34,0x00,0x20,0x03,0x3c,0x24,0x58,0xc2,0x00,0x25,0x20,0x83,0x00,
-0x00,0x40,0x02,0x3c,0x70,0x00,0xa5,0x30,0x25,0x58,0x62,0x01,0x08,0x01,0xa0,0x10,
-0x08,0x40,0xe4,0xac,0x94,0x0e,0x82,0x35,0x9c,0x0e,0x83,0x35,0xa4,0x0e,0x86,0x35,
-0x00,0x00,0x45,0x8c,0xac,0x0e,0x87,0x35,0x00,0x00,0x68,0x8c,0x00,0x00,0xca,0x8c,
-0x02,0x80,0x06,0x3c,0x00,0x00,0xe4,0x8c,0x68,0x15,0xc6,0x24,0x0c,0x40,0xc3,0x8c,
-0xb4,0x0e,0x82,0x35,0x00,0x00,0x47,0x8c,0xff,0x03,0x02,0x3c,0x00,0xfc,0x06,0x24,
-0x24,0x28,0xa2,0x00,0x24,0x20,0x82,0x00,0xbc,0x0e,0x82,0x35,0x00,0x00,0x49,0x8c,
-0x02,0x2c,0x05,0x00,0x24,0x10,0x66,0x01,0x24,0x18,0x66,0x00,0x02,0x24,0x04,0x00,
-0xc4,0x0e,0x86,0x35,0x25,0x18,0x65,0x00,0x25,0x10,0x44,0x00,0x00,0x00,0xc5,0x8c,
-0xff,0x03,0x04,0x3c,0xf0,0xff,0x06,0x3c,0xff,0x03,0xc6,0x34,0x24,0x38,0xe4,0x00,
-0xcc,0x0e,0x8b,0x35,0x24,0x40,0x04,0x01,0x82,0x39,0x07,0x00,0x00,0x00,0x64,0x8d,
-0x24,0x10,0x46,0x00,0x24,0x18,0x66,0x00,0x25,0x10,0x47,0x00,0x82,0x41,0x08,0x00,
-0xff,0x03,0x07,0x3c,0x0f,0xc0,0x06,0x3c,0x24,0x50,0x47,0x01,0x24,0x48,0x27,0x01,
-0xff,0xff,0xc6,0x34,0x25,0x18,0x68,0x00,0x24,0x28,0xa7,0x00,0x24,0x20,0x87,0x00,
-0x00,0x51,0x0a,0x00,0x24,0x18,0x66,0x00,0x00,0x49,0x09,0x00,0x24,0x10,0x46,0x00,
-0x02,0x80,0x07,0x3c,0x68,0x15,0xe7,0x24,0x25,0x18,0x6a,0x00,0x25,0x10,0x49,0x00,
-0x02,0x2c,0x05,0x00,0x02,0x24,0x04,0x00,0x0c,0x40,0xe3,0xac,0x10,0x40,0xe2,0xac,
-0x14,0x40,0xe5,0xa4,0x16,0x40,0xe4,0xa4,0x02,0x80,0x02,0x3c,0x68,0x15,0x43,0x24,
-0x0c,0x40,0x62,0x8c,0x00,0x00,0x00,0x00,0xbd,0x00,0x40,0x04,0x00,0x00,0x00,0x00,
-0x00,0xff,0x02,0x32,0xc6,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,
-0xc3,0x42,0x62,0xa0,0x7a,0x54,0x00,0x0c,0x10,0x00,0xa4,0x27,0xc2,0x53,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x0c,0x40,0x62,0x8e,0x00,0x80,0x03,0x3c,0x25,0x10,0x43,0x00,
-0x0c,0x40,0x62,0xae,0xc3,0x42,0x62,0x92,0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34,
-0x00,0x00,0x62,0xa0,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xcf,0x4e,0x00,0x0c,0x21,0x20,0x00,0x02,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x17,0x51,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x9e,0x00,0x83,0x36,0x00,0x00,0x40,0xa0,0x00,0x00,0x60,0xa4,
-0x94,0x00,0x82,0x36,0x00,0x00,0x43,0x94,0x25,0xb0,0x06,0x3c,0x44,0x00,0xc6,0x34,
-0xff,0xff,0x71,0x30,0x80,0x12,0x11,0x00,0x00,0xf8,0x42,0x24,0x42,0x89,0x02,0x00,
-0x26,0xb0,0x02,0x3c,0xb0,0x03,0x83,0x36,0x7c,0x00,0x42,0x34,0x00,0x00,0x71,0xac,
-0x00,0x00,0x51,0xa4,0x00,0x00,0xc3,0x94,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,
-0x00,0x00,0xc3,0xa4,0x00,0x00,0xc2,0x94,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x34,
-0x00,0x00,0xc2,0xa4,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x5b,0x4e,0x00,0x0c,0x01,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x80,0x10,0x08,0x00,
-0x21,0x10,0x53,0x00,0xec,0x44,0x43,0xac,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xa7,0x0b,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x28,0xb0,0x11,0x3c,0x00,0x00,0x22,0x96,0xff,0x00,0x04,0x3c,0x24,0x18,0x04,0x02,
-0x02,0x24,0x03,0x00,0xff,0x00,0x42,0x30,0x0a,0x00,0x82,0x10,0xff,0x7f,0x02,0x3c,
-0x08,0x00,0x31,0x26,0x00,0x00,0x22,0x96,0xff,0xff,0x23,0x32,0xff,0x00,0x42,0x30,
-0x03,0x00,0x82,0x10,0x00,0x08,0x63,0x2c,0xf9,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
-0xff,0x7f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x22,0x02,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xf8,0x63,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x03,0x3c,
-0x24,0x10,0x03,0x02,0x00,0xff,0x04,0x32,0xcc,0x02,0x83,0x36,0x02,0x3c,0x02,0x00,
-0x00,0x00,0x70,0xac,0x04,0x00,0xe0,0x10,0x02,0x82,0x04,0x00,0x01,0x00,0x02,0x24,
-0x02,0x00,0xe2,0x10,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x7a,0x42,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x8f,0x0f,0x00,0x06,0x3c,0xff,0xff,0xc5,0x34,
-0x21,0x20,0x00,0x02,0xba,0x44,0x00,0x0c,0x21,0x30,0x20,0x02,0x0f,0x00,0x07,0x3c,
-0x21,0x20,0x00,0x02,0xdd,0x44,0x00,0x0c,0xff,0xff,0xe5,0x34,0x00,0x00,0xc2,0xaf,
-0x21,0x88,0x40,0x00,0x25,0xb0,0x02,0x3c,0xc8,0x02,0x42,0x34,0x00,0x00,0x51,0xac,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x25,0xb0,0x06,0x3c,0xff,0x00,0x02,0x24,0x56,0x01,0xc6,0x34,0x00,0x00,0xc2,0xa4,
-0x01,0x00,0x03,0x24,0x02,0x80,0x07,0x3c,0xc0,0x02,0x82,0x36,0xb8,0x7d,0xe3,0xa0,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xde,0x4f,0x00,0x0c,
-0x03,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xde,0x4e,0x00,0x0c,0x21,0x20,0x00,0x02,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x40,0x62,0x8e,
-0xff,0x9f,0x04,0x3c,0xff,0xff,0x84,0x34,0x24,0x10,0x44,0x00,0x08,0x40,0x62,0xae,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x53,0x00,0x70,0x51,0x43,0x8c,0xc0,0x02,0x82,0x36,
-0x00,0x00,0xc3,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x7a,0x54,0x00,0x0c,0x10,0x00,0xa4,0x27,0xc3,0x42,0x62,0x92,0x25,0xb0,0x03,0x3c,
-0x61,0x0c,0x63,0x34,0x00,0x00,0x62,0xa0,0xd4,0x4c,0x00,0x08,0xc0,0x02,0x82,0x36,
-0x22,0x51,0x00,0x0c,0x10,0x40,0xeb,0xac,0xbd,0x4c,0x00,0x08,0x02,0x80,0x02,0x3c,
-0xc6,0x4c,0x00,0x08,0x12,0x00,0x02,0x24,0x1a,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xff,0xff,0x02,0x34,0x8c,0x65,0x62,0xae,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x53,0x00,
-0x74,0x51,0x43,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc3,0xaf,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x53,0x00,
-0xd4,0x51,0x43,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc3,0xaf,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x02,0x80,0x06,0x3c,0x80,0x10,0x02,0x00,
-0xe0,0x66,0xc3,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0xc0,0x02,0x82,0x36,
-0x00,0x00,0xc4,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x12,0x00,0x02,0x24,0xc7,0x42,0xa2,0xa1,0x77,0x4a,0x00,0x08,0xc3,0x42,0xa2,0xa1,
-0x88,0x7d,0x82,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x7a,0x42,0x00,0x0c,
-0x21,0x20,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xff,0x00,0x06,0x3c,0x00,0xff,0xc6,0x34,0x00,0x00,0xc5,0x8f,
-0x24,0x20,0x06,0x02,0xe1,0x50,0x00,0x0c,0x02,0x22,0x04,0x00,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,
-0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x02,0x80,0x07,0x3c,
-0x80,0x10,0x02,0x00,0xf0,0x66,0xe3,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x02,0x80,0x06,0x3c,0x80,0x10,0x02,0x00,0xec,0x66,0xc3,0x24,
-0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,
-0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x02,0x80,0x04,0x3c,
-0xe8,0x66,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x02,0x80,0x07,0x3c,0x80,0x10,0x02,0x00,0xe4,0x66,0xe3,0x24,
-0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,
-0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x02,0x80,0x04,0x3c,
-0x00,0x67,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x02,0x80,0x07,0x3c,0x80,0x10,0x02,0x00,0xfc,0x66,0xe3,0x24,
-0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,
-0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x02,0x80,0x06,0x3c,
-0x80,0x10,0x02,0x00,0xf8,0x66,0xc3,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x02,0x80,0x04,0x3c,0xf4,0x66,0x83,0x24,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xde,0x4f,0x00,0x0c,
-0x02,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xde,0x4f,0x00,0x0c,0x01,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x7a,0x42,0x00,0x0c,
-0x01,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x05,0x3c,0x01,0x00,0x06,0x24,0x01,0x80,0x02,0x3c,
-0x04,0x30,0x86,0x00,0xf1,0x02,0xa7,0x34,0xed,0x02,0xa4,0x34,0x6c,0x39,0x42,0x24,
-0x18,0x03,0xa5,0x34,0x08,0x00,0x03,0x24,0x00,0x00,0xa2,0xac,0x00,0x00,0xe3,0xa0,
-0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,
-0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,
-0x00,0x00,0x80,0xa0,0x00,0x00,0xe0,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xc8,0x39,0x42,0x24,0x18,0x03,0x63,0x34,
-0x00,0x00,0x62,0xac,0x00,0x00,0x83,0x90,0x30,0x00,0x02,0x24,0x05,0x00,0x62,0x10,
-0x21,0x20,0x00,0x00,0x31,0x00,0x02,0x24,0x02,0x00,0x62,0x10,0x01,0x00,0x04,0x24,
-0x07,0x00,0x04,0x24,0x5b,0x4e,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,
-0x25,0xb0,0x03,0x3c,0x04,0x3a,0x42,0x24,0x18,0x03,0x63,0x34,0x02,0x80,0x04,0x3c,
-0x00,0x00,0x62,0xac,0x08,0x00,0xe0,0x03,0xc4,0x7d,0x80,0xac,0x02,0x80,0x02,0x3c,
-0x08,0x7b,0x42,0x24,0xc0,0x20,0x04,0x00,0x21,0x20,0x82,0x00,0x21,0x28,0x00,0x00,
-0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x09,0x00,0x44,0x10,0x00,0x00,0x00,0x00,
-0x04,0x00,0x43,0x8c,0x21,0x28,0x40,0x00,0x00,0x00,0x42,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,0x00,0x00,0xa5,0xac,0x04,0x00,0xa5,0xac,
-0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0x21,0x18,0x80,0x00,
-0xe8,0xff,0xbd,0x27,0x01,0x01,0x62,0x2c,0x10,0x00,0xbf,0xaf,0x01,0x00,0x04,0x24,
-0x01,0x02,0x65,0x2c,0x0a,0x00,0x40,0x14,0x21,0x30,0x00,0x00,0x02,0x00,0x04,0x24,
-0x07,0x00,0xa0,0x14,0x01,0x08,0x62,0x2c,0x05,0x00,0x40,0x14,0x03,0x00,0x04,0x24,
-0x10,0x00,0xbf,0x8f,0x21,0x10,0xc0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
-0x89,0x4e,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0x21,0x30,0x40,0x00,
-0x21,0x10,0xc0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,
-0x20,0x7b,0x62,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x06,0x40,
-0x01,0x00,0xc1,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x10,0x00,0x83,0x8c,
-0x02,0x80,0x02,0x3c,0x08,0x7b,0x42,0x24,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00,
-0x00,0x00,0x65,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x04,0x00,0xa4,0xac,
-0x00,0x00,0x64,0xac,0x04,0x00,0x83,0xac,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x18,0x04,0x00,
-0x21,0x18,0x64,0x00,0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x42,0x24,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x78,0x51,0x64,0x8c,
-0xff,0xf1,0x02,0x24,0x24,0x20,0x82,0x00,0x08,0x00,0xe0,0x03,0x78,0x51,0x64,0xac,
-0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x18,0x04,0x00,0x21,0x18,0x64,0x00,
-0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,
-0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x78,0x51,0x64,0x8c,0xff,0xf1,0x02,0x24,
-0x24,0x20,0x82,0x00,0x00,0x02,0x84,0x34,0x08,0x00,0xe0,0x03,0x78,0x51,0x64,0xac,
-0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,
-0x80,0x80,0x10,0x00,0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,
-0x80,0x80,0x10,0x00,0x21,0x80,0x02,0x02,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,
-0x14,0x00,0xb1,0xaf,0x78,0x51,0x05,0x8e,0xff,0x1f,0x02,0x3c,0x25,0xb0,0x12,0x3c,
-0xff,0xff,0x42,0x34,0x70,0x51,0x02,0xae,0x84,0x01,0x43,0x36,0xf8,0xff,0x02,0x24,
-0x00,0x00,0x66,0x8c,0x24,0x28,0xa2,0x00,0xff,0xfe,0x02,0x24,0x24,0x28,0xa2,0x00,
-0xff,0xef,0x03,0x24,0x24,0x28,0xa3,0x00,0x74,0x51,0x06,0xae,0x78,0x51,0x05,0xae,
-0xce,0x0d,0x00,0x0c,0x21,0x88,0x80,0x00,0x7a,0x51,0x02,0x92,0x21,0x88,0x32,0x02,
-0x1c,0x00,0xbf,0x8f,0x60,0x01,0x22,0xa2,0x18,0x00,0xb2,0x8f,0x64,0x51,0x00,0xae,
-0x48,0x51,0x00,0xae,0x4c,0x51,0x00,0xae,0x50,0x51,0x00,0xae,0x54,0x51,0x00,0xae,
-0x58,0x51,0x00,0xae,0x5c,0x51,0x00,0xae,0x60,0x51,0x00,0xae,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xff,0x00,0xa5,0x30,
-0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,
-0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
-0x78,0x51,0x43,0x8c,0x25,0xb0,0x05,0x3c,0xff,0x00,0xc6,0x30,0x21,0x30,0xc5,0x00,
-0xaf,0x01,0xc2,0x90,0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x65,0x00,
-0xff,0x00,0x88,0x30,0xff,0x00,0x49,0x30,0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,
-0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,
-0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,0x3e,0x4f,0x00,0x08,0x01,0x00,0x07,0x24,
-0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,
-0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,
-0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,
-0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,
-0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,
-0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,
-0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,
-0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,
-0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,
-0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,
-0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,0x5f,0x4f,0x00,0x08,0xff,0x00,0x44,0x30,
-0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xff,0x00,0x84,0x30,
-0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,
-0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
-0x25,0xb0,0x06,0x3c,0x78,0x51,0x43,0x8c,0xff,0x00,0xa5,0x30,0x21,0x20,0x86,0x00,
-0x21,0x28,0xa6,0x00,0x60,0x01,0x82,0x90,0xaf,0x01,0xa4,0x90,0x07,0x00,0x63,0x30,
-0x80,0x18,0x03,0x00,0x21,0x18,0x66,0x00,0xff,0x00,0x48,0x30,0xff,0x00,0x89,0x30,
-0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,
-0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,
-0x8c,0x4f,0x00,0x08,0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,
-0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,
-0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,
-0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,
-0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,
-0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,
-0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,
-0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,
-0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,
-0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,
-0xad,0x4f,0x00,0x08,0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x80,0x00,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x10,0x00,0xb0,0xaf,
-0x68,0x15,0x50,0x24,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x1c,0x00,0xbf,0xaf,
-0x21,0x88,0x00,0x00,0x21,0x90,0x00,0x02,0xee,0x4e,0x00,0x0c,0x21,0x20,0x20,0x02,
-0x7a,0x51,0x02,0x92,0x21,0x28,0x00,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x52,0x00,
-0xec,0x44,0x44,0x8c,0x60,0x45,0x43,0x8c,0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00,
-0x42,0x18,0x03,0x00,0x44,0x51,0x03,0xae,0x21,0x10,0x05,0x02,0x01,0x00,0xa5,0x24,
-0x1d,0x00,0xa3,0x28,0xb6,0x51,0x40,0xa0,0x7c,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,
-0x99,0x51,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xd4,0x51,0x00,0xae,
-0xe9,0xff,0x40,0x14,0x94,0x00,0x10,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x30,0x00,0xbe,0xaf,0x28,0x00,0xb6,0xaf,
-0x68,0x15,0x46,0x24,0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb7,0xaf,0x24,0x00,0xb5,0xaf,
-0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,
-0x10,0x00,0xb0,0xaf,0x8c,0x65,0xc2,0x8c,0xff,0x00,0x8d,0x30,0xff,0x00,0x03,0x24,
-0xff,0xff,0x42,0x38,0x21,0xf0,0x00,0x00,0xff,0xff,0x04,0x34,0x0a,0xf0,0x62,0x00,
-0x8c,0x65,0xc4,0xac,0xb0,0x00,0xa0,0x11,0x08,0x00,0x16,0x24,0x02,0x80,0x02,0x3c,
-0xb8,0x90,0x45,0x24,0x90,0x44,0xc4,0x24,0xff,0x4f,0x00,0x08,0x21,0x88,0x00,0x00,
-0x01,0x00,0x31,0x26,0x00,0x00,0x82,0xa0,0x1d,0x00,0x22,0x2a,0x0b,0x00,0x40,0x10,
-0x01,0x00,0x84,0x24,0x21,0x10,0x25,0x02,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,
-0xf7,0xff,0x40,0x10,0xfd,0xff,0x43,0x24,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,
-0x00,0x00,0x83,0xa0,0xf7,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x50,0x8e,0x6c,0x24,
-0xd8,0x8d,0x4b,0x24,0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,
-0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,
-0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,
-0xc5,0x43,0x64,0xa0,0xf8,0xff,0x40,0x14,0x34,0x43,0x65,0xa0,0x21,0x10,0x2b,0x02,
-0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,
-0x1d,0x00,0x22,0x2a,0x73,0x44,0x64,0xa0,0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,
-0x05,0x00,0x29,0x25,0xa6,0x00,0xa0,0x11,0x02,0x80,0x02,0x3c,0x68,0x15,0x48,0x24,
-0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x4c,0x91,0x69,0x24,0xd8,0x90,0x47,0x24,
-0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x10,0x69,0x00,0x21,0x20,0x67,0x00,
-0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,0x21,0x18,0x68,0x00,
-0x04,0x00,0x22,0x2a,0xec,0x44,0x65,0xac,0xf6,0xff,0x40,0x14,0x60,0x45,0x66,0xac,
-0x02,0x80,0x02,0x3c,0x68,0x15,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
-0x4c,0x91,0x68,0x24,0xd8,0x90,0x47,0x24,0x04,0x00,0x11,0x24,0x80,0x20,0x11,0x00,
-0x21,0x10,0x88,0x00,0x21,0x30,0x87,0x00,0x00,0x00,0x45,0x8c,0x00,0x00,0xc3,0x8c,
-0x01,0x00,0x31,0x26,0x21,0x20,0x89,0x00,0x82,0x28,0x05,0x00,0x82,0x18,0x03,0x00,
-0x1d,0x00,0x22,0x2a,0xec,0x44,0x83,0xac,0xf4,0xff,0x40,0x14,0x60,0x45,0x85,0xac,
-0x02,0x80,0x02,0x3c,0x68,0x15,0x55,0x24,0x21,0x88,0x00,0x00,0x21,0xb8,0xa0,0x02,
-0x21,0xa0,0x00,0x00,0x5a,0x50,0x00,0x08,0x21,0x90,0xa0,0x02,0x01,0x00,0x31,0x26,
-0x20,0x00,0x22,0x2a,0x94,0x00,0x52,0x26,0x38,0x00,0x40,0x10,0x94,0x00,0x94,0x26,
-0x78,0x51,0x44,0x8e,0x01,0x00,0x03,0x24,0x02,0x13,0x04,0x00,0x01,0x00,0x53,0x30,
-0xf6,0xff,0x63,0x16,0x07,0x00,0x82,0x30,0x25,0xb0,0x03,0x3c,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x84,0x01,0x45,0x8c,0x70,0x51,0x43,0x8e,0x21,0x20,0x20,0x02,
-0x24,0x28,0xa3,0x00,0xce,0x0d,0x00,0x0c,0x74,0x51,0x45,0xae,0x7a,0x51,0x44,0x92,
-0x5c,0x0d,0x00,0x0c,0xff,0x00,0x25,0x32,0x7a,0x51,0x50,0x92,0x00,0x00,0x00,0x00,
-0x21,0x20,0x00,0x02,0x63,0x0d,0x00,0x0c,0x80,0x80,0x10,0x00,0x21,0x80,0x17,0x02,
-0x48,0x51,0x40,0xae,0x4c,0x51,0x40,0xae,0x50,0x51,0x40,0xae,0x54,0x51,0x40,0xae,
-0x58,0x51,0x40,0xae,0x5c,0x51,0x40,0xae,0x60,0x51,0x40,0xae,0x64,0x51,0x40,0xae,
-0xec,0x44,0x04,0x8e,0x60,0x45,0x03,0x8e,0x26,0x10,0x53,0x00,0x21,0x30,0x00,0x00,
-0x21,0x18,0x64,0x00,0x42,0x18,0x03,0x00,0x04,0x00,0x04,0x24,0x0a,0xb0,0x82,0x00,
-0x44,0x51,0x43,0xae,0x21,0x20,0x95,0x02,0x21,0x10,0x86,0x00,0x01,0x00,0xc6,0x24,
-0x1d,0x00,0xc3,0x28,0xb6,0x51,0x40,0xa0,0x7c,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,
-0x99,0x51,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xd4,0x51,0x80,0xac,
-0x94,0x00,0x52,0x26,0xca,0xff,0x40,0x14,0x94,0x00,0x94,0x26,0x25,0xb0,0x02,0x3c,
-0x80,0x01,0x42,0x34,0x00,0x00,0x56,0xa0,0x03,0x00,0xc0,0x17,0x02,0x80,0x03,0x3c,
-0x68,0x15,0x62,0x24,0x8c,0x65,0x40,0xac,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,
-0x2c,0x00,0xb7,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,
-0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0xb8,0x90,0x45,0x24,
-0x90,0x44,0xc4,0x24,0x21,0x88,0x00,0x00,0x21,0x10,0x25,0x02,0x00,0x00,0x43,0x90,
-0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0,0xfa,0xff,0x40,0x14,
-0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x68,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,
-0x02,0x80,0x02,0x3c,0x74,0x8f,0x6c,0x24,0x14,0x8e,0x4b,0x24,0x21,0x88,0x00,0x00,
-0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01,
-0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,
-0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc5,0x43,0x64,0xa0,0xf8,0xff,0x40,0x14,
-0x34,0x43,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,
-0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x73,0x44,0x64,0xa0,
-0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x4c,0x91,0x68,0x24,
-0xd8,0x90,0x47,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x10,0x68,0x00,
-0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,
-0x21,0x18,0x69,0x00,0x1d,0x00,0x22,0x2a,0xec,0x44,0x65,0xac,0xf6,0xff,0x40,0x14,
-0x60,0x45,0x66,0xac,0x4f,0x50,0x00,0x08,0x02,0x80,0x02,0x3c,0xd8,0xff,0xbd,0x27,
-0xff,0xff,0x84,0x30,0x18,0x00,0xb2,0xaf,0xf0,0x01,0x92,0x30,0x02,0x91,0x12,0x00,
-0x14,0x00,0xb1,0xaf,0xc0,0x88,0x12,0x00,0x21,0x88,0x32,0x02,0x80,0x88,0x11,0x00,
-0x21,0x88,0x32,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x80,0x88,0x11,0x00,
-0x21,0x88,0x22,0x02,0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x10,0x00,0xb0,0xaf,
-0x78,0x51,0x30,0x8e,0x00,0x02,0x82,0x30,0xff,0xfe,0x03,0x24,0x2b,0x10,0x02,0x00,
-0x00,0x10,0x10,0x36,0x24,0x80,0x03,0x02,0x00,0x12,0x02,0x00,0x25,0x80,0x02,0x02,
-0x70,0x51,0x25,0xae,0x78,0x51,0x30,0xae,0xa0,0x0e,0x00,0x0c,0x21,0x98,0xa0,0x00,
-0xf8,0xff,0x03,0x24,0x24,0x80,0x03,0x02,0x07,0x00,0x42,0x30,0x25,0x80,0x02,0x02,
-0x07,0x00,0x03,0x32,0x25,0xb0,0x02,0x3c,0x80,0x18,0x03,0x00,0x78,0x51,0x30,0xae,
-0x21,0x18,0x62,0x00,0x84,0x01,0x62,0x8c,0x21,0x20,0x40,0x02,0x24,0x10,0x53,0x00,
-0xce,0x0d,0x00,0x0c,0x74,0x51,0x22,0xae,0x7a,0x51,0x24,0x92,0x21,0x28,0x40,0x02,
-0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x5c,0x0d,0x00,0x08,0x28,0x00,0xbd,0x27,0xee,0x4e,0x00,0x08,
-0xff,0x00,0x84,0x30,0x02,0x80,0x02,0x3c,0x68,0x15,0x43,0x24,0x1f,0x00,0x04,0x24,
-0x78,0x51,0x62,0x8c,0xff,0xff,0x84,0x24,0x00,0x10,0x42,0x34,0x78,0x51,0x62,0xac,
-0xfb,0xff,0x81,0x04,0x94,0x00,0x63,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x78,0xff,0xbd,0x27,0x60,0x00,0xb0,0xaf,0x25,0xb0,0x10,0x3c,0x70,0x00,0xb4,0xaf,
-0xc4,0x02,0x14,0x36,0x00,0x00,0x80,0xae,0x74,0x00,0xb5,0xaf,0x6c,0x00,0xb3,0xaf,
-0x68,0x00,0xb2,0xaf,0x64,0x00,0xb1,0xaf,0x84,0x00,0xbf,0xaf,0x80,0x00,0xbe,0xaf,
-0x7c,0x00,0xb7,0xaf,0x78,0x00,0xb6,0xaf,0x04,0x00,0x02,0x36,0x04,0x0c,0x13,0x36,
-0x00,0x00,0x43,0x8c,0x00,0x00,0x62,0x8e,0x0f,0x00,0x11,0x3c,0x24,0x18,0x71,0x00,
-0x08,0x0c,0x12,0x36,0x4c,0x00,0xa2,0xaf,0x02,0xac,0x03,0x00,0x00,0x00,0x43,0x8e,
-0x00,0x00,0x00,0x00,0x50,0x00,0xa3,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0xdd,0x44,0x00,0x0c,
-0xff,0xff,0x25,0x36,0x10,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x7a,0x42,0x00,0x0c,
-0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0xdd,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,
-0x14,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x7a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,
-0xe0,0x0e,0x05,0x36,0x00,0x00,0xad,0x8c,0xdc,0x0e,0x06,0x36,0x70,0x0e,0x07,0x36,
-0x18,0x00,0xad,0xaf,0x00,0x00,0xc2,0x8c,0x74,0x0e,0x08,0x36,0x78,0x0e,0x09,0x36,
-0x1c,0x00,0xa2,0xaf,0x00,0x00,0xe3,0x8c,0x7c,0x0e,0x0a,0x36,0x80,0x0e,0x0b,0x36,
-0x20,0x00,0xa3,0xaf,0x00,0x00,0x0d,0x8d,0x84,0x0e,0x0c,0x36,0x88,0x0e,0x17,0x36,
-0x24,0x00,0xad,0xaf,0x00,0x00,0x22,0x8d,0x8c,0x0e,0x0e,0x36,0xd0,0x0e,0x18,0x36,
-0x28,0x00,0xa2,0xaf,0x00,0x00,0x43,0x8d,0xd8,0x0e,0x11,0x36,0xd4,0x0e,0x10,0x36,
-0x2c,0x00,0xa3,0xaf,0x00,0x00,0x6d,0x8d,0xed,0x3f,0x04,0x3c,0xfb,0x92,0x84,0x34,
-0x30,0x00,0xad,0xaf,0x00,0x00,0x82,0x8d,0x25,0xb0,0x1e,0x3c,0x21,0xb0,0x00,0x00,
-0x34,0x00,0xa2,0xaf,0x00,0x00,0xe3,0x8e,0xff,0x03,0x0f,0x3c,0x38,0x00,0xa3,0xaf,
-0x00,0x00,0xcd,0x8d,0x00,0x00,0x00,0x00,0x3c,0x00,0xad,0xaf,0x00,0x00,0x02,0x8f,
-0x00,0x00,0x00,0x00,0x40,0x00,0xa2,0xaf,0x00,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,
-0x44,0x00,0xa3,0xaf,0x00,0x00,0x2d,0x8e,0x00,0x00,0x00,0x00,0x48,0x00,0xad,0xaf,
-0x00,0x00,0xa4,0xac,0x00,0x00,0xc4,0xac,0x00,0x00,0xe4,0xac,0x00,0x00,0x04,0xad,
-0x00,0x00,0x24,0xad,0x00,0x00,0x44,0xad,0x00,0x00,0x64,0xad,0x00,0x00,0x84,0xad,
-0x00,0x00,0xe4,0xae,0x00,0x00,0xc4,0xad,0x00,0x00,0x04,0xaf,0x00,0x00,0x04,0xae,
-0x00,0x00,0x24,0xae,0xd0,0x51,0x00,0x08,0x00,0x00,0x00,0x00,0x7a,0x00,0xa2,0x12,
-0x00,0x10,0x03,0x3c,0xac,0x0e,0xc2,0x37,0x94,0x0e,0xc3,0x37,0x25,0xb0,0x09,0x3c,
-0x00,0x00,0x4a,0x8c,0xbc,0x0e,0x29,0x35,0x00,0x00,0x64,0x8c,0xb4,0x0e,0xc2,0x37,
-0x9c,0x0e,0xc3,0x37,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,0x00,0x00,0x27,0x8d,
-0x24,0x20,0x8f,0x00,0x00,0xd8,0x02,0x3c,0x24,0x10,0x42,0x01,0x24,0x28,0xaf,0x00,
-0x24,0x30,0xcf,0x00,0x24,0x38,0xef,0x00,0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,
-0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0xf2,0x00,0x83,0x10,
-0x02,0x3c,0x07,0x00,0xf0,0x00,0xa3,0x10,0x20,0x00,0x03,0x24,0xee,0x00,0xc3,0x10,
-0x00,0x00,0x00,0x00,0xec,0x00,0xe3,0x10,0x01,0x00,0x08,0x24,0x80,0x00,0x03,0x24,
-0x08,0x00,0x83,0x10,0x21,0x20,0x00,0x00,0x06,0x00,0xa3,0x10,0x21,0x20,0x00,0x00,
-0xe0,0x03,0x03,0x24,0x03,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0xe5,0x00,0xe3,0x10,
-0x01,0x00,0x04,0x24,0x06,0x00,0x40,0x10,0x09,0x00,0x02,0x24,0x04,0x00,0x00,0x11,
-0x00,0x00,0x00,0x00,0x6d,0x01,0x80,0x14,0x25,0xb0,0x12,0x3c,0x09,0x00,0x02,0x24,
-0xde,0x00,0xc2,0x12,0x25,0xb0,0x04,0x3c,0x01,0x00,0xd6,0x26,0x0a,0x00,0xc2,0x2e,
-0x1d,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xc8,0xff,0xa0,0x16,0x01,0x00,0x02,0x24,
-0xa0,0x00,0x03,0x3c,0x25,0xb0,0x09,0x3c,0x30,0x54,0x62,0x34,0x04,0x0c,0x29,0x35,
-0x00,0x00,0x22,0xad,0x25,0xb0,0x0d,0x3c,0x08,0x00,0x02,0x3c,0xe4,0x00,0x42,0x34,
-0x08,0x0c,0xad,0x35,0x25,0xb0,0x09,0x3c,0x00,0x00,0xa2,0xad,0x28,0x0e,0x29,0x35,
-0x80,0x80,0x02,0x3c,0x00,0x00,0x22,0xad,0x14,0x02,0x04,0x3c,0x16,0x68,0x02,0x3c,
-0x48,0x01,0x83,0x34,0x40,0x0e,0xc5,0x37,0x44,0x0e,0xc6,0x37,0xa2,0x04,0x42,0x34,
-0x25,0xb0,0x0d,0x3c,0x00,0x00,0xa3,0xac,0x4c,0x0e,0xad,0x35,0x00,0x00,0xc2,0xac,
-0xd1,0x28,0x02,0x24,0x00,0x00,0xa2,0xad,0x14,0x02,0x03,0x3c,0x16,0x28,0x02,0x3c,
-0x4d,0x01,0x63,0x34,0x60,0x0e,0xc7,0x37,0x64,0x0e,0xc8,0x37,0xba,0x08,0x42,0x34,
-0x00,0x00,0xe3,0xac,0x25,0xb0,0x06,0x3c,0x00,0x00,0x02,0xad,0x00,0xfb,0x0d,0x3c,
-0x25,0xb0,0x09,0x3c,0x00,0xf8,0x02,0x3c,0xd1,0x28,0x07,0x24,0x6c,0x0e,0xc6,0x34,
-0x48,0x0e,0x29,0x35,0x01,0x00,0x42,0x34,0x01,0x00,0xad,0x35,0x00,0x00,0xc7,0xac,
-0x03,0x00,0x04,0x24,0x00,0x00,0x2d,0xad,0x00,0x00,0x22,0xad,0x84,0x0a,0x00,0x0c,
-0x58,0x00,0xaf,0xaf,0xa0,0x00,0x04,0x3c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x06,0x3c,
-0x25,0xb0,0x07,0x3c,0xe4,0x00,0x02,0x24,0x33,0x54,0x84,0x34,0x04,0x0c,0x63,0x34,
-0x08,0x0c,0xc6,0x34,0x28,0x0e,0xe7,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0xc2,0xac,
-0x00,0x00,0xe0,0xac,0x01,0x00,0x02,0x24,0x58,0x00,0xaf,0x8f,0x8a,0xff,0xa2,0x16,
-0xac,0x0e,0xc2,0x37,0x00,0x10,0x03,0x3c,0x1f,0xdc,0x79,0x34,0x1f,0x8c,0x7f,0x34,
-0x23,0x8c,0x6d,0x34,0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34,0x00,0x01,0x17,0x3c,
-0x25,0xb0,0x09,0x3c,0x25,0xb0,0x03,0x3c,0x00,0x01,0xe2,0x36,0x20,0x08,0x29,0x35,
-0x20,0x08,0x63,0x34,0x00,0x00,0x30,0x8d,0x00,0x00,0x62,0xac,0x25,0xb0,0x03,0x3c,
-0x28,0x08,0x63,0x34,0x00,0x00,0x62,0xac,0x25,0xb0,0x02,0x3c,0x04,0x0c,0x42,0x34,
-0x00,0x00,0x45,0xac,0x25,0xb0,0x03,0x3c,0x08,0x00,0x02,0x3c,0xe4,0x00,0x42,0x34,
-0x08,0x0c,0x63,0x34,0x00,0x00,0x62,0xac,0x25,0xb0,0x03,0x3c,0x00,0x7c,0xf3,0x36,
-0x00,0x48,0xf4,0x36,0x30,0x0e,0xc6,0x37,0x34,0x0e,0xc7,0x37,0x80,0x80,0x02,0x3c,
-0x28,0x0e,0x63,0x34,0x00,0x00,0x62,0xac,0x00,0x00,0xd3,0xac,0x00,0x00,0xf4,0xac,
-0x14,0x02,0x06,0x3c,0x16,0x68,0x07,0x3c,0x38,0x0e,0xc8,0x37,0x40,0x0e,0xca,0x37,
-0x44,0x0e,0xcb,0x37,0x3c,0x0e,0xc9,0x37,0x02,0x01,0xc6,0x34,0xc7,0x04,0xe7,0x34,
-0x00,0x00,0x19,0xad,0x25,0xb0,0x03,0x3c,0x00,0x00,0x3f,0xad,0x00,0x00,0x46,0xad,
-0x25,0xb0,0x09,0x3c,0x00,0x00,0x67,0xad,0x25,0xb0,0x06,0x3c,0x00,0x10,0x07,0x3c,
-0x50,0x0e,0xcc,0x37,0x58,0x0e,0xce,0x37,0x5c,0x0e,0xd8,0x37,0xd1,0x28,0x02,0x24,
-0x23,0xdc,0xe7,0x34,0x4c,0x0e,0x29,0x35,0x6c,0x0e,0x63,0x34,0x54,0x0e,0xc6,0x34,
-0x00,0x00,0x22,0xad,0x00,0x00,0x62,0xac,0x14,0x02,0x09,0x3c,0x00,0x00,0x93,0xad,
-0x25,0xb0,0x02,0x3c,0x00,0x00,0xd4,0xac,0x00,0x00,0xc7,0xad,0x00,0x00,0x0d,0xaf,
-0x16,0x28,0x0d,0x3c,0x48,0x0e,0x42,0x34,0x00,0xf8,0x06,0x3c,0x02,0x01,0x29,0x35,
-0x07,0x0d,0xad,0x35,0x00,0xfb,0x03,0x3c,0x60,0x0e,0xd1,0x37,0x64,0x0e,0xd2,0x37,
-0x00,0x00,0x29,0xae,0x03,0x00,0x04,0x24,0x00,0x00,0x4d,0xae,0x00,0x00,0x43,0xac,
-0x00,0x00,0x46,0xac,0x84,0x0a,0x00,0x0c,0x58,0x00,0xaf,0xaf,0x00,0x02,0x02,0x3c,
-0x25,0xb0,0x07,0x3c,0x25,0xb0,0x09,0x3c,0xd1,0x28,0x42,0x34,0x4c,0x0e,0xe7,0x34,
-0x6c,0x0e,0x29,0x35,0x25,0xb0,0x0d,0x3c,0x00,0x00,0xe2,0xac,0x48,0x0e,0xad,0x35,
-0x00,0x00,0x22,0xad,0x00,0xf8,0x03,0x3c,0x00,0xfb,0x02,0x3c,0x00,0x00,0xa2,0xad,
-0x03,0x00,0x04,0x24,0x00,0x00,0xa3,0xad,0x84,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x4c,0x00,0xa6,0x8f,0x25,0xb0,0x04,0x3c,0x04,0x0c,0x84,0x34,0x00,0x00,0x86,0xac,
-0x50,0x00,0xa9,0x8f,0x25,0xb0,0x07,0x3c,0x25,0xb0,0x0d,0x3c,0x00,0x01,0x10,0x32,
-0x08,0x0c,0xe7,0x34,0x28,0x0e,0xad,0x35,0x00,0x00,0xe9,0xac,0x2b,0x80,0x10,0x00,
-0x00,0x00,0xa0,0xad,0x58,0x00,0xaf,0x8f,0x17,0xff,0x00,0x16,0xac,0x0e,0xc2,0x37,
-0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x20,0x08,0x42,0x34,0x28,0x08,0x63,0x34,
-0x00,0x00,0x57,0xac,0x25,0xb0,0x09,0x3c,0x00,0x00,0x77,0xac,0xac,0x0e,0xc2,0x37,
-0x94,0x0e,0xc3,0x37,0x00,0x00,0x4a,0x8c,0xbc,0x0e,0x29,0x35,0x00,0x00,0x64,0x8c,
-0xb4,0x0e,0xc2,0x37,0x9c,0x0e,0xc3,0x37,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,
-0x00,0x00,0x27,0x8d,0x24,0x20,0x8f,0x00,0x00,0xd8,0x02,0x3c,0x24,0x10,0x42,0x01,
-0x24,0x28,0xaf,0x00,0x24,0x30,0xcf,0x00,0x24,0x38,0xef,0x00,0x02,0x24,0x04,0x00,
-0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,
-0x10,0xff,0x83,0x14,0x02,0x3c,0x07,0x00,0x80,0x00,0x03,0x24,0x16,0xff,0x83,0x14,
-0x21,0x40,0x00,0x00,0xc3,0x51,0x00,0x08,0x21,0x20,0x00,0x00,0xff,0xff,0x02,0x34,
-0xc4,0x02,0x84,0x34,0x00,0x00,0x82,0xac,0x94,0x0e,0xc3,0x37,0x9c,0x0e,0xc2,0x37,
-0xa4,0x0e,0xc4,0x37,0xac,0x0e,0xc7,0x37,0x00,0x00,0x66,0x8c,0x00,0x00,0x49,0x8c,
-0x00,0x00,0x8b,0x8c,0x00,0x00,0xe5,0x8c,0x02,0x80,0x07,0x3c,0x68,0x15,0xe7,0x24,
-0x0c,0x40,0xe3,0x8c,0x10,0x40,0xe4,0x8c,0xb4,0x0e,0xc2,0x37,0x00,0x00,0x47,0x8c,
-0x25,0xb0,0x0d,0x3c,0x00,0xfc,0x02,0x24,0x24,0x30,0xcf,0x00,0x24,0x28,0xaf,0x00,
-0xbc,0x0e,0xad,0x35,0x00,0x00,0xa8,0x8d,0x24,0x20,0x82,0x00,0x02,0x34,0x06,0x00,
-0x24,0x18,0x62,0x00,0x02,0x2c,0x05,0x00,0xc4,0x0e,0xca,0x37,0xcc,0x0e,0xcc,0x37,
-0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x18,0x66,0x00,0x25,0x20,0x85,0x00,
-0x00,0x00,0x46,0x8d,0x24,0x48,0x2f,0x01,0x00,0x00,0x85,0x8d,0x24,0x38,0xef,0x00,
-0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00,0x82,0x49,0x09,0x00,0x82,0x39,0x07,0x00,
-0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x18,0x69,0x00,0x25,0x20,0x87,0x00,
-0x24,0x58,0x6f,0x01,0x24,0x40,0x0f,0x01,0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00,
-0x00,0x59,0x0b,0x00,0x00,0x41,0x08,0x00,0x24,0x30,0xcf,0x00,0x24,0x28,0xaf,0x00,
-0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x25,0x18,0x6b,0x00,0x25,0x20,0x88,0x00,
-0x02,0x34,0x06,0x00,0x02,0x2c,0x05,0x00,0x01,0x00,0xd6,0x26,0x0c,0x40,0x43,0xac,
-0x10,0x40,0x44,0xac,0x14,0x40,0x46,0xa4,0x16,0x40,0x45,0xa4,0x0a,0x00,0xc2,0x2e,
-0xe5,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0x18,0x00,0xad,0x8f,0x25,0xb0,0x02,0x3c,
-0xe0,0x0e,0x43,0x34,0x10,0x00,0xa6,0x8f,0x00,0x00,0x6d,0xac,0x1c,0x00,0xa3,0x8f,
-0xdc,0x0e,0x47,0x34,0x70,0x0e,0x48,0x34,0x00,0x00,0xe3,0xac,0x20,0x00,0xa7,0x8f,
-0x74,0x0e,0x49,0x34,0x78,0x0e,0x4a,0x34,0x00,0x00,0x07,0xad,0x24,0x00,0xad,0x8f,
-0x7c,0x0e,0x4b,0x34,0x80,0x0e,0x4c,0x34,0x00,0x00,0x2d,0xad,0x28,0x00,0xa3,0x8f,
-0x25,0xb0,0x0d,0x3c,0x84,0x0e,0xad,0x35,0x00,0x00,0x43,0xad,0x2c,0x00,0xa7,0x8f,
-0x88,0x0e,0x52,0x34,0x8c,0x0e,0x4e,0x34,0x00,0x00,0x67,0xad,0x30,0x00,0xa9,0x8f,
-0xd4,0x0e,0x51,0x34,0xd0,0x0e,0x42,0x34,0x00,0x00,0x89,0xad,0x34,0x00,0xa3,0x8f,
-0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0x00,0x00,0xa3,0xad,0x38,0x00,0xa7,0x8f,
-0x21,0x20,0x00,0x00,0x00,0x00,0x47,0xae,0x3c,0x00,0xa9,0x8f,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc9,0xad,0x40,0x00,0xad,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0xac,
-0x44,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xae,0x48,0x00,0xa3,0x8f,
-0x00,0x00,0x00,0x00,0x00,0x00,0x43,0xae,0xba,0x44,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x7a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,
-0x14,0x00,0xa6,0x8f,0xff,0xff,0x05,0x36,0xba,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x84,0x00,0xbf,0x8f,0x80,0x00,0xbe,0x8f,
-0x7c,0x00,0xb7,0x8f,0x78,0x00,0xb6,0x8f,0x74,0x00,0xb5,0x8f,0x70,0x00,0xb4,0x8f,
-0x6c,0x00,0xb3,0x8f,0x68,0x00,0xb2,0x8f,0x64,0x00,0xb1,0x8f,0x60,0x00,0xb0,0x8f,
-0x21,0x20,0x00,0x00,0x7a,0x42,0x00,0x08,0x88,0x00,0xbd,0x27,0x94,0x0e,0x42,0x36,
-0x9c,0x0e,0x43,0x36,0xa4,0x0e,0x44,0x36,0xac,0x0e,0x45,0x36,0x02,0x80,0x0d,0x3c,
-0x00,0x00,0x47,0x8c,0x68,0x15,0xad,0x25,0x00,0x00,0x6a,0x8c,0x00,0x00,0x8c,0x8c,
-0x00,0x00,0xa3,0x8c,0x10,0x40,0xa4,0x8d,0xb4,0x0e,0x42,0x36,0x00,0x00,0x48,0x8c,
-0x0c,0x40,0xa5,0x8d,0x25,0xb0,0x02,0x3c,0x00,0xfc,0x13,0x24,0xbc,0x0e,0x42,0x34,
-0x24,0x18,0x6f,0x00,0x00,0x00,0x49,0x8c,0x02,0x1c,0x03,0x00,0x24,0x38,0xef,0x00,
-0x24,0x20,0x93,0x00,0xf0,0xff,0x06,0x3c,0x25,0x20,0x83,0x00,0xff,0x03,0xc6,0x34,
-0x02,0x3c,0x07,0x00,0xc4,0x0e,0x42,0x36,0x24,0x28,0xb3,0x00,0x24,0x40,0x0f,0x01,
-0xcc,0x0e,0x4b,0x36,0x25,0x28,0xa7,0x00,0x24,0x20,0x86,0x00,0x00,0x00,0x47,0x8c,
-0x24,0x50,0x4f,0x01,0x00,0x00,0x63,0x8d,0x82,0x41,0x08,0x00,0x0f,0xc0,0x02,0x3c,
-0xff,0xff,0x42,0x34,0x25,0x20,0x88,0x00,0x82,0x51,0x0a,0x00,0x24,0x28,0xa6,0x00,
-0x24,0x48,0x2f,0x01,0x24,0x88,0x82,0x00,0x25,0x28,0xaa,0x00,0x24,0x60,0x8f,0x01,
-0x00,0x49,0x09,0x00,0x25,0x88,0x29,0x02,0x24,0x28,0xa2,0x00,0x24,0x18,0x6f,0x00,
-0x00,0x61,0x0c,0x00,0x24,0x38,0xef,0x00,0x25,0x28,0xac,0x00,0x02,0x3c,0x07,0x00,
-0x02,0x1c,0x03,0x00,0x82,0x27,0x11,0x00,0x01,0x00,0x02,0x24,0x16,0x40,0xa3,0xa5,
-0x14,0x40,0xa7,0xa5,0x0c,0x40,0xa5,0xad,0x4a,0x00,0x82,0x10,0x10,0x40,0xb1,0xad,
-0x80,0x0c,0x4c,0x36,0x00,0x00,0x8a,0x8d,0x82,0x72,0x05,0x00,0xff,0x03,0xce,0x31,
-0x00,0x02,0xc3,0x31,0x25,0x10,0xd3,0x01,0x0b,0x70,0x43,0x00,0x82,0x85,0x0a,0x00,
-0x18,0x00,0xd0,0x01,0xff,0x03,0xaf,0x30,0x00,0x02,0xa3,0x30,0x25,0x10,0xf3,0x01,
-0x0b,0x78,0x43,0x00,0x02,0x75,0x11,0x00,0xff,0x03,0xce,0x31,0xc0,0xff,0x08,0x3c,
-0x25,0x18,0xd3,0x01,0x00,0x02,0xc2,0x31,0x00,0xfc,0x06,0x35,0x0b,0x70,0x62,0x00,
-0x24,0x38,0x46,0x01,0x94,0x0c,0x4a,0x36,0xff,0x0f,0x09,0x3c,0xff,0xff,0x29,0x35,
-0x88,0x0c,0x54,0x36,0x12,0x20,0x00,0x00,0x02,0x22,0x04,0x00,0x3f,0x00,0x82,0x30,
-0x18,0x00,0xf0,0x01,0x82,0x7a,0x11,0x00,0xff,0x03,0xef,0x31,0x00,0x14,0x02,0x00,
-0x25,0x38,0xe2,0x00,0x00,0x02,0xe3,0x31,0x25,0x10,0xf3,0x01,0x0b,0x78,0x43,0x00,
-0xc0,0x03,0x84,0x30,0x80,0x25,0x04,0x00,0x9c,0x0c,0x4b,0x36,0x12,0x28,0x00,0x00,
-0x02,0x2a,0x05,0x00,0xff,0x03,0xa2,0x30,0x25,0x10,0xe2,0x00,0x00,0x00,0x82,0xad,
-0x00,0x00,0x42,0x8d,0x00,0x00,0x00,0x00,0x24,0x10,0x49,0x00,0x25,0x10,0x44,0x00,
-0x00,0x00,0x42,0xad,0x00,0x00,0x8a,0x8e,0x00,0x00,0x00,0x00,0x24,0x40,0x48,0x01,
-0x82,0x85,0x08,0x00,0x18,0x00,0xd0,0x01,0x24,0x30,0x46,0x01,0x12,0x18,0x00,0x00,
-0x02,0x1a,0x03,0x00,0x3f,0x00,0x62,0x30,0x18,0x00,0xf0,0x01,0x00,0x14,0x02,0x00,
-0x25,0x30,0xc2,0x00,0xc0,0x03,0x63,0x30,0x80,0x1d,0x03,0x00,0x12,0x20,0x00,0x00,
-0x02,0x22,0x04,0x00,0xff,0x03,0x82,0x30,0x25,0x10,0xc2,0x00,0x00,0x00,0x82,0xae,
-0x00,0x00,0x62,0x8d,0x00,0x00,0x00,0x00,0x24,0x10,0x49,0x00,0x25,0x10,0x43,0x00,
-0x00,0x00,0x62,0xad,0x00,0x17,0x16,0x00,0x25,0xb0,0x03,0x3c,0xdd,0xdd,0x42,0x34,
-0xc4,0x02,0x63,0x34,0x00,0x00,0x62,0xac,0xec,0x52,0x00,0x08,0x00,0x00,0x00,0x00,
-0xe0,0xff,0xbd,0x27,0x44,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24,
-0x47,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x8c,0x97,0xe7,0x24,0x11,0x00,0xa3,0xa3,
-0x12,0x00,0xa2,0xa3,0x10,0x27,0x03,0x24,0x01,0x00,0x02,0x24,0x01,0x80,0x06,0x3c,
-0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xe8,0x51,0xc6,0x24,0x0c,0x00,0xe3,0xac,
-0x14,0x00,0xe2,0xa0,0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,0x13,0x00,0xa0,0xa3,
-0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0xd0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,
-0x03,0x0d,0x44,0x34,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,
-0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x83,0x90,
-0x42,0x00,0x45,0x34,0xff,0x00,0x73,0x30,0x70,0x00,0x74,0x32,0x29,0x00,0x80,0x16,
-0x8f,0x00,0x62,0x32,0xff,0xff,0x02,0x24,0x00,0x00,0xa2,0xa0,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,
-0x18,0x00,0x04,0x24,0xdd,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0x00,0x80,0x06,0x36,0xff,0xff,0x25,0x36,0xba,0x44,0x00,0x0c,
-0x18,0x00,0x04,0x24,0x84,0x0a,0x00,0x0c,0x03,0x00,0x04,0x24,0x21,0x30,0xa0,0x02,
-0xff,0xff,0x25,0x36,0x5c,0x00,0x80,0x16,0x21,0x20,0x00,0x00,0x2c,0x00,0xbf,0x8f,
-0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,
-0x42,0x00,0x42,0x34,0x30,0x00,0xbd,0x27,0x00,0x00,0x40,0xa0,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x21,0x20,0x00,0x00,
-0xdd,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0xa8,0x40,0x00,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,
-0x7a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0xdd,0x44,0x00,0x0c,
-0xff,0xff,0x25,0x36,0x21,0xb0,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x64,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x08,0x00,0x10,0x3c,
-0xff,0xff,0x10,0x36,0x7a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x01,0x00,0x12,0x3c,
-0x24,0x30,0xb0,0x02,0x25,0x30,0xd2,0x00,0xff,0xff,0x25,0x36,0xba,0x44,0x00,0x0c,
-0x21,0x20,0x00,0x00,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x24,0x80,0xd0,0x02,
-0x7a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x25,0x30,0x12,0x02,0xff,0xff,0x25,0x36,
-0xba,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,
-0x7a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24,
-0xdd,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,
-0x00,0x80,0x06,0x36,0xff,0xff,0x25,0x36,0xba,0x44,0x00,0x0c,0x18,0x00,0x04,0x24,
-0x84,0x0a,0x00,0x0c,0x03,0x00,0x04,0x24,0x21,0x30,0xa0,0x02,0xff,0xff,0x25,0x36,
-0xa6,0xff,0x80,0x12,0x21,0x20,0x00,0x00,0x25,0xb0,0x02,0x3c,0x03,0x0d,0x42,0x34,
-0x00,0x00,0x53,0xa0,0xba,0x44,0x00,0x0c,0x00,0x00,0x00,0x00,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0x7a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0xff,0xff,0x25,0x36,
-0x21,0x30,0xc0,0x02,0xba,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,
-0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x21,0x20,0x00,0x00,0x7a,0x42,0x00,0x08,0x30,0x00,0xbd,0x27,
-0xd0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,0x02,0x80,0x14,0x3c,0x2c,0x00,0xbf,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x68,0x15,0x86,0x26,0x0c,0x40,0xc2,0x8c,0x00,0x00,0x00,0x00,0x82,0x17,0x02,0x00,
-0x01,0x00,0x42,0x30,0x07,0x00,0x40,0x14,0x68,0x15,0x85,0x26,0x08,0x40,0xc2,0x8c,
-0x01,0x00,0x03,0x24,0x42,0x17,0x02,0x00,0x03,0x00,0x42,0x30,0xf0,0x00,0x43,0x10,
-0x25,0xb0,0x02,0x3c,0x0c,0x40,0xa2,0x8c,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,
-0x01,0x00,0x44,0x30,0x0a,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x2c,0x00,0xbf,0x8f,
-0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
-0x18,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
-0x08,0x40,0xa2,0x8c,0x00,0x00,0x00,0x00,0x42,0x17,0x02,0x00,0x03,0x00,0x42,0x30,
-0xf2,0xff,0x44,0x14,0x25,0xb0,0x02,0x3c,0x0e,0x0c,0x44,0x34,0x00,0x00,0x83,0x90,
-0x00,0x01,0x02,0x24,0xff,0x00,0x63,0x30,0x01,0x00,0x63,0x24,0x8b,0x01,0x62,0x10,
-0x00,0x00,0x00,0x00,0x00,0x00,0x83,0xa0,0x68,0x15,0x84,0x26,0x10,0x40,0x82,0x8c,
-0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0xa4,0x01,0x43,0x10,0x0f,0x00,0x10,0x3c,
-0xc7,0x42,0x92,0x90,0x68,0x15,0x90,0x26,0xc6,0x42,0x03,0x92,0x25,0xb0,0x11,0x3c,
-0x62,0x0c,0x22,0x36,0x00,0x00,0x52,0xa0,0x17,0x01,0x60,0x10,0x01,0x00,0x02,0x24,
-0x03,0x0d,0x23,0x36,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x70,0x00,0x42,0x30,
-0x3e,0x01,0x40,0x14,0x63,0x0c,0x23,0x36,0xc4,0x42,0x02,0x96,0x00,0x00,0x00,0x00,
-0x23,0x20,0x52,0x00,0x2b,0x18,0x52,0x00,0x23,0x10,0x42,0x02,0x0a,0x10,0x83,0x00,
-0x03,0x00,0x42,0x2c,0x0b,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xc4,0x42,0x03,0x96,
-0x63,0x0c,0x22,0x36,0x00,0x00,0x43,0xa0,0x68,0x15,0x83,0x26,0xc3,0x42,0x62,0x90,
-0x08,0x40,0x66,0x8c,0xc2,0x42,0x72,0xa0,0x23,0x20,0x52,0x00,0x2b,0x38,0x42,0x02,
-0x23,0x50,0x42,0x02,0x02,0x2c,0x06,0x00,0x0b,0x50,0x87,0x00,0x3f,0x00,0xa5,0x30,
-0x3f,0x00,0xc4,0x30,0x24,0x00,0x02,0x24,0x20,0x00,0x03,0x24,0x23,0x10,0x44,0x00,
-0x2d,0x01,0x40,0x15,0x23,0x18,0x65,0x00,0x21,0x30,0x80,0x00,0x21,0x48,0xa0,0x00,
-0x02,0x80,0x0b,0x3c,0x68,0x15,0x83,0x26,0x80,0x10,0x06,0x00,0x21,0x10,0x43,0x00,
-0x0c,0x40,0x63,0x8c,0x18,0x40,0x44,0x8c,0xff,0x03,0x67,0x30,0x1b,0x01,0xe0,0x10,
-0x82,0x2d,0x04,0x00,0x00,0x02,0x62,0x30,0x04,0x00,0x40,0x10,0x18,0x00,0xe5,0x00,
-0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,0x18,0x00,0xe5,0x00,0x82,0x22,0x03,0x00,
-0xff,0x03,0x84,0x30,0x00,0x02,0x83,0x30,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,
-0x03,0x00,0x60,0x10,0xff,0x03,0x48,0x30,0x00,0xfc,0x02,0x24,0x25,0x20,0x82,0x00,
-0x18,0x00,0x85,0x00,0x80,0x2d,0x05,0x00,0x25,0xb0,0x06,0x3c,0x80,0x0c,0xc7,0x34,
-0x94,0x0c,0xc6,0x34,0x12,0x20,0x00,0x00,0x02,0x22,0x04,0x00,0x3f,0x00,0x82,0x30,
-0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0x25,0x28,0xa8,0x00,0x10,0x00,0xa5,0xaf,
-0x00,0x00,0xe5,0xac,0x00,0x00,0xc3,0x8c,0xff,0x0f,0x02,0x3c,0xc0,0x03,0x84,0x30,
-0xff,0xff,0x42,0x34,0x80,0x25,0x04,0x00,0x24,0x18,0x62,0x00,0x25,0x18,0x64,0x00,
-0x10,0x00,0xa3,0xaf,0x00,0x00,0xc3,0xac,0x68,0x15,0x83,0x26,0x08,0x40,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x08,0x01,0x40,0x04,0xc0,0x28,0x09,0x00,0x21,0x28,0xa3,0x00,
-0xac,0x40,0xa3,0x90,0x25,0xb0,0x04,0x3c,0x22,0x0a,0x82,0x34,0x00,0x00,0x43,0xa0,
-0xad,0x40,0xa6,0x90,0x23,0x0a,0x82,0x34,0x24,0x0a,0x87,0x34,0x00,0x00,0x46,0xa0,
-0xae,0x40,0xa3,0x90,0x25,0x0a,0x86,0x34,0x26,0x0a,0x88,0x34,0x00,0x00,0xe3,0xa0,
-0xaf,0x40,0xa2,0x90,0x27,0x0a,0x87,0x34,0x28,0x0a,0x89,0x34,0x00,0x00,0xc2,0xa0,
-0xb0,0x40,0xa3,0x90,0x29,0x0a,0x84,0x34,0x00,0x00,0x03,0xa1,0xb1,0x40,0xa2,0x90,
-0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0xa0,0xb2,0x40,0xa3,0x90,0x00,0x00,0x00,0x00,
-0x00,0x00,0x23,0xa1,0xb3,0x40,0xa2,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xa0,
-0x8e,0x7d,0x63,0x91,0x22,0x00,0x02,0x24,0x03,0x00,0x62,0x10,0x92,0x00,0x02,0x24,
-0x62,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x68,0x15,0x82,0x26,0x08,0x40,0x43,0x8c,
-0x01,0x00,0x44,0x39,0x24,0x00,0x02,0x24,0x02,0x1a,0x03,0x00,0x3f,0x00,0x63,0x30,
-0x01,0x00,0x84,0x30,0x04,0x01,0x80,0x10,0x23,0x28,0x43,0x00,0x42,0x18,0x0a,0x00,
-0x40,0x10,0x03,0x00,0x21,0x50,0x43,0x00,0x68,0x15,0x83,0x26,0xc3,0x42,0x62,0x90,
-0x00,0x00,0x00,0x00,0x2b,0x10,0x42,0x02,0x08,0x01,0x40,0x10,0x21,0x20,0x00,0x00,
-0x2b,0x10,0x45,0x01,0x07,0x00,0x40,0x10,0x24,0x00,0x04,0x24,0x08,0x40,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x21,0x20,0x4a,0x00,
-0x68,0x15,0x83,0x26,0x80,0x10,0x04,0x00,0x10,0x40,0x66,0x8c,0x21,0x10,0x43,0x00,
-0x18,0x40,0x44,0x8c,0x82,0x3a,0x06,0x00,0xff,0x03,0xe7,0x30,0xf0,0x00,0xe0,0x10,
-0x82,0x2d,0x04,0x00,0x00,0x02,0xe2,0x30,0x04,0x00,0x40,0x10,0x18,0x00,0xe5,0x00,
-0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,0x18,0x00,0xe5,0x00,0x02,0x25,0x06,0x00,
-0xff,0x03,0x84,0x30,0x00,0x02,0x83,0x30,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,
-0x03,0x00,0x60,0x10,0xff,0x03,0x48,0x30,0x00,0xfc,0x02,0x24,0x25,0x20,0x82,0x00,
-0x18,0x00,0x85,0x00,0x80,0x2d,0x05,0x00,0x25,0xb0,0x06,0x3c,0x88,0x0c,0xc7,0x34,
-0x9c,0x0c,0xc6,0x34,0x12,0x20,0x00,0x00,0x02,0x22,0x04,0x00,0x3f,0x00,0x82,0x30,
-0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0x25,0x28,0xa8,0x00,0x10,0x00,0xa5,0xaf,
-0x00,0x00,0xe5,0xac,0x00,0x00,0xc3,0x8c,0xff,0x0f,0x02,0x3c,0xc0,0x03,0x84,0x30,
-0xff,0xff,0x42,0x34,0x80,0x25,0x04,0x00,0x24,0x18,0x62,0x00,0x25,0x18,0x64,0x00,
-0x10,0x00,0xa3,0xaf,0x00,0x00,0xc3,0xac,0x95,0x54,0x00,0x08,0x00,0x00,0x00,0x00,
-0x80,0x0c,0x42,0x34,0x00,0x00,0x43,0x8c,0xc0,0xff,0x02,0x3c,0x21,0x88,0x00,0x00,
-0x24,0x28,0x62,0x00,0xc0,0xff,0x04,0x3c,0x8a,0x55,0x00,0x08,0x18,0x40,0xc3,0x24,
-0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,0x0d,0x00,0x40,0x10,0x02,0x80,0x0b,0x3c,
-0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x44,0x00,0xf8,0xff,0x45,0x14,
-0x04,0x00,0x63,0x24,0x08,0x40,0xc2,0x8c,0xc0,0xff,0x03,0x24,0x3f,0x00,0x24,0x32,
-0x24,0x10,0x43,0x00,0x25,0x10,0x44,0x00,0x08,0x40,0xc2,0xac,0x02,0x80,0x0b,0x3c,
-0x8e,0x7d,0x63,0x91,0x22,0x00,0x02,0x24,0x3e,0x00,0x62,0x10,0x92,0x00,0x02,0x24,
-0x3d,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x02,0x3c,0x24,0x0a,0x42,0x34,
-0x00,0x00,0x44,0x8c,0x3f,0x3f,0x03,0x3c,0x3f,0x3f,0x63,0x34,0x24,0x20,0x83,0x00,
-0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x16,0x56,0x53,0x24,0x1e,0x57,0x72,0x24,
-0x21,0x88,0x00,0x00,0xb1,0x55,0x00,0x08,0x10,0x00,0xa4,0xaf,0xd4,0x45,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x47,0x00,0x40,0x10,0x68,0x15,0x85,0x26,0x01,0x00,0x31,0x26,
-0x21,0x00,0x22,0x2e,0x17,0x00,0x40,0x10,0x68,0x15,0x84,0x26,0xc0,0x80,0x11,0x00,
-0x10,0x00,0xa4,0x27,0x21,0x28,0x13,0x02,0xd4,0x45,0x00,0x0c,0x04,0x00,0x06,0x24,
-0x21,0x28,0x12,0x02,0x10,0x00,0xa4,0x27,0xf0,0xff,0x40,0x14,0x04,0x00,0x06,0x24,
-0x68,0x15,0x85,0x26,0x08,0x40,0xa3,0x8c,0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0xff,0x7f,0x02,0x3c,
-0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x08,0x40,0xa3,0xac,
-0x68,0x15,0x84,0x26,0x0c,0x40,0x83,0x8c,0x00,0x40,0x02,0x3c,0x25,0x18,0x62,0x00,
-0x25,0xb0,0x02,0x3c,0x0e,0x0c,0x42,0x34,0x0c,0x40,0x83,0xac,0x00,0x00,0x40,0xa0,
-0x8f,0x54,0x00,0x08,0x68,0x15,0x85,0x26,0xc6,0x42,0x02,0xa2,0xba,0x54,0x00,0x08,
-0xc4,0x42,0x12,0xa6,0xda,0x53,0x00,0x0c,0x00,0x00,0x00,0x00,0xc9,0x54,0x00,0x08,
-0xc4,0x42,0x12,0xa6,0x25,0xb0,0x02,0x3c,0x88,0x0c,0x42,0x34,0x00,0x00,0x44,0x8c,
-0x02,0x80,0x03,0x3c,0x68,0x15,0x66,0x24,0xc0,0xff,0x02,0x3c,0x24,0x28,0x82,0x00,
-0x21,0x88,0x00,0x00,0xc0,0xff,0x04,0x3c,0xe6,0x55,0x00,0x08,0x18,0x40,0xc3,0x24,
-0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,0xb8,0xff,0x40,0x10,0x25,0xb0,0x02,0x3c,
-0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x44,0x00,0xf8,0xff,0x45,0x14,
-0x04,0x00,0x63,0x24,0x08,0x40,0xc2,0x8c,0x3f,0x00,0x23,0x32,0xff,0xc0,0x04,0x24,
-0x24,0x10,0x44,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x43,0x00,0x9c,0x55,0x00,0x08,
-0x08,0x40,0xc2,0xac,0x08,0x40,0xa3,0x8c,0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,
-0x00,0x80,0x02,0x3c,0xc5,0x55,0x00,0x08,0x25,0x18,0x62,0x00,0xcc,0xff,0x02,0x24,
-0x00,0x00,0x62,0xa0,0xcd,0x54,0x00,0x08,0x68,0x15,0x83,0x26,0x25,0xb0,0x02,0x3c,
-0x94,0x0c,0x43,0x34,0x80,0x0c,0x42,0x34,0x00,0x00,0x44,0xac,0x00,0x00,0x60,0xac,
-0x0d,0x55,0x00,0x08,0x68,0x15,0x83,0x26,0x2f,0x00,0xe0,0x10,0x21,0x30,0x00,0x00,
-0x2b,0x10,0x42,0x01,0x21,0x20,0x8a,0x00,0x00,0x00,0x42,0x38,0x24,0x00,0x06,0x24,
-0x2b,0x18,0x43,0x01,0x0b,0x30,0x82,0x00,0xcd,0xfe,0x60,0x10,0x20,0x00,0x09,0x24,
-0x68,0x15,0x83,0x26,0x0a,0x40,0x62,0x94,0x02,0x80,0x0b,0x3c,0x3f,0x00,0x42,0x30,
-0xe0,0x54,0x00,0x08,0x21,0x48,0x4a,0x00,0x21,0x28,0xa3,0x00,0xb4,0x41,0xa3,0x90,
-0x25,0xb0,0x04,0x3c,0x22,0x0a,0x82,0x34,0x00,0x00,0x43,0xa0,0xb5,0x41,0xa6,0x90,
-0x23,0x0a,0x82,0x34,0x24,0x0a,0x87,0x34,0x00,0x00,0x46,0xa0,0xb6,0x41,0xa3,0x90,
-0x25,0x0a,0x86,0x34,0x26,0x0a,0x88,0x34,0x00,0x00,0xe3,0xa0,0xb7,0x41,0xa2,0x90,
-0x27,0x0a,0x87,0x34,0x28,0x0a,0x89,0x34,0x00,0x00,0xc2,0xa0,0xb8,0x41,0xa3,0x90,
-0x29,0x0a,0x84,0x34,0x00,0x00,0x03,0xa1,0xb9,0x41,0xa2,0x90,0x00,0x00,0x00,0x00,
-0x00,0x00,0xe2,0xa0,0xba,0x41,0xa3,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xa1,
-0xbb,0x41,0xa2,0x90,0x2d,0x55,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xa0,
-0xad,0x54,0x00,0x08,0x68,0x15,0x84,0x26,0x23,0x10,0x8a,0x00,0x2b,0x18,0x44,0x01,
-0x2b,0x20,0x45,0x01,0x0b,0x30,0x43,0x00,0xa1,0xfe,0x80,0x14,0x23,0x48,0xaa,0x00,
-0xde,0x54,0x00,0x08,0x21,0x48,0x00,0x00,0xff,0xff,0x43,0x25,0x42,0x18,0x03,0x00,
-0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x40,0x55,0x00,0x08,0x01,0x00,0x4a,0x24,
-0x25,0xb0,0x02,0x3c,0x9c,0x0c,0x43,0x34,0x88,0x0c,0x42,0x34,0x00,0x00,0x44,0xac,
-0x00,0x00,0x60,0xac,0x95,0x54,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x40,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x23,0x18,0x4a,0x00,
-0x2b,0x10,0x42,0x01,0x4e,0x55,0x00,0x08,0x0b,0x20,0x62,0x00,0xff,0xff,0x05,0x36,
-0x60,0x00,0x06,0x24,0xba,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0x84,0x0a,0x00,0x0c,
-0xe8,0x03,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x24,0x00,0x04,0x24,0xdd,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,
-0x1f,0x00,0x52,0x30,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0xb4,0x54,0x00,0x08,0x68,0x15,0x90,0x26,
-0x00,0xff,0x84,0x30,0x02,0x22,0x04,0x00,0x08,0x00,0x80,0x10,0x02,0x80,0x02,0x3c,
-0xff,0x00,0x02,0x24,0x04,0x00,0x82,0x10,0xcc,0xff,0x03,0x24,0x02,0x80,0x02,0x3c,
-0x08,0x00,0xe0,0x03,0x4e,0x58,0x43,0xa0,0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,
-0x4e,0x58,0x44,0xa0,0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,
-0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,
-0x80,0x10,0x02,0x00,0x68,0x15,0x63,0x24,0x20,0x00,0x84,0x2c,0x09,0x00,0x80,0x10,
-0x21,0x10,0x43,0x00,0x68,0x51,0x43,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
-0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x44,0x79,0x43,0x8c,0x25,0xb0,0x02,0x3c,
-0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x85,0x30,0xd2,0xff,0xa3,0x24,
-0xfe,0xff,0xa2,0x24,0xda,0xff,0xa4,0x24,0x04,0x00,0x63,0x2c,0x08,0x00,0x84,0x2c,
-0x06,0x00,0x60,0x14,0xff,0x00,0x42,0x30,0xf0,0xff,0xa2,0x24,0xfc,0xff,0xa3,0x24,
-0x16,0x00,0x46,0x2c,0x03,0x00,0x80,0x10,0xff,0x00,0x62,0x30,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0xfa,0xff,0xa3,0x24,0xfc,0xff,0xc0,0x10,0x21,0x10,0xa0,0x00,
-0x08,0x00,0xe0,0x03,0xff,0x00,0x62,0x30,0x25,0xb0,0x04,0x3c,0x03,0x0d,0x85,0x34,
-0x00,0x00,0xa3,0x90,0x2d,0x0a,0x84,0x34,0xff,0x00,0x63,0x30,0x08,0x00,0x63,0x34,
-0x00,0x00,0xa3,0xa0,0x00,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,0xf7,0x00,0x42,0x30,
-0x00,0x00,0xa2,0xa0,0x00,0x00,0x83,0x90,0x00,0x00,0x00,0x00,0x3f,0x00,0x63,0x30,
-0x00,0x00,0x83,0xa0,0x00,0x00,0x82,0x90,0x80,0xff,0x03,0x24,0x25,0x10,0x43,0x00,
-0x00,0x00,0x82,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
-0xff,0x00,0x03,0x3c,0x82,0x01,0x49,0x34,0x81,0x01,0x48,0x34,0x24,0x10,0x83,0x00,
-0x02,0x3c,0x02,0x00,0x00,0xff,0x63,0x34,0x02,0x80,0x02,0x3c,0x68,0x15,0x45,0x24,
-0x02,0x32,0x04,0x00,0x01,0x00,0x02,0x24,0x24,0x20,0x83,0x00,0xc2,0x4c,0xa2,0xa0,
-0xb0,0x4c,0xa0,0xac,0xb4,0x4c,0xa0,0xac,0xb8,0x4c,0xa0,0xac,0x06,0x00,0x80,0x14,
-0xbc,0x4c,0xa0,0xac,0x00,0x00,0x02,0x91,0x00,0x00,0x23,0x91,0xc0,0x4c,0xa2,0xa0,
-0x08,0x00,0xe0,0x03,0xc1,0x4c,0xa3,0xa0,0xc1,0x4c,0xa7,0xa0,0x08,0x00,0xe0,0x03,
-0xc0,0x4c,0xa6,0xa0,0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0xc1,0x4c,0x66,0x90,
-0xc0,0x4c,0x65,0x90,0x25,0xb0,0x02,0x3c,0x82,0x01,0x44,0x34,0x81,0x01,0x42,0x34,
-0x00,0x00,0x45,0xa0,0x00,0x00,0x86,0xa0,0x08,0x00,0xe0,0x03,0xc2,0x4c,0x60,0xa0,
-0x02,0x80,0x08,0x3c,0x68,0x15,0x04,0x25,0xc2,0x4c,0x82,0x90,0x00,0x00,0x00,0x00,
-0x15,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0xb4,0x4c,0x82,0x8c,0xb0,0x4c,0x85,0x8c,
-0x25,0xb0,0x03,0x3c,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x82,0x01,0x67,0x34,
-0x0f,0x00,0x40,0x10,0x81,0x01,0x66,0x34,0xc1,0x4c,0x83,0x90,0xc0,0x4c,0x82,0x90,
-0xf0,0x00,0x63,0x30,0x1f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0,0x00,0x00,0xe3,0xa0,
-0x68,0x15,0x02,0x25,0x01,0x00,0x03,0x24,0xbc,0x4c,0x40,0xac,0xb0,0x4c,0x40,0xac,
-0xb4,0x4c,0x40,0xac,0xb8,0x4c,0x40,0xac,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0xb8,0x4c,0x82,0x8c,0x25,0xb0,0x03,0x3c,0x82,0x01,0x69,0x34,0x40,0x11,0x02,0x00,
-0x2b,0x10,0xa2,0x00,0x0e,0x00,0x40,0x14,0x81,0x01,0x66,0x34,0xbc,0x4c,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x08,0x00,0x40,0x14,
-0x00,0x00,0x00,0x00,0xc1,0x4c,0x83,0x90,0xc0,0x4c,0x82,0x90,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc2,0xa0,0x00,0x00,0x23,0xa1,0xf7,0x56,0x00,0x08,0x68,0x15,0x02,0x25,
-0xc1,0x4c,0x83,0x90,0xc0,0x4c,0x82,0x90,0xf0,0x00,0x63,0x30,0x7f,0x00,0x42,0x30,
-0x00,0x00,0xc2,0xa0,0x00,0x00,0x23,0xa1,0xf7,0x56,0x00,0x08,0x68,0x15,0x02,0x25,
-0x02,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x3d,0x58,0x43,0xa0,
-0xcc,0xff,0x03,0x24,0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x3d,0x58,0x43,0xa0,
-0x25,0xb0,0x03,0x3c,0x33,0x02,0x65,0x34,0x00,0x11,0x04,0x00,0x00,0x00,0xa2,0xa0,
-0x30,0x02,0x63,0x34,0x00,0x00,0x65,0x8c,0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x24,0x28,0xa2,0x00,0x01,0x00,0x03,0x24,0x04,0x18,0x83,0x00,0x02,0x00,0xa0,0x10,
-0x21,0x10,0x00,0x00,0xff,0xff,0x62,0x30,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x25,0xb0,0x11,0x3c,0x18,0x00,0xb2,0xaf,
-0x4c,0x00,0x22,0x36,0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x44,0x90,
-0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x24,0xff,0x00,0x84,0x30,0x07,0x00,0x82,0x10,
-0x68,0x15,0x72,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe6,0x63,0x43,0x96,
-0x01,0x00,0x02,0x24,0xf7,0xff,0x62,0x14,0x21,0x20,0x00,0x00,0x22,0x57,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x24,0x22,0x57,0x00,0x0c,0x21,0x80,0x40,0x00,
-0x25,0x80,0x02,0x02,0x33,0x02,0x23,0x36,0x08,0x00,0x02,0x24,0xff,0xff,0x10,0x32,
-0x40,0x00,0x25,0x36,0x00,0x00,0x62,0xa0,0xea,0xff,0x00,0x16,0x00,0x00,0x00,0x00,
-0x00,0x00,0xa2,0x94,0xe4,0x63,0x43,0x96,0xff,0xdf,0x42,0x30,0x00,0x20,0x44,0x34,
-0x01,0x00,0x63,0x24,0xe4,0x63,0x43,0xa6,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa4,0xa4,
-0x3f,0x57,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x18,0x03,0x42,0x34,0x80,0x5d,0x63,0x24,0x00,0x00,0x43,0xac,0x63,0x00,0x02,0x24,
-0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x02,0x80,0x02,0x3c,
-0x88,0x7d,0x45,0x94,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x8b,0x7d,0x66,0x90,
-0x98,0x7d,0x47,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xa3,0x7d,0x69,0x90,
-0xa5,0x7d,0x4a,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xa8,0x7d,0x6b,0x90,
-0xaa,0x7d,0x4c,0x90,0x07,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x25,0xb0,0x04,0x3c,
-0x95,0x7d,0x43,0xa0,0xb0,0x03,0x84,0x34,0x02,0x80,0x02,0x3c,0x02,0x80,0x18,0x3c,
-0x8a,0x7d,0x08,0x93,0x00,0x00,0x85,0xac,0x96,0x7d,0x40,0xa0,0x02,0x80,0x02,0x3c,
-0x00,0x00,0x86,0xac,0x02,0x80,0x0f,0x3c,0x97,0x7d,0x40,0xa0,0x02,0x80,0x02,0x3c,
-0x00,0x00,0x87,0xac,0x68,0x15,0xee,0x25,0xb8,0x7d,0x40,0xa0,0xfd,0xff,0x02,0x24,
-0xd5,0x4a,0xc2,0xa1,0x01,0x00,0x03,0x24,0x00,0x78,0x02,0x24,0xd4,0x4a,0xc3,0xa1,
-0xd8,0x4a,0xc2,0xa5,0xff,0x07,0x03,0x24,0x0f,0x00,0x0d,0x31,0x02,0x00,0x02,0x24,
-0xda,0x4a,0xc3,0xa5,0x00,0x00,0x88,0xac,0x00,0x00,0x89,0xac,0x00,0x00,0x8a,0xac,
-0x00,0x00,0x8b,0xac,0x00,0x00,0x8c,0xac,0x17,0x00,0xa2,0x11,0x02,0x80,0x02,0x3c,
-0x8a,0x7d,0x02,0x93,0x01,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x05,0x00,0x43,0x10,
-0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0xca,0x7d,0x40,0xa4,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x3c,0x68,0x15,0xe4,0x25,0x02,0xbc,0x42,0x34,
-0x68,0x4b,0x82,0xac,0x15,0x15,0x03,0x3c,0x02,0x02,0x02,0x3c,0x07,0x07,0x63,0x34,
-0x64,0x4b,0x82,0xac,0x02,0x80,0x02,0x3c,0x60,0x4b,0x83,0xac,0xca,0x7d,0x40,0xa4,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x8f,0x7d,0x44,0x90,0x06,0x00,0x03,0x24,
-0x15,0x00,0x83,0x10,0x0b,0x00,0x02,0x24,0x0a,0x00,0x82,0x10,0x00,0xe0,0x02,0x3c,
-0x68,0x15,0xe4,0x25,0x00,0xb2,0x42,0x34,0x00,0x1c,0x03,0x3c,0x68,0x4b,0x82,0xac,
-0x00,0x1c,0x63,0x34,0x00,0x04,0x02,0x24,0x60,0x4b,0x83,0xac,0x9a,0x57,0x00,0x08,
-0x64,0x4b,0x82,0xac,0x00,0x80,0x02,0x3c,0x00,0xbc,0x42,0x34,0x15,0x15,0x03,0x3c,
-0x68,0x4b,0xc2,0xad,0x07,0x07,0x63,0x34,0x03,0x03,0x02,0x3c,0x60,0x4b,0xc3,0xad,
-0x9a,0x57,0x00,0x08,0x64,0x4b,0xc2,0xad,0x00,0xc0,0x02,0x3c,0x00,0xb2,0x42,0x34,
-0x1c,0x1c,0x03,0x3c,0x68,0x4b,0xc2,0xad,0x07,0x07,0x63,0x34,0x00,0x04,0x02,0x24,
-0x60,0x4b,0xc3,0xad,0x9a,0x57,0x00,0x08,0x64,0x4b,0xc2,0xad,0x25,0xb0,0x02,0x3c,
-0x4d,0x00,0x44,0x34,0xff,0x00,0x03,0x3c,0xec,0x02,0x42,0x34,0x00,0x00,0x43,0xac,
-0x00,0x00,0x80,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x64,0x5f,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x7f,0x00,0x02,0x3c,0xfd,0xbf,0x45,0x34,
-0x80,0x04,0x03,0x3c,0x25,0x28,0xa3,0x00,0x00,0x08,0x04,0x3c,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x42,0x24,0x25,0x28,0xa4,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x65,0xac,
-0x04,0x4b,0x45,0xac,0xfc,0x4a,0x45,0xac,0x08,0x00,0x63,0x34,0x86,0x00,0x05,0x24,
-0x00,0x00,0x65,0xa4,0x08,0x4b,0x45,0xa4,0x00,0x4b,0x40,0xac,0x0a,0x4b,0x40,0xa4,
-0x0c,0x4b,0x45,0xa4,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf8,0x57,0x00,0x08,0x00,0x00,0x00,0x00,
-0x42,0xb0,0x02,0x3c,0xa0,0xff,0x03,0x24,0x01,0x00,0x42,0x34,0xe8,0xff,0xbd,0x27,
-0x21,0x20,0x00,0x00,0x01,0x00,0x05,0x24,0x00,0x01,0x06,0x24,0x00,0x00,0x43,0xa0,
-0x10,0x00,0xbf,0xaf,0xc4,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,
-0x03,0x00,0x04,0x24,0x01,0x00,0x05,0x24,0x40,0x1f,0x06,0x24,0xc4,0x0c,0x00,0x08,
-0x18,0x00,0xbd,0x27,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x14,0x00,0xbf,0xaf,
-0x21,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,
-0x48,0x01,0x03,0x24,0xe0,0x63,0x43,0xac,0xdc,0x63,0x43,0xac,0x21,0x80,0x40,0x00,
-0x1f,0x00,0x03,0x24,0xff,0xff,0x63,0x24,0xc4,0x4c,0x40,0xa4,0xc6,0x4c,0x40,0xa4,
-0xc8,0x4c,0x40,0xa4,0xca,0x4c,0x40,0xa4,0xcc,0x4c,0x40,0xa4,0xce,0x4c,0x40,0xa4,
-0xd0,0x4c,0x40,0xa4,0xd2,0x4c,0x40,0xa4,0xd4,0x4c,0x40,0xa4,0xf5,0xff,0x61,0x04,
-0x24,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x10,0x00,0x03,0x24,0xb0,0x03,0x42,0x34,
-0x02,0x80,0x04,0x3c,0x8c,0x58,0x84,0x24,0x00,0x00,0x43,0xac,0x21,0x28,0x00,0x00,
-0x97,0x45,0x00,0x0c,0x04,0x00,0x06,0x24,0xef,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x71,0x5c,0x00,0x0c,0x8c,0x65,0x00,0xae,0xa7,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x4b,0x5e,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x8e,0x7d,0x64,0x90,
-0x92,0x00,0x02,0x24,0x03,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0xf7,0x5d,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xdd,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,0x8b,0x5c,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xe4,0x63,0x00,0xa6,0x67,0x5e,0x00,0x0c,0xe6,0x63,0x00,0xa6,
-0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x80,0x04,0x3c,0x02,0x80,0x05,0x3c,
-0xf8,0x7a,0x82,0x24,0x00,0x7b,0xa3,0x24,0x18,0x00,0xbd,0x27,0x04,0x00,0x42,0xac,
-0xf8,0x7a,0x82,0xac,0x00,0x7b,0xa3,0xac,0x08,0x00,0xe0,0x03,0x04,0x00,0x63,0xac,
-0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x01,0x80,0x02,0x3c,0x25,0xb0,0x10,0x3c,
-0x18,0x03,0x03,0x36,0x38,0x61,0x42,0x24,0x00,0x00,0x62,0xac,0x14,0x00,0xbf,0xaf,
-0x60,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0xd5,0x58,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x01,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0xfd,0x5a,0x00,0x0c,0xdb,0x60,0x43,0xa0,
-0xd1,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x41,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x0b,0x58,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x00,0x03,0x36,0x00,0x00,0x62,0x94,
-0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x34,0x00,0x00,0x62,0xa4,0xd9,0x57,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xfa,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0xc9,0x5a,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x8e,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,
-0xb4,0x24,0x84,0x24,0xe6,0x5a,0x00,0x0c,0x01,0x00,0x05,0x24,0x01,0x80,0x04,0x3c,
-0x08,0x1e,0x84,0x24,0xe6,0x5a,0x00,0x0c,0x02,0x00,0x05,0x24,0x81,0x4e,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,0x54,0x34,0x84,0x24,0xe6,0x5a,0x00,0x0c,
-0x03,0x00,0x05,0x24,0x02,0x80,0x02,0x3c,0x98,0x7d,0x43,0x90,0x43,0x00,0x04,0x36,
-0x29,0x00,0x60,0x10,0xd8,0x00,0x10,0x36,0x07,0x00,0x02,0x24,0x2b,0x00,0x62,0x10,
-0x25,0xb0,0x04,0x3c,0x10,0x02,0x86,0x34,0x43,0x00,0x85,0x34,0x03,0x00,0x02,0x24,
-0x10,0x00,0x03,0x24,0x00,0x00,0xa2,0xa0,0xd8,0x00,0x84,0x34,0x00,0x00,0xc3,0xa0,
-0x00,0x00,0x82,0x90,0x80,0xff,0x03,0x24,0x42,0xb0,0x05,0x3c,0x25,0x10,0x43,0x00,
-0x00,0x00,0x82,0xa0,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x82,0x94,
-0x00,0x00,0x00,0x00,0xc0,0x00,0x42,0x34,0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,
-0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x34,0x00,0x00,0xa3,0xa0,0xe0,0x57,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24,0x21,0x28,0x00,0x00,
-0x21,0x30,0x00,0x00,0x31,0x1c,0x00,0x0c,0x21,0x38,0x00,0x00,0xf8,0x57,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x00,0x00,0x80,0xa0,0x00,0x00,0x03,0x92,
-0x80,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x00,0x00,0x03,0xa2,0x25,0xb0,0x04,0x3c,
-0x44,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0x42,0xb0,0x05,0x3c,0xc0,0x00,0x42,0x34,
-0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x34,
-0x00,0x00,0xa3,0xa0,0xe0,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,
-0x08,0x00,0x84,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0x31,0x1c,0x00,0x0c,
-0x21,0x38,0x00,0x00,0xf8,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,
-0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
-0x21,0x20,0x00,0x00,0x20,0xb0,0x06,0x3c,0xff,0xff,0x05,0x34,0x21,0x18,0x86,0x00,
-0x04,0x00,0x84,0x24,0x2a,0x10,0xa4,0x00,0x00,0x00,0x60,0xac,0xfb,0xff,0x40,0x10,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xb8,0xff,0xbd,0x27,
-0x25,0xb0,0x04,0x3c,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf,0x3c,0x00,0xb7,0xaf,
-0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf,0x2c,0x00,0xb3,0xaf,
-0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf,0x0a,0x00,0x83,0x34,
-0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30,0x0c,0x00,0x40,0x10,
-0x4c,0x87,0x02,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x30,
-0x66,0x01,0x40,0x10,0x4c,0x87,0x02,0x3c,0x54,0x00,0x83,0x34,0x50,0x00,0x82,0x34,
-0x00,0x00,0x45,0xac,0x00,0x00,0x65,0xa4,0xf9,0x58,0x00,0x08,0x02,0x80,0x03,0x3c,
-0x54,0x00,0x85,0x34,0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24,
-0x00,0x00,0x82,0xac,0x00,0x00,0xa3,0xac,0x02,0x80,0x03,0x3c,0x68,0x15,0x62,0x24,
-0xd5,0x4a,0x43,0x90,0xda,0x4a,0x45,0x94,0x25,0xb0,0x1e,0x3c,0x1c,0x00,0xa3,0xa3,
-0x60,0x4b,0x43,0x8c,0x58,0x00,0xc6,0x37,0xff,0xff,0x04,0x24,0x10,0x00,0xa3,0xaf,
-0x64,0x4b,0x43,0x8c,0x5c,0x00,0xc7,0x37,0x60,0x00,0xc8,0x37,0x14,0x00,0xa3,0xaf,
-0x68,0x4b,0x42,0x8c,0x64,0x00,0xc9,0x37,0x8a,0x00,0xca,0x37,0x18,0x00,0xa2,0xaf,
-0x24,0x10,0x02,0x3c,0x21,0x28,0xa2,0x00,0x4c,0x81,0x02,0x3c,0x00,0xe0,0x42,0x34,
-0x00,0x00,0xc2,0xac,0x96,0x01,0x03,0x24,0x28,0x28,0x02,0x24,0x00,0x00,0xe3,0xac,
-0x89,0x00,0xcb,0x37,0x00,0x00,0x04,0xad,0x8c,0x00,0xcc,0x37,0x00,0x00,0x24,0xad,
-0x09,0x00,0x03,0x24,0x00,0x00,0x42,0xa5,0x10,0x10,0x02,0x24,0x00,0x00,0x63,0xa1,
-0x8e,0x00,0xcd,0x37,0x00,0x00,0x82,0xa5,0x0a,0x0a,0x03,0x24,0x13,0x00,0x02,0x24,
-0x90,0x00,0xce,0x37,0x00,0x00,0xa3,0xa5,0x00,0x00,0xc2,0xa1,0x25,0xb0,0x02,0x3c,
-0x40,0x00,0x03,0x24,0x91,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x25,0xb0,0x03,0x3c,
-0x3a,0x01,0x02,0x24,0x92,0x00,0x63,0x34,0x00,0x00,0x62,0xa4,0xb5,0x00,0xd1,0x37,
-0x21,0x00,0x03,0x24,0x00,0x00,0x23,0xa2,0x10,0x00,0xa2,0x8f,0xa0,0x00,0xd2,0x37,
-0xa4,0x00,0xd3,0x37,0x00,0x00,0x42,0xae,0x14,0x00,0xa3,0x8f,0xa8,0x00,0xd4,0x37,
-0xac,0x00,0xd5,0x37,0x00,0x00,0x63,0xae,0x18,0x00,0xa2,0x8f,0x25,0xb0,0x03,0x3c,
-0xb0,0x00,0x63,0x34,0x00,0x00,0x82,0xae,0x21,0x10,0x02,0x3c,0xff,0x77,0x42,0x34,
-0x00,0x00,0xa2,0xae,0x25,0xb0,0x02,0x3c,0xd8,0x00,0x42,0x34,0x00,0x00,0x65,0xac,
-0x00,0x00,0x40,0xa0,0x1c,0x00,0xa2,0x93,0x25,0xb0,0x03,0x3c,0xb4,0x00,0x63,0x34,
-0x00,0x00,0x62,0xa0,0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x24,0xb6,0x00,0x63,0x34,
-0x00,0x00,0x62,0xa0,0x25,0xb0,0x03,0x3c,0x0f,0x00,0x02,0x24,0xba,0x00,0x63,0x34,
-0xb9,0x00,0xdf,0x37,0x00,0x00,0xe4,0xa3,0x00,0x00,0x62,0xa4,0x25,0xb0,0x02,0x3c,
-0x1a,0x01,0x42,0x34,0x16,0x01,0xd0,0x37,0x18,0x01,0xcf,0x37,0x00,0x00,0x00,0xa6,
-0x25,0xb0,0x03,0x3c,0x00,0x00,0xe0,0xa5,0x00,0x00,0x40,0xa4,0xff,0xff,0x02,0x3c,
-0xff,0x0f,0x42,0x34,0xdc,0x00,0x63,0x34,0x00,0x00,0x62,0xac,0x2f,0x00,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x32,0x32,0x63,0x34,0xd0,0x01,0x42,0x34,0x00,0x00,0x43,0xac,
-0x5e,0x00,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x32,0x43,0x42,0x34,0xd4,0x01,0x63,0x34,
-0x00,0x00,0x62,0xac,0x08,0x00,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x30,0xa5,0x63,0x34,
-0xd8,0x01,0x42,0x34,0x00,0x00,0x43,0xac,0xdc,0x01,0xc4,0x37,0x02,0x80,0x03,0x3c,
-0x49,0xa5,0x02,0x34,0x8e,0x7d,0x6d,0x90,0x00,0x00,0x82,0xac,0xc2,0x00,0x02,0x3c,
-0x1a,0x06,0x03,0x24,0x51,0x10,0x42,0x34,0xe0,0x01,0xc5,0x37,0xf4,0x01,0xc6,0x37,
-0xf8,0x01,0xc7,0x37,0x07,0x07,0x04,0x24,0x00,0x00,0xa3,0xa4,0x00,0x02,0xc8,0x37,
-0x00,0x00,0xc4,0xa4,0x26,0x00,0x03,0x24,0x00,0x00,0xe2,0xac,0x03,0x02,0xc9,0x37,
-0x04,0x00,0x02,0x24,0x00,0x00,0x03,0xa5,0x36,0x02,0xca,0x37,0x00,0x00,0x22,0xa1,
-0xc0,0x01,0x03,0x24,0x0c,0x00,0x02,0x24,0x34,0x02,0xcb,0x37,0x00,0x00,0x42,0xa1,
-0x37,0x02,0xcc,0x37,0x00,0x00,0x63,0xa5,0x03,0x00,0x02,0x24,0x22,0x00,0x03,0x24,
-0x00,0x00,0x82,0xa1,0xd6,0x00,0xa3,0x11,0x1b,0x1b,0x02,0x3c,0x13,0x13,0x02,0x3c,
-0x13,0x13,0x42,0x34,0x60,0x01,0xc3,0x37,0x64,0x01,0xc4,0x37,0x68,0x01,0xc5,0x37,
-0x7c,0x01,0xca,0x37,0x6c,0x01,0xc6,0x37,0x70,0x01,0xc7,0x37,0x74,0x01,0xc8,0x37,
-0x78,0x01,0xc9,0x37,0x00,0x00,0x62,0xac,0x00,0x00,0x82,0xac,0x02,0x80,0x03,0x3c,
-0x00,0x00,0xa2,0xac,0x00,0x00,0xc2,0xac,0x00,0x00,0xe2,0xac,0x00,0x00,0x02,0xad,
-0x00,0x00,0x22,0xad,0x00,0x00,0x42,0xad,0x8e,0x7d,0x65,0x90,0x25,0xb0,0x0c,0x3c,
-0x01,0x70,0x03,0x3c,0x80,0x01,0x82,0x35,0x08,0x5f,0x63,0x34,0x22,0x00,0x04,0x24,
-0x00,0x00,0x43,0xac,0xb5,0x00,0xa4,0x10,0x0f,0x1f,0x02,0x3c,0x92,0x00,0x02,0x24,
-0xb2,0x00,0xa2,0x10,0x0f,0x1f,0x02,0x3c,0x0f,0x10,0x02,0x3c,0x00,0xf0,0x51,0x34,
-0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0x77,0x00,0x0e,0x24,0x84,0x01,0x87,0x35,
-0x88,0x01,0x88,0x35,0x10,0xf0,0x44,0x34,0x8c,0x01,0x85,0x35,0x05,0xf0,0x42,0x34,
-0x00,0x00,0xed,0xac,0x90,0x01,0x83,0x35,0x00,0x00,0x04,0xad,0x94,0x01,0x86,0x35,
-0x00,0x00,0xa2,0xac,0xf5,0x0f,0x02,0x24,0x00,0x00,0x71,0xac,0x25,0xb0,0x05,0x3c,
-0x00,0x00,0xc2,0xac,0x98,0x01,0x89,0x35,0x9c,0x01,0x8a,0x35,0xf0,0x0f,0x03,0x24,
-0x0d,0x00,0x02,0x24,0x00,0x00,0x23,0xad,0xa0,0x01,0x8b,0x35,0x00,0x00,0x42,0xad,
-0xa7,0x01,0xb7,0x34,0xf6,0x01,0x8c,0x35,0xff,0xff,0x02,0x24,0x00,0x00,0x6d,0xad,
-0x00,0x00,0x8e,0xa1,0x00,0x00,0x4e,0xa2,0x00,0x00,0xe2,0xa2,0x25,0xb0,0x02,0x3c,
-0xa8,0x01,0xb6,0x34,0xff,0xff,0x09,0x24,0xac,0x01,0x42,0x34,0x00,0x00,0xc9,0xae,
-0x03,0x04,0x04,0x3c,0x00,0x00,0x49,0xac,0x07,0x08,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x01,0x02,0x84,0x34,0x05,0x06,0x63,0x34,0xb4,0x01,0xb1,0x34,0xb8,0x01,0xb2,0x34,
-0xbc,0x01,0xb3,0x34,0xb0,0x01,0x42,0x34,0x00,0x00,0x44,0xac,0x00,0x00,0x23,0xae,
-0x25,0xb0,0x02,0x3c,0x00,0x00,0x44,0xae,0x00,0x00,0x63,0xae,0x25,0xb0,0x03,0x3c,
-0x0c,0x00,0x06,0x24,0xc0,0x01,0xb4,0x34,0xc1,0x01,0xb5,0x34,0x0d,0x00,0x08,0x24,
-0xc2,0x01,0x63,0x34,0xc3,0x01,0x42,0x34,0x00,0x00,0x86,0xa2,0xc4,0x01,0xab,0x34,
-0x00,0x00,0xa6,0xa2,0xc5,0x01,0xac,0x34,0x00,0x00,0x66,0xa0,0x0e,0x00,0x07,0x24,
-0x00,0x00,0x48,0xa0,0xc6,0x01,0xaa,0x34,0xc7,0x01,0xad,0x34,0x0f,0x00,0x02,0x24,
-0x00,0x00,0x68,0xa1,0x00,0x00,0x87,0xa1,0x00,0x00,0x47,0xa1,0x00,0x00,0xa2,0xa1,
-0x57,0x01,0x02,0x3c,0x48,0x00,0xbf,0x34,0x46,0x00,0xae,0x34,0x0e,0xe2,0x42,0x34,
-0x00,0x00,0xc0,0xa5,0x4c,0x00,0xbe,0x34,0x00,0x00,0xe2,0xaf,0x4d,0x00,0xb9,0x34,
-0x80,0xff,0x02,0x24,0x00,0x00,0xc0,0xa3,0x00,0x00,0x22,0xa3,0x25,0xb0,0x02,0x3c,
-0xbc,0x00,0x03,0x24,0x40,0x00,0x42,0x34,0x00,0x00,0x43,0xa4,0x25,0xb0,0x03,0x3c,
-0x64,0x03,0xb8,0x34,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,0x00,0x00,0x00,0xa3,
-0xd8,0x00,0xa7,0x34,0x00,0x00,0x62,0xa4,0x00,0x00,0xe3,0x90,0x2a,0xb0,0x04,0x3c,
-0x80,0xff,0x02,0x24,0x26,0xb0,0x06,0x3c,0x25,0x18,0x62,0x00,0x30,0x00,0x89,0x34,
-0x20,0x20,0x02,0x24,0x38,0x00,0x84,0x34,0x00,0x00,0xe3,0xa0,0x79,0x00,0xc8,0x34,
-0x00,0x00,0x82,0xa4,0x40,0x00,0x03,0x24,0x16,0x00,0x02,0x24,0x00,0x00,0x23,0xa1,
-0x94,0x00,0xaa,0x34,0x00,0x00,0x02,0xa1,0x98,0x00,0xab,0x34,0x64,0x00,0x03,0x24,
-0x22,0x00,0x02,0x24,0x00,0x00,0x43,0xa5,0x7c,0x00,0xd1,0x34,0x00,0x00,0x62,0xa5,
-0x04,0x00,0x12,0x24,0x9c,0x00,0xac,0x34,0x7a,0x00,0xc6,0x34,0x20,0x0c,0x02,0x24,
-0x0a,0x00,0x03,0x24,0x00,0x00,0xd2,0xa0,0x9a,0x00,0xad,0x34,0x00,0x00,0x22,0xa6,
-0x96,0x00,0xae,0x34,0x00,0x00,0x83,0xa1,0xff,0x03,0x02,0x24,0x02,0x00,0x03,0x24,
-0x00,0x00,0xa2,0xa5,0x00,0x00,0xc3,0xa5,0x25,0xb0,0x03,0x3c,0x20,0x00,0x02,0x24,
-0xb7,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,0x25,0xb0,0x02,0x3c,0x09,0x00,0x03,0x24,
-0x89,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x44,0x00,0xa5,0x34,0x00,0x00,0xa2,0x94,
-0x02,0x80,0x03,0x3c,0x68,0x15,0x66,0x24,0xff,0xfd,0x03,0x24,0x24,0x10,0x43,0x00,
-0x00,0x00,0xa2,0xa4,0x00,0x00,0xa3,0x94,0xd5,0x4a,0xc4,0x90,0x29,0xb0,0x02,0x3c,
-0x40,0x00,0x42,0x34,0x00,0x02,0x63,0x34,0x00,0x00,0xa3,0xa4,0x00,0x00,0x52,0xa0,
-0xd3,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,
-0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,
-0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,
-0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x54,0x00,0x85,0x34,
-0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24,0x00,0x00,0x82,0xac,
-0x00,0x00,0xa3,0xa4,0xf9,0x58,0x00,0x08,0x02,0x80,0x03,0x3c,0x00,0xf0,0x51,0x34,
-0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0xad,0x59,0x00,0x08,0xff,0xff,0x0e,0x24,
-0x8b,0x59,0x00,0x08,0x1b,0x1b,0x42,0x34,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x08,0x3c,
-0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,0x02,0x80,0x04,0x3c,0x00,0x00,0x62,0xa4,
-0x14,0x80,0x84,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,0x00,0x00,0x83,0x94,
-0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,0x0a,0x00,0x47,0x10,
-0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac,
-0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,0x00,0x00,0xc2,0xac,
-0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,0x01,0x80,0x02,0x3c,
-0x0c,0x7a,0x44,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,0x00,0x00,0x83,0x94,
-0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,0x0a,0x00,0x47,0x10,
-0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac,
-0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,0x00,0x00,0xc2,0xac,
-0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x01,0x80,0x02,0x3c,0x02,0x80,0x05,0x3c,0x10,0x6b,0x42,0x24,0x02,0x80,0x03,0x3c,
-0xcc,0x7d,0xa2,0xac,0x00,0x80,0x02,0x3c,0x6c,0x7e,0x60,0xac,0xcc,0x7d,0xa4,0x24,
-0x02,0x80,0x03,0x3c,0xc8,0x06,0x42,0x24,0x70,0x7e,0x60,0xa4,0x08,0x00,0x82,0xac,
-0x02,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x72,0x7e,0x60,0xa4,0x02,0x80,0x06,0x3c,
-0x08,0x0a,0x42,0x24,0x00,0x80,0x03,0x3c,0x74,0x7e,0xc7,0x24,0x14,0x00,0x82,0xac,
-0x38,0x08,0x63,0x24,0x02,0x80,0x02,0x3c,0x74,0x7e,0xc0,0xac,0x10,0x00,0x83,0xac,
-0x04,0x00,0xe0,0xac,0x7c,0x7e,0x40,0xa0,0x00,0x80,0x02,0x3c,0x88,0x19,0x42,0x24,
-0x3c,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x24,0x0c,0x63,0x24,
-0x78,0x0f,0x42,0x24,0x1c,0x00,0x83,0xac,0x20,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,
-0x00,0x80,0x02,0x3c,0xc8,0x12,0x63,0x24,0x28,0x16,0x42,0x24,0x24,0x00,0x83,0xac,
-0x28,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,0x01,0x80,0x02,0x3c,0x4c,0x1f,0x63,0x24,
-0xd0,0x04,0x42,0x24,0x2c,0x00,0x83,0xac,0x30,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,
-0x00,0x80,0x02,0x3c,0xe4,0x19,0x63,0x24,0x00,0x03,0x42,0x24,0x38,0x00,0x83,0xac,
-0x08,0x00,0xe0,0x03,0x4c,0x00,0x82,0xac,0x25,0xb0,0x02,0x3c,0x08,0x00,0x42,0x34,
-0x00,0x00,0x43,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x0e,0x3c,
-0x02,0x80,0x08,0x3c,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xf8,0x03,0x4d,0x24,
-0x00,0x14,0x6c,0x24,0x01,0x00,0x07,0x24,0x00,0x00,0xcb,0x25,0xff,0xff,0x0a,0x24,
-0x00,0x04,0x09,0x25,0x80,0x1a,0x07,0x00,0x21,0x10,0x6b,0x00,0x00,0x00,0x42,0xac,
-0x90,0x00,0x4a,0xac,0x00,0x04,0x04,0x8d,0x01,0x00,0xe7,0x24,0x08,0x00,0x45,0x24,
-0x21,0x18,0x6d,0x00,0x05,0x00,0xe6,0x28,0x04,0x00,0x82,0xac,0x00,0x00,0x44,0xac,
-0x04,0x00,0x49,0xac,0x00,0x04,0x02,0xad,0x8c,0x00,0x40,0xac,0x6c,0x00,0xa3,0xac,
-0xf0,0xff,0xc0,0x14,0x68,0x00,0xac,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0xc9,0xad,
-0x05,0x00,0xa2,0x2c,0x13,0x00,0x40,0x10,0xff,0xff,0x07,0x24,0x02,0x80,0x02,0x3c,
-0x80,0x1a,0x05,0x00,0x00,0x00,0x42,0x24,0x0e,0x00,0xa0,0x10,0x21,0x30,0x62,0x00,
-0x90,0x00,0xc3,0x8c,0xff,0xff,0x02,0x24,0x0a,0x00,0x62,0x14,0x00,0x00,0x00,0x00,
-0x8c,0x00,0xc2,0x8c,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
-0x01,0x00,0x02,0x24,0x88,0x00,0xc4,0xac,0x8c,0x00,0xc2,0xac,0x90,0x00,0xc5,0xac,
-0x21,0x38,0xa0,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,0x25,0xb0,0x04,0x3c,
-0x01,0x80,0x02,0x3c,0x18,0x03,0x85,0x34,0xf4,0x6b,0x42,0x24,0xe0,0xff,0xbd,0x27,
-0x00,0x00,0xa2,0xac,0x1b,0x00,0x86,0x34,0xdb,0xff,0x03,0x24,0x27,0x00,0x84,0x34,
-0x07,0x00,0x02,0x24,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x83,0xa0,
-0x18,0x00,0xbf,0xaf,0x00,0x00,0xc2,0xa0,0x01,0x00,0x11,0x24,0x21,0x80,0x00,0x00,
-0x7a,0x42,0x00,0x0c,0x21,0x20,0x00,0x02,0x01,0x00,0x02,0x26,0xff,0x00,0x50,0x30,
-0x2b,0x18,0x30,0x02,0xfa,0xff,0x60,0x10,0x00,0x00,0x00,0x00,0x7a,0x42,0x00,0x0c,
-0x21,0x20,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
-0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x42,0x24,0x40,0x10,0x03,0x3c,0xff,0xff,0x44,0x30,0x25,0xc0,0x83,0x00,
-0x94,0x64,0x58,0xac,0x40,0x00,0x18,0x27,0xa0,0x64,0x58,0xac,0x40,0x00,0x18,0x27,
-0xac,0x64,0x58,0xac,0x40,0x00,0x18,0x27,0xb8,0x64,0x58,0xac,0x40,0x00,0x18,0x27,
-0xe0,0xff,0xbd,0x27,0xc4,0x64,0x58,0xac,0x40,0x00,0x18,0x27,0x1c,0x00,0xb7,0xaf,
-0x18,0x00,0xb6,0xaf,0x14,0x00,0xb5,0xaf,0x10,0x00,0xb4,0xaf,0x0c,0x00,0xb3,0xaf,
-0x08,0x00,0xb2,0xaf,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0xd0,0x64,0x58,0xac,
-0xa0,0x64,0x45,0x8c,0xac,0x64,0x46,0x8c,0xb8,0x64,0x47,0x8c,0xc4,0x64,0x48,0x8c,
-0xd0,0x64,0x49,0x8c,0x40,0x00,0x18,0x27,0xdc,0x64,0x58,0xac,0x21,0x50,0x00,0x03,
-0x25,0x20,0x83,0x00,0x40,0x00,0x18,0x27,0x20,0x10,0x03,0x3c,0x90,0x64,0x44,0xac,
-0x9c,0x64,0x45,0xac,0xa8,0x64,0x46,0xac,0xb4,0x64,0x47,0xac,0xc0,0x64,0x48,0xac,
-0xcc,0x64,0x49,0xac,0x25,0xb0,0x06,0x3c,0x28,0x64,0x43,0xac,0x24,0x64,0x43,0xac,
-0x34,0x64,0x43,0xac,0x30,0x64,0x43,0xac,0x40,0x64,0x43,0xac,0x3c,0x64,0x43,0xac,
-0x4c,0x64,0x43,0xac,0x48,0x64,0x43,0xac,0xe8,0x64,0x58,0xac,0x00,0x02,0x18,0x27,
-0xd8,0x64,0x4a,0xac,0x00,0x65,0x58,0xac,0x58,0x64,0x43,0xac,0x54,0x64,0x43,0xac,
-0x64,0x64,0x43,0xac,0x60,0x64,0x43,0xac,0x70,0x64,0x43,0xac,0x6c,0x64,0x43,0xac,
-0xac,0x00,0xc4,0x34,0xb0,0x00,0xc5,0x34,0x00,0x00,0x92,0x8c,0xe8,0x64,0x50,0x8c,
-0x00,0x00,0xb3,0x8c,0x21,0x10,0x04,0x3c,0x23,0x10,0x09,0x3c,0x22,0x10,0x0c,0x3c,
-0x02,0x80,0x14,0x3c,0x02,0x80,0x15,0x3c,0x02,0x80,0x16,0x3c,0x02,0x80,0x17,0x3c,
-0x24,0x10,0x05,0x3c,0x21,0x88,0x00,0x03,0x08,0x7b,0x87,0x26,0x00,0x04,0x18,0x27,
-0x10,0x7b,0xa8,0x26,0x18,0x7b,0xca,0x26,0x20,0x7b,0xeb,0x26,0x00,0x04,0x2d,0x35,
-0x00,0x40,0x8e,0x34,0x00,0x80,0x8f,0x35,0x00,0x01,0xc6,0x34,0xe4,0x64,0x50,0xac,
-0xfc,0x64,0x51,0xac,0x64,0x65,0x4d,0xac,0x28,0x65,0x52,0xac,0x34,0x65,0x4e,0xac,
-0x58,0x65,0x4f,0xac,0x4c,0x65,0x53,0xac,0x00,0x00,0xc5,0xac,0x48,0x65,0x45,0xac,
-0x68,0x65,0x43,0xac,0x74,0x65,0x58,0xac,0x7c,0x64,0x43,0xac,0x78,0x64,0x43,0xac,
-0x06,0x65,0x40,0xa4,0x05,0x65,0x40,0xa0,0x04,0x65,0x40,0xa0,0x5c,0x65,0x49,0xac,
-0x60,0x65,0x49,0xac,0x20,0x65,0x44,0xac,0x24,0x65,0x44,0xac,0x2c,0x65,0x44,0xac,
-0x30,0x65,0x44,0xac,0x50,0x65,0x4c,0xac,0x54,0x65,0x4c,0xac,0x44,0x65,0x45,0xac,
-0x6c,0x65,0x43,0xac,0x78,0x65,0x58,0xac,0x04,0x00,0x08,0xad,0x08,0x7b,0x87,0xae,
-0x04,0x00,0x4a,0xad,0x10,0x7b,0xa8,0xae,0x04,0x00,0x6b,0xad,0x18,0x7b,0xca,0xae,
-0x20,0x7b,0xeb,0xae,0x04,0x00,0xe7,0xac,0x02,0x80,0x02,0x3c,0x00,0x14,0x43,0x24,
-0x21,0x20,0xe0,0x00,0x03,0x00,0x06,0x24,0x21,0x10,0x80,0x00,0xff,0xff,0xc6,0x24,
-0x08,0x00,0x78,0xac,0x00,0x00,0x63,0xac,0x10,0x00,0x60,0xac,0x00,0x00,0x67,0xac,
-0x21,0x20,0x60,0x00,0x04,0x00,0x62,0xac,0x00,0x00,0x43,0xac,0x00,0x01,0x18,0x27,
-0xf5,0xff,0xc1,0x04,0x18,0x00,0x63,0x24,0x02,0x80,0x02,0x3c,0x10,0x7b,0x49,0x24,
-0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x00,0x28,0x8d,0x60,0x14,0x4b,0x24,
-0x04,0x00,0xe4,0xac,0x00,0x14,0x6a,0x24,0x01,0x00,0x07,0x24,0x21,0x28,0x00,0x00,
-0x07,0x00,0x06,0x24,0x21,0x20,0xab,0x00,0x21,0x10,0xaa,0x00,0xff,0xff,0xc6,0x24,
-0x68,0x00,0x58,0xac,0x70,0x00,0x47,0xac,0x18,0x00,0xa5,0x24,0x00,0x00,0x89,0xac,
-0x04,0x00,0x88,0xac,0x00,0x00,0x04,0xad,0x00,0x01,0x18,0x27,0xf5,0xff,0xc1,0x04,
-0x21,0x40,0x80,0x00,0x02,0x80,0x02,0x3c,0x18,0x7b,0x4a,0x24,0x02,0x80,0x03,0x3c,
-0x02,0x80,0x02,0x3c,0x04,0x00,0x45,0x8d,0x20,0x15,0x4b,0x24,0x04,0x00,0x24,0xad,
-0x02,0x00,0x07,0x24,0x00,0x14,0x69,0x24,0x21,0x20,0x00,0x00,0x01,0x00,0x06,0x24,
-0x21,0x40,0x8b,0x00,0x21,0x10,0x89,0x00,0xff,0xff,0xc6,0x24,0x28,0x01,0x58,0xac,
-0x30,0x01,0x47,0xac,0x18,0x00,0x84,0x24,0x00,0x00,0x0a,0xad,0x04,0x00,0x05,0xad,
-0x00,0x00,0xa8,0xac,0x00,0x02,0x18,0x27,0xf5,0xff,0xc1,0x04,0x21,0x28,0x00,0x01,
-0x02,0x80,0x05,0x3c,0x20,0x7b,0xa5,0x24,0x04,0x00,0xa6,0x8c,0x1c,0x00,0xb7,0x8f,
-0x18,0x00,0xb6,0x8f,0x14,0x00,0xb5,0x8f,0x10,0x00,0xb4,0x8f,0x0c,0x00,0xb3,0x8f,
-0x08,0x00,0xb2,0x8f,0x04,0x00,0xb1,0x8f,0x00,0x00,0xb0,0x8f,0x02,0x80,0x07,0x3c,
-0x02,0x80,0x03,0x3c,0x50,0x15,0xe4,0x24,0x00,0x14,0x63,0x24,0x03,0x00,0x02,0x24,
-0x20,0x00,0xbd,0x27,0x58,0x01,0x78,0xac,0x04,0x00,0x48,0xad,0x04,0x00,0xa4,0xac,
-0x60,0x01,0x62,0xac,0x50,0x15,0xe5,0xac,0x04,0x00,0x86,0xac,0x08,0x00,0xe0,0x03,
-0x00,0x00,0xc4,0xac,0xd0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x20,0x00,0xb2,0xaf,
-0x02,0x80,0x03,0x3c,0x4c,0x91,0x52,0x24,0x02,0x80,0x02,0x3c,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x2c,0x00,0xbf,0xaf,
-0xd8,0x90,0x73,0x24,0x68,0x15,0x50,0x24,0x21,0x88,0x00,0x00,0x02,0x80,0x14,0x3c,
-0xee,0x4e,0x00,0x0c,0x21,0x20,0x20,0x02,0x78,0x51,0x05,0x8e,0x6c,0x00,0x66,0x8e,
-0xb8,0x90,0x82,0x26,0x6c,0x00,0x43,0x8e,0x1b,0x00,0x44,0x90,0xff,0xf1,0x02,0x24,
-0x21,0x18,0x66,0x00,0x24,0x28,0xa2,0x00,0x00,0x21,0x04,0x00,0x42,0x18,0x03,0x00,
-0x00,0x02,0xa5,0x34,0x44,0x51,0x03,0xae,0x68,0x51,0x04,0xae,0x78,0x51,0x05,0xae,
-0x6c,0x51,0x04,0xae,0x21,0x30,0x00,0x00,0x21,0x10,0x06,0x02,0x01,0x00,0xc6,0x24,
-0x1d,0x00,0xc3,0x28,0x99,0x51,0x40,0xa0,0x7c,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,
-0xb6,0x51,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xd4,0x51,0x00,0xae,
-0xe3,0xff,0x40,0x14,0x94,0x00,0x10,0x26,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,
-0x68,0x15,0x4b,0x24,0x02,0x80,0x02,0x3c,0x4c,0x91,0x6f,0x24,0xd8,0x90,0x4d,0x24,
-0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb8,0x90,0x6e,0x24,0x98,0x90,0x4c,0x24,
-0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x20,0x6d,0x00,0x21,0x10,0x6f,0x00,
-0x21,0x28,0x2e,0x02,0x21,0x30,0x2c,0x02,0x00,0x00,0x88,0x8c,0x00,0x00,0xa9,0x90,
-0x00,0x00,0xc7,0x90,0x00,0x00,0x4a,0x8c,0x21,0x10,0x2b,0x02,0x01,0x00,0x31,0x26,
-0x21,0x18,0x6b,0x00,0x1d,0x00,0x24,0x2a,0xec,0x44,0x68,0xac,0xca,0x44,0x47,0xa0,
-0x60,0x45,0x6a,0xac,0xef,0xff,0x80,0x14,0x90,0x44,0x49,0xa0,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x74,0x8f,0x6b,0x24,
-0x14,0x8e,0x4c,0x24,0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,
-0x21,0x40,0x2a,0x01,0x21,0x38,0x2b,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,
-0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,
-0xc5,0x43,0x64,0xa0,0xf8,0xff,0x40,0x14,0x34,0x43,0x65,0xa0,0x21,0x10,0x2c,0x02,
-0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,
-0x1d,0x00,0x22,0x2a,0x73,0x44,0x64,0xa0,0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,
-0x05,0x00,0x29,0x25,0x52,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,0x41,0x00,0x03,0x24,
-0x4d,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x1c,0x97,0xe7,0x24,0x11,0x00,0xa3,0xa3,
-0x12,0x00,0xa2,0xa3,0xe8,0x03,0x03,0x24,0x01,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,
-0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xf0,0x37,0xc6,0x24,0x0c,0x00,0xe3,0xac,
-0x14,0x00,0xe2,0xa0,0xfb,0x0c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x2c,0x00,0xbf,0x8f,
-0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
-0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
-0x02,0x80,0x02,0x3c,0x42,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3,0x55,0x60,0x40,0xa0,
-0x4e,0x00,0x03,0x24,0x43,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x54,0x97,0xe7,0x24,
-0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,
-0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xdc,0x44,0xc6,0x24,
-0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,
-0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0x48,0xfd,0xbd,0x27,0xb4,0x02,0xb3,0xaf,0x02,0x80,0x02,0x3c,
-0x02,0x80,0x13,0x3c,0x24,0x92,0x46,0x24,0x68,0x15,0x63,0x26,0xb0,0x02,0xb2,0xaf,
-0xac,0x02,0xb1,0xaf,0xa8,0x02,0xb0,0xaf,0x03,0x40,0x60,0xa0,0x21,0x38,0xa0,0x03,
-0x90,0x00,0xc8,0x24,0x00,0x00,0xc2,0x8c,0x04,0x00,0xc3,0x8c,0x08,0x00,0xc4,0x8c,
-0x0c,0x00,0xc5,0x8c,0x10,0x00,0xc6,0x24,0x00,0x00,0xe2,0xac,0x04,0x00,0xe3,0xac,
-0x08,0x00,0xe4,0xac,0x0c,0x00,0xe5,0xac,0xf6,0xff,0xc8,0x14,0x10,0x00,0xe7,0x24,
-0x00,0x00,0xc3,0x8c,0x02,0x80,0x02,0x3c,0xb8,0x92,0x58,0x24,0x00,0x00,0xe3,0xac,
-0x98,0x00,0xb9,0x27,0x00,0x01,0x12,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,
-0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,
-0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,
-0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,
-0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,
-0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,
-0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,
-0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,
-0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,
-0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,
-0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,
-0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,
-0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,
-0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,
-0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,
-0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,
-0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,0x02,0x80,0x02,0x3c,
-0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0xc0,0x93,0x58,0x24,0x04,0x00,0x26,0xaf,
-0x00,0x00,0x27,0xaf,0x00,0x01,0x12,0x27,0xa0,0x01,0xb9,0x27,0x01,0x00,0x02,0x93,
-0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,
-0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,
-0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,
-0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,
-0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,
-0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,
-0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,
-0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,
-0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,
-0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,
-0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,
-0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,
-0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,
-0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,
-0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,
-0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,
-0x25,0x30,0xc5,0x00,0x25,0x38,0xe4,0x00,0x02,0x80,0x02,0x3c,0x04,0x00,0x26,0xaf,
-0x00,0x00,0x27,0xaf,0x68,0x15,0x46,0x24,0x21,0x50,0x00,0x00,0x80,0x20,0x0a,0x00,
-0x21,0x10,0x9d,0x00,0x00,0x00,0x45,0x8c,0x01,0x00,0x43,0x25,0xff,0x00,0x6a,0x30,
-0x21,0x20,0x86,0x00,0x25,0x00,0x42,0x2d,0xf8,0xff,0x40,0x14,0x18,0x40,0x85,0xac,
-0x02,0x80,0x02,0x3c,0x68,0x15,0x4b,0x24,0x21,0x50,0x00,0x00,0xc0,0x10,0x0a,0x00,
-0x21,0x48,0x5d,0x00,0x21,0x38,0x00,0x00,0x21,0x40,0x4b,0x00,0x21,0x10,0x27,0x01,
-0xa0,0x01,0x46,0x90,0x98,0x00,0x45,0x90,0x01,0x00,0xe4,0x24,0x21,0x18,0x07,0x01,
-0xff,0x00,0x87,0x30,0x08,0x00,0xe2,0x2c,0xb4,0x41,0x66,0xa0,0xf7,0xff,0x40,0x14,
-0xac,0x40,0x65,0xa0,0x01,0x00,0x42,0x25,0xff,0x00,0x4a,0x30,0x21,0x00,0x43,0x2d,
-0xef,0xff,0x60,0x14,0xc0,0x10,0x0a,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,
-0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x63,0x30,0x42,0x00,0x60,0x10,
-0x68,0x15,0x64,0x26,0x33,0x00,0x02,0x24,0xc1,0x42,0x62,0xa1,0x1c,0x00,0x03,0x24,
-0x0f,0x00,0x02,0x24,0xbc,0x42,0x63,0xa1,0xbd,0x42,0x62,0xa1,0x68,0x15,0x65,0x26,
-0x08,0x40,0xa4,0x8c,0xff,0x7f,0x08,0x3c,0xff,0xff,0x08,0x35,0xc0,0xff,0x02,0x24,
-0x24,0x20,0x88,0x00,0x24,0x20,0x82,0x00,0x0c,0x00,0x84,0x34,0xff,0xc0,0x02,0x24,
-0x24,0x20,0x82,0x00,0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x00,0x18,0x84,0x34,
-0xbf,0xff,0x03,0x3c,0x24,0x20,0x82,0x00,0xff,0xff,0x63,0x34,0x7f,0xff,0x02,0x3c,
-0x24,0x20,0x83,0x00,0xff,0xff,0x42,0x34,0x24,0x20,0x82,0x00,0x0c,0x40,0xa6,0x8c,
-0x7f,0xff,0x03,0x24,0x40,0x40,0x84,0x34,0xff,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,
-0xff,0x7f,0x42,0x34,0xff,0xbf,0x03,0x3c,0x10,0x40,0xa7,0x8c,0x24,0x20,0x82,0x00,
-0xff,0xff,0x63,0x34,0xff,0x9f,0x02,0x3c,0x24,0x30,0xc3,0x00,0xff,0xff,0x42,0x34,
-0xff,0x3f,0x03,0x3c,0x24,0x20,0x82,0x00,0xff,0xff,0x63,0x34,0x12,0x00,0x02,0x24,
-0xb4,0x02,0xb3,0x8f,0xb0,0x02,0xb2,0x8f,0xac,0x02,0xb1,0x8f,0xa8,0x02,0xb0,0x8f,
-0x24,0x38,0xe3,0x00,0xc7,0x42,0xa2,0xa0,0x1f,0x00,0x03,0x24,0x01,0x00,0x02,0x24,
-0x24,0x30,0xc8,0x00,0xbe,0x42,0xa3,0xa0,0xc0,0x42,0xa2,0xa0,0xff,0x00,0x03,0x24,
-0xff,0xff,0x02,0x24,0xb8,0x02,0xbd,0x27,0x08,0x40,0xa4,0xac,0x10,0x40,0xa7,0xac,
-0x0c,0x40,0xa6,0xac,0xc2,0x42,0xa2,0xa0,0xc4,0x42,0xa3,0xa4,0xbf,0x42,0xa0,0xa0,
-0x08,0x00,0xe0,0x03,0xc6,0x42,0xa0,0xa0,0x33,0x00,0x02,0x24,0xc1,0x42,0x82,0xa0,
-0x0d,0x00,0x03,0x24,0x03,0x00,0x02,0x24,0xbc,0x42,0x83,0xa0,0x65,0x5d,0x00,0x08,
-0xbd,0x42,0x82,0xa0,0xe0,0xff,0xbd,0x27,0x02,0x80,0x07,0x3c,0x68,0x15,0xe7,0x24,
-0x18,0x00,0xbf,0xaf,0x00,0x40,0xe3,0x8c,0xf0,0xff,0x02,0x24,0x02,0x80,0x08,0x3c,
-0x24,0x18,0x62,0x00,0xff,0xf0,0x02,0x24,0x24,0x18,0x62,0x00,0x00,0x40,0xe3,0xac,
-0x1c,0x00,0x03,0x24,0x36,0x00,0x02,0x24,0xcf,0x42,0xe3,0xa0,0x20,0x00,0x03,0x24,
-0xce,0x42,0xe2,0xa0,0xd1,0x42,0xe3,0xa0,0x32,0x00,0x02,0x24,0x20,0x00,0x03,0x24,
-0xd0,0x42,0xe2,0xa0,0xc8,0x42,0xe3,0xa4,0x0a,0x00,0x02,0x24,0x00,0x02,0x03,0x24,
-0xd2,0x42,0xe2,0xa0,0xcc,0x42,0xe3,0xa4,0x00,0x01,0x02,0x24,0x49,0x00,0x03,0x24,
-0x38,0x97,0x08,0x25,0xff,0xff,0x0a,0x34,0x01,0x00,0x09,0x24,0x11,0x00,0xa3,0xa3,
-0xca,0x42,0xe2,0xa4,0xd0,0x07,0x03,0x24,0x44,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,
-0x10,0x00,0xa2,0xa3,0x10,0x00,0xa5,0x27,0x47,0x00,0x02,0x24,0x21,0x20,0x00,0x01,
-0x54,0x45,0xc6,0x24,0x04,0x40,0xea,0xac,0x02,0x40,0xe9,0xa0,0x0c,0x00,0x03,0xad,
-0x14,0x00,0x09,0xa1,0xe6,0x42,0xe0,0xa0,0xdc,0x63,0xea,0xac,0xd7,0x42,0xe0,0xa0,
-0x12,0x00,0xa2,0xa3,0xfb,0x0c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
-0x02,0x80,0x02,0x3c,0x50,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3,0x2a,0x62,0x40,0xa0,
-0x41,0x00,0x03,0x24,0x52,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0xc4,0x97,0xe7,0x24,
-0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,
-0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0x88,0x5b,0xc6,0x24,
-0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,
-0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0xd8,0xff,0xbd,0x27,0x18,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c,
-0x68,0x15,0x10,0x26,0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb1,0xaf,0x00,0x40,0x09,0x8e,
-0xff,0xff,0x02,0x24,0xff,0x00,0x4b,0x30,0x0f,0xff,0x02,0x24,0x24,0x48,0x22,0x01,
-0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,0x24,0x48,0x22,0x01,0x01,0x00,0x07,0x3c,
-0x47,0x00,0x02,0x24,0x3b,0x00,0x03,0x24,0x02,0x80,0x08,0x3c,0x10,0x00,0xa2,0xa3,
-0x11,0x00,0xa3,0xa3,0xe0,0x97,0x08,0x25,0x56,0x30,0xea,0x34,0xd0,0x07,0x02,0x24,
-0x01,0x00,0x03,0x24,0xf4,0x98,0xe7,0x34,0x00,0x80,0x06,0x3c,0x04,0x43,0x0b,0xae,
-0x00,0x40,0x09,0xae,0x43,0x00,0x11,0x24,0x10,0x00,0xa5,0x27,0x0c,0x43,0x07,0xae,
-0x10,0x43,0x0a,0xae,0x0c,0x00,0x02,0xad,0x14,0x00,0x03,0xa1,0x08,0x43,0x00,0xae,
-0x14,0x43,0x00,0xae,0x18,0x43,0x00,0xae,0x21,0x20,0x00,0x01,0xe4,0x4e,0xc6,0x24,
-0x12,0x00,0xb1,0xa3,0xfb,0x0c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x1e,0x00,0x02,0x24,
-0x21,0x43,0x02,0xa2,0x4a,0x00,0x03,0x24,0x45,0x00,0x02,0x24,0x1c,0x43,0x03,0xa2,
-0x1d,0x43,0x02,0xa2,0x23,0x00,0x03,0x24,0x3e,0x00,0x02,0x24,0x1e,0x43,0x11,0xa2,
-0x1f,0x43,0x02,0xa2,0x20,0x43,0x03,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb1,0x8f,
-0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
-0x3b,0x00,0x02,0x24,0x43,0x00,0x03,0x24,0x10,0x00,0xa2,0xa3,0x11,0x00,0xa3,0xa3,
-0x36,0x00,0x02,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x07,0x3c,0xfc,0x97,0xe7,0x24,
-0x12,0x00,0xa2,0xa3,0x3b,0x58,0x60,0xa0,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,
-0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0x20,0x53,0xc6,0x24,
-0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,
-0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0xff,0xff,0x07,0x24,0x02,0x80,0x02,0x3c,0xe0,0xff,0xbd,0x27,
-0x3d,0x58,0x47,0xa0,0x3b,0x00,0x03,0x24,0x43,0x00,0x02,0x24,0x10,0x00,0xa3,0xa3,
-0x11,0x00,0xa2,0xa3,0x36,0x00,0x03,0x24,0x16,0x00,0x02,0x24,0x02,0x80,0x08,0x3c,
-0x18,0x98,0x08,0x25,0x12,0x00,0xa3,0xa3,0x13,0x00,0xa2,0xa3,0xd0,0x07,0x03,0x24,
-0x01,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0x00,0x01,
-0x0c,0x00,0x03,0xad,0x14,0x00,0x02,0xa1,0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,
-0xb8,0x54,0xc6,0x24,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x52,0x00,0x03,0x24,
-0x10,0x00,0xa3,0xa3,0x4c,0x79,0x40,0xa4,0x54,0x00,0x03,0x24,0x53,0x00,0x02,0x24,
-0x02,0x80,0x07,0x3c,0x34,0x98,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,
-0xf4,0x01,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,
-0x21,0x20,0xe0,0x00,0xc8,0x5c,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,
-0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x78,0x0c,0x00,0x00,0x01,0x00,0x00,0x5e,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x01,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x02,0x5e,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x03,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x04,0x5d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x05,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x06,0x59,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x07,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x08,0x55,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x09,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x0a,0x51,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x0b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x0c,0x4d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x0d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x0e,0x49,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x0f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x10,0x45,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x11,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x12,0x41,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x13,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x14,0x3d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x15,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x16,0x39,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x17,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x18,0x35,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x19,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x1a,0x31,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x1b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x1c,0x2d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x1d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x1e,0x29,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x1f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x20,0x25,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x21,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x22,0x21,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x23,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x24,0x1d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x25,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x26,0x19,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x27,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x28,0x15,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x29,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x2a,0x11,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x2b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x2c,0x0d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x2d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x2e,0x09,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x2f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x30,0x05,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x31,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x32,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x33,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x34,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x35,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x36,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x37,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x38,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x39,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3a,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x3b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3c,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x3d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3e,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x3f,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x40,0x5e,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x41,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x42,0x5e,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x43,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x44,0x5d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x45,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x46,0x59,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x47,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x48,0x55,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x49,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x4a,0x51,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x4b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x4c,0x4d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x4d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x4e,0x49,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x4f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x50,0x45,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x51,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x52,0x41,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x53,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x54,0x3d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x55,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x56,0x39,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x57,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x58,0x35,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x59,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x5a,0x31,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x5b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x5c,0x2d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x5d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x5e,0x29,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x5f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x60,0x25,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x61,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x62,0x21,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x63,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x64,0x1d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x65,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x66,0x19,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x67,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x68,0x15,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x69,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x6a,0x11,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x6b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x6c,0x0d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x6d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x6e,0x09,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x6f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x70,0x05,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x71,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x72,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x73,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x74,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x75,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x76,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x77,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x78,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x79,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7a,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x7b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7c,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x7d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7e,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x7f,0x01,0x78,0x0c,0x00,0x00,0x1e,0x00,0x00,0x30,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x01,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x02,0x30,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x03,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x04,0x30,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x05,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x06,0x30,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x07,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x08,0x3e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x09,0x40,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0a,0x42,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x0b,0x44,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0c,0x46,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x0d,0x48,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0e,0x48,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x0f,0x4a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x10,0x4a,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x11,0x4c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x12,0x4c,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x13,0x4e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x14,0x50,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x15,0x50,0x78,0x0c,0x00,0x00,0x1e,0x00,0x16,0x50,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x17,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x18,0x52,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x19,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1a,0x54,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x1b,0x54,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1c,0x54,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x1d,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1e,0x56,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x1f,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x20,0x56,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x21,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x22,0x58,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x23,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x24,0x58,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x25,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x26,0x5a,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x27,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x28,0x5c,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x29,0x5c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2a,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x2b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2c,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x2d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2e,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x2f,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x30,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x31,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x32,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x33,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x34,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x35,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x36,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x37,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x38,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x39,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3a,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x3b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3c,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x3d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3e,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x3f,0x5e,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x08,0x00,0x00,
-0x00,0x00,0x04,0x03,0x04,0x08,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x08,0x00,0x00,
-0x00,0xfc,0x00,0x00,0x0c,0x08,0x00,0x00,0x0a,0x00,0x00,0x04,0x10,0x08,0x00,0x00,
-0xff,0x10,0x10,0x80,0x14,0x08,0x00,0x00,0x10,0x3d,0x0c,0x02,0x18,0x08,0x00,0x00,
-0xc5,0x03,0x00,0x00,0x1c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x00,
-0x04,0x00,0x00,0x00,0x24,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x28,0x08,0x00,0x00,
-0x04,0x00,0x00,0x00,0x2c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x30,0x08,0x00,0x00,
-0x04,0x00,0x00,0x00,0x34,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x38,0x08,0x00,0x00,
-0x04,0x00,0x00,0x00,0x3c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x40,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x44,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x4c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x54,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x08,0x00,0x00,
-0x65,0xa9,0x65,0xa9,0x5c,0x08,0x00,0x00,0x65,0xa9,0x65,0xa9,0x60,0x08,0x00,0x00,
-0x30,0x01,0x7f,0x0f,0x64,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x68,0x08,0x00,0x00,
-0x30,0x01,0x7f,0x0f,0x6c,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x70,0x08,0x00,0x00,
-0x00,0x03,0x00,0x03,0x74,0x08,0x00,0x00,0x00,0x03,0x00,0x03,0x78,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x7c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x94,0x08,0x00,0x00,0xfe,0xff,0xff,0xff,0x98,0x08,0x00,0x00,
-0x10,0x20,0x30,0x40,0x9c,0x08,0x00,0x00,0x50,0x60,0x70,0x00,0xb0,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0xe0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x04,0x0e,0x00,0x00,
-0x03,0x03,0x03,0x03,0x08,0x0e,0x00,0x00,0x03,0x03,0x00,0x00,0x0c,0x0e,0x00,0x00,
-0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x14,0x0e,0x00,0x00,
-0x03,0x03,0x03,0x03,0x18,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x1c,0x0e,0x00,0x00,
-0x03,0x03,0x03,0x03,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x09,0x00,0x00,
-0x23,0x00,0x00,0x00,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x09,0x00,0x00,
-0x33,0x13,0x32,0x03,0x08,0x0a,0x00,0x00,0x00,0x86,0x88,0x8f,0x2c,0x0a,0x00,0x00,
-0x00,0x00,0x92,0x00,0x00,0x0c,0x00,0x00,0x80,0x00,0x00,0x00,0x04,0x0c,0x00,0x00,
-0x33,0x54,0x00,0x00,0x08,0x0c,0x00,0x00,0xe4,0x00,0x00,0x00,0x0c,0x0c,0x00,0x00,
-0x6c,0x6c,0x6c,0x6c,0x10,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x0c,0x00,0x00,
-0x00,0x01,0x00,0x40,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x0c,0x00,0x00,
-0x00,0x01,0x00,0x40,0x20,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x24,0x0c,0x00,0x00,
-0x00,0x01,0x00,0x40,0x28,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x2c,0x0c,0x00,0x00,
-0x00,0x01,0x00,0x40,0x30,0x0c,0x00,0x00,0x44,0x6a,0xe9,0x8d,0x34,0x0c,0x00,0x00,
-0xcd,0x52,0x96,0x46,0x38,0x0c,0x00,0x00,0x90,0x5a,0x01,0x48,0x3c,0x0c,0x00,0x00,
-0x64,0x97,0x97,0x1a,0x40,0x0c,0x00,0x00,0x3f,0x42,0x7c,0x1f,0x44,0x0c,0x00,0x00,
-0xb7,0x00,0x01,0x00,0x48,0x0c,0x00,0x00,0x00,0x00,0x02,0xec,0x4c,0x0c,0x00,0x00,
-0x03,0x03,0xfc,0x00,0x50,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x54,0x0c,0x00,0x00,
-0x94,0x00,0x3c,0x43,0x58,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x5c,0x0c,0x00,0x00,
-0x94,0x00,0x3c,0x43,0x60,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x64,0x0c,0x00,0x00,
-0x94,0x00,0x3c,0x43,0x68,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x6c,0x0c,0x00,0x00,
-0x94,0x00,0x3c,0x43,0x70,0x0c,0x00,0x00,0x0d,0x00,0x5a,0x2c,0x74,0x0c,0x00,0x00,
-0x1b,0x15,0x86,0x01,0x78,0x0c,0x00,0x00,0x1f,0x00,0x00,0x00,0x7c,0x0c,0x00,0x00,
-0x12,0x16,0xb9,0x00,0x80,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x84,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0x88,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x8c,0x0c,0x00,0x00,
-0x00,0x00,0x20,0x08,0x90,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x94,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0x98,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x9c,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xa0,0x0c,0x00,0x00,0x92,0x24,0x49,0x00,0xa4,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xa8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xb0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xb8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x0c,0x00,0x00,
-0x92,0x24,0x49,0x00,0xc0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xc4,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xc8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xcc,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xd0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xd8,0x0c,0x00,0x00,0x27,0x24,0xb2,0x64,0xdc,0x0c,0x00,0x00,
-0x32,0x69,0x76,0x00,0xe0,0x0c,0x00,0x00,0x22,0x22,0x22,0x00,0xe4,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xe8,0x0c,0x00,0x00,0x02,0x43,0x64,0x07,0x00,0x0d,0x00,0x00,
-0x80,0x07,0x00,0x00,0x04,0x0d,0x00,0x00,0x03,0x04,0x00,0x00,0x08,0x0d,0x00,0x00,
-0x7f,0x90,0x00,0x00,0x0c,0x0d,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x0d,0x00,0x00,
-0x99,0x99,0x69,0xa0,0x14,0x0d,0x00,0x00,0x67,0x3c,0x99,0x99,0x18,0x0d,0x00,0x00,
-0x6b,0x5b,0x8f,0x6a,0x1c,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x24,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x2c,0x0d,0x00,0x00,0x75,0x19,0x97,0xcc,0x30,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x34,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x3c,0x0d,0x00,0x00,0x93,0x72,0x02,0x00,0x40,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x44,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x50,0x0d,0x00,0x00,0x0a,0x14,0x37,0x64,0x54,0x0d,0x00,0x00,
-0x02,0xbd,0x4d,0x02,0x58,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x0d,0x00,0x00,
-0x64,0x20,0x03,0x30,0x60,0x0d,0x00,0x00,0x68,0xde,0x53,0x46,0x64,0x0d,0x00,0x00,
-0x3c,0x8a,0x51,0x00,0x68,0x0d,0x00,0x00,0x06,0x01,0x00,0x00,0xff,0x00,0x00,0x00,
-0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
-0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x74,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
-0xe0,0x2e,0x00,0x80,0x10,0x00,0x00,0x00,0xec,0x2e,0x00,0x80,0x10,0x00,0x00,0x00,
-0xa0,0x08,0x01,0x80,0x08,0x00,0x00,0x00,0x38,0x06,0x01,0x80,0x00,0xb7,0x00,0x00,
-0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00,0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,
-0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00,0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,
-0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00,0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,
-0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00,0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,
-0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00,0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,
-0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00,0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,
-0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00,0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,
-0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00,0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,
-0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00,0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,
-0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00,0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,
-0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00,0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,
-0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00,0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,
-0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00,0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,
-0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00,0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,
-0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00,0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,
-0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00,0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,
-0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00,0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,
-0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00,0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,
-0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00,0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,
-0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00,0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,
-0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00,0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,
-0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00,0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,
-0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00,0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,
-0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00,0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,
-0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00,0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,
-0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00,0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,
-0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00,0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,
-0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00,0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,
-0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00,0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,
-0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00,0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,
-0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00,0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,
-0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00,0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,
-0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00,0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,
-0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00,0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,
-0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00,0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,
-0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00,0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,
-0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00,0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,
-0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00,0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,
-0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00,0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,
-0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00,0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,
-0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00,0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,
-0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00,0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,
-0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00,0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,
-0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00,0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,
-0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00,0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,
-0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00,0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,
-0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00,0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,
-0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00,0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,
-0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00,0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,
-0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00,0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,
-0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00,0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,
-0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00,0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,
-0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,
-0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,
-0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xb7,0x00,0x00,
-0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00,0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,
-0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00,0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,
-0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00,0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,
-0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00,0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,
-0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00,0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,
-0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00,0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,
-0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00,0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,
-0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00,0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,
-0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00,0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,
-0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00,0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,
-0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00,0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,
-0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00,0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,
-0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00,0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,
-0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00,0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,
-0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00,0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,
-0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00,0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,
-0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00,0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,
-0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00,0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,
-0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00,0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,
-0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00,0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,
-0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00,0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,
-0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00,0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,
-0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00,0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,
-0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00,0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,
-0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00,0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,
-0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00,0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,
-0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00,0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,
-0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00,0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,
-0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00,0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,
-0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00,0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,
-0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00,0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,
-0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00,0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,
-0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00,0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,
-0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00,0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,
-0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00,0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,
-0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00,0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,
-0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00,0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,
-0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00,0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,
-0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00,0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,
-0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00,0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,
-0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00,0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,
-0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00,0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,
-0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00,0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,
-0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00,0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,
-0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00,0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,
-0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00,0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,
-0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00,0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,
-0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00,0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,
-0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00,0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,
-0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00,0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,
-0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00,0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,
-0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00,0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,
-0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,
-0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,
-0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x0a,0x00,0x00,0x00,
-0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,0x65,0x71,0x00,0x00,0x4f,0x6e,0x41,0x73,
-0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,
-0x63,0x52,0x65,0x71,0x00,0x00,0x00,0x00,0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,
-0x63,0x52,0x73,0x70,0x00,0x00,0x00,0x00,0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52,
-0x65,0x71,0x00,0x00,0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52,0x73,0x70,0x00,0x00,
-0x44,0x6f,0x52,0x65,0x73,0x65,0x72,0x76,0x65,0x64,0x00,0x00,0x44,0x6f,0x52,0x65,
-0x73,0x65,0x72,0x76,0x65,0x64,0x00,0x00,0x4f,0x6e,0x42,0x65,0x61,0x63,0x6f,0x6e,
-0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x54,0x49,0x4d,0x00,0x00,0x4f,0x6e,0x44,0x69,
-0x73,0x61,0x73,0x73,0x6f,0x63,0x00,0x00,0x4f,0x6e,0x41,0x75,0x74,0x68,0x00,0x00,
-0x4f,0x6e,0x44,0x65,0x41,0x75,0x74,0x68,0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x63,
-0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x8b,0x01,0x80,
-0x28,0x14,0x01,0x80,0x10,0x00,0x00,0x00,0x94,0x8b,0x01,0x80,0x30,0x14,0x01,0x80,
-0x20,0x00,0x00,0x00,0xa0,0x8b,0x01,0x80,0x28,0x14,0x01,0x80,0x30,0x00,0x00,0x00,
-0xb0,0x8b,0x01,0x80,0x30,0x14,0x01,0x80,0x40,0x00,0x00,0x00,0xc0,0x8b,0x01,0x80,
-0x38,0x14,0x01,0x80,0x50,0x00,0x00,0x00,0xcc,0x8b,0x01,0x80,0x40,0x14,0x01,0x80,
-0x00,0x00,0x00,0x00,0xd8,0x8b,0x01,0x80,0xa8,0x14,0x01,0x80,0x00,0x00,0x00,0x00,
-0xe4,0x8b,0x01,0x80,0xa8,0x14,0x01,0x80,0x80,0x00,0x00,0x00,0xf0,0x8b,0x01,0x80,
-0x48,0x14,0x01,0x80,0x90,0x00,0x00,0x00,0xfc,0x8b,0x01,0x80,0x50,0x14,0x01,0x80,
-0xa0,0x00,0x00,0x00,0x04,0x8c,0x01,0x80,0x58,0x14,0x01,0x80,0xb0,0x00,0x00,0x00,
-0x10,0x8c,0x01,0x80,0x90,0x14,0x01,0x80,0xc0,0x00,0x00,0x00,0x18,0x8c,0x01,0x80,
-0x98,0x14,0x01,0x80,0xd0,0x00,0x00,0x00,0x24,0x8c,0x01,0x80,0xa0,0x14,0x01,0x80,
-0x00,0x00,0x00,0x00,0xdc,0x8c,0x01,0x80,0xdc,0x8c,0x01,0x80,0x31,0x10,0x10,0x00,
-0x00,0x30,0x00,0x00,0x31,0x20,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x28,0x10,0x00,
-0x00,0x30,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x30,0x00,0x00,0x31,0x2f,0x10,0x10,
-0x00,0x30,0x00,0x00,0x31,0x30,0x18,0x00,0x00,0x30,0x00,0x00,0x31,0x30,0x20,0x10,
-0x00,0x30,0x00,0x00,0x22,0x20,0x18,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x14,0x08,
-0x00,0x20,0x00,0x00,0x22,0x21,0x1c,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x08,
-0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x18,
-0x00,0x20,0x00,0x00,0x1a,0x19,0x18,0x10,0x00,0x18,0x00,0x00,0x12,0x11,0x10,0x08,
-0x00,0x10,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x02,
-0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x06,
-0x00,0x08,0x00,0x00,0x08,0x07,0x06,0x04,0x00,0x06,0x00,0x00,0x06,0x05,0x04,0x02,
-0x00,0x04,0x00,0x00,0x06,0x05,0x04,0x03,0x00,0x04,0x00,0x00,0x05,0x04,0x03,0x02,
-0x00,0x03,0x00,0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,0x05,0x04,0x04,0x03,
-0x06,0x05,0x05,0x04,0x04,0x03,0x03,0x03,0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x02,
-0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,0x05,0x04,0x04,0x03,0x05,0x04,0x04,
-0x03,0x03,0x02,0x02,0x02,0x04,0x03,0x03,0x02,0x02,0x01,0x01,0x01,0x00,0x00,0x00,
-0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08,
-0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x30,0x08,0x08,0x08,
-0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30,
-0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x08,0x08,0x08,0x08,
-0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,
-0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x18,0x18,0x18,
-0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30,0x30,0x08,0x10,0x20,
-0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,
-0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x00,
-0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,
-0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11,0x10,0x08,0x00,0x22,
-0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,
-0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,
-0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x0a,0x09,0x08,0x02,
-0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,
-0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x22,
-0x21,0x1c,0x08,0x00,0x31,0x30,0x18,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,
-0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x1a,0x19,0x18,
-0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,
-0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31,0x2c,0x10,0x10,0x00,
-0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,
-0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x20,
-0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10,0x00,0x0a,0x09,0x08,
-0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,
-0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,
-0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00,0x0a,0x09,0x08,0x04,
-0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,
-0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,
-0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11,
-0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,
-0x04,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,
-0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x21,0x14,0x08,0x00,
-0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,
-0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21,
-0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x0a,0x09,0x08,
-0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,
-0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,
-0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31,
-0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,
-0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,
-0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10,
-0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,
-0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,
-0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00,
-0x01,0x02,0x04,0x08,0x02,0x04,0x08,0x0c,0x10,0x18,0x20,0x30,0x02,0x04,0x08,0x0c,
-0x10,0x18,0x20,0x30,0x06,0x0c,0x10,0x18,0x24,0x30,0x3c,0x48,0x48,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x27,0x2c,0x19,0x1b,0x1e,0x20,
-0x23,0x29,0x2a,0x2b,0x00,0x00,0x00,0x00,0x25,0x29,0x2b,0x2e,0x2e,0x00,0x00,0x00,
-0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
-0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,
-0x60,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,
-0x50,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,
-0x40,0x01,0x00,0x00,0x90,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,0x30,0x02,0x00,0x00,
-0x2c,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,0xd0,0x02,0x00,0x00,
-0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00,0xa0,0x0f,0x00,0x00,
-0xa0,0x0f,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
-0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
-0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x60,0x00,0x00,0x00,
-0x6c,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x50,0x00,0x00,0x00,
-0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,
-0x18,0x01,0x00,0x00,0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,
-0x68,0x01,0x00,0x00,0x40,0x06,0x00,0x00,0x40,0x06,0x00,0x00,0x40,0x06,0x00,0x00,
-0xd0,0x07,0x00,0x00,0xd0,0x07,0x00,0x00,0x2c,0x05,0x00,0x80,0x20,0x05,0x00,0x80,
-0x14,0x05,0x00,0x80,0x08,0x05,0x00,0x80,0xfc,0x04,0x00,0x80,0xf0,0x04,0x00,0x80,
-0xe4,0x04,0x00,0x80,0xd8,0x04,0x00,0x80,0xcc,0x04,0x00,0x80,0xc0,0x04,0x00,0x80,
-0x78,0x04,0x00,0x80,0x68,0x15,0x02,0x80,0xc0,0x3a,0x00,0x80,0xcc,0x3a,0x00,0x80,
-0xd8,0x3a,0x00,0x80,0xe4,0x3a,0x00,0x80,0xc0,0x3a,0x00,0x80,0xc0,0x3a,0x00,0x80,
-0xc0,0x3a,0x00,0x80,0xc0,0x3a,0x00,0x80,0xf0,0x3a,0x00,0x80,0xfc,0x3a,0x00,0x80,
-0x08,0x3b,0x00,0x80,0x14,0x3b,0x00,0x80,0x68,0x15,0x02,0x80,0xfe,0x01,0x80,0x7f,
-0xe2,0x01,0x80,0x78,0xc7,0x01,0xc0,0x71,0xae,0x01,0x80,0x6b,0x95,0x01,0x40,0x65,
-0x7f,0x01,0xc0,0x5f,0x69,0x01,0x40,0x5a,0x55,0x01,0x40,0x55,0x42,0x01,0x80,0x50,
-0x30,0x01,0x00,0x4c,0x1f,0x01,0xc0,0x47,0x0f,0x01,0xc0,0x43,0x00,0x01,0x00,0x40,
-0xf2,0x00,0x80,0x3c,0xe4,0x00,0x00,0x39,0xd7,0x00,0xc0,0x35,0xcb,0x00,0xc0,0x32,
-0xc0,0x00,0x00,0x30,0xb5,0x00,0x40,0x2d,0xab,0x00,0xc0,0x2a,0xa2,0x00,0x80,0x28,
-0x98,0x00,0x00,0x26,0x90,0x00,0x00,0x24,0x88,0x00,0x00,0x22,0x80,0x00,0x00,0x20,
-0x79,0x00,0x40,0x1e,0x72,0x00,0x80,0x1c,0x6c,0x00,0x00,0x1b,0x66,0x00,0x80,0x19,
-0x60,0x00,0x00,0x18,0x5b,0x00,0xc0,0x16,0x56,0x00,0x80,0x15,0x51,0x00,0x40,0x14,
-0x4c,0x00,0x00,0x13,0x48,0x00,0x00,0x12,0x44,0x00,0x00,0x11,0x40,0x00,0x00,0x10,
-0x36,0x35,0x2e,0x25,0x1c,0x12,0x09,0x04,0x33,0x32,0x2b,0x23,0x1a,0x11,0x08,0x04,
-0x30,0x2f,0x29,0x21,0x19,0x10,0x08,0x03,0x2d,0x2d,0x27,0x1f,0x18,0x0f,0x08,0x03,
-0x2b,0x2a,0x25,0x1e,0x16,0x0e,0x07,0x03,0x28,0x28,0x22,0x1c,0x15,0x0d,0x07,0x03,
-0x26,0x25,0x21,0x1b,0x14,0x0d,0x06,0x03,0x24,0x23,0x1f,0x19,0x13,0x0c,0x06,0x03,
-0x22,0x21,0x1d,0x18,0x11,0x0b,0x06,0x02,0x20,0x20,0x1b,0x16,0x11,0x08,0x05,0x02,
-0x1f,0x1e,0x1a,0x15,0x10,0x0a,0x05,0x02,0x1d,0x1c,0x18,0x14,0x0f,0x0a,0x05,0x02,
-0x1b,0x1a,0x17,0x13,0x0e,0x09,0x04,0x02,0x1a,0x19,0x16,0x12,0x0d,0x09,0x04,0x02,
-0x18,0x17,0x15,0x11,0x0c,0x08,0x04,0x02,0x17,0x16,0x13,0x10,0x0c,0x08,0x04,0x02,
-0x16,0x15,0x12,0x0f,0x0b,0x07,0x04,0x01,0x14,0x14,0x11,0x0e,0x0b,0x07,0x03,0x02,
-0x13,0x13,0x10,0x0d,0x0a,0x06,0x03,0x01,0x12,0x12,0x0f,0x0c,0x09,0x06,0x03,0x01,
-0x11,0x11,0x0f,0x0c,0x09,0x06,0x03,0x01,0x10,0x10,0x0e,0x0b,0x08,0x05,0x03,0x01,
-0x0f,0x0f,0x0d,0x0b,0x08,0x05,0x03,0x01,0x0e,0x0e,0x0c,0x0a,0x08,0x05,0x02,0x01,
-0x0d,0x0d,0x0c,0x0a,0x07,0x05,0x02,0x01,0x0d,0x0c,0x0b,0x09,0x07,0x04,0x02,0x01,
-0x0c,0x0c,0x0a,0x09,0x06,0x04,0x02,0x01,0x0b,0x0b,0x0a,0x08,0x06,0x04,0x02,0x01,
-0x0b,0x0a,0x09,0x08,0x06,0x04,0x02,0x01,0x0a,0x0a,0x09,0x07,0x05,0x03,0x02,0x01,
-0x0a,0x09,0x08,0x07,0x05,0x03,0x02,0x01,0x09,0x09,0x08,0x06,0x05,0x03,0x01,0x01,
-0x09,0x08,0x07,0x06,0x04,0x03,0x01,0x01,0x36,0x35,0x2e,0x1b,0x00,0x00,0x00,0x00,
-0x33,0x32,0x2b,0x19,0x00,0x00,0x00,0x00,0x30,0x2f,0x29,0x18,0x00,0x00,0x00,0x00,
-0x2d,0x2d,0x17,0x17,0x00,0x00,0x00,0x00,0x2b,0x2a,0x25,0x15,0x00,0x00,0x00,0x00,
-0x28,0x28,0x24,0x14,0x00,0x00,0x00,0x00,0x26,0x25,0x21,0x13,0x00,0x00,0x00,0x00,
-0x24,0x23,0x1f,0x12,0x00,0x00,0x00,0x00,0x22,0x21,0x1d,0x11,0x00,0x00,0x00,0x00,
-0x20,0x20,0x1b,0x10,0x00,0x00,0x00,0x00,0x1f,0x1e,0x1a,0x0f,0x00,0x00,0x00,0x00,
-0x1d,0x1c,0x18,0x0e,0x00,0x00,0x00,0x00,0x1b,0x1a,0x17,0x0e,0x00,0x00,0x00,0x00,
-0x1a,0x19,0x16,0x0d,0x00,0x00,0x00,0x00,0x18,0x17,0x15,0x0c,0x00,0x00,0x00,0x00,
-0x17,0x16,0x13,0x0b,0x00,0x00,0x00,0x00,0x16,0x15,0x12,0x0b,0x00,0x00,0x00,0x00,
-0x14,0x14,0x11,0x0a,0x00,0x00,0x00,0x00,0x13,0x13,0x10,0x0a,0x00,0x00,0x00,0x00,
-0x12,0x12,0x0f,0x09,0x00,0x00,0x00,0x00,0x11,0x11,0x0f,0x09,0x00,0x00,0x00,0x00,
-0x10,0x10,0x0e,0x08,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0d,0x08,0x00,0x00,0x00,0x00,
-0x0e,0x0e,0x0c,0x07,0x00,0x00,0x00,0x00,0x0d,0x0d,0x0c,0x07,0x00,0x00,0x00,0x00,
-0x0d,0x0c,0x0b,0x06,0x00,0x00,0x00,0x00,0x0c,0x0c,0x0a,0x06,0x00,0x00,0x00,0x00,
-0x0b,0x0b,0x0a,0x06,0x00,0x00,0x00,0x00,0x0b,0x0a,0x09,0x05,0x00,0x00,0x00,0x00,
-0x0a,0x0a,0x09,0x05,0x00,0x00,0x00,0x00,0x0a,0x09,0x08,0x05,0x00,0x00,0x00,0x00,
-0x09,0x09,0x08,0x05,0x00,0x00,0x00,0x00,0x09,0x08,0x07,0x04,0x00,0x00,0x00,0x00,
-0x06,0x00,0x2a,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
-0x08,0x28,0x28,0x28,0x28,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
-0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
-0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
-0x04,0x04,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x41,0x41,0x41,0x41,0x41,0x41,0x01,
-0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
-0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x42,0x42,0x42,0x42,0x42,0x42,0x02,
-0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
-0x02,0x02,0x02,0x10,0x10,0x10,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
-0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
-0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
-0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10,
-0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
-0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,
-0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x19,0x77,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x26,0x72,0xb0,0x00,0x26,0x72,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x26,0x65,0x60,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x02,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xf2,0x30,0xb8,0xff,0xff,0xff,0xff,
-};
-
 u8 Rtl8192SUFwMainArray[MainArrayLength] = {
 0x0, };
 
diff --git a/drivers/staging/rtl8192su/r8192SU_HWImg.h b/drivers/staging/rtl8192su/r8192SU_HWImg.h
index 96b1525..36e84af 100644
--- a/drivers/staging/rtl8192su/r8192SU_HWImg.h
+++ b/drivers/staging/rtl8192su/r8192SU_HWImg.h
@@ -5,8 +5,6 @@
 
 /*Created on  2009/ 3/ 6,  5:29*/
 
-#define ImgArrayLength 68368
-extern u8 Rtl8192SUFwImgArray[ImgArrayLength];
 #define MainArrayLength 1
 extern u8 Rtl8192SUFwMainArray[MainArrayLength];
 #define DataArrayLength 1
diff --git a/drivers/staging/rtl8192su/r8192S_firmware.c b/drivers/staging/rtl8192su/r8192S_firmware.c
index 3561adf0..752a3f1 100644
--- a/drivers/staging/rtl8192su/r8192S_firmware.c
+++ b/drivers/staging/rtl8192su/r8192S_firmware.c
@@ -360,117 +360,58 @@
 
 	RT_TRACE(COMP_FIRMWARE, " --->FirmwareDownload92S()\n");
 
-	//3//
-	//3 //<1> Open Image file, and map file to contineous memory if open file success.
-	//3  //        or read image file from array. Default load from BIN file
-	//3//
-	priv->firmware_source = FW_SOURCE_IMG_FILE;// We should decided by Reg.
-
-	switch( priv->firmware_source )
+/*
+* Load the firmware from RTL8192SU/rtl8192sfw.bin
+*/
+	if(pFirmware->szFwTmpBufferLen == 0)
 	{
-		case FW_SOURCE_IMG_FILE:
-			if(pFirmware->szFwTmpBufferLen == 0)
-			{
-
-				rc = request_firmware(&fw_entry, pFwImageFileName[ulInitStep],&priv->udev->dev);//===>1
-				if(rc < 0 ) {
-					RT_TRACE(COMP_ERR, "request firmware fail!\n");
-					goto DownloadFirmware_Fail;
-				}
-
-				if(fw_entry->size > sizeof(pFirmware->szFwTmpBuffer))
-				{
-					RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
-					release_firmware(fw_entry);
-					goto DownloadFirmware_Fail;
-				}
-
-				memcpy(pFirmware->szFwTmpBuffer,fw_entry->data,fw_entry->size);
-				pFirmware->szFwTmpBufferLen = fw_entry->size;
-				release_firmware(fw_entry);
-
-				pucMappedFile = pFirmware->szFwTmpBuffer;
-				file_length = pFirmware->szFwTmpBufferLen;
-
-				//Retrieve FW header.
-				pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;
-				pFwHdr = pFirmware->pFwHeader;
-				RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \
-						pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \
-						pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE);
-				pFirmware->FirmwareVersion =  byte(pFwHdr->Version ,0);
-				if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM)))
-				{
-					RT_TRACE(COMP_ERR, "%s: memory for data image is less than IMEM required\n",\
-							__FUNCTION__);
-					goto DownloadFirmware_Fail;
-				} else {
-					pucMappedFile+=FwHdrSize;
-
-					//Retrieve IMEM image.
-					memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
-					pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;
-				}
-
-				if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM))
-				{
-					RT_TRACE(COMP_ERR, "%s: memory for data image is less than EMEM required\n",\
-							__FUNCTION__);
-					goto DownloadFirmware_Fail;
-				} else {
-					pucMappedFile += pFirmware->FwIMEMLen;
-
-					/* Retriecve EMEM image */
-					memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);//===>6
-					pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
-				}
-
-
+		rc = request_firmware(&fw_entry, pFwImageFileName[ulInitStep],&priv->udev->dev);
+			if(rc < 0 ) {
+				RT_TRACE(COMP_ERR, "request firmware fail!\n");
+				goto DownloadFirmware_Fail;
 			}
-			break;
 
-		case FW_SOURCE_HEADER_FILE:
-#if 1
-#define Rtl819XFwImageArray Rtl8192SUFwImgArray
-			//2008.11.10 Add by tynli.
-			pucMappedFile = Rtl819XFwImageArray;
-			ulFileLength = ImgArrayLength;
+			if(fw_entry->size > sizeof(pFirmware->szFwTmpBuffer)) {
+				RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
+				release_firmware(fw_entry);
+				goto DownloadFirmware_Fail;
+			}
 
-			RT_TRACE(COMP_INIT,"Fw download from header.\n");
-			/* Retrieve FW header*/
+			memcpy(pFirmware->szFwTmpBuffer,fw_entry->data,fw_entry->size);
+			pFirmware->szFwTmpBufferLen = fw_entry->size;
+			release_firmware(fw_entry);
+
+			pucMappedFile = pFirmware->szFwTmpBuffer;
+			file_length = pFirmware->szFwTmpBufferLen;
+
+			/* Retrieve FW header. */
 			pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;
 			pFwHdr = pFirmware->pFwHeader;
 			RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \
 					pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \
 					pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE);
 			pFirmware->FirmwareVersion =  byte(pFwHdr->Version ,0);
-
-			if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM)))
-			{
-				printk("FirmwareDownload92S(): memory for data image is less than IMEM required\n");
+			if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM))) {
+				RT_TRACE(COMP_ERR, "%s: memory for data image is less than IMEM required\n",\
+					__FUNCTION__);
 				goto DownloadFirmware_Fail;
 			} else {
 				pucMappedFile+=FwHdrSize;
-				//Retrieve IMEM image.
+				/* Retrieve IMEM image. */
 				memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
 				pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;
 			}
 
-			if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM))
-			{
-				printk(" FirmwareDownload92S(): memory for data image is less than EMEM required\n");
-				goto DownloadFirmware_Fail;
-			} else {
-				pucMappedFile+= pFirmware->FwIMEMLen;
-
-				//Retriecve EMEM image.
-				memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);
-				pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
-			}
-#endif
-			break;
-		default:
-			break;
+			if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM)) {
+				RT_TRACE(COMP_ERR, "%s: memory for data image is less than EMEM required\n",\
+					__FUNCTION__);
+					goto DownloadFirmware_Fail;
+				} else {
+					pucMappedFile += pFirmware->FwIMEMLen;
+					/* Retriecve EMEM image */
+					memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);//===>6
+					pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
+				}
 	}
 
 	FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
@@ -538,3 +479,4 @@
 	return rtStatus;
 }
 
+MODULE_FIRMWARE("RTL8192SU/rtl8192sfw.bin");
diff --git a/drivers/staging/rtl8192su/r8192S_firmware.h b/drivers/staging/rtl8192su/r8192S_firmware.h
index c525380..2c2cf80 100644
--- a/drivers/staging/rtl8192su/r8192S_firmware.h
+++ b/drivers/staging/rtl8192su/r8192S_firmware.h
@@ -59,12 +59,6 @@
 	DESC_PACKET_TYPE_NORMAL = 1,
 }desc_packet_type_e;
 
-typedef enum _firmware_source{
-	FW_SOURCE_IMG_FILE = 0,
-	FW_SOURCE_HEADER_FILE = 1,
-}firmware_source_e, *pfirmware_source_e;
-
-
 typedef enum _opt_rst_type{
 	OPT_SYSTEM_RESET = 0,
 	OPT_FIRMWARE_RESET = 1,
@@ -185,7 +179,6 @@
 #define RTL8190_MAX_FIRMWARE_CODE_SIZE  64000   //64k
 
 typedef struct _rt_firmware{
-	firmware_source_e	eFWSource;
 	PRT_8192S_FIRMWARE_HDR	pFwHeader;
 	FIRMWARE_8192S_STATUS	FWStatus;
 	u16             FirmwareVersion;
diff --git a/drivers/staging/rtl8192su/r8192S_phy.c b/drivers/staging/rtl8192su/r8192S_phy.c
index 77ab026..63d4e5f 100644
--- a/drivers/staging/rtl8192su/r8192S_phy.c
+++ b/drivers/staging/rtl8192su/r8192S_phy.c
@@ -2407,8 +2407,8 @@
 			break;
 
 		default:
-			RT_TRACE(COMP_DBG, "SetBWModeCallback8190Pci():\
-						unknown Bandwidth: %#X\n",priv->CurrentChannelBW);
+			RT_TRACE(COMP_DBG, "SetBWModeCallback8190Pci(): unknown Bandwidth: %#X\n",
+				 priv->CurrentChannelBW);
 			break;
 	}
 
@@ -3398,8 +3398,8 @@
 	u32			delay;
 //	bool			ret;
 
-	RT_TRACE(COMP_SCAN, "==>SwChnlCallback8190Pci(), switch to channel\
-				%d\n", priv->chan);
+	RT_TRACE(COMP_SCAN, "==>SwChnlCallback8190Pci(), switch to channel %d\n",
+		 priv->chan);
 
 
 	if(!priv->up)
@@ -3525,8 +3525,8 @@
 			break;
 
 		default:
-			RT_TRACE(COMP_DBG, "SetChannelBandwidth8190Pci():\
-						unknown Bandwidth: %#X\n",priv->CurrentChannelBW);
+			RT_TRACE(COMP_DBG, "SetChannelBandwidth8190Pci(): unknown Bandwidth: %#X\n",
+				 priv->CurrentChannelBW);
 			break;
 	}
 
@@ -3660,8 +3660,8 @@
 			break;
 
 		default:
-			RT_TRACE(COMP_DBG, "SetBWModeCallback8192SUsbWorkItem():\
-						unknown Bandwidth: %#X\n",priv->CurrentChannelBW);
+			RT_TRACE(COMP_DBG, "SetBWModeCallback8192SUsbWorkItem(): unknown Bandwidth: %#X\n",
+				 priv->CurrentChannelBW);
 			break;
 	}
 
diff --git a/drivers/staging/rtl8192su/r8192U.h b/drivers/staging/rtl8192su/r8192U.h
index 2a11e01..ba87623 100644
--- a/drivers/staging/rtl8192su/r8192U.h
+++ b/drivers/staging/rtl8192su/r8192U.h
@@ -1258,7 +1258,6 @@
 	u8 Rf_Mode; //add for Firmware RF -R/W switch
 	prt_firmware		pFirmware;
 	rtl819xUsb_loopback_e	LoopbackMode;
-	firmware_source_e	firmware_source;
 	bool usb_error;
 
 	u16 EEPROMTxPowerDiff;
diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c
index 6f424fe..7d0305c 100644
--- a/drivers/staging/rtl8192su/r8192U_core.c
+++ b/drivers/staging/rtl8192su/r8192U_core.c
@@ -110,7 +110,7 @@
 #define TOTAL_CAM_ENTRY 32
 #define CAM_CONTENT_COUNT 8
 
-static struct usb_device_id rtl8192_usb_id_tbl[] = {
+static const struct usb_device_id rtl8192_usb_id_tbl[] = {
 	/* Realtek */
 	{USB_DEVICE(0x0bda, 0x8192)},
 	{USB_DEVICE(0x0bda, 0x8709)},
@@ -2340,25 +2340,24 @@
 				    skb->len, rtl8192_tx_isr, skb);
 
 	status = usb_submit_urb(tx_urb, GFP_ATOMIC);
-	if (!status){
-//we need to send 0 byte packet whenever 512N bytes/64N(HIGN SPEED/NORMAL SPEED) bytes packet has been transmitted. Otherwise, it will be halt to wait for another packet. WB. 2008.08.27
+	if (!status) {
+		/*
+		 * we need to send 0 byte packet whenever 512N bytes/64N(HIGN SPEED/NORMAL SPEED) bytes packet has been transmitted.
+		 * Otherwise, it will be halt to wait for another packet. WB. 2008.08.27
+		 */
 		bool bSend0Byte = false;
 		u8 zero = 0;
-		if(udev->speed == USB_SPEED_HIGH)
-		{
+		if(udev->speed == USB_SPEED_HIGH) {
 			if (skb->len > 0 && skb->len % 512 == 0)
 				bSend0Byte = true;
 		}
-		else
-		{
+		else {
 			if (skb->len > 0 && skb->len % 64 == 0)
 				bSend0Byte = true;
 		}
-		if (bSend0Byte)
-		{
-#if 1
+		if (bSend0Byte) {
 			tx_urb_zero = usb_alloc_urb(0,GFP_ATOMIC);
-			if(!tx_urb_zero){
+			if(!tx_urb_zero) {
 				RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
 				return -ENOMEM;
 			}
@@ -2366,16 +2365,23 @@
 					usb_sndbulkpipe(udev,idx_pipe), &zero,
 					0, tx_zero_isr, dev);
 			status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
-			if (status){
-			RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
-			return -1;
+			switch (status) {
+				case 0:
+					break;
+				case -ECONNRESET:
+				case -ENOENT:
+				case -ESHUTDOWN:
+					break;
+				default:
+					RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d",
+						atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
+					return -1;
 			}
-#endif
 		}
 		dev->trans_start = jiffies;
 		atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
 		return 0;
-	}else{
+	} else {
 		RT_TRACE(COMP_ERR, "Error TX URB %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]),
 				status);
 		return -1;
@@ -2952,7 +2958,7 @@
 			wireless_mode = WIRELESS_MODE_B;
 		}
 	}
-#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we shoud wait for FPGA
+#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we should wait for FPGA
 	ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
 #endif
 	//LZM 090306 usb crash here, mark it temp
@@ -3359,6 +3365,46 @@
 	return RFtype;
 }
 
+void update_hal_variables(struct r8192_priv *priv)
+{
+	int rf_path;
+	int i;
+	u8 index;
+
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		for (i = 0; i < 3; i++)	{
+			RT_TRACE((COMP_INIT), "CCK RF-%d CHan_Area-%d = 0x%x\n", rf_path, i, priv->RfCckChnlAreaTxPwr[rf_path][i]);
+			RT_TRACE((COMP_INIT), "OFDM-1T RF-%d CHan_Area-%d = 0x%x\n", rf_path, i, priv->RfOfdmChnlAreaTxPwr1T[rf_path][i]);
+			RT_TRACE((COMP_INIT), "OFDM-2T RF-%d CHan_Area-%d = 0x%x\n", rf_path, i, priv->RfOfdmChnlAreaTxPwr2T[rf_path][i]);
+		}
+		/* Assign dedicated channel tx power */
+		for(i = 0; i < 14; i++) {
+			/* channel 1-3 use the same Tx Power Level. */
+			if (i < 3)			/* Channel 1-3 */
+				index = 0;
+			else if (i < 9)			/* Channel 4-9 */
+				index = 1;
+			else				/* Channel 10-14 */
+				index = 2;
+			/* Record A & B CCK /OFDM - 1T/2T Channel area tx power */
+			priv->RfTxPwrLevelCck[rf_path][i] = priv->RfCckChnlAreaTxPwr[rf_path][index];
+			priv->RfTxPwrLevelOfdm1T[rf_path][i]  = priv->RfOfdmChnlAreaTxPwr1T[rf_path][index];
+			priv->RfTxPwrLevelOfdm2T[rf_path][i]  = priv->RfOfdmChnlAreaTxPwr2T[rf_path][index];
+			if (rf_path == 0) {
+				priv->TxPowerLevelOFDM24G[i] = priv->RfTxPwrLevelOfdm1T[rf_path][i] ;
+				priv->TxPowerLevelCCK[i] = priv->RfTxPwrLevelCck[rf_path][i];
+			}
+		}
+		for(i = 0; i < 14; i++) {
+			RT_TRACE((COMP_INIT),
+			"Rf-%d TxPwr CH-%d CCK OFDM_1T OFDM_2T= 0x%x/0x%x/0x%x\n",
+				rf_path, i, priv->RfTxPwrLevelCck[rf_path][i],
+				priv->RfTxPwrLevelOfdm1T[rf_path][i] ,
+				priv->RfTxPwrLevelOfdm2T[rf_path][i] );
+		}
+	}
+}
+
 //
 //	Description:
 //		Config HW adapter information into initial value.
@@ -3374,7 +3420,7 @@
 	struct r8192_priv 	*priv = ieee80211_priv(dev);
 	//u16			i,usValue;
 	//u8 sMacAddr[6] = {0x00, 0xE0, 0x4C, 0x81, 0x92, 0x00};
-	u8		rf_path, index;	// For EEPROM/EFUSE After V0.6_1117
+	u8		rf_path;	// For EEPROM/EFUSE After V0.6_1117
 	int	i;
 
 	RT_TRACE(COMP_INIT, "====> ConfigAdapterInfo8192SForAutoLoadFail\n");
@@ -3426,10 +3472,9 @@
 	write_nic_dword(dev, IDR0, ((u32*)dev->dev_addr)[0]);
 	write_nic_word(dev, IDR4, ((u16*)(dev->dev_addr + 4))[0]);
 
-	RT_TRACE(COMP_INIT, "ReadAdapterInfo8192SEFuse(), Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
-			dev->dev_addr[0], dev->dev_addr[1],
-			dev->dev_addr[2], dev->dev_addr[3],
-			dev->dev_addr[4], dev->dev_addr[5]);
+	RT_TRACE(COMP_INIT,
+		"ReadAdapterInfo8192SEFuse(), Permanent Address = %pM\n",
+		dev->dev_addr);
 
 	priv->EEPROMBoardType = EEPROM_Default_BoardType;
 	priv->rf_type = RF_1T2R; //RF_2T2R
@@ -3455,42 +3500,7 @@
 		}
 	}
 
-	for (i = 0; i < 3; i++)
-	{
-		//RT_TRACE((COMP_EFUSE), "CCK RF-%d CHan_Area-%d = 0x%x\n",  rf_path, i,
-		//priv->RfCckChnlAreaTxPwr[rf_path][i]);
-		//RT_TRACE((COMP_EFUSE), "OFDM-1T RF-%d CHan_Area-%d = 0x%x\n",  rf_path, i,
-		//priv->RfOfdmChnlAreaTxPwr1T[rf_path][i]);
-		//RT_TRACE((COMP_EFUSE), "OFDM-2T RF-%d CHan_Area-%d = 0x%x\n",  rf_path, i,
-		//priv->RfOfdmChnlAreaTxPwr2T[rf_path][i]);
-	}
-
-	// Assign dedicated channel tx power
-	for(i=0; i<14; i++)	// channel 1~3 use the same Tx Power Level.
-		{
-		if (i < 3)			// Cjanel 1-3
-			index = 0;
-		else if (i < 9)		// Channel 4-9
-			index = 1;
-		else				// Channel 10-14
-			index = 2;
-
-		// Record A & B CCK /OFDM - 1T/2T Channel area tx power
-		priv->RfTxPwrLevelCck[rf_path][i]  =
-		priv->RfCckChnlAreaTxPwr[rf_path][index];
-		priv->RfTxPwrLevelOfdm1T[rf_path][i]  =
-		priv->RfOfdmChnlAreaTxPwr1T[rf_path][index];
-		priv->RfTxPwrLevelOfdm2T[rf_path][i]  =
-		priv->RfOfdmChnlAreaTxPwr2T[rf_path][index];
-		}
-
-		for(i=0; i<14; i++)
-		{
-		//RT_TRACE((COMP_EFUSE), "Rf-%d TxPwr CH-%d CCK OFDM_1T OFDM_2T= 0x%x/0x%x/0x%x\n",
-		//rf_path, i, priv->RfTxPwrLevelCck[0][i],
-		//priv->RfTxPwrLevelOfdm1T[0][i] ,
-		//priv->RfTxPwrLevelOfdm2T[0][i] );
-		}
+	update_hal_variables(priv);
 
 	//
 	// Update remained HAL variables.
@@ -3767,10 +3777,9 @@
 	write_nic_dword(dev, IDR0, ((u32*)dev->dev_addr)[0]);
 	write_nic_word(dev, IDR4, ((u16*)(dev->dev_addr + 4))[0]);
 
-	RT_TRACE(COMP_INIT, "ReadAdapterInfo8192SEFuse(), Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
-			dev->dev_addr[0], dev->dev_addr[1],
-			dev->dev_addr[2], dev->dev_addr[3],
-			dev->dev_addr[4], dev->dev_addr[5]);
+	RT_TRACE(COMP_INIT,
+		"ReadAdapterInfo8192SEFuse(), Permanent Address = %pM\n",
+		dev->dev_addr);
 
 	//
 	// Get CustomerID(Boad Type)
@@ -3901,53 +3910,7 @@
 			}
 
 		}
-//
-		// Update Tx Power HAL variables.
-//
-		for (rf_path = 0; rf_path < 2; rf_path++)
-		{
-			for (i = 0; i < 3; i++)
-			{
-				RT_TRACE((COMP_INIT),  "CCK RF-%d CHan_Area-%d = 0x%x\n",  rf_path, i,
-				priv->RfCckChnlAreaTxPwr[rf_path][i]);
-				RT_TRACE((COMP_INIT), "OFDM-1T RF-%d CHan_Area-%d = 0x%x\n",  rf_path, i,
-				priv->RfOfdmChnlAreaTxPwr1T[rf_path][i]);
-				RT_TRACE((COMP_INIT), "OFDM-2T RF-%d CHan_Area-%d = 0x%x\n",  rf_path, i, priv->RfOfdmChnlAreaTxPwr2T[rf_path][i]);
-			}
-
-			// Assign dedicated channel tx power
-			for(i=0; i<14; i++)	// channel 1~3 use the same Tx Power Level.
-			{
-				if (i < 3)			// Cjanel 1-3
-					index = 0;
-				else if (i < 9)		// Channel 4-9
-					index = 1;
-				else				// Channel 10-14
-					index = 2;
-
-				// Record A & B CCK /OFDM - 1T/2T Channel area tx power
-				priv->RfTxPwrLevelCck[rf_path][i]  =
-				priv->RfCckChnlAreaTxPwr[rf_path][index];
-				priv->RfTxPwrLevelOfdm1T[rf_path][i]  =
-				priv->RfOfdmChnlAreaTxPwr1T[rf_path][index];
-				priv->RfTxPwrLevelOfdm2T[rf_path][i]  =
-				priv->RfOfdmChnlAreaTxPwr2T[rf_path][index];
-				if (rf_path == 0)
-				{
-					priv->TxPowerLevelOFDM24G[i] = priv->RfTxPwrLevelOfdm1T[rf_path][i] ;
-					priv->TxPowerLevelCCK[i] = priv->RfTxPwrLevelCck[rf_path][i];
-				}
-			}
-
-			for(i=0; i<14; i++)
-			{
-				RT_TRACE((COMP_INIT),
-				"Rf-%d TxPwr CH-%d CCK OFDM_1T OFDM_2T= 0x%x/0x%x/0x%x\n",
-				rf_path, i, priv->RfTxPwrLevelCck[rf_path][i],
-				priv->RfTxPwrLevelOfdm1T[rf_path][i] ,
-				priv->RfTxPwrLevelOfdm2T[rf_path][i] );
-			}
-		}
+		update_hal_variables(priv);
 	}
 
 	//
@@ -7677,7 +7640,7 @@
 	if (EntryNo >= TOTAL_CAM_ENTRY)
 		RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
 
-	RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex, KeyType, MAC_ARG(MacAddr));
+	RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", dev,EntryNo, KeyIndex, KeyType, MacAddr);
 
 	if (DefaultKey)
 		usConfig |= BIT15 | (KeyType<<2);
diff --git a/drivers/staging/rtl8192su/r8192U_dm.c b/drivers/staging/rtl8192su/r8192U_dm.c
index 7891e96..fa5e244 100644
--- a/drivers/staging/rtl8192su/r8192U_dm.c
+++ b/drivers/staging/rtl8192su/r8192U_dm.c
@@ -2697,7 +2697,7 @@
 		u8* peername[11] = {"unknown", "realtek", "realtek_92se", "broadcom", "ralink", "atheros", "cisco", "marvell", "92u_softap", "self_softap"};
 		static int wb_tmp = 0;
 		if (wb_tmp == 0){
-			printk("%s():iot peer is %#x:%s, bssid:"MAC_FMT"\n",__FUNCTION__,pHTInfo->IOTPeer,peername[pHTInfo->IOTPeer], MAC_ARG(priv->ieee80211->current_network.bssid));
+			printk("%s():iot peer is %#x:%s, bssid:%pM\n",__FUNCTION__,pHTInfo->IOTPeer,peername[pHTInfo->IOTPeer], priv->ieee80211->current_network.bssid);
 			wb_tmp = 1;
 		}
 	}
diff --git a/drivers/staging/rtl8192u/Kconfig b/drivers/staging/rtl8192u/Kconfig
index 9913ab8..0439c90 100644
--- a/drivers/staging/rtl8192u/Kconfig
+++ b/drivers/staging/rtl8192u/Kconfig
@@ -1,6 +1,7 @@
 config RTL8192U
 	tristate "RealTek RTL8192U Wireless LAN NIC driver"
 	depends on PCI && WLAN && USB
-	depends on WIRELESS_EXT
+	select WIRELESS_EXT
+	select WEXT_PRIV
 	default N
 	---help---
diff --git a/drivers/staging/rtl8192u/Makefile b/drivers/staging/rtl8192u/Makefile
index 2d59c4e..738f4a8 100644
--- a/drivers/staging/rtl8192u/Makefile
+++ b/drivers/staging/rtl8192u/Makefile
@@ -3,7 +3,7 @@
 EXTRA_CFLAGS += -std=gnu89
 EXTRA_CFLAGS += -O2
 
-EXTRA_CFLAGS += -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y
+EXTRA_CFLAGS += -DCONFIG_FORCE_HARD_FLOAT=y
 EXTRA_CFLAGS += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX
 EXTRA_CFLAGS += -DTHOMAS_BEACON -DTHOMAS_TASKLET -DTHOMAS_SKB -DTHOMAS_TURBO
 #EXTRA_CFLAGS += -DUSB_TX_DRIVER_AGGREGATION_ENABLE
diff --git a/drivers/staging/rtl8192u/ieee80211.h b/drivers/staging/rtl8192u/ieee80211.h
index 3a47f12..9d05ed6 100644
--- a/drivers/staging/rtl8192u/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211.h
@@ -551,9 +551,6 @@
 
 /* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
 
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
-
 /*
  * To use the debug system;
  *
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index 10908e123..39847c8 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -30,6 +30,7 @@
 #include <linux/jiffies.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
+#include <linux/semaphore.h>
 
 #include <linux/delay.h>
 #include <linux/wireless.h>
@@ -551,9 +552,6 @@
 
 /* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
 
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
-
 /*
  * To use the debug system;
  *
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
index 0b33bf4..0b57632 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
@@ -288,7 +288,7 @@
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "CCMP: received packet without ExtIV"
-			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			       " flag from %pM\n", hdr->addr2);
 		}
 		key->dot11RSNAStatsCCMPFormatErrors++;
 		return -2;
@@ -301,9 +301,9 @@
 	}
 	if (!key->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
+			printk(KERN_DEBUG "CCMP: received packet from %pM"
 			       " with keyid=%d that does not have a configured"
-			       " key\n", MAC_ARG(hdr->addr2), keyidx);
+			       " key\n", hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -318,11 +318,9 @@
 
 	if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
-			       " previous PN %02x%02x%02x%02x%02x%02x "
-			       "received PN %02x%02x%02x%02x%02x%02x\n",
-			       MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
-			       MAC_ARG(pn));
+			printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
+			       " previous PN %pm received PN %pm\n",
+			       hdr->addr2, key->rx_pn, pn);
 		}
 		key->dot11RSNAStatsCCMPReplays++;
 		return -4;
@@ -359,7 +357,7 @@
 		if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG "CCMP: decrypt failed: STA="
-				MAC_FMT "\n", MAC_ARG(hdr->addr2));
+				"%pM\n", hdr->addr2);
 			}
 			key->dot11RSNAStatsCCMPDecryptErrors++;
 			return -5;
@@ -435,11 +433,10 @@
 {
 	struct ieee80211_ccmp_data *ccmp = priv;
 	p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
-		     "tx_pn=%02x%02x%02x%02x%02x%02x "
-		     "rx_pn=%02x%02x%02x%02x%02x%02x "
+		     "tx_pn=%pm rx_pn=%pm "
 		     "format_errors=%d replays=%d decrypt_errors=%d\n",
 		     ccmp->key_idx, ccmp->key_set,
-		     MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
+		     ccmp->tx_pn, ccmp->rx_pn,
 		     ccmp->dot11RSNAStatsCCMPFormatErrors,
 		     ccmp->dot11RSNAStatsCCMPReplays,
 		     ccmp->dot11RSNAStatsCCMPDecryptErrors);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
index 841b999..9510507 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
@@ -410,7 +410,7 @@
 	if (!(keyidx & (1 << 5))) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "TKIP: received packet without ExtIV"
-			       " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+			       " flag from %pM\n", hdr->addr2);
 		}
 		return -2;
 	}
@@ -422,9 +422,9 @@
 	}
 	if (!tkey->key_set) {
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
+			printk(KERN_DEBUG "TKIP: received packet from %pM"
 			       " with keyid=%d that does not have a configured"
-			       " key\n", MAC_ARG(hdr->addr2), keyidx);
+			       " key\n", hdr->addr2, keyidx);
 		}
 		return -3;
 	}
@@ -437,9 +437,9 @@
 		if (iv32 < tkey->rx_iv32 ||
 		(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
 			if (net_ratelimit()) {
-				printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
+				printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
 				" previous TSC %08x%04x received TSC "
-				"%08x%04x\n", MAC_ARG(hdr->addr2),
+				"%08x%04x\n", hdr->addr2,
 				tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
 			}
 			tkey->dot11RSNAStatsTKIPReplays++;
@@ -460,8 +460,8 @@
 		if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG ": TKIP: failed to decrypt "
-						"received packet from " MAC_FMT "\n",
-						MAC_ARG(hdr->addr2));
+						"received packet from %pM\n",
+						hdr->addr2);
 			}
 			return -7;
 		}
@@ -480,7 +480,7 @@
 			}
 			if (net_ratelimit()) {
 				printk(KERN_DEBUG "TKIP: ICV error detected: STA="
-				MAC_FMT "\n", MAC_ARG(hdr->addr2));
+				"%pM\n", hdr->addr2);
 			}
 			tkey->dot11RSNAStatsTKIPICVErrors++;
 			return -5;
@@ -635,8 +635,8 @@
 		struct ieee80211_hdr_4addr *hdr;
 		hdr = (struct ieee80211_hdr_4addr *) skb->data;
 		printk(KERN_DEBUG "%s: Michael MIC verification failed for "
-		       "MSDU from " MAC_FMT " keyidx=%d\n",
-		       skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
+		       "MSDU from %pM keyidx=%d\n",
+		       skb->dev ? skb->dev->name : "N/A", hdr->addr2,
 		       keyidx);
 		if (skb->dev)
 			ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index 7a8690f..b752017 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -260,7 +260,7 @@
 			     unsigned long count, void *data)
 {
 	char buf[] = "0x00000000";
-	unsigned long len = min(sizeof(buf) - 1, count);
+	unsigned long len = min_t(unsigned long, sizeof(buf) - 1, count);
 	char *p = (char *)buf;
 	unsigned long val;
 
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index 0e003c5..7e9b367 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -360,8 +360,8 @@
 	    strcmp(crypt->ops->name, "TKIP") == 0) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "received packet from " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(hdr->addr2));
+			       "received packet from %pM\n",
+			       ieee->dev->name, hdr->addr2);
 		}
 		return -1;
 	}
@@ -372,8 +372,8 @@
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
 		IEEE80211_DEBUG_DROP(
-			"decryption failed (SA=" MAC_FMT
-			") res=%d\n", MAC_ARG(hdr->addr2), res);
+			"decryption failed (SA=%pM"
+			") res=%d\n", hdr->addr2, res);
 		if (res == -2)
 			IEEE80211_DEBUG_DROP("Decryption failed ICV "
 					     "mismatch (key %d)\n",
@@ -410,8 +410,8 @@
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
 		printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
-		       " (SA=" MAC_FMT " keyidx=%d)\n",
-		       ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
+		       " (SA=%pM keyidx=%d)\n",
+		       ieee->dev->name, hdr->addr2, keyidx);
 		return -1;
 	}
 
@@ -1016,8 +1016,8 @@
 			 * frames silently instead of filling system log with
 			 * these reports. */
 			IEEE80211_DEBUG_DROP("Decryption failed (not set)"
-					     " (SA=" MAC_FMT ")\n",
-					     MAC_ARG(hdr->addr2));
+					     " (SA=%pM)\n",
+					     hdr->addr2);
 			ieee->ieee_stats.rx_discards_undecryptable++;
 			goto rx_dropped;
 		}
@@ -1256,8 +1256,8 @@
 		} else {
 			IEEE80211_DEBUG_DROP(
 				"encryption configured, but RX "
-				"frame not encrypted (SA=" MAC_FMT ")\n",
-				MAC_ARG(hdr->addr2));
+				"frame not encrypted (SA=%pM)\n",
+				hdr->addr2);
 			goto rx_dropped;
 		}
 	}
@@ -1276,9 +1276,9 @@
 	    !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
 		IEEE80211_DEBUG_DROP(
 			"dropped unencrypted RX data "
-			"frame from " MAC_FMT
+			"frame from %pM"
 			" (drop_unencrypted=1)\n",
-			MAC_ARG(hdr->addr2));
+			hdr->addr2);
 		goto rx_dropped;
 	}
 /*
@@ -2260,11 +2260,11 @@
 	}
 
 	if (network->mode == 0) {
-		IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
+		IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
 				     "network.\n",
 				     escape_essid(network->ssid,
 						  network->ssid_len),
-				     MAC_ARG(network->bssid));
+				     network->bssid);
 		return 1;
 	}
 
@@ -2439,9 +2439,9 @@
 
 	memset(&network, 0, sizeof(struct ieee80211_network));
 	IEEE80211_DEBUG_SCAN(
-		"'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+		"'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
 		escape_essid(info_element->data, info_element->len),
-		MAC_ARG(beacon->header.addr3),
+		beacon->header.addr3,
 		(beacon->capability & (1<<0xf)) ? '1' : '0',
 		(beacon->capability & (1<<0xe)) ? '1' : '0',
 		(beacon->capability & (1<<0xd)) ? '1' : '0',
@@ -2460,10 +2460,10 @@
 		(beacon->capability & (1<<0x0)) ? '1' : '0');
 
 	if (ieee80211_network_init(ieee, beacon, &network, stats)) {
-		IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
 				     escape_essid(info_element->data,
 						  info_element->len),
-				     MAC_ARG(beacon->header.addr3),
+				     beacon->header.addr3,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
@@ -2574,11 +2574,11 @@
 			/* If there are no more slots, expire the oldest */
 			list_del(&oldest->list);
 			target = oldest;
-			IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
+			IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
 					     "network list.\n",
 					     escape_essid(target->ssid,
 							  target->ssid_len),
-					     MAC_ARG(target->bssid));
+					     target->bssid);
 		} else {
 			/* Otherwise just pull from the free list */
 			target = list_entry(ieee->network_free_list.next,
@@ -2588,10 +2588,10 @@
 
 
 #ifdef CONFIG_IEEE80211_DEBUG
-		IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
 				     escape_essid(network.ssid,
 						  network.ssid_len),
-				     MAC_ARG(network.bssid),
+				     network.bssid,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
@@ -2601,10 +2601,10 @@
 		if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
 			ieee80211_softmac_new_net(ieee,&network);
 	} else {
-		IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
+		IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
 				     escape_essid(target->ssid,
 						  target->ssid_len),
-				     MAC_ARG(target->bssid),
+				     target->bssid,
 				     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
 				     IEEE80211_STYPE_PROBE_RESP ?
 				     "PROBE RESPONSE" : "BEACON");
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index 8a86e93..27d9257 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -1731,7 +1731,7 @@
 		ieee80211_resp_to_assoc_rq(ieee, dest);
 	}
 
-	printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
+	printk(KERN_INFO"New client associated: %pM\n", dest);
 	//FIXME
 }
 
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
index b29c36b..48537d9 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
@@ -200,8 +200,8 @@
 		header = (struct ieee80211_hdr *) frag->data;
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "TX packet to " MAC_FMT "\n",
-			       ieee->dev->name, MAC_ARG(header->addr1));
+			       "TX packet to %pM\n",
+			       ieee->dev->name, header->addr1);
 		}
 		return -1;
 	}
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
index 5f12d62..c0b2c02 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
@@ -289,10 +289,10 @@
 		else
 			IEEE80211_DEBUG_SCAN(
 				"Not showing network '%s ("
-				MAC_FMT ")' due to age (%lums).\n",
+				"%pM)' due to age (%lums).\n",
 				escape_essid(network->ssid,
 					     network->ssid_len),
-				MAC_ARG(network->bssid),
+				network->bssid,
 				(jiffies - network->last_scanned) / (HZ / 100));
 	}
 
@@ -718,7 +718,7 @@
 	} else
 		idx = ieee->tx_keyidx;
 
-	if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY &&
+	if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
 	    ext->alg != IW_ENCODE_ALG_WEP)
 		if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
 			return -EINVAL;
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
index 512a57a..27d083a 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
@@ -113,7 +113,7 @@
 	u16 tmp = 0;
 	u16 len = ieee->tx_headroom + 9;
 	//category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) +  BA Timeout Value(2) +  BA Start SeqCtrl(2)(or StatusCode(2))
-	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __FUNCTION__, type, MAC_ARG(Dst), ieee->dev);
+	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
 	if (pBA == NULL||ieee == NULL)
 	{
 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
@@ -201,7 +201,7 @@
 	u16 len = 6 + ieee->tx_headroom;
 
 	if (net_ratelimit())
-	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst));
+	IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
 
 	memset(&DelbaParamSet, 0, 2);
 
@@ -355,7 +355,7 @@
 	pBaTimeoutVal = (u16*)(tag + 5);
 	pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
 
-	printk("====================>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst));
+	printk("====================>rx ADDBAREQ from :%pM\n", dst);
 //some other capability is not ready now.
 	if(	(ieee->current_network.qos_data.active == 0) ||
 		(ieee->pHTInfo->bCurrentHTSupport == false)) //||
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c
index 2c4eb38..50f4f59 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c
@@ -41,7 +41,7 @@
 //static u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0};
 static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
 
-// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Shoud we put the
+// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Should we put the
 // code in other place??
 //static u8 WIFI_CISCO_G_AP[3] = {0x00, 0x40, 0x96};
 /********************************************************************************************************************
@@ -1342,7 +1342,7 @@
 
 		pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
 
-		pHTInfo->CurrentMPDUDensity = pHTInfo->CurrentMPDUDensity;
+		pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
 
 		// Set BWOpMode register
 
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
index 5373d56..d1275e8 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
@@ -290,7 +290,7 @@
 		if(search_dir[dir] ==false )
 			continue;
 		list_for_each_entry(pRet, psearch_list, List){
-	//		IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:"MAC_FMT", TID:%d, dir:%d\n", MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
+	//		IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
 			if (memcmp(pRet->Addr, Addr, 6) == 0)
 				if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
 					if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
@@ -445,7 +445,7 @@
 					ResetRxTsEntry(tmp);
 				}
 
-				IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT"\n", UP, Dir, MAC_ARG(Addr));
+				IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
 				// Prepare TS Info releated field
 				pTSInfo->field.ucTrafficType = 0;			// Traffic type: WMM is reserved in this field
 				pTSInfo->field.ucTSID = UP;			// TSID
@@ -531,7 +531,7 @@
 void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr)
 {
 	PTS_COMMON_INFO	pTS, pTmpTS;
-	printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr));
+	printk("===========>RemovePeerTS,%pM\n", Addr);
 	list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
 	{
 		if (memcmp(pTS->Addr, Addr, 6) == 0)
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index adade13..f1e085b 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -104,7 +104,7 @@
 #define TOTAL_CAM_ENTRY 32
 #define CAM_CONTENT_COUNT 8
 
-static struct usb_device_id rtl8192_usb_id_tbl[] = {
+static const struct usb_device_id rtl8192_usb_id_tbl[] = {
 	/* Realtek */
 	{USB_DEVICE(0x0bda, 0x8192)},
 	{USB_DEVICE(0x0bda, 0x8709)},
@@ -2719,7 +2719,7 @@
 			wireless_mode = WIRELESS_MODE_B;
 		}
 	}
-#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we shoud wait for FPGA
+#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we should wait for FPGA
 	ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
 #endif
 	priv->ieee80211->mode = wireless_mode;
@@ -2976,7 +2976,7 @@
 		memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
 		//should I set IDR0 here?
 	}
-	RT_TRACE(COMP_EPROM, "MAC addr:"MAC_FMT"\n", MAC_ARG(dev->dev_addr));
+	RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
 	priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
 	priv->rf_chip = RF_8256;
 
@@ -6037,7 +6037,7 @@
 	if (EntryNo >= TOTAL_CAM_ENTRY)
 		RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
 
-	RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex, KeyType, MAC_ARG(MacAddr));
+	RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", dev,EntryNo, KeyIndex, KeyType, MacAddr);
 
 	if (DefaultKey)
 		usConfig |= BIT15 | (KeyType<<2);
diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c
index 4877138..dd7ea4c0 100644
--- a/drivers/staging/samsung-laptop/samsung-laptop.c
+++ b/drivers/staging/samsung-laptop/samsung-laptop.c
@@ -99,7 +99,8 @@
 
 static int force;
 module_param(force, bool, 0);
-MODULE_PARM_DESC(force, "Disable the DMI check and forces the driver to be loaded");
+MODULE_PARM_DESC(force,
+		"Disable the DMI check and forces the driver to be loaded");
 
 static int debug;
 module_param(debug, bool, S_IRUGO | S_IWUSR);
@@ -370,7 +371,8 @@
 	{
 		.ident = "N128",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "N128"),
 			DMI_MATCH(DMI_BOARD_NAME, "N128"),
 		},
@@ -379,7 +381,8 @@
 	{
 		.ident = "N130",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "N130"),
 			DMI_MATCH(DMI_BOARD_NAME, "N130"),
 		},
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index e7bc9ec..265de79 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -35,6 +35,7 @@
 #include <linux/cdev.h>
 #include <linux/kdev_t.h>
 #include <linux/mutex.h>
+#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/poll.h>
 #include <linux/wait.h>
@@ -182,8 +183,8 @@
 static int sep_load_firmware(struct sep_device *sep)
 {
 	const struct firmware *fw;
-	char *cache_name = "cache.image.bin";
-	char *res_name = "resident.image.bin";
+	char *cache_name = "sep/cache.image.bin";
+	char *res_name = "sep/resident.image.bin";
 	int error;
 
 	edbg("SEP Driver:rar_virtual is %p\n", sep->rar_addr);
@@ -222,6 +223,9 @@
 	return 0;
 }
 
+MODULE_FIRMWARE("sep/cache.image.bin");
+MODULE_FIRMWARE("sep/resident.image.bin");
+
 /**
  *	sep_map_and_alloc_shared_area	-	allocate shared block
  *	@sep: security processor
@@ -273,8 +277,8 @@
 						void *virt_address)
 {
 	dma_addr_t pa = sep->shared_bus + (virt_address - sep->shared_addr);
-	edbg("sep: virt to bus b %08llx v %p\n",
-		(unsigned long long)pa, virt_address);
+	edbg("sep: virt to bus b %08llx v %p\n", (unsigned long long) pa,
+								virt_address);
 	return pa;
 }
 
@@ -380,8 +384,7 @@
 	   shared area */
 	if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
 		edbg("SEP Driver mmap requested size is more than allowed\n");
-		printk(KERN_WARNING "SEP Driver mmap requested size is more \
-			than allowed\n");
+		printk(KERN_WARNING "SEP Driver mmap requested size is more than allowed\n");
 		printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_end);
 		printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_start);
 		return -EAGAIN;
@@ -941,8 +944,9 @@
 			dbg("data_size is %lu\n", data_size);
 			while (1);
 		}
-		edbg("lli_array[%lu].physical_address is %08lx, \
-		lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
+		edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n",
+		     count, lli_array[count].physical_address,
+		     count, lli_array[count].block_size);
 	}
 
 	/* set output params */
@@ -1771,7 +1775,7 @@
 static int sep_create_flow_dma_tables_handler(struct sep_device *sep,
 							unsigned long arg)
 {
-	int error;
+	int error = -ENOENT;
 	struct sep_driver_build_flow_table_t command_args;
 	/* first table - output */
 	struct sep_lli_entry_t first_table_data;
@@ -2232,7 +2236,7 @@
 	return error;
 }
 
-static int sep_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	int error = 0;
 	struct sep_device *sep = filp->private_data;
@@ -2586,7 +2590,7 @@
 	return error;
 }
 
-static struct pci_device_id sep_pci_id_tbl[] = {
+static const struct pci_device_id sep_pci_id_tbl[] = {
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080c)},
 	{0}
 };
@@ -2607,7 +2611,7 @@
 /* the files operations structure of the driver */
 static struct file_operations sep_file_operations = {
 	.owner = THIS_MODULE,
-	.ioctl = sep_ioctl,
+	.unlocked_ioctl = sep_ioctl,
 	.poll = sep_poll,
 	.open = sep_open,
 	.release = sep_release,
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
index 060e9de..44f2d4e 100644
--- a/drivers/staging/serqt_usb2/serqt_usb2.c
+++ b/drivers/staging/serqt_usb2/serqt_usb2.c
@@ -126,7 +126,7 @@
 #define MODEM_CTRL          0x40
 #define RS232_MODE          0x00
 
-static struct usb_device_id serqt_id_table[] = {
+static const struct usb_device_id serqt_id_table[] = {
 	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
 	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU200)},
 	{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100)},
@@ -1277,7 +1277,7 @@
 	if (cflag & CSTOPB)
 		new_LCR |= SERIAL_TWO_STOPB;
 	else
-		new_LCR |= SERIAL_TWO_STOPB;
+		new_LCR |= SERIAL_ONE_STOPB;
 
 	dbg("%s - 4\n", __func__);
 
diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h
index ccf7625..eb3a619 100644
--- a/drivers/staging/slicoss/slic.h
+++ b/drivers/staging/slicoss/slic.h
@@ -527,15 +527,6 @@
     (largestat) += ((newstat) - (oldstat));                              \
 }
 
-#define ETHER_EQ_ADDR(_AddrA, _AddrB, _Result)                           \
-{                                                                        \
-    _Result = true;                                                      \
-    if (*(u32 *)(_AddrA) != *(u32 *)(_AddrB))                          \
-	_Result = false;                                                 \
-    if (*(u16 *)(&((_AddrA)[4])) != *(u16 *)(&((_AddrB)[4])))        \
-	_Result = false;                                                 \
-}
-
 #if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
 #define   SLIC_GET_ADDR_LOW(_addr)  (u32)((u64)(_addr) & \
 	0x00000000FFFFFFFF)
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index f5cc01b..7daeced 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -101,7 +101,7 @@
 static int slic_entry_open(struct net_device *dev);
 static int slic_entry_halt(struct net_device *dev);
 static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev);
 static void slic_xmit_fail(struct adapter *adapter, struct sk_buff *skb,
 			   void *cmd, u32 skbtype, u32 status);
 static void slic_config_pci(struct pci_dev *pcidev);
@@ -194,14 +194,10 @@
 module_param(intagg_delay, int, 0);
 MODULE_PARM_DESC(intagg_delay, "uSec Interrupt Aggregation Delay");
 
-static struct pci_device_id slic_pci_tbl[] __devinitdata = {
-	{PCI_VENDOR_ID_ALACRITECH,
-	 SLIC_1GB_DEVICE_ID,
-	 PCI_ANY_ID, PCI_ANY_ID,},
-	{PCI_VENDOR_ID_ALACRITECH,
-	 SLIC_2GB_DEVICE_ID,
-	 PCI_ANY_ID, PCI_ANY_ID,},
-	{0,}
+static DEFINE_PCI_DEVICE_TABLE(slic_pci_tbl) = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_1GB_DEVICE_ID) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_2GB_DEVICE_ID) },
+	{ 0 }
 };
 
 MODULE_DEVICE_TABLE(pci, slic_pci_tbl);
@@ -292,7 +288,7 @@
 {
 	ushort index;
 	struct slic_handle *pslic_handle;
-	struct adapter *adapter = (struct adapter *)netdev_priv(netdev);
+	struct adapter *adapter = netdev_priv(netdev);
 
 /*	adapter->pcidev = pcidev;*/
 	adapter->vendid = pci_tbl_entry->vendor;
@@ -370,6 +366,7 @@
 	ulong mmio_start = 0;
 	ulong mmio_len = 0;
 	struct sliccard *card = NULL;
+	int pci_using_dac = 0;
 
 	slic_global.dynamic_intagg = dynamic_intagg;
 
@@ -383,16 +380,26 @@
 		printk(KERN_DEBUG "%s\n", slic_proc_version);
 	}
 
-	err = pci_set_dma_mask(pcidev, DMA_BIT_MASK(64));
-	if (err) {
-		err = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32));
-		if (err)
+	if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(64))) {
+		pci_using_dac = 1;
+		if (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) {
+			dev_err(&pcidev->dev, "unable to obtain 64-bit DMA for "
+					"consistent allocations\n");
 			goto err_out_disable_pci;
+		}
+	} else if (pci_set_dma_mask(pcidev, DMA_BIT_MASK(32))) {
+		pci_using_dac = 0;
+		pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
+	} else {
+		dev_err(&pcidev->dev, "no usable DMA configuration\n");
+		goto err_out_disable_pci;
 	}
 
 	err = pci_request_regions(pcidev, DRV_NAME);
-	if (err)
+	if (err) {
+		dev_err(&pcidev->dev, "can't obtain PCI resources\n");
 		goto err_out_disable_pci;
+	}
 
 	pci_set_master(pcidev);
 
@@ -408,6 +415,8 @@
 	adapter = netdev_priv(netdev);
 	adapter->netdev = netdev;
 	adapter->pcidev = pcidev;
+	if (pci_using_dac)
+		netdev->features |= NETIF_F_HIGHDMA;
 
 	mmio_start = pci_resource_start(pcidev, 0);
 	mmio_len = pci_resource_len(pcidev, 0);
@@ -484,7 +493,7 @@
 
 static int slic_entry_open(struct net_device *dev)
 {
-	struct adapter *adapter = (struct adapter *) netdev_priv(dev);
+	struct adapter *adapter = netdev_priv(dev);
 	struct sliccard *card = adapter->card;
 	u32 locked = 0;
 	int status;
@@ -534,7 +543,7 @@
 	struct net_device *dev = pci_get_drvdata(pcidev);
 	u32 mmio_start = 0;
 	uint mmio_len = 0;
-	struct adapter *adapter = (struct adapter *) netdev_priv(dev);
+	struct adapter *adapter = netdev_priv(dev);
 	struct sliccard *card;
 	struct mcast_address *mcaddr, *mlist;
 
@@ -581,7 +590,7 @@
 
 static int slic_entry_halt(struct net_device *dev)
 {
-	struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+	struct adapter *adapter = netdev_priv(dev);
 	struct sliccard *card = adapter->card;
 	__iomem struct slic_regs *slic_regs = adapter->slic_regs;
 
@@ -624,7 +633,7 @@
 
 static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+	struct adapter *adapter = netdev_priv(dev);
 	struct ethtool_cmd edata;
 	struct ethtool_cmd ecmd;
 	u32 data[7];
@@ -649,8 +658,7 @@
 
 			if (copy_from_user(data, rq->ifr_data, 28)) {
 				PRINT_ERROR
-				    ("slic: copy_from_user FAILED getting \
-				     initial simba param\n");
+				    ("slic: copy_from_user FAILED getting initial simba param\n");
 				return -EFAULT;
 			}
 
@@ -665,8 +673,7 @@
 				   (tracemon_request ==
 				    SLIC_DUMP_IN_PROGRESS)) {
 				PRINT_ERROR
-				    ("ATK Diagnostic Trace Dump Requested but \
-				     already in progress... ignore\n");
+				    ("ATK Diagnostic Trace Dump Requested but already in progress... ignore\n");
 			} else {
 				PRINT_ERROR
 				    ("ATK Diagnostic Trace Dump Requested\n");
@@ -784,10 +791,10 @@
 
 #define NORMAL_ETHFRAME     0
 
-static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sliccard *card;
-	struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+	struct adapter *adapter = netdev_priv(dev);
 	struct slic_hostcmd *hcmd = NULL;
 	u32 status = 0;
 	u32 skbtype = NORMAL_ETHFRAME;
@@ -1071,7 +1078,7 @@
 static irqreturn_t slic_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
-	struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+	struct adapter *adapter = netdev_priv(dev);
 	u32 isr;
 
 	if ((adapter->pshmem) && (adapter->pshmem->isr)) {
@@ -1229,22 +1236,21 @@
 
 static struct net_device_stats *slic_get_stats(struct net_device *dev)
 {
-	struct adapter *adapter = (struct adapter *)netdev_priv(dev);
-	struct net_device_stats *stats;
+	struct adapter *adapter = netdev_priv(dev);
 
 	ASSERT(adapter);
-	stats = &adapter->stats;
-	stats->collisions = adapter->slic_stats.iface.xmit_collisions;
-	stats->rx_errors = adapter->slic_stats.iface.rcv_errors;
-	stats->tx_errors = adapter->slic_stats.iface.xmt_errors;
-	stats->rx_missed_errors = adapter->slic_stats.iface.rcv_discards;
-	stats->tx_heartbeat_errors = 0;
-	stats->tx_aborted_errors = 0;
-	stats->tx_window_errors = 0;
-	stats->tx_fifo_errors = 0;
-	stats->rx_frame_errors = 0;
-	stats->rx_length_errors = 0;
-	return &adapter->stats;
+	dev->stats.collisions = adapter->slic_stats.iface.xmit_collisions;
+	dev->stats.rx_errors = adapter->slic_stats.iface.rcv_errors;
+	dev->stats.tx_errors = adapter->slic_stats.iface.xmt_errors;
+	dev->stats.rx_missed_errors = adapter->slic_stats.iface.rcv_discards;
+	dev->stats.tx_heartbeat_errors = 0;
+	dev->stats.tx_aborted_errors = 0;
+	dev->stats.tx_window_errors = 0;
+	dev->stats.tx_fifo_errors = 0;
+	dev->stats.rx_frame_errors = 0;
+	dev->stats.rx_length_errors = 0;
+
+	return &dev->stats;
 }
 
 /*
@@ -1254,13 +1260,11 @@
 static int slic_mcast_add_list(struct adapter *adapter, char *address)
 {
 	struct mcast_address *mcaddr, *mlist;
-	bool equaladdr;
 
 	/* Check to see if it already exists */
 	mlist = adapter->mcastaddrs;
 	while (mlist) {
-		ETHER_EQ_ADDR(mlist->address, address, equaladdr);
-		if (equaladdr)
+		if (!compare_ether_addr(mlist->address, address))
 			return STATUS_SUCCESS;
 		mlist = mlist->next;
 	}
@@ -1360,7 +1364,7 @@
 
 static void slic_mcast_set_list(struct net_device *dev)
 {
-	struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+	struct adapter *adapter = netdev_priv(dev);
 	int status = STATUS_SUCCESS;
 	char *addresses;
 	struct dev_mc_list *mc_list;
@@ -1852,6 +1856,9 @@
 	return 0;
 }
 
+MODULE_FIRMWARE("slicoss/oasisrcvucode.sys");
+MODULE_FIRMWARE("slicoss/gbrcvucode.sys");
+
 static int slic_card_download(struct adapter *adapter)
 {
 	const struct firmware *fw;
@@ -1963,6 +1970,9 @@
 	return STATUS_SUCCESS;
 }
 
+MODULE_FIRMWARE("slicoss/oasisdownload.sys");
+MODULE_FIRMWARE("slicoss/gbdownload.sys");
+
 static void slic_adapter_set_hwaddr(struct adapter *adapter)
 {
 	struct sliccard *card = adapter->card;
@@ -2466,7 +2476,6 @@
 	u32 opts = adapter->macopts;
 	u32 *dhost4 = (u32 *)&ether_frame->ether_dhost[0];
 	u16 *dhost2 = (u16 *)&ether_frame->ether_dhost[4];
-	bool equaladdr;
 
 	if (opts & MAC_PROMISC)
 		return true;
@@ -2490,10 +2499,8 @@
 			struct mcast_address *mcaddr = adapter->mcastaddrs;
 
 			while (mcaddr) {
-				ETHER_EQ_ADDR(mcaddr->address,
-					      ether_frame->ether_dhost,
-					      equaladdr);
-				if (equaladdr) {
+				if (!compare_ether_addr(mcaddr->address,
+							ether_frame->ether_dhost)) {
 					adapter->rcv_multicasts++;
 					adapter->stats.multicast++;
 					return true;
@@ -2515,7 +2522,7 @@
 
 static int slic_mac_set_address(struct net_device *dev, void *ptr)
 {
-	struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+	struct adapter *adapter = netdev_priv(dev);
 	struct sockaddr *addr = ptr;
 
 	if (netif_running(dev))
@@ -2523,6 +2530,9 @@
 	if (!adapter)
 		return -EBUSY;
 
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EINVAL;
+
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 	memcpy(adapter->currmacaddr, addr->sa_data, dev->addr_len);
 
@@ -3960,10 +3970,8 @@
 
 static void slic_debug_adapter_destroy(struct adapter *adapter)
 {
-	if (adapter->debugfs_entry) {
-		debugfs_remove(adapter->debugfs_entry);
-		adapter->debugfs_entry = NULL;
-	}
+	debugfs_remove(adapter->debugfs_entry);
+	adapter->debugfs_entry = NULL;
 }
 
 static void slic_debug_card_create(struct sliccard *card)
diff --git a/drivers/staging/sm7xx/Kconfig b/drivers/staging/sm7xx/Kconfig
index 204dbfc..315102c 100644
--- a/drivers/staging/sm7xx/Kconfig
+++ b/drivers/staging/sm7xx/Kconfig
@@ -6,10 +6,3 @@
 	select FB_CFB_IMAGEBLIT
 	help
 	  Frame Buffer driver for the Silicon Motion SM7XX serial graphic card.
-
-config FB_SM7XX_ACCEL
-	bool "Siliconmotion Acceleration functions (EXPERIMENTAL)"
-	depends on FB_SM7XX && EXPERIMENTAL
-	help
-	  This will compile the Trident frame buffer device with
-	  acceleration functions.
diff --git a/drivers/staging/sm7xx/TODO b/drivers/staging/sm7xx/TODO
index 1f61f5e..a66d9e4 100644
--- a/drivers/staging/sm7xx/TODO
+++ b/drivers/staging/sm7xx/TODO
@@ -1,5 +1,6 @@
 TODO:
 - Dual head support
+- 2D acceleration support
 - use kernel coding style
 - checkpatch.pl clean
 - refine the code and remove unused code
diff --git a/drivers/staging/sm7xx/smtc2d.c b/drivers/staging/sm7xx/smtc2d.c
deleted file mode 100644
index 2fff0a0..0000000
--- a/drivers/staging/sm7xx/smtc2d.c
+++ /dev/null
@@ -1,979 +0,0 @@
-/*
- * Silicon Motion SM7XX 2D drawing engine functions.
- *
- * Copyright (C) 2006 Silicon Motion Technology Corp.
- * Author: Boyod boyod.yang@siliconmotion.com.cn
- *
- * Copyright (C) 2009 Lemote, Inc.
- * Author: Wu Zhangjin, wuzhangjin@gmail.com
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- *
- * Version 0.10.26192.21.01
- * 	- Add PowerPC support
- * 	- Add 2D support for Lynx -
- * Verified on 2.6.19.2
- * 	Boyod.yang  <boyod.yang@siliconmotion.com.cn>
- */
-
-unsigned char smtc_de_busy;
-
-void SMTC_write2Dreg(unsigned long nOffset, unsigned long nData)
-{
-	writel(nData, smtc_2DBaseAddress + nOffset);
-}
-
-unsigned long SMTC_read2Dreg(unsigned long nOffset)
-{
-	return readl(smtc_2DBaseAddress + nOffset);
-}
-
-void SMTC_write2Ddataport(unsigned long nOffset, unsigned long nData)
-{
-	writel(nData, smtc_2Ddataport + nOffset);
-}
-
-/**********************************************************************
- *
- * deInit
- *
- * Purpose
- *    Drawing engine initialization.
- *
- **********************************************************************/
-
-void deInit(unsigned int nModeWidth, unsigned int nModeHeight,
-		unsigned int bpp)
-{
-	/* Get current power configuration. */
-	unsigned char clock;
-	clock = smtc_seqr(0x21);
-
-	/* initialize global 'mutex lock' variable */
-	smtc_de_busy = 0;
-
-	/* Enable 2D Drawing Engine */
-	smtc_seqw(0x21, clock & 0xF8);
-
-	SMTC_write2Dreg(DE_CLIP_TL,
-			FIELD_VALUE(0, DE_CLIP_TL, TOP, 0) |
-			FIELD_SET(0, DE_CLIP_TL, STATUS, DISABLE) |
-			FIELD_SET(0, DE_CLIP_TL, INHIBIT, OUTSIDE) |
-			FIELD_VALUE(0, DE_CLIP_TL, LEFT, 0));
-
-	if (bpp >= 24) {
-		SMTC_write2Dreg(DE_PITCH,
-				FIELD_VALUE(0, DE_PITCH, DESTINATION,
-					    nModeWidth * 3) | FIELD_VALUE(0,
-								  DE_PITCH,
-								  SOURCE,
-								  nModeWidth
-								  * 3));
-	} else {
-		SMTC_write2Dreg(DE_PITCH,
-				FIELD_VALUE(0, DE_PITCH, DESTINATION,
-					    nModeWidth) | FIELD_VALUE(0,
-							      DE_PITCH,
-							      SOURCE,
-							      nModeWidth));
-	}
-
-	SMTC_write2Dreg(DE_WINDOW_WIDTH,
-			FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
-				    nModeWidth) | FIELD_VALUE(0,
-							      DE_WINDOW_WIDTH,
-							      SOURCE,
-							      nModeWidth));
-
-	switch (bpp) {
-	case 8:
-		SMTC_write2Dreg(DE_STRETCH_FORMAT,
-				FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
-					  NORMAL) | FIELD_VALUE(0,
-							DE_STRETCH_FORMAT,
-							PATTERN_Y,
-							0) |
-				FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
-				    0) | FIELD_SET(0, DE_STRETCH_FORMAT,
-						   PIXEL_FORMAT,
-						   8) | FIELD_SET(0,
-							  DE_STRETCH_FORMAT,
-							  ADDRESSING,
-							  XY) |
-				FIELD_VALUE(0, DE_STRETCH_FORMAT,
-					SOURCE_HEIGHT, 3));
-		break;
-	case 24:
-		SMTC_write2Dreg(DE_STRETCH_FORMAT,
-				FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
-					  NORMAL) | FIELD_VALUE(0,
-							DE_STRETCH_FORMAT,
-							PATTERN_Y,
-							0) |
-				FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
-				    0) | FIELD_SET(0, DE_STRETCH_FORMAT,
-							   PIXEL_FORMAT,
-							   24) | FIELD_SET(0,
-							   DE_STRETCH_FORMAT,
-							   ADDRESSING,
-							   XY) |
-				FIELD_VALUE(0, DE_STRETCH_FORMAT,
-					SOURCE_HEIGHT, 3));
-		break;
-	case 16:
-	default:
-		SMTC_write2Dreg(DE_STRETCH_FORMAT,
-				FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
-					  NORMAL) | FIELD_VALUE(0,
-							DE_STRETCH_FORMAT,
-							PATTERN_Y,
-							0) |
-				FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
-				    0) | FIELD_SET(0, DE_STRETCH_FORMAT,
-							   PIXEL_FORMAT,
-							   16) | FIELD_SET(0,
-							   DE_STRETCH_FORMAT,
-							   ADDRESSING,
-							   XY) |
-				FIELD_VALUE(0, DE_STRETCH_FORMAT,
-					SOURCE_HEIGHT, 3));
-		break;
-	}
-
-	SMTC_write2Dreg(DE_MASKS,
-			FIELD_VALUE(0, DE_MASKS, BYTE_MASK, 0xFFFF) |
-			FIELD_VALUE(0, DE_MASKS, BIT_MASK, 0xFFFF));
-	SMTC_write2Dreg(DE_COLOR_COMPARE_MASK,
-			FIELD_VALUE(0, DE_COLOR_COMPARE_MASK, MASKS, \
-				0xFFFFFF));
-	SMTC_write2Dreg(DE_COLOR_COMPARE,
-			FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, 0xFFFFFF));
-}
-
-void deVerticalLine(unsigned long dst_base,
-		    unsigned long dst_pitch,
-		    unsigned long nX,
-		    unsigned long nY,
-		    unsigned long dst_height, unsigned long nColor)
-{
-	deWaitForNotBusy();
-
-	SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
-			FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
-				    dst_base));
-
-	SMTC_write2Dreg(DE_PITCH,
-			FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
-			FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
-
-	SMTC_write2Dreg(DE_WINDOW_WIDTH,
-			FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
-			    dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH,
-						     SOURCE,
-						     dst_pitch));
-
-	SMTC_write2Dreg(DE_FOREGROUND,
-			FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
-
-	SMTC_write2Dreg(DE_DESTINATION,
-			FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
-			FIELD_VALUE(0, DE_DESTINATION, X, nX) |
-			FIELD_VALUE(0, DE_DESTINATION, Y, nY));
-
-	SMTC_write2Dreg(DE_DIMENSION,
-			FIELD_VALUE(0, DE_DIMENSION, X, 1) |
-			FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
-
-	SMTC_write2Dreg(DE_CONTROL,
-			FIELD_SET(0, DE_CONTROL, STATUS, START) |
-			FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
-			FIELD_SET(0, DE_CONTROL, MAJOR, Y) |
-			FIELD_SET(0, DE_CONTROL, STEP_X, NEGATIVE) |
-			FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) |
-			FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
-			FIELD_SET(0, DE_CONTROL, COMMAND, SHORT_STROKE) |
-			FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
-			FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
-
-	smtc_de_busy = 1;
-}
-
-void deHorizontalLine(unsigned long dst_base,
-		      unsigned long dst_pitch,
-		      unsigned long nX,
-		      unsigned long nY,
-		      unsigned long dst_width, unsigned long nColor)
-{
-	deWaitForNotBusy();
-
-	SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
-			FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
-				    dst_base));
-
-	SMTC_write2Dreg(DE_PITCH,
-			FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
-			FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
-
-	SMTC_write2Dreg(DE_WINDOW_WIDTH,
-			FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
-			    dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH,
-						     SOURCE,
-						     dst_pitch));
-	SMTC_write2Dreg(DE_FOREGROUND,
-			FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
-	SMTC_write2Dreg(DE_DESTINATION,
-			FIELD_SET(0, DE_DESTINATION, WRAP,
-			  DISABLE) | FIELD_VALUE(0, DE_DESTINATION, X,
-						 nX) | FIELD_VALUE(0,
-							   DE_DESTINATION,
-							   Y,
-							   nY));
-	SMTC_write2Dreg(DE_DIMENSION,
-			FIELD_VALUE(0, DE_DIMENSION, X,
-			    dst_width) | FIELD_VALUE(0, DE_DIMENSION,
-						     Y_ET, 1));
-	SMTC_write2Dreg(DE_CONTROL,
-		FIELD_SET(0, DE_CONTROL, STATUS, START) | FIELD_SET(0,
-							    DE_CONTROL,
-							    DIRECTION,
-							    RIGHT_TO_LEFT)
-		| FIELD_SET(0, DE_CONTROL, MAJOR, X) | FIELD_SET(0,
-							 DE_CONTROL,
-							 STEP_X,
-							 POSITIVE)
-		| FIELD_SET(0, DE_CONTROL, STEP_Y,
-			    NEGATIVE) | FIELD_SET(0, DE_CONTROL,
-						  LAST_PIXEL,
-						  OFF) | FIELD_SET(0,
-							   DE_CONTROL,
-							   COMMAND,
-							   SHORT_STROKE)
-		| FIELD_SET(0, DE_CONTROL, ROP_SELECT,
-			    ROP2) | FIELD_VALUE(0, DE_CONTROL, ROP,
-						0x0C));
-
-	smtc_de_busy = 1;
-}
-
-void deLine(unsigned long dst_base,
-	    unsigned long dst_pitch,
-	    unsigned long nX1,
-	    unsigned long nY1,
-	    unsigned long nX2, unsigned long nY2, unsigned long nColor)
-{
-	unsigned long nCommand =
-	    FIELD_SET(0, DE_CONTROL, STATUS, START) |
-	    FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
-	    FIELD_SET(0, DE_CONTROL, MAJOR, X) |
-	    FIELD_SET(0, DE_CONTROL, STEP_X, POSITIVE) |
-	    FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) |
-	    FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
-	    FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
-	    FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C);
-	unsigned long DeltaX;
-	unsigned long DeltaY;
-
-	/* Calculate delta X */
-	if (nX1 <= nX2)
-		DeltaX = nX2 - nX1;
-	else {
-		DeltaX = nX1 - nX2;
-		nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_X, NEGATIVE);
-	}
-
-	/* Calculate delta Y */
-	if (nY1 <= nY2)
-		DeltaY = nY2 - nY1;
-	else {
-		DeltaY = nY1 - nY2;
-		nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_Y, NEGATIVE);
-	}
-
-	/* Determine the major axis */
-	if (DeltaX < DeltaY)
-		nCommand = FIELD_SET(nCommand, DE_CONTROL, MAJOR, Y);
-
-	/* Vertical line? */
-	if (nX1 == nX2)
-		deVerticalLine(dst_base, dst_pitch, nX1, nY1, DeltaY, nColor);
-
-	/* Horizontal line? */
-	else if (nY1 == nY2)
-		deHorizontalLine(dst_base, dst_pitch, nX1, nY1, \
-				DeltaX, nColor);
-
-	/* Diagonal line? */
-	else if (DeltaX == DeltaY) {
-		deWaitForNotBusy();
-
-		SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
-				FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE,
-					    ADDRESS, dst_base));
-
-		SMTC_write2Dreg(DE_PITCH,
-				FIELD_VALUE(0, DE_PITCH, DESTINATION,
-					    dst_pitch) | FIELD_VALUE(0,
-							     DE_PITCH,
-							     SOURCE,
-							     dst_pitch));
-
-		SMTC_write2Dreg(DE_WINDOW_WIDTH,
-				FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
-					    dst_pitch) | FIELD_VALUE(0,
-							     DE_WINDOW_WIDTH,
-							     SOURCE,
-							     dst_pitch));
-
-		SMTC_write2Dreg(DE_FOREGROUND,
-				FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
-
-		SMTC_write2Dreg(DE_DESTINATION,
-				FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
-				FIELD_VALUE(0, DE_DESTINATION, X, 1) |
-				FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
-
-		SMTC_write2Dreg(DE_DIMENSION,
-				FIELD_VALUE(0, DE_DIMENSION, X, 1) |
-				FIELD_VALUE(0, DE_DIMENSION, Y_ET, DeltaX));
-
-		SMTC_write2Dreg(DE_CONTROL,
-				FIELD_SET(nCommand, DE_CONTROL, COMMAND,
-					  SHORT_STROKE));
-	}
-
-	/* Generic line */
-	else {
-		unsigned int k1, k2, et, w;
-		if (DeltaX < DeltaY) {
-			k1 = 2 * DeltaX;
-			et = k1 - DeltaY;
-			k2 = et - DeltaY;
-			w = DeltaY + 1;
-		} else {
-			k1 = 2 * DeltaY;
-			et = k1 - DeltaX;
-			k2 = et - DeltaX;
-			w = DeltaX + 1;
-		}
-
-		deWaitForNotBusy();
-
-		SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
-				FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE,
-					    ADDRESS, dst_base));
-
-		SMTC_write2Dreg(DE_PITCH,
-				FIELD_VALUE(0, DE_PITCH, DESTINATION,
-					    dst_pitch) | FIELD_VALUE(0,
-							     DE_PITCH,
-							     SOURCE,
-							     dst_pitch));
-
-		SMTC_write2Dreg(DE_WINDOW_WIDTH,
-				FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
-					    dst_pitch) | FIELD_VALUE(0,
-							     DE_WINDOW_WIDTH,
-							     SOURCE,
-							     dst_pitch));
-
-		SMTC_write2Dreg(DE_FOREGROUND,
-				FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
-
-		SMTC_write2Dreg(DE_SOURCE,
-				FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
-				FIELD_VALUE(0, DE_SOURCE, X_K1, k1) |
-				FIELD_VALUE(0, DE_SOURCE, Y_K2, k2));
-
-		SMTC_write2Dreg(DE_DESTINATION,
-				FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
-				FIELD_VALUE(0, DE_DESTINATION, X, nX1) |
-				FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
-
-		SMTC_write2Dreg(DE_DIMENSION,
-				FIELD_VALUE(0, DE_DIMENSION, X, w) |
-				FIELD_VALUE(0, DE_DIMENSION, Y_ET, et));
-
-		SMTC_write2Dreg(DE_CONTROL,
-				FIELD_SET(nCommand, DE_CONTROL, COMMAND,
-					  LINE_DRAW));
-	}
-
-	smtc_de_busy = 1;
-}
-
-void deFillRect(unsigned long dst_base,
-		unsigned long dst_pitch,
-		unsigned long dst_X,
-		unsigned long dst_Y,
-		unsigned long dst_width,
-		unsigned long dst_height, unsigned long nColor)
-{
-	deWaitForNotBusy();
-
-	SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
-			FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
-				    dst_base));
-
-	if (dst_pitch) {
-		SMTC_write2Dreg(DE_PITCH,
-				FIELD_VALUE(0, DE_PITCH, DESTINATION,
-					    dst_pitch) | FIELD_VALUE(0,
-							     DE_PITCH,
-							     SOURCE,
-							     dst_pitch));
-
-		SMTC_write2Dreg(DE_WINDOW_WIDTH,
-				FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
-					    dst_pitch) | FIELD_VALUE(0,
-							     DE_WINDOW_WIDTH,
-							     SOURCE,
-							     dst_pitch));
-	}
-
-	SMTC_write2Dreg(DE_FOREGROUND,
-			FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
-
-	SMTC_write2Dreg(DE_DESTINATION,
-			FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
-			FIELD_VALUE(0, DE_DESTINATION, X, dst_X) |
-			FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y));
-
-	SMTC_write2Dreg(DE_DIMENSION,
-			FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
-			FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
-
-	SMTC_write2Dreg(DE_CONTROL,
-			FIELD_SET(0, DE_CONTROL, STATUS, START) |
-			FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
-			FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
-			FIELD_SET(0, DE_CONTROL, COMMAND, RECTANGLE_FILL) |
-			FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
-			FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
-
-	smtc_de_busy = 1;
-}
-
-/**********************************************************************
- *
- * deRotatePattern
- *
- * Purpose
- *    Rotate the given pattern if necessary
- *
- * Parameters
- *    [in]
- *	   pPattern  - Pointer to DE_SURFACE structure containing
- *		       pattern attributes
- *	   patternX  - X position (0-7) of pattern origin
- *	   patternY  - Y position (0-7) of pattern origin
- *
- *    [out]
- *	   pattern_dstaddr - Pointer to pre-allocated buffer containing
- *	   rotated pattern
- *
- **********************************************************************/
-void deRotatePattern(unsigned char *pattern_dstaddr,
-		     unsigned long pattern_src_addr,
-		     unsigned long pattern_BPP,
-		     unsigned long pattern_stride, int patternX, int patternY)
-{
-	unsigned int i;
-	unsigned long pattern[PATTERN_WIDTH * PATTERN_HEIGHT];
-	unsigned int x, y;
-	unsigned char *pjPatByte;
-
-	if (pattern_dstaddr != NULL) {
-		deWaitForNotBusy();
-
-		if (patternX || patternY) {
-			/* Rotate pattern */
-			pjPatByte = (unsigned char *)pattern;
-
-			switch (pattern_BPP) {
-			case 8:
-				{
-					for (y = 0; y < 8; y++) {
-						unsigned char *pjBuffer =
-						    pattern_dstaddr +
-						    ((patternY + y) & 7) * 8;
-						for (x = 0; x < 8; x++) {
-							pjBuffer[(patternX +
-								  x) & 7] =
-							    pjPatByte[x];
-						}
-						pjPatByte += pattern_stride;
-					}
-					break;
-				}
-
-			case 16:
-				{
-					for (y = 0; y < 8; y++) {
-						unsigned short *pjBuffer =
-						    (unsigned short *)
-						    pattern_dstaddr +
-						    ((patternY + y) & 7) * 8;
-						for (x = 0; x < 8; x++) {
-							pjBuffer[(patternX +
-								  x) & 7] =
-							    ((unsigned short *)
-							     pjPatByte)[x];
-						}
-						pjPatByte += pattern_stride;
-					}
-					break;
-				}
-
-			case 32:
-				{
-					for (y = 0; y < 8; y++) {
-						unsigned long *pjBuffer =
-						    (unsigned long *)
-						    pattern_dstaddr +
-						    ((patternY + y) & 7) * 8;
-						for (x = 0; x < 8; x++) {
-							pjBuffer[(patternX +
-								  x) & 7] =
-							    ((unsigned long *)
-							     pjPatByte)[x];
-						}
-						pjPatByte += pattern_stride;
-					}
-					break;
-				}
-			}
-		} else {
-			/*Don't rotate,just copy pattern into pattern_dstaddr*/
-			for (i = 0; i < (pattern_BPP * 2); i++) {
-				((unsigned long *)pattern_dstaddr)[i] =
-				    pattern[i];
-			}
-		}
-
-	}
-}
-
-/**********************************************************************
- *
- * deCopy
- *
- * Purpose
- *    Copy a rectangular area of the source surface to a destination surface
- *
- * Remarks
- *    Source bitmap must have the same color depth (BPP) as the destination
- *    bitmap.
- *
-**********************************************************************/
-void deCopy(unsigned long dst_base,
-	    unsigned long dst_pitch,
-	    unsigned long dst_BPP,
-	    unsigned long dst_X,
-	    unsigned long dst_Y,
-	    unsigned long dst_width,
-	    unsigned long dst_height,
-	    unsigned long src_base,
-	    unsigned long src_pitch,
-	    unsigned long src_X,
-	    unsigned long src_Y, pTransparent pTransp, unsigned char nROP2)
-{
-	unsigned long nDirection = 0;
-	unsigned long nTransparent = 0;
-	/* Direction of ROP2 operation:
-	 * 1 = Left to Right,
-	 * (-1) = Right to Left
-	 */
-	unsigned long opSign = 1;
-	/* xWidth is in pixels */
-	unsigned long xWidth = 192 / (dst_BPP / 8);
-	unsigned long de_ctrl = 0;
-
-	deWaitForNotBusy();
-
-	SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
-			FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
-				    dst_base));
-
-	SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE,
-			FIELD_VALUE(0, DE_WINDOW_SOURCE_BASE, ADDRESS,
-				    src_base));
-
-	if (dst_pitch && src_pitch) {
-		SMTC_write2Dreg(DE_PITCH,
-			FIELD_VALUE(0, DE_PITCH, DESTINATION,
-				    dst_pitch) | FIELD_VALUE(0,
-						     DE_PITCH,
-						     SOURCE,
-						     src_pitch));
-
-		SMTC_write2Dreg(DE_WINDOW_WIDTH,
-			FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
-				    dst_pitch) | FIELD_VALUE(0,
-						     DE_WINDOW_WIDTH,
-						     SOURCE,
-						     src_pitch));
-	}
-
-	/* Set transparent bits if necessary */
-	if (pTransp != NULL) {
-		nTransparent =
-		    pTransp->match | pTransp->select | pTransp->control;
-
-		/* Set color compare register */
-		SMTC_write2Dreg(DE_COLOR_COMPARE,
-				FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR,
-					    pTransp->color));
-	}
-
-	/* Determine direction of operation */
-	if (src_Y < dst_Y) {
-		/* +----------+
-		   |S         |
-		   |          +----------+
-		   |          |      |   |
-		   |          |      |   |
-		   +---|------+      |
-		   |               D |
-		   +----------+ */
-
-		nDirection = BOTTOM_TO_TOP;
-	} else if (src_Y > dst_Y) {
-		/* +----------+
-		   |D         |
-		   |          +----------+
-		   |          |      |   |
-		   |          |      |   |
-		   +---|------+      |
-		   |               S |
-		   +----------+ */
-
-		nDirection = TOP_TO_BOTTOM;
-	} else {
-		/* src_Y == dst_Y */
-
-		if (src_X <= dst_X) {
-			/* +------+---+------+
-			   |S     |   |     D|
-			   |      |   |      |
-			   |      |   |      |
-			   |      |   |      |
-			   +------+---+------+ */
-
-			nDirection = RIGHT_TO_LEFT;
-		} else {
-			/* src_X > dst_X */
-
-			/* +------+---+------+
-			   |D     |   |     S|
-			   |      |   |      |
-			   |      |   |      |
-			   |      |   |      |
-			   +------+---+------+ */
-
-			nDirection = LEFT_TO_RIGHT;
-		}
-	}
-
-	if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
-		src_X += dst_width - 1;
-		src_Y += dst_height - 1;
-		dst_X += dst_width - 1;
-		dst_Y += dst_height - 1;
-		opSign = (-1);
-	}
-
-	if (dst_BPP >= 24) {
-		src_X *= 3;
-		src_Y *= 3;
-		dst_X *= 3;
-		dst_Y *= 3;
-		dst_width *= 3;
-		if ((nDirection == BOTTOM_TO_TOP)
-		    || (nDirection == RIGHT_TO_LEFT)) {
-			src_X += 2;
-			dst_X += 2;
-		}
-	}
-
-	/* Workaround for 192 byte hw bug */
-	if ((nROP2 != 0x0C) && ((dst_width * (dst_BPP / 8)) >= 192)) {
-		/*
-		 * Perform the ROP2 operation in chunks of (xWidth *
-		 * dst_height)
-		 */
-		while (1) {
-			deWaitForNotBusy();
-
-			SMTC_write2Dreg(DE_SOURCE,
-				FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
-				FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) |
-				FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y));
-
-			SMTC_write2Dreg(DE_DESTINATION,
-				FIELD_SET(0, DE_DESTINATION, WRAP,
-				  DISABLE) | FIELD_VALUE(0,
-							 DE_DESTINATION,
-							 X,
-							 dst_X)
-			| FIELD_VALUE(0, DE_DESTINATION, Y,
-						      dst_Y));
-
-			SMTC_write2Dreg(DE_DIMENSION,
-				FIELD_VALUE(0, DE_DIMENSION, X,
-				    xWidth) | FIELD_VALUE(0,
-							  DE_DIMENSION,
-							  Y_ET,
-							  dst_height));
-
-			de_ctrl =
-			    FIELD_VALUE(0, DE_CONTROL, ROP,
-				nROP2) | nTransparent | FIELD_SET(0,
-							  DE_CONTROL,
-							  ROP_SELECT,
-							  ROP2)
-			    | FIELD_SET(0, DE_CONTROL, COMMAND,
-				BITBLT) | ((nDirection ==
-					    1) ? FIELD_SET(0,
-						   DE_CONTROL,
-						   DIRECTION,
-						   RIGHT_TO_LEFT)
-					   : FIELD_SET(0, DE_CONTROL,
-					       DIRECTION,
-					       LEFT_TO_RIGHT)) |
-			    FIELD_SET(0, DE_CONTROL, STATUS, START);
-
-			SMTC_write2Dreg(DE_CONTROL, de_ctrl);
-
-			src_X += (opSign * xWidth);
-			dst_X += (opSign * xWidth);
-			dst_width -= xWidth;
-
-			if (dst_width <= 0) {
-				/* ROP2 operation is complete */
-				break;
-			}
-
-			if (xWidth > dst_width)
-				xWidth = dst_width;
-		}
-	} else {
-		deWaitForNotBusy();
-		SMTC_write2Dreg(DE_SOURCE,
-			FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
-			FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) |
-			FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y));
-
-		SMTC_write2Dreg(DE_DESTINATION,
-			FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
-			FIELD_VALUE(0, DE_DESTINATION, X, dst_X) |
-			FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y));
-
-		SMTC_write2Dreg(DE_DIMENSION,
-			FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
-			FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
-
-		de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, nROP2) |
-		    nTransparent |
-		    FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
-		    FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
-		    ((nDirection == 1) ? FIELD_SET(0, DE_CONTROL, DIRECTION,
-						   RIGHT_TO_LEFT)
-		     : FIELD_SET(0, DE_CONTROL, DIRECTION,
-				 LEFT_TO_RIGHT)) | FIELD_SET(0, DE_CONTROL,
-							     STATUS, START);
-		SMTC_write2Dreg(DE_CONTROL, de_ctrl);
-	}
-
-	smtc_de_busy = 1;
-}
-
-/*
- * This function sets the pixel format that will apply to the 2D Engine.
- */
-void deSetPixelFormat(unsigned long bpp)
-{
-	unsigned long de_format;
-
-	de_format = SMTC_read2Dreg(DE_STRETCH_FORMAT);
-
-	switch (bpp) {
-	case 8:
-		de_format =
-		    FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 8);
-		break;
-	default:
-	case 16:
-		de_format =
-		    FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 16);
-		break;
-	case 32:
-		de_format =
-		    FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 32);
-		break;
-	}
-
-	SMTC_write2Dreg(DE_STRETCH_FORMAT, de_format);
-}
-
-/*
- * System memory to Video memory monochrome expansion.
- *
- * Source is monochrome image in system memory.  This function expands the
- * monochrome data to color image in video memory.
- */
-
-long deSystemMem2VideoMemMonoBlt(const char *pSrcbuf,
-				 long srcDelta,
-				 unsigned long startBit,
-				 unsigned long dBase,
-				 unsigned long dPitch,
-				 unsigned long bpp,
-				 unsigned long dx, unsigned long dy,
-				 unsigned long width, unsigned long height,
-				 unsigned long fColor,
-				 unsigned long bColor,
-				 unsigned long rop2) {
-	unsigned long bytePerPixel;
-	unsigned long ulBytesPerScan;
-	unsigned long ul4BytesPerScan;
-	unsigned long ulBytesRemain;
-	unsigned long de_ctrl = 0;
-	unsigned char ajRemain[4];
-	long i, j;
-
-	bytePerPixel = bpp / 8;
-
-	/* Just make sure the start bit is within legal range */
-	startBit &= 7;
-
-	ulBytesPerScan = (width + startBit + 7) / 8;
-	ul4BytesPerScan = ulBytesPerScan & ~3;
-	ulBytesRemain = ulBytesPerScan & 3;
-
-	if (smtc_de_busy)
-		deWaitForNotBusy();
-
-	/*
-	 * 2D Source Base.  Use 0 for HOST Blt.
-	 */
-
-	SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE, 0);
-
-	/*
-	 * 2D Destination Base.
-	 *
-	 * It is an address offset (128 bit aligned) from the beginning of
-	 * frame buffer.
-	 */
-
-	SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, dBase);
-
-	if (dPitch) {
-
-		/*
-		 * Program pitch (distance between the 1st points of two
-		 * adjacent lines).
-		 *
-		 * Note that input pitch is BYTE value, but the 2D Pitch
-		 * register uses pixel values. Need Byte to pixel convertion.
-		 */
-
-		SMTC_write2Dreg(DE_PITCH,
-			FIELD_VALUE(0, DE_PITCH, DESTINATION,
-			    dPitch /
-			    bytePerPixel) | FIELD_VALUE(0,
-							DE_PITCH,
-							SOURCE,
-							dPitch /
-							bytePerPixel));
-
-		/* Screen Window width in Pixels.
-		 *
-		 * 2D engine uses this value to calculate the linear address in
-		 * frame buffer for a given point.
-		 */
-
-		SMTC_write2Dreg(DE_WINDOW_WIDTH,
-			FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
-			    (dPitch /
-			     bytePerPixel)) | FIELD_VALUE(0,
-							  DE_WINDOW_WIDTH,
-							  SOURCE,
-							  (dPitch
-							   /
-							   bytePerPixel)));
-	}
-	/* Note: For 2D Source in Host Write, only X_K1 field is needed, and
-	 * Y_K2 field is not used. For mono bitmap, use startBit for X_K1.
-	 */
-
-	SMTC_write2Dreg(DE_SOURCE,
-			FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
-			FIELD_VALUE(0, DE_SOURCE, X_K1, startBit) |
-			FIELD_VALUE(0, DE_SOURCE, Y_K2, 0));
-
-	SMTC_write2Dreg(DE_DESTINATION,
-			FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
-			FIELD_VALUE(0, DE_DESTINATION, X, dx) |
-			FIELD_VALUE(0, DE_DESTINATION, Y, dy));
-
-	SMTC_write2Dreg(DE_DIMENSION,
-			FIELD_VALUE(0, DE_DIMENSION, X, width) |
-			FIELD_VALUE(0, DE_DIMENSION, Y_ET, height));
-
-	SMTC_write2Dreg(DE_FOREGROUND, fColor);
-	SMTC_write2Dreg(DE_BACKGROUND, bColor);
-
-	if (bpp)
-		deSetPixelFormat(bpp);
-	/* Set the pixel format of the destination */
-
-	de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
-	    FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
-	    FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) |
-	    FIELD_SET(0, DE_CONTROL, HOST, MONO) |
-	    FIELD_SET(0, DE_CONTROL, STATUS, START);
-
-	SMTC_write2Dreg(DE_CONTROL, de_ctrl | deGetTransparency());
-
-	/* Write MONO data (line by line) to 2D Engine data port */
-	for (i = 0; i < height; i++) {
-		/* For each line, send the data in chunks of 4 bytes */
-		for (j = 0; j < (ul4BytesPerScan / 4); j++)
-			SMTC_write2Ddataport(0,
-					     *(unsigned long *)(pSrcbuf +
-								(j * 4)));
-
-		if (ulBytesRemain) {
-			memcpy(ajRemain, pSrcbuf + ul4BytesPerScan,
-			       ulBytesRemain);
-			SMTC_write2Ddataport(0, *(unsigned long *)ajRemain);
-		}
-
-		pSrcbuf += srcDelta;
-	}
-	smtc_de_busy = 1;
-
-	return 0;
-}
-
-/*
- * This function gets the transparency status from DE_CONTROL register.
- * It returns a double word with the transparent fields properly set,
- * while other fields are 0.
- */
-unsigned long deGetTransparency(void)
-{
-	unsigned long de_ctrl;
-
-	de_ctrl = SMTC_read2Dreg(DE_CONTROL);
-
-	de_ctrl &=
-	    FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
-	    FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT) |
-	    FIELD_MASK(DE_CONTROL_TRANSPARENCY);
-
-	return de_ctrl;
-}
diff --git a/drivers/staging/sm7xx/smtc2d.h b/drivers/staging/sm7xx/smtc2d.h
deleted file mode 100644
index 02b4fa2..0000000
--- a/drivers/staging/sm7xx/smtc2d.h
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Silicon Motion SM712 2D drawing engine functions.
- *
- * Copyright (C) 2006 Silicon Motion Technology Corp.
- * Author: Ge Wang, gewang@siliconmotion.com
- *
- * Copyright (C) 2009 Lemote, Inc.
- * Author: Wu Zhangjin, wuzhangjin@gmail.com
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#ifndef NULL
-#define NULL	 0
-#endif
-
-/* Internal macros */
-
-#define _F_START(f)		(0 ? f)
-#define _F_END(f)		(1 ? f)
-#define _F_SIZE(f)		(1 + _F_END(f) - _F_START(f))
-#define _F_MASK(f)		(((1ULL << _F_SIZE(f)) - 1) << _F_START(f))
-#define _F_NORMALIZE(v, f)	(((v) & _F_MASK(f)) >> _F_START(f))
-#define _F_DENORMALIZE(v, f)	(((v) << _F_START(f)) & _F_MASK(f))
-
-/* Global macros */
-
-#define FIELD_GET(x, reg, field) \
-( \
-    _F_NORMALIZE((x), reg ## _ ## field) \
-)
-
-#define FIELD_SET(x, reg, field, value) \
-( \
-    (x & ~_F_MASK(reg ## _ ## field)) \
-    | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
-)
-
-#define FIELD_VALUE(x, reg, field, value) \
-( \
-    (x & ~_F_MASK(reg ## _ ## field)) \
-    | _F_DENORMALIZE(value, reg ## _ ## field) \
-)
-
-#define FIELD_CLEAR(reg, field) \
-( \
-    ~_F_MASK(reg ## _ ## field) \
-)
-
-/* Field Macros                        */
-
-#define FIELD_START(field)	(0 ? field)
-#define FIELD_END(field)	(1 ? field)
-#define FIELD_SIZE(field) \
-	(1 + FIELD_END(field) - FIELD_START(field))
-
-#define FIELD_MASK(field) \
-	(((1 << (FIELD_SIZE(field)-1)) \
-	| ((1 << (FIELD_SIZE(field)-1)) - 1)) \
-	<< FIELD_START(field))
-
-#define FIELD_NORMALIZE(reg, field) \
-	(((reg) & FIELD_MASK(field)) >> FIELD_START(field))
-
-#define FIELD_DENORMALIZE(field, value) \
-	(((value) << FIELD_START(field)) & FIELD_MASK(field))
-
-#define FIELD_INIT(reg, field, value) \
-	FIELD_DENORMALIZE(reg ## _ ## field, \
-		reg ## _ ## field ## _ ## value)
-
-#define FIELD_INIT_VAL(reg, field, value) \
-	(FIELD_DENORMALIZE(reg ## _ ## field, value))
-
-#define FIELD_VAL_SET(x, r, f, v) ({ \
-	x = (x & ~FIELD_MASK(r ## _ ## f)) \
-	| FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v) \
-})
-
-#define RGB(r, g, b)	((unsigned long)(((r) << 16) | ((g) << 8) | (b)))
-
-/* Transparent info definition */
-typedef struct {
-	unsigned long match;	/* Matching pixel is OPAQUE/TRANSPARENT */
-	unsigned long select;	/* Transparency controlled by SRC/DST */
-	unsigned long control;	/* ENABLE/DISABLE transparency */
-	unsigned long color;	/* Transparent color */
-} Transparent, *pTransparent;
-
-#define PIXEL_DEPTH_1_BP	0	/* 1 bit per pixel */
-#define PIXEL_DEPTH_8_BPP	1	/* 8 bits per pixel */
-#define PIXEL_DEPTH_16_BPP	2	/* 16 bits per pixel */
-#define PIXEL_DEPTH_32_BPP	3	/* 32 bits per pixel */
-#define PIXEL_DEPTH_YUV422	8	/* 16 bits per pixel YUV422 */
-#define PIXEL_DEPTH_YUV420	9	/* 16 bits per pixel YUV420 */
-
-#define PATTERN_WIDTH		8
-#define PATTERN_HEIGHT		8
-
-#define	TOP_TO_BOTTOM		0
-#define	BOTTOM_TO_TOP		1
-#define RIGHT_TO_LEFT		BOTTOM_TO_TOP
-#define LEFT_TO_RIGHT		TOP_TO_BOTTOM
-
-/* Constants used in Transparent structure */
-#define MATCH_OPAQUE		0x00000000
-#define MATCH_TRANSPARENT	0x00000400
-#define SOURCE			0x00000000
-#define DESTINATION		0x00000200
-
-/* 2D registers. */
-
-#define	DE_SOURCE			0x000000
-#define	DE_SOURCE_WRAP			31 : 31
-#define	DE_SOURCE_WRAP_DISABLE		0
-#define	DE_SOURCE_WRAP_ENABLE		1
-#define	DE_SOURCE_X_K1			29 : 16
-#define	DE_SOURCE_Y_K2			15 : 0
-
-#define	DE_DESTINATION			0x000004
-#define	DE_DESTINATION_WRAP		31 : 31
-#define	DE_DESTINATION_WRAP_DISABLE	0
-#define	DE_DESTINATION_WRAP_ENABLE	1
-#define	DE_DESTINATION_X		28 : 16
-#define	DE_DESTINATION_Y		15 : 0
-
-#define	DE_DIMENSION			0x000008
-#define	DE_DIMENSION_X			28 : 16
-#define	DE_DIMENSION_Y_ET		15 : 0
-
-#define	DE_CONTROL			0x00000C
-#define	DE_CONTROL_STATUS		31 : 31
-#define	DE_CONTROL_STATUS_STOP		0
-#define	DE_CONTROL_STATUS_START		1
-#define	DE_CONTROL_PATTERN		30 : 30
-#define	DE_CONTROL_PATTERN_MONO		0
-#define	DE_CONTROL_PATTERN_COLOR	1
-#define	DE_CONTROL_UPDATE_DESTINATION_X		29 : 29
-#define	DE_CONTROL_UPDATE_DESTINATION_X_DISABLE	0
-#define	DE_CONTROL_UPDATE_DESTINATION_X_ENABLE	1
-#define	DE_CONTROL_QUICK_START			28 : 28
-#define	DE_CONTROL_QUICK_START_DISABLE		0
-#define	DE_CONTROL_QUICK_START_ENABLE		1
-#define	DE_CONTROL_DIRECTION			27 : 27
-#define	DE_CONTROL_DIRECTION_LEFT_TO_RIGHT	0
-#define	DE_CONTROL_DIRECTION_RIGHT_TO_LEFT	1
-#define	DE_CONTROL_MAJOR			26 : 26
-#define	DE_CONTROL_MAJOR_X			0
-#define	DE_CONTROL_MAJOR_Y			1
-#define	DE_CONTROL_STEP_X			25 : 25
-#define	DE_CONTROL_STEP_X_POSITIVE		1
-#define	DE_CONTROL_STEP_X_NEGATIVE		0
-#define	DE_CONTROL_STEP_Y			24 : 24
-#define	DE_CONTROL_STEP_Y_POSITIVE		1
-#define	DE_CONTROL_STEP_Y_NEGATIVE		0
-#define	DE_CONTROL_STRETCH			23 : 23
-#define	DE_CONTROL_STRETCH_DISABLE		0
-#define	DE_CONTROL_STRETCH_ENABLE		1
-#define	DE_CONTROL_HOST				22 : 22
-#define	DE_CONTROL_HOST_COLOR			0
-#define	DE_CONTROL_HOST_MONO			1
-#define	DE_CONTROL_LAST_PIXEL			21 : 21
-#define	DE_CONTROL_LAST_PIXEL_OFF		0
-#define	DE_CONTROL_LAST_PIXEL_ON		1
-#define	DE_CONTROL_COMMAND			20 : 16
-#define	DE_CONTROL_COMMAND_BITBLT		0
-#define	DE_CONTROL_COMMAND_RECTANGLE_FILL	1
-#define	DE_CONTROL_COMMAND_DE_TILE		2
-#define	DE_CONTROL_COMMAND_TRAPEZOID_FILL	3
-#define	DE_CONTROL_COMMAND_ALPHA_BLEND		4
-#define	DE_CONTROL_COMMAND_RLE_STRIP		5
-#define	DE_CONTROL_COMMAND_SHORT_STROKE		6
-#define	DE_CONTROL_COMMAND_LINE_DRAW		7
-#define	DE_CONTROL_COMMAND_HOST_WRITE		8
-#define	DE_CONTROL_COMMAND_HOST_READ		9
-#define	DE_CONTROL_COMMAND_HOST_WRITE_BOTTOM_UP	10
-#define	DE_CONTROL_COMMAND_ROTATE		11
-#define	DE_CONTROL_COMMAND_FONT			12
-#define	DE_CONTROL_COMMAND_TEXTURE_LOAD		15
-#define	DE_CONTROL_ROP_SELECT			15 : 15
-#define	DE_CONTROL_ROP_SELECT_ROP3		0
-#define	DE_CONTROL_ROP_SELECT_ROP2		1
-#define	DE_CONTROL_ROP2_SOURCE			14 : 14
-#define	DE_CONTROL_ROP2_SOURCE_BITMAP		0
-#define	DE_CONTROL_ROP2_SOURCE_PATTERN		1
-#define	DE_CONTROL_MONO_DATA			13 : 12
-#define	DE_CONTROL_MONO_DATA_NOT_PACKED		0
-#define	DE_CONTROL_MONO_DATA_8_PACKED		1
-#define	DE_CONTROL_MONO_DATA_16_PACKED		2
-#define	DE_CONTROL_MONO_DATA_32_PACKED		3
-#define	DE_CONTROL_REPEAT_ROTATE		11 : 11
-#define	DE_CONTROL_REPEAT_ROTATE_DISABLE	0
-#define	DE_CONTROL_REPEAT_ROTATE_ENABLE		1
-#define	DE_CONTROL_TRANSPARENCY_MATCH		10 : 10
-#define	DE_CONTROL_TRANSPARENCY_MATCH_OPAQUE		0
-#define	DE_CONTROL_TRANSPARENCY_MATCH_TRANSPARENT	1
-#define	DE_CONTROL_TRANSPARENCY_SELECT			9 : 9
-#define	DE_CONTROL_TRANSPARENCY_SELECT_SOURCE		0
-#define	DE_CONTROL_TRANSPARENCY_SELECT_DESTINATION	1
-#define	DE_CONTROL_TRANSPARENCY				8 : 8
-#define	DE_CONTROL_TRANSPARENCY_DISABLE			0
-#define	DE_CONTROL_TRANSPARENCY_ENABLE			1
-#define	DE_CONTROL_ROP					7 : 0
-
-/* Pseudo fields. */
-
-#define	DE_CONTROL_SHORT_STROKE_DIR			27 : 24
-#define	DE_CONTROL_SHORT_STROKE_DIR_225			0
-#define	DE_CONTROL_SHORT_STROKE_DIR_135			1
-#define	DE_CONTROL_SHORT_STROKE_DIR_315			2
-#define	DE_CONTROL_SHORT_STROKE_DIR_45			3
-#define	DE_CONTROL_SHORT_STROKE_DIR_270			4
-#define	DE_CONTROL_SHORT_STROKE_DIR_90			5
-#define	DE_CONTROL_SHORT_STROKE_DIR_180			8
-#define	DE_CONTROL_SHORT_STROKE_DIR_0			10
-#define	DE_CONTROL_ROTATION				25 : 24
-#define	DE_CONTROL_ROTATION_0				0
-#define	DE_CONTROL_ROTATION_270				1
-#define	DE_CONTROL_ROTATION_90				2
-#define	DE_CONTROL_ROTATION_180				3
-
-#define	DE_PITCH					0x000010
-#define	DE_PITCH_DESTINATION				28 : 16
-#define	DE_PITCH_SOURCE					12 : 0
-
-#define	DE_FOREGROUND					0x000014
-#define	DE_FOREGROUND_COLOR				31 : 0
-
-#define	DE_BACKGROUND					0x000018
-#define	DE_BACKGROUND_COLOR				31 : 0
-
-#define	DE_STRETCH_FORMAT				0x00001C
-#define	DE_STRETCH_FORMAT_PATTERN_XY			30 : 30
-#define	DE_STRETCH_FORMAT_PATTERN_XY_NORMAL		0
-#define	DE_STRETCH_FORMAT_PATTERN_XY_OVERWRITE		1
-#define	DE_STRETCH_FORMAT_PATTERN_Y			29 : 27
-#define	DE_STRETCH_FORMAT_PATTERN_X			25 : 23
-#define	DE_STRETCH_FORMAT_PIXEL_FORMAT			21 : 20
-#define	DE_STRETCH_FORMAT_PIXEL_FORMAT_8		0
-#define	DE_STRETCH_FORMAT_PIXEL_FORMAT_16		1
-#define	DE_STRETCH_FORMAT_PIXEL_FORMAT_24		3
-#define	DE_STRETCH_FORMAT_PIXEL_FORMAT_32		2
-#define	DE_STRETCH_FORMAT_ADDRESSING			19 : 16
-#define	DE_STRETCH_FORMAT_ADDRESSING_XY			0
-#define	DE_STRETCH_FORMAT_ADDRESSING_LINEAR		15
-#define	DE_STRETCH_FORMAT_SOURCE_HEIGHT			11 : 0
-
-#define	DE_COLOR_COMPARE				0x000020
-#define	DE_COLOR_COMPARE_COLOR				23 : 0
-
-#define	DE_COLOR_COMPARE_MASK				0x000024
-#define	DE_COLOR_COMPARE_MASK_MASKS			23 : 0
-
-#define	DE_MASKS					0x000028
-#define	DE_MASKS_BYTE_MASK				31 : 16
-#define	DE_MASKS_BIT_MASK				15 : 0
-
-#define	DE_CLIP_TL					0x00002C
-#define	DE_CLIP_TL_TOP					31 : 16
-#define	DE_CLIP_TL_STATUS				13 : 13
-#define	DE_CLIP_TL_STATUS_DISABLE			0
-#define	DE_CLIP_TL_STATUS_ENABLE			1
-#define	DE_CLIP_TL_INHIBIT				12 : 12
-#define	DE_CLIP_TL_INHIBIT_OUTSIDE			0
-#define	DE_CLIP_TL_INHIBIT_INSIDE			1
-#define	DE_CLIP_TL_LEFT					11 : 0
-
-#define	DE_CLIP_BR					0x000030
-#define	DE_CLIP_BR_BOTTOM				31 : 16
-#define	DE_CLIP_BR_RIGHT				12 : 0
-
-#define	DE_MONO_PATTERN_LOW				0x000034
-#define	DE_MONO_PATTERN_LOW_PATTERN			31 : 0
-
-#define	DE_MONO_PATTERN_HIGH				0x000038
-#define	DE_MONO_PATTERN_HIGH_PATTERN			31 : 0
-
-#define	DE_WINDOW_WIDTH					0x00003C
-#define	DE_WINDOW_WIDTH_DESTINATION			28 : 16
-#define	DE_WINDOW_WIDTH_SOURCE				12 : 0
-
-#define	DE_WINDOW_SOURCE_BASE				0x000040
-#define	DE_WINDOW_SOURCE_BASE_EXT			27 : 27
-#define	DE_WINDOW_SOURCE_BASE_EXT_LOCAL			0
-#define	DE_WINDOW_SOURCE_BASE_EXT_EXTERNAL		1
-#define	DE_WINDOW_SOURCE_BASE_CS			26 : 26
-#define	DE_WINDOW_SOURCE_BASE_CS_0			0
-#define	DE_WINDOW_SOURCE_BASE_CS_1			1
-#define	DE_WINDOW_SOURCE_BASE_ADDRESS			25 : 0
-
-#define	DE_WINDOW_DESTINATION_BASE			0x000044
-#define	DE_WINDOW_DESTINATION_BASE_EXT			27 : 27
-#define	DE_WINDOW_DESTINATION_BASE_EXT_LOCAL		0
-#define	DE_WINDOW_DESTINATION_BASE_EXT_EXTERNAL		1
-#define	DE_WINDOW_DESTINATION_BASE_CS			26 : 26
-#define	DE_WINDOW_DESTINATION_BASE_CS_0			0
-#define	DE_WINDOW_DESTINATION_BASE_CS_1			1
-#define	DE_WINDOW_DESTINATION_BASE_ADDRESS		25 : 0
-
-#define	DE_ALPHA					0x000048
-#define	DE_ALPHA_VALUE					7 : 0
-
-#define	DE_WRAP						0x00004C
-#define	DE_WRAP_X					31 : 16
-#define	DE_WRAP_Y					15 : 0
-
-#define	DE_STATUS					0x000050
-#define	DE_STATUS_CSC					1 : 1
-#define	DE_STATUS_CSC_CLEAR				0
-#define	DE_STATUS_CSC_NOT_ACTIVE			0
-#define	DE_STATUS_CSC_ACTIVE				1
-#define	DE_STATUS_2D					0 : 0
-#define	DE_STATUS_2D_CLEAR				0
-#define	DE_STATUS_2D_NOT_ACTIVE				0
-#define	DE_STATUS_2D_ACTIVE				1
-
-/* Color Space Conversion registers. */
-
-#define	CSC_Y_SOURCE_BASE				0x0000C8
-#define	CSC_Y_SOURCE_BASE_EXT				27 : 27
-#define	CSC_Y_SOURCE_BASE_EXT_LOCAL			0
-#define	CSC_Y_SOURCE_BASE_EXT_EXTERNAL			1
-#define	CSC_Y_SOURCE_BASE_CS				26 : 26
-#define	CSC_Y_SOURCE_BASE_CS_0				0
-#define	CSC_Y_SOURCE_BASE_CS_1				1
-#define	CSC_Y_SOURCE_BASE_ADDRESS			25 : 0
-
-#define	CSC_CONSTANTS					0x0000CC
-#define	CSC_CONSTANTS_Y					31 : 24
-#define	CSC_CONSTANTS_R					23 : 16
-#define	CSC_CONSTANTS_G					15 : 8
-#define	CSC_CONSTANTS_B					7 : 0
-
-#define	CSC_Y_SOURCE_X					0x0000D0
-#define	CSC_Y_SOURCE_X_INTEGER				26 : 16
-#define	CSC_Y_SOURCE_X_FRACTION				15 : 3
-
-#define	CSC_Y_SOURCE_Y					0x0000D4
-#define	CSC_Y_SOURCE_Y_INTEGER				27 : 16
-#define	CSC_Y_SOURCE_Y_FRACTION				15 : 3
-
-#define	CSC_U_SOURCE_BASE				0x0000D8
-#define	CSC_U_SOURCE_BASE_EXT				27 : 27
-#define	CSC_U_SOURCE_BASE_EXT_LOCAL			0
-#define	CSC_U_SOURCE_BASE_EXT_EXTERNAL			1
-#define	CSC_U_SOURCE_BASE_CS				26 : 26
-#define	CSC_U_SOURCE_BASE_CS_0				0
-#define	CSC_U_SOURCE_BASE_CS_1				1
-#define	CSC_U_SOURCE_BASE_ADDRESS			25 : 0
-
-#define	CSC_V_SOURCE_BASE				0x0000DC
-#define	CSC_V_SOURCE_BASE_EXT				27 : 27
-#define	CSC_V_SOURCE_BASE_EXT_LOCAL			0
-#define	CSC_V_SOURCE_BASE_EXT_EXTERNAL			1
-#define	CSC_V_SOURCE_BASE_CS				26 : 26
-#define	CSC_V_SOURCE_BASE_CS_0				0
-#define	CSC_V_SOURCE_BASE_CS_1				1
-#define	CSC_V_SOURCE_BASE_ADDRESS			25 : 0
-
-#define	CSC_SOURCE_DIMENSION				0x0000E0
-#define	CSC_SOURCE_DIMENSION_X				31 : 16
-#define	CSC_SOURCE_DIMENSION_Y				15 : 0
-
-#define	CSC_SOURCE_PITCH				0x0000E4
-#define	CSC_SOURCE_PITCH_Y				31 : 16
-#define	CSC_SOURCE_PITCH_UV				15 : 0
-
-#define	CSC_DESTINATION					0x0000E8
-#define	CSC_DESTINATION_WRAP				31 : 31
-#define	CSC_DESTINATION_WRAP_DISABLE			0
-#define	CSC_DESTINATION_WRAP_ENABLE			1
-#define	CSC_DESTINATION_X				27 : 16
-#define	CSC_DESTINATION_Y				11 : 0
-
-#define	CSC_DESTINATION_DIMENSION			0x0000EC
-#define	CSC_DESTINATION_DIMENSION_X			31 : 16
-#define	CSC_DESTINATION_DIMENSION_Y			15 : 0
-
-#define	CSC_DESTINATION_PITCH				0x0000F0
-#define	CSC_DESTINATION_PITCH_X				31 : 16
-#define	CSC_DESTINATION_PITCH_Y				15 : 0
-
-#define	CSC_SCALE_FACTOR				0x0000F4
-#define	CSC_SCALE_FACTOR_HORIZONTAL			31 : 16
-#define	CSC_SCALE_FACTOR_VERTICAL			15 : 0
-
-#define	CSC_DESTINATION_BASE				0x0000F8
-#define	CSC_DESTINATION_BASE_EXT			27 : 27
-#define	CSC_DESTINATION_BASE_EXT_LOCAL			0
-#define	CSC_DESTINATION_BASE_EXT_EXTERNAL		1
-#define	CSC_DESTINATION_BASE_CS				26 : 26
-#define	CSC_DESTINATION_BASE_CS_0			0
-#define	CSC_DESTINATION_BASE_CS_1			1
-#define	CSC_DESTINATION_BASE_ADDRESS			25 : 0
-
-#define	CSC_CONTROL					0x0000FC
-#define	CSC_CONTROL_STATUS				31 : 31
-#define	CSC_CONTROL_STATUS_STOP				0
-#define	CSC_CONTROL_STATUS_START			1
-#define	CSC_CONTROL_SOURCE_FORMAT			30 : 28
-#define	CSC_CONTROL_SOURCE_FORMAT_YUV422		0
-#define	CSC_CONTROL_SOURCE_FORMAT_YUV420I		1
-#define	CSC_CONTROL_SOURCE_FORMAT_YUV420		2
-#define	CSC_CONTROL_SOURCE_FORMAT_YVU9			3
-#define	CSC_CONTROL_SOURCE_FORMAT_IYU1			4
-#define	CSC_CONTROL_SOURCE_FORMAT_IYU2			5
-#define	CSC_CONTROL_SOURCE_FORMAT_RGB565		6
-#define	CSC_CONTROL_SOURCE_FORMAT_RGB8888		7
-#define	CSC_CONTROL_DESTINATION_FORMAT			27 : 26
-#define	CSC_CONTROL_DESTINATION_FORMAT_RGB565		0
-#define	CSC_CONTROL_DESTINATION_FORMAT_RGB8888		1
-#define	CSC_CONTROL_HORIZONTAL_FILTER			25 : 25
-#define	CSC_CONTROL_HORIZONTAL_FILTER_DISABLE		0
-#define	CSC_CONTROL_HORIZONTAL_FILTER_ENABLE		1
-#define	CSC_CONTROL_VERTICAL_FILTER			24 : 24
-#define	CSC_CONTROL_VERTICAL_FILTER_DISABLE		0
-#define	CSC_CONTROL_VERTICAL_FILTER_ENABLE		1
-#define	CSC_CONTROL_BYTE_ORDER				23 : 23
-#define	CSC_CONTROL_BYTE_ORDER_YUYV			0
-#define	CSC_CONTROL_BYTE_ORDER_UYVY			1
-
-#define	DE_DATA_PORT_501				0x110000
-#define	DE_DATA_PORT_712				0x400000
-#define	DE_DATA_PORT_722				0x6000
-
-/* point to virtual Memory Map IO starting address */
-extern char *smtc_RegBaseAddress;
-/* point to virtual video memory starting address */
-extern char *smtc_VRAMBaseAddress;
-extern unsigned char smtc_de_busy;
-
-extern unsigned long memRead32(unsigned long nOffset);
-extern void memWrite32(unsigned long nOffset, unsigned long nData);
-extern unsigned long SMTC_read2Dreg(unsigned long nOffset);
-
-/* 2D functions */
-extern void deInit(unsigned int nModeWidth, unsigned int nModeHeight,
-		   unsigned int bpp);
-
-extern void deWaitForNotBusy(void);
-
-extern void deVerticalLine(unsigned long dst_base,
-	unsigned long dst_pitch,
-	unsigned long nX,
-	unsigned long nY,
-	unsigned long dst_height,
-	unsigned long nColor);
-
-extern void deHorizontalLine(unsigned long dst_base,
-	unsigned long dst_pitch,
-	unsigned long nX,
-	unsigned long nY,
-	unsigned long dst_width,
-	unsigned long nColor);
-
-extern void deLine(unsigned long dst_base,
-	unsigned long dst_pitch,
-	unsigned long nX1,
-	unsigned long nY1,
-	unsigned long nX2,
-	unsigned long nY2,
-	unsigned long nColor);
-
-extern void deFillRect(unsigned long dst_base,
-	unsigned long dst_pitch,
-	unsigned long dst_X,
-	unsigned long dst_Y,
-	unsigned long dst_width,
-	unsigned long dst_height,
-	unsigned long nColor);
-
-extern void deRotatePattern(unsigned char *pattern_dstaddr,
-	unsigned long pattern_src_addr,
-	unsigned long pattern_BPP,
-	unsigned long pattern_stride,
-	int	patternX,
-	int	patternY);
-
-extern void deCopy(unsigned long dst_base,
-	unsigned long dst_pitch,
-	unsigned long dst_BPP,
-	unsigned long dst_X,
-	unsigned long dst_Y,
-	unsigned long dst_width,
-	unsigned long dst_height,
-	unsigned long src_base,
-	unsigned long src_pitch,
-	unsigned long src_X,
-	unsigned long src_Y,
-	pTransparent	pTransp,
-	unsigned char nROP2);
-
-/*
- * System memory to Video memory monochrome expansion.
- *
- * Source is monochrome image in system memory.  This function expands the
- * monochrome data to color image in video memory.
- *
- * @pSrcbuf: pointer to start of source buffer in system memory
- * @srcDelta: Pitch value (in bytes) of the source buffer, +ive means top
- * 		down and -ive mean button up
- * @startBit: Mono data can start at any bit in a byte, this value should
- * 		be 0 to 7
- * @dBase: Address of destination :  offset in frame buffer
- * @dPitch: Pitch value of destination surface in BYTE
- * @bpp: Color depth of destination surface
- * @dx, dy: Starting coordinate of destination surface
- * @width, height: width and height of rectange in pixel value
- * @fColor,bColor: Foreground, Background color (corresponding to a 1, 0 in
- * 	the monochrome data)
- * @rop2: ROP value
- */
-
-extern long deSystemMem2VideoMemMonoBlt(
-	const char *pSrcbuf,
-	long srcDelta,
-	unsigned long startBit,
-	unsigned long dBase,
-	unsigned long dPitch,
-	unsigned long bpp,
-	unsigned long dx, unsigned long dy,
-	unsigned long width, unsigned long height,
-	unsigned long fColor,
-	unsigned long bColor,
-	unsigned long rop2);
-
-extern unsigned long deGetTransparency(void);
-extern void deSetPixelFormat(unsigned long bpp);
diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c
index a4f6f49..9c82a1a 100644
--- a/drivers/staging/sm7xx/smtcfb.c
+++ b/drivers/staging/sm7xx/smtcfb.c
@@ -45,7 +45,6 @@
 struct screen_info smtc_screen_info;
 
 #include "smtcfb.h"
-#include "smtc2d.h"
 
 #ifdef DEBUG
 #define smdbg(format, arg...)	printk(KERN_DEBUG format , ## arg)
@@ -120,10 +119,6 @@
 char __iomem *smtc_RegBaseAddress;	/* Memory Map IO starting address */
 char __iomem *smtc_VRAMBaseAddress;	/* video memory starting address */
 
-char *smtc_2DBaseAddress;	/* 2D engine starting address */
-char *smtc_2Ddataport;		/* 2D data port offset */
-short smtc_2Dacceleration;
-
 static u32 colreg[17];
 static struct par_info hw;	/* hardware information */
 
@@ -135,16 +130,6 @@
 
 #define numSMTCchipIDs (sizeof(smtc_ChipIDs) / sizeof(u16))
 
-void deWaitForNotBusy(void)
-{
-	unsigned long i = 0x1000000;
-	while (i--) {
-		if ((smtc_seqr(0x16) & 0x18) == 0x10)
-			break;
-	}
-	smtc_de_busy = 0;
-}
-
 static void sm712_set_timing(struct smtcfb_info *sfb,
 			     struct par_info *ppar_info)
 {
@@ -324,7 +309,7 @@
 	return chan << bf->offset;
 }
 
-static int smtcfb_blank(int blank_mode, struct fb_info *info)
+static int cfb_blank(int blank_mode, struct fb_info *info)
 {
 	/* clear DPMS setting */
 	switch (blank_mode) {
@@ -622,93 +607,13 @@
 }
 #endif	/* ! __BIG_ENDIAN */
 
-#include "smtc2d.c"
-
-void smtcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-	struct par_info *p = (struct par_info *)info->par;
-
-	if (smtc_2Dacceleration) {
-		if (!area->width || !area->height)
-			return;
-
-		deCopy(p->BaseAddressInVRAM, 0, info->var.bits_per_pixel,
-		       area->dx, area->dy, area->width, area->height,
-		       p->BaseAddressInVRAM, 0, area->sx, area->sy, 0, 0xC);
-
-	} else
-		cfb_copyarea(info, area);
-}
-
-void smtcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct par_info *p = (struct par_info *)info->par;
-
-	if (smtc_2Dacceleration) {
-		if (!rect->width || !rect->height)
-			return;
-		if (info->var.bits_per_pixel >= 24)
-			deFillRect(p->BaseAddressInVRAM, 0, rect->dx * 3,
-				   rect->dy * 3, rect->width * 3, rect->height,
-				   rect->color);
-		else
-			deFillRect(p->BaseAddressInVRAM, 0, rect->dx, rect->dy,
-				   rect->width, rect->height, rect->color);
-	} else
-		cfb_fillrect(info, rect);
-}
-
-void smtcfb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct par_info *p = (struct par_info *)info->par;
-	u32 bg_col = 0, fg_col = 0;
-
-	if ((smtc_2Dacceleration) && (image->depth == 1)) {
-		if (smtc_de_busy)
-			deWaitForNotBusy();
-
-		switch (info->var.bits_per_pixel) {
-		case 8:
-			bg_col = image->bg_color;
-			fg_col = image->fg_color;
-			break;
-		case 16:
-			bg_col =
-			    ((u32 *) (info->pseudo_palette))[image->bg_color];
-			fg_col =
-			    ((u32 *) (info->pseudo_palette))[image->fg_color];
-			break;
-		case 32:
-			bg_col =
-			    ((u32 *) (info->pseudo_palette))[image->bg_color];
-			fg_col =
-			    ((u32 *) (info->pseudo_palette))[image->fg_color];
-			break;
-		}
-
-		deSystemMem2VideoMemMonoBlt(
-			image->data,
-			image->width / 8,
-			0,
-			p->BaseAddressInVRAM,
-			0,
-			0,
-			image->dx, image->dy,
-			image->width, image->height,
-			fg_col, bg_col,
-			0x0C);
-
-	} else
-		cfb_imageblit(info, image);
-}
-
 static struct fb_ops smtcfb_ops = {
 	.owner = THIS_MODULE,
 	.fb_setcolreg = smtc_setcolreg,
-	.fb_blank = smtcfb_blank,
-	.fb_fillrect = smtcfb_fillrect,
-	.fb_imageblit = smtcfb_imageblit,
-	.fb_copyarea = smtcfb_copyarea,
+	.fb_blank = cfb_blank,
+	.fb_fillrect = cfb_fillrect,
+	.fb_imageblit = cfb_imageblit,
+	.fb_copyarea = cfb_copyarea,
 #ifdef __BIG_ENDIAN
 	.fb_read = smtcfb_read,
 	.fb_write = smtcfb_write,
@@ -772,12 +677,6 @@
 	hw.height = sfb->fb.var.yres;
 	hw.hz = 60;
 	smtc_set_timing(sfb, &hw);
-	if (smtc_2Dacceleration) {
-		printk("2D acceleration enabled!\n");
-		/* Init smtc drawing engine */
-		deInit(sfb->fb.var.xres, sfb->fb.var.yres,
-				sfb->fb.var.bits_per_pixel);
-	}
 }
 
 /*
@@ -1004,9 +903,7 @@
 #endif
 		hw.m_pMMIO = (smtc_RegBaseAddress =
 		    smtc_VRAMBaseAddress + 0x00700000);
-		smtc_2DBaseAddress = (hw.m_pDPR =
-		    smtc_VRAMBaseAddress + 0x00408000);
-		smtc_2Ddataport = smtc_VRAMBaseAddress + DE_DATA_PORT_712;
+		hw.m_pDPR = smtc_VRAMBaseAddress + 0x00408000;
 		hw.m_pVPR = hw.m_pLFB + 0x0040c000;
 #ifdef __BIG_ENDIAN
 		if (sfb->fb.var.bits_per_pixel == 32) {
@@ -1035,27 +932,21 @@
 		if (sfb->fb.var.bits_per_pixel == 32)
 			smtc_seqw(0x17, 0x30);
 #endif
-#ifdef CONFIG_FB_SM7XX_ACCEL
-		smtc_2Dacceleration = 1;
-#endif
 		break;
 	case 0x720:
 		sfb->fb.fix.mmio_start = pFramebufferPhysical;
 		sfb->fb.fix.mmio_len = 0x00200000;
 		smem_size = SM722_VIDEOMEMORYSIZE;
-		smtc_2DBaseAddress = (hw.m_pDPR =
-		    ioremap(pFramebufferPhysical, 0x00a00000));
+		hw.m_pDPR = ioremap(pFramebufferPhysical, 0x00a00000);
 		hw.m_pLFB = (smtc_VRAMBaseAddress =
-		    smtc_2DBaseAddress + 0x00200000);
+		    hw.m_pDPR + 0x00200000);
 		hw.m_pMMIO = (smtc_RegBaseAddress =
-		    smtc_2DBaseAddress + 0x000c0000);
-		smtc_2Ddataport = smtc_2DBaseAddress + DE_DATA_PORT_722;
-		hw.m_pVPR = smtc_2DBaseAddress + 0x800;
+		    hw.m_pDPR + 0x000c0000);
+		hw.m_pVPR = hw.m_pDPR + 0x800;
 
 		smtc_seqw(0x62, 0xff);
 		smtc_seqw(0x6a, 0x0d);
 		smtc_seqw(0x6b, 0x02);
-		smtc_2Dacceleration = 0;
 		break;
 	default:
 		printk(KERN_INFO
@@ -1103,7 +994,7 @@
 
 
 /* Jason (08/11/2009) PCI_DRV wrapper essential structs */
-static struct pci_device_id smtcfb_pci_table[] = {
+static const struct pci_device_id smtcfb_pci_table[] = {
 	{0x126f, 0x710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x126f, 0x712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0x126f, 0x720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
diff --git a/drivers/staging/udlfb/Kconfig b/drivers/staging/udlfb/Kconfig
index 641692d..65bd5db 100644
--- a/drivers/staging/udlfb/Kconfig
+++ b/drivers/staging/udlfb/Kconfig
@@ -1,8 +1,14 @@
 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 an experimental driver for DisplayLink USB devices
-	  that provides a framebuffer device.  A normal framebuffer can
-	  be used with this driver, or xorg can be run on the device
-	  using it.
+	  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/udlfb.c b/drivers/staging/udlfb/udlfb.c
index f5416af..8f6223c 100644
--- a/drivers/staging/udlfb/udlfb.c
+++ b/drivers/staging/udlfb/udlfb.c
@@ -1,17 +1,20 @@
-/*****************************************************************************
- *                          DLFB Kernel Driver                               *
- *                            Version 0.2 (udlfb)                            *
- *             (C) 2009 Roberto De Ioris <roberto@unbit.it>                  *
- *                                                                           *
- *     This file is licensed under the GPLv2. See COPYING in the package.    *
- * Based on the amazing work of Florian Echtler and libdlo 0.1               *
- *                                                                           *
- *                                                                           *
- * 10.06.09 release 0.2.3 (edid ioctl, fallback for unsupported modes)       *
- * 05.06.09 release 0.2.2 (real screen blanking, rle compression, double buffer) *
- * 31.05.09 release 0.2                                                      *
- * 22.05.09 First public (ugly) release                                      *
- *****************************************************************************/
+/*
+ * 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>
@@ -20,60 +23,282 @@
 #include <linux/uaccess.h>
 #include <linux/mm.h>
 #include <linux/fb.h>
-#include <linux/mutex.h>
 #include <linux/vmalloc.h>
 
 #include "udlfb.h"
 
-#define DRIVER_VERSION "DLFB 0.2"
+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,
+};
 
-/* memory functions taken from vfb */
+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;
 
-static void *rvmalloc(unsigned long size)
+/*
+ * 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);
+
+#ifndef CONFIG_FB_DEFERRED_IO
+#warning message "kernel FB_DEFFERRED_IO option to support generic fbdev apps"
+#endif
+
+#ifndef CONFIG_FB_SYS_IMAGEBLIT
+#ifndef CONFIG_FB_SYS_IMAGEBLIT_MODULE
+#warning message "FB_SYS_* in kernel or module option to support fb console"
+#endif
+#endif
+
+#ifndef CONFIG_FB_MODE_HELPERS
+#warning message "kernel FB_MODE_HELPERS required. Expect build break"
+#endif
+
+/* 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);
+
+/* other symbols with dependents */
+#ifdef CONFIG_FB_DEFERRED_IO
+static struct fb_deferred_io dlfb_defio;
+#endif
+
+/*
+ * 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)
 {
-	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;
+	*buf++ = 0xAF;
+	*buf++ = 0x20;
+	*buf++ = reg;
+	*buf++ = val;
+	return buf;
 }
 
-static void rvfree(void *mem, unsigned long size)
+static char *dlfb_vidreg_lock(char *buf)
 {
-	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);
+	return dlfb_set_register(buf, 0xFF, 0x00);
 }
 
-static int dlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+static char *dlfb_vidreg_unlock(char *buf)
+{
+	return dlfb_set_register(buf, 0xFF, 0xFF);
+}
+
+/*
+ * On/Off for driving the DisplayLink framebuffer to the display
+ */
+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, 0x01);
+}
+
+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;
+	struct dlfb_data *dev = info->par;
 
-	printk("MMAP: %lu %u\n", offset + size, info->fix.smem_len);
+	dl_notice("MMAP: %lu %u\n", offset + size, info->fix.smem_len);
 
 	if (offset + size > info->fix.smem_len)
 		return -EINVAL;
@@ -98,528 +323,372 @@
 
 }
 
-/* ioctl structure */
-struct dloarea {
-	int x, y;
-	int w, h;
-	int x2, y2;
-};
-
 /*
-static struct usb_device_id id_table [] = {
-	{ USB_DEVICE(0x17e9, 0x023d) },
-	{ }
-};
-*/
-
-static struct usb_device_id id_table[] = {
-	{.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
-	{},
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver dlfb_driver;
-
-// thanks to Henrik Bjerregaard Pedersen for this function
-static char *rle_compress16(uint16_t * src, char *dst, int rem)
+ * 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;
 
-	int rl;
-	uint16_t pix0;
-	char *end_if_raw = dst + 6 + 2 * rem;
+	prefetch((void *) front);
+	prefetch((void *) back);
 
-	dst += 6;		// header will be filled in if RLE is worth it
-
-	while (rem && dst < end_if_raw) {
-		char *start = (char *)src;
-
-		pix0 = *src++;
-		rl = 1;
-		rem--;
-		while (rem && *src == pix0)
-			rem--, rl++, src++;
-		*dst++ = rl;
-		*dst++ = start[1];
-		*dst++ = start[0];
+	for (j = 0; j < width; j++) {
+		if (back[j] != front[j]) {
+			start = j;
+			break;
+		}
 	}
 
-	return dst;
+	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);
 }
 
 /*
-Thanks to Henrik Bjerregaard Pedersen for rle implementation and code refactoring.
-Next step is huffman compression.
+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 int
-image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height,
-	   char *data)
+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;
 
-	int i, j, base;
-	int rem = width;
-	int ret;
+	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;
+		const uint32_t be_dev_addr = cpu_to_be32(dev_addr);
 
-	int firstdiff, thistime;
+		prefetchw((void *) cmd); /* pull in one cache line at least */
 
-	char *bufptr;
+		*cmd++ = 0xAF;
+		*cmd++ = 0x6B;
+		*cmd++ = (uint8_t) ((be_dev_addr >> 8) & 0xFF);
+		*cmd++ = (uint8_t) ((be_dev_addr >> 16) & 0xFF);
+		*cmd++ = (uint8_t) ((be_dev_addr >> 24) & 0xFF);
 
-	if (x + width > dev_info->info->var.xres)
-		return -EINVAL;
+		cmd_pixels_count_byte = cmd++; /*  we'll know this later */
+		cmd_pixel_start = pixel;
 
-	if (y + height > dev_info->info->var.yres)
-		return -EINVAL;
+		raw_pixels_count_byte = cmd++; /*  we'll know this later */
+		raw_pixel_start = pixel;
 
-	mutex_lock(&dev_info->bulk_mutex);
+		cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
+			min((int)(pixel_end - pixel),
+			    (int)(cmd_buffer_end - cmd) / bpp));
 
-	base =
-	    dev_info->base16 + ((dev_info->info->var.xres * 2 * y) + (x * 2));
+		prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp);
 
-	data += (dev_info->info->var.xres * 2 * y) + (x * 2);
+		while (pixel < cmd_pixel_end) {
+			const uint16_t * const repeating_pixel = pixel;
 
-	/* printk("IMAGE_BLIT\n"); */
+			*(uint16_t *)cmd = cpu_to_be16p(pixel);
+			cmd += 2;
+			pixel++;
 
-	bufptr = dev_info->buf;
+			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;
 
-	for (i = y; i < y + height; i++) {
-
-		if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
-			ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
-			bufptr = dev_info->buf;
-		}
-
-		rem = width;
-
-		/* printk("WRITING LINE %d\n", i); */
-
-		while (rem) {
-
-			if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
-				ret =
-				    dlfb_bulk_msg(dev_info,
-						  bufptr - dev_info->buf);
-				bufptr = dev_info->buf;
-			}
-			// number of pixels to consider this time
-			thistime = rem;
-			if (thistime > 255)
-				thistime = 255;
-
-			// find position of first pixel that has changed
-			firstdiff = -1;
-			for (j = 0; j < thistime * 2; j++) {
-				if (dev_info->backing_buffer
-				    [base - dev_info->base16 + j] != data[j]) {
-					firstdiff = j / 2;
-					break;
+				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 (firstdiff >= 0) {
-				char *end_of_rle;
-
-				end_of_rle =
-				    rle_compress16((uint16_t *) (data +
-								 firstdiff * 2),
-						   bufptr,
-						   thistime - firstdiff);
-
-				if (end_of_rle <
-				    bufptr + 6 + 2 * (thistime - firstdiff)) {
-					bufptr[0] = 0xAF;
-					bufptr[1] = 0x69;
-
-					bufptr[2] =
-					    (char)((base +
-						    firstdiff * 2) >> 16);
-					bufptr[3] =
-					    (char)((base + firstdiff * 2) >> 8);
-					bufptr[4] =
-					    (char)(base + firstdiff * 2);
-					bufptr[5] = thistime - firstdiff;
-
-					bufptr = end_of_rle;
-
-				} else {
-					// fallback to raw (or some other encoding?)
-					*bufptr++ = 0xAF;
-					*bufptr++ = 0x68;
-
-					*bufptr++ =
-					    (char)((base +
-						    firstdiff * 2) >> 16);
-					*bufptr++ =
-					    (char)((base + firstdiff * 2) >> 8);
-					*bufptr++ =
-					    (char)(base + firstdiff * 2);
-					*bufptr++ = thistime - firstdiff;
-					// PUT COMPRESSION HERE
-					for (j = firstdiff * 2;
-					     j < thistime * 2; j += 2) {
-						*bufptr++ = data[j + 1];
-						*bufptr++ = data[j];
-					}
-				}
-			}
-
-			base += thistime * 2;
-			data += thistime * 2;
-			rem -= thistime;
 		}
 
-		memcpy(dev_info->backing_buffer + (base - dev_info->base16) -
-		       (width * 2), data - (width * 2), width * 2);
+		if (pixel > raw_pixel_start) {
+			/* finalize last RAW span */
+			*raw_pixels_count_byte = (pixel-raw_pixel_start) & 0xFF;
+		}
 
-		base += (dev_info->info->var.xres * 2) - (width * 2);
-		data += (dev_info->info->var.xres * 2) - (width * 2);
-
+		*cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
+		dev_addr += (pixel - cmd_pixel_start) * bpp;
 	}
 
-	if (bufptr > dev_info->buf) {
-		ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
+	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;
 	}
 
-	mutex_unlock(&dev_info->bulk_mutex);
+	*command_buffer_ptr = cmd;
+	*pixel_start_ptr = pixel;
+	*device_address_ptr = dev_addr;
 
-	return base;
-
+	return;
 }
 
-static int
-draw_rect(struct dlfb_data *dev_info, int x, int y, int width, int height,
-	  unsigned char red, unsigned char green, unsigned char blue)
+/*
+ * 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 void 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;
 
-	int i, j, base;
-	int ret;
-	unsigned short col =
-	    (((((red) & 0xF8) | ((green) >> 5)) & 0xFF) << 8) +
-	    (((((green) & 0x1C) << 3) | ((blue) >> 3)) & 0xFF);
-	int rem = width;
+	line_start = (u8 *) (front + byte_offset);
+	next_pixel = line_start;
+	line_end = next_pixel + byte_width;
 
-	char *bufptr;
+	if (dev->backing_buffer) {
+		int offset;
+		const u8 *back_start = (u8 *) (dev->backing_buffer
+						+ byte_offset);
 
-	if (x + width > dev_info->info->var.xres)
-		return -EINVAL;
+		*ident_ptr += dlfb_trim_hline(back_start, &next_pixel,
+			&byte_width);
 
-	if (y + height > dev_info->info->var.yres)
-		return -EINVAL;
+		offset = next_pixel - line_start;
+		line_end = next_pixel + byte_width;
+		dev_addr += offset;
+		back_start += offset;
+		line_start += offset;
 
-	mutex_lock(&dev_info->bulk_mutex);
-
-	base = dev_info->base16 + (dev_info->info->var.xres * 2 * y) + (x * 2);
-
-	bufptr = dev_info->buf;
-
-	for (i = y; i < y + height; i++) {
-
-		for (j = 0; j < width * 2; j += 2) {
-			dev_info->backing_buffer[base - dev_info->base16 + j] =
-			    (char)(col >> 8);
-			dev_info->backing_buffer[base - dev_info->base16 + j +
-						 1] = (char)(col);
-		}
-		if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
-			ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
-			bufptr = dev_info->buf;
-		}
-
-		rem = width;
-
-		while (rem) {
-
-			if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
-				ret =
-				    dlfb_bulk_msg(dev_info,
-						  bufptr - dev_info->buf);
-				bufptr = dev_info->buf;
-			}
-
-			*bufptr++ = 0xAF;
-			*bufptr++ = 0x69;
-
-			*bufptr++ = (char)(base >> 16);
-			*bufptr++ = (char)(base >> 8);
-			*bufptr++ = (char)(base);
-
-			if (rem > 255) {
-				*bufptr++ = 255;
-				*bufptr++ = 255;
-				rem -= 255;
-				base += 255 * 2;
-			} else {
-				*bufptr++ = rem;
-				*bufptr++ = rem;
-				base += rem * 2;
-				rem = 0;
-			}
-
-			*bufptr++ = (char)(col >> 8);
-			*bufptr++ = (char)(col);
-
-		}
-
-		base += (dev_info->info->var.xres * 2) - (width * 2);
-
+		memcpy((char *)back_start, (char *) line_start,
+		       byte_width);
 	}
 
-	if (bufptr > dev_info->buf)
-		ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
+	while (next_pixel < line_end) {
 
-	mutex_unlock(&dev_info->bulk_mutex);
+		dlfb_compress_hline((const uint16_t **) &next_pixel,
+			     (const uint16_t *) line_end, &dev_addr,
+			(u8 **) &cmd, (u8 *) cmd_end);
 
-	return 1;
+		if (cmd >= cmd_end) {
+			int len = cmd - (u8 *) urb->transfer_buffer;
+			if (dlfb_submit_urb(dev, urb, len))
+				return; /* lost pixels is set */
+			*sent_ptr += len;
+			urb = dlfb_get_urb(dev);
+			if (!urb)
+				return; /* lost_pixels is set */
+			*urb_ptr = urb;
+			cmd = urb->transfer_buffer;
+			cmd_end = &cmd[urb->transfer_buffer_length];
+		}
+	}
+
+	*urb_buf_ptr = cmd;
 }
 
-static void swapfb(struct dlfb_data *dev_info)
+int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
+	       int width, int height, char *data)
 {
-
-	int tmpbase;
-	char *bufptr;
-
-	mutex_lock(&dev_info->bulk_mutex);
-
-	tmpbase = dev_info->base16;
-
-	dev_info->base16 = dev_info->base16d;
-	dev_info->base16d = tmpbase;
-
-	bufptr = dev_info->buf;
-
-	bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
-
-	// set addresses
-	bufptr =
-	    dlfb_set_register(bufptr, 0x20, (char)(dev_info->base16 >> 16));
-	bufptr = dlfb_set_register(bufptr, 0x21, (char)(dev_info->base16 >> 8));
-	bufptr = dlfb_set_register(bufptr, 0x22, (char)(dev_info->base16));
-
-	bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
-
-	dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
-
-	mutex_unlock(&dev_info->bulk_mutex);
-}
-
-static int copyfb(struct dlfb_data *dev_info)
-{
-	int base;
-	int source;
-	int rem;
 	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;
 
-	char *bufptr;
+	start_cycles = get_cycles();
 
-	base = dev_info->base16d;
+	aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
+	width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
+	x = aligned_x;
 
-	mutex_lock(&dev_info->bulk_mutex);
-
-	source = dev_info->base16;
-
-	bufptr = dev_info->buf;
-
-	for (i = 0; i < dev_info->info->var.yres; i++) {
-
-		if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
-			ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
-			bufptr = dev_info->buf;
-		}
-
-		rem = dev_info->info->var.xres;
-
-		while (rem) {
-
-			if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
-				ret =
-				    dlfb_bulk_msg(dev_info,
-						  bufptr - dev_info->buf);
-				bufptr = dev_info->buf;
-
-			}
-
-			*bufptr++ = 0xAF;
-			*bufptr++ = 0x6A;
-
-			*bufptr++ = (char)(base >> 16);
-			*bufptr++ = (char)(base >> 8);
-			*bufptr++ = (char)(base);
-
-			if (rem > 255) {
-				*bufptr++ = 255;
-				*bufptr++ = (char)(source >> 16);
-				*bufptr++ = (char)(source >> 8);
-				*bufptr++ = (char)(source);
-
-				rem -= 255;
-				base += 255 * 2;
-				source += 255 * 2;
-
-			} else {
-				*bufptr++ = rem;
-				*bufptr++ = (char)(source >> 16);
-				*bufptr++ = (char)(source >> 8);
-				*bufptr++ = (char)(source);
-
-				base += rem * 2;
-				source += rem * 2;
-				rem = 0;
-			}
-		}
-	}
-
-	if (bufptr > dev_info->buf)
-		ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
-
-	mutex_unlock(&dev_info->bulk_mutex);
-
-	return 1;
-
-}
-
-static int
-copyarea(struct dlfb_data *dev_info, int dx, int dy, int sx, int sy,
-	 int width, int height)
-{
-	int base;
-	int source;
-	int rem;
-	int i, ret;
-
-	char *bufptr;
-
-	if (dx + width > dev_info->info->var.xres)
+	if ((width <= 0) ||
+	    (x + width > dev->info->var.xres) ||
+	    (y + height > dev->info->var.yres))
 		return -EINVAL;
 
-	if (dy + height > dev_info->info->var.yres)
-		return -EINVAL;
+	if (!atomic_read(&dev->usb_active))
+		return 0;
 
-	mutex_lock(&dev_info->bulk_mutex);
+	urb = dlfb_get_urb(dev);
+	if (!urb)
+		return 0;
+	cmd = urb->transfer_buffer;
 
-	base =
-	    dev_info->base16 + (dev_info->info->var.xres * 2 * dy) + (dx * 2);
-	source = (dev_info->info->var.xres * 2 * sy) + (sx * 2);
+	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);
 
-	bufptr = dev_info->buf;
-
-	for (i = sy; i < sy + height; i++) {
-
-		memcpy(dev_info->backing_buffer + base - dev_info->base16,
-		       dev_info->backing_buffer + source, width * 2);
-
-		if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
-			ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
-			bufptr = dev_info->buf;
-		}
-
-		rem = width;
-
-		while (rem) {
-
-			if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
-				ret =
-				    dlfb_bulk_msg(dev_info,
-						  bufptr - dev_info->buf);
-				bufptr = dev_info->buf;
-			}
-
-			*bufptr++ = 0xAF;
-			*bufptr++ = 0x6A;
-
-			*bufptr++ = (char)(base >> 16);
-			*bufptr++ = (char)(base >> 8);
-			*bufptr++ = (char)(base);
-
-			if (rem > 255) {
-				*bufptr++ = 255;
-				*bufptr++ = (char)(source >> 16);
-				*bufptr++ = (char)(source >> 8);
-				*bufptr++ = (char)(source);
-
-				rem -= 255;
-				base += 255 * 2;
-				source += 255 * 2;
-
-			} else {
-				*bufptr++ = rem;
-				*bufptr++ = (char)(source >> 16);
-				*bufptr++ = (char)(source >> 8);
-				*bufptr++ = (char)(source);
-
-				base += rem * 2;
-				source += rem * 2;
-				rem = 0;
-			}
-		}
-
-		base += (dev_info->info->var.xres * 2) - (width * 2);
-		source += (dev_info->info->var.xres * 2) - (width * 2);
+		dlfb_render_hline(dev, &urb, (char *) dev->info->fix.smem_start,
+				  &cmd, byte_offset, width * BPP,
+				  &bytes_identical, &bytes_sent);
 	}
 
-	if (bufptr > dev_info->buf)
-		ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
+	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);
 
-	mutex_unlock(&dev_info->bulk_mutex);
+	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 1;
+	return 0;
 }
 
-static void dlfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+/* 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;
 
-	copyarea(dev, area->dx, area->dy, area->sx, area->sy, area->width,
-		 area->height);
+#if defined CONFIG_FB_SYS_COPYAREA || defined CONFIG_FB_SYS_COPYAREA_MODULE
 
-	/* printk("COPY AREA %d %d %d %d %d %d !!!\n", area->dx, area->dy, area->sx, area->sy, area->width, area->height); */
+	sys_copyarea(info, area);
+
+	dlfb_handle_damage(dev, area->dx, area->dy,
+			area->width, area->height, info->screen_base);
+#endif
+	atomic_inc(&dev->copy_count);
 
 }
 
-static void dlfb_imageblit(struct fb_info *info, const struct fb_image *image)
+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
+
+	atomic_inc(&dev->blit_count);
+}
+
+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
+
+	atomic_inc(&dev->fill_count);
+
+}
+
+static void dlfb_get_edid(struct dlfb_data *dev)
+{
+	int i;
 	int ret;
-	struct dlfb_data *dev = info->par;
-	/* printk("IMAGE BLIT (1) %d %d %d %d DEPTH %d {%p}!!!\n", image->dx, image->dy, image->width, image->height, image->depth, dev->udev); */
-	cfb_imageblit(info, image);
-	ret =
-	    image_blit(dev, image->dx, image->dy, image->width, image->height,
-		       info->screen_base);
-	/* printk("IMAGE BLIT (2) %d %d %d %d DEPTH %d {%p} %d!!!\n", image->dx, image->dy, image->width, image->height, image->depth, dev->udev, ret); */
+	char rbuf[2];
+
+	for (i = 0; i < sizeof(dev->edid); i++) {
+		ret = usb_control_msg(dev->udev,
+				    usb_rcvctrlpipe(dev->udev, 0), (0x02),
+				    (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
+				    0);
+		dev->edid[i] = rbuf[1];
+	}
 }
 
-static void dlfb_fillrect(struct fb_info *info,
-			  const struct fb_fillrect *region)
+static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
+				unsigned long arg)
 {
 
-	unsigned char red, green, blue;
 	struct dlfb_data *dev = info->par;
-
-	memcpy(&red, &region->color, 1);
-	memcpy(&green, &region->color + 1, 1);
-	memcpy(&blue, &region->color + 2, 1);
-	draw_rect(dev, region->dx, region->dy, region->width, region->height,
-		  red, green, blue);
-	/* printk("FILL RECT %d %d !!!\n", region->dx, region->dy); */
-
-}
-
-static int dlfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-
-	struct dlfb_data *dev_info = info->par;
 	struct dloarea *area = NULL;
 
-	if (cmd == 0xAD) {
+	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;
-		dlfb_edid(dev_info);
-		if (copy_to_user(edid, dev_info->edid, 128)) {
+		dlfb_get_edid(dev);
+		if (copy_to_user(edid, dev->edid, sizeof(dev->edid)))
 			return -EFAULT;
-		}
 		return 0;
 	}
 
-	if (cmd == 0xAA || cmd == 0xAB || cmd == 0xAC) {
+	/* TODO: Help propose a standard fb.h ioctl to report mmap damage */
+	if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
 
 		area = (struct dloarea *)arg;
 
@@ -634,36 +703,20 @@
 
 		if (area->y > info->var.yres)
 			area->y = info->var.yres;
-	}
 
-	if (cmd == 0xAA) {
-		image_blit(dev_info, area->x, area->y, area->w, area->h,
+		atomic_set(&dev->use_defio, 0);
+
+		dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
 			   info->screen_base);
+		atomic_inc(&dev->damage_count);
 	}
-	if (cmd == 0xAC) {
-		copyfb(dev_info);
-		image_blit(dev_info, area->x, area->y, area->w, area->h,
-			   info->screen_base);
-		swapfb(dev_info);
-	} else if (cmd == 0xAB) {
 
-		if (area->x2 < 0)
-			area->x2 = 0;
-
-		if (area->y2 < 0)
-			area->y2 = 0;
-
-		copyarea(dev_info,
-			 area->x2, area->y2, area->x, area->y, area->w,
-			 area->h);
-	}
 	return 0;
 }
 
 /* taken from vesafb */
-
 static int
-dlfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+dlfb_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
 	       unsigned blue, unsigned transp, struct fb_info *info)
 {
 	int err = 0;
@@ -688,234 +741,698 @@
 	return err;
 }
 
-static int dlfb_release(struct fb_info *info, int user)
+/*
+ * It's common for several clients to have framebuffer open simultaneously.
+ * e.g. both fbcon and X. Makes things interesting.
+ */
+static int dlfb_ops_open(struct fb_info *info, int user)
 {
-	struct dlfb_data *dev_info = info->par;
-	image_blit(dev_info, 0, 0, info->var.xres, info->var.yres,
-		   info->screen_base);
+	struct dlfb_data *dev = info->par;
+
+/*	if (user == 0)
+ *		We could special case kernel mode clients (fbcon) here
+ */
+
+	mutex_lock(&dev->fb_open_lock);
+
+	dev->fb_count++;
+
+#ifdef CONFIG_FB_DEFERRED_IO
+	if ((atomic_read(&dev->use_defio)) && (info->fbdefio == NULL)) {
+		/* enable defio */
+		info->fbdefio = &dlfb_defio;
+		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);
+
+	mutex_unlock(&dev->fb_open_lock);
+
 	return 0;
 }
 
-static int dlfb_blank(int blank_mode, struct fb_info *info)
+static int dlfb_ops_release(struct fb_info *info, int user)
 {
-	struct dlfb_data *dev_info = info->par;
-	char *bufptr = dev_info->buf;
+	struct dlfb_data *dev = info->par;
 
-	bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
-	if (blank_mode != FB_BLANK_UNBLANK) {
-		bufptr = dlfb_set_register(bufptr, 0x1F, 0x01);
-	} else {
-		bufptr = dlfb_set_register(bufptr, 0x1F, 0x00);
+	mutex_lock(&dev->fb_open_lock);
+
+	dev->fb_count--;
+
+#ifdef CONFIG_FB_DEFERRED_IO
+	if ((dev->fb_count == 0) && (info->fbdefio)) {
+		fb_deferred_io_cleanup(info);
+		info->fbdefio = NULL;
+		info->fbops->fb_mmap = dlfb_ops_mmap;
 	}
-	bufptr = dlfb_set_register(bufptr, 0xFF, 0xFF);
+#endif
 
-	dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
+	dl_notice("release /dev/fb%d user=%d count=%d\n",
+		  info->node, user, dev->fb_count);
+
+	mutex_unlock(&dev->fb_open_lock);
+
+	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_delete(struct kref *kref)
+{
+	struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
+
+	if (dev->backing_buffer)
+		vfree(dev->backing_buffer);
+
+	mutex_destroy(&dev->fb_open_lock);
+
+	kfree(dev);
+}
+
+/*
+ * Called by fbdev as last part of unregister_framebuffer() process
+ * No new clients can open connections. Deallocate everything fb_info.
+ */
+static void dlfb_ops_destroy(struct fb_info *info)
+{
+	struct dlfb_data *dev = info->par;
+
+	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);
+
+	/* ref taken before register_framebuffer() for dlfb_data clients */
+	kref_put(&dev->kref, dlfb_delete);
+}
+
+/*
+ * 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)
+		return 0;
+
+	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;
+
+	dl_notice("set_par mode %dx%d\n", info->var.xres, info->var.yres);
+
+	return dlfb_set_video_mode(dev, &info->var);
+}
+
+static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
+{
+	struct dlfb_data *dev = info->par;
+	char *bufptr;
+	struct urb *urb;
+
+	urb = dlfb_get_urb(dev);
+	if (!urb)
+		return 0;
+	bufptr = (char *) urb->transfer_buffer;
+
+	/* overloading usb_active.  UNBLANK can conflict with teardown */
+
+	bufptr = dlfb_vidreg_lock(bufptr);
+	if (blank_mode != FB_BLANK_UNBLANK) {
+		atomic_set(&dev->usb_active, 0);
+		bufptr = dlfb_enable_hvsync(bufptr, false);
+	} else {
+		atomic_set(&dev->usb_active, 1);
+		bufptr = dlfb_enable_hvsync(bufptr, true);
+	}
+	bufptr = dlfb_vidreg_unlock(bufptr);
+
+	dlfb_submit_urb(dev, urb, bufptr - (char *) urb->transfer_buffer);
 
 	return 0;
 }
 
 static struct fb_ops dlfb_ops = {
-	.fb_setcolreg = dlfb_setcolreg,
-	.fb_fillrect = dlfb_fillrect,
-	.fb_copyarea = dlfb_copyarea,
-	.fb_imageblit = dlfb_imageblit,
-	.fb_mmap = dlfb_mmap,
-	.fb_ioctl = dlfb_ioctl,
-	.fb_release = dlfb_release,
-	.fb_blank = dlfb_blank,
+	.owner = THIS_MODULE,
+	.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,
 };
 
-static int
-dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id)
+/*
+ * Calls dlfb_get_edid() to query the EDID of attached monitor via usb cmds
+ * Then 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 EDID parses successfully
+ */
+static int dlfb_parse_edid(struct dlfb_data *dev,
+			    struct fb_var_screeninfo *var,
+			    struct fb_info *info)
 {
-	struct dlfb_data *dev_info;
-	struct fb_info *info;
+	int i;
+	const struct fb_videomode *default_vmode = NULL;
+	int result = 0;
 
-	int ret;
-	char rbuf[4];
+	fb_destroy_modelist(&info->modelist);
+	memset(&info->monspecs, 0, sizeof(info->monspecs));
 
-	dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
-	if (dev_info == NULL) {
-		printk("cannot allocate dev_info structure.\n");
-		return -ENOMEM;
-	}
+	dlfb_get_edid(dev);
+	fb_edid_to_monspecs(dev->edid, &info->monspecs);
 
-	mutex_init(&dev_info->bulk_mutex);
+	if (info->monspecs.modedb_len > 0) {
 
-	dev_info->udev = usb_get_dev(interface_to_usbdev(interface));
-	dev_info->interface = interface;
-
-	printk("DisplayLink device attached\n");
-
-	/* add framebuffer info to usb interface */
-	usb_set_intfdata(interface, dev_info);
-
-	dev_info->buf = kmalloc(BUF_SIZE, GFP_KERNEL);
-	/* usb_buffer_alloc(dev_info->udev, BUF_SIZE , GFP_KERNEL, &dev_info->tx_urb->transfer_dma); */
-
-	if (dev_info->buf == NULL) {
-		printk("unable to allocate memory for dlfb commands\n");
-		goto out;
-	}
-	dev_info->bufend = dev_info->buf + BUF_SIZE;
-
-	dev_info->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	usb_fill_bulk_urb(dev_info->tx_urb, dev_info->udev,
-			  usb_sndbulkpipe(dev_info->udev, 1), dev_info->buf, 0,
-			  dlfb_bulk_callback, dev_info);
-
-	ret =
-	    usb_control_msg(dev_info->udev, usb_rcvctrlpipe(dev_info->udev, 0),
-			    (0x06), (0x80 | (0x02 << 5)), 0, 0, rbuf, 4, 0);
-	printk("ret control msg 0: %d %x%x%x%x\n", ret, rbuf[0], rbuf[1],
-	       rbuf[2], rbuf[3]);
-
-	dlfb_edid(dev_info);
-
-	info = framebuffer_alloc(sizeof(u32) * 256, &dev_info->udev->dev);
-
-	if (!info) {
-		printk("non posso allocare il framebuffer displaylink");
-		goto out;
-	}
-
-	fb_parse_edid(dev_info->edid, &info->var);
-
-	printk("EDID XRES %d YRES %d\n", info->var.xres, info->var.yres);
-
-	if (dlfb_set_video_mode(dev_info, info->var.xres, info->var.yres) != 0) {
-		info->var.xres = 1280;
-		info->var.yres = 1024;
-		if (dlfb_set_video_mode
-		    (dev_info, info->var.xres, info->var.yres) != 0) {
-			goto out;
+		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);
 		}
-	}
 
-	printk("found valid mode...%d\n", info->var.pixclock);
-
-	info->pseudo_palette = info->par;
-	info->par = dev_info;
-
-	dev_info->info = info;
-
-	info->flags =
-	    FBINFO_DEFAULT | FBINFO_READS_FAST | FBINFO_HWACCEL_IMAGEBLIT |
-	    FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
-	info->fbops = &dlfb_ops;
-	info->screen_base = rvmalloc(dev_info->screen_size);
-
-	if (info->screen_base == NULL) {
-		printk
-		    ("cannot allocate framebuffer virtual memory of %d bytes\n",
-		     dev_info->screen_size);
-		goto out0;
-	}
-
-	printk("screen base allocated !!!\n");
-
-	dev_info->backing_buffer = kzalloc(dev_info->screen_size, GFP_KERNEL);
-
-	if (!dev_info->backing_buffer)
-		printk("non posso allocare il backing buffer\n");
-
-	/* info->var = dev_info->si; */
-
-	info->var.bits_per_pixel = 16;
-	info->var.activate = FB_ACTIVATE_TEST;
-	info->var.vmode = FB_VMODE_NONINTERLACED;
-
-	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;
-
-	/* info->var.pixclock =  (10000000 / FB_W * 1000 / FB_H)/2 ; */
-
-	info->fix.smem_start = (unsigned long)info->screen_base;
-	info->fix.smem_len = PAGE_ALIGN(dev_info->screen_size);
-	if (strlen(dev_info->udev->product) > 15) {
-		memcpy(info->fix.id, dev_info->udev->product, 15);
+		default_vmode = fb_find_best_display(&info->monspecs,
+						     &info->modelist);
 	} else {
-		memcpy(info->fix.id, dev_info->udev->product,
-		       strlen(dev_info->udev->product));
+		struct fb_videomode fb_vmode = {0};
+
+		dl_err("Unable to get valid EDID from device/display\n");
+		result = 1;
+
+		/*
+		 * 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);
 	}
-	info->fix.type = FB_TYPE_PACKED_PIXELS;
-	info->fix.visual = FB_VISUAL_TRUECOLOR;
-	info->fix.accel = info->flags;
-	info->fix.line_length = dev_info->line_length;
 
-	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
-		goto out1;
+	fb_videomode_to_var(var, default_vmode);
+	dlfb_var_color_format(var);
 
-	printk("colormap allocated\n");
-	if (register_framebuffer(info) < 0)
-		goto out2;
-
-	draw_rect(dev_info, 0, 0, dev_info->info->var.xres,
-		  dev_info->info->var.yres, 0x30, 0xff, 0x30);
-
-	return 0;
-
-out2:
-	fb_dealloc_cmap(&info->cmap);
-out1:
-	rvfree(info->screen_base, dev_info->screen_size);
-out0:
-	framebuffer_release(info);
-out:
-	usb_set_intfdata(interface, NULL);
-	usb_put_dev(dev_info->udev);
-	kfree(dev_info);
-	return -ENOMEM;
-
+	return result;
 }
 
-static void dlfb_disconnect(struct usb_interface *interface)
+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 metrics_misc_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,
+			"Calls to\ndamage: %u\nblit: %u\n"
+			"defio faults: %u\ncopy: %u\n"
+			"fill: %u\n\n"
+			"active framebuffer clients: %d\n"
+			"urbs available %d(%d)\n"
+			"Shadow framebuffer in use? %s\n"
+			"Any lost pixels? %s\n",
+			atomic_read(&dev->damage_count),
+			atomic_read(&dev->blit_count),
+			atomic_read(&dev->defio_fault_count),
+			atomic_read(&dev->copy_count),
+			atomic_read(&dev->fill_count),
+			dev->fb_count,
+			dev->urbs.available, dev->urbs.limit_sem.count,
+			(dev->backing_buffer) ? "yes" : "no",
+			atomic_read(&dev->lost_pixels) ? "yes" : "no");
+}
+
+static ssize_t edid_show(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;
+	char *edid = &dev->edid[0];
+	const size_t size = sizeof(dev->edid);
+
+	if (dlfb_parse_edid(dev, &fb_info->var, fb_info))
+		return 0;
+
+	if (off >= size)
+		return 0;
+
+	if (off + count > size)
+		count = size - off;
+	memcpy(buf, edid + off, count);
+
+	return count;
+}
+
+
+static ssize_t metrics_reset_store(struct device *fbdev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
-	struct dlfb_data *dev_info = usb_get_intfdata(interface);
+	struct fb_info *fb_info = dev_get_drvdata(fbdev);
+	struct dlfb_data *dev = fb_info->par;
 
-	mutex_unlock(&dev_info->bulk_mutex);
+	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);
+	atomic_set(&dev->blit_count, 0);
+	atomic_set(&dev->copy_count, 0);
+	atomic_set(&dev->fill_count, 0);
+	atomic_set(&dev->defio_fault_count, 0);
+	atomic_set(&dev->damage_count, 0);
 
-	usb_kill_urb(dev_info->tx_urb);
-	usb_free_urb(dev_info->tx_urb);
-	usb_set_intfdata(interface, NULL);
-	usb_put_dev(dev_info->udev);
+	return count;
+}
 
-	if (dev_info->info) {
-		unregister_framebuffer(dev_info->info);
-		fb_dealloc_cmap(&dev_info->info->cmap);
-		rvfree(dev_info->info->screen_base, dev_info->screen_size);
-		kfree(dev_info->backing_buffer);
-		framebuffer_release(dev_info->info);
+static ssize_t use_defio_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, "%d\n",
+			atomic_read(&dev->use_defio));
+}
 
+static ssize_t use_defio_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;
+
+	if (count > 0) {
+		if (buf[0] == '0')
+			atomic_set(&dev->use_defio, 0);
+		if (buf[0] == '1')
+			atomic_set(&dev->use_defio, 1);
+	}
+	return count;
+}
+
+static struct bin_attribute edid_attr = {
+	.attr.name = "edid",
+	.attr.mode = 0444,
+	.size = 128,
+	.read = edid_show,
+};
+
+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_RO(metrics_misc),
+	__ATTR(metrics_reset, S_IWUGO, NULL, metrics_reset_store),
+	__ATTR_RW(use_defio),
+};
+
+#ifdef CONFIG_FB_DEFERRED_IO
+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;
+	int fault_count = 0;
+
+	if (!atomic_read(&dev->use_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) {
+		dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
+				  &cmd, cur->index << PAGE_SHIFT,
+				  PAGE_SIZE, &bytes_identical, &bytes_sent);
+		bytes_rendered += PAGE_SIZE;
+		fault_count++;
 	}
 
-	kfree(dev_info);
+	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);
 
-	printk("DisplayLink device disconnected\n");
+	atomic_add(fault_count, &dev->defio_fault_count);
+	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 struct fb_deferred_io dlfb_defio = {
+	.delay          = 5,
+	.deferred_io    = dlfb_dpy_deferred_io,
+};
+
+#endif
+
+/*
+ * 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_usb_probe(struct usb_interface *interface,
+			const struct usb_device_id *id)
+{
+	struct usb_device *usbdev;
+	struct dlfb_data *dev;
+	struct fb_info *info;
+	int videomemorysize;
+	int i;
+	unsigned char *videomemory;
+	int retval = -ENOMEM;
+	struct fb_var_screeninfo *var;
+	int registered = 0;
+	u16 *pix_framebuffer;
+
+	/* 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 .fb_destroy function*/
+
+	dev->udev = usbdev;
+	dev->gdev = &usbdev->dev; /* our generic struct device * */
+	usb_set_intfdata(interface, dev);
+
+	if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
+		retval = -ENOMEM;
+		dl_err("dlfb_alloc_urb_list failed\n");
+		goto error;
+	}
+
+	mutex_init(&dev->fb_open_lock);
+
+	/* 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;
+
+	var = &info->var;
+
+	/* TODO set limit based on actual SKU detection */
+	dev->sku_pixel_limit = 2048 * 1152;
+
+	INIT_LIST_HEAD(&info->modelist);
+	dlfb_parse_edid(dev, var, info);
+
+	/*
+	 * ok, now that we've got the size info, we can alloc our framebuffer.
+	 */
+	info->fix = dlfb_fix;
+	info->fix.line_length = var->xres * (var->bits_per_pixel / 8);
+	videomemorysize = info->fix.line_length * var->yres;
+
+	/*
+	 * The big chunk of system memory we use as a virtual framebuffer.
+	 * TODO: Handle fbcon cursor code calling blit in interrupt context
+	 */
+	videomemory = vmalloc(videomemorysize);
+	if (!videomemory) {
+		retval = -ENOMEM;
+		dl_err("Virtual framebuffer alloc failed\n");
+		goto error;
+	}
+
+	info->screen_base = videomemory;
+	info->fix.smem_len = PAGE_ALIGN(videomemorysize);
+	info->fix.smem_start = (unsigned long) videomemory;
+	info->flags = udlfb_info_flags;
+
+
+	/*
+	 * Second framebuffer copy, mirroring the state of the framebuffer
+	 * on the physical USB device. We can function without this.
+	 * But with imperfect damage info we may end up sending pixels over USB
+	 * that were, in fact, unchanged -- wasting limited USB bandwidth
+	 */
+	dev->backing_buffer = vmalloc(videomemorysize);
+	if (!dev->backing_buffer)
+		dl_warn("No shadow/backing buffer allcoated\n");
+	else
+		memset(dev->backing_buffer, 0, videomemorysize);
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0) {
+		dl_err("fb_alloc_cmap failed %x\n", retval);
+		goto error;
+	}
+
+	/* ready to begin using device */
+
+#ifdef CONFIG_FB_DEFERRED_IO
+	atomic_set(&dev->use_defio, 1);
+#endif
+	atomic_set(&dev->usb_active, 1);
+	dlfb_select_std_channel(dev);
+
+	dlfb_ops_check_var(var, info);
+	dlfb_ops_set_par(info);
+
+	/* paint greenscreen */
+	pix_framebuffer = (u16 *) videomemory;
+	for (i = 0; i < videomemorysize / 2; i++)
+		pix_framebuffer[i] = 0x37e6;
+
+	dlfb_handle_damage(dev, 0, 0, info->var.xres, info->var.yres,
+				videomemory);
+
+	retval = register_framebuffer(info);
+	if (retval < 0) {
+		dl_err("register_framebuffer failed %d\n", retval);
+		goto error;
+	}
+	registered = 1;
+
+	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_err("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
+			" Using %dK framebuffer memory\n", info->node,
+			var->xres, var->yres,
+			((dev->backing_buffer) ?
+			videomemorysize * 2 : videomemorysize) >> 10);
+	return 0;
+
+error:
+	if (dev) {
+		if (registered) {
+			unregister_framebuffer(info);
+			dlfb_ops_destroy(info);
+		} else
+			kref_put(&dev->kref, dlfb_delete);
+
+		if (dev->urbs.count > 0)
+			dlfb_free_urb_list(dev);
+		kref_put(&dev->kref, dlfb_delete); /* 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;
+
+	/* when non-active we'll update virtual framebuffer, but no new urbs */
+	atomic_set(&dev->usb_active, 0);
+
+	usb_set_intfdata(interface, NULL);
+
+	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);
+
+	/* this function will wait for all in-flight urbs to complete */
+	dlfb_free_urb_list(dev);
+
+	if (info) {
+		dl_notice("Detaching /dev/fb%d\n", info->node);
+		unregister_framebuffer(info);
+		dlfb_ops_destroy(info);
+	}
+
+	/* release reference taken by kref_init in probe() */
+	kref_put(&dev->kref, dlfb_delete);
+
+	/* consider dlfb_data freed */
+
+	return;
 }
 
 static struct usb_driver dlfb_driver = {
 	.name = "udlfb",
-	.probe = dlfb_probe,
-	.disconnect = dlfb_disconnect,
+	.probe = dlfb_usb_probe,
+	.disconnect = dlfb_usb_disconnect,
 	.id_table = id_table,
 };
 
-static int __init dlfb_init(void)
+static int __init dlfb_module_init(void)
 {
 	int res;
 
-	dlfb_init_modes();
-
 	res = usb_register(&dlfb_driver);
 	if (res)
 		err("usb_register failed. Error number %d", res);
@@ -925,14 +1442,186 @@
 	return res;
 }
 
-static void __exit dlfb_exit(void)
+static void __exit dlfb_module_exit(void)
 {
 	usb_deregister(&dlfb_driver);
 }
 
-module_init(dlfb_init);
-module_exit(dlfb_exit);
+module_init(dlfb_module_init);
+module_exit(dlfb_module_exit);
 
-MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>");
-MODULE_DESCRIPTION(DRIVER_VERSION);
+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);
+
+	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--) {
+		/* Timeout means a memory leak and/or fault */
+		ret = down_timeout(&dev->urbs.limit_sem, FREE_URB_TIMEOUT);
+		if (ret) {
+			BUG_ON(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_buffer_free(urb->dev, dev->urbs.size,
+			urb->transfer_buffer, urb->transfer_dma);
+		usb_free_urb(urb);
+		kfree(node);
+	}
+
+	kref_put(&dev->kref, dlfb_delete);
+
+}
+
+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;
+
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			kfree(unode);
+			break;
+		}
+		unode->urb = urb;
+
+		buf = usb_buffer_alloc(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;
+
+	kref_get(&dev->kref); /* released in free_render_urbs() */
+
+	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_err("wait for urb interrupted: %x\n", ret);
+		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_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
index 40ad85e..b07a693 100644
--- a/drivers/staging/udlfb/udlfb.h
+++ b/drivers/staging/udlfb/udlfb.h
@@ -1,225 +1,106 @@
 #ifndef UDLFB_H
 #define UDLFB_H
 
-#define MAX_VMODES	4
-#define FB_BPP		16
+/*
+ * 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;
+};
 
-#define STD_CHANNEL	"\x57\xCD\xDC\xA7\x1C\x88\x5E\x15"	\
-			"\x60\xFE\xC6\x97\x16\x3D\x47\xF2"
+struct urb_node {
+	struct list_head entry;
+	struct dlfb_data *dev;
+	struct urb *urb;
+};
 
-/* as libdlo */
-#define BUF_HIGH_WATER_MARK	1024
-#define BUF_SIZE		(64*1024)
+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 usb_interface *interface;
-	struct urb *tx_urb, *ctrl_urb;
-	struct usb_ctrlrequest dr;
+	struct device *gdev; /* &udev->dev */
 	struct fb_info *info;
-	char *buf;
-	char *bufend;
+	struct urb_list urbs;
+	struct kref kref;
 	char *backing_buffer;
-	struct mutex bulk_mutex;
+	struct delayed_work deferred_work;
+	struct mutex fb_open_lock;
+	int fb_count;
+	atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
+	atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
+	atomic_t use_defio; /* 0 = rely on ioctls and blit/copy/fill rects */
 	char edid[128];
-	int screen_size;
-	int line_length;
-	struct completion done;
+	int sku_pixel_limit;
 	int base16;
-	int base16d;
 	int base8;
-	int base8d;
+	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 */
+	/* interface usage metrics. Clients can call driver via several */
+	atomic_t blit_count;
+	atomic_t copy_count;
+	atomic_t fill_count;
+	atomic_t damage_count;
+	atomic_t defio_fault_count;
 };
 
-struct dlfb_video_mode {
-	uint8_t col;
-	uint32_t hclock;
-	uint32_t vclock;
-	uint8_t unknown1[6];
-	uint16_t xres;
-	uint8_t unknown2[6];
-	uint16_t yres;
-	uint8_t unknown3[4];
-} __attribute__ ((__packed__));
+#define NR_USB_REQUEST_I2C_SUB_IO 0x02
+#define NR_USB_REQUEST_CHANNEL 0x12
 
-static struct dlfb_video_mode dlfb_video_modes[MAX_VMODES];
+/* -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)
 
-static void dlfb_bulk_callback(struct urb *urb)
-{
-	struct dlfb_data *dev_info = urb->context;
-	complete(&dev_info->done);
-}
+#define GET_URB_TIMEOUT	HZ
+#define FREE_URB_TIMEOUT (HZ*2)
 
-static void dlfb_edid(struct dlfb_data *dev_info)
-{
-	int i;
-	int ret;
-	char rbuf[2];
+#define BPP                     2
+#define MAX_CMD_PIXELS		255
 
-	for (i = 0; i < 128; i++) {
-		ret =
-		    usb_control_msg(dev_info->udev,
-				    usb_rcvctrlpipe(dev_info->udev, 0), (0x02),
-				    (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
-				    0);
-		/*printk("ret control msg edid %d: %d [%d]\n",i, ret, rbuf[1]); */
-		dev_info->edid[i] = rbuf[1];
-	}
+#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)
 
-static int dlfb_bulk_msg(struct dlfb_data *dev_info, int len)
-{
-	int ret;
+#define RAW_HEADER_BYTES	6
+#define MIN_RAW_PIX_BYTES	2
+#define MIN_RAW_CMD_BYTES	(RAW_HEADER_BYTES + MIN_RAW_PIX_BYTES)
 
-	init_completion(&dev_info->done);
+/* 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)
 
-	dev_info->tx_urb->actual_length = 0;
-	dev_info->tx_urb->transfer_buffer_length = len;
+/* remove once this gets added to sysfs.h */
+#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
 
-	ret = usb_submit_urb(dev_info->tx_urb, GFP_KERNEL);
-	if (!wait_for_completion_timeout(&dev_info->done, 1000)) {
-		usb_kill_urb(dev_info->tx_urb);
-		printk("usb timeout !!!\n");
-	}
-
-	return dev_info->tx_urb->actual_length;
-}
-
-static void dlfb_init_modes(void)
-{
-	dlfb_video_modes[0].col = 0;
-	memcpy(&dlfb_video_modes[0].hclock, "\x20\x3C\x7A\xC9", 4);
-	memcpy(&dlfb_video_modes[0].vclock, "\xF2\x6C\x48\xF9", 4);
-	memcpy(&dlfb_video_modes[0].unknown1, "\x70\x53\xFF\xFF\x21\x27", 6);
-	dlfb_video_modes[0].xres = 800;
-	memcpy(&dlfb_video_modes[0].unknown2, "\x91\xF3\xFF\xFF\xFF\xF9", 6);
-	dlfb_video_modes[0].yres = 480;
-	memcpy(&dlfb_video_modes[0].unknown3, "\x01\x02\xC8\x19", 4);
-
-	dlfb_video_modes[1].col = 0;
-	memcpy(&dlfb_video_modes[1].hclock, "\x36\x18\xD5\x10", 4);
-	memcpy(&dlfb_video_modes[1].vclock, "\x60\xA9\x7B\x33", 4);
-	memcpy(&dlfb_video_modes[1].unknown1, "\xA1\x2B\x27\x32\xFF\xFF", 6);
-	dlfb_video_modes[1].xres = 1024;
-	memcpy(&dlfb_video_modes[1].unknown2, "\xD9\x9A\xFF\xCA\xFF\xFF", 6);
-	dlfb_video_modes[1].yres = 768;
-	memcpy(&dlfb_video_modes[1].unknown3, "\x04\x03\xC8\x32", 4);
-
-	dlfb_video_modes[2].col = 0;
-	memcpy(&dlfb_video_modes[2].hclock, "\x98\xF8\x0D\x57", 4);
-	memcpy(&dlfb_video_modes[2].vclock, "\x2A\x55\x4D\x54", 4);
-	memcpy(&dlfb_video_modes[2].unknown1, "\xCA\x0D\xFF\xFF\x94\x43", 6);
-	dlfb_video_modes[2].xres = 1280;
-	memcpy(&dlfb_video_modes[2].unknown2, "\x9A\xA8\xFF\xFF\xFF\xF9", 6);
-	dlfb_video_modes[2].yres = 1024;
-	memcpy(&dlfb_video_modes[2].unknown3, "\x04\x02\x60\x54", 4);
-
-	dlfb_video_modes[3].col = 0;
-	memcpy(&dlfb_video_modes[3].hclock, "\x42\x24\x38\x36", 4);
-	memcpy(&dlfb_video_modes[3].vclock, "\xC1\x52\xD9\x29", 4);
-	memcpy(&dlfb_video_modes[3].unknown1, "\xEA\xB8\x32\x60\xFF\xFF", 6);
-	dlfb_video_modes[3].xres = 1400;
-	memcpy(&dlfb_video_modes[3].unknown2, "\xC9\x4E\xFF\xFF\xFF\xF2", 6);
-	dlfb_video_modes[3].yres = 1050;
-	memcpy(&dlfb_video_modes[3].unknown3, "\x04\x02\x1E\x5F", 4);
-}
-
-static char *dlfb_set_register(char *bufptr, uint8_t reg, uint8_t val)
-{
-	*bufptr++ = 0xAF;
-	*bufptr++ = 0x20;
-	*bufptr++ = reg;
-	*bufptr++ = val;
-
-	return bufptr;
-}
-
-static int dlfb_set_video_mode(struct dlfb_data *dev_info, int width, int height)
-{
-	int i, ret;
-	unsigned char j;
-	char *bufptr = dev_info->buf;
-	uint8_t *vdata;
-
-	for (i = 0; i < MAX_VMODES; i++) {
-		printk("INIT VIDEO %d %d %d\n", i, dlfb_video_modes[i].xres,
-		       dlfb_video_modes[i].yres);
-		if (dlfb_video_modes[i].xres == width
-		    && dlfb_video_modes[i].yres == height) {
-
-			dev_info->base16 = 0;
-			dev_info->base16d = width * height * (FB_BPP / 8);
-
-			//dev_info->base8 = width * height * (FB_BPP / 8);
-
-			dev_info->base8 = dev_info->base16;
-			dev_info->base8d = dev_info->base16d;
-
-			/* set encryption key (null) */
-			memcpy(dev_info->buf, STD_CHANNEL, 16);
-			ret =
-			    usb_control_msg(dev_info->udev,
-					    usb_sndctrlpipe(dev_info->udev, 0),
-					    0x12, (0x02 << 5), 0, 0,
-					    dev_info->buf, 16, 0);
-			printk("ret control msg 1 (STD_CHANNEL): %d\n", ret);
-
-			/* set registers */
-			bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
-
-			/* set color depth */
-			bufptr = dlfb_set_register(bufptr, 0x00, 0x00);
-
-			/* set addresses */
-			bufptr =
-			    dlfb_set_register(bufptr, 0x20,
-					      (char)(dev_info->base16 >> 16));
-			bufptr =
-			    dlfb_set_register(bufptr, 0x21,
-					      (char)(dev_info->base16 >> 8));
-			bufptr =
-			    dlfb_set_register(bufptr, 0x22,
-					      (char)(dev_info->base16));
-
-			bufptr =
-			    dlfb_set_register(bufptr, 0x26,
-					      (char)(dev_info->base8 >> 16));
-			bufptr =
-			    dlfb_set_register(bufptr, 0x27,
-					      (char)(dev_info->base8 >> 8));
-			bufptr =
-			    dlfb_set_register(bufptr, 0x28,
-					      (char)(dev_info->base8));
-
-			/* set video mode */
-			vdata = (uint8_t *)&dlfb_video_modes[i];
-			for (j = 0; j < 29; j++)
-				bufptr = dlfb_set_register(bufptr, j, vdata[j]);
-
-			/* blank */
-			bufptr = dlfb_set_register(bufptr, 0x1F, 0x00);
-
-			/* end registers */
-			bufptr = dlfb_set_register(bufptr, 0xFF, 0xFF);
-
-			/* send */
-			ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
-			printk("ret bulk 2: %d %td\n", ret,
-			       bufptr - dev_info->buf);
-
-			/* flush */
-			ret = dlfb_bulk_msg(dev_info, 0);
-			printk("ret bulk 3: %d\n", ret);
-
-			dev_info->screen_size = width * height * (FB_BPP / 8);
-			dev_info->line_length = width * (FB_BPP / 8);
-
-			return 0;
-		}
-	}
-
-	return -1;
-}
-
+#define dl_err(format, arg...) \
+	dev_err(dev->gdev, "dlfb: " format, ## arg)
+#define dl_warn(format, arg...) \
+	dev_warn(dev->gdev, "dlfb: " format, ## arg)
+#define dl_notice(format, arg...) \
+	dev_notice(dev->gdev, "dlfb: " format, ## arg)
+#define dl_info(format, arg...) \
+	dev_info(dev->gdev, "dlfb: " format, ## arg)
 #endif
diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig
index 350d5d6..2c1d10a 100644
--- a/drivers/staging/usbip/Kconfig
+++ b/drivers/staging/usbip/Kconfig
@@ -34,3 +34,10 @@
 
 	 To compile this driver as a module, choose M here: the
 	 module will be called usbip.
+
+config USB_IP_DEBUG_ENABLE
+	bool "USB-IP Debug Enable"
+	depends on USB_IP_COMMON
+	default N
+	---help---
+	  This enables the debug messages from the USB-IP drivers.
diff --git a/drivers/staging/usbip/Makefile b/drivers/staging/usbip/Makefile
index 179f421..6f2916b 100644
--- a/drivers/staging/usbip/Makefile
+++ b/drivers/staging/usbip/Makefile
@@ -7,6 +7,6 @@
 obj-$(CONFIG_USB_IP_HOST) += usbip.o
 usbip-objs := stub_dev.o stub_main.o stub_rx.o stub_tx.o
 
-ifeq ($(CONFIG_USB_DEBUG),y)
+ifeq ($(CONFIG_USB_IP_DEBUG_ENABLE),y)
 	EXTRA_CFLAGS += -DDEBUG
 endif
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index ddb6f5f..7a45da8 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -33,7 +33,7 @@
 /*-------------------------------------------------------------------------*/
 /* debug routines */
 
-#ifdef CONFIG_USB_DEBUG
+#ifdef CONFIG_USB_IP_DEBUG_ENABLE
 unsigned long usbip_debug_flag = 0xffffffff;
 #else
 unsigned long usbip_debug_flag;
@@ -55,10 +55,7 @@
 static ssize_t store_flag(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	unsigned long flag;
-
-	sscanf(buf, "%lx", &flag);
-	usbip_debug_flag = flag;
+	sscanf(buf, "%lx", &usbip_debug_flag);
 
 	return count;
 }
@@ -66,33 +63,8 @@
 
 static void usbip_dump_buffer(char *buff, int bufflen)
 {
-	int i;
-
-	if (bufflen > 128) {
-		for (i = 0; i < 128; i++) {
-			if (i%24 == 0)
-				printk(KERN_DEBUG "   ");
-			printk(KERN_DEBUG "%02x ", (unsigned char) buff[i]);
-			if (i%4 == 3)
-				printk(KERN_DEBUG "| ");
-			if (i%24 == 23)
-				printk(KERN_DEBUG "\n");
-		}
-		printk(KERN_DEBUG "... (%d byte)\n", bufflen);
-		return;
-	}
-
-	for (i = 0; i < bufflen; i++) {
-		if (i%24 == 0)
-			printk(KERN_DEBUG "   ");
-		printk(KERN_DEBUG "%02x ", (unsigned char) buff[i]);
-		if (i%4 == 3)
-			printk(KERN_DEBUG "| ");
-		if (i%24 == 23)
-			printk(KERN_DEBUG "\n");
-	}
-	printk(KERN_DEBUG "\n");
-
+	print_hex_dump(KERN_DEBUG, "usb-ip", DUMP_PREFIX_OFFSET, 16, 4,
+		       buff, bufflen, false);
 }
 
 static void usbip_dump_pipe(unsigned int p)
@@ -558,60 +530,6 @@
 }
 EXPORT_SYMBOL_GPL(usbip_xmit);
 
-
-/* now a usrland utility should set options. */
-#if 0
-int setquickack(struct socket *socket)
-{
-	mm_segment_t oldfs;
-	int val = 1;
-	int ret;
-
-	oldfs = get_fs();
-	set_fs(get_ds());
-	ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_QUICKACK,
-			(char __user *) &val, sizeof(ret));
-	set_fs(oldfs);
-
-	return ret;
-}
-
-int setnodelay(struct socket *socket)
-{
-	mm_segment_t oldfs;
-	int val = 1;
-	int ret;
-
-	oldfs = get_fs();
-	set_fs(get_ds());
-	ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_NODELAY,
-			(char __user *) &val, sizeof(ret));
-	set_fs(oldfs);
-
-	return ret;
-}
-
-int setkeepalive(struct socket *socket)
-{
-	mm_segment_t oldfs;
-	int val = 1;
-	int ret;
-
-	oldfs = get_fs();
-	set_fs(get_ds());
-	ret = socket->ops->setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE,
-			(char __user *) &val, sizeof(ret));
-	set_fs(oldfs);
-
-	return ret;
-}
-
-void setreuse(struct socket *socket)
-{
-	socket->sk->sk_reuse = 1;
-}
-#endif
-
 struct socket *sockfd_to_socket(unsigned int sockfd)
 {
 	struct socket *socket;
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
index 1ca3eab..6f1dcb1 100644
--- a/drivers/staging/usbip/usbip_common.h
+++ b/drivers/staging/usbip/usbip_common.h
@@ -33,12 +33,12 @@
  */
 
 /**
- * usbip_udbg - print debug messages if CONFIG_USB_DEBUG is defined
+ * usbip_udbg - print debug messages if CONFIG_USB_IP_DEBUG_ENABLE is defined
  * @fmt:
  * @args:
  */
 
-#ifdef CONFIG_USB_DEBUG
+#ifdef CONFIG_USB_IP_DEBUG_ENABLE
 
 #define usbip_udbg(fmt, args...)					\
 	do {								\
@@ -47,11 +47,11 @@
 			__FILE__, __LINE__, __func__, ##args);		\
 	} while (0)
 
-#else  /* CONFIG_USB_DEBUG */
+#else  /* CONFIG_USB_IP_DEBUG_ENABLE */
 
 #define usbip_udbg(fmt, args...)		do { } while (0)
 
-#endif /* CONFIG_USB_DEBUG */
+#endif /* CONFIG_USB_IP_DEBUG_ENABLE */
 
 
 enum {
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
index d8992d1..f6e34e0 100644
--- a/drivers/staging/usbip/vhci_sysfs.c
+++ b/drivers/staging/usbip/vhci_sysfs.c
@@ -144,7 +144,7 @@
 	case USB_SPEED_LOW:
 	case USB_SPEED_FULL:
 	case USB_SPEED_HIGH:
-	case USB_SPEED_VARIABLE:
+	case USB_SPEED_WIRELESS:
 		break;
 	default:
 		usbip_uerr("speed %d\n", speed);
diff --git a/drivers/staging/vme/Kconfig b/drivers/staging/vme/Kconfig
index ae628a5..6411ae5 100644
--- a/drivers/staging/vme/Kconfig
+++ b/drivers/staging/vme/Kconfig
@@ -14,4 +14,6 @@
 
 source "drivers/staging/vme/devices/Kconfig"
 
+source "drivers/staging/vme/boards/Kconfig"
+
 endif # VME
diff --git a/drivers/staging/vme/Makefile b/drivers/staging/vme/Makefile
index 8c3b90e..b4ea3f8 100644
--- a/drivers/staging/vme/Makefile
+++ b/drivers/staging/vme/Makefile
@@ -5,3 +5,4 @@
 
 obj-y				+= bridges/
 obj-y				+= devices/
+obj-y				+= boards/
diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO
index 2201ff6..82c222b 100644
--- a/drivers/staging/vme/TODO
+++ b/drivers/staging/vme/TODO
@@ -4,28 +4,6 @@
 API
 ===
 
-DMA Resource Allocation incomplete
-----------------------------------
-
-The current DMA resource Allocation provides no means of selecting the
-suitability of a DMA controller based on it's supported modes of operation, as
-opposed to the resource allocation mechanisms for master and slave windows:
-
-	struct vme_resource *vme_dma_request(struct device *dev);
-
-As opposed to:
-
-	struct vme_resource * vme_master_request(struct device *dev,
-		vme_address_t aspace, vme_cycle_t cycle, vme_width_t width);
-
-The TSI148 can perform, VME-to-PCI, PCI-to-VME, PATTERN-to-VME, PATTERN-to-PCI,
-VME-to-VME and PCI-to-PCI transfers. The CA91C142 can only provide VME-to-PCI
-and PCI-to-VME.
-
-Add a mechanism to select a VME controller based on source/target type,
-required aspace, cycle and width requirements.
-
-
 Master window broadcast select mask
 -----------------------------------
 
@@ -59,7 +37,6 @@
 Core
 ====
 
-- Rename vme_master_resource's "pci_resource" to be bus agnostic.
 - Improve generic sanity checks (Such as does an offset and size fit within a
   window and parameter checking).
 
@@ -69,7 +46,6 @@
 Tempe (tsi148)
 --------------
 
-- Driver can currently only support a single bridge.
 - 2eSST Broadcast mode.
 - Mailboxes unsupported.
 - Improve error detection.
@@ -80,10 +56,6 @@
 Universe II (ca91c142)
 ----------------------
 
-- Driver can currently only support a single bridge.
-- DMA unsupported.
-- RMW transactions unsupported.
-- Location Monitors unsupported.
 - Mailboxes unsupported.
 - Error Detection.
 - Control of prefetch size, threshold.
diff --git a/drivers/staging/vme/boards/Kconfig b/drivers/staging/vme/boards/Kconfig
new file mode 100644
index 0000000..7616313
--- /dev/null
+++ b/drivers/staging/vme/boards/Kconfig
@@ -0,0 +1,9 @@
+comment "VME Board Drivers"
+
+config VMIVME_7805
+	tristate "VMIVME-7805"
+	help
+	  If you say Y here you get support for the VMIVME-7805 board.
+	  This board has an additional control interface to the Universe II
+	  chip. This driver has to be included if you want to access VME bus
+	  with VMIVME-7805 board.
diff --git a/drivers/staging/vme/boards/Makefile b/drivers/staging/vme/boards/Makefile
new file mode 100644
index 0000000..4365834
--- /dev/null
+++ b/drivers/staging/vme/boards/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the VME board drivers.
+#
+
+obj-$(CONFIG_VMIVME_7805)	+= vme_vmivme7805.o
diff --git a/drivers/staging/vme/boards/vme_vmivme7805.c b/drivers/staging/vme/boards/vme_vmivme7805.c
new file mode 100644
index 0000000..843c9ed
--- /dev/null
+++ b/drivers/staging/vme/boards/vme_vmivme7805.c
@@ -0,0 +1,124 @@
+/*
+ * Support for the VMIVME-7805 board access to the Universe II bridge.
+ *
+ * Author: Arthur Benilov <arthur.benilov@iba-group.com>
+ * Copyright 2010 Ion Beam Application, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+
+#include "vme_vmivme7805.h"
+
+static int __init vmic_init(void);
+static int vmic_probe(struct pci_dev *, const struct pci_device_id *);
+static void vmic_remove(struct pci_dev *);
+static void __exit vmic_exit(void);
+
+/** Base address to access FPGA register */
+static void *vmic_base;
+
+static char driver_name[] = "vmivme_7805";
+
+static struct pci_device_id vmic_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_VMIC, PCI_DEVICE_ID_VTIMR) },
+	{ },
+};
+
+static struct pci_driver vmic_driver = {
+	.name = driver_name,
+	.id_table = vmic_ids,
+	.probe = vmic_probe,
+	.remove = vmic_remove,
+};
+
+static int __init vmic_init(void)
+{
+	return pci_register_driver(&vmic_driver);
+}
+
+static int vmic_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	int retval;
+	u32 data;
+
+	/* Enable the device */
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "Unable to enable device\n");
+		goto err;
+	}
+
+	/* Map Registers */
+	retval = pci_request_regions(pdev, driver_name);
+	if (retval) {
+		dev_err(&pdev->dev, "Unable to reserve resources\n");
+		goto err_resource;
+	}
+
+	/* Map registers in BAR 0 */
+	vmic_base = ioremap_nocache(pci_resource_start(pdev, 0), 16);
+	if (!vmic_base) {
+		dev_err(&pdev->dev, "Unable to remap CRG region\n");
+		retval = -EIO;
+		goto err_remap;
+	}
+
+	/* Clear the FPGA VME IF contents */
+	iowrite32(0, vmic_base + VME_CONTROL);
+
+	/* Clear any initial BERR  */
+	data = ioread32(vmic_base + VME_CONTROL) & 0x00000FFF;
+	data |= BM_VME_CONTROL_BERRST;
+	iowrite32(data, vmic_base + VME_CONTROL);
+
+	/* Enable the vme interface and byte swapping */
+	data = ioread32(vmic_base + VME_CONTROL) & 0x00000FFF;
+	data = data | BM_VME_CONTROL_MASTER_ENDIAN |
+			BM_VME_CONTROL_SLAVE_ENDIAN |
+			BM_VME_CONTROL_ABLE |
+			BM_VME_CONTROL_BERRI |
+			BM_VME_CONTROL_BPENA |
+			BM_VME_CONTROL_VBENA;
+	iowrite32(data, vmic_base + VME_CONTROL);
+
+	return 0;
+
+err_remap:
+	pci_release_regions(pdev);
+err_resource:
+	pci_disable_device(pdev);
+err:
+	return retval;
+}
+
+static void vmic_remove(struct pci_dev *pdev)
+{
+	iounmap(vmic_base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+
+}
+
+static void __exit vmic_exit(void)
+{
+	pci_unregister_driver(&vmic_driver);
+}
+
+MODULE_DESCRIPTION("VMIVME-7805 board support driver");
+MODULE_AUTHOR("Arthur Benilov <arthur.benilov@iba-group.com>");
+MODULE_LICENSE("GPL");
+
+module_init(vmic_init);
+module_exit(vmic_exit);
+
diff --git a/drivers/staging/vme/boards/vme_vmivme7805.h b/drivers/staging/vme/boards/vme_vmivme7805.h
new file mode 100644
index 0000000..44c2c44
--- /dev/null
+++ b/drivers/staging/vme/boards/vme_vmivme7805.h
@@ -0,0 +1,37 @@
+/*
+ * vmivme_7805.h
+ *
+ * Support for the VMIVME-7805 board access to the Universe II bridge.
+ *
+ * Author: Arthur Benilov <arthur.benilov@iba-group.com>
+ * Copyright 2010 Ion Beam Application, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+
+#ifndef _VMIVME_7805_H
+#define _VMIVME_7805_H
+
+#ifndef PCI_VENDOR_ID_VMIC
+#define PCI_VENDOR_ID_VMIC		0x114A
+#endif
+
+#ifndef PCI_DEVICE_ID_VTIMR
+#define PCI_DEVICE_ID_VTIMR		0x0004
+#endif
+
+#define VME_CONTROL			0x0000
+#define BM_VME_CONTROL_MASTER_ENDIAN	0x0001
+#define BM_VME_CONTROL_SLAVE_ENDIAN	0x0002
+#define BM_VME_CONTROL_ABLE		0x0004
+#define BM_VME_CONTROL_BERRI		0x0040
+#define BM_VME_CONTROL_BERRST		0x0080
+#define BM_VME_CONTROL_BPENA		0x0400
+#define BM_VME_CONTROL_VBENA		0x0800
+
+#endif /* _VMIVME_7805_H */
+
diff --git a/drivers/staging/vme/bridges/Kconfig b/drivers/staging/vme/bridges/Kconfig
index 023cceb..9331064 100644
--- a/drivers/staging/vme/bridges/Kconfig
+++ b/drivers/staging/vme/bridges/Kconfig
@@ -2,12 +2,14 @@
 
 config VME_CA91CX42
 	tristate "Universe II"
+	depends on VIRT_TO_BUS
 	help
 	 If you say Y here you get support for the Tundra CA91C142
 	 (Universe II) VME bridge chip.
 
 config VME_TSI148
 	tristate "Tempe"
+	depends on VIRT_TO_BUS
 	help
 	 If you say Y here you get support for the Tundra TSI148 VME bridge
 	 chip.
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index 1cf3e91..2795ff2 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
@@ -1,8 +1,8 @@
 /*
  * Support for the Tundra Universe I/II VME-PCI Bridge Chips
  *
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
  *
  * Based on work by Tom Armistead and Ajit Prem
  * Copyright 2004 Motorola Inc.
@@ -38,25 +38,12 @@
 static void ca91cx42_remove(struct pci_dev *);
 static void __exit ca91cx42_exit(void);
 
-struct vme_bridge *ca91cx42_bridge;
-wait_queue_head_t dma_queue;
-wait_queue_head_t iack_queue;
-wait_queue_head_t lm_queue;
-wait_queue_head_t mbox_queue;
-
-void (*lm_callback[4])(int);    /* Called in interrupt handler, be careful! */
-void *crcsr_kernel;
-dma_addr_t crcsr_bus;
-
-struct mutex vme_rmw;   /* Only one RMW cycle at a time */
-struct mutex vme_int;   /*
-			 * Only one VME interrupt can be
-			 * generated at a time, provide locking
-			 */
+/* Module parameters */
+static int geoid;
 
 static char driver_name[] = "vme_ca91cx42";
 
-static struct pci_device_id ca91cx42_ids[] = {
+static const struct pci_device_id ca91cx42_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) },
 	{ },
 };
@@ -68,14 +55,14 @@
 	.remove = ca91cx42_remove,
 };
 
-static u32 ca91cx42_DMA_irqhandler(void)
+static u32 ca91cx42_DMA_irqhandler(struct ca91cx42_driver *bridge)
 {
-	wake_up(&dma_queue);
+	wake_up(&(bridge->dma_queue));
 
 	return CA91CX42_LINT_DMA;
 }
 
-static u32 ca91cx42_LM_irqhandler(u32 stat)
+static u32 ca91cx42_LM_irqhandler(struct ca91cx42_driver *bridge, u32 stat)
 {
 	int i;
 	u32 serviced = 0;
@@ -83,7 +70,7 @@
 	for (i = 0; i < 4; i++) {
 		if (stat & CA91CX42_LINT_LM[i]) {
 			/* We only enable interrupts if the callback is set */
-			lm_callback[i](i);
+			bridge->lm_callback[i](i);
 			serviced |= CA91CX42_LINT_LM[i];
 		}
 	}
@@ -92,40 +79,25 @@
 }
 
 /* XXX This needs to be split into 4 queues */
-static u32 ca91cx42_MB_irqhandler(int mbox_mask)
+static u32 ca91cx42_MB_irqhandler(struct ca91cx42_driver *bridge, int mbox_mask)
 {
-	wake_up(&mbox_queue);
+	wake_up(&(bridge->mbox_queue));
 
 	return CA91CX42_LINT_MBOX;
 }
 
-static u32 ca91cx42_IACK_irqhandler(void)
+static u32 ca91cx42_IACK_irqhandler(struct ca91cx42_driver *bridge)
 {
-	wake_up(&iack_queue);
+	wake_up(&(bridge->iack_queue));
 
 	return CA91CX42_LINT_SW_IACK;
 }
 
-#if 0
-int ca91cx42_bus_error_chk(int clrflag)
-{
-	int tmp;
-	tmp = ioread32(ca91cx42_bridge->base + PCI_COMMAND);
-	if (tmp & 0x08000000) {	/* S_TA is Set */
-		if (clrflag)
-			iowrite32(tmp | 0x08000000,
-			       ca91cx42_bridge->base + PCI_COMMAND);
-		return 1;
-	}
-	return 0;
-}
-#endif
-
-static u32 ca91cx42_VERR_irqhandler(void)
+static u32 ca91cx42_VERR_irqhandler(struct ca91cx42_driver *bridge)
 {
 	int val;
 
-	val = ioread32(ca91cx42_bridge->base + DGCS);
+	val = ioread32(bridge->base + DGCS);
 
 	if (!(val & 0x00000800)) {
 		printk(KERN_ERR "ca91c042: ca91cx42_VERR_irqhandler DMA Read "
@@ -135,11 +107,11 @@
 	return CA91CX42_LINT_VERR;
 }
 
-static u32 ca91cx42_LERR_irqhandler(void)
+static u32 ca91cx42_LERR_irqhandler(struct ca91cx42_driver *bridge)
 {
 	int val;
 
-	val = ioread32(ca91cx42_bridge->base + DGCS);
+	val = ioread32(bridge->base + DGCS);
 
 	if (!(val & 0x00000800)) {
 		printk(KERN_ERR "ca91c042: ca91cx42_LERR_irqhandler DMA Read "
@@ -151,13 +123,18 @@
 }
 
 
-static u32 ca91cx42_VIRQ_irqhandler(int stat)
+static u32 ca91cx42_VIRQ_irqhandler(struct vme_bridge *ca91cx42_bridge,
+	int stat)
 {
 	int vec, i, serviced = 0;
+	struct ca91cx42_driver *bridge;
+
+	bridge = ca91cx42_bridge->driver_priv;
+
 
 	for (i = 7; i > 0; i--) {
 		if (stat & (1 << i)) {
-			vec = ioread32(ca91cx42_bridge->base +
+			vec = ioread32(bridge->base +
 				CA91CX42_V_STATID[i]) & 0xff;
 
 			vme_irq_handler(ca91cx42_bridge, i, vec);
@@ -169,15 +146,18 @@
 	return serviced;
 }
 
-static irqreturn_t ca91cx42_irqhandler(int irq, void *dev_id)
+static irqreturn_t ca91cx42_irqhandler(int irq, void *ptr)
 {
 	u32 stat, enable, serviced = 0;
+	struct vme_bridge *ca91cx42_bridge;
+	struct ca91cx42_driver *bridge;
 
-	if (dev_id != ca91cx42_bridge->base)
-		return IRQ_NONE;
+	ca91cx42_bridge = ptr;
 
-	enable = ioread32(ca91cx42_bridge->base + LINT_EN);
-	stat = ioread32(ca91cx42_bridge->base + LINT_STAT);
+	bridge = ca91cx42_bridge->driver_priv;
+
+	enable = ioread32(bridge->base + LINT_EN);
+	stat = ioread32(bridge->base + LINT_STAT);
 
 	/* Only look at unmasked interrupts */
 	stat &= enable;
@@ -186,42 +166,45 @@
 		return IRQ_NONE;
 
 	if (stat & CA91CX42_LINT_DMA)
-		serviced |= ca91cx42_DMA_irqhandler();
+		serviced |= ca91cx42_DMA_irqhandler(bridge);
 	if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 |
 			CA91CX42_LINT_LM3))
-		serviced |= ca91cx42_LM_irqhandler(stat);
+		serviced |= ca91cx42_LM_irqhandler(bridge, stat);
 	if (stat & CA91CX42_LINT_MBOX)
-		serviced |= ca91cx42_MB_irqhandler(stat);
+		serviced |= ca91cx42_MB_irqhandler(bridge, stat);
 	if (stat & CA91CX42_LINT_SW_IACK)
-		serviced |= ca91cx42_IACK_irqhandler();
+		serviced |= ca91cx42_IACK_irqhandler(bridge);
 	if (stat & CA91CX42_LINT_VERR)
-		serviced |= ca91cx42_VERR_irqhandler();
+		serviced |= ca91cx42_VERR_irqhandler(bridge);
 	if (stat & CA91CX42_LINT_LERR)
-		serviced |= ca91cx42_LERR_irqhandler();
+		serviced |= ca91cx42_LERR_irqhandler(bridge);
 	if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 |
 			CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 |
 			CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 |
 			CA91CX42_LINT_VIRQ7))
-		serviced |= ca91cx42_VIRQ_irqhandler(stat);
+		serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat);
 
 	/* Clear serviced interrupts */
-	iowrite32(stat, ca91cx42_bridge->base + LINT_STAT);
+	iowrite32(stat, bridge->base + LINT_STAT);
 
 	return IRQ_HANDLED;
 }
 
-static int ca91cx42_irq_init(struct vme_bridge *bridge)
+static int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge)
 {
 	int result, tmp;
 	struct pci_dev *pdev;
+	struct ca91cx42_driver *bridge;
+
+	bridge = ca91cx42_bridge->driver_priv;
 
 	/* Need pdev */
-	pdev = container_of(bridge->parent, struct pci_dev, dev);
+	pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev);
 
 	/* Initialise list for VME bus errors */
-	INIT_LIST_HEAD(&(bridge->vme_errors));
+	INIT_LIST_HEAD(&(ca91cx42_bridge->vme_errors));
 
-	mutex_init(&(bridge->irq_mtx));
+	mutex_init(&(ca91cx42_bridge->irq_mtx));
 
 	/* Disable interrupts from PCI to VME */
 	iowrite32(0, bridge->base + VINT_EN);
@@ -232,7 +215,7 @@
 	iowrite32(0x00FFFFFF, bridge->base + LINT_STAT);
 
 	result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED,
-			driver_name, pdev);
+			driver_name, ca91cx42_bridge);
 	if (result) {
 		dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n",
 		       pdev->irq);
@@ -254,15 +237,16 @@
 	return 0;
 }
 
-static void ca91cx42_irq_exit(struct pci_dev *pdev)
+static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge,
+	struct pci_dev *pdev)
 {
 	/* Disable interrupts from PCI to VME */
-	iowrite32(0, ca91cx42_bridge->base + VINT_EN);
+	iowrite32(0, bridge->base + VINT_EN);
 
 	/* Disable PCI interrupts */
-	iowrite32(0, ca91cx42_bridge->base + LINT_EN);
+	iowrite32(0, bridge->base + LINT_EN);
 	/* Clear Any Pending PCI Interrupts */
-	iowrite32(0x00FFFFFF, ca91cx42_bridge->base + LINT_STAT);
+	iowrite32(0x00FFFFFF, bridge->base + LINT_STAT);
 
 	free_irq(pdev->irq, pdev);
 }
@@ -270,21 +254,25 @@
 /*
  * Set up an VME interrupt
  */
-void ca91cx42_irq_set(int level, int state, int sync)
+void ca91cx42_irq_set(struct vme_bridge *ca91cx42_bridge, int level, int state,
+	int sync)
 
 {
 	struct pci_dev *pdev;
 	u32 tmp;
+	struct ca91cx42_driver *bridge;
+
+	bridge = ca91cx42_bridge->driver_priv;
 
 	/* Enable IRQ level */
-	tmp = ioread32(ca91cx42_bridge->base + LINT_EN);
+	tmp = ioread32(bridge->base + LINT_EN);
 
 	if (state == 0)
 		tmp &= ~CA91CX42_LINT_VIRQ[level];
 	else
 		tmp |= CA91CX42_LINT_VIRQ[level];
 
-	iowrite32(tmp, ca91cx42_bridge->base + LINT_EN);
+	iowrite32(tmp, bridge->base + LINT_EN);
 
 	if ((state == 0) && (sync != 0)) {
 		pdev = container_of(ca91cx42_bridge->parent, struct pci_dev,
@@ -294,34 +282,38 @@
 	}
 }
 
-int ca91cx42_irq_generate(int level, int statid)
+int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level,
+	int statid)
 {
 	u32 tmp;
+	struct ca91cx42_driver *bridge;
+
+	bridge = ca91cx42_bridge->driver_priv;
 
 	/* Universe can only generate even vectors */
 	if (statid & 1)
 		return -EINVAL;
 
-	mutex_lock(&(vme_int));
+	mutex_lock(&(bridge->vme_int));
 
-	tmp = ioread32(ca91cx42_bridge->base + VINT_EN);
+	tmp = ioread32(bridge->base + VINT_EN);
 
 	/* Set Status/ID */
-	iowrite32(statid << 24, ca91cx42_bridge->base + STATID);
+	iowrite32(statid << 24, bridge->base + STATID);
 
 	/* Assert VMEbus IRQ */
 	tmp = tmp | (1 << (level + 24));
-	iowrite32(tmp, ca91cx42_bridge->base + VINT_EN);
+	iowrite32(tmp, bridge->base + VINT_EN);
 
 	/* Wait for IACK */
-	wait_event_interruptible(iack_queue, 0);
+	wait_event_interruptible(bridge->iack_queue, 0);
 
 	/* Return interrupt to low state */
-	tmp = ioread32(ca91cx42_bridge->base + VINT_EN);
+	tmp = ioread32(bridge->base + VINT_EN);
 	tmp = tmp & ~(1 << (level + 24));
-	iowrite32(tmp, ca91cx42_bridge->base + VINT_EN);
+	iowrite32(tmp, bridge->base + VINT_EN);
 
-	mutex_unlock(&(vme_int));
+	mutex_unlock(&(bridge->vme_int));
 
 	return 0;
 }
@@ -330,9 +322,12 @@
 	unsigned long long vme_base, unsigned long long size,
 	dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle)
 {
-	unsigned int i, addr = 0, granularity = 0;
+	unsigned int i, addr = 0, granularity;
 	unsigned int temp_ctl = 0;
 	unsigned int vme_bound, pci_offset;
+	struct ca91cx42_driver *bridge;
+
+	bridge = image->parent->driver_priv;
 
 	i = image->number;
 
@@ -366,13 +361,9 @@
 	 * Bound address is a valid address for the window, adjust
 	 * accordingly
 	 */
-	vme_bound = vme_base + size - granularity;
+	vme_bound = vme_base + size;
 	pci_offset = pci_base - vme_base;
 
-	/* XXX Need to check that vme_base, vme_bound and pci_offset aren't
-	 * too big for registers
-	 */
-
 	if ((i == 0) || (i == 4))
 		granularity = 0x1000;
 	else
@@ -392,26 +383,14 @@
 	}
 
 	/* Disable while we are mucking around */
-	temp_ctl = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]);
+	temp_ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]);
 	temp_ctl &= ~CA91CX42_VSI_CTL_EN;
-	iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]);
+	iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]);
 
 	/* Setup mapping */
-	iowrite32(vme_base, ca91cx42_bridge->base + CA91CX42_VSI_BS[i]);
-	iowrite32(vme_bound, ca91cx42_bridge->base + CA91CX42_VSI_BD[i]);
-	iowrite32(pci_offset, ca91cx42_bridge->base + CA91CX42_VSI_TO[i]);
-
-/* XXX Prefetch stuff currently unsupported */
-#if 0
-	if (vmeIn->wrPostEnable)
-		temp_ctl |= CA91CX42_VSI_CTL_PWEN;
-	if (vmeIn->prefetchEnable)
-		temp_ctl |= CA91CX42_VSI_CTL_PREN;
-	if (vmeIn->rmwLock)
-		temp_ctl |= CA91CX42_VSI_CTL_LLRMW;
-	if (vmeIn->data64BitCapable)
-		temp_ctl |= CA91CX42_VSI_CTL_LD64EN;
-#endif
+	iowrite32(vme_base, bridge->base + CA91CX42_VSI_BS[i]);
+	iowrite32(vme_bound, bridge->base + CA91CX42_VSI_BD[i]);
+	iowrite32(pci_offset, bridge->base + CA91CX42_VSI_TO[i]);
 
 	/* Setup address space */
 	temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M;
@@ -429,12 +408,12 @@
 		temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA;
 
 	/* Write ctl reg without enable */
-	iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]);
+	iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]);
 
 	if (enabled)
 		temp_ctl |= CA91CX42_VSI_CTL_EN;
 
-	iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]);
+	iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]);
 
 	return 0;
 }
@@ -445,6 +424,9 @@
 {
 	unsigned int i, granularity = 0, ctl = 0;
 	unsigned long long vme_bound, pci_offset;
+	struct ca91cx42_driver *bridge;
+
+	bridge = image->parent->driver_priv;
 
 	i = image->number;
 
@@ -454,11 +436,11 @@
 		granularity = 0x10000;
 
 	/* Read Registers */
-	ctl = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]);
+	ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]);
 
-	*vme_base = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_BS[i]);
-	vme_bound = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_BD[i]);
-	pci_offset = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_TO[i]);
+	*vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]);
+	vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]);
+	pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]);
 
 	*pci_base = (dma_addr_t)vme_base + pci_offset;
 	*size = (unsigned long long)((vme_bound - *vme_base) + granularity);
@@ -502,6 +484,9 @@
 	unsigned long long existing_size;
 	int retval = 0;
 	struct pci_dev *pdev;
+	struct vme_bridge *ca91cx42_bridge;
+
+	ca91cx42_bridge = image->parent;
 
 	/* Find pci_dev container of dev */
 	if (ca91cx42_bridge->parent == NULL) {
@@ -510,8 +495,8 @@
 	}
 	pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev);
 
-	existing_size = (unsigned long long)(image->pci_resource.end -
-		image->pci_resource.start);
+	existing_size = (unsigned long long)(image->bus_resource.end -
+		image->bus_resource.start);
 
 	/* If the existing size is OK, return */
 	if (existing_size == (size - 1))
@@ -520,15 +505,15 @@
 	if (existing_size != 0) {
 		iounmap(image->kern_base);
 		image->kern_base = NULL;
-		if (image->pci_resource.name != NULL)
-			kfree(image->pci_resource.name);
-		release_resource(&(image->pci_resource));
-		memset(&(image->pci_resource), 0, sizeof(struct resource));
+		if (image->bus_resource.name != NULL)
+			kfree(image->bus_resource.name);
+		release_resource(&(image->bus_resource));
+		memset(&(image->bus_resource), 0, sizeof(struct resource));
 	}
 
-	if (image->pci_resource.name == NULL) {
-		image->pci_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
-		if (image->pci_resource.name == NULL) {
+	if (image->bus_resource.name == NULL) {
+		image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
+		if (image->bus_resource.name == NULL) {
 			printk(KERN_ERR "Unable to allocate memory for resource"
 				" name\n");
 			retval = -ENOMEM;
@@ -536,26 +521,26 @@
 		}
 	}
 
-	sprintf((char *)image->pci_resource.name, "%s.%d",
+	sprintf((char *)image->bus_resource.name, "%s.%d",
 		ca91cx42_bridge->name, image->number);
 
-	image->pci_resource.start = 0;
-	image->pci_resource.end = (unsigned long)size;
-	image->pci_resource.flags = IORESOURCE_MEM;
+	image->bus_resource.start = 0;
+	image->bus_resource.end = (unsigned long)size;
+	image->bus_resource.flags = IORESOURCE_MEM;
 
 	retval = pci_bus_alloc_resource(pdev->bus,
-		&(image->pci_resource), size, size, PCIBIOS_MIN_MEM,
+		&(image->bus_resource), size, size, PCIBIOS_MIN_MEM,
 		0, NULL, NULL);
 	if (retval) {
 		printk(KERN_ERR "Failed to allocate mem resource for "
 			"window %d size 0x%lx start 0x%lx\n",
 			image->number, (unsigned long)size,
-			(unsigned long)image->pci_resource.start);
+			(unsigned long)image->bus_resource.start);
 		goto err_resource;
 	}
 
 	image->kern_base = ioremap_nocache(
-		image->pci_resource.start, size);
+		image->bus_resource.start, size);
 	if (image->kern_base == NULL) {
 		printk(KERN_ERR "Failed to remap resource\n");
 		retval = -ENOMEM;
@@ -567,24 +552,24 @@
 	iounmap(image->kern_base);
 	image->kern_base = NULL;
 err_remap:
-	release_resource(&(image->pci_resource));
+	release_resource(&(image->bus_resource));
 err_resource:
-	kfree(image->pci_resource.name);
-	memset(&(image->pci_resource), 0, sizeof(struct resource));
+	kfree(image->bus_resource.name);
+	memset(&(image->bus_resource), 0, sizeof(struct resource));
 err_name:
 	return retval;
 }
 
 /*
- *  * Free and unmap PCI Resource
- *   */
+ * Free and unmap PCI Resource
+ */
 static void ca91cx42_free_resource(struct vme_master_resource *image)
 {
 	iounmap(image->kern_base);
 	image->kern_base = NULL;
-	release_resource(&(image->pci_resource));
-	kfree(image->pci_resource.name);
-	memset(&(image->pci_resource), 0, sizeof(struct resource));
+	release_resource(&(image->bus_resource));
+	kfree(image->bus_resource.name);
+	memset(&(image->bus_resource), 0, sizeof(struct resource));
 }
 
 
@@ -593,17 +578,27 @@
 	vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
 {
 	int retval = 0;
-	unsigned int i;
+	unsigned int i, granularity = 0;
 	unsigned int temp_ctl = 0;
 	unsigned long long pci_bound, vme_offset, pci_base;
+	struct ca91cx42_driver *bridge;
+
+	bridge = image->parent->driver_priv;
+
+	i = image->number;
+
+	if ((i == 0) || (i == 4))
+		granularity = 0x1000;
+	else
+		granularity = 0x10000;
 
 	/* Verify input data */
-	if (vme_base & 0xFFF) {
+	if (vme_base & (granularity - 1)) {
 		printk(KERN_ERR "Invalid VME Window alignment\n");
 		retval = -EINVAL;
 		goto err_window;
 	}
-	if (size & 0xFFF) {
+	if (size & (granularity - 1)) {
 		printk(KERN_ERR "Invalid VME Window alignment\n");
 		retval = -EINVAL;
 		goto err_window;
@@ -611,9 +606,6 @@
 
 	spin_lock(&(image->lock));
 
-	/* XXX We should do this much later, so that we can exit without
-	 *     needing to redo the mapping...
-	 */
 	/*
 	 * Let's allocate the resource here rather than further up the stack as
 	 * it avoids pushing loads of bus dependant stuff up the stack
@@ -627,27 +619,19 @@
 		goto err_res;
 	}
 
-	pci_base = (unsigned long long)image->pci_resource.start;
+	pci_base = (unsigned long long)image->bus_resource.start;
 
 	/*
 	 * Bound address is a valid address for the window, adjust
 	 * according to window granularity.
 	 */
-	pci_bound = pci_base + (size - 0x1000);
+	pci_bound = pci_base + size;
 	vme_offset = vme_base - pci_base;
 
-	i = image->number;
-
 	/* Disable while we are mucking around */
-	temp_ctl = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]);
+	temp_ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]);
 	temp_ctl &= ~CA91CX42_LSI_CTL_EN;
-	iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]);
-
-/* XXX Prefetch stuff currently unsupported */
-#if 0
-	if (vmeOut->wrPostEnable)
-		temp_ctl |= 0x40000000;
-#endif
+	iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]);
 
 	/* Setup cycle types */
 	temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M;
@@ -718,17 +702,17 @@
 		temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM;
 
 	/* Setup mapping */
-	iowrite32(pci_base, ca91cx42_bridge->base + CA91CX42_LSI_BS[i]);
-	iowrite32(pci_bound, ca91cx42_bridge->base + CA91CX42_LSI_BD[i]);
-	iowrite32(vme_offset, ca91cx42_bridge->base + CA91CX42_LSI_TO[i]);
+	iowrite32(pci_base, bridge->base + CA91CX42_LSI_BS[i]);
+	iowrite32(pci_bound, bridge->base + CA91CX42_LSI_BD[i]);
+	iowrite32(vme_offset, bridge->base + CA91CX42_LSI_TO[i]);
 
 	/* Write ctl reg without enable */
-	iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]);
+	iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]);
 
 	if (enabled)
 		temp_ctl |= CA91CX42_LSI_CTL_EN;
 
-	iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]);
+	iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]);
 
 	spin_unlock(&(image->lock));
 	return 0;
@@ -747,17 +731,20 @@
 {
 	unsigned int i, ctl;
 	unsigned long long pci_base, pci_bound, vme_offset;
+	struct ca91cx42_driver *bridge;
+
+	bridge = image->parent->driver_priv;
 
 	i = image->number;
 
-	ctl = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]);
+	ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]);
 
-	pci_base = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BS[i]);
-	vme_offset = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_TO[i]);
-	pci_bound = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BD[i]);
+	pci_base = ioread32(bridge->base + CA91CX42_LSI_BS[i]);
+	vme_offset = ioread32(bridge->base + CA91CX42_LSI_TO[i]);
+	pci_bound = ioread32(bridge->base + CA91CX42_LSI_BD[i]);
 
 	*vme_base = pci_base + vme_offset;
-	*size = (pci_bound - pci_base) + 0x1000;
+	*size = (unsigned long long)(pci_bound - pci_base);
 
 	*enabled = 0;
 	*aspace = 0;
@@ -822,12 +809,6 @@
 		break;
 	}
 
-/* XXX Prefetch stuff currently unsupported */
-#if 0
-	if (ctl & 0x40000000)
-		vmeOut->wrPostEnable = 1;
-#endif
-
 	return 0;
 }
 
@@ -850,7 +831,7 @@
 ssize_t ca91cx42_master_read(struct vme_master_resource *image, void *buf,
 	size_t count, loff_t offset)
 {
-	int retval;
+	ssize_t retval;
 
 	spin_lock(&(image->lock));
 
@@ -877,12 +858,528 @@
 	return retval;
 }
 
-int ca91cx42_slot_get(void)
+unsigned int ca91cx42_master_rmw(struct vme_master_resource *image,
+	unsigned int mask, unsigned int compare, unsigned int swap,
+	loff_t offset)
+{
+	u32 pci_addr, result;
+	int i;
+	struct ca91cx42_driver *bridge;
+	struct device *dev;
+
+	bridge = image->parent->driver_priv;
+	dev = image->parent->parent;
+
+	/* Find the PCI address that maps to the desired VME address */
+	i = image->number;
+
+	/* Locking as we can only do one of these at a time */
+	mutex_lock(&(bridge->vme_rmw));
+
+	/* Lock image */
+	spin_lock(&(image->lock));
+
+	pci_addr = (u32)image->kern_base + offset;
+
+	/* Address must be 4-byte aligned */
+	if (pci_addr & 0x3) {
+		dev_err(dev, "RMW Address not 4-byte aligned\n");
+		return -EINVAL;
+	}
+
+	/* Ensure RMW Disabled whilst configuring */
+	iowrite32(0, bridge->base + SCYC_CTL);
+
+	/* Configure registers */
+	iowrite32(mask, bridge->base + SCYC_EN);
+	iowrite32(compare, bridge->base + SCYC_CMP);
+	iowrite32(swap, bridge->base + SCYC_SWP);
+	iowrite32(pci_addr, bridge->base + SCYC_ADDR);
+
+	/* Enable RMW */
+	iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL);
+
+	/* Kick process off with a read to the required address. */
+	result = ioread32(image->kern_base + offset);
+
+	/* Disable RMW */
+	iowrite32(0, bridge->base + SCYC_CTL);
+
+	spin_unlock(&(image->lock));
+
+	mutex_unlock(&(bridge->vme_rmw));
+
+	return result;
+}
+
+int ca91cx42_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src,
+	struct vme_dma_attr *dest, size_t count)
+{
+	struct ca91cx42_dma_entry *entry, *prev;
+	struct vme_dma_pci *pci_attr;
+	struct vme_dma_vme *vme_attr;
+	dma_addr_t desc_ptr;
+	int retval = 0;
+
+	/* XXX descriptor must be aligned on 64-bit boundaries */
+	entry = (struct ca91cx42_dma_entry *)
+		kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL);
+	if (entry == NULL) {
+		printk(KERN_ERR "Failed to allocate memory for dma resource "
+			"structure\n");
+		retval = -ENOMEM;
+		goto err_mem;
+	}
+
+	/* Test descriptor alignment */
+	if ((unsigned long)&(entry->descriptor) & CA91CX42_DCPP_M) {
+		printk("Descriptor not aligned to 16 byte boundary as "
+			"required: %p\n", &(entry->descriptor));
+		retval = -EINVAL;
+		goto err_align;
+	}
+
+	memset(&(entry->descriptor), 0, sizeof(struct ca91cx42_dma_descriptor));
+
+	if (dest->type == VME_DMA_VME) {
+		entry->descriptor.dctl |= CA91CX42_DCTL_L2V;
+		vme_attr = (struct vme_dma_vme *)dest->private;
+		pci_attr = (struct vme_dma_pci *)src->private;
+	} else {
+		vme_attr = (struct vme_dma_vme *)src->private;
+		pci_attr = (struct vme_dma_pci *)dest->private;
+	}
+
+	/* Check we can do fullfill required attributes */
+	if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 |
+		VME_USER2)) != 0) {
+
+		printk(KERN_ERR "Unsupported cycle type\n");
+		retval = -EINVAL;
+		goto err_aspace;
+	}
+
+	if ((vme_attr->cycle & ~(VME_SCT | VME_BLT | VME_SUPER | VME_USER |
+		VME_PROG | VME_DATA)) != 0) {
+
+		printk(KERN_ERR "Unsupported cycle type\n");
+		retval = -EINVAL;
+		goto err_cycle;
+	}
+
+	/* Check to see if we can fullfill source and destination */
+	if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) ||
+		((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) {
+
+		printk(KERN_ERR "Cannot perform transfer with this "
+			"source-destination combination\n");
+		retval = -EINVAL;
+		goto err_direct;
+	}
+
+	/* Setup cycle types */
+	if (vme_attr->cycle & VME_BLT)
+		entry->descriptor.dctl |= CA91CX42_DCTL_VCT_BLT;
+
+	/* Setup data width */
+	switch (vme_attr->dwidth) {
+	case VME_D8:
+		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D8;
+		break;
+	case VME_D16:
+		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D16;
+		break;
+	case VME_D32:
+		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D32;
+		break;
+	case VME_D64:
+		entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D64;
+		break;
+	default:
+		printk(KERN_ERR "Invalid data width\n");
+		return -EINVAL;
+	}
+
+	/* Setup address space */
+	switch (vme_attr->aspace) {
+	case VME_A16:
+		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A16;
+		break;
+	case VME_A24:
+		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A24;
+		break;
+	case VME_A32:
+		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A32;
+		break;
+	case VME_USER1:
+		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER1;
+		break;
+	case VME_USER2:
+		entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER2;
+		break;
+	default:
+		printk(KERN_ERR "Invalid address space\n");
+		return -EINVAL;
+		break;
+	}
+
+	if (vme_attr->cycle & VME_SUPER)
+		entry->descriptor.dctl |= CA91CX42_DCTL_SUPER_SUPR;
+	if (vme_attr->cycle & VME_PROG)
+		entry->descriptor.dctl |= CA91CX42_DCTL_PGM_PGM;
+
+	entry->descriptor.dtbc = count;
+	entry->descriptor.dla = pci_attr->address;
+	entry->descriptor.dva = vme_attr->address;
+	entry->descriptor.dcpp = CA91CX42_DCPP_NULL;
+
+	/* Add to list */
+	list_add_tail(&(entry->list), &(list->entries));
+
+	/* Fill out previous descriptors "Next Address" */
+	if (entry->list.prev != &(list->entries)) {
+		prev = list_entry(entry->list.prev, struct ca91cx42_dma_entry,
+			list);
+		/* We need the bus address for the pointer */
+		desc_ptr = virt_to_bus(&(entry->descriptor));
+		prev->descriptor.dcpp = desc_ptr & ~CA91CX42_DCPP_M;
+	}
+
+	return 0;
+
+err_cycle:
+err_aspace:
+err_direct:
+err_align:
+	kfree(entry);
+err_mem:
+	return retval;
+}
+
+static int ca91cx42_dma_busy(struct vme_bridge *ca91cx42_bridge)
+{
+	u32 tmp;
+	struct ca91cx42_driver *bridge;
+
+	bridge = ca91cx42_bridge->driver_priv;
+
+	tmp = ioread32(bridge->base + DGCS);
+
+	if (tmp & CA91CX42_DGCS_ACT)
+		return 0;
+	else
+		return 1;
+}
+
+int ca91cx42_dma_list_exec(struct vme_dma_list *list)
+{
+	struct vme_dma_resource *ctrlr;
+	struct ca91cx42_dma_entry *entry;
+	int retval = 0;
+	dma_addr_t bus_addr;
+	u32 val;
+
+	struct ca91cx42_driver *bridge;
+
+	ctrlr = list->parent;
+
+	bridge = ctrlr->parent->driver_priv;
+
+	mutex_lock(&(ctrlr->mtx));
+
+	if (!(list_empty(&(ctrlr->running)))) {
+		/*
+		 * XXX We have an active DMA transfer and currently haven't
+		 *     sorted out the mechanism for "pending" DMA transfers.
+		 *     Return busy.
+		 */
+		/* Need to add to pending here */
+		mutex_unlock(&(ctrlr->mtx));
+		return -EBUSY;
+	} else {
+		list_add(&(list->list), &(ctrlr->running));
+	}
+
+	/* Get first bus address and write into registers */
+	entry = list_first_entry(&(list->entries), struct ca91cx42_dma_entry,
+		list);
+
+	bus_addr = virt_to_bus(&(entry->descriptor));
+
+	mutex_unlock(&(ctrlr->mtx));
+
+	iowrite32(0, bridge->base + DTBC);
+	iowrite32(bus_addr & ~CA91CX42_DCPP_M, bridge->base + DCPP);
+
+	/* Start the operation */
+	val = ioread32(bridge->base + DGCS);
+
+	/* XXX Could set VMEbus On and Off Counters here */
+	val &= (CA91CX42_DGCS_VON_M | CA91CX42_DGCS_VOFF_M);
+
+	val |= (CA91CX42_DGCS_CHAIN | CA91CX42_DGCS_STOP | CA91CX42_DGCS_HALT |
+		CA91CX42_DGCS_DONE | CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR |
+		CA91CX42_DGCS_PERR);
+
+	iowrite32(val, bridge->base + DGCS);
+
+	val |= CA91CX42_DGCS_GO;
+
+	iowrite32(val, bridge->base + DGCS);
+
+	wait_event_interruptible(bridge->dma_queue,
+		ca91cx42_dma_busy(ctrlr->parent));
+
+	/*
+	 * Read status register, this register is valid until we kick off a
+	 * new transfer.
+	 */
+	val = ioread32(bridge->base + DGCS);
+
+	if (val & (CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR |
+		CA91CX42_DGCS_PERR)) {
+
+		printk(KERN_ERR "ca91c042: DMA Error. DGCS=%08X\n", val);
+		val = ioread32(bridge->base + DCTL);
+	}
+
+	/* Remove list from running list */
+	mutex_lock(&(ctrlr->mtx));
+	list_del(&(list->list));
+	mutex_unlock(&(ctrlr->mtx));
+
+	return retval;
+
+}
+
+int ca91cx42_dma_list_empty(struct vme_dma_list *list)
+{
+	struct list_head *pos, *temp;
+	struct ca91cx42_dma_entry *entry;
+
+	/* detach and free each entry */
+	list_for_each_safe(pos, temp, &(list->entries)) {
+		list_del(pos);
+		entry = list_entry(pos, struct ca91cx42_dma_entry, list);
+		kfree(entry);
+	}
+
+	return 0;
+}
+
+/*
+ * All 4 location monitors reside at the same base - this is therefore a
+ * system wide configuration.
+ *
+ * This does not enable the LM monitor - that should be done when the first
+ * callback is attached and disabled when the last callback is removed.
+ */
+int ca91cx42_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
+	vme_address_t aspace, vme_cycle_t cycle)
+{
+	u32 temp_base, lm_ctl = 0;
+	int i;
+	struct ca91cx42_driver *bridge;
+	struct device *dev;
+
+	bridge = lm->parent->driver_priv;
+	dev = lm->parent->parent;
+
+	/* Check the alignment of the location monitor */
+	temp_base = (u32)lm_base;
+	if (temp_base & 0xffff) {
+		dev_err(dev, "Location monitor must be aligned to 64KB "
+			"boundary");
+		return -EINVAL;
+	}
+
+	mutex_lock(&(lm->mtx));
+
+	/* If we already have a callback attached, we can't move it! */
+	for (i = 0; i < lm->monitors; i++) {
+		if (bridge->lm_callback[i] != NULL) {
+			mutex_unlock(&(lm->mtx));
+			dev_err(dev, "Location monitor callback attached, "
+				"can't reset\n");
+			return -EBUSY;
+		}
+	}
+
+	switch (aspace) {
+	case VME_A16:
+		lm_ctl |= CA91CX42_LM_CTL_AS_A16;
+		break;
+	case VME_A24:
+		lm_ctl |= CA91CX42_LM_CTL_AS_A24;
+		break;
+	case VME_A32:
+		lm_ctl |= CA91CX42_LM_CTL_AS_A32;
+		break;
+	default:
+		mutex_unlock(&(lm->mtx));
+		dev_err(dev, "Invalid address space\n");
+		return -EINVAL;
+		break;
+	}
+
+	if (cycle & VME_SUPER)
+		lm_ctl |= CA91CX42_LM_CTL_SUPR;
+	if (cycle & VME_USER)
+		lm_ctl |= CA91CX42_LM_CTL_NPRIV;
+	if (cycle & VME_PROG)
+		lm_ctl |= CA91CX42_LM_CTL_PGM;
+	if (cycle & VME_DATA)
+		lm_ctl |= CA91CX42_LM_CTL_DATA;
+
+	iowrite32(lm_base, bridge->base + LM_BS);
+	iowrite32(lm_ctl, bridge->base + LM_CTL);
+
+	mutex_unlock(&(lm->mtx));
+
+	return 0;
+}
+
+/* Get configuration of the callback monitor and return whether it is enabled
+ * or disabled.
+ */
+int ca91cx42_lm_get(struct vme_lm_resource *lm, unsigned long long *lm_base,
+	vme_address_t *aspace, vme_cycle_t *cycle)
+{
+	u32 lm_ctl, enabled = 0;
+	struct ca91cx42_driver *bridge;
+
+	bridge = lm->parent->driver_priv;
+
+	mutex_lock(&(lm->mtx));
+
+	*lm_base = (unsigned long long)ioread32(bridge->base + LM_BS);
+	lm_ctl = ioread32(bridge->base + LM_CTL);
+
+	if (lm_ctl & CA91CX42_LM_CTL_EN)
+		enabled = 1;
+
+	if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16)
+		*aspace = VME_A16;
+	if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24)
+		*aspace = VME_A24;
+	if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32)
+		*aspace = VME_A32;
+
+	*cycle = 0;
+	if (lm_ctl & CA91CX42_LM_CTL_SUPR)
+		*cycle |= VME_SUPER;
+	if (lm_ctl & CA91CX42_LM_CTL_NPRIV)
+		*cycle |= VME_USER;
+	if (lm_ctl & CA91CX42_LM_CTL_PGM)
+		*cycle |= VME_PROG;
+	if (lm_ctl & CA91CX42_LM_CTL_DATA)
+		*cycle |= VME_DATA;
+
+	mutex_unlock(&(lm->mtx));
+
+	return enabled;
+}
+
+/*
+ * Attach a callback to a specific location monitor.
+ *
+ * Callback will be passed the monitor triggered.
+ */
+int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor,
+	void (*callback)(int))
+{
+	u32 lm_ctl, tmp;
+	struct ca91cx42_driver *bridge;
+	struct device *dev;
+
+	bridge = lm->parent->driver_priv;
+	dev = lm->parent->parent;
+
+	mutex_lock(&(lm->mtx));
+
+	/* Ensure that the location monitor is configured - need PGM or DATA */
+	lm_ctl = ioread32(bridge->base + LM_CTL);
+	if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) {
+		mutex_unlock(&(lm->mtx));
+		dev_err(dev, "Location monitor not properly configured\n");
+		return -EINVAL;
+	}
+
+	/* Check that a callback isn't already attached */
+	if (bridge->lm_callback[monitor] != NULL) {
+		mutex_unlock(&(lm->mtx));
+		dev_err(dev, "Existing callback attached\n");
+		return -EBUSY;
+	}
+
+	/* Attach callback */
+	bridge->lm_callback[monitor] = callback;
+
+	/* Enable Location Monitor interrupt */
+	tmp = ioread32(bridge->base + LINT_EN);
+	tmp |= CA91CX42_LINT_LM[monitor];
+	iowrite32(tmp, bridge->base + LINT_EN);
+
+	/* Ensure that global Location Monitor Enable set */
+	if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) {
+		lm_ctl |= CA91CX42_LM_CTL_EN;
+		iowrite32(lm_ctl, bridge->base + LM_CTL);
+	}
+
+	mutex_unlock(&(lm->mtx));
+
+	return 0;
+}
+
+/*
+ * Detach a callback function forn a specific location monitor.
+ */
+int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor)
+{
+	u32 tmp;
+	struct ca91cx42_driver *bridge;
+
+	bridge = lm->parent->driver_priv;
+
+	mutex_lock(&(lm->mtx));
+
+	/* Disable Location Monitor and ensure previous interrupts are clear */
+	tmp = ioread32(bridge->base + LINT_EN);
+	tmp &= ~CA91CX42_LINT_LM[monitor];
+	iowrite32(tmp, bridge->base + LINT_EN);
+
+	iowrite32(CA91CX42_LINT_LM[monitor],
+		 bridge->base + LINT_STAT);
+
+	/* Detach callback */
+	bridge->lm_callback[monitor] = NULL;
+
+	/* If all location monitors disabled, disable global Location Monitor */
+	if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 |
+			CA91CX42_LINT_LM3)) == 0) {
+		tmp = ioread32(bridge->base + LM_CTL);
+		tmp &= ~CA91CX42_LM_CTL_EN;
+		iowrite32(tmp, bridge->base + LM_CTL);
+	}
+
+	mutex_unlock(&(lm->mtx));
+
+	return 0;
+}
+
+int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge)
 {
 	u32 slot = 0;
+	struct ca91cx42_driver *bridge;
 
-	slot = ioread32(ca91cx42_bridge->base + VCSR_BS);
-	slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27);
+	bridge = ca91cx42_bridge->driver_priv;
+
+	if (!geoid) {
+		slot = ioread32(bridge->base + VCSR_BS);
+		slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27);
+	} else
+		slot = geoid;
+
 	return (int)slot;
 
 }
@@ -900,19 +1397,21 @@
  * Auto-ID or Geographic address. This function ensures that the window is
  * enabled at an offset consistent with the boards geopgraphic address.
  */
-static int ca91cx42_crcsr_init(struct pci_dev *pdev)
+static int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge,
+	struct pci_dev *pdev)
 {
 	unsigned int crcsr_addr;
 	int tmp, slot;
+	struct ca91cx42_driver *bridge;
 
-/* XXX We may need to set this somehow as the Universe II does not support
- *     geographical addressing.
- */
-#if 0
-	if (vme_slotnum != -1)
-		iowrite32(vme_slotnum << 27, ca91cx42_bridge->base + VCSR_BS);
-#endif
-	slot = ca91cx42_slot_get();
+	bridge = ca91cx42_bridge->driver_priv;
+
+	slot = ca91cx42_slot_get(ca91cx42_bridge);
+
+	/* Write CSR Base Address if slot ID is supplied as a module param */
+	if (geoid)
+		iowrite32(geoid << 27, bridge->base + VCSR_BS);
+
 	dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot);
 	if (slot == 0) {
 		dev_err(&pdev->dev, "Slot number is unset, not configuring "
@@ -921,39 +1420,44 @@
 	}
 
 	/* Allocate mem for CR/CSR image */
-	crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
-		&crcsr_bus);
-	if (crcsr_kernel == NULL) {
+	bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
+		&(bridge->crcsr_bus));
+	if (bridge->crcsr_kernel == NULL) {
 		dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR "
 			"image\n");
 		return -ENOMEM;
 	}
 
-	memset(crcsr_kernel, 0, VME_CRCSR_BUF_SIZE);
+	memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE);
 
 	crcsr_addr = slot * (512 * 1024);
-	iowrite32(crcsr_bus - crcsr_addr, ca91cx42_bridge->base + VCSR_TO);
+	iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO);
 
-	tmp = ioread32(ca91cx42_bridge->base + VCSR_CTL);
+	tmp = ioread32(bridge->base + VCSR_CTL);
 	tmp |= CA91CX42_VCSR_CTL_EN;
-	iowrite32(tmp, ca91cx42_bridge->base + VCSR_CTL);
+	iowrite32(tmp, bridge->base + VCSR_CTL);
 
 	return 0;
 }
 
-static void ca91cx42_crcsr_exit(struct pci_dev *pdev)
+static void ca91cx42_crcsr_exit(struct vme_bridge *ca91cx42_bridge,
+	struct pci_dev *pdev)
 {
 	u32 tmp;
+	struct ca91cx42_driver *bridge;
+
+	bridge = ca91cx42_bridge->driver_priv;
 
 	/* Turn off CR/CSR space */
-	tmp = ioread32(ca91cx42_bridge->base + VCSR_CTL);
+	tmp = ioread32(bridge->base + VCSR_CTL);
 	tmp &= ~CA91CX42_VCSR_CTL_EN;
-	iowrite32(tmp, ca91cx42_bridge->base + VCSR_CTL);
+	iowrite32(tmp, bridge->base + VCSR_CTL);
 
 	/* Free image */
-	iowrite32(0, ca91cx42_bridge->base + VCSR_TO);
+	iowrite32(0, bridge->base + VCSR_TO);
 
-	pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, crcsr_kernel, crcsr_bus);
+	pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel,
+		bridge->crcsr_bus);
 }
 
 static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -961,11 +1465,11 @@
 	int retval, i;
 	u32 data;
 	struct list_head *pos = NULL;
+	struct vme_bridge *ca91cx42_bridge;
+	struct ca91cx42_driver *ca91cx42_device;
 	struct vme_master_resource *master_image;
 	struct vme_slave_resource *slave_image;
-#if 0
 	struct vme_dma_resource *dma_ctrlr;
-#endif
 	struct vme_lm_resource *lm;
 
 	/* We want to support more than one of each bridge so we need to
@@ -982,6 +1486,19 @@
 
 	memset(ca91cx42_bridge, 0, sizeof(struct vme_bridge));
 
+	ca91cx42_device = kmalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL);
+
+	if (ca91cx42_device == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate memory for device "
+			"structure\n");
+		retval = -ENOMEM;
+		goto err_driver;
+	}
+
+	memset(ca91cx42_device, 0, sizeof(struct ca91cx42_driver));
+
+	ca91cx42_bridge->driver_priv = ca91cx42_device;
+
 	/* Enable the device */
 	retval = pci_enable_device(pdev);
 	if (retval) {
@@ -997,16 +1514,16 @@
 	}
 
 	/* map registers in BAR 0 */
-	ca91cx42_bridge->base = ioremap_nocache(pci_resource_start(pdev, 0),
+	ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0),
 		4096);
-	if (!ca91cx42_bridge->base) {
+	if (!ca91cx42_device->base) {
 		dev_err(&pdev->dev, "Unable to remap CRG region\n");
 		retval = -EIO;
 		goto err_remap;
 	}
 
 	/* Check to see if the mapping worked out */
-	data = ioread32(ca91cx42_bridge->base + CA91CX42_PCI_ID) & 0x0000FFFF;
+	data = ioread32(ca91cx42_device->base + CA91CX42_PCI_ID) & 0x0000FFFF;
 	if (data != PCI_VENDOR_ID_TUNDRA) {
 		dev_err(&pdev->dev, "PCI_ID check failed\n");
 		retval = -EIO;
@@ -1014,11 +1531,10 @@
 	}
 
 	/* Initialize wait queues & mutual exclusion flags */
-	/* XXX These need to be moved to the vme_bridge structure */
-	init_waitqueue_head(&dma_queue);
-	init_waitqueue_head(&iack_queue);
-	mutex_init(&(vme_int));
-	mutex_init(&(vme_rmw));
+	init_waitqueue_head(&(ca91cx42_device->dma_queue));
+	init_waitqueue_head(&(ca91cx42_device->iack_queue));
+	mutex_init(&(ca91cx42_device->vme_int));
+	mutex_init(&(ca91cx42_device->vme_rmw));
 
 	ca91cx42_bridge->parent = &(pdev->dev);
 	strcpy(ca91cx42_bridge->name, driver_name);
@@ -1050,7 +1566,7 @@
 		master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
 			VME_SUPER | VME_USER | VME_PROG | VME_DATA;
 		master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64;
-		memset(&(master_image->pci_resource), 0,
+		memset(&(master_image->bus_resource), 0,
 			sizeof(struct resource));
 		master_image->kern_base  = NULL;
 		list_add_tail(&(master_image->list),
@@ -1084,7 +1600,7 @@
 		list_add_tail(&(slave_image->list),
 			&(ca91cx42_bridge->slave_resources));
 	}
-#if 0
+
 	/* Add dma engines to list */
 	INIT_LIST_HEAD(&(ca91cx42_bridge->dma_resources));
 	for (i = 0; i < CA91C142_MAX_DMA; i++) {
@@ -1100,12 +1616,14 @@
 		mutex_init(&(dma_ctrlr->mtx));
 		dma_ctrlr->locked = 0;
 		dma_ctrlr->number = i;
+		dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM |
+			VME_DMA_MEM_TO_VME;
 		INIT_LIST_HEAD(&(dma_ctrlr->pending));
 		INIT_LIST_HEAD(&(dma_ctrlr->running));
 		list_add_tail(&(dma_ctrlr->list),
 			&(ca91cx42_bridge->dma_resources));
 	}
-#endif
+
 	/* Add location monitor to list */
 	INIT_LIST_HEAD(&(ca91cx42_bridge->lm_resources));
 	lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL);
@@ -1128,33 +1646,26 @@
 	ca91cx42_bridge->master_set = ca91cx42_master_set;
 	ca91cx42_bridge->master_read = ca91cx42_master_read;
 	ca91cx42_bridge->master_write = ca91cx42_master_write;
-#if 0
 	ca91cx42_bridge->master_rmw = ca91cx42_master_rmw;
 	ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add;
 	ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec;
 	ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty;
-#endif
 	ca91cx42_bridge->irq_set = ca91cx42_irq_set;
 	ca91cx42_bridge->irq_generate = ca91cx42_irq_generate;
-#if 0
 	ca91cx42_bridge->lm_set = ca91cx42_lm_set;
 	ca91cx42_bridge->lm_get = ca91cx42_lm_get;
 	ca91cx42_bridge->lm_attach = ca91cx42_lm_attach;
 	ca91cx42_bridge->lm_detach = ca91cx42_lm_detach;
-#endif
 	ca91cx42_bridge->slot_get = ca91cx42_slot_get;
 
-	data = ioread32(ca91cx42_bridge->base + MISC_CTL);
+	data = ioread32(ca91cx42_device->base + MISC_CTL);
 	dev_info(&pdev->dev, "Board is%s the VME system controller\n",
 		(data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not");
-	dev_info(&pdev->dev, "Slot ID is %d\n", ca91cx42_slot_get());
+	dev_info(&pdev->dev, "Slot ID is %d\n",
+		ca91cx42_slot_get(ca91cx42_bridge));
 
-	if (ca91cx42_crcsr_init(pdev)) {
+	if (ca91cx42_crcsr_init(ca91cx42_bridge, pdev)) {
 		dev_err(&pdev->dev, "CR/CSR configuration failed.\n");
-		retval = -EINVAL;
-#if 0
-		goto err_crcsr;
-#endif
 	}
 
 	/* Need to save ca91cx42_bridge pointer locally in link list for use in
@@ -1166,14 +1677,13 @@
 		goto err_reg;
 	}
 
+	pci_set_drvdata(pdev, ca91cx42_bridge);
+
 	return 0;
 
 	vme_unregister_bridge(ca91cx42_bridge);
 err_reg:
-	ca91cx42_crcsr_exit(pdev);
-#if 0
-err_crcsr:
-#endif
+	ca91cx42_crcsr_exit(ca91cx42_bridge, pdev);
 err_lm:
 	/* resources are stored in link list */
 	list_for_each(pos, &(ca91cx42_bridge->lm_resources)) {
@@ -1181,7 +1691,6 @@
 		list_del(pos);
 		kfree(lm);
 	}
-#if 0
 err_dma:
 	/* resources are stored in link list */
 	list_for_each(pos, &(ca91cx42_bridge->dma_resources)) {
@@ -1189,7 +1698,6 @@
 		list_del(pos);
 		kfree(dma_ctrlr);
 	}
-#endif
 err_slave:
 	/* resources are stored in link list */
 	list_for_each(pos, &(ca91cx42_bridge->slave_resources)) {
@@ -1206,15 +1714,17 @@
 		kfree(master_image);
 	}
 
-	ca91cx42_irq_exit(pdev);
+	ca91cx42_irq_exit(ca91cx42_device, pdev);
 err_irq:
 err_test:
-	iounmap(ca91cx42_bridge->base);
+	iounmap(ca91cx42_device->base);
 err_remap:
 	pci_release_regions(pdev);
 err_resource:
 	pci_disable_device(pdev);
 err_enable:
+	kfree(ca91cx42_device);
+err_driver:
 	kfree(ca91cx42_bridge);
 err_struct:
 	return retval;
@@ -1228,32 +1738,37 @@
 	struct vme_slave_resource *slave_image;
 	struct vme_dma_resource *dma_ctrlr;
 	struct vme_lm_resource *lm;
+	struct ca91cx42_driver *bridge;
+	struct vme_bridge *ca91cx42_bridge = pci_get_drvdata(pdev);
+
+	bridge = ca91cx42_bridge->driver_priv;
+
 
 	/* Turn off Ints */
-	iowrite32(0, ca91cx42_bridge->base + LINT_EN);
+	iowrite32(0, bridge->base + LINT_EN);
 
 	/* Turn off the windows */
-	iowrite32(0x00800000, ca91cx42_bridge->base + LSI0_CTL);
-	iowrite32(0x00800000, ca91cx42_bridge->base + LSI1_CTL);
-	iowrite32(0x00800000, ca91cx42_bridge->base + LSI2_CTL);
-	iowrite32(0x00800000, ca91cx42_bridge->base + LSI3_CTL);
-	iowrite32(0x00800000, ca91cx42_bridge->base + LSI4_CTL);
-	iowrite32(0x00800000, ca91cx42_bridge->base + LSI5_CTL);
-	iowrite32(0x00800000, ca91cx42_bridge->base + LSI6_CTL);
-	iowrite32(0x00800000, ca91cx42_bridge->base + LSI7_CTL);
-	iowrite32(0x00F00000, ca91cx42_bridge->base + VSI0_CTL);
-	iowrite32(0x00F00000, ca91cx42_bridge->base + VSI1_CTL);
-	iowrite32(0x00F00000, ca91cx42_bridge->base + VSI2_CTL);
-	iowrite32(0x00F00000, ca91cx42_bridge->base + VSI3_CTL);
-	iowrite32(0x00F00000, ca91cx42_bridge->base + VSI4_CTL);
-	iowrite32(0x00F00000, ca91cx42_bridge->base + VSI5_CTL);
-	iowrite32(0x00F00000, ca91cx42_bridge->base + VSI6_CTL);
-	iowrite32(0x00F00000, ca91cx42_bridge->base + VSI7_CTL);
+	iowrite32(0x00800000, bridge->base + LSI0_CTL);
+	iowrite32(0x00800000, bridge->base + LSI1_CTL);
+	iowrite32(0x00800000, bridge->base + LSI2_CTL);
+	iowrite32(0x00800000, bridge->base + LSI3_CTL);
+	iowrite32(0x00800000, bridge->base + LSI4_CTL);
+	iowrite32(0x00800000, bridge->base + LSI5_CTL);
+	iowrite32(0x00800000, bridge->base + LSI6_CTL);
+	iowrite32(0x00800000, bridge->base + LSI7_CTL);
+	iowrite32(0x00F00000, bridge->base + VSI0_CTL);
+	iowrite32(0x00F00000, bridge->base + VSI1_CTL);
+	iowrite32(0x00F00000, bridge->base + VSI2_CTL);
+	iowrite32(0x00F00000, bridge->base + VSI3_CTL);
+	iowrite32(0x00F00000, bridge->base + VSI4_CTL);
+	iowrite32(0x00F00000, bridge->base + VSI5_CTL);
+	iowrite32(0x00F00000, bridge->base + VSI6_CTL);
+	iowrite32(0x00F00000, bridge->base + VSI7_CTL);
 
 	vme_unregister_bridge(ca91cx42_bridge);
-#if 0
-	ca91cx42_crcsr_exit(pdev);
-#endif
+
+	ca91cx42_crcsr_exit(ca91cx42_bridge, pdev);
+
 	/* resources are stored in link list */
 	list_for_each(pos, &(ca91cx42_bridge->lm_resources)) {
 		lm = list_entry(pos, struct vme_lm_resource, list);
@@ -1283,9 +1798,9 @@
 		kfree(master_image);
 	}
 
-	ca91cx42_irq_exit(pdev);
+	ca91cx42_irq_exit(bridge, pdev);
 
-	iounmap(ca91cx42_bridge->base);
+	iounmap(bridge->base);
 
 	pci_release_regions(pdev);
 
@@ -1299,588 +1814,11 @@
 	pci_unregister_driver(&ca91cx42_driver);
 }
 
+MODULE_PARM_DESC(geoid, "Override geographical addressing");
+module_param(geoid, int, 0);
+
 MODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge");
 MODULE_LICENSE("GPL");
 
 module_init(ca91cx42_init);
 module_exit(ca91cx42_exit);
-
-/*----------------------------------------------------------------------------
- * STAGING
- *--------------------------------------------------------------------------*/
-
-#if 0
-#define	SWIZZLE(X) ( ((X & 0xFF000000) >> 24) | ((X & 0x00FF0000) >>  8) | ((X & 0x0000FF00) <<  8) | ((X & 0x000000FF) << 24))
-
-int ca91cx42_master_rmw(vmeRmwCfg_t *vmeRmw)
-{
-	int temp_ctl = 0;
-	int tempBS = 0;
-	int tempBD = 0;
-	int tempTO = 0;
-	int vmeBS = 0;
-	int vmeBD = 0;
-	int *rmw_pci_data_ptr = NULL;
-	int *vaDataPtr = NULL;
-	int i;
-	vmeOutWindowCfg_t vmeOut;
-	if (vmeRmw->maxAttempts < 1) {
-		return -EINVAL;
-	}
-	if (vmeRmw->targetAddrU) {
-		return -EINVAL;
-	}
-	/* Find the PCI address that maps to the desired VME address */
-	for (i = 0; i < 8; i++) {
-		temp_ctl = ioread32(ca91cx42_bridge->base +
-			CA91CX42_LSI_CTL[i]);
-		if ((temp_ctl & 0x80000000) == 0) {
-			continue;
-		}
-		memset(&vmeOut, 0, sizeof(vmeOut));
-		vmeOut.windowNbr = i;
-		ca91cx42_get_out_bound(&vmeOut);
-		if (vmeOut.addrSpace != vmeRmw->addrSpace) {
-			continue;
-		}
-		tempBS = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BS[i]);
-		tempBD = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BD[i]);
-		tempTO = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_TO[i]);
-		vmeBS = tempBS + tempTO;
-		vmeBD = tempBD + tempTO;
-		if ((vmeRmw->targetAddr >= vmeBS) &&
-		    (vmeRmw->targetAddr < vmeBD)) {
-			rmw_pci_data_ptr =
-			    (int *)(tempBS + (vmeRmw->targetAddr - vmeBS));
-			vaDataPtr =
-			    (int *)(out_image_va[i] +
-				    (vmeRmw->targetAddr - vmeBS));
-			break;
-		}
-	}
-
-	/* If no window - fail. */
-	if (rmw_pci_data_ptr == NULL) {
-		return -EINVAL;
-	}
-	/* Setup the RMW registers. */
-	iowrite32(0, ca91cx42_bridge->base + SCYC_CTL);
-	iowrite32(SWIZZLE(vmeRmw->enableMask), ca91cx42_bridge->base + SCYC_EN);
-	iowrite32(SWIZZLE(vmeRmw->compareData), ca91cx42_bridge->base +
-		SCYC_CMP);
-	iowrite32(SWIZZLE(vmeRmw->swapData), ca91cx42_bridge->base + SCYC_SWP);
-	iowrite32((int)rmw_pci_data_ptr, ca91cx42_bridge->base + SCYC_ADDR);
-	iowrite32(1, ca91cx42_bridge->base + SCYC_CTL);
-
-	/* Run the RMW cycle until either success or max attempts. */
-	vmeRmw->numAttempts = 1;
-	while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) {
-
-		if ((ioread32(vaDataPtr) & vmeRmw->enableMask) ==
-		    (vmeRmw->swapData & vmeRmw->enableMask)) {
-
-			iowrite32(0, ca91cx42_bridge->base + SCYC_CTL);
-			break;
-
-		}
-		vmeRmw->numAttempts++;
-	}
-
-	/* If no success, set num Attempts to be greater than max attempts */
-	if (vmeRmw->numAttempts > vmeRmw->maxAttempts) {
-		vmeRmw->numAttempts = vmeRmw->maxAttempts + 1;
-	}
-
-	return 0;
-}
-
-int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn)
-{
-	unsigned int dctlreg = 0x80;
-	struct vmeAttr *vmeAttr;
-
-	if (vmeDma->srcBus == VME_DMA_VME) {
-		dctlreg = 0;
-		vmeAttr = &vmeDma->srcVmeAttr;
-	} else {
-		dctlreg = 0x80000000;
-		vmeAttr = &vmeDma->dstVmeAttr;
-	}
-
-	switch (vmeAttr->maxDataWidth) {
-	case VME_D8:
-		break;
-	case VME_D16:
-		dctlreg |= 0x00400000;
-		break;
-	case VME_D32:
-		dctlreg |= 0x00800000;
-		break;
-	case VME_D64:
-		dctlreg |= 0x00C00000;
-		break;
-	}
-
-	switch (vmeAttr->addrSpace) {
-	case VME_A16:
-		break;
-	case VME_A24:
-		dctlreg |= 0x00010000;
-		break;
-	case VME_A32:
-		dctlreg |= 0x00020000;
-		break;
-	case VME_USER1:
-		dctlreg |= 0x00060000;
-		break;
-	case VME_USER2:
-		dctlreg |= 0x00070000;
-		break;
-
-	case VME_A64:		/* not supported in Universe DMA */
-	case VME_CRCSR:
-	case VME_USER3:
-	case VME_USER4:
-		return -EINVAL;
-		break;
-	}
-	if (vmeAttr->userAccessType == VME_PROG) {
-		dctlreg |= 0x00004000;
-	}
-	if (vmeAttr->dataAccessType == VME_SUPER) {
-		dctlreg |= 0x00001000;
-	}
-	if (vmeAttr->xferProtocol != VME_SCT) {
-		dctlreg |= 0x00000100;
-	}
-	*dctlregreturn = dctlreg;
-	return 0;
-}
-
-unsigned int
-ca91cx42_start_dma(int channel, unsigned int dgcsreg, TDMA_Cmd_Packet *vmeLL)
-{
-	unsigned int val;
-
-	/* Setup registers as needed for direct or chained. */
-	if (dgcsreg & 0x8000000) {
-		iowrite32(0, ca91cx42_bridge->base + DTBC);
-		iowrite32((unsigned int)vmeLL, ca91cx42_bridge->base + DCPP);
-	} else {
-#if	0
-		printk(KERN_ERR "Starting: DGCS = %08x\n", dgcsreg);
-		printk(KERN_ERR "Starting: DVA  = %08x\n",
-			ioread32(&vmeLL->dva));
-		printk(KERN_ERR "Starting: DLV  = %08x\n",
-			ioread32(&vmeLL->dlv));
-		printk(KERN_ERR "Starting: DTBC = %08x\n",
-			ioread32(&vmeLL->dtbc));
-		printk(KERN_ERR "Starting: DCTL = %08x\n",
-			ioread32(&vmeLL->dctl));
-#endif
-		/* Write registers */
-		iowrite32(ioread32(&vmeLL->dva), ca91cx42_bridge->base + DVA);
-		iowrite32(ioread32(&vmeLL->dlv), ca91cx42_bridge->base + DLA);
-		iowrite32(ioread32(&vmeLL->dtbc), ca91cx42_bridge->base + DTBC);
-		iowrite32(ioread32(&vmeLL->dctl), ca91cx42_bridge->base + DCTL);
-		iowrite32(0, ca91cx42_bridge->base + DCPP);
-	}
-
-	/* Start the operation */
-	iowrite32(dgcsreg, ca91cx42_bridge->base + DGCS);
-	val = get_tbl();
-	iowrite32(dgcsreg | 0x8000000F, ca91cx42_bridge->base + DGCS);
-	return val;
-}
-
-TDMA_Cmd_Packet *ca91cx42_setup_dma(vmeDmaPacket_t * vmeDma)
-{
-	vmeDmaPacket_t *vmeCur;
-	int maxPerPage;
-	int currentLLcount;
-	TDMA_Cmd_Packet *startLL;
-	TDMA_Cmd_Packet *currentLL;
-	TDMA_Cmd_Packet *nextLL;
-	unsigned int dctlreg = 0;
-
-	maxPerPage = PAGESIZE / sizeof(TDMA_Cmd_Packet) - 1;
-	startLL = (TDMA_Cmd_Packet *) __get_free_pages(GFP_KERNEL, 0);
-	if (startLL == 0) {
-		return startLL;
-	}
-	/* First allocate pages for descriptors and create linked list */
-	vmeCur = vmeDma;
-	currentLL = startLL;
-	currentLLcount = 0;
-	while (vmeCur != 0) {
-		if (vmeCur->pNextPacket != 0) {
-			currentLL->dcpp = (unsigned int)(currentLL + 1);
-			currentLLcount++;
-			if (currentLLcount >= maxPerPage) {
-				currentLL->dcpp =
-				    __get_free_pages(GFP_KERNEL, 0);
-				currentLLcount = 0;
-			}
-			currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
-		} else {
-			currentLL->dcpp = (unsigned int)0;
-		}
-		vmeCur = vmeCur->pNextPacket;
-	}
-
-	/* Next fill in information for each descriptor */
-	vmeCur = vmeDma;
-	currentLL = startLL;
-	while (vmeCur != 0) {
-		if (vmeCur->srcBus == VME_DMA_VME) {
-			iowrite32(vmeCur->srcAddr, &currentLL->dva);
-			iowrite32(vmeCur->dstAddr, &currentLL->dlv);
-		} else {
-			iowrite32(vmeCur->srcAddr, &currentLL->dlv);
-			iowrite32(vmeCur->dstAddr, &currentLL->dva);
-		}
-		uniSetupDctlReg(vmeCur, &dctlreg);
-		iowrite32(dctlreg, &currentLL->dctl);
-		iowrite32(vmeCur->byteCount, &currentLL->dtbc);
-
-		currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
-		vmeCur = vmeCur->pNextPacket;
-	}
-
-	/* Convert Links to PCI addresses. */
-	currentLL = startLL;
-	while (currentLL != 0) {
-		nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
-		if (nextLL == 0) {
-			iowrite32(1, &currentLL->dcpp);
-		} else {
-			iowrite32((unsigned int)virt_to_bus(nextLL),
-			       &currentLL->dcpp);
-		}
-		currentLL = nextLL;
-	}
-
-	/* Return pointer to descriptors list */
-	return startLL;
-}
-
-int ca91cx42_free_dma(TDMA_Cmd_Packet *startLL)
-{
-	TDMA_Cmd_Packet *currentLL;
-	TDMA_Cmd_Packet *prevLL;
-	TDMA_Cmd_Packet *nextLL;
-	unsigned int dcppreg;
-
-	/* Convert Links to virtual addresses. */
-	currentLL = startLL;
-	while (currentLL != 0) {
-		dcppreg = ioread32(&currentLL->dcpp);
-		dcppreg &= ~6;
-		if (dcppreg & 1) {
-			currentLL->dcpp = 0;
-		} else {
-			currentLL->dcpp = (unsigned int)bus_to_virt(dcppreg);
-		}
-		currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
-	}
-
-	/* Free all pages associated with the descriptors. */
-	currentLL = startLL;
-	prevLL = currentLL;
-	while (currentLL != 0) {
-		nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
-		if (currentLL + 1 != nextLL) {
-			free_pages((int)prevLL, 0);
-			prevLL = nextLL;
-		}
-		currentLL = nextLL;
-	}
-
-	/* Return pointer to descriptors list */
-	return 0;
-}
-
-int ca91cx42_do_dma(vmeDmaPacket_t *vmeDma)
-{
-	unsigned int dgcsreg = 0;
-	unsigned int dctlreg = 0;
-	int val;
-	int channel, x;
-	vmeDmaPacket_t *curDma;
-	TDMA_Cmd_Packet *dmaLL;
-
-	/* Sanity check the VME chain. */
-	channel = vmeDma->channel_number;
-	if (channel > 0) {
-		return -EINVAL;
-	}
-	curDma = vmeDma;
-	while (curDma != 0) {
-		if (curDma->byteCount == 0) {
-			return -EINVAL;
-		}
-		if (curDma->byteCount >= 0x1000000) {
-			return -EINVAL;
-		}
-		if ((curDma->srcAddr & 7) != (curDma->dstAddr & 7)) {
-			return -EINVAL;
-		}
-		switch (curDma->srcBus) {
-		case VME_DMA_PCI:
-			if (curDma->dstBus != VME_DMA_VME) {
-				return -EINVAL;
-			}
-			break;
-		case VME_DMA_VME:
-			if (curDma->dstBus != VME_DMA_PCI) {
-				return -EINVAL;
-			}
-			break;
-		default:
-			return -EINVAL;
-			break;
-		}
-		if (uniSetupDctlReg(curDma, &dctlreg) < 0) {
-			return -EINVAL;
-		}
-
-		curDma = curDma->pNextPacket;
-		if (curDma == vmeDma) {	/* Endless Loop! */
-			return -EINVAL;
-		}
-	}
-
-	/* calculate control register */
-	if (vmeDma->pNextPacket != 0) {
-		dgcsreg = 0x8000000;
-	} else {
-		dgcsreg = 0;
-	}
-
-	for (x = 0; x < 8; x++) {	/* vme block size */
-		if ((256 << x) >= vmeDma->maxVmeBlockSize) {
-			break;
-		}
-	}
-	if (x == 8)
-		x = 7;
-	dgcsreg |= (x << 20);
-
-	if (vmeDma->vmeBackOffTimer) {
-		for (x = 1; x < 8; x++) {	/* vme timer */
-			if ((16 << (x - 1)) >= vmeDma->vmeBackOffTimer) {
-				break;
-			}
-		}
-		if (x == 8)
-			x = 7;
-		dgcsreg |= (x << 16);
-	}
-	/*` Setup the dma chain */
-	dmaLL = ca91cx42_setup_dma(vmeDma);
-
-	/* Start the DMA */
-	if (dgcsreg & 0x8000000) {
-		vmeDma->vmeDmaStartTick =
-		    ca91cx42_start_dma(channel, dgcsreg,
-				  (TDMA_Cmd_Packet *) virt_to_phys(dmaLL));
-	} else {
-		vmeDma->vmeDmaStartTick =
-		    ca91cx42_start_dma(channel, dgcsreg, dmaLL);
-	}
-
-	wait_event_interruptible(dma_queue,
-		ioread32(ca91cx42_bridge->base + DGCS) & 0x800);
-
-	val = ioread32(ca91cx42_bridge->base + DGCS);
-	iowrite32(val | 0xF00, ca91cx42_bridge->base + DGCS);
-
-	vmeDma->vmeDmaStatus = 0;
-
-	if (!(val & 0x00000800)) {
-		vmeDma->vmeDmaStatus = val & 0x700;
-		printk(KERN_ERR "ca91c042: DMA Error in ca91cx42_DMA_irqhandler"
-			" DGCS=%08X\n", val);
-		val = ioread32(ca91cx42_bridge->base + DCPP);
-		printk(KERN_ERR "ca91c042: DCPP=%08X\n", val);
-		val = ioread32(ca91cx42_bridge->base + DCTL);
-		printk(KERN_ERR "ca91c042: DCTL=%08X\n", val);
-		val = ioread32(ca91cx42_bridge->base + DTBC);
-		printk(KERN_ERR "ca91c042: DTBC=%08X\n", val);
-		val = ioread32(ca91cx42_bridge->base + DLA);
-		printk(KERN_ERR "ca91c042: DLA=%08X\n", val);
-		val = ioread32(ca91cx42_bridge->base + DVA);
-		printk(KERN_ERR "ca91c042: DVA=%08X\n", val);
-
-	}
-	/* Free the dma chain */
-	ca91cx42_free_dma(dmaLL);
-
-	return 0;
-}
-
-int ca91cx42_lm_set(vmeLmCfg_t *vmeLm)
-{
-	int temp_ctl = 0;
-
-	if (vmeLm->addrU)
-		return -EINVAL;
-
-	switch (vmeLm->addrSpace) {
-	case VME_A64:
-	case VME_USER3:
-	case VME_USER4:
-		return -EINVAL;
-	case VME_A16:
-		temp_ctl |= 0x00000;
-		break;
-	case VME_A24:
-		temp_ctl |= 0x10000;
-		break;
-	case VME_A32:
-		temp_ctl |= 0x20000;
-		break;
-	case VME_CRCSR:
-		temp_ctl |= 0x50000;
-		break;
-	case VME_USER1:
-		temp_ctl |= 0x60000;
-		break;
-	case VME_USER2:
-		temp_ctl |= 0x70000;
-		break;
-	}
-
-	/* Disable while we are mucking around */
-	iowrite32(0x00000000, ca91cx42_bridge->base + LM_CTL);
-
-	iowrite32(vmeLm->addr, ca91cx42_bridge->base + LM_BS);
-
-	/* Setup CTL register. */
-	if (vmeLm->userAccessType & VME_SUPER)
-		temp_ctl |= 0x00200000;
-	if (vmeLm->userAccessType & VME_USER)
-		temp_ctl |= 0x00100000;
-	if (vmeLm->dataAccessType & VME_PROG)
-		temp_ctl |= 0x00800000;
-	if (vmeLm->dataAccessType & VME_DATA)
-		temp_ctl |= 0x00400000;
-
-
-	/* Write ctl reg and enable */
-	iowrite32(0x80000000 | temp_ctl, ca91cx42_bridge->base + LM_CTL);
-	temp_ctl = ioread32(ca91cx42_bridge->base + LM_CTL);
-
-	return 0;
-}
-
-int ca91cx42_wait_lm(vmeLmCfg_t *vmeLm)
-{
-	unsigned long flags;
-	unsigned int tmp;
-
-	spin_lock_irqsave(&lm_lock, flags);
-	spin_unlock_irqrestore(&lm_lock, flags);
-	if (tmp == 0) {
-		if (vmeLm->lmWait < 10)
-			vmeLm->lmWait = 10;
-		interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait);
-	}
-	iowrite32(0x00000000, ca91cx42_bridge->base + LM_CTL);
-
-	return 0;
-}
-
-
-
-int ca91cx42_set_arbiter(vmeArbiterCfg_t *vmeArb)
-{
-	int temp_ctl = 0;
-	int vbto = 0;
-
-	temp_ctl = ioread32(ca91cx42_bridge->base + MISC_CTL);
-	temp_ctl &= 0x00FFFFFF;
-
-	if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) {
-		vbto = 7;
-	} else if (vmeArb->globalTimeoutTimer > 1024) {
-		return -EINVAL;
-	} else if (vmeArb->globalTimeoutTimer == 0) {
-		vbto = 0;
-	} else {
-		vbto = 1;
-		while ((16 * (1 << (vbto - 1))) < vmeArb->globalTimeoutTimer)
-			vbto += 1;
-	}
-	temp_ctl |= (vbto << 28);
-
-	if (vmeArb->arbiterMode == VME_PRIORITY_MODE)
-		temp_ctl |= 1 << 26;
-
-	if (vmeArb->arbiterTimeoutFlag)
-		temp_ctl |= 2 << 24;
-
-	iowrite32(temp_ctl, ca91cx42_bridge->base + MISC_CTL);
-	return 0;
-}
-
-int ca91cx42_get_arbiter(vmeArbiterCfg_t *vmeArb)
-{
-	int temp_ctl = 0;
-	int vbto = 0;
-
-	temp_ctl = ioread32(ca91cx42_bridge->base + MISC_CTL);
-
-	vbto = (temp_ctl >> 28) & 0xF;
-	if (vbto != 0)
-		vmeArb->globalTimeoutTimer = (16 * (1 << (vbto - 1)));
-
-	if (temp_ctl & (1 << 26))
-		vmeArb->arbiterMode = VME_PRIORITY_MODE;
-	else
-		vmeArb->arbiterMode = VME_R_ROBIN_MODE;
-
-	if (temp_ctl & (3 << 24))
-		vmeArb->arbiterTimeoutFlag = 1;
-
-	return 0;
-}
-
-int ca91cx42_set_requestor(vmeRequesterCfg_t *vmeReq)
-{
-	int temp_ctl = 0;
-
-	temp_ctl = ioread32(ca91cx42_bridge->base + MAST_CTL);
-	temp_ctl &= 0xFF0FFFFF;
-
-	if (vmeReq->releaseMode == 1)
-		temp_ctl |= (1 << 20);
-
-	if (vmeReq->fairMode == 1)
-		temp_ctl |= (1 << 21);
-
-	temp_ctl |= (vmeReq->requestLevel << 22);
-
-	iowrite32(temp_ctl, ca91cx42_bridge->base + MAST_CTL);
-	return 0;
-}
-
-int ca91cx42_get_requestor(vmeRequesterCfg_t *vmeReq)
-{
-	int temp_ctl = 0;
-
-	temp_ctl = ioread32(ca91cx42_bridge->base + MAST_CTL);
-
-	if (temp_ctl & (1 << 20))
-		vmeReq->releaseMode = 1;
-
-	if (temp_ctl & (1 << 21))
-		vmeReq->fairMode = 1;
-
-	vmeReq->requestLevel = (temp_ctl & 0xC00000) >> 22;
-
-	return 0;
-}
-
-
-#endif
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.h b/drivers/staging/vme/bridges/vme_ca91cx42.h
index 95a42c2..e72c65b 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.h
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.h
@@ -7,8 +7,8 @@
  * Updated by Ajit Prem
  * Copyright 2004 Motorola Inc.
  *
- * Further updated by Martyn Welch <martyn.welch@gefanuc.com>
- * Copyright 2009 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Further updated by Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc.
  *
  * Derived from ca91c042.h by Michael Wyrick
  *
@@ -37,11 +37,27 @@
 #define CA91C142_MAX_DMA		1	/* Max DMA Controllers */
 #define CA91C142_MAX_MAILBOX		4	/* Max Mail Box registers */
 
+/* Structure used to hold driver specific information */
+struct ca91cx42_driver {
+	void *base;	/* Base Address of device registers */
+	wait_queue_head_t dma_queue;
+	wait_queue_head_t iack_queue;
+	wait_queue_head_t mbox_queue;
+	void (*lm_callback[4])(int);	/* Called in interrupt handler */
+	void *crcsr_kernel;
+	dma_addr_t crcsr_bus;
+	struct mutex vme_rmw;		/* Only one RMW cycle at a time */
+	struct mutex vme_int;		/*
+					 * Only one VME interrupt can be
+					 * generated at a time, provide locking
+					 */
+};
+
 /* See Page 2-77 in the Universe User Manual */
 struct ca91cx42_dma_descriptor {
 	unsigned int dctl;      /* DMA Control */
 	unsigned int dtbc;      /* Transfer Byte Count */
-	unsigned int dlv;       /* PCI Address */
+	unsigned int dla;       /* PCI Address */
 	unsigned int res1;      /* Reserved */
 	unsigned int dva;       /* Vme Address */
 	unsigned int res2;      /* Reserved */
@@ -237,32 +253,6 @@
 #define VCSR_SET		0x0FF8
 #define VCSR_BS			0x0FFC
 
-// DMA General Control/Status Register DGCS (0x220)
-// 32-24 ||  GO   | STOPR | HALTR |   0   || CHAIN |   0   |   0   |   0   ||
-// 23-16 ||              VON              ||             VOFF              ||
-// 15-08 ||  ACT  | STOP  | HALT  |   0   || DONE  | LERR  | VERR  | P_ERR ||
-// 07-00 ||   0   | INT_S | INT_H |   0   || I_DNE | I_LER | I_VER | I_PER ||
-
-// VON - Length Per DMA VMEBus Transfer
-//  0000 = None
-//  0001 = 256 Bytes
-//  0010 = 512
-//  0011 = 1024
-//  0100 = 2048
-//  0101 = 4096
-//  0110 = 8192
-//  0111 = 16384
-
-// VOFF - wait between DMA tenures
-//  0000 = 0    us
-//  0001 = 16
-//  0010 = 32
-//  0011 = 64
-//  0100 = 128
-//  0101 = 256
-//  0110 = 512
-//  0111 = 1024
-
 /*
  * PCI Class Register
  * offset 008
@@ -326,6 +316,16 @@
 #define CA91CX42_LSI_CTL_VCT_MBLT	(1<<8)
 #define CA91CX42_LSI_CTL_LAS		(1<<0)
 
+/*
+ * SCYC_CTL Register
+ * offset 178
+ */
+#define CA91CX42_SCYC_CTL_LAS_PCIMEM	0
+#define CA91CX42_SCYC_CTL_LAS_PCIIO	(1<<2)
+
+#define CA91CX42_SCYC_CTL_CYC_M		(3<<0)
+#define CA91CX42_SCYC_CTL_CYC_RMW	(1<<0)
+#define CA91CX42_SCYC_CTL_CYC_ADOH	(1<<1)
 
 /*
  * LMISC Register
@@ -355,6 +355,71 @@
 #define CA91CX42_BM_SLSI_RESERVED           0x3F0F0000
 
 /*
+ * DCTL Register
+ * offset 200
+ */
+#define CA91CX42_DCTL_L2V		(1<<31)
+#define CA91CX42_DCTL_VDW_M		(3<<22)
+#define CA91CX42_DCTL_VDW_M		(3<<22)
+#define CA91CX42_DCTL_VDW_D8		0
+#define CA91CX42_DCTL_VDW_D16		(1<<22)
+#define CA91CX42_DCTL_VDW_D32		(1<<23)
+#define CA91CX42_DCTL_VDW_D64		(3<<22)
+
+#define CA91CX42_DCTL_VAS_M		(7<<16)
+#define CA91CX42_DCTL_VAS_A16		0
+#define CA91CX42_DCTL_VAS_A24		(1<<16)
+#define CA91CX42_DCTL_VAS_A32		(1<<17)
+#define CA91CX42_DCTL_VAS_USER1		(3<<17)
+#define CA91CX42_DCTL_VAS_USER2		(7<<16)
+
+#define CA91CX42_DCTL_PGM_M		(1<<14)
+#define CA91CX42_DCTL_PGM_DATA		0
+#define CA91CX42_DCTL_PGM_PGM		(1<<14)
+
+#define CA91CX42_DCTL_SUPER_M		(1<<12)
+#define CA91CX42_DCTL_SUPER_NPRIV	0
+#define CA91CX42_DCTL_SUPER_SUPR	(1<<12)
+
+#define CA91CX42_DCTL_VCT_M		(1<<8)
+#define CA91CX42_DCTL_VCT_BLT		(1<<8)
+#define CA91CX42_DCTL_LD64EN		(1<<7)
+
+/*
+ * DCPP Register
+ * offset 218
+ */
+#define CA91CX42_DCPP_M			0xf
+#define CA91CX42_DCPP_NULL		(1<<0)
+
+/*
+ * DMA General Control/Status Register (DGCS)
+ * offset 220
+ */
+#define CA91CX42_DGCS_GO		(1<<31)
+#define CA91CX42_DGCS_STOP_REQ		(1<<30)
+#define CA91CX42_DGCS_HALT_REQ		(1<<29)
+#define CA91CX42_DGCS_CHAIN		(1<<27)
+
+#define CA91CX42_DGCS_VON_M		(7<<20)
+
+#define CA91CX42_DGCS_VOFF_M		(0xf<<16)
+
+#define CA91CX42_DGCS_ACT		(1<<15)
+#define CA91CX42_DGCS_STOP		(1<<14)
+#define CA91CX42_DGCS_HALT		(1<<13)
+#define CA91CX42_DGCS_DONE		(1<<11)
+#define CA91CX42_DGCS_LERR		(1<<10)
+#define CA91CX42_DGCS_VERR		(1<<9)
+#define CA91CX42_DGCS_PERR		(1<<8)
+#define CA91CX42_DGCS_INT_STOP		(1<<6)
+#define CA91CX42_DGCS_INT_HALT		(1<<5)
+#define CA91CX42_DGCS_INT_DONE		(1<<3)
+#define CA91CX42_DGCS_INT_LERR		(1<<2)
+#define CA91CX42_DGCS_INT_VERR		(1<<1)
+#define CA91CX42_DGCS_INT_PERR		(1<<0)
+
+/*
  * PCI Interrupt Enable Register
  * offset  300
  */
@@ -475,6 +540,19 @@
 #define CA91CX42_VSI_CTL_LAS_PCI_IO	(1<<0)
 #define CA91CX42_VSI_CTL_LAS_PCI_CONF	(1<<1)
 
+/* LM_CTL Register
+ * offset  F64
+ */
+#define CA91CX42_LM_CTL_EN		(1<<31)
+#define CA91CX42_LM_CTL_PGM		(1<<23)
+#define CA91CX42_LM_CTL_DATA		(1<<22)
+#define CA91CX42_LM_CTL_SUPR		(1<<21)
+#define CA91CX42_LM_CTL_NPRIV		(1<<20)
+#define CA91CX42_LM_CTL_AS_M		(5<<16)
+#define CA91CX42_LM_CTL_AS_A16		0
+#define CA91CX42_LM_CTL_AS_A24		(1<<16)
+#define CA91CX42_LM_CTL_AS_A32		(1<<17)
+
 /*
  * VRAI_CTL Register
  * offset  F70
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
index 89a7dcc..faf652e 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/staging/vme/bridges/vme_tsi148.c
@@ -1,8 +1,8 @@
 /*
  * Support for the Tundra TSI148 VME-PCI Bridge Chip
  *
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
  *
  * Based on work by Tom Armistead and Ajit Prem
  * Copyright 2004 Motorola Inc.
@@ -59,28 +59,14 @@
 int tsi148_dma_list_exec(struct vme_dma_list *);
 int tsi148_dma_list_empty(struct vme_dma_list *);
 int tsi148_generate_irq(int, int);
-int tsi148_slot_get(void);
 
-/* Modue parameter */
-int err_chk = 0;
-
-/* XXX These should all be in a per device structure */
-struct vme_bridge *tsi148_bridge;
-wait_queue_head_t dma_queue[2];
-wait_queue_head_t iack_queue;
-void (*lm_callback[4])(int);	/* Called in interrupt handler, be careful! */
-void *crcsr_kernel;
-dma_addr_t crcsr_bus;
-struct vme_master_resource *flush_image;
-struct mutex vme_rmw;	/* Only one RMW cycle at a time */
-struct mutex vme_int;	/*
-				 * Only one VME interrupt can be
-				 * generated at a time, provide locking
-				 */
+/* Module parameter */
+static int err_chk;
+static int geoid;
 
 static char driver_name[] = "vme_tsi148";
 
-static struct pci_device_id tsi148_ids[] = {
+static const struct pci_device_id tsi148_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) },
 	{ },
 };
@@ -109,16 +95,17 @@
 /*
  * Wakes up DMA queue.
  */
-static u32 tsi148_DMA_irqhandler(int channel_mask)
+static u32 tsi148_DMA_irqhandler(struct tsi148_driver *bridge,
+	int channel_mask)
 {
 	u32 serviced = 0;
 
 	if (channel_mask & TSI148_LCSR_INTS_DMA0S) {
-		wake_up(&dma_queue[0]);
+		wake_up(&(bridge->dma_queue[0]));
 		serviced |= TSI148_LCSR_INTC_DMA0C;
 	}
 	if (channel_mask & TSI148_LCSR_INTS_DMA1S) {
-		wake_up(&dma_queue[1]);
+		wake_up(&(bridge->dma_queue[1]));
 		serviced |= TSI148_LCSR_INTC_DMA1C;
 	}
 
@@ -128,7 +115,7 @@
 /*
  * Wake up location monitor queue
  */
-static u32 tsi148_LM_irqhandler(u32 stat)
+static u32 tsi148_LM_irqhandler(struct tsi148_driver *bridge, u32 stat)
 {
 	int i;
 	u32 serviced = 0;
@@ -136,7 +123,7 @@
 	for (i = 0; i < 4; i++) {
 		if(stat & TSI148_LCSR_INTS_LMS[i]) {
 			/* We only enable interrupts if the callback is set */
-			lm_callback[i](i);
+			bridge->lm_callback[i](i);
 			serviced |= TSI148_LCSR_INTC_LMC[i];
 		}
 	}
@@ -149,7 +136,7 @@
  *
  * XXX This functionality is not exposed up though API.
  */
-static u32 tsi148_MB_irqhandler(u32 stat)
+static u32 tsi148_MB_irqhandler(struct tsi148_driver *bridge, u32 stat)
 {
 	int i;
 	u32 val;
@@ -157,8 +144,7 @@
 
 	for (i = 0; i < 4; i++) {
 		if(stat & TSI148_LCSR_INTS_MBS[i]) {
-			val = ioread32be(tsi148_bridge->base +
-				TSI148_GCSR_MBOX[i]);
+			val = ioread32be(bridge->base +	TSI148_GCSR_MBOX[i]);
 			printk("VME Mailbox %d received: 0x%x\n", i, val);
 			serviced |= TSI148_LCSR_INTC_MBC[i];
 		}
@@ -170,22 +156,21 @@
 /*
  * Display error & status message when PERR (PCI) exception interrupt occurs.
  */
-static u32 tsi148_PERR_irqhandler(void)
+static u32 tsi148_PERR_irqhandler(struct tsi148_driver *bridge)
 {
 	printk(KERN_ERR
 		"PCI Exception at address: 0x%08x:%08x, attributes: %08x\n",
-		ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPAU),
-		ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPAL),
-		ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPAT)
+		ioread32be(bridge->base + TSI148_LCSR_EDPAU),
+		ioread32be(bridge->base + TSI148_LCSR_EDPAL),
+		ioread32be(bridge->base + TSI148_LCSR_EDPAT)
 		);
 	printk(KERN_ERR
 		"PCI-X attribute reg: %08x, PCI-X split completion reg: %08x\n",
-		ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPXA),
-		ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPXS)
+		ioread32be(bridge->base + TSI148_LCSR_EDPXA),
+		ioread32be(bridge->base + TSI148_LCSR_EDPXS)
 		);
 
-	iowrite32be(TSI148_LCSR_EDPAT_EDPCL,
-		tsi148_bridge->base + TSI148_LCSR_EDPAT);
+	iowrite32be(TSI148_LCSR_EDPAT_EDPCL, bridge->base + TSI148_LCSR_EDPAT);
 
 	return TSI148_LCSR_INTC_PERRC;
 }
@@ -193,16 +178,19 @@
 /*
  * Save address and status when VME error interrupt occurs.
  */
-static u32 tsi148_VERR_irqhandler(void)
+static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge)
 {
 	unsigned int error_addr_high, error_addr_low;
 	unsigned long long error_addr;
 	u32 error_attrib;
 	struct vme_bus_error *error;
+	struct tsi148_driver *bridge;
 
-	error_addr_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_VEAU);
-	error_addr_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_VEAL);
-	error_attrib = ioread32be(tsi148_bridge->base + TSI148_LCSR_VEAT);
+	bridge = tsi148_bridge->driver_priv;
+
+	error_addr_high = ioread32be(bridge->base + TSI148_LCSR_VEAU);
+	error_addr_low = ioread32be(bridge->base + TSI148_LCSR_VEAL);
+	error_attrib = ioread32be(bridge->base + TSI148_LCSR_VEAT);
 
 	reg_join(error_addr_high, error_addr_low, &error_addr);
 
@@ -226,8 +214,7 @@
 	}
 
 	/* Clear Status */
-	iowrite32be(TSI148_LCSR_VEAT_VESCL,
-		tsi148_bridge->base + TSI148_LCSR_VEAT);
+	iowrite32be(TSI148_LCSR_VEAT_VESCL, bridge->base + TSI148_LCSR_VEAT);
 
 	return TSI148_LCSR_INTC_VERRC;
 }
@@ -235,9 +222,9 @@
 /*
  * Wake up IACK queue.
  */
-static u32 tsi148_IACK_irqhandler(void)
+static u32 tsi148_IACK_irqhandler(struct tsi148_driver *bridge)
 {
-	wake_up(&iack_queue);
+	wake_up(&(bridge->iack_queue));
 
 	return TSI148_LCSR_INTC_IACKC;
 }
@@ -245,9 +232,13 @@
 /*
  * Calling VME bus interrupt callback if provided.
  */
-static u32 tsi148_VIRQ_irqhandler(u32 stat)
+static u32 tsi148_VIRQ_irqhandler(struct vme_bridge *tsi148_bridge,
+	u32 stat)
 {
 	int vec, i, serviced = 0;
+	struct tsi148_driver *bridge;
+
+	bridge = tsi148_bridge->driver_priv;
 
 	for (i = 7; i > 0; i--) {
 		if (stat & (1 << i)) {
@@ -257,8 +248,7 @@
 			 * 	8-bit IACK cycles on the bus, read from offset
 			 * 	3.
 			 */
-			vec = ioread8(tsi148_bridge->base +
-				TSI148_LCSR_VIACK[i] + 3);
+			vec = ioread8(bridge->base + TSI148_LCSR_VIACK[i] + 3);
 
 			vme_irq_handler(tsi148_bridge, i, vec);
 
@@ -273,13 +263,19 @@
  * Top level interrupt handler.  Clears appropriate interrupt status bits and
  * then calls appropriate sub handler(s).
  */
-static irqreturn_t tsi148_irqhandler(int irq, void *dev_id)
+static irqreturn_t tsi148_irqhandler(int irq, void *ptr)
 {
 	u32 stat, enable, serviced = 0;
+	struct vme_bridge *tsi148_bridge;
+	struct tsi148_driver *bridge;
+
+	tsi148_bridge = ptr;
+
+	bridge = tsi148_bridge->driver_priv;
 
 	/* Determine which interrupts are unmasked and set */
-	enable = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
-	stat = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTS);
+	enable = ioread32be(bridge->base + TSI148_LCSR_INTEO);
+	stat = ioread32be(bridge->base + TSI148_LCSR_INTS);
 
 	/* Only look at unmasked interrupts */
 	stat &= enable;
@@ -291,61 +287,63 @@
 	/* Call subhandlers as appropriate */
 	/* DMA irqs */
 	if (stat & (TSI148_LCSR_INTS_DMA1S | TSI148_LCSR_INTS_DMA0S))
-		serviced |= tsi148_DMA_irqhandler(stat);
+		serviced |= tsi148_DMA_irqhandler(bridge, stat);
 
 	/* Location monitor irqs */
 	if (stat & (TSI148_LCSR_INTS_LM3S | TSI148_LCSR_INTS_LM2S |
 			TSI148_LCSR_INTS_LM1S | TSI148_LCSR_INTS_LM0S))
-		serviced |= tsi148_LM_irqhandler(stat);
+		serviced |= tsi148_LM_irqhandler(bridge, stat);
 
 	/* Mail box irqs */
 	if (stat & (TSI148_LCSR_INTS_MB3S | TSI148_LCSR_INTS_MB2S |
 			TSI148_LCSR_INTS_MB1S | TSI148_LCSR_INTS_MB0S))
-		serviced |= tsi148_MB_irqhandler(stat);
+		serviced |= tsi148_MB_irqhandler(bridge, stat);
 
 	/* PCI bus error */
 	if (stat & TSI148_LCSR_INTS_PERRS)
-		serviced |= tsi148_PERR_irqhandler();
+		serviced |= tsi148_PERR_irqhandler(bridge);
 
 	/* VME bus error */
 	if (stat & TSI148_LCSR_INTS_VERRS)
-		serviced |= tsi148_VERR_irqhandler();
+		serviced |= tsi148_VERR_irqhandler(tsi148_bridge);
 
 	/* IACK irq */
 	if (stat & TSI148_LCSR_INTS_IACKS)
-		serviced |= tsi148_IACK_irqhandler();
+		serviced |= tsi148_IACK_irqhandler(bridge);
 
 	/* VME bus irqs */
 	if (stat & (TSI148_LCSR_INTS_IRQ7S | TSI148_LCSR_INTS_IRQ6S |
 			TSI148_LCSR_INTS_IRQ5S | TSI148_LCSR_INTS_IRQ4S |
 			TSI148_LCSR_INTS_IRQ3S | TSI148_LCSR_INTS_IRQ2S |
 			TSI148_LCSR_INTS_IRQ1S))
-		serviced |= tsi148_VIRQ_irqhandler(stat);
+		serviced |= tsi148_VIRQ_irqhandler(tsi148_bridge, stat);
 
 	/* Clear serviced interrupts */
-	iowrite32be(serviced, tsi148_bridge->base + TSI148_LCSR_INTC);
+	iowrite32be(serviced, bridge->base + TSI148_LCSR_INTC);
 
 	return IRQ_HANDLED;
 }
 
-static int tsi148_irq_init(struct vme_bridge *bridge)
+static int tsi148_irq_init(struct vme_bridge *tsi148_bridge)
 {
 	int result;
 	unsigned int tmp;
 	struct pci_dev *pdev;
+	struct tsi148_driver *bridge;
 
-	/* Need pdev */
-        pdev = container_of(bridge->parent, struct pci_dev, dev);
+	pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev);
+
+	bridge = tsi148_bridge->driver_priv;
 
 	/* Initialise list for VME bus errors */
-	INIT_LIST_HEAD(&(bridge->vme_errors));
+	INIT_LIST_HEAD(&(tsi148_bridge->vme_errors));
 
-	mutex_init(&(bridge->irq_mtx));
+	mutex_init(&(tsi148_bridge->irq_mtx));
 
 	result = request_irq(pdev->irq,
 			     tsi148_irqhandler,
 			     IRQF_SHARED,
-			     driver_name, pdev);
+			     driver_name, tsi148_bridge);
 	if (result) {
 		dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n",
 			pdev->irq);
@@ -359,7 +357,7 @@
 		TSI148_LCSR_INTEO_PERREO | TSI148_LCSR_INTEO_VERREO |
 		TSI148_LCSR_INTEO_IACKEO;
 
-	/* XXX This leaves the following interrupts masked.
+	/* This leaves the following interrupts masked.
 	 * TSI148_LCSR_INTEO_VIEEO
 	 * TSI148_LCSR_INTEO_SYSFLEO
 	 * TSI148_LCSR_INTEO_ACFLEO
@@ -392,14 +390,14 @@
 	return 0;
 }
 
-static void tsi148_irq_exit(struct pci_dev *pdev)
+static void tsi148_irq_exit(struct tsi148_driver *bridge, struct pci_dev *pdev)
 {
 	/* Turn off interrupts */
-	iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTEO);
-	iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTEN);
+	iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEO);
+	iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEN);
 
 	/* Clear all interrupts */
-	iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_INTC);
+	iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_INTC);
 
 	/* Detach interrupt handler */
 	free_irq(pdev->irq, pdev);
@@ -408,11 +406,11 @@
 /*
  * Check to see if an IACk has been received, return true (1) or false (0).
  */
-int tsi148_iack_received(void)
+int tsi148_iack_received(struct tsi148_driver *bridge)
 {
 	u32 tmp;
 
-	tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VICR);
+	tmp = ioread32be(bridge->base + TSI148_LCSR_VICR);
 
 	if (tmp & TSI148_LCSR_VICR_IRQS)
 		return 0;
@@ -423,20 +421,24 @@
 /*
  * Configure VME interrupt
  */
-void tsi148_irq_set(int level, int state, int sync)
+void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level,
+	int state, int sync)
 {
 	struct pci_dev *pdev;
 	u32 tmp;
+	struct tsi148_driver *bridge;
+
+	bridge = tsi148_bridge->driver_priv;
 
 	/* We need to do the ordering differently for enabling and disabling */
 	if (state == 0) {
-		tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+		tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN);
 		tmp &= ~TSI148_LCSR_INTEN_IRQEN[level - 1];
-		iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN);
+		iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
 
-		tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+		tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
 		tmp &= ~TSI148_LCSR_INTEO_IRQEO[level - 1];
-		iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+		iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
 
 		if (sync != 0) {
 			pdev = container_of(tsi148_bridge->parent,
@@ -445,13 +447,13 @@
 			synchronize_irq(pdev->irq);
 		}
 	} else {
-		tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+		tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
 		tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1];
-		iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+		iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
 
-		tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+		tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN);
 		tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1];
-		iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN);
+		iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
 	}
 }
 
@@ -459,28 +461,32 @@
  * Generate a VME bus interrupt at the requested level & vector. Wait for
  * interrupt to be acked.
  */
-int tsi148_irq_generate(int level, int statid)
+int tsi148_irq_generate(struct vme_bridge *tsi148_bridge, int level, int statid)
 {
 	u32 tmp;
+	struct tsi148_driver *bridge;
 
-	mutex_lock(&(vme_int));
+	bridge = tsi148_bridge->driver_priv;
+
+	mutex_lock(&(bridge->vme_int));
 
 	/* Read VICR register */
-	tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VICR);
+	tmp = ioread32be(bridge->base + TSI148_LCSR_VICR);
 
 	/* Set Status/ID */
 	tmp = (tmp & ~TSI148_LCSR_VICR_STID_M) |
 		(statid & TSI148_LCSR_VICR_STID_M);
-	iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VICR);
+	iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR);
 
 	/* Assert VMEbus IRQ */
 	tmp = tmp | TSI148_LCSR_VICR_IRQL[level];
-	iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VICR);
+	iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR);
 
 	/* XXX Consider implementing a timeout? */
-	wait_event_interruptible(iack_queue, tsi148_iack_received());
+	wait_event_interruptible(bridge->iack_queue,
+		tsi148_iack_received(bridge));
 
-	mutex_unlock(&(vme_int));
+	mutex_unlock(&(bridge->vme_int));
 
 	return 0;
 }
@@ -488,8 +494,8 @@
 /*
  * Find the first error in this address range
  */
-static struct vme_bus_error *tsi148_find_error(vme_address_t aspace,
-	unsigned long long address, size_t count)
+static struct vme_bus_error *tsi148_find_error(struct vme_bridge *tsi148_bridge,
+	vme_address_t aspace, unsigned long long address, size_t count)
 {
 	struct list_head *err_pos;
 	struct vme_bus_error *vme_err, *valid = NULL;
@@ -520,8 +526,8 @@
 /*
  * Clear errors in the provided address range.
  */
-static void tsi148_clear_errors(vme_address_t aspace,
-	unsigned long long address, size_t count)
+static void tsi148_clear_errors(struct vme_bridge *tsi148_bridge,
+	vme_address_t aspace, unsigned long long address, size_t count)
 {
 	struct list_head *err_pos, *temp;
 	struct vme_bus_error *vme_err;
@@ -561,16 +567,9 @@
 	unsigned int vme_bound_low, vme_bound_high;
 	unsigned int pci_offset_low, pci_offset_high;
 	unsigned long long vme_bound, pci_offset;
+	struct tsi148_driver *bridge;
 
-#if 0
-        printk("Set slave image %d to:\n", image->number);
- 	printk("\tEnabled: %s\n", (enabled == 1)? "yes" : "no");
-	printk("\tVME Base:0x%llx\n", vme_base);
-	printk("\tWindow Size:0x%llx\n", size);
-	printk("\tPCI Base:0x%lx\n", (unsigned long)pci_base);
-	printk("\tAddress Space:0x%x\n", aspace);
-	printk("\tTransfer Cycle Properties:0x%x\n", cycle);
-#endif
+	bridge = image->parent->driver_priv;
 
 	i = image->number;
 
@@ -627,49 +626,27 @@
 		return -EINVAL;
 	}
 
-#if 0
-	printk("\tVME Bound:0x%llx\n", vme_bound);
-	printk("\tPCI Offset:0x%llx\n", pci_offset);
-#endif
-
 	/*  Disable while we are mucking around */
-	temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	temp_ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITAT);
 	temp_ctl &= ~TSI148_LCSR_ITAT_EN;
-	iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITAT);
 
 	/* Setup mapping */
-	iowrite32be(vme_base_high, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	iowrite32be(vme_base_high, bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITSAU);
-	iowrite32be(vme_base_low, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	iowrite32be(vme_base_low, bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITSAL);
-	iowrite32be(vme_bound_high, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	iowrite32be(vme_bound_high, bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITEAU);
-	iowrite32be(vme_bound_low, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	iowrite32be(vme_bound_low, bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITEAL);
-	iowrite32be(pci_offset_high, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	iowrite32be(pci_offset_high, bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITOFU);
-	iowrite32be(pci_offset_low, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	iowrite32be(pci_offset_low, bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITOFL);
 
-/* XXX Prefetch stuff currently unsupported */
-#if 0
-
-	for (x = 0; x < 4; x++) {
-		if ((64 << x) >= vmeIn->prefetchSize) {
-			break;
-		}
-	}
-	if (x == 4)
-		x--;
-	temp_ctl |= (x << 16);
-
-	if (vmeIn->prefetchThreshold)
-		if (vmeIn->prefetchThreshold)
-			temp_ctl |= 0x40000;
-#endif
-
 	/* Setup 2eSST speeds */
 	temp_ctl &= ~TSI148_LCSR_ITAT_2eSSTM_M;
 	switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
@@ -712,13 +689,13 @@
 		temp_ctl |= TSI148_LCSR_ITAT_DATA;
 
 	/* Write ctl reg without enable */
-	iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITAT);
 
 	if (enabled)
 		temp_ctl |= TSI148_LCSR_ITAT_EN;
 
-	iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITAT);
 
 	return 0;
@@ -726,8 +703,6 @@
 
 /*
  * Get slave window configuration.
- *
- * XXX Prefetch currently unsupported.
  */
 int tsi148_slave_get(struct vme_slave_resource *image, int *enabled,
 	unsigned long long *vme_base, unsigned long long *size,
@@ -738,25 +713,27 @@
 	unsigned int vme_bound_low, vme_bound_high;
 	unsigned int pci_offset_low, pci_offset_high;
 	unsigned long long vme_bound, pci_offset;
+	struct tsi148_driver *bridge;
 
+	bridge = image->parent->driver_priv;
 
 	i = image->number;
 
 	/* Read registers */
-	ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITAT);
 
-	vme_base_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	vme_base_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITSAU);
-	vme_base_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	vme_base_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITSAL);
-	vme_bound_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	vme_bound_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITEAU);
-	vme_bound_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	vme_bound_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITEAL);
-	pci_offset_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	pci_offset_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITOFU);
-	pci_offset_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+	pci_offset_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
 		TSI148_LCSR_OFFSET_ITOFL);
 
 	/* Convert 64-bit variables to 2x 32-bit variables */
@@ -833,6 +810,9 @@
 	unsigned long long existing_size;
 	int retval = 0;
 	struct pci_dev *pdev;
+	struct vme_bridge *tsi148_bridge;
+
+	tsi148_bridge = image->parent;
 
 	/* Find pci_dev container of dev */
         if (tsi148_bridge->parent == NULL) {
@@ -841,8 +821,8 @@
         }
         pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev);
 
-	existing_size = (unsigned long long)(image->pci_resource.end -
-		image->pci_resource.start);
+	existing_size = (unsigned long long)(image->bus_resource.end -
+		image->bus_resource.start);
 
 	/* If the existing size is OK, return */
 	if ((size != 0) && (existing_size == (size - 1)))
@@ -851,10 +831,10 @@
 	if (existing_size != 0) {
 		iounmap(image->kern_base);
 		image->kern_base = NULL;
-		if (image->pci_resource.name != NULL)
-			kfree(image->pci_resource.name);
-		release_resource(&(image->pci_resource));
-		memset(&(image->pci_resource), 0, sizeof(struct resource));
+		if (image->bus_resource.name != NULL)
+			kfree(image->bus_resource.name);
+		release_resource(&(image->bus_resource));
+		memset(&(image->bus_resource), 0, sizeof(struct resource));
 	}
 
 	/* Exit here if size is zero */
@@ -862,9 +842,9 @@
 		return 0;
 	}
 
-	if (image->pci_resource.name == NULL) {
-		image->pci_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
-		if (image->pci_resource.name == NULL) {
+	if (image->bus_resource.name == NULL) {
+		image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
+		if (image->bus_resource.name == NULL) {
 			printk(KERN_ERR "Unable to allocate memory for resource"
 				" name\n");
 			retval = -ENOMEM;
@@ -872,26 +852,26 @@
 		}
 	}
 
-	sprintf((char *)image->pci_resource.name, "%s.%d", tsi148_bridge->name,
+	sprintf((char *)image->bus_resource.name, "%s.%d", tsi148_bridge->name,
 		image->number);
 
-	image->pci_resource.start = 0;
-	image->pci_resource.end = (unsigned long)size;
-	image->pci_resource.flags = IORESOURCE_MEM;
+	image->bus_resource.start = 0;
+	image->bus_resource.end = (unsigned long)size;
+	image->bus_resource.flags = IORESOURCE_MEM;
 
 	retval = pci_bus_alloc_resource(pdev->bus,
-		&(image->pci_resource), size, size, PCIBIOS_MIN_MEM,
+		&(image->bus_resource), size, size, PCIBIOS_MIN_MEM,
 		0, NULL, NULL);
 	if (retval) {
 		printk(KERN_ERR "Failed to allocate mem resource for "
 			"window %d size 0x%lx start 0x%lx\n",
 			image->number, (unsigned long)size,
-			(unsigned long)image->pci_resource.start);
+			(unsigned long)image->bus_resource.start);
 		goto err_resource;
 	}
 
 	image->kern_base = ioremap_nocache(
-		image->pci_resource.start, size);
+		image->bus_resource.start, size);
 	if (image->kern_base == NULL) {
 		printk(KERN_ERR "Failed to remap resource\n");
 		retval = -ENOMEM;
@@ -903,10 +883,10 @@
 	iounmap(image->kern_base);
 	image->kern_base = NULL;
 err_remap:
-	release_resource(&(image->pci_resource));
+	release_resource(&(image->bus_resource));
 err_resource:
-	kfree(image->pci_resource.name);
-	memset(&(image->pci_resource), 0, sizeof(struct resource));
+	kfree(image->bus_resource.name);
+	memset(&(image->bus_resource), 0, sizeof(struct resource));
 err_name:
 	return retval;
 }
@@ -918,9 +898,9 @@
 {
 	iounmap(image->kern_base);
 	image->kern_base = NULL;
-	release_resource(&(image->pci_resource));
-	kfree(image->pci_resource.name);
-	memset(&(image->pci_resource), 0, sizeof(struct resource));
+	release_resource(&(image->bus_resource));
+	kfree(image->bus_resource.name);
+	memset(&(image->bus_resource), 0, sizeof(struct resource));
 }
 
 /*
@@ -937,6 +917,9 @@
 	unsigned int pci_bound_low, pci_bound_high;
 	unsigned int vme_offset_low, vme_offset_high;
 	unsigned long long pci_bound, vme_offset, pci_base;
+	struct tsi148_driver *bridge;
+
+	bridge = image->parent->driver_priv;
 
 	/* Verify input data */
 	if (vme_base & 0xFFFF) {
@@ -970,7 +953,7 @@
 		pci_bound = 0;
 		vme_offset = 0;
 	} else {
-		pci_base = (unsigned long long)image->pci_resource.start;
+		pci_base = (unsigned long long)image->bus_resource.start;
 
 		/*
 		 * Bound address is a valid address for the window, adjust
@@ -1007,26 +990,12 @@
 	i = image->number;
 
 	/* Disable while we are mucking around */
-	temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	temp_ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTAT);
 	temp_ctl &= ~TSI148_LCSR_OTAT_EN;
-	iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTAT);
 
-/* XXX Prefetch stuff currently unsupported */
-#if 0
-	if (vmeOut->prefetchEnable) {
-		temp_ctl |= 0x40000;
-		for (x = 0; x < 4; x++) {
-			if ((2 << x) >= vmeOut->prefetchSize)
-				break;
-		}
-		if (x == 4)
-			x = 3;
-		temp_ctl |= (x << 16);
-	}
-#endif
-
 	/* Setup 2eSST speeds */
 	temp_ctl &= ~TSI148_LCSR_OTAT_2eSSTM_M;
 	switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
@@ -1126,33 +1095,27 @@
 		temp_ctl |= TSI148_LCSR_OTAT_PGM;
 
 	/* Setup mapping */
-	iowrite32be(pci_base_high, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	iowrite32be(pci_base_high, bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTSAU);
-	iowrite32be(pci_base_low, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	iowrite32be(pci_base_low, bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTSAL);
-	iowrite32be(pci_bound_high, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	iowrite32be(pci_bound_high, bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTEAU);
-	iowrite32be(pci_bound_low, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	iowrite32be(pci_bound_low, bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTEAL);
-	iowrite32be(vme_offset_high, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	iowrite32be(vme_offset_high, bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTOFU);
-	iowrite32be(vme_offset_low, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	iowrite32be(vme_offset_low, bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTOFL);
 
-/* XXX We need to deal with OTBS */
-#if 0
-	iowrite32be(vmeOut->bcastSelect2esst, tsi148_bridge->base +
-		TSI148_LCSR_OT[i] + TSI148_LCSR_OFFSET_OTBS);
-#endif
-
 	/* Write ctl reg without enable */
-	iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTAT);
 
 	if (enabled)
 		temp_ctl |= TSI148_LCSR_OTAT_EN;
 
-	iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTAT);
 
 	spin_unlock(&(image->lock));
@@ -1183,23 +1146,26 @@
 	unsigned int vme_offset_low, vme_offset_high;
 
 	unsigned long long pci_base, pci_bound, vme_offset;
+	struct tsi148_driver *bridge;
+
+	bridge = image->parent->driver_priv;
 
 	i = image->number;
 
-	ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTAT);
 
-	pci_base_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	pci_base_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTSAU);
-	pci_base_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	pci_base_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTSAL);
-	pci_bound_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	pci_bound_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTEAU);
-	pci_bound_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	pci_bound_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTEAL);
-	vme_offset_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	vme_offset_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTOFU);
-	vme_offset_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	vme_offset_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTOFL);
 
 	/* Convert 64-bit variables to 2x 32-bit variables */
@@ -1305,6 +1271,9 @@
 	vme_cycle_t cycle;
 	vme_width_t dwidth;
 	struct vme_bus_error *vme_err = NULL;
+	struct vme_bridge *tsi148_bridge;
+
+	tsi148_bridge = image->parent;
 
 	spin_lock(&(image->lock));
 
@@ -1317,13 +1286,15 @@
 	__tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle,
 		&dwidth);
 
-	vme_err = tsi148_find_error(aspace, vme_base + offset, count);
+	vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset,
+		count);
 	if(vme_err != NULL) {
 		dev_err(image->parent->parent, "First VME read error detected "
 			"an at address 0x%llx\n", vme_err->address);
 		retval = vme_err->address - (vme_base + offset);
 		/* Clear down save errors in this address range */
-		tsi148_clear_errors(aspace, vme_base + offset, count);
+		tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset,
+			count);
 	}
 
 skip_chk:
@@ -1333,9 +1304,6 @@
 }
 
 
-/* XXX We need to change vme_master_resource->mtx to a spinlock so that read
- *     and write functions can be used in an interrupt context
- */
 ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
 	size_t count, loff_t offset)
 {
@@ -1346,6 +1314,12 @@
 	vme_width_t dwidth;
 
 	struct vme_bus_error *vme_err = NULL;
+	struct vme_bridge *tsi148_bridge;
+	struct tsi148_driver *bridge;
+
+	tsi148_bridge = image->parent;
+
+	bridge = tsi148_bridge->driver_priv;
 
 	spin_lock(&(image->lock));
 
@@ -1373,15 +1347,17 @@
 	__tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle,
 		&dwidth);
 
-	ioread16(flush_image->kern_base + 0x7F000);
+	ioread16(bridge->flush_image->kern_base + 0x7F000);
 
-	vme_err = tsi148_find_error(aspace, vme_base + offset, count);
+	vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset,
+		count);
 	if(vme_err != NULL) {
 		printk("First VME write error detected an at address 0x%llx\n",
 			vme_err->address);
 		retval = vme_err->address - (vme_base + offset);
 		/* Clear down save errors in this address range */
-		tsi148_clear_errors(aspace, vme_base + offset, count);
+		tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset,
+			count);
 	}
 
 skip_chk:
@@ -1403,48 +1379,50 @@
 	unsigned int pci_addr_high, pci_addr_low;
 	u32 tmp, result;
 	int i;
+	struct tsi148_driver *bridge;
 
+	bridge = image->parent->driver_priv;
 
 	/* Find the PCI address that maps to the desired VME address */
 	i = image->number;
 
 	/* Locking as we can only do one of these at a time */
-	mutex_lock(&(vme_rmw));
+	mutex_lock(&(bridge->vme_rmw));
 
 	/* Lock image */
 	spin_lock(&(image->lock));
 
-	pci_addr_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	pci_addr_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTSAU);
-	pci_addr_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+	pci_addr_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
 		TSI148_LCSR_OFFSET_OTSAL);
 
 	reg_join(pci_addr_high, pci_addr_low, &pci_addr);
 	reg_split(pci_addr + offset, &pci_addr_high, &pci_addr_low);
 
 	/* Configure registers */
-	iowrite32be(mask, tsi148_bridge->base + TSI148_LCSR_RMWEN);
-	iowrite32be(compare, tsi148_bridge->base + TSI148_LCSR_RMWC);
-	iowrite32be(swap, tsi148_bridge->base + TSI148_LCSR_RMWS);
-	iowrite32be(pci_addr_high, tsi148_bridge->base + TSI148_LCSR_RMWAU);
-	iowrite32be(pci_addr_low, tsi148_bridge->base + TSI148_LCSR_RMWAL);
+	iowrite32be(mask, bridge->base + TSI148_LCSR_RMWEN);
+	iowrite32be(compare, bridge->base + TSI148_LCSR_RMWC);
+	iowrite32be(swap, bridge->base + TSI148_LCSR_RMWS);
+	iowrite32be(pci_addr_high, bridge->base + TSI148_LCSR_RMWAU);
+	iowrite32be(pci_addr_low, bridge->base + TSI148_LCSR_RMWAL);
 
 	/* Enable RMW */
-	tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+	tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL);
 	tmp |= TSI148_LCSR_VMCTRL_RMWEN;
-	iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+	iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL);
 
 	/* Kick process off with a read to the required address. */
 	result = ioread32be(image->kern_base + offset);
 
 	/* Disable RMW */
-	tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+	tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL);
 	tmp &= ~TSI148_LCSR_VMCTRL_RMWEN;
-	iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+	iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL);
 
 	spin_unlock(&(image->lock));
 
-	mutex_unlock(&(vme_rmw));
+	mutex_unlock(&(bridge->vme_rmw));
 
 	return result;
 }
@@ -1637,8 +1615,6 @@
 
 /*
  * Add a link list descriptor to the list
- *
- * XXX Need to handle 2eSST Broadcast select bits
  */
 int tsi148_dma_list_add (struct vme_dma_list *list, struct vme_dma_attr *src,
 	struct vme_dma_attr *dest, size_t count)
@@ -1651,7 +1627,7 @@
 	dma_addr_t desc_ptr;
 	int retval = 0;
 
-	/* XXX descriptor must be aligned on 64-bit boundaries */
+	/* Descriptor must be aligned on 64-bit boundaries */
 	entry = (struct tsi148_dma_entry *)kmalloc(
 		sizeof(struct tsi148_dma_entry), GFP_KERNEL);
 	if (entry == NULL) {
@@ -1788,11 +1764,14 @@
 /*
  * Check to see if the provided DMA channel is busy.
  */
-static int tsi148_dma_busy(int channel)
+static int tsi148_dma_busy(struct vme_bridge *tsi148_bridge, int channel)
 {
 	u32 tmp;
+	struct tsi148_driver *bridge;
 
-	tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
+	bridge = tsi148_bridge->driver_priv;
+
+	tmp = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] +
 		TSI148_LCSR_OFFSET_DSTA);
 
 	if (tmp & TSI148_LCSR_DSTA_BSY)
@@ -1815,12 +1794,12 @@
 	dma_addr_t bus_addr;
 	u32 bus_addr_high, bus_addr_low;
 	u32 val, dctlreg = 0;
-#if 0
-	int x;
-#endif
+	struct tsi148_driver *bridge;
 
 	ctrlr = list->parent;
 
+	bridge = ctrlr->parent->driver_priv;
+
 	mutex_lock(&(ctrlr->mtx));
 
 	channel = ctrlr->number;
@@ -1837,48 +1816,6 @@
 	} else {
 		list_add(&(list->list), &(ctrlr->running));
 	}
-#if 0
-	/* XXX Still todo */
-	for (x = 0; x < 8; x++) {	/* vme block size */
-		if ((32 << x) >= vmeDma->maxVmeBlockSize) {
-			break;
-		}
-	}
-	if (x == 8)
-		x = 7;
-	dctlreg |= (x << 12);
-
-	for (x = 0; x < 8; x++) {	/* pci block size */
-		if ((32 << x) >= vmeDma->maxPciBlockSize) {
-			break;
-		}
-	}
-	if (x == 8)
-		x = 7;
-	dctlreg |= (x << 4);
-
-	if (vmeDma->vmeBackOffTimer) {
-		for (x = 1; x < 8; x++) {	/* vme timer */
-			if ((1 << (x - 1)) >= vmeDma->vmeBackOffTimer) {
-				break;
-			}
-		}
-		if (x == 8)
-			x = 7;
-		dctlreg |= (x << 8);
-	}
-
-	if (vmeDma->pciBackOffTimer) {
-		for (x = 1; x < 8; x++) {	/* pci timer */
-			if ((1 << (x - 1)) >= vmeDma->pciBackOffTimer) {
-				break;
-			}
-		}
-		if (x == 8)
-			x = 7;
-		dctlreg |= (x << 0);
-	}
-#endif
 
 	/* Get first bus address and write into registers */
 	entry = list_first_entry(&(list->entries), struct tsi148_dma_entry,
@@ -1890,21 +1827,22 @@
 
 	reg_split(bus_addr, &bus_addr_high, &bus_addr_low);
 
-	iowrite32be(bus_addr_high, tsi148_bridge->base +
+	iowrite32be(bus_addr_high, bridge->base +
 		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAU);
-	iowrite32be(bus_addr_low, tsi148_bridge->base +
+	iowrite32be(bus_addr_low, bridge->base +
 		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAL);
 
 	/* Start the operation */
-	iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, tsi148_bridge->base +
+	iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, bridge->base +
 		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
 
-	wait_event_interruptible(dma_queue[channel], tsi148_dma_busy(channel));
+	wait_event_interruptible(bridge->dma_queue[channel],
+		tsi148_dma_busy(ctrlr->parent, channel));
 	/*
 	 * Read status register, this register is valid until we kick off a
 	 * new transfer.
 	 */
-	val = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
+	val = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] +
 		TSI148_LCSR_OFFSET_DSTA);
 
 	if (val & TSI148_LCSR_DSTA_VBE) {
@@ -1952,12 +1890,15 @@
 {
 	u32 lm_base_high, lm_base_low, lm_ctl = 0;
 	int i;
+	struct tsi148_driver *bridge;
+
+	bridge = lm->parent->driver_priv;
 
 	mutex_lock(&(lm->mtx));
 
 	/* If we already have a callback attached, we can't move it! */
 	for (i = 0; i < lm->monitors; i++) {
-		if(lm_callback[i] != NULL) {
+		if (bridge->lm_callback[i] != NULL) {
 			mutex_unlock(&(lm->mtx));
 			printk("Location monitor callback attached, can't "
 				"reset\n");
@@ -1996,9 +1937,9 @@
 
 	reg_split(lm_base, &lm_base_high, &lm_base_low);
 
-	iowrite32be(lm_base_high, tsi148_bridge->base + TSI148_LCSR_LMBAU);
-	iowrite32be(lm_base_low, tsi148_bridge->base + TSI148_LCSR_LMBAL);
-	iowrite32be(lm_ctl, tsi148_bridge->base + TSI148_LCSR_LMAT);
+	iowrite32be(lm_base_high, bridge->base + TSI148_LCSR_LMBAU);
+	iowrite32be(lm_base_low, bridge->base + TSI148_LCSR_LMBAL);
+	iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT);
 
 	mutex_unlock(&(lm->mtx));
 
@@ -2012,12 +1953,15 @@
 	vme_address_t *aspace, vme_cycle_t *cycle)
 {
 	u32 lm_base_high, lm_base_low, lm_ctl, enabled = 0;
+	struct tsi148_driver *bridge;
+
+	bridge = lm->parent->driver_priv;
 
 	mutex_lock(&(lm->mtx));
 
-	lm_base_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMBAU);
-	lm_base_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMBAL);
-	lm_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMAT);
+	lm_base_high = ioread32be(bridge->base + TSI148_LCSR_LMBAU);
+	lm_base_low = ioread32be(bridge->base + TSI148_LCSR_LMBAL);
+	lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT);
 
 	reg_join(lm_base_high, lm_base_low, lm_base);
 
@@ -2060,11 +2004,14 @@
 	void (*callback)(int))
 {
 	u32 lm_ctl, tmp;
+	struct tsi148_driver *bridge;
+
+	bridge = lm->parent->driver_priv;
 
 	mutex_lock(&(lm->mtx));
 
 	/* Ensure that the location monitor is configured - need PGM or DATA */
-	lm_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMAT);
+	lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT);
 	if ((lm_ctl & (TSI148_LCSR_LMAT_PGM | TSI148_LCSR_LMAT_DATA)) == 0) {
 		mutex_unlock(&(lm->mtx));
 		printk("Location monitor not properly configured\n");
@@ -2072,28 +2019,28 @@
 	}
 
 	/* Check that a callback isn't already attached */
-	if (lm_callback[monitor] != NULL) {
+	if (bridge->lm_callback[monitor] != NULL) {
 		mutex_unlock(&(lm->mtx));
 		printk("Existing callback attached\n");
 		return -EBUSY;
 	}
 
 	/* Attach callback */
-	lm_callback[monitor] = callback;
+	bridge->lm_callback[monitor] = callback;
 
 	/* Enable Location Monitor interrupt */
-	tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+	tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN);
 	tmp |= TSI148_LCSR_INTEN_LMEN[monitor];
-	iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN);
+	iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
 
-	tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+	tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
 	tmp |= TSI148_LCSR_INTEO_LMEO[monitor];
-	iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+	iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
 
 	/* Ensure that global Location Monitor Enable set */
 	if ((lm_ctl & TSI148_LCSR_LMAT_EN) == 0) {
 		lm_ctl |= TSI148_LCSR_LMAT_EN;
-		iowrite32be(lm_ctl, tsi148_bridge->base + TSI148_LCSR_LMAT);
+		iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT);
 	}
 
 	mutex_unlock(&(lm->mtx));
@@ -2107,30 +2054,33 @@
 int tsi148_lm_detach(struct vme_lm_resource *lm, int monitor)
 {
 	u32 lm_en, tmp;
+	struct tsi148_driver *bridge;
+
+	bridge = lm->parent->driver_priv;
 
 	mutex_lock(&(lm->mtx));
 
 	/* Disable Location Monitor and ensure previous interrupts are clear */
-	lm_en = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+	lm_en = ioread32be(bridge->base + TSI148_LCSR_INTEN);
 	lm_en &= ~TSI148_LCSR_INTEN_LMEN[monitor];
-	iowrite32be(lm_en, tsi148_bridge->base + TSI148_LCSR_INTEN);
+	iowrite32be(lm_en, bridge->base + TSI148_LCSR_INTEN);
 
-	tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+	tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
 	tmp &= ~TSI148_LCSR_INTEO_LMEO[monitor];
-	iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+	iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
 
 	iowrite32be(TSI148_LCSR_INTC_LMC[monitor],
-		 tsi148_bridge->base + TSI148_LCSR_INTC);
+		 bridge->base + TSI148_LCSR_INTC);
 
 	/* Detach callback */
-	lm_callback[monitor] = NULL;
+	bridge->lm_callback[monitor] = NULL;
 
 	/* If all location monitors disabled, disable global Location Monitor */
 	if ((lm_en & (TSI148_LCSR_INTS_LM0S | TSI148_LCSR_INTS_LM1S |
 			TSI148_LCSR_INTS_LM2S | TSI148_LCSR_INTS_LM3S)) == 0) {
-		tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMAT);
+		tmp = ioread32be(bridge->base + TSI148_LCSR_LMAT);
 		tmp &= ~TSI148_LCSR_LMAT_EN;
-		iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_LMAT);
+		iowrite32be(tmp, bridge->base + TSI148_LCSR_LMAT);
 	}
 
 	mutex_unlock(&(lm->mtx));
@@ -2141,12 +2091,19 @@
 /*
  * Determine Geographical Addressing
  */
-int tsi148_slot_get(void)
+int tsi148_slot_get(struct vme_bridge *tsi148_bridge)
 {
         u32 slot = 0;
+	struct tsi148_driver *bridge;
 
-	slot = ioread32be(tsi148_bridge->base + TSI148_LCSR_VSTAT);
-	slot = slot & TSI148_LCSR_VSTAT_GA_M;
+	bridge = tsi148_bridge->driver_priv;
+
+	if (!geoid) {
+		slot = ioread32be(bridge->base + TSI148_LCSR_VSTAT);
+		slot = slot & TSI148_LCSR_VSTAT_GA_M;
+	} else
+		slot = geoid;
+
 	return (int)slot;
 }
 
@@ -2167,45 +2124,50 @@
  * boards registers, this means there is a fix length 508kB window which must
  * be mapped onto PCI memory.
  */
-static int tsi148_crcsr_init(struct pci_dev *pdev)
+static int tsi148_crcsr_init(struct vme_bridge *tsi148_bridge,
+	struct pci_dev *pdev)
 {
 	u32 cbar, crat, vstat;
 	u32 crcsr_bus_high, crcsr_bus_low;
 	int retval;
+	struct tsi148_driver *bridge;
+
+	bridge = tsi148_bridge->driver_priv;
 
 	/* Allocate mem for CR/CSR image */
-	crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
-		&crcsr_bus);
-	if (crcsr_kernel == NULL) {
+	bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
+		&(bridge->crcsr_bus));
+	if (bridge->crcsr_kernel == NULL) {
 		dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR "
 			"image\n");
 		return -ENOMEM;
 	}
 
-	memset(crcsr_kernel, 0, VME_CRCSR_BUF_SIZE);
+	memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE);
 
-	reg_split(crcsr_bus, &crcsr_bus_high, &crcsr_bus_low);
+	reg_split(bridge->crcsr_bus, &crcsr_bus_high, &crcsr_bus_low);
 
-	iowrite32be(crcsr_bus_high, tsi148_bridge->base + TSI148_LCSR_CROU);
-	iowrite32be(crcsr_bus_low, tsi148_bridge->base + TSI148_LCSR_CROL);
+	iowrite32be(crcsr_bus_high, bridge->base + TSI148_LCSR_CROU);
+	iowrite32be(crcsr_bus_low, bridge->base + TSI148_LCSR_CROL);
 
 	/* Ensure that the CR/CSR is configured at the correct offset */
-	cbar = ioread32be(tsi148_bridge->base + TSI148_CBAR);
+	cbar = ioread32be(bridge->base + TSI148_CBAR);
 	cbar = (cbar & TSI148_CRCSR_CBAR_M)>>3;
 
-	vstat = tsi148_slot_get();
+	vstat = tsi148_slot_get(tsi148_bridge);
 
 	if (cbar != vstat) {
+		cbar = vstat;
 		dev_info(&pdev->dev, "Setting CR/CSR offset\n");
-		iowrite32be(cbar<<3, tsi148_bridge->base + TSI148_CBAR);
+		iowrite32be(cbar<<3, bridge->base + TSI148_CBAR);
 	}
 	dev_info(&pdev->dev, "CR/CSR Offset: %d\n", cbar);
 
-	crat = ioread32be(tsi148_bridge->base + TSI148_LCSR_CRAT);
+	crat = ioread32be(bridge->base + TSI148_LCSR_CRAT);
 	if (crat & TSI148_LCSR_CRAT_EN) {
 		dev_info(&pdev->dev, "Enabling CR/CSR space\n");
 		iowrite32be(crat | TSI148_LCSR_CRAT_EN,
-			tsi148_bridge->base + TSI148_LCSR_CRAT);
+			bridge->base + TSI148_LCSR_CRAT);
 	} else
 		dev_info(&pdev->dev, "CR/CSR already enabled\n");
 
@@ -2214,8 +2176,9 @@
 	 * through VME writes.
 	 */
 	if(err_chk) {
-		retval = tsi148_master_set(flush_image, 1, (vstat * 0x80000),
-			0x80000, VME_CRCSR, VME_SCT, VME_D16);
+		retval = tsi148_master_set(bridge->flush_image, 1,
+			(vstat * 0x80000), 0x80000, VME_CRCSR, VME_SCT,
+			VME_D16);
 		if (retval)
 			dev_err(&pdev->dev, "Configuring flush image failed\n");
 	}
@@ -2224,20 +2187,25 @@
 
 }
 
-static void tsi148_crcsr_exit(struct pci_dev *pdev)
+static void tsi148_crcsr_exit(struct vme_bridge *tsi148_bridge,
+	struct pci_dev *pdev)
 {
 	u32 crat;
+	struct tsi148_driver *bridge;
+
+	bridge = tsi148_bridge->driver_priv;
 
 	/* Turn off CR/CSR space */
-	crat = ioread32be(tsi148_bridge->base + TSI148_LCSR_CRAT);
+	crat = ioread32be(bridge->base + TSI148_LCSR_CRAT);
 	iowrite32be(crat & ~TSI148_LCSR_CRAT_EN,
-		tsi148_bridge->base + TSI148_LCSR_CRAT);
+		bridge->base + TSI148_LCSR_CRAT);
 
 	/* Free image */
-	iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_CROU);
-	iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_CROL);
+	iowrite32be(0, bridge->base + TSI148_LCSR_CROU);
+	iowrite32be(0, bridge->base + TSI148_LCSR_CROL);
 
-	pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, crcsr_kernel, crcsr_bus);
+	pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel,
+		bridge->crcsr_bus);
 }
 
 static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -2245,6 +2213,8 @@
 	int retval, i, master_num;
 	u32 data;
 	struct list_head *pos = NULL;
+	struct vme_bridge *tsi148_bridge;
+	struct tsi148_driver *tsi148_device;
 	struct vme_master_resource *master_image;
 	struct vme_slave_resource *slave_image;
 	struct vme_dma_resource *dma_ctrlr;
@@ -2264,6 +2234,18 @@
 
 	memset(tsi148_bridge, 0, sizeof(struct vme_bridge));
 
+	tsi148_device = kmalloc(sizeof(struct tsi148_driver), GFP_KERNEL);
+	if (tsi148_device == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate memory for device "
+			"structure\n");
+		retval = -ENOMEM;
+		goto err_driver;
+	}
+
+	memset(tsi148_device, 0, sizeof(struct tsi148_driver));
+
+	tsi148_bridge->driver_priv = tsi148_device;
+
 	/* Enable the device */
 	retval = pci_enable_device(pdev);
 	if (retval) {
@@ -2279,15 +2261,16 @@
 	}
 
 	/* map registers in BAR 0 */
-	tsi148_bridge->base = ioremap_nocache(pci_resource_start(pdev, 0), 4096);
-	if (!tsi148_bridge->base) {
+	tsi148_device->base = ioremap_nocache(pci_resource_start(pdev, 0),
+		4096);
+	if (!tsi148_device->base) {
 		dev_err(&pdev->dev, "Unable to remap CRG region\n");
 		retval = -EIO;
 		goto err_remap;
 	}
 
 	/* Check to see if the mapping worked out */
-	data = ioread32(tsi148_bridge->base + TSI148_PCFS_ID) & 0x0000FFFF;
+	data = ioread32(tsi148_device->base + TSI148_PCFS_ID) & 0x0000FFFF;
 	if (data != PCI_VENDOR_ID_TUNDRA) {
 		dev_err(&pdev->dev, "CRG region check failed\n");
 		retval = -EIO;
@@ -2295,12 +2278,11 @@
 	}
 
 	/* Initialize wait queues & mutual exclusion flags */
-	/* XXX These need to be moved to the vme_bridge structure */
-	init_waitqueue_head(&dma_queue[0]);
-	init_waitqueue_head(&dma_queue[1]);
-	init_waitqueue_head(&iack_queue);
-	mutex_init(&(vme_int));
-	mutex_init(&(vme_rmw));
+	init_waitqueue_head(&(tsi148_device->dma_queue[0]));
+	init_waitqueue_head(&(tsi148_device->dma_queue[1]));
+	init_waitqueue_head(&(tsi148_device->iack_queue));
+	mutex_init(&(tsi148_device->vme_int));
+	mutex_init(&(tsi148_device->vme_rmw));
 
 	tsi148_bridge->parent = &(pdev->dev);
 	strcpy(tsi148_bridge->name, driver_name);
@@ -2320,29 +2302,29 @@
 	master_num = TSI148_MAX_MASTER;
 	if(err_chk){
 		master_num--;
-		/* XXX */
-		flush_image = (struct vme_master_resource *)kmalloc(
-			sizeof(struct vme_master_resource), GFP_KERNEL);
-		if (flush_image == NULL) {
+
+		tsi148_device->flush_image = (struct vme_master_resource *)
+			kmalloc(sizeof(struct vme_master_resource), GFP_KERNEL);
+		if (tsi148_device->flush_image == NULL) {
 			dev_err(&pdev->dev, "Failed to allocate memory for "
 			"flush resource structure\n");
 			retval = -ENOMEM;
 			goto err_master;
 		}
-		flush_image->parent = tsi148_bridge;
-		spin_lock_init(&(flush_image->lock));
-		flush_image->locked = 1;
-		flush_image->number = master_num;
-		flush_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
-			VME_A64;
-		flush_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
-			VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
-			VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
-			VME_PROG | VME_DATA;
-		flush_image->width_attr = VME_D16 | VME_D32;
-		memset(&(flush_image->pci_resource), 0,
+		tsi148_device->flush_image->parent = tsi148_bridge;
+		spin_lock_init(&(tsi148_device->flush_image->lock));
+		tsi148_device->flush_image->locked = 1;
+		tsi148_device->flush_image->number = master_num;
+		tsi148_device->flush_image->address_attr = VME_A16 | VME_A24 |
+			VME_A32 | VME_A64;
+		tsi148_device->flush_image->cycle_attr = VME_SCT | VME_BLT |
+			VME_MBLT | VME_2eVME | VME_2eSST | VME_2eSSTB |
+			VME_2eSST160 | VME_2eSST267 | VME_2eSST320 | VME_SUPER |
+			VME_USER | VME_PROG | VME_DATA;
+		tsi148_device->flush_image->width_attr = VME_D16 | VME_D32;
+		memset(&(tsi148_device->flush_image->bus_resource), 0,
 			sizeof(struct resource));
-		flush_image->kern_base  = NULL;
+		tsi148_device->flush_image->kern_base  = NULL;
 	}
 
 	/* Add master windows to list */
@@ -2367,7 +2349,7 @@
 			VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
 			VME_PROG | VME_DATA;
 		master_image->width_attr = VME_D16 | VME_D32;
-		memset(&(master_image->pci_resource), 0,
+		memset(&(master_image->bus_resource), 0,
 			sizeof(struct resource));
 		master_image->kern_base  = NULL;
 		list_add_tail(&(master_image->list),
@@ -2415,6 +2397,10 @@
 		mutex_init(&(dma_ctrlr->mtx));
 		dma_ctrlr->locked = 0;
 		dma_ctrlr->number = i;
+		dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM |
+			VME_DMA_MEM_TO_VME | VME_DMA_VME_TO_VME |
+			VME_DMA_MEM_TO_MEM | VME_DMA_PATTERN_TO_VME |
+			VME_DMA_PATTERN_TO_MEM;
 		INIT_LIST_HEAD(&(dma_ctrlr->pending));
 		INIT_LIST_HEAD(&(dma_ctrlr->running));
 		list_add_tail(&(dma_ctrlr->list),
@@ -2455,40 +2441,42 @@
 	tsi148_bridge->lm_detach = tsi148_lm_detach;
 	tsi148_bridge->slot_get = tsi148_slot_get;
 
-	data = ioread32be(tsi148_bridge->base + TSI148_LCSR_VSTAT);
+	data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT);
 	dev_info(&pdev->dev, "Board is%s the VME system controller\n",
 		(data & TSI148_LCSR_VSTAT_SCONS)? "" : " not");
-	dev_info(&pdev->dev, "VME geographical address is %d\n",
-		data & TSI148_LCSR_VSTAT_GA_M);
+	if (!geoid)
+		dev_info(&pdev->dev, "VME geographical address is %d\n",
+			data & TSI148_LCSR_VSTAT_GA_M);
+	else
+		dev_info(&pdev->dev, "VME geographical address is set to %d\n",
+			geoid);
+
 	dev_info(&pdev->dev, "VME Write and flush and error check is %s\n",
 		err_chk ? "enabled" : "disabled");
 
-	if(tsi148_crcsr_init(pdev)) {
+	if (tsi148_crcsr_init(tsi148_bridge, pdev))
 		dev_err(&pdev->dev, "CR/CSR configuration failed.\n");
 		goto err_crcsr;
 
-	}
-
-	/* Need to save tsi148_bridge pointer locally in link list for use in
-	 * tsi148_remove()
-	 */
 	retval = vme_register_bridge(tsi148_bridge);
 	if (retval != 0) {
 		dev_err(&pdev->dev, "Chip Registration failed.\n");
 		goto err_reg;
 	}
 
+	pci_set_drvdata(pdev, tsi148_bridge);
+
 	/* Clear VME bus "board fail", and "power-up reset" lines */
-	data = ioread32be(tsi148_bridge->base + TSI148_LCSR_VSTAT);
+	data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT);
 	data &= ~TSI148_LCSR_VSTAT_BRDFL;
 	data |= TSI148_LCSR_VSTAT_CPURST;
-	iowrite32be(data, tsi148_bridge->base + TSI148_LCSR_VSTAT);
+	iowrite32be(data, tsi148_device->base + TSI148_LCSR_VSTAT);
 
 	return 0;
 
 	vme_unregister_bridge(tsi148_bridge);
 err_reg:
-	tsi148_crcsr_exit(pdev);
+	tsi148_crcsr_exit(tsi148_bridge, pdev);
 err_crcsr:
 err_lm:
 	/* resources are stored in link list */
@@ -2519,15 +2507,17 @@
 		kfree(master_image);
 	}
 
-	tsi148_irq_exit(pdev);
+	tsi148_irq_exit(tsi148_device, pdev);
 err_irq:
 err_test:
-	iounmap(tsi148_bridge->base);
+	iounmap(tsi148_device->base);
 err_remap:
 	pci_release_regions(pdev);
 err_resource:
 	pci_disable_device(pdev);
 err_enable:
+	kfree(tsi148_device);
+err_driver:
 	kfree(tsi148_bridge);
 err_struct:
 	return retval;
@@ -2541,56 +2531,58 @@
 	struct vme_slave_resource *slave_image;
 	struct vme_dma_resource *dma_ctrlr;
 	int i;
+	struct tsi148_driver *bridge;
+	struct vme_bridge *tsi148_bridge = pci_get_drvdata(pdev);
+
+	bridge = tsi148_bridge->driver_priv;
+
 
 	dev_dbg(&pdev->dev, "Driver is being unloaded.\n");
 
-	/* XXX We need to find the pdev->dev in the list of vme_bridge->dev's */
-
 	/*
 	 *  Shutdown all inbound and outbound windows.
 	 */
 	for (i = 0; i < 8; i++) {
-		iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+		iowrite32be(0, bridge->base + TSI148_LCSR_IT[i] +
 			TSI148_LCSR_OFFSET_ITAT);
-		iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+		iowrite32be(0, bridge->base + TSI148_LCSR_OT[i] +
 			TSI148_LCSR_OFFSET_OTAT);
 	}
 
 	/*
 	 *  Shutdown Location monitor.
 	 */
-	iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_LMAT);
+	iowrite32be(0, bridge->base + TSI148_LCSR_LMAT);
 
 	/*
 	 *  Shutdown CRG map.
 	 */
-	iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_CSRAT);
+	iowrite32be(0, bridge->base + TSI148_LCSR_CSRAT);
 
 	/*
 	 *  Clear error status.
 	 */
-	iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_EDPAT);
-	iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_VEAT);
-	iowrite32be(0x07000700, tsi148_bridge->base + TSI148_LCSR_PSTAT);
+	iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_EDPAT);
+	iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_VEAT);
+	iowrite32be(0x07000700, bridge->base + TSI148_LCSR_PSTAT);
 
 	/*
 	 *  Remove VIRQ interrupt (if any)
 	 */
-	if (ioread32be(tsi148_bridge->base + TSI148_LCSR_VICR) & 0x800) {
-		iowrite32be(0x8000, tsi148_bridge->base + TSI148_LCSR_VICR);
-	}
+	if (ioread32be(bridge->base + TSI148_LCSR_VICR) & 0x800)
+		iowrite32be(0x8000, bridge->base + TSI148_LCSR_VICR);
 
 	/*
 	 *  Map all Interrupts to PCI INTA
 	 */
-	iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTM1);
-	iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTM2);
+	iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM1);
+	iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM2);
 
-	tsi148_irq_exit(pdev);
+	tsi148_irq_exit(bridge, pdev);
 
 	vme_unregister_bridge(tsi148_bridge);
 
-	tsi148_crcsr_exit(pdev);
+	tsi148_crcsr_exit(tsi148_bridge, pdev);
 
 	/* resources are stored in link list */
 	list_for_each(pos, &(tsi148_bridge->dma_resources)) {
@@ -2608,19 +2600,22 @@
 
 	/* resources are stored in link list */
 	list_for_each(pos, &(tsi148_bridge->master_resources)) {
-		master_image = list_entry(pos, struct vme_master_resource,				list);
+		master_image = list_entry(pos, struct vme_master_resource,
+			list);
 		list_del(pos);
 		kfree(master_image);
 	}
 
-	tsi148_irq_exit(pdev);
+	tsi148_irq_exit(bridge, pdev);
 
-	iounmap(tsi148_bridge->base);
+	iounmap(bridge->base);
 
 	pci_release_regions(pdev);
 
 	pci_disable_device(pdev);
 
+	kfree(tsi148_bridge->driver_priv);
+
 	kfree(tsi148_bridge);
 }
 
@@ -2634,250 +2629,11 @@
 MODULE_PARM_DESC(err_chk, "Check for VME errors on reads and writes");
 module_param(err_chk, bool, 0);
 
+MODULE_PARM_DESC(geoid, "Override geographical addressing");
+module_param(geoid, int, 0);
+
 MODULE_DESCRIPTION("VME driver for the Tundra Tempe VME bridge");
 MODULE_LICENSE("GPL");
 
 module_init(tsi148_init);
 module_exit(tsi148_exit);
-
-/*----------------------------------------------------------------------------
- * STAGING
- *--------------------------------------------------------------------------*/
-
-#if 0
-/*
- * Direct Mode DMA transfer
- *
- * XXX Not looking at direct mode for now, we can always use link list mode
- *     with a single entry.
- */
-int tsi148_dma_run(struct vme_dma_resource *resource, struct vme_dma_attr src,
-	struct vme_dma_attr dest, size_t count)
-{
-	u32 dctlreg = 0;
-	unsigned int tmp;
-	int val;
-	int channel, x;
-	struct vmeDmaPacket *cur_dma;
-	struct tsi148_dma_descriptor *dmaLL;
-
-	/* direct mode */
-	dctlreg = 0x800000;
-
-	for (x = 0; x < 8; x++) {	/* vme block size */
-		if ((32 << x) >= vmeDma->maxVmeBlockSize) {
-			break;
-		}
-	}
-	if (x == 8)
-		x = 7;
-	dctlreg |= (x << 12);
-
-	for (x = 0; x < 8; x++) {	/* pci block size */
-		if ((32 << x) >= vmeDma->maxPciBlockSize) {
-			break;
-		}
-	}
-	if (x == 8)
-		x = 7;
-	dctlreg |= (x << 4);
-
-	if (vmeDma->vmeBackOffTimer) {
-		for (x = 1; x < 8; x++) {	/* vme timer */
-			if ((1 << (x - 1)) >= vmeDma->vmeBackOffTimer) {
-				break;
-			}
-		}
-		if (x == 8)
-			x = 7;
-		dctlreg |= (x << 8);
-	}
-
-	if (vmeDma->pciBackOffTimer) {
-		for (x = 1; x < 8; x++) {	/* pci timer */
-			if ((1 << (x - 1)) >= vmeDma->pciBackOffTimer) {
-				break;
-			}
-		}
-		if (x == 8)
-			x = 7;
-		dctlreg |= (x << 0);
-	}
-
-	/* Program registers for DMA transfer */
-	iowrite32be(dmaLL->dsau, tsi148_bridge->base +
-		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DSAU);
-	iowrite32be(dmaLL->dsal, tsi148_bridge->base +
-		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DSAL);
-	iowrite32be(dmaLL->ddau, tsi148_bridge->base +
-		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDAU);
-	iowrite32be(dmaLL->ddal, tsi148_bridge->base +
-		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDAL);
-	iowrite32be(dmaLL->dsat, tsi148_bridge->base +
-		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DSAT);
-	iowrite32be(dmaLL->ddat, tsi148_bridge->base +
-		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDAT);
-	iowrite32be(dmaLL->dcnt, tsi148_bridge->base +
-		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCNT);
-	iowrite32be(dmaLL->ddbs, tsi148_bridge->base +
-		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDBS);
-
-	/* Start the operation */
-	iowrite32be(dctlreg | 0x2000000, tsi148_bridge->base +
-		TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
-
-	tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
-		TSI148_LCSR_OFFSET_DSTA);
-	wait_event_interruptible(dma_queue[channel], (tmp & 0x1000000) == 0);
-
-	/*
-	 * Read status register, we should probably do this in some error
-	 * handler rather than here so that we can be sure we haven't kicked off
-	 * another DMA transfer.
-	 */
-	val = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
-		TSI148_LCSR_OFFSET_DSTA);
-
-	vmeDma->vmeDmaStatus = 0;
-	if (val & 0x10000000) {
-		printk(KERN_ERR
-			"DMA Error in DMA_tempe_irqhandler DSTA=%08X\n",
-			val);
-		vmeDma->vmeDmaStatus = val;
-
-	}
-	return (0);
-}
-#endif
-
-#if 0
-
-/* Global VME controller information */
-struct pci_dev *vme_pci_dev;
-
-/*
- * Set the VME bus arbiter with the requested attributes
- */
-int tempe_set_arbiter(vmeArbiterCfg_t * vmeArb)
-{
-	int temp_ctl = 0;
-	int gto = 0;
-
-	temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VCTRL);
-	temp_ctl &= 0xFFEFFF00;
-
-	if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) {
-		gto = 8;
-	} else if (vmeArb->globalTimeoutTimer > 2048) {
-		return (-EINVAL);
-	} else if (vmeArb->globalTimeoutTimer == 0) {
-		gto = 0;
-	} else {
-		gto = 1;
-		while ((16 * (1 << (gto - 1))) < vmeArb->globalTimeoutTimer) {
-			gto += 1;
-		}
-	}
-	temp_ctl |= gto;
-
-	if (vmeArb->arbiterMode != VME_PRIORITY_MODE) {
-		temp_ctl |= 1 << 6;
-	}
-
-	if (vmeArb->arbiterTimeoutFlag) {
-		temp_ctl |= 1 << 7;
-	}
-
-	if (vmeArb->noEarlyReleaseFlag) {
-		temp_ctl |= 1 << 20;
-	}
-	iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_VCTRL);
-
-	return (0);
-}
-
-/*
- * Return the attributes of the VME bus arbiter.
- */
-int tempe_get_arbiter(vmeArbiterCfg_t * vmeArb)
-{
-	int temp_ctl = 0;
-	int gto = 0;
-
-
-	temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VCTRL);
-
-	gto = temp_ctl & 0xF;
-	if (gto != 0) {
-		vmeArb->globalTimeoutTimer = (16 * (1 << (gto - 1)));
-	}
-
-	if (temp_ctl & (1 << 6)) {
-		vmeArb->arbiterMode = VME_R_ROBIN_MODE;
-	} else {
-		vmeArb->arbiterMode = VME_PRIORITY_MODE;
-	}
-
-	if (temp_ctl & (1 << 7)) {
-		vmeArb->arbiterTimeoutFlag = 1;
-	}
-
-	if (temp_ctl & (1 << 20)) {
-		vmeArb->noEarlyReleaseFlag = 1;
-	}
-
-	return (0);
-}
-
-/*
- * Set the VME bus requestor with the requested attributes
- */
-int tempe_set_requestor(vmeRequesterCfg_t * vmeReq)
-{
-	int temp_ctl = 0;
-
-	temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
-	temp_ctl &= 0xFFFF0000;
-
-	if (vmeReq->releaseMode == 1) {
-		temp_ctl |= (1 << 3);
-	}
-
-	if (vmeReq->fairMode == 1) {
-		temp_ctl |= (1 << 2);
-	}
-
-	temp_ctl |= (vmeReq->timeonTimeoutTimer & 7) << 8;
-	temp_ctl |= (vmeReq->timeoffTimeoutTimer & 7) << 12;
-	temp_ctl |= vmeReq->requestLevel;
-
-	iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_VMCTRL);
-	return (0);
-}
-
-/*
- * Return the attributes of the VME bus requestor
- */
-int tempe_get_requestor(vmeRequesterCfg_t * vmeReq)
-{
-	int temp_ctl = 0;
-
-	temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
-
-	if (temp_ctl & 0x18) {
-		vmeReq->releaseMode = 1;
-	}
-
-	if (temp_ctl & (1 << 2)) {
-		vmeReq->fairMode = 1;
-	}
-
-	vmeReq->requestLevel = temp_ctl & 3;
-	vmeReq->timeonTimeoutTimer = (temp_ctl >> 8) & 7;
-	vmeReq->timeoffTimeoutTimer = (temp_ctl >> 12) & 7;
-
-	return (0);
-}
-
-
-#endif
diff --git a/drivers/staging/vme/bridges/vme_tsi148.h b/drivers/staging/vme/bridges/vme_tsi148.h
index 6f0f705..9e5f7fa 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.h
+++ b/drivers/staging/vme/bridges/vme_tsi148.h
@@ -33,6 +33,22 @@
 #define TSI148_MAX_MAILBOX		4	/* Max Mail Box registers */
 #define TSI148_MAX_SEMAPHORE		8	/* Max Semaphores */
 
+/* Structure used to hold driver specific information */
+struct tsi148_driver {
+	void *base;	/* Base Address of device registers */
+	wait_queue_head_t dma_queue[2];
+	wait_queue_head_t iack_queue;
+	void (*lm_callback[4])(int);	/* Called in interrupt handler */
+	void *crcsr_kernel;
+	dma_addr_t crcsr_bus;
+	struct vme_master_resource *flush_image;
+	struct mutex vme_rmw;		/* Only one RMW cycle at a time */
+	struct mutex vme_int;		/*
+					 * Only one VME interrupt can be
+					 * generated at a time, provide locking
+					 */
+};
+
 /*
  * Layout of a DMAC Linked-List Descriptor
  *
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index e228942..c60c80f 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -1,8 +1,8 @@
 /*
  * VMEbus User access driver
  *
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
  *
  * Based on work by:
  *   Tom Armistead and Ajit Prem
@@ -400,8 +400,39 @@
 
 static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)
 {
-	printk(KERN_ERR "Llseek currently incomplete\n");
-	return -EINVAL;
+	loff_t absolute = -1;
+	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+	size_t image_size;
+
+	down(&image[minor].sem);
+	image_size = vme_get_size(image[minor].resource);
+
+	switch (whence) {
+	case SEEK_SET:
+		absolute = off;
+		break;
+	case SEEK_CUR:
+		absolute = file->f_pos + off;
+		break;
+	case SEEK_END:
+		absolute = image_size + off;
+		break;
+	default:
+		up(&image[minor].sem);
+		return -EINVAL;
+		break;
+	}
+
+	if ((absolute < 0) || (absolute >= image_size)) {
+		up(&image[minor].sem);
+		return -EINVAL;
+	}
+
+	file->f_pos = absolute;
+
+	up(&image[minor].sem);
+
+	return absolute;
 }
 
 /*
@@ -574,8 +605,8 @@
 	 * in future revisions if that ever becomes necessary.
 	 */
 	if (bus_num > USER_BUS_MAX) {
-		printk(KERN_ERR "%s: Driver only able to handle %d PIO2 "
-			"Cards\n", driver_name, USER_BUS_MAX);
+		printk(KERN_ERR "%s: Driver only able to handle %d buses\n",
+			driver_name, USER_BUS_MAX);
 		bus_num = USER_BUS_MAX;
 	}
 
@@ -670,8 +701,12 @@
 	/* Request slave resources and allocate buffers (128kB wide) */
 	for (i = SLAVE_MINOR; i < (SLAVE_MAX + 1); i++) {
 		/* XXX Need to properly request attributes */
+		/* For ca91cx42 bridge there are only two slave windows
+		 * supporting A16 addressing, so we request A24 supported
+		 * by all windows.
+		 */
 		image[i].resource = vme_slave_request(vme_user_bridge,
-			VME_A16, VME_SCT);
+			VME_A24, VME_SCT);
 		if (image[i].resource == NULL) {
 			printk(KERN_WARNING "Unable to allocate slave "
 				"resource\n");
@@ -703,6 +738,14 @@
 				"resource\n");
 			goto err_master;
 		}
+		image[i].size_buf = PCI_BUF_SIZE;
+		image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL);
+		if (image[i].kern_buf == NULL) {
+			printk(KERN_WARNING "Unable to allocate memory for "
+				"master window buffers\n");
+			err = -ENOMEM;
+			goto err_master_buf;
+		}
 	}
 
 	/* Create sysfs entries - on udev systems this creates the dev files */
@@ -756,6 +799,9 @@
 
 	/* Ensure counter set correcty to unalloc all master windows */
 	i = MASTER_MAX + 1;
+err_master_buf:
+	for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++)
+		kfree(image[i].kern_buf);
 err_master:
 	while (i > MASTER_MINOR) {
 		i--;
@@ -791,6 +837,9 @@
 	}
 	class_destroy(vme_user_sysfs_class);
 
+	for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++)
+		kfree(image[i].kern_buf);
+
 	for (i = SLAVE_MINOR; i < (SLAVE_MAX + 1); i++) {
 		vme_slave_set(image[i].resource, 0, 0, 0, 0, VME_A32, 0);
 		vme_slave_free(image[i].resource);
@@ -818,7 +867,7 @@
 module_param_array(bus, int, &bus_num, 0);
 
 MODULE_DESCRIPTION("VME User Space Access Driver");
-MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
 MODULE_LICENSE("GPL");
 
 module_init(vme_user_init);
diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c
index 994fdb9..d6d84eb 100644
--- a/drivers/staging/vme/vme.c
+++ b/drivers/staging/vme/vme.c
@@ -1,8 +1,8 @@
 /*
  * VME Bridge Framework
  *
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
  *
  * Based on work by Tom Armistead and Ajit Prem
  * Copyright 2004 Motorola Inc.
@@ -37,8 +37,8 @@
 static unsigned int vme_bus_numbers;
 DEFINE_MUTEX(vme_bus_num_mtx);
 
-static void __exit vme_exit (void);
-static int __init vme_init (void);
+static void __exit vme_exit(void);
+static int __init vme_init(void);
 
 
 /*
@@ -86,26 +86,26 @@
  * XXX VME bridges could be available on buses other than PCI. At the momment
  *     this framework only supports PCI devices.
  */
-void * vme_alloc_consistent(struct vme_resource *resource, size_t size,
+void *vme_alloc_consistent(struct vme_resource *resource, size_t size,
 	dma_addr_t *dma)
 {
 	struct vme_bridge *bridge;
 	struct pci_dev *pdev;
 
-	if(resource == NULL) {
-		printk("No resource\n");
+	if (resource == NULL) {
+		printk(KERN_ERR "No resource\n");
 		return NULL;
 	}
 
 	bridge = find_bridge(resource);
-	if(bridge == NULL) {
-		printk("Can't find bridge\n");
+	if (bridge == NULL) {
+		printk(KERN_ERR "Can't find bridge\n");
 		return NULL;
 	}
 
 	/* Find pci_dev container of dev */
 	if (bridge->parent == NULL) {
-		printk("Dev entry NULL\n");
+		printk(KERN_ERR "Dev entry NULL\n");
 		return NULL;
 	}
 	pdev = container_of(bridge->parent, struct pci_dev, dev);
@@ -126,14 +126,14 @@
 	struct vme_bridge *bridge;
 	struct pci_dev *pdev;
 
-	if(resource == NULL) {
-		printk("No resource\n");
+	if (resource == NULL) {
+		printk(KERN_ERR "No resource\n");
 		return;
 	}
 
 	bridge = find_bridge(resource);
-	if(bridge == NULL) {
-		printk("Can't find bridge\n");
+	if (bridge == NULL) {
+		printk(KERN_ERR "Can't find bridge\n");
 		return;
 	}
 
@@ -216,7 +216,7 @@
 		/* User Defined */
 		break;
 	default:
-		printk("Invalid address space\n");
+		printk(KERN_ERR "Invalid address space\n");
 		retval = -EINVAL;
 		break;
 	}
@@ -228,7 +228,7 @@
  * Request a slave image with specific attributes, return some unique
  * identifier.
  */
-struct vme_resource * vme_slave_request(struct device *dev,
+struct vme_resource *vme_slave_request(struct device *dev,
 	vme_address_t address, vme_cycle_t cycle)
 {
 	struct vme_bridge *bridge;
@@ -249,13 +249,13 @@
 			struct vme_slave_resource, list);
 
 		if (slave_image == NULL) {
-			printk("Registered NULL Slave resource\n");
+			printk(KERN_ERR "Registered NULL Slave resource\n");
 			continue;
 		}
 
 		/* Find an unlocked and compatible image */
 		mutex_lock(&(slave_image->mtx));
-		if(((slave_image->address_attr & address) == address) &&
+		if (((slave_image->address_attr & address) == address) &&
 			((slave_image->cycle_attr & cycle) == cycle) &&
 			(slave_image->locked == 0)) {
 
@@ -292,7 +292,7 @@
 }
 EXPORT_SYMBOL(vme_slave_request);
 
-int vme_slave_set (struct vme_resource *resource, int enabled,
+int vme_slave_set(struct vme_resource *resource, int enabled,
 	unsigned long long vme_base, unsigned long long size,
 	dma_addr_t buf_base, vme_address_t aspace, vme_cycle_t cycle)
 {
@@ -301,25 +301,25 @@
 	int retval;
 
 	if (resource->type != VME_SLAVE) {
-		printk("Not a slave resource\n");
+		printk(KERN_ERR "Not a slave resource\n");
 		return -EINVAL;
 	}
 
 	image = list_entry(resource->entry, struct vme_slave_resource, list);
 
 	if (bridge->slave_set == NULL) {
-		printk("Function not supported\n");
+		printk(KERN_ERR "Function not supported\n");
 		return -ENOSYS;
 	}
 
-	if(!(((image->address_attr & aspace) == aspace) &&
+	if (!(((image->address_attr & aspace) == aspace) &&
 		((image->cycle_attr & cycle) == cycle))) {
-		printk("Invalid attributes\n");
+		printk(KERN_ERR "Invalid attributes\n");
 		return -EINVAL;
 	}
 
 	retval = vme_check_window(aspace, vme_base, size);
-	if(retval)
+	if (retval)
 		return retval;
 
 	return bridge->slave_set(image, enabled, vme_base, size, buf_base,
@@ -327,7 +327,7 @@
 }
 EXPORT_SYMBOL(vme_slave_set);
 
-int vme_slave_get (struct vme_resource *resource, int *enabled,
+int vme_slave_get(struct vme_resource *resource, int *enabled,
 	unsigned long long *vme_base, unsigned long long *size,
 	dma_addr_t *buf_base, vme_address_t *aspace, vme_cycle_t *cycle)
 {
@@ -335,14 +335,14 @@
 	struct vme_slave_resource *image;
 
 	if (resource->type != VME_SLAVE) {
-		printk("Not a slave resource\n");
+		printk(KERN_ERR "Not a slave resource\n");
 		return -EINVAL;
 	}
 
 	image = list_entry(resource->entry, struct vme_slave_resource, list);
 
 	if (bridge->slave_get == NULL) {
-		printk("vme_slave_get not supported\n");
+		printk(KERN_ERR "vme_slave_get not supported\n");
 		return -EINVAL;
 	}
 
@@ -356,14 +356,14 @@
 	struct vme_slave_resource *slave_image;
 
 	if (resource->type != VME_SLAVE) {
-		printk("Not a slave resource\n");
+		printk(KERN_ERR "Not a slave resource\n");
 		return;
 	}
 
 	slave_image = list_entry(resource->entry, struct vme_slave_resource,
 		list);
 	if (slave_image == NULL) {
-		printk("Can't find slave resource\n");
+		printk(KERN_ERR "Can't find slave resource\n");
 		return;
 	}
 
@@ -384,7 +384,7 @@
  * Request a master image with specific attributes, return some unique
  * identifier.
  */
-struct vme_resource * vme_master_request(struct device *dev,
+struct vme_resource *vme_master_request(struct device *dev,
 	vme_address_t address, vme_cycle_t cycle, vme_width_t dwidth)
 {
 	struct vme_bridge *bridge;
@@ -411,7 +411,7 @@
 
 		/* Find an unlocked and compatible image */
 		spin_lock(&(master_image->lock));
-		if(((master_image->address_attr & address) == address) &&
+		if (((master_image->address_attr & address) == address) &&
 			((master_image->cycle_attr & cycle) == cycle) &&
 			((master_image->width_attr & dwidth) == dwidth) &&
 			(master_image->locked == 0)) {
@@ -452,7 +452,7 @@
 }
 EXPORT_SYMBOL(vme_master_request);
 
-int vme_master_set (struct vme_resource *resource, int enabled,
+int vme_master_set(struct vme_resource *resource, int enabled,
 	unsigned long long vme_base, unsigned long long size,
 	vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
 {
@@ -461,26 +461,26 @@
 	int retval;
 
 	if (resource->type != VME_MASTER) {
-		printk("Not a master resource\n");
+		printk(KERN_ERR "Not a master resource\n");
 		return -EINVAL;
 	}
 
 	image = list_entry(resource->entry, struct vme_master_resource, list);
 
 	if (bridge->master_set == NULL) {
-		printk("vme_master_set not supported\n");
+		printk(KERN_WARNING "vme_master_set not supported\n");
 		return -EINVAL;
 	}
 
-	if(!(((image->address_attr & aspace) == aspace) &&
+	if (!(((image->address_attr & aspace) == aspace) &&
 		((image->cycle_attr & cycle) == cycle) &&
 		((image->width_attr & dwidth) == dwidth))) {
-		printk("Invalid attributes\n");
+		printk(KERN_WARNING "Invalid attributes\n");
 		return -EINVAL;
 	}
 
 	retval = vme_check_window(aspace, vme_base, size);
-	if(retval)
+	if (retval)
 		return retval;
 
 	return bridge->master_set(image, enabled, vme_base, size, aspace,
@@ -488,7 +488,7 @@
 }
 EXPORT_SYMBOL(vme_master_set);
 
-int vme_master_get (struct vme_resource *resource, int *enabled,
+int vme_master_get(struct vme_resource *resource, int *enabled,
 	unsigned long long *vme_base, unsigned long long *size,
 	vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
 {
@@ -496,14 +496,14 @@
 	struct vme_master_resource *image;
 
 	if (resource->type != VME_MASTER) {
-		printk("Not a master resource\n");
+		printk(KERN_ERR "Not a master resource\n");
 		return -EINVAL;
 	}
 
 	image = list_entry(resource->entry, struct vme_master_resource, list);
 
 	if (bridge->master_get == NULL) {
-		printk("vme_master_set not supported\n");
+		printk(KERN_WARNING "vme_master_set not supported\n");
 		return -EINVAL;
 	}
 
@@ -515,7 +515,7 @@
 /*
  * Read data out of VME space into a buffer.
  */
-ssize_t vme_master_read (struct vme_resource *resource, void *buf, size_t count,
+ssize_t vme_master_read(struct vme_resource *resource, void *buf, size_t count,
 	loff_t offset)
 {
 	struct vme_bridge *bridge = find_bridge(resource);
@@ -523,12 +523,12 @@
 	size_t length;
 
 	if (bridge->master_read == NULL) {
-		printk("Reading from resource not supported\n");
+		printk(KERN_WARNING "Reading from resource not supported\n");
 		return -EINVAL;
 	}
 
 	if (resource->type != VME_MASTER) {
-		printk("Not a master resource\n");
+		printk(KERN_ERR "Not a master resource\n");
 		return -EINVAL;
 	}
 
@@ -537,7 +537,7 @@
 	length = vme_get_size(resource);
 
 	if (offset > length) {
-		printk("Invalid Offset\n");
+		printk(KERN_WARNING "Invalid Offset\n");
 		return -EFAULT;
 	}
 
@@ -552,7 +552,7 @@
 /*
  * Write data out to VME space from a buffer.
  */
-ssize_t vme_master_write (struct vme_resource *resource, void *buf,
+ssize_t vme_master_write(struct vme_resource *resource, void *buf,
 	size_t count, loff_t offset)
 {
 	struct vme_bridge *bridge = find_bridge(resource);
@@ -560,12 +560,12 @@
 	size_t length;
 
 	if (bridge->master_write == NULL) {
-		printk("Writing to resource not supported\n");
+		printk(KERN_WARNING "Writing to resource not supported\n");
 		return -EINVAL;
 	}
 
 	if (resource->type != VME_MASTER) {
-		printk("Not a master resource\n");
+		printk(KERN_ERR "Not a master resource\n");
 		return -EINVAL;
 	}
 
@@ -574,7 +574,7 @@
 	length = vme_get_size(resource);
 
 	if (offset > length) {
-		printk("Invalid Offset\n");
+		printk(KERN_WARNING "Invalid Offset\n");
 		return -EFAULT;
 	}
 
@@ -588,19 +588,19 @@
 /*
  * Perform RMW cycle to provided location.
  */
-unsigned int vme_master_rmw (struct vme_resource *resource, unsigned int mask,
+unsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask,
 	unsigned int compare, unsigned int swap, loff_t offset)
 {
 	struct vme_bridge *bridge = find_bridge(resource);
 	struct vme_master_resource *image;
 
 	if (bridge->master_rmw == NULL) {
-		printk("Writing to resource not supported\n");
+		printk(KERN_WARNING "Writing to resource not supported\n");
 		return -EINVAL;
 	}
 
 	if (resource->type != VME_MASTER) {
-		printk("Not a master resource\n");
+		printk(KERN_ERR "Not a master resource\n");
 		return -EINVAL;
 	}
 
@@ -615,14 +615,14 @@
 	struct vme_master_resource *master_image;
 
 	if (resource->type != VME_MASTER) {
-		printk("Not a master resource\n");
+		printk(KERN_ERR "Not a master resource\n");
 		return;
 	}
 
 	master_image = list_entry(resource->entry, struct vme_master_resource,
 		list);
 	if (master_image == NULL) {
-		printk("Can't find master resource\n");
+		printk(KERN_ERR "Can't find master resource\n");
 		return;
 	}
 
@@ -643,7 +643,7 @@
  * Request a DMA controller with specific attributes, return some unique
  * identifier.
  */
-struct vme_resource *vme_dma_request(struct device *dev)
+struct vme_resource *vme_dma_request(struct device *dev, vme_dma_route_t route)
 {
 	struct vme_bridge *bridge;
 	struct list_head *dma_pos = NULL;
@@ -666,13 +666,15 @@
 			struct vme_dma_resource, list);
 
 		if (dma_ctrlr == NULL) {
-			printk("Registered NULL DMA resource\n");
+			printk(KERN_ERR "Registered NULL DMA resource\n");
 			continue;
 		}
 
-		/* Find an unlocked controller */
+		/* Find an unlocked and compatible controller */
 		mutex_lock(&(dma_ctrlr->mtx));
-		if(dma_ctrlr->locked == 0) {
+		if (((dma_ctrlr->route_attr & route) == route) &&
+			(dma_ctrlr->locked == 0)) {
+
 			dma_ctrlr->locked = 1;
 			mutex_unlock(&(dma_ctrlr->mtx));
 			allocated_ctrlr = dma_ctrlr;
@@ -715,16 +717,15 @@
 	struct vme_dma_list *dma_list;
 
 	if (resource->type != VME_DMA) {
-		printk("Not a DMA resource\n");
+		printk(KERN_ERR "Not a DMA resource\n");
 		return NULL;
 	}
 
 	ctrlr = list_entry(resource->entry, struct vme_dma_resource, list);
 
-	dma_list = (struct vme_dma_list *)kmalloc(
-		sizeof(struct vme_dma_list), GFP_KERNEL);
-	if(dma_list == NULL) {
-		printk("Unable to allocate memory for new dma list\n");
+	dma_list = kmalloc(sizeof(struct vme_dma_list), GFP_KERNEL);
+	if (dma_list == NULL) {
+		printk(KERN_ERR "Unable to allocate memory for new dma list\n");
 		return NULL;
 	}
 	INIT_LIST_HEAD(&(dma_list->entries));
@@ -744,17 +745,17 @@
 	struct vme_dma_attr *attributes;
 	struct vme_dma_pattern *pattern_attr;
 
-	attributes = (struct vme_dma_attr *)kmalloc(
-		sizeof(struct vme_dma_attr), GFP_KERNEL);
-	if(attributes == NULL) {
-		printk("Unable to allocate memory for attributes structure\n");
+	attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL);
+	if (attributes == NULL) {
+		printk(KERN_ERR "Unable to allocate memory for attributes "
+			"structure\n");
 		goto err_attr;
 	}
 
-	pattern_attr = (struct vme_dma_pattern *)kmalloc(
-		sizeof(struct vme_dma_pattern), GFP_KERNEL);
-	if(pattern_attr == NULL) {
-		printk("Unable to allocate memory for pattern attributes\n");
+	pattern_attr = kmalloc(sizeof(struct vme_dma_pattern), GFP_KERNEL);
+	if (pattern_attr == NULL) {
+		printk(KERN_ERR "Unable to allocate memory for pattern "
+			"attributes\n");
 		goto err_pat;
 	}
 
@@ -784,17 +785,17 @@
 
 	/* XXX Run some sanity checks here */
 
-	attributes = (struct vme_dma_attr *)kmalloc(
-		sizeof(struct vme_dma_attr), GFP_KERNEL);
-	if(attributes == NULL) {
-		printk("Unable to allocate memory for attributes structure\n");
+	attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL);
+	if (attributes == NULL) {
+		printk(KERN_ERR "Unable to allocate memory for attributes "
+			"structure\n");
 		goto err_attr;
 	}
 
-	pci_attr = (struct vme_dma_pci *)kmalloc(sizeof(struct vme_dma_pci),
-		GFP_KERNEL);
-	if(pci_attr == NULL) {
-		printk("Unable to allocate memory for pci attributes\n");
+	pci_attr = kmalloc(sizeof(struct vme_dma_pci), GFP_KERNEL);
+	if (pci_attr == NULL) {
+		printk(KERN_ERR "Unable to allocate memory for pci "
+			"attributes\n");
 		goto err_pci;
 	}
 
@@ -824,19 +825,18 @@
 	struct vme_dma_attr *attributes;
 	struct vme_dma_vme *vme_attr;
 
-	/* XXX Run some sanity checks here */
-
-	attributes = (struct vme_dma_attr *)kmalloc(
+	attributes = kmalloc(
 		sizeof(struct vme_dma_attr), GFP_KERNEL);
-	if(attributes == NULL) {
-		printk("Unable to allocate memory for attributes structure\n");
+	if (attributes == NULL) {
+		printk(KERN_ERR "Unable to allocate memory for attributes "
+			"structure\n");
 		goto err_attr;
 	}
 
-	vme_attr = (struct vme_dma_vme *)kmalloc(sizeof(struct vme_dma_vme),
-		GFP_KERNEL);
-	if(vme_attr == NULL) {
-		printk("Unable to allocate memory for vme attributes\n");
+	vme_attr = kmalloc(sizeof(struct vme_dma_vme), GFP_KERNEL);
+	if (vme_attr == NULL) {
+		printk(KERN_ERR "Unable to allocate memory for vme "
+			"attributes\n");
 		goto err_vme;
 	}
 
@@ -875,12 +875,12 @@
 	int retval;
 
 	if (bridge->dma_list_add == NULL) {
-		printk("Link List DMA generation not supported\n");
+		printk(KERN_WARNING "Link List DMA generation not supported\n");
 		return -EINVAL;
 	}
 
 	if (!mutex_trylock(&(list->mtx))) {
-		printk("Link List already submitted\n");
+		printk(KERN_ERR "Link List already submitted\n");
 		return -EINVAL;
 	}
 
@@ -898,7 +898,7 @@
 	int retval;
 
 	if (bridge->dma_list_exec == NULL) {
-		printk("Link List DMA execution not supported\n");
+		printk(KERN_ERR "Link List DMA execution not supported\n");
 		return -EINVAL;
 	}
 
@@ -918,12 +918,12 @@
 	int retval;
 
 	if (bridge->dma_list_empty == NULL) {
-		printk("Emptying of Link Lists not supported\n");
+		printk(KERN_WARNING "Emptying of Link Lists not supported\n");
 		return -EINVAL;
 	}
 
 	if (!mutex_trylock(&(list->mtx))) {
-		printk("Link List in use\n");
+		printk(KERN_ERR "Link List in use\n");
 		return -EINVAL;
 	}
 
@@ -933,7 +933,7 @@
 	 */
 	retval = bridge->dma_list_empty(list);
 	if (retval) {
-		printk("Unable to empty link-list entries\n");
+		printk(KERN_ERR "Unable to empty link-list entries\n");
 		mutex_unlock(&(list->mtx));
 		return retval;
 	}
@@ -949,19 +949,19 @@
 	struct vme_dma_resource *ctrlr;
 
 	if (resource->type != VME_DMA) {
-		printk("Not a DMA resource\n");
+		printk(KERN_ERR "Not a DMA resource\n");
 		return -EINVAL;
 	}
 
 	ctrlr = list_entry(resource->entry, struct vme_dma_resource, list);
 
 	if (!mutex_trylock(&(ctrlr->mtx))) {
-		printk("Resource busy, can't free\n");
+		printk(KERN_ERR "Resource busy, can't free\n");
 		return -EBUSY;
 	}
 
 	if (!(list_empty(&(ctrlr->pending)) && list_empty(&(ctrlr->running)))) {
-		printk("Resource still processing transfers\n");
+		printk(KERN_WARNING "Resource still processing transfers\n");
 		mutex_unlock(&(ctrlr->mtx));
 		return -EBUSY;
 	}
@@ -991,7 +991,7 @@
 EXPORT_SYMBOL(vme_irq_handler);
 
 int vme_irq_request(struct device *dev, int level, int statid,
-	void (*callback)(int level, int vector, void *priv_data),
+	void (*callback)(int, int, void *),
 	void *priv_data)
 {
 	struct vme_bridge *bridge;
@@ -1002,7 +1002,7 @@
 		return -EINVAL;
 	}
 
-	if((level < 1) || (level > 7)) {
+	if ((level < 1) || (level > 7)) {
 		printk(KERN_ERR "Invalid interrupt level\n");
 		return -EINVAL;
 	}
@@ -1025,7 +1025,7 @@
 	bridge->irq[level - 1].callback[statid].func = callback;
 
 	/* Enable IRQ level */
-	bridge->irq_set(level, 1, 1);
+	bridge->irq_set(bridge, level, 1, 1);
 
 	mutex_unlock(&(bridge->irq_mtx));
 
@@ -1043,7 +1043,7 @@
 		return;
 	}
 
-	if((level < 1) || (level > 7)) {
+	if ((level < 1) || (level > 7)) {
 		printk(KERN_ERR "Invalid interrupt level\n");
 		return;
 	}
@@ -1059,7 +1059,7 @@
 
 	/* Disable IRQ level if no more interrupts attached at this level*/
 	if (bridge->irq[level - 1].count == 0)
-		bridge->irq_set(level, 0, 1);
+		bridge->irq_set(bridge, level, 0, 1);
 
 	bridge->irq[level - 1].callback[statid].func = NULL;
 	bridge->irq[level - 1].callback[statid].priv_data = NULL;
@@ -1078,17 +1078,17 @@
 		return -EINVAL;
 	}
 
-	if((level < 1) || (level > 7)) {
+	if ((level < 1) || (level > 7)) {
 		printk(KERN_WARNING "Invalid interrupt level\n");
 		return -EINVAL;
 	}
 
 	if (bridge->irq_generate == NULL) {
-		printk("Interrupt generation not supported\n");
+		printk(KERN_WARNING "Interrupt generation not supported\n");
 		return -EINVAL;
 	}
 
-	return bridge->irq_generate(level, statid);
+	return bridge->irq_generate(bridge, level, statid);
 }
 EXPORT_SYMBOL(vme_irq_generate);
 
@@ -1189,8 +1189,6 @@
 		return -EINVAL;
 	}
 
-	/* XXX Check parameters */
-
 	return bridge->lm_set(lm, lm_base, aspace, cycle);
 }
 EXPORT_SYMBOL(vme_lm_set);
@@ -1297,11 +1295,11 @@
 	}
 
 	if (bridge->slot_get == NULL) {
-		printk("vme_slot_get not supported\n");
+		printk(KERN_WARNING "vme_slot_get not supported\n");
 		return -EINVAL;
 	}
 
-	return bridge->slot_get();
+	return bridge->slot_get(bridge);
 }
 EXPORT_SYMBOL(vme_slot_get);
 
@@ -1331,7 +1329,7 @@
 	mutex_unlock(&vme_bus_num_mtx);
 }
 
-int vme_register_bridge (struct vme_bridge *bridge)
+int vme_register_bridge(struct vme_bridge *bridge)
 {
 	struct device *dev;
 	int retval;
@@ -1358,7 +1356,7 @@
 		dev_set_name(dev, "vme-%x.%x", bridge->num, i + 1);
 
 		retval = device_register(dev);
-		if(retval)
+		if (retval)
 			goto err_reg;
 	}
 
@@ -1375,7 +1373,7 @@
 }
 EXPORT_SYMBOL(vme_register_bridge);
 
-void vme_unregister_bridge (struct vme_bridge *bridge)
+void vme_unregister_bridge(struct vme_bridge *bridge)
 {
 	int i;
 	struct device *dev;
@@ -1392,7 +1390,7 @@
 
 /* - Driver Registration --------------------------------------------------- */
 
-int vme_register_driver (struct vme_driver *drv)
+int vme_register_driver(struct vme_driver *drv)
 {
 	drv->driver.name = drv->name;
 	drv->driver.bus = &vme_bus_type;
@@ -1401,7 +1399,7 @@
 }
 EXPORT_SYMBOL(vme_register_driver);
 
-void vme_unregister_driver (struct vme_driver *drv)
+void vme_unregister_driver(struct vme_driver *drv)
 {
 	driver_unregister(&drv->driver);
 }
@@ -1418,10 +1416,10 @@
 
 	/* Determine slot number */
 	num = 0;
-	while(num < VME_SLOTS_MAX) {
-		if(&(bridge->dev[num]) == dev) {
+	while (num < VME_SLOTS_MAX) {
+		if (&(bridge->dev[num]) == dev)
 			break;
-		}
+
 		num++;
 	}
 	if (num == VME_SLOTS_MAX) {
@@ -1437,8 +1435,8 @@
 
 static struct vme_driver *dev_to_vme_driver(struct device *dev)
 {
-	if(dev->driver == NULL)
-		printk("Bugger dev->driver is NULL\n");
+	if (dev->driver == NULL)
+		printk(KERN_ERR "Bugger dev->driver is NULL\n");
 
 	return container_of(dev->driver, struct vme_driver, driver);
 }
@@ -1462,7 +1460,7 @@
 	}
 
 	i = 0;
-	while((driver->bind_table[i].bus != 0) ||
+	while ((driver->bind_table[i].bus != 0) ||
 		(driver->bind_table[i].slot != 0)) {
 
 		if (bridge->num == driver->bind_table[i].bus) {
@@ -1493,9 +1491,8 @@
 	driver = dev_to_vme_driver(dev);
 	bridge = dev_to_bridge(dev);
 
-	if(driver->probe != NULL) {
+	if (driver->probe != NULL)
 		retval = driver->probe(dev, bridge->num, vme_calc_slot(dev));
-	}
 
 	return retval;
 }
@@ -1509,9 +1506,8 @@
 	driver = dev_to_vme_driver(dev);
 	bridge = dev_to_bridge(dev);
 
-	if(driver->remove != NULL) {
+	if (driver->remove != NULL)
 		retval = driver->remove(dev, bridge->num, vme_calc_slot(dev));
-	}
 
 	return retval;
 }
@@ -1524,18 +1520,18 @@
 };
 EXPORT_SYMBOL(vme_bus_type);
 
-static int __init vme_init (void)
+static int __init vme_init(void)
 {
 	return bus_register(&vme_bus_type);
 }
 
-static void __exit vme_exit (void)
+static void __exit vme_exit(void)
 {
 	bus_unregister(&vme_bus_type);
 }
 
 MODULE_DESCRIPTION("VME bridge driver framework");
-MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
 MODULE_LICENSE("GPL");
 
 module_init(vme_init);
diff --git a/drivers/staging/vme/vme.h b/drivers/staging/vme/vme.h
index 97dc22e..48768ca 100644
--- a/drivers/staging/vme/vme.h
+++ b/drivers/staging/vme/vme.h
@@ -68,6 +68,14 @@
 #define VME_DMA_PATTERN_WORD		(1<<1)
 #define VME_DMA_PATTERN_INCREMENT	(1<<2)
 
+typedef u32 vme_dma_route_t;
+#define VME_DMA_VME_TO_MEM		(1<<0)
+#define VME_DMA_MEM_TO_VME		(1<<1)
+#define VME_DMA_VME_TO_VME		(1<<2)
+#define VME_DMA_MEM_TO_MEM		(1<<3)
+#define VME_DMA_PATTERN_TO_VME		(1<<4)
+#define VME_DMA_PATTERN_TO_MEM		(1<<5)
+
 struct vme_dma_attr {
 	vme_dma_t type;
 	void *private;
@@ -98,32 +106,33 @@
 	struct device_driver    driver;
 };
 
-void * vme_alloc_consistent(struct vme_resource *, size_t, dma_addr_t *);
+void *vme_alloc_consistent(struct vme_resource *, size_t, dma_addr_t *);
 void vme_free_consistent(struct vme_resource *, size_t,  void *,
 	dma_addr_t);
 
 size_t vme_get_size(struct vme_resource *);
 
-struct vme_resource * vme_slave_request(struct device *, vme_address_t, vme_cycle_t);
-int vme_slave_set (struct vme_resource *, int, unsigned long long,
+struct vme_resource *vme_slave_request(struct device *, vme_address_t,
+	vme_cycle_t);
+int vme_slave_set(struct vme_resource *, int, unsigned long long,
 	unsigned long long, dma_addr_t, vme_address_t, vme_cycle_t);
-int vme_slave_get (struct vme_resource *, int *, unsigned long long *,
+int vme_slave_get(struct vme_resource *, int *, unsigned long long *,
 	unsigned long long *, dma_addr_t *, vme_address_t *, vme_cycle_t *);
 void vme_slave_free(struct vme_resource *);
 
-struct vme_resource * vme_master_request(struct device *, vme_address_t, vme_cycle_t,
-	vme_width_t);
-int vme_master_set (struct vme_resource *, int, unsigned long long,
+struct vme_resource *vme_master_request(struct device *, vme_address_t,
+	vme_cycle_t, vme_width_t);
+int vme_master_set(struct vme_resource *, int, unsigned long long,
 	unsigned long long, vme_address_t, vme_cycle_t, vme_width_t);
-int vme_master_get (struct vme_resource *, int *, unsigned long long *,
+int vme_master_get(struct vme_resource *, int *, unsigned long long *,
 	unsigned long long *, vme_address_t *, vme_cycle_t *, vme_width_t *);
 ssize_t vme_master_read(struct vme_resource *, void *, size_t, loff_t);
 ssize_t vme_master_write(struct vme_resource *, void *, size_t, loff_t);
-unsigned int vme_master_rmw (struct vme_resource *, unsigned int, unsigned int,
+unsigned int vme_master_rmw(struct vme_resource *, unsigned int, unsigned int,
 	unsigned int, loff_t);
 void vme_master_free(struct vme_resource *);
 
-struct vme_resource *vme_dma_request(struct device *);
+struct vme_resource *vme_dma_request(struct device *, vme_dma_route_t);
 struct vme_dma_list *vme_new_dma_list(struct vme_resource *);
 struct vme_dma_attr *vme_dma_pattern_attribute(u32, vme_pattern_t);
 struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t);
@@ -153,8 +162,8 @@
 
 int vme_slot_get(struct device *);
 
-int vme_register_driver (struct vme_driver *);
-void vme_unregister_driver (struct vme_driver *);
+int vme_register_driver(struct vme_driver *);
+void vme_unregister_driver(struct vme_driver *);
 
 
 #endif /* _VME_H_ */
diff --git a/drivers/staging/vme/vme_api.txt b/drivers/staging/vme/vme_api.txt
index a5c1b1cd5..a910a0c 100644
--- a/drivers/staging/vme/vme_api.txt
+++ b/drivers/staging/vme/vme_api.txt
@@ -77,16 +77,21 @@
 	struct vme_resource * vme_slave_request(struct device *dev,
 		vme_address_t aspace, vme_cycle_t cycle);
 
-	struct vme_resource *vme_dma_request(struct device *dev);
+	struct vme_resource *vme_dma_request(struct device *dev,
+		vme_dma_route_t route);
 
 For slave windows these attributes are split into those of type 'vme_address_t'
-and 'vme_cycle_t'. Master windows add a further set of attributes 'vme_cycle_t'.
-These attributes are defined as bitmasks and as such any combination of the
-attributes can be requested for a single window, the core will assign a window
-that meets the requirements, returning a pointer of type vme_resource that
-should be used to identify the allocated resource when it is used. If an
-unallocated window fitting the requirements can not be found a NULL pointer will
-be returned.
+and 'vme_cycle_t'. Master windows add a further set of attributes
+'vme_cycle_t'.  These attributes are defined as bitmasks and as such any
+combination of the attributes can be requested for a single window, the core
+will assign a window that meets the requirements, returning a pointer of type
+vme_resource that should be used to identify the allocated resource when it is
+used. For DMA controllers, the request function requires the potential
+direction of any transfers to be provided in the route attributes. This is
+typically VME-to-MEM and/or MEM-to-VME, though some hardware can support
+VME-to-VME and MEM-to-MEM transfers as well as test pattern generation. If an
+unallocated window fitting the requirements can not be found a NULL pointer
+will be returned.
 
 Functions are also provided to free window allocations once they are no longer
 required. These functions should be passed the pointer to the resource provided
@@ -237,6 +242,12 @@
 		struct vme_dma_attr *src, struct vme_dma_attr *dest,
 		size_t count);
 
+NOTE:	The detailed attributes of the transfers source and destination
+	are not checked until an entry is added to a DMA list, the request
+	for a DMA channel purely checks the directions in which the
+	controller is expected to transfer data. As a result it is
+	possible for this call to return an error, for example if the
+	source or destination is in an unsupported VME address space.
 
 Transfer Attributes
 -------------------
diff --git a/drivers/staging/vme/vme_bridge.h b/drivers/staging/vme/vme_bridge.h
index 851fa92..b653ec0 100644
--- a/drivers/staging/vme/vme_bridge.h
+++ b/drivers/staging/vme/vme_bridge.h
@@ -19,7 +19,7 @@
 	vme_address_t address_attr;
 	vme_cycle_t cycle_attr;
 	vme_width_t width_attr;
-	struct resource pci_resource;	/* XXX Rename to be bus agnostic */
+	struct resource bus_resource;
 	void *kern_base;
 };
 
@@ -64,6 +64,7 @@
 	int number;
 	struct list_head pending;
 	struct list_head running;
+	vme_dma_route_t route_attr;
 };
 
 struct vme_lm_resource {
@@ -101,7 +102,7 @@
  * Currently we assume that all chips are PCI-based
  */
 struct vme_bridge {
-        char name[VMENAMSIZ];
+	char name[VMENAMSIZ];
 	int num;
 	struct list_head master_resources;
 	struct list_head slave_resources;
@@ -112,7 +113,7 @@
 
 	/* Bridge Info - XXX Move to private structure? */
 	struct device *parent;	/* Generic device struct (pdev->dev for PCI) */
-	void * base;		/* Base Address of device registers */
+	void *driver_priv;	/* Private pointer for the bridge driver */
 
 	struct device dev[VME_SLOTS_MAX];	/* Device registered with
 						 * device model on VME bus
@@ -151,8 +152,8 @@
 	int (*dma_list_empty) (struct vme_dma_list *);
 
 	/* Interrupt Functions */
-	void (*irq_set) (int, int, int);
-	int (*irq_generate) (int, int);
+	void (*irq_set) (struct vme_bridge *, int, int, int);
+	int (*irq_generate) (struct vme_bridge *, int, int);
 
 	/* Location monitor functions */
 	int (*lm_set) (struct vme_lm_resource *, unsigned long long,
@@ -163,102 +164,12 @@
 	int (*lm_detach) (struct vme_lm_resource *, int);
 
 	/* CR/CSR space functions */
-	int (*slot_get) (void);
-	/* Use standard master read and write functions to access CR/CSR */
-
-#if 0
-	int (*set_prefetch) (void);
-	int (*get_prefetch) (void);
-	int (*set_arbiter) (void);
-	int (*get_arbiter) (void);
-	int (*set_requestor) (void);
-	int (*get_requestor) (void);
-#endif
+	int (*slot_get) (struct vme_bridge *);
 };
 
 void vme_irq_handler(struct vme_bridge *, int, int);
 
-int vme_register_bridge (struct vme_bridge *);
-void vme_unregister_bridge (struct vme_bridge *);
+int vme_register_bridge(struct vme_bridge *);
+void vme_unregister_bridge(struct vme_bridge *);
 
 #endif /* _VME_BRIDGE_H_ */
-
-#if 0
-/*
- *  VMEbus GET INFO Arg Structure
- */
-struct vmeInfoCfg {
-	int vmeSlotNum;		/*  VME slot number of interest */
-	int boardResponded;	/* Board responded */
-	char sysConFlag;	/*  System controller flag */
-	int vmeControllerID;	/*  Vendor/device ID of VME bridge */
-	int vmeControllerRev;	/*  Revision of VME bridge */
-	char osName[8];		/*  Name of OS e.g. "Linux" */
-	int vmeSharedDataValid;	/*  Validity of data struct */
-	int vmeDriverRev;	/*  Revision of VME driver */
-	unsigned int vmeAddrHi[8];	/* Address on VME bus */
-	unsigned int vmeAddrLo[8];	/* Address on VME bus */
-	unsigned int vmeSize[8];	/* Size on VME bus */
-	unsigned int vmeAm[8];	/* Address modifier on VME bus */
-	int reserved;		/* For future use */
-};
-typedef struct vmeInfoCfg vmeInfoCfg_t;
-
-/*
- *  VMEbus Requester Arg Structure
- */
-struct vmeRequesterCfg {
-	int requestLevel;	/*  Requester Bus Request Level */
-	char fairMode;		/*  Requester Fairness Mode Indicator */
-	int releaseMode;	/*  Requester Bus Release Mode */
-	int timeonTimeoutTimer;	/*  Master Time-on Time-out Timer */
-	int timeoffTimeoutTimer;	/*  Master Time-off Time-out Timer */
-	int reserved;		/* For future use */
-};
-typedef struct vmeRequesterCfg vmeRequesterCfg_t;
-
-/*
- *  VMEbus Arbiter Arg Structure
- */
-struct vmeArbiterCfg {
-	vme_arbitration_t arbiterMode;	/*  Arbitration Scheduling Algorithm */
-	char arbiterTimeoutFlag;	/*  Arbiter Time-out Timer Indicator */
-	int globalTimeoutTimer;	/*  VMEbus Global Time-out Timer */
-	char noEarlyReleaseFlag;	/*  No Early Release on BBUSY */
-	int reserved;		/* For future use */
-};
-typedef struct vmeArbiterCfg vmeArbiterCfg_t;
-
-
-/*
- *  VMEbus RMW Configuration Data
- */
-struct vmeRmwCfg {
-	unsigned int targetAddrU;	/*  VME Address (Upper) to trigger RMW cycle */
-	unsigned int targetAddr;	/*  VME Address (Lower) to trigger RMW cycle */
-	vme_address_t addrSpace;	/*  VME Address Space */
-	int enableMask;		/*  Bit mask defining the bits of interest */
-	int compareData;	/*  Data to be compared with the data read */
-	int swapData;		/*  Data written to the VMEbus on success */
-	int maxAttempts;	/*  Maximum times to try */
-	int numAttempts;	/*  Number of attempts before success */
-	int reserved;		/* For future use */
-
-};
-typedef struct vmeRmwCfg vmeRmwCfg_t;
-
-/*
- *  VMEbus Location Monitor Arg Structure
- */
-struct vmeLmCfg {
-	unsigned int addrU;	/*  Location Monitor Address upper */
-	unsigned int addr;	/*  Location Monitor Address lower */
-	vme_address_t addrSpace;	/*  Address Space */
-	int userAccessType;	/*  User/Supervisor Access Type */
-	int dataAccessType;	/*  Data/Program Access Type */
-	int lmWait;		/* Time to wait for access */
-	int lmEvents;		/* Lm event mask */
-	int reserved;		/* For future use */
-};
-typedef struct vmeLmCfg vmeLmCfg_t;
-#endif
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
index db78614..bf4fd49 100644
--- a/drivers/staging/vt6655/card.c
+++ b/drivers/staging/vt6655/card.c
@@ -2788,16 +2788,18 @@
 
      //Determines the highest basic rate.
      for (ii = RATE_54M; ii >= RATE_6M; ii --) {
-         if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) )
+         if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) ) {
              byTopOFDM = ii;
              break;
+         }
      }
      pDevice->byTopOFDMBasicRate = byTopOFDM;
 
      for (ii = RATE_11M;; ii --) {
-         if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) )
+         if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) ) {
              byTopCCK = ii;
              break;
+         }
          if (ii == RATE_1M)
             break;
      }
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 0dadb76..1d64365 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -1105,10 +1105,7 @@
     struct net_device* dev=pDevice->dev;
 
     DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: %s\n",dev->name, get_chip_name(pDevice->chip_id));
-    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
-        dev->name,
-        dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2],
-        dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]);
+    DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%pM", dev->name, dev->dev_addr);
 #ifdef IO_MAP
     DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx  ",(ULONG) pDevice->ioaddr);
     DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IRQ=%d \n", pDevice->dev->irq);
diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c
index 108830f..78b4983 100644
--- a/drivers/staging/vt6655/iwctl.c
+++ b/drivers/staging/vt6655/iwctl.c
@@ -1472,7 +1472,7 @@
 		if ( index < 4 ) {
 		    pDevice->byKeyIndex = index;
 		}
-		else if(!wrq->flags & IW_ENCODE_MODE) {
+		else if(!(wrq->flags & IW_ENCODE_MODE)) {
 				rc = -EINVAL;
 				return rc;
 	    }
diff --git a/drivers/staging/winbond/core.h b/drivers/staging/winbond/core.h
index 7d4bd5e..0a2060b 100644
--- a/drivers/staging/winbond/core.h
+++ b/drivers/staging/winbond/core.h
@@ -14,7 +14,7 @@
 struct wbsoft_priv {
 	u32 adapterIndex;	// 20060703.4 Add for using padapterContext global adapter point
 
-	WB_LOCALDESCRIPT sLocalPara;	// Myself connected parameters
+	struct wb_local_para sLocalPara;	// Myself connected parameters
 
 	MLME_FRAME sMlmeFrame;	// connect to peerSTA parameters
 
diff --git a/drivers/staging/winbond/localpara.h b/drivers/staging/winbond/localpara.h
index 5626a76..fcf6a044 100644
--- a/drivers/staging/winbond/localpara.h
+++ b/drivers/staging/winbond/localpara.h
@@ -110,33 +110,20 @@
 // 20061108 WPS IE buffer
 #define MAX_IE_APPEND_SIZE					256 + 4 // Due to [E id][Length][OUI][Data] may 257 bytes
 
-typedef struct _EVENTLOG
-{
-	u16		Count;			//Total count from start
-	u16		index;			//Buffer index, 0 ~ 63
-	u32		EventValue[64];	//BYTE 3~2 : count, BYTE 1 : Event, BYTE 0 : reason
-} Event_Log, *pEvent_Log;
-
-typedef struct _ChanInfo
+struct chan_info
 {
 	u8		band;
 	u8		ChanNo;
-} ChanInfo, *pChanInfo;
+};
 
-typedef struct _CHAN_LIST
-{
-	u16				Count;
-	ChanInfo		Channel[50]; // 100B
-} CHAN_LIST, *psCHAN_LIST;
-
-typedef struct _RadioOff
+struct radio_off
 {
 	u8			boHwRadioOff;
 	u8			boSwRadioOff;
-} RadioOff, *psRadioOff;
+};
 
 //===========================================================================
-typedef struct LOCAL_PARA
+struct wb_local_para
 {
 	u8			PermanentAddress[ MAC_ADDR_LENGTH + 2 ]; 	// read from EPROM, manufacture set for each NetCard
     u8    		ThisMacAddress[ MAC_ADDR_LENGTH + 2 ];			// the driver will use actually.
@@ -186,7 +173,7 @@
     u16			ListenInterval;     	// The listen interval when SME invoking MLME_
             	                    	// (Re)Associate_Request().
 
-	RadioOff		RadioOffStatus;
+	struct radio_off		RadioOffStatus;
 	u8			Reserved0[2];
 
 	u8			boMsRadioOff;			// Ndis demands to be true when set Disassoc. OID and be false when set SSID OID.
@@ -196,7 +183,7 @@
 	u8			RoamStatus;
 	u8			reserved7[3];
 
-	ChanInfo	CurrentChan;			//Current channel no. and channel band. It may be changed by scanning.
+	struct chan_info	CurrentChan;			//Current channel no. and channel band. It may be changed by scanning.
 	u8			boHandover;				// Roaming, Hnadover to other AP.
 	u8			boCCAbusy;
 
@@ -253,19 +240,16 @@
     u32	   		_dot11WEPUndecryptableCount;
     u32	   		_dot11FrameDuplicateCount;
 
-	ChanInfo	IbssChanSetting;	// 2B. Start IBSS Channel setting by registry or WWU.
+	struct chan_info	IbssChanSetting;	// 2B. Start IBSS Channel setting by registry or WWU.
 	u8		reserved_5[2];		//It may not be used after considering RF type,
 									//region and modulation type.
 
-	CHAN_LIST	sSupportChanList;	// 86B. It will be obtained according to RF type and region
 	u8		reserved_6[2];		//two variables are for wep key error detection added by ws 02/02/04
 
     u32	      bWepKeyError;
     u32         bToSelfPacketReceived;
     u32         WepKeyDetectTimerCount;
 
-	Event_Log	EventLog;
-
 	u16		SignalLostTh;
 	u16		SignalRoamTh;
 
@@ -274,6 +258,6 @@
 	u16		IE_Append_size;
 	u16		reserved_7;
 
-} WB_LOCALDESCRIPT, *PWB_LOCALDESCRIPT;
+};
 
 #endif
diff --git a/drivers/staging/winbond/mds_f.h b/drivers/staging/winbond/mds_f.h
index ab1ea53..e09dd4b8 100644
--- a/drivers/staging/winbond/mds_f.h
+++ b/drivers/staging/winbond/mds_f.h
@@ -11,9 +11,6 @@
 void Mds_MpduProcess(  struct wbsoft_priv *adapter,  struct wb35_descriptor *pRxDes );
 extern void DataDmp(u8 *pdata, u32 len, u32 offset);
 
-// For Asynchronous indicating. The routine collocates with USB.
-void Mds_MsduProcess(  struct wbsoft_priv *adapter,  PRXLAYER1 pRxLayer1,  u8 SlotIndex);
-
 // For data frame sending 20060802
 u16 MDS_GetPacketSize(  struct wbsoft_priv *adapter );
 void MDS_GetNextPacket(  struct wbsoft_priv *adapter,  struct wb35_descriptor *pDes );
diff --git a/drivers/staging/winbond/mds_s.h b/drivers/staging/winbond/mds_s.h
index e8e13bd..217ff08 100644
--- a/drivers/staging/winbond/mds_s.h
+++ b/drivers/staging/winbond/mds_s.h
@@ -133,32 +133,4 @@
 
 };
 
-//
-// Reveive Layer 1 Format.
-//----------------------------
-typedef struct _RXLAYER1
-{
-    u16  SequenceNumber;     // The sequence number of the last received packet.
-	u16	BufferTotalSize;
-
-	u32	InUsed;
-    u32   DecryptionMethod;   // The desired defragment number of the next incoming packet.
-
-	u8	DeFragmentNumber;
-	u8	FrameType;
-    u8	TypeEncapsulated;
-	u8	BufferNumber;
-
-	u32	FirstFrameArrivedTime;
-
-	u8		LastFrameType; // 20061004 for fix intel 3945 's bug
-	u8		RESERVED[3];  //@@ anson
-
-	/////////////////////////////////////////////////////////////////////////////////////////////
-	// For brand-new Rx system
-	u8	ReservedBuffer[ 2400 ];//If Buffer ID is reserved one, it must copy the data into this area
-	u8	*ReservedBufferPoint;// Point to the next availabe address of reserved buffer
-
-}RXLAYER1, * PRXLAYER1;
-
 #endif
diff --git a/drivers/staging/winbond/mlme_s.h b/drivers/staging/winbond/mlme_s.h
index ea12684..1217a1c 100644
--- a/drivers/staging/winbond/mlme_s.h
+++ b/drivers/staging/winbond/mlme_s.h
@@ -165,14 +165,6 @@
 
 } MLME_AUTHREQ_PARA, *psMLME_AUTHREQ_PARA;
 
-struct _Reason_Code {
-
-	u8	peerMACaddr[MAC_ADDR_LENGTH];
-	u16	wReasonCode;
-};
-typedef struct _Reason_Code MLME_DEAUTHREQ_PARA, *psMLME_DEAUTHREQ_PARA;
-typedef struct _Reason_Code MLME_DISASSOCREQ_PARA, *psMLME_DISASSOCREQ_PARA;
-
 typedef struct _ASSOCREQ {
   u8       PeerSTAAddr[MAC_ADDR_LENGTH];
   u16       CapabilityInfo;
diff --git a/drivers/staging/winbond/mto.h b/drivers/staging/winbond/mto.h
index 4fe24b0..fb4781d 100644
--- a/drivers/staging/winbond/mto.h
+++ b/drivers/staging/winbond/mto.h
@@ -141,11 +141,6 @@
 #define MTO_DATA_RATE()          MTO_Data_Rate_Tbl[MTO_RATE_LEVEL()]
 #define MTO_FRAG_TH()            MTO_Frag_Th_Tbl[MTO_FRAG_TH_LEVEL()]
 
-typedef struct {
-	u8 tx_rate;
-	u8 tx_retry_rate;
-} TXRETRY_REC;
-
 extern void MTO_Init(struct wbsoft_priv *);
 extern void MTO_PeriodicTimerExpired(struct wbsoft_priv *);
 extern void MTO_SetDTORateRange(struct wbsoft_priv *, u8 *, u8);
diff --git a/drivers/staging/winbond/reg.c b/drivers/staging/winbond/reg.c
index d915cbd..5f5048a 100644
--- a/drivers/staging/winbond/reg.c
+++ b/drivers/staging/winbond/reg.c
@@ -1823,12 +1823,12 @@
 		reg->SQ3_filter[i] = 0x2f; // half of Bit 0 ~ 6
 }
 
-void set_tx_power_per_channel_max2829(  struct hw_data * pHwData,  ChanInfo Channel)
+void set_tx_power_per_channel_max2829(  struct hw_data * pHwData,  struct chan_info Channel)
 {
 	RFSynthesizer_SetPowerIndex( pHwData, 100 ); // 20060620.1 Modify
 }
 
-void set_tx_power_per_channel_al2230(  struct hw_data * pHwData,  ChanInfo Channel )
+void set_tx_power_per_channel_al2230(  struct hw_data * pHwData,  struct chan_info Channel )
 {
 	u8	index = 100;
 
@@ -1838,7 +1838,7 @@
 	RFSynthesizer_SetPowerIndex( pHwData, index );
 }
 
-void set_tx_power_per_channel_al7230(  struct hw_data * pHwData,  ChanInfo Channel)
+void set_tx_power_per_channel_al7230(  struct hw_data * pHwData,  struct chan_info Channel)
 {
 	u8	i, index = 100;
 
@@ -1868,7 +1868,7 @@
 	RFSynthesizer_SetPowerIndex( pHwData, index );
 }
 
-void set_tx_power_per_channel_wb242(  struct hw_data * pHwData,  ChanInfo Channel)
+void set_tx_power_per_channel_wb242(  struct hw_data * pHwData,  struct chan_info Channel)
 {
 	u8	index = 100;
 
@@ -1901,7 +1901,7 @@
 //   None.
 //=============================================================================================================
 void
-RFSynthesizer_SwitchingChannel(  struct hw_data * pHwData,  ChanInfo Channel )
+RFSynthesizer_SwitchingChannel(  struct hw_data * pHwData,  struct chan_info Channel )
 {
 	struct wb35_reg *reg = &pHwData->reg;
 	u32	pltmp[16]; // The 16 is the maximum capability of hardware
diff --git a/drivers/staging/winbond/scan_s.h b/drivers/staging/winbond/scan_s.h
index 775bb81..209717f5 100644
--- a/drivers/staging/winbond/scan_s.h
+++ b/drivers/staging/winbond/scan_s.h
@@ -35,7 +35,6 @@
 {
 	u32				ScanType;			//passive/active scan
 
-	CHAN_LIST		sChannelList;	// 86B
 	u8			reserved_1[2];
 
 	struct SSID_Element	sSSID; // 34B. scan only for this SSID
diff --git a/drivers/staging/winbond/sme_api.h b/drivers/staging/winbond/sme_api.h
index 5498783..b589829 100644
--- a/drivers/staging/winbond/sme_api.h
+++ b/drivers/staging/winbond/sme_api.h
@@ -193,8 +193,6 @@
 s8 sme_get_cwmax_value(void *pcore_data, u16 *cwmax);
 s8 sme_get_ms_radio_mode(void *pcore_data, u8 * pMsRadioOff);
 s8 sme_set_ms_radio_mode(void *pcore_data, u8 boMsRadioOff);
-s8 sme_get_radio_mode(void *pcore_data, psRadioOff pRadioOffData);
-s8 sme_set_radio_mode(void *pcore_data, RadioOff RadioOffData);
 
 void sme_get_tx_power_level(void *pcore_data, u32 *TxPower);
 u8 sme_set_tx_power_level(void *pcore_data, u32 TxPower);
@@ -203,7 +201,7 @@
 u8 sme_set_rx_antenna(void *pcore_data, u32 RxAntenna);
 void sme_get_tx_antenna(void *pcore_data, u32 *TxAntenna);
 s8 sme_set_tx_antenna(void *pcore_data, u32 TxAntenna);
-s8 sme_set_IBSS_chan(void *pcore_data, ChanInfo chan);
+s8 sme_set_IBSS_chan(void *pcore_data, struct chan_info chan);
 
 //20061108 WPS
 s8 sme_set_IE_append(void *pcore_data, u8 *buffer, u16 buf_len);
diff --git a/drivers/staging/winbond/wb35reg_f.h b/drivers/staging/winbond/wb35reg_f.h
index 30f5b5a..d352bce 100644
--- a/drivers/staging/winbond/wb35reg_f.h
+++ b/drivers/staging/winbond/wb35reg_f.h
@@ -14,7 +14,7 @@
 void Mxx_initial(  struct hw_data * pHwData );
 void RFSynthesizer_initial(  struct hw_data * pHwData );
 //void RFSynthesizer_SwitchingChannel(  struct hw_data * pHwData,  s8 Channel );
-void RFSynthesizer_SwitchingChannel(  struct hw_data * pHwData,  ChanInfo Channel );
+void RFSynthesizer_SwitchingChannel(  struct hw_data * pHwData,  struct chan_info Channel );
 void BBProcessor_initial(  struct hw_data * pHwData );
 void BBProcessor_RateChanging(  struct hw_data * pHwData,  u8 rate ); // 20060613.1
 //void RF_RateChanging(  struct hw_data * pHwData,  u8 rate ); // 20060626.5.c Add
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index 067082a..3482eec 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -23,7 +23,7 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.1");
 
-static struct usb_device_id wb35_table[] __devinitdata = {
+static const struct usb_device_id wb35_table[] __devinitconst = {
 	{ USB_DEVICE(0x0416, 0x0035) },
 	{ USB_DEVICE(0x18E8, 0x6201) },
 	{ USB_DEVICE(0x18E8, 0x6206) },
@@ -65,17 +65,17 @@
 }
 
 static int wbsoft_add_interface(struct ieee80211_hw *dev,
-				struct ieee80211_if_init_conf *conf)
+				struct ieee80211_vif *vif)
 {
 	struct wbsoft_priv *priv = dev->priv;
 
-	hal_set_beacon_period(&priv->sHwData, conf->vif->bss_conf.beacon_int);
+	hal_set_beacon_period(&priv->sHwData, vif->bss_conf.beacon_int);
 
 	return 0;
 }
 
 static void wbsoft_remove_interface(struct ieee80211_hw *dev,
-				    struct ieee80211_if_init_conf *conf)
+				    struct ieee80211_vif *vif)
 {
 	printk("wbsoft_remove interface called\n");
 }
@@ -92,13 +92,6 @@
 	return 0;
 }
 
-static int wbsoft_get_tx_stats(struct ieee80211_hw *hw,
-			       struct ieee80211_tx_queue_stats *stats)
-{
-	printk(KERN_INFO "%s called\n", __func__);
-	return 0;
-}
-
 static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
 				    struct dev_addr_list *mc_list)
 {
@@ -161,7 +154,7 @@
 }
 
 static void
-hal_set_current_channel_ex(struct hw_data *pHwData, ChanInfo channel)
+hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
 {
 	struct wb35_reg *reg = &pHwData->reg;
 
@@ -180,10 +173,10 @@
 	reg->M28_MacControl &= ~0xff;	// Clean channel information field
 	reg->M28_MacControl |= channel.ChanNo;
 	Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
-				       (s8 *) & channel, sizeof(ChanInfo));
+				       (s8 *) & channel, sizeof(struct chan_info));
 }
 
-static void hal_set_current_channel(struct hw_data *pHwData, ChanInfo channel)
+static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
 {
 	hal_set_current_channel_ex(pHwData, channel);
 }
@@ -253,7 +246,7 @@
 static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
 {
 	struct wbsoft_priv *priv = dev->priv;
-	ChanInfo ch;
+	struct chan_info ch;
 
 	printk("wbsoft_config called\n");
 
@@ -287,7 +280,6 @@
 	.prepare_multicast	= wbsoft_prepare_multicast,
 	.configure_filter	= wbsoft_configure_filter,
 	.get_stats		= wbsoft_get_stats,
-	.get_tx_stats		= wbsoft_get_tx_stats,
 	.get_tsf		= wbsoft_get_tsf,
 };
 
diff --git a/drivers/staging/wlags49_h2/wl_main.c b/drivers/staging/wlags49_h2/wl_main.c
index 16764a0..cf0c384 100644
--- a/drivers/staging/wlags49_h2/wl_main.c
+++ b/drivers/staging/wlags49_h2/wl_main.c
@@ -3792,7 +3792,7 @@
 	}
 	if  (count > 0 ) {
 		proc_number[count] = 0;
-		nr = wl_atoi( proc_number );
+		nr = simple_strtoul(proc_number , NULL, 0);
  		*(unsigned int *)data = nr;
 		if ( nr & 0x8000 ) {	//;?kludgy but it is unclear to me were else to place this
 #if DBG
diff --git a/drivers/staging/wlags49_h2/wl_netdev.c b/drivers/staging/wlags49_h2/wl_netdev.c
index c33e225..fa082d9 100644
--- a/drivers/staging/wlags49_h2/wl_netdev.c
+++ b/drivers/staging/wlags49_h2/wl_netdev.c
@@ -360,7 +360,7 @@
     wl_lock( lp, &flags );
 
     if( status != HCF_SUCCESS ) {
-	// Unsuccesfull, try reset of the card to recover
+	// Unsuccessful, try reset of the card to recover
 	status = wl_reset( dev );
     }
 
diff --git a/drivers/staging/wlags49_h2/wl_pci.c b/drivers/staging/wlags49_h2/wl_pci.c
index a3db111..01e4bec 100644
--- a/drivers/staging/wlags49_h2/wl_pci.c
+++ b/drivers/staging/wlags49_h2/wl_pci.c
@@ -81,7 +81,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 
diff --git a/drivers/staging/wlags49_h2/wl_profile.c b/drivers/staging/wlags49_h2/wl_profile.c
index 715f027..1e0c75f 100644
--- a/drivers/staging/wlags49_h2/wl_profile.c
+++ b/drivers/staging/wlags49_h2/wl_profile.c
@@ -383,15 +383,15 @@
 				DbgInfo->DebugFlag |= DBG_DEFAULTS;
 			}
 		} else {
-			DbgInfo->DebugFlag = wl_atoi( value ); //;?DebugFlag;
+			DbgInfo->DebugFlag = simple_strtoul(value, NULL, 0); //;?DebugFlag;
 		}
-		DbgInfo->DebugFlag = wl_atoi( value ); //;?Delete ASAP
+		DbgInfo->DebugFlag = simple_strtoul(value, NULL, 0); //;?Delete ASAP
 	}
 #endif /* DBG */
 	if ( strcmp( key, PARM_NAME_AUTH_KEY_MGMT_SUITE ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_AUTH_KEY_MGMT_SUITE, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_AUTH_KEY_MGMT_SUITE ) || ( value_convert <= PARM_MAX_AUTH_KEY_MGMT_SUITE )) {
 			lp->AuthKeyMgmtSuite = value_convert;
 		} else {
@@ -401,7 +401,7 @@
 	else if ( strcmp( key, PARM_NAME_BRSC_2GHZ ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_BRSC_2GHZ, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_BRSC ) || ( value_convert <= PARM_MAX_BRSC )) {
 			lp->brsc[0] = value_convert;
 		} else {
@@ -411,7 +411,7 @@
 	else if ( strcmp( key, PARM_NAME_BRSC_5GHZ ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_BRSC_5GHZ, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_BRSC ) || ( value_convert <= PARM_MAX_BRSC )) {
 			lp->brsc[1] = value_convert;
 		} else {
@@ -448,7 +448,7 @@
 	else if ( strcmp( key, PARM_NAME_ENABLE_ENCRYPTION ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_ENABLE_ENCRYPTION, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_ENABLE_ENCRYPTION ) && ( value_convert <= PARM_MAX_ENABLE_ENCRYPTION )) {
 			lp->EnableEncryption = value_convert;
 		} else {
@@ -529,7 +529,7 @@
 	else if ( strcmp( key, PARM_NAME_MULTICAST_RATE ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_MULTICAST_RATE, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 
 		if (( value_convert >= PARM_MIN_MULTICAST_RATE ) && ( value_convert <= PARM_MAX_MULTICAST_RATE )) {
 			lp->MulticastRate[0] = value_convert;
@@ -540,7 +540,7 @@
 	else if ( strcmp( key, PARM_NAME_OWN_CHANNEL ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_CHANNEL, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if ( wl_is_a_valid_chan( value_convert )) {
 			if ( value_convert > 14 ) {
 				value_convert = value_convert | 0x100;
@@ -567,7 +567,7 @@
 	else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
 			lp->RTSThreshold = value_convert;
 		} else {
@@ -577,7 +577,7 @@
 	else if ( strcmp( key, PARM_NAME_SRSC_2GHZ ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_SRSC_2GHZ, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_SRSC ) || ( value_convert <= PARM_MAX_SRSC )) {
 			lp->srsc[0] = value_convert;
 		} else {
@@ -587,7 +587,7 @@
 	else if ( strcmp( key, PARM_NAME_SRSC_5GHZ ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_SRSC_5GHZ, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_SRSC ) || ( value_convert <= PARM_MAX_SRSC )) {
 			lp->srsc[1] = value_convert;
 		} else {
@@ -597,7 +597,7 @@
 	else if ( strcmp( key, PARM_NAME_SYSTEM_SCALE ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_SYSTEM_SCALE, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_SYSTEM_SCALE ) && ( value_convert <= PARM_MAX_SYSTEM_SCALE )) {
 			lp->DistanceBetweenAPs = value_convert;
 		} else {
@@ -607,9 +607,9 @@
 	else if ( strcmp( key, PARM_NAME_TX_KEY ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_KEY, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_TX_KEY ) && ( value_convert <= PARM_MAX_TX_KEY )) {
-			lp->TransmitKeyID = wl_atoi( value );
+			lp->TransmitKeyID = simple_strtoul(value, NULL, 0);
 		} else {
 			DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_KEY );
 		}
@@ -617,7 +617,7 @@
 	else if ( strcmp( key, PARM_NAME_TX_RATE ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
 			lp->TxRateControl[0] = value_convert;
 		} else {
@@ -627,7 +627,7 @@
 	else if ( strcmp( key, PARM_NAME_TX_POW_LEVEL ) == 0 ) {
 		DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_POW_LEVEL, value );
 
-		value_convert = wl_atoi( value );
+		value_convert = simple_strtoul(value, NULL, 0);
 		if (( value_convert >= PARM_MIN_TX_POW_LEVEL ) || ( value_convert <= PARM_MAX_TX_POW_LEVEL )) {
 			lp->txPowLevel = value_convert;
 		} else {
@@ -645,7 +645,7 @@
 		if ( strcmp( key, PARM_NAME_PORT_TYPE ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_PORT_TYPE, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert == PARM_MIN_PORT_TYPE ) || ( value_convert == PARM_MAX_PORT_TYPE )) {
 				lp->PortType = value_convert;
 			} else {
@@ -654,7 +654,7 @@
 		}
 		else if ( strcmp( key, PARM_NAME_PM_ENABLED ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_PM_ENABLED, value );
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 	/* ;? how about wl_main.c containing
 	 * VALID_PARAM( PARM_PM_ENABLED <= WVLAN_PM_STATE_STANDARD ||
 	 *					 ( PARM_PM_ENABLED & 0x7FFF ) <= WVLAN_PM_STATE_STANDARD );
@@ -677,7 +677,7 @@
 		else if ( strcmp( key, PARM_NAME_MAX_SLEEP ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_MAX_SLEEP, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= 0 ) && ( value_convert <= 65535 )) {
 				lp->MaxSleepDuration = value_convert;
 			} else {
@@ -696,7 +696,7 @@
 		else if ( strcmp( key, PARM_NAME_AUTHENTICATION ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_AUTHENTICATION, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_AUTHENTICATION ) && ( value_convert <= PARM_MAX_AUTHENTICATION )) {
 				lp->authentication = value_convert;
 			} else {
@@ -706,7 +706,7 @@
 		else if ( strcmp( key, PARM_NAME_OWN_ATIM_WINDOW ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_ATIM_WINDOW, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_OWN_ATIM_WINDOW ) && ( value_convert <= PARM_MAX_OWN_ATIM_WINDOW )) {
 				lp->atimWindow = value_convert;
 			} else {
@@ -716,7 +716,7 @@
 		else if ( strcmp( key, PARM_NAME_PM_HOLDOVER_DURATION ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_PM_HOLDOVER_DURATION, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_PM_HOLDOVER_DURATION ) && ( value_convert <= PARM_MAX_PM_HOLDOVER_DURATION )) {
 				lp->holdoverDuration = value_convert;
 			} else {
@@ -730,7 +730,7 @@
 		else if ( strcmp( key, PARM_NAME_CONNECTION_CONTROL ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_CONNECTION_CONTROL, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_CONNECTION_CONTROL ) && ( value_convert <= PARM_MAX_CONNECTION_CONTROL )) {
 				lp->connectionControl = value_convert;
 			} else {
@@ -749,7 +749,7 @@
 		if ( strcmp( key, PARM_NAME_OWN_DTIM_PERIOD ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_DTIM_PERIOD, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if ( value_convert >= PARM_MIN_OWN_DTIM_PERIOD ) {
 				lp->DTIMPeriod = value_convert;
 			} else {
@@ -775,7 +775,7 @@
 		else if ( strcmp( key, PARM_NAME_OWN_BEACON_INTERVAL ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_BEACON_INTERVAL, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if ( value_convert >= PARM_MIN_OWN_BEACON_INTERVAL ) {
 				lp->ownBeaconInterval = value_convert;
 			} else {
@@ -785,7 +785,7 @@
 		else if ( strcmp( key, PARM_NAME_COEXISTENCE ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_COEXISTENCE, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if ( value_convert >= PARM_MIN_COEXISTENCE ) {
 				lp->coexistence = value_convert;
 			} else {
@@ -797,7 +797,7 @@
 		else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD1 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD1, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
 				lp->wds_port[0].rtsThreshold = value_convert;
 			} else {
@@ -807,7 +807,7 @@
 		else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD2 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD2, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
 				lp->wds_port[1].rtsThreshold = value_convert;
 			} else {
@@ -817,7 +817,7 @@
 		else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD3 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD3, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
 				lp->wds_port[2].rtsThreshold = value_convert;
 			} else {
@@ -827,7 +827,7 @@
 		else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD4 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD4, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
 				lp->wds_port[3].rtsThreshold = value_convert;
 			} else {
@@ -837,7 +837,7 @@
 		else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD5 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD5, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
 				lp->wds_port[4].rtsThreshold = value_convert;
 			} else {
@@ -847,7 +847,7 @@
 		else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD6 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD6, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
 				lp->wds_port[5].rtsThreshold = value_convert;
 			} else {
@@ -857,7 +857,7 @@
 		else if ( strcmp( key, PARM_NAME_TX_RATE1 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE1, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
 				lp->wds_port[0].txRateCntl = value_convert;
 			} else {
@@ -867,7 +867,7 @@
 		else if ( strcmp( key, PARM_NAME_TX_RATE2 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE2, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
 				lp->wds_port[1].txRateCntl = value_convert;
 			} else {
@@ -877,7 +877,7 @@
 		else if ( strcmp( key, PARM_NAME_TX_RATE3 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE3, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
 				lp->wds_port[2].txRateCntl = value_convert;
 			} else {
@@ -887,7 +887,7 @@
 		else if ( strcmp( key, PARM_NAME_TX_RATE4 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE4, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
 				lp->wds_port[3].txRateCntl = value_convert;
 			} else {
@@ -897,7 +897,7 @@
 		else if ( strcmp( key, PARM_NAME_TX_RATE5 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE5, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
 				lp->wds_port[4].txRateCntl = value_convert;
 			} else {
@@ -907,7 +907,7 @@
 		else if ( strcmp( key, PARM_NAME_TX_RATE6 ) == 0 ) {
 			DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE6, value );
 
-			value_convert = wl_atoi( value );
+			value_convert = simple_strtoul(value, NULL, 0);
 			if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
 				lp->wds_port[5].txRateCntl = value_convert;
 			} else {
diff --git a/drivers/staging/wlags49_h2/wl_util.c b/drivers/staging/wlags49_h2/wl_util.c
index ac1e7f3..bbdb997 100644
--- a/drivers/staging/wlags49_h2/wl_util.c
+++ b/drivers/staging/wlags49_h2/wl_util.c
@@ -1536,52 +1536,3 @@
     return ret;
 }
 
-/*******************************************************************************
- *	wl_atoi()
- *******************************************************************************
- *
- *  DESCRIPTION:
- *
- *      Believe it or not, we need our own implementation of atoi in the kernel.
- *
- *  PARAMETERS:
- *
- *      string  - the ASCII string to convert to an integer
- *
- *  RETURNS:
- *
- *      unsigned integer
- *
- ******************************************************************************/
-unsigned int wl_atoi( char *string )
-{
-unsigned int base = 10;				//default to decimal
-unsigned int value = 0;
-unsigned int c;
-int i = strlen( string );
-
-	if ( i > 2 && string[0] == '0' && ( string[1] | ('X'^'x') ) == 'x' ) {
-		base = 16;
-		string +=2;
-	}
-	while ( ( c = *string++ ) != '\0' ) {
-		if ( value > UINT_MAX / base ) {	//test for overrun
-			DBG_FUNC( "wl_atoi" );	//don't overload the log file with good messages
-			DBG_ENTER( DbgInfo );
-			DBG_ERROR( DbgInfo, "string \"%s\", lenght exceeds expectations\n", string );
-			printk( "<1>string \"%s\", lenght exceeds expectations\n", string );
-			DBG_LEAVE( DbgInfo );
-			break;
-		}
-		c -= '0';
-		if ( 0 <= c && c <= 9 ) value = base * value + c;
-		else if ( base == 16 ) {
-			c += '0';
-			c |= 'A'^'a';
-			c = c - 'a'+ 10;
-			if ( 10 <= c && c <= 15 ) value = base * value + c;
-		}
-	}
-	return value;
-} // wl_atoi
-
diff --git a/drivers/staging/wlags49_h2/wl_util.h b/drivers/staging/wlags49_h2/wl_util.h
index 16cd6c5..561e85b 100644
--- a/drivers/staging/wlags49_h2/wl_util.h
+++ b/drivers/staging/wlags49_h2/wl_util.h
@@ -100,6 +100,4 @@
 void wl_process_assoc_status( struct wl_private *lp );
 void wl_process_security_status( struct wl_private *lp );
 
-unsigned int wl_atoi( char *string );
-
 #endif  // __WL_UTIL_H__
diff --git a/drivers/staging/wlan-ng/Kconfig b/drivers/staging/wlan-ng/Kconfig
index f44294b..82fcc16 100644
--- a/drivers/staging/wlan-ng/Kconfig
+++ b/drivers/staging/wlan-ng/Kconfig
@@ -1,6 +1,8 @@
 config PRISM2_USB
 	tristate "Prism2.5/3 USB driver"
-	depends on WLAN && USB && WIRELESS_EXT
+	depends on WLAN && USB
+	select WIRELESS_EXT
+	select WEXT_PRIV
 	default n
 	---help---
 	  This is the wlan-ng prism 2.5/3 USB driver for a wide range of
diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h
index 46cce81..1fa42e0 100644
--- a/drivers/staging/wlan-ng/hfa384x.h
+++ b/drivers/staging/wlan-ng/hfa384x.h
@@ -61,17 +61,17 @@
 #include <linux/if_ether.h>
 
 /*--- Mins & Maxs -----------------------------------*/
-#define		HFA384x_PORTID_MAX		((u16)7)
-#define		HFA384x_NUMPORTS_MAX		((u16)(HFA384x_PORTID_MAX+1))
-#define		HFA384x_PDR_LEN_MAX		((u16)512)	/* in bytes, from EK */
-#define		HFA384x_PDA_RECS_MAX		((u16)200)	/* a guess */
-#define		HFA384x_PDA_LEN_MAX		((u16)1024)	/* in bytes, from EK */
-#define		HFA384x_SCANRESULT_MAX		((u16)31)
-#define		HFA384x_HSCANRESULT_MAX		((u16)31)
-#define		HFA384x_CHINFORESULT_MAX	((u16)16)
-#define		HFA384x_RID_GUESSING_MAXLEN	2048	/* I'm not really sure */
-#define		HFA384x_RIDDATA_MAXLEN		HFA384x_RID_GUESSING_MAXLEN
-#define		HFA384x_USB_RWMEM_MAXLEN	2048
+#define	HFA384x_PORTID_MAX		((u16)7)
+#define	HFA384x_NUMPORTS_MAX		((u16)(HFA384x_PORTID_MAX+1))
+#define	HFA384x_PDR_LEN_MAX		((u16)512) /* in bytes, from EK */
+#define	HFA384x_PDA_RECS_MAX		((u16)200) /* a guess */
+#define	HFA384x_PDA_LEN_MAX		((u16)1024) /* in bytes, from EK*/
+#define	HFA384x_SCANRESULT_MAX		((u16)31)
+#define	HFA384x_HSCANRESULT_MAX		((u16)31)
+#define	HFA384x_CHINFORESULT_MAX	((u16)16)
+#define	HFA384x_RID_GUESSING_MAXLEN	2048	/* I'm not really sure */
+#define	HFA384x_RIDDATA_MAXLEN		HFA384x_RID_GUESSING_MAXLEN
+#define	HFA384x_USB_RWMEM_MAXLEN	2048
 
 /*--- Support Constants -----------------------------*/
 #define		HFA384x_PORTTYPE_IBSS			((u16)0)
@@ -115,8 +115,8 @@
 
 /* Make a 32-bit flat address from AUX format 16-bit page and offset */
 #define		HFA384x_ADDR_AUX_MKFLAT(p, o)	\
-		(((u32)(((u16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) << 7) | \
-		((u32)(((u16)(o))&HFA384x_ADDR_AUX_OFF_MASK))
+		((((u32)(((u16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) << 7) | \
+		((u32)(((u16)(o))&HFA384x_ADDR_AUX_OFF_MASK)))
 
 /* Make CMD format offset and page from a 32-bit flat address */
 #define		HFA384x_ADDR_CMD_MKPAGE(f) \
@@ -135,12 +135,21 @@
 #define		HFA384x_DLSTATE_FLASHENABLED		2
 
 /*--- Register Field Masks --------------------------*/
-#define		HFA384x_CMD_AINFO		((u16)(BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) | BIT(8)))
-#define		HFA384x_CMD_MACPORT		((u16)(BIT(10) | BIT(9) | BIT(8)))
+#define		HFA384x_CMD_AINFO		((u16)(BIT(14) | BIT(13) \
+							| BIT(12) | BIT(11) \
+							| BIT(10) | BIT(9) \
+							| BIT(8)))
+#define		HFA384x_CMD_MACPORT		((u16)(BIT(10) | BIT(9) | \
+							BIT(8)))
 #define		HFA384x_CMD_PROGMODE		((u16)(BIT(9) | BIT(8)))
-#define		HFA384x_CMD_CMDCODE		((u16)(BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)))
+#define		HFA384x_CMD_CMDCODE		((u16)(BIT(5) | BIT(4) | \
+							BIT(3) | BIT(2) | \
+							BIT(1) | BIT(0)))
 
-#define		HFA384x_STATUS_RESULT		((u16)(BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) | BIT(8)))
+#define		HFA384x_STATUS_RESULT		((u16)(BIT(14) | BIT(13) \
+							| BIT(12) | BIT(11) \
+							| BIT(10) | BIT(9) \
+							| BIT(8)))
 
 /*--- Command Code Constants --------------------------*/
 /*--- Controller Commands --------------------------*/
@@ -244,8 +253,10 @@
   This is the length of JUST the DATA part of the RID (does not
   include the len or code fields)
 --------------------------------------------------------------------*/
-#define		HFA384x_RID_DBMCOMMSQUALITY_LEN		((u16)sizeof(hfa384x_dbmcommsquality_t))
-#define		HFA384x_RID_JOINREQUEST_LEN		((u16)sizeof(hfa384x_JoinRequest_data_t))
+#define		HFA384x_RID_DBMCOMMSQUALITY_LEN	 \
+	((u16) sizeof(hfa384x_dbmcommsquality_t))
+#define		HFA384x_RID_JOINREQUEST_LEN \
+	((u16)sizeof(hfa384x_JoinRequest_data_t))
 
 /*--------------------------------------------------------------------
 Information RIDs:  Modem Information
@@ -322,9 +333,11 @@
 
 /*--- Register Test/Get/Set Field macros ------------------------*/
 
-#define		HFA384x_CMD_AINFO_SET(value)		((u16)((u16)(value) << 8))
-#define		HFA384x_CMD_MACPORT_SET(value)		((u16)HFA384x_CMD_AINFO_SET(value))
-#define		HFA384x_CMD_PROGMODE_SET(value)		((u16)HFA384x_CMD_AINFO_SET((u16)value))
+#define		HFA384x_CMD_AINFO_SET(value)	((u16)((u16)(value) << 8))
+#define		HFA384x_CMD_MACPORT_SET(value)	\
+			((u16)HFA384x_CMD_AINFO_SET(value))
+#define		HFA384x_CMD_PROGMODE_SET(value)	\
+			((u16)HFA384x_CMD_AINFO_SET((u16)value))
 #define		HFA384x_CMD_CMDCODE_SET(value)		((u16)(value))
 
 #define		HFA384x_STATUS_RESULT_SET(value)	(((u16)(value)) << 8)
@@ -402,7 +415,7 @@
 /*-- Configuration Record: WPAData       (data portion only) --*/
 typedef struct hfa384x_WPAData {
 	u16 datalen;
-	u8 data[0];		// max 80
+	u8 data[0];		/* max 80 */
 } __attribute__ ((packed)) hfa384x_WPAData_t;
 
 /*--------------------------------------------------------------------
@@ -479,7 +492,8 @@
 #define		HFA384x_TXSTATUS_AGEDERR		((u16)BIT(1))
 #define		HFA384x_TXSTATUS_RETRYERR		((u16)BIT(0))
 /*-- Transmit Control Field --*/
-#define		HFA384x_TX_MACPORT			((u16)(BIT(10) | BIT(9) | BIT(8)))
+#define		HFA384x_TX_MACPORT			((u16)(BIT(10) | \
+							  BIT(9) | BIT(8)))
 #define		HFA384x_TX_STRUCTYPE			((u16)(BIT(4) | BIT(3)))
 #define		HFA384x_TX_TXEX				((u16)BIT(2))
 #define		HFA384x_TX_TXOK				((u16)BIT(1))
@@ -496,7 +510,8 @@
 #define	HFA384x_TX_SET(v, m, s)		((((u16)(v))<<((u16)(s)))&((u16)(m)))
 
 #define	HFA384x_TX_MACPORT_SET(v)	HFA384x_TX_SET(v, HFA384x_TX_MACPORT, 8)
-#define	HFA384x_TX_STRUCTYPE_SET(v)	HFA384x_TX_SET(v, HFA384x_TX_STRUCTYPE, 3)
+#define	HFA384x_TX_STRUCTYPE_SET(v)	HFA384x_TX_SET(v, \
+						HFA384x_TX_STRUCTYPE, 3)
 #define	HFA384x_TX_TXEX_SET(v)		HFA384x_TX_SET(v, HFA384x_TX_TXEX, 2)
 #define	HFA384x_TX_TXOK_SET(v)		HFA384x_TX_SET(v, HFA384x_TX_TXOK, 1)
 /*--------------------------------------------------------------------
@@ -534,13 +549,17 @@
 --------------------------------------------------------------------*/
 
 /*-- Status Fields --*/
-#define		HFA384x_RXSTATUS_MACPORT		((u16)(BIT(10) | BIT(9) | BIT(8)))
+#define		HFA384x_RXSTATUS_MACPORT		((u16)(BIT(10) | \
+								BIT(9) | \
+								BIT(8)))
 #define		HFA384x_RXSTATUS_FCSERR			((u16)BIT(0))
 /*--------------------------------------------------------------------
 Communication Frames: Test/Get/Set Field Values for Receive Frames
 --------------------------------------------------------------------*/
-#define		HFA384x_RXSTATUS_MACPORT_GET(value)	((u16)((((u16)(value)) & HFA384x_RXSTATUS_MACPORT) >> 8))
-#define		HFA384x_RXSTATUS_ISFCSERR(value)	((u16)(((u16)(value)) & HFA384x_RXSTATUS_FCSERR))
+#define		HFA384x_RXSTATUS_MACPORT_GET(value)	((u16)((((u16)(value)) \
+					    & HFA384x_RXSTATUS_MACPORT) >> 8))
+#define		HFA384x_RXSTATUS_ISFCSERR(value)	((u16)(((u16)(value)) \
+						  & HFA384x_RXSTATUS_FCSERR))
 /*--------------------------------------------------------------------
  FRAME STRUCTURES: Information Types and Information Frame Structures
 ----------------------------------------------------------------------
@@ -1133,7 +1152,7 @@
 
 typedef void (*ctlx_cmdcb_t) (struct hfa384x *, const struct hfa384x_usbctlx *);
 
-typedef void (*ctlx_usercb_t) (struct hfa384x * hw,
+typedef void (*ctlx_usercb_t) (struct hfa384x *hw,
 			       void *ctlxresult, void *usercb_data);
 
 typedef struct hfa384x_usbctlx {
@@ -1174,14 +1193,14 @@
 } hfa384x_metacmd_t;
 
 #define	MAX_GRP_ADDR		32
-#define WLAN_COMMENT_MAX	80	/* Max. length of user comment string. */
+#define WLAN_COMMENT_MAX	80  /* Max. length of user comment string. */
 
-#define WLAN_AUTH_MAX           60	/* Max. # of authenticated stations. */
-#define WLAN_ACCESS_MAX		60	/* Max. # of stations in an access list. */
-#define WLAN_ACCESS_NONE	0	/* No stations may be authenticated. */
-#define WLAN_ACCESS_ALL		1	/* All stations may be authenticated. */
-#define WLAN_ACCESS_ALLOW	2	/* Authenticate only "allowed" stations. */
-#define WLAN_ACCESS_DENY	3	/* Do not authenticate "denied" stations. */
+#define WLAN_AUTH_MAX           60  /* Max. # of authenticated stations. */
+#define WLAN_ACCESS_MAX		60  /* Max. # of stations in an access list. */
+#define WLAN_ACCESS_NONE	0   /* No stations may be authenticated. */
+#define WLAN_ACCESS_ALL		1   /* All stations may be authenticated. */
+#define WLAN_ACCESS_ALLOW	2   /* Authenticate only "allowed" stations. */
+#define WLAN_ACCESS_DENY	3   /* Do not authenticate "denied" stations. */
 
 /* XXX These are going away ASAP */
 typedef struct prism2sta_authlist {
@@ -1294,10 +1313,23 @@
 	hfa384x_caplevel_t cap_sup_ap;
 
 	/* Actor compatibility ranges */
-	hfa384x_caplevel_t cap_act_pri_cfi;	/* pri f/w to controller interface */
-	hfa384x_caplevel_t cap_act_sta_cfi;	/* sta f/w to controller interface */
+	hfa384x_caplevel_t cap_act_pri_cfi;	/*
+						 * pri f/w to controller
+						 * interface
+						 */
+
+	hfa384x_caplevel_t cap_act_sta_cfi;	/*
+						 * sta f/w to controller
+						 * interface
+						 */
+
 	hfa384x_caplevel_t cap_act_sta_mfi;	/* sta f/w to modem interface */
-	hfa384x_caplevel_t cap_act_ap_cfi;	/* ap f/w to controller interface */
+
+	hfa384x_caplevel_t cap_act_ap_cfi;	/*
+						 * ap f/w to controller
+						 * interface
+						 */
+
 	hfa384x_caplevel_t cap_act_ap_mfi;	/* ap f/w to modem interface */
 
 	u32 psusercount;	/* Power save user count. */
@@ -1320,25 +1352,25 @@
 
 } hfa384x_t;
 
-void hfa384x_create(hfa384x_t * hw, struct usb_device *usb);
-void hfa384x_destroy(hfa384x_t * hw);
+void hfa384x_create(hfa384x_t *hw, struct usb_device *usb);
+void hfa384x_destroy(hfa384x_t *hw);
 
 int
-hfa384x_corereset(hfa384x_t * hw, int holdtime, int settletime, int genesis);
-int hfa384x_drvr_commtallies(hfa384x_t * hw);
-int hfa384x_drvr_disable(hfa384x_t * hw, u16 macport);
-int hfa384x_drvr_enable(hfa384x_t * hw, u16 macport);
-int hfa384x_drvr_flashdl_enable(hfa384x_t * hw);
-int hfa384x_drvr_flashdl_disable(hfa384x_t * hw);
-int hfa384x_drvr_flashdl_write(hfa384x_t * hw, u32 daddr, void *buf, u32 len);
-int hfa384x_drvr_getconfig(hfa384x_t * hw, u16 rid, void *buf, u16 len);
-int hfa384x_drvr_ramdl_enable(hfa384x_t * hw, u32 exeaddr);
-int hfa384x_drvr_ramdl_disable(hfa384x_t * hw);
-int hfa384x_drvr_ramdl_write(hfa384x_t * hw, u32 daddr, void *buf, u32 len);
-int hfa384x_drvr_readpda(hfa384x_t * hw, void *buf, unsigned int len);
-int hfa384x_drvr_setconfig(hfa384x_t * hw, u16 rid, void *buf, u16 len);
+hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis);
+int hfa384x_drvr_commtallies(hfa384x_t *hw);
+int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport);
+int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport);
+int hfa384x_drvr_flashdl_enable(hfa384x_t *hw);
+int hfa384x_drvr_flashdl_disable(hfa384x_t *hw);
+int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len);
+int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len);
+int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr);
+int hfa384x_drvr_ramdl_disable(hfa384x_t *hw);
+int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len);
+int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len);
+int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len);
 
-static inline int hfa384x_drvr_getconfig16(hfa384x_t * hw, u16 rid, void *val)
+static inline int hfa384x_drvr_getconfig16(hfa384x_t *hw, u16 rid, void *val)
 {
 	int result = 0;
 	result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(u16));
@@ -1347,46 +1379,46 @@
 	return result;
 }
 
-static inline int hfa384x_drvr_setconfig16(hfa384x_t * hw, u16 rid, u16 val)
+static inline int hfa384x_drvr_setconfig16(hfa384x_t *hw, u16 rid, u16 val)
 {
 	u16 value = cpu_to_le16(val);
 	return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value));
 }
 
 int
-hfa384x_drvr_getconfig_async(hfa384x_t * hw,
+hfa384x_drvr_getconfig_async(hfa384x_t *hw,
 			     u16 rid, ctlx_usercb_t usercb, void *usercb_data);
 
 int
-hfa384x_drvr_setconfig_async(hfa384x_t * hw,
+hfa384x_drvr_setconfig_async(hfa384x_t *hw,
 			     u16 rid,
 			     void *buf,
 			     u16 len, ctlx_usercb_t usercb, void *usercb_data);
 
 static inline int
-hfa384x_drvr_setconfig16_async(hfa384x_t * hw, u16 rid, u16 val)
+hfa384x_drvr_setconfig16_async(hfa384x_t *hw, u16 rid, u16 val)
 {
 	u16 value = cpu_to_le16(val);
 	return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value),
 					    NULL, NULL);
 }
 
-int hfa384x_drvr_start(hfa384x_t * hw);
-int hfa384x_drvr_stop(hfa384x_t * hw);
+int hfa384x_drvr_start(hfa384x_t *hw);
+int hfa384x_drvr_stop(hfa384x_t *hw);
 int
-hfa384x_drvr_txframe(hfa384x_t * hw, struct sk_buff *skb,
-		     p80211_hdr_t * p80211_hdr, p80211_metawep_t * p80211_wep);
-void hfa384x_tx_timeout(wlandevice_t * wlandev);
+hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb,
+		     p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep);
+void hfa384x_tx_timeout(wlandevice_t *wlandev);
 
-int hfa384x_cmd_initialize(hfa384x_t * hw);
-int hfa384x_cmd_enable(hfa384x_t * hw, u16 macport);
-int hfa384x_cmd_disable(hfa384x_t * hw, u16 macport);
-int hfa384x_cmd_allocate(hfa384x_t * hw, u16 len);
-int hfa384x_cmd_monitor(hfa384x_t * hw, u16 enable);
+int hfa384x_cmd_initialize(hfa384x_t *hw);
+int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport);
+int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport);
+int hfa384x_cmd_allocate(hfa384x_t *hw, u16 len);
+int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable);
 int
-hfa384x_cmd_download(hfa384x_t * hw,
+hfa384x_cmd_download(hfa384x_t *hw,
 		     u16 mode, u16 lowaddr, u16 highaddr, u16 codelen);
 
-#endif /* __KERNEL__ */
+#endif /*__KERNEL__ */
 
-#endif /* _HFA384x_H */
+#endif /*_HFA384x_H */
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index 925678b..5df56f0 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -52,7 +52,7 @@
 * around the register accesses.  The next higher level represents C-callable
 * prism2 API functions that match the Intersil documentation as closely
 * as is reasonable.  The next higher layer implements common sequences
-* of invokations of the API layer (e.g. write to bap, followed by cmd).
+* of invocations of the API layer (e.g. write to bap, followed by cmd).
 *
 * Common sequences:
 * hfa384x_drvr_xxx	Highest level abstractions provided by the
@@ -118,15 +118,15 @@
 #include <linux/wireless.h>
 #include <linux/netdevice.h>
 #include <linux/timer.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <asm/byteorder.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <linux/list.h>
 #include <linux/usb.h>
 #include <linux/byteorder/generic.h>
 
-#define SUBMIT_URB(u,f)  usb_submit_urb(u,f)
+#define SUBMIT_URB(u, f)  usb_submit_urb(u, f)
 
 #include "p80211types.h"
 #include "p80211hdr.h"
@@ -627,7 +627,7 @@
 {
 	hfa384x_usbctlx_t *ctlx;
 
-	ctlx = kmalloc(sizeof(*ctlx), in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
+	ctlx = kmalloc(sizeof(*ctlx), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
 	if (ctlx != NULL) {
 		memset(ctlx, 0, sizeof(*ctlx));
 		init_completion(&ctlx->done);
@@ -675,7 +675,7 @@
 };
 typedef struct usbctlx_cmd_completor usbctlx_cmd_completor_t;
 
-static int usbctlx_cmd_completor_fn(usbctlx_completor_t * head)
+static int usbctlx_cmd_completor_fn(usbctlx_completor_t *head)
 {
 	usbctlx_cmd_completor_t *complete = (usbctlx_cmd_completor_t *) head;
 	return usbctlx_get_status(complete->cmdresp, complete->result);
@@ -1909,18 +1909,19 @@
 		return -EINVAL;
 
 	/* Retrieve the buffer loc&size and timeout */
-	if ((result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER,
-					     &(hw->bufinfo),
-					     sizeof(hw->bufinfo)))) {
+	result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER,
+					&(hw->bufinfo), sizeof(hw->bufinfo));
+	if (result)
 		return result;
-	}
+
 	hw->bufinfo.page = le16_to_cpu(hw->bufinfo.page);
 	hw->bufinfo.offset = le16_to_cpu(hw->bufinfo.offset);
 	hw->bufinfo.len = le16_to_cpu(hw->bufinfo.len);
-	if ((result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME,
-					       &(hw->dltimeout)))) {
+	result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME,
+					  &(hw->dltimeout));
+	if (result)
 		return result;
-	}
+
 	hw->dltimeout = le16_to_cpu(hw->dltimeout);
 
 	pr_debug("flashdl_enable\n");
@@ -3071,9 +3072,9 @@
 				  hfa384x_ctlxout_callback, hw);
 		hw->ctlx_urb.transfer_flags |= USB_QUEUE_BULK;
 
-		/* Now submit the URB and update the CTLX's state
-		 */
-		if ((result = SUBMIT_URB(&hw->ctlx_urb, GFP_ATOMIC)) == 0) {
+		/* Now submit the URB and update the CTLX's state */
+		result = SUBMIT_URB(&hw->ctlx_urb, GFP_ATOMIC);
+		if (result == 0) {
 			/* This CTLX is now running on the active queue */
 			head->state = CTLX_REQ_SUBMITTED;
 
@@ -3599,7 +3600,8 @@
 			 skblen - sizeof(p80211_caphdr_t));
 	}
 
-	if ((skb = dev_alloc_skb(skblen)) == NULL) {
+	skb = dev_alloc_skb(skblen);
+	if (skb == NULL) {
 		printk(KERN_ERR
 		       "alloc_skb failed trying to allocate %d bytes\n",
 		       skblen);
@@ -3642,7 +3644,7 @@
 		/* check for unencrypted stuff if WEP bit set. */
 		if (*(datap - hdrlen + 1) & 0x40)	/* wep set */
 			if ((*(datap) == 0xaa) && (*(datap + 1) == 0xaa))
-				*(datap - hdrlen + 1) &= 0xbf;	// clear wep; it's the 802.2 header!
+				*(datap - hdrlen + 1) &= 0xbf;	/* clear wep; it's the 802.2 header! */
 	}
 
 	if (hw->sniff_fcs) {
@@ -3870,9 +3872,9 @@
 
 delresp:
 	if (delete_resptimer) {
-		if ((timer_ok = del_timer(&hw->resptimer)) != 0) {
+		timer_ok = del_timer(&hw->resptimer);
+		if (timer_ok != 0)
 			hw->resp_timer_done = 1;
-		}
 	}
 
 	spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c
index 5952c67..a1605fb 100644
--- a/drivers/staging/wlan-ng/p80211conv.c
+++ b/drivers/staging/wlan-ng/p80211conv.c
@@ -206,12 +206,11 @@
 		/* XXXX need to pick keynum other than default? */
 
 		p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC);
-
-		if ((foo = wep_encrypt(wlandev, skb->data, p80211_wep->data,
-				       skb->len,
-				       (wlandev->hostwep &
-					HOSTWEP_DEFAULTKEY_MASK),
-				       p80211_wep->iv, p80211_wep->icv))) {
+		foo = wep_encrypt(wlandev, skb->data, p80211_wep->data,
+				  skb->len,
+				  (wlandev->hostwep &HOSTWEP_DEFAULTKEY_MASK),
+				  p80211_wep->iv, p80211_wep->icv);
+		if (foo) {
 			printk(KERN_WARNING
 			       "Host en-WEP failed, dropping frame (%d).\n",
 			       foo);
@@ -323,11 +322,12 @@
 			       skb->len);
 			return 1;
 		}
-		if ((foo = wep_decrypt(wlandev, skb->data + payload_offset + 4,
+		foo = wep_decrypt(wlandev, skb->data + payload_offset + 4,
 				       payload_length - 8, -1,
 				       skb->data + payload_offset,
 				       skb->data + payload_offset +
-				       payload_length - 4))) {
+				       payload_length - 4);
+		if (foo) {
 			/* de-wep failed, drop skb. */
 			pr_debug("Host de-WEP failed, dropping frame (%d).\n",
 				 foo);
diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h
index 0c62df1..6fe163b 100644
--- a/drivers/staging/wlan-ng/p80211conv.h
+++ b/drivers/staging/wlan-ng/p80211conv.h
@@ -153,8 +153,8 @@
 int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv,
 			struct sk_buff *skb);
 int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv,
-			struct sk_buff *skb, p80211_hdr_t * p80211_hdr,
-			p80211_metawep_t * p80211_wep);
+			struct sk_buff *skb, p80211_hdr_t *p80211_hdr,
+			p80211_metawep_t *p80211_wep);
 
 int p80211_stt_findproto(u16 proto);
 
diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h
index da8b6f5..0ccfba1 100644
--- a/drivers/staging/wlan-ng/p80211metadef.h
+++ b/drivers/staging/wlan-ng/p80211metadef.h
@@ -190,9 +190,9 @@
 			(P80211DID_MKSECTION(2) | \
 			P80211DID_MKGROUP(1))
 #define DIDmib_dot11mac_dot11OperationTable_dot11MACAddress \
-                        (P80211DID_MKSECTION(2) | \
-                        P80211DID_MKGROUP(1) | \
-                        P80211DID_MKITEM(1) | 0x18000000)
+			(P80211DID_MKSECTION(2) | \
+			P80211DID_MKGROUP(1) | \
+			P80211DID_MKITEM(1) | 0x18000000)
 #define DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold \
 			(P80211DID_MKSECTION(2) | \
 			P80211DID_MKGROUP(1) | \
@@ -210,18 +210,18 @@
 			P80211DID_MKGROUP(1) | \
 			P80211DID_MKITEM(5) | 0x18000000)
 #define DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime \
-                       (P80211DID_MKSECTION(2) | \
-                       P80211DID_MKGROUP(1) | \
-                       P80211DID_MKITEM(6) | 0x10000000)
+			(P80211DID_MKSECTION(2) | \
+			P80211DID_MKGROUP(1) | \
+			P80211DID_MKITEM(6) | 0x10000000)
 #define DIDmib_cat_dot11phy \
 			P80211DID_MKSECTION(3)
 #define DIDmib_dot11phy_dot11PhyOperationTable \
 			(P80211DID_MKSECTION(3) | \
 			P80211DID_MKGROUP(1))
 #define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel \
-                       (P80211DID_MKSECTION(3) | \
-                       P80211DID_MKGROUP(3) | \
-                       P80211DID_MKITEM(10) | 0x18000000)
+			(P80211DID_MKSECTION(3) | \
+			P80211DID_MKGROUP(3) | \
+			P80211DID_MKITEM(10) | 0x18000000)
 #define DIDmib_dot11phy_dot11PhyDSSSTable \
 			(P80211DID_MKSECTION(3) | \
 			P80211DID_MKGROUP(5))
diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h
index 14cdc86..deb52f5 100644
--- a/drivers/staging/wlan-ng/p80211mgmt.h
+++ b/drivers/staging/wlan-ng/p80211mgmt.h
@@ -100,7 +100,7 @@
 #ifndef _P80211MGMT_H
 #define _P80211MGMT_H
 
-#ifndef  _P80211HDR_H
+#ifndef _P80211HDR_H
 #include "p80211hdr.h"
 #endif
 
@@ -496,25 +496,25 @@
 
 } wlan_fr_deauthen_t;
 
-void wlan_mgmt_encode_beacon(wlan_fr_beacon_t * f);
-void wlan_mgmt_decode_beacon(wlan_fr_beacon_t * f);
-void wlan_mgmt_encode_disassoc(wlan_fr_disassoc_t * f);
-void wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t * f);
-void wlan_mgmt_encode_assocreq(wlan_fr_assocreq_t * f);
-void wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t * f);
-void wlan_mgmt_encode_assocresp(wlan_fr_assocresp_t * f);
-void wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t * f);
-void wlan_mgmt_encode_reassocreq(wlan_fr_reassocreq_t * f);
-void wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t * f);
-void wlan_mgmt_encode_reassocresp(wlan_fr_reassocresp_t * f);
-void wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t * f);
-void wlan_mgmt_encode_probereq(wlan_fr_probereq_t * f);
-void wlan_mgmt_decode_probereq(wlan_fr_probereq_t * f);
-void wlan_mgmt_encode_proberesp(wlan_fr_proberesp_t * f);
-void wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t * f);
-void wlan_mgmt_encode_authen(wlan_fr_authen_t * f);
-void wlan_mgmt_decode_authen(wlan_fr_authen_t * f);
-void wlan_mgmt_encode_deauthen(wlan_fr_deauthen_t * f);
-void wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t * f);
+void wlan_mgmt_encode_beacon(wlan_fr_beacon_t *f);
+void wlan_mgmt_decode_beacon(wlan_fr_beacon_t *f);
+void wlan_mgmt_encode_disassoc(wlan_fr_disassoc_t *f);
+void wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t *f);
+void wlan_mgmt_encode_assocreq(wlan_fr_assocreq_t *f);
+void wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t *f);
+void wlan_mgmt_encode_assocresp(wlan_fr_assocresp_t *f);
+void wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t *f);
+void wlan_mgmt_encode_reassocreq(wlan_fr_reassocreq_t *f);
+void wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t *f);
+void wlan_mgmt_encode_reassocresp(wlan_fr_reassocresp_t *f);
+void wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t *f);
+void wlan_mgmt_encode_probereq(wlan_fr_probereq_t *f);
+void wlan_mgmt_decode_probereq(wlan_fr_probereq_t *f);
+void wlan_mgmt_encode_proberesp(wlan_fr_proberesp_t *f);
+void wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t *f);
+void wlan_mgmt_encode_authen(wlan_fr_authen_t *f);
+void wlan_mgmt_decode_authen(wlan_fr_authen_t *f);
+void wlan_mgmt_encode_deauthen(wlan_fr_deauthen_t *f);
+void wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t *f);
 
 #endif /* _P80211MGMT_H */
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c
index 22424c8..763ab11 100644
--- a/drivers/staging/wlan-ng/p80211netdev.c
+++ b/drivers/staging/wlan-ng/p80211netdev.c
@@ -586,7 +586,8 @@
 	}
 
 	/* Allocate a buf of size req->len */
-	if ((msgbuf = kmalloc(req->len, GFP_KERNEL))) {
+	msgbuf = kmalloc(req->len, GFP_KERNEL);
+	if (msgbuf) {
 		if (copy_from_user(msgbuf, (void __user *)req->data, req->len))
 			result = -EFAULT;
 		else
@@ -646,7 +647,7 @@
 
 	/* Set up some convenience pointers. */
 	mibattr = &dot11req.mibattribute;
-	macaddr = (p80211item_pstr6_t *) & mibattr->data;
+	macaddr = (p80211item_pstr6_t *) &mibattr->data;
 	resultcode = &dot11req.resultcode;
 
 	/* Set up a dot11req_mibset */
@@ -674,7 +675,7 @@
 	resultcode->data = 0;
 
 	/* now fire the request */
-	result = p80211req_dorequest(dev->ml_priv, (u8 *) & dot11req);
+	result = p80211req_dorequest(dev->ml_priv, (u8 *) &dot11req);
 
 	/* If the request wasn't successful, report an error and don't
 	 * change the netdev address
diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h
index 8bd9dfb..3c8c648 100644
--- a/drivers/staging/wlan-ng/p80211netdev.h
+++ b/drivers/staging/wlan-ng/p80211netdev.h
@@ -179,16 +179,16 @@
 	unsigned int ethconv;
 
 	/* device methods (init by MSD, used by p80211 */
-	int (*open) (struct wlandevice * wlandev);
-	int (*close) (struct wlandevice * wlandev);
-	void (*reset) (struct wlandevice * wlandev);
-	int (*txframe) (struct wlandevice * wlandev, struct sk_buff * skb,
-			p80211_hdr_t * p80211_hdr,
-			p80211_metawep_t * p80211_wep);
-	int (*mlmerequest) (struct wlandevice * wlandev, p80211msg_t * msg);
-	int (*set_multicast_list) (struct wlandevice * wlandev,
-				   netdevice_t * dev);
-	void (*tx_timeout) (struct wlandevice * wlandev);
+	int (*open) (struct wlandevice *wlandev);
+	int (*close) (struct wlandevice *wlandev);
+	void (*reset) (struct wlandevice *wlandev);
+	int (*txframe) (struct wlandevice *wlandev, struct sk_buff *skb,
+			p80211_hdr_t *p80211_hdr,
+			p80211_metawep_t *p80211_wep);
+	int (*mlmerequest) (struct wlandevice *wlandev, p80211msg_t *msg);
+	int (*set_multicast_list) (struct wlandevice *wlandev,
+				   netdevice_t *dev);
+	void (*tx_timeout) (struct wlandevice *wlandev);
 
 	/* 802.11 State */
 	u8 bssid[WLAN_BSSID_LEN];
@@ -227,16 +227,16 @@
 } wlandevice_t;
 
 /* WEP stuff */
-int wep_change_key(wlandevice_t * wlandev, int keynum, u8 * key, int keylen);
-int wep_decrypt(wlandevice_t * wlandev, u8 * buf, u32 len, int key_override,
-		u8 * iv, u8 * icv);
-int wep_encrypt(wlandevice_t * wlandev, u8 * buf, u8 * dst, u32 len, int keynum,
-		u8 * iv, u8 * icv);
+int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen);
+int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override,
+		u8 *iv, u8 *icv);
+int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum,
+		u8 *iv, u8 *icv);
 
-int wlan_setup(wlandevice_t * wlandev);
-int wlan_unsetup(wlandevice_t * wlandev);
-int register_wlandev(wlandevice_t * wlandev);
-int unregister_wlandev(wlandevice_t * wlandev);
-void p80211netdev_rx(wlandevice_t * wlandev, struct sk_buff *skb);
-void p80211netdev_hwremoved(wlandevice_t * wlandev);
+int wlan_setup(wlandevice_t *wlandev);
+int wlan_unsetup(wlandevice_t *wlandev);
+int register_wlandev(wlandevice_t *wlandev);
+int unregister_wlandev(wlandevice_t *wlandev);
+void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb);
+void p80211netdev_hwremoved(wlandevice_t *wlandev);
 #endif
diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c
index c88156c..c2e95f1 100644
--- a/drivers/staging/wlan-ng/p80211req.c
+++ b/drivers/staging/wlan-ng/p80211req.c
@@ -94,7 +94,7 @@
 *	Potentially blocks the caller, so it's a good idea to
 *	not call this function from an interrupt context.
 ----------------------------------------------------------------*/
-int p80211req_dorequest(wlandevice_t * wlandev, u8 * msgbuf)
+int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf)
 {
 	int result = 0;
 	p80211msg_t *msg = (p80211msg_t *) msgbuf;
diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h
index 5d91767..a95a45a 100644
--- a/drivers/staging/wlan-ng/p80211req.h
+++ b/drivers/staging/wlan-ng/p80211req.h
@@ -48,6 +48,6 @@
 #ifndef _LINUX_P80211REQ_H
 #define _LINUX_P80211REQ_H
 
-int p80211req_dorequest(wlandevice_t * wlandev, u8 * msgbuf);
+int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf);
 
 #endif
diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h
index 2b83ab0..41a99c5 100644
--- a/drivers/staging/wlan-ng/p80211types.h
+++ b/drivers/staging/wlan-ng/p80211types.h
@@ -168,12 +168,12 @@
 					P80211DID_MASK_ISTABLE, \
 					P80211DID_LSB_ISTABLE)
 
-#define P80211DID_MKID(s,g,i,n,t,a)	(P80211DID_MKSECTION(s) | \
-						P80211DID_MKGROUP(g) | \
-				 		P80211DID_MKITEM(i) | \
-				 		P80211DID_MKINDEX(n) | \
-						P80211DID_MKISTABLE(t) | \
-						(a))
+#define P80211DID_MKID(s, g, i, n, t, a)	(P80211DID_MKSECTION(s) | \
+					P80211DID_MKGROUP(g) | \
+					P80211DID_MKITEM(i) | \
+					P80211DID_MKINDEX(n) | \
+					P80211DID_MKISTABLE(t) | \
+					(a))
 
 #define P80211DID_GET(a, m, l)	((((u32)(a)) >> (l)) & (m))
 
@@ -340,11 +340,11 @@
 /*  metadata items.  Some components may choose to use more, */
 /*  less or different metadata items. */
 
-typedef void (*p80211_totext_t) (struct catlistitem *, u32 did, u8 * itembuf,
+typedef void (*p80211_totext_t) (struct catlistitem *, u32 did, u8 *itembuf,
 				 char *textbuf);
-typedef void (*p80211_fromtext_t) (struct catlistitem *, u32 did, u8 * itembuf,
+typedef void (*p80211_fromtext_t) (struct catlistitem *, u32 did, u8 *itembuf,
 				   char *textbuf);
-typedef u32(*p80211_valid_t) (struct catlistitem *, u32 did, u8 * itembuf);
+typedef u32(*p80211_valid_t) (struct catlistitem *, u32 did, u8 *itembuf);
 
 /*----------------------------------------------------------------*/
 /* Enumeration Lists */
diff --git a/drivers/staging/wlan-ng/p80211wext.c b/drivers/staging/wlan-ng/p80211wext.c
index 74d8022..2fa1dfa 100644
--- a/drivers/staging/wlan-ng/p80211wext.c
+++ b/drivers/staging/wlan-ng/p80211wext.c
@@ -46,8 +46,8 @@
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
 #include <linux/if_arp.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
+#include <linux/bitops.h>
+#include <linux/uaccess.h>
 #include <asm/byteorder.h>
 #include <linux/if_ether.h>
 #include <linux/bitops.h>
@@ -134,10 +134,11 @@
 	int result;
 
 	msg.msgcode = DIDmsg_dot11req_mibset;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did = did;
 	mibitem.data = data;
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	return result;
 }
@@ -174,7 +175,7 @@
 	memcpy(msg.ssid.data.data, ssid, data.length);
 	msg.ssid.data.len = data.length;
 
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -211,7 +212,7 @@
 	if (wlandev->mlmerequest == NULL)
 		return NULL;
 
-	retval = wlandev->mlmerequest(wlandev, (p80211msg_t *) & quality);
+	retval = wlandev->mlmerequest(wlandev, (p80211msg_t *) &quality);
 
 	wstats->qual.qual = qual_as_percent(quality.link.data);	/* overall link quality */
 	wstats->qual.level = quality.level.data;	/* instant signal level */
@@ -269,9 +270,10 @@
 	int err = 0;
 
 	msg.msgcode = DIDmsg_dot11req_mibget;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -309,6 +311,7 @@
 	}
 
 	msg.msgcode = DIDmsg_dot11req_mibset;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
 	mibitem.status = P80211ENUM_msgitem_status_data_ok;
 
@@ -318,7 +321,7 @@
 		mibitem.data = p80211_mhz_to_channel(freq->m);
 
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -396,10 +399,11 @@
 
 	/* Set Operation mode to the PORT TYPE RID */
 	msg.msgcode = DIDmsg_dot11req_mibset;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
 	mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result)
 		err = -EFAULT;
@@ -549,14 +553,14 @@
 	}
 
 	/* Check the Key index first. */
-	if ((i = (erq->flags & IW_ENCODE_INDEX))) {
-
+	i = (erq->flags & IW_ENCODE_INDEX);
+	if (i) {
 		if ((i < 1) || (i > NUM_WEPKEYS)) {
 			err = -EINVAL;
 			goto exit;
-		} else
+		} else {
 			i--;
-
+		}
 		/* Set current key number only if no keys are given */
 		if (erq->flags & IW_ENCODE_NOKEY) {
 			result =
@@ -621,7 +625,7 @@
 
 			msg.msgcode = DIDmsg_dot11req_mibset;
 			memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
-			result = p80211req_dorequest(wlandev, (u8 *) & msg);
+			result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 			if (result) {
 				err = -EFAULT;
@@ -729,7 +733,7 @@
 	msg.ssid.data.len = length;
 
 	pr_debug("autojoin_ssid for %s \n", essid);
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 	pr_debug("autojoin_ssid %d\n", result);
 
 	if (result) {
@@ -771,9 +775,10 @@
 	int err = 0;
 
 	msg.msgcode = DIDmsg_dot11req_mibget;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -822,9 +827,10 @@
 	int err = 0;
 
 	msg.msgcode = DIDmsg_dot11req_mibget;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -857,6 +863,7 @@
 	}
 
 	msg.msgcode = DIDmsg_dot11req_mibget;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
 	if (rts->disabled)
 		mibitem.data = 2347;
@@ -864,7 +871,7 @@
 		mibitem.data = rts->value;
 
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -886,10 +893,11 @@
 	int err = 0;
 
 	msg.msgcode = DIDmsg_dot11req_mibget;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did =
 	    DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -922,6 +930,7 @@
 	}
 
 	msg.msgcode = DIDmsg_dot11req_mibset;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did =
 	    DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
 
@@ -931,7 +940,7 @@
 		mibitem.data = frag->value;
 
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -962,10 +971,11 @@
 	u16 shortretry, longretry, lifetime;
 
 	msg.msgcode = DIDmsg_dot11req_mibget;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
 
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -979,7 +989,7 @@
 	mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
 
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -994,7 +1004,7 @@
 	    DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
 
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -1037,6 +1047,8 @@
 	int result;
 	int err = 0;
 
+	memset(&mibitem, 0, sizeof(mibitem));
+
 	if (!wlan_wext_write) {
 		err = (-EOPNOTSUPP);
 		goto exit;
@@ -1055,7 +1067,7 @@
 		mibitem.data = rrq->value /= 1024;
 
 		memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-		result = p80211req_dorequest(wlandev, (u8 *) & msg);
+		result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 		if (result) {
 			err = -EFAULT;
@@ -1069,7 +1081,7 @@
 
 			memcpy(&msg.mibattribute.data, &mibitem,
 			       sizeof(mibitem));
-			result = p80211req_dorequest(wlandev, (u8 *) & msg);
+			result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 			if (result) {
 				err = -EFAULT;
@@ -1084,7 +1096,7 @@
 
 			memcpy(&msg.mibattribute.data, &mibitem,
 			       sizeof(mibitem));
-			result = p80211req_dorequest(wlandev, (u8 *) & msg);
+			result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 			if (result) {
 				err = -EFAULT;
@@ -1114,6 +1126,7 @@
 	}
 
 	msg.msgcode = DIDmsg_dot11req_mibset;
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did =
 	    DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
 	if (rrq->fixed == 0)
@@ -1121,7 +1134,7 @@
 	else
 		mibitem.data = rrq->value;
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -1143,11 +1156,13 @@
 	int err = 0;
 
 	msg.msgcode = DIDmsg_dot11req_mibget;
+
+	memset(&mibitem, 0, sizeof(mibitem));
 	mibitem.did =
 	    DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
 
 	memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 
 	if (result) {
 		err = -EFAULT;
@@ -1295,7 +1310,7 @@
 	msg.maxchanneltime.data = 250;
 	msg.minchanneltime.data = 200;
 
-	result = p80211req_dorequest(wlandev, (u8 *) & msg);
+	result = p80211req_dorequest(wlandev, (u8 *) &msg);
 	if (result)
 		err = prism2_result2err(msg.resultcode.data);
 
@@ -1414,7 +1429,7 @@
 		msg.msgcode = DIDmsg_dot11req_scan_results;
 		msg.bssindex.data = i;
 
-		result = p80211req_dorequest(wlandev, (u8 *) & msg);
+		result = p80211req_dorequest(wlandev, (u8 *) &msg);
 		if ((result != 0) ||
 		    (msg.resultcode.data != P80211ENUM_resultcode_success)) {
 			break;
@@ -1489,7 +1504,7 @@
 		memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
 
 		memset(&msg, 0, sizeof(msg));
-		pstr = (p80211item_pstr32_t *) & msg.mibattribute.data;
+		pstr = (p80211item_pstr32_t *) &msg.mibattribute.data;
 		memcpy(pstr->data.data, ext->key, ext->key_len);
 		pstr->data.len = ext->key_len;
 		switch (idx) {
@@ -1513,7 +1528,7 @@
 			break;
 		}
 		msg.msgcode = DIDmsg_dot11req_mibset;
-		result = p80211req_dorequest(wlandev, (u8 *) & msg);
+		result = p80211req_dorequest(wlandev, (u8 *) &msg);
 		pr_debug("result (%d)\n", result);
 	}
 	return result;
@@ -1729,15 +1744,11 @@
 
 struct iw_handler_def p80211wext_handler_def = {
 	.num_standard = ARRAY_SIZE(p80211wext_handlers),
-	.num_private = 0,
-	.num_private_args = 0,
 	.standard = p80211wext_handlers,
-	.private = NULL,
-	.private_args = NULL,
 	.get_wireless_stats = p80211wext_get_wireless_stats
 };
 
-int p80211wext_event_associated(wlandevice_t * wlandev, int assoc)
+int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
 {
 	union iwreq_data data;
 
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
index aaa70ed..4be54ce 100644
--- a/drivers/staging/wlan-ng/prism2fw.c
+++ b/drivers/staging/wlan-ng/prism2fw.c
@@ -53,6 +53,7 @@
 /* Local Constants */
 
 #define PRISM2_USB_FWFILE	"prism2_ru.fw"
+MODULE_FIRMWARE(PRISM2_USB_FWFILE);
 
 #define S3DATA_MAX		5000
 #define S3PLUG_MAX		200
@@ -108,9 +109,9 @@
 } pda_t;
 
 typedef struct imgchunk {
-	u32 addr;		/* start address */
-	u32 len;		/* in bytes */
-	u16 crc;		/* CRC value (if it falls at a chunk boundary) */
+	u32 addr;	/* start address */
+	u32 len;	/* in bytes */
+	u16 crc;	/* CRC value (if it falls at a chunk boundary) */
 	u8 *data;
 } imgchunk_t;
 
@@ -204,7 +205,7 @@
 		return 1;
 	}
 
-	printk(KERN_INFO "prism2_usb: %s will be processed, size %d\n",
+	printk(KERN_INFO "prism2_usb: %s will be processed, size %zu\n",
 	       PRISM2_USB_FWFILE, fw_entry->size);
 	prism2_fwapply((const struct ihex_binrec *)fw_entry->data, wlandev);
 
@@ -264,7 +265,7 @@
 	/* Build the PDA we're going to use. */
 	if (read_cardpda(&pda, wlandev)) {
 		printk(KERN_ERR "load_cardpda failed, exiting.\n");
-		return (1);
+		return 1;
 	}
 
 	/* read the card's PRI-SUP */
@@ -286,9 +287,8 @@
 
 	/* DIDmsg_dot11req_mibget */
 	prism2mgmt_mibset_mibget(wlandev, &getmsg);
-	if (getmsg.resultcode.data != P80211ENUM_resultcode_success) {
+	if (getmsg.resultcode.data != P80211ENUM_resultcode_success)
 		printk(KERN_ERR "Couldn't fetch PRI-SUP info\n");
-	}
 
 	/* Already in host order */
 	priid.role = *data++;
@@ -301,19 +301,19 @@
 	result = read_fwfile(rfptr);
 	if (result) {
 		printk(KERN_ERR "Failed to read the data exiting.\n");
-		return (1);
+		return 1;
 	}
 
 	result = validate_identity();
 
 	if (result) {
 		printk(KERN_ERR "Incompatible firmware image.\n");
-		return (1);
+		return 1;
 	}
 
 	if (startaddr == 0x00000000) {
 		printk(KERN_ERR "Can't RAM download a Flash image!\n");
-		return (1);
+		return 1;
 	}
 
 	/* Make the image chunks */
@@ -323,20 +323,20 @@
 	result = plugimage(fchunk, nfchunks, s3plug, ns3plug, &pda);
 	if (result) {
 		printk(KERN_ERR "Failed to plug data.\n");
-		return (1);
+		return 1;
 	}
 
 	/* Insert any CRCs */
 	if (crcimage(fchunk, nfchunks, s3crc, ns3crc)) {
 		printk(KERN_ERR "Failed to insert all CRCs\n");
-		return (1);
+		return 1;
 	}
 
 	/* Write the image */
 	result = writeimage(wlandev, fchunk, nfchunks);
 	if (result) {
 		printk(KERN_ERR "Failed to ramwrite image data.\n");
-		return (1);
+		return 1;
 	}
 
 	/* clear any allocated memory */
@@ -434,9 +434,8 @@
 {
 	int i;
 	for (i = 0; i < *nfchunks; i++) {
-		if (fchunk[i].data != NULL) {
+		if (fchunk[i].data != NULL)
 			kfree(fchunk[i].data);
-		}
 	}
 	*nfchunks = 0;
 	memset(fchunk, 0, sizeof(*fchunk));
@@ -531,7 +530,7 @@
 		if (clist[i].data == NULL) {
 			printk(KERN_ERR
 			       "failed to allocate image space, exitting.\n");
-			return (1);
+			return 1;
 		}
 		memset(clist[i].data, 0, clist[i].len);
 		pr_debug("chunk[%d]: addr=0x%06x len=%d\n",
@@ -545,15 +544,14 @@
 		for (j = 0; j < *ccnt; j++) {
 			cstart = clist[j].addr;
 			cend = cstart + clist[j].len - 1;
-			if (s3start >= cstart && s3end <= cend) {
+			if (s3start >= cstart && s3end <= cend)
 				break;
-			}
 		}
 		if (((unsigned int)j) >= (*ccnt)) {
 			printk(KERN_ERR
 			       "s3rec(a=0x%06x,l=%d), no chunk match, exiting.\n",
 			       s3start, s3data[i].len);
-			return (1);
+			return 1;
 		}
 		coffset = s3start - cstart;
 		memcpy(clist[j].data + coffset, s3data[i].data, s3data[i].len);
@@ -586,7 +584,7 @@
 	curroff = 0;
 	while (curroff < (HFA384x_PDA_LEN_MAX / 2) &&
 	       le16_to_cpu(pda16[curroff + 1]) != HFA384x_PDR_END_OF_PDA) {
-		pda->rec[pda->nrec] = (hfa384x_pdrec_t *) & (pda16[curroff]);
+		pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]);
 
 		if (le16_to_cpu(pda->rec[pda->nrec]->code) == HFA384x_PDR_NICID) {
 			memcpy(&nicid, &pda->rec[pda->nrec]->data.nicid,
@@ -623,10 +621,10 @@
 		printk(KERN_ERR
 		       "no end record found or invalid lengths in "
 		       "PDR data, exiting. %x %d\n", curroff, pda->nrec);
-		return (1);
+		return 1;
 	}
 	if (le16_to_cpu(pda16[curroff + 1]) == HFA384x_PDR_END_OF_PDA) {
-		pda->rec[pda->nrec] = (hfa384x_pdrec_t *) & (pda16[curroff]);
+		pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]);
 		(pda->nrec)++;
 	}
 	return result;
@@ -869,7 +867,7 @@
 		ptr16 = (u16 *) record->data;
 
 		/* parse what was an S3 srec and put it in the right array */
-		switch(addr) {
+		switch (addr) {
 		case S3ADDR_START:
 			startaddr = *ptr32;
 			pr_debug("  S7 start addr, record=%d "
@@ -890,7 +888,7 @@
 				      s3plug[ns3plug].len);
 
 			ns3plug++;
-			if ( ns3plug == S3PLUG_MAX ) {
+			if (ns3plug == S3PLUG_MAX) {
 				printk(KERN_ERR "S3 plugrec limit reached - aborting\n");
 				return 1;
 			}
@@ -907,7 +905,7 @@
 				      s3crc[ns3crc].len,
 				      s3crc[ns3crc].dowrite);
 			ns3crc++;
-			if ( ns3crc == S3CRC_MAX ) {
+			if (ns3crc == S3CRC_MAX) {
 				printk(KERN_ERR "S3 crcrec limit reached - aborting\n");
 				return 1;
 			}
@@ -921,12 +919,12 @@
 				      rcnt,
 				      s3info[ns3info].len,
 				      s3info[ns3info].type);
-			if ( ((s3info[ns3info].len - 1) * sizeof(u16)) > sizeof(s3info[ns3info].info) ) {
+			if (((s3info[ns3info].len - 1) * sizeof(u16)) > sizeof(s3info[ns3info].info)) {
 				printk(KERN_ERR " S3 inforec length too long - aborting\n");
 				return 1;
 			}
 
-			tmpinfo = (u16*)&(s3info[ns3info].info.version);
+			tmpinfo = (u16 *)&(s3info[ns3info].info.version);
 			pr_debug("            info=");
 			for (i = 0; i < s3info[ns3info].len - 1; i++) {
 				tmpinfo[i] = *(ptr16 + 2 + i);
@@ -935,7 +933,7 @@
 			pr_debug("\n");
 
 			ns3info++;
-			if ( ns3info == S3INFO_MAX ) {
+			if (ns3info == S3INFO_MAX) {
 				printk(KERN_ERR "S3 inforec limit reached - aborting\n");
 				return 1;
 			}
@@ -945,7 +943,7 @@
 			s3data[ns3data].len = len;
 			s3data[ns3data].data = (uint8_t *) record->data;
 			ns3data++;
-			if ( ns3data == S3DATA_MAX ) {
+			if (ns3data == S3DATA_MAX) {
 				printk(KERN_ERR "S3 datarec limit reached - aborting\n");
 				return 1;
 			}
@@ -1023,7 +1021,7 @@
 	rstatemsg.enable.data = P80211ENUM_truth_true;
 	rstatemsg.exeaddr.data = startaddr;
 
-	msgp = (p80211msg_t *) & rstatemsg;
+	msgp = (p80211msg_t *) &rstatemsg;
 	result = prism2mgmt_ramdl_state(wlandev, msgp);
 	if (result) {
 		printk(KERN_ERR
@@ -1063,7 +1061,7 @@
 			    ("Sending xxxdl_write message addr=%06x len=%d.\n",
 			     currdaddr, currlen);
 
-			msgp = (p80211msg_t *) & rwritemsg;
+			msgp = (p80211msg_t *) &rwritemsg;
 			result = prism2mgmt_ramdl_write(wlandev, msgp);
 
 			/* Check the results */
@@ -1090,7 +1088,7 @@
 	rstatemsg.enable.data = P80211ENUM_truth_false;
 	rstatemsg.exeaddr.data = 0;
 
-	msgp = (p80211msg_t *) & rstatemsg;
+	msgp = (p80211msg_t *) &rstatemsg;
 	result = prism2mgmt_ramdl_state(wlandev, msgp);
 	if (result) {
 		printk(KERN_ERR
@@ -1161,7 +1159,7 @@
 			/* SEC compat range */
 			if ((s3info[i].info.compat.role == 1) &&
 			    (s3info[i].info.compat.id == 4)) {
-
+				/* FIXME: isn't something missing here? */
 			}
 
 			break;
@@ -1196,8 +1194,9 @@
 			pr_debug("Unknown inforec type %d\n", s3info[i].type);
 		}
 	}
-	// walk through
+	/* walk through */
 
-	if (trump && (result != 2)) result = 0;
+	if (trump && (result != 2))
+		result = 0;
 	return result;
 }
diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c
index 9f7d96c..ad163da 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.c
+++ b/drivers/staging/wlan-ng/prism2mgmt.c
@@ -67,7 +67,7 @@
 #include <linux/wireless.h>
 #include <linux/netdevice.h>
 #include <linux/delay.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/byteorder.h>
 #include <linux/random.h>
 #include <linux/usb.h>
@@ -541,7 +541,7 @@
 	/*** STATION ***/
 	/* Set the REQUIRED config items */
 	/* SSID */
-	pstr = (p80211pstrd_t *) & (msg->ssid.data);
+	pstr = (p80211pstrd_t *) &(msg->ssid.data);
 	prism2mgmt_pstr2bytestr(p2bytestr, pstr);
 	result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
 					bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
@@ -1034,7 +1034,7 @@
 
 	/* Set the ssid */
 	memset(bytebuf, 0, 256);
-	pstr = (p80211pstrd_t *) & (msg->ssid.data);
+	pstr = (p80211pstrd_t *) &(msg->ssid.data);
 	prism2mgmt_pstr2bytestr(p2bytestr, pstr);
 	result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
 					bytebuf,
@@ -1123,8 +1123,8 @@
 		if (hw->presniff_port_type != 0) {
 			word = hw->presniff_port_type;
 			result = hfa384x_drvr_setconfig16(hw,
-							  HFA384x_RID_CNFPORTTYPE,
-							  word);
+						  HFA384x_RID_CNFPORTTYPE,
+						  word);
 			if (result) {
 				pr_debug
 				    ("failed to restore porttype, result=%d\n",
@@ -1156,10 +1156,8 @@
 			if (wlandev->netdev->type == ARPHRD_ETHER) {
 				/* Save macport 0 state */
 				result = hfa384x_drvr_getconfig16(hw,
-								  HFA384x_RID_CNFPORTTYPE,
-								  &
-								  (hw->
-								   presniff_port_type));
+						  HFA384x_RID_CNFPORTTYPE,
+						  &(hw->presniff_port_type));
 				if (result) {
 					pr_debug
 					    ("failed to read porttype, result=%d\n",
@@ -1168,10 +1166,8 @@
 				}
 				/* Save the wepflags state */
 				result = hfa384x_drvr_getconfig16(hw,
-								  HFA384x_RID_CNFWEPFLAGS,
-								  &
-								  (hw->
-								   presniff_wepflags));
+						  HFA384x_RID_CNFWEPFLAGS,
+						  &(hw->presniff_wepflags));
 				if (result) {
 					pr_debug
 					    ("failed to read wepflags, result=%d\n",
@@ -1218,8 +1214,8 @@
 			/* Set the port type to pIbss */
 			word = HFA384x_PORTTYPE_PSUEDOIBSS;
 			result = hfa384x_drvr_setconfig16(hw,
-							  HFA384x_RID_CNFPORTTYPE,
-							  word);
+						  HFA384x_RID_CNFPORTTYPE,
+						  word);
 			if (result) {
 				pr_debug
 				    ("failed to set porttype %d, result=%d\n",
@@ -1235,8 +1231,8 @@
 				    HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
 				result =
 				    hfa384x_drvr_setconfig16(hw,
-							     HFA384x_RID_CNFWEPFLAGS,
-							     word);
+						     HFA384x_RID_CNFWEPFLAGS,
+						     word);
 			}
 
 			if (result) {
diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h
index bdf2b3e..07eeceb 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.h
+++ b/drivers/staging/wlan-ng/prism2mgmt.h
@@ -63,43 +63,43 @@
 extern int prism2_reset_holdtime;
 extern int prism2_reset_settletime;
 
-u32 prism2sta_ifstate(wlandevice_t * wlandev, u32 ifstate);
+u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate);
 
-void prism2sta_ev_info(wlandevice_t * wlandev, hfa384x_InfFrame_t * inf);
-void prism2sta_ev_txexc(wlandevice_t * wlandev, u16 status);
-void prism2sta_ev_tx(wlandevice_t * wlandev, u16 status);
-void prism2sta_ev_rx(wlandevice_t * wlandev, struct sk_buff *skb);
-void prism2sta_ev_alloc(wlandevice_t * wlandev);
+void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status);
+void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status);
+void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb);
+void prism2sta_ev_alloc(wlandevice_t *wlandev);
 
-int prism2mgmt_mibset_mibget(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_scan(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_scan_results(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_start(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_wlansniff(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_readpda(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_ramdl_state(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_ramdl_write(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_flashdl_state(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_flashdl_write(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_autojoin(wlandevice_t * wlandev, void *msgp);
+int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_start(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp);
 
 /*---------------------------------------------------------------
 * conversion functions going between wlan message data types and
 * Prism2 data types
 ---------------------------------------------------------------*/
 /* byte area conversion functions*/
-void prism2mgmt_pstr2bytearea(u8 * bytearea, p80211pstrd_t * pstr);
-void prism2mgmt_bytearea2pstr(u8 * bytearea, p80211pstrd_t * pstr, int len);
+void prism2mgmt_pstr2bytearea(u8 *bytearea, p80211pstrd_t *pstr);
+void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len);
 
 /* byte string conversion functions*/
-void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t * bytestr, p80211pstrd_t * pstr);
-void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t * bytestr, p80211pstrd_t * pstr);
+void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr);
+void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr);
 
 /* functions to convert Group Addresses */
-void prism2mgmt_get_grpaddr(u32 did, p80211pstrd_t * pstr, hfa384x_t * priv);
+void prism2mgmt_get_grpaddr(u32 did, p80211pstrd_t *pstr, hfa384x_t *priv);
 int prism2mgmt_set_grpaddr(u32 did,
-			   u8 * prism2buf, p80211pstrd_t * pstr,
-			   hfa384x_t * priv);
+			   u8 *prism2buf, p80211pstrd_t *pstr,
+			   hfa384x_t *priv);
 int prism2mgmt_get_grpaddr_index(u32 did);
 
 void prism2sta_processing_defer(struct work_struct *data);
diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c
index 2fff0a1..98a5d58 100644
--- a/drivers/staging/wlan-ng/prism2mib.c
+++ b/drivers/staging/wlan-ng/prism2mib.c
@@ -114,7 +114,7 @@
 
 static int prism2mib_wepdefaultkey(mibrec_t *mib,
 				   int isget,
-				   wlandevice_t * wlandev,
+				   wlandevice_t *wlandev,
 				   hfa384x_t *hw,
 				   p80211msg_dot11req_mibset_t *msg,
 				   void *data);
@@ -726,7 +726,7 @@
 			if (isget) {
 				hfa384x_drvr_getconfig(hw,
 						       HFA384x_RID_CNFWPADATA,
-						       (u8 *) & wpa,
+						       (u8 *) &wpa,
 						       sizeof(wpa));
 				pstr->len = le16_to_cpu(wpa.datalen);
 				memcpy(pstr->data, wpa.data, pstr->len);
@@ -736,9 +736,9 @@
 
 				result =
 				    hfa384x_drvr_setconfig(hw,
-							   HFA384x_RID_CNFWPADATA,
-							   (u8 *) & wpa,
-							   sizeof(wpa));
+						   HFA384x_RID_CNFWPADATA,
+						   (u8 *) &wpa,
+						   sizeof(wpa));
 			}
 			break;
 		}
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
index 50f301d..31ac8da 100644
--- a/drivers/staging/wlan-ng/prism2sta.c
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -64,7 +64,7 @@
 #include <linux/byteorder/generic.h>
 #include <linux/ctype.h>
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <asm/byteorder.h>
 #include <linux/if_arp.h>
@@ -1023,13 +1023,13 @@
 
 	cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(u32);
 	if (inf->framelen > 22) {
-		dst = (u32 *) & hw->tallies;
-		src32 = (u32 *) & inf->info.commtallies32;
+		dst = (u32 *) &hw->tallies;
+		src32 = (u32 *) &inf->info.commtallies32;
 		for (i = 0; i < cnt; i++, dst++, src32++)
 			*dst += le32_to_cpu(*src32);
 	} else {
-		dst = (u32 *) & hw->tallies;
-		src16 = (u16 *) & inf->info.commtallies16;
+		dst = (u32 *) &hw->tallies;
+		src16 = (u16 *) &inf->info.commtallies16;
 		for (i = 0; i < cnt; i++, dst++, src16++)
 			*dst += le16_to_cpu(*src16);
 	}
@@ -1280,7 +1280,7 @@
 				     HFA384x_RID_CURRENTSSID, result);
 				goto failed;
 			}
-			prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) & ssid,
+			prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid,
 						(p80211pstrd_t *) &
 						wlandev->ssid);
 
@@ -1368,8 +1368,8 @@
 				 HFA384x_RID_CURRENTSSID, result);
 			goto failed;
 		}
-		prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) & ssid,
-					(p80211pstrd_t *) & wlandev->ssid);
+		prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid,
+					(p80211pstrd_t *) &wlandev->ssid);
 
 		hw->link_status = HFA384x_LINK_CONNECTED;
 		netif_carrier_on(wlandev->netdev);
@@ -2028,8 +2028,8 @@
 			 HFA384x_RID_CURRENTSSID, result);
 		goto done;
 	}
-	prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) & ssid,
-				(p80211pstrd_t *) & wlandev->ssid);
+	prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid,
+				(p80211pstrd_t *) &wlandev->ssid);
 
 	/* Reschedule timer */
 	mod_timer(&hw->commsqual_timer, jiffies + HZ);
diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c
index 9dde68b..501d27f 100644
--- a/drivers/staging/wlan-ng/prism2usb.c
+++ b/drivers/staging/wlan-ng/prism2usb.c
@@ -24,8 +24,9 @@
 	 (0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps WLAN USB Adapter")},
 	{PRISM_USB_DEVICE
 	 (0x067c, 0x1022, "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter")},
-	{PRISM_USB_DEVICE(0x049f, 0x0033,
-			  "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter")},
+	{PRISM_USB_DEVICE
+	 (0x049f, 0x0033,
+	 "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter")},
 	{PRISM_USB_DEVICE
 	 (0x0411, 0x0016, "Melco WLI-USB-S11 11Mbps WLAN Adapter")},
 	{PRISM_USB_DEVICE
@@ -55,7 +56,6 @@
 	 (0x04f1, 0x3009, "JVC MP-XP7250 Builtin USB WLAN Adapter")},
 	{PRISM_USB_DEVICE(0x0846, 0x4110, "NetGear MA111")},
 	{PRISM_USB_DEVICE(0x03f3, 0x0020, "Adaptec AWN-8020 USB WLAN Adapter")},
-/*      {PRISM_USB_DEVICE(0x0ace, 0x1201, "ZyDAS ZD1201 Wireless USB Adapter")}, */
 	{PRISM_USB_DEVICE(0x2821, 0x3300, "ASUS-WL140 Wireless USB Adapter")},
 	{PRISM_USB_DEVICE(0x2001, 0x3700, "DWL-122 Wireless USB Adapter")},
 	{PRISM_USB_DEVICE
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 8aa1955..1da73ec 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -44,17 +44,6 @@
 
 	  If you don't know what to do here, say N.
 
-config UIO_SMX
-	tristate "SMX cryptengine UIO interface"
-	help
-	  Userspace IO interface to the Cryptography engine found on the
-	  Nias Digital SMX boards.  These will be available from Q4 2008
-	  from http://www.niasdigital.com.  The userspace part of this
-	  driver will be released under the GPL at the same time as the
-	  hardware and will be able to be downloaded from the same site.
-
-	  If you compile this as a module, it will be called uio_smx.
-
 config UIO_AEC
 	tristate "AEC video timestamp device"
 	depends on PCI
@@ -74,6 +63,7 @@
 
 config UIO_SERCOS3
 	tristate "Automata Sercos III PCI card driver"
+	depends on PCI
 	help
 	  Userspace I/O interface for the Sercos III PCI card from
 	  Automata GmbH. The userspace part of this driver will be
@@ -87,11 +77,21 @@
 config UIO_PCI_GENERIC
 	tristate "Generic driver for PCI 2.3 and PCI Express cards"
 	depends on PCI
-	default n
 	help
 	  Generic driver that you can bind, dynamically, to any
 	  PCI 2.3 compliant and PCI Express card. It is useful,
 	  primarily, for virtualization scenarios.
 	  If you compile this as a module, it will be called uio_pci_generic.
 
+config UIO_NETX
+	tristate "Hilscher NetX Card driver"
+	depends on PCI
+	help
+	  Driver for Hilscher NetX based fieldbus cards (cifX, comX).
+	  This driver requires a userspace component that comes with the card
+	  or is available from Hilscher (http://www.hilscher.com).
+
+	  To compile this driver as a module, choose M here; the module
+	  will be called uio_netx.
+
 endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 73b2e75..18fd818 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -2,7 +2,7 @@
 obj-$(CONFIG_UIO_CIF)	+= uio_cif.o
 obj-$(CONFIG_UIO_PDRV)	+= uio_pdrv.o
 obj-$(CONFIG_UIO_PDRV_GENIRQ)	+= uio_pdrv_genirq.o
-obj-$(CONFIG_UIO_SMX)	+= uio_smx.o
 obj-$(CONFIG_UIO_AEC)	+= uio_aec.o
 obj-$(CONFIG_UIO_SERCOS3)	+= uio_sercos3.o
 obj-$(CONFIG_UIO_PCI_GENERIC)	+= uio_pci_generic.o
+obj-$(CONFIG_UIO_NETX)	+= uio_netx.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index e941367..4de382a 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -129,7 +129,7 @@
 	return entry->show(mem, buf);
 }
 
-static struct sysfs_ops map_sysfs_ops = {
+static const struct sysfs_ops map_sysfs_ops = {
 	.show = map_type_show,
 };
 
@@ -217,7 +217,7 @@
 	return entry->show(port, buf);
 }
 
-static struct sysfs_ops portio_sysfs_ops = {
+static const struct sysfs_ops portio_sysfs_ops = {
 	.show = portio_type_show,
 };
 
diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c
new file mode 100644
index 0000000..afbf0bd
--- /dev/null
+++ b/drivers/uio/uio_netx.c
@@ -0,0 +1,172 @@
+/*
+ * UIO driver for Hilscher NetX based fieldbus cards (cifX, comX).
+ * See http://www.hilscher.com for details.
+ *
+ * (C) 2007 Hans J. Koch <hjk@linutronix.de>
+ * (C) 2008 Manuel Traut <manut@linutronix.de>
+ *
+ * Licensed under GPL version 2 only.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/uio_driver.h>
+
+#define PCI_VENDOR_ID_HILSCHER		0x15CF
+#define PCI_DEVICE_ID_HILSCHER_NETX	0x0000
+#define PCI_SUBDEVICE_ID_NXSB_PCA	0x3235
+#define PCI_SUBDEVICE_ID_NXPCA		0x3335
+
+#define DPM_HOST_INT_EN0	0xfff0
+#define DPM_HOST_INT_STAT0	0xffe0
+
+#define DPM_HOST_INT_MASK	0xe600ffff
+#define DPM_HOST_INT_GLOBAL_EN	0x80000000
+
+static irqreturn_t netx_handler(int irq, struct uio_info *dev_info)
+{
+	void __iomem *int_enable_reg = dev_info->mem[0].internal_addr
+					+ DPM_HOST_INT_EN0;
+	void __iomem *int_status_reg = dev_info->mem[0].internal_addr
+					+ DPM_HOST_INT_STAT0;
+
+	/* Is one of our interrupts enabled and active ? */
+	if (!(ioread32(int_enable_reg) & ioread32(int_status_reg)
+		& DPM_HOST_INT_MASK))
+		return IRQ_NONE;
+
+	/* Disable interrupt */
+	iowrite32(ioread32(int_enable_reg) & ~DPM_HOST_INT_GLOBAL_EN,
+		int_enable_reg);
+	return IRQ_HANDLED;
+}
+
+static int __devinit netx_pci_probe(struct pci_dev *dev,
+					const struct pci_device_id *id)
+{
+	struct uio_info *info;
+	int bar;
+
+	info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	if (pci_enable_device(dev))
+		goto out_free;
+
+	if (pci_request_regions(dev, "netx"))
+		goto out_disable;
+
+	switch (id->device) {
+	case PCI_DEVICE_ID_HILSCHER_NETX:
+		bar = 0;
+		info->name = "netx";
+		break;
+	default:
+		bar = 2;
+		info->name = "netx_plx";
+	}
+
+	/* BAR0 or 2 points to the card's dual port memory */
+	info->mem[0].addr = pci_resource_start(dev, bar);
+	if (!info->mem[0].addr)
+		goto out_release;
+	info->mem[0].internal_addr = ioremap(pci_resource_start(dev, bar),
+						pci_resource_len(dev, bar));
+
+	if (!info->mem[0].internal_addr)
+			goto out_release;
+
+	info->mem[0].size = pci_resource_len(dev, bar);
+	info->mem[0].memtype = UIO_MEM_PHYS;
+	info->irq = dev->irq;
+	info->irq_flags = IRQF_SHARED;
+	info->handler = netx_handler;
+	info->version = "0.0.1";
+
+	/* Make sure all interrupts are disabled */
+	iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0);
+
+	if (uio_register_device(&dev->dev, info))
+		goto out_unmap;
+
+	pci_set_drvdata(dev, info);
+	dev_info(&dev->dev, "Found %s card, registered UIO device.\n",
+				info->name);
+
+	return 0;
+
+out_unmap:
+	iounmap(info->mem[0].internal_addr);
+out_release:
+	pci_release_regions(dev);
+out_disable:
+	pci_disable_device(dev);
+out_free:
+	kfree(info);
+	return -ENODEV;
+}
+
+static void netx_pci_remove(struct pci_dev *dev)
+{
+	struct uio_info *info = pci_get_drvdata(dev);
+
+	/* Disable all interrupts */
+	iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0);
+	uio_unregister_device(info);
+	pci_release_regions(dev);
+	pci_disable_device(dev);
+	pci_set_drvdata(dev, NULL);
+	iounmap(info->mem[0].internal_addr);
+
+	kfree(info);
+}
+
+static struct pci_device_id netx_pci_ids[] = {
+	{
+		.vendor =	PCI_VENDOR_ID_HILSCHER,
+		.device =	PCI_DEVICE_ID_HILSCHER_NETX,
+		.subvendor =	0,
+		.subdevice =	0,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_PLX,
+		.device =	PCI_DEVICE_ID_PLX_9030,
+		.subvendor =	PCI_VENDOR_ID_PLX,
+		.subdevice =	PCI_SUBDEVICE_ID_NXSB_PCA,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_PLX,
+		.device =	PCI_DEVICE_ID_PLX_9030,
+		.subvendor =	PCI_VENDOR_ID_PLX,
+		.subdevice =	PCI_SUBDEVICE_ID_NXPCA,
+	},
+	{ 0, }
+};
+
+static struct pci_driver netx_pci_driver = {
+	.name = "netx",
+	.id_table = netx_pci_ids,
+	.probe = netx_pci_probe,
+	.remove = netx_pci_remove,
+};
+
+static int __init netx_init_module(void)
+{
+	return pci_register_driver(&netx_pci_driver);
+}
+
+static void __exit netx_exit_module(void)
+{
+	pci_unregister_driver(&netx_pci_driver);
+}
+
+module_init(netx_init_module);
+module_exit(netx_exit_module);
+
+MODULE_DEVICE_TABLE(pci, netx_pci_ids);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Hans J. Koch, Manuel Traut");
diff --git a/drivers/uio/uio_smx.c b/drivers/uio/uio_smx.c
deleted file mode 100644
index 44054a6..0000000
--- a/drivers/uio/uio_smx.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * UIO SMX Cryptengine driver.
- *
- * (C) 2008 Nias Digital P/L <bn@niasdigital.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/device.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/uio_driver.h>
-#include <linux/io.h>
-
-#define DRV_NAME "smx-ce"
-#define DRV_VERSION "0.03"
-
-#define SMX_CSR  0x00000000
-#define SMX_EnD  0x00000001
-#define SMX_RUN  0x00000002
-#define SMX_DRDY 0x00000004
-#define SMX_ERR  0x00000008
-
-static irqreturn_t smx_handler(int irq, struct uio_info *dev_info)
-{
-	void __iomem *csr = dev_info->mem[0].internal_addr + SMX_CSR;
-
-	u32 status = ioread32(csr);
-
-	if (!(status & SMX_DRDY))
-		return IRQ_NONE;
-
-	/* Disable interrupt */
-	iowrite32(status & ~SMX_DRDY, csr);
-	return IRQ_HANDLED;
-}
-
-static int __devinit smx_ce_probe(struct platform_device *dev)
-{
-
-	int ret = -ENODEV;
-	struct uio_info *info;
-	struct resource *regs;
-
-	info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-
-	regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!regs) {
-		dev_err(&dev->dev, "No memory resource specified\n");
-		goto out_free;
-	}
-
-	info->mem[0].addr = regs->start;
-	if (!info->mem[0].addr) {
-		dev_err(&dev->dev, "Invalid memory resource\n");
-		goto out_free;
-	}
-
-	info->mem[0].size = regs->end - regs->start + 1;
-	info->mem[0].internal_addr = ioremap(regs->start, info->mem[0].size);
-
-	if (!info->mem[0].internal_addr) {
-		dev_err(&dev->dev, "Can't remap memory address range\n");
-		goto out_free;
-	}
-
-	info->mem[0].memtype = UIO_MEM_PHYS;
-
-	info->name = "smx-ce";
-	info->version = "0.03";
-
-	info->irq = platform_get_irq(dev, 0);
-	if (info->irq < 0) {
-		ret = info->irq;
-		dev_err(&dev->dev, "No (or invalid) IRQ resource specified\n");
-		goto out_unmap;
-	}
-
-	info->irq_flags = IRQF_SHARED;
-	info->handler = smx_handler;
-
-	platform_set_drvdata(dev, info);
-
-	ret = uio_register_device(&dev->dev, info);
-
-	if (ret)
-		goto out_unmap;
-
-	return 0;
-
-out_unmap:
-	iounmap(info->mem[0].internal_addr);
-out_free:
-	kfree(info);
-
-	return ret;
-}
-
-static int __devexit smx_ce_remove(struct platform_device *dev)
-{
-	struct uio_info *info = platform_get_drvdata(dev);
-
-	uio_unregister_device(info);
-	platform_set_drvdata(dev, NULL);
-	iounmap(info->mem[0].internal_addr);
-
-	kfree(info);
-
-	return 0;
-}
-
-static struct platform_driver smx_ce_driver = {
-	.probe		= smx_ce_probe,
-	.remove		= __devexit_p(smx_ce_remove),
-	.driver		= {
-		.name	= DRV_NAME,
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init smx_ce_init_module(void)
-{
-	return platform_driver_register(&smx_ce_driver);
-}
-module_init(smx_ce_init_module);
-
-static void __exit smx_ce_exit_module(void)
-{
-	platform_driver_unregister(&smx_ce_driver);
-}
-module_exit(smx_ce_exit_module);
-
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR("Ben Nizette <bn@niasdigital.com>");
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 4f5bb56..6a58cb1 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -21,6 +21,7 @@
 	default y if USB_ARCH_HAS_EHCI
 	default y if PCMCIA && !M32R			# sl811_cs
 	default y if ARM				# SL-811
+	default y if BLACKFIN				# SL-811
 	default y if SUPERH				# r8a66597-hcd
 	default PCI
 
@@ -39,6 +40,7 @@
 	default y if ARCH_PNX4008 && I2C
 	default y if MFD_TC6393XB
 	default y if ARCH_W90X900
+	default y if ARCH_DAVINCI_DA8XX
 	# PPC:
 	default y if STB03xxx
 	default y if PPC_MPC52xx
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index be3c9b8..80b4008 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -21,6 +21,7 @@
 obj-$(CONFIG_USB_R8A66597_HCD)	+= host/
 obj-$(CONFIG_USB_HWA_HCD)	+= host/
 obj-$(CONFIG_USB_ISP1760_HCD)	+= host/
+obj-$(CONFIG_USB_IMX21_HCD)	+= host/
 
 obj-$(CONFIG_USB_C67X00_HCD)	+= c67x00/
 
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 56802d2..c89990f 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -5,6 +5,7 @@
  *  Copyright (C) 2004 David Woodhouse, Duncan Sands, Roman Kagan
  *  Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)
  *  Copyright (C) 2007 Simon Arlott
+ *  Copyright (C) 2009 Simon Arlott
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License as published by the Free
@@ -43,7 +44,7 @@
 #include "usbatm.h"
 
 #define DRIVER_AUTHOR	"Roman Kagan, David Woodhouse, Duncan Sands, Simon Arlott"
-#define DRIVER_VERSION	"0.3"
+#define DRIVER_VERSION	"0.4"
 #define DRIVER_DESC	"Conexant AccessRunner ADSL USB modem driver"
 
 static const char cxacru_driver_name[] = "cxacru";
@@ -52,6 +53,7 @@
 #define CXACRU_EP_DATA		0x02	/* Bulk in/out */
 
 #define CMD_PACKET_SIZE		64	/* Should be maxpacket(ep)? */
+#define CMD_MAX_CONFIG		((CMD_PACKET_SIZE / 4 - 1) / 2)
 
 /* Addresses */
 #define PLLFCLK_ADDR	0x00350068
@@ -105,6 +107,26 @@
 	CM_REQUEST_MAX,
 };
 
+/* commands for interaction with the flash memory
+ *
+ * read:  response is the contents of the first 60 bytes of flash memory
+ * write: request contains the 60 bytes of data to write to flash memory
+ *        response is the contents of the first 60 bytes of flash memory
+ *
+ * layout: PP PP VV VV  MM MM MM MM  MM MM ?? ??  SS SS SS SS  SS SS SS SS
+ *         SS SS SS SS  SS SS SS SS  00 00 00 00  00 00 00 00  00 00 00 00
+ *         00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00
+ *
+ *   P: le16  USB Product ID
+ *   V: le16  USB Vendor ID
+ *   M: be48  MAC Address
+ *   S: le16  ASCII Serial Number
+ */
+enum cxacru_cm_flash {
+	CM_FLASH_READ = 0xa1,
+	CM_FLASH_WRITE = 0xa2
+};
+
 /* reply codes to the commands above */
 enum cxacru_cm_status {
 	CM_STATUS_UNDEFINED,
@@ -196,23 +218,32 @@
 static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \
 	cxacru_sysfs_show_##_name, cxacru_sysfs_store_##_name)
 
+#define CXACRU_SET_INIT(_name) \
+static DEVICE_ATTR(_name, S_IWUSR, \
+	NULL, cxacru_sysfs_store_##_name)
+
 #define CXACRU_ATTR_INIT(_value, _type, _name) \
 static ssize_t cxacru_sysfs_show_##_name(struct device *dev, \
 	struct device_attribute *attr, char *buf) \
 { \
-	struct usb_interface *intf = to_usb_interface(dev); \
-	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf); \
-	struct cxacru_data *instance = usbatm_instance->driver_data; \
+	struct cxacru_data *instance = to_usbatm_driver_data(\
+		to_usb_interface(dev)); \
+\
+	if (instance == NULL) \
+		return -ENODEV; \
+\
 	return cxacru_sysfs_showattr_##_type(instance->card_info[_value], buf); \
 } \
 CXACRU__ATTR_INIT(_name)
 
 #define CXACRU_ATTR_CREATE(_v, _t, _name) CXACRU_DEVICE_CREATE_FILE(_name)
 #define CXACRU_CMD_CREATE(_name)          CXACRU_DEVICE_CREATE_FILE(_name)
+#define CXACRU_SET_CREATE(_name)          CXACRU_DEVICE_CREATE_FILE(_name)
 #define CXACRU__ATTR_CREATE(_name)        CXACRU_DEVICE_CREATE_FILE(_name)
 
 #define CXACRU_ATTR_REMOVE(_v, _t, _name) CXACRU_DEVICE_REMOVE_FILE(_name)
 #define CXACRU_CMD_REMOVE(_name)          CXACRU_DEVICE_REMOVE_FILE(_name)
+#define CXACRU_SET_REMOVE(_name)          CXACRU_DEVICE_REMOVE_FILE(_name)
 #define CXACRU__ATTR_REMOVE(_name)        CXACRU_DEVICE_REMOVE_FILE(_name)
 
 static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf)
@@ -267,12 +298,12 @@
 static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
 {
 	static char *str[] = {
-			NULL,
+			"",
 			"ANSI T1.413",
 			"ITU-T G.992.1 (G.DMT)",
 			"ITU-T G.992.2 (G.LITE)"
 	};
-	if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
+	if (unlikely(value >= ARRAY_SIZE(str)))
 		return snprintf(buf, PAGE_SIZE, "%u\n", value);
 	return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
 }
@@ -288,22 +319,28 @@
 static ssize_t cxacru_sysfs_show_mac_address(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
-	struct atm_dev *atm_dev = usbatm_instance->atm_dev;
+	struct cxacru_data *instance = to_usbatm_driver_data(
+			to_usb_interface(dev));
 
-	return snprintf(buf, PAGE_SIZE, "%pM\n", atm_dev->esi);
+	if (instance == NULL || instance->usbatm->atm_dev == NULL)
+		return -ENODEV;
+
+	return snprintf(buf, PAGE_SIZE, "%pM\n",
+		instance->usbatm->atm_dev->esi);
 }
 
 static ssize_t cxacru_sysfs_show_adsl_state(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
-	struct cxacru_data *instance = usbatm_instance->driver_data;
-	u32 value = instance->card_info[CXINF_LINE_STARTABLE];
-
 	static char *str[] = { "running", "stopped" };
+	struct cxacru_data *instance = to_usbatm_driver_data(
+			to_usb_interface(dev));
+	u32 value;
+
+	if (instance == NULL)
+		return -ENODEV;
+
+	value = instance->card_info[CXINF_LINE_STARTABLE];
 	if (unlikely(value >= ARRAY_SIZE(str)))
 		return snprintf(buf, PAGE_SIZE, "%u\n", value);
 	return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
@@ -312,9 +349,8 @@
 static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct usb_interface *intf = to_usb_interface(dev);
-	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
-	struct cxacru_data *instance = usbatm_instance->driver_data;
+	struct cxacru_data *instance = to_usbatm_driver_data(
+			to_usb_interface(dev));
 	int ret;
 	int poll = -1;
 	char str_cmd[8];
@@ -328,13 +364,16 @@
 		return -EINVAL;
 	ret = 0;
 
+	if (instance == NULL)
+		return -ENODEV;
+
 	if (mutex_lock_interruptible(&instance->adsl_state_serialize))
 		return -ERESTARTSYS;
 
 	if (!strcmp(str_cmd, "stop") || !strcmp(str_cmd, "restart")) {
 		ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_STOP, NULL, 0, NULL, 0);
 		if (ret < 0) {
-			atm_err(usbatm_instance, "change adsl state:"
+			atm_err(instance->usbatm, "change adsl state:"
 				" CHIP_ADSL_LINE_STOP returned %d\n", ret);
 
 			ret = -EIO;
@@ -354,7 +393,7 @@
 	if (!strcmp(str_cmd, "start") || !strcmp(str_cmd, "restart")) {
 		ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
 		if (ret < 0) {
-			atm_err(usbatm_instance, "change adsl state:"
+			atm_err(instance->usbatm, "change adsl state:"
 				" CHIP_ADSL_LINE_START returned %d\n", ret);
 
 			ret = -EIO;
@@ -407,6 +446,72 @@
 	return ret;
 }
 
+/* CM_REQUEST_CARD_DATA_GET times out, so no show attribute */
+
+static ssize_t cxacru_sysfs_store_adsl_config(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct cxacru_data *instance = to_usbatm_driver_data(
+			to_usb_interface(dev));
+	int len = strlen(buf);
+	int ret, pos, num;
+	__le32 data[CMD_PACKET_SIZE / 4];
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EACCES;
+
+	if (instance == NULL)
+		return -ENODEV;
+
+	pos = 0;
+	num = 0;
+	while (pos < len) {
+		int tmp;
+		u32 index;
+		u32 value;
+
+		ret = sscanf(buf + pos, "%x=%x%n", &index, &value, &tmp);
+		if (ret < 2)
+			return -EINVAL;
+		if (index < 0 || index > 0x7f)
+			return -EINVAL;
+		pos += tmp;
+
+		/* skip trailing newline */
+		if (buf[pos] == '\n' && pos == len-1)
+			pos++;
+
+		data[num * 2 + 1] = cpu_to_le32(index);
+		data[num * 2 + 2] = cpu_to_le32(value);
+		num++;
+
+		/* send config values when data buffer is full
+		 * or no more data
+		 */
+		if (pos >= len || num >= CMD_MAX_CONFIG) {
+			char log[CMD_MAX_CONFIG * 12 + 1]; /* %02x=%08x */
+
+			data[0] = cpu_to_le32(num);
+			ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET,
+				(u8 *) data, 4 + num * 8, NULL, 0);
+			if (ret < 0) {
+				atm_err(instance->usbatm,
+					"set card data returned %d\n", ret);
+				return -EIO;
+			}
+
+			for (tmp = 0; tmp < num; tmp++)
+				snprintf(log + tmp*12, 13, " %02x=%08x",
+					le32_to_cpu(data[tmp * 2 + 1]),
+					le32_to_cpu(data[tmp * 2 + 2]));
+			atm_info(instance->usbatm, "config%s\n", log);
+			num = 0;
+		}
+	}
+
+	return len;
+}
+
 /*
  * All device attributes are included in CXACRU_ALL_FILES
  * so that the same list can be used multiple times:
@@ -442,7 +547,8 @@
 CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND,              u32,  adsl_headend); \
 CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND_ENVIRONMENT,  u32,  adsl_headend_environment); \
 CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION,        u32,  adsl_controller_version); \
-CXACRU_CMD_##_action(                                        adsl_state);
+CXACRU_CMD_##_action(                                        adsl_state); \
+CXACRU_SET_##_action(                                        adsl_config);
 
 CXACRU_ALL_FILES(INIT);
 
@@ -596,7 +702,7 @@
 	len = ret / 4;
 	for (offb = 0; offb < len; ) {
 		int l = le32_to_cpu(buf[offb++]);
-		if (l > stride || l > (len - offb) / 2) {
+		if (l < 0 || l > stride || l > (len - offb) / 2) {
 			if (printk_ratelimit())
 				usb_err(instance->usbatm, "invalid data length from cm %#x: %d\n",
 					cm, l);
@@ -649,9 +755,6 @@
 {
 	struct cxacru_data *instance = usbatm_instance->driver_data;
 	struct usb_interface *intf = usbatm_instance->usb_intf;
-	/*
-	struct atm_dev *atm_dev = usbatm_instance->atm_dev;
-	*/
 	int ret;
 	int start_polling = 1;
 
@@ -697,6 +800,9 @@
 	mutex_unlock(&instance->poll_state_serialize);
 	mutex_unlock(&instance->adsl_state_serialize);
 
+	printk(KERN_INFO "%s%d: %s %pM\n", atm_dev->type, atm_dev->number,
+			usbatm_instance->description, atm_dev->esi);
+
 	if (start_polling)
 		cxacru_poll_status(&instance->poll_work.work);
 	return 0;
@@ -873,11 +979,9 @@
 
 static void cxacru_upload_firmware(struct cxacru_data *instance,
 				   const struct firmware *fw,
-				   const struct firmware *bp,
-				   const struct firmware *cf)
+				   const struct firmware *bp)
 {
 	int ret;
-	int off;
 	struct usbatm_data *usbatm = instance->usbatm;
 	struct usb_device *usb_dev = usbatm->usb_dev;
 	__le16 signature[] = { usb_dev->descriptor.idVendor,
@@ -911,6 +1015,7 @@
 	}
 
 	/* Firmware */
+	usb_info(usbatm, "loading firmware\n");
 	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
 	if (ret) {
 		usb_err(usbatm, "Firmware upload failed: %d\n", ret);
@@ -919,6 +1024,7 @@
 
 	/* Boot ROM patch */
 	if (instance->modem_type->boot_rom_patch) {
+		usb_info(usbatm, "loading boot ROM patch\n");
 		ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size);
 		if (ret) {
 			usb_err(usbatm, "Boot ROM patching failed: %d\n", ret);
@@ -933,6 +1039,7 @@
 		return;
 	}
 
+	usb_info(usbatm, "starting device\n");
 	if (instance->modem_type->boot_rom_patch) {
 		val = cpu_to_le32(BR_ADDR);
 		ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4);
@@ -958,26 +1065,6 @@
 		usb_err(usbatm, "modem failed to initialize: %d\n", ret);
 		return;
 	}
-
-	/* Load config data (le32), doing one packet at a time */
-	if (cf)
-		for (off = 0; off < cf->size / 4; ) {
-			__le32 buf[CMD_PACKET_SIZE / 4 - 1];
-			int i, len = min_t(int, cf->size / 4 - off, CMD_PACKET_SIZE / 4 / 2 - 1);
-			buf[0] = cpu_to_le32(len);
-			for (i = 0; i < len; i++, off++) {
-				buf[i * 2 + 1] = cpu_to_le32(off);
-				memcpy(buf + i * 2 + 2, cf->data + off * 4, 4);
-			}
-			ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET,
-					(u8 *) buf, len, NULL, 0);
-			if (ret < 0) {
-				usb_err(usbatm, "load config data failed: %d\n", ret);
-				return;
-			}
-		}
-
-	msleep_interruptible(4000);
 }
 
 static int cxacru_find_firmware(struct cxacru_data *instance,
@@ -1003,7 +1090,7 @@
 static int cxacru_heavy_init(struct usbatm_data *usbatm_instance,
 			     struct usb_interface *usb_intf)
 {
-	const struct firmware *fw, *bp, *cf;
+	const struct firmware *fw, *bp;
 	struct cxacru_data *instance = usbatm_instance->driver_data;
 
 	int ret = cxacru_find_firmware(instance, "fw", &fw);
@@ -1021,13 +1108,8 @@
 		}
 	}
 
-	if (cxacru_find_firmware(instance, "cf", &cf))		/* optional */
-		cf = NULL;
+	cxacru_upload_firmware(instance, fw, bp);
 
-	cxacru_upload_firmware(instance, fw, bp, cf);
-
-	if (cf)
-		release_firmware(cf);
 	if (instance->modem_type->boot_rom_patch)
 		release_firmware(bp);
 	release_firmware(fw);
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index fbea856..9b53e8d 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -1333,6 +1333,7 @@
 	if (instance->atm_dev) {
 		sysfs_remove_link(&instance->atm_dev->class_dev.kobj, "device");
 		atm_dev_deregister(instance->atm_dev);
+		instance->atm_dev = NULL;
 	}
 
 	usbatm_put_instance(instance);	/* taken in usbatm_usb_probe */
@@ -1348,7 +1349,7 @@
 {
 	dbg("%s: driver version %s", __func__, DRIVER_VERSION);
 
-	if (sizeof(struct usbatm_control) > sizeof(((struct sk_buff *) 0)->cb)) {
+	if (sizeof(struct usbatm_control) > FIELD_SIZEOF(struct sk_buff, cb)) {
 		printk(KERN_ERR "%s unusable with this kernel!\n", usbatm_driver_name);
 		return -EIO;
 	}
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
index f6f4508..0863f85 100644
--- a/drivers/usb/atm/usbatm.h
+++ b/drivers/usb/atm/usbatm.h
@@ -204,4 +204,19 @@
 	struct urb *urbs[0];
 };
 
+static inline void *to_usbatm_driver_data(struct usb_interface *intf)
+{
+	struct usbatm_data *usbatm_instance;
+
+	if (intf == NULL)
+		return NULL;
+
+	usbatm_instance = usb_get_intfdata(intf);
+
+	if (usbatm_instance == NULL) /* set NULL before unbind() */
+		return NULL;
+
+	return usbatm_instance->driver_data; /* set NULL after unbind() */
+}
+
 #endif	/* _USBATM_H_ */
diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
index 5633bc5..029ee4a 100644
--- a/drivers/usb/c67x00/c67x00-drv.c
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -137,13 +137,13 @@
 	if (!c67x00)
 		return -ENOMEM;
 
-	if (!request_mem_region(res->start, res->end - res->start + 1,
+	if (!request_mem_region(res->start, resource_size(res),
 				pdev->name)) {
 		dev_err(&pdev->dev, "Memory region busy\n");
 		ret = -EBUSY;
 		goto request_mem_failed;
 	}
-	c67x00->hpi.base = ioremap(res->start, res->end - res->start + 1);
+	c67x00->hpi.base = ioremap(res->start, resource_size(res));
 	if (!c67x00->hpi.base) {
 		dev_err(&pdev->dev, "Unable to map HPI registers\n");
 		ret = -EIO;
@@ -182,7 +182,7 @@
  request_irq_failed:
 	iounmap(c67x00->hpi.base);
  map_failed:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
  request_mem_failed:
 	kfree(c67x00);
 
@@ -208,7 +208,7 @@
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res)
-		release_mem_region(res->start, res->end - res->start + 1);
+		release_mem_region(res->start, resource_size(res));
 
 	kfree(c67x00);
 
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 34d4eb9..975d556 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -170,6 +170,7 @@
 {
 	wb->use = 0;
 	acm->transmitting--;
+	usb_autopm_put_interface_async(acm->control);
 }
 
 /*
@@ -211,9 +212,12 @@
 	}
 
 	dbg("%s susp_count: %d", __func__, acm->susp_count);
+	usb_autopm_get_interface_async(acm->control);
 	if (acm->susp_count) {
-		acm->delayed_wb = wb;
-		schedule_work(&acm->waker);
+		if (!acm->delayed_wb)
+			acm->delayed_wb = wb;
+		else
+			usb_autopm_put_interface_async(acm->control);
 		spin_unlock_irqrestore(&acm->write_lock, flags);
 		return 0;	/* A white lie */
 	}
@@ -424,7 +428,6 @@
 		throttled = acm->throttle;
 		spin_unlock_irqrestore(&acm->throttle_lock, flags);
 		if (!throttled) {
-			tty_buffer_request_room(tty, buf->size);
 			tty_insert_flip_string(tty, buf->base, buf->size);
 			tty_flip_buffer_push(tty);
 		} else {
@@ -534,23 +537,6 @@
 	tty_kref_put(tty);
 }
 
-static void acm_waker(struct work_struct *waker)
-{
-	struct acm *acm = container_of(waker, struct acm, waker);
-	int rv;
-
-	rv = usb_autopm_get_interface(acm->control);
-	if (rv < 0) {
-		dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__);
-		return;
-	}
-	if (acm->delayed_wb) {
-		acm_start_wb(acm, acm->delayed_wb);
-		acm->delayed_wb = NULL;
-	}
-	usb_autopm_put_interface(acm->control);
-}
-
 /*
  * TTY handlers
  */
@@ -566,7 +552,7 @@
 
 	acm = acm_table[tty->index];
 	if (!acm || !acm->dev)
-		goto err_out;
+		goto out;
 	else
 		rv = 0;
 
@@ -582,8 +568,9 @@
 
 	mutex_lock(&acm->mutex);
 	if (acm->port.count++) {
+		mutex_unlock(&acm->mutex);
 		usb_autopm_put_interface(acm->control);
-		goto done;
+		goto out;
 	}
 
 	acm->ctrlurb->dev = acm->dev;
@@ -612,18 +599,18 @@
 	set_bit(ASYNCB_INITIALIZED, &acm->port.flags);
 	rv = tty_port_block_til_ready(&acm->port, tty, filp);
 	tasklet_schedule(&acm->urb_task);
-done:
+
 	mutex_unlock(&acm->mutex);
-err_out:
+out:
 	mutex_unlock(&open_mutex);
 	return rv;
 
 full_bailout:
 	usb_kill_urb(acm->ctrlurb);
 bail_out:
-	usb_autopm_put_interface(acm->control);
 	acm->port.count--;
 	mutex_unlock(&acm->mutex);
+	usb_autopm_put_interface(acm->control);
 early_bail:
 	mutex_unlock(&open_mutex);
 	tty_port_tty_set(&acm->port, NULL);
@@ -1023,7 +1010,7 @@
 		case USB_CDC_CALL_MANAGEMENT_TYPE:
 			call_management_function = buffer[3];
 			call_interface_num = buffer[4];
-			if ((call_management_function & 3) != 3)
+			if ( (quirks & NOT_A_MODEM) == 0 && (call_management_function & 3) != 3)
 				dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n");
 			break;
 		default:
@@ -1178,7 +1165,6 @@
 	acm->urb_task.func = acm_rx_tasklet;
 	acm->urb_task.data = (unsigned long) acm;
 	INIT_WORK(&acm->work, acm_softint);
-	INIT_WORK(&acm->waker, acm_waker);
 	init_waitqueue_head(&acm->drain_wait);
 	spin_lock_init(&acm->throttle_lock);
 	spin_lock_init(&acm->write_lock);
@@ -1343,7 +1329,6 @@
 	tasklet_enable(&acm->urb_task);
 
 	cancel_work_sync(&acm->work);
-	cancel_work_sync(&acm->waker);
 }
 
 static void acm_disconnect(struct usb_interface *intf)
@@ -1435,6 +1420,7 @@
 static int acm_resume(struct usb_interface *intf)
 {
 	struct acm *acm = usb_get_intfdata(intf);
+	struct acm_wb *wb;
 	int rv = 0;
 	int cnt;
 
@@ -1449,6 +1435,21 @@
 	mutex_lock(&acm->mutex);
 	if (acm->port.count) {
 		rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
+
+		spin_lock_irq(&acm->write_lock);
+		if (acm->delayed_wb) {
+			wb = acm->delayed_wb;
+			acm->delayed_wb = NULL;
+			spin_unlock_irq(&acm->write_lock);
+			acm_start_wb(acm, acm->delayed_wb);
+		} else {
+			spin_unlock_irq(&acm->write_lock);
+		}
+
+		/*
+		 * delayed error checking because we must
+		 * do the write path at all cost
+		 */
 		if (rv < 0)
 			goto err_out;
 
@@ -1460,6 +1461,23 @@
 	return rv;
 }
 
+static int acm_reset_resume(struct usb_interface *intf)
+{
+	struct acm *acm = usb_get_intfdata(intf);
+	struct tty_struct *tty;
+
+	mutex_lock(&acm->mutex);
+	if (acm->port.count) {
+		tty = tty_port_tty_get(&acm->port);
+		if (tty) {
+			tty_hangup(tty);
+			tty_kref_put(tty);
+		}
+	}
+	mutex_unlock(&acm->mutex);
+	return acm_resume(intf);
+}
+
 #endif /* CONFIG_PM */
 
 #define NOKIA_PCSUITE_ACM_INFO(x) \
@@ -1471,7 +1489,7 @@
  * USB driver structure.
  */
 
-static struct usb_device_id acm_ids[] = {
+static const struct usb_device_id acm_ids[] = {
 	/* quirky and broken devices */
 	{ USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
@@ -1576,6 +1594,11 @@
 
 	/* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */
 
+	/* Support Lego NXT using pbLua firmware */
+	{ USB_DEVICE(0x0694, 0xff00),
+	.driver_info = NOT_A_MODEM,
+       	},
+
 	/* control interfaces with various AT-command sets */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_ACM_PROTO_AT_V25TER) },
@@ -1602,6 +1625,7 @@
 #ifdef CONFIG_PM
 	.suspend =	acm_suspend,
 	.resume =	acm_resume,
+	.reset_resume =	acm_reset_resume,
 #endif
 	.id_table =	acm_ids,
 #ifdef CONFIG_PM
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index c4a0ee8..4a8e87e 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -112,7 +112,6 @@
 	struct mutex mutex;
 	struct usb_cdc_line_coding line;		/* bits, stop, parity */
 	struct work_struct work;			/* work queue entry for line discipline waking up */
-	struct work_struct waker;
 	wait_queue_head_t drain_wait;			/* close processing */
 	struct tasklet_struct urb_task;                 /* rx processing */
 	spinlock_t throttle_lock;			/* synchronize throtteling and read callback */
@@ -137,3 +136,4 @@
 #define NO_UNION_NORMAL			1
 #define SINGLE_RX_URB			2
 #define NO_CAP_LINE			4
+#define NOT_A_MODEM			8
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 3e564bf..18aafcb 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -31,7 +31,7 @@
 #define DRIVER_AUTHOR "Oliver Neukum"
 #define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
 
-static struct usb_device_id wdm_ids[] = {
+static const struct usb_device_id wdm_ids[] = {
 	{
 		.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
 				 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 9bc112e..93b5f85 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -163,7 +163,6 @@
 	unsigned char		used;			/* True if open */
 	unsigned char		present;		/* True if not disconnected */
 	unsigned char		bidir;			/* interface is bidirectional */
-	unsigned char		sleeping;		/* interface is suspended */
 	unsigned char		no_paper;		/* Paper Out happened */
 	unsigned char		*device_id_string;	/* IEEE 1284 DEVICE ID string (ptr) */
 							/* first 2 bytes are (big-endian) length */
@@ -191,7 +190,6 @@
 	dbg("quirks=%d", usblp->quirks);
 	dbg("used=%d", usblp->used);
 	dbg("bidir=%d", usblp->bidir);
-	dbg("sleeping=%d", usblp->sleeping);
 	dbg("device_id_string=\"%s\"",
 		usblp->device_id_string ?
 			usblp->device_id_string + 2 :
@@ -376,7 +374,7 @@
 
 static int handle_bidir (struct usblp *usblp)
 {
-	if (usblp->bidir && usblp->used && !usblp->sleeping) {
+	if (usblp->bidir && usblp->used) {
 		if (usblp_submit_read(usblp) < 0)
 			return -EIO;
 	}
@@ -503,11 +501,6 @@
 		goto done;
 	}
 
-	if (usblp->sleeping) {
-		retval = -ENODEV;
-		goto done;
-	}
-
 	dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd),
 		_IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) );
 
@@ -914,8 +907,6 @@
 		return 0;
 	}
 	spin_unlock_irqrestore(&usblp->lock, flags);
-	if (usblp->sleeping)
-		return -ENODEV;
 	if (nonblock)
 		return -EAGAIN;
 	return 1;
@@ -968,8 +959,6 @@
 		return 0;
 	}
 	spin_unlock_irqrestore(&usblp->lock, flags);
-	if (usblp->sleeping)
-		return -ENODEV;
 	if (nonblock)
 		return -EAGAIN;
 	return 1;
@@ -1377,12 +1366,10 @@
 	mutex_unlock (&usblp_mutex);
 }
 
-static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
+static int usblp_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct usblp *usblp = usb_get_intfdata (intf);
 
-	/* we take no more IO */
-	usblp->sleeping = 1;
 	usblp_unlink_urbs(usblp);
 #if 0 /* XXX Do we want this? What if someone is reading, should we fail? */
 	/* not strictly necessary, but just in case */
@@ -1393,18 +1380,17 @@
 	return 0;
 }
 
-static int usblp_resume (struct usb_interface *intf)
+static int usblp_resume(struct usb_interface *intf)
 {
 	struct usblp *usblp = usb_get_intfdata (intf);
 	int r;
 
-	usblp->sleeping = 0;
 	r = handle_bidir (usblp);
 
 	return r;
 }
 
-static struct usb_device_id usblp_ids [] = {
+static const struct usb_device_id usblp_ids[] = {
 	{ USB_DEVICE_INFO(7, 1, 1) },
 	{ USB_DEVICE_INFO(7, 1, 2) },
 	{ USB_DEVICE_INFO(7, 1, 3) },
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index 7c5f4e3..8588c09 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -48,7 +48,7 @@
  */
 #define USBTMC_MAX_READS_TO_CLEAR_BULK_IN	100
 
-static struct usb_device_id usbtmc_devices[] = {
+static const struct usb_device_id usbtmc_devices[] = {
 	{ USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), },
 	{ USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), },
 	{ 0, } /* terminating entry */
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index ad92594..97a819c 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -91,8 +91,8 @@
 	  If you are unsure about this, say N here.
 
 config USB_SUSPEND
-	bool "USB selective suspend/resume and wakeup"
-	depends on USB && PM
+	bool "USB runtime power management (suspend/resume and wakeup)"
+	depends on USB && PM_RUNTIME
 	help
 	  If you say Y here, you can use driver calls or the sysfs
 	  "power/level" file to suspend or resume individual USB
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 355dffc..d41811b 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -117,12 +117,20 @@
  * However, these will come from functions that return ptrs to each of them.
  */
 
-static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
-static unsigned int conndiscevcnt;
-
-/* this struct stores the poll state for <mountpoint>/devices pollers */
-struct usb_device_status {
-	unsigned int lastev;
+/*
+ * Wait for an connect/disconnect event to happen. We initialize
+ * the event counter with an odd number, and each event will increment
+ * the event counter by two, so it will always _stay_ odd. That means
+ * that it will never be zero, so "event 0" will never match a current
+ * event, and thus 'poll' will always trigger as readable for the first
+ * time it gets called.
+ */
+static struct device_connect_event {
+	atomic_t count;
+	wait_queue_head_t wait;
+} device_event = {
+	.count = ATOMIC_INIT(1),
+	.wait = __WAIT_QUEUE_HEAD_INITIALIZER(device_event.wait)
 };
 
 struct class_info {
@@ -156,8 +164,8 @@
 
 void usbfs_conn_disc_event(void)
 {
-	conndiscevcnt++;
-	wake_up(&deviceconndiscwq);
+	atomic_add(2, &device_event.count);
+	wake_up(&device_event.wait);
 }
 
 static const char *class_decode(const int class)
@@ -629,55 +637,16 @@
 static unsigned int usb_device_poll(struct file *file,
 				    struct poll_table_struct *wait)
 {
-	struct usb_device_status *st = file->private_data;
-	unsigned int mask = 0;
+	unsigned int event_count;
 
-	lock_kernel();
-	if (!st) {
-		st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
+	poll_wait(file, &device_event.wait, wait);
 
-		/* we may have dropped BKL -
-		 * need to check for having lost the race */
-		if (file->private_data) {
-			kfree(st);
-			st = file->private_data;
-			goto lost_race;
-		}
-		/* we haven't lost - check for allocation failure now */
-		if (!st) {
-			unlock_kernel();
-			return POLLIN;
-		}
-
-		/*
-		 * need to prevent the module from being unloaded, since
-		 * proc_unregister does not call the release method and
-		 * we would have a memory leak
-		 */
-		st->lastev = conndiscevcnt;
-		file->private_data = st;
-		mask = POLLIN;
+	event_count = atomic_read(&device_event.count);
+	if (file->f_version != event_count) {
+		file->f_version = event_count;
+		return POLLIN | POLLRDNORM;
 	}
-lost_race:
-	if (file->f_mode & FMODE_READ)
-		poll_wait(file, &deviceconndiscwq, wait);
-	if (st->lastev != conndiscevcnt)
-		mask |= POLLIN;
-	st->lastev = conndiscevcnt;
-	unlock_kernel();
-	return mask;
-}
 
-static int usb_device_open(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-	return 0;
-}
-
-static int usb_device_release(struct inode *inode, struct file *file)
-{
-	kfree(file->private_data);
-	file->private_data = NULL;
 	return 0;
 }
 
@@ -685,7 +654,7 @@
 {
 	loff_t ret;
 
-	lock_kernel();
+	mutex_lock(&file->f_dentry->d_inode->i_mutex);
 
 	switch (orig) {
 	case 0:
@@ -701,7 +670,7 @@
 		ret = -EINVAL;
 	}
 
-	unlock_kernel();
+	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
 	return ret;
 }
 
@@ -709,6 +678,4 @@
 	.llseek =	usb_device_lseek,
 	.read =		usb_device_read,
 	.poll =		usb_device_poll,
-	.open =		usb_device_open,
-	.release =	usb_device_release,
 };
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index a678186..e909ff7 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -122,7 +122,7 @@
 {
 	loff_t ret;
 
-	lock_kernel();
+	mutex_lock(&file->f_dentry->d_inode->i_mutex);
 
 	switch (orig) {
 	case 0:
@@ -138,7 +138,7 @@
 		ret = -EINVAL;
 	}
 
-	unlock_kernel();
+	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
 	return ret;
 }
 
@@ -310,7 +310,8 @@
 
 static void snoop_urb(struct usb_device *udev,
 		void __user *userurb, int pipe, unsigned length,
-		int timeout_or_status, enum snoop_when when)
+		int timeout_or_status, enum snoop_when when,
+		unsigned char *data, unsigned data_len)
 {
 	static const char *types[] = {"isoc", "int", "ctrl", "bulk"};
 	static const char *dirs[] = {"out", "in"};
@@ -344,6 +345,11 @@
 					"status %d\n",
 					ep, t, d, length, timeout_or_status);
 	}
+
+	if (data && data_len > 0) {
+		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1,
+			data, data_len, 1);
+	}
 }
 
 #define AS_CONTINUATION	1
@@ -410,7 +416,9 @@
 	}
 	snoop(&urb->dev->dev, "urb complete\n");
 	snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length,
-			as->status, COMPLETE);
+			as->status, COMPLETE,
+			((urb->transfer_flags & URB_DIR_MASK) == USB_DIR_OUT) ?
+				NULL : urb->transfer_buffer, urb->actual_length);
 	if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET &&
 			as->status != -ENOENT)
 		cancel_bulk_urbs(ps, as->bulk_addr);
@@ -653,20 +661,20 @@
 	const struct cred *cred = current_cred();
 	int ret;
 
-	lock_kernel();
-	/* Protect against simultaneous removal or release */
-	mutex_lock(&usbfs_mutex);
-
 	ret = -ENOMEM;
 	ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL);
 	if (!ps)
-		goto out;
+		goto out_free_ps;
 
 	ret = -ENODEV;
 
+	/* Protect against simultaneous removal or release */
+	mutex_lock(&usbfs_mutex);
+
 	/* usbdev device-node */
 	if (imajor(inode) == USB_DEVICE_MAJOR)
 		dev = usbdev_lookup_by_devt(inode->i_rdev);
+
 #ifdef CONFIG_USB_DEVICEFS
 	/* procfs file */
 	if (!dev) {
@@ -678,13 +686,19 @@
 			dev = NULL;
 	}
 #endif
-	if (!dev || dev->state == USB_STATE_NOTATTACHED)
-		goto out;
+	mutex_unlock(&usbfs_mutex);
+
+	if (!dev)
+		goto out_free_ps;
+
+	usb_lock_device(dev);
+	if (dev->state == USB_STATE_NOTATTACHED)
+		goto out_unlock_device;
+
 	ret = usb_autoresume_device(dev);
 	if (ret)
-		goto out;
+		goto out_unlock_device;
 
-	ret = 0;
 	ps->dev = dev;
 	ps->file = file;
 	spin_lock_init(&ps->lock);
@@ -702,15 +716,16 @@
 	smp_wmb();
 	list_add_tail(&ps->list, &dev->filelist);
 	file->private_data = ps;
+	usb_unlock_device(dev);
 	snoop(&dev->dev, "opened by process %d: %s\n", task_pid_nr(current),
 			current->comm);
- out:
-	if (ret) {
-		kfree(ps);
-		usb_put_dev(dev);
-	}
-	mutex_unlock(&usbfs_mutex);
-	unlock_kernel();
+	return ret;
+
+ out_unlock_device:
+	usb_unlock_device(dev);
+	usb_put_dev(dev);
+ out_free_ps:
+	kfree(ps);
 	return ret;
 }
 
@@ -724,10 +739,7 @@
 	usb_lock_device(dev);
 	usb_hub_release_all_ports(dev, ps);
 
-	/* Protect against simultaneous open */
-	mutex_lock(&usbfs_mutex);
 	list_del_init(&ps->list);
-	mutex_unlock(&usbfs_mutex);
 
 	for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed);
 			ifnum++) {
@@ -770,6 +782,13 @@
 	if (!tbuf)
 		return -ENOMEM;
 	tmo = ctrl.timeout;
+	snoop(&dev->dev, "control urb: bRequestType=%02x "
+		"bRequest=%02x wValue=%04x "
+		"wIndex=%04x wLength=%04x\n",
+		ctrl.bRequestType, ctrl.bRequest,
+		__le16_to_cpup(&ctrl.wValue),
+		__le16_to_cpup(&ctrl.wIndex),
+		__le16_to_cpup(&ctrl.wLength));
 	if (ctrl.bRequestType & 0x80) {
 		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data,
 					       ctrl.wLength)) {
@@ -777,15 +796,15 @@
 			return -EINVAL;
 		}
 		pipe = usb_rcvctrlpipe(dev, 0);
-		snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT);
+		snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, NULL, 0);
 
 		usb_unlock_device(dev);
 		i = usb_control_msg(dev, pipe, ctrl.bRequest,
 				    ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
 				    tbuf, ctrl.wLength, tmo);
 		usb_lock_device(dev);
-		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE);
-
+		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE,
+			tbuf, i);
 		if ((i > 0) && ctrl.wLength) {
 			if (copy_to_user(ctrl.data, tbuf, i)) {
 				free_page((unsigned long)tbuf);
@@ -800,14 +819,15 @@
 			}
 		}
 		pipe = usb_sndctrlpipe(dev, 0);
-		snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT);
+		snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT,
+			tbuf, ctrl.wLength);
 
 		usb_unlock_device(dev);
 		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest,
 				    ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
 				    tbuf, ctrl.wLength, tmo);
 		usb_lock_device(dev);
-		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE);
+		snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0);
 	}
 	free_page((unsigned long)tbuf);
 	if (i < 0 && i != -EPIPE) {
@@ -853,12 +873,12 @@
 			kfree(tbuf);
 			return -EINVAL;
 		}
-		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT);
+		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0);
 
 		usb_unlock_device(dev);
 		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
 		usb_lock_device(dev);
-		snoop_urb(dev, NULL, pipe, len2, i, COMPLETE);
+		snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, tbuf, len2);
 
 		if (!i && len2) {
 			if (copy_to_user(bulk.data, tbuf, len2)) {
@@ -873,12 +893,12 @@
 				return -EFAULT;
 			}
 		}
-		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT);
+		snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1);
 
 		usb_unlock_device(dev);
 		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
 		usb_lock_device(dev);
-		snoop_urb(dev, NULL, pipe, len2, i, COMPLETE);
+		snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0);
 	}
 	kfree(tbuf);
 	if (i < 0)
@@ -1097,6 +1117,13 @@
 			is_in = 0;
 			uurb->endpoint &= ~USB_DIR_IN;
 		}
+		snoop(&ps->dev->dev, "control urb: bRequestType=%02x "
+			"bRequest=%02x wValue=%04x "
+			"wIndex=%04x wLength=%04x\n",
+			dr->bRequestType, dr->bRequest,
+			__le16_to_cpup(&dr->wValue),
+			__le16_to_cpup(&dr->wIndex),
+			__le16_to_cpup(&dr->wLength));
 		break;
 
 	case USBDEVFS_URB_TYPE_BULK:
@@ -1104,13 +1131,25 @@
 		case USB_ENDPOINT_XFER_CONTROL:
 		case USB_ENDPOINT_XFER_ISOC:
 			return -EINVAL;
-		/* allow single-shot interrupt transfers, at bogus rates */
+		case USB_ENDPOINT_XFER_INT:
+			/* allow single-shot interrupt transfers */
+			uurb->type = USBDEVFS_URB_TYPE_INTERRUPT;
+			goto interrupt_urb;
 		}
 		uurb->number_of_packets = 0;
 		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
 			return -EINVAL;
 		break;
 
+	case USBDEVFS_URB_TYPE_INTERRUPT:
+		if (!usb_endpoint_xfer_int(&ep->desc))
+			return -EINVAL;
+ interrupt_urb:
+		uurb->number_of_packets = 0;
+		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+			return -EINVAL;
+		break;
+
 	case USBDEVFS_URB_TYPE_ISO:
 		/* arbitrary limit */
 		if (uurb->number_of_packets < 1 ||
@@ -1143,14 +1182,6 @@
 		uurb->buffer_length = totlen;
 		break;
 
-	case USBDEVFS_URB_TYPE_INTERRUPT:
-		uurb->number_of_packets = 0;
-		if (!usb_endpoint_xfer_int(&ep->desc))
-			return -EINVAL;
-		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
-			return -EINVAL;
-		break;
-
 	default:
 		return -EINVAL;
 	}
@@ -1236,7 +1267,9 @@
 		}
 	}
 	snoop_urb(ps->dev, as->userurb, as->urb->pipe,
-			as->urb->transfer_buffer_length, 0, SUBMIT);
+			as->urb->transfer_buffer_length, 0, SUBMIT,
+			is_in ? NULL : as->urb->transfer_buffer,
+				uurb->buffer_length);
 	async_newpending(as);
 
 	if (usb_endpoint_xfer_bulk(&ep->desc)) {
@@ -1274,7 +1307,7 @@
 		dev_printk(KERN_DEBUG, &ps->dev->dev,
 			   "usbfs: usb_submit_urb returned %d\n", ret);
 		snoop_urb(ps->dev, as->userurb, as->urb->pipe,
-				0, ret, COMPLETE);
+				0, ret, COMPLETE, NULL, 0);
 		async_removepending(as);
 		free_async(as);
 		return ret;
@@ -1628,7 +1661,10 @@
 		if (driver == NULL || driver->ioctl == NULL) {
 			retval = -ENOTTY;
 		} else {
+			/* keep API that guarantees BKL */
+			lock_kernel();
 			retval = driver->ioctl(intf, ctl->ioctl_code, buf);
+			unlock_kernel();
 			if (retval == -ENOIOCTLCMD)
 				retval = -ENOTTY;
 		}
@@ -1711,6 +1747,7 @@
 
 	if (!(file->f_mode & FMODE_WRITE))
 		return -EPERM;
+
 	usb_lock_device(dev);
 	if (!connected(ps)) {
 		usb_unlock_device(dev);
@@ -1877,9 +1914,7 @@
 {
 	int ret;
 
-	lock_kernel();
 	ret = usbdev_do_ioctl(file, cmd, (void __user *)arg);
-	unlock_kernel();
 
 	return ret;
 }
@@ -1890,9 +1925,7 @@
 {
 	int ret;
 
-	lock_kernel();
 	ret = usbdev_do_ioctl(file, cmd, compat_ptr(arg));
-	unlock_kernel();
 
 	return ret;
 }
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index f2f055e..f3c2338 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -25,7 +25,7 @@
 #include <linux/device.h>
 #include <linux/usb.h>
 #include <linux/usb/quirks.h>
-#include <linux/workqueue.h>
+#include <linux/pm_runtime.h>
 #include "hcd.h"
 #include "usb.h"
 
@@ -221,7 +221,7 @@
 {
 	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
 	struct usb_device *udev = to_usb_device(dev);
-	int error = -ENODEV;
+	int error = 0;
 
 	dev_dbg(dev, "%s\n", __func__);
 
@@ -230,18 +230,23 @@
 	/* The device should always appear to be in use
 	 * unless the driver suports autosuspend.
 	 */
-	udev->pm_usage_cnt = !(udriver->supports_autosuspend);
+	if (!udriver->supports_autosuspend)
+		error = usb_autoresume_device(udev);
 
-	error = udriver->probe(udev);
+	if (!error)
+		error = udriver->probe(udev);
 	return error;
 }
 
 /* called from driver core with dev locked */
 static int usb_unbind_device(struct device *dev)
 {
+	struct usb_device *udev = to_usb_device(dev);
 	struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
 
-	udriver->disconnect(to_usb_device(dev));
+	udriver->disconnect(udev);
+	if (!udriver->supports_autosuspend)
+		usb_autosuspend_device(udev);
 	return 0;
 }
 
@@ -274,60 +279,62 @@
 	intf->needs_binding = 0;
 
 	if (usb_device_is_owned(udev))
-		return -ENODEV;
+		return error;
 
 	if (udev->authorized == 0) {
 		dev_err(&intf->dev, "Device is not authorized for usage\n");
-		return -ENODEV;
+		return error;
 	}
 
 	id = usb_match_id(intf, driver->id_table);
 	if (!id)
 		id = usb_match_dynamic_id(intf, driver);
-	if (id) {
-		dev_dbg(dev, "%s - got id\n", __func__);
+	if (!id)
+		return error;
 
-		error = usb_autoresume_device(udev);
-		if (error)
-			return error;
+	dev_dbg(dev, "%s - got id\n", __func__);
 
-		/* Interface "power state" doesn't correspond to any hardware
-		 * state whatsoever.  We use it to record when it's bound to
-		 * a driver that may start I/0:  it's not frozen/quiesced.
-		 */
-		mark_active(intf);
-		intf->condition = USB_INTERFACE_BINDING;
+	error = usb_autoresume_device(udev);
+	if (error)
+		return error;
 
-		/* The interface should always appear to be in use
-		 * unless the driver suports autosuspend.
-		 */
-		atomic_set(&intf->pm_usage_cnt, !driver->supports_autosuspend);
+	intf->condition = USB_INTERFACE_BINDING;
 
-		/* Carry out a deferred switch to altsetting 0 */
-		if (intf->needs_altsetting0) {
-			error = usb_set_interface(udev, intf->altsetting[0].
-					desc.bInterfaceNumber, 0);
-			if (error < 0)
-				goto err;
+	/* Bound interfaces are initially active.  They are
+	 * runtime-PM-enabled only if the driver has autosuspend support.
+	 * They are sensitive to their children's power states.
+	 */
+	pm_runtime_set_active(dev);
+	pm_suspend_ignore_children(dev, false);
+	if (driver->supports_autosuspend)
+		pm_runtime_enable(dev);
 
-			intf->needs_altsetting0 = 0;
-		}
-
-		error = driver->probe(intf, id);
-		if (error)
+	/* Carry out a deferred switch to altsetting 0 */
+	if (intf->needs_altsetting0) {
+		error = usb_set_interface(udev, intf->altsetting[0].
+				desc.bInterfaceNumber, 0);
+		if (error < 0)
 			goto err;
-
-		intf->condition = USB_INTERFACE_BOUND;
-		usb_autosuspend_device(udev);
+		intf->needs_altsetting0 = 0;
 	}
 
+	error = driver->probe(intf, id);
+	if (error)
+		goto err;
+
+	intf->condition = USB_INTERFACE_BOUND;
+	usb_autosuspend_device(udev);
 	return error;
 
-err:
-	mark_quiesced(intf);
+ err:
 	intf->needs_remote_wakeup = 0;
 	intf->condition = USB_INTERFACE_UNBOUND;
 	usb_cancel_queued_reset(intf);
+
+	/* Unbound interfaces are always runtime-PM-disabled and -suspended */
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+
 	usb_autosuspend_device(udev);
 	return error;
 }
@@ -377,9 +384,17 @@
 	usb_set_intfdata(intf, NULL);
 
 	intf->condition = USB_INTERFACE_UNBOUND;
-	mark_quiesced(intf);
 	intf->needs_remote_wakeup = 0;
 
+	/* Unbound interfaces are always runtime-PM-disabled and -suspended */
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+
+	/* Undo any residual pm_autopm_get_interface_* calls */
+	for (r = atomic_read(&intf->pm_usage_cnt); r > 0; --r)
+		usb_autopm_put_interface_no_suspend(intf);
+	atomic_set(&intf->pm_usage_cnt, 0);
+
 	if (!error)
 		usb_autosuspend_device(udev);
 
@@ -410,7 +425,6 @@
 				struct usb_interface *iface, void *priv)
 {
 	struct device *dev = &iface->dev;
-	struct usb_device *udev = interface_to_usbdev(iface);
 	int retval = 0;
 
 	if (dev->driver)
@@ -420,11 +434,16 @@
 	usb_set_intfdata(iface, priv);
 	iface->needs_binding = 0;
 
-	usb_pm_lock(udev);
 	iface->condition = USB_INTERFACE_BOUND;
-	mark_active(iface);
-	atomic_set(&iface->pm_usage_cnt, !driver->supports_autosuspend);
-	usb_pm_unlock(udev);
+
+	/* Bound interfaces are initially active.  They are
+	 * runtime-PM-enabled only if the driver has autosuspend support.
+	 * They are sensitive to their children's power states.
+	 */
+	pm_runtime_set_active(dev);
+	pm_suspend_ignore_children(dev, false);
+	if (driver->supports_autosuspend)
+		pm_runtime_enable(dev);
 
 	/* if interface was already added, bind now; else let
 	 * the future device_add() bind it, bypassing probe()
@@ -470,10 +489,10 @@
 	if (device_is_registered(dev)) {
 		device_release_driver(dev);
 	} else {
-		down(&dev->sem);
+		device_lock(dev);
 		usb_unbind_interface(dev);
 		dev->driver = NULL;
-		up(&dev->sem);
+		device_unlock(dev);
 	}
 }
 EXPORT_SYMBOL_GPL(usb_driver_release_interface);
@@ -691,9 +710,6 @@
 {
 	struct usb_device *usb_dev;
 
-	/* driver is often null here; dev_dbg() would oops */
-	pr_debug("usb %s: uevent\n", dev_name(dev));
-
 	if (is_usb_device(dev)) {
 		usb_dev = to_usb_device(dev);
 	} else if (is_usb_interface(dev)) {
@@ -705,6 +721,7 @@
 	}
 
 	if (usb_dev->devnum < 0) {
+		/* driver is often null here; dev_dbg() would oops */
 		pr_debug("usb %s: already deleted?\n", dev_name(dev));
 		return -ENODEV;
 	}
@@ -983,7 +1000,6 @@
 	}
 }
 
-/* Caller has locked udev's pm_mutex */
 static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
 {
 	struct usb_device_driver	*udriver;
@@ -1007,7 +1023,6 @@
 	return status;
 }
 
-/* Caller has locked udev's pm_mutex */
 static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
 {
 	struct usb_device_driver	*udriver;
@@ -1041,27 +1056,20 @@
 	return status;
 }
 
-/* Caller has locked intf's usb_device's pm mutex */
 static int usb_suspend_interface(struct usb_device *udev,
 		struct usb_interface *intf, pm_message_t msg)
 {
 	struct usb_driver	*driver;
 	int			status = 0;
 
-	/* with no hardware, USB interfaces only use FREEZE and ON states */
-	if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
-		goto done;
-
-	/* This can happen; see usb_driver_release_interface() */
-	if (intf->condition == USB_INTERFACE_UNBOUND)
+	if (udev->state == USB_STATE_NOTATTACHED ||
+			intf->condition == USB_INTERFACE_UNBOUND)
 		goto done;
 	driver = to_usb_driver(intf->dev.driver);
 
 	if (driver->suspend) {
 		status = driver->suspend(intf, msg);
-		if (status == 0)
-			mark_quiesced(intf);
-		else if (!(msg.event & PM_EVENT_AUTO))
+		if (status && !(msg.event & PM_EVENT_AUTO))
 			dev_err(&intf->dev, "%s error %d\n",
 					"suspend", status);
 	} else {
@@ -1069,7 +1077,6 @@
 		intf->needs_binding = 1;
 		dev_warn(&intf->dev, "no %s for driver %s?\n",
 				"suspend", driver->name);
-		mark_quiesced(intf);
 	}
 
  done:
@@ -1077,14 +1084,13 @@
 	return status;
 }
 
-/* Caller has locked intf's usb_device's pm_mutex */
 static int usb_resume_interface(struct usb_device *udev,
 		struct usb_interface *intf, pm_message_t msg, int reset_resume)
 {
 	struct usb_driver	*driver;
 	int			status = 0;
 
-	if (udev->state == USB_STATE_NOTATTACHED || is_active(intf))
+	if (udev->state == USB_STATE_NOTATTACHED)
 		goto done;
 
 	/* Don't let autoresume interfere with unbinding */
@@ -1135,90 +1141,11 @@
 
 done:
 	dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
-	if (status == 0 && intf->condition == USB_INTERFACE_BOUND)
-		mark_active(intf);
 
 	/* Later we will unbind the driver and/or reprobe, if necessary */
 	return status;
 }
 
-#ifdef	CONFIG_USB_SUSPEND
-
-/* Internal routine to check whether we may autosuspend a device. */
-static int autosuspend_check(struct usb_device *udev, int reschedule)
-{
-	int			i;
-	struct usb_interface	*intf;
-	unsigned long		suspend_time, j;
-
-	/* For autosuspend, fail fast if anything is in use or autosuspend
-	 * is disabled.  Also fail if any interfaces require remote wakeup
-	 * but it isn't available.
-	 */
-	if (udev->pm_usage_cnt > 0)
-		return -EBUSY;
-	if (udev->autosuspend_delay < 0 || udev->autosuspend_disabled)
-		return -EPERM;
-
-	suspend_time = udev->last_busy + udev->autosuspend_delay;
-	if (udev->actconfig) {
-		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-			intf = udev->actconfig->interface[i];
-			if (!is_active(intf))
-				continue;
-			if (atomic_read(&intf->pm_usage_cnt) > 0)
-				return -EBUSY;
-			if (intf->needs_remote_wakeup &&
-					!udev->do_remote_wakeup) {
-				dev_dbg(&udev->dev, "remote wakeup needed "
-						"for autosuspend\n");
-				return -EOPNOTSUPP;
-			}
-
-			/* Don't allow autosuspend if the device will need
-			 * a reset-resume and any of its interface drivers
-			 * doesn't include support.
-			 */
-			if (udev->quirks & USB_QUIRK_RESET_RESUME) {
-				struct usb_driver *driver;
-
-				driver = to_usb_driver(intf->dev.driver);
-				if (!driver->reset_resume ||
-				    intf->needs_remote_wakeup)
-					return -EOPNOTSUPP;
-			}
-		}
-	}
-
-	/* If everything is okay but the device hasn't been idle for long
-	 * enough, queue a delayed autosuspend request.  If the device
-	 * _has_ been idle for long enough and the reschedule flag is set,
-	 * likewise queue a delayed (1 second) autosuspend request.
-	 */
-	j = jiffies;
-	if (time_before(j, suspend_time))
-		reschedule = 1;
-	else
-		suspend_time = j + HZ;
-	if (reschedule) {
-		if (!timer_pending(&udev->autosuspend.timer)) {
-			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
-				round_jiffies_up_relative(suspend_time - j));
-		}
-		return -EAGAIN;
-	}
-	return 0;
-}
-
-#else
-
-static inline int autosuspend_check(struct usb_device *udev, int reschedule)
-{
-	return 0;
-}
-
-#endif	/* CONFIG_USB_SUSPEND */
-
 /**
  * usb_suspend_both - suspend a USB device and its interfaces
  * @udev: the usb_device to suspend
@@ -1230,27 +1157,12 @@
  * all the interfaces which were suspended are resumed so that they remain
  * in the same state as the device.
  *
- * If an autosuspend is in progress the routine checks first to make sure
- * that neither the device itself or any of its active interfaces is in use
- * (pm_usage_cnt is greater than 0).  If they are, the autosuspend fails.
- *
- * If the suspend succeeds, the routine recursively queues an autosuspend
- * request for @udev's parent device, thereby propagating the change up
- * the device tree.  If all of the parent's children are now suspended,
- * the parent will autosuspend in turn.
- *
- * The suspend method calls are subject to mutual exclusion under control
- * of @udev's pm_mutex.  Many of these calls are also under the protection
- * of @udev's device lock (including all requests originating outside the
- * USB subsystem), but autosuspend requests generated by a child device or
- * interface driver may not be.  Usbcore will insure that the method calls
- * do not arrive during bind, unbind, or reset operations.  However, drivers
- * must be prepared to handle suspend calls arriving at unpredictable times.
- * The only way to block such calls is to do an autoresume (preventing
- * autosuspends) while holding @udev's device lock (preventing outside
- * suspends).
- *
- * The caller must hold @udev->pm_mutex.
+ * Autosuspend requests originating from a child device or an interface
+ * driver may be made without the protection of @udev's device lock, but
+ * all other suspend calls will hold the lock.  Usbcore will insure that
+ * method calls do not arrive during bind, unbind, or reset operations.
+ * However drivers must be prepared to handle suspend calls arriving at
+ * unpredictable times.
  *
  * This routine can run only in process context.
  */
@@ -1259,20 +1171,11 @@
 	int			status = 0;
 	int			i = 0;
 	struct usb_interface	*intf;
-	struct usb_device	*parent = udev->parent;
 
 	if (udev->state == USB_STATE_NOTATTACHED ||
 			udev->state == USB_STATE_SUSPENDED)
 		goto done;
 
-	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
-
-	if (msg.event & PM_EVENT_AUTO) {
-		status = autosuspend_check(udev, 0);
-		if (status < 0)
-			goto done;
-	}
-
 	/* Suspend all the interfaces and then udev itself */
 	if (udev->actconfig) {
 		for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
@@ -1287,35 +1190,21 @@
 
 	/* If the suspend failed, resume interfaces that did get suspended */
 	if (status != 0) {
-		pm_message_t msg2;
-
-		msg2.event = msg.event ^ (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
+		msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
 		while (--i >= 0) {
 			intf = udev->actconfig->interface[i];
-			usb_resume_interface(udev, intf, msg2, 0);
+			usb_resume_interface(udev, intf, msg, 0);
 		}
 
-		/* Try another autosuspend when the interfaces aren't busy */
-		if (msg.event & PM_EVENT_AUTO)
-			autosuspend_check(udev, status == -EBUSY);
-
-	/* If the suspend succeeded then prevent any more URB submissions,
-	 * flush any outstanding URBs, and propagate the suspend up the tree.
+	/* If the suspend succeeded then prevent any more URB submissions
+	 * and flush any outstanding URBs.
 	 */
 	} else {
-		cancel_delayed_work(&udev->autosuspend);
 		udev->can_submit = 0;
 		for (i = 0; i < 16; ++i) {
 			usb_hcd_flush_endpoint(udev, udev->ep_out[i]);
 			usb_hcd_flush_endpoint(udev, udev->ep_in[i]);
 		}
-
-		/* If this is just a FREEZE or a PRETHAW, udev might
-		 * not really be suspended.  Only true suspends get
-		 * propagated up the device tree.
-		 */
-		if (parent && udev->state == USB_STATE_SUSPENDED)
-			usb_autosuspend_device(parent);
 	}
 
  done:
@@ -1332,23 +1221,12 @@
  * the resume method for @udev and then calls the resume methods for all
  * the interface drivers in @udev.
  *
- * Before starting the resume, the routine calls itself recursively for
- * the parent device of @udev, thereby propagating the change up the device
- * tree and assuring that @udev will be able to resume.  If the parent is
- * unable to resume successfully, the routine fails.
- *
- * The resume method calls are subject to mutual exclusion under control
- * of @udev's pm_mutex.  Many of these calls are also under the protection
- * of @udev's device lock (including all requests originating outside the
- * USB subsystem), but autoresume requests generated by a child device or
- * interface driver may not be.  Usbcore will insure that the method calls
- * do not arrive during bind, unbind, or reset operations.  However, drivers
- * must be prepared to handle resume calls arriving at unpredictable times.
- * The only way to block such calls is to do an autoresume (preventing
- * other autoresumes) while holding @udev's device lock (preventing outside
- * resumes).
- *
- * The caller must hold @udev->pm_mutex.
+ * Autoresume requests originating from a child device or an interface
+ * driver may be made without the protection of @udev's device lock, but
+ * all other resume calls will hold the lock.  Usbcore will insure that
+ * method calls do not arrive during bind, unbind, or reset operations.
+ * However drivers must be prepared to handle resume calls arriving at
+ * unpredictable times.
  *
  * This routine can run only in process context.
  */
@@ -1357,48 +1235,18 @@
 	int			status = 0;
 	int			i;
 	struct usb_interface	*intf;
-	struct usb_device	*parent = udev->parent;
 
-	cancel_delayed_work(&udev->autosuspend);
 	if (udev->state == USB_STATE_NOTATTACHED) {
 		status = -ENODEV;
 		goto done;
 	}
 	udev->can_submit = 1;
 
-	/* Propagate the resume up the tree, if necessary */
-	if (udev->state == USB_STATE_SUSPENDED) {
-		if (parent) {
-			status = usb_autoresume_device(parent);
-			if (status == 0) {
-				status = usb_resume_device(udev, msg);
-				if (status || udev->state ==
-						USB_STATE_NOTATTACHED) {
-					usb_autosuspend_device(parent);
-
-					/* It's possible usb_resume_device()
-					 * failed after the port was
-					 * unsuspended, causing udev to be
-					 * logically disconnected.  We don't
-					 * want usb_disconnect() to autosuspend
-					 * the parent again, so tell it that
-					 * udev disconnected while still
-					 * suspended. */
-					if (udev->state ==
-							USB_STATE_NOTATTACHED)
-						udev->discon_suspended = 1;
-				}
-			}
-		} else {
-
-			/* We can't progagate beyond the USB subsystem,
-			 * so if a root hub's controller is suspended
-			 * then we're stuck. */
-			status = usb_resume_device(udev, msg);
-		}
-	} else if (udev->reset_resume)
+	/* Resume the device */
+	if (udev->state == USB_STATE_SUSPENDED || udev->reset_resume)
 		status = usb_resume_device(udev, msg);
 
+	/* Resume the interfaces */
 	if (status == 0 && udev->actconfig) {
 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
 			intf = udev->actconfig->interface[i];
@@ -1414,55 +1262,94 @@
 	return status;
 }
 
-#ifdef CONFIG_USB_SUSPEND
-
-/* Internal routine to adjust a device's usage counter and change
- * its autosuspend state.
- */
-static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+/* The device lock is held by the PM core */
+int usb_suspend(struct device *dev, pm_message_t msg)
 {
-	int	status = 0;
+	struct usb_device	*udev = to_usb_device(dev);
 
-	usb_pm_lock(udev);
-	udev->pm_usage_cnt += inc_usage_cnt;
-	WARN_ON(udev->pm_usage_cnt < 0);
-	if (inc_usage_cnt)
-		udev->last_busy = jiffies;
-	if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
-		if (udev->state == USB_STATE_SUSPENDED)
-			status = usb_resume_both(udev, PMSG_AUTO_RESUME);
-		if (status != 0)
-			udev->pm_usage_cnt -= inc_usage_cnt;
-		else if (inc_usage_cnt)
+	do_unbind_rebind(udev, DO_UNBIND);
+	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+	return usb_suspend_both(udev, msg);
+}
+
+/* The device lock is held by the PM core */
+int usb_resume(struct device *dev, pm_message_t msg)
+{
+	struct usb_device	*udev = to_usb_device(dev);
+	int			status;
+
+	/* For PM complete calls, all we do is rebind interfaces */
+	if (msg.event == PM_EVENT_ON) {
+		if (udev->state != USB_STATE_NOTATTACHED)
+			do_unbind_rebind(udev, DO_REBIND);
+		status = 0;
+
+	/* For all other calls, take the device back to full power and
+	 * tell the PM core in case it was autosuspended previously.
+	 */
+	} else {
+		status = usb_resume_both(udev, msg);
+		if (status == 0) {
+			pm_runtime_disable(dev);
+			pm_runtime_set_active(dev);
+			pm_runtime_enable(dev);
 			udev->last_busy = jiffies;
-	} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {
-		status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+		}
 	}
-	usb_pm_unlock(udev);
+
+	/* Avoid PM error messages for devices disconnected while suspended
+	 * as we'll display regular disconnect messages just a bit later.
+	 */
+	if (status == -ENODEV)
+		status = 0;
 	return status;
 }
 
-/* usb_autosuspend_work - callback routine to autosuspend a USB device */
-void usb_autosuspend_work(struct work_struct *work)
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_USB_SUSPEND
+
+/**
+ * usb_enable_autosuspend - allow a USB device to be autosuspended
+ * @udev: the USB device which may be autosuspended
+ *
+ * This routine allows @udev to be autosuspended.  An autosuspend won't
+ * take place until the autosuspend_delay has elapsed and all the other
+ * necessary conditions are satisfied.
+ *
+ * The caller must hold @udev's device lock.
+ */
+int usb_enable_autosuspend(struct usb_device *udev)
 {
-	struct usb_device *udev =
-		container_of(work, struct usb_device, autosuspend.work);
-
-	usb_autopm_do_device(udev, 0);
+	if (udev->autosuspend_disabled) {
+		udev->autosuspend_disabled = 0;
+		usb_autosuspend_device(udev);
+	}
+	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_enable_autosuspend);
 
-/* usb_autoresume_work - callback routine to autoresume a USB device */
-void usb_autoresume_work(struct work_struct *work)
+/**
+ * usb_disable_autosuspend - prevent a USB device from being autosuspended
+ * @udev: the USB device which may not be autosuspended
+ *
+ * This routine prevents @udev from being autosuspended and wakes it up
+ * if it is already autosuspended.
+ *
+ * The caller must hold @udev's device lock.
+ */
+int usb_disable_autosuspend(struct usb_device *udev)
 {
-	struct usb_device *udev =
-		container_of(work, struct usb_device, autoresume);
+	int rc = 0;
 
-	/* Wake it up, let the drivers do their thing, and then put it
-	 * back to sleep.
-	 */
-	if (usb_autopm_do_device(udev, 1) == 0)
-		usb_autopm_do_device(udev, -1);
+	if (!udev->autosuspend_disabled) {
+		rc = usb_autoresume_device(udev);
+		if (rc == 0)
+			udev->autosuspend_disabled = 1;
+	}
+	return rc;
 }
+EXPORT_SYMBOL_GPL(usb_disable_autosuspend);
 
 /**
  * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
@@ -1472,15 +1359,11 @@
  * @udev and wants to allow it to autosuspend.  Examples would be when
  * @udev's device file in usbfs is closed or after a configuration change.
  *
- * @udev's usage counter is decremented.  If it or any of the usage counters
- * for an active interface is greater than 0, no autosuspend request will be
- * queued.  (If an interface driver does not support autosuspend then its
- * usage counter is permanently positive.)  Furthermore, if an interface
- * driver requires remote-wakeup capability during autosuspend but remote
- * wakeup is disabled, the autosuspend will fail.
+ * @udev's usage counter is decremented; if it drops to 0 and all the
+ * interfaces are inactive then a delayed autosuspend will be attempted.
+ * The attempt may fail (see autosuspend_check()).
  *
- * Often the caller will hold @udev's device lock, but this is not
- * necessary.
+ * The caller must hold @udev's device lock.
  *
  * This routine can run only in process context.
  */
@@ -1488,9 +1371,11 @@
 {
 	int	status;
 
-	status = usb_autopm_do_device(udev, -1);
-	dev_vdbg(&udev->dev, "%s: cnt %d\n",
-			__func__, udev->pm_usage_cnt);
+	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);
 }
 
 /**
@@ -1500,17 +1385,22 @@
  * This routine should be called when a core subsystem thinks @udev may
  * be ready to autosuspend.
  *
- * @udev's usage counter left unchanged.  If it or any of the usage counters
- * for an active interface is greater than 0, or autosuspend is not allowed
- * for any other reason, no autosuspend request will be queued.
+ * @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)
 {
-	usb_autopm_do_device(udev, 0);
-	dev_vdbg(&udev->dev, "%s: cnt %d\n",
-			__func__, udev->pm_usage_cnt);
+	int	status;
+
+	status = pm_runtime_idle(&udev->dev);
+	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
+			__func__, atomic_read(&udev->dev.power.usage_count),
+			status);
 }
 
 /**
@@ -1519,16 +1409,15 @@
  *
  * This routine should be called when a core subsystem wants to use @udev
  * and needs to guarantee that it is not suspended.  No autosuspend will
- * occur until usb_autosuspend_device is called.  (Note that this will not
- * prevent suspend events originating in the PM core.)  Examples would be
- * when @udev's device file in usbfs is opened or when a remote-wakeup
+ * occur until usb_autosuspend_device() is called.  (Note that this will
+ * not prevent suspend events originating in the PM core.)  Examples would
+ * be when @udev's device file in usbfs is opened or when a remote-wakeup
  * request is received.
  *
  * @udev's usage counter is incremented to prevent subsequent autosuspends.
  * However if the autoresume fails then the usage counter is re-decremented.
  *
- * Often the caller will hold @udev's device lock, but this is not
- * necessary (and attempting it might cause deadlock).
+ * The caller must hold @udev's device lock.
  *
  * This routine can run only in process context.
  */
@@ -1536,42 +1425,14 @@
 {
 	int	status;
 
-	status = usb_autopm_do_device(udev, 1);
-	dev_vdbg(&udev->dev, "%s: status %d cnt %d\n",
-			__func__, status, udev->pm_usage_cnt);
-	return status;
-}
-
-/* Internal routine to adjust an interface's usage counter and change
- * its device's autosuspend state.
- */
-static int usb_autopm_do_interface(struct usb_interface *intf,
-		int inc_usage_cnt)
-{
-	struct usb_device	*udev = interface_to_usbdev(intf);
-	int			status = 0;
-
-	usb_pm_lock(udev);
-	if (intf->condition == USB_INTERFACE_UNBOUND)
-		status = -ENODEV;
-	else {
-		atomic_add(inc_usage_cnt, &intf->pm_usage_cnt);
-		udev->last_busy = jiffies;
-		if (inc_usage_cnt >= 0 &&
-				atomic_read(&intf->pm_usage_cnt) > 0) {
-			if (udev->state == USB_STATE_SUSPENDED)
-				status = usb_resume_both(udev,
-						PMSG_AUTO_RESUME);
-			if (status != 0)
-				atomic_sub(inc_usage_cnt, &intf->pm_usage_cnt);
-			else
-				udev->last_busy = jiffies;
-		} else if (inc_usage_cnt <= 0 &&
-				atomic_read(&intf->pm_usage_cnt) <= 0) {
-			status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
-		}
-	}
-	usb_pm_unlock(udev);
+	status = pm_runtime_get_sync(&udev->dev);
+	if (status < 0)
+		pm_runtime_put_sync(&udev->dev);
+	dev_vdbg(&udev->dev, "%s: cnt %d -> %d\n",
+			__func__, atomic_read(&udev->dev.power.usage_count),
+			status);
+	if (status > 0)
+		status = 0;
 	return status;
 }
 
@@ -1585,34 +1446,25 @@
  * closed.
  *
  * The routine decrements @intf's usage counter.  When the counter reaches
- * 0, a delayed autosuspend request for @intf's device is queued.  When
- * the delay expires, if @intf->pm_usage_cnt is still <= 0 along with all
- * the other usage counters for the sibling interfaces and @intf's
- * usb_device, the device and all its interfaces will be autosuspended.
- *
- * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
- * core will not change its value other than the increment and decrement
- * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
- * may use this simple counter-oriented discipline or may set the value
- * any way it likes.
+ * 0, a delayed autosuspend request for @intf's device is attempted.  The
+ * attempt may fail (see autosuspend_check()).
  *
  * If the driver has set @intf->needs_remote_wakeup then autosuspend will
  * take place only if the device's remote-wakeup facility is enabled.
  *
- * Suspend method calls queued by this routine can arrive at any time
- * while @intf is resumed and its usage counter is equal to 0.  They are
- * not protected by the usb_device's lock but only by its pm_mutex.
- * Drivers must provide their own synchronization.
- *
  * This routine can run only in process context.
  */
 void usb_autopm_put_interface(struct usb_interface *intf)
 {
-	int	status;
+	struct usb_device	*udev = interface_to_usbdev(intf);
+	int			status;
 
-	status = usb_autopm_do_interface(intf, -1);
-	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
-			__func__, status, atomic_read(&intf->pm_usage_cnt));
+	udev->last_busy = jiffies;
+	atomic_dec(&intf->pm_usage_cnt);
+	status = pm_runtime_put_sync(&intf->dev);
+	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
+			__func__, atomic_read(&intf->dev.power.usage_count),
+			status);
 }
 EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
 
@@ -1620,11 +1472,11 @@
  * usb_autopm_put_interface_async - decrement a USB interface's PM-usage counter
  * @intf: the usb_interface whose counter should be decremented
  *
- * This routine does essentially the same thing as
- * usb_autopm_put_interface(): it decrements @intf's usage counter and
- * queues a delayed autosuspend request if the counter is <= 0.  The
- * difference is that it does not acquire the device's pm_mutex;
- * callers must handle all synchronization issues themselves.
+ * This routine does much the same thing as usb_autopm_put_interface():
+ * It decrements @intf's usage counter and schedules a delayed
+ * autosuspend request if the counter is <= 0.  The difference is that it
+ * does not perform any synchronization; callers should hold a private
+ * lock and handle all synchronization issues themselves.
  *
  * Typically a driver would call this routine during an URB's completion
  * handler, if no more URBs were pending.
@@ -1634,28 +1486,58 @@
 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;
 
-	if (intf->condition == USB_INTERFACE_UNBOUND) {
-		status = -ENODEV;
-	} else {
-		udev->last_busy = jiffies;
-		atomic_dec(&intf->pm_usage_cnt);
-		if (udev->autosuspend_disabled || udev->autosuspend_delay < 0)
-			status = -EPERM;
-		else if (atomic_read(&intf->pm_usage_cnt) <= 0 &&
-				!timer_pending(&udev->autosuspend.timer)) {
-			queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+	last_busy = udev->last_busy;
+	udev->last_busy = jiffies;
+	atomic_dec(&intf->pm_usage_cnt);
+	pm_runtime_put_noidle(&intf->dev);
+
+	if (!udev->autosuspend_disabled) {
+		/* 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));
+						udev->autosuspend_delay)));
 		}
 	}
-	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
-			__func__, status, atomic_read(&intf->pm_usage_cnt));
+	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
+			__func__, atomic_read(&intf->dev.power.usage_count),
+			status);
 }
 EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async);
 
 /**
+ * usb_autopm_put_interface_no_suspend - decrement a USB interface's PM-usage counter
+ * @intf: the usb_interface whose counter should be decremented
+ *
+ * This routine decrements @intf's usage counter but does not carry out an
+ * autosuspend.
+ *
+ * This routine can run in atomic context.
+ */
+void usb_autopm_put_interface_no_suspend(struct usb_interface *intf)
+{
+	struct usb_device	*udev = interface_to_usbdev(intf);
+
+	udev->last_busy = jiffies;
+	atomic_dec(&intf->pm_usage_cnt);
+	pm_runtime_put_noidle(&intf->dev);
+}
+EXPORT_SYMBOL_GPL(usb_autopm_put_interface_no_suspend);
+
+/**
  * usb_autopm_get_interface - increment a USB interface's PM-usage counter
  * @intf: the usb_interface whose counter should be incremented
  *
@@ -1667,25 +1549,8 @@
  * or @intf is unbound.  A typical example would be a character-device
  * driver when its device file is opened.
  *
- *
- * The routine increments @intf's usage counter.  (However if the
- * autoresume fails then the counter is re-decremented.)  So long as the
- * counter is greater than 0, autosuspend will not be allowed for @intf
- * or its usb_device.  When the driver is finished using @intf it should
- * call usb_autopm_put_interface() to decrement the usage counter and
- * queue a delayed autosuspend request (if the counter is <= 0).
- *
- *
- * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
- * core will not change its value other than the increment and decrement
- * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
- * may use this simple counter-oriented discipline or may set the value
- * any way it likes.
- *
- * Resume method calls generated by this routine can arrive at any time
- * while @intf is suspended.  They are not protected by the usb_device's
- * lock but only by its pm_mutex.  Drivers must provide their own
- * synchronization.
+ * @intf's usage counter is incremented to prevent subsequent autosuspends.
+ * However if the autoresume fails then the counter is re-decremented.
  *
  * This routine can run only in process context.
  */
@@ -1693,9 +1558,16 @@
 {
 	int	status;
 
-	status = usb_autopm_do_interface(intf, 1);
-	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
-			__func__, status, atomic_read(&intf->pm_usage_cnt));
+	status = pm_runtime_get_sync(&intf->dev);
+	if (status < 0)
+		pm_runtime_put_sync(&intf->dev);
+	else
+		atomic_inc(&intf->pm_usage_cnt);
+	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
+			__func__, atomic_read(&intf->dev.power.usage_count),
+			status);
+	if (status > 0)
+		status = 0;
 	return status;
 }
 EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
@@ -1705,149 +1577,207 @@
  * @intf: the usb_interface whose counter should be incremented
  *
  * This routine does much the same thing as
- * usb_autopm_get_interface(): it increments @intf's usage counter and
- * queues an autoresume request if the result is > 0.  The differences
- * are that it does not acquire the device's pm_mutex (callers must
- * handle all synchronization issues themselves), and it does not
- * autoresume the device directly (it only queues a request).  After a
- * successful call, the device will generally not yet be resumed.
+ * usb_autopm_get_interface(): It increments @intf's usage counter and
+ * queues an autoresume request if the device is suspended.  The
+ * differences are that it does not perform any synchronization (callers
+ * should hold a private lock and handle all synchronization issues
+ * themselves), and it does not autoresume the device directly (it only
+ * queues a request).  After a successful call, the device may not yet be
+ * resumed.
  *
  * This routine can run in atomic context.
  */
 int usb_autopm_get_interface_async(struct usb_interface *intf)
 {
-	struct usb_device	*udev = interface_to_usbdev(intf);
-	int			status = 0;
+	int		status = 0;
+	enum rpm_status	s;
 
-	if (intf->condition == USB_INTERFACE_UNBOUND)
-		status = -ENODEV;
-	else {
+	/* 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);
+
+	if (status < 0 && status != -EINPROGRESS)
+		pm_runtime_put_noidle(&intf->dev);
+	else
 		atomic_inc(&intf->pm_usage_cnt);
-		if (atomic_read(&intf->pm_usage_cnt) > 0 &&
-				udev->state == USB_STATE_SUSPENDED)
-			queue_work(ksuspend_usb_wq, &udev->autoresume);
-	}
-	dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
-			__func__, status, atomic_read(&intf->pm_usage_cnt));
+	dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
+			__func__, atomic_read(&intf->dev.power.usage_count),
+			status);
+	if (status > 0)
+		status = 0;
 	return status;
 }
 EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async);
 
-#else
-
-void usb_autosuspend_work(struct work_struct *work)
-{}
-
-void usb_autoresume_work(struct work_struct *work)
-{}
-
-#endif /* CONFIG_USB_SUSPEND */
-
 /**
- * usb_external_suspend_device - external suspend of a USB device and its interfaces
- * @udev: the usb_device to suspend
- * @msg: Power Management message describing this state transition
+ * usb_autopm_get_interface_no_resume - increment a USB interface's PM-usage counter
+ * @intf: the usb_interface whose counter should be incremented
  *
- * This routine handles external suspend requests: ones not generated
- * internally by a USB driver (autosuspend) but rather coming from the user
- * (via sysfs) or the PM core (system sleep).  The suspend will be carried
- * out regardless of @udev's usage counter or those of its interfaces,
- * and regardless of whether or not remote wakeup is enabled.  Of course,
- * interface drivers still have the option of failing the suspend (if
- * there are unsuspended children, for example).
+ * This routine increments @intf's usage counter but does not carry out an
+ * autoresume.
  *
- * The caller must hold @udev's device lock.
+ * This routine can run in atomic context.
  */
-int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg)
+void usb_autopm_get_interface_no_resume(struct usb_interface *intf)
 {
-	int	status;
+	struct usb_device	*udev = interface_to_usbdev(intf);
 
-	do_unbind_rebind(udev, DO_UNBIND);
-	usb_pm_lock(udev);
-	status = usb_suspend_both(udev, msg);
-	usb_pm_unlock(udev);
-	return status;
-}
-
-/**
- * usb_external_resume_device - external resume of a USB device and its interfaces
- * @udev: the usb_device to resume
- * @msg: Power Management message describing this state transition
- *
- * This routine handles external resume requests: ones not generated
- * internally by a USB driver (autoresume) but rather coming from the user
- * (via sysfs), the PM core (system resume), or the device itself (remote
- * wakeup).  @udev's usage counter is unaffected.
- *
- * The caller must hold @udev's device lock.
- */
-int usb_external_resume_device(struct usb_device *udev, pm_message_t msg)
-{
-	int	status;
-
-	usb_pm_lock(udev);
-	status = usb_resume_both(udev, msg);
 	udev->last_busy = jiffies;
-	usb_pm_unlock(udev);
-	if (status == 0)
-		do_unbind_rebind(udev, DO_REBIND);
-
-	/* Now that the device is awake, we can start trying to autosuspend
-	 * it again. */
-	if (status == 0)
-		usb_try_autosuspend_device(udev);
-	return status;
+	atomic_inc(&intf->pm_usage_cnt);
+	pm_runtime_get_noresume(&intf->dev);
 }
+EXPORT_SYMBOL_GPL(usb_autopm_get_interface_no_resume);
 
-int usb_suspend(struct device *dev, pm_message_t msg)
+/* Internal routine to check whether we may autosuspend a device. */
+static int autosuspend_check(struct usb_device *udev)
 {
-	struct usb_device	*udev;
+	int			i;
+	struct usb_interface	*intf;
+	unsigned long		suspend_time, j;
 
-	udev = to_usb_device(dev);
-
-	/* If udev is already suspended, we can skip this suspend and
-	 * we should also skip the upcoming system resume.  High-speed
-	 * root hubs are an exception; they need to resume whenever the
-	 * system wakes up in order for USB-PERSIST port handover to work
-	 * properly.
+	/* Fail if autosuspend is disabled, or any interfaces are in use, or
+	 * any interface drivers require remote wakeup but it isn't available.
 	 */
-	if (udev->state == USB_STATE_SUSPENDED) {
-		if (udev->parent || udev->speed != USB_SPEED_HIGH)
-			udev->skip_sys_resume = 1;
-		return 0;
+	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+	if (udev->actconfig) {
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			intf = udev->actconfig->interface[i];
+
+			/* We don't need to check interfaces that are
+			 * disabled for runtime PM.  Either they are unbound
+			 * or else their drivers don't support autosuspend
+			 * and so they are permanently active.
+			 */
+			if (intf->dev.power.disable_depth)
+				continue;
+			if (atomic_read(&intf->dev.power.usage_count) > 0)
+				return -EBUSY;
+			if (intf->needs_remote_wakeup &&
+					!udev->do_remote_wakeup) {
+				dev_dbg(&udev->dev, "remote wakeup needed "
+						"for autosuspend\n");
+				return -EOPNOTSUPP;
+			}
+
+			/* Don't allow autosuspend if the device will need
+			 * a reset-resume and any of its interface drivers
+			 * doesn't include support or needs remote wakeup.
+			 */
+			if (udev->quirks & USB_QUIRK_RESET_RESUME) {
+				struct usb_driver *driver;
+
+				driver = to_usb_driver(intf->dev.driver);
+				if (!driver->reset_resume ||
+						intf->needs_remote_wakeup)
+					return -EOPNOTSUPP;
+			}
+		}
 	}
 
-	udev->skip_sys_resume = 0;
-	return usb_external_suspend_device(udev, msg);
+	/* 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;
 }
 
-int usb_resume(struct device *dev, pm_message_t msg)
+static int usb_runtime_suspend(struct device *dev)
 {
-	struct usb_device	*udev;
-	int			status;
+	int	status = 0;
 
-	udev = to_usb_device(dev);
-
-	/* If udev->skip_sys_resume is set then udev was already suspended
-	 * when the system sleep started, so we don't want to resume it
-	 * during this system wakeup.
+	/* 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 (udev->skip_sys_resume)
-		return 0;
-	status = usb_external_resume_device(udev, msg);
+	if (is_usb_device(dev)) {
+		struct usb_device	*udev = to_usb_device(dev);
 
-	/* Avoid PM error messages for devices disconnected while suspended
-	 * as we'll display regular disconnect messages just a bit later.
-	 */
-	if (status == -ENODEV)
-		return 0;
+		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. */
 	return status;
 }
 
-#endif /* CONFIG_PM */
+static int usb_runtime_resume(struct device *dev)
+{
+	/* 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;
+}
+
+static int usb_runtime_idle(struct 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.
+	 */
+	if (is_usb_device(dev)) {
+		struct usb_device	*udev = to_usb_device(dev);
+
+		if (autosuspend_check(udev) != 0)
+			return 0;
+	}
+
+	pm_runtime_suspend(dev);
+	return 0;
+}
+
+static struct dev_pm_ops usb_bus_pm_ops = {
+	.runtime_suspend =	usb_runtime_suspend,
+	.runtime_resume =	usb_runtime_resume,
+	.runtime_idle =		usb_runtime_idle,
+};
+
+#else
+
+#define usb_bus_pm_ops	(*(struct dev_pm_ops *) NULL)
+
+#endif /* CONFIG_USB_SUSPEND */
 
 struct bus_type usb_bus_type = {
 	.name =		"usb",
 	.match =	usb_device_match,
 	.uevent =	usb_uevent,
+	.pm =		&usb_bus_pm_ops,
 };
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index bfc6c2e..c3536f1 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -34,7 +34,6 @@
 	int err = -ENODEV;
 	const struct file_operations *old_fops, *new_fops = NULL;
 
-	lock_kernel();
 	down_read(&minor_rwsem);
 	c = usb_minors[minor];
 
@@ -53,7 +52,6 @@
 	fops_put(old_fops);
  done:
 	up_read(&minor_rwsem);
-	unlock_kernel();
 	return err;
 }
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 80995ef..2f8cedd 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -39,6 +39,7 @@
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/usb.h>
 
@@ -141,7 +142,7 @@
 	0x09,       /*  __u8  bMaxPacketSize0; 2^9 = 512 Bytes */
 
 	0x6b, 0x1d, /*  __le16 idVendor; Linux Foundation */
-	0x02, 0x00, /*  __le16 idProduct; device 0x0002 */
+	0x03, 0x00, /*  __le16 idProduct; device 0x0003 */
 	KERNEL_VER, KERNEL_REL, /*  __le16 bcdDevice */
 
 	0x03,       /*  __u8  iManufacturer; */
@@ -1670,11 +1671,16 @@
 			}
 		}
 		for (i = 0; i < num_intfs; ++i) {
+			struct usb_host_interface *first_alt;
+			int iface_num;
+
+			first_alt = &new_config->intf_cache[i]->altsetting[0];
+			iface_num = first_alt->desc.bInterfaceNumber;
 			/* Set up endpoints for alternate interface setting 0 */
-			alt = usb_find_alt_setting(new_config, i, 0);
+			alt = usb_find_alt_setting(new_config, iface_num, 0);
 			if (!alt)
 				/* No alt setting 0? Pick the first setting. */
-				alt = &new_config->intf_cache[i]->altsetting[0];
+				alt = first_alt;
 
 			for (j = 0; j < alt->desc.bNumEndpoints; j++) {
 				ret = hcd->driver->add_endpoint(hcd, udev, &alt->endpoint[j]);
@@ -1853,6 +1859,10 @@
 	return status;
 }
 
+#endif	/* CONFIG_PM */
+
+#ifdef	CONFIG_USB_SUSPEND
+
 /* Workqueue routine for root-hub remote wakeup */
 static void hcd_resume_work(struct work_struct *work)
 {
@@ -1860,8 +1870,7 @@
 	struct usb_device *udev = hcd->self.root_hub;
 
 	usb_lock_device(udev);
-	usb_mark_last_busy(udev);
-	usb_external_resume_device(udev, PMSG_REMOTE_RESUME);
+	usb_remote_wakeup(udev);
 	usb_unlock_device(udev);
 }
 
@@ -1880,12 +1889,12 @@
 
 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
 	if (hcd->rh_registered)
-		queue_work(ksuspend_usb_wq, &hcd->wakeup_work);
+		queue_work(pm_wq, &hcd->wakeup_work);
 	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
 }
 EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
 
-#endif
+#endif	/* CONFIG_USB_SUSPEND */
 
 /*-------------------------------------------------------------------------*/
 
@@ -2030,7 +2039,7 @@
 	init_timer(&hcd->rh_timer);
 	hcd->rh_timer.function = rh_timer_func;
 	hcd->rh_timer.data = (unsigned long) hcd;
-#ifdef CONFIG_PM
+#ifdef CONFIG_USB_SUSPEND
 	INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
 #endif
 	mutex_init(&hcd->bandwidth_mutex);
@@ -2230,7 +2239,7 @@
 	hcd->rh_registered = 0;
 	spin_unlock_irq (&hcd_root_hub_lock);
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_USB_SUSPEND
 	cancel_work_sync(&hcd->wakeup_work);
 #endif
 
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index bbe2b92..a3cdb09 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -80,7 +80,7 @@
 
 	struct timer_list	rh_timer;	/* drives root-hub polling */
 	struct urb		*status_urb;	/* the current status urb */
-#ifdef CONFIG_PM
+#ifdef CONFIG_USB_SUSPEND
 	struct work_struct	wakeup_work;	/* for remote wakeup */
 #endif
 
@@ -248,7 +248,7 @@
 	/* xHCI specific functions */
 		/* Called by usb_alloc_dev to alloc HC device structures */
 	int	(*alloc_dev)(struct usb_hcd *, struct usb_device *);
-		/* Called by usb_release_dev to free HC device structures */
+		/* Called by usb_disconnect to free HC device structures */
 	void	(*free_dev)(struct usb_hcd *, struct usb_device *);
 
 	/* Bandwidth computation functions */
@@ -286,6 +286,7 @@
 		 */
 	int	(*update_hub_device)(struct usb_hcd *, struct usb_device *hdev,
 			struct usb_tt *tt, gfp_t mem_flags);
+	int	(*reset_device)(struct usb_hcd *, struct usb_device *);
 };
 
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
@@ -463,16 +464,20 @@
 #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
 
 #ifdef CONFIG_PM
-extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
 extern void usb_root_hub_lost_power(struct usb_device *rhdev);
 extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg);
 extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg);
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_USB_SUSPEND
+extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
 #else
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
 	return;
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_USB_SUSPEND */
+
 
 /*
  * USB device fs stuff
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 20ecb4c..0940ccd 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -22,6 +22,7 @@
 #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>
@@ -71,7 +72,6 @@
 
 	unsigned		mA_per_port;	/* current for each child */
 
-	unsigned		init_done:1;
 	unsigned		limited_power:1;
 	unsigned		quiescing:1;
 	unsigned		disconnected:1;
@@ -820,7 +820,6 @@
 	}
  init3:
 	hub->quiescing = 0;
-	hub->init_done = 1;
 
 	status = usb_submit_urb(hub->urb, GFP_NOIO);
 	if (status < 0)
@@ -861,11 +860,6 @@
 	int i;
 
 	cancel_delayed_work_sync(&hub->init_work);
-	if (!hub->init_done) {
-		hub->init_done = 1;
-		usb_autopm_put_interface_no_suspend(
-				to_usb_interface(hub->intfdev));
-	}
 
 	/* khubd and related activity won't re-trigger */
 	hub->quiescing = 1;
@@ -1224,6 +1218,9 @@
 	desc = intf->cur_altsetting;
 	hdev = interface_to_usbdev(intf);
 
+	/* Hubs have proper suspend/resume support */
+	usb_enable_autosuspend(hdev);
+
 	if (hdev->level == MAX_TOPO_LEVEL) {
 		dev_err(&intf->dev,
 			"Unsupported bus topology: hub nested too deep\n");
@@ -1402,10 +1399,8 @@
 		if (udev->children[i])
 			recursively_mark_NOTATTACHED(udev->children[i]);
 	}
-	if (udev->state == USB_STATE_SUSPENDED) {
-		udev->discon_suspended = 1;
+	if (udev->state == USB_STATE_SUSPENDED)
 		udev->active_duration -= jiffies;
-	}
 	udev->state = USB_STATE_NOTATTACHED;
 }
 
@@ -1448,11 +1443,11 @@
 					|| new_state == USB_STATE_SUSPENDED)
 				;	/* No change to wakeup settings */
 			else if (new_state == USB_STATE_CONFIGURED)
-				device_init_wakeup(&udev->dev,
+				device_set_wakeup_capable(&udev->dev,
 					(udev->actconfig->desc.bmAttributes
 					 & USB_CONFIG_ATT_WAKEUP));
 			else
-				device_init_wakeup(&udev->dev, 0);
+				device_set_wakeup_capable(&udev->dev, 0);
 		}
 		if (udev->state == USB_STATE_SUSPENDED &&
 			new_state != USB_STATE_SUSPENDED)
@@ -1529,31 +1524,15 @@
 		udev->devnum = devnum;
 }
 
-#ifdef	CONFIG_USB_SUSPEND
-
-static void usb_stop_pm(struct usb_device *udev)
+static void hub_free_dev(struct usb_device *udev)
 {
-	/* Synchronize with the ksuspend thread to prevent any more
-	 * autosuspend requests from being submitted, and decrement
-	 * the parent's count of unsuspended children.
-	 */
-	usb_pm_lock(udev);
-	if (udev->parent && !udev->discon_suspended)
-		usb_autosuspend_device(udev->parent);
-	usb_pm_unlock(udev);
+	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
 
-	/* Stop any autosuspend or autoresume requests already submitted */
-	cancel_delayed_work_sync(&udev->autosuspend);
-	cancel_work_sync(&udev->autoresume);
+	/* Root hubs aren't real devices, so don't free HCD resources */
+	if (hcd->driver->free_dev && udev->parent)
+		hcd->driver->free_dev(hcd, udev);
 }
 
-#else
-
-static inline void usb_stop_pm(struct usb_device *udev)
-{ }
-
-#endif
-
 /**
  * usb_disconnect - disconnect a device (usbcore-internal)
  * @pdev: pointer to device being disconnected
@@ -1622,7 +1601,7 @@
 	*pdev = NULL;
 	spin_unlock_irq(&device_state_lock);
 
-	usb_stop_pm(udev);
+	hub_free_dev(udev);
 
 	put_device(&udev->dev);
 }
@@ -1799,9 +1778,18 @@
 {
 	int err;
 
-	/* Increment the parent's count of unsuspended children */
-	if (udev->parent)
-		usb_autoresume_device(udev->parent);
+	if (udev->parent) {
+		/* Initialize non-root-hub device wakeup to disabled;
+		 * device (un)configuration controls wakeup capable
+		 * sysfs power/wakeup controls wakeup enabled/disabled
+		 */
+		device_init_wakeup(&udev->dev, 0);
+		device_set_wakeup_enable(&udev->dev, 1);
+	}
+
+	/* Tell the runtime-PM framework the device is active */
+	pm_runtime_set_active(&udev->dev);
+	pm_runtime_enable(&udev->dev);
 
 	usb_detect_quirks(udev);
 	err = usb_enumerate_device(udev);	/* Read descriptors */
@@ -1833,7 +1821,8 @@
 
 fail:
 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
-	usb_stop_pm(udev);
+	pm_runtime_disable(&udev->dev);
+	pm_runtime_set_suspended(&udev->dev);
 	return err;
 }
 
@@ -1982,7 +1971,7 @@
 		if (!(portstatus & USB_PORT_STAT_RESET) &&
 		    (portstatus & USB_PORT_STAT_ENABLE)) {
 			if (hub_is_wusb(hub))
-				udev->speed = USB_SPEED_VARIABLE;
+				udev->speed = USB_SPEED_WIRELESS;
 			else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
 				udev->speed = USB_SPEED_HIGH;
 			else if (portstatus & USB_PORT_STAT_LOW_SPEED)
@@ -2008,7 +1997,9 @@
 				struct usb_device *udev, unsigned int delay)
 {
 	int i, status;
+	struct usb_hcd *hcd;
 
+	hcd = bus_to_hcd(udev->bus);
 	/* Block EHCI CF initialization during the port reset.
 	 * Some companion controllers don't like it when they mix.
 	 */
@@ -2036,6 +2027,14 @@
 			/* TRSTRCY = 10 ms; plus some extra */
 			msleep(10 + 40);
 			update_address(udev, 0);
+			if (hcd->driver->reset_device) {
+				status = hcd->driver->reset_device(hcd, udev);
+				if (status < 0) {
+					dev_err(&udev->dev, "Cannot reset "
+							"HCD device state\n");
+					break;
+				}
+			}
 			/* FALL THROUGH */
 		case -ENOTCONN:
 		case -ENODEV:
@@ -2381,14 +2380,17 @@
 }
 
 /* caller has locked udev */
-static int remote_wakeup(struct usb_device *udev)
+int usb_remote_wakeup(struct usb_device *udev)
 {
 	int	status = 0;
 
 	if (udev->state == USB_STATE_SUSPENDED) {
 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
-		usb_mark_last_busy(udev);
-		status = usb_external_resume_device(udev, PMSG_REMOTE_RESUME);
+		status = usb_autoresume_device(udev);
+		if (status == 0) {
+			/* Let the drivers do their thing, then... */
+			usb_autosuspend_device(udev);
+		}
 	}
 	return status;
 }
@@ -2425,11 +2427,6 @@
 	return status;
 }
 
-static inline int remote_wakeup(struct usb_device *udev)
-{
-	return 0;
-}
-
 #endif
 
 static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
@@ -2496,11 +2493,6 @@
 
 #else	/* CONFIG_PM */
 
-static inline int remote_wakeup(struct usb_device *udev)
-{
-	return 0;
-}
-
 #define hub_suspend		NULL
 #define hub_resume		NULL
 #define hub_reset_resume	NULL
@@ -2645,14 +2637,7 @@
 
 	mutex_lock(&usb_address0_mutex);
 
-	if ((hcd->driver->flags & HCD_USB3) && udev->config) {
-		/* FIXME this will need special handling by the xHCI driver. */
-		dev_dbg(&udev->dev,
-				"xHCI reset of configured device "
-				"not supported yet.\n");
-		retval = -EINVAL;
-		goto fail;
-	} else if (!udev->config && oldspeed == USB_SPEED_SUPER) {
+	if (!udev->config && oldspeed == USB_SPEED_SUPER) {
 		/* Don't reset USB 3.0 devices during an initial setup */
 		usb_set_device_state(udev, USB_STATE_DEFAULT);
 	} else {
@@ -2678,7 +2663,7 @@
 	 */
 	switch (udev->speed) {
 	case USB_SPEED_SUPER:
-	case USB_SPEED_VARIABLE:	/* fixed at 512 */
+	case USB_SPEED_WIRELESS:	/* fixed at 512 */
 		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
 		break;
 	case USB_SPEED_HIGH:		/* fixed at 64 */
@@ -2706,7 +2691,7 @@
 	case USB_SPEED_SUPER:
 				speed = "super";
 				break;
-	case USB_SPEED_VARIABLE:
+	case USB_SPEED_WIRELESS:
 				speed = "variable";
 				type = "Wireless ";
 				break;
@@ -3006,7 +2991,7 @@
 			/* For a suspended device, treat this as a
 			 * remote wakeup event.
 			 */
-			status = remote_wakeup(udev);
+			status = usb_remote_wakeup(udev);
 #endif
 
 		} else {
@@ -3192,6 +3177,7 @@
 loop:
 		usb_ep0_reinit(udev);
 		release_address(udev);
+		hub_free_dev(udev);
 		usb_put_dev(udev);
 		if ((status == -ENOTCONN) || (status == -ENOTSUPP))
 			break;
@@ -3259,7 +3245,7 @@
 		 * disconnected while waiting for the lock to succeed. */
 		usb_lock_device(hdev);
 		if (unlikely(hub->disconnected))
-			goto loop2;
+			goto loop_disconnected;
 
 		/* If the hub has died, clean up after it */
 		if (hdev->state == USB_STATE_NOTATTACHED) {
@@ -3352,7 +3338,7 @@
 					msleep(10);
 
 					usb_lock_device(udev);
-					ret = remote_wakeup(hdev->
+					ret = usb_remote_wakeup(hdev->
 							children[i-1]);
 					usb_unlock_device(udev);
 					if (ret < 0)
@@ -3419,7 +3405,7 @@
 		 * kick_khubd() and allow autosuspend.
 		 */
 		usb_autopm_put_interface(intf);
- loop2:
+ loop_disconnected:
 		usb_unlock_device(hdev);
 		kref_put(&hub->kref, hub_release);
 
@@ -3446,7 +3432,7 @@
 	return 0;
 }
 
-static struct usb_device_id hub_id_table [] = {
+static const struct usb_device_id hub_id_table[] = {
     { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS,
       .bDeviceClass = USB_CLASS_HUB},
     { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index df73574..cd22027 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1316,7 +1316,7 @@
 
 	alt = usb_altnum_to_altsetting(iface, alternate);
 	if (!alt) {
-		dev_warn(&dev->dev, "selecting invalid altsetting %d",
+		dev_warn(&dev->dev, "selecting invalid altsetting %d\n",
 			 alternate);
 		return -EINVAL;
 	}
@@ -1471,7 +1471,7 @@
 	/* If not, reinstate the old alternate settings */
 	if (retval < 0) {
 reset_old_alts:
-		for (; i >= 0; i--) {
+		for (i--; i >= 0; i--) {
 			struct usb_interface *intf = config->interface[i];
 			struct usb_host_interface *alt;
 
@@ -1843,7 +1843,6 @@
 		intf->dev.dma_mask = dev->dev.dma_mask;
 		INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
 		device_initialize(&intf->dev);
-		mark_quiesced(intf);
 		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 ab93918..f073c5c 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -103,10 +103,19 @@
 		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
 				udev->quirks);
 
-	/* By default, disable autosuspend for all non-hubs */
 #ifdef	CONFIG_USB_SUSPEND
-	if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
-		udev->autosuspend_disabled = 1;
+
+	/* 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 */
@@ -120,6 +129,7 @@
 	 * for all devices.  It will affect things like hub resets
 	 * and EMF-related port disables.
 	 */
-	udev->persist_enabled = 1;
+	if (!(udev->quirks & USB_QUIRK_RESET_MORPHS))
+		udev->persist_enabled = 1;
 #endif	/* CONFIG_PM */
 }
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 5f3908f..43c002e 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -115,7 +115,7 @@
 	case USB_SPEED_HIGH:
 		speed = "480";
 		break;
-	case USB_SPEED_VARIABLE:
+	case USB_SPEED_WIRELESS:
 		speed = "480";
 		break;
 	case USB_SPEED_SUPER:
@@ -191,6 +191,36 @@
 static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
 
 static ssize_t
+show_avoid_reset_quirk(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct usb_device *udev;
+
+	udev = to_usb_device(dev);
+	return sprintf(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET_MORPHS));
+}
+
+static ssize_t
+set_avoid_reset_quirk(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct usb_device	*udev = to_usb_device(dev);
+	int			config;
+
+	if (sscanf(buf, "%d", &config) != 1 || config < 0 || config > 1)
+		return -EINVAL;
+	usb_lock_device(udev);
+	if (config)
+		udev->quirks |= USB_QUIRK_RESET_MORPHS;
+	else
+		udev->quirks &= ~USB_QUIRK_RESET_MORPHS;
+	usb_unlock_device(udev);
+	return count;
+}
+
+static DEVICE_ATTR(avoid_reset_quirk, S_IRUGO | S_IWUSR,
+		show_avoid_reset_quirk, set_avoid_reset_quirk);
+
+static ssize_t
 show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_device *udev;
@@ -226,9 +256,10 @@
 
 	if (sscanf(buf, "%d", &value) != 1)
 		return -EINVAL;
-	usb_pm_lock(udev);
+
+	usb_lock_device(udev);
 	udev->persist_enabled = !!value;
-	usb_pm_unlock(udev);
+	usb_unlock_device(udev);
 	return count;
 }
 
@@ -315,20 +346,34 @@
 		const char *buf, size_t count)
 {
 	struct usb_device *udev = to_usb_device(dev);
-	int value;
+	int value, old_delay;
+	int rc;
 
 	if (sscanf(buf, "%d", &value) != 1 || value >= INT_MAX/HZ ||
 			value <= - INT_MAX/HZ)
 		return -EINVAL;
 	value *= HZ;
 
+	usb_lock_device(udev);
+	old_delay = udev->autosuspend_delay;
 	udev->autosuspend_delay = value;
-	if (value >= 0)
-		usb_try_autosuspend_device(udev);
-	else {
-		if (usb_autoresume_device(udev) == 0)
+
+	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);
 	return count;
 }
 
@@ -356,34 +401,25 @@
 	struct usb_device *udev = to_usb_device(dev);
 	int len = count;
 	char *cp;
-	int rc = 0;
-	int old_autosuspend_disabled;
+	int rc;
 
 	cp = memchr(buf, '\n', count);
 	if (cp)
 		len = cp - buf;
 
 	usb_lock_device(udev);
-	old_autosuspend_disabled = udev->autosuspend_disabled;
 
-	/* Setting the flags without calling usb_pm_lock is a subject to
-	 * races, but who cares...
-	 */
 	if (len == sizeof on_string - 1 &&
-			strncmp(buf, on_string, len) == 0) {
-		udev->autosuspend_disabled = 1;
-		rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
+			strncmp(buf, on_string, len) == 0)
+		rc = usb_disable_autosuspend(udev);
 
-	} else if (len == sizeof auto_string - 1 &&
-			strncmp(buf, auto_string, len) == 0) {
-		udev->autosuspend_disabled = 0;
-		rc = usb_external_resume_device(udev, PMSG_USER_RESUME);
+	else if (len == sizeof auto_string - 1 &&
+			strncmp(buf, auto_string, len) == 0)
+		rc = usb_enable_autosuspend(udev);
 
-	} else
+	else
 		rc = -EINVAL;
 
-	if (rc)
-		udev->autosuspend_disabled = old_autosuspend_disabled;
 	usb_unlock_device(udev);
 	return (rc < 0 ? rc : count);
 }
@@ -558,6 +594,7 @@
 	&dev_attr_version.attr,
 	&dev_attr_maxchild.attr,
 	&dev_attr_quirks.attr,
+	&dev_attr_avoid_reset_quirk.attr,
 	&dev_attr_authorized.attr,
 	&dev_attr_remove.attr,
 	NULL,
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index e7cae13..2708056 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -387,6 +387,13 @@
 	{
 	unsigned int	orig_flags = urb->transfer_flags;
 	unsigned int	allowed;
+	static int pipetypes[4] = {
+		PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
+	};
+
+	/* Check that the pipe's type matches the endpoint's type */
+	if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+		return -EPIPE;		/* The most suitable error code :-) */
 
 	/* enforce simple/standard policy */
 	allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
@@ -430,7 +437,7 @@
 	case USB_ENDPOINT_XFER_INT:
 		/* too small? */
 		switch (dev->speed) {
-		case USB_SPEED_VARIABLE:
+		case USB_SPEED_WIRELESS:
 			if (urb->interval < 6)
 				return -EINVAL;
 			break;
@@ -446,7 +453,7 @@
 			if (urb->interval > (1 << 15))
 				return -EINVAL;
 			max = 1 << 15;
-		case USB_SPEED_VARIABLE:
+		case USB_SPEED_WIRELESS:
 			if (urb->interval > 16)
 				return -EINVAL;
 			break;
@@ -473,7 +480,7 @@
 		default:
 			return -EINVAL;
 		}
-		if (dev->speed != USB_SPEED_VARIABLE) {
+		if (dev->speed != USB_SPEED_WIRELESS) {
 			/* Round down to a power of 2, no more than max */
 			urb->interval = min(max, 1 << ilog2(urb->interval));
 		}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 0daff0d..1297e9b 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -49,9 +49,6 @@
 
 static int nousb;	/* Disable USB when built into kernel image */
 
-/* Workqueue for autosuspend and for remote wakeup of root hubs */
-struct workqueue_struct *ksuspend_usb_wq;
-
 #ifdef	CONFIG_USB_SUSPEND
 static int usb_autosuspend_delay = 2;		/* Default delay value,
 						 * in seconds */
@@ -228,9 +225,6 @@
 	hcd = bus_to_hcd(udev->bus);
 
 	usb_destroy_configuration(udev);
-	/* Root hubs aren't real devices, so don't free HCD resources */
-	if (hcd->driver->free_dev && udev->parent)
-		hcd->driver->free_dev(hcd, udev);
 	usb_put_hcd(hcd);
 	kfree(udev->product);
 	kfree(udev->manufacturer);
@@ -264,23 +258,6 @@
 
 #ifdef	CONFIG_PM
 
-static int ksuspend_usb_init(void)
-{
-	/* This workqueue is supposed to be both freezable and
-	 * singlethreaded.  Its job doesn't justify running on more
-	 * than one CPU.
-	 */
-	ksuspend_usb_wq = create_freezeable_workqueue("ksuspend_usbd");
-	if (!ksuspend_usb_wq)
-		return -ENOMEM;
-	return 0;
-}
-
-static void ksuspend_usb_cleanup(void)
-{
-	destroy_workqueue(ksuspend_usb_wq);
-}
-
 /* USB device Power-Management thunks.
  * There's no need to distinguish here between quiescing a USB device
  * and powering it down; the generic_suspend() routine takes care of
@@ -296,7 +273,7 @@
 static void usb_dev_complete(struct device *dev)
 {
 	/* Currently used only for rebinding interfaces */
-	usb_resume(dev, PMSG_RESUME);	/* Message event is meaningless */
+	usb_resume(dev, PMSG_ON);	/* FIXME: change to PMSG_COMPLETE */
 }
 
 static int usb_dev_suspend(struct device *dev)
@@ -342,9 +319,7 @@
 
 #else
 
-#define ksuspend_usb_init()	0
-#define ksuspend_usb_cleanup()	do {} while (0)
-#define usb_device_pm_ops	(*(struct dev_pm_ops *)0)
+#define usb_device_pm_ops	(*(struct dev_pm_ops *) NULL)
 
 #endif	/* CONFIG_PM */
 
@@ -472,9 +447,6 @@
 	INIT_LIST_HEAD(&dev->filelist);
 
 #ifdef	CONFIG_PM
-	mutex_init(&dev->pm_mutex);
-	INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
-	INIT_WORK(&dev->autoresume, usb_autoresume_work);
 	dev->autosuspend_delay = usb_autosuspend_delay * HZ;
 	dev->connect_time = jiffies;
 	dev->active_duration = -jiffies;
@@ -1117,9 +1089,6 @@
 	if (retval)
 		goto out;
 
-	retval = ksuspend_usb_init();
-	if (retval)
-		goto out;
 	retval = bus_register(&usb_bus_type);
 	if (retval)
 		goto bus_register_failed;
@@ -1159,7 +1128,7 @@
 bus_notifier_failed:
 	bus_unregister(&usb_bus_type);
 bus_register_failed:
-	ksuspend_usb_cleanup();
+	usb_debugfs_cleanup();
 out:
 	return retval;
 }
@@ -1181,7 +1150,6 @@
 	usb_hub_cleanup();
 	bus_unregister_notifier(&usb_bus_type, &usb_bus_nb);
 	bus_unregister(&usb_bus_type);
-	ksuspend_usb_cleanup();
 	usb_debugfs_cleanup();
 }
 
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 4c36c7f..cd88220 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -55,24 +55,8 @@
 extern int usb_suspend(struct device *dev, pm_message_t msg);
 extern int usb_resume(struct device *dev, pm_message_t msg);
 
-extern void usb_autosuspend_work(struct work_struct *work);
-extern void usb_autoresume_work(struct work_struct *work);
 extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg);
 extern int usb_port_resume(struct usb_device *dev, pm_message_t msg);
-extern int usb_external_suspend_device(struct usb_device *udev,
-		pm_message_t msg);
-extern int usb_external_resume_device(struct usb_device *udev,
-		pm_message_t msg);
-
-static inline void usb_pm_lock(struct usb_device *udev)
-{
-	mutex_lock_nested(&udev->pm_mutex, udev->level);
-}
-
-static inline void usb_pm_unlock(struct usb_device *udev)
-{
-	mutex_unlock(&udev->pm_mutex);
-}
 
 #else
 
@@ -86,9 +70,6 @@
 	return 0;
 }
 
-static inline void usb_pm_lock(struct usb_device *udev) {}
-static inline void usb_pm_unlock(struct usb_device *udev) {}
-
 #endif
 
 #ifdef CONFIG_USB_SUSPEND
@@ -96,6 +77,7 @@
 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
 
@@ -106,9 +88,13 @@
 	return 0;
 }
 
+static inline int usb_remote_wakeup(struct usb_device *udev)
+{
+	return 0;
+}
+
 #endif
 
-extern struct workqueue_struct *ksuspend_usb_wq;
 extern struct bus_type usb_bus_type;
 extern struct device_type usb_device_type;
 extern struct device_type usb_if_device_type;
@@ -138,23 +124,6 @@
 			for_devices;
 }
 
-/* Interfaces and their "power state" are owned by usbcore */
-
-static inline void mark_active(struct usb_interface *f)
-{
-	f->is_active = 1;
-}
-
-static inline void mark_quiesced(struct usb_interface *f)
-{
-	f->is_active = 0;
-}
-
-static inline int is_active(const struct usb_interface *f)
-{
-	return f->is_active;
-}
-
 
 /* for labeling diagnostics */
 extern const char *usbcore_name;
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index 2958a12..6e98a36 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -66,8 +66,6 @@
 
 #define USB_DEBUG_DEVNUM 127
 
-#define DBGP_DATA_TOGGLE	0x8800
-
 #ifdef DBGP_DEBUG
 #define dbgp_printk printk
 static void dbgp_ehci_status(char *str)
@@ -88,11 +86,6 @@
 static inline void dbgp_printk(const char *fmt, ...) { }
 #endif
 
-static inline u32 dbgp_pid_update(u32 x, u32 tok)
-{
-	return ((x ^ DBGP_DATA_TOGGLE) & 0xffff00) | (tok & 0xff);
-}
-
 static inline u32 dbgp_len_update(u32 x, u32 len)
 {
 	return (x & ~0x0f) | (len & 0x0f);
@@ -136,6 +129,19 @@
 
 #define DBGP_MAX_PACKET		8
 #define DBGP_TIMEOUT		(250 * 1000)
+#define DBGP_LOOPS		1000
+
+static inline u32 dbgp_pid_write_update(u32 x, u32 tok)
+{
+	static int data0 = USB_PID_DATA1;
+	data0 ^= USB_PID_DATA_TOGGLE;
+	return (x & 0xffff0000) | (data0 << 8) | (tok & 0xff);
+}
+
+static inline u32 dbgp_pid_read_update(u32 x, u32 tok)
+{
+	return (x & 0xffff0000) | (USB_PID_DATA0 << 8) | (tok & 0xff);
+}
 
 static int dbgp_wait_until_complete(void)
 {
@@ -180,7 +186,7 @@
 {
 	u32 pids, lpid;
 	int ret;
-	int loop = 3;
+	int loop = DBGP_LOOPS;
 
 retry:
 	writel(ctrl | DBGP_GO, &ehci_debug->control);
@@ -197,6 +203,8 @@
 		 */
 		if (ret == -DBGP_TIMEOUT && !dbgp_not_safe)
 			dbgp_not_safe = 1;
+		if (ret == -DBGP_ERR_BAD && --loop > 0)
+			goto retry;
 		return ret;
 	}
 
@@ -245,12 +253,20 @@
 		bytes[i] = (hi >> (8*(i - 4))) & 0xff;
 }
 
-static int dbgp_out(u32 addr, const char *bytes, int size)
+static int dbgp_bulk_write(unsigned devnum, unsigned endpoint,
+			 const char *bytes, int size)
 {
+	int ret;
+	u32 addr;
 	u32 pids, ctrl;
 
+	if (size > DBGP_MAX_PACKET)
+		return -1;
+
+	addr = DBGP_EPADDR(devnum, endpoint);
+
 	pids = readl(&ehci_debug->pids);
-	pids = dbgp_pid_update(pids, USB_PID_OUT);
+	pids = dbgp_pid_write_update(pids, USB_PID_OUT);
 
 	ctrl = readl(&ehci_debug->control);
 	ctrl = dbgp_len_update(ctrl, size);
@@ -260,34 +276,7 @@
 	dbgp_set_data(bytes, size);
 	writel(addr, &ehci_debug->address);
 	writel(pids, &ehci_debug->pids);
-	return dbgp_wait_until_done(ctrl);
-}
-
-static int dbgp_bulk_write(unsigned devnum, unsigned endpoint,
-			 const char *bytes, int size)
-{
-	int ret;
-	int loops = 5;
-	u32 addr;
-	if (size > DBGP_MAX_PACKET)
-		return -1;
-
-	addr = DBGP_EPADDR(devnum, endpoint);
-try_again:
-	if (loops--) {
-		ret = dbgp_out(addr, bytes, size);
-		if (ret == -DBGP_ERR_BAD) {
-			int try_loops = 3;
-			do {
-				/* Emit a dummy packet to re-sync communication
-				 * with the debug device */
-				if (dbgp_out(addr, "12345678", 8) >= 0) {
-					udelay(2);
-					goto try_again;
-				}
-			} while (try_loops--);
-		}
-	}
+	ret = dbgp_wait_until_done(ctrl);
 
 	return ret;
 }
@@ -304,7 +293,7 @@
 	addr = DBGP_EPADDR(devnum, endpoint);
 
 	pids = readl(&ehci_debug->pids);
-	pids = dbgp_pid_update(pids, USB_PID_IN);
+	pids = dbgp_pid_read_update(pids, USB_PID_IN);
 
 	ctrl = readl(&ehci_debug->control);
 	ctrl = dbgp_len_update(ctrl, size);
@@ -362,7 +351,6 @@
 	return dbgp_bulk_read(devnum, 0, data, size);
 }
 
-
 /* Find a PCI capability */
 static u32 __init find_cap(u32 num, u32 slot, u32 func, int cap)
 {
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index ee41120..7460cd7 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -812,6 +812,16 @@
 	  Say "y" to link the driver statically, or "m" to build a
 	  dynamically linked module.
 
+config USB_G_NOKIA
+	tristate "Nokia composite gadget"
+	depends on PHONET
+	help
+	  The Nokia composite gadget provides support for acm, obex
+	  and phonet in only one composite gadget driver.
+
+	  It's only really useful for N900 hardware. If you're building
+	  a kernel for N900, say Y or M here. If unsure, say N.
+
 config USB_G_MULTI
 	tristate "Multifunction Composite Gadget (EXPERIMENTAL)"
 	depends on BLOCK && NET
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 2e2c047..43b51da 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -43,6 +43,7 @@
 g_printer-objs			:= printer.o
 g_cdc-objs			:= cdc2.o
 g_multi-objs			:= multi.o
+g_nokia-objs			:= nokia.o
 
 obj-$(CONFIG_USB_ZERO)		+= g_zero.o
 obj-$(CONFIG_USB_AUDIO)		+= g_audio.o
@@ -55,4 +56,5 @@
 obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
 obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
 obj-$(CONFIG_USB_G_MULTI)	+= g_multi.o
+obj-$(CONFIG_USB_G_NOKIA)	+= g_nokia.o
 
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 043e04d..12ac9cd 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1656,9 +1656,7 @@
 	if (!res)
 		return -ENXIO;
 
-	if (!request_mem_region(res->start,
-			res->end - res->start + 1,
-			driver_name)) {
+	if (!request_mem_region(res->start, resource_size(res), driver_name)) {
 		DBG("someone's using UDC memory\n");
 		return -EBUSY;
 	}
@@ -1699,7 +1697,7 @@
 		udc->ep[3].maxpacket = 64;
 	}
 
-	udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
+	udc->udp_baseaddr = ioremap(res->start, resource_size(res));
 	if (!udc->udp_baseaddr) {
 		retval = -ENOMEM;
 		goto fail0a;
@@ -1781,7 +1779,7 @@
 	if (cpu_is_at91rm9200())
 		gpio_free(udc->board.pullup_pin);
 fail0:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 	DBG("%s probe failed, %d\n", driver_name, retval);
 	return retval;
 }
@@ -1813,7 +1811,7 @@
 		gpio_free(udc->board.pullup_pin);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 
 	clk_put(udc->iclk);
 	clk_put(udc->fclk);
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 4e970cf..f79bdfe 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -320,7 +320,7 @@
 static int vbus_is_present(struct usba_udc *udc)
 {
 	if (gpio_is_valid(udc->vbus_pin))
-		return gpio_get_value(udc->vbus_pin);
+		return gpio_get_value(udc->vbus_pin) ^ udc->vbus_pin_inverted;
 
 	/* No Vbus detection: Assume always present */
 	return 1;
@@ -1763,7 +1763,7 @@
 	if (!udc->driver)
 		goto out;
 
-	vbus = gpio_get_value(udc->vbus_pin);
+	vbus = vbus_is_present(udc);
 	if (vbus != udc->vbus_prev) {
 		if (vbus) {
 			toggle_bias(1);
@@ -1914,14 +1914,14 @@
 	udc->vbus_pin = -ENODEV;
 
 	ret = -ENOMEM;
-	udc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	udc->regs = ioremap(regs->start, resource_size(regs));
 	if (!udc->regs) {
 		dev_err(&pdev->dev, "Unable to map I/O memory, aborting.\n");
 		goto err_map_regs;
 	}
 	dev_info(&pdev->dev, "MMIO registers at 0x%08lx mapped at %p\n",
 		 (unsigned long)regs->start, udc->regs);
-	udc->fifo = ioremap(fifo->start, fifo->end - fifo->start + 1);
+	udc->fifo = ioremap(fifo->start, resource_size(fifo));
 	if (!udc->fifo) {
 		dev_err(&pdev->dev, "Unable to map FIFO, aborting.\n");
 		goto err_map_fifo;
@@ -2000,6 +2000,7 @@
 	if (gpio_is_valid(pdata->vbus_pin)) {
 		if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
 			udc->vbus_pin = pdata->vbus_pin;
+			udc->vbus_pin_inverted = pdata->vbus_pin_inverted;
 
 			ret = request_irq(gpio_to_irq(udc->vbus_pin),
 					usba_vbus_irq, 0,
diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h
index f7baea3..88a2e07 100644
--- a/drivers/usb/gadget/atmel_usba_udc.h
+++ b/drivers/usb/gadget/atmel_usba_udc.h
@@ -323,6 +323,7 @@
 	struct platform_device *pdev;
 	int irq;
 	int vbus_pin;
+	int vbus_pin_inverted;
 	struct clk *pclk;
 	struct clk *hclk;
 
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index cd0914e..65a5f94 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -265,16 +265,24 @@
 				return ep;
 		}
 
-	} else if (gadget_is_sh (gadget) && USB_ENDPOINT_XFER_INT == type) {
-		/* single buffering is enough; maybe 8 byte fifo is too */
-		ep = find_ep (gadget, "ep3in-bulk");
+#ifdef CONFIG_BLACKFIN
+	} else if (gadget_is_musbhsfc(gadget) || gadget_is_musbhdrc(gadget)) {
+		if ((USB_ENDPOINT_XFER_BULK == type) ||
+		    (USB_ENDPOINT_XFER_ISOC == type)) {
+			if (USB_DIR_IN & desc->bEndpointAddress)
+				ep = find_ep (gadget, "ep5in");
+			else
+				ep = find_ep (gadget, "ep6out");
+		} else if (USB_ENDPOINT_XFER_INT == type) {
+			if (USB_DIR_IN & desc->bEndpointAddress)
+				ep = find_ep(gadget, "ep1in");
+			else
+				ep = find_ep(gadget, "ep2out");
+		} else
+			ep = NULL;
 		if (ep && ep_matches (gadget, ep, desc))
 			return ep;
-
-	} else if (gadget_is_mq11xx (gadget) && USB_ENDPOINT_XFER_INT == type) {
-		ep = find_ep (gadget, "ep1-bulk");
-		if (ep && ep_matches (gadget, ep, desc))
-			return ep;
+#endif
 	}
 
 	/* Second, look at endpoints until an unclaimed one looks usable */
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 141372b..400f8037 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -259,7 +259,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef USB_ETH_EEM
+#ifdef CONFIG_USB_ETH_EEM
 static int use_eem = 1;
 #else
 static int use_eem;
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index d10353d..e49c732 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -702,14 +702,6 @@
 /* Some controllers can't support CDC ACM ... */
 static inline bool can_support_cdc(struct usb_configuration *c)
 {
-	/* SH3 doesn't support multiple interfaces */
-	if (gadget_is_sh(c->cdev->gadget))
-		return false;
-
-	/* sa1100 doesn't have a third interrupt endpoint */
-	if (gadget_is_sa1100(c->cdev->gadget))
-		return false;
-
 	/* everything else is *probably* fine ... */
 	return true;
 }
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index ecf5bdd..2fff530 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -497,12 +497,9 @@
 			struct net_device	*net;
 
 			/* Enable zlps by default for ECM conformance;
-			 * override for musb_hdrc (avoids txdma ovhead)
-			 * and sa1100 (can't).
+			 * override for musb_hdrc (avoids txdma ovhead).
 			 */
-			ecm->port.is_zlp_ok = !(
-				   gadget_is_sa1100(cdev->gadget)
-				|| gadget_is_musbhdrc(cdev->gadget)
+			ecm->port.is_zlp_ok = !(gadget_is_musbhdrc(cdev->gadget)
 				);
 			ecm->port.cdc_filter = DEFAULT_FILTER;
 			DBG(cdev, "activate ecm\n");
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index a37640e..5a3cdd0 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -368,7 +368,7 @@
 	struct task_struct	*thread_task;
 
 	/* Callback function to call when thread exits. */
-	void			(*thread_exits)(struct fsg_common *common);
+	int			(*thread_exits)(struct fsg_common *common);
 	/* Gadget's private data. */
 	void			*private_data;
 
@@ -392,8 +392,12 @@
 	const char		*lun_name_format;
 	const char		*thread_name;
 
-	/* Callback function to call when thread exits. */
-	void			(*thread_exits)(struct fsg_common *common);
+	/* 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). */
+	int			(*thread_exits)(struct fsg_common *common);
 	/* Gadget's private data. */
 	void			*private_data;
 
@@ -614,7 +618,12 @@
 			return -EDOM;
 		VDBG(fsg, "get max LUN\n");
 		*(u8 *) req->buf = fsg->common->nluns - 1;
-		return 1;
+
+		/* Respond with data/status */
+		req->length = min((u16)1, w_length);
+		fsg->common->ep0req_name =
+			ctrl->bRequestType & USB_DIR_IN ? "ep0-in" : "ep0-out";
+		return ep0_queue(fsg->common);
 	}
 
 	VDBG(fsg,
@@ -1041,7 +1050,7 @@
 	unsigned long	rc;
 
 	rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
-	VLDBG(curlun, "invalidate_inode_pages -> %ld\n", rc);
+	VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
 }
 
 static int do_verify(struct fsg_common *common)
@@ -2524,14 +2533,6 @@
 
 	case FSG_STATE_CONFIG_CHANGE:
 		rc = do_set_config(common, new_config);
-		if (common->ep0_req_tag != exception_req_tag)
-			break;
-		if (rc != 0) {			/* STALL on errors */
-			DBG(common, "ep0 set halt\n");
-			usb_ep_set_halt(common->ep0);
-		} else {			/* Complete the status stage */
-			ep0_queue(common);
-		}
 		break;
 
 	case FSG_STATE_EXIT:
@@ -2615,8 +2616,20 @@
 	common->thread_task = NULL;
 	spin_unlock_irq(&common->lock);
 
-	if (common->thread_exits)
-		common->thread_exits(common);
+	if (!common->thread_exits || common->thread_exits(common) < 0) {
+		struct fsg_lun *curlun = common->luns;
+		unsigned i = common->nluns;
+
+		down_write(&common->filesem);
+		for (; i--; ++curlun) {
+			if (!fsg_lun_is_open(curlun))
+				continue;
+
+			fsg_lun_close(curlun);
+			curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
+		}
+		up_write(&common->filesem);
+	}
 
 	/* Let the unbind and cleanup routines know the thread has exited */
 	complete_and_exit(&common->thread_notifier, 0);
@@ -2763,10 +2776,7 @@
 	if (cfg->release != 0xffff) {
 		i = cfg->release;
 	} else {
-		/* The sa1100 controller is not supported */
-		i = gadget_is_sa1100(gadget)
-			? -1
-			: usb_gadget_controller_number(gadget);
+		i = usb_gadget_controller_number(gadget);
 		if (i >= 0) {
 			i = 0x0300 + i;
 		} else {
@@ -2791,8 +2801,7 @@
 	 * disable stalls.
 	 */
 	common->can_stall = cfg->can_stall &&
-		!(gadget_is_sh(common->gadget) ||
-		  gadget_is_at91(common->gadget));
+		!(gadget_is_at91(common->gadget));
 
 
 	spin_lock_init(&common->lock);
@@ -2852,7 +2861,6 @@
 	/* Call fsg_common_release() directly, ref might be not
 	 * initialised */
 	fsg_common_release(&common->ref);
-	complete(&common->thread_notifier);
 	return ERR_PTR(rc);
 }
 
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 95dae4c..a30e60c 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -769,10 +769,6 @@
 /* Some controllers can't support RNDIS ... */
 static inline bool can_support_rndis(struct usb_configuration *c)
 {
-	/* only two endpoints on sa1100 */
-	if (gadget_is_sa1100(c->cdev->gadget))
-		return false;
-
 	/* everything else is *presumably* fine */
 	return true;
 }
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 29dfb02..b49d86e 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1448,7 +1448,7 @@
 	unsigned long	rc;
 
 	rc = invalidate_mapping_pages(inode->i_mapping, 0, -1);
-	VLDBG(curlun, "invalidate_inode_pages -> %ld\n", rc);
+	VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc);
 }
 
 static int do_verify(struct fsg_dev *fsg)
@@ -3208,15 +3208,11 @@
 	 * halt bulk endpoints correctly.  If one of them is present,
 	 * disable stalls.
 	 */
-	if (gadget_is_sh(fsg->gadget) || gadget_is_at91(fsg->gadget))
+	if (gadget_is_at91(fsg->gadget))
 		mod_data.can_stall = 0;
 
 	if (mod_data.release == 0xffff) {	// Parameter wasn't set
-		/* The sa1100 controller is not supported */
-		if (gadget_is_sa1100(fsg->gadget))
-			gcnum = -1;
-		else
-			gcnum = usb_gadget_controller_number(fsg->gadget);
+		gcnum = usb_gadget_controller_number(fsg->gadget);
 		if (gcnum >= 0)
 			mod_data.release = 0x0300 + gcnum;
 		else {
diff --git a/drivers/usb/gadget/fsl_mx3_udc.c b/drivers/usb/gadget/fsl_mx3_udc.c
index 4bc2bf3..20a802e 100644
--- a/drivers/usb/gadget/fsl_mx3_udc.c
+++ b/drivers/usb/gadget/fsl_mx3_udc.c
@@ -17,6 +17,8 @@
 #include <linux/fsl_devices.h>
 #include <linux/platform_device.h>
 
+#include <mach/hardware.h>
+
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_usb_clk;
 
@@ -28,14 +30,16 @@
 
 	pdata = pdev->dev.platform_data;
 
-	mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb");
-	if (IS_ERR(mxc_ahb_clk))
-		return PTR_ERR(mxc_ahb_clk);
+	if (!cpu_is_mx35()) {
+		mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb");
+		if (IS_ERR(mxc_ahb_clk))
+			return PTR_ERR(mxc_ahb_clk);
 
-	ret = clk_enable(mxc_ahb_clk);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "clk_enable(\"usb_ahb\") failed\n");
-		goto eenahb;
+		ret = clk_enable(mxc_ahb_clk);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "clk_enable(\"usb_ahb\") failed\n");
+			goto eenahb;
+		}
 	}
 
 	/* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
@@ -50,6 +54,7 @@
 	if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
 	    (freq < 59999000 || freq > 60001000)) {
 		dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
+		ret = -EINVAL;
 		goto eclkrate;
 	}
 
@@ -66,9 +71,11 @@
 	clk_put(mxc_usb_clk);
 	mxc_usb_clk = NULL;
 egusb:
-	clk_disable(mxc_ahb_clk);
+	if (!cpu_is_mx35())
+		clk_disable(mxc_ahb_clk);
 eenahb:
-	clk_put(mxc_ahb_clk);
+	if (!cpu_is_mx35())
+		clk_put(mxc_ahb_clk);
 	return ret;
 }
 
@@ -90,6 +97,8 @@
 		clk_disable(mxc_usb_clk);
 		clk_put(mxc_usb_clk);
 	}
-	clk_disable(mxc_ahb_clk);
-	clk_put(mxc_ahb_clk);
+	if (!cpu_is_mx35()) {
+		clk_disable(mxc_ahb_clk);
+		clk_put(mxc_ahb_clk);
+	}
 }
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 7881f12..3537d51 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2749,7 +2749,7 @@
 }
 
 /*-------------------------------------------------------------------------*/
-static struct of_device_id __devinitdata qe_udc_match[] = {
+static const struct of_device_id qe_udc_match[] __devinitconst = {
 	{
 		.compatible = "fsl,mpc8323-qe-usb",
 		.data = (void *)PORT_QE,
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index f2d270b..1edbc12 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -45,46 +45,18 @@
 #define	gadget_is_goku(g)	0
 #endif
 
-/* SH3 UDC -- not yet ported 2.4 --> 2.6 */
-#ifdef CONFIG_USB_GADGET_SUPERH
-#define	gadget_is_sh(g)		!strcmp("sh_udc", (g)->name)
-#else
-#define	gadget_is_sh(g)		0
-#endif
-
-/* not yet stable on 2.6 (would help "original Zaurus") */
-#ifdef CONFIG_USB_GADGET_SA1100
-#define	gadget_is_sa1100(g)	!strcmp("sa1100_udc", (g)->name)
-#else
-#define	gadget_is_sa1100(g)	0
-#endif
-
 #ifdef CONFIG_USB_GADGET_LH7A40X
 #define	gadget_is_lh7a40x(g)	!strcmp("lh7a40x_udc", (g)->name)
 #else
 #define	gadget_is_lh7a40x(g)	0
 #endif
 
-/* handhelds.org tree (?) */
-#ifdef CONFIG_USB_GADGET_MQ11XX
-#define	gadget_is_mq11xx(g)	!strcmp("mq11xx_udc", (g)->name)
-#else
-#define	gadget_is_mq11xx(g)	0
-#endif
-
 #ifdef CONFIG_USB_GADGET_OMAP
 #define	gadget_is_omap(g)	!strcmp("omap_udc", (g)->name)
 #else
 #define	gadget_is_omap(g)	0
 #endif
 
-/* not yet ported 2.4 --> 2.6 */
-#ifdef CONFIG_USB_GADGET_N9604
-#define	gadget_is_n9604(g)	!strcmp("n9604_udc", (g)->name)
-#else
-#define	gadget_is_n9604(g)	0
-#endif
-
 /* various unstable versions available */
 #ifdef CONFIG_USB_GADGET_PXA27X
 #define	gadget_is_pxa27x(g)	!strcmp("pxa27x_udc", (g)->name)
@@ -122,14 +94,6 @@
 #define gadget_is_fsl_usb2(g)	0
 #endif
 
-/* Mentor high speed function controller */
-/* from Montavista kernel (?) */
-#ifdef CONFIG_USB_GADGET_MUSBHSFC
-#define gadget_is_musbhsfc(g)	!strcmp("musbhsfc_udc", (g)->name)
-#else
-#define gadget_is_musbhsfc(g)	0
-#endif
-
 /* 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)
@@ -143,13 +107,6 @@
 #define gadget_is_langwell(g)	0
 #endif
 
-/* from Montavista kernel (?) */
-#ifdef CONFIG_USB_GADGET_MPC8272
-#define gadget_is_mpc8272(g)	!strcmp("mpc8272_udc", (g)->name)
-#else
-#define gadget_is_mpc8272(g)	0
-#endif
-
 #ifdef CONFIG_USB_GADGET_M66592
 #define	gadget_is_m66592(g)	!strcmp("m66592_udc", (g)->name)
 #else
@@ -203,20 +160,12 @@
 		return 0x02;
 	else if (gadget_is_pxa(gadget))
 		return 0x03;
-	else if (gadget_is_sh(gadget))
-		return 0x04;
-	else if (gadget_is_sa1100(gadget))
-		return 0x05;
 	else if (gadget_is_goku(gadget))
 		return 0x06;
-	else if (gadget_is_mq11xx(gadget))
-		return 0x07;
 	else if (gadget_is_omap(gadget))
 		return 0x08;
 	else if (gadget_is_lh7a40x(gadget))
 		return 0x09;
-	else if (gadget_is_n9604(gadget))
-		return 0x10;
 	else if (gadget_is_pxa27x(gadget))
 		return 0x11;
 	else if (gadget_is_s3c2410(gadget))
@@ -225,12 +174,8 @@
 		return 0x13;
 	else if (gadget_is_imx(gadget))
 		return 0x14;
-	else if (gadget_is_musbhsfc(gadget))
-		return 0x15;
 	else if (gadget_is_musbhdrc(gadget))
 		return 0x16;
-	else if (gadget_is_mpc8272(gadget))
-		return 0x17;
 	else if (gadget_is_atmel_usba(gadget))
 		return 0x18;
 	else if (gadget_is_fsl_usb2(gadget))
@@ -265,10 +210,6 @@
 	if (gadget_is_pxa27x(gadget))
 		return false;
 
-	/* SH3 hardware just doesn't do altsettings */
-	if (gadget_is_sh(gadget))
-		return false;
-
 	/* Everything else is *presumably* fine ... */
 	return true;
 }
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 5f6a2e0..04f6224 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -618,11 +618,6 @@
 	}
 #endif
 
-	if (gadget_is_sa1100(gadget) && dev->config) {
-		/* tx fifo is full, but we can't clear it...*/
-		ERROR(dev, "can't change configurations\n");
-		return -ESPIPE;
-	}
 	gmidi_reset_config(dev);
 
 	switch (number) {
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 112bb40..e8edc64 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1859,7 +1859,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static struct pci_device_id pci_ids [] = { {
+static const struct pci_device_id pci_ids[] = { {
 	.class =	((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
 	.class_mask =	~0,
 	.vendor =	0x102f,		/* Toshiba */
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index bf0f652..de8a838 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -194,7 +194,7 @@
 };
 
 struct ep_data {
-	struct semaphore		lock;
+	struct mutex			lock;
 	enum ep_state			state;
 	atomic_t			count;
 	struct dev_data			*dev;
@@ -298,10 +298,10 @@
 	int	val;
 
 	if (f_flags & O_NONBLOCK) {
-		if (down_trylock (&epdata->lock) != 0)
+		if (!mutex_trylock(&epdata->lock))
 			goto nonblock;
 		if (epdata->state != STATE_EP_ENABLED) {
-			up (&epdata->lock);
+			mutex_unlock(&epdata->lock);
 nonblock:
 			val = -EAGAIN;
 		} else
@@ -309,7 +309,8 @@
 		return val;
 	}
 
-	if ((val = down_interruptible (&epdata->lock)) < 0)
+	val = mutex_lock_interruptible(&epdata->lock);
+	if (val < 0)
 		return val;
 
 	switch (epdata->state) {
@@ -323,7 +324,7 @@
 		// FALLTHROUGH
 	case STATE_EP_UNBOUND:			/* clean disconnect */
 		val = -ENODEV;
-		up (&epdata->lock);
+		mutex_unlock(&epdata->lock);
 	}
 	return val;
 }
@@ -393,7 +394,7 @@
 		if (likely (data->ep != NULL))
 			usb_ep_set_halt (data->ep);
 		spin_unlock_irq (&data->dev->lock);
-		up (&data->lock);
+		mutex_unlock(&data->lock);
 		return -EBADMSG;
 	}
 
@@ -411,7 +412,7 @@
 		value = -EFAULT;
 
 free1:
-	up (&data->lock);
+	mutex_unlock(&data->lock);
 	kfree (kbuf);
 	return value;
 }
@@ -436,7 +437,7 @@
 		if (likely (data->ep != NULL))
 			usb_ep_set_halt (data->ep);
 		spin_unlock_irq (&data->dev->lock);
-		up (&data->lock);
+		mutex_unlock(&data->lock);
 		return -EBADMSG;
 	}
 
@@ -455,7 +456,7 @@
 	VDEBUG (data->dev, "%s write %zu IN, status %d\n",
 		data->name, len, (int) value);
 free1:
-	up (&data->lock);
+	mutex_unlock(&data->lock);
 	kfree (kbuf);
 	return value;
 }
@@ -466,7 +467,8 @@
 	struct ep_data		*data = fd->private_data;
 	int value;
 
-	if ((value = down_interruptible(&data->lock)) < 0)
+	value = mutex_lock_interruptible(&data->lock);
+	if (value < 0)
 		return value;
 
 	/* clean up if this can be reopened */
@@ -476,7 +478,7 @@
 		data->hs_desc.bDescriptorType = 0;
 		usb_ep_disable(data->ep);
 	}
-	up (&data->lock);
+	mutex_unlock(&data->lock);
 	put_ep (data);
 	return 0;
 }
@@ -507,7 +509,7 @@
 	} else
 		status = -ENODEV;
 	spin_unlock_irq (&data->dev->lock);
-	up (&data->lock);
+	mutex_unlock(&data->lock);
 	return status;
 }
 
@@ -673,7 +675,7 @@
 		value = -ENODEV;
 	spin_unlock_irq(&epdata->dev->lock);
 
-	up(&epdata->lock);
+	mutex_unlock(&epdata->lock);
 
 	if (unlikely(value)) {
 		kfree(priv);
@@ -765,7 +767,8 @@
 	u32			tag;
 	int			value, length = len;
 
-	if ((value = down_interruptible (&data->lock)) < 0)
+	value = mutex_lock_interruptible(&data->lock);
+	if (value < 0)
 		return value;
 
 	if (data->state != STATE_EP_READY) {
@@ -854,7 +857,7 @@
 		data->desc.bDescriptorType = 0;
 		data->hs_desc.bDescriptorType = 0;
 	}
-	up (&data->lock);
+	mutex_unlock(&data->lock);
 	return value;
 fail0:
 	value = -EINVAL;
@@ -870,7 +873,7 @@
 	struct ep_data		*data = inode->i_private;
 	int			value = -EBUSY;
 
-	if (down_interruptible (&data->lock) != 0)
+	if (mutex_lock_interruptible(&data->lock) != 0)
 		return -EINTR;
 	spin_lock_irq (&data->dev->lock);
 	if (data->dev->state == STATE_DEV_UNBOUND)
@@ -885,7 +888,7 @@
 		DBG (data->dev, "%s state %d\n",
 			data->name, data->state);
 	spin_unlock_irq (&data->dev->lock);
-	up (&data->lock);
+	mutex_unlock(&data->lock);
 	return value;
 }
 
@@ -1631,7 +1634,7 @@
 		if (!data)
 			goto enomem0;
 		data->state = STATE_EP_DISABLED;
-		init_MUTEX (&data->lock);
+		mutex_init(&data->lock);
 		init_waitqueue_head (&data->wait);
 
 		strncpy (data->name, ep->name, sizeof (data->name) - 1);
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 19619fb..705cc1f 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -135,6 +135,12 @@
 static unsigned long msg_registered = 0;
 static void msg_cleanup(void);
 
+static int msg_thread_exits(struct fsg_common *common)
+{
+	msg_cleanup();
+	return 0;
+}
+
 static int __init msg_do_config(struct usb_configuration *c)
 {
 	struct fsg_common *common;
@@ -147,7 +153,7 @@
 	}
 
 	fsg_config_from_params(&config, &mod_data);
-	config.thread_exits = (void(*)(struct fsg_common*))&msg_cleanup;
+	config.thread_exits = msg_thread_exits;
 	common = fsg_common_init(0, c->cdev, &config);
 	if (IS_ERR(common))
 		return PTR_ERR(common);
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c
new file mode 100644
index 0000000..7d6b66a
--- /dev/null
+++ b/drivers/usb/gadget/nokia.c
@@ -0,0 +1,259 @@
+/*
+ * nokia.c -- Nokia Composite Gadget Driver
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ * Contact: Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * This gadget driver borrows from serial.c which is:
+ *
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 by David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * version 2 of that License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+
+#include "u_serial.h"
+#include "u_ether.h"
+#include "u_phonet.h"
+#include "gadget_chips.h"
+
+/* Defines */
+
+#define NOKIA_VERSION_NUM		0x0211
+#define NOKIA_LONG_NAME			"N900 (PC-Suite Mode)"
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * 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 "u_serial.c"
+#include "f_acm.c"
+#include "f_ecm.c"
+#include "f_obex.c"
+#include "f_serial.c"
+#include "f_phonet.c"
+#include "u_ether.c"
+
+/*-------------------------------------------------------------------------*/
+
+#define NOKIA_VENDOR_ID			0x0421	/* Nokia */
+#define NOKIA_PRODUCT_ID		0x01c8	/* Nokia Gadget */
+
+/* string IDs are assigned dynamically */
+
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
+#define STRING_DESCRIPTION_IDX		2
+
+static char manufacturer_nokia[] = "Nokia";
+static const char product_nokia[] = NOKIA_LONG_NAME;
+static const char description_nokia[] = "PC-Suite Configuration";
+
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer_nokia,
+	[STRING_PRODUCT_IDX].s = NOKIA_LONG_NAME,
+	[STRING_DESCRIPTION_IDX].s = description_nokia,
+	{  } /* 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 struct usb_device_descriptor device_desc = {
+	.bLength		= USB_DT_DEVICE_SIZE,
+	.bDescriptorType	= USB_DT_DEVICE,
+	.bcdUSB			= __constant_cpu_to_le16(0x0200),
+	.bDeviceClass		= USB_CLASS_COMM,
+	.idVendor		= __constant_cpu_to_le16(NOKIA_VENDOR_ID),
+	.idProduct		= __constant_cpu_to_le16(NOKIA_PRODUCT_ID),
+	/* .iManufacturer = DYNAMIC */
+	/* .iProduct = DYNAMIC */
+	.bNumConfigurations =	1,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Module */
+MODULE_DESCRIPTION("Nokia composite gadget driver for N900");
+MODULE_AUTHOR("Felipe Balbi");
+MODULE_LICENSE("GPL");
+
+/*-------------------------------------------------------------------------*/
+
+static u8 hostaddr[ETH_ALEN];
+
+static int __init nokia_bind_config(struct usb_configuration *c)
+{
+	int status = 0;
+
+	status = phonet_bind_config(c);
+	if (status)
+		printk(KERN_DEBUG "could not bind phonet config\n");
+
+	status = obex_bind_config(c, 0);
+	if (status)
+		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
+
+	status = obex_bind_config(c, 1);
+	if (status)
+		printk(KERN_DEBUG "could not bind obex config %d\n", 0);
+
+	status = acm_bind_config(c, 2);
+	if (status)
+		printk(KERN_DEBUG "could not bind acm config\n");
+
+	status = ecm_bind_config(c, hostaddr);
+	if (status)
+		printk(KERN_DEBUG "could not bind ecm config\n");
+
+	return status;
+}
+
+static struct usb_configuration nokia_config_500ma_driver = {
+	.label		= "Bus Powered",
+	.bind		= nokia_bind_config,
+	.bConfigurationValue = 1,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes	= USB_CONFIG_ATT_ONE,
+	.bMaxPower	= 250, /* 500mA */
+};
+
+static struct usb_configuration nokia_config_100ma_driver = {
+	.label		= "Self Powered",
+	.bind		= nokia_bind_config,
+	.bConfigurationValue = 2,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes	= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower	= 50, /* 100 mA */
+};
+
+static int __init nokia_bind(struct usb_composite_dev *cdev)
+{
+	int			gcnum;
+	struct usb_gadget	*gadget = cdev->gadget;
+	int			status;
+
+	status = gphonet_setup(cdev->gadget);
+	if (status < 0)
+		goto err_phonet;
+
+	status = gserial_setup(cdev->gadget, 3);
+	if (status < 0)
+		goto err_serial;
+
+	status = gether_setup(cdev->gadget, hostaddr);
+	if (status < 0)
+		goto err_ether;
+
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto err_usb;
+	strings_dev[STRING_MANUFACTURER_IDX].id = status;
+
+	device_desc.iManufacturer = status;
+
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto err_usb;
+	strings_dev[STRING_PRODUCT_IDX].id = status;
+
+	device_desc.iProduct = status;
+
+	/* config description */
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto err_usb;
+	strings_dev[STRING_DESCRIPTION_IDX].id = status;
+
+	nokia_config_500ma_driver.iConfiguration = status;
+	nokia_config_100ma_driver.iConfiguration = status;
+
+	/* set up other descriptors */
+	gcnum = usb_gadget_controller_number(gadget);
+	if (gcnum >= 0)
+		device_desc.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM);
+	else {
+		/* this should only work with hw that supports altsettings
+		 * and several endpoints, anything else, panic.
+		 */
+		pr_err("nokia_bind: controller '%s' not recognized\n",
+			gadget->name);
+		goto err_usb;
+	}
+
+	/* finaly register the configuration */
+	status = usb_add_config(cdev, &nokia_config_500ma_driver);
+	if (status < 0)
+		goto err_usb;
+
+	status = usb_add_config(cdev, &nokia_config_100ma_driver);
+	if (status < 0)
+		goto err_usb;
+
+	dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
+
+	return 0;
+
+err_usb:
+	gether_cleanup();
+err_ether:
+	gserial_cleanup();
+err_serial:
+	gphonet_cleanup();
+err_phonet:
+	return status;
+}
+
+static int __exit nokia_unbind(struct usb_composite_dev *cdev)
+{
+	gphonet_cleanup();
+	gserial_cleanup();
+	gether_cleanup();
+
+	return 0;
+}
+
+static struct usb_composite_driver nokia_driver = {
+	.name		= "g_nokia",
+	.dev		= &device_desc,
+	.strings	= dev_strings,
+	.bind		= nokia_bind,
+	.unbind		= __exit_p(nokia_unbind),
+};
+
+static int __init nokia_init(void)
+{
+	return usb_composite_register(&nokia_driver);
+}
+module_init(nokia_init);
+
+static void __exit nokia_cleanup(void)
+{
+	usb_composite_unregister(&nokia_driver);
+}
+module_exit(nokia_cleanup);
+
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 2d867fd..6b8bf8c 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -949,12 +949,6 @@
 	int			result = 0;
 	struct usb_gadget	*gadget = dev->gadget;
 
-	if (gadget_is_sa1100(gadget) && dev->config) {
-		/* tx fifo is full, but we can't clear it...*/
-		INFO(dev, "can't change configurations\n");
-		return -ESPIPE;
-	}
-
 	switch (number) {
 	case DEV_CONFIG_VALUE:
 		result = 0;
@@ -1033,12 +1027,6 @@
 {
 	int			result = 0;
 
-	if (gadget_is_sa1100(dev->gadget) && dev->interface < 0) {
-		/* tx fifo is full, but we can't clear it...*/
-		INFO(dev, "can't change interfaces\n");
-		return -ESPIPE;
-	}
-
 	/* Free the current interface */
 	switch (dev->interface) {
 	case PRINTER_INTERFACE:
@@ -1392,12 +1380,6 @@
 		goto fail;
 	}
 
-	if (gadget_is_sa1100(gadget)) {
-		/* hardware can't write zero length packets. */
-		ERROR(dev, "SA1100 controller is unsupport by this driver\n");
-		goto fail;
-	}
-
 	gcnum = usb_gadget_controller_number(gadget);
 	if (gcnum >= 0) {
 		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index e6fedbd..be5fb34 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -65,6 +65,10 @@
 #include <mach/pxa25x-udc.h>
 #endif
 
+#ifdef CONFIG_ARCH_LUBBOCK
+#include <mach/lubbock.h>
+#endif
+
 #include <asm/mach/udc_pxa2xx.h>
 
 
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index adda120..05b892c 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -742,13 +742,17 @@
  * @ep: pxa physical endpoint
  * @req: pxa request
  * @status: usb request status sent to gadget API
+ * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
  *
- * Context: ep->lock held
+ * Context: ep->lock held if flags not NULL, else ep->lock released
  *
  * Retire a pxa27x usb request. Endpoint must be locked.
  */
-static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status)
+static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status,
+	unsigned long *pflags)
 {
+	unsigned long	flags;
+
 	ep_del_request(ep, req);
 	if (likely(req->req.status == -EINPROGRESS))
 		req->req.status = status;
@@ -760,38 +764,48 @@
 			&req->req, status,
 			req->req.actual, req->req.length);
 
+	if (pflags)
+		spin_unlock_irqrestore(&ep->lock, *pflags);
+	local_irq_save(flags);
 	req->req.complete(&req->udc_usb_ep->usb_ep, &req->req);
+	local_irq_restore(flags);
+	if (pflags)
+		spin_lock_irqsave(&ep->lock, *pflags);
 }
 
 /**
  * ep_end_out_req - Ends endpoint OUT request
  * @ep: physical endpoint
  * @req: pxa request
+ * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
  *
- * Context: ep->lock held
+ * Context: ep->lock held or released (see req_done())
  *
  * Ends endpoint OUT request (completes usb request).
  */
-static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
+static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req,
+	unsigned long *pflags)
 {
 	inc_ep_stats_reqs(ep, !USB_DIR_IN);
-	req_done(ep, req, 0);
+	req_done(ep, req, 0, pflags);
 }
 
 /**
  * ep0_end_out_req - Ends control endpoint OUT request (ends data stage)
  * @ep: physical endpoint
  * @req: pxa request
+ * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
  *
- * Context: ep->lock held
+ * Context: ep->lock held or released (see req_done())
  *
  * Ends control endpoint OUT request (completes usb request), and puts
  * control endpoint into idle state
  */
-static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
+static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req,
+	unsigned long *pflags)
 {
 	set_ep0state(ep->dev, OUT_STATUS_STAGE);
-	ep_end_out_req(ep, req);
+	ep_end_out_req(ep, req, pflags);
 	ep0_idle(ep->dev);
 }
 
@@ -799,31 +813,35 @@
  * ep_end_in_req - Ends endpoint IN request
  * @ep: physical endpoint
  * @req: pxa request
+ * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
  *
- * Context: ep->lock held
+ * Context: ep->lock held or released (see req_done())
  *
  * Ends endpoint IN request (completes usb request).
  */
-static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
+static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req,
+	unsigned long *pflags)
 {
 	inc_ep_stats_reqs(ep, USB_DIR_IN);
-	req_done(ep, req, 0);
+	req_done(ep, req, 0, pflags);
 }
 
 /**
  * ep0_end_in_req - Ends control endpoint IN request (ends data stage)
  * @ep: physical endpoint
  * @req: pxa request
+ * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held
  *
- * Context: ep->lock held
+ * Context: ep->lock held or released (see req_done())
  *
  * Ends control endpoint IN request (completes usb request), and puts
  * control endpoint into status state
  */
-static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
+static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req,
+	unsigned long *pflags)
 {
 	set_ep0state(ep->dev, IN_STATUS_STAGE);
-	ep_end_in_req(ep, req);
+	ep_end_in_req(ep, req, pflags);
 }
 
 /**
@@ -831,19 +849,22 @@
  * @ep: pxa endpoint
  * @status: usb request status
  *
- * Context: ep->lock held
+ * Context: ep->lock released
  *
  * Dequeues all requests on an endpoint. As a side effect, interrupts will be
  * disabled on that endpoint (because no more requests).
  */
 static void nuke(struct pxa_ep *ep, int status)
 {
-	struct pxa27x_request *req;
+	struct pxa27x_request	*req;
+	unsigned long		flags;
 
+	spin_lock_irqsave(&ep->lock, flags);
 	while (!list_empty(&ep->queue)) {
 		req = list_entry(ep->queue.next, struct pxa27x_request, queue);
-		req_done(ep, req, status);
+		req_done(ep, req, status, &flags);
 	}
+	spin_unlock_irqrestore(&ep->lock, flags);
 }
 
 /**
@@ -1123,6 +1144,7 @@
 	int			rc = 0;
 	int			is_first_req;
 	unsigned		length;
+	int			recursion_detected;
 
 	req = container_of(_req, struct pxa27x_request, req);
 	udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
@@ -1152,6 +1174,7 @@
 		return -EMSGSIZE;
 
 	spin_lock_irqsave(&ep->lock, flags);
+	recursion_detected = ep->in_handle_ep;
 
 	is_first_req = list_empty(&ep->queue);
 	ep_dbg(ep, "queue req %p(first=%s), len %d buf %p\n",
@@ -1161,12 +1184,12 @@
 	if (!ep->enabled) {
 		_req->status = -ESHUTDOWN;
 		rc = -ESHUTDOWN;
-		goto out;
+		goto out_locked;
 	}
 
 	if (req->in_use) {
 		ep_err(ep, "refusing to queue req %p (already queued)\n", req);
-		goto out;
+		goto out_locked;
 	}
 
 	length = _req->length;
@@ -1174,12 +1197,13 @@
 	_req->actual = 0;
 
 	ep_add_request(ep, req);
+	spin_unlock_irqrestore(&ep->lock, flags);
 
 	if (is_ep0(ep)) {
 		switch (dev->ep0state) {
 		case WAIT_ACK_SET_CONF_INTERF:
 			if (length == 0) {
-				ep_end_in_req(ep, req);
+				ep_end_in_req(ep, req, NULL);
 			} else {
 				ep_err(ep, "got a request of %d bytes while"
 					"in state WAIT_ACK_SET_CONF_INTERF\n",
@@ -1192,12 +1216,12 @@
 		case IN_DATA_STAGE:
 			if (!ep_is_full(ep))
 				if (write_ep0_fifo(ep, req))
-					ep0_end_in_req(ep, req);
+					ep0_end_in_req(ep, req, NULL);
 			break;
 		case OUT_DATA_STAGE:
 			if ((length == 0) || !epout_has_pkt(ep))
 				if (read_ep0_fifo(ep, req))
-					ep0_end_out_req(ep, req);
+					ep0_end_out_req(ep, req, NULL);
 			break;
 		default:
 			ep_err(ep, "odd state %s to send me a request\n",
@@ -1207,12 +1231,15 @@
 			break;
 		}
 	} else {
-		handle_ep(ep);
+		if (!recursion_detected)
+			handle_ep(ep);
 	}
 
 out:
-	spin_unlock_irqrestore(&ep->lock, flags);
 	return rc;
+out_locked:
+	spin_unlock_irqrestore(&ep->lock, flags);
+	goto out;
 }
 
 /**
@@ -1242,13 +1269,14 @@
 	/* make sure it's actually queued on this endpoint */
 	list_for_each_entry(req, &ep->queue, queue) {
 		if (&req->req == _req) {
-			req_done(ep, req, -ECONNRESET);
 			rc = 0;
 			break;
 		}
 	}
 
 	spin_unlock_irqrestore(&ep->lock, flags);
+	if (!rc)
+		req_done(ep, req, -ECONNRESET, NULL);
 	return rc;
 }
 
@@ -1445,7 +1473,6 @@
 {
 	struct pxa_ep		*ep;
 	struct udc_usb_ep	*udc_usb_ep;
-	unsigned long		flags;
 
 	if (!_ep)
 		return -EINVAL;
@@ -1455,10 +1482,8 @@
 	if (!ep || is_ep0(ep) || !list_empty(&ep->queue))
 		return -EINVAL;
 
-	spin_lock_irqsave(&ep->lock, flags);
 	ep->enabled = 0;
 	nuke(ep, -ESHUTDOWN);
-	spin_unlock_irqrestore(&ep->lock, flags);
 
 	pxa_ep_fifo_flush(_ep);
 	udc_usb_ep->pxa_ep = NULL;
@@ -1907,8 +1932,10 @@
 	} u;
 	int i;
 	int have_extrabytes = 0;
+	unsigned long flags;
 
 	nuke(ep, -EPROTO);
+	spin_lock_irqsave(&ep->lock, flags);
 
 	/*
 	 * In the PXA320 manual, in the section about Back-to-Back setup
@@ -1947,10 +1974,13 @@
 	/* Tell UDC to enter Data Stage */
 	ep_write_UDCCSR(ep, UDCCSR0_SA | UDCCSR0_OPC);
 
+	spin_unlock_irqrestore(&ep->lock, flags);
 	i = udc->driver->setup(&udc->gadget, &u.r);
+	spin_lock_irqsave(&ep->lock, flags);
 	if (i < 0)
 		goto stall;
 out:
+	spin_unlock_irqrestore(&ep->lock, flags);
 	return;
 stall:
 	ep_dbg(ep, "protocol STALL, udccsr0=%03x err %d\n",
@@ -2055,13 +2085,13 @@
 		if (req && !ep_is_full(ep))
 			completed = write_ep0_fifo(ep, req);
 		if (completed)
-			ep0_end_in_req(ep, req);
+			ep0_end_in_req(ep, req, NULL);
 		break;
 	case OUT_DATA_STAGE:			/* SET_DESCRIPTOR */
 		if (epout_has_pkt(ep) && req)
 			completed = read_ep0_fifo(ep, req);
 		if (completed)
-			ep0_end_out_req(ep, req);
+			ep0_end_out_req(ep, req, NULL);
 		break;
 	case STALL:
 		ep_write_UDCCSR(ep, UDCCSR0_FST);
@@ -2091,7 +2121,7 @@
  * Tries to transfer all pending request data into the endpoint and/or
  * transfer all pending data in the endpoint into usb requests.
  *
- * Is always called when in_interrupt() or with ep->lock held.
+ * Is always called when in_interrupt() and with ep->lock released.
  */
 static void handle_ep(struct pxa_ep *ep)
 {
@@ -2100,10 +2130,17 @@
 	u32 udccsr;
 	int is_in = ep->dir_in;
 	int loop = 0;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&ep->lock, flags);
+	if (ep->in_handle_ep)
+		goto recursion_detected;
+	ep->in_handle_ep = 1;
 
 	do {
 		completed = 0;
 		udccsr = udc_ep_readl(ep, UDCCSR);
+
 		if (likely(!list_empty(&ep->queue)))
 			req = list_entry(ep->queue.next,
 					struct pxa27x_request, queue);
@@ -2122,15 +2159,22 @@
 		if (unlikely(is_in)) {
 			if (likely(!ep_is_full(ep)))
 				completed = write_fifo(ep, req);
-			if (completed)
-				ep_end_in_req(ep, req);
 		} else {
 			if (likely(epout_has_pkt(ep)))
 				completed = read_fifo(ep, req);
-			if (completed)
-				ep_end_out_req(ep, req);
+		}
+
+		if (completed) {
+			if (is_in)
+				ep_end_in_req(ep, req, &flags);
+			else
+				ep_end_out_req(ep, req, &flags);
 		}
 	} while (completed);
+
+	ep->in_handle_ep = 0;
+recursion_detected:
+	spin_unlock_irqrestore(&ep->lock, flags);
 }
 
 /**
@@ -2218,9 +2262,13 @@
 			continue;
 
 		udc_writel(udc, UDCISR0, UDCISR_INT(i, UDCISR_INT_MASK));
-		ep = &udc->pxa_ep[i];
-		ep->stats.irqs++;
-		handle_ep(ep);
+
+		WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep));
+		if (i < ARRAY_SIZE(udc->pxa_ep)) {
+			ep = &udc->pxa_ep[i];
+			ep->stats.irqs++;
+			handle_ep(ep);
+		}
 	}
 
 	for (i = 16; udcisr1 != 0 && i < 24; udcisr1 >>= 2, i++) {
@@ -2228,9 +2276,12 @@
 		if (!(udcisr1 & UDCISR_INT_MASK))
 			continue;
 
-		ep = &udc->pxa_ep[i];
-		ep->stats.irqs++;
-		handle_ep(ep);
+		WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep));
+		if (i < ARRAY_SIZE(udc->pxa_ep)) {
+			ep = &udc->pxa_ep[i];
+			ep->stats.irqs++;
+			handle_ep(ep);
+		}
 	}
 
 }
@@ -2439,7 +2490,7 @@
 	}
 
 	retval = -ENOMEM;
-	udc->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	udc->regs = ioremap(regs->start, resource_size(regs));
 	if (!udc->regs) {
 		dev_err(&pdev->dev, "Unable to map UDC I/O memory\n");
 		goto err_map;
diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h
index e25225e..ff61e48 100644
--- a/drivers/usb/gadget/pxa27x_udc.h
+++ b/drivers/usb/gadget/pxa27x_udc.h
@@ -318,6 +318,11 @@
  * @queue: requests queue
  * @lock: lock to pxa_ep data (queues and stats)
  * @enabled: true when endpoint enabled (not stopped by gadget layer)
+ * @in_handle_ep: number of recursions of handle_ep() function
+ * 	Prevents deadlocks or infinite recursions of types :
+ *	  irq->handle_ep()->req_done()->req.complete()->pxa_ep_queue()->handle_ep()
+ *      or
+ *        pxa_ep_queue()->handle_ep()->req_done()->req.complete()->pxa_ep_queue()
  * @idx: endpoint index (1 => epA, 2 => epB, ..., 24 => epX)
  * @name: endpoint name (for trace/debug purpose)
  * @dir_in: 1 if IN endpoint, 0 if OUT endpoint
@@ -346,6 +351,7 @@
 	spinlock_t		lock;		/* Protects this structure */
 						/* (queues, stats) */
 	unsigned		enabled:1;
+	unsigned		in_handle_ep:1;
 
 	unsigned		idx:5;
 	char			*name;
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 5fc80a1..f742c8e 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -30,7 +30,7 @@
 
 #include <plat/regs-usb-hsotg-phy.h>
 #include <plat/regs-usb-hsotg.h>
-#include <plat/regs-sys.h>
+#include <mach/regs-sys.h>
 #include <plat/udc-hs.h>
 
 #define DMA_ADDR_INVALID (~((dma_addr_t)0))
@@ -317,7 +317,8 @@
  *
  * Allocate a new USB request structure appropriate for the specified endpoint
  */
-struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep, gfp_t flags)
+static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
+						      gfp_t flags)
 {
 	struct s3c_hsotg_req *req;
 
@@ -373,7 +374,7 @@
 		req->dma = DMA_ADDR_INVALID;
 		hs_req->mapped = 0;
 	} else {
-		dma_sync_single(hsotg->dev, req->dma, req->length, dir);
+		dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
 	}
 }
 
@@ -755,7 +756,7 @@
 		hs_req->mapped = 1;
 		req->dma = dma;
 	} else {
-		dma_sync_single(hsotg->dev, req->dma, req->length, dir);
+		dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
 		hs_req->mapped = 0;
 	}
 
@@ -1460,7 +1461,7 @@
  * as the actual data should be sent to the memory directly and we turn
  * on the completion interrupts to get notifications of transfer completion.
  */
-void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
+static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
 {
 	u32 grxstsr = readl(hsotg->regs + S3C_GRXSTSP);
 	u32 epnum, status, size;
@@ -3094,7 +3095,7 @@
 	local_irq_restore(flags);
 }
 
-struct s3c_hsotg_plat s3c_hsotg_default_pdata;
+static struct s3c_hsotg_plat s3c_hsotg_default_pdata;
 
 static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 {
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 2fc02bd..84ca195 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -746,6 +746,10 @@
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
+static struct device_type gadget_type = {
+	.name	= "gadget",
+};
+
 /**
  * gether_setup - initialize one ethernet-over-usb link
  * @g: gadget to associated with these links
@@ -808,6 +812,7 @@
 
 	dev->gadget = g;
 	SET_NETDEV_DEV(net, &g->dev);
+	SET_NETDEV_DEVTYPE(net, &gadget_type);
 
 	status = register_netdev(net);
 	if (status < 0) {
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index fd55f45..3c8c0c9 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -93,13 +93,6 @@
 	if (!gadget_supports_altsettings(gadget))
 		return false;
 
-	/* SA1100 can do ECM, *without* status endpoint ... but we'll
-	 * only use it in non-ECM mode for backwards compatibility
-	 * (and since we currently require a status endpoint)
-	 */
-	if (gadget_is_sa1100(gadget))
-		return false;
-
 	/* Everything else is *presumably* fine ... but this is a bit
 	 * chancy, so be **CERTAIN** there are no hardware issues with
 	 * your controller.  Add it above if it can't handle CDC.
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 2d77240..fac81ee 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -297,12 +297,10 @@
 	 */
 	if (loopdefault) {
 		loopback_add(cdev, autoresume != 0);
-		if (!gadget_is_sh(gadget))
-			sourcesink_add(cdev, autoresume != 0);
+		sourcesink_add(cdev, autoresume != 0);
 	} else {
 		sourcesink_add(cdev, autoresume != 0);
-		if (!gadget_is_sh(gadget))
-			loopback_add(cdev, autoresume != 0);
+		loopback_add(cdev, autoresume != 0);
 	}
 
 	gcnum = usb_gadget_controller_number(gadget);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 2678a16..8d3df03 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -399,3 +399,14 @@
 
 	  To compile this driver a module, choose M here: the module
 	  will be called "hwa-hc".
+
+config USB_IMX21_HCD
+       tristate "iMX21 HCD support"
+       depends on USB && ARM && MACH_MX21
+       help
+         This driver enables support for the on-chip USB host in the
+         iMX21 processor.
+
+         To compile this driver as a module, choose M here: the
+         module will be called "imx21-hcd".
+
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index f58b249..4e0c67f 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -32,3 +32,5 @@
 obj-$(CONFIG_USB_R8A66597_HCD)	+= r8a66597-hcd.o
 obj-$(CONFIG_USB_ISP1760_HCD)	+= isp1760.o
 obj-$(CONFIG_USB_HWA_HCD)	+= hwa-hc.o
+obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd.o
+
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 87c1b7c..51bd0ed 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -149,7 +149,7 @@
 		goto fail_request_resource;
 	}
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->rsrc_len = resource_size(res);
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
 				driver->description)) {
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index dbfb482..e3a74e7 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -121,6 +121,7 @@
 {
 	struct usb_hcd *hcd;
 	struct ehci_hcd *ehci;
+	struct resource *res;
 	int ret;
 
 	if (usb_disabled())
@@ -144,8 +145,9 @@
 	if (!hcd)
 		return -ENOMEM;
 
-	hcd->rsrc_start = pdev->resource[0].start;
-	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+	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");
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 9911749..0e26aa1 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2005 MontaVista Software
+ * Copyright 2005-2009 MontaVista Software, Inc.
+ * Copyright 2008      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
@@ -17,17 +18,20 @@
  *
  * Ported to 834x by Randy Vinson <rvinson@mvista.com> using code provided
  * by Hunter Wu.
+ * Power Management support by Dave Liu <daveliu@freescale.com>,
+ * Jerry Huang <Chang-Ming.Huang@freescale.com> and
+ * Anton Vorontsov <avorontsov@ru.mvista.com>.
  */
 
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
 #include <linux/platform_device.h>
 #include <linux/fsl_devices.h>
 
 #include "ehci-fsl.h"
 
-/* FIXME: Power Management is un-ported so temporarily disable it */
-#undef CONFIG_PM
-
-
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
 
@@ -40,8 +44,8 @@
  * Allocates basic resources for this USB host controller.
  *
  */
-int usb_hcd_fsl_probe(const struct hc_driver *driver,
-		      struct platform_device *pdev)
+static int usb_hcd_fsl_probe(const struct hc_driver *driver,
+			     struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata;
 	struct usb_hcd *hcd;
@@ -147,7 +151,8 @@
  * Reverses the effect of usb_hcd_fsl_probe().
  *
  */
-void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct platform_device *pdev)
+static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
+			       struct platform_device *pdev)
 {
 	usb_remove_hcd(hcd);
 	iounmap(hcd->regs);
@@ -284,10 +289,81 @@
 	return retval;
 }
 
+struct ehci_fsl {
+	struct ehci_hcd	ehci;
+
+#ifdef CONFIG_PM
+	/* Saved USB PHY settings, need to restore after deep sleep. */
+	u32 usb_ctrl;
+#endif
+};
+
+#ifdef CONFIG_PM
+
+static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+	return container_of(ehci, struct ehci_fsl, ehci);
+}
+
+static int ehci_fsl_drv_suspend(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
+	void __iomem *non_ehci = hcd->regs;
+
+	if (!fsl_deep_sleep())
+		return 0;
+
+	ehci_fsl->usb_ctrl = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+	return 0;
+}
+
+static int ehci_fsl_drv_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	void __iomem *non_ehci = hcd->regs;
+
+	if (!fsl_deep_sleep())
+		return 0;
+
+	usb_root_hub_lost_power(hcd->self.root_hub);
+
+	/* Restore USB PHY settings and enable the controller. */
+	out_be32(non_ehci + FSL_SOC_USB_CTRL, ehci_fsl->usb_ctrl);
+
+	ehci_reset(ehci);
+	ehci_fsl_reinit(ehci);
+
+	return 0;
+}
+
+static int ehci_fsl_drv_restore(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+	usb_root_hub_lost_power(hcd->self.root_hub);
+	return 0;
+}
+
+static struct dev_pm_ops ehci_fsl_pm_ops = {
+	.suspend = ehci_fsl_drv_suspend,
+	.resume = ehci_fsl_drv_resume,
+	.restore = ehci_fsl_drv_restore,
+};
+
+#define EHCI_FSL_PM_OPS		(&ehci_fsl_pm_ops)
+#else
+#define EHCI_FSL_PM_OPS		NULL
+#endif /* CONFIG_PM */
+
 static const struct hc_driver ehci_fsl_hc_driver = {
 	.description = hcd_name,
 	.product_desc = "Freescale On-Chip EHCI Host Controller",
-	.hcd_priv_size = sizeof(struct ehci_hcd),
+	.hcd_priv_size = sizeof(struct ehci_fsl),
 
 	/*
 	 * generic hardware linkage
@@ -354,6 +430,7 @@
 	.remove = ehci_fsl_drv_remove,
 	.shutdown = usb_hcd_platform_shutdown,
 	.driver = {
-		   .name = "fsl-ehci",
+		.name = "fsl-ehci",
+		.pm = EHCI_FSL_PM_OPS,
 	},
 };
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index 35c56f4..23cd917 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -162,6 +162,17 @@
 		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)) {
@@ -192,18 +203,6 @@
 	if (ret < 0)
 		goto err_init;
 
-	/* call platform specific init function */
-	if (pdata->init) {
-		ret = pdata->init(pdev);
-		if (ret) {
-			dev_err(dev, "platform init failed\n");
-			goto err_init;
-		}
-	}
-
-	/* most platforms need some time to settle changed IO settings */
-	mdelay(10);
-
 	/* Initialize the transceiver */
 	if (pdata->otg) {
 		pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 74d07f4..f0282d6 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -26,10 +26,9 @@
  * 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 23rd, 2009):
+ * TODO (last updated Feb 12, 2010):
  *	- add kernel-doc
  *	- enable AUTOIDLE
- *	- move DPLL5 programming to clock fw
  *	- add suspend/resume
  *	- move workarounds to board-files
  */
@@ -37,6 +36,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
 #include <plat/usb.h>
 
 /*
@@ -178,6 +178,11 @@
 	void __iomem		*uhh_base;
 	void __iomem		*tll_base;
 	void __iomem		*ehci_base;
+
+	/* Regulators for USB PHYs.
+	 * Each PHY can have a seperate regulator.
+	 */
+	struct regulator        *regulator[OMAP3_HS_USB_PORTS];
 };
 
 /*-------------------------------------------------------------------------*/
@@ -546,6 +551,8 @@
 
 	int irq = platform_get_irq(pdev, 0);
 	int ret = -ENODEV;
+	int i;
+	char supply[7];
 
 	if (!pdata) {
 		dev_dbg(&pdev->dev, "missing platform_data\n");
@@ -613,6 +620,21 @@
 		goto err_tll_ioremap;
 	}
 
+	/* get ehci regulator and enable */
+	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
+		if (omap->port_mode[i] != EHCI_HCD_OMAP_MODE_PHY) {
+			omap->regulator[i] = NULL;
+			continue;
+		}
+		snprintf(supply, sizeof(supply), "hsusb%d", i);
+		omap->regulator[i] = regulator_get(omap->dev, supply);
+		if (IS_ERR(omap->regulator[i]))
+			dev_dbg(&pdev->dev,
+			"failed to get ehci port%d regulator\n", i);
+		else
+			regulator_enable(omap->regulator[i]);
+	}
+
 	ret = omap_start_ehc(omap, hcd);
 	if (ret) {
 		dev_dbg(&pdev->dev, "failed to start ehci\n");
@@ -622,13 +644,12 @@
 	omap->ehci->regs = hcd->regs
 		+ HC_LENGTH(readl(&omap->ehci->caps->hc_capbase));
 
+	dbg_hcs_params(omap->ehci, "reset");
+	dbg_hcc_params(omap->ehci, "reset");
+
 	/* cache this readonly data; minimize chip reads */
 	omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params);
 
-	/* SET 1 micro-frame Interrupt interval */
-	writel(readl(&omap->ehci->regs->command) | (1 << 16),
-			&omap->ehci->regs->command);
-
 	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (ret) {
 		dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
@@ -641,6 +662,12 @@
 	omap_stop_ehc(omap, hcd);
 
 err_start:
+	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
+		if (omap->regulator[i]) {
+			regulator_disable(omap->regulator[i]);
+			regulator_put(omap->regulator[i]);
+		}
+	}
 	iounmap(omap->tll_base);
 
 err_tll_ioremap:
@@ -674,13 +701,21 @@
 {
 	struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
 	struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
+	int i;
 
 	usb_remove_hcd(hcd);
 	omap_stop_ehc(omap, hcd);
 	iounmap(hcd->regs);
+	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
+		if (omap->regulator[i]) {
+			regulator_disable(omap->regulator[i]);
+			regulator_put(omap->regulator[i]);
+		}
+	}
 	iounmap(omap->tll_base);
 	iounmap(omap->uhh_base);
 	usb_put_hcd(hcd);
+	kfree(omap);
 
 	return 0;
 }
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 1d283e1..0f87dc7 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -222,14 +222,14 @@
 		goto err1;
 	}
 
-	if (!request_mem_region(res->start, res->end - res->start + 1,
+	if (!request_mem_region(res->start, resource_size(res),
 				ehci_orion_hc_driver.description)) {
 		dev_dbg(&pdev->dev, "controller already in use\n");
 		err = -EBUSY;
 		goto err1;
 	}
 
-	regs = ioremap(res->start, res->end - res->start + 1);
+	regs = ioremap(res->start, resource_size(res));
 	if (regs == NULL) {
 		dev_dbg(&pdev->dev, "error mapping memory\n");
 		err = -EFAULT;
@@ -244,7 +244,7 @@
 	}
 
 	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = res->end - res->start + 1;
+	hcd->rsrc_len = resource_size(res);
 	hcd->regs = regs;
 
 	ehci = hcd_to_ehci(hcd);
@@ -287,7 +287,7 @@
 err3:
 	iounmap(regs);
 err2:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 err1:
 	dev_err(&pdev->dev, "init %s fail, %d\n",
 		dev_name(&pdev->dev), err);
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index 36f96da..8df33b8 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -134,21 +134,21 @@
 	hcd->rsrc_len = res.end - res.start + 1;
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		printk(KERN_ERR __FILE__ ": request_mem_region failed\n");
+		printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
 		rv = -EBUSY;
 		goto err_rmr;
 	}
 
 	irq = irq_of_parse_and_map(dn, 0);
 	if (irq == NO_IRQ) {
-		printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
+		printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
 		rv = -EBUSY;
 		goto err_irq;
 	}
 
 	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
 	if (!hcd->regs) {
-		printk(KERN_ERR __FILE__ ": ioremap failed\n");
+		printk(KERN_ERR "%s: ioremap failed\n", __FILE__);
 		rv = -ENOMEM;
 		goto err_ioremap;
 	}
@@ -161,9 +161,9 @@
 			ehci->ohci_hcctrl_reg = ioremap(res.start +
 					OHCI_HCCTRL_OFFSET, OHCI_HCCTRL_LEN);
 		else
-			pr_debug(__FILE__ ": no ohci offset in fdt\n");
+			pr_debug("%s: no ohci offset in fdt\n", __FILE__);
 		if (!ehci->ohci_hcctrl_reg) {
-			pr_debug(__FILE__ ": ioremap for ohci hcctrl failed\n");
+			pr_debug("%s: ioremap for ohci hcctrl failed\n", __FILE__);
 		} else {
 			ehci->has_amcc_usb23 = 1;
 		}
@@ -241,7 +241,7 @@
 				else
 					release_mem_region(res.start, 0x4);
 			else
-				pr_debug(__FILE__ ": no ohci offset in fdt\n");
+				pr_debug("%s: no ohci offset in fdt\n", __FILE__);
 			of_node_put(np);
 		}
 
@@ -264,7 +264,7 @@
 }
 
 
-static struct of_device_id ehci_hcd_ppc_of_match[] = {
+static const struct of_device_id ehci_hcd_ppc_of_match[] = {
 	{
 		.compatible = "usb-ehci",
 	},
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 1e391e6..39340ae 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -510,6 +510,8 @@
 	ehci_writel(ehci, cmd, &ehci->regs->command);
 	/* posted write ... */
 
+	free_cached_itd_list(ehci);
+
 	ehci->next_uframe = -1;
 	return 0;
 }
@@ -2322,9 +2324,13 @@
 				 * No need to check for activity unless the
 				 * frame is current.
 				 */
-				if (frame == clock_frame && live &&
-						(q.sitd->hw_results &
-							SITD_ACTIVE(ehci))) {
+				if (((frame == clock_frame) ||
+				     (((frame + 1) % ehci->periodic_size)
+				      == clock_frame))
+				    && live
+				    && (q.sitd->hw_results &
+					SITD_ACTIVE(ehci))) {
+
 					incomplete = true;
 					q_p = &q.sitd->sitd_next;
 					hw_p = &q.sitd->hw_next;
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index a5861531..f603bb2 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -177,21 +177,21 @@
 	hcd->rsrc_len = res.end - res.start + 1;
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		printk(KERN_ERR __FILE__ ": request_mem_region failed\n");
+		printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
 		rv = -EBUSY;
 		goto err_rmr;
 	}
 
 	irq = irq_of_parse_and_map(dn, 0);
 	if (irq == NO_IRQ) {
-		printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
+		printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
 		rv = -EBUSY;
 		goto err_irq;
 	}
 
 	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
 	if (!hcd->regs) {
-		printk(KERN_ERR __FILE__ ": ioremap failed\n");
+		printk(KERN_ERR "%s: ioremap failed\n", __FILE__);
 		rv = -ENOMEM;
 		goto err_ioremap;
 	}
@@ -281,7 +281,7 @@
 }
 
 
-static struct of_device_id ehci_hcd_xilinx_of_match[] = {
+static const struct of_device_id ehci_hcd_xilinx_of_match[] = {
 		{.compatible = "xlnx,xps-usb-host-1.00.a",},
 	{},
 };
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index 78e7c3c..5dcfb3d 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -433,7 +433,7 @@
 		return -ENOMEM;
 
 	/* allocate the private part of the URB */
-	urb_priv->tds = kzalloc(size * sizeof(struct td), mem_flags);
+	urb_priv->tds = kcalloc(size, sizeof(*urb_priv->tds), mem_flags);
 	if (!urb_priv->tds) {
 		kfree(urb_priv);
 		return -ENOMEM;
@@ -805,7 +805,7 @@
 	return fhci_remove(&ofdev->dev);
 }
 
-static struct of_device_id of_fhci_match[] = {
+static const struct of_device_id of_fhci_match[] = {
 	{ .compatible = "fsl,mpc8323-qe-usb", },
 	{},
 };
diff --git a/drivers/usb/host/imx21-dbg.c b/drivers/usb/host/imx21-dbg.c
new file mode 100644
index 0000000..512f647
--- /dev/null
+++ b/drivers/usb/host/imx21-dbg.c
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2009 by Martin Fuzzey
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You 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 file is part of imx21-hcd.c */
+
+#ifndef DEBUG
+
+static inline void create_debug_files(struct imx21 *imx21) { }
+static inline void remove_debug_files(struct imx21 *imx21) { }
+static inline void debug_urb_submitted(struct imx21 *imx21, struct urb *urb) {}
+static inline void debug_urb_completed(struct imx21 *imx21, struct urb *urb,
+	int status) {}
+static inline void debug_urb_unlinked(struct imx21 *imx21, struct urb *urb) {}
+static inline void debug_urb_queued_for_etd(struct imx21 *imx21,
+	struct urb *urb) {}
+static inline void debug_urb_queued_for_dmem(struct imx21 *imx21,
+	struct urb *urb) {}
+static inline void debug_etd_allocated(struct imx21 *imx21) {}
+static inline void debug_etd_freed(struct imx21 *imx21) {}
+static inline void debug_dmem_allocated(struct imx21 *imx21, int size) {}
+static inline void debug_dmem_freed(struct imx21 *imx21, int size) {}
+static inline void debug_isoc_submitted(struct imx21 *imx21,
+	int frame, struct td *td) {}
+static inline void debug_isoc_completed(struct imx21 *imx21,
+	int frame, struct td *td, int cc, int len) {}
+
+#else
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static const char *dir_labels[] = {
+	"TD 0",
+	"OUT",
+	"IN",
+	"TD 1"
+};
+
+static const char *speed_labels[] = {
+	"Full",
+	"Low"
+};
+
+static const char *format_labels[] = {
+	"Control",
+	"ISO",
+	"Bulk",
+	"Interrupt"
+};
+
+static inline struct debug_stats *stats_for_urb(struct imx21 *imx21,
+	struct urb *urb)
+{
+	return usb_pipeisoc(urb->pipe) ?
+		&imx21->isoc_stats : &imx21->nonisoc_stats;
+}
+
+static void debug_urb_submitted(struct imx21 *imx21, struct urb *urb)
+{
+	stats_for_urb(imx21, urb)->submitted++;
+}
+
+static void debug_urb_completed(struct imx21 *imx21, struct urb *urb, int st)
+{
+	if (st)
+		stats_for_urb(imx21, urb)->completed_failed++;
+	else
+		stats_for_urb(imx21, urb)->completed_ok++;
+}
+
+static void debug_urb_unlinked(struct imx21 *imx21, struct urb *urb)
+{
+	stats_for_urb(imx21, urb)->unlinked++;
+}
+
+static void debug_urb_queued_for_etd(struct imx21 *imx21, struct urb *urb)
+{
+	stats_for_urb(imx21, urb)->queue_etd++;
+}
+
+static void debug_urb_queued_for_dmem(struct imx21 *imx21, struct urb *urb)
+{
+	stats_for_urb(imx21, urb)->queue_dmem++;
+}
+
+static inline void debug_etd_allocated(struct imx21 *imx21)
+{
+	imx21->etd_usage.maximum = max(
+			++(imx21->etd_usage.value),
+			imx21->etd_usage.maximum);
+}
+
+static inline void debug_etd_freed(struct imx21 *imx21)
+{
+	imx21->etd_usage.value--;
+}
+
+static inline void debug_dmem_allocated(struct imx21 *imx21, int size)
+{
+	imx21->dmem_usage.value += size;
+	imx21->dmem_usage.maximum = max(
+			imx21->dmem_usage.value,
+			imx21->dmem_usage.maximum);
+}
+
+static inline void debug_dmem_freed(struct imx21 *imx21, int size)
+{
+	imx21->dmem_usage.value -= size;
+}
+
+
+static void debug_isoc_submitted(struct imx21 *imx21,
+	int frame, struct td *td)
+{
+	struct debug_isoc_trace *trace = &imx21->isoc_trace[
+		imx21->isoc_trace_index++];
+
+	imx21->isoc_trace_index %= ARRAY_SIZE(imx21->isoc_trace);
+	trace->schedule_frame = td->frame;
+	trace->submit_frame = frame;
+	trace->request_len = td->len;
+	trace->td = td;
+}
+
+static inline void debug_isoc_completed(struct imx21 *imx21,
+	int frame, struct td *td, int cc, int len)
+{
+	struct debug_isoc_trace *trace, *trace_failed;
+	int i;
+	int found = 0;
+
+	trace = imx21->isoc_trace;
+	for (i = 0; i < ARRAY_SIZE(imx21->isoc_trace); i++, trace++) {
+		if (trace->td == td) {
+			trace->done_frame = frame;
+			trace->done_len = len;
+			trace->cc = cc;
+			trace->td = NULL;
+			found = 1;
+			break;
+		}
+	}
+
+	if (found && cc) {
+		trace_failed = &imx21->isoc_trace_failed[
+					imx21->isoc_trace_index_failed++];
+
+		imx21->isoc_trace_index_failed %= ARRAY_SIZE(
+						imx21->isoc_trace_failed);
+		*trace_failed = *trace;
+	}
+}
+
+
+static char *format_ep(struct usb_host_endpoint *ep, char *buf, int bufsize)
+{
+	if (ep)
+		snprintf(buf, bufsize, "ep_%02x (type:%02X kaddr:%p)",
+			ep->desc.bEndpointAddress,
+			usb_endpoint_type(&ep->desc),
+			ep);
+	else
+		snprintf(buf, bufsize, "none");
+	return buf;
+}
+
+static char *format_etd_dword0(u32 value, char *buf, int bufsize)
+{
+	snprintf(buf, bufsize,
+		"addr=%d ep=%d dir=%s speed=%s format=%s halted=%d",
+		value & 0x7F,
+		(value >> DW0_ENDPNT) & 0x0F,
+		dir_labels[(value >> DW0_DIRECT) & 0x03],
+		speed_labels[(value >> DW0_SPEED) & 0x01],
+		format_labels[(value >> DW0_FORMAT) & 0x03],
+		(value >> DW0_HALTED) & 0x01);
+	return buf;
+}
+
+static int debug_status_show(struct seq_file *s, void *v)
+{
+	struct imx21 *imx21 = s->private;
+	int etds_allocated = 0;
+	int etds_sw_busy = 0;
+	int etds_hw_busy = 0;
+	int dmem_blocks = 0;
+	int queued_for_etd = 0;
+	int queued_for_dmem = 0;
+	unsigned int dmem_bytes = 0;
+	int i;
+	struct etd_priv *etd;
+	u32 etd_enable_mask;
+	unsigned long flags;
+	struct imx21_dmem_area *dmem;
+	struct ep_priv *ep_priv;
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	etd_enable_mask = readl(imx21->regs + USBH_ETDENSET);
+	for (i = 0, etd = imx21->etd; i < USB_NUM_ETD; i++, etd++) {
+		if (etd->alloc)
+			etds_allocated++;
+		if (etd->urb)
+			etds_sw_busy++;
+		if (etd_enable_mask & (1<<i))
+			etds_hw_busy++;
+	}
+
+	list_for_each_entry(dmem, &imx21->dmem_list, list) {
+		dmem_bytes += dmem->size;
+		dmem_blocks++;
+	}
+
+	list_for_each_entry(ep_priv, &imx21->queue_for_etd, queue)
+		queued_for_etd++;
+
+	list_for_each_entry(etd, &imx21->queue_for_dmem, queue)
+		queued_for_dmem++;
+
+	spin_unlock_irqrestore(&imx21->lock, flags);
+
+	seq_printf(s,
+		"Frame: %d\n"
+		"ETDs allocated: %d/%d (max=%d)\n"
+		"ETDs in use sw: %d\n"
+		"ETDs in use hw: %d\n"
+		"DMEM alocated: %d/%d (max=%d)\n"
+		"DMEM blocks: %d\n"
+		"Queued waiting for ETD: %d\n"
+		"Queued waiting for DMEM: %d\n",
+		readl(imx21->regs + USBH_FRMNUB) & 0xFFFF,
+		etds_allocated, USB_NUM_ETD, imx21->etd_usage.maximum,
+		etds_sw_busy,
+		etds_hw_busy,
+		dmem_bytes, DMEM_SIZE, imx21->dmem_usage.maximum,
+		dmem_blocks,
+		queued_for_etd,
+		queued_for_dmem);
+
+	return 0;
+}
+
+static int debug_dmem_show(struct seq_file *s, void *v)
+{
+	struct imx21 *imx21 = s->private;
+	struct imx21_dmem_area *dmem;
+	unsigned long flags;
+	char ep_text[40];
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	list_for_each_entry(dmem, &imx21->dmem_list, list)
+		seq_printf(s,
+			"%04X: size=0x%X "
+			"ep=%s\n",
+			dmem->offset, dmem->size,
+			format_ep(dmem->ep, ep_text, sizeof(ep_text)));
+
+	spin_unlock_irqrestore(&imx21->lock, flags);
+
+	return 0;
+}
+
+static int debug_etd_show(struct seq_file *s, void *v)
+{
+	struct imx21 *imx21 = s->private;
+	struct etd_priv *etd;
+	char buf[60];
+	u32 dword;
+	int i, j;
+	unsigned long flags;
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	for (i = 0, etd = imx21->etd; i < USB_NUM_ETD; i++, etd++) {
+		int state = -1;
+		struct urb_priv *urb_priv;
+		if (etd->urb) {
+			urb_priv = etd->urb->hcpriv;
+			if (urb_priv)
+				state = urb_priv->state;
+		}
+
+		seq_printf(s,
+			"etd_num: %d\n"
+			"ep: %s\n"
+			"alloc: %d\n"
+			"len: %d\n"
+			"busy sw: %d\n"
+			"busy hw: %d\n"
+			"urb state: %d\n"
+			"current urb: %p\n",
+
+			i,
+			format_ep(etd->ep, buf, sizeof(buf)),
+			etd->alloc,
+			etd->len,
+			etd->urb != NULL,
+			(readl(imx21->regs + USBH_ETDENSET) & (1 << i)) > 0,
+			state,
+			etd->urb);
+
+		for (j = 0; j < 4; j++) {
+			dword = etd_readl(imx21, i, j);
+			switch (j) {
+			case 0:
+				format_etd_dword0(dword, buf, sizeof(buf));
+				break;
+			case 2:
+				snprintf(buf, sizeof(buf),
+					"cc=0X%02X", dword >> DW2_COMPCODE);
+				break;
+			default:
+				*buf = 0;
+				break;
+			}
+			seq_printf(s,
+				"dword %d: submitted=%08X cur=%08X [%s]\n",
+				j,
+				etd->submitted_dwords[j],
+				dword,
+				buf);
+		}
+		seq_printf(s, "\n");
+	}
+
+	spin_unlock_irqrestore(&imx21->lock, flags);
+
+	return 0;
+}
+
+static void debug_statistics_show_one(struct seq_file *s,
+	const char *name, struct debug_stats *stats)
+{
+	seq_printf(s, "%s:\n"
+		"submitted URBs: %lu\n"
+		"completed OK: %lu\n"
+		"completed failed: %lu\n"
+		"unlinked: %lu\n"
+		"queued for ETD: %lu\n"
+		"queued for DMEM: %lu\n\n",
+		name,
+		stats->submitted,
+		stats->completed_ok,
+		stats->completed_failed,
+		stats->unlinked,
+		stats->queue_etd,
+		stats->queue_dmem);
+}
+
+static int debug_statistics_show(struct seq_file *s, void *v)
+{
+	struct imx21 *imx21 = s->private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	debug_statistics_show_one(s, "nonisoc", &imx21->nonisoc_stats);
+	debug_statistics_show_one(s, "isoc", &imx21->isoc_stats);
+	seq_printf(s, "unblock kludge triggers: %lu\n", imx21->debug_unblocks);
+	spin_unlock_irqrestore(&imx21->lock, flags);
+
+	return 0;
+}
+
+static void debug_isoc_show_one(struct seq_file *s,
+	const char *name, int index, 	struct debug_isoc_trace *trace)
+{
+	seq_printf(s, "%s %d:\n"
+		"cc=0X%02X\n"
+		"scheduled frame %d (%d)\n"
+		"submittted frame %d (%d)\n"
+		"completed frame %d (%d)\n"
+		"requested length=%d\n"
+		"completed length=%d\n\n",
+		name, index,
+		trace->cc,
+		trace->schedule_frame, trace->schedule_frame & 0xFFFF,
+		trace->submit_frame, trace->submit_frame & 0xFFFF,
+		trace->done_frame, trace->done_frame & 0xFFFF,
+		trace->request_len,
+		trace->done_len);
+}
+
+static int debug_isoc_show(struct seq_file *s, void *v)
+{
+	struct imx21 *imx21 = s->private;
+	struct debug_isoc_trace *trace;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	trace = imx21->isoc_trace_failed;
+	for (i = 0; i < ARRAY_SIZE(imx21->isoc_trace_failed); i++, trace++)
+		debug_isoc_show_one(s, "isoc failed", i, trace);
+
+	trace = imx21->isoc_trace;
+	for (i = 0; i < ARRAY_SIZE(imx21->isoc_trace); i++, trace++)
+		debug_isoc_show_one(s, "isoc", i, trace);
+
+	spin_unlock_irqrestore(&imx21->lock, flags);
+
+	return 0;
+}
+
+static int debug_status_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, debug_status_show, inode->i_private);
+}
+
+static int debug_dmem_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, debug_dmem_show, inode->i_private);
+}
+
+static int debug_etd_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, debug_etd_show, inode->i_private);
+}
+
+static int debug_statistics_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, debug_statistics_show, inode->i_private);
+}
+
+static int debug_isoc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, debug_isoc_show, inode->i_private);
+}
+
+static const struct file_operations debug_status_fops = {
+	.open = debug_status_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations debug_dmem_fops = {
+	.open = debug_dmem_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations debug_etd_fops = {
+	.open = debug_etd_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations debug_statistics_fops = {
+	.open = debug_statistics_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations debug_isoc_fops = {
+	.open = debug_isoc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static void create_debug_files(struct imx21 *imx21)
+{
+	imx21->debug_root = debugfs_create_dir(dev_name(imx21->dev), NULL);
+	if (!imx21->debug_root)
+		goto failed_create_rootdir;
+
+	if (!debugfs_create_file("status", S_IRUGO,
+			imx21->debug_root, imx21, &debug_status_fops))
+		goto failed_create;
+
+	if (!debugfs_create_file("dmem", S_IRUGO,
+			imx21->debug_root, imx21, &debug_dmem_fops))
+		goto failed_create;
+
+	if (!debugfs_create_file("etd", S_IRUGO,
+			imx21->debug_root, imx21, &debug_etd_fops))
+		goto failed_create;
+
+	if (!debugfs_create_file("statistics", S_IRUGO,
+			imx21->debug_root, imx21, &debug_statistics_fops))
+		goto failed_create;
+
+	if (!debugfs_create_file("isoc", S_IRUGO,
+			imx21->debug_root, imx21, &debug_isoc_fops))
+		goto failed_create;
+
+	return;
+
+failed_create:
+	debugfs_remove_recursive(imx21->debug_root);
+
+failed_create_rootdir:
+	imx21->debug_root = NULL;
+}
+
+
+static void remove_debug_files(struct imx21 *imx21)
+{
+	if (imx21->debug_root) {
+		debugfs_remove_recursive(imx21->debug_root);
+		imx21->debug_root = NULL;
+	}
+}
+
+#endif
+
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
new file mode 100644
index 0000000..213e270
--- /dev/null
+++ b/drivers/usb/host/imx21-hcd.c
@@ -0,0 +1,1789 @@
+/*
+ * USB Host Controller Driver for IMX21
+ *
+ * Copyright (C) 2006 Loping Dog Embedded Systems
+ * Copyright (C) 2009 Martin Fuzzey
+ * Originally written by Jay Monkman <jtm@lopingdog.com>
+ * Ported to 2.6.30, debugged and enhanced by Martin Fuzzey
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You 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.
+ */
+
+
+ /*
+  * The i.MX21 USB hardware contains
+  *    * 32 transfer descriptors (called ETDs)
+  *    * 4Kb of Data memory
+  *
+  * The data memory is shared between the host and fuction controlers
+  * (but this driver only supports the host controler)
+  *
+  * So setting up a transfer involves:
+  *    * Allocating a ETD
+  *    * Fill in ETD with appropriate information
+  *    * Allocating data memory (and putting the offset in the ETD)
+  *    * Activate the ETD
+  *    * Get interrupt when done.
+  *
+  * An ETD is assigned to each active endpoint.
+  *
+  * Low resource (ETD and Data memory) situations are handled differently for
+  * isochronous and non insosynchronous transactions :
+  *
+  * Non ISOC transfers are queued if either ETDs or Data memory are unavailable
+  *
+  * ISOC transfers use 2 ETDs per endpoint to achieve double buffering.
+  * They allocate both ETDs and Data memory during URB submission
+  * (and fail if unavailable).
+  */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+
+#include "../core/hcd.h"
+#include "imx21-hcd.h"
+
+#ifdef DEBUG
+#define DEBUG_LOG_FRAME(imx21, etd, event) \
+	(etd)->event##_frame = readl((imx21)->regs + USBH_FRMNUB)
+#else
+#define DEBUG_LOG_FRAME(imx21, etd, event) do { } while (0)
+#endif
+
+static const char hcd_name[] = "imx21-hcd";
+
+static inline struct imx21 *hcd_to_imx21(struct usb_hcd *hcd)
+{
+	return (struct imx21 *)hcd->hcd_priv;
+}
+
+
+/* =========================================== */
+/* Hardware access helpers			*/
+/* =========================================== */
+
+static inline void set_register_bits(struct imx21 *imx21, u32 offset, u32 mask)
+{
+	void __iomem *reg = imx21->regs + offset;
+	writel(readl(reg) | mask, reg);
+}
+
+static inline void clear_register_bits(struct imx21 *imx21,
+	u32 offset, u32 mask)
+{
+	void __iomem *reg = imx21->regs + offset;
+	writel(readl(reg) & ~mask, reg);
+}
+
+static inline void clear_toggle_bit(struct imx21 *imx21, u32 offset, u32 mask)
+{
+	void __iomem *reg = imx21->regs + offset;
+
+	if (readl(reg) & mask)
+		writel(mask, reg);
+}
+
+static inline void set_toggle_bit(struct imx21 *imx21, u32 offset, u32 mask)
+{
+	void __iomem *reg = imx21->regs + offset;
+
+	if (!(readl(reg) & mask))
+		writel(mask, reg);
+}
+
+static void etd_writel(struct imx21 *imx21, int etd_num, int dword, u32 value)
+{
+	writel(value, imx21->regs + USB_ETD_DWORD(etd_num, dword));
+}
+
+static u32 etd_readl(struct imx21 *imx21, int etd_num, int dword)
+{
+	return readl(imx21->regs + USB_ETD_DWORD(etd_num, dword));
+}
+
+static inline int wrap_frame(int counter)
+{
+	return counter & 0xFFFF;
+}
+
+static inline int frame_after(int frame, int after)
+{
+	/* handle wrapping like jiffies time_afer */
+	return (s16)((s16)after - (s16)frame) < 0;
+}
+
+static int imx21_hc_get_frame(struct usb_hcd *hcd)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+
+	return wrap_frame(readl(imx21->regs + USBH_FRMNUB));
+}
+
+
+#include "imx21-dbg.c"
+
+/* =========================================== */
+/* ETD management				*/
+/* ===========================================	*/
+
+static int alloc_etd(struct imx21 *imx21)
+{
+	int i;
+	struct etd_priv *etd = imx21->etd;
+
+	for (i = 0; i < USB_NUM_ETD; i++, etd++) {
+		if (etd->alloc == 0) {
+			memset(etd, 0, sizeof(imx21->etd[0]));
+			etd->alloc = 1;
+			debug_etd_allocated(imx21);
+			return i;
+		}
+	}
+	return -1;
+}
+
+static void disactivate_etd(struct imx21 *imx21, int num)
+{
+	int etd_mask = (1 << num);
+	struct etd_priv *etd = &imx21->etd[num];
+
+	writel(etd_mask, imx21->regs + USBH_ETDENCLR);
+	clear_register_bits(imx21, USBH_ETDDONEEN, etd_mask);
+	writel(etd_mask, imx21->regs + USB_ETDDMACHANLCLR);
+	clear_toggle_bit(imx21, USBH_ETDDONESTAT, etd_mask);
+
+	etd->active_count = 0;
+
+	DEBUG_LOG_FRAME(imx21, etd, disactivated);
+}
+
+static void reset_etd(struct imx21 *imx21, int num)
+{
+	struct etd_priv *etd = imx21->etd + num;
+	int i;
+
+	disactivate_etd(imx21, num);
+
+	for (i = 0; i < 4; i++)
+		etd_writel(imx21, num, i, 0);
+	etd->urb = NULL;
+	etd->ep = NULL;
+	etd->td = NULL;;
+}
+
+static void free_etd(struct imx21 *imx21, int num)
+{
+	if (num < 0)
+		return;
+
+	if (num >= USB_NUM_ETD) {
+		dev_err(imx21->dev, "BAD etd=%d!\n", num);
+		return;
+	}
+	if (imx21->etd[num].alloc == 0) {
+		dev_err(imx21->dev, "ETD %d already free!\n", num);
+		return;
+	}
+
+	debug_etd_freed(imx21);
+	reset_etd(imx21, num);
+	memset(&imx21->etd[num], 0, sizeof(imx21->etd[0]));
+}
+
+
+static void setup_etd_dword0(struct imx21 *imx21,
+	int etd_num, struct urb *urb,  u8 dir, u16 maxpacket)
+{
+	etd_writel(imx21, etd_num, 0,
+		((u32) usb_pipedevice(urb->pipe)) <<  DW0_ADDRESS |
+		((u32) usb_pipeendpoint(urb->pipe) << DW0_ENDPNT) |
+		((u32) dir << DW0_DIRECT) |
+		((u32) ((urb->dev->speed == USB_SPEED_LOW) ?
+			1 : 0) << DW0_SPEED) |
+		((u32) fmt_urb_to_etd[usb_pipetype(urb->pipe)] << DW0_FORMAT) |
+		((u32) maxpacket << DW0_MAXPKTSIZ));
+}
+
+static void activate_etd(struct imx21 *imx21,
+	int etd_num, dma_addr_t dma, u8 dir)
+{
+	u32 etd_mask = 1 << etd_num;
+	struct etd_priv *etd = &imx21->etd[etd_num];
+
+	clear_toggle_bit(imx21, USBH_ETDDONESTAT, etd_mask);
+	set_register_bits(imx21, USBH_ETDDONEEN, etd_mask);
+	clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
+	clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
+
+	if (dma) {
+		set_register_bits(imx21, USB_ETDDMACHANLCLR, etd_mask);
+		clear_toggle_bit(imx21, USBH_XBUFSTAT, etd_mask);
+		clear_toggle_bit(imx21, USBH_YBUFSTAT, etd_mask);
+		writel(dma, imx21->regs + USB_ETDSMSA(etd_num));
+		set_register_bits(imx21, USB_ETDDMAEN, etd_mask);
+	} else {
+		if (dir != TD_DIR_IN) {
+			/* need to set for ZLP */
+			set_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
+			set_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
+		}
+	}
+
+	DEBUG_LOG_FRAME(imx21, etd, activated);
+
+#ifdef DEBUG
+	if (!etd->active_count) {
+		int i;
+		etd->activated_frame = readl(imx21->regs + USBH_FRMNUB);
+		etd->disactivated_frame = -1;
+		etd->last_int_frame = -1;
+		etd->last_req_frame = -1;
+
+		for (i = 0; i < 4; i++)
+			etd->submitted_dwords[i] = etd_readl(imx21, etd_num, i);
+	}
+#endif
+
+	etd->active_count = 1;
+	writel(etd_mask, imx21->regs + USBH_ETDENSET);
+}
+
+/* ===========================================	*/
+/* Data memory management			*/
+/* ===========================================	*/
+
+static int alloc_dmem(struct imx21 *imx21, unsigned int size,
+		      struct usb_host_endpoint *ep)
+{
+	unsigned int offset = 0;
+	struct imx21_dmem_area *area;
+	struct imx21_dmem_area *tmp;
+
+	size += (~size + 1) & 0x3; /* Round to 4 byte multiple */
+
+	if (size > DMEM_SIZE) {
+		dev_err(imx21->dev, "size=%d > DMEM_SIZE(%d)\n",
+			size, DMEM_SIZE);
+		return -EINVAL;
+	}
+
+	list_for_each_entry(tmp, &imx21->dmem_list, list) {
+		if ((size + offset) < offset)
+			goto fail;
+		if ((size + offset) <= tmp->offset)
+			break;
+		offset = tmp->size + tmp->offset;
+		if ((offset + size) > DMEM_SIZE)
+			goto fail;
+	}
+
+	area = kmalloc(sizeof(struct imx21_dmem_area), GFP_ATOMIC);
+	if (area == NULL)
+		return -ENOMEM;
+
+	area->ep = ep;
+	area->offset = offset;
+	area->size = size;
+	list_add_tail(&area->list, &tmp->list);
+	debug_dmem_allocated(imx21, size);
+	return offset;
+
+fail:
+	return -ENOMEM;
+}
+
+/* Memory now available for a queued ETD - activate it */
+static void activate_queued_etd(struct imx21 *imx21,
+	struct etd_priv *etd, u32 dmem_offset)
+{
+	struct urb_priv *urb_priv = etd->urb->hcpriv;
+	int etd_num = etd - &imx21->etd[0];
+	u32 maxpacket = etd_readl(imx21, etd_num, 1) >> DW1_YBUFSRTAD;
+	u8 dir = (etd_readl(imx21, etd_num, 2) >> DW2_DIRPID) & 0x03;
+
+	dev_dbg(imx21->dev, "activating queued ETD %d now DMEM available\n",
+		etd_num);
+	etd_writel(imx21, etd_num, 1,
+	    ((dmem_offset + maxpacket) << DW1_YBUFSRTAD) | dmem_offset);
+
+	urb_priv->active = 1;
+	activate_etd(imx21, etd_num, etd->dma_handle, dir);
+}
+
+static void free_dmem(struct imx21 *imx21, int offset)
+{
+	struct imx21_dmem_area *area;
+	struct etd_priv *etd, *tmp;
+	int found = 0;
+
+	list_for_each_entry(area, &imx21->dmem_list, list) {
+		if (area->offset == offset) {
+			debug_dmem_freed(imx21, area->size);
+			list_del(&area->list);
+			kfree(area);
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found)  {
+		dev_err(imx21->dev,
+			"Trying to free unallocated DMEM %d\n", offset);
+		return;
+	}
+
+	/* Try again to allocate memory for anything we've queued */
+	list_for_each_entry_safe(etd, tmp, &imx21->queue_for_dmem, queue) {
+		offset = alloc_dmem(imx21, etd->dmem_size, etd->ep);
+		if (offset >= 0) {
+			list_del(&etd->queue);
+			activate_queued_etd(imx21, etd, (u32)offset);
+		}
+	}
+}
+
+static void free_epdmem(struct imx21 *imx21, struct usb_host_endpoint *ep)
+{
+	struct imx21_dmem_area *area, *tmp;
+
+	list_for_each_entry_safe(area, tmp, &imx21->dmem_list, list) {
+		if (area->ep == ep) {
+			dev_err(imx21->dev,
+				"Active DMEM %d for disabled ep=%p\n",
+				area->offset, ep);
+			list_del(&area->list);
+			kfree(area);
+		}
+	}
+}
+
+
+/* ===========================================	*/
+/* End handling 				*/
+/* ===========================================	*/
+static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb);
+
+/* Endpoint now idle - release it's ETD(s) or asssign to queued request */
+static void ep_idle(struct imx21 *imx21, struct ep_priv *ep_priv)
+{
+	int etd_num;
+	int i;
+
+	for (i = 0; i < NUM_ISO_ETDS; i++) {
+		etd_num = ep_priv->etd[i];
+		if (etd_num < 0)
+			continue;
+
+		ep_priv->etd[i] = -1;
+		if (list_empty(&imx21->queue_for_etd)) {
+			free_etd(imx21, etd_num);
+			continue;
+		}
+
+		dev_dbg(imx21->dev,
+			"assigning idle etd %d for queued request\n", etd_num);
+		ep_priv = list_first_entry(&imx21->queue_for_etd,
+			struct ep_priv, queue);
+		list_del(&ep_priv->queue);
+		reset_etd(imx21, etd_num);
+		ep_priv->waiting_etd = 0;
+		ep_priv->etd[i] = etd_num;
+
+		if (list_empty(&ep_priv->ep->urb_list)) {
+			dev_err(imx21->dev, "No urb for queued ep!\n");
+			continue;
+		}
+		schedule_nonisoc_etd(imx21, list_first_entry(
+			&ep_priv->ep->urb_list, struct urb, urb_list));
+	}
+}
+
+static void urb_done(struct usb_hcd *hcd, struct urb *urb, int status)
+__releases(imx21->lock)
+__acquires(imx21->lock)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	struct ep_priv *ep_priv = urb->ep->hcpriv;
+	struct urb_priv *urb_priv = urb->hcpriv;
+
+	debug_urb_completed(imx21, urb, status);
+	dev_vdbg(imx21->dev, "urb %p done %d\n", urb, status);
+
+	kfree(urb_priv->isoc_td);
+	kfree(urb->hcpriv);
+	urb->hcpriv = NULL;
+	usb_hcd_unlink_urb_from_ep(hcd, urb);
+	spin_unlock(&imx21->lock);
+	usb_hcd_giveback_urb(hcd, urb, status);
+	spin_lock(&imx21->lock);
+	if (list_empty(&ep_priv->ep->urb_list))
+		ep_idle(imx21, ep_priv);
+}
+
+/* ===========================================	*/
+/* ISOC Handling ... 				*/
+/* ===========================================	*/
+
+static void schedule_isoc_etds(struct usb_hcd *hcd,
+	struct usb_host_endpoint *ep)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	struct ep_priv *ep_priv = ep->hcpriv;
+	struct etd_priv *etd;
+	struct urb_priv *urb_priv;
+	struct td *td;
+	int etd_num;
+	int i;
+	int cur_frame;
+	u8 dir;
+
+	for (i = 0; i < NUM_ISO_ETDS; i++) {
+too_late:
+		if (list_empty(&ep_priv->td_list))
+			break;
+
+		etd_num = ep_priv->etd[i];
+		if (etd_num < 0)
+			break;
+
+		etd = &imx21->etd[etd_num];
+		if (etd->urb)
+			continue;
+
+		td = list_entry(ep_priv->td_list.next, struct td, list);
+		list_del(&td->list);
+		urb_priv = td->urb->hcpriv;
+
+		cur_frame = imx21_hc_get_frame(hcd);
+		if (frame_after(cur_frame, td->frame)) {
+			dev_dbg(imx21->dev, "isoc too late frame %d > %d\n",
+				cur_frame, td->frame);
+			urb_priv->isoc_status = -EXDEV;
+			td->urb->iso_frame_desc[
+				td->isoc_index].actual_length = 0;
+			td->urb->iso_frame_desc[td->isoc_index].status = -EXDEV;
+			if (--urb_priv->isoc_remaining == 0)
+				urb_done(hcd, td->urb, urb_priv->isoc_status);
+			goto too_late;
+		}
+
+		urb_priv->active = 1;
+		etd->td = td;
+		etd->ep = td->ep;
+		etd->urb = td->urb;
+		etd->len = td->len;
+
+		debug_isoc_submitted(imx21, cur_frame, td);
+
+		dir = usb_pipeout(td->urb->pipe) ? TD_DIR_OUT : TD_DIR_IN;
+		setup_etd_dword0(imx21, etd_num, td->urb, dir, etd->dmem_size);
+		etd_writel(imx21, etd_num, 1, etd->dmem_offset);
+		etd_writel(imx21, etd_num, 2,
+			(TD_NOTACCESSED << DW2_COMPCODE) |
+			((td->frame & 0xFFFF) << DW2_STARTFRM));
+		etd_writel(imx21, etd_num, 3,
+			(TD_NOTACCESSED << DW3_COMPCODE0) |
+			(td->len << DW3_PKTLEN0));
+
+		activate_etd(imx21, etd_num, td->data, dir);
+	}
+}
+
+static void isoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	int etd_mask = 1 << etd_num;
+	struct urb_priv *urb_priv = urb->hcpriv;
+	struct etd_priv *etd = imx21->etd + etd_num;
+	struct td *td = etd->td;
+	struct usb_host_endpoint *ep = etd->ep;
+	int isoc_index = td->isoc_index;
+	unsigned int pipe = urb->pipe;
+	int dir_in = usb_pipein(pipe);
+	int cc;
+	int bytes_xfrd;
+
+	disactivate_etd(imx21, etd_num);
+
+	cc = (etd_readl(imx21, etd_num, 3) >> DW3_COMPCODE0) & 0xf;
+	bytes_xfrd = etd_readl(imx21, etd_num, 3) & 0x3ff;
+
+	/* Input doesn't always fill the buffer, don't generate an error
+	 * when this happens.
+	 */
+	if (dir_in && (cc == TD_DATAUNDERRUN))
+		cc = TD_CC_NOERROR;
+
+	if (cc == TD_NOTACCESSED)
+		bytes_xfrd = 0;
+
+	debug_isoc_completed(imx21,
+		imx21_hc_get_frame(hcd), td, cc, bytes_xfrd);
+	if (cc) {
+		urb_priv->isoc_status = -EXDEV;
+		dev_dbg(imx21->dev,
+			"bad iso cc=0x%X frame=%d sched frame=%d "
+			"cnt=%d len=%d urb=%p etd=%d index=%d\n",
+			cc,  imx21_hc_get_frame(hcd), td->frame,
+			bytes_xfrd, td->len, urb, etd_num, isoc_index);
+	}
+
+	if (dir_in)
+		clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
+
+	urb->actual_length += bytes_xfrd;
+	urb->iso_frame_desc[isoc_index].actual_length = bytes_xfrd;
+	urb->iso_frame_desc[isoc_index].status = cc_to_error[cc];
+
+	etd->td = NULL;
+	etd->urb = NULL;
+	etd->ep = NULL;
+
+	if (--urb_priv->isoc_remaining == 0)
+		urb_done(hcd, urb, urb_priv->isoc_status);
+
+	schedule_isoc_etds(hcd, ep);
+}
+
+static struct ep_priv *alloc_isoc_ep(
+	struct imx21 *imx21, struct usb_host_endpoint *ep)
+{
+	struct ep_priv *ep_priv;
+	int i;
+
+	ep_priv = kzalloc(sizeof(struct ep_priv), GFP_ATOMIC);
+	if (ep_priv == NULL)
+		return NULL;
+
+	/* Allocate the ETDs */
+	for (i = 0; i < NUM_ISO_ETDS; i++) {
+		ep_priv->etd[i] = alloc_etd(imx21);
+		if (ep_priv->etd[i] < 0) {
+			int j;
+			dev_err(imx21->dev, "isoc: Couldn't allocate etd\n");
+			for (j = 0; j < i; j++)
+				free_etd(imx21, ep_priv->etd[j]);
+			goto alloc_etd_failed;
+		}
+		imx21->etd[ep_priv->etd[i]].ep = ep;
+	}
+
+	INIT_LIST_HEAD(&ep_priv->td_list);
+	ep_priv->ep = ep;
+	ep->hcpriv = ep_priv;
+	return ep_priv;
+
+alloc_etd_failed:
+	kfree(ep_priv);
+	return NULL;
+}
+
+static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
+				     struct usb_host_endpoint *ep,
+				     struct urb *urb, gfp_t mem_flags)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	struct urb_priv *urb_priv;
+	unsigned long flags;
+	struct ep_priv *ep_priv;
+	struct td *td = NULL;
+	int i;
+	int ret;
+	int cur_frame;
+	u16 maxpacket;
+
+	urb_priv = kzalloc(sizeof(struct urb_priv), mem_flags);
+	if (urb_priv == NULL)
+		return -ENOMEM;
+
+	urb_priv->isoc_td = kzalloc(
+		sizeof(struct td) * urb->number_of_packets, mem_flags);
+	if (urb_priv->isoc_td == NULL) {
+		ret = -ENOMEM;
+		goto alloc_td_failed;
+	}
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	if (ep->hcpriv == NULL) {
+		ep_priv = alloc_isoc_ep(imx21, ep);
+		if (ep_priv == NULL) {
+			ret = -ENOMEM;
+			goto alloc_ep_failed;
+		}
+	} else {
+		ep_priv = ep->hcpriv;
+	}
+
+	ret = usb_hcd_link_urb_to_ep(hcd, urb);
+	if (ret)
+		goto link_failed;
+
+	urb->status = -EINPROGRESS;
+	urb->actual_length = 0;
+	urb->error_count = 0;
+	urb->hcpriv = urb_priv;
+	urb_priv->ep = ep;
+
+	/* allocate data memory for largest packets if not already done */
+	maxpacket = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+	for (i = 0; i < NUM_ISO_ETDS; i++) {
+		struct etd_priv *etd = &imx21->etd[ep_priv->etd[i]];
+
+		if (etd->dmem_size > 0 && etd->dmem_size < maxpacket) {
+			/* not sure if this can really occur.... */
+			dev_err(imx21->dev, "increasing isoc buffer %d->%d\n",
+				etd->dmem_size, maxpacket);
+			ret = -EMSGSIZE;
+			goto alloc_dmem_failed;
+		}
+
+		if (etd->dmem_size == 0) {
+			etd->dmem_offset = alloc_dmem(imx21, maxpacket, ep);
+			if (etd->dmem_offset < 0) {
+				dev_dbg(imx21->dev, "failed alloc isoc dmem\n");
+				ret = -EAGAIN;
+				goto alloc_dmem_failed;
+			}
+			etd->dmem_size = maxpacket;
+		}
+	}
+
+	/* calculate frame */
+	cur_frame = imx21_hc_get_frame(hcd);
+	if (urb->transfer_flags & URB_ISO_ASAP) {
+		if (list_empty(&ep_priv->td_list))
+			urb->start_frame = cur_frame + 5;
+		else
+			urb->start_frame = list_entry(
+				ep_priv->td_list.prev,
+				struct td, list)->frame + urb->interval;
+	}
+	urb->start_frame = wrap_frame(urb->start_frame);
+	if (frame_after(cur_frame, urb->start_frame)) {
+		dev_dbg(imx21->dev,
+			"enqueue: adjusting iso start %d (cur=%d) asap=%d\n",
+			urb->start_frame, cur_frame,
+			(urb->transfer_flags & URB_ISO_ASAP) != 0);
+		urb->start_frame = wrap_frame(cur_frame + 1);
+	}
+
+	/* set up transfers */
+	td = urb_priv->isoc_td;
+	for (i = 0; i < urb->number_of_packets; i++, td++) {
+		td->ep = ep;
+		td->urb = urb;
+		td->len = urb->iso_frame_desc[i].length;
+		td->isoc_index = i;
+		td->frame = wrap_frame(urb->start_frame + urb->interval * i);
+		td->data = urb->transfer_dma + urb->iso_frame_desc[i].offset;
+		list_add_tail(&td->list, &ep_priv->td_list);
+	}
+
+	urb_priv->isoc_remaining = urb->number_of_packets;
+	dev_vdbg(imx21->dev, "setup %d packets for iso frame %d->%d\n",
+		urb->number_of_packets, urb->start_frame, td->frame);
+
+	debug_urb_submitted(imx21, urb);
+	schedule_isoc_etds(hcd, ep);
+
+	spin_unlock_irqrestore(&imx21->lock, flags);
+	return 0;
+
+alloc_dmem_failed:
+	usb_hcd_unlink_urb_from_ep(hcd, urb);
+
+link_failed:
+alloc_ep_failed:
+	spin_unlock_irqrestore(&imx21->lock, flags);
+	kfree(urb_priv->isoc_td);
+
+alloc_td_failed:
+	kfree(urb_priv);
+	return ret;
+}
+
+static void dequeue_isoc_urb(struct imx21 *imx21,
+	struct urb *urb, struct ep_priv *ep_priv)
+{
+	struct urb_priv *urb_priv = urb->hcpriv;
+	struct td *td, *tmp;
+	int i;
+
+	if (urb_priv->active) {
+		for (i = 0; i < NUM_ISO_ETDS; i++) {
+			int etd_num = ep_priv->etd[i];
+			if (etd_num != -1 && imx21->etd[etd_num].urb == urb) {
+				struct etd_priv *etd = imx21->etd + etd_num;
+
+				reset_etd(imx21, etd_num);
+				if (etd->dmem_size)
+					free_dmem(imx21, etd->dmem_offset);
+				etd->dmem_size = 0;
+			}
+		}
+	}
+
+	list_for_each_entry_safe(td, tmp, &ep_priv->td_list, list) {
+		if (td->urb == urb) {
+			dev_vdbg(imx21->dev, "removing td %p\n", td);
+			list_del(&td->list);
+		}
+	}
+}
+
+/* =========================================== */
+/* NON ISOC Handling ... 			*/
+/* =========================================== */
+
+static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
+{
+	unsigned int pipe = urb->pipe;
+	struct urb_priv *urb_priv = urb->hcpriv;
+	struct ep_priv *ep_priv = urb_priv->ep->hcpriv;
+	int state = urb_priv->state;
+	int etd_num = ep_priv->etd[0];
+	struct etd_priv *etd;
+	int dmem_offset;
+	u32 count;
+	u16 etd_buf_size;
+	u16 maxpacket;
+	u8 dir;
+	u8 bufround;
+	u8 datatoggle;
+	u8 interval = 0;
+	u8 relpolpos = 0;
+
+	if (etd_num < 0) {
+		dev_err(imx21->dev, "No valid ETD\n");
+		return;
+	}
+	if (readl(imx21->regs + USBH_ETDENSET) & (1 << etd_num))
+		dev_err(imx21->dev, "submitting to active ETD %d\n", etd_num);
+
+	etd = &imx21->etd[etd_num];
+	maxpacket = usb_maxpacket(urb->dev, pipe, usb_pipeout(pipe));
+	if (!maxpacket)
+		maxpacket = 8;
+
+	if (usb_pipecontrol(pipe) && (state != US_CTRL_DATA)) {
+		if (state == US_CTRL_SETUP) {
+			dir = TD_DIR_SETUP;
+			etd->dma_handle = urb->setup_dma;
+			bufround = 0;
+			count = 8;
+			datatoggle = TD_TOGGLE_DATA0;
+		} else {	/* US_CTRL_ACK */
+			dir = usb_pipeout(pipe) ? TD_DIR_IN : TD_DIR_OUT;
+			etd->dma_handle = urb->transfer_dma;
+			bufround = 0;
+			count = 0;
+			datatoggle = TD_TOGGLE_DATA1;
+		}
+	} else {
+		dir = usb_pipeout(pipe) ? TD_DIR_OUT : TD_DIR_IN;
+		bufround = (dir == TD_DIR_IN) ? 1 : 0;
+		etd->dma_handle = urb->transfer_dma;
+		if (usb_pipebulk(pipe) && (state == US_BULK0))
+			count = 0;
+		else
+			count = urb->transfer_buffer_length;
+
+		if (usb_pipecontrol(pipe)) {
+			datatoggle = TD_TOGGLE_DATA1;
+		} else {
+			if (usb_gettoggle(
+					urb->dev,
+					usb_pipeendpoint(urb->pipe),
+					usb_pipeout(urb->pipe)))
+				datatoggle = TD_TOGGLE_DATA1;
+			else
+				datatoggle = TD_TOGGLE_DATA0;
+		}
+	}
+
+	etd->urb = urb;
+	etd->ep = urb_priv->ep;
+	etd->len = count;
+
+	if (usb_pipeint(pipe)) {
+		interval = urb->interval;
+		relpolpos = (readl(imx21->regs + USBH_FRMNUB) + 1) & 0xff;
+	}
+
+	/* Write ETD to device memory */
+	setup_etd_dword0(imx21, etd_num, urb, dir, maxpacket);
+
+	etd_writel(imx21, etd_num, 2,
+		(u32) interval << DW2_POLINTERV |
+		((u32) relpolpos << DW2_RELPOLPOS) |
+		((u32) dir << DW2_DIRPID) |
+		((u32) bufround << DW2_BUFROUND) |
+		((u32) datatoggle << DW2_DATATOG) |
+		((u32) TD_NOTACCESSED << DW2_COMPCODE));
+
+	/* DMA will always transfer buffer size even if TOBYCNT in DWORD3
+	   is smaller. Make sure we don't overrun the buffer!
+	 */
+	if (count && count < maxpacket)
+		etd_buf_size = count;
+	else
+		etd_buf_size = maxpacket;
+
+	etd_writel(imx21, etd_num, 3,
+		((u32) (etd_buf_size - 1) << DW3_BUFSIZE) | (u32) count);
+
+	if (!count)
+		etd->dma_handle = 0;
+
+	/* allocate x and y buffer space at once */
+	etd->dmem_size = (count > maxpacket) ? maxpacket * 2 : maxpacket;
+	dmem_offset = alloc_dmem(imx21, etd->dmem_size, urb_priv->ep);
+	if (dmem_offset < 0) {
+		/* Setup everything we can in HW and update when we get DMEM */
+		etd_writel(imx21, etd_num, 1, (u32)maxpacket << 16);
+
+		dev_dbg(imx21->dev, "Queuing etd %d for DMEM\n", etd_num);
+		debug_urb_queued_for_dmem(imx21, urb);
+		list_add_tail(&etd->queue, &imx21->queue_for_dmem);
+		return;
+	}
+
+	etd_writel(imx21, etd_num, 1,
+		(((u32) dmem_offset + (u32) maxpacket) << DW1_YBUFSRTAD) |
+		(u32) dmem_offset);
+
+	urb_priv->active = 1;
+
+	/* enable the ETD to kick off transfer */
+	dev_vdbg(imx21->dev, "Activating etd %d for %d bytes %s\n",
+		etd_num, count, dir != TD_DIR_IN ? "out" : "in");
+	activate_etd(imx21, etd_num, etd->dma_handle, dir);
+
+}
+
+static void nonisoc_etd_done(struct usb_hcd *hcd, struct urb *urb, int etd_num)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	struct etd_priv *etd = &imx21->etd[etd_num];
+	u32 etd_mask = 1 << etd_num;
+	struct urb_priv *urb_priv = urb->hcpriv;
+	int dir;
+	u16 xbufaddr;
+	int cc;
+	u32 bytes_xfrd;
+	int etd_done;
+
+	disactivate_etd(imx21, etd_num);
+
+	dir = (etd_readl(imx21, etd_num, 0) >> DW0_DIRECT) & 0x3;
+	xbufaddr = etd_readl(imx21, etd_num, 1) & 0xffff;
+	cc = (etd_readl(imx21, etd_num, 2) >> DW2_COMPCODE) & 0xf;
+	bytes_xfrd = etd->len - (etd_readl(imx21, etd_num, 3) & 0x1fffff);
+
+	/* save toggle carry */
+	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+		      usb_pipeout(urb->pipe),
+		      (etd_readl(imx21, etd_num, 0) >> DW0_TOGCRY) & 0x1);
+
+	if (dir == TD_DIR_IN) {
+		clear_toggle_bit(imx21, USBH_XFILLSTAT, etd_mask);
+		clear_toggle_bit(imx21, USBH_YFILLSTAT, etd_mask);
+	}
+	free_dmem(imx21, xbufaddr);
+
+	urb->error_count = 0;
+	if (!(urb->transfer_flags & URB_SHORT_NOT_OK)
+			&& (cc == TD_DATAUNDERRUN))
+		cc = TD_CC_NOERROR;
+
+	if (cc != 0)
+		dev_vdbg(imx21->dev, "cc is 0x%x\n", cc);
+
+	etd_done = (cc_to_error[cc] != 0);	/* stop if error */
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		switch (urb_priv->state) {
+		case US_CTRL_SETUP:
+			if (urb->transfer_buffer_length > 0)
+				urb_priv->state = US_CTRL_DATA;
+			else
+				urb_priv->state = US_CTRL_ACK;
+			break;
+		case US_CTRL_DATA:
+			urb->actual_length += bytes_xfrd;
+			urb_priv->state = US_CTRL_ACK;
+			break;
+		case US_CTRL_ACK:
+			etd_done = 1;
+			break;
+		default:
+			dev_err(imx21->dev,
+				"Invalid pipe state %d\n", urb_priv->state);
+			etd_done = 1;
+			break;
+		}
+		break;
+
+	case PIPE_BULK:
+		urb->actual_length += bytes_xfrd;
+		if ((urb_priv->state == US_BULK)
+		    && (urb->transfer_flags & URB_ZERO_PACKET)
+		    && urb->transfer_buffer_length > 0
+		    && ((urb->transfer_buffer_length %
+			 usb_maxpacket(urb->dev, urb->pipe,
+				       usb_pipeout(urb->pipe))) == 0)) {
+			/* need a 0-packet */
+			urb_priv->state = US_BULK0;
+		} else {
+			etd_done = 1;
+		}
+		break;
+
+	case PIPE_INTERRUPT:
+		urb->actual_length += bytes_xfrd;
+		etd_done = 1;
+		break;
+	}
+
+	if (!etd_done) {
+		dev_vdbg(imx21->dev, "next state=%d\n", urb_priv->state);
+		schedule_nonisoc_etd(imx21, urb);
+	} else {
+		struct usb_host_endpoint *ep = urb->ep;
+
+		urb_done(hcd, urb, cc_to_error[cc]);
+		etd->urb = NULL;
+
+		if (!list_empty(&ep->urb_list)) {
+			urb = list_first_entry(&ep->urb_list,
+				struct urb, urb_list);
+			dev_vdbg(imx21->dev, "next URB %p\n", urb);
+			schedule_nonisoc_etd(imx21, urb);
+		}
+	}
+}
+
+static struct ep_priv *alloc_ep(void)
+{
+	int i;
+	struct ep_priv *ep_priv;
+
+	ep_priv = kzalloc(sizeof(struct ep_priv), GFP_ATOMIC);
+	if (!ep_priv)
+		return NULL;
+
+	for (i = 0; i < NUM_ISO_ETDS; ++i)
+		ep_priv->etd[i] = -1;
+
+	return ep_priv;
+}
+
+static int imx21_hc_urb_enqueue(struct usb_hcd *hcd,
+				struct urb *urb, gfp_t mem_flags)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	struct usb_host_endpoint *ep = urb->ep;
+	struct urb_priv *urb_priv;
+	struct ep_priv *ep_priv;
+	struct etd_priv *etd;
+	int ret;
+	unsigned long flags;
+	int new_ep = 0;
+
+	dev_vdbg(imx21->dev,
+		"enqueue urb=%p ep=%p len=%d "
+		"buffer=%p dma=%08X setupBuf=%p setupDma=%08X\n",
+		urb, ep,
+		urb->transfer_buffer_length,
+		urb->transfer_buffer, urb->transfer_dma,
+		urb->setup_packet, urb->setup_dma);
+
+	if (usb_pipeisoc(urb->pipe))
+		return imx21_hc_urb_enqueue_isoc(hcd, ep, urb, mem_flags);
+
+	urb_priv = kzalloc(sizeof(struct urb_priv), mem_flags);
+	if (!urb_priv)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	ep_priv = ep->hcpriv;
+	if (ep_priv == NULL) {
+		ep_priv = alloc_ep();
+		if (!ep_priv) {
+			ret = -ENOMEM;
+			goto failed_alloc_ep;
+		}
+		ep->hcpriv = ep_priv;
+		ep_priv->ep = ep;
+		new_ep = 1;
+	}
+
+	ret = usb_hcd_link_urb_to_ep(hcd, urb);
+	if (ret)
+		goto failed_link;
+
+	urb->status = -EINPROGRESS;
+	urb->actual_length = 0;
+	urb->error_count = 0;
+	urb->hcpriv = urb_priv;
+	urb_priv->ep = ep;
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		urb_priv->state = US_CTRL_SETUP;
+		break;
+	case PIPE_BULK:
+		urb_priv->state = US_BULK;
+		break;
+	}
+
+	debug_urb_submitted(imx21, urb);
+	if (ep_priv->etd[0] < 0) {
+		if (ep_priv->waiting_etd) {
+			dev_dbg(imx21->dev,
+				"no ETD available already queued %p\n",
+				ep_priv);
+			debug_urb_queued_for_etd(imx21, urb);
+			goto out;
+		}
+		ep_priv->etd[0] = alloc_etd(imx21);
+		if (ep_priv->etd[0] < 0) {
+			dev_dbg(imx21->dev,
+				"no ETD available queueing %p\n", ep_priv);
+			debug_urb_queued_for_etd(imx21, urb);
+			list_add_tail(&ep_priv->queue, &imx21->queue_for_etd);
+			ep_priv->waiting_etd = 1;
+			goto out;
+		}
+	}
+
+	/* Schedule if no URB already active for this endpoint */
+	etd = &imx21->etd[ep_priv->etd[0]];
+	if (etd->urb == NULL) {
+		DEBUG_LOG_FRAME(imx21, etd, last_req);
+		schedule_nonisoc_etd(imx21, urb);
+	}
+
+out:
+	spin_unlock_irqrestore(&imx21->lock, flags);
+	return 0;
+
+failed_link:
+failed_alloc_ep:
+	spin_unlock_irqrestore(&imx21->lock, flags);
+	kfree(urb_priv);
+	return ret;
+}
+
+static int imx21_hc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
+				int status)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	unsigned long flags;
+	struct usb_host_endpoint *ep;
+	struct ep_priv *ep_priv;
+	struct urb_priv *urb_priv = urb->hcpriv;
+	int ret = -EINVAL;
+
+	dev_vdbg(imx21->dev, "dequeue urb=%p iso=%d status=%d\n",
+		urb, usb_pipeisoc(urb->pipe), status);
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	ret = usb_hcd_check_unlink_urb(hcd, urb, status);
+	if (ret)
+		goto fail;
+	ep = urb_priv->ep;
+	ep_priv = ep->hcpriv;
+
+	debug_urb_unlinked(imx21, urb);
+
+	if (usb_pipeisoc(urb->pipe)) {
+		dequeue_isoc_urb(imx21, urb, ep_priv);
+		schedule_isoc_etds(hcd, ep);
+	} else if (urb_priv->active) {
+		int etd_num = ep_priv->etd[0];
+		if (etd_num != -1) {
+			disactivate_etd(imx21, etd_num);
+			free_dmem(imx21, etd_readl(imx21, etd_num, 1) & 0xffff);
+			imx21->etd[etd_num].urb = NULL;
+		}
+	}
+
+	urb_done(hcd, urb, status);
+
+	spin_unlock_irqrestore(&imx21->lock, flags);
+	return 0;
+
+fail:
+	spin_unlock_irqrestore(&imx21->lock, flags);
+	return ret;
+}
+
+/* =========================================== */
+/* Interrupt dispatch	 			*/
+/* =========================================== */
+
+static void process_etds(struct usb_hcd *hcd, struct imx21 *imx21, int sof)
+{
+	int etd_num;
+	int enable_sof_int = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	for (etd_num = 0; etd_num < USB_NUM_ETD; etd_num++) {
+		u32 etd_mask = 1 << etd_num;
+		u32 enabled = readl(imx21->regs + USBH_ETDENSET) & etd_mask;
+		u32 done = readl(imx21->regs + USBH_ETDDONESTAT) & etd_mask;
+		struct etd_priv *etd = &imx21->etd[etd_num];
+
+
+		if (done) {
+			DEBUG_LOG_FRAME(imx21, etd, last_int);
+		} else {
+/*
+ * Kludge warning!
+ *
+ * When multiple transfers are using the bus we sometimes get into a state
+ * where the transfer has completed (the CC field of the ETD is != 0x0F),
+ * the ETD has self disabled but the ETDDONESTAT flag is not set
+ * (and hence no interrupt occurs).
+ * This causes the transfer in question to hang.
+ * The kludge below checks for this condition at each SOF and processes any
+ * blocked ETDs (after an arbitary 10 frame wait)
+ *
+ * With a single active transfer the usbtest test suite will run for days
+ * without the kludge.
+ * With other bus activity (eg mass storage) even just test1 will hang without
+ * the kludge.
+ */
+			u32 dword0;
+			int cc;
+
+			if (etd->active_count && !enabled) /* suspicious... */
+				enable_sof_int = 1;
+
+			if (!sof || enabled || !etd->active_count)
+				continue;
+
+			cc = etd_readl(imx21, etd_num, 2) >> DW2_COMPCODE;
+			if (cc == TD_NOTACCESSED)
+				continue;
+
+			if (++etd->active_count < 10)
+				continue;
+
+			dword0 = etd_readl(imx21, etd_num, 0);
+			dev_dbg(imx21->dev,
+				"unblock ETD %d dev=0x%X ep=0x%X cc=0x%02X!\n",
+				etd_num, dword0 & 0x7F,
+				(dword0 >> DW0_ENDPNT) & 0x0F,
+				cc);
+
+#ifdef DEBUG
+			dev_dbg(imx21->dev,
+				"frame: act=%d disact=%d"
+				" int=%d req=%d cur=%d\n",
+				etd->activated_frame,
+				etd->disactivated_frame,
+				etd->last_int_frame,
+				etd->last_req_frame,
+				readl(imx21->regs + USBH_FRMNUB));
+			imx21->debug_unblocks++;
+#endif
+			etd->active_count = 0;
+/* End of kludge */
+		}
+
+		if (etd->ep == NULL || etd->urb == NULL) {
+			dev_dbg(imx21->dev,
+				"Interrupt for unexpected etd %d"
+				" ep=%p urb=%p\n",
+				etd_num, etd->ep, etd->urb);
+			disactivate_etd(imx21, etd_num);
+			continue;
+		}
+
+		if (usb_pipeisoc(etd->urb->pipe))
+			isoc_etd_done(hcd, etd->urb, etd_num);
+		else
+			nonisoc_etd_done(hcd, etd->urb, etd_num);
+	}
+
+	/* only enable SOF interrupt if it may be needed for the kludge */
+	if (enable_sof_int)
+		set_register_bits(imx21, USBH_SYSIEN, USBH_SYSIEN_SOFINT);
+	else
+		clear_register_bits(imx21, USBH_SYSIEN, USBH_SYSIEN_SOFINT);
+
+
+	spin_unlock_irqrestore(&imx21->lock, flags);
+}
+
+static irqreturn_t imx21_irq(struct usb_hcd *hcd)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	u32 ints = readl(imx21->regs + USBH_SYSISR);
+
+	if (ints & USBH_SYSIEN_HERRINT)
+		dev_dbg(imx21->dev, "Scheduling error\n");
+
+	if (ints & USBH_SYSIEN_SORINT)
+		dev_dbg(imx21->dev, "Scheduling overrun\n");
+
+	if (ints & (USBH_SYSISR_DONEINT | USBH_SYSISR_SOFINT))
+		process_etds(hcd, imx21, ints & USBH_SYSISR_SOFINT);
+
+	writel(ints, imx21->regs + USBH_SYSISR);
+	return IRQ_HANDLED;
+}
+
+static void imx21_hc_endpoint_disable(struct usb_hcd *hcd,
+				      struct usb_host_endpoint *ep)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	unsigned long flags;
+	struct ep_priv *ep_priv;
+	int i;
+
+	if (ep == NULL)
+		return;
+
+	spin_lock_irqsave(&imx21->lock, flags);
+	ep_priv = ep->hcpriv;
+	dev_vdbg(imx21->dev, "disable ep=%p, ep->hcpriv=%p\n", ep, ep_priv);
+
+	if (!list_empty(&ep->urb_list))
+		dev_dbg(imx21->dev, "ep's URB list is not empty\n");
+
+	if (ep_priv != NULL) {
+		for (i = 0; i < NUM_ISO_ETDS; i++) {
+			if (ep_priv->etd[i] > -1)
+				dev_dbg(imx21->dev, "free etd %d for disable\n",
+					ep_priv->etd[i]);
+
+			free_etd(imx21, ep_priv->etd[i]);
+		}
+		kfree(ep_priv);
+		ep->hcpriv = NULL;
+	}
+
+	for (i = 0; i < USB_NUM_ETD; i++) {
+		if (imx21->etd[i].alloc && imx21->etd[i].ep == ep) {
+			dev_err(imx21->dev,
+				"Active etd %d for disabled ep=%p!\n", i, ep);
+			free_etd(imx21, i);
+		}
+	}
+	free_epdmem(imx21, ep);
+	spin_unlock_irqrestore(&imx21->lock, flags);
+}
+
+/* =========================================== */
+/* Hub handling		 			*/
+/* =========================================== */
+
+static int get_hub_descriptor(struct usb_hcd *hcd,
+			      struct usb_hub_descriptor *desc)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	desc->bDescriptorType = 0x29;	/* HUB descriptor */
+	desc->bHubContrCurrent = 0;
+
+	desc->bNbrPorts = readl(imx21->regs + USBH_ROOTHUBA)
+		& USBH_ROOTHUBA_NDNSTMPRT_MASK;
+	desc->bDescLength = 9;
+	desc->bPwrOn2PwrGood = 0;
+	desc->wHubCharacteristics = (__force __u16) cpu_to_le16(
+		0x0002 |	/* No power switching */
+		0x0010 |	/* No over current protection */
+		0);
+
+	desc->bitmap[0] = 1 << 1;
+	desc->bitmap[1] = ~0;
+	return 0;
+}
+
+static int imx21_hc_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	int ports;
+	int changed = 0;
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&imx21->lock, flags);
+	ports = readl(imx21->regs + USBH_ROOTHUBA)
+		& USBH_ROOTHUBA_NDNSTMPRT_MASK;
+	if (ports > 7) {
+		ports = 7;
+		dev_err(imx21->dev, "ports %d > 7\n", ports);
+	}
+	for (i = 0; i < ports; i++) {
+		if (readl(imx21->regs + USBH_PORTSTAT(i)) &
+			(USBH_PORTSTAT_CONNECTSC |
+			USBH_PORTSTAT_PRTENBLSC |
+			USBH_PORTSTAT_PRTSTATSC |
+			USBH_PORTSTAT_OVRCURIC |
+			USBH_PORTSTAT_PRTRSTSC)) {
+
+			changed = 1;
+			buf[0] |= 1 << (i + 1);
+		}
+	}
+	spin_unlock_irqrestore(&imx21->lock, flags);
+
+	if (changed)
+		dev_info(imx21->dev, "Hub status changed\n");
+	return changed;
+}
+
+static int imx21_hc_hub_control(struct usb_hcd *hcd,
+				u16 typeReq,
+				u16 wValue, u16 wIndex, char *buf, u16 wLength)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	int rc = 0;
+	u32 status_write = 0;
+
+	switch (typeReq) {
+	case ClearHubFeature:
+		dev_dbg(imx21->dev, "ClearHubFeature\n");
+		switch (wValue) {
+		case C_HUB_OVER_CURRENT:
+			dev_dbg(imx21->dev, "    OVER_CURRENT\n");
+			break;
+		case C_HUB_LOCAL_POWER:
+			dev_dbg(imx21->dev, "    LOCAL_POWER\n");
+			break;
+		default:
+			dev_dbg(imx21->dev, "    unknown\n");
+			rc = -EINVAL;
+			break;
+		}
+		break;
+
+	case ClearPortFeature:
+		dev_dbg(imx21->dev, "ClearPortFeature\n");
+		switch (wValue) {
+		case USB_PORT_FEAT_ENABLE:
+			dev_dbg(imx21->dev, "    ENABLE\n");
+			status_write = USBH_PORTSTAT_CURCONST;
+			break;
+		case USB_PORT_FEAT_SUSPEND:
+			dev_dbg(imx21->dev, "    SUSPEND\n");
+			status_write = USBH_PORTSTAT_PRTOVRCURI;
+			break;
+		case USB_PORT_FEAT_POWER:
+			dev_dbg(imx21->dev, "    POWER\n");
+			status_write = USBH_PORTSTAT_LSDEVCON;
+			break;
+		case USB_PORT_FEAT_C_ENABLE:
+			dev_dbg(imx21->dev, "    C_ENABLE\n");
+			status_write = USBH_PORTSTAT_PRTENBLSC;
+			break;
+		case USB_PORT_FEAT_C_SUSPEND:
+			dev_dbg(imx21->dev, "    C_SUSPEND\n");
+			status_write = USBH_PORTSTAT_PRTSTATSC;
+			break;
+		case USB_PORT_FEAT_C_CONNECTION:
+			dev_dbg(imx21->dev, "    C_CONNECTION\n");
+			status_write = USBH_PORTSTAT_CONNECTSC;
+			break;
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+			dev_dbg(imx21->dev, "    C_OVER_CURRENT\n");
+			status_write = USBH_PORTSTAT_OVRCURIC;
+			break;
+		case USB_PORT_FEAT_C_RESET:
+			dev_dbg(imx21->dev, "    C_RESET\n");
+			status_write = USBH_PORTSTAT_PRTRSTSC;
+			break;
+		default:
+			dev_dbg(imx21->dev, "    unknown\n");
+			rc = -EINVAL;
+			break;
+		}
+
+		break;
+
+	case GetHubDescriptor:
+		dev_dbg(imx21->dev, "GetHubDescriptor\n");
+		rc = get_hub_descriptor(hcd, (void *)buf);
+		break;
+
+	case GetHubStatus:
+		dev_dbg(imx21->dev, "  GetHubStatus\n");
+		*(__le32 *) buf = 0;
+		break;
+
+	case GetPortStatus:
+		dev_dbg(imx21->dev, "GetPortStatus: port: %d, 0x%x\n",
+		    wIndex, USBH_PORTSTAT(wIndex - 1));
+		*(__le32 *) buf = readl(imx21->regs +
+			USBH_PORTSTAT(wIndex - 1));
+		break;
+
+	case SetHubFeature:
+		dev_dbg(imx21->dev, "SetHubFeature\n");
+		switch (wValue) {
+		case C_HUB_OVER_CURRENT:
+			dev_dbg(imx21->dev, "    OVER_CURRENT\n");
+			break;
+
+		case C_HUB_LOCAL_POWER:
+			dev_dbg(imx21->dev, "    LOCAL_POWER\n");
+			break;
+		default:
+			dev_dbg(imx21->dev, "    unknown\n");
+			rc = -EINVAL;
+			break;
+		}
+
+		break;
+
+	case SetPortFeature:
+		dev_dbg(imx21->dev, "SetPortFeature\n");
+		switch (wValue) {
+		case USB_PORT_FEAT_SUSPEND:
+			dev_dbg(imx21->dev, "    SUSPEND\n");
+			status_write = USBH_PORTSTAT_PRTSUSPST;
+			break;
+		case USB_PORT_FEAT_POWER:
+			dev_dbg(imx21->dev, "    POWER\n");
+			status_write = USBH_PORTSTAT_PRTPWRST;
+			break;
+		case USB_PORT_FEAT_RESET:
+			dev_dbg(imx21->dev, "    RESET\n");
+			status_write = USBH_PORTSTAT_PRTRSTST;
+			break;
+		default:
+			dev_dbg(imx21->dev, "    unknown\n");
+			rc = -EINVAL;
+			break;
+		}
+		break;
+
+	default:
+		dev_dbg(imx21->dev, "  unknown\n");
+		rc = -EINVAL;
+		break;
+	}
+
+	if (status_write)
+		writel(status_write, imx21->regs + USBH_PORTSTAT(wIndex - 1));
+	return rc;
+}
+
+/* =========================================== */
+/* Host controller management 			*/
+/* =========================================== */
+
+static int imx21_hc_reset(struct usb_hcd *hcd)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	unsigned long timeout;
+	unsigned long flags;
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	/* Reset the Host controler modules */
+	writel(USBOTG_RST_RSTCTRL | USBOTG_RST_RSTRH |
+		USBOTG_RST_RSTHSIE | USBOTG_RST_RSTHC,
+		imx21->regs + USBOTG_RST_CTRL);
+
+	/* Wait for reset to finish */
+	timeout = jiffies + HZ;
+	while (readl(imx21->regs + USBOTG_RST_CTRL) != 0) {
+		if (time_after(jiffies, timeout)) {
+			spin_unlock_irqrestore(&imx21->lock, flags);
+			dev_err(imx21->dev, "timeout waiting for reset\n");
+			return -ETIMEDOUT;
+		}
+		spin_unlock_irq(&imx21->lock);
+		schedule_timeout(1);
+		spin_lock_irq(&imx21->lock);
+	}
+	spin_unlock_irqrestore(&imx21->lock, flags);
+	return 0;
+}
+
+static int __devinit imx21_hc_start(struct usb_hcd *hcd)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	unsigned long flags;
+	int i, j;
+	u32 hw_mode = USBOTG_HWMODE_CRECFG_HOST;
+	u32 usb_control = 0;
+
+	hw_mode |= ((imx21->pdata->host_xcvr << USBOTG_HWMODE_HOSTXCVR_SHIFT) &
+			USBOTG_HWMODE_HOSTXCVR_MASK);
+	hw_mode |= ((imx21->pdata->otg_xcvr << USBOTG_HWMODE_OTGXCVR_SHIFT) &
+			USBOTG_HWMODE_OTGXCVR_MASK);
+
+	if (imx21->pdata->host1_txenoe)
+		usb_control |= USBCTRL_HOST1_TXEN_OE;
+
+	if (!imx21->pdata->host1_xcverless)
+		usb_control |= USBCTRL_HOST1_BYP_TLL;
+
+	if (imx21->pdata->otg_ext_xcvr)
+		usb_control |= USBCTRL_OTC_RCV_RXDP;
+
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	writel((USBOTG_CLK_CTRL_HST | USBOTG_CLK_CTRL_MAIN),
+		imx21->regs + USBOTG_CLK_CTRL);
+	writel(hw_mode, imx21->regs + USBOTG_HWMODE);
+	writel(usb_control, imx21->regs + USBCTRL);
+	writel(USB_MISCCONTROL_SKPRTRY  | USB_MISCCONTROL_ARBMODE,
+		imx21->regs + USB_MISCCONTROL);
+
+	/* Clear the ETDs */
+	for (i = 0; i < USB_NUM_ETD; i++)
+		for (j = 0; j < 4; j++)
+			etd_writel(imx21, i, j, 0);
+
+	/* Take the HC out of reset */
+	writel(USBH_HOST_CTRL_HCUSBSTE_OPERATIONAL | USBH_HOST_CTRL_CTLBLKSR_1,
+		imx21->regs + USBH_HOST_CTRL);
+
+	/* Enable ports */
+	if (imx21->pdata->enable_otg_host)
+		writel(USBH_PORTSTAT_PRTPWRST | USBH_PORTSTAT_PRTENABST,
+			imx21->regs + USBH_PORTSTAT(0));
+
+	if (imx21->pdata->enable_host1)
+		writel(USBH_PORTSTAT_PRTPWRST | USBH_PORTSTAT_PRTENABST,
+			imx21->regs + USBH_PORTSTAT(1));
+
+	if (imx21->pdata->enable_host2)
+		writel(USBH_PORTSTAT_PRTPWRST | USBH_PORTSTAT_PRTENABST,
+			imx21->regs + USBH_PORTSTAT(2));
+
+
+	hcd->state = HC_STATE_RUNNING;
+
+	/* Enable host controller interrupts */
+	set_register_bits(imx21, USBH_SYSIEN,
+		USBH_SYSIEN_HERRINT |
+		USBH_SYSIEN_DONEINT | USBH_SYSIEN_SORINT);
+	set_register_bits(imx21, USBOTG_CINT_STEN, USBOTG_HCINT);
+
+	spin_unlock_irqrestore(&imx21->lock, flags);
+
+	return 0;
+}
+
+static void imx21_hc_stop(struct usb_hcd *hcd)
+{
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	unsigned long flags;
+
+	spin_lock_irqsave(&imx21->lock, flags);
+
+	writel(0, imx21->regs + USBH_SYSIEN);
+	clear_register_bits(imx21, USBOTG_CINT_STEN, USBOTG_HCINT);
+	clear_register_bits(imx21, USBOTG_CLK_CTRL_HST | USBOTG_CLK_CTRL_MAIN,
+					USBOTG_CLK_CTRL);
+	spin_unlock_irqrestore(&imx21->lock, flags);
+}
+
+/* =========================================== */
+/* Driver glue		 			*/
+/* =========================================== */
+
+static struct hc_driver imx21_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "IMX21 USB Host Controller",
+	.hcd_priv_size = sizeof(struct imx21),
+
+	.flags = HCD_USB11,
+	.irq = imx21_irq,
+
+	.reset = imx21_hc_reset,
+	.start = imx21_hc_start,
+	.stop = imx21_hc_stop,
+
+	/* I/O requests */
+	.urb_enqueue = imx21_hc_urb_enqueue,
+	.urb_dequeue = imx21_hc_urb_dequeue,
+	.endpoint_disable = imx21_hc_endpoint_disable,
+
+	/* scheduling support */
+	.get_frame_number = imx21_hc_get_frame,
+
+	/* Root hub support */
+	.hub_status_data = imx21_hc_hub_status_data,
+	.hub_control = imx21_hc_hub_control,
+
+};
+
+static struct mx21_usbh_platform_data default_pdata = {
+	.host_xcvr = MX21_USBXCVR_TXDIF_RXDIF,
+	.otg_xcvr = MX21_USBXCVR_TXDIF_RXDIF,
+	.enable_host1 = 1,
+	.enable_host2 = 1,
+	.enable_otg_host = 1,
+
+};
+
+static int imx21_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct imx21 *imx21 = hcd_to_imx21(hcd);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	remove_debug_files(imx21);
+	usb_remove_hcd(hcd);
+
+	if (res != NULL) {
+		clk_disable(imx21->clk);
+		clk_put(imx21->clk);
+		iounmap(imx21->regs);
+		release_mem_region(res->start, resource_size(res));
+	}
+
+	kfree(hcd);
+	return 0;
+}
+
+
+static int imx21_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct imx21 *imx21;
+	struct resource *res;
+	int ret;
+	int irq;
+
+	printk(KERN_INFO "%s\n", imx21_hc_driver.product_desc);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return -ENXIO;
+
+	hcd = usb_create_hcd(&imx21_hc_driver,
+		&pdev->dev, dev_name(&pdev->dev));
+	if (hcd == NULL) {
+		dev_err(&pdev->dev, "Cannot create hcd (%s)\n",
+		    dev_name(&pdev->dev));
+		return -ENOMEM;
+	}
+
+	imx21 = hcd_to_imx21(hcd);
+	imx21->dev = &pdev->dev;
+	imx21->pdata = pdev->dev.platform_data;
+	if (!imx21->pdata)
+		imx21->pdata = &default_pdata;
+
+	spin_lock_init(&imx21->lock);
+	INIT_LIST_HEAD(&imx21->dmem_list);
+	INIT_LIST_HEAD(&imx21->queue_for_etd);
+	INIT_LIST_HEAD(&imx21->queue_for_dmem);
+	create_debug_files(imx21);
+
+	res = request_mem_region(res->start, resource_size(res), hcd_name);
+	if (!res) {
+		ret = -EBUSY;
+		goto failed_request_mem;
+	}
+
+	imx21->regs = ioremap(res->start, resource_size(res));
+	if (imx21->regs == NULL) {
+		dev_err(imx21->dev, "Cannot map registers\n");
+		ret = -ENOMEM;
+		goto failed_ioremap;
+	}
+
+	/* Enable clocks source */
+	imx21->clk = clk_get(imx21->dev, NULL);
+	if (IS_ERR(imx21->clk)) {
+		dev_err(imx21->dev, "no clock found\n");
+		ret = PTR_ERR(imx21->clk);
+		goto failed_clock_get;
+	}
+
+	ret = clk_set_rate(imx21->clk, clk_round_rate(imx21->clk, 48000000));
+	if (ret)
+		goto failed_clock_set;
+	ret = clk_enable(imx21->clk);
+	if (ret)
+		goto failed_clock_enable;
+
+	dev_info(imx21->dev, "Hardware HC revision: 0x%02X\n",
+		(readl(imx21->regs + USBOTG_HWMODE) >> 16) & 0xFF);
+
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+	if (ret != 0) {
+		dev_err(imx21->dev, "usb_add_hcd() returned %d\n", ret);
+		goto failed_add_hcd;
+	}
+
+	return 0;
+
+failed_add_hcd:
+	clk_disable(imx21->clk);
+failed_clock_enable:
+failed_clock_set:
+	clk_put(imx21->clk);
+failed_clock_get:
+	iounmap(imx21->regs);
+failed_ioremap:
+	release_mem_region(res->start, res->end - res->start);
+failed_request_mem:
+	remove_debug_files(imx21);
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+static struct platform_driver imx21_hcd_driver = {
+	.driver = {
+		   .name = (char *)hcd_name,
+		   },
+	.probe = imx21_probe,
+	.remove = imx21_remove,
+	.suspend = NULL,
+	.resume = NULL,
+};
+
+static int __init imx21_hcd_init(void)
+{
+	return platform_driver_register(&imx21_hcd_driver);
+}
+
+static void __exit imx21_hcd_cleanup(void)
+{
+	platform_driver_unregister(&imx21_hcd_driver);
+}
+
+module_init(imx21_hcd_init);
+module_exit(imx21_hcd_cleanup);
+
+MODULE_DESCRIPTION("i.MX21 USB Host controller");
+MODULE_AUTHOR("Martin Fuzzey");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imx21-hcd");
diff --git a/drivers/usb/host/imx21-hcd.h b/drivers/usb/host/imx21-hcd.h
new file mode 100644
index 0000000..1b0d913
--- /dev/null
+++ b/drivers/usb/host/imx21-hcd.h
@@ -0,0 +1,436 @@
+/*
+ * Macros and prototypes for i.MX21
+ *
+ * Copyright (C) 2006 Loping Dog Embedded Systems
+ * Copyright (C) 2009 Martin Fuzzey
+ * Originally written by Jay Monkman <jtm@lopingdog.com>
+ * Ported to 2.6.30, debugged and enhanced by Martin Fuzzey
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU General Public License
+ * for more details.
+ *
+ * You 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_IMX21_HCD_H__
+#define __LINUX_IMX21_HCD_H__
+
+#include <mach/mx21-usbhost.h>
+
+#define NUM_ISO_ETDS 	2
+#define USB_NUM_ETD	32
+#define DMEM_SIZE   	4096
+
+/* Register definitions */
+#define USBOTG_HWMODE		0x00
+#define USBOTG_HWMODE_ANASDBEN		(1 << 14)
+#define USBOTG_HWMODE_OTGXCVR_SHIFT	6
+#define USBOTG_HWMODE_OTGXCVR_MASK	(3 << 6)
+#define USBOTG_HWMODE_OTGXCVR_TD_RD	(0 << 6)
+#define USBOTG_HWMODE_OTGXCVR_TS_RD	(2 << 6)
+#define USBOTG_HWMODE_OTGXCVR_TD_RS	(1 << 6)
+#define USBOTG_HWMODE_OTGXCVR_TS_RS	(3 << 6)
+#define USBOTG_HWMODE_HOSTXCVR_SHIFT	4
+#define USBOTG_HWMODE_HOSTXCVR_MASK	(3 << 4)
+#define USBOTG_HWMODE_HOSTXCVR_TD_RD	(0 << 4)
+#define USBOTG_HWMODE_HOSTXCVR_TS_RD	(2 << 4)
+#define USBOTG_HWMODE_HOSTXCVR_TD_RS	(1 << 4)
+#define USBOTG_HWMODE_HOSTXCVR_TS_RS	(3 << 4)
+#define USBOTG_HWMODE_CRECFG_MASK	(3 << 0)
+#define USBOTG_HWMODE_CRECFG_HOST	(1 << 0)
+#define USBOTG_HWMODE_CRECFG_FUNC	(2 << 0)
+#define USBOTG_HWMODE_CRECFG_HNP	(3 << 0)
+
+#define USBOTG_CINT_STAT	0x04
+#define USBOTG_CINT_STEN	0x08
+#define USBOTG_ASHNPINT			(1 << 5)
+#define USBOTG_ASFCINT			(1 << 4)
+#define USBOTG_ASHCINT			(1 << 3)
+#define USBOTG_SHNPINT			(1 << 2)
+#define USBOTG_FCINT			(1 << 1)
+#define USBOTG_HCINT			(1 << 0)
+
+#define USBOTG_CLK_CTRL		0x0c
+#define USBOTG_CLK_CTRL_FUNC		(1 << 2)
+#define USBOTG_CLK_CTRL_HST		(1 << 1)
+#define USBOTG_CLK_CTRL_MAIN		(1 << 0)
+
+#define USBOTG_RST_CTRL		0x10
+#define USBOTG_RST_RSTI2C		(1 << 15)
+#define USBOTG_RST_RSTCTRL		(1 << 5)
+#define USBOTG_RST_RSTFC		(1 << 4)
+#define USBOTG_RST_RSTFSKE		(1 << 3)
+#define USBOTG_RST_RSTRH		(1 << 2)
+#define USBOTG_RST_RSTHSIE		(1 << 1)
+#define USBOTG_RST_RSTHC		(1 << 0)
+
+#define USBOTG_FRM_INTVL    	0x14
+#define USBOTG_FRM_REMAIN   	0x18
+#define USBOTG_HNP_CSR	    	0x1c
+#define USBOTG_HNP_ISR	    	0x2c
+#define USBOTG_HNP_IEN	    	0x30
+
+#define USBOTG_I2C_TXCVR_REG(x)	(0x100 + (x))
+#define USBOTG_I2C_XCVR_DEVAD		0x118
+#define USBOTG_I2C_SEQ_OP_REG		0x119
+#define USBOTG_I2C_SEQ_RD_STARTAD	0x11a
+#define USBOTG_I2C_OP_CTRL_REG	     	0x11b
+#define USBOTG_I2C_SCLK_TO_SCK_HPER  	0x11e
+#define USBOTG_I2C_MASTER_INT_REG    	0x11f
+
+#define USBH_HOST_CTRL		0x80
+#define USBH_HOST_CTRL_HCRESET			(1 << 31)
+#define USBH_HOST_CTRL_SCHDOVR(x)		((x) << 16)
+#define USBH_HOST_CTRL_RMTWUEN			(1 << 4)
+#define USBH_HOST_CTRL_HCUSBSTE_RESET		(0 << 2)
+#define USBH_HOST_CTRL_HCUSBSTE_RESUME		(1 << 2)
+#define USBH_HOST_CTRL_HCUSBSTE_OPERATIONAL	(2 << 2)
+#define USBH_HOST_CTRL_HCUSBSTE_SUSPEND	(3 << 2)
+#define USBH_HOST_CTRL_CTLBLKSR_1		(0 << 0)
+#define USBH_HOST_CTRL_CTLBLKSR_2		(1 << 0)
+#define USBH_HOST_CTRL_CTLBLKSR_3		(2 << 0)
+#define USBH_HOST_CTRL_CTLBLKSR_4		(3 << 0)
+
+#define USBH_SYSISR		0x88
+#define USBH_SYSISR_PSCINT		(1 << 6)
+#define USBH_SYSISR_FMOFINT		(1 << 5)
+#define USBH_SYSISR_HERRINT		(1 << 4)
+#define USBH_SYSISR_RESDETINT		(1 << 3)
+#define USBH_SYSISR_SOFINT		(1 << 2)
+#define USBH_SYSISR_DONEINT		(1 << 1)
+#define USBH_SYSISR_SORINT		(1 << 0)
+
+#define USBH_SYSIEN	    	0x8c
+#define USBH_SYSIEN_PSCINT		(1 << 6)
+#define USBH_SYSIEN_FMOFINT		(1 << 5)
+#define USBH_SYSIEN_HERRINT		(1 << 4)
+#define USBH_SYSIEN_RESDETINT		(1 << 3)
+#define USBH_SYSIEN_SOFINT		(1 << 2)
+#define USBH_SYSIEN_DONEINT		(1 << 1)
+#define USBH_SYSIEN_SORINT		(1 << 0)
+
+#define USBH_XBUFSTAT	    	0x98
+#define USBH_YBUFSTAT	    	0x9c
+#define USBH_XYINTEN	    	0xa0
+#define USBH_XFILLSTAT	    	0xa8
+#define USBH_YFILLSTAT	    	0xac
+#define USBH_ETDENSET	    	0xc0
+#define USBH_ETDENCLR	    	0xc4
+#define USBH_IMMEDINT	    	0xcc
+#define USBH_ETDDONESTAT    	0xd0
+#define USBH_ETDDONEEN	    	0xd4
+#define USBH_FRMNUB	    	0xe0
+#define USBH_LSTHRESH	    	0xe4
+
+#define USBH_ROOTHUBA	    	0xe8
+#define USBH_ROOTHUBA_PWRTOGOOD_MASK	(0xff)
+#define USBH_ROOTHUBA_PWRTOGOOD_SHIFT	(24)
+#define USBH_ROOTHUBA_NOOVRCURP	(1 << 12)
+#define USBH_ROOTHUBA_OVRCURPM		(1 << 11)
+#define USBH_ROOTHUBA_DEVTYPE		(1 << 10)
+#define USBH_ROOTHUBA_PWRSWTMD		(1 << 9)
+#define USBH_ROOTHUBA_NOPWRSWT		(1 << 8)
+#define USBH_ROOTHUBA_NDNSTMPRT_MASK	(0xff)
+
+#define USBH_ROOTHUBB		0xec
+#define USBH_ROOTHUBB_PRTPWRCM(x)	(1 << ((x) + 16))
+#define USBH_ROOTHUBB_DEVREMOVE(x)	(1 << (x))
+
+#define USBH_ROOTSTAT		0xf0
+#define USBH_ROOTSTAT_CLRRMTWUE	(1 << 31)
+#define USBH_ROOTSTAT_OVRCURCHG	(1 << 17)
+#define USBH_ROOTSTAT_DEVCONWUE	(1 << 15)
+#define USBH_ROOTSTAT_OVRCURI		(1 << 1)
+#define USBH_ROOTSTAT_LOCPWRS		(1 << 0)
+
+#define USBH_PORTSTAT(x)	(0xf4 + ((x) * 4))
+#define USBH_PORTSTAT_PRTRSTSC		(1 << 20)
+#define USBH_PORTSTAT_OVRCURIC		(1 << 19)
+#define USBH_PORTSTAT_PRTSTATSC	(1 << 18)
+#define USBH_PORTSTAT_PRTENBLSC	(1 << 17)
+#define USBH_PORTSTAT_CONNECTSC	(1 << 16)
+#define USBH_PORTSTAT_LSDEVCON		(1 << 9)
+#define USBH_PORTSTAT_PRTPWRST		(1 << 8)
+#define USBH_PORTSTAT_PRTRSTST		(1 << 4)
+#define USBH_PORTSTAT_PRTOVRCURI	(1 << 3)
+#define USBH_PORTSTAT_PRTSUSPST	(1 << 2)
+#define USBH_PORTSTAT_PRTENABST	(1 << 1)
+#define USBH_PORTSTAT_CURCONST		(1 << 0)
+
+#define USB_DMAREV		0x800
+#define USB_DMAINTSTAT	    	0x804
+#define USB_DMAINTSTAT_EPERR		(1 << 1)
+#define USB_DMAINTSTAT_ETDERR		(1 << 0)
+
+#define USB_DMAINTEN	    	0x808
+#define USB_DMAINTEN_EPERRINTEN	(1 << 1)
+#define USB_DMAINTEN_ETDERRINTEN	(1 << 0)
+
+#define USB_ETDDMAERSTAT    	0x80c
+#define USB_EPDMAERSTAT	    	0x810
+#define USB_ETDDMAEN	    	0x820
+#define USB_EPDMAEN	    	0x824
+#define USB_ETDDMAXTEN	    	0x828
+#define USB_EPDMAXTEN	    	0x82c
+#define USB_ETDDMAENXYT	    	0x830
+#define USB_EPDMAENXYT	    	0x834
+#define USB_ETDDMABST4EN    	0x838
+#define USB_EPDMABST4EN	    	0x83c
+
+#define USB_MISCCONTROL	    	0x840
+#define USB_MISCCONTROL_ISOPREVFRM	(1 << 3)
+#define USB_MISCCONTROL_SKPRTRY	(1 << 2)
+#define USB_MISCCONTROL_ARBMODE	(1 << 1)
+#define USB_MISCCONTROL_FILTCC		(1 << 0)
+
+#define USB_ETDDMACHANLCLR  	0x848
+#define USB_EPDMACHANLCLR   	0x84c
+#define USB_ETDSMSA(x)	    	(0x900 + ((x) * 4))
+#define USB_EPSMSA(x)	    	(0x980 + ((x) * 4))
+#define USB_ETDDMABUFPTR(x) 	(0xa00 + ((x) * 4))
+#define USB_EPDMABUFPTR(x)  	(0xa80 + ((x) * 4))
+
+#define USB_ETD_DWORD(x, w)	(0x200 + ((x) * 16) + ((w) * 4))
+#define DW0_ADDRESS	0
+#define	DW0_ENDPNT	7
+#define	DW0_DIRECT	11
+#define	DW0_SPEED	13
+#define DW0_FORMAT	14
+#define DW0_MAXPKTSIZ	16
+#define DW0_HALTED	27
+#define	DW0_TOGCRY	28
+#define	DW0_SNDNAK	30
+
+#define DW1_XBUFSRTAD	0
+#define DW1_YBUFSRTAD	16
+
+#define DW2_RTRYDELAY	0
+#define DW2_POLINTERV	0
+#define DW2_STARTFRM	0
+#define DW2_RELPOLPOS	8
+#define DW2_DIRPID	16
+#define	DW2_BUFROUND	18
+#define DW2_DELAYINT	19
+#define DW2_DATATOG	22
+#define DW2_ERRORCNT	24
+#define	DW2_COMPCODE	28
+
+#define DW3_TOTBYECNT	0
+#define DW3_PKTLEN0	0
+#define DW3_COMPCODE0	12
+#define DW3_PKTLEN1	16
+#define DW3_BUFSIZE	21
+#define DW3_COMPCODE1	28
+
+#define USBCTRL		    	0x600
+#define USBCTRL_I2C_WU_INT_STAT	(1 << 27)
+#define USBCTRL_OTG_WU_INT_STAT	(1 << 26)
+#define USBCTRL_HOST_WU_INT_STAT	(1 << 25)
+#define USBCTRL_FNT_WU_INT_STAT	(1 << 24)
+#define USBCTRL_I2C_WU_INT_EN		(1 << 19)
+#define USBCTRL_OTG_WU_INT_EN		(1 << 18)
+#define USBCTRL_HOST_WU_INT_EN		(1 << 17)
+#define USBCTRL_FNT_WU_INT_EN		(1 << 16)
+#define USBCTRL_OTC_RCV_RXDP		(1 << 13)
+#define USBCTRL_HOST1_BYP_TLL		(1 << 12)
+#define USBCTRL_OTG_BYP_VAL(x)		((x) << 10)
+#define USBCTRL_HOST1_BYP_VAL(x)	((x) << 8)
+#define USBCTRL_OTG_PWR_MASK		(1 << 6)
+#define USBCTRL_HOST1_PWR_MASK		(1 << 5)
+#define USBCTRL_HOST2_PWR_MASK		(1 << 4)
+#define USBCTRL_USB_BYP			(1 << 2)
+#define USBCTRL_HOST1_TXEN_OE		(1 << 1)
+
+
+/* Values in TD blocks */
+#define TD_DIR_SETUP	    0
+#define TD_DIR_OUT	    1
+#define TD_DIR_IN	    2
+#define TD_FORMAT_CONTROL   0
+#define TD_FORMAT_ISO	    1
+#define TD_FORMAT_BULK	    2
+#define TD_FORMAT_INT	    3
+#define TD_TOGGLE_CARRY	    0
+#define TD_TOGGLE_DATA0	    2
+#define TD_TOGGLE_DATA1	    3
+
+/* control transfer states */
+#define US_CTRL_SETUP	2
+#define US_CTRL_DATA	1
+#define US_CTRL_ACK	0
+
+/* bulk transfer main state and 0-length packet */
+#define US_BULK		1
+#define US_BULK0	0
+
+/*ETD format description*/
+#define IMX_FMT_CTRL   0x0
+#define IMX_FMT_ISO    0x1
+#define IMX_FMT_BULK   0x2
+#define IMX_FMT_INT    0x3
+
+static char fmt_urb_to_etd[4] = {
+/*PIPE_ISOCHRONOUS*/ IMX_FMT_ISO,
+/*PIPE_INTERRUPT*/ IMX_FMT_INT,
+/*PIPE_CONTROL*/ IMX_FMT_CTRL,
+/*PIPE_BULK*/ IMX_FMT_BULK
+};
+
+/* condition (error) CC codes and mapping (OHCI like) */
+
+#define TD_CC_NOERROR		0x00
+#define TD_CC_CRC		0x01
+#define TD_CC_BITSTUFFING	0x02
+#define TD_CC_DATATOGGLEM	0x03
+#define TD_CC_STALL		0x04
+#define TD_DEVNOTRESP		0x05
+#define TD_PIDCHECKFAIL		0x06
+/*#define TD_UNEXPECTEDPID	0x07 - reserved, not active on MX2*/
+#define TD_DATAOVERRUN		0x08
+#define TD_DATAUNDERRUN		0x09
+#define TD_BUFFEROVERRUN	0x0C
+#define TD_BUFFERUNDERRUN	0x0D
+#define	TD_SCHEDULEOVERRUN	0x0E
+#define TD_NOTACCESSED		0x0F
+
+static const int cc_to_error[16] = {
+	/* No  Error  */ 0,
+	/* CRC Error  */ -EILSEQ,
+	/* Bit Stuff  */ -EPROTO,
+	/* Data Togg  */ -EILSEQ,
+	/* Stall      */ -EPIPE,
+	/* DevNotResp */ -ETIMEDOUT,
+	/* PIDCheck   */ -EPROTO,
+	/* UnExpPID   */ -EPROTO,
+	/* DataOver   */ -EOVERFLOW,
+	/* DataUnder  */ -EREMOTEIO,
+	/* (for hw)   */ -EIO,
+	/* (for hw)   */ -EIO,
+	/* BufferOver */ -ECOMM,
+	/* BuffUnder  */ -ENOSR,
+	/* (for HCD)  */ -ENOSPC,
+	/* (for HCD)  */ -EALREADY
+};
+
+/* HCD data associated with a usb core URB */
+struct urb_priv {
+	struct urb *urb;
+	struct usb_host_endpoint *ep;
+	int active;
+	int state;
+	struct td *isoc_td;
+	int isoc_remaining;
+	int isoc_status;
+};
+
+/* HCD data associated with a usb core endpoint */
+struct ep_priv {
+	struct usb_host_endpoint *ep;
+	struct list_head td_list;
+	struct list_head queue;
+	int etd[NUM_ISO_ETDS];
+	int waiting_etd;
+};
+
+/* isoc packet */
+struct td {
+	struct list_head list;
+	struct urb *urb;
+	struct usb_host_endpoint *ep;
+	dma_addr_t data;
+	unsigned long buf_addr;
+	int len;
+	int frame;
+	int isoc_index;
+};
+
+/* HCD data associated with a hardware ETD */
+struct etd_priv {
+	struct usb_host_endpoint *ep;
+	struct urb *urb;
+	struct td *td;
+	struct list_head queue;
+	dma_addr_t dma_handle;
+	int alloc;
+	int len;
+	int dmem_size;
+	int dmem_offset;
+	int active_count;
+#ifdef DEBUG
+	int activated_frame;
+	int disactivated_frame;
+	int last_int_frame;
+	int last_req_frame;
+	u32 submitted_dwords[4];
+#endif
+};
+
+/* Hardware data memory info */
+struct imx21_dmem_area {
+	struct usb_host_endpoint *ep;
+	unsigned int offset;
+	unsigned int size;
+	struct list_head list;
+};
+
+#ifdef DEBUG
+struct debug_usage_stats {
+	unsigned int value;
+	unsigned int maximum;
+};
+
+struct debug_stats {
+	unsigned long submitted;
+	unsigned long completed_ok;
+	unsigned long completed_failed;
+	unsigned long unlinked;
+	unsigned long queue_etd;
+	unsigned long queue_dmem;
+};
+
+struct debug_isoc_trace {
+	int schedule_frame;
+	int submit_frame;
+	int request_len;
+	int done_frame;
+	int done_len;
+	int cc;
+	struct td *td;
+};
+#endif
+
+/* HCD data structure */
+struct imx21 {
+	spinlock_t lock;
+	struct device *dev;
+	struct mx21_usbh_platform_data *pdata;
+	struct list_head dmem_list;
+	struct list_head queue_for_etd; /* eps queued due to etd shortage */
+	struct list_head queue_for_dmem; /* etds queued due to dmem shortage */
+	struct etd_priv etd[USB_NUM_ETD];
+	struct clk *clk;
+	void __iomem *regs;
+#ifdef DEBUG
+	struct dentry *debug_root;
+	struct debug_stats nonisoc_stats;
+	struct debug_stats isoc_stats;
+	struct debug_usage_stats etd_usage;
+	struct debug_usage_stats dmem_usage;
+	struct debug_isoc_trace isoc_trace[20];
+	struct debug_isoc_trace isoc_trace_failed[20];
+	unsigned long debug_unblocks;
+	int isoc_trace_index;
+	int isoc_trace_index_failed;
+#endif
+};
+
+#endif
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 4297165..217fb51 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -1257,7 +1257,7 @@
 
 	/* avoid all allocations within spinlocks: request or endpoint */
 	if (!hep->hcpriv) {
-		ep = kcalloc(1, sizeof *ep, mem_flags);
+		ep = kzalloc(sizeof *ep, mem_flags);
 		if (!ep)
 			return -ENOMEM;
 	}
@@ -2719,24 +2719,11 @@
 	}
 	irq = irq_res->start;
 
-#ifdef CONFIG_USB_HCD_DMA
-	if (pdev->dev.dma_mask) {
-		struct resource *dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-
-		if (!dma_res) {
-			retval = -ENODEV;
-			goto err1;
-		}
-		isp1362_hcd->data_dma = dma_res->start;
-		isp1362_hcd->max_dma_size = resource_len(dma_res);
-	}
-#else
 	if (pdev->dev.dma_mask) {
 		DBG(1, "won't do DMA");
 		retval = -ENODEV;
 		goto err1;
 	}
-#endif
 
 	if (!request_mem_region(addr->start, resource_len(addr), hcd_name)) {
 		retval = -EBUSY;
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index 27b8f7c..9f01293 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -17,7 +17,9 @@
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
+#include <linux/mm.h>
 #include <asm/unaligned.h>
+#include <asm/cacheflush.h>
 
 #include "../core/hcd.h"
 #include "isp1760-hcd.h"
@@ -904,6 +906,14 @@
 			status = 0;
 	}
 
+	if (usb_pipein(urb->pipe) && usb_pipetype(urb->pipe) != PIPE_CONTROL) {
+		void *ptr;
+		for (ptr = urb->transfer_buffer;
+		     ptr < urb->transfer_buffer + urb->transfer_buffer_length;
+		     ptr += PAGE_SIZE)
+			flush_dcache_page(virt_to_page(ptr));
+	}
+
 	/* complete() can reenter this HCD */
 	usb_hcd_unlink_urb_from_ep(priv_to_hcd(priv), urb);
 	spin_unlock(&priv->lock);
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index 1c9f977..4293cfd 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -109,7 +109,7 @@
 	return 0;
 }
 
-static struct of_device_id of_isp1760_match[] = {
+static const struct of_device_id of_isp1760_match[] = {
 	{
 		.compatible = "nxp,usb-isp1760",
 	},
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
new file mode 100644
index 0000000..4aa08d3
--- /dev/null
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -0,0 +1,456 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * TI DA8xx (OMAP-L1x) Bus Glue
+ *
+ * Derived from: ohci-omap.c and ohci-s3c2410.c
+ * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.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/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <mach/da8xx.h>
+#include <mach/usb.h>
+
+#ifndef CONFIG_ARCH_DAVINCI_DA8XX
+#error "This file is DA8xx bus glue.  Define CONFIG_ARCH_DAVINCI_DA8XX."
+#endif
+
+#define CFGCHIP2	DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP2_REG)
+
+static struct clk *usb11_clk;
+static struct clk *usb20_clk;
+
+/* Over-current indicator change bitmask */
+static volatile u16 ocic_mask;
+
+static void ohci_da8xx_clock(int on)
+{
+	u32 cfgchip2;
+
+	cfgchip2 = __raw_readl(CFGCHIP2);
+	if (on) {
+		clk_enable(usb11_clk);
+
+		/*
+		 * If USB 1.1 reference clock is sourced from USB 2.0 PHY, we
+		 * need to enable the USB 2.0 module clocking, start its PHY,
+		 * and not allow it to stop the clock during USB 2.0 suspend.
+		 */
+		if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX)) {
+			clk_enable(usb20_clk);
+
+			cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
+			cfgchip2 |= CFGCHIP2_PHY_PLLON;
+			__raw_writel(cfgchip2, CFGCHIP2);
+
+			pr_info("Waiting for USB PHY clock good...\n");
+			while (!(__raw_readl(CFGCHIP2) & CFGCHIP2_PHYCLKGD))
+				cpu_relax();
+		}
+
+		/* Enable USB 1.1 PHY */
+		cfgchip2 |= CFGCHIP2_USB1SUSPENDM;
+	} else {
+		clk_disable(usb11_clk);
+		if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX))
+			clk_disable(usb20_clk);
+
+		/* Disable USB 1.1 PHY */
+		cfgchip2 &= ~CFGCHIP2_USB1SUSPENDM;
+	}
+	__raw_writel(cfgchip2, CFGCHIP2);
+}
+
+/*
+ * Handle the port over-current indicator change.
+ */
+static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub,
+				    unsigned port)
+{
+	ocic_mask |= 1 << port;
+
+	/* Once over-current is detected, the port needs to be powered down */
+	if (hub->get_oci(port) > 0)
+		hub->set_power(port, 0);
+}
+
+static int ohci_da8xx_init(struct usb_hcd *hcd)
+{
+	struct device *dev		= hcd->self.controller;
+	struct da8xx_ohci_root_hub *hub	= dev->platform_data;
+	struct ohci_hcd	*ohci		= hcd_to_ohci(hcd);
+	int result;
+	u32 rh_a;
+
+	dev_dbg(dev, "starting USB controller\n");
+
+	ohci_da8xx_clock(1);
+
+	/*
+	 * DA8xx only have 1 port connected to the pins but the HC root hub
+	 * register A reports 2 ports, thus we'll have to override it...
+	 */
+	ohci->num_ports = 1;
+
+	result = ohci_init(ohci);
+	if (result < 0)
+		return result;
+
+	/*
+	 * Since we're providing a board-specific root hub port power control
+	 * and over-current reporting, we have to override the HC root hub A
+	 * register's default value, so that ohci_hub_control() could return
+	 * the correct hub descriptor...
+	 */
+	rh_a = ohci_readl(ohci, &ohci->regs->roothub.a);
+	if (hub->set_power) {
+		rh_a &= ~RH_A_NPS;
+		rh_a |=  RH_A_PSM;
+	}
+	if (hub->get_oci) {
+		rh_a &= ~RH_A_NOCP;
+		rh_a |=  RH_A_OCPM;
+	}
+	rh_a &= ~RH_A_POTPGT;
+	rh_a |= hub->potpgt << 24;
+	ohci_writel(ohci, rh_a, &ohci->regs->roothub.a);
+
+	return result;
+}
+
+static void ohci_da8xx_stop(struct usb_hcd *hcd)
+{
+	ohci_stop(hcd);
+	ohci_da8xx_clock(0);
+}
+
+static int ohci_da8xx_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci		= hcd_to_ohci(hcd);
+	int result;
+
+	result = ohci_run(ohci);
+	if (result < 0)
+		ohci_da8xx_stop(hcd);
+
+	return result;
+}
+
+/*
+ * Update the status data from the hub with the over-current indicator change.
+ */
+static int ohci_da8xx_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+	int length		= ohci_hub_status_data(hcd, buf);
+
+	/* See if we have OCIC bit set on port 1 */
+	if (ocic_mask & (1 << 1)) {
+		dev_dbg(hcd->self.controller, "over-current indicator change "
+			"on port 1\n");
+
+		if (!length)
+			length = 1;
+
+		buf[0] |= 1 << 1;
+	}
+	return length;
+}
+
+/*
+ * Look at the control requests to the root hub and see if we need to override.
+ */
+static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+				  u16 wIndex, char *buf, u16 wLength)
+{
+	struct device *dev		= hcd->self.controller;
+	struct da8xx_ohci_root_hub *hub	= dev->platform_data;
+	int temp;
+
+	switch (typeReq) {
+	case GetPortStatus:
+		/* Check the port number */
+		if (wIndex != 1)
+			break;
+
+		dev_dbg(dev, "GetPortStatus(%u)\n", wIndex);
+
+		temp = roothub_portstatus(hcd_to_ohci(hcd), wIndex - 1);
+
+		/* The port power status (PPS) bit defaults to 1 */
+		if (hub->get_power && hub->get_power(wIndex) == 0)
+			temp &= ~RH_PS_PPS;
+
+		/* The port over-current indicator (POCI) bit is always 0 */
+		if (hub->get_oci && hub->get_oci(wIndex) > 0)
+			temp |=  RH_PS_POCI;
+
+		/* The over-current indicator change (OCIC) bit is 0 too */
+		if (ocic_mask & (1 << wIndex))
+			temp |=  RH_PS_OCIC;
+
+		put_unaligned(cpu_to_le32(temp), (__le32 *)buf);
+		return 0;
+	case SetPortFeature:
+		temp = 1;
+		goto check_port;
+	case ClearPortFeature:
+		temp = 0;
+
+check_port:
+		/* Check the port number */
+		if (wIndex != 1)
+			break;
+
+		switch (wValue) {
+		case USB_PORT_FEAT_POWER:
+			dev_dbg(dev, "%sPortFeature(%u): %s\n",
+				temp ? "Set" : "Clear", wIndex, "POWER");
+
+			if (!hub->set_power)
+				return -EPIPE;
+
+			return hub->set_power(wIndex, temp) ? -EPIPE : 0;
+		case USB_PORT_FEAT_C_OVER_CURRENT:
+			dev_dbg(dev, "%sPortFeature(%u): %s\n",
+				temp ? "Set" : "Clear", wIndex,
+				"C_OVER_CURRENT");
+
+			if (temp)
+				ocic_mask |= 1 << wIndex;
+			else
+				ocic_mask &= ~(1 << wIndex);
+			return 0;
+		}
+	}
+
+	return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+}
+
+static const struct hc_driver ohci_da8xx_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "DA8xx OHCI",
+	.hcd_priv_size		= sizeof(struct ohci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= ohci_irq,
+	.flags			= HCD_USB11 | HCD_MEMORY,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset			= ohci_da8xx_init,
+	.start			= ohci_da8xx_start,
+	.stop			= ohci_da8xx_stop,
+	.shutdown		= ohci_shutdown,
+
+	/*
+	 * 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_da8xx_hub_status_data,
+	.hub_control		= ohci_da8xx_hub_control,
+
+#ifdef	CONFIG_PM
+	.bus_suspend		= ohci_bus_suspend,
+	.bus_resume		= ohci_bus_resume,
+#endif
+	.start_port_reset	= ohci_start_port_reset,
+};
+
+/*-------------------------------------------------------------------------*/
+
+
+/**
+ * usb_hcd_da8xx_probe - initialize DA8xx-based HCDs
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ */
+static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
+			       struct platform_device *pdev)
+{
+	struct da8xx_ohci_root_hub *hub	= pdev->dev.platform_data;
+	struct usb_hcd	*hcd;
+	struct resource *mem;
+	int error, irq;
+
+	if (hub == NULL)
+		return -ENODEV;
+
+	usb11_clk = clk_get(&pdev->dev, "usb11");
+	if (IS_ERR(usb11_clk))
+		return PTR_ERR(usb11_clk);
+
+	usb20_clk = clk_get(&pdev->dev, "usb20");
+	if (IS_ERR(usb20_clk)) {
+		error = PTR_ERR(usb20_clk);
+		goto err0;
+	}
+
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		error = -ENOMEM;
+		goto err1;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		error = -ENODEV;
+		goto err2;
+	}
+	hcd->rsrc_start = mem->start;
+	hcd->rsrc_len = mem->end - mem->start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		error = -EBUSY;
+		goto err2;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		error = -ENOMEM;
+		goto err3;
+	}
+
+	ohci_hcd_init(hcd_to_ohci(hcd));
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		error = -ENODEV;
+		goto err4;
+	}
+	error = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+	if (error)
+		goto err4;
+
+	if (hub->ocic_notify) {
+		error = hub->ocic_notify(ohci_da8xx_ocic_handler);
+		if (!error)
+			return 0;
+	}
+
+	usb_remove_hcd(hcd);
+err4:
+	iounmap(hcd->regs);
+err3:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err2:
+	usb_put_hcd(hcd);
+err1:
+	clk_put(usb20_clk);
+err0:
+	clk_put(usb11_clk);
+	return error;
+}
+
+/**
+ * usb_hcd_da8xx_remove - shutdown processing for DA8xx-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_da8xx_probe(), first invoking
+ * the HCD's stop() method.  It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ */
+static inline void
+usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev)
+{
+	struct da8xx_ohci_root_hub *hub	= pdev->dev.platform_data;
+
+	hub->ocic_notify(NULL);
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	clk_put(usb20_clk);
+	clk_put(usb11_clk);
+}
+
+static int ohci_hcd_da8xx_drv_probe(struct platform_device *dev)
+{
+	return usb_hcd_da8xx_probe(&ohci_da8xx_hc_driver, dev);
+}
+
+static int ohci_hcd_da8xx_drv_remove(struct platform_device *dev)
+{
+	struct usb_hcd	*hcd = platform_get_drvdata(dev);
+
+	usb_hcd_da8xx_remove(hcd, dev);
+	platform_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ohci_da8xx_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);
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	ohci_da8xx_clock(0);
+	hcd->state = HC_STATE_SUSPENDED;
+	dev->dev.power.power_state = PMSG_SUSPEND;
+	return 0;
+}
+
+static int ohci_da8xx_resume(struct platform_device *dev)
+{
+	struct usb_hcd	*hcd	= platform_get_drvdata(dev);
+	struct ohci_hcd	*ohci	= hcd_to_ohci(hcd);
+
+	if (time_before(jiffies, ohci->next_statechange))
+		msleep(5);
+	ohci->next_statechange = jiffies;
+
+	ohci_da8xx_clock(1);
+	dev->dev.power.power_state = PMSG_ON;
+	usb_hcd_resume_root_hub(hcd);
+	return 0;
+}
+#endif
+
+/*
+ * Driver definition to register with platform structure.
+ */
+static struct platform_driver ohci_hcd_da8xx_driver = {
+	.probe		= ohci_hcd_da8xx_drv_probe,
+	.remove		= ohci_hcd_da8xx_drv_remove,
+	.shutdown 	= usb_hcd_platform_shutdown,
+#ifdef	CONFIG_PM
+	.suspend	= ohci_da8xx_suspend,
+	.resume		= ohci_da8xx_resume,
+#endif
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ohci",
+	},
+};
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 811f5dfd..8ad2441 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -53,13 +53,13 @@
 		int i, len;
 
 		if (usb_pipecontrol (pipe)) {
-			printk (KERN_DEBUG __FILE__ ": setup(8):");
+			printk (KERN_DEBUG "%s: setup(8):", __FILE__);
 			for (i = 0; i < 8 ; i++)
 				printk (" %02x", ((__u8 *) urb->setup_packet) [i]);
 			printk ("\n");
 		}
 		if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) {
-			printk (KERN_DEBUG __FILE__ ": data(%d/%d):",
+			printk (KERN_DEBUG "%s: data(%d/%d):", __FILE__,
 				urb->actual_length,
 				urb->transfer_buffer_length);
 			len = usb_pipeout (pipe)?
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 24eb747..afe59be 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1051,6 +1051,11 @@
 #define PLATFORM_DRIVER		usb_hcd_pnx4008_driver
 #endif
 
+#ifdef CONFIG_ARCH_DAVINCI_DA8XX
+#include "ohci-da8xx.c"
+#define PLATFORM_DRIVER		ohci_hcd_da8xx_driver
+#endif
+
 #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
     defined(CONFIG_CPU_SUBTYPE_SH7721) || \
     defined(CONFIG_CPU_SUBTYPE_SH7763) || \
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index de42283..18d39f0 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -28,8 +28,8 @@
 
 static void lh7a404_start_hc(struct platform_device *dev)
 {
-	printk(KERN_DEBUG __FILE__
-	       ": starting LH7A404 OHCI USB Controller\n");
+	printk(KERN_DEBUG "%s: starting LH7A404 OHCI USB Controller\n",
+	       __FILE__);
 
 	/*
 	 * Now, carefully enable the USB clock, and take
@@ -39,14 +39,13 @@
 	udelay(1000);
 	USBH_CMDSTATUS = OHCI_HCR;
 
-	printk(KERN_DEBUG __FILE__
-		   ": Clock to USB host has been enabled \n");
+	printk(KERN_DEBUG "%s: Clock to USB host has been enabled \n", __FILE__);
 }
 
 static void lh7a404_stop_hc(struct platform_device *dev)
 {
-	printk(KERN_DEBUG __FILE__
-	       ": stopping LH7A404 OHCI USB Controller\n");
+	printk(KERN_DEBUG "%s: stopping LH7A404 OHCI USB Controller\n",
+	       __FILE__);
 
 	CSC_PWRCNT &= ~CSC_PWRCNT_USBH_EN; /* Disable clock */
 }
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 2769326..cd74bbd 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -327,7 +327,7 @@
 	}
 	i2c_adap = i2c_get_adapter(2);
 	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
-	strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
+	strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
 	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
 						   normal_i2c);
 	i2c_put_adapter(i2c_adap);
@@ -411,7 +411,7 @@
 out2:
 	clk_put(usb_clk);
 out1:
-	i2c_unregister_client(isp1301_i2c_client);
+	i2c_unregister_device(isp1301_i2c_client);
 	isp1301_i2c_client = NULL;
 out_i2c_driver:
 	i2c_del_driver(&isp1301_driver);
@@ -430,7 +430,7 @@
 	pnx4008_unset_usb_bits();
 	clk_disable(usb_clk);
 	clk_put(usb_clk);
-	i2c_unregister_client(isp1301_i2c_client);
+	i2c_unregister_device(isp1301_i2c_client);
 	isp1301_i2c_client = NULL;
 	i2c_del_driver(&isp1301_driver);
 
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index 68a3017..103263c 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -114,21 +114,21 @@
 	hcd->rsrc_len = res.end - res.start + 1;
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		printk(KERN_ERR __FILE__ ": request_mem_region failed\n");
+		printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
 		rv = -EBUSY;
 		goto err_rmr;
 	}
 
 	irq = irq_of_parse_and_map(dn, 0);
 	if (irq == NO_IRQ) {
-		printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
+		printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
 		rv = -EBUSY;
 		goto err_irq;
 	}
 
 	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
 	if (!hcd->regs) {
-		printk(KERN_ERR __FILE__ ": ioremap failed\n");
+		printk(KERN_ERR "%s: ioremap failed\n", __FILE__);
 		rv = -ENOMEM;
 		goto err_ioremap;
 	}
@@ -169,7 +169,7 @@
 			} else
 				release_mem_region(res.start, 0x4);
 		} else
-		    pr_debug(__FILE__ ": cannot get ehci offset from fdt\n");
+			pr_debug("%s: cannot get ehci offset from fdt\n", __FILE__);
 	}
 
 	iounmap(hcd->regs);
@@ -212,7 +212,7 @@
 }
 
 
-static struct of_device_id ohci_hcd_ppc_of_match[] = {
+static const struct of_device_id ohci_hcd_ppc_of_match[] = {
 #ifdef CONFIG_USB_OHCI_HCD_PPC_OF_BE
 	{
 		.name = "usb",
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index cd3398b..89e670e 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -41,14 +41,14 @@
 
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
-		pr_debug(__FILE__ ": no irq\n");
+		pr_debug("%s: no irq\n", __FILE__);
 		return -ENODEV;
 	}
 	irq = res->start;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
-		pr_debug(__FILE__ ": no reg addr\n");
+		pr_debug("%s: no reg addr\n", __FILE__);
 		return -ENODEV;
 	}
 
@@ -59,14 +59,14 @@
 	hcd->rsrc_len = res->end - res->start + 1;
 
 	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		pr_debug(__FILE__ ": request_mem_region failed\n");
+		pr_debug("%s: request_mem_region failed\n", __FILE__);
 		retval = -EBUSY;
 		goto err1;
 	}
 
 	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
 	if (!hcd->regs) {
-		pr_debug(__FILE__ ": ioremap failed\n");
+		pr_debug("%s: ioremap failed\n", __FILE__);
 		retval = -ENOMEM;
 		goto err2;
 	}
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index e4bbe8e..d8eb3bd 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -31,8 +31,8 @@
 {
 	unsigned int usb_rst = 0;
 
-	printk(KERN_DEBUG __FILE__
-	       ": starting SA-1111 OHCI USB Controller\n");
+	printk(KERN_DEBUG "%s: starting SA-1111 OHCI USB Controller\n",
+	       __FILE__);
 
 #ifdef CONFIG_SA1100_BADGE4
 	if (machine_is_badge4()) {
@@ -65,8 +65,8 @@
 static void sa1111_stop_hc(struct sa1111_dev *dev)
 {
 	unsigned int usb_rst;
-	printk(KERN_DEBUG __FILE__
-	       ": stopping SA-1111 OHCI USB Controller\n");
+	printk(KERN_DEBUG "%s: stopping SA-1111 OHCI USB Controller\n",
+	       __FILE__);
 
 	/*
 	 * Put the USB host controller into reset.
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 5b22a4d..e11cc3a 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -51,6 +51,7 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/byteorder.h>
+#include <asm/unaligned.h>
 
 #include "../core/hcd.h"
 #include "sl811.h"
@@ -1272,12 +1273,12 @@
 		sl811h_hub_descriptor(sl811, (struct usb_hub_descriptor *) buf);
 		break;
 	case GetHubStatus:
-		*(__le32 *) buf = cpu_to_le32(0);
+		put_unaligned_le32(0, buf);
 		break;
 	case GetPortStatus:
 		if (wIndex != 1)
 			goto error;
-		*(__le32 *) buf = cpu_to_le32(sl811->port1);
+		put_unaligned_le32(sl811->port1, buf);
 
 #ifndef	VERBOSE
 	if (*(u16*)(buf+2))	/* only if wPortChange is interesting */
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 99cd00f..0919706 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -735,6 +735,7 @@
 		uhci_hc_died(uhci);
 	uhci_scan_schedule(uhci);
 	spin_unlock_irq(&uhci->lock);
+	synchronize_irq(hcd->irq);
 
 	del_timer_sync(&uhci->fsbr_timer);
 	release_uhci(uhci);
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 33128d5..105fa8b 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -406,6 +406,25 @@
 	}
 }
 
+char *xhci_get_slot_state(struct xhci_hcd *xhci,
+		struct xhci_container_ctx *ctx)
+{
+	struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
+
+	switch (GET_SLOT_STATE(slot_ctx->dev_state)) {
+	case 0:
+		return "enabled/disabled";
+	case 1:
+		return "default";
+	case 2:
+		return "addressed";
+	case 3:
+		return "configured";
+	default:
+		return "reserved";
+	}
+}
+
 void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx)
 {
 	/* Fields are 32 bits wide, DMA addresses are in bytes */
diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h
index ecc131c..78c4eda 100644
--- a/drivers/usb/host/xhci-ext-caps.h
+++ b/drivers/usb/host/xhci-ext-caps.h
@@ -101,12 +101,15 @@
 
 	next = readl(base + ext_offset);
 
-	if (ext_offset == XHCI_HCC_PARAMS_OFFSET)
+	if (ext_offset == XHCI_HCC_PARAMS_OFFSET) {
 		/* Find the first extended capability */
 		next = XHCI_HCC_EXT_CAPS(next);
-	else
+		ext_offset = 0;
+	} else {
 		/* Find the next extended capability */
 		next = XHCI_EXT_CAPS_NEXT(next);
+	}
+
 	if (!next)
 		return 0;
 	/*
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c
index 5e92c72..4cb69e0 100644
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -1007,7 +1007,7 @@
 	 * for usb_set_interface() and usb_set_configuration() claim).
 	 */
 	if (xhci_endpoint_init(xhci, xhci->devs[udev->slot_id],
-				udev, ep, GFP_KERNEL) < 0) {
+				udev, ep, GFP_NOIO) < 0) {
 		dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n",
 				__func__, ep->desc.bEndpointAddress);
 		return -ENOMEM;
@@ -1181,6 +1181,8 @@
 		ret = xhci_queue_evaluate_context(xhci, in_ctx->dma,
 				udev->slot_id);
 	if (ret < 0) {
+		if (command)
+			list_del(&command->cmd_list);
 		spin_unlock_irqrestore(&xhci->lock, flags);
 		xhci_dbg(xhci, "FIXME allocate a new ring segment\n");
 		return -ENOMEM;
@@ -1264,30 +1266,13 @@
 	xhci_zero_in_ctx(xhci, virt_dev);
 	/* Install new rings and free or cache any old rings */
 	for (i = 1; i < 31; ++i) {
-		int rings_cached;
-
 		if (!virt_dev->eps[i].new_ring)
 			continue;
 		/* Only cache or free the old ring if it exists.
 		 * It may not if this is the first add of an endpoint.
 		 */
 		if (virt_dev->eps[i].ring) {
-			rings_cached = virt_dev->num_rings_cached;
-			if (rings_cached < XHCI_MAX_RINGS_CACHED) {
-				virt_dev->num_rings_cached++;
-				rings_cached = virt_dev->num_rings_cached;
-				virt_dev->ring_cache[rings_cached] =
-					virt_dev->eps[i].ring;
-				xhci_dbg(xhci, "Cached old ring, "
-						"%d ring%s cached\n",
-						rings_cached,
-						(rings_cached > 1) ? "s" : "");
-			} else {
-				xhci_ring_free(xhci, virt_dev->eps[i].ring);
-				xhci_dbg(xhci, "Ring cache full (%d rings), "
-						"freeing ring\n",
-						virt_dev->num_rings_cached);
-			}
+			xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
 		}
 		virt_dev->eps[i].ring = virt_dev->eps[i].new_ring;
 		virt_dev->eps[i].new_ring = NULL;
@@ -1458,6 +1443,131 @@
 }
 
 /*
+ * This submits a Reset Device Command, which will set the device state to 0,
+ * set the device address to 0, and disable all the endpoints except the default
+ * control endpoint.  The USB core should come back and call
+ * xhci_address_device(), and then re-set up the configuration.  If this is
+ * called because of a usb_reset_and_verify_device(), then the old alternate
+ * settings will be re-installed through the normal bandwidth allocation
+ * functions.
+ *
+ * Wait for the Reset Device command to finish.  Remove all structures
+ * associated with the endpoints that were disabled.  Clear the input device
+ * structure?  Cache the rings?  Reset the control endpoint 0 max packet size?
+ */
+int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
+{
+	int ret, i;
+	unsigned long flags;
+	struct xhci_hcd *xhci;
+	unsigned int slot_id;
+	struct xhci_virt_device *virt_dev;
+	struct xhci_command *reset_device_cmd;
+	int timeleft;
+	int last_freed_endpoint;
+
+	ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+	if (ret <= 0)
+		return ret;
+	xhci = hcd_to_xhci(hcd);
+	slot_id = udev->slot_id;
+	virt_dev = xhci->devs[slot_id];
+	if (!virt_dev) {
+		xhci_dbg(xhci, "%s called with invalid slot ID %u\n",
+				__func__, slot_id);
+		return -EINVAL;
+	}
+
+	xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
+	/* Allocate the command structure that holds the struct completion.
+	 * Assume we're in process context, since the normal device reset
+	 * process has to wait for the device anyway.  Storage devices are
+	 * reset as part of error handling, so use GFP_NOIO instead of
+	 * GFP_KERNEL.
+	 */
+	reset_device_cmd = xhci_alloc_command(xhci, false, true, GFP_NOIO);
+	if (!reset_device_cmd) {
+		xhci_dbg(xhci, "Couldn't allocate command structure.\n");
+		return -ENOMEM;
+	}
+
+	/* Attempt to submit the Reset Device command to the command ring */
+	spin_lock_irqsave(&xhci->lock, flags);
+	reset_device_cmd->command_trb = xhci->cmd_ring->enqueue;
+	list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
+	ret = xhci_queue_reset_device(xhci, slot_id);
+	if (ret) {
+		xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
+		list_del(&reset_device_cmd->cmd_list);
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		goto command_cleanup;
+	}
+	xhci_ring_cmd_db(xhci);
+	spin_unlock_irqrestore(&xhci->lock, flags);
+
+	/* Wait for the Reset Device command to finish */
+	timeleft = wait_for_completion_interruptible_timeout(
+			reset_device_cmd->completion,
+			USB_CTRL_SET_TIMEOUT);
+	if (timeleft <= 0) {
+		xhci_warn(xhci, "%s while waiting for reset device command\n",
+				timeleft == 0 ? "Timeout" : "Signal");
+		spin_lock_irqsave(&xhci->lock, flags);
+		/* The timeout might have raced with the event ring handler, so
+		 * only delete from the list if the item isn't poisoned.
+		 */
+		if (reset_device_cmd->cmd_list.next != LIST_POISON1)
+			list_del(&reset_device_cmd->cmd_list);
+		spin_unlock_irqrestore(&xhci->lock, flags);
+		ret = -ETIME;
+		goto command_cleanup;
+	}
+
+	/* The Reset Device command can't fail, according to the 0.95/0.96 spec,
+	 * unless we tried to reset a slot ID that wasn't enabled,
+	 * or the device wasn't in the addressed or configured state.
+	 */
+	ret = reset_device_cmd->status;
+	switch (ret) {
+	case COMP_EBADSLT: /* 0.95 completion code for bad slot ID */
+	case COMP_CTX_STATE: /* 0.96 completion code for same thing */
+		xhci_info(xhci, "Can't reset device (slot ID %u) in %s state\n",
+				slot_id,
+				xhci_get_slot_state(xhci, virt_dev->out_ctx));
+		xhci_info(xhci, "Not freeing device rings.\n");
+		/* Don't treat this as an error.  May change my mind later. */
+		ret = 0;
+		goto command_cleanup;
+	case COMP_SUCCESS:
+		xhci_dbg(xhci, "Successful reset device command.\n");
+		break;
+	default:
+		if (xhci_is_vendor_info_code(xhci, ret))
+			break;
+		xhci_warn(xhci, "Unknown completion code %u for "
+				"reset device command.\n", ret);
+		ret = -EINVAL;
+		goto command_cleanup;
+	}
+
+	/* Everything but endpoint 0 is disabled, so free or cache the rings. */
+	last_freed_endpoint = 1;
+	for (i = 1; i < 31; ++i) {
+		if (!virt_dev->eps[i].ring)
+			continue;
+		xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
+		last_freed_endpoint = i;
+	}
+	xhci_dbg(xhci, "Output context after successful reset device cmd:\n");
+	xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint);
+	ret = 0;
+
+command_cleanup:
+	xhci_free_command(xhci, reset_device_cmd);
+	return ret;
+}
+
+/*
  * At this point, the struct usb_device is about to go away, the device has
  * disconnected, and all traffic has been stopped and the endpoints have been
  * disabled.  Free any HC data structures associated with that device.
@@ -1694,7 +1804,7 @@
 		xhci_warn(xhci, "Cannot update hub desc for unknown device.\n");
 		return -EINVAL;
 	}
-	config_cmd = xhci_alloc_command(xhci, true, mem_flags);
+	config_cmd = xhci_alloc_command(xhci, true, true, mem_flags);
 	if (!config_cmd) {
 		xhci_dbg(xhci, "Could not allocate xHCI command structure.\n");
 		return -ENOMEM;
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index eac5b53..208b805 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -129,6 +129,50 @@
 	return (state & XHCI_PORT_RO) | (state & XHCI_PORT_RWS);
 }
 
+static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
+		u32 __iomem *addr, u32 port_status)
+{
+	/* Write 1 to disable the port */
+	xhci_writel(xhci, port_status | PORT_PE, addr);
+	port_status = xhci_readl(xhci, addr);
+	xhci_dbg(xhci, "disable port, actual port %d status  = 0x%x\n",
+			wIndex, port_status);
+}
+
+static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
+		u16 wIndex, u32 __iomem *addr, u32 port_status)
+{
+	char *port_change_bit;
+	u32 status;
+
+	switch (wValue) {
+	case USB_PORT_FEAT_C_RESET:
+		status = PORT_RC;
+		port_change_bit = "reset";
+		break;
+	case USB_PORT_FEAT_C_CONNECTION:
+		status = PORT_CSC;
+		port_change_bit = "connect";
+		break;
+	case USB_PORT_FEAT_C_OVER_CURRENT:
+		status = PORT_OCC;
+		port_change_bit = "over-current";
+		break;
+	case USB_PORT_FEAT_C_ENABLE:
+		status = PORT_PEC;
+		port_change_bit = "enable/disable";
+		break;
+	default:
+		/* Should never happen */
+		return;
+	}
+	/* Change bits are all write 1 to clear */
+	xhci_writel(xhci, port_status | status, addr);
+	port_status = xhci_readl(xhci, addr);
+	xhci_dbg(xhci, "clear port %s change, actual port %d status  = 0x%x\n",
+			port_change_bit, wIndex, port_status);
+}
+
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		u16 wIndex, char *buf, u16 wLength)
 {
@@ -138,7 +182,6 @@
 	u32 temp, status;
 	int retval = 0;
 	u32 __iomem *addr;
-	char *port_change_bit;
 
 	ports = HCS_MAX_PORTS(xhci->hcs_params1);
 
@@ -229,26 +272,18 @@
 		temp = xhci_port_state_to_neutral(temp);
 		switch (wValue) {
 		case USB_PORT_FEAT_C_RESET:
-			status = PORT_RC;
-			port_change_bit = "reset";
-			break;
 		case USB_PORT_FEAT_C_CONNECTION:
-			status = PORT_CSC;
-			port_change_bit = "connect";
-			break;
 		case USB_PORT_FEAT_C_OVER_CURRENT:
-			status = PORT_OCC;
-			port_change_bit = "over-current";
+		case USB_PORT_FEAT_C_ENABLE:
+			xhci_clear_port_change_bit(xhci, wValue, wIndex,
+					addr, temp);
+			break;
+		case USB_PORT_FEAT_ENABLE:
+			xhci_disable_port(xhci, wIndex, addr, temp);
 			break;
 		default:
 			goto error;
 		}
-		/* Change bits are all write 1 to clear */
-		xhci_writel(xhci, temp | status, addr);
-		temp = xhci_readl(xhci, addr);
-		xhci_dbg(xhci, "clear port %s change, actual port %d status  = 0x%x\n",
-				port_change_bit, wIndex, temp);
-		temp = xhci_readl(xhci, addr); /* unblock any posted writes */
 		break;
 	default:
 error:
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index bffcef7..49f7d72 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -198,6 +198,31 @@
 	return 0;
 }
 
+void xhci_free_or_cache_endpoint_ring(struct xhci_hcd *xhci,
+		struct xhci_virt_device *virt_dev,
+		unsigned int ep_index)
+{
+	int rings_cached;
+
+	rings_cached = virt_dev->num_rings_cached;
+	if (rings_cached < XHCI_MAX_RINGS_CACHED) {
+		virt_dev->num_rings_cached++;
+		rings_cached = virt_dev->num_rings_cached;
+		virt_dev->ring_cache[rings_cached] =
+			virt_dev->eps[ep_index].ring;
+		xhci_dbg(xhci, "Cached old ring, "
+				"%d ring%s cached\n",
+				rings_cached,
+				(rings_cached > 1) ? "s" : "");
+	} else {
+		xhci_ring_free(xhci, virt_dev->eps[ep_index].ring);
+		xhci_dbg(xhci, "Ring cache full (%d rings), "
+				"freeing ring\n",
+				virt_dev->num_rings_cached);
+	}
+	virt_dev->eps[ep_index].ring = NULL;
+}
+
 /* Zero an endpoint ring (except for link TRBs) and move the enqueue and dequeue
  * pointers to the beginning of the ring.
  */
@@ -242,6 +267,8 @@
 void xhci_free_container_ctx(struct xhci_hcd *xhci,
 			     struct xhci_container_ctx *ctx)
 {
+	if (!ctx)
+		return;
 	dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma);
 	kfree(ctx);
 }
@@ -427,7 +454,7 @@
 	case USB_SPEED_LOW:
 		slot_ctx->dev_info |= (u32) SLOT_SPEED_LS;
 		break;
-	case USB_SPEED_VARIABLE:
+	case USB_SPEED_WIRELESS:
 		xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
 		return -EINVAL;
 		break;
@@ -471,7 +498,7 @@
 	case USB_SPEED_LOW:
 		ep0_ctx->ep_info2 |= MAX_PACKET(8);
 		break;
-	case USB_SPEED_VARIABLE:
+	case USB_SPEED_WIRELESS:
 		xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
 		return -EINVAL;
 		break;
@@ -819,7 +846,8 @@
 }
 
 struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
-		bool allocate_completion, gfp_t mem_flags)
+		bool allocate_in_ctx, bool allocate_completion,
+		gfp_t mem_flags)
 {
 	struct xhci_command *command;
 
@@ -827,11 +855,14 @@
 	if (!command)
 		return NULL;
 
-	command->in_ctx =
-		xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, mem_flags);
-	if (!command->in_ctx) {
-		kfree(command);
-		return NULL;
+	if (allocate_in_ctx) {
+		command->in_ctx =
+			xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT,
+					mem_flags);
+		if (!command->in_ctx) {
+			kfree(command);
+			return NULL;
+		}
 	}
 
 	if (allocate_completion) {
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index e097008..417d37a 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -139,6 +139,7 @@
 	.reset_bandwidth =	xhci_reset_bandwidth,
 	.address_device =	xhci_address_device,
 	.update_hub_device =	xhci_update_hub_device,
+	.reset_device =		xhci_reset_device,
 
 	/*
 	 * scheduling support
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index ee7bc7e..6ba841b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -953,6 +953,17 @@
 	case TRB_TYPE(TRB_RESET_EP):
 		handle_reset_ep_completion(xhci, event, xhci->cmd_ring->dequeue);
 		break;
+	case TRB_TYPE(TRB_RESET_DEV):
+		xhci_dbg(xhci, "Completed reset device command.\n");
+		slot_id = TRB_TO_SLOT_ID(
+				xhci->cmd_ring->dequeue->generic.field[3]);
+		virt_dev = xhci->devs[slot_id];
+		if (virt_dev)
+			handle_cmd_in_cmd_wait_list(xhci, virt_dev, event);
+		else
+			xhci_warn(xhci, "Reset device command completion "
+					"for disabled slot %u\n", slot_id);
+		break;
 	default:
 		/* Skip over unknown commands on the event ring */
 		xhci->error_bitmask |= 1 << 6;
@@ -1080,6 +1091,20 @@
 	return 0;
 }
 
+int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code)
+{
+	if (trb_comp_code >= 224 && trb_comp_code <= 255) {
+		/* Vendor defined "informational" completion code,
+		 * treat as not-an-error.
+		 */
+		xhci_dbg(xhci, "Vendor defined info completion code %u\n",
+				trb_comp_code);
+		xhci_dbg(xhci, "Treating code as success.\n");
+		return 1;
+	}
+	return 0;
+}
+
 /*
  * If this function returns an error condition, it means it got a Transfer
  * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address.
@@ -1196,13 +1221,7 @@
 		status = -ENOSR;
 		break;
 	default:
-		if (trb_comp_code >= 224 && trb_comp_code <= 255) {
-			/* Vendor defined "informational" completion code,
-			 * treat as not-an-error.
-			 */
-			xhci_dbg(xhci, "Vendor defined info completion code %u\n",
-					trb_comp_code);
-			xhci_dbg(xhci, "Treating code as success.\n");
+		if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
 			status = 0;
 			break;
 		}
@@ -2181,6 +2200,14 @@
 			false);
 }
 
+/* Queue a reset device command TRB */
+int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id)
+{
+	return queue_command(xhci, 0, 0, 0,
+			TRB_TYPE(TRB_RESET_DEV) | SLOT_ID_FOR_TRB(slot_id),
+			false);
+}
+
 /* Queue a configure endpoint command TRB */
 int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
 		u32 slot_id, bool command_must_succeed)
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 8778135..e5eb09b 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1210,6 +1210,8 @@
 void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci);
 void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring);
 void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep);
+char *xhci_get_slot_state(struct xhci_hcd *xhci,
+		struct xhci_container_ctx *ctx);
 
 /* xHCI memory management */
 void xhci_mem_cleanup(struct xhci_hcd *xhci);
@@ -1233,8 +1235,12 @@
 		struct usb_device *udev, struct usb_host_endpoint *ep,
 		gfp_t mem_flags);
 void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring);
+void xhci_free_or_cache_endpoint_ring(struct xhci_hcd *xhci,
+		struct xhci_virt_device *virt_dev,
+		unsigned int ep_index);
 struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
-		bool allocate_completion, gfp_t mem_flags);
+		bool allocate_in_ctx, bool allocate_completion,
+		gfp_t mem_flags);
 void xhci_free_command(struct xhci_hcd *xhci,
 		struct xhci_command *command);
 
@@ -1264,6 +1270,7 @@
 int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
 int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
 void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
+int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev);
 int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 
@@ -1272,6 +1279,7 @@
 struct xhci_segment *trb_in_td(struct xhci_segment *start_seg,
 		union xhci_trb *start_trb, union xhci_trb *end_trb,
 		dma_addr_t suspect_dma);
+int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code);
 void xhci_ring_cmd_db(struct xhci_hcd *xhci);
 void *xhci_setup_one_noop(struct xhci_hcd *xhci);
 void xhci_handle_event(struct xhci_hcd *xhci);
@@ -1293,6 +1301,7 @@
 		u32 slot_id);
 int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
 		unsigned int ep_index);
+int xhci_queue_reset_device(struct xhci_hcd *xhci, u32 slot_id);
 void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 		unsigned int slot_id, unsigned int ep_index,
 		struct xhci_td *cur_td, struct xhci_dequeue_state *state);
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index eca355d..e192e8f 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -967,7 +967,7 @@
 
 
 
-static struct usb_device_id mdc800_table [] = {
+static const struct usb_device_id mdc800_table[] = {
 	{ USB_DEVICE(MDC800_VENDOR_ID, MDC800_PRODUCT_ID) },
 	{ }						/* Terminating entry */
 };
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 459a728..3a6bcd5 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -155,7 +155,7 @@
 			 const struct usb_device_id *id);
 static void mts_usb_disconnect(struct usb_interface *intf);
 
-static struct usb_device_id mts_usb_ids [];
+static const struct usb_device_id mts_usb_ids[];
 
 static struct usb_driver mts_usb_driver = {
 	.name =		"microtekX6",
@@ -656,7 +656,7 @@
 /* The entries of microtek_table must correspond, line-by-line to
    the entries of mts_supported_products[]. */
 
-static struct usb_device_id mts_usb_ids [] =
+static const struct usb_device_id mts_usb_ids[] =
 {
 	{ USB_DEVICE(0x4ce, 0x0300) },
 	{ USB_DEVICE(0x5da, 0x0094) },
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index abe3aa6..55660ea 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -87,17 +87,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called usblcd.
 
-config USB_BERRY_CHARGE
-	tristate "USB BlackBerry recharge support"
-	depends on USB
-	help
-	  Say Y here if you want to connect a BlackBerry device to your
-	  computer's USB port and have it automatically switch to "recharge"
-	  mode.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called berry_charge.
-
 config USB_LED
 	tristate "USB LED driver support"
 	depends on USB
@@ -242,17 +231,3 @@
 	  driver beforehand. Tools for doing so are available at
 	  http://bersace03.free.fr
 
-config USB_VST
-	tristate "USB VST driver"
-	depends on USB
-	help
-	  This driver is intended for Vernier Software Technologies
-	  bulk usb devices such as their Ocean-Optics spectrometers or
-	  Labquest.
-	  It is a bulk channel driver with configurable read and write
-	  timeouts.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called vstusb.
-
-
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 0826aab..717703e 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -5,7 +5,6 @@
 
 obj-$(CONFIG_USB_ADUTUX)	+= adutux.o
 obj-$(CONFIG_USB_APPLEDISPLAY)	+= appledisplay.o
-obj-$(CONFIG_USB_BERRY_CHARGE)	+= berry_charge.o
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
 obj-$(CONFIG_USB_CYTHERM)	+= cytherm.o
 obj-$(CONFIG_USB_EMI26)		+= emi26.o
@@ -23,7 +22,6 @@
 obj-$(CONFIG_USB_TRANCEVIBRATOR)	+= trancevibrator.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
 obj-$(CONFIG_USB_SEVSEG)	+= usbsevseg.o
-obj-$(CONFIG_USB_VST)		+= vstusb.o
 
 obj-$(CONFIG_USB_SISUSBVGA)	+= sisusbvga/
 
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 2035265..d240de0 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -38,7 +38,7 @@
 #define dbg(lvl, format, arg...) 					\
 do { 									\
 	if (debug >= lvl)						\
-		printk(KERN_DEBUG __FILE__ " : " format " \n", ## arg);	\
+		printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg);	\
 } while (0)
 
 
@@ -56,7 +56,7 @@
 #define ADU_PRODUCT_ID 0x0064
 
 /* table of devices that work with this driver */
-static struct usb_device_id device_table [] = {
+static const struct usb_device_id device_table[] = {
 	{ USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID) },		/* ADU100 */
 	{ USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+20) }, 	/* ADU120 */
 	{ USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+30) }, 	/* ADU130 */
@@ -132,8 +132,8 @@
 	if (debug < level)
 		return;
 
-	printk(KERN_DEBUG __FILE__": %s - length = %d, data = ",
-	       function, size);
+	printk(KERN_DEBUG "%s: %s - length = %d, data = ",
+	       __FILE__, function, size);
 	for (i = 0; i < size; ++i)
 		printk("%.2x ", data[i]);
 	printk("\n");
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 1eb9e41..4d2952f 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -57,7 +57,7 @@
 	.bInterfaceProtocol = 0x00
 
 /* table of devices that work with this driver */
-static struct usb_device_id appledisplay_table [] = {
+static const struct usb_device_id appledisplay_table[] = {
 	{ APPLEDISPLAY_DEVICE(0x9218) },
 	{ APPLEDISPLAY_DEVICE(0x9219) },
 	{ APPLEDISPLAY_DEVICE(0x921c) },
@@ -179,7 +179,7 @@
 		return pdata->msgdata[1];
 }
 
-static struct backlight_ops appledisplay_bl_data = {
+static const struct backlight_ops appledisplay_bl_data = {
 	.get_brightness	= appledisplay_bl_get_brightness,
 	.update_status	= appledisplay_bl_update_status,
 };
@@ -283,6 +283,7 @@
 						&appledisplay_bl_data);
 	if (IS_ERR(pdata->bd)) {
 		dev_err(&iface->dev, "Backlight registration failed\n");
+		retval = PTR_ERR(pdata->bd);
 		goto error;
 	}
 
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c
deleted file mode 100644
index c05a85b..0000000
--- a/drivers/usb/misc/berry_charge.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * USB BlackBerry charging module
- *
- * Copyright (C) 2007 Greg Kroah-Hartman <gregkh@suse.de>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License as
- *	published by the Free Software Foundation, version 2.
- *
- * Information on how to switch configs was taken by the bcharge.cc file
- * created by the barry.sf.net project.
- *
- * bcharge.cc has the following copyright:
- * 	Copyright (C) 2006, Net Direct Inc. (http://www.netdirect.ca/)
- * and is released under the GPLv2.
- *
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-
-#define RIM_VENDOR		0x0fca
-#define BLACKBERRY		0x0001
-#define BLACKBERRY_PEARL_DUAL   0x0004
-#define BLACKBERRY_PEARL        0x0006
-
-static int debug;
-static int pearl_dual_mode = 1;
-
-#ifdef dbg
-#undef dbg
-#endif
-#define dbg(dev, format, arg...)				\
-	if (debug)						\
-		dev_printk(KERN_DEBUG , dev , format , ## arg)
-
-static struct usb_device_id id_table [] = {
-	{ USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
-	{ USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL) },
-	{ USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL_DUAL) },
-	{ },					/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static int magic_charge(struct usb_device *udev)
-{
-	char *dummy_buffer = kzalloc(2, GFP_KERNEL);
-	int retval;
-
-	if (!dummy_buffer)
-		return -ENOMEM;
-
-	/* send two magic commands and then set the configuration.  The device
-	 * will then reset itself with the new power usage and should start
-	 * charging. */
-
-	/* Note, with testing, it only seems that the first message is really
-	 * needed (at least for the 8700c), but to be safe, we emulate what
-	 * other operating systems seem to be sending to their device.  We
-	 * really need to get some specs for this device to be sure about what
-	 * is going on here.
-	 */
-	dbg(&udev->dev, "Sending first magic command\n");
-	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-				 0xa5, 0xc0, 0, 1, dummy_buffer, 2, 100);
-	if (retval != 2) {
-		dev_err(&udev->dev, "First magic command failed: %d.\n",
-			retval);
-		goto exit;
-	}
-
-	dbg(&udev->dev, "Sending second magic command\n");
-	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-				 0xa2, 0x40, 0, 1, dummy_buffer, 0, 100);
-	if (retval != 0) {
-		dev_err(&udev->dev, "Second magic command failed: %d.\n",
-			retval);
-		goto exit;
-	}
-
-	dbg(&udev->dev, "Calling set_configuration\n");
-	retval = usb_driver_set_configuration(udev, 1);
-	if (retval)
-		dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
-
-exit:
-	kfree(dummy_buffer);
-	return retval;
-}
-
-static int magic_dual_mode(struct usb_device *udev)
-{
-	char *dummy_buffer = kzalloc(2, GFP_KERNEL);
-	int retval;
-
-	if (!dummy_buffer)
-		return -ENOMEM;
-
-	/* send magic command so that the Blackberry Pearl device exposes
-	 * two interfaces: both the USB mass-storage one and one which can
-	 * be used for database access. */
-	dbg(&udev->dev, "Sending magic pearl command\n");
-	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-				 0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100);
-	dbg(&udev->dev, "Magic pearl command returned %d\n", retval);
-
-	dbg(&udev->dev, "Calling set_configuration\n");
-	retval = usb_driver_set_configuration(udev, 1);
-	if (retval)
-		dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
-
-	kfree(dummy_buffer);
-	return retval;
-}
-
-static int berry_probe(struct usb_interface *intf,
-		       const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-
-	if (udev->bus_mA < 500) {
-		dbg(&udev->dev, "Not enough power to charge available\n");
-		return -ENODEV;
-	}
-
-	dbg(&udev->dev, "Power is set to %dmA\n",
-	    udev->actconfig->desc.bMaxPower * 2);
-
-	/* check the power usage so we don't try to enable something that is
-	 * already enabled */
-	if ((udev->actconfig->desc.bMaxPower * 2) == 500) {
-		dbg(&udev->dev, "device is already charging, power is "
-		    "set to %dmA\n", udev->actconfig->desc.bMaxPower * 2);
-		return -ENODEV;
-	}
-
-	/* turn the power on */
-	magic_charge(udev);
-
-	if ((le16_to_cpu(udev->descriptor.idProduct) == BLACKBERRY_PEARL) &&
-	    (pearl_dual_mode))
-		magic_dual_mode(udev);
-
-	/* we don't really want to bind to the device, userspace programs can
-	 * handle the syncing just fine, so get outta here. */
-	return -ENODEV;
-}
-
-static void berry_disconnect(struct usb_interface *intf)
-{
-}
-
-static struct usb_driver berry_driver = {
-	.name =		"berry_charge",
-	.probe =	berry_probe,
-	.disconnect =	berry_disconnect,
-	.id_table =	id_table,
-};
-
-static int __init berry_init(void)
-{
-	return usb_register(&berry_driver);
-}
-
-static void __exit berry_exit(void)
-{
-	usb_deregister(&berry_driver);
-}
-
-module_init(berry_init);
-module_exit(berry_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-module_param(pearl_dual_mode, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(pearl_dual_mode, "Change Blackberry Pearl to run in dual mode");
diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c
index 5720bfe..1547d8c 100644
--- a/drivers/usb/misc/cypress_cy7c63.c
+++ b/drivers/usb/misc/cypress_cy7c63.c
@@ -56,7 +56,7 @@
 
 
 /* table of devices that work with this driver */
-static struct usb_device_id cypress_table [] = {
+static const struct usb_device_id cypress_table[] = {
 	{ USB_DEVICE(CYPRESS_VENDOR_ID, CYPRESS_PRODUCT_ID) },
 	{ }
 };
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
index 4fb3c38..b9cbbbda 100644
--- a/drivers/usb/misc/cytherm.c
+++ b/drivers/usb/misc/cytherm.c
@@ -27,7 +27,7 @@
 #define USB_SKEL_VENDOR_ID	0x04b4
 #define USB_SKEL_PRODUCT_ID	0x0002
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
 	{ }
 };
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 879a980..a6521c95 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -245,7 +245,7 @@
 	return err;
 }
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(EMI26_VENDOR_ID, EMI26_PRODUCT_ID) },
 	{ USB_DEVICE(EMI26_VENDOR_ID, EMI26B_PRODUCT_ID) },
 	{ }                                             /* Terminating entry */
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 59860b3..fc15ad4 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -259,7 +259,7 @@
 	return err;
 }
 
-static __devinitdata struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] __devinitconst = {
 	{ USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) },
 	{ }                                             /* Terminating entry */
 };
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 9d0675e..1edb6d3 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -86,7 +86,7 @@
 #define USB_FTDI_ELAN_VENDOR_ID 0x0403
 #define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea
 /* table of devices that work with this driver*/
-static struct usb_device_id ftdi_elan_table[] = {
+static const struct usb_device_id ftdi_elan_table[] = {
         {USB_DEVICE(USB_FTDI_ELAN_VENDOR_ID, USB_FTDI_ELAN_PRODUCT_ID)},
         { /* Terminating entry */ }
 };
@@ -623,9 +623,12 @@
 */
 static int ftdi_elan_open(struct inode *inode, struct file *file)
 {
-        int subminor = iminor(inode);
-        struct usb_interface *interface = usb_find_interface(&ftdi_elan_driver,
-                subminor);
+	int subminor;
+	struct usb_interface *interface;
+
+        subminor = iminor(inode);
+        interface = usb_find_interface(&ftdi_elan_driver, subminor);
+
         if (!interface) {
                 printk(KERN_ERR "can't find device for minor %d\n", subminor);
                 return -ENODEV;
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 1337a9c..a54c3cb 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -48,7 +48,7 @@
 #define ID_CHERRY  0x0010
 
 /* device ID table */
-static struct usb_device_id idmouse_table[] = {
+static const struct usb_device_id idmouse_table[] = {
 	{USB_DEVICE(ID_SIEMENS, ID_IDMOUSE)}, /* Siemens ID Mouse (Professional) */
 	{USB_DEVICE(ID_SIEMENS, ID_CHERRY )}, /* Cherry FingerTIP ID Board       */
 	{}                                    /* terminating null entry          */
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index e75bb87..d3c8523 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -139,7 +139,7 @@
 /* driver registration */
 /*---------------------*/
 /* table of devices that work with this driver */
-static struct usb_device_id iowarrior_ids[] = {
+static const struct usb_device_id iowarrior_ids[] = {
 	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40)},
 	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24)},
 	{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV1)},
@@ -602,10 +602,12 @@
 
 	dbg("%s", __func__);
 
+	lock_kernel();
 	subminor = iminor(inode);
 
 	interface = usb_find_interface(&iowarrior_driver, subminor);
 	if (!interface) {
+		unlock_kernel();
 		err("%s - error, can't find device for minor %d", __func__,
 		    subminor);
 		return -ENODEV;
@@ -615,6 +617,7 @@
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
 		mutex_unlock(&iowarrior_open_disc_lock);
+		unlock_kernel();
 		return -ENODEV;
 	}
 
@@ -641,6 +644,7 @@
 
 out:
 	mutex_unlock(&dev->mutex);
+	unlock_kernel();
 	return retval;
 }
 
diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c
index b897f65..06e990a 100644
--- a/drivers/usb/misc/isight_firmware.c
+++ b/drivers/usb/misc/isight_firmware.c
@@ -26,7 +26,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
 	{USB_DEVICE(0x05ac, 0x8300)},
 	{},
 };
@@ -112,6 +112,8 @@
 	return ret;
 }
 
+MODULE_FIRMWARE("isight.fw");
+
 static void isight_firmware_disconnect(struct usb_interface *intf)
 {
 }
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 90f1301..dd41d87 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -69,7 +69,7 @@
 #endif
 
 /* table of devices that work with this driver */
-static struct usb_device_id ld_usb_table [] = {
+static const struct usb_device_id ld_usb_table[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
 	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
 	{ USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) },
@@ -798,7 +798,7 @@
 	/* register this driver with the USB subsystem */
 	retval = usb_register(&ld_usb_driver);
 	if (retval)
-		err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval);
+		err("usb_register failed for the %s driver. Error number %d\n", __FILE__, retval);
 
 	return retval;
 }
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index faa6d62..8547bf9 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -95,8 +95,11 @@
 
 /* Use our own dbg macro */
 #undef dbg
-#define dbg(lvl, format, arg...) do { if (debug >= lvl) printk(KERN_DEBUG  __FILE__ ": " format "\n", ## arg); } while (0)
-
+#define dbg(lvl, format, arg...)					\
+do {									\
+	if (debug >= lvl)						\
+		printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg);	\
+} while (0)
 
 /* Version Information */
 #define DRIVER_VERSION "v0.96"
@@ -192,7 +195,7 @@
 
 
 /* table of devices that work with this driver */
-static struct usb_device_id tower_table [] = {
+static const struct usb_device_id tower_table[] = {
 	{ USB_DEVICE(LEGO_USB_TOWER_VENDOR_ID, LEGO_USB_TOWER_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
@@ -302,7 +305,7 @@
 	if (debug < level)
 		return;
 
-	printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", function, size);
+	printk (KERN_DEBUG "%s: %s - length = %d, data = ", __FILE__, function, size);
 	for (i = 0; i < size; ++i) {
 		printk ("%.2x ", data[i]);
 	}
@@ -1055,7 +1058,7 @@
 	/* register this driver with the USB subsystem */
 	result = usb_register(&tower_driver);
 	if (result < 0) {
-		err("usb_register failed for the "__FILE__" driver. Error number %d", result);
+		err("usb_register failed for the %s driver. Error number %d", __FILE__, result);
 		retval = -1;
 		goto exit;
 	}
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 32d0199..a85771b 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -78,10 +78,13 @@
 {
 	struct rio_usb_data *rio = &rio_instance;
 
+	/* against disconnect() */
+	lock_kernel();
 	mutex_lock(&(rio->lock));
 
 	if (rio->isopen || !rio->present) {
 		mutex_unlock(&(rio->lock));
+		unlock_kernel();
 		return -EBUSY;
 	}
 	rio->isopen = 1;
@@ -91,6 +94,7 @@
 	mutex_unlock(&(rio->lock));
 
 	dev_info(&rio->rio_dev->dev, "Rio opened.\n");
+	unlock_kernel();
 
 	return 0;
 }
@@ -115,7 +119,6 @@
 	int retries;
 	int retval=0;
 
-	lock_kernel();
 	mutex_lock(&(rio->lock));
         /* Sanity check to make sure rio is connected, powered, etc */
         if (rio->present == 0 || rio->rio_dev == NULL) {
@@ -254,7 +257,6 @@
 
 err_out:
 	mutex_unlock(&(rio->lock));
-	unlock_kernel();
 	return retval;
 }
 
@@ -489,6 +491,7 @@
 	struct rio_usb_data *rio = usb_get_intfdata (intf);
 
 	usb_set_intfdata (intf, NULL);
+	lock_kernel();
 	if (rio) {
 		usb_deregister_dev(intf, &usb_rio_class);
 
@@ -498,6 +501,7 @@
 			/* better let it finish - the release will do whats needed */
 			rio->rio_dev = NULL;
 			mutex_unlock(&(rio->lock));
+			unlock_kernel();
 			return;
 		}
 		kfree(rio->ibuf);
@@ -508,9 +512,10 @@
 		rio->present = 0;
 		mutex_unlock(&(rio->lock));
 	}
+	unlock_kernel();
 }
 
-static struct usb_device_id rio_table [] = {
+static const struct usb_device_id rio_table[] = {
 	{ USB_DEVICE(0x0841, 1) }, 		/* Rio 500 */
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 8b37a4b..aae95a0 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -250,7 +250,7 @@
 	sisusb->urbstatus[index] |= SU_URB_BUSY;
 
 	/* Submit URB */
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	retval = usb_submit_urb(urb, GFP_KERNEL);
 
 	/* If OK, and if timeout > 0, wait for completion */
 	if ((retval == 0) && timeout) {
@@ -306,7 +306,7 @@
 	urb->actual_length = 0;
 
 	sisusb->completein = 0;
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	retval = usb_submit_urb(urb, GFP_KERNEL);
 	if (retval == 0) {
 		wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
 		if (!sisusb->completein) {
@@ -2416,21 +2416,28 @@
 	struct usb_interface *interface;
 	int subminor = iminor(inode);
 
-	if (!(interface = usb_find_interface(&sisusb_driver, subminor)))
+	lock_kernel();
+	if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
+		unlock_kernel();
 		return -ENODEV;
+	}
 
-	if (!(sisusb = usb_get_intfdata(interface)))
+	if (!(sisusb = usb_get_intfdata(interface))) {
+		unlock_kernel();
 		return -ENODEV;
+	}
 
 	mutex_lock(&sisusb->lock);
 
 	if (!sisusb->present || !sisusb->ready) {
 		mutex_unlock(&sisusb->lock);
+		unlock_kernel();
 		return -ENODEV;
 	}
 
 	if (sisusb->isopen) {
 		mutex_unlock(&sisusb->lock);
+		unlock_kernel();
 		return -EBUSY;
 	}
 
@@ -2439,11 +2446,13 @@
 			if (sisusb_init_gfxdevice(sisusb, 0)) {
 				mutex_unlock(&sisusb->lock);
 				dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n");
+				unlock_kernel();
 				return -EIO;
 			}
 		} else {
 			mutex_unlock(&sisusb->lock);
 			dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n");
+			unlock_kernel();
 			return -EIO;
 		}
 	}
@@ -2456,6 +2465,7 @@
 	file->private_data = sisusb;
 
 	mutex_unlock(&sisusb->lock);
+	unlock_kernel();
 
 	return 0;
 }
@@ -3238,7 +3248,7 @@
 	kref_put(&sisusb->kref, sisusb_delete);
 }
 
-static struct usb_device_id sisusb_table [] = {
+static const struct usb_device_id sisusb_table[] = {
 	{ USB_DEVICE(0x0711, 0x0550) },
 	{ USB_DEVICE(0x0711, 0x0900) },
 	{ USB_DEVICE(0x0711, 0x0901) },
diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c
index 2e14102..5da28eae 100644
--- a/drivers/usb/misc/trancevibrator.c
+++ b/drivers/usb/misc/trancevibrator.c
@@ -33,7 +33,7 @@
 #define TRANCEVIBRATOR_VENDOR_ID	0x0b49	/* ASCII Corporation */
 #define TRANCEVIBRATOR_PRODUCT_ID	0x064f	/* Trance Vibrator */
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) },
 	{ },
 };
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 4fb1203..90aede9 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -30,7 +30,7 @@
 #define IOCTL_GET_DRV_VERSION	2
 
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, },
 	{ },
 };
@@ -74,10 +74,12 @@
 	struct usb_interface *interface;
 	int subminor, r;
 
+	lock_kernel();
 	subminor = iminor(inode);
 
 	interface = usb_find_interface(&lcd_driver, subminor);
 	if (!interface) {
+		unlock_kernel();
 		err ("USBLCD: %s - error, can't find device for minor %d",
 		     __func__, subminor);
 		return -ENODEV;
@@ -87,6 +89,7 @@
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
 		mutex_unlock(&open_disc_mutex);
+		unlock_kernel();
 		return -ENODEV;
 	}
 
@@ -98,11 +101,13 @@
 	r = usb_autopm_get_interface(interface);
 	if (r < 0) {
 		kref_put(&dev->kref, lcd_delete);
+		unlock_kernel();
 		return r;
 	}
 
 	/* save our object in the file's private structure */
 	file->private_data = dev;
+	unlock_kernel();
 
 	return 0;
 }
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index 06cb719..63da2c3 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -24,7 +24,7 @@
 #define PRODUCT_ID	0x1223
 
 /* table of devices that work with this driver */
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
 	{ },
 };
diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c
index 3db2555..a9555cb 100644
--- a/drivers/usb/misc/usbsevseg.c
+++ b/drivers/usb/misc/usbsevseg.c
@@ -27,7 +27,7 @@
 #define MAXLEN		6
 
 /* table of devices that work with this driver */
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
 	{ },
 };
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 3dab0c0..a21cce6 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -1580,10 +1580,6 @@
 		return -ERESTARTSYS;
 
 	/* FIXME: What if a system sleep starts while a test is running? */
-	if (!intf->is_active) {
-		mutex_unlock(&dev->lock);
-		return -EHOSTUNREACH;
-	}
 
 	/* some devices, like ez-usb default devices, need a non-default
 	 * altsetting to have any active endpoints.  some tests change
@@ -2101,7 +2097,7 @@
 #endif
 
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 
 	/*-------------------------------------------------------------*/
 
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 9a6c27a..f56fed5 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -770,7 +770,7 @@
 }
 
 /* table of cables that work through this driver */
-static struct usb_device_id uss720_table [] = {
+static const struct usb_device_id uss720_table[] = {
 	{ USB_DEVICE(0x047e, 0x1001) },
 	{ USB_DEVICE(0x0557, 0x2001) },
 	{ USB_DEVICE(0x0729, 0x1284) },
diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c
deleted file mode 100644
index f26ea8d..0000000
--- a/drivers/usb/misc/vstusb.c
+++ /dev/null
@@ -1,783 +0,0 @@
-/*****************************************************************************
- *  File: drivers/usb/misc/vstusb.c
- *
- *  Purpose: Support for the bulk USB Vernier Spectrophotometers
- *
- *  Author:     Johnnie Peters
- *              Axian Consulting
- *              Beaverton, OR, USA 97005
- *
- *  Modified by:     EQware Engineering, Inc.
- *                   Oregon City, OR, USA 97045
- *
- *  Copyright:  2007, 2008
- *              Vernier Software & Technology
- *              Beaverton, OR, USA 97005
- *
- *  Web:        www.vernier.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/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-
-#include <linux/usb/vstusb.h>
-
-#define DRIVER_VERSION "VST USB Driver Version 1.5"
-#define DRIVER_DESC "Vernier Software Technology Bulk USB Driver"
-
-#ifdef CONFIG_USB_DYNAMIC_MINORS
-	#define VSTUSB_MINOR_BASE	0
-#else
-	#define VSTUSB_MINOR_BASE	199
-#endif
-
-#define USB_VENDOR_OCEANOPTICS	0x2457
-#define USB_VENDOR_VERNIER	0x08F7	/* Vernier Software & Technology */
-
-#define USB_PRODUCT_USB2000	0x1002
-#define USB_PRODUCT_ADC1000_FW	0x1003	/* firmware download (renumerates) */
-#define USB_PRODUCT_ADC1000	0x1004
-#define USB_PRODUCT_HR2000_FW	0x1009	/* firmware download (renumerates) */
-#define USB_PRODUCT_HR2000	0x100A
-#define USB_PRODUCT_HR4000_FW	0x1011	/* firmware download (renumerates) */
-#define USB_PRODUCT_HR4000	0x1012
-#define USB_PRODUCT_USB650	0x1014	/* "Red Tide" */
-#define USB_PRODUCT_QE65000	0x1018
-#define USB_PRODUCT_USB4000	0x1022
-#define USB_PRODUCT_USB325	0x1024	/* "Vernier Spectrometer" */
-
-#define USB_PRODUCT_LABPRO	0x0001
-#define USB_PRODUCT_LABQUEST	0x0005
-
-#define VST_MAXBUFFER		(64*1024)
-
-static struct usb_device_id id_table[] = {
-	{ USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB2000)},
-	{ USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_HR4000)},
-	{ USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB650)},
-	{ USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB4000)},
-	{ USB_DEVICE(USB_VENDOR_OCEANOPTICS, USB_PRODUCT_USB325)},
-	{ USB_DEVICE(USB_VENDOR_VERNIER, USB_PRODUCT_LABQUEST)},
-	{ USB_DEVICE(USB_VENDOR_VERNIER, USB_PRODUCT_LABPRO)},
-	{},
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-struct vstusb_device {
-	struct kref				kref;
-	struct mutex            lock;
-	struct usb_device       *usb_dev;
-	char                    present;
-	char                    isopen;
-	struct usb_anchor       submitted;
-	int                     rd_pipe;
-	int                     rd_timeout_ms;
-	int                     wr_pipe;
-	int                     wr_timeout_ms;
-};
-#define to_vst_dev(d) container_of(d, struct vstusb_device, kref)
-
-static struct usb_driver vstusb_driver;
-
-static void vstusb_delete(struct kref *kref)
-{
-	struct vstusb_device *vstdev = to_vst_dev(kref);
-
-	usb_put_dev(vstdev->usb_dev);
-	kfree(vstdev);
-}
-
-static int vstusb_open(struct inode *inode, struct file *file)
-{
-	struct vstusb_device *vstdev;
-	struct usb_interface *interface;
-
-	interface = usb_find_interface(&vstusb_driver, iminor(inode));
-
-	if (!interface) {
-		printk(KERN_ERR KBUILD_MODNAME
-		       ": %s - error, can't find device for minor %d\n",
-		       __func__, iminor(inode));
-		return -ENODEV;
-	}
-
-	vstdev = usb_get_intfdata(interface);
-
-	if (!vstdev)
-		return -ENODEV;
-
-	/* lock this device */
-	mutex_lock(&vstdev->lock);
-
-	/* can only open one time */
-	if ((!vstdev->present) || (vstdev->isopen)) {
-		mutex_unlock(&vstdev->lock);
-		return -EBUSY;
-	}
-
-	/* increment our usage count */
-	kref_get(&vstdev->kref);
-
-	vstdev->isopen = 1;
-
-	/* save device in the file's private structure */
-	file->private_data = vstdev;
-
-	dev_dbg(&vstdev->usb_dev->dev, "%s: opened\n", __func__);
-
-	mutex_unlock(&vstdev->lock);
-
-	return 0;
-}
-
-static int vstusb_release(struct inode *inode, struct file *file)
-{
-	struct vstusb_device *vstdev;
-
-	vstdev = file->private_data;
-
-	if (vstdev == NULL)
-		return -ENODEV;
-
-	mutex_lock(&vstdev->lock);
-
-	vstdev->isopen = 0;
-
-	dev_dbg(&vstdev->usb_dev->dev, "%s: released\n", __func__);
-
-	mutex_unlock(&vstdev->lock);
-
-	kref_put(&vstdev->kref, vstusb_delete);
-
-	return 0;
-}
-
-static void usb_api_blocking_completion(struct urb *urb)
-{
-	struct completion *completeit = urb->context;
-
-	complete(completeit);
-}
-
-static int vstusb_fill_and_send_urb(struct urb *urb,
-				    struct usb_device *usb_dev,
-				    unsigned int pipe, void *data,
-				    unsigned int len, struct completion *done)
-{
-	struct usb_host_endpoint *ep;
-	struct usb_host_endpoint **hostep;
-	unsigned int pipend;
-
-	int status;
-
-	hostep = usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out;
-	pipend = usb_pipeendpoint(pipe);
-	ep = hostep[pipend];
-
-	if (!ep || (len == 0))
-		return -EINVAL;
-
-	if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-	    == USB_ENDPOINT_XFER_INT) {
-		pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
-		usb_fill_int_urb(urb, usb_dev, pipe, data, len,
-				 (usb_complete_t)usb_api_blocking_completion,
-				 NULL, ep->desc.bInterval);
-	} else
-		usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
-				  (usb_complete_t)usb_api_blocking_completion,
-				  NULL);
-
-	init_completion(done);
-	urb->context = done;
-	urb->actual_length = 0;
-	status = usb_submit_urb(urb, GFP_KERNEL);
-
-	return status;
-}
-
-static int vstusb_complete_urb(struct urb *urb, struct completion *done,
-			       int timeout, int *actual_length)
-{
-	unsigned long expire;
-	int status;
-
-	expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
-	if (!wait_for_completion_interruptible_timeout(done, expire)) {
-		usb_kill_urb(urb);
-		status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
-
-		dev_dbg(&urb->dev->dev,
-			"%s timed out on ep%d%s len=%d/%d, urb status = %d\n",
-			current->comm,
-			usb_pipeendpoint(urb->pipe),
-			usb_pipein(urb->pipe) ? "in" : "out",
-			urb->actual_length,
-			urb->transfer_buffer_length,
-			urb->status);
-
-	} else {
-		if (signal_pending(current)) {
-			/* if really an error */
-			if (urb->status && !((urb->status == -ENOENT)     ||
-					     (urb->status == -ECONNRESET) ||
-					     (urb->status == -ESHUTDOWN))) {
-				status = -EINTR;
-				usb_kill_urb(urb);
-			} else {
-				status = 0;
-			}
-
-			dev_dbg(&urb->dev->dev,
-				"%s: signal pending on ep%d%s len=%d/%d,"
-				"urb status = %d\n",
-				current->comm,
-				usb_pipeendpoint(urb->pipe),
-				usb_pipein(urb->pipe) ? "in" : "out",
-				urb->actual_length,
-				urb->transfer_buffer_length,
-				urb->status);
-
-		} else {
-			status = urb->status;
-		}
-	}
-
-	if (actual_length)
-		*actual_length = urb->actual_length;
-
-	return status;
-}
-
-static ssize_t vstusb_read(struct file *file, char __user *buffer,
-			   size_t count, loff_t *ppos)
-{
-	struct vstusb_device *vstdev;
-	int cnt = -1;
-	void *buf;
-	int retval = 0;
-
-	struct urb              *urb;
-	struct usb_device       *dev;
-	unsigned int            pipe;
-	int                     timeout;
-
-	DECLARE_COMPLETION_ONSTACK(done);
-
-	vstdev = file->private_data;
-
-	if (vstdev == NULL)
-		return -ENODEV;
-
-	/* verify that we actually want to read some data */
-	if ((count == 0) || (count > VST_MAXBUFFER))
-		return -EINVAL;
-
-	/* lock this object */
-	if (mutex_lock_interruptible(&vstdev->lock))
-		return -ERESTARTSYS;
-
-	/* anyone home */
-	if (!vstdev->present) {
-		mutex_unlock(&vstdev->lock);
-		printk(KERN_ERR KBUILD_MODNAME
-		       ": %s: device not present\n", __func__);
-		return -ENODEV;
-	}
-
-	/* pull out the necessary data */
-	dev =     vstdev->usb_dev;
-	pipe =    usb_rcvbulkpipe(dev, vstdev->rd_pipe);
-	timeout = vstdev->rd_timeout_ms;
-
-	buf = kmalloc(count, GFP_KERNEL);
-	if (buf == NULL) {
-		mutex_unlock(&vstdev->lock);
-		return -ENOMEM;
-	}
-
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb) {
-		kfree(buf);
-		mutex_unlock(&vstdev->lock);
-		return -ENOMEM;
-	}
-
-	usb_anchor_urb(urb, &vstdev->submitted);
-	retval = vstusb_fill_and_send_urb(urb, dev, pipe, buf, count, &done);
-	mutex_unlock(&vstdev->lock);
-	if (retval) {
-		usb_unanchor_urb(urb);
-		dev_err(&dev->dev, "%s: error %d filling and sending urb %d\n",
-			__func__, retval, pipe);
-		goto exit;
-	}
-
-	retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
-	if (retval) {
-		dev_err(&dev->dev, "%s: error %d completing urb %d\n",
-			__func__, retval, pipe);
-		goto exit;
-	}
-
-	if (copy_to_user(buffer, buf, cnt)) {
-		dev_err(&dev->dev, "%s: can't copy_to_user\n", __func__);
-		retval = -EFAULT;
-	} else {
-		retval = cnt;
-		dev_dbg(&dev->dev, "%s: read %d bytes from pipe %d\n",
-			__func__, cnt, pipe);
-	}
-
-exit:
-	usb_free_urb(urb);
-	kfree(buf);
-	return retval;
-}
-
-static ssize_t vstusb_write(struct file *file, const char __user *buffer,
-			    size_t count, loff_t *ppos)
-{
-	struct vstusb_device *vstdev;
-	int cnt = -1;
-	void *buf;
-	int retval = 0;
-
-	struct urb              *urb;
-	struct usb_device       *dev;
-	unsigned int            pipe;
-	int                     timeout;
-
-	DECLARE_COMPLETION_ONSTACK(done);
-
-	vstdev = file->private_data;
-
-	if (vstdev == NULL)
-		return -ENODEV;
-
-	/* verify that we actually have some data to write */
-	if ((count == 0) || (count > VST_MAXBUFFER))
-		return retval;
-
-	/* lock this object */
-	if (mutex_lock_interruptible(&vstdev->lock))
-		return -ERESTARTSYS;
-
-	/* anyone home */
-	if (!vstdev->present) {
-		mutex_unlock(&vstdev->lock);
-		printk(KERN_ERR KBUILD_MODNAME
-		       ": %s: device not present\n", __func__);
-		return -ENODEV;
-	}
-
-	/* pull out the necessary data */
-	dev =     vstdev->usb_dev;
-	pipe =    usb_sndbulkpipe(dev, vstdev->wr_pipe);
-	timeout = vstdev->wr_timeout_ms;
-
-	buf = kmalloc(count, GFP_KERNEL);
-	if (buf == NULL) {
-		mutex_unlock(&vstdev->lock);
-		return -ENOMEM;
-	}
-
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb) {
-		kfree(buf);
-		mutex_unlock(&vstdev->lock);
-		return -ENOMEM;
-	}
-
-	if (copy_from_user(buf, buffer, count)) {
-		mutex_unlock(&vstdev->lock);
-		dev_err(&dev->dev, "%s: can't copy_from_user\n", __func__);
-		retval = -EFAULT;
-		goto exit;
-	}
-
-	usb_anchor_urb(urb, &vstdev->submitted);
-	retval = vstusb_fill_and_send_urb(urb, dev, pipe, buf, count, &done);
-	mutex_unlock(&vstdev->lock);
-	if (retval) {
-		usb_unanchor_urb(urb);
-		dev_err(&dev->dev, "%s: error %d filling and sending urb %d\n",
-			__func__, retval, pipe);
-		goto exit;
-	}
-
-	retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
-	if (retval) {
-		dev_err(&dev->dev, "%s: error %d completing urb %d\n",
-			__func__, retval, pipe);
-		goto exit;
-	} else {
-		retval = cnt;
-		dev_dbg(&dev->dev, "%s: sent %d bytes to pipe %d\n",
-			__func__, cnt, pipe);
-	}
-
-exit:
-	usb_free_urb(urb);
-	kfree(buf);
-	return retval;
-}
-
-static long vstusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	int retval = 0;
-	int cnt = -1;
-	void __user *data = (void __user *)arg;
-	struct vstusb_args usb_data;
-
-	struct vstusb_device *vstdev;
-	void *buffer = NULL; /* must be initialized. buffer is
-			      *	referenced on exit but not all
-			      * ioctls allocate it */
-
-	struct urb              *urb = NULL; /* must be initialized. urb is
-					      *	referenced on exit but not all
-					      * ioctls allocate it */
-	struct usb_device       *dev;
-	unsigned int            pipe;
-	int                     timeout;
-
-	DECLARE_COMPLETION_ONSTACK(done);
-
-	vstdev = file->private_data;
-
-	if (_IOC_TYPE(cmd) != VST_IOC_MAGIC) {
-		dev_warn(&vstdev->usb_dev->dev,
-			 "%s: ioctl command %x, bad ioctl magic %x, "
-			 "expected %x\n", __func__, cmd,
-			 _IOC_TYPE(cmd), VST_IOC_MAGIC);
-		return -EINVAL;
-	}
-
-	if (vstdev == NULL)
-		return -ENODEV;
-
-	if (copy_from_user(&usb_data, data, sizeof(struct vstusb_args))) {
-		dev_err(&vstdev->usb_dev->dev, "%s: can't copy_from_user\n",
-			__func__);
-		return -EFAULT;
-	}
-
-	/* lock this object */
-	if (mutex_lock_interruptible(&vstdev->lock)) {
-		retval = -ERESTARTSYS;
-		goto exit;
-	}
-
-	/* anyone home */
-	if (!vstdev->present) {
-		mutex_unlock(&vstdev->lock);
-		dev_err(&vstdev->usb_dev->dev, "%s: device not present\n",
-			__func__);
-		retval = -ENODEV;
-		goto exit;
-	}
-
-	/* pull out the necessary data */
-	dev = vstdev->usb_dev;
-
-	switch (cmd) {
-
-	case IOCTL_VSTUSB_CONFIG_RW:
-
-		vstdev->rd_pipe = usb_data.rd_pipe;
-		vstdev->rd_timeout_ms = usb_data.rd_timeout_ms;
-		vstdev->wr_pipe = usb_data.wr_pipe;
-		vstdev->wr_timeout_ms = usb_data.wr_timeout_ms;
-
-		mutex_unlock(&vstdev->lock);
-
-		dev_dbg(&dev->dev, "%s: setting pipes/timeouts, "
-			"rdpipe = %d, rdtimeout = %d, "
-			"wrpipe = %d, wrtimeout = %d\n", __func__,
-			vstdev->rd_pipe, vstdev->rd_timeout_ms,
-			vstdev->wr_pipe, vstdev->wr_timeout_ms);
-		break;
-
-	case IOCTL_VSTUSB_SEND_PIPE:
-
-		if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) {
-			mutex_unlock(&vstdev->lock);
-			retval = -EINVAL;
-			goto exit;
-		}
-
-		buffer = kmalloc(usb_data.count, GFP_KERNEL);
-		if (buffer == NULL) {
-			mutex_unlock(&vstdev->lock);
-			retval = -ENOMEM;
-			goto exit;
-		}
-
-		urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!urb) {
-			mutex_unlock(&vstdev->lock);
-			retval = -ENOMEM;
-			goto exit;
-		}
-
-		timeout = usb_data.timeout_ms;
-
-		pipe = usb_sndbulkpipe(dev, usb_data.pipe);
-
-		if (copy_from_user(buffer, usb_data.buffer, usb_data.count)) {
-			dev_err(&dev->dev, "%s: can't copy_from_user\n",
-				__func__);
-			mutex_unlock(&vstdev->lock);
-			retval = -EFAULT;
-			goto exit;
-		}
-
-		usb_anchor_urb(urb, &vstdev->submitted);
-		retval = vstusb_fill_and_send_urb(urb, dev, pipe, buffer,
-						  usb_data.count, &done);
-		mutex_unlock(&vstdev->lock);
-		if (retval) {
-			usb_unanchor_urb(urb);
-			dev_err(&dev->dev,
-				"%s: error %d filling and sending urb %d\n",
-				__func__, retval, pipe);
-			goto exit;
-		}
-
-		retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
-		if (retval) {
-			dev_err(&dev->dev, "%s: error %d completing urb %d\n",
-				__func__, retval, pipe);
-		}
-
-		break;
-	case IOCTL_VSTUSB_RECV_PIPE:
-
-		if ((usb_data.count == 0) || (usb_data.count > VST_MAXBUFFER)) {
-			mutex_unlock(&vstdev->lock);
-			retval = -EINVAL;
-			goto exit;
-		}
-
-		buffer = kmalloc(usb_data.count, GFP_KERNEL);
-		if (buffer == NULL) {
-			mutex_unlock(&vstdev->lock);
-			retval = -ENOMEM;
-			goto exit;
-		}
-
-		urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!urb) {
-			mutex_unlock(&vstdev->lock);
-			retval = -ENOMEM;
-			goto exit;
-		}
-
-		timeout = usb_data.timeout_ms;
-
-		pipe = usb_rcvbulkpipe(dev, usb_data.pipe);
-
-		usb_anchor_urb(urb, &vstdev->submitted);
-		retval = vstusb_fill_and_send_urb(urb, dev, pipe, buffer,
-						  usb_data.count, &done);
-		mutex_unlock(&vstdev->lock);
-		if (retval) {
-			usb_unanchor_urb(urb);
-			dev_err(&dev->dev,
-				"%s: error %d filling and sending urb %d\n",
-				__func__, retval, pipe);
-			goto exit;
-		}
-
-		retval = vstusb_complete_urb(urb, &done, timeout, &cnt);
-		if (retval) {
-			dev_err(&dev->dev, "%s: error %d completing urb %d\n",
-				__func__, retval, pipe);
-			goto exit;
-		}
-
-		if (copy_to_user(usb_data.buffer, buffer, cnt)) {
-			dev_err(&dev->dev, "%s: can't copy_to_user\n",
-				__func__);
-			retval = -EFAULT;
-			goto exit;
-		}
-
-		usb_data.count = cnt;
-		if (copy_to_user(data, &usb_data, sizeof(struct vstusb_args))) {
-			dev_err(&dev->dev, "%s: can't copy_to_user\n",
-				__func__);
-			retval = -EFAULT;
-		} else {
-			dev_dbg(&dev->dev, "%s: recv %zd bytes from pipe %d\n",
-				__func__, usb_data.count, usb_data.pipe);
-		}
-
-		break;
-
-	default:
-		mutex_unlock(&vstdev->lock);
-		dev_warn(&dev->dev, "ioctl_vstusb: invalid ioctl cmd %x\n",
-			 cmd);
-		return -EINVAL;
-		break;
-	}
-exit:
-	usb_free_urb(urb);
-	kfree(buffer);
-	return retval;
-}
-
-static const struct file_operations vstusb_fops = {
-	.owner =                THIS_MODULE,
-	.read =                 vstusb_read,
-	.write =                vstusb_write,
-	.unlocked_ioctl =       vstusb_ioctl,
-	.compat_ioctl =         vstusb_ioctl,
-	.open =                 vstusb_open,
-	.release =              vstusb_release,
-};
-
-static struct usb_class_driver usb_vstusb_class = {
-	.name =         "usb/vstusb%d",
-	.fops =         &vstusb_fops,
-	.minor_base =   VSTUSB_MINOR_BASE,
-};
-
-static int vstusb_probe(struct usb_interface *intf,
-			const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct vstusb_device *vstdev;
-	int i;
-	int retval = 0;
-
-	/* allocate memory for our device state and intialize it */
-
-	vstdev = kzalloc(sizeof(*vstdev), GFP_KERNEL);
-	if (vstdev == NULL)
-		return -ENOMEM;
-
-	/* must do usb_get_dev() prior to kref_init() since the kref_put()
-	 * release function will do a usb_put_dev() */
-	usb_get_dev(dev);
-	kref_init(&vstdev->kref);
-	mutex_init(&vstdev->lock);
-
-	i = dev->descriptor.bcdDevice;
-
-	dev_dbg(&intf->dev, "Version %1d%1d.%1d%1d found at address %d\n",
-		(i & 0xF000) >> 12, (i & 0xF00) >> 8,
-		(i & 0xF0) >> 4, (i & 0xF), dev->devnum);
-
-	vstdev->present = 1;
-	vstdev->isopen = 0;
-	vstdev->usb_dev = dev;
-	init_usb_anchor(&vstdev->submitted);
-
-	usb_set_intfdata(intf, vstdev);
-	retval = usb_register_dev(intf, &usb_vstusb_class);
-	if (retval) {
-		dev_err(&intf->dev,
-			"%s: Not able to get a minor for this device.\n",
-			__func__);
-		usb_set_intfdata(intf, NULL);
-		kref_put(&vstdev->kref, vstusb_delete);
-		return retval;
-	}
-
-	/* let the user know what node this device is now attached to */
-	dev_info(&intf->dev,
-		 "VST USB Device #%d now attached to major %d minor %d\n",
-		 (intf->minor - VSTUSB_MINOR_BASE), USB_MAJOR, intf->minor);
-
-	dev_info(&intf->dev, "%s, %s\n", DRIVER_DESC, DRIVER_VERSION);
-
-	return retval;
-}
-
-static void vstusb_disconnect(struct usb_interface *intf)
-{
-	struct vstusb_device *vstdev = usb_get_intfdata(intf);
-
-	usb_deregister_dev(intf, &usb_vstusb_class);
-	usb_set_intfdata(intf, NULL);
-
-	if (vstdev) {
-
-		mutex_lock(&vstdev->lock);
-		vstdev->present = 0;
-
-		usb_kill_anchored_urbs(&vstdev->submitted);
-
-		mutex_unlock(&vstdev->lock);
-
-		kref_put(&vstdev->kref, vstusb_delete);
-	}
-
-}
-
-static int vstusb_suspend(struct usb_interface *intf, pm_message_t message)
-{
-	struct vstusb_device *vstdev = usb_get_intfdata(intf);
-	int time;
-	if (!vstdev)
-		return 0;
-
-	mutex_lock(&vstdev->lock);
-	time = usb_wait_anchor_empty_timeout(&vstdev->submitted, 1000);
-	if (!time)
-		usb_kill_anchored_urbs(&vstdev->submitted);
-	mutex_unlock(&vstdev->lock);
-
-	return 0;
-}
-
-static int vstusb_resume(struct usb_interface *intf)
-{
-	return 0;
-}
-
-static struct usb_driver vstusb_driver = {
-	.name =         "vstusb",
-	.probe =        vstusb_probe,
-	.disconnect =   vstusb_disconnect,
-	.suspend =      vstusb_suspend,
-	.resume =       vstusb_resume,
-	.id_table = id_table,
-};
-
-static int __init vstusb_init(void)
-{
-	int rc;
-
-	rc = usb_register(&vstusb_driver);
-	if (rc)
-		printk(KERN_ERR "%s: failed to register (%d)", __func__, rc);
-
-	return rc;
-}
-
-static void __exit vstusb_exit(void)
-{
-	usb_deregister(&vstusb_driver);
-}
-
-module_init(vstusb_init);
-module_exit(vstusb_exit);
-
-MODULE_AUTHOR("Dennis O'Brien/Stephen Ware");
-MODULE_DESCRIPTION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 385ec05..6dd44bc 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -460,8 +460,8 @@
     char ev_type, int status)
 {
 	const struct usb_endpoint_descriptor *epd = &urb->ep->desc;
-	unsigned long flags;
 	struct timeval ts;
+	unsigned long flags;
 	unsigned int urb_length;
 	unsigned int offset;
 	unsigned int length;
@@ -600,10 +600,13 @@
 static void mon_bin_error(void *data, struct urb *urb, int error)
 {
 	struct mon_reader_bin *rp = data;
+	struct timeval ts;
 	unsigned long flags;
 	unsigned int offset;
 	struct mon_bin_hdr *ep;
 
+	do_gettimeofday(&ts);
+
 	spin_lock_irqsave(&rp->b_lock, flags);
 
 	offset = mon_buff_area_alloc(rp, PKT_SIZE);
@@ -623,6 +626,8 @@
 	ep->devnum = urb->dev->devnum;
 	ep->busnum = urb->dev->bus->busnum;
 	ep->id = (unsigned long) urb;
+	ep->ts_sec = ts.tv_sec;
+	ep->ts_usec = ts.tv_usec;
 	ep->status = error;
 
 	ep->flag_setup = '-';
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 047568f..31c1188 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -180,7 +180,7 @@
 	unsigned int stamp;
 
 	do_gettimeofday(&tval);
-	stamp = tval.tv_sec & 0xFFFF;	/* 2^32 = 4294967296. Limit to 4096s. */
+	stamp = tval.tv_sec & 0xFFF;	/* 2^32 = 4294967296. Limit to 4096s. */
 	stamp = stamp * 1000000 + tval.tv_usec;
 	return stamp;
 }
@@ -273,12 +273,12 @@
 
 	ep->type = 'E';
 	ep->id = (unsigned long) urb;
-	ep->busnum = 0;
+	ep->busnum = urb->dev->bus->busnum;
 	ep->devnum = urb->dev->devnum;
 	ep->epnum = usb_endpoint_num(&urb->ep->desc);
 	ep->xfertype = usb_endpoint_type(&urb->ep->desc);
 	ep->is_in = usb_urb_dir_in(urb);
-	ep->tstamp = 0;
+	ep->tstamp = mon_get_timestamp();
 	ep->length = 0;
 	ep->status = error;
 
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index ad26e65..bcee133 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -30,7 +30,6 @@
 	void __iomem *fifo = hw_ep->fifo;
 	void __iomem *epio = hw_ep->regs;
 	u8 epnum = hw_ep->epnum;
-	u16 dma_reg = 0;
 
 	prefetch((u8 *)src);
 
@@ -42,15 +41,17 @@
 	dump_fifo_data(src, len);
 
 	if (!ANOMALY_05000380 && epnum != 0) {
-		flush_dcache_range((unsigned int)src,
-			(unsigned int)(src + len));
+		u16 dma_reg;
+
+		flush_dcache_range((unsigned long)src,
+			(unsigned long)(src + len));
 
 		/* Setup DMA address register */
-		dma_reg = (u16) ((u32) src & 0xFFFF);
+		dma_reg = (u32)src;
 		bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg);
 		SSYNC();
 
-		dma_reg = (u16) (((u32) src >> 16) & 0xFFFF);
+		dma_reg = (u32)src >> 16;
 		bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg);
 		SSYNC();
 
@@ -79,12 +80,9 @@
 		SSYNC();
 
 		if (unlikely((unsigned long)src & 0x01))
-			outsw_8((unsigned long)fifo, src,
-				len & 0x01 ? (len >> 1) + 1 : len >> 1);
+			outsw_8((unsigned long)fifo, src, (len + 1) >> 1);
 		else
-			outsw((unsigned long)fifo, src,
-				len & 0x01 ? (len >> 1) + 1 : len >> 1);
-
+			outsw((unsigned long)fifo, src, (len + 1) >> 1);
 	}
 }
 /*
@@ -94,19 +92,19 @@
 {
 	void __iomem *fifo = hw_ep->fifo;
 	u8 epnum = hw_ep->epnum;
-	u16 dma_reg = 0;
 
 	if (ANOMALY_05000467 && epnum != 0) {
+		u16 dma_reg;
 
-		invalidate_dcache_range((unsigned int)dst,
-			(unsigned int)(dst + len));
+		invalidate_dcache_range((unsigned long)dst,
+			(unsigned long)(dst + len));
 
 		/* Setup DMA address register */
-		dma_reg = (u16) ((u32) dst & 0xFFFF);
+		dma_reg = (u32)dst;
 		bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg);
 		SSYNC();
 
-		dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF);
+		dma_reg = (u32)dst >> 16;
 		bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg);
 		SSYNC();
 
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index a44a450..3c69a76 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -1191,8 +1191,13 @@
 
 		bd = tx_ch->head;
 
+		/*
+		 * If Head is null then this could mean that a abort interrupt
+		 * that needs to be acknowledged.
+		 */
 		if (NULL == bd) {
 			DBG(1, "null BD\n");
+			tx_ram->tx_complete = 0;
 			continue;
 		}
 
@@ -1412,15 +1417,6 @@
 
 	if (cppi_ch->transmit) {
 		struct cppi_tx_stateram __iomem *tx_ram;
-		int			enabled;
-
-		/* mask interrupts raised to signal teardown complete.  */
-		enabled = musb_readl(tibase, DAVINCI_TXCPPI_INTENAB_REG)
-				& (1 << cppi_ch->index);
-		if (enabled)
-			musb_writel(tibase, DAVINCI_TXCPPI_INTCLR_REG,
-					(1 << cppi_ch->index));
-
 		/* REVISIT put timeouts on these controller handshakes */
 
 		cppi_dump_tx(6, cppi_ch, " (teardown)");
@@ -1435,7 +1431,6 @@
 		do {
 			value = musb_readl(&tx_ram->tx_complete, 0);
 		} while (0xFFFFFFFC != value);
-		musb_writel(&tx_ram->tx_complete, 0, 0xFFFFFFFC);
 
 		/* FIXME clean up the transfer state ... here?
 		 * the completion routine should get called with
@@ -1448,23 +1443,15 @@
 		musb_writew(regs, MUSB_TXCSR, value);
 		musb_writew(regs, MUSB_TXCSR, value);
 
-		/* While we scrub the TX state RAM, ensure that we clean
-		 * up any interrupt that's currently asserted:
+		/*
 		 * 1. Write to completion Ptr value 0x1(bit 0 set)
 		 *    (write back mode)
-		 * 2. Write to completion Ptr value 0x0(bit 0 cleared)
-		 *    (compare mode)
-		 * Value written is compared(for bits 31:2) and when
-		 * equal, interrupt is deasserted.
+		 * 2. Wait for abort interrupt and then put the channel in
+		 *    compare mode by writing 1 to the tx_complete register.
 		 */
 		cppi_reset_tx(tx_ram, 1);
-		musb_writel(&tx_ram->tx_complete, 0, 0);
-
-		/* re-enable interrupt */
-		if (enabled)
-			musb_writel(tibase, DAVINCI_TXCPPI_INTENAB_REG,
-					(1 << cppi_ch->index));
-
+		cppi_ch->head = 0;
+		musb_writel(&tx_ram->tx_complete, 0, 1);
 		cppi_dump_tx(5, cppi_ch, " (done teardown)");
 
 		/* REVISIT tx side _should_ clean up the same way
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 6691381..a883f9d 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -274,7 +274,7 @@
 	/* NOTE: DaVinci shadows the Mentor IRQs.  Don't manage them through
 	 * the Mentor registers (except for setup), use the TI ones and EOI.
 	 *
-	 * Docs describe irq "vector" registers asociated with the CPPI and
+	 * Docs describe irq "vector" registers associated with the CPPI and
 	 * USB EOI registers.  These hold a bitmask corresponding to the
 	 * current IRQ, not an irq handler address.  Would using those bits
 	 * resolve some of the races observed in this dispatch code??
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 738efd8..b4bbf8f 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -557,6 +557,69 @@
 		handled = IRQ_HANDLED;
 	}
 
+
+	if (int_usb & MUSB_INTR_SUSPEND) {
+		DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
+				otg_state_string(musb), devctl, power);
+		handled = IRQ_HANDLED;
+
+		switch (musb->xceiv->state) {
+#ifdef	CONFIG_USB_MUSB_OTG
+		case OTG_STATE_A_PERIPHERAL:
+			/* We also come here if the cable is removed, since
+			 * this silicon doesn't report ID-no-longer-grounded.
+			 *
+			 * We depend on T(a_wait_bcon) to shut us down, and
+			 * hope users don't do anything dicey during this
+			 * undesired detour through A_WAIT_BCON.
+			 */
+			musb_hnp_stop(musb);
+			usb_hcd_resume_root_hub(musb_to_hcd(musb));
+			musb_root_disconnect(musb);
+			musb_platform_try_idle(musb, jiffies
+					+ msecs_to_jiffies(musb->a_wait_bcon
+						? : OTG_TIME_A_WAIT_BCON));
+
+			break;
+#endif
+		case OTG_STATE_B_IDLE:
+			if (!musb->is_active)
+				break;
+		case OTG_STATE_B_PERIPHERAL:
+			musb_g_suspend(musb);
+			musb->is_active = is_otg_enabled(musb)
+					&& musb->xceiv->gadget->b_hnp_enable;
+			if (musb->is_active) {
+#ifdef	CONFIG_USB_MUSB_OTG
+				musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
+				DBG(1, "HNP: Setting timer for b_ase0_brst\n");
+				mod_timer(&musb->otg_timer, jiffies
+					+ msecs_to_jiffies(
+							OTG_TIME_B_ASE0_BRST));
+#endif
+			}
+			break;
+		case OTG_STATE_A_WAIT_BCON:
+			if (musb->a_wait_bcon != 0)
+				musb_platform_try_idle(musb, jiffies
+					+ msecs_to_jiffies(musb->a_wait_bcon));
+			break;
+		case OTG_STATE_A_HOST:
+			musb->xceiv->state = OTG_STATE_A_SUSPEND;
+			musb->is_active = is_otg_enabled(musb)
+					&& musb->xceiv->host->b_hnp_enable;
+			break;
+		case OTG_STATE_B_HOST:
+			/* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
+			DBG(1, "REVISIT: SUSPEND as B_HOST\n");
+			break;
+		default:
+			/* "should not happen" */
+			musb->is_active = 0;
+			break;
+		}
+	}
+
 	if (int_usb & MUSB_INTR_CONNECT) {
 		struct usb_hcd *hcd = musb_to_hcd(musb);
 
@@ -625,136 +688,6 @@
 	}
 #endif	/* CONFIG_USB_MUSB_HDRC_HCD */
 
-	/* mentor saves a bit: bus reset and babble share the same irq.
-	 * only host sees babble; only peripheral sees bus reset.
-	 */
-	if (int_usb & MUSB_INTR_RESET) {
-		if (is_host_capable() && (devctl & MUSB_DEVCTL_HM) != 0) {
-			/*
-			 * Looks like non-HS BABBLE can be ignored, but
-			 * HS BABBLE is an error condition. For HS the solution
-			 * is to avoid babble in the first place and fix what
-			 * caused BABBLE. When HS BABBLE happens we can only
-			 * stop the session.
-			 */
-			if (devctl & (MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV))
-				DBG(1, "BABBLE devctl: %02x\n", devctl);
-			else {
-				ERR("Stopping host session -- babble\n");
-				musb_writeb(mbase, MUSB_DEVCTL, 0);
-			}
-		} else if (is_peripheral_capable()) {
-			DBG(1, "BUS RESET as %s\n", otg_state_string(musb));
-			switch (musb->xceiv->state) {
-#ifdef CONFIG_USB_OTG
-			case OTG_STATE_A_SUSPEND:
-				/* We need to ignore disconnect on suspend
-				 * otherwise tusb 2.0 won't reconnect after a
-				 * power cycle, which breaks otg compliance.
-				 */
-				musb->ignore_disconnect = 1;
-				musb_g_reset(musb);
-				/* FALLTHROUGH */
-			case OTG_STATE_A_WAIT_BCON:	/* OPT TD.4.7-900ms */
-				/* never use invalid T(a_wait_bcon) */
-				DBG(1, "HNP: in %s, %d msec timeout\n",
-						otg_state_string(musb),
-						TA_WAIT_BCON(musb));
-				mod_timer(&musb->otg_timer, jiffies
-					+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
-				break;
-			case OTG_STATE_A_PERIPHERAL:
-				musb->ignore_disconnect = 0;
-				del_timer(&musb->otg_timer);
-				musb_g_reset(musb);
-				break;
-			case OTG_STATE_B_WAIT_ACON:
-				DBG(1, "HNP: RESET (%s), to b_peripheral\n",
-					otg_state_string(musb));
-				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
-				musb_g_reset(musb);
-				break;
-#endif
-			case OTG_STATE_B_IDLE:
-				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
-				/* FALLTHROUGH */
-			case OTG_STATE_B_PERIPHERAL:
-				musb_g_reset(musb);
-				break;
-			default:
-				DBG(1, "Unhandled BUS RESET as %s\n",
-					otg_state_string(musb));
-			}
-		}
-
-		handled = IRQ_HANDLED;
-	}
-	schedule_work(&musb->irq_work);
-
-	return handled;
-}
-
-/*
- * Interrupt Service Routine to record USB "global" interrupts.
- * Since these do not happen often and signify things of
- * paramount importance, it seems OK to check them individually;
- * the order of the tests is specified in the manual
- *
- * @param musb instance pointer
- * @param int_usb register contents
- * @param devctl
- * @param power
- */
-static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
-				u8 devctl, u8 power)
-{
-	irqreturn_t handled = IRQ_NONE;
-
-#if 0
-/* REVISIT ... this would be for multiplexing periodic endpoints, or
- * supporting transfer phasing to prevent exceeding ISO bandwidth
- * limits of a given frame or microframe.
- *
- * It's not needed for peripheral side, which dedicates endpoints;
- * though it _might_ use SOF irqs for other purposes.
- *
- * And it's not currently needed for host side, which also dedicates
- * endpoints, relies on TX/RX interval registers, and isn't claimed
- * to support ISO transfers yet.
- */
-	if (int_usb & MUSB_INTR_SOF) {
-		void __iomem *mbase = musb->mregs;
-		struct musb_hw_ep	*ep;
-		u8 epnum;
-		u16 frame;
-
-		DBG(6, "START_OF_FRAME\n");
-		handled = IRQ_HANDLED;
-
-		/* start any periodic Tx transfers waiting for current frame */
-		frame = musb_readw(mbase, MUSB_FRAME);
-		ep = musb->endpoints;
-		for (epnum = 1; (epnum < musb->nr_endpoints)
-					&& (musb->epmask >= (1 << epnum));
-				epnum++, ep++) {
-			/*
-			 * FIXME handle framecounter wraps (12 bits)
-			 * eliminate duplicated StartUrb logic
-			 */
-			if (ep->dwWaitFrame >= frame) {
-				ep->dwWaitFrame = 0;
-				pr_debug("SOF --> periodic TX%s on %d\n",
-					ep->tx_channel ? " DMA" : "",
-					epnum);
-				if (!ep->tx_channel)
-					musb_h_tx_start(musb, epnum);
-				else
-					cppi_hostdma_start(musb, epnum);
-			}
-		}		/* end of for loop */
-	}
-#endif
-
 	if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
 		DBG(1, "DISCONNECT (%s) as %s, devctl %02x\n",
 				otg_state_string(musb),
@@ -803,69 +736,118 @@
 				otg_state_string(musb));
 			break;
 		}
-
-		schedule_work(&musb->irq_work);
 	}
 
-	if (int_usb & MUSB_INTR_SUSPEND) {
-		DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
-				otg_state_string(musb), devctl, power);
+	/* mentor saves a bit: bus reset and babble share the same irq.
+	 * only host sees babble; only peripheral sees bus reset.
+	 */
+	if (int_usb & MUSB_INTR_RESET) {
+		handled = IRQ_HANDLED;
+		if (is_host_capable() && (devctl & MUSB_DEVCTL_HM) != 0) {
+			/*
+			 * Looks like non-HS BABBLE can be ignored, but
+			 * HS BABBLE is an error condition. For HS the solution
+			 * is to avoid babble in the first place and fix what
+			 * caused BABBLE. When HS BABBLE happens we can only
+			 * stop the session.
+			 */
+			if (devctl & (MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV))
+				DBG(1, "BABBLE devctl: %02x\n", devctl);
+			else {
+				ERR("Stopping host session -- babble\n");
+				musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+			}
+		} else if (is_peripheral_capable()) {
+			DBG(1, "BUS RESET as %s\n", otg_state_string(musb));
+			switch (musb->xceiv->state) {
+#ifdef CONFIG_USB_OTG
+			case OTG_STATE_A_SUSPEND:
+				/* We need to ignore disconnect on suspend
+				 * otherwise tusb 2.0 won't reconnect after a
+				 * power cycle, which breaks otg compliance.
+				 */
+				musb->ignore_disconnect = 1;
+				musb_g_reset(musb);
+				/* FALLTHROUGH */
+			case OTG_STATE_A_WAIT_BCON:	/* OPT TD.4.7-900ms */
+				/* never use invalid T(a_wait_bcon) */
+				DBG(1, "HNP: in %s, %d msec timeout\n",
+						otg_state_string(musb),
+						TA_WAIT_BCON(musb));
+				mod_timer(&musb->otg_timer, jiffies
+					+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
+				break;
+			case OTG_STATE_A_PERIPHERAL:
+				musb->ignore_disconnect = 0;
+				del_timer(&musb->otg_timer);
+				musb_g_reset(musb);
+				break;
+			case OTG_STATE_B_WAIT_ACON:
+				DBG(1, "HNP: RESET (%s), to b_peripheral\n",
+					otg_state_string(musb));
+				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+				musb_g_reset(musb);
+				break;
+#endif
+			case OTG_STATE_B_IDLE:
+				musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+				/* FALLTHROUGH */
+			case OTG_STATE_B_PERIPHERAL:
+				musb_g_reset(musb);
+				break;
+			default:
+				DBG(1, "Unhandled BUS RESET as %s\n",
+					otg_state_string(musb));
+			}
+		}
+	}
+
+#if 0
+/* REVISIT ... this would be for multiplexing periodic endpoints, or
+ * supporting transfer phasing to prevent exceeding ISO bandwidth
+ * limits of a given frame or microframe.
+ *
+ * It's not needed for peripheral side, which dedicates endpoints;
+ * though it _might_ use SOF irqs for other purposes.
+ *
+ * And it's not currently needed for host side, which also dedicates
+ * endpoints, relies on TX/RX interval registers, and isn't claimed
+ * to support ISO transfers yet.
+ */
+	if (int_usb & MUSB_INTR_SOF) {
+		void __iomem *mbase = musb->mregs;
+		struct musb_hw_ep	*ep;
+		u8 epnum;
+		u16 frame;
+
+		DBG(6, "START_OF_FRAME\n");
 		handled = IRQ_HANDLED;
 
-		switch (musb->xceiv->state) {
-#ifdef	CONFIG_USB_MUSB_OTG
-		case OTG_STATE_A_PERIPHERAL:
-			/* We also come here if the cable is removed, since
-			 * this silicon doesn't report ID-no-longer-grounded.
-			 *
-			 * We depend on T(a_wait_bcon) to shut us down, and
-			 * hope users don't do anything dicey during this
-			 * undesired detour through A_WAIT_BCON.
+		/* start any periodic Tx transfers waiting for current frame */
+		frame = musb_readw(mbase, MUSB_FRAME);
+		ep = musb->endpoints;
+		for (epnum = 1; (epnum < musb->nr_endpoints)
+					&& (musb->epmask >= (1 << epnum));
+				epnum++, ep++) {
+			/*
+			 * FIXME handle framecounter wraps (12 bits)
+			 * eliminate duplicated StartUrb logic
 			 */
-			musb_hnp_stop(musb);
-			usb_hcd_resume_root_hub(musb_to_hcd(musb));
-			musb_root_disconnect(musb);
-			musb_platform_try_idle(musb, jiffies
-					+ msecs_to_jiffies(musb->a_wait_bcon
-						? : OTG_TIME_A_WAIT_BCON));
-			break;
-#endif
-		case OTG_STATE_B_PERIPHERAL:
-			musb_g_suspend(musb);
-			musb->is_active = is_otg_enabled(musb)
-					&& musb->xceiv->gadget->b_hnp_enable;
-			if (musb->is_active) {
-#ifdef	CONFIG_USB_MUSB_OTG
-				musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
-				DBG(1, "HNP: Setting timer for b_ase0_brst\n");
-				mod_timer(&musb->otg_timer, jiffies
-					+ msecs_to_jiffies(
-							OTG_TIME_B_ASE0_BRST));
-#endif
+			if (ep->dwWaitFrame >= frame) {
+				ep->dwWaitFrame = 0;
+				pr_debug("SOF --> periodic TX%s on %d\n",
+					ep->tx_channel ? " DMA" : "",
+					epnum);
+				if (!ep->tx_channel)
+					musb_h_tx_start(musb, epnum);
+				else
+					cppi_hostdma_start(musb, epnum);
 			}
-			break;
-		case OTG_STATE_A_WAIT_BCON:
-			if (musb->a_wait_bcon != 0)
-				musb_platform_try_idle(musb, jiffies
-					+ msecs_to_jiffies(musb->a_wait_bcon));
-			break;
-		case OTG_STATE_A_HOST:
-			musb->xceiv->state = OTG_STATE_A_SUSPEND;
-			musb->is_active = is_otg_enabled(musb)
-					&& musb->xceiv->host->b_hnp_enable;
-			break;
-		case OTG_STATE_B_HOST:
-			/* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
-			DBG(1, "REVISIT: SUSPEND as B_HOST\n");
-			break;
-		default:
-			/* "should not happen" */
-			musb->is_active = 0;
-			break;
-		}
-		schedule_work(&musb->irq_work);
+		}		/* end of for loop */
 	}
+#endif
 
+	schedule_work(&musb->irq_work);
 
 	return handled;
 }
@@ -1095,6 +1077,36 @@
 { .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, },
 };
 
+/* mode 5 - fits in 8KB */
+static struct fifo_cfg __initdata mode_5_cfg[] = {
+{ .hw_ep_num =  1, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  1, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  2, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  2, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  3, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  3, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  4, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  4, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  5, .style = FIFO_TX,   .maxpacket = 512, },
+{ .hw_ep_num =  5, .style = FIFO_RX,   .maxpacket = 512, },
+{ .hw_ep_num =  6, .style = FIFO_TX,   .maxpacket = 32, },
+{ .hw_ep_num =  6, .style = FIFO_RX,   .maxpacket = 32, },
+{ .hw_ep_num =  7, .style = FIFO_TX,   .maxpacket = 32, },
+{ .hw_ep_num =  7, .style = FIFO_RX,   .maxpacket = 32, },
+{ .hw_ep_num =  8, .style = FIFO_TX,   .maxpacket = 32, },
+{ .hw_ep_num =  8, .style = FIFO_RX,   .maxpacket = 32, },
+{ .hw_ep_num =  9, .style = FIFO_TX,   .maxpacket = 32, },
+{ .hw_ep_num =  9, .style = FIFO_RX,   .maxpacket = 32, },
+{ .hw_ep_num = 10, .style = FIFO_TX,   .maxpacket = 32, },
+{ .hw_ep_num = 10, .style = FIFO_RX,   .maxpacket = 32, },
+{ .hw_ep_num = 11, .style = FIFO_TX,   .maxpacket = 32, },
+{ .hw_ep_num = 11, .style = FIFO_RX,   .maxpacket = 32, },
+{ .hw_ep_num = 12, .style = FIFO_TX,   .maxpacket = 32, },
+{ .hw_ep_num = 12, .style = FIFO_RX,   .maxpacket = 32, },
+{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 512, },
+{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, },
+{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, },
+};
 
 /*
  * configure a fifo; for non-shared endpoints, this may be called
@@ -1210,6 +1222,10 @@
 		cfg = mode_4_cfg;
 		n = ARRAY_SIZE(mode_4_cfg);
 		break;
+	case 5:
+		cfg = mode_5_cfg;
+		n = ARRAY_SIZE(mode_5_cfg);
+		break;
 	}
 
 	printk(KERN_DEBUG "%s: setup fifo_mode %d\n",
@@ -1314,9 +1330,6 @@
  */
 static int __init musb_core_init(u16 musb_type, struct musb *musb)
 {
-#ifdef MUSB_AHB_ID
-	u32 data;
-#endif
 	u8 reg;
 	char *type;
 	char aInfo[90], aRevision[32], aDate[12];
@@ -1328,23 +1341,17 @@
 	reg = musb_read_configdata(mbase);
 
 	strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8");
-	if (reg & MUSB_CONFIGDATA_DYNFIFO)
+	if (reg & MUSB_CONFIGDATA_DYNFIFO) {
 		strcat(aInfo, ", dyn FIFOs");
+		musb->dyn_fifo = true;
+	}
 	if (reg & MUSB_CONFIGDATA_MPRXE) {
 		strcat(aInfo, ", bulk combine");
-#ifdef C_MP_RX
 		musb->bulk_combine = true;
-#else
-		strcat(aInfo, " (X)");		/* no driver support */
-#endif
 	}
 	if (reg & MUSB_CONFIGDATA_MPTXE) {
 		strcat(aInfo, ", bulk split");
-#ifdef C_MP_TX
 		musb->bulk_split = true;
-#else
-		strcat(aInfo, " (X)");		/* no driver support */
-#endif
 	}
 	if (reg & MUSB_CONFIGDATA_HBRXE) {
 		strcat(aInfo, ", HB-ISO Rx");
@@ -1360,20 +1367,7 @@
 	printk(KERN_DEBUG "%s: ConfigData=0x%02x (%s)\n",
 			musb_driver_name, reg, aInfo);
 
-#ifdef MUSB_AHB_ID
-	data = musb_readl(mbase, 0x404);
-	sprintf(aDate, "%04d-%02x-%02x", (data & 0xffff),
-		(data >> 16) & 0xff, (data >> 24) & 0xff);
-	/* FIXME ID2 and ID3 are unused */
-	data = musb_readl(mbase, 0x408);
-	printk(KERN_DEBUG "ID2=%lx\n", (long unsigned)data);
-	data = musb_readl(mbase, 0x40c);
-	printk(KERN_DEBUG "ID3=%lx\n", (long unsigned)data);
-	reg = musb_readb(mbase, 0x400);
-	musb_type = ('M' == reg) ? MUSB_CONTROLLER_MHDRC : MUSB_CONTROLLER_HDRC;
-#else
 	aDate[0] = 0;
-#endif
 	if (MUSB_CONTROLLER_MHDRC == musb_type) {
 		musb->is_multipoint = 1;
 		type = "M";
@@ -1404,21 +1398,10 @@
 	musb->nr_endpoints = 1;
 	musb->epmask = 1;
 
-	if (reg & MUSB_CONFIGDATA_DYNFIFO) {
-		if (musb->config->dyn_fifo)
-			status = ep_config_from_table(musb);
-		else {
-			ERR("reconfigure software for Dynamic FIFOs\n");
-			status = -ENODEV;
-		}
-	} else {
-		if (!musb->config->dyn_fifo)
-			status = ep_config_from_hw(musb);
-		else {
-			ERR("reconfigure software for static FIFOs\n");
-			return -ENODEV;
-		}
-	}
+	if (musb->dyn_fifo)
+		status = ep_config_from_table(musb);
+	else
+		status = ep_config_from_hw(musb);
 
 	if (status < 0)
 		return status;
@@ -1587,11 +1570,6 @@
 		ep_num++;
 	}
 
-	/* finish handling "global" interrupts after handling fifos */
-	if (musb->int_usb)
-		retval |= musb_stage2_irq(musb,
-				musb->int_usb, devctl, power);
-
 	return retval;
 }
 
@@ -1696,7 +1674,7 @@
 	unsigned long	val;
 
 	if (sscanf(buf, "%lu", &val) < 1) {
-		printk(KERN_ERR "Invalid VBUS timeout ms value\n");
+		dev_err(dev, "Invalid VBUS timeout ms value\n");
 		return -EINVAL;
 	}
 
@@ -1746,7 +1724,7 @@
 
 	if (sscanf(buf, "%hu", &srp) != 1
 			|| (srp != 1)) {
-		printk(KERN_ERR "SRP: Value must be 1\n");
+		dev_err(dev, "SRP: Value must be 1\n");
 		return -EINVAL;
 	}
 
@@ -1759,6 +1737,19 @@
 
 #endif /* CONFIG_USB_GADGET_MUSB_HDRC */
 
+static struct attribute *musb_attributes[] = {
+	&dev_attr_mode.attr,
+	&dev_attr_vbus.attr,
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+	&dev_attr_srp.attr,
+#endif
+	NULL
+};
+
+static const struct attribute_group musb_attr_group = {
+	.attrs = musb_attributes,
+};
+
 #endif	/* sysfs */
 
 /* Only used to provide driver mode change events */
@@ -1833,11 +1824,7 @@
 	 */
 
 #ifdef CONFIG_SYSFS
-	device_remove_file(musb->controller, &dev_attr_mode);
-	device_remove_file(musb->controller, &dev_attr_vbus);
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-	device_remove_file(musb->controller, &dev_attr_srp);
-#endif
+	sysfs_remove_group(&musb->controller->kobj, &musb_attr_group);
 #endif
 
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
@@ -2017,22 +2004,10 @@
 		musb->irq_wake = 0;
 	}
 
-	pr_info("%s: USB %s mode controller at %p using %s, IRQ %d\n",
-			musb_driver_name,
-			({char *s;
-			switch (musb->board_mode) {
-			case MUSB_HOST:		s = "Host"; break;
-			case MUSB_PERIPHERAL:	s = "Peripheral"; break;
-			default:		s = "OTG"; break;
-			}; s; }),
-			ctrl,
-			(is_dma_capable() && musb->dma_controller)
-				? "DMA" : "PIO",
-			musb->nIrq);
-
 	/* host side needs more setup */
 	if (is_host_enabled(musb)) {
 		struct usb_hcd	*hcd = musb_to_hcd(musb);
+		u8 busctl;
 
 		otg_set_host(musb->xceiv, &hcd->self);
 
@@ -2040,6 +2015,13 @@
 			hcd->self.otg_port = 1;
 		musb->xceiv->host = &hcd->self;
 		hcd->power_budget = 2 * (plat->power ? : 250);
+
+		/* program PHY to use external vBus if required */
+		if (plat->extvbus) {
+			busctl = musb_readb(musb->mregs, MUSB_ULPI_BUSCONTROL);
+			busctl |= MUSB_ULPI_USE_EXTVBUS;
+			musb_writeb(musb->mregs, MUSB_ULPI_BUSCONTROL, busctl);
+		}
 	}
 
 	/* For the host-only role, we can activate right away.
@@ -2079,26 +2061,26 @@
 	}
 
 #ifdef CONFIG_SYSFS
-	status = device_create_file(dev, &dev_attr_mode);
-	status = device_create_file(dev, &dev_attr_vbus);
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-	status = device_create_file(dev, &dev_attr_srp);
-#endif /* CONFIG_USB_GADGET_MUSB_HDRC */
-	status = 0;
+	status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);
 #endif
 	if (status)
 		goto fail2;
 
+	dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",
+			({char *s;
+			 switch (musb->board_mode) {
+			 case MUSB_HOST:		s = "Host"; break;
+			 case MUSB_PERIPHERAL:	s = "Peripheral"; break;
+			 default:		s = "OTG"; break;
+			 }; s; }),
+			ctrl,
+			(is_dma_capable() && musb->dma_controller)
+			? "DMA" : "PIO",
+			musb->nIrq);
+
 	return 0;
 
 fail2:
-#ifdef CONFIG_SYSFS
-	device_remove_file(musb->controller, &dev_attr_mode);
-	device_remove_file(musb->controller, &dev_attr_vbus);
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-	device_remove_file(musb->controller, &dev_attr_srp);
-#endif
-#endif
 	musb_platform_exit(musb);
 fail:
 	dev_err(musb->controller,
@@ -2127,6 +2109,7 @@
 {
 	struct device	*dev = &pdev->dev;
 	int		irq = platform_get_irq(pdev, 0);
+	int		status;
 	struct resource	*iomem;
 	void __iomem	*base;
 
@@ -2134,7 +2117,7 @@
 	if (!iomem || irq == 0)
 		return -ENODEV;
 
-	base = ioremap(iomem->start, iomem->end - iomem->start + 1);
+	base = ioremap(iomem->start, resource_size(iomem));
 	if (!base) {
 		dev_err(dev, "ioremap failed\n");
 		return -ENOMEM;
@@ -2144,7 +2127,12 @@
 	/* clobbered by use_dma=n */
 	orig_dma_mask = dev->dma_mask;
 #endif
-	return musb_init_controller(dev, irq, base);
+
+	status = musb_init_controller(dev, irq, base);
+	if (status < 0)
+		iounmap(base);
+
+	return status;
 }
 
 static int __exit musb_remove(struct platform_device *pdev)
@@ -2173,6 +2161,148 @@
 
 #ifdef	CONFIG_PM
 
+static struct musb_context_registers musb_context;
+
+void musb_save_context(struct musb *musb)
+{
+	int i;
+	void __iomem *musb_base = musb->mregs;
+
+	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.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_C_NUM_EPS; ++i) {
+		musb_writeb(musb_base, MUSB_INDEX, i);
+		musb_context.index_regs[i].txmaxp =
+			musb_readw(musb_base, 0x10 + MUSB_TXMAXP);
+		musb_context.index_regs[i].txcsr =
+			musb_readw(musb_base, 0x10 + MUSB_TXCSR);
+		musb_context.index_regs[i].rxmaxp =
+			musb_readw(musb_base, 0x10 + MUSB_RXMAXP);
+		musb_context.index_regs[i].rxcsr =
+			musb_readw(musb_base, 0x10 + MUSB_RXCSR);
+
+		if (musb->dyn_fifo) {
+			musb_context.index_regs[i].txfifoadd =
+					musb_read_txfifoadd(musb_base);
+			musb_context.index_regs[i].rxfifoadd =
+					musb_read_rxfifoadd(musb_base);
+			musb_context.index_regs[i].txfifosz =
+					musb_read_txfifosz(musb_base);
+			musb_context.index_regs[i].rxfifosz =
+					musb_read_rxfifosz(musb_base);
+		}
+		if (is_host_enabled(musb)) {
+			musb_context.index_regs[i].txtype =
+				musb_readb(musb_base, 0x10 + MUSB_TXTYPE);
+			musb_context.index_regs[i].txinterval =
+				musb_readb(musb_base, 0x10 + MUSB_TXINTERVAL);
+			musb_context.index_regs[i].rxtype =
+				musb_readb(musb_base, 0x10 + MUSB_RXTYPE);
+			musb_context.index_regs[i].rxinterval =
+				musb_readb(musb_base, 0x10 + MUSB_RXINTERVAL);
+
+			musb_context.index_regs[i].txfunaddr =
+				musb_read_txfunaddr(musb_base, i);
+			musb_context.index_regs[i].txhubaddr =
+				musb_read_txhubaddr(musb_base, i);
+			musb_context.index_regs[i].txhubport =
+				musb_read_txhubport(musb_base, i);
+
+			musb_context.index_regs[i].rxfunaddr =
+				musb_read_rxfunaddr(musb_base, i);
+			musb_context.index_regs[i].rxhubaddr =
+				musb_read_rxhubaddr(musb_base, i);
+			musb_context.index_regs[i].rxhubport =
+				musb_read_rxhubport(musb_base, i);
+		}
+	}
+
+	musb_writeb(musb_base, MUSB_INDEX, musb_context.index);
+
+	musb_platform_save_context(musb, &musb_context);
+}
+
+void musb_restore_context(struct musb *musb)
+{
+	int i;
+	void __iomem *musb_base = musb->mregs;
+	void __iomem *ep_target_regs;
+
+	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_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_C_NUM_EPS; ++i) {
+		musb_writeb(musb_base, MUSB_INDEX, i);
+		musb_writew(musb_base, 0x10 + MUSB_TXMAXP,
+			musb_context.index_regs[i].txmaxp);
+		musb_writew(musb_base, 0x10 + MUSB_TXCSR,
+			musb_context.index_regs[i].txcsr);
+		musb_writew(musb_base, 0x10 + MUSB_RXMAXP,
+			musb_context.index_regs[i].rxmaxp);
+		musb_writew(musb_base, 0x10 + MUSB_RXCSR,
+			musb_context.index_regs[i].rxcsr);
+
+		if (musb->dyn_fifo) {
+			musb_write_txfifosz(musb_base,
+				musb_context.index_regs[i].txfifosz);
+			musb_write_rxfifosz(musb_base,
+				musb_context.index_regs[i].rxfifosz);
+			musb_write_txfifoadd(musb_base,
+				musb_context.index_regs[i].txfifoadd);
+			musb_write_rxfifoadd(musb_base,
+				musb_context.index_regs[i].rxfifoadd);
+		}
+
+		if (is_host_enabled(musb)) {
+			musb_writeb(musb_base, 0x10 + MUSB_TXTYPE,
+				musb_context.index_regs[i].txtype);
+			musb_writeb(musb_base, 0x10 + MUSB_TXINTERVAL,
+				musb_context.index_regs[i].txinterval);
+			musb_writeb(musb_base, 0x10 + MUSB_RXTYPE,
+				musb_context.index_regs[i].rxtype);
+			musb_writeb(musb_base, 0x10 + MUSB_RXINTERVAL,
+
+			musb_context.index_regs[i].rxinterval);
+			musb_write_txfunaddr(musb_base, i,
+				musb_context.index_regs[i].txfunaddr);
+			musb_write_txhubaddr(musb_base, i,
+				musb_context.index_regs[i].txhubaddr);
+			musb_write_txhubport(musb_base, i,
+				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_write_rxhubaddr(ep_target_regs,
+				musb_context.index_regs[i].rxhubaddr);
+			musb_write_rxhubport(ep_target_regs,
+				musb_context.index_regs[i].rxhubport);
+		}
+	}
+
+	musb_writeb(musb_base, MUSB_INDEX, musb_context.index);
+}
+
 static int musb_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -2194,6 +2324,8 @@
 		 */
 	}
 
+	musb_save_context(musb);
+
 	if (musb->set_clock)
 		musb->set_clock(musb->clock, 0);
 	else
@@ -2215,6 +2347,8 @@
 	else
 		clk_enable(musb->clock);
 
+	musb_restore_context(musb);
+
 	/* for static cmos like DaVinci, register values were preserved
 	 * unless for some reason the whole soc powered down or the USB
 	 * module got reset through the PSC (vs just being disabled).
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 5514c7e..d849fb8 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -52,6 +52,15 @@
 struct musb_hw_ep;
 struct musb_ep;
 
+/* Helper defines for struct musb->hwvers */
+#define MUSB_HWVERS_MAJOR(x)	((x >> 10) & 0x1f)
+#define MUSB_HWVERS_MINOR(x)	(x & 0x3ff)
+#define MUSB_HWVERS_RC		0x8000
+#define MUSB_HWVERS_1300	0x52C
+#define MUSB_HWVERS_1400	0x590
+#define MUSB_HWVERS_1800	0x720
+#define MUSB_HWVERS_1900	0x784
+#define MUSB_HWVERS_2000	0x800
 
 #include "musb_debug.h"
 #include "musb_dma.h"
@@ -322,13 +331,6 @@
 	struct clk		*clock;
 	irqreturn_t		(*isr)(int, void *);
 	struct work_struct	irq_work;
-#define MUSB_HWVERS_MAJOR(x)	((x >> 10) & 0x1f)
-#define MUSB_HWVERS_MINOR(x)	(x & 0x3ff)
-#define MUSB_HWVERS_RC		0x8000
-#define MUSB_HWVERS_1300	0x52C
-#define MUSB_HWVERS_1400	0x590
-#define MUSB_HWVERS_1800	0x720
-#define MUSB_HWVERS_2000	0x800
 	u16			hwvers;
 
 /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
@@ -411,22 +413,15 @@
 
 	unsigned		hb_iso_rx:1;	/* high bandwidth iso rx? */
 	unsigned		hb_iso_tx:1;	/* high bandwidth iso tx? */
+	unsigned		dyn_fifo:1;	/* dynamic FIFO supported? */
 
-#ifdef C_MP_TX
-	unsigned bulk_split:1;
+	unsigned		bulk_split:1;
 #define	can_bulk_split(musb,type) \
-		(((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split)
-#else
-#define	can_bulk_split(musb, type)	0
-#endif
+	(((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split)
 
-#ifdef C_MP_RX
-	unsigned bulk_combine:1;
+	unsigned		bulk_combine:1;
 #define	can_bulk_combine(musb,type) \
-		(((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine)
-#else
-#define	can_bulk_combine(musb, type)	0
-#endif
+	(((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine)
 
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	/* is_suspended means USB B_PERIPHERAL suspend */
@@ -461,6 +456,45 @@
 #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_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430)
+	u32 otg_sysconfig, otg_forcestandby;
+#endif
+	u8 power;
+	u16 intrtxe, intrrxe;
+	u8 intrusbe;
+	u16 frame;
+	u8 index, testmode;
+
+	u8 devctl, misc;
+
+	struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
+};
+
+#if defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP2430)
+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);
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index cbcf14a2..a9f288c 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -895,7 +895,14 @@
 		/* REVISIT if can_bulk_split(), use by updating "tmp";
 		 * likewise high bandwidth periodic tx
 		 */
-		musb_writew(regs, MUSB_TXMAXP, tmp);
+		/* Set TXMAXP with the FIFO size of the endpoint
+		 * to disable double buffering mode. Currently, It seems that double
+		 * buffering has problem if musb RTL revision number < 2.0.
+		 */
+		if (musb->hwvers < MUSB_HWVERS_2000)
+			musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx);
+		else
+			musb_writew(regs, MUSB_TXMAXP, tmp);
 
 		csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG;
 		if (musb_readw(regs, MUSB_TXCSR)
@@ -925,7 +932,13 @@
 		/* REVISIT if can_bulk_combine() use by updating "tmp"
 		 * likewise high bandwidth periodic rx
 		 */
-		musb_writew(regs, MUSB_RXMAXP, tmp);
+		/* Set RXMAXP with the FIFO size of the endpoint
+		 * to disable double buffering mode.
+		 */
+		if (musb->hwvers < MUSB_HWVERS_2000)
+			musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx);
+		else
+			musb_writew(regs, MUSB_RXMAXP, tmp);
 
 		/* force shared fifo to OUT-only mode */
 		if (hw_ep->is_shared_fifo) {
@@ -1697,8 +1710,7 @@
 		return -EINVAL;
 
 	/* driver must be initialized to support peripheral mode */
-	if (!musb || !(musb->board_mode == MUSB_OTG
-				|| musb->board_mode != MUSB_OTG)) {
+	if (!musb) {
 		DBG(1, "%s, no dev??\n", __func__);
 		return -ENODEV;
 	}
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 74c4c36..3421cf9 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -605,8 +605,14 @@
 	musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg);
 	musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg);
 	/* NOTE: bulk combining rewrites high bits of maxpacket */
-	musb_writew(ep->regs, MUSB_RXMAXP,
-			qh->maxpacket | ((qh->hb_mult - 1) << 11));
+	/* Set RXMAXP with the FIFO size of the endpoint
+	 * to disable double buffer mode.
+	 */
+	if (musb->hwvers < MUSB_HWVERS_2000)
+		musb_writew(ep->regs, MUSB_RXMAXP, ep->max_packet_sz_rx);
+	else
+		musb_writew(ep->regs, MUSB_RXMAXP,
+				qh->maxpacket | ((qh->hb_mult - 1) << 11));
 
 	ep->rx_reinit = 0;
 }
@@ -1771,6 +1777,9 @@
 	int			best_end, epnum;
 	struct musb_hw_ep	*hw_ep = NULL;
 	struct list_head	*head = NULL;
+	u8			toggle;
+	u8			txtype;
+	struct urb		*urb = next_urb(qh);
 
 	/* use fixed hardware for control and bulk */
 	if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
@@ -1809,6 +1818,27 @@
 		diff -= (qh->maxpacket * qh->hb_mult);
 
 		if (diff >= 0 && best_diff > diff) {
+
+			/*
+			 * Mentor controller has a bug in that if we schedule
+			 * a BULK Tx transfer on an endpoint that had earlier
+			 * handled ISOC then the BULK transfer has to start on
+			 * a zero toggle.  If the BULK transfer starts on a 1
+			 * toggle then this transfer will fail as the mentor
+			 * controller starts the Bulk transfer on a 0 toggle
+			 * irrespective of the programming of the toggle bits
+			 * in the TXCSR register.  Check for this condition
+			 * while allocating the EP for a Tx Bulk transfer.  If
+			 * so skip this EP.
+			 */
+			hw_ep = musb->endpoints + epnum;
+			toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in);
+			txtype = (musb_readb(hw_ep->regs, MUSB_TXTYPE)
+					>> 4) & 0x3;
+			if (!is_in && (qh->type == USB_ENDPOINT_XFER_BULK) &&
+				toggle && (txtype == USB_ENDPOINT_XFER_ISOC))
+				continue;
+
 			best_diff = diff;
 			best_end = epnum;
 		}
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h
index 473a94e..8d8062b 100644
--- a/drivers/usb/musb/musb_regs.h
+++ b/drivers/usb/musb/musb_regs.h
@@ -72,6 +72,10 @@
 #define MUSB_DEVCTL_HR		0x02
 #define MUSB_DEVCTL_SESSION	0x01
 
+/* MUSB ULPI VBUSCONTROL */
+#define MUSB_ULPI_USE_EXTVBUS	0x01
+#define MUSB_ULPI_USE_EXTVBUSIND 0x02
+
 /* TESTMODE */
 #define MUSB_TEST_FORCE_HOST	0x80
 #define MUSB_TEST_FIFO_ACCESS	0x40
@@ -246,6 +250,7 @@
 
 /* REVISIT: vctrl/vstatus: optional vendor utmi+phy register at 0x68 */
 #define MUSB_HWVERS		0x6C	/* 8 bit */
+#define MUSB_ULPI_BUSCONTROL	0x70	/* 8 bit */
 
 #define MUSB_EPINFO		0x78	/* 8 bit */
 #define MUSB_RAMINFO		0x79	/* 8 bit */
@@ -321,6 +326,26 @@
 	musb_writew(mbase, MUSB_RXFIFOADD, c_off);
 }
 
+static inline u8 musb_read_txfifosz(void __iomem *mbase)
+{
+	return musb_readb(mbase, MUSB_TXFIFOSZ);
+}
+
+static inline u16 musb_read_txfifoadd(void __iomem *mbase)
+{
+	return musb_readw(mbase, MUSB_TXFIFOADD);
+}
+
+static inline u8 musb_read_rxfifosz(void __iomem *mbase)
+{
+	return musb_readb(mbase, MUSB_RXFIFOSZ);
+}
+
+static inline u16  musb_read_rxfifoadd(void __iomem *mbase)
+{
+	return musb_readw(mbase, MUSB_RXFIFOADD);
+}
+
 static inline u8 musb_read_configdata(void __iomem *mbase)
 {
 	musb_writeb(mbase, MUSB_INDEX, 0);
@@ -376,6 +401,36 @@
 			qh_h_port_reg);
 }
 
+static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum)
+{
+	return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXFUNCADDR));
+}
+
+static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)
+{
+	return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBADDR));
+}
+
+static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)
+{
+	return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBPORT));
+}
+
+static inline u8  musb_read_txfunaddr(void __iomem *mbase, u8 epnum)
+{
+	return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR));
+}
+
+static inline u8  musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
+{
+	return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR));
+}
+
+static inline u8  musb_read_txhubport(void __iomem *mbase, u8 epnum)
+{
+	return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT));
+}
+
 #else /* CONFIG_BLACKFIN */
 
 #define USB_BASE		USB_FADDR
@@ -436,7 +491,7 @@
 #define MUSB_FLAT_OFFSET(_epnum, _offset)	\
 	(USB_OFFSET(USB_EP_NI0_TXMAXP) + (0x40 * (_epnum)) + (_offset))
 
-/* Not implemented - HW has seperate Tx/Rx FIFO */
+/* Not implemented - HW has separate Tx/Rx FIFO */
 #define MUSB_TXCSR_MODE			0x0000
 
 static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size)
@@ -455,6 +510,22 @@
 {
 }
 
+static inline u8 musb_read_txfifosz(void __iomem *mbase)
+{
+}
+
+static inline u16 musb_read_txfifoadd(void __iomem *mbase)
+{
+}
+
+static inline u8 musb_read_rxfifosz(void __iomem *mbase)
+{
+}
+
+static inline u16  musb_read_rxfifoadd(void __iomem *mbase)
+{
+}
+
 static inline u8 musb_read_configdata(void __iomem *mbase)
 {
 	return 0;
@@ -462,7 +533,11 @@
 
 static inline u16 musb_read_hwvers(void __iomem *mbase)
 {
-	return 0;
+	/*
+	 * This register is invisible on Blackfin, actually the MUSB
+	 * RTL version of Blackfin is 1.9, so just harcode its value.
+	 */
+	return MUSB_HWVERS_1900;
 }
 
 static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase)
@@ -500,6 +575,30 @@
 {
 }
 
+static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum)
+{
+}
+
+static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)
+{
+}
+
+static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)
+{
+}
+
+static inline u8  musb_read_txfunaddr(void __iomem *mbase, u8 epnum)
+{
+}
+
+static inline u8  musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
+{
+}
+
+static inline void  musb_read_txhubport(void __iomem *mbase, u8 epnum)
+{
+}
+
 #endif /* CONFIG_BLACKFIN */
 
 #endif	/* __MUSB_REGS_H__ */
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c
index a237550..2fa7d5c 100644
--- a/drivers/usb/musb/musbhsdma.c
+++ b/drivers/usb/musb/musbhsdma.c
@@ -250,20 +250,39 @@
 	u8 bchannel;
 	u8 int_hsdma;
 
-	u32 addr;
+	u32 addr, count;
 	u16 csr;
 
 	spin_lock_irqsave(&musb->lock, flags);
 
 	int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR);
-	if (!int_hsdma)
-		goto done;
 
 #ifdef CONFIG_BLACKFIN
 	/* Clear DMA interrupt flags */
 	musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma);
 #endif
 
+	if (!int_hsdma) {
+		DBG(2, "spurious DMA irq\n");
+
+		for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) {
+			musb_channel = (struct musb_dma_channel *)
+					&(controller->channel[bchannel]);
+			channel = &musb_channel->channel;
+			if (channel->status == MUSB_DMA_STATUS_BUSY) {
+				count = musb_read_hsdma_count(mbase, bchannel);
+
+				if (count == 0)
+					int_hsdma |= (1 << bchannel);
+			}
+		}
+
+		DBG(2, "int_hsdma = 0x%x\n", int_hsdma);
+
+		if (!int_hsdma)
+			goto done;
+	}
+
 	for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) {
 		if (int_hsdma & (1 << bchannel)) {
 			musb_channel = (struct musb_dma_channel *)
diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h
index 1299d92..613f95a 100644
--- a/drivers/usb/musb/musbhsdma.h
+++ b/drivers/usb/musb/musbhsdma.h
@@ -55,6 +55,10 @@
 		    MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), \
 		    addr)
 
+#define musb_read_hsdma_count(mbase, bchannel)	\
+	musb_readl(mbase,	\
+		   MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT))
+
 #define musb_write_hsdma_count(mbase, bchannel, len) \
 	musb_writel(mbase, \
 		    MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \
@@ -96,6 +100,19 @@
 		((u16)(((u32) dma_addr >> 16) & 0xFFFF)));
 }
 
+static inline u32 musb_read_hsdma_count(void __iomem *mbase, u8 bchannel)
+{
+	u32 count = musb_readw(mbase,
+		MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_HIGH));
+
+	count = count << 16;
+
+	count |= musb_readw(mbase,
+		MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW));
+
+	return count;
+}
+
 static inline void musb_write_hsdma_count(void __iomem *mbase,
 				u8 bchannel, u32 len)
 {
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 83beeac..3fe1686 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -220,7 +220,7 @@
 
 	musb_platform_resume(musb);
 
-	l = omap_readl(OTG_SYSCONFIG);
+	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
 	l &= ~ENABLEWAKEUP;	/* disable wakeup */
 	l &= ~NOSTDBY;		/* remove possible nostdby */
 	l |= SMARTSTDBY;	/* enable smart standby */
@@ -233,17 +233,19 @@
 	 */
 	if (!cpu_is_omap3430())
 		l |= AUTOIDLE;		/* enable auto idle */
-	omap_writel(l, OTG_SYSCONFIG);
+	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
 
-	l = omap_readl(OTG_INTERFSEL);
+	l = musb_readl(musb->mregs, OTG_INTERFSEL);
 	l |= ULPI_12PIN;
-	omap_writel(l, OTG_INTERFSEL);
+	musb_writel(musb->mregs, OTG_INTERFSEL, l);
 
 	pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
 			"sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
-			omap_readl(OTG_REVISION), omap_readl(OTG_SYSCONFIG),
-			omap_readl(OTG_SYSSTATUS), omap_readl(OTG_INTERFSEL),
-			omap_readl(OTG_SIMENABLE));
+			musb_readl(musb->mregs, OTG_REVISION),
+			musb_readl(musb->mregs, OTG_SYSCONFIG),
+			musb_readl(musb->mregs, OTG_SYSSTATUS),
+			musb_readl(musb->mregs, OTG_INTERFSEL),
+			musb_readl(musb->mregs, OTG_SIMENABLE));
 
 	omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
 
@@ -255,6 +257,22 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+void musb_platform_save_context(struct musb *musb,
+		struct musb_context_registers *musb_context)
+{
+	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
+
 int musb_platform_suspend(struct musb *musb)
 {
 	u32 l;
@@ -263,13 +281,13 @@
 		return 0;
 
 	/* in any role */
-	l = omap_readl(OTG_FORCESTDBY);
+	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
 	l |= ENABLEFORCE;	/* enable MSTANDBY */
-	omap_writel(l, OTG_FORCESTDBY);
+	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 
-	l = omap_readl(OTG_SYSCONFIG);
+	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
 	l |= ENABLEWAKEUP;	/* enable wakeup */
-	omap_writel(l, OTG_SYSCONFIG);
+	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
 
 	otg_set_suspend(musb->xceiv, 1);
 
@@ -295,13 +313,13 @@
 	else
 		clk_enable(musb->clock);
 
-	l = omap_readl(OTG_SYSCONFIG);
+	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
 	l &= ~ENABLEWAKEUP;	/* disable wakeup */
-	omap_writel(l, OTG_SYSCONFIG);
+	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
 
-	l = omap_readl(OTG_FORCESTDBY);
+	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
 	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
-	omap_writel(l, OTG_FORCESTDBY);
+	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 
 	return 0;
 }
diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h
index fbede77..40b3c02 100644
--- a/drivers/usb/musb/omap2430.h
+++ b/drivers/usb/musb/omap2430.h
@@ -10,47 +10,43 @@
 #ifndef __MUSB_OMAP243X_H__
 #define __MUSB_OMAP243X_H__
 
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
-#include <mach/hardware.h>
 #include <plat/usb.h>
 
 /*
  * OMAP2430-specific definitions
  */
 
-#define MENTOR_BASE_OFFSET	0
-#if	defined(CONFIG_ARCH_OMAP2430)
-#define	OMAP_HSOTG_BASE		(OMAP243X_HS_BASE)
-#elif	defined(CONFIG_ARCH_OMAP3430)
-#define	OMAP_HSOTG_BASE		(OMAP34XX_HSUSB_OTG_BASE)
-#endif
-#define OMAP_HSOTG(offset)	(OMAP_HSOTG_BASE + 0x400 + (offset))
-#define OTG_REVISION		OMAP_HSOTG(0x0)
-#define OTG_SYSCONFIG		OMAP_HSOTG(0x4)
+#define OTG_REVISION		0x400
+
+#define OTG_SYSCONFIG		0x404
 #	define	MIDLEMODE	12	/* bit position */
 #	define	FORCESTDBY		(0 << MIDLEMODE)
 #	define	NOSTDBY			(1 << MIDLEMODE)
 #	define	SMARTSTDBY		(2 << MIDLEMODE)
+
 #	define	SIDLEMODE		3	/* bit position */
 #	define	FORCEIDLE		(0 << SIDLEMODE)
 #	define	NOIDLE			(1 << SIDLEMODE)
 #	define	SMARTIDLE		(2 << SIDLEMODE)
+
 #	define	ENABLEWAKEUP		(1 << 2)
 #	define	SOFTRST			(1 << 1)
 #	define	AUTOIDLE		(1 << 0)
-#define OTG_SYSSTATUS		OMAP_HSOTG(0x8)
+
+#define OTG_SYSSTATUS		0x408
 #	define	RESETDONE		(1 << 0)
-#define OTG_INTERFSEL		OMAP_HSOTG(0xc)
+
+#define OTG_INTERFSEL		0x40c
 #	define	EXTCP			(1 << 2)
-#	define	PHYSEL		0	/* bit position */
+#	define	PHYSEL			0	/* bit position */
 #	define	UTMI_8BIT		(0 << PHYSEL)
 #	define	ULPI_12PIN		(1 << PHYSEL)
 #	define	ULPI_8PIN		(2 << PHYSEL)
-#define OTG_SIMENABLE		OMAP_HSOTG(0x10)
-#	define	TM1			(1 << 0)
-#define OTG_FORCESTDBY		OMAP_HSOTG(0x14)
-#	define	ENABLEFORCE		(1 << 0)
 
-#endif	/* CONFIG_ARCH_OMAP2430 */
+#define OTG_SIMENABLE		0x410
+#	define	TM1			(1 << 0)
+
+#define OTG_FORCESTDBY		0x414
+#	define	ENABLEFORCE		(1 << 0)
 
 #endif	/* __MUSB_OMAP243X_H__ */
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 88b587c..ab776a8 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1118,7 +1118,7 @@
 	}
 	musb->sync = mem->start;
 
-	sync = ioremap(mem->start, mem->end - mem->start + 1);
+	sync = ioremap(mem->start, resource_size(mem));
 	if (!sync) {
 		pr_debug("ioremap for sync failed\n");
 		ret = -ENOMEM;
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index e13c770..1c86809 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -648,7 +648,7 @@
 		}
 	}
 
-	if (!tusb_dma->multichannel && tusb_dma && tusb_dma->ch >= 0)
+	if (tusb_dma && !tusb_dma->multichannel && tusb_dma->ch >= 0)
 		omap_free_dma(tusb_dma->ch);
 
 	kfree(tusb_dma);
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 2be9f2f..3e4e9f4 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -36,7 +36,7 @@
 #include <linux/i2c/twl.h>
 #include <linux/regulator/consumer.h>
 #include <linux/err.h>
-
+#include <linux/notifier.h>
 
 /* Register defines */
 
@@ -236,15 +236,6 @@
 #define PMBR1				0x0D
 #define GPIO_USB_4PIN_ULPI_2430C	(3 << 0)
 
-
-
-enum linkstat {
-	USB_LINK_UNKNOWN = 0,
-	USB_LINK_NONE,
-	USB_LINK_VBUS,
-	USB_LINK_ID,
-};
-
 struct twl4030_usb {
 	struct otg_transceiver	otg;
 	struct device		*dev;
@@ -347,10 +338,10 @@
 
 /*-------------------------------------------------------------------------*/
 
-static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl)
+static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl)
 {
 	int	status;
-	int	linkstat = USB_LINK_UNKNOWN;
+	int	linkstat = USB_EVENT_NONE;
 
 	/*
 	 * For ID/VBUS sensing, see manual section 15.4.8 ...
@@ -368,11 +359,11 @@
 		dev_err(twl->dev, "USB link status err %d\n", status);
 	else if (status & (BIT(7) | BIT(2))) {
 		if (status & BIT(2))
-			linkstat = USB_LINK_ID;
+			linkstat = USB_EVENT_ID;
 		else
-			linkstat = USB_LINK_VBUS;
+			linkstat = USB_EVENT_VBUS;
 	} else
-		linkstat = USB_LINK_NONE;
+		linkstat = USB_EVENT_NONE;
 
 	dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
 			status, status, linkstat);
@@ -383,7 +374,7 @@
 
 	spin_lock_irq(&twl->lock);
 	twl->linkstat = linkstat;
-	if (linkstat == USB_LINK_ID) {
+	if (linkstat == USB_EVENT_ID) {
 		twl->otg.default_a = true;
 		twl->otg.state = OTG_STATE_A_IDLE;
 	} else {
@@ -564,7 +555,7 @@
 
 	spin_lock_irqsave(&twl->lock, flags);
 	ret = sprintf(buf, "%s\n",
-			(twl->linkstat == USB_LINK_VBUS) ? "on" : "off");
+			(twl->linkstat == USB_EVENT_VBUS) ? "on" : "off");
 	spin_unlock_irqrestore(&twl->lock, flags);
 
 	return ret;
@@ -576,17 +567,8 @@
 	struct twl4030_usb *twl = _twl;
 	int status;
 
-#ifdef CONFIG_LOCKDEP
-	/* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
-	 * we don't want and can't tolerate.  Although it might be
-	 * friendlier not to borrow this thread context...
-	 */
-	local_irq_enable();
-#endif
-
 	status = twl4030_usb_linkstat(twl);
-	if (status != USB_LINK_UNKNOWN) {
-
+	if (status >= 0) {
 		/* FIXME add a set_power() method so that B-devices can
 		 * configure the charger appropriately.  It's not always
 		 * correct to consume VBUS power, and how much current to
@@ -598,12 +580,13 @@
 		 * USB_LINK_VBUS state.  musb_hdrc won't care until it
 		 * starts to handle softconnect right.
 		 */
-		if (status == USB_LINK_NONE)
+		if (status == USB_EVENT_NONE)
 			twl4030_phy_suspend(twl, 0);
 		else
 			twl4030_phy_resume(twl);
 
-		twl4030charger_usb_en(status == USB_LINK_VBUS);
+		blocking_notifier_call_chain(&twl->otg.notifier, status,
+				twl->otg.gadget);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
@@ -693,6 +676,8 @@
 	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);
+
 	/* Our job is to use irqs and status from the power module
 	 * to keep the transceiver disabled when nothing's connected.
 	 *
@@ -702,7 +687,7 @@
 	 * need both handles, otherwise just one suffices.
 	 */
 	twl->irq_enabled = true;
-	status = request_irq(twl->irq, twl4030_usb_irq,
+	status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq,
 			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
 			"twl4030_usb", twl);
 	if (status < 0) {
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index c480ea4..c78b255 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -472,6 +472,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called oti6858.
 
+config USB_SERIAL_QCAUX
+	tristate "USB Qualcomm Auxiliary Serial Port Driver"
+	---help---
+	  Say Y here if you want to use the auxiliary serial ports provided
+	  by many modems based on Qualcomm chipsets.  These ports often use
+	  a proprietary protocol called DM and cannot be used for AT- or
+	  PPP-based communication.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called moto_modem.  If unsure, choose N.
+
 config USB_SERIAL_QUALCOMM
 	tristate "USB Qualcomm Serial modem"
 	help
@@ -600,6 +611,14 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called opticon.
 
+config USB_SERIAL_VIVOPAY_SERIAL
+        tristate "USB ViVOpay serial interface driver"
+        help
+          Say Y here if you want to use a ViVOtech ViVOpay USB device.
+
+          To compile this driver as a module, choose M here: the
+          module will be called vivopay-serial.
+
 config USB_SERIAL_DEBUG
 	tristate "USB Debugging Device"
 	help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 66619be..83c9e43 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -45,6 +45,7 @@
 obj-$(CONFIG_USB_SERIAL_OPTION)			+= option.o
 obj-$(CONFIG_USB_SERIAL_OTI6858)		+= oti6858.o
 obj-$(CONFIG_USB_SERIAL_PL2303)			+= pl2303.o
+obj-$(CONFIG_USB_SERIAL_QCAUX)			+= qcaux.o
 obj-$(CONFIG_USB_SERIAL_QUALCOMM)		+= qcserial.o
 obj-$(CONFIG_USB_SERIAL_SAFE)			+= safe_serial.o
 obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI)		+= siemens_mpi.o
@@ -55,4 +56,5 @@
 obj-$(CONFIG_USB_SERIAL_VISOR)			+= visor.o
 obj-$(CONFIG_USB_SERIAL_WHITEHEAT)		+= whiteheat.o
 obj-$(CONFIG_USB_SERIAL_XIRCOM)			+= keyspan_pda.o
+obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL)	+= vivopay-serial.o
 
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index b10ac84..365db10 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -78,7 +78,7 @@
 #define DRIVER_DESC "AIRcable USB Driver"
 
 /* ID table that will be registered with USB core */
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(AIRCABLE_VID, AIRCABLE_USB_PID) },
 	{ },
 };
@@ -468,10 +468,6 @@
 
 	if (status) {
 		dbg("%s - urb status = %d", __func__, status);
-		if (!port->port.count) {
-			dbg("%s - port is closed, exiting.", __func__);
-			return;
-		}
 		if (status == -EPROTO) {
 			dbg("%s - caught -EPROTO, resubmitting the urb",
 			    __func__);
@@ -530,23 +526,19 @@
 	}
 	tty_kref_put(tty);
 
-	/* Schedule the next read _if_ we are still open */
-	if (port->port.count) {
-		usb_fill_bulk_urb(port->read_urb, port->serial->dev,
-				  usb_rcvbulkpipe(port->serial->dev,
-					  port->bulk_in_endpointAddress),
-				  port->read_urb->transfer_buffer,
-				  port->read_urb->transfer_buffer_length,
-				  aircable_read_bulk_callback, port);
+	/* Schedule the next read */
+	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+			  usb_rcvbulkpipe(port->serial->dev,
+				  port->bulk_in_endpointAddress),
+			  port->read_urb->transfer_buffer,
+			  port->read_urb->transfer_buffer_length,
+			  aircable_read_bulk_callback, port);
 
-		result = usb_submit_urb(urb, GFP_ATOMIC);
-		if (result)
-			dev_err(&urb->dev->dev,
-				"%s - failed resubmitting read urb, error %d\n",
-				__func__, result);
-	}
-
-	return;
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result && result != -EPERM)
+		dev_err(&urb->dev->dev,
+			"%s - failed resubmitting read urb, error %d\n",
+			__func__, result);
 }
 
 /* Based on ftdi_sio.c throttle */
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index a9c2dec..547c944 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -50,7 +50,7 @@
 /* usb timeout of 1 second */
 #define ARK_TIMEOUT (1*HZ)
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x6547, 0x0232) },
 	{ USB_DEVICE(0x18ec, 0x3118) },		/* USB to IrDA adapter */
 	{ },
@@ -733,7 +733,6 @@
 
 		tty = tty_port_tty_get(&port->port);
 		if (tty) {
-			tty_buffer_request_room(tty, urb->actual_length + 1);
 			/* overrun is special, not associated with a char */
 			if (unlikely(lsr & UART_LSR_OE))
 				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index a0467bc..1295e44 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -103,7 +103,7 @@
 					unsigned int set, unsigned int clear);
 
 
-static struct usb_device_id id_table_combined [] = {
+static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) },
 	{ USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) },
 	{ USB_DEVICE(PERACOM_VID, PERACOM_PID) },
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 59eff72..9f4fed1 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -22,6 +22,7 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include <linux/serial.h>
+#include <asm/unaligned.h>
 
 #define DEFAULT_BAUD_RATE 9600
 #define DEFAULT_TIMEOUT   1000
@@ -70,7 +71,7 @@
 
 static int debug;
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x4348, 0x5523) },
 	{ USB_DEVICE(0x1a86, 0x7523) },
 	{ },
@@ -392,17 +393,23 @@
 	struct usb_serial_port *port = tty->driver_data;
 	int r;
 	uint16_t reg_contents;
-	uint8_t break_reg[2];
+	uint8_t *break_reg;
 
 	dbg("%s()", __func__);
 
-	r = ch341_control_in(port->serial->dev, CH341_REQ_READ_REG,
-			ch341_break_reg, 0, break_reg, sizeof(break_reg));
-	if (r < 0) {
-		printk(KERN_WARNING "%s: USB control read error whilst getting"
-				" break register contents.\n", __FILE__);
+	break_reg = kmalloc(2, GFP_KERNEL);
+	if (!break_reg) {
+		dev_err(&port->dev, "%s - kmalloc failed\n", __func__);
 		return;
 	}
+
+	r = ch341_control_in(port->serial->dev, CH341_REQ_READ_REG,
+			ch341_break_reg, 0, break_reg, 2);
+	if (r < 0) {
+		dev_err(&port->dev, "%s - USB control read error (%d)\n",
+				__func__, r);
+		goto out;
+	}
 	dbg("%s - initial ch341 break register contents - reg1: %x, reg2: %x",
 			__func__, break_reg[0], break_reg[1]);
 	if (break_state != 0) {
@@ -416,12 +423,14 @@
 	}
 	dbg("%s - New ch341 break register contents - reg1: %x, reg2: %x",
 			__func__, break_reg[0], break_reg[1]);
-	reg_contents = (uint16_t)break_reg[0] | ((uint16_t)break_reg[1] << 8);
+	reg_contents = get_unaligned_le16(break_reg);
 	r = ch341_control_out(port->serial->dev, CH341_REQ_WRITE_REG,
 			ch341_break_reg, reg_contents);
 	if (r < 0)
-		printk(KERN_WARNING "%s: USB control write error whilst setting"
-				" break register contents.\n", __FILE__);
+		dev_err(&port->dev, "%s - USB control write error (%d)\n",
+				__func__, r);
+out:
+	kfree(break_reg);
 }
 
 static int ch341_tiocmset(struct tty_struct *tty, struct file *file,
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index bd254ec..507382b 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -55,7 +55,7 @@
 
 static int debug;
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */
 	{ USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
 	{ USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
@@ -91,11 +91,12 @@
 	{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
 	{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
 	{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
+	{ USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */
 	{ USB_DEVICE(0x10C4, 0x81F2) }, /* C1007 HF band RFID controller */
 	{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
 	{ USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */
 	{ USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */
-	{ USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */
+	{ USB_DEVICE(0x10C4, 0x8293) }, /* Telegesys ETRX2USB */
 	{ USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */
 	{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
 	{ USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */
@@ -612,7 +613,7 @@
 				baud);
 		if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV,
 					((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
-			dbg("Baud rate requested not supported by device\n");
+			dbg("Baud rate requested not supported by device");
 			baud = tty_termios_baud_rate(old_termios);
 		}
 	}
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index b0f6402..f744ab7 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -70,7 +70,7 @@
 static void cyberjack_read_bulk_callback(struct urb *urb);
 static void cyberjack_write_bulk_callback(struct urb *urb);
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) },
 	{ }			/* Terminating entry */
 };
@@ -391,11 +391,10 @@
 
 	tty = tty_port_tty_get(&port->port);
 	if (!tty) {
-		dbg("%s - ignoring since device not open\n", __func__);
+		dbg("%s - ignoring since device not open", __func__);
 		return;
 	}
 	if (urb->actual_length) {
-		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index a591ebe..e23c779 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -66,17 +66,15 @@
 #include <linux/serial.h>
 #include <linux/delay.h>
 #include <linux/uaccess.h>
+#include <asm/unaligned.h>
 
 #include "cypress_m8.h"
 
 
-#ifdef CONFIG_USB_SERIAL_DEBUG
-	static int debug = 1;
-#else
-	static int debug;
-#endif
+static int debug;
 static int stats;
 static int interval;
+static int unstable_bauds;
 
 /*
  * Version Information
@@ -89,24 +87,24 @@
 #define CYPRESS_BUF_SIZE	1024
 #define CYPRESS_CLOSING_WAIT	(30*HZ)
 
-static struct usb_device_id id_table_earthmate [] = {
+static const struct usb_device_id id_table_earthmate[] = {
 	{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
 	{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
 	{ }						/* Terminating entry */
 };
 
-static struct usb_device_id id_table_cyphidcomrs232 [] = {
+static const struct usb_device_id id_table_cyphidcomrs232[] = {
 	{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
 	{ USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
 	{ }						/* Terminating entry */
 };
 
-static struct usb_device_id id_table_nokiaca42v2 [] = {
+static const struct usb_device_id id_table_nokiaca42v2[] = {
 	{ USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
 	{ }						/* Terminating entry */
 };
 
-static struct usb_device_id id_table_combined [] = {
+static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
 	{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
 	{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
@@ -154,7 +152,7 @@
 	int isthrottled;		   /* if throttled, discard reads */
 	wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
 	char prev_status, diff_status;	   /* used for TIOCMIWAIT */
-	/* we pass a pointer to this as the arguement sent to
+	/* we pass a pointer to this as the argument sent to
 	   cypress_set_termios old_termios */
 	struct ktermios tmp_termios; 	   /* stores the old termios settings */
 };
@@ -295,6 +293,9 @@
 	struct cypress_private *priv;
 	priv = usb_get_serial_port_data(port);
 
+	if (unstable_bauds)
+		return new_rate;
+
 	/*
 	 * The general purpose firmware for the Cypress M8 allows for
 	 * a maximum speed of 57600bps (I have no idea whether DeLorme
@@ -344,7 +345,8 @@
 {
 	int new_baudrate = 0, retval = 0, tries = 0;
 	struct cypress_private *priv;
-	__u8 feature_buffer[5];
+	u8 *feature_buffer;
+	const unsigned int feature_len = 5;
 	unsigned long flags;
 
 	dbg("%s", __func__);
@@ -354,17 +356,18 @@
 	if (!priv->comm_is_ok)
 		return -ENODEV;
 
+	feature_buffer = kcalloc(feature_len, sizeof(u8), GFP_KERNEL);
+	if (!feature_buffer)
+		return -ENOMEM;
+
 	switch (cypress_request_type) {
 	case CYPRESS_SET_CONFIG:
-		new_baudrate = priv->baud_rate;
 		/* 0 means 'Hang up' so doesn't change the true bit rate */
-		if (baud_rate == 0)
-			new_baudrate = priv->baud_rate;
-		/* Change of speed ? */
-		else if (baud_rate != priv->baud_rate) {
+		new_baudrate = priv->baud_rate;
+		if (baud_rate && baud_rate != priv->baud_rate) {
 			dbg("%s - baud rate is changing", __func__);
 			retval = analyze_baud_rate(port, baud_rate);
-			if (retval >=  0) {
+			if (retval >= 0) {
 				new_baudrate = retval;
 				dbg("%s - New baud rate set to %d",
 				    __func__, new_baudrate);
@@ -373,9 +376,8 @@
 		dbg("%s - baud rate is being sent as %d",
 					__func__, new_baudrate);
 
-		memset(feature_buffer, 0, sizeof(feature_buffer));
 		/* fill the feature_buffer with new configuration */
-		*((u_int32_t *)feature_buffer) = new_baudrate;
+		put_unaligned_le32(new_baudrate, feature_buffer);
 		feature_buffer[4] |= data_bits;   /* assign data bits in 2 bit space ( max 3 ) */
 		/* 1 bit gap */
 		feature_buffer[4] |= (stop_bits << 3);   /* assign stop bits in 1 bit space */
@@ -397,15 +399,15 @@
 					HID_REQ_SET_REPORT,
 					USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
 					0x0300, 0, feature_buffer,
-					sizeof(feature_buffer), 500);
+					feature_len, 500);
 
 			if (tries++ >= 3)
 				break;
 
-		} while (retval != sizeof(feature_buffer) &&
+		} while (retval != feature_len &&
 			 retval != -ENODEV);
 
-		if (retval != sizeof(feature_buffer)) {
+		if (retval != feature_len) {
 			dev_err(&port->dev, "%s - failed sending serial "
 				"line settings - %d\n", __func__, retval);
 			cypress_set_dead(port);
@@ -425,43 +427,42 @@
 			/* Not implemented for this device,
 			   and if we try to do it we're likely
 			   to crash the hardware. */
-			return -ENOTTY;
+			retval = -ENOTTY;
+			goto out;
 		}
 		dbg("%s - retreiving serial line settings", __func__);
-		/* set initial values in feature buffer */
-		memset(feature_buffer, 0, sizeof(feature_buffer));
-
 		do {
 			retval = usb_control_msg(port->serial->dev,
 					usb_rcvctrlpipe(port->serial->dev, 0),
 					HID_REQ_GET_REPORT,
 					USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
 					0x0300, 0, feature_buffer,
-					sizeof(feature_buffer), 500);
+					feature_len, 500);
 
 			if (tries++ >= 3)
 				break;
-		} while (retval != sizeof(feature_buffer)
+		} while (retval != feature_len
 						&& retval != -ENODEV);
 
-		if (retval != sizeof(feature_buffer)) {
+		if (retval != feature_len) {
 			dev_err(&port->dev, "%s - failed to retrieve serial "
 				"line settings - %d\n", __func__, retval);
 			cypress_set_dead(port);
-			return retval;
+			goto out;
 		} else {
 			spin_lock_irqsave(&priv->lock, flags);
 			/* store the config in one byte, and later
 			   use bit masks to check values */
 			priv->current_config = feature_buffer[4];
-			priv->baud_rate = *((u_int32_t *)feature_buffer);
+			priv->baud_rate = get_unaligned_le32(feature_buffer);
 			spin_unlock_irqrestore(&priv->lock, flags);
 		}
 	}
 	spin_lock_irqsave(&priv->lock, flags);
 	++priv->cmd_count;
 	spin_unlock_irqrestore(&priv->lock, flags);
-
+out:
+	kfree(feature_buffer);
 	return retval;
 } /* cypress_serial_control */
 
@@ -690,7 +691,6 @@
 {
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	/* drop dtr and rts */
-	priv = usb_get_serial_port_data(port);
 	spin_lock_irq(&priv->lock);
 	if (on == 0)
 		priv->line_control = 0;
@@ -1307,13 +1307,9 @@
 		spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* process read if there is data other than line status */
-	if (tty && (bytes > i)) {
-		bytes = tty_buffer_request_room(tty, bytes);
-		for (; i < bytes ; ++i) {
-			dbg("pushing byte number %d - %d - %c", i, data[i],
-					data[i]);
-			tty_insert_flip_char(tty, data[i], tty_flag);
-		}
+	if (tty && bytes > i) {
+		tty_insert_flip_string_fixed_flag(tty, data + i,
+				bytes - i, tty_flag);
 		tty_flip_buffer_push(tty);
 	}
 
@@ -1325,9 +1321,9 @@
 continue_read:
 	tty_kref_put(tty);
 
-	/* Continue trying to always read... unless the port has closed. */
+	/* Continue trying to always read */
 
-	if (port->port.count > 0 && priv->comm_is_ok) {
+	if (priv->comm_is_ok) {
 		usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
 				usb_rcvintpipe(port->serial->dev,
 					port->interrupt_in_endpointAddress),
@@ -1336,7 +1332,7 @@
 				cypress_read_int_callback, port,
 				priv->read_urb_interval);
 		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-		if (result) {
+		if (result && result != -EPERM) {
 			dev_err(&urb->dev->dev, "%s - failed resubmitting "
 					"read urb, error %d\n", __func__,
 					result);
@@ -1650,3 +1646,5 @@
 MODULE_PARM_DESC(stats, "Enable statistics or not");
 module_param(interval, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(interval, "Overrides interrupt interval");
+module_param(unstable_bauds, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(unstable_bauds, "Allow unstable baud rates");
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 68e80be..68b0aa5 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -470,18 +470,18 @@
 
 static int debug;
 
-static struct usb_device_id id_table_combined [] = {
+static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) },
 	{ USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) },
 	{ }						/* Terminating entry */
 };
 
-static struct usb_device_id id_table_2 [] = {
+static const struct usb_device_id id_table_2[] = {
 	{ USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) },
 	{ }						/* Terminating entry */
 };
 
-static struct usb_device_id id_table_4 [] = {
+static const struct usb_device_id id_table_4[] = {
 	{ USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) },
 	{ }						/* Terminating entry */
 };
@@ -1262,10 +1262,10 @@
 		return;
 	}
 
-	/* try to send any buffered data on this port, if it is open */
+	/* try to send any buffered data on this port */
 	spin_lock(&priv->dp_port_lock);
 	priv->dp_write_urb_in_use = 0;
-	if (port->port.count && priv->dp_out_buf_len > 0) {
+	if (priv->dp_out_buf_len > 0) {
 		*((unsigned char *)(port->write_urb->transfer_buffer))
 			= (unsigned char)DIGI_CMD_SEND_DATA;
 		*((unsigned char *)(port->write_urb->transfer_buffer) + 1)
@@ -1288,7 +1288,7 @@
 	schedule_work(&priv->dp_wakeup_work);
 
 	spin_unlock(&priv->dp_port_lock);
-	if (ret)
+	if (ret && ret != -EPERM)
 		dev_err(&port->dev,
 			"%s: usb_submit_urb failed, ret=%d, port=%d\n",
 			__func__, ret, priv->dp_port_num);
@@ -1353,8 +1353,7 @@
 	struct digi_port *priv = usb_get_serial_port_data(port);
 	struct ktermios not_termios;
 
-	dbg("digi_open: TOP: port=%d, open_count=%d",
-		priv->dp_port_num, port->port.count);
+	dbg("digi_open: TOP: port=%d", priv->dp_port_num);
 
 	/* be sure the device is started up */
 	if (digi_startup_device(port->serial) != 0)
@@ -1393,8 +1392,7 @@
 	unsigned char buf[32];
 	struct digi_port *priv = usb_get_serial_port_data(port);
 
-	dbg("digi_close: TOP: port=%d, open_count=%d",
-		priv->dp_port_num, port->port.count);
+	dbg("digi_close: TOP: port=%d", priv->dp_port_num);
 
 	mutex_lock(&port->serial->disc_mutex);
 	/* if disconnected, just clear flags */
@@ -1629,7 +1627,7 @@
 	/* continue read */
 	urb->dev = port->serial->dev;
 	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret != 0) {
+	if (ret != 0 && ret != -EPERM) {
 		dev_err(&port->dev,
 			"%s: failed resubmitting urb, ret=%d, port=%d\n",
 			__func__, ret, priv->dp_port_num);
@@ -1658,12 +1656,11 @@
 	int port_status = ((unsigned char *)urb->transfer_buffer)[2];
 	unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3;
 	int flag, throttled;
-	int i;
 	int status = urb->status;
 
 	/* do not process callbacks on closed ports */
 	/* but do continue the read chain */
-	if (port->port.count == 0)
+	if (urb->status == -ENOENT)
 		return 0;
 
 	/* short/multiple packet check */
@@ -1705,17 +1702,9 @@
 
 		/* data length is len-1 (one byte of len is port_status) */
 		--len;
-
-		len = tty_buffer_request_room(tty, len);
 		if (len > 0) {
-			/* Hot path */
-			if (flag == TTY_NORMAL)
-				tty_insert_flip_string(tty, data, len);
-			else {
-				for (i = 0; i < len; i++)
-					tty_insert_flip_char(tty,
-								data[i], flag);
-			}
+			tty_insert_flip_string_fixed_flag(tty, data, len,
+									flag);
 			tty_flip_buffer_push(tty);
 		}
 	}
@@ -1776,8 +1765,7 @@
 
 		tty = tty_port_tty_get(&port->port);
 		rts = 0;
-		if (port->port.count)
-			rts = tty->termios->c_cflag & CRTSCTS;
+		rts = tty->termios->c_cflag & CRTSCTS;
 		
 		if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
 			spin_lock(&priv->dp_port_lock);
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 7dd0e3e..5f740a1 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -93,7 +93,7 @@
 static void empeg_write_bulk_callback(struct urb *urb);
 static void empeg_read_bulk_callback(struct urb *urb);
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(EMPEG_VENDOR_ID, EMPEG_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
@@ -346,7 +346,6 @@
 	tty = tty_port_tty_get(&port->port);
 
 	if (urb->actual_length) {
-		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 		bytes_in += urb->actual_length;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 7638828..6af0dfa 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -33,12 +33,12 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/serial.h>
@@ -88,10 +88,10 @@
 
 	unsigned int latency;		/* latency setting in use */
 	spinlock_t tx_lock;	/* spinlock for transmit state */
-	unsigned long tx_bytes;
 	unsigned long tx_outstanding_bytes;
 	unsigned long tx_outstanding_urbs;
 	unsigned short max_packet_size;
+	struct mutex cfg_lock; /* Avoid mess by parallel calls of config ioctl() */
 };
 
 /* struct ftdi_sio_quirk is used by devices requiring special attention. */
@@ -614,6 +614,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_OCEANIC_PID) },
 	{ USB_DEVICE(TTI_VID, TTI_QL355P_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
+	{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
 	{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
@@ -737,6 +738,10 @@
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
 	{ USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) },
+	{ USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) },
+	{ USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) },
+	{ USB_DEVICE(FTDI_VID, MJSG_HD_RADIO_PID) },
+	{ USB_DEVICE(FTDI_VID, MJSG_XM_RADIO_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -812,7 +817,7 @@
 		.name =		"ftdi_sio",
 	},
 	.description =		"FTDI USB Serial Device",
-	.usb_driver = 		&ftdi_driver ,
+	.usb_driver = 		&ftdi_driver,
 	.id_table =		id_table_combined,
 	.num_ports =		1,
 	.probe =		ftdi_sio_probe,
@@ -828,8 +833,8 @@
 	.chars_in_buffer =	ftdi_chars_in_buffer,
 	.read_bulk_callback =	ftdi_read_bulk_callback,
 	.write_bulk_callback =	ftdi_write_bulk_callback,
-	.tiocmget =             ftdi_tiocmget,
-	.tiocmset =             ftdi_tiocmset,
+	.tiocmget =		ftdi_tiocmget,
+	.tiocmset =		ftdi_tiocmset,
 	.ioctl =		ftdi_ioctl,
 	.set_termios =		ftdi_set_termios,
 	.break_ctl =		ftdi_break_ctl,
@@ -935,7 +940,6 @@
 							unsigned int clear)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	char *buf;
 	unsigned urb_value;
 	int rv;
 
@@ -944,10 +948,6 @@
 		return 0;	/* no change */
 	}
 
-	buf = kmalloc(1, GFP_NOIO);
-	if (!buf)
-		return -ENOMEM;
-
 	clear &= ~set;	/* 'set' takes precedence over 'clear' */
 	urb_value = 0;
 	if (clear & TIOCM_DTR)
@@ -963,9 +963,7 @@
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST,
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
 			       urb_value, priv->interface,
-			       buf, 0, WDR_TIMEOUT);
-
-	kfree(buf);
+			       NULL, 0, WDR_TIMEOUT);
 	if (rv < 0) {
 		dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s",
 				__func__,
@@ -1124,16 +1122,11 @@
 static int change_speed(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	char *buf;
 	__u16 urb_value;
 	__u16 urb_index;
 	__u32 urb_index_value;
 	int rv;
 
-	buf = kmalloc(1, GFP_NOIO);
-	if (!buf)
-		return -ENOMEM;
-
 	urb_index_value = get_ftdi_divisor(tty, port);
 	urb_value = (__u16)urb_index_value;
 	urb_index = (__u16)(urb_index_value >> 16);
@@ -1146,9 +1139,7 @@
 			    FTDI_SIO_SET_BAUDRATE_REQUEST,
 			    FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
 			    urb_value, urb_index,
-			    buf, 0, WDR_SHORT_TIMEOUT);
-
-	kfree(buf);
+			    NULL, 0, WDR_SHORT_TIMEOUT);
 	return rv;
 }
 
@@ -1156,8 +1147,7 @@
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	struct usb_device *udev = port->serial->dev;
-	char buf[1];
-	int rv = 0;
+	int rv;
 	int l = priv->latency;
 
 	if (priv->flags & ASYNC_LOW_LATENCY)
@@ -1170,8 +1160,7 @@
 			     FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
 			     FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
 			     l, priv->interface,
-			     buf, 0, WDR_TIMEOUT);
-
+			     NULL, 0, WDR_TIMEOUT);
 	if (rv < 0)
 		dev_err(&port->dev, "Unable to write latency timer: %i\n", rv);
 	return rv;
@@ -1181,24 +1170,29 @@
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	struct usb_device *udev = port->serial->dev;
-	unsigned short latency = 0;
-	int rv = 0;
-
+	unsigned char *buf;
+	int rv;
 
 	dbg("%s", __func__);
 
+	buf = kmalloc(1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
 	rv = usb_control_msg(udev,
 			     usb_rcvctrlpipe(udev, 0),
 			     FTDI_SIO_GET_LATENCY_TIMER_REQUEST,
 			     FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
 			     0, priv->interface,
-			     (char *) &latency, 1, WDR_TIMEOUT);
-
-	if (rv < 0) {
+			     buf, 1, WDR_TIMEOUT);
+	if (rv < 0)
 		dev_err(&port->dev, "Unable to read latency timer: %i\n", rv);
-		return -EIO;
-	}
-	return latency;
+	else
+		priv->latency = buf[0];
+
+	kfree(buf);
+
+	return rv;
 }
 
 static int get_serial_info(struct usb_serial_port *port,
@@ -1229,7 +1223,7 @@
 	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
 		return -EFAULT;
 
-	lock_kernel();
+	mutex_lock(&priv->cfg_lock);
 	old_priv = *priv;
 
 	/* Do error checking and permission checking */
@@ -1237,7 +1231,7 @@
 	if (!capable(CAP_SYS_ADMIN)) {
 		if (((new_serial.flags & ~ASYNC_USR_MASK) !=
 		     (priv->flags & ~ASYNC_USR_MASK))) {
-			unlock_kernel();
+			mutex_unlock(&priv->cfg_lock);
 			return -EPERM;
 		}
 		priv->flags = ((priv->flags & ~ASYNC_USR_MASK) |
@@ -1248,7 +1242,7 @@
 
 	if ((new_serial.baud_base != priv->baud_base) &&
 	    (new_serial.baud_base < 9600)) {
-	    	unlock_kernel();
+		mutex_unlock(&priv->cfg_lock);
 		return -EINVAL;
 	}
 
@@ -1278,11 +1272,11 @@
 	     (priv->flags & ASYNC_SPD_MASK)) ||
 	    (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
 	     (old_priv.custom_divisor != priv->custom_divisor))) {
-		unlock_kernel();
+		mutex_unlock(&priv->cfg_lock);
 		change_speed(tty, port);
 	}
 	else
-		unlock_kernel();
+		mutex_unlock(&priv->cfg_lock);
 	return 0;
 
 } /* set_serial_info */
@@ -1338,20 +1332,20 @@
 					__func__);
 		}
 	} else if (version < 0x200) {
-		/* Old device.  Assume its the original SIO. */
+		/* Old device.  Assume it's the original SIO. */
 		priv->chip_type = SIO;
 		priv->baud_base = 12000000 / 16;
 		priv->write_offset = 1;
 	} else if (version < 0x400) {
-		/* Assume its an FT8U232AM (or FT8U245AM) */
+		/* Assume it's an FT8U232AM (or FT8U245AM) */
 		/* (It might be a BM because of the iSerialNumber bug,
 		 * but it will still work as an AM device.) */
 		priv->chip_type = FT8U232AM;
 	} else if (version < 0x600) {
-		/* Assume its an FT232BM (or FT245BM) */
+		/* Assume it's an FT232BM (or FT245BM) */
 		priv->chip_type = FT232BM;
 	} else {
-		/* Assume its an FT232R  */
+		/* Assume it's an FT232R */
 		priv->chip_type = FT232RL;
 	}
 	dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
@@ -1371,7 +1365,7 @@
 	struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc;
 
 	unsigned num_endpoints;
-	int i = 0;
+	int i;
 
 	num_endpoints = interface->cur_altsetting->desc.bNumEndpoints;
 	dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints);
@@ -1423,7 +1417,7 @@
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	int v = simple_strtoul(valbuf, NULL, 10);
-	int rv = 0;
+	int rv;
 
 	priv->latency = v;
 	rv = write_latency_timer(port);
@@ -1440,9 +1434,8 @@
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	struct usb_device *udev = port->serial->dev;
-	char buf[1];
 	int v = simple_strtoul(valbuf, NULL, 10);
-	int rv = 0;
+	int rv;
 
 	dbg("%s: setting event char = %i", __func__, v);
 
@@ -1451,8 +1444,7 @@
 			     FTDI_SIO_SET_EVENT_CHAR_REQUEST,
 			     FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE,
 			     v, priv->interface,
-			     buf, 0, WDR_TIMEOUT);
-
+			     NULL, 0, WDR_TIMEOUT);
 	if (rv < 0) {
 		dbg("Unable to write event character: %i", rv);
 		return -EIO;
@@ -1551,9 +1543,9 @@
 
 	kref_init(&priv->kref);
 	spin_lock_init(&priv->tx_lock);
+	mutex_init(&priv->cfg_lock);
 	init_waitqueue_head(&priv->delta_msr_wait);
-	/* This will push the characters through immediately rather
-	   than queue a task to deliver them */
+
 	priv->flags = ASYNC_LOW_LATENCY;
 
 	if (quirk && quirk->port_probe)
@@ -1585,7 +1577,8 @@
 
 	ftdi_determine_type(port);
 	ftdi_set_max_packet_size(port);
-	read_latency_timer(port);
+	if (read_latency_timer(port) < 0)
+		priv->latency = 16;
 	create_sysfs_attrs(port);
 	return 0;
 }
@@ -1630,8 +1623,6 @@
 {
 	struct usb_device *udev = serial->dev;
 	int latency = ndi_latency_timer;
-	int rv = 0;
-	char buf[1];
 
 	if (latency == 0)
 		latency = 1;
@@ -1641,10 +1632,11 @@
 	dbg("%s setting NDI device latency to %d", __func__, latency);
 	dev_info(&udev->dev, "NDI device with a latency value of %d", latency);
 
-	rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+	/* FIXME: errors are not returned */
+	usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 				FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
 				FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
-				latency, 0, buf, 0, WDR_TIMEOUT);
+				latency, 0, NULL, 0, WDR_TIMEOUT);
 	return 0;
 }
 
@@ -1720,7 +1712,7 @@
 			   urb->transfer_buffer_length,
 			   ftdi_read_bulk_callback, port);
 	result = usb_submit_urb(urb, mem_flags);
-	if (result)
+	if (result && result != -EPERM)
 		dev_err(&port->dev,
 			"%s - failed submitting read urb, error %d\n",
 							__func__, result);
@@ -1732,16 +1724,10 @@
 	struct usb_device *dev = port->serial->dev;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
-
-	int result = 0;
-	char buf[1]; /* Needed for the usb_control_msg I think */
+	int result;
 
 	dbg("%s", __func__);
 
-	spin_lock_irqsave(&priv->tx_lock, flags);
-	priv->tx_bytes = 0;
-	spin_unlock_irqrestore(&priv->tx_lock, flags);
-
 	write_latency_timer(port);
 
 	/* No error checking for this (will get errors later anyway) */
@@ -1749,7 +1735,7 @@
 	usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE,
 			FTDI_SIO_RESET_SIO,
-			priv->interface, buf, 0, WDR_TIMEOUT);
+			priv->interface, NULL, 0, WDR_TIMEOUT);
 
 	/* Termios defaults are set by usb_serial_init. We don't change
 	   port->tty->termios - this would lose speed settings, etc.
@@ -1777,7 +1763,6 @@
 static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	char buf[1];
 
 	mutex_lock(&port->serial->disc_mutex);
 	if (!port->serial->disconnected) {
@@ -1786,7 +1771,7 @@
 			    usb_sndctrlpipe(port->serial->dev, 0),
 			    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 			    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-			    0, priv->interface, buf, 0,
+			    0, priv->interface, NULL, 0,
 			    WDR_TIMEOUT) < 0) {
 			    dev_err(&port->dev, "error from flowcontrol urb\n");
 		}
@@ -1847,7 +1832,7 @@
 	spin_lock_irqsave(&priv->tx_lock, flags);
 	if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) {
 		spin_unlock_irqrestore(&priv->tx_lock, flags);
-		dbg("%s - write limit hit\n", __func__);
+		dbg("%s - write limit hit", __func__);
 		return 0;
 	}
 	priv->tx_outstanding_urbs++;
@@ -1927,7 +1912,6 @@
 	} else {
 		spin_lock_irqsave(&priv->tx_lock, flags);
 		priv->tx_outstanding_bytes += count;
-		priv->tx_bytes += count;
 		spin_unlock_irqrestore(&priv->tx_lock, flags);
 	}
 
@@ -2154,8 +2138,7 @@
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	__u16 urb_value = 0;
-	char buf[1];
+	__u16 urb_value;
 
 	/* break_state = -1 to turn on break, and 0 to turn off break */
 	/* see drivers/char/tty_io.c to see it used */
@@ -2171,7 +2154,7 @@
 			FTDI_SIO_SET_DATA_REQUEST,
 			FTDI_SIO_SET_DATA_REQUEST_TYPE,
 			urb_value , priv->interface,
-			buf, 0, WDR_TIMEOUT) < 0) {
+			NULL, 0, WDR_TIMEOUT) < 0) {
 		dev_err(&port->dev, "%s FAILED to enable/disable break state "
 			"(state was %d)\n", __func__, break_state);
 	}
@@ -2195,7 +2178,6 @@
 	struct ktermios *termios = tty->termios;
 	unsigned int cflag = termios->c_cflag;
 	__u16 urb_value; /* will hold the new flags */
-	char buf[1]; /* Perhaps I should dynamically alloc this? */
 
 	/* Added for xon/xoff support */
 	unsigned int iflag = termios->c_iflag;
@@ -2246,12 +2228,10 @@
 	}
 	if (cflag & CSIZE) {
 		switch (cflag & CSIZE) {
-		case CS5: urb_value |= 5; dbg("Setting CS5"); break;
-		case CS6: urb_value |= 6; dbg("Setting CS6"); break;
 		case CS7: urb_value |= 7; dbg("Setting CS7"); break;
 		case CS8: urb_value |= 8; dbg("Setting CS8"); break;
 		default:
-			dev_err(&port->dev, "CSIZE was set but not CS5-CS8\n");
+			dev_err(&port->dev, "CSIZE was set but not CS7-CS8\n");
 		}
 	}
 
@@ -2263,7 +2243,7 @@
 			    FTDI_SIO_SET_DATA_REQUEST,
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
 			    urb_value , priv->interface,
-			    buf, 0, WDR_SHORT_TIMEOUT) < 0) {
+			    NULL, 0, WDR_SHORT_TIMEOUT) < 0) {
 		dev_err(&port->dev, "%s FAILED to set "
 			"databits/stopbits/parity\n", __func__);
 	}
@@ -2275,7 +2255,7 @@
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
 				    0, priv->interface,
-				    buf, 0, WDR_TIMEOUT) < 0) {
+				    NULL, 0, WDR_TIMEOUT) < 0) {
 			dev_err(&port->dev,
 				"%s error from disable flowcontrol urb\n",
 				__func__);
@@ -2301,7 +2281,7 @@
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
 				    0 , (FTDI_SIO_RTS_CTS_HS | priv->interface),
-				    buf, 0, WDR_TIMEOUT) < 0) {
+				    NULL, 0, WDR_TIMEOUT) < 0) {
 			dev_err(&port->dev,
 				"urb failed to set to rts/cts flow control\n");
 		}
@@ -2333,7 +2313,7 @@
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
 					    urb_value , (FTDI_SIO_XON_XOFF_HS
 							 | priv->interface),
-					    buf, 0, WDR_TIMEOUT) < 0) {
+					    NULL, 0, WDR_TIMEOUT) < 0) {
 				dev_err(&port->dev, "urb failed to set to "
 					"xon/xoff flow control\n");
 			}
@@ -2347,7 +2327,7 @@
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
 					    0, priv->interface,
-					    buf, 0, WDR_TIMEOUT) < 0) {
+					    NULL, 0, WDR_TIMEOUT) < 0) {
 				dev_err(&port->dev,
 					"urb failed to clear flow control\n");
 			}
@@ -2361,21 +2341,22 @@
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	unsigned char buf[2];
+	unsigned char *buf;
+	int len;
 	int ret;
 
 	dbg("%s TIOCMGET", __func__);
+
+	buf = kmalloc(2, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	/*
+	 * The 8U232AM returns a two byte value (the SIO a 1 byte value) in
+	 * the same format as the data returned from the in point.
+	 */
 	switch (priv->chip_type) {
 	case SIO:
-		/* Request the status from the device */
-		ret = usb_control_msg(port->serial->dev,
-			   usb_rcvctrlpipe(port->serial->dev, 0),
-			   FTDI_SIO_GET_MODEM_STATUS_REQUEST,
-			   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-			   0, 0,
-			   buf, 1, WDR_TIMEOUT);
-		if (ret < 0)
-			return ret;
+		len = 1;
 		break;
 	case FT8U232AM:
 	case FT232BM:
@@ -2383,27 +2364,30 @@
 	case FT232RL:
 	case FT2232H:
 	case FT4232H:
-		/* the 8U232AM returns a two byte value (the sio is a 1 byte
-		   value) - in the same format as the data returned from the in
-		   point */
-		ret = usb_control_msg(port->serial->dev,
-				   usb_rcvctrlpipe(port->serial->dev, 0),
-				   FTDI_SIO_GET_MODEM_STATUS_REQUEST,
-				   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-				   0, priv->interface,
-				   buf, 2, WDR_TIMEOUT);
-		if (ret < 0)
-			return ret;
+		len = 2;
 		break;
 	default:
-		return -EFAULT;
+		ret = -EFAULT;
+		goto out;
 	}
 
-	return  (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
+	ret = usb_control_msg(port->serial->dev,
+			usb_rcvctrlpipe(port->serial->dev, 0),
+			FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+			FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+			0, priv->interface,
+			buf, len, WDR_TIMEOUT);
+	if (ret < 0)
+		goto out;
+
+	ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
 		(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
 		(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
 		(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) |
 		priv->last_dtr_rts;
+out:
+	kfree(buf);
+	return ret;
 }
 
 static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,
@@ -2508,8 +2492,7 @@
 	port->throttled = port->throttle_req = 0;
 	spin_unlock_irqrestore(&port->lock, flags);
 
-	/* Resubmit urb if throttled and open. */
-	if (was_throttled && test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+	if (was_throttled)
 		ftdi_submit_read_urb(port, GFP_KERNEL);
 }
 
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index b0e0d64..ff9bf80 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -28,13 +28,13 @@
 #define FTDI_SIO_SET_FLOW_CTRL	2 /* Set flow control register */
 #define FTDI_SIO_SET_BAUD_RATE	3 /* Set baud rate */
 #define FTDI_SIO_SET_DATA	4 /* Set the data characteristics of the port */
-#define FTDI_SIO_GET_MODEM_STATUS	5 /* Retrieve current value of modern status register */
+#define FTDI_SIO_GET_MODEM_STATUS	5 /* Retrieve current value of modem status register */
 #define FTDI_SIO_SET_EVENT_CHAR	6 /* Set the event character */
 #define FTDI_SIO_SET_ERROR_CHAR	7 /* Set the error character */
 #define FTDI_SIO_SET_LATENCY_TIMER	9 /* Set the latency timer */
 #define FTDI_SIO_GET_LATENCY_TIMER	10 /* Get the latency timer */
 
-/* Interface indicies for FT2232, FT2232H and FT4232H devices*/
+/* Interface indices for FT2232, FT2232H and FT4232H devices */
 #define INTERFACE_A		1
 #define INTERFACE_B		2
 #define INTERFACE_C		3
@@ -270,7 +270,7 @@
  *   BmRequestType:  0100 0000b
  *   bRequest:       FTDI_SIO_SET_FLOW_CTRL
  *   wValue:         Xoff/Xon
- *   wIndex:         Protocol/Port - hIndex is protocl / lIndex is port
+ *   wIndex:         Protocol/Port - hIndex is protocol / lIndex is port
  *   wLength:        0
  *   Data:           None
  *
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index c8951ae..0727e19 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -22,7 +22,7 @@
 #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
 #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
 #define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
-#define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
+#define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX */
 #define FTDI_232RL_PID  0xFBFA  /* Product ID for FT232RL */
 
 
@@ -49,7 +49,7 @@
 #define LMI_LM3S_DEVEL_BOARD_PID	0xbcd8
 #define LMI_LM3S_EVAL_BOARD_PID		0xbcd9
 
-#define FTDI_TURTELIZER_PID	0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */
+#define FTDI_TURTELIZER_PID	0xBDC8 /* JTAG/RS-232 adapter by egnite GmbH */
 
 /* OpenDCC (www.opendcc.de) product id */
 #define FTDI_OPENDCC_PID	0xBFD8
@@ -185,7 +185,7 @@
 #define FTDI_ELV_TFD128_PID	0xE0EC	/* ELV Temperatur-Feuchte-Datenlogger TFD 128 */
 #define FTDI_ELV_FM3RX_PID	0xE0ED	/* ELV Messwertuebertragung FM3 RX */
 #define FTDI_ELV_WS777_PID	0xE0EE	/* Conrad WS 777 */
-#define FTDI_ELV_EM1010PC_PID	0xE0EF	/* Engery monitor EM 1010 PC */
+#define FTDI_ELV_EM1010PC_PID	0xE0EF	/* Energy monitor EM 1010 PC */
 #define FTDI_ELV_CSI8_PID	0xE0F0	/* Computer-Schalt-Interface (CSI 8) */
 #define FTDI_ELV_EM1000DL_PID	0xE0F1	/* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */
 #define FTDI_ELV_PCK100_PID	0xE0F2	/* PC-Kabeltester (PCK 100) */
@@ -212,8 +212,8 @@
  * drivers, or possibly the Comedi drivers in some cases. */
 #define FTDI_ELV_CLI7000_PID	0xFB59	/* Computer-Light-Interface (CLI 7000) */
 #define FTDI_ELV_PPS7330_PID	0xFB5C	/* Processor-Power-Supply (PPS 7330) */
-#define FTDI_ELV_TFM100_PID	0xFB5D	/* Temperartur-Feuchte Messgeraet (TFM 100) */
-#define FTDI_ELV_UDF77_PID	0xFB5E	/* USB DCF Funkurh (UDF 77) */
+#define FTDI_ELV_TFM100_PID	0xFB5D	/* Temperatur-Feuchte-Messgeraet (TFM 100) */
+#define FTDI_ELV_UDF77_PID	0xFB5E	/* USB DCF Funkuhr (UDF 77) */
 #define FTDI_ELV_UIO88_PID	0xFB5F	/* USB-I/O Interface (UIO 88) */
 
 /*
@@ -320,7 +320,7 @@
 
 /*
  * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485,
- * USB-TTY activ, USB-TTY passiv.  Some PIDs are used by several devices
+ * USB-TTY aktiv, USB-TTY passiv.  Some PIDs are used by several devices
  * and I'm not entirely sure which are used by which.
  */
 #define FTDI_4N_GALAXY_DE_1_PID	0xF3C0
@@ -330,10 +330,10 @@
  * Linx Technologies product ids
  */
 #define LINX_SDMUSBQSS_PID	0xF448	/* Linx SDM-USB-QS-S */
-#define LINX_MASTERDEVEL2_PID   0xF449   /* Linx Master Development 2.0 */
-#define LINX_FUTURE_0_PID   0xF44A   /* Linx future device */
-#define LINX_FUTURE_1_PID   0xF44B   /* Linx future device */
-#define LINX_FUTURE_2_PID   0xF44C   /* Linx future device */
+#define LINX_MASTERDEVEL2_PID   0xF449	/* Linx Master Development 2.0 */
+#define LINX_FUTURE_0_PID   0xF44A	/* Linx future device */
+#define LINX_FUTURE_1_PID   0xF44B	/* Linx future device */
+#define LINX_FUTURE_2_PID   0xF44C	/* Linx future device */
 
 /*
  * Oceanic product ids
@@ -494,6 +494,13 @@
 #define RATOC_PRODUCT_ID_USB60F	0xb020
 
 /*
+ * Contec products (http://www.contec.com)
+ * Submitted by Daniel Sangorrin
+ */
+#define CONTEC_VID		0x06CE	/* Vendor ID */
+#define CONTEC_COM1USBH_PID	0x8311	/* COM-1(USB)H */
+
+/*
  * Definitions for B&B Electronics products.
  */
 #define BANDB_VID		0x0856	/* B&B Electronics Vendor ID */
@@ -642,7 +649,7 @@
 #define FALCOM_TWIST_PID	0x0001	/* Falcom Twist USB GPRS modem */
 #define FALCOM_SAMBA_PID	0x0005	/* Falcom Samba USB GPRS modem */
 
-/* Larsen and Brusgaard AltiTrack/USBtrack  */
+/* Larsen and Brusgaard AltiTrack/USBtrack */
 #define LARSENBRUSGAARD_VID		0x0FD8
 #define LB_ALTITRACK_PID		0x0001
 
@@ -971,7 +978,7 @@
 #define ALTI2_N3_PID	0x6001	/* Neptune 3 */
 
 /*
- * Dresden Elektronic Sensor Terminal Board
+ * Dresden Elektronik Sensor Terminal Board
  */
 #define DE_VID			0x1cf1 /* Vendor ID */
 #define STB_PID			0x0001 /* Sensor Terminal Board */
@@ -1002,3 +1009,11 @@
 #define EVO_8U232AM_PID	0x02FF	/* Evolution robotics RCM2 (FT232AM)*/
 #define EVO_HYBRID_PID		0x0302	/* Evolution robotics RCM4 PID (FT232BM)*/
 #define EVO_RCM4_PID		0x0303	/* Evolution robotics RCM4 PID */
+
+/*
+ * MJS Gadgets HD Radio / XM Radio / Sirius Radio interfaces (using VID 0x0403)
+ */
+#define MJSG_GENERIC_PID	0x9378
+#define MJSG_SR_RADIO_PID	0x9379
+#define MJSG_XM_RADIO_PID	0x937A
+#define MJSG_HD_RADIO_PID	0x937C
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index d30f736..e21ce9d 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -18,7 +18,7 @@
 
 static int debug;
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x1404, 0xcddc) },
 	{ },
 };
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 5ac900e..a42b29a 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -210,7 +210,7 @@
 
 
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	/* the same device id seems to be used by all
 	   usb enabled GPS devices */
 	{ USB_DEVICE(GARMIN_VENDOR_ID, 3) },
@@ -271,7 +271,6 @@
 		usb_serial_debug_data(debug, &port->dev,
 					__func__, actual_length, data);
 
-		tty_buffer_request_room(tty, actual_length);
 		tty_insert_flip_string(tty, data, actual_length);
 		tty_flip_buffer_push(tty);
 	}
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 83443d6..89fac36 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -20,6 +20,7 @@
 #include <linux/usb/serial.h>
 #include <linux/uaccess.h>
 #include <linux/kfifo.h>
+#include <linux/serial.h>
 
 static int debug;
 
@@ -41,7 +42,7 @@
 
 /* we want to look at all devices, as the vendor/product id can change
  * depending on the command line argument */
-static struct usb_device_id generic_serial_ids[] = {
+static const struct usb_device_id generic_serial_ids[] = {
 	{.driver_info = 42},
 	{}
 };
@@ -194,7 +195,7 @@
 		if (port->urbs_in_flight >
 		    port->serial->type->max_in_flight_urbs) {
 			spin_unlock_irqrestore(&port->lock, flags);
-			dbg("%s - write limit hit\n", __func__);
+			dbg("%s - write limit hit", __func__);
 			return bwrite;
 		}
 		port->tx_bytes_flight += towrite;
@@ -585,7 +586,7 @@
 
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
-		if (!port->port.count)
+		if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
 			continue;
 
 		if (port->read_urb) {
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 4313292..8093791 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -29,7 +29,7 @@
 #define HP_VENDOR_ID 0x03f0
 #define HP49GP_PRODUCT_ID 0x0121
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(HP_VENDOR_ID, HP49GP_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index b97960a..3ef8df0 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -364,42 +364,6 @@
 	release_firmware(fw);
 }
 
-
-/************************************************************************
- *									*
- *  Get string descriptor from device					*
- *									*
- ************************************************************************/
-static int get_string(struct usb_device *dev, int Id, char *string, int buflen)
-{
-	struct usb_string_descriptor StringDesc;
-	struct usb_string_descriptor *pStringDesc;
-
-	dbg("%s - USB String ID = %d", __func__, Id);
-
-	if (!usb_get_descriptor(dev, USB_DT_STRING, Id,
-					&StringDesc, sizeof(StringDesc)))
-		return 0;
-
-	pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL);
-	if (!pStringDesc)
-		return 0;
-
-	if (!usb_get_descriptor(dev, USB_DT_STRING, Id,
-					pStringDesc, StringDesc.bLength)) {
-		kfree(pStringDesc);
-		return 0;
-	}
-
-	unicode_to_ascii(string, buflen,
-				pStringDesc->wData, pStringDesc->bLength/2);
-
-	kfree(pStringDesc);
-	dbg("%s - USB String %s", __func__, string);
-	return strlen(string);
-}
-
-
 #if 0
 /************************************************************************
  *
@@ -2007,7 +1971,7 @@
 			return;
 
 		case IOSP_EXT_STATUS_RX_CHECK_RSP:
-			dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3);
+			dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============", __func__, edge_serial->rxPort, byte3);
 			/* Port->RxCheckRsp = true; */
 			return;
 		}
@@ -2075,7 +2039,7 @@
 		break;
 
 	default:
-		dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
+		dbg("%s - Unrecognized IOSP status code %u", __func__, code);
 		break;
 	}
 	return;
@@ -2091,18 +2055,13 @@
 {
 	int cnt;
 
-	do {
-		cnt = tty_buffer_request_room(tty, length);
-		if (cnt < length) {
-			dev_err(dev, "%s - dropping data, %d bytes lost\n",
-					__func__, length - cnt);
-			if (cnt == 0)
-				break;
-		}
-		tty_insert_flip_string(tty, data, cnt);
-		data += cnt;
-		length -= cnt;
-	} while (length > 0);
+	cnt = tty_insert_flip_string(tty, data, length);
+	if (cnt < length) {
+		dev_err(dev, "%s - dropping data, %d bytes lost\n",
+				__func__, length - cnt);
+	}
+	data += cnt;
+	length -= cnt;
 
 	tty_flip_buffer_push(tty);
 }
@@ -2530,7 +2489,7 @@
 
 		*divisor = custom;
 
-		dbg("%s - Baud %d = %d\n", __func__, baudrate, custom);
+		dbg("%s - Baud %d = %d", __func__, baudrate, custom);
 		return 0;
 	}
 
@@ -2915,7 +2874,7 @@
 			break;
 
 		case EDGE_DOWNLOAD_FILE_NONE:
-			dbg     ("No download file specified, skipping download\n");
+			dbg("No download file specified, skipping download");
 			return;
 
 		default:
@@ -2997,10 +2956,12 @@
 	usb_set_serial_data(serial, edge_serial);
 
 	/* get the name for the device from the device */
-	i = get_string(dev, dev->descriptor.iManufacturer,
+	i = usb_string(dev, dev->descriptor.iManufacturer,
 	    &edge_serial->name[0], MAX_NAME_LEN+1);
+	if (i < 0)
+		i = 0;
 	edge_serial->name[i++] = ' ';
-	get_string(dev, dev->descriptor.iProduct,
+	usb_string(dev, dev->descriptor.iProduct,
 	    &edge_serial->name[i], MAX_NAME_LEN+2 - i);
 
 	dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name);
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 9241d31..feb56a4 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -14,7 +14,7 @@
 #ifndef IO_TABLES_H
 #define IO_TABLES_H
 
-static struct usb_device_id edgeport_2port_id_table [] = {
+static const struct usb_device_id edgeport_2port_id_table[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_421) },
@@ -23,7 +23,7 @@
 	{ }
 };
 
-static struct usb_device_id edgeport_4port_id_table [] = {
+static const struct usb_device_id edgeport_4port_id_table[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_RAPIDPORT_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4T) },
@@ -37,7 +37,7 @@
 	{ }
 };
 
-static struct usb_device_id edgeport_8port_id_table [] = {
+static const struct usb_device_id edgeport_8port_id_table[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8I) },
@@ -47,7 +47,7 @@
 	{ }
 };
 
-static struct usb_device_id Epic_port_id_table [] = {
+static const struct usb_device_id Epic_port_id_table[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0202) },
 	{ USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0203) },
 	{ USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0310) },
@@ -60,7 +60,7 @@
 };
 
 /* Devices that this driver supports */
-static struct usb_device_id id_table_combined [] = {
+static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_RAPIDPORT_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_4T) },
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index d4cc0f7..aa876f7 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -134,7 +134,7 @@
 
 
 /* Devices that this driver supports */
-static struct usb_device_id edgeport_1port_id_table [] = {
+static const struct usb_device_id edgeport_1port_id_table[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) },
@@ -154,7 +154,7 @@
 	{ }
 };
 
-static struct usb_device_id edgeport_2port_id_table [] = {
+static const struct usb_device_id edgeport_2port_id_table[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
@@ -177,7 +177,7 @@
 };
 
 /* Devices that this driver supports */
-static struct usb_device_id id_table_combined [] = {
+static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_1) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I) },
@@ -413,11 +413,18 @@
 {
 	int status = 0;
 	int i;
-	__u8 temp;
+	u8 *temp;
 
 	/* Must do a read before write */
 	if (!serial->TiReadI2C) {
-		status = read_boot_mem(serial, 0, 1, &temp);
+		temp = kmalloc(1, GFP_KERNEL);
+		if (!temp) {
+			dev_err(&serial->serial->dev->dev,
+					"%s - out of memory\n", __func__);
+			return -ENOMEM;
+		}
+		status = read_boot_mem(serial, 0, 1, temp);
+		kfree(temp);
 		if (status)
 			return status;
 	}
@@ -935,37 +942,47 @@
 static int i2c_type_bootmode(struct edgeport_serial *serial)
 {
 	int status;
-	__u8 data;
+	u8 *data;
+
+	data = kmalloc(1, GFP_KERNEL);
+	if (!data) {
+		dev_err(&serial->serial->dev->dev,
+				"%s - out of memory\n", __func__);
+		return -ENOMEM;
+	}
 
 	/* Try to read type 2 */
 	status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ,
-				DTK_ADDR_SPACE_I2C_TYPE_II, 0, &data, 0x01);
+				DTK_ADDR_SPACE_I2C_TYPE_II, 0, data, 0x01);
 	if (status)
 		dbg("%s - read 2 status error = %d", __func__, status);
 	else
-		dbg("%s - read 2 data = 0x%x", __func__, data);
-	if ((!status) && (data == UMP5152 || data == UMP3410)) {
+		dbg("%s - read 2 data = 0x%x", __func__, *data);
+	if ((!status) && (*data == UMP5152 || *data == UMP3410)) {
 		dbg("%s - ROM_TYPE_II", __func__);
 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
-		return 0;
+		goto out;
 	}
 
 	/* Try to read type 3 */
 	status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ,
-				DTK_ADDR_SPACE_I2C_TYPE_III, 0,	&data, 0x01);
+				DTK_ADDR_SPACE_I2C_TYPE_III, 0,	data, 0x01);
 	if (status)
 		dbg("%s - read 3 status error = %d", __func__, status);
 	else
-		dbg("%s - read 2 data = 0x%x", __func__, data);
-	if ((!status) && (data == UMP5152 || data == UMP3410)) {
+		dbg("%s - read 2 data = 0x%x", __func__, *data);
+	if ((!status) && (*data == UMP5152 || *data == UMP3410)) {
 		dbg("%s - ROM_TYPE_III", __func__);
 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III;
-		return 0;
+		goto out;
 	}
 
 	dbg("%s - Unknown", __func__);
 	serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
-	return -ENODEV;
+	status = -ENODEV;
+out:
+	kfree(data);
+	return status;
 }
 
 static int bulk_xfer(struct usb_serial *serial, void *buffer,
@@ -1113,7 +1130,7 @@
 				I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
 		if (start_address != 0) {
 			struct ti_i2c_firmware_rec *firmware_version;
-			__u8 record;
+			u8 *record;
 
 			dbg("%s - Found Type FIRMWARE (Type 2) record",
 								__func__);
@@ -1165,6 +1182,15 @@
 				    OperationalMajorVersion,
 				    OperationalMinorVersion);
 
+				record = kmalloc(1, GFP_KERNEL);
+				if (!record) {
+					dev_err(dev, "%s - out of memory.\n",
+							__func__);
+					kfree(firmware_version);
+					kfree(rom_desc);
+					kfree(ti_manuf_desc);
+					return -ENOMEM;
+				}
 				/* In order to update the I2C firmware we must
 				 * change the type 2 record to type 0xF2. This
 				 * will force the UMP to come up in Boot Mode.
@@ -1177,13 +1203,14 @@
 				 * firmware will update the record type from
 				 * 0xf2 to 0x02.
 				 */
-				record = I2C_DESC_TYPE_FIRMWARE_BLANK;
+				*record = I2C_DESC_TYPE_FIRMWARE_BLANK;
 
 				/* Change the I2C Firmware record type to
 				   0xf2 to trigger an update */
 				status = write_rom(serial, start_address,
-						sizeof(record),	&record);
+						sizeof(*record), record);
 				if (status) {
+					kfree(record);
 					kfree(firmware_version);
 					kfree(rom_desc);
 					kfree(ti_manuf_desc);
@@ -1196,19 +1223,21 @@
 				 */
 				status = read_rom(serial,
 							start_address,
-							sizeof(record),
-							&record);
+							sizeof(*record),
+							record);
 				if (status) {
+					kfree(record);
 					kfree(firmware_version);
 					kfree(rom_desc);
 					kfree(ti_manuf_desc);
 					return status;
 				}
 
-				if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
+				if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
 					dev_err(dev,
 						"%s - error resetting device\n",
 						__func__);
+					kfree(record);
 					kfree(firmware_version);
 					kfree(rom_desc);
 					kfree(ti_manuf_desc);
@@ -1226,6 +1255,7 @@
 						__func__, status);
 
 				/* return an error on purpose. */
+				kfree(record);
 				kfree(firmware_version);
 				kfree(rom_desc);
 				kfree(ti_manuf_desc);
@@ -1686,7 +1716,7 @@
 	case TIUMP_INTERRUPT_CODE_MSR:	/* MSR */
 		/* Copy MSR from UMP */
 		msr = data[1];
-		dbg("%s - ===== Port %u MSR Status = %02x ======\n",
+		dbg("%s - ===== Port %u MSR Status = %02x ======",
 		     __func__, port_number, msr);
 		handle_new_msr(edge_port, msr);
 		break;
@@ -1790,7 +1820,6 @@
 {
 	int queued;
 
-	tty_buffer_request_room(tty, length);
 	queued = tty_insert_flip_string(tty, data, length);
 	if (queued < length)
 		dev_err(dev, "%s - dropping data, %d bytes lost\n",
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index d6231c3..3fea929 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -747,7 +747,6 @@
 
 	tty = tty_port_tty_get(&port->port);
 	if (tty && urb->actual_length) {
-		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 		bytes_in += urb->actual_length;
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 727d323..e1d0784 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -134,7 +134,7 @@
 
 #define IPW_WANTS_TO_SEND	0x30
 
-static struct usb_device_id usb_ipw_ids[] = {
+static const struct usb_device_id usb_ipw_ids[] = {
 	{ USB_DEVICE(IPW_VID, IPW_PID) },
 	{ },
 };
@@ -172,7 +172,6 @@
 
 	tty = tty_port_tty_get(&port->port);
 	if (tty && urb->actual_length) {
-		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 95d8d26..4a0f519 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -100,7 +100,7 @@
 static u8 ir_xbof;
 static u8 ir_add_bof;
 
-static struct usb_device_id ir_id_table[] = {
+static const struct usb_device_id ir_id_table[] = {
 	{ USB_DEVICE(0x050f, 0x0180) },		/* KC Technology, KC-180 */
 	{ USB_DEVICE(0x08e9, 0x0100) },		/* XTNDAccess */
 	{ USB_DEVICE(0x09c4, 0x0011) },		/* ACTiSys ACT-IR2000U */
@@ -445,11 +445,6 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	if (!port->port.count) {
-		dbg("%s - port closed.", __func__);
-		return;
-	}
-
 	switch (status) {
 	case 0: /* Successful */
 		/*
@@ -462,10 +457,8 @@
 		usb_serial_debug_data(debug, &port->dev, __func__,
 						urb->actual_length, data);
 		tty = tty_port_tty_get(&port->port);
-		if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
-			tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
-			tty_flip_buffer_push(tty);
-		}
+		tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
+		tty_flip_buffer_push(tty);
 		tty_kref_put(tty);
 
 		/*
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index e6e02b1..43f13cf 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -43,7 +43,7 @@
 #define DRIVER_VERSION "v0.11"
 #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver"
 
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
 	{USB_DEVICE(IUU_USB_VENDOR_ID, IUU_USB_PRODUCT_ID)},
 	{}			/* Terminating entry */
 };
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index f8c4b07..297163c 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -464,13 +464,9 @@
 
 	/* Resubmit urb so we continue receiving */
 	urb->dev = port->serial->dev;
-	if (port->port.count) {
-		err = usb_submit_urb(urb, GFP_ATOMIC);
-		if (err != 0)
-			dbg("%s - resubmit read urb failed. (%d)",
-					__func__, err);
-	}
-	return;
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err != 0)
+		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
 }
 
 /* Outdat handling is common for all devices */
@@ -483,8 +479,7 @@
 	p_priv = usb_get_serial_port_data(port);
 	dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
 
-	if (port->port.count)
-		usb_serial_port_softint(port);
+	usb_serial_port_softint(port);
 }
 
 static void	usa26_inack_callback(struct urb *urb)
@@ -615,12 +610,10 @@
 
 		/* Resubmit urb so we continue receiving */
 		urb->dev = port->serial->dev;
-		if (port->port.count) {
-			err = usb_submit_urb(urb, GFP_ATOMIC);
-			if (err != 0)
-				dbg("%s - resubmit read urb failed. (%d)",
-								__func__, err);
-		}
+		err = usb_submit_urb(urb, GFP_ATOMIC);
+		if (err != 0)
+			dbg("%s - resubmit read urb failed. (%d)",
+							__func__, err);
 		p_priv->in_flip ^= 1;
 
 		urb = p_priv->in_urbs[p_priv->in_flip];
@@ -856,12 +849,9 @@
 
 	/* Resubmit urb so we continue receiving */
 	urb->dev = port->serial->dev;
-	if (port->port.count) {
-		err = usb_submit_urb(urb, GFP_ATOMIC);
-		if (err != 0)
-			dbg("%s - resubmit read urb failed. (%d)",
-							__func__, err);
-	}
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err != 0)
+		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
 }
 
 static void usa49wg_indat_callback(struct urb *urb)
@@ -904,11 +894,7 @@
 				/* no error on any byte */
 				i++;
 				for (x = 1; x < len ; ++x)
-					if (port->port.count)
-						tty_insert_flip_char(tty,
-								data[i++], 0);
-					else
-						i++;
+					tty_insert_flip_char(tty, data[i++], 0);
 			} else {
 				/*
 				 * some bytes had errors, every byte has status
@@ -922,14 +908,12 @@
 					if (stat & RXERROR_PARITY)
 						flag |= TTY_PARITY;
 					/* XXX should handle break (0x10) */
-					if (port->port.count)
-						tty_insert_flip_char(tty,
+					tty_insert_flip_char(tty,
 							data[i+1], flag);
 					i += 2;
 				}
 			}
-			if (port->port.count)
-				tty_flip_buffer_push(tty);
+			tty_flip_buffer_push(tty);
 			tty_kref_put(tty);
 		}
 	}
@@ -1013,13 +997,9 @@
 
 	/* Resubmit urb so we continue receiving */
 	urb->dev = port->serial->dev;
-	if (port->port.count) {
-		err = usb_submit_urb(urb, GFP_ATOMIC);
-		if (err != 0)
-			dbg("%s - resubmit read urb failed. (%d)",
-							__func__, err);
-	}
-	return;
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err != 0)
+		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
 }
 
 
@@ -2418,8 +2398,7 @@
 		msg.portEnabled = 0;
 	/* Sending intermediate configs */
 	else {
-		if (port->port.count)
-			msg.portEnabled = 1;
+		msg.portEnabled = 1;
 		msg.txBreak = (p_priv->break_on);
 	}
 
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 30771e5..bf3297d 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -456,7 +456,7 @@
 	NULL,
 };
 
-static struct usb_device_id keyspan_ids_combined[] = {
+static const struct usb_device_id keyspan_ids_combined[] = {
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_pre_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) },
@@ -497,7 +497,7 @@
 };
 
 /* usb_device_id table for the pre-firmware download keyspan devices */
-static struct usb_device_id keyspan_pre_ids[] = {
+static const struct usb_device_id keyspan_pre_ids[] = {
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_pre_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_pre_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_pre_product_id) },
@@ -513,7 +513,7 @@
 	{ } /* Terminating entry */
 };
 
-static struct usb_device_id keyspan_1port_ids[] = {
+static const struct usb_device_id keyspan_1port_ids[] = {
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) },
@@ -524,7 +524,7 @@
 	{ } /* Terminating entry */
 };
 
-static struct usb_device_id keyspan_2port_ids[] = {
+static const struct usb_device_id keyspan_2port_ids[] = {
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
@@ -532,7 +532,7 @@
 	{ } /* Terminating entry */
 };
 
-static struct usb_device_id keyspan_4port_ids[] = {
+static const struct usb_device_id keyspan_4port_ids[] = {
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 1296a09..185fe9a 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -125,7 +125,7 @@
 #define ENTREGRA_VENDOR_ID		0x1645
 #define ENTREGRA_FAKE_ID		0x8093
 
-static struct usb_device_id id_table_combined [] = {
+static const struct usb_device_id id_table_combined[] = {
 #ifdef KEYSPAN
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_FAKE_ID) },
 #endif
@@ -147,20 +147,20 @@
 	.no_dynamic_id = 	1,
 };
 
-static struct usb_device_id id_table_std [] = {
+static const struct usb_device_id id_table_std[] = {
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_ID) },
 	{ }						/* Terminating entry */
 };
 
 #ifdef KEYSPAN
-static struct usb_device_id id_table_fake [] = {
+static const struct usb_device_id id_table_fake[] = {
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, KEYSPAN_PDA_FAKE_ID) },
 	{ }						/* Terminating entry */
 };
 #endif
 
 #ifdef XIRCOM
-static struct usb_device_id id_table_fake_xircom [] = {
+static const struct usb_device_id id_table_fake_xircom[] = {
 	{ USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) },
 	{ USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) },
 	{ }
@@ -429,13 +429,20 @@
 				      unsigned char *value)
 {
 	int rc;
-	unsigned char data;
+	u8 *data;
+
+	data = kmalloc(1, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
 	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 			     3, /* get pins */
 			     USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN,
-			     0, 0, &data, 1, 2000);
+			     0, 0, data, 1, 2000);
 	if (rc >= 0)
-		*value = data;
+		*value = *data;
+
+	kfree(data);
 	return rc;
 }
 
@@ -543,7 +550,14 @@
 	   device how much room it really has.  This is done only on
 	   scheduler time, since usb_control_msg() sleeps. */
 	if (count > priv->tx_room && !in_interrupt()) {
-		unsigned char room;
+		u8 *room;
+
+		room = kmalloc(1, GFP_KERNEL);
+		if (!room) {
+			rc = -ENOMEM;
+			goto exit;
+		}
+
 		rc = usb_control_msg(serial->dev,
 				     usb_rcvctrlpipe(serial->dev, 0),
 				     6, /* write_room */
@@ -551,9 +565,14 @@
 				     | USB_DIR_IN,
 				     0, /* value: 0 means "remaining room" */
 				     0, /* index */
-				     &room,
+				     room,
 				     1,
 				     2000);
+		if (rc > 0) {
+			dbg(" roomquery says %d", *room);
+			priv->tx_room = *room;
+		}
+		kfree(room);
 		if (rc < 0) {
 			dbg(" roomquery failed");
 			goto exit;
@@ -563,8 +582,6 @@
 			rc = -EIO; /* device didn't return any data */
 			goto exit;
 		}
-		dbg(" roomquery says %d", room);
-		priv->tx_room = room;
 	}
 	if (count > priv->tx_room) {
 		/* we're about to completely fill the Tx buffer, so
@@ -684,18 +701,22 @@
 					struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
-	unsigned char room;
+	u8 *room;
 	int rc = 0;
 	struct keyspan_pda_private *priv;
 
 	/* find out how much room is in the Tx ring */
+	room = kmalloc(1, GFP_KERNEL);
+	if (!room)
+		return -ENOMEM;
+
 	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 			     6, /* write_room */
 			     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
 			     | USB_DIR_IN,
 			     0, /* value */
 			     0, /* index */
-			     &room,
+			     room,
 			     1,
 			     2000);
 	if (rc < 0) {
@@ -708,8 +729,8 @@
 		goto error;
 	}
 	priv = usb_get_serial_port_data(port);
-	priv->tx_room = room;
-	priv->tx_throttled = room ? 0 : 1;
+	priv->tx_room = *room;
+	priv->tx_throttled = *room ? 0 : 1;
 
 	/*Start reading from the device*/
 	port->interrupt_in_urb->dev = serial->dev;
@@ -718,8 +739,8 @@
 		dbg("%s - usb_submit_urb(read int) failed", __func__);
 		goto error;
 	}
-
 error:
+	kfree(room);
 	return rc;
 }
 static void keyspan_pda_close(struct usb_serial_port *port)
@@ -789,6 +810,13 @@
 	return 1;
 }
 
+#ifdef KEYSPAN
+MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw");
+#endif
+#ifdef XIRCOM
+MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw");
+#endif
+
 static int keyspan_pda_startup(struct usb_serial *serial)
 {
 
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 3a78738..8eef91b 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -94,7 +94,7 @@
 /*
  * All of the device info needed for the KLSI converters.
  */
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(PALMCONNECT_VID, PALMCONNECT_PID) },
 	{ USB_DEVICE(KLSI_VID, KLSI_KL5KUSB105D_PID) },
 	{ }		/* Terminating entry */
@@ -212,10 +212,19 @@
 				   unsigned long *line_state_p)
 {
 	int rc;
-	__u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1};
+	u8 *status_buf;
 	__u16 status;
 
 	dev_info(&port->serial->dev->dev, "sending SIO Poll request\n");
+
+	status_buf = kmalloc(KLSI_STATUSBUF_LEN, GFP_KERNEL);
+	if (!status_buf) {
+		dev_err(&port->dev, "%s - out of memory for status buffer.\n",
+				__func__);
+		return -ENOMEM;
+	}
+	status_buf[0] = 0xff;
+	status_buf[1] = 0xff;
 	rc = usb_control_msg(port->serial->dev,
 			     usb_rcvctrlpipe(port->serial->dev, 0),
 			     KL5KUSB105A_SIO_POLL,
@@ -236,6 +245,8 @@
 
 		*line_state_p = klsi_105_status2linestate(status);
 	}
+
+	kfree(status_buf);
 	return rc;
 }
 
@@ -364,7 +375,7 @@
 	int rc;
 	int i;
 	unsigned long line_state;
-	struct klsi_105_port_settings cfg;
+	struct klsi_105_port_settings *cfg;
 	unsigned long flags;
 
 	dbg("%s port %d", __func__, port->number);
@@ -376,12 +387,18 @@
 	 * Then read the modem line control and store values in
 	 * priv->line_state.
 	 */
-	cfg.pktlen   = 5;
-	cfg.baudrate = kl5kusb105a_sio_b9600;
-	cfg.databits = kl5kusb105a_dtb_8;
-	cfg.unknown1 = 0;
-	cfg.unknown2 = 1;
-	klsi_105_chg_port_settings(port, &cfg);
+	cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
+	if (!cfg) {
+		dev_err(&port->dev, "%s - out of memory for config buffer.\n",
+				__func__);
+		return -ENOMEM;
+	}
+	cfg->pktlen   = 5;
+	cfg->baudrate = kl5kusb105a_sio_b9600;
+	cfg->databits = kl5kusb105a_dtb_8;
+	cfg->unknown1 = 0;
+	cfg->unknown2 = 1;
+	klsi_105_chg_port_settings(port, cfg);
 
 	/* set up termios structure */
 	spin_lock_irqsave(&priv->lock, flags);
@@ -391,11 +408,11 @@
 	priv->termios.c_lflag = tty->termios->c_lflag;
 	for (i = 0; i < NCCS; i++)
 		priv->termios.c_cc[i] = tty->termios->c_cc[i];
-	priv->cfg.pktlen   = cfg.pktlen;
-	priv->cfg.baudrate = cfg.baudrate;
-	priv->cfg.databits = cfg.databits;
-	priv->cfg.unknown1 = cfg.unknown1;
-	priv->cfg.unknown2 = cfg.unknown2;
+	priv->cfg.pktlen   = cfg->pktlen;
+	priv->cfg.baudrate = cfg->baudrate;
+	priv->cfg.databits = cfg->databits;
+	priv->cfg.unknown1 = cfg->unknown1;
+	priv->cfg.unknown2 = cfg->unknown2;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* READ_ON and urb submission */
@@ -441,6 +458,7 @@
 		retval = rc;
 
 exit:
+	kfree(cfg);
 	return retval;
 } /* klsi_105_open */
 
@@ -681,7 +699,6 @@
 			bytes_sent = urb->actual_length - 2;
 		}
 
-		tty_buffer_request_room(tty, bytes_sent);
 		tty_insert_flip_string(tty, data + 2, bytes_sent);
 		tty_flip_buffer_push(tty);
 		tty_kref_put(tty);
@@ -714,10 +731,17 @@
 	unsigned int old_iflag = old_termios->c_iflag;
 	unsigned int cflag = tty->termios->c_cflag;
 	unsigned int old_cflag = old_termios->c_cflag;
-	struct klsi_105_port_settings cfg;
+	struct klsi_105_port_settings *cfg;
 	unsigned long flags;
 	speed_t baud;
 
+	cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
+	if (!cfg) {
+		dev_err(&port->dev, "%s - out of memory for config buffer.\n",
+				__func__);
+		return;
+	}
+
 	/* lock while we are modifying the settings */
 	spin_lock_irqsave(&priv->lock, flags);
 
@@ -793,11 +817,11 @@
 		case CS5:
 			dbg("%s - 5 bits/byte not supported", __func__);
 			spin_unlock_irqrestore(&priv->lock, flags);
-			return ;
+			goto err;
 		case CS6:
 			dbg("%s - 6 bits/byte not supported", __func__);
 			spin_unlock_irqrestore(&priv->lock, flags);
-			return ;
+			goto err;
 		case CS7:
 			priv->cfg.databits = kl5kusb105a_dtb_7;
 			break;
@@ -856,11 +880,13 @@
 #endif
 		;
 	}
-	memcpy(&cfg, &priv->cfg, sizeof(cfg));
+	memcpy(cfg, &priv->cfg, sizeof(*cfg));
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* now commit changes to device */
-	klsi_105_chg_port_settings(port, &cfg);
+	klsi_105_chg_port_settings(port, cfg);
+err:
+	kfree(cfg);
 } /* klsi_105_set_termios */
 
 
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 45ea694..c113a2a 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -86,7 +86,7 @@
 			struct usb_serial_port *port, struct ktermios *old);
 static void kobil_init_termios(struct tty_struct *tty);
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) },
 	{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_K_PRODUCT_ID) },
 	{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_USBTWIN_PRODUCT_ID) },
@@ -388,7 +388,6 @@
 		*/
 		/* END DEBUG */
 
-		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
@@ -624,7 +623,6 @@
 	unsigned short urb_val = 0;
 	int c_cflag = tty->termios->c_cflag;
 	speed_t speed;
-	void *settings;
 
 	priv = usb_get_serial_port_data(port);
 	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
@@ -647,25 +645,13 @@
 	}
 	urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits :
 							SUSBCR_SPASB_1StopBit;
-
-	settings = kzalloc(50, GFP_KERNEL);
-	if (!settings)
-		return;
-
-	sprintf(settings, "%d ", speed);
-
 	if (c_cflag & PARENB) {
-		if  (c_cflag & PARODD) {
+		if  (c_cflag & PARODD)
 			urb_val |= SUSBCR_SPASB_OddParity;
-			strcat(settings, "Odd Parity");
-		} else {
+		else
 			urb_val |= SUSBCR_SPASB_EvenParity;
-			strcat(settings, "Even Parity");
-		}
-	} else {
+	} else
 		urb_val |= SUSBCR_SPASB_NoParity;
-		strcat(settings, "No Parity");
-	}
 	tty->termios->c_cflag &= ~CMSPAR;
 	tty_encode_baud_rate(tty, speed, speed);
 
@@ -675,11 +661,10 @@
 		  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 		  urb_val,
 		  0,
-		  settings,
+		  NULL,
 		  0,
 		  KOBIL_TIMEOUT
 		);
-	kfree(settings);
 }
 
 static int kobil_ioctl(struct tty_struct *tty, struct file *file,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index cd009cb..2849f8c 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -75,6 +75,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
+#include <asm/unaligned.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "mct_u232.h"
@@ -110,7 +111,7 @@
 /*
  * All of the device info needed for the MCT USB-RS232 converter.
  */
-static struct usb_device_id id_table_combined [] = {
+static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
@@ -231,19 +232,22 @@
 static int mct_u232_set_baud_rate(struct tty_struct *tty,
 	struct usb_serial *serial, struct usb_serial_port *port, speed_t value)
 {
-	__le32 divisor;
+	unsigned int divisor;
 	int rc;
-	unsigned char zero_byte = 0;
+	unsigned char *buf;
 	unsigned char cts_enable_byte = 0;
 	speed_t speed;
 
-	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value,
-								&speed));
+	buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
 
+	divisor = mct_u232_calculate_baud_rate(serial, value, &speed);
+	put_unaligned_le32(cpu_to_le32(divisor), buf);
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 				MCT_U232_SET_BAUD_RATE_REQUEST,
 				MCT_U232_SET_REQUEST_TYPE,
-				0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
+				0, 0, buf, MCT_U232_SET_BAUD_RATE_SIZE,
 				WDR_TIMEOUT);
 	if (rc < 0)	/*FIXME: What value speed results */
 		dev_err(&port->dev, "Set BAUD RATE %d failed (error = %d)\n",
@@ -269,10 +273,11 @@
 	   a device which is not asserting 'CTS'.
 	*/
 
+	buf[0] = 0;
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 				MCT_U232_SET_UNKNOWN1_REQUEST,
 				MCT_U232_SET_REQUEST_TYPE,
-				0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE,
+				0, 0, buf, MCT_U232_SET_UNKNOWN1_SIZE,
 				WDR_TIMEOUT);
 	if (rc < 0)
 		dev_err(&port->dev, "Sending USB device request code %d "
@@ -284,30 +289,40 @@
 
 	dbg("set_baud_rate: send second control message, data = %02X",
 							cts_enable_byte);
+	buf[0] = cts_enable_byte;
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			MCT_U232_SET_CTS_REQUEST,
 			MCT_U232_SET_REQUEST_TYPE,
-			0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
+			0, 0, buf, MCT_U232_SET_CTS_SIZE,
 			WDR_TIMEOUT);
 	if (rc < 0)
 		dev_err(&port->dev, "Sending USB device request code %d "
 			"failed (error = %d)\n", MCT_U232_SET_CTS_REQUEST, rc);
 
+	kfree(buf);
 	return rc;
 } /* mct_u232_set_baud_rate */
 
 static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
 {
 	int rc;
+	unsigned char *buf;
+
+	buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	buf[0] = lcr;
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			MCT_U232_SET_LINE_CTRL_REQUEST,
 			MCT_U232_SET_REQUEST_TYPE,
-			0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
+			0, 0, buf, MCT_U232_SET_LINE_CTRL_SIZE,
 			WDR_TIMEOUT);
 	if (rc < 0)
 		dev_err(&serial->dev->dev,
 			"Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc);
 	dbg("set_line_ctrl: 0x%x", lcr);
+	kfree(buf);
 	return rc;
 } /* mct_u232_set_line_ctrl */
 
@@ -315,23 +330,31 @@
 				   unsigned int control_state)
 {
 	int rc;
-	unsigned char mcr = MCT_U232_MCR_NONE;
+	unsigned char mcr;
+	unsigned char *buf;
 
+	buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	mcr = MCT_U232_MCR_NONE;
 	if (control_state & TIOCM_DTR)
 		mcr |= MCT_U232_MCR_DTR;
 	if (control_state & TIOCM_RTS)
 		mcr |= MCT_U232_MCR_RTS;
 
+	buf[0] = mcr;
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			MCT_U232_SET_MODEM_CTRL_REQUEST,
 			MCT_U232_SET_REQUEST_TYPE,
-			0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
+			0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE,
 			WDR_TIMEOUT);
 	if (rc < 0)
 		dev_err(&serial->dev->dev,
 			"Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
 	dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
 
+	kfree(buf);
 	return rc;
 } /* mct_u232_set_modem_ctrl */
 
@@ -339,17 +362,27 @@
 						unsigned char *msr)
 {
 	int rc;
+	unsigned char *buf;
+
+	buf = kmalloc(MCT_U232_MAX_SIZE, GFP_KERNEL);
+	if (buf == NULL) {
+		*msr = 0;
+		return -ENOMEM;
+	}
 	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 			MCT_U232_GET_MODEM_STAT_REQUEST,
 			MCT_U232_GET_REQUEST_TYPE,
-			0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
+			0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE,
 			WDR_TIMEOUT);
 	if (rc < 0) {
 		dev_err(&serial->dev->dev,
 			"Get MODEM STATus failed (error = %d)\n", rc);
 		*msr = 0;
+	} else {
+		*msr = buf[0];
 	}
 	dbg("get_modem_stat: 0x%x", *msr);
+	kfree(buf);
 	return rc;
 } /* mct_u232_get_modem_stat */
 
diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h
index 07b6bec..7417d5c 100644
--- a/drivers/usb/serial/mct_u232.h
+++ b/drivers/usb/serial/mct_u232.h
@@ -73,6 +73,8 @@
 #define MCT_U232_SET_CTS_REQUEST   12
 #define MCT_U232_SET_CTS_SIZE       1
 
+#define MCT_U232_MAX_SIZE		4	/* of MCT_XXX_SIZE */
+
 /*
  * Baud rate (divisor)
  * Actually, there are two of them, MCT website calls them "Philips solution"
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 763e32a..0d47f2c 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -81,12 +81,15 @@
 
 static int debug;
 
+static struct usb_serial_driver moschip7720_2port_driver;
+
 #define USB_VENDOR_ID_MOSCHIP		0x9710
 #define MOSCHIP_DEVICE_ID_7720		0x7720
 #define MOSCHIP_DEVICE_ID_7715		0x7715
 
-static struct usb_device_id moschip_port_id_table[] = {
+static const struct usb_device_id moschip_port_id_table[] = {
 	{ USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) },
+	{ USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7715) },
 	{ } /* terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, moschip_port_id_table);
@@ -106,7 +109,7 @@
 	__u8 sp1;
 	__u8 sp2;
 
-	dbg("%s", " : Entering\n");
+	dbg(" : Entering");
 
 	switch (status) {
 	case 0:
@@ -186,6 +189,75 @@
 }
 
 /*
+ * mos7715_interrupt_callback
+ *	this is the 7715's callback function for when we have received data on
+ *	the interrupt endpoint.
+ */
+static void mos7715_interrupt_callback(struct urb *urb)
+{
+	int result;
+	int length;
+	int status = urb->status;
+	__u8 *data;
+	__u8 iir;
+
+	switch (status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d", __func__,
+		    status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d", __func__,
+		    status);
+		goto exit;
+	}
+
+	length = urb->actual_length;
+	data = urb->transfer_buffer;
+
+	/* Structure of data from 7715 device:
+	 * Byte 1: IIR serial Port
+	 * Byte 2: unused
+	 * Byte 2: DSR parallel port
+	 * Byte 4: FIFO status for both */
+
+	if (unlikely(length != 4)) {
+		dbg("Wrong data !!!");
+		return;
+	}
+
+	iir = data[0];
+	if (!(iir & 0x01)) {	/* serial port interrupt pending */
+		switch (iir & 0x0f) {
+		case SERIAL_IIR_RLS:
+			dbg("Serial Port: Receiver status error or address "
+			    "bit detected in 9-bit mode\n");
+			break;
+		case SERIAL_IIR_CTI:
+			dbg("Serial Port: Receiver time out");
+			break;
+		case SERIAL_IIR_MS:
+			dbg("Serial Port: Modem status change");
+			break;
+		}
+	}
+
+exit:
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result)
+		dev_err(&urb->dev->dev,
+			"%s - Error %d submitting control urb\n",
+			__func__, result);
+	return;
+}
+
+/*
  * mos7720_bulk_in_callback
  *	this is the callback function for when we have received data on the
  *	bulk in endpoint.
@@ -206,7 +278,7 @@
 
 	mos7720_port = urb->context;
 	if (!mos7720_port) {
-		dbg("%s", "NULL mos7720_port pointer \n");
+		dbg("NULL mos7720_port pointer");
 		return ;
 	}
 
@@ -218,7 +290,6 @@
 
 	tty = tty_port_tty_get(&port->port);
 	if (tty && urb->actual_length) {
-		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
@@ -275,17 +346,15 @@
  *	this function will be used for sending command to device
  */
 static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value,
-			__u16 index, void *data)
+			__u16 index, u8 *data)
 {
 	int status;
-	unsigned int pipe;
+	u8 *buf;
 	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
-	__u8 requesttype;
-	__u16 size = 0x0000;
 
 	if (value < MOS_MAX_PORT) {
 		if (product == MOSCHIP_DEVICE_ID_7715)
-			value = value*0x100+0x100;
+			value = 0x0200; /* identifies the 7715's serial port */
 		else
 			value = value*0x100+0x200;
 	} else {
@@ -298,27 +367,58 @@
 	}
 
 	if (request == MOS_WRITE) {
-		request = (__u8)MOS_WRITE;
-		requesttype = (__u8)0x40;
-		value  = value + (__u16)*((unsigned char *)data);
-		data = NULL;
-		pipe = usb_sndctrlpipe(serial->dev, 0);
+		value = value + *data;
+		status = usb_control_msg(serial->dev,
+				usb_sndctrlpipe(serial->dev, 0), MOS_WRITE,
+				0x40, value, index, NULL, 0, MOS_WDR_TIMEOUT);
 	} else {
-		request = (__u8)MOS_READ;
-		requesttype = (__u8)0xC0;
-		size = 0x01;
-		pipe = usb_rcvctrlpipe(serial->dev, 0);
+		buf = kmalloc(1, GFP_KERNEL);
+		if (!buf) {
+			status = -ENOMEM;
+			goto out;
+		}
+		status = usb_control_msg(serial->dev,
+				usb_rcvctrlpipe(serial->dev, 0), MOS_READ,
+				0xc0, value, index, buf, 1, MOS_WDR_TIMEOUT);
+		*data = *buf;
+		kfree(buf);
 	}
-
-	status = usb_control_msg(serial->dev, pipe, request, requesttype,
-				 value, index, data, size, MOS_WDR_TIMEOUT);
-
+out:
 	if (status < 0)
-		dbg("Command Write failed Value %x index %x\n", value, index);
+		dbg("Command Write failed Value %x index %x", value, index);
 
 	return status;
 }
 
+
+/*
+ * mos77xx_probe
+ *	this function installs the appropriate read interrupt endpoint callback
+ *	depending on whether the device is a 7720 or 7715, thus avoiding costly
+ *	run-time checks in the high-frequency callback routine itself.
+ */
+static int mos77xx_probe(struct usb_serial *serial,
+			 const struct usb_device_id *id)
+{
+	if (id->idProduct == MOSCHIP_DEVICE_ID_7715)
+		moschip7720_2port_driver.read_int_callback =
+			mos7715_interrupt_callback;
+	else
+		moschip7720_2port_driver.read_int_callback =
+			mos7720_interrupt_callback;
+
+	return 0;
+}
+
+static int mos77xx_calc_num_ports(struct usb_serial *serial)
+{
+	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
+	if (product == MOSCHIP_DEVICE_ID_7715)
+		return 1;
+
+	return 2;
+}
+
 static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	struct usb_serial *serial;
@@ -390,7 +490,7 @@
 	  */
 	port_number = port->number - port->serial->minor;
 	send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data);
-	dbg("SS::%p LSR:%x\n", mos7720_port, data);
+	dbg("SS::%p LSR:%x", mos7720_port, data);
 
 	dbg("Check:Sending Command ..........");
 
@@ -729,7 +829,7 @@
 	struct moschip_port *mos7720_port;
 	int status;
 
-	dbg("%s- port %d\n", __func__, port->number);
+	dbg("%s- port %d", __func__, port->number);
 
 	mos7720_port = usb_get_serial_port_data(port);
 
@@ -1208,7 +1308,7 @@
 		return;
 	}
 
-	dbg("%s\n", "setting termios - ASPIRE");
+	dbg("setting termios - ASPIRE");
 
 	cflag = tty->termios->c_cflag;
 
@@ -1226,7 +1326,7 @@
 	change_port_settings(tty, mos7720_port, old_termios);
 
 	if (!port->read_urb) {
-		dbg("%s", "URB KILLED !!!!!\n");
+		dbg("URB KILLED !!!!!");
 		return;
 	}
 
@@ -1495,6 +1595,7 @@
 	struct usb_device *dev;
 	int i;
 	char data;
+	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
 
 	dbg("%s: Entering ..........", __func__);
 
@@ -1514,6 +1615,29 @@
 
 	usb_set_serial_data(serial, mos7720_serial);
 
+	/*
+	 * The 7715 uses the first bulk in/out endpoint pair for the parallel
+	 * port, and the second for the serial port.  Because the usbserial core
+	 * assumes both pairs are serial ports, we must engage in a bit of
+	 * subterfuge and swap the pointers for ports 0 and 1 in order to make
+	 * port 0 point to the serial port.  However, both moschip devices use a
+	 * single interrupt-in endpoint for both ports (as mentioned a little
+	 * further down), and this endpoint was assigned to port 0.  So after
+	 * the swap, we must copy the interrupt endpoint elements from port 1
+	 * (as newly assigned) to port 0, and null out port 1 pointers.
+	 */
+	if (product == MOSCHIP_DEVICE_ID_7715) {
+		struct usb_serial_port *tmp = serial->port[0];
+		serial->port[0] = serial->port[1];
+		serial->port[1] = tmp;
+		serial->port[0]->interrupt_in_urb = tmp->interrupt_in_urb;
+		serial->port[0]->interrupt_in_buffer = tmp->interrupt_in_buffer;
+		serial->port[0]->interrupt_in_endpointAddress =
+			tmp->interrupt_in_endpointAddress;
+		serial->port[1]->interrupt_in_urb = NULL;
+		serial->port[1]->interrupt_in_buffer = NULL;
+	}
+
 	/* we set up the pointers to the endpoints in the mos7720_open *
 	 * function, as the structures aren't created yet.             */
 
@@ -1529,7 +1653,7 @@
 
 		/* Initialize all port interrupt end point to port 0 int
 		 * endpoint.  Our device has only one interrupt endpoint
-		 * comman to all ports */
+		 * common to all ports */
 		serial->port[i]->interrupt_in_endpointAddress =
 				serial->port[0]->interrupt_in_endpointAddress;
 
@@ -1584,11 +1708,12 @@
 	.description		= "Moschip 2 port adapter",
 	.usb_driver		= &usb_driver,
 	.id_table		= moschip_port_id_table,
-	.num_ports		= 2,
+	.calc_num_ports		= mos77xx_calc_num_ports,
 	.open			= mos7720_open,
 	.close			= mos7720_close,
 	.throttle		= mos7720_throttle,
 	.unthrottle		= mos7720_unthrottle,
+	.probe			= mos77xx_probe,
 	.attach			= mos7720_startup,
 	.release		= mos7720_release,
 	.ioctl			= mos7720_ioctl,
@@ -1600,7 +1725,7 @@
 	.chars_in_buffer	= mos7720_chars_in_buffer,
 	.break_ctl		= mos7720_break,
 	.read_bulk_callback	= mos7720_bulk_in_callback,
-	.read_int_callback	= mos7720_interrupt_callback,
+	.read_int_callback	= NULL  /* dynamically assigned in probe() */
 };
 
 static int __init moschip7720_init(void)
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 2cfe245..2fda1c0 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -181,7 +181,7 @@
 #define URB_TRANSFER_BUFFER_SIZE        32	/* URB Size  */
 
 
-static struct usb_device_id moschip_port_id_table[] = {
+static const struct usb_device_id moschip_port_id_table[] = {
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
 	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
@@ -198,7 +198,7 @@
 	{}			/* terminating entry */
 };
 
-static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
+static const struct usb_device_id moschip_id_table_combined[] __devinitconst = {
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
 	{USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
 	{USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)},
@@ -283,12 +283,19 @@
 {
 	struct usb_device *dev = port->serial->dev;
 	int ret = 0;
+	u8 *buf;
+
+	buf = kmalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
-			      MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH,
+			      MCS_RD_RTYPE, 0, reg, buf, VENDOR_READ_LENGTH,
 			      MOS_WDR_TIMEOUT);
+	*val = buf[0];
 	dbg("mos7840_get_reg_sync offset is %x, return val %x", reg, *val);
-	*val = (*val) & 0x00ff;
+
+	kfree(buf);
 	return ret;
 }
 
@@ -341,6 +348,11 @@
 	struct usb_device *dev = port->serial->dev;
 	int ret = 0;
 	__u16 Wval;
+	u8 *buf;
+
+	buf = kmalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
 	/* dbg("application number is %4x",
 	    (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */
@@ -364,9 +376,11 @@
 		}
 	}
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
-			      MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH,
+			      MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH,
 			      MOS_WDR_TIMEOUT);
-	*val = (*val) & 0x00ff;
+	*val = buf[0];
+
+	kfree(buf);
 	return ret;
 }
 
@@ -750,7 +764,6 @@
 	if (urb->actual_length) {
 		tty = tty_port_tty_get(&mos7840_port->port->port);
 		if (tty) {
-			tty_buffer_request_room(tty, urb->actual_length);
 			tty_insert_flip_string(tty, data, urb->actual_length);
 			dbg(" %s ", data);
 			tty_flip_buffer_push(tty);
diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c
index 99bd00f5..cf17183 100644
--- a/drivers/usb/serial/moto_modem.c
+++ b/drivers/usb/serial/moto_modem.c
@@ -21,7 +21,7 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x05c6, 0x3197) },	/* unknown Motorola phone */
 	{ USB_DEVICE(0x0c44, 0x0022) },	/* unknown Mororola phone */
 	{ USB_DEVICE(0x22b8, 0x2a64) },	/* Motorola KRZR K1m */
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 5ceaa4c6..04a6cbb 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -22,7 +22,7 @@
 
 static int debug;
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x0a99, 0x0001) },	/* Talon Technology device */
 	{ },
 };
@@ -66,7 +66,6 @@
 
 	tty = tty_port_tty_get(&port->port);
 	if (tty && urb->actual_length) {
-		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 0622650..89c724c 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -75,7 +75,7 @@
 static void omninet_release(struct usb_serial *serial);
 static int omninet_attach(struct usb_serial *serial);
 
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
 	{ USB_DEVICE(ZYXEL_VENDOR_ID, BT_IGNITIONPRO_ID) },
 	{ }						/* Terminating entry */
@@ -218,8 +218,8 @@
 
 	if (debug && header->oh_xxx != 0x30) {
 		if (urb->actual_length) {
-			printk(KERN_DEBUG __FILE__
-					": omninet_read %d: ", header->oh_len);
+			printk(KERN_DEBUG "%s: omninet_read %d: ",
+			       __FILE__, header->oh_len);
 			for (i = 0; i < (header->oh_len +
 						OMNINET_HEADERLEN); i++)
 				printk("%.2x ", data[i]);
@@ -332,7 +332,7 @@
 	struct usb_serial_port 	*port   =  urb->context;
 	int status = urb->status;
 
-	dbg("%s - port %0x\n", __func__, port->number);
+	dbg("%s - port %0x", __func__, port->number);
 
 	port->write_urb_busy = 0;
 	if (status) {
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 4cdb975..701452a 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -22,7 +22,7 @@
 
 static int debug;
 
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x065a, 0x0009) },
 	{ },
 };
@@ -55,7 +55,6 @@
 	int status = urb->status;
 	struct tty_struct *tty;
 	int result;
-	int available_room = 0;
 	int data_length;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -96,13 +95,9 @@
 			/* real data, send it to the tty layer */
 			tty = tty_port_tty_get(&port->port);
 			if (tty) {
-				available_room = tty_buffer_request_room(tty,
-								data_length);
-				if (available_room) {
-					tty_insert_flip_string(tty, data,
-							       available_room);
-					tty_flip_buffer_push(tty);
-				}
+				tty_insert_flip_string(tty, data,
+							       data_length);
+				tty_flip_buffer_push(tty);
 				tty_kref_put(tty);
 			}
 		} else {
@@ -120,7 +115,7 @@
 		}
 	} else {
 		dev_dbg(&priv->udev->dev,
-			"Improper ammount of data received from the device, "
+			"Improper amount of data received from the device, "
 			"%d bytes", urb->actual_length);
 	}
 
@@ -217,7 +212,7 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
 		spin_unlock_irqrestore(&priv->lock, flags);
-		dbg("%s - write limit hit\n", __func__);
+		dbg("%s - write limit hit", __func__);
 		return 0;
 	}
 	priv->outstanding_urbs++;
@@ -288,7 +283,7 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) {
 		spin_unlock_irqrestore(&priv->lock, flags);
-		dbg("%s - write limit hit\n", __func__);
+		dbg("%s - write limit hit", __func__);
 		return 0;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 6e94a67..847b805 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -336,15 +336,42 @@
 #define AIRPLUS_VENDOR_ID			0x1011
 #define AIRPLUS_PRODUCT_MCD650			0x3198
 
+/* Longcheer/Longsung vendor ID; makes whitelabel devices that
+ * many other vendors like 4G Systems, Alcatel, ChinaBird,
+ * Mobidata, etc sell under their own brand names.
+ */
+#define LONGCHEER_VENDOR_ID			0x1c9e
+
 /* 4G Systems products */
-#define FOUR_G_SYSTEMS_VENDOR_ID		0x1c9e
+/* This is the 4G XS Stick W14 a.k.a. Mobilcom Debitel Surf-Stick *
+ * It seems to contain a Qualcomm QSC6240/6290 chipset            */
 #define FOUR_G_SYSTEMS_PRODUCT_W14		0x9603
 
 /* Haier products */
 #define HAIER_VENDOR_ID				0x201e
 #define HAIER_PRODUCT_CE100			0x2009
 
-static struct usb_device_id option_ids[] = {
+/* some devices interfaces need special handling due to a number of reasons */
+enum option_blacklist_reason {
+		OPTION_BLACKLIST_NONE = 0,
+		OPTION_BLACKLIST_SENDSETUP = 1,
+		OPTION_BLACKLIST_RESERVED_IF = 2
+};
+
+struct option_blacklist_info {
+	const u32 infolen;	/* number of interface numbers on blacklist */
+	const u8  *ifaceinfo;	/* pointer to the array holding the numbers */
+	enum option_blacklist_reason reason;
+};
+
+static const u8 four_g_w14_no_sendsetup[] = { 0, 1 };
+static const struct option_blacklist_info four_g_w14_blacklist = {
+	.infolen = ARRAY_SIZE(four_g_w14_no_sendsetup),
+	.ifaceinfo = four_g_w14_no_sendsetup,
+	.reason = OPTION_BLACKLIST_SENDSETUP
+};
+
+static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
@@ -644,7 +671,9 @@
 	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
 	{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
 	{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
-	{ USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14) },
+	{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
+  	  .driver_info = (kernel_ulong_t)&four_g_w14_blacklist
+  	},
 	{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
 	{ } /* Terminating entry */
 };
@@ -709,6 +738,7 @@
 	spinlock_t susp_lock;
 	unsigned int suspended:1;
 	int in_flight;
+	struct option_blacklist_info *blacklist_info;
 };
 
 struct option_port_private {
@@ -778,9 +808,27 @@
 	if (!data)
 		return -ENOMEM;
 	spin_lock_init(&data->susp_lock);
+	data->blacklist_info = (struct option_blacklist_info*) id->driver_info;
 	return 0;
 }
 
+static enum option_blacklist_reason is_blacklisted(const u8 ifnum,
+				const struct option_blacklist_info *blacklist)
+{
+	const u8  *info;
+	int i;
+
+	if (blacklist) {
+		info = blacklist->ifaceinfo;
+
+		for (i = 0; i < blacklist->infolen; i++) {
+			if (info[i] == ifnum)
+				return blacklist->reason;
+		}
+	}
+	return OPTION_BLACKLIST_NONE;
+}
+
 static void option_set_termios(struct tty_struct *tty,
 		struct usb_serial_port *port, struct ktermios *old_termios)
 {
@@ -921,7 +969,6 @@
 	} else {
 		tty = tty_port_tty_get(&port->port);
 		if (urb->actual_length) {
-			tty_buffer_request_room(tty, urb->actual_length);
 			tty_insert_flip_string(tty, data, urb->actual_length);
 			tty_flip_buffer_push(tty);
 		} else 
@@ -929,9 +976,9 @@
 		tty_kref_put(tty);
 
 		/* Resubmit urb so we continue receiving */
-		if (port->port.count && status != -ESHUTDOWN) {
+		if (status != -ESHUTDOWN) {
 			err = usb_submit_urb(urb, GFP_ATOMIC);
-			if (err)
+			if (err && err != -EPERM)
 				printk(KERN_ERR "%s: resubmit read urb failed. "
 					"(%d)", __func__, err);
 			else
@@ -985,7 +1032,7 @@
 				(struct usb_ctrlrequest *)urb->transfer_buffer;
 
 		if (!req_pkt) {
-			dbg("%s: NULL req_pkt\n", __func__);
+			dbg("%s: NULL req_pkt", __func__);
 			return;
 		}
 		if ((req_pkt->bRequestType == 0xA1) &&
@@ -1211,11 +1258,19 @@
 static int option_send_setup(struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
+	struct option_intf_private *intfdata =
+		(struct option_intf_private *) serial->private;
 	struct option_port_private *portdata;
 	int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
 	int val = 0;
 	dbg("%s", __func__);
 
+	if (is_blacklisted(ifNum, intfdata->blacklist_info) ==
+						OPTION_BLACKLIST_SENDSETUP) {
+		dbg("No send_setup on blacklisted interface #%d\n", ifNum);
+		return -EIO;
+	}
+
 	portdata = usb_get_serial_port_data(port);
 
 	if (portdata->dtr_state)
@@ -1401,7 +1456,7 @@
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
 		if (!port->interrupt_in_urb) {
-			dbg("%s: No interrupt URB for port %d\n", __func__, i);
+			dbg("%s: No interrupt URB for port %d", __func__, i);
 			continue;
 		}
 		err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index c644e26..deeacde 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -58,7 +58,7 @@
 #define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>"
 #define OTI6858_VERSION "0.1"
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) },
 	{ }
 };
@@ -302,7 +302,7 @@
 	struct usb_serial_port *port = priv->port;
 	int count = 0, result;
 	unsigned long flags;
-	unsigned char allow;
+	u8 *allow;
 
 	dbg("%s(port = %d)", __func__, port->number);
 
@@ -321,13 +321,20 @@
 		count = port->bulk_out_size;
 
 	if (count != 0) {
+		allow = kmalloc(1, GFP_KERNEL);
+		if (!allow) {
+			dev_err(&port->dev, "%s(): kmalloc failed\n",
+					__func__);
+			return;
+		}
 		result = usb_control_msg(port->serial->dev,
 				usb_rcvctrlpipe(port->serial->dev, 0),
 				OTI6858_REQ_T_CHECK_TXBUFF,
 				OTI6858_REQ_CHECK_TXBUFF,
-				count, 0, &allow, 1, 100);
-		if (result != 1 || allow != 0)
+				count, 0, allow, 1, 100);
+		if (result != 1 || *allow != 0)
 			count = 0;
+		kfree(allow);
 	}
 
 	if (count == 0) {
@@ -578,9 +585,6 @@
 	usb_clear_halt(serial->dev, port->write_urb->pipe);
 	usb_clear_halt(serial->dev, port->read_urb->pipe);
 
-	if (port->port.count != 1)
-		return 0;
-
 	buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
 	if (buf == NULL) {
 		dev_err(&port->dev, "%s(): out of memory!\n", __func__);
@@ -927,10 +931,6 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	if (status != 0) {
-		if (!port->port.count) {
-			dbg("%s(): port is closed, exiting", __func__);
-			return;
-		}
 		/*
 		if (status == -EPROTO) {
 			* PL2303 mysteriously fails with -EPROTO reschedule
@@ -954,14 +954,12 @@
 	}
 	tty_kref_put(tty);
 
-	/* schedule the interrupt urb if we are still open */
-	if (port->port.count != 0) {
-		port->interrupt_in_urb->dev = port->serial->dev;
-		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-		if (result != 0) {
-			dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
-					" error %d\n", __func__, result);
-		}
+	/* schedule the interrupt urb */
+	port->interrupt_in_urb->dev = port->serial->dev;
+	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+	if (result != 0 && result != -EPERM) {
+		dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+				" error %d\n", __func__, result);
 	}
 }
 
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 9ec1a49..73d5f34 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -50,7 +50,7 @@
 	char		*buf_put;
 };
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
 	{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_DCU11) },
@@ -451,7 +451,6 @@
 			      port->write_urb->transfer_buffer);
 
 	port->write_urb->transfer_buffer_length = count;
-	port->write_urb->dev = port->serial->dev;
 	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 	if (result) {
 		dev_err(&port->dev, "%s - failed submitting write urb,"
@@ -769,7 +768,6 @@
 		pl2303_set_termios(tty, port, &tmp_termios);
 
 	dbg("%s - submitting read urb", __func__);
-	port->read_urb->dev = serial->dev;
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result) {
 		dev_err(&port->dev, "%s - failed submitting read urb,"
@@ -779,7 +777,6 @@
 	}
 
 	dbg("%s - submitting interrupt urb", __func__);
-	port->interrupt_in_urb->dev = serial->dev;
 	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 	if (result) {
 		dev_err(&port->dev, "%s - failed submitting interrupt urb,"
@@ -895,10 +892,23 @@
 static int pl2303_ioctl(struct tty_struct *tty, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
+	struct serial_struct ser;
 	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
 
 	switch (cmd) {
+	case TIOCGSERIAL:
+		memset(&ser, 0, sizeof ser);
+		ser.type = PORT_16654;
+		ser.line = port->serial->minor;
+		ser.port = port->number;
+		ser.baud_base = 460800;
+
+		if (copy_to_user((void __user *)arg, &ser, sizeof ser))
+			return -EFAULT;
+
+		return 0;
+
 	case TIOCMIWAIT:
 		dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
 		return wait_modem_info(port, arg);
@@ -1042,7 +1052,6 @@
 		tty_flag = TTY_FRAME;
 	dbg("%s - tty_flag = %d", __func__, tty_flag);
 
-	tty_buffer_request_room(tty, urb->actual_length + 1);
 	/* overrun is special, not associated with a char */
 	if (line_status & UART_OVERRUN_ERROR)
 		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
@@ -1072,16 +1081,11 @@
 
 	if (status) {
 		dbg("%s - urb status = %d", __func__, status);
-		if (!port->port.count) {
-			dbg("%s - port is closed, exiting.", __func__);
-			return;
-		}
 		if (status == -EPROTO) {
 			/* PL2303 mysteriously fails with -EPROTO reschedule
 			 * the read */
 			dbg("%s - caught -EPROTO, resubmitting the urb",
 			    __func__);
-			urb->dev = port->serial->dev;
 			result = usb_submit_urb(urb, GFP_ATOMIC);
 			if (result)
 				dev_err(&urb->dev->dev, "%s - failed"
@@ -1108,15 +1112,10 @@
 	}
 	tty_kref_put(tty);
 	/* Schedule the next read _if_ we are still open */
-	if (port->port.count) {
-		urb->dev = port->serial->dev;
-		result = usb_submit_urb(urb, GFP_ATOMIC);
-		if (result)
-			dev_err(&urb->dev->dev, "%s - failed resubmitting"
-				" read urb, error %d\n", __func__, result);
-	}
-
-	return;
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result && result != -EPERM)
+		dev_err(&urb->dev->dev, "%s - failed resubmitting"
+			" read urb, error %d\n", __func__, result);
 }
 
 static void pl2303_write_bulk_callback(struct urb *urb)
@@ -1146,7 +1145,6 @@
 		dbg("%s - nonzero write bulk status received: %d", __func__,
 		    status);
 		port->write_urb->transfer_buffer_length = 1;
-		port->write_urb->dev = port->serial->dev;
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 		if (result)
 			dev_err(&urb->dev->dev, "%s - failed resubmitting write"
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
new file mode 100644
index 0000000..0b93620
--- /dev/null
+++ b/drivers/usb/serial/qcaux.c
@@ -0,0 +1,96 @@
+/*
+ * Qualcomm USB Auxiliary Serial Port driver
+ *
+ * Copyright (C) 2008 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (C) 2010 Dan Williams <dcbw@redhat.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.
+ *
+ * Devices listed here usually provide a CDC ACM port on which normal modem
+ * AT commands and PPP can be used.  But when that port is in-use by PPP it
+ * cannot be used simultaneously for status or signal strength.  Instead, the
+ * ports here can be queried for that information using the Qualcomm DM
+ * protocol.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+/* NOTE: for now, only use this driver for devices that provide a CDC-ACM port
+ * for normal AT commands, but also provide secondary USB interfaces for the
+ * QCDM-capable ports.  Devices that do not provide a CDC-ACM port should
+ * probably be driven by option.ko.
+ */
+
+/* UTStarcom/Pantech/Curitel devices */
+#define UTSTARCOM_VENDOR_ID			0x106c
+#define UTSTARCOM_PRODUCT_PC5740		0x3701
+#define UTSTARCOM_PRODUCT_PC5750		0x3702 /* aka Pantech PX-500 */
+#define UTSTARCOM_PRODUCT_UM150			0x3711
+#define UTSTARCOM_PRODUCT_UM175_V1		0x3712
+#define UTSTARCOM_PRODUCT_UM175_V2		0x3714
+#define UTSTARCOM_PRODUCT_UM175_ALLTEL		0x3715
+
+/* CMOTECH devices */
+#define CMOTECH_VENDOR_ID			0x16d8
+#define CMOTECH_PRODUCT_CDU550			0x5553
+#define CMOTECH_PRODUCT_CDX650			0x6512
+
+static struct usb_device_id id_table[] = {
+	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_PC5740, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_PC5750, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_UM150, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_UM175_V1, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_UM175_V2, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, UTSTARCOM_PRODUCT_UM175_ALLTEL, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU550, 0xff, 0xff, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDX650, 0xff, 0xff, 0x00) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver qcaux_driver = {
+	.name =		"qcaux",
+	.probe =	usb_serial_probe,
+	.disconnect =	usb_serial_disconnect,
+	.id_table =	id_table,
+	.no_dynamic_id = 	1,
+};
+
+static struct usb_serial_driver qcaux_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"qcaux",
+	},
+	.id_table =		id_table,
+	.num_ports =		1,
+};
+
+static int __init qcaux_init(void)
+{
+	int retval;
+
+	retval = usb_serial_register(&qcaux_device);
+	if (retval)
+		return retval;
+	retval = usb_register(&qcaux_driver);
+	if (retval)
+		usb_serial_deregister(&qcaux_device);
+	return retval;
+}
+
+static void __exit qcaux_exit(void)
+{
+	usb_deregister(&qcaux_driver);
+	usb_serial_deregister(&qcaux_device);
+}
+
+module_init(qcaux_init);
+module_exit(qcaux_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 7528b8d..310ff6e 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -21,7 +21,7 @@
 
 static int debug;
 
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
 	{USB_DEVICE(0x05c6, 0x9211)},	/* Acer Gobi QDL device */
 	{USB_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
 	{USB_DEVICE(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */
diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c
index 951ea0c..cb8195c 100644
--- a/drivers/usb/serial/siemens_mpi.c
+++ b/drivers/usb/serial/siemens_mpi.c
@@ -22,7 +22,7 @@
 #define DRIVER_DESC "Driver for Siemens USB/MPI adapter"
 
 
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
 	/* Vendor and product id for 6ES7-972-0CB20-0XA0 */
 	{ USB_DEVICE(0x908, 0x0004) },
 	{ },
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 3eb6143..34e6f894 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -226,7 +226,7 @@
 	.ifaceinfo = direct_ip_non_serial_ifaces,
 };
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
 	{ USB_DEVICE(0x03F0, 0x1B1D) },	/* HP ev2200 a.k.a MC5720 */
 	{ USB_DEVICE(0x03F0, 0x1E1D) },	/* HP hs2300 a.k.a MC8775 */
@@ -304,16 +304,6 @@
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
-static struct usb_driver sierra_driver = {
-	.name       = "sierra",
-	.probe      = usb_serial_probe,
-	.disconnect = usb_serial_disconnect,
-	.suspend    = usb_serial_suspend,
-	.resume     = usb_serial_resume,
-	.id_table   = id_table,
-	.no_dynamic_id = 	1,
-	.supports_autosuspend =	1,
-};
 
 struct sierra_port_private {
 	spinlock_t lock;	/* lock the structure */
@@ -477,7 +467,7 @@
 static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
 					const unsigned char *buf, int count)
 {
-	struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+	struct sierra_port_private *portdata;
 	struct sierra_intf_private *intfdata;
 	struct usb_serial *serial = port->serial;
 	unsigned long flags;
@@ -604,14 +594,15 @@
 	} else {
 		if (urb->actual_length) {
 			tty = tty_port_tty_get(&port->port);
+			if (tty) {
+				tty_insert_flip_string(tty, data,
+					urb->actual_length);
+				tty_flip_buffer_push(tty);
 
-			tty_buffer_request_room(tty, urb->actual_length);
-			tty_insert_flip_string(tty, data, urb->actual_length);
-			tty_flip_buffer_push(tty);
-
-			tty_kref_put(tty);
-			usb_serial_debug_data(debug, &port->dev, __func__,
-				urb->actual_length, data);
+				tty_kref_put(tty);
+				usb_serial_debug_data(debug, &port->dev,
+					__func__, urb->actual_length, data);
+			}
 		} else {
 			dev_dbg(&port->dev, "%s: empty read urb"
 				" received\n", __func__);
@@ -619,10 +610,10 @@
 	}
 
 	/* Resubmit urb so we continue receiving */
-	if (port->port.count && status != -ESHUTDOWN && status != -EPERM) {
+	if (status != -ESHUTDOWN && status != -EPERM) {
 		usb_mark_last_busy(port->serial->dev);
 		err = usb_submit_urb(urb, GFP_ATOMIC);
-		if (err)
+		if (err && err != -EPERM)
 			dev_err(&port->dev, "resubmit read urb failed."
 				"(%d)\n", err);
 	}
@@ -681,11 +672,11 @@
 		dev_dbg(&port->dev, "%s: error %d\n", __func__, status);
 
 	/* Resubmit urb so we continue receiving IRQ data */
-	if (port->port.count && status != -ESHUTDOWN && status != -ENOENT) {
+	if (status != -ESHUTDOWN && status != -ENOENT) {
 		usb_mark_last_busy(serial->dev);
 		urb->dev = serial->dev;
 		err = usb_submit_urb(urb, GFP_ATOMIC);
-		if (err)
+		if (err && err != -EPERM)
 			dev_err(&port->dev, "%s: resubmit intr urb "
 				"failed. (%d)\n", __func__, err);
 	}
@@ -1061,11 +1052,31 @@
 
 	return ec ? -EIO : 0;
 }
+
+static int sierra_reset_resume(struct usb_interface *intf)
+{
+	struct usb_serial *serial = usb_get_intfdata(intf);
+	dev_err(&serial->dev->dev, "%s\n", __func__);
+	return usb_serial_resume(intf);
+}
 #else
 #define sierra_suspend NULL
 #define sierra_resume NULL
+#define sierra_reset_resume NULL
 #endif
 
+static struct usb_driver sierra_driver = {
+	.name       = "sierra",
+	.probe      = usb_serial_probe,
+	.disconnect = usb_serial_disconnect,
+	.suspend    = usb_serial_suspend,
+	.resume     = usb_serial_resume,
+	.reset_resume = sierra_reset_resume,
+	.id_table   = id_table,
+	.no_dynamic_id = 	1,
+	.supports_autosuspend =	1,
+};
+
 static struct usb_serial_driver sierra_device = {
 	.driver = {
 		.owner =	THIS_MODULE,
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 1e58220..5d39191 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -45,7 +45,7 @@
 #define SPCP8x5_835_VID		0x04fc
 #define SPCP8x5_835_PID		0x0231
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(SPCP8x5_PHILIPS_VID , SPCP8x5_PHILIPS_PID)},
 	{ USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
 	{ USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
@@ -609,7 +609,7 @@
 	if (i < 0)
 		dev_err(&port->dev, "Set UART format %#x failed (error = %d)\n",
 			uartdata, i);
-	dbg("0x21:0x40:0:0  %d\n", i);
+	dbg("0x21:0x40:0:0  %d", i);
 
 	if (cflag & CRTSCTS) {
 		/* enable hardware flow control */
@@ -677,7 +677,6 @@
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
 	unsigned long flags;
-	int i;
 	int result = urb->status;
 	u8 status;
 	char tty_flag;
@@ -687,8 +686,6 @@
 
 	/* check the urb status */
 	if (result) {
-		if (!port->port.count)
-			return;
 		if (result == -EPROTO) {
 			/* spcp8x5 mysteriously fails with -EPROTO */
 			/* reschedule the read */
@@ -726,26 +723,20 @@
 
 	tty = tty_port_tty_get(&port->port);
 	if (tty && urb->actual_length) {
-		tty_buffer_request_room(tty, urb->actual_length + 1);
 		/* overrun is special, not associated with a char */
 		if (status & UART_OVERRUN_ERROR)
 			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-		for (i = 0; i < urb->actual_length; ++i)
-			tty_insert_flip_char(tty, data[i], tty_flag);
+		tty_insert_flip_string_fixed_flag(tty, data,
+						urb->actual_length, tty_flag);
 		tty_flip_buffer_push(tty);
 	}
 	tty_kref_put(tty);
 
-	/* Schedule the next read _if_ we are still open */
-	if (port->port.count) {
-		urb->dev = port->serial->dev;
-		result = usb_submit_urb(urb , GFP_ATOMIC);
-		if (result)
-			dev_dbg(&port->dev, "failed submitting read urb %d\n",
-				result);
-	}
-
-	return;
+	/* Schedule the next read */
+	urb->dev = port->serial->dev;
+	result = usb_submit_urb(urb , GFP_ATOMIC);
+	if (result)
+		dev_dbg(&port->dev, "failed submitting read urb %d\n", result);
 }
 
 /* get data from ring buffer and then write to usb bus */
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index b282c0f..ee190cc 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -21,7 +21,7 @@
 
 static int debug;
 
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x05e0, 0x0600) },
 	{ },
 };
@@ -51,7 +51,6 @@
 	int status = urb->status;
 	struct tty_struct *tty;
 	int result;
-	int available_room = 0;
 	int data_length;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -89,18 +88,13 @@
 		 */
 		tty = tty_port_tty_get(&port->port);
 		if (tty) {
-			available_room = tty_buffer_request_room(tty,
-							data_length);
-			if (available_room) {
-				tty_insert_flip_string(tty, &data[1],
-						       available_room);
-				tty_flip_buffer_push(tty);
-			}
+			tty_insert_flip_string(tty, &data[1], data_length);
+			tty_flip_buffer_push(tty);
 			tty_kref_put(tty);
 		}
 	} else {
 		dev_dbg(&priv->udev->dev,
-			"Improper ammount of data received from the device, "
+			"Improper amount of data received from the device, "
 			"%d bytes", urb->actual_length);
 	}
 
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 1e9dc88..0afe5c7 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1271,14 +1271,13 @@
 	int cnt;
 
 	do {
-		cnt = tty_buffer_request_room(tty, length);
+		cnt = tty_insert_flip_string(tty, data, length);
 		if (cnt < length) {
 			dev_err(dev, "%s - dropping data, %d bytes lost\n",
 						__func__, length - cnt);
 			if (cnt == 0)
 				break;
 		}
-		tty_insert_flip_string(tty, data, cnt);
 		tty_flip_buffer_push(tty);
 		data += cnt;
 		length -= cnt;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 33c85f7..3873660 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -358,10 +358,6 @@
 
 	dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
 
-	/* count is managed under the mutex lock for the tty so cannot
-	   drop to zero until after the last close completes */
-	WARN_ON(!port->port.count);
-
 	/* pass on to the driver specific version of this function */
 	retval = port->serial->type->write(tty, port, buf, count);
 
@@ -373,7 +369,6 @@
 {
 	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s - port %d", __func__, port->number);
-	WARN_ON(!port->port.count);
 	/* pass on to the driver specific version of this function */
 	return port->serial->type->write_room(tty);
 }
@@ -381,7 +376,7 @@
 static int serial_chars_in_buffer(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	dbg("%s = port %d", __func__, port->number);
+	dbg("%s - port %d", __func__, port->number);
 
 	/* if the device was unplugged then any remaining characters
 	   fell out of the connector ;) */
@@ -396,7 +391,6 @@
 	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->port.count);
 	/* pass on to the driver specific version of this function */
 	if (port->serial->type->throttle)
 		port->serial->type->throttle(tty);
@@ -407,7 +401,6 @@
 	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->port.count);
 	/* pass on to the driver specific version of this function */
 	if (port->serial->type->unthrottle)
 		port->serial->type->unthrottle(tty);
@@ -421,8 +414,6 @@
 
 	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
 
-	WARN_ON(!port->port.count);
-
 	/* pass on to the driver specific version of this function
 	   if it is available */
 	if (port->serial->type->ioctl) {
@@ -437,7 +428,6 @@
 	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->port.count);
 	/* pass on to the driver specific version of this function
 	   if it is available */
 	if (port->serial->type->set_termios)
@@ -452,7 +442,6 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->port.count);
 	/* pass on to the driver specific version of this function
 	   if it is available */
 	if (port->serial->type->break_ctl)
@@ -513,7 +502,6 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->port.count);
 	if (port->serial->type->tiocmget)
 		return port->serial->type->tiocmget(tty, file);
 	return -EINVAL;
@@ -526,7 +514,6 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->port.count);
 	if (port->serial->type->tiocmset)
 		return port->serial->type->tiocmset(tty, file, set, clear);
 	return -EINVAL;
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index 7b5bfc4..252cc2d 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -29,7 +29,7 @@
 	0xff,
 };
 
-static struct usb_device_id id_table [] = {
+static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x0525, 0x127a) },
 	{ },
 };
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index ad1f923..0949427 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -368,7 +368,7 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
 		spin_unlock_irqrestore(&priv->lock, flags);
-		dbg("%s - write limit hit\n", __func__);
+		dbg("%s - write limit hit", __func__);
 		return 0;
 	}
 	priv->outstanding_urbs++;
@@ -446,7 +446,7 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) {
 		spin_unlock_irqrestore(&priv->lock, flags);
-		dbg("%s - write limit hit\n", __func__);
+		dbg("%s - write limit hit", __func__);
 		return 0;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -503,13 +503,9 @@
 	if (urb->actual_length) {
 		tty = tty_port_tty_get(&port->port);
 		if (tty) {
-			available_room = tty_buffer_request_room(tty,
-							urb->actual_length);
-			if (available_room) {
-				tty_insert_flip_string(tty, data,
-							available_room);
-				tty_flip_buffer_push(tty);
-			}
+			tty_insert_flip_string(tty, data,
+						urb->actual_length);
+			tty_flip_buffer_push(tty);
 			tty_kref_put(tty);
 		}
 		spin_lock(&priv->lock);
@@ -807,10 +803,14 @@
 {
 	struct device *dev = &serial->dev->dev;
 	int result;
-	u8 data;
+	u8 *data;
 
 	dbg("%s", __func__);
 
+	data = kmalloc(1, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
 	/*
 	 * Note that PEG-300 series devices expect the following two calls.
 	 */
@@ -818,36 +818,42 @@
 	/* get the config number */
 	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				  USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
-				  0, 0, &data, 1, 3000);
+				  0, 0, data, 1, 3000);
 	if (result < 0) {
 		dev_err(dev, "%s: get config number failed: %d\n",
 							__func__, result);
-		return result;
+		goto out;
 	}
 	if (result != 1) {
 		dev_err(dev, "%s: get config number bad return length: %d\n",
 							__func__, result);
-		return -EIO;
+		result = -EIO;
+		goto out;
 	}
 
 	/* get the interface number */
 	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				  USB_REQ_GET_INTERFACE,
 				  USB_DIR_IN | USB_RECIP_INTERFACE,
-				  0, 0, &data, 1, 3000);
+				  0, 0, data, 1, 3000);
 	if (result < 0) {
 		dev_err(dev, "%s: get interface number failed: %d\n",
 							__func__, result);
-		return result;
+		goto out;
 	}
 	if (result != 1) {
 		dev_err(dev,
 			"%s: get interface number bad return length: %d\n",
 							__func__, result);
-		return -EIO;
+		result = -EIO;
+		goto out;
 	}
 
-	return generic_startup(serial);
+	result = generic_startup(serial);
+out:
+	kfree(data);
+
+	return result;
 }
 
 static int treo_attach(struct usb_serial *serial)
diff --git a/drivers/usb/serial/vivopay-serial.c b/drivers/usb/serial/vivopay-serial.c
new file mode 100644
index 0000000..f719d00
--- /dev/null
+++ b/drivers/usb/serial/vivopay-serial.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2001-2005 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2009 Outpost Embedded, LLC
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+
+#define DRIVER_VERSION "v1.0"
+#define DRIVER_DESC "ViVOpay USB Serial Driver"
+
+#define VIVOPAY_VENDOR_ID 0x1d5f
+
+
+static struct usb_device_id id_table [] = {
+	/* ViVOpay 8800 */
+	{ USB_DEVICE(VIVOPAY_VENDOR_ID, 0x1004) },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver vivopay_serial_driver = {
+	.name =			"vivopay-serial",
+	.probe =		usb_serial_probe,
+	.disconnect =		usb_serial_disconnect,
+	.id_table =		id_table,
+	.no_dynamic_id =	1,
+};
+
+static struct usb_serial_driver vivopay_serial_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"vivopay-serial",
+	},
+	.id_table =		id_table,
+	.usb_driver =		&vivopay_serial_driver,
+	.num_ports =		1,
+};
+
+static int __init vivopay_serial_init(void)
+{
+	int retval;
+	retval = usb_serial_register(&vivopay_serial_device);
+	if (retval)
+		goto failed_usb_serial_register;
+	retval = usb_register(&vivopay_serial_driver);
+	if (retval)
+		goto failed_usb_register;
+	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+	    DRIVER_DESC "\n");
+	return 0;
+failed_usb_register:
+	usb_serial_deregister(&vivopay_serial_device);
+failed_usb_serial_register:
+	return retval;
+}
+
+static void __exit vivopay_serial_exit(void)
+{
+	usb_deregister(&vivopay_serial_driver);
+	usb_serial_deregister(&vivopay_serial_device);
+}
+
+module_init(vivopay_serial_init);
+module_exit(vivopay_serial_exit);
+
+MODULE_AUTHOR("Forest Bond <forest.bond@outpostembedded.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 1093d2e..12ed820 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -111,17 +111,17 @@
    separate ID tables, and then a third table that combines them
    just for the purpose of exporting the autoloading information.
 */
-static struct usb_device_id id_table_std [] = {
+static const struct usb_device_id id_table_std[] = {
 	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_WHITE_HEAT_ID) },
 	{ }						/* Terminating entry */
 };
 
-static struct usb_device_id id_table_prerenumeration [] = {
+static const struct usb_device_id id_table_prerenumeration[] = {
 	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_FAKE_WHITE_HEAT_ID) },
 	{ }						/* Terminating entry */
 };
 
-static struct usb_device_id id_table_combined [] = {
+static const struct usb_device_id id_table_combined[] = {
 	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_WHITE_HEAT_ID) },
 	{ USB_DEVICE(CONNECT_TECH_VENDOR_ID, CONNECT_TECH_FAKE_WHITE_HEAT_ID) },
 	{ }						/* Terminating entry */
@@ -1492,21 +1492,9 @@
 		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
 		urb = wrap->urb;
 
-		if (tty && urb->actual_length) {
-			int len = tty_buffer_request_room(tty,
-							urb->actual_length);
-			/* This stuff can go away now I suspect */
-			if (unlikely(len < urb->actual_length)) {
-				spin_lock_irqsave(&info->lock, flags);
-				list_add(tmp, &info->rx_urb_q);
-				spin_unlock_irqrestore(&info->lock, flags);
-				tty_flip_buffer_push(tty);
-				schedule_work(&info->rx_work);
-				goto out;
-			}
-			tty_insert_flip_string(tty, urb->transfer_buffer, len);
-			sent += len;
-		}
+		if (tty && urb->actual_length)
+			sent += tty_insert_flip_string(tty,
+				urb->transfer_buffer, urb->actual_length);
 
 		urb->dev = port->serial->dev;
 		result = usb_submit_urb(urb, GFP_ATOMIC);
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 80e65f2..198bb3e 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -202,7 +202,7 @@
 		goto fail1;
 
 	onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN,
-					  GFP_ATOMIC, &onetouch->data_dma);
+					  GFP_KERNEL, &onetouch->data_dma);
 	if (!onetouch->data)
 		goto fail1;
 
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index aadc16b..4cc0355 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -133,7 +133,7 @@
 
 		if (us->fflags & US_FL_MAX_SECTORS_MIN)
 			max_sectors = PAGE_CACHE_SIZE >> 9;
-		if (queue_max_sectors(sdev->request_queue) > max_sectors)
+		if (queue_max_hw_sectors(sdev->request_queue) > max_sectors)
 			blk_queue_max_hw_sectors(sdev->request_queue,
 					      max_sectors);
 	} else if (sdev->type == TYPE_TAPE) {
@@ -484,7 +484,7 @@
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 
-	return sprintf(buf, "%u\n", queue_max_sectors(sdev->request_queue));
+	return sprintf(buf, "%u\n", queue_max_hw_sectors(sdev->request_queue));
 }
 
 /* Input routine for the sysfs max_sectors file */
@@ -494,9 +494,9 @@
 	struct scsi_device *sdev = to_scsi_device(dev);
 	unsigned short ms;
 
-	if (sscanf(buf, "%hu", &ms) > 0 && ms <= SCSI_DEFAULT_MAX_SECTORS) {
+	if (sscanf(buf, "%hu", &ms) > 0) {
 		blk_queue_max_hw_sectors(sdev->request_queue, ms);
-		return strlen(buf);
+		return count;
 	}
 	return -EINVAL;	
 }
@@ -539,7 +539,7 @@
 	.slave_configure =		slave_configure,
 
 	/* lots of sg segments can be handled */
-	.sg_tablesize =			SG_ALL,
+	.sg_tablesize =			SCSI_MAX_SG_CHAIN_SEGMENTS,
 
 	/* limit the total size of a transfer to 120 KB */
 	.max_sectors =                  240,
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index b62a288..bd3f415 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1628,10 +1628,10 @@
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
-	if ( (result = usbat_multiple_write(us, 
-			registers, data, 7)) != USB_STOR_TRANSPORT_GOOD) {
+	result = usbat_multiple_write(us, registers, data, 7);
+
+	if (result != USB_STOR_TRANSPORT_GOOD)
 		return result;
-	}
 
 	/*
 	 * Write the 12-byte command header.
@@ -1643,12 +1643,11 @@
 	 * AT SPEED 4 IS UNRELIABLE!!!
 	 */
 
-	if ((result = usbat_write_block(us,
-			USBAT_ATA, srb->cmnd, 12,
-				(srb->cmnd[0]==GPCMD_BLANK ? 75 : 10), 0) !=
-			     USB_STOR_TRANSPORT_GOOD)) {
+	result = usbat_write_block(us, USBAT_ATA, srb->cmnd, 12,
+				   srb->cmnd[0] == GPCMD_BLANK ? 75 : 10, 0);
+
+	if (result != USB_STOR_TRANSPORT_GOOD)
 		return result;
-	}
 
 	/* If there is response data to be read in then do it here. */
 
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index cc313d1..4680381 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -47,6 +47,8 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
+#include <linux/usb/quirks.h>
+
 #include <scsi/scsi.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_device.h>
@@ -1297,6 +1299,10 @@
 {
 	int result;
 
+	/*for these devices we must use the class specific method */
+	if (us->pusb_dev->quirks & USB_QUIRK_RESET_MORPHS)
+		return -EPERM;
+
 	result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
 	if (result < 0)
 		US_DEBUGP("unable to lock device for reset: %d\n", result);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 49575fba..98b549b 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1147,8 +1147,8 @@
 		0 ),
 
 /* Reported by Jan Dumon <j.dumon@option.com>
- * This device (wrongly) has a vendor-specific device descriptor.
- * The entry is needed so usb-storage can bind to it's mass-storage
+ * These devices (wrongly) have a vendor-specific device descriptor.
+ * These entries are needed so usb-storage can bind to their mass-storage
  * interface as an interface driver */
 UNUSUAL_DEV( 0x0af0, 0x7501, 0x0000, 0x0000,
 		"Option",
@@ -1156,6 +1156,90 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		0 ),
 
+UNUSUAL_DEV( 0x0af0, 0x7701, 0x0000, 0x0000,
+		"Option",
+		"GI 0451 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x7706, 0x0000, 0x0000,
+		"Option",
+		"GI 0451 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x7901, 0x0000, 0x0000,
+		"Option",
+		"GI 0452 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x7A01, 0x0000, 0x0000,
+		"Option",
+		"GI 0461 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x7A05, 0x0000, 0x0000,
+		"Option",
+		"GI 0461 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x8300, 0x0000, 0x0000,
+		"Option",
+		"GI 033x SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x8302, 0x0000, 0x0000,
+		"Option",
+		"GI 033x SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0x8304, 0x0000, 0x0000,
+		"Option",
+		"GI 033x SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xc100, 0x0000, 0x0000,
+		"Option",
+		"GI 070x SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xd057, 0x0000, 0x0000,
+		"Option",
+		"GI 1505 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xd058, 0x0000, 0x0000,
+		"Option",
+		"GI 1509 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xd157, 0x0000, 0x0000,
+		"Option",
+		"GI 1515 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xd257, 0x0000, 0x0000,
+		"Option",
+		"GI 1215 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
+UNUSUAL_DEV( 0x0af0, 0xd357, 0x0000, 0x0000,
+		"Option",
+		"GI 1505 SD-Card",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		0 ),
+
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000,
 		"Seagate",
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index b1e579c..6152278 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -28,7 +28,7 @@
 #define USB_SKEL_PRODUCT_ID	0xfff0
 
 /* table of devices that work with this driver */
-static struct usb_device_id skel_table[] = {
+static const struct usb_device_id skel_table[] = {
 	{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c
index 25eae40..51a8e0d 100644
--- a/drivers/usb/wusbcore/cbaf.c
+++ b/drivers/usb/wusbcore/cbaf.c
@@ -641,7 +641,7 @@
 	kzfree(cbaf);
 }
 
-static struct usb_device_id cbaf_id_table[] = {
+static const struct usb_device_id cbaf_id_table[] = {
 	{ USB_INTERFACE_INFO(0xef, 0x03, 0x01), },
 	{ },
 };
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index dced419..1c91828 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -868,7 +868,7 @@
  * reference that we'll drop.
  *
  * First we need to determine if the device is a WUSB device (else we
- * ignore it). For that we use the speed setting (USB_SPEED_VARIABLE)
+ * ignore it). For that we use the speed setting (USB_SPEED_WIRELESS)
  * [FIXME: maybe we'd need something more definitive]. If so, we track
  * it's usb_busd and from there, the WUSB HC.
  *
diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c
index 3b52161..2d82739 100644
--- a/drivers/usb/wusbcore/mmc.c
+++ b/drivers/usb/wusbcore/mmc.c
@@ -263,7 +263,7 @@
 {
 	int result = 0;
 
-	if (memcmp(chid, &wusb_ckhdid_zero, sizeof(chid)) == 0)
+	if (memcmp(chid, &wusb_ckhdid_zero, sizeof(*chid)) == 0)
 		chid = NULL;
 
 	mutex_lock(&wusbhc->mutex);
diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h
index fd2fd4e..759cda5 100644
--- a/drivers/usb/wusbcore/wusbhc.h
+++ b/drivers/usb/wusbcore/wusbhc.h
@@ -198,7 +198,7 @@
  *                 ports) this HC will take. Read-only.
  *
  * @port      	   Array of port status for each fake root port. Guaranteed to
- *                 always be the same lenght during device existence
+ *                 always be the same length during device existence
  *                 [this allows for some unlocked but referenced reading].
  *
  * @mmcies_max	   Max number of Information Elements this HC can send
diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c
index da77e41..08bd6db 100644
--- a/drivers/uwb/driver.c
+++ b/drivers/uwb/driver.c
@@ -74,13 +74,16 @@
 unsigned long beacon_timeout_ms = 500;
 
 static
-ssize_t beacon_timeout_ms_show(struct class *class, char *buf)
+ssize_t beacon_timeout_ms_show(struct class *class,
+				struct class_attribute *attr,
+				char *buf)
 {
 	return scnprintf(buf, PAGE_SIZE, "%lu\n", beacon_timeout_ms);
 }
 
 static
 ssize_t beacon_timeout_ms_store(struct class *class,
+				struct class_attribute *attr,
 				const char *buf, size_t size)
 {
 	unsigned long bt;
diff --git a/drivers/uwb/i1480/i1480-est.c b/drivers/uwb/i1480/i1480-est.c
index 7bf8c6f..f2eb4d8 100644
--- a/drivers/uwb/i1480/i1480-est.c
+++ b/drivers/uwb/i1480/i1480-est.c
@@ -54,7 +54,7 @@
 		.size = sizeof(struct i1480_rceb) + 2 },
 };
 
-static int i1480_est_init(void)
+static int __init i1480_est_init(void)
 {
 	int result = uwb_est_register(i1480_CET_VS1, 0x00, 0x8086, 0x0c3b,
 				      i1480_est_fd00,
@@ -73,7 +73,7 @@
 }
 module_init(i1480_est_init);
 
-static void i1480_est_exit(void)
+static void __exit i1480_est_exit(void)
 {
 	uwb_est_unregister(i1480_CET_VS1, 0x00, 0x8086, 0x0c3b,
 			   i1480_est_fd00, ARRAY_SIZE(i1480_est_fd00));
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c
index cdd6c8e..5fad4e7 100644
--- a/drivers/uwb/umc-bus.c
+++ b/drivers/uwb/umc-bus.c
@@ -62,12 +62,12 @@
 	struct device *parent = umc->dev.parent;
 	int ret = 0;
 
-	if(down_trylock(&parent->sem))
+	if (device_trylock(parent))
 		return -EAGAIN;
 	ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper);
 	if (ret >= 0)
 		ret = device_for_each_child(parent, parent, umc_bus_post_reset_helper);
-	up(&parent->sem);
+	device_unlock(parent);
 
 	return ret;
 }
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h
index d5bcfc1..157485c 100644
--- a/drivers/uwb/uwb-internal.h
+++ b/drivers/uwb/uwb-internal.h
@@ -366,12 +366,12 @@
 
 static inline void uwb_dev_lock(struct uwb_dev *uwb_dev)
 {
-	down(&uwb_dev->dev.sem);
+	device_lock(&uwb_dev->dev);
 }
 
 static inline void uwb_dev_unlock(struct uwb_dev *uwb_dev)
 {
-	up(&uwb_dev->dev.sem);
+	device_unlock(&uwb_dev->dev);
 }
 
 #endif /* #ifndef __UWB_INTERNAL_H__ */
diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c
index 5a777d8..6210fe1 100644
--- a/drivers/uwb/uwbd.c
+++ b/drivers/uwb/uwbd.c
@@ -43,7 +43,7 @@
  *
  * EVENTS
  *
- * Events have a type, a subtype, a lenght, some other stuff and the
+ * Events have a type, a subtype, a length, some other stuff and the
  * data blob, which depends on the event. The header is 'struct
  * uwb_event'; for payloads, see 'struct uwbd_evt_*'.
  *
diff --git a/drivers/uwb/wlp/sysfs.c b/drivers/uwb/wlp/sysfs.c
index 0370399..6627c94 100644
--- a/drivers/uwb/wlp/sysfs.c
+++ b/drivers/uwb/wlp/sysfs.c
@@ -615,8 +615,7 @@
 	return ret;
 }
 
-static
-struct sysfs_ops wss_sysfs_ops = {
+static const struct sysfs_ops wss_sysfs_ops = {
 	.show	= wlp_wss_attr_show,
 	.store	= wlp_wss_attr_store,
 };
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 0b17824..2110556 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -308,7 +308,7 @@
 	 * Pseudocolor:
 	 *    uses offset = 0 && length = RAMDAC register width.
 	 *    var->{color}.offset is 0
-	 *    var->{color}.length contains widht of DAC
+	 *    var->{color}.length contains width of DAC
 	 *    cmap is not used
 	 *    RAMDAC[X] is programmed to (red, green, blue)
 	 * Truecolor:
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 5a5c303..1c60053 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -400,9 +400,12 @@
 	  If you plan to use the LCD display with your SA-1100 system, say
 	  Y here.
 
+config HAVE_FB_IMX
+	bool
+
 config FB_IMX
 	tristate "Motorola i.MX LCD support"
-	depends on FB && (ARCH_MX1 || ARCH_MX2)
+	depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2)
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -1494,7 +1497,6 @@
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
-       select FB_SOFT_CURSOR
        select I2C_ALGOBIT
        select I2C
        help
@@ -1945,6 +1947,27 @@
 	  Turn on debugging messages. Note that you can set/unset at run time
 	  through sysfs
 
+config FB_NUC900
+        bool "NUC900 LCD framebuffer support"
+        depends on FB && ARCH_W90X900
+        select FB_CFB_FILLRECT
+        select FB_CFB_COPYAREA
+        select FB_CFB_IMAGEBLIT
+        ---help---
+          Frame buffer driver for the built-in LCD controller in the Nuvoton
+          NUC900 processor
+
+config GPM1040A0_320X240
+        bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD"
+        depends on FB_NUC900
+
+config FB_NUC900_DEBUG
+        bool "NUC900 lcd debug messages"
+        depends on FB_NUC900
+        help
+          Turn on debugging messages. Note that you can set/unset at run time
+          through sysfs
+
 config FB_SM501
 	tristate "Silicon Motion SM501 framebuffer support"
 	depends on FB && MFD_SM501
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 4ecb30c..a42ad55 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -129,6 +129,7 @@
 obj-$(CONFIG_FB_CARMINE)          += carminefb.o
 obj-$(CONFIG_FB_MB862XX)	  += mb862xx/
 obj-$(CONFIG_FB_MSM)              += msm/
+obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 0bcc59e..43d7d50 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -1221,7 +1221,7 @@
 	printk("acornfb: freed %dK memory\n", mb_freed);
 }
 
-static int __init acornfb_probe(struct platform_device *dev)
+static int __devinit acornfb_probe(struct platform_device *dev)
 {
 	unsigned long size;
 	u_int h_sync, v_sync;
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index c343169..01554d6 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -504,7 +504,7 @@
 	.fb_ioctl 	= arcfb_ioctl,
 };
 
-static int __init arcfb_probe(struct platform_device *dev)
+static int __devinit arcfb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
 	int retval = -ENOMEM;
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index 9fe90ce..e70bc22 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -140,7 +140,7 @@
 
 		/* 3 <= m <= 257 */
 		if (m >= 3 && m <= 257) {
-			unsigned new_error = ((Ftarget * n) - (Fref * m)) >= 0 ?
+			unsigned new_error = Ftarget * n >= Fref * m ?
 					       ((Ftarget * n) - (Fref * m)) : ((Fref * m) - (Ftarget * n));
 			if (new_error < best_error) {
 				best_n = n;
@@ -152,7 +152,7 @@
 		else if (m <= 1028) {
 			/* remember there are still only 8-bits of precision in m, so
 			 * avoid over-optimistic error calculations */
-			unsigned new_error = ((Ftarget * n) - (Fref * (m & ~3))) >= 0 ?
+			unsigned new_error = Ftarget * n >= Fref * (m & ~3) ?
 					       ((Ftarget * n) - (Fref * (m & ~3))) : ((Fref * (m & ~3)) - (Ftarget * n));
 			if (new_error < best_error) {
 				best_n = n;
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
new file mode 100644
index 0000000..b8f705c
--- /dev/null
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -0,0 +1,304 @@
+/*
+ * Backlight driver for Marvell Semiconductor 88PM8606
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ *	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/backlight.h>
+#include <linux/mfd/88pm860x.h>
+
+#define MAX_BRIGHTNESS		(0xFF)
+#define MIN_BRIGHTNESS		(0)
+
+#define CURRENT_MASK		(0x1F << 1)
+
+struct pm860x_backlight_data {
+	struct pm860x_chip *chip;
+	struct i2c_client *i2c;
+	int	current_brightness;
+	int	port;
+	int	pwm;
+	int	iset;
+};
+
+static inline int wled_a(int port)
+{
+	int ret;
+
+	ret = ((port - PM8606_BACKLIGHT1) << 1) + 2;
+	return ret;
+}
+
+static inline int wled_b(int port)
+{
+	int ret;
+
+	ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
+	return ret;
+}
+
+/* WLED2 & WLED3 share the same IDC */
+static inline int wled_idc(int port)
+{
+	int ret;
+
+	switch (port) {
+	case PM8606_BACKLIGHT1:
+	case PM8606_BACKLIGHT2:
+		ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
+		break;
+	case PM8606_BACKLIGHT3:
+	default:
+		ret = ((port - PM8606_BACKLIGHT2) << 1) + 3;
+		break;
+	}
+	return ret;
+}
+
+static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
+{
+	struct pm860x_backlight_data *data = bl_get_data(bl);
+	struct pm860x_chip *chip = data->chip;
+	unsigned char value;
+	int ret;
+
+	if (brightness > MAX_BRIGHTNESS)
+		value = MAX_BRIGHTNESS;
+	else
+		value = brightness;
+
+	ret = pm860x_reg_write(data->i2c, wled_a(data->port), value);
+	if (ret < 0)
+		goto out;
+
+	if ((data->current_brightness == 0) && brightness) {
+		if (data->iset) {
+			ret = pm860x_set_bits(data->i2c, wled_idc(data->port),
+					      CURRENT_MASK, data->iset);
+			if (ret < 0)
+				goto out;
+		}
+		if (data->pwm) {
+			ret = pm860x_set_bits(data->i2c, PM8606_PWM,
+					      PM8606_PWM_FREQ_MASK, data->pwm);
+			if (ret < 0)
+				goto out;
+		}
+		if (brightness == MAX_BRIGHTNESS) {
+			/* set WLED_ON bit as 100% */
+			ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+					      PM8606_WLED_ON, PM8606_WLED_ON);
+		}
+	} else {
+		if (brightness == MAX_BRIGHTNESS) {
+			/* set WLED_ON bit as 100% */
+			ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+					      PM8606_WLED_ON, PM8606_WLED_ON);
+		} else {
+			/* clear WLED_ON bit since it's not 100% */
+			ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+					      PM8606_WLED_ON, 0);
+		}
+	}
+	if (ret < 0)
+		goto out;
+
+	dev_dbg(chip->dev, "set brightness %d\n", value);
+	data->current_brightness = value;
+	return 0;
+out:
+	dev_dbg(chip->dev, "set brightness %d failure with return "
+		"value:%d\n", value, ret);
+	return ret;
+}
+
+static int pm860x_backlight_update_status(struct backlight_device *bl)
+{
+	int brightness = bl->props.brightness;
+
+	if (bl->props.power != FB_BLANK_UNBLANK)
+		brightness = 0;
+
+	if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+		brightness = 0;
+
+	if (bl->props.state & BL_CORE_SUSPENDED)
+		brightness = 0;
+
+	return pm860x_backlight_set(bl, brightness);
+}
+
+static int pm860x_backlight_get_brightness(struct backlight_device *bl)
+{
+	struct pm860x_backlight_data *data = bl_get_data(bl);
+	struct pm860x_chip *chip = data->chip;
+	int ret;
+
+	ret = pm860x_reg_read(data->i2c, wled_a(data->port));
+	if (ret < 0)
+		goto out;
+	data->current_brightness = ret;
+	dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness);
+	return data->current_brightness;
+out:
+	return -EINVAL;
+}
+
+static struct backlight_ops pm860x_backlight_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= pm860x_backlight_update_status,
+	.get_brightness	= pm860x_backlight_get_brightness,
+};
+
+static int __check_device(struct pm860x_backlight_pdata *pdata, char *name)
+{
+	struct pm860x_backlight_pdata *p = pdata;
+	int ret = -EINVAL;
+
+	while (p && p->id) {
+		if ((p->id != PM8606_ID_BACKLIGHT) || (p->flags < 0))
+			break;
+
+		if (!strncmp(name, pm860x_backlight_name[p->flags],
+			MFD_NAME_SIZE)) {
+			ret = (int)p->flags;
+			break;
+		}
+		p++;
+	}
+	return ret;
+}
+
+static int pm860x_backlight_probe(struct platform_device *pdev)
+{
+	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pm860x_platform_data *pm860x_pdata;
+	struct pm860x_backlight_pdata *pdata = NULL;
+	struct pm860x_backlight_data *data;
+	struct backlight_device *bl;
+	struct resource *res;
+	unsigned char value;
+	char name[MFD_NAME_SIZE];
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "No I/O resource!\n");
+		return -EINVAL;
+	}
+
+	if (pdev->dev.parent->platform_data) {
+		pm860x_pdata = pdev->dev.parent->platform_data;
+		pdata = pm860x_pdata->backlight;
+	}
+	if (pdata == NULL) {
+		dev_err(&pdev->dev, "platform data isn't assigned to "
+			"backlight\n");
+		return -EINVAL;
+	}
+
+	data = kzalloc(sizeof(struct pm860x_backlight_data), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+	strncpy(name, res->name, MFD_NAME_SIZE);
+	data->chip = chip;
+	data->i2c = (chip->id == CHIP_PM8606) ? chip->client	\
+			: chip->companion;
+	data->current_brightness = MAX_BRIGHTNESS;
+	data->pwm = pdata->pwm;
+	data->iset = pdata->iset;
+	data->port = __check_device(pdata, name);
+	if (data->port < 0) {
+		dev_err(&pdev->dev, "wrong platform data is assigned");
+		return -EINVAL;
+	}
+
+	bl = backlight_device_register(name, &pdev->dev, data,
+					&pm860x_backlight_ops);
+	if (IS_ERR(bl)) {
+		dev_err(&pdev->dev, "failed to register backlight\n");
+		kfree(data);
+		return PTR_ERR(bl);
+	}
+	bl->props.max_brightness = MAX_BRIGHTNESS;
+	bl->props.brightness = MAX_BRIGHTNESS;
+
+	platform_set_drvdata(pdev, bl);
+
+	/* Enable reference VSYS */
+	ret = pm860x_reg_read(data->i2c, PM8606_VSYS);
+	if (ret < 0)
+		goto out;
+	if ((ret & PM8606_VSYS_EN) == 0) {
+		value = ret | PM8606_VSYS_EN;
+		ret = pm860x_reg_write(data->i2c, PM8606_VSYS, value);
+		if (ret < 0)
+			goto out;
+	}
+	/* Enable reference OSC */
+	ret = pm860x_reg_read(data->i2c, PM8606_MISC);
+	if (ret < 0)
+		goto out;
+	if ((ret & PM8606_MISC_OSC_EN) == 0) {
+		value = ret | PM8606_MISC_OSC_EN;
+		ret = pm860x_reg_write(data->i2c, PM8606_MISC, value);
+		if (ret < 0)
+			goto out;
+	}
+	/* read current backlight */
+	ret = pm860x_backlight_get_brightness(bl);
+	if (ret < 0)
+		goto out;
+
+	backlight_update_status(bl);
+	return 0;
+out:
+	kfree(data);
+	return ret;
+}
+
+static int pm860x_backlight_remove(struct platform_device *pdev)
+{
+	struct backlight_device *bl = platform_get_drvdata(pdev);
+	struct pm860x_backlight_data *data = bl_get_data(bl);
+
+	backlight_device_unregister(bl);
+	kfree(data);
+	return 0;
+}
+
+static struct platform_driver pm860x_backlight_driver = {
+	.driver		= {
+		.name	= "88pm860x-backlight",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pm860x_backlight_probe,
+	.remove		= pm860x_backlight_remove,
+};
+
+static int __init pm860x_backlight_init(void)
+{
+	return platform_driver_register(&pm860x_backlight_driver);
+}
+module_init(pm860x_backlight_init);
+
+static void __exit pm860x_backlight_exit(void)
+{
+	platform_driver_unregister(&pm860x_backlight_driver);
+}
+module_exit(pm860x_backlight_exit);
+
+MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:88pm860x-backlight");
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 09bfa96..0c77fc6 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -212,6 +212,13 @@
 	  If you have a LCD backlight connected to the WLED output of DA9030
 	  or DA9034 WLED output, say Y here to enable this driver.
 
+config BACKLIGHT_MAX8925
+	tristate "Backlight driver for MAX8925"
+	depends on BACKLIGHT_CLASS_DEVICE && MFD_MAX8925
+	help
+	  If you have a LCD backlight connected to the WLED output of MAX8925
+	  WLED output, say Y here to enable this driver.
+
 config BACKLIGHT_MBP_NVIDIA
        tristate "MacBook Pro Nvidia Backlight Driver"
        depends on BACKLIGHT_CLASS_DEVICE && X86
@@ -262,3 +269,9 @@
 	  To compile this driver as a module, choose M here: the module will
 	  be called adp5520_bl.
 
+config BACKLIGHT_88PM860X
+	tristate "Backlight Driver for 88PM8606 using WLED"
+	depends on BACKLIGHT_CLASS_DEVICE && MFD_88PM860X
+	help
+	  Say Y to enable the backlight driver for Marvell 88PM8606.
+
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 9a40554..6c704d4 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -22,10 +22,12 @@
 obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
 obj-$(CONFIG_BACKLIGHT_PWM)	+= pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_DA903X)	+= da903x_bl.o
+obj-$(CONFIG_BACKLIGHT_MAX8925)	+= max8925_bl.o
 obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)	+= tosa_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA)	+= kb3886_bl.o
 obj-$(CONFIG_BACKLIGHT_WM831X)	+= wm831x_bl.o
 obj-$(CONFIG_BACKLIGHT_ADX)    += adx_bl.o
 obj-$(CONFIG_BACKLIGHT_ADP5520)	+= adp5520_bl.o
+obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
 
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
new file mode 100644
index 0000000..c267069
--- /dev/null
+++ b/drivers/video/backlight/max8925_bl.c
@@ -0,0 +1,200 @@
+/*
+ * Backlight driver for Maxim MAX8925
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ *      Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/backlight.h>
+#include <linux/mfd/max8925.h>
+
+#define MAX_BRIGHTNESS		(0xff)
+#define MIN_BRIGHTNESS		(0)
+
+#define LWX_FREQ(x)		(((x - 601) / 100) & 0x7)
+
+struct max8925_backlight_data {
+	struct max8925_chip	*chip;
+
+	int		current_brightness;
+};
+
+static int max8925_backlight_set(struct backlight_device *bl, int brightness)
+{
+	struct max8925_backlight_data *data = bl_get_data(bl);
+	struct max8925_chip *chip = data->chip;
+	unsigned char value;
+	int ret;
+
+	if (brightness > MAX_BRIGHTNESS)
+		value = MAX_BRIGHTNESS;
+	else
+		value = brightness;
+
+	ret = max8925_reg_write(chip->i2c, MAX8925_WLED_CNTL, value);
+	if (ret < 0)
+		goto out;
+
+	if (!data->current_brightness && brightness)
+		/* enable WLED output */
+		ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 1);
+	else if (!brightness)
+		/* disable WLED output */
+		ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 0);
+	if (ret < 0)
+		goto out;
+	dev_dbg(chip->dev, "set brightness %d\n", value);
+	data->current_brightness = value;
+	return 0;
+out:
+	dev_dbg(chip->dev, "set brightness %d failure with return value:%d\n",
+		value, ret);
+	return ret;
+}
+
+static int max8925_backlight_update_status(struct backlight_device *bl)
+{
+	int brightness = bl->props.brightness;
+
+	if (bl->props.power != FB_BLANK_UNBLANK)
+		brightness = 0;
+
+	if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+		brightness = 0;
+
+	if (bl->props.state & BL_CORE_SUSPENDED)
+		brightness = 0;
+
+	return max8925_backlight_set(bl, brightness);
+}
+
+static int max8925_backlight_get_brightness(struct backlight_device *bl)
+{
+	struct max8925_backlight_data *data = bl_get_data(bl);
+	struct max8925_chip *chip = data->chip;
+	int ret;
+
+	ret = max8925_reg_read(chip->i2c, MAX8925_WLED_CNTL);
+	if (ret < 0)
+		return -EINVAL;
+	data->current_brightness = ret;
+	dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness);
+	return ret;
+}
+
+static struct backlight_ops max8925_backlight_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= max8925_backlight_update_status,
+	.get_brightness	= max8925_backlight_get_brightness,
+};
+
+static int __devinit max8925_backlight_probe(struct platform_device *pdev)
+{
+	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct max8925_platform_data *max8925_pdata;
+	struct max8925_backlight_pdata *pdata = NULL;
+	struct max8925_backlight_data *data;
+	struct backlight_device *bl;
+	struct resource *res;
+	char name[MAX8925_NAME_SIZE];
+	unsigned char value;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "No I/O resource!\n");
+		return -EINVAL;
+	}
+
+	if (pdev->dev.parent->platform_data) {
+		max8925_pdata = pdev->dev.parent->platform_data;
+		pdata = max8925_pdata->backlight;
+	}
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform data isn't assigned to "
+			"backlight\n");
+		return -EINVAL;
+	}
+
+	data = kzalloc(sizeof(struct max8925_backlight_data), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+	strncpy(name, res->name, MAX8925_NAME_SIZE);
+	data->chip = chip;
+	data->current_brightness = 0;
+
+	bl = backlight_device_register(name, &pdev->dev, data,
+					&max8925_backlight_ops);
+	if (IS_ERR(bl)) {
+		dev_err(&pdev->dev, "failed to register backlight\n");
+		kfree(data);
+		return PTR_ERR(bl);
+	}
+	bl->props.max_brightness = MAX_BRIGHTNESS;
+	bl->props.brightness = MAX_BRIGHTNESS;
+
+	platform_set_drvdata(pdev, bl);
+
+	value = 0;
+	if (pdata->lxw_scl)
+		value |= (1 << 7);
+	if (pdata->lxw_freq)
+		value |= (LWX_FREQ(pdata->lxw_freq) << 4);
+	if (pdata->dual_string)
+		value |= (1 << 1);
+	ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 0xfe, value);
+	if (ret < 0)
+		goto out;
+
+	backlight_update_status(bl);
+	return 0;
+out:
+	kfree(data);
+	return ret;
+}
+
+static int __devexit max8925_backlight_remove(struct platform_device *pdev)
+{
+	struct backlight_device *bl = platform_get_drvdata(pdev);
+	struct max8925_backlight_data *data = bl_get_data(bl);
+
+	backlight_device_unregister(bl);
+	kfree(data);
+	return 0;
+}
+
+static struct platform_driver max8925_backlight_driver = {
+	.driver		= {
+		.name	= "max8925-backlight",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= max8925_backlight_probe,
+	.remove		= __devexit_p(max8925_backlight_remove),
+};
+
+static int __init max8925_backlight_init(void)
+{
+	return platform_driver_register(&max8925_backlight_driver);
+}
+module_init(max8925_backlight_init);
+
+static void __exit max8925_backlight_exit(void)
+{
+	platform_driver_unregister(&max8925_backlight_driver);
+};
+module_exit(max8925_backlight_exit);
+
+MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:max8925-backlight");
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index e49ae5ed..814312a 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -82,7 +82,6 @@
 	unsigned char *fb_buffer;	/* RGB Buffer */
 
 	dma_addr_t dma_handle;
-	int lq043_mmap;
 	int lq043_open_cnt;
 	int irq;
 	spinlock_t lock;	/* lock */
@@ -316,7 +315,6 @@
 	spin_lock(&fbi->lock);
 
 	fbi->lq043_open_cnt--;
-	fbi->lq043_mmap = 0;
 
 	if (fbi->lq043_open_cnt <= 0) {
 
@@ -374,33 +372,6 @@
 	return 0;
 }
 
-static int bfin_bf54x_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-
-	struct bfin_bf54xfb_info *fbi = info->par;
-
-	if (fbi->lq043_mmap)
-		return -1;
-
-	spin_lock(&fbi->lock);
-	fbi->lq043_mmap = 1;
-	spin_unlock(&fbi->lock);
-
-	vma->vm_start = (unsigned long)(fbi->fb_buffer);
-
-	vma->vm_end = vma->vm_start + info->fix.smem_len;
-	/* For those who don't understand how mmap works, go read
-	 *   Documentation/nommu-mmap.txt.
-	 * For those that do, you will know that the VM_MAYSHARE flag
-	 * must be set in the vma->vm_flags structure on noMMU
-	 *   Other flags can be set, and are documented in
-	 *   include/linux/mm.h
-	 */
-	vma->vm_flags |=  VM_MAYSHARE | VM_SHARED;
-
-	return 0;
-}
-
 int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
 	if (nocursor)
@@ -452,7 +423,6 @@
 	.fb_fillrect = cfb_fillrect,
 	.fb_copyarea = cfb_copyarea,
 	.fb_imageblit = cfb_imageblit,
-	.fb_mmap = bfin_bf54x_fb_mmap,
 	.fb_cursor = bfin_bf54x_fb_cursor,
 	.fb_setcolreg = bfin_bf54x_fb_setcolreg,
 };
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
index b690c26..0387236 100644
--- a/drivers/video/bfin-lq035q1-fb.c
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -22,7 +22,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
-#include <linux/dma-mapping.h>
 
 #include <asm/blackfin.h>
 #include <asm/irq.h>
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 2549c53..5653d08 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -87,7 +87,6 @@
 	struct device *dev;
 	unsigned char *fb_buffer;	/* RGB Buffer */
 	dma_addr_t dma_handle;
-	int lq043_mmap;
 	int lq043_open_cnt;
 	int irq;
 	spinlock_t lock;	/* lock */
@@ -235,7 +234,6 @@
 	spin_lock(&fbi->lock);
 
 	fbi->lq043_open_cnt--;
-	fbi->lq043_mmap = 0;
 
 	if (fbi->lq043_open_cnt <= 0) {
 		bfin_t350mcqb_disable_ppi();
@@ -293,32 +291,6 @@
 	return 0;
 }
 
-static int bfin_t350mcqb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct bfin_t350mcqbfb_info *fbi = info->par;
-
-	if (fbi->lq043_mmap)
-		return -1;
-
-	spin_lock(&fbi->lock);
-	fbi->lq043_mmap = 1;
-	spin_unlock(&fbi->lock);
-
-	vma->vm_start = (unsigned long)(fbi->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET);
-
-	vma->vm_end = vma->vm_start + info->fix.smem_len;
-	/* For those who don't understand how mmap works, go read
-	 *   Documentation/nommu-mmap.txt.
-	 * For those that do, you will know that the VM_MAYSHARE flag
-	 * must be set in the vma->vm_flags structure on noMMU
-	 *   Other flags can be set, and are documented in
-	 *   include/linux/mm.h
-	 */
-	vma->vm_flags |= VM_MAYSHARE | VM_SHARED;
-
-	return 0;
-}
-
 int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
 	if (nocursor)
@@ -370,7 +342,6 @@
 	.fb_fillrect = cfb_fillrect,
 	.fb_copyarea = cfb_copyarea,
 	.fb_imageblit = cfb_imageblit,
-	.fb_mmap = bfin_t350mcqb_fb_mmap,
 	.fb_cursor = bfin_t350mcqb_fb_cursor,
 	.fb_setcolreg = bfin_t350mcqb_fb_setcolreg,
 };
diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c
index df9ccb9..ebda687 100644
--- a/drivers/video/broadsheetfb.c
+++ b/drivers/video/broadsheetfb.c
@@ -29,11 +29,65 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/list.h>
+#include <linux/firmware.h>
 #include <linux/uaccess.h>
 
 #include <video/broadsheetfb.h>
 
-/* Display specific information */
+/* track panel specific parameters */
+struct panel_info {
+	int w;
+	int h;
+	u16 sdcfg;
+	u16 gdcfg;
+	u16 lutfmt;
+	u16 fsynclen;
+	u16 fendfbegin;
+	u16 lsynclen;
+	u16 lendlbegin;
+	u16 pixclk;
+};
+
+/* table of panel specific parameters to be indexed into by the board drivers */
+static struct panel_info panel_table[] = {
+	{	/* standard 6" on TFT backplane */
+		.w = 800,
+		.h = 600,
+		.sdcfg = (100 | (1 << 8) | (1 << 9)),
+		.gdcfg = 2,
+		.lutfmt = (4 | (1 << 7)),
+		.fsynclen = 4,
+		.fendfbegin = (10 << 8) | 4,
+		.lsynclen = 10,
+		.lendlbegin = (100 << 8) | 4,
+		.pixclk = 6,
+	},
+	{	/* custom 3.7" flexible on PET or steel */
+		.w = 320,
+		.h = 240,
+		.sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)),
+		.gdcfg = 3,
+		.lutfmt = (4 | (1 << 7)),
+		.fsynclen = 0,
+		.fendfbegin = (80 << 8) | 4,
+		.lsynclen = 10,
+		.lendlbegin = (80 << 8) | 20,
+		.pixclk = 14,
+	},
+	{	/* standard 9.7" on TFT backplane */
+		.w = 1200,
+		.h = 825,
+		.sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)),
+		.gdcfg = 2,
+		.lutfmt = (4 | (1 << 7)),
+		.fsynclen = 0,
+		.fendfbegin = (4 << 8) | 4,
+		.lsynclen = 4,
+		.lendlbegin = (60 << 8) | 10,
+		.pixclk = 3,
+	},
+};
+
 #define DPY_W 800
 #define DPY_H 600
 
@@ -62,30 +116,30 @@
 };
 
 /* main broadsheetfb functions */
-static void broadsheet_issue_data(struct broadsheetfb_par *par, u16 data)
+static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data)
 {
 	par->board->set_ctl(par, BS_WR, 0);
 	par->board->set_hdb(par, data);
 	par->board->set_ctl(par, BS_WR, 1);
 }
 
-static void broadsheet_issue_cmd(struct broadsheetfb_par *par, u16 data)
+static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data)
 {
 	par->board->set_ctl(par, BS_DC, 0);
-	broadsheet_issue_data(par, data);
+	broadsheet_gpio_issue_data(par, data);
 }
 
-static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data)
+static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data)
 {
 	par->board->wait_for_rdy(par);
 
 	par->board->set_ctl(par, BS_CS, 0);
-	broadsheet_issue_cmd(par, data);
+	broadsheet_gpio_issue_cmd(par, data);
 	par->board->set_ctl(par, BS_DC, 1);
 	par->board->set_ctl(par, BS_CS, 1);
 }
 
-static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
+static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
 					int argc, u16 *argv)
 {
 	int i;
@@ -93,15 +147,43 @@
 	par->board->wait_for_rdy(par);
 
 	par->board->set_ctl(par, BS_CS, 0);
-	broadsheet_issue_cmd(par, cmd);
+	broadsheet_gpio_issue_cmd(par, cmd);
 	par->board->set_ctl(par, BS_DC, 1);
 
 	for (i = 0; i < argc; i++)
-		broadsheet_issue_data(par, argv[i]);
+		broadsheet_gpio_issue_data(par, argv[i]);
 	par->board->set_ctl(par, BS_CS, 1);
 }
 
-static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
+static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
+				    int argc, u16 *argv)
+{
+	int i;
+
+	par->board->mmio_write(par, BS_MMIO_CMD, cmd);
+
+	for (i = 0; i < argc; i++)
+		par->board->mmio_write(par, BS_MMIO_DATA, argv[i]);
+}
+
+static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data)
+{
+	if (par->board->mmio_write)
+		par->board->mmio_write(par, BS_MMIO_CMD, data);
+	else
+		broadsheet_gpio_send_command(par, data);
+}
+
+static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
+				    int argc, u16 *argv)
+{
+	if (par->board->mmio_write)
+		broadsheet_mmio_send_cmdargs(par, cmd, argc, argv);
+	else
+		broadsheet_gpio_send_cmdargs(par, cmd, argc, argv);
+}
+
+static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size,
 					u16 *data)
 {
 	int i;
@@ -121,7 +203,30 @@
 	par->board->set_ctl(par, BS_CS, 1);
 }
 
-static u16 broadsheet_get_data(struct broadsheetfb_par *par)
+static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size,
+				   u16 *data)
+{
+	int i;
+	u16 tmp;
+
+	for (i = 0; i < size; i++) {
+		tmp = (data[i] & 0x0F) << 4;
+		tmp |= (data[i] & 0x0F00) << 4;
+		par->board->mmio_write(par, BS_MMIO_DATA, tmp);
+	}
+
+}
+
+static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
+				   u16 *data)
+{
+	if (par->board->mmio_write)
+		broadsheet_mmio_burst_write(par, size, data);
+	else
+		broadsheet_gpio_burst_write(par, size, data);
+}
+
+static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par)
 {
 	u16 res;
 	/* wait for ready to go hi. (lo is busy) */
@@ -141,7 +246,16 @@
 	return res;
 }
 
-static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
+
+static u16 broadsheet_get_data(struct broadsheetfb_par *par)
+{
+	if (par->board->mmio_read)
+		return par->board->mmio_read(par);
+	else
+		return broadsheet_gpio_get_data(par);
+}
+
+static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg,
 					u16 data)
 {
 	/* wait for ready to go hi. (lo is busy) */
@@ -150,44 +264,541 @@
 	/* cs lo, dc lo for cmd, we lo for each data, db as usual */
 	par->board->set_ctl(par, BS_CS, 0);
 
-	broadsheet_issue_cmd(par, BS_CMD_WR_REG);
+	broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG);
 
 	par->board->set_ctl(par, BS_DC, 1);
 
-	broadsheet_issue_data(par, reg);
-	broadsheet_issue_data(par, data);
+	broadsheet_gpio_issue_data(par, reg);
+	broadsheet_gpio_issue_data(par, data);
 
 	par->board->set_ctl(par, BS_CS, 1);
 }
 
+static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg,
+				 u16 data)
+{
+	par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG);
+	par->board->mmio_write(par, BS_MMIO_DATA, reg);
+	par->board->mmio_write(par, BS_MMIO_DATA, data);
+
+}
+
+static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
+					u16 data)
+{
+	if (par->board->mmio_write)
+		broadsheet_mmio_write_reg(par, reg, data);
+	else
+		broadsheet_gpio_write_reg(par, reg, data);
+}
+
+static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg,
+					u32 data)
+{
+	broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF);
+	broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF);
+}
+
+
 static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg)
 {
-	broadsheet_send_command(par, reg);
-	msleep(100);
+	broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, &reg);
+	par->board->wait_for_rdy(par);
 	return broadsheet_get_data(par);
 }
 
+/* functions for waveform manipulation */
+static int is_broadsheet_pll_locked(struct broadsheetfb_par *par)
+{
+	return broadsheet_read_reg(par, 0x000A) & 0x0001;
+}
+
+static int broadsheet_setup_plls(struct broadsheetfb_par *par)
+{
+	int retry_count = 0;
+	u16 tmp;
+
+	/* disable arral saemipu mode */
+	broadsheet_write_reg(par, 0x0006, 0x0000);
+
+	broadsheet_write_reg(par, 0x0010, 0x0004);
+	broadsheet_write_reg(par, 0x0012, 0x5949);
+	broadsheet_write_reg(par, 0x0014, 0x0040);
+	broadsheet_write_reg(par, 0x0016, 0x0000);
+
+	do {
+		if (retry_count++ > 100)
+			return -ETIMEDOUT;
+		mdelay(1);
+	} while (!is_broadsheet_pll_locked(par));
+
+	tmp = broadsheet_read_reg(par, 0x0006);
+	tmp &= ~0x1;
+	broadsheet_write_reg(par, 0x0006, tmp);
+
+	return 0;
+}
+
+static int broadsheet_setup_spi(struct broadsheetfb_par *par)
+{
+
+	broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
+	broadsheet_write_reg(par, 0x0208, 0x0001);
+
+	return 0;
+}
+
+static int broadsheet_setup_spiflash(struct broadsheetfb_par *par,
+						u16 *orig_sfmcd)
+{
+
+	*orig_sfmcd = broadsheet_read_reg(par, 0x0204);
+	broadsheet_write_reg(par, 0x0208, 0);
+	broadsheet_write_reg(par, 0x0204, 0);
+	broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
+
+	return 0;
+}
+
+static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par,
+						u16 reg, int bitnum, int val,
+						int timeout)
+{
+	u16 tmp;
+
+	do {
+		tmp = broadsheet_read_reg(par, reg);
+		if (((tmp >> bitnum) & 1) == val)
+			return 0;
+		mdelay(1);
+	} while (timeout--);
+
+	return -ETIMEDOUT;
+}
+
+static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data)
+{
+	broadsheet_write_reg(par, 0x0202, (data | 0x100));
+
+	return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
+}
+
+static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data)
+{
+	int err;
+	u16 tmp;
+
+	broadsheet_write_reg(par, 0x0202, 0);
+
+	err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
+	if (err)
+		return err;
+
+	tmp = broadsheet_read_reg(par, 0x200);
+
+	*data = tmp & 0xFF;
+
+	return 0;
+}
+
+static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par,
+								int timeout)
+{
+	u8 tmp;
+	int err;
+
+	do {
+		broadsheet_write_reg(par, 0x0208, 1);
+
+		err = broadsheet_spiflash_write_byte(par, 0x05);
+		if (err)
+			goto failout;
+
+		err = broadsheet_spiflash_read_byte(par, &tmp);
+		if (err)
+			goto failout;
+
+		broadsheet_write_reg(par, 0x0208, 0);
+
+		if (!(tmp & 0x1))
+			return 0;
+
+		mdelay(5);
+	} while (timeout--);
+
+	dev_err(par->info->device, "Timed out waiting for spiflash status\n");
+	return -ETIMEDOUT;
+
+failout:
+	broadsheet_write_reg(par, 0x0208, 0);
+	return err;
+}
+
+static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par,
+							u8 op, u32 addr)
+{
+	int i;
+	u8 tmp;
+	int err;
+
+	broadsheet_write_reg(par, 0x0208, 1);
+
+	err = broadsheet_spiflash_write_byte(par, op);
+	if (err)
+		return err;
+
+	for (i = 2; i >= 0; i--) {
+		tmp = ((addr >> (i * 8)) & 0xFF);
+		err = broadsheet_spiflash_write_byte(par, tmp);
+		if (err)
+			return err;
+	}
+
+	return err;
+}
+
+static int broadsheet_verify_spiflash(struct broadsheetfb_par *par,
+						int *flash_type)
+{
+	int err = 0;
+	u8 sig;
+
+	err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000);
+	if (err)
+		goto failout;
+
+	err = broadsheet_spiflash_read_byte(par, &sig);
+	if (err)
+		goto failout;
+
+	if ((sig != 0x10) && (sig != 0x11)) {
+		dev_err(par->info->device, "Unexpected flash type\n");
+		err = -EINVAL;
+		goto failout;
+	}
+
+	*flash_type = sig;
+
+failout:
+	broadsheet_write_reg(par, 0x0208, 0);
+	return err;
+}
+
+static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par,
+					u16 *initial_sfmcd, int *flash_type)
+
+{
+	int err;
+
+	err = broadsheet_setup_plls(par);
+	if (err)
+		return err;
+
+	broadsheet_write_reg(par, 0x0106, 0x0203);
+
+	err = broadsheet_setup_spi(par);
+	if (err)
+		return err;
+
+	err = broadsheet_setup_spiflash(par, initial_sfmcd);
+	if (err)
+		return err;
+
+	return broadsheet_verify_spiflash(par, flash_type);
+}
+
+static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par,
+						int mode)
+{
+	int err;
+
+	broadsheet_write_reg(par, 0x0208, 1);
+	if (mode)
+		err = broadsheet_spiflash_write_byte(par, 0x06);
+	else
+		err = broadsheet_spiflash_write_byte(par, 0x04);
+
+	broadsheet_write_reg(par, 0x0208, 0);
+	return err;
+}
+
+static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par,
+						int addr)
+{
+	int err;
+
+	broadsheet_spiflash_write_control(par, 1);
+
+	err = broadsheet_spiflash_op_on_address(par, 0xD8, addr);
+
+	broadsheet_write_reg(par, 0x0208, 0);
+
+	if (err)
+		return err;
+
+	err = broadsheet_spiflash_wait_for_status(par, 1000);
+
+	return err;
+}
+
+static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par,
+						int addr, int size, char *data)
+{
+	int err;
+	int i;
+
+	err = broadsheet_spiflash_op_on_address(par, 0x03, addr);
+	if (err)
+		goto failout;
+
+	for (i = 0; i < size; i++) {
+		err = broadsheet_spiflash_read_byte(par, &data[i]);
+		if (err)
+			goto failout;
+	}
+
+failout:
+	broadsheet_write_reg(par, 0x0208, 0);
+	return err;
+}
+
+#define BS_SPIFLASH_PAGE_SIZE 256
+static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par,
+						int addr, const char *data)
+{
+	int err;
+	int i;
+
+	broadsheet_spiflash_write_control(par, 1);
+
+	err = broadsheet_spiflash_op_on_address(par, 0x02, addr);
+	if (err)
+		goto failout;
+
+	for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) {
+		err = broadsheet_spiflash_write_byte(par, data[i]);
+		if (err)
+			goto failout;
+	}
+
+	broadsheet_write_reg(par, 0x0208, 0);
+
+	err = broadsheet_spiflash_wait_for_status(par, 100);
+
+failout:
+	return err;
+}
+
+static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par,
+				int addr, const char *data, int sector_size)
+{
+	int i;
+	int err;
+
+	for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) {
+		err = broadsheet_spiflash_write_page(par, addr + i, &data[i]);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+/*
+ * The caller must guarantee that the data to be rewritten is entirely
+ * contained within this sector. That is, data_start_addr + data_len
+ * must be less than sector_start_addr + sector_size.
+ */
+static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
+					int sector_size, int data_start_addr,
+					int data_len, const char *data)
+{
+	int err;
+	char *sector_buffer;
+	int tail_start_addr;
+	int start_sector_addr;
+
+	sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL);
+	if (!sector_buffer)
+		return -ENOMEM;
+
+	/* the start address of the sector is the 0th byte of that sector */
+	start_sector_addr = (data_start_addr / sector_size) * sector_size;
+
+	/*
+	 * check if there is head data that we need to readback into our sector
+	 * buffer first
+	 */
+	if (data_start_addr != start_sector_addr) {
+		/*
+		 * we need to read every byte up till the start address of our
+		 * data and we put it into our sector buffer.
+		 */
+		err = broadsheet_spiflash_read_range(par, start_sector_addr,
+						data_start_addr, sector_buffer);
+		if (err)
+			return err;
+	}
+
+	/* now we copy our data into the right place in the sector buffer */
+	memcpy(sector_buffer + data_start_addr, data, data_len);
+
+	/*
+	 * now we check if there is a tail section of the sector that we need to
+	 * readback.
+	 */
+	tail_start_addr = (data_start_addr + data_len) % sector_size;
+
+	if (tail_start_addr) {
+		int tail_len;
+
+		tail_len = sector_size - tail_start_addr;
+
+		/* now we read this tail into our sector buffer */
+		err = broadsheet_spiflash_read_range(par, tail_start_addr,
+			tail_len, sector_buffer + tail_start_addr);
+		if (err)
+			return err;
+	}
+
+	/* if we got here we have the full sector that we want to rewrite. */
+
+	/* first erase the sector */
+	err = broadsheet_spiflash_erase_sector(par, start_sector_addr);
+	if (err)
+		return err;
+
+	/* now write it */
+	err = broadsheet_spiflash_write_sector(par, start_sector_addr,
+					sector_buffer, sector_size);
+	return err;
+}
+
+static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr,
+				const u8 *wfm, int bytecount, int flash_type)
+{
+	int sector_size;
+	int err;
+	int cur_addr;
+	int writecount;
+	int maxlen;
+	int offset = 0;
+
+	switch (flash_type) {
+	case 0x10:
+		sector_size = 32*1024;
+		break;
+	case 0x11:
+	default:
+		sector_size = 64*1024;
+		break;
+	}
+
+	while (bytecount) {
+		cur_addr = wfm_addr + offset;
+		maxlen = roundup(cur_addr, sector_size) - cur_addr;
+		writecount = min(bytecount, maxlen);
+
+		err = broadsheet_spiflash_rewrite_sector(par, sector_size,
+				cur_addr, writecount, wfm + offset);
+		if (err)
+			return err;
+
+		offset += writecount;
+		bytecount -= writecount;
+	}
+
+	return 0;
+}
+
+static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par,
+						const u8 *wfm, size_t wfm_size)
+{
+	int err = 0;
+	u16 initial_sfmcd = 0;
+	int flash_type = 0;
+
+	err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type);
+	if (err)
+		goto failout;
+
+	err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type);
+
+failout:
+	broadsheet_write_reg(par, 0x0204, initial_sfmcd);
+	return err;
+}
+
+static ssize_t broadsheet_loadstore_waveform(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf, size_t len)
+{
+	int err;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct broadsheetfb_par *par = info->par;
+	const struct firmware *fw_entry;
+
+	if (len < 1)
+		return -EINVAL;
+
+	err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
+	if (err < 0) {
+		dev_err(dev, "Failed to get broadsheet waveform\n");
+		goto err_failed;
+	}
+
+	/* try to enforce reasonable min max on waveform */
+	if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
+		dev_err(dev, "Invalid waveform\n");
+		err = -EINVAL;
+		goto err_failed;
+	}
+
+	mutex_lock(&(par->io_lock));
+	err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data,
+							fw_entry->size);
+
+	mutex_unlock(&(par->io_lock));
+	if (err < 0) {
+		dev_err(dev, "Failed to store broadsheet waveform\n");
+		goto err_failed;
+	}
+
+	dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
+
+	return len;
+
+err_failed:
+	return err;
+}
+static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
+			broadsheet_loadstore_waveform);
+
+/* upper level functions that manipulate the display and other stuff */
 static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
 {
 	u16 args[5];
+	int xres = par->info->var.xres;
+	int yres = par->info->var.yres;
 
-	args[0] = DPY_W;
-	args[1] = DPY_H;
-	args[2] = (100 | (1 << 8) | (1 << 9)); /* sdcfg */
-	args[3] = 2; /* gdrv cfg */
-	args[4] = (4 | (1 << 7)); /* lut index format */
+	args[0] = panel_table[par->panel_index].w;
+	args[1] = panel_table[par->panel_index].h;
+	args[2] = panel_table[par->panel_index].sdcfg;
+	args[3] = panel_table[par->panel_index].gdcfg;
+	args[4] = panel_table[par->panel_index].lutfmt;
 	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
 
 	/* did the controller really set it? */
 	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
 
-	args[0] = 4; /* fsync len */
-	args[1] = (10 << 8) | 4; /* fend/fbegin len */
-	args[2] = 10; /* line sync len */
-	args[3] = (100 << 8) | 4; /* line end/begin len */
-	args[4] = 6; /* pixel clock cfg */
+	args[0] = panel_table[par->panel_index].fsynclen;
+	args[1] = panel_table[par->panel_index].fendfbegin;
+	args[2] = panel_table[par->panel_index].lsynclen;
+	args[3] = panel_table[par->panel_index].lendlbegin;
+	args[4] = panel_table[par->panel_index].pixclk;
 	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
 
+	broadsheet_write_reg32(par, 0x310, xres*yres*2);
+
 	/* setup waveform */
 	args[0] = 0x886;
 	args[1] = 0;
@@ -207,8 +818,9 @@
 	args[0] = 0x154;
 	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
 
-	broadsheet_burst_write(par, DPY_W*DPY_H/2,
-				(u16 *) par->info->screen_base);
+	broadsheet_burst_write(par, (panel_table[par->panel_index].w *
+					panel_table[par->panel_index].h)/2,
+					(u16 *) par->info->screen_base);
 
 	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
 
@@ -222,6 +834,21 @@
 	par->board->wait_for_rdy(par);
 }
 
+static void __devinit broadsheet_identify(struct broadsheetfb_par *par)
+{
+	u16 rev, prc;
+	struct device *dev = par->info->device;
+
+	rev = broadsheet_read_reg(par, BS_REG_REV);
+	prc = broadsheet_read_reg(par, BS_REG_PRC);
+	dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc);
+
+	if (prc != 0x0047)
+		dev_warn(dev, "Unrecognized Broadsheet Product Code\n");
+	if (rev != 0x0100)
+		dev_warn(dev, "Unrecognized Broadsheet Revision\n");
+}
+
 static void __devinit broadsheet_init(struct broadsheetfb_par *par)
 {
 	broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
@@ -236,6 +863,7 @@
 	u16 args[5];
 	unsigned char *buf = (unsigned char *)par->info->screen_base;
 
+	mutex_lock(&(par->io_lock));
 	/* y1 must be a multiple of 4 so drop the lower bits */
 	y1 &= 0xFFFC;
 	/* y2 must be a multiple of 4 , but - 1 so up the lower bits */
@@ -265,6 +893,7 @@
 	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
 
 	par->board->wait_for_rdy(par);
+	mutex_unlock(&(par->io_lock));
 
 }
 
@@ -272,13 +901,15 @@
 {
 	u16 args[5];
 
+	mutex_lock(&(par->io_lock));
 	args[0] = 0x3 << 4;
 	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
 
 	args[0] = 0x154;
 	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
-	broadsheet_burst_write(par, DPY_W*DPY_H/2,
-				(u16 *) par->info->screen_base);
+	broadsheet_burst_write(par, (panel_table[par->panel_index].w *
+					panel_table[par->panel_index].h)/2,
+					(u16 *) par->info->screen_base);
 
 	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
 
@@ -290,7 +921,7 @@
 	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
 
 	par->board->wait_for_rdy(par);
-
+	mutex_unlock(&(par->io_lock));
 }
 
 /* this is called back from the deferred io workqueue */
@@ -436,6 +1067,8 @@
 	unsigned char *videomemory;
 	struct broadsheetfb_par *par;
 	int i;
+	int dpyw, dpyh;
+	int panel_index;
 
 	/* pick up board specific routines */
 	board = dev->dev.platform_data;
@@ -450,7 +1083,24 @@
 	if (!info)
 		goto err;
 
-	videomemorysize = (DPY_W*DPY_H);
+	switch (board->get_panel_type()) {
+	case 37:
+		panel_index = 1;
+		break;
+	case 97:
+		panel_index = 2;
+		break;
+	case 6:
+	default:
+		panel_index = 0;
+		break;
+	}
+
+	dpyw = panel_table[panel_index].w;
+	dpyh = panel_table[panel_index].h;
+
+	videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
+
 	videomemory = vmalloc(videomemorysize);
 	if (!videomemory)
 		goto err_fb_rel;
@@ -460,16 +1110,25 @@
 	info->screen_base = (char *)videomemory;
 	info->fbops = &broadsheetfb_ops;
 
+	broadsheetfb_var.xres = dpyw;
+	broadsheetfb_var.yres = dpyh;
+	broadsheetfb_var.xres_virtual = dpyw;
+	broadsheetfb_var.yres_virtual = dpyh;
 	info->var = broadsheetfb_var;
+
+	broadsheetfb_fix.line_length = dpyw;
 	info->fix = broadsheetfb_fix;
 	info->fix.smem_len = videomemorysize;
 	par = info->par;
+	par->panel_index = panel_index;
 	par->info = info;
 	par->board = board;
 	par->write_reg = broadsheet_write_reg;
 	par->read_reg = broadsheet_read_reg;
 	init_waitqueue_head(&par->waitq);
 
+	mutex_init(&par->io_lock);
+
 	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
 
 	info->fbdefio = &broadsheetfb_defio;
@@ -496,13 +1155,20 @@
 	if (retval < 0)
 		goto err_free_irq;
 
+	broadsheet_identify(par);
+
 	broadsheet_init(par);
 
 	retval = register_framebuffer(info);
 	if (retval < 0)
 		goto err_free_irq;
+
 	platform_set_drvdata(dev, info);
 
+	retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
+	if (retval < 0)
+		goto err_unreg_fb;
+
 	printk(KERN_INFO
 	       "fb%d: Broadsheet frame buffer, using %dK of video memory\n",
 	       info->node, videomemorysize >> 10);
@@ -510,6 +1176,8 @@
 
 	return 0;
 
+err_unreg_fb:
+	unregister_framebuffer(info);
 err_free_irq:
 	board->cleanup(par);
 err_cmap:
@@ -530,6 +1198,8 @@
 
 	if (info) {
 		struct broadsheetfb_par *par = info->par;
+
+		device_remove_file(info->dev, &dev_attr_loadstore_waveform);
 		unregister_framebuffer(info);
 		fb_deferred_io_cleanup(info);
 		par->board->cleanup(par);
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
index 108b89e..5eb61b5 100644
--- a/drivers/video/cobalt_lcdfb.c
+++ b/drivers/video/cobalt_lcdfb.c
@@ -287,7 +287,7 @@
 	.fb_cursor	= cobalt_lcdfb_cursor,
 };
 
-static int __init cobalt_lcdfb_probe(struct platform_device *dev)
+static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
 	struct resource *res;
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index fc7d9bb..8e8f18d 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -37,6 +37,7 @@
 config VGACON_SOFT_SCROLLBACK_SIZE
        int "Scrollback Buffer Size (in KB)"
        depends on VGACON_SOFT_SCROLLBACK
+       range 1 1024
        default "64"
        help
          Enter the amount of System RAM to allocate for the scrollback
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 3681c6a..b0a3fa0 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -3025,6 +3025,20 @@
 	return 0;
 }
 
+static void fbcon_remap_all(int idx)
+{
+	int i;
+	for (i = first_fb_vc; i <= last_fb_vc; i++)
+		set_con2fb_map(i, idx, 0);
+
+	if (con_is_bound(&fb_con)) {
+		printk(KERN_INFO "fbcon: Remapping primary device, "
+		       "fb%i, to tty %i-%i\n", idx,
+		       first_fb_vc + 1, last_fb_vc + 1);
+		info_idx = idx;
+	}
+}
+
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
 static void fbcon_select_primary(struct fb_info *info)
 {
@@ -3225,6 +3239,10 @@
 		caps = event->data;
 		fbcon_get_requirement(info, caps);
 		break;
+	case FB_EVENT_REMAP_ALL_CONSOLE:
+		idx = info->node;
+		fbcon_remap_all(idx);
+		break;
 	}
 done:
 	return ret;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index cc4bbbe..182dd6f 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -112,7 +112,7 @@
 static int 		vga_scan_lines		__read_mostly;
 static unsigned int 	vga_rolled_over;
 
-int vgacon_text_mode_force = 0;
+static int vgacon_text_mode_force;
 
 bool vgacon_text_force(void)
 {
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index d25df51..581d2db 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -210,7 +210,7 @@
 	return 0;
 }
 
-static int __init efifb_probe(struct platform_device *dev)
+static int __devinit efifb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
 	int err;
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index 2735b79..6d755bb 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -602,7 +602,7 @@
 	return 0;
 }
 
-int __init epson1355fb_probe(struct platform_device *dev)
+int __devinit epson1355fb_probe(struct platform_device *dev)
 {
 	struct epson1355_par *default_par;
 	struct fb_info *info;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 99bbd28..a15b44e 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1513,7 +1513,6 @@
 				       fb_info->fix.id,
 				       registered_fb[i]->fix.id);
 				unregister_framebuffer(registered_fb[i]);
-				break;
 			}
 		}
 	}
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 695fa01..5643a35 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -1128,7 +1128,7 @@
 	return 0;
 }
 
-static int __init gbefb_probe(struct platform_device *p_dev)
+static int __devinit gbefb_probe(struct platform_device *p_dev)
 {
 	int i, ret = 0;
 	struct fb_info *info;
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index 0129c04..db9b785 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -551,7 +551,7 @@
 	 *  Initialization
 	 */
 
-static int __init hgafb_probe(struct platform_device *pdev)
+static int __devinit hgafb_probe(struct platform_device *pdev)
 {
 	struct fb_info *info;
 
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 73c83a8..bf78779 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -325,7 +325,7 @@
 	.fb_imageblit	= cfb_imageblit,
 };
 
-static int __init hitfb_probe(struct platform_device *dev)
+static int __devinit hitfb_probe(struct platform_device *dev)
 {
 	unsigned short lcdclor, ldr3, ldvndr;
 	struct fb_info *info;
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
index fabb0c5..8280a58 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfb.c
@@ -31,15 +31,6 @@
 #define CARMINE_MEM_SIZE	0x8000000
 #define DRV_NAME		"mb862xxfb"
 
-#if defined(CONFIG_LWMON5)
-static struct mb862xx_gc_mode lwmon5_gc_mode = {
-	/* Mode for Sharp LQ104V1DG61 TFT LCD Panel */
-	{ "640x480", 60, 640, 480, 40000, 48, 16, 32, 11, 96, 2, 0, 0, 0 },
-	/* 16 bits/pixel, 32MB, 100MHz, SDRAM memory mode value */
-	16, 0x2000000, GC_CCF_COT_100, 0x414fb7f2
-};
-#endif
-
 #if defined(CONFIG_SOCRATES)
 static struct mb862xx_gc_mode socrates_gc_mode = {
 	/* Mode for Prime View PM070WL4 TFT LCD Panel */
@@ -600,10 +591,6 @@
 		goto irqdisp;
 	}
 
-#if defined(CONFIG_LWMON5)
-	par->gc_mode = &lwmon5_gc_mode;
-#endif
-
 #if defined(CONFIG_SOCRATES)
 	par->gc_mode = &socrates_gc_mode;
 #endif
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index 01f77bc..afea9ab 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -693,7 +693,7 @@
 	unsigned long tmp;
 	int i;
 
-	/* FIXME: use platfrom specific parameters */
+	/* FIXME: use platform specific parameters */
 	/* setup SDRAM controller */
 	write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS |
 		LMCFG_LMA_TS),
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 0129f1b..b895aae 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -893,7 +893,7 @@
 }
 
 /**
- * fb_add_videomode: adds videomode entry to modelist
+ * fb_add_videomode - adds videomode entry to modelist
  * @mode: videomode to add
  * @head: struct list_head of modelist
  *
@@ -928,7 +928,7 @@
 }
 
 /**
- * fb_delete_videomode: removed videomode entry from modelist
+ * fb_delete_videomode - removed videomode entry from modelist
  * @mode: videomode to remove
  * @head: struct list_head of modelist
  *
@@ -953,7 +953,7 @@
 }
 
 /**
- * fb_destroy_modelist: destroy modelist
+ * fb_destroy_modelist - destroy modelist
  * @head: struct list_head of modelist
  */
 void fb_destroy_modelist(struct list_head *head)
@@ -968,7 +968,7 @@
 EXPORT_SYMBOL_GPL(fb_destroy_modelist);
 
 /**
- * fb_videomode_to_modelist: convert mode array to mode list
+ * fb_videomode_to_modelist - convert mode array to mode list
  * @modedb: array of struct fb_videomode
  * @num: number of entries in array
  * @head: struct list_head of modelist
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
new file mode 100644
index 0000000..6bf0d46
--- /dev/null
+++ b/drivers/video/nuc900fb.c
@@ -0,0 +1,779 @@
+/*
+ *
+ * Copyright (c) 2009 Nuvoton technology corporation
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *  Description:
+ *    Nuvoton LCD Controller Driver
+ *  Author:
+ *    Wang Qiang (rurality.linux@gmail.com) 2009/12/11
+ */
+#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/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-ldm.h>
+#include <mach/fb.h>
+#include <mach/clkdev.h>
+
+#include "nuc900fb.h"
+
+
+/*
+ *  Initialize the nuc900 video (dual) buffer address
+ */
+static void nuc900fb_set_lcdaddr(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	void __iomem *regs = fbi->io;
+	unsigned long vbaddr1, vbaddr2;
+
+	vbaddr1  = info->fix.smem_start;
+	vbaddr2  = info->fix.smem_start;
+	vbaddr2 += info->fix.line_length * info->var.yres;
+
+	/* set frambuffer start phy addr*/
+	writel(vbaddr1, regs + REG_LCM_VA_BADDR0);
+	writel(vbaddr2, regs + REG_LCM_VA_BADDR1);
+
+	writel(fbi->regs.lcd_va_fbctrl, regs + REG_LCM_VA_FBCTRL);
+	writel(fbi->regs.lcd_va_scale, regs + REG_LCM_VA_SCALE);
+}
+
+/*
+ *	calculate divider for lcd div
+ */
+static unsigned int nuc900fb_calc_pixclk(struct nuc900fb_info *fbi,
+					 unsigned long pixclk)
+{
+	unsigned long clk = fbi->clk_rate;
+	unsigned long long div;
+
+	/* pixclk is in picseconds. our clock is in Hz*/
+	/* div = (clk * pixclk)/10^12 */
+	div = (unsigned long long)clk * pixclk;
+	div >>= 12;
+	do_div(div, 625 * 625UL * 625);
+
+	dev_dbg(fbi->dev, "pixclk %ld, divisor is %lld\n", pixclk, div);
+
+	return div;
+}
+
+/*
+ *	Check the video params of 'var'.
+ */
+static int nuc900fb_check_var(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data;
+	struct nuc900fb_display *display = NULL;
+	struct nuc900fb_display *default_display = mach_info->displays +
+						   mach_info->default_display;
+	int i;
+
+	dev_dbg(fbi->dev, "check_var(var=%p, info=%p)\n", var, info);
+
+	/* validate x/y resolution */
+	/* choose default mode if possible */
+	if (var->xres == default_display->xres &&
+	    var->yres == default_display->yres &&
+	    var->bits_per_pixel == default_display->bpp)
+		display = default_display;
+	else
+		for (i = 0; i < mach_info->num_displays; i++)
+			if (var->xres == mach_info->displays[i].xres &&
+			    var->yres == mach_info->displays[i].yres &&
+			    var->bits_per_pixel == mach_info->displays[i].bpp) {
+				display = mach_info->displays + i;
+				break;
+			}
+
+	if (display == NULL) {
+		printk(KERN_ERR "wrong resolution or depth %dx%d at %d bit per pixel\n",
+			var->xres, var->yres, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	/* it should be the same size as the display */
+	var->xres_virtual	= display->xres;
+	var->yres_virtual	= display->yres;
+	var->height		= display->height;
+	var->width		= display->width;
+
+	/* copy lcd settings */
+	var->pixclock		= display->pixclock;
+	var->left_margin	= display->left_margin;
+	var->right_margin	= display->right_margin;
+	var->upper_margin	= display->upper_margin;
+	var->lower_margin	= display->lower_margin;
+	var->vsync_len		= display->vsync_len;
+	var->hsync_len		= display->hsync_len;
+
+	var->transp.offset	= 0;
+	var->transp.length	= 0;
+
+	fbi->regs.lcd_dccs = display->dccs;
+	fbi->regs.lcd_device_ctrl = display->devctl;
+	fbi->regs.lcd_va_fbctrl = display->fbctrl;
+	fbi->regs.lcd_va_scale = display->scale;
+
+	/* set R/G/B possions */
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+	default:
+		var->red.offset 	= 0;
+		var->red.length 	= var->bits_per_pixel;
+		var->green 		= var->red;
+		var->blue		= var->red;
+		break;
+	case 12:
+		var->red.length		= 4;
+		var->green.length	= 4;
+		var->blue.length	= 4;
+		var->red.offset		= 8;
+		var->green.offset	= 4;
+		var->blue.offset	= 0;
+		break;
+	case 16:
+		var->red.length		= 5;
+		var->green.length	= 6;
+		var->blue.length	= 5;
+		var->red.offset		= 11;
+		var->green.offset	= 5;
+		var->blue.offset	= 0;
+		break;
+	case 18:
+		var->red.length		= 6;
+		var->green.length	= 6;
+		var->blue.length	= 6;
+		var->red.offset		= 12;
+		var->green.offset	= 6;
+		var->blue.offset	= 0;
+		break;
+	case 32:
+		var->red.length		= 8;
+		var->green.length	= 8;
+		var->blue.length	= 8;
+		var->red.offset		= 16;
+		var->green.offset	= 8;
+		var->blue.offset	= 0;
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ *	Calculate lcd register values from var setting & save into hw
+ */
+static void nuc900fb_calculate_lcd_regs(const struct fb_info *info,
+					struct nuc900fb_hw *regs)
+{
+	const struct fb_var_screeninfo *var = &info->var;
+	int vtt = var->height + var->upper_margin + var->lower_margin;
+	int htt = var->width + var->left_margin + var->right_margin;
+	int hsync = var->width + var->right_margin;
+	int vsync = var->height + var->lower_margin;
+
+	regs->lcd_crtc_size = LCM_CRTC_SIZE_VTTVAL(vtt) |
+			      LCM_CRTC_SIZE_HTTVAL(htt);
+	regs->lcd_crtc_dend = LCM_CRTC_DEND_VDENDVAL(var->height) |
+			      LCM_CRTC_DEND_HDENDVAL(var->width);
+	regs->lcd_crtc_hr = LCM_CRTC_HR_EVAL(var->width + 5) |
+			    LCM_CRTC_HR_SVAL(var->width + 1);
+	regs->lcd_crtc_hsync = LCM_CRTC_HSYNC_EVAL(hsync + var->hsync_len) |
+			       LCM_CRTC_HSYNC_SVAL(hsync);
+	regs->lcd_crtc_vr = LCM_CRTC_VR_EVAL(vsync + var->vsync_len) |
+			    LCM_CRTC_VR_SVAL(vsync);
+
+}
+
+/*
+ *	Activate (set) the controller from the given framebuffer
+ *	information
+ */
+static void nuc900fb_activate_var(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	void __iomem *regs = fbi->io;
+	struct fb_var_screeninfo *var = &info->var;
+	int clkdiv;
+
+	clkdiv = nuc900fb_calc_pixclk(fbi, var->pixclock) - 1;
+	if (clkdiv < 0)
+		clkdiv = 0;
+
+	nuc900fb_calculate_lcd_regs(info, &fbi->regs);
+
+	/* set the new lcd registers*/
+
+	dev_dbg(fbi->dev, "new lcd register set:\n");
+	dev_dbg(fbi->dev, "dccs       = 0x%08x\n", fbi->regs.lcd_dccs);
+	dev_dbg(fbi->dev, "dev_ctl    = 0x%08x\n", fbi->regs.lcd_device_ctrl);
+	dev_dbg(fbi->dev, "crtc_size  = 0x%08x\n", fbi->regs.lcd_crtc_size);
+	dev_dbg(fbi->dev, "crtc_dend  = 0x%08x\n", fbi->regs.lcd_crtc_dend);
+	dev_dbg(fbi->dev, "crtc_hr    = 0x%08x\n", fbi->regs.lcd_crtc_hr);
+	dev_dbg(fbi->dev, "crtc_hsync = 0x%08x\n", fbi->regs.lcd_crtc_hsync);
+	dev_dbg(fbi->dev, "crtc_vr    = 0x%08x\n", fbi->regs.lcd_crtc_vr);
+
+	writel(fbi->regs.lcd_device_ctrl, regs + REG_LCM_DEV_CTRL);
+	writel(fbi->regs.lcd_crtc_size, regs + REG_LCM_CRTC_SIZE);
+	writel(fbi->regs.lcd_crtc_dend, regs + REG_LCM_CRTC_DEND);
+	writel(fbi->regs.lcd_crtc_hr, regs + REG_LCM_CRTC_HR);
+	writel(fbi->regs.lcd_crtc_hsync, regs + REG_LCM_CRTC_HSYNC);
+	writel(fbi->regs.lcd_crtc_vr, regs + REG_LCM_CRTC_VR);
+
+	/* set lcd address pointers */
+	nuc900fb_set_lcdaddr(info);
+
+	writel(fbi->regs.lcd_dccs, regs + REG_LCM_DCCS);
+}
+
+/*
+ *      Alters the hardware state.
+ *
+ */
+static int nuc900fb_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+
+	switch (var->bits_per_pixel) {
+	case 32:
+	case 24:
+	case 18:
+	case 16:
+	case 12:
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		break;
+	case 1:
+		info->fix.visual = FB_VISUAL_MONO01;
+		break;
+	default:
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	}
+
+	info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
+
+	/* activate this new configuration */
+	nuc900fb_activate_var(info);
+	return 0;
+}
+
+static inline unsigned int chan_to_field(unsigned int chan,
+					 struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int nuc900fb_setcolreg(unsigned regno,
+			       unsigned red, unsigned green, unsigned blue,
+			       unsigned transp, struct fb_info *info)
+{
+	unsigned int val;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/* true-colour, use pseuo-palette */
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue, &info->var.blue);
+			pal[regno] = val;
+		}
+		break;
+
+	default:
+		return 1;   /* unknown type */
+	}
+	return 0;
+}
+
+/**
+ *      nuc900fb_blank
+ *
+ */
+static int nuc900fb_blank(int blank_mode, struct fb_info *info)
+{
+
+	return 0;
+}
+
+static struct fb_ops nuc900fb_ops = {
+	.owner			= THIS_MODULE,
+	.fb_check_var		= nuc900fb_check_var,
+	.fb_set_par		= nuc900fb_set_par,
+	.fb_blank		= nuc900fb_blank,
+	.fb_setcolreg		= nuc900fb_setcolreg,
+	.fb_fillrect		= cfb_fillrect,
+	.fb_copyarea		= cfb_copyarea,
+	.fb_imageblit		= cfb_imageblit,
+};
+
+
+static inline void modify_gpio(void __iomem *reg,
+			       unsigned long set, unsigned long mask)
+{
+	unsigned long tmp;
+	tmp = readl(reg) & ~mask;
+	writel(tmp | set, reg);
+}
+
+/*
+ * Initialise LCD-related registers
+ */
+static int nuc900fb_init_registers(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data;
+	void __iomem *regs = fbi->io;
+
+	/*reset the display engine*/
+	writel(0, regs + REG_LCM_DCCS);
+	writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_ENG_RST,
+	       regs + REG_LCM_DCCS);
+	ndelay(100);
+	writel(readl(regs + REG_LCM_DCCS) & (~LCM_DCCS_ENG_RST),
+	       regs + REG_LCM_DCCS);
+	ndelay(100);
+
+	writel(0, regs + REG_LCM_DEV_CTRL);
+
+	/* config gpio output */
+	modify_gpio(W90X900_VA_GPIO + 0x54, mach_info->gpio_dir,
+		    mach_info->gpio_dir_mask);
+	modify_gpio(W90X900_VA_GPIO + 0x58, mach_info->gpio_data,
+		    mach_info->gpio_data_mask);
+
+	return 0;
+}
+
+
+/*
+ *    Alloc the SDRAM region of NUC900 for the frame buffer.
+ *    The buffer should be a non-cached, non-buffered, memory region
+ *    to allow palette and pixel writes without flushing the cache.
+ */
+static int __init nuc900fb_map_video_memory(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	dma_addr_t map_dma;
+	unsigned long map_size = PAGE_ALIGN(info->fix.smem_len);
+
+	dev_dbg(fbi->dev, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n",
+		fbi, map_size);
+
+	info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
+							&map_dma, GFP_KERNEL);
+
+	if (!info->screen_base)
+		return -ENOMEM;
+
+	memset(info->screen_base, 0x00, map_size);
+	info->fix.smem_start = map_dma;
+
+	return 0;
+}
+
+static inline void nuc900fb_unmap_video_memory(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+			      info->screen_base, info->fix.smem_start);
+}
+
+static irqreturn_t nuc900fb_irqhandler(int irq, void *dev_id)
+{
+	struct nuc900fb_info *fbi = dev_id;
+	void __iomem *regs = fbi->io;
+	void __iomem *irq_base = fbi->irq_base;
+	unsigned long lcdirq = readl(regs + REG_LCM_INT_CS);
+
+	if (lcdirq & LCM_INT_CS_DISP_F_STATUS) {
+		writel(readl(irq_base) | 1<<30, irq_base);
+
+		/* wait VA_EN low */
+		if ((readl(regs + REG_LCM_DCCS) &
+		    LCM_DCCS_SINGLE) == LCM_DCCS_SINGLE)
+			while ((readl(regs + REG_LCM_DCCS) &
+			       LCM_DCCS_VA_EN) == LCM_DCCS_VA_EN)
+				;
+		/* display_out-enable */
+		writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_DISP_OUT_EN,
+			regs + REG_LCM_DCCS);
+		/* va-enable*/
+		writel(readl(regs + REG_LCM_DCCS) | LCM_DCCS_VA_EN,
+			regs + REG_LCM_DCCS);
+	} else if (lcdirq & LCM_INT_CS_UNDERRUN_INT) {
+		writel(readl(irq_base) | LCM_INT_CS_UNDERRUN_INT, irq_base);
+	} else if (lcdirq & LCM_INT_CS_BUS_ERROR_INT) {
+		writel(readl(irq_base) | LCM_INT_CS_BUS_ERROR_INT, irq_base);
+	}
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_CPU_FREQ
+
+static int nuc900fb_cpufreq_transition(struct notifier_block *nb,
+				       unsigned long val, void *data)
+{
+	struct nuc900fb_info *info;
+	struct fb_info *fbinfo;
+	long delta_f;
+	info = container_of(nb, struct nuc900fb_info, freq_transition);
+	fbinfo = platform_get_drvdata(to_platform_device(info->dev));
+
+	delta_f = info->clk_rate - clk_get_rate(info->clk);
+
+	if ((val == CPUFREQ_POSTCHANGE && delta_f > 0) ||
+	   (val == CPUFREQ_PRECHANGE && delta_f < 0)) {
+		info->clk_rate = clk_get_rate(info->clk);
+		nuc900fb_activate_var(fbinfo);
+	}
+
+	return 0;
+}
+
+static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi)
+{
+	fbi->freq_transition.notifier_call = nuc900fb_cpufreq_transition;
+	return cpufreq_register_notifier(&fbi->freq_transition,
+				  CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *fbi)
+{
+	cpufreq_unregister_notifier(&fbi->freq_transition,
+				    CPUFREQ_TRANSITION_NOTIFIER);
+}
+#else
+static inline int nuc900fb_cpufreq_transition(struct notifier_block *nb,
+				       unsigned long val, void *data)
+{
+	return 0;
+}
+
+static inline int nuc900fb_cpufreq_register(struct nuc900fb_info *fbi)
+{
+	return 0;
+}
+
+static inline void nuc900fb_cpufreq_deregister(struct nuc900fb_info *info)
+{
+}
+#endif
+
+static char driver_name[] = "nuc900fb";
+
+static int __devinit nuc900fb_probe(struct platform_device *pdev)
+{
+	struct nuc900fb_info *fbi;
+	struct nuc900fb_display *display;
+	struct fb_info	   *fbinfo;
+	struct nuc900fb_mach_info *mach_info;
+	struct resource *res;
+	int ret;
+	int irq;
+	int i;
+	int size;
+
+	dev_dbg(&pdev->dev, "devinit\n");
+	mach_info = pdev->dev.platform_data;
+	if (mach_info == NULL) {
+		dev_err(&pdev->dev,
+			"no platform data for lcd, cannot attach\n");
+		return -EINVAL;
+	}
+
+	if (mach_info->default_display > mach_info->num_displays) {
+		dev_err(&pdev->dev,
+			"default display No. is %d but only %d displays \n",
+			mach_info->default_display, mach_info->num_displays);
+		return -EINVAL;
+	}
+
+
+	display = mach_info->displays + mach_info->default_display;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq for device\n");
+		return -ENOENT;
+	}
+
+	fbinfo = framebuffer_alloc(sizeof(struct nuc900fb_info), &pdev->dev);
+	if (!fbinfo)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, fbinfo);
+
+	fbi = fbinfo->par;
+	fbi->dev = &pdev->dev;
+
+#ifdef CONFIG_CPU_NUC950
+	fbi->drv_type = LCDDRV_NUC950;
+#endif
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	size = (res->end - res->start) + 1;
+	fbi->mem = request_mem_region(res->start, size, pdev->name);
+	if (fbi->mem == NULL) {
+		dev_err(&pdev->dev, "failed to alloc memory region\n");
+		ret = -ENOENT;
+		goto free_fb;
+	}
+
+	fbi->io = ioremap(res->start, size);
+	if (fbi->io == NULL) {
+		dev_err(&pdev->dev, "ioremap() of lcd registers failed\n");
+		ret = -ENXIO;
+		goto release_mem_region;
+	}
+
+	fbi->irq_base = fbi->io + REG_LCM_INT_CS;
+
+
+	/* Stop the LCD */
+	writel(0, fbi->io + REG_LCM_DCCS);
+
+	/* fill the fbinfo*/
+	strcpy(fbinfo->fix.id, driver_name);
+	fbinfo->fix.type		= FB_TYPE_PACKED_PIXELS;
+	fbinfo->fix.type_aux		= 0;
+	fbinfo->fix.xpanstep		= 0;
+	fbinfo->fix.ypanstep		= 0;
+	fbinfo->fix.ywrapstep		= 0;
+	fbinfo->fix.accel		= FB_ACCEL_NONE;
+	fbinfo->var.nonstd		= 0;
+	fbinfo->var.activate		= FB_ACTIVATE_NOW;
+	fbinfo->var.accel_flags		= 0;
+	fbinfo->var.vmode		= FB_VMODE_NONINTERLACED;
+	fbinfo->fbops			= &nuc900fb_ops;
+	fbinfo->flags			= FBINFO_FLAG_DEFAULT;
+	fbinfo->pseudo_palette		= &fbi->pseudo_pal;
+
+	ret = request_irq(irq, nuc900fb_irqhandler, IRQF_DISABLED,
+			  pdev->name, fbinfo);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n",
+			irq, ret);
+		ret = -EBUSY;
+		goto release_regs;
+	}
+
+	nuc900_driver_clksrc_div(&pdev->dev, "ext", 0x2);
+
+	fbi->clk = clk_get(&pdev->dev, NULL);
+	if (!fbi->clk || IS_ERR(fbi->clk)) {
+		printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n");
+		ret = -ENOENT;
+		goto release_irq;
+	}
+
+	clk_enable(fbi->clk);
+	dev_dbg(&pdev->dev, "got and enabled clock\n");
+
+	fbi->clk_rate = clk_get_rate(fbi->clk);
+
+	/* calutate the video buffer size */
+	for (i = 0; i < mach_info->num_displays; i++) {
+		unsigned long smem_len = mach_info->displays[i].xres;
+		smem_len *= mach_info->displays[i].yres;
+		smem_len *= mach_info->displays[i].bpp;
+		smem_len >>= 3;
+		if (fbinfo->fix.smem_len < smem_len)
+			fbinfo->fix.smem_len = smem_len;
+	}
+
+	/* Initialize Video Memory */
+	ret = nuc900fb_map_video_memory(fbinfo);
+	if (ret) {
+		printk(KERN_ERR "Failed to allocate video RAM: %x\n", ret);
+		goto release_clock;
+	}
+
+	dev_dbg(&pdev->dev, "got video memory\n");
+
+	fbinfo->var.xres = display->xres;
+	fbinfo->var.yres = display->yres;
+	fbinfo->var.bits_per_pixel = display->bpp;
+
+	nuc900fb_init_registers(fbinfo);
+
+	nuc900fb_check_var(&fbinfo->var, fbinfo);
+
+	ret = nuc900fb_cpufreq_register(fbi);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register cpufreq\n");
+		goto free_video_memory;
+	}
+
+	ret = register_framebuffer(fbinfo);
+	if (ret) {
+		printk(KERN_ERR "failed to register framebuffer device: %d\n",
+			ret);
+		goto free_cpufreq;
+	}
+
+	printk(KERN_INFO "fb%d: %s frame buffer device\n",
+		fbinfo->node, fbinfo->fix.id);
+
+	return 0;
+
+free_cpufreq:
+	nuc900fb_cpufreq_deregister(fbi);
+free_video_memory:
+	nuc900fb_unmap_video_memory(fbinfo);
+release_clock:
+	clk_disable(fbi->clk);
+	clk_put(fbi->clk);
+release_irq:
+	free_irq(irq, fbi);
+release_regs:
+	iounmap(fbi->io);
+release_mem_region:
+	release_mem_region((unsigned long)fbi->mem, size);
+free_fb:
+	framebuffer_release(fbinfo);
+	return ret;
+}
+
+/*
+ * shutdown the lcd controller
+ */
+static void nuc900fb_stop_lcd(struct fb_info *info)
+{
+	struct nuc900fb_info *fbi = info->par;
+	void __iomem *regs = fbi->io;
+
+	writel((~LCM_DCCS_DISP_INT_EN) | (~LCM_DCCS_VA_EN) | (~LCM_DCCS_OSD_EN),
+		regs + REG_LCM_DCCS);
+}
+
+/*
+ *  Cleanup
+ */
+static int nuc900fb_remove(struct platform_device *pdev)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct nuc900fb_info *fbi = fbinfo->par;
+	int irq;
+
+	nuc900fb_stop_lcd(fbinfo);
+	msleep(1);
+
+	nuc900fb_unmap_video_memory(fbinfo);
+
+	iounmap(fbi->io);
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, fbi);
+
+	release_resource(fbi->mem);
+	kfree(fbi->mem);
+
+	platform_set_drvdata(pdev, NULL);
+	framebuffer_release(fbinfo);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+/*
+ *	suspend and resume support for the lcd controller
+ */
+
+static int nuc900fb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
+	struct nuc900fb_info *info = fbinfo->par;
+
+	nuc900fb_stop_lcd();
+	msleep(1);
+	clk_disable(info->clk);
+	return 0;
+}
+
+static int nuc900fb_resume(struct platform_device *dev)
+{
+	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
+	struct nuc900fb_info *fbi = fbinfo->par;
+
+	printk(KERN_INFO "nuc900fb resume\n");
+
+	clk_enable(fbi->clk);
+	msleep(1);
+
+	nuc900fb_init_registers(fbinfo);
+	nuc900fb_activate_var(bfinfo);
+
+	return 0;
+}
+
+#else
+#define nuc900fb_suspend NULL
+#define nuc900fb_resume  NULL
+#endif
+
+static struct platform_driver nuc900fb_driver = {
+	.probe		= nuc900fb_probe,
+	.remove		= nuc900fb_remove,
+	.suspend	= nuc900fb_suspend,
+	.resume		= nuc900fb_resume,
+	.driver		= {
+		.name	= "nuc900-lcd",
+		.owner	= THIS_MODULE,
+	},
+};
+
+int __devinit nuc900fb_init(void)
+{
+	return platform_driver_register(&nuc900fb_driver);
+}
+
+static void __exit nuc900fb_cleanup(void)
+{
+	platform_driver_unregister(&nuc900fb_driver);
+}
+
+module_init(nuc900fb_init);
+module_exit(nuc900fb_cleanup);
+
+MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/nuc900fb.h b/drivers/video/nuc900fb.h
new file mode 100644
index 0000000..6c23aa3
--- /dev/null
+++ b/drivers/video/nuc900fb.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright (c) 2009 Nuvoton technology corporation
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *   Auther:
+ *        Wang Qiang(rurality.linux@gmail.com)  2009/12/16
+ */
+
+#ifndef __NUC900FB_H
+#define __NUC900FB_H
+
+#include <mach/map.h>
+#include <mach/fb.h>
+
+enum nuc900_lcddrv_type {
+	LCDDRV_NUC910,
+	LCDDRV_NUC930,
+	LCDDRV_NUC932,
+	LCDDRV_NUC950,
+	LCDDRV_NUC960,
+};
+
+
+#define PALETTE_BUFFER_SIZE	256
+#define PALETTE_BUFF_CLEAR 	(0x80000000) /* entry is clear/invalid */
+
+struct nuc900fb_info {
+	struct device		*dev;
+	struct clk		*clk;
+
+	struct resource		*mem;
+	void __iomem		*io;
+	void __iomem		*irq_base;
+	int 			drv_type;
+	struct nuc900fb_hw	regs;
+	unsigned long		clk_rate;
+
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	freq_transition;
+#endif
+
+	/* keep these registers in case we need to re-write palette */
+	u32			palette_buffer[PALETTE_BUFFER_SIZE];
+	u32			pseudo_pal[16];
+};
+
+int nuc900fb_init(void);
+
+#endif /* __NUC900FB_H */
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index a334839..9557f96 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -389,7 +389,7 @@
 /*
  * Configure the LCD DMA for a palette load operation and do the palette
  * downloading synchronously. We don't use the frame+palette load mode of
- * the controller, since the palette can always be downloaded seperately.
+ * the controller, since the palette can always be downloaded separately.
  */
 static void load_palette(void)
 {
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 913142d..9acef00 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -341,7 +341,7 @@
 	return manager_attr->store(manager, buf, size);
 }
 
-static struct sysfs_ops manager_sysfs_ops = {
+static const struct sysfs_ops manager_sysfs_ops = {
 	.show = manager_attr_show,
 	.store = manager_attr_store,
 };
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 0c5bea2..aed3f31 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -320,7 +320,7 @@
 	return overlay_attr->store(overlay, buf, size);
 }
 
-static struct sysfs_ops overlay_sysfs_ops = {
+static const struct sysfs_ops overlay_sysfs_ops = {
 	.show = overlay_attr_show,
 	.store = overlay_attr_store,
 };
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 36436ee..27f93aa 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -896,7 +896,7 @@
 	 * Pseudocolor:
 	 *    uses offset = 0 && length = DAC register width.
 	 *    var->{color}.offset is 0
-	 *    var->{color}.length contains widht of DAC
+	 *    var->{color}.length contains width of DAC
 	 *    cmap is not used
 	 *    DAC[X] is programmed to (red, green, blue)
 	 * Truecolor:
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 4beac1d..de40a62 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -85,7 +85,7 @@
 	.fb_imageblit	= cfb_imageblit,
 };
 
-static int __init q40fb_probe(struct platform_device *dev)
+static int __devinit q40fb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
 
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index 0deb0a8..7b63429 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -517,12 +517,12 @@
 		src = (sy * stride) + (bpp * sx);
 	}
 
-	/* set source adress */
+	/* set source address */
 	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START0, (src & 0xff));
 	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START1, (src >> 8) & 0x00ff);
 	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_SRC_START2, (src >> 16) & 0x00ff);
 
-	/* set destination adress */
+	/* set destination address */
 	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START0, (dst & 0xff));
 	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START1, (dst >> 8) & 0x00ff);
 	s1d13xxxfb_writereg(info->par, S1DREG_BBLT_DST_START2, (dst >> 16) & 0x00ff);
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index aac6612..2b094de 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -1004,12 +1004,12 @@
 	return ret;
 }
 
-static int __init s3c2410fb_probe(struct platform_device *pdev)
+static int __devinit s3c2410fb_probe(struct platform_device *pdev)
 {
 	return s3c24xxfb_probe(pdev, DRV_S3C2410);
 }
 
-static int __init s3c2412fb_probe(struct platform_device *pdev)
+static int __devinit s3c2412fb_probe(struct platform_device *pdev)
 {
 	return s3c24xxfb_probe(pdev, DRV_S3C2412);
 }
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index cdaa873..e8b76d6 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1435,7 +1435,7 @@
 	return fbi;
 }
 
-static int __init sa1100fb_probe(struct platform_device *pdev)
+static int __devinit sa1100fb_probe(struct platform_device *pdev)
 {
 	struct sa1100fb_info *fbi;
 	int ret, irq;
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index f860122..7a3a5e2 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -745,7 +745,7 @@
 /*
  *  Initialisation
  */
-static int __init sgivwfb_probe(struct platform_device *dev)
+static int __devinit sgivwfb_probe(struct platform_device *dev)
 {
 	struct sgivw_par *par;
 	struct fb_info *info;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 8d7653e..bbd1dbf 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -943,7 +943,7 @@
 
 static int sh_mobile_lcdc_remove(struct platform_device *pdev);
 
-static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
+static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 {
 	struct fb_info *info;
 	struct sh_mobile_lcdc_priv *priv;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 9d2b6bc..a531a0f 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1891,9 +1891,6 @@
 	.fb_fillrect	= fbcon_sis_fillrect,
 	.fb_copyarea	= fbcon_sis_copyarea,
 	.fb_imageblit	= cfb_imageblit,
-#ifdef CONFIG_FB_SOFT_CURSOR
-	.fb_cursor	= soft_cursor,
-#endif
 	.fb_sync	= fbcon_sis_sync,
 #ifdef SIS_NEW_CONFIG_COMPAT
 	.fb_compat_ioctl= sisfb_ioctl,
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 35370d0..b7dc180 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -411,7 +411,7 @@
 	struct sm501fb_par  *par = info->par;
 	struct sm501fb_info *fbi = par->info;
 	unsigned long pixclock;      /* pixelclock in Hz */
-	unsigned long sm501pixclock; /* pixelclock the 501 can achive in Hz */
+	unsigned long sm501pixclock; /* pixelclock the 501 can achieve in Hz */
 	unsigned int mem_type;
 	unsigned int clock_type;
 	unsigned int head_addr;
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 609d0a5..79840f1 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -1102,7 +1102,7 @@
  * detect dac type
  * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset,
  * dram refresh disabled, FbiInit remaped.
- * TODO: mmh.. maybe i shoud put the "prerequisite" in the func ...
+ * TODO: mmh.. maybe i should put the "prerequisite" in the func ...
  */
 
 
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index bd37ee1..ef4128c 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -226,7 +226,7 @@
 	return 0;
 }
 
-static int __init vesafb_probe(struct platform_device *dev)
+static int __devinit vesafb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
 	int i, err;
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 050d432..b8ab995 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -479,7 +479,7 @@
      *  Initialisation
      */
 
-static int __init vfb_probe(struct platform_device *dev)
+static int __devinit vfb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
 	int retval = -ENOMEM;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 5b29389..76d8dae 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1293,7 +1293,7 @@
 }
 #endif
 
-static int __init vga16fb_probe(struct platform_device *dev)
+static int __devinit vga16fb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
 	struct vga16fb_par *par;
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
index e533b4b..eeed238 100644
--- a/drivers/video/via/Makefile
+++ b/drivers/video/via/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_FB_VIA) += viafb.o
 
-viafb-y	:=viafbdev.o hw.o iface.o  via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o
+viafb-y	:=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
index 474f428..8c06bd3 100644
--- a/drivers/video/via/chip.h
+++ b/drivers/video/via/chip.h
@@ -107,7 +107,6 @@
 struct tmds_chip_information {
 	int tmds_chip_name;
 	int tmds_chip_slave_addr;
-	int dvi_panel_id;
 	int data_mode;
 	int output_interface;
 	int i2c_port;
@@ -142,14 +141,9 @@
 	int iga_path;
 	int h_active;
 	int v_active;
-	int bpp;
-	int refresh_rate;
-	int get_dvi_size_method;
 	int max_pixel_clock;
-	int dvi_panel_size;
-	int dvi_panel_hres;
-	int dvi_panel_vres;
-	int native_size;
+	int max_hres;
+	int max_vres;
 };
 
 struct lvds_setting_information {
@@ -160,7 +154,6 @@
 	int refresh_rate;
 	int get_lcd_size_method;
 	int lcd_panel_id;
-	int lcd_panel_size;
 	int lcd_panel_hres;
 	int lcd_panel_vres;
 	int display_method;
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index 67b3693..abe59b8 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -23,11 +23,10 @@
 static void tmds_register_write(int index, u8 data);
 static int tmds_register_read(int index);
 static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
-static int check_reduce_blanking_mode(int mode_index,
-	int refresh_rate);
-static int dvi_get_panel_size_from_DDCv1(void);
-static int dvi_get_panel_size_from_DDCv2(void);
-static unsigned char dvi_get_panel_info(void);
+static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information
+	*tmds_chip, struct tmds_setting_information *tmds_setting);
+static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information
+	*tmds_chip, struct tmds_setting_information *tmds_setting);
 static int viafb_dvi_query_EDID(void);
 
 static int check_tmds_chip(int device_id_subaddr, int device_id)
@@ -38,23 +37,24 @@
 		return FAIL;
 }
 
-void viafb_init_dvi_size(void)
+void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
+	struct tmds_setting_information *tmds_setting)
 {
 	DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
-	DEBUG_MSG(KERN_INFO
-		"viaparinfo->tmds_setting_info->get_dvi_size_method %d\n",
-		  viaparinfo->tmds_setting_info->get_dvi_size_method);
 
-	switch (viaparinfo->tmds_setting_info->get_dvi_size_method) {
-	case GET_DVI_SIZE_BY_SYSTEM_BIOS:
+	viafb_dvi_sense();
+	switch (viafb_dvi_query_EDID()) {
+	case 1:
+		dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting);
 		break;
-	case GET_DVI_SZIE_BY_HW_STRAPPING:
+	case 2:
+		dvi_get_panel_size_from_DDCv2(tmds_chip, tmds_setting);
 		break;
-	case GET_DVI_SIZE_BY_VGA_BIOS:
 	default:
-		dvi_get_panel_info();
+		printk(KERN_WARNING "viafb_init_dvi_size: DVI panel size undetected!\n");
 		break;
 	}
+
 	return;
 }
 
@@ -189,42 +189,14 @@
 	return 0;
 }
 
-static int check_reduce_blanking_mode(int mode_index,
-	int refresh_rate)
-{
-	if (refresh_rate != 60)
-		return false;
-
-	switch (mode_index) {
-		/* Following modes have reduce blanking mode. */
-	case VIA_RES_1360X768:
-	case VIA_RES_1400X1050:
-	case VIA_RES_1440X900:
-	case VIA_RES_1600X900:
-	case VIA_RES_1680X1050:
-	case VIA_RES_1920X1080:
-	case VIA_RES_1920X1200:
-		break;
-
-	default:
-		DEBUG_MSG(KERN_INFO
-			  "This dvi mode %d have no reduce blanking mode!\n",
-			  mode_index);
-		return false;
-	}
-
-	return true;
-}
-
 /* DVI Set Mode */
-void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga)
+void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp,
+	int set_iga)
 {
-	struct VideoModeTable *videoMode = NULL;
+	struct VideoModeTable *rb_mode;
 	struct crt_mode_table *pDviTiming;
 	unsigned long desirePixelClock, maxPixelClock;
-	int status = 0;
-	videoMode = viafb_get_modetbl_pointer(video_index);
-	pDviTiming = videoMode->crtc;
+	pDviTiming = mode->crtc;
 	desirePixelClock = pDviTiming->clk / 1000000;
 	maxPixelClock = (unsigned long)viaparinfo->
 		tmds_setting_info->max_pixel_clock;
@@ -232,20 +204,14 @@
 	DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
 
 	if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
-		/*Check if reduce-blanking mode is exist */
-		status =
-		    check_reduce_blanking_mode(video_index,
-					       pDviTiming->refresh_rate);
-		if (status) {
-			video_index += 100;	/*Use reduce-blanking mode */
-			videoMode = viafb_get_modetbl_pointer(video_index);
-			pDviTiming = videoMode->crtc;
-			DEBUG_MSG(KERN_INFO
-				  "DVI use reduce blanking mode %d!!\n",
-				  video_index);
+		rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr,
+			mode->crtc[0].crtc.ver_addr);
+		if (rb_mode) {
+			mode = rb_mode;
+			pDviTiming = rb_mode->crtc;
 		}
 	}
-	viafb_fill_crtc_timing(pDviTiming, video_index, mode_bpp / 8, set_iga);
+	viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga);
 	viafb_set_output_path(DEVICE_DVI, set_iga,
 			viaparinfo->chip_info->tmds_chip_info.output_interface);
 }
@@ -350,25 +316,18 @@
 		return false;
 }
 
-/*
- *
- * int dvi_get_panel_size_from_DDCv1(void)
- *
- *     - Get Panel Size Using EDID1 Table
- *
- * Return Type:    int
- *
- */
-static int dvi_get_panel_size_from_DDCv1(void)
+/* Get Panel Size Using EDID1 Table */
+static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information
+	*tmds_chip, struct tmds_setting_information *tmds_setting)
 {
-	int i, max_h = 0, max_v = 0, tmp, restore;
+	int i, max_h = 0, tmp, restore;
 	unsigned char rData;
 	unsigned char EDID_DATA[18];
 
 	DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
 
-	restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
-	viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
+	restore = tmds_chip->tmds_chip_slave_addr;
+	tmds_chip->tmds_chip_slave_addr = 0xA0;
 
 	rData = tmds_register_read(0x23);
 	if (rData & 0x3C)
@@ -414,8 +373,8 @@
 				/* The first two byte must be zero. */
 				if (EDID_DATA[3] == 0xFD) {
 					/* To get max pixel clock. */
-					viaparinfo->tmds_setting_info->
-					max_pixel_clock = EDID_DATA[9] * 10;
+					tmds_setting->max_pixel_clock =
+						EDID_DATA[9] * 10;
 				}
 			}
 			break;
@@ -425,154 +384,88 @@
 		}
 	}
 
+	tmds_setting->max_hres = max_h;
 	switch (max_h) {
 	case 640:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_640X480;
+		tmds_setting->max_vres = 480;
 		break;
 	case 800:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_800X600;
+		tmds_setting->max_vres = 600;
 		break;
 	case 1024:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1024X768;
+		tmds_setting->max_vres = 768;
 		break;
 	case 1280:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1280X1024;
+		tmds_setting->max_vres = 1024;
 		break;
 	case 1400:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1400X1050;
+		tmds_setting->max_vres = 1050;
 		break;
 	case 1440:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1440X1050;
+		tmds_setting->max_vres = 1050;
 		break;
 	case 1600:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1600X1200;
+		tmds_setting->max_vres = 1200;
 		break;
 	case 1920:
-		if (max_v == 1200) {
-			viaparinfo->tmds_setting_info->dvi_panel_size =
-				VIA_RES_1920X1200;
-		} else {
-			viaparinfo->tmds_setting_info->dvi_panel_size =
-				VIA_RES_1920X1080;
-		}
-
+		tmds_setting->max_vres = 1080;
 		break;
 	default:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1024X768;
-		DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d !\
-					 set default panel size.\n", max_h);
+		DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d ! "
+					 "set default panel size.\n", max_h);
 		break;
 	}
 
 	DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
-		  viaparinfo->tmds_setting_info->max_pixel_clock);
-	viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
-	return viaparinfo->tmds_setting_info->dvi_panel_size;
+		tmds_setting->max_pixel_clock);
+	tmds_chip->tmds_chip_slave_addr = restore;
 }
 
-/*
- *
- * int dvi_get_panel_size_from_DDCv2(void)
- *
- *     - Get Panel Size Using EDID2 Table
- *
- * Return Type:    int
- *
- */
-static int dvi_get_panel_size_from_DDCv2(void)
+/* Get Panel Size Using EDID2 Table */
+static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information
+	*tmds_chip, struct tmds_setting_information *tmds_setting)
 {
-	int HSize = 0, restore;
+	int restore;
 	unsigned char R_Buffer[2];
 
 	DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n");
 
-	restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
-	viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA2;
+	restore = tmds_chip->tmds_chip_slave_addr;
+	tmds_chip->tmds_chip_slave_addr = 0xA2;
 
 	/* Horizontal: 0x76, 0x77 */
 	tmds_register_read_bytes(0x76, R_Buffer, 2);
-	HSize = R_Buffer[0];
-	HSize += R_Buffer[1] << 8;
+	tmds_setting->max_hres = R_Buffer[0] + (R_Buffer[1] << 8);
 
-	switch (HSize) {
+	switch (tmds_setting->max_hres) {
 	case 640:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_640X480;
+		tmds_setting->max_vres = 480;
 		break;
 	case 800:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_800X600;
+		tmds_setting->max_vres = 600;
 		break;
 	case 1024:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1024X768;
+		tmds_setting->max_vres = 768;
 		break;
 	case 1280:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1280X1024;
+		tmds_setting->max_vres = 1024;
 		break;
 	case 1400:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1400X1050;
+		tmds_setting->max_vres = 1050;
 		break;
 	case 1440:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1440X1050;
+		tmds_setting->max_vres = 1050;
 		break;
 	case 1600:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1600X1200;
+		tmds_setting->max_vres = 1200;
 		break;
 	default:
-		viaparinfo->tmds_setting_info->dvi_panel_size =
-			VIA_RES_1024X768;
-		DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d!\
-					set default panel size.\n", HSize);
+		DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d! "
+			"set default panel size.\n", tmds_setting->max_hres);
 		break;
 	}
 
-	viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
-	return viaparinfo->tmds_setting_info->dvi_panel_size;
-}
-
-/*
- *
- * unsigned char dvi_get_panel_info(void)
- *
- *     - Get Panel Size
- *
- * Return Type:    unsigned char
- */
-static unsigned char dvi_get_panel_info(void)
-{
-	unsigned char dvipanelsize;
-	DEBUG_MSG(KERN_INFO "dvi_get_panel_info! \n");
-
-	viafb_dvi_sense();
-	switch (viafb_dvi_query_EDID()) {
-	case 1:
-		dvi_get_panel_size_from_DDCv1();
-		break;
-	case 2:
-		dvi_get_panel_size_from_DDCv2();
-		break;
-	default:
-		break;
-	}
-
-	DEBUG_MSG(KERN_INFO "dvi panel size is %2d \n",
-		  viaparinfo->tmds_setting_info->dvi_panel_size);
-	dvipanelsize = (unsigned char)(viaparinfo->
-		tmds_setting_info->dvi_panel_size);
-	return dvipanelsize;
+	tmds_chip->tmds_chip_slave_addr = restore;
 }
 
 /* If Disable DVI, turn off pad */
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
index e1ec37f..0dffcfd 100644
--- a/drivers/video/via/dvi.h
+++ b/drivers/video/via/dvi.h
@@ -53,12 +53,13 @@
 #define     DEV_CONNECT_DVI     0x01
 #define     DEV_CONNECT_HDMI    0x02
 
-struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index);
 int viafb_dvi_sense(void);
 void viafb_dvi_disable(void);
 void viafb_dvi_enable(void);
 int viafb_tmds_trasmitter_identify(void);
-void viafb_init_dvi_size(void);
-void viafb_dvi_set_mode(int video_index, int mode_bpp, int set_iga);
+void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
+	struct tmds_setting_information *tmds_setting);
+void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp,
+	int set_iga);
 
 #endif /* __DVI_H__ */
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c
index b675cdb..1ee511b 100644
--- a/drivers/video/via/global.c
+++ b/drivers/video/via/global.c
@@ -23,15 +23,12 @@
 int viafb_device_lcd_dualedge = STATE_OFF;
 int viafb_bus_width = 12;
 int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI;
-int viafb_memsize;
 int viafb_DeviceStatus = CRT_Device;
 int viafb_hotplug;
 int viafb_refresh = 60;
 int viafb_refresh1 = 60;
 int viafb_lcd_dsp_method = LCD_EXPANDSION;
 int viafb_lcd_mode = LCD_OPENLDI;
-int viafb_bpp = 32;
-int viafb_bpp1 = 32;
 int viafb_CRT_ON = 1;
 int viafb_DVI_ON;
 int viafb_LCD_ON ;
@@ -42,8 +39,6 @@
 int viafb_hotplug_Yres = 480;
 int viafb_hotplug_bpp = 32;
 int viafb_hotplug_refresh = 60;
-unsigned int viafb_second_offset;
-int viafb_second_size;
 int viafb_primary_dev = None_Device;
 unsigned int viafb_second_xres = 640;
 unsigned int viafb_second_yres = 480;
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h
index d69d0ca..8d95d5f 100644
--- a/drivers/video/via/global.h
+++ b/drivers/video/via/global.h
@@ -35,7 +35,6 @@
 
 #include "debug.h"
 
-#include "iface.h"
 #include "viafbdev.h"
 #include "chip.h"
 #include "accel.h"
@@ -68,8 +67,6 @@
 extern int viafb_refresh1;
 extern int viafb_lcd_dsp_method;
 extern int viafb_lcd_mode;
-extern int viafb_bpp;
-extern int viafb_bpp1;
 
 extern int viafb_CRT_ON;
 extern int viafb_hotplug_Xres;
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 3e083ff..f2583b1 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -524,7 +524,6 @@
 static void dvi_patch_skew_dvp_low(void);
 static void set_dvi_output_path(int set_iga, int output_interface);
 static void set_lcd_output_path(int set_iga, int output_interface);
-static int search_mode_setting(int ModeInfoIndex);
 static void load_fix_bit_crtc_reg(void);
 static void init_gfx_chip_info(struct pci_dev *pdev,
 				const struct pci_device_id *pdi);
@@ -686,6 +685,84 @@
 	viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80);
 }
 
+void viafb_set_primary_color_depth(u8 depth)
+{
+	u8 value;
+
+	DEBUG_MSG(KERN_DEBUG "viafb_set_primary_color_depth(%d)\n", depth);
+	switch (depth) {
+	case 8:
+		value = 0x00;
+		break;
+	case 15:
+		value = 0x04;
+		break;
+	case 16:
+		value = 0x14;
+		break;
+	case 24:
+		value = 0x0C;
+		break;
+	case 30:
+		value = 0x08;
+		break;
+	default:
+		printk(KERN_WARNING "viafb_set_primary_color_depth: "
+			"Unsupported depth: %d\n", depth);
+		return;
+	}
+
+	viafb_write_reg_mask(0x15, VIASR, value, 0x1C);
+}
+
+void viafb_set_secondary_color_depth(u8 depth)
+{
+	u8 value;
+
+	DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_color_depth(%d)\n", depth);
+	switch (depth) {
+	case 8:
+		value = 0x00;
+		break;
+	case 16:
+		value = 0x40;
+		break;
+	case 24:
+		value = 0xC0;
+		break;
+	case 30:
+		value = 0x80;
+		break;
+	default:
+		printk(KERN_WARNING "viafb_set_secondary_color_depth: "
+			"Unsupported depth: %d\n", depth);
+		return;
+	}
+
+	viafb_write_reg_mask(0x67, VIACR, value, 0xC0);
+}
+
+static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
+{
+	outb(0xFF, 0x3C6); /* bit mask of palette */
+	outb(index, 0x3C8);
+	outb(red, 0x3C9);
+	outb(green, 0x3C9);
+	outb(blue, 0x3C9);
+}
+
+void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue)
+{
+	viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01);
+	set_color_register(index, red, green, blue);
+}
+
+void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue)
+{
+	viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01);
+	set_color_register(index, red, green, blue);
+}
+
 void viafb_set_output_path(int device, int set_iga, int output_interface)
 {
 	switch (device) {
@@ -710,11 +787,8 @@
 		viafb_write_reg_mask(SR16, VIASR, 0x00, BIT6);
 		break;
 	case IGA2:
-	case IGA1_IGA2:
 		viafb_write_reg_mask(CR6A, VIACR, 0xC0, BIT6 + BIT7);
 		viafb_write_reg_mask(SR16, VIASR, 0x40, BIT6);
-		if (set_iga == IGA1_IGA2)
-			viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
 		break;
 	}
 }
@@ -904,13 +978,6 @@
 
 		enable_second_display_channel();
 		break;
-
-	case IGA1_IGA2:
-		viafb_write_reg_mask(CR6B, VIACR, 0x08, BIT3);
-		viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
-
-		disable_second_display_channel();
-		break;
 	}
 
 	switch (output_interface) {
@@ -987,49 +1054,6 @@
 	}
 }
 
-/* Search Mode Index */
-static int search_mode_setting(int ModeInfoIndex)
-{
-	int i = 0;
-
-	while ((i < NUM_TOTAL_MODETABLE) &&
-			(ModeInfoIndex != CLE266Modes[i].ModeIndex))
-		i++;
-	if (i >= NUM_TOTAL_MODETABLE)
-		i = 0;
-	return i;
-
-}
-
-struct VideoModeTable *viafb_get_modetbl_pointer(int Index)
-{
-	struct VideoModeTable *TmpTbl = NULL;
-	TmpTbl = &CLE266Modes[search_mode_setting(Index)];
-	return TmpTbl;
-}
-
-struct VideoModeTable *viafb_get_cea_mode_tbl_pointer(int Index)
-{
-	struct VideoModeTable *TmpTbl = NULL;
-	int i = 0;
-	while ((i < NUM_TOTAL_CEA_MODES) &&
-			(Index != CEA_HDMI_Modes[i].ModeIndex))
-		i++;
-	if ((i < NUM_TOTAL_CEA_MODES))
-		TmpTbl = &CEA_HDMI_Modes[i];
-	 else {
-		/*Still use general timing if don't find CEA timing */
-		i = 0;
-		while ((i < NUM_TOTAL_MODETABLE) &&
-				(Index != CLE266Modes[i].ModeIndex))
-		       i++;
-		if (i >= NUM_TOTAL_MODETABLE)
-			i = 0;
-		TmpTbl = &CLE266Modes[i];
-	}
-	return TmpTbl;
-}
-
 static void load_fix_bit_crtc_reg(void)
 {
 	/* always set to 1 */
@@ -1121,15 +1145,13 @@
 	struct io_register *reg = NULL;
 
 	switch (set_iga) {
-	case IGA1_IGA2:
 	case IGA1:
 		reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
 		viafb_load_reg_num = fetch_count_reg.
 			iga1_fetch_count_reg.reg_num;
 		reg = fetch_count_reg.iga1_fetch_count_reg.reg;
 		viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
-		if (set_iga == IGA1)
-			break;
+		break;
 	case IGA2:
 		reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
 		viafb_load_reg_num = fetch_count_reg.
@@ -1499,7 +1521,7 @@
 	/* H.W. Reset : ON */
 	viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
 
-	if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) {
+	if (set_iga == IGA1) {
 		/* Change D,N FOR VCLK */
 		switch (viaparinfo->chip_info->gfx_chip_name) {
 		case UNICHROME_CLE266:
@@ -1528,7 +1550,7 @@
 		}
 	}
 
-	if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) {
+	if (set_iga == IGA2) {
 		/* Change D,N FOR LCK */
 		switch (viaparinfo->chip_info->gfx_chip_name) {
 		case UNICHROME_CLE266:
@@ -1557,12 +1579,12 @@
 	viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
 
 	/* Reset PLL */
-	if ((set_iga == IGA1) || (set_iga == IGA1_IGA2)) {
+	if (set_iga == IGA1) {
 		viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
 		viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
 	}
 
-	if ((set_iga == IGA2) || (set_iga == IGA1_IGA2)) {
+	if (set_iga == IGA2) {
 		viafb_write_reg_mask(SR40, VIASR, 0x01, BIT0);
 		viafb_write_reg_mask(SR40, VIASR, 0x00, BIT0);
 	}
@@ -1805,47 +1827,15 @@
 	viafb_lock_crt();
 }
 
-void viafb_set_color_depth(int bpp_byte, int set_iga)
-{
-	if (set_iga == IGA1) {
-		switch (bpp_byte) {
-		case MODE_8BPP:
-			viafb_write_reg_mask(SR15, VIASR, 0x22, 0x7E);
-			break;
-		case MODE_16BPP:
-			viafb_write_reg_mask(SR15, VIASR, 0xB6, 0xFE);
-			break;
-		case MODE_32BPP:
-			viafb_write_reg_mask(SR15, VIASR, 0xAE, 0xFE);
-			break;
-		}
-	} else {
-		switch (bpp_byte) {
-		case MODE_8BPP:
-			viafb_write_reg_mask(CR67, VIACR, 0x00, BIT6 + BIT7);
-			break;
-		case MODE_16BPP:
-			viafb_write_reg_mask(CR67, VIACR, 0x40, BIT6 + BIT7);
-			break;
-		case MODE_32BPP:
-			viafb_write_reg_mask(CR67, VIACR, 0xC0, BIT6 + BIT7);
-			break;
-		}
-	}
-}
-
 void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
-	int mode_index, int bpp_byte, int set_iga)
+	struct VideoModeTable *video_mode, int bpp_byte, int set_iga)
 {
-	struct VideoModeTable *video_mode;
 	struct display_timing crt_reg;
 	int i;
 	int index = 0;
 	int h_addr, v_addr;
 	u32 pll_D_N;
 
-	video_mode = &CLE266Modes[search_mode_setting(mode_index)];
-
 	for (i = 0; i < video_mode->mode_array; i++) {
 		index = i;
 
@@ -1858,8 +1848,10 @@
 
 	/* Mode 640x480 has border, but LCD/DFP didn't have border. */
 	/* So we would delete border. */
-	if ((viafb_LCD_ON | viafb_DVI_ON) && (mode_index == VIA_RES_640X480)
-	    && (viaparinfo->crt_setting_info->refresh_rate == 60)) {
+	if ((viafb_LCD_ON | viafb_DVI_ON)
+	    && video_mode->crtc[0].crtc.hor_addr == 640
+	    && video_mode->crtc[0].crtc.ver_addr == 480
+	    && viaparinfo->crt_setting_info->refresh_rate == 60) {
 		/* The border is 8 pixels. */
 		crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
 
@@ -1912,9 +1904,6 @@
 	    && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
 		viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
 
-	/* load SR Register About Memory and Color part */
-	viafb_set_color_depth(bpp_byte, set_iga);
-
 	pll_D_N = viafb_get_clk_value(crt_table[index].clk);
 	DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N);
 	viafb_set_vclock(pll_D_N, set_iga);
@@ -1956,9 +1945,6 @@
 
 		viaparinfo->tmds_setting_info->h_active = hres;
 		viaparinfo->tmds_setting_info->v_active = vres;
-		viaparinfo->tmds_setting_info->bpp = bpp;
-		viaparinfo->tmds_setting_info->refresh_rate =
-			vmode_refresh;
 
 		viaparinfo->lvds_setting_info->h_active = hres;
 		viaparinfo->lvds_setting_info->v_active = vres;
@@ -1975,9 +1961,6 @@
 		if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
 			viaparinfo->tmds_setting_info->h_active = hres;
 			viaparinfo->tmds_setting_info->v_active = vres;
-			viaparinfo->tmds_setting_info->bpp = bpp;
-			viaparinfo->tmds_setting_info->refresh_rate =
-				vmode_refresh;
 		}
 
 		if (viaparinfo->lvds_setting_info->iga_path == IGA2) {
@@ -2076,9 +2059,8 @@
 
 	DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
 		  viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
-	viaparinfo->tmds_setting_info->get_dvi_size_method =
-		GET_DVI_SIZE_BY_VGA_BIOS;
-	viafb_init_dvi_size();
+	viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info,
+		&viaparinfo->shared->tmds_setting_info);
 }
 
 static void init_lvds_chip_info(void)
@@ -2195,28 +2177,19 @@
 	}
 }
 
-int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
-	int vmode_index1, int hor_res1, int ver_res1, int video_bpp1)
+int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
+	struct VideoModeTable *vmode_tbl1, int video_bpp1)
 {
 	int i, j;
 	int port;
 	u8 value, index, mask;
-	struct VideoModeTable *vmode_tbl;
 	struct crt_mode_table *crt_timing;
-	struct VideoModeTable *vmode_tbl1 = NULL;
 	struct crt_mode_table *crt_timing1 = NULL;
 
-	DEBUG_MSG(KERN_INFO "Set Mode!!\n");
-	DEBUG_MSG(KERN_INFO
-		  "vmode_index=%d hor_res=%d ver_res=%d video_bpp=%d\n",
-		  vmode_index, hor_res, ver_res, video_bpp);
-
 	device_screen_off();
-	vmode_tbl = &CLE266Modes[search_mode_setting(vmode_index)];
 	crt_timing = vmode_tbl->crtc;
 
 	if (viafb_SAMM_ON == 1) {
-		vmode_tbl1 = &CLE266Modes[search_mode_setting(vmode_index1)];
 		crt_timing1 = vmode_tbl1->crtc;
 	}
 
@@ -2267,12 +2240,11 @@
 		outb(VPIT.SR[i - 1], VIASR + 1);
 	}
 
-	viafb_set_primary_address(0);
-	viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0);
+	viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
 	viafb_set_iga_path();
 
 	/* Write CRTC */
-	viafb_fill_crtc_timing(crt_timing, vmode_index, video_bpp / 8, IGA1);
+	viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1);
 
 	/* Write Graphic Controller */
 	for (i = 0; i < StdGR; i++) {
@@ -2292,65 +2264,25 @@
 
 	/* Update Patch Register */
 
-	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-	    || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)) {
-		for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
-			if (res_patch_table[i].mode_index == vmode_index) {
-				for (j = 0;
-				     j < res_patch_table[i].table_length; j++) {
-					index =
-					    res_patch_table[i].
-					    io_reg_table[j].index;
-					port =
-					    res_patch_table[i].
-					    io_reg_table[j].port;
-					value =
-					    res_patch_table[i].
-					    io_reg_table[j].value;
-					mask =
-					    res_patch_table[i].
-					    io_reg_table[j].mask;
-					viafb_write_reg_mask(index, port, value,
-						       mask);
-				}
-			}
-		}
-	}
-
-	if (viafb_SAMM_ON == 1) {
-		if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
-		    || (viaparinfo->chip_info->gfx_chip_name ==
-		    UNICHROME_K400)) {
-			for (i = 0; i < NUM_TOTAL_PATCH_MODE; i++) {
-				if (res_patch_table[i].mode_index ==
-				    vmode_index1) {
-					for (j = 0;
-					     j <
-					     res_patch_table[i].
-					     table_length; j++) {
-						index =
-						    res_patch_table[i].
-						    io_reg_table[j].index;
-						port =
-						    res_patch_table[i].
-						    io_reg_table[j].port;
-						value =
-						    res_patch_table[i].
-						    io_reg_table[j].value;
-						mask =
-						    res_patch_table[i].
-						    io_reg_table[j].mask;
-						viafb_write_reg_mask(index,
-							port, value, mask);
-					}
-				}
-			}
+	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
+	    || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
+	    && vmode_tbl->crtc[0].crtc.hor_addr == 1024
+	    && vmode_tbl->crtc[0].crtc.ver_addr == 768) {
+		for (j = 0; j < res_patch_table[0].table_length; j++) {
+			index = res_patch_table[0].io_reg_table[j].index;
+			port = res_patch_table[0].io_reg_table[j].port;
+			value = res_patch_table[0].io_reg_table[j].value;
+			mask = res_patch_table[0].io_reg_table[j].mask;
+			viafb_write_reg_mask(index, port, value, mask);
 		}
 	}
 
 	viafb_set_primary_pitch(viafbinfo->fix.line_length);
 	viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
 		: viafbinfo->fix.line_length);
+	viafb_set_primary_color_depth(viaparinfo->depth);
+	viafb_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
+		: viaparinfo->depth);
 	/* Update Refresh Rate Setting */
 
 	/* Clear On Screen */
@@ -2359,11 +2291,11 @@
 	if (viafb_CRT_ON) {
 		if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path ==
 			IGA2)) {
-			viafb_fill_crtc_timing(crt_timing1, vmode_index1,
+			viafb_fill_crtc_timing(crt_timing1, vmode_tbl1,
 				video_bpp1 / 8,
 				viaparinfo->crt_setting_info->iga_path);
 		} else {
-			viafb_fill_crtc_timing(crt_timing, vmode_index,
+			viafb_fill_crtc_timing(crt_timing, vmode_tbl,
 				video_bpp / 8,
 				viaparinfo->crt_setting_info->iga_path);
 		}
@@ -2373,7 +2305,7 @@
 		/* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
 		to 8 alignment (1368),there is several pixels (2 pixels)
 		on right side of screen. */
-		if (hor_res % 8) {
+		if (vmode_tbl->crtc[0].crtc.hor_addr % 8) {
 			viafb_unlock_crt();
 			viafb_write_reg(CR02, VIACR,
 				viafb_read_reg(VIACR, CR02) - 1);
@@ -2384,14 +2316,14 @@
 	if (viafb_DVI_ON) {
 		if (viafb_SAMM_ON &&
 			(viaparinfo->tmds_setting_info->iga_path == IGA2)) {
-			viafb_dvi_set_mode(viafb_get_mode_index
+			viafb_dvi_set_mode(viafb_get_mode
 				     (viaparinfo->tmds_setting_info->h_active,
 				      viaparinfo->tmds_setting_info->
 				      v_active),
 				     video_bpp1, viaparinfo->
 				     tmds_setting_info->iga_path);
 		} else {
-			viafb_dvi_set_mode(viafb_get_mode_index
+			viafb_dvi_set_mode(viafb_get_mode
 				     (viaparinfo->tmds_setting_info->h_active,
 				      viaparinfo->
 				      tmds_setting_info->v_active),
@@ -2445,8 +2377,8 @@
 
 	/* If set mode normally, save resolution information for hot-plug . */
 	if (!viafb_hotplug) {
-		viafb_hotplug_Xres = hor_res;
-		viafb_hotplug_Yres = ver_res;
+		viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr;
+		viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr;
 		viafb_hotplug_bpp = video_bpp;
 		viafb_hotplug_refresh = viafb_refresh;
 
@@ -2706,13 +2638,11 @@
 
 /*According var's xres, yres fill var's other timing information*/
 void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
-			  int mode_index)
+	struct VideoModeTable *vmode_tbl)
 {
-	struct VideoModeTable *vmode_tbl = NULL;
 	struct crt_mode_table *crt_timing = NULL;
 	struct display_timing crt_reg;
 	int i = 0, index = 0;
-	vmode_tbl = &CLE266Modes[search_mode_setting(mode_index)];
 	crt_timing = vmode_tbl->crtc;
 	for (i = 0; i < vmode_tbl->mode_array; i++) {
 		index = i;
@@ -2721,36 +2651,6 @@
 	}
 
 	crt_reg = crt_timing[index].crtc;
-	switch (var->bits_per_pixel) {
-	case 8:
-		var->red.offset = 0;
-		var->green.offset = 0;
-		var->blue.offset = 0;
-		var->red.length = 6;
-		var->green.length = 6;
-		var->blue.length = 6;
-		break;
-	case 16:
-		var->red.offset = 11;
-		var->green.offset = 5;
-		var->blue.offset = 0;
-		var->red.length = 5;
-		var->green.length = 6;
-		var->blue.length = 5;
-		break;
-	case 32:
-		var->red.offset = 16;
-		var->green.offset = 8;
-		var->blue.offset = 0;
-		var->red.length = 8;
-		var->green.length = 8;
-		var->blue.length = 8;
-		break;
-	default:
-		/* never happed, put here to keep consistent */
-		break;
-	}
-
 	var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
 	var->left_margin =
 	    crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index b874d95..12ef32d 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -22,6 +22,7 @@
 #ifndef __HW_H__
 #define __HW_H__
 
+#include "viamode.h"
 #include "global.h"
 
 /***************************************************
@@ -862,8 +863,6 @@
 };
 
 extern unsigned int viafb_second_virtual_xres;
-extern unsigned int viafb_second_offset;
-extern int viafb_second_size;
 extern int viafb_SAMM_ON;
 extern int viafb_dual_fb;
 extern int viafb_LCD2_ON;
@@ -874,8 +873,9 @@
 void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
 void viafb_set_output_path(int device, int set_iga,
 	int output_interface);
+
 void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
-		      int mode_index, int bpp_byte, int set_iga);
+	struct VideoModeTable *video_mode, int bpp_byte, int set_iga);
 
 void viafb_set_vclock(u32 CLK, int set_iga);
 void viafb_load_reg(int timing_value, int viafb_load_reg_num,
@@ -891,16 +891,15 @@
 void viafb_unlock_crt(void);
 void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
 void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
-struct VideoModeTable *viafb_get_modetbl_pointer(int Index);
 u32 viafb_get_clk_value(int clk);
 void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
-void viafb_set_color_depth(int bpp_byte, int set_iga);
 void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
 					*p_gfx_dpa_setting);
 
-int viafb_setmode(int vmode_index, int hor_res, int ver_res,
-	    int video_bpp, int vmode_index1, int hor_res1,
-	    int ver_res1, int video_bpp1);
+int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
+	struct VideoModeTable *vmode_tbl1, int video_bpp1);
+void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
+	struct VideoModeTable *vmode_tbl);
 void viafb_init_chip_info(struct pci_dev *pdev,
 			  const struct pci_device_id *pdi);
 void viafb_init_dac(int set_iga);
@@ -915,6 +914,8 @@
 void viafb_set_secondary_address(u32 addr);
 void viafb_set_primary_pitch(u32 pitch);
 void viafb_set_secondary_pitch(u32 pitch);
+void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
+void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue);
 void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
 
 #endif /* __HW_H__ */
diff --git a/drivers/video/via/iface.c b/drivers/video/via/iface.c
deleted file mode 100644
index 1570636..0000000
--- a/drivers/video/via/iface.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, 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, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You 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 "global.h"
-
-/* Get frame buffer size from VGA BIOS */
-
-unsigned int viafb_get_memsize(void)
-{
-	unsigned int m;
-
-	/* If memory size provided by user */
-	if (viafb_memsize)
-		m = viafb_memsize * Mb;
-	else {
-		m = (unsigned int)viafb_read_reg(VIASR, SR39);
-		m = m * (4 * Mb);
-
-		if ((m < (16 * Mb)) || (m > (64 * Mb)))
-			m = 16 * Mb;
-	}
-	DEBUG_MSG(KERN_INFO "framebuffer size = %d Mb\n", m / Mb);
-	return m;
-}
-
-/* Get Video Buffer Starting Physical Address(back door)*/
-
-unsigned long viafb_get_videobuf_addr(void)
-{
-	struct pci_dev *pdev = NULL;
-	unsigned char sys_mem;
-	unsigned char video_mem;
-	unsigned long sys_mem_size;
-	unsigned long video_mem_size;
-	/*system memory = 256 MB, video memory 64 MB */
-	unsigned long vmem_starting_adr = 0x0C000000;
-
-	pdev =
-	    (struct pci_dev *)pci_get_device(VIA_K800_BRIDGE_VID,
-					     VIA_K800_BRIDGE_DID, NULL);
-	if (pdev != NULL) {
-		pci_read_config_byte(pdev, VIA_K800_SYSTEM_MEMORY_REG,
-				     &sys_mem);
-		pci_read_config_byte(pdev, VIA_K800_VIDEO_MEMORY_REG,
-				     &video_mem);
-		video_mem = (video_mem & 0x70) >> 4;
-		sys_mem_size = ((unsigned long)sys_mem) << 24;
-		if (video_mem != 0)
-			video_mem_size = (1 << (video_mem)) * 1024 * 1024;
-		else
-			video_mem_size = 0;
-
-		vmem_starting_adr = sys_mem_size - video_mem_size;
-		pci_dev_put(pdev);
-	}
-
-	DEBUG_MSG(KERN_INFO "Video Memory Starting Address = %lx \n",
-		  vmem_starting_adr);
-	return vmem_starting_adr;
-}
diff --git a/drivers/video/via/iface.h b/drivers/video/via/iface.h
deleted file mode 100644
index 790ec3e..0000000
--- a/drivers/video/via/iface.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2008 S3 Graphics, 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, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.See the GNU General Public License
- * for more details.
-
- * You 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 __IFACE_H__
-#define __IFACE_H__
-
-#define Kb  (1024)
-#define Mb  (Kb*Kb)
-
-#define VIA_K800_BRIDGE_VID         0x1106
-#define VIA_K800_BRIDGE_DID         0x3204
-
-#define VIA_K800_SYSTEM_MEMORY_REG  0x47
-#define VIA_K800_VIDEO_MEMORY_REG   0xA1
-
-extern int viafb_memsize;
-unsigned int viafb_get_memsize(void);
-unsigned long viafb_get_videobuf_addr(void);
-
-#endif /* __IFACE_H__ */
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 09353e2..1b1ccdc 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -22,25 +22,7 @@
 #include "global.h"
 #include "lcdtbl.h"
 
-static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = {
-	/* IGA2 Shadow Horizontal Total */
-	{IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } },
-	/* IGA2 Shadow Horizontal Blank End */
-	{IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } },
-	/* IGA2 Shadow Vertical Total */
-	{IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } },
-	/* IGA2 Shadow Vertical Addressable Video */
-	{IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } },
-	/* IGA2 Shadow Vertical Blank Start */
-	{IGA2_SHADOW_VER_BLANK_START_REG_NUM,
-	 {{CR72, 0, 7}, {CR74, 4, 6} } },
-	/* IGA2 Shadow Vertical Blank End */
-	{IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } },
-	/* IGA2 Shadow Vertical Sync Start */
-	{IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } },
-	/* IGA2 Shadow Vertical Sync End */
-	{IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } }
-};
+#define viafb_compact_res(x, y) (((x)<<16)|(y))
 
 static struct _lcd_scaling_factor lcd_scaling_factor = {
 	/* LCD Horizontal Scaling Factor Register */
@@ -59,16 +41,10 @@
 
 static int check_lvds_chip(int device_id_subaddr, int device_id);
 static bool lvds_identify_integratedlvds(void);
-static int fp_id_to_vindex(int panel_id);
+static void fp_id_to_vindex(int panel_id);
 static int lvds_register_read(int index);
 static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
 		      int panel_vres);
-static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
-	int panel_id);
-static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
-	int panel_id);
-static void load_lcd_patch_regs(int set_hres, int set_vres,
-	int panel_id, int set_iga);
 static void via_pitch_alignment_patch_lcd(
 	struct lvds_setting_information *plvds_setting_info,
 				   struct lvds_chip_information
@@ -98,8 +74,6 @@
 static struct display_timing lcd_centering_timging(struct display_timing
 					    mode_crt_reg,
 					   struct display_timing panel_crt_reg);
-static void load_crtc_shadow_timing(struct display_timing mode_timing,
-			     struct display_timing panel_timing);
 static void viafb_load_scaling_factor_for_p4m900(int set_hres,
 	int set_vres, int panel_hres, int panel_vres);
 
@@ -125,33 +99,24 @@
 		break;
 	case GET_LCD_SIZE_BY_VGA_BIOS:
 		DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n");
-		viaparinfo->lvds_setting_info->lcd_panel_size =
-		    fp_id_to_vindex(viafb_lcd_panel_id);
+		fp_id_to_vindex(viafb_lcd_panel_id);
 		DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
 			  viaparinfo->lvds_setting_info->lcd_panel_id);
-		DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
-			  viaparinfo->lvds_setting_info->lcd_panel_size);
 		break;
 	case GET_LCD_SIZE_BY_USER_SETTING:
 		DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n");
-		viaparinfo->lvds_setting_info->lcd_panel_size =
-		    fp_id_to_vindex(viafb_lcd_panel_id);
+		fp_id_to_vindex(viafb_lcd_panel_id);
 		DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
 			  viaparinfo->lvds_setting_info->lcd_panel_id);
-		DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
-			  viaparinfo->lvds_setting_info->lcd_panel_size);
 		break;
 	default:
 		DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n");
 		viaparinfo->lvds_setting_info->lcd_panel_id =
 			LCD_PANEL_ID1_800X600;
-		viaparinfo->lvds_setting_info->lcd_panel_size =
-		    fp_id_to_vindex(LCD_PANEL_ID1_800X600);
+		fp_id_to_vindex(LCD_PANEL_ID1_800X600);
 	}
 	viaparinfo->lvds_setting_info2->lcd_panel_id =
 		viaparinfo->lvds_setting_info->lcd_panel_id;
-	viaparinfo->lvds_setting_info2->lcd_panel_size =
-		viaparinfo->lvds_setting_info->lcd_panel_size;
 	viaparinfo->lvds_setting_info2->lcd_panel_hres =
 		viaparinfo->lvds_setting_info->lcd_panel_hres;
 	viaparinfo->lvds_setting_info2->lcd_panel_vres =
@@ -171,13 +136,13 @@
 		if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
 			viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
 			    INTEGRATED_LVDS;
-			DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\
-				  (Internal LVDS + External LVDS)\n");
+			DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! "
+				  "(Internal LVDS + External LVDS)\n");
 		} else {
 			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
 			    INTEGRATED_LVDS;
-			DEBUG_MSG(KERN_INFO "Not found external LVDS,\
-				  so can't support two dual channel LVDS!\n");
+			DEBUG_MSG(KERN_INFO "Not found external LVDS, "
+				  "so can't support two dual channel LVDS!\n");
 		}
 	} else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
 		/* Two single channel LCD (Internal LVDS + Internal LVDS): */
@@ -185,8 +150,8 @@
 		INTEGRATED_LVDS;
 		viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
 			INTEGRATED_LVDS;
-		DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\
-			  (Internal LVDS + Internal LVDS)\n");
+		DEBUG_MSG(KERN_INFO "Support two single channel LVDS! "
+			  "(Internal LVDS + Internal LVDS)\n");
 	} else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
 		/* If we have found external LVDS, just use it,
 		   otherwise, we will use internal LVDS as default. */
@@ -248,7 +213,7 @@
 	return FAIL;
 }
 
-static int fp_id_to_vindex(int panel_id)
+static void fp_id_to_vindex(int panel_id)
 {
 	DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
 
@@ -264,7 +229,6 @@
 			LCD_PANEL_ID0_640X480;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_640X480;
 		break;
 	case 0x1:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
@@ -273,7 +237,6 @@
 			LCD_PANEL_ID1_800X600;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_800X600;
 		break;
 	case 0x2:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
@@ -282,7 +245,6 @@
 			LCD_PANEL_ID2_1024X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_1024X768;
 		break;
 	case 0x3:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -291,7 +253,6 @@
 			LCD_PANEL_ID3_1280X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_1280X768;
 		break;
 	case 0x4:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -300,7 +261,6 @@
 			LCD_PANEL_ID4_1280X1024;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_1280X1024;
 		break;
 	case 0x5:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
@@ -309,7 +269,6 @@
 			LCD_PANEL_ID5_1400X1050;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_1400X1050;
 		break;
 	case 0x6:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
@@ -318,7 +277,6 @@
 			LCD_PANEL_ID6_1600X1200;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_1600X1200;
 		break;
 	case 0x8:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
@@ -327,7 +285,6 @@
 			LCD_PANEL_IDA_800X480;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_800X480;
 		break;
 	case 0x9:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
@@ -336,7 +293,6 @@
 			LCD_PANEL_ID2_1024X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_1024X768;
 		break;
 	case 0xA:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
@@ -345,7 +301,6 @@
 			LCD_PANEL_ID2_1024X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		return VIA_RES_1024X768;
 		break;
 	case 0xB:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
@@ -354,7 +309,6 @@
 			LCD_PANEL_ID2_1024X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		return VIA_RES_1024X768;
 		break;
 	case 0xC:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -363,7 +317,6 @@
 			LCD_PANEL_ID3_1280X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		return VIA_RES_1280X768;
 		break;
 	case 0xD:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -372,7 +325,6 @@
 			LCD_PANEL_ID4_1280X1024;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		return VIA_RES_1280X1024;
 		break;
 	case 0xE:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
@@ -381,7 +333,6 @@
 			LCD_PANEL_ID5_1400X1050;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		return VIA_RES_1400X1050;
 		break;
 	case 0xF:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
@@ -390,7 +341,6 @@
 			LCD_PANEL_ID6_1600X1200;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		return VIA_RES_1600X1200;
 		break;
 	case 0x10:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
@@ -399,7 +349,6 @@
 			LCD_PANEL_ID7_1366X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		return VIA_RES_1368X768;
 		break;
 	case 0x11:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
@@ -408,7 +357,6 @@
 			LCD_PANEL_ID8_1024X600;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_1024X600;
 		break;
 	case 0x12:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -417,7 +365,6 @@
 			LCD_PANEL_ID3_1280X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_1280X768;
 		break;
 	case 0x13:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -426,7 +373,6 @@
 			LCD_PANEL_ID9_1280X800;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_1280X800;
 		break;
 	case 0x14:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
@@ -435,7 +381,6 @@
 			LCD_PANEL_IDB_1360X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		return VIA_RES_1360X768;
 		break;
 	case 0x15:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
@@ -444,7 +389,6 @@
 			LCD_PANEL_ID3_1280X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
-		return VIA_RES_1280X768;
 		break;
 	case 0x16:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
@@ -453,7 +397,6 @@
 			LCD_PANEL_IDC_480X640;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_480X640;
 		break;
 	default:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
@@ -462,7 +405,6 @@
 			LCD_PANEL_ID1_800X600;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
-		return VIA_RES_800X600;
 	}
 }
 
@@ -573,284 +515,6 @@
 	}
 }
 
-static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
-	int panel_id)
-{
-	int vmode_index;
-	int reg_num = 0;
-	struct io_reg *lcd_patch_reg = NULL;
-
-	vmode_index = viafb_get_mode_index(set_hres, set_vres);
-	switch (panel_id) {
-		/* LCD 800x600 */
-	case LCD_PANEL_ID1_800X600:
-		switch (vmode_index) {
-		case VIA_RES_640X400:
-		case VIA_RES_640X480:
-			reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6;
-			lcd_patch_reg = K400_LCD_RES_6X4_8X6;
-			break;
-		case VIA_RES_720X480:
-		case VIA_RES_720X576:
-			reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6;
-			lcd_patch_reg = K400_LCD_RES_7X4_8X6;
-			break;
-		}
-		break;
-
-		/* LCD 1024x768 */
-	case LCD_PANEL_ID2_1024X768:
-		switch (vmode_index) {
-		case VIA_RES_640X400:
-		case VIA_RES_640X480:
-			reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7;
-			lcd_patch_reg = K400_LCD_RES_6X4_10X7;
-			break;
-		case VIA_RES_720X480:
-		case VIA_RES_720X576:
-			reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7;
-			lcd_patch_reg = K400_LCD_RES_7X4_10X7;
-			break;
-		case VIA_RES_800X600:
-			reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7;
-			lcd_patch_reg = K400_LCD_RES_8X6_10X7;
-			break;
-		}
-		break;
-
-		/* LCD 1280x1024 */
-	case LCD_PANEL_ID4_1280X1024:
-		switch (vmode_index) {
-		case VIA_RES_640X400:
-		case VIA_RES_640X480:
-			reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10;
-			lcd_patch_reg = K400_LCD_RES_6X4_12X10;
-			break;
-		case VIA_RES_720X480:
-		case VIA_RES_720X576:
-			reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10;
-			lcd_patch_reg = K400_LCD_RES_7X4_12X10;
-			break;
-		case VIA_RES_800X600:
-			reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10;
-			lcd_patch_reg = K400_LCD_RES_8X6_12X10;
-			break;
-		case VIA_RES_1024X768:
-			reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10;
-			lcd_patch_reg = K400_LCD_RES_10X7_12X10;
-			break;
-
-		}
-		break;
-
-		/* LCD 1400x1050 */
-	case LCD_PANEL_ID5_1400X1050:
-		switch (vmode_index) {
-		case VIA_RES_640X480:
-			reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10;
-			lcd_patch_reg = K400_LCD_RES_6X4_14X10;
-			break;
-		case VIA_RES_800X600:
-			reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10;
-			lcd_patch_reg = K400_LCD_RES_8X6_14X10;
-			break;
-		case VIA_RES_1024X768:
-			reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10;
-			lcd_patch_reg = K400_LCD_RES_10X7_14X10;
-			break;
-		case VIA_RES_1280X768:
-		case VIA_RES_1280X800:
-		case VIA_RES_1280X960:
-		case VIA_RES_1280X1024:
-			reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10;
-			lcd_patch_reg = K400_LCD_RES_12X10_14X10;
-			break;
-		}
-		break;
-
-		/* LCD 1600x1200 */
-	case LCD_PANEL_ID6_1600X1200:
-		switch (vmode_index) {
-		case VIA_RES_640X400:
-		case VIA_RES_640X480:
-			reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12;
-			lcd_patch_reg = K400_LCD_RES_6X4_16X12;
-			break;
-		case VIA_RES_720X480:
-		case VIA_RES_720X576:
-			reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12;
-			lcd_patch_reg = K400_LCD_RES_7X4_16X12;
-			break;
-		case VIA_RES_800X600:
-			reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12;
-			lcd_patch_reg = K400_LCD_RES_8X6_16X12;
-			break;
-		case VIA_RES_1024X768:
-			reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12;
-			lcd_patch_reg = K400_LCD_RES_10X7_16X12;
-			break;
-		case VIA_RES_1280X768:
-		case VIA_RES_1280X800:
-		case VIA_RES_1280X960:
-		case VIA_RES_1280X1024:
-			reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12;
-			lcd_patch_reg = K400_LCD_RES_12X10_16X12;
-			break;
-		}
-		break;
-
-		/* LCD 1366x768 */
-	case LCD_PANEL_ID7_1366X768:
-		switch (vmode_index) {
-		case VIA_RES_640X480:
-			reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7;
-			lcd_patch_reg = K400_LCD_RES_6X4_1366X7;
-			break;
-		case VIA_RES_720X480:
-		case VIA_RES_720X576:
-			reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7;
-			lcd_patch_reg = K400_LCD_RES_7X4_1366X7;
-			break;
-		case VIA_RES_800X600:
-			reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7;
-			lcd_patch_reg = K400_LCD_RES_8X6_1366X7;
-			break;
-		case VIA_RES_1024X768:
-			reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7;
-			lcd_patch_reg = K400_LCD_RES_10X7_1366X7;
-			break;
-		case VIA_RES_1280X768:
-		case VIA_RES_1280X800:
-		case VIA_RES_1280X960:
-		case VIA_RES_1280X1024:
-			reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7;
-			lcd_patch_reg = K400_LCD_RES_12X10_1366X7;
-			break;
-		}
-		break;
-
-		/* LCD 1360x768 */
-	case LCD_PANEL_IDB_1360X768:
-		break;
-	}
-	if (reg_num != 0) {
-		/* H.W. Reset : ON */
-		viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
-
-		viafb_write_regx(lcd_patch_reg, reg_num);
-
-		/* H.W. Reset : OFF */
-		viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
-
-		/* Reset PLL */
-		viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
-		viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
-
-		/* Fire! */
-		outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
-	}
-}
-
-static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
-	int panel_id)
-{
-	int vmode_index;
-	int reg_num = 0;
-	struct io_reg *lcd_patch_reg = NULL;
-
-	vmode_index = viafb_get_mode_index(set_hres, set_vres);
-
-	switch (panel_id) {
-	case LCD_PANEL_ID5_1400X1050:
-		switch (vmode_index) {
-		case VIA_RES_640X480:
-			reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10;
-			lcd_patch_reg = P880_LCD_RES_6X4_14X10;
-			break;
-		case VIA_RES_800X600:
-			reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10;
-			lcd_patch_reg = P880_LCD_RES_8X6_14X10;
-			break;
-		}
-		break;
-	case LCD_PANEL_ID6_1600X1200:
-		switch (vmode_index) {
-		case VIA_RES_640X400:
-		case VIA_RES_640X480:
-			reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12;
-			lcd_patch_reg = P880_LCD_RES_6X4_16X12;
-			break;
-		case VIA_RES_720X480:
-		case VIA_RES_720X576:
-			reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12;
-			lcd_patch_reg = P880_LCD_RES_7X4_16X12;
-			break;
-		case VIA_RES_800X600:
-			reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12;
-			lcd_patch_reg = P880_LCD_RES_8X6_16X12;
-			break;
-		case VIA_RES_1024X768:
-			reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12;
-			lcd_patch_reg = P880_LCD_RES_10X7_16X12;
-			break;
-		case VIA_RES_1280X768:
-		case VIA_RES_1280X960:
-		case VIA_RES_1280X1024:
-			reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12;
-			lcd_patch_reg = P880_LCD_RES_12X10_16X12;
-			break;
-		}
-		break;
-
-	}
-	if (reg_num != 0) {
-		/* H.W. Reset : ON */
-		viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
-
-		viafb_write_regx(lcd_patch_reg, reg_num);
-
-		/* H.W. Reset : OFF */
-		viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
-
-		/* Reset PLL */
-		viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
-		viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
-
-		/* Fire! */
-		outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
-	}
-}
-
-static void load_lcd_patch_regs(int set_hres, int set_vres,
-	int panel_id, int set_iga)
-{
-	int vmode_index;
-
-	vmode_index = viafb_get_mode_index(set_hres, set_vres);
-
-	viafb_unlock_crt();
-
-	/* Patch for simultaneous & Expansion */
-	if ((set_iga == IGA1_IGA2) &&
-		(viaparinfo->lvds_setting_info->display_method ==
-	    LCD_EXPANDSION)) {
-		switch (viaparinfo->chip_info->gfx_chip_name) {
-		case UNICHROME_CLE266:
-		case UNICHROME_K400:
-			load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id);
-			break;
-		case UNICHROME_K800:
-			break;
-		case UNICHROME_PM800:
-		case UNICHROME_CN700:
-		case UNICHROME_CX700:
-			load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id);
-		}
-	}
-
-	viafb_lock_crt();
-}
-
 static void via_pitch_alignment_patch_lcd(
 	struct lvds_setting_information *plvds_setting_info,
 				   struct lvds_chip_information
@@ -949,29 +613,25 @@
 		  struct lvds_setting_information *plvds_setting_info,
 		  struct lvds_chip_information *plvds_chip_info)
 {
-	int video_index = plvds_setting_info->lcd_panel_size;
 	int set_iga = plvds_setting_info->iga_path;
 	int mode_bpp = plvds_setting_info->bpp;
-	int set_hres, set_vres;
-	int panel_hres, panel_vres;
+	int set_hres = plvds_setting_info->h_active;
+	int set_vres = plvds_setting_info->v_active;
+	int panel_hres = plvds_setting_info->lcd_panel_hres;
+	int panel_vres = plvds_setting_info->lcd_panel_vres;
 	u32 pll_D_N;
-	int offset;
 	struct display_timing mode_crt_reg, panel_crt_reg;
 	struct crt_mode_table *panel_crt_table = NULL;
-	struct VideoModeTable *vmode_tbl = NULL;
+	struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres,
+		panel_vres);
 
 	DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
 	/* Get mode table */
 	mode_crt_reg = mode_crt_table->crtc;
 	/* Get panel table Pointer */
-	vmode_tbl = viafb_get_modetbl_pointer(video_index);
 	panel_crt_table = vmode_tbl->crtc;
 	panel_crt_reg = panel_crt_table->crtc;
 	DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
-	set_hres = plvds_setting_info->h_active;
-	set_vres = plvds_setting_info->v_active;
-	panel_hres = plvds_setting_info->lcd_panel_hres;
-	panel_vres = plvds_setting_info->lcd_panel_vres;
 	if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
 		viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
 	plvds_setting_info->vclk = panel_crt_table->clk;
@@ -1001,54 +661,12 @@
 		}
 	}
 
-	if (set_iga == IGA1_IGA2) {
-		load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg);
-		/* Fill shadow registers */
+	/* Fetch count for IGA2 only */
+	viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
 
-		switch (plvds_setting_info->lcd_panel_id) {
-		case LCD_PANEL_ID0_640X480:
-			offset = 80;
-			break;
-		case LCD_PANEL_ID1_800X600:
-		case LCD_PANEL_IDA_800X480:
-			offset = 110;
-			break;
-		case LCD_PANEL_ID2_1024X768:
-			offset = 150;
-			break;
-		case LCD_PANEL_ID3_1280X768:
-		case LCD_PANEL_ID4_1280X1024:
-		case LCD_PANEL_ID5_1400X1050:
-		case LCD_PANEL_ID9_1280X800:
-			offset = 190;
-			break;
-		case LCD_PANEL_ID6_1600X1200:
-			offset = 250;
-			break;
-		case LCD_PANEL_ID7_1366X768:
-		case LCD_PANEL_IDB_1360X768:
-			offset = 212;
-			break;
-		default:
-			offset = 140;
-			break;
-		}
-
-		/* Offset for simultaneous */
-		viafb_set_secondary_pitch(offset << 3);
-		DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n");
-		viafb_load_fetch_count_reg(set_hres, 4, IGA2);
-		/* Fetch count for simultaneous */
-	} else {		/* SAMM */
-		/* Fetch count for IGA2 only */
-		viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
-
-		if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
-		    && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
-			viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
-
-		viafb_set_color_depth(mode_bpp / 8, set_iga);
-	}
+	if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
+		&& (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
+		viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
 
 	fill_lcd_format();
 
@@ -1065,11 +683,6 @@
 	    || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
 		viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
 
-	load_lcd_patch_regs(set_hres, set_vres,
-			    plvds_setting_info->lcd_panel_id, set_iga);
-
-	DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n");
-
 	/* Patch for non 32bit alignment mode */
 	via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info);
 }
@@ -1283,8 +896,7 @@
 		viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
 	}
 
-	if ((viaparinfo->lvds_setting_info->iga_path == IGA1)
-	    || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) {
+	if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
 		/* CRT path set to IGA2    */
 		viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
 		/* IGA2 path disabled      */
@@ -1476,210 +1088,6 @@
 	return crt_reg;
 }
 
-static void load_crtc_shadow_timing(struct display_timing mode_timing,
-			     struct display_timing panel_timing)
-{
-	struct io_register *reg = NULL;
-	int i;
-	int viafb_load_reg_Num = 0;
-	int reg_value = 0;
-
-	if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) {
-		/* Expansion */
-		for (i = 12; i < 20; i++) {
-			switch (i) {
-			case H_TOTAL_SHADOW_INDEX:
-				reg_value =
-				    IGA2_HOR_TOTAL_SHADOW_FORMULA
-				    (panel_timing.hor_total);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.hor_total_shadow.
-				    reg_num;
-				reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
-				break;
-			case H_BLANK_END_SHADOW_INDEX:
-				reg_value =
-				    IGA2_HOR_BLANK_END_SHADOW_FORMULA
-				    (panel_timing.hor_blank_start,
-				     panel_timing.hor_blank_end);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.
-				    hor_blank_end_shadow.reg_num;
-				reg =
-				    iga2_shadow_crtc_reg.
-				    hor_blank_end_shadow.reg;
-				break;
-			case V_TOTAL_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_TOTAL_SHADOW_FORMULA
-				    (panel_timing.ver_total);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.ver_total_shadow.
-				    reg_num;
-				reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
-				break;
-			case V_ADDR_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_ADDR_SHADOW_FORMULA
-				    (panel_timing.ver_addr);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.ver_addr_shadow.
-				    reg_num;
-				reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
-				break;
-			case V_BLANK_SATRT_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_BLANK_START_SHADOW_FORMULA
-				    (panel_timing.ver_blank_start);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.
-				    ver_blank_start_shadow.reg_num;
-				reg =
-				    iga2_shadow_crtc_reg.
-				    ver_blank_start_shadow.reg;
-				break;
-			case V_BLANK_END_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_BLANK_END_SHADOW_FORMULA
-				    (panel_timing.ver_blank_start,
-				     panel_timing.ver_blank_end);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.
-				    ver_blank_end_shadow.reg_num;
-				reg =
-				    iga2_shadow_crtc_reg.
-				    ver_blank_end_shadow.reg;
-				break;
-			case V_SYNC_SATRT_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_SYNC_START_SHADOW_FORMULA
-				    (panel_timing.ver_sync_start);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.
-				    ver_sync_start_shadow.reg_num;
-				reg =
-				    iga2_shadow_crtc_reg.
-				    ver_sync_start_shadow.reg;
-				break;
-			case V_SYNC_END_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_SYNC_END_SHADOW_FORMULA
-				    (panel_timing.ver_sync_start,
-				     panel_timing.ver_sync_end);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.
-				    ver_sync_end_shadow.reg_num;
-				reg =
-				    iga2_shadow_crtc_reg.
-				    ver_sync_end_shadow.reg;
-				break;
-			}
-			viafb_load_reg(reg_value,
-				viafb_load_reg_Num, reg, VIACR);
-		}
-	} else {		/* Centering */
-		for (i = 12; i < 20; i++) {
-			switch (i) {
-			case H_TOTAL_SHADOW_INDEX:
-				reg_value =
-				    IGA2_HOR_TOTAL_SHADOW_FORMULA
-				    (panel_timing.hor_total);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.hor_total_shadow.
-				    reg_num;
-				reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
-				break;
-			case H_BLANK_END_SHADOW_INDEX:
-				reg_value =
-				    IGA2_HOR_BLANK_END_SHADOW_FORMULA
-				    (panel_timing.hor_blank_start,
-				     panel_timing.hor_blank_end);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.
-				    hor_blank_end_shadow.reg_num;
-				reg =
-				    iga2_shadow_crtc_reg.
-				    hor_blank_end_shadow.reg;
-				break;
-			case V_TOTAL_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_TOTAL_SHADOW_FORMULA
-				    (panel_timing.ver_total);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.ver_total_shadow.
-				    reg_num;
-				reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
-				break;
-			case V_ADDR_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_ADDR_SHADOW_FORMULA
-				    (mode_timing.ver_addr);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.ver_addr_shadow.
-				    reg_num;
-				reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
-				break;
-			case V_BLANK_SATRT_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_BLANK_START_SHADOW_FORMULA
-				    (mode_timing.ver_blank_start);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.
-				    ver_blank_start_shadow.reg_num;
-				reg =
-				    iga2_shadow_crtc_reg.
-				    ver_blank_start_shadow.reg;
-				break;
-			case V_BLANK_END_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_BLANK_END_SHADOW_FORMULA
-				    (panel_timing.ver_blank_start,
-				     panel_timing.ver_blank_end);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.
-				    ver_blank_end_shadow.reg_num;
-				reg =
-				    iga2_shadow_crtc_reg.
-				    ver_blank_end_shadow.reg;
-				break;
-			case V_SYNC_SATRT_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_SYNC_START_SHADOW_FORMULA(
-				    (panel_timing.ver_sync_start -
-				    panel_timing.ver_blank_start) +
-				    (panel_timing.ver_addr -
-				    mode_timing.ver_addr) / 2 +
-				    mode_timing.ver_addr);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.ver_sync_start_shadow.
-				    reg_num;
-				reg =
-				    iga2_shadow_crtc_reg.ver_sync_start_shadow.
-				    reg;
-				break;
-			case V_SYNC_END_SHADOW_INDEX:
-				reg_value =
-				    IGA2_VER_SYNC_END_SHADOW_FORMULA(
-				    (panel_timing.ver_sync_start -
-				    panel_timing.ver_blank_start) +
-				    (panel_timing.ver_addr -
-				    mode_timing.ver_addr) / 2 +
-				    mode_timing.ver_addr,
-				    panel_timing.ver_sync_end);
-				viafb_load_reg_Num =
-				    iga2_shadow_crtc_reg.ver_sync_end_shadow.
-				    reg_num;
-				reg =
-				    iga2_shadow_crtc_reg.ver_sync_end_shadow.
-				    reg;
-				break;
-			}
-			viafb_load_reg(reg_value,
-				viafb_load_reg_Num, reg, VIACR);
-		}
-	}
-}
-
 bool viafb_lcd_get_mobile_state(bool *mobile)
 {
 	unsigned char *romptr, *tableptr;
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 7cd03e2..d55aaa7 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -43,61 +43,6 @@
 /* Video Memory Size */
 #define VIDEO_MEMORY_SIZE_16M    0x1000000
 
-/* Definition Mode Index
-*/
-#define     VIA_RES_640X480                 	0
-#define     VIA_RES_800X600                 	1
-#define     VIA_RES_1024X768                	2
-#define     VIA_RES_1152X864                	3
-#define     VIA_RES_1280X1024               	4
-#define     VIA_RES_1600X1200               	5
-#define     VIA_RES_1440X1050               	6
-#define     VIA_RES_1280X768                	7
-#define     VIA_RES_1280X960                	8
-#define     VIA_RES_1920X1440               	9
-#define     VIA_RES_848X480                 	10
-#define     VIA_RES_1400X1050               	11
-#define     VIA_RES_720X480                 	12
-#define     VIA_RES_720X576                 	13
-#define     VIA_RES_1024X512                	14
-#define     VIA_RES_856X480                 	15
-#define     VIA_RES_1024X576                	16
-#define     VIA_RES_640X400                 	17
-#define     VIA_RES_1280X720                	18
-#define     VIA_RES_1920X1080               	19
-#define     VIA_RES_800X480                 	20
-#define     VIA_RES_1368X768                	21
-#define     VIA_RES_1024X600                	22
-#define     VIA_RES_1280X800                	23
-#define     VIA_RES_1680X1050               	24
-#define     VIA_RES_960X600			25
-#define     VIA_RES_1000X600               	26
-#define     VIA_RES_1088X612               	27
-#define     VIA_RES_1152X720               	28
-#define     VIA_RES_1200X720               	29
-#define     VIA_RES_1280X600               	30
-#define     VIA_RES_1360X768               	31
-#define     VIA_RES_1366X768               	32
-#define     VIA_RES_1440X900               	33
-#define     VIA_RES_1600X900               	34
-#define     VIA_RES_1600X1024              	35
-#define     VIA_RES_1792X1344              	36
-#define     VIA_RES_1856X1392              	37
-#define     VIA_RES_1920X1200              	38
-#define     VIA_RES_2048X1536              	39
-#define     VIA_RES_480X640                  	40
-
-/*Reduce Blanking*/
-#define     VIA_RES_1360X768_RB          	131
-#define     VIA_RES_1440X900_RB          	133
-#define     VIA_RES_1400X1050_RB        	111
-#define     VIA_RES_1600X900_RB          	134
-#define     VIA_RES_1680X1050_RB        	124
-#define     VIA_RES_1920X1080_RB        	119
-#define     VIA_RES_1920X1200_RB        	138
-
-#define     VIA_RES_INVALID                 	255
-
 /* standard VGA IO port
 */
 #define VIARMisc    0x3CC
@@ -118,7 +63,6 @@
 /* Display path */
 #define IGA1        1
 #define IGA2        2
-#define IGA1_IGA2   3
 
 /* Define Color Depth  */
 #define MODE_8BPP       1
diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c
index d53c3d5..aefdeee 100644
--- a/drivers/video/via/via_utility.c
+++ b/drivers/video/via/via_utility.c
@@ -239,15 +239,3 @@
 	else
 		*support_state = CRT_Device | DVI_Device | LCD_Device;
 }
-
-int viafb_input_parameter_converter(int parameter_value)
-{
-	int result;
-
-	if (parameter_value >= 1 && parameter_value <= 9)
-		result = 1 << (parameter_value - 1);
-	else
-		result = 1;
-
-	return result;
-}
diff --git a/drivers/video/via/via_utility.h b/drivers/video/via/via_utility.h
index 2fd4552..1670ba8 100644
--- a/drivers/video/via/via_utility.h
+++ b/drivers/video/via/via_utility.h
@@ -30,6 +30,5 @@
 void viafb_set_gamma_table(int bpp, unsigned int *gamma_table);
 void viafb_get_gamma_table(unsigned int *gamma_table);
 void viafb_get_gamma_support_state(int bpp, unsigned int *support_state);
-int viafb_input_parameter_converter(int parameter_value);
 
 #endif /* __VIAUTILITY_H__ */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 3028e7d..ce7783b 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -26,18 +26,22 @@
 
 #include "global.h"
 
-static struct fb_var_screeninfo default_var;
 static char *viafb_name = "Via";
 static u32 pseudo_pal[17];
 
 /* video mode */
-static char *viafb_mode = "640x480";
-static char *viafb_mode1 = "640x480";
+static char *viafb_mode;
+static char *viafb_mode1;
+static int viafb_bpp = 32;
+static int viafb_bpp1 = 32;
+
+static unsigned int viafb_second_offset;
+static int viafb_second_size;
 
 static int viafb_accel = 1;
 
 /* Added for specifying active devices.*/
-char *viafb_active_dev = "";
+char *viafb_active_dev;
 
 /*Added for specify lcd output port*/
 char *viafb_lcd_port = "";
@@ -50,18 +54,78 @@
 	*sec_var);
 static void retrieve_device_setting(struct viafb_ioctl_setting
 	*setting_info);
+static int viafb_pan_display(struct fb_var_screeninfo *var,
+	struct fb_info *info);
 
 static struct fb_ops viafb_ops;
 
 
+static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
+{
+	var->grayscale = 0;
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	var->transp.msb_right = 0;
+	var->nonstd = 0;
+	switch (depth) {
+	case 8:
+		var->bits_per_pixel = 8;
+		var->red.offset = 0;
+		var->green.offset = 0;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	case 15:
+		var->bits_per_pixel = 16;
+		var->red.offset = 10;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 5;
+		var->blue.length = 5;
+		break;
+	case 16:
+		var->bits_per_pixel = 16;
+		var->red.offset = 11;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		break;
+	case 24:
+		var->bits_per_pixel = 32;
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	case 30:
+		var->bits_per_pixel = 32;
+		var->red.offset = 20;
+		var->green.offset = 10;
+		var->blue.offset = 0;
+		var->red.length = 10;
+		var->green.length = 10;
+		var->blue.length = 10;
+		break;
+	}
+}
+
 static void viafb_update_fix(struct fb_info *info)
 {
 	u32 bpp = info->var.bits_per_pixel;
 
 	info->fix.visual =
 		bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	info->fix.line_length =
-		((info->var.xres_virtual + 7) & ~7) * bpp / 8;
+	info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7;
 }
 
 static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
@@ -75,6 +139,7 @@
 
 	fix->type = FB_TYPE_PACKED_PIXELS;
 	fix->type_aux = 0;
+	fix->visual = FB_VISUAL_TRUECOLOR;
 
 	fix->xpanstep = fix->ywrapstep = 0;
 	fix->ypanstep = 1;
@@ -97,9 +162,10 @@
 static int viafb_check_var(struct fb_var_screeninfo *var,
 	struct fb_info *info)
 {
-	int vmode_index, htotal, vtotal;
+	int htotal, vtotal, depth;
+	struct VideoModeTable *vmode_entry;
 	struct viafb_par *ppar = info->par;
-	u32 long_refresh;
+	u32 long_refresh, line;
 
 	DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
 	/* Sanity check */
@@ -107,26 +173,36 @@
 	if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
 		return -EINVAL;
 
-	vmode_index = viafb_get_mode_index(var->xres, var->yres);
-	if (vmode_index == VIA_RES_INVALID) {
+	vmode_entry = viafb_get_mode(var->xres, var->yres);
+	if (!vmode_entry) {
 		DEBUG_MSG(KERN_INFO
 			  "viafb: Mode %dx%dx%d not supported!!\n",
 			  var->xres, var->yres, var->bits_per_pixel);
 		return -EINVAL;
 	}
 
-	if (24 == var->bits_per_pixel)
-		var->bits_per_pixel = 32;
+	depth = fb_get_color_depth(var, &info->fix);
+	if (!depth)
+		depth = var->bits_per_pixel;
 
-	if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
-		var->bits_per_pixel != 32)
+	if (depth < 0 || depth > 32)
 		return -EINVAL;
+	else if (!depth)
+		depth = 24;
+	else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1)
+		depth = 15;
+	else if (depth == 30)
+		depth = 30;
+	else if (depth <= 8)
+		depth = 8;
+	else if (depth <= 16)
+		depth = 16;
+	else
+		depth = 24;
 
-	if ((var->xres_virtual * (var->bits_per_pixel >> 3)) & 0x1F)
-		/*32 pixel alignment */
-		var->xres_virtual = (var->xres_virtual + 31) & ~31;
-	if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
-		ppar->memsize)
+	viafb_fill_var_color_info(var, depth);
+	line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7;
+	if (line * var->yres_virtual > ppar->memsize)
 		return -EINVAL;
 
 	/* Based on var passed in to calculate the refresh,
@@ -142,7 +218,7 @@
 	viafb_refresh = viafb_get_refresh(var->xres, var->yres, long_refresh);
 
 	/* Adjust var according to our driver's own table */
-	viafb_fill_var_timing_info(var, viafb_refresh, vmode_index);
+	viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry);
 	if (info->var.accel_flags & FB_ACCELF_TEXT &&
 		!ppar->shared->engine_mmio)
 		info->var.accel_flags = 0;
@@ -153,39 +229,45 @@
 static int viafb_set_par(struct fb_info *info)
 {
 	struct viafb_par *viapar = info->par;
-	int vmode_index;
-	int vmode_index1 = 0;
+	struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL;
 	DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
 
 	viapar->depth = fb_get_color_depth(&info->var, &info->fix);
-	viafb_update_device_setting(info->var.xres, info->var.yres,
-			      info->var.bits_per_pixel, viafb_refresh, 0);
+	viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
+		viafbinfo->var.bits_per_pixel, viafb_refresh, 0);
 
-	vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres);
-
-	if (viafb_SAMM_ON == 1) {
+	vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres);
+	if (viafb_dual_fb) {
+		vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres,
+			viafbinfo1->var.yres);
+		viafb_update_device_setting(viafbinfo1->var.xres,
+			viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
+			viafb_refresh1, 1);
+	} else if (viafb_SAMM_ON == 1) {
 		DEBUG_MSG(KERN_INFO
 		"viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
 			  viafb_second_xres, viafb_second_yres, viafb_bpp1);
-		vmode_index1 = viafb_get_mode_index(viafb_second_xres,
+		vmode_entry1 = viafb_get_mode(viafb_second_xres,
 			viafb_second_yres);
-		DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n",
-			vmode_index1);
 
 		viafb_update_device_setting(viafb_second_xres,
 			viafb_second_yres, viafb_bpp1, viafb_refresh1, 1);
 	}
 
-	if (vmode_index != VIA_RES_INVALID) {
+	if (vmode_entry) {
 		viafb_update_fix(info);
-		viafb_bpp = info->var.bits_per_pixel;
+		if (viafb_dual_fb && viapar->iga_path == IGA2)
+			viafb_bpp1 = info->var.bits_per_pixel;
+		else
+			viafb_bpp = info->var.bits_per_pixel;
+
 		if (info->var.accel_flags & FB_ACCELF_TEXT)
 			info->flags &= ~FBINFO_HWACCEL_DISABLED;
 		else
 			info->flags |= FBINFO_HWACCEL_DISABLED;
-		viafb_setmode(vmode_index, info->var.xres, info->var.yres,
-			info->var.bits_per_pixel, vmode_index1,
-			viafb_second_xres, viafb_second_yres, viafb_bpp1);
+		viafb_setmode(vmode_entry, info->var.bits_per_pixel,
+			vmode_entry1, viafb_bpp1);
+		viafb_pan_display(&info->var, info);
 	}
 
 	return 0;
@@ -195,234 +277,52 @@
 static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 unsigned blue, unsigned transp, struct fb_info *info)
 {
-	u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
-	unsigned cmap_entries = (info->var.bits_per_pixel == 8) ? 256 : 16;
-	DEBUG_MSG(KERN_INFO "viafb_setcolreg!\n");
-	if (regno >= cmap_entries)
-		return 1;
-	if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
-		/*
-		 * Read PCI bus 0,dev 0,function 0,index 0xF6 to get chip rev.
-		 */
-		outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
-		rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
-	}
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		outb(0x1A, 0x3C4);
-		sr1a = inb(0x3C5);
-		outb(0x1B, 0x3C4);
-		sr1b = inb(0x3C5);
-		outb(0x67, 0x3D4);
-		cr67 = inb(0x3D5);
-		outb(0x6A, 0x3D4);
-		cr6a = inb(0x3D5);
+	struct viafb_par *viapar = info->par;
+	u32 r, g, b;
 
-		/* Map the 3C6/7/8/9 to the IGA2 */
-		outb(0x1A, 0x3C4);
-		outb(sr1a | 0x01, 0x3C5);
-		/* Second Display Engine colck always on */
-		outb(0x1B, 0x3C4);
-		outb(sr1b | 0x80, 0x3C5);
-		/* Second Display Color Depth 8 */
-		outb(0x67, 0x3D4);
-		outb(cr67 & 0x3F, 0x3D5);
-		outb(0x6A, 0x3D4);
-		/* Second Display Channel Reset CR6A[6]) */
-		outb(cr6a & 0xBF, 0x3D5);
-		/* Second Display Channel Enable CR6A[7] */
-		outb(cr6a | 0x80, 0x3D5);
-		/* Second Display Channel stop reset) */
-		outb(cr6a | 0x40, 0x3D5);
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+		if (regno > 255)
+			return -EINVAL;
 
-		/* Bit mask of palette */
-		outb(0xFF, 0x3c6);
-		/* Write one register of IGA2 */
-		outb(regno, 0x3C8);
-		if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
-			rev >= 15) {
-			shift = 8;
-			viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
-			viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
-		} else {
-			shift = 10;
-			viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
-			viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
-		}
-		outb(red >> shift, 0x3C9);
-		outb(green >> shift, 0x3C9);
-		outb(blue >> shift, 0x3C9);
+		if (!viafb_dual_fb || viapar->iga_path == IGA1)
+			viafb_set_primary_color_register(regno, red >> 8,
+				green >> 8, blue >> 8);
 
-		/* Map the 3C6/7/8/9 to the IGA1 */
-		outb(0x1A, 0x3C4);
-		outb(sr1a & 0xFE, 0x3C5);
-		/* Bit mask of palette */
-		outb(0xFF, 0x3c6);
-		/* Write one register of IGA1 */
-		outb(regno, 0x3C8);
-		outb(red >> shift, 0x3C9);
-		outb(green >> shift, 0x3C9);
-		outb(blue >> shift, 0x3C9);
+		if (!viafb_dual_fb || viapar->iga_path == IGA2)
+			viafb_set_secondary_color_register(regno, red >> 8,
+				green >> 8, blue >> 8);
+	} else {
+		if (regno > 15)
+			return -EINVAL;
 
-		outb(0x1A, 0x3C4);
-		outb(sr1a, 0x3C5);
-		outb(0x1B, 0x3C4);
-		outb(sr1b, 0x3C5);
-		outb(0x67, 0x3D4);
-		outb(cr67, 0x3D5);
-		outb(0x6A, 0x3D4);
-		outb(cr6a, 0x3D5);
-		break;
-	case 16:
-		((u32 *) info->pseudo_palette)[regno] = (red & 0xF800) |
-		    ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
-		break;
-	case 32:
-		((u32 *) info->pseudo_palette)[regno] =
-		    ((transp & 0xFF00) << 16) |
-		    ((red & 0xFF00) << 8) |
-		    ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
-		break;
+		r = (red >> (16 - info->var.red.length))
+			<< info->var.red.offset;
+		b = (blue >> (16 - info->var.blue.length))
+			<< info->var.blue.offset;
+		g = (green >> (16 - info->var.green.length))
+			<< info->var.green.offset;
+		((u32 *) info->pseudo_palette)[regno] = r | g | b;
 	}
 
 	return 0;
-
-}
-
-/*CALLED BY: fb_set_cmap */
-/*           fb_set_var, pass 256 colors */
-/*CALLED BY: fb_set_cmap */
-/*           fbcon_set_palette, pass 16 colors */
-static int viafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
-{
-	u32 len = cmap->len;
-	u32 i;
-	u16 *pred = cmap->red;
-	u16 *pgreen = cmap->green;
-	u16 *pblue = cmap->blue;
-	u16 *ptransp = cmap->transp;
-	u8 sr1a, sr1b, cr67, cr6a, rev = 0, shift = 10;
-	if (len > 256)
-		return 1;
-	if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name) {
-		/*
-		 * Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip
-		 * rev.
-		 */
-		outl(0x80000000 | (0xf6 & ~3), (unsigned long)0xCF8);
-		rev = (inl((unsigned long)0xCFC) >> ((0xf6 & 3) * 8)) & 0xff;
-	}
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		outb(0x1A, 0x3C4);
-		sr1a = inb(0x3C5);
-		outb(0x1B, 0x3C4);
-		sr1b = inb(0x3C5);
-		outb(0x67, 0x3D4);
-		cr67 = inb(0x3D5);
-		outb(0x6A, 0x3D4);
-		cr6a = inb(0x3D5);
-		/* Map the 3C6/7/8/9 to the IGA2 */
-		outb(0x1A, 0x3C4);
-		outb(sr1a | 0x01, 0x3C5);
-		outb(0x1B, 0x3C4);
-		/* Second Display Engine colck always on */
-		outb(sr1b | 0x80, 0x3C5);
-		outb(0x67, 0x3D4);
-		/* Second Display Color Depth 8 */
-		outb(cr67 & 0x3F, 0x3D5);
-		outb(0x6A, 0x3D4);
-		/* Second Display Channel Reset CR6A[6]) */
-		outb(cr6a & 0xBF, 0x3D5);
-		/* Second Display Channel Enable CR6A[7] */
-		outb(cr6a | 0x80, 0x3D5);
-		/* Second Display Channel stop reset) */
-		outb(cr6a | 0xC0, 0x3D5);
-
-		/* Bit mask of palette */
-		outb(0xFF, 0x3c6);
-		outb(0x00, 0x3C8);
-		if (UNICHROME_CLE266 == viaparinfo->chip_info->gfx_chip_name &&
-			rev >= 15) {
-			shift = 8;
-			viafb_write_reg_mask(CR6A, VIACR, BIT5, BIT5);
-			viafb_write_reg_mask(SR15, VIASR, BIT7, BIT7);
-		} else {
-			shift = 10;
-			viafb_write_reg_mask(CR6A, VIACR, 0, BIT5);
-			viafb_write_reg_mask(SR15, VIASR, 0, BIT7);
-		}
-		for (i = 0; i < len; i++) {
-			outb((*(pred + i)) >> shift, 0x3C9);
-			outb((*(pgreen + i)) >> shift, 0x3C9);
-			outb((*(pblue + i)) >> shift, 0x3C9);
-		}
-
-		outb(0x1A, 0x3C4);
-		/* Map the 3C6/7/8/9 to the IGA1 */
-		outb(sr1a & 0xFE, 0x3C5);
-		/* Bit mask of palette */
-		outb(0xFF, 0x3c6);
-		outb(0x00, 0x3C8);
-		for (i = 0; i < len; i++) {
-			outb((*(pred + i)) >> shift, 0x3C9);
-			outb((*(pgreen + i)) >> shift, 0x3C9);
-			outb((*(pblue + i)) >> shift, 0x3C9);
-		}
-
-		outb(0x1A, 0x3C4);
-		outb(sr1a, 0x3C5);
-		outb(0x1B, 0x3C4);
-		outb(sr1b, 0x3C5);
-		outb(0x67, 0x3D4);
-		outb(cr67, 0x3D5);
-		outb(0x6A, 0x3D4);
-		outb(cr6a, 0x3D5);
-		break;
-	case 16:
-		if (len > 17)
-			return 0;	/* Because static u32 pseudo_pal[17]; */
-		for (i = 0; i < len; i++)
-			((u32 *) info->pseudo_palette)[i] =
-			    (*(pred + i) & 0xF800) |
-			    ((*(pgreen + i) & 0xFC00) >> 5) |
-			    ((*(pblue + i) & 0xF800) >> 11);
-		break;
-	case 32:
-		if (len > 17)
-			return 0;
-		if (ptransp) {
-			for (i = 0; i < len; i++)
-				((u32 *) info->pseudo_palette)[i] =
-				    ((*(ptransp + i) & 0xFF00) << 16) |
-				    ((*(pred + i) & 0xFF00) << 8) |
-				    ((*(pgreen + i) & 0xFF00)) |
-				    ((*(pblue + i) & 0xFF00) >> 8);
-		} else {
-			for (i = 0; i < len; i++)
-				((u32 *) info->pseudo_palette)[i] =
-				    0x00000000 |
-				    ((*(pred + i) & 0xFF00) << 8) |
-				    ((*(pgreen + i) & 0xFF00)) |
-				    ((*(pblue + i) & 0xFF00) >> 8);
-		}
-		break;
-	}
-	return 0;
 }
 
 static int viafb_pan_display(struct fb_var_screeninfo *var,
 	struct fb_info *info)
 {
-	unsigned int offset;
+	struct viafb_par *viapar = info->par;
+	u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset)
+		* (var->bits_per_pixel / 8) + viapar->vram_addr;
 
-	DEBUG_MSG(KERN_INFO "viafb_pan_display!\n");
+	DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
+	if (!viafb_dual_fb) {
+		viafb_set_primary_address(vram_addr);
+		viafb_set_secondary_address(vram_addr);
+	} else if (viapar->iga_path == IGA1)
+		viafb_set_primary_address(vram_addr);
+	else
+		viafb_set_secondary_address(vram_addr);
 
-	offset = (var->xoffset + (var->yoffset * var->xres_virtual)) *
-	    var->bits_per_pixel / 16;
-
-	DEBUG_MSG(KERN_INFO "\nviafb_pan_display,offset =%d ", offset);
-	viafb_set_primary_address(offset);
 	return 0;
 }
 
@@ -476,6 +376,7 @@
 	u32 gpu32;
 
 	DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
+	printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n");
 	memset(&u, 0, sizeof(u));
 
 	switch (cmd) {
@@ -1015,23 +916,6 @@
 	return 0;
 }
 
-int viafb_get_mode_index(int hres, int vres)
-{
-	u32 i;
-	DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n");
-
-	for (i = 0; i < NUM_TOTAL_MODETABLE; i++)
-		if (CLE266Modes[i].mode_array &&
-			CLE266Modes[i].crtc[0].crtc.hor_addr == hres &&
-			CLE266Modes[i].crtc[0].crtc.ver_addr == vres)
-			break;
-
-	if (i == NUM_TOTAL_MODETABLE)
-		return VIA_RES_INVALID;
-
-	return CLE266Modes[i].ModeIndex;
-}
-
 static void check_available_device_to_enable(int device_id)
 {
 	int device_num = 0;
@@ -1330,7 +1214,7 @@
 	setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
 }
 
-static void parse_active_dev(void)
+static int parse_active_dev(void)
 {
 	viafb_CRT_ON = STATE_OFF;
 	viafb_DVI_ON = STATE_OFF;
@@ -1341,60 +1225,63 @@
 	   IGA path to devices in SAMM case. */
 	/*    Note: The previous of active_dev is primary device,
 	   and the following is secondary device. */
-	if (!strncmp(viafb_active_dev, "CRT+DVI", 7)) {
+	if (!viafb_active_dev) {
+		viafb_CRT_ON = STATE_ON;
+		viafb_SAMM_ON = STATE_OFF;
+	} else if (!strcmp(viafb_active_dev, "CRT+DVI")) {
 		/* CRT+DVI */
 		viafb_CRT_ON = STATE_ON;
 		viafb_DVI_ON = STATE_ON;
 		viafb_primary_dev = CRT_Device;
-	} else if (!strncmp(viafb_active_dev, "DVI+CRT", 7)) {
+	} else if (!strcmp(viafb_active_dev, "DVI+CRT")) {
 		/* DVI+CRT */
 		viafb_CRT_ON = STATE_ON;
 		viafb_DVI_ON = STATE_ON;
 		viafb_primary_dev = DVI_Device;
-	} else if (!strncmp(viafb_active_dev, "CRT+LCD", 7)) {
+	} else if (!strcmp(viafb_active_dev, "CRT+LCD")) {
 		/* CRT+LCD */
 		viafb_CRT_ON = STATE_ON;
 		viafb_LCD_ON = STATE_ON;
 		viafb_primary_dev = CRT_Device;
-	} else if (!strncmp(viafb_active_dev, "LCD+CRT", 7)) {
+	} else if (!strcmp(viafb_active_dev, "LCD+CRT")) {
 		/* LCD+CRT */
 		viafb_CRT_ON = STATE_ON;
 		viafb_LCD_ON = STATE_ON;
 		viafb_primary_dev = LCD_Device;
-	} else if (!strncmp(viafb_active_dev, "DVI+LCD", 7)) {
+	} else if (!strcmp(viafb_active_dev, "DVI+LCD")) {
 		/* DVI+LCD */
 		viafb_DVI_ON = STATE_ON;
 		viafb_LCD_ON = STATE_ON;
 		viafb_primary_dev = DVI_Device;
-	} else if (!strncmp(viafb_active_dev, "LCD+DVI", 7)) {
+	} else if (!strcmp(viafb_active_dev, "LCD+DVI")) {
 		/* LCD+DVI */
 		viafb_DVI_ON = STATE_ON;
 		viafb_LCD_ON = STATE_ON;
 		viafb_primary_dev = LCD_Device;
-	} else if (!strncmp(viafb_active_dev, "LCD+LCD2", 8)) {
+	} else if (!strcmp(viafb_active_dev, "LCD+LCD2")) {
 		viafb_LCD_ON = STATE_ON;
 		viafb_LCD2_ON = STATE_ON;
 		viafb_primary_dev = LCD_Device;
-	} else if (!strncmp(viafb_active_dev, "LCD2+LCD", 8)) {
+	} else if (!strcmp(viafb_active_dev, "LCD2+LCD")) {
 		viafb_LCD_ON = STATE_ON;
 		viafb_LCD2_ON = STATE_ON;
 		viafb_primary_dev = LCD2_Device;
-	} else if (!strncmp(viafb_active_dev, "CRT", 3)) {
+	} else if (!strcmp(viafb_active_dev, "CRT")) {
 		/* CRT only */
 		viafb_CRT_ON = STATE_ON;
 		viafb_SAMM_ON = STATE_OFF;
-	} else if (!strncmp(viafb_active_dev, "DVI", 3)) {
+	} else if (!strcmp(viafb_active_dev, "DVI")) {
 		/* DVI only */
 		viafb_DVI_ON = STATE_ON;
 		viafb_SAMM_ON = STATE_OFF;
-	} else if (!strncmp(viafb_active_dev, "LCD", 3)) {
+	} else if (!strcmp(viafb_active_dev, "LCD")) {
 		/* LCD only */
 		viafb_LCD_ON = STATE_ON;
 		viafb_SAMM_ON = STATE_OFF;
-	} else {
-		viafb_CRT_ON = STATE_ON;
-		viafb_SAMM_ON = STATE_OFF;
-	}
+	} else
+		return -EINVAL;
+
+	return 0;
 }
 
 static int parse_port(char *opt_str, int *output_interface)
@@ -1823,35 +1710,37 @@
 	remove_proc_entry("viafb", NULL);
 }
 
-static void parse_mode(const char *str, u32 *xres, u32 *yres)
+static int parse_mode(const char *str, u32 *xres, u32 *yres)
 {
 	char *ptr;
 
+	if (!str) {
+		*xres = 640;
+		*yres = 480;
+		return 0;
+	}
+
 	*xres = simple_strtoul(str, &ptr, 10);
 	if (ptr[0] != 'x')
-		goto out_default;
+		return -EINVAL;
 
 	*yres = simple_strtoul(&ptr[1], &ptr, 10);
 	if (ptr[0])
-		goto out_default;
+		return -EINVAL;
 
-	return;
-
-out_default:
-	printk(KERN_WARNING "viafb received invalid mode string: %s\n", str);
-	*xres = 640;
-	*yres = 480;
+	return 0;
 }
 
 static int __devinit via_pci_probe(struct pci_dev *pdev,
 				   const struct pci_device_id *ent)
 {
 	u32 default_xres, default_yres;
-	int vmode_index;
+	struct VideoModeTable *vmode_entry;
+	struct fb_var_screeninfo default_var;
 	u32 viafb_par_length;
 
 	DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
-
+	memset(&default_var, 0, sizeof(default_var));
 	viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
 
 	/* Allocate fb_info and ***_par here, also including some other needed
@@ -1877,7 +1766,6 @@
 
 	if (viafb_dual_fb)
 		viafb_SAMM_ON = 1;
-	parse_active_dev();
 	parse_lcd_port();
 	parse_dvi_port();
 
@@ -1926,9 +1814,7 @@
 	}
 
 	parse_mode(viafb_mode, &default_xres, &default_yres);
-	vmode_index = viafb_get_mode_index(default_xres, default_yres);
-	DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index);
-
+	vmode_entry = viafb_get_mode(default_xres, default_yres);
 	if (viafb_SAMM_ON == 1) {
 		parse_mode(viafb_mode1, &viafb_second_xres,
 			&viafb_second_yres);
@@ -1947,19 +1833,6 @@
 			viafb_second_virtual_yres = viafb_second_yres;
 	}
 
-	switch (viafb_bpp) {
-	case 0 ... 8:
-		viafb_bpp = 8;
-		break;
-	case 9 ... 16:
-		viafb_bpp = 16;
-		break;
-	case 17 ... 32:
-		viafb_bpp = 32;
-		break;
-	default:
-		viafb_bpp = 8;
-	}
 	default_var.xres = default_xres;
 	default_var.yres = default_yres;
 	switch (default_xres) {
@@ -1972,8 +1845,6 @@
 	}
 	default_var.yres_virtual = default_yres;
 	default_var.bits_per_pixel = viafb_bpp;
-	if (default_var.bits_per_pixel == 15)
-		default_var.bits_per_pixel = 16;
 	default_var.pixclock =
 	    viafb_get_pixclock(default_xres, default_yres, viafb_refresh);
 	default_var.left_margin = (default_xres >> 3) & 0xf8;
@@ -1982,6 +1853,8 @@
 	default_var.lower_margin = 4;
 	default_var.hsync_len = default_var.left_margin;
 	default_var.vsync_len = 4;
+	viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
+	viafbinfo->var = default_var;
 
 	if (viafb_dual_fb) {
 		viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev);
@@ -2016,8 +1889,6 @@
 		default_var.yres = viafb_second_yres;
 		default_var.xres_virtual = viafb_second_virtual_xres;
 		default_var.yres_virtual = viafb_second_virtual_yres;
-		if (viafb_bpp1 != viafb_bpp)
-			viafb_bpp1 = viafb_bpp;
 		default_var.bits_per_pixel = viafb_bpp1;
 		default_var.pixclock =
 		    viafb_get_pixclock(viafb_second_xres, viafb_second_yres,
@@ -2037,9 +1908,7 @@
 			&viafbinfo1->fix);
 	}
 
-	viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
-	viafb_check_var(&default_var, viafbinfo);
-	viafbinfo->var = default_var;
+	viafb_check_var(&viafbinfo->var, viafbinfo);
 	viafb_update_fix(viafbinfo);
 	viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
 		&viafbinfo->fix);
@@ -2197,12 +2066,20 @@
 
 static int __init viafb_init(void)
 {
+	u32 dummy;
 #ifndef MODULE
 	char *option = NULL;
 	if (fb_get_options("viafb", &option))
 		return -ENODEV;
 	viafb_setup(option);
 #endif
+	if (parse_mode(viafb_mode, &dummy, &dummy)
+		|| parse_mode(viafb_mode1, &dummy, &dummy)
+		|| viafb_bpp < 0 || viafb_bpp > 32
+		|| viafb_bpp1 < 0 || viafb_bpp1 > 32
+		|| parse_active_dev())
+		return -EINVAL;
+
 	printk(KERN_INFO
        "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n",
 	       VERSION_MAJOR, VERSION_MINOR);
@@ -2230,15 +2107,12 @@
 	.fb_cursor = viafb_cursor,
 	.fb_ioctl = viafb_ioctl,
 	.fb_sync = viafb_sync,
-	.fb_setcmap = viafb_setcmap,
 };
 
 module_init(viafb_init);
 module_exit(viafb_exit);
 
 #ifdef MODULE
-module_param(viafb_memsize, int, S_IRUSR);
-
 module_param(viafb_mode, charp, S_IRUSR);
 MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
 
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 0c94d24..61b5953 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -83,22 +83,16 @@
 
 extern unsigned int viafb_second_virtual_yres;
 extern unsigned int viafb_second_virtual_xres;
-extern unsigned int viafb_second_offset;
-extern int viafb_second_size;
 extern int viafb_SAMM_ON;
 extern int viafb_dual_fb;
 extern int viafb_LCD2_ON;
 extern int viafb_LCD_ON;
 extern int viafb_DVI_ON;
 extern int viafb_hotplug;
-extern int viafb_memsize;
 
 extern int strict_strtoul(const char *cp, unsigned int base,
 	unsigned long *res);
 
-void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
-			  int mode_index);
-int viafb_get_mode_index(int hres, int vres);
 u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
 	*plvds_setting_info, struct lvds_chip_information
 	*plvds_chip_info, u8 index);
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index b74f8a6..af50e24 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -412,7 +412,7 @@
 };
 
 struct patch_table res_patch_table[] = {
-	{VIA_RES_1024X768, ARRAY_SIZE(PM1024x768), PM1024x768}
+	{ARRAY_SIZE(PM1024x768), PM1024x768}
 };
 
 /* struct VPITTable {
@@ -879,169 +879,151 @@
 	 {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} }
 };
 
-/* Video Mode Table */
-/* struct VideoModeTable {*/
-/*  int                               ModeIndex;*/
-/*  struct crt_mode_table             *crtc;*/
-/*  int                               mode_array;*/
-/* };*/
-struct VideoModeTable CLE266Modes[] = {
+struct VideoModeTable viafb_modes[] = {
 	/* Display : 480x640 (GTF) */
-	{VIA_RES_480X640, CRTM480x640, ARRAY_SIZE(CRTM480x640)},
+	{CRTM480x640, ARRAY_SIZE(CRTM480x640)},
 
 	/* Display : 640x480 */
-	{VIA_RES_640X480, CRTM640x480, ARRAY_SIZE(CRTM640x480)},
+	{CRTM640x480, ARRAY_SIZE(CRTM640x480)},
 
 	/* Display : 720x480 (GTF) */
-	{VIA_RES_720X480, CRTM720x480, ARRAY_SIZE(CRTM720x480)},
+	{CRTM720x480, ARRAY_SIZE(CRTM720x480)},
 
 	/* Display : 720x576 (GTF) */
-	{VIA_RES_720X576, CRTM720x576, ARRAY_SIZE(CRTM720x576)},
+	{CRTM720x576, ARRAY_SIZE(CRTM720x576)},
 
 	/* Display : 800x600 */
-	{VIA_RES_800X600, CRTM800x600, ARRAY_SIZE(CRTM800x600)},
+	{CRTM800x600, ARRAY_SIZE(CRTM800x600)},
 
 	/* Display : 800x480 (CVT) */
-	{VIA_RES_800X480, CRTM800x480, ARRAY_SIZE(CRTM800x480)},
+	{CRTM800x480, ARRAY_SIZE(CRTM800x480)},
 
 	/* Display : 848x480 (CVT) */
-	{VIA_RES_848X480, CRTM848x480, ARRAY_SIZE(CRTM848x480)},
+	{CRTM848x480, ARRAY_SIZE(CRTM848x480)},
 
 	/* Display : 852x480 (GTF) */
-	{VIA_RES_856X480, CRTM852x480, ARRAY_SIZE(CRTM852x480)},
+	{CRTM852x480, ARRAY_SIZE(CRTM852x480)},
 
 	/* Display : 1024x512 (GTF) */
-	{VIA_RES_1024X512, CRTM1024x512, ARRAY_SIZE(CRTM1024x512)},
+	{CRTM1024x512, ARRAY_SIZE(CRTM1024x512)},
 
 	/* Display : 1024x600 */
-	{VIA_RES_1024X600, CRTM1024x600, ARRAY_SIZE(CRTM1024x600)},
-
-	/* Display : 1024x576 (GTF) */
-	/*{ VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)}, */
+	{CRTM1024x600, ARRAY_SIZE(CRTM1024x600)},
 
 	/* Display : 1024x768 */
-	{VIA_RES_1024X768, CRTM1024x768, ARRAY_SIZE(CRTM1024x768)},
+	{CRTM1024x768, ARRAY_SIZE(CRTM1024x768)},
 
 	/* Display : 1152x864 */
-	{VIA_RES_1152X864, CRTM1152x864, ARRAY_SIZE(CRTM1152x864)},
+	{CRTM1152x864, ARRAY_SIZE(CRTM1152x864)},
 
 	/* Display : 1280x768 (GTF) */
-	{VIA_RES_1280X768, CRTM1280x768, ARRAY_SIZE(CRTM1280x768)},
+	{CRTM1280x768, ARRAY_SIZE(CRTM1280x768)},
 
 	/* Display : 960x600 (CVT) */
-	{VIA_RES_960X600, CRTM960x600, ARRAY_SIZE(CRTM960x600)},
+	{CRTM960x600, ARRAY_SIZE(CRTM960x600)},
 
 	/* Display : 1000x600 (GTF) */
-	{VIA_RES_1000X600, CRTM1000x600, ARRAY_SIZE(CRTM1000x600)},
+	{CRTM1000x600, ARRAY_SIZE(CRTM1000x600)},
 
 	/* Display : 1024x576 (GTF) */
-	{VIA_RES_1024X576, CRTM1024x576, ARRAY_SIZE(CRTM1024x576)},
+	{CRTM1024x576, ARRAY_SIZE(CRTM1024x576)},
 
 	/* Display : 1088x612 (GTF) */
-	{VIA_RES_1088X612, CRTM1088x612, ARRAY_SIZE(CRTM1088x612)},
+	{CRTM1088x612, ARRAY_SIZE(CRTM1088x612)},
 
 	/* Display : 1152x720 (CVT) */
-	{VIA_RES_1152X720, CRTM1152x720, ARRAY_SIZE(CRTM1152x720)},
+	{CRTM1152x720, ARRAY_SIZE(CRTM1152x720)},
 
 	/* Display : 1200x720 (GTF) */
-	{VIA_RES_1200X720, CRTM1200x720, ARRAY_SIZE(CRTM1200x720)},
+	{CRTM1200x720, ARRAY_SIZE(CRTM1200x720)},
 
 	/* Display : 1280x600 (GTF) */
-	{VIA_RES_1280X600, CRTM1280x600, ARRAY_SIZE(CRTM1280x600)},
+	{CRTM1280x600, ARRAY_SIZE(CRTM1280x600)},
 
 	/* Display : 1280x800 (CVT) */
-	{VIA_RES_1280X800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)},
-
-	/* Display : 1280x800 (GTF) */
-	/*{ M1280x800, CRTM1280x800, ARRAY_SIZE(CRTM1280x800)}, */
+	{CRTM1280x800, ARRAY_SIZE(CRTM1280x800)},
 
 	/* Display : 1280x960 */
-	{VIA_RES_1280X960, CRTM1280x960, ARRAY_SIZE(CRTM1280x960)},
+	{CRTM1280x960, ARRAY_SIZE(CRTM1280x960)},
 
 	/* Display : 1280x1024 */
-	{VIA_RES_1280X1024, CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)},
+	{CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)},
 
 	/* Display : 1360x768 (CVT) */
-	{VIA_RES_1360X768, CRTM1360x768, ARRAY_SIZE(CRTM1360x768)},
-
-	/* Display : 1360x768 (CVT Reduce Blanking) */
-	{VIA_RES_1360X768_RB, CRTM1360x768_RB,
-	 ARRAY_SIZE(CRTM1360x768_RB)},
+	{CRTM1360x768, ARRAY_SIZE(CRTM1360x768)},
 
 	/* Display : 1366x768 */
-	{VIA_RES_1366X768, CRTM1366x768, ARRAY_SIZE(CRTM1366x768)},
+	{CRTM1366x768, ARRAY_SIZE(CRTM1366x768)},
 
 	/* Display : 1368x768 (GTF) */
-	/*{ M1368x768,CRTM1368x768,ARRAY_SIZE(CRTM1368x768)}, */
-	/* Display : 1368x768 (GTF) */
-	{VIA_RES_1368X768, CRTM1368x768, ARRAY_SIZE(CRTM1368x768)},
+	{CRTM1368x768, ARRAY_SIZE(CRTM1368x768)},
 
 	/* Display : 1440x900 (CVT) */
-	{VIA_RES_1440X900, CRTM1440x900, ARRAY_SIZE(CRTM1440x900)},
-
-	/* Display : 1440x900 (CVT Reduce Blanking) */
-	{VIA_RES_1440X900_RB, CRTM1440x900_RB,
-	 ARRAY_SIZE(CRTM1440x900_RB)},
+	{CRTM1440x900, ARRAY_SIZE(CRTM1440x900)},
 
 	/* Display : 1440x1050 (GTF) */
-	{VIA_RES_1440X1050, CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)},
-
-	/* Display : 1400x1050 (CVT Reduce Blanking) */
-	{VIA_RES_1400X1050_RB, CRTM1400x1050_RB,
-	 ARRAY_SIZE(CRTM1400x1050_RB)},
+	{CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)},
 
 	/* Display : 1600x900 (CVT) */
-	{VIA_RES_1600X900, CRTM1600x900, ARRAY_SIZE(CRTM1600x900)},
-
-	/* Display : 1600x900 (CVT Reduce Blanking) */
-	{VIA_RES_1600X900_RB, CRTM1600x900_RB,
-	 ARRAY_SIZE(CRTM1600x900_RB)},
+	{CRTM1600x900, ARRAY_SIZE(CRTM1600x900)},
 
 	/* Display : 1600x1024 (GTF) */
-	{VIA_RES_1600X1024, CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)},
+	{CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)},
 
 	/* Display : 1600x1200 */
-	{VIA_RES_1600X1200, CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)},
+	{CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)},
 
 	/* Display : 1680x1050 (CVT) */
-	{VIA_RES_1680X1050, CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)},
-
-	/* Display : 1680x1050 (CVT Reduce Blanking) */
-	{VIA_RES_1680X1050_RB, CRTM1680x1050_RB,
-	 ARRAY_SIZE(CRTM1680x1050_RB)},
+	{CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)},
 
 	/* Display : 1792x1344 (DMT) */
-	{VIA_RES_1792X1344, CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)},
+	{CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)},
 
 	/* Display : 1856x1392 (DMT) */
-	{VIA_RES_1856X1392, CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)},
+	{CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)},
 
 	/* Display : 1920x1440 */
-	{VIA_RES_1920X1440, CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)},
+	{CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)},
 
 	/* Display : 2048x1536 */
-	{VIA_RES_2048X1536, CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)},
+	{CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)},
 
 	/* Display : 1280x720 */
-	{VIA_RES_1280X720, CRTM1280x720, ARRAY_SIZE(CRTM1280x720)},
+	{CRTM1280x720, ARRAY_SIZE(CRTM1280x720)},
 
 	/* Display : 1920x1080 (CVT) */
-	{VIA_RES_1920X1080, CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)},
-
-	/* Display : 1920x1080 (CVT Reduce Blanking) */
-	{VIA_RES_1920X1080_RB, CRTM1920x1080_RB,
-	 ARRAY_SIZE(CRTM1920x1080_RB)},
+	{CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)},
 
 	/* Display : 1920x1200 (CVT) */
-	{VIA_RES_1920X1200, CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)},
-
-	/* Display : 1920x1200 (CVT Reduce Blanking) */
-	{VIA_RES_1920X1200_RB, CRTM1920x1200_RB,
-	 ARRAY_SIZE(CRTM1920x1200_RB)},
+	{CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)},
 
 	/* Display : 1400x1050 (CVT) */
-	{VIA_RES_1400X1050, CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)}
+	{CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)}
 };
+
+struct VideoModeTable viafb_rb_modes[] = {
+	/* Display : 1360x768 (CVT Reduce Blanking) */
+	{CRTM1360x768_RB, ARRAY_SIZE(CRTM1360x768_RB)},
+
+	/* Display : 1440x900 (CVT Reduce Blanking) */
+	{CRTM1440x900_RB, ARRAY_SIZE(CRTM1440x900_RB)},
+
+	/* Display : 1400x1050 (CVT Reduce Blanking) */
+	{CRTM1400x1050_RB, ARRAY_SIZE(CRTM1400x1050_RB)},
+
+	/* Display : 1600x900 (CVT Reduce Blanking) */
+	{CRTM1600x900_RB, ARRAY_SIZE(CRTM1600x900_RB)},
+
+	/* Display : 1680x1050 (CVT Reduce Blanking) */
+	{CRTM1680x1050_RB, ARRAY_SIZE(CRTM1680x1050_RB)},
+
+	/* Display : 1920x1080 (CVT Reduce Blanking) */
+	{CRTM1920x1080_RB, ARRAY_SIZE(CRTM1920x1080_RB)},
+
+	/* Display : 1920x1200 (CVT Reduce Blanking) */
+	{CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)}
+};
+
 struct crt_mode_table CEAM1280x720[] = {
 	{REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP,
 	 M1280X720_CEA_R60_VSP,
@@ -1056,8 +1038,8 @@
 };
 struct VideoModeTable CEA_HDMI_Modes[] = {
 	/* Display : 1280x720 */
-	{VIA_RES_1280X720, CEAM1280x720, ARRAY_SIZE(CEAM1280x720)},
-	{VIA_RES_1920X1080, CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
+	{CEAM1280x720, ARRAY_SIZE(CEAM1280x720)},
+	{CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
 };
 
 int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl);
@@ -1069,4 +1051,28 @@
 int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs);
 int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
 int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
-int NUM_TOTAL_MODETABLE = ARRAY_SIZE(CLE266Modes);
+
+
+struct VideoModeTable *viafb_get_mode(int hres, int vres)
+{
+	u32 i;
+	for (i = 0; i < ARRAY_SIZE(viafb_modes); i++)
+		if (viafb_modes[i].mode_array &&
+			viafb_modes[i].crtc[0].crtc.hor_addr == hres &&
+			viafb_modes[i].crtc[0].crtc.ver_addr == vres)
+			return &viafb_modes[i];
+
+	return NULL;
+}
+
+struct VideoModeTable *viafb_get_rb_mode(int hres, int vres)
+{
+	u32 i;
+	for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++)
+		if (viafb_rb_modes[i].mode_array &&
+			viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres &&
+			viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres)
+			return &viafb_rb_modes[i];
+
+	return NULL;
+}
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index a9d6554..5b1ced8 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -32,13 +32,11 @@
 };
 
 struct VideoModeTable {
-	int ModeIndex;
 	struct crt_mode_table *crtc;
 	int mode_array;
 };
 
 struct patch_table {
-	int mode_index;
 	int table_length;
 	struct io_reg *io_reg_table;
 };
@@ -59,13 +57,11 @@
 extern int NUM_TOTAL_VX855_ModeXregs;
 extern int NUM_TOTAL_CLE266_ModeXregs;
 extern int NUM_TOTAL_PATCH_MODE;
-extern int NUM_TOTAL_MODETABLE;
 
 /********************/
 /* Mode Table       */
 /********************/
 
-extern struct VideoModeTable CLE266Modes[];
 extern struct crt_mode_table CEAM1280x720[];
 extern struct crt_mode_table CEAM1920x1080[];
 extern struct VideoModeTable CEA_HDMI_Modes[];
@@ -81,4 +77,8 @@
 extern struct io_reg PM1024x768[];
 extern struct patch_table res_patch_table[];
 extern struct VPITTable VPIT;
+
+struct VideoModeTable *viafb_get_mode(int hres, int vres);
+struct VideoModeTable *viafb_get_rb_mode(int hres, int vres);
+
 #endif /* __VIAMODE_H__ */
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 2376f68..5d22395 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -628,7 +628,7 @@
 #endif
 
 
-int __init w100fb_probe(struct platform_device *pdev)
+int __devinit w100fb_probe(struct platform_device *pdev)
 {
 	int err = -EIO;
 	struct w100fb_mach_info *inf;
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 1b65732..625447f 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -649,6 +649,7 @@
 		goto out_req_regions;
 
 	pci_set_drvdata(pci_dev, vp_dev);
+	pci_set_master(pci_dev);
 
 	/* we use the subsystem vendor/device id as the virtio vendor/device
 	 * id.  this allows us to use the same PCI vendor/device id for all
diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c
index 406caa6a..e5f7441 100644
--- a/drivers/w1/masters/ds2482.c
+++ b/drivers/w1/masters/ds2482.c
@@ -214,7 +214,7 @@
 			 (++retries < DS2482_WAIT_IDLE_TIMEOUT));
 	}
 
-	if (retries > DS2482_WAIT_IDLE_TIMEOUT)
+	if (retries >= DS2482_WAIT_IDLE_TIMEOUT)
 		printk(KERN_ERR "%s: timeout on channel %d\n",
 		       __func__, pdev->channel);
 
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
index 65244c0..4926703 100644
--- a/drivers/w1/masters/mxc_w1.c
+++ b/drivers/w1/masters/mxc_w1.c
@@ -102,7 +102,7 @@
 	return ((__raw_readb(ctrl_addr)) >> 3) & 0x1;
 }
 
-static int __init mxc_w1_probe(struct platform_device *pdev)
+static int __devinit mxc_w1_probe(struct platform_device *pdev)
 {
 	struct mxc_w1_device *mdev;
 	struct resource *res;
@@ -166,7 +166,7 @@
 /*
  * disassociate the w1 device from the driver
  */
-static int mxc_w1_remove(struct platform_device *pdev)
+static int __devexit mxc_w1_remove(struct platform_device *pdev)
 {
 	struct mxc_w1_device *mdev = platform_get_drvdata(pdev);
 	struct resource *res;
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index 0d92969..22977d3 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -72,7 +72,7 @@
 	int			init_trans;
 };
 
-static int __init omap_hdq_probe(struct platform_device *pdev);
+static int __devinit omap_hdq_probe(struct platform_device *pdev);
 static int omap_hdq_remove(struct platform_device *pdev);
 
 static struct platform_driver omap_hdq_driver = {
@@ -558,7 +558,7 @@
 	return;
 }
 
-static int __init omap_hdq_probe(struct platform_device *pdev)
+static int __devinit omap_hdq_probe(struct platform_device *pdev)
 {
 	struct hdq_data *hdq_data;
 	struct resource *res;
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index acc7e3b..ad5897d 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -986,7 +986,7 @@
 	return 0;
 }
 
-static int w1_init(void)
+static int __init w1_init(void)
 {
 	int retval;
 
@@ -1034,7 +1034,7 @@
 	return retval;
 }
 
-static void w1_fini(void)
+static void __exit w1_fini(void)
 {
 	struct w1_master *dev;
 
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 3da3f48..bdcdbd5 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -55,6 +55,11 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called softdog.
 
+config MAX63XX_WATCHDOG
+       tristate "Max63xx watchdog"
+       help
+         Support for memory mapped max63{69,70,71,72,73,74} watchdog timer.
+
 config WM831X_WATCHDOG
 	tristate "WM831x watchdog"
 	depends on MFD_WM831X
@@ -289,6 +294,17 @@
 	  Say Y here if you want support for the watchdog timer on Avionic
 	  Design Xanthos boards.
 
+config TS72XX_WATCHDOG
+	tristate "TS-72XX SBC Watchdog"
+	depends on MACH_TS72XX
+	help
+	  Technologic Systems TS-7200, TS-7250 and TS-7260 boards have
+	  watchdog timer implemented in a external CPLD chip. Say Y here
+	  if you want to support for the watchdog timer on TS-72XX boards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ts72xx_wdt.
+
 # AVR32 Architecture
 
 config AT32AP700X_WDT
@@ -845,10 +861,10 @@
 # POWERPC Architecture
 
 config GEF_WDT
-	tristate "GE Fanuc Watchdog Timer"
+	tristate "GE Watchdog Timer"
 	depends on GEF_SBC610 || GEF_SBC310 || GEF_PPC9A
 	---help---
-	  Watchdog timer found in a number of GE Fanuc single board computers.
+	  Watchdog timer found in a number of GE single board computers.
 
 config MPC5200_WDT
 	bool "MPC52xx Watchdog Timer"
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 475c611..5e3cb95 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -46,6 +46,7 @@
 obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o
 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
 obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
+obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
@@ -142,4 +143,5 @@
 # Architecture Independant
 obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
 obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
+obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
index 4d18c87..2ffce4d 100644
--- a/drivers/watchdog/acquirewdt.c
+++ b/drivers/watchdog/acquirewdt.c
@@ -150,7 +150,7 @@
 	int options, retval = -EINVAL;
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
 		.identity = WATCHDOG_NAME,
diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
index 824d076a..4d40965 100644
--- a/drivers/watchdog/advantechwdt.c
+++ b/drivers/watchdog/advantechwdt.c
@@ -137,7 +137,7 @@
 	int new_timeout;
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING |
 			   WDIOF_SETTIMEOUT |
 			   WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/adx_wdt.c b/drivers/watchdog/adx_wdt.c
index 9d7d155..a5ca7a6 100644
--- a/drivers/watchdog/adx_wdt.c
+++ b/drivers/watchdog/adx_wdt.c
@@ -37,7 +37,7 @@
 	spinlock_t lock;
 };
 
-static struct watchdog_info adx_wdt_info = {
+static const struct watchdog_info adx_wdt_info = {
 	.identity = "Avionic Design Xanthos Watchdog",
 	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 };
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c
index 937a80f..1e9caea 100644
--- a/drivers/watchdog/alim1535_wdt.c
+++ b/drivers/watchdog/alim1535_wdt.c
@@ -180,7 +180,7 @@
 {
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options =		WDIOF_KEEPALIVEPING |
 					WDIOF_SETTIMEOUT |
 					WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c
index f90afdb..d8d4da9 100644
--- a/drivers/watchdog/alim7101_wdt.c
+++ b/drivers/watchdog/alim7101_wdt.c
@@ -238,7 +238,7 @@
 {
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
 							| WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index 2bb95cd..c764c52 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -219,7 +219,7 @@
 static long ar7_wdt_ioctl(struct file *file,
 					unsigned int cmd, unsigned long arg)
 {
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.identity = LONGNAME,
 		.firmware_version = 1,
 		.options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
index 0378479..6873376 100644
--- a/drivers/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
@@ -202,7 +202,7 @@
 	return status;
 }
 
-static struct watchdog_info at32_wdt_info = {
+static const struct watchdog_info at32_wdt_info = {
 	.identity	= "at32ap700x watchdog",
 	.options	= WDIOF_SETTIMEOUT |
 			  WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index b185daf..b3046dc 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -121,7 +121,7 @@
 	return 0;
 }
 
-static struct watchdog_info at91_wdt_info = {
+static const struct watchdog_info at91_wdt_info = {
 	.identity	= "at91 watchdog",
 	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 };
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c
index 751c003..5f24552 100644
--- a/drivers/watchdog/bcm47xx_wdt.c
+++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -149,7 +149,7 @@
 	return len;
 }
 
-static struct watchdog_info bcm47xx_wdt_info = {
+static const struct watchdog_info bcm47xx_wdt_info = {
 	.identity 	= DRV_NAME,
 	.options 	= WDIOF_SETTIMEOUT |
 				WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 2159e66..9c7ccd1 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -19,8 +19,6 @@
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/fs.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
@@ -74,7 +72,7 @@
 
 static unsigned int timeout = WATCHDOG_TIMEOUT;
 static int nowayout = WATCHDOG_NOWAYOUT;
-static struct watchdog_info bfin_wdt_info;
+static const struct watchdog_info bfin_wdt_info;
 static unsigned long open_check;
 static char expect_close;
 static DEFINE_SPINLOCK(bfin_wdt_spinlock);
@@ -309,26 +307,6 @@
 	}
 }
 
-/**
- *	bfin_wdt_notify_sys - Notifier Handler
- *	@this: notifier block
- *	@code: notifier event
- *	@unused: unused
- *
- *	Handles specific events, such as turning off the watchdog during a
- *	shutdown event.
- */
-static int bfin_wdt_notify_sys(struct notifier_block *this,
-					unsigned long code, void *unused)
-{
-	stampit();
-
-	if (code == SYS_DOWN || code == SYS_HALT)
-		bfin_wdt_stop();
-
-	return NOTIFY_DONE;
-}
-
 #ifdef CONFIG_PM
 static int state_before_suspend;
 
@@ -388,40 +366,28 @@
 	.fops     = &bfin_wdt_fops,
 };
 
-static struct watchdog_info bfin_wdt_info = {
+static const struct watchdog_info bfin_wdt_info = {
 	.identity = "Blackfin Watchdog",
 	.options  = WDIOF_SETTIMEOUT |
 		    WDIOF_KEEPALIVEPING |
 		    WDIOF_MAGICCLOSE,
 };
 
-static struct notifier_block bfin_wdt_notifier = {
-	.notifier_call = bfin_wdt_notify_sys,
-};
-
 /**
  *	bfin_wdt_probe - Initialize module
  *
- *	Registers the misc device and notifier handler.  Actual device
+ *	Registers the misc device.  Actual device
  *	initialization is handled by bfin_wdt_open().
  */
 static int __devinit bfin_wdt_probe(struct platform_device *pdev)
 {
 	int ret;
 
-	ret = register_reboot_notifier(&bfin_wdt_notifier);
-	if (ret) {
-		pr_devinit(KERN_ERR PFX
-			"cannot register reboot notifier (err=%d)\n", ret);
-		return ret;
-	}
-
 	ret = misc_register(&bfin_wdt_miscdev);
 	if (ret) {
 		pr_devinit(KERN_ERR PFX
 			"cannot register miscdev on minor=%d (err=%d)\n",
 				WATCHDOG_MINOR, ret);
-		unregister_reboot_notifier(&bfin_wdt_notifier);
 		return ret;
 	}
 
@@ -434,21 +400,33 @@
 /**
  *	bfin_wdt_remove - Initialize module
  *
- *	Unregisters the misc device and notifier handler.  Actual device
+ *	Unregisters the misc device.  Actual device
  *	deinitialization is handled by bfin_wdt_close().
  */
 static int __devexit bfin_wdt_remove(struct platform_device *pdev)
 {
 	misc_deregister(&bfin_wdt_miscdev);
-	unregister_reboot_notifier(&bfin_wdt_notifier);
 	return 0;
 }
 
+/**
+ *	bfin_wdt_shutdown - Soft Shutdown Handler
+ *
+ *	Handles the soft shutdown event.
+ */
+static void bfin_wdt_shutdown(struct platform_device *pdev)
+{
+	stampit();
+
+	bfin_wdt_stop();
+}
+
 static struct platform_device *bfin_wdt_device;
 
 static struct platform_driver bfin_wdt_driver = {
 	.probe     = bfin_wdt_probe,
 	.remove    = __devexit_p(bfin_wdt_remove),
+	.shutdown  = bfin_wdt_shutdown,
 	.suspend   = bfin_wdt_suspend,
 	.resume    = bfin_wdt_resume,
 	.driver    = {
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index e8380ef..8b724aa 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -121,7 +121,7 @@
 	return count;
 }
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 	.identity = "PowerPC Book-E Watchdog",
 };
diff --git a/drivers/watchdog/coh901327_wdt.c b/drivers/watchdog/coh901327_wdt.c
index 923cc68..9291506 100644
--- a/drivers/watchdog/coh901327_wdt.c
+++ b/drivers/watchdog/coh901327_wdt.c
@@ -257,7 +257,7 @@
 		struct watchdog_info __user *ident;
 		int __user *i;
 	} uarg;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options		= WDIOF_CARDRESET |
 					  WDIOF_SETTIMEOUT |
 					  WDIOF_KEEPALIVEPING,
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
index 71f6d7e..edd3475 100644
--- a/drivers/watchdog/cpu5wdt.c
+++ b/drivers/watchdog/cpu5wdt.c
@@ -154,7 +154,7 @@
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
 	unsigned int value;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_CARDRESET,
 		.identity = "CPU5 WDT",
 	};
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 081f295..37ea052 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -403,7 +403,7 @@
 
 static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	static struct watchdog_info info = {
+	static const struct watchdog_info info = {
 		.options		= WDIOF_SETTIMEOUT,
 		.firmware_version	= 1,
 		.identity		= DRIVER_NAME,
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index 887136d..56162c8 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -142,7 +142,7 @@
 	return len;
 }
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options = WDIOF_KEEPALIVEPING,
 	.identity = "DaVinci Watchdog",
 };
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index cdd55e0..88ed54e 100644
--- a/drivers/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
@@ -131,7 +131,7 @@
 	return len;
 }
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
 	.identity = "EP93xx Watchdog",
 };
diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c
index 9add354..d1c4e55 100644
--- a/drivers/watchdog/eurotechwdt.c
+++ b/drivers/watchdog/eurotechwdt.c
@@ -238,7 +238,7 @@
 {
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options	  = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
 							| WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index 734d980..abdbad0 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -1,9 +1,9 @@
 /*
- * GE Fanuc watchdog userspace interface
+ * GE watchdog userspace interface
  *
- * Author:  Martyn Welch <martyn.welch@gefanuc.com>
+ * Author:  Martyn Welch <martyn.welch@ge.com>
  *
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, 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
@@ -161,11 +161,11 @@
 	int timeout;
 	int options;
 	void __user *argp = (void __user *)arg;
-	static struct watchdog_info info = {
+	static const struct watchdog_info info = {
 		.options =	WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
 				WDIOF_KEEPALIVEPING,
 		.firmware_version = 0,
-		.identity = "GE Fanuc watchdog",
+		.identity = "GE watchdog",
 	};
 
 	switch (cmd) {
@@ -311,7 +311,7 @@
 
 static int __init gef_wdt_init(void)
 {
-	printk(KERN_INFO "GE Fanuc watchdog driver\n");
+	printk(KERN_INFO "GE watchdog driver\n");
 	return of_register_platform_driver(&gef_wdt_driver);
 }
 
@@ -323,8 +323,8 @@
 module_init(gef_wdt_init);
 module_exit(gef_wdt_exit);
 
-MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>");
-MODULE_DESCRIPTION("GE Fanuc watchdog driver");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com>");
+MODULE_DESCRIPTION("GE watchdog driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 MODULE_ALIAS("platform: gef_wdt");
diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
index 38252ff..9b49b12 100644
--- a/drivers/watchdog/geodewdt.c
+++ b/drivers/watchdog/geodewdt.c
@@ -142,7 +142,7 @@
 	int __user *p = argp;
 	int interval;
 
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
 		| WDIOF_MAGICCLOSE,
 		.firmware_version =     1,
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index a6c5674..70c2c24 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -554,7 +554,7 @@
 	return len;
 }
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options = WDIOF_SETTIMEOUT |
 		   WDIOF_KEEPALIVEPING |
 		   WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index 7ba0b11..bb9750a 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -34,7 +34,6 @@
 #include <linux/mm.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
-#include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
@@ -42,7 +41,7 @@
 #include <linux/io.h>
 
 /* Module and version information */
-#define ESB_VERSION "0.04"
+#define ESB_VERSION "0.05"
 #define ESB_MODULE_NAME "i6300ESB timer"
 #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
 #define PFX ESB_MODULE_NAME ": "
@@ -65,7 +64,7 @@
 /* Config register bits */
 #define ESB_WDT_REBOOT  (0x01 << 5)   /* Enable reboot on timeout          */
 #define ESB_WDT_FREQ    (0x01 << 2)   /* Decrement frequency               */
-#define ESB_WDT_INTTYPE (0x11 << 0)   /* Interrupt type on timer1 timeout  */
+#define ESB_WDT_INTTYPE (0x03 << 0)   /* Interrupt type on timer1 timeout  */
 
 /* Reload register bits */
 #define ESB_WDT_TIMEOUT (0x01 << 9)    /* Watchdog timed out                */
@@ -82,7 +81,9 @@
 static struct pci_dev *esb_pci;
 static unsigned short triggered; /* The status of the watchdog upon boot */
 static char esb_expect_close;
-static struct platform_device *esb_platform_device;
+
+/* We can only use 1 card due to the /dev/watchdog restriction */
+static int cards_found;
 
 /* module parameters */
 /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */
@@ -111,8 +112,8 @@
  */
 static inline void esb_unlock_registers(void)
 {
-	writeb(ESB_UNLOCK1, ESB_RELOAD_REG);
-	writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
+	writew(ESB_UNLOCK1, ESB_RELOAD_REG);
+	writew(ESB_UNLOCK2, ESB_RELOAD_REG);
 }
 
 static int esb_timer_start(void)
@@ -256,7 +257,7 @@
 	int new_heartbeat;
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options =		WDIOF_SETTIMEOUT |
 					WDIOF_KEEPALIVEPING |
 					WDIOF_MAGICCLOSE,
@@ -332,11 +333,6 @@
 
 /*
  * Data for PCI driver interface
- *
- * This data only exists for exporting the supported
- * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
- * register a pci_driver, because someone else might one day
- * want to register another driver on the same PCI id.
  */
 static struct pci_device_id esb_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
@@ -348,29 +344,19 @@
  *      Init & exit routines
  */
 
-static unsigned char __devinit esb_getdevice(void)
+static unsigned char __devinit esb_getdevice(struct pci_dev *pdev)
 {
-	/*
-	 *      Find the PCI device
-	 */
-
-	esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL,
-					PCI_DEVICE_ID_INTEL_ESB_9, NULL);
-
-	if (!esb_pci)
-		return 0;
-
-	if (pci_enable_device(esb_pci)) {
+	if (pci_enable_device(pdev)) {
 		printk(KERN_ERR PFX "failed to enable device\n");
 		goto err_devput;
 	}
 
-	if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
+	if (pci_request_region(pdev, 0, ESB_MODULE_NAME)) {
 		printk(KERN_ERR PFX "failed to request region\n");
 		goto err_disable;
 	}
 
-	BASEADDR = pci_ioremap_bar(esb_pci, 0);
+	BASEADDR = pci_ioremap_bar(pdev, 0);
 	if (BASEADDR == NULL) {
 		/* Something's wrong here, BASEADDR has to be set */
 		printk(KERN_ERR PFX "failed to get BASEADDR\n");
@@ -378,14 +364,14 @@
 	}
 
 	/* Done */
+	esb_pci = pdev;
 	return 1;
 
 err_release:
-	pci_release_region(esb_pci, 0);
+	pci_release_region(pdev, 0);
 err_disable:
-	pci_disable_device(esb_pci);
+	pci_disable_device(pdev);
 err_devput:
-	pci_dev_put(esb_pci);
 	return 0;
 }
 
@@ -430,12 +416,23 @@
 	esb_timer_set_heartbeat(heartbeat);
 }
 
-static int __devinit esb_probe(struct platform_device *dev)
+static int __devinit esb_probe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
 {
 	int ret;
 
+	cards_found++;
+	if (cards_found == 1)
+		printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n",
+			ESB_VERSION);
+
+	if (cards_found > 1) {
+		printk(KERN_ERR PFX "This driver only supports 1 device\n");
+		return -ENODEV;
+	}
+
 	/* Check whether or not the hardware watchdog is there */
-	if (!esb_getdevice() || esb_pci == NULL)
+	if (!esb_getdevice(pdev) || esb_pci == NULL)
 		return -ENODEV;
 
 	/* Check that the heartbeat value is within it's range;
@@ -467,11 +464,11 @@
 	iounmap(BASEADDR);
 	pci_release_region(esb_pci, 0);
 	pci_disable_device(esb_pci);
-	pci_dev_put(esb_pci);
+	esb_pci = NULL;
 	return ret;
 }
 
-static int __devexit esb_remove(struct platform_device *dev)
+static void __devexit esb_remove(struct pci_dev *pdev)
 {
 	/* Stop the timer before we leave */
 	if (!nowayout)
@@ -482,54 +479,30 @@
 	iounmap(BASEADDR);
 	pci_release_region(esb_pci, 0);
 	pci_disable_device(esb_pci);
-	pci_dev_put(esb_pci);
-	return 0;
+	esb_pci = NULL;
 }
 
-static void esb_shutdown(struct platform_device *dev)
+static void esb_shutdown(struct pci_dev *pdev)
 {
 	esb_timer_stop();
 }
 
-static struct platform_driver esb_platform_driver = {
+static struct pci_driver esb_driver = {
+	.name		= ESB_MODULE_NAME,
+	.id_table	= esb_pci_tbl,
 	.probe          = esb_probe,
 	.remove         = __devexit_p(esb_remove),
 	.shutdown       = esb_shutdown,
-	.driver         = {
-		.owner  = THIS_MODULE,
-		.name   = ESB_MODULE_NAME,
-	},
 };
 
 static int __init watchdog_init(void)
 {
-	int err;
-
-	printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n",
-		ESB_VERSION);
-
-	err = platform_driver_register(&esb_platform_driver);
-	if (err)
-		return err;
-
-	esb_platform_device = platform_device_register_simple(ESB_MODULE_NAME,
-								-1, NULL, 0);
-	if (IS_ERR(esb_platform_device)) {
-		err = PTR_ERR(esb_platform_device);
-		goto unreg_platform_driver;
-	}
-
-	return 0;
-
-unreg_platform_driver:
-	platform_driver_unregister(&esb_platform_driver);
-	return err;
+	return pci_register_driver(&esb_driver);
 }
 
 static void __exit watchdog_cleanup(void)
 {
-	platform_device_unregister(esb_platform_device);
-	platform_driver_unregister(&esb_platform_driver);
+	pci_unregister_driver(&esb_driver);
 	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 4bdb7f1..44bc6aa 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -584,7 +584,7 @@
 	int new_heartbeat;
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options =		WDIOF_SETTIMEOUT |
 					WDIOF_KEEPALIVEPING |
 					WDIOF_MAGICCLOSE,
@@ -698,7 +698,7 @@
 	if (iTCO_wdt_private.iTCO_version == 2) {
 		pci_read_config_dword(pdev, 0xf0, &base_address);
 		if ((base_address & 1) == 0) {
-			printk(KERN_ERR PFX "RCBA is disabled by harddware\n");
+			printk(KERN_ERR PFX "RCBA is disabled by hardware\n");
 			ret = -ENODEV;
 			goto out;
 		}
@@ -708,8 +708,8 @@
 
 	/* Check chipset's NO_REBOOT bit */
 	if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
-		printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
-					"reboot disabled by hardware\n");
+		printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, "
+					"platform may have disabled it\n");
 		ret = -ENODEV;	/* Cannot reset NO_REBOOT bit */
 		goto out_unmap;
 	}
@@ -805,6 +805,7 @@
 
 static int __devinit iTCO_wdt_probe(struct platform_device *dev)
 {
+	int ret = -ENODEV;
 	int found = 0;
 	struct pci_dev *pdev = NULL;
 	const struct pci_device_id *ent;
@@ -814,19 +815,17 @@
 	for_each_pci_dev(pdev) {
 		ent = pci_match_id(iTCO_wdt_pci_tbl, pdev);
 		if (ent) {
-			if (!(iTCO_wdt_init(pdev, ent, dev))) {
-				found++;
+			found++;
+			ret = iTCO_wdt_init(pdev, ent, dev);
+			if (!ret)
 				break;
-			}
 		}
 	}
 
-	if (!found) {
+	if (!found)
 		printk(KERN_INFO PFX "No card detected\n");
-		return -ENODEV;
-	}
 
-	return 0;
+	return ret;
 }
 
 static int __devexit iTCO_wdt_remove(struct platform_device *dev)
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
index 4bef3dd..0149d8d 100644
--- a/drivers/watchdog/ib700wdt.c
+++ b/drivers/watchdog/ib700wdt.c
@@ -174,7 +174,7 @@
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
 
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
 							| WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c
index bea8a12..1cc5609 100644
--- a/drivers/watchdog/indydog.c
+++ b/drivers/watchdog/indydog.c
@@ -111,7 +111,7 @@
 							unsigned long arg)
 {
 	int options, retval = -EINVAL;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options		= WDIOF_KEEPALIVEPING,
 		.firmware_version	= 0,
 		.identity		= "Hardware Watchdog for SGI IP22",
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index daed48d..f52c162 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -236,7 +236,7 @@
 {
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.identity = "IT8712F Watchdog",
 		.firmware_version = 1,
 		.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index cc133c5..b709b3b 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -421,7 +421,7 @@
 	return count;
 }
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
 	.firmware_version =	1,
 	.identity = WATCHDOG_NAME,
diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c
index 3c79dc5..e86952a 100644
--- a/drivers/watchdog/ixp2000_wdt.c
+++ b/drivers/watchdog/ixp2000_wdt.c
@@ -100,7 +100,7 @@
 }
 
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options	= WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
 				WDIOF_KEEPALIVEPING,
 	.identity	= "IXP2000 Watchdog",
diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c
index 147b4d5..e02c0ec 100644
--- a/drivers/watchdog/ixp4xx_wdt.c
+++ b/drivers/watchdog/ixp4xx_wdt.c
@@ -89,7 +89,7 @@
 	return len;
 }
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options	= WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
 			  WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 	.identity	= "IXP4xx Watchdog",
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index e1c8276..2852bb2 100644
--- a/drivers/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -145,7 +145,7 @@
 	return 0;
 }
 
-static struct watchdog_info ks8695_wdt_info = {
+static const struct watchdog_info ks8695_wdt_info = {
 	.identity	= "ks8695 watchdog",
 	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
 };
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c
index 47d7197..2d118cf 100644
--- a/drivers/watchdog/machzwd.c
+++ b/drivers/watchdog/machzwd.c
@@ -101,7 +101,7 @@
 
 #define PFX "machzwd"
 
-static struct watchdog_info zf_info = {
+static const struct watchdog_info zf_info = {
 	.options		= WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 	.firmware_version	= 1,
 	.identity		= "ZF-Logic watchdog",
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
new file mode 100644
index 0000000..6eb91d7
--- /dev/null
+++ b/drivers/watchdog/max63xx_wdt.c
@@ -0,0 +1,397 @@
+/*
+ * drivers/char/watchdog/max63xx_wdt.c
+ *
+ * Driver for max63{69,70,71,72,73,74} watchdog timers
+ *
+ * Copyright (C) 2009 Marc Zyngier <maz@misterjones.org>
+ *
+ * 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.
+ *
+ * This driver assumes the watchdog pins are memory mapped (as it is
+ * the case for the Arcom Zeus). Should it be connected over GPIOs or
+ * another interface, some abstraction will have to be introduced.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/device.h>
+
+#define DEFAULT_HEARTBEAT 60
+#define MAX_HEARTBEAT     60
+
+static int heartbeat = DEFAULT_HEARTBEAT;
+static int nowayout  = WATCHDOG_NOWAYOUT;
+
+/*
+ * Memory mapping: a single byte, 3 first lower bits to select bit 3
+ * to ping the watchdog.
+ */
+#define MAX6369_WDSET	(7 << 0)
+#define MAX6369_WDI   	(1 << 3)
+
+static DEFINE_SPINLOCK(io_lock);
+
+static unsigned long wdt_status;
+#define WDT_IN_USE	0
+#define WDT_RUNNING	1
+#define WDT_OK_TO_CLOSE 2
+
+static int nodelay;
+static struct resource	*wdt_mem;
+static void __iomem	*wdt_base;
+static struct platform_device *max63xx_pdev;
+
+/*
+ * The timeout values used are actually the absolute minimum the chip
+ * offers. Typical values on my board are slightly over twice as long
+ * (10s setting ends up with a 25s timeout), and can be up to 3 times
+ * the nominal setting (according to the datasheet). So please take
+ * these values with a grain of salt. Same goes for the initial delay
+ * "feature". Only max6373/74 have a few settings without this initial
+ * delay (selected with the "nodelay" parameter).
+ *
+ * I also decided to remove from the tables any timeout smaller than a
+ * second, as it looked completly overkill...
+ */
+
+/* Timeouts in second */
+struct max63xx_timeout {
+	u8 wdset;
+	u8 tdelay;
+	u8 twd;
+};
+
+static struct max63xx_timeout max6369_table[] = {
+	{ 5,  1,  1 },
+	{ 6, 10, 10 },
+	{ 7, 60, 60 },
+	{ },
+};
+
+static struct max63xx_timeout max6371_table[] = {
+	{ 6, 60,  3 },
+	{ 7, 60, 60 },
+	{ },
+};
+
+static struct max63xx_timeout max6373_table[] = {
+	{ 2, 60,  1 },
+	{ 5,  0,  1 },
+	{ 1,  3,  3 },
+	{ 7, 60, 10 },
+	{ 6,  0, 10 },
+	{ },
+};
+
+static struct max63xx_timeout *current_timeout;
+
+static struct max63xx_timeout *
+max63xx_select_timeout(struct max63xx_timeout *table, int value)
+{
+	while (table->twd) {
+		if (value <= table->twd) {
+			if (nodelay && table->tdelay == 0)
+				return table;
+
+			if (!nodelay)
+				return table;
+		}
+
+		table++;
+	}
+
+	return NULL;
+}
+
+static void max63xx_wdt_ping(void)
+{
+	u8 val;
+
+	spin_lock(&io_lock);
+
+	val = __raw_readb(wdt_base);
+
+	__raw_writeb(val | MAX6369_WDI, wdt_base);
+	__raw_writeb(val & ~MAX6369_WDI, wdt_base);
+
+	spin_unlock(&io_lock);
+}
+
+static void max63xx_wdt_enable(struct max63xx_timeout *entry)
+{
+	u8 val;
+
+	if (test_and_set_bit(WDT_RUNNING, &wdt_status))
+		return;
+
+	spin_lock(&io_lock);
+
+	val = __raw_readb(wdt_base);
+	val &= ~MAX6369_WDSET;
+	val |= entry->wdset;
+	__raw_writeb(val, wdt_base);
+
+	spin_unlock(&io_lock);
+
+	/* check for a edge triggered startup */
+	if (entry->tdelay == 0)
+		max63xx_wdt_ping();
+}
+
+static void max63xx_wdt_disable(void)
+{
+	spin_lock(&io_lock);
+
+	__raw_writeb(3, wdt_base);
+
+	spin_unlock(&io_lock);
+
+	clear_bit(WDT_RUNNING, &wdt_status);
+}
+
+static int max63xx_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+		return -EBUSY;
+
+	max63xx_wdt_enable(current_timeout);
+	clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+	return nonseekable_open(inode, file);
+}
+
+static ssize_t max63xx_wdt_write(struct file *file, const char *data,
+				 size_t len, loff_t *ppos)
+{
+	if (len) {
+		if (!nowayout) {
+			size_t i;
+
+			clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+			for (i = 0; i != len; i++) {
+				char c;
+
+				if (get_user(c, data + i))
+					return -EFAULT;
+
+				if (c == 'V')
+					set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+			}
+		}
+
+		max63xx_wdt_ping();
+	}
+
+	return len;
+}
+
+static const struct watchdog_info ident = {
+	.options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+	.identity = "max63xx Watchdog",
+};
+
+static long max63xx_wdt_ioctl(struct file *file, unsigned int cmd,
+			      unsigned long arg)
+{
+	int ret = -ENOTTY;
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		ret = copy_to_user((struct watchdog_info *)arg, &ident,
+				   sizeof(ident)) ? -EFAULT : 0;
+		break;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		ret = put_user(0, (int *)arg);
+		break;
+
+	case WDIOC_KEEPALIVE:
+		max63xx_wdt_ping();
+		ret = 0;
+		break;
+
+	case WDIOC_GETTIMEOUT:
+		ret = put_user(heartbeat, (int *)arg);
+		break;
+	}
+	return ret;
+}
+
+static int max63xx_wdt_release(struct inode *inode, struct file *file)
+{
+	if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
+		max63xx_wdt_disable();
+	else
+		dev_crit(&max63xx_pdev->dev,
+			 "device closed unexpectedly - timer will not stop\n");
+
+	clear_bit(WDT_IN_USE, &wdt_status);
+	clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+	return 0;
+}
+
+static const struct file_operations max63xx_wdt_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.write		= max63xx_wdt_write,
+	.unlocked_ioctl	= max63xx_wdt_ioctl,
+	.open		= max63xx_wdt_open,
+	.release	= max63xx_wdt_release,
+};
+
+static struct miscdevice max63xx_wdt_miscdev = {
+	.minor	= WATCHDOG_MINOR,
+	.name	= "watchdog",
+	.fops	= &max63xx_wdt_fops,
+};
+
+static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	int size;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+	struct max63xx_timeout *table;
+
+	table = (struct max63xx_timeout *)pdev->id_entry->driver_data;
+
+	if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
+		heartbeat = DEFAULT_HEARTBEAT;
+
+	dev_info(dev, "requesting %ds heartbeat\n", heartbeat);
+	current_timeout = max63xx_select_timeout(table, heartbeat);
+
+	if (!current_timeout) {
+		dev_err(dev, "unable to satisfy heartbeat request\n");
+		return -EINVAL;
+	}
+
+	dev_info(dev, "using %ds heartbeat with %ds initial delay\n",
+		 current_timeout->twd, current_timeout->tdelay);
+
+	heartbeat = current_timeout->twd;
+
+	max63xx_pdev = pdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(dev, "failed to get memory region resource\n");
+		return -ENOENT;
+	}
+
+	size = resource_size(res);
+	wdt_mem = request_mem_region(res->start, size, pdev->name);
+
+	if (wdt_mem == NULL) {
+		dev_err(dev, "failed to get memory region\n");
+		return -ENOENT;
+	}
+
+	wdt_base = ioremap(res->start, size);
+	if (!wdt_base) {
+		dev_err(dev, "failed to map memory region\n");
+		ret = -ENOMEM;
+		goto out_request;
+	}
+
+	ret = misc_register(&max63xx_wdt_miscdev);
+	if (ret < 0) {
+		dev_err(dev, "cannot register misc device\n");
+		goto out_unmap;
+	}
+
+	return 0;
+
+out_unmap:
+	iounmap(wdt_base);
+out_request:
+	release_resource(wdt_mem);
+	kfree(wdt_mem);
+
+	return ret;
+}
+
+static int __devexit max63xx_wdt_remove(struct platform_device *pdev)
+{
+	misc_deregister(&max63xx_wdt_miscdev);
+	if (wdt_mem) {
+		release_resource(wdt_mem);
+		kfree(wdt_mem);
+		wdt_mem = NULL;
+	}
+
+	if (wdt_base)
+		iounmap(wdt_base);
+
+	return 0;
+}
+
+static struct platform_device_id max63xx_id_table[] = {
+	{ "max6369_wdt", (kernel_ulong_t)max6369_table, },
+	{ "max6370_wdt", (kernel_ulong_t)max6369_table, },
+	{ "max6371_wdt", (kernel_ulong_t)max6371_table, },
+	{ "max6372_wdt", (kernel_ulong_t)max6371_table, },
+	{ "max6373_wdt", (kernel_ulong_t)max6373_table, },
+	{ "max6374_wdt", (kernel_ulong_t)max6373_table, },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, max63xx_id_table);
+
+static struct platform_driver max63xx_wdt_driver = {
+	.probe		= max63xx_wdt_probe,
+	.remove		= __devexit_p(max63xx_wdt_remove),
+	.id_table	= max63xx_id_table,
+	.driver		= {
+		.name	= "max63xx_wdt",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init max63xx_wdt_init(void)
+{
+	return platform_driver_register(&max63xx_wdt_driver);
+}
+
+static void __exit max63xx_wdt_exit(void)
+{
+	platform_driver_unregister(&max63xx_wdt_driver);
+}
+
+module_init(max63xx_wdt_init);
+module_exit(max63xx_wdt_exit);
+
+MODULE_AUTHOR("Marc Zyngier <maz@misterjones.org>");
+MODULE_DESCRIPTION("max63xx Watchdog Driver");
+
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat,
+		 "Watchdog heartbeat period in seconds from 1 to "
+		 __MODULE_STRING(MAX_HEARTBEAT) ", default "
+		 __MODULE_STRING(DEFAULT_HEARTBEAT));
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+		 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+module_param(nodelay, int, 0);
+MODULE_PARM_DESC(nodelay,
+		 "Force selection of a timeout setting without initial delay "
+		 "(max6373/74 only, default=0)");
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c
index 407b025..bc820d1 100644
--- a/drivers/watchdog/mixcomwd.c
+++ b/drivers/watchdog/mixcomwd.c
@@ -201,7 +201,7 @@
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
 	int status;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
 		.identity = "MixCOM watchdog",
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index 38c588e..4e3941c 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -148,7 +148,7 @@
 {
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING,
 		.firmware_version = 1,
 		.identity = "MPC8xxx",
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index a2dc07c..b0646da 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -213,7 +213,7 @@
 	return len;
 }
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options		= WDIOF_SETTIMEOUT |
 				  WDIOF_KEEPALIVEPING |
 				  WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c
index a51dbe4..97f8a48 100644
--- a/drivers/watchdog/mv64x60_wdt.c
+++ b/drivers/watchdog/mv64x60_wdt.c
@@ -179,7 +179,7 @@
 	int timeout;
 	int options;
 	void __user *argp = (void __user *)arg;
-	static struct watchdog_info info = {
+	static const struct watchdog_info info = {
 		.options =	WDIOF_SETTIMEOUT	|
 				WDIOF_MAGICCLOSE	|
 				WDIOF_KEEPALIVEPING,
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index 1a2b916..d3aa2f1 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -407,7 +407,7 @@
 		int __user *i;
 	} uarg;
 
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options          = WDIOF_KEEPALIVEPING |
 				    WDIOF_SETTIMEOUT |
 				    WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
index aa95123..06f7922 100644
--- a/drivers/watchdog/pcwd.c
+++ b/drivers/watchdog/pcwd.c
@@ -606,7 +606,7 @@
 	int temperature;
 	int new_heartbeat;
 	int __user *argp = (int __user *)arg;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options =		WDIOF_OVERHEAT |
 					WDIOF_CARDRESET |
 					WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
index 698f51bf..64374d6 100644
--- a/drivers/watchdog/pcwd_pci.c
+++ b/drivers/watchdog/pcwd_pci.c
@@ -481,7 +481,7 @@
 {
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options =		WDIOF_OVERHEAT |
 					WDIOF_CARDRESET |
 					WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c
index 052fe45..8e4eacc 100644
--- a/drivers/watchdog/pcwd_usb.c
+++ b/drivers/watchdog/pcwd_usb.c
@@ -404,7 +404,7 @@
 {
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options =		WDIOF_KEEPALIVEPING |
 					WDIOF_SETTIMEOUT |
 					WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c
index 2d22e99..435ec2a 100644
--- a/drivers/watchdog/pika_wdt.c
+++ b/drivers/watchdog/pika_wdt.c
@@ -52,7 +52,7 @@
 	struct timer_list timer;	/* The timer that pings the watchdog */
 } pikawdt_private;
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.identity	= DRV_NAME,
 	.options	= WDIOF_CARDRESET |
 			  WDIOF_SETTIMEOUT |
diff --git a/drivers/watchdog/pnx833x_wdt.c b/drivers/watchdog/pnx833x_wdt.c
index 538ec2c..09102f0 100644
--- a/drivers/watchdog/pnx833x_wdt.c
+++ b/drivers/watchdog/pnx833x_wdt.c
@@ -141,7 +141,7 @@
 	int options, new_timeout = 0;
 	uint32_t timeout, timeout_left = 0;
 
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
 		.firmware_version = 0,
 		.identity = "Hardware Watchdog for PNX833x",
diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c
index bf12d06..d4c29b5 100644
--- a/drivers/watchdog/rc32434_wdt.c
+++ b/drivers/watchdog/rc32434_wdt.c
@@ -198,7 +198,7 @@
 	void __user *argp = (void __user *)arg;
 	int new_timeout;
 	unsigned int value;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options =		WDIOF_SETTIMEOUT |
 					WDIOF_KEEPALIVEPING |
 					WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 4976bfd..69c6adb 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -149,7 +149,7 @@
 {
 	void __user *argp = (void __user *)arg;
 	unsigned int value;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_CARDRESET,
 		.identity = "RDC321x WDT",
 	};
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index c14ae86..ae57bf9 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -85,7 +85,7 @@
 
 static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
-	static struct watchdog_info info = {
+	static const struct watchdog_info info = {
 		.options		= WDIOF_SETTIMEOUT,
 		.firmware_version	= 1,
 		.identity		= DRIVER_NAME,
diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c
index e6763d2..8d44c9b 100644
--- a/drivers/watchdog/sbc_fitpc2_wdt.c
+++ b/drivers/watchdog/sbc_fitpc2_wdt.c
@@ -111,7 +111,7 @@
 }
 
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options	= WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
 				WDIOF_KEEPALIVEPING,
 	.identity	= WATCHDOG_NAME,
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
index 569eb29..9c40f48 100644
--- a/drivers/watchdog/sch311x_wdt.c
+++ b/drivers/watchdog/sch311x_wdt.c
@@ -250,7 +250,7 @@
 	int new_timeout;
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options		= WDIOF_KEEPALIVEPING |
 					  WDIOF_SETTIMEOUT |
 					  WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c
index 5dd9526..b3421fd 100644
--- a/drivers/watchdog/stmp3xxx_wdt.c
+++ b/drivers/watchdog/stmp3xxx_wdt.c
@@ -94,7 +94,7 @@
 	return len;
 }
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options	= WDIOF_CARDRESET |
 			  WDIOF_MAGICCLOSE |
 			  WDIOF_SETTIMEOUT |
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
new file mode 100644
index 0000000..565a2c3
--- /dev/null
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -0,0 +1,520 @@
+/*
+ * Watchdog driver for Technologic Systems TS-72xx based SBCs
+ * (TS-7200, TS-7250 and TS-7260). These boards have external
+ * glue logic CPLD chip, which includes programmable watchdog
+ * timer.
+ *
+ * Copyright (c) 2009 Mika Westerberg <mika.westerberg@iki.fi>
+ *
+ * This driver is based on ep93xx_wdt and wm831x_wdt 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/fs.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+#include <linux/uaccess.h>
+
+#define TS72XX_WDT_FEED_VAL		0x05
+#define TS72XX_WDT_DEFAULT_TIMEOUT	8
+
+static int timeout = TS72XX_WDT_DEFAULT_TIMEOUT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. "
+			  "(1 <= timeout <= 8, default="
+			  __MODULE_STRING(TS72XX_WDT_DEFAULT_TIMEOUT)
+			  ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
+
+/**
+ * struct ts72xx_wdt - watchdog control structure
+ * @lock: lock that protects this structure
+ * @regval: watchdog timeout value suitable for control register
+ * @flags: flags controlling watchdog device state
+ * @control_reg: watchdog control register
+ * @feed_reg: watchdog feed register
+ * @pdev: back pointer to platform dev
+ */
+struct ts72xx_wdt {
+	struct mutex	lock;
+	int		regval;
+
+#define TS72XX_WDT_BUSY_FLAG		1
+#define TS72XX_WDT_EXPECT_CLOSE_FLAG	2
+	int		flags;
+
+	void __iomem	*control_reg;
+	void __iomem	*feed_reg;
+
+	struct platform_device *pdev;
+};
+
+struct platform_device *ts72xx_wdt_pdev;
+
+/*
+ * TS-72xx Watchdog supports following timeouts (value written
+ * to control register):
+ *	value	description
+ *	-------------------------
+ * 	0x00	watchdog disabled
+ *	0x01	250ms
+ *	0x02	500ms
+ *	0x03	1s
+ *	0x04	reserved
+ *	0x05	2s
+ *	0x06	4s
+ *	0x07	8s
+ *
+ * Timeouts below 1s are not very usable so we don't
+ * allow them at all.
+ *
+ * We provide two functions that convert between these:
+ * timeout_to_regval() and regval_to_timeout().
+ */
+static const struct {
+	int	timeout;
+	int	regval;
+} ts72xx_wdt_map[] = {
+	{ 1, 3 },
+	{ 2, 5 },
+	{ 4, 6 },
+	{ 8, 7 },
+};
+
+/**
+ * timeout_to_regval() - converts given timeout to control register value
+ * @new_timeout: timeout in seconds to be converted
+ *
+ * Function converts given @new_timeout into valid value that can
+ * be programmed into watchdog control register. When conversion is
+ * not possible, function returns %-EINVAL.
+ */
+static int timeout_to_regval(int new_timeout)
+{
+	int i;
+
+	/* first limit it to 1 - 8 seconds */
+	new_timeout = clamp_val(new_timeout, 1, 8);
+
+	for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) {
+		if (ts72xx_wdt_map[i].timeout >= new_timeout)
+			return ts72xx_wdt_map[i].regval;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * regval_to_timeout() - converts control register value to timeout
+ * @regval: control register value to be converted
+ *
+ * Function converts given @regval to timeout in seconds (1, 2, 4 or 8).
+ * If @regval cannot be converted, function returns %-EINVAL.
+ */
+static int regval_to_timeout(int regval)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) {
+		if (ts72xx_wdt_map[i].regval == regval)
+			return ts72xx_wdt_map[i].timeout;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * ts72xx_wdt_kick() - kick the watchdog
+ * @wdt: watchdog to be kicked
+ *
+ * Called with @wdt->lock held.
+ */
+static inline void ts72xx_wdt_kick(struct ts72xx_wdt *wdt)
+{
+	__raw_writeb(TS72XX_WDT_FEED_VAL, wdt->feed_reg);
+}
+
+/**
+ * ts72xx_wdt_start() - starts the watchdog timer
+ * @wdt: watchdog to be started
+ *
+ * This function programs timeout to watchdog timer
+ * and starts it.
+ *
+ * Called with @wdt->lock held.
+ */
+static void ts72xx_wdt_start(struct ts72xx_wdt *wdt)
+{
+	/*
+	 * To program the wdt, it first must be "fed" and
+	 * only after that (within 30 usecs) the configuration
+	 * can be changed.
+	 */
+	ts72xx_wdt_kick(wdt);
+	__raw_writeb((u8)wdt->regval, wdt->control_reg);
+}
+
+/**
+ * ts72xx_wdt_stop() - stops the watchdog timer
+ * @wdt: watchdog to be stopped
+ *
+ * Called with @wdt->lock held.
+ */
+static void ts72xx_wdt_stop(struct ts72xx_wdt *wdt)
+{
+	ts72xx_wdt_kick(wdt);
+	__raw_writeb(0, wdt->control_reg);
+}
+
+static int ts72xx_wdt_open(struct inode *inode, struct file *file)
+{
+	struct ts72xx_wdt *wdt = platform_get_drvdata(ts72xx_wdt_pdev);
+	int regval;
+
+	/*
+	 * Try to convert default timeout to valid register
+	 * value first.
+	 */
+	regval = timeout_to_regval(timeout);
+	if (regval < 0) {
+		dev_err(&wdt->pdev->dev,
+			"failed to convert timeout (%d) to register value\n",
+			timeout);
+		return -EINVAL;
+	}
+
+	if (mutex_lock_interruptible(&wdt->lock))
+		return -ERESTARTSYS;
+
+	if ((wdt->flags & TS72XX_WDT_BUSY_FLAG) != 0) {
+		mutex_unlock(&wdt->lock);
+		return -EBUSY;
+	}
+
+	wdt->flags = TS72XX_WDT_BUSY_FLAG;
+	wdt->regval = regval;
+	file->private_data = wdt;
+
+	ts72xx_wdt_start(wdt);
+
+	mutex_unlock(&wdt->lock);
+	return nonseekable_open(inode, file);
+}
+
+static int ts72xx_wdt_release(struct inode *inode, struct file *file)
+{
+	struct ts72xx_wdt *wdt = file->private_data;
+
+	if (mutex_lock_interruptible(&wdt->lock))
+		return -ERESTARTSYS;
+
+	if ((wdt->flags & TS72XX_WDT_EXPECT_CLOSE_FLAG) != 0) {
+		ts72xx_wdt_stop(wdt);
+	} else {
+		dev_warn(&wdt->pdev->dev,
+			 "TS-72XX WDT device closed unexpectly. "
+			 "Watchdog timer will not stop!\n");
+		/*
+		 * Kick it one more time, to give userland some time
+		 * to recover (for example, respawning the kicker
+		 * daemon).
+		 */
+		ts72xx_wdt_kick(wdt);
+	}
+
+	wdt->flags = 0;
+
+	mutex_unlock(&wdt->lock);
+	return 0;
+}
+
+static ssize_t ts72xx_wdt_write(struct file *file,
+				const char __user *data,
+				size_t len,
+				loff_t *ppos)
+{
+	struct ts72xx_wdt *wdt = file->private_data;
+
+	if (!len)
+		return 0;
+
+	if (mutex_lock_interruptible(&wdt->lock))
+		return -ERESTARTSYS;
+
+	ts72xx_wdt_kick(wdt);
+
+	/*
+	 * Support for magic character closing. User process
+	 * writes 'V' into the device, just before it is closed.
+	 * This means that we know that the wdt timer can be
+	 * stopped after user closes the device.
+	 */
+	if (!nowayout) {
+		int i;
+
+		for (i = 0; i < len; i++) {
+			char c;
+
+			/* In case it was set long ago */
+			wdt->flags &= ~TS72XX_WDT_EXPECT_CLOSE_FLAG;
+
+			if (get_user(c, data + i)) {
+				mutex_unlock(&wdt->lock);
+				return -EFAULT;
+			}
+			if (c == 'V') {
+				wdt->flags |= TS72XX_WDT_EXPECT_CLOSE_FLAG;
+				break;
+			}
+		}
+	}
+
+	mutex_unlock(&wdt->lock);
+	return len;
+}
+
+static const struct watchdog_info winfo = {
+	.options		= WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
+				  WDIOF_MAGICCLOSE,
+	.firmware_version	= 1,
+	.identity		= "TS-72XX WDT",
+};
+
+static long ts72xx_wdt_ioctl(struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	struct ts72xx_wdt *wdt = file->private_data;
+	void __user *argp = (void __user *)arg;
+	int __user *p = (int __user *)argp;
+	int error = 0;
+
+	if (mutex_lock_interruptible(&wdt->lock))
+		return -ERESTARTSYS;
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		error = copy_to_user(argp, &winfo, sizeof(winfo));
+		break;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(0, p);
+
+	case WDIOC_KEEPALIVE:
+		ts72xx_wdt_kick(wdt);
+		break;
+
+	case WDIOC_SETOPTIONS: {
+		int options;
+
+		if (get_user(options, p)) {
+			error = -EFAULT;
+			break;
+		}
+
+		error = -EINVAL;
+
+		if ((options & WDIOS_DISABLECARD) != 0) {
+			ts72xx_wdt_stop(wdt);
+			error = 0;
+		}
+		if ((options & WDIOS_ENABLECARD) != 0) {
+			ts72xx_wdt_start(wdt);
+			error = 0;
+		}
+
+		break;
+	}
+
+	case WDIOC_SETTIMEOUT: {
+		int new_timeout;
+
+		if (get_user(new_timeout, p)) {
+			error = -EFAULT;
+		} else {
+			int regval;
+
+			regval = timeout_to_regval(new_timeout);
+			if (regval < 0) {
+				error = -EINVAL;
+			} else {
+				ts72xx_wdt_stop(wdt);
+				wdt->regval = regval;
+				ts72xx_wdt_start(wdt);
+			}
+		}
+		if (error)
+			break;
+
+		/*FALLTHROUGH*/
+	}
+
+	case WDIOC_GETTIMEOUT:
+		if (put_user(regval_to_timeout(wdt->regval), p))
+			error = -EFAULT;
+		break;
+
+	default:
+		error = -ENOTTY;
+		break;
+	}
+
+	mutex_unlock(&wdt->lock);
+	return error;
+}
+
+static const struct file_operations ts72xx_wdt_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.open		= ts72xx_wdt_open,
+	.release	= ts72xx_wdt_release,
+	.write		= ts72xx_wdt_write,
+	.unlocked_ioctl	= ts72xx_wdt_ioctl,
+};
+
+static struct miscdevice ts72xx_wdt_miscdev = {
+	.minor		= WATCHDOG_MINOR,
+	.name		= "watchdog",
+	.fops		= &ts72xx_wdt_fops,
+};
+
+static __devinit int ts72xx_wdt_probe(struct platform_device *pdev)
+{
+	struct ts72xx_wdt *wdt;
+	struct resource *r1, *r2;
+	int error = 0;
+
+	wdt = kzalloc(sizeof(struct ts72xx_wdt), GFP_KERNEL);
+	if (!wdt) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r1) {
+		dev_err(&pdev->dev, "failed to get memory resource\n");
+		error = -ENODEV;
+		goto fail;
+	}
+
+	r1 = request_mem_region(r1->start, resource_size(r1), pdev->name);
+	if (!r1) {
+		dev_err(&pdev->dev, "cannot request memory region\n");
+		error = -EBUSY;
+		goto fail;
+	}
+
+	wdt->control_reg = ioremap(r1->start, resource_size(r1));
+	if (!wdt->control_reg) {
+		dev_err(&pdev->dev, "failed to map memory\n");
+		error = -ENODEV;
+		goto fail_free_control;
+	}
+
+	r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!r2) {
+		dev_err(&pdev->dev, "failed to get memory resource\n");
+		error = -ENODEV;
+		goto fail_unmap_control;
+	}
+
+	r2 = request_mem_region(r2->start, resource_size(r2), pdev->name);
+	if (!r2) {
+		dev_err(&pdev->dev, "cannot request memory region\n");
+		error = -EBUSY;
+		goto fail_unmap_control;
+	}
+
+	wdt->feed_reg = ioremap(r2->start, resource_size(r2));
+	if (!wdt->feed_reg) {
+		dev_err(&pdev->dev, "failed to map memory\n");
+		error = -ENODEV;
+		goto fail_free_feed;
+	}
+
+	platform_set_drvdata(pdev, wdt);
+	ts72xx_wdt_pdev = pdev;
+	wdt->pdev = pdev;
+	mutex_init(&wdt->lock);
+
+	error = misc_register(&ts72xx_wdt_miscdev);
+	if (error) {
+		dev_err(&pdev->dev, "failed to register miscdev\n");
+		goto fail_unmap_feed;
+	}
+
+	dev_info(&pdev->dev, "TS-72xx Watchdog driver\n");
+
+	return 0;
+
+fail_unmap_feed:
+	platform_set_drvdata(pdev, NULL);
+	iounmap(wdt->feed_reg);
+fail_free_feed:
+	release_mem_region(r2->start, resource_size(r2));
+fail_unmap_control:
+	iounmap(wdt->control_reg);
+fail_free_control:
+	release_mem_region(r1->start, resource_size(r1));
+fail:
+	kfree(wdt);
+	return error;
+}
+
+static __devexit int ts72xx_wdt_remove(struct platform_device *pdev)
+{
+	struct ts72xx_wdt *wdt = platform_get_drvdata(pdev);
+	struct resource *res;
+	int error;
+
+	error = misc_deregister(&ts72xx_wdt_miscdev);
+	platform_set_drvdata(pdev, NULL);
+
+	iounmap(wdt->feed_reg);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	release_mem_region(res->start, resource_size(res));
+
+	iounmap(wdt->control_reg);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(wdt);
+	return error;
+}
+
+static struct platform_driver ts72xx_wdt_driver = {
+	.probe		= ts72xx_wdt_probe,
+	.remove		= __devexit_p(ts72xx_wdt_remove),
+	.driver		= {
+		.name	= "ts72xx-wdt",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static __init int ts72xx_wdt_init(void)
+{
+	return platform_driver_register(&ts72xx_wdt_driver);
+}
+module_init(ts72xx_wdt_init);
+
+static __exit void ts72xx_wdt_exit(void)
+{
+	platform_driver_unregister(&ts72xx_wdt_driver);
+}
+module_exit(ts72xx_wdt_exit);
+
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
+MODULE_DESCRIPTION("TS-72xx SBC Watchdog");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ts72xx-wdt");
diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c
index d635566..9e9ed7b 100644
--- a/drivers/watchdog/txx9wdt.c
+++ b/drivers/watchdog/txx9wdt.c
@@ -13,7 +13,6 @@
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/fs.h>
-#include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/uaccess.h>
 #include <linux/platform_device.h>
@@ -166,14 +165,6 @@
 	}
 }
 
-static int txx9wdt_notify_sys(struct notifier_block *this, unsigned long code,
-	void *unused)
-{
-	if (code == SYS_DOWN || code == SYS_HALT)
-		txx9wdt_stop();
-	return NOTIFY_DONE;
-}
-
 static const struct file_operations txx9wdt_fops = {
 	.owner		=	THIS_MODULE,
 	.llseek		=	no_llseek,
@@ -189,10 +180,6 @@
 	.fops	=	&txx9wdt_fops,
 };
 
-static struct notifier_block txx9wdt_notifier = {
-	.notifier_call = txx9wdt_notify_sys,
-};
-
 static int __init txx9wdt_probe(struct platform_device *dev)
 {
 	struct resource *res;
@@ -221,13 +208,8 @@
 	if (!txx9wdt_reg)
 		goto exit_busy;
 
-	ret = register_reboot_notifier(&txx9wdt_notifier);
-	if (ret)
-		goto exit;
-
 	ret = misc_register(&txx9wdt_miscdev);
 	if (ret) {
-		unregister_reboot_notifier(&txx9wdt_notifier);
 		goto exit;
 	}
 
@@ -249,14 +231,19 @@
 static int __exit txx9wdt_remove(struct platform_device *dev)
 {
 	misc_deregister(&txx9wdt_miscdev);
-	unregister_reboot_notifier(&txx9wdt_notifier);
 	clk_disable(txx9_imclk);
 	clk_put(txx9_imclk);
 	return 0;
 }
 
+static void txx9wdt_shutdown(struct platform_device *dev)
+{
+	txx9wdt_stop();
+}
+
 static struct platform_driver txx9wdt_driver = {
 	.remove = __exit_p(txx9wdt_remove),
+	.shutdown = txx9wdt_shutdown,
 	.driver = {
 		.name = "txx9wdt",
 		.owner = THIS_MODULE,
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index f201acc..0f5288d 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -201,7 +201,7 @@
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
 	int new_timeout;
-	static struct watchdog_info ident = {
+	static const struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
 							WDIOF_MAGICCLOSE,
 		.firmware_version = 1,
diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c
index 0560182..6e6743d 100644
--- a/drivers/watchdog/w83977f_wdt.c
+++ b/drivers/watchdog/w83977f_wdt.c
@@ -371,7 +371,7 @@
  *      according to their available features.
  */
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
 	.firmware_version =	1,
 	.identity = WATCHDOG_NAME,
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c
index 5bfb1f2..94ec22b 100644
--- a/drivers/watchdog/wdrtas.c
+++ b/drivers/watchdog/wdrtas.c
@@ -312,7 +312,7 @@
 {
 	int __user *argp = (void __user *)arg;
 	int i;
-	static struct watchdog_info wdinfo = {
+	static const struct watchdog_info wdinfo = {
 		.options = WDRTAS_SUPPORTED_MASK,
 		.firmware_version = 0,
 		.identity = "wdrtas",
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c
index 3bbefe9..bfda2e9 100644
--- a/drivers/watchdog/wdt.c
+++ b/drivers/watchdog/wdt.c
@@ -358,7 +358,7 @@
 	int new_heartbeat;
 	int status;
 
-	static struct watchdog_info ident = {
+	struct watchdog_info ident = {
 		.options =		WDIOF_SETTIMEOUT|
 					WDIOF_MAGICCLOSE|
 					WDIOF_KEEPALIVEPING,
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index f368dd8..7b22e3c 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -412,7 +412,7 @@
 	int new_heartbeat;
 	int status;
 
-	static struct watchdog_info ident = {
+	struct watchdog_info ident = {
 		.options =		WDIOF_SETTIMEOUT|
 					WDIOF_MAGICCLOSE|
 					WDIOF_KEEPALIVEPING,
diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
index 775bcd8..8c4b2d5 100644
--- a/drivers/watchdog/wm831x_wdt.c
+++ b/drivers/watchdog/wm831x_wdt.c
@@ -213,7 +213,7 @@
 	return count;
 }
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 	.identity = "WM831x Watchdog",
 };
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index a2d2e8e..89dd7b0 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -177,7 +177,7 @@
 	return count;
 }
 
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
 	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 	.identity = "WM8350 Watchdog",
 };
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index cab100a..fad3df2 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -1,6 +1,8 @@
+menu "Xen driver support"
+	depends on XEN
+
 config XEN_BALLOON
 	bool "Xen memory balloon driver"
-	depends on XEN
 	default y
 	help
 	  The balloon driver allows the Xen domain to request more memory from
@@ -20,7 +22,6 @@
 
 config XEN_DEV_EVTCHN
 	tristate "Xen /dev/xen/evtchn device"
-	depends on XEN
 	default y
 	help
 	  The evtchn driver allows a userspace process to triger event
@@ -30,7 +31,6 @@
 
 config XENFS
 	tristate "Xen filesystem"
-	depends on XEN
 	default y
 	help
 	  The xen filesystem provides a way for domains to share
@@ -53,11 +53,13 @@
 
 config XEN_SYS_HYPERVISOR
        bool "Create xen entries under /sys/hypervisor"
-       depends on XEN && SYSFS
+       depends on SYSFS
        select SYS_HYPERVISOR
        default y
        help
          Create entries under /sys/hypervisor describing the Xen
 	 hypervisor environment.  When running native or in another
 	 virtual environment, /sys/hypervisor will still be present,
-	 but will have no xen contents.
\ No newline at end of file
+	 but will have no xen contents.
+
+endmenu
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index ce602dd..2f84137 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -649,9 +649,13 @@
 				int bit_idx = __ffs(pending_bits);
 				int port = (word_idx * BITS_PER_LONG) + bit_idx;
 				int irq = evtchn_to_irq[port];
+				struct irq_desc *desc;
 
-				if (irq != -1)
-					handle_irq(irq, regs);
+				if (irq != -1) {
+					desc = irq_to_desc(irq);
+					if (desc)
+						generic_handle_irq_desc(irq, desc);
+				}
 			}
 		}
 
diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c
index ae5cb05..bb71ab2 100644
--- a/drivers/xen/sys-hypervisor.c
+++ b/drivers/xen/sys-hypervisor.c
@@ -426,7 +426,7 @@
 	return 0;
 }
 
-static struct sysfs_ops hyp_sysfs_ops = {
+static const struct sysfs_ops hyp_sysfs_ops = {
 	.show = hyp_sysfs_show,
 	.store = hyp_sysfs_store,
 };
diff --git a/drivers/zorro/zorro.ids b/drivers/zorro/zorro.ids
index 0c0f99e..de24e3d 100644
--- a/drivers/zorro/zorro.ids
+++ b/drivers/zorro/zorro.ids
@@ -108,7 +108,7 @@
 	0c00  500XP/SupraDrive WordSync [SCSI Host Adapter]
 	0d00  SupraDrive WordSync II [SCSI Host Adapter]
 	1000  2400zi+ [Modem]
-0422  Computer Systems Assosiates
+0422  Computer Systems Associates
 	1100  Magnum 40 [Accelerator and SCSI Host Adapter]
 	1500  12 Gauge [SCSI Host Adapter]
 0439  Marc Michael Groth
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 14d9442..08b2eb1 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -151,7 +151,7 @@
 			if (access == V9FS_ACCESS_SINGLE)
 				return ERR_PTR(-EPERM);
 
-			if (v9fs_extended(v9ses))
+			if (v9fs_proto_dotu(v9ses))
 				uname = NULL;
 			else
 				uname = v9ses->uname;
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 7d6c213..6c7f6a2 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -241,7 +241,7 @@
 	list_add(&v9ses->slist, &v9fs_sessionlist);
 	spin_unlock(&v9fs_sessionlist_lock);
 
-	v9ses->flags = V9FS_EXTENDED | V9FS_ACCESS_USER;
+	v9ses->flags = V9FS_PROTO_2000U | V9FS_ACCESS_USER;
 	strcpy(v9ses->uname, V9FS_DEFUSER);
 	strcpy(v9ses->aname, V9FS_DEFANAME);
 	v9ses->uid = ~0;
@@ -262,13 +262,13 @@
 		goto error;
 	}
 
-	if (!v9ses->clnt->dotu)
-		v9ses->flags &= ~V9FS_EXTENDED;
+	if (!p9_is_proto_dotu(v9ses->clnt))
+		v9ses->flags &= ~V9FS_PROTO_2000U;
 
 	v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;
 
 	/* for legacy mode, fall back to V9FS_ACCESS_ANY */
-	if (!v9fs_extended(v9ses) &&
+	if (!v9fs_proto_dotu(v9ses) &&
 		((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
 
 		v9ses->flags &= ~V9FS_ACCESS_MASK;
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 019f4cc..79000bf 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -23,7 +23,8 @@
 
 /**
  * enum p9_session_flags - option flags for each 9P session
- * @V9FS_EXTENDED: whether or not to use 9P2000.u extensions
+ * @V9FS_PROTO_2000U: whether or not to use 9P2000.u extensions
+ * @V9FS_PROTO_2010L: whether or not to use 9P2010.l extensions
  * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy
  * @V9FS_ACCESS_USER: a new attach will be issued for every user (default)
  * @V9FS_ACCESS_ANY: use a single attach for all users
@@ -32,11 +33,12 @@
  * Session flags reflect options selected by users at mount time
  */
 enum p9_session_flags {
-	V9FS_EXTENDED		= 0x01,
-	V9FS_ACCESS_SINGLE	= 0x02,
-	V9FS_ACCESS_USER	= 0x04,
-	V9FS_ACCESS_ANY		= 0x06,
-	V9FS_ACCESS_MASK	= 0x06,
+	V9FS_PROTO_2000U	= 0x01,
+	V9FS_PROTO_2010L	= 0x02,
+	V9FS_ACCESS_SINGLE	= 0x04,
+	V9FS_ACCESS_USER	= 0x08,
+	V9FS_ACCESS_ANY		= 0x0C,
+	V9FS_ACCESS_MASK	= 0x0C,
 };
 
 /* possible values of ->cache */
@@ -121,7 +123,12 @@
 	return (inode->i_sb->s_fs_info);
 }
 
-static inline int v9fs_extended(struct v9fs_session_info *v9ses)
+static inline int v9fs_proto_dotu(struct v9fs_session_info *v9ses)
 {
-	return v9ses->flags & V9FS_EXTENDED;
+	return v9ses->flags & V9FS_PROTO_2000U;
+}
+
+static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses)
+{
+	return v9ses->flags & V9FS_PROTO_2010L;
 }
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 15cce53..6580aa4 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -135,7 +135,7 @@
 		while (rdir->head < rdir->tail) {
 			err = p9stat_read(rdir->buf + rdir->head,
 						buflen - rdir->head, &st,
-						fid->clnt->dotu);
+						fid->clnt->proto_version);
 			if (err) {
 				P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err);
 				err = -EIO;
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 74a0461..3612268 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -61,7 +61,7 @@
 
 	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file);
 	v9ses = v9fs_inode2v9ses(inode);
-	omode = v9fs_uflags2omode(file->f_flags, v9fs_extended(v9ses));
+	omode = v9fs_uflags2omode(file->f_flags, v9fs_proto_dotu(v9ses));
 	fid = file->private_data;
 	if (!fid) {
 		fid = v9fs_fid_clone(file->f_path.dentry);
@@ -77,7 +77,7 @@
 			i_size_write(inode, 0);
 			inode->i_blocks = 0;
 		}
-		if ((file->f_flags & O_APPEND) && (!v9fs_extended(v9ses)))
+		if ((file->f_flags & O_APPEND) && (!v9fs_proto_dotu(v9ses)))
 			generic_file_llseek(file, 0, SEEK_END);
 	}
 
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index a407fa3..5fe45d6 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -60,7 +60,7 @@
 	res = mode & 0777;
 	if (S_ISDIR(mode))
 		res |= P9_DMDIR;
-	if (v9fs_extended(v9ses)) {
+	if (v9fs_proto_dotu(v9ses)) {
 		if (S_ISLNK(mode))
 			res |= P9_DMSYMLINK;
 		if (v9ses->nodev == 0) {
@@ -102,21 +102,21 @@
 
 	if ((mode & P9_DMDIR) == P9_DMDIR)
 		res |= S_IFDIR;
-	else if ((mode & P9_DMSYMLINK) && (v9fs_extended(v9ses)))
+	else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses)))
 		res |= S_IFLNK;
-	else if ((mode & P9_DMSOCKET) && (v9fs_extended(v9ses))
+	else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses))
 		 && (v9ses->nodev == 0))
 		res |= S_IFSOCK;
-	else if ((mode & P9_DMNAMEDPIPE) && (v9fs_extended(v9ses))
+	else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses))
 		 && (v9ses->nodev == 0))
 		res |= S_IFIFO;
-	else if ((mode & P9_DMDEVICE) && (v9fs_extended(v9ses))
+	else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses))
 		 && (v9ses->nodev == 0))
 		res |= S_IFBLK;
 	else
 		res |= S_IFREG;
 
-	if (v9fs_extended(v9ses)) {
+	if (v9fs_proto_dotu(v9ses)) {
 		if ((mode & P9_DMSETUID) == P9_DMSETUID)
 			res |= S_ISUID;
 
@@ -265,7 +265,7 @@
 	case S_IFBLK:
 	case S_IFCHR:
 	case S_IFSOCK:
-		if (!v9fs_extended(v9ses)) {
+		if (!v9fs_proto_dotu(v9ses)) {
 			P9_DPRINTK(P9_DEBUG_ERROR,
 				   "special files without extended mode\n");
 			err = -EINVAL;
@@ -278,7 +278,7 @@
 		inode->i_fop = &v9fs_file_operations;
 		break;
 	case S_IFLNK:
-		if (!v9fs_extended(v9ses)) {
+		if (!v9fs_proto_dotu(v9ses)) {
 			P9_DPRINTK(P9_DEBUG_ERROR,
 				   "extended modes used w/o 9P2000.u\n");
 			err = -EINVAL;
@@ -288,7 +288,7 @@
 		break;
 	case S_IFDIR:
 		inc_nlink(inode);
-		if (v9fs_extended(v9ses))
+		if (v9fs_proto_dotu(v9ses))
 			inode->i_op = &v9fs_dir_inode_operations_ext;
 		else
 			inode->i_op = &v9fs_dir_inode_operations;
@@ -575,7 +575,8 @@
 		flags = O_RDWR;
 
 	fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
-				v9fs_uflags2omode(flags, v9fs_extended(v9ses)));
+				v9fs_uflags2omode(flags,
+						v9fs_proto_dotu(v9ses)));
 	if (IS_ERR(fid)) {
 		err = PTR_ERR(fid);
 		fid = NULL;
@@ -858,7 +859,7 @@
 	if (iattr->ia_valid & ATTR_SIZE)
 		wstat.length = iattr->ia_size;
 
-	if (v9fs_extended(v9ses)) {
+	if (v9fs_proto_dotu(v9ses)) {
 		if (iattr->ia_valid & ATTR_UID)
 			wstat.n_uid = iattr->ia_uid;
 
@@ -886,6 +887,8 @@
 	struct super_block *sb)
 {
 	char ext[32];
+	char tag_name[14];
+	unsigned int i_nlink;
 	struct v9fs_session_info *v9ses = sb->s_fs_info;
 
 	inode->i_nlink = 1;
@@ -897,11 +900,26 @@
 	inode->i_uid = v9ses->dfltuid;
 	inode->i_gid = v9ses->dfltgid;
 
-	if (v9fs_extended(v9ses)) {
+	if (v9fs_proto_dotu(v9ses)) {
 		inode->i_uid = stat->n_uid;
 		inode->i_gid = stat->n_gid;
 	}
-
+	if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
+		if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
+			/*
+			 * Hadlink support got added later to
+			 * to the .u extension. So there can be
+			 * server out there that doesn't support
+			 * this even with .u extension. So check
+			 * for non NULL stat->extension
+			 */
+			strncpy(ext, stat->extension, sizeof(ext));
+			/* HARDLINKCOUNT %u */
+			sscanf(ext, "%13s %u", tag_name, &i_nlink);
+			if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
+				inode->i_nlink = i_nlink;
+		}
+	}
 	inode->i_mode = p9mode2unixmode(v9ses, stat->mode);
 	if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
 		char type = 0;
@@ -976,7 +994,7 @@
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
 
-	if (!v9fs_extended(v9ses))
+	if (!v9fs_proto_dotu(v9ses))
 		return -EBADF;
 
 	st = p9_client_stat(fid);
@@ -1066,7 +1084,7 @@
 	struct p9_fid *fid;
 
 	v9ses = v9fs_inode2v9ses(dir);
-	if (!v9fs_extended(v9ses)) {
+	if (!v9fs_proto_dotu(v9ses)) {
 		P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");
 		return -EPERM;
 	}
diff --git a/fs/Kconfig b/fs/Kconfig
index 64d44ef..7405f07 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -177,6 +177,7 @@
 source "fs/jffs2/Kconfig"
 # UBIFS File system configuration
 source "fs/ubifs/Kconfig"
+source "fs/logfs/Kconfig"
 source "fs/cramfs/Kconfig"
 source "fs/squashfs/Kconfig"
 source "fs/freevxfs/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index af6d047..c3633aa 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -99,6 +99,7 @@
 obj-$(CONFIG_UFS_FS)		+= ufs/
 obj-$(CONFIG_EFS_FS)		+= efs/
 obj-$(CONFIG_JFFS2_FS)		+= jffs2/
+obj-$(CONFIG_LOGFS)		+= logfs/
 obj-$(CONFIG_UBIFS_FS)		+= ubifs/
 obj-$(CONFIG_AFFS_FS)		+= affs/
 obj-$(CONFIG_ROMFS_FS)		+= romfs/
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index 9cc1877..2ff622f 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -121,7 +121,7 @@
 
 /* Inode stuff */
 struct inode *adfs_iget(struct super_block *sb, struct object_info *obj);
-int adfs_write_inode(struct inode *inode,int unused);
+int adfs_write_inode(struct inode *inode, struct writeback_control *wbc);
 int adfs_notify_change(struct dentry *dentry, struct iattr *attr);
 
 /* map.c */
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index 3f57ce4..0f5e309 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -9,6 +9,7 @@
  */
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/writeback.h>
 #include "adfs.h"
 
 /*
@@ -360,7 +361,7 @@
  * The adfs-specific inode data has already been updated by
  * adfs_notify_change()
  */
-int adfs_write_inode(struct inode *inode, int wait)
+int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	struct super_block *sb = inode->i_sb;
 	struct object_info obj;
@@ -375,7 +376,7 @@
 	obj.attr	= ADFS_I(inode)->attr;
 	obj.size	= inode->i_size;
 
-	ret = adfs_dir_update(sb, &obj, wait);
+	ret = adfs_dir_update(sb, &obj, wbc->sync_mode == WB_SYNC_ALL);
 	unlock_kernel();
 	return ret;
 }
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 0e40caa..861dae6 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -175,7 +175,8 @@
 extern void			 affs_clear_inode(struct inode *inode);
 extern struct inode		*affs_iget(struct super_block *sb,
 					unsigned long ino);
-extern int			 affs_write_inode(struct inode *inode, int);
+extern int			 affs_write_inode(struct inode *inode,
+					struct writeback_control *wbc);
 extern int			 affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type);
 
 /* file.c */
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c
index dc5ef14..8306d53 100644
--- a/fs/affs/bitmap.c
+++ b/fs/affs/bitmap.c
@@ -128,7 +128,7 @@
 /*
  * Allocate a block in the given allocation zone.
  * Since we have to byte-swap the bitmap on little-endian
- * machines, this is rather expensive. Therefor we will
+ * machines, this is rather expensive. Therefore we will
  * preallocate up to 16 blocks from the same word, if
  * possible. We are not doing preallocations in the
  * header zone, though.
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 3c4ec7d..c9744d7 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -166,7 +166,7 @@
 }
 
 int
-affs_write_inode(struct inode *inode, int unused)
+affs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	struct super_block	*sb = inode->i_sb;
 	struct buffer_head	*bh;
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 6ece2a1..c54dad4 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -733,7 +733,6 @@
 			struct page *page, void *fsdata);
 extern int afs_writepage(struct page *, struct writeback_control *);
 extern int afs_writepages(struct address_space *, struct writeback_control *);
-extern int afs_write_inode(struct inode *, int);
 extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
 extern ssize_t afs_file_write(struct kiocb *, const struct iovec *,
 			      unsigned long, loff_t);
diff --git a/fs/afs/super.c b/fs/afs/super.c
index e1ea1c2..14f6431 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -48,7 +48,6 @@
 static const struct super_operations afs_super_ops = {
 	.statfs		= afs_statfs,
 	.alloc_inode	= afs_alloc_inode,
-	.write_inode	= afs_write_inode,
 	.destroy_inode	= afs_destroy_inode,
 	.clear_inode	= afs_clear_inode,
 	.put_super	= afs_put_super,
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 5e15a21..3bed54a 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -585,27 +585,6 @@
 }
 
 /*
- * write an inode back
- */
-int afs_write_inode(struct inode *inode, int sync)
-{
-	struct afs_vnode *vnode = AFS_FS_I(inode);
-	int ret;
-
-	_enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
-
-	ret = 0;
-	if (sync) {
-		ret = filemap_fdatawait(inode->i_mapping);
-		if (ret < 0)
-			__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
-	}
-
-	_leave(" = %d", ret);
-	return ret;
-}
-
-/*
  * completion of write to server
  */
 void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call)
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 9f0bf13..2de0095 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -209,6 +209,7 @@
 	inode->i_mode = S_IRUSR | S_IWUSR;
 	inode->i_uid = current_fsuid();
 	inode->i_gid = current_fsgid();
+	inode->i_flags |= S_PRIVATE;
 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	return inode;
 }
diff --git a/fs/attr.c b/fs/attr.c
index 96d394b..0815e93 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -12,7 +12,6 @@
 #include <linux/capability.h>
 #include <linux/fsnotify.h>
 #include <linux/fcntl.h>
-#include <linux/quotaops.h>
 #include <linux/security.h>
 
 /* Taken over from the old code... */
@@ -82,7 +81,7 @@
 	if (inode->i_size < offset) {
 		unsigned long limit;
 
-		limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+		limit = rlimit(RLIMIT_FSIZE);
 		if (limit != RLIM_INFINITY && offset > limit)
 			goto out_sig;
 		if (offset > inode->i_sb->s_maxbytes)
@@ -212,14 +211,8 @@
 		error = inode->i_op->setattr(dentry, attr);
 	} else {
 		error = inode_change_ok(inode, attr);
-		if (!error) {
-			if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
-			    (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
-				error = vfs_dq_transfer(inode, attr) ?
-					-EDQUOT : 0;
-			if (!error)
-				error = inode_setattr(inode, attr);
-		}
+		if (!error)
+			error = inode_setattr(inode, attr);
 	}
 
 	if (ia_valid & ATTR_SIZE)
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 0118d67..3d283ab 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -60,11 +60,6 @@
 		current->pid, __func__, ##args);	\
 } while (0)
 
-struct rehash_entry {
-	struct task_struct *task;
-	struct list_head list;
-};
-
 /* 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
@@ -81,7 +76,6 @@
 
 	struct list_head active;
 	int active_count;
-	struct list_head rehash_list;
 
 	struct list_head expiring;
 
@@ -104,7 +98,6 @@
 #define AUTOFS_INF_EXPIRING	(1<<0) /* dentry is in the process of expiring */
 #define AUTOFS_INF_MOUNTPOINT	(1<<1) /* mountpoint status for direct expire */
 #define AUTOFS_INF_PENDING	(1<<2) /* dentry pending mount */
-#define AUTOFS_INF_REHASH	(1<<3) /* dentry in transit to ->lookup() */
 
 struct autofs_wait_queue {
 	wait_queue_head_t queue;
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 00bf8fc..c8a80df 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -544,10 +544,9 @@
 			goto out;
 		devid = new_encode_dev(path.mnt->mnt_sb->s_dev);
 		err = 0;
-		if (path.dentry->d_inode &&
-		    path.mnt->mnt_root == path.dentry) {
+		if (path.mnt->mnt_root == path.dentry) {
 			err = 1;
-			magic = path.dentry->d_inode->i_sb->s_magic;
+			magic = path.mnt->mnt_sb->s_magic;
 		}
 	} else {
 		dev_t dev = sbi->sb->s_dev;
@@ -560,10 +559,8 @@
 
 		err = have_submounts(path.dentry);
 
-		if (path.mnt->mnt_mountpoint != path.mnt->mnt_root) {
-			if (follow_down(&path))
-				magic = path.mnt->mnt_sb->s_magic;
-		}
+		if (follow_down(&path))
+			magic = path.mnt->mnt_sb->s_magic;
 	}
 
 	param->ismountpoint.out.devid = devid;
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 74bc9aa..a796c94 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -279,7 +279,6 @@
 			root->d_mounted--;
 		}
 		ino->flags |= AUTOFS_INF_EXPIRING;
-		autofs4_add_expiring(root);
 		init_completion(&ino->expire_complete);
 		spin_unlock(&sbi->fs_lock);
 		return root;
@@ -407,7 +406,6 @@
 		expired, (int)expired->d_name.len, expired->d_name.name);
 	ino = autofs4_dentry_ino(expired);
 	ino->flags |= AUTOFS_INF_EXPIRING;
-	autofs4_add_expiring(expired);
 	init_completion(&ino->expire_complete);
 	spin_unlock(&sbi->fs_lock);
 	spin_lock(&dcache_lock);
@@ -435,7 +433,7 @@
 
 		DPRINTK("expire done status=%d", status);
 
-		if (d_unhashed(dentry) && IS_DEADDIR(dentry->d_inode))
+		if (d_unhashed(dentry))
 			return -EAGAIN;
 
 		return status;
@@ -475,7 +473,6 @@
 	spin_lock(&sbi->fs_lock);
 	ino = autofs4_dentry_ino(dentry);
 	ino->flags &= ~AUTOFS_INF_EXPIRING;
-	autofs4_del_expiring(dentry);
 	complete_all(&ino->expire_complete);
 	spin_unlock(&sbi->fs_lock);
 
@@ -506,7 +503,6 @@
 			ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
 		}
 		ino->flags &= ~AUTOFS_INF_EXPIRING;
-		autofs4_del_expiring(dentry);
 		complete_all(&ino->expire_complete);
 		spin_unlock(&sbi->fs_lock);
 		dput(dentry);
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index d0a3de2..821b2b9 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -49,7 +49,6 @@
 		ino->dentry = NULL;
 		ino->size = 0;
 		INIT_LIST_HEAD(&ino->active);
-		INIT_LIST_HEAD(&ino->rehash_list);
 		ino->active_count = 0;
 		INIT_LIST_HEAD(&ino->expiring);
 		atomic_set(&ino->count, 0);
@@ -97,63 +96,6 @@
 	kfree(ino);
 }
 
-/*
- * Deal with the infamous "Busy inodes after umount ..." message.
- *
- * Clean up the dentry tree. This happens with autofs if the user
- * space program goes away due to a SIGKILL, SIGSEGV etc.
- */
-static void autofs4_force_release(struct autofs_sb_info *sbi)
-{
-	struct dentry *this_parent = sbi->sb->s_root;
-	struct list_head *next;
-
-	if (!sbi->sb->s_root)
-		return;
-
-	spin_lock(&dcache_lock);
-repeat:
-	next = this_parent->d_subdirs.next;
-resume:
-	while (next != &this_parent->d_subdirs) {
-		struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
-
-		/* Negative dentry - don`t care */
-		if (!simple_positive(dentry)) {
-			next = next->next;
-			continue;
-		}
-
-		if (!list_empty(&dentry->d_subdirs)) {
-			this_parent = dentry;
-			goto repeat;
-		}
-
-		next = next->next;
-		spin_unlock(&dcache_lock);
-
-		DPRINTK("dentry %p %.*s",
-			dentry, (int)dentry->d_name.len, dentry->d_name.name);
-
-		dput(dentry);
-		spin_lock(&dcache_lock);
-	}
-
-	if (this_parent != sbi->sb->s_root) {
-		struct dentry *dentry = this_parent;
-
-		next = this_parent->d_u.d_child.next;
-		this_parent = this_parent->d_parent;
-		spin_unlock(&dcache_lock);
-		DPRINTK("parent dentry %p %.*s",
-			dentry, (int)dentry->d_name.len, dentry->d_name.name);
-		dput(dentry);
-		spin_lock(&dcache_lock);
-		goto resume;
-	}
-	spin_unlock(&dcache_lock);
-}
-
 void autofs4_kill_sb(struct super_block *sb)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(sb);
@@ -170,15 +112,12 @@
 	/* Free wait queues, close pipe */
 	autofs4_catatonic_mode(sbi);
 
-	/* Clean up and release dangling references */
-	autofs4_force_release(sbi);
-
 	sb->s_fs_info = NULL;
 	kfree(sbi);
 
 out_kill_sb:
 	DPRINTK("shutting down");
-	kill_anon_super(sb);
+	kill_litter_super(sb);
 }
 
 static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt)
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 30cc9dd..a015b49 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -104,99 +104,6 @@
 	return;
 }
 
-static void autofs4_add_rehash_entry(struct autofs_info *ino,
-				     struct rehash_entry *entry)
-{
-	entry->task = current;
-	INIT_LIST_HEAD(&entry->list);
-	list_add(&entry->list, &ino->rehash_list);
-	return;
-}
-
-static void autofs4_remove_rehash_entry(struct autofs_info *ino)
-{
-	struct list_head *head = &ino->rehash_list;
-	struct rehash_entry *entry;
-	list_for_each_entry(entry, head, list) {
-		if (entry->task == current) {
-			list_del(&entry->list);
-			kfree(entry);
-			break;
-		}
-	}
-	return;
-}
-
-static void autofs4_remove_rehash_entrys(struct autofs_info *ino)
-{
-	struct autofs_sb_info *sbi = ino->sbi;
-	struct rehash_entry *entry, *next;
-	struct list_head *head;
-
-	spin_lock(&sbi->fs_lock);
-	spin_lock(&sbi->lookup_lock);
-	if (!(ino->flags & AUTOFS_INF_REHASH)) {
-		spin_unlock(&sbi->lookup_lock);
-		spin_unlock(&sbi->fs_lock);
-		return;
-	}
-	ino->flags &= ~AUTOFS_INF_REHASH;
-	head = &ino->rehash_list;
-	list_for_each_entry_safe(entry, next, head, list) {
-		list_del(&entry->list);
-		kfree(entry);
-	}
-	spin_unlock(&sbi->lookup_lock);
-	spin_unlock(&sbi->fs_lock);
-	dput(ino->dentry);
-
-	return;
-}
-
-static void autofs4_revalidate_drop(struct dentry *dentry,
-				    struct rehash_entry *entry)
-{
-	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
-	struct autofs_info *ino = autofs4_dentry_ino(dentry);
-	/*
-	 * Add to the active list so we can pick this up in
-	 * ->lookup(). Also add an entry to a rehash list so
-	 * we know when there are no dentrys in flight so we
-	 * know when we can rehash the dentry.
-	 */
-	spin_lock(&sbi->lookup_lock);
-	if (list_empty(&ino->active))
-		list_add(&ino->active, &sbi->active_list);
-	autofs4_add_rehash_entry(ino, entry);
-	spin_unlock(&sbi->lookup_lock);
-	if (!(ino->flags & AUTOFS_INF_REHASH)) {
-		ino->flags |= AUTOFS_INF_REHASH;
-		dget(dentry);
-		spin_lock(&dentry->d_lock);
-		__d_drop(dentry);
-		spin_unlock(&dentry->d_lock);
-	}
-	return;
-}
-
-static void autofs4_revalidate_rehash(struct dentry *dentry)
-{
-	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
-	struct autofs_info *ino = autofs4_dentry_ino(dentry);
-	if (ino->flags & AUTOFS_INF_REHASH) {
-		spin_lock(&sbi->lookup_lock);
-		autofs4_remove_rehash_entry(ino);
-		if (list_empty(&ino->rehash_list)) {
-			spin_unlock(&sbi->lookup_lock);
-			ino->flags &= ~AUTOFS_INF_REHASH;
-			d_rehash(dentry);
-			dput(ino->dentry);
-		} else
-			spin_unlock(&sbi->lookup_lock);
-	}
-	return;
-}
-
 static unsigned int autofs4_need_mount(unsigned int flags)
 {
 	unsigned int res = 0;
@@ -236,7 +143,7 @@
 	return dcache_dir_open(inode, file);
 }
 
-static int try_to_fill_dentry(struct dentry *dentry)
+static int try_to_fill_dentry(struct dentry *dentry, int flags)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
@@ -249,17 +156,55 @@
 	 * Wait for a pending mount, triggering one if there
 	 * isn't one already
 	 */
-	DPRINTK("waiting for mount name=%.*s",
-		 dentry->d_name.len, dentry->d_name.name);
+	if (dentry->d_inode == NULL) {
+		DPRINTK("waiting for mount name=%.*s",
+			 dentry->d_name.len, dentry->d_name.name);
 
-	status = autofs4_wait(sbi, dentry, NFY_MOUNT);
+		status = autofs4_wait(sbi, dentry, NFY_MOUNT);
 
-	DPRINTK("mount done status=%d", status);
+		DPRINTK("mount done status=%d", status);
 
-	/* Update expiry counter */
-	ino->last_used = jiffies;
+		/* Turn this into a real negative dentry? */
+		if (status == -ENOENT) {
+			spin_lock(&sbi->fs_lock);
+			ino->flags &= ~AUTOFS_INF_PENDING;
+			spin_unlock(&sbi->fs_lock);
+			return status;
+		} else if (status) {
+			/* Return a negative dentry, but leave it "pending" */
+			return status;
+		}
+	/* Trigger mount for path component or follow link */
+	} else if (ino->flags & AUTOFS_INF_PENDING ||
+			autofs4_need_mount(flags) ||
+			current->link_count) {
+		DPRINTK("waiting for mount name=%.*s",
+			dentry->d_name.len, dentry->d_name.name);
 
-	return status;
+		spin_lock(&sbi->fs_lock);
+		ino->flags |= AUTOFS_INF_PENDING;
+		spin_unlock(&sbi->fs_lock);
+		status = autofs4_wait(sbi, dentry, NFY_MOUNT);
+
+		DPRINTK("mount done status=%d", status);
+
+		if (status) {
+			spin_lock(&sbi->fs_lock);
+			ino->flags &= ~AUTOFS_INF_PENDING;
+			spin_unlock(&sbi->fs_lock);
+			return status;
+		}
+	}
+
+	/* Initialize expiry counter after successful mount */
+	if (ino)
+		ino->last_used = jiffies;
+
+	spin_lock(&sbi->fs_lock);
+	ino->flags &= ~AUTOFS_INF_PENDING;
+	spin_unlock(&sbi->fs_lock);
+
+	return 0;
 }
 
 /* For autofs direct mounts the follow link triggers the mount */
@@ -313,16 +258,10 @@
 	 */
 	if (ino->flags & AUTOFS_INF_PENDING ||
 	    (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) {
-		ino->flags |= AUTOFS_INF_PENDING;
 		spin_unlock(&dcache_lock);
 		spin_unlock(&sbi->fs_lock);
 
-		status = try_to_fill_dentry(dentry);
-
-		spin_lock(&sbi->fs_lock);
-		ino->flags &= ~AUTOFS_INF_PENDING;
-		spin_unlock(&sbi->fs_lock);
-
+		status = try_to_fill_dentry(dentry, 0);
 		if (status)
 			goto out_error;
 
@@ -361,47 +300,18 @@
 {
 	struct inode *dir = dentry->d_parent->d_inode;
 	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
-	struct autofs_info *ino = autofs4_dentry_ino(dentry);
-	struct rehash_entry *entry;
+	int oz_mode = autofs4_oz_mode(sbi);
 	int flags = nd ? nd->flags : 0;
-	unsigned int mutex_aquired;
+	int status = 1;
 
-	DPRINTK("name = %.*s oz_mode = %d",
-		dentry->d_name.len, dentry->d_name.name, oz_mode);
-
-	/* Daemon never causes a mount to trigger */
-	if (autofs4_oz_mode(sbi))
-		return 1;
-
-	entry = kmalloc(sizeof(struct rehash_entry), GFP_KERNEL);
-	if (!entry)
-		return -ENOMEM;
-
-	mutex_aquired = mutex_trylock(&dir->i_mutex);
-
-	spin_lock(&sbi->fs_lock);
-	spin_lock(&dcache_lock);
 	/* Pending dentry */
+	spin_lock(&sbi->fs_lock);
 	if (autofs4_ispending(dentry)) {
-		int status;
-
-		/*
-		 * We can only unhash and send this to ->lookup() if
-		 * the directory mutex is held over d_revalidate() and
-		 * ->lookup(). This prevents the VFS from incorrectly
-		 * seeing the dentry as non-existent.
-		 */
-		ino->flags |= AUTOFS_INF_PENDING;
-		if (!mutex_aquired) {
-			autofs4_revalidate_drop(dentry, entry);
-			spin_unlock(&dcache_lock);
-			spin_unlock(&sbi->fs_lock);
-			return 0;
-		}
-		spin_unlock(&dcache_lock);
+		/* The daemon never causes a mount to trigger */
 		spin_unlock(&sbi->fs_lock);
-		mutex_unlock(&dir->i_mutex);
-		kfree(entry);
+
+		if (oz_mode)
+			return 1;
 
 		/*
 		 * If the directory has gone away due to an expire
@@ -415,82 +325,45 @@
 		 * A zero status is success otherwise we have a
 		 * negative error code.
 		 */
-		status = try_to_fill_dentry(dentry);
-
-		spin_lock(&sbi->fs_lock);
-		ino->flags &= ~AUTOFS_INF_PENDING;
-		spin_unlock(&sbi->fs_lock);
-
+		status = try_to_fill_dentry(dentry, flags);
 		if (status == 0)
 			return 1;
 
 		return status;
 	}
+	spin_unlock(&sbi->fs_lock);
+
+	/* Negative dentry.. invalidate if "old" */
+	if (dentry->d_inode == NULL)
+		return 0;
 
 	/* Check for a non-mountpoint directory with no contents */
+	spin_lock(&dcache_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);
 
-		if (autofs4_need_mount(flags) || current->link_count) {
-			int status;
+		/* The daemon never causes a mount to trigger */
+		if (oz_mode)
+			return 1;
 
-			/*
-			 * We can only unhash and send this to ->lookup() if
-			 * the directory mutex is held over d_revalidate() and
-			 * ->lookup(). This prevents the VFS from incorrectly
-			 * seeing the dentry as non-existent.
-			 */
-			ino->flags |= AUTOFS_INF_PENDING;
-			if (!mutex_aquired) {
-				autofs4_revalidate_drop(dentry, entry);
-				spin_unlock(&dcache_lock);
-				spin_unlock(&sbi->fs_lock);
-				return 0;
-			}
-			spin_unlock(&dcache_lock);
-			spin_unlock(&sbi->fs_lock);
-			mutex_unlock(&dir->i_mutex);
-			kfree(entry);
+		/*
+		 * A zero status is success otherwise we have a
+		 * negative error code.
+		 */
+		status = try_to_fill_dentry(dentry, flags);
+		if (status == 0)
+			return 1;
 
-			/*
-			 * A zero status is success otherwise we have a
-			 * negative error code.
-			 */
-			status = try_to_fill_dentry(dentry);
-
-			spin_lock(&sbi->fs_lock);
-			ino->flags &= ~AUTOFS_INF_PENDING;
-			spin_unlock(&sbi->fs_lock);
-
-			if (status == 0)
-				return 1;
-
-			return status;
-		}
+		return status;
 	}
 	spin_unlock(&dcache_lock);
-	spin_unlock(&sbi->fs_lock);
-
-	if (mutex_aquired)
-		mutex_unlock(&dir->i_mutex);
-
-	kfree(entry);
 
 	return 1;
 }
 
-static void autofs4_free_rehash_entrys(struct autofs_info *inf)
-{
-	struct list_head *head = &inf->rehash_list;
-	struct rehash_entry *entry, *next;
-	list_for_each_entry_safe(entry, next, head, list) {
-		list_del(&entry->list);
-		kfree(entry);
-	}
-}
-
 void autofs4_dentry_release(struct dentry *de)
 {
 	struct autofs_info *inf;
@@ -509,8 +382,6 @@
 				list_del(&inf->active);
 			if (!list_empty(&inf->expiring))
 				list_del(&inf->expiring);
-			if (!list_empty(&inf->rehash_list))
-				autofs4_free_rehash_entrys(inf);
 			spin_unlock(&sbi->lookup_lock);
 		}
 
@@ -543,7 +414,6 @@
 	const unsigned char *str = name->name;
 	struct list_head *p, *head;
 
-restart:
 	spin_lock(&dcache_lock);
 	spin_lock(&sbi->lookup_lock);
 	head = &sbi->active_list;
@@ -561,19 +431,6 @@
 		if (atomic_read(&active->d_count) == 0)
 			goto next;
 
-		if (active->d_inode && IS_DEADDIR(active->d_inode)) {
-			if (!list_empty(&ino->rehash_list)) {
-				dget(active);
-				spin_unlock(&active->d_lock);
-				spin_unlock(&sbi->lookup_lock);
-				spin_unlock(&dcache_lock);
-				autofs4_remove_rehash_entrys(ino);
-				dput(active);
-				goto restart;
-			}
-			goto next;
-		}
-
 		qstr = &active->d_name;
 
 		if (active->d_name.hash != hash)
@@ -586,11 +443,13 @@
 		if (memcmp(qstr->name, str, len))
 			goto next;
 
-		dget(active);
-		spin_unlock(&active->d_lock);
-		spin_unlock(&sbi->lookup_lock);
-		spin_unlock(&dcache_lock);
-		return active;
+		if (d_unhashed(active)) {
+			dget(active);
+			spin_unlock(&active->d_lock);
+			spin_unlock(&sbi->lookup_lock);
+			spin_unlock(&dcache_lock);
+			return active;
+		}
 next:
 		spin_unlock(&active->d_lock);
 	}
@@ -639,11 +498,13 @@
 		if (memcmp(qstr->name, str, len))
 			goto next;
 
-		dget(expiring);
-		spin_unlock(&expiring->d_lock);
-		spin_unlock(&sbi->lookup_lock);
-		spin_unlock(&dcache_lock);
-		return expiring;
+		if (d_unhashed(expiring)) {
+			dget(expiring);
+			spin_unlock(&expiring->d_lock);
+			spin_unlock(&sbi->lookup_lock);
+			spin_unlock(&dcache_lock);
+			return expiring;
+		}
 next:
 		spin_unlock(&expiring->d_lock);
 	}
@@ -653,48 +514,6 @@
 	return NULL;
 }
 
-static struct autofs_info *init_new_dentry(struct autofs_sb_info *sbi,
-					   struct dentry *dentry, int oz_mode)
-{
-	struct autofs_info *ino;
-
-	/*
-	 * Mark the dentry incomplete but don't hash it. We do this
-	 * to serialize our inode creation operations (symlink and
-	 * mkdir) which prevents deadlock during the callback to
-	 * the daemon. Subsequent user space lookups for the same
-	 * dentry are placed on the wait queue while the daemon
-	 * itself is allowed passage unresticted so the create
-	 * operation itself can then hash the dentry. Finally,
-	 * we check for the hashed dentry and return the newly
-	 * hashed dentry.
-	 */
-	dentry->d_op = &autofs4_root_dentry_operations;
-
-	/*
-	 * And we need to ensure that the same dentry is used for
-	 * all following lookup calls until it is hashed so that
-	 * the dentry flags are persistent throughout the request.
-	 */
-	ino = autofs4_init_ino(NULL, sbi, 0555);
-	if (!ino)
-		return ERR_PTR(-ENOMEM);
-
-	dentry->d_fsdata = ino;
-	ino->dentry = dentry;
-
-	/*
-	 * Only set the mount pending flag for new dentrys not created
-	 * by the daemon.
-	 */
-	if (!oz_mode)
-		ino->flags |= AUTOFS_INF_PENDING;
-
-	d_instantiate(dentry, NULL);
-
-	return ino;
-}
-
 /* Lookups in the root directory */
 static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
@@ -702,7 +521,6 @@
 	struct autofs_info *ino;
 	struct dentry *expiring, *active;
 	int oz_mode;
-	int status = 0;
 
 	DPRINTK("name = %.*s",
 		dentry->d_name.len, dentry->d_name.name);
@@ -717,26 +535,44 @@
 	DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
 		 current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode);
 
-	spin_lock(&sbi->fs_lock);
 	active = autofs4_lookup_active(dentry);
 	if (active) {
 		dentry = active;
 		ino = autofs4_dentry_ino(dentry);
-		/* If this came from revalidate, rehash it */
-		autofs4_revalidate_rehash(dentry);
-		spin_unlock(&sbi->fs_lock);
 	} else {
-		spin_unlock(&sbi->fs_lock);
-		ino = init_new_dentry(sbi, dentry, oz_mode);
-		if (IS_ERR(ino))
-			return (struct dentry *) ino;
+		/*
+		 * Mark the dentry incomplete but don't hash it. We do this
+		 * to serialize our inode creation operations (symlink and
+		 * mkdir) which prevents deadlock during the callback to
+		 * the daemon. Subsequent user space lookups for the same
+		 * dentry are placed on the wait queue while the daemon
+		 * itself is allowed passage unresticted so the create
+		 * operation itself can then hash the dentry. Finally,
+		 * we check for the hashed dentry and return the newly
+		 * hashed dentry.
+		 */
+		dentry->d_op = &autofs4_root_dentry_operations;
+
+		/*
+		 * And we need to ensure that the same dentry is used for
+		 * all following lookup calls until it is hashed so that
+		 * the dentry flags are persistent throughout the request.
+		 */
+		ino = autofs4_init_ino(NULL, sbi, 0555);
+		if (!ino)
+			return ERR_PTR(-ENOMEM);
+
+		dentry->d_fsdata = ino;
+		ino->dentry = dentry;
+
+		autofs4_add_active(dentry);
+
+		d_instantiate(dentry, NULL);
 	}
 
-	autofs4_add_active(dentry);
-
 	if (!oz_mode) {
-		expiring = autofs4_lookup_expiring(dentry);
 		mutex_unlock(&dir->i_mutex);
+		expiring = autofs4_lookup_expiring(dentry);
 		if (expiring) {
 			/*
 			 * If we are racing with expire the request might not
@@ -744,22 +580,23 @@
 			 * so it must have been successful, so just wait for it.
 			 */
 			autofs4_expire_wait(expiring);
+			autofs4_del_expiring(expiring);
 			dput(expiring);
 		}
-		status = try_to_fill_dentry(dentry);
-		mutex_lock(&dir->i_mutex);
+
 		spin_lock(&sbi->fs_lock);
-		ino->flags &= ~AUTOFS_INF_PENDING;
+		ino->flags |= AUTOFS_INF_PENDING;
 		spin_unlock(&sbi->fs_lock);
+		if (dentry->d_op && dentry->d_op->d_revalidate)
+			(dentry->d_op->d_revalidate)(dentry, nd);
+		mutex_lock(&dir->i_mutex);
 	}
 
-	autofs4_del_active(dentry);
-
 	/*
-	 * If we had a mount fail, check if we had to handle
+	 * If we are still pending, check if we had to handle
 	 * a signal. If so we can force a restart..
 	 */
-	if (status) {
+	if (ino->flags & AUTOFS_INF_PENDING) {
 		/* See if we were interrupted */
 		if (signal_pending(current)) {
 			sigset_t *sigset = &current->pending.signal;
@@ -771,46 +608,43 @@
 			    return ERR_PTR(-ERESTARTNOINTR);
 			}
 		}
-	}
-
-	/*
-	 * User space can (and has done in the past) remove and re-create
-	 * this directory during the callback. This can leave us with an
-	 * unhashed dentry, but a successful mount!  So we need to
-	 * perform another cached lookup in case the dentry now exists.
-	 */
-	if (!oz_mode && !have_submounts(dentry)) {
-		struct dentry *new;
-		new = d_lookup(dentry->d_parent, &dentry->d_name);
-		if (new) {
-			if (active)
-				dput(active);
-			return new;
-		} else {
-			if (!status)
-				status = -ENOENT;
+		if (!oz_mode) {
+			spin_lock(&sbi->fs_lock);
+			ino->flags &= ~AUTOFS_INF_PENDING;
+			spin_unlock(&sbi->fs_lock);
 		}
 	}
 
 	/*
-	 * If we had a mount failure, return status to user space.
-	 * If the mount succeeded and we used a dentry from the active queue
-	 * return it.
+	 * If this dentry is unhashed, then we shouldn't honour this
+	 * lookup.  Returning ENOENT here doesn't do the right thing
+	 * for all system calls, but it should be OK for the operations
+	 * we permit from an autofs.
 	 */
-	if (status) {
-		dentry = ERR_PTR(status);
+	if (!oz_mode && d_unhashed(dentry)) {
+		/*
+		 * A user space application can (and has done in the past)
+		 * remove and re-create this directory during the callback.
+		 * This can leave us with an unhashed dentry, but a
+		 * successful mount!  So we need to perform another
+		 * cached lookup in case the dentry now exists.
+		 */
+		struct dentry *parent = dentry->d_parent;
+		struct dentry *new = d_lookup(parent, &dentry->d_name);
+		if (new != NULL)
+			dentry = new;
+		else
+			dentry = ERR_PTR(-ENOENT);
+
 		if (active)
 			dput(active);
+
 		return dentry;
-	} else {
-		/*
-		 * Valid successful mount, return active dentry or NULL
-		 * for a new dentry.
-		 */
-		if (active)
-			return active;
 	}
 
+	if (active)
+		return active;
+
 	return NULL;
 }
 
@@ -834,6 +668,8 @@
 	if (!ino)
 		return -ENOMEM;
 
+	autofs4_del_active(dentry);
+
 	ino->size = strlen(symname);
 	cp = kmalloc(ino->size + 1, GFP_KERNEL);
 	if (!cp) {
@@ -910,6 +746,7 @@
 	dir->i_mtime = CURRENT_TIME;
 
 	spin_lock(&dcache_lock);
+	autofs4_add_expiring(dentry);
 	spin_lock(&dentry->d_lock);
 	__d_drop(dentry);
 	spin_unlock(&dentry->d_lock);
@@ -935,6 +772,7 @@
 		spin_unlock(&dcache_lock);
 		return -ENOTEMPTY;
 	}
+	autofs4_add_expiring(dentry);
 	spin_lock(&dentry->d_lock);
 	__d_drop(dentry);
 	spin_unlock(&dentry->d_lock);
@@ -972,6 +810,8 @@
 	if (!ino)
 		return -ENOMEM;
 
+	autofs4_del_active(dentry);
+
 	inode = autofs4_get_inode(dir->i_sb, ino);
 	if (!inode) {
 		if (!dentry->d_fsdata)
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 8f3d9fd..f22a7d3 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -15,6 +15,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
+#include <linux/writeback.h>
 #include <asm/uaccess.h>
 #include "bfs.h"
 
@@ -98,7 +99,7 @@
 	return ERR_PTR(-EIO);
 }
 
-static int bfs_write_inode(struct inode *inode, int wait)
+static int bfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	struct bfs_sb_info *info = BFS_SB(inode->i_sb);
 	unsigned int ino = (u16)inode->i_ino;
@@ -147,7 +148,7 @@
 	di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1);
 
 	mark_buffer_dirty(bh);
-	if (wait) {
+	if (wbc->sync_mode == WB_SYNC_ALL) {
 		sync_dirty_buffer(bh);
 		if (buffer_req(bh) && !buffer_uptodate(bh))
 			err = -EIO;
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index fdd3970..15d80bb 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -24,6 +24,7 @@
 #include <linux/binfmts.h>
 #include <linux/personality.h>
 #include <linux/init.h>
+#include <linux/coredump.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -60,26 +61,6 @@
 }
 
 /*
- * These are the only things you should do on a core-file: use only these
- * macros to write out all the necessary info.
- */
-
-static int dump_write(struct file *file, const void *addr, int nr)
-{
-	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
-
-#define DUMP_WRITE(addr, nr)	\
-	if (!dump_write(file, (void *)(addr), (nr))) \
-		goto end_coredump;
-
-#define DUMP_SEEK(offset) \
-if (file->f_op->llseek) { \
-	if (file->f_op->llseek(file,(offset),0) != (offset)) \
- 		goto end_coredump; \
-} else file->f_pos = (offset)
-
-/*
  * Routine writes a core dump image in the current directory.
  * Currently only a stub-function.
  *
@@ -130,26 +111,31 @@
 
 	set_fs(KERNEL_DS);
 /* struct user */
-	DUMP_WRITE(&dump,sizeof(dump));
+	if (!dump_write(file, &dump, sizeof(dump)))
+		goto end_coredump;
 /* Now dump all of the user data.  Include malloced stuff as well */
-	DUMP_SEEK(PAGE_SIZE);
+	if (!dump_seek(cprm->file, PAGE_SIZE - sizeof(dump)))
+		goto end_coredump;
 /* now we start writing out the user space info */
 	set_fs(USER_DS);
 /* Dump the data area */
 	if (dump.u_dsize != 0) {
 		dump_start = START_DATA(dump);
 		dump_size = dump.u_dsize << PAGE_SHIFT;
-		DUMP_WRITE(dump_start,dump_size);
+		if (!dump_write(file, dump_start, dump_size))
+			goto end_coredump;
 	}
 /* Now prepare to dump the stack area */
 	if (dump.u_ssize != 0) {
 		dump_start = START_STACK(dump);
 		dump_size = dump.u_ssize << PAGE_SHIFT;
-		DUMP_WRITE(dump_start,dump_size);
+		if (!dump_write(file, dump_start, dump_size))
+			goto end_coredump;
 	}
 /* Finally dump the task struct.  Not be used by gdb, but could be useful */
 	set_fs(KERNEL_DS);
-	DUMP_WRITE(current,sizeof(*current));
+	if (!dump_write(file, current, sizeof(*current)))
+		goto end_coredump;
 end_coredump:
 	set_fs(fs);
 	return has_dumped;
@@ -247,7 +233,7 @@
 	 * size limits imposed on them by creating programs with large
 	 * arrays in the data or bss.
 	 */
-	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+	rlim = rlimit(RLIMIT_DATA);
 	if (rlim >= RLIM_INFINITY)
 		rlim = ~0;
 	if (ex.a_data + ex.a_bss > rlim)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index fd5b2ea..535e763 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -31,6 +31,7 @@
 #include <linux/random.h>
 #include <linux/elf.h>
 #include <linux/utsname.h>
+#include <linux/coredump.h>
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/page.h>
@@ -1085,36 +1086,6 @@
  * Modelled on fs/exec.c:aout_core_dump()
  * Jeremy Fitzhardinge <jeremy@sw.oz.au>
  */
-/*
- * These are the only things you should do on a core-file: use only these
- * functions to write out all the necessary info.
- */
-static int dump_write(struct file *file, const void *addr, int nr)
-{
-	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
-
-static int dump_seek(struct file *file, loff_t off)
-{
-	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
-		if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
-			return 0;
-	} else {
-		char *buf = (char *)get_zeroed_page(GFP_KERNEL);
-		if (!buf)
-			return 0;
-		while (off > 0) {
-			unsigned long n = off;
-			if (n > PAGE_SIZE)
-				n = PAGE_SIZE;
-			if (!dump_write(file, buf, n))
-				return 0;
-			off -= n;
-		}
-		free_page((unsigned long)buf);
-	}
-	return 1;
-}
 
 /*
  * Decide what to dump of a segment, part, all or none.
@@ -1249,11 +1220,6 @@
 }
 #undef DUMP_WRITE
 
-#define DUMP_WRITE(addr, nr)				\
-	if ((size += (nr)) > cprm->limit ||		\
-	    !dump_write(cprm->file, (addr), (nr)))	\
-		goto end_coredump;
-
 static void fill_elf_header(struct elfhdr *elf, int segs,
 			    u16 machine, u32 flags, u8 osabi)
 {
@@ -1872,6 +1838,34 @@
 	return gate_vma;
 }
 
+static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
+			     elf_addr_t e_shoff, int segs)
+{
+	elf->e_shoff = e_shoff;
+	elf->e_shentsize = sizeof(*shdr4extnum);
+	elf->e_shnum = 1;
+	elf->e_shstrndx = SHN_UNDEF;
+
+	memset(shdr4extnum, 0, sizeof(*shdr4extnum));
+
+	shdr4extnum->sh_type = SHT_NULL;
+	shdr4extnum->sh_size = elf->e_shnum;
+	shdr4extnum->sh_link = elf->e_shstrndx;
+	shdr4extnum->sh_info = segs;
+}
+
+static size_t elf_core_vma_data_size(struct vm_area_struct *gate_vma,
+				     unsigned long mm_flags)
+{
+	struct vm_area_struct *vma;
+	size_t size = 0;
+
+	for (vma = first_vma(current, gate_vma); vma != NULL;
+	     vma = next_vma(vma, gate_vma))
+		size += vma_dump_size(vma, mm_flags);
+	return size;
+}
+
 /*
  * Actual dumper
  *
@@ -1888,8 +1882,11 @@
 	struct vm_area_struct *vma, *gate_vma;
 	struct elfhdr *elf = NULL;
 	loff_t offset = 0, dataoff, foffset;
-	unsigned long mm_flags;
 	struct elf_note_info info;
+	struct elf_phdr *phdr4note = NULL;
+	struct elf_shdr *shdr4extnum = NULL;
+	Elf_Half e_phnum;
+	elf_addr_t e_shoff;
 
 	/*
 	 * We no longer stop all VM operations.
@@ -1912,20 +1909,25 @@
 	 * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here.
 	 */
 	segs = current->mm->map_count;
-#ifdef ELF_CORE_EXTRA_PHDRS
-	segs += ELF_CORE_EXTRA_PHDRS;
-#endif
+	segs += elf_core_extra_phdrs();
 
 	gate_vma = get_gate_vma(current);
 	if (gate_vma != NULL)
 		segs++;
 
+	/* for notes section */
+	segs++;
+
+	/* If segs > PN_XNUM(0xffff), then e_phnum overflows. To avoid
+	 * this, kernel supports extended numbering. Have a look at
+	 * include/linux/elf.h for further information. */
+	e_phnum = segs > PN_XNUM ? PN_XNUM : segs;
+
 	/*
 	 * Collect all the non-memory information about the process for the
 	 * notes.  This also sets up the file header.
 	 */
-	if (!fill_note_info(elf, segs + 1, /* including notes section */
-			    &info, cprm->signr, cprm->regs))
+	if (!fill_note_info(elf, e_phnum, &info, cprm->signr, cprm->regs))
 		goto cleanup;
 
 	has_dumped = 1;
@@ -1934,31 +1936,47 @@
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 
-	DUMP_WRITE(elf, sizeof(*elf));
 	offset += sizeof(*elf);				/* Elf header */
-	offset += (segs + 1) * sizeof(struct elf_phdr); /* Program headers */
+	offset += segs * sizeof(struct elf_phdr);	/* Program headers */
 	foffset = offset;
 
 	/* Write notes phdr entry */
 	{
-		struct elf_phdr phdr;
 		size_t sz = get_note_info_size(&info);
 
 		sz += elf_coredump_extra_notes_size();
 
-		fill_elf_note_phdr(&phdr, sz, offset);
+		phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
+		if (!phdr4note)
+			goto end_coredump;
+
+		fill_elf_note_phdr(phdr4note, sz, offset);
 		offset += sz;
-		DUMP_WRITE(&phdr, sizeof(phdr));
 	}
 
 	dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
-	/*
-	 * We must use the same mm->flags while dumping core to avoid
-	 * inconsistency between the program headers and bodies, otherwise an
-	 * unusable core file can be generated.
-	 */
-	mm_flags = current->mm->flags;
+	offset += elf_core_vma_data_size(gate_vma, cprm->mm_flags);
+	offset += elf_core_extra_data_size();
+	e_shoff = offset;
+
+	if (e_phnum == PN_XNUM) {
+		shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
+		if (!shdr4extnum)
+			goto end_coredump;
+		fill_extnum_info(elf, shdr4extnum, e_shoff, segs);
+	}
+
+	offset = dataoff;
+
+	size += sizeof(*elf);
+	if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
+		goto end_coredump;
+
+	size += sizeof(*phdr4note);
+	if (size > cprm->limit
+	    || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
+		goto end_coredump;
 
 	/* Write program headers for segments dump */
 	for (vma = first_vma(current, gate_vma); vma != NULL;
@@ -1969,7 +1987,7 @@
 		phdr.p_offset = offset;
 		phdr.p_vaddr = vma->vm_start;
 		phdr.p_paddr = 0;
-		phdr.p_filesz = vma_dump_size(vma, mm_flags);
+		phdr.p_filesz = vma_dump_size(vma, cprm->mm_flags);
 		phdr.p_memsz = vma->vm_end - vma->vm_start;
 		offset += phdr.p_filesz;
 		phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
@@ -1979,12 +1997,14 @@
 			phdr.p_flags |= PF_X;
 		phdr.p_align = ELF_EXEC_PAGESIZE;
 
-		DUMP_WRITE(&phdr, sizeof(phdr));
+		size += sizeof(phdr);
+		if (size > cprm->limit
+		    || !dump_write(cprm->file, &phdr, sizeof(phdr)))
+			goto end_coredump;
 	}
 
-#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
-	ELF_CORE_WRITE_EXTRA_PHDRS;
-#endif
+	if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit))
+		goto end_coredump;
 
  	/* write out the notes section */
 	if (!write_note_info(&info, cprm->file, &foffset))
@@ -2002,7 +2022,7 @@
 		unsigned long addr;
 		unsigned long end;
 
-		end = vma->vm_start + vma_dump_size(vma, mm_flags);
+		end = vma->vm_start + vma_dump_size(vma, cprm->mm_flags);
 
 		for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
 			struct page *page;
@@ -2023,15 +2043,24 @@
 		}
 	}
 
-#ifdef ELF_CORE_WRITE_EXTRA_DATA
-	ELF_CORE_WRITE_EXTRA_DATA;
-#endif
+	if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
+		goto end_coredump;
+
+	if (e_phnum == PN_XNUM) {
+		size += sizeof(*shdr4extnum);
+		if (size > cprm->limit
+		    || !dump_write(cprm->file, shdr4extnum,
+				   sizeof(*shdr4extnum)))
+			goto end_coredump;
+	}
 
 end_coredump:
 	set_fs(fs);
 
 cleanup:
 	free_note_info(&info);
+	kfree(shdr4extnum);
+	kfree(phdr4note);
 	kfree(elf);
 out:
 	return has_dumped;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 18d7729..2c32d00 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -34,6 +34,7 @@
 #include <linux/elf.h>
 #include <linux/elf-fdpic.h>
 #include <linux/elfcore.h>
+#include <linux/coredump.h>
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
@@ -1216,26 +1217,6 @@
 #ifdef CONFIG_ELF_CORE
 
 /*
- * These are the only things you should do on a core-file: use only these
- * functions to write out all the necessary info.
- */
-static int dump_write(struct file *file, const void *addr, int nr)
-{
-	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
-
-static int dump_seek(struct file *file, loff_t off)
-{
-	if (file->f_op->llseek) {
-		if (file->f_op->llseek(file, off, SEEK_SET) != off)
-			return 0;
-	} else {
-		file->f_pos = off;
-	}
-	return 1;
-}
-
-/*
  * Decide whether a segment is worth dumping; default is yes to be
  * sure (missing info is worse than too much; etc).
  * Personally I'd include everything, and use the coredump limit...
@@ -1313,35 +1294,35 @@
 
 /* #define DEBUG */
 
-#define DUMP_WRITE(addr, nr)	\
-	do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
-#define DUMP_SEEK(off)	\
-	do { if (!dump_seek(file, (off))) return 0; } while(0)
+#define DUMP_WRITE(addr, nr, foffset)	\
+	do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0)
 
-static int writenote(struct memelfnote *men, struct file *file)
+static int alignfile(struct file *file, loff_t *foffset)
+{
+	static const char buf[4] = { 0, };
+	DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
+	return 1;
+}
+
+static int writenote(struct memelfnote *men, struct file *file,
+			loff_t *foffset)
 {
 	struct elf_note en;
-
 	en.n_namesz = strlen(men->name) + 1;
 	en.n_descsz = men->datasz;
 	en.n_type = men->type;
 
-	DUMP_WRITE(&en, sizeof(en));
-	DUMP_WRITE(men->name, en.n_namesz);
-	/* XXX - cast from long long to long to avoid need for libgcc.a */
-	DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));	/* XXX */
-	DUMP_WRITE(men->data, men->datasz);
-	DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));	/* XXX */
+	DUMP_WRITE(&en, sizeof(en), foffset);
+	DUMP_WRITE(men->name, en.n_namesz, foffset);
+	if (!alignfile(file, foffset))
+		return 0;
+	DUMP_WRITE(men->data, men->datasz, foffset);
+	if (!alignfile(file, foffset))
+		return 0;
 
 	return 1;
 }
 #undef DUMP_WRITE
-#undef DUMP_SEEK
-
-#define DUMP_WRITE(addr, nr)				\
-	if ((size += (nr)) > cprm->limit ||		\
-	    !dump_write(cprm->file, (addr), (nr)))	\
-		goto end_coredump;
 
 static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs)
 {
@@ -1393,7 +1374,7 @@
 
 /*
  * fill up all the fields in prstatus from the given task struct, except
- * registers which need to be filled up seperately.
+ * registers which need to be filled up separately.
  */
 static void fill_prstatus(struct elf_prstatus *prstatus,
 			  struct task_struct *p, long signr)
@@ -1524,6 +1505,22 @@
 	return sz;
 }
 
+static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
+			     elf_addr_t e_shoff, int segs)
+{
+	elf->e_shoff = e_shoff;
+	elf->e_shentsize = sizeof(*shdr4extnum);
+	elf->e_shnum = 1;
+	elf->e_shstrndx = SHN_UNDEF;
+
+	memset(shdr4extnum, 0, sizeof(*shdr4extnum));
+
+	shdr4extnum->sh_type = SHT_NULL;
+	shdr4extnum->sh_size = elf->e_shnum;
+	shdr4extnum->sh_link = elf->e_shstrndx;
+	shdr4extnum->sh_info = segs;
+}
+
 /*
  * dump the segments for an MMU process
  */
@@ -1552,7 +1549,7 @@
 					err = -EIO;
 				kunmap(page);
 				page_cache_release(page);
-			} else if (!dump_seek(file, file->f_pos + PAGE_SIZE))
+			} else if (!dump_seek(file, PAGE_SIZE))
 				err = -EFBIG;
 			if (err)
 				goto out;
@@ -1588,6 +1585,17 @@
 }
 #endif
 
+static size_t elf_core_vma_data_size(unsigned long mm_flags)
+{
+	struct vm_area_struct *vma;
+	size_t size = 0;
+
+	for (vma = current->mm->mmap; vma; vma->vm_next)
+		if (maydump(vma, mm_flags))
+			size += vma->vm_end - vma->vm_start;
+	return size;
+}
+
 /*
  * Actual dumper
  *
@@ -1605,7 +1613,7 @@
 	int i;
 	struct vm_area_struct *vma;
 	struct elfhdr *elf = NULL;
-	loff_t offset = 0, dataoff;
+	loff_t offset = 0, dataoff, foffset;
 	int numnote;
 	struct memelfnote *notes = NULL;
 	struct elf_prstatus *prstatus = NULL;	/* NT_PRSTATUS */
@@ -1618,7 +1626,10 @@
 #endif
 	int thread_status_size = 0;
 	elf_addr_t *auxv;
-	unsigned long mm_flags;
+	struct elf_phdr *phdr4note = NULL;
+	struct elf_shdr *shdr4extnum = NULL;
+	Elf_Half e_phnum;
+	elf_addr_t e_shoff;
 
 	/*
 	 * We no longer stop all VM operations.
@@ -1683,12 +1694,18 @@
 	elf_core_copy_regs(&prstatus->pr_reg, cprm->regs);
 
 	segs = current->mm->map_count;
-#ifdef ELF_CORE_EXTRA_PHDRS
-	segs += ELF_CORE_EXTRA_PHDRS;
-#endif
+	segs += elf_core_extra_phdrs();
+
+	/* for notes section */
+	segs++;
+
+	/* If segs > PN_XNUM(0xffff), then e_phnum overflows. To avoid
+	 * this, kernel supports extended numbering. Have a look at
+	 * include/linux/elf.h for further information. */
+	e_phnum = segs > PN_XNUM ? PN_XNUM : segs;
 
 	/* Set up header */
-	fill_elf_fdpic_header(elf, segs + 1);	/* including notes section */
+	fill_elf_fdpic_header(elf, e_phnum);
 
 	has_dumped = 1;
 	current->flags |= PF_DUMPCORE;
@@ -1727,13 +1744,12 @@
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 
-	DUMP_WRITE(elf, sizeof(*elf));
 	offset += sizeof(*elf);				/* Elf header */
-	offset += (segs+1) * sizeof(struct elf_phdr);	/* Program headers */
+	offset += segs * sizeof(struct elf_phdr);	/* Program headers */
+	foffset = offset;
 
 	/* Write notes phdr entry */
 	{
-		struct elf_phdr phdr;
 		int sz = 0;
 
 		for (i = 0; i < numnote; i++)
@@ -1741,20 +1757,38 @@
 
 		sz += thread_status_size;
 
-		fill_elf_note_phdr(&phdr, sz, offset);
+		phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
+		if (!phdr4note)
+			goto end_coredump;
+
+		fill_elf_note_phdr(phdr4note, sz, offset);
 		offset += sz;
-		DUMP_WRITE(&phdr, sizeof(phdr));
 	}
 
 	/* Page-align dumped data */
 	dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
-	/*
-	 * We must use the same mm->flags while dumping core to avoid
-	 * inconsistency between the program headers and bodies, otherwise an
-	 * unusable core file can be generated.
-	 */
-	mm_flags = current->mm->flags;
+	offset += elf_core_vma_data_size(cprm->mm_flags);
+	offset += elf_core_extra_data_size();
+	e_shoff = offset;
+
+	if (e_phnum == PN_XNUM) {
+		shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
+		if (!shdr4extnum)
+			goto end_coredump;
+		fill_extnum_info(elf, shdr4extnum, e_shoff, segs);
+	}
+
+	offset = dataoff;
+
+	size += sizeof(*elf);
+	if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
+		goto end_coredump;
+
+	size += sizeof(*phdr4note);
+	if (size > cprm->limit
+	    || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
+		goto end_coredump;
 
 	/* write program headers for segments dump */
 	for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
@@ -1767,7 +1801,7 @@
 		phdr.p_offset = offset;
 		phdr.p_vaddr = vma->vm_start;
 		phdr.p_paddr = 0;
-		phdr.p_filesz = maydump(vma, mm_flags) ? sz : 0;
+		phdr.p_filesz = maydump(vma, cprm->mm_flags) ? sz : 0;
 		phdr.p_memsz = sz;
 		offset += phdr.p_filesz;
 		phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
@@ -1777,16 +1811,18 @@
 			phdr.p_flags |= PF_X;
 		phdr.p_align = ELF_EXEC_PAGESIZE;
 
-		DUMP_WRITE(&phdr, sizeof(phdr));
+		size += sizeof(phdr);
+		if (size > cprm->limit
+		    || !dump_write(cprm->file, &phdr, sizeof(phdr)))
+			goto end_coredump;
 	}
 
-#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
-	ELF_CORE_WRITE_EXTRA_PHDRS;
-#endif
+	if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit))
+		goto end_coredump;
 
  	/* write out the notes section */
 	for (i = 0; i < numnote; i++)
-		if (!writenote(notes + i, cprm->file))
+		if (!writenote(notes + i, cprm->file, &foffset))
 			goto end_coredump;
 
 	/* write out the thread status notes section */
@@ -1795,20 +1831,27 @@
 				list_entry(t, struct elf_thread_status, list);
 
 		for (i = 0; i < tmp->num_notes; i++)
-			if (!writenote(&tmp->notes[i], cprm->file))
+			if (!writenote(&tmp->notes[i], cprm->file, &foffset))
 				goto end_coredump;
 	}
 
-	if (!dump_seek(cprm->file, dataoff))
+	if (!dump_seek(cprm->file, dataoff - foffset))
 		goto end_coredump;
 
 	if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit,
-				    mm_flags) < 0)
+				    cprm->mm_flags) < 0)
 		goto end_coredump;
 
-#ifdef ELF_CORE_WRITE_EXTRA_DATA
-	ELF_CORE_WRITE_EXTRA_DATA;
-#endif
+	if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
+		goto end_coredump;
+
+	if (e_phnum == PN_XNUM) {
+		size += sizeof(*shdr4extnum);
+		if (size > cprm->limit
+		    || !dump_write(cprm->file, shdr4extnum,
+				   sizeof(*shdr4extnum)))
+			goto end_coredump;
+	}
 
 	if (cprm->file->f_pos != offset) {
 		/* Sanity check */
@@ -1826,7 +1869,7 @@
 		list_del(tmp);
 		kfree(list_entry(tmp, struct elf_thread_status, list));
 	}
-
+	kfree(phdr4note);
 	kfree(elf);
 	kfree(prstatus);
 	kfree(psinfo);
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 42c6b4a..e0e769b 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -501,7 +501,7 @@
 	 * size limits imposed on them by creating programs with large
 	 * arrays in the data or bss.
 	 */
-	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+	rlim = rlimit(RLIMIT_DATA);
 	if (rlim >= RLIM_INFINITY)
 		rlim = ~0;
 	if (data_len + bss_len > rlim) {
diff --git a/fs/bio.c b/fs/bio.c
index dc17afd..e1f9221 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -264,13 +264,12 @@
  * bio_alloc_bioset - allocate a bio for I/O
  * @gfp_mask:   the GFP_ mask given to the slab allocator
  * @nr_iovecs:	number of iovecs to pre-allocate
- * @bs:		the bio_set to allocate from. If %NULL, just use kmalloc
+ * @bs:		the bio_set to allocate from.
  *
  * Description:
- *   bio_alloc_bioset will first try its own mempool to satisfy the allocation.
+ *   bio_alloc_bioset will try its own mempool to satisfy the allocation.
  *   If %__GFP_WAIT is set then we will block on the internal pool waiting
- *   for a &struct bio to become free. If a %NULL @bs is passed in, we will
- *   fall back to just using @kmalloc to allocate the required memory.
+ *   for a &struct bio to become free.
  *
  *   Note that the caller must set ->bi_destructor on successful return
  *   of a bio, to do the appropriate freeing of the bio once the reference
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 2aa8ec6..8b5cfdd 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2326,7 +2326,7 @@
 int btrfs_readpage(struct file *file, struct page *page);
 void btrfs_delete_inode(struct inode *inode);
 void btrfs_put_inode(struct inode *inode);
-int btrfs_write_inode(struct inode *inode, int wait);
+int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
 void btrfs_dirty_inode(struct inode *inode);
 struct inode *btrfs_alloc_inode(struct super_block *sb);
 void btrfs_destroy_inode(struct inode *inode);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 2b59201..0427183 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -901,7 +901,7 @@
 	root->highest_objectid = 0;
 	root->name = NULL;
 	root->in_sysfs = 0;
-	root->inode_tree.rb_node = NULL;
+	root->inode_tree = RB_ROOT;
 
 	INIT_LIST_HEAD(&root->dirty_list);
 	INIT_LIST_HEAD(&root->orphan_list);
@@ -1673,7 +1673,7 @@
 	insert_inode_hash(fs_info->btree_inode);
 
 	spin_lock_init(&fs_info->block_group_cache_lock);
-	fs_info->block_group_cache_tree.rb_node = NULL;
+	fs_info->block_group_cache_tree = RB_ROOT;
 
 	extent_io_tree_init(&fs_info->freed_extents[0],
 			     fs_info->btree_inode->i_mapping, GFP_NOFS);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index b177ed3..7073cbb 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -104,8 +104,8 @@
 void extent_io_tree_init(struct extent_io_tree *tree,
 			  struct address_space *mapping, gfp_t mask)
 {
-	tree->state.rb_node = NULL;
-	tree->buffer.rb_node = NULL;
+	tree->state = RB_ROOT;
+	tree->buffer = RB_ROOT;
 	tree->ops = NULL;
 	tree->dirty_bytes = 0;
 	spin_lock_init(&tree->lock);
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 428fcac..28d87ba 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -35,7 +35,7 @@
  */
 void extent_map_tree_init(struct extent_map_tree *tree, gfp_t mask)
 {
-	tree->map.rb_node = NULL;
+	tree->map = RB_ROOT;
 	rwlock_init(&tree->lock);
 }
 
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index cb2849f..dd831ed 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -870,7 +870,7 @@
 		tree_insert_offset(&block_group->free_space_offset,
 				   entry->offset, &entry->offset_index, 0);
 	}
-	cluster->root.rb_node = NULL;
+	cluster->root = RB_ROOT;
 
 out:
 	spin_unlock(&cluster->lock);
@@ -1355,7 +1355,7 @@
 {
 	spin_lock_init(&cluster->lock);
 	spin_lock_init(&cluster->refill_lock);
-	cluster->root.rb_node = NULL;
+	cluster->root = RB_ROOT;
 	cluster->max_size = 0;
 	cluster->points_to_bitmap = false;
 	INIT_LIST_HEAD(&cluster->block_group_list);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 4deb280..c41db6d 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3968,7 +3968,7 @@
 	return ret;
 }
 
-int btrfs_write_inode(struct inode *inode, int wait)
+int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct btrfs_trans_handle *trans;
@@ -3977,7 +3977,7 @@
 	if (root->fs_info->btree_inode == inode)
 		return 0;
 
-	if (wait) {
+	if (wbc->sync_mode == WB_SYNC_ALL) {
 		trans = btrfs_join_transaction(root, 1);
 		btrfs_set_trans_block_group(trans, inode);
 		ret = btrfs_commit_transaction(trans, root);
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h
index 1fe1282..9116c6d 100644
--- a/fs/btrfs/ordered-data.h
+++ b/fs/btrfs/ordered-data.h
@@ -129,7 +129,7 @@
 btrfs_ordered_inode_tree_init(struct btrfs_ordered_inode_tree *t)
 {
 	mutex_init(&t->mutex);
-	t->tree.rb_node = NULL;
+	t->tree = RB_ROOT;
 	t->last = NULL;
 }
 
diff --git a/fs/btrfs/ref-cache.h b/fs/btrfs/ref-cache.h
index bc283ad..e2a55cb 100644
--- a/fs/btrfs/ref-cache.h
+++ b/fs/btrfs/ref-cache.h
@@ -52,7 +52,7 @@
 
 static inline void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree)
 {
-	tree->root.rb_node = NULL;
+	tree->root = RB_ROOT;
 	INIT_LIST_HEAD(&tree->list);
 	spin_lock_init(&tree->lock);
 }
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index ab7ab53..0109e56 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -170,14 +170,14 @@
 
 static void mapping_tree_init(struct mapping_tree *tree)
 {
-	tree->rb_root.rb_node = NULL;
+	tree->rb_root = RB_ROOT;
 	spin_lock_init(&tree->lock);
 }
 
 static void backref_cache_init(struct backref_cache *cache)
 {
 	int i;
-	cache->rb_root.rb_node = NULL;
+	cache->rb_root = RB_ROOT;
 	for (i = 0; i < BTRFS_MAX_LEVEL; i++)
 		INIT_LIST_HEAD(&cache->pending[i]);
 	spin_lock_init(&cache->lock);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 8a1ea6e..f8b4521 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -128,7 +128,7 @@
 {
 	struct btrfs_fs_info *info = root->fs_info;
 	substring_t args[MAX_OPT_ARGS];
-	char *p, *num;
+	char *p, *num, *orig;
 	int intarg;
 	int ret = 0;
 
@@ -143,6 +143,7 @@
 	if (!options)
 		return -ENOMEM;
 
+	orig = options;
 
 	while ((p = strsep(&options, ",")) != NULL) {
 		int token;
@@ -280,7 +281,7 @@
 		}
 	}
 out:
-	kfree(options);
+	kfree(orig);
 	return ret;
 }
 
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index a240b6f..4ce16ef7 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -164,12 +164,12 @@
 	complete(&root->kobj_unregister);
 }
 
-static struct sysfs_ops btrfs_super_attr_ops = {
+static const struct sysfs_ops btrfs_super_attr_ops = {
 	.show	= btrfs_super_attr_show,
 	.store	= btrfs_super_attr_store,
 };
 
-static struct sysfs_ops btrfs_root_attr_ops = {
+static const struct sysfs_ops btrfs_root_attr_ops = {
 	.show	= btrfs_root_attr_show,
 	.store	= btrfs_root_attr_store,
 };
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index b2acc79..2a36e23 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -69,7 +69,7 @@
 		cur_trans->commit_done = 0;
 		cur_trans->start_time = get_seconds();
 
-		cur_trans->delayed_refs.root.rb_node = NULL;
+		cur_trans->delayed_refs.root = RB_ROOT;
 		cur_trans->delayed_refs.num_entries = 0;
 		cur_trans->delayed_refs.num_heads_ready = 0;
 		cur_trans->delayed_refs.num_heads = 0;
diff --git a/fs/buffer.c b/fs/buffer.c
index 6fa5302..c9c266d 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2893,7 +2893,7 @@
 
 	/*
 	 * The page straddles i_size.  It must be zeroed out on each and every
-	 * writepage invokation because it may be mmapped.  "A file is mapped
+	 * writepage invocation because it may be mmapped.  "A file is mapped
 	 * in multiples of the page size.  For a file that is not a multiple of
 	 * the  page size, the remaining memory is zeroed when mapped, and
 	 * writes to that region are not written out to the file."
@@ -3265,7 +3265,7 @@
 	
 struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
 {
-	struct buffer_head *ret = kmem_cache_alloc(bh_cachep, 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++;
@@ -3352,15 +3352,6 @@
 }
 EXPORT_SYMBOL(bh_submit_read);
 
-static void
-init_buffer_head(void *data)
-{
-	struct buffer_head *bh = data;
-
-	memset(bh, 0, sizeof(*bh));
-	INIT_LIST_HEAD(&bh->b_assoc_buffers);
-}
-
 void __init buffer_init(void)
 {
 	int nrpages;
@@ -3369,7 +3360,7 @@
 			sizeof(struct buffer_head), 0,
 				(SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
 				SLAB_MEM_SPREAD),
-				init_buffer_head);
+				NULL);
 
 	/*
 	 * Limit the bh occupancy to 10% of ZONE_NORMAL
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 49503d2..bc0025c 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,6 +1,7 @@
 Version 1.62
 ------------
-Add sockopt=TCP_NODELAY mount option.
+Add sockopt=TCP_NODELAY mount option. EA (xattr) routines hardened
+to more strictly handle corrupt frames.
 
 Version 1.61
 ------------
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index 20692fb..a20bea5 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -136,7 +136,7 @@
 		return 0;
 	}
 
-	ch = *(ctx->pointer)++; /* ch has 0xa, ptr points to lenght octet */
+	ch = *(ctx->pointer)++; /* ch has 0xa, ptr points to length octet */
 	if ((ch) == ASN1_ENUM)  /* if ch value is ENUM, 0xa */
 		*val = *(++(ctx->pointer)); /* value has enum value */
 	else
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index b44ce0a..b1d61d0 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -54,7 +54,7 @@
  * Extracts sharename form full UNC.
  * i.e. strips from UNC trailing path that is not part of share
  * name and fixup missing '\' in the begining of DFS node refferal
- * if neccessary.
+ * if necessary.
  * Returns pointer to share name on success or ERR_PTR on error.
  * Caller is responsible for freeing returned string.
  */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index ed751bb..a1c817e 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -205,7 +205,7 @@
 struct cifsSesInfo {
 	struct list_head smb_ses_list;
 	struct list_head tcon_list;
-	struct semaphore sesSem;
+	struct mutex session_mutex;
 #if 0
 	struct cifsUidInfo *uidInfo;	/* pointer to user info */
 #endif
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 3877737..14d036d 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -415,10 +415,10 @@
 	__u8 WordCount;
 } __attribute__((packed));
 /* given a pointer to an smb_hdr retrieve the value of byte count */
-#define BCC(smb_var) (*(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
-#define BCC_LE(smb_var) (*(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
+#define BCC(smb_var) (*(__u16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount)))
+#define BCC_LE(smb_var) (*(__le16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount)))
 /* given a pointer to an smb_hdr retrieve the pointer to the byte area */
-#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2)
+#define pByteArea(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount) + 2)
 
 /*
  * Computer Name Length (since Netbios name was length 16 with last byte 0x20)
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 5646727..88e2bc4 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -363,13 +363,10 @@
 			__u32 filter, struct file *file, int multishot,
 			const struct nls_table *nls_codepage);
 extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
-			const unsigned char *searchName, char *EAData,
+			const unsigned char *searchName,
+			const unsigned char *ea_name, char *EAData,
 			size_t bufsize, const struct nls_table *nls_codepage,
 			int remap_special_chars);
-extern ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
-		const unsigned char *searchName, const unsigned char *ea_name,
-		unsigned char *ea_value, size_t buf_size,
-		const struct nls_table *nls_codepage, int remap_special_chars);
 extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
 		const char *fileName, const char *ea_name,
 		const void *ea_value, const __u16 ea_value_len,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 941441d..6118358 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -170,19 +170,19 @@
 	 * need to prevent multiple threads trying to simultaneously
 	 * reconnect the same SMB session
 	 */
-	down(&ses->sesSem);
+	mutex_lock(&ses->session_mutex);
 	if (ses->need_reconnect)
 		rc = cifs_setup_session(0, ses, nls_codepage);
 
 	/* do we need to reconnect tcon? */
 	if (rc || !tcon->need_reconnect) {
-		up(&ses->sesSem);
+		mutex_unlock(&ses->session_mutex);
 		goto out;
 	}
 
 	mark_open_files_invalid(tcon);
 	rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
-	up(&ses->sesSem);
+	mutex_unlock(&ses->session_mutex);
 	cFYI(1, ("reconnect tcon rc = %d", rc));
 
 	if (rc)
@@ -700,13 +700,13 @@
 	if (!ses || !ses->server)
 		return -EIO;
 
-	down(&ses->sesSem);
+	mutex_lock(&ses->session_mutex);
 	if (ses->need_reconnect)
 		goto session_already_dead; /* no need to send SMBlogoff if uid
 					      already closed due to reconnect */
 	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
 	if (rc) {
-		up(&ses->sesSem);
+		mutex_unlock(&ses->session_mutex);
 		return rc;
 	}
 
@@ -721,7 +721,7 @@
 	pSMB->AndXCommand = 0xFF;
 	rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
 session_already_dead:
-	up(&ses->sesSem);
+	mutex_unlock(&ses->session_mutex);
 
 	/* if session dead then we do not need to do ulogoff,
 		since server closed smb session, no sense reporting
@@ -3886,7 +3886,7 @@
 		goto parse_DFS_referrals_exit;
 	}
 
-	/* collect neccessary data from referrals */
+	/* collect necessary data from referrals */
 	for (i = 0; i < *num_of_nodes; i++) {
 		char *temp;
 		int max_len;
@@ -5269,22 +5269,34 @@
 	cifs_buf_release(pSMB);
 	return rc;
 }
+
 #ifdef CONFIG_CIFS_XATTR
+/*
+ * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common
+ * function used by listxattr and getxattr type calls. When ea_name is set,
+ * it looks for that attribute name and stuffs that value into the EAData
+ * buffer. When ea_name is NULL, it stuffs a list of attribute names into the
+ * buffer. In both cases, the return value is either the length of the
+ * resulting data or a negative error code. If EAData is a NULL pointer then
+ * the data isn't copied to it, but the length is returned.
+ */
 ssize_t
 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
-		 const unsigned char *searchName,
-		 char *EAData, size_t buf_size,
-		 const struct nls_table *nls_codepage, int remap)
+		const unsigned char *searchName, const unsigned char *ea_name,
+		char *EAData, size_t buf_size,
+		const struct nls_table *nls_codepage, int remap)
 {
 		/* BB assumes one setup word */
 	TRANSACTION2_QPI_REQ *pSMB = NULL;
 	TRANSACTION2_QPI_RSP *pSMBr = NULL;
 	int rc = 0;
 	int bytes_returned;
-	int name_len;
+	int list_len;
+	struct fealist *ea_response_data;
 	struct fea *temp_fea;
 	char *temp_ptr;
-	__u16 params, byte_count;
+	char *end_of_smb;
+	__u16 params, byte_count, data_offset;
 
 	cFYI(1, ("In Query All EAs path %s", searchName));
 QAllEAsRetry:
@@ -5294,22 +5306,22 @@
 		return rc;
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		name_len =
+		list_len =
 		    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
 				     PATH_MAX, nls_codepage, remap);
-		name_len++;	/* trailing null */
-		name_len *= 2;
+		list_len++;	/* trailing null */
+		list_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
-		name_len = strnlen(searchName, PATH_MAX);
-		name_len++;	/* trailing null */
-		strncpy(pSMB->FileName, searchName, name_len);
+		list_len = strnlen(searchName, PATH_MAX);
+		list_len++;	/* trailing null */
+		strncpy(pSMB->FileName, searchName, list_len);
 	}
 
-	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
+	params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	/* BB find exact max SMB PDU from sess structure BB */
-	pSMB->MaxDataCount = cpu_to_le16(4000);
+	pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize);
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
@@ -5334,85 +5346,114 @@
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QueryAllEAs = %d", rc));
-	} else {		/* decode response */
-		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+		goto QAllEAsOut;
+	}
 
-		/* BB also check enough total bytes returned */
-		/* BB we need to improve the validity checking
-		of these trans2 responses */
-		if (rc || (pSMBr->ByteCount < 4))
-			rc = -EIO;	/* bad smb */
-	   /* else if (pFindData){
-			memcpy((char *) pFindData,
-			       (char *) &pSMBr->hdr.Protocol +
-			       data_offset, kl);
-		}*/ else {
-			/* check that length of list is not more than bcc */
-			/* check that each entry does not go beyond length
-			   of list */
-			/* check that each element of each entry does not
-			   go beyond end of list */
-			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
-			struct fealist *ea_response_data;
-			rc = 0;
-			/* validate_trans2_offsets() */
-			/* BB check if start of smb + data_offset > &bcc+ bcc */
-			ea_response_data = (struct fealist *)
-				(((char *) &pSMBr->hdr.Protocol) +
-				data_offset);
-			name_len = le32_to_cpu(ea_response_data->list_len);
-			cFYI(1, ("ea length %d", name_len));
-			if (name_len <= 8) {
-			/* returned EA size zeroed at top of function */
-				cFYI(1, ("empty EA list returned from server"));
-			} else {
-				/* account for ea list len */
-				name_len -= 4;
-				temp_fea = ea_response_data->list;
-				temp_ptr = (char *)temp_fea;
-				while (name_len > 0) {
-					__u16 value_len;
-					name_len -= 4;
-					temp_ptr += 4;
-					rc += temp_fea->name_len;
-				/* account for prefix user. and trailing null */
-					rc = rc + 5 + 1;
-					if (rc < (int)buf_size) {
-						memcpy(EAData, "user.", 5);
-						EAData += 5;
-						memcpy(EAData, temp_ptr,
-						       temp_fea->name_len);
-						EAData += temp_fea->name_len;
-						/* null terminate name */
-						*EAData = 0;
-						EAData = EAData + 1;
-					} else if (buf_size == 0) {
-						/* skip copy - calc size only */
-					} else {
-						/* stop before overrun buffer */
-						rc = -ERANGE;
-						break;
-					}
-					name_len -= temp_fea->name_len;
-					temp_ptr += temp_fea->name_len;
-					/* account for trailing null */
-					name_len--;
-					temp_ptr++;
-					value_len =
-					      le16_to_cpu(temp_fea->value_len);
-					name_len -= value_len;
-					temp_ptr += value_len;
-					/* BB check that temp_ptr is still
-					      within the SMB BB*/
 
-					/* no trailing null to account for
-					   in value len */
-					/* go on to next EA */
-					temp_fea = (struct fea *)temp_ptr;
+	/* BB also check enough total bytes returned */
+	/* BB we need to improve the validity checking
+	of these trans2 responses */
+
+	rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+	if (rc || (pSMBr->ByteCount < 4)) {
+		rc = -EIO;	/* bad smb */
+		goto QAllEAsOut;
+	}
+
+	/* check that length of list is not more than bcc */
+	/* check that each entry does not go beyond length
+	   of list */
+	/* check that each element of each entry does not
+	   go beyond end of list */
+	/* validate_trans2_offsets() */
+	/* BB check if start of smb + data_offset > &bcc+ bcc */
+
+	data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+	ea_response_data = (struct fealist *)
+				(((char *) &pSMBr->hdr.Protocol) + data_offset);
+
+	list_len = le32_to_cpu(ea_response_data->list_len);
+	cFYI(1, ("ea length %d", list_len));
+	if (list_len <= 8) {
+		cFYI(1, ("empty EA list returned from server"));
+		goto QAllEAsOut;
+	}
+
+	/* make sure list_len doesn't go past end of SMB */
+	end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
+	if ((char *)ea_response_data + list_len > end_of_smb) {
+		cFYI(1, ("EA list appears to go beyond SMB"));
+		rc = -EIO;
+		goto QAllEAsOut;
+	}
+
+	/* account for ea list len */
+	list_len -= 4;
+	temp_fea = ea_response_data->list;
+	temp_ptr = (char *)temp_fea;
+	while (list_len > 0) {
+		unsigned int name_len;
+		__u16 value_len;
+
+		list_len -= 4;
+		temp_ptr += 4;
+		/* make sure we can read name_len and value_len */
+		if (list_len < 0) {
+			cFYI(1, ("EA entry goes beyond length of list"));
+			rc = -EIO;
+			goto QAllEAsOut;
+		}
+
+		name_len = temp_fea->name_len;
+		value_len = le16_to_cpu(temp_fea->value_len);
+		list_len -= name_len + 1 + value_len;
+		if (list_len < 0) {
+			cFYI(1, ("EA entry goes beyond length of list"));
+			rc = -EIO;
+			goto QAllEAsOut;
+		}
+
+		if (ea_name) {
+			if (strncmp(ea_name, temp_ptr, name_len) == 0) {
+				temp_ptr += name_len + 1;
+				rc = value_len;
+				if (buf_size == 0)
+					goto QAllEAsOut;
+				if ((size_t)value_len > buf_size) {
+					rc = -ERANGE;
+					goto QAllEAsOut;
 				}
+				memcpy(EAData, temp_ptr, value_len);
+				goto QAllEAsOut;
+			}
+		} else {
+			/* account for prefix user. and trailing null */
+			rc += (5 + 1 + name_len);
+			if (rc < (int) buf_size) {
+				memcpy(EAData, "user.", 5);
+				EAData += 5;
+				memcpy(EAData, temp_ptr, name_len);
+				EAData += name_len;
+				/* null terminate name */
+				*EAData = 0;
+				++EAData;
+			} else if (buf_size == 0) {
+				/* skip copy - calc size only */
+			} else {
+				/* stop before overrun buffer */
+				rc = -ERANGE;
+				break;
 			}
 		}
+		temp_ptr += name_len + 1 + value_len;
+		temp_fea = (struct fea *)temp_ptr;
 	}
+
+	/* didn't find the named attribute */
+	if (ea_name)
+		rc = -ENODATA;
+
+QAllEAsOut:
 	cifs_buf_release(pSMB);
 	if (rc == -EAGAIN)
 		goto QAllEAsRetry;
@@ -5420,155 +5461,6 @@
 	return (ssize_t)rc;
 }
 
-ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
-		const unsigned char *searchName, const unsigned char *ea_name,
-		unsigned char *ea_value, size_t buf_size,
-		const struct nls_table *nls_codepage, int remap)
-{
-	TRANSACTION2_QPI_REQ *pSMB = NULL;
-	TRANSACTION2_QPI_RSP *pSMBr = NULL;
-	int rc = 0;
-	int bytes_returned;
-	int name_len;
-	struct fea *temp_fea;
-	char *temp_ptr;
-	__u16 params, byte_count;
-
-	cFYI(1, ("In Query EA path %s", searchName));
-QEARetry:
-	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-		      (void **) &pSMBr);
-	if (rc)
-		return rc;
-
-	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-				     PATH_MAX, nls_codepage, remap);
-		name_len++;	/* trailing null */
-		name_len *= 2;
-	} else {	/* BB improve the check for buffer overruns BB */
-		name_len = strnlen(searchName, PATH_MAX);
-		name_len++;	/* trailing null */
-		strncpy(pSMB->FileName, searchName, name_len);
-	}
-
-	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
-	pSMB->TotalDataCount = 0;
-	pSMB->MaxParameterCount = cpu_to_le16(2);
-	/* BB find exact max SMB PDU from sess structure BB */
-	pSMB->MaxDataCount = cpu_to_le16(4000);
-	pSMB->MaxSetupCount = 0;
-	pSMB->Reserved = 0;
-	pSMB->Flags = 0;
-	pSMB->Timeout = 0;
-	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = cpu_to_le16(offsetof(
-		struct smb_com_transaction2_qpi_req, InformationLevel) - 4);
-	pSMB->DataCount = 0;
-	pSMB->DataOffset = 0;
-	pSMB->SetupCount = 1;
-	pSMB->Reserved3 = 0;
-	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	byte_count = params + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(params);
-	pSMB->ParameterCount = pSMB->TotalParameterCount;
-	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
-	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += byte_count;
-	pSMB->ByteCount = cpu_to_le16(byte_count);
-
-	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	if (rc) {
-		cFYI(1, ("Send error in Query EA = %d", rc));
-	} else {		/* decode response */
-		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
-		/* BB also check enough total bytes returned */
-		/* BB we need to improve the validity checking
-		of these trans2 responses */
-		if (rc || (pSMBr->ByteCount < 4))
-			rc = -EIO;	/* bad smb */
-	   /* else if (pFindData){
-			memcpy((char *) pFindData,
-			       (char *) &pSMBr->hdr.Protocol +
-			       data_offset, kl);
-		}*/ else {
-			/* check that length of list is not more than bcc */
-			/* check that each entry does not go beyond length
-			   of list */
-			/* check that each element of each entry does not
-			   go beyond end of list */
-			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
-			struct fealist *ea_response_data;
-			rc = -ENODATA;
-			/* validate_trans2_offsets() */
-			/* BB check if start of smb + data_offset > &bcc+ bcc*/
-			ea_response_data = (struct fealist *)
-				(((char *) &pSMBr->hdr.Protocol) +
-				data_offset);
-			name_len = le32_to_cpu(ea_response_data->list_len);
-			cFYI(1, ("ea length %d", name_len));
-			if (name_len <= 8) {
-			/* returned EA size zeroed at top of function */
-				cFYI(1, ("empty EA list returned from server"));
-			} else {
-				/* account for ea list len */
-				name_len -= 4;
-				temp_fea = ea_response_data->list;
-				temp_ptr = (char *)temp_fea;
-				/* loop through checking if we have a matching
-				name and then return the associated value */
-				while (name_len > 0) {
-					__u16 value_len;
-					name_len -= 4;
-					temp_ptr += 4;
-					value_len =
-					      le16_to_cpu(temp_fea->value_len);
-				/* BB validate that value_len falls within SMB,
-				even though maximum for name_len is 255 */
-					if (memcmp(temp_fea->name, ea_name,
-						  temp_fea->name_len) == 0) {
-						/* found a match */
-						rc = value_len;
-				/* account for prefix user. and trailing null */
-						if (rc <= (int)buf_size) {
-							memcpy(ea_value,
-								temp_fea->name+temp_fea->name_len+1,
-								rc);
-							/* ea values, unlike ea
-							   names, are not null
-							   terminated */
-						} else if (buf_size == 0) {
-						/* skip copy - calc size only */
-						} else {
-						/* stop before overrun buffer */
-							rc = -ERANGE;
-						}
-						break;
-					}
-					name_len -= temp_fea->name_len;
-					temp_ptr += temp_fea->name_len;
-					/* account for trailing null */
-					name_len--;
-					temp_ptr++;
-					name_len -= value_len;
-					temp_ptr += value_len;
-					/* No trailing null to account for in
-					   value_len.  Go on to next EA */
-					temp_fea = (struct fea *)temp_ptr;
-				}
-			}
-		}
-	}
-	cifs_buf_release(pSMB);
-	if (rc == -EAGAIN)
-		goto QEARetry;
-
-	return (ssize_t)rc;
-}
-
 int
 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
 	     const char *ea_name, const void *ea_value,
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2e9e09c..45eb6cb 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2388,13 +2388,13 @@
 		 */
 		cifs_put_tcp_session(srvTcp);
 
-		down(&pSesInfo->sesSem);
+		mutex_lock(&pSesInfo->session_mutex);
 		if (pSesInfo->need_reconnect) {
 			cFYI(1, ("Session needs reconnect"));
 			rc = cifs_setup_session(xid, pSesInfo,
 						cifs_sb->local_nls);
 		}
-		up(&pSesInfo->sesSem);
+		mutex_unlock(&pSesInfo->session_mutex);
 	} else if (!rc) {
 		cFYI(1, ("Existing smb sess not found"));
 		pSesInfo = sesInfoAlloc();
@@ -2437,12 +2437,12 @@
 		}
 		pSesInfo->linux_uid = volume_info->linux_uid;
 		pSesInfo->overrideSecFlg = volume_info->secFlg;
-		down(&pSesInfo->sesSem);
+		mutex_lock(&pSesInfo->session_mutex);
 
 		/* BB FIXME need to pass vol->secFlgs BB */
 		rc = cifs_setup_session(xid, pSesInfo,
 					cifs_sb->local_nls);
-		up(&pSesInfo->sesSem);
+		mutex_unlock(&pSesInfo->session_mutex);
 	}
 
 	/* search for existing tcon to this server share */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 057e1da..3d8f8a9 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2289,9 +2289,9 @@
 	if (inode && S_ISREG(inode->i_mode)) {
 #ifdef CONFIG_CIFS_EXPERIMENTAL
 		if (cinode->clientCanCacheAll == 0)
-			break_lease(inode, FMODE_READ);
+			break_lease(inode, O_RDONLY);
 		else if (cinode->clientCanCacheRead == 0)
-			break_lease(inode, FMODE_WRITE);
+			break_lease(inode, O_WRONLY);
 #endif
 		rc = filemap_fdatawrite(inode->i_mapping);
 		if (cinode->clientCanCacheRead == 0) {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index e3fda97..8bdbc81 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -111,6 +111,7 @@
 
 	cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
 
+	cifs_i->server_eof = fattr->cf_eof;
 	/*
 	 * Can't safely change the file size here if the client is writing to
 	 * it due to potential races.
@@ -366,7 +367,7 @@
 	char ea_value[4];
 	__u32 mode;
 
-	rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
+	rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS",
 			    ea_value, 4 /* size of buf */, cifs_sb->local_nls,
 			    cifs_sb->mnt_cifs_flags &
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index d27d4ec..d147499 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -79,7 +79,7 @@
 		++ret_buf->ses_count;
 		INIT_LIST_HEAD(&ret_buf->smb_ses_list);
 		INIT_LIST_HEAD(&ret_buf->tcon_list);
-		init_MUTEX(&ret_buf->sesSem);
+		mutex_init(&ret_buf->session_mutex);
 	}
 	return ret_buf;
 }
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index a75afa3..3e2ef0d 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -244,7 +244,7 @@
 			/* revalidate/getattr then populate from inode */
 		} /* BB add else when above is implemented */
 		ea_name += 5; /* skip past user. prefix */
-		rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value,
+		rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
 			buf_size, cifs_sb->local_nls,
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	} else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
@@ -252,7 +252,7 @@
 			goto get_ea_exit;
 
 		ea_name += 4; /* skip past os2. prefix */
-		rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value,
+		rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
 			buf_size, cifs_sb->local_nls,
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	} else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
@@ -364,8 +364,8 @@
 	/* if proc/fs/cifs/streamstoxattr is set then
 		search server for EAs or streams to
 		returns as xattrs */
-	rc = CIFSSMBQAllEAs(xid, pTcon, full_path, data, buf_size,
-				cifs_sb->local_nls,
+	rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data,
+				buf_size, cifs_sb->local_nls,
 				cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
 
diff --git a/fs/compat.c b/fs/compat.c
index 00d90c2..030602d 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1795,6 +1795,24 @@
 	return ret;
 }
 
+struct compat_sel_arg_struct {
+	compat_ulong_t n;
+	compat_uptr_t inp;
+	compat_uptr_t outp;
+	compat_uptr_t exp;
+	compat_uptr_t tvp;
+};
+
+asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg)
+{
+	struct compat_sel_arg_struct a;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EFAULT;
+	return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp),
+				 compat_ptr(a.exp), compat_ptr(a.tvp));
+}
+
 #ifdef HAVE_SET_RESTORE_SIGMASK
 static long do_compat_pselect(int n, compat_ulong_t __user *inp,
 	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c
index 0adced2..112e45a 100644
--- a/fs/compat_binfmt_elf.c
+++ b/fs/compat_binfmt_elf.c
@@ -28,10 +28,12 @@
 
 #undef	elfhdr
 #undef	elf_phdr
+#undef	elf_shdr
 #undef	elf_note
 #undef	elf_addr_t
 #define elfhdr		elf32_hdr
 #define elf_phdr	elf32_phdr
+#define elf_shdr	elf32_shdr
 #define elf_note	elf32_note
 #define elf_addr_t	Elf32_Addr
 
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 0ca9ec4..6d55b61 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -545,7 +545,7 @@
 		kcmd = MTIOCPOS;
 		karg = &pos;
 		break;
-	case MTIOCGET32:
+	default:	/* MTIOCGET32 */
 		kcmd = MTIOCGET;
 		karg = &get;
 		break;
@@ -663,7 +663,7 @@
 
         switch (cmd) {
         case RAW_SETBIND:
-        case RAW_GETBIND: {
+	default: {	/* RAW_GETBIND */
                 struct raw_config_request req;
                 mm_segment_t oldfs = get_fs();
 
diff --git a/fs/dcache.c b/fs/dcache.c
index 953173a..f1358e5 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -257,6 +257,7 @@
 	if (dentry)
 		goto repeat;
 }
+EXPORT_SYMBOL(dput);
 
 /**
  * d_invalidate - invalidate a dentry
@@ -314,6 +315,7 @@
 	spin_unlock(&dcache_lock);
 	return 0;
 }
+EXPORT_SYMBOL(d_invalidate);
 
 /* This should be called _only_ with dcache_lock held */
 
@@ -328,6 +330,7 @@
 {
 	return __dget_locked(dentry);
 }
+EXPORT_SYMBOL(dget_locked);
 
 /**
  * d_find_alias - grab a hashed alias of inode
@@ -384,6 +387,7 @@
 	}
 	return de;
 }
+EXPORT_SYMBOL(d_find_alias);
 
 /*
  *	Try to kill dentries associated with this inode.
@@ -408,6 +412,7 @@
 	}
 	spin_unlock(&dcache_lock);
 }
+EXPORT_SYMBOL(d_prune_aliases);
 
 /*
  * Throw away a dentry - free the inode, dput the parent.  This requires that
@@ -610,6 +615,7 @@
 {
 	__shrink_dcache_sb(sb, NULL, 0);
 }
+EXPORT_SYMBOL(shrink_dcache_sb);
 
 /*
  * destroy a single subtree of dentries for unmount
@@ -792,6 +798,7 @@
 	spin_unlock(&dcache_lock);
 	return 1;
 }
+EXPORT_SYMBOL(have_submounts);
 
 /*
  * Search the dentry child list for the specified parent,
@@ -876,6 +883,7 @@
 	while ((found = select_parent(parent)) != 0)
 		__shrink_dcache_sb(sb, &found, 0);
 }
+EXPORT_SYMBOL(shrink_dcache_parent);
 
 /*
  * Scan `nr' dentries and return the number which remain.
@@ -968,6 +976,7 @@
 
 	return dentry;
 }
+EXPORT_SYMBOL(d_alloc);
 
 struct dentry *d_alloc_name(struct dentry *parent, const char *name)
 {
@@ -1012,6 +1021,7 @@
 	spin_unlock(&dcache_lock);
 	security_d_instantiate(entry, inode);
 }
+EXPORT_SYMBOL(d_instantiate);
 
 /**
  * d_instantiate_unique - instantiate a non-aliased dentry
@@ -1108,6 +1118,7 @@
 	}
 	return res;
 }
+EXPORT_SYMBOL(d_alloc_root);
 
 static inline struct hlist_head *d_hash(struct dentry *parent,
 					unsigned long hash)
@@ -1211,7 +1222,6 @@
 			BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
 			spin_unlock(&dcache_lock);
 			security_d_instantiate(new, inode);
-			d_rehash(dentry);
 			d_move(new, dentry);
 			iput(inode);
 		} else {
@@ -1225,6 +1235,7 @@
 		d_add(dentry, inode);
 	return new;
 }
+EXPORT_SYMBOL(d_splice_alias);
 
 /**
  * d_add_ci - lookup or allocate new dentry with case-exact name
@@ -1314,6 +1325,7 @@
 	iput(inode);
 	return ERR_PTR(error);
 }
+EXPORT_SYMBOL(d_add_ci);
 
 /**
  * d_lookup - search for a dentry
@@ -1357,6 +1369,7 @@
 	} while (read_seqretry(&rename_lock, seq));
 	return dentry;
 }
+EXPORT_SYMBOL(d_lookup);
 
 struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
 {
@@ -1483,6 +1496,7 @@
 out:
 	return 0;
 }
+EXPORT_SYMBOL(d_validate);
 
 /*
  * When a file is deleted, we have two options:
@@ -1528,6 +1542,7 @@
 
 	fsnotify_nameremove(dentry, isdir);
 }
+EXPORT_SYMBOL(d_delete);
 
 static void __d_rehash(struct dentry * entry, struct hlist_head *list)
 {
@@ -1556,6 +1571,7 @@
 	spin_unlock(&entry->d_lock);
 	spin_unlock(&dcache_lock);
 }
+EXPORT_SYMBOL(d_rehash);
 
 /*
  * When switching names, the actual string doesn't strictly have to
@@ -1702,6 +1718,7 @@
 	d_move_locked(dentry, target);
 	spin_unlock(&dcache_lock);
 }
+EXPORT_SYMBOL(d_move);
 
 /**
  * d_ancestor - search for an ancestor
@@ -1868,6 +1885,7 @@
 	spin_unlock(&dcache_lock);
 	BUG();
 }
+EXPORT_SYMBOL_GPL(d_materialise_unique);
 
 static int prepend(char **buffer, int *buflen, const char *str, int namelen)
 {
@@ -2005,6 +2023,7 @@
 	path_put(&root);
 	return res;
 }
+EXPORT_SYMBOL(d_path);
 
 /*
  * Helper function for dentry_operations.d_dname() members
@@ -2171,6 +2190,30 @@
 	return result;
 }
 
+int path_is_under(struct path *path1, struct path *path2)
+{
+	struct vfsmount *mnt = path1->mnt;
+	struct dentry *dentry = path1->dentry;
+	int res;
+	spin_lock(&vfsmount_lock);
+	if (mnt != path2->mnt) {
+		for (;;) {
+			if (mnt->mnt_parent == mnt) {
+				spin_unlock(&vfsmount_lock);
+				return 0;
+			}
+			if (mnt->mnt_parent == path2->mnt)
+				break;
+			mnt = mnt->mnt_parent;
+		}
+		dentry = mnt->mnt_mountpoint;
+	}
+	res = is_subdir(dentry, path2->dentry);
+	spin_unlock(&vfsmount_lock);
+	return res;
+}
+EXPORT_SYMBOL(path_is_under);
+
 void d_genocide(struct dentry *root)
 {
 	struct dentry *this_parent = root;
@@ -2228,6 +2271,7 @@
 	}
 	return ino;
 }
+EXPORT_SYMBOL(find_inode_number);
 
 static __initdata unsigned long dhash_entries;
 static int __init set_dhash_entries(char *str)
@@ -2297,6 +2341,7 @@
 
 /* SLAB cache for __getname() consumers */
 struct kmem_cache *names_cachep __read_mostly;
+EXPORT_SYMBOL(names_cachep);
 
 EXPORT_SYMBOL(d_genocide);
 
@@ -2326,26 +2371,3 @@
 	bdev_cache_init();
 	chrdev_init();
 }
-
-EXPORT_SYMBOL(d_alloc);
-EXPORT_SYMBOL(d_alloc_root);
-EXPORT_SYMBOL(d_delete);
-EXPORT_SYMBOL(d_find_alias);
-EXPORT_SYMBOL(d_instantiate);
-EXPORT_SYMBOL(d_invalidate);
-EXPORT_SYMBOL(d_lookup);
-EXPORT_SYMBOL(d_move);
-EXPORT_SYMBOL_GPL(d_materialise_unique);
-EXPORT_SYMBOL(d_path);
-EXPORT_SYMBOL(d_prune_aliases);
-EXPORT_SYMBOL(d_rehash);
-EXPORT_SYMBOL(d_splice_alias);
-EXPORT_SYMBOL(d_add_ci);
-EXPORT_SYMBOL(d_validate);
-EXPORT_SYMBOL(dget_locked);
-EXPORT_SYMBOL(dput);
-EXPORT_SYMBOL(find_inode_number);
-EXPORT_SYMBOL(have_submounts);
-EXPORT_SYMBOL(names_cachep);
-EXPORT_SYMBOL(shrink_dcache_parent);
-EXPORT_SYMBOL(shrink_dcache_sb);
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 274ac86..049d6c3 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -496,7 +496,7 @@
 	}
 	d_move(old_dentry, dentry);
 	fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
-		old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
+		S_ISDIR(old_dentry->d_inode->i_mode),
 		NULL, old_dentry);
 	fsnotify_oldname_free(old_name);
 	unlock_rename(new_dir, old_dir);
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 26a8bd4..f994a7d 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -148,7 +148,7 @@
 	kfree(ls);
 }
 
-static struct sysfs_ops dlm_attr_ops = {
+static const struct sysfs_ops dlm_attr_ops = {
 	.show  = dlm_attr_show,
 	.store = dlm_attr_store,
 };
diff --git a/fs/dlm/member.c b/fs/dlm/member.c
index 84f70bf..b12532e 100644
--- a/fs/dlm/member.c
+++ b/fs/dlm/member.c
@@ -312,7 +312,7 @@
 	/*
 	 * This in_recovery lock does two things:
 	 * 1) Keeps this function from returning until all threads are out
-	 *    of locking routines and locking is truely stopped.
+	 *    of locking routines and locking is truly stopped.
 	 * 2) Keeps any new requests from being processed until it's unlocked
 	 *    when recovery is complete.
 	 */
diff --git a/fs/exec.c b/fs/exec.c
index cce6bbd..49cdaa1 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -195,7 +195,7 @@
 		 *    to work from.
 		 */
 		rlim = current->signal->rlim;
-		if (size > rlim[RLIMIT_STACK].rlim_cur / 4) {
+		if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) {
 			put_page(page);
 			return NULL;
 		}
@@ -246,6 +246,7 @@
 	vma->vm_start = vma->vm_end - PAGE_SIZE;
 	vma->vm_flags = VM_STACK_FLAGS;
 	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+	INIT_LIST_HEAD(&vma->anon_vma_chain);
 	err = insert_vm_struct(mm, vma);
 	if (err)
 		goto err;
@@ -516,7 +517,8 @@
 	/*
 	 * cover the whole range: [new_start, old_end)
 	 */
-	vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL);
+	if (vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL))
+		return -ENOMEM;
 
 	/*
 	 * move the page tables downwards, on failure we rely on
@@ -547,15 +549,13 @@
 	tlb_finish_mmu(tlb, new_end, old_end);
 
 	/*
-	 * shrink the vma to just the new range.
+	 * Shrink the vma to just the new range.  Always succeeds.
 	 */
 	vma_adjust(vma, new_start, new_end, vma->vm_pgoff, NULL);
 
 	return 0;
 }
 
-#define EXTRA_STACK_VM_PAGES	20	/* random */
-
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
  * the stack is optionally relocated, and some extra space is added.
@@ -577,7 +577,7 @@
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
-	stack_base = current->signal->rlim[RLIMIT_STACK].rlim_max;
+	stack_base = rlimit_max(RLIMIT_STACK);
 	if (stack_base > (1 << 30))
 		stack_base = 1 << 30;
 
@@ -630,7 +630,7 @@
 			goto out_unlock;
 	}
 
-	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
 	stack_size = vma->vm_end - vma->vm_start;
 	/*
 	 * Align this down to a page boundary as expand_stack
@@ -718,6 +718,7 @@
 	/* Notify parent that we're no longer interested in the old VM */
 	tsk = current;
 	old_mm = current->mm;
+	sync_mm_rss(tsk, old_mm);
 	mm_release(tsk, old_mm);
 
 	if (old_mm) {
@@ -1532,7 +1533,7 @@
 			/* core limit size */
 			case 'c':
 				rc = snprintf(out_ptr, out_end - out_ptr,
-					      "%lu", current->signal->rlim[RLIMIT_CORE].rlim_cur);
+					      "%lu", rlimit(RLIMIT_CORE));
 				if (rc > out_end - out_ptr)
 					goto out;
 				out_ptr += rc;
@@ -1560,12 +1561,13 @@
 	return ispipe;
 }
 
-static int zap_process(struct task_struct *start)
+static int zap_process(struct task_struct *start, int exit_code)
 {
 	struct task_struct *t;
 	int nr = 0;
 
 	start->signal->flags = SIGNAL_GROUP_EXIT;
+	start->signal->group_exit_code = exit_code;
 	start->signal->group_stop_count = 0;
 
 	t = start;
@@ -1590,8 +1592,7 @@
 	spin_lock_irq(&tsk->sighand->siglock);
 	if (!signal_group_exit(tsk->signal)) {
 		mm->core_state = core_state;
-		tsk->signal->group_exit_code = exit_code;
-		nr = zap_process(tsk);
+		nr = zap_process(tsk, exit_code);
 	}
 	spin_unlock_irq(&tsk->sighand->siglock);
 	if (unlikely(nr < 0))
@@ -1640,7 +1641,7 @@
 			if (p->mm) {
 				if (unlikely(p->mm == mm)) {
 					lock_task_sighand(p, &flags);
-					nr += zap_process(p);
+					nr += zap_process(p, exit_code);
 					unlock_task_sighand(p, &flags);
 				}
 				break;
@@ -1747,14 +1748,19 @@
 	}
 }
 
-int get_dumpable(struct mm_struct *mm)
+static int __get_dumpable(unsigned long mm_flags)
 {
 	int ret;
 
-	ret = mm->flags & 0x3;
+	ret = mm_flags & MMF_DUMPABLE_MASK;
 	return (ret >= 2) ? 2 : ret;
 }
 
+int get_dumpable(struct mm_struct *mm)
+{
+	return __get_dumpable(mm->flags);
+}
+
 static void wait_for_dump_helpers(struct file *file)
 {
 	struct pipe_inode_info *pipe;
@@ -1797,7 +1803,13 @@
 	struct coredump_params cprm = {
 		.signr = signr,
 		.regs = regs,
-		.limit = current->signal->rlim[RLIMIT_CORE].rlim_cur,
+		.limit = rlimit(RLIMIT_CORE),
+		/*
+		 * We must use the same mm->flags while dumping core to avoid
+		 * inconsistency of bit flags, since this flag is not protected
+		 * by any locks.
+		 */
+		.mm_flags = mm->flags,
 	};
 
 	audit_core_dumps(signr);
@@ -1816,7 +1828,7 @@
 	/*
 	 * If another thread got here first, or we are not dumpable, bail out.
 	 */
-	if (mm->core_state || !get_dumpable(mm)) {
+	if (mm->core_state || !__get_dumpable(cprm.mm_flags)) {
 		up_write(&mm->mmap_sem);
 		put_cred(cred);
 		goto fail;
@@ -1827,7 +1839,8 @@
 	 *	process nor do we know its entire history. We only know it
 	 *	was tainted so we dump it as root in mode 2.
 	 */
-	if (get_dumpable(mm) == 2) {	/* Setuid core dump mode */
+	if (__get_dumpable(cprm.mm_flags) == 2) {
+		/* Setuid core dump mode */
 		flag = O_EXCL;		/* Stop rewrite attacks */
 		cred->fsuid = 0;	/* Dump root private */
 	}
@@ -1923,8 +1936,9 @@
 	/*
 	 * Dont allow local users get cute and trick others to coredump
 	 * into their pre-created files:
+	 * Note, this is not relevant for pipes
 	 */
-	if (inode->i_uid != current_fsuid())
+	if (!ispipe && (inode->i_uid != current_fsuid()))
 		goto close_fail;
 	if (!cprm.file->f_op)
 		goto close_fail;
diff --git a/fs/exofs/common.h b/fs/exofs/common.h
index b1b178e..f0d5203 100644
--- a/fs/exofs/common.h
+++ b/fs/exofs/common.h
@@ -55,6 +55,8 @@
 /* exofs Application specific page/attribute */
 # define EXOFS_APAGE_FS_DATA	(OSD_APAGE_APP_DEFINED_FIRST + 3)
 # define EXOFS_ATTR_INODE_DATA	1
+# define EXOFS_ATTR_INODE_FILE_LAYOUT	2
+# define EXOFS_ATTR_INODE_DIR_LAYOUT	3
 
 /*
  * The maximum number of files we can have is limited by the size of the
@@ -206,4 +208,41 @@
 	(((name_len) + offsetof(struct exofs_dir_entry, name)  + \
 	  EXOFS_DIR_ROUND) & ~EXOFS_DIR_ROUND)
 
+/*
+ * The on-disk (optional) layout structure.
+ * sits in an EXOFS_ATTR_INODE_FILE_LAYOUT or EXOFS_ATTR_INODE_DIR_LAYOUT
+ * attribute, attached to any inode, usually to a directory.
+ */
+
+enum exofs_inode_layout_gen_functions {
+	LAYOUT_MOVING_WINDOW = 0,
+	LAYOUT_IMPLICT = 1,
+};
+
+struct exofs_on_disk_inode_layout {
+	__le16 gen_func; /* One of enum exofs_inode_layout_gen_functions */
+	__le16 pad;
+	union {
+		/* gen_func == LAYOUT_MOVING_WINDOW (default) */
+		struct exofs_layout_sliding_window {
+			__le32 num_devices; /* first n devices in global-table*/
+		} sliding_window __packed;
+
+		/* gen_func == LAYOUT_IMPLICT */
+		struct exofs_layout_implict_list {
+			struct exofs_dt_data_map data_map;
+			/* Variable array of size data_map.cb_num_comps. These
+			 * are device indexes of the devices in the global table
+			 */
+			__le32 dev_indexes[];
+		} implict __packed;
+	};
+} __packed;
+
+static inline size_t exofs_on_disk_inode_layout_size(unsigned max_devs)
+{
+	return sizeof(struct exofs_on_disk_inode_layout) +
+		max_devs * sizeof(__le32);
+}
+
 #endif /*ifndef __EXOFS_COM_H__*/
diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h
index c35fd46..8442e35 100644
--- a/fs/exofs/exofs.h
+++ b/fs/exofs/exofs.h
@@ -55,12 +55,28 @@
 /* u64 has problems with printk this will cast it to unsigned long long */
 #define _LLU(x) (unsigned long long)(x)
 
+struct exofs_layout {
+	osd_id		s_pid;			/* partition ID of file system*/
+
+	/* Our way of looking at the data_map */
+	unsigned stripe_unit;
+	unsigned mirrors_p1;
+
+	unsigned group_width;
+	u64	 group_depth;
+	unsigned group_count;
+
+	enum exofs_inode_layout_gen_functions lay_func;
+
+	unsigned	s_numdevs;		/* Num of devices in array    */
+	struct osd_dev	*s_ods[0];		/* Variable length            */
+};
+
 /*
  * our extension to the in-memory superblock
  */
 struct exofs_sb_info {
 	struct exofs_fscb s_fscb;		/* Written often, pre-allocate*/
-	osd_id		s_pid;			/* partition ID of file system*/
 	int		s_timeout;		/* timeout for OSD operations */
 	uint64_t	s_nextid;		/* highest object ID used     */
 	uint32_t	s_numfiles;		/* number of files on fs      */
@@ -69,22 +85,27 @@
 	atomic_t	s_curr_pending;		/* number of pending commands */
 	uint8_t		s_cred[OSD_CAP_LEN];	/* credential for the fscb    */
 
-	struct pnfs_osd_data_map data_map;	/* Default raid to use        */
-	unsigned	s_numdevs;		/* Num of devices in array    */
-	struct osd_dev	*s_ods[1];		/* Variable length, minimum 1 */
+	struct pnfs_osd_data_map data_map;	/* Default raid to use
+						 * FIXME: Needed ?
+						 */
+/*	struct exofs_layout	dir_layout;*/	/* Default dir layout */
+	struct exofs_layout	layout;		/* Default files layout,
+						 * contains the variable osd_dev
+						 * array. Keep last */
+	struct osd_dev	*_min_one_dev[1];	/* Place holder for one dev   */
 };
 
 /*
  * our extension to the in-memory inode
  */
 struct exofs_i_info {
+	struct inode   vfs_inode;          /* normal in-memory inode          */
+	wait_queue_head_t i_wq;            /* wait queue for inode            */
 	unsigned long  i_flags;            /* various atomic flags            */
 	uint32_t       i_data[EXOFS_IDATA];/*short symlink names and device #s*/
 	uint32_t       i_dir_start_lookup; /* which page to start lookup      */
-	wait_queue_head_t i_wq;            /* wait queue for inode            */
 	uint64_t       i_commit_size;      /* the object's written length     */
 	uint8_t        i_cred[OSD_CAP_LEN];/* all-powerful credential         */
-	struct inode   vfs_inode;          /* normal in-memory inode          */
 };
 
 static inline osd_id exofs_oi_objno(struct exofs_i_info *oi)
@@ -101,7 +122,7 @@
 	void			*private;
 	exofs_io_done_fn	done;
 
-	struct exofs_sb_info	*sbi;
+	struct exofs_layout	*layout;
 	struct osd_obj_id	obj;
 	u8			*cred;
 
@@ -109,7 +130,11 @@
 	loff_t			offset;
 	unsigned long		length;
 	void			*kern_buff;
-	struct bio		*bio;
+
+	struct page		**pages;
+	unsigned		nr_pages;
+	unsigned		pgbase;
+	unsigned		pages_consumed;
 
 	/* Attributes */
 	unsigned		in_attr_len;
@@ -122,6 +147,9 @@
 	struct exofs_per_dev_state {
 		struct osd_request *or;
 		struct bio *bio;
+		loff_t offset;
+		unsigned length;
+		unsigned dev;
 	} per_dev[];
 };
 
@@ -175,6 +203,12 @@
 }
 
 /*
+ * Given a layout, object_number and stripe_index return the associated global
+ * dev_index
+ */
+unsigned exofs_layout_od_id(struct exofs_layout *layout,
+			    osd_id obj_no, unsigned layout_index);
+/*
  * Maximum count of links to a file
  */
 #define EXOFS_LINK_MAX           32000
@@ -189,7 +223,8 @@
 int exofs_read_kern(struct osd_dev *od, u8 *cred, struct osd_obj_id *obj,
 		    u64 offset, void *p, unsigned length);
 
-int  exofs_get_io_state(struct exofs_sb_info *sbi, struct exofs_io_state** ios);
+int  exofs_get_io_state(struct exofs_layout *layout,
+			struct exofs_io_state **ios);
 void exofs_put_io_state(struct exofs_io_state *ios);
 
 int exofs_check_io(struct exofs_io_state *ios, u64 *resid);
@@ -226,7 +261,7 @@
 		struct page **pagep, void **fsdata);
 extern struct inode *exofs_iget(struct super_block *, unsigned long);
 struct inode *exofs_new_inode(struct inode *, int);
-extern int exofs_write_inode(struct inode *, int);
+extern int exofs_write_inode(struct inode *, struct writeback_control *wbc);
 extern void exofs_delete_inode(struct inode *);
 
 /* dir.c:                */
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 2afbceb..a17e4b7 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -41,16 +41,18 @@
 
 enum { BIO_MAX_PAGES_KMALLOC =
 		(PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec),
+	MAX_PAGES_KMALLOC =
+		PAGE_SIZE / sizeof(struct page *),
 };
 
 struct page_collect {
 	struct exofs_sb_info *sbi;
-	struct request_queue *req_q;
 	struct inode *inode;
 	unsigned expected_pages;
 	struct exofs_io_state *ios;
 
-	struct bio *bio;
+	struct page **pages;
+	unsigned alloc_pages;
 	unsigned nr_pages;
 	unsigned long length;
 	loff_t pg_first; /* keep 64bit also in 32-arches */
@@ -62,15 +64,12 @@
 	struct exofs_sb_info *sbi = inode->i_sb->s_fs_info;
 
 	pcol->sbi = sbi;
-	/* Create master bios on first Q, later on cloning, each clone will be
-	 * allocated on it's destination Q
-	 */
-	pcol->req_q = osd_request_queue(sbi->s_ods[0]);
 	pcol->inode = inode;
 	pcol->expected_pages = expected_pages;
 
 	pcol->ios = NULL;
-	pcol->bio = NULL;
+	pcol->pages = NULL;
+	pcol->alloc_pages = 0;
 	pcol->nr_pages = 0;
 	pcol->length = 0;
 	pcol->pg_first = -1;
@@ -80,7 +79,8 @@
 {
 	pcol->expected_pages -= min(pcol->nr_pages, pcol->expected_pages);
 
-	pcol->bio = NULL;
+	pcol->pages = NULL;
+	pcol->alloc_pages = 0;
 	pcol->nr_pages = 0;
 	pcol->length = 0;
 	pcol->pg_first = -1;
@@ -90,38 +90,43 @@
 	 * it might not end here. don't be left with nothing
 	 */
 	if (!pcol->expected_pages)
-		pcol->expected_pages = BIO_MAX_PAGES_KMALLOC;
+		pcol->expected_pages = MAX_PAGES_KMALLOC;
 }
 
 static int pcol_try_alloc(struct page_collect *pcol)
 {
-	int pages = min_t(unsigned, pcol->expected_pages,
-			  BIO_MAX_PAGES_KMALLOC);
+	unsigned pages = min_t(unsigned, pcol->expected_pages,
+			  MAX_PAGES_KMALLOC);
 
 	if (!pcol->ios) { /* First time allocate io_state */
-		int ret = exofs_get_io_state(pcol->sbi, &pcol->ios);
+		int ret = exofs_get_io_state(&pcol->sbi->layout, &pcol->ios);
 
 		if (ret)
 			return ret;
 	}
 
+	/* TODO: easily support bio chaining */
+	pages =  min_t(unsigned, pages,
+		       pcol->sbi->layout.group_width * BIO_MAX_PAGES_KMALLOC);
+
 	for (; pages; pages >>= 1) {
-		pcol->bio = bio_kmalloc(GFP_KERNEL, pages);
-		if (likely(pcol->bio))
+		pcol->pages = kmalloc(pages * sizeof(struct page *),
+				      GFP_KERNEL);
+		if (likely(pcol->pages)) {
+			pcol->alloc_pages = pages;
 			return 0;
+		}
 	}
 
-	EXOFS_ERR("Failed to bio_kmalloc expected_pages=%u\n",
+	EXOFS_ERR("Failed to kmalloc expected_pages=%u\n",
 		  pcol->expected_pages);
 	return -ENOMEM;
 }
 
 static void pcol_free(struct page_collect *pcol)
 {
-	if (pcol->bio) {
-		bio_put(pcol->bio);
-		pcol->bio = NULL;
-	}
+	kfree(pcol->pages);
+	pcol->pages = NULL;
 
 	if (pcol->ios) {
 		exofs_put_io_state(pcol->ios);
@@ -132,11 +137,10 @@
 static int pcol_add_page(struct page_collect *pcol, struct page *page,
 			 unsigned len)
 {
-	int added_len = bio_add_pc_page(pcol->req_q, pcol->bio, page, len, 0);
-	if (unlikely(len != added_len))
+	if (unlikely(pcol->nr_pages >= pcol->alloc_pages))
 		return -ENOMEM;
 
-	++pcol->nr_pages;
+	pcol->pages[pcol->nr_pages++] = page;
 	pcol->length += len;
 	return 0;
 }
@@ -181,7 +185,6 @@
  */
 static int __readpages_done(struct page_collect *pcol, bool do_unlock)
 {
-	struct bio_vec *bvec;
 	int i;
 	u64 resid;
 	u64 good_bytes;
@@ -193,13 +196,13 @@
 	else
 		good_bytes = pcol->length - resid;
 
-	EXOFS_DBGMSG("readpages_done(0x%lx) good_bytes=0x%llx"
+	EXOFS_DBGMSG2("readpages_done(0x%lx) good_bytes=0x%llx"
 		     " length=0x%lx nr_pages=%u\n",
 		     pcol->inode->i_ino, _LLU(good_bytes), pcol->length,
 		     pcol->nr_pages);
 
-	__bio_for_each_segment(bvec, pcol->bio, i, 0) {
-		struct page *page = bvec->bv_page;
+	for (i = 0; i < pcol->nr_pages; i++) {
+		struct page *page = pcol->pages[i];
 		struct inode *inode = page->mapping->host;
 		int page_stat;
 
@@ -218,11 +221,11 @@
 		ret = update_read_page(page, page_stat);
 		if (do_unlock)
 			unlock_page(page);
-		length += bvec->bv_len;
+		length += PAGE_SIZE;
 	}
 
 	pcol_free(pcol);
-	EXOFS_DBGMSG("readpages_done END\n");
+	EXOFS_DBGMSG2("readpages_done END\n");
 	return ret;
 }
 
@@ -238,11 +241,10 @@
 
 static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw)
 {
-	struct bio_vec *bvec;
 	int i;
 
-	__bio_for_each_segment(bvec, pcol->bio, i, 0) {
-		struct page *page = bvec->bv_page;
+	for (i = 0; i < pcol->nr_pages; i++) {
+		struct page *page = pcol->pages[i];
 
 		if (rw == READ)
 			update_read_page(page, ret);
@@ -260,13 +262,14 @@
 	struct page_collect *pcol_copy = NULL;
 	int ret;
 
-	if (!pcol->bio)
+	if (!pcol->pages)
 		return 0;
 
 	/* see comment in _readpage() about sync reads */
 	WARN_ON(is_sync && (pcol->nr_pages != 1));
 
-	ios->bio = pcol->bio;
+	ios->pages = pcol->pages;
+	ios->nr_pages = pcol->nr_pages;
 	ios->length = pcol->length;
 	ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT;
 
@@ -290,7 +293,7 @@
 
 	atomic_inc(&pcol->sbi->s_curr_pending);
 
-	EXOFS_DBGMSG("read_exec obj=0x%llx start=0x%llx length=0x%lx\n",
+	EXOFS_DBGMSG2("read_exec obj=0x%llx start=0x%llx length=0x%lx\n",
 		  ios->obj.id, _LLU(ios->offset), pcol->length);
 
 	/* pages ownership was passed to pcol_copy */
@@ -366,7 +369,7 @@
 		goto try_again;
 	}
 
-	if (!pcol->bio) {
+	if (!pcol->pages) {
 		ret = pcol_try_alloc(pcol);
 		if (unlikely(ret))
 			goto fail;
@@ -448,7 +451,6 @@
 static void writepages_done(struct exofs_io_state *ios, void *p)
 {
 	struct page_collect *pcol = p;
-	struct bio_vec *bvec;
 	int i;
 	u64 resid;
 	u64  good_bytes;
@@ -462,13 +464,13 @@
 	else
 		good_bytes = pcol->length - resid;
 
-	EXOFS_DBGMSG("writepages_done(0x%lx) good_bytes=0x%llx"
+	EXOFS_DBGMSG2("writepages_done(0x%lx) good_bytes=0x%llx"
 		     " length=0x%lx nr_pages=%u\n",
 		     pcol->inode->i_ino, _LLU(good_bytes), pcol->length,
 		     pcol->nr_pages);
 
-	__bio_for_each_segment(bvec, pcol->bio, i, 0) {
-		struct page *page = bvec->bv_page;
+	for (i = 0; i < pcol->nr_pages; i++) {
+		struct page *page = pcol->pages[i];
 		struct inode *inode = page->mapping->host;
 		int page_stat;
 
@@ -485,12 +487,12 @@
 		EXOFS_DBGMSG2("    writepages_done(0x%lx, 0x%lx) status=%d\n",
 			     inode->i_ino, page->index, page_stat);
 
-		length += bvec->bv_len;
+		length += PAGE_SIZE;
 	}
 
 	pcol_free(pcol);
 	kfree(pcol);
-	EXOFS_DBGMSG("writepages_done END\n");
+	EXOFS_DBGMSG2("writepages_done END\n");
 }
 
 static int write_exec(struct page_collect *pcol)
@@ -500,7 +502,7 @@
 	struct page_collect *pcol_copy = NULL;
 	int ret;
 
-	if (!pcol->bio)
+	if (!pcol->pages)
 		return 0;
 
 	pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL);
@@ -512,9 +514,8 @@
 
 	*pcol_copy = *pcol;
 
-	pcol_copy->bio->bi_rw |= (1 << BIO_RW); /* FIXME: bio_set_dir() */
-
-	ios->bio = pcol_copy->bio;
+	ios->pages = pcol_copy->pages;
+	ios->nr_pages = pcol_copy->nr_pages;
 	ios->offset = pcol_copy->pg_first << PAGE_CACHE_SHIFT;
 	ios->length = pcol_copy->length;
 	ios->done = writepages_done;
@@ -527,7 +528,7 @@
 	}
 
 	atomic_inc(&pcol->sbi->s_curr_pending);
-	EXOFS_DBGMSG("write_exec(0x%lx, 0x%llx) start=0x%llx length=0x%lx\n",
+	EXOFS_DBGMSG2("write_exec(0x%lx, 0x%llx) start=0x%llx length=0x%lx\n",
 		  pcol->inode->i_ino, pcol->pg_first, _LLU(ios->offset),
 		  pcol->length);
 	/* pages ownership was passed to pcol_copy */
@@ -605,7 +606,7 @@
 		goto try_again;
 	}
 
-	if (!pcol->bio) {
+	if (!pcol->pages) {
 		ret = pcol_try_alloc(pcol);
 		if (unlikely(ret))
 			goto fail;
@@ -616,7 +617,7 @@
 
 	ret = pcol_add_page(pcol, page, len);
 	if (unlikely(ret)) {
-		EXOFS_DBGMSG("Failed pcol_add_page "
+		EXOFS_DBGMSG2("Failed pcol_add_page "
 			     "nr_pages=%u total_length=0x%lx\n",
 			     pcol->nr_pages, pcol->length);
 
@@ -663,7 +664,7 @@
 	if (expected_pages < 32L)
 		expected_pages = 32L;
 
-	EXOFS_DBGMSG("inode(0x%lx) wbc->start=0x%llx wbc->end=0x%llx "
+	EXOFS_DBGMSG2("inode(0x%lx) wbc->start=0x%llx wbc->end=0x%llx "
 		     "nrpages=%lu start=0x%lx end=0x%lx expected_pages=%ld\n",
 		     mapping->host->i_ino, wbc->range_start, wbc->range_end,
 		     mapping->nrpages, start, end, expected_pages);
@@ -859,20 +860,33 @@
 	return error;
 }
 
+static const struct osd_attr g_attr_inode_file_layout = ATTR_DEF(
+	EXOFS_APAGE_FS_DATA,
+	EXOFS_ATTR_INODE_FILE_LAYOUT,
+	0);
+static const struct osd_attr g_attr_inode_dir_layout = ATTR_DEF(
+	EXOFS_APAGE_FS_DATA,
+	EXOFS_ATTR_INODE_DIR_LAYOUT,
+	0);
+
 /*
- * Read an inode from the OSD, and return it as is.  We also return the size
- * attribute in the 'obj_size' argument.
+ * Read the Linux inode info from the OSD, and return it as is. In exofs the
+ * inode info is in an application specific page/attribute of the osd-object.
  */
 static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi,
-		    struct exofs_fcb *inode, uint64_t *obj_size)
+		    struct exofs_fcb *inode)
 {
 	struct exofs_sb_info *sbi = sb->s_fs_info;
-	struct osd_attr attrs[2];
+	struct osd_attr attrs[] = {
+		[0] = g_attr_inode_data,
+		[1] = g_attr_inode_file_layout,
+		[2] = g_attr_inode_dir_layout,
+	};
 	struct exofs_io_state *ios;
+	struct exofs_on_disk_inode_layout *layout;
 	int ret;
 
-	*obj_size = ~0;
-	ret = exofs_get_io_state(sbi, &ios);
+	ret = exofs_get_io_state(&sbi->layout, &ios);
 	if (unlikely(ret)) {
 		EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
 		return ret;
@@ -882,14 +896,25 @@
 	exofs_make_credential(oi->i_cred, &ios->obj);
 	ios->cred = oi->i_cred;
 
-	attrs[0] = g_attr_inode_data;
-	attrs[1] = g_attr_logical_length;
+	attrs[1].len = exofs_on_disk_inode_layout_size(sbi->layout.s_numdevs);
+	attrs[2].len = exofs_on_disk_inode_layout_size(sbi->layout.s_numdevs);
+
 	ios->in_attr = attrs;
 	ios->in_attr_len = ARRAY_SIZE(attrs);
 
 	ret = exofs_sbi_read(ios);
-	if (ret)
+	if (unlikely(ret)) {
+		EXOFS_ERR("object(0x%llx) corrupted, return empty file=>%d\n",
+			  _LLU(ios->obj.id), ret);
+		memset(inode, 0, sizeof(*inode));
+		inode->i_mode = 0040000 | (0777 & ~022);
+		/* If object is lost on target we might as well enable it's
+		 * delete.
+		 */
+		if ((ret == -ENOENT) || (ret == -EINVAL))
+			ret = 0;
 		goto out;
+	}
 
 	ret = extract_attr_from_ios(ios, &attrs[0]);
 	if (ret) {
@@ -901,11 +926,33 @@
 
 	ret = extract_attr_from_ios(ios, &attrs[1]);
 	if (ret) {
-		EXOFS_ERR("%s: extract_attr of logical_length failed\n",
-			  __func__);
+		EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__);
 		goto out;
 	}
-	*obj_size = get_unaligned_be64(attrs[1].val_ptr);
+	if (attrs[1].len) {
+		layout = attrs[1].val_ptr;
+		if (layout->gen_func != cpu_to_le16(LAYOUT_MOVING_WINDOW)) {
+			EXOFS_ERR("%s: unsupported files layout %d\n",
+				__func__, layout->gen_func);
+			ret = -ENOTSUPP;
+			goto out;
+		}
+	}
+
+	ret = extract_attr_from_ios(ios, &attrs[2]);
+	if (ret) {
+		EXOFS_ERR("%s: extract_attr of inode_data failed\n", __func__);
+		goto out;
+	}
+	if (attrs[2].len) {
+		layout = attrs[2].val_ptr;
+		if (layout->gen_func != cpu_to_le16(LAYOUT_MOVING_WINDOW)) {
+			EXOFS_ERR("%s: unsupported meta-data layout %d\n",
+				__func__, layout->gen_func);
+			ret = -ENOTSUPP;
+			goto out;
+		}
+	}
 
 out:
 	exofs_put_io_state(ios);
@@ -925,7 +972,6 @@
 	struct exofs_i_info *oi;
 	struct exofs_fcb fcb;
 	struct inode *inode;
-	uint64_t obj_size;
 	int ret;
 
 	inode = iget_locked(sb, ino);
@@ -937,7 +983,7 @@
 	__oi_init(oi);
 
 	/* read the inode from the osd */
-	ret = exofs_get_inode(sb, oi, &fcb, &obj_size);
+	ret = exofs_get_inode(sb, oi, &fcb);
 	if (ret)
 		goto bad_inode;
 
@@ -958,13 +1004,6 @@
 	inode->i_blkbits = EXOFS_BLKSHIFT;
 	inode->i_generation = le32_to_cpu(fcb.i_generation);
 
-	if ((inode->i_size != obj_size) &&
-		(!exofs_inode_is_fast_symlink(inode))) {
-		EXOFS_ERR("WARNING: Size of inode=%llu != object=%llu\n",
-			  inode->i_size, _LLU(obj_size));
-		/* FIXME: call exofs_inode_recovery() */
-	}
-
 	oi->i_dir_start_lookup = 0;
 
 	if ((inode->i_nlink == 0) && (inode->i_mode == 0)) {
@@ -1043,7 +1082,7 @@
 
 	if (unlikely(ret)) {
 		EXOFS_ERR("object=0x%llx creation faild in pid=0x%llx",
-			  _LLU(exofs_oi_objno(oi)), _LLU(sbi->s_pid));
+			  _LLU(exofs_oi_objno(oi)), _LLU(sbi->layout.s_pid));
 		/*TODO: When FS is corrupted creation can fail, object already
 		 * exist. Get rid of this asynchronous creation, if exist
 		 * increment the obj counter and try the next object. Until we
@@ -1104,7 +1143,7 @@
 
 	mark_inode_dirty(inode);
 
-	ret = exofs_get_io_state(sbi, &ios);
+	ret = exofs_get_io_state(&sbi->layout, &ios);
 	if (unlikely(ret)) {
 		EXOFS_ERR("exofs_new_inode: exofs_get_io_state failed\n");
 		return ERR_PTR(ret);
@@ -1170,8 +1209,10 @@
 	int ret;
 
 	args = kzalloc(sizeof(*args), GFP_KERNEL);
-	if (!args)
+	if (!args) {
+		EXOFS_DBGMSG("Faild kzalloc of args\n");
 		return -ENOMEM;
+	}
 
 	fcb = &args->fcb;
 
@@ -1200,7 +1241,7 @@
 	} else
 		memcpy(fcb->i_data, oi->i_data, sizeof(fcb->i_data));
 
-	ret = exofs_get_io_state(sbi, &ios);
+	ret = exofs_get_io_state(&sbi->layout, &ios);
 	if (unlikely(ret)) {
 		EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__);
 		goto free_args;
@@ -1234,13 +1275,14 @@
 free_args:
 	kfree(args);
 out:
-	EXOFS_DBGMSG("ret=>%d\n", ret);
+	EXOFS_DBGMSG("(0x%lx) do_sync=%d ret=>%d\n",
+		     inode->i_ino, do_sync, ret);
 	return ret;
 }
 
-int exofs_write_inode(struct inode *inode, int wait)
+int exofs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
-	return exofs_update_inode(inode, wait);
+	return exofs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
 }
 
 /*
@@ -1283,7 +1325,7 @@
 
 	clear_inode(inode);
 
-	ret = exofs_get_io_state(sbi, &ios);
+	ret = exofs_get_io_state(&sbi->layout, &ios);
 	if (unlikely(ret)) {
 		EXOFS_ERR("%s: exofs_get_io_state failed\n", __func__);
 		return;
diff --git a/fs/exofs/ios.c b/fs/exofs/ios.c
index 5bad01f..5293bc4 100644
--- a/fs/exofs/ios.c
+++ b/fs/exofs/ios.c
@@ -23,9 +23,13 @@
  */
 
 #include <scsi/scsi_device.h>
+#include <asm/div64.h>
 
 #include "exofs.h"
 
+#define EXOFS_DBGMSG2(M...) do {} while (0)
+/* #define EXOFS_DBGMSG2 EXOFS_DBGMSG */
+
 void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj)
 {
 	osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
@@ -64,21 +68,24 @@
 	return ret;
 }
 
-int exofs_get_io_state(struct exofs_sb_info *sbi, struct exofs_io_state** pios)
+int exofs_get_io_state(struct exofs_layout *layout,
+		       struct exofs_io_state **pios)
 {
 	struct exofs_io_state *ios;
 
 	/*TODO: Maybe use kmem_cach per sbi of size
-	 * exofs_io_state_size(sbi->s_numdevs)
+	 * exofs_io_state_size(layout->s_numdevs)
 	 */
-	ios = kzalloc(exofs_io_state_size(sbi->s_numdevs), GFP_KERNEL);
+	ios = kzalloc(exofs_io_state_size(layout->s_numdevs), GFP_KERNEL);
 	if (unlikely(!ios)) {
+		EXOFS_DBGMSG("Faild kzalloc bytes=%d\n",
+			     exofs_io_state_size(layout->s_numdevs));
 		*pios = NULL;
 		return -ENOMEM;
 	}
 
-	ios->sbi = sbi;
-	ios->obj.partition = sbi->s_pid;
+	ios->layout = layout;
+	ios->obj.partition = layout->s_pid;
 	*pios = ios;
 	return 0;
 }
@@ -101,6 +108,29 @@
 	}
 }
 
+unsigned exofs_layout_od_id(struct exofs_layout *layout,
+			    osd_id obj_no, unsigned layout_index)
+{
+/*	switch (layout->lay_func) {
+	case LAYOUT_MOVING_WINDOW:
+	{*/
+		unsigned dev_mod = obj_no;
+
+		return (layout_index + dev_mod * layout->mirrors_p1) %
+							      layout->s_numdevs;
+/*	}
+	case LAYOUT_FUNC_IMPLICT:
+		return layout->devs[layout_index];
+	}*/
+}
+
+static inline struct osd_dev *exofs_ios_od(struct exofs_io_state *ios,
+					   unsigned layout_index)
+{
+	return ios->layout->s_ods[
+		exofs_layout_od_id(ios->layout, ios->obj.id, layout_index)];
+}
+
 static void _sync_done(struct exofs_io_state *ios, void *p)
 {
 	struct completion *waiting = p;
@@ -168,6 +198,21 @@
 	return ret;
 }
 
+static void _clear_bio(struct bio *bio)
+{
+	struct bio_vec *bv;
+	unsigned i;
+
+	__bio_for_each_segment(bv, bio, i, 0) {
+		unsigned this_count = bv->bv_len;
+
+		if (likely(PAGE_SIZE == this_count))
+			clear_highpage(bv->bv_page);
+		else
+			zero_user(bv->bv_page, bv->bv_offset, this_count);
+	}
+}
+
 int exofs_check_io(struct exofs_io_state *ios, u64 *resid)
 {
 	enum osd_err_priority acumulated_osd_err = 0;
@@ -176,16 +221,25 @@
 
 	for (i = 0; i < ios->numdevs; i++) {
 		struct osd_sense_info osi;
-		int ret = osd_req_decode_sense(ios->per_dev[i].or, &osi);
+		struct osd_request *or = ios->per_dev[i].or;
+		int ret;
 
+		if (unlikely(!or))
+			continue;
+
+		ret = osd_req_decode_sense(or, &osi);
 		if (likely(!ret))
 			continue;
 
-		if (unlikely(ret == -EFAULT)) {
-			EXOFS_DBGMSG("%s: EFAULT Need page clear\n", __func__);
-			/*FIXME: All the pages in this device range should:
-			 *	clear_highpage(page);
-			 */
+		if (OSD_ERR_PRI_CLEAR_PAGES == osi.osd_err_pri) {
+			/* start read offset passed endof file */
+			_clear_bio(ios->per_dev[i].bio);
+			EXOFS_DBGMSG("start read offset passed end of file "
+				"offset=0x%llx, length=0x%llx\n",
+				_LLU(ios->per_dev[i].offset),
+				_LLU(ios->per_dev[i].length));
+
+			continue; /* we recovered */
 		}
 
 		if (osi.osd_err_pri >= acumulated_osd_err) {
@@ -205,14 +259,259 @@
 	return acumulated_lin_err;
 }
 
+/*
+ * L - logical offset into the file
+ *
+ * U - The number of bytes in a stripe within a group
+ *
+ *	U = stripe_unit * group_width
+ *
+ * T - The number of bytes striped within a group of component objects
+ *     (before advancing to the next group)
+ *
+ *	T = stripe_unit * group_width * group_depth
+ *
+ * S - The number of bytes striped across all component objects
+ *     before the pattern repeats
+ *
+ *	S = stripe_unit * group_width * group_depth * group_count
+ *
+ * M - The "major" (i.e., across all components) stripe number
+ *
+ *	M = L / S
+ *
+ * G - Counts the groups from the beginning of the major stripe
+ *
+ *	G = (L - (M * S)) / T	[or (L % S) / T]
+ *
+ * H - The byte offset within the group
+ *
+ *	H = (L - (M * S)) % T	[or (L % S) % T]
+ *
+ * N - The "minor" (i.e., across the group) stripe number
+ *
+ *	N = H / U
+ *
+ * C - The component index coresponding to L
+ *
+ *	C = (H - (N * U)) / stripe_unit + G * group_width
+ *	[or (L % U) / stripe_unit + G * group_width]
+ *
+ * O - The component offset coresponding to L
+ *
+ *	O = L % stripe_unit + N * stripe_unit + M * group_depth * stripe_unit
+ */
+struct _striping_info {
+	u64 obj_offset;
+	u64 group_length;
+	u64 total_group_length;
+	u64 Major;
+	unsigned dev;
+	unsigned unit_off;
+};
+
+static void _calc_stripe_info(struct exofs_io_state *ios, u64 file_offset,
+			      struct _striping_info *si)
+{
+	u32	stripe_unit = ios->layout->stripe_unit;
+	u32	group_width = ios->layout->group_width;
+	u64	group_depth = ios->layout->group_depth;
+
+	u32	U = stripe_unit * group_width;
+	u64	T = U * group_depth;
+	u64	S = T * ios->layout->group_count;
+	u64	M = div64_u64(file_offset, S);
+
+	/*
+	G = (L - (M * S)) / T
+	H = (L - (M * S)) % T
+	*/
+	u64	LmodS = file_offset - M * S;
+	u32	G = div64_u64(LmodS, T);
+	u64	H = LmodS - G * T;
+
+	u32	N = div_u64(H, U);
+
+	/* "H - (N * U)" is just "H % U" so it's bound to u32 */
+	si->dev = (u32)(H - (N * U)) / stripe_unit + G * group_width;
+	si->dev *= ios->layout->mirrors_p1;
+
+	div_u64_rem(file_offset, stripe_unit, &si->unit_off);
+
+	si->obj_offset = si->unit_off + (N * stripe_unit) +
+				  (M * group_depth * stripe_unit);
+
+	si->group_length = T - H;
+	si->total_group_length = T;
+	si->Major = M;
+}
+
+static int _add_stripe_unit(struct exofs_io_state *ios,  unsigned *cur_pg,
+		unsigned pgbase, struct exofs_per_dev_state *per_dev,
+		int cur_len)
+{
+	unsigned pg = *cur_pg;
+	struct request_queue *q =
+			osd_request_queue(exofs_ios_od(ios, per_dev->dev));
+
+	per_dev->length += cur_len;
+
+	if (per_dev->bio == NULL) {
+		unsigned pages_in_stripe = ios->layout->group_width *
+					(ios->layout->stripe_unit / PAGE_SIZE);
+		unsigned bio_size = (ios->nr_pages + pages_in_stripe) /
+						ios->layout->group_width;
+
+		per_dev->bio = bio_kmalloc(GFP_KERNEL, bio_size);
+		if (unlikely(!per_dev->bio)) {
+			EXOFS_DBGMSG("Faild to allocate BIO size=%u\n",
+				     bio_size);
+			return -ENOMEM;
+		}
+	}
+
+	while (cur_len > 0) {
+		unsigned pglen = min_t(unsigned, PAGE_SIZE - pgbase, cur_len);
+		unsigned added_len;
+
+		BUG_ON(ios->nr_pages <= pg);
+		cur_len -= pglen;
+
+		added_len = bio_add_pc_page(q, per_dev->bio, ios->pages[pg],
+					    pglen, pgbase);
+		if (unlikely(pglen != added_len))
+			return -ENOMEM;
+		pgbase = 0;
+		++pg;
+	}
+	BUG_ON(cur_len);
+
+	*cur_pg = pg;
+	return 0;
+}
+
+static int _prepare_one_group(struct exofs_io_state *ios, u64 length,
+			      struct _striping_info *si, unsigned first_comp)
+{
+	unsigned stripe_unit = ios->layout->stripe_unit;
+	unsigned mirrors_p1 = ios->layout->mirrors_p1;
+	unsigned devs_in_group = ios->layout->group_width * mirrors_p1;
+	unsigned dev = si->dev;
+	unsigned first_dev = dev - (dev % devs_in_group);
+	unsigned comp = first_comp + (dev - first_dev);
+	unsigned max_comp = ios->numdevs ? ios->numdevs - mirrors_p1 : 0;
+	unsigned cur_pg = ios->pages_consumed;
+	int ret = 0;
+
+	while (length) {
+		struct exofs_per_dev_state *per_dev = &ios->per_dev[comp];
+		unsigned cur_len, page_off = 0;
+
+		if (!per_dev->length) {
+			per_dev->dev = dev;
+			if (dev < si->dev) {
+				per_dev->offset = si->obj_offset + stripe_unit -
+								   si->unit_off;
+				cur_len = stripe_unit;
+			} else if (dev == si->dev) {
+				per_dev->offset = si->obj_offset;
+				cur_len = stripe_unit - si->unit_off;
+				page_off = si->unit_off & ~PAGE_MASK;
+				BUG_ON(page_off && (page_off != ios->pgbase));
+			} else { /* dev > si->dev */
+				per_dev->offset = si->obj_offset - si->unit_off;
+				cur_len = stripe_unit;
+			}
+
+			if (max_comp < comp)
+				max_comp = comp;
+
+			dev += mirrors_p1;
+			dev = (dev % devs_in_group) + first_dev;
+		} else {
+			cur_len = stripe_unit;
+		}
+		if (cur_len >= length)
+			cur_len = length;
+
+		ret = _add_stripe_unit(ios, &cur_pg, page_off , per_dev,
+				       cur_len);
+		if (unlikely(ret))
+			goto out;
+
+		comp += mirrors_p1;
+		comp = (comp % devs_in_group) + first_comp;
+
+		length -= cur_len;
+	}
+out:
+	ios->numdevs = max_comp + mirrors_p1;
+	ios->pages_consumed = cur_pg;
+	return ret;
+}
+
+static int _prepare_for_striping(struct exofs_io_state *ios)
+{
+	u64 length = ios->length;
+	struct _striping_info si;
+	unsigned devs_in_group = ios->layout->group_width *
+				 ios->layout->mirrors_p1;
+	unsigned first_comp = 0;
+	int ret = 0;
+
+	_calc_stripe_info(ios, ios->offset, &si);
+
+	if (!ios->pages) {
+		if (ios->kern_buff) {
+			struct exofs_per_dev_state *per_dev = &ios->per_dev[0];
+
+			per_dev->offset = si.obj_offset;
+			per_dev->dev = si.dev;
+
+			/* no cross device without page array */
+			BUG_ON((ios->layout->group_width > 1) &&
+			       (si.unit_off + ios->length >
+				ios->layout->stripe_unit));
+		}
+		ios->numdevs = ios->layout->mirrors_p1;
+		return 0;
+	}
+
+	while (length) {
+		if (length < si.group_length)
+			si.group_length = length;
+
+		ret = _prepare_one_group(ios, si.group_length, &si, first_comp);
+		if (unlikely(ret))
+			goto out;
+
+		length -= si.group_length;
+
+		si.group_length = si.total_group_length;
+		si.unit_off = 0;
+		++si.Major;
+		si.obj_offset = si.Major * ios->layout->stripe_unit *
+						ios->layout->group_depth;
+
+		si.dev = (si.dev - (si.dev % devs_in_group)) + devs_in_group;
+		si.dev %= ios->layout->s_numdevs;
+
+		first_comp += devs_in_group;
+		first_comp %= ios->layout->s_numdevs;
+	}
+
+out:
+	return ret;
+}
+
 int exofs_sbi_create(struct exofs_io_state *ios)
 {
 	int i, ret;
 
-	for (i = 0; i < ios->sbi->s_numdevs; i++) {
+	for (i = 0; i < ios->layout->s_numdevs; i++) {
 		struct osd_request *or;
 
-		or = osd_start_request(ios->sbi->s_ods[i], GFP_KERNEL);
+		or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
 		if (unlikely(!or)) {
 			EXOFS_ERR("%s: osd_start_request failed\n", __func__);
 			ret = -ENOMEM;
@@ -233,10 +532,10 @@
 {
 	int i, ret;
 
-	for (i = 0; i < ios->sbi->s_numdevs; i++) {
+	for (i = 0; i < ios->layout->s_numdevs; i++) {
 		struct osd_request *or;
 
-		or = osd_start_request(ios->sbi->s_ods[i], GFP_KERNEL);
+		or = osd_start_request(exofs_ios_od(ios, i), GFP_KERNEL);
 		if (unlikely(!or)) {
 			EXOFS_ERR("%s: osd_start_request failed\n", __func__);
 			ret = -ENOMEM;
@@ -253,51 +552,74 @@
 	return ret;
 }
 
-int exofs_sbi_write(struct exofs_io_state *ios)
+static int _sbi_write_mirror(struct exofs_io_state *ios, int cur_comp)
 {
-	int i, ret;
+	struct exofs_per_dev_state *master_dev = &ios->per_dev[cur_comp];
+	unsigned dev = ios->per_dev[cur_comp].dev;
+	unsigned last_comp = cur_comp + ios->layout->mirrors_p1;
+	int ret = 0;
 
-	for (i = 0; i < ios->sbi->s_numdevs; i++) {
+	if (ios->pages && !master_dev->length)
+		return 0; /* Just an empty slot */
+
+	for (; cur_comp < last_comp; ++cur_comp, ++dev) {
+		struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
 		struct osd_request *or;
 
-		or = osd_start_request(ios->sbi->s_ods[i], GFP_KERNEL);
+		or = osd_start_request(exofs_ios_od(ios, dev), GFP_KERNEL);
 		if (unlikely(!or)) {
 			EXOFS_ERR("%s: osd_start_request failed\n", __func__);
 			ret = -ENOMEM;
 			goto out;
 		}
-		ios->per_dev[i].or = or;
-		ios->numdevs++;
+		per_dev->or = or;
+		per_dev->offset = master_dev->offset;
 
-		if (ios->bio) {
+		if (ios->pages) {
 			struct bio *bio;
 
-			if (i != 0) {
+			if (per_dev != master_dev) {
 				bio = bio_kmalloc(GFP_KERNEL,
-						  ios->bio->bi_max_vecs);
+						  master_dev->bio->bi_max_vecs);
 				if (unlikely(!bio)) {
+					EXOFS_DBGMSG(
+					      "Faild to allocate BIO size=%u\n",
+					      master_dev->bio->bi_max_vecs);
 					ret = -ENOMEM;
 					goto out;
 				}
 
-				__bio_clone(bio, ios->bio);
+				__bio_clone(bio, master_dev->bio);
 				bio->bi_bdev = NULL;
 				bio->bi_next = NULL;
-				ios->per_dev[i].bio =  bio;
+				per_dev->length = master_dev->length;
+				per_dev->bio =  bio;
+				per_dev->dev = dev;
 			} else {
-				bio = ios->bio;
+				bio = master_dev->bio;
+				/* FIXME: bio_set_dir() */
+				bio->bi_rw |= (1 << BIO_RW);
 			}
 
-			osd_req_write(or, &ios->obj, ios->offset, bio,
-				      ios->length);
-/*			EXOFS_DBGMSG("write sync=%d\n", sync);*/
+			osd_req_write(or, &ios->obj, per_dev->offset, bio,
+				      per_dev->length);
+			EXOFS_DBGMSG("write(0x%llx) offset=0x%llx "
+				      "length=0x%llx dev=%d\n",
+				     _LLU(ios->obj.id), _LLU(per_dev->offset),
+				     _LLU(per_dev->length), dev);
 		} else if (ios->kern_buff) {
-			osd_req_write_kern(or, &ios->obj, ios->offset,
+			ret = osd_req_write_kern(or, &ios->obj, per_dev->offset,
 					   ios->kern_buff, ios->length);
-/*			EXOFS_DBGMSG("write_kern sync=%d\n", sync);*/
+			if (unlikely(ret))
+				goto out;
+			EXOFS_DBGMSG2("write_kern(0x%llx) offset=0x%llx "
+				      "length=0x%llx dev=%d\n",
+				     _LLU(ios->obj.id), _LLU(per_dev->offset),
+				     _LLU(ios->length), dev);
 		} else {
 			osd_req_set_attributes(or, &ios->obj);
-/*			EXOFS_DBGMSG("set_attributes sync=%d\n", sync);*/
+			EXOFS_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n",
+				     _LLU(ios->obj.id), ios->out_attr_len, dev);
 		}
 
 		if (ios->out_attr)
@@ -308,54 +630,93 @@
 			osd_req_add_get_attr_list(or, ios->in_attr,
 						  ios->in_attr_len);
 	}
-	ret = exofs_io_execute(ios);
 
 out:
 	return ret;
 }
 
+int exofs_sbi_write(struct exofs_io_state *ios)
+{
+	int i;
+	int ret;
+
+	ret = _prepare_for_striping(ios);
+	if (unlikely(ret))
+		return ret;
+
+	for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
+		ret = _sbi_write_mirror(ios, i);
+		if (unlikely(ret))
+			return ret;
+	}
+
+	ret = exofs_io_execute(ios);
+	return ret;
+}
+
+static int _sbi_read_mirror(struct exofs_io_state *ios, unsigned cur_comp)
+{
+	struct osd_request *or;
+	struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
+	unsigned first_dev = (unsigned)ios->obj.id;
+
+	if (ios->pages && !per_dev->length)
+		return 0; /* Just an empty slot */
+
+	first_dev = per_dev->dev + first_dev % ios->layout->mirrors_p1;
+	or = osd_start_request(exofs_ios_od(ios, first_dev), GFP_KERNEL);
+	if (unlikely(!or)) {
+		EXOFS_ERR("%s: osd_start_request failed\n", __func__);
+		return -ENOMEM;
+	}
+	per_dev->or = or;
+
+	if (ios->pages) {
+		osd_req_read(or, &ios->obj, per_dev->offset,
+				per_dev->bio, per_dev->length);
+		EXOFS_DBGMSG("read(0x%llx) offset=0x%llx length=0x%llx"
+			     " dev=%d\n", _LLU(ios->obj.id),
+			     _LLU(per_dev->offset), _LLU(per_dev->length),
+			     first_dev);
+	} else if (ios->kern_buff) {
+		int ret = osd_req_read_kern(or, &ios->obj, per_dev->offset,
+					    ios->kern_buff, ios->length);
+		EXOFS_DBGMSG2("read_kern(0x%llx) offset=0x%llx "
+			      "length=0x%llx dev=%d ret=>%d\n",
+			      _LLU(ios->obj.id), _LLU(per_dev->offset),
+			      _LLU(ios->length), first_dev, ret);
+		if (unlikely(ret))
+			return ret;
+	} else {
+		osd_req_get_attributes(or, &ios->obj);
+		EXOFS_DBGMSG2("obj(0x%llx) get_attributes=%d dev=%d\n",
+			      _LLU(ios->obj.id), ios->in_attr_len, first_dev);
+	}
+	if (ios->out_attr)
+		osd_req_add_set_attr_list(or, ios->out_attr, ios->out_attr_len);
+
+	if (ios->in_attr)
+		osd_req_add_get_attr_list(or, ios->in_attr, ios->in_attr_len);
+
+	return 0;
+}
+
 int exofs_sbi_read(struct exofs_io_state *ios)
 {
-	int i, ret;
+	int i;
+	int ret;
 
-	for (i = 0; i < 1; i++) {
-		struct osd_request *or;
-		unsigned first_dev = (unsigned)ios->obj.id;
+	ret = _prepare_for_striping(ios);
+	if (unlikely(ret))
+		return ret;
 
-		first_dev %= ios->sbi->s_numdevs;
-		or = osd_start_request(ios->sbi->s_ods[first_dev], GFP_KERNEL);
-		if (unlikely(!or)) {
-			EXOFS_ERR("%s: osd_start_request failed\n", __func__);
-			ret = -ENOMEM;
-			goto out;
-		}
-		ios->per_dev[i].or = or;
-		ios->numdevs++;
-
-		if (ios->bio) {
-			osd_req_read(or, &ios->obj, ios->offset, ios->bio,
-				     ios->length);
-/*			EXOFS_DBGMSG("read sync=%d\n", sync);*/
-		} else if (ios->kern_buff) {
-			osd_req_read_kern(or, &ios->obj, ios->offset,
-					   ios->kern_buff, ios->length);
-/*			EXOFS_DBGMSG("read_kern sync=%d\n", sync);*/
-		} else {
-			osd_req_get_attributes(or, &ios->obj);
-/*			EXOFS_DBGMSG("get_attributes sync=%d\n", sync);*/
-		}
-
-		if (ios->out_attr)
-			osd_req_add_set_attr_list(or, ios->out_attr,
-						  ios->out_attr_len);
-
-		if (ios->in_attr)
-			osd_req_add_get_attr_list(or, ios->in_attr,
-						  ios->in_attr_len);
+	for (i = 0; i < ios->numdevs; i += ios->layout->mirrors_p1) {
+		ret = _sbi_read_mirror(ios, i);
+		if (unlikely(ret))
+			return ret;
 	}
-	ret = exofs_io_execute(ios);
 
-out:
+	ret = exofs_io_execute(ios);
 	return ret;
 }
 
@@ -380,42 +741,82 @@
 	return -EIO;
 }
 
+static int _truncate_mirrors(struct exofs_io_state *ios, unsigned cur_comp,
+			     struct osd_attr *attr)
+{
+	int last_comp = cur_comp + ios->layout->mirrors_p1;
+
+	for (; cur_comp < last_comp; ++cur_comp) {
+		struct exofs_per_dev_state *per_dev = &ios->per_dev[cur_comp];
+		struct osd_request *or;
+
+		or = osd_start_request(exofs_ios_od(ios, cur_comp), GFP_KERNEL);
+		if (unlikely(!or)) {
+			EXOFS_ERR("%s: osd_start_request failed\n", __func__);
+			return -ENOMEM;
+		}
+		per_dev->or = or;
+
+		osd_req_set_attributes(or, &ios->obj);
+		osd_req_add_set_attr_list(or, attr, 1);
+	}
+
+	return 0;
+}
+
 int exofs_oi_truncate(struct exofs_i_info *oi, u64 size)
 {
 	struct exofs_sb_info *sbi = oi->vfs_inode.i_sb->s_fs_info;
 	struct exofs_io_state *ios;
-	struct osd_attr attr;
-	__be64 newsize;
+	struct exofs_trunc_attr {
+		struct osd_attr attr;
+		__be64 newsize;
+	} *size_attrs;
+	struct _striping_info si;
 	int i, ret;
 
-	if (exofs_get_io_state(sbi, &ios))
-		return -ENOMEM;
+	ret = exofs_get_io_state(&sbi->layout, &ios);
+	if (unlikely(ret))
+		return ret;
+
+	size_attrs = kcalloc(ios->layout->group_width, sizeof(*size_attrs),
+			     GFP_KERNEL);
+	if (unlikely(!size_attrs)) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
 	ios->obj.id = exofs_oi_objno(oi);
 	ios->cred = oi->i_cred;
 
-	newsize = cpu_to_be64(size);
-	attr = g_attr_logical_length;
-	attr.val_ptr = &newsize;
+	ios->numdevs = ios->layout->s_numdevs;
+	_calc_stripe_info(ios, size, &si);
 
-	for (i = 0; i < sbi->s_numdevs; i++) {
-		struct osd_request *or;
+	for (i = 0; i < ios->layout->group_width; ++i) {
+		struct exofs_trunc_attr *size_attr = &size_attrs[i];
+		u64 obj_size;
 
-		or = osd_start_request(sbi->s_ods[i], GFP_KERNEL);
-		if (unlikely(!or)) {
-			EXOFS_ERR("%s: osd_start_request failed\n", __func__);
-			ret = -ENOMEM;
+		if (i < si.dev)
+			obj_size = si.obj_offset +
+					ios->layout->stripe_unit - si.unit_off;
+		else if (i == si.dev)
+			obj_size = si.obj_offset;
+		else /* i > si.dev */
+			obj_size = si.obj_offset - si.unit_off;
+
+		size_attr->newsize = cpu_to_be64(obj_size);
+		size_attr->attr = g_attr_logical_length;
+		size_attr->attr.val_ptr = &size_attr->newsize;
+
+		ret = _truncate_mirrors(ios, i * ios->layout->mirrors_p1,
+					&size_attr->attr);
+		if (unlikely(ret))
 			goto out;
-		}
-		ios->per_dev[i].or = or;
-		ios->numdevs++;
-
-		osd_req_set_attributes(or, &ios->obj);
-		osd_req_add_set_attr_list(or, &attr, 1);
 	}
 	ret = exofs_io_execute(ios);
 
 out:
+	kfree(size_attrs);
 	exofs_put_io_state(ios);
 	return ret;
 }
diff --git a/fs/exofs/super.c b/fs/exofs/super.c
index a1d1e77..6cf5e4e 100644
--- a/fs/exofs/super.c
+++ b/fs/exofs/super.c
@@ -210,7 +210,7 @@
 	sbi = sb->s_fs_info;
 	fscb = &sbi->s_fscb;
 
-	ret = exofs_get_io_state(sbi, &ios);
+	ret = exofs_get_io_state(&sbi->layout, &ios);
 	if (ret)
 		goto out;
 
@@ -264,12 +264,12 @@
 
 void exofs_free_sbi(struct exofs_sb_info *sbi)
 {
-	while (sbi->s_numdevs) {
-		int i = --sbi->s_numdevs;
-		struct osd_dev *od = sbi->s_ods[i];
+	while (sbi->layout.s_numdevs) {
+		int i = --sbi->layout.s_numdevs;
+		struct osd_dev *od = sbi->layout.s_ods[i];
 
 		if (od) {
-			sbi->s_ods[i] = NULL;
+			sbi->layout.s_ods[i] = NULL;
 			osduld_put_device(od);
 		}
 	}
@@ -298,7 +298,8 @@
 				  msecs_to_jiffies(100));
 	}
 
-	_exofs_print_device("Unmounting", NULL, sbi->s_ods[0], sbi->s_pid);
+	_exofs_print_device("Unmounting", NULL, sbi->layout.s_ods[0],
+			    sbi->layout.s_pid);
 
 	exofs_free_sbi(sbi);
 	sb->s_fs_info = NULL;
@@ -307,6 +308,8 @@
 static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs,
 				    struct exofs_device_table *dt)
 {
+	u64 stripe_length;
+
 	sbi->data_map.odm_num_comps   =
 				le32_to_cpu(dt->dt_data_map.cb_num_comps);
 	sbi->data_map.odm_stripe_unit =
@@ -320,14 +323,63 @@
 	sbi->data_map.odm_raid_algorithm  =
 				le32_to_cpu(dt->dt_data_map.cb_raid_algorithm);
 
-/* FIXME: Hard coded mirror only for now. if not so do not mount */
-	if ((sbi->data_map.odm_num_comps != numdevs) ||
-	    (sbi->data_map.odm_stripe_unit != EXOFS_BLKSIZE) ||
-	    (sbi->data_map.odm_raid_algorithm != PNFS_OSD_RAID_0) ||
-	    (sbi->data_map.odm_mirror_cnt != (numdevs - 1)))
+/* FIXME: Only raid0 for now. if not so, do not mount */
+	if (sbi->data_map.odm_num_comps != numdevs) {
+		EXOFS_ERR("odm_num_comps(%u) != numdevs(%u)\n",
+			  sbi->data_map.odm_num_comps, numdevs);
 		return -EINVAL;
-	else
-		return 0;
+	}
+	if (sbi->data_map.odm_raid_algorithm != PNFS_OSD_RAID_0) {
+		EXOFS_ERR("Only RAID_0 for now\n");
+		return -EINVAL;
+	}
+	if (0 != (numdevs % (sbi->data_map.odm_mirror_cnt + 1))) {
+		EXOFS_ERR("Data Map wrong, numdevs=%d mirrors=%d\n",
+			  numdevs, sbi->data_map.odm_mirror_cnt);
+		return -EINVAL;
+	}
+
+	if (0 != (sbi->data_map.odm_stripe_unit & ~PAGE_MASK)) {
+		EXOFS_ERR("Stripe Unit(0x%llx)"
+			  " must be Multples of PAGE_SIZE(0x%lx)\n",
+			  _LLU(sbi->data_map.odm_stripe_unit), PAGE_SIZE);
+		return -EINVAL;
+	}
+
+	sbi->layout.stripe_unit = sbi->data_map.odm_stripe_unit;
+	sbi->layout.mirrors_p1 = sbi->data_map.odm_mirror_cnt + 1;
+
+	if (sbi->data_map.odm_group_width) {
+		sbi->layout.group_width = sbi->data_map.odm_group_width;
+		sbi->layout.group_depth = sbi->data_map.odm_group_depth;
+		if (!sbi->layout.group_depth) {
+			EXOFS_ERR("group_depth == 0 && group_width != 0\n");
+			return -EINVAL;
+		}
+		sbi->layout.group_count = sbi->data_map.odm_num_comps /
+						sbi->layout.mirrors_p1 /
+						sbi->data_map.odm_group_width;
+	} else {
+		if (sbi->data_map.odm_group_depth) {
+			printk(KERN_NOTICE "Warning: group_depth ignored "
+				"group_width == 0 && group_depth == %d\n",
+				sbi->data_map.odm_group_depth);
+			sbi->data_map.odm_group_depth = 0;
+		}
+		sbi->layout.group_width = sbi->data_map.odm_num_comps /
+							sbi->layout.mirrors_p1;
+		sbi->layout.group_depth = -1;
+		sbi->layout.group_count = 1;
+	}
+
+	stripe_length = (u64)sbi->layout.group_width * sbi->layout.stripe_unit;
+	if (stripe_length >= (1ULL << 32)) {
+		EXOFS_ERR("Total Stripe length(0x%llx)"
+			  " >= 32bit is not supported\n", _LLU(stripe_length));
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 /* @odi is valid only as long as @fscb_dev is valid */
@@ -361,7 +413,7 @@
 {
 	struct exofs_sb_info *sbi = *psbi;
 	struct osd_dev *fscb_od;
-	struct osd_obj_id obj = {.partition = sbi->s_pid,
+	struct osd_obj_id obj = {.partition = sbi->layout.s_pid,
 				 .id = EXOFS_DEVTABLE_ID};
 	struct exofs_device_table *dt;
 	unsigned table_bytes = table_count * sizeof(dt->dt_dev_table[0]) +
@@ -376,9 +428,9 @@
 		return -ENOMEM;
 	}
 
-	fscb_od = sbi->s_ods[0];
-	sbi->s_ods[0] = NULL;
-	sbi->s_numdevs = 0;
+	fscb_od = sbi->layout.s_ods[0];
+	sbi->layout.s_ods[0] = NULL;
+	sbi->layout.s_numdevs = 0;
 	ret = exofs_read_kern(fscb_od, sbi->s_cred, &obj, 0, dt, table_bytes);
 	if (unlikely(ret)) {
 		EXOFS_ERR("ERROR: reading device table\n");
@@ -397,14 +449,15 @@
 		goto out;
 
 	if (likely(numdevs > 1)) {
-		unsigned size = numdevs * sizeof(sbi->s_ods[0]);
+		unsigned size = numdevs * sizeof(sbi->layout.s_ods[0]);
 
 		sbi = krealloc(sbi, sizeof(*sbi) + size, GFP_KERNEL);
 		if (unlikely(!sbi)) {
 			ret = -ENOMEM;
 			goto out;
 		}
-		memset(&sbi->s_ods[1], 0, size - sizeof(sbi->s_ods[0]));
+		memset(&sbi->layout.s_ods[1], 0,
+		       size - sizeof(sbi->layout.s_ods[0]));
 		*psbi = sbi;
 	}
 
@@ -427,8 +480,8 @@
 		 * line. We always keep them in device-table order.
 		 */
 		if (fscb_od && osduld_device_same(fscb_od, &odi)) {
-			sbi->s_ods[i] = fscb_od;
-			++sbi->s_numdevs;
+			sbi->layout.s_ods[i] = fscb_od;
+			++sbi->layout.s_numdevs;
 			fscb_od = NULL;
 			continue;
 		}
@@ -441,8 +494,8 @@
 			goto out;
 		}
 
-		sbi->s_ods[i] = od;
-		++sbi->s_numdevs;
+		sbi->layout.s_ods[i] = od;
+		++sbi->layout.s_numdevs;
 
 		/* Read the fscb of the other devices to make sure the FS
 		 * partition is there.
@@ -499,9 +552,15 @@
 		goto free_sbi;
 	}
 
-	sbi->s_ods[0] = od;
-	sbi->s_numdevs = 1;
-	sbi->s_pid = opts->pid;
+	/* Default layout in case we do not have a device-table */
+	sbi->layout.stripe_unit = PAGE_SIZE;
+	sbi->layout.mirrors_p1 = 1;
+	sbi->layout.group_width = 1;
+	sbi->layout.group_depth = -1;
+	sbi->layout.group_count = 1;
+	sbi->layout.s_ods[0] = od;
+	sbi->layout.s_numdevs = 1;
+	sbi->layout.s_pid = opts->pid;
 	sbi->s_timeout = opts->timeout;
 
 	/* fill in some other data by hand */
@@ -514,7 +573,7 @@
 	sb->s_bdev = NULL;
 	sb->s_dev = 0;
 
-	obj.partition = sbi->s_pid;
+	obj.partition = sbi->layout.s_pid;
 	obj.id = EXOFS_SUPER_ID;
 	exofs_make_credential(sbi->s_cred, &obj);
 
@@ -578,13 +637,13 @@
 		goto free_sbi;
 	}
 
-	_exofs_print_device("Mounting", opts->dev_name, sbi->s_ods[0],
-			    sbi->s_pid);
+	_exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0],
+			    sbi->layout.s_pid);
 	return 0;
 
 free_sbi:
 	EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n",
-		  opts->dev_name, sbi->s_pid, ret);
+		  opts->dev_name, sbi->layout.s_pid, ret);
 	exofs_free_sbi(sbi);
 	return ret;
 }
@@ -627,7 +686,7 @@
 	uint8_t cred_a[OSD_CAP_LEN];
 	int ret;
 
-	ret = exofs_get_io_state(sbi, &ios);
+	ret = exofs_get_io_state(&sbi->layout, &ios);
 	if (ret) {
 		EXOFS_DBGMSG("exofs_get_io_state failed.\n");
 		return ret;
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 7f8d2e5..1d081f0 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -570,7 +570,7 @@
 error_return:
 	brelse(bitmap_bh);
 	release_blocks(sb, freed);
-	vfs_dq_free_block(inode, freed);
+	dquot_free_block(inode, freed);
 }
 
 /**
@@ -1236,6 +1236,7 @@
 	unsigned short windowsz = 0;
 	unsigned long ngroups;
 	unsigned long num = *count;
+	int ret;
 
 	*errp = -ENOSPC;
 	sb = inode->i_sb;
@@ -1247,8 +1248,9 @@
 	/*
 	 * Check quota for allocation of this block.
 	 */
-	if (vfs_dq_alloc_block(inode, num)) {
-		*errp = -EDQUOT;
+	ret = dquot_alloc_block(inode, num);
+	if (ret) {
+		*errp = ret;
 		return 0;
 	}
 
@@ -1409,7 +1411,7 @@
 
 	*errp = 0;
 	brelse(bitmap_bh);
-	vfs_dq_free_block(inode, *count-num);
+	dquot_free_block(inode, *count-num);
 	*count = num;
 	return ret_block;
 
@@ -1420,7 +1422,7 @@
 	 * Undo the block allocation
 	 */
 	if (!performed_allocation)
-		vfs_dq_free_block(inode, *count);
+		dquot_free_block(inode, *count);
 	brelse(bitmap_bh);
 	return 0;
 }
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 061914a..0b038e4 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -118,7 +118,7 @@
 
 /* inode.c */
 extern struct inode *ext2_iget (struct super_block *, unsigned long);
-extern int ext2_write_inode (struct inode *, int);
+extern int ext2_write_inode (struct inode *, struct writeback_control *);
 extern void ext2_delete_inode (struct inode *);
 extern int ext2_sync_inode (struct inode *);
 extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int);
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 586e358..5d198d0 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -20,6 +20,7 @@
 
 #include <linux/time.h>
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
 #include "ext2.h"
 #include "xattr.h"
 #include "acl.h"
@@ -70,7 +71,7 @@
 	.compat_ioctl	= ext2_compat_ioctl,
 #endif
 	.mmap		= generic_file_mmap,
-	.open		= generic_file_open,
+	.open		= dquot_file_open,
 	.release	= ext2_release_file,
 	.fsync		= ext2_fsync,
 	.splice_read	= generic_file_splice_read,
@@ -87,7 +88,7 @@
 	.compat_ioctl	= ext2_compat_ioctl,
 #endif
 	.mmap		= xip_file_mmap,
-	.open		= generic_file_open,
+	.open		= dquot_file_open,
 	.release	= ext2_release_file,
 	.fsync		= ext2_fsync,
 };
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 15387c9..ad7d572 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -121,8 +121,8 @@
 	if (!is_bad_inode(inode)) {
 		/* Quota is already initialized in iput() */
 		ext2_xattr_delete_inode(inode);
-		vfs_dq_free_inode(inode);
-		vfs_dq_drop(inode);
+		dquot_free_inode(inode);
+		dquot_drop(inode);
 	}
 
 	es = EXT2_SB(sb)->s_es;
@@ -586,10 +586,10 @@
 		goto fail_drop;
 	}
 
-	if (vfs_dq_alloc_inode(inode)) {
-		err = -EDQUOT;
+	dquot_initialize(inode);
+	err = dquot_alloc_inode(inode);
+	if (err)
 		goto fail_drop;
-	}
 
 	err = ext2_init_acl(inode, dir);
 	if (err)
@@ -605,10 +605,10 @@
 	return inode;
 
 fail_free_drop:
-	vfs_dq_free_inode(inode);
+	dquot_free_inode(inode);
 
 fail_drop:
-	vfs_dq_drop(inode);
+	dquot_drop(inode);
 	inode->i_flags |= S_NOQUOTA;
 	inode->i_nlink = 0;
 	unlock_new_inode(inode);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 71b032c..fc13cc1 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -41,6 +41,8 @@
 MODULE_DESCRIPTION("Second Extended Filesystem");
 MODULE_LICENSE("GPL");
 
+static int __ext2_write_inode(struct inode *inode, int do_sync);
+
 /*
  * Test whether an inode is a fast symlink.
  */
@@ -58,13 +60,15 @@
  */
 void ext2_delete_inode (struct inode * inode)
 {
+	if (!is_bad_inode(inode))
+		dquot_initialize(inode);
 	truncate_inode_pages(&inode->i_data, 0);
 
 	if (is_bad_inode(inode))
 		goto no_delete;
 	EXT2_I(inode)->i_dtime	= get_seconds();
 	mark_inode_dirty(inode);
-	ext2_write_inode(inode, inode_needs_sync(inode));
+	__ext2_write_inode(inode, inode_needs_sync(inode));
 
 	inode->i_size = 0;
 	if (inode->i_blocks)
@@ -1335,7 +1339,7 @@
 	return ERR_PTR(ret);
 }
 
-int ext2_write_inode(struct inode *inode, int do_sync)
+static int __ext2_write_inode(struct inode *inode, int do_sync)
 {
 	struct ext2_inode_info *ei = EXT2_I(inode);
 	struct super_block *sb = inode->i_sb;
@@ -1440,6 +1444,11 @@
 	return err;
 }
 
+int ext2_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+	return __ext2_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+}
+
 int ext2_sync_inode(struct inode *inode)
 {
 	struct writeback_control wbc = {
@@ -1457,9 +1466,12 @@
 	error = inode_change_ok(inode, iattr);
 	if (error)
 		return error;
+
+	if (iattr->ia_valid & ATTR_SIZE)
+		dquot_initialize(inode);
 	if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
 	    (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) {
-		error = vfs_dq_transfer(inode, iattr) ? -EDQUOT : 0;
+		error = dquot_transfer(inode, iattr);
 		if (error)
 			return error;
 	}
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index dd7175c..71efb0e 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -31,6 +31,7 @@
  */
 
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
 #include "ext2.h"
 #include "xattr.h"
 #include "acl.h"
@@ -99,24 +100,27 @@
  */
 static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd)
 {
-	struct inode * inode = ext2_new_inode (dir, mode);
-	int err = PTR_ERR(inode);
-	if (!IS_ERR(inode)) {
-		inode->i_op = &ext2_file_inode_operations;
-		if (ext2_use_xip(inode->i_sb)) {
-			inode->i_mapping->a_ops = &ext2_aops_xip;
-			inode->i_fop = &ext2_xip_file_operations;
-		} else if (test_opt(inode->i_sb, NOBH)) {
-			inode->i_mapping->a_ops = &ext2_nobh_aops;
-			inode->i_fop = &ext2_file_operations;
-		} else {
-			inode->i_mapping->a_ops = &ext2_aops;
-			inode->i_fop = &ext2_file_operations;
-		}
-		mark_inode_dirty(inode);
-		err = ext2_add_nondir(dentry, inode);
+	struct inode *inode;
+
+	dquot_initialize(dir);
+
+	inode = ext2_new_inode(dir, mode);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	inode->i_op = &ext2_file_inode_operations;
+	if (ext2_use_xip(inode->i_sb)) {
+		inode->i_mapping->a_ops = &ext2_aops_xip;
+		inode->i_fop = &ext2_xip_file_operations;
+	} else if (test_opt(inode->i_sb, NOBH)) {
+		inode->i_mapping->a_ops = &ext2_nobh_aops;
+		inode->i_fop = &ext2_file_operations;
+	} else {
+		inode->i_mapping->a_ops = &ext2_aops;
+		inode->i_fop = &ext2_file_operations;
 	}
-	return err;
+	mark_inode_dirty(inode);
+	return ext2_add_nondir(dentry, inode);
 }
 
 static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev)
@@ -127,6 +131,8 @@
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
 
+	dquot_initialize(dir);
+
 	inode = ext2_new_inode (dir, mode);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
@@ -151,6 +157,8 @@
 	if (l > sb->s_blocksize)
 		goto out;
 
+	dquot_initialize(dir);
+
 	inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
@@ -194,6 +202,8 @@
 	if (inode->i_nlink >= EXT2_LINK_MAX)
 		return -EMLINK;
 
+	dquot_initialize(dir);
+
 	inode->i_ctime = CURRENT_TIME_SEC;
 	inode_inc_link_count(inode);
 	atomic_inc(&inode->i_count);
@@ -216,6 +226,8 @@
 	if (dir->i_nlink >= EXT2_LINK_MAX)
 		goto out;
 
+	dquot_initialize(dir);
+
 	inode_inc_link_count(dir);
 
 	inode = ext2_new_inode (dir, S_IFDIR | mode);
@@ -262,6 +274,8 @@
 	struct page * page;
 	int err = -ENOENT;
 
+	dquot_initialize(dir);
+
 	de = ext2_find_entry (dir, &dentry->d_name, &page);
 	if (!de)
 		goto out;
@@ -304,6 +318,9 @@
 	struct ext2_dir_entry_2 * old_de;
 	int err = -ENOENT;
 
+	dquot_initialize(old_dir);
+	dquot_initialize(new_dir);
+
 	old_de = ext2_find_entry (old_dir, &old_dentry->d_name, &old_page);
 	if (!old_de)
 		goto out;
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index f9cb54a..42e4a30 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -194,6 +194,8 @@
 static void ext2_clear_inode(struct inode *inode)
 {
 	struct ext2_block_alloc_info *rsv = EXT2_I(inode)->i_block_alloc_info;
+
+	dquot_drop(inode);
 	ext2_discard_reservation(inode);
 	EXT2_I(inode)->i_block_alloc_info = NULL;
 	if (unlikely(rsv))
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 904f006..e44dc92 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -644,8 +644,8 @@
 				   the inode.  */
 				ea_bdebug(new_bh, "reusing block");
 
-				error = -EDQUOT;
-				if (vfs_dq_alloc_block(inode, 1)) {
+				error = dquot_alloc_block(inode, 1);
+				if (error) {
 					unlock_buffer(new_bh);
 					goto cleanup;
 				}
@@ -702,7 +702,7 @@
 		 * as if nothing happened and cleanup the unused block */
 		if (error && error != -ENOSPC) {
 			if (new_bh && new_bh != old_bh)
-				vfs_dq_free_block(inode, 1);
+				dquot_free_block(inode, 1);
 			goto cleanup;
 		}
 	} else
@@ -734,7 +734,7 @@
 			le32_add_cpu(&HDR(old_bh)->h_refcount, -1);
 			if (ce)
 				mb_cache_entry_release(ce);
-			vfs_dq_free_block(inode, 1);
+			dquot_free_block(inode, 1);
 			mark_buffer_dirty(old_bh);
 			ea_bdebug(old_bh, "refcount now=%d",
 				le32_to_cpu(HDR(old_bh)->h_refcount));
@@ -797,7 +797,7 @@
 		mark_buffer_dirty(bh);
 		if (IS_SYNC(inode))
 			sync_dirty_buffer(bh);
-		vfs_dq_free_block(inode, 1);
+		dquot_free_block(inode, 1);
 	}
 	EXT2_I(inode)->i_file_acl = 0;
 
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 27967f9..161da2d 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -676,7 +676,7 @@
 	}
 	ext3_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
 	if (dquot_freed_blocks)
-		vfs_dq_free_block(inode, dquot_freed_blocks);
+		dquot_free_block(inode, dquot_freed_blocks);
 	return;
 }
 
@@ -1502,8 +1502,9 @@
 	/*
 	 * Check quota for allocation of this block.
 	 */
-	if (vfs_dq_alloc_block(inode, num)) {
-		*errp = -EDQUOT;
+	err = dquot_alloc_block(inode, num);
+	if (err) {
+		*errp = err;
 		return 0;
 	}
 
@@ -1713,7 +1714,7 @@
 
 	*errp = 0;
 	brelse(bitmap_bh);
-	vfs_dq_free_block(inode, *count-num);
+	dquot_free_block(inode, *count-num);
 	*count = num;
 	return ret_block;
 
@@ -1728,7 +1729,7 @@
 	 * Undo the block allocation
 	 */
 	if (!performed_allocation)
-		vfs_dq_free_block(inode, *count);
+		dquot_free_block(inode, *count);
 	brelse(bitmap_bh);
 	return 0;
 }
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 388bbdf..f55df0e 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -21,6 +21,7 @@
 #include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd.h>
+#include <linux/quotaops.h>
 #include <linux/ext3_fs.h>
 #include <linux/ext3_jbd.h>
 #include "xattr.h"
@@ -33,9 +34,9 @@
  */
 static int ext3_release_file (struct inode * inode, struct file * filp)
 {
-	if (EXT3_I(inode)->i_state & EXT3_STATE_FLUSH_ON_CLOSE) {
+	if (ext3_test_inode_state(inode, EXT3_STATE_FLUSH_ON_CLOSE)) {
 		filemap_flush(inode->i_mapping);
-		EXT3_I(inode)->i_state &= ~EXT3_STATE_FLUSH_ON_CLOSE;
+		ext3_clear_inode_state(inode, EXT3_STATE_FLUSH_ON_CLOSE);
 	}
 	/* if we are the last writer on the inode, drop the block reservation */
 	if ((filp->f_mode & FMODE_WRITE) &&
@@ -62,7 +63,7 @@
 	.compat_ioctl	= ext3_compat_ioctl,
 #endif
 	.mmap		= generic_file_mmap,
-	.open		= generic_file_open,
+	.open		= dquot_file_open,
 	.release	= ext3_release_file,
 	.fsync		= ext3_sync_file,
 	.splice_read	= generic_file_splice_read,
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index b399912..ef9008b 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -123,10 +123,10 @@
 	 * Note: we must free any quota before locking the superblock,
 	 * as writing the quota to disk may need the lock as well.
 	 */
-	vfs_dq_init(inode);
+	dquot_initialize(inode);
 	ext3_xattr_delete_inode(handle, inode);
-	vfs_dq_free_inode(inode);
-	vfs_dq_drop(inode);
+	dquot_free_inode(inode);
+	dquot_drop(inode);
 
 	is_directory = S_ISDIR(inode->i_mode);
 
@@ -588,10 +588,10 @@
 		sizeof(struct ext3_inode) - EXT3_GOOD_OLD_INODE_SIZE : 0;
 
 	ret = inode;
-	if (vfs_dq_alloc_inode(inode)) {
-		err = -EDQUOT;
+	dquot_initialize(inode);
+	err = dquot_alloc_inode(inode);
+	if (err)
 		goto fail_drop;
-	}
 
 	err = ext3_init_acl(handle, inode, dir);
 	if (err)
@@ -619,10 +619,10 @@
 	return ret;
 
 fail_free_drop:
-	vfs_dq_free_inode(inode);
+	dquot_free_inode(inode);
 
 fail_drop:
-	vfs_dq_drop(inode);
+	dquot_drop(inode);
 	inode->i_flags |= S_NOQUOTA;
 	inode->i_nlink = 0;
 	unlock_new_inode(inode);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 455e6e6..7f920b7 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -196,6 +196,9 @@
 {
 	handle_t *handle;
 
+	if (!is_bad_inode(inode))
+		dquot_initialize(inode);
+
 	truncate_inode_pages(&inode->i_data, 0);
 
 	if (is_bad_inode(inode))
@@ -1378,7 +1381,7 @@
 	 */
 	if (pos + len > inode->i_size && ext3_can_truncate(inode))
 		ext3_orphan_add(handle, inode);
-	EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
+	ext3_set_inode_state(inode, EXT3_STATE_JDATA);
 	if (inode->i_size > EXT3_I(inode)->i_disksize) {
 		EXT3_I(inode)->i_disksize = inode->i_size;
 		ret2 = ext3_mark_inode_dirty(handle, inode);
@@ -1417,7 +1420,7 @@
 	journal_t *journal;
 	int err;
 
-	if (EXT3_I(inode)->i_state & EXT3_STATE_JDATA) {
+	if (ext3_test_inode_state(inode, EXT3_STATE_JDATA)) {
 		/*
 		 * This is a REALLY heavyweight approach, but the use of
 		 * bmap on dirty files is expected to be extremely rare:
@@ -1436,7 +1439,7 @@
 		 * everything they get.
 		 */
 
-		EXT3_I(inode)->i_state &= ~EXT3_STATE_JDATA;
+		ext3_clear_inode_state(inode, EXT3_STATE_JDATA);
 		journal = EXT3_JOURNAL(inode);
 		journal_lock_updates(journal);
 		err = journal_flush(journal);
@@ -1528,6 +1531,7 @@
 	int err;
 
 	J_ASSERT(PageLocked(page));
+	WARN_ON_ONCE(IS_RDONLY(inode));
 
 	/*
 	 * We give up here if we're reentered, because it might be for a
@@ -1600,6 +1604,9 @@
 	int ret = 0;
 	int err;
 
+	J_ASSERT(PageLocked(page));
+	WARN_ON_ONCE(IS_RDONLY(inode));
+
 	if (ext3_journal_current_handle())
 		goto out_fail;
 
@@ -1642,6 +1649,9 @@
 	int ret = 0;
 	int err;
 
+	J_ASSERT(PageLocked(page));
+	WARN_ON_ONCE(IS_RDONLY(inode));
+
 	if (ext3_journal_current_handle())
 		goto no_write;
 
@@ -1670,7 +1680,7 @@
 				PAGE_CACHE_SIZE, NULL, write_end_fn);
 		if (ret == 0)
 			ret = err;
-		EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
+		ext3_set_inode_state(inode, EXT3_STATE_JDATA);
 		unlock_page(page);
 	} else {
 		/*
@@ -1785,8 +1795,9 @@
 		handle = ext3_journal_start(inode, 2);
 		if (IS_ERR(handle)) {
 			/* This is really bad luck. We've written the data
-			 * but cannot extend i_size. Bail out and pretend
-			 * the write failed... */
+			 * but cannot extend i_size. Truncate allocated blocks
+			 * and pretend the write failed... */
+			ext3_truncate(inode);
 			ret = PTR_ERR(handle);
 			goto out;
 		}
@@ -2402,7 +2413,7 @@
 		goto out_notrans;
 
 	if (inode->i_size == 0 && ext3_should_writeback_data(inode))
-		ei->i_state |= EXT3_STATE_FLUSH_ON_CLOSE;
+		ext3_set_inode_state(inode, EXT3_STATE_FLUSH_ON_CLOSE);
 
 	/*
 	 * We have to lock the EOF page here, because lock_page() nests
@@ -2721,7 +2732,7 @@
 {
 	/* We have all inode data except xattrs in memory here. */
 	return __ext3_get_inode_loc(inode, iloc,
-		!(EXT3_I(inode)->i_state & EXT3_STATE_XATTR));
+		!ext3_test_inode_state(inode, EXT3_STATE_XATTR));
 }
 
 void ext3_set_inode_flags(struct inode *inode)
@@ -2893,7 +2904,7 @@
 					EXT3_GOOD_OLD_INODE_SIZE +
 					ei->i_extra_isize;
 			if (*magic == cpu_to_le32(EXT3_XATTR_MAGIC))
-				 ei->i_state |= EXT3_STATE_XATTR;
+				 ext3_set_inode_state(inode, EXT3_STATE_XATTR);
 		}
 	} else
 		ei->i_extra_isize = 0;
@@ -2955,7 +2966,7 @@
 
 	/* For fields not not tracking in the in-memory inode,
 	 * initialise them to zero for new inodes. */
-	if (ei->i_state & EXT3_STATE_NEW)
+	if (ext3_test_inode_state(inode, EXT3_STATE_NEW))
 		memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size);
 
 	ext3_get_inode_flags(ei);
@@ -3052,7 +3063,7 @@
 	rc = ext3_journal_dirty_metadata(handle, bh);
 	if (!err)
 		err = rc;
-	ei->i_state &= ~EXT3_STATE_NEW;
+	ext3_clear_inode_state(inode, EXT3_STATE_NEW);
 
 	atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid);
 out_brelse:
@@ -3096,7 +3107,7 @@
  * `stuff()' is running, and the new i_size will be lost.  Plus the inode
  * will no longer be on the superblock's dirty inode list.
  */
-int ext3_write_inode(struct inode *inode, int wait)
+int ext3_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	if (current->flags & PF_MEMALLOC)
 		return 0;
@@ -3107,7 +3118,7 @@
 		return -EIO;
 	}
 
-	if (!wait)
+	if (wbc->sync_mode != WB_SYNC_ALL)
 		return 0;
 
 	return ext3_force_commit(inode->i_sb);
@@ -3140,6 +3151,8 @@
 	if (error)
 		return error;
 
+	if (ia_valid & ATTR_SIZE)
+		dquot_initialize(inode);
 	if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
 		(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
 		handle_t *handle;
@@ -3152,7 +3165,7 @@
 			error = PTR_ERR(handle);
 			goto err_out;
 		}
-		error = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0;
+		error = dquot_transfer(inode, attr);
 		if (error) {
 			ext3_journal_stop(handle);
 			return error;
@@ -3237,7 +3250,7 @@
 		ret = 2 * (bpp + indirects) + 2;
 
 #ifdef CONFIG_QUOTA
-	/* We know that structure was already allocated during vfs_dq_init so
+	/* We know that structure was already allocated during dquot_initialize so
 	 * we will be updating only the data blocks + inodes */
 	ret += EXT3_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb);
 #endif
@@ -3328,7 +3341,7 @@
  * i_size has been changed by generic_commit_write() and we thus need
  * to include the updated inode in the current transaction.
  *
- * Also, vfs_dq_alloc_space() will always dirty the inode when blocks
+ * Also, dquot_alloc_space() will always dirty the inode when blocks
  * are allocated to the file.
  *
  * If the inode is marked synchronous, we don't honour that here - doing
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 7b0e44f7..ee18408 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1696,6 +1696,8 @@
 	struct inode * inode;
 	int err, retries = 0;
 
+	dquot_initialize(dir);
+
 retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
@@ -1730,6 +1732,8 @@
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
 
+	dquot_initialize(dir);
+
 retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
@@ -1766,6 +1770,8 @@
 	if (dir->i_nlink >= EXT3_LINK_MAX)
 		return -EMLINK;
 
+	dquot_initialize(dir);
+
 retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
@@ -2060,7 +2066,9 @@
 
 	/* Initialize quotas before so that eventual writes go in
 	 * separate transaction */
-	vfs_dq_init(dentry->d_inode);
+	dquot_initialize(dir);
+	dquot_initialize(dentry->d_inode);
+
 	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
@@ -2119,7 +2127,9 @@
 
 	/* Initialize quotas before so that eventual writes go
 	 * in separate transaction */
-	vfs_dq_init(dentry->d_inode);
+	dquot_initialize(dir);
+	dquot_initialize(dentry->d_inode);
+
 	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
@@ -2174,6 +2184,8 @@
 	if (l > dir->i_sb->s_blocksize)
 		return -ENAMETOOLONG;
 
+	dquot_initialize(dir);
+
 retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
@@ -2228,6 +2240,9 @@
 
 	if (inode->i_nlink >= EXT3_LINK_MAX)
 		return -EMLINK;
+
+	dquot_initialize(dir);
+
 	/*
 	 * Return -ENOENT if we've raced with unlink and i_nlink is 0.  Doing
 	 * otherwise has the potential to corrupt the orphan inode list.
@@ -2278,12 +2293,15 @@
 	struct ext3_dir_entry_2 * old_de, * new_de;
 	int retval, flush_file = 0;
 
+	dquot_initialize(old_dir);
+	dquot_initialize(new_dir);
+
 	old_bh = new_bh = dir_bh = NULL;
 
 	/* Initialize quotas before so that eventual writes go
 	 * in separate transaction */
 	if (new_dentry->d_inode)
-		vfs_dq_init(new_dentry->d_inode);
+		dquot_initialize(new_dentry->d_inode);
 	handle = ext3_journal_start(old_dir, 2 *
 					EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index afa2b56..1bee604 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -164,7 +164,7 @@
  * write out the superblock safely.
  *
  * We'll just use the journal_abort() error code to record an error in
- * the journal instead.  On recovery, the journal will compain about
+ * the journal instead.  On recovery, the journal will complain about
  * that error until we've noted it down and cleared it.
  */
 
@@ -181,7 +181,7 @@
 	if (!test_opt (sb, ERRORS_CONT)) {
 		journal_t *journal = EXT3_SB(sb)->s_journal;
 
-		EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
+		set_opt(EXT3_SB(sb)->s_mount_opt, ABORT);
 		if (journal)
 			journal_abort(journal, -EIO);
 	}
@@ -296,7 +296,7 @@
 		"error: remounting filesystem read-only");
 	EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
 	sb->s_flags |= MS_RDONLY;
-	EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
+	set_opt(EXT3_SB(sb)->s_mount_opt, ABORT);
 	if (EXT3_SB(sb)->s_journal)
 		journal_abort(EXT3_SB(sb)->s_journal, -EIO);
 }
@@ -528,6 +528,8 @@
 static void ext3_clear_inode(struct inode *inode)
 {
 	struct ext3_block_alloc_info *rsv = EXT3_I(inode)->i_block_alloc_info;
+
+	dquot_drop(inode);
 	ext3_discard_reservation(inode);
 	EXT3_I(inode)->i_block_alloc_info = NULL;
 	if (unlikely(rsv))
@@ -562,10 +564,10 @@
 	if (sbi->s_qf_names[GRPQUOTA])
 		seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
 
-	if (sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA)
+	if (test_opt(sb, USRQUOTA))
 		seq_puts(seq, ",usrquota");
 
-	if (sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)
+	if (test_opt(sb, GRPQUOTA))
 		seq_puts(seq, ",grpquota");
 #endif
 }
@@ -656,8 +658,7 @@
 	if (test_opt(sb, NOBH))
 		seq_puts(seq, ",nobh");
 
-	seq_printf(seq, ",data=%s", data_mode_string(sbi->s_mount_opt &
-						     EXT3_MOUNT_DATA_FLAGS));
+	seq_printf(seq, ",data=%s", data_mode_string(test_opt(sb, DATA_FLAGS)));
 	if (test_opt(sb, DATA_ERR_ABORT))
 		seq_puts(seq, ",data_err=abort");
 
@@ -751,13 +752,6 @@
 				const char *data, size_t len, loff_t off);
 
 static const struct dquot_operations ext3_quota_operations = {
-	.initialize	= dquot_initialize,
-	.drop		= dquot_drop,
-	.alloc_space	= dquot_alloc_space,
-	.alloc_inode	= dquot_alloc_inode,
-	.free_space	= dquot_free_space,
-	.free_inode	= dquot_free_inode,
-	.transfer	= dquot_transfer,
 	.write_dquot	= ext3_write_dquot,
 	.acquire_dquot	= ext3_acquire_dquot,
 	.release_dquot	= ext3_release_dquot,
@@ -896,6 +890,63 @@
 	return sb_block;
 }
 
+#ifdef CONFIG_QUOTA
+static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
+{
+	struct ext3_sb_info *sbi = EXT3_SB(sb);
+	char *qname;
+
+	if (sb_any_quota_loaded(sb) &&
+		!sbi->s_qf_names[qtype]) {
+		ext3_msg(sb, KERN_ERR,
+			"Cannot change journaled "
+			"quota options when quota turned on");
+		return 0;
+	}
+	qname = match_strdup(args);
+	if (!qname) {
+		ext3_msg(sb, KERN_ERR,
+			"Not enough memory for storing quotafile name");
+		return 0;
+	}
+	if (sbi->s_qf_names[qtype] &&
+		strcmp(sbi->s_qf_names[qtype], qname)) {
+		ext3_msg(sb, KERN_ERR,
+			"%s quota file already specified", QTYPE2NAME(qtype));
+		kfree(qname);
+		return 0;
+	}
+	sbi->s_qf_names[qtype] = qname;
+	if (strchr(sbi->s_qf_names[qtype], '/')) {
+		ext3_msg(sb, KERN_ERR,
+			"quotafile must be on filesystem root");
+		kfree(sbi->s_qf_names[qtype]);
+		sbi->s_qf_names[qtype] = NULL;
+		return 0;
+	}
+	set_opt(sbi->s_mount_opt, QUOTA);
+	return 1;
+}
+
+static int clear_qf_name(struct super_block *sb, int qtype) {
+
+	struct ext3_sb_info *sbi = EXT3_SB(sb);
+
+	if (sb_any_quota_loaded(sb) &&
+		sbi->s_qf_names[qtype]) {
+		ext3_msg(sb, KERN_ERR, "Cannot change journaled quota options"
+			" when quota turned on");
+		return 0;
+	}
+	/*
+	 * The space will be released later when all options are confirmed
+	 * to be correct
+	 */
+	sbi->s_qf_names[qtype] = NULL;
+	return 1;
+}
+#endif
+
 static int parse_options (char *options, struct super_block *sb,
 			  unsigned int *inum, unsigned long *journal_devnum,
 			  ext3_fsblk_t *n_blocks_count, int is_remount)
@@ -906,8 +957,7 @@
 	int data_opt = 0;
 	int option;
 #ifdef CONFIG_QUOTA
-	int qtype, qfmt;
-	char *qname;
+	int qfmt;
 #endif
 
 	if (!options)
@@ -1065,20 +1115,19 @@
 			data_opt = EXT3_MOUNT_WRITEBACK_DATA;
 		datacheck:
 			if (is_remount) {
-				if ((sbi->s_mount_opt & EXT3_MOUNT_DATA_FLAGS)
-						== data_opt)
+				if (test_opt(sb, DATA_FLAGS) == data_opt)
 					break;
 				ext3_msg(sb, KERN_ERR,
 					"error: cannot change "
 					"data mode on remount. The filesystem "
 					"is mounted in data=%s mode and you "
 					"try to remount it in data=%s mode.",
-					data_mode_string(sbi->s_mount_opt &
-							EXT3_MOUNT_DATA_FLAGS),
+					data_mode_string(test_opt(sb,
+							DATA_FLAGS)),
 					data_mode_string(data_opt));
 				return 0;
 			} else {
-				sbi->s_mount_opt &= ~EXT3_MOUNT_DATA_FLAGS;
+				clear_opt(sbi->s_mount_opt, DATA_FLAGS);
 				sbi->s_mount_opt |= data_opt;
 			}
 			break;
@@ -1090,62 +1139,20 @@
 			break;
 #ifdef CONFIG_QUOTA
 		case Opt_usrjquota:
-			qtype = USRQUOTA;
-			goto set_qf_name;
+			if (!set_qf_name(sb, USRQUOTA, &args[0]))
+				return 0;
+			break;
 		case Opt_grpjquota:
-			qtype = GRPQUOTA;
-set_qf_name:
-			if (sb_any_quota_loaded(sb) &&
-			    !sbi->s_qf_names[qtype]) {
-				ext3_msg(sb, KERN_ERR,
-					"error: cannot change journaled "
-					"quota options when quota turned on.");
+			if (!set_qf_name(sb, GRPQUOTA, &args[0]))
 				return 0;
-			}
-			qname = match_strdup(&args[0]);
-			if (!qname) {
-				ext3_msg(sb, KERN_ERR,
-					"error: not enough memory for "
-					"storing quotafile name.");
-				return 0;
-			}
-			if (sbi->s_qf_names[qtype] &&
-			    strcmp(sbi->s_qf_names[qtype], qname)) {
-				ext3_msg(sb, KERN_ERR,
-					"error: %s quota file already "
-					"specified.", QTYPE2NAME(qtype));
-				kfree(qname);
-				return 0;
-			}
-			sbi->s_qf_names[qtype] = qname;
-			if (strchr(sbi->s_qf_names[qtype], '/')) {
-				ext3_msg(sb, KERN_ERR,
-					"error: quotafile must be on "
-					"filesystem root.");
-				kfree(sbi->s_qf_names[qtype]);
-				sbi->s_qf_names[qtype] = NULL;
-				return 0;
-			}
-			set_opt(sbi->s_mount_opt, QUOTA);
 			break;
 		case Opt_offusrjquota:
-			qtype = USRQUOTA;
-			goto clear_qf_name;
-		case Opt_offgrpjquota:
-			qtype = GRPQUOTA;
-clear_qf_name:
-			if (sb_any_quota_loaded(sb) &&
-			    sbi->s_qf_names[qtype]) {
-				ext3_msg(sb, KERN_ERR, "error: cannot change "
-					"journaled quota options when "
-					"quota turned on.");
+			if (!clear_qf_name(sb, USRQUOTA))
 				return 0;
-			}
-			/*
-			 * The space will be released later when all options
-			 * are confirmed to be correct
-			 */
-			sbi->s_qf_names[qtype] = NULL;
+			break;
+		case Opt_offgrpjquota:
+			if (!clear_qf_name(sb, GRPQUOTA))
+				return 0;
 			break;
 		case Opt_jqfmt_vfsold:
 			qfmt = QFMT_VFS_OLD;
@@ -1244,18 +1251,12 @@
 	}
 #ifdef CONFIG_QUOTA
 	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
-		if ((sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA) &&
-		     sbi->s_qf_names[USRQUOTA])
+		if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA])
 			clear_opt(sbi->s_mount_opt, USRQUOTA);
-
-		if ((sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA) &&
-		     sbi->s_qf_names[GRPQUOTA])
+		if (test_opt(sb, GRPQUOTA) && sbi->s_qf_names[GRPQUOTA])
 			clear_opt(sbi->s_mount_opt, GRPQUOTA);
 
-		if ((sbi->s_qf_names[USRQUOTA] &&
-				(sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)) ||
-		    (sbi->s_qf_names[GRPQUOTA] &&
-				(sbi->s_mount_opt & EXT3_MOUNT_USRQUOTA))) {
+		if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) {
 			ext3_msg(sb, KERN_ERR, "error: old and new quota "
 					"format mixing.");
 			return 0;
@@ -1478,7 +1479,7 @@
 		}
 
 		list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
-		vfs_dq_init(inode);
+		dquot_initialize(inode);
 		if (inode->i_nlink) {
 			printk(KERN_DEBUG
 				"%s: truncating inode %lu to %Ld bytes\n",
@@ -1671,11 +1672,11 @@
 		set_opt(sbi->s_mount_opt, POSIX_ACL);
 #endif
 	if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_DATA)
-		sbi->s_mount_opt |= EXT3_MOUNT_JOURNAL_DATA;
+		set_opt(sbi->s_mount_opt, JOURNAL_DATA);
 	else if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_ORDERED)
-		sbi->s_mount_opt |= EXT3_MOUNT_ORDERED_DATA;
+		set_opt(sbi->s_mount_opt, ORDERED_DATA);
 	else if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_WBACK)
-		sbi->s_mount_opt |= EXT3_MOUNT_WRITEBACK_DATA;
+		set_opt(sbi->s_mount_opt, WRITEBACK_DATA);
 
 	if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_PANIC)
 		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
@@ -1694,7 +1695,7 @@
 		goto failed_mount;
 
 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
-		((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);
 
 	if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV &&
 	    (EXT3_HAS_COMPAT_FEATURE(sb, ~0U) ||
@@ -2561,11 +2562,11 @@
 		goto restore_opts;
 	}
 
-	if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
+	if (test_opt(sb, ABORT))
 		ext3_abort(sb, __func__, "Abort forced by user");
 
 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
-		((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);
 
 	es = sbi->s_es;
 
@@ -2573,7 +2574,7 @@
 
 	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
 		n_blocks_count > le32_to_cpu(es->s_blocks_count)) {
-		if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) {
+		if (test_opt(sb, ABORT)) {
 			err = -EROFS;
 			goto restore_opts;
 		}
@@ -2734,7 +2735,7 @@
  * Process 1                         Process 2
  * ext3_create()                     quota_sync()
  *   journal_start()                   write_dquot()
- *   vfs_dq_init()                       down(dqio_mutex)
+ *   dquot_initialize()                       down(dqio_mutex)
  *     down(dqio_mutex)                    journal_start()
  *
  */
@@ -2942,9 +2943,7 @@
 	sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);
 	int err = 0;
 	int offset = off & (sb->s_blocksize - 1);
-	int tocopy;
 	int journal_quota = EXT3_SB(sb)->s_qf_names[type] != NULL;
-	size_t towrite = len;
 	struct buffer_head *bh;
 	handle_t *handle = journal_current_handle();
 
@@ -2955,53 +2954,54 @@
 			(unsigned long long)off, (unsigned long long)len);
 		return -EIO;
 	}
-	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
-	while (towrite > 0) {
-		tocopy = sb->s_blocksize - offset < towrite ?
-				sb->s_blocksize - offset : towrite;
-		bh = ext3_bread(handle, inode, blk, 1, &err);
-		if (!bh)
-			goto out;
-		if (journal_quota) {
-			err = ext3_journal_get_write_access(handle, bh);
-			if (err) {
-				brelse(bh);
-				goto out;
-			}
-		}
-		lock_buffer(bh);
-		memcpy(bh->b_data+offset, data, tocopy);
-		flush_dcache_page(bh->b_page);
-		unlock_buffer(bh);
-		if (journal_quota)
-			err = ext3_journal_dirty_metadata(handle, bh);
-		else {
-			/* Always do at least ordered writes for quotas */
-			err = ext3_journal_dirty_data(handle, bh);
-			mark_buffer_dirty(bh);
-		}
-		brelse(bh);
-		if (err)
-			goto out;
-		offset = 0;
-		towrite -= tocopy;
-		data += tocopy;
-		blk++;
+
+	/*
+	 * Since we account only one data block in transaction credits,
+	 * then it is impossible to cross a block boundary.
+	 */
+	if (sb->s_blocksize - offset < len) {
+		ext3_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)"
+			" cancelled because not block aligned",
+			(unsigned long long)off, (unsigned long long)len);
+		return -EIO;
 	}
+	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
+	bh = ext3_bread(handle, inode, blk, 1, &err);
+	if (!bh)
+		goto out;
+	if (journal_quota) {
+		err = ext3_journal_get_write_access(handle, bh);
+		if (err) {
+			brelse(bh);
+			goto out;
+		}
+	}
+	lock_buffer(bh);
+	memcpy(bh->b_data+offset, data, len);
+	flush_dcache_page(bh->b_page);
+	unlock_buffer(bh);
+	if (journal_quota)
+		err = ext3_journal_dirty_metadata(handle, bh);
+	else {
+		/* Always do at least ordered writes for quotas */
+		err = ext3_journal_dirty_data(handle, bh);
+		mark_buffer_dirty(bh);
+	}
+	brelse(bh);
 out:
-	if (len == towrite) {
+	if (err) {
 		mutex_unlock(&inode->i_mutex);
 		return err;
 	}
-	if (inode->i_size < off+len-towrite) {
-		i_size_write(inode, off+len-towrite);
+	if (inode->i_size < off + len) {
+		i_size_write(inode, off + len);
 		EXT3_I(inode)->i_disksize = inode->i_size;
 	}
 	inode->i_version++;
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	ext3_mark_inode_dirty(handle, inode);
 	mutex_unlock(&inode->i_mutex);
-	return len - towrite;
+	return len;
 }
 
 #endif
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 66895cc..534a94c 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -274,7 +274,7 @@
 	void *end;
 	int error;
 
-	if (!(EXT3_I(inode)->i_state & EXT3_STATE_XATTR))
+	if (!ext3_test_inode_state(inode, EXT3_STATE_XATTR))
 		return -ENODATA;
 	error = ext3_get_inode_loc(inode, &iloc);
 	if (error)
@@ -403,7 +403,7 @@
 	void *end;
 	int error;
 
-	if (!(EXT3_I(inode)->i_state & EXT3_STATE_XATTR))
+	if (!ext3_test_inode_state(inode, EXT3_STATE_XATTR))
 		return 0;
 	error = ext3_get_inode_loc(inode, &iloc);
 	if (error)
@@ -500,7 +500,7 @@
 		error = ext3_journal_dirty_metadata(handle, bh);
 		if (IS_SYNC(inode))
 			handle->h_sync = 1;
-		vfs_dq_free_block(inode, 1);
+		dquot_free_block(inode, 1);
 		ea_bdebug(bh, "refcount now=%d; releasing",
 			  le32_to_cpu(BHDR(bh)->h_refcount));
 		if (ce)
@@ -775,8 +775,8 @@
 			else {
 				/* The old block is released after updating
 				   the inode. */
-				error = -EDQUOT;
-				if (vfs_dq_alloc_block(inode, 1))
+				error = dquot_alloc_block(inode, 1);
+				if (error)
 					goto cleanup;
 				error = ext3_journal_get_write_access(handle,
 								      new_bh);
@@ -850,7 +850,7 @@
 	return error;
 
 cleanup_dquot:
-	vfs_dq_free_block(inode, 1);
+	dquot_free_block(inode, 1);
 	goto cleanup;
 
 bad_block:
@@ -882,7 +882,7 @@
 	is->s.base = is->s.first = IFIRST(header);
 	is->s.here = is->s.first;
 	is->s.end = (void *)raw_inode + EXT3_SB(inode->i_sb)->s_inode_size;
-	if (EXT3_I(inode)->i_state & EXT3_STATE_XATTR) {
+	if (ext3_test_inode_state(inode, EXT3_STATE_XATTR)) {
 		error = ext3_xattr_check_names(IFIRST(header), is->s.end);
 		if (error)
 			return error;
@@ -914,10 +914,10 @@
 	header = IHDR(inode, ext3_raw_inode(&is->iloc));
 	if (!IS_LAST_ENTRY(s->first)) {
 		header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
-		EXT3_I(inode)->i_state |= EXT3_STATE_XATTR;
+		ext3_set_inode_state(inode, EXT3_STATE_XATTR);
 	} else {
 		header->h_magic = cpu_to_le32(0);
-		EXT3_I(inode)->i_state &= ~EXT3_STATE_XATTR;
+		ext3_clear_inode_state(inode, EXT3_STATE_XATTR);
 	}
 	return 0;
 }
@@ -967,10 +967,10 @@
 	if (error)
 		goto cleanup;
 
-	if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) {
+	if (ext3_test_inode_state(inode, EXT3_STATE_NEW)) {
 		struct ext3_inode *raw_inode = ext3_raw_inode(&is.iloc);
 		memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size);
-		EXT3_I(inode)->i_state &= ~EXT3_STATE_NEW;
+		ext3_clear_inode_state(inode, EXT3_STATE_NEW);
 	}
 
 	error = ext3_xattr_ibody_find(inode, &i, &is);
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 22bc743..d2f37a5 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -97,8 +97,8 @@
 		/* If checksum is bad mark all blocks used to prevent allocation
 		 * essentially implementing a per-group read-only flag. */
 		if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
-			ext4_error(sb, __func__,
-				  "Checksum bad for group %u", block_group);
+			ext4_error(sb, "Checksum bad for group %u",
+					block_group);
 			ext4_free_blks_set(sb, gdp, 0);
 			ext4_free_inodes_set(sb, gdp, 0);
 			ext4_itable_unused_set(sb, gdp, 0);
@@ -130,8 +130,7 @@
 		 * to make sure we calculate the right free blocks
 		 */
 		group_blocks = ext4_blocks_count(sbi->s_es) -
-			le32_to_cpu(sbi->s_es->s_first_data_block) -
-			(EXT4_BLOCKS_PER_GROUP(sb) * (ngroups - 1));
+			ext4_group_first_block_no(sb, ngroups - 1);
 	} else {
 		group_blocks = EXT4_BLOCKS_PER_GROUP(sb);
 	}
@@ -189,9 +188,6 @@
  * when a file system is mounted (see ext4_fill_super).
  */
 
-
-#define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
-
 /**
  * ext4_get_group_desc() -- load group descriptor from disk
  * @sb:			super block
@@ -210,10 +206,8 @@
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 
 	if (block_group >= ngroups) {
-		ext4_error(sb, "ext4_get_group_desc",
-			   "block_group >= groups_count - "
-			   "block_group = %u, groups_count = %u",
-			   block_group, ngroups);
+		ext4_error(sb, "block_group >= groups_count - block_group = %u,"
+			   " groups_count = %u", block_group, ngroups);
 
 		return NULL;
 	}
@@ -221,8 +215,7 @@
 	group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
 	offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
 	if (!sbi->s_group_desc[group_desc]) {
-		ext4_error(sb, "ext4_get_group_desc",
-			   "Group descriptor not loaded - "
+		ext4_error(sb, "Group descriptor not loaded - "
 			   "block_group = %u, group_desc = %u, desc = %u",
 			   block_group, group_desc, offset);
 		return NULL;
@@ -282,9 +275,7 @@
 		return 1;
 
 err_out:
-	ext4_error(sb, __func__,
-			"Invalid block bitmap - "
-			"block_group = %d, block = %llu",
+	ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu",
 			block_group, bitmap_blk);
 	return 0;
 }
@@ -311,8 +302,7 @@
 	bitmap_blk = ext4_block_bitmap(sb, desc);
 	bh = sb_getblk(sb, bitmap_blk);
 	if (unlikely(!bh)) {
-		ext4_error(sb, __func__,
-			    "Cannot read block bitmap - "
+		ext4_error(sb, "Cannot read block bitmap - "
 			    "block_group = %u, block_bitmap = %llu",
 			    block_group, bitmap_blk);
 		return NULL;
@@ -354,8 +344,7 @@
 	set_bitmap_uptodate(bh);
 	if (bh_submit_read(bh) < 0) {
 		put_bh(bh);
-		ext4_error(sb, __func__,
-			    "Cannot read block bitmap - "
+		ext4_error(sb, "Cannot read block bitmap - "
 			    "block_group = %u, block_bitmap = %llu",
 			    block_group, bitmap_blk);
 		return NULL;
@@ -419,8 +408,7 @@
 	    in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) ||
 	    in_range(block + count - 1, ext4_inode_table(sb, desc),
 		     sbi->s_itb_per_group)) {
-		ext4_error(sb, __func__,
-			   "Adding blocks in system zones - "
+		ext4_error(sb, "Adding blocks in system zones - "
 			   "Block = %llu, count = %lu",
 			   block, count);
 		goto error_return;
@@ -453,8 +441,7 @@
 		BUFFER_TRACE(bitmap_bh, "clear bit");
 		if (!ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group),
 						bit + i, bitmap_bh->b_data)) {
-			ext4_error(sb, __func__,
-				   "bit already cleared for block %llu",
+			ext4_error(sb, "bit already cleared for block %llu",
 				   (ext4_fsblk_t)(block + i));
 			BUFFER_TRACE(bitmap_bh, "bit already cleared");
 		} else {
diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
index a60ab9a..983f0e1 100644
--- a/fs/ext4/block_validity.c
+++ b/fs/ext4/block_validity.c
@@ -205,14 +205,14 @@
 		entry = rb_entry(n, struct ext4_system_zone, node);
 		kmem_cache_free(ext4_system_zone_cachep, entry);
 		if (!parent)
-			EXT4_SB(sb)->system_blks.rb_node = NULL;
+			EXT4_SB(sb)->system_blks = RB_ROOT;
 		else if (parent->rb_left == n)
 			parent->rb_left = NULL;
 		else if (parent->rb_right == n)
 			parent->rb_right = NULL;
 		n = parent;
 	}
-	EXT4_SB(sb)->system_blks.rb_node = NULL;
+	EXT4_SB(sb)->system_blks = RB_ROOT;
 }
 
 /*
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 9dc93168..86cb6d8 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -83,10 +83,12 @@
 		error_msg = "inode out of bounds";
 
 	if (error_msg != NULL)
-		ext4_error(dir->i_sb, function,
-			"bad entry in directory #%lu: %s - "
-			"offset=%u, inode=%u, rec_len=%d, name_len=%d",
-			dir->i_ino, error_msg, offset,
+		__ext4_error(dir->i_sb, function,
+			"bad entry in directory #%lu: %s - block=%llu"
+			"offset=%u(%u), inode=%u, rec_len=%d, name_len=%d",
+			dir->i_ino, error_msg, 
+			(unsigned long long) bh->b_blocknr,     
+			(unsigned) (offset%bh->b_size), offset,
 			le32_to_cpu(de->inode),
 			rlen, de->name_len);
 	return error_msg == NULL ? 1 : 0;
@@ -150,7 +152,7 @@
 		 */
 		if (!bh) {
 			if (!dir_has_error) {
-				ext4_error(sb, __func__, "directory #%lu "
+				ext4_error(sb, "directory #%lu "
 					   "contains a hole at offset %Lu",
 					   inode->i_ino,
 					   (unsigned long long) filp->f_pos);
@@ -303,7 +305,7 @@
 			kfree(old);
 		}
 		if (!parent)
-			root->rb_node = NULL;
+			*root = RB_ROOT;
 		else if (parent->rb_left == n)
 			parent->rb_left = NULL;
 		else if (parent->rb_right == n)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 874d169..bf938cf 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -53,6 +53,12 @@
 #define ext4_debug(f, a...)	do {} while (0)
 #endif
 
+#define EXT4_ERROR_INODE(inode, fmt, a...) \
+	ext4_error_inode(__func__, (inode), (fmt), ## a);
+
+#define EXT4_ERROR_FILE(file, fmt, a...)	\
+	ext4_error_file(__func__, (file), (fmt), ## a);
+
 /* data type for block offset of block group */
 typedef int ext4_grpblk_t;
 
@@ -133,14 +139,14 @@
 	int pages_written;
 	int retval;
 };
-#define	DIO_AIO_UNWRITTEN	0x1
+#define	EXT4_IO_UNWRITTEN	0x1
 typedef struct ext4_io_end {
 	struct list_head	list;		/* per-file finished AIO list */
 	struct inode		*inode;		/* file being written to */
 	unsigned int		flag;		/* unwritten or not */
-	int			error;		/* I/O error code */
-	ext4_lblk_t		offset;		/* offset in the file */
-	size_t			size;		/* size of the extent */
+	struct page		*page;		/* page struct for buffer write */
+	loff_t			offset;		/* offset in the file */
+	ssize_t			size;		/* size of the extent */
 	struct work_struct	work;		/* data work queue */
 } ext4_io_end_t;
 
@@ -284,10 +290,12 @@
 #define EXT4_TOPDIR_FL			0x00020000 /* Top of directory hierarchies*/
 #define EXT4_HUGE_FILE_FL               0x00040000 /* Set to each huge file */
 #define EXT4_EXTENTS_FL			0x00080000 /* Inode uses extents */
+#define EXT4_EA_INODE_FL	        0x00200000 /* Inode used for large EA */
+#define EXT4_EOFBLOCKS_FL		0x00400000 /* Blocks allocated beyond EOF */
 #define EXT4_RESERVED_FL		0x80000000 /* reserved for ext4 lib */
 
-#define EXT4_FL_USER_VISIBLE		0x000BDFFF /* User visible flags */
-#define EXT4_FL_USER_MODIFIABLE		0x000B80FF /* User modifiable flags */
+#define EXT4_FL_USER_VISIBLE		0x004BDFFF /* User visible flags */
+#define EXT4_FL_USER_MODIFIABLE		0x004B80FF /* User modifiable flags */
 
 /* Flags that should be inherited by new inodes from their parent. */
 #define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
@@ -313,17 +321,6 @@
 		return flags & EXT4_OTHER_FLMASK;
 }
 
-/*
- * Inode dynamic state flags
- */
-#define EXT4_STATE_JDATA		0x00000001 /* journaled data exists */
-#define EXT4_STATE_NEW			0x00000002 /* inode is newly created */
-#define EXT4_STATE_XATTR		0x00000004 /* has in-inode xattrs */
-#define EXT4_STATE_NO_EXPAND		0x00000008 /* No space for expansion */
-#define EXT4_STATE_DA_ALLOC_CLOSE	0x00000010 /* Alloc DA blks on close */
-#define EXT4_STATE_EXT_MIGRATE		0x00000020 /* Inode is migrating */
-#define EXT4_STATE_DIO_UNWRITTEN	0x00000040 /* need convert on dio done*/
-
 /* Used to pass group descriptor data when online resize is done */
 struct ext4_new_group_input {
 	__u32 group;		/* Group number for this data */
@@ -364,19 +361,20 @@
 	/* caller is from the direct IO path, request to creation of an
 	unitialized extents if not allocated, split the uninitialized
 	extent if blocks has been preallocated already*/
-#define EXT4_GET_BLOCKS_DIO			0x0008
+#define EXT4_GET_BLOCKS_PRE_IO			0x0008
 #define EXT4_GET_BLOCKS_CONVERT			0x0010
-#define EXT4_GET_BLOCKS_DIO_CREATE_EXT		(EXT4_GET_BLOCKS_DIO|\
+#define EXT4_GET_BLOCKS_IO_CREATE_EXT		(EXT4_GET_BLOCKS_PRE_IO|\
 					 EXT4_GET_BLOCKS_CREATE_UNINIT_EXT)
-	/* Convert extent to initialized after direct IO complete */
-#define EXT4_GET_BLOCKS_DIO_CONVERT_EXT		(EXT4_GET_BLOCKS_CONVERT|\
-					 EXT4_GET_BLOCKS_DIO_CREATE_EXT)
+	/* Convert extent to initialized after IO complete */
+#define EXT4_GET_BLOCKS_IO_CONVERT_EXT		(EXT4_GET_BLOCKS_CONVERT|\
+					 EXT4_GET_BLOCKS_CREATE_UNINIT_EXT)
 
 /*
  * Flags used by ext4_free_blocks
  */
 #define EXT4_FREE_BLOCKS_METADATA	0x0001
 #define EXT4_FREE_BLOCKS_FORGET		0x0002
+#define EXT4_FREE_BLOCKS_VALIDATED	0x0004
 
 /*
  * ioctl commands
@@ -630,7 +628,7 @@
 	 * near to their parent directory's inode.
 	 */
 	ext4_group_t	i_block_group;
-	__u32	i_state;		/* Dynamic state flags for ext4 */
+	unsigned long	i_state_flags;		/* Dynamic state flags */
 
 	ext4_lblk_t		i_dir_start_lookup;
 #ifdef CONFIG_EXT4_FS_XATTR
@@ -708,8 +706,9 @@
 	qsize_t i_reserved_quota;
 #endif
 
-	/* completed async DIOs that might need unwritten extents handling */
-	struct list_head i_aio_dio_complete_list;
+	/* completed IOs that might need unwritten extents handling */
+	struct list_head i_completed_io_list;
+	spinlock_t i_completed_io_lock;
 	/* current io_end structure for async DIO write*/
 	ext4_io_end_t *cur_aio_dio;
 
@@ -760,6 +759,7 @@
 #define EXT4_MOUNT_QUOTA		0x80000 /* Some quota option set */
 #define EXT4_MOUNT_USRQUOTA		0x100000 /* "old" user quota */
 #define EXT4_MOUNT_GRPQUOTA		0x200000 /* "old" group quota */
+#define EXT4_MOUNT_DIOREAD_NOLOCK	0x400000 /* Enable support for dio read nolocking */
 #define EXT4_MOUNT_JOURNAL_CHECKSUM	0x800000 /* Journal checksums */
 #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT	0x1000000 /* Journal Async Commit */
 #define EXT4_MOUNT_I_VERSION            0x2000000 /* i_version support */
@@ -1014,7 +1014,7 @@
 	atomic_t s_lock_busy;
 
 	/* locality groups */
-	struct ext4_locality_group *s_locality_groups;
+	struct ext4_locality_group __percpu *s_locality_groups;
 
 	/* for write statistics */
 	unsigned long s_sectors_written_start;
@@ -1050,6 +1050,34 @@
 		(ino >= EXT4_FIRST_INO(sb) &&
 		 ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count));
 }
+
+/*
+ * Inode dynamic state flags
+ */
+enum {
+	EXT4_STATE_JDATA,		/* journaled data exists */
+	EXT4_STATE_NEW,			/* inode is newly created */
+	EXT4_STATE_XATTR,		/* has in-inode xattrs */
+	EXT4_STATE_NO_EXPAND,		/* No space for expansion */
+	EXT4_STATE_DA_ALLOC_CLOSE,	/* Alloc DA blks on close */
+	EXT4_STATE_EXT_MIGRATE,		/* Inode is migrating */
+	EXT4_STATE_DIO_UNWRITTEN,	/* need convert on dio done*/
+};
+
+static inline int ext4_test_inode_state(struct inode *inode, int bit)
+{
+	return test_bit(bit, &EXT4_I(inode)->i_state_flags);
+}
+
+static inline void ext4_set_inode_state(struct inode *inode, int bit)
+{
+	set_bit(bit, &EXT4_I(inode)->i_state_flags);
+}
+
+static inline void ext4_clear_inode_state(struct inode *inode, int bit)
+{
+	clear_bit(bit, &EXT4_I(inode)->i_state_flags);
+}
 #else
 /* Assume that user mode programs are passing in an ext4fs superblock, not
  * a kernel struct super_block.  This will allow us to call the feature-test
@@ -1126,6 +1154,8 @@
 #define EXT4_FEATURE_INCOMPAT_64BIT		0x0080
 #define EXT4_FEATURE_INCOMPAT_MMP               0x0100
 #define EXT4_FEATURE_INCOMPAT_FLEX_BG		0x0200
+#define EXT4_FEATURE_INCOMPAT_EA_INODE		0x0400 /* EA in inode */
+#define EXT4_FEATURE_INCOMPAT_DIRDATA		0x1000 /* data in dirent */
 
 #define EXT4_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR
 #define EXT4_FEATURE_INCOMPAT_SUPP	(EXT4_FEATURE_INCOMPAT_FILETYPE| \
@@ -1416,7 +1446,7 @@
 				struct buffer_head *bh_result, int create);
 
 extern struct inode *ext4_iget(struct super_block *, unsigned long);
-extern int  ext4_write_inode(struct inode *, int);
+extern int  ext4_write_inode(struct inode *, struct writeback_control *);
 extern int  ext4_setattr(struct dentry *, struct iattr *);
 extern int  ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
 				struct kstat *stat);
@@ -1439,7 +1469,7 @@
 		struct address_space *mapping, loff_t from);
 extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
 extern qsize_t *ext4_get_reserved_space(struct inode *inode);
-extern int flush_aio_dio_completed_IO(struct inode *inode);
+extern int flush_completed_IO(struct inode *inode);
 extern void ext4_da_update_reserve_space(struct inode *inode,
 					int used, int quota_claim);
 /* ioctl.c */
@@ -1465,13 +1495,20 @@
 				ext4_fsblk_t n_blocks_count);
 
 /* super.c */
-extern void ext4_error(struct super_block *, const char *, const char *, ...)
+extern void __ext4_error(struct super_block *, const char *, const char *, ...)
+	__attribute__ ((format (printf, 3, 4)));
+#define ext4_error(sb, message...)	__ext4_error(sb, __func__, ## message)
+extern void ext4_error_inode(const char *, struct inode *, const char *, ...)
+	__attribute__ ((format (printf, 3, 4)));
+extern void ext4_error_file(const char *, struct file *, const char *, ...)
 	__attribute__ ((format (printf, 3, 4)));
 extern void __ext4_std_error(struct super_block *, const char *, int);
 extern void ext4_abort(struct super_block *, const char *, const char *, ...)
 	__attribute__ ((format (printf, 3, 4)));
-extern void ext4_warning(struct super_block *, const char *, const char *, ...)
+extern void __ext4_warning(struct super_block *, const char *,
+			  const char *, ...)
 	__attribute__ ((format (printf, 3, 4)));
+#define ext4_warning(sb, message...)	__ext4_warning(sb, __func__, ## message)
 extern void ext4_msg(struct super_block *, const char *, const char *, ...)
 	__attribute__ ((format (printf, 3, 4)));
 extern void ext4_grp_locked_error(struct super_block *, ext4_group_t,
@@ -1744,7 +1781,7 @@
 extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
 			  loff_t len);
 extern int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
-			  loff_t len);
+			  ssize_t len);
 extern int ext4_get_blocks(handle_t *handle, struct inode *inode,
 			   sector_t block, unsigned int max_blocks,
 			   struct buffer_head *bh, int flags);
@@ -1756,6 +1793,15 @@
 			     __u64 len, __u64 *moved_len);
 
 
+/* BH_Uninit flag: blocks are allocated but uninitialized on disk */
+enum ext4_state_bits {
+	BH_Uninit	/* blocks are allocated but uninitialized on disk */
+	  = BH_JBDPrivateStart,
+};
+
+BUFFER_FNS(Uninit, uninit)
+TAS_BUFFER_FNS(Uninit, uninit)
+
 /*
  * Add new method to test wether block and inode bitmaps are properly
  * initialized. With uninit_bg reading the block from disk is not enough
@@ -1773,6 +1819,8 @@
 	set_bit(BH_BITMAP_UPTODATE, &(bh)->b_state);
 }
 
+#define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
+
 #endif	/* __KERNEL__ */
 
 #endif	/* _EXT4_H */
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index b57e5c7..53d2764 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -125,14 +125,14 @@
 			ext4_journal_abort_handle(where, __func__, bh,
 						  handle, err);
 	} else {
-		if (inode && bh)
+		if (inode)
 			mark_buffer_dirty_inode(bh, inode);
 		else
 			mark_buffer_dirty(bh);
 		if (inode && inode_needs_sync(inode)) {
 			sync_dirty_buffer(bh);
 			if (buffer_req(bh) && !buffer_uptodate(bh)) {
-				ext4_error(inode->i_sb, __func__,
+				ext4_error(inode->i_sb,
 					   "IO error syncing inode, "
 					   "inode=%lu, block=%llu",
 					   inode->i_ino,
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 05eca81..b79ad51 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -304,4 +304,28 @@
 	return 0;
 }
 
+/*
+ * This function controls whether or not we should try to go down the
+ * dioread_nolock code paths, which makes it safe to avoid taking
+ * i_mutex for direct I/O reads.  This only works for extent-based
+ * files, and it doesn't work for nobh or if data journaling is
+ * enabled, since the dioread_nolock code uses b_private to pass
+ * information back to the I/O completion handler, and this conflicts
+ * with the jbd's use of b_private.
+ */
+static inline int ext4_should_dioread_nolock(struct inode *inode)
+{
+	if (!test_opt(inode->i_sb, DIOREAD_NOLOCK))
+		return 0;
+	if (test_opt(inode->i_sb, NOBH))
+		return 0;
+	if (!S_ISREG(inode->i_mode))
+		return 0;
+	if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
+		return 0;
+	if (ext4_should_journal_data(inode))
+		return 0;
+	return 1;
+}
+
 #endif	/* _EXT4_JBD2_H */
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 765a482..94c8ee8 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -195,8 +195,7 @@
 		if (S_ISREG(inode->i_mode))
 			block_group++;
 	}
-	bg_start = (block_group * EXT4_BLOCKS_PER_GROUP(inode->i_sb)) +
-		le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_first_data_block);
+	bg_start = ext4_group_first_block_no(inode->i_sb, block_group);
 	last_block = ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es) - 1;
 
 	/*
@@ -440,7 +439,7 @@
 	return 0;
 
 corrupted:
-	ext4_error(inode->i_sb, function,
+	__ext4_error(inode->i_sb, function,
 			"bad header/extent in inode #%lu: %s - magic %x, "
 			"entries %u, max %u(%u), depth %u(%u)",
 			inode->i_ino, error_msg, le16_to_cpu(eh->eh_magic),
@@ -703,7 +702,12 @@
 		}
 		eh = ext_block_hdr(bh);
 		ppos++;
-		BUG_ON(ppos > depth);
+		if (unlikely(ppos > depth)) {
+			put_bh(bh);
+			EXT4_ERROR_INODE(inode,
+					 "ppos %d > depth %d", ppos, depth);
+			goto err;
+		}
 		path[ppos].p_bh = bh;
 		path[ppos].p_hdr = eh;
 		i--;
@@ -749,7 +753,12 @@
 	if (err)
 		return err;
 
-	BUG_ON(logical == le32_to_cpu(curp->p_idx->ei_block));
+	if (unlikely(logical == le32_to_cpu(curp->p_idx->ei_block))) {
+		EXT4_ERROR_INODE(inode,
+				 "logical %d == ei_block %d!",
+				 logical, le32_to_cpu(curp->p_idx->ei_block));
+		return -EIO;
+	}
 	len = EXT_MAX_INDEX(curp->p_hdr) - curp->p_idx;
 	if (logical > le32_to_cpu(curp->p_idx->ei_block)) {
 		/* insert after */
@@ -779,9 +788,17 @@
 	ext4_idx_store_pblock(ix, ptr);
 	le16_add_cpu(&curp->p_hdr->eh_entries, 1);
 
-	BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries)
-			     > le16_to_cpu(curp->p_hdr->eh_max));
-	BUG_ON(ix > EXT_LAST_INDEX(curp->p_hdr));
+	if (unlikely(le16_to_cpu(curp->p_hdr->eh_entries)
+			     > le16_to_cpu(curp->p_hdr->eh_max))) {
+		EXT4_ERROR_INODE(inode,
+				 "logical %d == ei_block %d!",
+				 logical, le32_to_cpu(curp->p_idx->ei_block));
+		return -EIO;
+	}
+	if (unlikely(ix > EXT_LAST_INDEX(curp->p_hdr))) {
+		EXT4_ERROR_INODE(inode, "ix > EXT_LAST_INDEX!");
+		return -EIO;
+	}
 
 	err = ext4_ext_dirty(handle, inode, curp);
 	ext4_std_error(inode->i_sb, err);
@@ -819,7 +836,10 @@
 
 	/* if current leaf will be split, then we should use
 	 * border from split point */
-	BUG_ON(path[depth].p_ext > EXT_MAX_EXTENT(path[depth].p_hdr));
+	if (unlikely(path[depth].p_ext > EXT_MAX_EXTENT(path[depth].p_hdr))) {
+		EXT4_ERROR_INODE(inode, "p_ext > EXT_MAX_EXTENT!");
+		return -EIO;
+	}
 	if (path[depth].p_ext != EXT_MAX_EXTENT(path[depth].p_hdr)) {
 		border = path[depth].p_ext[1].ee_block;
 		ext_debug("leaf will be split."
@@ -860,7 +880,11 @@
 
 	/* initialize new leaf */
 	newblock = ablocks[--a];
-	BUG_ON(newblock == 0);
+	if (unlikely(newblock == 0)) {
+		EXT4_ERROR_INODE(inode, "newblock == 0!");
+		err = -EIO;
+		goto cleanup;
+	}
 	bh = sb_getblk(inode->i_sb, newblock);
 	if (!bh) {
 		err = -EIO;
@@ -880,7 +904,14 @@
 	ex = EXT_FIRST_EXTENT(neh);
 
 	/* move remainder of path[depth] to the new leaf */
-	BUG_ON(path[depth].p_hdr->eh_entries != path[depth].p_hdr->eh_max);
+	if (unlikely(path[depth].p_hdr->eh_entries !=
+		     path[depth].p_hdr->eh_max)) {
+		EXT4_ERROR_INODE(inode, "eh_entries %d != eh_max %d!",
+				 path[depth].p_hdr->eh_entries,
+				 path[depth].p_hdr->eh_max);
+		err = -EIO;
+		goto cleanup;
+	}
 	/* start copy from next extent */
 	/* TODO: we could do it by single memmove */
 	m = 0;
@@ -927,7 +958,11 @@
 
 	/* create intermediate indexes */
 	k = depth - at - 1;
-	BUG_ON(k < 0);
+	if (unlikely(k < 0)) {
+		EXT4_ERROR_INODE(inode, "k %d < 0!", k);
+		err = -EIO;
+		goto cleanup;
+	}
 	if (k)
 		ext_debug("create %d intermediate indices\n", k);
 	/* insert new index into current index block */
@@ -964,8 +999,14 @@
 
 		ext_debug("cur 0x%p, last 0x%p\n", path[i].p_idx,
 				EXT_MAX_INDEX(path[i].p_hdr));
-		BUG_ON(EXT_MAX_INDEX(path[i].p_hdr) !=
-				EXT_LAST_INDEX(path[i].p_hdr));
+		if (unlikely(EXT_MAX_INDEX(path[i].p_hdr) !=
+					EXT_LAST_INDEX(path[i].p_hdr))) {
+			EXT4_ERROR_INODE(inode,
+					 "EXT_MAX_INDEX != EXT_LAST_INDEX ee_block %d!",
+					 le32_to_cpu(path[i].p_ext->ee_block));
+			err = -EIO;
+			goto cleanup;
+		}
 		while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
 			ext_debug("%d: move %d:%llu in new index %llu\n", i,
 					le32_to_cpu(path[i].p_idx->ei_block),
@@ -1203,7 +1244,10 @@
 	struct ext4_extent *ex;
 	int depth, ee_len;
 
-	BUG_ON(path == NULL);
+	if (unlikely(path == NULL)) {
+		EXT4_ERROR_INODE(inode, "path == NULL *logical %d!", *logical);
+		return -EIO;
+	}
 	depth = path->p_depth;
 	*phys = 0;
 
@@ -1217,15 +1261,33 @@
 	ex = path[depth].p_ext;
 	ee_len = ext4_ext_get_actual_len(ex);
 	if (*logical < le32_to_cpu(ex->ee_block)) {
-		BUG_ON(EXT_FIRST_EXTENT(path[depth].p_hdr) != ex);
+		if (unlikely(EXT_FIRST_EXTENT(path[depth].p_hdr) != ex)) {
+			EXT4_ERROR_INODE(inode,
+					 "EXT_FIRST_EXTENT != ex *logical %d ee_block %d!",
+					 *logical, le32_to_cpu(ex->ee_block));
+			return -EIO;
+		}
 		while (--depth >= 0) {
 			ix = path[depth].p_idx;
-			BUG_ON(ix != EXT_FIRST_INDEX(path[depth].p_hdr));
+			if (unlikely(ix != EXT_FIRST_INDEX(path[depth].p_hdr))) {
+				EXT4_ERROR_INODE(inode,
+				  "ix (%d) != EXT_FIRST_INDEX (%d) (depth %d)!",
+				  ix != NULL ? ix->ei_block : 0,
+				  EXT_FIRST_INDEX(path[depth].p_hdr) != NULL ?
+				    EXT_FIRST_INDEX(path[depth].p_hdr)->ei_block : 0,
+				  depth);
+				return -EIO;
+			}
 		}
 		return 0;
 	}
 
-	BUG_ON(*logical < (le32_to_cpu(ex->ee_block) + ee_len));
+	if (unlikely(*logical < (le32_to_cpu(ex->ee_block) + ee_len))) {
+		EXT4_ERROR_INODE(inode,
+				 "logical %d < ee_block %d + ee_len %d!",
+				 *logical, le32_to_cpu(ex->ee_block), ee_len);
+		return -EIO;
+	}
 
 	*logical = le32_to_cpu(ex->ee_block) + ee_len - 1;
 	*phys = ext_pblock(ex) + ee_len - 1;
@@ -1251,7 +1313,10 @@
 	int depth;	/* Note, NOT eh_depth; depth from top of tree */
 	int ee_len;
 
-	BUG_ON(path == NULL);
+	if (unlikely(path == NULL)) {
+		EXT4_ERROR_INODE(inode, "path == NULL *logical %d!", *logical);
+		return -EIO;
+	}
 	depth = path->p_depth;
 	*phys = 0;
 
@@ -1265,17 +1330,32 @@
 	ex = path[depth].p_ext;
 	ee_len = ext4_ext_get_actual_len(ex);
 	if (*logical < le32_to_cpu(ex->ee_block)) {
-		BUG_ON(EXT_FIRST_EXTENT(path[depth].p_hdr) != ex);
+		if (unlikely(EXT_FIRST_EXTENT(path[depth].p_hdr) != ex)) {
+			EXT4_ERROR_INODE(inode,
+					 "first_extent(path[%d].p_hdr) != ex",
+					 depth);
+			return -EIO;
+		}
 		while (--depth >= 0) {
 			ix = path[depth].p_idx;
-			BUG_ON(ix != EXT_FIRST_INDEX(path[depth].p_hdr));
+			if (unlikely(ix != EXT_FIRST_INDEX(path[depth].p_hdr))) {
+				EXT4_ERROR_INODE(inode,
+						 "ix != EXT_FIRST_INDEX *logical %d!",
+						 *logical);
+				return -EIO;
+			}
 		}
 		*logical = le32_to_cpu(ex->ee_block);
 		*phys = ext_pblock(ex);
 		return 0;
 	}
 
-	BUG_ON(*logical < (le32_to_cpu(ex->ee_block) + ee_len));
+	if (unlikely(*logical < (le32_to_cpu(ex->ee_block) + ee_len))) {
+		EXT4_ERROR_INODE(inode,
+				 "logical %d < ee_block %d + ee_len %d!",
+				 *logical, le32_to_cpu(ex->ee_block), ee_len);
+		return -EIO;
+	}
 
 	if (ex != EXT_LAST_EXTENT(path[depth].p_hdr)) {
 		/* next allocated block in this leaf */
@@ -1414,8 +1494,12 @@
 
 	eh = path[depth].p_hdr;
 	ex = path[depth].p_ext;
-	BUG_ON(ex == NULL);
-	BUG_ON(eh == NULL);
+
+	if (unlikely(ex == NULL || eh == NULL)) {
+		EXT4_ERROR_INODE(inode,
+				 "ex %p == NULL or eh %p == NULL", ex, eh);
+		return -EIO;
+	}
 
 	if (depth == 0) {
 		/* there is no tree at all */
@@ -1538,8 +1622,9 @@
 		merge_done = 1;
 		WARN_ON(eh->eh_entries == 0);
 		if (!eh->eh_entries)
-			ext4_error(inode->i_sb, "ext4_ext_try_to_merge",
-			   "inode#%lu, eh->eh_entries = 0!", inode->i_ino);
+			ext4_error(inode->i_sb,
+				   "inode#%lu, eh->eh_entries = 0!",
+				   inode->i_ino);
 	}
 
 	return merge_done;
@@ -1612,13 +1697,19 @@
 	ext4_lblk_t next;
 	unsigned uninitialized = 0;
 
-	BUG_ON(ext4_ext_get_actual_len(newext) == 0);
+	if (unlikely(ext4_ext_get_actual_len(newext) == 0)) {
+		EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0");
+		return -EIO;
+	}
 	depth = ext_depth(inode);
 	ex = path[depth].p_ext;
-	BUG_ON(path[depth].p_hdr == NULL);
+	if (unlikely(path[depth].p_hdr == NULL)) {
+		EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
+		return -EIO;
+	}
 
 	/* try to insert block into found extent and return */
-	if (ex && (flag != EXT4_GET_BLOCKS_DIO_CREATE_EXT)
+	if (ex && !(flag & EXT4_GET_BLOCKS_PRE_IO)
 		&& ext4_can_extents_be_merged(inode, ex, newext)) {
 		ext_debug("append [%d]%d block to %d:[%d]%d (from %llu)\n",
 				ext4_ext_is_uninitialized(newext),
@@ -1739,7 +1830,7 @@
 
 merge:
 	/* try to merge extents to the right */
-	if (flag != EXT4_GET_BLOCKS_DIO_CREATE_EXT)
+	if (!(flag & EXT4_GET_BLOCKS_PRE_IO))
 		ext4_ext_try_to_merge(inode, path, nearex);
 
 	/* try to merge extents to the left */
@@ -1787,7 +1878,11 @@
 		}
 
 		depth = ext_depth(inode);
-		BUG_ON(path[depth].p_hdr == NULL);
+		if (unlikely(path[depth].p_hdr == NULL)) {
+			EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
+			err = -EIO;
+			break;
+		}
 		ex = path[depth].p_ext;
 		next = ext4_ext_next_allocated_block(path);
 
@@ -1838,7 +1933,11 @@
 			cbex.ec_type = EXT4_EXT_CACHE_EXTENT;
 		}
 
-		BUG_ON(cbex.ec_len == 0);
+		if (unlikely(cbex.ec_len == 0)) {
+			EXT4_ERROR_INODE(inode, "cbex.ec_len == 0");
+			err = -EIO;
+			break;
+		}
 		err = func(inode, path, &cbex, ex, cbdata);
 		ext4_ext_drop_refs(path);
 
@@ -1952,7 +2051,7 @@
 
 	BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP &&
 			cex->ec_type != EXT4_EXT_CACHE_EXTENT);
-	if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
+	if (in_range(block, cex->ec_block, cex->ec_len)) {
 		ex->ee_block = cpu_to_le32(cex->ec_block);
 		ext4_ext_store_pblock(ex, cex->ec_start);
 		ex->ee_len = cpu_to_le16(cex->ec_len);
@@ -1981,7 +2080,10 @@
 	/* free index block */
 	path--;
 	leaf = idx_pblock(path->p_idx);
-	BUG_ON(path->p_hdr->eh_entries == 0);
+	if (unlikely(path->p_hdr->eh_entries == 0)) {
+		EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0");
+		return -EIO;
+	}
 	err = ext4_ext_get_access(handle, inode, path);
 	if (err)
 		return err;
@@ -2119,8 +2221,10 @@
 	if (!path[depth].p_hdr)
 		path[depth].p_hdr = ext_block_hdr(path[depth].p_bh);
 	eh = path[depth].p_hdr;
-	BUG_ON(eh == NULL);
-
+	if (unlikely(path[depth].p_hdr == NULL)) {
+		EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
+		return -EIO;
+	}
 	/* find where to start removing */
 	ex = EXT_LAST_EXTENT(eh);
 
@@ -2983,7 +3087,7 @@
 	ext4_ext_dirty(handle, inode, path + depth);
 	return err;
 }
-static int ext4_convert_unwritten_extents_dio(handle_t *handle,
+static int ext4_convert_unwritten_extents_endio(handle_t *handle,
 					      struct inode *inode,
 					      struct ext4_ext_path *path)
 {
@@ -3063,8 +3167,8 @@
 		  flags, allocated);
 	ext4_ext_show_leaf(inode, path);
 
-	/* DIO get_block() before submit the IO, split the extent */
-	if (flags == EXT4_GET_BLOCKS_DIO_CREATE_EXT) {
+	/* get_block() before submit the IO, split the extent */
+	if ((flags & EXT4_GET_BLOCKS_PRE_IO)) {
 		ret = ext4_split_unwritten_extents(handle,
 						inode, path, iblock,
 						max_blocks, flags);
@@ -3074,14 +3178,16 @@
 		 * completed
 		 */
 		if (io)
-			io->flag = DIO_AIO_UNWRITTEN;
+			io->flag = EXT4_IO_UNWRITTEN;
 		else
-			EXT4_I(inode)->i_state |= EXT4_STATE_DIO_UNWRITTEN;
+			ext4_set_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
+		if (ext4_should_dioread_nolock(inode))
+			set_buffer_uninit(bh_result);
 		goto out;
 	}
-	/* async DIO end_io complete, convert the filled extent to written */
-	if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) {
-		ret = ext4_convert_unwritten_extents_dio(handle, inode,
+	/* IO end_io complete, convert the filled extent to written */
+	if ((flags & EXT4_GET_BLOCKS_CONVERT)) {
+		ret = ext4_convert_unwritten_extents_endio(handle, inode,
 							path);
 		if (ret >= 0)
 			ext4_update_inode_fsync_trans(handle, inode, 1);
@@ -3185,7 +3291,7 @@
 {
 	struct ext4_ext_path *path = NULL;
 	struct ext4_extent_header *eh;
-	struct ext4_extent newex, *ex;
+	struct ext4_extent newex, *ex, *last_ex;
 	ext4_fsblk_t newblock;
 	int err = 0, depth, ret, cache_type;
 	unsigned int allocated = 0;
@@ -3237,10 +3343,10 @@
 	 * this situation is possible, though, _during_ tree modification;
 	 * this is why assert can't be put in ext4_ext_find_extent()
 	 */
-	if (path[depth].p_ext == NULL && depth != 0) {
-		ext4_error(inode->i_sb, __func__, "bad extent address "
-			   "inode: %lu, iblock: %d, depth: %d",
-			   inode->i_ino, iblock, depth);
+	if (unlikely(path[depth].p_ext == NULL && depth != 0)) {
+		EXT4_ERROR_INODE(inode, "bad extent address "
+				 "iblock: %d, depth: %d pblock %lld",
+				 iblock, depth, path[depth].p_block);
 		err = -EIO;
 		goto out2;
 	}
@@ -3258,7 +3364,7 @@
 		 */
 		ee_len = ext4_ext_get_actual_len(ex);
 		/* if found extent covers block, simply return it */
-		if (iblock >= ee_block && iblock < ee_block + ee_len) {
+		if (in_range(iblock, ee_block, ee_len)) {
 			newblock = iblock - ee_block + ee_start;
 			/* number of remaining blocks in the extent */
 			allocated = ee_len - (iblock - ee_block);
@@ -3350,21 +3456,35 @@
 	if (flags & EXT4_GET_BLOCKS_UNINIT_EXT){
 		ext4_ext_mark_uninitialized(&newex);
 		/*
-		 * io_end structure was created for every async
-		 * direct IO write to the middle of the file.
-		 * To avoid unecessary convertion for every aio dio rewrite
-		 * to the mid of file, here we flag the IO that is really
-		 * need the convertion.
+		 * io_end structure was created for every IO write to an
+		 * uninitialized extent. To avoid unecessary conversion,
+		 * here we flag the IO that really needs the conversion.
 		 * For non asycn direct IO case, flag the inode state
 		 * that we need to perform convertion when IO is done.
 		 */
-		if (flags == EXT4_GET_BLOCKS_DIO_CREATE_EXT) {
+		if ((flags & EXT4_GET_BLOCKS_PRE_IO)) {
 			if (io)
-				io->flag = DIO_AIO_UNWRITTEN;
+				io->flag = EXT4_IO_UNWRITTEN;
 			else
-				EXT4_I(inode)->i_state |=
-					EXT4_STATE_DIO_UNWRITTEN;;
+				ext4_set_inode_state(inode,
+						     EXT4_STATE_DIO_UNWRITTEN);
 		}
+		if (ext4_should_dioread_nolock(inode))
+			set_buffer_uninit(bh_result);
+	}
+
+	if (unlikely(EXT4_I(inode)->i_flags & EXT4_EOFBLOCKS_FL)) {
+		if (unlikely(!eh->eh_entries)) {
+			EXT4_ERROR_INODE(inode,
+					 "eh->eh_entries == 0 ee_block %d",
+					 ex->ee_block);
+			err = -EIO;
+			goto out2;
+		}
+		last_ex = EXT_LAST_EXTENT(eh);
+		if (iblock + ar.len > le32_to_cpu(last_ex->ee_block)
+		    + ext4_ext_get_actual_len(last_ex))
+			EXT4_I(inode)->i_flags &= ~EXT4_EOFBLOCKS_FL;
 	}
 	err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
 	if (err) {
@@ -3499,6 +3619,13 @@
 			i_size_write(inode, new_size);
 		if (new_size > EXT4_I(inode)->i_disksize)
 			ext4_update_i_disksize(inode, new_size);
+	} else {
+		/*
+		 * Mark that we allocate beyond EOF so the subsequent truncate
+		 * can proceed even if the new size is the same as i_size.
+		 */
+		if (new_size > i_size_read(inode))
+			EXT4_I(inode)->i_flags |= EXT4_EOFBLOCKS_FL;
 	}
 
 }
@@ -3603,7 +3730,7 @@
  * Returns 0 on success.
  */
 int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
-				    loff_t len)
+				    ssize_t len)
 {
 	handle_t *handle;
 	ext4_lblk_t block;
@@ -3635,7 +3762,7 @@
 		map_bh.b_state = 0;
 		ret = ext4_get_blocks(handle, inode, block,
 				      max_blocks, &map_bh,
-				      EXT4_GET_BLOCKS_DIO_CONVERT_EXT);
+				      EXT4_GET_BLOCKS_IO_CONVERT_EXT);
 		if (ret <= 0) {
 			WARN_ON(ret <= 0);
 			printk(KERN_ERR "%s: ext4_ext_get_blocks "
@@ -3739,7 +3866,7 @@
 	int error = 0;
 
 	/* in-inode? */
-	if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) {
+	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
 		struct ext4_iloc iloc;
 		int offset;	/* offset of xattr in inode */
 
@@ -3767,7 +3894,6 @@
 		__u64 start, __u64 len)
 {
 	ext4_lblk_t start_blk;
-	ext4_lblk_t len_blks;
 	int error = 0;
 
 	/* fallback to generic here if not in extents fmt */
@@ -3781,8 +3907,14 @@
 	if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
 		error = ext4_xattr_fiemap(inode, fieinfo);
 	} else {
+		ext4_lblk_t len_blks;
+		__u64 last_blk;
+
 		start_blk = start >> inode->i_sb->s_blocksize_bits;
-		len_blks = len >> inode->i_sb->s_blocksize_bits;
+		last_blk = (start + len - 1) >> inode->i_sb->s_blocksize_bits;
+		if (last_blk >= EXT_MAX_BLOCK)
+			last_blk = EXT_MAX_BLOCK-1;
+		len_blks = ((ext4_lblk_t) last_blk) - start_blk + 1;
 
 		/*
 		 * Walk the extent tree gathering extent information.
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 9630583..d0776e4 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -23,6 +23,7 @@
 #include <linux/jbd2.h>
 #include <linux/mount.h>
 #include <linux/path.h>
+#include <linux/quotaops.h>
 #include "ext4.h"
 #include "ext4_jbd2.h"
 #include "xattr.h"
@@ -35,9 +36,9 @@
  */
 static int ext4_release_file(struct inode *inode, struct file *filp)
 {
-	if (EXT4_I(inode)->i_state & EXT4_STATE_DA_ALLOC_CLOSE) {
+	if (ext4_test_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE)) {
 		ext4_alloc_da_blocks(inode);
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_DA_ALLOC_CLOSE;
+		ext4_clear_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
 	}
 	/* if we are the last writer on the inode, drop the block reservation */
 	if ((filp->f_mode & FMODE_WRITE) &&
@@ -116,18 +117,16 @@
 		 * devices or filesystem images.
 		 */
 		memset(buf, 0, sizeof(buf));
-		path.mnt = mnt->mnt_parent;
-		path.dentry = mnt->mnt_mountpoint;
-		path_get(&path);
+		path.mnt = mnt;
+		path.dentry = mnt->mnt_root;
 		cp = d_path(&path, buf, sizeof(buf));
-		path_put(&path);
 		if (!IS_ERR(cp)) {
 			memcpy(sbi->s_es->s_last_mounted, cp,
 			       sizeof(sbi->s_es->s_last_mounted));
 			sb->s_dirt = 1;
 		}
 	}
-	return generic_file_open(inode, filp);
+	return dquot_file_open(inode, filp);
 }
 
 const struct file_operations ext4_file_operations = {
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
index 98bd140..0d0c323 100644
--- a/fs/ext4/fsync.c
+++ b/fs/ext4/fsync.c
@@ -63,7 +63,7 @@
 	if (inode->i_sb->s_flags & MS_RDONLY)
 		return 0;
 
-	ret = flush_aio_dio_completed_IO(inode);
+	ret = flush_completed_IO(inode);
 	if (ret < 0)
 		return ret;
 	
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index f3624ea..361c0b9 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -76,8 +76,7 @@
 	/* If checksum is bad mark all blocks and inodes use to prevent
 	 * allocation, essentially implementing a per-group read-only flag. */
 	if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
-		ext4_error(sb, __func__, "Checksum bad for group %u",
-			   block_group);
+		ext4_error(sb, "Checksum bad for group %u", block_group);
 		ext4_free_blks_set(sb, gdp, 0);
 		ext4_free_inodes_set(sb, gdp, 0);
 		ext4_itable_unused_set(sb, gdp, 0);
@@ -111,8 +110,7 @@
 	bitmap_blk = ext4_inode_bitmap(sb, desc);
 	bh = sb_getblk(sb, bitmap_blk);
 	if (unlikely(!bh)) {
-		ext4_error(sb, __func__,
-			    "Cannot read inode bitmap - "
+		ext4_error(sb, "Cannot read inode bitmap - "
 			    "block_group = %u, inode_bitmap = %llu",
 			    block_group, bitmap_blk);
 		return NULL;
@@ -153,8 +151,7 @@
 	set_bitmap_uptodate(bh);
 	if (bh_submit_read(bh) < 0) {
 		put_bh(bh);
-		ext4_error(sb, __func__,
-			    "Cannot read inode bitmap - "
+		ext4_error(sb, "Cannot read inode bitmap - "
 			    "block_group = %u, inode_bitmap = %llu",
 			    block_group, bitmap_blk);
 		return NULL;
@@ -217,10 +214,10 @@
 	 * Note: we must free any quota before locking the superblock,
 	 * as writing the quota to disk may need the lock as well.
 	 */
-	vfs_dq_init(inode);
+	dquot_initialize(inode);
 	ext4_xattr_delete_inode(handle, inode);
-	vfs_dq_free_inode(inode);
-	vfs_dq_drop(inode);
+	dquot_free_inode(inode);
+	dquot_drop(inode);
 
 	is_directory = S_ISDIR(inode->i_mode);
 
@@ -229,8 +226,7 @@
 
 	es = EXT4_SB(sb)->s_es;
 	if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
-		ext4_error(sb, "ext4_free_inode",
-			   "reserved or nonexistent inode %lu", ino);
+		ext4_error(sb, "reserved or nonexistent inode %lu", ino);
 		goto error_return;
 	}
 	block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
@@ -248,8 +244,7 @@
 	cleared = ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group),
 					bit, bitmap_bh->b_data);
 	if (!cleared)
-		ext4_error(sb, "ext4_free_inode",
-			   "bit already cleared for inode %lu", ino);
+		ext4_error(sb, "bit already cleared for inode %lu", ino);
 	else {
 		gdp = ext4_get_group_desc(sb, block_group, &bh2);
 
@@ -736,8 +731,7 @@
 	if ((group == 0 && ino < EXT4_FIRST_INO(sb)) ||
 			ino > EXT4_INODES_PER_GROUP(sb)) {
 		ext4_unlock_group(sb, group);
-		ext4_error(sb, __func__,
-			   "reserved inode or inode > inodes count - "
+		ext4_error(sb, "reserved inode or inode > inodes count - "
 			   "block_group = %u, inode=%lu", group,
 			   ino + group * EXT4_INODES_PER_GROUP(sb));
 		return 1;
@@ -904,7 +898,7 @@
 				BUFFER_TRACE(inode_bitmap_bh,
 					"call ext4_handle_dirty_metadata");
 				err = ext4_handle_dirty_metadata(handle,
-								 inode,
+								 NULL,
 							inode_bitmap_bh);
 				if (err)
 					goto fail;
@@ -1029,15 +1023,16 @@
 	inode->i_generation = sbi->s_next_generation++;
 	spin_unlock(&sbi->s_next_gen_lock);
 
-	ei->i_state = EXT4_STATE_NEW;
+	ei->i_state_flags = 0;
+	ext4_set_inode_state(inode, EXT4_STATE_NEW);
 
 	ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
 
 	ret = inode;
-	if (vfs_dq_alloc_inode(inode)) {
-		err = -EDQUOT;
+	dquot_initialize(inode);
+	err = dquot_alloc_inode(inode);
+	if (err)
 		goto fail_drop;
-	}
 
 	err = ext4_init_acl(handle, inode, dir);
 	if (err)
@@ -1074,10 +1069,10 @@
 	return ret;
 
 fail_free_drop:
-	vfs_dq_free_inode(inode);
+	dquot_free_inode(inode);
 
 fail_drop:
-	vfs_dq_drop(inode);
+	dquot_drop(inode);
 	inode->i_flags |= S_NOQUOTA;
 	inode->i_nlink = 0;
 	unlock_new_inode(inode);
@@ -1098,8 +1093,7 @@
 
 	/* Error cases - e2fsck has already cleaned up for us */
 	if (ino > max_ino) {
-		ext4_warning(sb, __func__,
-			     "bad orphan ino %lu!  e2fsck was run?", ino);
+		ext4_warning(sb, "bad orphan ino %lu!  e2fsck was run?", ino);
 		goto error;
 	}
 
@@ -1107,8 +1101,7 @@
 	bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
 	bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
 	if (!bitmap_bh) {
-		ext4_warning(sb, __func__,
-			     "inode bitmap error for orphan %lu", ino);
+		ext4_warning(sb, "inode bitmap error for orphan %lu", ino);
 		goto error;
 	}
 
@@ -1140,8 +1133,7 @@
 	err = PTR_ERR(inode);
 	inode = NULL;
 bad_orphan:
-	ext4_warning(sb, __func__,
-		     "bad orphan inode %lu!  e2fsck was run?", ino);
+	ext4_warning(sb, "bad orphan inode %lu!  e2fsck was run?", ino);
 	printk(KERN_NOTICE "ext4_test_bit(bit=%d, block=%llu) = %d\n",
 	       bit, (unsigned long long)bitmap_bh->b_blocknr,
 	       ext4_test_bit(bit, bitmap_bh->b_data));
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e119524..986120f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -38,6 +38,7 @@
 #include <linux/uio.h>
 #include <linux/bio.h>
 #include <linux/workqueue.h>
+#include <linux/kernel.h>
 
 #include "ext4_jbd2.h"
 #include "xattr.h"
@@ -170,6 +171,9 @@
 	handle_t *handle;
 	int err;
 
+	if (!is_bad_inode(inode))
+		dquot_initialize(inode);
+
 	if (ext4_should_order_data(inode))
 		ext4_begin_ordered_truncate(inode, 0);
 	truncate_inode_pages(&inode->i_data, 0);
@@ -194,7 +198,7 @@
 	inode->i_size = 0;
 	err = ext4_mark_inode_dirty(handle, inode);
 	if (err) {
-		ext4_warning(inode->i_sb, __func__,
+		ext4_warning(inode->i_sb,
 			     "couldn't mark inode dirty (err %d)", err);
 		goto stop_handle;
 	}
@@ -212,7 +216,7 @@
 		if (err > 0)
 			err = ext4_journal_restart(handle, 3);
 		if (err != 0) {
-			ext4_warning(inode->i_sb, __func__,
+			ext4_warning(inode->i_sb,
 				     "couldn't extend journal (err %d)", err);
 		stop_handle:
 			ext4_journal_stop(handle);
@@ -323,8 +327,7 @@
 		offsets[n++] = i_block & (ptrs - 1);
 		final = ptrs;
 	} else {
-		ext4_warning(inode->i_sb, "ext4_block_to_path",
-			     "block %lu > max in inode %lu",
+		ext4_warning(inode->i_sb, "block %lu > max in inode %lu",
 			     i_block + direct_blocks +
 			     indirect_blocks + double_blocks, inode->i_ino);
 	}
@@ -344,7 +347,7 @@
 		if (blk &&
 		    unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
 						    blk, 1))) {
-			ext4_error(inode->i_sb, function,
+			__ext4_error(inode->i_sb, function,
 				   "invalid block reference %u "
 				   "in inode #%lu", blk, inode->i_ino);
 			return -EIO;
@@ -607,7 +610,14 @@
 		if (*err)
 			goto failed_out;
 
-		BUG_ON(current_block + count > EXT4_MAX_BLOCK_FILE_PHYS);
+		if (unlikely(current_block + count > EXT4_MAX_BLOCK_FILE_PHYS)) {
+			EXT4_ERROR_INODE(inode,
+					 "current_block %llu + count %lu > %d!",
+					 current_block, count,
+					 EXT4_MAX_BLOCK_FILE_PHYS);
+			*err = -EIO;
+			goto failed_out;
+		}
 
 		target -= count;
 		/* allocate blocks for indirect blocks */
@@ -643,7 +653,14 @@
 		ar.flags = EXT4_MB_HINT_DATA;
 
 	current_block = ext4_mb_new_blocks(handle, &ar, err);
-	BUG_ON(current_block + ar.len > EXT4_MAX_BLOCK_FILE_PHYS);
+	if (unlikely(current_block + ar.len > EXT4_MAX_BLOCK_FILE_PHYS)) {
+		EXT4_ERROR_INODE(inode,
+				 "current_block %llu + ar.len %d > %d!",
+				 current_block, ar.len,
+				 EXT4_MAX_BLOCK_FILE_PHYS);
+		*err = -EIO;
+		goto failed_out;
+	}
 
 	if (*err && (target == blks)) {
 		/*
@@ -1061,6 +1078,7 @@
 	int mdb_free = 0, allocated_meta_blocks = 0;
 
 	spin_lock(&ei->i_block_reservation_lock);
+	trace_ext4_da_update_reserve_space(inode, used);
 	if (unlikely(used > ei->i_reserved_data_blocks)) {
 		ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, used %d "
 			 "with only %d reserved data blocks\n",
@@ -1093,9 +1111,9 @@
 
 	/* Update quota subsystem */
 	if (quota_claim) {
-		vfs_dq_claim_block(inode, used);
+		dquot_claim_block(inode, used);
 		if (mdb_free)
-			vfs_dq_release_reservation_block(inode, mdb_free);
+			dquot_release_reservation_block(inode, mdb_free);
 	} else {
 		/*
 		 * We did fallocate with an offset that is already delayed
@@ -1106,8 +1124,8 @@
 		 * that
 		 */
 		if (allocated_meta_blocks)
-			vfs_dq_claim_block(inode, allocated_meta_blocks);
-		vfs_dq_release_reservation_block(inode, mdb_free + used);
+			dquot_claim_block(inode, allocated_meta_blocks);
+		dquot_release_reservation_block(inode, mdb_free + used);
 	}
 
 	/*
@@ -1124,7 +1142,7 @@
 				sector_t logical, sector_t phys, int len)
 {
 	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), phys, len)) {
-		ext4_error(inode->i_sb, msg,
+		__ext4_error(inode->i_sb, msg,
 			   "inode #%lu logical block %llu mapped to %llu "
 			   "(size %d)", inode->i_ino,
 			   (unsigned long long) logical,
@@ -1306,7 +1324,7 @@
 			 * i_data's format changing.  Force the migrate
 			 * to fail by clearing migrate flags
 			 */
-			EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
+			ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
 		}
 
 		/*
@@ -1534,6 +1552,8 @@
 	ext4_truncate(inode);
 }
 
+static int ext4_get_block_write(struct inode *inode, sector_t iblock,
+		   struct buffer_head *bh_result, int create);
 static int ext4_write_begin(struct file *file, struct address_space *mapping,
 			    loff_t pos, unsigned len, unsigned flags,
 			    struct page **pagep, void **fsdata)
@@ -1575,8 +1595,12 @@
 	}
 	*pagep = page;
 
-	ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
-				ext4_get_block);
+	if (ext4_should_dioread_nolock(inode))
+		ret = block_write_begin(file, mapping, pos, len, flags, pagep,
+				fsdata, ext4_get_block_write);
+	else
+		ret = block_write_begin(file, mapping, pos, len, flags, pagep,
+				fsdata, ext4_get_block);
 
 	if (!ret && ext4_should_journal_data(inode)) {
 		ret = walk_page_buffers(handle, page_buffers(page),
@@ -1793,7 +1817,7 @@
 	new_i_size = pos + copied;
 	if (new_i_size > inode->i_size)
 		i_size_write(inode, pos+copied);
-	EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
+	ext4_set_inode_state(inode, EXT4_STATE_JDATA);
 	if (new_i_size > EXT4_I(inode)->i_disksize) {
 		ext4_update_i_disksize(inode, new_i_size);
 		ret2 = ext4_mark_inode_dirty(handle, inode);
@@ -1836,6 +1860,7 @@
 	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
 	struct ext4_inode_info *ei = EXT4_I(inode);
 	unsigned long md_needed, md_reserved;
+	int ret;
 
 	/*
 	 * recalculate the amount of metadata blocks to reserve
@@ -1846,6 +1871,7 @@
 	spin_lock(&ei->i_block_reservation_lock);
 	md_reserved = ei->i_reserved_meta_blocks;
 	md_needed = ext4_calc_metadata_amount(inode, lblock);
+	trace_ext4_da_reserve_space(inode, md_needed);
 	spin_unlock(&ei->i_block_reservation_lock);
 
 	/*
@@ -1853,11 +1879,12 @@
 	 * later. Real quota accounting is done at pages writeout
 	 * time.
 	 */
-	if (vfs_dq_reserve_block(inode, md_needed + 1))
-		return -EDQUOT;
+	ret = dquot_reserve_block(inode, md_needed + 1);
+	if (ret)
+		return ret;
 
 	if (ext4_claim_free_blocks(sbi, md_needed + 1)) {
-		vfs_dq_release_reservation_block(inode, md_needed + 1);
+		dquot_release_reservation_block(inode, md_needed + 1);
 		if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
 			yield();
 			goto repeat;
@@ -1914,7 +1941,7 @@
 
 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 
-	vfs_dq_release_reservation_block(inode, to_free);
+	dquot_release_reservation_block(inode, to_free);
 }
 
 static void ext4_da_page_release_reservation(struct page *page,
@@ -2091,6 +2118,8 @@
 				} else if (buffer_mapped(bh))
 					BUG_ON(bh->b_blocknr != pblock);
 
+				if (buffer_uninit(exbh))
+					set_buffer_uninit(bh);
 				cur_logical++;
 				pblock++;
 			} while ((bh = bh->b_this_page) != head);
@@ -2133,17 +2162,16 @@
 			break;
 		for (i = 0; i < nr_pages; i++) {
 			struct page *page = pvec.pages[i];
-			index = page->index;
-			if (index > end)
+			if (page->index > end)
 				break;
-			index++;
-
 			BUG_ON(!PageLocked(page));
 			BUG_ON(PageWriteback(page));
 			block_invalidatepage(page, 0);
 			ClearPageUptodate(page);
 			unlock_page(page);
 		}
+		index = pvec.pages[nr_pages - 1]->index + 1;
+		pagevec_release(&pvec);
 	}
 	return;
 }
@@ -2220,6 +2248,8 @@
 	 */
 	new.b_state = 0;
 	get_blocks_flags = EXT4_GET_BLOCKS_CREATE;
+	if (ext4_should_dioread_nolock(mpd->inode))
+		get_blocks_flags |= EXT4_GET_BLOCKS_IO_CREATE_EXT;
 	if (mpd->b_state & (1 << BH_Delay))
 		get_blocks_flags |= EXT4_GET_BLOCKS_DELALLOC_RESERVE;
 
@@ -2630,11 +2660,14 @@
 		ret = err;
 
 	walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one);
-	EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
+	ext4_set_inode_state(inode, EXT4_STATE_JDATA);
 out:
 	return ret;
 }
 
+static int ext4_set_bh_endio(struct buffer_head *bh, struct inode *inode);
+static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate);
+
 /*
  * Note that we don't need to start a transaction unless we're journaling data
  * because we should have holes filled from ext4_page_mkwrite(). We even don't
@@ -2682,7 +2715,7 @@
 	int ret = 0;
 	loff_t size;
 	unsigned int len;
-	struct buffer_head *page_bufs;
+	struct buffer_head *page_bufs = NULL;
 	struct inode *inode = page->mapping->host;
 
 	trace_ext4_writepage(inode, page);
@@ -2758,7 +2791,11 @@
 
 	if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
 		ret = nobh_writepage(page, noalloc_get_block_write, wbc);
-	else
+	else if (page_bufs && buffer_uninit(page_bufs)) {
+		ext4_set_bh_endio(page_bufs, inode);
+		ret = block_write_full_page_endio(page, noalloc_get_block_write,
+					    wbc, ext4_end_io_buffer_write);
+	} else
 		ret = block_write_full_page(page, noalloc_get_block_write,
 					    wbc);
 
@@ -3301,7 +3338,8 @@
 		filemap_write_and_wait(mapping);
 	}
 
-	if (EXT4_JOURNAL(inode) && EXT4_I(inode)->i_state & EXT4_STATE_JDATA) {
+	if (EXT4_JOURNAL(inode) &&
+	    ext4_test_inode_state(inode, EXT4_STATE_JDATA)) {
 		/*
 		 * This is a REALLY heavyweight approach, but the use of
 		 * bmap on dirty files is expected to be extremely rare:
@@ -3320,7 +3358,7 @@
 		 * everything they get.
 		 */
 
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_JDATA;
+		ext4_clear_inode_state(inode, EXT4_STATE_JDATA);
 		journal = EXT4_JOURNAL(inode);
 		jbd2_journal_lock_updates(journal);
 		err = jbd2_journal_flush(journal);
@@ -3345,11 +3383,45 @@
 	return mpage_readpages(mapping, pages, nr_pages, ext4_get_block);
 }
 
+static void ext4_free_io_end(ext4_io_end_t *io)
+{
+	BUG_ON(!io);
+	if (io->page)
+		put_page(io->page);
+	iput(io->inode);
+	kfree(io);
+}
+
+static void ext4_invalidatepage_free_endio(struct page *page, unsigned long offset)
+{
+	struct buffer_head *head, *bh;
+	unsigned int curr_off = 0;
+
+	if (!page_has_buffers(page))
+		return;
+	head = bh = page_buffers(page);
+	do {
+		if (offset <= curr_off && test_clear_buffer_uninit(bh)
+					&& bh->b_private) {
+			ext4_free_io_end(bh->b_private);
+			bh->b_private = NULL;
+			bh->b_end_io = NULL;
+		}
+		curr_off = curr_off + bh->b_size;
+		bh = bh->b_this_page;
+	} while (bh != head);
+}
+
 static void ext4_invalidatepage(struct page *page, unsigned long offset)
 {
 	journal_t *journal = EXT4_JOURNAL(page->mapping->host);
 
 	/*
+	 * free any io_end structure allocated for buffers to be discarded
+	 */
+	if (ext4_should_dioread_nolock(page->mapping->host))
+		ext4_invalidatepage_free_endio(page, offset);
+	/*
 	 * If it's a full truncate we just forget about the pending dirtying
 	 */
 	if (offset == 0)
@@ -3420,7 +3492,14 @@
 	}
 
 retry:
-	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+	if (rw == READ && ext4_should_dioread_nolock(inode))
+		ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
+				 inode->i_sb->s_bdev, iov,
+				 offset, nr_segs,
+				 ext4_get_block, NULL);
+	else
+		ret = blockdev_direct_IO(rw, iocb, inode,
+				 inode->i_sb->s_bdev, iov,
 				 offset, nr_segs,
 				 ext4_get_block, NULL);
 	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
@@ -3436,6 +3515,9 @@
 			 * but cannot extend i_size. Bail out and pretend
 			 * the write failed... */
 			ret = PTR_ERR(handle);
+			if (inode->i_nlink)
+				ext4_orphan_del(NULL, inode);
+
 			goto out;
 		}
 		if (inode->i_nlink)
@@ -3463,75 +3545,63 @@
 	return ret;
 }
 
-static int ext4_get_block_dio_write(struct inode *inode, sector_t iblock,
+static int ext4_get_block_write(struct inode *inode, sector_t iblock,
 		   struct buffer_head *bh_result, int create)
 {
-	handle_t *handle = NULL;
+	handle_t *handle = ext4_journal_current_handle();
 	int ret = 0;
 	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
 	int dio_credits;
+	int started = 0;
 
-	ext4_debug("ext4_get_block_dio_write: inode %lu, create flag %d\n",
+	ext4_debug("ext4_get_block_write: inode %lu, create flag %d\n",
 		   inode->i_ino, create);
 	/*
-	 * DIO VFS code passes create = 0 flag for write to
-	 * the middle of file. It does this to avoid block
-	 * allocation for holes, to prevent expose stale data
-	 * out when there is parallel buffered read (which does
-	 * not hold the i_mutex lock) while direct IO write has
-	 * not completed. DIO request on holes finally falls back
-	 * to buffered IO for this reason.
-	 *
-	 * For ext4 extent based file, since we support fallocate,
-	 * new allocated extent as uninitialized, for holes, we
-	 * could fallocate blocks for holes, thus parallel
-	 * buffered IO read will zero out the page when read on
-	 * a hole while parallel DIO write to the hole has not completed.
-	 *
-	 * when we come here, we know it's a direct IO write to
-	 * to the middle of file (<i_size)
-	 * so it's safe to override the create flag from VFS.
+	 * ext4_get_block in prepare for a DIO write or buffer write.
+	 * We allocate an uinitialized extent if blocks haven't been allocated.
+	 * The extent will be converted to initialized after IO complete.
 	 */
-	create = EXT4_GET_BLOCKS_DIO_CREATE_EXT;
+	create = EXT4_GET_BLOCKS_IO_CREATE_EXT;
 
-	if (max_blocks > DIO_MAX_BLOCKS)
-		max_blocks = DIO_MAX_BLOCKS;
-	dio_credits = ext4_chunk_trans_blocks(inode, max_blocks);
-	handle = ext4_journal_start(inode, dio_credits);
-	if (IS_ERR(handle)) {
-		ret = PTR_ERR(handle);
-		goto out;
+	if (!handle) {
+		if (max_blocks > DIO_MAX_BLOCKS)
+			max_blocks = DIO_MAX_BLOCKS;
+		dio_credits = ext4_chunk_trans_blocks(inode, max_blocks);
+		handle = ext4_journal_start(inode, dio_credits);
+		if (IS_ERR(handle)) {
+			ret = PTR_ERR(handle);
+			goto out;
+		}
+		started = 1;
 	}
+
 	ret = ext4_get_blocks(handle, inode, iblock, max_blocks, bh_result,
 			      create);
 	if (ret > 0) {
 		bh_result->b_size = (ret << inode->i_blkbits);
 		ret = 0;
 	}
-	ext4_journal_stop(handle);
+	if (started)
+		ext4_journal_stop(handle);
 out:
 	return ret;
 }
 
-static void ext4_free_io_end(ext4_io_end_t *io)
-{
-	BUG_ON(!io);
-	iput(io->inode);
-	kfree(io);
-}
-static void dump_aio_dio_list(struct inode * inode)
+static void dump_completed_IO(struct inode * inode)
 {
 #ifdef	EXT4_DEBUG
 	struct list_head *cur, *before, *after;
 	ext4_io_end_t *io, *io0, *io1;
+	unsigned long flags;
 
-	if (list_empty(&EXT4_I(inode)->i_aio_dio_complete_list)){
-		ext4_debug("inode %lu aio dio list is empty\n", inode->i_ino);
+	if (list_empty(&EXT4_I(inode)->i_completed_io_list)){
+		ext4_debug("inode %lu completed_io list is empty\n", inode->i_ino);
 		return;
 	}
 
-	ext4_debug("Dump inode %lu aio_dio_completed_IO list \n", inode->i_ino);
-	list_for_each_entry(io, &EXT4_I(inode)->i_aio_dio_complete_list, list){
+	ext4_debug("Dump inode %lu completed_io list \n", inode->i_ino);
+	spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
+	list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list){
 		cur = &io->list;
 		before = cur->prev;
 		io0 = container_of(before, ext4_io_end_t, list);
@@ -3541,32 +3611,31 @@
 		ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n",
 			    io, inode->i_ino, io0, io1);
 	}
+	spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags);
 #endif
 }
 
 /*
  * check a range of space and convert unwritten extents to written.
  */
-static int ext4_end_aio_dio_nolock(ext4_io_end_t *io)
+static int ext4_end_io_nolock(ext4_io_end_t *io)
 {
 	struct inode *inode = io->inode;
 	loff_t offset = io->offset;
-	size_t size = io->size;
+	ssize_t size = io->size;
 	int ret = 0;
 
-	ext4_debug("end_aio_dio_onlock: io 0x%p from inode %lu,list->next 0x%p,"
+	ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p,"
 		   "list->prev 0x%p\n",
 	           io, inode->i_ino, io->list.next, io->list.prev);
 
 	if (list_empty(&io->list))
 		return ret;
 
-	if (io->flag != DIO_AIO_UNWRITTEN)
+	if (io->flag != EXT4_IO_UNWRITTEN)
 		return ret;
 
-	if (offset + size <= i_size_read(inode))
-		ret = ext4_convert_unwritten_extents(inode, offset, size);
-
+	ret = ext4_convert_unwritten_extents(inode, offset, size);
 	if (ret < 0) {
 		printk(KERN_EMERG "%s: failed to convert unwritten"
 			"extents to written extents, error is %d"
@@ -3579,50 +3648,64 @@
 	io->flag = 0;
 	return ret;
 }
+
 /*
  * work on completed aio dio IO, to convert unwritten extents to extents
  */
-static void ext4_end_aio_dio_work(struct work_struct *work)
+static void ext4_end_io_work(struct work_struct *work)
 {
-	ext4_io_end_t *io  = container_of(work, ext4_io_end_t, work);
-	struct inode *inode = io->inode;
-	int ret = 0;
+	ext4_io_end_t		*io = container_of(work, ext4_io_end_t, work);
+	struct inode		*inode = io->inode;
+	struct ext4_inode_info	*ei = EXT4_I(inode);
+	unsigned long		flags;
+	int			ret;
 
 	mutex_lock(&inode->i_mutex);
-	ret = ext4_end_aio_dio_nolock(io);
-	if (ret >= 0) {
-		if (!list_empty(&io->list))
-			list_del_init(&io->list);
-		ext4_free_io_end(io);
+	ret = ext4_end_io_nolock(io);
+	if (ret < 0) {
+		mutex_unlock(&inode->i_mutex);
+		return;
 	}
+
+	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+	if (!list_empty(&io->list))
+		list_del_init(&io->list);
+	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 	mutex_unlock(&inode->i_mutex);
+	ext4_free_io_end(io);
 }
+
 /*
  * This function is called from ext4_sync_file().
  *
- * When AIO DIO IO is completed, the work to convert unwritten
- * extents to written is queued on workqueue but may not get immediately
+ * When IO is completed, the work to convert unwritten extents to
+ * written is queued on workqueue but may not get immediately
  * scheduled. When fsync is called, we need to ensure the
  * conversion is complete before fsync returns.
- * The inode keeps track of a list of completed AIO from DIO path
- * that might needs to do the conversion. This function walks through
- * the list and convert the related unwritten extents to written.
+ * The inode keeps track of a list of pending/completed IO that
+ * might needs to do the conversion. This function walks through
+ * the list and convert the related unwritten extents for completed IO
+ * to written.
+ * The function return the number of pending IOs on success.
  */
-int flush_aio_dio_completed_IO(struct inode *inode)
+int flush_completed_IO(struct inode *inode)
 {
 	ext4_io_end_t *io;
+	struct ext4_inode_info *ei = EXT4_I(inode);
+	unsigned long flags;
 	int ret = 0;
 	int ret2 = 0;
 
-	if (list_empty(&EXT4_I(inode)->i_aio_dio_complete_list))
+	if (list_empty(&ei->i_completed_io_list))
 		return ret;
 
-	dump_aio_dio_list(inode);
-	while (!list_empty(&EXT4_I(inode)->i_aio_dio_complete_list)){
-		io = list_entry(EXT4_I(inode)->i_aio_dio_complete_list.next,
+	dump_completed_IO(inode);
+	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+	while (!list_empty(&ei->i_completed_io_list)){
+		io = list_entry(ei->i_completed_io_list.next,
 				ext4_io_end_t, list);
 		/*
-		 * Calling ext4_end_aio_dio_nolock() to convert completed
+		 * Calling ext4_end_io_nolock() to convert completed
 		 * IO to written.
 		 *
 		 * When ext4_sync_file() is called, run_queue() may already
@@ -3635,20 +3718,23 @@
 		 * avoid double converting from both fsync and background work
 		 * queue work.
 		 */
-		ret = ext4_end_aio_dio_nolock(io);
+		spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+		ret = ext4_end_io_nolock(io);
+		spin_lock_irqsave(&ei->i_completed_io_lock, flags);
 		if (ret < 0)
 			ret2 = ret;
 		else
 			list_del_init(&io->list);
 	}
+	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 	return (ret2 < 0) ? ret2 : 0;
 }
 
-static ext4_io_end_t *ext4_init_io_end (struct inode *inode)
+static ext4_io_end_t *ext4_init_io_end (struct inode *inode, gfp_t flags)
 {
 	ext4_io_end_t *io = NULL;
 
-	io = kmalloc(sizeof(*io), GFP_NOFS);
+	io = kmalloc(sizeof(*io), flags);
 
 	if (io) {
 		igrab(inode);
@@ -3656,8 +3742,8 @@
 		io->flag = 0;
 		io->offset = 0;
 		io->size = 0;
-		io->error = 0;
-		INIT_WORK(&io->work, ext4_end_aio_dio_work);
+		io->page = NULL;
+		INIT_WORK(&io->work, ext4_end_io_work);
 		INIT_LIST_HEAD(&io->list);
 	}
 
@@ -3669,6 +3755,8 @@
 {
         ext4_io_end_t *io_end = iocb->private;
 	struct workqueue_struct *wq;
+	unsigned long flags;
+	struct ext4_inode_info *ei;
 
 	/* if not async direct IO or dio with 0 bytes write, just return */
 	if (!io_end || !size)
@@ -3680,7 +3768,7 @@
 		  size);
 
 	/* if not aio dio with unwritten extents, just free io and return */
-	if (io_end->flag != DIO_AIO_UNWRITTEN){
+	if (io_end->flag != EXT4_IO_UNWRITTEN){
 		ext4_free_io_end(io_end);
 		iocb->private = NULL;
 		return;
@@ -3688,16 +3776,85 @@
 
 	io_end->offset = offset;
 	io_end->size = size;
+	io_end->flag = EXT4_IO_UNWRITTEN;
 	wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq;
 
 	/* queue the work to convert unwritten extents to written */
 	queue_work(wq, &io_end->work);
 
 	/* Add the io_end to per-inode completed aio dio list*/
-	list_add_tail(&io_end->list,
-		 &EXT4_I(io_end->inode)->i_aio_dio_complete_list);
+	ei = EXT4_I(io_end->inode);
+	spin_lock_irqsave(&ei->i_completed_io_lock, flags);
+	list_add_tail(&io_end->list, &ei->i_completed_io_list);
+	spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 	iocb->private = NULL;
 }
+
+static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
+{
+	ext4_io_end_t *io_end = bh->b_private;
+	struct workqueue_struct *wq;
+	struct inode *inode;
+	unsigned long flags;
+
+	if (!test_clear_buffer_uninit(bh) || !io_end)
+		goto out;
+
+	if (!(io_end->inode->i_sb->s_flags & MS_ACTIVE)) {
+		printk("sb umounted, discard end_io request for inode %lu\n",
+			io_end->inode->i_ino);
+		ext4_free_io_end(io_end);
+		goto out;
+	}
+
+	io_end->flag = EXT4_IO_UNWRITTEN;
+	inode = io_end->inode;
+
+	/* Add the io_end to per-inode completed io list*/
+	spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
+	list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list);
+	spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags);
+
+	wq = EXT4_SB(inode->i_sb)->dio_unwritten_wq;
+	/* queue the work to convert unwritten extents to written */
+	queue_work(wq, &io_end->work);
+out:
+	bh->b_private = NULL;
+	bh->b_end_io = NULL;
+	clear_buffer_uninit(bh);
+	end_buffer_async_write(bh, uptodate);
+}
+
+static int ext4_set_bh_endio(struct buffer_head *bh, struct inode *inode)
+{
+	ext4_io_end_t *io_end;
+	struct page *page = bh->b_page;
+	loff_t offset = (sector_t)page->index << PAGE_CACHE_SHIFT;
+	size_t size = bh->b_size;
+
+retry:
+	io_end = ext4_init_io_end(inode, GFP_ATOMIC);
+	if (!io_end) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING "%s: allocation fail\n", __func__);
+		schedule();
+		goto retry;
+	}
+	io_end->offset = offset;
+	io_end->size = size;
+	/*
+	 * We need to hold a reference to the page to make sure it
+	 * doesn't get evicted before ext4_end_io_work() has a chance
+	 * to convert the extent from written to unwritten.
+	 */
+	io_end->page = page;
+	get_page(io_end->page);
+
+	bh->b_private = io_end;
+	bh->b_end_io = ext4_end_io_buffer_write;
+	return 0;
+}
+
 /*
  * For ext4 extent files, ext4 will do direct-io write to holes,
  * preallocated extents, and those write extend the file, no need to
@@ -3751,7 +3908,7 @@
 		iocb->private = NULL;
 		EXT4_I(inode)->cur_aio_dio = NULL;
 		if (!is_sync_kiocb(iocb)) {
-			iocb->private = ext4_init_io_end(inode);
+			iocb->private = ext4_init_io_end(inode, GFP_NOFS);
 			if (!iocb->private)
 				return -ENOMEM;
 			/*
@@ -3767,7 +3924,7 @@
 		ret = blockdev_direct_IO(rw, iocb, inode,
 					 inode->i_sb->s_bdev, iov,
 					 offset, nr_segs,
-					 ext4_get_block_dio_write,
+					 ext4_get_block_write,
 					 ext4_end_io_dio);
 		if (iocb->private)
 			EXT4_I(inode)->cur_aio_dio = NULL;
@@ -3788,8 +3945,8 @@
 		if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
 			ext4_free_io_end(iocb->private);
 			iocb->private = NULL;
-		} else if (ret > 0 && (EXT4_I(inode)->i_state &
-				       EXT4_STATE_DIO_UNWRITTEN)) {
+		} else if (ret > 0 && ext4_test_inode_state(inode,
+						EXT4_STATE_DIO_UNWRITTEN)) {
 			int err;
 			/*
 			 * for non AIO case, since the IO is already
@@ -3799,7 +3956,7 @@
 							     offset, ret);
 			if (err < 0)
 				ret = err;
-			EXT4_I(inode)->i_state &= ~EXT4_STATE_DIO_UNWRITTEN;
+			ext4_clear_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN);
 		}
 		return ret;
 	}
@@ -4130,18 +4287,27 @@
  * We release `count' blocks on disk, but (last - first) may be greater
  * than `count' because there can be holes in there.
  */
-static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
-			      struct buffer_head *bh,
-			      ext4_fsblk_t block_to_free,
-			      unsigned long count, __le32 *first,
-			      __le32 *last)
+static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
+			     struct buffer_head *bh,
+			     ext4_fsblk_t block_to_free,
+			     unsigned long count, __le32 *first,
+			     __le32 *last)
 {
 	__le32 *p;
-	int	flags = EXT4_FREE_BLOCKS_FORGET;
+	int	flags = EXT4_FREE_BLOCKS_FORGET | EXT4_FREE_BLOCKS_VALIDATED;
 
 	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
 		flags |= EXT4_FREE_BLOCKS_METADATA;
 
+	if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), block_to_free,
+				   count)) {
+		ext4_error(inode->i_sb, "inode #%lu: "
+			   "attempt to clear blocks %llu len %lu, invalid",
+			   inode->i_ino, (unsigned long long) block_to_free,
+			   count);
+		return 1;
+	}
+
 	if (try_to_extend_transaction(handle, inode)) {
 		if (bh) {
 			BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
@@ -4160,6 +4326,7 @@
 		*p = 0;
 
 	ext4_free_blocks(handle, inode, 0, block_to_free, count, flags);
+	return 0;
 }
 
 /**
@@ -4215,9 +4382,10 @@
 			} else if (nr == block_to_free + count) {
 				count++;
 			} else {
-				ext4_clear_blocks(handle, inode, this_bh,
-						  block_to_free,
-						  count, block_to_free_p, p);
+				if (ext4_clear_blocks(handle, inode, this_bh,
+						      block_to_free, count,
+						      block_to_free_p, p))
+					break;
 				block_to_free = nr;
 				block_to_free_p = p;
 				count = 1;
@@ -4241,7 +4409,7 @@
 		if ((EXT4_JOURNAL(inode) == NULL) || bh2jh(this_bh))
 			ext4_handle_dirty_metadata(handle, inode, this_bh);
 		else
-			ext4_error(inode->i_sb, __func__,
+			ext4_error(inode->i_sb,
 				   "circular indirect block detected, "
 				   "inode=%lu, block=%llu",
 				   inode->i_ino,
@@ -4281,6 +4449,16 @@
 			if (!nr)
 				continue;		/* A hole */
 
+			if (!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+						   nr, 1)) {
+				ext4_error(inode->i_sb,
+					   "indirect mapped block in inode "
+					   "#%lu invalid (level %d, blk #%lu)",
+					   inode->i_ino, depth,
+					   (unsigned long) nr);
+				break;
+			}
+
 			/* Go read the buffer for the next level down */
 			bh = sb_bread(inode->i_sb, nr);
 
@@ -4289,7 +4467,7 @@
 			 * (should be rare).
 			 */
 			if (!bh) {
-				ext4_error(inode->i_sb, "ext4_free_branches",
+				ext4_error(inode->i_sb,
 					   "Read failure, inode=%lu, block=%llu",
 					   inode->i_ino, nr);
 				continue;
@@ -4433,8 +4611,10 @@
 	if (!ext4_can_truncate(inode))
 		return;
 
+	EXT4_I(inode)->i_flags &= ~EXT4_EOFBLOCKS_FL;
+
 	if (inode->i_size == 0 && !test_opt(inode->i_sb, NO_AUTO_DA_ALLOC))
-		ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE;
+		ext4_set_inode_state(inode, EXT4_STATE_DA_ALLOC_CLOSE);
 
 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
 		ext4_ext_truncate(inode);
@@ -4604,9 +4784,8 @@
 
 	bh = sb_getblk(sb, block);
 	if (!bh) {
-		ext4_error(sb, "ext4_get_inode_loc", "unable to read "
-			   "inode block - inode=%lu, block=%llu",
-			   inode->i_ino, block);
+		ext4_error(sb, "unable to read inode block - "
+			   "inode=%lu, block=%llu", inode->i_ino, block);
 		return -EIO;
 	}
 	if (!buffer_uptodate(bh)) {
@@ -4704,9 +4883,8 @@
 		submit_bh(READ_META, bh);
 		wait_on_buffer(bh);
 		if (!buffer_uptodate(bh)) {
-			ext4_error(sb, __func__,
-				   "unable to read inode block - inode=%lu, "
-				   "block=%llu", inode->i_ino, block);
+			ext4_error(sb, "unable to read inode block - inode=%lu,"
+				   " block=%llu", inode->i_ino, block);
 			brelse(bh);
 			return -EIO;
 		}
@@ -4720,7 +4898,7 @@
 {
 	/* We have all inode data except xattrs in memory here. */
 	return __ext4_get_inode_loc(inode, iloc,
-		!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR));
+		!ext4_test_inode_state(inode, EXT4_STATE_XATTR));
 }
 
 void ext4_set_inode_flags(struct inode *inode)
@@ -4814,7 +4992,7 @@
 	}
 	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
 
-	ei->i_state = 0;
+	ei->i_state_flags = 0;
 	ei->i_dir_start_lookup = 0;
 	ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
 	/* We now have enough fields to check if the inode was active or not.
@@ -4897,7 +5075,7 @@
 					EXT4_GOOD_OLD_INODE_SIZE +
 					ei->i_extra_isize;
 			if (*magic == cpu_to_le32(EXT4_XATTR_MAGIC))
-				ei->i_state |= EXT4_STATE_XATTR;
+				ext4_set_inode_state(inode, EXT4_STATE_XATTR);
 		}
 	} else
 		ei->i_extra_isize = 0;
@@ -4917,8 +5095,7 @@
 	ret = 0;
 	if (ei->i_file_acl &&
 	    !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) {
-		ext4_error(sb, __func__,
-			   "bad extended attribute block %llu in inode #%lu",
+		ext4_error(sb, "bad extended attribute block %llu inode #%lu",
 			   ei->i_file_acl, inode->i_ino);
 		ret = -EIO;
 		goto bad_inode;
@@ -4964,8 +5141,7 @@
 			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
 	} else {
 		ret = -EIO;
-		ext4_error(inode->i_sb, __func__,
-			   "bogus i_mode (%o) for inode=%lu",
+		ext4_error(inode->i_sb, "bogus i_mode (%o) for inode=%lu",
 			   inode->i_mode, inode->i_ino);
 		goto bad_inode;
 	}
@@ -5037,7 +5213,7 @@
 
 	/* For fields not not tracking in the in-memory inode,
 	 * initialise them to zero for new inodes. */
-	if (ei->i_state & EXT4_STATE_NEW)
+	if (ext4_test_inode_state(inode, EXT4_STATE_NEW))
 		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
 
 	ext4_get_inode_flags(ei);
@@ -5101,7 +5277,7 @@
 					EXT4_FEATURE_RO_COMPAT_LARGE_FILE);
 			sb->s_dirt = 1;
 			ext4_handle_sync(handle);
-			err = ext4_handle_dirty_metadata(handle, inode,
+			err = ext4_handle_dirty_metadata(handle, NULL,
 					EXT4_SB(sb)->s_sbh);
 		}
 	}
@@ -5130,10 +5306,10 @@
 	}
 
 	BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
-	rc = ext4_handle_dirty_metadata(handle, inode, bh);
+	rc = ext4_handle_dirty_metadata(handle, NULL, bh);
 	if (!err)
 		err = rc;
-	ei->i_state &= ~EXT4_STATE_NEW;
+	ext4_clear_inode_state(inode, EXT4_STATE_NEW);
 
 	ext4_update_inode_fsync_trans(handle, inode, 0);
 out_brelse:
@@ -5177,7 +5353,7 @@
  * `stuff()' is running, and the new i_size will be lost.  Plus the inode
  * will no longer be on the superblock's dirty inode list.
  */
-int ext4_write_inode(struct inode *inode, int wait)
+int ext4_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	int err;
 
@@ -5191,7 +5367,7 @@
 			return -EIO;
 		}
 
-		if (!wait)
+		if (wbc->sync_mode != WB_SYNC_ALL)
 			return 0;
 
 		err = ext4_force_commit(inode->i_sb);
@@ -5201,13 +5377,11 @@
 		err = ext4_get_inode_loc(inode, &iloc);
 		if (err)
 			return err;
-		if (wait)
+		if (wbc->sync_mode == WB_SYNC_ALL)
 			sync_dirty_buffer(iloc.bh);
 		if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) {
-			ext4_error(inode->i_sb, __func__,
-				   "IO error syncing inode, "
-				   "inode=%lu, block=%llu",
-				   inode->i_ino,
+			ext4_error(inode->i_sb, "IO error syncing inode, "
+				   "inode=%lu, block=%llu", inode->i_ino,
 				   (unsigned long long)iloc.bh->b_blocknr);
 			err = -EIO;
 		}
@@ -5249,6 +5423,8 @@
 	if (error)
 		return error;
 
+	if (ia_valid & ATTR_SIZE)
+		dquot_initialize(inode);
 	if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
 		(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
 		handle_t *handle;
@@ -5261,7 +5437,7 @@
 			error = PTR_ERR(handle);
 			goto err_out;
 		}
-		error = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0;
+		error = dquot_transfer(inode, attr);
 		if (error) {
 			ext4_journal_stop(handle);
 			return error;
@@ -5288,7 +5464,9 @@
 	}
 
 	if (S_ISREG(inode->i_mode) &&
-	    attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
+	    attr->ia_valid & ATTR_SIZE &&
+	    (attr->ia_size < inode->i_size ||
+	     (EXT4_I(inode)->i_flags & EXT4_EOFBLOCKS_FL))) {
 		handle_t *handle;
 
 		handle = ext4_journal_start(inode, 3);
@@ -5319,6 +5497,9 @@
 				goto err_out;
 			}
 		}
+		/* ext4_truncate will clear the flag */
+		if ((EXT4_I(inode)->i_flags & EXT4_EOFBLOCKS_FL))
+			ext4_truncate(inode);
 	}
 
 	rc = inode_setattr(inode, attr);
@@ -5557,8 +5738,8 @@
 	entry = IFIRST(header);
 
 	/* No extended attributes present */
-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR) ||
-		header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
+	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
+	    header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
 		memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0,
 			new_extra_isize);
 		EXT4_I(inode)->i_extra_isize = new_extra_isize;
@@ -5602,7 +5783,7 @@
 	err = ext4_reserve_inode_write(handle, inode, &iloc);
 	if (ext4_handle_valid(handle) &&
 	    EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize &&
-	    !(EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND)) {
+	    !ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND)) {
 		/*
 		 * We need extra buffer credits since we may write into EA block
 		 * with this same handle. If journal_extend fails, then it will
@@ -5616,10 +5797,11 @@
 						      sbi->s_want_extra_isize,
 						      iloc, handle);
 			if (ret) {
-				EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
+				ext4_set_inode_state(inode,
+						     EXT4_STATE_NO_EXPAND);
 				if (mnt_count !=
 					le16_to_cpu(sbi->s_es->s_mnt_count)) {
-					ext4_warning(inode->i_sb, __func__,
+					ext4_warning(inode->i_sb,
 					"Unable to expand inode %lu. Delete"
 					" some EAs or run e2fsck.",
 					inode->i_ino);
@@ -5641,7 +5823,7 @@
  * i_size has been changed by generic_commit_write() and we thus need
  * to include the updated inode in the current transaction.
  *
- * Also, vfs_dq_alloc_block() will always dirty the inode when blocks
+ * Also, dquot_alloc_block() will always dirty the inode when blocks
  * are allocated to the file.
  *
  * If the inode is marked synchronous, we don't honour that here - doing
@@ -5683,7 +5865,7 @@
 			err = jbd2_journal_get_write_access(handle, iloc.bh);
 			if (!err)
 				err = ext4_handle_dirty_metadata(handle,
-								 inode,
+								 NULL,
 								 iloc.bh);
 			brelse(iloc.bh);
 		}
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index b63d193..016d024 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -92,6 +92,15 @@
 			flags &= ~EXT4_EXTENTS_FL;
 		}
 
+		if (flags & EXT4_EOFBLOCKS_FL) {
+			/* we don't support adding EOFBLOCKS flag */
+			if (!(oldflags & EXT4_EOFBLOCKS_FL)) {
+				err = -EOPNOTSUPP;
+				goto flags_out;
+			}
+		} else if (oldflags & EXT4_EOFBLOCKS_FL)
+			ext4_truncate(inode);
+
 		handle = ext4_journal_start(inode, 1);
 		if (IS_ERR(handle)) {
 			err = PTR_ERR(handle);
@@ -249,7 +258,8 @@
 		if (me.moved_len > 0)
 			file_remove_suid(donor_filp);
 
-		if (copy_to_user((struct move_extent *)arg, &me, sizeof(me)))
+		if (copy_to_user((struct move_extent __user *)arg, 
+				 &me, sizeof(me)))
 			err = -EFAULT;
 mext_out:
 		fput(donor_filp);
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index d34afad..54df209 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -69,7 +69,7 @@
  *
  * pa_lstart -> the logical start block for this prealloc space
  * pa_pstart -> the physical start block for this prealloc space
- * pa_len    -> lenght for this prealloc space
+ * pa_len    -> length for this prealloc space
  * pa_free   ->  free space available in this prealloc space
  *
  * The inode preallocation space is used looking at the _logical_ start
@@ -441,10 +441,9 @@
 	for (i = 0; i < count; i++) {
 		if (!mb_test_bit(first + i, e4b->bd_info->bb_bitmap)) {
 			ext4_fsblk_t blocknr;
-			blocknr = e4b->bd_group * EXT4_BLOCKS_PER_GROUP(sb);
+
+			blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
 			blocknr += first + i;
-			blocknr +=
-			    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
 			ext4_grp_locked_error(sb, e4b->bd_group,
 				   __func__, "double-free of inode"
 				   " %lu's block %llu(bit %u in group %u)",
@@ -1255,10 +1254,9 @@
 
 		if (!mb_test_bit(block, EXT4_MB_BITMAP(e4b))) {
 			ext4_fsblk_t blocknr;
-			blocknr = e4b->bd_group * EXT4_BLOCKS_PER_GROUP(sb);
+
+			blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
 			blocknr += block;
-			blocknr +=
-			    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
 			ext4_grp_locked_error(sb, e4b->bd_group,
 				   __func__, "double-free of inode"
 				   " %lu's block %llu(bit %u in group %u)",
@@ -1631,7 +1629,6 @@
 	int max;
 	int err;
 	struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
-	struct ext4_super_block *es = sbi->s_es;
 	struct ext4_free_extent ex;
 
 	if (!(ac->ac_flags & EXT4_MB_HINT_TRY_GOAL))
@@ -1648,8 +1645,8 @@
 	if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) {
 		ext4_fsblk_t start;
 
-		start = (e4b->bd_group * EXT4_BLOCKS_PER_GROUP(ac->ac_sb)) +
-			ex.fe_start + le32_to_cpu(es->s_first_data_block);
+		start = ext4_group_first_block_no(ac->ac_sb, e4b->bd_group) +
+			ex.fe_start;
 		/* use do_div to get remainder (would be 64-bit modulo) */
 		if (do_div(start, sbi->s_stripe) == 0) {
 			ac->ac_found++;
@@ -1803,8 +1800,8 @@
 	BUG_ON(sbi->s_stripe == 0);
 
 	/* find first stripe-aligned block in group */
-	first_group_block = e4b->bd_group * EXT4_BLOCKS_PER_GROUP(sb)
-		+ le32_to_cpu(sbi->s_es->s_first_data_block);
+	first_group_block = ext4_group_first_block_no(sb, e4b->bd_group);
+
 	a = first_group_block + sbi->s_stripe - 1;
 	do_div(a, sbi->s_stripe);
 	i = (a * sbi->s_stripe) - first_group_block;
@@ -2256,7 +2253,7 @@
 
 	INIT_LIST_HEAD(&meta_group_info[i]->bb_prealloc_list);
 	init_rwsem(&meta_group_info[i]->alloc_sem);
-	meta_group_info[i]->bb_free_root.rb_node = NULL;
+	meta_group_info[i]->bb_free_root = RB_ROOT;
 
 #ifdef DOUBLE_CHECK
 	{
@@ -2560,12 +2557,9 @@
 		ext4_unlock_group(sb, entry->group);
 		if (test_opt(sb, DISCARD)) {
 			ext4_fsblk_t discard_block;
-			struct ext4_super_block *es = EXT4_SB(sb)->s_es;
 
-			discard_block = (ext4_fsblk_t)entry->group *
-						EXT4_BLOCKS_PER_GROUP(sb)
-					+ entry->start_blk
-					+ le32_to_cpu(es->s_first_data_block);
+			discard_block = entry->start_blk +
+				ext4_group_first_block_no(sb, entry->group);
 			trace_ext4_discard_blocks(sb,
 					(unsigned long long)discard_block,
 					entry->count);
@@ -2703,14 +2697,11 @@
 	if (err)
 		goto out_err;
 
-	block = ac->ac_b_ex.fe_group * EXT4_BLOCKS_PER_GROUP(sb)
-		+ ac->ac_b_ex.fe_start
-		+ le32_to_cpu(es->s_first_data_block);
+	block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
 
 	len = ac->ac_b_ex.fe_len;
 	if (!ext4_data_block_valid(sbi, block, len)) {
-		ext4_error(sb, __func__,
-			   "Allocating blocks %llu-%llu which overlap "
+		ext4_error(sb, "Allocating blocks %llu-%llu which overlap "
 			   "fs metadata\n", block, block+len);
 		/* File system mounted not to panic on error
 		 * Fix the bitmap and repeat the block allocation
@@ -3161,9 +3152,7 @@
 		/* The max size of hash table is PREALLOC_TB_SIZE */
 		order = PREALLOC_TB_SIZE - 1;
 
-	goal_block = ac->ac_g_ex.fe_group * EXT4_BLOCKS_PER_GROUP(ac->ac_sb) +
-		     ac->ac_g_ex.fe_start +
-		     le32_to_cpu(EXT4_SB(ac->ac_sb)->s_es->s_first_data_block);
+	goal_block = ext4_grp_offs_to_block(ac->ac_sb, &ac->ac_g_ex);
 	/*
 	 * search for the prealloc space that is having
 	 * minimal distance from the goal block.
@@ -3526,8 +3515,7 @@
 		if (bit >= end)
 			break;
 		next = mb_find_next_bit(bitmap_bh->b_data, end, bit);
-		start = group * EXT4_BLOCKS_PER_GROUP(sb) + bit +
-				le32_to_cpu(sbi->s_es->s_first_data_block);
+		start = ext4_group_first_block_no(sb, group) + bit;
 		mb_debug(1, "    free preallocated %u/%u in group %u\n",
 				(unsigned) start, (unsigned) next - bit,
 				(unsigned) group);
@@ -3623,15 +3611,13 @@
 
 	bitmap_bh = ext4_read_block_bitmap(sb, group);
 	if (bitmap_bh == NULL) {
-		ext4_error(sb, __func__, "Error in reading block "
-				"bitmap for %u", group);
+		ext4_error(sb, "Error reading block bitmap for %u", group);
 		return 0;
 	}
 
 	err = ext4_mb_load_buddy(sb, group, &e4b);
 	if (err) {
-		ext4_error(sb, __func__, "Error in loading buddy "
-				"information for %u", group);
+		ext4_error(sb, "Error loading buddy information for %u", group);
 		put_bh(bitmap_bh);
 		return 0;
 	}
@@ -3804,15 +3790,15 @@
 
 		err = ext4_mb_load_buddy(sb, group, &e4b);
 		if (err) {
-			ext4_error(sb, __func__, "Error in loading buddy "
-					"information for %u", group);
+			ext4_error(sb, "Error loading buddy information for %u",
+					group);
 			continue;
 		}
 
 		bitmap_bh = ext4_read_block_bitmap(sb, group);
 		if (bitmap_bh == NULL) {
-			ext4_error(sb, __func__, "Error in reading block "
-					"bitmap for %u", group);
+			ext4_error(sb, "Error reading block bitmap for %u",
+					group);
 			ext4_mb_release_desc(&e4b);
 			continue;
 		}
@@ -3938,7 +3924,7 @@
 
 	/* don't use group allocation for large files */
 	size = max(size, isize);
-	if (size >= sbi->s_mb_stream_request) {
+	if (size > sbi->s_mb_stream_request) {
 		ac->ac_flags |= EXT4_MB_STREAM_ALLOC;
 		return;
 	}
@@ -4077,8 +4063,8 @@
 
 		ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL);
 		if (ext4_mb_load_buddy(sb, group, &e4b)) {
-			ext4_error(sb, __func__, "Error in loading buddy "
-					"information for %u", group);
+			ext4_error(sb, "Error loading buddy information for %u",
+					group);
 			continue;
 		}
 		ext4_lock_group(sb, group);
@@ -4254,7 +4240,7 @@
 			return 0;
 		}
 		reserv_blks = ar->len;
-		while (ar->len && vfs_dq_alloc_block(ar->inode, ar->len)) {
+		while (ar->len && dquot_alloc_block(ar->inode, ar->len)) {
 			ar->flags |= EXT4_MB_HINT_NOPREALLOC;
 			ar->len--;
 		}
@@ -4331,7 +4317,7 @@
 	kmem_cache_free(ext4_ac_cachep, ac);
 out1:
 	if (inquota && ar->len < inquota)
-		vfs_dq_free_block(ar->inode, inquota - ar->len);
+		dquot_free_block(ar->inode, inquota - ar->len);
 out3:
 	if (!ar->len) {
 		if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag)
@@ -4476,10 +4462,10 @@
 
 	sbi = EXT4_SB(sb);
 	es = EXT4_SB(sb)->s_es;
-	if (!ext4_data_block_valid(sbi, block, count)) {
-		ext4_error(sb, __func__,
-			    "Freeing blocks not in datazone - "
-			    "block = %llu, count = %lu", block, count);
+	if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
+	    !ext4_data_block_valid(sbi, block, count)) {
+		ext4_error(sb, "Freeing blocks not in datazone - "
+			   "block = %llu, count = %lu", block, count);
 		goto error_return;
 	}
 
@@ -4547,8 +4533,7 @@
 	    in_range(block + count - 1, ext4_inode_table(sb, gdp),
 		      EXT4_SB(sb)->s_itb_per_group)) {
 
-		ext4_error(sb, __func__,
-			   "Freeing blocks in system zone - "
+		ext4_error(sb, "Freeing blocks in system zone - "
 			   "Block = %llu, count = %lu", block, count);
 		/* err = 0. ext4_std_error should be a no op */
 		goto error_return;
@@ -4646,7 +4631,7 @@
 	sb->s_dirt = 1;
 error_return:
 	if (freed)
-		vfs_dq_free_block(inode, freed);
+		dquot_free_block(inode, freed);
 	brelse(bitmap_bh);
 	ext4_std_error(sb, err);
 	if (ac)
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
index 436521c..b619322 100644
--- a/fs/ext4/mballoc.h
+++ b/fs/ext4/mballoc.h
@@ -220,16 +220,9 @@
 #define EXT4_MB_BITMAP(e4b)	((e4b)->bd_bitmap)
 #define EXT4_MB_BUDDY(e4b)	((e4b)->bd_buddy)
 
-#define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
-
 static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
 					struct ext4_free_extent *fex)
 {
-	ext4_fsblk_t block;
-
-	block = (ext4_fsblk_t) fex->fe_group * EXT4_BLOCKS_PER_GROUP(sb)
-			+ fex->fe_start
-			+ le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
-	return block;
+	return ext4_group_first_block_no(sb, fex->fe_group) + fex->fe_start;
 }
 #endif
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
index 8141581..8b87bd0 100644
--- a/fs/ext4/migrate.c
+++ b/fs/ext4/migrate.c
@@ -365,12 +365,12 @@
 	 * happened after we started the migrate. We need to
 	 * fail the migrate
 	 */
-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_EXT_MIGRATE)) {
+	if (!ext4_test_inode_state(inode, EXT4_STATE_EXT_MIGRATE)) {
 		retval = -EAGAIN;
 		up_write(&EXT4_I(inode)->i_data_sem);
 		goto err_out;
 	} else
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
+		ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
 	/*
 	 * We have the extent map build with the tmp inode.
 	 * Now copy the i_data across
@@ -503,14 +503,10 @@
 	}
 	i_size_write(tmp_inode, i_size_read(inode));
 	/*
-	 * We don't want the inode to be reclaimed
-	 * if we got interrupted in between. We have
-	 * this tmp inode carrying reference to the
-	 * data blocks of the original file. We set
-	 * the i_nlink to zero at the last stage after
-	 * switching the original file to extent format
+	 * Set the i_nlink to zero so it will be deleted later
+	 * when we drop inode reference.
 	 */
-	tmp_inode->i_nlink = 1;
+	tmp_inode->i_nlink = 0;
 
 	ext4_ext_tree_init(handle, tmp_inode);
 	ext4_orphan_add(handle, tmp_inode);
@@ -533,10 +529,20 @@
 	 * allocation.
 	 */
 	down_read((&EXT4_I(inode)->i_data_sem));
-	EXT4_I(inode)->i_state |= EXT4_STATE_EXT_MIGRATE;
+	ext4_set_inode_state(inode, EXT4_STATE_EXT_MIGRATE);
 	up_read((&EXT4_I(inode)->i_data_sem));
 
 	handle = ext4_journal_start(inode, 1);
+	if (IS_ERR(handle)) {
+		/*
+		 * It is impossible to update on-disk structures without
+		 * a handle, so just rollback in-core changes and live other
+		 * work to orphan_list_cleanup()
+		 */
+		ext4_orphan_del(NULL, tmp_inode);
+		retval = PTR_ERR(handle);
+		goto out;
+	}
 
 	ei = EXT4_I(inode);
 	i_data = ei->i_data;
@@ -618,15 +624,8 @@
 
 	/* Reset the extent details */
 	ext4_ext_tree_init(handle, tmp_inode);
-
-	/*
-	 * Set the i_nlink to zero so that
-	 * generic_drop_inode really deletes the
-	 * inode
-	 */
-	tmp_inode->i_nlink = 0;
-
 	ext4_journal_stop(handle);
+out:
 	unlock_new_inode(tmp_inode);
 	iput(tmp_inode);
 
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 82c415b..aa5fe28 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -152,12 +152,12 @@
 	int ret = 0;
 
 	if (inode1 == NULL) {
-		ext4_error(inode2->i_sb, function,
+		__ext4_error(inode2->i_sb, function,
 			"Both inodes should not be NULL: "
 			"inode1 NULL inode2 %lu", inode2->i_ino);
 		ret = -EIO;
 	} else if (inode2 == NULL) {
-		ext4_error(inode1->i_sb, function,
+		__ext4_error(inode1->i_sb, function,
 			"Both inodes should not be NULL: "
 			"inode1 %lu inode2 NULL", inode1->i_ino);
 		ret = -EIO;
@@ -252,6 +252,7 @@
 		}
 
 		o_start->ee_len = start_ext->ee_len;
+		eblock = le32_to_cpu(start_ext->ee_block);
 		new_flag = 1;
 
 	} else if (start_ext->ee_len && new_ext->ee_len &&
@@ -262,6 +263,7 @@
 		 * orig  |------------------------------|
 		 */
 		o_start->ee_len = start_ext->ee_len;
+		eblock = le32_to_cpu(start_ext->ee_block);
 		new_flag = 1;
 
 	} else if (!start_ext->ee_len && new_ext->ee_len &&
@@ -475,7 +477,6 @@
 	struct ext4_extent *oext, *o_start, *o_end, *prev_ext;
 	struct ext4_extent new_ext, start_ext, end_ext;
 	ext4_lblk_t new_ext_end;
-	ext4_fsblk_t new_phys_end;
 	int oext_alen, new_ext_alen, end_ext_alen;
 	int depth = ext_depth(orig_inode);
 	int ret;
@@ -489,7 +490,6 @@
 	new_ext.ee_len = dext->ee_len;
 	new_ext_alen = ext4_ext_get_actual_len(&new_ext);
 	new_ext_end = le32_to_cpu(new_ext.ee_block) + new_ext_alen - 1;
-	new_phys_end = ext_pblock(&new_ext) + new_ext_alen - 1;
 
 	/*
 	 * Case: original extent is first
@@ -502,6 +502,7 @@
 		le32_to_cpu(oext->ee_block) + oext_alen) {
 		start_ext.ee_len = cpu_to_le16(le32_to_cpu(new_ext.ee_block) -
 					       le32_to_cpu(oext->ee_block));
+		start_ext.ee_block = oext->ee_block;
 		copy_extent_status(oext, &start_ext);
 	} else if (oext > EXT_FIRST_EXTENT(orig_path[depth].p_hdr)) {
 		prev_ext = oext - 1;
@@ -515,6 +516,7 @@
 			start_ext.ee_len = cpu_to_le16(
 				ext4_ext_get_actual_len(prev_ext) +
 				new_ext_alen);
+			start_ext.ee_block = oext->ee_block;
 			copy_extent_status(prev_ext, &start_ext);
 			new_ext.ee_len = 0;
 		}
@@ -526,7 +528,7 @@
 	 * new_ext       |-------|
 	 */
 	if (le32_to_cpu(oext->ee_block) + oext_alen - 1 < new_ext_end) {
-		ext4_error(orig_inode->i_sb, __func__,
+		ext4_error(orig_inode->i_sb,
 			"new_ext_end(%u) should be less than or equal to "
 			"oext->ee_block(%u) + oext_alen(%d) - 1",
 			new_ext_end, le32_to_cpu(oext->ee_block),
@@ -689,12 +691,12 @@
 	while (1) {
 		/* The extent for donor must be found. */
 		if (!dext) {
-			ext4_error(donor_inode->i_sb, __func__,
+			ext4_error(donor_inode->i_sb,
 				   "The extent for donor must be found");
 			*err = -EIO;
 			goto out;
 		} else if (donor_off != le32_to_cpu(tmp_dext.ee_block)) {
-			ext4_error(donor_inode->i_sb, __func__,
+			ext4_error(donor_inode->i_sb,
 				"Donor offset(%u) and the first block of donor "
 				"extent(%u) should be equal",
 				donor_off,
@@ -928,7 +930,7 @@
 }
 
 /**
- * mext_check_argumants - Check whether move extent can be done
+ * mext_check_arguments - Check whether move extent can be done
  *
  * @orig_inode:		original inode
  * @donor_inode:	donor inode
@@ -949,14 +951,6 @@
 	unsigned int blkbits = orig_inode->i_blkbits;
 	unsigned int blocksize = 1 << blkbits;
 
-	/* Regular file check */
-	if (!S_ISREG(orig_inode->i_mode) || !S_ISREG(donor_inode->i_mode)) {
-		ext4_debug("ext4 move extent: The argument files should be "
-			"regular file [ino:orig %lu, donor %lu]\n",
-			orig_inode->i_ino, donor_inode->i_ino);
-		return -EINVAL;
-	}
-
 	if (donor_inode->i_mode & (S_ISUID|S_ISGID)) {
 		ext4_debug("ext4 move extent: suid or sgid is set"
 			   " to donor file [ino:orig %lu, donor %lu]\n",
@@ -1204,6 +1198,14 @@
 		return -EINVAL;
 	}
 
+	/* Regular file check */
+	if (!S_ISREG(orig_inode->i_mode) || !S_ISREG(donor_inode->i_mode)) {
+		ext4_debug("ext4 move extent: The argument files should be "
+			"regular file [ino:orig %lu, donor %lu]\n",
+			orig_inode->i_ino, donor_inode->i_ino);
+		return -EINVAL;
+	}
+
 	/* Protect orig and donor inodes against a truncate */
 	ret1 = mext_inode_double_lock(orig_inode, donor_inode);
 	if (ret1 < 0)
@@ -1351,7 +1353,7 @@
 			if (ret1 < 0)
 				break;
 			if (*moved_len > len) {
-				ext4_error(orig_inode->i_sb, __func__,
+				ext4_error(orig_inode->i_sb,
 					"We replaced blocks too much! "
 					"sum of replaced: %llu requested: %llu",
 					*moved_len, len);
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 17a17e1..0c070fa 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -383,8 +383,7 @@
 	if (root->info.hash_version != DX_HASH_TEA &&
 	    root->info.hash_version != DX_HASH_HALF_MD4 &&
 	    root->info.hash_version != DX_HASH_LEGACY) {
-		ext4_warning(dir->i_sb, __func__,
-			     "Unrecognised inode hash code %d",
+		ext4_warning(dir->i_sb, "Unrecognised inode hash code %d",
 			     root->info.hash_version);
 		brelse(bh);
 		*err = ERR_BAD_DX_DIR;
@@ -399,8 +398,7 @@
 	hash = hinfo->hash;
 
 	if (root->info.unused_flags & 1) {
-		ext4_warning(dir->i_sb, __func__,
-			     "Unimplemented inode hash flags: %#06x",
+		ext4_warning(dir->i_sb, "Unimplemented inode hash flags: %#06x",
 			     root->info.unused_flags);
 		brelse(bh);
 		*err = ERR_BAD_DX_DIR;
@@ -408,8 +406,7 @@
 	}
 
 	if ((indirect = root->info.indirect_levels) > 1) {
-		ext4_warning(dir->i_sb, __func__,
-			     "Unimplemented inode hash depth: %#06x",
+		ext4_warning(dir->i_sb, "Unimplemented inode hash depth: %#06x",
 			     root->info.indirect_levels);
 		brelse(bh);
 		*err = ERR_BAD_DX_DIR;
@@ -421,8 +418,7 @@
 
 	if (dx_get_limit(entries) != dx_root_limit(dir,
 						   root->info.info_length)) {
-		ext4_warning(dir->i_sb, __func__,
-			     "dx entry: limit != root limit");
+		ext4_warning(dir->i_sb, "dx entry: limit != root limit");
 		brelse(bh);
 		*err = ERR_BAD_DX_DIR;
 		goto fail;
@@ -433,7 +429,7 @@
 	{
 		count = dx_get_count(entries);
 		if (!count || count > dx_get_limit(entries)) {
-			ext4_warning(dir->i_sb, __func__,
+			ext4_warning(dir->i_sb,
 				     "dx entry: no count or count > limit");
 			brelse(bh);
 			*err = ERR_BAD_DX_DIR;
@@ -478,7 +474,7 @@
 			goto fail2;
 		at = entries = ((struct dx_node *) bh->b_data)->entries;
 		if (dx_get_limit(entries) != dx_node_limit (dir)) {
-			ext4_warning(dir->i_sb, __func__,
+			ext4_warning(dir->i_sb,
 				     "dx entry: limit != node limit");
 			brelse(bh);
 			*err = ERR_BAD_DX_DIR;
@@ -494,7 +490,7 @@
 	}
 fail:
 	if (*err == ERR_BAD_DX_DIR)
-		ext4_warning(dir->i_sb, __func__,
+		ext4_warning(dir->i_sb,
 			     "Corrupt dir inode %ld, running e2fsck is "
 			     "recommended.", dir->i_ino);
 	return NULL;
@@ -947,9 +943,8 @@
 		wait_on_buffer(bh);
 		if (!buffer_uptodate(bh)) {
 			/* read error, skip block & hope for the best */
-			ext4_error(sb, __func__, "reading directory #%lu "
-				   "offset %lu", dir->i_ino,
-				   (unsigned long)block);
+			ext4_error(sb, "reading directory #%lu offset %lu",
+				   dir->i_ino, (unsigned long)block);
 			brelse(bh);
 			goto next;
 		}
@@ -1041,7 +1036,7 @@
 		retval = ext4_htree_next_block(dir, hash, frame,
 					       frames, NULL);
 		if (retval < 0) {
-			ext4_warning(sb, __func__,
+			ext4_warning(sb,
 			     "error reading index page in directory #%lu",
 			     dir->i_ino);
 			*err = retval;
@@ -1071,14 +1066,13 @@
 		__u32 ino = le32_to_cpu(de->inode);
 		brelse(bh);
 		if (!ext4_valid_inum(dir->i_sb, ino)) {
-			ext4_error(dir->i_sb, "ext4_lookup",
-				   "bad inode number: %u", ino);
+			ext4_error(dir->i_sb, "bad inode number: %u", ino);
 			return ERR_PTR(-EIO);
 		}
 		inode = ext4_iget(dir->i_sb, ino);
 		if (unlikely(IS_ERR(inode))) {
 			if (PTR_ERR(inode) == -ESTALE) {
-				ext4_error(dir->i_sb, __func__,
+				ext4_error(dir->i_sb,
 						"deleted inode referenced: %u",
 						ino);
 				return ERR_PTR(-EIO);
@@ -1110,7 +1104,7 @@
 	brelse(bh);
 
 	if (!ext4_valid_inum(child->d_inode->i_sb, ino)) {
-		ext4_error(child->d_inode->i_sb, "ext4_get_parent",
+		ext4_error(child->d_inode->i_sb,
 			   "bad inode number: %u", ino);
 		return ERR_PTR(-EIO);
 	}
@@ -1410,7 +1404,7 @@
 	de = (struct ext4_dir_entry_2 *)((char *)fde +
 		ext4_rec_len_from_disk(fde->rec_len, blocksize));
 	if ((char *) de >= (((char *) root) + blocksize)) {
-		ext4_error(dir->i_sb, __func__,
+		ext4_error(dir->i_sb,
 			   "invalid rec_len for '..' in inode %lu",
 			   dir->i_ino);
 		brelse(bh);
@@ -1575,8 +1569,7 @@
 
 		if (levels && (dx_get_count(frames->entries) ==
 			       dx_get_limit(frames->entries))) {
-			ext4_warning(sb, __func__,
-				     "Directory index full!");
+			ext4_warning(sb, "Directory index full!");
 			err = -ENOSPC;
 			goto cleanup;
 		}
@@ -1766,6 +1759,8 @@
 	struct inode *inode;
 	int err, retries = 0;
 
+	dquot_initialize(dir);
+
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
@@ -1800,6 +1795,8 @@
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
 
+	dquot_initialize(dir);
+
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
@@ -1837,6 +1834,8 @@
 	if (EXT4_DIR_LINK_MAX(dir))
 		return -EMLINK;
 
+	dquot_initialize(dir);
+
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
@@ -1916,11 +1915,11 @@
 	if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2) ||
 	    !(bh = ext4_bread(NULL, inode, 0, 0, &err))) {
 		if (err)
-			ext4_error(inode->i_sb, __func__,
+			ext4_error(inode->i_sb,
 				   "error %d reading directory #%lu offset 0",
 				   err, inode->i_ino);
 		else
-			ext4_warning(inode->i_sb, __func__,
+			ext4_warning(inode->i_sb,
 				     "bad directory (dir #%lu) - no data block",
 				     inode->i_ino);
 		return 1;
@@ -1931,7 +1930,7 @@
 			!le32_to_cpu(de1->inode) ||
 			strcmp(".", de->name) ||
 			strcmp("..", de1->name)) {
-		ext4_warning(inode->i_sb, "empty_dir",
+		ext4_warning(inode->i_sb,
 			     "bad directory (dir #%lu) - no `.' or `..'",
 			     inode->i_ino);
 		brelse(bh);
@@ -1949,7 +1948,7 @@
 				offset >> EXT4_BLOCK_SIZE_BITS(sb), 0, &err);
 			if (!bh) {
 				if (err)
-					ext4_error(sb, __func__,
+					ext4_error(sb,
 						   "error %d reading directory"
 						   " #%lu offset %u",
 						   err, inode->i_ino, offset);
@@ -2020,11 +2019,18 @@
 	err = ext4_reserve_inode_write(handle, inode, &iloc);
 	if (err)
 		goto out_unlock;
+	/*
+	 * Due to previous errors inode may be already a part of on-disk
+	 * orphan list. If so skip on-disk list modification.
+	 */
+	if (NEXT_ORPHAN(inode) && NEXT_ORPHAN(inode) <=
+		(le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)))
+			goto mem_insert;
 
 	/* Insert this inode at the head of the on-disk orphan list... */
 	NEXT_ORPHAN(inode) = le32_to_cpu(EXT4_SB(sb)->s_es->s_last_orphan);
 	EXT4_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
-	err = ext4_handle_dirty_metadata(handle, inode, EXT4_SB(sb)->s_sbh);
+	err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
 	rc = ext4_mark_iloc_dirty(handle, inode, &iloc);
 	if (!err)
 		err = rc;
@@ -2037,6 +2043,7 @@
 	 *
 	 * This is safe: on error we're going to ignore the orphan list
 	 * anyway on the next recovery. */
+mem_insert:
 	if (!err)
 		list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);
 
@@ -2096,7 +2103,7 @@
 		if (err)
 			goto out_brelse;
 		sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
-		err = ext4_handle_dirty_metadata(handle, inode, sbi->s_sbh);
+		err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh);
 	} else {
 		struct ext4_iloc iloc2;
 		struct inode *i_prev =
@@ -2136,7 +2143,9 @@
 
 	/* Initialize quotas before so that eventual writes go in
 	 * separate transaction */
-	vfs_dq_init(dentry->d_inode);
+	dquot_initialize(dir);
+	dquot_initialize(dentry->d_inode);
+
 	handle = ext4_journal_start(dir, EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
@@ -2163,7 +2172,7 @@
 	if (retval)
 		goto end_rmdir;
 	if (!EXT4_DIR_LINK_EMPTY(inode))
-		ext4_warning(inode->i_sb, "ext4_rmdir",
+		ext4_warning(inode->i_sb,
 			     "empty directory has too many links (%d)",
 			     inode->i_nlink);
 	inode->i_version++;
@@ -2195,7 +2204,9 @@
 
 	/* Initialize quotas before so that eventual writes go
 	 * in separate transaction */
-	vfs_dq_init(dentry->d_inode);
+	dquot_initialize(dir);
+	dquot_initialize(dentry->d_inode);
+
 	handle = ext4_journal_start(dir, EXT4_DELETE_TRANS_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
@@ -2215,7 +2226,7 @@
 		goto end_unlink;
 
 	if (!inode->i_nlink) {
-		ext4_warning(inode->i_sb, "ext4_unlink",
+		ext4_warning(inode->i_sb,
 			     "Deleting nonexistent file (%lu), %d",
 			     inode->i_ino, inode->i_nlink);
 		inode->i_nlink = 1;
@@ -2250,6 +2261,8 @@
 	if (l > dir->i_sb->s_blocksize)
 		return -ENAMETOOLONG;
 
+	dquot_initialize(dir);
+
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 5 +
@@ -2308,6 +2321,8 @@
 	if (inode->i_nlink >= EXT4_LINK_MAX)
 		return -EMLINK;
 
+	dquot_initialize(dir);
+
 	/*
 	 * Return -ENOENT if we've raced with unlink and i_nlink is 0.  Doing
 	 * otherwise has the potential to corrupt the orphan inode list.
@@ -2358,12 +2373,15 @@
 	struct ext4_dir_entry_2 *old_de, *new_de;
 	int retval, force_da_alloc = 0;
 
+	dquot_initialize(old_dir);
+	dquot_initialize(new_dir);
+
 	old_bh = new_bh = dir_bh = NULL;
 
 	/* Initialize quotas before so that eventual writes go
 	 * in separate transaction */
 	if (new_dentry->d_inode)
-		vfs_dq_init(new_dentry->d_inode);
+		dquot_initialize(new_dentry->d_inode);
 	handle = ext4_journal_start(old_dir, 2 *
 					EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS + 2);
@@ -2462,7 +2480,7 @@
 		}
 	}
 	if (retval) {
-		ext4_warning(old_dir->i_sb, "ext4_rename",
+		ext4_warning(old_dir->i_sb,
 				"Deleting old file (%lu), %d, error=%d",
 				old_dir->i_ino, old_dir->i_nlink, retval);
 	}
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 3b2c554..5692c48 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -48,65 +48,54 @@
 
 	ext4_get_group_no_and_offset(sb, start, NULL, &offset);
 	if (group != sbi->s_groups_count)
-		ext4_warning(sb, __func__,
-			     "Cannot add at group %u (only %u groups)",
+		ext4_warning(sb, "Cannot add at group %u (only %u groups)",
 			     input->group, sbi->s_groups_count);
 	else if (offset != 0)
-			ext4_warning(sb, __func__, "Last group not full");
+			ext4_warning(sb, "Last group not full");
 	else if (input->reserved_blocks > input->blocks_count / 5)
-		ext4_warning(sb, __func__, "Reserved blocks too high (%u)",
+		ext4_warning(sb, "Reserved blocks too high (%u)",
 			     input->reserved_blocks);
 	else if (free_blocks_count < 0)
-		ext4_warning(sb, __func__, "Bad blocks count %u",
+		ext4_warning(sb, "Bad blocks count %u",
 			     input->blocks_count);
 	else if (!(bh = sb_bread(sb, end - 1)))
-		ext4_warning(sb, __func__,
-			     "Cannot read last block (%llu)",
+		ext4_warning(sb, "Cannot read last block (%llu)",
 			     end - 1);
 	else if (outside(input->block_bitmap, start, end))
-		ext4_warning(sb, __func__,
-			     "Block bitmap not in group (block %llu)",
+		ext4_warning(sb, "Block bitmap not in group (block %llu)",
 			     (unsigned long long)input->block_bitmap);
 	else if (outside(input->inode_bitmap, start, end))
-		ext4_warning(sb, __func__,
-			     "Inode bitmap not in group (block %llu)",
+		ext4_warning(sb, "Inode bitmap not in group (block %llu)",
 			     (unsigned long long)input->inode_bitmap);
 	else if (outside(input->inode_table, start, end) ||
 		 outside(itend - 1, start, end))
-		ext4_warning(sb, __func__,
-			     "Inode table not in group (blocks %llu-%llu)",
+		ext4_warning(sb, "Inode table not in group (blocks %llu-%llu)",
 			     (unsigned long long)input->inode_table, itend - 1);
 	else if (input->inode_bitmap == input->block_bitmap)
-		ext4_warning(sb, __func__,
-			     "Block bitmap same as inode bitmap (%llu)",
+		ext4_warning(sb, "Block bitmap same as inode bitmap (%llu)",
 			     (unsigned long long)input->block_bitmap);
 	else if (inside(input->block_bitmap, input->inode_table, itend))
-		ext4_warning(sb, __func__,
-			     "Block bitmap (%llu) in inode table (%llu-%llu)",
+		ext4_warning(sb, "Block bitmap (%llu) in inode table "
+			     "(%llu-%llu)",
 			     (unsigned long long)input->block_bitmap,
 			     (unsigned long long)input->inode_table, itend - 1);
 	else if (inside(input->inode_bitmap, input->inode_table, itend))
-		ext4_warning(sb, __func__,
-			     "Inode bitmap (%llu) in inode table (%llu-%llu)",
+		ext4_warning(sb, "Inode bitmap (%llu) in inode table "
+			     "(%llu-%llu)",
 			     (unsigned long long)input->inode_bitmap,
 			     (unsigned long long)input->inode_table, itend - 1);
 	else if (inside(input->block_bitmap, start, metaend))
-		ext4_warning(sb, __func__,
-			     "Block bitmap (%llu) in GDT table"
-			     " (%llu-%llu)",
+		ext4_warning(sb, "Block bitmap (%llu) in GDT table (%llu-%llu)",
 			     (unsigned long long)input->block_bitmap,
 			     start, metaend - 1);
 	else if (inside(input->inode_bitmap, start, metaend))
-		ext4_warning(sb, __func__,
-			     "Inode bitmap (%llu) in GDT table"
-			     " (%llu-%llu)",
+		ext4_warning(sb, "Inode bitmap (%llu) in GDT table (%llu-%llu)",
 			     (unsigned long long)input->inode_bitmap,
 			     start, metaend - 1);
 	else if (inside(input->inode_table, start, metaend) ||
 		 inside(itend - 1, start, metaend))
-		ext4_warning(sb, __func__,
-			     "Inode table (%llu-%llu) overlaps"
-			     "GDT table (%llu-%llu)",
+		ext4_warning(sb, "Inode table (%llu-%llu) overlaps GDT table "
+			     "(%llu-%llu)",
 			     (unsigned long long)input->inode_table,
 			     itend - 1, start, metaend - 1);
 	else
@@ -364,8 +353,7 @@
 	while ((grp = ext4_list_backups(sb, &three, &five, &seven)) < end) {
 		if (le32_to_cpu(*p++) !=
 		    grp * EXT4_BLOCKS_PER_GROUP(sb) + blk){
-			ext4_warning(sb, __func__,
-				     "reserved GDT %llu"
+			ext4_warning(sb, "reserved GDT %llu"
 				     " missing grp %d (%llu)",
 				     blk, grp,
 				     grp *
@@ -420,8 +408,7 @@
          */
 	if (EXT4_SB(sb)->s_sbh->b_blocknr !=
 	    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) {
-		ext4_warning(sb, __func__,
-			"won't resize using backup superblock at %llu",
+		ext4_warning(sb, "won't resize using backup superblock at %llu",
 			(unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr);
 		return -EPERM;
 	}
@@ -444,8 +431,7 @@
 
 	data = (__le32 *)dind->b_data;
 	if (le32_to_cpu(data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)]) != gdblock) {
-		ext4_warning(sb, __func__,
-			     "new group %u GDT block %llu not reserved",
+		ext4_warning(sb, "new group %u GDT block %llu not reserved",
 			     input->group, gdblock);
 		err = -EINVAL;
 		goto exit_dind;
@@ -468,7 +454,7 @@
 			GFP_NOFS);
 	if (!n_group_desc) {
 		err = -ENOMEM;
-		ext4_warning(sb, __func__,
+		ext4_warning(sb,
 			      "not enough memory for %lu groups", gdb_num + 1);
 		goto exit_inode;
 	}
@@ -567,8 +553,7 @@
 	/* Get each reserved primary GDT block and verify it holds backups */
 	for (res = 0; res < reserved_gdb; res++, blk++) {
 		if (le32_to_cpu(*data) != blk) {
-			ext4_warning(sb, __func__,
-				     "reserved block %llu"
+			ext4_warning(sb, "reserved block %llu"
 				     " not at offset %ld",
 				     blk,
 				     (long)(data - (__le32 *)dind->b_data));
@@ -713,8 +698,7 @@
 	 */
 exit_err:
 	if (err) {
-		ext4_warning(sb, __func__,
-			     "can't update backup for group %u (err %d), "
+		ext4_warning(sb, "can't update backup for group %u (err %d), "
 			     "forcing fsck on next reboot", group, err);
 		sbi->s_mount_state &= ~EXT4_VALID_FS;
 		sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
@@ -753,20 +737,19 @@
 
 	if (gdb_off == 0 && !EXT4_HAS_RO_COMPAT_FEATURE(sb,
 					EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
-		ext4_warning(sb, __func__,
-			     "Can't resize non-sparse filesystem further");
+		ext4_warning(sb, "Can't resize non-sparse filesystem further");
 		return -EPERM;
 	}
 
 	if (ext4_blocks_count(es) + input->blocks_count <
 	    ext4_blocks_count(es)) {
-		ext4_warning(sb, __func__, "blocks_count overflow");
+		ext4_warning(sb, "blocks_count overflow");
 		return -EINVAL;
 	}
 
 	if (le32_to_cpu(es->s_inodes_count) + EXT4_INODES_PER_GROUP(sb) <
 	    le32_to_cpu(es->s_inodes_count)) {
-		ext4_warning(sb, __func__, "inodes_count overflow");
+		ext4_warning(sb, "inodes_count overflow");
 		return -EINVAL;
 	}
 
@@ -774,14 +757,13 @@
 		if (!EXT4_HAS_COMPAT_FEATURE(sb,
 					     EXT4_FEATURE_COMPAT_RESIZE_INODE)
 		    || !le16_to_cpu(es->s_reserved_gdt_blocks)) {
-			ext4_warning(sb, __func__,
+			ext4_warning(sb,
 				     "No reserved GDT blocks, can't resize");
 			return -EPERM;
 		}
 		inode = ext4_iget(sb, EXT4_RESIZE_INO);
 		if (IS_ERR(inode)) {
-			ext4_warning(sb, __func__,
-				     "Error opening resize inode");
+			ext4_warning(sb, "Error opening resize inode");
 			return PTR_ERR(inode);
 		}
 	}
@@ -810,8 +792,7 @@
 
 	mutex_lock(&sbi->s_resize_lock);
 	if (input->group != sbi->s_groups_count) {
-		ext4_warning(sb, __func__,
-			     "multiple resizers run on filesystem!");
+		ext4_warning(sb, "multiple resizers run on filesystem!");
 		err = -EBUSY;
 		goto exit_journal;
 	}
@@ -997,13 +978,12 @@
 			" too large to resize to %llu blocks safely\n",
 			sb->s_id, n_blocks_count);
 		if (sizeof(sector_t) < 8)
-			ext4_warning(sb, __func__, "CONFIG_LBDAF not enabled");
+			ext4_warning(sb, "CONFIG_LBDAF not enabled");
 		return -EINVAL;
 	}
 
 	if (n_blocks_count < o_blocks_count) {
-		ext4_warning(sb, __func__,
-			     "can't shrink FS - resize aborted");
+		ext4_warning(sb, "can't shrink FS - resize aborted");
 		return -EBUSY;
 	}
 
@@ -1011,15 +991,14 @@
 	ext4_get_group_no_and_offset(sb, o_blocks_count, &group, &last);
 
 	if (last == 0) {
-		ext4_warning(sb, __func__,
-			     "need to use ext2online to resize further");
+		ext4_warning(sb, "need to use ext2online to resize further");
 		return -EPERM;
 	}
 
 	add = EXT4_BLOCKS_PER_GROUP(sb) - last;
 
 	if (o_blocks_count + add < o_blocks_count) {
-		ext4_warning(sb, __func__, "blocks_count overflow");
+		ext4_warning(sb, "blocks_count overflow");
 		return -EINVAL;
 	}
 
@@ -1027,16 +1006,13 @@
 		add = n_blocks_count - o_blocks_count;
 
 	if (o_blocks_count + add < n_blocks_count)
-		ext4_warning(sb, __func__,
-			     "will only finish group (%llu"
-			     " blocks, %u new)",
+		ext4_warning(sb, "will only finish group (%llu blocks, %u new)",
 			     o_blocks_count + add, add);
 
 	/* See if the device is actually as big as what was requested */
 	bh = sb_bread(sb, o_blocks_count + add - 1);
 	if (!bh) {
-		ext4_warning(sb, __func__,
-			     "can't read last block, resize aborted");
+		ext4_warning(sb, "can't read last block, resize aborted");
 		return -ENOSPC;
 	}
 	brelse(bh);
@@ -1047,14 +1023,13 @@
 	handle = ext4_journal_start_sb(sb, 3);
 	if (IS_ERR(handle)) {
 		err = PTR_ERR(handle);
-		ext4_warning(sb, __func__, "error %d on journal start", err);
+		ext4_warning(sb, "error %d on journal start", err);
 		goto exit_put;
 	}
 
 	mutex_lock(&EXT4_SB(sb)->s_resize_lock);
 	if (o_blocks_count != ext4_blocks_count(es)) {
-		ext4_warning(sb, __func__,
-			     "multiple resizers run on filesystem!");
+		ext4_warning(sb, "multiple resizers run on filesystem!");
 		mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
 		ext4_journal_stop(handle);
 		err = -EBUSY;
@@ -1063,8 +1038,7 @@
 
 	if ((err = ext4_journal_get_write_access(handle,
 						 EXT4_SB(sb)->s_sbh))) {
-		ext4_warning(sb, __func__,
-			     "error %d on journal write access", err);
+		ext4_warning(sb, "error %d on journal write access", err);
 		mutex_unlock(&EXT4_SB(sb)->s_resize_lock);
 		ext4_journal_stop(handle);
 		goto exit_put;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 735c20d..ba191da 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -302,7 +302,7 @@
  * write out the superblock safely.
  *
  * We'll just use the jbd2_journal_abort() error code to record an error in
- * the journal instead.  On recovery, the journal will compain about
+ * the journal instead.  On recovery, the journal will complain about
  * that error until we've noted it down and cleared it.
  */
 
@@ -333,7 +333,7 @@
 			sb->s_id);
 }
 
-void ext4_error(struct super_block *sb, const char *function,
+void __ext4_error(struct super_block *sb, const char *function,
 		const char *fmt, ...)
 {
 	va_list args;
@@ -347,6 +347,42 @@
 	ext4_handle_error(sb);
 }
 
+void ext4_error_inode(const char *function, struct inode *inode,
+		      const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT4-fs error (device %s): %s: inode #%lu: (comm %s) ",
+	       inode->i_sb->s_id, function, inode->i_ino, current->comm);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
+
+	ext4_handle_error(inode->i_sb);
+}
+
+void ext4_error_file(const char *function, struct file *file,
+		     const char *fmt, ...)
+{
+	va_list args;
+	struct inode *inode = file->f_dentry->d_inode;
+	char pathname[80], *path;
+
+	va_start(args, fmt);
+	path = d_path(&(file->f_path), pathname, sizeof(pathname));
+	if (!path)
+		path = "(unknown)";
+	printk(KERN_CRIT
+	       "EXT4-fs error (device %s): %s: inode #%lu (comm %s path %s): ",
+	       inode->i_sb->s_id, function, inode->i_ino, current->comm, path);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
+
+	ext4_handle_error(inode->i_sb);
+}
+
 static const char *ext4_decode_error(struct super_block *sb, int errno,
 				     char nbuf[16])
 {
@@ -450,7 +486,7 @@
 	va_end(args);
 }
 
-void ext4_warning(struct super_block *sb, const char *function,
+void __ext4_warning(struct super_block *sb, const char *function,
 		  const char *fmt, ...)
 {
 	va_list args;
@@ -507,7 +543,7 @@
 	if (le32_to_cpu(es->s_rev_level) > EXT4_GOOD_OLD_REV)
 		return;
 
-	ext4_warning(sb, __func__,
+	ext4_warning(sb,
 		     "updating to rev %d because of new feature flag, "
 		     "running e2fsck is recommended",
 		     EXT4_DYNAMIC_REV);
@@ -708,7 +744,8 @@
 #ifdef CONFIG_QUOTA
 	ei->i_reserved_quota = 0;
 #endif
-	INIT_LIST_HEAD(&ei->i_aio_dio_complete_list);
+	INIT_LIST_HEAD(&ei->i_completed_io_list);
+	spin_lock_init(&ei->i_completed_io_lock);
 	ei->cur_aio_dio = NULL;
 	ei->i_sync_tid = 0;
 	ei->i_datasync_tid = 0;
@@ -761,6 +798,7 @@
 
 static void ext4_clear_inode(struct inode *inode)
 {
+	dquot_drop(inode);
 	ext4_discard_preallocations(inode);
 	if (EXT4_JOURNAL(inode))
 		jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal,
@@ -796,10 +834,10 @@
 	if (sbi->s_qf_names[GRPQUOTA])
 		seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
 
-	if (sbi->s_mount_opt & EXT4_MOUNT_USRQUOTA)
+	if (test_opt(sb, USRQUOTA))
 		seq_puts(seq, ",usrquota");
 
-	if (sbi->s_mount_opt & EXT4_MOUNT_GRPQUOTA)
+	if (test_opt(sb, GRPQUOTA))
 		seq_puts(seq, ",grpquota");
 #endif
 }
@@ -926,6 +964,9 @@
 	if (test_opt(sb, NOLOAD))
 		seq_puts(seq, ",norecovery");
 
+	if (test_opt(sb, DIOREAD_NOLOCK))
+		seq_puts(seq, ",dioread_nolock");
+
 	ext4_show_quota_options(seq, sb);
 
 	return 0;
@@ -1012,19 +1053,9 @@
 				const char *data, size_t len, loff_t off);
 
 static const struct dquot_operations ext4_quota_operations = {
-	.initialize	= dquot_initialize,
-	.drop		= dquot_drop,
-	.alloc_space	= dquot_alloc_space,
-	.reserve_space	= dquot_reserve_space,
-	.claim_space	= dquot_claim_space,
-	.release_rsv	= dquot_release_reserved_space,
 #ifdef CONFIG_QUOTA
 	.get_reserved_space = ext4_get_reserved_space,
 #endif
-	.alloc_inode	= dquot_alloc_inode,
-	.free_space	= dquot_free_space,
-	.free_inode	= dquot_free_inode,
-	.transfer	= dquot_transfer,
 	.write_dquot	= ext4_write_dquot,
 	.acquire_dquot	= ext4_acquire_dquot,
 	.release_dquot	= ext4_release_dquot,
@@ -1109,6 +1140,7 @@
 	Opt_stripe, Opt_delalloc, Opt_nodelalloc,
 	Opt_block_validity, Opt_noblock_validity,
 	Opt_inode_readahead_blks, Opt_journal_ioprio,
+	Opt_dioread_nolock, Opt_dioread_lock,
 	Opt_discard, Opt_nodiscard,
 };
 
@@ -1176,6 +1208,8 @@
 	{Opt_auto_da_alloc, "auto_da_alloc=%u"},
 	{Opt_auto_da_alloc, "auto_da_alloc"},
 	{Opt_noauto_da_alloc, "noauto_da_alloc"},
+	{Opt_dioread_nolock, "dioread_nolock"},
+	{Opt_dioread_lock, "dioread_lock"},
 	{Opt_discard, "discard"},
 	{Opt_nodiscard, "nodiscard"},
 	{Opt_err, NULL},
@@ -1205,6 +1239,66 @@
 }
 
 #define DEFAULT_JOURNAL_IOPRIO (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 3))
+static char deprecated_msg[] = "Mount option \"%s\" will be removed by %s\n"
+	"Contact linux-ext4@vger.kernel.org if you think we should keep it.\n";
+
+#ifdef CONFIG_QUOTA
+static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
+{
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+	char *qname;
+
+	if (sb_any_quota_loaded(sb) &&
+		!sbi->s_qf_names[qtype]) {
+		ext4_msg(sb, KERN_ERR,
+			"Cannot change journaled "
+			"quota options when quota turned on");
+		return 0;
+	}
+	qname = match_strdup(args);
+	if (!qname) {
+		ext4_msg(sb, KERN_ERR,
+			"Not enough memory for storing quotafile name");
+		return 0;
+	}
+	if (sbi->s_qf_names[qtype] &&
+		strcmp(sbi->s_qf_names[qtype], qname)) {
+		ext4_msg(sb, KERN_ERR,
+			"%s quota file already specified", QTYPE2NAME(qtype));
+		kfree(qname);
+		return 0;
+	}
+	sbi->s_qf_names[qtype] = qname;
+	if (strchr(sbi->s_qf_names[qtype], '/')) {
+		ext4_msg(sb, KERN_ERR,
+			"quotafile must be on filesystem root");
+		kfree(sbi->s_qf_names[qtype]);
+		sbi->s_qf_names[qtype] = NULL;
+		return 0;
+	}
+	set_opt(sbi->s_mount_opt, QUOTA);
+	return 1;
+}
+
+static int clear_qf_name(struct super_block *sb, int qtype)
+{
+
+	struct ext4_sb_info *sbi = EXT4_SB(sb);
+
+	if (sb_any_quota_loaded(sb) &&
+		sbi->s_qf_names[qtype]) {
+		ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options"
+			" when quota turned on");
+		return 0;
+	}
+	/*
+	 * The space will be released later when all options are confirmed
+	 * to be correct
+	 */
+	sbi->s_qf_names[qtype] = NULL;
+	return 1;
+}
+#endif
 
 static int parse_options(char *options, struct super_block *sb,
 			 unsigned long *journal_devnum,
@@ -1217,8 +1311,7 @@
 	int data_opt = 0;
 	int option;
 #ifdef CONFIG_QUOTA
-	int qtype, qfmt;
-	char *qname;
+	int qfmt;
 #endif
 
 	if (!options)
@@ -1229,19 +1322,31 @@
 		if (!*p)
 			continue;
 
+		/*
+		 * Initialize args struct so we know whether arg was
+		 * found; some options take optional arguments.
+		 */
+		args[0].to = args[0].from = 0;
 		token = match_token(p, tokens, args);
 		switch (token) {
 		case Opt_bsd_df:
+			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
 			clear_opt(sbi->s_mount_opt, MINIX_DF);
 			break;
 		case Opt_minix_df:
+			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
 			set_opt(sbi->s_mount_opt, MINIX_DF);
+
 			break;
 		case Opt_grpid:
+			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
 			set_opt(sbi->s_mount_opt, GRPID);
+
 			break;
 		case Opt_nogrpid:
+			ext4_msg(sb, KERN_WARNING, deprecated_msg, p, "2.6.38");
 			clear_opt(sbi->s_mount_opt, GRPID);
+
 			break;
 		case Opt_resuid:
 			if (match_int(&args[0], &option))
@@ -1378,14 +1483,13 @@
 			data_opt = EXT4_MOUNT_WRITEBACK_DATA;
 		datacheck:
 			if (is_remount) {
-				if ((sbi->s_mount_opt & EXT4_MOUNT_DATA_FLAGS)
-						!= data_opt) {
+				if (test_opt(sb, DATA_FLAGS) != data_opt) {
 					ext4_msg(sb, KERN_ERR,
 						"Cannot change data mode on remount");
 					return 0;
 				}
 			} else {
-				sbi->s_mount_opt &= ~EXT4_MOUNT_DATA_FLAGS;
+				clear_opt(sbi->s_mount_opt, DATA_FLAGS);
 				sbi->s_mount_opt |= data_opt;
 			}
 			break;
@@ -1397,63 +1501,22 @@
 			break;
 #ifdef CONFIG_QUOTA
 		case Opt_usrjquota:
-			qtype = USRQUOTA;
-			goto set_qf_name;
+			if (!set_qf_name(sb, USRQUOTA, &args[0]))
+				return 0;
+			break;
 		case Opt_grpjquota:
-			qtype = GRPQUOTA;
-set_qf_name:
-			if (sb_any_quota_loaded(sb) &&
-			    !sbi->s_qf_names[qtype]) {
-				ext4_msg(sb, KERN_ERR,
-				       "Cannot change journaled "
-				       "quota options when quota turned on");
+			if (!set_qf_name(sb, GRPQUOTA, &args[0]))
 				return 0;
-			}
-			qname = match_strdup(&args[0]);
-			if (!qname) {
-				ext4_msg(sb, KERN_ERR,
-					"Not enough memory for "
-					"storing quotafile name");
-				return 0;
-			}
-			if (sbi->s_qf_names[qtype] &&
-			    strcmp(sbi->s_qf_names[qtype], qname)) {
-				ext4_msg(sb, KERN_ERR,
-					"%s quota file already "
-					"specified", QTYPE2NAME(qtype));
-				kfree(qname);
-				return 0;
-			}
-			sbi->s_qf_names[qtype] = qname;
-			if (strchr(sbi->s_qf_names[qtype], '/')) {
-				ext4_msg(sb, KERN_ERR,
-					"quotafile must be on "
-					"filesystem root");
-				kfree(sbi->s_qf_names[qtype]);
-				sbi->s_qf_names[qtype] = NULL;
-				return 0;
-			}
-			set_opt(sbi->s_mount_opt, QUOTA);
 			break;
 		case Opt_offusrjquota:
-			qtype = USRQUOTA;
-			goto clear_qf_name;
-		case Opt_offgrpjquota:
-			qtype = GRPQUOTA;
-clear_qf_name:
-			if (sb_any_quota_loaded(sb) &&
-			    sbi->s_qf_names[qtype]) {
-				ext4_msg(sb, KERN_ERR, "Cannot change "
-					"journaled quota options when "
-					"quota turned on");
+			if (!clear_qf_name(sb, USRQUOTA))
 				return 0;
-			}
-			/*
-			 * The space will be released later when all options
-			 * are confirmed to be correct
-			 */
-			sbi->s_qf_names[qtype] = NULL;
 			break;
+		case Opt_offgrpjquota:
+			if (!clear_qf_name(sb, GRPQUOTA))
+				return 0;
+			break;
+
 		case Opt_jqfmt_vfsold:
 			qfmt = QFMT_VFS_OLD;
 			goto set_qf_format;
@@ -1518,10 +1581,11 @@
 			clear_opt(sbi->s_mount_opt, BARRIER);
 			break;
 		case Opt_barrier:
-			if (match_int(&args[0], &option)) {
-				set_opt(sbi->s_mount_opt, BARRIER);
-				break;
-			}
+			if (args[0].from) {
+				if (match_int(&args[0], &option))
+					return 0;
+			} else
+				option = 1;	/* No argument, default to 1 */
 			if (option)
 				set_opt(sbi->s_mount_opt, BARRIER);
 			else
@@ -1594,10 +1658,11 @@
 			set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC);
 			break;
 		case Opt_auto_da_alloc:
-			if (match_int(&args[0], &option)) {
-				clear_opt(sbi->s_mount_opt, NO_AUTO_DA_ALLOC);
-				break;
-			}
+			if (args[0].from) {
+				if (match_int(&args[0], &option))
+					return 0;
+			} else
+				option = 1;	/* No argument, default to 1 */
 			if (option)
 				clear_opt(sbi->s_mount_opt, NO_AUTO_DA_ALLOC);
 			else
@@ -1609,6 +1674,12 @@
 		case Opt_nodiscard:
 			clear_opt(sbi->s_mount_opt, DISCARD);
 			break;
+		case Opt_dioread_nolock:
+			set_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
+			break;
+		case Opt_dioread_lock:
+			clear_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
+			break;
 		default:
 			ext4_msg(sb, KERN_ERR,
 			       "Unrecognized mount option \"%s\" "
@@ -1618,18 +1689,13 @@
 	}
 #ifdef CONFIG_QUOTA
 	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
-		if ((sbi->s_mount_opt & EXT4_MOUNT_USRQUOTA) &&
-		     sbi->s_qf_names[USRQUOTA])
+		if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA])
 			clear_opt(sbi->s_mount_opt, USRQUOTA);
 
-		if ((sbi->s_mount_opt & EXT4_MOUNT_GRPQUOTA) &&
-		     sbi->s_qf_names[GRPQUOTA])
+		if (test_opt(sb, GRPQUOTA) && sbi->s_qf_names[GRPQUOTA])
 			clear_opt(sbi->s_mount_opt, GRPQUOTA);
 
-		if ((sbi->s_qf_names[USRQUOTA] &&
-				(sbi->s_mount_opt & EXT4_MOUNT_GRPQUOTA)) ||
-		    (sbi->s_qf_names[GRPQUOTA] &&
-				(sbi->s_mount_opt & EXT4_MOUNT_USRQUOTA))) {
+		if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) {
 			ext4_msg(sb, KERN_ERR, "old and new quota "
 					"format mixing");
 			return 0;
@@ -1939,7 +2005,7 @@
 		}
 
 		list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);
-		vfs_dq_init(inode);
+		dquot_initialize(inode);
 		if (inode->i_nlink) {
 			ext4_msg(sb, KERN_DEBUG,
 				"%s: truncating inode %lu to %lld bytes",
@@ -2292,7 +2358,7 @@
 }
 
 
-static struct sysfs_ops ext4_attr_ops = {
+static const struct sysfs_ops ext4_attr_ops = {
 	.show	= ext4_attr_show,
 	.store	= ext4_attr_store,
 };
@@ -2432,8 +2498,11 @@
 	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
 	if (def_mount_opts & EXT4_DEFM_DEBUG)
 		set_opt(sbi->s_mount_opt, DEBUG);
-	if (def_mount_opts & EXT4_DEFM_BSDGROUPS)
+	if (def_mount_opts & EXT4_DEFM_BSDGROUPS) {
+		ext4_msg(sb, KERN_WARNING, deprecated_msg, "bsdgroups",
+			"2.6.38");
 		set_opt(sbi->s_mount_opt, GRPID);
+	}
 	if (def_mount_opts & EXT4_DEFM_UID16)
 		set_opt(sbi->s_mount_opt, NO_UID32);
 #ifdef CONFIG_EXT4_FS_XATTR
@@ -2445,11 +2514,11 @@
 		set_opt(sbi->s_mount_opt, POSIX_ACL);
 #endif
 	if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
-		sbi->s_mount_opt |= EXT4_MOUNT_JOURNAL_DATA;
+		set_opt(sbi->s_mount_opt, JOURNAL_DATA);
 	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)
-		sbi->s_mount_opt |= EXT4_MOUNT_ORDERED_DATA;
+		set_opt(sbi->s_mount_opt, ORDERED_DATA);
 	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_WBACK)
-		sbi->s_mount_opt |= EXT4_MOUNT_WRITEBACK_DATA;
+		set_opt(sbi->s_mount_opt, WRITEBACK_DATA);
 
 	if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC)
 		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
@@ -2477,7 +2546,7 @@
 		goto failed_mount;
 
 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
-		((sbi->s_mount_opt & EXT4_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);
 
 	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV &&
 	    (EXT4_HAS_COMPAT_FEATURE(sb, ~0U) ||
@@ -2766,7 +2835,7 @@
 	      EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
 		ext4_msg(sb, KERN_ERR, "required journal recovery "
 		       "suppressed and not mounted read-only");
-		goto failed_mount4;
+		goto failed_mount_wq;
 	} else {
 		clear_opt(sbi->s_mount_opt, DATA_FLAGS);
 		set_opt(sbi->s_mount_opt, WRITEBACK_DATA);
@@ -2779,7 +2848,7 @@
 	    !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0,
 				       JBD2_FEATURE_INCOMPAT_64BIT)) {
 		ext4_msg(sb, KERN_ERR, "Failed to set 64-bit journal feature");
-		goto failed_mount4;
+		goto failed_mount_wq;
 	}
 
 	if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
@@ -2818,7 +2887,7 @@
 		    (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) {
 			ext4_msg(sb, KERN_ERR, "Journal does not support "
 			       "requested data journaling mode");
-			goto failed_mount4;
+			goto failed_mount_wq;
 		}
 	default:
 		break;
@@ -2826,13 +2895,17 @@
 	set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
 
 no_journal:
-
 	if (test_opt(sb, NOBH)) {
 		if (!(test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)) {
 			ext4_msg(sb, KERN_WARNING, "Ignoring nobh option - "
 				"its supported only with writeback mode");
 			clear_opt(sbi->s_mount_opt, NOBH);
 		}
+		if (test_opt(sb, DIOREAD_NOLOCK)) {
+			ext4_msg(sb, KERN_WARNING, "dioread_nolock option is "
+				"not supported with nobh mode");
+			goto failed_mount_wq;
+		}
 	}
 	EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten");
 	if (!EXT4_SB(sb)->dio_unwritten_wq) {
@@ -2897,6 +2970,18 @@
 			 "requested data journaling mode");
 		clear_opt(sbi->s_mount_opt, DELALLOC);
 	}
+	if (test_opt(sb, DIOREAD_NOLOCK)) {
+		if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+			ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
+				"option - requested data journaling mode");
+			clear_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
+		}
+		if (sb->s_blocksize < PAGE_SIZE) {
+			ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
+				"option - block size is too small");
+			clear_opt(sbi->s_mount_opt, DIOREAD_NOLOCK);
+		}
+	}
 
 	err = ext4_setup_system_zone(sb);
 	if (err) {
@@ -3360,10 +3445,9 @@
 		char nbuf[16];
 
 		errstr = ext4_decode_error(sb, j_errno, nbuf);
-		ext4_warning(sb, __func__, "Filesystem error recorded "
+		ext4_warning(sb, "Filesystem error recorded "
 			     "from previous mount: %s", errstr);
-		ext4_warning(sb, __func__, "Marking fs in need of "
-			     "filesystem check.");
+		ext4_warning(sb, "Marking fs in need of filesystem check.");
 
 		EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
 		es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
@@ -3514,7 +3598,7 @@
 		ext4_abort(sb, __func__, "Abort forced by user");
 
 	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
-		((sbi->s_mount_opt & EXT4_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);
 
 	es = sbi->s_es;
 
@@ -3708,7 +3792,7 @@
  * Process 1                         Process 2
  * ext4_create()                     quota_sync()
  *   jbd2_journal_start()                  write_dquot()
- *   vfs_dq_init()                         down(dqio_mutex)
+ *   dquot_initialize()                         down(dqio_mutex)
  *     down(dqio_mutex)                    jbd2_journal_start()
  *
  */
@@ -3917,9 +4001,7 @@
 	ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
 	int err = 0;
 	int offset = off & (sb->s_blocksize - 1);
-	int tocopy;
 	int journal_quota = EXT4_SB(sb)->s_qf_names[type] != NULL;
-	size_t towrite = len;
 	struct buffer_head *bh;
 	handle_t *handle = journal_current_handle();
 
@@ -3929,52 +4011,53 @@
 			(unsigned long long)off, (unsigned long long)len);
 		return -EIO;
 	}
-	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
-	while (towrite > 0) {
-		tocopy = sb->s_blocksize - offset < towrite ?
-				sb->s_blocksize - offset : towrite;
-		bh = ext4_bread(handle, inode, blk, 1, &err);
-		if (!bh)
-			goto out;
-		if (journal_quota) {
-			err = ext4_journal_get_write_access(handle, bh);
-			if (err) {
-				brelse(bh);
-				goto out;
-			}
-		}
-		lock_buffer(bh);
-		memcpy(bh->b_data+offset, data, tocopy);
-		flush_dcache_page(bh->b_page);
-		unlock_buffer(bh);
-		if (journal_quota)
-			err = ext4_handle_dirty_metadata(handle, NULL, bh);
-		else {
-			/* Always do at least ordered writes for quotas */
-			err = ext4_jbd2_file_inode(handle, inode);
-			mark_buffer_dirty(bh);
-		}
-		brelse(bh);
-		if (err)
-			goto out;
-		offset = 0;
-		towrite -= tocopy;
-		data += tocopy;
-		blk++;
+	/*
+	 * Since we account only one data block in transaction credits,
+	 * then it is impossible to cross a block boundary.
+	 */
+	if (sb->s_blocksize - offset < len) {
+		ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)"
+			" cancelled because not block aligned",
+			(unsigned long long)off, (unsigned long long)len);
+		return -EIO;
 	}
+
+	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
+	bh = ext4_bread(handle, inode, blk, 1, &err);
+	if (!bh)
+		goto out;
+	if (journal_quota) {
+		err = ext4_journal_get_write_access(handle, bh);
+		if (err) {
+			brelse(bh);
+			goto out;
+		}
+	}
+	lock_buffer(bh);
+	memcpy(bh->b_data+offset, data, len);
+	flush_dcache_page(bh->b_page);
+	unlock_buffer(bh);
+	if (journal_quota)
+		err = ext4_handle_dirty_metadata(handle, NULL, bh);
+	else {
+		/* Always do at least ordered writes for quotas */
+		err = ext4_jbd2_file_inode(handle, inode);
+		mark_buffer_dirty(bh);
+	}
+	brelse(bh);
 out:
-	if (len == towrite) {
+	if (err) {
 		mutex_unlock(&inode->i_mutex);
 		return err;
 	}
-	if (inode->i_size < off+len-towrite) {
-		i_size_write(inode, off+len-towrite);
+	if (inode->i_size < off + len) {
+		i_size_write(inode, off + len);
 		EXT4_I(inode)->i_disksize = inode->i_size;
 	}
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 	ext4_mark_inode_dirty(handle, inode);
 	mutex_unlock(&inode->i_mutex);
-	return len - towrite;
+	return len;
 }
 
 #endif
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index f3a2f7e..b4c5aa8 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -227,7 +227,8 @@
 	ea_bdebug(bh, "b_count=%d, refcount=%d",
 		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
 	if (ext4_xattr_check_block(bh)) {
-bad_block:	ext4_error(inode->i_sb, __func__,
+bad_block:
+		ext4_error(inode->i_sb,
 			   "inode %lu: bad block %llu", inode->i_ino,
 			   EXT4_I(inode)->i_file_acl);
 		error = -EIO;
@@ -267,7 +268,7 @@
 	void *end;
 	int error;
 
-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR))
+	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
 		return -ENODATA;
 	error = ext4_get_inode_loc(inode, &iloc);
 	if (error)
@@ -371,7 +372,7 @@
 	ea_bdebug(bh, "b_count=%d, refcount=%d",
 		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
 	if (ext4_xattr_check_block(bh)) {
-		ext4_error(inode->i_sb, __func__,
+		ext4_error(inode->i_sb,
 			   "inode %lu: bad block %llu", inode->i_ino,
 			   EXT4_I(inode)->i_file_acl);
 		error = -EIO;
@@ -396,7 +397,7 @@
 	void *end;
 	int error;
 
-	if (!(EXT4_I(inode)->i_state & EXT4_STATE_XATTR))
+	if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
 		return 0;
 	error = ext4_get_inode_loc(inode, &iloc);
 	if (error)
@@ -494,7 +495,7 @@
 		error = ext4_handle_dirty_metadata(handle, inode, bh);
 		if (IS_SYNC(inode))
 			ext4_handle_sync(handle);
-		vfs_dq_free_block(inode, 1);
+		dquot_free_block(inode, 1);
 		ea_bdebug(bh, "refcount now=%d; releasing",
 			  le32_to_cpu(BHDR(bh)->h_refcount));
 		if (ce)
@@ -665,9 +666,8 @@
 			atomic_read(&(bs->bh->b_count)),
 			le32_to_cpu(BHDR(bs->bh)->h_refcount));
 		if (ext4_xattr_check_block(bs->bh)) {
-			ext4_error(sb, __func__,
-				"inode %lu: bad block %llu", inode->i_ino,
-				EXT4_I(inode)->i_file_acl);
+			ext4_error(sb, "inode %lu: bad block %llu",
+				   inode->i_ino, EXT4_I(inode)->i_file_acl);
 			error = -EIO;
 			goto cleanup;
 		}
@@ -787,8 +787,8 @@
 			else {
 				/* The old block is released after updating
 				   the inode. */
-				error = -EDQUOT;
-				if (vfs_dq_alloc_block(inode, 1))
+				error = dquot_alloc_block(inode, 1);
+				if (error)
 					goto cleanup;
 				error = ext4_journal_get_write_access(handle,
 								      new_bh);
@@ -876,13 +876,12 @@
 	return error;
 
 cleanup_dquot:
-	vfs_dq_free_block(inode, 1);
+	dquot_free_block(inode, 1);
 	goto cleanup;
 
 bad_block:
-	ext4_error(inode->i_sb, __func__,
-		   "inode %lu: bad block %llu", inode->i_ino,
-		   EXT4_I(inode)->i_file_acl);
+	ext4_error(inode->i_sb, "inode %lu: bad block %llu",
+		   inode->i_ino, EXT4_I(inode)->i_file_acl);
 	goto cleanup;
 
 #undef header
@@ -908,7 +907,7 @@
 	is->s.base = is->s.first = IFIRST(header);
 	is->s.here = is->s.first;
 	is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
-	if (EXT4_I(inode)->i_state & EXT4_STATE_XATTR) {
+	if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
 		error = ext4_xattr_check_names(IFIRST(header), is->s.end);
 		if (error)
 			return error;
@@ -940,10 +939,10 @@
 	header = IHDR(inode, ext4_raw_inode(&is->iloc));
 	if (!IS_LAST_ENTRY(s->first)) {
 		header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC);
-		EXT4_I(inode)->i_state |= EXT4_STATE_XATTR;
+		ext4_set_inode_state(inode, EXT4_STATE_XATTR);
 	} else {
 		header->h_magic = cpu_to_le32(0);
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_XATTR;
+		ext4_clear_inode_state(inode, EXT4_STATE_XATTR);
 	}
 	return 0;
 }
@@ -986,8 +985,8 @@
 	if (strlen(name) > 255)
 		return -ERANGE;
 	down_write(&EXT4_I(inode)->xattr_sem);
-	no_expand = EXT4_I(inode)->i_state & EXT4_STATE_NO_EXPAND;
-	EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
+	no_expand = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND);
+	ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
 
 	error = ext4_get_inode_loc(inode, &is.iloc);
 	if (error)
@@ -997,10 +996,10 @@
 	if (error)
 		goto cleanup;
 
-	if (EXT4_I(inode)->i_state & EXT4_STATE_NEW) {
+	if (ext4_test_inode_state(inode, EXT4_STATE_NEW)) {
 		struct ext4_inode *raw_inode = ext4_raw_inode(&is.iloc);
 		memset(raw_inode, 0, EXT4_SB(inode->i_sb)->s_inode_size);
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_NEW;
+		ext4_clear_inode_state(inode, EXT4_STATE_NEW);
 	}
 
 	error = ext4_xattr_ibody_find(inode, &i, &is);
@@ -1052,7 +1051,7 @@
 		ext4_xattr_update_super_block(handle, inode->i_sb);
 		inode->i_ctime = ext4_current_time(inode);
 		if (!value)
-			EXT4_I(inode)->i_state &= ~EXT4_STATE_NO_EXPAND;
+			ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
 		error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
 		/*
 		 * The bh is consumed by ext4_mark_iloc_dirty, even with
@@ -1067,7 +1066,7 @@
 	brelse(is.iloc.bh);
 	brelse(bs.bh);
 	if (no_expand == 0)
-		EXT4_I(inode)->i_state &= ~EXT4_STATE_NO_EXPAND;
+		ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
 	up_write(&EXT4_I(inode)->xattr_sem);
 	return error;
 }
@@ -1195,9 +1194,8 @@
 		if (!bh)
 			goto cleanup;
 		if (ext4_xattr_check_block(bh)) {
-			ext4_error(inode->i_sb, __func__,
-				"inode %lu: bad block %llu", inode->i_ino,
-				EXT4_I(inode)->i_file_acl);
+			ext4_error(inode->i_sb, "inode %lu: bad block %llu",
+				   inode->i_ino, EXT4_I(inode)->i_file_acl);
 			error = -EIO;
 			goto cleanup;
 		}
@@ -1302,6 +1300,8 @@
 
 		/* Remove the chosen entry from the inode */
 		error = ext4_xattr_ibody_set(handle, inode, &i, is);
+		if (error)
+			goto cleanup;
 
 		entry = IFIRST(header);
 		if (entry_size + EXT4_XATTR_SIZE(size) >= new_extra_isize)
@@ -1372,16 +1372,14 @@
 		goto cleanup;
 	bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
 	if (!bh) {
-		ext4_error(inode->i_sb, __func__,
-			"inode %lu: block %llu read error", inode->i_ino,
-			EXT4_I(inode)->i_file_acl);
+		ext4_error(inode->i_sb, "inode %lu: block %llu read error",
+			   inode->i_ino, EXT4_I(inode)->i_file_acl);
 		goto cleanup;
 	}
 	if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
 	    BHDR(bh)->h_blocks != cpu_to_le32(1)) {
-		ext4_error(inode->i_sb, __func__,
-			"inode %lu: bad block %llu", inode->i_ino,
-			EXT4_I(inode)->i_file_acl);
+		ext4_error(inode->i_sb, "inode %lu: bad block %llu",
+			   inode->i_ino, EXT4_I(inode)->i_file_acl);
 		goto cleanup;
 	}
 	ext4_xattr_release_block(handle, inode, bh);
@@ -1506,7 +1504,7 @@
 		}
 		bh = sb_bread(inode->i_sb, ce->e_block);
 		if (!bh) {
-			ext4_error(inode->i_sb, __func__,
+			ext4_error(inode->i_sb,
 				"inode %lu: block %lu read error",
 				inode->i_ino, (unsigned long) ce->e_block);
 		} else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 14da530..0ce143b 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -558,7 +558,7 @@
 	buf->f_bavail = sbi->free_clusters;
 	buf->f_fsid.val[0] = (u32)id;
 	buf->f_fsid.val[1] = (u32)(id >> 32);
-	buf->f_namelen = sbi->options.isvfat ? 260 : 12;
+	buf->f_namelen = sbi->options.isvfat ? FAT_LFN_LEN : 12;
 
 	return 0;
 }
@@ -577,7 +577,7 @@
 	return i_pos;
 }
 
-static int fat_write_inode(struct inode *inode, int wait)
+static int __fat_write_inode(struct inode *inode, int wait)
 {
 	struct super_block *sb = inode->i_sb;
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
@@ -634,9 +634,14 @@
 	return err;
 }
 
+static int fat_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+	return __fat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+}
+
 int fat_sync_inode(struct inode *inode)
 {
-	return fat_write_inode(inode, 1);
+	return __fat_write_inode(inode, 1);
 }
 
 EXPORT_SYMBOL_GPL(fat_sync_inode);
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index f565f24..c1ef501 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -502,14 +502,14 @@
 		*outlen = utf8s_to_utf16s(name, len, (wchar_t *)outname);
 		if (*outlen < 0)
 			return *outlen;
-		else if (*outlen > 255)
+		else if (*outlen > FAT_LFN_LEN)
 			return -ENAMETOOLONG;
 
 		op = &outname[*outlen * sizeof(wchar_t)];
 	} else {
 		if (nls) {
 			for (i = 0, ip = name, op = outname, *outlen = 0;
-			     i < len && *outlen <= 255;
+			     i < len && *outlen <= FAT_LFN_LEN;
 			     *outlen += 1)
 			{
 				if (escape && (*ip == ':')) {
@@ -549,7 +549,7 @@
 				return -ENAMETOOLONG;
 		} else {
 			for (i = 0, ip = name, op = outname, *outlen = 0;
-			     i < len && *outlen <= 255;
+			     i < len && *outlen <= FAT_LFN_LEN;
 			     i++, *outlen += 1)
 			{
 				*op++ = *ip++;
@@ -701,6 +701,15 @@
 	return fat_search_long(dir, qname->name, len, sinfo);
 }
 
+/*
+ * (nfsd's) anonymous disconnected dentry?
+ * NOTE: !IS_ROOT() is not anonymous (I.e. d_splice_alias() did the job).
+ */
+static int vfat_d_anon_disconn(struct dentry *dentry)
+{
+	return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED);
+}
+
 static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
 				  struct nameidata *nd)
 {
@@ -729,11 +738,11 @@
 	}
 
 	alias = d_find_alias(inode);
-	if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
+	if (alias && !vfat_d_anon_disconn(alias)) {
 		/*
-		 * This inode has non DCACHE_DISCONNECTED dentry. This
-		 * means, the user did ->lookup() by an another name
-		 * (longname vs 8.3 alias of it) in past.
+		 * This inode has non anonymous-DCACHE_DISCONNECTED
+		 * dentry. This means, the user did ->lookup() by an
+		 * another name (longname vs 8.3 alias of it) in past.
 		 *
 		 * Switch to new one for reason of locality if possible.
 		 */
@@ -743,7 +752,9 @@
 		iput(inode);
 		unlock_super(sb);
 		return alias;
-	}
+	} else
+		dput(alias);
+
 out:
 	unlock_super(sb);
 	dentry->d_op = sb->s_root->d_op;
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 97e01dc..452d02f 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -344,7 +344,7 @@
 	switch (cmd) {
 	case F_DUPFD:
 	case F_DUPFD_CLOEXEC:
-		if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
+		if (arg >= rlimit(RLIMIT_NOFILE))
 			break;
 		err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0);
 		if (err >= 0) {
diff --git a/fs/file.c b/fs/file.c
index 38039af..34bb7f7 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -257,7 +257,7 @@
 	 * N.B. For clone tasks sharing a files structure, this test
 	 * will limit the total number of files that can be opened.
 	 */
-	if (nr >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
+	if (nr >= rlimit(RLIMIT_NOFILE))
 		return -EMFILE;
 
 	/* Do we need to expand? */
diff --git a/fs/file_table.c b/fs/file_table.c
index b98404b..32d12b7 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -393,7 +393,9 @@
 			continue;
 		if (!(f->f_mode & FMODE_WRITE))
 			continue;
+		spin_lock(&f->f_lock);
 		f->f_mode &= ~FMODE_WRITE;
+		spin_unlock(&f->f_lock);
 		if (file_check_writeable(f) != 0)
 			continue;
 		file_release_write(f);
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 1a7c42c..76fc4d5 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -381,10 +381,10 @@
 	move_expired_inodes(&wb->b_dirty, &wb->b_io, older_than_this);
 }
 
-static int write_inode(struct inode *inode, int sync)
+static int write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	if (inode->i_sb->s_op->write_inode && !is_bad_inode(inode))
-		return inode->i_sb->s_op->write_inode(inode, sync);
+		return inode->i_sb->s_op->write_inode(inode, wbc);
 	return 0;
 }
 
@@ -421,7 +421,6 @@
 writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	struct address_space *mapping = inode->i_mapping;
-	int wait = wbc->sync_mode == WB_SYNC_ALL;
 	unsigned dirty;
 	int ret;
 
@@ -439,7 +438,7 @@
 		 * We'll have another go at writing back this inode when we
 		 * completed a full scan of b_io.
 		 */
-		if (!wait) {
+		if (wbc->sync_mode != WB_SYNC_ALL) {
 			requeue_io(inode);
 			return 0;
 		}
@@ -461,15 +460,20 @@
 
 	ret = do_writepages(mapping, wbc);
 
-	/* Don't write the inode if only I_DIRTY_PAGES was set */
-	if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
-		int err = write_inode(inode, wait);
+	/*
+	 * Make sure to wait on the data before writing out the metadata.
+	 * This is important for filesystems that modify metadata on data
+	 * I/O completion.
+	 */
+	if (wbc->sync_mode == WB_SYNC_ALL) {
+		int err = filemap_fdatawait(mapping);
 		if (ret == 0)
 			ret = err;
 	}
 
-	if (wait) {
-		int err = filemap_fdatawait(mapping);
+	/* Don't write the inode if only I_DIRTY_PAGES was set */
+	if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
+		int err = write_inode(inode, wbc);
 		if (ret == 0)
 			ret = err;
 	}
diff --git a/fs/fscache/Kconfig b/fs/fscache/Kconfig
index 864dac2..cc94bb9 100644
--- a/fs/fscache/Kconfig
+++ b/fs/fscache/Kconfig
@@ -1,7 +1,6 @@
 
 config FSCACHE
 	tristate "General filesystem local caching manager"
-	depends on EXPERIMENTAL
 	select SLOW_WORK
 	help
 	  This option enables a generic filesystem caching manager that can be
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 51d9e33..eb7e942 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -865,13 +865,10 @@
 
 	down_read(&fc->killsb);
 	err = -ENOENT;
-	if (!fc->sb)
-		goto err_unlock;
-
-	err = fuse_reverse_inval_inode(fc->sb, outarg.ino,
-				       outarg.off, outarg.len);
-
-err_unlock:
+	if (fc->sb) {
+		err = fuse_reverse_inval_inode(fc->sb, outarg.ino,
+					       outarg.off, outarg.len);
+	}
 	up_read(&fc->killsb);
 	return err;
 
@@ -884,10 +881,15 @@
 				   struct fuse_copy_state *cs)
 {
 	struct fuse_notify_inval_entry_out outarg;
-	int err = -EINVAL;
-	char buf[FUSE_NAME_MAX+1];
+	int err = -ENOMEM;
+	char *buf;
 	struct qstr name;
 
+	buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL);
+	if (!buf)
+		goto err;
+
+	err = -EINVAL;
 	if (size < sizeof(outarg))
 		goto err;
 
@@ -910,16 +912,14 @@
 
 	down_read(&fc->killsb);
 	err = -ENOENT;
-	if (!fc->sb)
-		goto err_unlock;
-
-	err = fuse_reverse_inval_entry(fc->sb, outarg.parent, &name);
-
-err_unlock:
+	if (fc->sb)
+		err = fuse_reverse_inval_entry(fc->sb, outarg.parent, &name);
 	up_read(&fc->killsb);
+	kfree(buf);
 	return err;
 
 err:
+	kfree(buf);
 	fuse_copy_finish(cs);
 	return err;
 }
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 1a822ce..ec14d19 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -850,7 +850,7 @@
 	req->in.args[0].size = sizeof(*arg);
 	req->in.args[0].value = arg;
 	req->out.numargs = 1;
-	/* Variable length arguement used for backward compatibility
+	/* Variable length argument used for backward compatibility
 	   with interface version < 7.5.  Rest of init_out is zeroed
 	   by do_get_request(), so a short reply is not a problem */
 	req->out.argvar = 1;
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index 4dcddf8..a47b431 100644
--- a/fs/gfs2/Kconfig
+++ b/fs/gfs2/Kconfig
@@ -8,7 +8,6 @@
 	select FS_POSIX_ACL
 	select CRC32
 	select SLOW_WORK
-	select QUOTA
 	select QUOTACTL
 	help
 	  A cluster filesystem.
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 7b8da94..0c1d0b8 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -1061,8 +1061,8 @@
 
 int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
 {
-	struct inode *aspace = page->mapping->host;
-	struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info;
+	struct address_space *mapping = page->mapping;
+	struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
 	struct buffer_head *bh, *head;
 	struct gfs2_bufdata *bd;
 
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index a6abbae8..e6dd2ae 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -640,7 +640,7 @@
 
 	if (!(fl->fl_flags & FL_POSIX))
 		return -ENOLCK;
-	if (__mandatory_lock(&ip->i_inode))
+	if (__mandatory_lock(&ip->i_inode) && fl->fl_type != F_UNLCK)
 		return -ENOLCK;
 
 	if (cmd == F_CANCELLK) {
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index f426633..454d4b4 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -19,7 +19,6 @@
 #include <linux/list.h>
 #include <linux/wait.h>
 #include <linux/module.h>
-#include <linux/rwsem.h>
 #include <asm/uaccess.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
@@ -60,7 +59,6 @@
 #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0)
 static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target);
 
-static DECLARE_RWSEM(gfs2_umount_flush_sem);
 static struct dentry *gfs2_root;
 static struct workqueue_struct *glock_workqueue;
 struct workqueue_struct *gfs2_delete_workqueue;
@@ -154,12 +152,14 @@
 static void glock_free(struct gfs2_glock *gl)
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
-	struct inode *aspace = gl->gl_aspace;
+	struct address_space *mapping = gfs2_glock2aspace(gl);
+	struct kmem_cache *cachep = gfs2_glock_cachep;
 
-	if (aspace)
-		gfs2_aspace_put(aspace);
+	GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
 	trace_gfs2_glock_put(gl);
-	sdp->sd_lockstruct.ls_ops->lm_put_lock(gfs2_glock_cachep, gl);
+	if (mapping)
+		cachep = gfs2_glock_aspace_cachep;
+	sdp->sd_lockstruct.ls_ops->lm_put_lock(cachep, gl);
 }
 
 /**
@@ -712,7 +712,6 @@
 		finish_xmote(gl, gl->gl_reply);
 		drop_ref = 1;
 	}
-	down_read(&gfs2_umount_flush_sem);
 	spin_lock(&gl->gl_spin);
 	if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
 	    gl->gl_state != LM_ST_UNLOCKED &&
@@ -725,7 +724,6 @@
 	}
 	run_queue(gl, 0);
 	spin_unlock(&gl->gl_spin);
-	up_read(&gfs2_umount_flush_sem);
 	if (!delay ||
 	    queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)
 		gfs2_glock_put(gl);
@@ -750,10 +748,11 @@
 		   const struct gfs2_glock_operations *glops, int create,
 		   struct gfs2_glock **glp)
 {
+	struct super_block *s = sdp->sd_vfs;
 	struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type };
 	struct gfs2_glock *gl, *tmp;
 	unsigned int hash = gl_hash(sdp, &name);
-	int error;
+	struct address_space *mapping;
 
 	read_lock(gl_lock_addr(hash));
 	gl = search_bucket(hash, sdp, &name);
@@ -765,7 +764,10 @@
 	if (!create)
 		return -ENOENT;
 
-	gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL);
+	if (glops->go_flags & GLOF_ASPACE)
+		gl = kmem_cache_alloc(gfs2_glock_aspace_cachep, GFP_KERNEL);
+	else
+		gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL);
 	if (!gl)
 		return -ENOMEM;
 
@@ -784,18 +786,18 @@
 	gl->gl_tchange = jiffies;
 	gl->gl_object = NULL;
 	gl->gl_sbd = sdp;
-	gl->gl_aspace = NULL;
 	INIT_DELAYED_WORK(&gl->gl_work, glock_work_func);
 	INIT_WORK(&gl->gl_delete, delete_work_func);
 
-	/* If this glock protects actual on-disk data or metadata blocks,
-	   create a VFS inode to manage the pages/buffers holding them. */
-	if (glops == &gfs2_inode_glops || glops == &gfs2_rgrp_glops) {
-		gl->gl_aspace = gfs2_aspace_get(sdp);
-		if (!gl->gl_aspace) {
-			error = -ENOMEM;
-			goto fail;
-		}
+	mapping = gfs2_glock2aspace(gl);
+	if (mapping) {
+                mapping->a_ops = &gfs2_meta_aops;
+		mapping->host = s->s_bdev->bd_inode;
+		mapping->flags = 0;
+		mapping_set_gfp_mask(mapping, GFP_NOFS);
+		mapping->assoc_mapping = NULL;
+		mapping->backing_dev_info = s->s_bdi;
+		mapping->writeback_index = 0;
 	}
 
 	write_lock(gl_lock_addr(hash));
@@ -812,10 +814,6 @@
 	*glp = gl;
 
 	return 0;
-
-fail:
-	kmem_cache_free(gfs2_glock_cachep, gl);
-	return error;
 }
 
 /**
@@ -1510,35 +1508,10 @@
 
 void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
 {
-	unsigned long t;
 	unsigned int x;
-	int cont;
 
-	t = jiffies;
-
-	for (;;) {
-		cont = 0;
-		for (x = 0; x < GFS2_GL_HASH_SIZE; x++) {
-			if (examine_bucket(clear_glock, sdp, x))
-				cont = 1;
-		}
-
-		if (!cont)
-			break;
-
-		if (time_after_eq(jiffies,
-				  t + gfs2_tune_get(sdp, gt_stall_secs) * HZ)) {
-			fs_warn(sdp, "Unmount seems to be stalled. "
-				     "Dumping lock state...\n");
-			gfs2_dump_lockstate(sdp);
-			t = jiffies;
-		}
-
-		down_write(&gfs2_umount_flush_sem);
-		invalidate_inodes(sdp->sd_vfs);
-		up_write(&gfs2_umount_flush_sem);
-		msleep(10);
-	}
+	for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
+		examine_bucket(clear_glock, sdp, x);
 	flush_workqueue(glock_workqueue);
 	wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0);
 	gfs2_dump_lockstate(sdp);
@@ -1685,7 +1658,7 @@
 	dtime *= 1000000/HZ; /* demote time in uSec */
 	if (!test_bit(GLF_DEMOTE, &gl->gl_flags))
 		dtime = 0;
-	gfs2_print_dbg(seq, "G:  s:%s n:%u/%llu f:%s t:%s d:%s/%llu a:%d r:%d\n",
+	gfs2_print_dbg(seq, "G:  s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d r:%d\n",
 		  state2str(gl->gl_state),
 		  gl->gl_name.ln_type,
 		  (unsigned long long)gl->gl_name.ln_number,
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index c0262fa..2bda191 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -180,6 +180,13 @@
 	return gl->gl_state == LM_ST_SHARED;
 }
 
+static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl)
+{
+	if (gl->gl_ops->go_flags & GLOF_ASPACE)
+		return (struct address_space *)(gl + 1);
+	return NULL;
+}
+
 int gfs2_glock_get(struct gfs2_sbd *sdp,
 		   u64 number, const struct gfs2_glock_operations *glops,
 		   int create, struct gfs2_glock **glp);
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 78554ac..38e3749 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -87,7 +87,7 @@
 
 static void rgrp_go_sync(struct gfs2_glock *gl)
 {
-	struct address_space *metamapping = gl->gl_aspace->i_mapping;
+	struct address_space *metamapping = gfs2_glock2aspace(gl);
 	int error;
 
 	if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
@@ -113,7 +113,7 @@
 
 static void rgrp_go_inval(struct gfs2_glock *gl, int flags)
 {
-	struct address_space *mapping = gl->gl_aspace->i_mapping;
+	struct address_space *mapping = gfs2_glock2aspace(gl);
 
 	BUG_ON(!(flags & DIO_METADATA));
 	gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
@@ -134,7 +134,7 @@
 static void inode_go_sync(struct gfs2_glock *gl)
 {
 	struct gfs2_inode *ip = gl->gl_object;
-	struct address_space *metamapping = gl->gl_aspace->i_mapping;
+	struct address_space *metamapping = gfs2_glock2aspace(gl);
 	int error;
 
 	if (ip && !S_ISREG(ip->i_inode.i_mode))
@@ -183,7 +183,7 @@
 	gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count));
 
 	if (flags & DIO_METADATA) {
-		struct address_space *mapping = gl->gl_aspace->i_mapping;
+		struct address_space *mapping = gfs2_glock2aspace(gl);
 		truncate_inode_pages(mapping, 0);
 		if (ip) {
 			set_bit(GIF_INVALID, &ip->i_flags);
@@ -282,7 +282,8 @@
 
 static int rgrp_go_demote_ok(const struct gfs2_glock *gl)
 {
-	return !gl->gl_aspace->i_mapping->nrpages;
+	const struct address_space *mapping = (const struct address_space *)(gl + 1);
+	return !mapping->nrpages;
 }
 
 /**
@@ -387,8 +388,7 @@
 	struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object;
 
 	if (gl->gl_demote_state == LM_ST_UNLOCKED &&
-	    gl->gl_state == LM_ST_SHARED &&
-	    ip && test_bit(GIF_USER, &ip->i_flags)) {
+	    gl->gl_state == LM_ST_SHARED && ip) {
 		gfs2_glock_hold(gl);
 		if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0)
 			gfs2_glock_put_nolock(gl);
@@ -407,6 +407,7 @@
 	.go_dump = inode_go_dump,
 	.go_type = LM_TYPE_INODE,
 	.go_min_hold_time = HZ / 5,
+	.go_flags = GLOF_ASPACE,
 };
 
 const struct gfs2_glock_operations gfs2_rgrp_glops = {
@@ -418,6 +419,7 @@
 	.go_dump = gfs2_rgrp_dump,
 	.go_type = LM_TYPE_RGRP,
 	.go_min_hold_time = HZ / 5,
+	.go_flags = GLOF_ASPACE,
 };
 
 const struct gfs2_glock_operations gfs2_trans_glops = {
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index bc0ad15..3aac46f 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -162,6 +162,8 @@
 	void (*go_callback) (struct gfs2_glock *gl);
 	const int go_type;
 	const unsigned long go_min_hold_time;
+	const unsigned long go_flags;
+#define GLOF_ASPACE 1
 };
 
 enum {
@@ -225,7 +227,6 @@
 
 	struct gfs2_sbd *gl_sbd;
 
-	struct inode *gl_aspace;
 	struct list_head gl_ail_list;
 	atomic_t gl_ail_count;
 	struct delayed_work gl_work;
@@ -258,7 +259,6 @@
 	GIF_INVALID		= 0,
 	GIF_QD_LOCKED		= 1,
 	GIF_SW_PAGED		= 3,
-	GIF_USER                = 4, /* user inode, not metadata addr space */
 };
 
 
@@ -451,7 +451,6 @@
 	unsigned int gt_quota_quantum; /* Secs between syncs to quota file */
 	unsigned int gt_new_files_jdata;
 	unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */
-	unsigned int gt_stall_secs; /* Detects trouble! */
 	unsigned int gt_complain_secs;
 	unsigned int gt_statfs_quantum;
 	unsigned int gt_statfs_slow;
@@ -617,7 +616,7 @@
 	unsigned int sd_log_blks_reserved;
 	unsigned int sd_log_commited_buf;
 	unsigned int sd_log_commited_databuf;
-	unsigned int sd_log_commited_revoke;
+	int sd_log_commited_revoke;
 
 	unsigned int sd_log_num_buf;
 	unsigned int sd_log_num_revoke;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 6e220f4..b1bf269 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -45,7 +45,7 @@
 	struct gfs2_inode *ip = GFS2_I(inode);
 	u64 *no_addr = opaque;
 
-	if (ip->i_no_addr == *no_addr && test_bit(GIF_USER, &ip->i_flags))
+	if (ip->i_no_addr == *no_addr)
 		return 1;
 
 	return 0;
@@ -58,7 +58,6 @@
 
 	inode->i_ino = (unsigned long)*no_addr;
 	ip->i_no_addr = *no_addr;
-	set_bit(GIF_USER, &ip->i_flags);
 	return 0;
 }
 
@@ -84,7 +83,7 @@
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_skip_data *data = opaque;
 
-	if (ip->i_no_addr == data->no_addr && test_bit(GIF_USER, &ip->i_flags)){
+	if (ip->i_no_addr == data->no_addr) {
 		if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){
 			data->skipped = 1;
 			return 0;
@@ -103,7 +102,6 @@
 		return 1;
 	inode->i_ino = (unsigned long)(data->no_addr);
 	ip->i_no_addr = data->no_addr;
-	set_bit(GIF_USER, &ip->i_flags);
 	return 0;
 }
 
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 0e5e0e7..569b462 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -30,7 +30,10 @@
 
 	switch (gl->gl_lksb.sb_status) {
 	case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */
-		kmem_cache_free(gfs2_glock_cachep, gl);
+		if (gl->gl_ops->go_flags & GLOF_ASPACE)
+			kmem_cache_free(gfs2_glock_aspace_cachep, gl);
+		else
+			kmem_cache_free(gfs2_glock_cachep, gl);
 		if (atomic_dec_and_test(&sdp->sd_glock_disposal))
 			wake_up(&sdp->sd_glock_wait);
 		return;
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 4511b08..e5bf4b5 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -417,7 +417,7 @@
 	databufhdrs_needed = (sdp->sd_log_commited_databuf +
 			      (dbuf_limit - 1)) / dbuf_limit;
 
-	if (sdp->sd_log_commited_revoke)
+	if (sdp->sd_log_commited_revoke > 0)
 		revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
 					  sizeof(u64));
 
@@ -790,7 +790,6 @@
 	gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) ||
 			     (((int)sdp->sd_log_commited_databuf) >= 0));
 	sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
-	gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
 	reserved = calc_reserved(sdp);
 	gfs2_assert_withdraw(sdp, sdp->sd_log_blks_reserved + tr->tr_reserved >= reserved);
 	unused = sdp->sd_log_blks_reserved - reserved + tr->tr_reserved;
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index de97632..adc260f 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -528,9 +528,9 @@
 		gfs2_pin(sdp, bd->bd_bh);
 		tr->tr_num_databuf_new++;
 		sdp->sd_log_num_databuf++;
-		list_add(&le->le_list, &sdp->sd_log_le_databuf);
+		list_add_tail(&le->le_list, &sdp->sd_log_le_databuf);
 	} else {
-		list_add(&le->le_list, &sdp->sd_log_le_ordered);
+		list_add_tail(&le->le_list, &sdp->sd_log_le_ordered);
 	}
 out:
 	gfs2_log_unlock(sdp);
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index 5b31f77..a88fadc 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -52,6 +52,22 @@
 	atomic_set(&gl->gl_ail_count, 0);
 }
 
+static void gfs2_init_gl_aspace_once(void *foo)
+{
+	struct gfs2_glock *gl = foo;
+	struct address_space *mapping = (struct address_space *)(gl + 1);
+
+	gfs2_init_glock_once(gl);
+	memset(mapping, 0, sizeof(*mapping));
+	INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC);
+	spin_lock_init(&mapping->tree_lock);
+	spin_lock_init(&mapping->i_mmap_lock);
+	INIT_LIST_HEAD(&mapping->private_list);
+	spin_lock_init(&mapping->private_lock);
+	INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap);
+	INIT_LIST_HEAD(&mapping->i_mmap_nonlinear);
+}
+
 /**
  * init_gfs2_fs - Register GFS2 as a filesystem
  *
@@ -78,6 +94,14 @@
 	if (!gfs2_glock_cachep)
 		goto fail;
 
+	gfs2_glock_aspace_cachep = kmem_cache_create("gfs2_glock (aspace)",
+					sizeof(struct gfs2_glock) +
+					sizeof(struct address_space),
+					0, 0, gfs2_init_gl_aspace_once);
+
+	if (!gfs2_glock_aspace_cachep)
+		goto fail;
+
 	gfs2_inode_cachep = kmem_cache_create("gfs2_inode",
 					      sizeof(struct gfs2_inode),
 					      0,  SLAB_RECLAIM_ACCOUNT|
@@ -144,6 +168,9 @@
 	if (gfs2_inode_cachep)
 		kmem_cache_destroy(gfs2_inode_cachep);
 
+	if (gfs2_glock_aspace_cachep)
+		kmem_cache_destroy(gfs2_glock_aspace_cachep);
+
 	if (gfs2_glock_cachep)
 		kmem_cache_destroy(gfs2_glock_cachep);
 
@@ -169,6 +196,7 @@
 	kmem_cache_destroy(gfs2_rgrpd_cachep);
 	kmem_cache_destroy(gfs2_bufdata_cachep);
 	kmem_cache_destroy(gfs2_inode_cachep);
+	kmem_cache_destroy(gfs2_glock_aspace_cachep);
 	kmem_cache_destroy(gfs2_glock_cachep);
 
 	gfs2_sys_uninit();
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 6f68a5f..0bb12c8 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -93,49 +93,13 @@
 	return err;
 }
 
-static const struct address_space_operations aspace_aops = {
+const struct address_space_operations gfs2_meta_aops = {
 	.writepage = gfs2_aspace_writepage,
 	.releasepage = gfs2_releasepage,
 	.sync_page = block_sync_page,
 };
 
 /**
- * gfs2_aspace_get - Create and initialize a struct inode structure
- * @sdp: the filesystem the aspace is in
- *
- * Right now a struct inode is just a struct inode.  Maybe Linux
- * will supply a more lightweight address space construct (that works)
- * in the future.
- *
- * Make sure pages/buffers in this aspace aren't in high memory.
- *
- * Returns: the aspace
- */
-
-struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp)
-{
-	struct inode *aspace;
-	struct gfs2_inode *ip;
-
-	aspace = new_inode(sdp->sd_vfs);
-	if (aspace) {
-		mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS);
-		aspace->i_mapping->a_ops = &aspace_aops;
-		aspace->i_size = MAX_LFS_FILESIZE;
-		ip = GFS2_I(aspace);
-		clear_bit(GIF_USER, &ip->i_flags);
-		insert_inode_hash(aspace);
-	}
-	return aspace;
-}
-
-void gfs2_aspace_put(struct inode *aspace)
-{
-	remove_inode_hash(aspace);
-	iput(aspace);
-}
-
-/**
  * gfs2_meta_sync - Sync all buffers associated with a glock
  * @gl: The glock
  *
@@ -143,7 +107,7 @@
 
 void gfs2_meta_sync(struct gfs2_glock *gl)
 {
-	struct address_space *mapping = gl->gl_aspace->i_mapping;
+	struct address_space *mapping = gfs2_glock2aspace(gl);
 	int error;
 
 	filemap_fdatawrite(mapping);
@@ -164,7 +128,7 @@
 
 struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)
 {
-	struct address_space *mapping = gl->gl_aspace->i_mapping;
+	struct address_space *mapping = gfs2_glock2aspace(gl);
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	struct page *page;
 	struct buffer_head *bh;
@@ -344,8 +308,10 @@
 
 void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta)
 {
-	struct gfs2_sbd *sdp = GFS2_SB(bh->b_page->mapping->host);
+	struct address_space *mapping = bh->b_page->mapping;
+	struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);
 	struct gfs2_bufdata *bd = bh->b_private;
+
 	if (test_clear_buffer_pinned(bh)) {
 		list_del_init(&bd->bd_le.le_list);
 		if (meta) {
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index de270c2..6a1d9ba 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -37,8 +37,16 @@
 	       0, from_head - to_head);
 }
 
-struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp);
-void gfs2_aspace_put(struct inode *aspace);
+extern const struct address_space_operations gfs2_meta_aops;
+
+static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)
+{
+	struct inode *inode = mapping->host;
+	if (mapping->a_ops == &gfs2_meta_aops)
+		return (((struct gfs2_glock *)mapping) - 1)->gl_sbd;
+	else
+		return inode->i_sb->s_fs_info;
+}
 
 void gfs2_meta_sync(struct gfs2_glock *gl);
 
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index a86ed63..c1309ed 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -65,7 +65,6 @@
 	gt->gt_quota_scale_den = 1;
 	gt->gt_new_files_jdata = 0;
 	gt->gt_max_readahead = 1 << 18;
-	gt->gt_stall_secs = 600;
 	gt->gt_complain_secs = 10;
 }
 
@@ -1002,7 +1001,7 @@
 /**
  * gfs2_lm_mount - mount a locking protocol
  * @sdp: the filesystem
- * @args: mount arguements
+ * @args: mount arguments
  * @silent: if 1, don't complain if the FS isn't a GFS2 fs
  *
  * Returns: errno
@@ -1241,10 +1240,9 @@
 fail_locking:
 	init_locking(sdp, &mount_gh, UNDO);
 fail_lm:
+	invalidate_inodes(sb);
 	gfs2_gl_hash_clear(sdp);
 	gfs2_lm_unmount(sdp);
-	while (invalidate_inodes(sb))
-		yield();
 fail_sys:
 	gfs2_sys_fs_del(sdp);
 fail:
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index 84350e1..4e64352 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -976,102 +976,11 @@
 }
 
 /**
- * gfs2_readlinki - return the contents of a symlink
- * @ip: the symlink's inode
- * @buf: a pointer to the buffer to be filled
- * @len: a pointer to the length of @buf
- *
- * If @buf is too small, a piece of memory is kmalloc()ed and needs
- * to be freed by the caller.
- *
- * Returns: errno
- */
-
-static int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
-{
-	struct gfs2_holder i_gh;
-	struct buffer_head *dibh;
-	unsigned int x;
-	int error;
-
-	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
-	error = gfs2_glock_nq(&i_gh);
-	if (error) {
-		gfs2_holder_uninit(&i_gh);
-		return error;
-	}
-
-	if (!ip->i_disksize) {
-		gfs2_consist_inode(ip);
-		error = -EIO;
-		goto out;
-	}
-
-	error = gfs2_meta_inode_buffer(ip, &dibh);
-	if (error)
-		goto out;
-
-	x = ip->i_disksize + 1;
-	if (x > *len) {
-		*buf = kmalloc(x, GFP_NOFS);
-		if (!*buf) {
-			error = -ENOMEM;
-			goto out_brelse;
-		}
-	}
-
-	memcpy(*buf, dibh->b_data + sizeof(struct gfs2_dinode), x);
-	*len = x;
-
-out_brelse:
-	brelse(dibh);
-out:
-	gfs2_glock_dq_uninit(&i_gh);
-	return error;
-}
-
-/**
- * gfs2_readlink - Read the value of a symlink
- * @dentry: the symlink
- * @buf: the buffer to read the symlink data into
- * @size: the size of the buffer
- *
- * Returns: errno
- */
-
-static int gfs2_readlink(struct dentry *dentry, char __user *user_buf,
-			 int user_size)
-{
-	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-	char array[GFS2_FAST_NAME_SIZE], *buf = array;
-	unsigned int len = GFS2_FAST_NAME_SIZE;
-	int error;
-
-	error = gfs2_readlinki(ip, &buf, &len);
-	if (error)
-		return error;
-
-	if (user_size > len - 1)
-		user_size = len - 1;
-
-	if (copy_to_user(user_buf, buf, user_size))
-		error = -EFAULT;
-	else
-		error = user_size;
-
-	if (buf != array)
-		kfree(buf);
-
-	return error;
-}
-
-/**
  * gfs2_follow_link - Follow a symbolic link
  * @dentry: The dentry of the link
  * @nd: Data that we pass to vfs_follow_link()
  *
- * This can handle symlinks of any size. It is optimised for symlinks
- * under GFS2_FAST_NAME_SIZE.
+ * This can handle symlinks of any size.
  *
  * Returns: 0 on success or error code
  */
@@ -1079,19 +988,50 @@
 static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-	char array[GFS2_FAST_NAME_SIZE], *buf = array;
-	unsigned int len = GFS2_FAST_NAME_SIZE;
+	struct gfs2_holder i_gh;
+	struct buffer_head *dibh;
+	unsigned int x;
+	char *buf;
 	int error;
 
-	error = gfs2_readlinki(ip, &buf, &len);
-	if (!error) {
-		error = vfs_follow_link(nd, buf);
-		if (buf != array)
-			kfree(buf);
-	} else
-		path_put(&nd->path);
+	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
+	error = gfs2_glock_nq(&i_gh);
+	if (error) {
+		gfs2_holder_uninit(&i_gh);
+		nd_set_link(nd, ERR_PTR(error));
+		return NULL;
+	}
 
-	return ERR_PTR(error);
+	if (!ip->i_disksize) {
+		gfs2_consist_inode(ip);
+		buf = ERR_PTR(-EIO);
+		goto out;
+	}
+
+	error = gfs2_meta_inode_buffer(ip, &dibh);
+	if (error) {
+		buf = ERR_PTR(error);
+		goto out;
+	}
+
+	x = ip->i_disksize + 1;
+	buf = kmalloc(x, GFP_NOFS);
+	if (!buf)
+		buf = ERR_PTR(-ENOMEM);
+	else
+		memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), x);
+	brelse(dibh);
+out:
+	gfs2_glock_dq_uninit(&i_gh);
+	nd_set_link(nd, buf);
+	return NULL;
+}
+
+static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+{
+	char *s = nd_get_link(nd);
+	if (!IS_ERR(s))
+		kfree(s);
 }
 
 /**
@@ -1426,8 +1366,9 @@
 };
 
 const struct inode_operations gfs2_symlink_iops = {
-	.readlink = gfs2_readlink,
+	.readlink = generic_readlink,
 	.follow_link = gfs2_follow_link,
+	.put_link = gfs2_put_link,
 	.permission = gfs2_permission,
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index e3bf6ea..6dbcbad 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -1083,7 +1083,7 @@
 	}
 }
 
-int gfs2_quota_sync(struct super_block *sb, int type)
+int gfs2_quota_sync(struct super_block *sb, int type, int wait)
 {
 	struct gfs2_sbd *sdp = sb->s_fs_info;
 	struct gfs2_quota_data **qda;
@@ -1127,6 +1127,11 @@
 	return error;
 }
 
+static int gfs2_quota_sync_timeo(struct super_block *sb, int type)
+{
+	return gfs2_quota_sync(sb, type, 0);
+}
+
 int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
 {
 	struct gfs2_quota_data *qd;
@@ -1382,7 +1387,7 @@
 					   &tune->gt_statfs_quantum);
 
 		/* Update quota file */
-		quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t,
+		quotad_check_timeo(sdp, "sync", gfs2_quota_sync_timeo, t,
 				   &quotad_timeo, &tune->gt_quota_quantum);
 
 		/* Check for & recover partially truncated inodes */
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
index e271fa0..195f60c 100644
--- a/fs/gfs2/quota.h
+++ b/fs/gfs2/quota.h
@@ -25,7 +25,7 @@
 extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
 			      u32 uid, u32 gid);
 
-extern int gfs2_quota_sync(struct super_block *sb, int type);
+extern int gfs2_quota_sync(struct super_block *sb, int type, int wait);
 extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id);
 
 extern int gfs2_quota_init(struct gfs2_sbd *sdp);
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index b9dd3da..50aac60 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -22,6 +22,7 @@
 #include <linux/crc32.h>
 #include <linux/time.h>
 #include <linux/wait.h>
+#include <linux/writeback.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -711,7 +712,7 @@
  * Returns: errno
  */
 
-static int gfs2_write_inode(struct inode *inode, int sync)
+static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
@@ -722,8 +723,7 @@
 	int ret = 0;
 
 	/* Check this is a "normal" inode, etc */
-	if (!test_bit(GIF_USER, &ip->i_flags) ||
-	    (current->flags & PF_MEMALLOC))
+	if (current->flags & PF_MEMALLOC)
 		return 0;
 	ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
 	if (ret)
@@ -746,7 +746,7 @@
 do_unlock:
 	gfs2_glock_dq_uninit(&gh);
 do_flush:
-	if (sync != 0)
+	if (wbc->sync_mode == WB_SYNC_ALL)
 		gfs2_log_flush(GFS2_SB(inode), ip->i_gl);
 	return ret;
 }
@@ -764,7 +764,7 @@
 	int error;
 
 	flush_workqueue(gfs2_delete_workqueue);
-	gfs2_quota_sync(sdp->sd_vfs, 0);
+	gfs2_quota_sync(sdp->sd_vfs, 0, 1);
 	gfs2_statfs_sync(sdp->sd_vfs, 0);
 
 	error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,
@@ -860,6 +860,7 @@
 	gfs2_clear_rgrpd(sdp);
 	gfs2_jindex_free(sdp);
 	/*  Take apart glock structures and buffer lists  */
+	invalidate_inodes(sdp->sd_vfs);
 	gfs2_gl_hash_clear(sdp);
 	/*  Unmount the locking protocol  */
 	gfs2_lm_unmount(sdp);
@@ -1194,7 +1195,7 @@
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
 
-	if (test_bit(GIF_USER, &ip->i_flags) && inode->i_nlink) {
+	if (inode->i_nlink) {
 		struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
 		if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags))
 			clear_nlink(inode);
@@ -1212,18 +1213,12 @@
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
 
-	/* This tells us its a "real" inode and not one which only
-	 * serves to contain an address space (see rgrp.c, meta_io.c)
-	 * which therefore doesn't have its own glocks.
-	 */
-	if (test_bit(GIF_USER, &ip->i_flags)) {
-		ip->i_gl->gl_object = NULL;
-		gfs2_glock_put(ip->i_gl);
-		ip->i_gl = NULL;
-		if (ip->i_iopen_gh.gh_gl) {
-			ip->i_iopen_gh.gh_gl->gl_object = NULL;
-			gfs2_glock_dq_uninit(&ip->i_iopen_gh);
-		}
+	ip->i_gl->gl_object = NULL;
+	gfs2_glock_put(ip->i_gl);
+	ip->i_gl = NULL;
+	if (ip->i_iopen_gh.gh_gl) {
+		ip->i_iopen_gh.gh_gl->gl_object = NULL;
+		gfs2_glock_dq_uninit(&ip->i_iopen_gh);
 	}
 }
 
@@ -1358,9 +1353,6 @@
 	struct gfs2_holder gh;
 	int error;
 
-	if (!test_bit(GIF_USER, &ip->i_flags))
-		goto out;
-
 	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
 	if (unlikely(error)) {
 		gfs2_glock_dq_uninit(&ip->i_iopen_gh);
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index 0dc3462..419042f 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -49,7 +49,7 @@
 	return a->store ? a->store(sdp, buf, len) : len;
 }
 
-static struct sysfs_ops gfs2_attr_ops = {
+static const struct sysfs_ops gfs2_attr_ops = {
 	.show  = gfs2_attr_show,
 	.store = gfs2_attr_store,
 };
@@ -167,7 +167,7 @@
 	if (simple_strtol(buf, NULL, 0) != 1)
 		return -EINVAL;
 
-	gfs2_quota_sync(sdp->sd_vfs, 0);
+	gfs2_quota_sync(sdp->sd_vfs, 0, 1);
 	return len;
 }
 
@@ -478,7 +478,6 @@
 TUNE_ATTR(statfs_slow, 0);
 TUNE_ATTR(new_files_jdata, 0);
 TUNE_ATTR(quota_simul_sync, 1);
-TUNE_ATTR(stall_secs, 1);
 TUNE_ATTR(statfs_quantum, 1);
 TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
 
@@ -491,7 +490,6 @@
 	&tune_attr_complain_secs.attr,
 	&tune_attr_statfs_slow.attr,
 	&tune_attr_quota_simul_sync.attr,
-	&tune_attr_stall_secs.attr,
 	&tune_attr_statfs_quantum.attr,
 	&tune_attr_quota_scale.attr,
 	&tune_attr_new_files_jdata.attr,
@@ -576,7 +574,7 @@
 	return 0;
 }
 
-static struct kset_uevent_ops gfs2_uevent_ops = {
+static const struct kset_uevent_ops gfs2_uevent_ops = {
 	.uevent = gfs2_uevent,
 };
 
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index f6a7efa..226f2bf 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -21,6 +21,7 @@
 #include "util.h"
 
 struct kmem_cache *gfs2_glock_cachep __read_mostly;
+struct kmem_cache *gfs2_glock_aspace_cachep __read_mostly;
 struct kmem_cache *gfs2_inode_cachep __read_mostly;
 struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
 struct kmem_cache *gfs2_rgrpd_cachep __read_mostly;
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h
index 33e96b0..b432e04 100644
--- a/fs/gfs2/util.h
+++ b/fs/gfs2/util.h
@@ -145,6 +145,7 @@
 
 
 extern struct kmem_cache *gfs2_glock_cachep;
+extern struct kmem_cache *gfs2_glock_aspace_cachep;
 extern struct kmem_cache *gfs2_inode_cachep;
 extern struct kmem_cache *gfs2_bufdata_cachep;
 extern struct kmem_cache *gfs2_rgrpd_cachep;
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 052387e..fe35e3b 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -188,7 +188,7 @@
 
 extern struct inode *hfs_new_inode(struct inode *, struct qstr *, int);
 extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *);
-extern int hfs_write_inode(struct inode *, int);
+extern int hfs_write_inode(struct inode *, struct writeback_control *);
 extern int hfs_inode_setattr(struct dentry *, struct iattr *);
 extern void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
 			__be32 log_size, __be32 phys_size, u32 clump_size);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index a1cbff2..14f5cb1 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -381,7 +381,7 @@
 					 HFS_SB(inode->i_sb)->alloc_blksz);
 }
 
-int hfs_write_inode(struct inode *inode, int unused)
+int hfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	struct inode *main_inode = inode;
 	struct hfs_find_data fd;
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 43022f3..74b473a 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -87,7 +87,8 @@
 	return ERR_PTR(err);
 }
 
-static int hfsplus_write_inode(struct inode *inode, int unused)
+static int hfsplus_write_inode(struct inode *inode,
+		struct writeback_control *wbc)
 {
 	struct hfsplus_vh *vhdr;
 	int ret = 0;
diff --git a/fs/hpfs/anode.c b/fs/hpfs/anode.c
index 1aa88c4..6a2f04b 100644
--- a/fs/hpfs/anode.c
+++ b/fs/hpfs/anode.c
@@ -353,7 +353,7 @@
 }
 
 int hpfs_ea_write(struct super_block *s, secno a, int ano, unsigned pos,
-	     unsigned len, char *buf)
+	     unsigned len, const char *buf)
 {
 	struct buffer_head *bh;
 	char *data;
diff --git a/fs/hpfs/dentry.c b/fs/hpfs/dentry.c
index 940d6d1..67d9d36 100644
--- a/fs/hpfs/dentry.c
+++ b/fs/hpfs/dentry.c
@@ -20,8 +20,8 @@
 
 	if (l == 1) if (qstr->name[0]=='.') goto x;
 	if (l == 2) if (qstr->name[0]=='.' || qstr->name[1]=='.') goto x;
-	hpfs_adjust_length((char *)qstr->name, &l);
-	/*if (hpfs_chk_name((char *)qstr->name,&l))*/
+	hpfs_adjust_length(qstr->name, &l);
+	/*if (hpfs_chk_name(qstr->name,&l))*/
 		/*return -ENAMETOOLONG;*/
 		/*return -ENOENT;*/
 	x:
@@ -38,14 +38,16 @@
 {
 	unsigned al=a->len;
 	unsigned bl=b->len;
-	hpfs_adjust_length((char *)a->name, &al);
-	/*hpfs_adjust_length((char *)b->name, &bl);*/
+	hpfs_adjust_length(a->name, &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.
 	 */
 
-	if (hpfs_chk_name((char *)b->name, &bl)) return 1;
-	if (hpfs_compare_names(dentry->d_sb, (char *)a->name, al, (char *)b->name, bl, 0)) return 1;
+	if (hpfs_chk_name(b->name, &bl))
+		return 1;
+	if (hpfs_compare_names(dentry->d_sb, a->name, al, b->name, bl, 0))
+		return 1;
 	return 0;
 }
 
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
index 8865c94..26e3964 100644
--- a/fs/hpfs/dir.c
+++ b/fs/hpfs/dir.c
@@ -59,7 +59,7 @@
 	struct hpfs_dirent *de;
 	int lc;
 	long old_pos;
-	char *tempname;
+	unsigned char *tempname;
 	int c1, c2 = 0;
 	int ret = 0;
 
@@ -158,11 +158,11 @@
 		tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3);
 		if (filldir(dirent, tempname, de->namelen, old_pos, de->fnode, DT_UNKNOWN) < 0) {
 			filp->f_pos = old_pos;
-			if (tempname != (char *)de->name) kfree(tempname);
+			if (tempname != de->name) kfree(tempname);
 			hpfs_brelse4(&qbh);
 			goto out;
 		}
-		if (tempname != (char *)de->name) kfree(tempname);
+		if (tempname != de->name) kfree(tempname);
 		hpfs_brelse4(&qbh);
 	}
 out:
@@ -187,7 +187,7 @@
 
 struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
-	const char *name = dentry->d_name.name;
+	const unsigned char *name = dentry->d_name.name;
 	unsigned len = dentry->d_name.len;
 	struct quad_buffer_head qbh;
 	struct hpfs_dirent *de;
@@ -197,7 +197,7 @@
 	struct hpfs_inode_info *hpfs_result;
 
 	lock_kernel();
-	if ((err = hpfs_chk_name((char *)name, &len))) {
+	if ((err = hpfs_chk_name(name, &len))) {
 		if (err == -ENAMETOOLONG) {
 			unlock_kernel();
 			return ERR_PTR(-ENAMETOOLONG);
@@ -209,7 +209,7 @@
 	 * '.' and '..' will never be passed here.
 	 */
 
-	de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *) name, len, NULL, &qbh);
+	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, NULL, &qbh);
 
 	/*
 	 * This is not really a bailout, just means file not found.
@@ -250,7 +250,7 @@
 	hpfs_result = hpfs_i(result);
 	if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino;
 
-	hpfs_decide_conv(result, (char *)name, len);
+	hpfs_decide_conv(result, name, len);
 
 	if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) {
 		hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");
diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c
index fe83c2b..9b2ffad 100644
--- a/fs/hpfs/dnode.c
+++ b/fs/hpfs/dnode.c
@@ -158,7 +158,8 @@
 
 /* Add an entry to dnode and don't care if it grows over 2048 bytes */
 
-struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d, unsigned char *name,
+struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,
+				const unsigned char *name,
 				unsigned namelen, secno down_ptr)
 {
 	struct hpfs_dirent *de;
@@ -223,7 +224,7 @@
 /* Add an entry to dnode and do dnode splitting if required */
 
 static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
-			     unsigned char *name, unsigned namelen,
+			     const unsigned char *name, unsigned namelen,
 			     struct hpfs_dirent *new_de, dnode_secno down_ptr)
 {
 	struct quad_buffer_head qbh, qbh1, qbh2;
@@ -231,7 +232,7 @@
 	dnode_secno adno, rdno;
 	struct hpfs_dirent *de;
 	struct hpfs_dirent nde;
-	char *nname;
+	unsigned char *nname;
 	int h;
 	int pos;
 	struct buffer_head *bh;
@@ -305,7 +306,9 @@
 		pos++;
 	}
 	copy_de(new_de = &nde, de);
-	memcpy(name = nname, de->name, namelen = de->namelen);
+	memcpy(nname, de->name, de->namelen);
+	name = nname;
+	namelen = de->namelen;
 	for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | pos, 4);
 	down_ptr = adno;
 	set_last_pointer(i->i_sb, ad, de->down ? de_down_pointer(de) : 0);
@@ -368,7 +371,8 @@
  * I hope, now it's finally bug-free.
  */
 
-int hpfs_add_dirent(struct inode *i, unsigned char *name, unsigned namelen,
+int hpfs_add_dirent(struct inode *i,
+		    const unsigned char *name, unsigned namelen,
 		    struct hpfs_dirent *new_de, int cdepth)
 {
 	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
@@ -897,7 +901,8 @@
 
 /* Find a dirent in tree */
 
-struct hpfs_dirent *map_dirent(struct inode *inode, dnode_secno dno, char *name, unsigned len,
+struct hpfs_dirent *map_dirent(struct inode *inode, dnode_secno dno,
+			       const unsigned char *name, unsigned len,
 			       dnode_secno *dd, struct quad_buffer_head *qbh)
 {
 	struct dnode *dnode;
@@ -988,8 +993,8 @@
 struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
 				     struct fnode *f, struct quad_buffer_head *qbh)
 {
-	char *name1;
-	char *name2;
+	unsigned char *name1;
+	unsigned char *name2;
 	int name1len, name2len;
 	struct dnode *d;
 	dnode_secno dno, downd;
diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c
index 547a838..45e53d9 100644
--- a/fs/hpfs/ea.c
+++ b/fs/hpfs/ea.c
@@ -62,8 +62,8 @@
 	return ret;
 }
 
-static void set_indirect_ea(struct super_block *s, int ano, secno a, char *data,
-			    int size)
+static void set_indirect_ea(struct super_block *s, int ano, secno a,
+			    const char *data, int size)
 {
 	hpfs_ea_write(s, a, ano, 0, size, data);
 }
@@ -186,7 +186,8 @@
  * This driver can't change sizes of eas ('cause I just don't need it).
  */
 
-void hpfs_set_ea(struct inode *inode, struct fnode *fnode, char *key, char *data, int size)
+void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
+		 const char *data, int size)
 {
 	fnode_secno fno = inode->i_ino;
 	struct super_block *s = inode->i_sb;
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 701ca54..97bf738 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -215,7 +215,7 @@
 secno hpfs_add_sector_to_btree(struct super_block *, secno, int, unsigned);
 void hpfs_remove_btree(struct super_block *, struct bplus_header *);
 int hpfs_ea_read(struct super_block *, secno, int, unsigned, unsigned, char *);
-int hpfs_ea_write(struct super_block *, secno, int, unsigned, unsigned, char *);
+int hpfs_ea_write(struct super_block *, secno, int, unsigned, unsigned, const char *);
 void hpfs_ea_remove(struct super_block *, secno, int, unsigned);
 void hpfs_truncate_btree(struct super_block *, secno, int, unsigned);
 void hpfs_remove_fnode(struct super_block *, fnode_secno fno);
@@ -244,13 +244,17 @@
 
 void hpfs_add_pos(struct inode *, loff_t *);
 void hpfs_del_pos(struct inode *, loff_t *);
-struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *, unsigned char *, unsigned, secno);
-int hpfs_add_dirent(struct inode *, unsigned char *, unsigned, struct hpfs_dirent *, int);
+struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *,
+				const unsigned char *, unsigned, secno);
+int hpfs_add_dirent(struct inode *, const unsigned char *, unsigned,
+		    struct hpfs_dirent *, int);
 int hpfs_remove_dirent(struct inode *, dnode_secno, struct hpfs_dirent *, struct quad_buffer_head *, int);
 void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *);
 dnode_secno hpfs_de_as_down_as_possible(struct super_block *, dnode_secno dno);
 struct hpfs_dirent *map_pos_dirent(struct inode *, loff_t *, struct quad_buffer_head *);
-struct hpfs_dirent *map_dirent(struct inode *, dnode_secno, char *, unsigned, dnode_secno *, struct quad_buffer_head *);
+struct hpfs_dirent *map_dirent(struct inode *, dnode_secno,
+			       const unsigned char *, unsigned, dnode_secno *,
+			       struct quad_buffer_head *);
 void hpfs_remove_dtree(struct super_block *, dnode_secno);
 struct hpfs_dirent *map_fnode_dirent(struct super_block *, fnode_secno, struct fnode *, struct quad_buffer_head *);
 
@@ -259,7 +263,8 @@
 void hpfs_ea_ext_remove(struct super_block *, secno, int, unsigned);
 int hpfs_read_ea(struct super_block *, struct fnode *, char *, char *, int);
 char *hpfs_get_ea(struct super_block *, struct fnode *, char *, int *);
-void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int);
+void hpfs_set_ea(struct inode *, struct fnode *, const char *,
+		 const char *, int);
 
 /* file.c */
 
@@ -282,7 +287,7 @@
 
 unsigned *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *);
 unsigned *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *);
-char *hpfs_load_code_page(struct super_block *, secno);
+unsigned char *hpfs_load_code_page(struct super_block *, secno);
 secno *hpfs_load_bitmap_directory(struct super_block *, secno bmp);
 struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **);
 struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **);
@@ -292,12 +297,13 @@
 /* name.c */
 
 unsigned char hpfs_upcase(unsigned char *, unsigned char);
-int hpfs_chk_name(unsigned char *, unsigned *);
-char *hpfs_translate_name(struct super_block *, unsigned char *, unsigned, int, int);
-int hpfs_compare_names(struct super_block *, unsigned char *, unsigned, unsigned char *, unsigned, int);
-int hpfs_is_name_long(unsigned char *, unsigned);
-void hpfs_adjust_length(unsigned char *, unsigned *);
-void hpfs_decide_conv(struct inode *, unsigned char *, unsigned);
+int hpfs_chk_name(const unsigned char *, unsigned *);
+unsigned char *hpfs_translate_name(struct super_block *, unsigned char *, unsigned, int, int);
+int hpfs_compare_names(struct super_block *, const unsigned char *, unsigned,
+		       const unsigned char *, unsigned, int);
+int hpfs_is_name_long(const unsigned char *, unsigned);
+void hpfs_adjust_length(const unsigned char *, unsigned *);
+void hpfs_decide_conv(struct inode *, const unsigned char *, unsigned);
 
 /* namei.c */
 
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index fe703ae..ff90affb 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -46,7 +46,7 @@
 	struct fnode *fnode;
 	struct super_block *sb = i->i_sb;
 	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
-	unsigned char *ea;
+	void *ea;
 	int ea_size;
 
 	if (!(fnode = hpfs_map_fnode(sb, i->i_ino, &bh))) {
@@ -112,7 +112,7 @@
 		}
 	}
 	if (fnode->dirflag) {
-		unsigned n_dnodes, n_subdirs;
+		int n_dnodes, n_subdirs;
 		i->i_mode |= S_IFDIR;
 		i->i_op = &hpfs_dir_iops;
 		i->i_fop = &hpfs_dir_ops;
diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c
index c472458..840d033 100644
--- a/fs/hpfs/map.c
+++ b/fs/hpfs/map.c
@@ -35,7 +35,7 @@
  * lowercasing table
  */
 
-char *hpfs_load_code_page(struct super_block *s, secno cps)
+unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
 {
 	struct buffer_head *bh;
 	secno cpds;
@@ -71,7 +71,7 @@
 		brelse(bh);
 		return NULL;
 	}
-	ptr = (char *)cpd + cpd->offs[cpi] + 6;
+	ptr = (unsigned char *)cpd + cpd->offs[cpi] + 6;
 	if (!(cp_table = kmalloc(256, GFP_KERNEL))) {
 		printk("HPFS: out of memory for code page table\n");
 		brelse(bh);
@@ -217,7 +217,7 @@
 	if ((dnode = hpfs_map_4sectors(s, secno, qbh, DNODE_RD_AHEAD)))
 		if (hpfs_sb(s)->sb_chk) {
 			unsigned p, pp = 0;
-			unsigned char *d = (char *)dnode;
+			unsigned char *d = (unsigned char *)dnode;
 			int b = 0;
 			if (dnode->magic != DNODE_MAGIC) {
 				hpfs_error(s, "bad magic on dnode %08x", secno);
diff --git a/fs/hpfs/name.c b/fs/hpfs/name.c
index 1f4a964..f24736d 100644
--- a/fs/hpfs/name.c
+++ b/fs/hpfs/name.c
@@ -8,16 +8,16 @@
 
 #include "hpfs_fn.h"
 
-static char *text_postfix[]={
+static const char *text_postfix[]={
 ".ASM", ".BAS", ".BAT", ".C", ".CC", ".CFG", ".CMD", ".CON", ".CPP", ".DEF",
 ".DOC", ".DPR", ".ERX", ".H", ".HPP", ".HTM", ".HTML", ".JAVA", ".LOG", ".PAS",
 ".RC", ".TEX", ".TXT", ".Y", ""};
 
-static char *text_prefix[]={
+static const char *text_prefix[]={
 "AUTOEXEC.", "CHANGES", "COPYING", "CONFIG.", "CREDITS", "FAQ", "FILE_ID.DIZ",
 "MAKEFILE", "READ.ME", "README", "TERMCAP", ""};
 
-void hpfs_decide_conv(struct inode *inode, unsigned char *name, unsigned len)
+void hpfs_decide_conv(struct inode *inode, const unsigned char *name, unsigned len)
 {
 	struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
 	int i;
@@ -71,7 +71,7 @@
 	return dir[a];
 }
 
-int hpfs_chk_name(unsigned char *name, unsigned *len)
+int hpfs_chk_name(const unsigned char *name, unsigned *len)
 {
 	int i;
 	if (*len > 254) return -ENAMETOOLONG;
@@ -83,10 +83,10 @@
 	return 0;
 }
 
-char *hpfs_translate_name(struct super_block *s, unsigned char *from,
+unsigned char *hpfs_translate_name(struct super_block *s, unsigned char *from,
 			  unsigned len, int lc, int lng)
 {
-	char *to;
+	unsigned char *to;
 	int i;
 	if (hpfs_sb(s)->sb_chk >= 2) if (hpfs_is_name_long(from, len) != lng) {
 		printk("HPFS: Long name flag mismatch - name ");
@@ -103,8 +103,9 @@
 	return to;
 }
 
-int hpfs_compare_names(struct super_block *s, unsigned char *n1, unsigned l1,
-		       unsigned char *n2, unsigned l2, int last)
+int hpfs_compare_names(struct super_block *s,
+		       const unsigned char *n1, unsigned l1,
+		       const unsigned char *n2, unsigned l2, int last)
 {
 	unsigned l = l1 < l2 ? l1 : l2;
 	unsigned i;
@@ -120,7 +121,7 @@
 	return 0;
 }
 
-int hpfs_is_name_long(unsigned char *name, unsigned len)
+int hpfs_is_name_long(const unsigned char *name, unsigned len)
 {
 	int i,j;
 	for (i = 0; i < len && name[i] != '.'; i++)
@@ -134,7 +135,7 @@
 
 /* OS/2 clears dots and spaces at the end of file name, so we have to */
 
-void hpfs_adjust_length(unsigned char *name, unsigned *len)
+void hpfs_adjust_length(const unsigned char *name, unsigned *len)
 {
 	if (!*len) return;
 	if (*len == 1 && name[0] == '.') return;
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 82b9c4b..11c2b40 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -11,7 +11,7 @@
 
 static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-	const char *name = dentry->d_name.name;
+	const unsigned char *name = dentry->d_name.name;
 	unsigned len = dentry->d_name.len;
 	struct quad_buffer_head qbh0;
 	struct buffer_head *bh;
@@ -24,7 +24,7 @@
 	int r;
 	struct hpfs_dirent dee;
 	int err;
-	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
+	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
 	lock_kernel();
 	err = -ENOSPC;
 	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
@@ -62,7 +62,7 @@
 		result->i_mode &= ~0222;
 
 	mutex_lock(&hpfs_i(dir)->i_mutex);
-	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+	r = hpfs_add_dirent(dir, name, len, &dee, 0);
 	if (r == 1)
 		goto bail3;
 	if (r == -1) {
@@ -121,7 +121,7 @@
 
 static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
 {
-	const char *name = dentry->d_name.name;
+	const unsigned char *name = dentry->d_name.name;
 	unsigned len = dentry->d_name.len;
 	struct inode *result = NULL;
 	struct buffer_head *bh;
@@ -130,7 +130,7 @@
 	int r;
 	struct hpfs_dirent dee;
 	int err;
-	if ((err = hpfs_chk_name((char *)name, &len)))
+	if ((err = hpfs_chk_name(name, &len)))
 		return err==-ENOENT ? -EINVAL : err;
 	lock_kernel();
 	err = -ENOSPC;
@@ -155,7 +155,7 @@
 	result->i_op = &hpfs_file_iops;
 	result->i_fop = &hpfs_file_ops;
 	result->i_nlink = 1;
-	hpfs_decide_conv(result, (char *)name, len);
+	hpfs_decide_conv(result, name, len);
 	hpfs_i(result)->i_parent_dir = dir->i_ino;
 	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
 	result->i_ctime.tv_nsec = 0;
@@ -170,7 +170,7 @@
 	hpfs_i(result)->mmu_private = 0;
 
 	mutex_lock(&hpfs_i(dir)->i_mutex);
-	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+	r = hpfs_add_dirent(dir, name, len, &dee, 0);
 	if (r == 1)
 		goto bail2;
 	if (r == -1) {
@@ -211,7 +211,7 @@
 
 static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
 {
-	const char *name = dentry->d_name.name;
+	const unsigned char *name = dentry->d_name.name;
 	unsigned len = dentry->d_name.len;
 	struct buffer_head *bh;
 	struct fnode *fnode;
@@ -220,7 +220,7 @@
 	struct hpfs_dirent dee;
 	struct inode *result = NULL;
 	int err;
-	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
+	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
 	if (hpfs_sb(dir->i_sb)->sb_eas < 2) return -EPERM;
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
@@ -256,7 +256,7 @@
 	init_special_inode(result, mode, rdev);
 
 	mutex_lock(&hpfs_i(dir)->i_mutex);
-	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+	r = hpfs_add_dirent(dir, name, len, &dee, 0);
 	if (r == 1)
 		goto bail2;
 	if (r == -1) {
@@ -289,7 +289,7 @@
 
 static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
 {
-	const char *name = dentry->d_name.name;
+	const unsigned char *name = dentry->d_name.name;
 	unsigned len = dentry->d_name.len;
 	struct buffer_head *bh;
 	struct fnode *fnode;
@@ -298,7 +298,7 @@
 	struct hpfs_dirent dee;
 	struct inode *result;
 	int err;
-	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
+	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
 	lock_kernel();
 	if (hpfs_sb(dir->i_sb)->sb_eas < 2) {
 		unlock_kernel();
@@ -335,7 +335,7 @@
 	result->i_data.a_ops = &hpfs_symlink_aops;
 
 	mutex_lock(&hpfs_i(dir)->i_mutex);
-	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+	r = hpfs_add_dirent(dir, name, len, &dee, 0);
 	if (r == 1)
 		goto bail2;
 	if (r == -1) {
@@ -345,7 +345,7 @@
 	fnode->len = len;
 	memcpy(fnode->name, name, len > 15 ? 15 : len);
 	fnode->up = dir->i_ino;
-	hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink));
+	hpfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink));
 	mark_buffer_dirty(bh);
 	brelse(bh);
 
@@ -369,7 +369,7 @@
 
 static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
 {
-	const char *name = dentry->d_name.name;
+	const unsigned char *name = dentry->d_name.name;
 	unsigned len = dentry->d_name.len;
 	struct quad_buffer_head qbh;
 	struct hpfs_dirent *de;
@@ -381,12 +381,12 @@
 	int err;
 
 	lock_kernel();
-	hpfs_adjust_length((char *)name, &len);
+	hpfs_adjust_length(name, &len);
 again:
 	mutex_lock(&hpfs_i(inode)->i_parent_mutex);
 	mutex_lock(&hpfs_i(dir)->i_mutex);
 	err = -ENOENT;
-	de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh);
+	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
 	if (!de)
 		goto out;
 
@@ -413,22 +413,25 @@
 
 		mutex_unlock(&hpfs_i(dir)->i_mutex);
 		mutex_unlock(&hpfs_i(inode)->i_parent_mutex);
-		d_drop(dentry);
-		spin_lock(&dentry->d_lock);
-		if (atomic_read(&dentry->d_count) > 1 ||
-		    generic_permission(inode, MAY_WRITE, NULL) ||
+		dentry_unhash(dentry);
+		if (!d_unhashed(dentry)) {
+			dput(dentry);
+			unlock_kernel();
+			return -ENOSPC;
+		}
+		if (generic_permission(inode, MAY_WRITE, NULL) ||
 		    !S_ISREG(inode->i_mode) ||
 		    get_write_access(inode)) {
-			spin_unlock(&dentry->d_lock);
 			d_rehash(dentry);
+			dput(dentry);
 		} else {
 			struct iattr newattrs;
-			spin_unlock(&dentry->d_lock);
 			/*printk("HPFS: truncating file before delete.\n");*/
 			newattrs.ia_size = 0;
 			newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
 			err = notify_change(dentry, &newattrs);
 			put_write_access(inode);
+			dput(dentry);
 			if (!err)
 				goto again;
 		}
@@ -451,7 +454,7 @@
 
 static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-	const char *name = dentry->d_name.name;
+	const unsigned char *name = dentry->d_name.name;
 	unsigned len = dentry->d_name.len;
 	struct quad_buffer_head qbh;
 	struct hpfs_dirent *de;
@@ -462,12 +465,12 @@
 	int err;
 	int r;
 
-	hpfs_adjust_length((char *)name, &len);
+	hpfs_adjust_length(name, &len);
 	lock_kernel();
 	mutex_lock(&hpfs_i(inode)->i_parent_mutex);
 	mutex_lock(&hpfs_i(dir)->i_mutex);
 	err = -ENOENT;
-	de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh);
+	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
 	if (!de)
 		goto out;
 
@@ -546,10 +549,10 @@
 static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		struct inode *new_dir, struct dentry *new_dentry)
 {
-	char *old_name = (char *)old_dentry->d_name.name;
-	int old_len = old_dentry->d_name.len;
-	char *new_name = (char *)new_dentry->d_name.name;
-	int new_len = new_dentry->d_name.len;
+	const unsigned char *old_name = old_dentry->d_name.name;
+	unsigned old_len = old_dentry->d_name.len;
+	const unsigned char *new_name = new_dentry->d_name.name;
+	unsigned new_len = new_dentry->d_name.len;
 	struct inode *i = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
 	struct quad_buffer_head qbh, qbh1;
@@ -560,9 +563,9 @@
 	struct buffer_head *bh;
 	struct fnode *fnode;
 	int err;
-	if ((err = hpfs_chk_name((char *)new_name, &new_len))) return err;
+	if ((err = hpfs_chk_name(new_name, &new_len))) return err;
 	err = 0;
-	hpfs_adjust_length((char *)old_name, &old_len);
+	hpfs_adjust_length(old_name, &old_len);
 
 	lock_kernel();
 	/* order doesn't matter, due to VFS exclusion */
@@ -579,7 +582,7 @@
 		goto end1;
 	}
 
-	if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, (char *)old_name, old_len, &dno, &qbh))) {
+	if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
 		hpfs_error(i->i_sb, "lookup succeeded but map dirent failed");
 		err = -ENOENT;
 		goto end1;
@@ -590,7 +593,7 @@
 	if (new_inode) {
 		int r;
 		if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
-			if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, (char *)new_name, new_len, NULL, &qbh1))) {
+			if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, new_name, new_len, NULL, &qbh1))) {
 				clear_nlink(new_inode);
 				copy_de(nde, &de);
 				memcpy(nde->name, new_name, new_len);
@@ -618,7 +621,7 @@
 	}
 	
 	if (new_dir == old_dir)
-		if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, (char *)old_name, old_len, &dno, &qbh))) {
+		if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
 			hpfs_unlock_creation(i->i_sb);
 			hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");
 			err = -ENOENT;
@@ -648,7 +651,7 @@
 		brelse(bh);
 	}
 	hpfs_i(i)->i_conv = hpfs_sb(i->i_sb)->sb_conv;
-	hpfs_decide_conv(i, (char *)new_name, new_len);
+	hpfs_decide_conv(i, new_name, new_len);
 end1:
 	if (old_dir != new_dir)
 		mutex_unlock(&hpfs_i(new_dir)->i_mutex);
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c
index 7239efc..2e4dfa8 100644
--- a/fs/hppfs/hppfs.c
+++ b/fs/hppfs/hppfs.c
@@ -718,7 +718,7 @@
 	struct vfsmount *proc_mnt;
 	int err = -ENOENT;
 
-	proc_mnt = do_kern_mount("proc", 0, "proc", NULL);
+	proc_mnt = mntget(current->nsproxy->pid_ns->proc_mnt);
 	if (IS_ERR(proc_mnt))
 		goto out;
 
diff --git a/fs/inode.c b/fs/inode.c
index 03dfeb2..407bf39 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -8,7 +8,6 @@
 #include <linux/mm.h>
 #include <linux/dcache.h>
 #include <linux/init.h>
-#include <linux/quotaops.h>
 #include <linux/slab.h>
 #include <linux/writeback.h>
 #include <linux/module.h>
@@ -314,7 +313,6 @@
 	BUG_ON(!(inode->i_state & I_FREEING));
 	BUG_ON(inode->i_state & I_CLEAR);
 	inode_sync_wait(inode);
-	vfs_dq_drop(inode);
 	if (inode->i_sb->s_op->clear_inode)
 		inode->i_sb->s_op->clear_inode(inode);
 	if (S_ISBLK(inode->i_mode) && inode->i_bdev)
@@ -1211,8 +1209,6 @@
 
 	if (op->delete_inode) {
 		void (*delete)(struct inode *) = op->delete_inode;
-		if (!is_bad_inode(inode))
-			vfs_dq_init(inode);
 		/* Filesystems implementing their own
 		 * s_op->delete_inode are required to call
 		 * truncate_inode_pages and clear_inode()
diff --git a/fs/internal.h b/fs/internal.h
index e96a166..8a03a54 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -70,6 +70,8 @@
 
 extern void __init mnt_init(void);
 
+extern spinlock_t vfsmount_lock;
+
 /*
  * fs_struct.c
  */
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 4bd8825..2c90e3e 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -862,12 +862,12 @@
 		/* A buffer which has been freed while still being
 		 * journaled by a previous transaction may end up still
 		 * being dirty here, but we want to avoid writing back
-		 * that buffer in the future now that the last use has
-		 * been committed.  That's not only a performance gain,
-		 * it also stops aliasing problems if the buffer is left
-		 * behind for writeback and gets reallocated for another
+		 * that buffer in the future after the "add to orphan"
+		 * operation been committed,  That's not only a performance
+		 * gain, it also stops aliasing problems if the buffer is
+		 * left behind for writeback and gets reallocated for another
 		 * use in a different page. */
-		if (buffer_freed(bh)) {
+		if (buffer_freed(bh) && !jh->b_next_transaction) {
 			clear_buffer_freed(bh);
 			clear_buffer_jbddirty(bh);
 		}
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 006f9ad..5ae71e7 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1398,7 +1398,7 @@
 	 * the case where our storage is so fast that it is more optimal to go
 	 * ahead and force a flush and wait for the transaction to be committed
 	 * than it is to wait for an arbitrary amount of time for new writers to
-	 * join the transaction.  We acheive this by measuring how long it takes
+	 * join the transaction.  We achieve this by measuring how long it takes
 	 * to commit a transaction, and compare it with how long this
 	 * transaction has been running, and if run time < commit time then we
 	 * sleep for the delta and commit.  This greatly helps super fast disks
@@ -1864,6 +1864,21 @@
 	if (!jh)
 		goto zap_buffer_no_jh;
 
+	/*
+	 * We cannot remove the buffer from checkpoint lists until the
+	 * transaction adding inode to orphan list (let's call it T)
+	 * is committed.  Otherwise if the transaction changing the
+	 * buffer would be cleaned from the journal before T is
+	 * committed, a crash will cause that the correct contents of
+	 * the buffer will be lost.  On the other hand we have to
+	 * clear the buffer dirty bit at latest at the moment when the
+	 * transaction marking the buffer as freed in the filesystem
+	 * structures is committed because from that moment on the
+	 * buffer can be reallocated and used by a different page.
+	 * Since the block hasn't been freed yet but the inode has
+	 * already been added to orphan list, it is safe for us to add
+	 * the buffer to BJ_Forget list of the newest transaction.
+	 */
 	transaction = jh->b_transaction;
 	if (transaction == NULL) {
 		/* First case: not on any transaction.  If it
@@ -1929,16 +1944,15 @@
 			goto zap_buffer;
 		}
 		/*
-		 * If it is committing, we simply cannot touch it.  We
-		 * can remove it's next_transaction pointer from the
-		 * running transaction if that is set, but nothing
-		 * else. */
+		 * The buffer is committing, we simply cannot touch
+		 * it. So we just set j_next_transaction to the
+		 * running transaction (if there is one) and mark
+		 * buffer as freed so that commit code knows it should
+		 * clear dirty bits when it is done with the buffer.
+		 */
 		set_buffer_freed(bh);
-		if (jh->b_next_transaction) {
-			J_ASSERT(jh->b_next_transaction ==
-					journal->j_running_transaction);
-			jh->b_next_transaction = NULL;
-		}
+		if (journal->j_running_transaction && buffer_jbddirty(bh))
+			jh->b_next_transaction = journal->j_running_transaction;
 		journal_put_journal_head(jh);
 		spin_unlock(&journal->j_list_lock);
 		jbd_unlock_bh_state(bh);
@@ -2120,7 +2134,7 @@
  */
 void __journal_refile_buffer(struct journal_head *jh)
 {
-	int was_dirty;
+	int was_dirty, jlist;
 	struct buffer_head *bh = jh2bh(jh);
 
 	J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
@@ -2142,8 +2156,13 @@
 	__journal_temp_unlink_buffer(jh);
 	jh->b_transaction = jh->b_next_transaction;
 	jh->b_next_transaction = NULL;
-	__journal_file_buffer(jh, jh->b_transaction,
-				jh->b_modified ? BJ_Metadata : BJ_Reserved);
+	if (buffer_freed(bh))
+		jlist = BJ_Forget;
+	else if (jh->b_modified)
+		jlist = BJ_Metadata;
+	else
+		jlist = BJ_Reserved;
+	__journal_file_buffer(jh, jh->b_transaction, jlist);
 	J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING);
 
 	if (was_dirty)
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 8868493..30beb11 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -507,6 +507,7 @@
 	if (blocknr < journal->j_tail)
 		freed = freed + journal->j_last - journal->j_first;
 
+	trace_jbd2_cleanup_journal_tail(journal, first_tid, blocknr, freed);
 	jbd_debug(1,
 		  "Cleaning journal tail from %d to %d (offset %lu), "
 		  "freeing %lu\n",
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 1bc74b6..671da7f 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -883,8 +883,7 @@
 		spin_unlock(&journal->j_list_lock);
 		bh = jh2bh(jh);
 		jbd_lock_bh_state(bh);
-		J_ASSERT_JH(jh,	jh->b_transaction == commit_transaction ||
-			jh->b_transaction == journal->j_running_transaction);
+		J_ASSERT_JH(jh,	jh->b_transaction == commit_transaction);
 
 		/*
 		 * If there is undo-protected committed data against
@@ -930,12 +929,12 @@
 		/* A buffer which has been freed while still being
 		 * journaled by a previous transaction may end up still
 		 * being dirty here, but we want to avoid writing back
-		 * that buffer in the future now that the last use has
-		 * been committed.  That's not only a performance gain,
-		 * it also stops aliasing problems if the buffer is left
-		 * behind for writeback and gets reallocated for another
+		 * that buffer in the future after the "add to orphan"
+		 * operation been committed,  That's not only a performance
+		 * gain, it also stops aliasing problems if the buffer is
+		 * left behind for writeback and gets reallocated for another
 		 * use in a different page. */
-		if (buffer_freed(bh)) {
+		if (buffer_freed(bh) && !jh->b_next_transaction) {
 			clear_buffer_freed(bh);
 			clear_buffer_jbddirty(bh);
 		}
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index ac0d027..c03d4dc 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -39,6 +39,8 @@
 #include <linux/seq_file.h>
 #include <linux/math64.h>
 #include <linux/hash.h>
+#include <linux/log2.h>
+#include <linux/vmalloc.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/jbd2.h>
@@ -93,6 +95,7 @@
 
 static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
 static void __journal_abort_soft (journal_t *journal, int errno);
+static int jbd2_journal_create_slab(size_t slab_size);
 
 /*
  * Helper function used to manage commit timeouts
@@ -1248,6 +1251,13 @@
 		}
 	}
 
+	/*
+	 * Create a slab for this blocksize
+	 */
+	err = jbd2_journal_create_slab(be32_to_cpu(sb->s_blocksize));
+	if (err)
+		return err;
+
 	/* Let the recovery code check whether it needs to recover any
 	 * data from the journal. */
 	if (jbd2_journal_recover(journal))
@@ -1807,6 +1817,127 @@
 }
 
 /*
+ * JBD memory management
+ *
+ * These functions are used to allocate block-sized chunks of memory
+ * used for making copies of buffer_head data.  Very often it will be
+ * page-sized chunks of data, but sometimes it will be in
+ * sub-page-size chunks.  (For example, 16k pages on Power systems
+ * with a 4k block file system.)  For blocks smaller than a page, we
+ * use a SLAB allocator.  There are slab caches for each block size,
+ * which are allocated at mount time, if necessary, and we only free
+ * (all of) the slab caches when/if the jbd2 module is unloaded.  For
+ * this reason we don't need to a mutex to protect access to
+ * jbd2_slab[] allocating or releasing memory; only in
+ * jbd2_journal_create_slab().
+ */
+#define JBD2_MAX_SLABS 8
+static struct kmem_cache *jbd2_slab[JBD2_MAX_SLABS];
+static DECLARE_MUTEX(jbd2_slab_create_sem);
+
+static const char *jbd2_slab_names[JBD2_MAX_SLABS] = {
+	"jbd2_1k", "jbd2_2k", "jbd2_4k", "jbd2_8k",
+	"jbd2_16k", "jbd2_32k", "jbd2_64k", "jbd2_128k"
+};
+
+
+static void jbd2_journal_destroy_slabs(void)
+{
+	int i;
+
+	for (i = 0; i < JBD2_MAX_SLABS; i++) {
+		if (jbd2_slab[i])
+			kmem_cache_destroy(jbd2_slab[i]);
+		jbd2_slab[i] = NULL;
+	}
+}
+
+static int jbd2_journal_create_slab(size_t size)
+{
+	int i = order_base_2(size) - 10;
+	size_t slab_size;
+
+	if (size == PAGE_SIZE)
+		return 0;
+
+	if (i >= JBD2_MAX_SLABS)
+		return -EINVAL;
+
+	if (unlikely(i < 0))
+		i = 0;
+	down(&jbd2_slab_create_sem);
+	if (jbd2_slab[i]) {
+		up(&jbd2_slab_create_sem);
+		return 0;	/* Already created */
+	}
+
+	slab_size = 1 << (i+10);
+	jbd2_slab[i] = kmem_cache_create(jbd2_slab_names[i], slab_size,
+					 slab_size, 0, NULL);
+	up(&jbd2_slab_create_sem);
+	if (!jbd2_slab[i]) {
+		printk(KERN_EMERG "JBD2: no memory for jbd2_slab cache\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static struct kmem_cache *get_slab(size_t size)
+{
+	int i = order_base_2(size) - 10;
+
+	BUG_ON(i >= JBD2_MAX_SLABS);
+	if (unlikely(i < 0))
+		i = 0;
+	BUG_ON(jbd2_slab[i] == 0);
+	return jbd2_slab[i];
+}
+
+void *jbd2_alloc(size_t size, gfp_t flags)
+{
+	void *ptr;
+
+	BUG_ON(size & (size-1)); /* Must be a power of 2 */
+
+	flags |= __GFP_REPEAT;
+	if (size == PAGE_SIZE)
+		ptr = (void *)__get_free_pages(flags, 0);
+	else if (size > PAGE_SIZE) {
+		int order = get_order(size);
+
+		if (order < 3)
+			ptr = (void *)__get_free_pages(flags, order);
+		else
+			ptr = vmalloc(size);
+	} else
+		ptr = kmem_cache_alloc(get_slab(size), flags);
+
+	/* Check alignment; SLUB has gotten this wrong in the past,
+	 * and this can lead to user data corruption! */
+	BUG_ON(((unsigned long) ptr) & (size-1));
+
+	return ptr;
+}
+
+void jbd2_free(void *ptr, size_t size)
+{
+	if (size == PAGE_SIZE) {
+		free_pages((unsigned long)ptr, 0);
+		return;
+	}
+	if (size > PAGE_SIZE) {
+		int order = get_order(size);
+
+		if (order < 3)
+			free_pages((unsigned long)ptr, order);
+		else
+			vfree(ptr);
+		return;
+	}
+	kmem_cache_free(get_slab(size), ptr);
+};
+
+/*
  * Journal_head storage management
  */
 static struct kmem_cache *jbd2_journal_head_cache;
@@ -2204,6 +2335,7 @@
 	jbd2_journal_destroy_revoke_caches();
 	jbd2_journal_destroy_jbd2_journal_head_cache();
 	jbd2_journal_destroy_handle_cache();
+	jbd2_journal_destroy_slabs();
 }
 
 static int __init journal_init(void)
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index a051270..bfc70f5 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -1727,6 +1727,21 @@
 	if (!jh)
 		goto zap_buffer_no_jh;
 
+	/*
+	 * We cannot remove the buffer from checkpoint lists until the
+	 * transaction adding inode to orphan list (let's call it T)
+	 * is committed.  Otherwise if the transaction changing the
+	 * buffer would be cleaned from the journal before T is
+	 * committed, a crash will cause that the correct contents of
+	 * the buffer will be lost.  On the other hand we have to
+	 * clear the buffer dirty bit at latest at the moment when the
+	 * transaction marking the buffer as freed in the filesystem
+	 * structures is committed because from that moment on the
+	 * buffer can be reallocated and used by a different page.
+	 * Since the block hasn't been freed yet but the inode has
+	 * already been added to orphan list, it is safe for us to add
+	 * the buffer to BJ_Forget list of the newest transaction.
+	 */
 	transaction = jh->b_transaction;
 	if (transaction == NULL) {
 		/* First case: not on any transaction.  If it
@@ -1783,16 +1798,15 @@
 	} else if (transaction == journal->j_committing_transaction) {
 		JBUFFER_TRACE(jh, "on committing transaction");
 		/*
-		 * If it is committing, we simply cannot touch it.  We
-		 * can remove it's next_transaction pointer from the
-		 * running transaction if that is set, but nothing
-		 * else. */
+		 * The buffer is committing, we simply cannot touch
+		 * it. So we just set j_next_transaction to the
+		 * running transaction (if there is one) and mark
+		 * buffer as freed so that commit code knows it should
+		 * clear dirty bits when it is done with the buffer.
+		 */
 		set_buffer_freed(bh);
-		if (jh->b_next_transaction) {
-			J_ASSERT(jh->b_next_transaction ==
-					journal->j_running_transaction);
-			jh->b_next_transaction = NULL;
-		}
+		if (journal->j_running_transaction && buffer_jbddirty(bh))
+			jh->b_next_transaction = journal->j_running_transaction;
 		jbd2_journal_put_journal_head(jh);
 		spin_unlock(&journal->j_list_lock);
 		jbd_unlock_bh_state(bh);
@@ -1969,7 +1983,7 @@
  */
 void __jbd2_journal_refile_buffer(struct journal_head *jh)
 {
-	int was_dirty;
+	int was_dirty, jlist;
 	struct buffer_head *bh = jh2bh(jh);
 
 	J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
@@ -1991,8 +2005,13 @@
 	__jbd2_journal_temp_unlink_buffer(jh);
 	jh->b_transaction = jh->b_next_transaction;
 	jh->b_next_transaction = NULL;
-	__jbd2_journal_file_buffer(jh, jh->b_transaction,
-				jh->b_modified ? BJ_Metadata : BJ_Reserved);
+	if (buffer_freed(bh))
+		jlist = BJ_Forget;
+	else if (jh->b_modified)
+		jlist = BJ_Metadata;
+	else
+		jlist = BJ_Reserved;
+	__jbd2_journal_file_buffer(jh, jh->b_transaction, jlist);
 	J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING);
 
 	if (was_dirty)
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index d66477c..2131697 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -20,7 +20,6 @@
 
 #include <linux/sched.h>
 #include <linux/fs.h>
-#include <linux/quotaops.h>
 #include <linux/posix_acl_xattr.h>
 #include "jfs_incore.h"
 #include "jfs_txnmgr.h"
@@ -174,7 +173,7 @@
 	return rc;
 }
 
-static int jfs_acl_chmod(struct inode *inode)
+int jfs_acl_chmod(struct inode *inode)
 {
 	struct posix_acl *acl, *clone;
 	int rc;
@@ -205,26 +204,3 @@
 	posix_acl_release(clone);
 	return rc;
 }
-
-int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
-{
-	struct inode *inode = dentry->d_inode;
-	int rc;
-
-	rc = inode_change_ok(inode, iattr);
-	if (rc)
-		return rc;
-
-	if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
-	    (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) {
-		if (vfs_dq_transfer(inode, iattr))
-			return -EDQUOT;
-	}
-
-	rc = inode_setattr(inode, iattr);
-
-	if (!rc && (iattr->ia_valid & ATTR_MODE))
-		rc = jfs_acl_chmod(inode);
-
-	return rc;
-}
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index 2b70fa7..14ba982 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_inode.h"
 #include "jfs_dmap.h"
@@ -47,7 +48,7 @@
 {
 	int rc;
 
-	if ((rc = generic_file_open(inode, file)))
+	if ((rc = dquot_file_open(inode, file)))
 		return rc;
 
 	/*
@@ -88,14 +89,40 @@
 	return 0;
 }
 
+int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+	struct inode *inode = dentry->d_inode;
+	int rc;
+
+	rc = inode_change_ok(inode, iattr);
+	if (rc)
+		return rc;
+
+	if (iattr->ia_valid & ATTR_SIZE)
+		dquot_initialize(inode);
+	if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
+	    (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) {
+		rc = dquot_transfer(inode, iattr);
+		if (rc)
+			return rc;
+	}
+
+	rc = inode_setattr(inode, iattr);
+
+	if (!rc && (iattr->ia_valid & ATTR_MODE))
+		rc = jfs_acl_chmod(inode);
+
+	return rc;
+}
+
 const struct inode_operations jfs_file_inode_operations = {
 	.truncate	= jfs_truncate,
 	.setxattr	= jfs_setxattr,
 	.getxattr	= jfs_getxattr,
 	.listxattr	= jfs_listxattr,
 	.removexattr	= jfs_removexattr,
-#ifdef CONFIG_JFS_POSIX_ACL
 	.setattr	= jfs_setattr,
+#ifdef CONFIG_JFS_POSIX_ACL
 	.check_acl	= jfs_check_acl,
 #endif
 };
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index b2ae190..9dd1262 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -22,6 +22,7 @@
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
+#include <linux/writeback.h>
 #include "jfs_incore.h"
 #include "jfs_inode.h"
 #include "jfs_filsys.h"
@@ -120,8 +121,10 @@
 	return rc;
 }
 
-int jfs_write_inode(struct inode *inode, int wait)
+int jfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
+	int wait = wbc->sync_mode == WB_SYNC_ALL;
+
 	if (test_cflag(COMMIT_Nolink, inode))
 		return 0;
 	/*
@@ -146,6 +149,9 @@
 {
 	jfs_info("In jfs_delete_inode, inode = 0x%p", inode);
 
+	if (!is_bad_inode(inode))
+		dquot_initialize(inode);
+
 	if (!is_bad_inode(inode) &&
 	    (JFS_IP(inode)->fileset == FILESYSTEM_I)) {
 		truncate_inode_pages(&inode->i_data, 0);
@@ -158,9 +164,9 @@
 		/*
 		 * Free the inode from the quota allocation.
 		 */
-		vfs_dq_init(inode);
-		vfs_dq_free_inode(inode);
-		vfs_dq_drop(inode);
+		dquot_initialize(inode);
+		dquot_free_inode(inode);
+		dquot_drop(inode);
 	}
 
 	clear_inode(inode);
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index b07bd41..54e0755 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -22,7 +22,7 @@
 
 int jfs_check_acl(struct inode *, int);
 int jfs_init_acl(tid_t, struct inode *, struct inode *);
-int jfs_setattr(struct dentry *, struct iattr *);
+int jfs_acl_chmod(struct inode *inode);
 
 #else
 
@@ -32,5 +32,10 @@
 	return 0;
 }
 
+static inline int jfs_acl_chmod(struct inode *inode)
+{
+	return 0;
+}
+
 #endif
 #endif		/* _H_JFS_ACL */
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 925871e..0e4623b 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -381,10 +381,10 @@
 		 * It's time to move the inline table to an external
 		 * page and begin to build the xtree
 		 */
-		if (vfs_dq_alloc_block(ip, sbi->nbperpage))
+		if (dquot_alloc_block(ip, sbi->nbperpage))
 			goto clean_up;
 		if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr)) {
-			vfs_dq_free_block(ip, sbi->nbperpage);
+			dquot_free_block(ip, sbi->nbperpage);
 			goto clean_up;
 		}
 
@@ -408,7 +408,7 @@
 			memcpy(&jfs_ip->i_dirtable, temp_table,
 			       sizeof (temp_table));
 			dbFree(ip, xaddr, sbi->nbperpage);
-			vfs_dq_free_block(ip, sbi->nbperpage);
+			dquot_free_block(ip, sbi->nbperpage);
 			goto clean_up;
 		}
 		ip->i_size = PSIZE;
@@ -1027,10 +1027,9 @@
 			n = xlen;
 
 		/* Allocate blocks to quota. */
-		if (vfs_dq_alloc_block(ip, n)) {
-			rc = -EDQUOT;
+		rc = dquot_alloc_block(ip, n);
+		if (rc)
 			goto extendOut;
-		}
 		quota_allocation += n;
 
 		if ((rc = dbReAlloc(sbi->ipbmap, xaddr, (s64) xlen,
@@ -1308,7 +1307,7 @@
 
 	/* Rollback quota allocation */
 	if (rc && quota_allocation)
-		vfs_dq_free_block(ip, quota_allocation);
+		dquot_free_block(ip, quota_allocation);
 
       dtSplitUp_Exit:
 
@@ -1369,9 +1368,10 @@
 		return -EIO;
 
 	/* Allocate blocks to quota. */
-	if (vfs_dq_alloc_block(ip, lengthPXD(pxd))) {
+	rc = dquot_alloc_block(ip, lengthPXD(pxd));
+	if (rc) {
 		release_metapage(rmp);
-		return -EDQUOT;
+		return rc;
 	}
 
 	jfs_info("dtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
@@ -1892,6 +1892,7 @@
 	struct dt_lock *dtlck;
 	struct tlock *tlck;
 	struct lv *lv;
+	int rc;
 
 	/* get split root page */
 	smp = split->mp;
@@ -1916,9 +1917,10 @@
 	rp = rmp->data;
 
 	/* Allocate blocks to quota. */
-	if (vfs_dq_alloc_block(ip, lengthPXD(pxd))) {
+	rc = dquot_alloc_block(ip, lengthPXD(pxd));
+	if (rc) {
 		release_metapage(rmp);
-		return -EDQUOT;
+		return rc;
 	}
 
 	BT_MARK_DIRTY(rmp, ip);
@@ -2287,7 +2289,7 @@
 	xlen = lengthPXD(&fp->header.self);
 
 	/* Free quota allocation. */
-	vfs_dq_free_block(ip, xlen);
+	dquot_free_block(ip, xlen);
 
 	/* free/invalidate its buffer page */
 	discard_metapage(fmp);
@@ -2363,7 +2365,7 @@
 				xlen = lengthPXD(&p->header.self);
 
 				/* Free quota allocation */
-				vfs_dq_free_block(ip, xlen);
+				dquot_free_block(ip, xlen);
 
 				/* free/invalidate its buffer page */
 				discard_metapage(mp);
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 41d6045..5d3bbd1 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -141,10 +141,11 @@
 	}
 
 	/* Allocate blocks to quota. */
-	if (vfs_dq_alloc_block(ip, nxlen)) {
+	rc = dquot_alloc_block(ip, nxlen);
+	if (rc) {
 		dbFree(ip, nxaddr, (s64) nxlen);
 		mutex_unlock(&JFS_IP(ip)->commit_mutex);
-		return -EDQUOT;
+		return rc;
 	}
 
 	/* determine the value of the extent flag */
@@ -164,7 +165,7 @@
 	 */
 	if (rc) {
 		dbFree(ip, nxaddr, nxlen);
-		vfs_dq_free_block(ip, nxlen);
+		dquot_free_block(ip, nxlen);
 		mutex_unlock(&JFS_IP(ip)->commit_mutex);
 		return (rc);
 	}
@@ -256,10 +257,11 @@
 		goto exit;
 
 	/* Allocat blocks to quota. */
-	if (vfs_dq_alloc_block(ip, nxlen)) {
+	rc = dquot_alloc_block(ip, nxlen);
+	if (rc) {
 		dbFree(ip, nxaddr, (s64) nxlen);
 		mutex_unlock(&JFS_IP(ip)->commit_mutex);
-		return -EDQUOT;
+		return rc;
 	}
 
 	delta = nxlen - xlen;
@@ -297,7 +299,7 @@
 		/* extend the extent */
 		if ((rc = xtExtend(0, ip, xoff + xlen, (int) nextend, 0))) {
 			dbFree(ip, xaddr + xlen, delta);
-			vfs_dq_free_block(ip, nxlen);
+			dquot_free_block(ip, nxlen);
 			goto exit;
 		}
 	} else {
@@ -308,7 +310,7 @@
 		 */
 		if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) {
 			dbFree(ip, nxaddr, nxlen);
-			vfs_dq_free_block(ip, nxlen);
+			dquot_free_block(ip, nxlen);
 			goto exit;
 		}
 	}
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index dc0e021..829921b 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -116,10 +116,10 @@
 	/*
 	 * Allocate inode to quota.
 	 */
-	if (vfs_dq_alloc_inode(inode)) {
-		rc = -EDQUOT;
+	dquot_initialize(inode);
+	rc = dquot_alloc_inode(inode);
+	if (rc)
 		goto fail_drop;
-	}
 
 	inode->i_mode = mode;
 	/* inherit flags from parent */
@@ -162,7 +162,7 @@
 	return inode;
 
 fail_drop:
-	vfs_dq_drop(inode);
+	dquot_drop(inode);
 	inode->i_flags |= S_NOQUOTA;
 fail_unlock:
 	inode->i_nlink = 0;
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 1eff7db..79e2c79 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -26,7 +26,7 @@
 extern long jfs_compat_ioctl(struct file *, unsigned int, unsigned long);
 extern struct inode *jfs_iget(struct super_block *, unsigned long);
 extern int jfs_commit_inode(struct inode *, int);
-extern int jfs_write_inode(struct inode*, int);
+extern int jfs_write_inode(struct inode *, struct writeback_control *);
 extern void jfs_delete_inode(struct inode *);
 extern void jfs_dirty_inode(struct inode *);
 extern void jfs_truncate(struct inode *);
@@ -40,6 +40,7 @@
 	int fh_len, int fh_type);
 extern void jfs_set_inode_flags(struct inode *);
 extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
+extern int jfs_setattr(struct dentry *, struct iattr *);
 
 extern const struct address_space_operations jfs_aops;
 extern const struct inode_operations jfs_dir_inode_operations;
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index d654a64..6c50871 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -585,10 +585,10 @@
 			hint = addressXAD(xad) + lengthXAD(xad) - 1;
 		} else
 			hint = 0;
-		if ((rc = vfs_dq_alloc_block(ip, xlen)))
+		if ((rc = dquot_alloc_block(ip, xlen)))
 			goto out;
 		if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr))) {
-			vfs_dq_free_block(ip, xlen);
+			dquot_free_block(ip, xlen);
 			goto out;
 		}
 	}
@@ -617,7 +617,7 @@
 			/* undo data extent allocation */
 			if (*xaddrp == 0) {
 				dbFree(ip, xaddr, (s64) xlen);
-				vfs_dq_free_block(ip, xlen);
+				dquot_free_block(ip, xlen);
 			}
 			return rc;
 		}
@@ -985,10 +985,9 @@
 	rbn = addressPXD(pxd);
 
 	/* Allocate blocks to quota. */
-	if (vfs_dq_alloc_block(ip, lengthPXD(pxd))) {
-		rc = -EDQUOT;
+	rc = dquot_alloc_block(ip, lengthPXD(pxd));
+	if (rc)
 		goto clean_up;
-	}
 
 	quota_allocation += lengthPXD(pxd);
 
@@ -1195,7 +1194,7 @@
 
 	/* Rollback quota allocation. */
 	if (quota_allocation)
-		vfs_dq_free_block(ip, quota_allocation);
+		dquot_free_block(ip, quota_allocation);
 
 	return (rc);
 }
@@ -1235,6 +1234,7 @@
 	struct pxdlist *pxdlist;
 	struct tlock *tlck;
 	struct xtlock *xtlck;
+	int rc;
 
 	sp = &JFS_IP(ip)->i_xtroot;
 
@@ -1252,9 +1252,10 @@
 		return -EIO;
 
 	/* Allocate blocks to quota. */
-	if (vfs_dq_alloc_block(ip, lengthPXD(pxd))) {
+	rc = dquot_alloc_block(ip, lengthPXD(pxd));
+	if (rc) {
 		release_metapage(rmp);
-		return -EDQUOT;
+		return rc;
 	}
 
 	jfs_info("xtSplitRoot: ip:0x%p rmp:0x%p", ip, rmp);
@@ -3680,7 +3681,7 @@
 		ip->i_size = newsize;
 
 	/* update quota allocation to reflect freed blocks */
-	vfs_dq_free_block(ip, nfreed);
+	dquot_free_block(ip, nfreed);
 
 	/*
 	 * free tlock of invalidated pages
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index c79a4270..4a3e9f3 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -85,6 +85,8 @@
 
 	jfs_info("jfs_create: dip:0x%p name:%s", dip, dentry->d_name.name);
 
+	dquot_initialize(dip);
+
 	/*
 	 * search parent directory for entry/freespace
 	 * (dtSearch() returns parent directory page pinned)
@@ -215,6 +217,8 @@
 
 	jfs_info("jfs_mkdir: dip:0x%p name:%s", dip, dentry->d_name.name);
 
+	dquot_initialize(dip);
+
 	/* link count overflow on parent directory ? */
 	if (dip->i_nlink == JFS_LINK_MAX) {
 		rc = -EMLINK;
@@ -356,7 +360,8 @@
 	jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);
 
 	/* Init inode for quota operations. */
-	vfs_dq_init(ip);
+	dquot_initialize(dip);
+	dquot_initialize(ip);
 
 	/* directory must be empty to be removed */
 	if (!dtEmpty(ip)) {
@@ -483,7 +488,8 @@
 	jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name);
 
 	/* Init inode for quota operations. */
-	vfs_dq_init(ip);
+	dquot_initialize(dip);
+	dquot_initialize(ip);
 
 	if ((rc = get_UCSname(&dname, dentry)))
 		goto out;
@@ -805,6 +811,8 @@
 	if (ip->i_nlink == 0)
 		return -ENOENT;
 
+	dquot_initialize(dir);
+
 	tid = txBegin(ip->i_sb, 0);
 
 	mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT);
@@ -896,6 +904,8 @@
 
 	jfs_info("jfs_symlink: dip:0x%p name:%s", dip, name);
 
+	dquot_initialize(dip);
+
 	ssize = strlen(name) + 1;
 
 	/*
@@ -1087,6 +1097,9 @@
 	jfs_info("jfs_rename: %s %s", old_dentry->d_name.name,
 		 new_dentry->d_name.name);
 
+	dquot_initialize(old_dir);
+	dquot_initialize(new_dir);
+
 	old_ip = old_dentry->d_inode;
 	new_ip = new_dentry->d_inode;
 
@@ -1136,7 +1149,7 @@
 	} else if (new_ip) {
 		IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL);
 		/* Init inode for quota operations. */
-		vfs_dq_init(new_ip);
+		dquot_initialize(new_ip);
 	}
 
 	/*
@@ -1360,6 +1373,8 @@
 
 	jfs_info("jfs_mknod: %s", dentry->d_name.name);
 
+	dquot_initialize(dir);
+
 	if ((rc = get_UCSname(&dname, dentry)))
 		goto out;
 
@@ -1541,8 +1556,8 @@
 	.getxattr	= jfs_getxattr,
 	.listxattr	= jfs_listxattr,
 	.removexattr	= jfs_removexattr,
-#ifdef CONFIG_JFS_POSIX_ACL
 	.setattr	= jfs_setattr,
+#ifdef CONFIG_JFS_POSIX_ACL
 	.check_acl	= jfs_check_acl,
 #endif
 };
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index d929a82..266699de 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -131,6 +131,11 @@
 	kmem_cache_free(jfs_inode_cachep, ji);
 }
 
+static void jfs_clear_inode(struct inode *inode)
+{
+	dquot_drop(inode);
+}
+
 static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct jfs_sb_info *sbi = JFS_SBI(dentry->d_sb);
@@ -745,6 +750,7 @@
 	.dirty_inode	= jfs_dirty_inode,
 	.write_inode	= jfs_write_inode,
 	.delete_inode	= jfs_delete_inode,
+	.clear_inode	= jfs_clear_inode,
 	.put_super	= jfs_put_super,
 	.sync_fs	= jfs_sync_fs,
 	.freeze_fs	= jfs_freeze,
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index fad3645..1f594ab 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -260,14 +260,14 @@
 	nblocks = (size + (sb->s_blocksize - 1)) >> sb->s_blocksize_bits;
 
 	/* Allocate new blocks to quota. */
-	if (vfs_dq_alloc_block(ip, nblocks)) {
-		return -EDQUOT;
-	}
+	rc = dquot_alloc_block(ip, nblocks);
+	if (rc)
+		return rc;
 
 	rc = dbAlloc(ip, INOHINT(ip), nblocks, &blkno);
 	if (rc) {
 		/*Rollback quota allocation. */
-		vfs_dq_free_block(ip, nblocks);
+		dquot_free_block(ip, nblocks);
 		return rc;
 	}
 
@@ -332,7 +332,7 @@
 
       failed:
 	/* Rollback quota allocation. */
-	vfs_dq_free_block(ip, nblocks);
+	dquot_free_block(ip, nblocks);
 
 	dbFree(ip, blkno, nblocks);
 	return rc;
@@ -538,7 +538,8 @@
 
 	if (blocks_needed > current_blocks) {
 		/* Allocate new blocks to quota. */
-		if (vfs_dq_alloc_block(inode, blocks_needed))
+		rc = dquot_alloc_block(inode, blocks_needed);
+		if (rc)
 			return -EDQUOT;
 
 		quota_allocation = blocks_needed;
@@ -602,7 +603,7 @@
       clean_up:
 	/* Rollback quota allocation */
 	if (quota_allocation)
-		vfs_dq_free_block(inode, quota_allocation);
+		dquot_free_block(inode, quota_allocation);
 
 	return (rc);
 }
@@ -677,7 +678,7 @@
 
 	/* If old blocks exist, they must be removed from quota allocation. */
 	if (old_blocks)
-		vfs_dq_free_block(inode, old_blocks);
+		dquot_free_block(inode, old_blocks);
 
 	inode->i_ctime = CURRENT_TIME;
 
diff --git a/fs/libfs.c b/fs/libfs.c
index 6e8d17e..9e50bcf 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -338,28 +338,14 @@
 	return 0;
 }
 
-int simple_prepare_write(struct file *file, struct page *page,
-			unsigned from, unsigned to)
-{
-	if (!PageUptodate(page)) {
-		if (to - from != PAGE_CACHE_SIZE)
-			zero_user_segments(page,
-				0, from,
-				to, PAGE_CACHE_SIZE);
-	}
-	return 0;
-}
-
 int simple_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned flags,
 			struct page **pagep, void **fsdata)
 {
 	struct page *page;
 	pgoff_t index;
-	unsigned from;
 
 	index = pos >> PAGE_CACHE_SHIFT;
-	from = pos & (PAGE_CACHE_SIZE - 1);
 
 	page = grab_cache_page_write_begin(mapping, index, flags);
 	if (!page)
@@ -367,14 +353,48 @@
 
 	*pagep = page;
 
-	return simple_prepare_write(file, page, from, from+len);
+	if (!PageUptodate(page) && (len != PAGE_CACHE_SIZE)) {
+		unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+
+		zero_user_segments(page, 0, from, from + len, PAGE_CACHE_SIZE);
+	}
+	return 0;
 }
 
-static int simple_commit_write(struct file *file, struct page *page,
-			       unsigned from, unsigned to)
+/**
+ * simple_write_end - .write_end helper for non-block-device FSes
+ * @available: See .write_end of address_space_operations
+ * @file: 		"
+ * @mapping: 		"
+ * @pos: 		"
+ * @len: 		"
+ * @copied: 		"
+ * @page: 		"
+ * @fsdata: 		"
+ *
+ * simple_write_end does the minimum needed for updating a page after writing is
+ * done. It has the same API signature as the .write_end of
+ * address_space_operations vector. So it can just be set onto .write_end for
+ * FSes that don't need any other processing. i_mutex is assumed to be held.
+ * Block based filesystems should use generic_write_end().
+ * NOTE: Even though i_size might get updated by this function, mark_inode_dirty
+ * is not called, so a filesystem that actually does store data in .write_inode
+ * should extend on what's done here with a call to mark_inode_dirty() in the
+ * case that i_size has changed.
+ */
+int simple_write_end(struct file *file, struct address_space *mapping,
+			loff_t pos, unsigned len, unsigned copied,
+			struct page *page, void *fsdata)
 {
 	struct inode *inode = page->mapping->host;
-	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+	loff_t last_pos = pos + copied;
+
+	/* zero the stale part of the page if we did a short copy */
+	if (copied < len) {
+		unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+
+		zero_user(page, from + copied, len - copied);
+	}
 
 	if (!PageUptodate(page))
 		SetPageUptodate(page);
@@ -382,28 +402,10 @@
 	 * No need to use i_size_read() here, the i_size
 	 * cannot change under us because we hold the i_mutex.
 	 */
-	if (pos > inode->i_size)
-		i_size_write(inode, pos);
+	if (last_pos > inode->i_size)
+		i_size_write(inode, last_pos);
+
 	set_page_dirty(page);
-	return 0;
-}
-
-int simple_write_end(struct file *file, struct address_space *mapping,
-			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
-{
-	unsigned from = pos & (PAGE_CACHE_SIZE - 1);
-
-	/* zero the stale part of the page if we did a short copy */
-	if (copied < len) {
-		void *kaddr = kmap_atomic(page, KM_USER0);
-		memset(kaddr + from + copied, 0, len - copied);
-		flush_dcache_page(page);
-		kunmap_atomic(kaddr, KM_USER0);
-	}
-
-	simple_commit_write(file, page, from, from+copied);
-
 	unlock_page(page);
 	page_cache_release(page);
 
@@ -853,7 +855,6 @@
 EXPORT_SYMBOL(simple_link);
 EXPORT_SYMBOL(simple_lookup);
 EXPORT_SYMBOL(simple_pin_fs);
-EXPORT_UNUSED_SYMBOL(simple_prepare_write);
 EXPORT_SYMBOL(simple_readpage);
 EXPORT_SYMBOL(simple_release_fs);
 EXPORT_SYMBOL(simple_rename);
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 4600c20..bb464d1210 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -479,8 +479,8 @@
 			}
 		}
 	}
-
 	mutex_unlock(&nlm_host_mutex);
+	nsm_release(nsm);
 }
 
 /*
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index f956651..fefa4df 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -349,9 +349,9 @@
  * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle
  * @info: pointer to NLMPROC_SM_NOTIFY arguments
  *
- * Returns a matching nsm_handle if found in the nsm cache; the returned
- * nsm_handle's reference count is bumped and sm_monitored is cleared.
- * Otherwise returns NULL if some error occurred.
+ * Returns a matching nsm_handle if found in the nsm cache. The returned
+ * nsm_handle's reference count is bumped. Otherwise returns NULL if some
+ * error occurred.
  */
 struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info)
 {
@@ -370,12 +370,6 @@
 	atomic_inc(&cached->sm_count);
 	spin_unlock(&nsm_lock);
 
-	/*
-	 * During subsequent lock activity, force a fresh
-	 * notification to be set up for this host.
-	 */
-	cached->sm_monitored = 0;
-
 	dprintk("lockd: host %s (%s) rebooted, cnt %d\n",
 			cached->sm_name, cached->sm_addrbuf,
 			atomic_read(&cached->sm_count));
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index e50cfa3..7d15051 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -243,11 +243,9 @@
 	if (err < 0)
 		goto out_err;
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	err = create_lockd_family(serv, PF_INET6);
 	if (err < 0 && err != -EAFNOSUPPORT)
 		goto out_err;
-#endif	/* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
 
 	warned = 0;
 	return 0;
diff --git a/fs/locks.c b/fs/locks.c
index a8794f2..ab24d49 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1182,8 +1182,9 @@
 	struct file_lock *fl;
 	unsigned long break_time;
 	int i_have_this_lease = 0;
+	int want_write = (mode & O_ACCMODE) != O_RDONLY;
 
-	new_fl = lease_alloc(NULL, mode & FMODE_WRITE ? F_WRLCK : F_RDLCK);
+	new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK);
 
 	lock_kernel();
 
@@ -1197,7 +1198,7 @@
 		if (fl->fl_owner == current->files)
 			i_have_this_lease = 1;
 
-	if (mode & FMODE_WRITE) {
+	if (want_write) {
 		/* If we want write access, we have to revoke any lease. */
 		future = F_UNLCK | F_INPROGRESS;
 	} else if (flock->fl_type & F_INPROGRESS) {
@@ -1454,7 +1455,7 @@
  *	leases held by processes on this node.
  *
  *	There is also no break_lease method; filesystems that
- *	handle their own leases shoud break leases themselves from the
+ *	handle their own leases should break leases themselves from the
  *	filesystem's open, create, and (on truncate) setattr methods.
  *
  *	Warning: the only current setlease methods exist only to disable
diff --git a/fs/logfs/Kconfig b/fs/logfs/Kconfig
new file mode 100644
index 0000000..daf9a9b
--- /dev/null
+++ b/fs/logfs/Kconfig
@@ -0,0 +1,17 @@
+config LOGFS
+	tristate "LogFS file system (EXPERIMENTAL)"
+	depends on (MTD || BLOCK) && EXPERIMENTAL
+	select ZLIB_INFLATE
+	select ZLIB_DEFLATE
+	select CRC32
+	select BTREE
+	help
+	  Flash filesystem aimed to scale efficiently to large devices.
+	  In comparison to JFFS2 it offers significantly faster mount
+	  times and potentially less RAM usage, although the latter has
+	  not been measured yet.
+
+	  In its current state it is still very experimental and should
+	  not be used for other than testing purposes.
+
+	  If unsure, say N.
diff --git a/fs/logfs/Makefile b/fs/logfs/Makefile
new file mode 100644
index 0000000..4820027
--- /dev/null
+++ b/fs/logfs/Makefile
@@ -0,0 +1,13 @@
+obj-$(CONFIG_LOGFS)	+= logfs.o
+
+logfs-y	+= compr.o
+logfs-y	+= dir.o
+logfs-y	+= file.o
+logfs-y	+= gc.o
+logfs-y	+= inode.o
+logfs-y	+= journal.o
+logfs-y	+= readwrite.o
+logfs-y	+= segment.o
+logfs-y	+= super.o
+logfs-$(CONFIG_BLOCK)	+= dev_bdev.o
+logfs-$(CONFIG_MTD)	+= dev_mtd.o
diff --git a/fs/logfs/compr.c b/fs/logfs/compr.c
new file mode 100644
index 0000000..44bbfd2
--- /dev/null
+++ b/fs/logfs/compr.c
@@ -0,0 +1,95 @@
+/*
+ * fs/logfs/compr.c	- compression routines
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/vmalloc.h>
+#include <linux/zlib.h>
+
+#define COMPR_LEVEL 3
+
+static DEFINE_MUTEX(compr_mutex);
+static struct z_stream_s stream;
+
+int logfs_compress(void *in, void *out, size_t inlen, size_t outlen)
+{
+	int err, ret;
+
+	ret = -EIO;
+	mutex_lock(&compr_mutex);
+	err = zlib_deflateInit(&stream, COMPR_LEVEL);
+	if (err != Z_OK)
+		goto error;
+
+	stream.next_in = in;
+	stream.avail_in = inlen;
+	stream.total_in = 0;
+	stream.next_out = out;
+	stream.avail_out = outlen;
+	stream.total_out = 0;
+
+	err = zlib_deflate(&stream, Z_FINISH);
+	if (err != Z_STREAM_END)
+		goto error;
+
+	err = zlib_deflateEnd(&stream);
+	if (err != Z_OK)
+		goto error;
+
+	if (stream.total_out >= stream.total_in)
+		goto error;
+
+	ret = stream.total_out;
+error:
+	mutex_unlock(&compr_mutex);
+	return ret;
+}
+
+int logfs_uncompress(void *in, void *out, size_t inlen, size_t outlen)
+{
+	int err, ret;
+
+	ret = -EIO;
+	mutex_lock(&compr_mutex);
+	err = zlib_inflateInit(&stream);
+	if (err != Z_OK)
+		goto error;
+
+	stream.next_in = in;
+	stream.avail_in = inlen;
+	stream.total_in = 0;
+	stream.next_out = out;
+	stream.avail_out = outlen;
+	stream.total_out = 0;
+
+	err = zlib_inflate(&stream, Z_FINISH);
+	if (err != Z_STREAM_END)
+		goto error;
+
+	err = zlib_inflateEnd(&stream);
+	if (err != Z_OK)
+		goto error;
+
+	ret = 0;
+error:
+	mutex_unlock(&compr_mutex);
+	return ret;
+}
+
+int __init logfs_compr_init(void)
+{
+	size_t size = max(zlib_deflate_workspacesize(),
+			zlib_inflate_workspacesize());
+	stream.workspace = vmalloc(size);
+	if (!stream.workspace)
+		return -ENOMEM;
+	return 0;
+}
+
+void logfs_compr_exit(void)
+{
+	vfree(stream.workspace);
+}
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c
new file mode 100644
index 0000000..9718c22
--- /dev/null
+++ b/fs/logfs/dev_bdev.c
@@ -0,0 +1,327 @@
+/*
+ * fs/logfs/dev_bdev.c	- Device access methods for block devices
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+
+#define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
+
+static void request_complete(struct bio *bio, int err)
+{
+	complete((struct completion *)bio->bi_private);
+}
+
+static int sync_request(struct page *page, struct block_device *bdev, int rw)
+{
+	struct bio bio;
+	struct bio_vec bio_vec;
+	struct completion complete;
+
+	bio_init(&bio);
+	bio.bi_io_vec = &bio_vec;
+	bio_vec.bv_page = page;
+	bio_vec.bv_len = PAGE_SIZE;
+	bio_vec.bv_offset = 0;
+	bio.bi_vcnt = 1;
+	bio.bi_idx = 0;
+	bio.bi_size = PAGE_SIZE;
+	bio.bi_bdev = bdev;
+	bio.bi_sector = page->index * (PAGE_SIZE >> 9);
+	init_completion(&complete);
+	bio.bi_private = &complete;
+	bio.bi_end_io = request_complete;
+
+	submit_bio(rw, &bio);
+	generic_unplug_device(bdev_get_queue(bdev));
+	wait_for_completion(&complete);
+	return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO;
+}
+
+static int bdev_readpage(void *_sb, struct page *page)
+{
+	struct super_block *sb = _sb;
+	struct block_device *bdev = logfs_super(sb)->s_bdev;
+	int err;
+
+	err = sync_request(page, bdev, READ);
+	if (err) {
+		ClearPageUptodate(page);
+		SetPageError(page);
+	} else {
+		SetPageUptodate(page);
+		ClearPageError(page);
+	}
+	unlock_page(page);
+	return err;
+}
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+static void writeseg_end_io(struct bio *bio, int err)
+{
+	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+	struct super_block *sb = bio->bi_private;
+	struct logfs_super *super = logfs_super(sb);
+	struct page *page;
+
+	BUG_ON(!uptodate); /* FIXME: Retry io or write elsewhere */
+	BUG_ON(err);
+	BUG_ON(bio->bi_vcnt == 0);
+	do {
+		page = bvec->bv_page;
+		if (--bvec >= bio->bi_io_vec)
+			prefetchw(&bvec->bv_page->flags);
+
+		end_page_writeback(page);
+	} while (bvec >= bio->bi_io_vec);
+	bio_put(bio);
+	if (atomic_dec_and_test(&super->s_pending_writes))
+		wake_up(&wq);
+}
+
+static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
+		size_t nr_pages)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping = super->s_mapping_inode->i_mapping;
+	struct bio *bio;
+	struct page *page;
+	struct request_queue *q = bdev_get_queue(sb->s_bdev);
+	unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
+	int i;
+
+	bio = bio_alloc(GFP_NOFS, max_pages);
+	BUG_ON(!bio); /* FIXME: handle this */
+
+	for (i = 0; i < nr_pages; i++) {
+		if (i >= max_pages) {
+			/* Block layer cannot split bios :( */
+			bio->bi_vcnt = i;
+			bio->bi_idx = 0;
+			bio->bi_size = i * PAGE_SIZE;
+			bio->bi_bdev = super->s_bdev;
+			bio->bi_sector = ofs >> 9;
+			bio->bi_private = sb;
+			bio->bi_end_io = writeseg_end_io;
+			atomic_inc(&super->s_pending_writes);
+			submit_bio(WRITE, bio);
+
+			ofs += i * PAGE_SIZE;
+			index += i;
+			nr_pages -= i;
+			i = 0;
+
+			bio = bio_alloc(GFP_NOFS, max_pages);
+			BUG_ON(!bio);
+		}
+		page = find_lock_page(mapping, index + i);
+		BUG_ON(!page);
+		bio->bi_io_vec[i].bv_page = page;
+		bio->bi_io_vec[i].bv_len = PAGE_SIZE;
+		bio->bi_io_vec[i].bv_offset = 0;
+
+		BUG_ON(PageWriteback(page));
+		set_page_writeback(page);
+		unlock_page(page);
+	}
+	bio->bi_vcnt = nr_pages;
+	bio->bi_idx = 0;
+	bio->bi_size = nr_pages * PAGE_SIZE;
+	bio->bi_bdev = super->s_bdev;
+	bio->bi_sector = ofs >> 9;
+	bio->bi_private = sb;
+	bio->bi_end_io = writeseg_end_io;
+	atomic_inc(&super->s_pending_writes);
+	submit_bio(WRITE, bio);
+	return 0;
+}
+
+static void bdev_writeseg(struct super_block *sb, u64 ofs, size_t len)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int head;
+
+	BUG_ON(super->s_flags & LOGFS_SB_FLAG_RO);
+
+	if (len == 0) {
+		/* This can happen when the object fit perfectly into a
+		 * segment, the segment gets written per sync and subsequently
+		 * closed.
+		 */
+		return;
+	}
+	head = ofs & (PAGE_SIZE - 1);
+	if (head) {
+		ofs -= head;
+		len += head;
+	}
+	len = PAGE_ALIGN(len);
+	__bdev_writeseg(sb, ofs, ofs >> PAGE_SHIFT, len >> PAGE_SHIFT);
+	generic_unplug_device(bdev_get_queue(logfs_super(sb)->s_bdev));
+}
+
+
+static void erase_end_io(struct bio *bio, int err) 
+{ 
+	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); 
+	struct super_block *sb = bio->bi_private; 
+	struct logfs_super *super = logfs_super(sb); 
+
+	BUG_ON(!uptodate); /* FIXME: Retry io or write elsewhere */ 
+	BUG_ON(err); 
+	BUG_ON(bio->bi_vcnt == 0); 
+	bio_put(bio); 
+	if (atomic_dec_and_test(&super->s_pending_writes))
+		wake_up(&wq); 
+} 
+
+static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
+		size_t nr_pages)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct bio *bio;
+	struct request_queue *q = bdev_get_queue(sb->s_bdev);
+	unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
+	int i;
+
+	bio = bio_alloc(GFP_NOFS, max_pages);
+	BUG_ON(!bio); /* FIXME: handle this */
+
+	for (i = 0; i < nr_pages; i++) {
+		if (i >= max_pages) {
+			/* Block layer cannot split bios :( */
+			bio->bi_vcnt = i;
+			bio->bi_idx = 0;
+			bio->bi_size = i * PAGE_SIZE;
+			bio->bi_bdev = super->s_bdev;
+			bio->bi_sector = ofs >> 9;
+			bio->bi_private = sb;
+			bio->bi_end_io = erase_end_io;
+			atomic_inc(&super->s_pending_writes);
+			submit_bio(WRITE, bio);
+
+			ofs += i * PAGE_SIZE;
+			index += i;
+			nr_pages -= i;
+			i = 0;
+
+			bio = bio_alloc(GFP_NOFS, max_pages);
+			BUG_ON(!bio);
+		}
+		bio->bi_io_vec[i].bv_page = super->s_erase_page;
+		bio->bi_io_vec[i].bv_len = PAGE_SIZE;
+		bio->bi_io_vec[i].bv_offset = 0;
+	}
+	bio->bi_vcnt = nr_pages;
+	bio->bi_idx = 0;
+	bio->bi_size = nr_pages * PAGE_SIZE;
+	bio->bi_bdev = super->s_bdev;
+	bio->bi_sector = ofs >> 9;
+	bio->bi_private = sb;
+	bio->bi_end_io = erase_end_io;
+	atomic_inc(&super->s_pending_writes);
+	submit_bio(WRITE, bio);
+	return 0;
+}
+
+static int bdev_erase(struct super_block *sb, loff_t to, size_t len,
+		int ensure_write)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	BUG_ON(to & (PAGE_SIZE - 1));
+	BUG_ON(len & (PAGE_SIZE - 1));
+
+	if (super->s_flags & LOGFS_SB_FLAG_RO)
+		return -EROFS;
+
+	if (ensure_write) {
+		/*
+		 * Object store doesn't care whether erases happen or not.
+		 * But for the journal they are required.  Otherwise a scan
+		 * can find an old commit entry and assume it is the current
+		 * one, travelling back in time.
+		 */
+		do_erase(sb, to, to >> PAGE_SHIFT, len >> PAGE_SHIFT);
+	}
+
+	return 0;
+}
+
+static void bdev_sync(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	wait_event(wq, atomic_read(&super->s_pending_writes) == 0);
+}
+
+static struct page *bdev_find_first_sb(struct super_block *sb, u64 *ofs)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping = super->s_mapping_inode->i_mapping;
+	filler_t *filler = bdev_readpage;
+
+	*ofs = 0;
+	return read_cache_page(mapping, 0, filler, sb);
+}
+
+static struct page *bdev_find_last_sb(struct super_block *sb, u64 *ofs)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping = super->s_mapping_inode->i_mapping;
+	filler_t *filler = bdev_readpage;
+	u64 pos = (super->s_bdev->bd_inode->i_size & ~0xfffULL) - 0x1000;
+	pgoff_t index = pos >> PAGE_SHIFT;
+
+	*ofs = pos;
+	return read_cache_page(mapping, index, filler, sb);
+}
+
+static int bdev_write_sb(struct super_block *sb, struct page *page)
+{
+	struct block_device *bdev = logfs_super(sb)->s_bdev;
+
+	/* Nothing special to do for block devices. */
+	return sync_request(page, bdev, WRITE);
+}
+
+static void bdev_put_device(struct super_block *sb)
+{
+	close_bdev_exclusive(logfs_super(sb)->s_bdev, FMODE_READ|FMODE_WRITE);
+}
+
+static const struct logfs_device_ops bd_devops = {
+	.find_first_sb	= bdev_find_first_sb,
+	.find_last_sb	= bdev_find_last_sb,
+	.write_sb	= bdev_write_sb,
+	.readpage	= bdev_readpage,
+	.writeseg	= bdev_writeseg,
+	.erase		= bdev_erase,
+	.sync		= bdev_sync,
+	.put_device	= bdev_put_device,
+};
+
+int logfs_get_sb_bdev(struct file_system_type *type, int flags,
+		const char *devname, struct vfsmount *mnt)
+{
+	struct block_device *bdev;
+
+	bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, type);
+	if (IS_ERR(bdev))
+		return PTR_ERR(bdev);
+
+	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
+		int mtdnr = MINOR(bdev->bd_dev);
+		close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE);
+		return logfs_get_sb_mtd(type, flags, mtdnr, mnt);
+	}
+
+	return logfs_get_sb_device(type, flags, NULL, bdev, &bd_devops, mnt);
+}
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
new file mode 100644
index 0000000..cafb6ef
--- /dev/null
+++ b/fs/logfs/dev_mtd.c
@@ -0,0 +1,254 @@
+/*
+ * fs/logfs/dev_mtd.c	- Device access methods for MTD
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/completion.h>
+#include <linux/mount.h>
+#include <linux/sched.h>
+
+#define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
+
+static int mtd_read(struct super_block *sb, loff_t ofs, size_t len, void *buf)
+{
+	struct mtd_info *mtd = logfs_super(sb)->s_mtd;
+	size_t retlen;
+	int ret;
+
+	ret = mtd->read(mtd, ofs, len, &retlen, buf);
+	BUG_ON(ret == -EINVAL);
+	if (ret)
+		return ret;
+
+	/* Not sure if we should loop instead. */
+	if (retlen != len)
+		return -EIO;
+
+	return 0;
+}
+
+static int mtd_write(struct super_block *sb, loff_t ofs, size_t len, void *buf)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct mtd_info *mtd = super->s_mtd;
+	size_t retlen;
+	loff_t page_start, page_end;
+	int ret;
+
+	if (super->s_flags & LOGFS_SB_FLAG_RO)
+		return -EROFS;
+
+	BUG_ON((ofs >= mtd->size) || (len > mtd->size - ofs));
+	BUG_ON(ofs != (ofs >> super->s_writeshift) << super->s_writeshift);
+	BUG_ON(len > PAGE_CACHE_SIZE);
+	page_start = ofs & PAGE_CACHE_MASK;
+	page_end = PAGE_CACHE_ALIGN(ofs + len) - 1;
+	ret = mtd->write(mtd, ofs, len, &retlen, buf);
+	if (ret || (retlen != len))
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * For as long as I can remember (since about 2001) mtd->erase has been an
+ * asynchronous interface lacking the first driver to actually use the
+ * asynchronous properties.  So just to prevent the first implementor of such
+ * a thing from breaking logfs in 2350, we do the usual pointless dance to
+ * declare a completion variable and wait for completion before returning
+ * from mtd_erase().  What an excercise in futility!
+ */
+static void logfs_erase_callback(struct erase_info *ei)
+{
+	complete((struct completion *)ei->priv);
+}
+
+static int mtd_erase_mapping(struct super_block *sb, loff_t ofs, size_t len)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping = super->s_mapping_inode->i_mapping;
+	struct page *page;
+	pgoff_t index = ofs >> PAGE_SHIFT;
+
+	for (index = ofs >> PAGE_SHIFT; index < (ofs + len) >> PAGE_SHIFT; index++) {
+		page = find_get_page(mapping, index);
+		if (!page)
+			continue;
+		memset(page_address(page), 0xFF, PAGE_SIZE);
+		page_cache_release(page);
+	}
+	return 0;
+}
+
+static int mtd_erase(struct super_block *sb, loff_t ofs, size_t len,
+		int ensure_write)
+{
+	struct mtd_info *mtd = logfs_super(sb)->s_mtd;
+	struct erase_info ei;
+	DECLARE_COMPLETION_ONSTACK(complete);
+	int ret;
+
+	BUG_ON(len % mtd->erasesize);
+	if (logfs_super(sb)->s_flags & LOGFS_SB_FLAG_RO)
+		return -EROFS;
+
+	memset(&ei, 0, sizeof(ei));
+	ei.mtd = mtd;
+	ei.addr = ofs;
+	ei.len = len;
+	ei.callback = logfs_erase_callback;
+	ei.priv = (long)&complete;
+	ret = mtd->erase(mtd, &ei);
+	if (ret)
+		return -EIO;
+
+	wait_for_completion(&complete);
+	if (ei.state != MTD_ERASE_DONE)
+		return -EIO;
+	return mtd_erase_mapping(sb, ofs, len);
+}
+
+static void mtd_sync(struct super_block *sb)
+{
+	struct mtd_info *mtd = logfs_super(sb)->s_mtd;
+
+	if (mtd->sync)
+		mtd->sync(mtd);
+}
+
+static int mtd_readpage(void *_sb, struct page *page)
+{
+	struct super_block *sb = _sb;
+	int err;
+
+	err = mtd_read(sb, page->index << PAGE_SHIFT, PAGE_SIZE,
+			page_address(page));
+	if (err == -EUCLEAN) {
+		err = 0;
+		/* FIXME: force GC this segment */
+	}
+	if (err) {
+		ClearPageUptodate(page);
+		SetPageError(page);
+	} else {
+		SetPageUptodate(page);
+		ClearPageError(page);
+	}
+	unlock_page(page);
+	return err;
+}
+
+static struct page *mtd_find_first_sb(struct super_block *sb, u64 *ofs)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping = super->s_mapping_inode->i_mapping;
+	filler_t *filler = mtd_readpage;
+	struct mtd_info *mtd = super->s_mtd;
+
+	if (!mtd->block_isbad)
+		return NULL;
+
+	*ofs = 0;
+	while (mtd->block_isbad(mtd, *ofs)) {
+		*ofs += mtd->erasesize;
+		if (*ofs >= mtd->size)
+			return NULL;
+	}
+	BUG_ON(*ofs & ~PAGE_MASK);
+	return read_cache_page(mapping, *ofs >> PAGE_SHIFT, filler, sb);
+}
+
+static struct page *mtd_find_last_sb(struct super_block *sb, u64 *ofs)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping = super->s_mapping_inode->i_mapping;
+	filler_t *filler = mtd_readpage;
+	struct mtd_info *mtd = super->s_mtd;
+
+	if (!mtd->block_isbad)
+		return NULL;
+
+	*ofs = mtd->size - mtd->erasesize;
+	while (mtd->block_isbad(mtd, *ofs)) {
+		*ofs -= mtd->erasesize;
+		if (*ofs <= 0)
+			return NULL;
+	}
+	*ofs = *ofs + mtd->erasesize - 0x1000;
+	BUG_ON(*ofs & ~PAGE_MASK);
+	return read_cache_page(mapping, *ofs >> PAGE_SHIFT, filler, sb);
+}
+
+static int __mtd_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
+		size_t nr_pages)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping = super->s_mapping_inode->i_mapping;
+	struct page *page;
+	int i, err;
+
+	for (i = 0; i < nr_pages; i++) {
+		page = find_lock_page(mapping, index + i);
+		BUG_ON(!page);
+
+		err = mtd_write(sb, page->index << PAGE_SHIFT, PAGE_SIZE,
+				page_address(page));
+		unlock_page(page);
+		page_cache_release(page);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static void mtd_writeseg(struct super_block *sb, u64 ofs, size_t len)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int head;
+
+	if (super->s_flags & LOGFS_SB_FLAG_RO)
+		return;
+
+	if (len == 0) {
+		/* This can happen when the object fit perfectly into a
+		 * segment, the segment gets written per sync and subsequently
+		 * closed.
+		 */
+		return;
+	}
+	head = ofs & (PAGE_SIZE - 1);
+	if (head) {
+		ofs -= head;
+		len += head;
+	}
+	len = PAGE_ALIGN(len);
+	__mtd_writeseg(sb, ofs, ofs >> PAGE_SHIFT, len >> PAGE_SHIFT);
+}
+
+static void mtd_put_device(struct super_block *sb)
+{
+	put_mtd_device(logfs_super(sb)->s_mtd);
+}
+
+static const struct logfs_device_ops mtd_devops = {
+	.find_first_sb	= mtd_find_first_sb,
+	.find_last_sb	= mtd_find_last_sb,
+	.readpage	= mtd_readpage,
+	.writeseg	= mtd_writeseg,
+	.erase		= mtd_erase,
+	.sync		= mtd_sync,
+	.put_device	= mtd_put_device,
+};
+
+int logfs_get_sb_mtd(struct file_system_type *type, int flags,
+		int mtdnr, struct vfsmount *mnt)
+{
+	struct mtd_info *mtd;
+	const struct logfs_device_ops *devops = &mtd_devops;
+
+	mtd = get_mtd_device(NULL, mtdnr);
+	return logfs_get_sb_device(type, flags, mtd, NULL, devops, mnt);
+}
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
new file mode 100644
index 0000000..56a8bfb
--- /dev/null
+++ b/fs/logfs/dir.c
@@ -0,0 +1,827 @@
+/*
+ * fs/logfs/dir.c	- directory-related code
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+
+
+/*
+ * Atomic dir operations
+ *
+ * Directory operations are by default not atomic.  Dentries and Inodes are
+ * created/removed/altered in seperate operations.  Therefore we need to do
+ * a small amount of journaling.
+ *
+ * Create, link, mkdir, mknod and symlink all share the same function to do
+ * the work: __logfs_create.  This function works in two atomic steps:
+ * 1. allocate inode (remember in journal)
+ * 2. allocate dentry (clear journal)
+ *
+ * As we can only get interrupted between the two, when the inode we just
+ * created is simply stored in the anchor.  On next mount, if we were
+ * interrupted, we delete the inode.  From a users point of view the
+ * operation never happened.
+ *
+ * Unlink and rmdir also share the same function: unlink.  Again, this
+ * function works in two atomic steps
+ * 1. remove dentry (remember inode in journal)
+ * 2. unlink inode (clear journal)
+ *
+ * And again, on the next mount, if we were interrupted, we delete the inode.
+ * From a users point of view the operation succeeded.
+ *
+ * Rename is the real pain to deal with, harder than all the other methods
+ * combined.  Depending on the circumstances we can run into three cases.
+ * A "target rename" where the target dentry already existed, a "local
+ * rename" where both parent directories are identical or a "cross-directory
+ * rename" in the remaining case.
+ *
+ * Local rename is atomic, as the old dentry is simply rewritten with a new
+ * name.
+ *
+ * Cross-directory rename works in two steps, similar to __logfs_create and
+ * logfs_unlink:
+ * 1. Write new dentry (remember old dentry in journal)
+ * 2. Remove old dentry (clear journal)
+ *
+ * Here we remember a dentry instead of an inode.  On next mount, if we were
+ * interrupted, we delete the dentry.  From a users point of view, the
+ * operation succeeded.
+ *
+ * Target rename works in three atomic steps:
+ * 1. Attach old inode to new dentry (remember old dentry and new inode)
+ * 2. Remove old dentry (still remember the new inode)
+ * 3. Remove victim inode
+ *
+ * Here we remember both an inode an a dentry.  If we get interrupted
+ * between steps 1 and 2, we delete both the dentry and the inode.  If
+ * we get interrupted between steps 2 and 3, we delete just the inode.
+ * In either case, the remaining objects are deleted on next mount.  From
+ * a users point of view, the operation succeeded.
+ */
+
+static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd,
+		loff_t pos)
+{
+	return logfs_inode_write(dir, dd, sizeof(*dd), pos, WF_LOCK, NULL);
+}
+
+static int write_inode(struct inode *inode)
+{
+	return __logfs_write_inode(inode, WF_LOCK);
+}
+
+static s64 dir_seek_data(struct inode *inode, s64 pos)
+{
+	s64 new_pos = logfs_seek_data(inode, pos);
+
+	return max(pos, new_pos - 1);
+}
+
+static int beyond_eof(struct inode *inode, loff_t bix)
+{
+	loff_t pos = bix << inode->i_sb->s_blocksize_bits;
+	return pos >= i_size_read(inode);
+}
+
+/*
+ * Prime value was chosen to be roughly 256 + 26.  r5 hash uses 11,
+ * so short names (len <= 9) don't even occupy the complete 32bit name
+ * space.  A prime >256 ensures short names quickly spread the 32bit
+ * name space.  Add about 26 for the estimated amount of information
+ * of each character and pick a prime nearby, preferrably a bit-sparse
+ * one.
+ */
+static u32 hash_32(const char *s, int len, u32 seed)
+{
+	u32 hash = seed;
+	int i;
+
+	for (i = 0; i < len; i++)
+		hash = hash * 293 + s[i];
+	return hash;
+}
+
+/*
+ * We have to satisfy several conflicting requirements here.  Small
+ * directories should stay fairly compact and not require too many
+ * indirect blocks.  The number of possible locations for a given hash
+ * should be small to make lookup() fast.  And we should try hard not
+ * to overflow the 32bit name space or nfs and 32bit host systems will
+ * be unhappy.
+ *
+ * So we use the following scheme.  First we reduce the hash to 0..15
+ * and try a direct block.  If that is occupied we reduce the hash to
+ * 16..255 and try an indirect block.  Same for 2x and 3x indirect
+ * blocks.  Lastly we reduce the hash to 0x800_0000 .. 0xffff_ffff,
+ * but use buckets containing eight entries instead of a single one.
+ *
+ * Using 16 entries should allow for a reasonable amount of hash
+ * collisions, so the 32bit name space can be packed fairly tight
+ * before overflowing.  Oh and currently we don't overflow but return
+ * and error.
+ *
+ * How likely are collisions?  Doing the appropriate math is beyond me
+ * and the Bronstein textbook.  But running a test program to brute
+ * force collisions for a couple of days showed that on average the
+ * first collision occurs after 598M entries, with 290M being the
+ * smallest result.  Obviously 21 entries could already cause a
+ * collision if all entries are carefully chosen.
+ */
+static pgoff_t hash_index(u32 hash, int round)
+{
+	u32 i0_blocks = I0_BLOCKS;
+	u32 i1_blocks = I1_BLOCKS;
+	u32 i2_blocks = I2_BLOCKS;
+	u32 i3_blocks = I3_BLOCKS;
+
+	switch (round) {
+	case 0:
+		return hash % i0_blocks;
+	case 1:
+		return i0_blocks + hash % (i1_blocks - i0_blocks);
+	case 2:
+		return i1_blocks + hash % (i2_blocks - i1_blocks);
+	case 3:
+		return i2_blocks + hash % (i3_blocks - i2_blocks);
+	case 4 ... 19:
+		return i3_blocks + 16 * (hash % (((1<<31) - i3_blocks) / 16))
+			+ round - 4;
+	}
+	BUG();
+}
+
+static struct page *logfs_get_dd_page(struct inode *dir, struct dentry *dentry)
+{
+	struct qstr *name = &dentry->d_name;
+	struct page *page;
+	struct logfs_disk_dentry *dd;
+	u32 hash = hash_32(name->name, name->len, 0);
+	pgoff_t index;
+	int round;
+
+	if (name->len > LOGFS_MAX_NAMELEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	for (round = 0; round < 20; round++) {
+		index = hash_index(hash, round);
+
+		if (beyond_eof(dir, index))
+			return NULL;
+		if (!logfs_exist_block(dir, index))
+			continue;
+		page = read_cache_page(dir->i_mapping, index,
+				(filler_t *)logfs_readpage, NULL);
+		if (IS_ERR(page))
+			return page;
+		dd = kmap_atomic(page, KM_USER0);
+		BUG_ON(dd->namelen == 0);
+
+		if (name->len != be16_to_cpu(dd->namelen) ||
+				memcmp(name->name, dd->name, name->len)) {
+			kunmap_atomic(dd, KM_USER0);
+			page_cache_release(page);
+			continue;
+		}
+
+		kunmap_atomic(dd, KM_USER0);
+		return page;
+	}
+	return NULL;
+}
+
+static int logfs_remove_inode(struct inode *inode)
+{
+	int ret;
+
+	inode->i_nlink--;
+	ret = write_inode(inode);
+	LOGFS_BUG_ON(ret, inode->i_sb);
+	return ret;
+}
+
+static void abort_transaction(struct inode *inode, struct logfs_transaction *ta)
+{
+	if (logfs_inode(inode)->li_block)
+		logfs_inode(inode)->li_block->ta = NULL;
+	kfree(ta);
+}
+
+static int logfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+	struct logfs_super *super = logfs_super(dir->i_sb);
+	struct inode *inode = dentry->d_inode;
+	struct logfs_transaction *ta;
+	struct page *page;
+	pgoff_t index;
+	int ret;
+
+	ta = kzalloc(sizeof(*ta), GFP_KERNEL);
+	if (!ta)
+		return -ENOMEM;
+
+	ta->state = UNLINK_1;
+	ta->ino = inode->i_ino;
+
+	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+
+	page = logfs_get_dd_page(dir, dentry);
+	if (!page) {
+		kfree(ta);
+		return -ENOENT;
+	}
+	if (IS_ERR(page)) {
+		kfree(ta);
+		return PTR_ERR(page);
+	}
+	index = page->index;
+	page_cache_release(page);
+
+	mutex_lock(&super->s_dirop_mutex);
+	logfs_add_transaction(dir, ta);
+
+	ret = logfs_delete(dir, index, NULL);
+	if (!ret)
+		ret = write_inode(dir);
+
+	if (ret) {
+		abort_transaction(dir, ta);
+		printk(KERN_ERR"LOGFS: unable to delete inode\n");
+		goto out;
+	}
+
+	ta->state = UNLINK_2;
+	logfs_add_transaction(inode, ta);
+	ret = logfs_remove_inode(inode);
+out:
+	mutex_unlock(&super->s_dirop_mutex);
+	return ret;
+}
+
+static inline int logfs_empty_dir(struct inode *dir)
+{
+	u64 data;
+
+	data = logfs_seek_data(dir, 0) << dir->i_sb->s_blocksize_bits;
+	return data >= i_size_read(dir);
+}
+
+static int logfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode = dentry->d_inode;
+
+	if (!logfs_empty_dir(inode))
+		return -ENOTEMPTY;
+
+	return logfs_unlink(dir, dentry);
+}
+
+/* FIXME: readdir currently has it's own dir_walk code.  I don't see a good
+ * way to combine the two copies */
+#define IMPLICIT_NODES 2
+static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir)
+{
+	struct inode *dir = file->f_dentry->d_inode;
+	loff_t pos = file->f_pos - IMPLICIT_NODES;
+	struct page *page;
+	struct logfs_disk_dentry *dd;
+	int full;
+
+	BUG_ON(pos < 0);
+	for (;; pos++) {
+		if (beyond_eof(dir, pos))
+			break;
+		if (!logfs_exist_block(dir, pos)) {
+			/* deleted dentry */
+			pos = dir_seek_data(dir, pos);
+			continue;
+		}
+		page = read_cache_page(dir->i_mapping, pos,
+				(filler_t *)logfs_readpage, NULL);
+		if (IS_ERR(page))
+			return PTR_ERR(page);
+		dd = kmap_atomic(page, KM_USER0);
+		BUG_ON(dd->namelen == 0);
+
+		full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen),
+				pos, be64_to_cpu(dd->ino), dd->type);
+		kunmap_atomic(dd, KM_USER0);
+		page_cache_release(page);
+		if (full)
+			break;
+	}
+
+	file->f_pos = pos + IMPLICIT_NODES;
+	return 0;
+}
+
+static int logfs_readdir(struct file *file, void *buf, filldir_t filldir)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	ino_t pino = parent_ino(file->f_dentry);
+	int err;
+
+	if (file->f_pos < 0)
+		return -EINVAL;
+
+	if (file->f_pos == 0) {
+		if (filldir(buf, ".", 1, 1, inode->i_ino, DT_DIR) < 0)
+			return 0;
+		file->f_pos++;
+	}
+	if (file->f_pos == 1) {
+		if (filldir(buf, "..", 2, 2, pino, DT_DIR) < 0)
+			return 0;
+		file->f_pos++;
+	}
+
+	err = __logfs_readdir(file, buf, filldir);
+	return err;
+}
+
+static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name)
+{
+	dd->namelen = cpu_to_be16(name->len);
+	memcpy(dd->name, name->name, name->len);
+}
+
+static struct dentry *logfs_lookup(struct inode *dir, struct dentry *dentry,
+		struct nameidata *nd)
+{
+	struct page *page;
+	struct logfs_disk_dentry *dd;
+	pgoff_t index;
+	u64 ino = 0;
+	struct inode *inode;
+
+	page = logfs_get_dd_page(dir, dentry);
+	if (IS_ERR(page))
+		return ERR_CAST(page);
+	if (!page) {
+		d_add(dentry, NULL);
+		return NULL;
+	}
+	index = page->index;
+	dd = kmap_atomic(page, KM_USER0);
+	ino = be64_to_cpu(dd->ino);
+	kunmap_atomic(dd, KM_USER0);
+	page_cache_release(page);
+
+	inode = logfs_iget(dir->i_sb, ino);
+	if (IS_ERR(inode)) {
+		printk(KERN_ERR"LogFS: Cannot read inode #%llx for dentry (%lx, %lx)n",
+				ino, dir->i_ino, index);
+		return ERR_CAST(inode);
+	}
+	return d_splice_alias(inode, dentry);
+}
+
+static void grow_dir(struct inode *dir, loff_t index)
+{
+	index = (index + 1) << dir->i_sb->s_blocksize_bits;
+	if (i_size_read(dir) < index)
+		i_size_write(dir, index);
+}
+
+static int logfs_write_dir(struct inode *dir, struct dentry *dentry,
+		struct inode *inode)
+{
+	struct page *page;
+	struct logfs_disk_dentry *dd;
+	u32 hash = hash_32(dentry->d_name.name, dentry->d_name.len, 0);
+	pgoff_t index;
+	int round, err;
+
+	for (round = 0; round < 20; round++) {
+		index = hash_index(hash, round);
+
+		if (logfs_exist_block(dir, index))
+			continue;
+		page = find_or_create_page(dir->i_mapping, index, GFP_KERNEL);
+		if (!page)
+			return -ENOMEM;
+
+		dd = kmap_atomic(page, KM_USER0);
+		memset(dd, 0, sizeof(*dd));
+		dd->ino = cpu_to_be64(inode->i_ino);
+		dd->type = logfs_type(inode);
+		logfs_set_name(dd, &dentry->d_name);
+		kunmap_atomic(dd, KM_USER0);
+
+		err = logfs_write_buf(dir, page, WF_LOCK);
+		unlock_page(page);
+		page_cache_release(page);
+		if (!err)
+			grow_dir(dir, index);
+		return err;
+	}
+	/* FIXME: Is there a better return value?  In most cases neither
+	 * the filesystem nor the directory are full.  But we have had
+	 * too many collisions for this particular hash and no fallback.
+	 */
+	return -ENOSPC;
+}
+
+static int __logfs_create(struct inode *dir, struct dentry *dentry,
+		struct inode *inode, const char *dest, long destlen)
+{
+	struct logfs_super *super = logfs_super(dir->i_sb);
+	struct logfs_inode *li = logfs_inode(inode);
+	struct logfs_transaction *ta;
+	int ret;
+
+	ta = kzalloc(sizeof(*ta), GFP_KERNEL);
+	if (!ta)
+		return -ENOMEM;
+
+	ta->state = CREATE_1;
+	ta->ino = inode->i_ino;
+	mutex_lock(&super->s_dirop_mutex);
+	logfs_add_transaction(inode, ta);
+
+	if (dest) {
+		/* symlink */
+		ret = logfs_inode_write(inode, dest, destlen, 0, WF_LOCK, NULL);
+		if (!ret)
+			ret = write_inode(inode);
+	} else {
+		/* creat/mkdir/mknod */
+		ret = write_inode(inode);
+	}
+	if (ret) {
+		abort_transaction(inode, ta);
+		li->li_flags |= LOGFS_IF_STILLBORN;
+		/* FIXME: truncate symlink */
+		inode->i_nlink--;
+		iput(inode);
+		goto out;
+	}
+
+	ta->state = CREATE_2;
+	logfs_add_transaction(dir, ta);
+	ret = logfs_write_dir(dir, dentry, inode);
+	/* sync directory */
+	if (!ret)
+		ret = write_inode(dir);
+
+	if (ret) {
+		logfs_del_transaction(dir, ta);
+		ta->state = CREATE_2;
+		logfs_add_transaction(inode, ta);
+		logfs_remove_inode(inode);
+		iput(inode);
+		goto out;
+	}
+	d_instantiate(dentry, inode);
+out:
+	mutex_unlock(&super->s_dirop_mutex);
+	return ret;
+}
+
+static int logfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	struct inode *inode;
+
+	/*
+	 * FIXME: why do we have to fill in S_IFDIR, while the mode is
+	 * correct for mknod, creat, etc.?  Smells like the vfs *should*
+	 * do it for us but for some reason fails to do so.
+	 */
+	inode = logfs_new_inode(dir, S_IFDIR | mode);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	inode->i_op = &logfs_dir_iops;
+	inode->i_fop = &logfs_dir_fops;
+
+	return __logfs_create(dir, dentry, inode, NULL, 0);
+}
+
+static int logfs_create(struct inode *dir, struct dentry *dentry, int mode,
+		struct nameidata *nd)
+{
+	struct inode *inode;
+
+	inode = logfs_new_inode(dir, mode);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	inode->i_op = &logfs_reg_iops;
+	inode->i_fop = &logfs_reg_fops;
+	inode->i_mapping->a_ops = &logfs_reg_aops;
+
+	return __logfs_create(dir, dentry, inode, NULL, 0);
+}
+
+static int logfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+		dev_t rdev)
+{
+	struct inode *inode;
+
+	if (dentry->d_name.len > LOGFS_MAX_NAMELEN)
+		return -ENAMETOOLONG;
+
+	inode = logfs_new_inode(dir, mode);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	init_special_inode(inode, mode, rdev);
+
+	return __logfs_create(dir, dentry, inode, NULL, 0);
+}
+
+static int logfs_symlink(struct inode *dir, struct dentry *dentry,
+		const char *target)
+{
+	struct inode *inode;
+	size_t destlen = strlen(target) + 1;
+
+	if (destlen > dir->i_sb->s_blocksize)
+		return -ENAMETOOLONG;
+
+	inode = logfs_new_inode(dir, S_IFLNK | 0777);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+
+	inode->i_op = &logfs_symlink_iops;
+	inode->i_mapping->a_ops = &logfs_reg_aops;
+
+	return __logfs_create(dir, dentry, inode, target, destlen);
+}
+
+static int logfs_permission(struct inode *inode, int mask)
+{
+	return generic_permission(inode, mask, NULL);
+}
+
+static int logfs_link(struct dentry *old_dentry, struct inode *dir,
+		struct dentry *dentry)
+{
+	struct inode *inode = old_dentry->d_inode;
+
+	if (inode->i_nlink >= LOGFS_LINK_MAX)
+		return -EMLINK;
+
+	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	atomic_inc(&inode->i_count);
+	inode->i_nlink++;
+	mark_inode_dirty_sync(inode);
+
+	return __logfs_create(dir, dentry, inode, NULL, 0);
+}
+
+static int logfs_get_dd(struct inode *dir, struct dentry *dentry,
+		struct logfs_disk_dentry *dd, loff_t *pos)
+{
+	struct page *page;
+	void *map;
+
+	page = logfs_get_dd_page(dir, dentry);
+	if (IS_ERR(page))
+		return PTR_ERR(page);
+	*pos = page->index;
+	map = kmap_atomic(page, KM_USER0);
+	memcpy(dd, map, sizeof(*dd));
+	kunmap_atomic(map, KM_USER0);
+	page_cache_release(page);
+	return 0;
+}
+
+static int logfs_delete_dd(struct inode *dir, loff_t pos)
+{
+	/*
+	 * Getting called with pos somewhere beyond eof is either a goofup
+	 * within this file or means someone maliciously edited the
+	 * (crc-protected) journal.
+	 */
+	BUG_ON(beyond_eof(dir, pos));
+	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	log_dir(" Delete dentry (%lx, %llx)\n", dir->i_ino, pos);
+	return logfs_delete(dir, pos, NULL);
+}
+
+/*
+ * Cross-directory rename, target does not exist.  Just a little nasty.
+ * Create a new dentry in the target dir, then remove the old dentry,
+ * all the while taking care to remember our operation in the journal.
+ */
+static int logfs_rename_cross(struct inode *old_dir, struct dentry *old_dentry,
+			      struct inode *new_dir, struct dentry *new_dentry)
+{
+	struct logfs_super *super = logfs_super(old_dir->i_sb);
+	struct logfs_disk_dentry dd;
+	struct logfs_transaction *ta;
+	loff_t pos;
+	int err;
+
+	/* 1. locate source dd */
+	err = logfs_get_dd(old_dir, old_dentry, &dd, &pos);
+	if (err)
+		return err;
+
+	ta = kzalloc(sizeof(*ta), GFP_KERNEL);
+	if (!ta)
+		return -ENOMEM;
+
+	ta->state = CROSS_RENAME_1;
+	ta->dir = old_dir->i_ino;
+	ta->pos = pos;
+
+	/* 2. write target dd */
+	mutex_lock(&super->s_dirop_mutex);
+	logfs_add_transaction(new_dir, ta);
+	err = logfs_write_dir(new_dir, new_dentry, old_dentry->d_inode);
+	if (!err)
+		err = write_inode(new_dir);
+
+	if (err) {
+		super->s_rename_dir = 0;
+		super->s_rename_pos = 0;
+		abort_transaction(new_dir, ta);
+		goto out;
+	}
+
+	/* 3. remove source dd */
+	ta->state = CROSS_RENAME_2;
+	logfs_add_transaction(old_dir, ta);
+	err = logfs_delete_dd(old_dir, pos);
+	if (!err)
+		err = write_inode(old_dir);
+	LOGFS_BUG_ON(err, old_dir->i_sb);
+out:
+	mutex_unlock(&super->s_dirop_mutex);
+	return err;
+}
+
+static int logfs_replace_inode(struct inode *dir, struct dentry *dentry,
+		struct logfs_disk_dentry *dd, struct inode *inode)
+{
+	loff_t pos;
+	int err;
+
+	err = logfs_get_dd(dir, dentry, dd, &pos);
+	if (err)
+		return err;
+	dd->ino = cpu_to_be64(inode->i_ino);
+	dd->type = logfs_type(inode);
+
+	err = write_dir(dir, dd, pos);
+	if (err)
+		return err;
+	log_dir("Replace dentry (%lx, %llx) %s -> %llx\n", dir->i_ino, pos,
+			dd->name, be64_to_cpu(dd->ino));
+	return write_inode(dir);
+}
+
+/* Target dentry exists - the worst case.  We need to attach the source
+ * inode to the target dentry, then remove the orphaned target inode and
+ * source dentry.
+ */
+static int logfs_rename_target(struct inode *old_dir, struct dentry *old_dentry,
+			       struct inode *new_dir, struct dentry *new_dentry)
+{
+	struct logfs_super *super = logfs_super(old_dir->i_sb);
+	struct inode *old_inode = old_dentry->d_inode;
+	struct inode *new_inode = new_dentry->d_inode;
+	int isdir = S_ISDIR(old_inode->i_mode);
+	struct logfs_disk_dentry dd;
+	struct logfs_transaction *ta;
+	loff_t pos;
+	int err;
+
+	BUG_ON(isdir != S_ISDIR(new_inode->i_mode));
+	if (isdir) {
+		if (!logfs_empty_dir(new_inode))
+			return -ENOTEMPTY;
+	}
+
+	/* 1. locate source dd */
+	err = logfs_get_dd(old_dir, old_dentry, &dd, &pos);
+	if (err)
+		return err;
+
+	ta = kzalloc(sizeof(*ta), GFP_KERNEL);
+	if (!ta)
+		return -ENOMEM;
+
+	ta->state = TARGET_RENAME_1;
+	ta->dir = old_dir->i_ino;
+	ta->pos = pos;
+	ta->ino = new_inode->i_ino;
+
+	/* 2. attach source inode to target dd */
+	mutex_lock(&super->s_dirop_mutex);
+	logfs_add_transaction(new_dir, ta);
+	err = logfs_replace_inode(new_dir, new_dentry, &dd, old_inode);
+	if (err) {
+		super->s_rename_dir = 0;
+		super->s_rename_pos = 0;
+		super->s_victim_ino = 0;
+		abort_transaction(new_dir, ta);
+		goto out;
+	}
+
+	/* 3. remove source dd */
+	ta->state = TARGET_RENAME_2;
+	logfs_add_transaction(old_dir, ta);
+	err = logfs_delete_dd(old_dir, pos);
+	if (!err)
+		err = write_inode(old_dir);
+	LOGFS_BUG_ON(err, old_dir->i_sb);
+
+	/* 4. remove target inode */
+	ta->state = TARGET_RENAME_3;
+	logfs_add_transaction(new_inode, ta);
+	err = logfs_remove_inode(new_inode);
+
+out:
+	mutex_unlock(&super->s_dirop_mutex);
+	return err;
+}
+
+static int logfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+			struct inode *new_dir, struct dentry *new_dentry)
+{
+	if (new_dentry->d_inode)
+		return logfs_rename_target(old_dir, old_dentry,
+					   new_dir, new_dentry);
+	return logfs_rename_cross(old_dir, old_dentry, new_dir, new_dentry);
+}
+
+/* No locking done here, as this is called before .get_sb() returns. */
+int logfs_replay_journal(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct inode *inode;
+	u64 ino, pos;
+	int err;
+
+	if (super->s_victim_ino) {
+		/* delete victim inode */
+		ino = super->s_victim_ino;
+		printk(KERN_INFO"LogFS: delete unmapped inode #%llx\n", ino);
+		inode = logfs_iget(sb, ino);
+		if (IS_ERR(inode))
+			goto fail;
+
+		LOGFS_BUG_ON(i_size_read(inode) > 0, sb);
+		super->s_victim_ino = 0;
+		err = logfs_remove_inode(inode);
+		iput(inode);
+		if (err) {
+			super->s_victim_ino = ino;
+			goto fail;
+		}
+	}
+	if (super->s_rename_dir) {
+		/* delete old dd from rename */
+		ino = super->s_rename_dir;
+		pos = super->s_rename_pos;
+		printk(KERN_INFO"LogFS: delete unbacked dentry (%llx, %llx)\n",
+				ino, pos);
+		inode = logfs_iget(sb, ino);
+		if (IS_ERR(inode))
+			goto fail;
+
+		super->s_rename_dir = 0;
+		super->s_rename_pos = 0;
+		err = logfs_delete_dd(inode, pos);
+		iput(inode);
+		if (err) {
+			super->s_rename_dir = ino;
+			super->s_rename_pos = pos;
+			goto fail;
+		}
+	}
+	return 0;
+fail:
+	LOGFS_BUG(sb);
+	return -EIO;
+}
+
+const struct inode_operations logfs_symlink_iops = {
+	.readlink	= generic_readlink,
+	.follow_link	= page_follow_link_light,
+};
+
+const struct inode_operations logfs_dir_iops = {
+	.create		= logfs_create,
+	.link		= logfs_link,
+	.lookup		= logfs_lookup,
+	.mkdir		= logfs_mkdir,
+	.mknod		= logfs_mknod,
+	.rename		= logfs_rename,
+	.rmdir		= logfs_rmdir,
+	.permission	= logfs_permission,
+	.symlink	= logfs_symlink,
+	.unlink		= logfs_unlink,
+};
+const struct file_operations logfs_dir_fops = {
+	.fsync		= logfs_fsync,
+	.ioctl		= logfs_ioctl,
+	.readdir	= logfs_readdir,
+	.read		= generic_read_dir,
+};
diff --git a/fs/logfs/file.c b/fs/logfs/file.c
new file mode 100644
index 0000000..370f367
--- /dev/null
+++ b/fs/logfs/file.c
@@ -0,0 +1,263 @@
+/*
+ * fs/logfs/file.c	- prepare_write, commit_write and friends
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/sched.h>
+#include <linux/writeback.h>
+
+static int logfs_write_begin(struct file *file, struct address_space *mapping,
+		loff_t pos, unsigned len, unsigned flags,
+		struct page **pagep, void **fsdata)
+{
+	struct inode *inode = mapping->host;
+	struct page *page;
+	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+
+	page = grab_cache_page_write_begin(mapping, index, flags);
+	if (!page)
+		return -ENOMEM;
+	*pagep = page;
+
+	if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
+		return 0;
+	if ((pos & PAGE_CACHE_MASK) >= i_size_read(inode)) {
+		unsigned start = pos & (PAGE_CACHE_SIZE - 1);
+		unsigned end = start + len;
+
+		/* Reading beyond i_size is simple: memset to zero */
+		zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE);
+		return 0;
+	}
+	return logfs_readpage_nolock(page);
+}
+
+static int logfs_write_end(struct file *file, struct address_space *mapping,
+		loff_t pos, unsigned len, unsigned copied, struct page *page,
+		void *fsdata)
+{
+	struct inode *inode = mapping->host;
+	pgoff_t index = page->index;
+	unsigned start = pos & (PAGE_CACHE_SIZE - 1);
+	unsigned end = start + copied;
+	int ret = 0;
+
+	BUG_ON(PAGE_CACHE_SIZE != inode->i_sb->s_blocksize);
+	BUG_ON(page->index > I3_BLOCKS);
+
+	if (copied < len) {
+		/*
+		 * Short write of a non-initialized paged.  Just tell userspace
+		 * to retry the entire page.
+		 */
+		if (!PageUptodate(page)) {
+			copied = 0;
+			goto out;
+		}
+	}
+	if (copied == 0)
+		goto out; /* FIXME: do we need to update inode? */
+
+	if (i_size_read(inode) < (index << PAGE_CACHE_SHIFT) + end) {
+		i_size_write(inode, (index << PAGE_CACHE_SHIFT) + end);
+		mark_inode_dirty_sync(inode);
+	}
+
+	SetPageUptodate(page);
+	if (!PageDirty(page)) {
+		if (!get_page_reserve(inode, page))
+			__set_page_dirty_nobuffers(page);
+		else
+			ret = logfs_write_buf(inode, page, WF_LOCK);
+	}
+out:
+	unlock_page(page);
+	page_cache_release(page);
+	return ret ? ret : copied;
+}
+
+int logfs_readpage(struct file *file, struct page *page)
+{
+	int ret;
+
+	ret = logfs_readpage_nolock(page);
+	unlock_page(page);
+	return ret;
+}
+
+/* Clear the page's dirty flag in the radix tree. */
+/* TODO: mucking with PageWriteback is silly.  Add a generic function to clear
+ * the dirty bit from the radix tree for filesystems that don't have to wait
+ * for page writeback to finish (i.e. any compressing filesystem).
+ */
+static void clear_radix_tree_dirty(struct page *page)
+{
+	BUG_ON(PagePrivate(page) || page->private);
+	set_page_writeback(page);
+	end_page_writeback(page);
+}
+
+static int __logfs_writepage(struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	int err;
+
+	err = logfs_write_buf(inode, page, WF_LOCK);
+	if (err)
+		set_page_dirty(page);
+	else
+		clear_radix_tree_dirty(page);
+	unlock_page(page);
+	return err;
+}
+
+static int logfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+	struct inode *inode = page->mapping->host;
+	loff_t i_size = i_size_read(inode);
+	pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
+	unsigned offset;
+	u64 bix;
+	level_t level;
+
+	log_file("logfs_writepage(%lx, %lx, %p)\n", inode->i_ino, page->index,
+			page);
+
+	logfs_unpack_index(page->index, &bix, &level);
+
+	/* Indirect blocks are never truncated */
+	if (level != 0)
+		return __logfs_writepage(page);
+
+	/*
+	 * TODO: everything below is a near-verbatim copy of nobh_writepage().
+	 * The relevant bits should be factored out after logfs is merged.
+	 */
+
+	/* Is the page fully inside i_size? */
+	if (bix < end_index)
+		return __logfs_writepage(page);
+
+	 /* Is the page fully outside i_size? (truncate in progress) */
+	offset = i_size & (PAGE_CACHE_SIZE-1);
+	if (bix > end_index || offset == 0) {
+		unlock_page(page);
+		return 0; /* don't care */
+	}
+
+	/*
+	 * The page straddles i_size.  It must be zeroed out on each and every
+	 * writepage invokation because it may be mmapped.  "A file is mapped
+	 * in multiples of the page size.  For a file that is not a multiple of
+	 * the  page size, the remaining memory is zeroed when mapped, and
+	 * writes to that region are not written out to the file."
+	 */
+	zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+	return __logfs_writepage(page);
+}
+
+static void logfs_invalidatepage(struct page *page, unsigned long offset)
+{
+	move_page_to_btree(page);
+	BUG_ON(PagePrivate(page) || page->private);
+}
+
+static int logfs_releasepage(struct page *page, gfp_t only_xfs_uses_this)
+{
+	return 0; /* None of these are easy to release */
+}
+
+
+int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		unsigned long arg)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	unsigned int oldflags, flags;
+	int err;
+
+	switch (cmd) {
+	case FS_IOC_GETFLAGS:
+		flags = li->li_flags & LOGFS_FL_USER_VISIBLE;
+		return put_user(flags, (int __user *)arg);
+	case FS_IOC_SETFLAGS:
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
+		if (!is_owner_or_cap(inode))
+			return -EACCES;
+
+		err = get_user(flags, (int __user *)arg);
+		if (err)
+			return err;
+
+		mutex_lock(&inode->i_mutex);
+		oldflags = li->li_flags;
+		flags &= LOGFS_FL_USER_MODIFIABLE;
+		flags |= oldflags & ~LOGFS_FL_USER_MODIFIABLE;
+		li->li_flags = flags;
+		mutex_unlock(&inode->i_mutex);
+
+		inode->i_ctime = CURRENT_TIME;
+		mark_inode_dirty_sync(inode);
+		return 0;
+
+	default:
+		return -ENOTTY;
+	}
+}
+
+int logfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+	struct super_block *sb = dentry->d_inode->i_sb;
+	struct logfs_super *super = logfs_super(sb);
+
+	/* FIXME: write anchor */
+	super->s_devops->sync(sb);
+	return 0;
+}
+
+static int logfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	struct inode *inode = dentry->d_inode;
+	int err = 0;
+
+	if (attr->ia_valid & ATTR_SIZE)
+		err = logfs_truncate(inode, attr->ia_size);
+	attr->ia_valid &= ~ATTR_SIZE;
+
+	if (!err)
+		err = inode_change_ok(inode, attr);
+	if (!err)
+		err = inode_setattr(inode, attr);
+	return err;
+}
+
+const struct inode_operations logfs_reg_iops = {
+	.setattr	= logfs_setattr,
+};
+
+const struct file_operations logfs_reg_fops = {
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= generic_file_aio_write,
+	.fsync		= logfs_fsync,
+	.ioctl		= logfs_ioctl,
+	.llseek		= generic_file_llseek,
+	.mmap		= generic_file_readonly_mmap,
+	.open		= generic_file_open,
+	.read		= do_sync_read,
+	.write		= do_sync_write,
+};
+
+const struct address_space_operations logfs_reg_aops = {
+	.invalidatepage	= logfs_invalidatepage,
+	.readpage	= logfs_readpage,
+	.releasepage	= logfs_releasepage,
+	.set_page_dirty	= __set_page_dirty_nobuffers,
+	.writepage	= logfs_writepage,
+	.writepages	= generic_writepages,
+	.write_begin	= logfs_write_begin,
+	.write_end	= logfs_write_end,
+};
diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c
new file mode 100644
index 0000000..92949f9
--- /dev/null
+++ b/fs/logfs/gc.c
@@ -0,0 +1,730 @@
+/*
+ * fs/logfs/gc.c	- garbage collection code
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/sched.h>
+
+/*
+ * Wear leveling needs to kick in when the difference between low erase
+ * counts and high erase counts gets too big.  A good value for "too big"
+ * may be somewhat below 10% of maximum erase count for the device.
+ * Why not 397, to pick a nice round number with no specific meaning? :)
+ *
+ * WL_RATELIMIT is the minimum time between two wear level events.  A huge
+ * number of segments may fulfil the requirements for wear leveling at the
+ * same time.  If that happens we don't want to cause a latency from hell,
+ * but just gently pick one segment every so often and minimize overhead.
+ */
+#define WL_DELTA 397
+#define WL_RATELIMIT 100
+#define MAX_OBJ_ALIASES	2600
+#define SCAN_RATIO 512	/* number of scanned segments per gc'd segment */
+#define LIST_SIZE 64	/* base size of candidate lists */
+#define SCAN_ROUNDS 128	/* maximum number of complete medium scans */
+#define SCAN_ROUNDS_HIGH 4 /* maximum number of higher-level scans */
+
+static int no_free_segments(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	return super->s_free_list.count;
+}
+
+/* journal has distance -1, top-most ifile layer distance 0 */
+static u8 root_distance(struct super_block *sb, gc_level_t __gc_level)
+{
+	struct logfs_super *super = logfs_super(sb);
+	u8 gc_level = (__force u8)__gc_level;
+
+	switch (gc_level) {
+	case 0: /* fall through */
+	case 1: /* fall through */
+	case 2: /* fall through */
+	case 3:
+		/* file data or indirect blocks */
+		return super->s_ifile_levels + super->s_iblock_levels - gc_level;
+	case 6: /* fall through */
+	case 7: /* fall through */
+	case 8: /* fall through */
+	case 9:
+		/* inode file data or indirect blocks */
+		return super->s_ifile_levels - (gc_level - 6);
+	default:
+		printk(KERN_ERR"LOGFS: segment of unknown level %x found\n",
+				gc_level);
+		WARN_ON(1);
+		return super->s_ifile_levels + super->s_iblock_levels;
+	}
+}
+
+static int segment_is_reserved(struct super_block *sb, u32 segno)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_area *area;
+	void *reserved;
+	int i;
+
+	/* Some segments are reserved.  Just pretend they were all valid */
+	reserved = btree_lookup32(&super->s_reserved_segments, segno);
+	if (reserved)
+		return 1;
+
+	/* Currently open segments */
+	for_each_area(i) {
+		area = super->s_area[i];
+		if (area->a_is_open && area->a_segno == segno)
+			return 1;
+	}
+
+	return 0;
+}
+
+static void logfs_mark_segment_bad(struct super_block *sb, u32 segno)
+{
+	BUG();
+}
+
+/*
+ * Returns the bytes consumed by valid objects in this segment.  Object headers
+ * are counted, the segment header is not.
+ */
+static u32 logfs_valid_bytes(struct super_block *sb, u32 segno, u32 *ec,
+		gc_level_t *gc_level)
+{
+	struct logfs_segment_entry se;
+	u32 ec_level;
+
+	logfs_get_segment_entry(sb, segno, &se);
+	if (se.ec_level == cpu_to_be32(BADSEG) ||
+			se.valid == cpu_to_be32(RESERVED))
+		return RESERVED;
+
+	ec_level = be32_to_cpu(se.ec_level);
+	*ec = ec_level >> 4;
+	*gc_level = GC_LEVEL(ec_level & 0xf);
+	return be32_to_cpu(se.valid);
+}
+
+static void logfs_cleanse_block(struct super_block *sb, u64 ofs, u64 ino,
+		u64 bix, gc_level_t gc_level)
+{
+	struct inode *inode;
+	int err, cookie;
+
+	inode = logfs_safe_iget(sb, ino, &cookie);
+	err = logfs_rewrite_block(inode, bix, ofs, gc_level, 0);
+	BUG_ON(err);
+	logfs_safe_iput(inode, cookie);
+}
+
+static u32 logfs_gc_segment(struct super_block *sb, u32 segno, u8 dist)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_segment_header sh;
+	struct logfs_object_header oh;
+	u64 ofs, ino, bix;
+	u32 seg_ofs, logical_segno, cleaned = 0;
+	int err, len, valid;
+	gc_level_t gc_level;
+
+	LOGFS_BUG_ON(segment_is_reserved(sb, segno), sb);
+
+	btree_insert32(&super->s_reserved_segments, segno, (void *)1, GFP_NOFS);
+	err = wbuf_read(sb, dev_ofs(sb, segno, 0), sizeof(sh), &sh);
+	BUG_ON(err);
+	gc_level = GC_LEVEL(sh.level);
+	logical_segno = be32_to_cpu(sh.segno);
+	if (sh.crc != logfs_crc32(&sh, sizeof(sh), 4)) {
+		logfs_mark_segment_bad(sb, segno);
+		cleaned = -1;
+		goto out;
+	}
+
+	for (seg_ofs = LOGFS_SEGMENT_HEADERSIZE;
+			seg_ofs + sizeof(oh) < super->s_segsize; ) {
+		ofs = dev_ofs(sb, logical_segno, seg_ofs);
+		err = wbuf_read(sb, dev_ofs(sb, segno, seg_ofs), sizeof(oh),
+				&oh);
+		BUG_ON(err);
+
+		if (!memchr_inv(&oh, 0xff, sizeof(oh)))
+			break;
+
+		if (oh.crc != logfs_crc32(&oh, sizeof(oh) - 4, 4)) {
+			logfs_mark_segment_bad(sb, segno);
+			cleaned = super->s_segsize - 1;
+			goto out;
+		}
+
+		ino = be64_to_cpu(oh.ino);
+		bix = be64_to_cpu(oh.bix);
+		len = sizeof(oh) + be16_to_cpu(oh.len);
+		valid = logfs_is_valid_block(sb, ofs, ino, bix, gc_level);
+		if (valid == 1) {
+			logfs_cleanse_block(sb, ofs, ino, bix, gc_level);
+			cleaned += len;
+		} else if (valid == 2) {
+			/* Will be invalid upon journal commit */
+			cleaned += len;
+		}
+		seg_ofs += len;
+	}
+out:
+	btree_remove32(&super->s_reserved_segments, segno);
+	return cleaned;
+}
+
+static struct gc_candidate *add_list(struct gc_candidate *cand,
+		struct candidate_list *list)
+{
+	struct rb_node **p = &list->rb_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct gc_candidate *cur;
+	int comp;
+
+	cand->list = list;
+	while (*p) {
+		parent = *p;
+		cur = rb_entry(parent, struct gc_candidate, rb_node);
+
+		if (list->sort_by_ec)
+			comp = cand->erase_count < cur->erase_count;
+		else
+			comp = cand->valid < cur->valid;
+
+		if (comp)
+			p = &parent->rb_left;
+		else
+			p = &parent->rb_right;
+	}
+	rb_link_node(&cand->rb_node, parent, p);
+	rb_insert_color(&cand->rb_node, &list->rb_tree);
+
+	if (list->count <= list->maxcount) {
+		list->count++;
+		return NULL;
+	}
+	cand = rb_entry(rb_last(&list->rb_tree), struct gc_candidate, rb_node);
+	rb_erase(&cand->rb_node, &list->rb_tree);
+	cand->list = NULL;
+	return cand;
+}
+
+static void remove_from_list(struct gc_candidate *cand)
+{
+	struct candidate_list *list = cand->list;
+
+	rb_erase(&cand->rb_node, &list->rb_tree);
+	list->count--;
+}
+
+static void free_candidate(struct super_block *sb, struct gc_candidate *cand)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	btree_remove32(&super->s_cand_tree, cand->segno);
+	kfree(cand);
+}
+
+u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec)
+{
+	struct gc_candidate *cand;
+	u32 segno;
+
+	BUG_ON(list->count == 0);
+
+	cand = rb_entry(rb_first(&list->rb_tree), struct gc_candidate, rb_node);
+	remove_from_list(cand);
+	segno = cand->segno;
+	if (ec)
+		*ec = cand->erase_count;
+	free_candidate(sb, cand);
+	return segno;
+}
+
+/*
+ * We have several lists to manage segments with.  The reserve_list is used to
+ * deal with bad blocks.  We try to keep the best (lowest ec) segments on this
+ * list.
+ * The free_list contains free segments for normal usage.  It usually gets the
+ * second pick after the reserve_list.  But when the free_list is running short
+ * it is more important to keep the free_list full than to keep a reserve.
+ *
+ * Segments that are not free are put onto a per-level low_list.  If we have
+ * to run garbage collection, we pick a candidate from there.  All segments on
+ * those lists should have at least some free space so GC will make progress.
+ *
+ * And last we have the ec_list, which is used to pick segments for wear
+ * leveling.
+ *
+ * If all appropriate lists are full, we simply free the candidate and forget
+ * about that segment for a while.  We have better candidates for each purpose.
+ */
+static void __add_candidate(struct super_block *sb, struct gc_candidate *cand)
+{
+	struct logfs_super *super = logfs_super(sb);
+	u32 full = super->s_segsize - LOGFS_SEGMENT_RESERVE;
+
+	if (cand->valid == 0) {
+		/* 100% free segments */
+		log_gc_noisy("add reserve segment %x (ec %x) at %llx\n",
+				cand->segno, cand->erase_count,
+				dev_ofs(sb, cand->segno, 0));
+		cand = add_list(cand, &super->s_reserve_list);
+		if (cand) {
+			log_gc_noisy("add free segment %x (ec %x) at %llx\n",
+					cand->segno, cand->erase_count,
+					dev_ofs(sb, cand->segno, 0));
+			cand = add_list(cand, &super->s_free_list);
+		}
+	} else {
+		/* good candidates for Garbage Collection */
+		if (cand->valid < full)
+			cand = add_list(cand, &super->s_low_list[cand->dist]);
+		/* good candidates for wear leveling,
+		 * segments that were recently written get ignored */
+		if (cand)
+			cand = add_list(cand, &super->s_ec_list);
+	}
+	if (cand)
+		free_candidate(sb, cand);
+}
+
+static int add_candidate(struct super_block *sb, u32 segno, u32 valid, u32 ec,
+		u8 dist)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct gc_candidate *cand;
+
+	cand = kmalloc(sizeof(*cand), GFP_NOFS);
+	if (!cand)
+		return -ENOMEM;
+
+	cand->segno = segno;
+	cand->valid = valid;
+	cand->erase_count = ec;
+	cand->dist = dist;
+
+	btree_insert32(&super->s_cand_tree, segno, cand, GFP_NOFS);
+	__add_candidate(sb, cand);
+	return 0;
+}
+
+static void remove_segment_from_lists(struct super_block *sb, u32 segno)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct gc_candidate *cand;
+
+	cand = btree_lookup32(&super->s_cand_tree, segno);
+	if (cand) {
+		remove_from_list(cand);
+		free_candidate(sb, cand);
+	}
+}
+
+static void scan_segment(struct super_block *sb, u32 segno)
+{
+	u32 valid, ec = 0;
+	gc_level_t gc_level = 0;
+	u8 dist;
+
+	if (segment_is_reserved(sb, segno))
+		return;
+
+	remove_segment_from_lists(sb, segno);
+	valid = logfs_valid_bytes(sb, segno, &ec, &gc_level);
+	if (valid == RESERVED)
+		return;
+
+	dist = root_distance(sb, gc_level);
+	add_candidate(sb, segno, valid, ec, dist);
+}
+
+static struct gc_candidate *first_in_list(struct candidate_list *list)
+{
+	if (list->count == 0)
+		return NULL;
+	return rb_entry(rb_first(&list->rb_tree), struct gc_candidate, rb_node);
+}
+
+/*
+ * Find the best segment for garbage collection.  Main criterion is
+ * the segment requiring the least effort to clean.  Secondary
+ * criterion is to GC on the lowest level available.
+ *
+ * So we search the least effort segment on the lowest level first,
+ * then move up and pick another segment iff is requires significantly
+ * less effort.  Hence the LOGFS_MAX_OBJECTSIZE in the comparison.
+ */
+static struct gc_candidate *get_candidate(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int i, max_dist;
+	struct gc_candidate *cand = NULL, *this;
+
+	max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS);
+
+	for (i = max_dist; i >= 0; i--) {
+		this = first_in_list(&super->s_low_list[i]);
+		if (!this)
+			continue;
+		if (!cand)
+			cand = this;
+		if (this->valid + LOGFS_MAX_OBJECTSIZE <= cand->valid)
+			cand = this;
+	}
+	return cand;
+}
+
+static int __logfs_gc_once(struct super_block *sb, struct gc_candidate *cand)
+{
+	struct logfs_super *super = logfs_super(sb);
+	gc_level_t gc_level;
+	u32 cleaned, valid, segno, ec;
+	u8 dist;
+
+	if (!cand) {
+		log_gc("GC attempted, but no candidate found\n");
+		return 0;
+	}
+
+	segno = cand->segno;
+	dist = cand->dist;
+	valid = logfs_valid_bytes(sb, segno, &ec, &gc_level);
+	free_candidate(sb, cand);
+	log_gc("GC segment #%02x at %llx, %x required, %x free, %x valid, %llx free\n",
+			segno, (u64)segno << super->s_segshift,
+			dist, no_free_segments(sb), valid,
+			super->s_free_bytes);
+	cleaned = logfs_gc_segment(sb, segno, dist);
+	log_gc("GC segment #%02x complete - now %x valid\n", segno,
+			valid - cleaned);
+	BUG_ON(cleaned != valid);
+	return 1;
+}
+
+static int logfs_gc_once(struct super_block *sb)
+{
+	struct gc_candidate *cand;
+
+	cand = get_candidate(sb);
+	if (cand)
+		remove_from_list(cand);
+	return __logfs_gc_once(sb, cand);
+}
+
+/* returns 1 if a wrap occurs, 0 otherwise */
+static int logfs_scan_some(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	u32 segno;
+	int i, ret = 0;
+
+	segno = super->s_sweeper;
+	for (i = SCAN_RATIO; i > 0; i--) {
+		segno++;
+		if (segno >= super->s_no_segs) {
+			segno = 0;
+			ret = 1;
+			/* Break out of the loop.  We want to read a single
+			 * block from the segment size on next invocation if
+			 * SCAN_RATIO is set to match block size
+			 */
+			break;
+		}
+
+		scan_segment(sb, segno);
+	}
+	super->s_sweeper = segno;
+	return ret;
+}
+
+/*
+ * In principle, this function should loop forever, looking for GC candidates
+ * and moving data.  LogFS is designed in such a way that this loop is
+ * guaranteed to terminate.
+ *
+ * Limiting the loop to some iterations serves purely to catch cases when
+ * these guarantees have failed.  An actual endless loop is an obvious bug
+ * and should be reported as such.
+ */
+static void __logfs_gc_pass(struct super_block *sb, int target)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_block *block;
+	int round, progress, last_progress = 0;
+
+	if (no_free_segments(sb) >= target &&
+			super->s_no_object_aliases < MAX_OBJ_ALIASES)
+		return;
+
+	log_gc("__logfs_gc_pass(%x)\n", target);
+	for (round = 0; round < SCAN_ROUNDS; ) {
+		if (no_free_segments(sb) >= target)
+			goto write_alias;
+
+		/* Sync in-memory state with on-medium state in case they
+		 * diverged */
+		logfs_write_anchor(sb);
+		round += logfs_scan_some(sb);
+		if (no_free_segments(sb) >= target)
+			goto write_alias;
+		progress = logfs_gc_once(sb);
+		if (progress)
+			last_progress = round;
+		else if (round - last_progress > 2)
+			break;
+		continue;
+
+		/*
+		 * The goto logic is nasty, I just don't know a better way to
+		 * code it.  GC is supposed to ensure two things:
+		 * 1. Enough free segments are available.
+		 * 2. The number of aliases is bounded.
+		 * When 1. is achieved, we take a look at 2. and write back
+		 * some alias-containing blocks, if necessary.  However, after
+		 * each such write we need to go back to 1., as writes can
+		 * consume free segments.
+		 */
+write_alias:
+		if (super->s_no_object_aliases < MAX_OBJ_ALIASES)
+			return;
+		if (list_empty(&super->s_object_alias)) {
+			/* All aliases are still in btree */
+			return;
+		}
+		log_gc("Write back one alias\n");
+		block = list_entry(super->s_object_alias.next,
+				struct logfs_block, alias_list);
+		block->ops->write_block(block);
+		/*
+		 * To round off the nasty goto logic, we reset round here.  It
+		 * is a safety-net for GC not making any progress and limited
+		 * to something reasonably small.  If incremented it for every
+		 * single alias, the loop could terminate rather quickly.
+		 */
+		round = 0;
+	}
+	LOGFS_BUG(sb);
+}
+
+static int wl_ratelimit(struct super_block *sb, u64 *next_event)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	if (*next_event < super->s_gec) {
+		*next_event = super->s_gec + WL_RATELIMIT;
+		return 0;
+	}
+	return 1;
+}
+
+static void logfs_wl_pass(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct gc_candidate *wl_cand, *free_cand;
+
+	if (wl_ratelimit(sb, &super->s_wl_gec_ostore))
+		return;
+
+	wl_cand = first_in_list(&super->s_ec_list);
+	if (!wl_cand)
+		return;
+	free_cand = first_in_list(&super->s_free_list);
+	if (!free_cand)
+		return;
+
+	if (wl_cand->erase_count < free_cand->erase_count + WL_DELTA) {
+		remove_from_list(wl_cand);
+		__logfs_gc_once(sb, wl_cand);
+	}
+}
+
+/*
+ * The journal needs wear leveling as well.  But moving the journal is an
+ * expensive operation so we try to avoid it as much as possible.  And if we
+ * have to do it, we move the whole journal, not individual segments.
+ *
+ * Ratelimiting is not strictly necessary here, it mainly serves to avoid the
+ * calculations.  First we check whether moving the journal would be a
+ * significant improvement.  That means that a) the current journal segments
+ * have more wear than the future journal segments and b) the current journal
+ * segments have more wear than normal ostore segments.
+ * Rationale for b) is that we don't have to move the journal if it is aging
+ * less than the ostore, even if the reserve segments age even less (they are
+ * excluded from wear leveling, after all).
+ * Next we check that the superblocks have less wear than the journal.  Since
+ * moving the journal requires writing the superblocks, we have to protect the
+ * superblocks even more than the journal.
+ *
+ * Also we double the acceptable wear difference, compared to ostore wear
+ * leveling.  Journal data is read and rewritten rapidly, comparatively.  So
+ * soft errors have much less time to accumulate and we allow the journal to
+ * be a bit worse than the ostore.
+ */
+static void logfs_journal_wl_pass(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct gc_candidate *cand;
+	u32 min_journal_ec = -1, max_reserve_ec = 0;
+	int i;
+
+	if (wl_ratelimit(sb, &super->s_wl_gec_journal))
+		return;
+
+	if (super->s_reserve_list.count < super->s_no_journal_segs) {
+		/* Reserve is not full enough to move complete journal */
+		return;
+	}
+
+	journal_for_each(i)
+		if (super->s_journal_seg[i])
+			min_journal_ec = min(min_journal_ec,
+					super->s_journal_ec[i]);
+	cand = rb_entry(rb_first(&super->s_free_list.rb_tree),
+			struct gc_candidate, rb_node);
+	max_reserve_ec = cand->erase_count;
+	for (i = 0; i < 2; i++) {
+		struct logfs_segment_entry se;
+		u32 segno = seg_no(sb, super->s_sb_ofs[i]);
+		u32 ec;
+
+		logfs_get_segment_entry(sb, segno, &se);
+		ec = be32_to_cpu(se.ec_level) >> 4;
+		max_reserve_ec = max(max_reserve_ec, ec);
+	}
+
+	if (min_journal_ec > max_reserve_ec + 2 * WL_DELTA) {
+		do_logfs_journal_wl_pass(sb);
+	}
+}
+
+void logfs_gc_pass(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	//BUG_ON(mutex_trylock(&logfs_super(sb)->s_w_mutex));
+	/* Write journal before free space is getting saturated with dirty
+	 * objects.
+	 */
+	if (super->s_dirty_used_bytes + super->s_dirty_free_bytes
+			+ LOGFS_MAX_OBJECTSIZE >= super->s_free_bytes)
+		logfs_write_anchor(sb);
+	__logfs_gc_pass(sb, super->s_total_levels);
+	logfs_wl_pass(sb);
+	logfs_journal_wl_pass(sb);
+}
+
+static int check_area(struct super_block *sb, int i)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_area *area = super->s_area[i];
+	struct logfs_object_header oh;
+	u32 segno = area->a_segno;
+	u32 ofs = area->a_used_bytes;
+	__be32 crc;
+	int err;
+
+	if (!area->a_is_open)
+		return 0;
+
+	for (ofs = area->a_used_bytes;
+	     ofs <= super->s_segsize - sizeof(oh);
+	     ofs += (u32)be16_to_cpu(oh.len) + sizeof(oh)) {
+		err = wbuf_read(sb, dev_ofs(sb, segno, ofs), sizeof(oh), &oh);
+		if (err)
+			return err;
+
+		if (!memchr_inv(&oh, 0xff, sizeof(oh)))
+			break;
+
+		crc = logfs_crc32(&oh, sizeof(oh) - 4, 4);
+		if (crc != oh.crc) {
+			printk(KERN_INFO "interrupted header at %llx\n",
+					dev_ofs(sb, segno, ofs));
+			return 0;
+		}
+	}
+	if (ofs != area->a_used_bytes) {
+		printk(KERN_INFO "%x bytes unaccounted data found at %llx\n",
+				ofs - area->a_used_bytes,
+				dev_ofs(sb, segno, area->a_used_bytes));
+		area->a_used_bytes = ofs;
+	}
+	return 0;
+}
+
+int logfs_check_areas(struct super_block *sb)
+{
+	int i, err;
+
+	for_each_area(i) {
+		err = check_area(sb, i);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static void logfs_init_candlist(struct candidate_list *list, int maxcount,
+		int sort_by_ec)
+{
+	list->count = 0;
+	list->maxcount = maxcount;
+	list->sort_by_ec = sort_by_ec;
+	list->rb_tree = RB_ROOT;
+}
+
+int logfs_init_gc(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int i;
+
+	btree_init_mempool32(&super->s_cand_tree, super->s_btree_pool);
+	logfs_init_candlist(&super->s_free_list, LIST_SIZE + SCAN_RATIO, 1);
+	logfs_init_candlist(&super->s_reserve_list,
+			super->s_bad_seg_reserve, 1);
+	for_each_area(i)
+		logfs_init_candlist(&super->s_low_list[i], LIST_SIZE, 0);
+	logfs_init_candlist(&super->s_ec_list, LIST_SIZE, 1);
+	return 0;
+}
+
+static void logfs_cleanup_list(struct super_block *sb,
+		struct candidate_list *list)
+{
+	struct gc_candidate *cand;
+
+	while (list->count) {
+		cand = rb_entry(list->rb_tree.rb_node, struct gc_candidate,
+				rb_node);
+		remove_from_list(cand);
+		free_candidate(sb, cand);
+	}
+	BUG_ON(list->rb_tree.rb_node);
+}
+
+void logfs_cleanup_gc(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int i;
+
+	if (!super->s_free_list.count)
+		return;
+
+	/*
+	 * FIXME: The btree may still contain a single empty node.  So we
+	 * call the grim visitor to clean up that mess.  Btree code should
+	 * do it for us, really.
+	 */
+	btree_grim_visitor32(&super->s_cand_tree, 0, NULL);
+	logfs_cleanup_list(sb, &super->s_free_list);
+	logfs_cleanup_list(sb, &super->s_reserve_list);
+	for_each_area(i)
+		logfs_cleanup_list(sb, &super->s_low_list[i]);
+	logfs_cleanup_list(sb, &super->s_ec_list);
+}
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
new file mode 100644
index 0000000..33ec1ae
--- /dev/null
+++ b/fs/logfs/inode.c
@@ -0,0 +1,417 @@
+/*
+ * fs/logfs/inode.c	- inode handling code
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/writeback.h>
+#include <linux/backing-dev.h>
+
+/*
+ * How soon to reuse old inode numbers?  LogFS doesn't store deleted inodes
+ * on the medium.  It therefore also lacks a method to store the previous
+ * generation number for deleted inodes.  Instead a single generation number
+ * is stored which will be used for new inodes.  Being just a 32bit counter,
+ * this can obvious wrap relatively quickly.  So we only reuse inodes if we
+ * know that a fair number of inodes can be created before we have to increment
+ * the generation again - effectively adding some bits to the counter.
+ * But being too aggressive here means we keep a very large and very sparse
+ * inode file, wasting space on indirect blocks.
+ * So what is a good value?  Beats me.  64k seems moderately bad on both
+ * fronts, so let's use that for now...
+ *
+ * NFS sucks, as everyone already knows.
+ */
+#define INOS_PER_WRAP (0x10000)
+
+/*
+ * Logfs' requirement to read inodes for garbage collection makes life a bit
+ * harder.  GC may have to read inodes that are in I_FREEING state, when they
+ * are being written out - and waiting for GC to make progress, naturally.
+ *
+ * So we cannot just call iget() or some variant of it, but first have to check
+ * wether the inode in question might be in I_FREEING state.  Therefore we
+ * maintain our own per-sb list of "almost deleted" inodes and check against
+ * that list first.  Normally this should be at most 1-2 entries long.
+ *
+ * Also, inodes have logfs-specific reference counting on top of what the vfs
+ * does.  When .destroy_inode is called, normally the reference count will drop
+ * to zero and the inode gets deleted.  But if GC accessed the inode, its
+ * refcount will remain nonzero and final deletion will have to wait.
+ *
+ * As a result we have two sets of functions to get/put inodes:
+ * logfs_safe_iget/logfs_safe_iput	- safe to call from GC context
+ * logfs_iget/iput			- normal version
+ */
+static struct kmem_cache *logfs_inode_cache;
+
+static DEFINE_SPINLOCK(logfs_inode_lock);
+
+static void logfs_inode_setops(struct inode *inode)
+{
+	switch (inode->i_mode & S_IFMT) {
+	case S_IFDIR:
+		inode->i_op = &logfs_dir_iops;
+		inode->i_fop = &logfs_dir_fops;
+		inode->i_mapping->a_ops = &logfs_reg_aops;
+		break;
+	case S_IFREG:
+		inode->i_op = &logfs_reg_iops;
+		inode->i_fop = &logfs_reg_fops;
+		inode->i_mapping->a_ops = &logfs_reg_aops;
+		break;
+	case S_IFLNK:
+		inode->i_op = &logfs_symlink_iops;
+		inode->i_mapping->a_ops = &logfs_reg_aops;
+		break;
+	case S_IFSOCK:	/* fall through */
+	case S_IFBLK:	/* fall through */
+	case S_IFCHR:	/* fall through */
+	case S_IFIFO:
+		init_special_inode(inode, inode->i_mode, inode->i_rdev);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static struct inode *__logfs_iget(struct super_block *sb, ino_t ino)
+{
+	struct inode *inode = iget_locked(sb, ino);
+	int err;
+
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+	if (!(inode->i_state & I_NEW))
+		return inode;
+
+	err = logfs_read_inode(inode);
+	if (err || inode->i_nlink == 0) {
+		/* inode->i_nlink == 0 can be true when called from
+		 * block validator */
+		/* set i_nlink to 0 to prevent caching */
+		inode->i_nlink = 0;
+		logfs_inode(inode)->li_flags |= LOGFS_IF_ZOMBIE;
+		iget_failed(inode);
+		if (!err)
+			err = -ENOENT;
+		return ERR_PTR(err);
+	}
+
+	logfs_inode_setops(inode);
+	unlock_new_inode(inode);
+	return inode;
+}
+
+struct inode *logfs_iget(struct super_block *sb, ino_t ino)
+{
+	BUG_ON(ino == LOGFS_INO_MASTER);
+	BUG_ON(ino == LOGFS_INO_SEGFILE);
+	return __logfs_iget(sb, ino);
+}
+
+/*
+ * is_cached is set to 1 if we hand out a cached inode, 0 otherwise.
+ * this allows logfs_iput to do the right thing later
+ */
+struct inode *logfs_safe_iget(struct super_block *sb, ino_t ino, int *is_cached)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_inode *li;
+
+	if (ino == LOGFS_INO_MASTER)
+		return super->s_master_inode;
+	if (ino == LOGFS_INO_SEGFILE)
+		return super->s_segfile_inode;
+
+	spin_lock(&logfs_inode_lock);
+	list_for_each_entry(li, &super->s_freeing_list, li_freeing_list)
+		if (li->vfs_inode.i_ino == ino) {
+			li->li_refcount++;
+			spin_unlock(&logfs_inode_lock);
+			*is_cached = 1;
+			return &li->vfs_inode;
+		}
+	spin_unlock(&logfs_inode_lock);
+
+	*is_cached = 0;
+	return __logfs_iget(sb, ino);
+}
+
+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);
+}
+
+static void logfs_destroy_inode(struct inode *inode)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+
+	BUG_ON(list_empty(&li->li_freeing_list));
+	spin_lock(&logfs_inode_lock);
+	li->li_refcount--;
+	if (li->li_refcount == 0)
+		__logfs_destroy_inode(inode);
+	spin_unlock(&logfs_inode_lock);
+}
+
+void logfs_safe_iput(struct inode *inode, int is_cached)
+{
+	if (inode->i_ino == LOGFS_INO_MASTER)
+		return;
+	if (inode->i_ino == LOGFS_INO_SEGFILE)
+		return;
+
+	if (is_cached) {
+		logfs_destroy_inode(inode);
+		return;
+	}
+
+	iput(inode);
+}
+
+static void logfs_init_inode(struct super_block *sb, struct inode *inode)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	int i;
+
+	li->li_flags	= 0;
+	li->li_height	= 0;
+	li->li_used_bytes = 0;
+	li->li_block	= NULL;
+	inode->i_uid	= 0;
+	inode->i_gid	= 0;
+	inode->i_size	= 0;
+	inode->i_blocks	= 0;
+	inode->i_ctime	= CURRENT_TIME;
+	inode->i_mtime	= CURRENT_TIME;
+	inode->i_nlink	= 1;
+	INIT_LIST_HEAD(&li->li_freeing_list);
+
+	for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+		li->li_data[i] = 0;
+
+	return;
+}
+
+static struct inode *logfs_alloc_inode(struct super_block *sb)
+{
+	struct logfs_inode *li;
+
+	li = kmem_cache_alloc(logfs_inode_cache, GFP_NOFS);
+	if (!li)
+		return NULL;
+	logfs_init_inode(sb, &li->vfs_inode);
+	return &li->vfs_inode;
+}
+
+/*
+ * In logfs inodes are written to an inode file.  The inode file, like any
+ * other file, is managed with a inode.  The inode file's inode, aka master
+ * inode, requires special handling in several respects.  First, it cannot be
+ * written to the inode file, so it is stored in the journal instead.
+ *
+ * Secondly, this inode cannot be written back and destroyed before all other
+ * inodes have been written.  The ordering is important.  Linux' VFS is happily
+ * unaware of the ordering constraint and would ordinarily destroy the master
+ * inode at umount time while other inodes are still in use and dirty.  Not
+ * good.
+ *
+ * So logfs makes sure the master inode is not written until all other inodes
+ * have been destroyed.  Sadly, this method has another side-effect.  The VFS
+ * will notice one remaining inode and print a frightening warning message.
+ * Worse, it is impossible to judge whether such a warning was caused by the
+ * master inode or any other inodes have leaked as well.
+ *
+ * Our attempt of solving this is with logfs_new_meta_inode() below.  Its
+ * purpose is to create a new inode that will not trigger the warning if such
+ * an inode is still in use.  An ugly hack, no doubt.  Suggections for
+ * improvement are welcome.
+ */
+struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino)
+{
+	struct inode *inode;
+
+	inode = logfs_alloc_inode(sb);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
+	inode->i_mode = S_IFREG;
+	inode->i_ino = ino;
+	inode->i_sb = sb;
+
+	/* This is a blatant copy of alloc_inode code.  We'd need alloc_inode
+	 * to be nonstatic, alas. */
+	{
+		struct address_space * const mapping = &inode->i_data;
+
+		mapping->a_ops = &logfs_reg_aops;
+		mapping->host = inode;
+		mapping->flags = 0;
+		mapping_set_gfp_mask(mapping, GFP_NOFS);
+		mapping->assoc_mapping = NULL;
+		mapping->backing_dev_info = &default_backing_dev_info;
+		inode->i_mapping = mapping;
+		inode->i_nlink = 1;
+	}
+
+	return inode;
+}
+
+struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino)
+{
+	struct inode *inode;
+	int err;
+
+	inode = logfs_new_meta_inode(sb, ino);
+	if (IS_ERR(inode))
+		return inode;
+
+	err = logfs_read_inode(inode);
+	if (err) {
+		destroy_meta_inode(inode);
+		return ERR_PTR(err);
+	}
+	logfs_inode_setops(inode);
+	return inode;
+}
+
+static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+	int ret;
+	long flags = WF_LOCK;
+
+	/* Can only happen if creat() failed.  Safe to skip. */
+	if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN)
+		return 0;
+
+	ret = __logfs_write_inode(inode, flags);
+	LOGFS_BUG_ON(ret, inode->i_sb);
+	return ret;
+}
+
+void destroy_meta_inode(struct inode *inode)
+{
+	if (inode) {
+		if (inode->i_data.nrpages)
+			truncate_inode_pages(&inode->i_data, 0);
+		logfs_clear_inode(inode);
+		kmem_cache_free(logfs_inode_cache, logfs_inode(inode));
+	}
+}
+
+/* called with inode_lock held */
+static void logfs_drop_inode(struct inode *inode)
+{
+	struct logfs_super *super = logfs_super(inode->i_sb);
+	struct logfs_inode *li = logfs_inode(inode);
+
+	spin_lock(&logfs_inode_lock);
+	list_move(&li->li_freeing_list, &super->s_freeing_list);
+	spin_unlock(&logfs_inode_lock);
+	generic_drop_inode(inode);
+}
+
+static void logfs_set_ino_generation(struct super_block *sb,
+		struct inode *inode)
+{
+	struct logfs_super *super = logfs_super(sb);
+	u64 ino;
+
+	mutex_lock(&super->s_journal_mutex);
+	ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino);
+	super->s_last_ino = ino;
+	super->s_inos_till_wrap--;
+	if (super->s_inos_till_wrap < 0) {
+		super->s_last_ino = LOGFS_RESERVED_INOS;
+		super->s_generation++;
+		super->s_inos_till_wrap = INOS_PER_WRAP;
+	}
+	inode->i_ino = ino;
+	inode->i_generation = super->s_generation;
+	mutex_unlock(&super->s_journal_mutex);
+}
+
+struct inode *logfs_new_inode(struct inode *dir, int mode)
+{
+	struct super_block *sb = dir->i_sb;
+	struct inode *inode;
+
+	inode = new_inode(sb);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
+	logfs_init_inode(sb, inode);
+
+	/* inherit parent flags */
+	logfs_inode(inode)->li_flags |=
+		logfs_inode(dir)->li_flags & LOGFS_FL_INHERITED;
+
+	inode->i_mode = mode;
+	logfs_set_ino_generation(sb, inode);
+
+	inode->i_uid = current_fsuid();
+	inode->i_gid = current_fsgid();
+	if (dir->i_mode & S_ISGID) {
+		inode->i_gid = dir->i_gid;
+		if (S_ISDIR(mode))
+			inode->i_mode |= S_ISGID;
+	}
+
+	logfs_inode_setops(inode);
+	insert_inode_hash(inode);
+
+	return inode;
+}
+
+static void logfs_init_once(void *_li)
+{
+	struct logfs_inode *li = _li;
+	int i;
+
+	li->li_flags = 0;
+	li->li_used_bytes = 0;
+	li->li_refcount = 1;
+	for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+		li->li_data[i] = 0;
+	inode_init_once(&li->vfs_inode);
+}
+
+static int logfs_sync_fs(struct super_block *sb, int wait)
+{
+	/* FIXME: write anchor */
+	logfs_super(sb)->s_devops->sync(sb);
+	return 0;
+}
+
+const struct super_operations logfs_super_operations = {
+	.alloc_inode	= logfs_alloc_inode,
+	.clear_inode	= logfs_clear_inode,
+	.delete_inode	= logfs_delete_inode,
+	.destroy_inode	= logfs_destroy_inode,
+	.drop_inode	= logfs_drop_inode,
+	.write_inode	= logfs_write_inode,
+	.statfs		= logfs_statfs,
+	.sync_fs	= logfs_sync_fs,
+};
+
+int logfs_init_inode_cache(void)
+{
+	logfs_inode_cache = kmem_cache_create("logfs_inode_cache",
+			sizeof(struct logfs_inode), 0, SLAB_RECLAIM_ACCOUNT,
+			logfs_init_once);
+	if (!logfs_inode_cache)
+		return -ENOMEM;
+	return 0;
+}
+
+void logfs_destroy_inode_cache(void)
+{
+	kmem_cache_destroy(logfs_inode_cache);
+}
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
new file mode 100644
index 0000000..6ad30a4
--- /dev/null
+++ b/fs/logfs/journal.c
@@ -0,0 +1,883 @@
+/*
+ * fs/logfs/journal.c	- journal handling code
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+
+static void logfs_calc_free(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	u64 reserve, no_segs = super->s_no_segs;
+	s64 free;
+	int i;
+
+	/* superblock segments */
+	no_segs -= 2;
+	super->s_no_journal_segs = 0;
+	/* journal */
+	journal_for_each(i)
+		if (super->s_journal_seg[i]) {
+			no_segs--;
+			super->s_no_journal_segs++;
+		}
+
+	/* open segments plus one extra per level for GC */
+	no_segs -= 2 * super->s_total_levels;
+
+	free = no_segs * (super->s_segsize - LOGFS_SEGMENT_RESERVE);
+	free -= super->s_used_bytes;
+	/* just a bit extra */
+	free -= super->s_total_levels * 4096;
+
+	/* Bad blocks are 'paid' for with speed reserve - the filesystem
+	 * simply gets slower as bad blocks accumulate.  Until the bad blocks
+	 * exceed the speed reserve - then the filesystem gets smaller.
+	 */
+	reserve = super->s_bad_segments + super->s_bad_seg_reserve;
+	reserve *= super->s_segsize - LOGFS_SEGMENT_RESERVE;
+	reserve = max(reserve, super->s_speed_reserve);
+	free -= reserve;
+	if (free < 0)
+		free = 0;
+
+	super->s_free_bytes = free;
+}
+
+static void reserve_sb_and_journal(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct btree_head32 *head = &super->s_reserved_segments;
+	int i, err;
+
+	err = btree_insert32(head, seg_no(sb, super->s_sb_ofs[0]), (void *)1,
+			GFP_KERNEL);
+	BUG_ON(err);
+
+	err = btree_insert32(head, seg_no(sb, super->s_sb_ofs[1]), (void *)1,
+			GFP_KERNEL);
+	BUG_ON(err);
+
+	journal_for_each(i) {
+		if (!super->s_journal_seg[i])
+			continue;
+		err = btree_insert32(head, super->s_journal_seg[i], (void *)1,
+				GFP_KERNEL);
+		BUG_ON(err);
+	}
+}
+
+static void read_dynsb(struct super_block *sb,
+		struct logfs_je_dynsb *dynsb)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	super->s_gec		= be64_to_cpu(dynsb->ds_gec);
+	super->s_sweeper	= be64_to_cpu(dynsb->ds_sweeper);
+	super->s_victim_ino	= be64_to_cpu(dynsb->ds_victim_ino);
+	super->s_rename_dir	= be64_to_cpu(dynsb->ds_rename_dir);
+	super->s_rename_pos	= be64_to_cpu(dynsb->ds_rename_pos);
+	super->s_used_bytes	= be64_to_cpu(dynsb->ds_used_bytes);
+	super->s_generation	= be32_to_cpu(dynsb->ds_generation);
+}
+
+static void read_anchor(struct super_block *sb,
+		struct logfs_je_anchor *da)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct inode *inode = super->s_master_inode;
+	struct logfs_inode *li = logfs_inode(inode);
+	int i;
+
+	super->s_last_ino = be64_to_cpu(da->da_last_ino);
+	li->li_flags	= 0;
+	li->li_height	= da->da_height;
+	i_size_write(inode, be64_to_cpu(da->da_size));
+	li->li_used_bytes = be64_to_cpu(da->da_used_bytes);
+
+	for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+		li->li_data[i] = be64_to_cpu(da->da_data[i]);
+}
+
+static void read_erasecount(struct super_block *sb,
+		struct logfs_je_journal_ec *ec)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int i;
+
+	journal_for_each(i)
+		super->s_journal_ec[i] = be32_to_cpu(ec->ec[i]);
+}
+
+static int read_area(struct super_block *sb, struct logfs_je_area *a)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_area *area = super->s_area[a->gc_level];
+	u64 ofs;
+	u32 writemask = ~(super->s_writesize - 1);
+
+	if (a->gc_level >= LOGFS_NO_AREAS)
+		return -EIO;
+	if (a->vim != VIM_DEFAULT)
+		return -EIO; /* TODO: close area and continue */
+
+	area->a_used_bytes = be32_to_cpu(a->used_bytes);
+	area->a_written_bytes = area->a_used_bytes & writemask;
+	area->a_segno = be32_to_cpu(a->segno);
+	if (area->a_segno)
+		area->a_is_open = 1;
+
+	ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
+	if (super->s_writesize > 1)
+		logfs_buf_recover(area, ofs, a + 1, super->s_writesize);
+	else
+		logfs_buf_recover(area, ofs, NULL, 0);
+	return 0;
+}
+
+static void *unpack(void *from, void *to)
+{
+	struct logfs_journal_header *jh = from;
+	void *data = from + sizeof(struct logfs_journal_header);
+	int err;
+	size_t inlen, outlen;
+
+	inlen = be16_to_cpu(jh->h_len);
+	outlen = be16_to_cpu(jh->h_datalen);
+
+	if (jh->h_compr == COMPR_NONE)
+		memcpy(to, data, inlen);
+	else {
+		err = logfs_uncompress(data, to, inlen, outlen);
+		BUG_ON(err);
+	}
+	return to;
+}
+
+static int __read_je_header(struct super_block *sb, u64 ofs,
+		struct logfs_journal_header *jh)
+{
+	struct logfs_super *super = logfs_super(sb);
+	size_t bufsize = max_t(size_t, sb->s_blocksize, super->s_writesize)
+		+ MAX_JOURNAL_HEADER;
+	u16 type, len, datalen;
+	int err;
+
+	/* read header only */
+	err = wbuf_read(sb, ofs, sizeof(*jh), jh);
+	if (err)
+		return err;
+	type = be16_to_cpu(jh->h_type);
+	len = be16_to_cpu(jh->h_len);
+	datalen = be16_to_cpu(jh->h_datalen);
+	if (len > sb->s_blocksize)
+		return -EIO;
+	if ((type < JE_FIRST) || (type > JE_LAST))
+		return -EIO;
+	if (datalen > bufsize)
+		return -EIO;
+	return 0;
+}
+
+static int __read_je_payload(struct super_block *sb, u64 ofs,
+		struct logfs_journal_header *jh)
+{
+	u16 len;
+	int err;
+
+	len = be16_to_cpu(jh->h_len);
+	err = wbuf_read(sb, ofs + sizeof(*jh), len, jh + 1);
+	if (err)
+		return err;
+	if (jh->h_crc != logfs_crc32(jh, len + sizeof(*jh), 4)) {
+		/* Old code was confused.  It forgot about the header length
+		 * and stopped calculating the crc 16 bytes before the end
+		 * of data - ick!
+		 * FIXME: Remove this hack once the old code is fixed.
+		 */
+		if (jh->h_crc == logfs_crc32(jh, len, 4))
+			WARN_ON_ONCE(1);
+		else
+			return -EIO;
+	}
+	return 0;
+}
+
+/*
+ * jh needs to be large enough to hold the complete entry, not just the header
+ */
+static int __read_je(struct super_block *sb, u64 ofs,
+		struct logfs_journal_header *jh)
+{
+	int err;
+
+	err = __read_je_header(sb, ofs, jh);
+	if (err)
+		return err;
+	return __read_je_payload(sb, ofs, jh);
+}
+
+static int read_je(struct super_block *sb, u64 ofs)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_journal_header *jh = super->s_compressed_je;
+	void *scratch = super->s_je;
+	u16 type, datalen;
+	int err;
+
+	err = __read_je(sb, ofs, jh);
+	if (err)
+		return err;
+	type = be16_to_cpu(jh->h_type);
+	datalen = be16_to_cpu(jh->h_datalen);
+
+	switch (type) {
+	case JE_DYNSB:
+		read_dynsb(sb, unpack(jh, scratch));
+		break;
+	case JE_ANCHOR:
+		read_anchor(sb, unpack(jh, scratch));
+		break;
+	case JE_ERASECOUNT:
+		read_erasecount(sb, unpack(jh, scratch));
+		break;
+	case JE_AREA:
+		read_area(sb, unpack(jh, scratch));
+		break;
+	case JE_OBJ_ALIAS:
+		err = logfs_load_object_aliases(sb, unpack(jh, scratch),
+				datalen);
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return -EIO;
+	}
+	return err;
+}
+
+static int logfs_read_segment(struct super_block *sb, u32 segno)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_journal_header *jh = super->s_compressed_je;
+	u64 ofs, seg_ofs = dev_ofs(sb, segno, 0);
+	u32 h_ofs, last_ofs = 0;
+	u16 len, datalen, last_len = 0;
+	int i, err;
+
+	/* search for most recent commit */
+	for (h_ofs = 0; h_ofs < super->s_segsize; h_ofs += sizeof(*jh)) {
+		ofs = seg_ofs + h_ofs;
+		err = __read_je_header(sb, ofs, jh);
+		if (err)
+			continue;
+		if (jh->h_type != cpu_to_be16(JE_COMMIT))
+			continue;
+		err = __read_je_payload(sb, ofs, jh);
+		if (err)
+			continue;
+		len = be16_to_cpu(jh->h_len);
+		datalen = be16_to_cpu(jh->h_datalen);
+		if ((datalen > sizeof(super->s_je_array)) ||
+				(datalen % sizeof(__be64)))
+			continue;
+		last_ofs = h_ofs;
+		last_len = datalen;
+		h_ofs += ALIGN(len, sizeof(*jh)) - sizeof(*jh);
+	}
+	/* read commit */
+	if (last_ofs == 0)
+		return -ENOENT;
+	ofs = seg_ofs + last_ofs;
+	log_journal("Read commit from %llx\n", ofs);
+	err = __read_je(sb, ofs, jh);
+	BUG_ON(err); /* We should have caught it in the scan loop already */
+	if (err)
+		return err;
+	/* uncompress */
+	unpack(jh, super->s_je_array);
+	super->s_no_je = last_len / sizeof(__be64);
+	/* iterate over array */
+	for (i = 0; i < super->s_no_je; i++) {
+		err = read_je(sb, be64_to_cpu(super->s_je_array[i]));
+		if (err)
+			return err;
+	}
+	super->s_journal_area->a_segno = segno;
+	return 0;
+}
+
+static u64 read_gec(struct super_block *sb, u32 segno)
+{
+	struct logfs_segment_header sh;
+	__be32 crc;
+	int err;
+
+	if (!segno)
+		return 0;
+	err = wbuf_read(sb, dev_ofs(sb, segno, 0), sizeof(sh), &sh);
+	if (err)
+		return 0;
+	crc = logfs_crc32(&sh, sizeof(sh), 4);
+	if (crc != sh.crc) {
+		WARN_ON(sh.gec != cpu_to_be64(0xffffffffffffffffull));
+		/* Most likely it was just erased */
+		return 0;
+	}
+	return be64_to_cpu(sh.gec);
+}
+
+static int logfs_read_journal(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	u64 gec[LOGFS_JOURNAL_SEGS], max;
+	u32 segno;
+	int i, max_i;
+
+	max = 0;
+	max_i = -1;
+	journal_for_each(i) {
+		segno = super->s_journal_seg[i];
+		gec[i] = read_gec(sb, super->s_journal_seg[i]);
+		if (gec[i] > max) {
+			max = gec[i];
+			max_i = i;
+		}
+	}
+	if (max_i == -1)
+		return -EIO;
+	/* FIXME: Try older segments in case of error */
+	return logfs_read_segment(sb, super->s_journal_seg[max_i]);
+}
+
+/*
+ * First search the current segment (outer loop), then pick the next segment
+ * in the array, skipping any zero entries (inner loop).
+ */
+static void journal_get_free_segment(struct logfs_area *area)
+{
+	struct logfs_super *super = logfs_super(area->a_sb);
+	int i;
+
+	journal_for_each(i) {
+		if (area->a_segno != super->s_journal_seg[i])
+			continue;
+
+		do {
+			i++;
+			if (i == LOGFS_JOURNAL_SEGS)
+				i = 0;
+		} while (!super->s_journal_seg[i]);
+
+		area->a_segno = super->s_journal_seg[i];
+		area->a_erase_count = ++(super->s_journal_ec[i]);
+		log_journal("Journal now at %x (ec %x)\n", area->a_segno,
+				area->a_erase_count);
+		return;
+	}
+	BUG();
+}
+
+static void journal_get_erase_count(struct logfs_area *area)
+{
+	/* erase count is stored globally and incremented in
+	 * journal_get_free_segment() - nothing to do here */
+}
+
+static int journal_erase_segment(struct logfs_area *area)
+{
+	struct super_block *sb = area->a_sb;
+	struct logfs_segment_header sh;
+	u64 ofs;
+	int err;
+
+	err = logfs_erase_segment(sb, area->a_segno, 1);
+	if (err)
+		return err;
+
+	sh.pad = 0;
+	sh.type = SEG_JOURNAL;
+	sh.level = 0;
+	sh.segno = cpu_to_be32(area->a_segno);
+	sh.ec = cpu_to_be32(area->a_erase_count);
+	sh.gec = cpu_to_be64(logfs_super(sb)->s_gec);
+	sh.crc = logfs_crc32(&sh, sizeof(sh), 4);
+
+	/* This causes a bug in segment.c.  Not yet. */
+	//logfs_set_segment_erased(sb, area->a_segno, area->a_erase_count, 0);
+
+	ofs = dev_ofs(sb, area->a_segno, 0);
+	area->a_used_bytes = ALIGN(sizeof(sh), 16);
+	logfs_buf_write(area, ofs, &sh, sizeof(sh));
+	return 0;
+}
+
+static size_t __logfs_write_header(struct logfs_super *super,
+		struct logfs_journal_header *jh, size_t len, size_t datalen,
+		u16 type, u8 compr)
+{
+	jh->h_len	= cpu_to_be16(len);
+	jh->h_type	= cpu_to_be16(type);
+	jh->h_datalen	= cpu_to_be16(datalen);
+	jh->h_compr	= compr;
+	jh->h_pad[0]	= 'H';
+	jh->h_pad[1]	= 'E';
+	jh->h_pad[2]	= 'A';
+	jh->h_pad[3]	= 'D';
+	jh->h_pad[4]	= 'R';
+	jh->h_crc	= logfs_crc32(jh, len + sizeof(*jh), 4);
+	return ALIGN(len, 16) + sizeof(*jh);
+}
+
+static size_t logfs_write_header(struct logfs_super *super,
+		struct logfs_journal_header *jh, size_t datalen, u16 type)
+{
+	size_t len = datalen;
+
+	return __logfs_write_header(super, jh, len, datalen, type, COMPR_NONE);
+}
+
+static inline size_t logfs_journal_erasecount_size(struct logfs_super *super)
+{
+	return LOGFS_JOURNAL_SEGS * sizeof(__be32);
+}
+
+static void *logfs_write_erasecount(struct super_block *sb, void *_ec,
+		u16 *type, size_t *len)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_je_journal_ec *ec = _ec;
+	int i;
+
+	journal_for_each(i)
+		ec->ec[i] = cpu_to_be32(super->s_journal_ec[i]);
+	*type = JE_ERASECOUNT;
+	*len = logfs_journal_erasecount_size(super);
+	return ec;
+}
+
+static void account_shadow(void *_shadow, unsigned long _sb, u64 ignore,
+		size_t ignore2)
+{
+	struct logfs_shadow *shadow = _shadow;
+	struct super_block *sb = (void *)_sb;
+	struct logfs_super *super = logfs_super(sb);
+
+	/* consume new space */
+	super->s_free_bytes	  -= shadow->new_len;
+	super->s_used_bytes	  += shadow->new_len;
+	super->s_dirty_used_bytes -= shadow->new_len;
+
+	/* free up old space */
+	super->s_free_bytes	  += shadow->old_len;
+	super->s_used_bytes	  -= shadow->old_len;
+	super->s_dirty_free_bytes -= shadow->old_len;
+
+	logfs_set_segment_used(sb, shadow->old_ofs, -shadow->old_len);
+	logfs_set_segment_used(sb, shadow->new_ofs, shadow->new_len);
+
+	log_journal("account_shadow(%llx, %llx, %x) %llx->%llx %x->%x\n",
+			shadow->ino, shadow->bix, shadow->gc_level,
+			shadow->old_ofs, shadow->new_ofs,
+			shadow->old_len, shadow->new_len);
+	mempool_free(shadow, super->s_shadow_pool);
+}
+
+static void account_shadows(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct inode *inode = super->s_master_inode;
+	struct logfs_inode *li = logfs_inode(inode);
+	struct shadow_tree *tree = &super->s_shadow_tree;
+
+	btree_grim_visitor64(&tree->new, (unsigned long)sb, account_shadow);
+	btree_grim_visitor64(&tree->old, (unsigned long)sb, account_shadow);
+
+	if (li->li_block) {
+		/*
+		 * We never actually use the structure, when attached to the
+		 * master inode.  But it is easier to always free it here than
+		 * to have checks in several places elsewhere when allocating
+		 * it.
+		 */
+		li->li_block->ops->free_block(sb, li->li_block);
+	}
+	BUG_ON((s64)li->li_used_bytes < 0);
+}
+
+static void *__logfs_write_anchor(struct super_block *sb, void *_da,
+		u16 *type, size_t *len)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_je_anchor *da = _da;
+	struct inode *inode = super->s_master_inode;
+	struct logfs_inode *li = logfs_inode(inode);
+	int i;
+
+	da->da_height	= li->li_height;
+	da->da_last_ino = cpu_to_be64(super->s_last_ino);
+	da->da_size	= cpu_to_be64(i_size_read(inode));
+	da->da_used_bytes = cpu_to_be64(li->li_used_bytes);
+	for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+		da->da_data[i] = cpu_to_be64(li->li_data[i]);
+	*type = JE_ANCHOR;
+	*len = sizeof(*da);
+	return da;
+}
+
+static void *logfs_write_dynsb(struct super_block *sb, void *_dynsb,
+		u16 *type, size_t *len)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_je_dynsb *dynsb = _dynsb;
+
+	dynsb->ds_gec		= cpu_to_be64(super->s_gec);
+	dynsb->ds_sweeper	= cpu_to_be64(super->s_sweeper);
+	dynsb->ds_victim_ino	= cpu_to_be64(super->s_victim_ino);
+	dynsb->ds_rename_dir	= cpu_to_be64(super->s_rename_dir);
+	dynsb->ds_rename_pos	= cpu_to_be64(super->s_rename_pos);
+	dynsb->ds_used_bytes	= cpu_to_be64(super->s_used_bytes);
+	dynsb->ds_generation	= cpu_to_be32(super->s_generation);
+	*type = JE_DYNSB;
+	*len = sizeof(*dynsb);
+	return dynsb;
+}
+
+static void write_wbuf(struct super_block *sb, struct logfs_area *area,
+		void *wbuf)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping = super->s_mapping_inode->i_mapping;
+	u64 ofs;
+	pgoff_t index;
+	int page_ofs;
+	struct page *page;
+
+	ofs = dev_ofs(sb, area->a_segno,
+			area->a_used_bytes & ~(super->s_writesize - 1));
+	index = ofs >> PAGE_SHIFT;
+	page_ofs = ofs & (PAGE_SIZE - 1);
+
+	page = find_lock_page(mapping, index);
+	BUG_ON(!page);
+	memcpy(wbuf, page_address(page) + page_ofs, super->s_writesize);
+	unlock_page(page);
+}
+
+static void *logfs_write_area(struct super_block *sb, void *_a,
+		u16 *type, size_t *len)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_area *area = super->s_area[super->s_sum_index];
+	struct logfs_je_area *a = _a;
+
+	a->vim = VIM_DEFAULT;
+	a->gc_level = super->s_sum_index;
+	a->used_bytes = cpu_to_be32(area->a_used_bytes);
+	a->segno = cpu_to_be32(area->a_segno);
+	if (super->s_writesize > 1)
+		write_wbuf(sb, area, a + 1);
+
+	*type = JE_AREA;
+	*len = sizeof(*a) + super->s_writesize;
+	return a;
+}
+
+static void *logfs_write_commit(struct super_block *sb, void *h,
+		u16 *type, size_t *len)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	*type = JE_COMMIT;
+	*len = super->s_no_je * sizeof(__be64);
+	return super->s_je_array;
+}
+
+static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type,
+		size_t len)
+{
+	struct logfs_super *super = logfs_super(sb);
+	void *header = super->s_compressed_je;
+	void *data = header + sizeof(struct logfs_journal_header);
+	ssize_t compr_len, pad_len;
+	u8 compr = COMPR_ZLIB;
+
+	if (len == 0)
+		return logfs_write_header(super, header, 0, type);
+
+	compr_len = logfs_compress(buf, data, len, sb->s_blocksize);
+	if (compr_len < 0 || type == JE_ANCHOR) {
+		BUG_ON(len > sb->s_blocksize);
+		memcpy(data, buf, len);
+		compr_len = len;
+		compr = COMPR_NONE;
+	}
+
+	pad_len = ALIGN(compr_len, 16);
+	memset(data + compr_len, 0, pad_len - compr_len);
+
+	return __logfs_write_header(super, header, compr_len, len, type, compr);
+}
+
+static s64 logfs_get_free_bytes(struct logfs_area *area, size_t *bytes,
+		int must_pad)
+{
+	u32 writesize = logfs_super(area->a_sb)->s_writesize;
+	s32 ofs;
+	int ret;
+
+	ret = logfs_open_area(area, *bytes);
+	if (ret)
+		return -EAGAIN;
+
+	ofs = area->a_used_bytes;
+	area->a_used_bytes += *bytes;
+
+	if (must_pad) {
+		area->a_used_bytes = ALIGN(area->a_used_bytes, writesize);
+		*bytes = area->a_used_bytes - ofs;
+	}
+
+	return dev_ofs(area->a_sb, area->a_segno, ofs);
+}
+
+static int logfs_write_je_buf(struct super_block *sb, void *buf, u16 type,
+		size_t buf_len)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_area *area = super->s_journal_area;
+	struct logfs_journal_header *jh = super->s_compressed_je;
+	size_t len;
+	int must_pad = 0;
+	s64 ofs;
+
+	len = __logfs_write_je(sb, buf, type, buf_len);
+	if (jh->h_type == cpu_to_be16(JE_COMMIT))
+		must_pad = 1;
+
+	ofs = logfs_get_free_bytes(area, &len, must_pad);
+	if (ofs < 0)
+		return ofs;
+	logfs_buf_write(area, ofs, super->s_compressed_je, len);
+	super->s_je_array[super->s_no_je++] = cpu_to_be64(ofs);
+	return 0;
+}
+
+static int logfs_write_je(struct super_block *sb,
+		void* (*write)(struct super_block *sb, void *scratch,
+			u16 *type, size_t *len))
+{
+	void *buf;
+	size_t len;
+	u16 type;
+
+	buf = write(sb, logfs_super(sb)->s_je, &type, &len);
+	return logfs_write_je_buf(sb, buf, type, len);
+}
+
+int write_alias_journal(struct super_block *sb, u64 ino, u64 bix,
+		level_t level, int child_no, __be64 val)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_obj_alias *oa = super->s_je;
+	int err = 0, fill = super->s_je_fill;
+
+	log_aliases("logfs_write_obj_aliases #%x(%llx, %llx, %x, %x) %llx\n",
+			fill, ino, bix, level, child_no, be64_to_cpu(val));
+	oa[fill].ino = cpu_to_be64(ino);
+	oa[fill].bix = cpu_to_be64(bix);
+	oa[fill].val = val;
+	oa[fill].level = (__force u8)level;
+	oa[fill].child_no = cpu_to_be16(child_no);
+	fill++;
+	if (fill >= sb->s_blocksize / sizeof(*oa)) {
+		err = logfs_write_je_buf(sb, oa, JE_OBJ_ALIAS, sb->s_blocksize);
+		fill = 0;
+	}
+
+	super->s_je_fill = fill;
+	return err;
+}
+
+static int logfs_write_obj_aliases(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int err;
+
+	log_journal("logfs_write_obj_aliases: %d aliases to write\n",
+			super->s_no_object_aliases);
+	super->s_je_fill = 0;
+	err = logfs_write_obj_aliases_pagecache(sb);
+	if (err)
+		return err;
+
+	if (super->s_je_fill)
+		err = logfs_write_je_buf(sb, super->s_je, JE_OBJ_ALIAS,
+				super->s_je_fill
+				* sizeof(struct logfs_obj_alias));
+	return err;
+}
+
+/*
+ * Write all journal entries.  The goto logic ensures that all journal entries
+ * are written whenever a new segment is used.  It is ugly and potentially a
+ * bit wasteful, but robustness is more important.  With this we can *always*
+ * erase all journal segments except the one containing the most recent commit.
+ */
+void logfs_write_anchor(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_area *area = super->s_journal_area;
+	int i, err;
+
+	if (!(super->s_flags & LOGFS_SB_FLAG_DIRTY))
+		return;
+	super->s_flags &= ~LOGFS_SB_FLAG_DIRTY;
+
+	BUG_ON(super->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
+	mutex_lock(&super->s_journal_mutex);
+
+	/* Do this first or suffer corruption */
+	logfs_sync_segments(sb);
+	account_shadows(sb);
+
+again:
+	super->s_no_je = 0;
+	for_each_area(i) {
+		if (!super->s_area[i]->a_is_open)
+			continue;
+		super->s_sum_index = i;
+		err = logfs_write_je(sb, logfs_write_area);
+		if (err)
+			goto again;
+	}
+	err = logfs_write_obj_aliases(sb);
+	if (err)
+		goto again;
+	err = logfs_write_je(sb, logfs_write_erasecount);
+	if (err)
+		goto again;
+	err = logfs_write_je(sb, __logfs_write_anchor);
+	if (err)
+		goto again;
+	err = logfs_write_je(sb, logfs_write_dynsb);
+	if (err)
+		goto again;
+	/*
+	 * Order is imperative.  First we sync all writes, including the
+	 * non-committed journal writes.  Then we write the final commit and
+	 * sync the current journal segment.
+	 * There is a theoretical bug here.  Syncing the journal segment will
+	 * write a number of journal entries and the final commit.  All these
+	 * are written in a single operation.  If the device layer writes the
+	 * data back-to-front, the commit will precede the other journal
+	 * entries, leaving a race window.
+	 * Two fixes are possible.  Preferred is to fix the device layer to
+	 * ensure writes happen front-to-back.  Alternatively we can insert
+	 * another logfs_sync_area() super->s_devops->sync() combo before
+	 * writing the commit.
+	 */
+	/*
+	 * On another subject, super->s_devops->sync is usually not necessary.
+	 * Unless called from sys_sync or friends, a barrier would suffice.
+	 */
+	super->s_devops->sync(sb);
+	err = logfs_write_je(sb, logfs_write_commit);
+	if (err)
+		goto again;
+	log_journal("Write commit to %llx\n",
+			be64_to_cpu(super->s_je_array[super->s_no_je - 1]));
+	logfs_sync_area(area);
+	BUG_ON(area->a_used_bytes != area->a_written_bytes);
+	super->s_devops->sync(sb);
+
+	mutex_unlock(&super->s_journal_mutex);
+	return;
+}
+
+void do_logfs_journal_wl_pass(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_area *area = super->s_journal_area;
+	u32 segno, ec;
+	int i, err;
+
+	log_journal("Journal requires wear-leveling.\n");
+	/* Drop old segments */
+	journal_for_each(i)
+		if (super->s_journal_seg[i]) {
+			logfs_set_segment_unreserved(sb,
+					super->s_journal_seg[i],
+					super->s_journal_ec[i]);
+			super->s_journal_seg[i] = 0;
+			super->s_journal_ec[i] = 0;
+		}
+	/* Get new segments */
+	for (i = 0; i < super->s_no_journal_segs; i++) {
+		segno = get_best_cand(sb, &super->s_reserve_list, &ec);
+		super->s_journal_seg[i] = segno;
+		super->s_journal_ec[i] = ec;
+		logfs_set_segment_reserved(sb, segno);
+	}
+	/* Manually move journal_area */
+	area->a_segno = super->s_journal_seg[0];
+	area->a_is_open = 0;
+	area->a_used_bytes = 0;
+	/* Write journal */
+	logfs_write_anchor(sb);
+	/* Write superblocks */
+	err = logfs_write_sb(sb);
+	BUG_ON(err);
+}
+
+static const struct logfs_area_ops journal_area_ops = {
+	.get_free_segment	= journal_get_free_segment,
+	.get_erase_count	= journal_get_erase_count,
+	.erase_segment		= journal_erase_segment,
+};
+
+int logfs_init_journal(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	size_t bufsize = max_t(size_t, sb->s_blocksize, super->s_writesize)
+		+ MAX_JOURNAL_HEADER;
+	int ret = -ENOMEM;
+
+	mutex_init(&super->s_journal_mutex);
+	btree_init_mempool32(&super->s_reserved_segments, super->s_btree_pool);
+
+	super->s_je = kzalloc(bufsize, GFP_KERNEL);
+	if (!super->s_je)
+		return ret;
+
+	super->s_compressed_je = kzalloc(bufsize, GFP_KERNEL);
+	if (!super->s_compressed_je)
+		return ret;
+
+	super->s_master_inode = logfs_new_meta_inode(sb, LOGFS_INO_MASTER);
+	if (IS_ERR(super->s_master_inode))
+		return PTR_ERR(super->s_master_inode);
+
+	ret = logfs_read_journal(sb);
+	if (ret)
+		return -EIO;
+
+	reserve_sb_and_journal(sb);
+	logfs_calc_free(sb);
+
+	super->s_journal_area->a_ops = &journal_area_ops;
+	return 0;
+}
+
+void logfs_cleanup_journal(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	btree_grim_visitor32(&super->s_reserved_segments, 0, NULL);
+	destroy_meta_inode(super->s_master_inode);
+	super->s_master_inode = NULL;
+
+	kfree(super->s_compressed_je);
+	kfree(super->s_je);
+}
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
new file mode 100644
index 0000000..1297794
--- /dev/null
+++ b/fs/logfs/logfs.h
@@ -0,0 +1,724 @@
+/*
+ * fs/logfs/logfs.h
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ *
+ * Private header for logfs.
+ */
+#ifndef FS_LOGFS_LOGFS_H
+#define FS_LOGFS_LOGFS_H
+
+#undef __CHECK_ENDIAN__
+#define __CHECK_ENDIAN__
+
+#include <linux/btree.h>
+#include <linux/crc32.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+#include <linux/pagemap.h>
+#include <linux/mtd/mtd.h>
+#include "logfs_abi.h"
+
+#define LOGFS_DEBUG_SUPER	(0x0001)
+#define LOGFS_DEBUG_SEGMENT	(0x0002)
+#define LOGFS_DEBUG_JOURNAL	(0x0004)
+#define LOGFS_DEBUG_DIR		(0x0008)
+#define LOGFS_DEBUG_FILE	(0x0010)
+#define LOGFS_DEBUG_INODE	(0x0020)
+#define LOGFS_DEBUG_READWRITE	(0x0040)
+#define LOGFS_DEBUG_GC		(0x0080)
+#define LOGFS_DEBUG_GC_NOISY	(0x0100)
+#define LOGFS_DEBUG_ALIASES	(0x0200)
+#define LOGFS_DEBUG_BLOCKMOVE	(0x0400)
+#define LOGFS_DEBUG_ALL		(0xffffffff)
+
+#define LOGFS_DEBUG		(0x01)
+/*
+ * To enable specific log messages, simply define LOGFS_DEBUG to match any
+ * or all of the above.
+ */
+#ifndef LOGFS_DEBUG
+#define LOGFS_DEBUG		(0)
+#endif
+
+#define log_cond(cond, fmt, arg...) do {	\
+	if (cond)				\
+		printk(KERN_DEBUG fmt, ##arg);	\
+} while (0)
+
+#define log_super(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_SUPER, fmt, ##arg)
+#define log_segment(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_SEGMENT, fmt, ##arg)
+#define log_journal(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_JOURNAL, fmt, ##arg)
+#define log_dir(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_DIR, fmt, ##arg)
+#define log_file(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_FILE, fmt, ##arg)
+#define log_inode(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_INODE, fmt, ##arg)
+#define log_readwrite(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_READWRITE, fmt, ##arg)
+#define log_gc(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_GC, fmt, ##arg)
+#define log_gc_noisy(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_GC_NOISY, fmt, ##arg)
+#define log_aliases(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_ALIASES, fmt, ##arg)
+#define log_blockmove(fmt, arg...) \
+	log_cond(LOGFS_DEBUG & LOGFS_DEBUG_BLOCKMOVE, fmt, ##arg)
+
+#define PG_pre_locked		PG_owner_priv_1
+#define PagePreLocked(page)	test_bit(PG_pre_locked, &(page)->flags)
+#define SetPagePreLocked(page)	set_bit(PG_pre_locked, &(page)->flags)
+#define ClearPagePreLocked(page) clear_bit(PG_pre_locked, &(page)->flags)
+
+/* FIXME: This should really be somewhere in the 64bit area. */
+#define LOGFS_LINK_MAX		(1<<30)
+
+/* Read-only filesystem */
+#define LOGFS_SB_FLAG_RO	0x0001
+#define LOGFS_SB_FLAG_DIRTY	0x0002
+#define LOGFS_SB_FLAG_OBJ_ALIAS	0x0004
+#define LOGFS_SB_FLAG_SHUTDOWN	0x0008
+
+/* Write Control Flags */
+#define WF_LOCK			0x01 /* take write lock */
+#define WF_WRITE		0x02 /* write block */
+#define WF_DELETE		0x04 /* delete old block */
+
+typedef u8 __bitwise level_t;
+typedef u8 __bitwise gc_level_t;
+
+#define LEVEL(level) ((__force level_t)(level))
+#define GC_LEVEL(gc_level) ((__force gc_level_t)(gc_level))
+
+#define SUBLEVEL(level) ( (void)((level) == LEVEL(1)),	\
+		(__force level_t)((__force u8)(level) - 1) )
+
+/**
+ * struct logfs_area - area management information
+ *
+ * @a_sb:			the superblock this area belongs to
+ * @a_is_open:			1 if the area is currently open, else 0
+ * @a_segno:			segment number of area
+ * @a_written_bytes:		number of bytes already written back
+ * @a_used_bytes:		number of used bytes
+ * @a_ops:			area operations (either journal or ostore)
+ * @a_erase_count:		erase count
+ * @a_level:			GC level
+ */
+struct logfs_area { /* a segment open for writing */
+	struct super_block *a_sb;
+	int	a_is_open;
+	u32	a_segno;
+	u32	a_written_bytes;
+	u32	a_used_bytes;
+	const struct logfs_area_ops *a_ops;
+	u32	a_erase_count;
+	gc_level_t a_level;
+};
+
+/**
+ * struct logfs_area_ops - area operations
+ *
+ * @get_free_segment:		fill area->ofs with the offset of a free segment
+ * @get_erase_count:		fill area->erase_count (needs area->ofs)
+ * @erase_segment:		erase and setup segment
+ */
+struct logfs_area_ops {
+	void	(*get_free_segment)(struct logfs_area *area);
+	void	(*get_erase_count)(struct logfs_area *area);
+	int	(*erase_segment)(struct logfs_area *area);
+};
+
+/**
+ * struct logfs_device_ops - device access operations
+ *
+ * @readpage:			read one page (mm page)
+ * @writeseg:			write one segment.  may be a partial segment
+ * @erase:			erase one segment
+ * @read:			read from the device
+ * @erase:			erase part of the device
+ */
+struct logfs_device_ops {
+	struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs);
+	struct page *(*find_last_sb)(struct super_block *sb, u64 *ofs);
+	int (*write_sb)(struct super_block *sb, struct page *page);
+	int (*readpage)(void *_sb, struct page *page);
+	void (*writeseg)(struct super_block *sb, u64 ofs, size_t len);
+	int (*erase)(struct super_block *sb, loff_t ofs, size_t len,
+			int ensure_write);
+	void (*sync)(struct super_block *sb);
+	void (*put_device)(struct super_block *sb);
+};
+
+/**
+ * struct candidate_list - list of similar candidates
+ */
+struct candidate_list {
+	struct rb_root rb_tree;
+	int count;
+	int maxcount;
+	int sort_by_ec;
+};
+
+/**
+ * struct gc_candidate - "candidate" segment to be garbage collected next
+ *
+ * @list:			list (either free of low)
+ * @segno:			segment number
+ * @valid:			number of valid bytes
+ * @erase_count:		erase count of segment
+ * @dist:			distance from tree root
+ *
+ * Candidates can be on two lists.  The free list contains electees rather
+ * than candidates - segments that no longer contain any valid data.  The
+ * low list contains candidates to be picked for GC.  It should be kept
+ * short.  It is not required to always pick a perfect candidate.  In the
+ * worst case GC will have to move more data than absolutely necessary.
+ */
+struct gc_candidate {
+	struct rb_node rb_node;
+	struct candidate_list *list;
+	u32	segno;
+	u32	valid;
+	u32	erase_count;
+	u8	dist;
+};
+
+/**
+ * struct logfs_journal_entry - temporary structure used during journal scan
+ *
+ * @used:
+ * @version:			normalized version
+ * @len:			length
+ * @offset:			offset
+ */
+struct logfs_journal_entry {
+	int used;
+	s16 version;
+	u16 len;
+	u16 datalen;
+	u64 offset;
+};
+
+enum transaction_state {
+	CREATE_1 = 1,
+	CREATE_2,
+	UNLINK_1,
+	UNLINK_2,
+	CROSS_RENAME_1,
+	CROSS_RENAME_2,
+	TARGET_RENAME_1,
+	TARGET_RENAME_2,
+	TARGET_RENAME_3
+};
+
+/**
+ * struct logfs_transaction - essential fields to support atomic dirops
+ *
+ * @ino:			target inode
+ * @dir:			inode of directory containing dentry
+ * @pos:			pos of dentry in directory
+ */
+struct logfs_transaction {
+	enum transaction_state state;
+	u64	 ino;
+	u64	 dir;
+	u64	 pos;
+};
+
+/**
+ * struct logfs_shadow - old block in the shadow of a not-yet-committed new one
+ * @old_ofs:			offset of old block on medium
+ * @new_ofs:			offset of new block on medium
+ * @ino:			inode number
+ * @bix:			block index
+ * @old_len:			size of old block, including header
+ * @new_len:			size of new block, including header
+ * @level:			block level
+ */
+struct logfs_shadow {
+	u64 old_ofs;
+	u64 new_ofs;
+	u64 ino;
+	u64 bix;
+	int old_len;
+	int new_len;
+	gc_level_t gc_level;
+};
+
+/**
+ * struct shadow_tree
+ * @new:			shadows where old_ofs==0, indexed by new_ofs
+ * @old:			shadows where old_ofs!=0, indexed by old_ofs
+ */
+struct shadow_tree {
+	struct btree_head64 new;
+	struct btree_head64 old;
+};
+
+struct object_alias_item {
+	struct list_head list;
+	__be64 val;
+	int child_no;
+};
+
+/**
+ * struct logfs_block - contains any block state
+ * @type:			indirect block or inode
+ * @full:			number of fully populated children
+ * @partial:			number of partially populated children
+ *
+ * Most blocks are directly represented by page cache pages.  But when a block
+ * becomes dirty, is part of a transaction, contains aliases or is otherwise
+ * special, a struct logfs_block is allocated to track the additional state.
+ * Inodes are very similar to indirect blocks, so they can also get one of
+ * these structures added when appropriate.
+ */
+#define BLOCK_INDIRECT	1	/* Indirect block */
+#define BLOCK_INODE	2	/* Inode */
+struct logfs_block_ops;
+struct logfs_block {
+	struct list_head alias_list;
+	struct list_head item_list;
+	struct super_block *sb;
+	u64 ino;
+	u64 bix;
+	level_t level;
+	struct page *page;
+	struct inode *inode;
+	struct logfs_transaction *ta;
+	unsigned long alias_map[LOGFS_BLOCK_FACTOR / BITS_PER_LONG];
+	struct logfs_block_ops *ops;
+	int full;
+	int partial;
+	int reserved_bytes;
+};
+
+typedef int write_alias_t(struct super_block *sb, u64 ino, u64 bix,
+		level_t level, int child_no, __be64 val);
+struct logfs_block_ops {
+	void	(*write_block)(struct logfs_block *block);
+	gc_level_t	(*block_level)(struct logfs_block *block);
+	void	(*free_block)(struct super_block *sb, struct logfs_block*block);
+	int	(*write_alias)(struct super_block *sb,
+			struct logfs_block *block,
+			write_alias_t *write_one_alias);
+};
+
+struct logfs_super {
+	struct mtd_info *s_mtd;			/* underlying device */
+	struct block_device *s_bdev;		/* underlying device */
+	const struct logfs_device_ops *s_devops;/* device access */
+	struct inode	*s_master_inode;	/* inode file */
+	struct inode	*s_segfile_inode;	/* segment file */
+	struct inode *s_mapping_inode;		/* device mapping */
+	atomic_t s_pending_writes;		/* outstanting bios */
+	long	 s_flags;
+	mempool_t *s_btree_pool;		/* for btree nodes */
+	mempool_t *s_alias_pool;		/* aliases in segment.c */
+	u64	 s_feature_incompat;
+	u64	 s_feature_ro_compat;
+	u64	 s_feature_compat;
+	u64	 s_feature_flags;
+	u64	 s_sb_ofs[2];
+	struct page *s_erase_page;		/* for dev_bdev.c */
+	/* alias.c fields */
+	struct btree_head32 s_segment_alias;	/* remapped segments */
+	int	 s_no_object_aliases;
+	struct list_head s_object_alias;	/* remapped objects */
+	struct btree_head128 s_object_alias_tree; /* remapped objects */
+	struct mutex s_object_alias_mutex;
+	/* dir.c fields */
+	struct mutex s_dirop_mutex;		/* for creat/unlink/rename */
+	u64	 s_victim_ino;			/* used for atomic dir-ops */
+	u64	 s_rename_dir;			/* source directory ino */
+	u64	 s_rename_pos;			/* position of source dd */
+	/* gc.c fields */
+	long	 s_segsize;			/* size of a segment */
+	int	 s_segshift;			/* log2 of segment size */
+	long	 s_segmask;			/* 1 << s_segshift - 1 */
+	long	 s_no_segs;			/* segments on device */
+	long	 s_no_journal_segs;		/* segments used for journal */
+	long	 s_no_blocks;			/* blocks per segment */
+	long	 s_writesize;			/* minimum write size */
+	int	 s_writeshift;			/* log2 of write size */
+	u64	 s_size;			/* filesystem size */
+	struct logfs_area *s_area[LOGFS_NO_AREAS];	/* open segment array */
+	u64	 s_gec;				/* global erase count */
+	u64	 s_wl_gec_ostore;		/* time of last wl event */
+	u64	 s_wl_gec_journal;		/* time of last wl event */
+	u64	 s_sweeper;			/* current sweeper pos */
+	u8	 s_ifile_levels;		/* max level of ifile */
+	u8	 s_iblock_levels;		/* max level of regular files */
+	u8	 s_data_levels;			/* # of segments to leaf block*/
+	u8	 s_total_levels;		/* sum of above three */
+	struct btree_head32 s_cand_tree;	/* all candidates */
+	struct candidate_list s_free_list;	/* 100% free segments */
+	struct candidate_list s_reserve_list;	/* Bad segment reserve */
+	struct candidate_list s_low_list[LOGFS_NO_AREAS];/* good candidates */
+	struct candidate_list s_ec_list;	/* wear level candidates */
+	struct btree_head32 s_reserved_segments;/* sb, journal, bad, etc. */
+	/* inode.c fields */
+	u64	 s_last_ino;			/* highest ino used */
+	long	 s_inos_till_wrap;
+	u32	 s_generation;			/* i_generation for new files */
+	struct list_head s_freeing_list;	/* inodes being freed */
+	/* journal.c fields */
+	struct mutex s_journal_mutex;
+	void	*s_je;				/* journal entry to compress */
+	void	*s_compressed_je;		/* block to write to journal */
+	u32	 s_journal_seg[LOGFS_JOURNAL_SEGS]; /* journal segments */
+	u32	 s_journal_ec[LOGFS_JOURNAL_SEGS]; /* journal erasecounts */
+	u64	 s_last_version;
+	struct logfs_area *s_journal_area;	/* open journal segment */
+	__be64	s_je_array[64];
+	int	s_no_je;
+
+	int	 s_sum_index;			/* for the 12 summaries */
+	struct shadow_tree s_shadow_tree;
+	int	 s_je_fill;			/* index of current je */
+	/* readwrite.c fields */
+	struct mutex s_write_mutex;
+	int	 s_lock_count;
+	mempool_t *s_block_pool;		/* struct logfs_block pool */
+	mempool_t *s_shadow_pool;		/* struct logfs_shadow pool */
+	/*
+	 * Space accounting:
+	 * - s_used_bytes specifies space used to store valid data objects.
+	 * - s_dirty_used_bytes is space used to store non-committed data
+	 *   objects.  Those objects have already been written themselves,
+	 *   but they don't become valid until all indirect blocks up to the
+	 *   journal have been written as well.
+	 * - s_dirty_free_bytes is space used to store the old copy of a
+	 *   replaced object, as long as the replacement is non-committed.
+	 *   In other words, it is the amount of space freed when all dirty
+	 *   blocks are written back.
+	 * - s_free_bytes is the amount of free space available for any
+	 *   purpose.
+	 * - s_root_reserve is the amount of free space available only to
+	 *   the root user.  Non-privileged users can no longer write once
+	 *   this watermark has been reached.
+	 * - s_speed_reserve is space which remains unused to speed up
+	 *   garbage collection performance.
+	 * - s_dirty_pages is the space reserved for currently dirty pages.
+	 *   It is a pessimistic estimate, so some/most will get freed on
+	 *   page writeback.
+	 *
+	 * s_used_bytes + s_free_bytes + s_speed_reserve = total usable size
+	 */
+	u64	 s_free_bytes;
+	u64	 s_used_bytes;
+	u64	 s_dirty_free_bytes;
+	u64	 s_dirty_used_bytes;
+	u64	 s_root_reserve;
+	u64	 s_speed_reserve;
+	u64	 s_dirty_pages;
+	/* Bad block handling:
+	 * - s_bad_seg_reserve is a number of segments usually kept
+	 *   free.  When encountering bad blocks, the affected segment's data
+	 *   is _temporarily_ moved to a reserved segment.
+	 * - s_bad_segments is the number of known bad segments.
+	 */
+	u32	 s_bad_seg_reserve;
+	u32	 s_bad_segments;
+};
+
+/**
+ * struct logfs_inode - in-memory inode
+ *
+ * @vfs_inode:			struct inode
+ * @li_data:			data pointers
+ * @li_used_bytes:		number of used bytes
+ * @li_freeing_list:		used to track inodes currently being freed
+ * @li_flags:			inode flags
+ * @li_refcount:		number of internal (GC-induced) references
+ */
+struct logfs_inode {
+	struct inode vfs_inode;
+	u64	li_data[LOGFS_EMBEDDED_FIELDS];
+	u64	li_used_bytes;
+	struct list_head li_freeing_list;
+	struct logfs_block *li_block;
+	u32	li_flags;
+	u8	li_height;
+	int	li_refcount;
+};
+
+#define journal_for_each(__i) for (__i = 0; __i < LOGFS_JOURNAL_SEGS; __i++)
+#define for_each_area(__i) for (__i = 0; __i < LOGFS_NO_AREAS; __i++)
+#define for_each_area_down(__i) for (__i = LOGFS_NO_AREAS - 1; __i >= 0; __i--)
+
+/* compr.c */
+int logfs_compress(void *in, void *out, size_t inlen, size_t outlen);
+int logfs_uncompress(void *in, void *out, size_t inlen, size_t outlen);
+int __init logfs_compr_init(void);
+void logfs_compr_exit(void);
+
+/* dev_bdev.c */
+#ifdef CONFIG_BLOCK
+int logfs_get_sb_bdev(struct file_system_type *type, int flags,
+		const char *devname, struct vfsmount *mnt);
+#else
+static inline int logfs_get_sb_bdev(struct file_system_type *type, int flags,
+		const char *devname, struct vfsmount *mnt)
+{
+	return -ENODEV;
+}
+#endif
+
+/* dev_mtd.c */
+#ifdef CONFIG_MTD
+int logfs_get_sb_mtd(struct file_system_type *type, int flags,
+		int mtdnr, struct vfsmount *mnt);
+#else
+static inline int logfs_get_sb_mtd(struct file_system_type *type, int flags,
+		int mtdnr, struct vfsmount *mnt)
+{
+	return -ENODEV;
+}
+#endif
+
+/* dir.c */
+extern const struct inode_operations logfs_symlink_iops;
+extern const struct inode_operations logfs_dir_iops;
+extern const struct file_operations logfs_dir_fops;
+int logfs_replay_journal(struct super_block *sb);
+
+/* file.c */
+extern const struct inode_operations logfs_reg_iops;
+extern const struct file_operations logfs_reg_fops;
+extern const struct address_space_operations logfs_reg_aops;
+int logfs_readpage(struct file *file, struct page *page);
+int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		unsigned long arg);
+int logfs_fsync(struct file *file, struct dentry *dentry, int datasync);
+
+/* gc.c */
+u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec);
+void logfs_gc_pass(struct super_block *sb);
+int logfs_check_areas(struct super_block *sb);
+int logfs_init_gc(struct super_block *sb);
+void logfs_cleanup_gc(struct super_block *sb);
+
+/* inode.c */
+extern const struct super_operations logfs_super_operations;
+struct inode *logfs_iget(struct super_block *sb, ino_t ino);
+struct inode *logfs_safe_iget(struct super_block *sb, ino_t ino, int *cookie);
+void logfs_safe_iput(struct inode *inode, int cookie);
+struct inode *logfs_new_inode(struct inode *dir, int mode);
+struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino);
+struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino);
+int logfs_init_inode_cache(void);
+void logfs_destroy_inode_cache(void);
+void destroy_meta_inode(struct inode *inode);
+void logfs_set_blocks(struct inode *inode, u64 no);
+/* these logically belong into inode.c but actually reside in readwrite.c */
+int logfs_read_inode(struct inode *inode);
+int __logfs_write_inode(struct inode *inode, long flags);
+void logfs_delete_inode(struct inode *inode);
+void logfs_clear_inode(struct inode *inode);
+
+/* journal.c */
+void logfs_write_anchor(struct super_block *sb);
+int logfs_init_journal(struct super_block *sb);
+void logfs_cleanup_journal(struct super_block *sb);
+int write_alias_journal(struct super_block *sb, u64 ino, u64 bix,
+		level_t level, int child_no, __be64 val);
+void do_logfs_journal_wl_pass(struct super_block *sb);
+
+/* readwrite.c */
+pgoff_t logfs_pack_index(u64 bix, level_t level);
+void logfs_unpack_index(pgoff_t index, u64 *bix, level_t *level);
+int logfs_inode_write(struct inode *inode, const void *buf, size_t count,
+		loff_t bix, long flags, struct shadow_tree *shadow_tree);
+int logfs_readpage_nolock(struct page *page);
+int logfs_write_buf(struct inode *inode, struct page *page, long flags);
+int logfs_delete(struct inode *inode, pgoff_t index,
+		struct shadow_tree *shadow_tree);
+int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
+		gc_level_t gc_level, long flags);
+int logfs_is_valid_block(struct super_block *sb, u64 ofs, u64 ino, u64 bix,
+		gc_level_t gc_level);
+int logfs_truncate(struct inode *inode, u64 size);
+u64 logfs_seek_hole(struct inode *inode, u64 bix);
+u64 logfs_seek_data(struct inode *inode, u64 bix);
+int logfs_open_segfile(struct super_block *sb);
+int logfs_init_rw(struct super_block *sb);
+void logfs_cleanup_rw(struct super_block *sb);
+void logfs_add_transaction(struct inode *inode, struct logfs_transaction *ta);
+void logfs_del_transaction(struct inode *inode, struct logfs_transaction *ta);
+void logfs_write_block(struct logfs_block *block, long flags);
+int logfs_write_obj_aliases_pagecache(struct super_block *sb);
+void logfs_get_segment_entry(struct super_block *sb, u32 segno,
+		struct logfs_segment_entry *se);
+void logfs_set_segment_used(struct super_block *sb, u64 ofs, int increment);
+void logfs_set_segment_erased(struct super_block *sb, u32 segno, u32 ec,
+		gc_level_t gc_level);
+void logfs_set_segment_reserved(struct super_block *sb, u32 segno);
+void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec);
+struct logfs_block *__alloc_block(struct super_block *sb,
+		u64 ino, u64 bix, level_t level);
+void __free_block(struct super_block *sb, struct logfs_block *block);
+void btree_write_block(struct logfs_block *block);
+void initialize_block_counters(struct page *page, struct logfs_block *block,
+		__be64 *array, int page_is_empty);
+int logfs_exist_block(struct inode *inode, u64 bix);
+int get_page_reserve(struct inode *inode, struct page *page);
+extern struct logfs_block_ops indirect_block_ops;
+
+/* segment.c */
+int logfs_erase_segment(struct super_block *sb, u32 ofs, int ensure_erase);
+int wbuf_read(struct super_block *sb, u64 ofs, size_t len, void *buf);
+int logfs_segment_read(struct inode *inode, struct page *page, u64 ofs, u64 bix,
+		level_t level);
+int logfs_segment_write(struct inode *inode, struct page *page,
+		struct logfs_shadow *shadow);
+int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow);
+int logfs_load_object_aliases(struct super_block *sb,
+		struct logfs_obj_alias *oa, int count);
+void move_page_to_btree(struct page *page);
+int logfs_init_mapping(struct super_block *sb);
+void logfs_sync_area(struct logfs_area *area);
+void logfs_sync_segments(struct super_block *sb);
+
+/* area handling */
+int logfs_init_areas(struct super_block *sb);
+void logfs_cleanup_areas(struct super_block *sb);
+int logfs_open_area(struct logfs_area *area, size_t bytes);
+void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
+		int use_filler);
+
+static inline void logfs_buf_write(struct logfs_area *area, u64 ofs,
+		void *buf, size_t len)
+{
+	__logfs_buf_write(area, ofs, buf, len, 0);
+}
+
+static inline void logfs_buf_recover(struct logfs_area *area, u64 ofs,
+		void *buf, size_t len)
+{
+	__logfs_buf_write(area, ofs, buf, len, 1);
+}
+
+/* super.c */
+struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index);
+void emergency_read_end(struct page *page);
+void logfs_crash_dump(struct super_block *sb);
+void *memchr_inv(const void *s, int c, size_t n);
+int logfs_statfs(struct dentry *dentry, struct kstatfs *stats);
+int logfs_get_sb_device(struct file_system_type *type, int flags,
+		struct mtd_info *mtd, struct block_device *bdev,
+		const struct logfs_device_ops *devops, struct vfsmount *mnt);
+int logfs_check_ds(struct logfs_disk_super *ds);
+int logfs_write_sb(struct super_block *sb);
+
+static inline struct logfs_super *logfs_super(struct super_block *sb)
+{
+	return sb->s_fs_info;
+}
+
+static inline struct logfs_inode *logfs_inode(struct inode *inode)
+{
+	return container_of(inode, struct logfs_inode, vfs_inode);
+}
+
+static inline void logfs_set_ro(struct super_block *sb)
+{
+	logfs_super(sb)->s_flags |= LOGFS_SB_FLAG_RO;
+}
+
+#define LOGFS_BUG(sb) do {					\
+	struct super_block *__sb = sb;				\
+	logfs_crash_dump(__sb);					\
+	logfs_super(__sb)->s_flags |= LOGFS_SB_FLAG_RO;		\
+	BUG();							\
+} while (0)
+
+#define LOGFS_BUG_ON(condition, sb) \
+	do { if (unlikely(condition)) LOGFS_BUG((sb)); } while (0)
+
+static inline __be32 logfs_crc32(void *data, size_t len, size_t skip)
+{
+	return cpu_to_be32(crc32(~0, data+skip, len-skip));
+}
+
+static inline u8 logfs_type(struct inode *inode)
+{
+	return (inode->i_mode >> 12) & 15;
+}
+
+static inline pgoff_t logfs_index(struct super_block *sb, u64 pos)
+{
+	return pos >> sb->s_blocksize_bits;
+}
+
+static inline u64 dev_ofs(struct super_block *sb, u32 segno, u32 ofs)
+{
+	return ((u64)segno << logfs_super(sb)->s_segshift) + ofs;
+}
+
+static inline u32 seg_no(struct super_block *sb, u64 ofs)
+{
+	return ofs >> logfs_super(sb)->s_segshift;
+}
+
+static inline u32 seg_ofs(struct super_block *sb, u64 ofs)
+{
+	return ofs & logfs_super(sb)->s_segmask;
+}
+
+static inline u64 seg_align(struct super_block *sb, u64 ofs)
+{
+	return ofs & ~logfs_super(sb)->s_segmask;
+}
+
+static inline struct logfs_block *logfs_block(struct page *page)
+{
+	return (void *)page->private;
+}
+
+static inline level_t shrink_level(gc_level_t __level)
+{
+	u8 level = (__force u8)__level;
+
+	if (level >= LOGFS_MAX_LEVELS)
+		level -= LOGFS_MAX_LEVELS;
+	return (__force level_t)level;
+}
+
+static inline gc_level_t expand_level(u64 ino, level_t __level)
+{
+	u8 level = (__force u8)__level;
+
+	if (ino == LOGFS_INO_MASTER) {
+		/* ifile has seperate areas */
+		level += LOGFS_MAX_LEVELS;
+	}
+	return (__force gc_level_t)level;
+}
+
+static inline int logfs_block_shift(struct super_block *sb, level_t level)
+{
+	level = shrink_level((__force gc_level_t)level);
+	return (__force int)level * (sb->s_blocksize_bits - 3);
+}
+
+static inline u64 logfs_block_mask(struct super_block *sb, level_t level)
+{
+	return ~0ull << logfs_block_shift(sb, level);
+}
+
+static inline struct logfs_area *get_area(struct super_block *sb,
+		gc_level_t gc_level)
+{
+	return logfs_super(sb)->s_area[(__force u8)gc_level];
+}
+
+#endif
diff --git a/fs/logfs/logfs_abi.h b/fs/logfs/logfs_abi.h
new file mode 100644
index 0000000..f674725
--- /dev/null
+++ b/fs/logfs/logfs_abi.h
@@ -0,0 +1,629 @@
+/*
+ * fs/logfs/logfs_abi.h
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ *
+ * Public header for logfs.
+ */
+#ifndef FS_LOGFS_LOGFS_ABI_H
+#define FS_LOGFS_LOGFS_ABI_H
+
+/* For out-of-kernel compiles */
+#ifndef BUILD_BUG_ON
+#define BUILD_BUG_ON(condition) /**/
+#endif
+
+#define SIZE_CHECK(type, size)					\
+static inline void check_##type(void)				\
+{								\
+	BUILD_BUG_ON(sizeof(struct type) != (size));		\
+}
+
+/*
+ * Throughout the logfs code, we're constantly dealing with blocks at
+ * various positions or offsets.  To remove confusion, we stricly
+ * distinguish between a "position" - the logical position within a
+ * file and an "offset" - the physical location within the device.
+ *
+ * Any usage of the term offset for a logical location or position for
+ * a physical one is a bug and should get fixed.
+ */
+
+/*
+ * Block are allocated in one of several segments depending on their
+ * level.  The following levels are used:
+ *  0	- regular data block
+ *  1	- i1 indirect blocks
+ *  2	- i2 indirect blocks
+ *  3	- i3 indirect blocks
+ *  4	- i4 indirect blocks
+ *  5	- i5 indirect blocks
+ *  6	- ifile data blocks
+ *  7	- ifile i1 indirect blocks
+ *  8	- ifile i2 indirect blocks
+ *  9	- ifile i3 indirect blocks
+ * 10	- ifile i4 indirect blocks
+ * 11	- ifile i5 indirect blocks
+ * Potential levels to be used in the future:
+ * 12	- gc recycled blocks, long-lived data
+ * 13	- replacement blocks, short-lived data
+ *
+ * Levels 1-11 are necessary for robust gc operations and help seperate
+ * short-lived metadata from longer-lived file data.  In the future,
+ * file data should get seperated into several segments based on simple
+ * heuristics.  Old data recycled during gc operation is expected to be
+ * long-lived.  New data is of uncertain life expectancy.  New data
+ * used to replace older blocks in existing files is expected to be
+ * short-lived.
+ */
+
+
+/* Magic numbers.  64bit for superblock, 32bit for statfs f_type */
+#define LOGFS_MAGIC		0x7a3a8e5cb9d5bf67ull
+#define LOGFS_MAGIC_U32		0xc97e8168u
+
+/*
+ * Various blocksize related macros.  Blocksize is currently fixed at 4KiB.
+ * Sooner or later that should become configurable and the macros replaced
+ * by something superblock-dependent.  Pointers in indirect blocks are and
+ * will remain 64bit.
+ *
+ * LOGFS_BLOCKSIZE	- self-explaining
+ * LOGFS_BLOCK_FACTOR	- number of pointers per indirect block
+ * LOGFS_BLOCK_BITS	- log2 of LOGFS_BLOCK_FACTOR, used for shifts
+ */
+#define LOGFS_BLOCKSIZE		(4096ull)
+#define LOGFS_BLOCK_FACTOR	(LOGFS_BLOCKSIZE / sizeof(u64))
+#define LOGFS_BLOCK_BITS	(9)
+
+/*
+ * Number of blocks at various levels of indirection.  There are 16 direct
+ * block pointers plus a single indirect pointer.
+ */
+#define I0_BLOCKS		(16)
+#define I1_BLOCKS		LOGFS_BLOCK_FACTOR
+#define I2_BLOCKS		(LOGFS_BLOCK_FACTOR * I1_BLOCKS)
+#define I3_BLOCKS		(LOGFS_BLOCK_FACTOR * I2_BLOCKS)
+#define I4_BLOCKS		(LOGFS_BLOCK_FACTOR * I3_BLOCKS)
+#define I5_BLOCKS		(LOGFS_BLOCK_FACTOR * I4_BLOCKS)
+
+#define INDIRECT_INDEX		I0_BLOCKS
+#define LOGFS_EMBEDDED_FIELDS	(I0_BLOCKS + 1)
+
+/*
+ * Sizes at which files require another level of indirection.  Files smaller
+ * than LOGFS_EMBEDDED_SIZE can be completely stored in the inode itself,
+ * similar like ext2 fast symlinks.
+ *
+ * Data at a position smaller than LOGFS_I0_SIZE is accessed through the
+ * direct pointers, else through the 1x indirect pointer and so forth.
+ */
+#define LOGFS_EMBEDDED_SIZE	(LOGFS_EMBEDDED_FIELDS * sizeof(u64))
+#define LOGFS_I0_SIZE		(I0_BLOCKS * LOGFS_BLOCKSIZE)
+#define LOGFS_I1_SIZE		(I1_BLOCKS * LOGFS_BLOCKSIZE)
+#define LOGFS_I2_SIZE		(I2_BLOCKS * LOGFS_BLOCKSIZE)
+#define LOGFS_I3_SIZE		(I3_BLOCKS * LOGFS_BLOCKSIZE)
+#define LOGFS_I4_SIZE		(I4_BLOCKS * LOGFS_BLOCKSIZE)
+#define LOGFS_I5_SIZE		(I5_BLOCKS * LOGFS_BLOCKSIZE)
+
+/*
+ * Each indirect block pointer must have this flag set, if all block pointers
+ * behind it are set, i.e. there is no hole hidden in the shadow of this
+ * indirect block pointer.
+ */
+#define LOGFS_FULLY_POPULATED (1ULL << 63)
+#define pure_ofs(ofs) (ofs & ~LOGFS_FULLY_POPULATED)
+
+/*
+ * LogFS needs to seperate data into levels.  Each level is defined as the
+ * maximal possible distance from the master inode (inode of the inode file).
+ * Data blocks reside on level 0, 1x indirect block on level 1, etc.
+ * Inodes reside on level 6, indirect blocks for the inode file on levels 7-11.
+ * This effort is necessary to guarantee garbage collection to always make
+ * progress.
+ *
+ * LOGFS_MAX_INDIRECT is the maximal indirection through indirect blocks,
+ * LOGFS_MAX_LEVELS is one more for the actual data level of a file.  It is
+ * the maximal number of levels for one file.
+ * LOGFS_NO_AREAS is twice that, as the inode file and regular files are
+ * effectively stacked on top of each other.
+ */
+#define LOGFS_MAX_INDIRECT	(5)
+#define LOGFS_MAX_LEVELS	(LOGFS_MAX_INDIRECT + 1)
+#define LOGFS_NO_AREAS		(2 * LOGFS_MAX_LEVELS)
+
+/* Maximum size of filenames */
+#define LOGFS_MAX_NAMELEN	(255)
+
+/* Number of segments in the primary journal. */
+#define LOGFS_JOURNAL_SEGS	(16)
+
+/* Maximum number of free/erased/etc. segments in journal entries */
+#define MAX_CACHED_SEGS		(64)
+
+
+/*
+ * LOGFS_OBJECT_HEADERSIZE is the size of a single header in the object store,
+ * LOGFS_MAX_OBJECTSIZE the size of the largest possible object, including
+ * its header,
+ * LOGFS_SEGMENT_RESERVE is the amount of space reserved for each segment for
+ * its segment header and the padded space at the end when no further objects
+ * fit.
+ */
+#define LOGFS_OBJECT_HEADERSIZE	(0x1c)
+#define LOGFS_SEGMENT_HEADERSIZE (0x18)
+#define LOGFS_MAX_OBJECTSIZE	(LOGFS_OBJECT_HEADERSIZE + LOGFS_BLOCKSIZE)
+#define LOGFS_SEGMENT_RESERVE	\
+	(LOGFS_SEGMENT_HEADERSIZE + LOGFS_MAX_OBJECTSIZE - 1)
+
+/*
+ * Segment types:
+ * SEG_SUPER	- Data or indirect block
+ * SEG_JOURNAL	- Inode
+ * SEG_OSTORE	- Dentry
+ */
+enum {
+	SEG_SUPER	= 0x01,
+	SEG_JOURNAL	= 0x02,
+	SEG_OSTORE	= 0x03,
+};
+
+/**
+ * struct logfs_segment_header - per-segment header in the ostore
+ *
+ * @crc:			crc32 of header (there is no data)
+ * @pad:			unused, must be 0
+ * @type:			segment type, see above
+ * @level:			GC level for all objects in this segment
+ * @segno:			segment number
+ * @ec:				erase count for this segment
+ * @gec:			global erase count at time of writing
+ */
+struct logfs_segment_header {
+	__be32	crc;
+	__be16	pad;
+	__u8	type;
+	__u8	level;
+	__be32	segno;
+	__be32	ec;
+	__be64	gec;
+};
+
+SIZE_CHECK(logfs_segment_header, LOGFS_SEGMENT_HEADERSIZE);
+
+#define LOGFS_FEATURES_INCOMPAT		(0ull)
+#define LOGFS_FEATURES_RO_COMPAT	(0ull)
+#define LOGFS_FEATURES_COMPAT		(0ull)
+
+/**
+ * struct logfs_disk_super - on-medium superblock
+ *
+ * @ds_magic:			magic number, must equal LOGFS_MAGIC
+ * @ds_crc:			crc32 of structure starting with the next field
+ * @ds_ifile_levels:		maximum number of levels for ifile
+ * @ds_iblock_levels:		maximum number of levels for regular files
+ * @ds_data_levels:		number of seperate levels for data
+ * @pad0:			reserved, must be 0
+ * @ds_feature_incompat:	incompatible filesystem features
+ * @ds_feature_ro_compat:	read-only compatible filesystem features
+ * @ds_feature_compat:		compatible filesystem features
+ * @ds_flags:			flags
+ * @ds_segment_shift:		log2 of segment size
+ * @ds_block_shift:		log2 of block size
+ * @ds_write_shift:		log2 of write size
+ * @pad1:			reserved, must be 0
+ * @ds_journal_seg:		segments used by primary journal
+ * @ds_root_reserve:		bytes reserved for the superuser
+ * @ds_speed_reserve:		bytes reserved to speed up GC
+ * @ds_bad_seg_reserve:		number of segments reserved to handle bad blocks
+ * @pad2:			reserved, must be 0
+ * @pad3:			reserved, must be 0
+ *
+ * Contains only read-only fields.  Read-write fields like the amount of used
+ * space is tracked in the dynamic superblock, which is stored in the journal.
+ */
+struct logfs_disk_super {
+	struct logfs_segment_header ds_sh;
+	__be64	ds_magic;
+
+	__be32	ds_crc;
+	__u8	ds_ifile_levels;
+	__u8	ds_iblock_levels;
+	__u8	ds_data_levels;
+	__u8	ds_segment_shift;
+	__u8	ds_block_shift;
+	__u8	ds_write_shift;
+	__u8	pad0[6];
+
+	__be64	ds_filesystem_size;
+	__be32	ds_segment_size;
+	__be32  ds_bad_seg_reserve;
+
+	__be64	ds_feature_incompat;
+	__be64	ds_feature_ro_compat;
+
+	__be64	ds_feature_compat;
+	__be64	ds_feature_flags;
+
+	__be64	ds_root_reserve;
+	__be64  ds_speed_reserve;
+
+	__be32	ds_journal_seg[LOGFS_JOURNAL_SEGS];
+
+	__be64	ds_super_ofs[2];
+	__be64	pad3[8];
+};
+
+SIZE_CHECK(logfs_disk_super, 256);
+
+/*
+ * Object types:
+ * OBJ_BLOCK	- Data or indirect block
+ * OBJ_INODE	- Inode
+ * OBJ_DENTRY	- Dentry
+ */
+enum {
+	OBJ_BLOCK	= 0x04,
+	OBJ_INODE	= 0x05,
+	OBJ_DENTRY	= 0x06,
+};
+
+/**
+ * struct logfs_object_header - per-object header in the ostore
+ *
+ * @crc:			crc32 of header, excluding data_crc
+ * @len:			length of data
+ * @type:			object type, see above
+ * @compr:			compression type
+ * @ino:			inode number
+ * @bix:			block index
+ * @data_crc:			crc32 of payload
+ */
+struct logfs_object_header {
+	__be32	crc;
+	__be16	len;
+	__u8	type;
+	__u8	compr;
+	__be64	ino;
+	__be64	bix;
+	__be32	data_crc;
+} __attribute__((packed));
+
+SIZE_CHECK(logfs_object_header, LOGFS_OBJECT_HEADERSIZE);
+
+/*
+ * Reserved inode numbers:
+ * LOGFS_INO_MASTER	- master inode (for inode file)
+ * LOGFS_INO_ROOT	- root directory
+ * LOGFS_INO_SEGFILE	- per-segment used bytes and erase count
+ */
+enum {
+	LOGFS_INO_MAPPING	= 0x00,
+	LOGFS_INO_MASTER	= 0x01,
+	LOGFS_INO_ROOT		= 0x02,
+	LOGFS_INO_SEGFILE	= 0x03,
+	LOGFS_RESERVED_INOS	= 0x10,
+};
+
+/*
+ * Inode flags.  High bits should never be written to the medium.  They are
+ * reserved for in-memory usage.
+ * Low bits should either remain in sync with the corresponding FS_*_FL or
+ * reuse slots that obviously don't make sense for logfs.
+ *
+ * LOGFS_IF_DIRTY	Inode must be written back
+ * LOGFS_IF_ZOMBIE	Inode has been deleted
+ * LOGFS_IF_STILLBORN	-ENOSPC happened when creating inode
+ */
+#define LOGFS_IF_COMPRESSED	0x00000004 /* == FS_COMPR_FL */
+#define LOGFS_IF_DIRTY		0x20000000
+#define LOGFS_IF_ZOMBIE		0x40000000
+#define LOGFS_IF_STILLBORN	0x80000000
+
+/* Flags available to chattr */
+#define LOGFS_FL_USER_VISIBLE	(LOGFS_IF_COMPRESSED)
+#define LOGFS_FL_USER_MODIFIABLE (LOGFS_IF_COMPRESSED)
+/* Flags inherited from parent directory on file/directory creation */
+#define LOGFS_FL_INHERITED	(LOGFS_IF_COMPRESSED)
+
+/**
+ * struct logfs_disk_inode - on-medium inode
+ *
+ * @di_mode:			file mode
+ * @di_pad:			reserved, must be 0
+ * @di_flags:			inode flags, see above
+ * @di_uid:			user id
+ * @di_gid:			group id
+ * @di_ctime:			change time
+ * @di_mtime:			modify time
+ * @di_refcount:		reference count (aka nlink or link count)
+ * @di_generation:		inode generation, for nfs
+ * @di_used_bytes:		number of bytes used
+ * @di_size:			file size
+ * @di_data:			data pointers
+ */
+struct logfs_disk_inode {
+	__be16	di_mode;
+	__u8	di_height;
+	__u8	di_pad;
+	__be32	di_flags;
+	__be32	di_uid;
+	__be32	di_gid;
+
+	__be64	di_ctime;
+	__be64	di_mtime;
+
+	__be64	di_atime;
+	__be32	di_refcount;
+	__be32	di_generation;
+
+	__be64	di_used_bytes;
+	__be64	di_size;
+
+	__be64	di_data[LOGFS_EMBEDDED_FIELDS];
+};
+
+SIZE_CHECK(logfs_disk_inode, 200);
+
+#define INODE_POINTER_OFS \
+	(offsetof(struct logfs_disk_inode, di_data) / sizeof(__be64))
+#define INODE_USED_OFS \
+	(offsetof(struct logfs_disk_inode, di_used_bytes) / sizeof(__be64))
+#define INODE_SIZE_OFS \
+	(offsetof(struct logfs_disk_inode, di_size) / sizeof(__be64))
+#define INODE_HEIGHT_OFS	(0)
+
+/**
+ * struct logfs_disk_dentry - on-medium dentry structure
+ *
+ * @ino:			inode number
+ * @namelen:			length of file name
+ * @type:			file type, identical to bits 12..15 of mode
+ * @name:			file name
+ */
+/* FIXME: add 6 bytes of padding to remove the __packed */
+struct logfs_disk_dentry {
+	__be64	ino;
+	__be16	namelen;
+	__u8	type;
+	__u8	name[LOGFS_MAX_NAMELEN];
+} __attribute__((packed));
+
+SIZE_CHECK(logfs_disk_dentry, 266);
+
+#define RESERVED		0xffffffff
+#define BADSEG			0xffffffff
+/**
+ * struct logfs_segment_entry - segment file entry
+ *
+ * @ec_level:			erase count and level
+ * @valid:			number of valid bytes
+ *
+ * Segment file contains one entry for every segment.  ec_level contains the
+ * erasecount in the upper 28 bits and the level in the lower 4 bits.  An
+ * ec_level of BADSEG (-1) identifies bad segments.  valid contains the number
+ * of valid bytes or RESERVED (-1 again) if the segment is used for either the
+ * superblock or the journal, or when the segment is bad.
+ */
+struct logfs_segment_entry {
+	__be32	ec_level;
+	__be32	valid;
+};
+
+SIZE_CHECK(logfs_segment_entry, 8);
+
+/**
+ * struct logfs_journal_header - header for journal entries (JEs)
+ *
+ * @h_crc:			crc32 of journal entry
+ * @h_len:			length of compressed journal entry,
+ *				not including header
+ * @h_datalen:			length of uncompressed data
+ * @h_type:			JE type
+ * @h_compr:			compression type
+ * @h_pad:			reserved
+ */
+struct logfs_journal_header {
+	__be32	h_crc;
+	__be16	h_len;
+	__be16	h_datalen;
+	__be16	h_type;
+	__u8	h_compr;
+	__u8	h_pad[5];
+};
+
+SIZE_CHECK(logfs_journal_header, 16);
+
+/*
+ * Life expectency of data.
+ * VIM_DEFAULT		- default vim
+ * VIM_SEGFILE		- for segment file only - very short-living
+ * VIM_GC		- GC'd data - likely long-living
+ */
+enum logfs_vim {
+	VIM_DEFAULT	= 0,
+	VIM_SEGFILE	= 1,
+};
+
+/**
+ * struct logfs_je_area - wbuf header
+ *
+ * @segno:			segment number of area
+ * @used_bytes:			number of bytes already used
+ * @gc_level:			GC level
+ * @vim:			life expectancy of data
+ *
+ * "Areas" are segments currently being used for writing.  There is at least
+ * one area per GC level.  Several may be used to seperate long-living from
+ * short-living data.  If an area with unknown vim is encountered, it can
+ * simply be closed.
+ * The write buffer immediately follow this header.
+ */
+struct logfs_je_area {
+	__be32	segno;
+	__be32	used_bytes;
+	__u8	gc_level;
+	__u8	vim;
+} __attribute__((packed));
+
+SIZE_CHECK(logfs_je_area, 10);
+
+#define MAX_JOURNAL_HEADER \
+	(sizeof(struct logfs_journal_header) + sizeof(struct logfs_je_area))
+
+/**
+ * struct logfs_je_dynsb - dynamic superblock
+ *
+ * @ds_gec:			global erase count
+ * @ds_sweeper:			current position of GC "sweeper"
+ * @ds_rename_dir:		source directory ino (see dir.c documentation)
+ * @ds_rename_pos:		position of source dd (see dir.c documentation)
+ * @ds_victim_ino:		victims of incomplete dir operation (see dir.c)
+ * @ds_victim_ino:		parent inode of victim (see dir.c)
+ * @ds_used_bytes:		number of used bytes
+ */
+struct logfs_je_dynsb {
+	__be64	ds_gec;
+	__be64	ds_sweeper;
+
+	__be64	ds_rename_dir;
+	__be64	ds_rename_pos;
+
+	__be64	ds_victim_ino;
+	__be64	ds_victim_parent; /* XXX */
+
+	__be64	ds_used_bytes;
+	__be32	ds_generation;
+	__be32	pad;
+};
+
+SIZE_CHECK(logfs_je_dynsb, 64);
+
+/**
+ * struct logfs_je_anchor - anchor of filesystem tree, aka master inode
+ *
+ * @da_size:			size of inode file
+ * @da_last_ino:		last created inode
+ * @da_used_bytes:		number of bytes used
+ * @da_data:			data pointers
+ */
+struct logfs_je_anchor {
+	__be64	da_size;
+	__be64	da_last_ino;
+
+	__be64	da_used_bytes;
+	u8	da_height;
+	u8	pad[7];
+
+	__be64	da_data[LOGFS_EMBEDDED_FIELDS];
+};
+
+SIZE_CHECK(logfs_je_anchor, 168);
+
+/**
+ * struct logfs_je_spillout - spillout entry (from 1st to 2nd journal)
+ *
+ * @so_segment:			segments used for 2nd journal
+ *
+ * Length of the array is given by h_len field in the header.
+ */
+struct logfs_je_spillout {
+	__be64	so_segment[0];
+};
+
+SIZE_CHECK(logfs_je_spillout, 0);
+
+/**
+ * struct logfs_je_journal_ec - erase counts for all journal segments
+ *
+ * @ec:				erase count
+ *
+ * Length of the array is given by h_len field in the header.
+ */
+struct logfs_je_journal_ec {
+	__be32	ec[0];
+};
+
+SIZE_CHECK(logfs_je_journal_ec, 0);
+
+/**
+ * struct logfs_je_free_segments - list of free segmetns with erase count
+ */
+struct logfs_je_free_segments {
+	__be32	segno;
+	__be32	ec;
+};
+
+SIZE_CHECK(logfs_je_free_segments, 8);
+
+/**
+ * struct logfs_seg_alias - list of segment aliases
+ */
+struct logfs_seg_alias {
+	__be32	old_segno;
+	__be32	new_segno;
+};
+
+SIZE_CHECK(logfs_seg_alias, 8);
+
+/**
+ * struct logfs_obj_alias - list of object aliases
+ */
+struct logfs_obj_alias {
+	__be64	ino;
+	__be64	bix;
+	__be64	val;
+	u8	level;
+	u8	pad[5];
+	__be16	child_no;
+};
+
+SIZE_CHECK(logfs_obj_alias, 32);
+
+/**
+ * Compression types.
+ *
+ * COMPR_NONE	- uncompressed
+ * COMPR_ZLIB	- compressed with zlib
+ */
+enum {
+	COMPR_NONE	= 0,
+	COMPR_ZLIB	= 1,
+};
+
+/*
+ * Journal entries come in groups of 16.  First group contains unique
+ * entries, next groups contain one entry per level
+ *
+ * JE_FIRST	- smallest possible journal entry number
+ *
+ * JEG_BASE	- base group, containing unique entries
+ * JE_COMMIT	- commit entry, validates all previous entries
+ * JE_DYNSB	- dynamic superblock, anything that ought to be in the
+ *		  superblock but cannot because it is read-write data
+ * JE_ANCHOR	- anchor aka master inode aka inode file's inode
+ * JE_ERASECOUNT  erasecounts for all journal segments
+ * JE_SPILLOUT	- unused
+ * JE_SEG_ALIAS	- aliases segments
+ * JE_AREA	- area description
+ *
+ * JE_LAST	- largest possible journal entry number
+ */
+enum {
+	JE_FIRST	= 0x01,
+
+	JEG_BASE	= 0x00,
+	JE_COMMIT	= 0x02,
+	JE_DYNSB	= 0x03,
+	JE_ANCHOR	= 0x04,
+	JE_ERASECOUNT	= 0x05,
+	JE_SPILLOUT	= 0x06,
+	JE_OBJ_ALIAS	= 0x0d,
+	JE_AREA		= 0x0e,
+
+	JE_LAST		= 0x0e,
+};
+
+#endif
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
new file mode 100644
index 0000000..7a23b3e
--- /dev/null
+++ b/fs/logfs/readwrite.c
@@ -0,0 +1,2246 @@
+/*
+ * fs/logfs/readwrite.c
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ *
+ *
+ * Actually contains five sets of very similar functions:
+ * read		read blocks from a file
+ * seek_hole	find next hole
+ * seek_data	find next data block
+ * valid	check whether a block still belongs to a file
+ * write	write blocks to a file
+ * delete	delete a block (for directories and ifile)
+ * rewrite	move existing blocks of a file to a new location (gc helper)
+ * truncate	truncate a file
+ */
+#include "logfs.h"
+#include <linux/sched.h>
+
+static u64 adjust_bix(u64 bix, level_t level)
+{
+	switch (level) {
+	case 0:
+		return bix;
+	case LEVEL(1):
+		return max_t(u64, bix, I0_BLOCKS);
+	case LEVEL(2):
+		return max_t(u64, bix, I1_BLOCKS);
+	case LEVEL(3):
+		return max_t(u64, bix, I2_BLOCKS);
+	case LEVEL(4):
+		return max_t(u64, bix, I3_BLOCKS);
+	case LEVEL(5):
+		return max_t(u64, bix, I4_BLOCKS);
+	default:
+		WARN_ON(1);
+		return bix;
+	}
+}
+
+static inline u64 maxbix(u8 height)
+{
+	return 1ULL << (LOGFS_BLOCK_BITS * height);
+}
+
+/**
+ * The inode address space is cut in two halves.  Lower half belongs to data
+ * pages, upper half to indirect blocks.  If the high bit (INDIRECT_BIT) is
+ * set, the actual block index (bix) and level can be derived from the page
+ * index.
+ *
+ * The lowest three bits of the block index are set to 0 after packing and
+ * unpacking.  Since the lowest n bits (9 for 4KiB blocksize) are ignored
+ * anyway this is harmless.
+ */
+#define ARCH_SHIFT	(BITS_PER_LONG - 32)
+#define INDIRECT_BIT	(0x80000000UL << ARCH_SHIFT)
+#define LEVEL_SHIFT	(28 + ARCH_SHIFT)
+static inline pgoff_t first_indirect_block(void)
+{
+	return INDIRECT_BIT | (1ULL << LEVEL_SHIFT);
+}
+
+pgoff_t logfs_pack_index(u64 bix, level_t level)
+{
+	pgoff_t index;
+
+	BUG_ON(bix >= INDIRECT_BIT);
+	if (level == 0)
+		return bix;
+
+	index  = INDIRECT_BIT;
+	index |= (__force long)level << LEVEL_SHIFT;
+	index |= bix >> ((__force u8)level * LOGFS_BLOCK_BITS);
+	return index;
+}
+
+void logfs_unpack_index(pgoff_t index, u64 *bix, level_t *level)
+{
+	u8 __level;
+
+	if (!(index & INDIRECT_BIT)) {
+		*bix = index;
+		*level = 0;
+		return;
+	}
+
+	__level = (index & ~INDIRECT_BIT) >> LEVEL_SHIFT;
+	*level = LEVEL(__level);
+	*bix = (index << (__level * LOGFS_BLOCK_BITS)) & ~INDIRECT_BIT;
+	*bix = adjust_bix(*bix, *level);
+	return;
+}
+#undef ARCH_SHIFT
+#undef INDIRECT_BIT
+#undef LEVEL_SHIFT
+
+/*
+ * Time is stored as nanoseconds since the epoch.
+ */
+static struct timespec be64_to_timespec(__be64 betime)
+{
+	return ns_to_timespec(be64_to_cpu(betime));
+}
+
+static __be64 timespec_to_be64(struct timespec tsp)
+{
+	return cpu_to_be64((u64)tsp.tv_sec * NSEC_PER_SEC + tsp.tv_nsec);
+}
+
+static void logfs_disk_to_inode(struct logfs_disk_inode *di, struct inode*inode)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	int i;
+
+	inode->i_mode	= be16_to_cpu(di->di_mode);
+	li->li_height	= di->di_height;
+	li->li_flags	= be32_to_cpu(di->di_flags);
+	inode->i_uid	= be32_to_cpu(di->di_uid);
+	inode->i_gid	= be32_to_cpu(di->di_gid);
+	inode->i_size	= be64_to_cpu(di->di_size);
+	logfs_set_blocks(inode, be64_to_cpu(di->di_used_bytes));
+	inode->i_atime	= be64_to_timespec(di->di_atime);
+	inode->i_ctime	= be64_to_timespec(di->di_ctime);
+	inode->i_mtime	= be64_to_timespec(di->di_mtime);
+	inode->i_nlink	= be32_to_cpu(di->di_refcount);
+	inode->i_generation = be32_to_cpu(di->di_generation);
+
+	switch (inode->i_mode & S_IFMT) {
+	case S_IFSOCK:	/* fall through */
+	case S_IFBLK:	/* fall through */
+	case S_IFCHR:	/* fall through */
+	case S_IFIFO:
+		inode->i_rdev = be64_to_cpu(di->di_data[0]);
+		break;
+	case S_IFDIR:	/* fall through */
+	case S_IFREG:	/* fall through */
+	case S_IFLNK:
+		for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+			li->li_data[i] = be64_to_cpu(di->di_data[i]);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static void logfs_inode_to_disk(struct inode *inode, struct logfs_disk_inode*di)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	int i;
+
+	di->di_mode	= cpu_to_be16(inode->i_mode);
+	di->di_height	= li->li_height;
+	di->di_pad	= 0;
+	di->di_flags	= cpu_to_be32(li->li_flags);
+	di->di_uid	= cpu_to_be32(inode->i_uid);
+	di->di_gid	= cpu_to_be32(inode->i_gid);
+	di->di_size	= cpu_to_be64(i_size_read(inode));
+	di->di_used_bytes = cpu_to_be64(li->li_used_bytes);
+	di->di_atime	= timespec_to_be64(inode->i_atime);
+	di->di_ctime	= timespec_to_be64(inode->i_ctime);
+	di->di_mtime	= timespec_to_be64(inode->i_mtime);
+	di->di_refcount	= cpu_to_be32(inode->i_nlink);
+	di->di_generation = cpu_to_be32(inode->i_generation);
+
+	switch (inode->i_mode & S_IFMT) {
+	case S_IFSOCK:	/* fall through */
+	case S_IFBLK:	/* fall through */
+	case S_IFCHR:	/* fall through */
+	case S_IFIFO:
+		di->di_data[0] = cpu_to_be64(inode->i_rdev);
+		break;
+	case S_IFDIR:	/* fall through */
+	case S_IFREG:	/* fall through */
+	case S_IFLNK:
+		for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+			di->di_data[i] = cpu_to_be64(li->li_data[i]);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static void __logfs_set_blocks(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct logfs_inode *li = logfs_inode(inode);
+
+	inode->i_blocks = ULONG_MAX;
+	if (li->li_used_bytes >> sb->s_blocksize_bits < ULONG_MAX)
+		inode->i_blocks = ALIGN(li->li_used_bytes, 512) >> 9;
+}
+
+void logfs_set_blocks(struct inode *inode, u64 bytes)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+
+	li->li_used_bytes = bytes;
+	__logfs_set_blocks(inode);
+}
+
+static void prelock_page(struct super_block *sb, struct page *page, int lock)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	BUG_ON(!PageLocked(page));
+	if (lock) {
+		BUG_ON(PagePreLocked(page));
+		SetPagePreLocked(page);
+	} else {
+		/* We are in GC path. */
+		if (PagePreLocked(page))
+			super->s_lock_count++;
+		else
+			SetPagePreLocked(page);
+	}
+}
+
+static void preunlock_page(struct super_block *sb, struct page *page, int lock)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	BUG_ON(!PageLocked(page));
+	if (lock)
+		ClearPagePreLocked(page);
+	else {
+		/* We are in GC path. */
+		BUG_ON(!PagePreLocked(page));
+		if (super->s_lock_count)
+			super->s_lock_count--;
+		else
+			ClearPagePreLocked(page);
+	}
+}
+
+/*
+ * Logfs is prone to an AB-BA deadlock where one task tries to acquire
+ * s_write_mutex with a locked page and GC tries to get that page while holding
+ * s_write_mutex.
+ * To solve this issue logfs will ignore the page lock iff the page in question
+ * is waiting for s_write_mutex.  We annotate this fact by setting PG_pre_locked
+ * in addition to PG_locked.
+ */
+static void logfs_get_wblocks(struct super_block *sb, struct page *page,
+		int lock)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	if (page)
+		prelock_page(sb, page, lock);
+
+	if (lock) {
+		mutex_lock(&super->s_write_mutex);
+		logfs_gc_pass(sb);
+		/* FIXME: We also have to check for shadowed space
+		 * and mempool fill grade */
+	}
+}
+
+static void logfs_put_wblocks(struct super_block *sb, struct page *page,
+		int lock)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	if (page)
+		preunlock_page(sb, page, lock);
+	/* Order matters - we must clear PG_pre_locked before releasing
+	 * s_write_mutex or we could race against another task. */
+	if (lock)
+		mutex_unlock(&super->s_write_mutex);
+}
+
+static struct page *logfs_get_read_page(struct inode *inode, u64 bix,
+		level_t level)
+{
+	return find_or_create_page(inode->i_mapping,
+			logfs_pack_index(bix, level), GFP_NOFS);
+}
+
+static void logfs_put_read_page(struct page *page)
+{
+	unlock_page(page);
+	page_cache_release(page);
+}
+
+static void logfs_lock_write_page(struct page *page)
+{
+	int loop = 0;
+
+	while (unlikely(!trylock_page(page))) {
+		if (loop++ > 0x1000) {
+			/* Has been observed once so far... */
+			printk(KERN_ERR "stack at %p\n", &loop);
+			BUG();
+		}
+		if (PagePreLocked(page)) {
+			/* Holder of page lock is waiting for us, it
+			 * is safe to use this page. */
+			break;
+		}
+		/* Some other process has this page locked and has
+		 * nothing to do with us.  Wait for it to finish.
+		 */
+		schedule();
+	}
+	BUG_ON(!PageLocked(page));
+}
+
+static struct page *logfs_get_write_page(struct inode *inode, u64 bix,
+		level_t level)
+{
+	struct address_space *mapping = inode->i_mapping;
+	pgoff_t index = logfs_pack_index(bix, level);
+	struct page *page;
+	int err;
+
+repeat:
+	page = find_get_page(mapping, index);
+	if (!page) {
+		page = __page_cache_alloc(GFP_NOFS);
+		if (!page)
+			return NULL;
+		err = add_to_page_cache_lru(page, mapping, index, GFP_NOFS);
+		if (unlikely(err)) {
+			page_cache_release(page);
+			if (err == -EEXIST)
+				goto repeat;
+			return NULL;
+		}
+	} else logfs_lock_write_page(page);
+	BUG_ON(!PageLocked(page));
+	return page;
+}
+
+static void logfs_unlock_write_page(struct page *page)
+{
+	if (!PagePreLocked(page))
+		unlock_page(page);
+}
+
+static void logfs_put_write_page(struct page *page)
+{
+	logfs_unlock_write_page(page);
+	page_cache_release(page);
+}
+
+static struct page *logfs_get_page(struct inode *inode, u64 bix, level_t level,
+		int rw)
+{
+	if (rw == READ)
+		return logfs_get_read_page(inode, bix, level);
+	else
+		return logfs_get_write_page(inode, bix, level);
+}
+
+static void logfs_put_page(struct page *page, int rw)
+{
+	if (rw == READ)
+		logfs_put_read_page(page);
+	else
+		logfs_put_write_page(page);
+}
+
+static unsigned long __get_bits(u64 val, int skip, int no)
+{
+	u64 ret = val;
+
+	ret >>= skip * no;
+	ret <<= 64 - no;
+	ret >>= 64 - no;
+	return ret;
+}
+
+static unsigned long get_bits(u64 val, level_t skip)
+{
+	return __get_bits(val, (__force int)skip, LOGFS_BLOCK_BITS);
+}
+
+static inline void init_shadow_tree(struct super_block *sb,
+		struct shadow_tree *tree)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	btree_init_mempool64(&tree->new, super->s_btree_pool);
+	btree_init_mempool64(&tree->old, super->s_btree_pool);
+}
+
+static void indirect_write_block(struct logfs_block *block)
+{
+	struct page *page;
+	struct inode *inode;
+	int ret;
+
+	page = block->page;
+	inode = page->mapping->host;
+	logfs_lock_write_page(page);
+	ret = logfs_write_buf(inode, page, 0);
+	logfs_unlock_write_page(page);
+	/*
+	 * This needs some rework.  Unless you want your filesystem to run
+	 * completely synchronously (you don't), the filesystem will always
+	 * report writes as 'successful' before the actual work has been
+	 * done.  The actual work gets done here and this is where any errors
+	 * will show up.  And there isn't much we can do about it, really.
+	 *
+	 * Some attempts to fix the errors (move from bad blocks, retry io,...)
+	 * have already been done, so anything left should be either a broken
+	 * device or a bug somewhere in logfs itself.  Being relatively new,
+	 * the odds currently favor a bug, so for now the line below isn't
+	 * entirely tasteles.
+	 */
+	BUG_ON(ret);
+}
+
+static void inode_write_block(struct logfs_block *block)
+{
+	struct inode *inode;
+	int ret;
+
+	inode = block->inode;
+	if (inode->i_ino == LOGFS_INO_MASTER)
+		logfs_write_anchor(inode->i_sb);
+	else {
+		ret = __logfs_write_inode(inode, 0);
+		/* see indirect_write_block comment */
+		BUG_ON(ret);
+	}
+}
+
+static gc_level_t inode_block_level(struct logfs_block *block)
+{
+	BUG_ON(block->inode->i_ino == LOGFS_INO_MASTER);
+	return GC_LEVEL(LOGFS_MAX_LEVELS);
+}
+
+static gc_level_t indirect_block_level(struct logfs_block *block)
+{
+	struct page *page;
+	struct inode *inode;
+	u64 bix;
+	level_t level;
+
+	page = block->page;
+	inode = page->mapping->host;
+	logfs_unpack_index(page->index, &bix, &level);
+	return expand_level(inode->i_ino, level);
+}
+
+/*
+ * This silences a false, yet annoying gcc warning.  I hate it when my editor
+ * jumps into bitops.h each time I recompile this file.
+ * TODO: Complain to gcc folks about this and upgrade compiler.
+ */
+static unsigned long fnb(const unsigned long *addr,
+		unsigned long size, unsigned long offset)
+{
+	return find_next_bit(addr, size, offset);
+}
+
+static __be64 inode_val0(struct inode *inode)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	u64 val;
+
+	/*
+	 * Explicit shifting generates good code, but must match the format
+	 * of the structure.  Add some paranoia just in case.
+	 */
+	BUILD_BUG_ON(offsetof(struct logfs_disk_inode, di_mode) != 0);
+	BUILD_BUG_ON(offsetof(struct logfs_disk_inode, di_height) != 2);
+	BUILD_BUG_ON(offsetof(struct logfs_disk_inode, di_flags) != 4);
+
+	val =	(u64)inode->i_mode << 48 |
+		(u64)li->li_height << 40 |
+		(u64)li->li_flags;
+	return cpu_to_be64(val);
+}
+
+static int inode_write_alias(struct super_block *sb,
+		struct logfs_block *block, write_alias_t *write_one_alias)
+{
+	struct inode *inode = block->inode;
+	struct logfs_inode *li = logfs_inode(inode);
+	unsigned long pos;
+	u64 ino , bix;
+	__be64 val;
+	level_t level;
+	int err;
+
+	for (pos = 0; ; pos++) {
+		pos = fnb(block->alias_map, LOGFS_BLOCK_FACTOR, pos);
+		if (pos >= LOGFS_EMBEDDED_FIELDS + INODE_POINTER_OFS)
+			return 0;
+
+		switch (pos) {
+		case INODE_HEIGHT_OFS:
+			val = inode_val0(inode);
+			break;
+		case INODE_USED_OFS:
+			val = cpu_to_be64(li->li_used_bytes);;
+			break;
+		case INODE_SIZE_OFS:
+			val = cpu_to_be64(i_size_read(inode));
+			break;
+		case INODE_POINTER_OFS ... INODE_POINTER_OFS + LOGFS_EMBEDDED_FIELDS - 1:
+			val = cpu_to_be64(li->li_data[pos - INODE_POINTER_OFS]);
+			break;
+		default:
+			BUG();
+		}
+
+		ino = LOGFS_INO_MASTER;
+		bix = inode->i_ino;
+		level = LEVEL(0);
+		err = write_one_alias(sb, ino, bix, level, pos, val);
+		if (err)
+			return err;
+	}
+}
+
+static int indirect_write_alias(struct super_block *sb,
+		struct logfs_block *block, write_alias_t *write_one_alias)
+{
+	unsigned long pos;
+	struct page *page = block->page;
+	u64 ino , bix;
+	__be64 *child, val;
+	level_t level;
+	int err;
+
+	for (pos = 0; ; pos++) {
+		pos = fnb(block->alias_map, LOGFS_BLOCK_FACTOR, pos);
+		if (pos >= LOGFS_BLOCK_FACTOR)
+			return 0;
+
+		ino = page->mapping->host->i_ino;
+		logfs_unpack_index(page->index, &bix, &level);
+		child = kmap_atomic(page, KM_USER0);
+		val = child[pos];
+		kunmap_atomic(child, KM_USER0);
+		err = write_one_alias(sb, ino, bix, level, pos, val);
+		if (err)
+			return err;
+	}
+}
+
+int logfs_write_obj_aliases_pagecache(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_block *block;
+	int err;
+
+	list_for_each_entry(block, &super->s_object_alias, alias_list) {
+		err = block->ops->write_alias(sb, block, write_alias_journal);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+void __free_block(struct super_block *sb, struct logfs_block *block)
+{
+	BUG_ON(!list_empty(&block->item_list));
+	list_del(&block->alias_list);
+	mempool_free(block, logfs_super(sb)->s_block_pool);
+}
+
+static void inode_free_block(struct super_block *sb, struct logfs_block *block)
+{
+	struct inode *inode = block->inode;
+
+	logfs_inode(inode)->li_block = NULL;
+	__free_block(sb, block);
+}
+
+static void indirect_free_block(struct super_block *sb,
+		struct logfs_block *block)
+{
+	ClearPagePrivate(block->page);
+	block->page->private = 0;
+	__free_block(sb, block);
+}
+
+
+static struct logfs_block_ops inode_block_ops = {
+	.write_block = inode_write_block,
+	.block_level = inode_block_level,
+	.free_block = inode_free_block,
+	.write_alias = inode_write_alias,
+};
+
+struct logfs_block_ops indirect_block_ops = {
+	.write_block = indirect_write_block,
+	.block_level = indirect_block_level,
+	.free_block = indirect_free_block,
+	.write_alias = indirect_write_alias,
+};
+
+struct logfs_block *__alloc_block(struct super_block *sb,
+		u64 ino, u64 bix, level_t level)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_block *block;
+
+	block = mempool_alloc(super->s_block_pool, GFP_NOFS);
+	memset(block, 0, sizeof(*block));
+	INIT_LIST_HEAD(&block->alias_list);
+	INIT_LIST_HEAD(&block->item_list);
+	block->sb = sb;
+	block->ino = ino;
+	block->bix = bix;
+	block->level = level;
+	return block;
+}
+
+static void alloc_inode_block(struct inode *inode)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	struct logfs_block *block;
+
+	if (li->li_block)
+		return;
+
+	block = __alloc_block(inode->i_sb, LOGFS_INO_MASTER, inode->i_ino, 0);
+	block->inode = inode;
+	li->li_block = block;
+	block->ops = &inode_block_ops;
+}
+
+void initialize_block_counters(struct page *page, struct logfs_block *block,
+		__be64 *array, int page_is_empty)
+{
+	u64 ptr;
+	int i, start;
+
+	block->partial = 0;
+	block->full = 0;
+	start = 0;
+	if (page->index < first_indirect_block()) {
+		/* Counters are pointless on level 0 */
+		return;
+	}
+	if (page->index == first_indirect_block()) {
+		/* Skip unused pointers */
+		start = I0_BLOCKS;
+		block->full = I0_BLOCKS;
+	}
+	if (!page_is_empty) {
+		for (i = start; i < LOGFS_BLOCK_FACTOR; i++) {
+			ptr = be64_to_cpu(array[i]);
+			if (ptr)
+				block->partial++;
+			if (ptr & LOGFS_FULLY_POPULATED)
+				block->full++;
+		}
+	}
+}
+
+static void alloc_data_block(struct inode *inode, struct page *page)
+{
+	struct logfs_block *block;
+	u64 bix;
+	level_t level;
+
+	if (PagePrivate(page))
+		return;
+
+	logfs_unpack_index(page->index, &bix, &level);
+	block = __alloc_block(inode->i_sb, inode->i_ino, bix, level);
+	block->page = page;
+	SetPagePrivate(page);
+	page->private = (unsigned long)block;
+	block->ops = &indirect_block_ops;
+}
+
+static void alloc_indirect_block(struct inode *inode, struct page *page,
+		int page_is_empty)
+{
+	struct logfs_block *block;
+	__be64 *array;
+
+	if (PagePrivate(page))
+		return;
+
+	alloc_data_block(inode, page);
+
+	block = logfs_block(page);
+	array = kmap_atomic(page, KM_USER0);
+	initialize_block_counters(page, block, array, page_is_empty);
+	kunmap_atomic(array, KM_USER0);
+}
+
+static void block_set_pointer(struct page *page, int index, u64 ptr)
+{
+	struct logfs_block *block = logfs_block(page);
+	__be64 *array;
+	u64 oldptr;
+
+	BUG_ON(!block);
+	array = kmap_atomic(page, KM_USER0);
+	oldptr = be64_to_cpu(array[index]);
+	array[index] = cpu_to_be64(ptr);
+	kunmap_atomic(array, KM_USER0);
+	SetPageUptodate(page);
+
+	block->full += !!(ptr & LOGFS_FULLY_POPULATED)
+		- !!(oldptr & LOGFS_FULLY_POPULATED);
+	block->partial += !!ptr - !!oldptr;
+}
+
+static u64 block_get_pointer(struct page *page, int index)
+{
+	__be64 *block;
+	u64 ptr;
+
+	block = kmap_atomic(page, KM_USER0);
+	ptr = be64_to_cpu(block[index]);
+	kunmap_atomic(block, KM_USER0);
+	return ptr;
+}
+
+static int logfs_read_empty(struct page *page)
+{
+	zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+	return 0;
+}
+
+static int logfs_read_direct(struct inode *inode, struct page *page)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	pgoff_t index = page->index;
+	u64 block;
+
+	block = li->li_data[index];
+	if (!block)
+		return logfs_read_empty(page);
+
+	return logfs_segment_read(inode, page, block, index, 0);
+}
+
+static int logfs_read_loop(struct inode *inode, struct page *page,
+		int rw_context)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	u64 bix, bofs = li->li_data[INDIRECT_INDEX];
+	level_t level, target_level;
+	int ret;
+	struct page *ipage;
+
+	logfs_unpack_index(page->index, &bix, &target_level);
+	if (!bofs)
+		return logfs_read_empty(page);
+
+	if (bix >= maxbix(li->li_height))
+		return logfs_read_empty(page);
+
+	for (level = LEVEL(li->li_height);
+			(__force u8)level > (__force u8)target_level;
+			level = SUBLEVEL(level)){
+		ipage = logfs_get_page(inode, bix, level, rw_context);
+		if (!ipage)
+			return -ENOMEM;
+
+		ret = logfs_segment_read(inode, ipage, bofs, bix, level);
+		if (ret) {
+			logfs_put_read_page(ipage);
+			return ret;
+		}
+
+		bofs = block_get_pointer(ipage, get_bits(bix, SUBLEVEL(level)));
+		logfs_put_page(ipage, rw_context);
+		if (!bofs)
+			return logfs_read_empty(page);
+	}
+
+	return logfs_segment_read(inode, page, bofs, bix, 0);
+}
+
+static int logfs_read_block(struct inode *inode, struct page *page,
+		int rw_context)
+{
+	pgoff_t index = page->index;
+
+	if (index < I0_BLOCKS)
+		return logfs_read_direct(inode, page);
+	return logfs_read_loop(inode, page, rw_context);
+}
+
+static int logfs_exist_loop(struct inode *inode, u64 bix)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	u64 bofs = li->li_data[INDIRECT_INDEX];
+	level_t level;
+	int ret;
+	struct page *ipage;
+
+	if (!bofs)
+		return 0;
+	if (bix >= maxbix(li->li_height))
+		return 0;
+
+	for (level = LEVEL(li->li_height); level != 0; level = SUBLEVEL(level)) {
+		ipage = logfs_get_read_page(inode, bix, level);
+		if (!ipage)
+			return -ENOMEM;
+
+		ret = logfs_segment_read(inode, ipage, bofs, bix, level);
+		if (ret) {
+			logfs_put_read_page(ipage);
+			return ret;
+		}
+
+		bofs = block_get_pointer(ipage, get_bits(bix, SUBLEVEL(level)));
+		logfs_put_read_page(ipage);
+		if (!bofs)
+			return 0;
+	}
+
+	return 1;
+}
+
+int logfs_exist_block(struct inode *inode, u64 bix)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+
+	if (bix < I0_BLOCKS)
+		return !!li->li_data[bix];
+	return logfs_exist_loop(inode, bix);
+}
+
+static u64 seek_holedata_direct(struct inode *inode, u64 bix, int data)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+
+	for (; bix < I0_BLOCKS; bix++)
+		if (data ^ (li->li_data[bix] == 0))
+			return bix;
+	return I0_BLOCKS;
+}
+
+static u64 seek_holedata_loop(struct inode *inode, u64 bix, int data)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	__be64 *rblock;
+	u64 increment, bofs = li->li_data[INDIRECT_INDEX];
+	level_t level;
+	int ret, slot;
+	struct page *page;
+
+	BUG_ON(!bofs);
+
+	for (level = LEVEL(li->li_height); level != 0; level = SUBLEVEL(level)) {
+		increment = 1 << (LOGFS_BLOCK_BITS * ((__force u8)level-1));
+		page = logfs_get_read_page(inode, bix, level);
+		if (!page)
+			return bix;
+
+		ret = logfs_segment_read(inode, page, bofs, bix, level);
+		if (ret) {
+			logfs_put_read_page(page);
+			return bix;
+		}
+
+		slot = get_bits(bix, SUBLEVEL(level));
+		rblock = kmap_atomic(page, KM_USER0);
+		while (slot < LOGFS_BLOCK_FACTOR) {
+			if (data && (rblock[slot] != 0))
+				break;
+			if (!data && !(be64_to_cpu(rblock[slot]) & LOGFS_FULLY_POPULATED))
+				break;
+			slot++;
+			bix += increment;
+			bix &= ~(increment - 1);
+		}
+		if (slot >= LOGFS_BLOCK_FACTOR) {
+			kunmap_atomic(rblock, KM_USER0);
+			logfs_put_read_page(page);
+			return bix;
+		}
+		bofs = be64_to_cpu(rblock[slot]);
+		kunmap_atomic(rblock, KM_USER0);
+		logfs_put_read_page(page);
+		if (!bofs) {
+			BUG_ON(data);
+			return bix;
+		}
+	}
+	return bix;
+}
+
+/**
+ * logfs_seek_hole - find next hole starting at a given block index
+ * @inode:		inode to search in
+ * @bix:		block index to start searching
+ *
+ * Returns next hole.  If the file doesn't contain any further holes, the
+ * block address next to eof is returned instead.
+ */
+u64 logfs_seek_hole(struct inode *inode, u64 bix)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+
+	if (bix < I0_BLOCKS) {
+		bix = seek_holedata_direct(inode, bix, 0);
+		if (bix < I0_BLOCKS)
+			return bix;
+	}
+
+	if (!li->li_data[INDIRECT_INDEX])
+		return bix;
+	else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED)
+		bix = maxbix(li->li_height);
+	else {
+		bix = seek_holedata_loop(inode, bix, 0);
+		if (bix < maxbix(li->li_height))
+			return bix;
+		/* Should not happen anymore.  But if some port writes semi-
+		 * corrupt images (as this one used to) we might run into it.
+		 */
+		WARN_ON_ONCE(bix == maxbix(li->li_height));
+	}
+
+	return bix;
+}
+
+static u64 __logfs_seek_data(struct inode *inode, u64 bix)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+
+	if (bix < I0_BLOCKS) {
+		bix = seek_holedata_direct(inode, bix, 1);
+		if (bix < I0_BLOCKS)
+			return bix;
+	}
+
+	if (bix < maxbix(li->li_height)) {
+		if (!li->li_data[INDIRECT_INDEX])
+			bix = maxbix(li->li_height);
+		else
+			return seek_holedata_loop(inode, bix, 1);
+	}
+
+	return bix;
+}
+
+/**
+ * logfs_seek_data - find next data block after a given block index
+ * @inode:		inode to search in
+ * @bix:		block index to start searching
+ *
+ * Returns next data block.  If the file doesn't contain any further data
+ * blocks, the last block in the file is returned instead.
+ */
+u64 logfs_seek_data(struct inode *inode, u64 bix)
+{
+	struct super_block *sb = inode->i_sb;
+	u64 ret, end;
+
+	ret = __logfs_seek_data(inode, bix);
+	end = i_size_read(inode) >> sb->s_blocksize_bits;
+	if (ret >= end)
+		ret = max(bix, end);
+	return ret;
+}
+
+static int logfs_is_valid_direct(struct logfs_inode *li, u64 bix, u64 ofs)
+{
+	return pure_ofs(li->li_data[bix]) == ofs;
+}
+
+static int __logfs_is_valid_loop(struct inode *inode, u64 bix,
+		u64 ofs, u64 bofs)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	level_t level;
+	int ret;
+	struct page *page;
+
+	for (level = LEVEL(li->li_height); level != 0; level = SUBLEVEL(level)){
+		page = logfs_get_write_page(inode, bix, level);
+		BUG_ON(!page);
+
+		ret = logfs_segment_read(inode, page, bofs, bix, level);
+		if (ret) {
+			logfs_put_write_page(page);
+			return 0;
+		}
+
+		bofs = block_get_pointer(page, get_bits(bix, SUBLEVEL(level)));
+		logfs_put_write_page(page);
+		if (!bofs)
+			return 0;
+
+		if (pure_ofs(bofs) == ofs)
+			return 1;
+	}
+	return 0;
+}
+
+static int logfs_is_valid_loop(struct inode *inode, u64 bix, u64 ofs)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	u64 bofs = li->li_data[INDIRECT_INDEX];
+
+	if (!bofs)
+		return 0;
+
+	if (bix >= maxbix(li->li_height))
+		return 0;
+
+	if (pure_ofs(bofs) == ofs)
+		return 1;
+
+	return __logfs_is_valid_loop(inode, bix, ofs, bofs);
+}
+
+static int __logfs_is_valid_block(struct inode *inode, u64 bix, u64 ofs)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+
+	if ((inode->i_nlink == 0) && atomic_read(&inode->i_count) == 1)
+		return 0;
+
+	if (bix < I0_BLOCKS)
+		return logfs_is_valid_direct(li, bix, ofs);
+	return logfs_is_valid_loop(inode, bix, ofs);
+}
+
+/**
+ * logfs_is_valid_block - check whether this block is still valid
+ *
+ * @sb	- superblock
+ * @ofs	- block physical offset
+ * @ino	- block inode number
+ * @bix	- block index
+ * @level - block level
+ *
+ * Returns 0 if the block is invalid, 1 if it is valid and 2 if it will
+ * become invalid once the journal is written.
+ */
+int logfs_is_valid_block(struct super_block *sb, u64 ofs, u64 ino, u64 bix,
+		gc_level_t gc_level)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct inode *inode;
+	int ret, cookie;
+
+	/* Umount closes a segment with free blocks remaining.  Those
+	 * blocks are by definition invalid. */
+	if (ino == -1)
+		return 0;
+
+	LOGFS_BUG_ON((u64)(u_long)ino != ino, sb);
+
+	inode = logfs_safe_iget(sb, ino, &cookie);
+	if (IS_ERR(inode))
+		goto invalid;
+
+	ret = __logfs_is_valid_block(inode, bix, ofs);
+	logfs_safe_iput(inode, cookie);
+	if (ret)
+		return ret;
+
+invalid:
+	/* Block is nominally invalid, but may still sit in the shadow tree,
+	 * waiting for a journal commit.
+	 */
+	if (btree_lookup64(&super->s_shadow_tree.old, ofs))
+		return 2;
+	return 0;
+}
+
+int logfs_readpage_nolock(struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	int ret = -EIO;
+
+	ret = logfs_read_block(inode, page, READ);
+
+	if (ret) {
+		ClearPageUptodate(page);
+		SetPageError(page);
+	} else {
+		SetPageUptodate(page);
+		ClearPageError(page);
+	}
+	flush_dcache_page(page);
+
+	return ret;
+}
+
+static int logfs_reserve_bytes(struct inode *inode, int bytes)
+{
+	struct logfs_super *super = logfs_super(inode->i_sb);
+	u64 available = super->s_free_bytes + super->s_dirty_free_bytes
+			- super->s_dirty_used_bytes - super->s_dirty_pages;
+
+	if (!bytes)
+		return 0;
+
+	if (available < bytes)
+		return -ENOSPC;
+
+	if (available < bytes + super->s_root_reserve &&
+			!capable(CAP_SYS_RESOURCE))
+		return -ENOSPC;
+
+	return 0;
+}
+
+int get_page_reserve(struct inode *inode, struct page *page)
+{
+	struct logfs_super *super = logfs_super(inode->i_sb);
+	int ret;
+
+	if (logfs_block(page) && logfs_block(page)->reserved_bytes)
+		return 0;
+
+	logfs_get_wblocks(inode->i_sb, page, WF_LOCK);
+	ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE);
+	if (!ret) {
+		alloc_data_block(inode, page);
+		logfs_block(page)->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE;
+		super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE;
+	}
+	logfs_put_wblocks(inode->i_sb, page, WF_LOCK);
+	return ret;
+}
+
+/*
+ * We are protected by write lock.  Push victims up to superblock level
+ * and release transaction when appropriate.
+ */
+/* FIXME: This is currently called from the wrong spots. */
+static void logfs_handle_transaction(struct inode *inode,
+		struct logfs_transaction *ta)
+{
+	struct logfs_super *super = logfs_super(inode->i_sb);
+
+	if (!ta)
+		return;
+	logfs_inode(inode)->li_block->ta = NULL;
+
+	if (inode->i_ino != LOGFS_INO_MASTER) {
+		BUG(); /* FIXME: Yes, this needs more thought */
+		/* just remember the transaction until inode is written */
+		//BUG_ON(logfs_inode(inode)->li_transaction);
+		//logfs_inode(inode)->li_transaction = ta;
+		return;
+	}
+
+	switch (ta->state) {
+	case CREATE_1: /* fall through */
+	case UNLINK_1:
+		BUG_ON(super->s_victim_ino);
+		super->s_victim_ino = ta->ino;
+		break;
+	case CREATE_2: /* fall through */
+	case UNLINK_2:
+		BUG_ON(super->s_victim_ino != ta->ino);
+		super->s_victim_ino = 0;
+		/* transaction ends here - free it */
+		kfree(ta);
+		break;
+	case CROSS_RENAME_1:
+		BUG_ON(super->s_rename_dir);
+		BUG_ON(super->s_rename_pos);
+		super->s_rename_dir = ta->dir;
+		super->s_rename_pos = ta->pos;
+		break;
+	case CROSS_RENAME_2:
+		BUG_ON(super->s_rename_dir != ta->dir);
+		BUG_ON(super->s_rename_pos != ta->pos);
+		super->s_rename_dir = 0;
+		super->s_rename_pos = 0;
+		kfree(ta);
+		break;
+	case TARGET_RENAME_1:
+		BUG_ON(super->s_rename_dir);
+		BUG_ON(super->s_rename_pos);
+		BUG_ON(super->s_victim_ino);
+		super->s_rename_dir = ta->dir;
+		super->s_rename_pos = ta->pos;
+		super->s_victim_ino = ta->ino;
+		break;
+	case TARGET_RENAME_2:
+		BUG_ON(super->s_rename_dir != ta->dir);
+		BUG_ON(super->s_rename_pos != ta->pos);
+		BUG_ON(super->s_victim_ino != ta->ino);
+		super->s_rename_dir = 0;
+		super->s_rename_pos = 0;
+		break;
+	case TARGET_RENAME_3:
+		BUG_ON(super->s_rename_dir);
+		BUG_ON(super->s_rename_pos);
+		BUG_ON(super->s_victim_ino != ta->ino);
+		super->s_victim_ino = 0;
+		kfree(ta);
+		break;
+	default:
+		BUG();
+	}
+}
+
+/*
+ * Not strictly a reservation, but rather a check that we still have enough
+ * space to satisfy the write.
+ */
+static int logfs_reserve_blocks(struct inode *inode, int blocks)
+{
+	return logfs_reserve_bytes(inode, blocks * LOGFS_MAX_OBJECTSIZE);
+}
+
+struct write_control {
+	u64 ofs;
+	long flags;
+};
+
+static struct logfs_shadow *alloc_shadow(struct inode *inode, u64 bix,
+		level_t level, u64 old_ofs)
+{
+	struct logfs_super *super = logfs_super(inode->i_sb);
+	struct logfs_shadow *shadow;
+
+	shadow = mempool_alloc(super->s_shadow_pool, GFP_NOFS);
+	memset(shadow, 0, sizeof(*shadow));
+	shadow->ino = inode->i_ino;
+	shadow->bix = bix;
+	shadow->gc_level = expand_level(inode->i_ino, level);
+	shadow->old_ofs = old_ofs & ~LOGFS_FULLY_POPULATED;
+	return shadow;
+}
+
+static void free_shadow(struct inode *inode, struct logfs_shadow *shadow)
+{
+	struct logfs_super *super = logfs_super(inode->i_sb);
+
+	mempool_free(shadow, super->s_shadow_pool);
+}
+
+/**
+ * fill_shadow_tree - Propagate shadow tree changes due to a write
+ * @inode:	Inode owning the page
+ * @page:	Struct page that was written
+ * @shadow:	Shadow for the current write
+ *
+ * Writes in logfs can result in two semi-valid objects.  The old object
+ * is still valid as long as it can be reached by following pointers on
+ * the medium.  Only when writes propagate all the way up to the journal
+ * has the new object safely replaced the old one.
+ *
+ * To handle this problem, a struct logfs_shadow is used to represent
+ * every single write.  It is attached to the indirect block, which is
+ * marked dirty.  When the indirect block is written, its shadows are
+ * handed up to the next indirect block (or inode).  Untimately they
+ * will reach the master inode and be freed upon journal commit.
+ *
+ * This function handles a single step in the propagation.  It adds the
+ * shadow for the current write to the tree, along with any shadows in
+ * the page's tree, in case it was an indirect block.  If a page is
+ * written, the inode parameter is left NULL, if an inode is written,
+ * the page parameter is left NULL.
+ */
+static void fill_shadow_tree(struct inode *inode, struct page *page,
+		struct logfs_shadow *shadow)
+{
+	struct logfs_super *super = logfs_super(inode->i_sb);
+	struct logfs_block *block = logfs_block(page);
+	struct shadow_tree *tree = &super->s_shadow_tree;
+
+	if (PagePrivate(page)) {
+		if (block->alias_map)
+			super->s_no_object_aliases -= bitmap_weight(
+					block->alias_map, LOGFS_BLOCK_FACTOR);
+		logfs_handle_transaction(inode, block->ta);
+		block->ops->free_block(inode->i_sb, block);
+	}
+	if (shadow) {
+		if (shadow->old_ofs)
+			btree_insert64(&tree->old, shadow->old_ofs, shadow,
+					GFP_NOFS);
+		else
+			btree_insert64(&tree->new, shadow->new_ofs, shadow,
+					GFP_NOFS);
+
+		super->s_dirty_used_bytes += shadow->new_len;
+		super->s_dirty_free_bytes += shadow->old_len;
+	}
+}
+
+static void logfs_set_alias(struct super_block *sb, struct logfs_block *block,
+		long child_no)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	if (block->inode && block->inode->i_ino == LOGFS_INO_MASTER) {
+		/* Aliases in the master inode are pointless. */
+		return;
+	}
+
+	if (!test_bit(child_no, block->alias_map)) {
+		set_bit(child_no, block->alias_map);
+		super->s_no_object_aliases++;
+	}
+	list_move_tail(&block->alias_list, &super->s_object_alias);
+}
+
+/*
+ * Object aliases can and often do change the size and occupied space of a
+ * file.  So not only do we have to change the pointers, we also have to
+ * change inode->i_size and li->li_used_bytes.  Which is done by setting
+ * another two object aliases for the inode itself.
+ */
+static void set_iused(struct inode *inode, struct logfs_shadow *shadow)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+
+	if (shadow->new_len == shadow->old_len)
+		return;
+
+	alloc_inode_block(inode);
+	li->li_used_bytes += shadow->new_len - shadow->old_len;
+	__logfs_set_blocks(inode);
+	logfs_set_alias(inode->i_sb, li->li_block, INODE_USED_OFS);
+	logfs_set_alias(inode->i_sb, li->li_block, INODE_SIZE_OFS);
+}
+
+static int logfs_write_i0(struct inode *inode, struct page *page,
+		struct write_control *wc)
+{
+	struct logfs_shadow *shadow;
+	u64 bix;
+	level_t level;
+	int full, err = 0;
+
+	logfs_unpack_index(page->index, &bix, &level);
+	if (wc->ofs == 0)
+		if (logfs_reserve_blocks(inode, 1))
+			return -ENOSPC;
+
+	shadow = alloc_shadow(inode, bix, level, wc->ofs);
+	if (wc->flags & WF_WRITE)
+		err = logfs_segment_write(inode, page, shadow);
+	if (wc->flags & WF_DELETE)
+		logfs_segment_delete(inode, shadow);
+	if (err) {
+		free_shadow(inode, shadow);
+		return err;
+	}
+
+	set_iused(inode, shadow);
+	full = 1;
+	if (level != 0) {
+		alloc_indirect_block(inode, page, 0);
+		full = logfs_block(page)->full == LOGFS_BLOCK_FACTOR;
+	}
+	fill_shadow_tree(inode, page, shadow);
+	wc->ofs = shadow->new_ofs;
+	if (wc->ofs && full)
+		wc->ofs |= LOGFS_FULLY_POPULATED;
+	return 0;
+}
+
+static int logfs_write_direct(struct inode *inode, struct page *page,
+		long flags)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	struct write_control wc = {
+		.ofs = li->li_data[page->index],
+		.flags = flags,
+	};
+	int err;
+
+	alloc_inode_block(inode);
+
+	err = logfs_write_i0(inode, page, &wc);
+	if (err)
+		return err;
+
+	li->li_data[page->index] = wc.ofs;
+	logfs_set_alias(inode->i_sb, li->li_block,
+			page->index + INODE_POINTER_OFS);
+	return 0;
+}
+
+static int ptr_change(u64 ofs, struct page *page)
+{
+	struct logfs_block *block = logfs_block(page);
+	int empty0, empty1, full0, full1;
+
+	empty0 = ofs == 0;
+	empty1 = block->partial == 0;
+	if (empty0 != empty1)
+		return 1;
+
+	/* The !! is necessary to shrink result to int */
+	full0 = !!(ofs & LOGFS_FULLY_POPULATED);
+	full1 = block->full == LOGFS_BLOCK_FACTOR;
+	if (full0 != full1)
+		return 1;
+	return 0;
+}
+
+static int __logfs_write_rec(struct inode *inode, struct page *page,
+		struct write_control *this_wc,
+		pgoff_t bix, level_t target_level, level_t level)
+{
+	int ret, page_empty = 0;
+	int child_no = get_bits(bix, SUBLEVEL(level));
+	struct page *ipage;
+	struct write_control child_wc = {
+		.flags = this_wc->flags,
+	};
+
+	ipage = logfs_get_write_page(inode, bix, level);
+	if (!ipage)
+		return -ENOMEM;
+
+	if (this_wc->ofs) {
+		ret = logfs_segment_read(inode, ipage, this_wc->ofs, bix, level);
+		if (ret)
+			goto out;
+	} else if (!PageUptodate(ipage)) {
+		page_empty = 1;
+		logfs_read_empty(ipage);
+	}
+
+	child_wc.ofs = block_get_pointer(ipage, child_no);
+
+	if ((__force u8)level-1 > (__force u8)target_level)
+		ret = __logfs_write_rec(inode, page, &child_wc, bix,
+				target_level, SUBLEVEL(level));
+	else
+		ret = logfs_write_i0(inode, page, &child_wc);
+
+	if (ret)
+		goto out;
+
+	alloc_indirect_block(inode, ipage, page_empty);
+	block_set_pointer(ipage, child_no, child_wc.ofs);
+	/* FIXME: first condition seems superfluous */
+	if (child_wc.ofs || logfs_block(ipage)->partial)
+		this_wc->flags |= WF_WRITE;
+	/* the condition on this_wc->ofs ensures that we won't consume extra
+	 * space for indirect blocks in the future, which we cannot reserve */
+	if (!this_wc->ofs || ptr_change(this_wc->ofs, ipage))
+		ret = logfs_write_i0(inode, ipage, this_wc);
+	else
+		logfs_set_alias(inode->i_sb, logfs_block(ipage), child_no);
+out:
+	logfs_put_write_page(ipage);
+	return ret;
+}
+
+static int logfs_write_rec(struct inode *inode, struct page *page,
+		pgoff_t bix, level_t target_level, long flags)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	struct write_control wc = {
+		.ofs = li->li_data[INDIRECT_INDEX],
+		.flags = flags,
+	};
+	int ret;
+
+	alloc_inode_block(inode);
+
+	if (li->li_height > (__force u8)target_level)
+		ret = __logfs_write_rec(inode, page, &wc, bix, target_level,
+				LEVEL(li->li_height));
+	else
+		ret = logfs_write_i0(inode, page, &wc);
+	if (ret)
+		return ret;
+
+	if (li->li_data[INDIRECT_INDEX] != wc.ofs) {
+		li->li_data[INDIRECT_INDEX] = wc.ofs;
+		logfs_set_alias(inode->i_sb, li->li_block,
+				INDIRECT_INDEX + INODE_POINTER_OFS);
+	}
+	return ret;
+}
+
+void logfs_add_transaction(struct inode *inode, struct logfs_transaction *ta)
+{
+	alloc_inode_block(inode);
+	logfs_inode(inode)->li_block->ta = ta;
+}
+
+void logfs_del_transaction(struct inode *inode, struct logfs_transaction *ta)
+{
+	struct logfs_block *block = logfs_inode(inode)->li_block;
+
+	if (block && block->ta)
+		block->ta = NULL;
+}
+
+static int grow_inode(struct inode *inode, u64 bix, level_t level)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	u8 height = (__force u8)level;
+	struct page *page;
+	struct write_control wc = {
+		.flags = WF_WRITE,
+	};
+	int err;
+
+	BUG_ON(height > 5 || li->li_height > 5);
+	while (height > li->li_height || bix >= maxbix(li->li_height)) {
+		page = logfs_get_write_page(inode, I0_BLOCKS + 1,
+				LEVEL(li->li_height + 1));
+		if (!page)
+			return -ENOMEM;
+		logfs_read_empty(page);
+		alloc_indirect_block(inode, page, 1);
+		block_set_pointer(page, 0, li->li_data[INDIRECT_INDEX]);
+		err = logfs_write_i0(inode, page, &wc);
+		logfs_put_write_page(page);
+		if (err)
+			return err;
+		li->li_data[INDIRECT_INDEX] = wc.ofs;
+		wc.ofs = 0;
+		li->li_height++;
+		logfs_set_alias(inode->i_sb, li->li_block, INODE_HEIGHT_OFS);
+	}
+	return 0;
+}
+
+static int __logfs_write_buf(struct inode *inode, struct page *page, long flags)
+{
+	struct logfs_super *super = logfs_super(inode->i_sb);
+	pgoff_t index = page->index;
+	u64 bix;
+	level_t level;
+	int err;
+
+	flags |= WF_WRITE | WF_DELETE;
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+	logfs_unpack_index(index, &bix, &level);
+	if (logfs_block(page) && logfs_block(page)->reserved_bytes)
+		super->s_dirty_pages -= logfs_block(page)->reserved_bytes;
+
+	if (index < I0_BLOCKS)
+		return logfs_write_direct(inode, page, flags);
+
+	bix = adjust_bix(bix, level);
+	err = grow_inode(inode, bix, level);
+	if (err)
+		return err;
+	return logfs_write_rec(inode, page, bix, level, flags);
+}
+
+int logfs_write_buf(struct inode *inode, struct page *page, long flags)
+{
+	struct super_block *sb = inode->i_sb;
+	int ret;
+
+	logfs_get_wblocks(sb, page, flags & WF_LOCK);
+	ret = __logfs_write_buf(inode, page, flags);
+	logfs_put_wblocks(sb, page, flags & WF_LOCK);
+	return ret;
+}
+
+static int __logfs_delete(struct inode *inode, struct page *page)
+{
+	long flags = WF_DELETE;
+
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+	if (page->index < I0_BLOCKS)
+		return logfs_write_direct(inode, page, flags);
+	return logfs_write_rec(inode, page, page->index, 0, flags);
+}
+
+int logfs_delete(struct inode *inode, pgoff_t index,
+		struct shadow_tree *shadow_tree)
+{
+	struct super_block *sb = inode->i_sb;
+	struct page *page;
+	int ret;
+
+	page = logfs_get_read_page(inode, index, 0);
+	if (!page)
+		return -ENOMEM;
+
+	logfs_get_wblocks(sb, page, 1);
+	ret = __logfs_delete(inode, page);
+	logfs_put_wblocks(sb, page, 1);
+
+	logfs_put_read_page(page);
+
+	return ret;
+}
+
+/* Rewrite cannot mark the inode dirty but has to write it immediatly. */
+int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
+		gc_level_t gc_level, long flags)
+{
+	level_t level = shrink_level(gc_level);
+	struct page *page;
+	int err;
+
+	page = logfs_get_write_page(inode, bix, level);
+	if (!page)
+		return -ENOMEM;
+
+	err = logfs_segment_read(inode, page, ofs, bix, level);
+	if (!err) {
+		if (level != 0)
+			alloc_indirect_block(inode, page, 0);
+		err = logfs_write_buf(inode, page, flags);
+	}
+	logfs_put_write_page(page);
+	return err;
+}
+
+static int truncate_data_block(struct inode *inode, struct page *page,
+		u64 ofs, struct logfs_shadow *shadow, u64 size)
+{
+	loff_t pageofs = page->index << inode->i_sb->s_blocksize_bits;
+	u64 bix;
+	level_t level;
+	int err;
+
+	/* Does truncation happen within this page? */
+	if (size <= pageofs || size - pageofs >= PAGE_SIZE)
+		return 0;
+
+	logfs_unpack_index(page->index, &bix, &level);
+	BUG_ON(level != 0);
+
+	err = logfs_segment_read(inode, page, ofs, bix, level);
+	if (err)
+		return err;
+
+	zero_user_segment(page, size - pageofs, PAGE_CACHE_SIZE);
+	return logfs_segment_write(inode, page, shadow);
+}
+
+static int logfs_truncate_i0(struct inode *inode, struct page *page,
+		struct write_control *wc, u64 size)
+{
+	struct logfs_shadow *shadow;
+	u64 bix;
+	level_t level;
+	int err = 0;
+
+	logfs_unpack_index(page->index, &bix, &level);
+	BUG_ON(level != 0);
+	shadow = alloc_shadow(inode, bix, level, wc->ofs);
+
+	err = truncate_data_block(inode, page, wc->ofs, shadow, size);
+	if (err) {
+		free_shadow(inode, shadow);
+		return err;
+	}
+
+	logfs_segment_delete(inode, shadow);
+	set_iused(inode, shadow);
+	fill_shadow_tree(inode, page, shadow);
+	wc->ofs = shadow->new_ofs;
+	return 0;
+}
+
+static int logfs_truncate_direct(struct inode *inode, u64 size)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	struct write_control wc;
+	struct page *page;
+	int e;
+	int err;
+
+	alloc_inode_block(inode);
+
+	for (e = I0_BLOCKS - 1; e >= 0; e--) {
+		if (size > (e+1) * LOGFS_BLOCKSIZE)
+			break;
+
+		wc.ofs = li->li_data[e];
+		if (!wc.ofs)
+			continue;
+
+		page = logfs_get_write_page(inode, e, 0);
+		if (!page)
+			return -ENOMEM;
+		err = logfs_segment_read(inode, page, wc.ofs, e, 0);
+		if (err) {
+			logfs_put_write_page(page);
+			return err;
+		}
+		err = logfs_truncate_i0(inode, page, &wc, size);
+		logfs_put_write_page(page);
+		if (err)
+			return err;
+
+		li->li_data[e] = wc.ofs;
+	}
+	return 0;
+}
+
+/* FIXME: these need to become per-sb once we support different blocksizes */
+static u64 __logfs_step[] = {
+	1,
+	I1_BLOCKS,
+	I2_BLOCKS,
+	I3_BLOCKS,
+};
+
+static u64 __logfs_start_index[] = {
+	I0_BLOCKS,
+	I1_BLOCKS,
+	I2_BLOCKS,
+	I3_BLOCKS
+};
+
+static inline u64 logfs_step(level_t level)
+{
+	return __logfs_step[(__force u8)level];
+}
+
+static inline u64 logfs_factor(u8 level)
+{
+	return __logfs_step[level] * LOGFS_BLOCKSIZE;
+}
+
+static inline u64 logfs_start_index(level_t level)
+{
+	return __logfs_start_index[(__force u8)level];
+}
+
+static void logfs_unpack_raw_index(pgoff_t index, u64 *bix, level_t *level)
+{
+	logfs_unpack_index(index, bix, level);
+	if (*bix <= logfs_start_index(SUBLEVEL(*level)))
+		*bix = 0;
+}
+
+static int __logfs_truncate_rec(struct inode *inode, struct page *ipage,
+		struct write_control *this_wc, u64 size)
+{
+	int truncate_happened = 0;
+	int e, err = 0;
+	u64 bix, child_bix, next_bix;
+	level_t level;
+	struct page *page;
+	struct write_control child_wc = { /* FIXME: flags */ };
+
+	logfs_unpack_raw_index(ipage->index, &bix, &level);
+	err = logfs_segment_read(inode, ipage, this_wc->ofs, bix, level);
+	if (err)
+		return err;
+
+	for (e = LOGFS_BLOCK_FACTOR - 1; e >= 0; e--) {
+		child_bix = bix + e * logfs_step(SUBLEVEL(level));
+		next_bix = child_bix + logfs_step(SUBLEVEL(level));
+		if (size > next_bix * LOGFS_BLOCKSIZE)
+			break;
+
+		child_wc.ofs = pure_ofs(block_get_pointer(ipage, e));
+		if (!child_wc.ofs)
+			continue;
+
+		page = logfs_get_write_page(inode, child_bix, SUBLEVEL(level));
+		if (!page)
+			return -ENOMEM;
+
+		if ((__force u8)level > 1)
+			err = __logfs_truncate_rec(inode, page, &child_wc, size);
+		else
+			err = logfs_truncate_i0(inode, page, &child_wc, size);
+		logfs_put_write_page(page);
+		if (err)
+			return err;
+
+		truncate_happened = 1;
+		alloc_indirect_block(inode, ipage, 0);
+		block_set_pointer(ipage, e, child_wc.ofs);
+	}
+
+	if (!truncate_happened) {
+		printk("ineffectual truncate (%lx, %lx, %llx)\n", inode->i_ino, ipage->index, size);
+		return 0;
+	}
+
+	this_wc->flags = WF_DELETE;
+	if (logfs_block(ipage)->partial)
+		this_wc->flags |= WF_WRITE;
+
+	return logfs_write_i0(inode, ipage, this_wc);
+}
+
+static int logfs_truncate_rec(struct inode *inode, u64 size)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	struct write_control wc = {
+		.ofs = li->li_data[INDIRECT_INDEX],
+	};
+	struct page *page;
+	int err;
+
+	alloc_inode_block(inode);
+
+	if (!wc.ofs)
+		return 0;
+
+	page = logfs_get_write_page(inode, 0, LEVEL(li->li_height));
+	if (!page)
+		return -ENOMEM;
+
+	err = __logfs_truncate_rec(inode, page, &wc, size);
+	logfs_put_write_page(page);
+	if (err)
+		return err;
+
+	if (li->li_data[INDIRECT_INDEX] != wc.ofs)
+		li->li_data[INDIRECT_INDEX] = wc.ofs;
+	return 0;
+}
+
+static int __logfs_truncate(struct inode *inode, u64 size)
+{
+	int ret;
+
+	if (size >= logfs_factor(logfs_inode(inode)->li_height))
+		return 0;
+
+	ret = logfs_truncate_rec(inode, size);
+	if (ret)
+		return ret;
+
+	return logfs_truncate_direct(inode, size);
+}
+
+int logfs_truncate(struct inode *inode, u64 size)
+{
+	struct super_block *sb = inode->i_sb;
+	int err;
+
+	logfs_get_wblocks(sb, NULL, 1);
+	err = __logfs_truncate(inode, size);
+	if (!err)
+		err = __logfs_write_inode(inode, 0);
+	logfs_put_wblocks(sb, NULL, 1);
+
+	if (!err)
+		err = vmtruncate(inode, size);
+
+	/* I don't trust error recovery yet. */
+	WARN_ON(err);
+	return err;
+}
+
+static void move_page_to_inode(struct inode *inode, struct page *page)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	struct logfs_block *block = logfs_block(page);
+
+	if (!block)
+		return;
+
+	log_blockmove("move_page_to_inode(%llx, %llx, %x)\n",
+			block->ino, block->bix, block->level);
+	BUG_ON(li->li_block);
+	block->ops = &inode_block_ops;
+	block->inode = inode;
+	li->li_block = block;
+
+	block->page = NULL;
+	page->private = 0;
+	ClearPagePrivate(page);
+}
+
+static void move_inode_to_page(struct page *page, struct inode *inode)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+	struct logfs_block *block = li->li_block;
+
+	if (!block)
+		return;
+
+	log_blockmove("move_inode_to_page(%llx, %llx, %x)\n",
+			block->ino, block->bix, block->level);
+	BUG_ON(PagePrivate(page));
+	block->ops = &indirect_block_ops;
+	block->page = page;
+	page->private = (unsigned long)block;
+	SetPagePrivate(page);
+
+	block->inode = NULL;
+	li->li_block = NULL;
+}
+
+int logfs_read_inode(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct logfs_super *super = logfs_super(sb);
+	struct inode *master_inode = super->s_master_inode;
+	struct page *page;
+	struct logfs_disk_inode *di;
+	u64 ino = inode->i_ino;
+
+	if (ino << sb->s_blocksize_bits > i_size_read(master_inode))
+		return -ENODATA;
+	if (!logfs_exist_block(master_inode, ino))
+		return -ENODATA;
+
+	page = read_cache_page(master_inode->i_mapping, ino,
+			(filler_t *)logfs_readpage, NULL);
+	if (IS_ERR(page))
+		return PTR_ERR(page);
+
+	di = kmap_atomic(page, KM_USER0);
+	logfs_disk_to_inode(di, inode);
+	kunmap_atomic(di, KM_USER0);
+	move_page_to_inode(inode, page);
+	page_cache_release(page);
+	return 0;
+}
+
+/* Caller must logfs_put_write_page(page); */
+static struct page *inode_to_page(struct inode *inode)
+{
+	struct inode *master_inode = logfs_super(inode->i_sb)->s_master_inode;
+	struct logfs_disk_inode *di;
+	struct page *page;
+
+	BUG_ON(inode->i_ino == LOGFS_INO_MASTER);
+
+	page = logfs_get_write_page(master_inode, inode->i_ino, 0);
+	if (!page)
+		return NULL;
+
+	di = kmap_atomic(page, KM_USER0);
+	logfs_inode_to_disk(inode, di);
+	kunmap_atomic(di, KM_USER0);
+	move_inode_to_page(page, inode);
+	return page;
+}
+
+/* Cheaper version of write_inode.  All changes are concealed in
+ * aliases, which are moved back.  No write to the medium happens.
+ */
+void logfs_clear_inode(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct logfs_inode *li = logfs_inode(inode);
+	struct logfs_block *block = li->li_block;
+	struct page *page;
+
+	/* Only deleted files may be dirty at this point */
+	BUG_ON(inode->i_state & I_DIRTY && inode->i_nlink);
+	if (!block)
+		return;
+	if ((logfs_super(sb)->s_flags & LOGFS_SB_FLAG_SHUTDOWN)) {
+		block->ops->free_block(inode->i_sb, block);
+		return;
+	}
+
+	BUG_ON(inode->i_ino < LOGFS_RESERVED_INOS);
+	page = inode_to_page(inode);
+	BUG_ON(!page); /* FIXME: Use emergency page */
+	logfs_put_write_page(page);
+}
+
+static int do_write_inode(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct inode *master_inode = logfs_super(sb)->s_master_inode;
+	loff_t size = (inode->i_ino + 1) << inode->i_sb->s_blocksize_bits;
+	struct page *page;
+	int err;
+
+	BUG_ON(inode->i_ino == LOGFS_INO_MASTER);
+	/* FIXME: lock inode */
+
+	if (i_size_read(master_inode) < size)
+		i_size_write(master_inode, size);
+
+	/* TODO: Tell vfs this inode is clean now */
+
+	page = inode_to_page(inode);
+	if (!page)
+		return -ENOMEM;
+
+	/* FIXME: transaction is part of logfs_block now.  Is that enough? */
+	err = logfs_write_buf(master_inode, page, 0);
+	logfs_put_write_page(page);
+	return err;
+}
+
+static void logfs_mod_segment_entry(struct super_block *sb, u32 segno,
+		int write,
+		void (*change_se)(struct logfs_segment_entry *, long),
+		long arg)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct inode *inode;
+	struct page *page;
+	struct logfs_segment_entry *se;
+	pgoff_t page_no;
+	int child_no;
+
+	page_no = segno >> (sb->s_blocksize_bits - 3);
+	child_no = segno & ((sb->s_blocksize >> 3) - 1);
+
+	inode = super->s_segfile_inode;
+	page = logfs_get_write_page(inode, page_no, 0);
+	BUG_ON(!page); /* FIXME: We need some reserve page for this case */
+	if (!PageUptodate(page))
+		logfs_read_block(inode, page, WRITE);
+
+	if (write)
+		alloc_indirect_block(inode, page, 0);
+	se = kmap_atomic(page, KM_USER0);
+	change_se(se + child_no, arg);
+	if (write) {
+		logfs_set_alias(sb, logfs_block(page), child_no);
+		BUG_ON((int)be32_to_cpu(se[child_no].valid) > super->s_segsize);
+	}
+	kunmap_atomic(se, KM_USER0);
+
+	logfs_put_write_page(page);
+}
+
+static void __get_segment_entry(struct logfs_segment_entry *se, long _target)
+{
+	struct logfs_segment_entry *target = (void *)_target;
+
+	*target = *se;
+}
+
+void logfs_get_segment_entry(struct super_block *sb, u32 segno,
+		struct logfs_segment_entry *se)
+{
+	logfs_mod_segment_entry(sb, segno, 0, __get_segment_entry, (long)se);
+}
+
+static void __set_segment_used(struct logfs_segment_entry *se, long increment)
+{
+	u32 valid;
+
+	valid = be32_to_cpu(se->valid);
+	valid += increment;
+	se->valid = cpu_to_be32(valid);
+}
+
+void logfs_set_segment_used(struct super_block *sb, u64 ofs, int increment)
+{
+	struct logfs_super *super = logfs_super(sb);
+	u32 segno = ofs >> super->s_segshift;
+
+	if (!increment)
+		return;
+
+	logfs_mod_segment_entry(sb, segno, 1, __set_segment_used, increment);
+}
+
+static void __set_segment_erased(struct logfs_segment_entry *se, long ec_level)
+{
+	se->ec_level = cpu_to_be32(ec_level);
+}
+
+void logfs_set_segment_erased(struct super_block *sb, u32 segno, u32 ec,
+		gc_level_t gc_level)
+{
+	u32 ec_level = ec << 4 | (__force u8)gc_level;
+
+	logfs_mod_segment_entry(sb, segno, 1, __set_segment_erased, ec_level);
+}
+
+static void __set_segment_reserved(struct logfs_segment_entry *se, long ignore)
+{
+	se->valid = cpu_to_be32(RESERVED);
+}
+
+void logfs_set_segment_reserved(struct super_block *sb, u32 segno)
+{
+	logfs_mod_segment_entry(sb, segno, 1, __set_segment_reserved, 0);
+}
+
+static void __set_segment_unreserved(struct logfs_segment_entry *se,
+		long ec_level)
+{
+	se->valid = 0;
+	se->ec_level = cpu_to_be32(ec_level);
+}
+
+void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec)
+{
+	u32 ec_level = ec << 4;
+
+	logfs_mod_segment_entry(sb, segno, 1, __set_segment_unreserved,
+			ec_level);
+}
+
+int __logfs_write_inode(struct inode *inode, long flags)
+{
+	struct super_block *sb = inode->i_sb;
+	int ret;
+
+	logfs_get_wblocks(sb, NULL, flags & WF_LOCK);
+	ret = do_write_inode(inode);
+	logfs_put_wblocks(sb, NULL, flags & WF_LOCK);
+	return ret;
+}
+
+static int do_delete_inode(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct inode *master_inode = logfs_super(sb)->s_master_inode;
+	struct page *page;
+	int ret;
+
+	page = logfs_get_write_page(master_inode, inode->i_ino, 0);
+	if (!page)
+		return -ENOMEM;
+
+	move_inode_to_page(page, inode);
+
+	logfs_get_wblocks(sb, page, 1);
+	ret = __logfs_delete(master_inode, page);
+	logfs_put_wblocks(sb, page, 1);
+
+	logfs_put_write_page(page);
+	return ret;
+}
+
+/*
+ * ZOMBIE inodes have already been deleted before and should remain dead,
+ * if it weren't for valid checking.  No need to kill them again here.
+ */
+void logfs_delete_inode(struct inode *inode)
+{
+	struct logfs_inode *li = logfs_inode(inode);
+
+	if (!(li->li_flags & LOGFS_IF_ZOMBIE)) {
+		li->li_flags |= LOGFS_IF_ZOMBIE;
+		if (i_size_read(inode) > 0)
+			logfs_truncate(inode, 0);
+		do_delete_inode(inode);
+	}
+	truncate_inode_pages(&inode->i_data, 0);
+	clear_inode(inode);
+}
+
+void btree_write_block(struct logfs_block *block)
+{
+	struct inode *inode;
+	struct page *page;
+	int err, cookie;
+
+	inode = logfs_safe_iget(block->sb, block->ino, &cookie);
+	page = logfs_get_write_page(inode, block->bix, block->level);
+
+	err = logfs_readpage_nolock(page);
+	BUG_ON(err);
+	BUG_ON(!PagePrivate(page));
+	BUG_ON(logfs_block(page) != block);
+	err = __logfs_write_buf(inode, page, 0);
+	BUG_ON(err);
+	BUG_ON(PagePrivate(page) || page->private);
+
+	logfs_put_write_page(page);
+	logfs_safe_iput(inode, cookie);
+}
+
+/**
+ * logfs_inode_write - write inode or dentry objects
+ *
+ * @inode:		parent inode (ifile or directory)
+ * @buf:		object to write (inode or dentry)
+ * @n:			object size
+ * @_pos:		object number (file position in blocks/objects)
+ * @flags:		write flags
+ * @lock:		0 if write lock is already taken, 1 otherwise
+ * @shadow_tree:	shadow below this inode
+ *
+ * FIXME: All caller of this put a 200-300 byte variable on the stack,
+ * only to call here and do a memcpy from that stack variable.  A good
+ * example of wasted performance and stack space.
+ */
+int logfs_inode_write(struct inode *inode, const void *buf, size_t count,
+		loff_t bix, long flags, struct shadow_tree *shadow_tree)
+{
+	loff_t pos = bix << inode->i_sb->s_blocksize_bits;
+	int err;
+	struct page *page;
+	void *pagebuf;
+
+	BUG_ON(pos & (LOGFS_BLOCKSIZE-1));
+	BUG_ON(count > LOGFS_BLOCKSIZE);
+	page = logfs_get_write_page(inode, bix, 0);
+	if (!page)
+		return -ENOMEM;
+
+	pagebuf = kmap_atomic(page, KM_USER0);
+	memcpy(pagebuf, buf, count);
+	flush_dcache_page(page);
+	kunmap_atomic(pagebuf, KM_USER0);
+
+	if (i_size_read(inode) < pos + LOGFS_BLOCKSIZE)
+		i_size_write(inode, pos + LOGFS_BLOCKSIZE);
+
+	err = logfs_write_buf(inode, page, flags);
+	logfs_put_write_page(page);
+	return err;
+}
+
+int logfs_open_segfile(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct inode *inode;
+
+	inode = logfs_read_meta_inode(sb, LOGFS_INO_SEGFILE);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+	super->s_segfile_inode = inode;
+	return 0;
+}
+
+int logfs_init_rw(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int min_fill = 3 * super->s_no_blocks;
+
+	INIT_LIST_HEAD(&super->s_object_alias);
+	mutex_init(&super->s_write_mutex);
+	super->s_block_pool = mempool_create_kmalloc_pool(min_fill,
+			sizeof(struct logfs_block));
+	super->s_shadow_pool = mempool_create_kmalloc_pool(min_fill,
+			sizeof(struct logfs_shadow));
+	return 0;
+}
+
+void logfs_cleanup_rw(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	destroy_meta_inode(super->s_segfile_inode);
+	if (super->s_block_pool)
+		mempool_destroy(super->s_block_pool);
+	if (super->s_shadow_pool)
+		mempool_destroy(super->s_shadow_pool);
+}
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
new file mode 100644
index 0000000..1a14f99
--- /dev/null
+++ b/fs/logfs/segment.c
@@ -0,0 +1,927 @@
+/*
+ * fs/logfs/segment.c	- Handling the Object Store
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ *
+ * Object store or ostore makes up the complete device with exception of
+ * the superblock and journal areas.  Apart from its own metadata it stores
+ * three kinds of objects: inodes, dentries and blocks, both data and indirect.
+ */
+#include "logfs.h"
+
+static int logfs_mark_segment_bad(struct super_block *sb, u32 segno)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct btree_head32 *head = &super->s_reserved_segments;
+	int err;
+
+	err = btree_insert32(head, segno, (void *)1, GFP_NOFS);
+	if (err)
+		return err;
+	logfs_super(sb)->s_bad_segments++;
+	/* FIXME: write to journal */
+	return 0;
+}
+
+int logfs_erase_segment(struct super_block *sb, u32 segno, int ensure_erase)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	super->s_gec++;
+
+	return super->s_devops->erase(sb, (u64)segno << super->s_segshift,
+			super->s_segsize, ensure_erase);
+}
+
+static s64 logfs_get_free_bytes(struct logfs_area *area, size_t bytes)
+{
+	s32 ofs;
+
+	logfs_open_area(area, bytes);
+
+	ofs = area->a_used_bytes;
+	area->a_used_bytes += bytes;
+	BUG_ON(area->a_used_bytes >= logfs_super(area->a_sb)->s_segsize);
+
+	return dev_ofs(area->a_sb, area->a_segno, ofs);
+}
+
+static struct page *get_mapping_page(struct super_block *sb, pgoff_t index,
+		int use_filler)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping = super->s_mapping_inode->i_mapping;
+	filler_t *filler = super->s_devops->readpage;
+	struct page *page;
+
+	BUG_ON(mapping_gfp_mask(mapping) & __GFP_FS);
+	if (use_filler)
+		page = read_cache_page(mapping, index, filler, sb);
+	else {
+		page = find_or_create_page(mapping, index, GFP_NOFS);
+		unlock_page(page);
+	}
+	return page;
+}
+
+void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
+		int use_filler)
+{
+	pgoff_t index = ofs >> PAGE_SHIFT;
+	struct page *page;
+	long offset = ofs & (PAGE_SIZE-1);
+	long copylen;
+
+	/* Only logfs_wbuf_recover may use len==0 */
+	BUG_ON(!len && !use_filler);
+	do {
+		copylen = min((ulong)len, PAGE_SIZE - offset);
+
+		page = get_mapping_page(area->a_sb, index, use_filler);
+		SetPageUptodate(page);
+		BUG_ON(!page); /* FIXME: reserve a pool */
+		memcpy(page_address(page) + offset, buf, copylen);
+		SetPagePrivate(page);
+		page_cache_release(page);
+
+		buf += copylen;
+		len -= copylen;
+		offset = 0;
+		index++;
+	} while (len);
+}
+
+/*
+ * bdev_writeseg will write full pages.  Memset the tail to prevent data leaks.
+ */
+static void pad_wbuf(struct logfs_area *area, int final)
+{
+	struct super_block *sb = area->a_sb;
+	struct logfs_super *super = logfs_super(sb);
+	struct page *page;
+	u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes);
+	pgoff_t index = ofs >> PAGE_SHIFT;
+	long offset = ofs & (PAGE_SIZE-1);
+	u32 len = PAGE_SIZE - offset;
+
+	if (len == PAGE_SIZE) {
+		/* The math in this function can surely use some love */
+		len = 0;
+	}
+	if (len) {
+		BUG_ON(area->a_used_bytes >= super->s_segsize);
+
+		page = get_mapping_page(area->a_sb, index, 0);
+		BUG_ON(!page); /* FIXME: reserve a pool */
+		memset(page_address(page) + offset, 0xff, len);
+		SetPagePrivate(page);
+		page_cache_release(page);
+	}
+
+	if (!final)
+		return;
+
+	area->a_used_bytes += len;
+	for ( ; area->a_used_bytes < super->s_segsize;
+			area->a_used_bytes += PAGE_SIZE) {
+		/* Memset another page */
+		index++;
+		page = get_mapping_page(area->a_sb, index, 0);
+		BUG_ON(!page); /* FIXME: reserve a pool */
+		memset(page_address(page), 0xff, PAGE_SIZE);
+		SetPagePrivate(page);
+		page_cache_release(page);
+	}
+}
+
+/*
+ * We have to be careful with the alias tree.  Since lookup is done by bix,
+ * it needs to be normalized, so 14, 15, 16, etc. all match when dealing with
+ * indirect blocks.  So always use it through accessor functions.
+ */
+static void *alias_tree_lookup(struct super_block *sb, u64 ino, u64 bix,
+		level_t level)
+{
+	struct btree_head128 *head = &logfs_super(sb)->s_object_alias_tree;
+	pgoff_t index = logfs_pack_index(bix, level);
+
+	return btree_lookup128(head, ino, index);
+}
+
+static int alias_tree_insert(struct super_block *sb, u64 ino, u64 bix,
+		level_t level, void *val)
+{
+	struct btree_head128 *head = &logfs_super(sb)->s_object_alias_tree;
+	pgoff_t index = logfs_pack_index(bix, level);
+
+	return btree_insert128(head, ino, index, val, GFP_NOFS);
+}
+
+static int btree_write_alias(struct super_block *sb, struct logfs_block *block,
+		write_alias_t *write_one_alias)
+{
+	struct object_alias_item *item;
+	int err;
+
+	list_for_each_entry(item, &block->item_list, list) {
+		err = write_alias_journal(sb, block->ino, block->bix,
+				block->level, item->child_no, item->val);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static gc_level_t btree_block_level(struct logfs_block *block)
+{
+	return expand_level(block->ino, block->level);
+}
+
+static struct logfs_block_ops btree_block_ops = {
+	.write_block	= btree_write_block,
+	.block_level	= btree_block_level,
+	.free_block	= __free_block,
+	.write_alias	= btree_write_alias,
+};
+
+int logfs_load_object_aliases(struct super_block *sb,
+		struct logfs_obj_alias *oa, int count)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_block *block;
+	struct object_alias_item *item;
+	u64 ino, bix;
+	level_t level;
+	int i, err;
+
+	super->s_flags |= LOGFS_SB_FLAG_OBJ_ALIAS;
+	count /= sizeof(*oa);
+	for (i = 0; i < count; i++) {
+		item = mempool_alloc(super->s_alias_pool, GFP_NOFS);
+		if (!item)
+			return -ENOMEM;
+		memset(item, 0, sizeof(*item));
+
+		super->s_no_object_aliases++;
+		item->val = oa[i].val;
+		item->child_no = be16_to_cpu(oa[i].child_no);
+
+		ino = be64_to_cpu(oa[i].ino);
+		bix = be64_to_cpu(oa[i].bix);
+		level = LEVEL(oa[i].level);
+
+		log_aliases("logfs_load_object_aliases(%llx, %llx, %x, %x) %llx\n",
+				ino, bix, level, item->child_no,
+				be64_to_cpu(item->val));
+		block = alias_tree_lookup(sb, ino, bix, level);
+		if (!block) {
+			block = __alloc_block(sb, ino, bix, level);
+			block->ops = &btree_block_ops;
+			err = alias_tree_insert(sb, ino, bix, level, block);
+			BUG_ON(err); /* mempool empty */
+		}
+		if (test_and_set_bit(item->child_no, block->alias_map)) {
+			printk(KERN_ERR"LogFS: Alias collision detected\n");
+			return -EIO;
+		}
+		list_move_tail(&block->alias_list, &super->s_object_alias);
+		list_add(&item->list, &block->item_list);
+	}
+	return 0;
+}
+
+static void kill_alias(void *_block, unsigned long ignore0,
+		u64 ignore1, u64 ignore2, size_t ignore3)
+{
+	struct logfs_block *block = _block;
+	struct super_block *sb = block->sb;
+	struct logfs_super *super = logfs_super(sb);
+	struct object_alias_item *item;
+
+	while (!list_empty(&block->item_list)) {
+		item = list_entry(block->item_list.next, typeof(*item), list);
+		list_del(&item->list);
+		mempool_free(item, super->s_alias_pool);
+	}
+	block->ops->free_block(sb, block);
+}
+
+static int obj_type(struct inode *inode, level_t level)
+{
+	if (level == 0) {
+		if (S_ISDIR(inode->i_mode))
+			return OBJ_DENTRY;
+		if (inode->i_ino == LOGFS_INO_MASTER)
+			return OBJ_INODE;
+	}
+	return OBJ_BLOCK;
+}
+
+static int obj_len(struct super_block *sb, int obj_type)
+{
+	switch (obj_type) {
+	case OBJ_DENTRY:
+		return sizeof(struct logfs_disk_dentry);
+	case OBJ_INODE:
+		return sizeof(struct logfs_disk_inode);
+	case OBJ_BLOCK:
+		return sb->s_blocksize;
+	default:
+		BUG();
+	}
+}
+
+static int __logfs_segment_write(struct inode *inode, void *buf,
+		struct logfs_shadow *shadow, int type, int len, int compr)
+{
+	struct logfs_area *area;
+	struct super_block *sb = inode->i_sb;
+	s64 ofs;
+	struct logfs_object_header h;
+	int acc_len;
+
+	if (shadow->gc_level == 0)
+		acc_len = len;
+	else
+		acc_len = obj_len(sb, type);
+
+	area = get_area(sb, shadow->gc_level);
+	ofs = logfs_get_free_bytes(area, len + LOGFS_OBJECT_HEADERSIZE);
+	LOGFS_BUG_ON(ofs <= 0, sb);
+	/*
+	 * Order is important.  logfs_get_free_bytes(), by modifying the
+	 * segment file, may modify the content of the very page we're about
+	 * to write now.  Which is fine, as long as the calculated crc and
+	 * written data still match.  So do the modifications _before_
+	 * calculating the crc.
+	 */
+
+	h.len	= cpu_to_be16(len);
+	h.type	= type;
+	h.compr	= compr;
+	h.ino	= cpu_to_be64(inode->i_ino);
+	h.bix	= cpu_to_be64(shadow->bix);
+	h.crc	= logfs_crc32(&h, sizeof(h) - 4, 4);
+	h.data_crc = logfs_crc32(buf, len, 0);
+
+	logfs_buf_write(area, ofs, &h, sizeof(h));
+	logfs_buf_write(area, ofs + LOGFS_OBJECT_HEADERSIZE, buf, len);
+
+	shadow->new_ofs = ofs;
+	shadow->new_len = acc_len + LOGFS_OBJECT_HEADERSIZE;
+
+	return 0;
+}
+
+static s64 logfs_segment_write_compress(struct inode *inode, void *buf,
+		struct logfs_shadow *shadow, int type, int len)
+{
+	struct super_block *sb = inode->i_sb;
+	void *compressor_buf = logfs_super(sb)->s_compressed_je;
+	ssize_t compr_len;
+	int ret;
+
+	mutex_lock(&logfs_super(sb)->s_journal_mutex);
+	compr_len = logfs_compress(buf, compressor_buf, len, len);
+
+	if (compr_len >= 0) {
+		ret = __logfs_segment_write(inode, compressor_buf, shadow,
+				type, compr_len, COMPR_ZLIB);
+	} else {
+		ret = __logfs_segment_write(inode, buf, shadow, type, len,
+				COMPR_NONE);
+	}
+	mutex_unlock(&logfs_super(sb)->s_journal_mutex);
+	return ret;
+}
+
+/**
+ * logfs_segment_write - write data block to object store
+ * @inode:		inode containing data
+ *
+ * Returns an errno or zero.
+ */
+int logfs_segment_write(struct inode *inode, struct page *page,
+		struct logfs_shadow *shadow)
+{
+	struct super_block *sb = inode->i_sb;
+	struct logfs_super *super = logfs_super(sb);
+	int do_compress, type, len;
+	int ret;
+	void *buf;
+
+	super->s_flags |= LOGFS_SB_FLAG_DIRTY;
+	BUG_ON(super->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
+	do_compress = logfs_inode(inode)->li_flags & LOGFS_IF_COMPRESSED;
+	if (shadow->gc_level != 0) {
+		/* temporarily disable compression for indirect blocks */
+		do_compress = 0;
+	}
+
+	type = obj_type(inode, shrink_level(shadow->gc_level));
+	len = obj_len(sb, type);
+	buf = kmap(page);
+	if (do_compress)
+		ret = logfs_segment_write_compress(inode, buf, shadow, type,
+				len);
+	else
+		ret = __logfs_segment_write(inode, buf, shadow, type, len,
+				COMPR_NONE);
+	kunmap(page);
+
+	log_segment("logfs_segment_write(%llx, %llx, %x) %llx->%llx %x->%x\n",
+			shadow->ino, shadow->bix, shadow->gc_level,
+			shadow->old_ofs, shadow->new_ofs,
+			shadow->old_len, shadow->new_len);
+	/* this BUG_ON did catch a locking bug.  useful */
+	BUG_ON(!(shadow->new_ofs & (super->s_segsize - 1)));
+	return ret;
+}
+
+int wbuf_read(struct super_block *sb, u64 ofs, size_t len, void *buf)
+{
+	pgoff_t index = ofs >> PAGE_SHIFT;
+	struct page *page;
+	long offset = ofs & (PAGE_SIZE-1);
+	long copylen;
+
+	while (len) {
+		copylen = min((ulong)len, PAGE_SIZE - offset);
+
+		page = get_mapping_page(sb, index, 1);
+		if (IS_ERR(page))
+			return PTR_ERR(page);
+		memcpy(buf, page_address(page) + offset, copylen);
+		page_cache_release(page);
+
+		buf += copylen;
+		len -= copylen;
+		offset = 0;
+		index++;
+	}
+	return 0;
+}
+
+/*
+ * The "position" of indirect blocks is ambiguous.  It can be the position
+ * of any data block somewhere behind this indirect block.  So we need to
+ * normalize the positions through logfs_block_mask() before comparing.
+ */
+static int check_pos(struct super_block *sb, u64 pos1, u64 pos2, level_t level)
+{
+	return	(pos1 & logfs_block_mask(sb, level)) !=
+		(pos2 & logfs_block_mask(sb, level));
+}
+
+#if 0
+static int read_seg_header(struct super_block *sb, u64 ofs,
+		struct logfs_segment_header *sh)
+{
+	__be32 crc;
+	int err;
+
+	err = wbuf_read(sb, ofs, sizeof(*sh), sh);
+	if (err)
+		return err;
+	crc = logfs_crc32(sh, sizeof(*sh), 4);
+	if (crc != sh->crc) {
+		printk(KERN_ERR"LOGFS: header crc error at %llx: expected %x, "
+				"got %x\n", ofs, be32_to_cpu(sh->crc),
+				be32_to_cpu(crc));
+		return -EIO;
+	}
+	return 0;
+}
+#endif
+
+static int read_obj_header(struct super_block *sb, u64 ofs,
+		struct logfs_object_header *oh)
+{
+	__be32 crc;
+	int err;
+
+	err = wbuf_read(sb, ofs, sizeof(*oh), oh);
+	if (err)
+		return err;
+	crc = logfs_crc32(oh, sizeof(*oh) - 4, 4);
+	if (crc != oh->crc) {
+		printk(KERN_ERR"LOGFS: header crc error at %llx: expected %x, "
+				"got %x\n", ofs, be32_to_cpu(oh->crc),
+				be32_to_cpu(crc));
+		return -EIO;
+	}
+	return 0;
+}
+
+static void move_btree_to_page(struct inode *inode, struct page *page,
+		__be64 *data)
+{
+	struct super_block *sb = inode->i_sb;
+	struct logfs_super *super = logfs_super(sb);
+	struct btree_head128 *head = &super->s_object_alias_tree;
+	struct logfs_block *block;
+	struct object_alias_item *item, *next;
+
+	if (!(super->s_flags & LOGFS_SB_FLAG_OBJ_ALIAS))
+		return;
+
+	block = btree_remove128(head, inode->i_ino, page->index);
+	if (!block)
+		return;
+
+	log_blockmove("move_btree_to_page(%llx, %llx, %x)\n",
+			block->ino, block->bix, block->level);
+	list_for_each_entry_safe(item, next, &block->item_list, list) {
+		data[item->child_no] = item->val;
+		list_del(&item->list);
+		mempool_free(item, super->s_alias_pool);
+	}
+	block->page = page;
+	SetPagePrivate(page);
+	page->private = (unsigned long)block;
+	block->ops = &indirect_block_ops;
+	initialize_block_counters(page, block, data, 0);
+}
+
+/*
+ * This silences a false, yet annoying gcc warning.  I hate it when my editor
+ * jumps into bitops.h each time I recompile this file.
+ * TODO: Complain to gcc folks about this and upgrade compiler.
+ */
+static unsigned long fnb(const unsigned long *addr,
+		unsigned long size, unsigned long offset)
+{
+	return find_next_bit(addr, size, offset);
+}
+
+void move_page_to_btree(struct page *page)
+{
+	struct logfs_block *block = logfs_block(page);
+	struct super_block *sb = block->sb;
+	struct logfs_super *super = logfs_super(sb);
+	struct object_alias_item *item;
+	unsigned long pos;
+	__be64 *child;
+	int err;
+
+	if (super->s_flags & LOGFS_SB_FLAG_SHUTDOWN) {
+		block->ops->free_block(sb, block);
+		return;
+	}
+	log_blockmove("move_page_to_btree(%llx, %llx, %x)\n",
+			block->ino, block->bix, block->level);
+	super->s_flags |= LOGFS_SB_FLAG_OBJ_ALIAS;
+
+	for (pos = 0; ; pos++) {
+		pos = fnb(block->alias_map, LOGFS_BLOCK_FACTOR, pos);
+		if (pos >= LOGFS_BLOCK_FACTOR)
+			break;
+
+		item = mempool_alloc(super->s_alias_pool, GFP_NOFS);
+		BUG_ON(!item); /* mempool empty */
+		memset(item, 0, sizeof(*item));
+
+		child = kmap_atomic(page, KM_USER0);
+		item->val = child[pos];
+		kunmap_atomic(child, KM_USER0);
+		item->child_no = pos;
+		list_add(&item->list, &block->item_list);
+	}
+	block->page = NULL;
+	ClearPagePrivate(page);
+	page->private = 0;
+	block->ops = &btree_block_ops;
+	err = alias_tree_insert(block->sb, block->ino, block->bix, block->level,
+			block);
+	BUG_ON(err); /* mempool empty */
+	ClearPageUptodate(page);
+}
+
+static int __logfs_segment_read(struct inode *inode, void *buf,
+		u64 ofs, u64 bix, level_t level)
+{
+	struct super_block *sb = inode->i_sb;
+	void *compressor_buf = logfs_super(sb)->s_compressed_je;
+	struct logfs_object_header oh;
+	__be32 crc;
+	u16 len;
+	int err, block_len;
+
+	block_len = obj_len(sb, obj_type(inode, level));
+	err = read_obj_header(sb, ofs, &oh);
+	if (err)
+		goto out_err;
+
+	err = -EIO;
+	if (be64_to_cpu(oh.ino) != inode->i_ino
+			|| check_pos(sb, be64_to_cpu(oh.bix), bix, level)) {
+		printk(KERN_ERR"LOGFS: (ino, bix) don't match at %llx: "
+				"expected (%lx, %llx), got (%llx, %llx)\n",
+				ofs, inode->i_ino, bix,
+				be64_to_cpu(oh.ino), be64_to_cpu(oh.bix));
+		goto out_err;
+	}
+
+	len = be16_to_cpu(oh.len);
+
+	switch (oh.compr) {
+	case COMPR_NONE:
+		err = wbuf_read(sb, ofs + LOGFS_OBJECT_HEADERSIZE, len, buf);
+		if (err)
+			goto out_err;
+		crc = logfs_crc32(buf, len, 0);
+		if (crc != oh.data_crc) {
+			printk(KERN_ERR"LOGFS: uncompressed data crc error at "
+					"%llx: expected %x, got %x\n", ofs,
+					be32_to_cpu(oh.data_crc),
+					be32_to_cpu(crc));
+			goto out_err;
+		}
+		break;
+	case COMPR_ZLIB:
+		mutex_lock(&logfs_super(sb)->s_journal_mutex);
+		err = wbuf_read(sb, ofs + LOGFS_OBJECT_HEADERSIZE, len,
+				compressor_buf);
+		if (err) {
+			mutex_unlock(&logfs_super(sb)->s_journal_mutex);
+			goto out_err;
+		}
+		crc = logfs_crc32(compressor_buf, len, 0);
+		if (crc != oh.data_crc) {
+			printk(KERN_ERR"LOGFS: compressed data crc error at "
+					"%llx: expected %x, got %x\n", ofs,
+					be32_to_cpu(oh.data_crc),
+					be32_to_cpu(crc));
+			mutex_unlock(&logfs_super(sb)->s_journal_mutex);
+			goto out_err;
+		}
+		err = logfs_uncompress(compressor_buf, buf, len, block_len);
+		mutex_unlock(&logfs_super(sb)->s_journal_mutex);
+		if (err) {
+			printk(KERN_ERR"LOGFS: uncompress error at %llx\n", ofs);
+			goto out_err;
+		}
+		break;
+	default:
+		LOGFS_BUG(sb);
+		err = -EIO;
+		goto out_err;
+	}
+	return 0;
+
+out_err:
+	logfs_set_ro(sb);
+	printk(KERN_ERR"LOGFS: device is read-only now\n");
+	LOGFS_BUG(sb);
+	return err;
+}
+
+/**
+ * logfs_segment_read - read data block from object store
+ * @inode:		inode containing data
+ * @buf:		data buffer
+ * @ofs:		physical data offset
+ * @bix:		block index
+ * @level:		block level
+ *
+ * Returns 0 on success or a negative errno.
+ */
+int logfs_segment_read(struct inode *inode, struct page *page,
+		u64 ofs, u64 bix, level_t level)
+{
+	int err;
+	void *buf;
+
+	if (PageUptodate(page))
+		return 0;
+
+	ofs &= ~LOGFS_FULLY_POPULATED;
+
+	buf = kmap(page);
+	err = __logfs_segment_read(inode, buf, ofs, bix, level);
+	if (!err) {
+		move_btree_to_page(inode, page, buf);
+		SetPageUptodate(page);
+	}
+	kunmap(page);
+	log_segment("logfs_segment_read(%lx, %llx, %x) %llx (%d)\n",
+			inode->i_ino, bix, level, ofs, err);
+	return err;
+}
+
+int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow)
+{
+	struct super_block *sb = inode->i_sb;
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_object_header h;
+	u16 len;
+	int err;
+
+	super->s_flags |= LOGFS_SB_FLAG_DIRTY;
+	BUG_ON(super->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
+	BUG_ON(shadow->old_ofs & LOGFS_FULLY_POPULATED);
+	if (!shadow->old_ofs)
+		return 0;
+
+	log_segment("logfs_segment_delete(%llx, %llx, %x) %llx->%llx %x->%x\n",
+			shadow->ino, shadow->bix, shadow->gc_level,
+			shadow->old_ofs, shadow->new_ofs,
+			shadow->old_len, shadow->new_len);
+	err = read_obj_header(sb, shadow->old_ofs, &h);
+	LOGFS_BUG_ON(err, sb);
+	LOGFS_BUG_ON(be64_to_cpu(h.ino) != inode->i_ino, sb);
+	LOGFS_BUG_ON(check_pos(sb, shadow->bix, be64_to_cpu(h.bix),
+				shrink_level(shadow->gc_level)), sb);
+
+	if (shadow->gc_level == 0)
+		len = be16_to_cpu(h.len);
+	else
+		len = obj_len(sb, h.type);
+	shadow->old_len = len + sizeof(h);
+	return 0;
+}
+
+static void freeseg(struct super_block *sb, u32 segno)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping = super->s_mapping_inode->i_mapping;
+	struct page *page;
+	u64 ofs, start, end;
+
+	start = dev_ofs(sb, segno, 0);
+	end = dev_ofs(sb, segno + 1, 0);
+	for (ofs = start; ofs < end; ofs += PAGE_SIZE) {
+		page = find_get_page(mapping, ofs >> PAGE_SHIFT);
+		if (!page)
+			continue;
+		ClearPagePrivate(page);
+		page_cache_release(page);
+	}
+}
+
+int logfs_open_area(struct logfs_area *area, size_t bytes)
+{
+	struct super_block *sb = area->a_sb;
+	struct logfs_super *super = logfs_super(sb);
+	int err, closed = 0;
+
+	if (area->a_is_open && area->a_used_bytes + bytes <= super->s_segsize)
+		return 0;
+
+	if (area->a_is_open) {
+		u64 ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
+		u32 len = super->s_segsize - area->a_written_bytes;
+
+		log_gc("logfs_close_area(%x)\n", area->a_segno);
+		pad_wbuf(area, 1);
+		super->s_devops->writeseg(area->a_sb, ofs, len);
+		freeseg(sb, area->a_segno);
+		closed = 1;
+	}
+
+	area->a_used_bytes = 0;
+	area->a_written_bytes = 0;
+again:
+	area->a_ops->get_free_segment(area);
+	area->a_ops->get_erase_count(area);
+
+	log_gc("logfs_open_area(%x, %x)\n", area->a_segno, area->a_level);
+	err = area->a_ops->erase_segment(area);
+	if (err) {
+		printk(KERN_WARNING "LogFS: Error erasing segment %x\n",
+				area->a_segno);
+		logfs_mark_segment_bad(sb, area->a_segno);
+		goto again;
+	}
+	area->a_is_open = 1;
+	return closed;
+}
+
+void logfs_sync_area(struct logfs_area *area)
+{
+	struct super_block *sb = area->a_sb;
+	struct logfs_super *super = logfs_super(sb);
+	u64 ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
+	u32 len = (area->a_used_bytes - area->a_written_bytes);
+
+	if (super->s_writesize)
+		len &= ~(super->s_writesize - 1);
+	if (len == 0)
+		return;
+	pad_wbuf(area, 0);
+	super->s_devops->writeseg(sb, ofs, len);
+	area->a_written_bytes += len;
+}
+
+void logfs_sync_segments(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int i;
+
+	for_each_area(i)
+		logfs_sync_area(super->s_area[i]);
+}
+
+/*
+ * Pick a free segment to be used for this area.  Effectively takes a
+ * candidate from the free list (not really a candidate anymore).
+ */
+static void ostore_get_free_segment(struct logfs_area *area)
+{
+	struct super_block *sb = area->a_sb;
+	struct logfs_super *super = logfs_super(sb);
+
+	if (super->s_free_list.count == 0) {
+		printk(KERN_ERR"LOGFS: ran out of free segments\n");
+		LOGFS_BUG(sb);
+	}
+
+	area->a_segno = get_best_cand(sb, &super->s_free_list, NULL);
+}
+
+static void ostore_get_erase_count(struct logfs_area *area)
+{
+	struct logfs_segment_entry se;
+	u32 ec_level;
+
+	logfs_get_segment_entry(area->a_sb, area->a_segno, &se);
+	BUG_ON(se.ec_level == cpu_to_be32(BADSEG) ||
+			se.valid == cpu_to_be32(RESERVED));
+
+	ec_level = be32_to_cpu(se.ec_level);
+	area->a_erase_count = (ec_level >> 4) + 1;
+}
+
+static int ostore_erase_segment(struct logfs_area *area)
+{
+	struct super_block *sb = area->a_sb;
+	struct logfs_segment_header sh;
+	u64 ofs;
+	int err;
+
+	err = logfs_erase_segment(sb, area->a_segno, 0);
+	if (err)
+		return err;
+
+	sh.pad = 0;
+	sh.type = SEG_OSTORE;
+	sh.level = (__force u8)area->a_level;
+	sh.segno = cpu_to_be32(area->a_segno);
+	sh.ec = cpu_to_be32(area->a_erase_count);
+	sh.gec = cpu_to_be64(logfs_super(sb)->s_gec);
+	sh.crc = logfs_crc32(&sh, sizeof(sh), 4);
+
+	logfs_set_segment_erased(sb, area->a_segno, area->a_erase_count,
+			area->a_level);
+
+	ofs = dev_ofs(sb, area->a_segno, 0);
+	area->a_used_bytes = sizeof(sh);
+	logfs_buf_write(area, ofs, &sh, sizeof(sh));
+	return 0;
+}
+
+static const struct logfs_area_ops ostore_area_ops = {
+	.get_free_segment	= ostore_get_free_segment,
+	.get_erase_count	= ostore_get_erase_count,
+	.erase_segment		= ostore_erase_segment,
+};
+
+static void free_area(struct logfs_area *area)
+{
+	if (area)
+		freeseg(area->a_sb, area->a_segno);
+	kfree(area);
+}
+
+static struct logfs_area *alloc_area(struct super_block *sb)
+{
+	struct logfs_area *area;
+
+	area = kzalloc(sizeof(*area), GFP_KERNEL);
+	if (!area)
+		return NULL;
+
+	area->a_sb = sb;
+	return area;
+}
+
+static void map_invalidatepage(struct page *page, unsigned long l)
+{
+	BUG();
+}
+
+static int map_releasepage(struct page *page, gfp_t g)
+{
+	/* Don't release these pages */
+	return 0;
+}
+
+static const struct address_space_operations mapping_aops = {
+	.invalidatepage = map_invalidatepage,
+	.releasepage	= map_releasepage,
+	.set_page_dirty = __set_page_dirty_nobuffers,
+};
+
+int logfs_init_mapping(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct address_space *mapping;
+	struct inode *inode;
+
+	inode = logfs_new_meta_inode(sb, LOGFS_INO_MAPPING);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
+	super->s_mapping_inode = inode;
+	mapping = inode->i_mapping;
+	mapping->a_ops = &mapping_aops;
+	/* Would it be possible to use __GFP_HIGHMEM as well? */
+	mapping_set_gfp_mask(mapping, GFP_NOFS);
+	return 0;
+}
+
+int logfs_init_areas(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int i = -1;
+
+	super->s_alias_pool = mempool_create_kmalloc_pool(600,
+			sizeof(struct object_alias_item));
+	if (!super->s_alias_pool)
+		return -ENOMEM;
+
+	super->s_journal_area = alloc_area(sb);
+	if (!super->s_journal_area)
+		goto err;
+
+	for_each_area(i) {
+		super->s_area[i] = alloc_area(sb);
+		if (!super->s_area[i])
+			goto err;
+		super->s_area[i]->a_level = GC_LEVEL(i);
+		super->s_area[i]->a_ops = &ostore_area_ops;
+	}
+	btree_init_mempool128(&super->s_object_alias_tree,
+			super->s_btree_pool);
+	return 0;
+
+err:
+	for (i--; i >= 0; i--)
+		free_area(super->s_area[i]);
+	free_area(super->s_journal_area);
+	mempool_destroy(super->s_alias_pool);
+	return -ENOMEM;
+}
+
+void logfs_cleanup_areas(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int i;
+
+	btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias);
+	for_each_area(i)
+		free_area(super->s_area[i]);
+	free_area(super->s_journal_area);
+	destroy_meta_inode(super->s_mapping_inode);
+}
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
new file mode 100644
index 0000000..c66beab
--- /dev/null
+++ b/fs/logfs/super.c
@@ -0,0 +1,650 @@
+/*
+ * fs/logfs/super.c
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ *
+ * Generally contains mount/umount code and also serves as a dump area for
+ * any functions that don't fit elsewhere and neither justify a file of their
+ * own.
+ */
+#include "logfs.h"
+#include <linux/bio.h>
+#include <linux/mtd/mtd.h>
+#include <linux/statfs.h>
+#include <linux/buffer_head.h>
+
+static DEFINE_MUTEX(emergency_mutex);
+static struct page *emergency_page;
+
+struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index)
+{
+	filler_t *filler = (filler_t *)mapping->a_ops->readpage;
+	struct page *page;
+	int err;
+
+	page = read_cache_page(mapping, index, filler, NULL);
+	if (page)
+		return page;
+
+	/* No more pages available, switch to emergency page */
+	printk(KERN_INFO"Logfs: Using emergency page\n");
+	mutex_lock(&emergency_mutex);
+	err = filler(NULL, emergency_page);
+	if (err) {
+		mutex_unlock(&emergency_mutex);
+		printk(KERN_EMERG"Logfs: Error reading emergency page\n");
+		return ERR_PTR(err);
+	}
+	return emergency_page;
+}
+
+void emergency_read_end(struct page *page)
+{
+	if (page == emergency_page)
+		mutex_unlock(&emergency_mutex);
+	else
+		page_cache_release(page);
+}
+
+static void dump_segfile(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_segment_entry se;
+	u32 segno;
+
+	for (segno = 0; segno < super->s_no_segs; segno++) {
+		logfs_get_segment_entry(sb, segno, &se);
+		printk("%3x: %6x %8x", segno, be32_to_cpu(se.ec_level),
+				be32_to_cpu(se.valid));
+		if (++segno < super->s_no_segs) {
+			logfs_get_segment_entry(sb, segno, &se);
+			printk(" %6x %8x", be32_to_cpu(se.ec_level),
+					be32_to_cpu(se.valid));
+		}
+		if (++segno < super->s_no_segs) {
+			logfs_get_segment_entry(sb, segno, &se);
+			printk(" %6x %8x", be32_to_cpu(se.ec_level),
+					be32_to_cpu(se.valid));
+		}
+		if (++segno < super->s_no_segs) {
+			logfs_get_segment_entry(sb, segno, &se);
+			printk(" %6x %8x", be32_to_cpu(se.ec_level),
+					be32_to_cpu(se.valid));
+		}
+		printk("\n");
+	}
+}
+
+/*
+ * logfs_crash_dump - dump debug information to device
+ *
+ * The LogFS superblock only occupies part of a segment.  This function will
+ * write as much debug information as it can gather into the spare space.
+ */
+void logfs_crash_dump(struct super_block *sb)
+{
+	dump_segfile(sb);
+}
+
+/*
+ * TODO: move to lib/string.c
+ */
+/**
+ * memchr_inv - Find a character in an area of memory.
+ * @s: The memory area
+ * @c: The byte to search for
+ * @n: The size of the area.
+ *
+ * returns the address of the first character other than @c, or %NULL
+ * if the whole buffer contains just @c.
+ */
+void *memchr_inv(const void *s, int c, size_t n)
+{
+	const unsigned char *p = s;
+	while (n-- != 0)
+		if ((unsigned char)c != *p++)
+			return (void *)(p - 1);
+
+	return NULL;
+}
+
+/*
+ * FIXME: There should be a reserve for root, similar to ext2.
+ */
+int logfs_statfs(struct dentry *dentry, struct kstatfs *stats)
+{
+	struct super_block *sb = dentry->d_sb;
+	struct logfs_super *super = logfs_super(sb);
+
+	stats->f_type		= LOGFS_MAGIC_U32;
+	stats->f_bsize		= sb->s_blocksize;
+	stats->f_blocks		= super->s_size >> LOGFS_BLOCK_BITS >> 3;
+	stats->f_bfree		= super->s_free_bytes >> sb->s_blocksize_bits;
+	stats->f_bavail		= super->s_free_bytes >> sb->s_blocksize_bits;
+	stats->f_files		= 0;
+	stats->f_ffree		= 0;
+	stats->f_namelen	= LOGFS_MAX_NAMELEN;
+	return 0;
+}
+
+static int logfs_sb_set(struct super_block *sb, void *_super)
+{
+	struct logfs_super *super = _super;
+
+	sb->s_fs_info = super;
+	sb->s_mtd = super->s_mtd;
+	sb->s_bdev = super->s_bdev;
+	return 0;
+}
+
+static int logfs_sb_test(struct super_block *sb, void *_super)
+{
+	struct logfs_super *super = _super;
+	struct mtd_info *mtd = super->s_mtd;
+
+	if (mtd && sb->s_mtd == mtd)
+		return 1;
+	if (super->s_bdev && sb->s_bdev == super->s_bdev)
+		return 1;
+	return 0;
+}
+
+static void set_segment_header(struct logfs_segment_header *sh, u8 type,
+		u8 level, u32 segno, u32 ec)
+{
+	sh->pad = 0;
+	sh->type = type;
+	sh->level = level;
+	sh->segno = cpu_to_be32(segno);
+	sh->ec = cpu_to_be32(ec);
+	sh->gec = cpu_to_be64(segno);
+	sh->crc = logfs_crc32(sh, LOGFS_SEGMENT_HEADERSIZE, 4);
+}
+
+static void logfs_write_ds(struct super_block *sb, struct logfs_disk_super *ds,
+		u32 segno, u32 ec)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_segment_header *sh = &ds->ds_sh;
+	int i;
+
+	memset(ds, 0, sizeof(*ds));
+	set_segment_header(sh, SEG_SUPER, 0, segno, ec);
+
+	ds->ds_ifile_levels	= super->s_ifile_levels;
+	ds->ds_iblock_levels	= super->s_iblock_levels;
+	ds->ds_data_levels	= super->s_data_levels; /* XXX: Remove */
+	ds->ds_segment_shift	= super->s_segshift;
+	ds->ds_block_shift	= sb->s_blocksize_bits;
+	ds->ds_write_shift	= super->s_writeshift;
+	ds->ds_filesystem_size	= cpu_to_be64(super->s_size);
+	ds->ds_segment_size	= cpu_to_be32(super->s_segsize);
+	ds->ds_bad_seg_reserve	= cpu_to_be32(super->s_bad_seg_reserve);
+	ds->ds_feature_incompat	= cpu_to_be64(super->s_feature_incompat);
+	ds->ds_feature_ro_compat= cpu_to_be64(super->s_feature_ro_compat);
+	ds->ds_feature_compat	= cpu_to_be64(super->s_feature_compat);
+	ds->ds_feature_flags	= cpu_to_be64(super->s_feature_flags);
+	ds->ds_root_reserve	= cpu_to_be64(super->s_root_reserve);
+	ds->ds_speed_reserve	= cpu_to_be64(super->s_speed_reserve);
+	journal_for_each(i)
+		ds->ds_journal_seg[i] = cpu_to_be32(super->s_journal_seg[i]);
+	ds->ds_magic		= cpu_to_be64(LOGFS_MAGIC);
+	ds->ds_crc = logfs_crc32(ds, sizeof(*ds),
+			LOGFS_SEGMENT_HEADERSIZE + 12);
+}
+
+static int write_one_sb(struct super_block *sb,
+		struct page *(*find_sb)(struct super_block *sb, u64 *ofs))
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_disk_super *ds;
+	struct logfs_segment_entry se;
+	struct page *page;
+	u64 ofs;
+	u32 ec, segno;
+	int err;
+
+	page = find_sb(sb, &ofs);
+	if (!page)
+		return -EIO;
+	ds = page_address(page);
+	segno = seg_no(sb, ofs);
+	logfs_get_segment_entry(sb, segno, &se);
+	ec = be32_to_cpu(se.ec_level) >> 4;
+	ec++;
+	logfs_set_segment_erased(sb, segno, ec, 0);
+	logfs_write_ds(sb, ds, segno, ec);
+	err = super->s_devops->write_sb(sb, page);
+	page_cache_release(page);
+	return err;
+}
+
+int logfs_write_sb(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int err;
+
+	/* First superblock */
+	err = write_one_sb(sb, super->s_devops->find_first_sb);
+	if (err)
+		return err;
+
+	/* Last superblock */
+	err = write_one_sb(sb, super->s_devops->find_last_sb);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int ds_cmp(const void *ds0, const void *ds1)
+{
+	size_t len = sizeof(struct logfs_disk_super);
+
+	/* We know the segment headers differ, so ignore them */
+	len -= LOGFS_SEGMENT_HEADERSIZE;
+	ds0 += LOGFS_SEGMENT_HEADERSIZE;
+	ds1 += LOGFS_SEGMENT_HEADERSIZE;
+	return memcmp(ds0, ds1, len);
+}
+
+static int logfs_recover_sb(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct logfs_disk_super _ds0, *ds0 = &_ds0;
+	struct logfs_disk_super _ds1, *ds1 = &_ds1;
+	int err, valid0, valid1;
+
+	/* read first superblock */
+	err = wbuf_read(sb, super->s_sb_ofs[0], sizeof(*ds0), ds0);
+	if (err)
+		return err;
+	/* read last superblock */
+	err = wbuf_read(sb, super->s_sb_ofs[1], sizeof(*ds1), ds1);
+	if (err)
+		return err;
+	valid0 = logfs_check_ds(ds0) == 0;
+	valid1 = logfs_check_ds(ds1) == 0;
+
+	if (!valid0 && valid1) {
+		printk(KERN_INFO"First superblock is invalid - fixing.\n");
+		return write_one_sb(sb, super->s_devops->find_first_sb);
+	}
+	if (valid0 && !valid1) {
+		printk(KERN_INFO"Last superblock is invalid - fixing.\n");
+		return write_one_sb(sb, super->s_devops->find_last_sb);
+	}
+	if (valid0 && valid1 && ds_cmp(ds0, ds1)) {
+		printk(KERN_INFO"Superblocks don't match - fixing.\n");
+		return write_one_sb(sb, super->s_devops->find_last_sb);
+	}
+	/* If neither is valid now, something's wrong.  Didn't we properly
+	 * check them before?!? */
+	BUG_ON(!valid0 && !valid1);
+	return 0;
+}
+
+static int logfs_make_writeable(struct super_block *sb)
+{
+	int err;
+
+	/* Repair any broken superblock copies */
+	err = logfs_recover_sb(sb);
+	if (err)
+		return err;
+
+	/* Check areas for trailing unaccounted data */
+	err = logfs_check_areas(sb);
+	if (err)
+		return err;
+
+	err = logfs_open_segfile(sb);
+	if (err)
+		return err;
+
+	/* Do one GC pass before any data gets dirtied */
+	logfs_gc_pass(sb);
+
+	/* after all initializations are done, replay the journal
+	 * for rw-mounts, if necessary */
+	err = logfs_replay_journal(sb);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct inode *rootdir;
+	int err;
+
+	/* root dir */
+	rootdir = logfs_iget(sb, LOGFS_INO_ROOT);
+	if (IS_ERR(rootdir))
+		goto fail;
+
+	sb->s_root = d_alloc_root(rootdir);
+	if (!sb->s_root)
+		goto fail;
+
+	super->s_erase_page = alloc_pages(GFP_KERNEL, 0);
+	if (!super->s_erase_page)
+		goto fail2;
+	memset(page_address(super->s_erase_page), 0xFF, PAGE_SIZE);
+
+	/* FIXME: check for read-only mounts */
+	err = logfs_make_writeable(sb);
+	if (err)
+		goto fail3;
+
+	log_super("LogFS: Finished mounting\n");
+	simple_set_mnt(mnt, sb);
+	return 0;
+
+fail3:
+	__free_page(super->s_erase_page);
+fail2:
+	iput(rootdir);
+fail:
+	iput(logfs_super(sb)->s_master_inode);
+	return -EIO;
+}
+
+int logfs_check_ds(struct logfs_disk_super *ds)
+{
+	struct logfs_segment_header *sh = &ds->ds_sh;
+
+	if (ds->ds_magic != cpu_to_be64(LOGFS_MAGIC))
+		return -EINVAL;
+	if (sh->crc != logfs_crc32(sh, LOGFS_SEGMENT_HEADERSIZE, 4))
+		return -EINVAL;
+	if (ds->ds_crc != logfs_crc32(ds, sizeof(*ds),
+				LOGFS_SEGMENT_HEADERSIZE + 12))
+		return -EINVAL;
+	return 0;
+}
+
+static struct page *find_super_block(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct page *first, *last;
+
+	first = super->s_devops->find_first_sb(sb, &super->s_sb_ofs[0]);
+	if (!first || IS_ERR(first))
+		return NULL;
+	last = super->s_devops->find_last_sb(sb, &super->s_sb_ofs[1]);
+	if (!last || IS_ERR(first)) {
+		page_cache_release(first);
+		return NULL;
+	}
+
+	if (!logfs_check_ds(page_address(first))) {
+		page_cache_release(last);
+		return first;
+	}
+
+	/* First one didn't work, try the second superblock */
+	if (!logfs_check_ds(page_address(last))) {
+		page_cache_release(first);
+		return last;
+	}
+
+	/* Neither worked, sorry folks */
+	page_cache_release(first);
+	page_cache_release(last);
+	return NULL;
+}
+
+static int __logfs_read_sb(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	struct page *page;
+	struct logfs_disk_super *ds;
+	int i;
+
+	page = find_super_block(sb);
+	if (!page)
+		return -EIO;
+
+	ds = page_address(page);
+	super->s_size = be64_to_cpu(ds->ds_filesystem_size);
+	super->s_root_reserve = be64_to_cpu(ds->ds_root_reserve);
+	super->s_speed_reserve = be64_to_cpu(ds->ds_speed_reserve);
+	super->s_bad_seg_reserve = be32_to_cpu(ds->ds_bad_seg_reserve);
+	super->s_segsize = 1 << ds->ds_segment_shift;
+	super->s_segmask = (1 << ds->ds_segment_shift) - 1;
+	super->s_segshift = ds->ds_segment_shift;
+	sb->s_blocksize = 1 << ds->ds_block_shift;
+	sb->s_blocksize_bits = ds->ds_block_shift;
+	super->s_writesize = 1 << ds->ds_write_shift;
+	super->s_writeshift = ds->ds_write_shift;
+	super->s_no_segs = super->s_size >> super->s_segshift;
+	super->s_no_blocks = super->s_segsize >> sb->s_blocksize_bits;
+	super->s_feature_incompat = be64_to_cpu(ds->ds_feature_incompat);
+	super->s_feature_ro_compat = be64_to_cpu(ds->ds_feature_ro_compat);
+	super->s_feature_compat = be64_to_cpu(ds->ds_feature_compat);
+	super->s_feature_flags = be64_to_cpu(ds->ds_feature_flags);
+
+	journal_for_each(i)
+		super->s_journal_seg[i] = be32_to_cpu(ds->ds_journal_seg[i]);
+
+	super->s_ifile_levels = ds->ds_ifile_levels;
+	super->s_iblock_levels = ds->ds_iblock_levels;
+	super->s_data_levels = ds->ds_data_levels;
+	super->s_total_levels = super->s_ifile_levels + super->s_iblock_levels
+		+ super->s_data_levels;
+	page_cache_release(page);
+	return 0;
+}
+
+static int logfs_read_sb(struct super_block *sb, int read_only)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int ret;
+
+	super->s_btree_pool = mempool_create(32, btree_alloc, btree_free, NULL);
+	if (!super->s_btree_pool)
+		return -ENOMEM;
+
+	btree_init_mempool64(&super->s_shadow_tree.new, super->s_btree_pool);
+	btree_init_mempool64(&super->s_shadow_tree.old, super->s_btree_pool);
+
+	ret = logfs_init_mapping(sb);
+	if (ret)
+		return ret;
+
+	ret = __logfs_read_sb(sb);
+	if (ret)
+		return ret;
+
+	if (super->s_feature_incompat & ~LOGFS_FEATURES_INCOMPAT)
+		return -EIO;
+	if ((super->s_feature_ro_compat & ~LOGFS_FEATURES_RO_COMPAT) &&
+			!read_only)
+		return -EIO;
+
+	mutex_init(&super->s_dirop_mutex);
+	mutex_init(&super->s_object_alias_mutex);
+	INIT_LIST_HEAD(&super->s_freeing_list);
+
+	ret = logfs_init_rw(sb);
+	if (ret)
+		return ret;
+
+	ret = logfs_init_areas(sb);
+	if (ret)
+		return ret;
+
+	ret = logfs_init_gc(sb);
+	if (ret)
+		return ret;
+
+	ret = logfs_init_journal(sb);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void logfs_kill_sb(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+
+	log_super("LogFS: Start unmounting\n");
+	/* Alias entries slow down mount, so evict as many as possible */
+	sync_filesystem(sb);
+	logfs_write_anchor(sb);
+
+	/*
+	 * From this point on alias entries are simply dropped - and any
+	 * writes to the object store are considered bugs.
+	 */
+	super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
+	log_super("LogFS: Now in shutdown\n");
+	generic_shutdown_super(sb);
+
+	BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes);
+
+	logfs_cleanup_gc(sb);
+	logfs_cleanup_journal(sb);
+	logfs_cleanup_areas(sb);
+	logfs_cleanup_rw(sb);
+	if (super->s_erase_page)
+		__free_page(super->s_erase_page);
+	super->s_devops->put_device(sb);
+	mempool_destroy(super->s_btree_pool);
+	mempool_destroy(super->s_alias_pool);
+	kfree(super);
+	log_super("LogFS: Finished unmounting\n");
+}
+
+int logfs_get_sb_device(struct file_system_type *type, int flags,
+		struct mtd_info *mtd, struct block_device *bdev,
+		const struct logfs_device_ops *devops, struct vfsmount *mnt)
+{
+	struct logfs_super *super;
+	struct super_block *sb;
+	int err = -ENOMEM;
+	static int mount_count;
+
+	log_super("LogFS: Start mount %x\n", mount_count++);
+	super = kzalloc(sizeof(*super), GFP_KERNEL);
+	if (!super)
+		goto err0;
+
+	super->s_mtd	= mtd;
+	super->s_bdev	= bdev;
+	err = -EINVAL;
+	sb = sget(type, logfs_sb_test, logfs_sb_set, super);
+	if (IS_ERR(sb))
+		goto err0;
+
+	if (sb->s_root) {
+		/* Device is already in use */
+		err = 0;
+		simple_set_mnt(mnt, sb);
+		goto err0;
+	}
+
+	super->s_devops = devops;
+
+	/*
+	 * sb->s_maxbytes is limited to 8TB.  On 32bit systems, the page cache
+	 * only covers 16TB and the upper 8TB are used for indirect blocks.
+	 * On 64bit system we could bump up the limit, but that would make
+	 * the filesystem incompatible with 32bit systems.
+	 */
+	sb->s_maxbytes	= (1ull << 43) - 1;
+	sb->s_op	= &logfs_super_operations;
+	sb->s_flags	= flags | MS_NOATIME;
+
+	err = logfs_read_sb(sb, sb->s_flags & MS_RDONLY);
+	if (err)
+		goto err1;
+
+	sb->s_flags |= MS_ACTIVE;
+	err = logfs_get_sb_final(sb, mnt);
+	if (err)
+		goto err1;
+	return 0;
+
+err1:
+	up_write(&sb->s_umount);
+	deactivate_super(sb);
+	return err;
+err0:
+	kfree(super);
+	//devops->put_device(sb);
+	return err;
+}
+
+static int logfs_get_sb(struct file_system_type *type, int flags,
+		const char *devname, void *data, struct vfsmount *mnt)
+{
+	ulong mtdnr;
+
+	if (!devname)
+		return logfs_get_sb_bdev(type, flags, devname, mnt);
+	if (strncmp(devname, "mtd", 3))
+		return logfs_get_sb_bdev(type, flags, devname, mnt);
+
+	{
+		char *garbage;
+		mtdnr = simple_strtoul(devname+3, &garbage, 0);
+		if (*garbage)
+			return -EINVAL;
+	}
+
+	return logfs_get_sb_mtd(type, flags, mtdnr, mnt);
+}
+
+static struct file_system_type logfs_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "logfs",
+	.get_sb		= logfs_get_sb,
+	.kill_sb	= logfs_kill_sb,
+	.fs_flags	= FS_REQUIRES_DEV,
+
+};
+
+static int __init logfs_init(void)
+{
+	int ret;
+
+	emergency_page = alloc_pages(GFP_KERNEL, 0);
+	if (!emergency_page)
+		return -ENOMEM;
+
+	ret = logfs_compr_init();
+	if (ret)
+		goto out1;
+
+	ret = logfs_init_inode_cache();
+	if (ret)
+		goto out2;
+
+	return register_filesystem(&logfs_fs_type);
+out2:
+	logfs_compr_exit();
+out1:
+	__free_pages(emergency_page, 0);
+	return ret;
+}
+
+static void __exit logfs_exit(void)
+{
+	unregister_filesystem(&logfs_fs_type);
+	logfs_destroy_inode_cache();
+	logfs_compr_exit();
+	__free_pages(emergency_page, 0);
+}
+
+module_init(logfs_init);
+module_exit(logfs_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Joern Engel <joern@logfs.org>");
+MODULE_DESCRIPTION("scalable flash filesystem");
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 74ea82d..756f8c9 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -17,8 +17,10 @@
 #include <linux/init.h>
 #include <linux/highuid.h>
 #include <linux/vfs.h>
+#include <linux/writeback.h>
 
-static int minix_write_inode(struct inode * inode, int wait);
+static int minix_write_inode(struct inode *inode,
+		struct writeback_control *wbc);
 static int minix_statfs(struct dentry *dentry, struct kstatfs *buf);
 static int minix_remount (struct super_block * sb, int * flags, char * data);
 
@@ -552,7 +554,7 @@
 	return bh;
 }
 
-static int minix_write_inode(struct inode *inode, int wait)
+static int minix_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	int err = 0;
 	struct buffer_head *bh;
@@ -563,7 +565,7 @@
 		bh = V2_minix_update_inode(inode);
 	if (!bh)
 		return -EIO;
-	if (wait && buffer_dirty(bh)) {
+	if (wbc->sync_mode == WB_SYNC_ALL && buffer_dirty(bh)) {
 		sync_dirty_buffer(bh);
 		if (buffer_req(bh) && !buffer_uptodate(bh)) {
 			printk("IO error syncing minix inode [%s:%08lx]\n",
diff --git a/fs/mpage.c b/fs/mpage.c
index 42381bd..598d54e 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -561,7 +561,7 @@
 	if (page->index >= end_index) {
 		/*
 		 * The page straddles i_size.  It must be zeroed out on each
-		 * and every writepage invokation because it may be mmapped.
+		 * and every writepage invocation because it may be mmapped.
 		 * "A file is mapped in multiples of the page size.  For a file
 		 * that is not a multiple of the page size, the remaining memory
 		 * is zeroed when mapped, and writes to that region are not
diff --git a/fs/namei.c b/fs/namei.c
index a4855af..1c0fca6 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -19,7 +19,6 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
-#include <linux/quotaops.h>
 #include <linux/pagemap.h>
 #include <linux/fsnotify.h>
 #include <linux/personality.h>
@@ -498,8 +497,6 @@
 
 static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
 {
-	int res = 0;
-	char *name;
 	if (IS_ERR(link))
 		goto fail;
 
@@ -510,22 +507,7 @@
 		path_get(&nd->root);
 	}
 
-	res = link_path_walk(link, nd);
-	if (nd->depth || res || nd->last_type!=LAST_NORM)
-		return res;
-	/*
-	 * If it is an iterative symlinks resolution in open_namei() we
-	 * have to copy the last component. And all that crap because of
-	 * bloody create() on broken symlinks. Furrfu...
-	 */
-	name = __getname();
-	if (unlikely(!name)) {
-		path_put(&nd->path);
-		return -ENOMEM;
-	}
-	strcpy(name, nd->last.name);
-	nd->last.name = name;
-	return 0;
+	return link_path_walk(link, nd);
 fail:
 	path_put(&nd->path);
 	return PTR_ERR(link);
@@ -547,10 +529,10 @@
 	nd->path.dentry = path->dentry;
 }
 
-static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
+static __always_inline int
+__do_follow_link(struct path *path, struct nameidata *nd, void **p)
 {
 	int error;
-	void *cookie;
 	struct dentry *dentry = path->dentry;
 
 	touch_atime(path->mnt, dentry);
@@ -562,9 +544,9 @@
 	}
 	mntget(path->mnt);
 	nd->last_type = LAST_BIND;
-	cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
-	error = PTR_ERR(cookie);
-	if (!IS_ERR(cookie)) {
+	*p = dentry->d_inode->i_op->follow_link(dentry, nd);
+	error = PTR_ERR(*p);
+	if (!IS_ERR(*p)) {
 		char *s = nd_get_link(nd);
 		error = 0;
 		if (s)
@@ -574,8 +556,6 @@
 			if (error)
 				path_put(&nd->path);
 		}
-		if (dentry->d_inode->i_op->put_link)
-			dentry->d_inode->i_op->put_link(dentry, nd, cookie);
 	}
 	return error;
 }
@@ -589,6 +569,7 @@
  */
 static inline int do_follow_link(struct path *path, struct nameidata *nd)
 {
+	void *cookie;
 	int err = -ELOOP;
 	if (current->link_count >= MAX_NESTED_LINKS)
 		goto loop;
@@ -602,7 +583,9 @@
 	current->link_count++;
 	current->total_link_count++;
 	nd->depth++;
-	err = __do_follow_link(path, nd);
+	err = __do_follow_link(path, nd, &cookie);
+	if (!IS_ERR(cookie) && path->dentry->d_inode->i_op->put_link)
+		path->dentry->d_inode->i_op->put_link(path->dentry, nd, cookie);
 	path_put(path);
 	current->link_count--;
 	nd->depth--;
@@ -689,33 +672,20 @@
 	set_root(nd);
 
 	while(1) {
-		struct vfsmount *parent;
 		struct dentry *old = nd->path.dentry;
 
 		if (nd->path.dentry == nd->root.dentry &&
 		    nd->path.mnt == nd->root.mnt) {
 			break;
 		}
-		spin_lock(&dcache_lock);
 		if (nd->path.dentry != nd->path.mnt->mnt_root) {
-			nd->path.dentry = dget(nd->path.dentry->d_parent);
-			spin_unlock(&dcache_lock);
+			/* rare case of legitimate dget_parent()... */
+			nd->path.dentry = dget_parent(nd->path.dentry);
 			dput(old);
 			break;
 		}
-		spin_unlock(&dcache_lock);
-		spin_lock(&vfsmount_lock);
-		parent = nd->path.mnt->mnt_parent;
-		if (parent == nd->path.mnt) {
-			spin_unlock(&vfsmount_lock);
+		if (!follow_up(&nd->path))
 			break;
-		}
-		mntget(parent);
-		nd->path.dentry = dget(nd->path.mnt->mnt_mountpoint);
-		spin_unlock(&vfsmount_lock);
-		dput(old);
-		mntput(nd->path.mnt);
-		nd->path.mnt = parent;
 	}
 	follow_mount(&nd->path);
 }
@@ -1347,7 +1317,7 @@
 		return -ENOENT;
 
 	BUG_ON(victim->d_parent->d_inode != dir);
-	audit_inode_child(victim->d_name.name, victim, dir);
+	audit_inode_child(victim, dir);
 
 	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
 	if (error)
@@ -1388,22 +1358,6 @@
 	return inode_permission(dir, MAY_WRITE | MAY_EXEC);
 }
 
-/* 
- * O_DIRECTORY translates into forcing a directory lookup.
- */
-static inline int lookup_flags(unsigned int f)
-{
-	unsigned long retval = LOOKUP_FOLLOW;
-
-	if (f & O_NOFOLLOW)
-		retval &= ~LOOKUP_FOLLOW;
-	
-	if (f & O_DIRECTORY)
-		retval |= LOOKUP_DIRECTORY;
-
-	return retval;
-}
-
 /*
  * p1 and p2 should be directories on the same fs.
  */
@@ -1461,7 +1415,6 @@
 	error = security_inode_create(dir, dentry, mode);
 	if (error)
 		return error;
-	vfs_dq_init(dir);
 	error = dir->i_op->create(dir, dentry, mode, nd);
 	if (!error)
 		fsnotify_create(dir, dentry);
@@ -1503,7 +1456,7 @@
 	 * An append-only file must be opened in append mode for writing.
 	 */
 	if (IS_APPEND(inode)) {
-		if  ((flag & FMODE_WRITE) && !(flag & O_APPEND))
+		if  ((flag & O_ACCMODE) != O_RDONLY && !(flag & O_APPEND))
 			return -EPERM;
 		if (flag & O_TRUNC)
 			return -EPERM;
@@ -1547,7 +1500,7 @@
  * what get passed to sys_open().
  */
 static int __open_namei_create(struct nameidata *nd, struct path *path,
-				int flag, int mode)
+				int open_flag, int mode)
 {
 	int error;
 	struct dentry *dir = nd->path.dentry;
@@ -1565,7 +1518,7 @@
 	if (error)
 		return error;
 	/* Don't check for write permission, don't truncate */
-	return may_open(&nd->path, 0, flag & ~O_TRUNC);
+	return may_open(&nd->path, 0, open_flag & ~O_TRUNC);
 }
 
 /*
@@ -1603,129 +1556,132 @@
 	return (flag & O_TRUNC);
 }
 
-/*
- * Note that the low bits of the passed in "open_flag"
- * are not the same as in the local variable "flag". See
- * open_to_namei_flags() for more details.
- */
-struct file *do_filp_open(int dfd, const char *pathname,
-		int open_flag, int mode, int acc_mode)
+static struct file *finish_open(struct nameidata *nd,
+				int open_flag, int acc_mode)
 {
 	struct file *filp;
-	struct nameidata nd;
-	int error;
-	struct path path;
-	struct dentry *dir;
-	int count = 0;
 	int will_truncate;
-	int flag = open_to_namei_flags(open_flag);
-	int force_reval = 0;
+	int error;
 
-	/*
-	 * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
-	 * check for O_DSYNC if the need any syncing at all we enforce it's
-	 * always set instead of having to deal with possibly weird behaviour
-	 * for malicious applications setting only __O_SYNC.
-	 */
-	if (open_flag & __O_SYNC)
-		open_flag |= O_DSYNC;
-
-	if (!acc_mode)
-		acc_mode = MAY_OPEN | ACC_MODE(open_flag);
-
-	/* O_TRUNC implies we need access checks for write permissions */
-	if (flag & O_TRUNC)
-		acc_mode |= MAY_WRITE;
-
-	/* Allow the LSM permission hook to distinguish append 
-	   access from general write access. */
-	if (flag & O_APPEND)
-		acc_mode |= MAY_APPEND;
-
-	/*
-	 * The simplest case - just a plain lookup.
-	 */
-	if (!(flag & O_CREAT)) {
-		filp = get_empty_filp();
-
-		if (filp == NULL)
-			return ERR_PTR(-ENFILE);
-		nd.intent.open.file = filp;
-		filp->f_flags = open_flag;
-		nd.intent.open.flags = flag;
-		nd.intent.open.create_mode = 0;
-		error = do_path_lookup(dfd, pathname,
-					lookup_flags(flag)|LOOKUP_OPEN, &nd);
-		if (IS_ERR(nd.intent.open.file)) {
-			if (error == 0) {
-				error = PTR_ERR(nd.intent.open.file);
-				path_put(&nd.path);
-			}
-		} else if (error)
-			release_open_intent(&nd);
+	will_truncate = open_will_truncate(open_flag, nd->path.dentry->d_inode);
+	if (will_truncate) {
+		error = mnt_want_write(nd->path.mnt);
 		if (error)
-			return ERR_PTR(error);
+			goto exit;
+	}
+	error = may_open(&nd->path, acc_mode, open_flag);
+	if (error) {
+		if (will_truncate)
+			mnt_drop_write(nd->path.mnt);
+		goto exit;
+	}
+	filp = nameidata_to_filp(nd);
+	if (!IS_ERR(filp)) {
+		error = ima_file_check(filp, acc_mode);
+		if (error) {
+			fput(filp);
+			filp = ERR_PTR(error);
+		}
+	}
+	if (!IS_ERR(filp)) {
+		if (will_truncate) {
+			error = handle_truncate(&nd->path);
+			if (error) {
+				fput(filp);
+				filp = ERR_PTR(error);
+			}
+		}
+	}
+	/*
+	 * It is now safe to drop the mnt write
+	 * because the filp has had a write taken
+	 * on its behalf.
+	 */
+	if (will_truncate)
+		mnt_drop_write(nd->path.mnt);
+	return filp;
+
+exit:
+	if (!IS_ERR(nd->intent.open.file))
+		release_open_intent(nd);
+	path_put(&nd->path);
+	return ERR_PTR(error);
+}
+
+static struct file *do_last(struct nameidata *nd, struct path *path,
+			    int open_flag, int acc_mode,
+			    int mode, const char *pathname,
+			    int *want_dir)
+{
+	struct dentry *dir = nd->path.dentry;
+	struct file *filp;
+	int error = -EISDIR;
+
+	switch (nd->last_type) {
+	case LAST_DOTDOT:
+		follow_dotdot(nd);
+		dir = nd->path.dentry;
+		if (nd->path.mnt->mnt_sb->s_type->fs_flags & FS_REVAL_DOT) {
+			if (!dir->d_op->d_revalidate(dir, nd)) {
+				error = -ESTALE;
+				goto exit;
+			}
+		}
+		/* fallthrough */
+	case LAST_DOT:
+	case LAST_ROOT:
+		if (open_flag & O_CREAT)
+			goto exit;
+		/* fallthrough */
+	case LAST_BIND:
+		audit_inode(pathname, dir);
 		goto ok;
 	}
 
-	/*
-	 * Create - we need to know the parent.
-	 */
-reval:
-	error = path_init(dfd, pathname, LOOKUP_PARENT, &nd);
-	if (error)
-		return ERR_PTR(error);
-	if (force_reval)
-		nd.flags |= LOOKUP_REVAL;
-	error = path_walk(pathname, &nd);
-	if (error) {
-		if (nd.root.mnt)
-			path_put(&nd.root);
-		return ERR_PTR(error);
+	/* trailing slashes? */
+	if (nd->last.name[nd->last.len]) {
+		if (open_flag & O_CREAT)
+			goto exit;
+		*want_dir = 1;
 	}
-	if (unlikely(!audit_dummy_context()))
-		audit_inode(pathname, nd.path.dentry);
 
-	/*
-	 * We have the parent and last component. First of all, check
-	 * that we are not asked to creat(2) an obvious directory - that
-	 * will not do.
-	 */
-	error = -EISDIR;
-	if (nd.last_type != LAST_NORM || nd.last.name[nd.last.len])
-		goto exit_parent;
+	/* 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 (*want_dir && !path->dentry->d_inode->i_op->lookup)
+			goto exit_dput;
+		path_to_nameidata(path, nd);
+		audit_inode(pathname, nd->path.dentry);
+		goto ok;
+	}
 
-	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;
-	dir = nd.path.dentry;
-	nd.flags &= ~LOOKUP_PARENT;
-	nd.flags |= LOOKUP_CREATE | LOOKUP_OPEN;
-	if (flag & O_EXCL)
-		nd.flags |= LOOKUP_EXCL;
+	/* OK, it's O_CREAT */
 	mutex_lock(&dir->d_inode->i_mutex);
-	path.dentry = lookup_hash(&nd);
-	path.mnt = nd.path.mnt;
 
-do_last:
-	error = PTR_ERR(path.dentry);
-	if (IS_ERR(path.dentry)) {
+	path->dentry = lookup_hash(nd);
+	path->mnt = nd->path.mnt;
+
+	error = PTR_ERR(path->dentry);
+	if (IS_ERR(path->dentry)) {
 		mutex_unlock(&dir->d_inode->i_mutex);
 		goto exit;
 	}
 
-	if (IS_ERR(nd.intent.open.file)) {
-		error = PTR_ERR(nd.intent.open.file);
+	if (IS_ERR(nd->intent.open.file)) {
+		error = PTR_ERR(nd->intent.open.file);
 		goto exit_mutex_unlock;
 	}
 
 	/* Negative dentry, just create the file */
-	if (!path.dentry->d_inode) {
+	if (!path->dentry->d_inode) {
 		/*
 		 * This write is needed to ensure that a
 		 * ro->rw transition does not occur between
@@ -1733,18 +1689,16 @@
 		 * a permanent write count is taken through
 		 * the 'struct file' in nameidata_to_filp().
 		 */
-		error = mnt_want_write(nd.path.mnt);
+		error = mnt_want_write(nd->path.mnt);
 		if (error)
 			goto exit_mutex_unlock;
-		error = __open_namei_create(&nd, &path, flag, mode);
+		error = __open_namei_create(nd, path, open_flag, mode);
 		if (error) {
-			mnt_drop_write(nd.path.mnt);
+			mnt_drop_write(nd->path.mnt);
 			goto exit;
 		}
-		filp = nameidata_to_filp(&nd);
-		mnt_drop_write(nd.path.mnt);
-		if (nd.root.mnt)
-			path_put(&nd.root);
+		filp = nameidata_to_filp(nd);
+		mnt_drop_write(nd->path.mnt);
 		if (!IS_ERR(filp)) {
 			error = ima_file_check(filp, acc_mode);
 			if (error) {
@@ -1759,150 +1713,181 @@
 	 * It already exists.
 	 */
 	mutex_unlock(&dir->d_inode->i_mutex);
-	audit_inode(pathname, path.dentry);
+	audit_inode(pathname, path->dentry);
 
 	error = -EEXIST;
-	if (flag & O_EXCL)
+	if (open_flag & O_EXCL)
 		goto exit_dput;
 
-	if (__follow_mount(&path)) {
+	if (__follow_mount(path)) {
 		error = -ELOOP;
-		if (flag & O_NOFOLLOW)
+		if (open_flag & O_NOFOLLOW)
 			goto exit_dput;
 	}
 
 	error = -ENOENT;
-	if (!path.dentry->d_inode)
+	if (!path->dentry->d_inode)
 		goto exit_dput;
-	if (path.dentry->d_inode->i_op->follow_link)
-		goto do_link;
 
-	path_to_nameidata(&path, &nd);
+	if (path->dentry->d_inode->i_op->follow_link)
+		return NULL;
+
+	path_to_nameidata(path, nd);
 	error = -EISDIR;
-	if (S_ISDIR(path.dentry->d_inode->i_mode))
+	if (S_ISDIR(path->dentry->d_inode->i_mode))
 		goto exit;
 ok:
-	/*
-	 * Consider:
-	 * 1. may_open() truncates a file
-	 * 2. a rw->ro mount transition occurs
-	 * 3. nameidata_to_filp() fails due to
-	 *    the ro mount.
-	 * That would be inconsistent, and should
-	 * be avoided. Taking this mnt write here
-	 * ensures that (2) can not occur.
-	 */
-	will_truncate = open_will_truncate(flag, nd.path.dentry->d_inode);
-	if (will_truncate) {
-		error = mnt_want_write(nd.path.mnt);
-		if (error)
-			goto exit;
-	}
-	error = may_open(&nd.path, acc_mode, flag);
-	if (error) {
-		if (will_truncate)
-			mnt_drop_write(nd.path.mnt);
-		goto exit;
-	}
-	filp = nameidata_to_filp(&nd);
-	if (!IS_ERR(filp)) {
-		error = ima_file_check(filp, acc_mode);
-		if (error) {
-			fput(filp);
-			filp = ERR_PTR(error);
-		}
-	}
-	if (!IS_ERR(filp)) {
-		if (acc_mode & MAY_WRITE)
-			vfs_dq_init(nd.path.dentry->d_inode);
-
-		if (will_truncate) {
-			error = handle_truncate(&nd.path);
-			if (error) {
-				fput(filp);
-				filp = ERR_PTR(error);
-			}
-		}
-	}
-	/*
-	 * It is now safe to drop the mnt write
-	 * because the filp has had a write taken
-	 * on its behalf.
-	 */
-	if (will_truncate)
-		mnt_drop_write(nd.path.mnt);
-	if (nd.root.mnt)
-		path_put(&nd.root);
+	filp = finish_open(nd, open_flag, acc_mode);
 	return filp;
 
 exit_mutex_unlock:
 	mutex_unlock(&dir->d_inode->i_mutex);
 exit_dput:
-	path_put_conditional(&path, &nd);
+	path_put_conditional(path, nd);
 exit:
+	if (!IS_ERR(nd->intent.open.file))
+		release_open_intent(nd);
+	path_put(&nd->path);
+	return ERR_PTR(error);
+}
+
+/*
+ * Note that the low bits of the passed in "open_flag"
+ * are not the same as in the local variable "flag". See
+ * open_to_namei_flags() for more details.
+ */
+struct file *do_filp_open(int dfd, const char *pathname,
+		int open_flag, int mode, int acc_mode)
+{
+	struct file *filp;
+	struct nameidata nd;
+	int error;
+	struct path path;
+	int count = 0;
+	int flag = open_to_namei_flags(open_flag);
+	int force_reval = 0;
+	int want_dir = open_flag & O_DIRECTORY;
+
+	if (!(open_flag & O_CREAT))
+		mode = 0;
+
+	/*
+	 * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
+	 * check for O_DSYNC if the need any syncing at all we enforce it's
+	 * always set instead of having to deal with possibly weird behaviour
+	 * for malicious applications setting only __O_SYNC.
+	 */
+	if (open_flag & __O_SYNC)
+		open_flag |= O_DSYNC;
+
+	if (!acc_mode)
+		acc_mode = MAY_OPEN | ACC_MODE(open_flag);
+
+	/* O_TRUNC implies we need access checks for write permissions */
+	if (open_flag & O_TRUNC)
+		acc_mode |= MAY_WRITE;
+
+	/* Allow the LSM permission hook to distinguish append 
+	   access from general write access. */
+	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;
+	}
+	if (unlikely(!audit_dummy_context()) && (open_flag & O_CREAT))
+		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;
+	}
+	filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname, &want_dir);
+	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 ((open_flag & O_NOFOLLOW) && !S_ISDIR(inode->i_mode))
+			goto exit_dput;
+		if (count++ == 32)
+			goto exit_dput;
+		/*
+		 * This is subtle. Instead of calling do_follow_link() we do
+		 * the thing by hands. The reason is that this way we have zero
+		 * link_count and path_walk() (called from ->follow_link)
+		 * honoring LOOKUP_PARENT.  After that we have the parent and
+		 * last component, i.e. we are in the same situation as after
+		 * the first path_walk().  Well, almost - if the last component
+		 * is normal we get its copy stored in nd->last.name and we will
+		 * have to putname() it when we are done. Procfs-like symlinks
+		 * just set LAST_BIND.
+		 */
+		nd.flags |= LOOKUP_PARENT;
+		error = security_inode_follow_link(path.dentry, &nd);
+		if (error)
+			goto exit_dput;
+		error = __do_follow_link(&path, &nd, &cookie);
+		if (unlikely(error)) {
+			/* 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;
+		}
+		holder = path;
+		nd.flags &= ~LOOKUP_PARENT;
+		filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname, &want_dir);
+		if (inode->i_op->put_link)
+			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;
+		goto reval;
+	}
+	return filp;
+
+exit_dput:
+	path_put_conditional(&path, &nd);
 	if (!IS_ERR(nd.intent.open.file))
 		release_open_intent(&nd);
 exit_parent:
-	if (nd.root.mnt)
-		path_put(&nd.root);
 	path_put(&nd.path);
-	return ERR_PTR(error);
-
-do_link:
-	error = -ELOOP;
-	if (flag & O_NOFOLLOW)
-		goto exit_dput;
-	/*
-	 * This is subtle. Instead of calling do_follow_link() we do the
-	 * thing by hands. The reason is that this way we have zero link_count
-	 * and path_walk() (called from ->follow_link) honoring LOOKUP_PARENT.
-	 * After that we have the parent and last component, i.e.
-	 * we are in the same situation as after the first path_walk().
-	 * Well, almost - if the last component is normal we get its copy
-	 * stored in nd->last.name and we will have to putname() it when we
-	 * are done. Procfs-like symlinks just set LAST_BIND.
-	 */
-	nd.flags |= LOOKUP_PARENT;
-	error = security_inode_follow_link(path.dentry, &nd);
-	if (error)
-		goto exit_dput;
-	error = __do_follow_link(&path, &nd);
-	path_put(&path);
-	if (error) {
-		/* Does someone understand code flow here? Or it is only
-		 * me so stupid? Anathema to whoever designed this non-sense
-		 * with "intent.open".
-		 */
-		release_open_intent(&nd);
-		if (nd.root.mnt)
-			path_put(&nd.root);
-		if (error == -ESTALE && !force_reval) {
-			force_reval = 1;
-			goto reval;
-		}
-		return ERR_PTR(error);
-	}
-	nd.flags &= ~LOOKUP_PARENT;
-	if (nd.last_type == LAST_BIND)
-		goto ok;
-	error = -EISDIR;
-	if (nd.last_type != LAST_NORM)
-		goto exit;
-	if (nd.last.name[nd.last.len]) {
-		__putname(nd.last.name);
-		goto exit;
-	}
-	error = -ELOOP;
-	if (count++==32) {
-		__putname(nd.last.name);
-		goto exit;
-	}
-	dir = nd.path.dentry;
-	mutex_lock(&dir->d_inode->i_mutex);
-	path.dentry = lookup_hash(&nd);
-	path.mnt = nd.path.mnt;
-	__putname(nd.last.name);
-	goto do_last;
+	filp = ERR_PTR(error);
+	goto out;
 }
 
 /**
@@ -1996,7 +1981,6 @@
 	if (error)
 		return error;
 
-	vfs_dq_init(dir);
 	error = dir->i_op->mknod(dir, dentry, mode, dev);
 	if (!error)
 		fsnotify_create(dir, dentry);
@@ -2095,7 +2079,6 @@
 	if (error)
 		return error;
 
-	vfs_dq_init(dir);
 	error = dir->i_op->mkdir(dir, dentry, mode);
 	if (!error)
 		fsnotify_mkdir(dir, dentry);
@@ -2181,8 +2164,6 @@
 	if (!dir->i_op->rmdir)
 		return -EPERM;
 
-	vfs_dq_init(dir);
-
 	mutex_lock(&dentry->d_inode->i_mutex);
 	dentry_unhash(dentry);
 	if (d_mountpoint(dentry))
@@ -2268,15 +2249,16 @@
 	if (!dir->i_op->unlink)
 		return -EPERM;
 
-	vfs_dq_init(dir);
-
 	mutex_lock(&dentry->d_inode->i_mutex);
 	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
 		error = security_inode_unlink(dir, dentry);
-		if (!error)
+		if (!error) {
 			error = dir->i_op->unlink(dir, dentry);
+			if (!error)
+				dentry->d_inode->i_flags |= S_DEAD;
+		}
 	}
 	mutex_unlock(&dentry->d_inode->i_mutex);
 
@@ -2379,7 +2361,6 @@
 	if (error)
 		return error;
 
-	vfs_dq_init(dir);
 	error = dir->i_op->symlink(dir, dentry, oldname);
 	if (!error)
 		fsnotify_create(dir, dentry);
@@ -2463,7 +2444,6 @@
 		return error;
 
 	mutex_lock(&inode->i_mutex);
-	vfs_dq_init(dir);
 	error = dir->i_op->link(old_dentry, dir, new_dentry);
 	mutex_unlock(&inode->i_mutex);
 	if (!error)
@@ -2564,7 +2544,7 @@
  *	e) conversion from fhandle to dentry may come in the wrong moment - when
  *	   we are removing the target. Solution: we will have to grab ->i_mutex
  *	   in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on
- *	   ->i_mutex on parents, which works but leads to some truely excessive
+ *	   ->i_mutex on parents, which works but leads to some truly excessive
  *	   locking].
  */
 static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
@@ -2629,6 +2609,8 @@
 	else
 		error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
 	if (!error) {
+		if (target)
+			target->i_flags |= S_DEAD;
 		if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
 			d_move(old_dentry, new_dentry);
 	}
@@ -2662,20 +2644,15 @@
 	if (!old_dir->i_op->rename)
 		return -EPERM;
 
-	vfs_dq_init(old_dir);
-	vfs_dq_init(new_dir);
-
 	old_name = fsnotify_oldname_init(old_dentry->d_name.name);
 
 	if (is_dir)
 		error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
 	else
 		error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-	if (!error) {
-		const char *new_name = old_dentry->d_name.name;
-		fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
+	if (!error)
+		fsnotify_move(old_dir, new_dir, old_name, is_dir,
 			      new_dentry->d_inode, old_dentry);
-	}
 	fsnotify_oldname_free(old_name);
 
 	return error;
diff --git a/fs/namespace.c b/fs/namespace.c
index c768f73..8174c8a 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -573,7 +573,7 @@
 			mnt->mnt_master = old;
 			CLEAR_MNT_SHARED(mnt);
 		} else if (!(flag & CL_PRIVATE)) {
-			if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old))
+			if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old))
 				list_add(&mnt->mnt_share, &old->mnt_share);
 			if (IS_MNT_SLAVE(old))
 				list_add(&mnt->mnt_slave, &old->mnt_slave);
@@ -737,6 +737,21 @@
 	up_read(&namespace_sem);
 }
 
+int mnt_had_events(struct proc_mounts *p)
+{
+	struct mnt_namespace *ns = p->ns;
+	int res = 0;
+
+	spin_lock(&vfsmount_lock);
+	if (p->event != ns->event) {
+		p->event = ns->event;
+		res = 1;
+	}
+	spin_unlock(&vfsmount_lock);
+
+	return res;
+}
+
 struct proc_fs_info {
 	int flag;
 	const char *str;
@@ -1121,8 +1136,15 @@
 {
 	struct path path;
 	int retval;
+	int lookup_flags = 0;
 
-	retval = user_path(name, &path);
+	if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
+		return -EINVAL;
+
+	if (!(flags & UMOUNT_NOFOLLOW))
+		lookup_flags |= LOOKUP_FOLLOW;
+
+	retval = user_path_at(AT_FDCWD, name, lookup_flags, &path);
 	if (retval)
 		goto out;
 	retval = -EINVAL;
@@ -1246,6 +1268,21 @@
 	release_mounts(&umount_list);
 }
 
+int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
+		   struct vfsmount *root)
+{
+	struct vfsmount *mnt;
+	int res = f(root, arg);
+	if (res)
+		return res;
+	list_for_each_entry(mnt, &root->mnt_list, mnt_list) {
+		res = f(mnt, arg);
+		if (res)
+			return res;
+	}
+	return 0;
+}
+
 static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
 {
 	struct vfsmount *p;
@@ -1538,7 +1575,7 @@
 		err = do_remount_sb(sb, flags, data, 0);
 	if (!err) {
 		spin_lock(&vfsmount_lock);
-		mnt_flags |= path->mnt->mnt_flags & MNT_PNODE_MASK;
+		mnt_flags |= path->mnt->mnt_flags & MNT_PROPAGATION_MASK;
 		path->mnt->mnt_flags = mnt_flags;
 		spin_unlock(&vfsmount_lock);
 	}
@@ -1671,7 +1708,7 @@
 {
 	int err;
 
-	mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD);
+	mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
 
 	down_write(&namespace_sem);
 	/* Something was mounted here while we slept */
@@ -2314,17 +2351,13 @@
 
 void put_mnt_ns(struct mnt_namespace *ns)
 {
-	struct vfsmount *root;
 	LIST_HEAD(umount_list);
 
-	if (!atomic_dec_and_lock(&ns->count, &vfsmount_lock))
+	if (!atomic_dec_and_test(&ns->count))
 		return;
-	root = ns->root;
-	ns->root = NULL;
-	spin_unlock(&vfsmount_lock);
 	down_write(&namespace_sem);
 	spin_lock(&vfsmount_lock);
-	umount_tree(root, 0, &umount_list);
+	umount_tree(ns->root, 0, &umount_list);
 	spin_unlock(&vfsmount_lock);
 	up_write(&namespace_sem);
 	release_mounts(&umount_list);
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 73ab220..36dfdae 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -118,7 +118,6 @@
 	dprintk("NFS: Callback listener port = %u (af %u)\n",
 			nfs_callback_tcpport, PF_INET);
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	ret = svc_create_xprt(serv, "tcp", PF_INET6,
 				nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
 	if (ret > 0) {
@@ -129,7 +128,6 @@
 		ret = 0;
 	else
 		goto out_err;
-#endif	/* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
 
 	return svc_prepare_thread(serv, &serv->sv_pools[0]);
 
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index d4036be..85a7cfd 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -119,6 +119,14 @@
 };
 
 extern unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy);
+
+struct cb_recallslotargs {
+	struct sockaddr	*crsa_addr;
+	uint32_t	crsa_target_max_slots;
+};
+extern unsigned nfs4_callback_recallslot(struct cb_recallslotargs *args,
+					  void *dummy);
+
 #endif /* CONFIG_NFS_V4_1 */
 
 extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index defa9b4..84761b5 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -143,44 +143,49 @@
  * Return success if the sequenceID is one more than what we last saw on
  * this slot, accounting for wraparound.  Increments the slot's sequence.
  *
- * We don't yet implement a duplicate request cache, so at this time
- * we will log replays, and process them as if we had not seen them before,
- * but we don't bump the sequence in the slot.  Not too worried about it,
+ * We don't yet implement a duplicate request cache, instead we set the
+ * back channel ca_maxresponsesize_cached to zero. This is OK for now
  * since we only currently implement idempotent callbacks anyway.
  *
  * We have a single slot backchannel at this time, so we don't bother
  * checking the used_slots bit array on the table.  The lower layer guarantees
  * a single outstanding callback request at a time.
  */
-static int
-validate_seqid(struct nfs4_slot_table *tbl, u32 slotid, u32 seqid)
+static __be32
+validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
 {
 	struct nfs4_slot *slot;
 
 	dprintk("%s enter. slotid %d seqid %d\n",
-		__func__, slotid, seqid);
+		__func__, args->csa_slotid, args->csa_sequenceid);
 
-	if (slotid > NFS41_BC_MAX_CALLBACKS)
+	if (args->csa_slotid > NFS41_BC_MAX_CALLBACKS)
 		return htonl(NFS4ERR_BADSLOT);
 
-	slot = tbl->slots + slotid;
+	slot = tbl->slots + args->csa_slotid;
 	dprintk("%s slot table seqid: %d\n", __func__, slot->seq_nr);
 
 	/* Normal */
-	if (likely(seqid == slot->seq_nr + 1)) {
+	if (likely(args->csa_sequenceid == slot->seq_nr + 1)) {
 		slot->seq_nr++;
 		return htonl(NFS4_OK);
 	}
 
 	/* Replay */
-	if (seqid == slot->seq_nr) {
-		dprintk("%s seqid %d is a replay - no DRC available\n",
-			__func__, seqid);
-		return htonl(NFS4_OK);
+	if (args->csa_sequenceid == slot->seq_nr) {
+		dprintk("%s seqid %d is a replay\n",
+			__func__, args->csa_sequenceid);
+		/* Signal process_op to set this error on next op */
+		if (args->csa_cachethis == 0)
+			return htonl(NFS4ERR_RETRY_UNCACHED_REP);
+
+		/* The ca_maxresponsesize_cached is 0 with no DRC */
+		else if (args->csa_cachethis == 1)
+			return htonl(NFS4ERR_REP_TOO_BIG_TO_CACHE);
 	}
 
 	/* Wraparound */
-	if (seqid == 1 && (slot->seq_nr + 1) == 0) {
+	if (args->csa_sequenceid == 1 && (slot->seq_nr + 1) == 0) {
 		slot->seq_nr = 1;
 		return htonl(NFS4_OK);
 	}
@@ -225,27 +230,87 @@
 	return NULL;
 }
 
-/* FIXME: referring calls should be processed */
-unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
+/*
+ * For each referring call triple, check the session's slot table for
+ * a match.  If the slot is in use and the sequence numbers match, the
+ * client is still waiting for a response to the original request.
+ */
+static bool referring_call_exists(struct nfs_client *clp,
+				  uint32_t nrclists,
+				  struct referring_call_list *rclists)
+{
+	bool status = 0;
+	int i, j;
+	struct nfs4_session *session;
+	struct nfs4_slot_table *tbl;
+	struct referring_call_list *rclist;
+	struct referring_call *ref;
+
+	/*
+	 * XXX When client trunking is implemented, this becomes
+	 * a session lookup from within the loop
+	 */
+	session = clp->cl_session;
+	tbl = &session->fc_slot_table;
+
+	for (i = 0; i < nrclists; i++) {
+		rclist = &rclists[i];
+		if (memcmp(session->sess_id.data,
+			   rclist->rcl_sessionid.data,
+			   NFS4_MAX_SESSIONID_LEN) != 0)
+			continue;
+
+		for (j = 0; j < rclist->rcl_nrefcalls; j++) {
+			ref = &rclist->rcl_refcalls[j];
+
+			dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u "
+				"slotid %u\n", __func__,
+				((u32 *)&rclist->rcl_sessionid.data)[0],
+				((u32 *)&rclist->rcl_sessionid.data)[1],
+				((u32 *)&rclist->rcl_sessionid.data)[2],
+				((u32 *)&rclist->rcl_sessionid.data)[3],
+				ref->rc_sequenceid, ref->rc_slotid);
+
+			spin_lock(&tbl->slot_tbl_lock);
+			status = (test_bit(ref->rc_slotid, tbl->used_slots) &&
+				  tbl->slots[ref->rc_slotid].seq_nr ==
+					ref->rc_sequenceid);
+			spin_unlock(&tbl->slot_tbl_lock);
+			if (status)
+				goto out;
+		}
+	}
+
+out:
+	return status;
+}
+
+__be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
 				struct cb_sequenceres *res)
 {
 	struct nfs_client *clp;
-	int i, status;
-
-	for (i = 0; i < args->csa_nrclists; i++)
-		kfree(args->csa_rclists[i].rcl_refcalls);
-	kfree(args->csa_rclists);
+	int i;
+	__be32 status;
 
 	status = htonl(NFS4ERR_BADSESSION);
 	clp = find_client_with_session(args->csa_addr, 4, &args->csa_sessionid);
 	if (clp == NULL)
 		goto out;
 
-	status = validate_seqid(&clp->cl_session->bc_slot_table,
-				args->csa_slotid, args->csa_sequenceid);
+	status = validate_seqid(&clp->cl_session->bc_slot_table, args);
 	if (status)
 		goto out_putclient;
 
+	/*
+	 * Check for pending referring calls.  If a match is found, a
+	 * related callback was received before the response to the original
+	 * call.
+	 */
+	if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists)) {
+		status = htonl(NFS4ERR_DELAY);
+		goto out_putclient;
+	}
+
 	memcpy(&res->csr_sessionid, &args->csa_sessionid,
 	       sizeof(res->csr_sessionid));
 	res->csr_sequenceid = args->csa_sequenceid;
@@ -256,15 +321,23 @@
 out_putclient:
 	nfs_put_client(clp);
 out:
-	dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
-	res->csr_status = status;
-	return res->csr_status;
+	for (i = 0; i < args->csa_nrclists; i++)
+		kfree(args->csa_rclists[i].rcl_refcalls);
+	kfree(args->csa_rclists);
+
+	if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP))
+		res->csr_status = 0;
+	else
+		res->csr_status = status;
+	dprintk("%s: exit with status = %d res->csr_status %d\n", __func__,
+		ntohl(status), ntohl(res->csr_status));
+	return status;
 }
 
-unsigned nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy)
+__be32 nfs4_callback_recallany(struct cb_recallanyargs *args, void *dummy)
 {
 	struct nfs_client *clp;
-	int status;
+	__be32 status;
 	fmode_t flags = 0;
 
 	status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
@@ -289,4 +362,40 @@
 	dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
 	return status;
 }
+
+/* Reduce the fore channel's max_slots to the target value */
+__be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy)
+{
+	struct nfs_client *clp;
+	struct nfs4_slot_table *fc_tbl;
+	__be32 status;
+
+	status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
+	clp = nfs_find_client(args->crsa_addr, 4);
+	if (clp == NULL)
+		goto out;
+
+	dprintk("NFS: CB_RECALL_SLOT request from %s target max slots %d\n",
+		rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR),
+		args->crsa_target_max_slots);
+
+	fc_tbl = &clp->cl_session->fc_slot_table;
+
+	status = htonl(NFS4ERR_BAD_HIGH_SLOT);
+	if (args->crsa_target_max_slots > fc_tbl->max_slots ||
+	    args->crsa_target_max_slots < 1)
+		goto out_putclient;
+
+	status = htonl(NFS4_OK);
+	if (args->crsa_target_max_slots == fc_tbl->max_slots)
+		goto out_putclient;
+
+	fc_tbl->target_max_slots = args->crsa_target_max_slots;
+	nfs41_handle_recall_slot(clp);
+out_putclient:
+	nfs_put_client(clp);	/* balance nfs_find_client */
+out:
+	dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
+	return status;
+}
 #endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 8e1a251..db30c0b 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -24,10 +24,14 @@
 #define CB_OP_SEQUENCE_RES_MAXSZ	(CB_OP_HDR_RES_MAXSZ + \
 					4 + 1 + 3)
 #define CB_OP_RECALLANY_RES_MAXSZ	(CB_OP_HDR_RES_MAXSZ)
+#define CB_OP_RECALLSLOT_RES_MAXSZ	(CB_OP_HDR_RES_MAXSZ)
 #endif /* CONFIG_NFS_V4_1 */
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
 
+/* Internal error code */
+#define NFS4ERR_RESOURCE_HDR	11050
+
 typedef __be32 (*callback_process_op_t)(void *, void *);
 typedef __be32 (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *);
 typedef __be32 (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *);
@@ -173,7 +177,7 @@
 	__be32 *p;
 	p = read_buf(xdr, 4);
 	if (unlikely(p == NULL))
-		return htonl(NFS4ERR_RESOURCE);
+		return htonl(NFS4ERR_RESOURCE_HDR);
 	*op = ntohl(*p);
 	return 0;
 }
@@ -215,10 +219,10 @@
 
 #if defined(CONFIG_NFS_V4_1)
 
-static unsigned decode_sessionid(struct xdr_stream *xdr,
+static __be32 decode_sessionid(struct xdr_stream *xdr,
 				 struct nfs4_sessionid *sid)
 {
-	uint32_t *p;
+	__be32 *p;
 	int len = NFS4_MAX_SESSIONID_LEN;
 
 	p = read_buf(xdr, len);
@@ -229,12 +233,12 @@
 	return 0;
 }
 
-static unsigned decode_rc_list(struct xdr_stream *xdr,
+static __be32 decode_rc_list(struct xdr_stream *xdr,
 			       struct referring_call_list *rc_list)
 {
-	uint32_t *p;
+	__be32 *p;
 	int i;
-	unsigned status;
+	__be32 status;
 
 	status = decode_sessionid(xdr, &rc_list->rcl_sessionid);
 	if (status)
@@ -267,13 +271,13 @@
 	return status;
 }
 
-static unsigned decode_cb_sequence_args(struct svc_rqst *rqstp,
+static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
 					struct xdr_stream *xdr,
 					struct cb_sequenceargs *args)
 {
-	uint32_t *p;
+	__be32 *p;
 	int i;
-	unsigned status;
+	__be32 status;
 
 	status = decode_sessionid(xdr, &args->csa_sessionid);
 	if (status)
@@ -327,11 +331,11 @@
 	goto out;
 }
 
-static unsigned decode_recallany_args(struct svc_rqst *rqstp,
+static __be32 decode_recallany_args(struct svc_rqst *rqstp,
 				      struct xdr_stream *xdr,
 				      struct cb_recallanyargs *args)
 {
-	uint32_t *p;
+	__be32 *p;
 
 	args->craa_addr = svc_addr(rqstp);
 	p = read_buf(xdr, 4);
@@ -346,6 +350,20 @@
 	return 0;
 }
 
+static __be32 decode_recallslot_args(struct svc_rqst *rqstp,
+					struct xdr_stream *xdr,
+					struct cb_recallslotargs *args)
+{
+	__be32 *p;
+
+	args->crsa_addr = svc_addr(rqstp);
+	p = read_buf(xdr, 4);
+	if (unlikely(p == NULL))
+		return htonl(NFS4ERR_BADXDR);
+	args->crsa_target_max_slots = ntohl(*p++);
+	return 0;
+}
+
 #endif /* CONFIG_NFS_V4_1 */
 
 static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
@@ -465,7 +483,7 @@
 	
 	p = xdr_reserve_space(xdr, 8);
 	if (unlikely(p == NULL))
-		return htonl(NFS4ERR_RESOURCE);
+		return htonl(NFS4ERR_RESOURCE_HDR);
 	*p++ = htonl(op);
 	*p = res;
 	return 0;
@@ -499,10 +517,10 @@
 
 #if defined(CONFIG_NFS_V4_1)
 
-static unsigned encode_sessionid(struct xdr_stream *xdr,
+static __be32 encode_sessionid(struct xdr_stream *xdr,
 				 const struct nfs4_sessionid *sid)
 {
-	uint32_t *p;
+	__be32 *p;
 	int len = NFS4_MAX_SESSIONID_LEN;
 
 	p = xdr_reserve_space(xdr, len);
@@ -513,11 +531,11 @@
 	return 0;
 }
 
-static unsigned encode_cb_sequence_res(struct svc_rqst *rqstp,
+static __be32 encode_cb_sequence_res(struct svc_rqst *rqstp,
 				       struct xdr_stream *xdr,
 				       const struct cb_sequenceres *res)
 {
-	uint32_t *p;
+	__be32 *p;
 	unsigned status = res->csr_status;
 
 	if (unlikely(status != 0))
@@ -554,6 +572,7 @@
 	case OP_CB_RECALL:
 	case OP_CB_SEQUENCE:
 	case OP_CB_RECALL_ANY:
+	case OP_CB_RECALL_SLOT:
 		*op = &callback_ops[op_nr];
 		break;
 
@@ -562,7 +581,6 @@
 	case OP_CB_NOTIFY:
 	case OP_CB_PUSH_DELEG:
 	case OP_CB_RECALLABLE_OBJ_AVAIL:
-	case OP_CB_RECALL_SLOT:
 	case OP_CB_WANTS_CANCELLED:
 	case OP_CB_NOTIFY_LOCK:
 		return htonl(NFS4ERR_NOTSUPP);
@@ -602,20 +620,18 @@
 static __be32 process_op(uint32_t minorversion, int nop,
 		struct svc_rqst *rqstp,
 		struct xdr_stream *xdr_in, void *argp,
-		struct xdr_stream *xdr_out, void *resp)
+		struct xdr_stream *xdr_out, void *resp, int* drc_status)
 {
 	struct callback_op *op = &callback_ops[0];
-	unsigned int op_nr = OP_CB_ILLEGAL;
+	unsigned int op_nr;
 	__be32 status;
 	long maxlen;
 	__be32 res;
 
 	dprintk("%s: start\n", __func__);
 	status = decode_op_hdr(xdr_in, &op_nr);
-	if (unlikely(status)) {
-		status = htonl(NFS4ERR_OP_ILLEGAL);
-		goto out;
-	}
+	if (unlikely(status))
+		return status;
 
 	dprintk("%s: minorversion=%d nop=%d op_nr=%u\n",
 		__func__, minorversion, nop, op_nr);
@@ -624,19 +640,32 @@
 				preprocess_nfs4_op(op_nr, &op);
 	if (status == htonl(NFS4ERR_OP_ILLEGAL))
 		op_nr = OP_CB_ILLEGAL;
-out:
+	if (status)
+		goto encode_hdr;
+
+	if (*drc_status) {
+		status = *drc_status;
+		goto encode_hdr;
+	}
+
 	maxlen = xdr_out->end - xdr_out->p;
 	if (maxlen > 0 && maxlen < PAGE_SIZE) {
-		if (likely(status == 0 && op->decode_args != NULL))
-			status = op->decode_args(rqstp, xdr_in, argp);
-		if (likely(status == 0 && op->process_op != NULL))
+		status = op->decode_args(rqstp, xdr_in, argp);
+		if (likely(status == 0))
 			status = op->process_op(argp, resp);
 	} else
 		status = htonl(NFS4ERR_RESOURCE);
 
+	/* Only set by OP_CB_SEQUENCE processing */
+	if (status == htonl(NFS4ERR_RETRY_UNCACHED_REP)) {
+		*drc_status = status;
+		status = 0;
+	}
+
+encode_hdr:
 	res = encode_op_hdr(xdr_out, op_nr, status);
-	if (status == 0)
-		status = res;
+	if (unlikely(res))
+		return res;
 	if (op->encode_res != NULL && status == 0)
 		status = op->encode_res(rqstp, xdr_out, resp);
 	dprintk("%s: done, status = %d\n", __func__, ntohl(status));
@@ -652,7 +681,7 @@
 	struct cb_compound_hdr_res hdr_res = { NULL };
 	struct xdr_stream xdr_in, xdr_out;
 	__be32 *p;
-	__be32 status;
+	__be32 status, drc_status = 0;
 	unsigned int nops = 0;
 
 	dprintk("%s: start\n", __func__);
@@ -672,11 +701,18 @@
 		return rpc_system_err;
 
 	while (status == 0 && nops != hdr_arg.nops) {
-		status = process_op(hdr_arg.minorversion, nops,
-				    rqstp, &xdr_in, argp, &xdr_out, resp);
+		status = process_op(hdr_arg.minorversion, nops, rqstp,
+				    &xdr_in, argp, &xdr_out, resp, &drc_status);
 		nops++;
 	}
 
+	/* Buffer overflow in decode_ops_hdr or encode_ops_hdr. Return
+	* resource error in cb_compound status without returning op */
+	if (unlikely(status == htonl(NFS4ERR_RESOURCE_HDR))) {
+		status = htonl(NFS4ERR_RESOURCE);
+		nops--;
+	}
+
 	*hdr_res.status = status;
 	*hdr_res.nops = htonl(nops);
 	dprintk("%s: done, status = %u\n", __func__, ntohl(status));
@@ -713,6 +749,11 @@
 		.decode_args = (callback_decode_arg_t)decode_recallany_args,
 		.res_maxsize = CB_OP_RECALLANY_RES_MAXSZ,
 	},
+	[OP_CB_RECALL_SLOT] = {
+		.process_op = (callback_process_op_t)nfs4_callback_recallslot,
+		.decode_args = (callback_decode_arg_t)decode_recallslot_args,
+		.res_maxsize = CB_OP_RECALLSLOT_RES_MAXSZ,
+	},
 #endif /* CONFIG_NFS_V4_1 */
 };
 
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index ee77713..2274f17 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -164,30 +164,7 @@
 	return ERR_PTR(err);
 }
 
-static void nfs4_shutdown_client(struct nfs_client *clp)
-{
 #ifdef CONFIG_NFS_V4
-	if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
-		nfs4_kill_renewd(clp);
-	BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
-	if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
-		nfs_idmap_delete(clp);
-
-	rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
-#endif
-}
-
-/*
- * Destroy the NFS4 callback service
- */
-static void nfs4_destroy_callback(struct nfs_client *clp)
-{
-#ifdef CONFIG_NFS_V4
-	if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
-		nfs_callback_down(clp->cl_minorversion);
-#endif /* CONFIG_NFS_V4 */
-}
-
 /*
  * Clears/puts all minor version specific parts from an nfs_client struct
  * reverting it to minorversion 0.
@@ -202,18 +179,41 @@
 
 	clp->cl_call_sync = _nfs4_call_sync;
 #endif /* CONFIG_NFS_V4_1 */
-
-	nfs4_destroy_callback(clp);
 }
 
 /*
+ * Destroy the NFS4 callback service
+ */
+static void nfs4_destroy_callback(struct nfs_client *clp)
+{
+	if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
+		nfs_callback_down(clp->cl_minorversion);
+}
+
+static void nfs4_shutdown_client(struct nfs_client *clp)
+{
+	if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
+		nfs4_kill_renewd(clp);
+	nfs4_clear_client_minor_version(clp);
+	nfs4_destroy_callback(clp);
+	if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+		nfs_idmap_delete(clp);
+
+	rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
+}
+#else
+static void nfs4_shutdown_client(struct nfs_client *clp)
+{
+}
+#endif /* CONFIG_NFS_V4 */
+
+/*
  * Destroy a shared client record
  */
 static void nfs_free_client(struct nfs_client *clp)
 {
 	dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
 
-	nfs4_clear_client_minor_version(clp);
 	nfs4_shutdown_client(clp);
 
 	nfs_fscache_release_client_cookie(clp);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 3c7f03b..a1f6b44 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -560,7 +560,7 @@
 	desc->entry = &my_entry;
 
 	nfs_block_sillyrename(dentry);
-	res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping);
+	res = nfs_revalidate_mapping(inode, filp->f_mapping);
 	if (res < 0)
 		goto out;
 
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index 95e1ca7..3f0cd4d 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -36,6 +36,19 @@
 };
 
 
+static void nfs_dns_ent_update(struct cache_head *cnew,
+		struct cache_head *ckey)
+{
+	struct nfs_dns_ent *new;
+	struct nfs_dns_ent *key;
+
+	new = container_of(cnew, struct nfs_dns_ent, h);
+	key = container_of(ckey, struct nfs_dns_ent, h);
+
+	memcpy(&new->addr, &key->addr, key->addrlen);
+	new->addrlen = key->addrlen;
+}
+
 static void nfs_dns_ent_init(struct cache_head *cnew,
 		struct cache_head *ckey)
 {
@@ -49,8 +62,7 @@
 	new->hostname = kstrndup(key->hostname, key->namelen, GFP_KERNEL);
 	if (new->hostname) {
 		new->namelen = key->namelen;
-		memcpy(&new->addr, &key->addr, key->addrlen);
-		new->addrlen = key->addrlen;
+		nfs_dns_ent_update(cnew, ckey);
 	} else {
 		new->namelen = 0;
 		new->addrlen = 0;
@@ -234,7 +246,7 @@
 	.cache_show = nfs_dns_show,
 	.match = nfs_dns_match,
 	.init = nfs_dns_ent_init,
-	.update = nfs_dns_ent_init,
+	.update = nfs_dns_ent_update,
 	.alloc = nfs_dns_ent_alloc,
 };
 
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 63f2071..ae8d022 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -123,11 +123,11 @@
 			filp->f_path.dentry->d_parent->d_name.name,
 			filp->f_path.dentry->d_name.name);
 
+	nfs_inc_stats(inode, NFSIOS_VFSOPEN);
 	res = nfs_check_flags(filp->f_flags);
 	if (res)
 		return res;
 
-	nfs_inc_stats(inode, NFSIOS_VFSOPEN);
 	res = nfs_open(inode, filp);
 	return res;
 }
@@ -237,9 +237,9 @@
 			dentry->d_parent->d_name.name,
 			dentry->d_name.name);
 
+	nfs_inc_stats(inode, NFSIOS_VFSFLUSH);
 	if ((file->f_mode & FMODE_WRITE) == 0)
 		return 0;
-	nfs_inc_stats(inode, NFSIOS_VFSFLUSH);
 
 	/* Flush writes to the server and return any errors */
 	return nfs_do_fsync(ctx, inode);
@@ -262,9 +262,11 @@
 		(unsigned long) count, (unsigned long) pos);
 
 	result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
-	nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count);
-	if (!result)
+	if (!result) {
 		result = generic_file_aio_read(iocb, iov, nr_segs, pos);
+		if (result > 0)
+			nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, result);
+	}
 	return result;
 }
 
@@ -282,8 +284,11 @@
 		(unsigned long) count, (unsigned long long) *ppos);
 
 	res = nfs_revalidate_mapping(inode, filp->f_mapping);
-	if (!res)
+	if (!res) {
 		res = generic_file_splice_read(filp, ppos, pipe, count, flags);
+		if (res > 0)
+			nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, res);
+	}
 	return res;
 }
 
@@ -596,6 +601,7 @@
 {
 	struct dentry * dentry = iocb->ki_filp->f_path.dentry;
 	struct inode * inode = dentry->d_inode;
+	unsigned long written = 0;
 	ssize_t result;
 	size_t count = iov_length(iov, nr_segs);
 
@@ -622,14 +628,18 @@
 	if (!count)
 		goto out;
 
-	nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
 	result = generic_file_aio_write(iocb, iov, nr_segs, pos);
+	if (result > 0)
+		written = result;
+
 	/* Return error values for O_DSYNC and IS_SYNC() */
 	if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) {
 		int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode);
 		if (err < 0)
 			result = err;
 	}
+	if (result > 0)
+		nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written);
 out:
 	return result;
 
@@ -644,6 +654,7 @@
 {
 	struct dentry *dentry = filp->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
+	unsigned long written = 0;
 	ssize_t ret;
 
 	dprintk("NFS splice_write(%s/%s, %lu@%llu)\n",
@@ -654,14 +665,17 @@
 	 * The combination of splice and an O_APPEND destination is disallowed.
 	 */
 
-	nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
-
 	ret = generic_file_splice_write(pipe, filp, ppos, count, flags);
+	if (ret > 0)
+		written = ret;
+
 	if (ret >= 0 && nfs_need_sync_write(filp, inode)) {
 		int err = nfs_do_fsync(nfs_file_open_context(filp), inode);
 		if (err < 0)
 			ret = err;
 	}
+	if (ret > 0)
+		nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written);
 	return ret;
 }
 
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f141bde..657201a 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -97,22 +97,6 @@
 	return ino;
 }
 
-int nfs_write_inode(struct inode *inode, int sync)
-{
-	int ret;
-
-	if (sync) {
-		ret = filemap_fdatawait(inode->i_mapping);
-		if (ret == 0)
-			ret = nfs_commit_inode(inode, FLUSH_SYNC);
-	} else
-		ret = nfs_commit_inode(inode, 0);
-	if (ret >= 0)
-		return 0;
-	__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
-	return ret;
-}
-
 void nfs_clear_inode(struct inode *inode)
 {
 	/*
@@ -130,16 +114,12 @@
  */
 int nfs_sync_mapping(struct address_space *mapping)
 {
-	int ret;
+	int ret = 0;
 
-	if (mapping->nrpages == 0)
-		return 0;
-	unmap_mapping_range(mapping, 0, 0, 0);
-	ret = filemap_write_and_wait(mapping);
-	if (ret != 0)
-		goto out;
-	ret = nfs_wb_all(mapping->host);
-out:
+	if (mapping->nrpages != 0) {
+		unmap_mapping_range(mapping, 0, 0, 0);
+		ret = nfs_wb_all(mapping->host);
+	}
 	return ret;
 }
 
@@ -511,17 +491,11 @@
 	int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
 	int err;
 
-	/*
-	 * Flush out writes to the server in order to update c/mtime.
-	 *
-	 * Hold the i_mutex to suspend application writes temporarily;
-	 * this prevents long-running writing applications from blocking
-	 * nfs_wb_nocommit.
-	 */
+	/* Flush out writes to the server in order to update c/mtime.  */
 	if (S_ISREG(inode->i_mode)) {
-		mutex_lock(&inode->i_mutex);
-		nfs_wb_nocommit(inode);
-		mutex_unlock(&inode->i_mutex);
+		err = filemap_write_and_wait(inode->i_mapping);
+		if (err)
+			goto out;
 	}
 
 	/*
@@ -545,6 +519,7 @@
 		generic_fillattr(inode, stat);
 		stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode));
 	}
+out:
 	return err;
 }
 
@@ -574,14 +549,14 @@
 	nfs_revalidate_inode(server, inode);
 }
 
-static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred)
+static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred)
 {
 	struct nfs_open_context *ctx;
 
 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
 	if (ctx != NULL) {
-		ctx->path.dentry = dget(dentry);
-		ctx->path.mnt = mntget(mnt);
+		ctx->path = *path;
+		path_get(&ctx->path);
 		ctx->cred = get_rpccred(cred);
 		ctx->state = NULL;
 		ctx->lockowner = current->files;
@@ -620,11 +595,6 @@
 	__put_nfs_open_context(ctx, 0);
 }
 
-static void put_nfs_open_context_sync(struct nfs_open_context *ctx)
-{
-	__put_nfs_open_context(ctx, 1);
-}
-
 /*
  * Ensure that mmap has a recent RPC credential for use when writing out
  * shared pages
@@ -671,7 +641,7 @@
 		spin_lock(&inode->i_lock);
 		list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
 		spin_unlock(&inode->i_lock);
-		put_nfs_open_context_sync(ctx);
+		__put_nfs_open_context(ctx, filp->f_flags & O_DIRECT ? 0 : 1);
 	}
 }
 
@@ -686,7 +656,7 @@
 	cred = rpc_lookup_cred();
 	if (IS_ERR(cred))
 		return PTR_ERR(cred);
-	ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
+	ctx = alloc_nfs_open_context(&filp->f_path, cred);
 	put_rpccred(cred);
 	if (ctx == NULL)
 		return -ENOMEM;
@@ -779,7 +749,7 @@
 	return __nfs_revalidate_inode(server, inode);
 }
 
-static int nfs_invalidate_mapping_nolock(struct inode *inode, struct address_space *mapping)
+static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	
@@ -800,49 +770,10 @@
 	return 0;
 }
 
-static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping)
-{
-	int ret = 0;
-
-	mutex_lock(&inode->i_mutex);
-	if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_DATA) {
-		ret = nfs_sync_mapping(mapping);
-		if (ret == 0)
-			ret = nfs_invalidate_mapping_nolock(inode, mapping);
-	}
-	mutex_unlock(&inode->i_mutex);
-	return ret;
-}
-
-/**
- * nfs_revalidate_mapping_nolock - Revalidate the pagecache
- * @inode - pointer to host inode
- * @mapping - pointer to mapping
- */
-int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping)
-{
-	struct nfs_inode *nfsi = NFS_I(inode);
-	int ret = 0;
-
-	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
-			|| nfs_attribute_timeout(inode) || NFS_STALE(inode)) {
-		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
-		if (ret < 0)
-			goto out;
-	}
-	if (nfsi->cache_validity & NFS_INO_INVALID_DATA)
-		ret = nfs_invalidate_mapping_nolock(inode, mapping);
-out:
-	return ret;
-}
-
 /**
  * nfs_revalidate_mapping - Revalidate the pagecache
  * @inode - pointer to host inode
  * @mapping - pointer to mapping
- *
- * This version of the function will take the inode->i_mutex and attempt to
- * flush out all dirty data if it needs to invalidate the page cache.
  */
 int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
 {
@@ -1420,6 +1351,7 @@
 	INIT_LIST_HEAD(&nfsi->access_cache_inode_lru);
 	INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
 	nfsi->npages = 0;
+	nfsi->ncommit = 0;
 	atomic_set(&nfsi->silly_count, 1);
 	INIT_HLIST_HEAD(&nfsi->silly_list);
 	init_waitqueue_head(&nfsi->waitqueue);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 29e464d..11f82f0 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -211,7 +211,7 @@
 extern struct workqueue_struct *nfsiod_workqueue;
 extern struct inode *nfs_alloc_inode(struct super_block *sb);
 extern void nfs_destroy_inode(struct inode *);
-extern int nfs_write_inode(struct inode *,int);
+extern int nfs_write_inode(struct inode *, struct writeback_control *);
 extern void nfs_clear_inode(struct inode *);
 #ifdef CONFIG_NFS_V4
 extern void nfs4_clear_inode(struct inode *);
diff --git a/fs/nfs/iostat.h b/fs/nfs/iostat.h
index 46d779a..1d8d5c8 100644
--- a/fs/nfs/iostat.h
+++ b/fs/nfs/iostat.h
@@ -57,12 +57,12 @@
 }
 #endif
 
-static inline struct nfs_iostats *nfs_alloc_iostats(void)
+static inline struct nfs_iostats __percpu *nfs_alloc_iostats(void)
 {
 	return alloc_percpu(struct nfs_iostats);
 }
 
-static inline void nfs_free_iostats(struct nfs_iostats *stats)
+static inline void nfs_free_iostats(struct nfs_iostats __percpu *stats)
 {
 	if (stats != NULL)
 		free_percpu(stats);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 3f8881d..24992f0 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -22,14 +22,14 @@
 
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
-/* A wrapper to handle the EJUKEBOX error message */
+/* A wrapper to handle the EJUKEBOX and EKEYEXPIRED error messages */
 static int
 nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 {
 	int res;
 	do {
 		res = rpc_call_sync(clnt, msg, flags);
-		if (res != -EJUKEBOX)
+		if (res != -EJUKEBOX && res != -EKEYEXPIRED)
 			break;
 		schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
 		res = -ERESTARTSYS;
@@ -42,9 +42,10 @@
 static int
 nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode)
 {
-	if (task->tk_status != -EJUKEBOX)
+	if (task->tk_status != -EJUKEBOX && task->tk_status != -EKEYEXPIRED)
 		return 0;
-	nfs_inc_stats(inode, NFSIOS_DELAY);
+	if (task->tk_status == -EJUKEBOX)
+		nfs_inc_stats(inode, NFSIOS_DELAY);
 	task->tk_status = 0;
 	rpc_restart_call(task);
 	rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 0c6fda3..a187200 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -46,6 +46,7 @@
 	NFS4CLNT_DELEGRETURN,
 	NFS4CLNT_SESSION_RESET,
 	NFS4CLNT_SESSION_DRAINING,
+	NFS4CLNT_RECALL_SLOT,
 };
 
 /*
@@ -280,6 +281,7 @@
 extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state);
 extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state);
 extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
+extern void nfs41_handle_recall_slot(struct nfs_client *clp);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
 extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
 extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 375f0fa..eda74c4 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -281,6 +281,7 @@
 			}
 		case -NFS4ERR_GRACE:
 		case -NFS4ERR_DELAY:
+		case -EKEYEXPIRED:
 			ret = nfs4_delay(server->client, &exception->timeout);
 			if (ret != 0)
 				break;
@@ -418,7 +419,8 @@
 			clp->cl_last_renewal = timestamp;
 		spin_unlock(&clp->cl_lock);
 		/* Check sequence flags */
-		nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
+		if (atomic_read(&clp->cl_count) > 1)
+			nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
 	}
 out:
 	/* The session may be reset by one of the error handlers. */
@@ -724,8 +726,8 @@
 	p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
 	if (p->o_arg.seqid == NULL)
 		goto err_free;
-	p->path.mnt = mntget(path->mnt);
-	p->path.dentry = dget(path->dentry);
+	path_get(path);
+	p->path = *path;
 	p->dir = parent;
 	p->owner = sp;
 	atomic_inc(&sp->so_count);
@@ -1163,7 +1165,7 @@
 	int err;
 	do {
 		err = _nfs4_do_open_reclaim(ctx, state);
-		if (err != -NFS4ERR_DELAY)
+		if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
 			break;
 		nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
@@ -1582,6 +1584,7 @@
 			goto out;
 		case -NFS4ERR_GRACE:
 		case -NFS4ERR_DELAY:
+		case -EKEYEXPIRED:
 			nfs4_handle_exception(server, err, &exception);
 			err = 0;
 		}
@@ -1944,8 +1947,8 @@
 	calldata->res.seqid = calldata->arg.seqid;
 	calldata->res.server = server;
 	calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
-	calldata->path.mnt = mntget(path->mnt);
-	calldata->path.dentry = dget(path->dentry);
+	path_get(path);
+	calldata->path = *path;
 
 	msg.rpc_argp = &calldata->arg,
 	msg.rpc_resp = &calldata->res,
@@ -3145,10 +3148,19 @@
  * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
  * standalone procedure for queueing an asynchronous RENEW.
  */
+static void nfs4_renew_release(void *data)
+{
+	struct nfs_client *clp = data;
+
+	if (atomic_read(&clp->cl_count) > 1)
+		nfs4_schedule_state_renewal(clp);
+	nfs_put_client(clp);
+}
+
 static void nfs4_renew_done(struct rpc_task *task, void *data)
 {
-	struct nfs_client *clp = (struct nfs_client *)task->tk_msg.rpc_argp;
-	unsigned long timestamp = (unsigned long)data;
+	struct nfs_client *clp = data;
+	unsigned long timestamp = task->tk_start;
 
 	if (task->tk_status < 0) {
 		/* Unless we're shutting down, schedule state recovery! */
@@ -3164,6 +3176,7 @@
 
 static const struct rpc_call_ops nfs4_renew_ops = {
 	.rpc_call_done = nfs4_renew_done,
+	.rpc_release = nfs4_renew_release,
 };
 
 int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
@@ -3174,8 +3187,10 @@
 		.rpc_cred	= cred,
 	};
 
+	if (!atomic_inc_not_zero(&clp->cl_count))
+		return -EIO;
 	return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
-			&nfs4_renew_ops, (void *)jiffies);
+			&nfs4_renew_ops, clp);
 }
 
 int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
@@ -3452,6 +3467,7 @@
 			if (server)
 				nfs_inc_server_stats(server, NFSIOS_DELAY);
 		case -NFS4ERR_GRACE:
+		case -EKEYEXPIRED:
 			rpc_delay(task, NFS4_POLL_RETRY_MAX);
 			task->tk_status = 0;
 			return -EAGAIN;
@@ -3564,6 +3580,7 @@
 			case -NFS4ERR_RESOURCE:
 				/* The IBM lawyers misread another document! */
 			case -NFS4ERR_DELAY:
+			case -EKEYEXPIRED:
 				err = nfs4_delay(clp->cl_rpcclient, &timeout);
 		}
 	} while (err == 0);
@@ -4179,7 +4196,7 @@
 		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
 			return 0;
 		err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
-		if (err != -NFS4ERR_DELAY)
+		if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
 			break;
 		nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
@@ -4204,6 +4221,7 @@
 			goto out;
 		case -NFS4ERR_GRACE:
 		case -NFS4ERR_DELAY:
+		case -EKEYEXPIRED:
 			nfs4_handle_exception(server, err, &exception);
 			err = 0;
 		}
@@ -4355,6 +4373,7 @@
 				err = 0;
 				goto out;
 			case -NFS4ERR_DELAY:
+			case -EKEYEXPIRED:
 				break;
 		}
 		err = nfs4_handle_exception(server, err, &exception);
@@ -4500,7 +4519,7 @@
 
 		status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
 
-		if (status != NFS4ERR_CLID_INUSE)
+		if (status != -NFS4ERR_CLID_INUSE)
 			break;
 
 		if (signalled())
@@ -4554,6 +4573,7 @@
 	switch (task->tk_status) {
 	case -NFS4ERR_DELAY:
 	case -NFS4ERR_GRACE:
+	case -EKEYEXPIRED:
 		dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
 		rpc_delay(task, NFS4_POLL_RETRY_MIN);
 		task->tk_status = 0;
@@ -4611,26 +4631,32 @@
 /*
  * Reset a slot table
  */
-static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, int max_slots,
-		int old_max_slots, int ivalue)
+static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
+				 int ivalue)
 {
+	struct nfs4_slot *new = NULL;
 	int i;
 	int ret = 0;
 
-	dprintk("--> %s: max_reqs=%u, tbl %p\n", __func__, max_slots, tbl);
+	dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__,
+		max_reqs, tbl->max_slots);
 
-	/*
-	 * Until we have dynamic slot table adjustment, insist
-	 * upon the same slot table size
-	 */
-	if (max_slots != old_max_slots) {
-		dprintk("%s reset slot table does't match old\n",
-			__func__);
-		ret = -EINVAL; /*XXX NFS4ERR_REQ_TOO_BIG ? */
-		goto out;
+	/* Does the newly negotiated max_reqs match the existing slot table? */
+	if (max_reqs != tbl->max_slots) {
+		ret = -ENOMEM;
+		new = kmalloc(max_reqs * sizeof(struct nfs4_slot),
+			      GFP_KERNEL);
+		if (!new)
+			goto out;
+		ret = 0;
+		kfree(tbl->slots);
 	}
 	spin_lock(&tbl->slot_tbl_lock);
-	for (i = 0; i < max_slots; ++i)
+	if (new) {
+		tbl->slots = new;
+		tbl->max_slots = max_reqs;
+	}
+	for (i = 0; i < tbl->max_slots; ++i)
 		tbl->slots[i].seq_nr = ivalue;
 	spin_unlock(&tbl->slot_tbl_lock);
 	dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
@@ -4648,16 +4674,12 @@
 	int status;
 
 	status = nfs4_reset_slot_table(&session->fc_slot_table,
-			session->fc_attrs.max_reqs,
-			session->fc_slot_table.max_slots,
-			1);
+			session->fc_attrs.max_reqs, 1);
 	if (status)
 		return status;
 
 	status = nfs4_reset_slot_table(&session->bc_slot_table,
-			session->bc_attrs.max_reqs,
-			session->bc_slot_table.max_slots,
-			0);
+			session->bc_attrs.max_reqs, 0);
 	return status;
 }
 
@@ -4798,16 +4820,14 @@
 	args->fc_attrs.headerpadsz = 0;
 	args->fc_attrs.max_rqst_sz = mxrqst_sz;
 	args->fc_attrs.max_resp_sz = mxresp_sz;
-	args->fc_attrs.max_resp_sz_cached = mxresp_sz;
 	args->fc_attrs.max_ops = NFS4_MAX_OPS;
 	args->fc_attrs.max_reqs = session->clp->cl_rpcclient->cl_xprt->max_reqs;
 
 	dprintk("%s: Fore Channel : max_rqst_sz=%u max_resp_sz=%u "
-		"max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
+		"max_ops=%u max_reqs=%u\n",
 		__func__,
 		args->fc_attrs.max_rqst_sz, args->fc_attrs.max_resp_sz,
-		args->fc_attrs.max_resp_sz_cached, args->fc_attrs.max_ops,
-		args->fc_attrs.max_reqs);
+		args->fc_attrs.max_ops, args->fc_attrs.max_reqs);
 
 	/* Back channel attributes */
 	args->bc_attrs.headerpadsz = 0;
@@ -5016,7 +5036,16 @@
 				       &res, args.sa_cache_this, 1);
 }
 
-void nfs41_sequence_call_done(struct rpc_task *task, void *data)
+static void nfs41_sequence_release(void *data)
+{
+	struct nfs_client *clp = (struct nfs_client *)data;
+
+	if (atomic_read(&clp->cl_count) > 1)
+		nfs4_schedule_state_renewal(clp);
+	nfs_put_client(clp);
+}
+
+static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
 {
 	struct nfs_client *clp = (struct nfs_client *)data;
 
@@ -5024,6 +5053,8 @@
 
 	if (task->tk_status < 0) {
 		dprintk("%s ERROR %d\n", __func__, task->tk_status);
+		if (atomic_read(&clp->cl_count) == 1)
+			goto out;
 
 		if (_nfs4_async_handle_error(task, NULL, clp, NULL)
 								== -EAGAIN) {
@@ -5032,7 +5063,7 @@
 		}
 	}
 	dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
-
+out:
 	kfree(task->tk_msg.rpc_argp);
 	kfree(task->tk_msg.rpc_resp);
 
@@ -5057,6 +5088,7 @@
 static const struct rpc_call_ops nfs41_sequence_ops = {
 	.rpc_call_done = nfs41_sequence_call_done,
 	.rpc_call_prepare = nfs41_sequence_prepare,
+	.rpc_release = nfs41_sequence_release,
 };
 
 static int nfs41_proc_async_sequence(struct nfs_client *clp,
@@ -5069,12 +5101,13 @@
 		.rpc_cred = cred,
 	};
 
+	if (!atomic_inc_not_zero(&clp->cl_count))
+		return -EIO;
 	args = kzalloc(sizeof(*args), GFP_KERNEL);
-	if (!args)
-		return -ENOMEM;
 	res = kzalloc(sizeof(*res), GFP_KERNEL);
-	if (!res) {
+	if (!args || !res) {
 		kfree(args);
+		nfs_put_client(clp);
 		return -ENOMEM;
 	}
 	res->sr_slotid = NFS4_MAX_SLOT_TABLE;
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 0156c01..d87f103 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -36,11 +36,6 @@
  * as an rpc_task, not a real kernel thread, so it always runs in rpciod's
  * context.  There is one renewd per nfs_server.
  *
- * TODO: If the send queue gets backlogged (e.g., if the server goes down),
- * we will keep filling the queue with periodic RENEW requests.  We need a
- * mechanism for ensuring that if renewd successfully sends off a request,
- * then it only wakes up when the request is finished.  Maybe use the
- * child task framework of the RPC layer?
  */
 
 #include <linux/mm.h>
@@ -63,7 +58,7 @@
 	struct nfs_client *clp =
 		container_of(work, struct nfs_client, cl_renewd.work);
 	struct rpc_cred *cred;
-	long lease, timeout;
+	long lease;
 	unsigned long last, now;
 
 	ops = nfs4_state_renewal_ops[clp->cl_minorversion];
@@ -75,7 +70,6 @@
 	lease = clp->cl_lease_time;
 	last = clp->cl_last_renewal;
 	now = jiffies;
-	timeout = (2 * lease) / 3 + (long)last - (long)now;
 	/* Are we close to a lease timeout? */
 	if (time_after(now, last + lease/3)) {
 		cred = ops->get_state_renewal_cred_locked(clp);
@@ -90,19 +84,15 @@
 			/* Queue an asynchronous RENEW. */
 			ops->sched_state_renewal(clp, cred);
 			put_rpccred(cred);
+			goto out_exp;
 		}
-		timeout = (2 * lease) / 3;
-		spin_lock(&clp->cl_lock);
-	} else
+	} else {
 		dprintk("%s: failed to call renewd. Reason: lease not expired \n",
 				__func__);
-	if (timeout < 5 * HZ)    /* safeguard */
-		timeout = 5 * HZ;
-	dprintk("%s: requeueing work. Lease period = %ld\n",
-			__func__, (timeout + HZ - 1) / HZ);
-	cancel_delayed_work(&clp->cl_renewd);
-	schedule_delayed_work(&clp->cl_renewd, timeout);
-	spin_unlock(&clp->cl_lock);
+		spin_unlock(&clp->cl_lock);
+	}
+	nfs4_schedule_state_renewal(clp);
+out_exp:
 	nfs_expire_unreferenced_delegations(clp);
 out:
 	dprintk("%s: done\n", __func__);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c1e2733..6c5ed51 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1249,26 +1249,65 @@
 }
 
 #ifdef CONFIG_NFS_V4_1
+void nfs41_handle_recall_slot(struct nfs_client *clp)
+{
+	set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
+	nfs4_schedule_state_recovery(clp);
+}
+
+static void nfs4_reset_all_state(struct nfs_client *clp)
+{
+	if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
+		clp->cl_boot_time = CURRENT_TIME;
+		nfs4_state_start_reclaim_nograce(clp);
+		nfs4_schedule_state_recovery(clp);
+	}
+}
+
+static void nfs41_handle_server_reboot(struct nfs_client *clp)
+{
+	if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
+		nfs4_state_start_reclaim_reboot(clp);
+		nfs4_schedule_state_recovery(clp);
+	}
+}
+
+static void nfs41_handle_state_revoked(struct nfs_client *clp)
+{
+	/* Temporary */
+	nfs4_reset_all_state(clp);
+}
+
+static void nfs41_handle_recallable_state_revoked(struct nfs_client *clp)
+{
+	/* This will need to handle layouts too */
+	nfs_expire_all_delegations(clp);
+}
+
+static void nfs41_handle_cb_path_down(struct nfs_client *clp)
+{
+	nfs_expire_all_delegations(clp);
+	if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0)
+		nfs4_schedule_state_recovery(clp);
+}
+
 void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
 {
 	if (!flags)
 		return;
-	else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) {
-		set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-		nfs4_state_start_reclaim_reboot(clp);
-		nfs4_schedule_state_recovery(clp);
-	} else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
+	else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
+		nfs41_handle_server_reboot(clp);
+	else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
 			    SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
 			    SEQ4_STATUS_ADMIN_STATE_REVOKED |
-			    SEQ4_STATUS_RECALLABLE_STATE_REVOKED |
-			    SEQ4_STATUS_LEASE_MOVED)) {
-		set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-		nfs4_state_start_reclaim_nograce(clp);
-		nfs4_schedule_state_recovery(clp);
-	} else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
+			    SEQ4_STATUS_LEASE_MOVED))
+		nfs41_handle_state_revoked(clp);
+	else if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
+		nfs41_handle_recallable_state_revoked(clp);
+	else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
 			    SEQ4_STATUS_BACKCHANNEL_FAULT |
 			    SEQ4_STATUS_CB_PATH_DOWN_SESSION))
-		nfs_expire_all_delegations(clp);
+		nfs41_handle_cb_path_down(clp);
 }
 
 static int nfs4_reset_session(struct nfs_client *clp)
@@ -1285,23 +1324,52 @@
 
 	memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN);
 	status = nfs4_proc_create_session(clp);
-	if (status)
+	if (status) {
 		status = nfs4_recovery_handle_error(clp, status);
+		goto out;
+	}
+	/* create_session negotiated new slot table */
+	clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
 
-out:
-	/*
-	 * Let the state manager reestablish state
-	 */
-	if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
-	    status == 0)
+	 /* Let the state manager reestablish state */
+	if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
 		nfs41_setup_state_renewal(clp);
-
+out:
 	return status;
 }
 
+static int nfs4_recall_slot(struct nfs_client *clp)
+{
+	struct nfs4_slot_table *fc_tbl = &clp->cl_session->fc_slot_table;
+	struct nfs4_channel_attrs *fc_attrs = &clp->cl_session->fc_attrs;
+	struct nfs4_slot *new, *old;
+	int i;
+
+	nfs4_begin_drain_session(clp);
+	new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot),
+		      GFP_KERNEL);
+        if (!new)
+		return -ENOMEM;
+
+	spin_lock(&fc_tbl->slot_tbl_lock);
+	for (i = 0; i < fc_tbl->target_max_slots; i++)
+		new[i].seq_nr = fc_tbl->slots[i].seq_nr;
+	old = fc_tbl->slots;
+	fc_tbl->slots = new;
+	fc_tbl->max_slots = fc_tbl->target_max_slots;
+	fc_tbl->target_max_slots = 0;
+	fc_attrs->max_reqs = fc_tbl->max_slots;
+	spin_unlock(&fc_tbl->slot_tbl_lock);
+
+	kfree(old);
+	nfs4_end_drain_session(clp);
+	return 0;
+}
+
 #else /* CONFIG_NFS_V4_1 */
 static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
 static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; }
+static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
 #endif /* CONFIG_NFS_V4_1 */
 
 /* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors
@@ -1314,6 +1382,7 @@
 		case -NFS4ERR_DELAY:
 		case -NFS4ERR_CLID_INUSE:
 		case -EAGAIN:
+		case -EKEYEXPIRED:
 			break;
 
 		case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
@@ -1397,6 +1466,15 @@
 			nfs_client_return_marked_delegations(clp);
 			continue;
 		}
+		/* Recall session slots */
+		if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)
+		   && nfs4_has_session(clp)) {
+			status = nfs4_recall_slot(clp);
+			if (status < 0)
+				goto out_error;
+			continue;
+		}
+
 
 		nfs4_clear_state_manager_bit(clp);
 		/* Did we race with an attempt to give us more work? */
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 5cd5184..4d338be 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1578,6 +1578,14 @@
 	char machine_name[NFS4_MAX_MACHINE_NAME_LEN];
 	uint32_t len;
 	struct nfs_client *clp = args->client;
+	u32 max_resp_sz_cached;
+
+	/*
+	 * Assumes OPEN is the biggest non-idempotent compound.
+	 * 2 is the verifier.
+	 */
+	max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE +
+			      RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT;
 
 	len = scnprintf(machine_name, sizeof(machine_name), "%s",
 			clp->cl_ipaddr);
@@ -1592,7 +1600,7 @@
 	*p++ = cpu_to_be32(args->fc_attrs.headerpadsz);	/* header padding size */
 	*p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz);	/* max req size */
 	*p++ = cpu_to_be32(args->fc_attrs.max_resp_sz);	/* max resp size */
-	*p++ = cpu_to_be32(args->fc_attrs.max_resp_sz_cached);	/* Max resp sz cached */
+	*p++ = cpu_to_be32(max_resp_sz_cached);		/* Max resp sz cached */
 	*p++ = cpu_to_be32(args->fc_attrs.max_ops);	/* max operations */
 	*p++ = cpu_to_be32(args->fc_attrs.max_reqs);	/* max requests */
 	*p++ = cpu_to_be32(0);				/* rdmachannel_attrs */
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index ef58385..c752d94 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -47,6 +47,39 @@
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
 /*
+ * wrapper to handle the -EKEYEXPIRED error message. This should generally
+ * only happen if using krb5 auth and a user's TGT expires. NFSv2 doesn't
+ * support the NFSERR_JUKEBOX error code, but we handle this situation in the
+ * same way that we handle that error with NFSv3.
+ */
+static int
+nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
+{
+	int res;
+	do {
+		res = rpc_call_sync(clnt, msg, flags);
+		if (res != -EKEYEXPIRED)
+			break;
+		schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
+		res = -ERESTARTSYS;
+	} while (!fatal_signal_pending(current));
+	return res;
+}
+
+#define rpc_call_sync(clnt, msg, flags)	nfs_rpc_wrapper(clnt, msg, flags)
+
+static int
+nfs_async_handle_expired_key(struct rpc_task *task)
+{
+	if (task->tk_status != -EKEYEXPIRED)
+		return 0;
+	task->tk_status = 0;
+	rpc_restart_call(task);
+	rpc_delay(task, NFS_JUKEBOX_RETRY_TIME);
+	return 1;
+}
+
+/*
  * Bare-bones access to getattr: this is for nfs_read_super.
  */
 static int
@@ -307,6 +340,8 @@
 
 static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 {
+	if (nfs_async_handle_expired_key(task))
+		return 0;
 	nfs_mark_for_revalidate(dir);
 	return 1;
 }
@@ -560,6 +595,9 @@
 
 static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
 {
+	if (nfs_async_handle_expired_key(task))
+		return -EAGAIN;
+
 	nfs_invalidate_atime(data->inode);
 	if (task->tk_status >= 0) {
 		nfs_refresh_inode(data->inode, data->res.fattr);
@@ -579,6 +617,9 @@
 
 static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data)
 {
+	if (nfs_async_handle_expired_key(task))
+		return -EAGAIN;
+
 	if (task->tk_status >= 0)
 		nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr);
 	return 0;
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 412738d..2ea9e5c 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -50,7 +50,7 @@
 	struct page *page;
 	void *err;
 
-	err = ERR_PTR(nfs_revalidate_mapping_nolock(inode, inode->i_mapping));
+	err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
 	if (err)
 		goto read_failed;
 	page = read_cache_page(&inode->i_data, 0,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index d63d964..53ff70e 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -438,6 +438,7 @@
 	radix_tree_tag_set(&nfsi->nfs_page_tree,
 			req->wb_index,
 			NFS_PAGE_TAG_COMMIT);
+	nfsi->ncommit++;
 	spin_unlock(&inode->i_lock);
 	inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
 	inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE);
@@ -501,57 +502,6 @@
 }
 #endif
 
-/*
- * Wait for a request to complete.
- *
- * Interruptible by fatal signals only.
- */
-static int nfs_wait_on_requests_locked(struct inode *inode, pgoff_t idx_start, unsigned int npages)
-{
-	struct nfs_inode *nfsi = NFS_I(inode);
-	struct nfs_page *req;
-	pgoff_t idx_end, next;
-	unsigned int		res = 0;
-	int			error;
-
-	if (npages == 0)
-		idx_end = ~0;
-	else
-		idx_end = idx_start + npages - 1;
-
-	next = idx_start;
-	while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_LOCKED)) {
-		if (req->wb_index > idx_end)
-			break;
-
-		next = req->wb_index + 1;
-		BUG_ON(!NFS_WBACK_BUSY(req));
-
-		kref_get(&req->wb_kref);
-		spin_unlock(&inode->i_lock);
-		error = nfs_wait_on_request(req);
-		nfs_release_request(req);
-		spin_lock(&inode->i_lock);
-		if (error < 0)
-			return error;
-		res++;
-	}
-	return res;
-}
-
-static void nfs_cancel_commit_list(struct list_head *head)
-{
-	struct nfs_page *req;
-
-	while(!list_empty(head)) {
-		req = nfs_list_entry(head->next);
-		nfs_list_remove_request(req);
-		nfs_clear_request_commit(req);
-		nfs_inode_remove_request(req);
-		nfs_unlock_request(req);
-	}
-}
-
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
 static int
 nfs_need_commit(struct nfs_inode *nfsi)
@@ -573,11 +523,17 @@
 nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
+	int ret;
 
 	if (!nfs_need_commit(nfsi))
 		return 0;
 
-	return nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT);
+	ret = nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT);
+	if (ret > 0)
+		nfsi->ncommit -= ret;
+	if (nfs_need_commit(NFS_I(inode)))
+		__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+	return ret;
 }
 #else
 static inline int nfs_need_commit(struct nfs_inode *nfsi)
@@ -642,9 +598,10 @@
 		spin_lock(&inode->i_lock);
 	}
 
-	if (nfs_clear_request_commit(req))
-		radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree,
-				req->wb_index, NFS_PAGE_TAG_COMMIT);
+	if (nfs_clear_request_commit(req) &&
+			radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree,
+				req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL)
+		NFS_I(inode)->ncommit--;
 
 	/* Okay, the request matches. Update the region */
 	if (offset < req->wb_offset) {
@@ -1391,7 +1348,7 @@
 	.rpc_release = nfs_commit_release,
 };
 
-int nfs_commit_inode(struct inode *inode, int how)
+static int nfs_commit_inode(struct inode *inode, int how)
 {
 	LIST_HEAD(head);
 	int res;
@@ -1406,92 +1363,51 @@
 	}
 	return res;
 }
+
+static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+	int flags = FLUSH_SYNC;
+	int ret = 0;
+
+	/* Don't commit yet if this is a non-blocking flush and there are
+	 * lots of outstanding writes for this mapping.
+	 */
+	if (wbc->sync_mode == WB_SYNC_NONE &&
+	    nfsi->ncommit <= (nfsi->npages >> 1))
+		goto out_mark_dirty;
+
+	if (wbc->nonblocking || wbc->for_background)
+		flags = 0;
+	ret = nfs_commit_inode(inode, flags);
+	if (ret >= 0) {
+		if (wbc->sync_mode == WB_SYNC_NONE) {
+			if (ret < wbc->nr_to_write)
+				wbc->nr_to_write -= ret;
+			else
+				wbc->nr_to_write = 0;
+		}
+		return 0;
+	}
+out_mark_dirty:
+	__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+	return ret;
+}
 #else
-static inline int nfs_commit_list(struct inode *inode, struct list_head *head, int how)
+static int nfs_commit_inode(struct inode *inode, int how)
+{
+	return 0;
+}
+
+static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc)
 {
 	return 0;
 }
 #endif
 
-long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_control *wbc, int how)
+int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
-	struct inode *inode = mapping->host;
-	pgoff_t idx_start, idx_end;
-	unsigned int npages = 0;
-	LIST_HEAD(head);
-	int nocommit = how & FLUSH_NOCOMMIT;
-	long pages, ret;
-
-	/* FIXME */
-	if (wbc->range_cyclic)
-		idx_start = 0;
-	else {
-		idx_start = wbc->range_start >> PAGE_CACHE_SHIFT;
-		idx_end = wbc->range_end >> PAGE_CACHE_SHIFT;
-		if (idx_end > idx_start) {
-			pgoff_t l_npages = 1 + idx_end - idx_start;
-			npages = l_npages;
-			if (sizeof(npages) != sizeof(l_npages) &&
-					(pgoff_t)npages != l_npages)
-				npages = 0;
-		}
-	}
-	how &= ~FLUSH_NOCOMMIT;
-	spin_lock(&inode->i_lock);
-	do {
-		ret = nfs_wait_on_requests_locked(inode, idx_start, npages);
-		if (ret != 0)
-			continue;
-		if (nocommit)
-			break;
-		pages = nfs_scan_commit(inode, &head, idx_start, npages);
-		if (pages == 0)
-			break;
-		if (how & FLUSH_INVALIDATE) {
-			spin_unlock(&inode->i_lock);
-			nfs_cancel_commit_list(&head);
-			ret = pages;
-			spin_lock(&inode->i_lock);
-			continue;
-		}
-		pages += nfs_scan_commit(inode, &head, 0, 0);
-		spin_unlock(&inode->i_lock);
-		ret = nfs_commit_list(inode, &head, how);
-		spin_lock(&inode->i_lock);
-
-	} while (ret >= 0);
-	spin_unlock(&inode->i_lock);
-	return ret;
-}
-
-static int __nfs_write_mapping(struct address_space *mapping, struct writeback_control *wbc, int how)
-{
-	int ret;
-
-	ret = nfs_writepages(mapping, wbc);
-	if (ret < 0)
-		goto out;
-	ret = nfs_sync_mapping_wait(mapping, wbc, how);
-	if (ret < 0)
-		goto out;
-	return 0;
-out:
-	__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
-	return ret;
-}
-
-/* Two pass sync: first using WB_SYNC_NONE, then WB_SYNC_ALL */
-static int nfs_write_mapping(struct address_space *mapping, int how)
-{
-	struct writeback_control wbc = {
-		.bdi = mapping->backing_dev_info,
-		.sync_mode = WB_SYNC_ALL,
-		.nr_to_write = LONG_MAX,
-		.range_start = 0,
-		.range_end = LLONG_MAX,
-	};
-
-	return __nfs_write_mapping(mapping, &wbc, how);
+	return nfs_commit_unstable_pages(inode, wbc);
 }
 
 /*
@@ -1499,37 +1415,26 @@
  */
 int nfs_wb_all(struct inode *inode)
 {
-	return nfs_write_mapping(inode->i_mapping, 0);
-}
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = LONG_MAX,
+		.range_start = 0,
+		.range_end = LLONG_MAX,
+	};
 
-int nfs_wb_nocommit(struct inode *inode)
-{
-	return nfs_write_mapping(inode->i_mapping, FLUSH_NOCOMMIT);
+	return sync_inode(inode, &wbc);
 }
 
 int nfs_wb_page_cancel(struct inode *inode, struct page *page)
 {
 	struct nfs_page *req;
-	loff_t range_start = page_offset(page);
-	loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
-	struct writeback_control wbc = {
-		.bdi = page->mapping->backing_dev_info,
-		.sync_mode = WB_SYNC_ALL,
-		.nr_to_write = LONG_MAX,
-		.range_start = range_start,
-		.range_end = range_end,
-	};
 	int ret = 0;
 
 	BUG_ON(!PageLocked(page));
 	for (;;) {
 		req = nfs_page_find_request(page);
 		if (req == NULL)
-			goto out;
-		if (test_bit(PG_CLEAN, &req->wb_flags)) {
-			nfs_release_request(req);
 			break;
-		}
 		if (nfs_lock_request_dontget(req)) {
 			nfs_inode_remove_request(req);
 			/*
@@ -1543,52 +1448,52 @@
 		ret = nfs_wait_on_request(req);
 		nfs_release_request(req);
 		if (ret < 0)
-			goto out;
-	}
-	if (!PagePrivate(page))
-		return 0;
-	ret = nfs_sync_mapping_wait(page->mapping, &wbc, FLUSH_INVALIDATE);
-out:
-	return ret;
-}
-
-static int nfs_wb_page_priority(struct inode *inode, struct page *page,
-				int how)
-{
-	loff_t range_start = page_offset(page);
-	loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
-	struct writeback_control wbc = {
-		.bdi = page->mapping->backing_dev_info,
-		.sync_mode = WB_SYNC_ALL,
-		.nr_to_write = LONG_MAX,
-		.range_start = range_start,
-		.range_end = range_end,
-	};
-	int ret;
-
-	do {
-		if (clear_page_dirty_for_io(page)) {
-			ret = nfs_writepage_locked(page, &wbc);
-			if (ret < 0)
-				goto out_error;
-		} else if (!PagePrivate(page))
 			break;
-		ret = nfs_sync_mapping_wait(page->mapping, &wbc, how);
-		if (ret < 0)
-			goto out_error;
-	} while (PagePrivate(page));
-	return 0;
-out_error:
-	__mark_inode_dirty(inode, I_DIRTY_PAGES);
+	}
 	return ret;
 }
 
 /*
  * Write back all requests on one page - we do this before reading it.
  */
-int nfs_wb_page(struct inode *inode, struct page* page)
+int nfs_wb_page(struct inode *inode, struct page *page)
 {
-	return nfs_wb_page_priority(inode, page, FLUSH_STABLE);
+	loff_t range_start = page_offset(page);
+	loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1);
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = 0,
+		.range_start = range_start,
+		.range_end = range_end,
+	};
+	struct nfs_page *req;
+	int need_commit;
+	int ret;
+
+	while(PagePrivate(page)) {
+		if (clear_page_dirty_for_io(page)) {
+			ret = nfs_writepage_locked(page, &wbc);
+			if (ret < 0)
+				goto out_error;
+		}
+		req = nfs_find_and_lock_request(page);
+		if (!req)
+			break;
+		if (IS_ERR(req)) {
+			ret = PTR_ERR(req);
+			goto out_error;
+		}
+		need_commit = test_bit(PG_CLEAN, &req->wb_flags);
+		nfs_clear_page_tag_locked(req);
+		if (need_commit) {
+			ret = nfs_commit_inode(inode, FLUSH_SYNC);
+			if (ret < 0)
+				goto out_error;
+		}
+	}
+	return 0;
+out_error:
+	return ret;
 }
 
 #ifdef CONFIG_MIGRATION
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
index d3854d9..bf9cbd2 100644
--- a/fs/nfsctl.c
+++ b/fs/nfsctl.c
@@ -36,10 +36,9 @@
 		return ERR_PTR(error);
 
 	if (flags == O_RDWR)
-		error = may_open(&nd.path, MAY_READ|MAY_WRITE,
-					   FMODE_READ|FMODE_WRITE);
+		error = may_open(&nd.path, MAY_READ|MAY_WRITE, flags);
 	else
-		error = may_open(&nd.path, MAY_WRITE, FMODE_WRITE);
+		error = may_open(&nd.path, MAY_WRITE, flags);
 
 	if (!error)
 		return dentry_open(nd.path.dentry, nd.path.mnt, flags,
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index c6eed2a..4bc22c7 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -525,6 +525,8 @@
 
 int set_callback_cred(void)
 {
+	if (callback_cred)
+		return 0;
 	callback_cred = rpc_lookup_machine_cred();
 	if (!callback_cred)
 		return -ENOMEM;
@@ -542,7 +544,8 @@
 	};
 	int status;
 
-	status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_SOFT,
+	status = rpc_call_async(cb->cb_client, &msg,
+				RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
 				&nfsd4_cb_probe_ops, (void *)clp);
 	if (status) {
 		warn_no_callback_path(clp, status);
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 5a754f7..98fb98e 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -119,9 +119,7 @@
 static void
 nfsd4_sync_rec_dir(void)
 {
-	mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
-	nfsd_sync_dir(rec_dir.dentry);
-	mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
+	vfs_fsync(NULL, rec_dir.dentry, 0);
 }
 
 int
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f19ed86..c97fddb 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1998,7 +1998,9 @@
 {
 	if (share_access & NFS4_SHARE_ACCESS_WRITE) {
 		drop_file_write_access(filp);
+		spin_lock(&filp->f_lock);
 		filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
+		spin_unlock(&filp->f_lock);
 	}
 }
 
@@ -2480,8 +2482,10 @@
 	}
 	memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
 
-	if (nfsd4_has_session(&resp->cstate))
+	if (nfsd4_has_session(&resp->cstate)) {
 		open->op_stateowner->so_confirmed = 1;
+		nfsd4_create_clid_dir(open->op_stateowner->so_client);
+	}
 
 	/*
 	* Attempt to hand out a delegation. No error return, because the
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index a8587e9..c47b4d7 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1434,7 +1434,7 @@
 		}
 		op->opnum = ntohl(*argp->p++);
 
-		if (op->opnum >= OP_ACCESS && op->opnum < ops->nops)
+		if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP)
 			op->status = ops->decoders[op->opnum](argp, &op->u);
 		else {
 			op->opnum = OP_ILLEGAL;
@@ -1528,7 +1528,7 @@
 	} } while (0);
 
 /* Encode as an array of strings the string given with components
- * seperated @sep.
+ * separated @sep.
  */
 static __be32 nfsd4_encode_components(char sep, char *components,
 				   __be32 **pp, int *buflen)
@@ -2121,9 +2121,15 @@
 		 * and this is the root of a cross-mounted filesystem.
 		 */
 		if (ignore_crossmnt == 0 &&
-		    exp->ex_path.mnt->mnt_root->d_inode == dentry->d_inode) {
-			err = vfs_getattr(exp->ex_path.mnt->mnt_parent,
-				exp->ex_path.mnt->mnt_mountpoint, &stat);
+		    dentry == exp->ex_path.mnt->mnt_root) {
+			struct path path = exp->ex_path;
+			path_get(&path);
+			while (follow_up(&path)) {
+				if (path.dentry != path.mnt->mnt_root)
+					break;
+			}
+			err = vfs_getattr(path.mnt, path.dentry, &stat);
+			path_put(&path);
 			if (err)
 				goto out_nfserr;
 		}
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 2604c3e..0f0e77f 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -988,6 +988,7 @@
 static ssize_t __write_ports_addxprt(char *buf)
 {
 	char transport[16];
+	struct svc_xprt *xprt;
 	int port, err;
 
 	if (sscanf(buf, "%15s %4u", transport, &port) != 2)
@@ -1002,13 +1003,24 @@
 
 	err = svc_create_xprt(nfsd_serv, transport,
 				PF_INET, port, SVC_SOCK_ANONYMOUS);
-	if (err < 0) {
-		/* Give a reasonable perror msg for bad transport string */
-		if (err == -ENOENT)
-			err = -EPROTONOSUPPORT;
-		return err;
-	}
+	if (err < 0)
+		goto out_err;
+
+	err = svc_create_xprt(nfsd_serv, transport,
+				PF_INET6, port, SVC_SOCK_ANONYMOUS);
+	if (err < 0 && err != -EAFNOSUPPORT)
+		goto out_close;
 	return 0;
+out_close:
+	xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port);
+	if (xprt != NULL) {
+		svc_close_xprt(xprt);
+		svc_xprt_put(xprt);
+	}
+out_err:
+	/* Decrease the count, but don't shut down the service */
+	nfsd_serv->sv_nrthreads--;
+	return err;
 }
 
 /*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 8715d19..a11b0e867 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -20,13 +20,14 @@
 #include <linux/fcntl.h>
 #include <linux/namei.h>
 #include <linux/delay.h>
-#include <linux/quotaops.h>
 #include <linux/fsnotify.h>
 #include <linux/posix_acl_xattr.h>
 #include <linux/xattr.h>
 #include <linux/jhash.h>
 #include <linux/ima.h>
 #include <asm/uaccess.h>
+#include <linux/exportfs.h>
+#include <linux/writeback.h>
 
 #ifdef CONFIG_NFSD_V3
 #include "xdr3.h"
@@ -271,6 +272,32 @@
 	return err;
 }
 
+/*
+ * Commit metadata changes to stable storage.
+ */
+static int
+commit_metadata(struct svc_fh *fhp)
+{
+	struct inode *inode = fhp->fh_dentry->d_inode;
+	const struct export_operations *export_ops = inode->i_sb->s_export_op;
+	int error = 0;
+
+	if (!EX_ISSYNC(fhp->fh_export))
+		return 0;
+
+	if (export_ops->commit_metadata) {
+		error = export_ops->commit_metadata(inode);
+	} else {
+		struct writeback_control wbc = {
+			.sync_mode = WB_SYNC_ALL,
+			.nr_to_write = 0, /* metadata only */
+		};
+
+		error = sync_inode(inode, &wbc);
+	}
+
+	return error;
+}
 
 /*
  * Set various file attributes.
@@ -361,7 +388,7 @@
 		 * If we are changing the size of the file, then
 		 * we need to break all leases.
 		 */
-		host_err = break_lease(inode, FMODE_WRITE | O_NONBLOCK);
+		host_err = break_lease(inode, O_WRONLY | O_NONBLOCK);
 		if (host_err == -EWOULDBLOCK)
 			host_err = -ETIMEDOUT;
 		if (host_err) /* ENOMEM or EWOULDBLOCK */
@@ -377,7 +404,6 @@
 			put_write_access(inode);
 			goto out_nfserr;
 		}
-		vfs_dq_init(inode);
 	}
 
 	/* sanitize the mode change */
@@ -734,7 +760,7 @@
 	 * Check to see if there are any leases on this file.
 	 * This may block while leases are broken.
 	 */
-	host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? FMODE_WRITE : 0));
+	host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0));
 	if (host_err == -EWOULDBLOCK)
 		host_err = -ETIMEDOUT;
 	if (host_err) /* NOMEM or WOULDBLOCK */
@@ -745,8 +771,6 @@
 			flags = O_RDWR|O_LARGEFILE;
 		else
 			flags = O_WRONLY|O_LARGEFILE;
-
-		vfs_dq_init(inode);
 	}
 	*filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt),
 			    flags, current_cred());
@@ -771,43 +795,6 @@
 }
 
 /*
- * Sync a file
- * As this calls fsync (not fdatasync) there is no need for a write_inode
- * after it.
- */
-static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
-			      const struct file_operations *fop)
-{
-	struct inode *inode = dp->d_inode;
-	int (*fsync) (struct file *, struct dentry *, int);
-	int err;
-
-	err = filemap_write_and_wait(inode->i_mapping);
-	if (err == 0 && fop && (fsync = fop->fsync))
-		err = fsync(filp, dp, 0);
-	return err;
-}
-
-static int
-nfsd_sync(struct file *filp)
-{
-        int err;
-	struct inode *inode = filp->f_path.dentry->d_inode;
-	dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
-	mutex_lock(&inode->i_mutex);
-	err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
-	mutex_unlock(&inode->i_mutex);
-
-	return err;
-}
-
-int
-nfsd_sync_dir(struct dentry *dp)
-{
-	return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
-}
-
-/*
  * Obtain the readahead parameters for the file
  * specified by (dev, ino).
  */
@@ -1010,7 +997,7 @@
 
 	if (inode->i_state & I_DIRTY) {
 		dprintk("nfsd: write sync %d\n", task_pid_nr(current));
-		err = nfsd_sync(file);
+		err = vfs_fsync(file, file->f_path.dentry, 0);
 	}
 	last_ino = inode->i_ino;
 	last_dev = inode->i_sb->s_dev;
@@ -1158,8 +1145,9 @@
 #ifdef CONFIG_NFSD_V3
 /*
  * Commit all pending writes to stable storage.
- * Strictly speaking, we could sync just the indicated file region here,
- * but there's currently no way we can ask the VFS to do so.
+ *
+ * Note: we only guarantee that data that lies within the range specified
+ * by the 'offset' and 'count' parameters will be synced.
  *
  * Unfortunately we cannot lock the file to make sure we return full WCC
  * data to the client, as locking happens lower down in the filesystem.
@@ -1169,23 +1157,32 @@
                loff_t offset, unsigned long count)
 {
 	struct file	*file;
-	__be32		err;
+	loff_t		end = LLONG_MAX;
+	__be32		err = nfserr_inval;
 
-	if ((u64)count > ~(u64)offset)
-		return nfserr_inval;
+	if (offset < 0)
+		goto out;
+	if (count != 0) {
+		end = offset + (loff_t)count - 1;
+		if (end < offset)
+			goto out;
+	}
 
 	err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
 	if (err)
-		return err;
+		goto out;
 	if (EX_ISSYNC(fhp->fh_export)) {
-		if (file->f_op && file->f_op->fsync) {
-			err = nfserrno(nfsd_sync(file));
-		} else {
+		int err2 = vfs_fsync_range(file, file->f_path.dentry,
+				offset, end, 0);
+
+		if (err2 != -EINVAL)
+			err = nfserrno(err2);
+		else
 			err = nfserr_notsupp;
-		}
 	}
 
 	nfsd_close(file);
+out:
 	return err;
 }
 #endif /* CONFIG_NFSD_V3 */
@@ -1338,12 +1335,14 @@
 		goto out_nfserr;
 	}
 
-	if (EX_ISSYNC(fhp->fh_export)) {
-		err = nfserrno(nfsd_sync_dir(dentry));
-		write_inode_now(dchild->d_inode, 1);
-	}
+	err = nfsd_create_setattr(rqstp, resfhp, iap);
 
-	err2 = nfsd_create_setattr(rqstp, resfhp, iap);
+	/*
+	 * nfsd_setattr already committed the child.  Transactional filesystems
+	 * had a chance to commit changes for both parent and child
+	 * simultaneously making the following commit_metadata a noop.
+	 */
+	err2 = nfserrno(commit_metadata(fhp));
 	if (err2)
 		err = err2;
 	mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1375,7 +1374,6 @@
 	struct dentry	*dentry, *dchild = NULL;
 	struct inode	*dirp;
 	__be32		err;
-	__be32		err2;
 	int		host_err;
 	__u32		v_mtime=0, v_atime=0;
 
@@ -1470,11 +1468,6 @@
 	if (created)
 		*created = 1;
 
-	if (EX_ISSYNC(fhp->fh_export)) {
-		err = nfserrno(nfsd_sync_dir(dentry));
-		/* setattr will sync the child (or not) */
-	}
-
 	nfsd_check_ignore_resizing(iap);
 
 	if (createmode == NFS3_CREATE_EXCLUSIVE) {
@@ -1489,9 +1482,13 @@
 	}
 
  set_attr:
-	err2 = nfsd_create_setattr(rqstp, resfhp, iap);
-	if (err2)
-		err = err2;
+	err = nfsd_create_setattr(rqstp, resfhp, iap);
+
+	/*
+	 * nfsd_setattr already committed the child (and possibly also the parent).
+	 */
+	if (!err)
+		err = nfserrno(commit_metadata(fhp));
 
 	mnt_drop_write(fhp->fh_export->ex_path.mnt);
 	/*
@@ -1606,12 +1603,9 @@
 		}
 	} else
 		host_err = vfs_symlink(dentry->d_inode, dnew, path);
-
-	if (!host_err) {
-		if (EX_ISSYNC(fhp->fh_export))
-			host_err = nfsd_sync_dir(dentry);
-	}
 	err = nfserrno(host_err);
+	if (!err)
+		err = nfserrno(commit_metadata(fhp));
 	fh_unlock(fhp);
 
 	mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1673,11 +1667,9 @@
 	}
 	host_err = vfs_link(dold, dirp, dnew);
 	if (!host_err) {
-		if (EX_ISSYNC(ffhp->fh_export)) {
-			err = nfserrno(nfsd_sync_dir(ddir));
-			write_inode_now(dest, 1);
-		}
-		err = 0;
+		err = nfserrno(commit_metadata(ffhp));
+		if (!err)
+			err = nfserrno(commit_metadata(tfhp));
 	} else {
 		if (host_err == -EXDEV && rqstp->rq_vers == 2)
 			err = nfserr_acces;
@@ -1773,10 +1765,10 @@
 		goto out_dput_new;
 
 	host_err = vfs_rename(fdir, odentry, tdir, ndentry);
-	if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
-		host_err = nfsd_sync_dir(tdentry);
+	if (!host_err) {
+		host_err = commit_metadata(tfhp);
 		if (!host_err)
-			host_err = nfsd_sync_dir(fdentry);
+			host_err = commit_metadata(ffhp);
 	}
 
 	mnt_drop_write(ffhp->fh_export->ex_path.mnt);
@@ -1857,12 +1849,9 @@
 
 	dput(rdentry);
 
-	if (host_err)
-		goto out_drop;
-	if (EX_ISSYNC(fhp->fh_export))
-		host_err = nfsd_sync_dir(dentry);
+	if (!host_err)
+		host_err = commit_metadata(fhp);
 
-out_drop:
 	mnt_drop_write(fhp->fh_export->ex_path.mnt);
 out_nfserr:
 	err = nfserrno(host_err);
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index 187dd07..9d1e5de 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -388,8 +388,7 @@
 		ret = -ENOENT;
 		goto out;
 	}
-	if (blocknrp != NULL)
-		*blocknrp = blocknr;
+	*blocknrp = blocknr;
 
  out:
 	kunmap_atomic(kaddr, KM_USER0);
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 76d803e..0092840 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -224,7 +224,7 @@
  * len <= NILFS_NAME_LEN and de != NULL are guaranteed by caller.
  */
 static int
-nilfs_match(int len, const char * const name, struct nilfs_dir_entry *de)
+nilfs_match(int len, const unsigned char *name, struct nilfs_dir_entry *de)
 {
 	if (len != de->name_len)
 		return 0;
@@ -349,11 +349,11 @@
  * Entry is guaranteed to be valid.
  */
 struct nilfs_dir_entry *
-nilfs_find_entry(struct inode *dir, struct dentry *dentry,
+nilfs_find_entry(struct inode *dir, const struct qstr *qstr,
 		 struct page **res_page)
 {
-	const char *name = dentry->d_name.name;
-	int namelen = dentry->d_name.len;
+	const unsigned char *name = qstr->name;
+	int namelen = qstr->len;
 	unsigned reclen = NILFS_DIR_REC_LEN(namelen);
 	unsigned long start, n;
 	unsigned long npages = dir_pages(dir);
@@ -424,13 +424,13 @@
 	return de;
 }
 
-ino_t nilfs_inode_by_name(struct inode *dir, struct dentry *dentry)
+ino_t nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr)
 {
 	ino_t res = 0;
 	struct nilfs_dir_entry *de;
 	struct page *page;
 
-	de = nilfs_find_entry(dir, dentry, &page);
+	de = nilfs_find_entry(dir, qstr, &page);
 	if (de) {
 		res = le64_to_cpu(de->inode);
 		kunmap(page);
@@ -465,7 +465,7 @@
 int nilfs_add_link(struct dentry *dentry, struct inode *inode)
 {
 	struct inode *dir = dentry->d_parent->d_inode;
-	const char *name = dentry->d_name.name;
+	const unsigned char *name = dentry->d_name.name;
 	int namelen = dentry->d_name.len;
 	unsigned chunk_size = nilfs_chunk_size(dir);
 	unsigned reclen = NILFS_DIR_REC_LEN(namelen);
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index d6b2b83..313d0a2 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -26,6 +26,7 @@
 #include <linux/capability.h>	/* capable() */
 #include <linux/uaccess.h>	/* copy_from_user(), copy_to_user() */
 #include <linux/vmalloc.h>
+#include <linux/mount.h>	/* mnt_want_write(), mnt_drop_write() */
 #include <linux/nilfs2_fs.h>
 #include "nilfs.h"
 #include "segment.h"
@@ -107,20 +108,28 @@
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
+
+	ret = mnt_want_write(filp->f_path.mnt);
+	if (ret)
+		return ret;
+
+	ret = -EFAULT;
 	if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
-		return -EFAULT;
+		goto out;
 
 	mutex_lock(&nilfs->ns_mount_mutex);
+
 	nilfs_transaction_begin(inode->i_sb, &ti, 0);
 	ret = nilfs_cpfile_change_cpmode(
 		cpfile, cpmode.cm_cno, cpmode.cm_mode);
-	if (unlikely(ret < 0)) {
+	if (unlikely(ret < 0))
 		nilfs_transaction_abort(inode->i_sb);
-		mutex_unlock(&nilfs->ns_mount_mutex);
-		return ret;
-	}
-	nilfs_transaction_commit(inode->i_sb); /* never fails */
+	else
+		nilfs_transaction_commit(inode->i_sb); /* never fails */
+
 	mutex_unlock(&nilfs->ns_mount_mutex);
+out:
+	mnt_drop_write(filp->f_path.mnt);
 	return ret;
 }
 
@@ -135,16 +144,23 @@
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
+
+	ret = mnt_want_write(filp->f_path.mnt);
+	if (ret)
+		return ret;
+
+	ret = -EFAULT;
 	if (copy_from_user(&cno, argp, sizeof(cno)))
-		return -EFAULT;
+		goto out;
 
 	nilfs_transaction_begin(inode->i_sb, &ti, 0);
 	ret = nilfs_cpfile_delete_checkpoint(cpfile, cno);
-	if (unlikely(ret < 0)) {
+	if (unlikely(ret < 0))
 		nilfs_transaction_abort(inode->i_sb);
-		return ret;
-	}
-	nilfs_transaction_commit(inode->i_sb); /* never fails */
+	else
+		nilfs_transaction_commit(inode->i_sb); /* never fails */
+out:
+	mnt_drop_write(filp->f_path.mnt);
 	return ret;
 }
 
@@ -496,12 +512,19 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (copy_from_user(argv, argp, sizeof(argv)))
-		return -EFAULT;
+	ret = mnt_want_write(filp->f_path.mnt);
+	if (ret)
+		return ret;
 
+	ret = -EFAULT;
+	if (copy_from_user(argv, argp, sizeof(argv)))
+		goto out;
+
+	ret = -EINVAL;
 	nsegs = argv[4].v_nmembs;
 	if (argv[4].v_size != argsz[4])
-		return -EINVAL;
+		goto out;
+
 	/*
 	 * argv[4] points to segment numbers this ioctl cleans.  We
 	 * use kmalloc() for its buffer because memory used for the
@@ -509,9 +532,10 @@
 	 */
 	kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base,
 			       nsegs * sizeof(__u64));
-	if (IS_ERR(kbufs[4]))
-		return PTR_ERR(kbufs[4]);
-
+	if (IS_ERR(kbufs[4])) {
+		ret = PTR_ERR(kbufs[4]);
+		goto out;
+	}
 	nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
 
 	for (n = 0; n < 4; n++) {
@@ -563,10 +587,12 @@
 		nilfs_remove_all_gcinode(nilfs);
 	clear_nilfs_gc_running(nilfs);
 
- out_free:
+out_free:
 	while (--n >= 0)
 		vfree(kbufs[n]);
 	kfree(kbufs[4]);
+out:
+	mnt_drop_write(filp->f_path.mnt);
 	return ret;
 }
 
@@ -575,13 +601,17 @@
 {
 	__u64 cno;
 	int ret;
+	struct the_nilfs *nilfs;
 
 	ret = nilfs_construct_segment(inode->i_sb);
 	if (ret < 0)
 		return ret;
 
 	if (argp != NULL) {
-		cno = NILFS_SB(inode->i_sb)->s_nilfs->ns_cno - 1;
+		nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+		down_read(&nilfs->ns_segctor_sem);
+		cno = nilfs->ns_cno - 1;
+		up_read(&nilfs->ns_segctor_sem);
 		if (copy_to_user(argp, &cno, sizeof(cno)))
 			return -EFAULT;
 	}
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 07ba838..ad6ed2c 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -67,7 +67,7 @@
 	if (dentry->d_name.len > NILFS_NAME_LEN)
 		return ERR_PTR(-ENAMETOOLONG);
 
-	ino = nilfs_inode_by_name(dir, dentry);
+	ino = nilfs_inode_by_name(dir, &dentry->d_name);
 	inode = NULL;
 	if (ino) {
 		inode = nilfs_iget(dir->i_sb, ino);
@@ -81,10 +81,7 @@
 {
 	unsigned long ino;
 	struct inode *inode;
-	struct dentry dotdot;
-
-	dotdot.d_name.name = "..";
-	dotdot.d_name.len = 2;
+	struct qstr dotdot = {.name = "..", .len = 2};
 
 	ino = nilfs_inode_by_name(child->d_inode, &dotdot);
 	if (!ino)
@@ -296,7 +293,7 @@
 	int err;
 
 	err = -ENOENT;
-	de = nilfs_find_entry(dir, dentry, &page);
+	de = nilfs_find_entry(dir, &dentry->d_name, &page);
 	if (!de)
 		goto out;
 
@@ -389,7 +386,7 @@
 		return err;
 
 	err = -ENOENT;
-	old_de = nilfs_find_entry(old_dir, old_dentry, &old_page);
+	old_de = nilfs_find_entry(old_dir, &old_dentry->d_name, &old_page);
 	if (!old_de)
 		goto out;
 
@@ -409,7 +406,7 @@
 			goto out_dir;
 
 		err = -ENOENT;
-		new_de = nilfs_find_entry(new_dir, new_dentry, &new_page);
+		new_de = nilfs_find_entry(new_dir, &new_dentry->d_name, &new_page);
 		if (!new_de)
 			goto out_dir;
 		inc_nlink(old_inode);
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 4da6f67..8723e5b 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -217,10 +217,10 @@
 
 /* dir.c */
 extern int nilfs_add_link(struct dentry *, struct inode *);
-extern ino_t nilfs_inode_by_name(struct inode *, struct dentry *);
+extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *);
 extern int nilfs_make_empty(struct inode *, struct inode *);
 extern struct nilfs_dir_entry *
-nilfs_find_entry(struct inode *, struct dentry *, struct page **);
+nilfs_find_entry(struct inode *, const struct qstr *, struct page **);
 extern int nilfs_delete_entry(struct nilfs_dir_entry *, struct page *);
 extern int nilfs_empty_dir(struct inode *);
 extern struct nilfs_dir_entry *nilfs_dotdot(struct inode *, struct page **);
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index c9c96c7..017bedc 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -39,7 +39,6 @@
 	NILFS_SEG_FAIL_IO,
 	NILFS_SEG_FAIL_MAGIC,
 	NILFS_SEG_FAIL_SEQ,
-	NILFS_SEG_FAIL_CHECKSUM_SEGSUM,
 	NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT,
 	NILFS_SEG_FAIL_CHECKSUM_FULL,
 	NILFS_SEG_FAIL_CONSISTENCY,
@@ -71,10 +70,6 @@
 		printk(KERN_WARNING
 		       "NILFS warning: Sequence number mismatch\n");
 		break;
-	case NILFS_SEG_FAIL_CHECKSUM_SEGSUM:
-		printk(KERN_WARNING
-		       "NILFS warning: Checksum error in segment summary\n");
-		break;
 	case NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT:
 		printk(KERN_WARNING
 		       "NILFS warning: Checksum error in super root\n");
@@ -206,19 +201,15 @@
  * @pseg_start: start disk block number of partial segment
  * @seg_seq: sequence number requested
  * @ssi: pointer to nilfs_segsum_info struct to store information
- * @full_check: full check flag
- *              (0: only checks segment summary CRC, 1: data CRC)
  */
 static int
 load_segment_summary(struct nilfs_sb_info *sbi, sector_t pseg_start,
-		     u64 seg_seq, struct nilfs_segsum_info *ssi,
-		     int full_check)
+		     u64 seg_seq, struct nilfs_segsum_info *ssi)
 {
 	struct buffer_head *bh_sum;
 	struct nilfs_segment_summary *sum;
-	unsigned long offset, nblock;
-	u64 check_bytes;
-	u32 crc, crc_sum;
+	unsigned long nblock;
+	u32 crc;
 	int ret = NILFS_SEG_FAIL_IO;
 
 	bh_sum = sb_bread(sbi->s_super, pseg_start);
@@ -237,34 +228,24 @@
 		ret = NILFS_SEG_FAIL_SEQ;
 		goto failed;
 	}
-	if (full_check) {
-		offset = sizeof(sum->ss_datasum);
-		check_bytes =
-			((u64)ssi->nblocks << sbi->s_super->s_blocksize_bits);
-		nblock = ssi->nblocks;
-		crc_sum = le32_to_cpu(sum->ss_datasum);
-		ret = NILFS_SEG_FAIL_CHECKSUM_FULL;
-	} else { /* only checks segment summary */
-		offset = sizeof(sum->ss_datasum) + sizeof(sum->ss_sumsum);
-		check_bytes = ssi->sumbytes;
-		nblock = ssi->nsumblk;
-		crc_sum = le32_to_cpu(sum->ss_sumsum);
-		ret = NILFS_SEG_FAIL_CHECKSUM_SEGSUM;
-	}
 
+	nblock = ssi->nblocks;
 	if (unlikely(nblock == 0 ||
 		     nblock > sbi->s_nilfs->ns_blocks_per_segment)) {
 		/* This limits the number of blocks read in the CRC check */
 		ret = NILFS_SEG_FAIL_CONSISTENCY;
 		goto failed;
 	}
-	if (calc_crc_cont(sbi, bh_sum, &crc, offset, check_bytes,
+	if (calc_crc_cont(sbi, bh_sum, &crc, sizeof(sum->ss_datasum),
+			  ((u64)nblock << sbi->s_super->s_blocksize_bits),
 			  pseg_start, nblock)) {
 		ret = NILFS_SEG_FAIL_IO;
 		goto failed;
 	}
-	if (crc == crc_sum)
+	if (crc == le32_to_cpu(sum->ss_datasum))
 		ret = 0;
+	else
+		ret = NILFS_SEG_FAIL_CHECKSUM_FULL;
  failed:
 	brelse(bh_sum);
  out:
@@ -598,7 +579,7 @@
 
 	while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) {
 
-		ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi, 1);
+		ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi);
 		if (ret) {
 			if (ret == NILFS_SEG_FAIL_IO) {
 				err = -EIO;
@@ -821,7 +802,7 @@
 
 	for (;;) {
 		/* Load segment summary */
-		ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi, 1);
+		ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi);
 		if (ret) {
 			if (ret == NILFS_SEG_FAIL_IO)
 				goto failed;
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c
index 645c786..ab56fe4 100644
--- a/fs/nilfs2/segbuf.c
+++ b/fs/nilfs2/segbuf.c
@@ -40,6 +40,11 @@
 };
 
 
+static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf,
+			      struct the_nilfs *nilfs);
+static int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf);
+
+
 static struct kmem_cache *nilfs_segbuf_cachep;
 
 static void nilfs_segbuf_init_once(void *obj)
@@ -302,6 +307,19 @@
 	}
 }
 
+int nilfs_write_logs(struct list_head *logs, struct the_nilfs *nilfs)
+{
+	struct nilfs_segment_buffer *segbuf;
+	int ret = 0;
+
+	list_for_each_entry(segbuf, logs, sb_list) {
+		ret = nilfs_segbuf_write(segbuf, nilfs);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
 int nilfs_wait_on_logs(struct list_head *logs)
 {
 	struct nilfs_segment_buffer *segbuf;
diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h
index 6af1630..94dfd35 100644
--- a/fs/nilfs2/segbuf.h
+++ b/fs/nilfs2/segbuf.h
@@ -166,13 +166,10 @@
 	segbuf->sb_sum.nfileblk++;
 }
 
-int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf,
-		       struct the_nilfs *nilfs);
-int nilfs_segbuf_wait(struct nilfs_segment_buffer *segbuf);
-
 void nilfs_clear_logs(struct list_head *logs);
 void nilfs_truncate_logs(struct list_head *logs,
 			 struct nilfs_segment_buffer *last);
+int nilfs_write_logs(struct list_head *logs, struct the_nilfs *nilfs);
 int nilfs_wait_on_logs(struct list_head *logs);
 
 static inline void nilfs_destroy_logs(struct list_head *logs)
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 105b508..ada2f1b 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -1764,14 +1764,9 @@
 static int nilfs_segctor_write(struct nilfs_sc_info *sci,
 			       struct the_nilfs *nilfs)
 {
-	struct nilfs_segment_buffer *segbuf;
-	int ret = 0;
+	int ret;
 
-	list_for_each_entry(segbuf, &sci->sc_segbufs, sb_list) {
-		ret = nilfs_segbuf_write(segbuf, nilfs);
-		if (ret)
-			break;
-	}
+	ret = nilfs_write_logs(&sci->sc_segbufs, nilfs);
 	list_splice_tail_init(&sci->sc_segbufs, &sci->sc_write_logs);
 	return ret;
 }
@@ -1937,8 +1932,7 @@
 {
 	struct nilfs_segment_buffer *segbuf;
 	struct page *bd_page = NULL, *fs_page = NULL;
-	struct nilfs_sb_info *sbi = sci->sc_sbi;
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
 	int update_sr = (sci->sc_super_root != NULL);
 
 	list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) {
@@ -2020,7 +2014,7 @@
 	if (update_sr) {
 		nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start,
 				       segbuf->sb_sum.seg_seq, nilfs->ns_cno++);
-		sbi->s_super->s_dirt = 1;
+		set_nilfs_sb_dirty(nilfs);
 
 		clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags);
 		clear_bit(NILFS_SC_DIRTY, &sci->sc_flags);
@@ -2425,43 +2419,43 @@
 	return err;
 }
 
-struct nilfs_segctor_req {
-	int mode;
-	__u32 seq_accepted;
-	int sc_err;  /* construction failure */
-	int sb_err;  /* super block writeback failure */
-};
-
 #define FLUSH_FILE_BIT	(0x1) /* data file only */
 #define FLUSH_DAT_BIT	(1 << NILFS_DAT_INO) /* DAT only */
 
-static void nilfs_segctor_accept(struct nilfs_sc_info *sci,
-				 struct nilfs_segctor_req *req)
+/**
+ * nilfs_segctor_accept - record accepted sequence count of log-write requests
+ * @sci: segment constructor object
+ */
+static void nilfs_segctor_accept(struct nilfs_sc_info *sci)
 {
-	req->sc_err = req->sb_err = 0;
 	spin_lock(&sci->sc_state_lock);
-	req->seq_accepted = sci->sc_seq_request;
+	sci->sc_seq_accepted = sci->sc_seq_request;
 	spin_unlock(&sci->sc_state_lock);
 
 	if (sci->sc_timer)
 		del_timer_sync(sci->sc_timer);
 }
 
-static void nilfs_segctor_notify(struct nilfs_sc_info *sci,
-				 struct nilfs_segctor_req *req)
+/**
+ * nilfs_segctor_notify - notify the result of request to caller threads
+ * @sci: segment constructor object
+ * @mode: mode of log forming
+ * @err: error code to be notified
+ */
+static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err)
 {
 	/* Clear requests (even when the construction failed) */
 	spin_lock(&sci->sc_state_lock);
 
-	if (req->mode == SC_LSEG_SR) {
+	if (mode == SC_LSEG_SR) {
 		sci->sc_state &= ~NILFS_SEGCTOR_COMMIT;
-		sci->sc_seq_done = req->seq_accepted;
-		nilfs_segctor_wakeup(sci, req->sc_err ? : req->sb_err);
+		sci->sc_seq_done = sci->sc_seq_accepted;
+		nilfs_segctor_wakeup(sci, err);
 		sci->sc_flush_request = 0;
 	} else {
-		if (req->mode == SC_FLUSH_FILE)
+		if (mode == SC_FLUSH_FILE)
 			sci->sc_flush_request &= ~FLUSH_FILE_BIT;
-		else if (req->mode == SC_FLUSH_DAT)
+		else if (mode == SC_FLUSH_DAT)
 			sci->sc_flush_request &= ~FLUSH_DAT_BIT;
 
 		/* re-enable timer if checkpoint creation was not done */
@@ -2472,30 +2466,37 @@
 	spin_unlock(&sci->sc_state_lock);
 }
 
-static int nilfs_segctor_construct(struct nilfs_sc_info *sci,
-				   struct nilfs_segctor_req *req)
+/**
+ * nilfs_segctor_construct - form logs and write them to disk
+ * @sci: segment constructor object
+ * @mode: mode of log forming
+ */
+static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
 {
 	struct nilfs_sb_info *sbi = sci->sc_sbi;
 	struct the_nilfs *nilfs = sbi->s_nilfs;
 	int err = 0;
 
+	nilfs_segctor_accept(sci);
+
 	if (nilfs_discontinued(nilfs))
-		req->mode = SC_LSEG_SR;
-	if (!nilfs_segctor_confirm(sci)) {
-		err = nilfs_segctor_do_construct(sci, req->mode);
-		req->sc_err = err;
-	}
+		mode = SC_LSEG_SR;
+	if (!nilfs_segctor_confirm(sci))
+		err = nilfs_segctor_do_construct(sci, mode);
+
 	if (likely(!err)) {
-		if (req->mode != SC_FLUSH_DAT)
+		if (mode != SC_FLUSH_DAT)
 			atomic_set(&nilfs->ns_ndirtyblks, 0);
 		if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) &&
 		    nilfs_discontinued(nilfs)) {
 			down_write(&nilfs->ns_sem);
-			req->sb_err = nilfs_commit_super(sbi,
-					nilfs_altsb_need_update(nilfs));
+			err = nilfs_commit_super(
+				sbi, nilfs_altsb_need_update(nilfs));
 			up_write(&nilfs->ns_sem);
 		}
 	}
+
+	nilfs_segctor_notify(sci, mode, err);
 	return err;
 }
 
@@ -2526,7 +2527,6 @@
 	struct nilfs_sc_info *sci = NILFS_SC(sbi);
 	struct the_nilfs *nilfs = sbi->s_nilfs;
 	struct nilfs_transaction_info ti;
-	struct nilfs_segctor_req req = { .mode = SC_LSEG_SR };
 	int err;
 
 	if (unlikely(!sci))
@@ -2547,10 +2547,8 @@
 	list_splice_tail_init(&nilfs->ns_gc_inodes, &sci->sc_gc_inodes);
 
 	for (;;) {
-		nilfs_segctor_accept(sci, &req);
-		err = nilfs_segctor_construct(sci, &req);
+		err = nilfs_segctor_construct(sci, SC_LSEG_SR);
 		nilfs_remove_written_gcinodes(nilfs, &sci->sc_gc_inodes);
-		nilfs_segctor_notify(sci, &req);
 
 		if (likely(!err))
 			break;
@@ -2560,6 +2558,16 @@
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(sci->sc_interval);
 	}
+	if (nilfs_test_opt(sbi, DISCARD)) {
+		int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs,
+						 sci->sc_nfreesegs);
+		if (ret) {
+			printk(KERN_WARNING
+			       "NILFS warning: error %d on discard request, "
+			       "turning discards off for the device\n", ret);
+			nilfs_clear_opt(sbi, DISCARD);
+		}
+	}
 
  out_unlock:
 	sci->sc_freesegs = NULL;
@@ -2573,13 +2581,9 @@
 {
 	struct nilfs_sb_info *sbi = sci->sc_sbi;
 	struct nilfs_transaction_info ti;
-	struct nilfs_segctor_req req = { .mode = mode };
 
 	nilfs_transaction_lock(sbi, &ti, 0);
-
-	nilfs_segctor_accept(sci, &req);
-	nilfs_segctor_construct(sci, &req);
-	nilfs_segctor_notify(sci, &req);
+	nilfs_segctor_construct(sci, mode);
 
 	/*
 	 * Unclosed segment should be retried.  We do this using sc_timer.
@@ -2635,6 +2639,7 @@
 static int nilfs_segctor_thread(void *arg)
 {
 	struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg;
+	struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
 	struct timer_list timer;
 	int timeout = 0;
 
@@ -2680,7 +2685,6 @@
 	} else {
 		DEFINE_WAIT(wait);
 		int should_sleep = 1;
-		struct the_nilfs *nilfs;
 
 		prepare_to_wait(&sci->sc_wait_daemon, &wait,
 				TASK_INTERRUPTIBLE);
@@ -2701,8 +2705,8 @@
 		finish_wait(&sci->sc_wait_daemon, &wait);
 		timeout = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) &&
 			   time_after_eq(jiffies, sci->sc_timer->expires));
-		nilfs = sci->sc_sbi->s_nilfs;
-		if (sci->sc_super->s_dirt && nilfs_sb_need_update(nilfs))
+
+		if (nilfs_sb_dirty(nilfs) && nilfs_sb_need_update(nilfs))
 			set_nilfs_discontinued(nilfs);
 	}
 	goto loop;
@@ -2797,12 +2801,9 @@
 	do {
 		struct nilfs_sb_info *sbi = sci->sc_sbi;
 		struct nilfs_transaction_info ti;
-		struct nilfs_segctor_req req = { .mode = SC_LSEG_SR };
 
 		nilfs_transaction_lock(sbi, &ti, 0);
-		nilfs_segctor_accept(sci, &req);
-		ret = nilfs_segctor_construct(sci, &req);
-		nilfs_segctor_notify(sci, &req);
+		ret = nilfs_segctor_construct(sci, SC_LSEG_SR);
 		nilfs_transaction_unlock(sbi);
 
 	} while (ret && retrycount-- > 0);
@@ -2865,8 +2866,15 @@
 	struct the_nilfs *nilfs = sbi->s_nilfs;
 	int err;
 
-	/* Each field of nilfs_segctor is cleared through the initialization
-	   of super-block info */
+	if (NILFS_SC(sbi)) {
+		/*
+		 * This happens if the filesystem was remounted
+		 * read/write after nilfs_error degenerated it into a
+		 * read-only mount.
+		 */
+		nilfs_detach_segment_constructor(sbi);
+	}
+
 	sbi->s_sc_info = nilfs_segctor_new(sbi);
 	if (!sbi->s_sc_info)
 		return -ENOMEM;
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
index 3d3ab2f..3155e0c 100644
--- a/fs/nilfs2/segment.h
+++ b/fs/nilfs2/segment.h
@@ -116,6 +116,7 @@
  * @sc_wait_daemon: Daemon wait queue
  * @sc_wait_task: Start/end wait queue to control segctord task
  * @sc_seq_request: Request counter
+ * @sc_seq_accept: Accepted request count
  * @sc_seq_done: Completion counter
  * @sc_sync: Request of explicit sync operation
  * @sc_interval: Timeout value of background construction
@@ -169,6 +170,7 @@
 	wait_queue_head_t	sc_wait_task;
 
 	__u32			sc_seq_request;
+	__u32			sc_seq_accepted;
 	__u32			sc_seq_done;
 
 	int			sc_sync;
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 8173fae..92579cc 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -96,9 +96,6 @@
 	if (!(sb->s_flags & MS_RDONLY)) {
 		struct the_nilfs *nilfs = sbi->s_nilfs;
 
-		if (!nilfs_test_opt(sbi, ERRORS_CONT))
-			nilfs_detach_segment_constructor(sbi);
-
 		down_write(&nilfs->ns_sem);
 		if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) {
 			nilfs->ns_mount_state |= NILFS_ERROR_FS;
@@ -301,7 +298,7 @@
 		memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
 		nilfs->ns_sbwtime[1] = t;
 	}
-	sbi->s_super->s_dirt = 0;
+	clear_nilfs_sb_dirty(nilfs);
 	return nilfs_sync_super(sbi, dupsb);
 }
 
@@ -345,7 +342,7 @@
 		err = nilfs_construct_segment(sb);
 
 	down_write(&nilfs->ns_sem);
-	if (sb->s_dirt)
+	if (nilfs_sb_dirty(nilfs))
 		nilfs_commit_super(sbi, 1);
 	up_write(&nilfs->ns_sem);
 
@@ -481,6 +478,8 @@
 		seq_printf(seq, ",order=strict");
 	if (nilfs_test_opt(sbi, NORECOVERY))
 		seq_printf(seq, ",norecovery");
+	if (nilfs_test_opt(sbi, DISCARD))
+		seq_printf(seq, ",discard");
 
 	return 0;
 }
@@ -550,7 +549,7 @@
 enum {
 	Opt_err_cont, Opt_err_panic, Opt_err_ro,
 	Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery,
-	Opt_err,
+	Opt_discard, Opt_err,
 };
 
 static match_table_t tokens = {
@@ -561,6 +560,7 @@
 	{Opt_snapshot, "cp=%u"},
 	{Opt_order, "order=%s"},
 	{Opt_norecovery, "norecovery"},
+	{Opt_discard, "discard"},
 	{Opt_err, NULL}
 };
 
@@ -614,6 +614,9 @@
 		case Opt_norecovery:
 			nilfs_set_opt(sbi, NORECOVERY);
 			break;
+		case Opt_discard:
+			nilfs_set_opt(sbi, DISCARD);
+			break;
 		default:
 			printk(KERN_ERR
 			       "NILFS: Unrecognized mount option \"%s\"\n", p);
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 6241e17..92733d5 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -646,6 +646,44 @@
 	goto out;
 }
 
+int nilfs_discard_segments(struct the_nilfs *nilfs, __u64 *segnump,
+			    size_t nsegs)
+{
+	sector_t seg_start, seg_end;
+	sector_t start = 0, nblocks = 0;
+	unsigned int sects_per_block;
+	__u64 *sn;
+	int ret = 0;
+
+	sects_per_block = (1 << nilfs->ns_blocksize_bits) /
+		bdev_logical_block_size(nilfs->ns_bdev);
+	for (sn = segnump; sn < segnump + nsegs; sn++) {
+		nilfs_get_segment_range(nilfs, *sn, &seg_start, &seg_end);
+
+		if (!nblocks) {
+			start = seg_start;
+			nblocks = seg_end - seg_start + 1;
+		} else if (start + nblocks == seg_start) {
+			nblocks += seg_end - seg_start + 1;
+		} else {
+			ret = blkdev_issue_discard(nilfs->ns_bdev,
+						   start * sects_per_block,
+						   nblocks * sects_per_block,
+						   GFP_NOFS,
+						   DISCARD_FL_BARRIER);
+			if (ret < 0)
+				return ret;
+			nblocks = 0;
+		}
+	}
+	if (nblocks)
+		ret = blkdev_issue_discard(nilfs->ns_bdev,
+					   start * sects_per_block,
+					   nblocks * sects_per_block,
+					   GFP_NOFS, DISCARD_FL_BARRIER);
+	return ret;
+}
+
 int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks)
 {
 	struct inode *dat = nilfs_dat_inode(nilfs);
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index 589786e..e9795f1 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -38,6 +38,7 @@
 				   the latest checkpoint was loaded */
 	THE_NILFS_DISCONTINUED,	/* 'next' pointer chain has broken */
 	THE_NILFS_GC_RUNNING,	/* gc process is running */
+	THE_NILFS_SB_DIRTY,	/* super block is dirty */
 };
 
 /**
@@ -197,6 +198,7 @@
 THE_NILFS_FNS(LOADED, loaded)
 THE_NILFS_FNS(DISCONTINUED, discontinued)
 THE_NILFS_FNS(GC_RUNNING, gc_running)
+THE_NILFS_FNS(SB_DIRTY, sb_dirty)
 
 /* Minimum interval of periodical update of superblocks (in seconds) */
 #define NILFS_SB_FREQ		10
@@ -221,6 +223,7 @@
 void put_nilfs(struct the_nilfs *);
 int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
 int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
+int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t);
 int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
 struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
 int nilfs_checkpoint_is_mounted(struct the_nilfs *, __u64, int);
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index a94e8bd..472cdf2 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -29,14 +29,12 @@
 #include <linux/init.h> /* module_init */
 #include <linux/inotify.h>
 #include <linux/kernel.h> /* roundup() */
-#include <linux/magic.h> /* superblock magic number */
-#include <linux/mount.h> /* mntget */
 #include <linux/namei.h> /* LOOKUP_FOLLOW */
-#include <linux/path.h> /* struct path */
 #include <linux/sched.h> /* struct user */
 #include <linux/slab.h> /* struct kmem_cache */
 #include <linux/syscalls.h>
 #include <linux/types.h>
+#include <linux/anon_inodes.h>
 #include <linux/uaccess.h>
 #include <linux/poll.h>
 #include <linux/wait.h>
@@ -45,8 +43,6 @@
 
 #include <asm/ioctls.h>
 
-static struct vfsmount *inotify_mnt __read_mostly;
-
 /* these are configurable via /proc/sys/fs/inotify/ */
 static int inotify_max_user_instances __read_mostly;
 static int inotify_max_queued_events __read_mostly;
@@ -645,9 +641,7 @@
 {
 	struct fsnotify_group *group;
 	struct user_struct *user;
-	struct file *filp;
-	struct path path;
-	int fd, ret;
+	int ret;
 
 	/* Check the IN_* constants for consistency.  */
 	BUILD_BUG_ON(IN_CLOEXEC != O_CLOEXEC);
@@ -656,10 +650,6 @@
 	if (flags & ~(IN_CLOEXEC | IN_NONBLOCK))
 		return -EINVAL;
 
-	fd = get_unused_fd_flags(flags & O_CLOEXEC);
-	if (fd < 0)
-		return fd;
-
 	user = get_current_user();
 	if (unlikely(atomic_read(&user->inotify_devs) >=
 			inotify_max_user_instances)) {
@@ -676,27 +666,14 @@
 
 	atomic_inc(&user->inotify_devs);
 
-	path.mnt = inotify_mnt;
-	path.dentry = inotify_mnt->mnt_root;
-	path_get(&path);
-	filp = alloc_file(&path, FMODE_READ, &inotify_fops);
-	if (!filp)
-		goto Enfile;
+	ret = anon_inode_getfd("inotify", &inotify_fops, group,
+				  O_RDONLY | flags);
+	if (ret >= 0)
+		return ret;
 
-	filp->f_flags = O_RDONLY | (flags & O_NONBLOCK);
-	filp->private_data = group;
-
-	fd_install(fd, filp);
-
-	return fd;
-
-Enfile:
-	ret = -ENFILE;
-	path_put(&path);
 	atomic_dec(&user->inotify_devs);
 out_free_uid:
 	free_uid(user);
-	put_unused_fd(fd);
 	return ret;
 }
 
@@ -783,20 +760,6 @@
 	return ret;
 }
 
-static int
-inotify_get_sb(struct file_system_type *fs_type, int flags,
-	       const char *dev_name, void *data, struct vfsmount *mnt)
-{
-	return get_sb_pseudo(fs_type, "inotify", NULL,
-			INOTIFYFS_SUPER_MAGIC, mnt);
-}
-
-static struct file_system_type inotify_fs_type = {
-    .name	= "inotifyfs",
-    .get_sb	= inotify_get_sb,
-    .kill_sb	= kill_anon_super,
-};
-
 /*
  * inotify_user_setup - Our initialization function.  Note that we cannnot return
  * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
@@ -804,16 +767,6 @@
  */
 static int __init inotify_user_setup(void)
 {
-	int ret;
-
-	ret = register_filesystem(&inotify_fs_type);
-	if (unlikely(ret))
-		panic("inotify: register_filesystem returned %d!\n", ret);
-
-	inotify_mnt = kern_mount(&inotify_fs_type);
-	if (IS_ERR(inotify_mnt))
-		panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt));
-
 	inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark_entry, SLAB_PANIC);
 	event_priv_cachep = KMEM_CACHE(inotify_event_private_data, SLAB_PANIC);
 
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
deleted file mode 100644
index 37c11e1..0000000
--- a/fs/ntfs/ChangeLog
+++ /dev/null
@@ -1,1702 +0,0 @@
-ToDo/Notes:
-	- Find and fix bugs.
-	- The only places in the kernel where a file is resized are
-	  ntfs_file_write*() and ntfs_truncate() for both of which i_mutex is
-	  held.  Just have to be careful in read-/writepage and other helpers
-	  not running under i_mutex that we play nice.  Also need to be careful
-	  with initialized_size extension in ntfs_file_write*() and writepage.
-	  UPDATE: The only things that need to be checked are the compressed
-	  write and the other attribute resize/write cases like index
-	  attributes, etc.  For now none of these are implemented so are safe.
-	- Implement filling in of holes in aops.c::ntfs_writepage() and its
-	  helpers.
-	- Implement mft.c::sync_mft_mirror_umount().  We currently will just
-	  leave the volume dirty on umount if the final iput(vol->mft_ino)
-	  causes a write of any mirrored mft records due to the mft mirror
-	  inode having been discarded already.  Whether this can actually ever
-	  happen is unclear however so it is worth waiting until someone hits
-	  the problem.
-
-2.1.29 - Fix a deadlock at mount time.
-
-	- During mount the VFS holds s_umount lock on the superblock.  So when
-	  we try to empty the journal $LogFile contents by calling
-	  ntfs_attr_set() when the machine does not have much memory and the
-	  journal is large ntfs_attr_set() results in the VM trying to balance
-	  dirty pages which in turn tries to that the s_umount lock and thus we
-	  get a deadlock.  The solution is to not use ntfs_attr_set() and
-	  instead do the zeroing by hand at the block level rather than page
-	  cache level.
-	- Fix sparse warnings.
-
-2.1.28 - Fix a deadlock.
-
-	- Fix deadlock in fs/ntfs/inode.c::ntfs_put_inode().  Thanks to Sergey
-	  Vlasov for the report and detailed analysis of the deadlock.  The fix
-	  involved getting rid of ntfs_put_inode() altogether and hence NTFS no
-	  longer has a ->put_inode super operation.
-
-2.1.27 - Various bug fixes and cleanups.
-
-	- Fix two compiler warnings on Alpha.  Thanks to Andrew Morton for
-	  reporting them.
-	- Fix an (innocent) off-by-one error in the runlist code.
-	- Fix a buggette in an "should be impossible" case handling where we
-	  continued the attribute lookup loop instead of aborting it.
-	- Use buffer_migrate_page() for the ->migratepage function of all ntfs
-	  address space operations.
-	- Fix comparison of $MFT and $MFTMirr to not bail out when there are
-	  unused, invalid mft records which are the same in both $MFT and
-	  $MFTMirr.
-	- Add support for sparse files which have a compression unit of 0.
-	- Remove all the make_bad_inode() calls.  This should only be called
-	  from read inode and new inode code paths.
-	- Limit name length in fs/ntfs/unistr.c::ntfs_nlstoucs() to maximum
-	  allowed by NTFS, i.e. 255 Unicode characters, not including the
-	  terminating NULL (which is not stored on disk).
-	- Improve comments on file attribute flags in fs/ntfs/layout.h.
-	- Fix a bug in fs/ntfs/inode.c::ntfs_read_locked_index_inode() where we
-	  forgot to update a temporary variable so loading index inodes which
-	  have an index allocation attribute failed.
-	- Add a missing call to flush_dcache_mft_record_page() in
-	  fs/ntfs/inode.c::ntfs_write_inode().
-	- Handle the recently introduced -ENAMETOOLONG return value from
-	  fs/ntfs/unistr.c::ntfs_nlstoucs() in fs/ntfs/namei.c::ntfs_lookup().
-	- Semaphore to mutex conversion.  (Ingo Molnar)
-
-2.1.26 - Minor bug fixes and updates.
-
-	- Fix a potential overflow in file.c where a cast to s64 was missing in
-	  a left shift of a page index.
-	- The struct inode has had its i_sem semaphore changed to a mutex named
-	  i_mutex.
-	- We have struct kmem_cache now so use it instead of the typedef
-	  kmem_cache_t.  (Pekka Enberg)
-	- Implement support for sector sizes above 512 bytes (up to the maximum
-	  supported by NTFS which is 4096 bytes).
-	- Do more detailed reporting of why we cannot mount read-write by
-	  special casing the VOLUME_MODIFIED_BY_CHKDSK flag.
-	- Miscellaneous updates to layout.h.
-	- Cope with attribute list attribute having invalid flags.  Windows
-	  copes with this and even chkdsk does not detect or fix this so we
-	  have to cope with it, too.  Thanks to Pawel Kot for reporting the
-	  problem.
-
-2.1.25 - (Almost) fully implement write(2) and truncate(2).
-
-	- Change ntfs_map_runlist_nolock(), ntfs_attr_find_vcn_nolock() and
-	  {__,}ntfs_cluster_free() to also take an optional attribute search
-	  context as argument.  This allows calling these functions with the
-	  mft record mapped.  Update all callers.
-	- Fix potential deadlock in ntfs_mft_data_extend_allocation_nolock()
-	  error handling by passing in the active search context when calling
-	  ntfs_cluster_free().
-	- Change ntfs_cluster_alloc() to take an extra boolean parameter
-	  specifying whether the cluster are being allocated to extend an
-	  attribute or to fill a hole.
-	- Change ntfs_attr_make_non_resident() to call ntfs_cluster_alloc()
-	  with @is_extension set to TRUE and remove the runlist terminator
-	  fixup code as this is now done by ntfs_cluster_alloc().
-	- Change ntfs_attr_make_non_resident to take the attribute value size
-	  as an extra parameter.  This is needed since we need to know the size
-	  before we can map the mft record and our callers always know it.  The
-	  reason we cannot simply read the size from the vfs inode i_size is
-	  that this is not necessarily uptodate.  This happens when
-	  ntfs_attr_make_non_resident() is called in the ->truncate call path.
-	- Fix ntfs_attr_make_non_resident() to update the vfs inode i_blocks
-	  which is zero for a resident attribute but should no longer be zero
-	  once the attribute is non-resident as it then has real clusters
-	  allocated.
-	- Add fs/ntfs/attrib.[hc]::ntfs_attr_extend_allocation(), a function to
-	  extend the allocation of an attributes.  Optionally, the data size,
-	  but not the initialized size can be extended, too.
-	- Implement fs/ntfs/inode.[hc]::ntfs_truncate().  It only supports
-	  uncompressed and unencrypted files and it never creates sparse files
-	  at least for the moment (making a file sparse requires us to modify
-	  its directory entries and we do not support directory operations at
-	  the moment).  Also, support for highly fragmented files, i.e. ones
-	  whose data attribute is split across multiple extents, is severly
-	  limited.  When such a case is encountered, EOPNOTSUPP is returned.
-	- Enable ATTR_SIZE attribute changes in ntfs_setattr().  This completes
-	  the initial implementation of file truncation.  Now both open(2)ing
-	  a file with the O_TRUNC flag and the {,f}truncate(2) system calls
-	  will resize a file appropriately.  The limitations are that only
-	  uncompressed and unencrypted files are supported.  Also, there is
-	  only very limited support for highly fragmented files (the ones whose
-	  $DATA attribute is split into multiple attribute extents).
-	- In attrib.c::ntfs_attr_set() call balance_dirty_pages_ratelimited()
-	  and cond_resched() in the main loop as we could be dirtying a lot of
-	  pages and this ensures we play nice with the VM and the system as a
-	  whole.
-	- Implement file operations ->write, ->aio_write, ->writev for regular
-	  files.  This replaces the old use of generic_file_write(), et al and
-	  the address space operations ->prepare_write and ->commit_write.
-	  This means that both sparse and non-sparse (unencrypted and
-	  uncompressed) files can now be extended using the normal write(2)
-	  code path.  There are two limitations at present and these are that
-	  we never create sparse files and that we only have limited support
-	  for highly fragmented files, i.e. ones whose data attribute is split
-	  across multiple extents.   When such a case is encountered,
-	  EOPNOTSUPP is returned.
-	- $EA attributes can be both resident and non-resident.
-	- Use %z for size_t to fix compilation warnings.  (Andrew Morton)
-	- Fix compilation warnings with gcc-4.0.2 on SUSE 10.0.
-	- Document extended attribute ($EA) NEED_EA flag.  (Based on libntfs
-	  patch by Yura Pakhuchiy.)
-
-2.1.24 - Lots of bug fixes and support more clean journal states.
-
-	- Support journals ($LogFile) which have been modified by chkdsk.  This
-	  means users can boot into Windows after we marked the volume dirty.
-	  The Windows boot will run chkdsk and then reboot.  The user can then
-	  immediately boot into Linux rather than having to do a full Windows
-	  boot first before rebooting into Linux and we will recognize such a
-	  journal and empty it as it is clean by definition.  Note, this only
-	  works if chkdsk left the journal in an obviously clean state.
-	- Support journals ($LogFile) with only one restart page as well as
-	  journals with two different restart pages.  We sanity check both and
-	  either use the only sane one or the more recent one of the two in the
-	  case that both are valid.
-	- Add fs/ntfs/malloc.h::ntfs_malloc_nofs_nofail() which is analogous to
-	  ntfs_malloc_nofs() but it performs allocations with __GFP_NOFAIL and
-	  hence cannot fail.
-	- Use ntfs_malloc_nofs_nofail() in the two critical regions in
-	  fs/ntfs/runlist.c::ntfs_runlists_merge().  This means we no longer
-	  need to panic() if the allocation fails as it now cannot fail.
-	- Fix two nasty runlist merging bugs that had gone unnoticed so far.
-	  Thanks to Stefano Picerno for the bug report.
-	- Remove two bogus BUG_ON()s from fs/ntfs/mft.c.
-	- Fix handling of valid but empty mapping pairs array in
-	  fs/ntfs/runlist.c::ntfs_mapping_pairs_decompress().
-	- Report unrepresentable inodes during ntfs_readdir() as KERN_WARNING
-	  messages and include the inode number.  Thanks to Yura Pakhuchiy for
-	  pointing this out.
-	- Change ntfs_rl_truncate_nolock() to throw away the runlist if the new
-	  length is zero.
-	- Add runlist.[hc]::ntfs_rl_punch_nolock() which punches a caller
-	  specified hole into a runlist.
-	- Fix a bug in fs/ntfs/index.c::ntfs_index_lookup().  When the returned
-	  index entry is in the index root, we forgot to set the @ir pointer in
-	  the index context.  Thanks to Yura Pakhuchiy for finding this bug.
-	- Remove bogus setting of PageError in ntfs_read_compressed_block().
-	- Add fs/ntfs/attrib.[hc]::ntfs_resident_attr_value_resize().
-	- Fix a bug in ntfs_map_runlist_nolock() where we forgot to protect
-	  access to the allocated size in the ntfs inode with the size lock.
-	- Fix ntfs_attr_vcn_to_lcn_nolock() and ntfs_attr_find_vcn_nolock() to
-	  return LCN_ENOENT when there is no runlist and the allocated size is
-	  zero.
-	- Fix load_attribute_list() to handle the case of a NULL runlist.
-	- Fix handling of sparse attributes in ntfs_attr_make_non_resident().
-	- Add BUG() checks to ntfs_attr_make_non_resident() and ntfs_attr_set()
-	  to ensure that these functions are never called for compressed or
-	  encrypted attributes.
-	- Fix cluster (de)allocators to work when the runlist is NULL and more
-	  importantly to take a locked runlist rather than them locking it
-	  which leads to lock reversal.
-	- Truncate {a,c,m}time to the ntfs supported time granularity when
-	  updating the times in the inode in ntfs_setattr().
-	- Fixup handling of sparse, compressed, and encrypted attributes in
-	  fs/ntfs/inode.c::ntfs_read_locked_{,attr_,index_}inode(),
-	  fs/ntfs/aops.c::ntfs_{read,write}page().
-	- Make ntfs_write_block() not instantiate sparse blocks if they contain
-	  only zeroes.
-	- Optimize fs/ntfs/aops.c::ntfs_write_block() by extending the page
-	  lock protection over the buffer submission for i/o which allows the
-	  removal of the get_bh()/put_bh() pairs for each buffer.
-	- Fix fs/ntfs/aops.c::ntfs_{read,write}_block() to handle the case
-	  where a concurrent truncate has truncated the runlist under our feet.
-	- Fix page_has_buffers()/page_buffers() handling in fs/ntfs/aops.c.
-	- In fs/ntfs/aops.c::ntfs_end_buffer_async_read(), use a bit spin lock
-	  in the first buffer head instead of a driver global spin lock to
-	  improve scalability.
-	- Minor fix to error handling and error message display in
-	  fs/ntfs/aops.c::ntfs_prepare_nonresident_write().
-	- Change the mount options {u,f,d}mask to always parse the number as
-	  an octal number to conform to how chmod(1) works, too.  Thanks to
-	  Giuseppe Bilotta and Horst von Brand for pointing out the errors of
-	  my ways.
-	- Fix various bugs in the runlist merging code.  (Based on libntfs
-	  changes by Richard Russon.)
-	- Fix sparse warnings that have crept in over time.
-	- Change ntfs_cluster_free() to require a write locked runlist on entry
-	  since we otherwise get into a lock reversal deadlock if a read locked
-	  runlist is passed in. In the process also change it to take an ntfs
-	  inode instead of a vfs inode as parameter.
-	- Fix the definition of the CHKD ntfs record magic.  It had an off by
-	  two error causing it to be CHKB instead of CHKD.
-	- Fix a stupid bug in __ntfs_bitmap_set_bits_in_run() which caused the
-	  count to become negative and hence we had a wild memset() scribbling
-	  all over the system's ram.
-
-2.1.23 - Implement extension of resident files and make writing safe as well as
-	 many bug fixes, cleanups, and enhancements...
-
-	- Add printk rate limiting for ntfs_warning() and ntfs_error() when
-	  compiled without debug.  This avoids a possible denial of service
-	  attack.  Thanks to Carl-Daniel Hailfinger from SuSE for pointing this
-	  out.
-	- Fix compilation warnings on ia64.  (Randy Dunlap)
-	- Use i_size_{read,write}() instead of reading i_size by hand and cache
-	  the value where apropriate.
-	- Add size_lock to the ntfs_inode structure.  This is an rw spinlock
-	  and it locks against access to the inode sizes.  Note, ->size_lock
-	  is also accessed from irq context so you must use the _irqsave and
-	  _irqrestore lock and unlock functions, respectively.  Protect all
-	  accesses to allocated_size, initialized_size, and compressed_size.
-	- Minor optimization to fs/ntfs/super.c::ntfs_statfs() and its helpers.
-	- Implement extension of resident files in the regular file write code
-	  paths (fs/ntfs/aops.c::ntfs_{prepare,commit}_write()).  At present
-	  this only works until the data attribute becomes too big for the mft
-	  record after which we abort the write returning -EOPNOTSUPP from
-	  ntfs_prepare_write().
-	- Add disable_sparse mount option together with a per volume sparse
-	  enable bit which is set appropriately and a per inode sparse disable
-	  bit which is preset on some system file inodes as appropriate.
-	- Enforce that sparse support is disabled on NTFS volumes pre 3.0.
-	- Fix a bug in fs/ntfs/runlist.c::ntfs_mapping_pairs_decompress() in
-	  the creation of the unmapped runlist element for the base attribute
-	  extent.
-	- Split ntfs_map_runlist() into ntfs_map_runlist() and a non-locking
-	  helper ntfs_map_runlist_nolock() which is used by ntfs_map_runlist().
-	  This allows us to map runlist fragments with the runlist lock already
-	  held without having to drop and reacquire it around the call.  Adapt
-	  all callers.
-	- Change ntfs_find_vcn() to ntfs_find_vcn_nolock() which takes a locked
-	  runlist.  This allows us to find runlist elements with the runlist
-	  lock already held without having to drop and reacquire it around the
-	  call.  Adapt all callers.
-	- Change time to u64 in time.h::ntfs2utc() as it otherwise generates a
-	  warning in the do_div() call on sparc32.  Thanks to Meelis Roos for
-	  the report and analysis of the warning.
-	- Fix a nasty runlist merge bug when merging two holes.
-	- Set the ntfs_inode->allocated_size to the real allocated size in the
-	  mft record for resident attributes (fs/ntfs/inode.c).
-	- Small readability cleanup to use "a" instead of "ctx->attr"
-	  everywhere (fs/ntfs/inode.c).
-	- Make fs/ntfs/namei.c::ntfs_get_{parent,dentry} static and move the
-	  definition of ntfs_export_ops from fs/ntfs/super.c to namei.c.  Also,
-	  declare ntfs_export_ops in fs/ntfs/ntfs.h.
-	- Correct sparse file handling.  The compressed values need to be
-	  checked and set in the ntfs inode as done for compressed files and
-	  the compressed size needs to be used for vfs inode->i_blocks instead
-	  of the allocated size, again, as done for compressed files.
-	- Add AT_EA in addition to AT_DATA to whitelist for being allowed to be
-	  non-resident in fs/ntfs/attrib.c::ntfs_attr_can_be_non_resident().
-	- Add fs/ntfs/attrib.c::ntfs_attr_vcn_to_lcn_nolock() used by the new
-	  write code.
-	- Fix bug in fs/ntfs/attrib.c::ntfs_find_vcn_nolock() where after
-	  dropping the read lock and taking the write lock we were not checking
-	  whether someone else did not already do the work we wanted to do.
-	- Rename fs/ntfs/attrib.c::ntfs_find_vcn_nolock() to
-	  ntfs_attr_find_vcn_nolock() and update all callers.
-	- Add fs/ntfs/attrib.[hc]::ntfs_attr_make_non_resident().
-	- Fix sign of various error return values to be negative in
-	  fs/ntfs/lcnalloc.c.
-	- Modify ->readpage and ->writepage (fs/ntfs/aops.c) so they detect and
-	  handle the case where an attribute is converted from resident to
-	  non-resident by a concurrent file write.
-	- Remove checks for NULL before calling kfree() since kfree() does the
-	  checking itself.  (Jesper Juhl)
-	- Some utilities modify the boot sector but do not update the checksum.
-	  Thus, relax the checking in fs/ntfs/super.c::is_boot_sector_ntfs() to
-	  only emit a warning when the checksum is incorrect rather than
-	  refusing the mount.  Thanks to Bernd Casimir for pointing this
-	  problem out.
-	- Update attribute definition handling.
-	- Add NTFS_MAX_CLUSTER_SIZE and NTFS_MAX_PAGES_PER_CLUSTER constants.
-	- Use NTFS_MAX_CLUSTER_SIZE in super.c instead of hard coding 0x10000.
-	- Use MAX_BUF_PER_PAGE instead of variable sized array allocation for
-	  better code generation and one less sparse warning in fs/ntfs/aops.c.
-	- Remove spurious void pointer casts from fs/ntfs/.  (Pekka Enberg)
-	- Use C99 style structure initialization after memory allocation where
-	  possible (fs/ntfs/{attrib.c,index.c,super.c}).  Thanks to Al Viro and
-	  Pekka Enberg.
-	- Stamp the transaction log ($UsnJrnl), aka user space journal, if it
-	  is active on the volume and we are mounting read-write or remounting
-	  from read-only to read-write.
-	- Fix a bug in address space operations error recovery code paths where
-	  if the runlist was not mapped at all and a mapping error occured we
-	  would leave the runlist locked on exit to the function so that the
-	  next access to the same file would try to take the lock and deadlock.
-	- Detect the case when Windows has been suspended to disk on the volume
-	  to be mounted and if this is the case do not allow (re)mounting
-	  read-write.  This is done by parsing hiberfil.sys if present.
-	- Fix several occurences of a bug where we would perform 'var & ~const'
-	  with a 64-bit variable and a int, i.e. 32-bit, constant.  This causes
-	  the higher order 32-bits of the 64-bit variable to be zeroed.  To fix
-	  this cast the 'const' to the same 64-bit type as 'var'.
-	- Change the runlist terminator of the newly allocated cluster(s) to
-	  LCN_ENOENT in ntfs_attr_make_non_resident().  Otherwise the runlist
-	  code gets confused.
-	- Add an extra parameter @last_vcn to ntfs_get_size_for_mapping_pairs()
-	  and ntfs_mapping_pairs_build() to allow the runlist encoding to be
-	  partial which is desirable when filling holes in sparse attributes.
-	  Update all callers.
-	- Change ntfs_map_runlist_nolock() to only decompress the mapping pairs
-	  if the requested vcn is inside it.  Otherwise we get into problems
-	  when we try to map an out of bounds vcn because we then try to map
-	  the already mapped runlist fragment which causes
-	  ntfs_mapping_pairs_decompress() to fail and return error.  Update
-	  ntfs_attr_find_vcn_nolock() accordingly.
-	- Fix a nasty deadlock that appeared in recent kernels.
-	  The situation: VFS inode X on a mounted ntfs volume is dirty.  For
-	  same inode X, the ntfs_inode is dirty and thus corresponding on-disk
-	  inode, i.e. mft record, which is in a dirty PAGE_CACHE_PAGE belonging
-	  to the table of inodes, i.e. $MFT, inode 0.
-	  What happens:
-	  Process 1: sys_sync()/umount()/whatever...  calls
-	  __sync_single_inode() for $MFT -> do_writepages() -> write_page for
-	  the dirty page containing the on-disk inode X, the page is now locked
-	  -> ntfs_write_mst_block() which clears PageUptodate() on the page to
-	  prevent anyone else getting hold of it whilst it does the write out.
-	  This is necessary as the on-disk inode needs "fixups" applied before
-	  the write to disk which are removed again after the write and
-	  PageUptodate is then set again.  It then analyses the page looking
-	  for dirty on-disk inodes and when it finds one it calls
-	  ntfs_may_write_mft_record() to see if it is safe to write this
-	  on-disk inode.  This then calls ilookup5() to check if the
-	  corresponding VFS inode is in icache().  This in turn calls ifind()
-	  which waits on the inode lock via wait_on_inode whilst holding the
-	  global inode_lock.
-	  Process 2: pdflush results in a call to __sync_single_inode for the
-	  same VFS inode X on the ntfs volume.  This locks the inode (I_LOCK)
-	  then calls write-inode -> ntfs_write_inode -> map_mft_record() ->
-	  read_cache_page() for the page (in page cache of table of inodes
-	  $MFT, inode 0) containing the on-disk inode.  This page has
-	  PageUptodate() clear because of Process 1 (see above) so
-	  read_cache_page() blocks when it tries to take the page lock for the
-	  page so it can call ntfs_read_page().
-	  Thus Process 1 is holding the page lock on the page containing the
-	  on-disk inode X and it is waiting on the inode X to be unlocked in
-	  ifind() so it can write the page out and then unlock the page.
-	  And Process 2 is holding the inode lock on inode X and is waiting for
-	  the page to be unlocked so it can call ntfs_readpage() or discover
-	  that Process 1 set PageUptodate() again and use the page.
-	  Thus we have a deadlock due to ifind() waiting on the inode lock.
-	  The solution: The fix is to use the newly introduced
-	  ilookup5_nowait() which does not wait on the inode's lock and hence
-	  avoids the deadlock.  This is safe as we do not care about the VFS
-	  inode and only use the fact that it is in the VFS inode cache and the
-	  fact that the vfs and ntfs inodes are one struct in memory to find
-	  the ntfs inode in memory if present.  Also, the ntfs inode has its
-	  own locking so it does not matter if the vfs inode is locked.
-	- Fix bug in mft record writing where we forgot to set the device in
-	  the buffers when mapping them after the VM had discarded them.
-	  Thanks to Martin MOKREJÅ for the bug report.
-
-2.1.22 - Many bug and race fixes and error handling improvements.
-
-	- Improve error handling in fs/ntfs/inode.c::ntfs_truncate().
-	- Change fs/ntfs/inode.c::ntfs_truncate() to return an error code
-	  instead of void and provide a helper ntfs_truncate_vfs() for the
-	  vfs ->truncate method.
-	- Add a new ntfs inode flag NInoTruncateFailed() and modify
-	  fs/ntfs/inode.c::ntfs_truncate() to set and clear it appropriately.
-	- Fix min_size and max_size definitions in ATTR_DEF structure in
-	  fs/ntfs/layout.h to be signed.
-	- Add attribute definition handling helpers to fs/ntfs/attrib.[hc]:
-	  ntfs_attr_size_bounds_check(), ntfs_attr_can_be_non_resident(), and
-	  ntfs_attr_can_be_resident(), which in turn use the new private helper
-	  ntfs_attr_find_in_attrdef().
-	- In fs/ntfs/aops.c::mark_ntfs_record_dirty(), take the
-	  mapping->private_lock around the dirtying of the buffer heads
-	  analagous to the way it is done in __set_page_dirty_buffers().
-	- Ensure the mft record size does not exceed the PAGE_CACHE_SIZE at
-	  mount time as this cannot work with the current implementation.
-	- Check for location of attribute name and improve error handling in
-	  general in fs/ntfs/inode.c::ntfs_read_locked_inode() and friends.
-	- In fs/ntfs/aops.c::ntfs_writepage(), if the page is fully outside
-	  i_size, i.e. race with truncate, invalidate the buffers on the page
-	  so that they become freeable and hence the page does not leak.
-	- Remove unused function fs/ntfs/runlist.c::ntfs_rl_merge().  (Adrian
-	  Bunk)
-	- Fix stupid bug in fs/ntfs/attrib.c::ntfs_attr_find() that resulted in
-	  a NULL pointer dereference in the error code path when a corrupt
-	  attribute was found.  (Thanks to Domen Puncer for the bug report.)
-	- Add MODULE_VERSION() to fs/ntfs/super.c.
-	- Make several functions and variables static.  (Adrian Bunk)
-	- Modify fs/ntfs/aops.c::mark_ntfs_record_dirty() so it allocates
-	  buffers for the page if they are not present and then marks the
-	  buffers belonging to the ntfs record dirty.  This causes the buffers
-	  to become busy and hence they are safe from removal until the page
-	  has been written out.
-	- Fix stupid bug in fs/ntfs/attrib.c::ntfs_external_attr_find() in the
-	  error handling code path that resulted in a BUG() due to trying to
-	  unmap an extent mft record when the mapping of it had failed and it
-	  thus was not mapped.  (Thanks to Ken MacFerrin for the bug report.)
-	- Drop the runlist lock after the vcn has been read in
-	  fs/ntfs/lcnalloc.c::__ntfs_cluster_free().
-	- Rewrite handling of multi sector transfer errors.  We now do not set
-	  PageError() when such errors are detected in the async i/o handler
-	  fs/ntfs/aops.c::ntfs_end_buffer_async_read().  All users of mst
-	  protected attributes now check the magic of each ntfs record as they
-	  use it and act appropriately.  This has the effect of making errors
-	  granular per ntfs record rather than per page which solves the case
-	  where we cannot access any of the ntfs records in a page when a
-	  single one of them had an mst error.  (Thanks to Ken MacFerrin for
-	  the bug report.)
-	- Fix error handling in fs/ntfs/quota.c::ntfs_mark_quotas_out_of_date()
-	  where we failed to release i_mutex on the $Quota/$Q attribute inode.
-	- Fix bug in handling of bad inodes in fs/ntfs/namei.c::ntfs_lookup().
-	- Add mapping of unmapped buffers to all remaining code paths, i.e.
-	  fs/ntfs/aops.c::ntfs_write_mst_block(), mft.c::ntfs_sync_mft_mirror(),
-	  and write_mft_record_nolock().  From now on we require that the
-	  complete runlist for the mft mirror is always mapped into memory.
-	- Add creation of buffers to fs/ntfs/mft.c::ntfs_sync_mft_mirror().
-	- Improve error handling in fs/ntfs/aops.c::ntfs_{read,write}_block().
-	- Cleanup fs/ntfs/aops.c::ntfs_{read,write}page() since we know that a
-	  resident attribute will be smaller than a page which makes the code
-	  simpler.  Also make the code more tolerant to concurrent ->truncate.
-
-2.1.21 - Fix some races and bugs, rewrite mft write code, add mft allocator.
-
-	- Implement extent mft record deallocation
-	  fs/ntfs/mft.c::ntfs_extent_mft_record_free().
-	- Splitt runlist related functions off from attrib.[hc] to runlist.[hc].
-	- Add vol->mft_data_pos and initialize it at mount time.
-	- Rename init_runlist() to ntfs_init_runlist(), ntfs_vcn_to_lcn() to
-	  ntfs_rl_vcn_to_lcn(), decompress_mapping_pairs() to
-	  ntfs_mapping_pairs_decompress(), ntfs_merge_runlists() to
-	  ntfs_runlists_merge() and adapt all callers.
-	- Add fs/ntfs/runlist.[hc]::ntfs_get_nr_significant_bytes(),
-	  ntfs_get_size_for_mapping_pairs(), ntfs_write_significant_bytes(),
-	  and ntfs_mapping_pairs_build(), adapted from libntfs.
-	- Make fs/ntfs/lcnalloc.c::ntfs_cluster_free_from_rl_nolock() not
-	  static and add a declaration for it to lcnalloc.h.
-	- Add fs/ntfs/lcnalloc.h::ntfs_cluster_free_from_rl() which is a static
-	  inline wrapper for ntfs_cluster_free_from_rl_nolock() which takes the
-	  cluster bitmap lock for the duration of the call.
-	- Add fs/ntfs/attrib.[hc]::ntfs_attr_record_resize().
-	- Implement the equivalent of memset() for an ntfs attribute in
-	  fs/ntfs/attrib.[hc]::ntfs_attr_set() and switch
-	  fs/ntfs/logfile.c::ntfs_empty_logfile() to using it.
-	- Remove unnecessary casts from LCN_* constants.
-	- Implement fs/ntfs/runlist.c::ntfs_rl_truncate_nolock().
-	- Add MFT_RECORD_OLD as a copy of MFT_RECORD in fs/ntfs/layout.h and
-	  change MFT_RECORD to contain the NTFS 3.1+ specific fields.
-	- Add a helper function fs/ntfs/aops.c::mark_ntfs_record_dirty() which
-	  marks all buffers belonging to an ntfs record dirty, followed by
-	  marking the page the ntfs record is in dirty and also marking the vfs
-	  inode containing the ntfs record dirty (I_DIRTY_PAGES).
-	- Switch fs/ntfs/index.h::ntfs_index_entry_mark_dirty() to using the
-	  new helper fs/ntfs/aops.c::mark_ntfs_record_dirty() and remove the no
-	  longer needed fs/ntfs/index.[hc]::__ntfs_index_entry_mark_dirty().
-	- Move ntfs_{un,}map_page() from ntfs.h to aops.h and fix resulting
-	  include errors.
-	- Move the typedefs for runlist_element and runlist from types.h to
-	  runlist.h and fix resulting include errors.
-	- Remove unused {__,}format_mft_record() from fs/ntfs/mft.c.
-	- Modify fs/ntfs/mft.c::__mark_mft_record_dirty() to use the helper
-	  mark_ntfs_record_dirty() which also changes the behaviour in that we
-	  now set the buffers belonging to the mft record dirty as well as the
-	  page itself.
-	- Update fs/ntfs/mft.c::write_mft_record_nolock() and sync_mft_mirror()
-	  to cope with the fact that there now are dirty buffers in mft pages.
-	- Update fs/ntfs/inode.c::ntfs_write_inode() to also use the helper
-	  mark_ntfs_record_dirty() and thus to set the buffers belonging to the
-	  mft record dirty as well as the page itself.
-	- Fix compiler warnings on x86-64 in fs/ntfs/dir.c.  (Randy Dunlap,
-	  slightly modified by me)
-	- Add fs/ntfs/mft.c::try_map_mft_record() which fails with -EALREADY if
-	  the mft record is already locked and otherwise behaves the same way
-	  as fs/ntfs/mft.c::map_mft_record().
-	- Modify fs/ntfs/mft.c::write_mft_record_nolock() so that it only
-	  writes the mft record if the buffers belonging to it are dirty.
-	  Otherwise we assume that it was written out by other means already.
-	- Attempting to write outside initialized size is _not_ a bug so remove
-	  the bug check from fs/ntfs/aops.c::ntfs_write_mst_block().  It is in
-	  fact required to write outside initialized size when preparing to
-	  extend the initialized size.
-	- Map the page instead of using page_address() before writing to it in
-	  fs/ntfs/aops.c::ntfs_mft_writepage().
-	- Provide exclusion between opening an inode / mapping an mft record
-	  and accessing the mft record in fs/ntfs/mft.c::ntfs_mft_writepage()
-	  by setting the page not uptodate throughout ntfs_mft_writepage().
-	- Clear the page uptodate flag in fs/ntfs/aops.c::ntfs_write_mst_block()
-	  to ensure noone can see the page whilst the mst fixups are applied.
-	- Add the helper fs/ntfs/mft.c::ntfs_may_write_mft_record() which
-	  checks if an mft record may be written out safely obtaining any
-	  necessary locks in the process.  This is used by
-	  fs/ntfs/aops.c::ntfs_write_mst_block().
-	- Modify fs/ntfs/aops.c::ntfs_write_mst_block() to also work for
-	  writing mft records and improve its error handling in the process.
-	  Now if any of the records in the page fail to be written out, all
-	  other records will be written out instead of aborting completely.
-	- Remove ntfs_mft_aops and update all users to use ntfs_mst_aops.
-	- Modify fs/ntfs/inode.c::ntfs_read_locked_inode() to set the
-	  ntfs_mst_aops for all inodes which are NInoMstProtected() and
-	  ntfs_aops for all other inodes.
-	- Rename fs/ntfs/mft.c::sync_mft_mirror{,_umount}() to
-	  ntfs_sync_mft_mirror{,_umount}() and change their parameters so they
-	  no longer require an ntfs inode to be present.  Update all callers.
-	- Cleanup the error handling in fs/ntfs/mft.c::ntfs_sync_mft_mirror().
-	- Clear the page uptodate flag in fs/ntfs/mft.c::ntfs_sync_mft_mirror()
-	  to ensure noone can see the page whilst the mst fixups are applied.
-	- Remove the no longer needed fs/ntfs/mft.c::ntfs_mft_writepage() and
-	  fs/ntfs/mft.c::try_map_mft_record().
-	- Fix callers of fs/ntfs/aops.c::mark_ntfs_record_dirty() to call it
-	  with the ntfs inode which contains the page rather than the ntfs
-	  inode the mft record of which is in the page.
-	- Fix race condition in fs/ntfs/inode.c::ntfs_put_inode() by moving the
-	  index inode bitmap inode release code from there to
-	  fs/ntfs/inode.c::ntfs_clear_big_inode().  (Thanks to Christoph
-	  Hellwig for spotting this.)
-	- Fix race condition in fs/ntfs/inode.c::ntfs_put_inode() by taking the
-	  inode semaphore around the code that sets ni->itype.index.bmp_ino to
-	  NULL and reorganize the code to optimize it a bit.  (Thanks to
-	  Christoph Hellwig for spotting this.)
-	- Modify fs/ntfs/aops.c::mark_ntfs_record_dirty() to no longer take the
-	  ntfs inode as a parameter as this is confusing and misleading and the
-	  needed ntfs inode is available via NTFS_I(page->mapping->host).
-	  Adapt all callers to this change.
-	- Modify fs/ntfs/mft.c::write_mft_record_nolock() and
-	  fs/ntfs/aops.c::ntfs_write_mst_block() to only check the dirty state
-	  of the first buffer in a record and to take this as the ntfs record
-	  dirty state.  We cannot look at the dirty state for subsequent
-	  buffers because we might be racing with
-	  fs/ntfs/aops.c::mark_ntfs_record_dirty().
-	- Move the static inline ntfs_init_big_inode() from fs/ntfs/inode.c to
-	  inode.h and make fs/ntfs/inode.c::__ntfs_init_inode() non-static and
-	  add a declaration for it to inode.h.  Fix some compilation issues
-	  that resulted due to #includes and header file interdependencies.
-	- Simplify setup of i_mode in fs/ntfs/inode.c::ntfs_read_locked_inode().
-	- Add helpers fs/ntfs/layout.h::MK_MREF() and MK_LE_MREF().
-	- Modify fs/ntfs/mft.c::map_extent_mft_record() to only verify the mft
-	  record sequence number if it is specified (i.e. not zero).
-	- Add fs/ntfs/mft.[hc]::ntfs_mft_record_alloc() and various helper
-	  functions used by it.
-	- Update Documentation/filesystems/ntfs.txt with instructions on how to
-	  use the Device-Mapper driver with NTFS ftdisk/LDM raid.  This removes
-	  the linear raid problem with the Software RAID / MD driver when one
-	  or more of the devices has an odd number of sectors.
-
-2.1.20 - Fix two stupid bugs introduced in 2.1.18 release.
-
-	- Fix stupid bug in fs/ntfs/attrib.c::ntfs_attr_reinit_search_ctx()
-	  where we did not clear ctx->al_entry but it was still set due to
-	  changes in ntfs_attr_lookup() and ntfs_external_attr_find() in
-	  particular.
-	- Fix another stupid bug in fs/ntfs/attrib.c::ntfs_external_attr_find()
-	  where we forgot to unmap the extent mft record when we had finished
-	  enumerating an attribute which caused a bug check to trigger when the
-	  VFS calls ->clear_inode.
-
-2.1.19 - Many cleanups, improvements, and a minor bug fix.
-
-	- Update ->setattr (fs/ntfs/inode.c::ntfs_setattr()) to refuse to
-	  change the uid, gid, and mode of an inode as we do not support NTFS
-	  ACLs yet.
-	- Remove BKL use from ntfs_setattr() syncing up with the rest of the
-	  kernel.
-	- Get rid of the ugly transparent union in fs/ntfs/dir.c::ntfs_readdir()
-	  and ntfs_filldir() as per suggestion from Al Viro.
-	- Change '\0' and L'\0' to simply 0 as per advice from Linus Torvalds.
-	- Update ->truncate (fs/ntfs/inode.c::ntfs_truncate()) to check if the
-	  inode size has changed and to only output an error if so.
-	- Rename fs/ntfs/attrib.h::attribute_value_length() to ntfs_attr_size().
-	- Add le{16,32,64} as well as sle{16,32,64} data types to
-	  fs/ntfs/types.h.
-	- Change ntfschar to be le16 instead of u16 in fs/ntfs/types.h.
-	- Add le versions of VCN, LCN, and LSN called leVCN, leLCN, and leLSN,
-	  respectively, to fs/ntfs/types.h.
-	- Update endianness conversion macros in fs/ntfs/endian.h to use the
-	  new types as appropriate.
-	- Do proper type casting when using sle64_to_cpup() in fs/ntfs/dir.c
-	  and index.c.
-	- Add leMFT_REF data type to fs/ntfs/layout.h.
-	- Update all NTFS header files with the new little endian data types.
-	  Affected files are fs/ntfs/layout.h, logfile.h, and time.h.
-	- Do proper type casting when using ntfs_is_*_recordp() in
-	  fs/ntfs/logfile.c, mft.c, and super.c. 
-	- Fix all the sparse bitwise warnings.  Had to change all the typedef
-	  enums storing little endian values to simple enums plus a typedef for
-	  the datatype to make sparse happy.
-	- Fix a bug found by the new sparse bitwise warnings where the default
-	  upcase table was defined as a pointer to wchar_t rather than ntfschar
-	  in fs/ntfs/ntfs.h and super.c.
-	- Change {const_,}cpu_to_le{16,32}(0) to just 0 as suggested by Al Viro.
-
-2.1.18 - Fix scheduling latencies at mount time as well as an endianness bug.
-
-	- Remove vol->nr_mft_records as it was pretty meaningless and optimize
-	  the calculation of total/free inodes as used by statfs().
-	- Fix scheduling latencies in ntfs_fill_super() by dropping the BKL
-	  because the code itself is using the ntfs_lock semaphore which
-	  provides safe locking.  (Ingo Molnar)
-	- Fix a potential bug in fs/ntfs/mft.c::map_extent_mft_record() that
-	  could occur in the future for when we start closing/freeing extent
-	  inodes if we don't set base_ni->ext.extent_ntfs_inos to NULL after
-	  we free it.
-	- Rename {find,lookup}_attr() to ntfs_attr_{find,lookup}() as well as
-	  find_external_attr() to ntfs_external_attr_find() to cleanup the
-	  namespace a bit and to be more consistent with libntfs.
-	- Rename {{re,}init,get,put}_attr_search_ctx() to
-	  ntfs_attr_{{re,}init,get,put}_search_ctx() as well as the type
-	  attr_search_context to ntfs_attr_search_ctx.
-	- Force use of ntfs_attr_find() in ntfs_attr_lookup() when searching
-	  for the attribute list attribute itself.
-	- Fix endianness bug in ntfs_external_attr_find().
-	- Change ntfs_{external_,}attr_find() to return 0 on success, -ENOENT
-	  if the attribute is not found, and -EIO on real error.  In the case
-	  of -ENOENT, the search context is updated to describe the attribute
-	  before which the attribute being searched for would need to be
-	  inserted if such an action were to be desired and in the case of
-	  ntfs_external_attr_find() the search context is also updated to
-	  indicate the attribute list entry before which the attribute list
-	  entry of the attribute being searched for would need to be inserted
-	  if such an action were to be desired.  Also make ntfs_find_attr()
-	  static and remove its prototype from attrib.h as it is not used
-	  anywhere other than attrib.c.  Update ntfs_attr_lookup() and all
-	  callers of ntfs_{external,}attr_{find,lookup}() for the new return
-	  values.
-	- Minor cleanup of fs/ntfs/inode.c::ntfs_init_locked_inode().
-
-2.1.17 - Fix bugs in mount time error code paths and other updates.
-
-	- Implement bitmap modification code (fs/ntfs/bitmap.[hc]).  This
-	  includes functions to set/clear a single bit or a run of bits.
-	- Add fs/ntfs/attrib.[hc]::ntfs_find_vcn() which returns the locked
-	  runlist element containing a particular vcn.  It also takes care of
-	  mapping any needed runlist fragments.
-	- Implement cluster (de-)allocation code (fs/ntfs/lcnalloc.[hc]).
-	- Load attribute definition table from $AttrDef at mount time.
-	- Fix bugs in mount time error code paths involving (de)allocation of
-	  the default and volume upcase tables.
-	- Remove ntfs_nr_mounts as it is no longer used.
-
-2.1.16 - Implement access time updates, file sync, async io, and read/writev.
-
-	- Add support for readv/writev and aio_read/aio_write (fs/ntfs/file.c).
-	  This is done by setting the appropriate file operations pointers to
-	  the generic helper functions provided by mm/filemap.c.
-	- Implement fsync, fdatasync, and msync both for files (fs/ntfs/file.c)
-	  and directories (fs/ntfs/dir.c).
-	- Add support for {a,m,c}time updates to inode.c::ntfs_write_inode().
-	  Note, except for the root directory and any other system files opened
-	  by the user, the system files will not have their access times
-	  updated as they are only accessed at the inode level an hence the
-	  file level functions which cause the times to be updated are never
-	  invoked.
-
-2.1.15 - Invalidate quotas when (re)mounting read-write.
-
-	- Add new element itype.index.collation_rule to the ntfs inode
-	  structure and set it appropriately in ntfs_read_locked_inode().
-	- Implement a new inode type "index" to allow efficient access to the
-	  indices found in various system files and adapt inode handling
-	  accordingly (fs/ntfs/inode.[hc]).  An index inode is essentially an
-	  attribute inode (NInoAttr() is true) with an attribute type of
-	  AT_INDEX_ALLOCATION.  As such, it is no longer allowed to call
-	  ntfs_attr_iget() with an attribute type of AT_INDEX_ALLOCATION as
-	  there would be no way to distinguish between normal attribute inodes
-	  and index inodes.  The function to obtain an index inode is
-	  ntfs_index_iget() and it uses the helper function
-	  ntfs_read_locked_index_inode().  Note, we do not overload
-	  ntfs_attr_iget() as indices consist of multiple attributes so using
-	  ntfs_attr_iget() to obtain an index inode would be confusing.
-	- Ensure that there is no overflow when doing page->index <<
-	  PAGE_CACHE_SHIFT by casting page->index to s64 in fs/ntfs/aops.c.
-	- Use atomic kmap instead of kmap() in fs/ntfs/aops.c::ntfs_read_page()
-	  and ntfs_read_block().
-	- Use case sensitive attribute lookups instead of case insensitive ones.
-	- Lock all page cache pages belonging to mst protected attributes while
-	  accessing them to ensure we never see corrupt data while the page is
-	  under writeout.
-	- Add framework for generic ntfs collation (fs/ntfs/collation.[hc]).
-	  We have ntfs_is_collation_rule_supported() to check if the collation
-	  rule you want to use is supported and ntfs_collation() which actually
-	  collates two data items.  We currently only support COLLATION_BINARY
-	  and COLLATION_NTOFS_ULONG but support for other collation rules will
-	  be added as the need arises.
-	- Add a new type, ntfs_index_context, to allow retrieval of an index
-	  entry using the corresponding index key.  To get an index context,
-	  use ntfs_index_ctx_get() and to release it, use ntfs_index_ctx_put().
-	  This also adds a new slab cache for the index contexts.  To lookup a
-	  key in an index inode, use ntfs_index_lookup().  After modifying an
-	  index entry, call ntfs_index_entry_flush_dcache_page() followed by
-	  ntfs_index_entry_mark_dirty() to ensure the changes are written out
-	  to disk.  For details see fs/ntfs/index.[hc].  Note, at present, if
-	  an index entry is in the index allocation attribute rather than the
-	  index root attribute it will not be written out (you will get a
-	  warning message about discarded changes instead).
-	- Load the quota file ($Quota) and check if quota tracking is enabled
-	  and if so, mark the quotas out of date.  This causes windows to
-	  rescan the volume on boot and update all quota entries.
-	- Add a set_page_dirty address space operation for ntfs_m[fs]t_aops.
-	  It is simply set to __set_page_dirty_nobuffers() to make sure that
-	  running set_page_dirty() on a page containing mft/ntfs records will
-	  not affect the dirty state of the page buffers.
-	- Add fs/ntfs/index.c::__ntfs_index_entry_mark_dirty() which sets all
-	  buffers that are inside the ntfs record in the page dirty after which
-	  it sets the page dirty.  This allows ->writepage to only write the
-	  dirty index records rather than having to write all the records in
-	  the page.  Modify fs/ntfs/index.h::ntfs_index_entry_mark_dirty() to
-	  use this rather than __set_page_dirty_nobuffers().
-	- Implement fs/ntfs/aops.c::ntfs_write_mst_block() which enables the
-	  writing of page cache pages belonging to mst protected attributes
-	  like the index allocation attribute in directory indices and other
-	  indices like $Quota/$Q, etc.  This means that the quota is now marked
-	  out of date on all volumes rather than only on ones where the quota
-	  defaults entry is in the index root attribute of the $Quota/$Q index.
-
-2.1.14 - Fix an NFSd caused deadlock reported by several users.
-
-	- Modify fs/ntfs/ntfs_readdir() to copy the index root attribute value
-	  to a buffer so that we can put the search context and unmap the mft
-	  record before calling the filldir() callback.  We need to do this
-	  because of NFSd which calls ->lookup() from its filldir callback()
-	  and this causes NTFS to deadlock as ntfs_lookup() maps the mft record
-	  of the directory and since ntfs_readdir() has got it mapped already
-	  ntfs_lookup() deadlocks.
-
-2.1.13 - Enable overwriting of resident files and housekeeping of system files.
-
-	- Implement writing of mft records (fs/ntfs/mft.[hc]), which includes
-	  keeping the mft mirror in sync with the mft when mirrored mft records
-	  are written.  The functions are write_mft_record{,_nolock}().  The
-	  implementation is quite rudimentary for now with lots of things not
-	  implemented yet but I am not sure any of them can actually occur so
-	  I will wait for people to hit each one and only then implement it.
-	- Commit open system inodes at umount time.  This should make it
-	  virtually impossible for sync_mft_mirror_umount() to ever be needed.
-	- Implement ->write_inode (fs/ntfs/inode.c::ntfs_write_inode()) for the
-	  ntfs super operations.  This gives us inode writing via the VFS inode
-	  dirty code paths.  Note:  Access time updates are not implemented yet.
-	- Implement fs/ntfs/mft.[hc]::{,__}mark_mft_record_dirty() and make
-	  fs/ntfs/aops.c::ntfs_writepage() and ntfs_commit_write() use it, thus
-	  finally enabling resident file overwrite!  (-8  This also includes a
-	  placeholder for ->writepage (ntfs_mft_writepage()), which for now
-	  just redirties the page and returns.  Also, at umount time, we for
-	  now throw away all mft data page cache pages after the last call to
-	  ntfs_commit_inode() in the hope that all inodes will have been
-	  written out by then and hence no dirty (meta)data will be lost.  We
-	  also check for this case and emit an error message telling the user
-	  to run chkdsk.
-	- Use set_page_writeback() and end_page_writeback() in the resident
-	  attribute code path of fs/ntfs/aops.c::ntfs_writepage() otherwise
-	  the radix-tree tag PAGECACHE_TAG_DIRTY remains set even though the
-	  page is clean.
-	- Implement ntfs_mft_writepage() so it now checks if any of the mft
-	  records in the page are dirty and if so redirties the page and
-	  returns.  Otherwise it just returns (after doing set_page_writeback(),
-	  unlock_page(), end_page_writeback() or the radix-tree tag
-	  PAGECACHE_TAG_DIRTY remains set even though the page is clean), thus
-	  alowing the VM to do with the page as it pleases.  Also, at umount
-	  time, now only throw away dirty mft (meta)data pages if dirty inodes
-	  are present and ask the user to email us if they see this happening.
-	- Add functions ntfs_{clear,set}_volume_flags(), to modify the volume
-	  information flags (fs/ntfs/super.c).
-	- Mark the volume dirty when (re)mounting read-write and mark it clean
-	  when unmounting or remounting read-only.  If any volume errors are
-	  found, the volume is left marked dirty to force chkdsk to run.
-	- Add code to set the NT4 compatibility flag when (re)mounting
-	  read-write for newer NTFS versions but leave it commented out for now
-	  since we do not make any modifications that are NTFS 1.2 specific yet
-	  and since setting this flag breaks Captive-NTFS which is not nice.
-	  This code must be enabled once we start writing NTFS 1.2 specific
-	  changes otherwise Windows NTFS driver might crash / cause corruption.
-
-2.1.12 - Fix the second fix to the decompression engine and some cleanups.
-
-	- Add a new address space operations struct, ntfs_mst_aops, for mst
-	  protected attributes.  This is because the default ntfs_aops do not
-	  make sense with mst protected data and were they to write anything to
-	  such an attribute they would cause data corruption so we provide
-	  ntfs_mst_aops which does not have any write related operations set.
-	- Cleanup dirty ntfs inode handling (fs/ntfs/inode.[hc]) which also
-	  includes an adapted ntfs_commit_inode() and an implementation of
-	  ntfs_write_inode() which for now just cleans dirty inodes without
-	  writing them (it does emit a warning that this is happening).
-	- Undo the second decompression engine fix (see 2.1.9 release ChangeLog
-	  entry) as it was only fixing a theoretical bug but at the same time
-	  it badly broke the handling of sparse and uncompressed compression
-	  blocks.
-
-2.1.11 - Driver internal cleanups.
-
-	- Only build logfile.o if building the driver with read-write support.
-	- Really final white space cleanups.
-	- Use generic_ffs() instead of ffs() in logfile.c which allows the
-	  log_page_size variable to be optimized by gcc into a constant.
-	- Rename uchar_t to ntfschar everywhere as uchar_t is unsigned 1-byte
-	  char as defined by POSIX and as found on some systems.
-
-2.1.10 - Force read-only (re)mounting of volumes with unsupported volume flags.
-
-	- Finish off the white space cleanups (remove trailing spaces, etc).
-	- Clean up ntfs_fill_super() and ntfs_read_inode_mount() by removing
-	  the kludges around the first iget().  Instead of (re)setting ->s_op
-	  we have the $MFT inode set up by explicit new_inode() / set ->i_ino /
-	  insert_inode_hash() / call ntfs_read_inode_mount() directly.  This
-	  kills the need for second super_operations and allows to return error
-	  from ntfs_read_inode_mount() without resorting to ugly "poisoning"
-	  tricks.  (Al Viro)
-	- Force read-only (re)mounting if any of the following bits are set in
-	  the volume information flags:
-	  	VOLUME_IS_DIRTY, VOLUME_RESIZE_LOG_FILE,
-		VOLUME_UPGRADE_ON_MOUNT, VOLUME_DELETE_USN_UNDERWAY,
-		VOLUME_REPAIR_OBJECT_ID, VOLUME_MODIFIED_BY_CHKDSK
-	  To make this easier we define VOLUME_MUST_MOUNT_RO_MASK with all the
-	  above bits set so the test is made easy.
-
-2.1.9 - Fix two bugs in decompression engine.
-
-	- Fix a bug where we would not always detect that we have reached the
-	  end of a compression block because we were ending at minus one byte
-	  which is effectively the same as being at the end.  The fix is to
-	  check whether the uncompressed buffer has been fully filled and if so
-	  we assume we have reached the end of the compression block.  A big
-	  thank you to Marcin Gibuła for the bug report, the assistance in
-	  tracking down the bug and testing the fix.
-	- Fix a possible bug where when a compressed read is truncated to the
-	  end of the file, the offset inside the last page was not truncated.
-
-2.1.8 - Handle $MFT mirror and $LogFile, improve time handling, and cleanups.
-
-	- Use get_bh() instead of manual atomic_inc() in fs/ntfs/compress.c.
-	- Modify fs/ntfs/time.c::ntfs2utc(), get_current_ntfs_time(), and
-	  utc2ntfs() to work with struct timespec instead of time_t on the
-	  Linux UTC time side thus preserving the full precision of the NTFS
-	  time and only loosing up to 99 nano-seconds in the Linux UTC time.
-	- Move fs/ntfs/time.c to fs/ntfs/time.h and make the time functions
-	  static inline.
-	- Remove unused ntfs_dirty_inode().
-	- Cleanup super operations declaration in fs/ntfs/super.c.
-	- Wrap flush_dcache_mft_record_page() in #ifdef NTFS_RW.
-	- Add NInoTestSetFoo() and NInoTestClearFoo() macro magic to
-	  fs/ntfs/inode.h and use it to declare NInoTest{Set,Clear}Dirty.
-	- Move typedefs for ntfs_attr and test_t from fs/ntfs/inode.c to
-	  fs/ntfs/inode.h so they can be used elsewhere.
-	- Determine the mft mirror size as the number of mirrored mft records
-	  and store it in ntfs_volume->mftmirr_size (fs/ntfs/super.c).
-	- Load the mft mirror at mount time and compare the mft records stored
-	  in it to the ones in the mft.  Force a read-only mount if the two do
-	  not match (fs/ntfs/super.c).
-	- Fix type casting related warnings on 64-bit architectures.  Thanks
-	  to Meelis Roos for reporting them.
-	- Move %L to %ll as %L is floating point and %ll is integer which is
-	  what we want.
-	- Read the journal ($LogFile) and determine if the volume has been
-	  shutdown cleanly and force a read-only mount if not (fs/ntfs/super.c
-	  and fs/ntfs/logfile.c).  This is a little bit of a crude check in
-	  that we only look at the restart areas and not at the actual log
-	  records so that there will be a very small number of cases where we
-	  think that a volume is dirty when in fact it is clean.  This should
-	  only affect volumes that have not been shutdown cleanly and did not
-	  have any pending, non-check-pointed i/o.
-	- If the $LogFile indicates a clean shutdown and a read-write (re)mount
-	  is requested, empty $LogFile by overwriting it with 0xff bytes to
-	  ensure that Windows cannot cause data corruption by replaying a stale
-	  journal after Linux has written to the volume.
-
-2.1.7 - Enable NFS exporting of mounted NTFS volumes.
-
-	- Set i_generation in the VFS inode from the seq_no of the NTFS inode.
-	- Make ntfs_lookup() NFS export safe, i.e. use d_splice_alias(), etc.
-	- Implement ->get_dentry() in fs/ntfs/namei.c::ntfs_get_dentry() as the
-	  default doesn't allow inode number 0 which is a valid inode on NTFS
-	  and even if it did allow that it uses iget() instead of ntfs_iget()
-	  which makes it useless for us.
-	- Implement ->get_parent() in fs/ntfs/namei.c::ntfs_get_parent() as the
-	  default just returns -EACCES which is not very useful.
-	- Define export operations (->s_export_op) for NTFS (ntfs_export_ops)
-	  and set them up in the super block at mount time (super.c) this
-	  allows mounted NTFS volumes to be exported via NFS.
-	- Add missing return -EOPNOTSUPP; in
-	  fs/ntfs/aops.c::ntfs_commit_nonresident_write().
-	- Enforce no atime and no dir atime updates at mount/remount time as
-	  they are not implemented yet anyway.
-	- Move a few assignments in fs/ntfs/attrib.c::load_attribute_list() to
-	  after a NULL check.  Thanks to Dave Jones for pointing this out.
-
-2.1.6 - Fix minor bug in handling of compressed directories.
-
-	- Fix bug in handling of compressed directories.  A compressed
-	  directory is not really compressed so when we set the ->i_blocks
-	  field of a compressed directory inode we were setting it from the
-	  non-existing field ni->itype.compressed.size which gave random
-	  results...  For directories we now always use ni->allocated_size.
-
-2.1.5 - Fix minor bug in attribute list attribute handling.
-
-	- Fix bug in attribute list handling.  Actually it is not as much a bug
-	  as too much protection in that we were not allowing attribute lists
-	  which waste space on disk while Windows XP clearly allows it and in
-	  fact creates such attribute lists so our driver was failing.
-	- Update NTFS documentation ready for 2.6 kernel release.
-
-2.1.4 - Reduce compiler requirements.
-
-	- Remove all uses of unnamed structs and unions in the driver to make
-	  old and newer gcc versions happy. Makes it a bit uglier IMO but at
-	  least people will stop hassling me about it.
-
-2.1.3 - Important bug fixes in corner cases.
-
-	- super.c::parse_ntfs_boot_sector(): Correct the check for 64-bit
-	  clusters. (Philipp Thomas)
-	- attrib.c::load_attribute_list(): Fix bug when initialized_size is a
-	  multiple of the block_size but not the cluster size. (Szabolcs
-	  Szakacsits)
-
-2.1.2 - Important bug fixes aleviating the hangs in statfs.
-
-	- Fix buggy free cluster and free inode determination logic.
-
-2.1.1 - Minor updates.
-
-	- Add handling for initialized_size != data_size in compressed files.
-	- Reduce function local stack usage from 0x3d4 bytes to just noise in
-	  fs/ntfs/upcase.c. (Randy Dunlap)
-	- Remove compiler warnings for newer gcc.
-	- Pages are no longer kmapped by mm/filemap.c::generic_file_write()
-	  around calls to ->{prepare,commit}_write.  Adapt NTFS appropriately
-	  in fs/ntfs/aops.c::ntfs_prepare_nonresident_write() by using
-	  kmap_atomic(KM_USER0).
-
-2.1.0 - First steps towards write support: implement file overwrite.
-
-	- Add configuration option for developmental write support with an
-	  appropriately scary configuration help text.
-	- Initial implementation of fs/ntfs/aops.c::ntfs_writepage() and its
-	  helper fs/ntfs/aops.c::ntfs_write_block(). This enables mmap(2) based
-	  overwriting of existing files on ntfs. Note: Resident files are
-	  only written into memory, and not written out to disk at present, so
-	  avoid writing to files smaller than about 1kiB.
-	- Initial implementation of fs/ntfs/aops.c::ntfs_prepare_write(), its
-	  helper fs/ntfs/aops.c::ntfs_prepare_nonresident_write() and their
-	  counterparts, fs/ntfs/aops.c::ntfs_commit_write(), and
-	  fs/ntfs/aops.c::ntfs_commit_nonresident_write(), respectively. Also,
-	  add generic_file_write() to the ntfs file operations (fs/ntfs/file.c).
-	  This enables write(2) based overwriting of existing files on ntfs.
-	  Note: As with mmap(2) based overwriting, resident files are only
-	  written into memory, and not written out to disk at present, so avoid
-	  writing to files smaller than about 1kiB.
-	- Implement ->truncate (fs/ntfs/inode.c::ntfs_truncate()) and
-	  ->setattr() (fs/ntfs/inode.c::ntfs_setattr()) inode operations for
-	  files with the purpose of intercepting and aborting all i_size
-	  changes which we do not support yet. ntfs_truncate() actually only
-	  emits a warning message but AFAICS our interception of i_size changes
-	  elsewhere means ntfs_truncate() never gets called for i_size changes.
-	  It is only called from generic_file_write() when we fail in
-	  ntfs_prepare_{,nonresident_}write() in order to discard any
-	  instantiated buffers beyond i_size. Thus i_size is not actually
-	  changed so our warning message is enough. Unfortunately it is not
-	  possible to easily determine if i_size is being changed or not hence
-	  we just emit an appropriately worded error message.
-
-2.0.25 - Small bug fixes and cleanups.
-
-	- Unlock the page in an out of memory error code path in
-	  fs/ntfs/aops.c::ntfs_read_block().
-	- If fs/ntfs/aops.c::ntfs_read_page() is called on an uptodate page,
-	  just unlock the page and return. (This can happen due to ->writepage
-	  clearing PageUptodate() during write out of MstProtected()
-	  attributes.
-	- Remove leaked write code again.
-
-2.0.24 - Cleanups.
-
-	- Treat BUG_ON() as ASSERT() not VERIFY(), i.e. do not use side effects
-	  inside BUG_ON(). (Adam J. Richter)
-	- Split logical OR expressions inside BUG_ON() into individual BUG_ON()
-	  calls for improved debugging. (Adam J. Richter)
-	- Add errors flag to the ntfs volume state, accessed via
-	  NVol{,Set,Clear}Errors(vol).
-	- Do not allow read-write remounts of read-only volumes with errors.
-	- Clarify comment for ntfs file operation sendfile which was added by
-	  Christoph Hellwig a while ago (just using generic_file_sendfile())
-	  to say that ntfs ->sendfile is only used for the case where the
-	  source data is on the ntfs partition and the destination is
-	  somewhere else, i.e. nothing we need to concern ourselves with.
-	- Add generic_file_write() as our ntfs file write operation.
-
-2.0.23 - Major bug fixes (races, deadlocks, non-i386 architectures).
-
-	- Massive internal locking changes to mft record locking. Fixes lock
-	  recursion and replaces the mrec_lock read/write semaphore with a
-	  mutex. Also removes the now superfluous mft_count. This fixes several
-	  race conditions and deadlocks, especially in the future write code.
-	- Fix ntfs over loopback for compressed files by adding an
-	  optimization barrier. (gcc was screwing up otherwise ?)
-	- Miscellaneous cleanups all over the code and a fix or two in error
-	  handling code paths.
-	Thanks go to Christoph Hellwig for pointing out the following two:
-	- Remove now unused function fs/ntfs/malloc.h::vmalloc_nofs().
-	- Fix ntfs_free() for ia64 and parisc by checking for VMALLOC_END, too.
-
-2.0.22 - Cleanups, mainly to ntfs_readdir(), and use C99 initializers.
-
-	- Change fs/ntfs/dir.c::ntfs_reddir() to only read/write ->f_pos once
-	  at entry/exit respectively.
-	- Use C99 initializers for structures.
-	- Remove unused variable blocks from fs/ntfs/aops.c::ntfs_read_block().
-
-2.0.21 - Check for, and refuse to work with too large files/directories/volumes.
-
-	- Limit volume size at mount time to 2TiB on architectures where
-	  unsigned long is 32-bits (fs/ntfs/super.c::parse_ntfs_boot_sector()).
-	  This is the most we can do without overflowing the 32-bit limit of
-	  the block device size imposed on us by sb_bread() and sb_getblk()
-	  for the time being.
-	- Limit file/directory size at open() time to 16TiB on architectures
-	  where unsigned long is 32-bits (fs/ntfs/file.c::ntfs_file_open() and
-	  fs/ntfs/dir.c::ntfs_dir_open()). This is the most we can do without
-	  overflowing the page cache page index.
-
-2.0.20 - Support non-resident directory index bitmaps, fix page leak in readdir.
-
-	- Move the directory index bitmap to use an attribute inode instead of
-	  having special fields for it inside the ntfs inode structure. This
-	  means that the index bitmaps now use the page cache for i/o, too,
-	  and also as a side effect we get support for non-resident index
-	  bitmaps for free.
-	- Simplify/cleanup error handling in fs/ntfs/dir.c::ntfs_readdir() and
-	  fix a page leak that manifested itself in some cases.
-	- Add fs/ntfs/inode.c::ntfs_put_inode(), which we need to release the
-	  index bitmap inode on the final iput().
-
-2.0.19 - Fix race condition, improvements, and optimizations in i/o interface.
-
-	- Apply block optimization added to fs/ntfs/aops.c::ntfs_read_block()
-	  to fs/ntfs/compress.c::ntfs_file_read_compressed_block() as well.
-	- Drop the "file" from ntfs_file_read_compressed_block().
-	- Rename fs/ntfs/aops.c::ntfs_enb_buffer_read_async() to
-	  ntfs_end_buffer_async_read() (more like the fs/buffer.c counterpart).
-	- Update ntfs_end_buffer_async_read() with the improved logic from
-	  its updated counterpart fs/buffer.c::end_buffer_async_read(). Apply
-	  further logic improvements to better determine when we set PageError.
-	- Update submission of buffers in fs/ntfs/aops.c::ntfs_read_block() to
-	  check for the buffers being uptodate first in line with the updated
-	  fs/buffer.c::block_read_full_page(). This plugs a small race
-	  condition.
-
-2.0.18 - Fix race condition in reading of compressed files.
-
-	- There was a narrow window between checking a buffer head for being
-	  uptodate and locking it in ntfs_file_read_compressed_block(). We now
-	  lock the buffer and then check whether it is uptodate or not.
-
-2.0.17 - Cleanups and optimizations - shrinking the ToDo list.
-
-	- Modify fs/ntfs/inode.c::ntfs_read_locked_inode() to return an error
-	  code and update callers, i.e. ntfs_iget(), to pass that error code
-	  up instead of just using -EIO.
-	- Modifications to super.c to ensure that both mount and remount
-	  cannot set any write related options when the driver is compiled
-	  read-only.
-	- Optimize block resolution in fs/ntfs/aops.c::ntfs_read_block() to
-	  cache the current runlist element. This should improve performance
-	  when reading very large and/or very fragmented data.
-
-2.0.16 - Convert access to $MFT/$BITMAP to attribute inode API.
-
-	- Fix a stupid bug introduced in 2.0.15 where we were unmapping the
-	  wrong inode in fs/ntfs/inode.c::ntfs_attr_iget().
-	- Fix debugging check in fs/ntfs/aops.c::ntfs_read_block().
-	- Convert $MFT/$BITMAP access to attribute inode API and remove all
-	  remnants of the ugly mftbmp address space and operations hack. This
-	  means we finally have only one readpage function as well as only one
-	  async io completion handler. Yey! The mft bitmap is now just an
-	  attribute inode and is accessed from vol->mftbmp_ino just as if it
-	  were a normal file. Fake inodes rule. (-:
-
-2.0.15 - Fake inodes based attribute i/o via the pagecache, fixes and cleanups.
-
-	- Fix silly bug in fs/ntfs/super.c::parse_options() which was causing
-	  remounts to fail when the partition had an entry in /etc/fstab and
-	  the entry specified the nls= option.
-	- Apply same macro magic used in fs/ntfs/inode.h to fs/ntfs/volume.h to
-	  expand all the helper functions NVolFoo(), NVolSetFoo(), and
-	  NVolClearFoo().
-	- Move copyright statement from driver initialisation message to
-	  module description (fs/super.c). This makes the initialisation
-	  message fit on one line and fits in better with rest of kernel.
-	- Update fs/ntfs/attrib.c::map_run_list() to work on both real and
-	  attribute inodes, and both for files and directories.
-	- Implement fake attribute inodes allowing all attribute i/o to go via
-	  the page cache and to use all the normal vfs/mm functionality:
-	  - Add ntfs_attr_iget() and its helper ntfs_read_locked_attr_inode()
-	    to fs/ntfs/inode.c.
-	  - Add needed cleanup code to ntfs_clear_big_inode().
-	- Merge address space operations for files and directories (aops.c),
-	  now just have ntfs_aops:
-	  - Rename:
-		end_buffer_read_attr_async() ->	ntfs_end_buffer_read_async(),
-		ntfs_attr_read_block()	     ->	ntfs_read_block(),
-		ntfs_file_read_page()	     ->	ntfs_readpage().
-	  - Rewrite fs/ntfs/aops.c::ntfs_readpage() to work on both real and
-	    attribute inodes, and both for files and directories.
-	  - Remove obsolete fs/ntfs/aops.c::ntfs_mst_readpage().
-
-2.0.14 - Run list merging code cleanup, minor locking changes, typo fixes.
-
-	- Change fs/ntfs/super.c::ntfs_statfs() to not rely on BKL by moving
-	  the locking out of super.c::get_nr_free_mft_records() and taking and
-	  dropping the mftbmp_lock rw_semaphore in ntfs_statfs() itself.
-	- Bring attribute runlist merging code (fs/ntfs/attrib.c) in sync with
-	  current userspace ntfs library code. This means that if a merge
-	  fails the original runlists are always left unmodified instead of
-	  being silently corrupted.
-	- Misc typo fixes.
-
-2.0.13 - Use iget5_locked() in preparation for fake inodes and small cleanups.
-
-	- Remove nr_mft_bits and the now superfluous union with nr_mft_records
-	  from ntfs_volume structure.
-	- Remove nr_lcn_bits and the now superfluous union with nr_clusters
-	  from ntfs_volume structure.
-	- Use iget5_locked() and friends instead of conventional iget(). Wrap
-	  the call in fs/ntfs/inode.c::ntfs_iget() and update callers of iget()
-	  to use ntfs_iget(). Leave only one iget() call at mount time so we
-	  don't need an ntfs_iget_mount().
-	- Change fs/ntfs/inode.c::ntfs_new_extent_inode() to take mft_no as an
-	  additional argument.
-
-2.0.12 - Initial cleanup of address space operations following 2.0.11 changes.
-
-	- Merge fs/ntfs/aops.c::end_buffer_read_mst_async() and
-	  fs/ntfs/aops.c::end_buffer_read_file_async() into one function
-	  fs/ntfs/aops.c::end_buffer_read_attr_async() using NInoMstProtected()
-	  to determine whether to apply mst fixups or not.
-	- Above change allows merging fs/ntfs/aops.c::ntfs_file_read_block()
-	  and fs/ntfs/aops.c::ntfs_mst_readpage() into one function
-	  fs/ntfs/aops.c::ntfs_attr_read_block(). Also, create a tiny wrapper
-	  fs/ntfs/aops.c::ntfs_mst_readpage() to transform the parameters from
-	  the VFS readpage function prototype to the ntfs_attr_read_block()
-	  function prototype.
-
-2.0.11 - Initial preparations for fake inode based attribute i/o.
-
-	- Move definition of ntfs_inode_state_bits to fs/ntfs/inode.h and
-	  do some macro magic (adapted from include/linux/buffer_head.h) to
-	  expand all the helper functions NInoFoo(), NInoSetFoo(), and
-	  NInoClearFoo().
-	- Add new flag to ntfs_inode_state_bits: NI_Sparse.
-	- Add new fields to ntfs_inode structure to allow use of fake inodes
-	  for attribute i/o: type, name, name_len. Also add new state bits:
-	  NI_Attr, which, if set, indicates the inode is a fake inode, and
-	  NI_MstProtected, which, if set, indicates the attribute uses multi
-	  sector transfer protection, i.e. fixups need to be applied after
-	  reads and before/after writes.
-	- Rename fs/ntfs/inode.c::ntfs_{new,clear,destroy}_inode() to
-	  ntfs_{new,clear,destroy}_extent_inode() and update callers.
-	- Use ntfs_clear_extent_inode() in fs/ntfs/inode.c::__ntfs_clear_inode()
-	  instead of ntfs_destroy_extent_inode().
-	- Cleanup memory deallocations in {__,}ntfs_clear_{,big_}inode().
-	- Make all operations on ntfs inode state bits use the NIno* functions.
-	- Set up the new ntfs inode fields and state bits in
-	  fs/ntfs/inode.c::ntfs_read_inode() and add appropriate cleanup of
-	  allocated memory to __ntfs_clear_inode().
-	- Cleanup ntfs_inode structure a bit for better ordering of elements
-	  w.r.t. their size to allow better packing of the structure in memory.
-
-2.0.10 - There can only be 2^32 - 1 inodes on an NTFS volume.
-
-	- Add check at mount time to verify that the number of inodes on the
-	  volume does not exceed 2^32 - 1, which is the maximum allowed for
-	  NTFS according to Microsoft.
-	- Change mft_no member of ntfs_inode structure to be unsigned long.
-	  Update all users. This makes ntfs_inode->mft_no just a copy of struct
-	  inode->i_ino. But we can't just always use struct inode->i_ino and
-	  remove mft_no because extent inodes do not have an attached struct
-	  inode.
-
-2.0.9 - Decompression engine now uses a single buffer and other cleanups.
-
-	- Change decompression engine to use a single buffer protected by a
-	  spin lock instead of per-CPU buffers. (Rusty Russell)
-	- Do not update cb_pos when handling a partial final page during
-	  decompression of a sparse compression block, as the value is later
-	  reset without being read/used. (Rusty Russell)
-	- Switch to using the new KM_BIO_SRC_IRQ for atomic kmap()s. (Andrew
-	  Morton)
-	- Change buffer size in ntfs_readdir()/ntfs_filldir() to use
-	  NLS_MAX_CHARSET_SIZE which makes the buffers almost 1kiB each but
-	  it also makes everything safer so it is a good thing.
-	- Miscellaneous minor cleanups to comments.
-
-2.0.8 - Major updates for handling of case sensitivity and dcache aliasing.
-
-	Big thanks go to Al Viro and other inhabitants of #kernel for investing
-	their time to discuss the case sensitivity and dcache aliasing issues.
-
-	- Remove unused source file fs/ntfs/attraops.c.
-	- Remove show_inodes mount option(s), thus dropping support for
-	  displaying of short file names.
-	- Remove deprecated mount option posix.
-	- Restore show_sys_files mount option.
-	- Add new mount option case_sensitive, to determine if the driver
-	  treats file names as case sensitive or not. If case sensitive, create
-	  file names in the POSIX namespace. Otherwise create file names in the
-	  LONG/WIN32 namespace. Note, files remain accessible via their short
-	  file name, if it exists.
-	- Remove really dumb logic bug in boot sector recovery code.
-	- Fix dcache aliasing issues wrt short/long file names via changes
-	  to fs/ntfs/dir.c::ntfs_lookup_inode_by_name() and
-	  fs/ntfs/namei.c::ntfs_lookup():
-	  - Add additional argument to ntfs_lookup_inode_by_name() in which we
-	    return information about the matching file name if the case is not
-	    matching or the match is a short file name. See comments above the
-	    function definition for details.
-	  - Change ntfs_lookup() to only create dcache entries for the correctly
-	    cased file name and only for the WIN32 namespace counterpart of DOS
-	    namespace file names. This ensures we have only one dentry per
-	    directory and also removes all dcache aliasing issues between short
-	    and long file names once we add write support. See comments above
-	    function for details.
-	- Fix potential 1 byte overflow in fs/ntfs/unistr.c::ntfs_ucstonls().
-
-2.0.7 - Minor cleanups and updates for changes in core kernel code.
-
-	- Remove much of the NULL struct element initializers.
-	- Various updates to make compatible with recent kernels.
-	- Remove defines of MAX_BUF_PER_PAGE and include linux/buffer_head.h
-	  in fs/ntfs/ntfs.h instead.
-	- Remove no longer needed KERNEL_VERSION checks. We are now in the
-	  kernel proper so they are no longer needed.
-
-2.0.6 - Major bugfix to make compatible with other kernel changes.
-
-	- Initialize the mftbmp address space properly now that there are more
-	  fields in the struct address_space. This was leading to hangs and
-	  oopses on umount since 2.5.12 because of changes to other parts of
-	  the kernel. We probably want a kernel generic init_address_space()
-	  function...
-	- Drop BKL from ntfs_readdir() after consultation with Al Viro. The
-	  only caller of ->readdir() is vfs_readdir() which holds i_mutex
-	  during the call, and i_mutex is sufficient protection against changes
-	  in the directory inode (including ->i_size).
-	- Use generic_file_llseek() for directories (as opposed to
-	  default_llseek()) as this downs i_mutex instead of the BKL which is
-	  what we now need for exclusion against ->f_pos changes considering we
-	  no longer take the BKL in ntfs_readdir().
-
-2.0.5 - Major bugfix. Buffer overflow in extent inode handling.
-
-	- No need to set old blocksize in super.c::ntfs_fill_super() as the
-	  VFS does so via invocation of deactivate_super() calling
-	  fs->fill_super() calling block_kill_super() which does it.
-	- BKL moved from VFS into dir.c::ntfs_readdir(). (Linus Torvalds)
-	  -> Do we really need it? I don't think so as we have exclusion on
-	  the directory ntfs_inode rw_semaphore mrec_lock. We mmight have to
-	  move the ->f_pos accesses under the mrec_lock though. Check this...
-	- Fix really, really, really stupid buffer overflow in extent inode
-	  handling in mft.c::map_extent_mft_record().
-
-2.0.4 - Cleanups and updates for kernel 2.5.11.
-
-	- Add documentation on how to use the MD driver to be able to use NTFS
-	  stripe and volume sets in Linux and generally cleanup documentation
-	  a bit.
-	Remove all uses of kdev_t in favour of struct block_device *:
-	- Change compress.c::ntfs_file_read_compressed_block() to use
-	  sb_getblk() instead of getblk().
-	- Change super.c::ntfs_fill_super() to use bdev_hardsect_size() instead
-	  of get_hardsect_size().
-	- No need to get old blocksize in super.c::ntfs_fill_super() as
-	  fs/super.c::get_sb_bdev() already does this.
-	- Set bh->b_bdev instead of bh->b_dev throughout aops.c.
-
-2.0.3 - Small bug fixes, cleanups, and performance improvements.
-
-	- Remove some dead code from mft.c.
-	- Optimize readpage and read_block functions throughout aops.c so that
-	  only initialized blocks are read. Non-initialized ones have their
-	  buffer head mapped, zeroed, and set up to date, without scheduling
-	  any i/o. Thanks to Al Viro for advice on how to avoid the device i/o.
-	Thanks go to Andrew Morton for spotting the below:
-	- Fix buglet in allocate_compression_buffers() error code path.
-	- Call flush_dcache_page() after modifying page cache page contents in
-	  ntfs_file_readpage().
-	- Check for existence of page buffers throughout aops.c before calling
-	  create_empty_buffers(). This happens when an I/O error occurs and the
-	  read is retried. (It also happens once writing is implemented so that
-	  needed doing anyway but I had left it for later...)
-	- Don't BUG_ON() uptodate and/or mapped buffers throughout aops.c in
-	  readpage and read_block functions. Reasoning same as above (i.e. I/O
-	  error retries and future write code paths.)
-
-2.0.2 - Minor updates and cleanups.
-
-	- Cleanup: rename mst.c::__post_read_mst_fixup to post_write_mst_fixup
-	  and cleanup the code a bit, removing the unused size parameter.
-	- Change default fmask to 0177 and update documentation.
-	- Change attrib.c::get_attr_search_ctx() to return the search context
-	  directly instead of taking the address of a pointer. A return value
-	  of NULL means the allocation failed. Updated all callers
-	  appropriately.
-	- Update to 2.5.9 kernel (preserving backwards compatibility) by
-	  replacing all occurences of page->buffers with page_buffers(page).
-	- Fix minor bugs in runlist merging, also minor cleanup.
-	- Updates to bootsector layout and mft mirror contents descriptions.
-	- Small bug fix in error detection in unistr.c and some cleanups.
-	- Grow name buffer allocations in unistr.c in aligned mutlipled of 64
-	  bytes.
-
-2.0.1 - Minor updates.
-
-	- Make default umask correspond to documentation.
-	- Improve documentation.
-	- Set default mode to include execute bit. The {u,f,d}mask can be used
-	  to take it away if desired. This allows binaries to be executed from
-	  a mounted ntfs partition.
-
-2.0.0 - New version number. Remove TNG from the name. Now in the kernel.
-
-	- Add kill_super, just keeping up with the vfs changes in the kernel.
-	- Repeat some changes from tng-0.0.8 that somehow got lost on the way
-	  from the CVS import into BitKeeper.
-	- Begin to implement proper handling of allocated_size vs
-	  initialized_size vs data_size (i.e. i_size). Done are
-	  mft.c::ntfs_mft_readpage(), aops.c::end_buffer_read_index_async(),
-	  and attrib.c::load_attribute_list().
-	- Lock the runlist in attrib.c::load_attribute_list() while using it.
-	- Fix memory leak in ntfs_file_read_compressed_block() and generally
-	  clean up compress.c a little, removing some uncommented/unused debug
-	  code.
-	- Tidy up dir.c a little bit.
-	- Don't bother getting the runlist in inode.c::ntfs_read_inode().
-	- Merge mft.c::ntfs_mft_readpage() and aops.c::ntfs_index_readpage()
-	  creating aops.c::ntfs_mst_readpage(), improving the handling of
-	  holes and overflow in the process and implementing the correct
-	  equivalent of ntfs_file_get_block() in ntfs_mst_readpage() itself.
-	  I am aiming for correctness at the moment. Modularisation can come
-	  later.
-	- Rename aops.c::end_buffer_read_index_async() to
-	  end_buffer_read_mst_async() and optimize the overflow checking and
-	  handling.
-	- Use the host of the mftbmp address space mapping to hold the ntfs
-	  volume. This is needed so the async i/o completion handler can
-	  retrieve a pointer to the volume. Hopefully this will not cause
-	  problems elsewhere in the kernel... Otherwise will need to use a
-	  fake inode.
-	- Complete implementation of proper handling of allocated_size vs
-	  initialized_size vs data_size (i.e. i_size) in whole driver.
-	  Basically aops.c is now completely rewritten.
-	- Change NTFS driver name to just NTFS and set version number to 2.0.0
-	  to make a clear distinction from the old driver which is still on
-	  version 1.1.22.
-
-tng-0.0.8 - 08/03/2002 - Now using BitKeeper, http://linux-ntfs.bkbits.net/
-
-	- Replace bdevname(sb->s_dev) with sb->s_id.
-	- Remove now superfluous new-line characters in all callers of
-	  ntfs_debug().
-	- Apply kludge in ntfs_read_inode(), setting i_nlink to 1 for
-	  directories. Without this the "find" utility gets very upset which is
-	  fair enough as Linux/Unix do not support directory hard links.
-	- Further runlist merging work. (Richard Russon)
-	- Backwards compatibility for gcc-2.95. (Richard Russon)
-	- Update to kernel 2.5.5-pre1 and rediff the now tiny patch.
-	- Convert to new filesystem declaration using ->ntfs_get_sb() and
-	  replacing ntfs_read_super() with ntfs_fill_super().
-	- Set s_maxbytes to MAX_LFS_FILESIZE to avoid page cache page index
-	  overflow on 32-bit architectures.
-	- Cleanup upcase loading code to use ntfs_(un)map_page().
-	- Disable/reenable preemtion in critical sections of compession engine.
-	- Replace device size determination in ntfs_fill_super() with
-	  sb->s_bdev->bd_inode->i_size (in bytes) and remove now superfluous
-	  function super.c::get_nr_blocks().
-	- Implement a mount time option (show_inodes) allowing choice of which
-	  types of inode names readdir() returns and modify ntfs_filldir()
-	  accordingly. There are several parameters to show_inodes:
-		system:	system files
-		win32:	long file names (including POSIX file names) [DEFAULT]
-		long:	same as win32
-		dos:	short file names only (excluding POSIX file names)
-		short:	same as dos
-		posix:	same as both win32 and dos
-		all:	all file names
-	  Note that the options are additive, i.e. specifying:
-		-o show_inodes=system,show_inodes=win32,show_inodes=dos
-	  is the same as specifying:
-		-o show_inodes=all
-	  Note that the "posix" and "all" options will show all directory
-	  names, BUT the link count on each directory inode entry is set to 1,
-	  due to Linux not supporting directory hard links. This may well
-	  confuse some userspace applications, since the directory names will
-	  have the same inode numbers. Thus it is NOT advisable to use the
-	  "posix" or "all" options. We provide them only for completeness sake.
-	- Add copies of allocated_size, initialized_size, and compressed_size to
-	  the ntfs inode structure and set them up in
-	  inode.c::ntfs_read_inode(). These reflect the unnamed data attribute
-	  for files and the index allocation attribute for directories.
-	- Add copies of allocated_size and initialized_size to ntfs inode for
-	  $BITMAP attribute of large directories and set them up in
-	  inode.c::ntfs_read_inode().
-	- Add copies of allocated_size and initialized_size to ntfs volume for
-	  $BITMAP attribute of $MFT and set them up in
-	  super.c::load_system_files().
-	- Parse deprecated ntfs driver options (iocharset, show_sys_files,
-	  posix, and utf8) and tell user what the new options to use are. Note
-	  we still do support them but they will be removed with kernel 2.7.x.
-	- Change all occurences of integer long long printf formatting to hex
-	  as printk() will not support long long integer format if/when the
-	  div64 patch goes into the kernel.
-	- Make slab caches have stable names and change the names to what they
-	  were intended to be. These changes are required/made possible by the
-	  new slab cache name handling which removes the length limitation by
-	  requiring the caller of kmem_cache_create() to supply a stable name
-	  which is then referenced but not copied.
-	- Rename run_list structure to run_list_element and create a new
-	  run_list structure containing a pointer to a run_list_element
-	  structure and a read/write semaphore. Adapt all users of runlists
-	  to new scheme and take and release the lock as needed. This fixes a
-	  nasty race as the run_list changes even when inodes are locked for
-	  reading and even when the inode isn't locked at all, so we really
-	  needed the serialization. We use a semaphore rather than a spinlock
-	  as memory allocations can sleep and doing everything GFP_ATOMIC
-	  would be silly.
-	- Cleanup read_inode() removing all code checking for lowest_vcn != 0.
-	  This can never happen due to the nature of lookup_attr() and how we
-	  support attribute lists. If it did happen it would imply the inode
-	  being corrupt.
-	- Check for lowest_vcn != 0 in ntfs_read_inode() and mark the inode as
-	  bad if found.
-	- Update to 2.5.6-pre2 changes in struct address_space.
-	- Use parent_ino() when accessing d_parent inode number in dir.c.
-	- Import Sourceforge CVS repository into BitKeeper repository:
-		http://linux-ntfs.bkbits.net/ntfs-tng-2.5
-	- Update fs/Makefile, fs/Config.help, fs/Config.in, and
-	  Documentation/filesystems/ntfs.txt for NTFS TNG.
-	- Create kernel configuration option controlling whether debugging
-	  is enabled or not.
-	- Add the required export of end_buffer_io_sync() from the patches
-	  directory to the kernel code.
-	- Update inode.c::ntfs_show_options() with show_inodes mount option.
-	- Update errors mount option.
-
-tng-0.0.7 - 13/02/2002 - The driver is now feature complete for read-only!
-
-	- Cleanup mft.c and it's debug/error output in particular. Fix a minor
-	  bug in mapping of extent inodes. Update all the comments to fit all
-	  the recent code changes.
-	- Modify vcn_to_lcn() to cope with entirely unmapped runlists.
-	- Cleanups in compress.c, mostly comments and folding help.
-	- Implement attrib.c::map_run_list() as a generic helper.
-	- Make compress.c::ntfs_file_read_compressed_block() use map_run_list()
-	  thus making code shorter and enabling attribute list support.
-	- Cleanup incorrect use of [su]64 with %L printf format specifier in
-	  all source files. Type casts to [unsigned] long long added to correct
-	  the mismatches (important for architectures which have long long not
-	  being 64 bits).
-	- Merge async io completion handlers for directory indexes and $MFT
-	  data into one by setting the index_block_size{_bits} of the ntfs
-	  inode for $MFT to the mft_record_size{_bits} of the ntfs_volume.
-	- Cleanup aops.c, update comments.
-	- Make ntfs_file_get_block() use map_run_list() so all files now
-	  support attribute lists.
-	- Make ntfs_dir_readpage() almost verbatim copy of
-	  block_read_full_page() by using ntfs_file_get_block() with only real
-	  difference being the use of our own async io completion handler
-	  rather than the default one, thus reducing the amount of code and
-	  automatically enabling attribute list support for directory indices.
-	- Fix bug in load_attribute_list() - forgot to call brelse in error
-	  code path.
-	- Change parameters to find_attr() and lookup_attr(). We no longer
-	  pass in the upcase table and its length. These can be gotten from
-	  ctx->ntfs_ino->vol->upcase{_len}. Update all callers.
-	- Cleanups in attrib.c.
-	- Implement merging of runlists, attrib.c::merge_run_lists() and its
-	  helpers. (Richard Russon)
-	- Attribute lists part 2, attribute extents and multi part runlists:
-	  enable proper support for LCN_RL_NOT_MAPPED and automatic mapping of
-	  further runlist parts via attrib.c::map_run_list().
-	- Tiny endianness bug fix in decompress_mapping_pairs().
-
-tng-0.0.6 - Encrypted directories, bug fixes, cleanups, debugging enhancements.
-
-	- Enable encrypted directories. (Their index root is marked encrypted
-	  to indicate that new files in that directory should be created
-	  encrypted.)
-	- Fix bug in NInoBmpNonResident() macro. (Cut and paste error.)
-	- Enable $Extend system directory. Most (if not all) extended system
-	  files do not have unnamed data attributes so ntfs_read_inode() had to
-	  special case them but that is ok, as the special casing recovery
-	  happens inside an error code path so there is zero slow down in the
-	  normal fast path. The special casing is done by introducing a new
-	  function inode.c::ntfs_is_extended_system_file() which checks if any
-	  of the hard links in the inode point to $Extend as being their parent
-	  directory and if they do we assume this is an extended system file.
-	- Create a sysctl/proc interface to allow {dis,en}abling of debug output
-	  when compiled with -DDEBUG. Default is debug messages to be disabled.
-	  To enable them, one writes a non-zero value to /proc/sys/fs/ntfs-debug
-	  (if /proc is enabled) or uses sysctl(2) to effect the same (if sysctl
-	  interface is enabled). Inspired by old ntfs driver.
-	- Add debug_msgs insmod/kernel boot parameter to set whether debug
-	  messages are {dis,en}abled. This is useful to enable debug messages
-	  during ntfs initialization and is the only way to activate debugging
-	  when the sysctl interface is not enabled.
-	- Cleanup debug output in various places.
-	- Remove all dollar signs ($) from the source (except comments) to
-	  enable compilation on architectures whose gcc compiler does not
-	  support dollar signs in the names of variables/constants. Attribute
-	  types now start with AT_ instead of $ and $I30 is now just I30.
-	- Cleanup ntfs_lookup() and add consistency check of sequence numbers.
-	- Load complete runlist for $MFT/$BITMAP during mount and cleanup
-	  access functions. This means we now cope with $MFT/$BITMAP being
-	  spread accross several mft records.
-	- Disable modification of mft_zone_multiplier on remount. We can always
-	  reenable this later on if we really want to, but we will need to make
-	  sure we readjust the mft_zone size / layout accordingly.
-
-tng-0.0.5 - Modernize for 2.5.x and further in line-ing with Al Viro's comments.
-
-	- Use sb_set_blocksize() instead of set_blocksize() and verify the
-	  return value.
-	- Use sb_bread() instead of bread() throughout.
-	- Add index_vcn_size{_bits} to ntfs_inode structure to store the size
-	  of a directory index block vcn. Apply resulting simplifications in
-	  dir.c everywhere.
-	- Fix a small bug somewhere (but forgot what it was).
-	- Change ntfs_{debug,error,warning} to enable gcc to do type checking
-	  on the printf-format parameter list and fix bugs reported by gcc
-	  as a result. (Richard Russon)
-	- Move inode allocation strategy to Al's new stuff but maintain the
-	  divorce of ntfs_inode from struct inode. To achieve this we have two
-	  separate slab caches, one for big ntfs inodes containing a struct
-	  inode and pure ntfs inodes and at the same time fix some faulty
-	  error code paths in ntfs_read_inode().
-	- Show mount options in proc (inode.c::ntfs_show_options()).
-
-tng-0.0.4 - Big changes, getting in line with Al Viro's comments.
-
-	- Modified (un)map_mft_record functions to be common for read and write
-	  case. To specify which is which, added extra parameter at front of
-	  parameter list. Pass either READ or WRITE to this, each has the
-	  obvious meaning.
-	- General cleanups to allow for easier folding in vi.
-	- attrib.c::decompress_mapping_pairs() now accepts the old runlist
-	  argument, and invokes attrib.c::merge_run_lists() to merge the old
-	  and the new runlists.
-	- Removed attrib.c::find_first_attr().
-	- Implemented loading of attribute list and complete runlist for $MFT.
-	  This means we now cope with $MFT being spread across several mft
-	  records.
-	- Adapt to 2.5.2-pre9 and the changed create_empty_buffers() syntax.
-	- Adapt major/minor/kdev_t/[bk]devname stuff to new 2.5.x kernels.
-	- Make ntfs_volume be allocated via kmalloc() instead of using a slab
-	  cache. There are too little ntfs_volume structures at any one time
-	  to justify a private slab cache.
-	- Fix bogus kmap() use in async io completion. Now use kmap_atomic().
-	  Use KM_BIO_IRQ on advice from IRC/kernel...
-	- Use ntfs_map_page() in map_mft_record() and create ->readpage method
-	  for reading $MFT (ntfs_mft_readpage). In the process create dedicated
-	  address space operations (ntfs_mft_aops) for $MFT inode mapping. Also
-	  removed the now superfluous exports from the kernel core patch.
-	- Fix a bug where kfree() was used instead of ntfs_free().
-	- Change map_mft_record() to take ntfs_inode as argument instead of
-	  vfs inode. Dito for unmap_mft_record(). Adapt all callers.
-	- Add pointer to ntfs_volume to ntfs_inode.
-	- Add mft record number and sequence number to ntfs_inode. Stop using
-	  i_ino and i_generation for in-driver purposes.
-	- Implement attrib.c::merge_run_lists(). (Richard Russon)
-	- Remove use of proper inodes by extent inodes. Move i_ino and
-	  i_generation to ntfs_inode to do this. Apply simplifications that
-	  result and remove iget_no_wait(), etc.
-	- Pass ntfs_inode everywhere in the driver (used to be struct inode).
-	- Add reference counting in ntfs_inode for the ntfs inode itself and
-	  for the mapped mft record.
-	- Extend mft record mapping so we can (un)map extent mft records (new
-	  functions (un)map_extent_mft_record), and so mappings are reference
-	  counted and don't have to happen twice if already mapped - just ref
-	  count increases.
-	- Add -o iocharset as alias to -o nls for backwards compatibility.
-	- The latest core patch is now tiny. In fact just a single additional
-	  export is necessary over the base kernel.
-
-tng-0.0.3 - Cleanups, enhancements, bug fixes.
-
-	- Work on attrib.c::decompress_mapping_pairs() to detect base extents
-	  and setup the runlist appropriately using knowledge provided by the
-	  sizes in the base attribute record.
-	- Balance the get_/put_attr_search_ctx() calls so we don't leak memory
-	  any more.
-	- Introduce ntfs_malloc_nofs() and ntfs_free() to allocate/free a single
-	  page or use vmalloc depending on the amount of memory requested.
-	- Cleanup error output. The __FUNCTION__ "(): " is now added
-	  automatically. Introduced a new header file debug.h to support this
-	  and also moved ntfs_debug() function into it.
-	- Make reading of compressed files more intelligent and especially get
-	  rid of the vmalloc_nofs() from readpage(). This now uses per CPU
-	  buffers (allocated at first mount with cluster size <= 4kiB and
-	  deallocated on last umount with cluster size <= 4kiB), and
-	  asynchronous io for the compressed data using a list of buffer heads.
-	  Er, we use synchronous io as async io only works on whole pages
-	  covered by buffers and not on individual buffer heads...
-	- Bug fix for reading compressed files with sparse compression blocks.
-
-tng-0.0.2 - Now handles larger/fragmented/compressed volumes/files/dirs.
-
-	- Fixed handling of directories when cluster size exceeds index block
-	  size.
-	- Hide DOS only name space directory entries from readdir() but allow
-	  them in lookup(). This should fix the problem that Linux doesn't
-	  support directory hard links, while still allowing access to entries
-	  via their short file name. This also has the benefit of mimicking
-	  what Windows users are used to, so it is the ideal solution.
-	- Implemented sync_page everywhere so no more hangs in D state when
-	  waiting for a page.
-	- Stop using bforget() in favour of brelse().
-	- Stop locking buffers unnecessarily.
-	- Implemented compressed files (inode->mapping contains uncompressed
-	  data, raw compressed data is currently bread() into a vmalloc()ed
-	  memory buffer).
-	- Enable compressed directories. (Their index root is marked compressed
-	  to indicate that new files in that directory should be created
-	  compressed.)
-	- Use vsnprintf rather than vsprintf in the ntfs_error and ntfs_warning
-	  functions. (Thanks to Will Dyson for pointing this out.)
-	- Moved the ntfs_inode and ntfs_volume (the former ntfs_inode_info and
-	  ntfs_sb_info) out of the common inode and super_block structures and
-	  started using the generic_ip and generic_sbp pointers instead. This
-	  makes ntfs entirely private with respect to the kernel tree.
-	- Detect compiler version and abort with error message if gcc less than
-	  2.96 is used.
-	- Fix bug in name comparison function in unistr.c.
-	- Implement attribute lists part 1, the infrastructure: search contexts
-	  and operations, find_external_attr(), lookup_attr()) and make the
-	  code use the infrastructure.
-	- Fix stupid buffer overflow bug that became apparent on larger run
-	  list containing attributes.
-	- Fix bugs in readdir() that became apparent on larger directories.
-
-	The driver is now really useful and survives the test
-		find . -type f -exec md5sum "{}" \;
-	without any error messages on a over 1GiB sized partition with >16k
-	files on it, including compressed files and directories and many files
-	and directories with attribute lists.
-
-tng-0.0.1 - The first useful version.
-
-	- Added ntfs_lookup().
-	- Added default upcase generation and handling.
-	- Added compile options to be shown on module init.
-	- Many bug fixes that were "hidden" before.
-	- Update to latest kernel.
-	- Added ntfs_readdir().
-	- Added file operations for mmap(), read(), open() and llseek(). We just
-	  use the generic ones. The whole point of going through implementing
-	  readpage() methods and where possible get_block() call backs is that
-	  this allows us to make use of the generic high level methods provided
-	  by the kernel.
-
-	The driver is now actually useful! Yey. (-: It undoubtedly has got bugs
-	though and it doesn't implement accesssing compressed files yet. Also,
-	accessing files with attribute list attributes is not implemented yet
-	either. But for small or simple filesystems it should work and allow
-	you to list directories, use stat on directory entries and the file
-	system, open, read, mmap and llseek around in files. A big mile stone
-	has been reached!
-
-tng-0.0.0 - Initial version tag.
-
-	Initial driver implementation. The driver can mount and umount simple
-	NTFS filesystems (i.e. ones without attribute lists in the system
-	files). If the mount fails there might be problems in the error handling
-	code paths, so be warned. Otherwise it seems to be loading the system
-	files nicely and the mft record read mapping/unmapping seems to be
-	working nicely, too. Proof of inode metadata in the page cache and non-
-	resident file unnamed stream data in the page cache concepts is thus
-	complete.
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
index 5a9e344..9173e82 100644
--- a/fs/ntfs/dir.c
+++ b/fs/ntfs/dir.c
@@ -1545,7 +1545,7 @@
  		write_inode_now(bmp_vi, !datasync);
 		iput(bmp_vi);
 	}
-	ret = ntfs_write_inode(vi, 1);
+	ret = __ntfs_write_inode(vi, 1);
 	write_inode_now(vi, !datasync);
 	err = sync_blockdev(vi->i_sb->s_bdev);
 	if (unlikely(err && !ret))
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 43179dd..b681c71 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2182,7 +2182,7 @@
 	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
 	BUG_ON(S_ISDIR(vi->i_mode));
 	if (!datasync || !NInoNonResident(NTFS_I(vi)))
-		ret = ntfs_write_inode(vi, 1);
+		ret = __ntfs_write_inode(vi, 1);
 	write_inode_now(vi, !datasync);
 	/*
 	 * NOTE: If we were to use mapping->private_list (see ext2 and
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index dc2505a..4b57fb1 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -2957,7 +2957,7 @@
  *
  * Return 0 on success and -errno on error.
  */
-int ntfs_write_inode(struct inode *vi, int sync)
+int __ntfs_write_inode(struct inode *vi, int sync)
 {
 	sle64 nt;
 	ntfs_inode *ni = NTFS_I(vi);
diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h
index 117eaf8..9a11354 100644
--- a/fs/ntfs/inode.h
+++ b/fs/ntfs/inode.h
@@ -307,12 +307,12 @@
 
 extern int ntfs_setattr(struct dentry *dentry, struct iattr *attr);
 
-extern int ntfs_write_inode(struct inode *vi, int sync);
+extern int __ntfs_write_inode(struct inode *vi, int sync);
 
 static inline void ntfs_commit_inode(struct inode *vi)
 {
 	if (!is_bad_inode(vi))
-		ntfs_write_inode(vi, 1);
+		__ntfs_write_inode(vi, 1);
 	return;
 }
 
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 80b0477..1cf39df 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -39,6 +39,7 @@
 #include "dir.h"
 #include "debug.h"
 #include "index.h"
+#include "inode.h"
 #include "aops.h"
 #include "layout.h"
 #include "malloc.h"
@@ -2662,6 +2663,13 @@
 	return 0;
 }
 
+#ifdef NTFS_RW
+static int ntfs_write_inode(struct inode *vi, struct writeback_control *wbc)
+{
+	return __ntfs_write_inode(vi, wbc->sync_mode == WB_SYNC_ALL);
+}
+#endif
+
 /**
  * The complete super operations.
  */
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index 600d2d2..791c088 100644
--- a/fs/ocfs2/Makefile
+++ b/fs/ocfs2/Makefile
@@ -46,6 +46,7 @@
 ocfs2_stack_o2cb-objs := stack_o2cb.o
 ocfs2_stack_user-objs := stack_user.o
 
+obj-$(CONFIG_OCFS2_FS) += dlmfs/
 # cluster/ is always needed when OCFS2_FS for masklog support
 obj-$(CONFIG_OCFS2_FS) += cluster/
 obj-$(CONFIG_OCFS2_FS_O2CB) += dlm/
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index d17bdc7..9f8bd91 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -1050,7 +1050,8 @@
 			strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);
 			eb->h_blkno = cpu_to_le64(first_blkno);
 			eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
-			eb->h_suballoc_slot = cpu_to_le16(osb->slot_num);
+			eb->h_suballoc_slot =
+				cpu_to_le16(meta_ac->ac_alloc_slot);
 			eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 			eb->h_list.l_count =
 				cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));
@@ -5712,7 +5713,7 @@
 		goto out;
 	}
 
-	vfs_dq_free_space_nodirty(inode,
+	dquot_free_space_nodirty(inode,
 				  ocfs2_clusters_to_bytes(inode->i_sb, len));
 
 	ret = ocfs2_remove_extent(handle, et, cpos, len, meta_ac, dealloc);
@@ -6037,7 +6038,7 @@
 	if (status < 0)
 		mlog_errno(status);
 	else
-		ocfs2_init_inode_steal_slot(osb);
+		ocfs2_init_steal_slots(osb);
 
 	mlog_exit(status);
 }
@@ -6935,7 +6936,7 @@
 		goto bail;
 	}
 
-	vfs_dq_free_space_nodirty(inode,
+	dquot_free_space_nodirty(inode,
 			ocfs2_clusters_to_bytes(osb->sb, clusters_to_del));
 	spin_lock(&OCFS2_I(inode)->ip_lock);
 	OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters) -
@@ -7300,11 +7301,10 @@
 		unsigned int page_end;
 		u64 phys;
 
-		if (vfs_dq_alloc_space_nodirty(inode,
-				       ocfs2_clusters_to_bytes(osb->sb, 1))) {
-			ret = -EDQUOT;
+		ret = dquot_alloc_space_nodirty(inode,
+				       ocfs2_clusters_to_bytes(osb->sb, 1));
+		if (ret)
 			goto out_commit;
-		}
 		did_quota = 1;
 
 		ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off,
@@ -7380,7 +7380,7 @@
 
 out_commit:
 	if (ret < 0 && did_quota)
-		vfs_dq_free_space_nodirty(inode,
+		dquot_free_space_nodirty(inode,
 					  ocfs2_clusters_to_bytes(osb->sb, 1));
 
 	ocfs2_commit_trans(osb, handle);
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 7e9df11..21441dd 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -577,8 +577,9 @@
 		goto bail;
 	}
 
-	/* We should already CoW the refcounted extent. */
-	BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED);
+	/* We should already CoW the refcounted extent in case of create. */
+	BUG_ON(create && (ext_flags & OCFS2_EXT_REFCOUNTED));
+
 	/*
 	 * get_more_blocks() expects us to describe a hole by clearing
 	 * the mapped bit on bh_result().
@@ -1763,10 +1764,11 @@
 
 	wc->w_handle = handle;
 
-	if (clusters_to_alloc && vfs_dq_alloc_space_nodirty(inode,
-			ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc))) {
-		ret = -EDQUOT;
-		goto out_commit;
+	if (clusters_to_alloc) {
+		ret = dquot_alloc_space_nodirty(inode,
+			ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc));
+		if (ret)
+			goto out_commit;
 	}
 	/*
 	 * We don't want this to fail in ocfs2_write_end(), so do it
@@ -1809,7 +1811,7 @@
 	return 0;
 out_quota:
 	if (clusters_to_alloc)
-		vfs_dq_free_space(inode,
+		dquot_free_space(inode,
 			  ocfs2_clusters_to_bytes(osb->sb, clusters_to_alloc));
 out_commit:
 	ocfs2_commit_trans(osb, handle);
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index 1cd2934..3bb928a 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -112,6 +112,7 @@
 	define_mask(XATTR),
 	define_mask(QUOTA),
 	define_mask(REFCOUNT),
+	define_mask(BASTS),
 	define_mask(ERROR),
 	define_mask(NOTICE),
 	define_mask(KTHREAD),
@@ -135,7 +136,7 @@
 	return mlog_mask_store(mlog_attr->mask, buf, count);
 }
 
-static struct sysfs_ops mlog_attr_ops = {
+static const struct sysfs_ops mlog_attr_ops = {
 	.show  = mlog_show,
 	.store = mlog_store,
 };
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index 9b4d117..3dfddbe 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -114,6 +114,7 @@
 #define ML_XATTR	0x0000000020000000ULL /* ocfs2 extended attributes */
 #define ML_QUOTA	0x0000000040000000ULL /* ocfs2 quota operations */
 #define ML_REFCOUNT	0x0000000080000000ULL /* refcount tree operations */
+#define ML_BASTS	0x0000001000000000ULL /* dlmglue asts and basts */
 /* bits that are infrequently given and frequently matched in the high word */
 #define ML_ERROR	0x0000000100000000ULL /* sent to KERN_ERR */
 #define ML_NOTICE	0x0000000200000000ULL /* setn to KERN_NOTICE */
@@ -194,9 +195,9 @@
  * previous token if args expands to nothing.
  */
 #define __mlog_printk(level, fmt, args...)				\
-	printk(level "(%u,%lu):%s:%d " fmt, task_pid_nr(current),	\
-	       __mlog_cpu_guess, __PRETTY_FUNCTION__, __LINE__ ,	\
-	       ##args)
+	printk(level "(%s,%u,%lu):%s:%d " fmt, current->comm,		\
+	       task_pid_nr(current), __mlog_cpu_guess,			\
+	       __PRETTY_FUNCTION__, __LINE__ , ##args)
 
 #define mlog(mask, fmt, args...) do {					\
 	u64 __m = MLOG_MASK_PREFIX | (mask);				\
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index d8d0c65..73e743e 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -72,9 +72,9 @@
 
 #include "tcp_internal.h"
 
-#define SC_NODEF_FMT "node %s (num %u) at %u.%u.%u.%u:%u"
+#define SC_NODEF_FMT "node %s (num %u) at %pI4:%u"
 #define SC_NODEF_ARGS(sc) sc->sc_node->nd_name, sc->sc_node->nd_num,	\
-			  NIPQUAD(sc->sc_node->nd_ipv4_address),	\
+			  &sc->sc_node->nd_ipv4_address,		\
 			  ntohs(sc->sc_node->nd_ipv4_port)
 
 /*
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index 28c3ec2..efd77d0 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -2439,7 +2439,7 @@
 	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
 	memset(dx_root, 0, osb->sb->s_blocksize);
 	strcpy(dx_root->dr_signature, OCFS2_DX_ROOT_SIGNATURE);
-	dx_root->dr_suballoc_slot = cpu_to_le16(osb->slot_num);
+	dx_root->dr_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
 	dx_root->dr_suballoc_bit = cpu_to_le16(dr_suballoc_bit);
 	dx_root->dr_fs_generation = cpu_to_le32(osb->fs_generation);
 	dx_root->dr_blkno = cpu_to_le64(dr_blkno);
@@ -2964,12 +2964,10 @@
 		goto out;
 	}
 
-	if (vfs_dq_alloc_space_nodirty(dir,
-				ocfs2_clusters_to_bytes(osb->sb,
-							alloc + dx_alloc))) {
-		ret = -EDQUOT;
+	ret = dquot_alloc_space_nodirty(dir,
+		ocfs2_clusters_to_bytes(osb->sb, alloc + dx_alloc));
+	if (ret)
 		goto out_commit;
-	}
 	did_quota = 1;
 
 	if (ocfs2_supports_indexed_dirs(osb) && !dx_inline) {
@@ -3178,7 +3176,7 @@
 
 out_commit:
 	if (ret < 0 && did_quota)
-		vfs_dq_free_space_nodirty(dir, bytes_allocated);
+		dquot_free_space_nodirty(dir, bytes_allocated);
 
 	ocfs2_commit_trans(osb, handle);
 
@@ -3221,11 +3219,10 @@
 	if (extend) {
 		u32 offset = OCFS2_I(dir)->ip_clusters;
 
-		if (vfs_dq_alloc_space_nodirty(dir,
-					ocfs2_clusters_to_bytes(sb, 1))) {
-			status = -EDQUOT;
+		status = dquot_alloc_space_nodirty(dir,
+					ocfs2_clusters_to_bytes(sb, 1));
+		if (status)
 			goto bail;
-		}
 		did_quota = 1;
 
 		status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset,
@@ -3254,7 +3251,7 @@
 	status = 0;
 bail:
 	if (did_quota && status < 0)
-		vfs_dq_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1));
+		dquot_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1));
 	mlog_exit(status);
 	return status;
 }
@@ -3889,11 +3886,10 @@
 		goto out;
 	}
 
-	if (vfs_dq_alloc_space_nodirty(dir,
-				       ocfs2_clusters_to_bytes(dir->i_sb, 1))) {
-		ret = -EDQUOT;
+	ret = dquot_alloc_space_nodirty(dir,
+				       ocfs2_clusters_to_bytes(dir->i_sb, 1));
+	if (ret)
 		goto out_commit;
-	}
 	did_quota = 1;
 
 	ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), dx_leaf_bh,
@@ -3983,7 +3979,7 @@
 
 out_commit:
 	if (ret < 0 && did_quota)
-		vfs_dq_free_space_nodirty(dir,
+		dquot_free_space_nodirty(dir,
 				ocfs2_clusters_to_bytes(dir->i_sb, 1));
 
 	ocfs2_commit_trans(osb, handle);
@@ -4165,11 +4161,10 @@
 		goto out;
 	}
 
-	if (vfs_dq_alloc_space_nodirty(dir,
-				       ocfs2_clusters_to_bytes(osb->sb, 1))) {
-		ret = -EDQUOT;
+	ret = dquot_alloc_space_nodirty(dir,
+				       ocfs2_clusters_to_bytes(osb->sb, 1));
+	if (ret)
 		goto out_commit;
-	}
 	did_quota = 1;
 
 	/*
@@ -4229,7 +4224,7 @@
 
 out_commit:
 	if (ret < 0 && did_quota)
-		vfs_dq_free_space_nodirty(dir,
+		dquot_free_space_nodirty(dir,
 					  ocfs2_clusters_to_bytes(dir->i_sb, 1));
 
 	ocfs2_commit_trans(osb, handle);
diff --git a/fs/ocfs2/dlm/Makefile b/fs/ocfs2/dlm/Makefile
index 1903613..dcebf0d 100644
--- a/fs/ocfs2/dlm/Makefile
+++ b/fs/ocfs2/dlm/Makefile
@@ -1,8 +1,7 @@
 EXTRA_CFLAGS += -Ifs/ocfs2
 
-obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o ocfs2_dlmfs.o
+obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o
 
 ocfs2_dlm-objs := dlmdomain.o dlmdebug.o dlmthread.o dlmrecovery.o \
 	dlmmaster.o dlmast.o dlmconvert.o dlmlock.o dlmunlock.o dlmver.o
 
-ocfs2_dlmfs-objs := userdlm.o dlmfs.o dlmfsver.o
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
deleted file mode 100644
index 02bf178..0000000
--- a/fs/ocfs2/dlm/dlmfs.c
+++ /dev/null
@@ -1,652 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * dlmfs.c
- *
- * Code which implements the kernel side of a minimal userspace
- * interface to our DLM. This file handles the virtual file system
- * used for communication with userspace. Credit should go to ramfs,
- * which was a template for the fs side of this module.
- *
- * Copyright (C) 2003, 2004 Oracle.  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 021110-1307, USA.
- */
-
-/* Simple VFS hooks based on: */
-/*
- * Resizable simple ram filesystem for Linux.
- *
- * Copyright (C) 2000 Linus Torvalds.
- *               2000 Transmeta Corp.
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/pagemap.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/highmem.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/backing-dev.h>
-
-#include <asm/uaccess.h>
-
-
-#include "cluster/nodemanager.h"
-#include "cluster/heartbeat.h"
-#include "cluster/tcp.h"
-
-#include "dlmapi.h"
-
-#include "userdlm.h"
-
-#include "dlmfsver.h"
-
-#define MLOG_MASK_PREFIX ML_DLMFS
-#include "cluster/masklog.h"
-
-#include "ocfs2_lockingver.h"
-
-static const struct super_operations dlmfs_ops;
-static const struct file_operations dlmfs_file_operations;
-static const struct inode_operations dlmfs_dir_inode_operations;
-static const struct inode_operations dlmfs_root_inode_operations;
-static const struct inode_operations dlmfs_file_inode_operations;
-static struct kmem_cache *dlmfs_inode_cache;
-
-struct workqueue_struct *user_dlm_worker;
-
-/*
- * This is the userdlmfs locking protocol version.
- *
- * See fs/ocfs2/dlmglue.c for more details on locking versions.
- */
-static const struct dlm_protocol_version user_locking_protocol = {
-	.pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR,
-	.pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR,
-};
-
-/*
- * decodes a set of open flags into a valid lock level and a set of flags.
- * returns < 0 if we have invalid flags
- * flags which mean something to us:
- * O_RDONLY -> PRMODE level
- * O_WRONLY -> EXMODE level
- *
- * O_NONBLOCK -> LKM_NOQUEUE
- */
-static int dlmfs_decode_open_flags(int open_flags,
-				   int *level,
-				   int *flags)
-{
-	if (open_flags & (O_WRONLY|O_RDWR))
-		*level = LKM_EXMODE;
-	else
-		*level = LKM_PRMODE;
-
-	*flags = 0;
-	if (open_flags & O_NONBLOCK)
-		*flags |= LKM_NOQUEUE;
-
-	return 0;
-}
-
-static int dlmfs_file_open(struct inode *inode,
-			   struct file *file)
-{
-	int status, level, flags;
-	struct dlmfs_filp_private *fp = NULL;
-	struct dlmfs_inode_private *ip;
-
-	if (S_ISDIR(inode->i_mode))
-		BUG();
-
-	mlog(0, "open called on inode %lu, flags 0x%x\n", inode->i_ino,
-		file->f_flags);
-
-	status = dlmfs_decode_open_flags(file->f_flags, &level, &flags);
-	if (status < 0)
-		goto bail;
-
-	/* We don't want to honor O_APPEND at read/write time as it
-	 * doesn't make sense for LVB writes. */
-	file->f_flags &= ~O_APPEND;
-
-	fp = kmalloc(sizeof(*fp), GFP_NOFS);
-	if (!fp) {
-		status = -ENOMEM;
-		goto bail;
-	}
-	fp->fp_lock_level = level;
-
-	ip = DLMFS_I(inode);
-
-	status = user_dlm_cluster_lock(&ip->ip_lockres, level, flags);
-	if (status < 0) {
-		/* this is a strange error to return here but I want
-		 * to be able userspace to be able to distinguish a
-		 * valid lock request from one that simply couldn't be
-		 * granted. */
-		if (flags & LKM_NOQUEUE && status == -EAGAIN)
-			status = -ETXTBSY;
-		kfree(fp);
-		goto bail;
-	}
-
-	file->private_data = fp;
-bail:
-	return status;
-}
-
-static int dlmfs_file_release(struct inode *inode,
-			      struct file *file)
-{
-	int level, status;
-	struct dlmfs_inode_private *ip = DLMFS_I(inode);
-	struct dlmfs_filp_private *fp =
-		(struct dlmfs_filp_private *) file->private_data;
-
-	if (S_ISDIR(inode->i_mode))
-		BUG();
-
-	mlog(0, "close called on inode %lu\n", inode->i_ino);
-
-	status = 0;
-	if (fp) {
-		level = fp->fp_lock_level;
-		if (level != LKM_IVMODE)
-			user_dlm_cluster_unlock(&ip->ip_lockres, level);
-
-		kfree(fp);
-		file->private_data = NULL;
-	}
-
-	return 0;
-}
-
-static ssize_t dlmfs_file_read(struct file *filp,
-			       char __user *buf,
-			       size_t count,
-			       loff_t *ppos)
-{
-	int bytes_left;
-	ssize_t readlen;
-	char *lvb_buf;
-	struct inode *inode = filp->f_path.dentry->d_inode;
-
-	mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
-		inode->i_ino, count, *ppos);
-
-	if (*ppos >= i_size_read(inode))
-		return 0;
-
-	if (!count)
-		return 0;
-
-	if (!access_ok(VERIFY_WRITE, buf, count))
-		return -EFAULT;
-
-	/* don't read past the lvb */
-	if ((count + *ppos) > i_size_read(inode))
-		readlen = i_size_read(inode) - *ppos;
-	else
-		readlen = count - *ppos;
-
-	lvb_buf = kmalloc(readlen, GFP_NOFS);
-	if (!lvb_buf)
-		return -ENOMEM;
-
-	user_dlm_read_lvb(inode, lvb_buf, readlen);
-	bytes_left = __copy_to_user(buf, lvb_buf, readlen);
-	readlen -= bytes_left;
-
-	kfree(lvb_buf);
-
-	*ppos = *ppos + readlen;
-
-	mlog(0, "read %zd bytes\n", readlen);
-	return readlen;
-}
-
-static ssize_t dlmfs_file_write(struct file *filp,
-				const char __user *buf,
-				size_t count,
-				loff_t *ppos)
-{
-	int bytes_left;
-	ssize_t writelen;
-	char *lvb_buf;
-	struct inode *inode = filp->f_path.dentry->d_inode;
-
-	mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
-		inode->i_ino, count, *ppos);
-
-	if (*ppos >= i_size_read(inode))
-		return -ENOSPC;
-
-	if (!count)
-		return 0;
-
-	if (!access_ok(VERIFY_READ, buf, count))
-		return -EFAULT;
-
-	/* don't write past the lvb */
-	if ((count + *ppos) > i_size_read(inode))
-		writelen = i_size_read(inode) - *ppos;
-	else
-		writelen = count - *ppos;
-
-	lvb_buf = kmalloc(writelen, GFP_NOFS);
-	if (!lvb_buf)
-		return -ENOMEM;
-
-	bytes_left = copy_from_user(lvb_buf, buf, writelen);
-	writelen -= bytes_left;
-	if (writelen)
-		user_dlm_write_lvb(inode, lvb_buf, writelen);
-
-	kfree(lvb_buf);
-
-	*ppos = *ppos + writelen;
-	mlog(0, "wrote %zd bytes\n", writelen);
-	return writelen;
-}
-
-static void dlmfs_init_once(void *foo)
-{
-	struct dlmfs_inode_private *ip =
-		(struct dlmfs_inode_private *) foo;
-
-	ip->ip_dlm = NULL;
-	ip->ip_parent = NULL;
-
-	inode_init_once(&ip->ip_vfs_inode);
-}
-
-static struct inode *dlmfs_alloc_inode(struct super_block *sb)
-{
-	struct dlmfs_inode_private *ip;
-
-	ip = kmem_cache_alloc(dlmfs_inode_cache, GFP_NOFS);
-	if (!ip)
-		return NULL;
-
-	return &ip->ip_vfs_inode;
-}
-
-static void dlmfs_destroy_inode(struct inode *inode)
-{
-	kmem_cache_free(dlmfs_inode_cache, DLMFS_I(inode));
-}
-
-static void dlmfs_clear_inode(struct inode *inode)
-{
-	int status;
-	struct dlmfs_inode_private *ip;
-
-	if (!inode)
-		return;
-
-	mlog(0, "inode %lu\n", inode->i_ino);
-
-	ip = DLMFS_I(inode);
-
-	if (S_ISREG(inode->i_mode)) {
-		status = user_dlm_destroy_lock(&ip->ip_lockres);
-		if (status < 0)
-			mlog_errno(status);
-		iput(ip->ip_parent);
-		goto clear_fields;
-	}
-
-	mlog(0, "we're a directory, ip->ip_dlm = 0x%p\n", ip->ip_dlm);
-	/* we must be a directory. If required, lets unregister the
-	 * dlm context now. */
-	if (ip->ip_dlm)
-		user_dlm_unregister_context(ip->ip_dlm);
-clear_fields:
-	ip->ip_parent = NULL;
-	ip->ip_dlm = NULL;
-}
-
-static struct backing_dev_info dlmfs_backing_dev_info = {
-	.name		= "ocfs2-dlmfs",
-	.ra_pages	= 0,	/* No readahead */
-	.capabilities	= BDI_CAP_NO_ACCT_AND_WRITEBACK,
-};
-
-static struct inode *dlmfs_get_root_inode(struct super_block *sb)
-{
-	struct inode *inode = new_inode(sb);
-	int mode = S_IFDIR | 0755;
-	struct dlmfs_inode_private *ip;
-
-	if (inode) {
-		ip = DLMFS_I(inode);
-
-		inode->i_mode = mode;
-		inode->i_uid = current_fsuid();
-		inode->i_gid = current_fsgid();
-		inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-		inc_nlink(inode);
-
-		inode->i_fop = &simple_dir_operations;
-		inode->i_op = &dlmfs_root_inode_operations;
-	}
-
-	return inode;
-}
-
-static struct inode *dlmfs_get_inode(struct inode *parent,
-				     struct dentry *dentry,
-				     int mode)
-{
-	struct super_block *sb = parent->i_sb;
-	struct inode * inode = new_inode(sb);
-	struct dlmfs_inode_private *ip;
-
-	if (!inode)
-		return NULL;
-
-	inode->i_mode = mode;
-	inode->i_uid = current_fsuid();
-	inode->i_gid = current_fsgid();
-	inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
-	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-
-	ip = DLMFS_I(inode);
-	ip->ip_dlm = DLMFS_I(parent)->ip_dlm;
-
-	switch (mode & S_IFMT) {
-	default:
-		/* for now we don't support anything other than
-		 * directories and regular files. */
-		BUG();
-		break;
-	case S_IFREG:
-		inode->i_op = &dlmfs_file_inode_operations;
-		inode->i_fop = &dlmfs_file_operations;
-
-		i_size_write(inode,  DLM_LVB_LEN);
-
-		user_dlm_lock_res_init(&ip->ip_lockres, dentry);
-
-		/* released at clear_inode time, this insures that we
-		 * get to drop the dlm reference on each lock *before*
-		 * we call the unregister code for releasing parent
-		 * directories. */
-		ip->ip_parent = igrab(parent);
-		BUG_ON(!ip->ip_parent);
-		break;
-	case S_IFDIR:
-		inode->i_op = &dlmfs_dir_inode_operations;
-		inode->i_fop = &simple_dir_operations;
-
-		/* directory inodes start off with i_nlink ==
-		 * 2 (for "." entry) */
-		inc_nlink(inode);
-		break;
-	}
-
-	if (parent->i_mode & S_ISGID) {
-		inode->i_gid = parent->i_gid;
-		if (S_ISDIR(mode))
-			inode->i_mode |= S_ISGID;
-	}
-
-	return inode;
-}
-
-/*
- * File creation. Allocate an inode, and we're done..
- */
-/* SMP-safe */
-static int dlmfs_mkdir(struct inode * dir,
-		       struct dentry * dentry,
-		       int mode)
-{
-	int status;
-	struct inode *inode = NULL;
-	struct qstr *domain = &dentry->d_name;
-	struct dlmfs_inode_private *ip;
-	struct dlm_ctxt *dlm;
-	struct dlm_protocol_version proto = user_locking_protocol;
-
-	mlog(0, "mkdir %.*s\n", domain->len, domain->name);
-
-	/* verify that we have a proper domain */
-	if (domain->len >= O2NM_MAX_NAME_LEN) {
-		status = -EINVAL;
-		mlog(ML_ERROR, "invalid domain name for directory.\n");
-		goto bail;
-	}
-
-	inode = dlmfs_get_inode(dir, dentry, mode | S_IFDIR);
-	if (!inode) {
-		status = -ENOMEM;
-		mlog_errno(status);
-		goto bail;
-	}
-
-	ip = DLMFS_I(inode);
-
-	dlm = user_dlm_register_context(domain, &proto);
-	if (IS_ERR(dlm)) {
-		status = PTR_ERR(dlm);
-		mlog(ML_ERROR, "Error %d could not register domain \"%.*s\"\n",
-		     status, domain->len, domain->name);
-		goto bail;
-	}
-	ip->ip_dlm = dlm;
-
-	inc_nlink(dir);
-	d_instantiate(dentry, inode);
-	dget(dentry);	/* Extra count - pin the dentry in core */
-
-	status = 0;
-bail:
-	if (status < 0)
-		iput(inode);
-	return status;
-}
-
-static int dlmfs_create(struct inode *dir,
-			struct dentry *dentry,
-			int mode,
-			struct nameidata *nd)
-{
-	int status = 0;
-	struct inode *inode;
-	struct qstr *name = &dentry->d_name;
-
-	mlog(0, "create %.*s\n", name->len, name->name);
-
-	/* verify name is valid and doesn't contain any dlm reserved
-	 * characters */
-	if (name->len >= USER_DLM_LOCK_ID_MAX_LEN ||
-	    name->name[0] == '$') {
-		status = -EINVAL;
-		mlog(ML_ERROR, "invalid lock name, %.*s\n", name->len,
-		     name->name);
-		goto bail;
-	}
-
-	inode = dlmfs_get_inode(dir, dentry, mode | S_IFREG);
-	if (!inode) {
-		status = -ENOMEM;
-		mlog_errno(status);
-		goto bail;
-	}
-
-	d_instantiate(dentry, inode);
-	dget(dentry);	/* Extra count - pin the dentry in core */
-bail:
-	return status;
-}
-
-static int dlmfs_unlink(struct inode *dir,
-			struct dentry *dentry)
-{
-	int status;
-	struct inode *inode = dentry->d_inode;
-
-	mlog(0, "unlink inode %lu\n", inode->i_ino);
-
-	/* if there are no current holders, or none that are waiting
-	 * to acquire a lock, this basically destroys our lockres. */
-	status = user_dlm_destroy_lock(&DLMFS_I(inode)->ip_lockres);
-	if (status < 0) {
-		mlog(ML_ERROR, "unlink %.*s, error %d from destroy\n",
-		     dentry->d_name.len, dentry->d_name.name, status);
-		goto bail;
-	}
-	status = simple_unlink(dir, dentry);
-bail:
-	return status;
-}
-
-static int dlmfs_fill_super(struct super_block * sb,
-			    void * data,
-			    int silent)
-{
-	struct inode * inode;
-	struct dentry * root;
-
-	sb->s_maxbytes = MAX_LFS_FILESIZE;
-	sb->s_blocksize = PAGE_CACHE_SIZE;
-	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-	sb->s_magic = DLMFS_MAGIC;
-	sb->s_op = &dlmfs_ops;
-	inode = dlmfs_get_root_inode(sb);
-	if (!inode)
-		return -ENOMEM;
-
-	root = d_alloc_root(inode);
-	if (!root) {
-		iput(inode);
-		return -ENOMEM;
-	}
-	sb->s_root = root;
-	return 0;
-}
-
-static const struct file_operations dlmfs_file_operations = {
-	.open		= dlmfs_file_open,
-	.release	= dlmfs_file_release,
-	.read		= dlmfs_file_read,
-	.write		= dlmfs_file_write,
-};
-
-static const struct inode_operations dlmfs_dir_inode_operations = {
-	.create		= dlmfs_create,
-	.lookup		= simple_lookup,
-	.unlink		= dlmfs_unlink,
-};
-
-/* this way we can restrict mkdir to only the toplevel of the fs. */
-static const struct inode_operations dlmfs_root_inode_operations = {
-	.lookup		= simple_lookup,
-	.mkdir		= dlmfs_mkdir,
-	.rmdir		= simple_rmdir,
-};
-
-static const struct super_operations dlmfs_ops = {
-	.statfs		= simple_statfs,
-	.alloc_inode	= dlmfs_alloc_inode,
-	.destroy_inode	= dlmfs_destroy_inode,
-	.clear_inode	= dlmfs_clear_inode,
-	.drop_inode	= generic_delete_inode,
-};
-
-static const struct inode_operations dlmfs_file_inode_operations = {
-	.getattr	= simple_getattr,
-};
-
-static int dlmfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
-{
-	return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super, mnt);
-}
-
-static struct file_system_type dlmfs_fs_type = {
-	.owner		= THIS_MODULE,
-	.name		= "ocfs2_dlmfs",
-	.get_sb		= dlmfs_get_sb,
-	.kill_sb	= kill_litter_super,
-};
-
-static int __init init_dlmfs_fs(void)
-{
-	int status;
-	int cleanup_inode = 0, cleanup_worker = 0;
-
-	dlmfs_print_version();
-
-	status = bdi_init(&dlmfs_backing_dev_info);
-	if (status)
-		return status;
-
-	dlmfs_inode_cache = kmem_cache_create("dlmfs_inode_cache",
-				sizeof(struct dlmfs_inode_private),
-				0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
-					SLAB_MEM_SPREAD),
-				dlmfs_init_once);
-	if (!dlmfs_inode_cache) {
-		status = -ENOMEM;
-		goto bail;
-	}
-	cleanup_inode = 1;
-
-	user_dlm_worker = create_singlethread_workqueue("user_dlm");
-	if (!user_dlm_worker) {
-		status = -ENOMEM;
-		goto bail;
-	}
-	cleanup_worker = 1;
-
-	status = register_filesystem(&dlmfs_fs_type);
-bail:
-	if (status) {
-		if (cleanup_inode)
-			kmem_cache_destroy(dlmfs_inode_cache);
-		if (cleanup_worker)
-			destroy_workqueue(user_dlm_worker);
-		bdi_destroy(&dlmfs_backing_dev_info);
-	} else
-		printk("OCFS2 User DLM kernel interface loaded\n");
-	return status;
-}
-
-static void __exit exit_dlmfs_fs(void)
-{
-	unregister_filesystem(&dlmfs_fs_type);
-
-	flush_workqueue(user_dlm_worker);
-	destroy_workqueue(user_dlm_worker);
-
-	kmem_cache_destroy(dlmfs_inode_cache);
-
-	bdi_destroy(&dlmfs_backing_dev_info);
-}
-
-MODULE_AUTHOR("Oracle");
-MODULE_LICENSE("GPL");
-
-module_init(init_dlmfs_fs)
-module_exit(exit_dlmfs_fs)
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 344bcf9..b4f99de 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -310,7 +310,7 @@
 	mlog(0, "dlm thread running for %s...\n", dlm->name);
 
 	while (!kthread_should_stop()) {
-		if (dlm_joined(dlm)) {
+		if (dlm_domain_fully_joined(dlm)) {
 			status = dlm_do_recovery(dlm);
 			if (status == -EAGAIN) {
 				/* do not sleep, recheck immediately. */
diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c
deleted file mode 100644
index 4cb1d3d..0000000
--- a/fs/ocfs2/dlm/userdlm.c
+++ /dev/null
@@ -1,676 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * userdlm.c
- *
- * Code which implements the kernel side of a minimal userspace
- * interface to our DLM.
- *
- * Many of the functions here are pared down versions of dlmglue.c
- * functions.
- *
- * Copyright (C) 2003, 2004 Oracle.  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 021110-1307, USA.
- */
-
-#include <linux/signal.h>
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/types.h>
-#include <linux/crc32.h>
-
-
-#include "cluster/nodemanager.h"
-#include "cluster/heartbeat.h"
-#include "cluster/tcp.h"
-
-#include "dlmapi.h"
-
-#include "userdlm.h"
-
-#define MLOG_MASK_PREFIX ML_DLMFS
-#include "cluster/masklog.h"
-
-static inline int user_check_wait_flag(struct user_lock_res *lockres,
-				       int flag)
-{
-	int ret;
-
-	spin_lock(&lockres->l_lock);
-	ret = lockres->l_flags & flag;
-	spin_unlock(&lockres->l_lock);
-
-	return ret;
-}
-
-static inline void user_wait_on_busy_lock(struct user_lock_res *lockres)
-
-{
-	wait_event(lockres->l_event,
-		   !user_check_wait_flag(lockres, USER_LOCK_BUSY));
-}
-
-static inline void user_wait_on_blocked_lock(struct user_lock_res *lockres)
-
-{
-	wait_event(lockres->l_event,
-		   !user_check_wait_flag(lockres, USER_LOCK_BLOCKED));
-}
-
-/* I heart container_of... */
-static inline struct dlm_ctxt *
-dlm_ctxt_from_user_lockres(struct user_lock_res *lockres)
-{
-	struct dlmfs_inode_private *ip;
-
-	ip = container_of(lockres,
-			  struct dlmfs_inode_private,
-			  ip_lockres);
-	return ip->ip_dlm;
-}
-
-static struct inode *
-user_dlm_inode_from_user_lockres(struct user_lock_res *lockres)
-{
-	struct dlmfs_inode_private *ip;
-
-	ip = container_of(lockres,
-			  struct dlmfs_inode_private,
-			  ip_lockres);
-	return &ip->ip_vfs_inode;
-}
-
-static inline void user_recover_from_dlm_error(struct user_lock_res *lockres)
-{
-	spin_lock(&lockres->l_lock);
-	lockres->l_flags &= ~USER_LOCK_BUSY;
-	spin_unlock(&lockres->l_lock);
-}
-
-#define user_log_dlm_error(_func, _stat, _lockres) do {			\
-	mlog(ML_ERROR, "Dlm error \"%s\" while calling %s on "		\
-		"resource %.*s: %s\n", dlm_errname(_stat), _func,	\
-		_lockres->l_namelen, _lockres->l_name, dlm_errmsg(_stat)); \
-} while (0)
-
-/* WARNING: This function lives in a world where the only three lock
- * levels are EX, PR, and NL. It *will* have to be adjusted when more
- * lock types are added. */
-static inline int user_highest_compat_lock_level(int level)
-{
-	int new_level = LKM_EXMODE;
-
-	if (level == LKM_EXMODE)
-		new_level = LKM_NLMODE;
-	else if (level == LKM_PRMODE)
-		new_level = LKM_PRMODE;
-	return new_level;
-}
-
-static void user_ast(void *opaque)
-{
-	struct user_lock_res *lockres = opaque;
-	struct dlm_lockstatus *lksb;
-
-	mlog(0, "AST fired for lockres %.*s\n", lockres->l_namelen,
-	     lockres->l_name);
-
-	spin_lock(&lockres->l_lock);
-
-	lksb = &(lockres->l_lksb);
-	if (lksb->status != DLM_NORMAL) {
-		mlog(ML_ERROR, "lksb status value of %u on lockres %.*s\n",
-		     lksb->status, lockres->l_namelen, lockres->l_name);
-		spin_unlock(&lockres->l_lock);
-		return;
-	}
-
-	mlog_bug_on_msg(lockres->l_requested == LKM_IVMODE,
-			"Lockres %.*s, requested ivmode. flags 0x%x\n",
-			lockres->l_namelen, lockres->l_name, lockres->l_flags);
-
-	/* we're downconverting. */
-	if (lockres->l_requested < lockres->l_level) {
-		if (lockres->l_requested <=
-		    user_highest_compat_lock_level(lockres->l_blocking)) {
-			lockres->l_blocking = LKM_NLMODE;
-			lockres->l_flags &= ~USER_LOCK_BLOCKED;
-		}
-	}
-
-	lockres->l_level = lockres->l_requested;
-	lockres->l_requested = LKM_IVMODE;
-	lockres->l_flags |= USER_LOCK_ATTACHED;
-	lockres->l_flags &= ~USER_LOCK_BUSY;
-
-	spin_unlock(&lockres->l_lock);
-
-	wake_up(&lockres->l_event);
-}
-
-static inline void user_dlm_grab_inode_ref(struct user_lock_res *lockres)
-{
-	struct inode *inode;
-	inode = user_dlm_inode_from_user_lockres(lockres);
-	if (!igrab(inode))
-		BUG();
-}
-
-static void user_dlm_unblock_lock(struct work_struct *work);
-
-static void __user_dlm_queue_lockres(struct user_lock_res *lockres)
-{
-	if (!(lockres->l_flags & USER_LOCK_QUEUED)) {
-		user_dlm_grab_inode_ref(lockres);
-
-		INIT_WORK(&lockres->l_work, user_dlm_unblock_lock);
-
-		queue_work(user_dlm_worker, &lockres->l_work);
-		lockres->l_flags |= USER_LOCK_QUEUED;
-	}
-}
-
-static void __user_dlm_cond_queue_lockres(struct user_lock_res *lockres)
-{
-	int queue = 0;
-
-	if (!(lockres->l_flags & USER_LOCK_BLOCKED))
-		return;
-
-	switch (lockres->l_blocking) {
-	case LKM_EXMODE:
-		if (!lockres->l_ex_holders && !lockres->l_ro_holders)
-			queue = 1;
-		break;
-	case LKM_PRMODE:
-		if (!lockres->l_ex_holders)
-			queue = 1;
-		break;
-	default:
-		BUG();
-	}
-
-	if (queue)
-		__user_dlm_queue_lockres(lockres);
-}
-
-static void user_bast(void *opaque, int level)
-{
-	struct user_lock_res *lockres = opaque;
-
-	mlog(0, "Blocking AST fired for lockres %.*s. Blocking level %d\n",
-	     lockres->l_namelen, lockres->l_name, level);
-
-	spin_lock(&lockres->l_lock);
-	lockres->l_flags |= USER_LOCK_BLOCKED;
-	if (level > lockres->l_blocking)
-		lockres->l_blocking = level;
-
-	__user_dlm_queue_lockres(lockres);
-	spin_unlock(&lockres->l_lock);
-
-	wake_up(&lockres->l_event);
-}
-
-static void user_unlock_ast(void *opaque, enum dlm_status status)
-{
-	struct user_lock_res *lockres = opaque;
-
-	mlog(0, "UNLOCK AST called on lock %.*s\n", lockres->l_namelen,
-	     lockres->l_name);
-
-	if (status != DLM_NORMAL && status != DLM_CANCELGRANT)
-		mlog(ML_ERROR, "Dlm returns status %d\n", status);
-
-	spin_lock(&lockres->l_lock);
-	/* The teardown flag gets set early during the unlock process,
-	 * so test the cancel flag to make sure that this ast isn't
-	 * for a concurrent cancel. */
-	if (lockres->l_flags & USER_LOCK_IN_TEARDOWN
-	    && !(lockres->l_flags & USER_LOCK_IN_CANCEL)) {
-		lockres->l_level = LKM_IVMODE;
-	} else if (status == DLM_CANCELGRANT) {
-		/* We tried to cancel a convert request, but it was
-		 * already granted. Don't clear the busy flag - the
-		 * ast should've done this already. */
-		BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL));
-		lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
-		goto out_noclear;
-	} else {
-		BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL));
-		/* Cancel succeeded, we want to re-queue */
-		lockres->l_requested = LKM_IVMODE; /* cancel an
-						    * upconvert
-						    * request. */
-		lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
-		/* we want the unblock thread to look at it again
-		 * now. */
-		if (lockres->l_flags & USER_LOCK_BLOCKED)
-			__user_dlm_queue_lockres(lockres);
-	}
-
-	lockres->l_flags &= ~USER_LOCK_BUSY;
-out_noclear:
-	spin_unlock(&lockres->l_lock);
-
-	wake_up(&lockres->l_event);
-}
-
-static inline void user_dlm_drop_inode_ref(struct user_lock_res *lockres)
-{
-	struct inode *inode;
-	inode = user_dlm_inode_from_user_lockres(lockres);
-	iput(inode);
-}
-
-static void user_dlm_unblock_lock(struct work_struct *work)
-{
-	int new_level, status;
-	struct user_lock_res *lockres =
-		container_of(work, struct user_lock_res, l_work);
-	struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres);
-
-	mlog(0, "processing lockres %.*s\n", lockres->l_namelen,
-	     lockres->l_name);
-
-	spin_lock(&lockres->l_lock);
-
-	mlog_bug_on_msg(!(lockres->l_flags & USER_LOCK_QUEUED),
-			"Lockres %.*s, flags 0x%x\n",
-			lockres->l_namelen, lockres->l_name, lockres->l_flags);
-
-	/* notice that we don't clear USER_LOCK_BLOCKED here. If it's
-	 * set, we want user_ast clear it. */
-	lockres->l_flags &= ~USER_LOCK_QUEUED;
-
-	/* It's valid to get here and no longer be blocked - if we get
-	 * several basts in a row, we might be queued by the first
-	 * one, the unblock thread might run and clear the queued
-	 * flag, and finally we might get another bast which re-queues
-	 * us before our ast for the downconvert is called. */
-	if (!(lockres->l_flags & USER_LOCK_BLOCKED)) {
-		spin_unlock(&lockres->l_lock);
-		goto drop_ref;
-	}
-
-	if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
-		spin_unlock(&lockres->l_lock);
-		goto drop_ref;
-	}
-
-	if (lockres->l_flags & USER_LOCK_BUSY) {
-		if (lockres->l_flags & USER_LOCK_IN_CANCEL) {
-			spin_unlock(&lockres->l_lock);
-			goto drop_ref;
-		}
-
-		lockres->l_flags |= USER_LOCK_IN_CANCEL;
-		spin_unlock(&lockres->l_lock);
-
-		status = dlmunlock(dlm,
-				   &lockres->l_lksb,
-				   LKM_CANCEL,
-				   user_unlock_ast,
-				   lockres);
-		if (status != DLM_NORMAL)
-			user_log_dlm_error("dlmunlock", status, lockres);
-		goto drop_ref;
-	}
-
-	/* If there are still incompat holders, we can exit safely
-	 * without worrying about re-queueing this lock as that will
-	 * happen on the last call to user_cluster_unlock. */
-	if ((lockres->l_blocking == LKM_EXMODE)
-	    && (lockres->l_ex_holders || lockres->l_ro_holders)) {
-		spin_unlock(&lockres->l_lock);
-		mlog(0, "can't downconvert for ex: ro = %u, ex = %u\n",
-			lockres->l_ro_holders, lockres->l_ex_holders);
-		goto drop_ref;
-	}
-
-	if ((lockres->l_blocking == LKM_PRMODE)
-	    && lockres->l_ex_holders) {
-		spin_unlock(&lockres->l_lock);
-		mlog(0, "can't downconvert for pr: ex = %u\n",
-			lockres->l_ex_holders);
-		goto drop_ref;
-	}
-
-	/* yay, we can downconvert now. */
-	new_level = user_highest_compat_lock_level(lockres->l_blocking);
-	lockres->l_requested = new_level;
-	lockres->l_flags |= USER_LOCK_BUSY;
-	mlog(0, "Downconvert lock from %d to %d\n",
-		lockres->l_level, new_level);
-	spin_unlock(&lockres->l_lock);
-
-	/* need lock downconvert request now... */
-	status = dlmlock(dlm,
-			 new_level,
-			 &lockres->l_lksb,
-			 LKM_CONVERT|LKM_VALBLK,
-			 lockres->l_name,
-			 lockres->l_namelen,
-			 user_ast,
-			 lockres,
-			 user_bast);
-	if (status != DLM_NORMAL) {
-		user_log_dlm_error("dlmlock", status, lockres);
-		user_recover_from_dlm_error(lockres);
-	}
-
-drop_ref:
-	user_dlm_drop_inode_ref(lockres);
-}
-
-static inline void user_dlm_inc_holders(struct user_lock_res *lockres,
-					int level)
-{
-	switch(level) {
-	case LKM_EXMODE:
-		lockres->l_ex_holders++;
-		break;
-	case LKM_PRMODE:
-		lockres->l_ro_holders++;
-		break;
-	default:
-		BUG();
-	}
-}
-
-/* predict what lock level we'll be dropping down to on behalf
- * of another node, and return true if the currently wanted
- * level will be compatible with it. */
-static inline int
-user_may_continue_on_blocked_lock(struct user_lock_res *lockres,
-				  int wanted)
-{
-	BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED));
-
-	return wanted <= user_highest_compat_lock_level(lockres->l_blocking);
-}
-
-int user_dlm_cluster_lock(struct user_lock_res *lockres,
-			  int level,
-			  int lkm_flags)
-{
-	int status, local_flags;
-	struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres);
-
-	if (level != LKM_EXMODE &&
-	    level != LKM_PRMODE) {
-		mlog(ML_ERROR, "lockres %.*s: invalid request!\n",
-		     lockres->l_namelen, lockres->l_name);
-		status = -EINVAL;
-		goto bail;
-	}
-
-	mlog(0, "lockres %.*s: asking for %s lock, passed flags = 0x%x\n",
-	     lockres->l_namelen, lockres->l_name,
-	     (level == LKM_EXMODE) ? "LKM_EXMODE" : "LKM_PRMODE",
-	     lkm_flags);
-
-again:
-	if (signal_pending(current)) {
-		status = -ERESTARTSYS;
-		goto bail;
-	}
-
-	spin_lock(&lockres->l_lock);
-
-	/* We only compare against the currently granted level
-	 * here. If the lock is blocked waiting on a downconvert,
-	 * we'll get caught below. */
-	if ((lockres->l_flags & USER_LOCK_BUSY) &&
-	    (level > lockres->l_level)) {
-		/* is someone sitting in dlm_lock? If so, wait on
-		 * them. */
-		spin_unlock(&lockres->l_lock);
-
-		user_wait_on_busy_lock(lockres);
-		goto again;
-	}
-
-	if ((lockres->l_flags & USER_LOCK_BLOCKED) &&
-	    (!user_may_continue_on_blocked_lock(lockres, level))) {
-		/* is the lock is currently blocked on behalf of
-		 * another node */
-		spin_unlock(&lockres->l_lock);
-
-		user_wait_on_blocked_lock(lockres);
-		goto again;
-	}
-
-	if (level > lockres->l_level) {
-		local_flags = lkm_flags | LKM_VALBLK;
-		if (lockres->l_level != LKM_IVMODE)
-			local_flags |= LKM_CONVERT;
-
-		lockres->l_requested = level;
-		lockres->l_flags |= USER_LOCK_BUSY;
-		spin_unlock(&lockres->l_lock);
-
-		BUG_ON(level == LKM_IVMODE);
-		BUG_ON(level == LKM_NLMODE);
-
-		/* call dlm_lock to upgrade lock now */
-		status = dlmlock(dlm,
-				 level,
-				 &lockres->l_lksb,
-				 local_flags,
-				 lockres->l_name,
-				 lockres->l_namelen,
-				 user_ast,
-				 lockres,
-				 user_bast);
-		if (status != DLM_NORMAL) {
-			if ((lkm_flags & LKM_NOQUEUE) &&
-			    (status == DLM_NOTQUEUED))
-				status = -EAGAIN;
-			else {
-				user_log_dlm_error("dlmlock", status, lockres);
-				status = -EINVAL;
-			}
-			user_recover_from_dlm_error(lockres);
-			goto bail;
-		}
-
-		user_wait_on_busy_lock(lockres);
-		goto again;
-	}
-
-	user_dlm_inc_holders(lockres, level);
-	spin_unlock(&lockres->l_lock);
-
-	status = 0;
-bail:
-	return status;
-}
-
-static inline void user_dlm_dec_holders(struct user_lock_res *lockres,
-					int level)
-{
-	switch(level) {
-	case LKM_EXMODE:
-		BUG_ON(!lockres->l_ex_holders);
-		lockres->l_ex_holders--;
-		break;
-	case LKM_PRMODE:
-		BUG_ON(!lockres->l_ro_holders);
-		lockres->l_ro_holders--;
-		break;
-	default:
-		BUG();
-	}
-}
-
-void user_dlm_cluster_unlock(struct user_lock_res *lockres,
-			     int level)
-{
-	if (level != LKM_EXMODE &&
-	    level != LKM_PRMODE) {
-		mlog(ML_ERROR, "lockres %.*s: invalid request!\n",
-		     lockres->l_namelen, lockres->l_name);
-		return;
-	}
-
-	spin_lock(&lockres->l_lock);
-	user_dlm_dec_holders(lockres, level);
-	__user_dlm_cond_queue_lockres(lockres);
-	spin_unlock(&lockres->l_lock);
-}
-
-void user_dlm_write_lvb(struct inode *inode,
-			const char *val,
-			unsigned int len)
-{
-	struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres;
-	char *lvb = lockres->l_lksb.lvb;
-
-	BUG_ON(len > DLM_LVB_LEN);
-
-	spin_lock(&lockres->l_lock);
-
-	BUG_ON(lockres->l_level < LKM_EXMODE);
-	memcpy(lvb, val, len);
-
-	spin_unlock(&lockres->l_lock);
-}
-
-void user_dlm_read_lvb(struct inode *inode,
-		       char *val,
-		       unsigned int len)
-{
-	struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres;
-	char *lvb = lockres->l_lksb.lvb;
-
-	BUG_ON(len > DLM_LVB_LEN);
-
-	spin_lock(&lockres->l_lock);
-
-	BUG_ON(lockres->l_level < LKM_PRMODE);
-	memcpy(val, lvb, len);
-
-	spin_unlock(&lockres->l_lock);
-}
-
-void user_dlm_lock_res_init(struct user_lock_res *lockres,
-			    struct dentry *dentry)
-{
-	memset(lockres, 0, sizeof(*lockres));
-
-	spin_lock_init(&lockres->l_lock);
-	init_waitqueue_head(&lockres->l_event);
-	lockres->l_level = LKM_IVMODE;
-	lockres->l_requested = LKM_IVMODE;
-	lockres->l_blocking = LKM_IVMODE;
-
-	/* should have been checked before getting here. */
-	BUG_ON(dentry->d_name.len >= USER_DLM_LOCK_ID_MAX_LEN);
-
-	memcpy(lockres->l_name,
-	       dentry->d_name.name,
-	       dentry->d_name.len);
-	lockres->l_namelen = dentry->d_name.len;
-}
-
-int user_dlm_destroy_lock(struct user_lock_res *lockres)
-{
-	int status = -EBUSY;
-	struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres);
-
-	mlog(0, "asked to destroy %.*s\n", lockres->l_namelen, lockres->l_name);
-
-	spin_lock(&lockres->l_lock);
-	if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
-		spin_unlock(&lockres->l_lock);
-		return 0;
-	}
-
-	lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
-
-	while (lockres->l_flags & USER_LOCK_BUSY) {
-		spin_unlock(&lockres->l_lock);
-
-		user_wait_on_busy_lock(lockres);
-
-		spin_lock(&lockres->l_lock);
-	}
-
-	if (lockres->l_ro_holders || lockres->l_ex_holders) {
-		spin_unlock(&lockres->l_lock);
-		goto bail;
-	}
-
-	status = 0;
-	if (!(lockres->l_flags & USER_LOCK_ATTACHED)) {
-		spin_unlock(&lockres->l_lock);
-		goto bail;
-	}
-
-	lockres->l_flags &= ~USER_LOCK_ATTACHED;
-	lockres->l_flags |= USER_LOCK_BUSY;
-	spin_unlock(&lockres->l_lock);
-
-	status = dlmunlock(dlm,
-			   &lockres->l_lksb,
-			   LKM_VALBLK,
-			   user_unlock_ast,
-			   lockres);
-	if (status != DLM_NORMAL) {
-		user_log_dlm_error("dlmunlock", status, lockres);
-		status = -EINVAL;
-		goto bail;
-	}
-
-	user_wait_on_busy_lock(lockres);
-
-	status = 0;
-bail:
-	return status;
-}
-
-struct dlm_ctxt *user_dlm_register_context(struct qstr *name,
-					   struct dlm_protocol_version *proto)
-{
-	struct dlm_ctxt *dlm;
-	u32 dlm_key;
-	char *domain;
-
-	domain = kmalloc(name->len + 1, GFP_NOFS);
-	if (!domain) {
-		mlog_errno(-ENOMEM);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	dlm_key = crc32_le(0, name->name, name->len);
-
-	snprintf(domain, name->len + 1, "%.*s", name->len, name->name);
-
-	dlm = dlm_register_domain(domain, dlm_key, proto);
-	if (IS_ERR(dlm))
-		mlog_errno(PTR_ERR(dlm));
-
-	kfree(domain);
-	return dlm;
-}
-
-void user_dlm_unregister_context(struct dlm_ctxt *dlm)
-{
-	dlm_unregister_domain(dlm);
-}
diff --git a/fs/ocfs2/dlm/userdlm.h b/fs/ocfs2/dlm/userdlm.h
deleted file mode 100644
index 0c3cc03..0000000
--- a/fs/ocfs2/dlm/userdlm.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * userdlm.h
- *
- * Userspace dlm defines
- *
- * Copyright (C) 2002, 2004 Oracle.  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 021110-1307, USA.
- */
-
-
-#ifndef USERDLM_H
-#define USERDLM_H
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-
-/* user_lock_res->l_flags flags. */
-#define USER_LOCK_ATTACHED      (0x00000001) /* we have initialized
-					       * the lvb */
-#define USER_LOCK_BUSY          (0x00000002) /* we are currently in
-					       * dlm_lock */
-#define USER_LOCK_BLOCKED       (0x00000004) /* blocked waiting to
-					      * downconvert*/
-#define USER_LOCK_IN_TEARDOWN   (0x00000008) /* we're currently
-					      * destroying this
-					      * lock. */
-#define USER_LOCK_QUEUED        (0x00000010) /* lock is on the
-					      * workqueue */
-#define USER_LOCK_IN_CANCEL     (0x00000020)
-
-struct user_lock_res {
-	spinlock_t               l_lock;
-
-	int                      l_flags;
-
-#define USER_DLM_LOCK_ID_MAX_LEN  32
-	char                     l_name[USER_DLM_LOCK_ID_MAX_LEN];
-	int                      l_namelen;
-	int                      l_level;
-	unsigned int             l_ro_holders;
-	unsigned int             l_ex_holders;
-	struct dlm_lockstatus    l_lksb;
-
-	int                      l_requested;
-	int                      l_blocking;
-
-	wait_queue_head_t        l_event;
-
-	struct work_struct       l_work;
-};
-
-extern struct workqueue_struct *user_dlm_worker;
-
-void user_dlm_lock_res_init(struct user_lock_res *lockres,
-			    struct dentry *dentry);
-int user_dlm_destroy_lock(struct user_lock_res *lockres);
-int user_dlm_cluster_lock(struct user_lock_res *lockres,
-			  int level,
-			  int lkm_flags);
-void user_dlm_cluster_unlock(struct user_lock_res *lockres,
-			     int level);
-void user_dlm_write_lvb(struct inode *inode,
-			const char *val,
-			unsigned int len);
-void user_dlm_read_lvb(struct inode *inode,
-		       char *val,
-		       unsigned int len);
-struct dlm_ctxt *user_dlm_register_context(struct qstr *name,
-					   struct dlm_protocol_version *proto);
-void user_dlm_unregister_context(struct dlm_ctxt *dlm);
-
-struct dlmfs_inode_private {
-	struct dlm_ctxt             *ip_dlm;
-
-	struct user_lock_res ip_lockres; /* unused for directories. */
-	struct inode         *ip_parent;
-
-	struct inode         ip_vfs_inode;
-};
-
-static inline struct dlmfs_inode_private *
-DLMFS_I(struct inode *inode)
-{
-        return container_of(inode,
-			    struct dlmfs_inode_private,
-			    ip_vfs_inode);
-}
-
-struct dlmfs_filp_private {
-	int                  fp_lock_level;
-};
-
-#define DLMFS_MAGIC	0x76a9f425
-
-#endif /* USERDLM_H */
diff --git a/fs/ocfs2/dlmfs/Makefile b/fs/ocfs2/dlmfs/Makefile
new file mode 100644
index 0000000..df69b48
--- /dev/null
+++ b/fs/ocfs2/dlmfs/Makefile
@@ -0,0 +1,5 @@
+EXTRA_CFLAGS += -Ifs/ocfs2
+
+obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o
+
+ocfs2_dlmfs-objs := userdlm.o dlmfs.o dlmfsver.o
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c
new file mode 100644
index 0000000..1b0de15
--- /dev/null
+++ b/fs/ocfs2/dlmfs/dlmfs.c
@@ -0,0 +1,715 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmfs.c
+ *
+ * Code which implements the kernel side of a minimal userspace
+ * interface to our DLM. This file handles the virtual file system
+ * used for communication with userspace. Credit should go to ramfs,
+ * which was a template for the fs side of this module.
+ *
+ * Copyright (C) 2003, 2004 Oracle.  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 021110-1307, USA.
+ */
+
+/* Simple VFS hooks based on: */
+/*
+ * Resizable simple ram filesystem for Linux.
+ *
+ * Copyright (C) 2000 Linus Torvalds.
+ *               2000 Transmeta Corp.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/backing-dev.h>
+#include <linux/poll.h>
+
+#include <asm/uaccess.h>
+
+#include "stackglue.h"
+#include "userdlm.h"
+#include "dlmfsver.h"
+
+#define MLOG_MASK_PREFIX ML_DLMFS
+#include "cluster/masklog.h"
+
+
+static const struct super_operations dlmfs_ops;
+static const struct file_operations dlmfs_file_operations;
+static const struct inode_operations dlmfs_dir_inode_operations;
+static const struct inode_operations dlmfs_root_inode_operations;
+static const struct inode_operations dlmfs_file_inode_operations;
+static struct kmem_cache *dlmfs_inode_cache;
+
+struct workqueue_struct *user_dlm_worker;
+
+
+
+/*
+ * These are the ABI capabilities of dlmfs.
+ *
+ * Over time, dlmfs has added some features that were not part of the
+ * initial ABI.  Unfortunately, some of these features are not detectable
+ * via standard usage.  For example, Linux's default poll always returns
+ * POLLIN, so there is no way for a caller of poll(2) to know when dlmfs
+ * added poll support.  Instead, we provide this list of new capabilities.
+ *
+ * Capabilities is a read-only attribute.  We do it as a module parameter
+ * so we can discover it whether dlmfs is built in, loaded, or even not
+ * loaded.
+ *
+ * The ABI features are local to this machine's dlmfs mount.  This is
+ * distinct from the locking protocol, which is concerned with inter-node
+ * interaction.
+ *
+ * Capabilities:
+ * - bast	: POLLIN against the file descriptor of a held lock
+ *		  signifies a bast fired on the lock.
+ */
+#define DLMFS_CAPABILITIES "bast stackglue"
+extern int param_set_dlmfs_capabilities(const char *val,
+					struct kernel_param *kp)
+{
+	printk(KERN_ERR "%s: readonly parameter\n", kp->name);
+	return -EINVAL;
+}
+static int param_get_dlmfs_capabilities(char *buffer,
+					struct kernel_param *kp)
+{
+	return strlcpy(buffer, DLMFS_CAPABILITIES,
+		       strlen(DLMFS_CAPABILITIES) + 1);
+}
+module_param_call(capabilities, param_set_dlmfs_capabilities,
+		  param_get_dlmfs_capabilities, NULL, 0444);
+MODULE_PARM_DESC(capabilities, DLMFS_CAPABILITIES);
+
+
+/*
+ * decodes a set of open flags into a valid lock level and a set of flags.
+ * returns < 0 if we have invalid flags
+ * flags which mean something to us:
+ * O_RDONLY -> PRMODE level
+ * O_WRONLY -> EXMODE level
+ *
+ * O_NONBLOCK -> LKM_NOQUEUE
+ */
+static int dlmfs_decode_open_flags(int open_flags,
+				   int *level,
+				   int *flags)
+{
+	if (open_flags & (O_WRONLY|O_RDWR))
+		*level = LKM_EXMODE;
+	else
+		*level = LKM_PRMODE;
+
+	*flags = 0;
+	if (open_flags & O_NONBLOCK)
+		*flags |= LKM_NOQUEUE;
+
+	return 0;
+}
+
+static int dlmfs_file_open(struct inode *inode,
+			   struct file *file)
+{
+	int status, level, flags;
+	struct dlmfs_filp_private *fp = NULL;
+	struct dlmfs_inode_private *ip;
+
+	if (S_ISDIR(inode->i_mode))
+		BUG();
+
+	mlog(0, "open called on inode %lu, flags 0x%x\n", inode->i_ino,
+		file->f_flags);
+
+	status = dlmfs_decode_open_flags(file->f_flags, &level, &flags);
+	if (status < 0)
+		goto bail;
+
+	/* We don't want to honor O_APPEND at read/write time as it
+	 * doesn't make sense for LVB writes. */
+	file->f_flags &= ~O_APPEND;
+
+	fp = kmalloc(sizeof(*fp), GFP_NOFS);
+	if (!fp) {
+		status = -ENOMEM;
+		goto bail;
+	}
+	fp->fp_lock_level = level;
+
+	ip = DLMFS_I(inode);
+
+	status = user_dlm_cluster_lock(&ip->ip_lockres, level, flags);
+	if (status < 0) {
+		/* this is a strange error to return here but I want
+		 * to be able userspace to be able to distinguish a
+		 * valid lock request from one that simply couldn't be
+		 * granted. */
+		if (flags & LKM_NOQUEUE && status == -EAGAIN)
+			status = -ETXTBSY;
+		kfree(fp);
+		goto bail;
+	}
+
+	file->private_data = fp;
+bail:
+	return status;
+}
+
+static int dlmfs_file_release(struct inode *inode,
+			      struct file *file)
+{
+	int level, status;
+	struct dlmfs_inode_private *ip = DLMFS_I(inode);
+	struct dlmfs_filp_private *fp =
+		(struct dlmfs_filp_private *) file->private_data;
+
+	if (S_ISDIR(inode->i_mode))
+		BUG();
+
+	mlog(0, "close called on inode %lu\n", inode->i_ino);
+
+	status = 0;
+	if (fp) {
+		level = fp->fp_lock_level;
+		if (level != LKM_IVMODE)
+			user_dlm_cluster_unlock(&ip->ip_lockres, level);
+
+		kfree(fp);
+		file->private_data = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * We do ->setattr() just to override size changes.  Our size is the size
+ * of the LVB and nothing else.
+ */
+static int dlmfs_file_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	int error;
+	struct inode *inode = dentry->d_inode;
+
+	attr->ia_valid &= ~ATTR_SIZE;
+	error = inode_change_ok(inode, attr);
+	if (!error)
+		error = inode_setattr(inode, attr);
+
+	return error;
+}
+
+static unsigned int dlmfs_file_poll(struct file *file, poll_table *wait)
+{
+	int event = 0;
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct dlmfs_inode_private *ip = DLMFS_I(inode);
+
+	poll_wait(file, &ip->ip_lockres.l_event, wait);
+
+	spin_lock(&ip->ip_lockres.l_lock);
+	if (ip->ip_lockres.l_flags & USER_LOCK_BLOCKED)
+		event = POLLIN | POLLRDNORM;
+	spin_unlock(&ip->ip_lockres.l_lock);
+
+	return event;
+}
+
+static ssize_t dlmfs_file_read(struct file *filp,
+			       char __user *buf,
+			       size_t count,
+			       loff_t *ppos)
+{
+	int bytes_left;
+	ssize_t readlen, got;
+	char *lvb_buf;
+	struct inode *inode = filp->f_path.dentry->d_inode;
+
+	mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
+		inode->i_ino, count, *ppos);
+
+	if (*ppos >= i_size_read(inode))
+		return 0;
+
+	if (!count)
+		return 0;
+
+	if (!access_ok(VERIFY_WRITE, buf, count))
+		return -EFAULT;
+
+	/* don't read past the lvb */
+	if ((count + *ppos) > i_size_read(inode))
+		readlen = i_size_read(inode) - *ppos;
+	else
+		readlen = count - *ppos;
+
+	lvb_buf = kmalloc(readlen, GFP_NOFS);
+	if (!lvb_buf)
+		return -ENOMEM;
+
+	got = user_dlm_read_lvb(inode, lvb_buf, readlen);
+	if (got) {
+		BUG_ON(got != readlen);
+		bytes_left = __copy_to_user(buf, lvb_buf, readlen);
+		readlen -= bytes_left;
+	} else
+		readlen = 0;
+
+	kfree(lvb_buf);
+
+	*ppos = *ppos + readlen;
+
+	mlog(0, "read %zd bytes\n", readlen);
+	return readlen;
+}
+
+static ssize_t dlmfs_file_write(struct file *filp,
+				const char __user *buf,
+				size_t count,
+				loff_t *ppos)
+{
+	int bytes_left;
+	ssize_t writelen;
+	char *lvb_buf;
+	struct inode *inode = filp->f_path.dentry->d_inode;
+
+	mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
+		inode->i_ino, count, *ppos);
+
+	if (*ppos >= i_size_read(inode))
+		return -ENOSPC;
+
+	if (!count)
+		return 0;
+
+	if (!access_ok(VERIFY_READ, buf, count))
+		return -EFAULT;
+
+	/* don't write past the lvb */
+	if ((count + *ppos) > i_size_read(inode))
+		writelen = i_size_read(inode) - *ppos;
+	else
+		writelen = count - *ppos;
+
+	lvb_buf = kmalloc(writelen, GFP_NOFS);
+	if (!lvb_buf)
+		return -ENOMEM;
+
+	bytes_left = copy_from_user(lvb_buf, buf, writelen);
+	writelen -= bytes_left;
+	if (writelen)
+		user_dlm_write_lvb(inode, lvb_buf, writelen);
+
+	kfree(lvb_buf);
+
+	*ppos = *ppos + writelen;
+	mlog(0, "wrote %zd bytes\n", writelen);
+	return writelen;
+}
+
+static void dlmfs_init_once(void *foo)
+{
+	struct dlmfs_inode_private *ip =
+		(struct dlmfs_inode_private *) foo;
+
+	ip->ip_conn = NULL;
+	ip->ip_parent = NULL;
+
+	inode_init_once(&ip->ip_vfs_inode);
+}
+
+static struct inode *dlmfs_alloc_inode(struct super_block *sb)
+{
+	struct dlmfs_inode_private *ip;
+
+	ip = kmem_cache_alloc(dlmfs_inode_cache, GFP_NOFS);
+	if (!ip)
+		return NULL;
+
+	return &ip->ip_vfs_inode;
+}
+
+static void dlmfs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(dlmfs_inode_cache, DLMFS_I(inode));
+}
+
+static void dlmfs_clear_inode(struct inode *inode)
+{
+	int status;
+	struct dlmfs_inode_private *ip;
+
+	if (!inode)
+		return;
+
+	mlog(0, "inode %lu\n", inode->i_ino);
+
+	ip = DLMFS_I(inode);
+
+	if (S_ISREG(inode->i_mode)) {
+		status = user_dlm_destroy_lock(&ip->ip_lockres);
+		if (status < 0)
+			mlog_errno(status);
+		iput(ip->ip_parent);
+		goto clear_fields;
+	}
+
+	mlog(0, "we're a directory, ip->ip_conn = 0x%p\n", ip->ip_conn);
+	/* we must be a directory. If required, lets unregister the
+	 * dlm context now. */
+	if (ip->ip_conn)
+		user_dlm_unregister(ip->ip_conn);
+clear_fields:
+	ip->ip_parent = NULL;
+	ip->ip_conn = NULL;
+}
+
+static struct backing_dev_info dlmfs_backing_dev_info = {
+	.name		= "ocfs2-dlmfs",
+	.ra_pages	= 0,	/* No readahead */
+	.capabilities	= BDI_CAP_NO_ACCT_AND_WRITEBACK,
+};
+
+static struct inode *dlmfs_get_root_inode(struct super_block *sb)
+{
+	struct inode *inode = new_inode(sb);
+	int mode = S_IFDIR | 0755;
+	struct dlmfs_inode_private *ip;
+
+	if (inode) {
+		ip = DLMFS_I(inode);
+
+		inode->i_mode = mode;
+		inode->i_uid = current_fsuid();
+		inode->i_gid = current_fsgid();
+		inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		inc_nlink(inode);
+
+		inode->i_fop = &simple_dir_operations;
+		inode->i_op = &dlmfs_root_inode_operations;
+	}
+
+	return inode;
+}
+
+static struct inode *dlmfs_get_inode(struct inode *parent,
+				     struct dentry *dentry,
+				     int mode)
+{
+	struct super_block *sb = parent->i_sb;
+	struct inode * inode = new_inode(sb);
+	struct dlmfs_inode_private *ip;
+
+	if (!inode)
+		return NULL;
+
+	inode->i_mode = mode;
+	inode->i_uid = current_fsuid();
+	inode->i_gid = current_fsgid();
+	inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+
+	ip = DLMFS_I(inode);
+	ip->ip_conn = DLMFS_I(parent)->ip_conn;
+
+	switch (mode & S_IFMT) {
+	default:
+		/* for now we don't support anything other than
+		 * directories and regular files. */
+		BUG();
+		break;
+	case S_IFREG:
+		inode->i_op = &dlmfs_file_inode_operations;
+		inode->i_fop = &dlmfs_file_operations;
+
+		i_size_write(inode,  DLM_LVB_LEN);
+
+		user_dlm_lock_res_init(&ip->ip_lockres, dentry);
+
+		/* released at clear_inode time, this insures that we
+		 * get to drop the dlm reference on each lock *before*
+		 * we call the unregister code for releasing parent
+		 * directories. */
+		ip->ip_parent = igrab(parent);
+		BUG_ON(!ip->ip_parent);
+		break;
+	case S_IFDIR:
+		inode->i_op = &dlmfs_dir_inode_operations;
+		inode->i_fop = &simple_dir_operations;
+
+		/* directory inodes start off with i_nlink ==
+		 * 2 (for "." entry) */
+		inc_nlink(inode);
+		break;
+	}
+
+	if (parent->i_mode & S_ISGID) {
+		inode->i_gid = parent->i_gid;
+		if (S_ISDIR(mode))
+			inode->i_mode |= S_ISGID;
+	}
+
+	return inode;
+}
+
+/*
+ * File creation. Allocate an inode, and we're done..
+ */
+/* SMP-safe */
+static int dlmfs_mkdir(struct inode * dir,
+		       struct dentry * dentry,
+		       int mode)
+{
+	int status;
+	struct inode *inode = NULL;
+	struct qstr *domain = &dentry->d_name;
+	struct dlmfs_inode_private *ip;
+	struct ocfs2_cluster_connection *conn;
+
+	mlog(0, "mkdir %.*s\n", domain->len, domain->name);
+
+	/* verify that we have a proper domain */
+	if (domain->len >= GROUP_NAME_MAX) {
+		status = -EINVAL;
+		mlog(ML_ERROR, "invalid domain name for directory.\n");
+		goto bail;
+	}
+
+	inode = dlmfs_get_inode(dir, dentry, mode | S_IFDIR);
+	if (!inode) {
+		status = -ENOMEM;
+		mlog_errno(status);
+		goto bail;
+	}
+
+	ip = DLMFS_I(inode);
+
+	conn = user_dlm_register(domain);
+	if (IS_ERR(conn)) {
+		status = PTR_ERR(conn);
+		mlog(ML_ERROR, "Error %d could not register domain \"%.*s\"\n",
+		     status, domain->len, domain->name);
+		goto bail;
+	}
+	ip->ip_conn = conn;
+
+	inc_nlink(dir);
+	d_instantiate(dentry, inode);
+	dget(dentry);	/* Extra count - pin the dentry in core */
+
+	status = 0;
+bail:
+	if (status < 0)
+		iput(inode);
+	return status;
+}
+
+static int dlmfs_create(struct inode *dir,
+			struct dentry *dentry,
+			int mode,
+			struct nameidata *nd)
+{
+	int status = 0;
+	struct inode *inode;
+	struct qstr *name = &dentry->d_name;
+
+	mlog(0, "create %.*s\n", name->len, name->name);
+
+	/* verify name is valid and doesn't contain any dlm reserved
+	 * characters */
+	if (name->len >= USER_DLM_LOCK_ID_MAX_LEN ||
+	    name->name[0] == '$') {
+		status = -EINVAL;
+		mlog(ML_ERROR, "invalid lock name, %.*s\n", name->len,
+		     name->name);
+		goto bail;
+	}
+
+	inode = dlmfs_get_inode(dir, dentry, mode | S_IFREG);
+	if (!inode) {
+		status = -ENOMEM;
+		mlog_errno(status);
+		goto bail;
+	}
+
+	d_instantiate(dentry, inode);
+	dget(dentry);	/* Extra count - pin the dentry in core */
+bail:
+	return status;
+}
+
+static int dlmfs_unlink(struct inode *dir,
+			struct dentry *dentry)
+{
+	int status;
+	struct inode *inode = dentry->d_inode;
+
+	mlog(0, "unlink inode %lu\n", inode->i_ino);
+
+	/* if there are no current holders, or none that are waiting
+	 * to acquire a lock, this basically destroys our lockres. */
+	status = user_dlm_destroy_lock(&DLMFS_I(inode)->ip_lockres);
+	if (status < 0) {
+		mlog(ML_ERROR, "unlink %.*s, error %d from destroy\n",
+		     dentry->d_name.len, dentry->d_name.name, status);
+		goto bail;
+	}
+	status = simple_unlink(dir, dentry);
+bail:
+	return status;
+}
+
+static int dlmfs_fill_super(struct super_block * sb,
+			    void * data,
+			    int silent)
+{
+	struct inode * inode;
+	struct dentry * root;
+
+	sb->s_maxbytes = MAX_LFS_FILESIZE;
+	sb->s_blocksize = PAGE_CACHE_SIZE;
+	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+	sb->s_magic = DLMFS_MAGIC;
+	sb->s_op = &dlmfs_ops;
+	inode = dlmfs_get_root_inode(sb);
+	if (!inode)
+		return -ENOMEM;
+
+	root = d_alloc_root(inode);
+	if (!root) {
+		iput(inode);
+		return -ENOMEM;
+	}
+	sb->s_root = root;
+	return 0;
+}
+
+static const struct file_operations dlmfs_file_operations = {
+	.open		= dlmfs_file_open,
+	.release	= dlmfs_file_release,
+	.poll		= dlmfs_file_poll,
+	.read		= dlmfs_file_read,
+	.write		= dlmfs_file_write,
+};
+
+static const struct inode_operations dlmfs_dir_inode_operations = {
+	.create		= dlmfs_create,
+	.lookup		= simple_lookup,
+	.unlink		= dlmfs_unlink,
+};
+
+/* this way we can restrict mkdir to only the toplevel of the fs. */
+static const struct inode_operations dlmfs_root_inode_operations = {
+	.lookup		= simple_lookup,
+	.mkdir		= dlmfs_mkdir,
+	.rmdir		= simple_rmdir,
+};
+
+static const struct super_operations dlmfs_ops = {
+	.statfs		= simple_statfs,
+	.alloc_inode	= dlmfs_alloc_inode,
+	.destroy_inode	= dlmfs_destroy_inode,
+	.clear_inode	= dlmfs_clear_inode,
+	.drop_inode	= generic_delete_inode,
+};
+
+static const struct inode_operations dlmfs_file_inode_operations = {
+	.getattr	= simple_getattr,
+	.setattr	= dlmfs_file_setattr,
+};
+
+static int dlmfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
+{
+	return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super, mnt);
+}
+
+static struct file_system_type dlmfs_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "ocfs2_dlmfs",
+	.get_sb		= dlmfs_get_sb,
+	.kill_sb	= kill_litter_super,
+};
+
+static int __init init_dlmfs_fs(void)
+{
+	int status;
+	int cleanup_inode = 0, cleanup_worker = 0;
+
+	dlmfs_print_version();
+
+	status = bdi_init(&dlmfs_backing_dev_info);
+	if (status)
+		return status;
+
+	dlmfs_inode_cache = kmem_cache_create("dlmfs_inode_cache",
+				sizeof(struct dlmfs_inode_private),
+				0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
+					SLAB_MEM_SPREAD),
+				dlmfs_init_once);
+	if (!dlmfs_inode_cache) {
+		status = -ENOMEM;
+		goto bail;
+	}
+	cleanup_inode = 1;
+
+	user_dlm_worker = create_singlethread_workqueue("user_dlm");
+	if (!user_dlm_worker) {
+		status = -ENOMEM;
+		goto bail;
+	}
+	cleanup_worker = 1;
+
+	user_dlm_set_locking_protocol();
+	status = register_filesystem(&dlmfs_fs_type);
+bail:
+	if (status) {
+		if (cleanup_inode)
+			kmem_cache_destroy(dlmfs_inode_cache);
+		if (cleanup_worker)
+			destroy_workqueue(user_dlm_worker);
+		bdi_destroy(&dlmfs_backing_dev_info);
+	} else
+		printk("OCFS2 User DLM kernel interface loaded\n");
+	return status;
+}
+
+static void __exit exit_dlmfs_fs(void)
+{
+	unregister_filesystem(&dlmfs_fs_type);
+
+	flush_workqueue(user_dlm_worker);
+	destroy_workqueue(user_dlm_worker);
+
+	kmem_cache_destroy(dlmfs_inode_cache);
+
+	bdi_destroy(&dlmfs_backing_dev_info);
+}
+
+MODULE_AUTHOR("Oracle");
+MODULE_LICENSE("GPL");
+
+module_init(init_dlmfs_fs)
+module_exit(exit_dlmfs_fs)
diff --git a/fs/ocfs2/dlm/dlmfsver.c b/fs/ocfs2/dlmfs/dlmfsver.c
similarity index 100%
rename from fs/ocfs2/dlm/dlmfsver.c
rename to fs/ocfs2/dlmfs/dlmfsver.c
diff --git a/fs/ocfs2/dlm/dlmfsver.h b/fs/ocfs2/dlmfs/dlmfsver.h
similarity index 100%
rename from fs/ocfs2/dlm/dlmfsver.h
rename to fs/ocfs2/dlmfs/dlmfsver.h
diff --git a/fs/ocfs2/dlmfs/userdlm.c b/fs/ocfs2/dlmfs/userdlm.c
new file mode 100644
index 0000000..0499e3f
--- /dev/null
+++ b/fs/ocfs2/dlmfs/userdlm.c
@@ -0,0 +1,688 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * userdlm.c
+ *
+ * Code which implements the kernel side of a minimal userspace
+ * interface to our DLM.
+ *
+ * Many of the functions here are pared down versions of dlmglue.c
+ * functions.
+ *
+ * Copyright (C) 2003, 2004 Oracle.  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 021110-1307, USA.
+ */
+
+#include <linux/signal.h>
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/crc32.h>
+
+#include "ocfs2_lockingver.h"
+#include "stackglue.h"
+#include "userdlm.h"
+
+#define MLOG_MASK_PREFIX ML_DLMFS
+#include "cluster/masklog.h"
+
+
+static inline struct user_lock_res *user_lksb_to_lock_res(struct ocfs2_dlm_lksb *lksb)
+{
+	return container_of(lksb, struct user_lock_res, l_lksb);
+}
+
+static inline int user_check_wait_flag(struct user_lock_res *lockres,
+				       int flag)
+{
+	int ret;
+
+	spin_lock(&lockres->l_lock);
+	ret = lockres->l_flags & flag;
+	spin_unlock(&lockres->l_lock);
+
+	return ret;
+}
+
+static inline void user_wait_on_busy_lock(struct user_lock_res *lockres)
+
+{
+	wait_event(lockres->l_event,
+		   !user_check_wait_flag(lockres, USER_LOCK_BUSY));
+}
+
+static inline void user_wait_on_blocked_lock(struct user_lock_res *lockres)
+
+{
+	wait_event(lockres->l_event,
+		   !user_check_wait_flag(lockres, USER_LOCK_BLOCKED));
+}
+
+/* I heart container_of... */
+static inline struct ocfs2_cluster_connection *
+cluster_connection_from_user_lockres(struct user_lock_res *lockres)
+{
+	struct dlmfs_inode_private *ip;
+
+	ip = container_of(lockres,
+			  struct dlmfs_inode_private,
+			  ip_lockres);
+	return ip->ip_conn;
+}
+
+static struct inode *
+user_dlm_inode_from_user_lockres(struct user_lock_res *lockres)
+{
+	struct dlmfs_inode_private *ip;
+
+	ip = container_of(lockres,
+			  struct dlmfs_inode_private,
+			  ip_lockres);
+	return &ip->ip_vfs_inode;
+}
+
+static inline void user_recover_from_dlm_error(struct user_lock_res *lockres)
+{
+	spin_lock(&lockres->l_lock);
+	lockres->l_flags &= ~USER_LOCK_BUSY;
+	spin_unlock(&lockres->l_lock);
+}
+
+#define user_log_dlm_error(_func, _stat, _lockres) do {			\
+	mlog(ML_ERROR, "Dlm error %d while calling %s on "		\
+		"resource %.*s\n", _stat, _func,			\
+		_lockres->l_namelen, _lockres->l_name); 		\
+} while (0)
+
+/* WARNING: This function lives in a world where the only three lock
+ * levels are EX, PR, and NL. It *will* have to be adjusted when more
+ * lock types are added. */
+static inline int user_highest_compat_lock_level(int level)
+{
+	int new_level = DLM_LOCK_EX;
+
+	if (level == DLM_LOCK_EX)
+		new_level = DLM_LOCK_NL;
+	else if (level == DLM_LOCK_PR)
+		new_level = DLM_LOCK_PR;
+	return new_level;
+}
+
+static void user_ast(struct ocfs2_dlm_lksb *lksb)
+{
+	struct user_lock_res *lockres = user_lksb_to_lock_res(lksb);
+	int status;
+
+	mlog(ML_BASTS, "AST fired for lockres %.*s, level %d => %d\n",
+	     lockres->l_namelen, lockres->l_name, lockres->l_level,
+	     lockres->l_requested);
+
+	spin_lock(&lockres->l_lock);
+
+	status = ocfs2_dlm_lock_status(&lockres->l_lksb);
+	if (status) {
+		mlog(ML_ERROR, "lksb status value of %u on lockres %.*s\n",
+		     status, lockres->l_namelen, lockres->l_name);
+		spin_unlock(&lockres->l_lock);
+		return;
+	}
+
+	mlog_bug_on_msg(lockres->l_requested == DLM_LOCK_IV,
+			"Lockres %.*s, requested ivmode. flags 0x%x\n",
+			lockres->l_namelen, lockres->l_name, lockres->l_flags);
+
+	/* we're downconverting. */
+	if (lockres->l_requested < lockres->l_level) {
+		if (lockres->l_requested <=
+		    user_highest_compat_lock_level(lockres->l_blocking)) {
+			lockres->l_blocking = DLM_LOCK_NL;
+			lockres->l_flags &= ~USER_LOCK_BLOCKED;
+		}
+	}
+
+	lockres->l_level = lockres->l_requested;
+	lockres->l_requested = DLM_LOCK_IV;
+	lockres->l_flags |= USER_LOCK_ATTACHED;
+	lockres->l_flags &= ~USER_LOCK_BUSY;
+
+	spin_unlock(&lockres->l_lock);
+
+	wake_up(&lockres->l_event);
+}
+
+static inline void user_dlm_grab_inode_ref(struct user_lock_res *lockres)
+{
+	struct inode *inode;
+	inode = user_dlm_inode_from_user_lockres(lockres);
+	if (!igrab(inode))
+		BUG();
+}
+
+static void user_dlm_unblock_lock(struct work_struct *work);
+
+static void __user_dlm_queue_lockres(struct user_lock_res *lockres)
+{
+	if (!(lockres->l_flags & USER_LOCK_QUEUED)) {
+		user_dlm_grab_inode_ref(lockres);
+
+		INIT_WORK(&lockres->l_work, user_dlm_unblock_lock);
+
+		queue_work(user_dlm_worker, &lockres->l_work);
+		lockres->l_flags |= USER_LOCK_QUEUED;
+	}
+}
+
+static void __user_dlm_cond_queue_lockres(struct user_lock_res *lockres)
+{
+	int queue = 0;
+
+	if (!(lockres->l_flags & USER_LOCK_BLOCKED))
+		return;
+
+	switch (lockres->l_blocking) {
+	case DLM_LOCK_EX:
+		if (!lockres->l_ex_holders && !lockres->l_ro_holders)
+			queue = 1;
+		break;
+	case DLM_LOCK_PR:
+		if (!lockres->l_ex_holders)
+			queue = 1;
+		break;
+	default:
+		BUG();
+	}
+
+	if (queue)
+		__user_dlm_queue_lockres(lockres);
+}
+
+static void user_bast(struct ocfs2_dlm_lksb *lksb, int level)
+{
+	struct user_lock_res *lockres = user_lksb_to_lock_res(lksb);
+
+	mlog(ML_BASTS, "BAST fired for lockres %.*s, blocking %d, level %d\n",
+	     lockres->l_namelen, lockres->l_name, level, lockres->l_level);
+
+	spin_lock(&lockres->l_lock);
+	lockres->l_flags |= USER_LOCK_BLOCKED;
+	if (level > lockres->l_blocking)
+		lockres->l_blocking = level;
+
+	__user_dlm_queue_lockres(lockres);
+	spin_unlock(&lockres->l_lock);
+
+	wake_up(&lockres->l_event);
+}
+
+static void user_unlock_ast(struct ocfs2_dlm_lksb *lksb, int status)
+{
+	struct user_lock_res *lockres = user_lksb_to_lock_res(lksb);
+
+	mlog(ML_BASTS, "UNLOCK AST fired for lockres %.*s, flags 0x%x\n",
+	     lockres->l_namelen, lockres->l_name, lockres->l_flags);
+
+	if (status)
+		mlog(ML_ERROR, "dlm returns status %d\n", status);
+
+	spin_lock(&lockres->l_lock);
+	/* The teardown flag gets set early during the unlock process,
+	 * so test the cancel flag to make sure that this ast isn't
+	 * for a concurrent cancel. */
+	if (lockres->l_flags & USER_LOCK_IN_TEARDOWN
+	    && !(lockres->l_flags & USER_LOCK_IN_CANCEL)) {
+		lockres->l_level = DLM_LOCK_IV;
+	} else if (status == DLM_CANCELGRANT) {
+		/* We tried to cancel a convert request, but it was
+		 * already granted. Don't clear the busy flag - the
+		 * ast should've done this already. */
+		BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL));
+		lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
+		goto out_noclear;
+	} else {
+		BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL));
+		/* Cancel succeeded, we want to re-queue */
+		lockres->l_requested = DLM_LOCK_IV; /* cancel an
+						    * upconvert
+						    * request. */
+		lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
+		/* we want the unblock thread to look at it again
+		 * now. */
+		if (lockres->l_flags & USER_LOCK_BLOCKED)
+			__user_dlm_queue_lockres(lockres);
+	}
+
+	lockres->l_flags &= ~USER_LOCK_BUSY;
+out_noclear:
+	spin_unlock(&lockres->l_lock);
+
+	wake_up(&lockres->l_event);
+}
+
+/*
+ * This is the userdlmfs locking protocol version.
+ *
+ * See fs/ocfs2/dlmglue.c for more details on locking versions.
+ */
+static struct ocfs2_locking_protocol user_dlm_lproto = {
+	.lp_max_version = {
+		.pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR,
+		.pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR,
+	},
+	.lp_lock_ast		= user_ast,
+	.lp_blocking_ast	= user_bast,
+	.lp_unlock_ast		= user_unlock_ast,
+};
+
+static inline void user_dlm_drop_inode_ref(struct user_lock_res *lockres)
+{
+	struct inode *inode;
+	inode = user_dlm_inode_from_user_lockres(lockres);
+	iput(inode);
+}
+
+static void user_dlm_unblock_lock(struct work_struct *work)
+{
+	int new_level, status;
+	struct user_lock_res *lockres =
+		container_of(work, struct user_lock_res, l_work);
+	struct ocfs2_cluster_connection *conn =
+		cluster_connection_from_user_lockres(lockres);
+
+	mlog(0, "lockres %.*s\n", lockres->l_namelen, lockres->l_name);
+
+	spin_lock(&lockres->l_lock);
+
+	mlog_bug_on_msg(!(lockres->l_flags & USER_LOCK_QUEUED),
+			"Lockres %.*s, flags 0x%x\n",
+			lockres->l_namelen, lockres->l_name, lockres->l_flags);
+
+	/* notice that we don't clear USER_LOCK_BLOCKED here. If it's
+	 * set, we want user_ast clear it. */
+	lockres->l_flags &= ~USER_LOCK_QUEUED;
+
+	/* It's valid to get here and no longer be blocked - if we get
+	 * several basts in a row, we might be queued by the first
+	 * one, the unblock thread might run and clear the queued
+	 * flag, and finally we might get another bast which re-queues
+	 * us before our ast for the downconvert is called. */
+	if (!(lockres->l_flags & USER_LOCK_BLOCKED)) {
+		mlog(ML_BASTS, "lockres %.*s USER_LOCK_BLOCKED\n",
+		     lockres->l_namelen, lockres->l_name);
+		spin_unlock(&lockres->l_lock);
+		goto drop_ref;
+	}
+
+	if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
+		mlog(ML_BASTS, "lockres %.*s USER_LOCK_IN_TEARDOWN\n",
+		     lockres->l_namelen, lockres->l_name);
+		spin_unlock(&lockres->l_lock);
+		goto drop_ref;
+	}
+
+	if (lockres->l_flags & USER_LOCK_BUSY) {
+		if (lockres->l_flags & USER_LOCK_IN_CANCEL) {
+			mlog(ML_BASTS, "lockres %.*s USER_LOCK_IN_CANCEL\n",
+			     lockres->l_namelen, lockres->l_name);
+			spin_unlock(&lockres->l_lock);
+			goto drop_ref;
+		}
+
+		lockres->l_flags |= USER_LOCK_IN_CANCEL;
+		spin_unlock(&lockres->l_lock);
+
+		status = ocfs2_dlm_unlock(conn, &lockres->l_lksb,
+					  DLM_LKF_CANCEL);
+		if (status)
+			user_log_dlm_error("ocfs2_dlm_unlock", status, lockres);
+		goto drop_ref;
+	}
+
+	/* If there are still incompat holders, we can exit safely
+	 * without worrying about re-queueing this lock as that will
+	 * happen on the last call to user_cluster_unlock. */
+	if ((lockres->l_blocking == DLM_LOCK_EX)
+	    && (lockres->l_ex_holders || lockres->l_ro_holders)) {
+		spin_unlock(&lockres->l_lock);
+		mlog(ML_BASTS, "lockres %.*s, EX/PR Holders %u,%u\n",
+		     lockres->l_namelen, lockres->l_name,
+		     lockres->l_ex_holders, lockres->l_ro_holders);
+		goto drop_ref;
+	}
+
+	if ((lockres->l_blocking == DLM_LOCK_PR)
+	    && lockres->l_ex_holders) {
+		spin_unlock(&lockres->l_lock);
+		mlog(ML_BASTS, "lockres %.*s, EX Holders %u\n",
+		     lockres->l_namelen, lockres->l_name,
+		     lockres->l_ex_holders);
+		goto drop_ref;
+	}
+
+	/* yay, we can downconvert now. */
+	new_level = user_highest_compat_lock_level(lockres->l_blocking);
+	lockres->l_requested = new_level;
+	lockres->l_flags |= USER_LOCK_BUSY;
+	mlog(ML_BASTS, "lockres %.*s, downconvert %d => %d\n",
+	     lockres->l_namelen, lockres->l_name, lockres->l_level, new_level);
+	spin_unlock(&lockres->l_lock);
+
+	/* need lock downconvert request now... */
+	status = ocfs2_dlm_lock(conn, new_level, &lockres->l_lksb,
+				DLM_LKF_CONVERT|DLM_LKF_VALBLK,
+				lockres->l_name,
+				lockres->l_namelen);
+	if (status) {
+		user_log_dlm_error("ocfs2_dlm_lock", status, lockres);
+		user_recover_from_dlm_error(lockres);
+	}
+
+drop_ref:
+	user_dlm_drop_inode_ref(lockres);
+}
+
+static inline void user_dlm_inc_holders(struct user_lock_res *lockres,
+					int level)
+{
+	switch(level) {
+	case DLM_LOCK_EX:
+		lockres->l_ex_holders++;
+		break;
+	case DLM_LOCK_PR:
+		lockres->l_ro_holders++;
+		break;
+	default:
+		BUG();
+	}
+}
+
+/* predict what lock level we'll be dropping down to on behalf
+ * of another node, and return true if the currently wanted
+ * level will be compatible with it. */
+static inline int
+user_may_continue_on_blocked_lock(struct user_lock_res *lockres,
+				  int wanted)
+{
+	BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED));
+
+	return wanted <= user_highest_compat_lock_level(lockres->l_blocking);
+}
+
+int user_dlm_cluster_lock(struct user_lock_res *lockres,
+			  int level,
+			  int lkm_flags)
+{
+	int status, local_flags;
+	struct ocfs2_cluster_connection *conn =
+		cluster_connection_from_user_lockres(lockres);
+
+	if (level != DLM_LOCK_EX &&
+	    level != DLM_LOCK_PR) {
+		mlog(ML_ERROR, "lockres %.*s: invalid request!\n",
+		     lockres->l_namelen, lockres->l_name);
+		status = -EINVAL;
+		goto bail;
+	}
+
+	mlog(ML_BASTS, "lockres %.*s, level %d, flags = 0x%x\n",
+	     lockres->l_namelen, lockres->l_name, level, lkm_flags);
+
+again:
+	if (signal_pending(current)) {
+		status = -ERESTARTSYS;
+		goto bail;
+	}
+
+	spin_lock(&lockres->l_lock);
+
+	/* We only compare against the currently granted level
+	 * here. If the lock is blocked waiting on a downconvert,
+	 * we'll get caught below. */
+	if ((lockres->l_flags & USER_LOCK_BUSY) &&
+	    (level > lockres->l_level)) {
+		/* is someone sitting in dlm_lock? If so, wait on
+		 * them. */
+		spin_unlock(&lockres->l_lock);
+
+		user_wait_on_busy_lock(lockres);
+		goto again;
+	}
+
+	if ((lockres->l_flags & USER_LOCK_BLOCKED) &&
+	    (!user_may_continue_on_blocked_lock(lockres, level))) {
+		/* is the lock is currently blocked on behalf of
+		 * another node */
+		spin_unlock(&lockres->l_lock);
+
+		user_wait_on_blocked_lock(lockres);
+		goto again;
+	}
+
+	if (level > lockres->l_level) {
+		local_flags = lkm_flags | DLM_LKF_VALBLK;
+		if (lockres->l_level != DLM_LOCK_IV)
+			local_flags |= DLM_LKF_CONVERT;
+
+		lockres->l_requested = level;
+		lockres->l_flags |= USER_LOCK_BUSY;
+		spin_unlock(&lockres->l_lock);
+
+		BUG_ON(level == DLM_LOCK_IV);
+		BUG_ON(level == DLM_LOCK_NL);
+
+		/* call dlm_lock to upgrade lock now */
+		status = ocfs2_dlm_lock(conn, level, &lockres->l_lksb,
+					local_flags, lockres->l_name,
+					lockres->l_namelen);
+		if (status) {
+			if ((lkm_flags & DLM_LKF_NOQUEUE) &&
+			    (status != -EAGAIN))
+				user_log_dlm_error("ocfs2_dlm_lock",
+						   status, lockres);
+			user_recover_from_dlm_error(lockres);
+			goto bail;
+		}
+
+		user_wait_on_busy_lock(lockres);
+		goto again;
+	}
+
+	user_dlm_inc_holders(lockres, level);
+	spin_unlock(&lockres->l_lock);
+
+	status = 0;
+bail:
+	return status;
+}
+
+static inline void user_dlm_dec_holders(struct user_lock_res *lockres,
+					int level)
+{
+	switch(level) {
+	case DLM_LOCK_EX:
+		BUG_ON(!lockres->l_ex_holders);
+		lockres->l_ex_holders--;
+		break;
+	case DLM_LOCK_PR:
+		BUG_ON(!lockres->l_ro_holders);
+		lockres->l_ro_holders--;
+		break;
+	default:
+		BUG();
+	}
+}
+
+void user_dlm_cluster_unlock(struct user_lock_res *lockres,
+			     int level)
+{
+	if (level != DLM_LOCK_EX &&
+	    level != DLM_LOCK_PR) {
+		mlog(ML_ERROR, "lockres %.*s: invalid request!\n",
+		     lockres->l_namelen, lockres->l_name);
+		return;
+	}
+
+	spin_lock(&lockres->l_lock);
+	user_dlm_dec_holders(lockres, level);
+	__user_dlm_cond_queue_lockres(lockres);
+	spin_unlock(&lockres->l_lock);
+}
+
+void user_dlm_write_lvb(struct inode *inode,
+			const char *val,
+			unsigned int len)
+{
+	struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres;
+	char *lvb;
+
+	BUG_ON(len > DLM_LVB_LEN);
+
+	spin_lock(&lockres->l_lock);
+
+	BUG_ON(lockres->l_level < DLM_LOCK_EX);
+	lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
+	memcpy(lvb, val, len);
+
+	spin_unlock(&lockres->l_lock);
+}
+
+ssize_t user_dlm_read_lvb(struct inode *inode,
+			  char *val,
+			  unsigned int len)
+{
+	struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres;
+	char *lvb;
+	ssize_t ret = len;
+
+	BUG_ON(len > DLM_LVB_LEN);
+
+	spin_lock(&lockres->l_lock);
+
+	BUG_ON(lockres->l_level < DLM_LOCK_PR);
+	if (ocfs2_dlm_lvb_valid(&lockres->l_lksb)) {
+		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
+		memcpy(val, lvb, len);
+	} else
+		ret = 0;
+
+	spin_unlock(&lockres->l_lock);
+	return ret;
+}
+
+void user_dlm_lock_res_init(struct user_lock_res *lockres,
+			    struct dentry *dentry)
+{
+	memset(lockres, 0, sizeof(*lockres));
+
+	spin_lock_init(&lockres->l_lock);
+	init_waitqueue_head(&lockres->l_event);
+	lockres->l_level = DLM_LOCK_IV;
+	lockres->l_requested = DLM_LOCK_IV;
+	lockres->l_blocking = DLM_LOCK_IV;
+
+	/* should have been checked before getting here. */
+	BUG_ON(dentry->d_name.len >= USER_DLM_LOCK_ID_MAX_LEN);
+
+	memcpy(lockres->l_name,
+	       dentry->d_name.name,
+	       dentry->d_name.len);
+	lockres->l_namelen = dentry->d_name.len;
+}
+
+int user_dlm_destroy_lock(struct user_lock_res *lockres)
+{
+	int status = -EBUSY;
+	struct ocfs2_cluster_connection *conn =
+		cluster_connection_from_user_lockres(lockres);
+
+	mlog(ML_BASTS, "lockres %.*s\n", lockres->l_namelen, lockres->l_name);
+
+	spin_lock(&lockres->l_lock);
+	if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
+		spin_unlock(&lockres->l_lock);
+		return 0;
+	}
+
+	lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
+
+	while (lockres->l_flags & USER_LOCK_BUSY) {
+		spin_unlock(&lockres->l_lock);
+
+		user_wait_on_busy_lock(lockres);
+
+		spin_lock(&lockres->l_lock);
+	}
+
+	if (lockres->l_ro_holders || lockres->l_ex_holders) {
+		spin_unlock(&lockres->l_lock);
+		goto bail;
+	}
+
+	status = 0;
+	if (!(lockres->l_flags & USER_LOCK_ATTACHED)) {
+		spin_unlock(&lockres->l_lock);
+		goto bail;
+	}
+
+	lockres->l_flags &= ~USER_LOCK_ATTACHED;
+	lockres->l_flags |= USER_LOCK_BUSY;
+	spin_unlock(&lockres->l_lock);
+
+	status = ocfs2_dlm_unlock(conn, &lockres->l_lksb, DLM_LKF_VALBLK);
+	if (status) {
+		user_log_dlm_error("ocfs2_dlm_unlock", status, lockres);
+		goto bail;
+	}
+
+	user_wait_on_busy_lock(lockres);
+
+	status = 0;
+bail:
+	return status;
+}
+
+static void user_dlm_recovery_handler_noop(int node_num,
+					   void *recovery_data)
+{
+	/* We ignore recovery events */
+	return;
+}
+
+void user_dlm_set_locking_protocol(void)
+{
+	ocfs2_stack_glue_set_max_proto_version(&user_dlm_lproto.lp_max_version);
+}
+
+struct ocfs2_cluster_connection *user_dlm_register(struct qstr *name)
+{
+	int rc;
+	struct ocfs2_cluster_connection *conn;
+
+	rc = ocfs2_cluster_connect_agnostic(name->name, name->len,
+					    &user_dlm_lproto,
+					    user_dlm_recovery_handler_noop,
+					    NULL, &conn);
+	if (rc)
+		mlog_errno(rc);
+
+	return rc ? ERR_PTR(rc) : conn;
+}
+
+void user_dlm_unregister(struct ocfs2_cluster_connection *conn)
+{
+	ocfs2_cluster_disconnect(conn, 0);
+}
diff --git a/fs/ocfs2/dlmfs/userdlm.h b/fs/ocfs2/dlmfs/userdlm.h
new file mode 100644
index 0000000..3b42d79
--- /dev/null
+++ b/fs/ocfs2/dlmfs/userdlm.h
@@ -0,0 +1,113 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * userdlm.h
+ *
+ * Userspace dlm defines
+ *
+ * Copyright (C) 2002, 2004 Oracle.  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 021110-1307, USA.
+ */
+
+
+#ifndef USERDLM_H
+#define USERDLM_H
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+/* user_lock_res->l_flags flags. */
+#define USER_LOCK_ATTACHED      (0x00000001) /* we have initialized
+					       * the lvb */
+#define USER_LOCK_BUSY          (0x00000002) /* we are currently in
+					       * dlm_lock */
+#define USER_LOCK_BLOCKED       (0x00000004) /* blocked waiting to
+					      * downconvert*/
+#define USER_LOCK_IN_TEARDOWN   (0x00000008) /* we're currently
+					      * destroying this
+					      * lock. */
+#define USER_LOCK_QUEUED        (0x00000010) /* lock is on the
+					      * workqueue */
+#define USER_LOCK_IN_CANCEL     (0x00000020)
+
+struct user_lock_res {
+	spinlock_t               l_lock;
+
+	int                      l_flags;
+
+#define USER_DLM_LOCK_ID_MAX_LEN  32
+	char                     l_name[USER_DLM_LOCK_ID_MAX_LEN];
+	int                      l_namelen;
+	int                      l_level;
+	unsigned int             l_ro_holders;
+	unsigned int             l_ex_holders;
+	struct ocfs2_dlm_lksb    l_lksb;
+
+	int                      l_requested;
+	int                      l_blocking;
+
+	wait_queue_head_t        l_event;
+
+	struct work_struct       l_work;
+};
+
+extern struct workqueue_struct *user_dlm_worker;
+
+void user_dlm_lock_res_init(struct user_lock_res *lockres,
+			    struct dentry *dentry);
+int user_dlm_destroy_lock(struct user_lock_res *lockres);
+int user_dlm_cluster_lock(struct user_lock_res *lockres,
+			  int level,
+			  int lkm_flags);
+void user_dlm_cluster_unlock(struct user_lock_res *lockres,
+			     int level);
+void user_dlm_write_lvb(struct inode *inode,
+			const char *val,
+			unsigned int len);
+ssize_t user_dlm_read_lvb(struct inode *inode,
+			  char *val,
+			  unsigned int len);
+struct ocfs2_cluster_connection *user_dlm_register(struct qstr *name);
+void user_dlm_unregister(struct ocfs2_cluster_connection *conn);
+void user_dlm_set_locking_protocol(void);
+
+struct dlmfs_inode_private {
+	struct ocfs2_cluster_connection	*ip_conn;
+
+	struct user_lock_res ip_lockres; /* unused for directories. */
+	struct inode         *ip_parent;
+
+	struct inode         ip_vfs_inode;
+};
+
+static inline struct dlmfs_inode_private *
+DLMFS_I(struct inode *inode)
+{
+        return container_of(inode,
+			    struct dlmfs_inode_private,
+			    ip_vfs_inode);
+}
+
+struct dlmfs_filp_private {
+	int                  fp_lock_level;
+};
+
+#define DLMFS_MAGIC	0x76a9f425
+
+#endif /* USERDLM_H */
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index e044019..50c4ee8 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -297,6 +297,11 @@
 		lockres->l_type == OCFS2_LOCK_TYPE_OPEN;
 }
 
+static inline struct ocfs2_lock_res *ocfs2_lksb_to_lock_res(struct ocfs2_dlm_lksb *lksb)
+{
+	return container_of(lksb, struct ocfs2_lock_res, l_lksb);
+}
+
 static inline struct inode *ocfs2_lock_res_inode(struct ocfs2_lock_res *lockres)
 {
 	BUG_ON(!ocfs2_is_inode_lock(lockres));
@@ -927,6 +932,10 @@
 		lockres->l_blocking = level;
 	}
 
+	mlog(ML_BASTS, "lockres %s, block %d, level %d, l_block %d, dwn %d\n",
+	     lockres->l_name, level, lockres->l_level, lockres->l_blocking,
+	     needs_downconvert);
+
 	if (needs_downconvert)
 		lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
 
@@ -1040,18 +1049,17 @@
 	return lockres->l_pending_gen;
 }
 
-
-static void ocfs2_blocking_ast(void *opaque, int level)
+static void ocfs2_blocking_ast(struct ocfs2_dlm_lksb *lksb, int level)
 {
-	struct ocfs2_lock_res *lockres = opaque;
+	struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb);
 	struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres);
 	int needs_downconvert;
 	unsigned long flags;
 
 	BUG_ON(level <= DLM_LOCK_NL);
 
-	mlog(0, "BAST fired for lockres %s, blocking %d, level %d type %s\n",
-	     lockres->l_name, level, lockres->l_level,
+	mlog(ML_BASTS, "BAST fired for lockres %s, blocking %d, level %d, "
+	     "type %s\n", lockres->l_name, level, lockres->l_level,
 	     ocfs2_lock_type_string(lockres->l_type));
 
 	/*
@@ -1072,9 +1080,9 @@
 	ocfs2_wake_downconvert_thread(osb);
 }
 
-static void ocfs2_locking_ast(void *opaque)
+static void ocfs2_locking_ast(struct ocfs2_dlm_lksb *lksb)
 {
-	struct ocfs2_lock_res *lockres = opaque;
+	struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb);
 	struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres);
 	unsigned long flags;
 	int status;
@@ -1095,6 +1103,10 @@
 		return;
 	}
 
+	mlog(ML_BASTS, "AST fired for lockres %s, action %d, unlock %d, "
+	     "level %d => %d\n", lockres->l_name, lockres->l_action,
+	     lockres->l_unlock_action, lockres->l_level, lockres->l_requested);
+
 	switch(lockres->l_action) {
 	case OCFS2_AST_ATTACH:
 		ocfs2_generic_handle_attach_action(lockres);
@@ -1107,8 +1119,8 @@
 		ocfs2_generic_handle_downconvert_action(lockres);
 		break;
 	default:
-		mlog(ML_ERROR, "lockres %s: ast fired with invalid action: %u "
-		     "lockres flags = 0x%lx, unlock action: %u\n",
+		mlog(ML_ERROR, "lockres %s: AST fired with invalid action: %u, "
+		     "flags 0x%lx, unlock: %u\n",
 		     lockres->l_name, lockres->l_action, lockres->l_flags,
 		     lockres->l_unlock_action);
 		BUG();
@@ -1134,6 +1146,88 @@
 	spin_unlock_irqrestore(&lockres->l_lock, flags);
 }
 
+static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error)
+{
+	struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb);
+	unsigned long flags;
+
+	mlog_entry_void();
+
+	mlog(ML_BASTS, "UNLOCK AST fired for lockres %s, action = %d\n",
+	     lockres->l_name, lockres->l_unlock_action);
+
+	spin_lock_irqsave(&lockres->l_lock, flags);
+	if (error) {
+		mlog(ML_ERROR, "Dlm passes error %d for lock %s, "
+		     "unlock_action %d\n", error, lockres->l_name,
+		     lockres->l_unlock_action);
+		spin_unlock_irqrestore(&lockres->l_lock, flags);
+		mlog_exit_void();
+		return;
+	}
+
+	switch(lockres->l_unlock_action) {
+	case OCFS2_UNLOCK_CANCEL_CONVERT:
+		mlog(0, "Cancel convert success for %s\n", lockres->l_name);
+		lockres->l_action = OCFS2_AST_INVALID;
+		/* Downconvert thread may have requeued this lock, we
+		 * need to wake it. */
+		if (lockres->l_flags & OCFS2_LOCK_BLOCKED)
+			ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb(lockres));
+		break;
+	case OCFS2_UNLOCK_DROP_LOCK:
+		lockres->l_level = DLM_LOCK_IV;
+		break;
+	default:
+		BUG();
+	}
+
+	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
+	lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
+	wake_up(&lockres->l_event);
+	spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+	mlog_exit_void();
+}
+
+/*
+ * This is the filesystem locking protocol.  It provides the lock handling
+ * hooks for the underlying DLM.  It has a maximum version number.
+ * The version number allows interoperability with systems running at
+ * the same major number and an equal or smaller minor number.
+ *
+ * Whenever the filesystem does new things with locks (adds or removes a
+ * lock, orders them differently, does different things underneath a lock),
+ * the version must be changed.  The protocol is negotiated when joining
+ * the dlm domain.  A node may join the domain if its major version is
+ * identical to all other nodes and its minor version is greater than
+ * or equal to all other nodes.  When its minor version is greater than
+ * the other nodes, it will run at the minor version specified by the
+ * other nodes.
+ *
+ * If a locking change is made that will not be compatible with older
+ * versions, the major number must be increased and the minor version set
+ * to zero.  If a change merely adds a behavior that can be disabled when
+ * speaking to older versions, the minor version must be increased.  If a
+ * change adds a fully backwards compatible change (eg, LVB changes that
+ * are just ignored by older versions), the version does not need to be
+ * updated.
+ */
+static struct ocfs2_locking_protocol lproto = {
+	.lp_max_version = {
+		.pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR,
+		.pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR,
+	},
+	.lp_lock_ast		= ocfs2_locking_ast,
+	.lp_blocking_ast	= ocfs2_blocking_ast,
+	.lp_unlock_ast		= ocfs2_unlock_ast,
+};
+
+void ocfs2_set_locking_protocol(void)
+{
+	ocfs2_stack_glue_set_max_proto_version(&lproto.lp_max_version);
+}
+
 static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
 						int convert)
 {
@@ -1189,8 +1283,7 @@
 			     &lockres->l_lksb,
 			     dlm_flags,
 			     lockres->l_name,
-			     OCFS2_LOCK_ID_MAX_LEN - 1,
-			     lockres);
+			     OCFS2_LOCK_ID_MAX_LEN - 1);
 	lockres_clear_pending(lockres, gen, osb);
 	if (ret) {
 		ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
@@ -1412,7 +1505,7 @@
 		BUG_ON(level == DLM_LOCK_IV);
 		BUG_ON(level == DLM_LOCK_NL);
 
-		mlog(0, "lock %s, convert from %d to level = %d\n",
+		mlog(ML_BASTS, "lockres %s, convert from %d to %d\n",
 		     lockres->l_name, lockres->l_level, level);
 
 		/* call dlm_lock to upgrade lock now */
@@ -1421,8 +1514,7 @@
 				     &lockres->l_lksb,
 				     lkm_flags,
 				     lockres->l_name,
-				     OCFS2_LOCK_ID_MAX_LEN - 1,
-				     lockres);
+				     OCFS2_LOCK_ID_MAX_LEN - 1);
 		lockres_clear_pending(lockres, gen, osb);
 		if (ret) {
 			if (!(lkm_flags & DLM_LKF_NOQUEUE) ||
@@ -1789,7 +1881,7 @@
  * ocfs2_file_lock() and ocfs2_file_unlock() map to a single pair of
  * flock() calls. The locking approach this requires is sufficiently
  * different from all other cluster lock types that we implement a
- * seperate path to the "low-level" dlm calls. In particular:
+ * separate path to the "low-level" dlm calls. In particular:
  *
  * - No optimization of lock levels is done - we take at exactly
  *   what's been requested.
@@ -1859,8 +1951,7 @@
 	spin_unlock_irqrestore(&lockres->l_lock, flags);
 
 	ret = ocfs2_dlm_lock(osb->cconn, level, &lockres->l_lksb, lkm_flags,
-			     lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1,
-			     lockres);
+			     lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1);
 	if (ret) {
 		if (!trylock || (ret != -EAGAIN)) {
 			ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
@@ -2989,7 +3080,7 @@
 	status = ocfs2_cluster_connect(osb->osb_cluster_stack,
 				       osb->uuid_str,
 				       strlen(osb->uuid_str),
-				       ocfs2_do_node_down, osb,
+				       &lproto, ocfs2_do_node_down, osb,
 				       &conn);
 	if (status) {
 		mlog_errno(status);
@@ -3056,50 +3147,6 @@
 	mlog_exit_void();
 }
 
-static void ocfs2_unlock_ast(void *opaque, int error)
-{
-	struct ocfs2_lock_res *lockres = opaque;
-	unsigned long flags;
-
-	mlog_entry_void();
-
-	mlog(0, "UNLOCK AST called on lock %s, action = %d\n", lockres->l_name,
-	     lockres->l_unlock_action);
-
-	spin_lock_irqsave(&lockres->l_lock, flags);
-	if (error) {
-		mlog(ML_ERROR, "Dlm passes error %d for lock %s, "
-		     "unlock_action %d\n", error, lockres->l_name,
-		     lockres->l_unlock_action);
-		spin_unlock_irqrestore(&lockres->l_lock, flags);
-		mlog_exit_void();
-		return;
-	}
-
-	switch(lockres->l_unlock_action) {
-	case OCFS2_UNLOCK_CANCEL_CONVERT:
-		mlog(0, "Cancel convert success for %s\n", lockres->l_name);
-		lockres->l_action = OCFS2_AST_INVALID;
-		/* Downconvert thread may have requeued this lock, we
-		 * need to wake it. */
-		if (lockres->l_flags & OCFS2_LOCK_BLOCKED)
-			ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb(lockres));
-		break;
-	case OCFS2_UNLOCK_DROP_LOCK:
-		lockres->l_level = DLM_LOCK_IV;
-		break;
-	default:
-		BUG();
-	}
-
-	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
-	lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
-	wake_up(&lockres->l_event);
-	spin_unlock_irqrestore(&lockres->l_lock, flags);
-
-	mlog_exit_void();
-}
-
 static int ocfs2_drop_lock(struct ocfs2_super *osb,
 			   struct ocfs2_lock_res *lockres)
 {
@@ -3167,8 +3214,7 @@
 
 	mlog(0, "lock %s\n", lockres->l_name);
 
-	ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb, lkm_flags,
-			       lockres);
+	ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb, lkm_flags);
 	if (ret) {
 		ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres);
 		mlog(ML_ERROR, "lockres flags: %lu\n", lockres->l_flags);
@@ -3276,13 +3322,20 @@
 	BUG_ON(lockres->l_blocking <= DLM_LOCK_NL);
 
 	if (lockres->l_level <= new_level) {
-		mlog(ML_ERROR, "lockres->l_level (%d) <= new_level (%d)\n",
-		     lockres->l_level, new_level);
+		mlog(ML_ERROR, "lockres %s, lvl %d <= %d, blcklst %d, mask %d, "
+		     "type %d, flags 0x%lx, hold %d %d, act %d %d, req %d, "
+		     "block %d, pgen %d\n", lockres->l_name, lockres->l_level,
+		     new_level, list_empty(&lockres->l_blocked_list),
+		     list_empty(&lockres->l_mask_waiters), lockres->l_type,
+		     lockres->l_flags, lockres->l_ro_holders,
+		     lockres->l_ex_holders, lockres->l_action,
+		     lockres->l_unlock_action, lockres->l_requested,
+		     lockres->l_blocking, lockres->l_pending_gen);
 		BUG();
 	}
 
-	mlog(0, "lock %s, new_level = %d, l_blocking = %d\n",
-	     lockres->l_name, new_level, lockres->l_blocking);
+	mlog(ML_BASTS, "lockres %s, level %d => %d, blocking %d\n",
+	     lockres->l_name, lockres->l_level, new_level, lockres->l_blocking);
 
 	lockres->l_action = OCFS2_AST_DOWNCONVERT;
 	lockres->l_requested = new_level;
@@ -3301,6 +3354,9 @@
 
 	mlog_entry_void();
 
+	mlog(ML_BASTS, "lockres %s, level %d => %d\n", lockres->l_name,
+	     lockres->l_level, new_level);
+
 	if (lvb)
 		dlm_flags |= DLM_LKF_VALBLK;
 
@@ -3309,8 +3365,7 @@
 			     &lockres->l_lksb,
 			     dlm_flags,
 			     lockres->l_name,
-			     OCFS2_LOCK_ID_MAX_LEN - 1,
-			     lockres);
+			     OCFS2_LOCK_ID_MAX_LEN - 1);
 	lockres_clear_pending(lockres, generation, osb);
 	if (ret) {
 		ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, lockres);
@@ -3331,14 +3386,12 @@
 	assert_spin_locked(&lockres->l_lock);
 
 	mlog_entry_void();
-	mlog(0, "lock %s\n", lockres->l_name);
 
 	if (lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
 		/* If we're already trying to cancel a lock conversion
 		 * then just drop the spinlock and allow the caller to
 		 * requeue this lock. */
-
-		mlog(0, "Lockres %s, skip convert\n", lockres->l_name);
+		mlog(ML_BASTS, "lockres %s, skip convert\n", lockres->l_name);
 		return 0;
 	}
 
@@ -3353,6 +3406,8 @@
 			"lock %s, invalid flags: 0x%lx\n",
 			lockres->l_name, lockres->l_flags);
 
+	mlog(ML_BASTS, "lockres %s\n", lockres->l_name);
+
 	return 1;
 }
 
@@ -3362,16 +3417,15 @@
 	int ret;
 
 	mlog_entry_void();
-	mlog(0, "lock %s\n", lockres->l_name);
 
 	ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb,
-			       DLM_LKF_CANCEL, lockres);
+			       DLM_LKF_CANCEL);
 	if (ret) {
 		ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres);
 		ocfs2_recover_from_dlm_error(lockres, 0);
 	}
 
-	mlog(0, "lock %s return from ocfs2_dlm_unlock\n", lockres->l_name);
+	mlog(ML_BASTS, "lockres %s\n", lockres->l_name);
 
 	mlog_exit(ret);
 	return ret;
@@ -3428,8 +3482,11 @@
 		 * at the same time they set OCFS2_DLM_BUSY.  They must
 		 * clear OCFS2_DLM_PENDING after dlm_lock() returns.
 		 */
-		if (lockres->l_flags & OCFS2_LOCK_PENDING)
+		if (lockres->l_flags & OCFS2_LOCK_PENDING) {
+			mlog(ML_BASTS, "lockres %s, ReQ: Pending\n",
+			     lockres->l_name);
 			goto leave_requeue;
+		}
 
 		ctl->requeue = 1;
 		ret = ocfs2_prepare_cancel_convert(osb, lockres);
@@ -3461,6 +3518,7 @@
 	 */
 	if (lockres->l_level == DLM_LOCK_NL) {
 		BUG_ON(lockres->l_ex_holders || lockres->l_ro_holders);
+		mlog(ML_BASTS, "lockres %s, Aborting dc\n", lockres->l_name);
 		lockres->l_blocking = DLM_LOCK_NL;
 		lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED);
 		spin_unlock_irqrestore(&lockres->l_lock, flags);
@@ -3470,28 +3528,41 @@
 	/* if we're blocking an exclusive and we have *any* holders,
 	 * then requeue. */
 	if ((lockres->l_blocking == DLM_LOCK_EX)
-	    && (lockres->l_ex_holders || lockres->l_ro_holders))
+	    && (lockres->l_ex_holders || lockres->l_ro_holders)) {
+		mlog(ML_BASTS, "lockres %s, ReQ: EX/PR Holders %u,%u\n",
+		     lockres->l_name, lockres->l_ex_holders,
+		     lockres->l_ro_holders);
 		goto leave_requeue;
+	}
 
 	/* If it's a PR we're blocking, then only
 	 * requeue if we've got any EX holders */
 	if (lockres->l_blocking == DLM_LOCK_PR &&
-	    lockres->l_ex_holders)
+	    lockres->l_ex_holders) {
+		mlog(ML_BASTS, "lockres %s, ReQ: EX Holders %u\n",
+		     lockres->l_name, lockres->l_ex_holders);
 		goto leave_requeue;
+	}
 
 	/*
 	 * Can we get a lock in this state if the holder counts are
 	 * zero? The meta data unblock code used to check this.
 	 */
 	if ((lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH)
-	    && (lockres->l_flags & OCFS2_LOCK_REFRESHING))
+	    && (lockres->l_flags & OCFS2_LOCK_REFRESHING)) {
+		mlog(ML_BASTS, "lockres %s, ReQ: Lock Refreshing\n",
+		     lockres->l_name);
 		goto leave_requeue;
+	}
 
 	new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking);
 
 	if (lockres->l_ops->check_downconvert
-	    && !lockres->l_ops->check_downconvert(lockres, new_level))
+	    && !lockres->l_ops->check_downconvert(lockres, new_level)) {
+		mlog(ML_BASTS, "lockres %s, ReQ: Checkpointing\n",
+		     lockres->l_name);
 		goto leave_requeue;
+	}
 
 	/* If we get here, then we know that there are no more
 	 * incompatible holders (and anyone asking for an incompatible
@@ -3509,13 +3580,19 @@
 
 	ctl->unblock_action = lockres->l_ops->downconvert_worker(lockres, blocking);
 
-	if (ctl->unblock_action == UNBLOCK_STOP_POST)
+	if (ctl->unblock_action == UNBLOCK_STOP_POST) {
+		mlog(ML_BASTS, "lockres %s, UNBLOCK_STOP_POST\n",
+		     lockres->l_name);
 		goto leave;
+	}
 
 	spin_lock_irqsave(&lockres->l_lock, flags);
 	if ((blocking != lockres->l_blocking) || (level != lockres->l_level)) {
 		/* If this changed underneath us, then we can't drop
 		 * it just yet. */
+		mlog(ML_BASTS, "lockres %s, block=%d:%d, level=%d:%d, "
+		     "Recheck\n", lockres->l_name, blocking,
+		     lockres->l_blocking, level, lockres->l_level);
 		goto recheck;
 	}
 
@@ -3910,45 +3987,6 @@
 		ocfs2_cluster_unlock(osb, lockres, level);
 }
 
-/*
- * This is the filesystem locking protocol.  It provides the lock handling
- * hooks for the underlying DLM.  It has a maximum version number.
- * The version number allows interoperability with systems running at
- * the same major number and an equal or smaller minor number.
- *
- * Whenever the filesystem does new things with locks (adds or removes a
- * lock, orders them differently, does different things underneath a lock),
- * the version must be changed.  The protocol is negotiated when joining
- * the dlm domain.  A node may join the domain if its major version is
- * identical to all other nodes and its minor version is greater than
- * or equal to all other nodes.  When its minor version is greater than
- * the other nodes, it will run at the minor version specified by the
- * other nodes.
- *
- * If a locking change is made that will not be compatible with older
- * versions, the major number must be increased and the minor version set
- * to zero.  If a change merely adds a behavior that can be disabled when
- * speaking to older versions, the minor version must be increased.  If a
- * change adds a fully backwards compatible change (eg, LVB changes that
- * are just ignored by older versions), the version does not need to be
- * updated.
- */
-static struct ocfs2_locking_protocol lproto = {
-	.lp_max_version = {
-		.pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR,
-		.pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR,
-	},
-	.lp_lock_ast		= ocfs2_locking_ast,
-	.lp_blocking_ast	= ocfs2_blocking_ast,
-	.lp_unlock_ast		= ocfs2_unlock_ast,
-};
-
-void ocfs2_set_locking_protocol(void)
-{
-	ocfs2_stack_glue_set_locking_protocol(&lproto);
-}
-
-
 static void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
 				       struct ocfs2_lock_res *lockres)
 {
@@ -3965,7 +4003,7 @@
 	BUG_ON(!lockres);
 	BUG_ON(!lockres->l_ops);
 
-	mlog(0, "lockres %s blocked.\n", lockres->l_name);
+	mlog(ML_BASTS, "lockres %s blocked\n", lockres->l_name);
 
 	/* Detect whether a lock has been marked as going away while
 	 * the downconvert thread was processing other things. A lock can
@@ -3988,7 +4026,7 @@
 	} else
 		ocfs2_schedule_blocked_lock(osb, lockres);
 
-	mlog(0, "lockres %s, requeue = %s.\n", lockres->l_name,
+	mlog(ML_BASTS, "lockres %s, requeue = %s.\n", lockres->l_name,
 	     ctl.requeue ? "yes" : "no");
 	spin_unlock_irqrestore(&lockres->l_lock, flags);
 
@@ -4010,7 +4048,7 @@
 		/* Do not schedule a lock for downconvert when it's on
 		 * the way to destruction - any nodes wanting access
 		 * to the resource will get it soon. */
-		mlog(0, "Lockres %s won't be scheduled: flags 0x%lx\n",
+		mlog(ML_BASTS, "lockres %s won't be scheduled: flags 0x%lx\n",
 		     lockres->l_name, lockres->l_flags);
 		return;
 	}
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
index 5328529..c562a75 100644
--- a/fs/ocfs2/extent_map.c
+++ b/fs/ocfs2/extent_map.c
@@ -453,7 +453,7 @@
 	if (i == -1) {
 		/*
 		 * Holes can be larger than the maximum size of an
-		 * extent, so we return their lengths in a seperate
+		 * extent, so we return their lengths in a separate
 		 * field.
 		 */
 		if (hole_len) {
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 558ce03..17947dc 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -107,6 +107,9 @@
 	mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
 		   file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name);
 
+	if (file->f_mode & FMODE_WRITE)
+		dquot_initialize(inode);
+
 	spin_lock(&oi->ip_lock);
 
 	/* Check that the inode hasn't been wiped from disk by another
@@ -629,11 +632,10 @@
 	}
 
 restarted_transaction:
-	if (vfs_dq_alloc_space_nodirty(inode, ocfs2_clusters_to_bytes(osb->sb,
-	    clusters_to_add))) {
-		status = -EDQUOT;
+	status = dquot_alloc_space_nodirty(inode,
+			ocfs2_clusters_to_bytes(osb->sb, clusters_to_add));
+	if (status)
 		goto leave;
-	}
 	did_quota = 1;
 
 	/* reserve a write to the file entry early on - that we if we
@@ -674,7 +676,7 @@
 	clusters_to_add -= (OCFS2_I(inode)->ip_clusters - prev_clusters);
 	spin_unlock(&OCFS2_I(inode)->ip_lock);
 	/* Release unused quota reservation */
-	vfs_dq_free_space(inode,
+	dquot_free_space(inode,
 			ocfs2_clusters_to_bytes(osb->sb, clusters_to_add));
 	did_quota = 0;
 
@@ -710,7 +712,7 @@
 
 leave:
 	if (status < 0 && did_quota)
-		vfs_dq_free_space(inode,
+		dquot_free_space(inode,
 			ocfs2_clusters_to_bytes(osb->sb, clusters_to_add));
 	if (handle) {
 		ocfs2_commit_trans(osb, handle);
@@ -978,6 +980,8 @@
 
 	size_change = S_ISREG(inode->i_mode) && attr->ia_valid & ATTR_SIZE;
 	if (size_change) {
+		dquot_initialize(inode);
+
 		status = ocfs2_rw_lock(inode, 1);
 		if (status < 0) {
 			mlog_errno(status);
@@ -993,10 +997,9 @@
 	}
 
 	if (size_change && attr->ia_size != i_size_read(inode)) {
-		if (attr->ia_size > sb->s_maxbytes) {
-			status = -EFBIG;
+		status = inode_newsize_ok(inode, attr->ia_size);
+		if (status)
 			goto bail_unlock;
-		}
 
 		if (i_size_read(inode) > attr->ia_size) {
 			if (ocfs2_should_order_data(inode)) {
@@ -1021,7 +1024,7 @@
 		/*
 		 * Gather pointers to quota structures so that allocation /
 		 * freeing of quota structures happens here and not inside
-		 * vfs_dq_transfer() where we have problems with lock ordering
+		 * dquot_transfer() where we have problems with lock ordering
 		 */
 		if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid
 		    && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
@@ -1054,7 +1057,7 @@
 			mlog_errno(status);
 			goto bail_unlock;
 		}
-		status = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0;
+		status = dquot_transfer(inode, attr);
 		if (status < 0)
 			goto bail_commit;
 	} else {
@@ -1836,6 +1839,8 @@
 							       &meta_level);
 			if (has_refcount)
 				*has_refcount = 1;
+			if (direct_io)
+				*direct_io = 0;
 		}
 
 		if (ret < 0) {
@@ -1859,10 +1864,6 @@
 			break;
 		}
 
-		if (has_refcount && *has_refcount == 1) {
-			*direct_io = 0;
-			break;
-		}
 		/*
 		 * Allowing concurrent direct writes means
 		 * i_size changes wouldn't be synchronized, so
@@ -2043,7 +2044,7 @@
 	 * async dio is going to do it in the future or an end_io after an
 	 * error has already done it.
 	 */
-	if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) {
+	if ((ret == -EIOCBQUEUED) || (!ocfs2_iocb_is_rw_locked(iocb))) {
 		rw_level = -1;
 		have_alloc_sem = 0;
 	}
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 88459bd..278a223 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -665,7 +665,7 @@
 	}
 
 	ocfs2_remove_from_cache(INODE_CACHE(inode), di_bh);
-	vfs_dq_free_inode(inode);
+	dquot_free_inode(inode);
 
 	status = ocfs2_free_dinode(handle, inode_alloc_inode,
 				   inode_alloc_bh, di);
@@ -971,6 +971,8 @@
 		goto bail;
 	}
 
+	dquot_initialize(inode);
+
 	if (!ocfs2_inode_is_valid_to_delete(inode)) {
 		/* It's probably not necessary to truncate_inode_pages
 		 * here but we do it for safety anyway (it will most
@@ -1087,6 +1089,8 @@
 	mlog_bug_on_msg(OCFS2_SB(inode->i_sb) == NULL,
 			"Inode=%lu\n", inode->i_ino);
 
+	dquot_drop(inode);
+
 	/* To preven remote deletes we hold open lock before, now it
 	 * is time to unlock PR and EX open locks. */
 	ocfs2_open_unlock(inode);
diff --git a/fs/ocfs2/ioctl.h b/fs/ocfs2/ioctl.h
index cf9a5ee..0cd5323 100644
--- a/fs/ocfs2/ioctl.h
+++ b/fs/ocfs2/ioctl.h
@@ -7,10 +7,10 @@
  *
  */
 
-#ifndef OCFS2_IOCTL_H
-#define OCFS2_IOCTL_H
+#ifndef OCFS2_IOCTL_PROTO_H
+#define OCFS2_IOCTL_PROTO_H
 
 long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg);
 
-#endif /* OCFS2_IOCTL_H */
+#endif /* OCFS2_IOCTL_PROTO_H */
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index ac10f83..ca992d9 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -476,7 +476,7 @@
 
 out:
 	if (!status)
-		ocfs2_init_inode_steal_slot(osb);
+		ocfs2_init_steal_slots(osb);
 	mlog_exit(status);
 	return status;
 }
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 50fb26a..d9cd4e3 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -212,7 +212,7 @@
 	} else
 		inode->i_gid = current_fsgid();
 	inode->i_mode = mode;
-	vfs_dq_init(inode);
+	dquot_initialize(inode);
 	return inode;
 }
 
@@ -244,6 +244,8 @@
 		   (unsigned long)dev, dentry->d_name.len,
 		   dentry->d_name.name);
 
+	dquot_initialize(dir);
+
 	/* get our super block */
 	osb = OCFS2_SB(dir->i_sb);
 
@@ -348,13 +350,9 @@
 		goto leave;
 	}
 
-	/* We don't use standard VFS wrapper because we don't want vfs_dq_init
-	 * to be called. */
-	if (sb_any_quota_active(osb->sb) &&
-	    osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
-		status = -EDQUOT;
+	status = dquot_alloc_inode(inode);
+	if (status)
 		goto leave;
-	}
 	did_quota_inode = 1;
 
 	mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry,
@@ -431,7 +429,7 @@
 	status = 0;
 leave:
 	if (status < 0 && did_quota_inode)
-		vfs_dq_free_inode(inode);
+		dquot_free_inode(inode);
 	if (handle)
 		ocfs2_commit_trans(osb, handle);
 
@@ -636,6 +634,8 @@
 	if (S_ISDIR(inode->i_mode))
 		return -EPERM;
 
+	dquot_initialize(dir);
+
 	err = ocfs2_inode_lock_nested(dir, &parent_fe_bh, 1, OI_LS_PARENT);
 	if (err < 0) {
 		if (err != -ENOENT)
@@ -791,6 +791,8 @@
 	mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry,
 		   dentry->d_name.len, dentry->d_name.name);
 
+	dquot_initialize(dir);
+
 	BUG_ON(dentry->d_parent->d_inode != dir);
 
 	mlog(0, "ino = %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno);
@@ -1051,6 +1053,9 @@
 		   old_dentry->d_name.len, old_dentry->d_name.name,
 		   new_dentry->d_name.len, new_dentry->d_name.name);
 
+	dquot_initialize(old_dir);
+	dquot_initialize(new_dir);
+
 	osb = OCFS2_SB(old_dir->i_sb);
 
 	if (new_inode) {
@@ -1599,6 +1604,8 @@
 	mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir,
 		   dentry, symname, dentry->d_name.len, dentry->d_name.name);
 
+	dquot_initialize(dir);
+
 	sb = dir->i_sb;
 	osb = OCFS2_SB(sb);
 
@@ -1688,13 +1695,9 @@
 		goto bail;
 	}
 
-	/* We don't use standard VFS wrapper because we don't want vfs_dq_init
-	 * to be called. */
-	if (sb_any_quota_active(osb->sb) &&
-	    osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
-		status = -EDQUOT;
+	status = dquot_alloc_inode(inode);
+	if (status)
 		goto bail;
-	}
 	did_quota_inode = 1;
 
 	mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry,
@@ -1716,11 +1719,10 @@
 		u32 offset = 0;
 
 		inode->i_op = &ocfs2_symlink_inode_operations;
-		if (vfs_dq_alloc_space_nodirty(inode,
-		    ocfs2_clusters_to_bytes(osb->sb, 1))) {
-			status = -EDQUOT;
+		status = dquot_alloc_space_nodirty(inode,
+		    ocfs2_clusters_to_bytes(osb->sb, 1));
+		if (status)
 			goto bail;
-		}
 		did_quota = 1;
 		status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
 					      new_fe_bh,
@@ -1788,10 +1790,10 @@
 	d_instantiate(dentry, inode);
 bail:
 	if (status < 0 && did_quota)
-		vfs_dq_free_space_nodirty(inode,
+		dquot_free_space_nodirty(inode,
 					ocfs2_clusters_to_bytes(osb->sb, 1));
 	if (status < 0 && did_quota_inode)
-		vfs_dq_free_inode(inode);
+		dquot_free_inode(inode);
 	if (handle)
 		ocfs2_commit_trans(osb, handle);
 
@@ -2099,13 +2101,9 @@
 		goto leave;
 	}
 
-	/* We don't use standard VFS wrapper because we don't want vfs_dq_init
-	 * to be called. */
-	if (sb_any_quota_active(osb->sb) &&
-	    osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
-		status = -EDQUOT;
+	status = dquot_alloc_inode(inode);
+	if (status)
 		goto leave;
-	}
 	did_quota_inode = 1;
 
 	inode->i_nlink = 0;
@@ -2140,7 +2138,7 @@
 	insert_inode_hash(inode);
 leave:
 	if (status < 0 && did_quota_inode)
-		vfs_dq_free_inode(inode);
+		dquot_free_inode(inode);
 	if (handle)
 		ocfs2_commit_trans(osb, handle);
 
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 740f448..1238b49 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -42,6 +42,7 @@
 
 #include "ocfs2_fs.h"
 #include "ocfs2_lockid.h"
+#include "ocfs2_ioctl.h"
 
 /* For struct ocfs2_blockcheck_stats */
 #include "blockcheck.h"
@@ -159,7 +160,7 @@
 	int                      l_level;
 	unsigned int             l_ro_holders;
 	unsigned int             l_ex_holders;
-	union ocfs2_dlm_lksb     l_lksb;
+	struct ocfs2_dlm_lksb    l_lksb;
 
 	/* used from AST/BAST funcs. */
 	enum ocfs2_ast_action    l_action;
@@ -305,7 +306,9 @@
 	u32 s_next_generation;
 	unsigned long osb_flags;
 	s16 s_inode_steal_slot;
+	s16 s_meta_steal_slot;
 	atomic_t s_num_inodes_stolen;
+	atomic_t s_num_meta_stolen;
 
 	unsigned long s_mount_opt;
 	unsigned int s_atime_quantum;
@@ -760,33 +763,6 @@
 	return megs << (20 - OCFS2_SB(sb)->s_clustersize_bits);
 }
 
-static inline void ocfs2_init_inode_steal_slot(struct ocfs2_super *osb)
-{
-	spin_lock(&osb->osb_lock);
-	osb->s_inode_steal_slot = OCFS2_INVALID_SLOT;
-	spin_unlock(&osb->osb_lock);
-	atomic_set(&osb->s_num_inodes_stolen, 0);
-}
-
-static inline void ocfs2_set_inode_steal_slot(struct ocfs2_super *osb,
-					      s16 slot)
-{
-	spin_lock(&osb->osb_lock);
-	osb->s_inode_steal_slot = slot;
-	spin_unlock(&osb->osb_lock);
-}
-
-static inline s16 ocfs2_get_inode_steal_slot(struct ocfs2_super *osb)
-{
-	s16 slot;
-
-	spin_lock(&osb->osb_lock);
-	slot = osb->s_inode_steal_slot;
-	spin_unlock(&osb->osb_lock);
-
-	return slot;
-}
-
 #define ocfs2_set_bit ext2_set_bit
 #define ocfs2_clear_bit ext2_clear_bit
 #define ocfs2_test_bit ext2_test_bit
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index 7638a38..bb37218 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -254,63 +254,6 @@
 						 * refcount tree */
 
 /*
- * ioctl commands
- */
-#define OCFS2_IOC_GETFLAGS	_IOR('f', 1, long)
-#define OCFS2_IOC_SETFLAGS	_IOW('f', 2, long)
-#define OCFS2_IOC32_GETFLAGS	_IOR('f', 1, int)
-#define OCFS2_IOC32_SETFLAGS	_IOW('f', 2, int)
-
-/*
- * Space reservation / allocation / free ioctls and argument structure
- * are designed to be compatible with XFS.
- *
- * ALLOCSP* and FREESP* are not and will never be supported, but are
- * included here for completeness.
- */
-struct ocfs2_space_resv {
-	__s16		l_type;
-	__s16		l_whence;
-	__s64		l_start;
-	__s64		l_len;		/* len == 0 means until end of file */
-	__s32		l_sysid;
-	__u32		l_pid;
-	__s32		l_pad[4];	/* reserve area			    */
-};
-
-#define OCFS2_IOC_ALLOCSP		_IOW ('X', 10, struct ocfs2_space_resv)
-#define OCFS2_IOC_FREESP		_IOW ('X', 11, struct ocfs2_space_resv)
-#define OCFS2_IOC_RESVSP		_IOW ('X', 40, struct ocfs2_space_resv)
-#define OCFS2_IOC_UNRESVSP	_IOW ('X', 41, struct ocfs2_space_resv)
-#define OCFS2_IOC_ALLOCSP64	_IOW ('X', 36, struct ocfs2_space_resv)
-#define OCFS2_IOC_FREESP64	_IOW ('X', 37, struct ocfs2_space_resv)
-#define OCFS2_IOC_RESVSP64	_IOW ('X', 42, struct ocfs2_space_resv)
-#define OCFS2_IOC_UNRESVSP64	_IOW ('X', 43, struct ocfs2_space_resv)
-
-/* Used to pass group descriptor data when online resize is done */
-struct ocfs2_new_group_input {
-	__u64 group;		/* Group descriptor's blkno. */
-	__u32 clusters;		/* Total number of clusters in this group */
-	__u32 frees;		/* Total free clusters in this group */
-	__u16 chain;		/* Chain for this group */
-	__u16 reserved1;
-	__u32 reserved2;
-};
-
-#define OCFS2_IOC_GROUP_EXTEND	_IOW('o', 1, int)
-#define OCFS2_IOC_GROUP_ADD	_IOW('o', 2,struct ocfs2_new_group_input)
-#define OCFS2_IOC_GROUP_ADD64	_IOW('o', 3,struct ocfs2_new_group_input)
-
-/* Used to pass 2 file names to reflink. */
-struct reflink_arguments {
-	__u64 old_path;
-	__u64 new_path;
-	__u64 preserve;
-};
-#define OCFS2_IOC_REFLINK	_IOW('o', 4, struct reflink_arguments)
-
-
-/*
  * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
  */
 #define OCFS2_JOURNAL_DIRTY_FL	(0x00000001)	/* Journal needs recovery */
diff --git a/fs/ocfs2/ocfs2_ioctl.h b/fs/ocfs2/ocfs2_ioctl.h
new file mode 100644
index 0000000..2d3420a
--- /dev/null
+++ b/fs/ocfs2/ocfs2_ioctl.h
@@ -0,0 +1,79 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ocfs2_ioctl.h
+ *
+ * Defines OCFS2 ioctls.
+ *
+ * Copyright (C) 2010 Oracle.  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 program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 OCFS2_IOCTL_H
+#define OCFS2_IOCTL_H
+
+/*
+ * ioctl commands
+ */
+#define OCFS2_IOC_GETFLAGS	_IOR('f', 1, long)
+#define OCFS2_IOC_SETFLAGS	_IOW('f', 2, long)
+#define OCFS2_IOC32_GETFLAGS	_IOR('f', 1, int)
+#define OCFS2_IOC32_SETFLAGS	_IOW('f', 2, int)
+
+/*
+ * Space reservation / allocation / free ioctls and argument structure
+ * are designed to be compatible with XFS.
+ *
+ * ALLOCSP* and FREESP* are not and will never be supported, but are
+ * included here for completeness.
+ */
+struct ocfs2_space_resv {
+	__s16		l_type;
+	__s16		l_whence;
+	__s64		l_start;
+	__s64		l_len;		/* len == 0 means until end of file */
+	__s32		l_sysid;
+	__u32		l_pid;
+	__s32		l_pad[4];	/* reserve area			    */
+};
+
+#define OCFS2_IOC_ALLOCSP		_IOW ('X', 10, struct ocfs2_space_resv)
+#define OCFS2_IOC_FREESP		_IOW ('X', 11, struct ocfs2_space_resv)
+#define OCFS2_IOC_RESVSP		_IOW ('X', 40, struct ocfs2_space_resv)
+#define OCFS2_IOC_UNRESVSP	_IOW ('X', 41, struct ocfs2_space_resv)
+#define OCFS2_IOC_ALLOCSP64	_IOW ('X', 36, struct ocfs2_space_resv)
+#define OCFS2_IOC_FREESP64	_IOW ('X', 37, struct ocfs2_space_resv)
+#define OCFS2_IOC_RESVSP64	_IOW ('X', 42, struct ocfs2_space_resv)
+#define OCFS2_IOC_UNRESVSP64	_IOW ('X', 43, struct ocfs2_space_resv)
+
+/* Used to pass group descriptor data when online resize is done */
+struct ocfs2_new_group_input {
+	__u64 group;		/* Group descriptor's blkno. */
+	__u32 clusters;		/* Total number of clusters in this group */
+	__u32 frees;		/* Total free clusters in this group */
+	__u16 chain;		/* Chain for this group */
+	__u16 reserved1;
+	__u32 reserved2;
+};
+
+#define OCFS2_IOC_GROUP_EXTEND	_IOW('o', 1, int)
+#define OCFS2_IOC_GROUP_ADD	_IOW('o', 2,struct ocfs2_new_group_input)
+#define OCFS2_IOC_GROUP_ADD64	_IOW('o', 3,struct ocfs2_new_group_input)
+
+/* Used to pass 2 file names to reflink. */
+struct reflink_arguments {
+	__u64 old_path;
+	__u64 new_path;
+	__u64 preserve;
+};
+#define OCFS2_IOC_REFLINK	_IOW('o', 4, struct reflink_arguments)
+
+#endif /* OCFS2_IOCTL_H */
diff --git a/fs/ocfs2/ocfs2_lockingver.h b/fs/ocfs2/ocfs2_lockingver.h
index 82d5eea..2e45c8d 100644
--- a/fs/ocfs2/ocfs2_lockingver.h
+++ b/fs/ocfs2/ocfs2_lockingver.h
@@ -23,6 +23,8 @@
 /*
  * The protocol version for ocfs2 cluster locking.  See dlmglue.c for
  * more details.
+ *
+ * 1.0 - Initial locking version from ocfs2 1.4.
  */
 #define OCFS2_LOCKING_PROTOCOL_MAJOR 1
 #define OCFS2_LOCKING_PROTOCOL_MINOR 0
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index b437dc0..355f41d 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -851,13 +851,6 @@
 }
 
 const struct dquot_operations ocfs2_quota_operations = {
-	.initialize	= dquot_initialize,
-	.drop		= dquot_drop,
-	.alloc_space	= dquot_alloc_space,
-	.alloc_inode	= dquot_alloc_inode,
-	.free_space	= dquot_free_space,
-	.free_inode	= dquot_free_inode,
-	.transfer	= dquot_transfer,
 	.write_dquot	= ocfs2_write_dquot,
 	.acquire_dquot	= ocfs2_acquire_dquot,
 	.release_dquot	= ocfs2_release_dquot,
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index 21f9e71..a6467f3 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -457,7 +457,7 @@
 			break;
 		}
 		dchunk = (struct ocfs2_local_disk_chunk *)hbh->b_data;
-		for_each_bit(bit, rchunk->rc_bitmap, ol_chunk_entries(sb)) {
+		for_each_set_bit(bit, rchunk->rc_bitmap, ol_chunk_entries(sb)) {
 			qbh = NULL;
 			status = ocfs2_read_quota_block(lqinode,
 						ol_dqblk_block(sb, chunk, bit),
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 8ae65c9..9e96921 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -626,7 +626,7 @@
 	rb = (struct ocfs2_refcount_block *)new_bh->b_data;
 	memset(rb, 0, inode->i_sb->s_blocksize);
 	strcpy((void *)rb, OCFS2_REFCOUNT_BLOCK_SIGNATURE);
-	rb->rf_suballoc_slot = cpu_to_le16(osb->slot_num);
+	rb->rf_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
 	rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 	rb->rf_fs_generation = cpu_to_le32(osb->fs_generation);
 	rb->rf_blkno = cpu_to_le64(first_blkno);
@@ -1330,7 +1330,7 @@
 	memcpy(new_bh->b_data, ref_root_bh->b_data, sb->s_blocksize);
 
 	new_rb = (struct ocfs2_refcount_block *)new_bh->b_data;
-	new_rb->rf_suballoc_slot = cpu_to_le16(OCFS2_SB(sb)->slot_num);
+	new_rb->rf_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
 	new_rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 	new_rb->rf_blkno = cpu_to_le64(blkno);
 	new_rb->rf_cpos = cpu_to_le32(0);
@@ -1576,7 +1576,7 @@
 	new_rb = (struct ocfs2_refcount_block *)new_bh->b_data;
 	memset(new_rb, 0, sb->s_blocksize);
 	strcpy((void *)new_rb, OCFS2_REFCOUNT_BLOCK_SIGNATURE);
-	new_rb->rf_suballoc_slot = cpu_to_le16(OCFS2_SB(sb)->slot_num);
+	new_rb->rf_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
 	new_rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 	new_rb->rf_fs_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
 	new_rb->rf_blkno = cpu_to_le64(blkno);
@@ -4390,7 +4390,7 @@
 	}
 
 	mutex_lock(&inode->i_mutex);
-	vfs_dq_init(dir);
+	dquot_initialize(dir);
 	error = ocfs2_reflink(old_dentry, dir, new_dentry, preserve);
 	mutex_unlock(&inode->i_mutex);
 	if (!error)
diff --git a/fs/ocfs2/stack_o2cb.c b/fs/ocfs2/stack_o2cb.c
index 3038c92..7020e12 100644
--- a/fs/ocfs2/stack_o2cb.c
+++ b/fs/ocfs2/stack_o2cb.c
@@ -161,24 +161,23 @@
 
 static void o2dlm_lock_ast_wrapper(void *astarg)
 {
-	BUG_ON(o2cb_stack.sp_proto == NULL);
+	struct ocfs2_dlm_lksb *lksb = astarg;
 
-	o2cb_stack.sp_proto->lp_lock_ast(astarg);
+	lksb->lksb_conn->cc_proto->lp_lock_ast(lksb);
 }
 
 static void o2dlm_blocking_ast_wrapper(void *astarg, int level)
 {
-	BUG_ON(o2cb_stack.sp_proto == NULL);
+	struct ocfs2_dlm_lksb *lksb = astarg;
 
-	o2cb_stack.sp_proto->lp_blocking_ast(astarg, level);
+	lksb->lksb_conn->cc_proto->lp_blocking_ast(lksb, level);
 }
 
 static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status)
 {
+	struct ocfs2_dlm_lksb *lksb = astarg;
 	int error = dlm_status_to_errno(status);
 
-	BUG_ON(o2cb_stack.sp_proto == NULL);
-
 	/*
 	 * In o2dlm, you can get both the lock_ast() for the lock being
 	 * granted and the unlock_ast() for the CANCEL failing.  A
@@ -193,16 +192,15 @@
 	if (status == DLM_CANCELGRANT)
 		return;
 
-	o2cb_stack.sp_proto->lp_unlock_ast(astarg, error);
+	lksb->lksb_conn->cc_proto->lp_unlock_ast(lksb, error);
 }
 
 static int o2cb_dlm_lock(struct ocfs2_cluster_connection *conn,
 			 int mode,
-			 union ocfs2_dlm_lksb *lksb,
+			 struct ocfs2_dlm_lksb *lksb,
 			 u32 flags,
 			 void *name,
-			 unsigned int namelen,
-			 void *astarg)
+			 unsigned int namelen)
 {
 	enum dlm_status status;
 	int o2dlm_mode = mode_to_o2dlm(mode);
@@ -211,28 +209,27 @@
 
 	status = dlmlock(conn->cc_lockspace, o2dlm_mode, &lksb->lksb_o2dlm,
 			 o2dlm_flags, name, namelen,
-			 o2dlm_lock_ast_wrapper, astarg,
+			 o2dlm_lock_ast_wrapper, lksb,
 			 o2dlm_blocking_ast_wrapper);
 	ret = dlm_status_to_errno(status);
 	return ret;
 }
 
 static int o2cb_dlm_unlock(struct ocfs2_cluster_connection *conn,
-			   union ocfs2_dlm_lksb *lksb,
-			   u32 flags,
-			   void *astarg)
+			   struct ocfs2_dlm_lksb *lksb,
+			   u32 flags)
 {
 	enum dlm_status status;
 	int o2dlm_flags = flags_to_o2dlm(flags);
 	int ret;
 
 	status = dlmunlock(conn->cc_lockspace, &lksb->lksb_o2dlm,
-			   o2dlm_flags, o2dlm_unlock_ast_wrapper, astarg);
+			   o2dlm_flags, o2dlm_unlock_ast_wrapper, lksb);
 	ret = dlm_status_to_errno(status);
 	return ret;
 }
 
-static int o2cb_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
+static int o2cb_dlm_lock_status(struct ocfs2_dlm_lksb *lksb)
 {
 	return dlm_status_to_errno(lksb->lksb_o2dlm.status);
 }
@@ -242,17 +239,17 @@
  * contents, it will zero out the LVB.  Thus the caller can always trust
  * the contents.
  */
-static int o2cb_dlm_lvb_valid(union ocfs2_dlm_lksb *lksb)
+static int o2cb_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb)
 {
 	return 1;
 }
 
-static void *o2cb_dlm_lvb(union ocfs2_dlm_lksb *lksb)
+static void *o2cb_dlm_lvb(struct ocfs2_dlm_lksb *lksb)
 {
 	return (void *)(lksb->lksb_o2dlm.lvb);
 }
 
-static void o2cb_dump_lksb(union ocfs2_dlm_lksb *lksb)
+static void o2cb_dump_lksb(struct ocfs2_dlm_lksb *lksb)
 {
 	dlm_print_one_lock(lksb->lksb_o2dlm.lockid);
 }
@@ -280,7 +277,7 @@
 	struct dlm_protocol_version fs_version;
 
 	BUG_ON(conn == NULL);
-	BUG_ON(o2cb_stack.sp_proto == NULL);
+	BUG_ON(conn->cc_proto == NULL);
 
 	/* for now we only have one cluster/node, make sure we see it
 	 * in the heartbeat universe */
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
index da78a2a..5ae8812 100644
--- a/fs/ocfs2/stack_user.c
+++ b/fs/ocfs2/stack_user.c
@@ -25,7 +25,6 @@
 #include <linux/reboot.h>
 #include <asm/uaccess.h>
 
-#include "ocfs2.h"  /* For struct ocfs2_lock_res */
 #include "stackglue.h"
 
 #include <linux/dlm_plock.h>
@@ -63,8 +62,8 @@
  * negotiated by the client.  The client negotiates based on the maximum
  * version advertised in /sys/fs/ocfs2/max_locking_protocol.  The major
  * number from the "SETV" message must match
- * ocfs2_user_plugin.sp_proto->lp_max_version.pv_major, and the minor number
- * must be less than or equal to ...->lp_max_version.pv_minor.
+ * ocfs2_user_plugin.sp_max_proto.pv_major, and the minor number
+ * must be less than or equal to ...sp_max_version.pv_minor.
  *
  * Once this information has been set, mounts will be allowed.  From this
  * point on, the "DOWN" message can be sent for node down notification.
@@ -401,7 +400,7 @@
 	char *ptr = NULL;
 	struct ocfs2_control_private *p = file->private_data;
 	struct ocfs2_protocol_version *max =
-		&ocfs2_user_plugin.sp_proto->lp_max_version;
+		&ocfs2_user_plugin.sp_max_proto;
 
 	if (ocfs2_control_get_handshake_state(file) !=
 	    OCFS2_CONTROL_HANDSHAKE_PROTOCOL)
@@ -664,18 +663,10 @@
 		       -rc);
 }
 
-static struct dlm_lksb *fsdlm_astarg_to_lksb(void *astarg)
-{
-	struct ocfs2_lock_res *res = astarg;
-	return &res->l_lksb.lksb_fsdlm;
-}
-
 static void fsdlm_lock_ast_wrapper(void *astarg)
 {
-	struct dlm_lksb *lksb = fsdlm_astarg_to_lksb(astarg);
-	int status = lksb->sb_status;
-
-	BUG_ON(ocfs2_user_plugin.sp_proto == NULL);
+	struct ocfs2_dlm_lksb *lksb = astarg;
+	int status = lksb->lksb_fsdlm.sb_status;
 
 	/*
 	 * For now we're punting on the issue of other non-standard errors
@@ -688,25 +679,24 @@
 	 */
 
 	if (status == -DLM_EUNLOCK || status == -DLM_ECANCEL)
-		ocfs2_user_plugin.sp_proto->lp_unlock_ast(astarg, 0);
+		lksb->lksb_conn->cc_proto->lp_unlock_ast(lksb, 0);
 	else
-		ocfs2_user_plugin.sp_proto->lp_lock_ast(astarg);
+		lksb->lksb_conn->cc_proto->lp_lock_ast(lksb);
 }
 
 static void fsdlm_blocking_ast_wrapper(void *astarg, int level)
 {
-	BUG_ON(ocfs2_user_plugin.sp_proto == NULL);
+	struct ocfs2_dlm_lksb *lksb = astarg;
 
-	ocfs2_user_plugin.sp_proto->lp_blocking_ast(astarg, level);
+	lksb->lksb_conn->cc_proto->lp_blocking_ast(lksb, level);
 }
 
 static int user_dlm_lock(struct ocfs2_cluster_connection *conn,
 			 int mode,
-			 union ocfs2_dlm_lksb *lksb,
+			 struct ocfs2_dlm_lksb *lksb,
 			 u32 flags,
 			 void *name,
-			 unsigned int namelen,
-			 void *astarg)
+			 unsigned int namelen)
 {
 	int ret;
 
@@ -716,36 +706,35 @@
 
 	ret = dlm_lock(conn->cc_lockspace, mode, &lksb->lksb_fsdlm,
 		       flags|DLM_LKF_NODLCKWT, name, namelen, 0,
-		       fsdlm_lock_ast_wrapper, astarg,
+		       fsdlm_lock_ast_wrapper, lksb,
 		       fsdlm_blocking_ast_wrapper);
 	return ret;
 }
 
 static int user_dlm_unlock(struct ocfs2_cluster_connection *conn,
-			   union ocfs2_dlm_lksb *lksb,
-			   u32 flags,
-			   void *astarg)
+			   struct ocfs2_dlm_lksb *lksb,
+			   u32 flags)
 {
 	int ret;
 
 	ret = dlm_unlock(conn->cc_lockspace, lksb->lksb_fsdlm.sb_lkid,
-			 flags, &lksb->lksb_fsdlm, astarg);
+			 flags, &lksb->lksb_fsdlm, lksb);
 	return ret;
 }
 
-static int user_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
+static int user_dlm_lock_status(struct ocfs2_dlm_lksb *lksb)
 {
 	return lksb->lksb_fsdlm.sb_status;
 }
 
-static int user_dlm_lvb_valid(union ocfs2_dlm_lksb *lksb)
+static int user_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb)
 {
 	int invalid = lksb->lksb_fsdlm.sb_flags & DLM_SBF_VALNOTVALID;
 
 	return !invalid;
 }
 
-static void *user_dlm_lvb(union ocfs2_dlm_lksb *lksb)
+static void *user_dlm_lvb(struct ocfs2_dlm_lksb *lksb)
 {
 	if (!lksb->lksb_fsdlm.sb_lvbptr)
 		lksb->lksb_fsdlm.sb_lvbptr = (char *)lksb +
@@ -753,7 +742,7 @@
 	return (void *)(lksb->lksb_fsdlm.sb_lvbptr);
 }
 
-static void user_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
+static void user_dlm_dump_lksb(struct ocfs2_dlm_lksb *lksb)
 {
 }
 
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index f3df0ba..39abf89 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -36,7 +36,7 @@
 #define OCFS2_STACK_PLUGIN_USER		"user"
 #define OCFS2_MAX_HB_CTL_PATH		256
 
-static struct ocfs2_locking_protocol *lproto;
+static struct ocfs2_protocol_version locking_max_version;
 static DEFINE_SPINLOCK(ocfs2_stack_lock);
 static LIST_HEAD(ocfs2_stack_list);
 static char cluster_stack_name[OCFS2_STACK_LABEL_LEN + 1];
@@ -176,7 +176,7 @@
 	spin_lock(&ocfs2_stack_lock);
 	if (!ocfs2_stack_lookup(plugin->sp_name)) {
 		plugin->sp_count = 0;
-		plugin->sp_proto = lproto;
+		plugin->sp_max_proto = locking_max_version;
 		list_add(&plugin->sp_list, &ocfs2_stack_list);
 		printk(KERN_INFO "ocfs2: Registered cluster interface %s\n",
 		       plugin->sp_name);
@@ -213,77 +213,76 @@
 }
 EXPORT_SYMBOL_GPL(ocfs2_stack_glue_unregister);
 
-void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto)
+void ocfs2_stack_glue_set_max_proto_version(struct ocfs2_protocol_version *max_proto)
 {
 	struct ocfs2_stack_plugin *p;
 
-	BUG_ON(proto == NULL);
-
 	spin_lock(&ocfs2_stack_lock);
-	BUG_ON(active_stack != NULL);
+	if (memcmp(max_proto, &locking_max_version,
+		   sizeof(struct ocfs2_protocol_version))) {
+		BUG_ON(locking_max_version.pv_major != 0);
 
-	lproto = proto;
-	list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
-		p->sp_proto = lproto;
+		locking_max_version = *max_proto;
+		list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
+			p->sp_max_proto = locking_max_version;
+		}
 	}
-
 	spin_unlock(&ocfs2_stack_lock);
 }
-EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_locking_protocol);
+EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_max_proto_version);
 
 
 /*
- * The ocfs2_dlm_lock() and ocfs2_dlm_unlock() functions take
- * "struct ocfs2_lock_res *astarg" instead of "void *astarg" because the
- * underlying stack plugins need to pilfer the lksb off of the lock_res.
- * If some other structure needs to be passed as an astarg, the plugins
- * will need to be given a different avenue to the lksb.
+ * The ocfs2_dlm_lock() and ocfs2_dlm_unlock() functions take no argument
+ * for the ast and bast functions.  They will pass the lksb to the ast
+ * and bast.  The caller can wrap the lksb with their own structure to
+ * get more information.
  */
 int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
 		   int mode,
-		   union ocfs2_dlm_lksb *lksb,
+		   struct ocfs2_dlm_lksb *lksb,
 		   u32 flags,
 		   void *name,
-		   unsigned int namelen,
-		   struct ocfs2_lock_res *astarg)
+		   unsigned int namelen)
 {
-	BUG_ON(lproto == NULL);
-
+	if (!lksb->lksb_conn)
+		lksb->lksb_conn = conn;
+	else
+		BUG_ON(lksb->lksb_conn != conn);
 	return active_stack->sp_ops->dlm_lock(conn, mode, lksb, flags,
-					      name, namelen, astarg);
+					      name, namelen);
 }
 EXPORT_SYMBOL_GPL(ocfs2_dlm_lock);
 
 int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
-		     union ocfs2_dlm_lksb *lksb,
-		     u32 flags,
-		     struct ocfs2_lock_res *astarg)
+		     struct ocfs2_dlm_lksb *lksb,
+		     u32 flags)
 {
-	BUG_ON(lproto == NULL);
+	BUG_ON(lksb->lksb_conn == NULL);
 
-	return active_stack->sp_ops->dlm_unlock(conn, lksb, flags, astarg);
+	return active_stack->sp_ops->dlm_unlock(conn, lksb, flags);
 }
 EXPORT_SYMBOL_GPL(ocfs2_dlm_unlock);
 
-int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
+int ocfs2_dlm_lock_status(struct ocfs2_dlm_lksb *lksb)
 {
 	return active_stack->sp_ops->lock_status(lksb);
 }
 EXPORT_SYMBOL_GPL(ocfs2_dlm_lock_status);
 
-int ocfs2_dlm_lvb_valid(union ocfs2_dlm_lksb *lksb)
+int ocfs2_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb)
 {
 	return active_stack->sp_ops->lvb_valid(lksb);
 }
 EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb_valid);
 
-void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb)
+void *ocfs2_dlm_lvb(struct ocfs2_dlm_lksb *lksb)
 {
 	return active_stack->sp_ops->lock_lvb(lksb);
 }
 EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb);
 
-void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
+void ocfs2_dlm_dump_lksb(struct ocfs2_dlm_lksb *lksb)
 {
 	active_stack->sp_ops->dump_lksb(lksb);
 }
@@ -312,6 +311,7 @@
 int ocfs2_cluster_connect(const char *stack_name,
 			  const char *group,
 			  int grouplen,
+			  struct ocfs2_locking_protocol *lproto,
 			  void (*recovery_handler)(int node_num,
 						   void *recovery_data),
 			  void *recovery_data,
@@ -329,6 +329,12 @@
 		goto out;
 	}
 
+	if (memcmp(&lproto->lp_max_version, &locking_max_version,
+		   sizeof(struct ocfs2_protocol_version))) {
+		rc = -EINVAL;
+		goto out;
+	}
+
 	new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection),
 			   GFP_KERNEL);
 	if (!new_conn) {
@@ -341,6 +347,7 @@
 	new_conn->cc_recovery_handler = recovery_handler;
 	new_conn->cc_recovery_data = recovery_data;
 
+	new_conn->cc_proto = lproto;
 	/* Start the new connection at our maximum compatibility level */
 	new_conn->cc_version = lproto->lp_max_version;
 
@@ -366,6 +373,24 @@
 }
 EXPORT_SYMBOL_GPL(ocfs2_cluster_connect);
 
+/* The caller will ensure all nodes have the same cluster stack */
+int ocfs2_cluster_connect_agnostic(const char *group,
+				   int grouplen,
+				   struct ocfs2_locking_protocol *lproto,
+				   void (*recovery_handler)(int node_num,
+							    void *recovery_data),
+				   void *recovery_data,
+				   struct ocfs2_cluster_connection **conn)
+{
+	char *stack_name = NULL;
+
+	if (cluster_stack_name[0])
+		stack_name = cluster_stack_name;
+	return ocfs2_cluster_connect(stack_name, group, grouplen, lproto,
+				     recovery_handler, recovery_data, conn);
+}
+EXPORT_SYMBOL_GPL(ocfs2_cluster_connect_agnostic);
+
 /* If hangup_pending is 0, the stack driver will be dropped */
 int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
 			     int hangup_pending)
@@ -453,10 +478,10 @@
 	ssize_t ret = 0;
 
 	spin_lock(&ocfs2_stack_lock);
-	if (lproto)
+	if (locking_max_version.pv_major)
 		ret = snprintf(buf, PAGE_SIZE, "%u.%u\n",
-			       lproto->lp_max_version.pv_major,
-			       lproto->lp_max_version.pv_minor);
+			       locking_max_version.pv_major,
+			       locking_max_version.pv_minor);
 	spin_unlock(&ocfs2_stack_lock);
 
 	return ret;
@@ -685,7 +710,10 @@
 
 static void __exit ocfs2_stack_glue_exit(void)
 {
-	lproto = NULL;
+	memset(&locking_max_version, 0,
+	       sizeof(struct ocfs2_protocol_version));
+	locking_max_version.pv_major = 0;
+	locking_max_version.pv_minor = 0;
 	ocfs2_sysfs_exit();
 	if (ocfs2_table_header)
 		unregister_sysctl_table(ocfs2_table_header);
diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h
index 03a44d6..8ce7398 100644
--- a/fs/ocfs2/stackglue.h
+++ b/fs/ocfs2/stackglue.h
@@ -56,17 +56,6 @@
 };
 
 /*
- * The ocfs2_locking_protocol defines the handlers called on ocfs2's behalf.
- */
-struct ocfs2_locking_protocol {
-	struct ocfs2_protocol_version lp_max_version;
-	void (*lp_lock_ast)(void *astarg);
-	void (*lp_blocking_ast)(void *astarg, int level);
-	void (*lp_unlock_ast)(void *astarg, int error);
-};
-
-
-/*
  * The dlm_lockstatus struct includes lvb space, but the dlm_lksb struct only
  * has a pointer to separately allocated lvb space.  This struct exists only to
  * include in the lksb union to make space for a combined dlm_lksb and lvb.
@@ -81,13 +70,28 @@
  * size of the union is known.  Lock status structures are embedded in
  * ocfs2 inodes.
  */
-union ocfs2_dlm_lksb {
-	struct dlm_lockstatus lksb_o2dlm;
-	struct dlm_lksb lksb_fsdlm;
-	struct fsdlm_lksb_plus_lvb padding;
+struct ocfs2_cluster_connection;
+struct ocfs2_dlm_lksb {
+	 union {
+		 struct dlm_lockstatus lksb_o2dlm;
+		 struct dlm_lksb lksb_fsdlm;
+		 struct fsdlm_lksb_plus_lvb padding;
+	 };
+	 struct ocfs2_cluster_connection *lksb_conn;
 };
 
 /*
+ * The ocfs2_locking_protocol defines the handlers called on ocfs2's behalf.
+ */
+struct ocfs2_locking_protocol {
+	struct ocfs2_protocol_version lp_max_version;
+	void (*lp_lock_ast)(struct ocfs2_dlm_lksb *lksb);
+	void (*lp_blocking_ast)(struct ocfs2_dlm_lksb *lksb, int level);
+	void (*lp_unlock_ast)(struct ocfs2_dlm_lksb *lksb, int error);
+};
+
+
+/*
  * A cluster connection.  Mostly opaque to ocfs2, the connection holds
  * state for the underlying stack.  ocfs2 does use cc_version to determine
  * locking compatibility.
@@ -96,6 +100,7 @@
 	char cc_name[GROUP_NAME_MAX];
 	int cc_namelen;
 	struct ocfs2_protocol_version cc_version;
+	struct ocfs2_locking_protocol *cc_proto;
 	void (*cc_recovery_handler)(int node_num, void *recovery_data);
 	void *cc_recovery_data;
 	void *cc_lockspace;
@@ -155,27 +160,29 @@
 	 *
 	 * ast and bast functions are not part of the call because the
 	 * stack will likely want to wrap ast and bast calls before passing
-	 * them to stack->sp_proto.
+	 * them to stack->sp_proto.  There is no astarg.  The lksb will
+	 * be passed back to the ast and bast functions.  The caller can
+	 * use this to find their object.
 	 */
 	int (*dlm_lock)(struct ocfs2_cluster_connection *conn,
 			int mode,
-			union ocfs2_dlm_lksb *lksb,
+			struct ocfs2_dlm_lksb *lksb,
 			u32 flags,
 			void *name,
-			unsigned int namelen,
-			void *astarg);
+			unsigned int namelen);
 
 	/*
 	 * Call the underlying dlm unlock function.  The ->dlm_unlock()
 	 * function should convert the flags as appropriate.
 	 *
 	 * The unlock ast is not passed, as the stack will want to wrap
-	 * it before calling stack->sp_proto->lp_unlock_ast().
+	 * it before calling stack->sp_proto->lp_unlock_ast().  There is
+	 * no astarg.  The lksb will be passed back to the unlock ast
+	 * function.  The caller can use this to find their object.
 	 */
 	int (*dlm_unlock)(struct ocfs2_cluster_connection *conn,
-			  union ocfs2_dlm_lksb *lksb,
-			  u32 flags,
-			  void *astarg);
+			  struct ocfs2_dlm_lksb *lksb,
+			  u32 flags);
 
 	/*
 	 * Return the status of the current lock status block.  The fs
@@ -183,17 +190,17 @@
 	 * callback pulls out the stack-specific lksb, converts the status
 	 * to a proper errno, and returns it.
 	 */
-	int (*lock_status)(union ocfs2_dlm_lksb *lksb);
+	int (*lock_status)(struct ocfs2_dlm_lksb *lksb);
 
 	/*
 	 * Return non-zero if the LVB is valid.
 	 */
-	int (*lvb_valid)(union ocfs2_dlm_lksb *lksb);
+	int (*lvb_valid)(struct ocfs2_dlm_lksb *lksb);
 
 	/*
 	 * Pull the lvb pointer off of the stack-specific lksb.
 	 */
-	void *(*lock_lvb)(union ocfs2_dlm_lksb *lksb);
+	void *(*lock_lvb)(struct ocfs2_dlm_lksb *lksb);
 
 	/*
 	 * Cluster-aware posix locks
@@ -210,7 +217,7 @@
 	 * This is an optoinal debugging hook.  If provided, the
 	 * stack can dump debugging information about this lock.
 	 */
-	void (*dump_lksb)(union ocfs2_dlm_lksb *lksb);
+	void (*dump_lksb)(struct ocfs2_dlm_lksb *lksb);
 };
 
 /*
@@ -226,7 +233,7 @@
 	/* These are managed by the stackglue code. */
 	struct list_head sp_list;
 	unsigned int sp_count;
-	struct ocfs2_locking_protocol *sp_proto;
+	struct ocfs2_protocol_version sp_max_proto;
 };
 
 
@@ -234,10 +241,22 @@
 int ocfs2_cluster_connect(const char *stack_name,
 			  const char *group,
 			  int grouplen,
+			  struct ocfs2_locking_protocol *lproto,
 			  void (*recovery_handler)(int node_num,
 						   void *recovery_data),
 			  void *recovery_data,
 			  struct ocfs2_cluster_connection **conn);
+/*
+ * Used by callers that don't store their stack name.  They must ensure
+ * all nodes have the same stack.
+ */
+int ocfs2_cluster_connect_agnostic(const char *group,
+				   int grouplen,
+				   struct ocfs2_locking_protocol *lproto,
+				   void (*recovery_handler)(int node_num,
+							    void *recovery_data),
+				   void *recovery_data,
+				   struct ocfs2_cluster_connection **conn);
 int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
 			     int hangup_pending);
 void ocfs2_cluster_hangup(const char *group, int grouplen);
@@ -246,26 +265,24 @@
 struct ocfs2_lock_res;
 int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
 		   int mode,
-		   union ocfs2_dlm_lksb *lksb,
+		   struct ocfs2_dlm_lksb *lksb,
 		   u32 flags,
 		   void *name,
-		   unsigned int namelen,
-		   struct ocfs2_lock_res *astarg);
+		   unsigned int namelen);
 int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
-		     union ocfs2_dlm_lksb *lksb,
-		     u32 flags,
-		     struct ocfs2_lock_res *astarg);
+		     struct ocfs2_dlm_lksb *lksb,
+		     u32 flags);
 
-int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb);
-int ocfs2_dlm_lvb_valid(union ocfs2_dlm_lksb *lksb);
-void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb);
-void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb);
+int ocfs2_dlm_lock_status(struct ocfs2_dlm_lksb *lksb);
+int ocfs2_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb);
+void *ocfs2_dlm_lvb(struct ocfs2_dlm_lksb *lksb);
+void ocfs2_dlm_dump_lksb(struct ocfs2_dlm_lksb *lksb);
 
 int ocfs2_stack_supports_plocks(void);
 int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino,
 		struct file *file, int cmd, struct file_lock *fl);
 
-void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto);
+void ocfs2_stack_glue_set_max_proto_version(struct ocfs2_protocol_version *max_proto);
 
 
 /* Used by stack plugins */
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index c30b644..c3c60bc 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -51,7 +51,7 @@
 #define ALLOC_NEW_GROUP			0x1
 #define ALLOC_GROUPS_FROM_GLOBAL	0x2
 
-#define OCFS2_MAX_INODES_TO_STEAL	1024
+#define OCFS2_MAX_TO_STEAL		1024
 
 static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg);
 static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe);
@@ -637,12 +637,113 @@
 	return status;
 }
 
+static void ocfs2_init_inode_steal_slot(struct ocfs2_super *osb)
+{
+	spin_lock(&osb->osb_lock);
+	osb->s_inode_steal_slot = OCFS2_INVALID_SLOT;
+	spin_unlock(&osb->osb_lock);
+	atomic_set(&osb->s_num_inodes_stolen, 0);
+}
+
+static void ocfs2_init_meta_steal_slot(struct ocfs2_super *osb)
+{
+	spin_lock(&osb->osb_lock);
+	osb->s_meta_steal_slot = OCFS2_INVALID_SLOT;
+	spin_unlock(&osb->osb_lock);
+	atomic_set(&osb->s_num_meta_stolen, 0);
+}
+
+void ocfs2_init_steal_slots(struct ocfs2_super *osb)
+{
+	ocfs2_init_inode_steal_slot(osb);
+	ocfs2_init_meta_steal_slot(osb);
+}
+
+static void __ocfs2_set_steal_slot(struct ocfs2_super *osb, int slot, int type)
+{
+	spin_lock(&osb->osb_lock);
+	if (type == INODE_ALLOC_SYSTEM_INODE)
+		osb->s_inode_steal_slot = slot;
+	else if (type == EXTENT_ALLOC_SYSTEM_INODE)
+		osb->s_meta_steal_slot = slot;
+	spin_unlock(&osb->osb_lock);
+}
+
+static int __ocfs2_get_steal_slot(struct ocfs2_super *osb, int type)
+{
+	int slot = OCFS2_INVALID_SLOT;
+
+	spin_lock(&osb->osb_lock);
+	if (type == INODE_ALLOC_SYSTEM_INODE)
+		slot = osb->s_inode_steal_slot;
+	else if (type == EXTENT_ALLOC_SYSTEM_INODE)
+		slot = osb->s_meta_steal_slot;
+	spin_unlock(&osb->osb_lock);
+
+	return slot;
+}
+
+static int ocfs2_get_inode_steal_slot(struct ocfs2_super *osb)
+{
+	return __ocfs2_get_steal_slot(osb, INODE_ALLOC_SYSTEM_INODE);
+}
+
+static int ocfs2_get_meta_steal_slot(struct ocfs2_super *osb)
+{
+	return __ocfs2_get_steal_slot(osb, EXTENT_ALLOC_SYSTEM_INODE);
+}
+
+static int ocfs2_steal_resource(struct ocfs2_super *osb,
+				struct ocfs2_alloc_context *ac,
+				int type)
+{
+	int i, status = -ENOSPC;
+	int slot = __ocfs2_get_steal_slot(osb, type);
+
+	/* Start to steal resource from the first slot after ours. */
+	if (slot == OCFS2_INVALID_SLOT)
+		slot = osb->slot_num + 1;
+
+	for (i = 0; i < osb->max_slots; i++, slot++) {
+		if (slot == osb->max_slots)
+			slot = 0;
+
+		if (slot == osb->slot_num)
+			continue;
+
+		status = ocfs2_reserve_suballoc_bits(osb, ac,
+						     type,
+						     (u32)slot, NULL,
+						     NOT_ALLOC_NEW_GROUP);
+		if (status >= 0) {
+			__ocfs2_set_steal_slot(osb, slot, type);
+			break;
+		}
+
+		ocfs2_free_ac_resource(ac);
+	}
+
+	return status;
+}
+
+static int ocfs2_steal_inode(struct ocfs2_super *osb,
+			     struct ocfs2_alloc_context *ac)
+{
+	return ocfs2_steal_resource(osb, ac, INODE_ALLOC_SYSTEM_INODE);
+}
+
+static int ocfs2_steal_meta(struct ocfs2_super *osb,
+			    struct ocfs2_alloc_context *ac)
+{
+	return ocfs2_steal_resource(osb, ac, EXTENT_ALLOC_SYSTEM_INODE);
+}
+
 int ocfs2_reserve_new_metadata_blocks(struct ocfs2_super *osb,
 				      int blocks,
 				      struct ocfs2_alloc_context **ac)
 {
 	int status;
-	u32 slot;
+	int slot = ocfs2_get_meta_steal_slot(osb);
 
 	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
 	if (!(*ac)) {
@@ -653,12 +754,34 @@
 
 	(*ac)->ac_bits_wanted = blocks;
 	(*ac)->ac_which = OCFS2_AC_USE_META;
-	slot = osb->slot_num;
 	(*ac)->ac_group_search = ocfs2_block_group_search;
 
+	if (slot != OCFS2_INVALID_SLOT &&
+		atomic_read(&osb->s_num_meta_stolen) < OCFS2_MAX_TO_STEAL)
+		goto extent_steal;
+
+	atomic_set(&osb->s_num_meta_stolen, 0);
 	status = ocfs2_reserve_suballoc_bits(osb, (*ac),
 					     EXTENT_ALLOC_SYSTEM_INODE,
-					     slot, NULL, ALLOC_NEW_GROUP);
+					     (u32)osb->slot_num, NULL,
+					     ALLOC_NEW_GROUP);
+
+
+	if (status >= 0) {
+		status = 0;
+		if (slot != OCFS2_INVALID_SLOT)
+			ocfs2_init_meta_steal_slot(osb);
+		goto bail;
+	} else if (status < 0 && status != -ENOSPC) {
+		mlog_errno(status);
+		goto bail;
+	}
+
+	ocfs2_free_ac_resource(*ac);
+
+extent_steal:
+	status = ocfs2_steal_meta(osb, *ac);
+	atomic_inc(&osb->s_num_meta_stolen);
 	if (status < 0) {
 		if (status != -ENOSPC)
 			mlog_errno(status);
@@ -685,43 +808,11 @@
 					ac);
 }
 
-static int ocfs2_steal_inode_from_other_nodes(struct ocfs2_super *osb,
-					      struct ocfs2_alloc_context *ac)
-{
-	int i, status = -ENOSPC;
-	s16 slot = ocfs2_get_inode_steal_slot(osb);
-
-	/* Start to steal inodes from the first slot after ours. */
-	if (slot == OCFS2_INVALID_SLOT)
-		slot = osb->slot_num + 1;
-
-	for (i = 0; i < osb->max_slots; i++, slot++) {
-		if (slot == osb->max_slots)
-			slot = 0;
-
-		if (slot == osb->slot_num)
-			continue;
-
-		status = ocfs2_reserve_suballoc_bits(osb, ac,
-						     INODE_ALLOC_SYSTEM_INODE,
-						     slot, NULL,
-						     NOT_ALLOC_NEW_GROUP);
-		if (status >= 0) {
-			ocfs2_set_inode_steal_slot(osb, slot);
-			break;
-		}
-
-		ocfs2_free_ac_resource(ac);
-	}
-
-	return status;
-}
-
 int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
 			    struct ocfs2_alloc_context **ac)
 {
 	int status;
-	s16 slot = ocfs2_get_inode_steal_slot(osb);
+	int slot = ocfs2_get_inode_steal_slot(osb);
 	u64 alloc_group;
 
 	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
@@ -754,14 +845,14 @@
 	 * need to check our slots to see whether there is some space for us.
 	 */
 	if (slot != OCFS2_INVALID_SLOT &&
-	    atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_INODES_TO_STEAL)
+	    atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_TO_STEAL)
 		goto inode_steal;
 
 	atomic_set(&osb->s_num_inodes_stolen, 0);
 	alloc_group = osb->osb_inode_alloc_group;
 	status = ocfs2_reserve_suballoc_bits(osb, *ac,
 					     INODE_ALLOC_SYSTEM_INODE,
-					     osb->slot_num,
+					     (u32)osb->slot_num,
 					     &alloc_group,
 					     ALLOC_NEW_GROUP |
 					     ALLOC_GROUPS_FROM_GLOBAL);
@@ -789,7 +880,7 @@
 	ocfs2_free_ac_resource(*ac);
 
 inode_steal:
-	status = ocfs2_steal_inode_from_other_nodes(osb, *ac);
+	status = ocfs2_steal_inode(osb, *ac);
 	atomic_inc(&osb->s_num_inodes_stolen);
 	if (status < 0) {
 		if (status != -ENOSPC)
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
index 8c9a78a..fa60723 100644
--- a/fs/ocfs2/suballoc.h
+++ b/fs/ocfs2/suballoc.h
@@ -56,6 +56,7 @@
 				 is the same as ~0 - unlimited */
 };
 
+void ocfs2_init_steal_slots(struct ocfs2_super *osb);
 void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac);
 static inline int ocfs2_alloc_context_bits_left(struct ocfs2_alloc_context *ac)
 {
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 755cd49..dee0319 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -69,6 +69,7 @@
 #include "xattr.h"
 #include "quota.h"
 #include "refcounttree.h"
+#include "suballoc.h"
 
 #include "buffer_head_io.h"
 
@@ -301,9 +302,12 @@
 
 	spin_lock(&osb->osb_lock);
 	out += snprintf(buf + out, len - out,
-			"%10s => Slot: %d  NumStolen: %d\n", "Steal",
+			"%10s => InodeSlot: %d  StolenInodes: %d, "
+			"MetaSlot: %d  StolenMeta: %d\n", "Steal",
 			osb->s_inode_steal_slot,
-			atomic_read(&osb->s_num_inodes_stolen));
+			atomic_read(&osb->s_num_inodes_stolen),
+			osb->s_meta_steal_slot,
+			atomic_read(&osb->s_num_meta_stolen));
 	spin_unlock(&osb->osb_lock);
 
 	out += snprintf(buf + out, len - out, "OrphanScan => ");
@@ -1997,7 +2001,7 @@
 	osb->blocked_lock_count = 0;
 	spin_lock_init(&osb->osb_lock);
 	spin_lock_init(&osb->osb_xattr_lock);
-	ocfs2_init_inode_steal_slot(osb);
+	ocfs2_init_steal_slots(osb);
 
 	atomic_set(&osb->alloc_stats.moves, 0);
 	atomic_set(&osb->alloc_stats.local_data, 0);
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 8fc6fb0..d1b0d38 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -116,10 +116,11 @@
 };
 
 struct ocfs2_xattr_info {
-	int name_index;
-	const char *name;
-	const void *value;
-	size_t value_len;
+	int		xi_name_index;
+	const char	*xi_name;
+	int		xi_name_len;
+	const void	*xi_value;
+	size_t		xi_value_len;
 };
 
 struct ocfs2_xattr_search {
@@ -137,6 +138,115 @@
 	int not_found;
 };
 
+/* Operations on struct ocfs2_xa_entry */
+struct ocfs2_xa_loc;
+struct ocfs2_xa_loc_operations {
+	/*
+	 * Journal functions
+	 */
+	int (*xlo_journal_access)(handle_t *handle, struct ocfs2_xa_loc *loc,
+				  int type);
+	void (*xlo_journal_dirty)(handle_t *handle, struct ocfs2_xa_loc *loc);
+
+	/*
+	 * Return a pointer to the appropriate buffer in loc->xl_storage
+	 * at the given offset from loc->xl_header.
+	 */
+	void *(*xlo_offset_pointer)(struct ocfs2_xa_loc *loc, int offset);
+
+	/* Can we reuse the existing entry for the new value? */
+	int (*xlo_can_reuse)(struct ocfs2_xa_loc *loc,
+			     struct ocfs2_xattr_info *xi);
+
+	/* How much space is needed for the new value? */
+	int (*xlo_check_space)(struct ocfs2_xa_loc *loc,
+			       struct ocfs2_xattr_info *xi);
+
+	/*
+	 * Return the offset of the first name+value pair.  This is
+	 * the start of our downward-filling free space.
+	 */
+	int (*xlo_get_free_start)(struct ocfs2_xa_loc *loc);
+
+	/*
+	 * Remove the name+value at this location.  Do whatever is
+	 * appropriate with the remaining name+value pairs.
+	 */
+	void (*xlo_wipe_namevalue)(struct ocfs2_xa_loc *loc);
+
+	/* Fill xl_entry with a new entry */
+	void (*xlo_add_entry)(struct ocfs2_xa_loc *loc, u32 name_hash);
+
+	/* Add name+value storage to an entry */
+	void (*xlo_add_namevalue)(struct ocfs2_xa_loc *loc, int size);
+
+	/*
+	 * Initialize the value buf's access and bh fields for this entry.
+	 * ocfs2_xa_fill_value_buf() will handle the xv pointer.
+	 */
+	void (*xlo_fill_value_buf)(struct ocfs2_xa_loc *loc,
+				   struct ocfs2_xattr_value_buf *vb);
+};
+
+/*
+ * Describes an xattr entry location.  This is a memory structure
+ * tracking the on-disk structure.
+ */
+struct ocfs2_xa_loc {
+	/* This xattr belongs to this inode */
+	struct inode *xl_inode;
+
+	/* The ocfs2_xattr_header inside the on-disk storage. Not NULL. */
+	struct ocfs2_xattr_header *xl_header;
+
+	/* Bytes from xl_header to the end of the storage */
+	int xl_size;
+
+	/*
+	 * The ocfs2_xattr_entry this location describes.  If this is
+	 * NULL, this location describes the on-disk structure where it
+	 * would have been.
+	 */
+	struct ocfs2_xattr_entry *xl_entry;
+
+	/*
+	 * Internal housekeeping
+	 */
+
+	/* Buffer(s) containing this entry */
+	void *xl_storage;
+
+	/* Operations on the storage backing this location */
+	const struct ocfs2_xa_loc_operations *xl_ops;
+};
+
+/*
+ * Convenience functions to calculate how much space is needed for a
+ * given name+value pair
+ */
+static int namevalue_size(int name_len, uint64_t value_len)
+{
+	if (value_len > OCFS2_XATTR_INLINE_SIZE)
+		return OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
+	else
+		return OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(value_len);
+}
+
+static int namevalue_size_xi(struct ocfs2_xattr_info *xi)
+{
+	return namevalue_size(xi->xi_name_len, xi->xi_value_len);
+}
+
+static int namevalue_size_xe(struct ocfs2_xattr_entry *xe)
+{
+	u64 value_len = le64_to_cpu(xe->xe_value_size);
+
+	BUG_ON((value_len > OCFS2_XATTR_INLINE_SIZE) &&
+	       ocfs2_xattr_is_local(xe));
+	return namevalue_size(xe->xe_name_len, value_len);
+}
+
+
 static int ocfs2_xattr_bucket_get_name_value(struct super_block *sb,
 					     struct ocfs2_xattr_header *xh,
 					     int index,
@@ -212,14 +322,6 @@
 	return OCFS2_XATTR_BUCKET_SIZE / (1 << sb->s_blocksize_bits);
 }
 
-static inline u16 ocfs2_xattr_max_xe_in_bucket(struct super_block *sb)
-{
-	u16 len = sb->s_blocksize -
-		 offsetof(struct ocfs2_xattr_header, xh_entries);
-
-	return len / sizeof(struct ocfs2_xattr_entry);
-}
-
 #define bucket_blkno(_b) ((_b)->bu_bhs[0]->b_blocknr)
 #define bucket_block(_b, _n) ((_b)->bu_bhs[(_n)]->b_data)
 #define bucket_xh(_b) ((struct ocfs2_xattr_header *)bucket_block((_b), 0))
@@ -463,35 +565,22 @@
 	return hash;
 }
 
-/*
- * ocfs2_xattr_hash_entry()
- *
- * Compute the hash of an extended attribute.
- */
-static void ocfs2_xattr_hash_entry(struct inode *inode,
-				   struct ocfs2_xattr_header *header,
-				   struct ocfs2_xattr_entry *entry)
-{
-	u32 hash = 0;
-	char *name = (char *)header + le16_to_cpu(entry->xe_name_offset);
-
-	hash = ocfs2_xattr_name_hash(inode, name, entry->xe_name_len);
-	entry->xe_name_hash = cpu_to_le32(hash);
-
-	return;
-}
-
 static int ocfs2_xattr_entry_real_size(int name_len, size_t value_len)
 {
-	int size = 0;
+	return namevalue_size(name_len, value_len) +
+		sizeof(struct ocfs2_xattr_entry);
+}
 
-	if (value_len <= OCFS2_XATTR_INLINE_SIZE)
-		size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(value_len);
-	else
-		size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
-	size += sizeof(struct ocfs2_xattr_entry);
+static int ocfs2_xi_entry_usage(struct ocfs2_xattr_info *xi)
+{
+	return namevalue_size_xi(xi) +
+		sizeof(struct ocfs2_xattr_entry);
+}
 
-	return size;
+static int ocfs2_xe_entry_usage(struct ocfs2_xattr_entry *xe)
+{
+	return namevalue_size_xe(xe) +
+		sizeof(struct ocfs2_xattr_entry);
 }
 
 int ocfs2_calc_security_init(struct inode *dir,
@@ -1308,452 +1397,897 @@
 	return ret;
 }
 
-static int ocfs2_xattr_cleanup(struct inode *inode,
-			       handle_t *handle,
-			       struct ocfs2_xattr_info *xi,
-			       struct ocfs2_xattr_search *xs,
-			       struct ocfs2_xattr_value_buf *vb,
-			       size_t offs)
+static int ocfs2_xa_check_space_helper(int needed_space, int free_start,
+				       int num_entries)
 {
-	int ret = 0;
-	size_t name_len = strlen(xi->name);
-	void *val = xs->base + offs;
-	size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
+	int free_space;
 
-	ret = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh,
-			    OCFS2_JOURNAL_ACCESS_WRITE);
-	if (ret) {
-		mlog_errno(ret);
-		goto out;
-	}
-	/* Decrease xattr count */
-	le16_add_cpu(&xs->header->xh_count, -1);
-	/* Remove the xattr entry and tree root which has already be set*/
-	memset((void *)xs->here, 0, sizeof(struct ocfs2_xattr_entry));
-	memset(val, 0, size);
+	if (!needed_space)
+		return 0;
 
-	ret = ocfs2_journal_dirty(handle, vb->vb_bh);
-	if (ret < 0)
-		mlog_errno(ret);
-out:
-	return ret;
-}
-
-static int ocfs2_xattr_update_entry(struct inode *inode,
-				    handle_t *handle,
-				    struct ocfs2_xattr_info *xi,
-				    struct ocfs2_xattr_search *xs,
-				    struct ocfs2_xattr_value_buf *vb,
-				    size_t offs)
-{
-	int ret;
-
-	ret = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh,
-			    OCFS2_JOURNAL_ACCESS_WRITE);
-	if (ret) {
-		mlog_errno(ret);
-		goto out;
-	}
-
-	xs->here->xe_name_offset = cpu_to_le16(offs);
-	xs->here->xe_value_size = cpu_to_le64(xi->value_len);
-	if (xi->value_len <= OCFS2_XATTR_INLINE_SIZE)
-		ocfs2_xattr_set_local(xs->here, 1);
-	else
-		ocfs2_xattr_set_local(xs->here, 0);
-	ocfs2_xattr_hash_entry(inode, xs->header, xs->here);
-
-	ret = ocfs2_journal_dirty(handle, vb->vb_bh);
-	if (ret < 0)
-		mlog_errno(ret);
-out:
-	return ret;
-}
-
-/*
- * ocfs2_xattr_set_value_outside()
- *
- * Set large size value in B tree.
- */
-static int ocfs2_xattr_set_value_outside(struct inode *inode,
-					 struct ocfs2_xattr_info *xi,
-					 struct ocfs2_xattr_search *xs,
-					 struct ocfs2_xattr_set_ctxt *ctxt,
-					 struct ocfs2_xattr_value_buf *vb,
-					 size_t offs)
-{
-	size_t name_len = strlen(xi->name);
-	void *val = xs->base + offs;
-	struct ocfs2_xattr_value_root *xv = NULL;
-	size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
-	int ret = 0;
-
-	memset(val, 0, size);
-	memcpy(val, xi->name, name_len);
-	xv = (struct ocfs2_xattr_value_root *)
-		(val + OCFS2_XATTR_SIZE(name_len));
-	xv->xr_clusters = 0;
-	xv->xr_last_eb_blk = 0;
-	xv->xr_list.l_tree_depth = 0;
-	xv->xr_list.l_count = cpu_to_le16(1);
-	xv->xr_list.l_next_free_rec = 0;
-	vb->vb_xv = xv;
-
-	ret = ocfs2_xattr_value_truncate(inode, vb, xi->value_len, ctxt);
-	if (ret < 0) {
-		mlog_errno(ret);
-		return ret;
-	}
-	ret = ocfs2_xattr_update_entry(inode, ctxt->handle, xi, xs, vb, offs);
-	if (ret < 0) {
-		mlog_errno(ret);
-		return ret;
-	}
-	ret = __ocfs2_xattr_set_value_outside(inode, ctxt->handle, vb,
-					      xi->value, xi->value_len);
-	if (ret < 0)
-		mlog_errno(ret);
-
-	return ret;
-}
-
-/*
- * ocfs2_xattr_set_entry_local()
- *
- * Set, replace or remove extended attribute in local.
- */
-static void ocfs2_xattr_set_entry_local(struct inode *inode,
-					struct ocfs2_xattr_info *xi,
-					struct ocfs2_xattr_search *xs,
-					struct ocfs2_xattr_entry *last,
-					size_t min_offs)
-{
-	size_t name_len = strlen(xi->name);
-	int i;
-
-	if (xi->value && xs->not_found) {
-		/* Insert the new xattr entry. */
-		le16_add_cpu(&xs->header->xh_count, 1);
-		ocfs2_xattr_set_type(last, xi->name_index);
-		ocfs2_xattr_set_local(last, 1);
-		last->xe_name_len = name_len;
-	} else {
-		void *first_val;
-		void *val;
-		size_t offs, size;
-
-		first_val = xs->base + min_offs;
-		offs = le16_to_cpu(xs->here->xe_name_offset);
-		val = xs->base + offs;
-
-		if (le64_to_cpu(xs->here->xe_value_size) >
-		    OCFS2_XATTR_INLINE_SIZE)
-			size = OCFS2_XATTR_SIZE(name_len) +
-				OCFS2_XATTR_ROOT_SIZE;
-		else
-			size = OCFS2_XATTR_SIZE(name_len) +
-			OCFS2_XATTR_SIZE(le64_to_cpu(xs->here->xe_value_size));
-
-		if (xi->value && size == OCFS2_XATTR_SIZE(name_len) +
-				OCFS2_XATTR_SIZE(xi->value_len)) {
-			/* The old and the new value have the
-			   same size. Just replace the value. */
-			ocfs2_xattr_set_local(xs->here, 1);
-			xs->here->xe_value_size = cpu_to_le64(xi->value_len);
-			/* Clear value bytes. */
-			memset(val + OCFS2_XATTR_SIZE(name_len),
-			       0,
-			       OCFS2_XATTR_SIZE(xi->value_len));
-			memcpy(val + OCFS2_XATTR_SIZE(name_len),
-			       xi->value,
-			       xi->value_len);
-			return;
-		}
-		/* Remove the old name+value. */
-		memmove(first_val + size, first_val, val - first_val);
-		memset(first_val, 0, size);
-		xs->here->xe_name_hash = 0;
-		xs->here->xe_name_offset = 0;
-		ocfs2_xattr_set_local(xs->here, 1);
-		xs->here->xe_value_size = 0;
-
-		min_offs += size;
-
-		/* Adjust all value offsets. */
-		last = xs->header->xh_entries;
-		for (i = 0 ; i < le16_to_cpu(xs->header->xh_count); i++) {
-			size_t o = le16_to_cpu(last->xe_name_offset);
-
-			if (o < offs)
-				last->xe_name_offset = cpu_to_le16(o + size);
-			last += 1;
-		}
-
-		if (!xi->value) {
-			/* Remove the old entry. */
-			last -= 1;
-			memmove(xs->here, xs->here + 1,
-				(void *)last - (void *)xs->here);
-			memset(last, 0, sizeof(struct ocfs2_xattr_entry));
-			le16_add_cpu(&xs->header->xh_count, -1);
-		}
-	}
-	if (xi->value) {
-		/* Insert the new name+value. */
-		size_t size = OCFS2_XATTR_SIZE(name_len) +
-				OCFS2_XATTR_SIZE(xi->value_len);
-		void *val = xs->base + min_offs - size;
-
-		xs->here->xe_name_offset = cpu_to_le16(min_offs - size);
-		memset(val, 0, size);
-		memcpy(val, xi->name, name_len);
-		memcpy(val + OCFS2_XATTR_SIZE(name_len),
-		       xi->value,
-		       xi->value_len);
-		xs->here->xe_value_size = cpu_to_le64(xi->value_len);
-		ocfs2_xattr_set_local(xs->here, 1);
-		ocfs2_xattr_hash_entry(inode, xs->header, xs->here);
-	}
-
-	return;
-}
-
-/*
- * ocfs2_xattr_set_entry()
- *
- * Set extended attribute entry into inode or block.
- *
- * If extended attribute value size > OCFS2_XATTR_INLINE_SIZE,
- * We first insert tree root(ocfs2_xattr_value_root) with set_entry_local(),
- * then set value in B tree with set_value_outside().
- */
-static int ocfs2_xattr_set_entry(struct inode *inode,
-				 struct ocfs2_xattr_info *xi,
-				 struct ocfs2_xattr_search *xs,
-				 struct ocfs2_xattr_set_ctxt *ctxt,
-				 int flag)
-{
-	struct ocfs2_xattr_entry *last;
-	struct ocfs2_inode_info *oi = OCFS2_I(inode);
-	struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
-	size_t min_offs = xs->end - xs->base, name_len = strlen(xi->name);
-	size_t size_l = 0;
-	handle_t *handle = ctxt->handle;
-	int free, i, ret;
-	struct ocfs2_xattr_info xi_l = {
-		.name_index = xi->name_index,
-		.name = xi->name,
-		.value = xi->value,
-		.value_len = xi->value_len,
-	};
-	struct ocfs2_xattr_value_buf vb = {
-		.vb_bh = xs->xattr_bh,
-		.vb_access = ocfs2_journal_access_di,
-	};
-
-	if (!(flag & OCFS2_INLINE_XATTR_FL)) {
-		BUG_ON(xs->xattr_bh == xs->inode_bh);
-		vb.vb_access = ocfs2_journal_access_xb;
-	} else
-		BUG_ON(xs->xattr_bh != xs->inode_bh);
-
-	/* Compute min_offs, last and free space. */
-	last = xs->header->xh_entries;
-
-	for (i = 0 ; i < le16_to_cpu(xs->header->xh_count); i++) {
-		size_t offs = le16_to_cpu(last->xe_name_offset);
-		if (offs < min_offs)
-			min_offs = offs;
-		last += 1;
-	}
-
-	free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP;
-	if (free < 0)
+	free_space = free_start -
+		sizeof(struct ocfs2_xattr_header) -
+		(num_entries * sizeof(struct ocfs2_xattr_entry)) -
+		OCFS2_XATTR_HEADER_GAP;
+	if (free_space < 0)
 		return -EIO;
+	if (free_space < needed_space)
+		return -ENOSPC;
 
-	if (!xs->not_found) {
-		size_t size = 0;
-		if (ocfs2_xattr_is_local(xs->here))
-			size = OCFS2_XATTR_SIZE(name_len) +
-			OCFS2_XATTR_SIZE(le64_to_cpu(xs->here->xe_value_size));
+	return 0;
+}
+
+static int ocfs2_xa_journal_access(handle_t *handle, struct ocfs2_xa_loc *loc,
+				   int type)
+{
+	return loc->xl_ops->xlo_journal_access(handle, loc, type);
+}
+
+static void ocfs2_xa_journal_dirty(handle_t *handle, struct ocfs2_xa_loc *loc)
+{
+	loc->xl_ops->xlo_journal_dirty(handle, loc);
+}
+
+/* Give a pointer into the storage for the given offset */
+static void *ocfs2_xa_offset_pointer(struct ocfs2_xa_loc *loc, int offset)
+{
+	BUG_ON(offset >= loc->xl_size);
+	return loc->xl_ops->xlo_offset_pointer(loc, offset);
+}
+
+/*
+ * Wipe the name+value pair and allow the storage to reclaim it.  This
+ * must be followed by either removal of the entry or a call to
+ * ocfs2_xa_add_namevalue().
+ */
+static void ocfs2_xa_wipe_namevalue(struct ocfs2_xa_loc *loc)
+{
+	loc->xl_ops->xlo_wipe_namevalue(loc);
+}
+
+/*
+ * Find lowest offset to a name+value pair.  This is the start of our
+ * downward-growing free space.
+ */
+static int ocfs2_xa_get_free_start(struct ocfs2_xa_loc *loc)
+{
+	return loc->xl_ops->xlo_get_free_start(loc);
+}
+
+/* Can we reuse loc->xl_entry for xi? */
+static int ocfs2_xa_can_reuse_entry(struct ocfs2_xa_loc *loc,
+				    struct ocfs2_xattr_info *xi)
+{
+	return loc->xl_ops->xlo_can_reuse(loc, xi);
+}
+
+/* How much free space is needed to set the new value */
+static int ocfs2_xa_check_space(struct ocfs2_xa_loc *loc,
+				struct ocfs2_xattr_info *xi)
+{
+	return loc->xl_ops->xlo_check_space(loc, xi);
+}
+
+static void ocfs2_xa_add_entry(struct ocfs2_xa_loc *loc, u32 name_hash)
+{
+	loc->xl_ops->xlo_add_entry(loc, name_hash);
+	loc->xl_entry->xe_name_hash = cpu_to_le32(name_hash);
+	/*
+	 * We can't leave the new entry's xe_name_offset at zero or
+	 * add_namevalue() will go nuts.  We set it to the size of our
+	 * storage so that it can never be less than any other entry.
+	 */
+	loc->xl_entry->xe_name_offset = cpu_to_le16(loc->xl_size);
+}
+
+static void ocfs2_xa_add_namevalue(struct ocfs2_xa_loc *loc,
+				   struct ocfs2_xattr_info *xi)
+{
+	int size = namevalue_size_xi(xi);
+	int nameval_offset;
+	char *nameval_buf;
+
+	loc->xl_ops->xlo_add_namevalue(loc, size);
+	loc->xl_entry->xe_value_size = cpu_to_le64(xi->xi_value_len);
+	loc->xl_entry->xe_name_len = xi->xi_name_len;
+	ocfs2_xattr_set_type(loc->xl_entry, xi->xi_name_index);
+	ocfs2_xattr_set_local(loc->xl_entry,
+			      xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE);
+
+	nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset);
+	nameval_buf = ocfs2_xa_offset_pointer(loc, nameval_offset);
+	memset(nameval_buf, 0, size);
+	memcpy(nameval_buf, xi->xi_name, xi->xi_name_len);
+}
+
+static void ocfs2_xa_fill_value_buf(struct ocfs2_xa_loc *loc,
+				    struct ocfs2_xattr_value_buf *vb)
+{
+	int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset);
+	int name_size = OCFS2_XATTR_SIZE(loc->xl_entry->xe_name_len);
+
+	/* Value bufs are for value trees */
+	BUG_ON(ocfs2_xattr_is_local(loc->xl_entry));
+	BUG_ON(namevalue_size_xe(loc->xl_entry) !=
+	       (name_size + OCFS2_XATTR_ROOT_SIZE));
+
+	loc->xl_ops->xlo_fill_value_buf(loc, vb);
+	vb->vb_xv =
+		(struct ocfs2_xattr_value_root *)ocfs2_xa_offset_pointer(loc,
+							nameval_offset +
+							name_size);
+}
+
+static int ocfs2_xa_block_journal_access(handle_t *handle,
+					 struct ocfs2_xa_loc *loc, int type)
+{
+	struct buffer_head *bh = loc->xl_storage;
+	ocfs2_journal_access_func access;
+
+	if (loc->xl_size == (bh->b_size -
+			     offsetof(struct ocfs2_xattr_block,
+				      xb_attrs.xb_header)))
+		access = ocfs2_journal_access_xb;
+	else
+		access = ocfs2_journal_access_di;
+	return access(handle, INODE_CACHE(loc->xl_inode), bh, type);
+}
+
+static void ocfs2_xa_block_journal_dirty(handle_t *handle,
+					 struct ocfs2_xa_loc *loc)
+{
+	struct buffer_head *bh = loc->xl_storage;
+
+	ocfs2_journal_dirty(handle, bh);
+}
+
+static void *ocfs2_xa_block_offset_pointer(struct ocfs2_xa_loc *loc,
+					   int offset)
+{
+	return (char *)loc->xl_header + offset;
+}
+
+static int ocfs2_xa_block_can_reuse(struct ocfs2_xa_loc *loc,
+				    struct ocfs2_xattr_info *xi)
+{
+	/*
+	 * Block storage is strict.  If the sizes aren't exact, we will
+	 * remove the old one and reinsert the new.
+	 */
+	return namevalue_size_xe(loc->xl_entry) ==
+		namevalue_size_xi(xi);
+}
+
+static int ocfs2_xa_block_get_free_start(struct ocfs2_xa_loc *loc)
+{
+	struct ocfs2_xattr_header *xh = loc->xl_header;
+	int i, count = le16_to_cpu(xh->xh_count);
+	int offset, free_start = loc->xl_size;
+
+	for (i = 0; i < count; i++) {
+		offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset);
+		if (offset < free_start)
+			free_start = offset;
+	}
+
+	return free_start;
+}
+
+static int ocfs2_xa_block_check_space(struct ocfs2_xa_loc *loc,
+				      struct ocfs2_xattr_info *xi)
+{
+	int count = le16_to_cpu(loc->xl_header->xh_count);
+	int free_start = ocfs2_xa_get_free_start(loc);
+	int needed_space = ocfs2_xi_entry_usage(xi);
+
+	/*
+	 * Block storage will reclaim the original entry before inserting
+	 * the new value, so we only need the difference.  If the new
+	 * entry is smaller than the old one, we don't need anything.
+	 */
+	if (loc->xl_entry) {
+		/* Don't need space if we're reusing! */
+		if (ocfs2_xa_can_reuse_entry(loc, xi))
+			needed_space = 0;
 		else
-			size = OCFS2_XATTR_SIZE(name_len) +
-				OCFS2_XATTR_ROOT_SIZE;
-		free += (size + sizeof(struct ocfs2_xattr_entry));
+			needed_space -= ocfs2_xe_entry_usage(loc->xl_entry);
 	}
-	/* Check free space in inode or block */
-	if (xi->value && xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
-		if (free < sizeof(struct ocfs2_xattr_entry) +
-			   OCFS2_XATTR_SIZE(name_len) +
-			   OCFS2_XATTR_ROOT_SIZE) {
-			ret = -ENOSPC;
-			goto out;
-		}
-		size_l = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE;
-		xi_l.value = (void *)&def_xv;
-		xi_l.value_len = OCFS2_XATTR_ROOT_SIZE;
-	} else if (xi->value) {
-		if (free < sizeof(struct ocfs2_xattr_entry) +
-			   OCFS2_XATTR_SIZE(name_len) +
-			   OCFS2_XATTR_SIZE(xi->value_len)) {
-			ret = -ENOSPC;
-			goto out;
+	if (needed_space < 0)
+		needed_space = 0;
+	return ocfs2_xa_check_space_helper(needed_space, free_start, count);
+}
+
+/*
+ * Block storage for xattrs keeps the name+value pairs compacted.  When
+ * we remove one, we have to shift any that preceded it towards the end.
+ */
+static void ocfs2_xa_block_wipe_namevalue(struct ocfs2_xa_loc *loc)
+{
+	int i, offset;
+	int namevalue_offset, first_namevalue_offset, namevalue_size;
+	struct ocfs2_xattr_entry *entry = loc->xl_entry;
+	struct ocfs2_xattr_header *xh = loc->xl_header;
+	int count = le16_to_cpu(xh->xh_count);
+
+	namevalue_offset = le16_to_cpu(entry->xe_name_offset);
+	namevalue_size = namevalue_size_xe(entry);
+	first_namevalue_offset = ocfs2_xa_get_free_start(loc);
+
+	/* Shift the name+value pairs */
+	memmove((char *)xh + first_namevalue_offset + namevalue_size,
+		(char *)xh + first_namevalue_offset,
+		namevalue_offset - first_namevalue_offset);
+	memset((char *)xh + first_namevalue_offset, 0, namevalue_size);
+
+	/* Now tell xh->xh_entries about it */
+	for (i = 0; i < count; i++) {
+		offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset);
+		if (offset < namevalue_offset)
+			le16_add_cpu(&xh->xh_entries[i].xe_name_offset,
+				     namevalue_size);
+	}
+
+	/*
+	 * Note that we don't update xh_free_start or xh_name_value_len
+	 * because they're not used in block-stored xattrs.
+	 */
+}
+
+static void ocfs2_xa_block_add_entry(struct ocfs2_xa_loc *loc, u32 name_hash)
+{
+	int count = le16_to_cpu(loc->xl_header->xh_count);
+	loc->xl_entry = &(loc->xl_header->xh_entries[count]);
+	le16_add_cpu(&loc->xl_header->xh_count, 1);
+	memset(loc->xl_entry, 0, sizeof(struct ocfs2_xattr_entry));
+}
+
+static void ocfs2_xa_block_add_namevalue(struct ocfs2_xa_loc *loc, int size)
+{
+	int free_start = ocfs2_xa_get_free_start(loc);
+
+	loc->xl_entry->xe_name_offset = cpu_to_le16(free_start - size);
+}
+
+static void ocfs2_xa_block_fill_value_buf(struct ocfs2_xa_loc *loc,
+					  struct ocfs2_xattr_value_buf *vb)
+{
+	struct buffer_head *bh = loc->xl_storage;
+
+	if (loc->xl_size == (bh->b_size -
+			     offsetof(struct ocfs2_xattr_block,
+				      xb_attrs.xb_header)))
+		vb->vb_access = ocfs2_journal_access_xb;
+	else
+		vb->vb_access = ocfs2_journal_access_di;
+	vb->vb_bh = bh;
+}
+
+/*
+ * Operations for xattrs stored in blocks.  This includes inline inode
+ * storage and unindexed ocfs2_xattr_blocks.
+ */
+static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = {
+	.xlo_journal_access	= ocfs2_xa_block_journal_access,
+	.xlo_journal_dirty	= ocfs2_xa_block_journal_dirty,
+	.xlo_offset_pointer	= ocfs2_xa_block_offset_pointer,
+	.xlo_check_space	= ocfs2_xa_block_check_space,
+	.xlo_can_reuse		= ocfs2_xa_block_can_reuse,
+	.xlo_get_free_start	= ocfs2_xa_block_get_free_start,
+	.xlo_wipe_namevalue	= ocfs2_xa_block_wipe_namevalue,
+	.xlo_add_entry		= ocfs2_xa_block_add_entry,
+	.xlo_add_namevalue	= ocfs2_xa_block_add_namevalue,
+	.xlo_fill_value_buf	= ocfs2_xa_block_fill_value_buf,
+};
+
+static int ocfs2_xa_bucket_journal_access(handle_t *handle,
+					  struct ocfs2_xa_loc *loc, int type)
+{
+	struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
+
+	return ocfs2_xattr_bucket_journal_access(handle, bucket, type);
+}
+
+static void ocfs2_xa_bucket_journal_dirty(handle_t *handle,
+					  struct ocfs2_xa_loc *loc)
+{
+	struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
+
+	ocfs2_xattr_bucket_journal_dirty(handle, bucket);
+}
+
+static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc,
+					    int offset)
+{
+	struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
+	int block, block_offset;
+
+	/* The header is at the front of the bucket */
+	block = offset >> loc->xl_inode->i_sb->s_blocksize_bits;
+	block_offset = offset % loc->xl_inode->i_sb->s_blocksize;
+
+	return bucket_block(bucket, block) + block_offset;
+}
+
+static int ocfs2_xa_bucket_can_reuse(struct ocfs2_xa_loc *loc,
+				     struct ocfs2_xattr_info *xi)
+{
+	return namevalue_size_xe(loc->xl_entry) >=
+		namevalue_size_xi(xi);
+}
+
+static int ocfs2_xa_bucket_get_free_start(struct ocfs2_xa_loc *loc)
+{
+	struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
+	return le16_to_cpu(bucket_xh(bucket)->xh_free_start);
+}
+
+static int ocfs2_bucket_align_free_start(struct super_block *sb,
+					 int free_start, int size)
+{
+	/*
+	 * We need to make sure that the name+value pair fits within
+	 * one block.
+	 */
+	if (((free_start - size) >> sb->s_blocksize_bits) !=
+	    ((free_start - 1) >> sb->s_blocksize_bits))
+		free_start -= free_start % sb->s_blocksize;
+
+	return free_start;
+}
+
+static int ocfs2_xa_bucket_check_space(struct ocfs2_xa_loc *loc,
+				       struct ocfs2_xattr_info *xi)
+{
+	int rc;
+	int count = le16_to_cpu(loc->xl_header->xh_count);
+	int free_start = ocfs2_xa_get_free_start(loc);
+	int needed_space = ocfs2_xi_entry_usage(xi);
+	int size = namevalue_size_xi(xi);
+	struct super_block *sb = loc->xl_inode->i_sb;
+
+	/*
+	 * Bucket storage does not reclaim name+value pairs it cannot
+	 * reuse.  They live as holes until the bucket fills, and then
+	 * the bucket is defragmented.  However, the bucket can reclaim
+	 * the ocfs2_xattr_entry.
+	 */
+	if (loc->xl_entry) {
+		/* Don't need space if we're reusing! */
+		if (ocfs2_xa_can_reuse_entry(loc, xi))
+			needed_space = 0;
+		else
+			needed_space -= sizeof(struct ocfs2_xattr_entry);
+	}
+	BUG_ON(needed_space < 0);
+
+	if (free_start < size) {
+		if (needed_space)
+			return -ENOSPC;
+	} else {
+		/*
+		 * First we check if it would fit in the first place.
+		 * Below, we align the free start to a block.  This may
+		 * slide us below the minimum gap.  By checking unaligned
+		 * first, we avoid that error.
+		 */
+		rc = ocfs2_xa_check_space_helper(needed_space, free_start,
+						 count);
+		if (rc)
+			return rc;
+		free_start = ocfs2_bucket_align_free_start(sb, free_start,
+							   size);
+	}
+	return ocfs2_xa_check_space_helper(needed_space, free_start, count);
+}
+
+static void ocfs2_xa_bucket_wipe_namevalue(struct ocfs2_xa_loc *loc)
+{
+	le16_add_cpu(&loc->xl_header->xh_name_value_len,
+		     -namevalue_size_xe(loc->xl_entry));
+}
+
+static void ocfs2_xa_bucket_add_entry(struct ocfs2_xa_loc *loc, u32 name_hash)
+{
+	struct ocfs2_xattr_header *xh = loc->xl_header;
+	int count = le16_to_cpu(xh->xh_count);
+	int low = 0, high = count - 1, tmp;
+	struct ocfs2_xattr_entry *tmp_xe;
+
+	/*
+	 * We keep buckets sorted by name_hash, so we need to find
+	 * our insert place.
+	 */
+	while (low <= high && count) {
+		tmp = (low + high) / 2;
+		tmp_xe = &xh->xh_entries[tmp];
+
+		if (name_hash > le32_to_cpu(tmp_xe->xe_name_hash))
+			low = tmp + 1;
+		else if (name_hash < le32_to_cpu(tmp_xe->xe_name_hash))
+			high = tmp - 1;
+		else {
+			low = tmp;
+			break;
 		}
 	}
 
-	if (!xs->not_found) {
-		/* For existing extended attribute */
-		size_t size = OCFS2_XATTR_SIZE(name_len) +
-			OCFS2_XATTR_SIZE(le64_to_cpu(xs->here->xe_value_size));
-		size_t offs = le16_to_cpu(xs->here->xe_name_offset);
-		void *val = xs->base + offs;
+	if (low != count)
+		memmove(&xh->xh_entries[low + 1],
+			&xh->xh_entries[low],
+			((count - low) * sizeof(struct ocfs2_xattr_entry)));
 
-		if (ocfs2_xattr_is_local(xs->here) && size == size_l) {
-			/* Replace existing local xattr with tree root */
-			ret = ocfs2_xattr_set_value_outside(inode, xi, xs,
-							    ctxt, &vb, offs);
-			if (ret < 0)
-				mlog_errno(ret);
-			goto out;
-		} else if (!ocfs2_xattr_is_local(xs->here)) {
-			/* For existing xattr which has value outside */
-			vb.vb_xv = (struct ocfs2_xattr_value_root *)
-				(val + OCFS2_XATTR_SIZE(name_len));
+	le16_add_cpu(&xh->xh_count, 1);
+	loc->xl_entry = &xh->xh_entries[low];
+	memset(loc->xl_entry, 0, sizeof(struct ocfs2_xattr_entry));
+}
 
-			if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
-				/*
-				 * If new value need set outside also,
-				 * first truncate old value to new value,
-				 * then set new value with set_value_outside().
-				 */
-				ret = ocfs2_xattr_value_truncate(inode,
-								 &vb,
-								 xi->value_len,
-								 ctxt);
-				if (ret < 0) {
-					mlog_errno(ret);
-					goto out;
-				}
+static void ocfs2_xa_bucket_add_namevalue(struct ocfs2_xa_loc *loc, int size)
+{
+	int free_start = ocfs2_xa_get_free_start(loc);
+	struct ocfs2_xattr_header *xh = loc->xl_header;
+	struct super_block *sb = loc->xl_inode->i_sb;
+	int nameval_offset;
 
-				ret = ocfs2_xattr_update_entry(inode,
-							       handle,
-							       xi,
-							       xs,
-							       &vb,
-							       offs);
-				if (ret < 0) {
-					mlog_errno(ret);
-					goto out;
-				}
+	free_start = ocfs2_bucket_align_free_start(sb, free_start, size);
+	nameval_offset = free_start - size;
+	loc->xl_entry->xe_name_offset = cpu_to_le16(nameval_offset);
+	xh->xh_free_start = cpu_to_le16(nameval_offset);
+	le16_add_cpu(&xh->xh_name_value_len, size);
 
-				ret = __ocfs2_xattr_set_value_outside(inode,
-								handle,
-								&vb,
-								xi->value,
-								xi->value_len);
-				if (ret < 0)
-					mlog_errno(ret);
+}
+
+static void ocfs2_xa_bucket_fill_value_buf(struct ocfs2_xa_loc *loc,
+					   struct ocfs2_xattr_value_buf *vb)
+{
+	struct ocfs2_xattr_bucket *bucket = loc->xl_storage;
+	struct super_block *sb = loc->xl_inode->i_sb;
+	int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset);
+	int size = namevalue_size_xe(loc->xl_entry);
+	int block_offset = nameval_offset >> sb->s_blocksize_bits;
+
+	/* Values are not allowed to straddle block boundaries */
+	BUG_ON(block_offset !=
+	       ((nameval_offset + size - 1) >> sb->s_blocksize_bits));
+	/* We expect the bucket to be filled in */
+	BUG_ON(!bucket->bu_bhs[block_offset]);
+
+	vb->vb_access = ocfs2_journal_access;
+	vb->vb_bh = bucket->bu_bhs[block_offset];
+}
+
+/* Operations for xattrs stored in buckets. */
+static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = {
+	.xlo_journal_access	= ocfs2_xa_bucket_journal_access,
+	.xlo_journal_dirty	= ocfs2_xa_bucket_journal_dirty,
+	.xlo_offset_pointer	= ocfs2_xa_bucket_offset_pointer,
+	.xlo_check_space	= ocfs2_xa_bucket_check_space,
+	.xlo_can_reuse		= ocfs2_xa_bucket_can_reuse,
+	.xlo_get_free_start	= ocfs2_xa_bucket_get_free_start,
+	.xlo_wipe_namevalue	= ocfs2_xa_bucket_wipe_namevalue,
+	.xlo_add_entry		= ocfs2_xa_bucket_add_entry,
+	.xlo_add_namevalue	= ocfs2_xa_bucket_add_namevalue,
+	.xlo_fill_value_buf	= ocfs2_xa_bucket_fill_value_buf,
+};
+
+static unsigned int ocfs2_xa_value_clusters(struct ocfs2_xa_loc *loc)
+{
+	struct ocfs2_xattr_value_buf vb;
+
+	if (ocfs2_xattr_is_local(loc->xl_entry))
+		return 0;
+
+	ocfs2_xa_fill_value_buf(loc, &vb);
+	return le32_to_cpu(vb.vb_xv->xr_clusters);
+}
+
+static int ocfs2_xa_value_truncate(struct ocfs2_xa_loc *loc, u64 bytes,
+				   struct ocfs2_xattr_set_ctxt *ctxt)
+{
+	int trunc_rc, access_rc;
+	struct ocfs2_xattr_value_buf vb;
+
+	ocfs2_xa_fill_value_buf(loc, &vb);
+	trunc_rc = ocfs2_xattr_value_truncate(loc->xl_inode, &vb, bytes,
+					      ctxt);
+
+	/*
+	 * The caller of ocfs2_xa_value_truncate() has already called
+	 * ocfs2_xa_journal_access on the loc.  However, The truncate code
+	 * calls ocfs2_extend_trans().  This may commit the previous
+	 * transaction and open a new one.  If this is a bucket, truncate
+	 * could leave only vb->vb_bh set up for journaling.  Meanwhile,
+	 * the caller is expecting to dirty the entire bucket.  So we must
+	 * reset the journal work.  We do this even if truncate has failed,
+	 * as it could have failed after committing the extend.
+	 */
+	access_rc = ocfs2_xa_journal_access(ctxt->handle, loc,
+					    OCFS2_JOURNAL_ACCESS_WRITE);
+
+	/* Errors in truncate take precedence */
+	return trunc_rc ? trunc_rc : access_rc;
+}
+
+static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc)
+{
+	int index, count;
+	struct ocfs2_xattr_header *xh = loc->xl_header;
+	struct ocfs2_xattr_entry *entry = loc->xl_entry;
+
+	ocfs2_xa_wipe_namevalue(loc);
+	loc->xl_entry = NULL;
+
+	le16_add_cpu(&xh->xh_count, -1);
+	count = le16_to_cpu(xh->xh_count);
+
+	/*
+	 * Only zero out the entry if there are more remaining.  This is
+	 * important for an empty bucket, as it keeps track of the
+	 * bucket's hash value.  It doesn't hurt empty block storage.
+	 */
+	if (count) {
+		index = ((char *)entry - (char *)&xh->xh_entries) /
+			sizeof(struct ocfs2_xattr_entry);
+		memmove(&xh->xh_entries[index], &xh->xh_entries[index + 1],
+			(count - index) * sizeof(struct ocfs2_xattr_entry));
+		memset(&xh->xh_entries[count], 0,
+		       sizeof(struct ocfs2_xattr_entry));
+	}
+}
+
+/*
+ * If we have a problem adjusting the size of an external value during
+ * ocfs2_xa_prepare_entry() or ocfs2_xa_remove(), we may have an xattr
+ * in an intermediate state.  For example, the value may be partially
+ * truncated.
+ *
+ * If the value tree hasn't changed, the extend/truncate went nowhere.
+ * We have nothing to do.  The caller can treat it as a straight error.
+ *
+ * If the value tree got partially truncated, we now have a corrupted
+ * extended attribute.  We're going to wipe its entry and leak the
+ * clusters.  Better to leak some storage than leave a corrupt entry.
+ *
+ * If the value tree grew, it obviously didn't grow enough for the
+ * new entry.  We're not going to try and reclaim those clusters either.
+ * If there was already an external value there (orig_clusters != 0),
+ * the new clusters are attached safely and we can just leave the old
+ * value in place.  If there was no external value there, we remove
+ * the entry.
+ *
+ * This way, the xattr block we store in the journal will be consistent.
+ * If the size change broke because of the journal, no changes will hit
+ * disk anyway.
+ */
+static void ocfs2_xa_cleanup_value_truncate(struct ocfs2_xa_loc *loc,
+					    const char *what,
+					    unsigned int orig_clusters)
+{
+	unsigned int new_clusters = ocfs2_xa_value_clusters(loc);
+	char *nameval_buf = ocfs2_xa_offset_pointer(loc,
+				le16_to_cpu(loc->xl_entry->xe_name_offset));
+
+	if (new_clusters < orig_clusters) {
+		mlog(ML_ERROR,
+		     "Partial truncate while %s xattr %.*s.  Leaking "
+		     "%u clusters and removing the entry\n",
+		     what, loc->xl_entry->xe_name_len, nameval_buf,
+		     orig_clusters - new_clusters);
+		ocfs2_xa_remove_entry(loc);
+	} else if (!orig_clusters) {
+		mlog(ML_ERROR,
+		     "Unable to allocate an external value for xattr "
+		     "%.*s safely.  Leaking %u clusters and removing the "
+		     "entry\n",
+		     loc->xl_entry->xe_name_len, nameval_buf,
+		     new_clusters - orig_clusters);
+		ocfs2_xa_remove_entry(loc);
+	} else if (new_clusters > orig_clusters)
+		mlog(ML_ERROR,
+		     "Unable to grow xattr %.*s safely.  %u new clusters "
+		     "have been added, but the value will not be "
+		     "modified\n",
+		     loc->xl_entry->xe_name_len, nameval_buf,
+		     new_clusters - orig_clusters);
+}
+
+static int ocfs2_xa_remove(struct ocfs2_xa_loc *loc,
+			   struct ocfs2_xattr_set_ctxt *ctxt)
+{
+	int rc = 0;
+	unsigned int orig_clusters;
+
+	if (!ocfs2_xattr_is_local(loc->xl_entry)) {
+		orig_clusters = ocfs2_xa_value_clusters(loc);
+		rc = ocfs2_xa_value_truncate(loc, 0, ctxt);
+		if (rc) {
+			mlog_errno(rc);
+			/*
+			 * Since this is remove, we can return 0 if
+			 * ocfs2_xa_cleanup_value_truncate() is going to
+			 * wipe the entry anyway.  So we check the
+			 * cluster count as well.
+			 */
+			if (orig_clusters != ocfs2_xa_value_clusters(loc))
+				rc = 0;
+			ocfs2_xa_cleanup_value_truncate(loc, "removing",
+							orig_clusters);
+			if (rc)
 				goto out;
-			} else {
-				/*
-				 * If new value need set in local,
-				 * just trucate old value to zero.
-				 */
-				 ret = ocfs2_xattr_value_truncate(inode,
-								  &vb,
-								  0,
-								  ctxt);
-				if (ret < 0)
-					mlog_errno(ret);
+		}
+	}
+
+	ocfs2_xa_remove_entry(loc);
+
+out:
+	return rc;
+}
+
+static void ocfs2_xa_install_value_root(struct ocfs2_xa_loc *loc)
+{
+	int name_size = OCFS2_XATTR_SIZE(loc->xl_entry->xe_name_len);
+	char *nameval_buf;
+
+	nameval_buf = ocfs2_xa_offset_pointer(loc,
+				le16_to_cpu(loc->xl_entry->xe_name_offset));
+	memcpy(nameval_buf + name_size, &def_xv, OCFS2_XATTR_ROOT_SIZE);
+}
+
+/*
+ * Take an existing entry and make it ready for the new value.  This
+ * won't allocate space, but it may free space.  It should be ready for
+ * ocfs2_xa_prepare_entry() to finish the work.
+ */
+static int ocfs2_xa_reuse_entry(struct ocfs2_xa_loc *loc,
+				struct ocfs2_xattr_info *xi,
+				struct ocfs2_xattr_set_ctxt *ctxt)
+{
+	int rc = 0;
+	int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len);
+	unsigned int orig_clusters;
+	char *nameval_buf;
+	int xe_local = ocfs2_xattr_is_local(loc->xl_entry);
+	int xi_local = xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE;
+
+	BUG_ON(OCFS2_XATTR_SIZE(loc->xl_entry->xe_name_len) !=
+	       name_size);
+
+	nameval_buf = ocfs2_xa_offset_pointer(loc,
+				le16_to_cpu(loc->xl_entry->xe_name_offset));
+	if (xe_local) {
+		memset(nameval_buf + name_size, 0,
+		       namevalue_size_xe(loc->xl_entry) - name_size);
+		if (!xi_local)
+			ocfs2_xa_install_value_root(loc);
+	} else {
+		orig_clusters = ocfs2_xa_value_clusters(loc);
+		if (xi_local) {
+			rc = ocfs2_xa_value_truncate(loc, 0, ctxt);
+			if (rc < 0)
+				mlog_errno(rc);
+			else
+				memset(nameval_buf + name_size, 0,
+				       namevalue_size_xe(loc->xl_entry) -
+				       name_size);
+		} else if (le64_to_cpu(loc->xl_entry->xe_value_size) >
+			   xi->xi_value_len) {
+			rc = ocfs2_xa_value_truncate(loc, xi->xi_value_len,
+						     ctxt);
+			if (rc < 0)
+				mlog_errno(rc);
+		}
+
+		if (rc) {
+			ocfs2_xa_cleanup_value_truncate(loc, "reusing",
+							orig_clusters);
+			goto out;
+		}
+	}
+
+	loc->xl_entry->xe_value_size = cpu_to_le64(xi->xi_value_len);
+	ocfs2_xattr_set_local(loc->xl_entry, xi_local);
+
+out:
+	return rc;
+}
+
+/*
+ * Prepares loc->xl_entry to receive the new xattr.  This includes
+ * properly setting up the name+value pair region.  If loc->xl_entry
+ * already exists, it will take care of modifying it appropriately.
+ *
+ * Note that this modifies the data.  You did journal_access already,
+ * right?
+ */
+static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc,
+				  struct ocfs2_xattr_info *xi,
+				  u32 name_hash,
+				  struct ocfs2_xattr_set_ctxt *ctxt)
+{
+	int rc = 0;
+	unsigned int orig_clusters;
+	__le64 orig_value_size = 0;
+
+	rc = ocfs2_xa_check_space(loc, xi);
+	if (rc)
+		goto out;
+
+	if (loc->xl_entry) {
+		if (ocfs2_xa_can_reuse_entry(loc, xi)) {
+			orig_value_size = loc->xl_entry->xe_value_size;
+			rc = ocfs2_xa_reuse_entry(loc, xi, ctxt);
+			if (rc)
+				goto out;
+			goto alloc_value;
+		}
+
+		if (!ocfs2_xattr_is_local(loc->xl_entry)) {
+			orig_clusters = ocfs2_xa_value_clusters(loc);
+			rc = ocfs2_xa_value_truncate(loc, 0, ctxt);
+			if (rc) {
+				mlog_errno(rc);
+				ocfs2_xa_cleanup_value_truncate(loc,
+								"overwriting",
+								orig_clusters);
+				goto out;
 			}
 		}
+		ocfs2_xa_wipe_namevalue(loc);
+	} else
+		ocfs2_xa_add_entry(loc, name_hash);
+
+	/*
+	 * If we get here, we have a blank entry.  Fill it.  We grow our
+	 * name+value pair back from the end.
+	 */
+	ocfs2_xa_add_namevalue(loc, xi);
+	if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE)
+		ocfs2_xa_install_value_root(loc);
+
+alloc_value:
+	if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
+		orig_clusters = ocfs2_xa_value_clusters(loc);
+		rc = ocfs2_xa_value_truncate(loc, xi->xi_value_len, ctxt);
+		if (rc < 0) {
+			/*
+			 * If we tried to grow an existing external value,
+			 * ocfs2_xa_cleanuP-value_truncate() is going to
+			 * let it stand.  We have to restore its original
+			 * value size.
+			 */
+			loc->xl_entry->xe_value_size = orig_value_size;
+			ocfs2_xa_cleanup_value_truncate(loc, "growing",
+							orig_clusters);
+			mlog_errno(rc);
+		}
 	}
 
-	ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), xs->inode_bh,
+out:
+	return rc;
+}
+
+/*
+ * Store the value portion of the name+value pair.  This will skip
+ * values that are stored externally.  Their tree roots were set up
+ * by ocfs2_xa_prepare_entry().
+ */
+static int ocfs2_xa_store_value(struct ocfs2_xa_loc *loc,
+				struct ocfs2_xattr_info *xi,
+				struct ocfs2_xattr_set_ctxt *ctxt)
+{
+	int rc = 0;
+	int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset);
+	int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len);
+	char *nameval_buf;
+	struct ocfs2_xattr_value_buf vb;
+
+	nameval_buf = ocfs2_xa_offset_pointer(loc, nameval_offset);
+	if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
+		ocfs2_xa_fill_value_buf(loc, &vb);
+		rc = __ocfs2_xattr_set_value_outside(loc->xl_inode,
+						     ctxt->handle, &vb,
+						     xi->xi_value,
+						     xi->xi_value_len);
+	} else
+		memcpy(nameval_buf + name_size, xi->xi_value, xi->xi_value_len);
+
+	return rc;
+}
+
+static int ocfs2_xa_set(struct ocfs2_xa_loc *loc,
+			struct ocfs2_xattr_info *xi,
+			struct ocfs2_xattr_set_ctxt *ctxt)
+{
+	int ret;
+	u32 name_hash = ocfs2_xattr_name_hash(loc->xl_inode, xi->xi_name,
+					      xi->xi_name_len);
+
+	ret = ocfs2_xa_journal_access(ctxt->handle, loc,
 				      OCFS2_JOURNAL_ACCESS_WRITE);
 	if (ret) {
 		mlog_errno(ret);
 		goto out;
 	}
 
-	if (!(flag & OCFS2_INLINE_XATTR_FL)) {
-		ret = vb.vb_access(handle, INODE_CACHE(inode), vb.vb_bh,
-				   OCFS2_JOURNAL_ACCESS_WRITE);
-		if (ret) {
-			mlog_errno(ret);
-			goto out;
-		}
-	}
-
 	/*
-	 * Set value in local, include set tree root in local.
-	 * This is the first step for value size >INLINE_SIZE.
+	 * From here on out, everything is going to modify the buffer a
+	 * little.  Errors are going to leave the xattr header in a
+	 * sane state.  Thus, even with errors we dirty the sucker.
 	 */
-	ocfs2_xattr_set_entry_local(inode, &xi_l, xs, last, min_offs);
 
-	if (!(flag & OCFS2_INLINE_XATTR_FL)) {
-		ret = ocfs2_journal_dirty(handle, xs->xattr_bh);
-		if (ret < 0) {
+	/* Don't worry, we are never called with !xi_value and !xl_entry */
+	if (!xi->xi_value) {
+		ret = ocfs2_xa_remove(loc, ctxt);
+		goto out_dirty;
+	}
+
+	ret = ocfs2_xa_prepare_entry(loc, xi, name_hash, ctxt);
+	if (ret) {
+		if (ret != -ENOSPC)
 			mlog_errno(ret);
-			goto out;
-		}
+		goto out_dirty;
 	}
 
-	if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) &&
-	    (flag & OCFS2_INLINE_XATTR_FL)) {
-		struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-		unsigned int xattrsize = osb->s_xattr_inline_size;
-
-		/*
-		 * Adjust extent record count or inline data size
-		 * to reserve space for extended attribute.
-		 */
-		if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
-			struct ocfs2_inline_data *idata = &di->id2.i_data;
-			le16_add_cpu(&idata->id_count, -xattrsize);
-		} else if (!(ocfs2_inode_is_fast_symlink(inode))) {
-			struct ocfs2_extent_list *el = &di->id2.i_list;
-			le16_add_cpu(&el->l_count, -(xattrsize /
-					sizeof(struct ocfs2_extent_rec)));
-		}
-		di->i_xattr_inline_size = cpu_to_le16(xattrsize);
-	}
-	/* Update xattr flag */
-	spin_lock(&oi->ip_lock);
-	oi->ip_dyn_features |= flag;
-	di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);
-	spin_unlock(&oi->ip_lock);
-
-	ret = ocfs2_journal_dirty(handle, xs->inode_bh);
-	if (ret < 0)
+	ret = ocfs2_xa_store_value(loc, xi, ctxt);
+	if (ret)
 		mlog_errno(ret);
 
-	if (!ret && xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
-		/*
-		 * Set value outside in B tree.
-		 * This is the second step for value size > INLINE_SIZE.
-		 */
-		size_t offs = le16_to_cpu(xs->here->xe_name_offset);
-		ret = ocfs2_xattr_set_value_outside(inode, xi, xs, ctxt,
-						    &vb, offs);
-		if (ret < 0) {
-			int ret2;
+out_dirty:
+	ocfs2_xa_journal_dirty(ctxt->handle, loc);
 
-			mlog_errno(ret);
-			/*
-			 * If set value outside failed, we have to clean
-			 * the junk tree root we have already set in local.
-			 */
-			ret2 = ocfs2_xattr_cleanup(inode, ctxt->handle,
-						   xi, xs, &vb, offs);
-			if (ret2 < 0)
-				mlog_errno(ret2);
-		}
-	}
 out:
 	return ret;
 }
 
+static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc,
+				     struct inode *inode,
+				     struct buffer_head *bh,
+				     struct ocfs2_xattr_entry *entry)
+{
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data;
+
+	BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_XATTR_FL));
+
+	loc->xl_inode = inode;
+	loc->xl_ops = &ocfs2_xa_block_loc_ops;
+	loc->xl_storage = bh;
+	loc->xl_entry = entry;
+	loc->xl_size = le16_to_cpu(di->i_xattr_inline_size);
+	loc->xl_header =
+		(struct ocfs2_xattr_header *)(bh->b_data + bh->b_size -
+					      loc->xl_size);
+}
+
+static void ocfs2_init_xattr_block_xa_loc(struct ocfs2_xa_loc *loc,
+					  struct inode *inode,
+					  struct buffer_head *bh,
+					  struct ocfs2_xattr_entry *entry)
+{
+	struct ocfs2_xattr_block *xb =
+		(struct ocfs2_xattr_block *)bh->b_data;
+
+	BUG_ON(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED);
+
+	loc->xl_inode = inode;
+	loc->xl_ops = &ocfs2_xa_block_loc_ops;
+	loc->xl_storage = bh;
+	loc->xl_header = &(xb->xb_attrs.xb_header);
+	loc->xl_entry = entry;
+	loc->xl_size = bh->b_size - offsetof(struct ocfs2_xattr_block,
+					     xb_attrs.xb_header);
+}
+
+static void ocfs2_init_xattr_bucket_xa_loc(struct ocfs2_xa_loc *loc,
+					   struct ocfs2_xattr_bucket *bucket,
+					   struct ocfs2_xattr_entry *entry)
+{
+	loc->xl_inode = bucket->bu_inode;
+	loc->xl_ops = &ocfs2_xa_bucket_loc_ops;
+	loc->xl_storage = bucket;
+	loc->xl_header = bucket_xh(bucket);
+	loc->xl_entry = entry;
+	loc->xl_size = OCFS2_XATTR_BUCKET_SIZE;
+}
+
 /*
  * In xattr remove, if it is stored outside and refcounted, we may have
  * the chance to split the refcount tree. So need the allocators.
@@ -2149,6 +2683,55 @@
 	return 0;
 }
 
+static int ocfs2_xattr_ibody_init(struct inode *inode,
+				  struct buffer_head *di_bh,
+				  struct ocfs2_xattr_set_ctxt *ctxt)
+{
+	int ret;
+	struct ocfs2_inode_info *oi = OCFS2_I(inode);
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
+	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	unsigned int xattrsize = osb->s_xattr_inline_size;
+
+	if (!ocfs2_xattr_has_space_inline(inode, di)) {
+		ret = -ENOSPC;
+		goto out;
+	}
+
+	ret = ocfs2_journal_access_di(ctxt->handle, INODE_CACHE(inode), di_bh,
+				      OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	/*
+	 * Adjust extent record count or inline data size
+	 * to reserve space for extended attribute.
+	 */
+	if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
+		struct ocfs2_inline_data *idata = &di->id2.i_data;
+		le16_add_cpu(&idata->id_count, -xattrsize);
+	} else if (!(ocfs2_inode_is_fast_symlink(inode))) {
+		struct ocfs2_extent_list *el = &di->id2.i_list;
+		le16_add_cpu(&el->l_count, -(xattrsize /
+					     sizeof(struct ocfs2_extent_rec)));
+	}
+	di->i_xattr_inline_size = cpu_to_le16(xattrsize);
+
+	spin_lock(&oi->ip_lock);
+	oi->ip_dyn_features |= OCFS2_INLINE_XATTR_FL|OCFS2_HAS_XATTR_FL;
+	di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);
+	spin_unlock(&oi->ip_lock);
+
+	ret = ocfs2_journal_dirty(ctxt->handle, di_bh);
+	if (ret < 0)
+		mlog_errno(ret);
+
+out:
+	return ret;
+}
+
 /*
  * ocfs2_xattr_ibody_set()
  *
@@ -2160,9 +2743,10 @@
 				 struct ocfs2_xattr_search *xs,
 				 struct ocfs2_xattr_set_ctxt *ctxt)
 {
+	int ret;
 	struct ocfs2_inode_info *oi = OCFS2_I(inode);
 	struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data;
-	int ret;
+	struct ocfs2_xa_loc loc;
 
 	if (inode->i_sb->s_blocksize == OCFS2_MIN_BLOCKSIZE)
 		return -ENOSPC;
@@ -2175,8 +2759,25 @@
 		}
 	}
 
-	ret = ocfs2_xattr_set_entry(inode, xi, xs, ctxt,
-				(OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL));
+	if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL)) {
+		ret = ocfs2_xattr_ibody_init(inode, xs->inode_bh, ctxt);
+		if (ret) {
+			if (ret != -ENOSPC)
+				mlog_errno(ret);
+			goto out;
+		}
+	}
+
+	ocfs2_init_dinode_xa_loc(&loc, inode, xs->inode_bh,
+				 xs->not_found ? NULL : xs->here);
+	ret = ocfs2_xa_set(&loc, xi, ctxt);
+	if (ret) {
+		if (ret != -ENOSPC)
+			mlog_errno(ret);
+		goto out;
+	}
+	xs->here = loc.xl_entry;
+
 out:
 	up_write(&oi->ip_alloc_sem);
 
@@ -2236,12 +2837,11 @@
 	return ret;
 }
 
-static int ocfs2_create_xattr_block(handle_t *handle,
-				    struct inode *inode,
+static int ocfs2_create_xattr_block(struct inode *inode,
 				    struct buffer_head *inode_bh,
-				    struct ocfs2_alloc_context *meta_ac,
-				    struct buffer_head **ret_bh,
-				    int indexed)
+				    struct ocfs2_xattr_set_ctxt *ctxt,
+				    int indexed,
+				    struct buffer_head **ret_bh)
 {
 	int ret;
 	u16 suballoc_bit_start;
@@ -2252,14 +2852,14 @@
 	struct buffer_head *new_bh = NULL;
 	struct ocfs2_xattr_block *xblk;
 
-	ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), inode_bh,
-				      OCFS2_JOURNAL_ACCESS_CREATE);
+	ret = ocfs2_journal_access_di(ctxt->handle, INODE_CACHE(inode),
+				      inode_bh, OCFS2_JOURNAL_ACCESS_CREATE);
 	if (ret < 0) {
 		mlog_errno(ret);
 		goto end;
 	}
 
-	ret = ocfs2_claim_metadata(osb, handle, meta_ac, 1,
+	ret = ocfs2_claim_metadata(osb, ctxt->handle, ctxt->meta_ac, 1,
 				   &suballoc_bit_start, &num_got,
 				   &first_blkno);
 	if (ret < 0) {
@@ -2270,7 +2870,7 @@
 	new_bh = sb_getblk(inode->i_sb, first_blkno);
 	ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), new_bh);
 
-	ret = ocfs2_journal_access_xb(handle, INODE_CACHE(inode),
+	ret = ocfs2_journal_access_xb(ctxt->handle, INODE_CACHE(inode),
 				      new_bh,
 				      OCFS2_JOURNAL_ACCESS_CREATE);
 	if (ret < 0) {
@@ -2282,11 +2882,10 @@
 	xblk = (struct ocfs2_xattr_block *)new_bh->b_data;
 	memset(xblk, 0, inode->i_sb->s_blocksize);
 	strcpy((void *)xblk, OCFS2_XATTR_BLOCK_SIGNATURE);
-	xblk->xb_suballoc_slot = cpu_to_le16(osb->slot_num);
+	xblk->xb_suballoc_slot = cpu_to_le16(ctxt->meta_ac->ac_alloc_slot);
 	xblk->xb_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 	xblk->xb_fs_generation = cpu_to_le32(osb->fs_generation);
 	xblk->xb_blkno = cpu_to_le64(first_blkno);
-
 	if (indexed) {
 		struct ocfs2_xattr_tree_root *xr = &xblk->xb_attrs.xb_root;
 		xr->xt_clusters = cpu_to_le32(1);
@@ -2297,14 +2896,17 @@
 		xr->xt_list.l_next_free_rec = cpu_to_le16(1);
 		xblk->xb_flags = cpu_to_le16(OCFS2_XATTR_INDEXED);
 	}
+	ocfs2_journal_dirty(ctxt->handle, new_bh);
 
-	ret = ocfs2_journal_dirty(handle, new_bh);
-	if (ret < 0) {
-		mlog_errno(ret);
-		goto end;
-	}
+	/* Add it to the inode */
 	di->i_xattr_loc = cpu_to_le64(first_blkno);
-	ocfs2_journal_dirty(handle, inode_bh);
+
+	spin_lock(&OCFS2_I(inode)->ip_lock);
+	OCFS2_I(inode)->ip_dyn_features |= OCFS2_HAS_XATTR_FL;
+	di->i_dyn_features = cpu_to_le16(OCFS2_I(inode)->ip_dyn_features);
+	spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+	ocfs2_journal_dirty(ctxt->handle, inode_bh);
 
 	*ret_bh = new_bh;
 	new_bh = NULL;
@@ -2326,13 +2928,13 @@
 				 struct ocfs2_xattr_set_ctxt *ctxt)
 {
 	struct buffer_head *new_bh = NULL;
-	handle_t *handle = ctxt->handle;
 	struct ocfs2_xattr_block *xblk = NULL;
 	int ret;
+	struct ocfs2_xa_loc loc;
 
 	if (!xs->xattr_bh) {
-		ret = ocfs2_create_xattr_block(handle, inode, xs->inode_bh,
-					       ctxt->meta_ac, &new_bh, 0);
+		ret = ocfs2_create_xattr_block(inode, xs->inode_bh, ctxt,
+					       0, &new_bh);
 		if (ret) {
 			mlog_errno(ret);
 			goto end;
@@ -2348,21 +2950,25 @@
 		xblk = (struct ocfs2_xattr_block *)xs->xattr_bh->b_data;
 
 	if (!(le16_to_cpu(xblk->xb_flags) & OCFS2_XATTR_INDEXED)) {
-		/* Set extended attribute into external block */
-		ret = ocfs2_xattr_set_entry(inode, xi, xs, ctxt,
-					    OCFS2_HAS_XATTR_FL);
-		if (!ret || ret != -ENOSPC)
-			goto end;
+		ocfs2_init_xattr_block_xa_loc(&loc, inode, xs->xattr_bh,
+					      xs->not_found ? NULL : xs->here);
 
-		ret = ocfs2_xattr_create_index_block(inode, xs, ctxt);
-		if (ret)
+		ret = ocfs2_xa_set(&loc, xi, ctxt);
+		if (!ret)
+			xs->here = loc.xl_entry;
+		else if (ret != -ENOSPC)
 			goto end;
+		else {
+			ret = ocfs2_xattr_create_index_block(inode, xs, ctxt);
+			if (ret)
+				goto end;
+		}
 	}
 
-	ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs, ctxt);
+	if (le16_to_cpu(xblk->xb_flags) & OCFS2_XATTR_INDEXED)
+		ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs, ctxt);
 
 end:
-
 	return ret;
 }
 
@@ -2371,7 +2977,6 @@
 				       struct ocfs2_xattr_info *xi,
 				       struct ocfs2_xattr_search *xs)
 {
-	u64 value_size;
 	struct ocfs2_xattr_entry *last;
 	int free, i;
 	size_t min_offs = xs->end - xs->base;
@@ -2394,13 +2999,7 @@
 
 	BUG_ON(!xs->not_found);
 
-	if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
-		value_size = OCFS2_XATTR_ROOT_SIZE;
-	else
-		value_size = OCFS2_XATTR_SIZE(xi->value_len);
-
-	if (free >= sizeof(struct ocfs2_xattr_entry) +
-		   OCFS2_XATTR_SIZE(strlen(xi->name)) + value_size)
+	if (free >= (sizeof(struct ocfs2_xattr_entry) + namevalue_size_xi(xi)))
 		return 1;
 
 	return 0;
@@ -2424,7 +3023,7 @@
 	char *base = NULL;
 	int name_offset, name_len = 0;
 	u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb,
-						    xi->value_len);
+						    xi->xi_value_len);
 	u64 value_size;
 
 	/*
@@ -2432,14 +3031,14 @@
 	 * No matter whether we replace an old one or add a new one,
 	 * we need this for writing.
 	 */
-	if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
+	if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE)
 		credits += new_clusters *
 			   ocfs2_clusters_to_blocks(inode->i_sb, 1);
 
 	if (xis->not_found && xbs->not_found) {
 		credits += ocfs2_blocks_per_xattr_bucket(inode->i_sb);
 
-		if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+		if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
 			clusters_add += new_clusters;
 			credits += ocfs2_calc_extend_credits(inode->i_sb,
 							&def_xv.xv.xr_list,
@@ -2484,7 +3083,7 @@
 	 * The credits for removing the value tree will be extended
 	 * by ocfs2_remove_extent itself.
 	 */
-	if (!xi->value) {
+	if (!xi->xi_value) {
 		if (!ocfs2_xattr_is_local(xe))
 			credits += ocfs2_remove_extent_credits(inode->i_sb);
 
@@ -2514,7 +3113,7 @@
 		}
 	}
 
-	if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) {
+	if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE) {
 		/* the new values will be stored outside. */
 		u32 old_clusters = 0;
 
@@ -2547,9 +3146,10 @@
 		 * value, we don't need any allocation, otherwise we have
 		 * to guess metadata allocation.
 		 */
-		if ((ocfs2_xattr_is_local(xe) && value_size >= xi->value_len) ||
+		if ((ocfs2_xattr_is_local(xe) &&
+		     (value_size >= xi->xi_value_len)) ||
 		    (!ocfs2_xattr_is_local(xe) &&
-		     OCFS2_XATTR_ROOT_SIZE >= xi->value_len))
+		     OCFS2_XATTR_ROOT_SIZE >= xi->xi_value_len))
 			goto out;
 	}
 
@@ -2639,7 +3239,7 @@
 
 	meta_add += extra_meta;
 	mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d, "
-	     "credits = %d\n", xi->name, meta_add, clusters_add, *credits);
+	     "credits = %d\n", xi->xi_name, meta_add, clusters_add, *credits);
 
 	if (meta_add) {
 		ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add,
@@ -2679,7 +3279,7 @@
 {
 	int ret = 0, credits, old_found;
 
-	if (!xi->value) {
+	if (!xi->xi_value) {
 		/* Remove existing extended attribute */
 		if (!xis->not_found)
 			ret = ocfs2_xattr_ibody_set(inode, xi, xis, ctxt);
@@ -2693,8 +3293,8 @@
 			 * If succeed and that extended attribute existing in
 			 * external block, then we will remove it.
 			 */
-			xi->value = NULL;
-			xi->value_len = 0;
+			xi->xi_value = NULL;
+			xi->xi_value_len = 0;
 
 			old_found = xis->not_found;
 			xis->not_found = -ENODATA;
@@ -2722,8 +3322,8 @@
 		} else if (ret == -ENOSPC) {
 			if (di->i_xattr_loc && !xbs->xattr_bh) {
 				ret = ocfs2_xattr_block_find(inode,
-							     xi->name_index,
-							     xi->name, xbs);
+							     xi->xi_name_index,
+							     xi->xi_name, xbs);
 				if (ret)
 					goto out;
 
@@ -2762,8 +3362,8 @@
 				 * If succeed and that extended attribute
 				 * existing in inode, we will remove it.
 				 */
-				xi->value = NULL;
-				xi->value_len = 0;
+				xi->xi_value = NULL;
+				xi->xi_value_len = 0;
 				xbs->not_found = -ENODATA;
 				ret = ocfs2_calc_xattr_set_need(inode,
 								di,
@@ -2829,10 +3429,11 @@
 	int ret;
 
 	struct ocfs2_xattr_info xi = {
-		.name_index = name_index,
-		.name = name,
-		.value = value,
-		.value_len = value_len,
+		.xi_name_index = name_index,
+		.xi_name = name,
+		.xi_name_len = strlen(name),
+		.xi_value = value,
+		.xi_value_len = value_len,
 	};
 
 	struct ocfs2_xattr_search xis = {
@@ -2912,10 +3513,11 @@
 	struct ocfs2_refcount_tree *ref_tree = NULL;
 
 	struct ocfs2_xattr_info xi = {
-		.name_index = name_index,
-		.name = name,
-		.value = value,
-		.value_len = value_len,
+		.xi_name_index = name_index,
+		.xi_name = name,
+		.xi_name_len = strlen(name),
+		.xi_value = value,
+		.xi_value_len = value_len,
 	};
 
 	struct ocfs2_xattr_search xis = {
@@ -3759,7 +4361,7 @@
 				     struct ocfs2_xattr_bucket *bucket)
 {
 	int ret, i;
-	size_t end, offset, len, value_len;
+	size_t end, offset, len;
 	struct ocfs2_xattr_header *xh;
 	char *entries, *buf, *bucket_buf = NULL;
 	u64 blkno = bucket_blkno(bucket);
@@ -3813,12 +4415,7 @@
 	end = OCFS2_XATTR_BUCKET_SIZE;
 	for (i = 0; i < le16_to_cpu(xh->xh_count); i++, xe++) {
 		offset = le16_to_cpu(xe->xe_name_offset);
-		if (ocfs2_xattr_is_local(xe))
-			value_len = OCFS2_XATTR_SIZE(
-					le64_to_cpu(xe->xe_value_size));
-		else
-			value_len = OCFS2_XATTR_ROOT_SIZE;
-		len = OCFS2_XATTR_SIZE(xe->xe_name_len) + value_len;
+		len = namevalue_size_xe(xe);
 
 		/*
 		 * We must make sure that the name/value pair
@@ -4007,7 +4604,7 @@
 				    int new_bucket_head)
 {
 	int ret, i;
-	int count, start, len, name_value_len = 0, xe_len, name_offset = 0;
+	int count, start, len, name_value_len = 0, name_offset = 0;
 	struct ocfs2_xattr_bucket *s_bucket = NULL, *t_bucket = NULL;
 	struct ocfs2_xattr_header *xh;
 	struct ocfs2_xattr_entry *xe;
@@ -4098,13 +4695,7 @@
 	name_value_len = 0;
 	for (i = 0; i < start; i++) {
 		xe = &xh->xh_entries[i];
-		xe_len = OCFS2_XATTR_SIZE(xe->xe_name_len);
-		if (ocfs2_xattr_is_local(xe))
-			xe_len +=
-			   OCFS2_XATTR_SIZE(le64_to_cpu(xe->xe_value_size));
-		else
-			xe_len += OCFS2_XATTR_ROOT_SIZE;
-		name_value_len += xe_len;
+		name_value_len += namevalue_size_xe(xe);
 		if (le16_to_cpu(xe->xe_name_offset) < name_offset)
 			name_offset = le16_to_cpu(xe->xe_name_offset);
 	}
@@ -4134,12 +4725,6 @@
 	xh->xh_free_start = cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE);
 	for (i = 0; i < le16_to_cpu(xh->xh_count); i++) {
 		xe = &xh->xh_entries[i];
-		xe_len = OCFS2_XATTR_SIZE(xe->xe_name_len);
-		if (ocfs2_xattr_is_local(xe))
-			xe_len +=
-			   OCFS2_XATTR_SIZE(le64_to_cpu(xe->xe_value_size));
-		else
-			xe_len += OCFS2_XATTR_ROOT_SIZE;
 		if (le16_to_cpu(xe->xe_name_offset) <
 		    le16_to_cpu(xh->xh_free_start))
 			xh->xh_free_start = xe->xe_name_offset;
@@ -4751,195 +5336,6 @@
 }
 
 /*
- * Handle the normal xattr set, including replace, delete and new.
- *
- * Note: "local" indicates the real data's locality. So we can't
- * just its bucket locality by its length.
- */
-static void ocfs2_xattr_set_entry_normal(struct inode *inode,
-					 struct ocfs2_xattr_info *xi,
-					 struct ocfs2_xattr_search *xs,
-					 u32 name_hash,
-					 int local)
-{
-	struct ocfs2_xattr_entry *last, *xe;
-	int name_len = strlen(xi->name);
-	struct ocfs2_xattr_header *xh = xs->header;
-	u16 count = le16_to_cpu(xh->xh_count), start;
-	size_t blocksize = inode->i_sb->s_blocksize;
-	char *val;
-	size_t offs, size, new_size;
-
-	last = &xh->xh_entries[count];
-	if (!xs->not_found) {
-		xe = xs->here;
-		offs = le16_to_cpu(xe->xe_name_offset);
-		if (ocfs2_xattr_is_local(xe))
-			size = OCFS2_XATTR_SIZE(name_len) +
-			OCFS2_XATTR_SIZE(le64_to_cpu(xe->xe_value_size));
-		else
-			size = OCFS2_XATTR_SIZE(name_len) +
-			OCFS2_XATTR_SIZE(OCFS2_XATTR_ROOT_SIZE);
-
-		/*
-		 * If the new value will be stored outside, xi->value has been
-		 * initalized as an empty ocfs2_xattr_value_root, and the same
-		 * goes with xi->value_len, so we can set new_size safely here.
-		 * See ocfs2_xattr_set_in_bucket.
-		 */
-		new_size = OCFS2_XATTR_SIZE(name_len) +
-			   OCFS2_XATTR_SIZE(xi->value_len);
-
-		le16_add_cpu(&xh->xh_name_value_len, -size);
-		if (xi->value) {
-			if (new_size > size)
-				goto set_new_name_value;
-
-			/* Now replace the old value with new one. */
-			if (local)
-				xe->xe_value_size = cpu_to_le64(xi->value_len);
-			else
-				xe->xe_value_size = 0;
-
-			val = ocfs2_xattr_bucket_get_val(inode,
-							 xs->bucket, offs);
-			memset(val + OCFS2_XATTR_SIZE(name_len), 0,
-			       size - OCFS2_XATTR_SIZE(name_len));
-			if (OCFS2_XATTR_SIZE(xi->value_len) > 0)
-				memcpy(val + OCFS2_XATTR_SIZE(name_len),
-				       xi->value, xi->value_len);
-
-			le16_add_cpu(&xh->xh_name_value_len, new_size);
-			ocfs2_xattr_set_local(xe, local);
-			return;
-		} else {
-			/*
-			 * Remove the old entry if there is more than one.
-			 * We don't remove the last entry so that we can
-			 * use it to indicate the hash value of the empty
-			 * bucket.
-			 */
-			last -= 1;
-			le16_add_cpu(&xh->xh_count, -1);
-			if (xh->xh_count) {
-				memmove(xe, xe + 1,
-					(void *)last - (void *)xe);
-				memset(last, 0,
-				       sizeof(struct ocfs2_xattr_entry));
-			} else
-				xh->xh_free_start =
-					cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE);
-
-			return;
-		}
-	} else {
-		/* find a new entry for insert. */
-		int low = 0, high = count - 1, tmp;
-		struct ocfs2_xattr_entry *tmp_xe;
-
-		while (low <= high && count) {
-			tmp = (low + high) / 2;
-			tmp_xe = &xh->xh_entries[tmp];
-
-			if (name_hash > le32_to_cpu(tmp_xe->xe_name_hash))
-				low = tmp + 1;
-			else if (name_hash <
-				 le32_to_cpu(tmp_xe->xe_name_hash))
-				high = tmp - 1;
-			else {
-				low = tmp;
-				break;
-			}
-		}
-
-		xe = &xh->xh_entries[low];
-		if (low != count)
-			memmove(xe + 1, xe, (void *)last - (void *)xe);
-
-		le16_add_cpu(&xh->xh_count, 1);
-		memset(xe, 0, sizeof(struct ocfs2_xattr_entry));
-		xe->xe_name_hash = cpu_to_le32(name_hash);
-		xe->xe_name_len = name_len;
-		ocfs2_xattr_set_type(xe, xi->name_index);
-	}
-
-set_new_name_value:
-	/* Insert the new name+value. */
-	size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_SIZE(xi->value_len);
-
-	/*
-	 * We must make sure that the name/value pair
-	 * exists in the same block.
-	 */
-	offs = le16_to_cpu(xh->xh_free_start);
-	start = offs - size;
-
-	if (start >> inode->i_sb->s_blocksize_bits !=
-	    (offs - 1) >> inode->i_sb->s_blocksize_bits) {
-		offs = offs - offs % blocksize;
-		xh->xh_free_start = cpu_to_le16(offs);
-	}
-
-	val = ocfs2_xattr_bucket_get_val(inode, xs->bucket, offs - size);
-	xe->xe_name_offset = cpu_to_le16(offs - size);
-
-	memset(val, 0, size);
-	memcpy(val, xi->name, name_len);
-	memcpy(val + OCFS2_XATTR_SIZE(name_len), xi->value, xi->value_len);
-
-	xe->xe_value_size = cpu_to_le64(xi->value_len);
-	ocfs2_xattr_set_local(xe, local);
-	xs->here = xe;
-	le16_add_cpu(&xh->xh_free_start, -size);
-	le16_add_cpu(&xh->xh_name_value_len, size);
-
-	return;
-}
-
-/*
- * Set the xattr entry in the specified bucket.
- * The bucket is indicated by xs->bucket and it should have the enough
- * space for the xattr insertion.
- */
-static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode,
-					   handle_t *handle,
-					   struct ocfs2_xattr_info *xi,
-					   struct ocfs2_xattr_search *xs,
-					   u32 name_hash,
-					   int local)
-{
-	int ret;
-	u64 blkno;
-
-	mlog(0, "Set xattr entry len = %lu index = %d in bucket %llu\n",
-	     (unsigned long)xi->value_len, xi->name_index,
-	     (unsigned long long)bucket_blkno(xs->bucket));
-
-	if (!xs->bucket->bu_bhs[1]) {
-		blkno = bucket_blkno(xs->bucket);
-		ocfs2_xattr_bucket_relse(xs->bucket);
-		ret = ocfs2_read_xattr_bucket(xs->bucket, blkno);
-		if (ret) {
-			mlog_errno(ret);
-			goto out;
-		}
-	}
-
-	ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket,
-						OCFS2_JOURNAL_ACCESS_WRITE);
-	if (ret < 0) {
-		mlog_errno(ret);
-		goto out;
-	}
-
-	ocfs2_xattr_set_entry_normal(inode, xi, xs, name_hash, local);
-	ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket);
-
-out:
-	return ret;
-}
-
-/*
  * Truncate the specified xe_off entry in xattr bucket.
  * bucket is indicated by header_bh and len is the new length.
  * Both the ocfs2_xattr_value_root and the entry will be updated here.
@@ -5009,66 +5405,6 @@
 	return ret;
 }
 
-static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode,
-					struct ocfs2_xattr_search *xs,
-					int len,
-					struct ocfs2_xattr_set_ctxt *ctxt)
-{
-	int ret, offset;
-	struct ocfs2_xattr_entry *xe = xs->here;
-	struct ocfs2_xattr_header *xh = (struct ocfs2_xattr_header *)xs->base;
-
-	BUG_ON(!xs->bucket->bu_bhs[0] || !xe || ocfs2_xattr_is_local(xe));
-
-	offset = xe - xh->xh_entries;
-	ret = ocfs2_xattr_bucket_value_truncate(inode, xs->bucket,
-						offset, len, ctxt);
-	if (ret)
-		mlog_errno(ret);
-
-	return ret;
-}
-
-static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode,
-						handle_t *handle,
-						struct ocfs2_xattr_search *xs,
-						char *val,
-						int value_len)
-{
-	int ret, offset, block_off;
-	struct ocfs2_xattr_value_root *xv;
-	struct ocfs2_xattr_entry *xe = xs->here;
-	struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket);
-	void *base;
-	struct ocfs2_xattr_value_buf vb = {
-		.vb_access = ocfs2_journal_access,
-	};
-
-	BUG_ON(!xs->base || !xe || ocfs2_xattr_is_local(xe));
-
-	ret = ocfs2_xattr_bucket_get_name_value(inode->i_sb, xh,
-						xe - xh->xh_entries,
-						&block_off,
-						&offset);
-	if (ret) {
-		mlog_errno(ret);
-		goto out;
-	}
-
-	base = bucket_block(xs->bucket, block_off);
-	xv = (struct ocfs2_xattr_value_root *)(base + offset +
-		 OCFS2_XATTR_SIZE(xe->xe_name_len));
-
-	vb.vb_xv = xv;
-	vb.vb_bh = xs->bucket->bu_bhs[block_off];
-	ret = __ocfs2_xattr_set_value_outside(inode, handle,
-					      &vb, val, value_len);
-	if (ret)
-		mlog_errno(ret);
-out:
-	return ret;
-}
-
 static int ocfs2_rm_xattr_cluster(struct inode *inode,
 				  struct buffer_head *root_bh,
 				  u64 blkno,
@@ -5167,128 +5503,6 @@
 	return ret;
 }
 
-static void ocfs2_xattr_bucket_remove_xs(struct inode *inode,
-					 handle_t *handle,
-					 struct ocfs2_xattr_search *xs)
-{
-	struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket);
-	struct ocfs2_xattr_entry *last = &xh->xh_entries[
-						le16_to_cpu(xh->xh_count) - 1];
-	int ret = 0;
-
-	ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket,
-						OCFS2_JOURNAL_ACCESS_WRITE);
-	if (ret) {
-		mlog_errno(ret);
-		return;
-	}
-
-	/* Remove the old entry. */
-	memmove(xs->here, xs->here + 1,
-		(void *)last - (void *)xs->here);
-	memset(last, 0, sizeof(struct ocfs2_xattr_entry));
-	le16_add_cpu(&xh->xh_count, -1);
-
-	ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket);
-}
-
-/*
- * Set the xattr name/value in the bucket specified in xs.
- *
- * As the new value in xi may be stored in the bucket or in an outside cluster,
- * we divide the whole process into 3 steps:
- * 1. insert name/value in the bucket(ocfs2_xattr_set_entry_in_bucket)
- * 2. truncate of the outside cluster(ocfs2_xattr_bucket_value_truncate_xs)
- * 3. Set the value to the outside cluster(ocfs2_xattr_bucket_set_value_outside)
- * 4. If the clusters for the new outside value can't be allocated, we need
- *    to free the xattr we allocated in set.
- */
-static int ocfs2_xattr_set_in_bucket(struct inode *inode,
-				     struct ocfs2_xattr_info *xi,
-				     struct ocfs2_xattr_search *xs,
-				     struct ocfs2_xattr_set_ctxt *ctxt)
-{
-	int ret, local = 1;
-	size_t value_len;
-	char *val = (char *)xi->value;
-	struct ocfs2_xattr_entry *xe = xs->here;
-	u32 name_hash = ocfs2_xattr_name_hash(inode, xi->name,
-					      strlen(xi->name));
-
-	if (!xs->not_found && !ocfs2_xattr_is_local(xe)) {
-		/*
-		 * We need to truncate the xattr storage first.
-		 *
-		 * If both the old and new value are stored to
-		 * outside block, we only need to truncate
-		 * the storage and then set the value outside.
-		 *
-		 * If the new value should be stored within block,
-		 * we should free all the outside block first and
-		 * the modification to the xattr block will be done
-		 * by following steps.
-		 */
-		if (xi->value_len > OCFS2_XATTR_INLINE_SIZE)
-			value_len = xi->value_len;
-		else
-			value_len = 0;
-
-		ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
-							   value_len,
-							   ctxt);
-		if (ret)
-			goto out;
-
-		if (value_len)
-			goto set_value_outside;
-	}
-
-	value_len = xi->value_len;
-	/* So we have to handle the inside block change now. */
-	if (value_len > OCFS2_XATTR_INLINE_SIZE) {
-		/*
-		 * If the new value will be stored outside of block,
-		 * initalize a new empty value root and insert it first.
-		 */
-		local = 0;
-		xi->value = &def_xv;
-		xi->value_len = OCFS2_XATTR_ROOT_SIZE;
-	}
-
-	ret = ocfs2_xattr_set_entry_in_bucket(inode, ctxt->handle, xi, xs,
-					      name_hash, local);
-	if (ret) {
-		mlog_errno(ret);
-		goto out;
-	}
-
-	if (value_len <= OCFS2_XATTR_INLINE_SIZE)
-		goto out;
-
-	/* allocate the space now for the outside block storage. */
-	ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs,
-						   value_len, ctxt);
-	if (ret) {
-		mlog_errno(ret);
-
-		if (xs->not_found) {
-			/*
-			 * We can't allocate enough clusters for outside
-			 * storage and we have allocated xattr already,
-			 * so need to remove it.
-			 */
-			ocfs2_xattr_bucket_remove_xs(inode, ctxt->handle, xs);
-		}
-		goto out;
-	}
-
-set_value_outside:
-	ret = ocfs2_xattr_bucket_set_value_outside(inode, ctxt->handle,
-						   xs, val, value_len);
-out:
-	return ret;
-}
-
 /*
  * check whether the xattr bucket is filled up with the same hash value.
  * If we want to insert the xattr with the same hash, return -ENOSPC.
@@ -5317,156 +5531,116 @@
 	return 0;
 }
 
+/*
+ * Try to set the entry in the current bucket.  If we fail, the caller
+ * will handle getting us another bucket.
+ */
+static int ocfs2_xattr_set_entry_bucket(struct inode *inode,
+					struct ocfs2_xattr_info *xi,
+					struct ocfs2_xattr_search *xs,
+					struct ocfs2_xattr_set_ctxt *ctxt)
+{
+	int ret;
+	struct ocfs2_xa_loc loc;
+
+	mlog_entry("Set xattr %s in xattr bucket\n", xi->xi_name);
+
+	ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket,
+				       xs->not_found ? NULL : xs->here);
+	ret = ocfs2_xa_set(&loc, xi, ctxt);
+	if (!ret) {
+		xs->here = loc.xl_entry;
+		goto out;
+	}
+	if (ret != -ENOSPC) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	/* Ok, we need space.  Let's try defragmenting the bucket. */
+	ret = ocfs2_defrag_xattr_bucket(inode, ctxt->handle,
+					xs->bucket);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_xa_set(&loc, xi, ctxt);
+	if (!ret) {
+		xs->here = loc.xl_entry;
+		goto out;
+	}
+	if (ret != -ENOSPC)
+		mlog_errno(ret);
+
+
+out:
+	mlog_exit(ret);
+	return ret;
+}
+
 static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
 					     struct ocfs2_xattr_info *xi,
 					     struct ocfs2_xattr_search *xs,
 					     struct ocfs2_xattr_set_ctxt *ctxt)
 {
-	struct ocfs2_xattr_header *xh;
-	struct ocfs2_xattr_entry *xe;
-	u16 count, header_size, xh_free_start;
-	int free, max_free, need, old;
-	size_t value_size = 0, name_len = strlen(xi->name);
-	size_t blocksize = inode->i_sb->s_blocksize;
-	int ret, allocation = 0;
+	int ret;
 
-	mlog_entry("Set xattr %s in xattr index block\n", xi->name);
+	mlog_entry("Set xattr %s in xattr index block\n", xi->xi_name);
 
-try_again:
-	xh = xs->header;
-	count = le16_to_cpu(xh->xh_count);
-	xh_free_start = le16_to_cpu(xh->xh_free_start);
-	header_size = sizeof(struct ocfs2_xattr_header) +
-			count * sizeof(struct ocfs2_xattr_entry);
-	max_free = OCFS2_XATTR_BUCKET_SIZE - header_size -
-		le16_to_cpu(xh->xh_name_value_len) - OCFS2_XATTR_HEADER_GAP;
-
-	mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size "
-			"of %u which exceed block size\n",
-			(unsigned long long)bucket_blkno(xs->bucket),
-			header_size);
-
-	if (xi->value && xi->value_len > OCFS2_XATTR_INLINE_SIZE)
-		value_size = OCFS2_XATTR_ROOT_SIZE;
-	else if (xi->value)
-		value_size = OCFS2_XATTR_SIZE(xi->value_len);
-
-	if (xs->not_found)
-		need = sizeof(struct ocfs2_xattr_entry) +
-			OCFS2_XATTR_SIZE(name_len) + value_size;
-	else {
-		need = value_size + OCFS2_XATTR_SIZE(name_len);
-
-		/*
-		 * We only replace the old value if the new length is smaller
-		 * than the old one. Otherwise we will allocate new space in the
-		 * bucket to store it.
-		 */
-		xe = xs->here;
-		if (ocfs2_xattr_is_local(xe))
-			old = OCFS2_XATTR_SIZE(le64_to_cpu(xe->xe_value_size));
-		else
-			old = OCFS2_XATTR_SIZE(OCFS2_XATTR_ROOT_SIZE);
-
-		if (old >= value_size)
-			need = 0;
+	ret = ocfs2_xattr_set_entry_bucket(inode, xi, xs, ctxt);
+	if (!ret)
+		goto out;
+	if (ret != -ENOSPC) {
+		mlog_errno(ret);
+		goto out;
 	}
 
-	free = xh_free_start - header_size - OCFS2_XATTR_HEADER_GAP;
+	/* Ack, need more space.  Let's try to get another bucket! */
+
 	/*
-	 * We need to make sure the new name/value pair
-	 * can exist in the same block.
+	 * We do not allow for overlapping ranges between buckets. And
+	 * the maximum number of collisions we will allow for then is
+	 * one bucket's worth, so check it here whether we need to
+	 * add a new bucket for the insert.
 	 */
-	if (xh_free_start % blocksize < need)
-		free -= xh_free_start % blocksize;
-
-	mlog(0, "xs->not_found = %d, in xattr bucket %llu: free = %d, "
-	     "need = %d, max_free = %d, xh_free_start = %u, xh_name_value_len ="
-	     " %u\n", xs->not_found,
-	     (unsigned long long)bucket_blkno(xs->bucket),
-	     free, need, max_free, le16_to_cpu(xh->xh_free_start),
-	     le16_to_cpu(xh->xh_name_value_len));
-
-	if (free < need ||
-	    (xs->not_found &&
-	     count == ocfs2_xattr_max_xe_in_bucket(inode->i_sb))) {
-		if (need <= max_free &&
-		    count < ocfs2_xattr_max_xe_in_bucket(inode->i_sb)) {
-			/*
-			 * We can create the space by defragment. Since only the
-			 * name/value will be moved, the xe shouldn't be changed
-			 * in xs.
-			 */
-			ret = ocfs2_defrag_xattr_bucket(inode, ctxt->handle,
-							xs->bucket);
-			if (ret) {
-				mlog_errno(ret);
-				goto out;
-			}
-
-			xh_free_start = le16_to_cpu(xh->xh_free_start);
-			free = xh_free_start - header_size
-				- OCFS2_XATTR_HEADER_GAP;
-			if (xh_free_start % blocksize < need)
-				free -= xh_free_start % blocksize;
-
-			if (free >= need)
-				goto xattr_set;
-
-			mlog(0, "Can't get enough space for xattr insert by "
-			     "defragment. Need %u bytes, but we have %d, so "
-			     "allocate new bucket for it.\n", need, free);
-		}
-
-		/*
-		 * We have to add new buckets or clusters and one
-		 * allocation should leave us enough space for insert.
-		 */
-		BUG_ON(allocation);
-
-		/*
-		 * We do not allow for overlapping ranges between buckets. And
-		 * the maximum number of collisions we will allow for then is
-		 * one bucket's worth, so check it here whether we need to
-		 * add a new bucket for the insert.
-		 */
-		ret = ocfs2_check_xattr_bucket_collision(inode,
-							 xs->bucket,
-							 xi->name);
-		if (ret) {
-			mlog_errno(ret);
-			goto out;
-		}
-
-		ret = ocfs2_add_new_xattr_bucket(inode,
-						 xs->xattr_bh,
+	ret = ocfs2_check_xattr_bucket_collision(inode,
 						 xs->bucket,
-						 ctxt);
-		if (ret) {
-			mlog_errno(ret);
-			goto out;
-		}
-
-		/*
-		 * ocfs2_add_new_xattr_bucket() will have updated
-		 * xs->bucket if it moved, but it will not have updated
-		 * any of the other search fields.  Thus, we drop it and
-		 * re-search.  Everything should be cached, so it'll be
-		 * quick.
-		 */
-		ocfs2_xattr_bucket_relse(xs->bucket);
-		ret = ocfs2_xattr_index_block_find(inode, xs->xattr_bh,
-						   xi->name_index,
-						   xi->name, xs);
-		if (ret && ret != -ENODATA)
-			goto out;
-		xs->not_found = ret;
-		allocation = 1;
-		goto try_again;
+						 xi->xi_name);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
 	}
 
-xattr_set:
-	ret = ocfs2_xattr_set_in_bucket(inode, xi, xs, ctxt);
+	ret = ocfs2_add_new_xattr_bucket(inode,
+					 xs->xattr_bh,
+					 xs->bucket,
+					 ctxt);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	/*
+	 * ocfs2_add_new_xattr_bucket() will have updated
+	 * xs->bucket if it moved, but it will not have updated
+	 * any of the other search fields.  Thus, we drop it and
+	 * re-search.  Everything should be cached, so it'll be
+	 * quick.
+	 */
+	ocfs2_xattr_bucket_relse(xs->bucket);
+	ret = ocfs2_xattr_index_block_find(inode, xs->xattr_bh,
+					   xi->xi_name_index,
+					   xi->xi_name, xs);
+	if (ret && ret != -ENODATA)
+		goto out;
+	xs->not_found = ret;
+
+	/* Ok, we have a new bucket, let's try again */
+	ret = ocfs2_xattr_set_entry_bucket(inode, xi, xs, ctxt);
+	if (ret && (ret != -ENOSPC))
+		mlog_errno(ret);
+
 out:
 	mlog_exit(ret);
 	return ret;
@@ -5678,7 +5852,7 @@
 	 * refcount tree, and make the original extent become 3. So we will need
 	 * 2 * cluster more extent recs at most.
 	 */
-	if (!xi->value || xi->value_len <= OCFS2_XATTR_INLINE_SIZE) {
+	if (!xi->xi_value || xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE) {
 
 		ret = ocfs2_refcounted_xattr_delete_need(inode,
 							 &(*ref_tree)->rf_ci,
@@ -6354,9 +6528,11 @@
 					  int indexed)
 {
 	int ret;
-	handle_t *handle;
 	struct ocfs2_alloc_context *meta_ac;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_xattr_set_ctxt ctxt = {
+		.meta_ac = meta_ac,
+	};
 
 	ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
 	if (ret < 0) {
@@ -6364,21 +6540,21 @@
 		return ret;
 	}
 
-	handle = ocfs2_start_trans(osb, OCFS2_XATTR_BLOCK_CREATE_CREDITS);
-	if (IS_ERR(handle)) {
-		ret = PTR_ERR(handle);
+	ctxt.handle = ocfs2_start_trans(osb, OCFS2_XATTR_BLOCK_CREATE_CREDITS);
+	if (IS_ERR(ctxt.handle)) {
+		ret = PTR_ERR(ctxt.handle);
 		mlog_errno(ret);
 		goto out;
 	}
 
 	mlog(0, "create new xattr block for inode %llu, index = %d\n",
 	     (unsigned long long)fe_bh->b_blocknr, indexed);
-	ret = ocfs2_create_xattr_block(handle, inode, fe_bh,
-				       meta_ac, ret_bh, indexed);
+	ret = ocfs2_create_xattr_block(inode, fe_bh, &ctxt, indexed,
+				       ret_bh);
 	if (ret)
 		mlog_errno(ret);
 
-	ocfs2_commit_trans(osb, handle);
+	ocfs2_commit_trans(osb, ctxt.handle);
 out:
 	ocfs2_free_alloc_context(meta_ac);
 	return ret;
diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c
index f3b7c15..75d9b5b 100644
--- a/fs/omfs/inode.c
+++ b/fs/omfs/inode.c
@@ -11,6 +11,7 @@
 #include <linux/parser.h>
 #include <linux/buffer_head.h>
 #include <linux/vmalloc.h>
+#include <linux/writeback.h>
 #include <linux/crc-itu-t.h>
 #include "omfs.h"
 
@@ -89,7 +90,7 @@
 	oi->i_head.h_check_xor = xor;
 }
 
-static int omfs_write_inode(struct inode *inode, int wait)
+static int __omfs_write_inode(struct inode *inode, int wait)
 {
 	struct omfs_inode *oi;
 	struct omfs_sb_info *sbi = OMFS_SB(inode->i_sb);
@@ -162,9 +163,14 @@
 	return ret;
 }
 
+static int omfs_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+	return __omfs_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+}
+
 int omfs_sync_inode(struct inode *inode)
 {
-	return omfs_write_inode(inode, 1);
+	return __omfs_write_inode(inode, 1);
 }
 
 /*
diff --git a/fs/open.c b/fs/open.c
index 040cef7..e17f544 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -8,7 +8,6 @@
 #include <linux/mm.h>
 #include <linux/file.h>
 #include <linux/fdtable.h>
-#include <linux/quotaops.h>
 #include <linux/fsnotify.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -271,17 +270,15 @@
 	 * Make sure that there are no leases.  get_write_access() protects
 	 * against the truncate racing with a lease-granting setlease().
 	 */
-	error = break_lease(inode, FMODE_WRITE);
+	error = break_lease(inode, O_WRONLY);
 	if (error)
 		goto put_write_and_out;
 
 	error = locks_verify_truncate(inode, NULL, length);
 	if (!error)
 		error = security_path_truncate(&path, length, 0);
-	if (!error) {
-		vfs_dq_init(inode);
+	if (!error)
 		error = do_truncate(path.dentry, length, 0, NULL);
-	}
 
 put_write_and_out:
 	put_write_access(inode);
diff --git a/fs/pnode.c b/fs/pnode.c
index 8d5f392..5cc564a 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -86,7 +86,7 @@
 
 	/*
 	 * slave 'mnt' to a peer mount that has the
-	 * same root dentry. If none is available than
+	 * same root dentry. If none is available then
 	 * slave it to anything that is available.
 	 */
 	while ((peer_mnt = next_peer(peer_mnt)) != mnt &&
@@ -147,6 +147,11 @@
  * get the next mount in the propagation tree.
  * @m: the mount seen last
  * @origin: the original mount from where the tree walk initiated
+ *
+ * Note that peer groups form contiguous segments of slave lists.
+ * We rely on that in get_source() to be able to find out if
+ * vfsmount found while iterating with propagation_next() is
+ * a peer of one we'd found earlier.
  */
 static struct vfsmount *propagation_next(struct vfsmount *m,
 					 struct vfsmount *origin)
@@ -186,10 +191,6 @@
 {
 	struct vfsmount *p_last_src = NULL;
 	struct vfsmount *p_last_dest = NULL;
-	*type = CL_PROPAGATION;
-
-	if (IS_MNT_SHARED(dest))
-		*type |= CL_MAKE_SHARED;
 
 	while (last_dest != dest->mnt_master) {
 		p_last_dest = last_dest;
@@ -202,13 +203,18 @@
 		do {
 			p_last_dest = next_peer(p_last_dest);
 		} while (IS_MNT_NEW(p_last_dest));
+		/* is that a peer of the earlier? */
+		if (dest == p_last_dest) {
+			*type = CL_MAKE_SHARED;
+			return p_last_src;
+		}
 	}
-
-	if (dest != p_last_dest) {
-		*type |= CL_SLAVE;
-		return last_src;
-	} else
-		return p_last_src;
+	/* slave of the earlier, then */
+	*type = CL_SLAVE;
+	/* beginning of peer group among the slaves? */
+	if (IS_MNT_SHARED(dest))
+		*type |= CL_MAKE_SHARED;
+	return last_src;
 }
 
 /*
diff --git a/fs/pnode.h b/fs/pnode.h
index 958665d..1ea4ae1 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -21,12 +21,11 @@
 #define CL_SLAVE     		0x02
 #define CL_COPY_ALL 		0x04
 #define CL_MAKE_SHARED 		0x08
-#define CL_PROPAGATION 		0x10
-#define CL_PRIVATE 		0x20
+#define CL_PRIVATE 		0x10
 
 static inline void set_mnt_shared(struct vfsmount *mnt)
 {
-	mnt->mnt_flags &= ~MNT_PNODE_MASK;
+	mnt->mnt_flags &= ~MNT_SHARED_MASK;
 	mnt->mnt_flags |= MNT_SHARED;
 }
 
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 18e20fe..aa8637b 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -273,7 +273,7 @@
 		rcu_read_lock();  /* FIXME: is this correct? */
 		qsize = atomic_read(&__task_cred(p)->user->sigpending);
 		rcu_read_unlock();
-		qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
+		qlim = task_rlimit(p, RLIMIT_SIGPENDING);
 		unlock_task_sighand(p, &flags);
 	}
 
@@ -420,7 +420,7 @@
 		cutime = sig->cutime;
 		cstime = sig->cstime;
 		cgtime = sig->cgtime;
-		rsslim = sig->rlim[RLIMIT_RSS].rlim_cur;
+		rsslim = ACCESS_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
 
 		/* add up live thread stats at the group level */
 		if (whole) {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 623e2ff..a731084 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -647,17 +647,11 @@
 static unsigned mounts_poll(struct file *file, poll_table *wait)
 {
 	struct proc_mounts *p = file->private_data;
-	struct mnt_namespace *ns = p->ns;
 	unsigned res = POLLIN | POLLRDNORM;
 
-	poll_wait(file, &ns->poll, wait);
-
-	spin_lock(&vfsmount_lock);
-	if (p->event != ns->event) {
-		p->event = ns->event;
+	poll_wait(file, &p->ns->poll, wait);
+	if (mnt_had_events(p))
 		res |= POLLERR | POLLPRI;
-	}
-	spin_unlock(&vfsmount_lock);
 
 	return res;
 }
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 480cb10..08f4d71 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -291,19 +291,17 @@
  * returns the struct proc_dir_entry for "/proc/tty/driver", and
  * returns "serial" in residual.
  */
-static int xlate_proc_name(const char *name,
-			   struct proc_dir_entry **ret, const char **residual)
+static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
+			     const char **residual)
 {
 	const char     		*cp = name, *next;
 	struct proc_dir_entry	*de;
 	int			len;
-	int 			rtn = 0;
 
 	de = *ret;
 	if (!de)
 		de = &proc_root;
 
-	spin_lock(&proc_subdir_lock);
 	while (1) {
 		next = strchr(cp, '/');
 		if (!next)
@@ -315,16 +313,25 @@
 				break;
 		}
 		if (!de) {
-			rtn = -ENOENT;
-			goto out;
+			WARN(1, "name '%s'\n", name);
+			return -ENOENT;
 		}
 		cp += len + 1;
 	}
 	*residual = cp;
 	*ret = de;
-out:
+	return 0;
+}
+
+static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
+			   const char **residual)
+{
+	int rv;
+
+	spin_lock(&proc_subdir_lock);
+	rv = __xlate_proc_name(name, ret, residual);
 	spin_unlock(&proc_subdir_lock);
-	return rtn;
+	return rv;
 }
 
 static DEFINE_IDA(proc_inum_ida);
@@ -662,6 +669,7 @@
 	}
 	return ent;
 }
+EXPORT_SYMBOL(proc_symlink);
 
 struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
 		struct proc_dir_entry *parent)
@@ -700,6 +708,7 @@
 {
 	return proc_mkdir_mode(name, S_IRUGO | S_IXUGO, parent);
 }
+EXPORT_SYMBOL(proc_mkdir);
 
 struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
 					 struct proc_dir_entry *parent)
@@ -728,6 +737,7 @@
 	}
 	return ent;
 }
+EXPORT_SYMBOL(create_proc_entry);
 
 struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
 					struct proc_dir_entry *parent,
@@ -762,6 +772,7 @@
 out:
 	return NULL;
 }
+EXPORT_SYMBOL(proc_create_data);
 
 static void free_proc_entry(struct proc_dir_entry *de)
 {
@@ -793,11 +804,13 @@
 	const char *fn = name;
 	int len;
 
-	if (xlate_proc_name(name, &parent, &fn) != 0)
+	spin_lock(&proc_subdir_lock);
+	if (__xlate_proc_name(name, &parent, &fn) != 0) {
+		spin_unlock(&proc_subdir_lock);
 		return;
+	}
 	len = strlen(fn);
 
-	spin_lock(&proc_subdir_lock);
 	for (p = &parent->subdir; *p; p=&(*p)->next ) {
 		if (proc_match(len, fn, *p)) {
 			de = *p;
@@ -807,8 +820,10 @@
 		}
 	}
 	spin_unlock(&proc_subdir_lock);
-	if (!de)
+	if (!de) {
+		WARN(1, "name '%s'\n", name);
 		return;
+	}
 
 	spin_lock(&de->pde_unload_lock);
 	/*
@@ -853,3 +868,4 @@
 			de->parent->name, de->name, de->subdir->name);
 	pde_put(de);
 }
+EXPORT_SYMBOL(remove_proc_entry);
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 7ca7834..cfe90a4 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -12,37 +12,37 @@
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
 #include <linux/fs.h>
+#include <linux/syslog.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
 extern wait_queue_head_t log_wait;
 
-extern int do_syslog(int type, char __user *bug, int count);
-
 static int kmsg_open(struct inode * inode, struct file * file)
 {
-	return do_syslog(1,NULL,0);
+	return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_FILE);
 }
 
 static int kmsg_release(struct inode * inode, struct file * file)
 {
-	(void) do_syslog(0,NULL,0);
+	(void) do_syslog(SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_FILE);
 	return 0;
 }
 
 static ssize_t kmsg_read(struct file *file, char __user *buf,
 			 size_t count, loff_t *ppos)
 {
-	if ((file->f_flags & O_NONBLOCK) && !do_syslog(9, NULL, 0))
+	if ((file->f_flags & O_NONBLOCK) &&
+	    !do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE))
 		return -EAGAIN;
-	return do_syslog(2, buf, count);
+	return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_FILE);
 }
 
 static unsigned int kmsg_poll(struct file *file, poll_table *wait)
 {
 	poll_wait(file, &log_wait, wait);
-	if (do_syslog(9, NULL, 0))
+	if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE))
 		return POLLIN | POLLRDNORM;
 	return 0;
 }
diff --git a/fs/proc/root.c b/fs/proc/root.c
index b080b79..757c069 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -220,9 +220,3 @@
 {
 	mntput(ns->proc_mnt);
 }
-
-EXPORT_SYMBOL(proc_symlink);
-EXPORT_SYMBOL(proc_mkdir);
-EXPORT_SYMBOL(create_proc_entry);
-EXPORT_SYMBOL(proc_create_data);
-EXPORT_SYMBOL(remove_proc_entry);
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index f277c4a..183f8ff 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -16,7 +16,7 @@
 
 void task_mem(struct seq_file *m, struct mm_struct *mm)
 {
-	unsigned long data, text, lib;
+	unsigned long data, text, lib, swap;
 	unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss;
 
 	/*
@@ -36,6 +36,7 @@
 	data = mm->total_vm - mm->shared_vm - mm->stack_vm;
 	text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10;
 	lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
+	swap = get_mm_counter(mm, MM_SWAPENTS);
 	seq_printf(m,
 		"VmPeak:\t%8lu kB\n"
 		"VmSize:\t%8lu kB\n"
@@ -46,7 +47,8 @@
 		"VmStk:\t%8lu kB\n"
 		"VmExe:\t%8lu kB\n"
 		"VmLib:\t%8lu kB\n"
-		"VmPTE:\t%8lu kB\n",
+		"VmPTE:\t%8lu kB\n"
+		"VmSwap:\t%8lu kB\n",
 		hiwater_vm << (PAGE_SHIFT-10),
 		(total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
 		mm->locked_vm << (PAGE_SHIFT-10),
@@ -54,7 +56,8 @@
 		total_rss << (PAGE_SHIFT-10),
 		data << (PAGE_SHIFT-10),
 		mm->stack_vm << (PAGE_SHIFT-10), text, lib,
-		(PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
+		(PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10,
+		swap << (PAGE_SHIFT-10));
 }
 
 unsigned long task_vsize(struct mm_struct *mm)
@@ -65,11 +68,11 @@
 int task_statm(struct mm_struct *mm, int *shared, int *text,
 	       int *data, int *resident)
 {
-	*shared = get_mm_counter(mm, file_rss);
+	*shared = get_mm_counter(mm, MM_FILEPAGES);
 	*text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
 								>> PAGE_SHIFT;
 	*data = mm->total_vm - mm->shared_vm;
-	*resident = *shared + get_mm_counter(mm, anon_rss);
+	*resident = *shared + get_mm_counter(mm, MM_ANONPAGES);
 	return mm->total_vm;
 }
 
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index ebf3440..277575d 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -201,7 +201,8 @@
 				rootdir = (struct qnx4_inode_entry *) (bh->b_data + i * QNX4_DIR_ENTRY_SIZE);
 				if (rootdir->di_fname != NULL) {
 					QNX4DEBUG((KERN_INFO "rootdir entry found : [%s]\n", rootdir->di_fname));
-					if (!strncmp(rootdir->di_fname, QNX4_BMNAME, sizeof QNX4_BMNAME)) {
+					if (!strcmp(rootdir->di_fname,
+						    QNX4_BMNAME)) {
 						found = 1;
 						qnx4_sb(sb)->BitMap = kmalloc( sizeof( struct qnx4_inode_entry ), GFP_KERNEL );
 						if (!qnx4_sb(sb)->BitMap) {
diff --git a/fs/quota/Kconfig b/fs/quota/Kconfig
index efc02eb..dad7fb2 100644
--- a/fs/quota/Kconfig
+++ b/fs/quota/Kconfig
@@ -59,3 +59,8 @@
 	bool
 	depends on XFS_QUOTA || QUOTA
 	default y
+
+config QUOTACTL_COMPAT
+	bool
+	depends on QUOTACTL && COMPAT_FOR_U64_ALIGNMENT
+	default y
diff --git a/fs/quota/Makefile b/fs/quota/Makefile
index 68d4f6d..5f9e9e2 100644
--- a/fs/quota/Makefile
+++ b/fs/quota/Makefile
@@ -3,3 +3,5 @@
 obj-$(CONFIG_QFMT_V2)		+= quota_v2.o
 obj-$(CONFIG_QUOTA_TREE)	+= quota_tree.o
 obj-$(CONFIG_QUOTACTL)		+= quota.o
+obj-$(CONFIG_QUOTACTL_COMPAT)	+= compat.o
+obj-$(CONFIG_QUOTA_NETLINK_INTERFACE)	+= netlink.o
diff --git a/fs/quota/compat.c b/fs/quota/compat.c
new file mode 100644
index 0000000..fb1892f
--- /dev/null
+++ b/fs/quota/compat.c
@@ -0,0 +1,118 @@
+
+#include <linux/syscalls.h>
+#include <linux/compat.h>
+#include <linux/quotaops.h>
+
+/*
+ * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
+ * and is necessary due to alignment problems.
+ */
+struct compat_if_dqblk {
+	compat_u64 dqb_bhardlimit;
+	compat_u64 dqb_bsoftlimit;
+	compat_u64 dqb_curspace;
+	compat_u64 dqb_ihardlimit;
+	compat_u64 dqb_isoftlimit;
+	compat_u64 dqb_curinodes;
+	compat_u64 dqb_btime;
+	compat_u64 dqb_itime;
+	compat_uint_t dqb_valid;
+};
+
+/* XFS structures */
+struct compat_fs_qfilestat {
+	compat_u64 dqb_bhardlimit;
+	compat_u64 qfs_nblks;
+	compat_uint_t qfs_nextents;
+};
+
+struct compat_fs_quota_stat {
+	__s8		qs_version;
+	__u16		qs_flags;
+	__s8		qs_pad;
+	struct compat_fs_qfilestat	qs_uquota;
+	struct compat_fs_qfilestat	qs_gquota;
+	compat_uint_t	qs_incoredqs;
+	compat_int_t	qs_btimelimit;
+	compat_int_t	qs_itimelimit;
+	compat_int_t	qs_rtbtimelimit;
+	__u16		qs_bwarnlimit;
+	__u16		qs_iwarnlimit;
+};
+
+asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
+						qid_t id, void __user *addr)
+{
+	unsigned int cmds;
+	struct if_dqblk __user *dqblk;
+	struct compat_if_dqblk __user *compat_dqblk;
+	struct fs_quota_stat __user *fsqstat;
+	struct compat_fs_quota_stat __user *compat_fsqstat;
+	compat_uint_t data;
+	u16 xdata;
+	long ret;
+
+	cmds = cmd >> SUBCMDSHIFT;
+
+	switch (cmds) {
+	case Q_GETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		if (ret)
+			break;
+		if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &dqblk->dqb_valid) ||
+			put_user(data, &compat_dqblk->dqb_valid))
+			ret = -EFAULT;
+		break;
+	case Q_SETQUOTA:
+		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
+		compat_dqblk = addr;
+		ret = -EFAULT;
+		if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
+			get_user(data, &compat_dqblk->dqb_valid) ||
+			put_user(data, &dqblk->dqb_valid))
+			break;
+		ret = sys_quotactl(cmd, special, id, dqblk);
+		break;
+	case Q_XGETQSTAT:
+		fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
+		compat_fsqstat = addr;
+		ret = sys_quotactl(cmd, special, id, fsqstat);
+		if (ret)
+			break;
+		ret = -EFAULT;
+		/* Copying qs_version, qs_flags, qs_pad */
+		if (copy_in_user(compat_fsqstat, fsqstat,
+			offsetof(struct compat_fs_quota_stat, qs_uquota)))
+			break;
+		/* Copying qs_uquota */
+		if (copy_in_user(&compat_fsqstat->qs_uquota,
+			&fsqstat->qs_uquota,
+			sizeof(compat_fsqstat->qs_uquota)) ||
+			get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
+			break;
+		/* Copying qs_gquota */
+		if (copy_in_user(&compat_fsqstat->qs_gquota,
+			&fsqstat->qs_gquota,
+			sizeof(compat_fsqstat->qs_gquota)) ||
+			get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
+			put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
+			break;
+		/* Copying the rest */
+		if (copy_in_user(&compat_fsqstat->qs_incoredqs,
+			&fsqstat->qs_incoredqs,
+			sizeof(struct compat_fs_quota_stat) -
+			offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
+			get_user(xdata, &fsqstat->qs_iwarnlimit) ||
+			put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
+			break;
+		ret = 0;
+		break;
+	default:
+		ret = sys_quotactl(cmd, special, id, addr);
+	}
+	return ret;
+}
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 3fc62b0..e0b870f 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -100,9 +100,13 @@
  *
  * Any operation working on dquots via inode pointers must hold dqptr_sem.  If
  * operation is just reading pointers from inode (or not using them at all) the
- * read lock is enough. If pointers are altered function must hold write lock
- * (these locking rules also apply for S_NOQUOTA flag in the inode - note that
- * for altering the flag i_mutex is also needed).
+ * read lock is enough. If pointers are altered function must hold write lock.
+ * Special care needs to be taken about S_NOQUOTA inode flag (marking that
+ * inode is a quota file). Functions adding pointers from inode to dquots have
+ * to check this flag under dqptr_sem and then (if S_NOQUOTA is not set) they
+ * have to do all pointer modifications before dropping dqptr_sem. This makes
+ * sure they cannot race with quotaon which first sets S_NOQUOTA flag and
+ * then drops all pointers to dquots from an inode.
  *
  * Each dquot has its dq_lock mutex. Locked dquots might not be referenced
  * from inodes (dquot_alloc_space() and such don't check the dq_lock).
@@ -225,6 +229,9 @@
 struct dqstats dqstats;
 EXPORT_SYMBOL(dqstats);
 
+static qsize_t inode_get_rsv_space(struct inode *inode);
+static void __dquot_initialize(struct inode *inode, int type);
+
 static inline unsigned int
 hashfn(const struct super_block *sb, unsigned int id, int type)
 {
@@ -564,7 +571,7 @@
 }
 EXPORT_SYMBOL(dquot_scan_active);
 
-int vfs_quota_sync(struct super_block *sb, int type)
+int vfs_quota_sync(struct super_block *sb, int type, int wait)
 {
 	struct list_head *dirty;
 	struct dquot *dquot;
@@ -609,6 +616,33 @@
 	spin_unlock(&dq_list_lock);
 	mutex_unlock(&dqopt->dqonoff_mutex);
 
+	if (!wait || (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE))
+		return 0;
+
+	/* This is not very clever (and fast) but currently I don't know about
+	 * any other simple way of getting quota data to disk and we must get
+	 * them there for userspace to be visible... */
+	if (sb->s_op->sync_fs)
+		sb->s_op->sync_fs(sb, 1);
+	sync_blockdev(sb->s_bdev);
+
+	/*
+	 * Now when everything is written we can discard the pagecache so
+	 * that userspace sees the changes.
+	 */
+	mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		if (type != -1 && cnt != type)
+			continue;
+		if (!sb_has_quota_active(sb, cnt))
+			continue;
+		mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex,
+				  I_MUTEX_QUOTA);
+		truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
+		mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex);
+	}
+	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+
 	return 0;
 }
 EXPORT_SYMBOL(vfs_quota_sync);
@@ -840,11 +874,14 @@
 static void add_dquot_ref(struct super_block *sb, int type)
 {
 	struct inode *inode, *old_inode = NULL;
+	int reserved = 0;
 
 	spin_lock(&inode_lock);
 	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
 		if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW))
 			continue;
+		if (unlikely(inode_get_rsv_space(inode) > 0))
+			reserved = 1;
 		if (!atomic_read(&inode->i_writecount))
 			continue;
 		if (!dqinit_needed(inode, type))
@@ -854,7 +891,7 @@
 		spin_unlock(&inode_lock);
 
 		iput(old_inode);
-		sb->dq_op->initialize(inode, type);
+		__dquot_initialize(inode, type);
 		/* We hold a reference to 'inode' so it couldn't have been
 		 * removed from s_inodes list while we dropped the inode_lock.
 		 * We cannot iput the inode now as we can be holding the last
@@ -865,6 +902,12 @@
 	}
 	spin_unlock(&inode_lock);
 	iput(old_inode);
+
+	if (reserved) {
+		printk(KERN_WARNING "VFS (%s): Writes happened before quota"
+			" was turned on thus quota information is probably "
+			"inconsistent. Please run quotacheck(8).\n", sb->s_id);
+	}
 }
 
 /*
@@ -978,10 +1021,12 @@
 /*
  * Claim reserved quota space
  */
-static void dquot_claim_reserved_space(struct dquot *dquot,
-						qsize_t number)
+static void dquot_claim_reserved_space(struct dquot *dquot, qsize_t number)
 {
-	WARN_ON(dquot->dq_dqb.dqb_rsvspace < number);
+	if (dquot->dq_dqb.dqb_rsvspace < number) {
+		WARN_ON_ONCE(1);
+		number = dquot->dq_dqb.dqb_rsvspace;
+	}
 	dquot->dq_dqb.dqb_curspace += number;
 	dquot->dq_dqb.dqb_rsvspace -= number;
 }
@@ -989,7 +1034,12 @@
 static inline
 void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
 {
-	dquot->dq_dqb.dqb_rsvspace -= number;
+	if (dquot->dq_dqb.dqb_rsvspace >= number)
+		dquot->dq_dqb.dqb_rsvspace -= number;
+	else {
+		WARN_ON_ONCE(1);
+		dquot->dq_dqb.dqb_rsvspace = 0;
+	}
 }
 
 static void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
@@ -1131,13 +1181,13 @@
 	*warntype = QUOTA_NL_NOWARN;
 	if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) ||
 	    test_bit(DQ_FAKE_B, &dquot->dq_flags))
-		return QUOTA_OK;
+		return 0;
 
 	if (dquot->dq_dqb.dqb_ihardlimit &&
 	    newinodes > dquot->dq_dqb.dqb_ihardlimit &&
             !ignore_hardlimit(dquot)) {
 		*warntype = QUOTA_NL_IHARDWARN;
-		return NO_QUOTA;
+		return -EDQUOT;
 	}
 
 	if (dquot->dq_dqb.dqb_isoftlimit &&
@@ -1146,7 +1196,7 @@
 	    get_seconds() >= dquot->dq_dqb.dqb_itime &&
             !ignore_hardlimit(dquot)) {
 		*warntype = QUOTA_NL_ISOFTLONGWARN;
-		return NO_QUOTA;
+		return -EDQUOT;
 	}
 
 	if (dquot->dq_dqb.dqb_isoftlimit &&
@@ -1157,7 +1207,7 @@
 		    sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
 	}
 
-	return QUOTA_OK;
+	return 0;
 }
 
 /* needs dq_data_lock */
@@ -1169,7 +1219,7 @@
 	*warntype = QUOTA_NL_NOWARN;
 	if (!sb_has_quota_limits_enabled(sb, dquot->dq_type) ||
 	    test_bit(DQ_FAKE_B, &dquot->dq_flags))
-		return QUOTA_OK;
+		return 0;
 
 	tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace
 		+ space;
@@ -1179,7 +1229,7 @@
             !ignore_hardlimit(dquot)) {
 		if (!prealloc)
 			*warntype = QUOTA_NL_BHARDWARN;
-		return NO_QUOTA;
+		return -EDQUOT;
 	}
 
 	if (dquot->dq_dqb.dqb_bsoftlimit &&
@@ -1189,7 +1239,7 @@
             !ignore_hardlimit(dquot)) {
 		if (!prealloc)
 			*warntype = QUOTA_NL_BSOFTLONGWARN;
-		return NO_QUOTA;
+		return -EDQUOT;
 	}
 
 	if (dquot->dq_dqb.dqb_bsoftlimit &&
@@ -1205,10 +1255,10 @@
 			 * We don't allow preallocation to exceed softlimit so exceeding will
 			 * be always printed
 			 */
-			return NO_QUOTA;
+			return -EDQUOT;
 	}
 
-	return QUOTA_OK;
+	return 0;
 }
 
 static int info_idq_free(struct dquot *dquot, qsize_t inodes)
@@ -1242,25 +1292,32 @@
 		return QUOTA_NL_BHARDBELOW;
 	return QUOTA_NL_NOWARN;
 }
+
 /*
- *	Initialize quota pointers in inode
- *	We do things in a bit complicated way but by that we avoid calling
- *	dqget() and thus filesystem callbacks under dqptr_sem.
+ * Initialize quota pointers in inode
+ *
+ * We do things in a bit complicated way but by that we avoid calling
+ * dqget() and thus filesystem callbacks under dqptr_sem.
+ *
+ * It is better to call this function outside of any transaction as it
+ * might need a lot of space in journal for dquot structure allocation.
  */
-int dquot_initialize(struct inode *inode, int type)
+static void __dquot_initialize(struct inode *inode, int type)
 {
 	unsigned int id = 0;
-	int cnt, ret = 0;
-	struct dquot *got[MAXQUOTAS] = { NULL, NULL };
+	int cnt;
+	struct dquot *got[MAXQUOTAS];
 	struct super_block *sb = inode->i_sb;
+	qsize_t rsv;
 
 	/* First test before acquiring mutex - solves deadlocks when we
          * re-enter the quota code and are already holding the mutex */
-	if (IS_NOQUOTA(inode))
-		return 0;
+	if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode))
+		return;
 
 	/* First get references to structures we might need. */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		got[cnt] = NULL;
 		if (type != -1 && cnt != type)
 			continue;
 		switch (cnt) {
@@ -1275,7 +1332,6 @@
 	}
 
 	down_write(&sb_dqopt(sb)->dqptr_sem);
-	/* Having dqptr_sem we know NOQUOTA flags can't be altered... */
 	if (IS_NOQUOTA(inode))
 		goto out_err;
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1287,20 +1343,31 @@
 		if (!inode->i_dquot[cnt]) {
 			inode->i_dquot[cnt] = got[cnt];
 			got[cnt] = NULL;
+			/*
+			 * Make quota reservation system happy if someone
+			 * did a write before quota was turned on
+			 */
+			rsv = inode_get_rsv_space(inode);
+			if (unlikely(rsv))
+				dquot_resv_space(inode->i_dquot[cnt], rsv);
 		}
 	}
 out_err:
 	up_write(&sb_dqopt(sb)->dqptr_sem);
 	/* Drop unused references */
 	dqput_all(got);
-	return ret;
+}
+
+void dquot_initialize(struct inode *inode)
+{
+	__dquot_initialize(inode, -1);
 }
 EXPORT_SYMBOL(dquot_initialize);
 
 /*
  * 	Release all quotas referenced by inode
  */
-int dquot_drop(struct inode *inode)
+static void __dquot_drop(struct inode *inode)
 {
 	int cnt;
 	struct dquot *put[MAXQUOTAS];
@@ -1312,33 +1379,32 @@
 	}
 	up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
 	dqput_all(put);
-	return 0;
+}
+
+void dquot_drop(struct inode *inode)
+{
+	int cnt;
+
+	if (IS_NOQUOTA(inode))
+		return;
+
+	/*
+	 * Test before calling to rule out calls from proc and such
+	 * where we are not allowed to block. Note that this is
+	 * actually reliable test even without the lock - the caller
+	 * must assure that nobody can come after the DQUOT_DROP and
+	 * add quota pointers back anyway.
+	 */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		if (inode->i_dquot[cnt])
+			break;
+	}
+
+	if (cnt < MAXQUOTAS)
+		__dquot_drop(inode);
 }
 EXPORT_SYMBOL(dquot_drop);
 
-/* Wrapper to remove references to quota structures from inode */
-void vfs_dq_drop(struct inode *inode)
-{
-	/* Here we can get arbitrary inode from clear_inode() so we have
-	 * to be careful. OTOH we don't need locking as quota operations
-	 * are allowed to change only at mount time */
-	if (!IS_NOQUOTA(inode) && inode->i_sb && inode->i_sb->dq_op
-	    && inode->i_sb->dq_op->drop) {
-		int cnt;
-		/* Test before calling to rule out calls from proc and such
-                 * where we are not allowed to block. Note that this is
-		 * actually reliable test even without the lock - the caller
-		 * must assure that nobody can come after the DQUOT_DROP and
-		 * add quota pointers back anyway */
-		for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-			if (inode->i_dquot[cnt])
-				break;
-		if (cnt < MAXQUOTAS)
-			inode->i_sb->dq_op->drop(inode);
-	}
-}
-EXPORT_SYMBOL(vfs_dq_drop);
-
 /*
  * inode_reserved_space is managed internally by quota, and protected by
  * i_lock similar to i_blocks+i_bytes.
@@ -1351,28 +1417,30 @@
 	return inode->i_sb->dq_op->get_reserved_space(inode);
 }
 
-static void inode_add_rsv_space(struct inode *inode, qsize_t number)
+void inode_add_rsv_space(struct inode *inode, qsize_t number)
 {
 	spin_lock(&inode->i_lock);
 	*inode_reserved_space(inode) += number;
 	spin_unlock(&inode->i_lock);
 }
+EXPORT_SYMBOL(inode_add_rsv_space);
 
-
-static void inode_claim_rsv_space(struct inode *inode, qsize_t number)
+void inode_claim_rsv_space(struct inode *inode, qsize_t number)
 {
 	spin_lock(&inode->i_lock);
 	*inode_reserved_space(inode) -= number;
 	__inode_add_bytes(inode, number);
 	spin_unlock(&inode->i_lock);
 }
+EXPORT_SYMBOL(inode_claim_rsv_space);
 
-static void inode_sub_rsv_space(struct inode *inode, qsize_t number)
+void inode_sub_rsv_space(struct inode *inode, qsize_t number)
 {
 	spin_lock(&inode->i_lock);
 	*inode_reserved_space(inode) -= number;
 	spin_unlock(&inode->i_lock);
 }
+EXPORT_SYMBOL(inode_sub_rsv_space);
 
 static qsize_t inode_get_rsv_space(struct inode *inode)
 {
@@ -1404,38 +1472,34 @@
 }
 
 /*
- * Following four functions update i_blocks+i_bytes fields and
- * quota information (together with appropriate checks)
- * NOTE: We absolutely rely on the fact that caller dirties
- * the inode (usually macros in quotaops.h care about this) and
- * holds a handle for the current transaction so that dquot write and
- * inode write go into the same transaction.
+ * This functions updates i_blocks+i_bytes fields and quota information
+ * (together with appropriate checks).
+ *
+ * NOTE: We absolutely rely on the fact that caller dirties the inode
+ * (usually helpers in quotaops.h care about this) and holds a handle for
+ * the current transaction so that dquot write and inode write go into the
+ * same transaction.
  */
 
 /*
  * This operation can block, but only after everything is updated
  */
 int __dquot_alloc_space(struct inode *inode, qsize_t number,
-			int warn, int reserve)
+		int warn, int reserve)
 {
-	int cnt, ret = QUOTA_OK;
+	int cnt, ret = 0;
 	char warntype[MAXQUOTAS];
 
 	/*
 	 * First test before acquiring mutex - solves deadlocks when we
 	 * re-enter the quota code and are already holding the mutex
 	 */
-	if (IS_NOQUOTA(inode)) {
+	if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode)) {
 		inode_incr_space(inode, number, reserve);
 		goto out;
 	}
 
 	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	if (IS_NOQUOTA(inode)) {
-		inode_incr_space(inode, number, reserve);
-		goto out_unlock;
-	}
-
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		warntype[cnt] = QUOTA_NL_NOWARN;
 
@@ -1443,9 +1507,9 @@
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (!inode->i_dquot[cnt])
 			continue;
-		if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt)
-		    == NO_QUOTA) {
-			ret = NO_QUOTA;
+		ret = check_bdq(inode->i_dquot[cnt], number, !warn,
+				warntype+cnt);
+		if (ret) {
 			spin_unlock(&dq_data_lock);
 			goto out_flush_warn;
 		}
@@ -1466,61 +1530,45 @@
 	mark_all_dquot_dirty(inode->i_dquot);
 out_flush_warn:
 	flush_warnings(inode->i_dquot, warntype);
-out_unlock:
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
 out:
 	return ret;
 }
-
-int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
-{
-	return __dquot_alloc_space(inode, number, warn, 0);
-}
-EXPORT_SYMBOL(dquot_alloc_space);
-
-int dquot_reserve_space(struct inode *inode, qsize_t number, int warn)
-{
-	return __dquot_alloc_space(inode, number, warn, 1);
-}
-EXPORT_SYMBOL(dquot_reserve_space);
+EXPORT_SYMBOL(__dquot_alloc_space);
 
 /*
  * This operation can block, but only after everything is updated
  */
-int dquot_alloc_inode(const struct inode *inode, qsize_t number)
+int dquot_alloc_inode(const struct inode *inode)
 {
-	int cnt, ret = NO_QUOTA;
+	int cnt, ret = 0;
 	char warntype[MAXQUOTAS];
 
 	/* First test before acquiring mutex - solves deadlocks when we
          * re-enter the quota code and are already holding the mutex */
-	if (IS_NOQUOTA(inode))
-		return QUOTA_OK;
+	if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode))
+		return 0;
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		warntype[cnt] = QUOTA_NL_NOWARN;
 	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	if (IS_NOQUOTA(inode)) {
-		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-		return QUOTA_OK;
-	}
 	spin_lock(&dq_data_lock);
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (!inode->i_dquot[cnt])
 			continue;
-		if (check_idq(inode->i_dquot[cnt], number, warntype+cnt)
-		    == NO_QUOTA)
+		ret = check_idq(inode->i_dquot[cnt], 1, warntype + cnt);
+		if (ret)
 			goto warn_put_all;
 	}
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (!inode->i_dquot[cnt])
 			continue;
-		dquot_incr_inodes(inode->i_dquot[cnt], number);
+		dquot_incr_inodes(inode->i_dquot[cnt], 1);
 	}
-	ret = QUOTA_OK;
+
 warn_put_all:
 	spin_unlock(&dq_data_lock);
-	if (ret == QUOTA_OK)
+	if (ret == 0)
 		mark_all_dquot_dirty(inode->i_dquot);
 	flush_warnings(inode->i_dquot, warntype);
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
@@ -1528,23 +1576,19 @@
 }
 EXPORT_SYMBOL(dquot_alloc_inode);
 
-int dquot_claim_space(struct inode *inode, qsize_t number)
+/*
+ * Convert in-memory reserved quotas to real consumed quotas
+ */
+int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
 {
 	int cnt;
-	int ret = QUOTA_OK;
 
-	if (IS_NOQUOTA(inode)) {
+	if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode)) {
 		inode_claim_rsv_space(inode, number);
-		goto out;
+		return 0;
 	}
 
 	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	if (IS_NOQUOTA(inode))	{
-		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-		inode_claim_rsv_space(inode, number);
-		goto out;
-	}
-
 	spin_lock(&dq_data_lock);
 	/* Claim reserved quotas to allocated quotas */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -1557,33 +1601,26 @@
 	spin_unlock(&dq_data_lock);
 	mark_all_dquot_dirty(inode->i_dquot);
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-out:
-	return ret;
+	return 0;
 }
-EXPORT_SYMBOL(dquot_claim_space);
+EXPORT_SYMBOL(dquot_claim_space_nodirty);
 
 /*
  * This operation can block, but only after everything is updated
  */
-int __dquot_free_space(struct inode *inode, qsize_t number, int reserve)
+void __dquot_free_space(struct inode *inode, qsize_t number, int reserve)
 {
 	unsigned int cnt;
 	char warntype[MAXQUOTAS];
 
 	/* First test before acquiring mutex - solves deadlocks when we
          * re-enter the quota code and are already holding the mutex */
-	if (IS_NOQUOTA(inode)) {
-out_sub:
+	if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode)) {
 		inode_decr_space(inode, number, reserve);
-		return QUOTA_OK;
+		return;
 	}
 
 	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	/* Now recheck reliably when holding dqptr_sem */
-	if (IS_NOQUOTA(inode)) {
-		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-		goto out_sub;
-	}
 	spin_lock(&dq_data_lock);
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (!inode->i_dquot[cnt])
@@ -1603,56 +1640,34 @@
 out_unlock:
 	flush_warnings(inode->i_dquot, warntype);
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	return QUOTA_OK;
 }
-
-int dquot_free_space(struct inode *inode, qsize_t number)
-{
-	return  __dquot_free_space(inode, number, 0);
-}
-EXPORT_SYMBOL(dquot_free_space);
-
-/*
- * Release reserved quota space
- */
-void dquot_release_reserved_space(struct inode *inode, qsize_t number)
-{
-	__dquot_free_space(inode, number, 1);
-
-}
-EXPORT_SYMBOL(dquot_release_reserved_space);
+EXPORT_SYMBOL(__dquot_free_space);
 
 /*
  * This operation can block, but only after everything is updated
  */
-int dquot_free_inode(const struct inode *inode, qsize_t number)
+void dquot_free_inode(const struct inode *inode)
 {
 	unsigned int cnt;
 	char warntype[MAXQUOTAS];
 
 	/* First test before acquiring mutex - solves deadlocks when we
          * re-enter the quota code and are already holding the mutex */
-	if (IS_NOQUOTA(inode))
-		return QUOTA_OK;
+	if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode))
+		return;
 
 	down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	/* Now recheck reliably when holding dqptr_sem */
-	if (IS_NOQUOTA(inode)) {
-		up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-		return QUOTA_OK;
-	}
 	spin_lock(&dq_data_lock);
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (!inode->i_dquot[cnt])
 			continue;
-		warntype[cnt] = info_idq_free(inode->i_dquot[cnt], number);
-		dquot_decr_inodes(inode->i_dquot[cnt], number);
+		warntype[cnt] = info_idq_free(inode->i_dquot[cnt], 1);
+		dquot_decr_inodes(inode->i_dquot[cnt], 1);
 	}
 	spin_unlock(&dq_data_lock);
 	mark_all_dquot_dirty(inode->i_dquot);
 	flush_warnings(inode->i_dquot, warntype);
 	up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	return QUOTA_OK;
 }
 EXPORT_SYMBOL(dquot_free_inode);
 
@@ -1662,37 +1677,31 @@
  * This operation can block, but only after everything is updated
  * A transaction must be started when entering this function.
  */
-int dquot_transfer(struct inode *inode, struct iattr *iattr)
+static int __dquot_transfer(struct inode *inode, qid_t *chid, unsigned long mask)
 {
 	qsize_t space, cur_space;
 	qsize_t rsv_space = 0;
 	struct dquot *transfer_from[MAXQUOTAS];
 	struct dquot *transfer_to[MAXQUOTAS];
-	int cnt, ret = QUOTA_OK;
-	int chuid = iattr->ia_valid & ATTR_UID && inode->i_uid != iattr->ia_uid,
-	    chgid = iattr->ia_valid & ATTR_GID && inode->i_gid != iattr->ia_gid;
+	int cnt, ret = 0;
 	char warntype_to[MAXQUOTAS];
 	char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS];
 
 	/* First test before acquiring mutex - solves deadlocks when we
          * re-enter the quota code and are already holding the mutex */
 	if (IS_NOQUOTA(inode))
-		return QUOTA_OK;
+		return 0;
 	/* Initialize the arrays */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		transfer_from[cnt] = NULL;
 		transfer_to[cnt] = NULL;
 		warntype_to[cnt] = QUOTA_NL_NOWARN;
 	}
-	if (chuid)
-		transfer_to[USRQUOTA] = dqget(inode->i_sb, iattr->ia_uid,
-					      USRQUOTA);
-	if (chgid)
-		transfer_to[GRPQUOTA] = dqget(inode->i_sb, iattr->ia_gid,
-					      GRPQUOTA);
-
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		if (mask & (1 << cnt))
+			transfer_to[cnt] = dqget(inode->i_sb, chid[cnt], cnt);
+	}
 	down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
-	/* Now recheck reliably when holding dqptr_sem */
 	if (IS_NOQUOTA(inode)) {	/* File without quota accounting? */
 		up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
 		goto put_all;
@@ -1706,9 +1715,11 @@
 		if (!transfer_to[cnt])
 			continue;
 		transfer_from[cnt] = inode->i_dquot[cnt];
-		if (check_idq(transfer_to[cnt], 1, warntype_to + cnt) ==
-		    NO_QUOTA || check_bdq(transfer_to[cnt], space, 0,
-		    warntype_to + cnt) == NO_QUOTA)
+		ret = check_idq(transfer_to[cnt], 1, warntype_to + cnt);
+		if (ret)
+			goto over_quota;
+		ret = check_bdq(transfer_to[cnt], space, 0, warntype_to + cnt);
+		if (ret)
 			goto over_quota;
 	}
 
@@ -1762,22 +1773,32 @@
 	/* Clear dquot pointers we don't want to dqput() */
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
 		transfer_from[cnt] = NULL;
-	ret = NO_QUOTA;
 	goto warn_put_all;
 }
-EXPORT_SYMBOL(dquot_transfer);
 
-/* Wrapper for transferring ownership of an inode */
-int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
+/* Wrapper for transferring ownership of an inode for uid/gid only
+ * Called from FSXXX_setattr()
+ */
+int dquot_transfer(struct inode *inode, struct iattr *iattr)
 {
+	qid_t chid[MAXQUOTAS];
+	unsigned long mask = 0;
+
+	if (iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) {
+		mask |= 1 << USRQUOTA;
+		chid[USRQUOTA] = iattr->ia_uid;
+	}
+	if (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid) {
+		mask |= 1 << GRPQUOTA;
+		chid[GRPQUOTA] = iattr->ia_gid;
+	}
 	if (sb_any_quota_active(inode->i_sb) && !IS_NOQUOTA(inode)) {
-		vfs_dq_init(inode);
-		if (inode->i_sb->dq_op->transfer(inode, iattr) == NO_QUOTA)
-			return 1;
+		dquot_initialize(inode);
+		return __dquot_transfer(inode, chid, mask);
 	}
 	return 0;
 }
-EXPORT_SYMBOL(vfs_dq_transfer);
+EXPORT_SYMBOL(dquot_transfer);
 
 /*
  * Write info of quota file to disk
@@ -1798,13 +1819,6 @@
  * Definitions of diskquota operations.
  */
 const struct dquot_operations dquot_operations = {
-	.initialize	= dquot_initialize,
-	.drop		= dquot_drop,
-	.alloc_space	= dquot_alloc_space,
-	.alloc_inode	= dquot_alloc_inode,
-	.free_space	= dquot_free_space,
-	.free_inode	= dquot_free_inode,
-	.transfer	= dquot_transfer,
 	.write_dquot	= dquot_commit,
 	.acquire_dquot	= dquot_acquire,
 	.release_dquot	= dquot_release,
@@ -1815,6 +1829,20 @@
 };
 
 /*
+ * Generic helper for ->open on filesystems supporting disk quotas.
+ */
+int dquot_file_open(struct inode *inode, struct file *file)
+{
+	int error;
+
+	error = generic_file_open(inode, file);
+	if (!error && (file->f_mode & FMODE_WRITE))
+		dquot_initialize(inode);
+	return error;
+}
+EXPORT_SYMBOL(dquot_file_open);
+
+/*
  * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
  */
 int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags)
@@ -1993,11 +2021,13 @@
 	}
 
 	if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) {
-		/* As we bypass the pagecache we must now flush the inode so
-		 * that we see all the changes from userspace... */
-		write_inode_now(inode, 1);
-		/* And now flush the block cache so that kernel sees the
-		 * changes */
+		/* As we bypass the pagecache we must now flush all the
+		 * dirty data and invalidate caches so that kernel sees
+		 * changes from userspace. It is not enough to just flush
+		 * the quota file since if blocksize < pagesize, invalidation
+		 * of the cache could fail because of other unrelated dirty
+		 * data */
+		sync_filesystem(sb);
 		invalidate_bdev(sb->s_bdev);
 	}
 	mutex_lock(&dqopt->dqonoff_mutex);
@@ -2010,14 +2040,16 @@
 		/* We don't want quota and atime on quota files (deadlocks
 		 * possible) Also nobody should write to the file - we use
 		 * special IO operations which ignore the immutable bit. */
-		down_write(&dqopt->dqptr_sem);
 		mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
 		oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE |
 					     S_NOQUOTA);
 		inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
 		mutex_unlock(&inode->i_mutex);
-		up_write(&dqopt->dqptr_sem);
-		sb->dq_op->drop(inode);
+		/*
+		 * When S_NOQUOTA is set, remove dquot references as no more
+		 * references can be added
+		 */
+		__dquot_drop(inode);
 	}
 
 	error = -EIO;
@@ -2053,14 +2085,12 @@
 	iput(inode);
 out_lock:
 	if (oldflags != -1) {
-		down_write(&dqopt->dqptr_sem);
 		mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
 		/* Set the flags back (in the case of accidental quotaon()
 		 * on a wrong file we don't want to mess up the flags) */
 		inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);
 		inode->i_flags |= oldflags;
 		mutex_unlock(&inode->i_mutex);
-		up_write(&dqopt->dqptr_sem);
 	}
 	mutex_unlock(&dqopt->dqonoff_mutex);
 out_fmt:
diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c
new file mode 100644
index 0000000..2663ed9
--- /dev/null
+++ b/fs/quota/netlink.c
@@ -0,0 +1,95 @@
+
+#include <linux/cred.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/quotaops.h>
+#include <linux/sched.h>
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+/* Netlink family structure for quota */
+static struct genl_family quota_genl_family = {
+	.id = GENL_ID_GENERATE,
+	.hdrsize = 0,
+	.name = "VFS_DQUOT",
+	.version = 1,
+	.maxattr = QUOTA_NL_A_MAX,
+};
+
+/**
+ * quota_send_warning - Send warning to userspace about exceeded quota
+ * @type: The quota type: USRQQUOTA, GRPQUOTA,...
+ * @id: The user or group id of the quota that was exceeded
+ * @dev: The device on which the fs is mounted (sb->s_dev)
+ * @warntype: The type of the warning: QUOTA_NL_...
+ *
+ * This can be used by filesystems (including those which don't use
+ * dquot) to send a message to userspace relating to quota limits.
+ *
+ */
+
+void quota_send_warning(short type, unsigned int id, dev_t dev,
+			const char warntype)
+{
+	static atomic_t seq;
+	struct sk_buff *skb;
+	void *msg_head;
+	int ret;
+	int msg_size = 4 * nla_total_size(sizeof(u32)) +
+		       2 * nla_total_size(sizeof(u64));
+
+	/* We have to allocate using GFP_NOFS as we are called from a
+	 * filesystem performing write and thus further recursion into
+	 * the fs to free some data could cause deadlocks. */
+	skb = genlmsg_new(msg_size, GFP_NOFS);
+	if (!skb) {
+		printk(KERN_ERR
+		  "VFS: Not enough memory to send quota warning.\n");
+		return;
+	}
+	msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
+			&quota_genl_family, 0, QUOTA_NL_C_WARNING);
+	if (!msg_head) {
+		printk(KERN_ERR
+		  "VFS: Cannot store netlink header in quota warning.\n");
+		goto err_out;
+	}
+	ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, type);
+	if (ret)
+		goto attr_err_out;
+	ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, id);
+	if (ret)
+		goto attr_err_out;
+	ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype);
+	if (ret)
+		goto attr_err_out;
+	ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev));
+	if (ret)
+		goto attr_err_out;
+	ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev));
+	if (ret)
+		goto attr_err_out;
+	ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid());
+	if (ret)
+		goto attr_err_out;
+	genlmsg_end(skb, msg_head);
+
+	genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
+	return;
+attr_err_out:
+	printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
+err_out:
+	kfree_skb(skb);
+}
+EXPORT_SYMBOL(quota_send_warning);
+
+static int __init quota_init(void)
+{
+	if (genl_register_family(&quota_genl_family) != 0)
+		printk(KERN_ERR
+		       "VFS: Failed to create quota netlink interface.\n");
+	return 0;
+};
+
+module_init(quota_init);
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index ee91e27..95388f9 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -10,7 +10,6 @@
 #include <linux/slab.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
-#include <linux/compat.h>
 #include <linux/kernel.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
@@ -18,220 +17,205 @@
 #include <linux/capability.h>
 #include <linux/quotaops.h>
 #include <linux/types.h>
-#include <net/netlink.h>
-#include <net/genetlink.h>
+#include <linux/writeback.h>
 
-/* Check validity of generic quotactl commands */
-static int generic_quotactl_valid(struct super_block *sb, int type, int cmd,
-				  qid_t id)
+static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
+				     qid_t id)
 {
-	if (type >= MAXQUOTAS)
-		return -EINVAL;
-	if (!sb && cmd != Q_SYNC)
-		return -ENODEV;
-	/* Is operation supported? */
-	if (sb && !sb->s_qcop)
-		return -ENOSYS;
-
 	switch (cmd) {
-		case Q_GETFMT:
+	/* these commands do not require any special privilegues */
+	case Q_GETFMT:
+	case Q_SYNC:
+	case Q_GETINFO:
+	case Q_XGETQSTAT:
+	case Q_XQUOTASYNC:
+		break;
+	/* allow to query information for dquots we "own" */
+	case Q_GETQUOTA:
+	case Q_XGETQUOTA:
+		if ((type == USRQUOTA && current_euid() == id) ||
+		    (type == GRPQUOTA && in_egroup_p(id)))
 			break;
-		case Q_QUOTAON:
-			if (!sb->s_qcop->quota_on)
-				return -ENOSYS;
-			break;
-		case Q_QUOTAOFF:
-			if (!sb->s_qcop->quota_off)
-				return -ENOSYS;
-			break;
-		case Q_SETINFO:
-			if (!sb->s_qcop->set_info)
-				return -ENOSYS;
-			break;
-		case Q_GETINFO:
-			if (!sb->s_qcop->get_info)
-				return -ENOSYS;
-			break;
-		case Q_SETQUOTA:
-			if (!sb->s_qcop->set_dqblk)
-				return -ENOSYS;
-			break;
-		case Q_GETQUOTA:
-			if (!sb->s_qcop->get_dqblk)
-				return -ENOSYS;
-			break;
-		case Q_SYNC:
-			if (sb && !sb->s_qcop->quota_sync)
-				return -ENOSYS;
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	/* Is quota turned on for commands which need it? */
-	switch (cmd) {
-		case Q_GETFMT:
-		case Q_GETINFO:
-		case Q_SETINFO:
-		case Q_SETQUOTA:
-		case Q_GETQUOTA:
-			/* This is just an informative test so we are satisfied
-			 * without the lock */
-			if (!sb_has_quota_active(sb, type))
-				return -ESRCH;
-	}
-
-	/* Check privileges */
-	if (cmd == Q_GETQUOTA) {
-		if (((type == USRQUOTA && current_euid() != id) ||
-		     (type == GRPQUOTA && !in_egroup_p(id))) &&
-		    !capable(CAP_SYS_ADMIN))
-			return -EPERM;
-	}
-	else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO)
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-
-	return 0;
-}
-
-/* Check validity of XFS Quota Manager commands */
-static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd,
-			      qid_t id)
-{
-	if (type >= XQM_MAXQUOTAS)
-		return -EINVAL;
-	if (!sb)
-		return -ENODEV;
-	if (!sb->s_qcop)
-		return -ENOSYS;
-
-	switch (cmd) {
-		case Q_XQUOTAON:
-		case Q_XQUOTAOFF:
-		case Q_XQUOTARM:
-			if (!sb->s_qcop->set_xstate)
-				return -ENOSYS;
-			break;
-		case Q_XGETQSTAT:
-			if (!sb->s_qcop->get_xstate)
-				return -ENOSYS;
-			break;
-		case Q_XSETQLIM:
-			if (!sb->s_qcop->set_xquota)
-				return -ENOSYS;
-			break;
-		case Q_XGETQUOTA:
-			if (!sb->s_qcop->get_xquota)
-				return -ENOSYS;
-			break;
-		case Q_XQUOTASYNC:
-			if (!sb->s_qcop->quota_sync)
-				return -ENOSYS;
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	/* Check privileges */
-	if (cmd == Q_XGETQUOTA) {
-		if (((type == XQM_USRQUOTA && current_euid() != id) ||
-		     (type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
-		     !capable(CAP_SYS_ADMIN))
-			return -EPERM;
-	} else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) {
+		/*FALLTHROUGH*/
+	default:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 	}
 
-	return 0;
+	return security_quotactl(cmd, type, id, sb);
 }
 
-static int check_quotactl_valid(struct super_block *sb, int type, int cmd,
-				qid_t id)
-{
-	int error;
-
-	if (XQM_COMMAND(cmd))
-		error = xqm_quotactl_valid(sb, type, cmd, id);
-	else
-		error = generic_quotactl_valid(sb, type, cmd, id);
-	if (!error)
-		error = security_quotactl(cmd, type, id, sb);
-	return error;
-}
-
-#ifdef CONFIG_QUOTA
-void sync_quota_sb(struct super_block *sb, int type)
-{
-	int cnt;
-
-	if (!sb->s_qcop->quota_sync)
-		return;
-
-	sb->s_qcop->quota_sync(sb, type);
-
-	if (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE)
-		return;
-	/* This is not very clever (and fast) but currently I don't know about
-	 * any other simple way of getting quota data to disk and we must get
-	 * them there for userspace to be visible... */
-	if (sb->s_op->sync_fs)
-		sb->s_op->sync_fs(sb, 1);
-	sync_blockdev(sb->s_bdev);
-
-	/*
-	 * Now when everything is written we can discard the pagecache so
-	 * that userspace sees the changes.
-	 */
-	mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
-	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (type != -1 && cnt != type)
-			continue;
-		if (!sb_has_quota_active(sb, cnt))
-			continue;
-		mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex,
-				  I_MUTEX_QUOTA);
-		truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
-		mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex);
-	}
-	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
-}
-#endif
-
-static void sync_dquots(int type)
+static int quota_sync_all(int type)
 {
 	struct super_block *sb;
-	int cnt;
+	int ret;
+
+	if (type >= MAXQUOTAS)
+		return -EINVAL;
+	ret = security_quotactl(Q_SYNC, type, 0, NULL);
+	if (ret)
+		return ret;
 
 	spin_lock(&sb_lock);
 restart:
 	list_for_each_entry(sb, &super_blocks, s_list) {
-		/* This test just improves performance so it needn't be
-		 * reliable... */
-		for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-			if (type != -1 && type != cnt)
-				continue;
-			if (!sb_has_quota_active(sb, cnt))
-				continue;
-			if (!info_dirty(&sb_dqopt(sb)->info[cnt]) &&
-			   list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list))
-				continue;
-			break;
-		}
-		if (cnt == MAXQUOTAS)
+		if (!sb->s_qcop || !sb->s_qcop->quota_sync)
 			continue;
+
 		sb->s_count++;
 		spin_unlock(&sb_lock);
 		down_read(&sb->s_umount);
 		if (sb->s_root)
-			sync_quota_sb(sb, type);
+			sb->s_qcop->quota_sync(sb, type, 1);
 		up_read(&sb->s_umount);
 		spin_lock(&sb_lock);
 		if (__put_super_and_need_restart(sb))
 			goto restart;
 	}
 	spin_unlock(&sb_lock);
+
+	return 0;
+}
+
+static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
+		         void __user *addr)
+{
+	char *pathname;
+	int ret = -ENOSYS;
+
+	pathname = getname(addr);
+	if (IS_ERR(pathname))
+		return PTR_ERR(pathname);
+	if (sb->s_qcop->quota_on)
+		ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0);
+	putname(pathname);
+	return ret;
+}
+
+static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
+{
+	__u32 fmt;
+
+	down_read(&sb_dqopt(sb)->dqptr_sem);
+	if (!sb_has_quota_active(sb, type)) {
+		up_read(&sb_dqopt(sb)->dqptr_sem);
+		return -ESRCH;
+	}
+	fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
+	up_read(&sb_dqopt(sb)->dqptr_sem);
+	if (copy_to_user(addr, &fmt, sizeof(fmt)))
+		return -EFAULT;
+	return 0;
+}
+
+static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
+{
+	struct if_dqinfo info;
+	int ret;
+
+	if (!sb_has_quota_active(sb, type))
+		return -ESRCH;
+	if (!sb->s_qcop->get_info)
+		return -ENOSYS;
+	ret = sb->s_qcop->get_info(sb, type, &info);
+	if (!ret && copy_to_user(addr, &info, sizeof(info)))
+		return -EFAULT;
+	return ret;
+}
+
+static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
+{
+	struct if_dqinfo info;
+
+	if (copy_from_user(&info, addr, sizeof(info)))
+		return -EFAULT;
+	if (!sb_has_quota_active(sb, type))
+		return -ESRCH;
+	if (!sb->s_qcop->set_info)
+		return -ENOSYS;
+	return sb->s_qcop->set_info(sb, type, &info);
+}
+
+static int quota_getquota(struct super_block *sb, int type, qid_t id,
+			  void __user *addr)
+{
+	struct if_dqblk idq;
+	int ret;
+
+	if (!sb_has_quota_active(sb, type))
+		return -ESRCH;
+	if (!sb->s_qcop->get_dqblk)
+		return -ENOSYS;
+	ret = sb->s_qcop->get_dqblk(sb, type, id, &idq);
+	if (ret)
+		return ret;
+	if (copy_to_user(addr, &idq, sizeof(idq)))
+		return -EFAULT;
+	return 0;
+}
+
+static int quota_setquota(struct super_block *sb, int type, qid_t id,
+			  void __user *addr)
+{
+	struct if_dqblk idq;
+
+	if (copy_from_user(&idq, addr, sizeof(idq)))
+		return -EFAULT;
+	if (!sb_has_quota_active(sb, type))
+		return -ESRCH;
+	if (!sb->s_qcop->set_dqblk)
+		return -ENOSYS;
+	return sb->s_qcop->set_dqblk(sb, type, id, &idq);
+}
+
+static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
+{
+	__u32 flags;
+
+	if (copy_from_user(&flags, addr, sizeof(flags)))
+		return -EFAULT;
+	if (!sb->s_qcop->set_xstate)
+		return -ENOSYS;
+	return sb->s_qcop->set_xstate(sb, flags, cmd);
+}
+
+static int quota_getxstate(struct super_block *sb, void __user *addr)
+{
+	struct fs_quota_stat fqs;
+	int ret;
+
+	if (!sb->s_qcop->get_xstate)
+		return -ENOSYS;
+	ret = sb->s_qcop->get_xstate(sb, &fqs);
+	if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
+		return -EFAULT;
+	return ret;
+}
+
+static int quota_setxquota(struct super_block *sb, int type, qid_t id,
+			   void __user *addr)
+{
+	struct fs_disk_quota fdq;
+
+	if (copy_from_user(&fdq, addr, sizeof(fdq)))
+		return -EFAULT;
+	if (!sb->s_qcop->set_xquota)
+		return -ENOSYS;
+	return sb->s_qcop->set_xquota(sb, type, id, &fdq);
+}
+
+static int quota_getxquota(struct super_block *sb, int type, qid_t id,
+			   void __user *addr)
+{
+	struct fs_disk_quota fdq;
+	int ret;
+
+	if (!sb->s_qcop->get_xquota)
+		return -ENOSYS;
+	ret = sb->s_qcop->get_xquota(sb, type, id, &fdq);
+	if (!ret && copy_to_user(addr, &fdq, sizeof(fdq)))
+		return -EFAULT;
+	return ret;
 }
 
 /* Copy parameters and call proper function */
@@ -240,117 +224,55 @@
 {
 	int ret;
 
+	if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS))
+		return -EINVAL;
+	if (!sb->s_qcop)
+		return -ENOSYS;
+
+	ret = check_quotactl_permission(sb, type, cmd, id);
+	if (ret < 0)
+		return ret;
+
 	switch (cmd) {
-		case Q_QUOTAON: {
-			char *pathname;
-
-			pathname = getname(addr);
-			if (IS_ERR(pathname))
-				return PTR_ERR(pathname);
-			ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0);
-			putname(pathname);
-			return ret;
-		}
-		case Q_QUOTAOFF:
-			return sb->s_qcop->quota_off(sb, type, 0);
-
-		case Q_GETFMT: {
-			__u32 fmt;
-
-			down_read(&sb_dqopt(sb)->dqptr_sem);
-			if (!sb_has_quota_active(sb, type)) {
-				up_read(&sb_dqopt(sb)->dqptr_sem);
-				return -ESRCH;
-			}
-			fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
-			up_read(&sb_dqopt(sb)->dqptr_sem);
-			if (copy_to_user(addr, &fmt, sizeof(fmt)))
-				return -EFAULT;
-			return 0;
-		}
-		case Q_GETINFO: {
-			struct if_dqinfo info;
-
-			ret = sb->s_qcop->get_info(sb, type, &info);
-			if (ret)
-				return ret;
-			if (copy_to_user(addr, &info, sizeof(info)))
-				return -EFAULT;
-			return 0;
-		}
-		case Q_SETINFO: {
-			struct if_dqinfo info;
-
-			if (copy_from_user(&info, addr, sizeof(info)))
-				return -EFAULT;
-			return sb->s_qcop->set_info(sb, type, &info);
-		}
-		case Q_GETQUOTA: {
-			struct if_dqblk idq;
-
-			ret = sb->s_qcop->get_dqblk(sb, type, id, &idq);
-			if (ret)
-				return ret;
-			if (copy_to_user(addr, &idq, sizeof(idq)))
-				return -EFAULT;
-			return 0;
-		}
-		case Q_SETQUOTA: {
-			struct if_dqblk idq;
-
-			if (copy_from_user(&idq, addr, sizeof(idq)))
-				return -EFAULT;
-			return sb->s_qcop->set_dqblk(sb, type, id, &idq);
-		}
-		case Q_SYNC:
-			if (sb)
-				sync_quota_sb(sb, type);
-			else
-				sync_dquots(type);
-			return 0;
-
-		case Q_XQUOTAON:
-		case Q_XQUOTAOFF:
-		case Q_XQUOTARM: {
-			__u32 flags;
-
-			if (copy_from_user(&flags, addr, sizeof(flags)))
-				return -EFAULT;
-			return sb->s_qcop->set_xstate(sb, flags, cmd);
-		}
-		case Q_XGETQSTAT: {
-			struct fs_quota_stat fqs;
-		
-			if ((ret = sb->s_qcop->get_xstate(sb, &fqs)))
-				return ret;
-			if (copy_to_user(addr, &fqs, sizeof(fqs)))
-				return -EFAULT;
-			return 0;
-		}
-		case Q_XSETQLIM: {
-			struct fs_disk_quota fdq;
-
-			if (copy_from_user(&fdq, addr, sizeof(fdq)))
-				return -EFAULT;
-		       return sb->s_qcop->set_xquota(sb, type, id, &fdq);
-		}
-		case Q_XGETQUOTA: {
-			struct fs_disk_quota fdq;
-
-			ret = sb->s_qcop->get_xquota(sb, type, id, &fdq);
-			if (ret)
-				return ret;
-			if (copy_to_user(addr, &fdq, sizeof(fdq)))
-				return -EFAULT;
-			return 0;
-		}
-		case Q_XQUOTASYNC:
-			return sb->s_qcop->quota_sync(sb, type);
-		/* We never reach here unless validity check is broken */
-		default:
-			BUG();
+	case Q_QUOTAON:
+		return quota_quotaon(sb, type, cmd, id, addr);
+	case Q_QUOTAOFF:
+		if (!sb->s_qcop->quota_off)
+			return -ENOSYS;
+		return sb->s_qcop->quota_off(sb, type, 0);
+	case Q_GETFMT:
+		return quota_getfmt(sb, type, addr);
+	case Q_GETINFO:
+		return quota_getinfo(sb, type, addr);
+	case Q_SETINFO:
+		return quota_setinfo(sb, type, addr);
+	case Q_GETQUOTA:
+		return quota_getquota(sb, type, id, addr);
+	case Q_SETQUOTA:
+		return quota_setquota(sb, type, id, addr);
+	case Q_SYNC:
+		if (!sb->s_qcop->quota_sync)
+			return -ENOSYS;
+		return sb->s_qcop->quota_sync(sb, type, 1);
+	case Q_XQUOTAON:
+	case Q_XQUOTAOFF:
+	case Q_XQUOTARM:
+		return quota_setxstate(sb, cmd, addr);
+	case Q_XGETQSTAT:
+		return quota_getxstate(sb, addr);
+	case Q_XSETQLIM:
+		return quota_setxquota(sb, type, id, addr);
+	case Q_XGETQUOTA:
+		return quota_getxquota(sb, type, id, addr);
+	case Q_XQUOTASYNC:
+		/* caller already holds s_umount */
+		if (sb->s_flags & MS_RDONLY)
+			return -EROFS;
+		writeback_inodes_sb(sb);
+		return 0;
+	default:
+		return -EINVAL;
 	}
-	return 0;
 }
 
 /*
@@ -397,224 +319,23 @@
 	cmds = cmd >> SUBCMDSHIFT;
 	type = cmd & SUBCMDMASK;
 
-	if (cmds != Q_SYNC || special) {
-		sb = quotactl_block(special);
-		if (IS_ERR(sb))
-			return PTR_ERR(sb);
+	/*
+	 * As a special case Q_SYNC can be called without a specific device.
+	 * It will iterate all superblocks that have quota enabled and call
+	 * the sync action on each of them.
+	 */
+	if (!special) {
+		if (cmds == Q_SYNC)
+			return quota_sync_all(type);
+		return -ENODEV;
 	}
 
-	ret = check_quotactl_valid(sb, type, cmds, id);
-	if (ret >= 0)
-		ret = do_quotactl(sb, type, cmds, id, addr);
-	if (sb)
-		drop_super(sb);
+	sb = quotactl_block(special);
+	if (IS_ERR(sb))
+		return PTR_ERR(sb);
 
+	ret = do_quotactl(sb, type, cmds, id, addr);
+
+	drop_super(sb);
 	return ret;
 }
-
-#if defined(CONFIG_COMPAT_FOR_U64_ALIGNMENT)
-/*
- * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
- * and is necessary due to alignment problems.
- */
-struct compat_if_dqblk {
-	compat_u64 dqb_bhardlimit;
-	compat_u64 dqb_bsoftlimit;
-	compat_u64 dqb_curspace;
-	compat_u64 dqb_ihardlimit;
-	compat_u64 dqb_isoftlimit;
-	compat_u64 dqb_curinodes;
-	compat_u64 dqb_btime;
-	compat_u64 dqb_itime;
-	compat_uint_t dqb_valid;
-};
-
-/* XFS structures */
-struct compat_fs_qfilestat {
-	compat_u64 dqb_bhardlimit;
-	compat_u64 qfs_nblks;
-	compat_uint_t qfs_nextents;
-};
-
-struct compat_fs_quota_stat {
-	__s8		qs_version;
-	__u16		qs_flags;
-	__s8		qs_pad;
-	struct compat_fs_qfilestat	qs_uquota;
-	struct compat_fs_qfilestat	qs_gquota;
-	compat_uint_t	qs_incoredqs;
-	compat_int_t	qs_btimelimit;
-	compat_int_t	qs_itimelimit;
-	compat_int_t	qs_rtbtimelimit;
-	__u16		qs_bwarnlimit;
-	__u16		qs_iwarnlimit;
-};
-
-asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
-						qid_t id, void __user *addr)
-{
-	unsigned int cmds;
-	struct if_dqblk __user *dqblk;
-	struct compat_if_dqblk __user *compat_dqblk;
-	struct fs_quota_stat __user *fsqstat;
-	struct compat_fs_quota_stat __user *compat_fsqstat;
-	compat_uint_t data;
-	u16 xdata;
-	long ret;
-
-	cmds = cmd >> SUBCMDSHIFT;
-
-	switch (cmds) {
-	case Q_GETQUOTA:
-		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
-		compat_dqblk = addr;
-		ret = sys_quotactl(cmd, special, id, dqblk);
-		if (ret)
-			break;
-		if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
-			get_user(data, &dqblk->dqb_valid) ||
-			put_user(data, &compat_dqblk->dqb_valid))
-			ret = -EFAULT;
-		break;
-	case Q_SETQUOTA:
-		dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
-		compat_dqblk = addr;
-		ret = -EFAULT;
-		if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
-			get_user(data, &compat_dqblk->dqb_valid) ||
-			put_user(data, &dqblk->dqb_valid))
-			break;
-		ret = sys_quotactl(cmd, special, id, dqblk);
-		break;
-	case Q_XGETQSTAT:
-		fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
-		compat_fsqstat = addr;
-		ret = sys_quotactl(cmd, special, id, fsqstat);
-		if (ret)
-			break;
-		ret = -EFAULT;
-		/* Copying qs_version, qs_flags, qs_pad */
-		if (copy_in_user(compat_fsqstat, fsqstat,
-			offsetof(struct compat_fs_quota_stat, qs_uquota)))
-			break;
-		/* Copying qs_uquota */
-		if (copy_in_user(&compat_fsqstat->qs_uquota,
-			&fsqstat->qs_uquota,
-			sizeof(compat_fsqstat->qs_uquota)) ||
-			get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
-			put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
-			break;
-		/* Copying qs_gquota */
-		if (copy_in_user(&compat_fsqstat->qs_gquota,
-			&fsqstat->qs_gquota,
-			sizeof(compat_fsqstat->qs_gquota)) ||
-			get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
-			put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
-			break;
-		/* Copying the rest */
-		if (copy_in_user(&compat_fsqstat->qs_incoredqs,
-			&fsqstat->qs_incoredqs,
-			sizeof(struct compat_fs_quota_stat) -
-			offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
-			get_user(xdata, &fsqstat->qs_iwarnlimit) ||
-			put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
-			break;
-		ret = 0;
-		break;
-	default:
-		ret = sys_quotactl(cmd, special, id, addr);
-	}
-	return ret;
-}
-#endif
-
-
-#ifdef CONFIG_QUOTA_NETLINK_INTERFACE
-
-/* Netlink family structure for quota */
-static struct genl_family quota_genl_family = {
-	.id = GENL_ID_GENERATE,
-	.hdrsize = 0,
-	.name = "VFS_DQUOT",
-	.version = 1,
-	.maxattr = QUOTA_NL_A_MAX,
-};
-
-/**
- * quota_send_warning - Send warning to userspace about exceeded quota
- * @type: The quota type: USRQQUOTA, GRPQUOTA,...
- * @id: The user or group id of the quota that was exceeded
- * @dev: The device on which the fs is mounted (sb->s_dev)
- * @warntype: The type of the warning: QUOTA_NL_...
- *
- * This can be used by filesystems (including those which don't use
- * dquot) to send a message to userspace relating to quota limits.
- *
- */
-
-void quota_send_warning(short type, unsigned int id, dev_t dev,
-			const char warntype)
-{
-	static atomic_t seq;
-	struct sk_buff *skb;
-	void *msg_head;
-	int ret;
-	int msg_size = 4 * nla_total_size(sizeof(u32)) +
-		       2 * nla_total_size(sizeof(u64));
-
-	/* We have to allocate using GFP_NOFS as we are called from a
-	 * filesystem performing write and thus further recursion into
-	 * the fs to free some data could cause deadlocks. */
-	skb = genlmsg_new(msg_size, GFP_NOFS);
-	if (!skb) {
-		printk(KERN_ERR
-		  "VFS: Not enough memory to send quota warning.\n");
-		return;
-	}
-	msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
-			&quota_genl_family, 0, QUOTA_NL_C_WARNING);
-	if (!msg_head) {
-		printk(KERN_ERR
-		  "VFS: Cannot store netlink header in quota warning.\n");
-		goto err_out;
-	}
-	ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, type);
-	if (ret)
-		goto attr_err_out;
-	ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, id);
-	if (ret)
-		goto attr_err_out;
-	ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype);
-	if (ret)
-		goto attr_err_out;
-	ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev));
-	if (ret)
-		goto attr_err_out;
-	ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev));
-	if (ret)
-		goto attr_err_out;
-	ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid());
-	if (ret)
-		goto attr_err_out;
-	genlmsg_end(skb, msg_head);
-
-	genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
-	return;
-attr_err_out:
-	printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
-err_out:
-	kfree_skb(skb);
-}
-EXPORT_SYMBOL(quota_send_warning);
-
-static int __init quota_init(void)
-{
-	if (genl_register_family(&quota_genl_family) != 0)
-		printk(KERN_ERR
-		       "VFS: Failed to create quota netlink interface.\n");
-	return 0;
-};
-
-module_init(quota_init);
-#endif
-
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index 65c8727..483442e 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -169,7 +169,7 @@
 			return 0;	// No free blocks in this bitmap
 		}
 
-		/* search for a first zero bit -- beggining of a window */
+		/* search for a first zero bit -- beginning of a window */
 		*beg = reiserfs_find_next_zero_le_bit
 		    ((unsigned long *)(bh->b_data), boundary, *beg);
 
@@ -425,7 +425,7 @@
 
 	journal_mark_dirty(th, s, sbh);
 	if (for_unformatted)
-		vfs_dq_free_block_nodirty(inode, 1);
+		dquot_free_block_nodirty(inode, 1);
 }
 
 void reiserfs_free_block(struct reiserfs_transaction_handle *th,
@@ -1049,7 +1049,7 @@
 			       amount_needed, hint->inode->i_uid);
 #endif
 		quota_ret =
-		    vfs_dq_alloc_block_nodirty(hint->inode, amount_needed);
+		    dquot_alloc_block_nodirty(hint->inode, amount_needed);
 		if (quota_ret)	/* Quota exceeded? */
 			return QUOTA_EXCEEDED;
 		if (hint->preallocate && hint->prealloc_size) {
@@ -1058,7 +1058,7 @@
 				       "reiserquota: allocating (prealloc) %d blocks id=%u",
 				       hint->prealloc_size, hint->inode->i_uid);
 #endif
-			quota_ret = vfs_dq_prealloc_block_nodirty(hint->inode,
+			quota_ret = dquot_prealloc_block_nodirty(hint->inode,
 							 hint->prealloc_size);
 			if (quota_ret)
 				hint->preallocate = hint->prealloc_size = 0;
@@ -1092,7 +1092,7 @@
 					       hint->inode->i_uid);
 #endif
 				/* Free not allocated blocks */
-				vfs_dq_free_block_nodirty(hint->inode,
+				dquot_free_block_nodirty(hint->inode,
 					amount_needed + hint->prealloc_size -
 					nr_allocated);
 			}
@@ -1125,7 +1125,7 @@
 			       REISERFS_I(hint->inode)->i_prealloc_count,
 			       hint->inode->i_uid);
 #endif
-		vfs_dq_free_block_nodirty(hint->inode, amount_needed +
+		dquot_free_block_nodirty(hint->inode, amount_needed +
 					 hint->prealloc_size - nr_allocated -
 					 REISERFS_I(hint->inode)->
 					 i_prealloc_count);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index da2dba0..1d9c127 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -289,7 +289,7 @@
 	.compat_ioctl = reiserfs_compat_ioctl,
 #endif
 	.mmap = reiserfs_file_mmap,
-	.open = generic_file_open,
+	.open = dquot_file_open,
 	.release = reiserfs_file_release,
 	.fsync = reiserfs_sync_file,
 	.aio_read = generic_file_aio_read,
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 2df0f5c..d1da94b 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -34,6 +34,9 @@
 	int depth;
 	int err;
 
+	if (!is_bad_inode(inode))
+		dquot_initialize(inode);
+
 	truncate_inode_pages(&inode->i_data, 0);
 
 	depth = reiserfs_write_lock_once(inode->i_sb);
@@ -54,7 +57,7 @@
 		 * after delete_object so that quota updates go into the same transaction as
 		 * stat data deletion */
 		if (!err) 
-			vfs_dq_free_inode(inode);
+			dquot_free_inode(inode);
 
 		if (journal_end(&th, inode->i_sb, jbegin_count))
 			goto out;
@@ -1615,7 +1618,7 @@
 ** to properly mark inodes for datasync and such, but only actually
 ** does something when called for a synchronous update.
 */
-int reiserfs_write_inode(struct inode *inode, int do_sync)
+int reiserfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	struct reiserfs_transaction_handle th;
 	int jbegin_count = 1;
@@ -1627,7 +1630,7 @@
 	 ** inode needs to reach disk for safety, and they can safely be
 	 ** ignored because the altered inode has already been logged.
 	 */
-	if (do_sync && !(current->flags & PF_MEMALLOC)) {
+	if (wbc->sync_mode == WB_SYNC_ALL && !(current->flags & PF_MEMALLOC)) {
 		reiserfs_write_lock(inode->i_sb);
 		if (!journal_begin(&th, inode->i_sb, jbegin_count)) {
 			reiserfs_update_sd(&th, inode);
@@ -1765,10 +1768,10 @@
 
 	BUG_ON(!th->t_trans_id);
 
-	if (vfs_dq_alloc_inode(inode)) {
-		err = -EDQUOT;
+	dquot_initialize(inode);
+	err = dquot_alloc_inode(inode);
+	if (err)
 		goto out_end_trans;
-	}
 	if (!dir->i_nlink) {
 		err = -EPERM;
 		goto out_bad_inode;
@@ -1959,12 +1962,12 @@
 	INODE_PKEY(inode)->k_objectid = 0;
 
 	/* Quota change must be inside a transaction for journaling */
-	vfs_dq_free_inode(inode);
+	dquot_free_inode(inode);
 
       out_end_trans:
 	journal_end(th, th->t_super, th->t_blocks_allocated);
 	/* Drop can be outside and it needs more credits so it's better to have it outside */
-	vfs_dq_drop(inode);
+	dquot_drop(inode);
 	inode->i_flags |= S_NOQUOTA;
 	make_bad_inode(inode);
 
@@ -3073,6 +3076,8 @@
 
 	depth = reiserfs_write_lock_once(inode->i_sb);
 	if (attr->ia_valid & ATTR_SIZE) {
+		dquot_initialize(inode);
+
 		/* version 2 items will be caught by the s_maxbytes check
 		 ** done for us in vmtruncate
 		 */
@@ -3134,8 +3139,7 @@
 						  jbegin_count);
 				if (error)
 					goto out;
-				error =
-				    vfs_dq_transfer(inode, attr) ? -EDQUOT : 0;
+				error = dquot_transfer(inode, attr);
 				if (error) {
 					journal_end(&th, inode->i_sb,
 						    jbegin_count);
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 9d4dcf0..96e4cbb 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -546,7 +546,7 @@
 */
 static int drop_new_inode(struct inode *inode)
 {
-	vfs_dq_drop(inode);
+	dquot_drop(inode);
 	make_bad_inode(inode);
 	inode->i_flags |= S_NOQUOTA;
 	iput(inode);
@@ -554,7 +554,7 @@
 }
 
 /* utility function that does setup for reiserfs_new_inode.
-** vfs_dq_init needs lots of credits so it's better to have it
+** dquot_initialize needs lots of credits so it's better to have it
 ** outside of a transaction, so we had to pull some bits of
 ** reiserfs_new_inode out into this func.
 */
@@ -577,7 +577,7 @@
 	} else {
 		inode->i_gid = current_fsgid();
 	}
-	vfs_dq_init(inode);
+	dquot_initialize(inode);
 	return 0;
 }
 
@@ -594,6 +594,8 @@
 	struct reiserfs_transaction_handle th;
 	struct reiserfs_security_handle security;
 
+	dquot_initialize(dir);
+
 	if (!(inode = new_inode(dir->i_sb))) {
 		return -ENOMEM;
 	}
@@ -666,6 +668,8 @@
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
 
+	dquot_initialize(dir);
+
 	if (!(inode = new_inode(dir->i_sb))) {
 		return -ENOMEM;
 	}
@@ -739,6 +743,8 @@
 	    2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb) +
 		 REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
 
+	dquot_initialize(dir);
+
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
 	/* set flag that new packing locality created and new blocks for the content     * of that directory are not displaced yet */
 	REISERFS_I(dir)->new_packing_locality = 1;
@@ -842,6 +848,8 @@
 	    JOURNAL_PER_BALANCE_CNT * 2 + 2 +
 	    4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
 
+	dquot_initialize(dir);
+
 	reiserfs_write_lock(dir->i_sb);
 	retval = journal_begin(&th, dir->i_sb, jbegin_count);
 	if (retval)
@@ -923,6 +931,8 @@
 	unsigned long savelink;
 	int depth;
 
+	dquot_initialize(dir);
+
 	inode = dentry->d_inode;
 
 	/* in this transaction we can be doing at max two balancings and update
@@ -1024,6 +1034,8 @@
 	    2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb) +
 		 REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb));
 
+	dquot_initialize(parent_dir);
+
 	if (!(inode = new_inode(parent_dir->i_sb))) {
 		return -ENOMEM;
 	}
@@ -1111,6 +1123,8 @@
 	    JOURNAL_PER_BALANCE_CNT * 3 +
 	    2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
 
+	dquot_initialize(dir);
+
 	reiserfs_write_lock(dir->i_sb);
 	if (inode->i_nlink >= REISERFS_LINK_MAX) {
 		//FIXME: sd_nlink is 32 bit for new files
@@ -1235,6 +1249,9 @@
 	    JOURNAL_PER_BALANCE_CNT * 3 + 5 +
 	    4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);
 
+	dquot_initialize(old_dir);
+	dquot_initialize(new_dir);
+
 	old_inode = old_dentry->d_inode;
 	new_dentry_inode = new_dentry->d_inode;
 
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 5fa7118..313d39d 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -1299,7 +1299,7 @@
 		       "reiserquota delete_item(): freeing %u, id=%u type=%c",
 		       quota_cut_bytes, inode->i_uid, head2type(&s_ih));
 #endif
-	vfs_dq_free_space_nodirty(inode, quota_cut_bytes);
+	dquot_free_space_nodirty(inode, quota_cut_bytes);
 
 	/* Return deleted body length */
 	return ret_value;
@@ -1383,7 +1383,7 @@
 					       quota_cut_bytes, inode->i_uid,
 					       key2type(key));
 #endif
-				vfs_dq_free_space_nodirty(inode,
+				dquot_free_space_nodirty(inode,
 							 quota_cut_bytes);
 			}
 			break;
@@ -1733,7 +1733,7 @@
 		       "reiserquota cut_from_item(): freeing %u id=%u type=%c",
 		       quota_cut_bytes, inode->i_uid, '?');
 #endif
-	vfs_dq_free_space_nodirty(inode, quota_cut_bytes);
+	dquot_free_space_nodirty(inode, quota_cut_bytes);
 	return ret_value;
 }
 
@@ -1968,9 +1968,10 @@
 		       key2type(&(key->on_disk_key)));
 #endif
 
-	if (vfs_dq_alloc_space_nodirty(inode, pasted_size)) {
+	retval = dquot_alloc_space_nodirty(inode, pasted_size);
+	if (retval) {
 		pathrelse(search_path);
-		return -EDQUOT;
+		return retval;
 	}
 	init_tb_struct(th, &s_paste_balance, th->t_super, search_path,
 		       pasted_size);
@@ -2024,7 +2025,7 @@
 		       pasted_size, inode->i_uid,
 		       key2type(&(key->on_disk_key)));
 #endif
-	vfs_dq_free_space_nodirty(inode, pasted_size);
+	dquot_free_space_nodirty(inode, pasted_size);
 	return retval;
 }
 
@@ -2062,9 +2063,10 @@
 #endif
 		/* We can't dirty inode here. It would be immediately written but
 		 * appropriate stat item isn't inserted yet... */
-		if (vfs_dq_alloc_space_nodirty(inode, quota_bytes)) {
+		retval = dquot_alloc_space_nodirty(inode, quota_bytes);
+		if (retval) {
 			pathrelse(path);
-			return -EDQUOT;
+			return retval;
 		}
 	}
 	init_tb_struct(th, &s_ins_balance, th->t_super, path,
@@ -2113,6 +2115,6 @@
 		       quota_bytes, inode->i_uid, head2type(ih));
 #endif
 	if (inode)
-		vfs_dq_free_space_nodirty(inode, quota_bytes);
+		dquot_free_space_nodirty(inode, quota_bytes);
 	return retval;
 }
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index b4a7dd0..04bf5d7 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -246,7 +246,7 @@
 			retval = remove_save_link_only(s, &save_link_key, 0);
 			continue;
 		}
-		vfs_dq_init(inode);
+		dquot_initialize(inode);
 
 		if (truncate && S_ISDIR(inode->i_mode)) {
 			/* We got a truncate request for a dir which is impossible.
@@ -578,6 +578,11 @@
 	reiserfs_write_unlock_once(inode->i_sb, lock_depth);
 }
 
+static void reiserfs_clear_inode(struct inode *inode)
+{
+	dquot_drop(inode);
+}
+
 #ifdef CONFIG_QUOTA
 static ssize_t reiserfs_quota_write(struct super_block *, int, const char *,
 				    size_t, loff_t);
@@ -590,6 +595,7 @@
 	.destroy_inode = reiserfs_destroy_inode,
 	.write_inode = reiserfs_write_inode,
 	.dirty_inode = reiserfs_dirty_inode,
+	.clear_inode = reiserfs_clear_inode,
 	.delete_inode = reiserfs_delete_inode,
 	.put_super = reiserfs_put_super,
 	.write_super = reiserfs_write_super,
@@ -616,13 +622,6 @@
 static int reiserfs_quota_on(struct super_block *, int, int, char *, int);
 
 static const struct dquot_operations reiserfs_quota_operations = {
-	.initialize = dquot_initialize,
-	.drop = dquot_drop,
-	.alloc_space = dquot_alloc_space,
-	.alloc_inode = dquot_alloc_inode,
-	.free_space = dquot_free_space,
-	.free_inode = dquot_free_inode,
-	.transfer = dquot_transfer,
 	.write_dquot = reiserfs_write_dquot,
 	.acquire_dquot = reiserfs_acquire_dquot,
 	.release_dquot = reiserfs_release_dquot,
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 81f09fa..37d034c 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -61,7 +61,6 @@
 static int xattr_create(struct inode *dir, struct dentry *dentry, int mode)
 {
 	BUG_ON(!mutex_is_locked(&dir->i_mutex));
-	vfs_dq_init(dir);
 	return dir->i_op->create(dir, dentry, mode, NULL);
 }
 #endif
@@ -69,7 +68,6 @@
 static int xattr_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	BUG_ON(!mutex_is_locked(&dir->i_mutex));
-	vfs_dq_init(dir);
 	return dir->i_op->mkdir(dir, dentry, mode);
 }
 
@@ -81,7 +79,6 @@
 {
 	int error;
 	BUG_ON(!mutex_is_locked(&dir->i_mutex));
-	vfs_dq_init(dir);
 
 	reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex,
 					I_MUTEX_CHILD, dir->i_sb);
@@ -97,7 +94,6 @@
 {
 	int error;
 	BUG_ON(!mutex_is_locked(&dir->i_mutex));
-	vfs_dq_init(dir);
 
 	reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex,
 					I_MUTEX_CHILD, dir->i_sb);
diff --git a/fs/select.c b/fs/select.c
index fd38ce2..500a669 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -691,6 +691,23 @@
 }
 #endif /* HAVE_SET_RESTORE_SIGMASK */
 
+#ifdef __ARCH_WANT_SYS_OLD_SELECT
+struct sel_arg_struct {
+	unsigned long n;
+	fd_set __user *inp, *outp, *exp;
+	struct timeval __user *tvp;
+};
+
+SYSCALL_DEFINE1(old_select, struct sel_arg_struct __user *, arg)
+{
+	struct sel_arg_struct a;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EFAULT;
+	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
+}
+#endif
+
 struct poll_list {
 	struct poll_list *next;
 	int len;
@@ -821,7 +838,7 @@
  	struct poll_list *walk = head;
  	unsigned long todo = nfds;
 
-	if (nfds > current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
+	if (nfds > rlimit(RLIMIT_NOFILE))
 		return -EINVAL;
 
 	len = min_t(unsigned int, nfds, N_STACK_PPS);
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 5afd554..e1f437b 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -734,7 +734,7 @@
  * seq_hlist_next - move to the next position of the hlist
  * @v:    the current iterator
  * @head: the head of the hlist
- * @pos:  the current posision
+ * @ppos: the current position
  *
  * Called at seq_file->op->next().
  */
@@ -800,7 +800,7 @@
  * seq_hlist_next_rcu - move to the next position of the hlist protected by RCU
  * @v:    the current iterator
  * @head: the head of the hlist
- * @pos:  the current posision
+ * @ppos: the current position
  *
  * Called at seq_file->op->next().
  *
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
index 70e3244..df8a19e 100644
--- a/fs/squashfs/Makefile
+++ b/fs/squashfs/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_SQUASHFS) += squashfs.o
 squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
-squashfs-y += namei.o super.o symlink.o
+squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 2a79603..1cb0d81 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.c
@@ -29,15 +29,14 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/mutex.h>
 #include <linux/string.h>
 #include <linux/buffer_head.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
 #include "squashfs_fs_i.h"
 #include "squashfs.h"
+#include "decompressor.h"
 
 /*
  * Read the metadata block length, this is stored in the first two
@@ -153,72 +152,10 @@
 	}
 
 	if (compressed) {
-		int zlib_err = 0, zlib_init = 0;
-
-		/*
-		 * Uncompress block.
-		 */
-
-		mutex_lock(&msblk->read_data_mutex);
-
-		msblk->stream.avail_out = 0;
-		msblk->stream.avail_in = 0;
-
-		bytes = length;
-		do {
-			if (msblk->stream.avail_in == 0 && k < b) {
-				avail = min(bytes, msblk->devblksize - offset);
-				bytes -= avail;
-				wait_on_buffer(bh[k]);
-				if (!buffer_uptodate(bh[k]))
-					goto release_mutex;
-
-				if (avail == 0) {
-					offset = 0;
-					put_bh(bh[k++]);
-					continue;
-				}
-
-				msblk->stream.next_in = bh[k]->b_data + offset;
-				msblk->stream.avail_in = avail;
-				offset = 0;
-			}
-
-			if (msblk->stream.avail_out == 0 && page < pages) {
-				msblk->stream.next_out = buffer[page++];
-				msblk->stream.avail_out = PAGE_CACHE_SIZE;
-			}
-
-			if (!zlib_init) {
-				zlib_err = zlib_inflateInit(&msblk->stream);
-				if (zlib_err != Z_OK) {
-					ERROR("zlib_inflateInit returned"
-						" unexpected result 0x%x,"
-						" srclength %d\n", zlib_err,
-						srclength);
-					goto release_mutex;
-				}
-				zlib_init = 1;
-			}
-
-			zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
-
-			if (msblk->stream.avail_in == 0 && k < b)
-				put_bh(bh[k++]);
-		} while (zlib_err == Z_OK);
-
-		if (zlib_err != Z_STREAM_END) {
-			ERROR("zlib_inflate error, data probably corrupt\n");
-			goto release_mutex;
-		}
-
-		zlib_err = zlib_inflateEnd(&msblk->stream);
-		if (zlib_err != Z_OK) {
-			ERROR("zlib_inflate error, data probably corrupt\n");
-			goto release_mutex;
-		}
-		length = msblk->stream.total_out;
-		mutex_unlock(&msblk->read_data_mutex);
+		length = squashfs_decompress(msblk, buffer, bh, b, offset,
+			 length, srclength, pages);
+		if (length < 0)
+			goto read_failure;
 	} else {
 		/*
 		 * Block is uncompressed.
@@ -255,9 +192,6 @@
 	kfree(bh);
 	return length;
 
-release_mutex:
-	mutex_unlock(&msblk->read_data_mutex);
-
 block_release:
 	for (; k < b; k++)
 		put_bh(bh[k]);
diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
index 40c98fa..57314be 100644
--- a/fs/squashfs/cache.c
+++ b/fs/squashfs/cache.c
@@ -51,7 +51,6 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
-#include <linux/zlib.h>
 #include <linux/pagemap.h>
 
 #include "squashfs_fs.h"
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
new file mode 100644
index 0000000..157478d
--- /dev/null
+++ b/fs/squashfs/decompressor.c
@@ -0,0 +1,68 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
+ *
+ * This program is free software; you can redistribute 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * decompressor.c
+ */
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/buffer_head.h>
+
+#include "squashfs_fs.h"
+#include "squashfs_fs_sb.h"
+#include "squashfs_fs_i.h"
+#include "decompressor.h"
+#include "squashfs.h"
+
+/*
+ * This file (and decompressor.h) implements a decompressor framework for
+ * Squashfs, allowing multiple decompressors to be easily supported
+ */
+
+static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = {
+	NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
+};
+
+static const struct squashfs_decompressor squashfs_lzo_unsupported_comp_ops = {
+	NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
+};
+
+static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
+	NULL, NULL, NULL, 0, "unknown", 0
+};
+
+static const struct squashfs_decompressor *decompressor[] = {
+	&squashfs_zlib_comp_ops,
+	&squashfs_lzma_unsupported_comp_ops,
+	&squashfs_lzo_unsupported_comp_ops,
+	&squashfs_unknown_comp_ops
+};
+
+
+const struct squashfs_decompressor *squashfs_lookup_decompressor(int id)
+{
+	int i;
+
+	for (i = 0; decompressor[i]->id; i++)
+		if (id == decompressor[i]->id)
+			break;
+
+	return decompressor[i];
+}
diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h
new file mode 100644
index 0000000..7425f80
--- /dev/null
+++ b/fs/squashfs/decompressor.h
@@ -0,0 +1,55 @@
+#ifndef DECOMPRESSOR_H
+#define DECOMPRESSOR_H
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
+ *
+ * This program is free software; you can redistribute 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * decompressor.h
+ */
+
+struct squashfs_decompressor {
+	void	*(*init)(struct squashfs_sb_info *);
+	void	(*free)(void *);
+	int	(*decompress)(struct squashfs_sb_info *, void **,
+		struct buffer_head **, int, int, int, int, int);
+	int	id;
+	char	*name;
+	int	supported;
+};
+
+static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk)
+{
+	return msblk->decompressor->init(msblk);
+}
+
+static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk,
+	void *s)
+{
+	if (msblk->decompressor)
+		msblk->decompressor->free(s);
+}
+
+static inline int squashfs_decompress(struct squashfs_sb_info *msblk,
+	void **buffer, struct buffer_head **bh, int b, int offset, int length,
+	int srclength, int pages)
+{
+	return msblk->decompressor->decompress(msblk, buffer, bh, b, offset,
+		length, srclength, pages);
+}
+#endif
diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c
index 566b0ea..12b933a 100644
--- a/fs/squashfs/dir.c
+++ b/fs/squashfs/dir.c
@@ -30,7 +30,6 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/export.c b/fs/squashfs/export.c
index 2b1b8fe..7f93d5a 100644
--- a/fs/squashfs/export.c
+++ b/fs/squashfs/export.c
@@ -39,7 +39,6 @@
 #include <linux/vfs.h>
 #include <linux/dcache.h>
 #include <linux/exportfs.h>
-#include <linux/zlib.h>
 #include <linux/slab.h>
 
 #include "squashfs_fs.h"
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
index 717767d..a25c506 100644
--- a/fs/squashfs/file.c
+++ b/fs/squashfs/file.c
@@ -47,7 +47,6 @@
 #include <linux/string.h>
 #include <linux/pagemap.h>
 #include <linux/mutex.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c
index b5a2c15..7c90bbd 100644
--- a/fs/squashfs/fragment.c
+++ b/fs/squashfs/fragment.c
@@ -36,7 +36,6 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c
index 3795b83..b7f64bc 100644
--- a/fs/squashfs/id.c
+++ b/fs/squashfs/id.c
@@ -34,7 +34,6 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index 9101dbd..49daaf6 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -40,7 +40,6 @@
 
 #include <linux/fs.h>
 #include <linux/vfs.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
index 9e39865..5266bd8 100644
--- a/fs/squashfs/namei.c
+++ b/fs/squashfs/namei.c
@@ -57,7 +57,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/dcache.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 0e9feb6..fe2587a 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -51,6 +51,9 @@
 				u64, int);
 extern int squashfs_read_table(struct super_block *, void *, u64, int);
 
+/* decompressor.c */
+extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
+
 /* export.c */
 extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
 				unsigned int);
@@ -71,7 +74,7 @@
 extern int squashfs_read_inode(struct inode *, long long);
 
 /*
- * Inodes and files operations
+ * Inodes, files and decompressor operations
  */
 
 /* dir.c */
@@ -88,3 +91,6 @@
 
 /* symlink.c */
 extern const struct address_space_operations squashfs_symlink_aops;
+
+/* zlib_wrapper.c */
+extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
index 283daaf..7902424 100644
--- a/fs/squashfs/squashfs_fs.h
+++ b/fs/squashfs/squashfs_fs.h
@@ -183,8 +183,6 @@
 #define SQUASHFS_MAX_FILE_SIZE		(1LL << \
 					(SQUASHFS_MAX_FILE_SIZE_LOG - 2))
 
-#define SQUASHFS_MARKER_BYTE		0xff
-
 /* meta index cache */
 #define SQUASHFS_META_INDEXES	(SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
 #define SQUASHFS_META_ENTRIES	127
@@ -211,7 +209,9 @@
 /*
  * definitions for structures on disk
  */
-#define ZLIB_COMPRESSION	 1
+#define ZLIB_COMPRESSION	1
+#define LZMA_COMPRESSION	2
+#define LZO_COMPRESSION		3
 
 struct squashfs_super_block {
 	__le32			s_magic;
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index c8c6561..2e77dc5 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -52,25 +52,25 @@
 };
 
 struct squashfs_sb_info {
-	int			devblksize;
-	int			devblksize_log2;
-	struct squashfs_cache	*block_cache;
-	struct squashfs_cache	*fragment_cache;
-	struct squashfs_cache	*read_page;
-	int			next_meta_index;
-	__le64			*id_table;
-	__le64			*fragment_index;
-	unsigned int		*fragment_index_2;
-	struct mutex		read_data_mutex;
-	struct mutex		meta_index_mutex;
-	struct meta_index	*meta_index;
-	z_stream		stream;
-	__le64			*inode_lookup_table;
-	u64			inode_table;
-	u64			directory_table;
-	unsigned int		block_size;
-	unsigned short		block_log;
-	long long		bytes_used;
-	unsigned int		inodes;
+	const struct squashfs_decompressor	*decompressor;
+	int					devblksize;
+	int					devblksize_log2;
+	struct squashfs_cache			*block_cache;
+	struct squashfs_cache			*fragment_cache;
+	struct squashfs_cache			*read_page;
+	int					next_meta_index;
+	__le64					*id_table;
+	__le64					*fragment_index;
+	struct mutex				read_data_mutex;
+	struct mutex				meta_index_mutex;
+	struct meta_index			*meta_index;
+	void					*stream;
+	__le64					*inode_lookup_table;
+	u64					inode_table;
+	u64					directory_table;
+	unsigned int				block_size;
+	unsigned short				block_log;
+	long long				bytes_used;
+	unsigned int				inodes;
 };
 #endif
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 6c197ef..3550aec 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -35,34 +35,41 @@
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/zlib.h>
 #include <linux/magic.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
 #include "squashfs_fs_i.h"
 #include "squashfs.h"
+#include "decompressor.h"
 
 static struct file_system_type squashfs_fs_type;
 static const struct super_operations squashfs_super_ops;
 
-static int supported_squashfs_filesystem(short major, short minor, short comp)
+static const struct squashfs_decompressor *supported_squashfs_filesystem(short
+	major, short minor, short id)
 {
+	const struct squashfs_decompressor *decompressor;
+
 	if (major < SQUASHFS_MAJOR) {
 		ERROR("Major/Minor mismatch, older Squashfs %d.%d "
 			"filesystems are unsupported\n", major, minor);
-		return -EINVAL;
+		return NULL;
 	} else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
 		ERROR("Major/Minor mismatch, trying to mount newer "
 			"%d.%d filesystem\n", major, minor);
 		ERROR("Please update your kernel\n");
-		return -EINVAL;
+		return NULL;
 	}
 
-	if (comp != ZLIB_COMPRESSION)
-		return -EINVAL;
+	decompressor = squashfs_lookup_decompressor(id);
+	if (!decompressor->supported) {
+		ERROR("Filesystem uses \"%s\" compression. This is not "
+			"supported\n", decompressor->name);
+		return NULL;
+	}
 
-	return 0;
+	return decompressor;
 }
 
 
@@ -87,13 +94,6 @@
 	}
 	msblk = sb->s_fs_info;
 
-	msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
-		GFP_KERNEL);
-	if (msblk->stream.workspace == NULL) {
-		ERROR("Failed to allocate zlib workspace\n");
-		goto failure;
-	}
-
 	sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
 	if (sblk == NULL) {
 		ERROR("Failed to allocate squashfs_super_block\n");
@@ -120,25 +120,25 @@
 		goto failed_mount;
 	}
 
+	err = -EINVAL;
+
 	/* Check it is a SQUASHFS superblock */
 	sb->s_magic = le32_to_cpu(sblk->s_magic);
 	if (sb->s_magic != SQUASHFS_MAGIC) {
 		if (!silent)
 			ERROR("Can't find a SQUASHFS superblock on %s\n",
 						bdevname(sb->s_bdev, b));
-		err = -EINVAL;
 		goto failed_mount;
 	}
 
-	/* Check the MAJOR & MINOR versions and compression type */
-	err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
+	/* Check the MAJOR & MINOR versions and lookup compression type */
+	msblk->decompressor = supported_squashfs_filesystem(
+			le16_to_cpu(sblk->s_major),
 			le16_to_cpu(sblk->s_minor),
 			le16_to_cpu(sblk->compression));
-	if (err < 0)
+	if (msblk->decompressor == NULL)
 		goto failed_mount;
 
-	err = -EINVAL;
-
 	/*
 	 * Check if there's xattrs in the filesystem.  These are not
 	 * supported in this version, so warn that they will be ignored.
@@ -205,6 +205,10 @@
 
 	err = -ENOMEM;
 
+	msblk->stream = squashfs_decompressor_init(msblk);
+	if (msblk->stream == NULL)
+		goto failed_mount;
+
 	msblk->block_cache = squashfs_cache_init("metadata",
 			SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
 	if (msblk->block_cache == NULL)
@@ -292,17 +296,16 @@
 	squashfs_cache_delete(msblk->block_cache);
 	squashfs_cache_delete(msblk->fragment_cache);
 	squashfs_cache_delete(msblk->read_page);
+	squashfs_decompressor_free(msblk, msblk->stream);
 	kfree(msblk->inode_lookup_table);
 	kfree(msblk->fragment_index);
 	kfree(msblk->id_table);
-	kfree(msblk->stream.workspace);
 	kfree(sb->s_fs_info);
 	sb->s_fs_info = NULL;
 	kfree(sblk);
 	return err;
 
 failure:
-	kfree(msblk->stream.workspace);
 	kfree(sb->s_fs_info);
 	sb->s_fs_info = NULL;
 	return -ENOMEM;
@@ -346,10 +349,10 @@
 		squashfs_cache_delete(sbi->block_cache);
 		squashfs_cache_delete(sbi->fragment_cache);
 		squashfs_cache_delete(sbi->read_page);
+		squashfs_decompressor_free(sbi, sbi->stream);
 		kfree(sbi->id_table);
 		kfree(sbi->fragment_index);
 		kfree(sbi->meta_index);
-		kfree(sbi->stream.workspace);
 		kfree(sb->s_fs_info);
 		sb->s_fs_info = NULL;
 	}
diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
index 83d8788..e80be20 100644
--- a/fs/squashfs/symlink.c
+++ b/fs/squashfs/symlink.c
@@ -36,7 +36,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/pagemap.h>
-#include <linux/zlib.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c
new file mode 100644
index 0000000..4dd70e0
--- /dev/null
+++ b/fs/squashfs/zlib_wrapper.c
@@ -0,0 +1,150 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Phillip Lougher <phillip@lougher.demon.co.uk>
+ *
+ * This program is free software; you can redistribute 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * zlib_wrapper.c
+ */
+
+
+#include <linux/mutex.h>
+#include <linux/buffer_head.h>
+#include <linux/zlib.h>
+
+#include "squashfs_fs.h"
+#include "squashfs_fs_sb.h"
+#include "squashfs_fs_i.h"
+#include "squashfs.h"
+#include "decompressor.h"
+
+static void *zlib_init(struct squashfs_sb_info *dummy)
+{
+	z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
+	if (stream == NULL)
+		goto failed;
+	stream->workspace = kmalloc(zlib_inflate_workspacesize(),
+		GFP_KERNEL);
+	if (stream->workspace == NULL)
+		goto failed;
+
+	return stream;
+
+failed:
+	ERROR("Failed to allocate zlib workspace\n");
+	kfree(stream);
+	return NULL;
+}
+
+
+static void zlib_free(void *strm)
+{
+	z_stream *stream = strm;
+
+	if (stream)
+		kfree(stream->workspace);
+	kfree(stream);
+}
+
+
+static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
+	struct buffer_head **bh, int b, int offset, int length, int srclength,
+	int pages)
+{
+	int zlib_err = 0, zlib_init = 0;
+	int avail, bytes, k = 0, page = 0;
+	z_stream *stream = msblk->stream;
+
+	mutex_lock(&msblk->read_data_mutex);
+
+	stream->avail_out = 0;
+	stream->avail_in = 0;
+
+	bytes = length;
+	do {
+		if (stream->avail_in == 0 && k < b) {
+			avail = min(bytes, msblk->devblksize - offset);
+			bytes -= avail;
+			wait_on_buffer(bh[k]);
+			if (!buffer_uptodate(bh[k]))
+				goto release_mutex;
+
+			if (avail == 0) {
+				offset = 0;
+				put_bh(bh[k++]);
+				continue;
+			}
+
+			stream->next_in = bh[k]->b_data + offset;
+			stream->avail_in = avail;
+			offset = 0;
+		}
+
+		if (stream->avail_out == 0 && page < pages) {
+			stream->next_out = buffer[page++];
+			stream->avail_out = PAGE_CACHE_SIZE;
+		}
+
+		if (!zlib_init) {
+			zlib_err = zlib_inflateInit(stream);
+			if (zlib_err != Z_OK) {
+				ERROR("zlib_inflateInit returned unexpected "
+					"result 0x%x, srclength %d\n",
+					zlib_err, srclength);
+				goto release_mutex;
+			}
+			zlib_init = 1;
+		}
+
+		zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH);
+
+		if (stream->avail_in == 0 && k < b)
+			put_bh(bh[k++]);
+	} while (zlib_err == Z_OK);
+
+	if (zlib_err != Z_STREAM_END) {
+		ERROR("zlib_inflate error, data probably corrupt\n");
+		goto release_mutex;
+	}
+
+	zlib_err = zlib_inflateEnd(stream);
+	if (zlib_err != Z_OK) {
+		ERROR("zlib_inflate error, data probably corrupt\n");
+		goto release_mutex;
+	}
+
+	mutex_unlock(&msblk->read_data_mutex);
+	return stream->total_out;
+
+release_mutex:
+	mutex_unlock(&msblk->read_data_mutex);
+
+	for (; k < b; k++)
+		put_bh(bh[k]);
+
+	return -EIO;
+}
+
+const struct squashfs_decompressor squashfs_zlib_comp_ops = {
+	.init = zlib_init,
+	.free = zlib_free,
+	.decompress = zlib_uncompress,
+	.id = ZLIB_COMPRESSION,
+	.name = "zlib",
+	.supported = 1
+};
+
diff --git a/fs/super.c b/fs/super.c
index aff046b..f35ac60 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -568,7 +568,7 @@
 int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
 {
 	int retval;
-	int remount_rw;
+	int remount_rw, remount_ro;
 
 	if (sb->s_frozen != SB_UNFROZEN)
 		return -EBUSY;
@@ -583,9 +583,12 @@
 	shrink_dcache_sb(sb);
 	sync_filesystem(sb);
 
+	remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY);
+	remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY);
+
 	/* If we are remounting RDONLY and current sb is read/write,
 	   make sure there are no rw files opened */
-	if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) {
+	if (remount_ro) {
 		if (force)
 			mark_files_ro(sb);
 		else if (!fs_may_remount_ro(sb))
@@ -594,7 +597,6 @@
 		if (retval < 0 && retval != -ENOSYS)
 			return -EBUSY;
 	}
-	remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY);
 
 	if (sb->s_op->remount_fs) {
 		retval = sb->s_op->remount_fs(sb, &flags, data);
@@ -604,6 +606,16 @@
 	sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
 	if (remount_rw)
 		vfs_dq_quota_on_remount(sb);
+	/*
+	 * Some filesystems modify their metadata via some other path than the
+	 * bdev buffer cache (eg. use a private mapping, or directories in
+	 * pagecache, etc). Also file data modifications go via their own
+	 * mappings. So If we try to mount readonly then copy the filesystem
+	 * from bdev, we could get stale data, so invalidate it to give a best
+	 * effort at coherency.
+	 */
+	if (remount_ro && sb->s_bdev)
+		invalidate_bdev(sb->s_bdev);
 	return 0;
 }
 
@@ -925,6 +937,9 @@
 	if (!mnt)
 		goto out;
 
+	if (flags & MS_KERNMOUNT)
+		mnt->mnt_flags = MNT_INTERNAL;
+
 	if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
 		secdata = alloc_secdata();
 		if (!secdata)
diff --git a/fs/sync.c b/fs/sync.c
index 418727a..f557d71 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -34,14 +34,14 @@
 	if (!sb->s_bdi)
 		return 0;
 
-	/* Avoid doing twice syncing and cache pruning for quota sync */
-	if (!wait) {
-		writeout_quota_sb(sb, -1);
-		writeback_inodes_sb(sb);
-	} else {
-		sync_quota_sb(sb, -1);
+	if (sb->s_qcop && sb->s_qcop->quota_sync)
+		sb->s_qcop->quota_sync(sb, -1, wait);
+
+	if (wait)
 		sync_inodes_sb(sb);
-	}
+	else
+		writeback_inodes_sb(sb);
+
 	if (sb->s_op->sync_fs)
 		sb->s_op->sync_fs(sb, wait);
 	return __sync_blockdev(sb->s_bdev, wait);
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index a0a500a..e9d2935 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -54,14 +54,14 @@
 	int rc;
 
 	/* need attr_sd for attr, its parent for kobj */
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return -ENODEV;
 
 	rc = -EIO;
 	if (attr->read)
 		rc = attr->read(kobj, attr, buffer, off, count);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 
 	return rc;
 }
@@ -125,14 +125,14 @@
 	int rc;
 
 	/* need attr_sd for attr, its parent for kobj */
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return -ENODEV;
 
 	rc = -EIO;
 	if (attr->write)
 		rc = attr->write(kobj, attr, buffer, offset, count);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 
 	return rc;
 }
@@ -184,12 +184,12 @@
 	if (!bb->vm_ops || !bb->vm_ops->open)
 		return;
 
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return;
 
 	bb->vm_ops->open(vma);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 }
 
 static void bin_vma_close(struct vm_area_struct *vma)
@@ -201,12 +201,12 @@
 	if (!bb->vm_ops || !bb->vm_ops->close)
 		return;
 
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return;
 
 	bb->vm_ops->close(vma);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 }
 
 static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -219,12 +219,12 @@
 	if (!bb->vm_ops || !bb->vm_ops->fault)
 		return VM_FAULT_SIGBUS;
 
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return VM_FAULT_SIGBUS;
 
 	ret = bb->vm_ops->fault(vma, vmf);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 	return ret;
 }
 
@@ -241,12 +241,12 @@
 	if (!bb->vm_ops->page_mkwrite)
 		return 0;
 
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return VM_FAULT_SIGBUS;
 
 	ret = bb->vm_ops->page_mkwrite(vma, vmf);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 	return ret;
 }
 
@@ -261,12 +261,12 @@
 	if (!bb->vm_ops || !bb->vm_ops->access)
 		return -EINVAL;
 
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return -EINVAL;
 
 	ret = bb->vm_ops->access(vma, addr, buf, len, write);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 	return ret;
 }
 
@@ -281,12 +281,12 @@
 	if (!bb->vm_ops || !bb->vm_ops->set_policy)
 		return 0;
 
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return -EINVAL;
 
 	ret = bb->vm_ops->set_policy(vma, new);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 	return ret;
 }
 
@@ -301,12 +301,12 @@
 	if (!bb->vm_ops || !bb->vm_ops->get_policy)
 		return vma->vm_policy;
 
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return vma->vm_policy;
 
 	pol = bb->vm_ops->get_policy(vma, addr);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 	return pol;
 }
 
@@ -321,12 +321,12 @@
 	if (!bb->vm_ops || !bb->vm_ops->migrate)
 		return 0;
 
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return 0;
 
 	ret = bb->vm_ops->migrate(vma, from, to, flags);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 	return ret;
 }
 #endif
@@ -356,7 +356,7 @@
 
 	/* need attr_sd for attr, its parent for kobj */
 	rc = -ENODEV;
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		goto out_unlock;
 
 	rc = -EINVAL;
@@ -384,7 +384,7 @@
 	bb->vm_ops = vma->vm_ops;
 	vma->vm_ops = &bin_vm_ops;
 out_put:
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 out_unlock:
 	mutex_unlock(&bb->mutex);
 
@@ -399,7 +399,7 @@
 	int error;
 
 	/* binary file operations requires both @sd and its parent */
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return -ENODEV;
 
 	error = -EACCES;
@@ -426,11 +426,11 @@
 	mutex_unlock(&sysfs_bin_lock);
 
 	/* open succeeded, put active references */
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 	return 0;
 
  err_out:
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 	kfree(bb);
 	return error;
 }
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 699f371..5907178 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -93,7 +93,7 @@
  *	RETURNS:
  *	Pointer to @sd on success, NULL on failure.
  */
-static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
+struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
 {
 	if (unlikely(!sd))
 		return NULL;
@@ -124,7 +124,7 @@
  *	Put an active reference to @sd.  This function is noop if @sd
  *	is NULL.
  */
-static void sysfs_put_active(struct sysfs_dirent *sd)
+void sysfs_put_active(struct sysfs_dirent *sd)
 {
 	struct completion *cmpl;
 	int v;
@@ -145,45 +145,6 @@
 }
 
 /**
- *	sysfs_get_active_two - get active references to sysfs_dirent and parent
- *	@sd: sysfs_dirent of interest
- *
- *	Get active reference to @sd and its parent.  Parent's active
- *	reference is grabbed first.  This function is noop if @sd is
- *	NULL.
- *
- *	RETURNS:
- *	Pointer to @sd on success, NULL on failure.
- */
-struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd)
-{
-	if (sd) {
-		if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent)))
-			return NULL;
-		if (unlikely(!sysfs_get_active(sd))) {
-			sysfs_put_active(sd->s_parent);
-			return NULL;
-		}
-	}
-	return sd;
-}
-
-/**
- *	sysfs_put_active_two - put active references to sysfs_dirent and parent
- *	@sd: sysfs_dirent of interest
- *
- *	Put active references to @sd and its parent.  This function is
- *	noop if @sd is NULL.
- */
-void sysfs_put_active_two(struct sysfs_dirent *sd)
-{
-	if (sd) {
-		sysfs_put_active(sd);
-		sysfs_put_active(sd->s_parent);
-	}
-}
-
-/**
  *	sysfs_deactivate - deactivate sysfs_dirent
  *	@sd: sysfs_dirent to deactivate
  *
@@ -195,6 +156,10 @@
 	int v;
 
 	BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
+
+	if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF))
+		return;
+
 	sd->s_sibling = (void *)&wait;
 
 	rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_);
@@ -354,7 +319,6 @@
 
 	atomic_set(&sd->s_count, 1);
 	atomic_set(&sd->s_active, 0);
-	sysfs_dirent_init_lockdep(sd);
 
 	sd->s_name = name;
 	sd->s_mode = mode;
@@ -681,7 +645,7 @@
 	}
 
 	/* attach dentry and inode */
-	inode = sysfs_get_inode(sd);
+	inode = sysfs_get_inode(dir->i_sb, sd);
 	if (!inode) {
 		ret = ERR_PTR(-ENOMEM);
 		goto out_unlock;
@@ -837,11 +801,46 @@
 	return (sd->s_mode >> 12) & 15;
 }
 
+static int sysfs_dir_release(struct inode *inode, struct file *filp)
+{
+	sysfs_put(filp->private_data);
+	return 0;
+}
+
+static struct sysfs_dirent *sysfs_dir_pos(struct sysfs_dirent *parent_sd,
+	ino_t ino, struct sysfs_dirent *pos)
+{
+	if (pos) {
+		int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) &&
+			pos->s_parent == parent_sd &&
+			ino == pos->s_ino;
+		sysfs_put(pos);
+		if (valid)
+			return pos;
+	}
+	pos = NULL;
+	if ((ino > 1) && (ino < INT_MAX)) {
+		pos = parent_sd->s_dir.children;
+		while (pos && (ino > pos->s_ino))
+			pos = pos->s_sibling;
+	}
+	return pos;
+}
+
+static struct sysfs_dirent *sysfs_dir_next_pos(struct sysfs_dirent *parent_sd,
+	ino_t ino, struct sysfs_dirent *pos)
+{
+	pos = sysfs_dir_pos(parent_sd, ino, pos);
+	if (pos)
+		pos = pos->s_sibling;
+	return pos;
+}
+
 static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
 	struct dentry *dentry = filp->f_path.dentry;
 	struct sysfs_dirent * parent_sd = dentry->d_fsdata;
-	struct sysfs_dirent *pos;
+	struct sysfs_dirent *pos = filp->private_data;
 	ino_t ino;
 
 	if (filp->f_pos == 0) {
@@ -857,29 +856,31 @@
 		if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0)
 			filp->f_pos++;
 	}
-	if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) {
-		mutex_lock(&sysfs_mutex);
+	mutex_lock(&sysfs_mutex);
+	for (pos = sysfs_dir_pos(parent_sd, filp->f_pos, pos);
+	     pos;
+	     pos = sysfs_dir_next_pos(parent_sd, filp->f_pos, pos)) {
+		const char * name;
+		unsigned int type;
+		int len, ret;
 
-		/* Skip the dentries we have already reported */
-		pos = parent_sd->s_dir.children;
-		while (pos && (filp->f_pos > pos->s_ino))
-			pos = pos->s_sibling;
+		name = pos->s_name;
+		len = strlen(name);
+		ino = pos->s_ino;
+		type = dt_type(pos);
+		filp->f_pos = ino;
+		filp->private_data = sysfs_get(pos);
 
-		for ( ; pos; pos = pos->s_sibling) {
-			const char * name;
-			int len;
-
-			name = pos->s_name;
-			len = strlen(name);
-			filp->f_pos = ino = pos->s_ino;
-
-			if (filldir(dirent, name, len, filp->f_pos, ino,
-					 dt_type(pos)) < 0)
-				break;
-		}
-		if (!pos)
-			filp->f_pos = INT_MAX;
 		mutex_unlock(&sysfs_mutex);
+		ret = filldir(dirent, name, len, filp->f_pos, ino, type);
+		mutex_lock(&sysfs_mutex);
+		if (ret < 0)
+			break;
+	}
+	mutex_unlock(&sysfs_mutex);
+	if ((filp->f_pos > 1) && !pos) { /* EOF */
+		filp->f_pos = INT_MAX;
+		filp->private_data = NULL;
 	}
 	return 0;
 }
@@ -888,5 +889,6 @@
 const struct file_operations sysfs_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= sysfs_readdir,
+	.release	= sysfs_dir_release,
 	.llseek		= generic_file_llseek,
 };
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index dc30d9e..e222b25 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -53,7 +53,7 @@
 	size_t			count;
 	loff_t			pos;
 	char			* page;
-	struct sysfs_ops	* ops;
+	const struct sysfs_ops	* ops;
 	struct mutex		mutex;
 	int			needs_read_fill;
 	int			event;
@@ -75,7 +75,7 @@
 {
 	struct sysfs_dirent *attr_sd = dentry->d_fsdata;
 	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-	struct sysfs_ops * ops = buffer->ops;
+	const struct sysfs_ops * ops = buffer->ops;
 	int ret = 0;
 	ssize_t count;
 
@@ -85,13 +85,13 @@
 		return -ENOMEM;
 
 	/* need attr_sd for attr and ops, its parent for kobj */
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return -ENODEV;
 
 	buffer->event = atomic_read(&attr_sd->s_attr.open->event);
 	count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 
 	/*
 	 * The code works fine with PAGE_SIZE return but it's likely to
@@ -199,16 +199,16 @@
 {
 	struct sysfs_dirent *attr_sd = dentry->d_fsdata;
 	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-	struct sysfs_ops * ops = buffer->ops;
+	const struct sysfs_ops * ops = buffer->ops;
 	int rc;
 
 	/* need attr_sd for attr and ops, its parent for kobj */
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return -ENODEV;
 
 	rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 
 	return rc;
 }
@@ -335,7 +335,7 @@
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
 	struct sysfs_buffer *buffer;
-	struct sysfs_ops *ops;
+	const struct sysfs_ops *ops;
 	int error = -EACCES;
 	char *p;
 
@@ -344,7 +344,7 @@
 		memmove(last_sysfs_file, p, strlen(p) + 1);
 
 	/* need attr_sd for attr and ops, its parent for kobj */
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		return -ENODEV;
 
 	/* every kobject with an attribute needs a ktype assigned */
@@ -393,13 +393,13 @@
 		goto err_free;
 
 	/* open succeeded, put active references */
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 	return 0;
 
  err_free:
 	kfree(buffer);
  err_out:
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 	return error;
 }
 
@@ -437,12 +437,12 @@
 	struct sysfs_open_dirent *od = attr_sd->s_attr.open;
 
 	/* need parent for the kobj, grab both */
-	if (!sysfs_get_active_two(attr_sd))
+	if (!sysfs_get_active(attr_sd))
 		goto trigger;
 
 	poll_wait(filp, &od->poll, wait);
 
-	sysfs_put_active_two(attr_sd);
+	sysfs_put_active(attr_sd);
 
 	if (buffer->event != atomic_read(&od->event))
 		goto trigger;
@@ -509,6 +509,7 @@
 	if (!sd)
 		return -ENOMEM;
 	sd->s_attr.attr = (void *)attr;
+	sysfs_dirent_init_lockdep(sd);
 
 	sysfs_addrm_start(&acxt, dir_sd);
 	rc = sysfs_add_one(&acxt, sd);
@@ -542,6 +543,18 @@
 
 }
 
+int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
+{
+	int err = 0;
+	int i;
+
+	for (i = 0; ptr[i] && !err; i++)
+		err = sysfs_create_file(kobj, ptr[i]);
+	if (err)
+		while (--i >= 0)
+			sysfs_remove_file(kobj, ptr[i]);
+	return err;
+}
 
 /**
  * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
@@ -614,6 +627,12 @@
 	sysfs_hash_and_remove(kobj->sd, attr->name);
 }
 
+void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr)
+{
+	int i;
+	for (i = 0; ptr[i]; i++)
+		sysfs_remove_file(kobj, ptr[i]);
+}
 
 /**
  * sysfs_remove_file_from_group - remove an attribute file from a group.
@@ -732,3 +751,5 @@
 
 EXPORT_SYMBOL_GPL(sysfs_create_file);
 EXPORT_SYMBOL_GPL(sysfs_remove_file);
+EXPORT_SYMBOL_GPL(sysfs_remove_files);
+EXPORT_SYMBOL_GPL(sysfs_create_files);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 6a06a1d..082daae 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -111,20 +111,20 @@
 	if (!sd)
 		return -EINVAL;
 
+	mutex_lock(&sysfs_mutex);
 	error = inode_change_ok(inode, iattr);
 	if (error)
-		return error;
+		goto out;
 
 	iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
 
 	error = inode_setattr(inode, iattr);
 	if (error)
-		return error;
+		goto out;
 
-	mutex_lock(&sysfs_mutex);
 	error = sysfs_sd_setattr(sd, iattr);
+out:
 	mutex_unlock(&sysfs_mutex);
-
 	return error;
 }
 
@@ -283,6 +283,7 @@
 
 /**
  *	sysfs_get_inode - get inode for sysfs_dirent
+ *	@sb: super block
  *	@sd: sysfs_dirent to allocate inode for
  *
  *	Get inode for @sd.  If such inode doesn't exist, a new inode
@@ -295,11 +296,11 @@
  *	RETURNS:
  *	Pointer to allocated inode on success, NULL on failure.
  */
-struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
+struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd)
 {
 	struct inode *inode;
 
-	inode = iget_locked(sysfs_sb, sd->s_ino);
+	inode = iget_locked(sb, sd->s_ino);
 	if (inode && (inode->i_state & I_NEW))
 		sysfs_init_inode(sd, inode);
 
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 4974995..0cb1088 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -23,7 +23,6 @@
 
 
 static struct vfsmount *sysfs_mount;
-struct super_block * sysfs_sb = NULL;
 struct kmem_cache *sysfs_dir_cachep;
 
 static const struct super_operations sysfs_ops = {
@@ -50,11 +49,10 @@
 	sb->s_magic = SYSFS_MAGIC;
 	sb->s_op = &sysfs_ops;
 	sb->s_time_gran = 1;
-	sysfs_sb = sb;
 
 	/* get root inode, initialize and unlock it */
 	mutex_lock(&sysfs_mutex);
-	inode = sysfs_get_inode(&sysfs_root);
+	inode = sysfs_get_inode(sb, &sysfs_root);
 	mutex_unlock(&sysfs_mutex);
 	if (!inode) {
 		pr_debug("sysfs: could not get root inode\n");
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index c5eff49..1b9a3a1 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -123,6 +123,44 @@
 	sysfs_hash_and_remove(parent_sd, name);
 }
 
+/**
+ *	sysfs_rename_link - rename symlink in object's directory.
+ *	@kobj:	object we're acting for.
+ *	@targ:	object we're pointing to.
+ *	@old:	previous name of the symlink.
+ *	@new:	new name of the symlink.
+ *
+ *	A helper function for the common rename symlink idiom.
+ */
+int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
+			const char *old, const char *new)
+{
+	struct sysfs_dirent *parent_sd, *sd = NULL;
+	int result;
+
+	if (!kobj)
+		parent_sd = &sysfs_root;
+	else
+		parent_sd = kobj->sd;
+
+	result = -ENOENT;
+	sd = sysfs_get_dirent(parent_sd, old);
+	if (!sd)
+		goto out;
+
+	result = -EINVAL;
+	if (sysfs_type(sd) != SYSFS_KOBJ_LINK)
+		goto out;
+	if (sd->s_symlink.target_sd->s_dir.kobj != targ)
+		goto out;
+
+	result = sysfs_rename(sd, parent_sd, new);
+
+out:
+	sysfs_put(sd);
+	return result;
+}
+
 static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
 				 struct sysfs_dirent *target_sd, char *path)
 {
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index cdd9377..30f5a44 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -66,8 +66,8 @@
 	};
 
 	unsigned int		s_flags;
+	unsigned short		s_mode;
 	ino_t			s_ino;
-	umode_t			s_mode;
 	struct sysfs_inode_attrs *s_iattr;
 };
 
@@ -79,6 +79,7 @@
 #define SYSFS_KOBJ_BIN_ATTR		0x0004
 #define SYSFS_KOBJ_LINK			0x0008
 #define SYSFS_COPY_NAME			(SYSFS_DIR | SYSFS_KOBJ_LINK)
+#define SYSFS_ACTIVE_REF		(SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR)
 
 #define SYSFS_FLAG_MASK			~SYSFS_TYPE_MASK
 #define SYSFS_FLAG_REMOVED		0x0200
@@ -91,9 +92,12 @@
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 #define sysfs_dirent_init_lockdep(sd)				\
 do {								\
-	static struct lock_class_key __key;			\
+	struct attribute *attr = sd->s_attr.attr;		\
+	struct lock_class_key *key = attr->key;			\
+	if (!key)						\
+		key = &attr->skey;				\
 								\
-	lockdep_init_map(&sd->dep_map, "s_active", &__key, 0);	\
+	lockdep_init_map(&sd->dep_map, "s_active", key, 0);	\
 } while(0)
 #else
 #define sysfs_dirent_init_lockdep(sd) do {} while(0)
@@ -111,7 +115,6 @@
  * mount.c
  */
 extern struct sysfs_dirent sysfs_root;
-extern struct super_block *sysfs_sb;
 extern struct kmem_cache *sysfs_dir_cachep;
 
 /*
@@ -124,8 +127,8 @@
 extern const struct inode_operations sysfs_dir_inode_operations;
 
 struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
-struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
-void sysfs_put_active_two(struct sysfs_dirent *sd);
+struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
+void sysfs_put_active(struct sysfs_dirent *sd);
 void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
 		       struct sysfs_dirent *parent_sd);
 int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
@@ -168,7 +171,7 @@
 /*
  * inode.c
  */
-struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
+struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd);
 void sysfs_delete_inode(struct inode *inode);
 int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
 int sysfs_permission(struct inode *inode, int mask);
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 9824743..4573734 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -26,6 +26,7 @@
 #include <linux/init.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
+#include <linux/writeback.h>
 #include <linux/namei.h>
 #include <asm/byteorder.h>
 #include "sysv.h"
@@ -246,7 +247,7 @@
 	return ERR_PTR(-EIO);
 }
 
-int sysv_write_inode(struct inode *inode, int wait)
+static int __sysv_write_inode(struct inode *inode, int wait)
 {
 	struct super_block * sb = inode->i_sb;
 	struct sysv_sb_info * sbi = SYSV_SB(sb);
@@ -296,9 +297,14 @@
 	return 0;
 }
 
+int sysv_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+	return __sysv_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+}
+
 int sysv_sync_inode(struct inode *inode)
 {
-	return sysv_write_inode(inode, 1);
+	return __sysv_write_inode(inode, 1);
 }
 
 static void sysv_delete_inode(struct inode *inode)
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index 53786eb..94cb9b4 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -142,7 +142,7 @@
 
 /* inode.c */
 extern struct inode *sysv_iget(struct super_block *, unsigned int);
-extern int sysv_write_inode(struct inode *, int);
+extern int sysv_write_inode(struct inode *, struct writeback_control *wbc);
 extern int sysv_sync_inode(struct inode *);
 extern void sysv_set_inode(struct inode *, dev_t);
 extern int sysv_getattr(struct vfsmount *, struct dentry *, struct kstat *);
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 552fb01..401e503 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1120,7 +1120,7 @@
 	if (release)
 		ubifs_release_budget(c, &ino_req);
 	if (IS_SYNC(old_inode))
-		err = old_inode->i_sb->s_op->write_inode(old_inode, 1);
+		err = old_inode->i_sb->s_op->write_inode(old_inode, NULL);
 	return err;
 
 out_cancel:
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 16a6444..e26c02a 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1011,7 +1011,7 @@
 	/* Is the page fully inside @i_size? */
 	if (page->index < end_index) {
 		if (page->index >= synced_i_size >> PAGE_CACHE_SHIFT) {
-			err = inode->i_sb->s_op->write_inode(inode, 1);
+			err = inode->i_sb->s_op->write_inode(inode, NULL);
 			if (err)
 				goto out_unlock;
 			/*
@@ -1039,7 +1039,7 @@
 	kunmap_atomic(kaddr, KM_USER0);
 
 	if (i_size > synced_i_size) {
-		err = inode->i_sb->s_op->write_inode(inode, 1);
+		err = inode->i_sb->s_op->write_inode(inode, NULL);
 		if (err)
 			goto out_unlock;
 	}
@@ -1242,7 +1242,7 @@
 	if (release)
 		ubifs_release_budget(c, &req);
 	if (IS_SYNC(inode))
-		err = inode->i_sb->s_op->write_inode(inode, 1);
+		err = inode->i_sb->s_op->write_inode(inode, NULL);
 	return err;
 
 out:
@@ -1316,7 +1316,7 @@
 	 * the inode unless this is a 'datasync()' call.
 	 */
 	if (!datasync || (inode->i_state & I_DIRTY_DATASYNC)) {
-		err = inode->i_sb->s_op->write_inode(inode, 1);
+		err = inode->i_sb->s_op->write_inode(inode, NULL);
 		if (err)
 			return err;
 	}
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 43f9d19..4d2f215 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -283,7 +283,7 @@
 /*
  * Note, Linux write-back code calls this without 'i_mutex'.
  */
-static int ubifs_write_inode(struct inode *inode, int wait)
+static int ubifs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	int err = 0;
 	struct ubifs_info *c = inode->i_sb->s_fs_info;
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index 82372e3..19626e2 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -31,55 +31,8 @@
 #define udf_clear_bit(nr, addr) ext2_clear_bit(nr, addr)
 #define udf_set_bit(nr, addr) ext2_set_bit(nr, addr)
 #define udf_test_bit(nr, addr) ext2_test_bit(nr, addr)
-#define udf_find_first_one_bit(addr, size) find_first_one_bit(addr, size)
 #define udf_find_next_one_bit(addr, size, offset) \
-		find_next_one_bit(addr, size, offset)
-
-#define leBPL_to_cpup(x) leNUM_to_cpup(BITS_PER_LONG, x)
-#define leNUM_to_cpup(x, y) xleNUM_to_cpup(x, y)
-#define xleNUM_to_cpup(x, y) (le ## x ## _to_cpup(y))
-#define uintBPL_t uint(BITS_PER_LONG)
-#define uint(x) xuint(x)
-#define xuint(x) __le ## x
-
-static inline int find_next_one_bit(void *addr, int size, int offset)
-{
-	uintBPL_t *p = ((uintBPL_t *) addr) + (offset / BITS_PER_LONG);
-	int result = offset & ~(BITS_PER_LONG - 1);
-	unsigned long tmp;
-
-	if (offset >= size)
-		return size;
-	size -= result;
-	offset &= (BITS_PER_LONG - 1);
-	if (offset) {
-		tmp = leBPL_to_cpup(p++);
-		tmp &= ~0UL << offset;
-		if (size < BITS_PER_LONG)
-			goto found_first;
-		if (tmp)
-			goto found_middle;
-		size -= BITS_PER_LONG;
-		result += BITS_PER_LONG;
-	}
-	while (size & ~(BITS_PER_LONG - 1)) {
-		tmp = leBPL_to_cpup(p++);
-		if (tmp)
-			goto found_middle;
-		result += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-	}
-	if (!size)
-		return result;
-	tmp = leBPL_to_cpup(p);
-found_first:
-	tmp &= ~0UL >> (BITS_PER_LONG - size);
-found_middle:
-	return result + ffz(~tmp);
-}
-
-#define find_first_one_bit(addr, size)\
-	find_next_one_bit((addr), (size), 0)
+		ext2_find_next_bit(addr, size, offset)
 
 static int read_block_bitmap(struct super_block *sb,
 			     struct udf_bitmap *bitmap, unsigned int block,
@@ -208,7 +161,7 @@
 					((char *)bh->b_data)[(bit + i) >> 3]);
 			} else {
 				if (inode)
-					vfs_dq_free_block(inode, 1);
+					dquot_free_block(inode, 1);
 				udf_add_free_space(sb, sbi->s_partition, 1);
 			}
 		}
@@ -260,11 +213,11 @@
 		while (bit < (sb->s_blocksize << 3) && block_count > 0) {
 			if (!udf_test_bit(bit, bh->b_data))
 				goto out;
-			else if (vfs_dq_prealloc_block(inode, 1))
+			else if (dquot_prealloc_block(inode, 1))
 				goto out;
 			else if (!udf_clear_bit(bit, bh->b_data)) {
 				udf_debug("bit already cleared for block %d\n", bit);
-				vfs_dq_free_block(inode, 1);
+				dquot_free_block(inode, 1);
 				goto out;
 			}
 			block_count--;
@@ -390,10 +343,14 @@
 	/*
 	 * Check quota for allocation of this block.
 	 */
-	if (inode && vfs_dq_alloc_block(inode, 1)) {
-		mutex_unlock(&sbi->s_alloc_mutex);
-		*err = -EDQUOT;
-		return 0;
+	if (inode) {
+		int ret = dquot_alloc_block(inode, 1);
+
+		if (ret) {
+			mutex_unlock(&sbi->s_alloc_mutex);
+			*err = ret;
+			return 0;
+		}
 	}
 
 	newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) -
@@ -449,7 +406,7 @@
 	/* We do this up front - There are some error conditions that
 	   could occure, but.. oh well */
 	if (inode)
-		vfs_dq_free_block(inode, count);
+		dquot_free_block(inode, count);
 	udf_add_free_space(sb, sbi->s_partition, count);
 
 	start = bloc->logicalBlockNum + offset;
@@ -547,7 +504,7 @@
 		}
 
 		if (epos.offset + (2 * adsize) > sb->s_blocksize) {
-			char *sptr, *dptr;
+			unsigned char *sptr, *dptr;
 			int loffset;
 
 			brelse(oepos.bh);
@@ -694,7 +651,7 @@
 		epos.offset -= adsize;
 
 		alloc_count = (elen >> sb->s_blocksize_bits);
-		if (inode && vfs_dq_prealloc_block(inode,
+		if (inode && dquot_prealloc_block(inode,
 			alloc_count > block_count ? block_count : alloc_count))
 			alloc_count = 0;
 		else if (alloc_count > block_count) {
@@ -797,12 +754,13 @@
 	newblock = goal_eloc.logicalBlockNum;
 	goal_eloc.logicalBlockNum++;
 	goal_elen -= sb->s_blocksize;
-
-	if (inode && vfs_dq_alloc_block(inode, 1)) {
-		brelse(goal_epos.bh);
-		mutex_unlock(&sbi->s_alloc_mutex);
-		*err = -EDQUOT;
-		return 0;
+	if (inode) {
+		*err = dquot_alloc_block(inode, 1);
+		if (*err) {
+			brelse(goal_epos.bh);
+			mutex_unlock(&sbi->s_alloc_mutex);
+			return 0;
+		}
 	}
 
 	if (goal_elen)
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index 61d9a76..f0f2a43 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -45,8 +45,8 @@
 	int block, iblock;
 	loff_t nf_pos = (filp->f_pos - 1) << 2;
 	int flen;
-	char *fname = NULL;
-	char *nameptr;
+	unsigned char *fname = NULL;
+	unsigned char *nameptr;
 	uint16_t liu;
 	uint8_t lfi;
 	loff_t size = udf_ext0_offset(dir) + dir->i_size;
diff --git a/fs/udf/file.c b/fs/udf/file.c
index f311d50..1eb0677 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -34,6 +34,7 @@
 #include <linux/errno.h>
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/aio.h>
 
@@ -207,7 +208,7 @@
 	.read			= do_sync_read,
 	.aio_read		= generic_file_aio_read,
 	.ioctl			= udf_ioctl,
-	.open			= generic_file_open,
+	.open			= dquot_file_open,
 	.mmap			= generic_file_mmap,
 	.write			= do_sync_write,
 	.aio_write		= udf_file_aio_write,
@@ -217,6 +218,29 @@
 	.llseek			= generic_file_llseek,
 };
 
+static int udf_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+
+	error = inode_change_ok(inode, iattr);
+	if (error)
+		return error;
+
+	if (iattr->ia_valid & ATTR_SIZE)
+		dquot_initialize(inode);
+
+	if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
+            (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) {
+		error = dquot_transfer(inode, iattr);
+		if (error)
+			return error;
+	}
+
+	return inode_setattr(inode, iattr);
+}
+
 const struct inode_operations udf_file_inode_operations = {
-	.truncate = udf_truncate,
+	.truncate		= udf_truncate,
+	.setattr		= udf_setattr,
 };
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index c10fa39..fb68c9c 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -36,8 +36,8 @@
 	 * Note: we must free any quota before locking the superblock,
 	 * as writing the quota to disk may need the lock as well.
 	 */
-	vfs_dq_free_inode(inode);
-	vfs_dq_drop(inode);
+	dquot_free_inode(inode);
+	dquot_drop(inode);
 
 	clear_inode(inode);
 
@@ -61,7 +61,7 @@
 	struct super_block *sb = dir->i_sb;
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	struct inode *inode;
-	int block;
+	int block, ret;
 	uint32_t start = UDF_I(dir)->i_location.logicalBlockNum;
 	struct udf_inode_info *iinfo;
 	struct udf_inode_info *dinfo = UDF_I(dir);
@@ -153,12 +153,14 @@
 	insert_inode_hash(inode);
 	mark_inode_dirty(inode);
 
-	if (vfs_dq_alloc_inode(inode)) {
-		vfs_dq_drop(inode);
+	dquot_initialize(inode);
+	ret = dquot_alloc_inode(inode);
+	if (ret) {
+		dquot_drop(inode);
 		inode->i_flags |= S_NOQUOTA;
 		inode->i_nlink = 0;
 		iput(inode);
-		*err = -EDQUOT;
+		*err = ret;
 		return NULL;
 	}
 
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index f90231e..bb863fe 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -36,6 +36,7 @@
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
+#include <linux/quotaops.h>
 #include <linux/slab.h>
 #include <linux/crc-itu-t.h>
 
@@ -70,6 +71,9 @@
 
 void udf_delete_inode(struct inode *inode)
 {
+	if (!is_bad_inode(inode))
+		dquot_initialize(inode);
+
 	truncate_inode_pages(&inode->i_data, 0);
 
 	if (is_bad_inode(inode))
@@ -102,12 +106,14 @@
 	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
 	    inode->i_size != iinfo->i_lenExtents) {
 		printk(KERN_WARNING "UDF-fs (%s): Inode %lu (mode %o) has "
-			"inode size %llu different from extent lenght %llu. "
+			"inode size %llu different from extent length %llu. "
 			"Filesystem need not be standards compliant.\n",
 			inode->i_sb->s_id, inode->i_ino, inode->i_mode,
 			(unsigned long long)inode->i_size,
 			(unsigned long long)iinfo->i_lenExtents);
 	}
+
+	dquot_drop(inode);
 	kfree(iinfo->i_ext.i_data);
 	iinfo->i_ext.i_data = NULL;
 }
@@ -1373,12 +1379,12 @@
 	return mode;
 }
 
-int udf_write_inode(struct inode *inode, int sync)
+int udf_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	int ret;
 
 	lock_kernel();
-	ret = udf_update_inode(inode, sync);
+	ret = udf_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
 	unlock_kernel();
 
 	return ret;
@@ -1402,20 +1408,19 @@
 	unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
 	struct udf_inode_info *iinfo = UDF_I(inode);
 
-	bh = udf_tread(inode->i_sb,
-			udf_get_lb_pblock(inode->i_sb,
-					  &iinfo->i_location, 0));
+	bh = udf_tgetblk(inode->i_sb,
+			udf_get_lb_pblock(inode->i_sb, &iinfo->i_location, 0));
 	if (!bh) {
-		udf_debug("bread failure\n");
-		return -EIO;
+		udf_debug("getblk failure\n");
+		return -ENOMEM;
 	}
 
-	memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
-
+	lock_buffer(bh);
+	memset(bh->b_data, 0, inode->i_sb->s_blocksize);
 	fe = (struct fileEntry *)bh->b_data;
 	efe = (struct extendedFileEntry *)bh->b_data;
 
-	if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) {
+	if (iinfo->i_use) {
 		struct unallocSpaceEntry *use =
 			(struct unallocSpaceEntry *)bh->b_data;
 
@@ -1423,20 +1428,18 @@
 		memcpy(bh->b_data + sizeof(struct unallocSpaceEntry),
 		       iinfo->i_ext.i_data, inode->i_sb->s_blocksize -
 					sizeof(struct unallocSpaceEntry));
+		use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE);
+		use->descTag.tagLocation =
+				cpu_to_le32(iinfo->i_location.logicalBlockNum);
 		crclen = sizeof(struct unallocSpaceEntry) +
 				iinfo->i_lenAlloc - sizeof(struct tag);
-		use->descTag.tagLocation = cpu_to_le32(
-						iinfo->i_location.
-							logicalBlockNum);
 		use->descTag.descCRCLength = cpu_to_le16(crclen);
 		use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use +
 							   sizeof(struct tag),
 							   crclen));
 		use->descTag.tagChecksum = udf_tag_checksum(&use->descTag);
 
-		mark_buffer_dirty(bh);
-		brelse(bh);
-		return err;
+		goto out;
 	}
 
 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
@@ -1591,18 +1594,21 @@
 	fe->descTag.tagSerialNum = cpu_to_le16(sbi->s_serial_number);
 	fe->descTag.tagLocation = cpu_to_le32(
 					iinfo->i_location.logicalBlockNum);
-	crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc -
-								sizeof(struct tag);
+	crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - sizeof(struct tag);
 	fe->descTag.descCRCLength = cpu_to_le16(crclen);
 	fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(struct tag),
 						  crclen));
 	fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);
 
+out:
+	set_buffer_uptodate(bh);
+	unlock_buffer(bh);
+
 	/* write the data blocks */
 	mark_buffer_dirty(bh);
 	if (do_sync) {
 		sync_dirty_buffer(bh);
-		if (buffer_req(bh) && !buffer_uptodate(bh)) {
+		if (buffer_write_io_error(bh)) {
 			printk(KERN_WARNING "IO error syncing udf inode "
 				"[%s:%08lx]\n", inode->i_sb->s_id,
 				inode->i_ino);
@@ -1672,7 +1678,7 @@
 		return -1;
 
 	if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) {
-		char *sptr, *dptr;
+		unsigned char *sptr, *dptr;
 		struct buffer_head *nbh;
 		int err, loffset;
 		struct kernel_lb_addr obloc = epos->block;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index cd21150..db423ab 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -34,8 +34,8 @@
 #include <linux/crc-itu-t.h>
 #include <linux/exportfs.h>
 
-static inline int udf_match(int len1, const char *name1, int len2,
-			    const char *name2)
+static inline int udf_match(int len1, const unsigned char *name1, int len2,
+			    const unsigned char *name2)
 {
 	if (len1 != len2)
 		return 0;
@@ -142,15 +142,15 @@
 }
 
 static struct fileIdentDesc *udf_find_entry(struct inode *dir,
-					    struct qstr *child,
+					    const struct qstr *child,
 					    struct udf_fileident_bh *fibh,
 					    struct fileIdentDesc *cfi)
 {
 	struct fileIdentDesc *fi = NULL;
 	loff_t f_pos;
 	int block, flen;
-	char *fname = NULL;
-	char *nameptr;
+	unsigned char *fname = NULL;
+	unsigned char *nameptr;
 	uint8_t lfi;
 	uint16_t liu;
 	loff_t size;
@@ -308,7 +308,7 @@
 {
 	struct super_block *sb = dir->i_sb;
 	struct fileIdentDesc *fi = NULL;
-	char *name = NULL;
+	unsigned char *name = NULL;
 	int namelen;
 	loff_t f_pos;
 	loff_t size = udf_ext0_offset(dir) + dir->i_size;
@@ -563,6 +563,8 @@
 	int err;
 	struct udf_inode_info *iinfo;
 
+	dquot_initialize(dir);
+
 	lock_kernel();
 	inode = udf_new_inode(dir, mode, &err);
 	if (!inode) {
@@ -616,6 +618,8 @@
 	if (!old_valid_dev(rdev))
 		return -EINVAL;
 
+	dquot_initialize(dir);
+
 	lock_kernel();
 	err = -EIO;
 	inode = udf_new_inode(dir, mode, &err);
@@ -662,6 +666,8 @@
 	struct udf_inode_info *dinfo = UDF_I(dir);
 	struct udf_inode_info *iinfo;
 
+	dquot_initialize(dir);
+
 	lock_kernel();
 	err = -EMLINK;
 	if (dir->i_nlink >= (256 << sizeof(dir->i_nlink)) - 1)
@@ -799,6 +805,8 @@
 	struct fileIdentDesc *fi, cfi;
 	struct kernel_lb_addr tloc;
 
+	dquot_initialize(dir);
+
 	retval = -ENOENT;
 	lock_kernel();
 	fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
@@ -845,6 +853,8 @@
 	struct fileIdentDesc cfi;
 	struct kernel_lb_addr tloc;
 
+	dquot_initialize(dir);
+
 	retval = -ENOENT;
 	lock_kernel();
 	fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
@@ -885,20 +895,22 @@
 {
 	struct inode *inode;
 	struct pathComponent *pc;
-	char *compstart;
+	const char *compstart;
 	struct udf_fileident_bh fibh;
 	struct extent_position epos = {};
 	int eoffset, elen = 0;
 	struct fileIdentDesc *fi;
 	struct fileIdentDesc cfi;
-	char *ea;
+	uint8_t *ea;
 	int err;
 	int block;
-	char *name = NULL;
+	unsigned char *name = NULL;
 	int namelen;
 	struct buffer_head *bh;
 	struct udf_inode_info *iinfo;
 
+	dquot_initialize(dir);
+
 	lock_kernel();
 	inode = udf_new_inode(dir, S_IFLNK, &err);
 	if (!inode)
@@ -970,7 +982,7 @@
 
 		pc = (struct pathComponent *)(ea + elen);
 
-		compstart = (char *)symname;
+		compstart = symname;
 
 		do {
 			symname++;
@@ -1069,6 +1081,8 @@
 	int err;
 	struct buffer_head *bh;
 
+	dquot_initialize(dir);
+
 	lock_kernel();
 	if (inode->i_nlink >= (256 << sizeof(inode->i_nlink)) - 1) {
 		unlock_kernel();
@@ -1131,6 +1145,9 @@
 	struct kernel_lb_addr tloc;
 	struct udf_inode_info *old_iinfo = UDF_I(old_inode);
 
+	dquot_initialize(old_dir);
+	dquot_initialize(new_dir);
+
 	lock_kernel();
 	ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
 	if (ofi) {
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index c3265e1..852e918 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -32,12 +32,12 @@
 #include <linux/buffer_head.h>
 #include "udf_i.h"
 
-static void udf_pc_to_char(struct super_block *sb, char *from, int fromlen,
-			   char *to)
+static void udf_pc_to_char(struct super_block *sb, unsigned char *from,
+			   int fromlen, unsigned char *to)
 {
 	struct pathComponent *pc;
 	int elen = 0;
-	char *p = to;
+	unsigned char *p = to;
 
 	while (elen < fromlen) {
 		pc = (struct pathComponent *)(from + elen);
@@ -75,9 +75,9 @@
 {
 	struct inode *inode = page->mapping->host;
 	struct buffer_head *bh = NULL;
-	char *symlink;
+	unsigned char *symlink;
 	int err = -EIO;
-	char *p = kmap(page);
+	unsigned char *p = kmap(page);
 	struct udf_inode_info *iinfo;
 
 	lock_kernel();
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 8d46f42..4223ac8 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -142,7 +142,7 @@
 extern void udf_read_inode(struct inode *);
 extern void udf_delete_inode(struct inode *);
 extern void udf_clear_inode(struct inode *);
-extern int udf_write_inode(struct inode *, int);
+extern int udf_write_inode(struct inode *, struct writeback_control *wbc);
 extern long udf_block_map(struct inode *, sector_t);
 extern int udf_extend_file(struct inode *, struct extent_position *,
 			   struct kernel_long_ad *, sector_t);
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 54c16ec..5cfa4d8 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -85,7 +85,7 @@
 				   "bit already cleared for fragment %u", i);
 	}
 	
-	vfs_dq_free_block(inode, count);
+	dquot_free_block(inode, count);
 
 	
 	fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
@@ -195,7 +195,7 @@
 		ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
 		if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
 			ufs_clusteracct (sb, ucpi, blkno, 1);
-		vfs_dq_free_block(inode, uspi->s_fpb);
+		dquot_free_block(inode, uspi->s_fpb);
 
 		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
 		uspi->cs_total.cs_nbfree++;
@@ -511,6 +511,7 @@
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
 	unsigned cgno, fragno, fragoff, count, fragsize, i;
+	int ret;
 	
 	UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n",
 	     (unsigned long long)fragment, oldcount, newcount);
@@ -556,8 +557,9 @@
 		fs32_add(sb, &ucg->cg_frsum[fragsize - count], 1);
 	for (i = oldcount; i < newcount; i++)
 		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i);
-	if (vfs_dq_alloc_block(inode, count)) {
-		*err = -EDQUOT;
+	ret = dquot_alloc_block(inode, count);
+	if (ret) {
+		*err = ret;
 		return 0;
 	}
 
@@ -596,6 +598,7 @@
 	struct ufs_cylinder_group * ucg;
 	unsigned oldcg, i, j, k, allocsize;
 	u64 result;
+	int ret;
 	
 	UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n",
 	     inode->i_ino, cgno, (unsigned long long)goal, count);
@@ -664,7 +667,7 @@
 		for (i = count; i < uspi->s_fpb; i++)
 			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
 		i = uspi->s_fpb - count;
-		vfs_dq_free_block(inode, i);
+		dquot_free_block(inode, i);
 
 		fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
 		uspi->cs_total.cs_nffree += i;
@@ -676,8 +679,9 @@
 	result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
 	if (result == INVBLOCK)
 		return 0;
-	if (vfs_dq_alloc_block(inode, count)) {
-		*err = -EDQUOT;
+	ret = dquot_alloc_block(inode, count);
+	if (ret) {
+		*err = ret;
 		return 0;
 	}
 	for (i = 0; i < count; i++)
@@ -714,6 +718,7 @@
 	struct ufs_super_block_first * usb1;
 	struct ufs_cylinder_group * ucg;
 	u64 result, blkno;
+	int ret;
 
 	UFSD("ENTER, goal %llu\n", (unsigned long long)goal);
 
@@ -747,8 +752,9 @@
 	ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
 	if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
 		ufs_clusteracct (sb, ucpi, blkno, -1);
-	if (vfs_dq_alloc_block(inode, uspi->s_fpb)) {
-		*err = -EDQUOT;
+	ret = dquot_alloc_block(inode, uspi->s_fpb);
+	if (ret) {
+		*err = ret;
 		return INVBLOCK;
 	}
 
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 22af68f..317a0d4 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -31,7 +31,7 @@
  * len <= UFS_MAXNAMLEN and de != NULL are guaranteed by caller.
  */
 static inline int ufs_match(struct super_block *sb, int len,
-		const char * const name, struct ufs_dir_entry * de)
+		const unsigned char *name, struct ufs_dir_entry *de)
 {
 	if (len != ufs_get_de_namlen(sb, de))
 		return 0;
@@ -70,7 +70,7 @@
 	return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
 }
 
-ino_t ufs_inode_by_name(struct inode *dir, struct qstr *qstr)
+ino_t ufs_inode_by_name(struct inode *dir, const struct qstr *qstr)
 {
 	ino_t res = 0;
 	struct ufs_dir_entry *de;
@@ -249,11 +249,11 @@
  * (as a parameter - res_dir). Page is returned mapped and unlocked.
  * Entry is guaranteed to be valid.
  */
-struct ufs_dir_entry *ufs_find_entry(struct inode *dir, struct qstr *qstr,
+struct ufs_dir_entry *ufs_find_entry(struct inode *dir, const struct qstr *qstr,
 				     struct page **res_page)
 {
 	struct super_block *sb = dir->i_sb;
-	const char *name = qstr->name;
+	const unsigned char *name = qstr->name;
 	int namelen = qstr->len;
 	unsigned reclen = UFS_DIR_REC_LEN(namelen);
 	unsigned long start, n;
@@ -313,7 +313,7 @@
 int ufs_add_link(struct dentry *dentry, struct inode *inode)
 {
 	struct inode *dir = dentry->d_parent->d_inode;
-	const char *name = dentry->d_name.name;
+	const unsigned char *name = dentry->d_name.name;
 	int namelen = dentry->d_name.len;
 	struct super_block *sb = dir->i_sb;
 	unsigned reclen = UFS_DIR_REC_LEN(namelen);
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 73655c6..a8962ce 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -24,6 +24,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 
 #include "ufs_fs.h"
 #include "ufs.h"
@@ -40,7 +41,7 @@
 	.write		= do_sync_write,
 	.aio_write	= generic_file_aio_write,
 	.mmap		= generic_file_mmap,
-	.open           = generic_file_open,
+	.open           = dquot_file_open,
 	.fsync		= simple_fsync,
 	.splice_read	= generic_file_splice_read,
 };
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 3527c00..230ecf6 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -95,8 +95,8 @@
 
 	is_directory = S_ISDIR(inode->i_mode);
 
-	vfs_dq_free_inode(inode);
-	vfs_dq_drop(inode);
+	dquot_free_inode(inode);
+	dquot_drop(inode);
 
 	clear_inode (inode);
 
@@ -355,9 +355,10 @@
 
 	unlock_super (sb);
 
-	if (vfs_dq_alloc_inode(inode)) {
-		vfs_dq_drop(inode);
-		err = -EDQUOT;
+	dquot_initialize(inode);
+	err = dquot_alloc_inode(inode);
+	if (err) {
+		dquot_drop(inode);
 		goto fail_without_unlock;
 	}
 
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 7cf3337..80b68c3 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -36,6 +36,8 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
+#include <linux/writeback.h>
+#include <linux/quotaops.h>
 
 #include "ufs_fs.h"
 #include "ufs.h"
@@ -890,11 +892,11 @@
 	return 0;
 }
 
-int ufs_write_inode (struct inode * inode, int wait)
+int ufs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	int ret;
 	lock_kernel();
-	ret = ufs_update_inode (inode, wait);
+	ret = ufs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
 	unlock_kernel();
 	return ret;
 }
@@ -908,6 +910,9 @@
 {
 	loff_t old_i_size;
 
+	if (!is_bad_inode(inode))
+		dquot_initialize(inode);
+
 	truncate_inode_pages(&inode->i_data, 0);
 	if (is_bad_inode(inode))
 		goto no_delete;
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 4c26d9e..1185562 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -30,6 +30,7 @@
 #include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/smp_lock.h>
+#include <linux/quotaops.h>
 
 #include "ufs_fs.h"
 #include "ufs.h"
@@ -84,6 +85,9 @@
 	int err;
 
 	UFSD("BEGIN\n");
+
+	dquot_initialize(dir);
+
 	inode = ufs_new_inode(dir, mode);
 	err = PTR_ERR(inode);
 
@@ -107,6 +111,9 @@
 
 	if (!old_valid_dev(rdev))
 		return -EINVAL;
+
+	dquot_initialize(dir);
+
 	inode = ufs_new_inode(dir, mode);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
@@ -131,6 +138,8 @@
 	if (l > sb->s_blocksize)
 		goto out_notlocked;
 
+	dquot_initialize(dir);
+
 	lock_kernel();
 	inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
 	err = PTR_ERR(inode);
@@ -176,6 +185,8 @@
 		return -EMLINK;
 	}
 
+	dquot_initialize(dir);
+
 	inode->i_ctime = CURRENT_TIME_SEC;
 	inode_inc_link_count(inode);
 	atomic_inc(&inode->i_count);
@@ -193,6 +204,8 @@
 	if (dir->i_nlink >= UFS_LINK_MAX)
 		goto out;
 
+	dquot_initialize(dir);
+
 	lock_kernel();
 	inode_inc_link_count(dir);
 
@@ -237,6 +250,8 @@
 	struct page *page;
 	int err = -ENOENT;
 
+	dquot_initialize(dir);
+
 	de = ufs_find_entry(dir, &dentry->d_name, &page);
 	if (!de)
 		goto out;
@@ -281,6 +296,9 @@
 	struct ufs_dir_entry *old_de;
 	int err = -ENOENT;
 
+	dquot_initialize(old_dir);
+	dquot_initialize(new_dir);
+
 	old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page);
 	if (!old_de)
 		goto out;
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 143c20b..14743d9 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -1016,6 +1016,9 @@
 		case UFS_FSSTABLE:
 			UFSD("fs is stable\n");
 			break;
+		case UFS_FSLOG:
+			UFSD("fs is logging fs\n");
+			break;
 		case UFS_FSOSF1:
 			UFSD("fs is DEC OSF/1\n");
 			break;
@@ -1432,6 +1435,11 @@
 	kmem_cache_destroy(ufs_inode_cachep);
 }
 
+static void ufs_clear_inode(struct inode *inode)
+{
+	dquot_drop(inode);
+}
+
 #ifdef CONFIG_QUOTA
 static ssize_t ufs_quota_read(struct super_block *, int, char *,size_t, loff_t);
 static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t);
@@ -1442,6 +1450,7 @@
 	.destroy_inode	= ufs_destroy_inode,
 	.write_inode	= ufs_write_inode,
 	.delete_inode	= ufs_delete_inode,
+	.clear_inode	= ufs_clear_inode,
 	.put_super	= ufs_put_super,
 	.write_super	= ufs_write_super,
 	.sync_fs	= ufs_sync_fs,
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index 41dd431..d3b6270 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -44,6 +44,7 @@
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
 #include <linux/sched.h>
+#include <linux/quotaops.h>
 
 #include "ufs_fs.h"
 #include "ufs.h"
@@ -517,9 +518,18 @@
 	if (error)
 		return error;
 
+	if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
+	    (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+		error = dquot_transfer(inode, attr);
+		if (error)
+			return error;
+	}
 	if (ia_valid & ATTR_SIZE &&
 	    attr->ia_size != i_size_read(inode)) {
 		loff_t old_i_size = inode->i_size;
+
+		dquot_initialize(inode);
+
 		error = vmtruncate(inode, attr->ia_size);
 		if (error)
 			return error;
diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h
index 0b4c39b..43f9f5d 100644
--- a/fs/ufs/ufs.h
+++ b/fs/ufs/ufs.h
@@ -86,9 +86,9 @@
 /* dir.c */
 extern const struct inode_operations ufs_dir_inode_operations;
 extern int ufs_add_link (struct dentry *, struct inode *);
-extern ino_t ufs_inode_by_name(struct inode *, struct qstr *);
+extern ino_t ufs_inode_by_name(struct inode *, const struct qstr *);
 extern int ufs_make_empty(struct inode *, struct inode *);
-extern struct ufs_dir_entry *ufs_find_entry(struct inode *, struct qstr *, struct page **);
+extern struct ufs_dir_entry *ufs_find_entry(struct inode *, const struct qstr *, struct page **);
 extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page *);
 extern int ufs_empty_dir (struct inode *);
 extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **);
@@ -106,7 +106,7 @@
 
 /* inode.c */
 extern struct inode *ufs_iget(struct super_block *, unsigned long);
-extern int ufs_write_inode (struct inode *, int);
+extern int ufs_write_inode (struct inode *, struct writeback_control *);
 extern int ufs_sync_inode (struct inode *);
 extern void ufs_delete_inode (struct inode *);
 extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
diff --git a/fs/ufs/ufs_fs.h b/fs/ufs/ufs_fs.h
index 54bde18..6943ec6 100644
--- a/fs/ufs/ufs_fs.h
+++ b/fs/ufs/ufs_fs.h
@@ -138,6 +138,7 @@
 
 #define UFS_USEEFT  ((__u16)65535)
 
+/* fs_clean values */
 #define UFS_FSOK      0x7c269d38
 #define UFS_FSACTIVE  ((__s8)0x00)
 #define UFS_FSCLEAN   ((__s8)0x01)
@@ -145,6 +146,11 @@
 #define UFS_FSOSF1    ((__s8)0x03)	/* is this correct for DEC OSF/1? */
 #define UFS_FSBAD     ((__s8)0xff)
 
+/* Solaris-specific fs_clean values */
+#define UFS_FSSUSPEND ((__s8)0xfe)	/* temporarily suspended */
+#define UFS_FSLOG     ((__s8)0xfd)	/* logging fs */
+#define UFS_FSFIX     ((__s8)0xfc)	/* being repaired while mounted */
+
 /* From here to next blank line, s_flags for ufs_sb_info */
 /* directory entry encoding */
 #define UFS_DE_MASK		0x00000010	/* mask for the following */
@@ -227,11 +233,16 @@
  */
 #define ufs_cbtocylno(bno) \
 	((bno) * uspi->s_nspf / uspi->s_spc)
-#define ufs_cbtorpos(bno) \
+#define ufs_cbtorpos(bno)				      \
+	((UFS_SB(sb)->s_flags & UFS_CG_SUN) ?		      \
+	 (((((bno) * uspi->s_nspf % uspi->s_spc) %	      \
+	    uspi->s_nsect) *				      \
+	   uspi->s_nrpos) / uspi->s_nsect)		      \
+	 :						      \
 	((((bno) * uspi->s_nspf % uspi->s_spc / uspi->s_nsect \
 	* uspi->s_trackskew + (bno) * uspi->s_nspf % uspi->s_spc \
 	% uspi->s_nsect * uspi->s_interleave) % uspi->s_nsect \
-	* uspi->s_nrpos) / uspi->s_npsect)
+	  * uspi->s_nrpos) / uspi->s_npsect))
 
 /*
  * The following macros optimize certain frequently calculated
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 5c5a366..b4769e4 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -105,7 +105,6 @@
 				   xfs_globals.o \
 				   xfs_ioctl.o \
 				   xfs_iops.o \
-				   xfs_lrw.o \
 				   xfs_super.o \
 				   xfs_sync.o \
 				   xfs_xattr.o)
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 66abe36..9083357 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -39,6 +39,7 @@
 #include "xfs_iomap.h"
 #include "xfs_vnodeops.h"
 #include "xfs_trace.h"
+#include "xfs_bmap.h"
 #include <linux/mpage.h>
 #include <linux/pagevec.h>
 #include <linux/writeback.h>
@@ -163,14 +164,17 @@
 }
 
 /*
- * Update on-disk file size now that data has been written to disk.
- * The current in-memory file size is i_size.  If a write is beyond
- * eof i_new_size will be the intended file size until i_size is
- * updated.  If this write does not extend all the way to the valid
- * file size then restrict this update to the end of the write.
+ * Update on-disk file size now that data has been written to disk.  The
+ * current in-memory file size is i_size.  If a write is beyond eof i_new_size
+ * will be the intended file size until i_size is updated.  If this write does
+ * not extend all the way to the valid file size then restrict this update to
+ * the end of the write.
+ *
+ * This function does not block as blocking on the inode lock in IO completion
+ * can lead to IO completion order dependency deadlocks.. If it can't get the
+ * inode ilock it will return EAGAIN. Callers must handle this.
  */
-
-STATIC void
+STATIC int
 xfs_setfilesize(
 	xfs_ioend_t		*ioend)
 {
@@ -181,50 +185,19 @@
 	ASSERT(ioend->io_type != IOMAP_READ);
 
 	if (unlikely(ioend->io_error))
-		return;
+		return 0;
 
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL))
+		return EAGAIN;
+
 	isize = xfs_ioend_new_eof(ioend);
 	if (isize) {
 		ip->i_d.di_size = isize;
-		xfs_mark_inode_dirty_sync(ip);
+		xfs_mark_inode_dirty(ip);
 	}
 
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-}
-
-/*
- * IO write completion.
- */
-STATIC void
-xfs_end_io(
-	struct work_struct	*work)
-{
-	xfs_ioend_t		*ioend =
-		container_of(work, xfs_ioend_t, io_work);
-	struct xfs_inode	*ip = XFS_I(ioend->io_inode);
-
-	/*
-	 * For unwritten extents we need to issue transactions to convert a
-	 * range to normal written extens after the data I/O has finished.
-	 */
-	if (ioend->io_type == IOMAP_UNWRITTEN &&
-	    likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) {
-		int error;
-
-		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
-						 ioend->io_size);
-		if (error)
-			ioend->io_error = error;
-	}
-
-	/*
-	 * We might have to update the on-disk file size after extending
-	 * writes.
-	 */
-	if (ioend->io_type != IOMAP_READ)
-		xfs_setfilesize(ioend);
-	xfs_destroy_ioend(ioend);
+	return 0;
 }
 
 /*
@@ -249,6 +222,53 @@
 }
 
 /*
+ * IO write completion.
+ */
+STATIC void
+xfs_end_io(
+	struct work_struct *work)
+{
+	xfs_ioend_t	*ioend = container_of(work, xfs_ioend_t, io_work);
+	struct xfs_inode *ip = XFS_I(ioend->io_inode);
+	int		error = 0;
+
+	/*
+	 * For unwritten extents we need to issue transactions to convert a
+	 * range to normal written extens after the data I/O has finished.
+	 */
+	if (ioend->io_type == IOMAP_UNWRITTEN &&
+	    likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) {
+
+		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
+						 ioend->io_size);
+		if (error)
+			ioend->io_error = error;
+	}
+
+	/*
+	 * We might have to update the on-disk file size after extending
+	 * writes.
+	 */
+	if (ioend->io_type != IOMAP_READ) {
+		error = xfs_setfilesize(ioend);
+		ASSERT(!error || error == EAGAIN);
+	}
+
+	/*
+	 * If we didn't complete processing of the ioend, requeue it to the
+	 * tail of the workqueue for another attempt later. Otherwise destroy
+	 * it.
+	 */
+	if (error == EAGAIN) {
+		atomic_inc(&ioend->io_remaining);
+		xfs_finish_ioend(ioend, 0);
+		/* ensure we don't spin on blocked ioends */
+		delay(1);
+	} else
+		xfs_destroy_ioend(ioend);
+}
+
+/*
  * Allocate and initialise an IO completion structure.
  * We need to track unwritten extent write completion here initially.
  * We'll need to extend this for updating the ondisk inode size later
@@ -341,7 +361,7 @@
 	 * but don't update the inode size until I/O completion.
 	 */
 	if (xfs_ioend_new_eof(ioend))
-		xfs_mark_inode_dirty_sync(XFS_I(ioend->io_inode));
+		xfs_mark_inode_dirty(XFS_I(ioend->io_inode));
 
 	submit_bio(wbc->sync_mode == WB_SYNC_ALL ?
 		   WRITE_SYNC_PLUG : WRITE, bio);
@@ -874,6 +894,118 @@
 	}
 }
 
+STATIC void
+xfs_vm_invalidatepage(
+	struct page		*page,
+	unsigned long		offset)
+{
+	trace_xfs_invalidatepage(page->mapping->host, page, offset);
+	block_invalidatepage(page, offset);
+}
+
+/*
+ * If the page has delalloc buffers on it, we need to punch them out before we
+ * invalidate the page. If we don't, we leave a stale delalloc mapping on the
+ * inode that can trip a BUG() in xfs_get_blocks() later on if a direct IO read
+ * is done on that same region - the delalloc extent is returned when none is
+ * supposed to be there.
+ *
+ * We prevent this by truncating away the delalloc regions on the page before
+ * invalidating it. Because they are delalloc, we can do this without needing a
+ * transaction. Indeed - if we get ENOSPC errors, we have to be able to do this
+ * truncation without a transaction as there is no space left for block
+ * reservation (typically why we see a ENOSPC in writeback).
+ *
+ * This is not a performance critical path, so for now just do the punching a
+ * buffer head at a time.
+ */
+STATIC void
+xfs_aops_discard_page(
+	struct page		*page)
+{
+	struct inode		*inode = page->mapping->host;
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct buffer_head	*bh, *head;
+	loff_t			offset = page_offset(page);
+	ssize_t			len = 1 << inode->i_blkbits;
+
+	if (!xfs_is_delayed_page(page, IOMAP_DELAY))
+		goto out_invalidate;
+
+	xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+		"page discard on page %p, inode 0x%llx, offset %llu.",
+			page, ip->i_ino, offset);
+
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	bh = head = page_buffers(page);
+	do {
+		int		done;
+		xfs_fileoff_t	offset_fsb;
+		xfs_bmbt_irec_t	imap;
+		int		nimaps = 1;
+		int		error;
+		xfs_fsblock_t	firstblock;
+		xfs_bmap_free_t flist;
+
+		if (!buffer_delay(bh))
+			goto next_buffer;
+
+		offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
+
+		/*
+		 * Map the range first and check that it is a delalloc extent
+		 * before trying to unmap the range. Otherwise we will be
+		 * trying to remove a real extent (which requires a
+		 * transaction) or a hole, which is probably a bad idea...
+		 */
+		error = xfs_bmapi(NULL, ip, offset_fsb, 1,
+				XFS_BMAPI_ENTIRE,  NULL, 0, &imap,
+				&nimaps, NULL, NULL);
+
+		if (error) {
+			/* something screwed, just bail */
+			xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+			"page discard failed delalloc mapping lookup.");
+			break;
+		}
+		if (!nimaps) {
+			/* nothing there */
+			goto next_buffer;
+		}
+		if (imap.br_startblock != DELAYSTARTBLOCK) {
+			/* been converted, ignore */
+			goto next_buffer;
+		}
+		WARN_ON(imap.br_blockcount == 0);
+
+		/*
+		 * Note: while we initialise the firstblock/flist pair, they
+		 * should never be used because blocks should never be
+		 * allocated or freed for a delalloc extent and hence we need
+		 * don't cancel or finish them after the xfs_bunmapi() call.
+		 */
+		xfs_bmap_init(&flist, &firstblock);
+		error = xfs_bunmapi(NULL, ip, offset_fsb, 1, 0, 1, &firstblock,
+					&flist, NULL, &done);
+
+		ASSERT(!flist.xbf_count && !flist.xbf_first);
+		if (error) {
+			/* something screwed, just bail */
+			xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+			"page discard unable to remove delalloc mapping.");
+			break;
+		}
+next_buffer:
+		offset += len;
+
+	} while ((bh = bh->b_this_page) != head);
+
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+out_invalidate:
+	xfs_vm_invalidatepage(page, 0);
+	return;
+}
+
 /*
  * Calling this without startio set means we are being asked to make a dirty
  * page ready for freeing it's buffers.  When called with startio set then
@@ -1125,7 +1257,7 @@
 	 */
 	if (err != -EAGAIN) {
 		if (!unmapped)
-			block_invalidatepage(page, 0);
+			xfs_aops_discard_page(page);
 		ClearPageUptodate(page);
 	}
 	return err;
@@ -1535,15 +1667,6 @@
 	return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks);
 }
 
-STATIC void
-xfs_vm_invalidatepage(
-	struct page		*page,
-	unsigned long		offset)
-{
-	trace_xfs_invalidatepage(page->mapping->host, page, offset);
-	block_invalidatepage(page, offset);
-}
-
 const struct address_space_operations xfs_address_space_operations = {
 	.readpage		= xfs_vm_readpage,
 	.readpages		= xfs_vm_readpages,
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index 87b8cbd..846b75a 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -29,6 +29,7 @@
 #include "xfs_vnodeops.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_inode.h"
+#include "xfs_inode_item.h"
 
 /*
  * Note that we only accept fileids which are long enough rather than allow
@@ -215,9 +216,28 @@
 	return d_obtain_alias(VFS_I(cip));
 }
 
+STATIC int
+xfs_fs_nfs_commit_metadata(
+	struct inode		*inode)
+{
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct xfs_mount	*mp = ip->i_mount;
+	int			error = 0;
+
+	xfs_ilock(ip, XFS_ILOCK_SHARED);
+	if (xfs_ipincount(ip)) {
+		error = _xfs_log_force_lsn(mp, ip->i_itemp->ili_last_lsn,
+				XFS_LOG_SYNC, NULL);
+	}
+	xfs_iunlock(ip, XFS_ILOCK_SHARED);
+
+	return error;
+}
+
 const struct export_operations xfs_export_operations = {
 	.encode_fh		= xfs_fs_encode_fh,
 	.fh_to_dentry		= xfs_fs_fh_to_dentry,
 	.fh_to_parent		= xfs_fs_fh_to_parent,
 	.get_parent		= xfs_fs_get_parent,
+	.commit_metadata	= xfs_fs_nfs_commit_metadata,
 };
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index e4caeb2..42dd3bc 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -16,6 +16,7 @@
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include "xfs.h"
+#include "xfs_fs.h"
 #include "xfs_bit.h"
 #include "xfs_log.h"
 #include "xfs_inum.h"
@@ -34,52 +35,279 @@
 #include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
+#include "xfs_inode_item.h"
+#include "xfs_bmap.h"
 #include "xfs_error.h"
 #include "xfs_rw.h"
 #include "xfs_vnodeops.h"
 #include "xfs_da_btree.h"
 #include "xfs_ioctl.h"
+#include "xfs_trace.h"
 
 #include <linux/dcache.h>
 
 static const struct vm_operations_struct xfs_file_vm_ops;
 
-STATIC ssize_t
-xfs_file_aio_read(
-	struct kiocb		*iocb,
-	const struct iovec	*iov,
-	unsigned long		nr_segs,
-	loff_t			pos)
+/*
+ *	xfs_iozero
+ *
+ *	xfs_iozero clears the specified range of buffer supplied,
+ *	and marks all the affected blocks as valid and modified.  If
+ *	an affected block is not allocated, it will be allocated.  If
+ *	an affected block is not completely overwritten, and is not
+ *	valid before the operation, it will be read from disk before
+ *	being partially zeroed.
+ */
+STATIC int
+xfs_iozero(
+	struct xfs_inode	*ip,	/* inode			*/
+	loff_t			pos,	/* offset in file		*/
+	size_t			count)	/* size of data to zero		*/
 {
-	struct file		*file = iocb->ki_filp;
-	int			ioflags = 0;
+	struct page		*page;
+	struct address_space	*mapping;
+	int			status;
 
-	BUG_ON(iocb->ki_pos != pos);
-	if (unlikely(file->f_flags & O_DIRECT))
-		ioflags |= IO_ISDIRECT;
-	if (file->f_mode & FMODE_NOCMTIME)
-		ioflags |= IO_INVIS;
-	return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov,
-				nr_segs, &iocb->ki_pos, ioflags);
+	mapping = VFS_I(ip)->i_mapping;
+	do {
+		unsigned offset, bytes;
+		void *fsdata;
+
+		offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
+		bytes = PAGE_CACHE_SIZE - offset;
+		if (bytes > count)
+			bytes = count;
+
+		status = pagecache_write_begin(NULL, mapping, pos, bytes,
+					AOP_FLAG_UNINTERRUPTIBLE,
+					&page, &fsdata);
+		if (status)
+			break;
+
+		zero_user(page, offset, bytes);
+
+		status = pagecache_write_end(NULL, mapping, pos, bytes, bytes,
+					page, fsdata);
+		WARN_ON(status <= 0); /* can't return less than zero! */
+		pos += bytes;
+		count -= bytes;
+		status = 0;
+	} while (count);
+
+	return (-status);
+}
+
+STATIC int
+xfs_file_fsync(
+	struct file		*file,
+	struct dentry		*dentry,
+	int			datasync)
+{
+	struct xfs_inode	*ip = XFS_I(dentry->d_inode);
+	struct xfs_trans	*tp;
+	int			error = 0;
+	int			log_flushed = 0;
+
+	xfs_itrace_entry(ip);
+
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return -XFS_ERROR(EIO);
+
+	xfs_iflags_clear(ip, XFS_ITRUNCATED);
+
+	/*
+	 * We always need to make sure that the required inode state is safe on
+	 * disk.  The inode might be clean but we still might need to force the
+	 * log because of committed transactions that haven't hit the disk yet.
+	 * Likewise, there could be unflushed non-transactional changes to the
+	 * inode core that have to go to disk and this requires us to issue
+	 * a synchronous transaction to capture these changes correctly.
+	 *
+	 * This code relies on the assumption that if the i_update_core field
+	 * of the inode is clear and the inode is unpinned then it is clean
+	 * and no action is required.
+	 */
+	xfs_ilock(ip, XFS_ILOCK_SHARED);
+
+	/*
+	 * First check if the VFS inode is marked dirty.  All the dirtying
+	 * of non-transactional updates no goes through mark_inode_dirty*,
+	 * which allows us to distinguish beteeen pure timestamp updates
+	 * and i_size updates which need to be caught for fdatasync.
+	 * After that also theck for the dirty state in the XFS inode, which
+	 * might gets cleared when the inode gets written out via the AIL
+	 * or xfs_iflush_cluster.
+	 */
+	if (((dentry->d_inode->i_state & I_DIRTY_DATASYNC) ||
+	    ((dentry->d_inode->i_state & I_DIRTY_SYNC) && !datasync)) &&
+	    ip->i_update_core) {
+		/*
+		 * Kick off a transaction to log the inode core to get the
+		 * updates.  The sync transaction will also force the log.
+		 */
+		xfs_iunlock(ip, XFS_ILOCK_SHARED);
+		tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS);
+		error = xfs_trans_reserve(tp, 0,
+				XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0);
+		if (error) {
+			xfs_trans_cancel(tp, 0);
+			return -error;
+		}
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+		/*
+		 * Note - it's possible that we might have pushed ourselves out
+		 * of the way during trans_reserve which would flush the inode.
+		 * But there's no guarantee that the inode buffer has actually
+		 * gone out yet (it's delwri).	Plus the buffer could be pinned
+		 * anyway if it's part of an inode in another recent
+		 * transaction.	 So we play it safe and fire off the
+		 * transaction anyway.
+		 */
+		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+		xfs_trans_ihold(tp, ip);
+		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+		xfs_trans_set_sync(tp);
+		error = _xfs_trans_commit(tp, 0, &log_flushed);
+
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	} else {
+		/*
+		 * Timestamps/size haven't changed since last inode flush or
+		 * inode transaction commit.  That means either nothing got
+		 * written or a transaction committed which caught the updates.
+		 * If the latter happened and the transaction hasn't hit the
+		 * disk yet, the inode will be still be pinned.  If it is,
+		 * force the log.
+		 */
+		if (xfs_ipincount(ip)) {
+			error = _xfs_log_force_lsn(ip->i_mount,
+					ip->i_itemp->ili_last_lsn,
+					XFS_LOG_SYNC, &log_flushed);
+		}
+		xfs_iunlock(ip, XFS_ILOCK_SHARED);
+	}
+
+	if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) {
+		/*
+		 * If the log write didn't issue an ordered tag we need
+		 * to flush the disk cache for the data device now.
+		 */
+		if (!log_flushed)
+			xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp);
+
+		/*
+		 * If this inode is on the RT dev we need to flush that
+		 * cache as well.
+		 */
+		if (XFS_IS_REALTIME_INODE(ip))
+			xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp);
+	}
+
+	return -error;
 }
 
 STATIC ssize_t
-xfs_file_aio_write(
+xfs_file_aio_read(
 	struct kiocb		*iocb,
-	const struct iovec	*iov,
+	const struct iovec	*iovp,
 	unsigned long		nr_segs,
 	loff_t			pos)
 {
 	struct file		*file = iocb->ki_filp;
+	struct inode		*inode = file->f_mapping->host;
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct xfs_mount	*mp = ip->i_mount;
+	size_t			size = 0;
+	ssize_t			ret = 0;
 	int			ioflags = 0;
+	xfs_fsize_t		n;
+	unsigned long		seg;
+
+	XFS_STATS_INC(xs_read_calls);
 
 	BUG_ON(iocb->ki_pos != pos);
+
 	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
 	if (file->f_mode & FMODE_NOCMTIME)
 		ioflags |= IO_INVIS;
-	return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs,
-				&iocb->ki_pos, ioflags);
+
+	/* START copy & waste from filemap.c */
+	for (seg = 0; seg < nr_segs; seg++) {
+		const struct iovec *iv = &iovp[seg];
+
+		/*
+		 * If any segment has a negative length, or the cumulative
+		 * length ever wraps negative then return -EINVAL.
+		 */
+		size += iv->iov_len;
+		if (unlikely((ssize_t)(size|iv->iov_len) < 0))
+			return XFS_ERROR(-EINVAL);
+	}
+	/* END copy & waste from filemap.c */
+
+	if (unlikely(ioflags & IO_ISDIRECT)) {
+		xfs_buftarg_t	*target =
+			XFS_IS_REALTIME_INODE(ip) ?
+				mp->m_rtdev_targp : mp->m_ddev_targp;
+		if ((iocb->ki_pos & target->bt_smask) ||
+		    (size & target->bt_smask)) {
+			if (iocb->ki_pos == ip->i_size)
+				return 0;
+			return -XFS_ERROR(EINVAL);
+		}
+	}
+
+	n = XFS_MAXIOFFSET(mp) - iocb->ki_pos;
+	if (n <= 0 || size == 0)
+		return 0;
+
+	if (n < size)
+		size = n;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return -EIO;
+
+	if (unlikely(ioflags & IO_ISDIRECT))
+		mutex_lock(&inode->i_mutex);
+	xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+	if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
+		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
+		int iolock = XFS_IOLOCK_SHARED;
+
+		ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, ip, iocb->ki_pos, size,
+					dmflags, &iolock);
+		if (ret) {
+			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+			if (unlikely(ioflags & IO_ISDIRECT))
+				mutex_unlock(&inode->i_mutex);
+			return ret;
+		}
+	}
+
+	if (unlikely(ioflags & IO_ISDIRECT)) {
+		if (inode->i_mapping->nrpages) {
+			ret = -xfs_flushinval_pages(ip,
+					(iocb->ki_pos & PAGE_CACHE_MASK),
+					-1, FI_REMAPF_LOCKED);
+		}
+		mutex_unlock(&inode->i_mutex);
+		if (ret) {
+			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+			return ret;
+		}
+	}
+
+	trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags);
+
+	ret = generic_file_aio_read(iocb, iovp, nr_segs, iocb->ki_pos);
+	if (ret > 0)
+		XFS_STATS_ADD(xs_read_bytes, ret);
+
+	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+	return ret;
 }
 
 STATIC ssize_t
@@ -87,16 +315,44 @@
 	struct file		*infilp,
 	loff_t			*ppos,
 	struct pipe_inode_info	*pipe,
-	size_t			len,
+	size_t			count,
 	unsigned int		flags)
 {
+	struct xfs_inode	*ip = XFS_I(infilp->f_mapping->host);
+	struct xfs_mount	*mp = ip->i_mount;
 	int			ioflags = 0;
+	ssize_t			ret;
+
+	XFS_STATS_INC(xs_read_calls);
 
 	if (infilp->f_mode & FMODE_NOCMTIME)
 		ioflags |= IO_INVIS;
 
-	return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
-				   infilp, ppos, pipe, len, flags, ioflags);
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return -EIO;
+
+	xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+	if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
+		int iolock = XFS_IOLOCK_SHARED;
+		int error;
+
+		error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *ppos, count,
+					FILP_DELAY_FLAG(infilp), &iolock);
+		if (error) {
+			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+			return -error;
+		}
+	}
+
+	trace_xfs_file_splice_read(ip, count, *ppos, ioflags);
+
+	ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
+	if (ret > 0)
+		XFS_STATS_ADD(xs_read_bytes, ret);
+
+	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+	return ret;
 }
 
 STATIC ssize_t
@@ -104,16 +360,538 @@
 	struct pipe_inode_info	*pipe,
 	struct file		*outfilp,
 	loff_t			*ppos,
-	size_t			len,
+	size_t			count,
 	unsigned int		flags)
 {
+	struct inode		*inode = outfilp->f_mapping->host;
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct xfs_mount	*mp = ip->i_mount;
+	xfs_fsize_t		isize, new_size;
 	int			ioflags = 0;
+	ssize_t			ret;
+
+	XFS_STATS_INC(xs_write_calls);
 
 	if (outfilp->f_mode & FMODE_NOCMTIME)
 		ioflags |= IO_INVIS;
 
-	return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
-				    pipe, outfilp, ppos, len, flags, ioflags);
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return -EIO;
+
+	xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
+	if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
+		int iolock = XFS_IOLOCK_EXCL;
+		int error;
+
+		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, *ppos, count,
+					FILP_DELAY_FLAG(outfilp), &iolock);
+		if (error) {
+			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+			return -error;
+		}
+	}
+
+	new_size = *ppos + count;
+
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	if (new_size > ip->i_size)
+		ip->i_new_size = new_size;
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+	trace_xfs_file_splice_write(ip, count, *ppos, ioflags);
+
+	ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
+	if (ret > 0)
+		XFS_STATS_ADD(xs_write_bytes, ret);
+
+	isize = i_size_read(inode);
+	if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize))
+		*ppos = isize;
+
+	if (*ppos > ip->i_size) {
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+		if (*ppos > ip->i_size)
+			ip->i_size = *ppos;
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	}
+
+	if (ip->i_new_size) {
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+		ip->i_new_size = 0;
+		if (ip->i_d.di_size > ip->i_size)
+			ip->i_d.di_size = ip->i_size;
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	}
+	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+	return ret;
+}
+
+/*
+ * This routine is called to handle zeroing any space in the last
+ * block of the file that is beyond the EOF.  We do this since the
+ * size is being increased without writing anything to that block
+ * and we don't want anyone to read the garbage on the disk.
+ */
+STATIC int				/* error (positive) */
+xfs_zero_last_block(
+	xfs_inode_t	*ip,
+	xfs_fsize_t	offset,
+	xfs_fsize_t	isize)
+{
+	xfs_fileoff_t	last_fsb;
+	xfs_mount_t	*mp = ip->i_mount;
+	int		nimaps;
+	int		zero_offset;
+	int		zero_len;
+	int		error = 0;
+	xfs_bmbt_irec_t	imap;
+
+	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+	zero_offset = XFS_B_FSB_OFFSET(mp, isize);
+	if (zero_offset == 0) {
+		/*
+		 * There are no extra bytes in the last block on disk to
+		 * zero, so return.
+		 */
+		return 0;
+	}
+
+	last_fsb = XFS_B_TO_FSBT(mp, isize);
+	nimaps = 1;
+	error = xfs_bmapi(NULL, ip, last_fsb, 1, 0, NULL, 0, &imap,
+			  &nimaps, NULL, NULL);
+	if (error) {
+		return error;
+	}
+	ASSERT(nimaps > 0);
+	/*
+	 * If the block underlying isize is just a hole, then there
+	 * is nothing to zero.
+	 */
+	if (imap.br_startblock == HOLESTARTBLOCK) {
+		return 0;
+	}
+	/*
+	 * Zero the part of the last block beyond the EOF, and write it
+	 * out sync.  We need to drop the ilock while we do this so we
+	 * don't deadlock when the buffer cache calls back to us.
+	 */
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+	zero_len = mp->m_sb.sb_blocksize - zero_offset;
+	if (isize + zero_len > offset)
+		zero_len = offset - isize;
+	error = xfs_iozero(ip, isize, zero_len);
+
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	ASSERT(error >= 0);
+	return error;
+}
+
+/*
+ * Zero any on disk space between the current EOF and the new,
+ * larger EOF.  This handles the normal case of zeroing the remainder
+ * of the last block in the file and the unusual case of zeroing blocks
+ * out beyond the size of the file.  This second case only happens
+ * with fixed size extents and when the system crashes before the inode
+ * size was updated but after blocks were allocated.  If fill is set,
+ * then any holes in the range are filled and zeroed.  If not, the holes
+ * are left alone as holes.
+ */
+
+int					/* error (positive) */
+xfs_zero_eof(
+	xfs_inode_t	*ip,
+	xfs_off_t	offset,		/* starting I/O offset */
+	xfs_fsize_t	isize)		/* current inode size */
+{
+	xfs_mount_t	*mp = ip->i_mount;
+	xfs_fileoff_t	start_zero_fsb;
+	xfs_fileoff_t	end_zero_fsb;
+	xfs_fileoff_t	zero_count_fsb;
+	xfs_fileoff_t	last_fsb;
+	xfs_fileoff_t	zero_off;
+	xfs_fsize_t	zero_len;
+	int		nimaps;
+	int		error = 0;
+	xfs_bmbt_irec_t	imap;
+
+	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+	ASSERT(offset > isize);
+
+	/*
+	 * First handle zeroing the block on which isize resides.
+	 * We only zero a part of that block so it is handled specially.
+	 */
+	error = xfs_zero_last_block(ip, offset, isize);
+	if (error) {
+		ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+		return error;
+	}
+
+	/*
+	 * Calculate the range between the new size and the old
+	 * where blocks needing to be zeroed may exist.  To get the
+	 * block where the last byte in the file currently resides,
+	 * we need to subtract one from the size and truncate back
+	 * to a block boundary.  We subtract 1 in case the size is
+	 * exactly on a block boundary.
+	 */
+	last_fsb = isize ? XFS_B_TO_FSBT(mp, isize - 1) : (xfs_fileoff_t)-1;
+	start_zero_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)isize);
+	end_zero_fsb = XFS_B_TO_FSBT(mp, offset - 1);
+	ASSERT((xfs_sfiloff_t)last_fsb < (xfs_sfiloff_t)start_zero_fsb);
+	if (last_fsb == end_zero_fsb) {
+		/*
+		 * The size was only incremented on its last block.
+		 * We took care of that above, so just return.
+		 */
+		return 0;
+	}
+
+	ASSERT(start_zero_fsb <= end_zero_fsb);
+	while (start_zero_fsb <= end_zero_fsb) {
+		nimaps = 1;
+		zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
+		error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb,
+				  0, NULL, 0, &imap, &nimaps, NULL, NULL);
+		if (error) {
+			ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+			return error;
+		}
+		ASSERT(nimaps > 0);
+
+		if (imap.br_state == XFS_EXT_UNWRITTEN ||
+		    imap.br_startblock == HOLESTARTBLOCK) {
+			/*
+			 * This loop handles initializing pages that were
+			 * partially initialized by the code below this
+			 * loop. It basically zeroes the part of the page
+			 * that sits on a hole and sets the page as P_HOLE
+			 * and calls remapf if it is a mapped file.
+			 */
+			start_zero_fsb = imap.br_startoff + imap.br_blockcount;
+			ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
+			continue;
+		}
+
+		/*
+		 * There are blocks we need to zero.
+		 * Drop the inode lock while we're doing the I/O.
+		 * We'll still have the iolock to protect us.
+		 */
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+		zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
+		zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
+
+		if ((zero_off + zero_len) > offset)
+			zero_len = offset - zero_off;
+
+		error = xfs_iozero(ip, zero_off, zero_len);
+		if (error) {
+			goto out_lock;
+		}
+
+		start_zero_fsb = imap.br_startoff + imap.br_blockcount;
+		ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
+
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+	}
+
+	return 0;
+
+out_lock:
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	ASSERT(error >= 0);
+	return error;
+}
+
+STATIC ssize_t
+xfs_file_aio_write(
+	struct kiocb		*iocb,
+	const struct iovec	*iovp,
+	unsigned long		nr_segs,
+	loff_t			pos)
+{
+	struct file		*file = iocb->ki_filp;
+	struct address_space	*mapping = file->f_mapping;
+	struct inode		*inode = mapping->host;
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct xfs_mount	*mp = ip->i_mount;
+	ssize_t			ret = 0, error = 0;
+	int			ioflags = 0;
+	xfs_fsize_t		isize, new_size;
+	int			iolock;
+	int			eventsent = 0;
+	size_t			ocount = 0, count;
+	int			need_i_mutex;
+
+	XFS_STATS_INC(xs_write_calls);
+
+	BUG_ON(iocb->ki_pos != pos);
+
+	if (unlikely(file->f_flags & O_DIRECT))
+		ioflags |= IO_ISDIRECT;
+	if (file->f_mode & FMODE_NOCMTIME)
+		ioflags |= IO_INVIS;
+
+	error = generic_segment_checks(iovp, &nr_segs, &ocount, VERIFY_READ);
+	if (error)
+		return error;
+
+	count = ocount;
+	if (count == 0)
+		return 0;
+
+	xfs_wait_for_freeze(mp, SB_FREEZE_WRITE);
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return -EIO;
+
+relock:
+	if (ioflags & IO_ISDIRECT) {
+		iolock = XFS_IOLOCK_SHARED;
+		need_i_mutex = 0;
+	} else {
+		iolock = XFS_IOLOCK_EXCL;
+		need_i_mutex = 1;
+		mutex_lock(&inode->i_mutex);
+	}
+
+	xfs_ilock(ip, XFS_ILOCK_EXCL|iolock);
+
+start:
+	error = -generic_write_checks(file, &pos, &count,
+					S_ISBLK(inode->i_mode));
+	if (error) {
+		xfs_iunlock(ip, XFS_ILOCK_EXCL|iolock);
+		goto out_unlock_mutex;
+	}
+
+	if ((DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) &&
+	    !(ioflags & IO_INVIS) && !eventsent)) {
+		int		dmflags = FILP_DELAY_FLAG(file);
+
+		if (need_i_mutex)
+			dmflags |= DM_FLAGS_IMUX;
+
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+		error = XFS_SEND_DATA(ip->i_mount, DM_EVENT_WRITE, ip,
+				      pos, count, dmflags, &iolock);
+		if (error) {
+			goto out_unlock_internal;
+		}
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+		eventsent = 1;
+
+		/*
+		 * The iolock was dropped and reacquired in XFS_SEND_DATA
+		 * so we have to recheck the size when appending.
+		 * We will only "goto start;" once, since having sent the
+		 * event prevents another call to XFS_SEND_DATA, which is
+		 * what allows the size to change in the first place.
+		 */
+		if ((file->f_flags & O_APPEND) && pos != ip->i_size)
+			goto start;
+	}
+
+	if (ioflags & IO_ISDIRECT) {
+		xfs_buftarg_t	*target =
+			XFS_IS_REALTIME_INODE(ip) ?
+				mp->m_rtdev_targp : mp->m_ddev_targp;
+
+		if ((pos & target->bt_smask) || (count & target->bt_smask)) {
+			xfs_iunlock(ip, XFS_ILOCK_EXCL|iolock);
+			return XFS_ERROR(-EINVAL);
+		}
+
+		if (!need_i_mutex && (mapping->nrpages || pos > ip->i_size)) {
+			xfs_iunlock(ip, XFS_ILOCK_EXCL|iolock);
+			iolock = XFS_IOLOCK_EXCL;
+			need_i_mutex = 1;
+			mutex_lock(&inode->i_mutex);
+			xfs_ilock(ip, XFS_ILOCK_EXCL|iolock);
+			goto start;
+		}
+	}
+
+	new_size = pos + count;
+	if (new_size > ip->i_size)
+		ip->i_new_size = new_size;
+
+	if (likely(!(ioflags & IO_INVIS)))
+		file_update_time(file);
+
+	/*
+	 * If the offset is beyond the size of the file, we have a couple
+	 * of things to do. First, if there is already space allocated
+	 * we need to either create holes or zero the disk or ...
+	 *
+	 * If there is a page where the previous size lands, we need
+	 * to zero it out up to the new size.
+	 */
+
+	if (pos > ip->i_size) {
+		error = xfs_zero_eof(ip, pos, ip->i_size);
+		if (error) {
+			xfs_iunlock(ip, XFS_ILOCK_EXCL);
+			goto out_unlock_internal;
+		}
+	}
+	xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+	/*
+	 * If we're writing the file then make sure to clear the
+	 * setuid and setgid bits if the process is not being run
+	 * by root.  This keeps people from modifying setuid and
+	 * setgid binaries.
+	 */
+	error = -file_remove_suid(file);
+	if (unlikely(error))
+		goto out_unlock_internal;
+
+	/* We can write back this queue in page reclaim */
+	current->backing_dev_info = mapping->backing_dev_info;
+
+	if ((ioflags & IO_ISDIRECT)) {
+		if (mapping->nrpages) {
+			WARN_ON(need_i_mutex == 0);
+			error = xfs_flushinval_pages(ip,
+					(pos & PAGE_CACHE_MASK),
+					-1, FI_REMAPF_LOCKED);
+			if (error)
+				goto out_unlock_internal;
+		}
+
+		if (need_i_mutex) {
+			/* demote the lock now the cached pages are gone */
+			xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
+			mutex_unlock(&inode->i_mutex);
+
+			iolock = XFS_IOLOCK_SHARED;
+			need_i_mutex = 0;
+		}
+
+		trace_xfs_file_direct_write(ip, count, iocb->ki_pos, ioflags);
+		ret = generic_file_direct_write(iocb, iovp,
+				&nr_segs, pos, &iocb->ki_pos, count, ocount);
+
+		/*
+		 * direct-io write to a hole: fall through to buffered I/O
+		 * for completing the rest of the request.
+		 */
+		if (ret >= 0 && ret != count) {
+			XFS_STATS_ADD(xs_write_bytes, ret);
+
+			pos += ret;
+			count -= ret;
+
+			ioflags &= ~IO_ISDIRECT;
+			xfs_iunlock(ip, iolock);
+			goto relock;
+		}
+	} else {
+		int enospc = 0;
+		ssize_t ret2 = 0;
+
+write_retry:
+		trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, ioflags);
+		ret2 = generic_file_buffered_write(iocb, iovp, nr_segs,
+				pos, &iocb->ki_pos, count, ret);
+		/*
+		 * if we just got an ENOSPC, flush the inode now we
+		 * aren't holding any page locks and retry *once*
+		 */
+		if (ret2 == -ENOSPC && !enospc) {
+			error = xfs_flush_pages(ip, 0, -1, 0, FI_NONE);
+			if (error)
+				goto out_unlock_internal;
+			enospc = 1;
+			goto write_retry;
+		}
+		ret = ret2;
+	}
+
+	current->backing_dev_info = NULL;
+
+	isize = i_size_read(inode);
+	if (unlikely(ret < 0 && ret != -EFAULT && iocb->ki_pos > isize))
+		iocb->ki_pos = isize;
+
+	if (iocb->ki_pos > ip->i_size) {
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+		if (iocb->ki_pos > ip->i_size)
+			ip->i_size = iocb->ki_pos;
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	}
+
+	if (ret == -ENOSPC &&
+	    DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
+		xfs_iunlock(ip, iolock);
+		if (need_i_mutex)
+			mutex_unlock(&inode->i_mutex);
+		error = XFS_SEND_NAMESP(ip->i_mount, DM_EVENT_NOSPACE, ip,
+				DM_RIGHT_NULL, ip, DM_RIGHT_NULL, NULL, NULL,
+				0, 0, 0); /* Delay flag intentionally  unused */
+		if (need_i_mutex)
+			mutex_lock(&inode->i_mutex);
+		xfs_ilock(ip, iolock);
+		if (error)
+			goto out_unlock_internal;
+		goto start;
+	}
+
+	error = -ret;
+	if (ret <= 0)
+		goto out_unlock_internal;
+
+	XFS_STATS_ADD(xs_write_bytes, ret);
+
+	/* Handle various SYNC-type writes */
+	if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
+		loff_t end = pos + ret - 1;
+		int error2;
+
+		xfs_iunlock(ip, iolock);
+		if (need_i_mutex)
+			mutex_unlock(&inode->i_mutex);
+
+		error2 = filemap_write_and_wait_range(mapping, pos, end);
+		if (!error)
+			error = error2;
+		if (need_i_mutex)
+			mutex_lock(&inode->i_mutex);
+		xfs_ilock(ip, iolock);
+
+		error2 = -xfs_file_fsync(file, file->f_path.dentry,
+					 (file->f_flags & __O_SYNC) ? 0 : 1);
+		if (!error)
+			error = error2;
+	}
+
+ out_unlock_internal:
+	if (ip->i_new_size) {
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+		ip->i_new_size = 0;
+		/*
+		 * If this was a direct or synchronous I/O that failed (such
+		 * as ENOSPC) then part of the I/O may have been written to
+		 * disk before the error occured.  In this case the on-disk
+		 * file size may have been adjusted beyond the in-memory file
+		 * size and now needs to be truncated back.
+		 */
+		if (ip->i_d.di_size > ip->i_size)
+			ip->i_d.di_size = ip->i_size;
+		xfs_iunlock(ip, XFS_ILOCK_EXCL);
+	}
+	xfs_iunlock(ip, iolock);
+ out_unlock_mutex:
+	if (need_i_mutex)
+		mutex_unlock(&inode->i_mutex);
+	return -error;
 }
 
 STATIC int
@@ -160,28 +938,6 @@
 	return -xfs_release(XFS_I(inode));
 }
 
-/*
- * We ignore the datasync flag here because a datasync is effectively
- * identical to an fsync. That is, datasync implies that we need to write
- * only the metadata needed to be able to access the data that is written
- * if we crash after the call completes. Hence if we are writing beyond
- * EOF we have to log the inode size change as well, which makes it a
- * full fsync. If we don't write beyond EOF, the inode core will be
- * clean in memory and so we don't need to log the inode, just like
- * fsync.
- */
-STATIC int
-xfs_file_fsync(
-	struct file		*file,
-	struct dentry		*dentry,
-	int			datasync)
-{
-	struct xfs_inode	*ip = XFS_I(dentry->d_inode);
-
-	xfs_iflags_clear(ip, XFS_ITRUNCATED);
-	return -xfs_fsync(ip);
-}
-
 STATIC int
 xfs_file_readdir(
 	struct file	*filp,
@@ -203,9 +959,9 @@
 	 *
 	 * Try to give it an estimate that's good enough, maybe at some
 	 * point we can change the ->readdir prototype to include the
-	 * buffer size.
+	 * buffer size.  For now we use the current glibc buffer size.
 	 */
-	bufsize = (size_t)min_t(loff_t, PAGE_SIZE, ip->i_d.di_size);
+	bufsize = (size_t)min_t(loff_t, 32768, ip->i_d.di_size);
 
 	error = xfs_readdir(ip, dirent, bufsize,
 				(xfs_off_t *)&filp->f_pos, filldir);
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index e8566bb..61a9960 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -91,6 +91,16 @@
 		mark_inode_dirty_sync(inode);
 }
 
+void
+xfs_mark_inode_dirty(
+	xfs_inode_t	*ip)
+{
+	struct inode	*inode = VFS_I(ip);
+
+	if (!(inode->i_state & (I_WILL_FREE|I_FREEING|I_CLEAR)))
+		mark_inode_dirty(inode);
+}
+
 /*
  * Change the requested timestamp in the given inode.
  * We don't lock across timestamp updates, and we don't log them but
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 5af0c81c..facfb32 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -88,7 +88,6 @@
 #include <xfs_super.h>
 #include <xfs_globals.h>
 #include <xfs_fs_subr.h>
-#include <xfs_lrw.h>
 #include <xfs_buf.h>
 
 /*
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
deleted file mode 100644
index eac6f80..0000000
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ /dev/null
@@ -1,796 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, 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.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_bit.h"
-#include "xfs_log.h"
-#include "xfs_inum.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir2.h"
-#include "xfs_alloc.h"
-#include "xfs_dmapi.h"
-#include "xfs_quota.h"
-#include "xfs_mount.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dinode.h"
-#include "xfs_inode.h"
-#include "xfs_bmap.h"
-#include "xfs_btree.h"
-#include "xfs_ialloc.h"
-#include "xfs_rtalloc.h"
-#include "xfs_error.h"
-#include "xfs_itable.h"
-#include "xfs_rw.h"
-#include "xfs_attr.h"
-#include "xfs_inode_item.h"
-#include "xfs_buf_item.h"
-#include "xfs_utils.h"
-#include "xfs_iomap.h"
-#include "xfs_vnodeops.h"
-#include "xfs_trace.h"
-
-#include <linux/capability.h>
-#include <linux/writeback.h>
-
-
-/*
- *	xfs_iozero
- *
- *	xfs_iozero clears the specified range of buffer supplied,
- *	and marks all the affected blocks as valid and modified.  If
- *	an affected block is not allocated, it will be allocated.  If
- *	an affected block is not completely overwritten, and is not
- *	valid before the operation, it will be read from disk before
- *	being partially zeroed.
- */
-STATIC int
-xfs_iozero(
-	struct xfs_inode	*ip,	/* inode			*/
-	loff_t			pos,	/* offset in file		*/
-	size_t			count)	/* size of data to zero		*/
-{
-	struct page		*page;
-	struct address_space	*mapping;
-	int			status;
-
-	mapping = VFS_I(ip)->i_mapping;
-	do {
-		unsigned offset, bytes;
-		void *fsdata;
-
-		offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
-		bytes = PAGE_CACHE_SIZE - offset;
-		if (bytes > count)
-			bytes = count;
-
-		status = pagecache_write_begin(NULL, mapping, pos, bytes,
-					AOP_FLAG_UNINTERRUPTIBLE,
-					&page, &fsdata);
-		if (status)
-			break;
-
-		zero_user(page, offset, bytes);
-
-		status = pagecache_write_end(NULL, mapping, pos, bytes, bytes,
-					page, fsdata);
-		WARN_ON(status <= 0); /* can't return less than zero! */
-		pos += bytes;
-		count -= bytes;
-		status = 0;
-	} while (count);
-
-	return (-status);
-}
-
-ssize_t			/* bytes read, or (-)  error */
-xfs_read(
-	xfs_inode_t		*ip,
-	struct kiocb		*iocb,
-	const struct iovec	*iovp,
-	unsigned int		segs,
-	loff_t			*offset,
-	int			ioflags)
-{
-	struct file		*file = iocb->ki_filp;
-	struct inode		*inode = file->f_mapping->host;
-	xfs_mount_t		*mp = ip->i_mount;
-	size_t			size = 0;
-	ssize_t			ret = 0;
-	xfs_fsize_t		n;
-	unsigned long		seg;
-
-
-	XFS_STATS_INC(xs_read_calls);
-
-	/* START copy & waste from filemap.c */
-	for (seg = 0; seg < segs; seg++) {
-		const struct iovec *iv = &iovp[seg];
-
-		/*
-		 * If any segment has a negative length, or the cumulative
-		 * length ever wraps negative then return -EINVAL.
-		 */
-		size += iv->iov_len;
-		if (unlikely((ssize_t)(size|iv->iov_len) < 0))
-			return XFS_ERROR(-EINVAL);
-	}
-	/* END copy & waste from filemap.c */
-
-	if (unlikely(ioflags & IO_ISDIRECT)) {
-		xfs_buftarg_t	*target =
-			XFS_IS_REALTIME_INODE(ip) ?
-				mp->m_rtdev_targp : mp->m_ddev_targp;
-		if ((*offset & target->bt_smask) ||
-		    (size & target->bt_smask)) {
-			if (*offset == ip->i_size) {
-				return (0);
-			}
-			return -XFS_ERROR(EINVAL);
-		}
-	}
-
-	n = XFS_MAXIOFFSET(mp) - *offset;
-	if ((n <= 0) || (size == 0))
-		return 0;
-
-	if (n < size)
-		size = n;
-
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return -EIO;
-
-	if (unlikely(ioflags & IO_ISDIRECT))
-		mutex_lock(&inode->i_mutex);
-	xfs_ilock(ip, XFS_IOLOCK_SHARED);
-
-	if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
-		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
-		int iolock = XFS_IOLOCK_SHARED;
-
-		ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *offset, size,
-					dmflags, &iolock);
-		if (ret) {
-			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-			if (unlikely(ioflags & IO_ISDIRECT))
-				mutex_unlock(&inode->i_mutex);
-			return ret;
-		}
-	}
-
-	if (unlikely(ioflags & IO_ISDIRECT)) {
-		if (inode->i_mapping->nrpages)
-			ret = -xfs_flushinval_pages(ip, (*offset & PAGE_CACHE_MASK),
-						    -1, FI_REMAPF_LOCKED);
-		mutex_unlock(&inode->i_mutex);
-		if (ret) {
-			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-			return ret;
-		}
-	}
-
-	trace_xfs_file_read(ip, size, *offset, ioflags);
-
-	iocb->ki_pos = *offset;
-	ret = generic_file_aio_read(iocb, iovp, segs, *offset);
-	if (ret > 0)
-		XFS_STATS_ADD(xs_read_bytes, ret);
-
-	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-	return ret;
-}
-
-ssize_t
-xfs_splice_read(
-	xfs_inode_t		*ip,
-	struct file		*infilp,
-	loff_t			*ppos,
-	struct pipe_inode_info	*pipe,
-	size_t			count,
-	int			flags,
-	int			ioflags)
-{
-	xfs_mount_t		*mp = ip->i_mount;
-	ssize_t			ret;
-
-	XFS_STATS_INC(xs_read_calls);
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-		return -EIO;
-
-	xfs_ilock(ip, XFS_IOLOCK_SHARED);
-
-	if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
-		int iolock = XFS_IOLOCK_SHARED;
-		int error;
-
-		error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *ppos, count,
-					FILP_DELAY_FLAG(infilp), &iolock);
-		if (error) {
-			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-			return -error;
-		}
-	}
-
-	trace_xfs_file_splice_read(ip, count, *ppos, ioflags);
-
-	ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
-	if (ret > 0)
-		XFS_STATS_ADD(xs_read_bytes, ret);
-
-	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
-	return ret;
-}
-
-ssize_t
-xfs_splice_write(
-	xfs_inode_t		*ip,
-	struct pipe_inode_info	*pipe,
-	struct file		*outfilp,
-	loff_t			*ppos,
-	size_t			count,
-	int			flags,
-	int			ioflags)
-{
-	xfs_mount_t		*mp = ip->i_mount;
-	ssize_t			ret;
-	struct inode		*inode = outfilp->f_mapping->host;
-	xfs_fsize_t		isize, new_size;
-
-	XFS_STATS_INC(xs_write_calls);
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-		return -EIO;
-
-	xfs_ilock(ip, XFS_IOLOCK_EXCL);
-
-	if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
-		int iolock = XFS_IOLOCK_EXCL;
-		int error;
-
-		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, *ppos, count,
-					FILP_DELAY_FLAG(outfilp), &iolock);
-		if (error) {
-			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
-			return -error;
-		}
-	}
-
-	new_size = *ppos + count;
-
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	if (new_size > ip->i_size)
-		ip->i_new_size = new_size;
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
-	trace_xfs_file_splice_write(ip, count, *ppos, ioflags);
-
-	ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
-	if (ret > 0)
-		XFS_STATS_ADD(xs_write_bytes, ret);
-
-	isize = i_size_read(inode);
-	if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize))
-		*ppos = isize;
-
-	if (*ppos > ip->i_size) {
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		if (*ppos > ip->i_size)
-			ip->i_size = *ppos;
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-	}
-
-	if (ip->i_new_size) {
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		ip->i_new_size = 0;
-		if (ip->i_d.di_size > ip->i_size)
-			ip->i_d.di_size = ip->i_size;
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-	}
-	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
-	return ret;
-}
-
-/*
- * This routine is called to handle zeroing any space in the last
- * block of the file that is beyond the EOF.  We do this since the
- * size is being increased without writing anything to that block
- * and we don't want anyone to read the garbage on the disk.
- */
-STATIC int				/* error (positive) */
-xfs_zero_last_block(
-	xfs_inode_t	*ip,
-	xfs_fsize_t	offset,
-	xfs_fsize_t	isize)
-{
-	xfs_fileoff_t	last_fsb;
-	xfs_mount_t	*mp = ip->i_mount;
-	int		nimaps;
-	int		zero_offset;
-	int		zero_len;
-	int		error = 0;
-	xfs_bmbt_irec_t	imap;
-
-	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-
-	zero_offset = XFS_B_FSB_OFFSET(mp, isize);
-	if (zero_offset == 0) {
-		/*
-		 * There are no extra bytes in the last block on disk to
-		 * zero, so return.
-		 */
-		return 0;
-	}
-
-	last_fsb = XFS_B_TO_FSBT(mp, isize);
-	nimaps = 1;
-	error = xfs_bmapi(NULL, ip, last_fsb, 1, 0, NULL, 0, &imap,
-			  &nimaps, NULL, NULL);
-	if (error) {
-		return error;
-	}
-	ASSERT(nimaps > 0);
-	/*
-	 * If the block underlying isize is just a hole, then there
-	 * is nothing to zero.
-	 */
-	if (imap.br_startblock == HOLESTARTBLOCK) {
-		return 0;
-	}
-	/*
-	 * Zero the part of the last block beyond the EOF, and write it
-	 * out sync.  We need to drop the ilock while we do this so we
-	 * don't deadlock when the buffer cache calls back to us.
-	 */
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
-	zero_len = mp->m_sb.sb_blocksize - zero_offset;
-	if (isize + zero_len > offset)
-		zero_len = offset - isize;
-	error = xfs_iozero(ip, isize, zero_len);
-
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	ASSERT(error >= 0);
-	return error;
-}
-
-/*
- * Zero any on disk space between the current EOF and the new,
- * larger EOF.  This handles the normal case of zeroing the remainder
- * of the last block in the file and the unusual case of zeroing blocks
- * out beyond the size of the file.  This second case only happens
- * with fixed size extents and when the system crashes before the inode
- * size was updated but after blocks were allocated.  If fill is set,
- * then any holes in the range are filled and zeroed.  If not, the holes
- * are left alone as holes.
- */
-
-int					/* error (positive) */
-xfs_zero_eof(
-	xfs_inode_t	*ip,
-	xfs_off_t	offset,		/* starting I/O offset */
-	xfs_fsize_t	isize)		/* current inode size */
-{
-	xfs_mount_t	*mp = ip->i_mount;
-	xfs_fileoff_t	start_zero_fsb;
-	xfs_fileoff_t	end_zero_fsb;
-	xfs_fileoff_t	zero_count_fsb;
-	xfs_fileoff_t	last_fsb;
-	xfs_fileoff_t	zero_off;
-	xfs_fsize_t	zero_len;
-	int		nimaps;
-	int		error = 0;
-	xfs_bmbt_irec_t	imap;
-
-	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
-	ASSERT(offset > isize);
-
-	/*
-	 * First handle zeroing the block on which isize resides.
-	 * We only zero a part of that block so it is handled specially.
-	 */
-	error = xfs_zero_last_block(ip, offset, isize);
-	if (error) {
-		ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
-		return error;
-	}
-
-	/*
-	 * Calculate the range between the new size and the old
-	 * where blocks needing to be zeroed may exist.  To get the
-	 * block where the last byte in the file currently resides,
-	 * we need to subtract one from the size and truncate back
-	 * to a block boundary.  We subtract 1 in case the size is
-	 * exactly on a block boundary.
-	 */
-	last_fsb = isize ? XFS_B_TO_FSBT(mp, isize - 1) : (xfs_fileoff_t)-1;
-	start_zero_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)isize);
-	end_zero_fsb = XFS_B_TO_FSBT(mp, offset - 1);
-	ASSERT((xfs_sfiloff_t)last_fsb < (xfs_sfiloff_t)start_zero_fsb);
-	if (last_fsb == end_zero_fsb) {
-		/*
-		 * The size was only incremented on its last block.
-		 * We took care of that above, so just return.
-		 */
-		return 0;
-	}
-
-	ASSERT(start_zero_fsb <= end_zero_fsb);
-	while (start_zero_fsb <= end_zero_fsb) {
-		nimaps = 1;
-		zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
-		error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb,
-				  0, NULL, 0, &imap, &nimaps, NULL, NULL);
-		if (error) {
-			ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
-			return error;
-		}
-		ASSERT(nimaps > 0);
-
-		if (imap.br_state == XFS_EXT_UNWRITTEN ||
-		    imap.br_startblock == HOLESTARTBLOCK) {
-			/*
-			 * This loop handles initializing pages that were
-			 * partially initialized by the code below this
-			 * loop. It basically zeroes the part of the page
-			 * that sits on a hole and sets the page as P_HOLE
-			 * and calls remapf if it is a mapped file.
-			 */
-			start_zero_fsb = imap.br_startoff + imap.br_blockcount;
-			ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
-			continue;
-		}
-
-		/*
-		 * There are blocks we need to zero.
-		 * Drop the inode lock while we're doing the I/O.
-		 * We'll still have the iolock to protect us.
-		 */
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
-		zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
-		zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
-
-		if ((zero_off + zero_len) > offset)
-			zero_len = offset - zero_off;
-
-		error = xfs_iozero(ip, zero_off, zero_len);
-		if (error) {
-			goto out_lock;
-		}
-
-		start_zero_fsb = imap.br_startoff + imap.br_blockcount;
-		ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
-
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-	}
-
-	return 0;
-
-out_lock:
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	ASSERT(error >= 0);
-	return error;
-}
-
-ssize_t				/* bytes written, or (-) error */
-xfs_write(
-	struct xfs_inode	*xip,
-	struct kiocb		*iocb,
-	const struct iovec	*iovp,
-	unsigned int		nsegs,
-	loff_t			*offset,
-	int			ioflags)
-{
-	struct file		*file = iocb->ki_filp;
-	struct address_space	*mapping = file->f_mapping;
-	struct inode		*inode = mapping->host;
-	unsigned long		segs = nsegs;
-	xfs_mount_t		*mp;
-	ssize_t			ret = 0, error = 0;
-	xfs_fsize_t		isize, new_size;
-	int			iolock;
-	int			eventsent = 0;
-	size_t			ocount = 0, count;
-	loff_t			pos;
-	int			need_i_mutex;
-
-	XFS_STATS_INC(xs_write_calls);
-
-	error = generic_segment_checks(iovp, &segs, &ocount, VERIFY_READ);
-	if (error)
-		return error;
-
-	count = ocount;
-	pos = *offset;
-
-	if (count == 0)
-		return 0;
-
-	mp = xip->i_mount;
-
-	xfs_wait_for_freeze(mp, SB_FREEZE_WRITE);
-
-	if (XFS_FORCED_SHUTDOWN(mp))
-		return -EIO;
-
-relock:
-	if (ioflags & IO_ISDIRECT) {
-		iolock = XFS_IOLOCK_SHARED;
-		need_i_mutex = 0;
-	} else {
-		iolock = XFS_IOLOCK_EXCL;
-		need_i_mutex = 1;
-		mutex_lock(&inode->i_mutex);
-	}
-
-	xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
-
-start:
-	error = -generic_write_checks(file, &pos, &count,
-					S_ISBLK(inode->i_mode));
-	if (error) {
-		xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-		goto out_unlock_mutex;
-	}
-
-	if ((DM_EVENT_ENABLED(xip, DM_EVENT_WRITE) &&
-	    !(ioflags & IO_INVIS) && !eventsent)) {
-		int		dmflags = FILP_DELAY_FLAG(file);
-
-		if (need_i_mutex)
-			dmflags |= DM_FLAGS_IMUX;
-
-		xfs_iunlock(xip, XFS_ILOCK_EXCL);
-		error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, xip,
-				      pos, count, dmflags, &iolock);
-		if (error) {
-			goto out_unlock_internal;
-		}
-		xfs_ilock(xip, XFS_ILOCK_EXCL);
-		eventsent = 1;
-
-		/*
-		 * The iolock was dropped and reacquired in XFS_SEND_DATA
-		 * so we have to recheck the size when appending.
-		 * We will only "goto start;" once, since having sent the
-		 * event prevents another call to XFS_SEND_DATA, which is
-		 * what allows the size to change in the first place.
-		 */
-		if ((file->f_flags & O_APPEND) && pos != xip->i_size)
-			goto start;
-	}
-
-	if (ioflags & IO_ISDIRECT) {
-		xfs_buftarg_t	*target =
-			XFS_IS_REALTIME_INODE(xip) ?
-				mp->m_rtdev_targp : mp->m_ddev_targp;
-
-		if ((pos & target->bt_smask) || (count & target->bt_smask)) {
-			xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-			return XFS_ERROR(-EINVAL);
-		}
-
-		if (!need_i_mutex && (mapping->nrpages || pos > xip->i_size)) {
-			xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-			iolock = XFS_IOLOCK_EXCL;
-			need_i_mutex = 1;
-			mutex_lock(&inode->i_mutex);
-			xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
-			goto start;
-		}
-	}
-
-	new_size = pos + count;
-	if (new_size > xip->i_size)
-		xip->i_new_size = new_size;
-
-	if (likely(!(ioflags & IO_INVIS)))
-		file_update_time(file);
-
-	/*
-	 * If the offset is beyond the size of the file, we have a couple
-	 * of things to do. First, if there is already space allocated
-	 * we need to either create holes or zero the disk or ...
-	 *
-	 * If there is a page where the previous size lands, we need
-	 * to zero it out up to the new size.
-	 */
-
-	if (pos > xip->i_size) {
-		error = xfs_zero_eof(xip, pos, xip->i_size);
-		if (error) {
-			xfs_iunlock(xip, XFS_ILOCK_EXCL);
-			goto out_unlock_internal;
-		}
-	}
-	xfs_iunlock(xip, XFS_ILOCK_EXCL);
-
-	/*
-	 * If we're writing the file then make sure to clear the
-	 * setuid and setgid bits if the process is not being run
-	 * by root.  This keeps people from modifying setuid and
-	 * setgid binaries.
-	 */
-	error = -file_remove_suid(file);
-	if (unlikely(error))
-		goto out_unlock_internal;
-
-	/* We can write back this queue in page reclaim */
-	current->backing_dev_info = mapping->backing_dev_info;
-
-	if ((ioflags & IO_ISDIRECT)) {
-		if (mapping->nrpages) {
-			WARN_ON(need_i_mutex == 0);
-			error = xfs_flushinval_pages(xip,
-					(pos & PAGE_CACHE_MASK),
-					-1, FI_REMAPF_LOCKED);
-			if (error)
-				goto out_unlock_internal;
-		}
-
-		if (need_i_mutex) {
-			/* demote the lock now the cached pages are gone */
-			xfs_ilock_demote(xip, XFS_IOLOCK_EXCL);
-			mutex_unlock(&inode->i_mutex);
-
-			iolock = XFS_IOLOCK_SHARED;
-			need_i_mutex = 0;
-		}
-
-		trace_xfs_file_direct_write(xip, count, *offset, ioflags);
-		ret = generic_file_direct_write(iocb, iovp,
-				&segs, pos, offset, count, ocount);
-
-		/*
-		 * direct-io write to a hole: fall through to buffered I/O
-		 * for completing the rest of the request.
-		 */
-		if (ret >= 0 && ret != count) {
-			XFS_STATS_ADD(xs_write_bytes, ret);
-
-			pos += ret;
-			count -= ret;
-
-			ioflags &= ~IO_ISDIRECT;
-			xfs_iunlock(xip, iolock);
-			goto relock;
-		}
-	} else {
-		int enospc = 0;
-		ssize_t ret2 = 0;
-
-write_retry:
-		trace_xfs_file_buffered_write(xip, count, *offset, ioflags);
-		ret2 = generic_file_buffered_write(iocb, iovp, segs,
-				pos, offset, count, ret);
-		/*
-		 * if we just got an ENOSPC, flush the inode now we
-		 * aren't holding any page locks and retry *once*
-		 */
-		if (ret2 == -ENOSPC && !enospc) {
-			error = xfs_flush_pages(xip, 0, -1, 0, FI_NONE);
-			if (error)
-				goto out_unlock_internal;
-			enospc = 1;
-			goto write_retry;
-		}
-		ret = ret2;
-	}
-
-	current->backing_dev_info = NULL;
-
-	isize = i_size_read(inode);
-	if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize))
-		*offset = isize;
-
-	if (*offset > xip->i_size) {
-		xfs_ilock(xip, XFS_ILOCK_EXCL);
-		if (*offset > xip->i_size)
-			xip->i_size = *offset;
-		xfs_iunlock(xip, XFS_ILOCK_EXCL);
-	}
-
-	if (ret == -ENOSPC &&
-	    DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
-		xfs_iunlock(xip, iolock);
-		if (need_i_mutex)
-			mutex_unlock(&inode->i_mutex);
-		error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, xip,
-				DM_RIGHT_NULL, xip, DM_RIGHT_NULL, NULL, NULL,
-				0, 0, 0); /* Delay flag intentionally  unused */
-		if (need_i_mutex)
-			mutex_lock(&inode->i_mutex);
-		xfs_ilock(xip, iolock);
-		if (error)
-			goto out_unlock_internal;
-		goto start;
-	}
-
-	error = -ret;
-	if (ret <= 0)
-		goto out_unlock_internal;
-
-	XFS_STATS_ADD(xs_write_bytes, ret);
-
-	/* Handle various SYNC-type writes */
-	if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
-		loff_t end = pos + ret - 1;
-		int error2;
-
-		xfs_iunlock(xip, iolock);
-		if (need_i_mutex)
-			mutex_unlock(&inode->i_mutex);
-
-		error2 = filemap_write_and_wait_range(mapping, pos, end);
-		if (!error)
-			error = error2;
-		if (need_i_mutex)
-			mutex_lock(&inode->i_mutex);
-		xfs_ilock(xip, iolock);
-
-		error2 = xfs_fsync(xip);
-		if (!error)
-			error = error2;
-	}
-
- out_unlock_internal:
-	if (xip->i_new_size) {
-		xfs_ilock(xip, XFS_ILOCK_EXCL);
-		xip->i_new_size = 0;
-		/*
-		 * If this was a direct or synchronous I/O that failed (such
-		 * as ENOSPC) then part of the I/O may have been written to
-		 * disk before the error occured.  In this case the on-disk
-		 * file size may have been adjusted beyond the in-memory file
-		 * size and now needs to be truncated back.
-		 */
-		if (xip->i_d.di_size > xip->i_size)
-			xip->i_d.di_size = xip->i_size;
-		xfs_iunlock(xip, XFS_ILOCK_EXCL);
-	}
-	xfs_iunlock(xip, iolock);
- out_unlock_mutex:
-	if (need_i_mutex)
-		mutex_unlock(&inode->i_mutex);
-	return -error;
-}
-
-/*
- * If the underlying (data/log/rt) device is readonly, there are some
- * operations that cannot proceed.
- */
-int
-xfs_dev_is_read_only(
-	xfs_mount_t		*mp,
-	char			*message)
-{
-	if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
-	    xfs_readonly_buftarg(mp->m_logdev_targp) ||
-	    (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
-		cmn_err(CE_NOTE,
-			"XFS: %s required on read-only device.", message);
-		cmn_err(CE_NOTE,
-			"XFS: write access unavailable, cannot proceed.");
-		return EROFS;
-	}
-	return 0;
-}
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
deleted file mode 100644
index 342ae8c..0000000
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, 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.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_LRW_H__
-#define __XFS_LRW_H__
-
-struct xfs_mount;
-struct xfs_inode;
-struct xfs_buf;
-
-extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
-
-extern int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
-
-#endif	/* __XFS_LRW_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_quotaops.c b/fs/xfs/linux-2.6/xfs_quotaops.c
index 3d4a0c8..1947514 100644
--- a/fs/xfs/linux-2.6/xfs_quotaops.c
+++ b/fs/xfs/linux-2.6/xfs_quotaops.c
@@ -44,20 +44,6 @@
 }
 
 STATIC int
-xfs_fs_quota_sync(
-	struct super_block	*sb,
-	int			type)
-{
-	struct xfs_mount	*mp = XFS_M(sb);
-
-	if (sb->s_flags & MS_RDONLY)
-		return -EROFS;
-	if (!XFS_IS_QUOTA_RUNNING(mp))
-		return -ENOSYS;
-	return -xfs_sync_data(mp, 0);
-}
-
-STATIC int
 xfs_fs_get_xstate(
 	struct super_block	*sb,
 	struct fs_quota_stat	*fqs)
@@ -82,8 +68,6 @@
 		return -EROFS;
 	if (op != Q_XQUOTARM && !XFS_IS_QUOTA_RUNNING(mp))
 		return -ENOSYS;
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
 
 	if (uflags & XFS_QUOTA_UDQ_ACCT)
 		flags |= XFS_UQUOTA_ACCT;
@@ -144,14 +128,11 @@
 		return -ENOSYS;
 	if (!XFS_IS_QUOTA_ON(mp))
 		return -ESRCH;
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
 
 	return -xfs_qm_scall_setqlim(mp, id, xfs_quota_type(type), fdq);
 }
 
 const struct quotactl_ops xfs_quotactl_operations = {
-	.quota_sync		= xfs_fs_quota_sync,
 	.get_xstate		= xfs_fs_get_xstate,
 	.set_xstate		= xfs_fs_set_xstate,
 	.get_xquota		= xfs_fs_get_xquota,
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 25ea240..71345a3 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1063,7 +1063,7 @@
 STATIC int
 xfs_fs_write_inode(
 	struct inode		*inode,
-	int			sync)
+	struct writeback_control *wbc)
 {
 	struct xfs_inode	*ip = XFS_I(inode);
 	struct xfs_mount	*mp = ip->i_mount;
@@ -1074,11 +1074,7 @@
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
 
-	if (sync) {
-		error = xfs_wait_on_pages(ip, 0, -1);
-		if (error)
-			goto out;
-
+	if (wbc->sync_mode == WB_SYNC_ALL) {
 		/*
 		 * Make sure the inode has hit stable storage.  By using the
 		 * log and the fsync transactions we reduce the IOs we have
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index a9f6d20..05cd853 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -607,7 +607,8 @@
 	set_freezable();
 	timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
 	for (;;) {
-		timeleft = schedule_timeout_interruptible(timeleft);
+		if (list_empty(&mp->m_sync_list))
+			timeleft = schedule_timeout_interruptible(timeleft);
 		/* swsusp */
 		try_to_freeze();
 		if (kthread_should_stop() && list_empty(&mp->m_sync_list))
@@ -627,8 +628,7 @@
 			list_add_tail(&mp->m_sync_work.w_list,
 					&mp->m_sync_list);
 		}
-		list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list)
-			list_move(&work->w_list, &tmp);
+		list_splice_init(&mp->m_sync_list, &tmp);
 		spin_unlock(&mp->m_sync_lock);
 
 		list_for_each_entry_safe(work, n, &tmp, w_list) {
@@ -688,12 +688,12 @@
 	struct xfs_perag *pag;
 
 	pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
-	read_lock(&pag->pag_ici_lock);
+	write_lock(&pag->pag_ici_lock);
 	spin_lock(&ip->i_flags_lock);
 	__xfs_inode_set_reclaim_tag(pag, ip);
 	__xfs_iflags_set(ip, XFS_IRECLAIMABLE);
 	spin_unlock(&ip->i_flags_lock);
-	read_unlock(&pag->pag_ici_lock);
+	write_unlock(&pag->pag_ici_lock);
 	xfs_perag_put(pag);
 }
 
diff --git a/fs/xfs/linux-2.6/xfs_trace.c b/fs/xfs/linux-2.6/xfs_trace.c
index 856eb3c..5a10760 100644
--- a/fs/xfs/linux-2.6/xfs_trace.c
+++ b/fs/xfs/linux-2.6/xfs_trace.c
@@ -52,22 +52,6 @@
 #include "quota/xfs_dquot.h"
 
 /*
- * Format fsblock number into a static buffer & return it.
- */
-STATIC char *xfs_fmtfsblock(xfs_fsblock_t bno)
-{
-	static char rval[50];
-
-	if (bno == NULLFSBLOCK)
-		sprintf(rval, "NULLFSBLOCK");
-	else if (isnullstartblock(bno))
-		sprintf(rval, "NULLSTARTBLOCK(%lld)", startblockval(bno));
-	else
-		sprintf(rval, "%lld", (xfs_dfsbno_t)bno);
-	return rval;
-}
-
-/*
  * We include this last to have the helpers above available for the trace
  * event implementations.
  */
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h
index a4574dc..fcaa62f 100644
--- a/fs/xfs/linux-2.6/xfs_trace.h
+++ b/fs/xfs/linux-2.6/xfs_trace.h
@@ -197,13 +197,13 @@
 		__entry->caller_ip = caller_ip;
 	),
 	TP_printk("dev %d:%d ino 0x%llx state %s idx %ld "
-		  "offset %lld block %s count %lld flag %d caller %pf",
+		  "offset %lld block %lld count %lld flag %d caller %pf",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
 		  __entry->ino,
 		  __print_flags(__entry->bmap_state, "|", XFS_BMAP_EXT_FLAGS),
 		  (long)__entry->idx,
 		  __entry->startoff,
-		  xfs_fmtfsblock(__entry->startblock),
+		  (__int64_t)__entry->startblock,
 		  __entry->blockcount,
 		  __entry->state,
 		  (char *)__entry->caller_ip)
@@ -241,13 +241,13 @@
 		__entry->caller_ip = caller_ip;
 	),
 	TP_printk("dev %d:%d ino 0x%llx state %s idx %ld "
-		  "offset %lld block %s count %lld flag %d caller %pf",
+		  "offset %lld block %lld count %lld flag %d caller %pf",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
 		  __entry->ino,
 		  __print_flags(__entry->bmap_state, "|", XFS_BMAP_EXT_FLAGS),
 		  (long)__entry->idx,
 		  __entry->startoff,
-		  xfs_fmtfsblock(__entry->startblock),
+		  (__int64_t)__entry->startblock,
 		  __entry->blockcount,
 		  __entry->state,
 		  (char *)__entry->caller_ip)
@@ -593,7 +593,7 @@
 	TP_ARGS(dqp),
 	TP_STRUCT__entry(
 		__field(dev_t, dev)
-		__field(__be32, id)
+		__field(u32, id)
 		__field(unsigned, flags)
 		__field(unsigned, nrefs)
 		__field(unsigned long long, res_bcount)
@@ -606,7 +606,7 @@
 	), \
 	TP_fast_assign(
 		__entry->dev = dqp->q_mount->m_super->s_dev;
-		__entry->id = dqp->q_core.d_id;
+		__entry->id = be32_to_cpu(dqp->q_core.d_id);
 		__entry->flags = dqp->dq_flags;
 		__entry->nrefs = dqp->q_nrefs;
 		__entry->res_bcount = dqp->q_res_bcount;
@@ -622,10 +622,10 @@
 			be64_to_cpu(dqp->q_core.d_ino_softlimit);
 	),
 	TP_printk("dev %d:%d id 0x%x flags %s nrefs %u res_bc 0x%llx "
-		  "bcnt 0x%llx [hard 0x%llx | soft 0x%llx] "
-		  "icnt 0x%llx [hard 0x%llx | soft 0x%llx]",
+		  "bcnt 0x%llx bhardlimit 0x%llx bsoftlimit 0x%llx "
+		  "icnt 0x%llx ihardlimit 0x%llx isoftlimit 0x%llx]",
 		  MAJOR(__entry->dev), MINOR(__entry->dev),
-		  be32_to_cpu(__entry->id),
+		  __entry->id,
 		  __print_flags(__entry->flags, "|", XFS_DQ_FLAGS),
 		  __entry->nrefs,
 		  __entry->res_bcount,
@@ -881,7 +881,7 @@
 	), \
 	TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
 		  "offset 0x%llx count %zd flags %s " \
-		  "startoff 0x%llx startblock %s blockcount 0x%llx", \
+		  "startoff 0x%llx startblock %lld blockcount 0x%llx", \
 		  MAJOR(__entry->dev), MINOR(__entry->dev), \
 		  __entry->ino, \
 		  __entry->size, \
@@ -890,7 +890,7 @@
 		  __entry->count, \
 		  __print_flags(__entry->flags, "|", BMAPI_FLAGS), \
 		  __entry->startoff, \
-		  xfs_fmtfsblock(__entry->startblock), \
+		  (__int64_t)__entry->startblock, \
 		  __entry->blockcount) \
 )
 DEFINE_IOMAP_EVENT(xfs_iomap_enter);
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 1869fb9..5c11e4d 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -2550,22 +2550,134 @@
 }
 
 STATIC int
+xfs_bmap_btalloc_nullfb(
+	struct xfs_bmalloca	*ap,
+	struct xfs_alloc_arg	*args,
+	xfs_extlen_t		*blen)
+{
+	struct xfs_mount	*mp = ap->ip->i_mount;
+	struct xfs_perag	*pag;
+	xfs_agnumber_t		ag, startag;
+	int			notinit = 0;
+	int			error;
+
+	if (ap->userdata && xfs_inode_is_filestream(ap->ip))
+		args->type = XFS_ALLOCTYPE_NEAR_BNO;
+	else
+		args->type = XFS_ALLOCTYPE_START_BNO;
+	args->total = ap->total;
+
+	/*
+	 * Search for an allocation group with a single extent large enough
+	 * for the request.  If one isn't found, then adjust the minimum
+	 * allocation size to the largest space found.
+	 */
+	startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
+	if (startag == NULLAGNUMBER)
+		startag = ag = 0;
+
+	pag = xfs_perag_get(mp, ag);
+	while (*blen < ap->alen) {
+		if (!pag->pagf_init) {
+			error = xfs_alloc_pagf_init(mp, args->tp, ag,
+						    XFS_ALLOC_FLAG_TRYLOCK);
+			if (error) {
+				xfs_perag_put(pag);
+				return error;
+			}
+		}
+
+		/*
+		 * See xfs_alloc_fix_freelist...
+		 */
+		if (pag->pagf_init) {
+			xfs_extlen_t	longest;
+			longest = xfs_alloc_longest_free_extent(mp, pag);
+			if (*blen < longest)
+				*blen = longest;
+		} else
+			notinit = 1;
+
+		if (xfs_inode_is_filestream(ap->ip)) {
+			if (*blen >= ap->alen)
+				break;
+
+			if (ap->userdata) {
+				/*
+				 * If startag is an invalid AG, we've
+				 * come here once before and
+				 * xfs_filestream_new_ag picked the
+				 * best currently available.
+				 *
+				 * Don't continue looping, since we
+				 * could loop forever.
+				 */
+				if (startag == NULLAGNUMBER)
+					break;
+
+				error = xfs_filestream_new_ag(ap, &ag);
+				xfs_perag_put(pag);
+				if (error)
+					return error;
+
+				/* loop again to set 'blen'*/
+				startag = NULLAGNUMBER;
+				pag = xfs_perag_get(mp, ag);
+				continue;
+			}
+		}
+		if (++ag == mp->m_sb.sb_agcount)
+			ag = 0;
+		if (ag == startag)
+			break;
+		xfs_perag_put(pag);
+		pag = xfs_perag_get(mp, ag);
+	}
+	xfs_perag_put(pag);
+
+	/*
+	 * Since the above loop did a BUF_TRYLOCK, it is
+	 * possible that there is space for this request.
+	 */
+	if (notinit || *blen < ap->minlen)
+		args->minlen = ap->minlen;
+	/*
+	 * If the best seen length is less than the request
+	 * length, use the best as the minimum.
+	 */
+	else if (*blen < ap->alen)
+		args->minlen = *blen;
+	/*
+	 * Otherwise we've seen an extent as big as alen,
+	 * use that as the minimum.
+	 */
+	else
+		args->minlen = ap->alen;
+
+	/*
+	 * set the failure fallback case to look in the selected
+	 * AG as the stream may have moved.
+	 */
+	if (xfs_inode_is_filestream(ap->ip))
+		ap->rval = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
+
+	return 0;
+}
+
+STATIC int
 xfs_bmap_btalloc(
 	xfs_bmalloca_t	*ap)		/* bmap alloc argument struct */
 {
 	xfs_mount_t	*mp;		/* mount point structure */
 	xfs_alloctype_t	atype = 0;	/* type for allocation routines */
 	xfs_extlen_t	align;		/* minimum allocation alignment */
-	xfs_agnumber_t	ag;
 	xfs_agnumber_t	fb_agno;	/* ag number of ap->firstblock */
-	xfs_agnumber_t	startag;
+	xfs_agnumber_t	ag;
 	xfs_alloc_arg_t	args;
 	xfs_extlen_t	blen;
 	xfs_extlen_t	nextminlen = 0;
-	xfs_perag_t	*pag;
 	int		nullfb;		/* true if ap->firstblock isn't set */
 	int		isaligned;
-	int		notinit;
 	int		tryagain;
 	int		error;
 
@@ -2612,103 +2724,9 @@
 	args.firstblock = ap->firstblock;
 	blen = 0;
 	if (nullfb) {
-		if (ap->userdata && xfs_inode_is_filestream(ap->ip))
-			args.type = XFS_ALLOCTYPE_NEAR_BNO;
-		else
-			args.type = XFS_ALLOCTYPE_START_BNO;
-		args.total = ap->total;
-
-		/*
-		 * Search for an allocation group with a single extent
-		 * large enough for the request.
-		 *
-		 * If one isn't found, then adjust the minimum allocation
-		 * size to the largest space found.
-		 */
-		startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
-		if (startag == NULLAGNUMBER)
-			startag = ag = 0;
-		notinit = 0;
-		pag = xfs_perag_get(mp, ag);
-		while (blen < ap->alen) {
-			if (!pag->pagf_init &&
-			    (error = xfs_alloc_pagf_init(mp, args.tp,
-				    ag, XFS_ALLOC_FLAG_TRYLOCK))) {
-				xfs_perag_put(pag);
-				return error;
-			}
-			/*
-			 * See xfs_alloc_fix_freelist...
-			 */
-			if (pag->pagf_init) {
-				xfs_extlen_t	longest;
-				longest = xfs_alloc_longest_free_extent(mp, pag);
-				if (blen < longest)
-					blen = longest;
-			} else
-				notinit = 1;
-
-			if (xfs_inode_is_filestream(ap->ip)) {
-				if (blen >= ap->alen)
-					break;
-
-				if (ap->userdata) {
-					/*
-					 * If startag is an invalid AG, we've
-					 * come here once before and
-					 * xfs_filestream_new_ag picked the
-					 * best currently available.
-					 *
-					 * Don't continue looping, since we
-					 * could loop forever.
-					 */
-					if (startag == NULLAGNUMBER)
-						break;
-
-					error = xfs_filestream_new_ag(ap, &ag);
-					xfs_perag_put(pag);
-					if (error)
-						return error;
-
-					/* loop again to set 'blen'*/
-					startag = NULLAGNUMBER;
-					pag = xfs_perag_get(mp, ag);
-					continue;
-				}
-			}
-			if (++ag == mp->m_sb.sb_agcount)
-				ag = 0;
-			if (ag == startag)
-				break;
-			xfs_perag_put(pag);
-			pag = xfs_perag_get(mp, ag);
-		}
-		xfs_perag_put(pag);
-		/*
-		 * Since the above loop did a BUF_TRYLOCK, it is
-		 * possible that there is space for this request.
-		 */
-		if (notinit || blen < ap->minlen)
-			args.minlen = ap->minlen;
-		/*
-		 * If the best seen length is less than the request
-		 * length, use the best as the minimum.
-		 */
-		else if (blen < ap->alen)
-			args.minlen = blen;
-		/*
-		 * Otherwise we've seen an extent as big as alen,
-		 * use that as the minimum.
-		 */
-		else
-			args.minlen = ap->alen;
-
-		/*
-		 * set the failure fallback case to look in the selected
-		 * AG as the stream may have moved.
-		 */
-		if (xfs_inode_is_filestream(ap->ip))
-			ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
+		error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
+		if (error)
+			return error;
 	} else if (ap->low) {
 		if (xfs_inode_is_filestream(ap->ip))
 			args.type = XFS_ALLOCTYPE_FIRST_AG;
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index f52ac27..7cf7220 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -292,7 +292,8 @@
 	__s32		bs_extents;	/* number of extents		*/
 	__u32		bs_gen;		/* generation count		*/
 	__u16		bs_projid;	/* project id			*/
-	unsigned char	bs_pad[14];	/* pad space, unused		*/
+	__u16		bs_forkoff;	/* inode fork offset in bytes	*/
+	unsigned char	bs_pad[12];	/* pad space, unused		*/
 	__u32		bs_dmevmask;	/* DMIG event mask		*/
 	__u16		bs_dmstate;	/* DMIG state info		*/
 	__u16		bs_aextents;	/* attribute number of extents	*/
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index e281eb4..6845db9 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -190,13 +190,12 @@
 		trace_xfs_iget_reclaim(ip);
 
 		/*
-		 * We need to set XFS_INEW atomically with clearing the
-		 * reclaimable tag so that we do have an indicator of the
-		 * inode still being initialized.
+		 * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
+		 * from stomping over us while we recycle the inode.  We can't
+		 * clear the radix tree reclaimable tag yet as it requires
+		 * pag_ici_lock to be held exclusive.
 		 */
-		ip->i_flags |= XFS_INEW;
-		ip->i_flags &= ~XFS_IRECLAIMABLE;
-		__xfs_inode_clear_reclaim_tag(mp, pag, ip);
+		ip->i_flags |= XFS_IRECLAIM;
 
 		spin_unlock(&ip->i_flags_lock);
 		read_unlock(&pag->pag_ici_lock);
@@ -216,7 +215,15 @@
 			trace_xfs_iget_reclaim(ip);
 			goto out_error;
 		}
+
+		write_lock(&pag->pag_ici_lock);
+		spin_lock(&ip->i_flags_lock);
+		ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM);
+		ip->i_flags |= XFS_INEW;
+		__xfs_inode_clear_reclaim_tag(mp, pag, ip);
 		inode->i_state = I_NEW;
+		spin_unlock(&ip->i_flags_lock);
+		write_unlock(&pag->pag_ici_lock);
 	} else {
 		/* If the VFS inode is being torn down, pause and try again. */
 		if (!igrab(inode)) {
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index fa31360..0ffd564 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2439,75 +2439,31 @@
 }
 
 /*
- * Increment the pin count of the given buffer.
- * This value is protected by ipinlock spinlock in the mount structure.
+ * This is called to unpin an inode.  The caller must have the inode locked
+ * in at least shared mode so that the buffer cannot be subsequently pinned
+ * once someone is waiting for it to be unpinned.
  */
-void
-xfs_ipin(
-	xfs_inode_t	*ip)
+static void
+xfs_iunpin_nowait(
+	struct xfs_inode	*ip)
 {
-	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-
-	atomic_inc(&ip->i_pincount);
-}
-
-/*
- * Decrement the pin count of the given inode, and wake up
- * anyone in xfs_iwait_unpin() if the count goes to 0.  The
- * inode must have been previously pinned with a call to xfs_ipin().
- */
-void
-xfs_iunpin(
-	xfs_inode_t	*ip)
-{
-	ASSERT(atomic_read(&ip->i_pincount) > 0);
-
-	if (atomic_dec_and_test(&ip->i_pincount))
-		wake_up(&ip->i_ipin_wait);
-}
-
-/*
- * This is called to unpin an inode. It can be directed to wait or to return
- * immediately without waiting for the inode to be unpinned.  The caller must
- * have the inode locked in at least shared mode so that the buffer cannot be
- * subsequently pinned once someone is waiting for it to be unpinned.
- */
-STATIC void
-__xfs_iunpin_wait(
-	xfs_inode_t	*ip,
-	int		wait)
-{
-	xfs_inode_log_item_t	*iip = ip->i_itemp;
-
 	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
-	if (atomic_read(&ip->i_pincount) == 0)
-		return;
 
 	/* Give the log a push to start the unpinning I/O */
-	if (iip && iip->ili_last_lsn)
-		xfs_log_force_lsn(ip->i_mount, iip->ili_last_lsn, 0);
-	else
-		xfs_log_force(ip->i_mount, 0);
+	xfs_log_force_lsn(ip->i_mount, ip->i_itemp->ili_last_lsn, 0);
 
-	if (wait)
-		wait_event(ip->i_ipin_wait, (atomic_read(&ip->i_pincount) == 0));
 }
 
 void
 xfs_iunpin_wait(
-	xfs_inode_t	*ip)
+	struct xfs_inode	*ip)
 {
-	__xfs_iunpin_wait(ip, 1);
+	if (xfs_ipincount(ip)) {
+		xfs_iunpin_nowait(ip);
+		wait_event(ip->i_ipin_wait, (xfs_ipincount(ip) == 0));
+	}
 }
 
-static inline void
-xfs_iunpin_nowait(
-	xfs_inode_t	*ip)
-{
-	__xfs_iunpin_wait(ip, 0);
-}
-
-
 /*
  * xfs_iextents_copy()
  *
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 6c912b0..9965e40 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -471,8 +471,6 @@
 int		xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
 
 void		xfs_iext_realloc(xfs_inode_t *, int, int);
-void		xfs_ipin(xfs_inode_t *);
-void		xfs_iunpin(xfs_inode_t *);
 void		xfs_iunpin_wait(xfs_inode_t *);
 int		xfs_iflush(xfs_inode_t *, uint);
 void		xfs_ichgtime(xfs_inode_t *, int);
@@ -480,6 +478,7 @@
 void		xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
 
 void		xfs_synchronize_times(xfs_inode_t *);
+void		xfs_mark_inode_dirty(xfs_inode_t *);
 void		xfs_mark_inode_dirty_sync(xfs_inode_t *);
 
 #define IHOLD(ip) \
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index d4dc063..7bfea85 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -535,23 +535,23 @@
 
 /*
  * This is called to pin the inode associated with the inode log
- * item in memory so it cannot be written out.  Do this by calling
- * xfs_ipin() to bump the pin count in the inode while holding the
- * inode pin lock.
+ * item in memory so it cannot be written out.
  */
 STATIC void
 xfs_inode_item_pin(
 	xfs_inode_log_item_t	*iip)
 {
 	ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL));
-	xfs_ipin(iip->ili_inode);
+
+	atomic_inc(&iip->ili_inode->i_pincount);
 }
 
 
 /*
  * This is called to unpin the inode associated with the inode log
  * item which was previously pinned with a call to xfs_inode_item_pin().
- * Just call xfs_iunpin() on the inode to do this.
+ *
+ * Also wake up anyone in xfs_iunpin_wait() if the count goes to 0.
  */
 /* ARGSUSED */
 STATIC void
@@ -559,7 +559,11 @@
 	xfs_inode_log_item_t	*iip,
 	int			stale)
 {
-	xfs_iunpin(iip->ili_inode);
+	struct xfs_inode	*ip = iip->ili_inode;
+
+	ASSERT(atomic_read(&ip->i_pincount) > 0);
+	if (atomic_dec_and_test(&ip->i_pincount))
+		wake_up(&ip->i_ipin_wait);
 }
 
 /* ARGSUSED */
@@ -568,7 +572,7 @@
 	xfs_inode_log_item_t	*iip,
 	xfs_trans_t		*tp)
 {
-	xfs_iunpin(iip->ili_inode);
+	xfs_inode_item_unpin(iip, 0);
 }
 
 /*
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 3af0231..b1b801e 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -106,6 +106,7 @@
 	buf->bs_dmevmask = dic->di_dmevmask;
 	buf->bs_dmstate = dic->di_dmstate;
 	buf->bs_aextents = dic->di_anextents;
+	buf->bs_forkoff = XFS_IFORK_BOFF(ip);
 
 	switch (dic->di_format) {
 	case XFS_DINODE_FMT_DEV:
@@ -176,6 +177,7 @@
 	buf->bs_dmevmask = be32_to_cpu(dic->di_dmevmask);
 	buf->bs_dmstate = be16_to_cpu(dic->di_dmstate);
 	buf->bs_aextents = be16_to_cpu(dic->di_anextents);
+	buf->bs_forkoff = XFS_DFORK_BOFF(dic);
 
 	switch (dic->di_format) {
 	case XFS_DINODE_FMT_DEV:
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 4f16be4..e8fba92 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -60,7 +60,7 @@
 STATIC int	 xlog_sync(xlog_t *log, xlog_in_core_t *iclog);
 STATIC void	 xlog_dealloc_log(xlog_t *log);
 STATIC int	 xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[],
-			    int nentries, xfs_log_ticket_t tic,
+			    int nentries, struct xlog_ticket *tic,
 			    xfs_lsn_t *start_lsn,
 			    xlog_in_core_t **commit_iclog,
 			    uint flags);
@@ -243,14 +243,14 @@
  * out when the next write occurs.
  */
 xfs_lsn_t
-xfs_log_done(xfs_mount_t	*mp,
-	     xfs_log_ticket_t	xtic,
-	     void		**iclog,
-	     uint		flags)
+xfs_log_done(
+	struct xfs_mount	*mp,
+	struct xlog_ticket	*ticket,
+	struct xlog_in_core	**iclog,
+	uint			flags)
 {
-	xlog_t		*log    = mp->m_log;
-	xlog_ticket_t	*ticket = (xfs_log_ticket_t) xtic;
-	xfs_lsn_t	lsn	= 0;
+	struct log		*log = mp->m_log;
+	xfs_lsn_t		lsn = 0;
 
 	if (XLOG_FORCED_SHUTDOWN(log) ||
 	    /*
@@ -258,8 +258,7 @@
 	     * If we get an error, just continue and give back the log ticket.
 	     */
 	    (((ticket->t_flags & XLOG_TIC_INITED) == 0) &&
-	     (xlog_commit_record(mp, ticket,
-				 (xlog_in_core_t **)iclog, &lsn)))) {
+	     (xlog_commit_record(mp, ticket, iclog, &lsn)))) {
 		lsn = (xfs_lsn_t) -1;
 		if (ticket->t_flags & XLOG_TIC_PERM_RESERV) {
 			flags |= XFS_LOG_REL_PERM_RESERV;
@@ -289,7 +288,7 @@
 	}
 
 	return lsn;
-}	/* xfs_log_done */
+}
 
 /*
  * Attaches a new iclog I/O completion callback routine during
@@ -298,11 +297,11 @@
  * executing the callback at an appropriate time.
  */
 int
-xfs_log_notify(xfs_mount_t	  *mp,		/* mount of partition */
-	       void		  *iclog_hndl,	/* iclog to hang callback off */
-	       xfs_log_callback_t *cb)
+xfs_log_notify(
+	struct xfs_mount	*mp,
+	struct xlog_in_core	*iclog,
+	xfs_log_callback_t	*cb)
 {
-	xlog_in_core_t	  *iclog = (xlog_in_core_t *)iclog_hndl;
 	int	abortflg;
 
 	spin_lock(&iclog->ic_callback_lock);
@@ -316,16 +315,14 @@
 	}
 	spin_unlock(&iclog->ic_callback_lock);
 	return abortflg;
-}	/* xfs_log_notify */
+}
 
 int
-xfs_log_release_iclog(xfs_mount_t *mp,
-		      void	  *iclog_hndl)
+xfs_log_release_iclog(
+	struct xfs_mount	*mp,
+	struct xlog_in_core	*iclog)
 {
-	xlog_t *log = mp->m_log;
-	xlog_in_core_t	  *iclog = (xlog_in_core_t *)iclog_hndl;
-
-	if (xlog_state_release_iclog(log, iclog)) {
+	if (xlog_state_release_iclog(mp->m_log, iclog)) {
 		xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
 		return EIO;
 	}
@@ -344,17 +341,18 @@
  * reservation, we prevent over allocation problems.
  */
 int
-xfs_log_reserve(xfs_mount_t	 *mp,
-		int		 unit_bytes,
-		int		 cnt,
-		xfs_log_ticket_t *ticket,
-		__uint8_t	 client,
-		uint		 flags,
-		uint		 t_type)
+xfs_log_reserve(
+	struct xfs_mount	*mp,
+	int		 	unit_bytes,
+	int		 	cnt,
+	struct xlog_ticket	**ticket,
+	__uint8_t	 	client,
+	uint		 	flags,
+	uint		 	t_type)
 {
-	xlog_t		*log = mp->m_log;
-	xlog_ticket_t	*internal_ticket;
-	int		retval = 0;
+	struct log		*log = mp->m_log;
+	struct xlog_ticket	*internal_ticket;
+	int			retval = 0;
 
 	ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);
 	ASSERT((flags & XFS_LOG_NOSLEEP) == 0);
@@ -367,7 +365,7 @@
 
 	if (*ticket != NULL) {
 		ASSERT(flags & XFS_LOG_PERM_RESERV);
-		internal_ticket = (xlog_ticket_t *)*ticket;
+		internal_ticket = *ticket;
 
 		trace_xfs_log_reserve(log, internal_ticket);
 
@@ -519,7 +517,7 @@
 	xlog_in_core_t	 *first_iclog;
 #endif
 	xfs_log_iovec_t  reg[1];
-	xfs_log_ticket_t tic = NULL;
+	xlog_ticket_t	*tic = NULL;
 	xfs_lsn_t	 lsn;
 	int		 error;
 
@@ -656,24 +654,24 @@
  * transaction occur with one call to xfs_log_write().
  */
 int
-xfs_log_write(xfs_mount_t *	mp,
-	      xfs_log_iovec_t	reg[],
-	      int		nentries,
-	      xfs_log_ticket_t	tic,
-	      xfs_lsn_t		*start_lsn)
+xfs_log_write(
+	struct xfs_mount	*mp,
+	struct xfs_log_iovec	reg[],
+	int			nentries,
+	struct xlog_ticket	*tic,
+	xfs_lsn_t		*start_lsn)
 {
-	int	error;
-	xlog_t *log = mp->m_log;
+	struct log		*log = mp->m_log;
+	int			error;
 
 	if (XLOG_FORCED_SHUTDOWN(log))
 		return XFS_ERROR(EIO);
 
-	if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) {
+	error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0);
+	if (error)
 		xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
-	}
 	return error;
-}	/* xfs_log_write */
-
+}
 
 void
 xfs_log_move_tail(xfs_mount_t	*mp,
@@ -1642,16 +1640,16 @@
  *	bytes have been written out.
  */
 STATIC int
-xlog_write(xfs_mount_t *	mp,
-	   xfs_log_iovec_t	reg[],
-	   int			nentries,
-	   xfs_log_ticket_t	tic,
-	   xfs_lsn_t		*start_lsn,
-	   xlog_in_core_t	**commit_iclog,
-	   uint			flags)
+xlog_write(
+	struct xfs_mount	*mp,
+	struct xfs_log_iovec	reg[],
+	int			nentries,
+	struct xlog_ticket	*ticket,
+	xfs_lsn_t		*start_lsn,
+	struct xlog_in_core	**commit_iclog,
+	uint			flags)
 {
     xlog_t	     *log = mp->m_log;
-    xlog_ticket_t    *ticket = (xlog_ticket_t *)tic;
     xlog_in_core_t   *iclog = NULL;  /* ptr to current in-core log */
     xlog_op_header_t *logop_head;    /* ptr to log operation header */
     __psint_t	     ptr;	     /* copy address into data region */
@@ -1765,7 +1763,7 @@
 	    default:
 		xfs_fs_cmn_err(CE_WARN, mp,
 		    "Bad XFS transaction clientid 0x%x in ticket 0x%p",
-		    logop_head->oh_clientid, tic);
+		    logop_head->oh_clientid, ticket);
 		return XFS_ERROR(EIO);
 	    }
 
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 7074be9..97a24c7 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -110,8 +110,6 @@
 	uint		i_type;		/* type of region */
 } xfs_log_iovec_t;
 
-typedef void* xfs_log_ticket_t;
-
 /*
  * Structure used to pass callback function and the function's argument
  * to the log manager.
@@ -126,10 +124,12 @@
 #ifdef __KERNEL__
 /* Log manager interfaces */
 struct xfs_mount;
+struct xlog_in_core;
 struct xlog_ticket;
+
 xfs_lsn_t xfs_log_done(struct xfs_mount *mp,
-		       xfs_log_ticket_t ticket,
-		       void		**iclog,
+		       struct xlog_ticket *ticket,
+		       struct xlog_in_core **iclog,
 		       uint		flags);
 int	  _xfs_log_force(struct xfs_mount *mp,
 			 uint		flags,
@@ -151,21 +151,21 @@
 void	  xfs_log_move_tail(struct xfs_mount	*mp,
 			    xfs_lsn_t		tail_lsn);
 int	  xfs_log_notify(struct xfs_mount	*mp,
-			 void			*iclog,
+			 struct xlog_in_core	*iclog,
 			 xfs_log_callback_t	*callback_entry);
 int	  xfs_log_release_iclog(struct xfs_mount *mp,
-			 void			 *iclog_hndl);
+			 struct xlog_in_core	 *iclog);
 int	  xfs_log_reserve(struct xfs_mount *mp,
 			  int		   length,
 			  int		   count,
-			  xfs_log_ticket_t *ticket,
+			  struct xlog_ticket **ticket,
 			  __uint8_t	   clientid,
 			  uint		   flags,
 			  uint		   t_type);
 int	  xfs_log_write(struct xfs_mount *mp,
 			xfs_log_iovec_t  region[],
 			int		 nentries,
-			xfs_log_ticket_t ticket,
+			struct xlog_ticket *ticket,
 			xfs_lsn_t	 *start_lsn);
 int	  xfs_log_unmount_write(struct xfs_mount *mp);
 void      xfs_log_unmount(struct xfs_mount *mp);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 6afaaeb..e79b56b 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1097,13 +1097,15 @@
 	__uint64_t resblks;
 
 	/*
-	 * We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
-	 * This may drive us straight to ENOSPC on mount, but that implies
-	 * we were already there on the last unmount. Warn if this occurs.
+	 * We default to 5% or 8192 fsbs of space reserved, whichever is
+	 * smaller.  This is intended to cover concurrent allocation
+	 * transactions when we initially hit enospc. These each require a 4
+	 * block reservation. Hence by default we cover roughly 2000 concurrent
+	 * allocation reservations.
 	 */
 	resblks = mp->m_sb.sb_dblocks;
 	do_div(resblks, 20);
-	resblks = min_t(__uint64_t, resblks, 1024);
+	resblks = min_t(__uint64_t, resblks, 8192);
 	return resblks;
 }
 
@@ -1417,6 +1419,9 @@
 	 * when at ENOSPC. This is needed for operations like create with
 	 * attr, unwritten extent conversion at ENOSPC, etc. Data allocations
 	 * are not allowed to use this reserved space.
+	 *
+	 * This may drive us straight to ENOSPC on mount, but that implies
+	 * we were already there on the last unmount. Warn if this occurs.
 	 */
 	if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
 		resblks = xfs_default_resblks(mp);
@@ -1725,26 +1730,30 @@
 				lcounter += rem;
 			}
 		} else {				/* Taking blocks away */
-
 			lcounter += delta;
-
-		/*
-		 * If were out of blocks, use any available reserved blocks if
-		 * were allowed to.
-		 */
-
-			if (lcounter < 0) {
-				if (rsvd) {
-					lcounter = (long long)mp->m_resblks_avail + delta;
-					if (lcounter < 0) {
-						return XFS_ERROR(ENOSPC);
-					}
-					mp->m_resblks_avail = lcounter;
-					return 0;
-				} else {	/* not reserved */
-					return XFS_ERROR(ENOSPC);
-				}
+			if (lcounter >= 0) {
+				mp->m_sb.sb_fdblocks = lcounter +
+							XFS_ALLOC_SET_ASIDE(mp);
+				return 0;
 			}
+
+			/*
+			 * We are out of blocks, use any available reserved
+			 * blocks if were allowed to.
+			 */
+			if (!rsvd)
+				return XFS_ERROR(ENOSPC);
+
+			lcounter = (long long)mp->m_resblks_avail + delta;
+			if (lcounter >= 0) {
+				mp->m_resblks_avail = lcounter;
+				return 0;
+			}
+			printk_once(KERN_WARNING
+				"Filesystem \"%s\": reserve blocks depleted! "
+				"Consider increasing reserve pool size.",
+				mp->m_fsname);
+			return XFS_ERROR(ENOSPC);
 		}
 
 		mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
@@ -2052,6 +2061,26 @@
 	return error;
 }
 
+/*
+ * If the underlying (data/log/rt) device is readonly, there are some
+ * operations that cannot proceed.
+ */
+int
+xfs_dev_is_read_only(
+	struct xfs_mount	*mp,
+	char			*message)
+{
+	if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
+	    xfs_readonly_buftarg(mp->m_logdev_targp) ||
+	    (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
+		cmn_err(CE_NOTE,
+			"XFS: %s required on read-only device.", message);
+		cmn_err(CE_NOTE,
+			"XFS: write access unavailable, cannot proceed.");
+		return EROFS;
+	}
+	return 0;
+}
 
 #ifdef HAVE_PERCPU_SB
 /*
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 70504fc..4fa0bc7 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -245,7 +245,7 @@
 	struct xfs_qmops	*m_qm_ops;	/* vector of XQM ops */
 	atomic_t		m_active_trans;	/* number trans frozen */
 #ifdef HAVE_PERCPU_SB
-	xfs_icsb_cnts_t		*m_sb_cnts;	/* per-cpu superblock counters */
+	xfs_icsb_cnts_t __percpu *m_sb_cnts;	/* per-cpu superblock counters */
 	unsigned long		m_icsb_counters; /* disabled per-cpu counters */
 	struct notifier_block	m_icsb_notifier; /* hotplug cpu notifier */
 	struct mutex		m_icsb_mutex;	/* balancer sync lock */
@@ -436,6 +436,8 @@
 extern int	xfs_fs_writable(xfs_mount_t *);
 extern int	xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
 
+extern int	xfs_dev_is_read_only(struct xfs_mount *, char *);
+
 extern int	xfs_dmops_get(struct xfs_mount *);
 extern void	xfs_dmops_put(struct xfs_mount *);
 
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index be942d4..f73e358 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -796,7 +796,7 @@
 	int			sync;
 #define	XFS_TRANS_LOGVEC_COUNT	16
 	xfs_log_iovec_t		log_vector_fast[XFS_TRANS_LOGVEC_COUNT];
-	void			*commit_iclog;
+	struct xlog_in_core	*commit_iclog;
 	int			shutdown;
 
 	commit_lsn = -1;
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index c93e3a1..79c8bab 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -910,7 +910,7 @@
 	unsigned int		t_blk_res_used;	/* # of resvd blocks used */
 	unsigned int		t_rtx_res;	/* # of rt extents resvd */
 	unsigned int		t_rtx_res_used;	/* # of resvd rt extents used */
-	xfs_log_ticket_t	t_ticket;	/* log mgr ticket */
+	struct xlog_ticket	*t_ticket;	/* log mgr ticket */
 	xfs_lsn_t		t_lsn;		/* log seq num of start of
 						 * transaction. */
 	xfs_lsn_t		t_commit_lsn;	/* log seq num of end of
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 5ffd544..fb586360 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -46,6 +46,65 @@
 STATIC xfs_buf_t *xfs_trans_buf_item_match_all(xfs_trans_t *, xfs_buftarg_t *,
 		xfs_daddr_t, int);
 
+/*
+ * Add the locked buffer to the transaction.
+ *
+ * The buffer must be locked, and it cannot be associated with any
+ * transaction.
+ *
+ * If the buffer does not yet have a buf log item associated with it,
+ * then allocate one for it.  Then add the buf item to the transaction.
+ */
+STATIC void
+_xfs_trans_bjoin(
+	struct xfs_trans	*tp,
+	struct xfs_buf		*bp,
+	int			reset_recur)
+{
+	struct xfs_buf_log_item	*bip;
+
+	ASSERT(XFS_BUF_ISBUSY(bp));
+	ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL);
+
+	/*
+	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If
+	 * it doesn't have one yet, then allocate one and initialize it.
+	 * The checks to see if one is there are in xfs_buf_item_init().
+	 */
+	xfs_buf_item_init(bp, tp->t_mountp);
+	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
+	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
+	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
+	if (reset_recur)
+		bip->bli_recur = 0;
+
+	/*
+	 * Take a reference for this transaction on the buf item.
+	 */
+	atomic_inc(&bip->bli_refcount);
+
+	/*
+	 * Get a log_item_desc to point at the new item.
+	 */
+	(void) xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
+
+	/*
+	 * Initialize b_fsprivate2 so we can find it with incore_match()
+	 * in xfs_trans_get_buf() and friends above.
+	 */
+	XFS_BUF_SET_FSPRIVATE2(bp, tp);
+
+}
+
+void
+xfs_trans_bjoin(
+	struct xfs_trans	*tp,
+	struct xfs_buf		*bp)
+{
+	_xfs_trans_bjoin(tp, bp, 0);
+	trace_xfs_trans_bjoin(bp->b_fspriv);
+}
 
 /*
  * Get and lock the buffer for the caller if it is not already
@@ -132,40 +191,8 @@
 
 	ASSERT(!XFS_BUF_GETERROR(bp));
 
-	/*
-	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If
-	 * it doesn't have one yet, then allocate one and initialize it.
-	 * The checks to see if one is there are in xfs_buf_item_init().
-	 */
-	xfs_buf_item_init(bp, tp->t_mountp);
-
-	/*
-	 * Set the recursion count for the buffer within this transaction
-	 * to 0.
-	 */
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
-	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
-	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
-	bip->bli_recur = 0;
-
-	/*
-	 * Take a reference for this transaction on the buf item.
-	 */
-	atomic_inc(&bip->bli_refcount);
-
-	/*
-	 * Get a log_item_desc to point at the new item.
-	 */
-	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);
-
-	/*
-	 * Initialize b_fsprivate2 so we can find it with incore_match()
-	 * above.
-	 */
-	XFS_BUF_SET_FSPRIVATE2(bp, tp);
-
-	trace_xfs_trans_get_buf(bip);
+	_xfs_trans_bjoin(tp, bp, 1);
+	trace_xfs_trans_get_buf(bp->b_fspriv);
 	return (bp);
 }
 
@@ -210,44 +237,11 @@
 	}
 
 	bp = xfs_getsb(mp, flags);
-	if (bp == NULL) {
+	if (bp == NULL)
 		return NULL;
-	}
 
-	/*
-	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If
-	 * it doesn't have one yet, then allocate one and initialize it.
-	 * The checks to see if one is there are in xfs_buf_item_init().
-	 */
-	xfs_buf_item_init(bp, mp);
-
-	/*
-	 * Set the recursion count for the buffer within this transaction
-	 * to 0.
-	 */
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
-	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
-	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
-	bip->bli_recur = 0;
-
-	/*
-	 * Take a reference for this transaction on the buf item.
-	 */
-	atomic_inc(&bip->bli_refcount);
-
-	/*
-	 * Get a log_item_desc to point at the new item.
-	 */
-	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);
-
-	/*
-	 * Initialize b_fsprivate2 so we can find it with incore_match()
-	 * above.
-	 */
-	XFS_BUF_SET_FSPRIVATE2(bp, tp);
-
-	trace_xfs_trans_getsb(bip);
+	_xfs_trans_bjoin(tp, bp, 1);
+	trace_xfs_trans_getsb(bp->b_fspriv);
 	return (bp);
 }
 
@@ -425,40 +419,9 @@
 	if (XFS_FORCED_SHUTDOWN(mp))
 		goto shutdown_abort;
 
-	/*
-	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If
-	 * it doesn't have one yet, then allocate one and initialize it.
-	 * The checks to see if one is there are in xfs_buf_item_init().
-	 */
-	xfs_buf_item_init(bp, tp->t_mountp);
+	_xfs_trans_bjoin(tp, bp, 1);
+	trace_xfs_trans_read_buf(bp->b_fspriv);
 
-	/*
-	 * Set the recursion count for the buffer within this transaction
-	 * to 0.
-	 */
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
-	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
-	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
-	bip->bli_recur = 0;
-
-	/*
-	 * Take a reference for this transaction on the buf item.
-	 */
-	atomic_inc(&bip->bli_refcount);
-
-	/*
-	 * Get a log_item_desc to point at the new item.
-	 */
-	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);
-
-	/*
-	 * Initialize b_fsprivate2 so we can find it with incore_match()
-	 * above.
-	 */
-	XFS_BUF_SET_FSPRIVATE2(bp, tp);
-
-	trace_xfs_trans_read_buf(bip);
 	*bpp = bp;
 	return 0;
 
@@ -623,53 +586,6 @@
 }
 
 /*
- * Add the locked buffer to the transaction.
- * The buffer must be locked, and it cannot be associated with any
- * transaction.
- *
- * If the buffer does not yet have a buf log item associated with it,
- * then allocate one for it.  Then add the buf item to the transaction.
- */
-void
-xfs_trans_bjoin(xfs_trans_t	*tp,
-		xfs_buf_t	*bp)
-{
-	xfs_buf_log_item_t	*bip;
-
-	ASSERT(XFS_BUF_ISBUSY(bp));
-	ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL);
-
-	/*
-	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If
-	 * it doesn't have one yet, then allocate one and initialize it.
-	 * The checks to see if one is there are in xfs_buf_item_init().
-	 */
-	xfs_buf_item_init(bp, tp->t_mountp);
-	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
-	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
-	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
-
-	/*
-	 * Take a reference for this transaction on the buf item.
-	 */
-	atomic_inc(&bip->bli_refcount);
-
-	/*
-	 * Get a log_item_desc to point at the new item.
-	 */
-	(void) xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
-
-	/*
-	 * Initialize b_fsprivate2 so we can find it with incore_match()
-	 * in xfs_trans_get_buf() and friends above.
-	 */
-	XFS_BUF_SET_FSPRIVATE2(bp, tp);
-
-	trace_xfs_trans_bjoin(bip);
-}
-
-/*
  * Mark the buffer as not needing to be unlocked when the buf item's
  * IOP_UNLOCK() routine is called.  The buffer must already be locked
  * and associated with the given transaction.
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index ddd2c5d..9d376be 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -584,113 +584,6 @@
 }
 
 /*
- * xfs_fsync
- *
- * This is called to sync the inode and its data out to disk.  We need to hold
- * the I/O lock while flushing the data, and the inode lock while flushing the
- * inode.  The inode lock CANNOT be held while flushing the data, so acquire
- * after we're done with that.
- */
-int
-xfs_fsync(
-	xfs_inode_t	*ip)
-{
-	xfs_trans_t	*tp;
-	int		error = 0;
-	int		log_flushed = 0;
-
-	xfs_itrace_entry(ip);
-
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-		return XFS_ERROR(EIO);
-
-	/*
-	 * We always need to make sure that the required inode state is safe on
-	 * disk.  The inode might be clean but we still might need to force the
-	 * log because of committed transactions that haven't hit the disk yet.
-	 * Likewise, there could be unflushed non-transactional changes to the
-	 * inode core that have to go to disk and this requires us to issue
-	 * a synchronous transaction to capture these changes correctly.
-	 *
-	 * This code relies on the assumption that if the update_* fields
-	 * of the inode are clear and the inode is unpinned then it is clean
-	 * and no action is required.
-	 */
-	xfs_ilock(ip, XFS_ILOCK_SHARED);
-
-	if (!ip->i_update_core) {
-		/*
-		 * Timestamps/size haven't changed since last inode flush or
-		 * inode transaction commit.  That means either nothing got
-		 * written or a transaction committed which caught the updates.
-		 * If the latter happened and the transaction hasn't hit the
-		 * disk yet, the inode will be still be pinned.  If it is,
-		 * force the log.
-		 */
-		xfs_iunlock(ip, XFS_ILOCK_SHARED);
-		if (xfs_ipincount(ip)) {
-			if (ip->i_itemp->ili_last_lsn) {
-				error = _xfs_log_force_lsn(ip->i_mount,
-						ip->i_itemp->ili_last_lsn,
-						XFS_LOG_SYNC, &log_flushed);
-			} else {
-				error = _xfs_log_force(ip->i_mount,
-						XFS_LOG_SYNC, &log_flushed);
-			}
-		}
-	} else	{
-		/*
-		 * Kick off a transaction to log the inode core to get the
-		 * updates.  The sync transaction will also force the log.
-		 */
-		xfs_iunlock(ip, XFS_ILOCK_SHARED);
-		tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS);
-		error = xfs_trans_reserve(tp, 0,
-				XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0);
-		if (error) {
-			xfs_trans_cancel(tp, 0);
-			return error;
-		}
-		xfs_ilock(ip, XFS_ILOCK_EXCL);
-
-		/*
-		 * Note - it's possible that we might have pushed ourselves out
-		 * of the way during trans_reserve which would flush the inode.
-		 * But there's no guarantee that the inode buffer has actually
-		 * gone out yet (it's delwri).	Plus the buffer could be pinned
-		 * anyway if it's part of an inode in another recent
-		 * transaction.	 So we play it safe and fire off the
-		 * transaction anyway.
-		 */
-		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-		xfs_trans_ihold(tp, ip);
-		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-		xfs_trans_set_sync(tp);
-		error = _xfs_trans_commit(tp, 0, &log_flushed);
-
-		xfs_iunlock(ip, XFS_ILOCK_EXCL);
-	}
-
-	if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) {
-		/*
-		 * If the log write didn't issue an ordered tag we need
-		 * to flush the disk cache for the data device now.
-		 */
-		if (!log_flushed)
-			xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp);
-
-		/*
-		 * If this inode is on the RT dev we need to flush that
-		 * cache as well.
-		 */
-		if (XFS_IS_REALTIME_INODE(ip))
-			xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp);
-	}
-
-	return error;
-}
-
-/*
  * Flags for xfs_free_eofblocks
  */
 #define XFS_FREE_EOF_TRYLOCK	(1<<0)
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index 774f407..d8dfa8d 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -21,7 +21,6 @@
 #define XFS_ATTR_NOACL		0x08	/* Don't call xfs_acl_chmod */
 
 int xfs_readlink(struct xfs_inode *ip, char *link);
-int xfs_fsync(struct xfs_inode *ip);
 int xfs_release(struct xfs_inode *ip);
 int xfs_inactive(struct xfs_inode *ip);
 int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
@@ -50,18 +49,6 @@
 int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
 int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
 		int flags, struct attrlist_cursor_kern *cursor);
-ssize_t xfs_read(struct xfs_inode *ip, struct kiocb *iocb,
-		const struct iovec *iovp, unsigned int segs,
-		loff_t *offset, int ioflags);
-ssize_t xfs_splice_read(struct xfs_inode *ip, struct file *infilp,
-		loff_t *ppos, struct pipe_inode_info *pipe, size_t count,
-		int flags, int ioflags);
-ssize_t xfs_splice_write(struct xfs_inode *ip,
-		struct pipe_inode_info *pipe, struct file *outfilp,
-		loff_t *ppos, size_t count, int flags, int ioflags);
-ssize_t xfs_write(struct xfs_inode *xip, struct kiocb *iocb,
-		const struct iovec *iovp, unsigned int nsegs,
-		loff_t *offset, int ioflags);
 int xfs_bmap(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
 		int flags, struct xfs_iomap *iomapp, int *niomaps);
 void xfs_tosspages(struct xfs_inode *inode, xfs_off_t first,
@@ -72,4 +59,6 @@
 		xfs_off_t last, uint64_t flags, int fiopt);
 int xfs_wait_on_pages(struct xfs_inode *ip, xfs_off_t first, xfs_off_t last);
 
+int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
+
 #endif /* _XFS_VNODEOPS_H */
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 2983176..1172c27 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -238,7 +238,7 @@
 
 extern int acpi_processor_preregister_performance(struct
 						  acpi_processor_performance
-						  *performance);
+						  __percpu *performance);
 
 extern int acpi_processor_register_performance(struct acpi_processor_performance
 					       *performance, unsigned int cpu);
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 485eeb6..979c6a5 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -136,6 +136,32 @@
 
 extern int __gpio_to_irq(unsigned gpio);
 
+#define GPIOF_DIR_OUT	(0 << 0)
+#define GPIOF_DIR_IN	(1 << 0)
+
+#define GPIOF_INIT_LOW	(0 << 1)
+#define GPIOF_INIT_HIGH	(1 << 1)
+
+#define GPIOF_IN		(GPIOF_DIR_IN)
+#define GPIOF_OUT_INIT_LOW	(GPIOF_DIR_OUT | GPIOF_INIT_LOW)
+#define GPIOF_OUT_INIT_HIGH	(GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
+
+/**
+ * struct gpio - a structure describing a GPIO with configuration
+ * @gpio:	the GPIO number
+ * @flags:	GPIO configuration as specified by GPIOF_*
+ * @label:	a literal description string of this GPIO
+ */
+struct gpio {
+	unsigned	gpio;
+	unsigned long	flags;
+	const char	*label;
+};
+
+extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
+extern int gpio_request_array(struct gpio *array, size_t num);
+extern void gpio_free_array(struct gpio *array, size_t num);
+
 #ifdef CONFIG_GPIO_SYSFS
 
 /*
diff --git a/include/asm-generic/local.h b/include/asm-generic/local.h
index fc21844..c8a5d68 100644
--- a/include/asm-generic/local.h
+++ b/include/asm-generic/local.h
@@ -52,23 +52,4 @@
 #define __local_add(i,l)	local_set((l), local_read(l) + (i))
 #define __local_sub(i,l)	local_set((l), local_read(l) - (i))
 
-/* Use these for per-cpu local_t variables: on some archs they are
- * much more efficient than these naive implementations.  Note they take
- * a variable (eg. mystruct.foo), not an address.
- */
-#define cpu_local_read(l)	local_read(&__get_cpu_var(l))
-#define cpu_local_set(l, i)	local_set(&__get_cpu_var(l), (i))
-#define cpu_local_inc(l)	local_inc(&__get_cpu_var(l))
-#define cpu_local_dec(l)	local_dec(&__get_cpu_var(l))
-#define cpu_local_add(i, l)	local_add((i), &__get_cpu_var(l))
-#define cpu_local_sub(i, l)	local_sub((i), &__get_cpu_var(l))
-
-/* Non-atomic increments, ie. preemption disabled and won't be touched
- * in interrupt, etc.  Some archs can optimize this case well.
- */
-#define __cpu_local_inc(l)	__local_inc(&__get_cpu_var(l))
-#define __cpu_local_dec(l)	__local_dec(&__get_cpu_var(l))
-#define __cpu_local_add(i, l)	__local_add((i), &__get_cpu_var(l))
-#define __cpu_local_sub(i, l)	__local_sub((i), &__get_cpu_var(l))
-
 #endif /* _ASM_GENERIC_LOCAL_H */
diff --git a/include/asm-generic/pci-dma-compat.h b/include/asm-generic/pci-dma-compat.h
index 37b3706..1437b7d 100644
--- a/include/asm-generic/pci-dma-compat.h
+++ b/include/asm-generic/pci-dma-compat.h
@@ -6,9 +6,6 @@
 
 #include <linux/dma-mapping.h>
 
-/* note pci_set_dma_mask isn't here, since it's a public function
- * exported from drivers/pci, use dma_supported instead */
-
 static inline int
 pci_dma_supported(struct pci_dev *hwdev, u64 mask)
 {
@@ -104,4 +101,16 @@
 	return dma_mapping_error(&pdev->dev, dma_addr);
 }
 
+#ifdef CONFIG_PCI
+static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{
+	return dma_set_mask(&dev->dev, mask);
+}
+
+static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
+{
+	return dma_set_coherent_mask(&dev->dev, mask);
+}
+#endif
+
 #endif
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index 8087b90..04f91c2 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -41,7 +41,11 @@
  * Only S390 provides its own means of moving the pointer.
  */
 #ifndef SHIFT_PERCPU_PTR
-#define SHIFT_PERCPU_PTR(__p, __offset)	RELOC_HIDE((__p), (__offset))
+/* Weird cast keeps both GCC and sparse happy. */
+#define SHIFT_PERCPU_PTR(__p, __offset)	({				\
+	__verify_pcpu_ptr((__p));					\
+	RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \
+})
 #endif
 
 /*
@@ -50,11 +54,11 @@
  * offset.
  */
 #define per_cpu(var, cpu) \
-	(*SHIFT_PERCPU_PTR(&per_cpu_var(var), per_cpu_offset(cpu)))
+	(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
 #define __get_cpu_var(var) \
-	(*SHIFT_PERCPU_PTR(&per_cpu_var(var), my_cpu_offset))
+	(*SHIFT_PERCPU_PTR(&(var), my_cpu_offset))
 #define __raw_get_cpu_var(var) \
-	(*SHIFT_PERCPU_PTR(&per_cpu_var(var), __my_cpu_offset))
+	(*SHIFT_PERCPU_PTR(&(var), __my_cpu_offset))
 
 #define this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, my_cpu_offset)
 #define __this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, __my_cpu_offset)
@@ -66,9 +70,9 @@
 
 #else /* ! SMP */
 
-#define per_cpu(var, cpu)			(*((void)(cpu), &per_cpu_var(var)))
-#define __get_cpu_var(var)			per_cpu_var(var)
-#define __raw_get_cpu_var(var)			per_cpu_var(var)
+#define per_cpu(var, cpu)			(*((void)(cpu), &(var)))
+#define __get_cpu_var(var)			(var)
+#define __raw_get_cpu_var(var)			(var)
 #define this_cpu_ptr(ptr) per_cpu_ptr(ptr, 0)
 #define __this_cpu_ptr(ptr) this_cpu_ptr(ptr)
 
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index ffac157..4a3c4e4 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -801,6 +801,7 @@
 	 */
 	int (*gem_init_object) (struct drm_gem_object *obj);
 	void (*gem_free_object) (struct drm_gem_object *obj);
+	void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
 
 	/* vga arb irq handler */
 	void (*vgaarb_irq)(struct drm_device *dev, bool state);
@@ -1427,6 +1428,7 @@
 int drm_gem_init(struct drm_device *dev);
 void drm_gem_destroy(struct drm_device *dev);
 void drm_gem_object_free(struct kref *kref);
+void drm_gem_object_free_unlocked(struct kref *kref);
 struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
 					    size_t size);
 void drm_gem_object_handle_free(struct kref *kref);
@@ -1443,10 +1445,15 @@
 static inline void
 drm_gem_object_unreference(struct drm_gem_object *obj)
 {
-	if (obj == NULL)
-		return;
+	if (obj != NULL)
+		kref_put(&obj->refcount, drm_gem_object_free);
+}
 
-	kref_put(&obj->refcount, drm_gem_object_free);
+static inline void
+drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
+{
+	if (obj != NULL)
+		kref_put(&obj->refcount, drm_gem_object_free_unlocked);
 }
 
 int drm_gem_handle_create(struct drm_file *file_priv,
@@ -1475,6 +1482,21 @@
 	drm_gem_object_unreference(obj);
 }
 
+static inline void
+drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
+{
+	if (obj == NULL)
+		return;
+
+	/*
+	* Must bump handle count first as this may be the last
+	* ref, in which case the object would disappear before we
+	* checked for a name
+	*/
+	kref_put(&obj->handlecount, drm_gem_object_handle_free);
+	drm_gem_object_unreference_unlocked(obj);
+}
+
 struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev,
 					     struct drm_file *filp,
 					     u32 handle);
diff --git a/include/drm/drm_buffer.h b/include/drm/drm_buffer.h
new file mode 100644
index 0000000..322dbff
--- /dev/null
+++ b/include/drm/drm_buffer.h
@@ -0,0 +1,148 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Pauli Nieminen.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+/*
+ * Multipart buffer for coping data which is larger than the page size.
+ *
+ * Authors:
+ * Pauli Nieminen <suokkos-at-gmail-dot-com>
+ */
+
+#ifndef _DRM_BUFFER_H_
+#define _DRM_BUFFER_H_
+
+#include "drmP.h"
+
+struct drm_buffer {
+	int iterator;
+	int size;
+	char *data[];
+};
+
+
+/**
+ * Return the index of page that buffer is currently pointing at.
+ */
+static inline int drm_buffer_page(struct drm_buffer *buf)
+{
+	return buf->iterator / PAGE_SIZE;
+}
+/**
+ * Return the index of the current byte in the page
+ */
+static inline int drm_buffer_index(struct drm_buffer *buf)
+{
+	return buf->iterator & (PAGE_SIZE - 1);
+}
+/**
+ * Return number of bytes that is left to process
+ */
+static inline int drm_buffer_unprocessed(struct drm_buffer *buf)
+{
+	return buf->size - buf->iterator;
+}
+
+/**
+ * Advance the buffer iterator number of bytes that is given.
+ */
+static inline void drm_buffer_advance(struct drm_buffer *buf, int bytes)
+{
+	buf->iterator += bytes;
+}
+
+/**
+ * Allocate the drm buffer object.
+ *
+ *   buf: A pointer to a pointer where the object is stored.
+ *   size: The number of bytes to allocate.
+ */
+extern int drm_buffer_alloc(struct drm_buffer **buf, int size);
+
+/**
+ * Copy the user data to the begin of the buffer and reset the processing
+ * iterator.
+ *
+ *   user_data: A pointer the data that is copied to the buffer.
+ *   size: The Number of bytes to copy.
+ */
+extern int drm_buffer_copy_from_user(struct drm_buffer *buf,
+		void __user *user_data, int size);
+
+/**
+ * Free the drm buffer object
+ */
+extern void drm_buffer_free(struct drm_buffer *buf);
+
+/**
+ * Read an object from buffer that may be split to multiple parts. If object
+ * is not split function just returns the pointer to object in buffer. But in
+ * case of split object data is copied to given stack object that is suplied
+ * by caller.
+ *
+ * The processing location of the buffer is also advanced to the next byte
+ * after the object.
+ *
+ *   objsize: The size of the objet in bytes.
+ *   stack_obj: A pointer to a memory location where object can be copied.
+ */
+extern void *drm_buffer_read_object(struct drm_buffer *buf,
+		int objsize, void *stack_obj);
+
+/**
+ * Returns the pointer to the dword which is offset number of elements from the
+ * current processing location.
+ *
+ * Caller must make sure that dword is not split in the buffer. This
+ * requirement is easily met if all the sizes of objects in buffer are
+ * multiples of dword and PAGE_SIZE is multiple dword.
+ *
+ * Call to this function doesn't change the processing location.
+ *
+ *   offset: The index of the dword relative to the internat iterator.
+ */
+static inline void *drm_buffer_pointer_to_dword(struct drm_buffer *buffer,
+		int offset)
+{
+	int iter = buffer->iterator + offset * 4;
+	return &buffer->data[iter / PAGE_SIZE][iter & (PAGE_SIZE - 1)];
+}
+/**
+ * Returns the pointer to the dword which is offset number of elements from
+ * the current processing location.
+ *
+ * Call to this function doesn't change the processing location.
+ *
+ *   offset: The index of the byte relative to the internat iterator.
+ */
+static inline void *drm_buffer_pointer_to_byte(struct drm_buffer *buffer,
+		int offset)
+{
+	int iter = buffer->iterator + offset;
+	return &buffer->data[iter / PAGE_SIZE][iter & (PAGE_SIZE - 1)];
+}
+
+#endif
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index fdf43ab..1347524 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -801,4 +801,6 @@
 				bool interlaced, int margins);
 extern int drm_add_modes_noedid(struct drm_connector *connector,
 				int hdisplay, int vdisplay);
+
+extern bool drm_edid_is_valid(struct edid *edid);
 #endif /* __DRM_CRTC_H__ */
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index d33c3e0..b420989 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -201,4 +201,7 @@
 
 #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8))
 
+/* define the number of Extension EDID block */
+#define DRM_MAX_EDID_EXT_NUM 4
+
 #endif /* __DRM_EDID_H__ */
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index e6f3b12..676104b 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -141,6 +141,41 @@
 	{0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x688A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6898, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6899, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x689c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x689d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x689e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68a0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68a8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68a9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68be, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68c8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68c9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68de, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68e0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68e1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68e5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68e8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68e9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68f1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68f8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68f9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x68fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x7100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x7101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x7102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@@ -558,4 +593,5 @@
 	{0x8086, 0x35e8, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
 	{0x8086, 0x0042, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
 	{0x8086, 0x0046, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
+	{0x8086, 0x0102, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
 	{0, 0, 0}
diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h
index f745948..a6a9f4a 100644
--- a/include/drm/nouveau_drm.h
+++ b/include/drm/nouveau_drm.h
@@ -25,13 +25,14 @@
 #ifndef __NOUVEAU_DRM_H__
 #define __NOUVEAU_DRM_H__
 
-#define NOUVEAU_DRM_HEADER_PATCHLEVEL 15
+#define NOUVEAU_DRM_HEADER_PATCHLEVEL 16
 
 struct drm_nouveau_channel_alloc {
 	uint32_t     fb_ctxdma_handle;
 	uint32_t     tt_ctxdma_handle;
 
 	int          channel;
+	uint32_t     pushbuf_domains;
 
 	/* Notifier memory */
 	uint32_t     notifier_handle;
@@ -109,68 +110,58 @@
 	uint32_t align;
 };
 
+#define NOUVEAU_GEM_MAX_BUFFERS 1024
+struct drm_nouveau_gem_pushbuf_bo_presumed {
+	uint32_t valid;
+	uint32_t domain;
+	uint64_t offset;
+};
+
 struct drm_nouveau_gem_pushbuf_bo {
 	uint64_t user_priv;
 	uint32_t handle;
 	uint32_t read_domains;
 	uint32_t write_domains;
 	uint32_t valid_domains;
-	uint32_t presumed_ok;
-	uint32_t presumed_domain;
-	uint64_t presumed_offset;
+	struct drm_nouveau_gem_pushbuf_bo_presumed presumed;
 };
 
 #define NOUVEAU_GEM_RELOC_LOW  (1 << 0)
 #define NOUVEAU_GEM_RELOC_HIGH (1 << 1)
 #define NOUVEAU_GEM_RELOC_OR   (1 << 2)
+#define NOUVEAU_GEM_MAX_RELOCS 1024
 struct drm_nouveau_gem_pushbuf_reloc {
+	uint32_t reloc_bo_index;
+	uint32_t reloc_bo_offset;
 	uint32_t bo_index;
-	uint32_t reloc_index;
 	uint32_t flags;
 	uint32_t data;
 	uint32_t vor;
 	uint32_t tor;
 };
 
-#define NOUVEAU_GEM_MAX_BUFFERS 1024
-#define NOUVEAU_GEM_MAX_RELOCS 1024
+#define NOUVEAU_GEM_MAX_PUSH 512
+struct drm_nouveau_gem_pushbuf_push {
+	uint32_t bo_index;
+	uint32_t pad;
+	uint64_t offset;
+	uint64_t length;
+};
 
 struct drm_nouveau_gem_pushbuf {
 	uint32_t channel;
-	uint32_t nr_dwords;
 	uint32_t nr_buffers;
-	uint32_t nr_relocs;
-	uint64_t dwords;
 	uint64_t buffers;
-	uint64_t relocs;
-};
-
-struct drm_nouveau_gem_pushbuf_call {
-	uint32_t channel;
-	uint32_t handle;
-	uint32_t offset;
-	uint32_t nr_buffers;
 	uint32_t nr_relocs;
-	uint32_t nr_dwords;
-	uint64_t buffers;
+	uint32_t nr_push;
 	uint64_t relocs;
+	uint64_t push;
 	uint32_t suffix0;
 	uint32_t suffix1;
-	/* below only accessed for CALL2 */
 	uint64_t vram_available;
 	uint64_t gart_available;
 };
 
-struct drm_nouveau_gem_pin {
-	uint32_t handle;
-	uint32_t domain;
-	uint64_t offset;
-};
-
-struct drm_nouveau_gem_unpin {
-	uint32_t handle;
-};
-
 #define NOUVEAU_GEM_CPU_PREP_NOWAIT                                  0x00000001
 #define NOUVEAU_GEM_CPU_PREP_NOBLOCK                                 0x00000002
 #define NOUVEAU_GEM_CPU_PREP_WRITE                                   0x00000004
@@ -183,14 +174,6 @@
 	uint32_t handle;
 };
 
-struct drm_nouveau_gem_tile {
-	uint32_t handle;
-	uint32_t offset;
-	uint32_t size;
-	uint32_t tile_mode;
-	uint32_t tile_flags;
-};
-
 enum nouveau_bus_type {
 	NV_AGP     = 0,
 	NV_PCI     = 1,
@@ -200,22 +183,17 @@
 struct drm_nouveau_sarea {
 };
 
-#define DRM_NOUVEAU_CARD_INIT          0x00
-#define DRM_NOUVEAU_GETPARAM           0x01
-#define DRM_NOUVEAU_SETPARAM           0x02
-#define DRM_NOUVEAU_CHANNEL_ALLOC      0x03
-#define DRM_NOUVEAU_CHANNEL_FREE       0x04
-#define DRM_NOUVEAU_GROBJ_ALLOC        0x05
-#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC  0x06
-#define DRM_NOUVEAU_GPUOBJ_FREE        0x07
+#define DRM_NOUVEAU_GETPARAM           0x00
+#define DRM_NOUVEAU_SETPARAM           0x01
+#define DRM_NOUVEAU_CHANNEL_ALLOC      0x02
+#define DRM_NOUVEAU_CHANNEL_FREE       0x03
+#define DRM_NOUVEAU_GROBJ_ALLOC        0x04
+#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC  0x05
+#define DRM_NOUVEAU_GPUOBJ_FREE        0x06
 #define DRM_NOUVEAU_GEM_NEW            0x40
 #define DRM_NOUVEAU_GEM_PUSHBUF        0x41
-#define DRM_NOUVEAU_GEM_PUSHBUF_CALL   0x42
-#define DRM_NOUVEAU_GEM_PIN            0x43 /* !KMS only */
-#define DRM_NOUVEAU_GEM_UNPIN          0x44 /* !KMS only */
-#define DRM_NOUVEAU_GEM_CPU_PREP       0x45
-#define DRM_NOUVEAU_GEM_CPU_FINI       0x46
-#define DRM_NOUVEAU_GEM_INFO           0x47
-#define DRM_NOUVEAU_GEM_PUSHBUF_CALL2  0x48
+#define DRM_NOUVEAU_GEM_CPU_PREP       0x42
+#define DRM_NOUVEAU_GEM_CPU_FINI       0x43
+#define DRM_NOUVEAU_GEM_INFO           0x44
 
 #endif /* __NOUVEAU_DRM_H__ */
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
index 39537f3..81e614b 100644
--- a/include/drm/radeon_drm.h
+++ b/include/drm/radeon_drm.h
@@ -808,6 +808,7 @@
 #define RADEON_TILING_SWAP_32BIT  0x8
 #define RADEON_TILING_SURFACE     0x10 /* this object requires a surface
 					* when mapped - i.e. front buffer */
+#define RADEON_TILING_MICRO_SQUARE 0x20
 
 struct drm_radeon_gem_set_tiling {
 	uint32_t	handle;
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 4c4e0f8..e3f1b4a 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -908,7 +908,7 @@
  * Utility function that returns the pgprot_t that should be used for
  * setting up a PTE with the caching model indicated by @c_state.
  */
-extern pgprot_t ttm_io_prot(enum ttm_caching_state c_state, pgprot_t tmp);
+extern pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp);
 
 #if (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
 #define TTM_HAS_AGP
diff --git a/include/linux/acct.h b/include/linux/acct.h
index 882dc72..3e4737f 100644
--- a/include/linux/acct.h
+++ b/include/linux/acct.h
@@ -121,16 +121,15 @@
 struct super_block;
 struct pacct_struct;
 struct pid_namespace;
+extern int acct_parm[]; /* for sysctl */
 extern void acct_auto_close_mnt(struct vfsmount *m);
 extern void acct_auto_close(struct super_block *sb);
-extern void acct_init_pacct(struct pacct_struct *pacct);
 extern void acct_collect(long exitcode, int group_dead);
 extern void acct_process(void);
 extern void acct_exit_ns(struct pid_namespace *);
 #else
 #define acct_auto_close_mnt(x)	do { } while (0)
 #define acct_auto_close(x)	do { } while (0)
-#define acct_init_pacct(x)	do { } while (0)
 #define acct_collect(x,y)	do { } while (0)
 #define acct_process()		do { } while (0)
 #define acct_exit_ns(ns)	do { } while (0)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 3c7a358..f391d45 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -424,7 +424,7 @@
 extern void __audit_getname(const char *name);
 extern void audit_putname(const char *name);
 extern void __audit_inode(const char *name, const struct dentry *dentry);
-extern void __audit_inode_child(const char *dname, const struct dentry *dentry,
+extern void __audit_inode_child(const struct dentry *dentry,
 				const struct inode *parent);
 extern void __audit_ptrace(struct task_struct *t);
 
@@ -442,11 +442,10 @@
 	if (unlikely(!audit_dummy_context()))
 		__audit_inode(name, dentry);
 }
-static inline void audit_inode_child(const char *dname, 
-				     const struct dentry *dentry,
+static inline void audit_inode_child(const struct dentry *dentry,
 				     const struct inode *parent) {
 	if (unlikely(!audit_dummy_context()))
-		__audit_inode_child(dname, dentry, parent);
+		__audit_inode_child(dentry, parent);
 }
 void audit_core_dumps(long signr);
 
@@ -544,9 +543,9 @@
 #define audit_getname(n) do { ; } while (0)
 #define audit_putname(n) do { ; } while (0)
 #define __audit_inode(n,d) do { ; } while (0)
-#define __audit_inode_child(d,i,p) do { ; } while (0)
+#define __audit_inode_child(i,p) do { ; } while (0)
 #define audit_inode(n,d) do { ; } while (0)
-#define audit_inode_child(d,i,p) do { ; } while (0)
+#define audit_inode_child(i,p) do { ; } while (0)
 #define audit_core_dumps(i) do { ; } while (0)
 #define auditsc_get_stamp(c,t,s) (0)
 #define audit_get_loginuid(t) (-1)
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 89c6249..c809e28 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -74,6 +74,7 @@
 	struct pt_regs *regs;
 	struct file *file;
 	unsigned long limit;
+	unsigned long mm_flags;
 };
 
 /*
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 25b8b2f..b793898 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -16,11 +16,13 @@
  */
 #include <asm/bitops.h>
 
-#define for_each_bit(bit, addr, size) \
+#define for_each_set_bit(bit, addr, size) \
 	for ((bit) = find_first_bit((addr), (size)); \
 	     (bit) < (size); \
 	     (bit) = find_next_bit((addr), (size), (bit) + 1))
 
+/* Temporary */
+#define for_each_bit(bit, addr, size) for_each_set_bit(bit, addr, size)
 
 static __inline__ int get_bitmask_order(unsigned int count)
 {
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index 3b73b99..416bf62 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -150,8 +150,8 @@
 struct blk_trace {
 	int trace_state;
 	struct rchan *rchan;
-	unsigned long *sequence;
-	unsigned char *msg_data;
+	unsigned long __percpu *sequence;
+	unsigned char __percpu *msg_data;
 	u16 act_mask;
 	u64 start_lba;
 	u64 end_lba;
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index b10ec49..266ab92 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -23,6 +23,7 @@
 extern unsigned long saved_max_pfn;
 #endif
 
+#ifndef CONFIG_NO_BOOTMEM
 /*
  * node_bootmem_map is a map pointer - the bits represent all physical 
  * memory pages (including holes) on the node.
@@ -37,6 +38,7 @@
 } bootmem_data_t;
 
 extern bootmem_data_t bootmem_node_data[];
+#endif
 
 extern unsigned long bootmem_bootmap_pages(unsigned long);
 
@@ -46,6 +48,7 @@
 				       unsigned long endpfn);
 extern unsigned long init_bootmem(unsigned long addr, unsigned long memend);
 
+unsigned long free_all_memory_core_early(int nodeid);
 extern unsigned long free_all_bootmem_node(pg_data_t *pgdat);
 extern unsigned long free_all_bootmem(void);
 
@@ -84,6 +87,10 @@
 				  unsigned long size,
 				  unsigned long align,
 				  unsigned long goal);
+void *__alloc_bootmem_node_high(pg_data_t *pgdat,
+				  unsigned long size,
+				  unsigned long align,
+				  unsigned long goal);
 extern void *__alloc_bootmem_node_nopanic(pg_data_t *pgdat,
 				  unsigned long size,
 				  unsigned long align,
diff --git a/include/linux/btree-128.h b/include/linux/btree-128.h
new file mode 100644
index 0000000..0b3414c
--- /dev/null
+++ b/include/linux/btree-128.h
@@ -0,0 +1,109 @@
+extern struct btree_geo btree_geo128;
+
+struct btree_head128 { struct btree_head h; };
+
+static inline void btree_init_mempool128(struct btree_head128 *head,
+					 mempool_t *mempool)
+{
+	btree_init_mempool(&head->h, mempool);
+}
+
+static inline int btree_init128(struct btree_head128 *head)
+{
+	return btree_init(&head->h);
+}
+
+static inline void btree_destroy128(struct btree_head128 *head)
+{
+	btree_destroy(&head->h);
+}
+
+static inline void *btree_lookup128(struct btree_head128 *head, u64 k1, u64 k2)
+{
+	u64 key[2] = {k1, k2};
+	return btree_lookup(&head->h, &btree_geo128, (unsigned long *)&key);
+}
+
+static inline void *btree_get_prev128(struct btree_head128 *head,
+				      u64 *k1, u64 *k2)
+{
+	u64 key[2] = {*k1, *k2};
+	void *val;
+
+	val = btree_get_prev(&head->h, &btree_geo128,
+			     (unsigned long *)&key);
+	*k1 = key[0];
+	*k2 = key[1];
+	return val;
+}
+
+static inline int btree_insert128(struct btree_head128 *head, u64 k1, u64 k2,
+				  void *val, gfp_t gfp)
+{
+	u64 key[2] = {k1, k2};
+	return btree_insert(&head->h, &btree_geo128,
+			    (unsigned long *)&key, val, gfp);
+}
+
+static inline int btree_update128(struct btree_head128 *head, u64 k1, u64 k2,
+				  void *val)
+{
+	u64 key[2] = {k1, k2};
+	return btree_update(&head->h, &btree_geo128,
+			    (unsigned long *)&key, val);
+}
+
+static inline void *btree_remove128(struct btree_head128 *head, u64 k1, u64 k2)
+{
+	u64 key[2] = {k1, k2};
+	return btree_remove(&head->h, &btree_geo128, (unsigned long *)&key);
+}
+
+static inline void *btree_last128(struct btree_head128 *head, u64 *k1, u64 *k2)
+{
+	u64 key[2];
+	void *val;
+
+	val = btree_last(&head->h, &btree_geo128, (unsigned long *)&key[0]);
+	if (val) {
+		*k1 = key[0];
+		*k2 = key[1];
+	}
+
+	return val;
+}
+
+static inline int btree_merge128(struct btree_head128 *target,
+				 struct btree_head128 *victim,
+				 gfp_t gfp)
+{
+	return btree_merge(&target->h, &victim->h, &btree_geo128, gfp);
+}
+
+void visitor128(void *elem, unsigned long opaque, unsigned long *__key,
+		size_t index, void *__func);
+
+typedef void (*visitor128_t)(void *elem, unsigned long opaque,
+			     u64 key1, u64 key2, size_t index);
+
+static inline size_t btree_visitor128(struct btree_head128 *head,
+				      unsigned long opaque,
+				      visitor128_t func2)
+{
+	return btree_visitor(&head->h, &btree_geo128, opaque,
+			     visitor128, func2);
+}
+
+static inline size_t btree_grim_visitor128(struct btree_head128 *head,
+					   unsigned long opaque,
+					   visitor128_t func2)
+{
+	return btree_grim_visitor(&head->h, &btree_geo128, opaque,
+				  visitor128, func2);
+}
+
+#define btree_for_each_safe128(head, k1, k2, val)	\
+	for (val = btree_last128(head, &k1, &k2);	\
+	     val;					\
+	     val = btree_get_prev128(head, &k1, &k2))
+
diff --git a/include/linux/btree-type.h b/include/linux/btree-type.h
new file mode 100644
index 0000000..9a1147e
--- /dev/null
+++ b/include/linux/btree-type.h
@@ -0,0 +1,147 @@
+#define __BTREE_TP(pfx, type, sfx)	pfx ## type ## sfx
+#define _BTREE_TP(pfx, type, sfx)	__BTREE_TP(pfx, type, sfx)
+#define BTREE_TP(pfx)			_BTREE_TP(pfx, BTREE_TYPE_SUFFIX,)
+#define BTREE_FN(name)			BTREE_TP(btree_ ## name)
+#define BTREE_TYPE_HEAD			BTREE_TP(struct btree_head)
+#define VISITOR_FN			BTREE_TP(visitor)
+#define VISITOR_FN_T			_BTREE_TP(visitor, BTREE_TYPE_SUFFIX, _t)
+
+BTREE_TYPE_HEAD {
+	struct btree_head h;
+};
+
+static inline void BTREE_FN(init_mempool)(BTREE_TYPE_HEAD *head,
+					  mempool_t *mempool)
+{
+	btree_init_mempool(&head->h, mempool);
+}
+
+static inline int BTREE_FN(init)(BTREE_TYPE_HEAD *head)
+{
+	return btree_init(&head->h);
+}
+
+static inline void BTREE_FN(destroy)(BTREE_TYPE_HEAD *head)
+{
+	btree_destroy(&head->h);
+}
+
+static inline int BTREE_FN(merge)(BTREE_TYPE_HEAD *target,
+				  BTREE_TYPE_HEAD *victim,
+				  gfp_t gfp)
+{
+	return btree_merge(&target->h, &victim->h, BTREE_TYPE_GEO, gfp);
+}
+
+#if (BITS_PER_LONG > BTREE_TYPE_BITS)
+static inline void *BTREE_FN(lookup)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key)
+{
+	unsigned long _key = key;
+	return btree_lookup(&head->h, BTREE_TYPE_GEO, &_key);
+}
+
+static inline int BTREE_FN(insert)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key,
+				   void *val, gfp_t gfp)
+{
+	unsigned long _key = key;
+	return btree_insert(&head->h, BTREE_TYPE_GEO, &_key, val, gfp);
+}
+
+static inline int BTREE_FN(update)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key,
+		void *val)
+{
+	unsigned long _key = key;
+	return btree_update(&head->h, BTREE_TYPE_GEO, &_key, val);
+}
+
+static inline void *BTREE_FN(remove)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key)
+{
+	unsigned long _key = key;
+	return btree_remove(&head->h, BTREE_TYPE_GEO, &_key);
+}
+
+static inline void *BTREE_FN(last)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE *key)
+{
+	unsigned long _key;
+	void *val = btree_last(&head->h, BTREE_TYPE_GEO, &_key);
+	if (val)
+		*key = _key;
+	return val;
+}
+
+static inline void *BTREE_FN(get_prev)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE *key)
+{
+	unsigned long _key = *key;
+	void *val = btree_get_prev(&head->h, BTREE_TYPE_GEO, &_key);
+	if (val)
+		*key = _key;
+	return val;
+}
+#else
+static inline void *BTREE_FN(lookup)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key)
+{
+	return btree_lookup(&head->h, BTREE_TYPE_GEO, (unsigned long *)&key);
+}
+
+static inline int BTREE_FN(insert)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key,
+			   void *val, gfp_t gfp)
+{
+	return btree_insert(&head->h, BTREE_TYPE_GEO, (unsigned long *)&key,
+			    val, gfp);
+}
+
+static inline int BTREE_FN(update)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key,
+		void *val)
+{
+	return btree_update(&head->h, BTREE_TYPE_GEO, (unsigned long *)&key, val);
+}
+
+static inline void *BTREE_FN(remove)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key)
+{
+	return btree_remove(&head->h, BTREE_TYPE_GEO, (unsigned long *)&key);
+}
+
+static inline void *BTREE_FN(last)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE *key)
+{
+	return btree_last(&head->h, BTREE_TYPE_GEO, (unsigned long *)key);
+}
+
+static inline void *BTREE_FN(get_prev)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE *key)
+{
+	return btree_get_prev(&head->h, BTREE_TYPE_GEO, (unsigned long *)key);
+}
+#endif
+
+void VISITOR_FN(void *elem, unsigned long opaque, unsigned long *key,
+		size_t index, void *__func);
+
+typedef void (*VISITOR_FN_T)(void *elem, unsigned long opaque,
+			     BTREE_KEYTYPE key, size_t index);
+
+static inline size_t BTREE_FN(visitor)(BTREE_TYPE_HEAD *head,
+				       unsigned long opaque,
+				       VISITOR_FN_T func2)
+{
+	return btree_visitor(&head->h, BTREE_TYPE_GEO, opaque,
+			     visitorl, func2);
+}
+
+static inline size_t BTREE_FN(grim_visitor)(BTREE_TYPE_HEAD *head,
+					    unsigned long opaque,
+					    VISITOR_FN_T func2)
+{
+	return btree_grim_visitor(&head->h, BTREE_TYPE_GEO, opaque,
+				  visitorl, func2);
+}
+
+#undef VISITOR_FN
+#undef VISITOR_FN_T
+#undef __BTREE_TP
+#undef _BTREE_TP
+#undef BTREE_TP
+#undef BTREE_FN
+#undef BTREE_TYPE_HEAD
+#undef BTREE_TYPE_SUFFIX
+#undef BTREE_TYPE_GEO
+#undef BTREE_KEYTYPE
+#undef BTREE_TYPE_BITS
diff --git a/include/linux/btree.h b/include/linux/btree.h
new file mode 100644
index 0000000..65b5bb0
--- /dev/null
+++ b/include/linux/btree.h
@@ -0,0 +1,243 @@
+#ifndef BTREE_H
+#define BTREE_H
+
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+
+/**
+ * DOC: B+Tree basics
+ *
+ * A B+Tree is a data structure for looking up arbitrary (currently allowing
+ * unsigned long, u32, u64 and 2 * u64) keys into pointers. The data structure
+ * is described at http://en.wikipedia.org/wiki/B-tree, we currently do not
+ * use binary search to find the key on lookups.
+ *
+ * Each B+Tree consists of a head, that contains bookkeeping information and
+ * a variable number (starting with zero) nodes. Each node contains the keys
+ * and pointers to sub-nodes, or, for leaf nodes, the keys and values for the
+ * tree entries.
+ *
+ * Each node in this implementation has the following layout:
+ * [key1, key2, ..., keyN] [val1, val2, ..., valN]
+ *
+ * Each key here is an array of unsigned longs, geo->no_longs in total. The
+ * number of keys and values (N) is geo->no_pairs.
+ */
+
+/**
+ * struct btree_head - btree head
+ *
+ * @node: the first node in the tree
+ * @mempool: mempool used for node allocations
+ * @height: current of the tree
+ */
+struct btree_head {
+	unsigned long *node;
+	mempool_t *mempool;
+	int height;
+};
+
+/* btree geometry */
+struct btree_geo;
+
+/**
+ * btree_alloc - allocate function for the mempool
+ * @gfp_mask: gfp mask for the allocation
+ * @pool_data: unused
+ */
+void *btree_alloc(gfp_t gfp_mask, void *pool_data);
+
+/**
+ * btree_free - free function for the mempool
+ * @element: the element to free
+ * @pool_data: unused
+ */
+void btree_free(void *element, void *pool_data);
+
+/**
+ * btree_init_mempool - initialise a btree with given mempool
+ *
+ * @head: the btree head to initialise
+ * @mempool: the mempool to use
+ *
+ * When this function is used, there is no need to destroy
+ * the mempool.
+ */
+void btree_init_mempool(struct btree_head *head, mempool_t *mempool);
+
+/**
+ * btree_init - initialise a btree
+ *
+ * @head: the btree head to initialise
+ *
+ * This function allocates the memory pool that the
+ * btree needs. Returns zero or a negative error code
+ * (-%ENOMEM) when memory allocation fails.
+ *
+ */
+int __must_check btree_init(struct btree_head *head);
+
+/**
+ * btree_destroy - destroy mempool
+ *
+ * @head: the btree head to destroy
+ *
+ * This function destroys the internal memory pool, use only
+ * when using btree_init(), not with btree_init_mempool().
+ */
+void btree_destroy(struct btree_head *head);
+
+/**
+ * btree_lookup - look up a key in the btree
+ *
+ * @head: the btree to look in
+ * @geo: the btree geometry
+ * @key: the key to look up
+ *
+ * This function returns the value for the given key, or %NULL.
+ */
+void *btree_lookup(struct btree_head *head, struct btree_geo *geo,
+		   unsigned long *key);
+
+/**
+ * btree_insert - insert an entry into the btree
+ *
+ * @head: the btree to add to
+ * @geo: the btree geometry
+ * @key: the key to add (must not already be present)
+ * @val: the value to add (must not be %NULL)
+ * @gfp: allocation flags for node allocations
+ *
+ * This function returns 0 if the item could be added, or an
+ * error code if it failed (may fail due to memory pressure).
+ */
+int __must_check btree_insert(struct btree_head *head, struct btree_geo *geo,
+			      unsigned long *key, void *val, gfp_t gfp);
+/**
+ * btree_update - update an entry in the btree
+ *
+ * @head: the btree to update
+ * @geo: the btree geometry
+ * @key: the key to update
+ * @val: the value to change it to (must not be %NULL)
+ *
+ * This function returns 0 if the update was successful, or
+ * -%ENOENT if the key could not be found.
+ */
+int btree_update(struct btree_head *head, struct btree_geo *geo,
+		 unsigned long *key, void *val);
+/**
+ * btree_remove - remove an entry from the btree
+ *
+ * @head: the btree to update
+ * @geo: the btree geometry
+ * @key: the key to remove
+ *
+ * This function returns the removed entry, or %NULL if the key
+ * could not be found.
+ */
+void *btree_remove(struct btree_head *head, struct btree_geo *geo,
+		   unsigned long *key);
+
+/**
+ * btree_merge - merge two btrees
+ *
+ * @target: the tree that gets all the entries
+ * @victim: the tree that gets merged into @target
+ * @geo: the btree geometry
+ * @gfp: allocation flags
+ *
+ * The two trees @target and @victim may not contain the same keys,
+ * that is a bug and triggers a BUG(). This function returns zero
+ * if the trees were merged successfully, and may return a failure
+ * when memory allocation fails, in which case both trees might have
+ * been partially merged, i.e. some entries have been moved from
+ * @victim to @target.
+ */
+int btree_merge(struct btree_head *target, struct btree_head *victim,
+		struct btree_geo *geo, gfp_t gfp);
+
+/**
+ * btree_last - get last entry in btree
+ *
+ * @head: btree head
+ * @geo: btree geometry
+ * @key: last key
+ *
+ * Returns the last entry in the btree, and sets @key to the key
+ * of that entry; returns NULL if the tree is empty, in that case
+ * key is not changed.
+ */
+void *btree_last(struct btree_head *head, struct btree_geo *geo,
+		 unsigned long *key);
+
+/**
+ * btree_get_prev - get previous entry
+ *
+ * @head: btree head
+ * @geo: btree geometry
+ * @key: pointer to key
+ *
+ * The function returns the next item right before the value pointed to by
+ * @key, and updates @key with its key, or returns %NULL when there is no
+ * entry with a key smaller than the given key.
+ */
+void *btree_get_prev(struct btree_head *head, struct btree_geo *geo,
+		     unsigned long *key);
+
+
+/* internal use, use btree_visitor{l,32,64,128} */
+size_t btree_visitor(struct btree_head *head, struct btree_geo *geo,
+		     unsigned long opaque,
+		     void (*func)(void *elem, unsigned long opaque,
+				  unsigned long *key, size_t index,
+				  void *func2),
+		     void *func2);
+
+/* internal use, use btree_grim_visitor{l,32,64,128} */
+size_t btree_grim_visitor(struct btree_head *head, struct btree_geo *geo,
+			  unsigned long opaque,
+			  void (*func)(void *elem, unsigned long opaque,
+				       unsigned long *key,
+				       size_t index, void *func2),
+			  void *func2);
+
+
+#include <linux/btree-128.h>
+
+extern struct btree_geo btree_geo32;
+#define BTREE_TYPE_SUFFIX l
+#define BTREE_TYPE_BITS BITS_PER_LONG
+#define BTREE_TYPE_GEO &btree_geo32
+#define BTREE_KEYTYPE unsigned long
+#include <linux/btree-type.h>
+
+#define btree_for_each_safel(head, key, val)	\
+	for (val = btree_lastl(head, &key);	\
+	     val;				\
+	     val = btree_get_prevl(head, &key))
+
+#define BTREE_TYPE_SUFFIX 32
+#define BTREE_TYPE_BITS 32
+#define BTREE_TYPE_GEO &btree_geo32
+#define BTREE_KEYTYPE u32
+#include <linux/btree-type.h>
+
+#define btree_for_each_safe32(head, key, val)	\
+	for (val = btree_last32(head, &key);	\
+	     val;				\
+	     val = btree_get_prev32(head, &key))
+
+extern struct btree_geo btree_geo64;
+#define BTREE_TYPE_SUFFIX 64
+#define BTREE_TYPE_BITS 64
+#define BTREE_TYPE_GEO &btree_geo64
+#define BTREE_KEYTYPE u64
+#include <linux/btree-type.h>
+
+#define btree_for_each_safe64(head, key, val)	\
+	for (val = btree_last64(head, &key);	\
+	     val;				\
+	     val = btree_get_prev64(head, &key))
+
+#endif
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index c9bbcb2..b8ad1ea9 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -37,16 +37,24 @@
 extern void cgroup_exit(struct task_struct *p, int run_callbacks);
 extern int cgroupstats_build(struct cgroupstats *stats,
 				struct dentry *dentry);
+extern int cgroup_load_subsys(struct cgroup_subsys *ss);
+extern void cgroup_unload_subsys(struct cgroup_subsys *ss);
 
 extern const struct file_operations proc_cgroup_operations;
 
-/* Define the enumeration of all cgroup subsystems */
+/* Define the enumeration of all builtin cgroup subsystems */
 #define SUBSYS(_x) _x ## _subsys_id,
 enum cgroup_subsys_id {
 #include <linux/cgroup_subsys.h>
-	CGROUP_SUBSYS_COUNT
+	CGROUP_BUILTIN_SUBSYS_COUNT
 };
 #undef SUBSYS
+/*
+ * This define indicates the maximum number of subsystems that can be loaded
+ * at once. We limit to this many since cgroupfs_root has subsys_bits to keep
+ * track of all of them.
+ */
+#define CGROUP_SUBSYS_COUNT (BITS_PER_BYTE*sizeof(unsigned long))
 
 /* Per-subsystem/per-cgroup state maintained by the system. */
 struct cgroup_subsys_state {
@@ -76,6 +84,12 @@
 	CSS_REMOVED, /* This CSS is dead */
 };
 
+/* Caller must verify that the css is not for root cgroup */
+static inline void __css_get(struct cgroup_subsys_state *css, int count)
+{
+	atomic_add(count, &css->refcnt);
+}
+
 /*
  * Call css_get() to hold a reference on the css; it can be used
  * for a reference obtained via:
@@ -87,7 +101,7 @@
 {
 	/* We don't need to reference count the root state */
 	if (!test_bit(CSS_ROOT, &css->flags))
-		atomic_inc(&css->refcnt);
+		__css_get(css, 1);
 }
 
 static inline bool css_is_removed(struct cgroup_subsys_state *css)
@@ -118,11 +132,11 @@
  * css_get() or css_tryget()
  */
 
-extern void __css_put(struct cgroup_subsys_state *css);
+extern void __css_put(struct cgroup_subsys_state *css, int count);
 static inline void css_put(struct cgroup_subsys_state *css)
 {
 	if (!test_bit(CSS_ROOT, &css->flags))
-		__css_put(css);
+		__css_put(css, 1);
 }
 
 /* bits in struct cgroup flags field */
@@ -221,6 +235,10 @@
 
 	/* For RCU-protected deletion */
 	struct rcu_head rcu_head;
+
+	/* List of events which userspace want to recieve */
+	struct list_head event_list;
+	spinlock_t event_list_lock;
 };
 
 /*
@@ -258,7 +276,8 @@
 	/*
 	 * Set of subsystem states, one for each subsystem. This array
 	 * is immutable after creation apart from the init_css_set
-	 * during subsystem registration (at boot time).
+	 * during subsystem registration (at boot time) and modular subsystem
+	 * loading/unloading.
 	 */
 	struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
 
@@ -363,6 +382,23 @@
 	int (*trigger)(struct cgroup *cgrp, unsigned int event);
 
 	int (*release)(struct inode *inode, struct file *file);
+
+	/*
+	 * register_event() callback will be used to add new userspace
+	 * waiter for changes related to the cftype. Implement it if
+	 * you want to provide this functionality. Use eventfd_signal()
+	 * on eventfd to send notification to userspace.
+	 */
+	int (*register_event)(struct cgroup *cgrp, struct cftype *cft,
+			struct eventfd_ctx *eventfd, const char *args);
+	/*
+	 * unregister_event() callback will be called when userspace
+	 * closes the eventfd or on cgroup removing.
+	 * This callback must be implemented, if you want provide
+	 * notification functionality.
+	 */
+	int (*unregister_event)(struct cgroup *cgrp, struct cftype *cft,
+			struct eventfd_ctx *eventfd);
 };
 
 struct cgroup_scanner {
@@ -428,6 +464,8 @@
 	void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
 	int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
 			  struct task_struct *tsk, bool threadgroup);
+	void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
+			  struct task_struct *tsk, bool threadgroup);
 	void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
 			struct cgroup *old_cgrp, struct task_struct *tsk,
 			bool threadgroup);
@@ -472,6 +510,9 @@
 	/* used when use_id == true */
 	struct idr idr;
 	spinlock_t id_lock;
+
+	/* should be defined only by modular subsystems */
+	struct module *module;
 };
 
 #define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys;
diff --git a/include/linux/compat.h b/include/linux/compat.h
index ef68119..717c691 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -23,6 +23,7 @@
 typedef __compat_uid32_t	compat_uid_t;
 typedef __compat_gid32_t	compat_gid_t;
 
+struct compat_sel_arg_struct;
 struct rusage;
 
 struct compat_itimerspec { 
@@ -249,6 +250,8 @@
 		compat_ulong_t __user *outp, compat_ulong_t __user *exp,
 		struct compat_timeval __user *tvp);
 
+asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg);
+
 asmlinkage long compat_sys_wait4(compat_pid_t pid,
 				 compat_uint_t __user *stat_addr, int options,
 				 struct compat_rusage __user *ru);
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 188fcae..a5a472b 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -5,7 +5,7 @@
 
 #ifdef __CHECKER__
 # define __user		__attribute__((noderef, address_space(1)))
-# define __kernel	/* default address space */
+# define __kernel	__attribute__((address_space(0)))
 # define __safe		__attribute__((safe))
 # define __force	__attribute__((force))
 # define __nocast	__attribute__((nocast))
diff --git a/include/linux/coredump.h b/include/linux/coredump.h
new file mode 100644
index 0000000..8ba66a9
--- /dev/null
+++ b/include/linux/coredump.h
@@ -0,0 +1,45 @@
+#ifndef _LINUX_COREDUMP_H
+#define _LINUX_COREDUMP_H
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+
+/*
+ * These are the only things you should do on a core-file: use only these
+ * functions to write out all the necessary info.
+ */
+static inline int dump_write(struct file *file, const void *addr, int nr)
+{
+	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+}
+
+static inline int dump_seek(struct file *file, loff_t off)
+{
+	int ret = 1;
+
+	if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+		if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
+			return 0;
+	} else {
+		char *buf = (char *)get_zeroed_page(GFP_KERNEL);
+
+		if (!buf)
+			return 0;
+		while (off > 0) {
+			unsigned long n = off;
+
+			if (n > PAGE_SIZE)
+				n = PAGE_SIZE;
+			if (!dump_write(file, buf, n)) {
+				ret = 0;
+				break;
+			}
+			off -= n;
+		}
+		free_page((unsigned long)buf);
+	}
+	return ret;
+}
+
+#endif /* _LINUX_COREDUMP_H */
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index dbcee76..bae6fe2 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -90,10 +90,10 @@
 #define cpu_present(cpu)	cpumask_test_cpu((cpu), cpu_present_mask)
 #define cpu_active(cpu)		cpumask_test_cpu((cpu), cpu_active_mask)
 #else
-#define num_online_cpus()	1
-#define num_possible_cpus()	1
-#define num_present_cpus()	1
-#define num_active_cpus()	1
+#define num_online_cpus()	1U
+#define num_possible_cpus()	1U
+#define num_present_cpus()	1U
+#define num_active_cpus()	1U
 #define cpu_online(cpu)		((cpu) == 0)
 #define cpu_possible(cpu)	((cpu) == 0)
 #define cpu_present(cpu)	((cpu) == 0)
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 4db09f8..52507c3 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -280,7 +280,7 @@
  * task or by holding tasklist_lock to prevent it from being unlinked.
  */
 #define __task_cred(task) \
-	((const struct cred *)(rcu_dereference_check((task)->real_cred, rcu_read_lock_held() || lockdep_is_held(&tasklist_lock))))
+	((const struct cred *)(rcu_dereference_check((task)->real_cred, rcu_read_lock_held() || lockdep_tasklist_lock_is_held())))
 
 /**
  * get_task_cred - Get another task's objective credentials
diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h
index 5032b9a..ad5ec1d 100644
--- a/include/linux/decompress/mm.h
+++ b/include/linux/decompress/mm.h
@@ -14,11 +14,21 @@
 
 /* Code active when included from pre-boot environment: */
 
+/*
+ * Some architectures want to ensure there is no local data in their
+ * pre-boot environment, so that data can arbitarily relocated (via
+ * GOT references).  This is achieved by defining STATIC_RW_DATA to
+ * be null.
+ */
+#ifndef STATIC_RW_DATA
+#define STATIC_RW_DATA static
+#endif
+
 /* A trivial malloc implementation, adapted from
  *  malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
  */
-static unsigned long malloc_ptr;
-static int malloc_count;
+STATIC_RW_DATA unsigned long malloc_ptr;
+STATIC_RW_DATA int malloc_count;
 
 static void *malloc(int size)
 {
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index d4c9c0b..1381cd9 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -118,10 +118,9 @@
 /*
  * Constructors should call these functions to ensure destination devices
  * are opened/closed correctly.
- * FIXME: too many arguments.
  */
-int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
-		  sector_t len, fmode_t mode, struct dm_dev **result);
+int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
+						 struct dm_dev **result);
 void dm_put_device(struct dm_target *ti, struct dm_dev *d);
 
 /*
diff --git a/include/linux/device.h b/include/linux/device.h
index b30527d..1821928 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -106,7 +106,7 @@
 
 /* All 4 notifers below get called with the target struct device *
  * as an argument. Note that those functions are likely to be called
- * with the device semaphore held in the core, so be careful.
+ * with the device lock held in the core, so be careful.
  */
 #define BUS_NOTIFY_ADD_DEVICE		0x00000001 /* device added */
 #define BUS_NOTIFY_DEL_DEVICE		0x00000002 /* device removed */
@@ -251,8 +251,10 @@
 
 struct class_attribute {
 	struct attribute attr;
-	ssize_t (*show)(struct class *class, char *buf);
-	ssize_t (*store)(struct class *class, const char *buf, size_t count);
+	ssize_t (*show)(struct class *class, struct class_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct class *class, struct class_attribute *attr,
+			const char *buf, size_t count);
 };
 
 #define CLASS_ATTR(_name, _mode, _show, _store)			\
@@ -263,6 +265,23 @@
 extern void class_remove_file(struct class *class,
 			      const struct class_attribute *attr);
 
+/* Simple class attribute that is just a static string */
+
+struct class_attribute_string {
+	struct class_attribute attr;
+	char *str;
+};
+
+/* Currently read-only only */
+#define _CLASS_ATTR_STRING(_name, _mode, _str) \
+	{ __ATTR(_name, _mode, show_class_attr_string, NULL), _str }
+#define CLASS_ATTR_STRING(_name, _mode, _str) \
+	struct class_attribute_string class_attr_##_name = \
+		_CLASS_ATTR_STRING(_name, _mode, _str)
+
+extern ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr,
+                        char *buf);
+
 struct class_interface {
 	struct list_head	node;
 	struct class		*class;
@@ -489,6 +508,21 @@
 	return !!dev->power.async_suspend;
 }
 
+static inline void device_lock(struct device *dev)
+{
+	down(&dev->sem);
+}
+
+static inline int device_trylock(struct device *dev)
+{
+	return down_trylock(&dev->sem);
+}
+
+static inline void device_unlock(struct device *dev)
+{
+	up(&dev->sem);
+}
+
 void driver_init(void);
 
 /*
diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h
index b6bf17e..5c9186b 100644
--- a/include/linux/dm-io.h
+++ b/include/linux/dm-io.h
@@ -37,14 +37,14 @@
 struct dm_io_memory {
 	enum dm_io_mem_type type;
 
+	unsigned offset;
+
 	union {
 		struct page_list *pl;
 		struct bio_vec *bvec;
 		void *vma;
 		void *addr;
 	} ptr;
-
-	unsigned offset;
 };
 
 struct dm_io_notify {
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index aa95508..2c445e1 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -266,9 +266,9 @@
 #define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR	4
-#define DM_VERSION_MINOR	16
+#define DM_VERSION_MINOR	17
 #define DM_VERSION_PATCHLEVEL	0
-#define DM_VERSION_EXTRA	"-ioctl (2009-11-05)"
+#define DM_VERSION_EXTRA	"-ioctl (2010-03-05)"
 
 /* Status bits */
 #define DM_READONLY_FLAG	(1 << 0) /* In/Out */
@@ -316,4 +316,9 @@
  */
 #define DM_QUERY_INACTIVE_TABLE_FLAG	(1 << 12) /* In */
 
+/*
+ * If set, a uevent was generated for which the caller may need to wait.
+ */
+#define DM_UEVENT_GENERATED_FLAG	(1 << 13) /* Out */
+
 #endif				/* _LINUX_DM_IOCTL_H */
diff --git a/include/linux/dm9000.h b/include/linux/dm9000.h
index c30879c..96e8769 100644
--- a/include/linux/dm9000.h
+++ b/include/linux/dm9000.h
@@ -23,7 +23,7 @@
 #define DM9000_PLATF_NO_EEPROM	(0x0010)
 #define DM9000_PLATF_SIMPLE_PHY (0x0020)  /* Use NSR to find LinkStatus */
 
-/* platfrom data for platfrom device structure's platfrom_data field */
+/* platform data for platform device structure's platform_data field */
 
 struct dm9000_plat_data {
 	unsigned int	flags;
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 91b7618..ca32ed7 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -127,6 +127,14 @@
 	return DMA_BIT_MASK(32);
 }
 
+static inline int dma_set_coherent_mask(struct device *dev, u64 mask)
+{
+	if (!dma_supported(dev, mask))
+		return -EIO;
+	dev->coherent_dma_mask = mask;
+	return 0;
+}
+
 extern u64 dma_get_required_mask(struct device *dev);
 
 static inline unsigned int dma_get_max_seg_size(struct device *dev)
@@ -232,4 +240,20 @@
 
 #endif /* CONFIG_HAVE_DMA_ATTRS */
 
+#ifdef CONFIG_NEED_DMA_MAP_STATE
+#define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME)        dma_addr_t ADDR_NAME
+#define DEFINE_DMA_UNMAP_LEN(LEN_NAME)          __u32 LEN_NAME
+#define dma_unmap_addr(PTR, ADDR_NAME)           ((PTR)->ADDR_NAME)
+#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL)  (((PTR)->ADDR_NAME) = (VAL))
+#define dma_unmap_len(PTR, LEN_NAME)             ((PTR)->LEN_NAME)
+#define dma_unmap_len_set(PTR, LEN_NAME, VAL)    (((PTR)->LEN_NAME) = (VAL))
+#else
+#define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME)
+#define DEFINE_DMA_UNMAP_LEN(LEN_NAME)
+#define dma_unmap_addr(PTR, ADDR_NAME)           (0)
+#define dma_unmap_addr_set(PTR, ADDR_NAME, VAL)  do { } while (0)
+#define dma_unmap_len(PTR, LEN_NAME)             (0)
+#define dma_unmap_len_set(PTR, LEN_NAME, VAL)    do { } while (0)
+#endif
+
 #endif
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 7878498..20ea12c 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -31,6 +31,8 @@
  * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code
  */
 typedef s32 dma_cookie_t;
+#define DMA_MIN_COOKIE	1
+#define DMA_MAX_COOKIE	INT_MAX
 
 #define dma_submit_error(cookie) ((cookie) < 0 ? 1 : 0)
 
@@ -162,7 +164,7 @@
 	struct dma_chan_dev *dev;
 
 	struct list_head device_node;
-	struct dma_chan_percpu *local;
+	struct dma_chan_percpu __percpu *local;
 	int client_count;
 	int table_count;
 	void *private;
diff --git a/include/linux/early_res.h b/include/linux/early_res.h
new file mode 100644
index 0000000..29c09f5
--- /dev/null
+++ b/include/linux/early_res.h
@@ -0,0 +1,23 @@
+#ifndef _LINUX_EARLY_RES_H
+#define _LINUX_EARLY_RES_H
+#ifdef __KERNEL__
+
+extern void reserve_early(u64 start, u64 end, char *name);
+extern void reserve_early_overlap_ok(u64 start, u64 end, char *name);
+extern void free_early(u64 start, u64 end);
+void free_early_partial(u64 start, u64 end);
+extern void early_res_to_bootmem(u64 start, u64 end);
+
+void reserve_early_without_check(u64 start, u64 end, char *name);
+u64 find_early_area(u64 ei_start, u64 ei_last, u64 start, u64 end,
+			 u64 size, u64 align);
+u64 find_early_area_size(u64 ei_start, u64 ei_last, u64 start,
+			 u64 *sizep, u64 align);
+u64 find_fw_memmap_area(u64 start, u64 end, u64 size, u64 align);
+u64 get_max_mapped(void);
+#include <linux/range.h>
+int get_free_all_memory_range(struct range **rangep, int nodeid);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_EARLY_RES_H */
diff --git a/include/linux/elf.h b/include/linux/elf.h
index ad990c5..5978584 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -50,6 +50,28 @@
 
 #define PT_GNU_STACK	(PT_LOOS + 0x474e551)
 
+/*
+ * Extended Numbering
+ *
+ * If the real number of program header table entries is larger than
+ * or equal to PN_XNUM(0xffff), it is set to sh_info field of the
+ * section header at index 0, and PN_XNUM is set to e_phnum
+ * field. Otherwise, the section header at index 0 is zero
+ * initialized, if it exists.
+ *
+ * Specifications are available in:
+ *
+ * - Sun microsystems: Linker and Libraries.
+ *   Part No: 817-1984-17, September 2008.
+ *   URL: http://docs.sun.com/app/docs/doc/817-1984
+ *
+ * - System V ABI AMD64 Architecture Processor Supplement
+ *   Draft Version 0.99.,
+ *   May 11, 2009.
+ *   URL: http://www.x86-64.org/
+ */
+#define PN_XNUM 0xffff
+
 /* These constants define the different elf file types */
 #define ET_NONE   0
 #define ET_REL    1
@@ -286,7 +308,7 @@
 #define SHN_COMMON	0xfff2
 #define SHN_HIRESERVE	0xffff
  
-typedef struct {
+typedef struct elf32_shdr {
   Elf32_Word	sh_name;
   Elf32_Word	sh_type;
   Elf32_Word	sh_flags;
@@ -394,16 +416,20 @@
 extern Elf32_Dyn _DYNAMIC [];
 #define elfhdr		elf32_hdr
 #define elf_phdr	elf32_phdr
+#define elf_shdr	elf32_shdr
 #define elf_note	elf32_note
 #define elf_addr_t	Elf32_Off
+#define Elf_Half	Elf32_Half
 
 #else
 
 extern Elf64_Dyn _DYNAMIC [];
 #define elfhdr		elf64_hdr
 #define elf_phdr	elf64_phdr
+#define elf_shdr	elf64_shdr
 #define elf_note	elf64_note
 #define elf_addr_t	Elf64_Off
+#define Elf_Half	Elf64_Half
 
 #endif
 
diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h
index 00d6a68..e687bc3 100644
--- a/include/linux/elfcore.h
+++ b/include/linux/elfcore.h
@@ -8,6 +8,8 @@
 #include <linux/user.h>
 #endif
 #include <linux/ptrace.h>
+#include <linux/elf.h>
+#include <linux/fs.h>
 
 struct elf_siginfo
 {
@@ -150,5 +152,20 @@
 
 #endif /* __KERNEL__ */
 
+/*
+ * These functions parameterize elf_core_dump in fs/binfmt_elf.c to write out
+ * extra segments containing the gate DSO contents.  Dumping its
+ * contents makes post-mortem fully interpretable later without matching up
+ * the same kernel and hardware config to see what PC values meant.
+ * Dumping its extra ELF program headers includes all the other information
+ * a debugger needs to easily find how the gate DSO was being used.
+ */
+extern Elf_Half elf_core_extra_phdrs(void);
+extern int
+elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
+			   unsigned long limit);
+extern int
+elf_core_write_extra_data(struct file *file, size_t *size, unsigned long limit);
+extern size_t elf_core_extra_data_size(void);
 
 #endif /* _LINUX_ELFCORE_H */
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index dc12f41..a9cd507 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -96,6 +96,7 @@
  * @fh_to_parent:   find the implied object's parent and get a dentry for it
  * @get_name:       find the name for a given inode in a given directory
  * @get_parent:     find the parent of a given directory
+ * @commit_metadata: commit metadata changes to stable storage
  *
  * See Documentation/filesystems/nfs/Exporting for details on how to use
  * this interface correctly.
@@ -137,6 +138,9 @@
  *    is also a directory.  In the event that it cannot be found, or storage
  *    space cannot be allocated, a %ERR_PTR should be returned.
  *
+ * commit_metadata:
+ *    @commit_metadata should commit metadata changes to stable storage.
+ *
  * Locking rules:
  *    get_parent is called with child->d_inode->i_mutex down
  *    get_name is not (which is possibly inconsistent)
@@ -152,6 +156,7 @@
 	int (*get_name)(struct dentry *parent, char *name,
 			struct dentry *child);
 	struct dentry * (*get_parent)(struct dentry *child);
+	int (*commit_metadata)(struct inode *inode);
 };
 
 extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid,
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 6b04903..cac84b0 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -202,14 +202,6 @@
 		return flags & EXT3_OTHER_FLMASK;
 }
 
-/*
- * Inode dynamic state flags
- */
-#define EXT3_STATE_JDATA		0x00000001 /* journaled data exists */
-#define EXT3_STATE_NEW			0x00000002 /* inode is newly created */
-#define EXT3_STATE_XATTR		0x00000004 /* has in-inode xattrs */
-#define EXT3_STATE_FLUSH_ON_CLOSE	0x00000008
-
 /* Used to pass group descriptor data when online resize is done */
 struct ext3_new_group_input {
 	__u32 group;            /* Group number for this data */
@@ -560,6 +552,31 @@
 		(ino >= EXT3_FIRST_INO(sb) &&
 		 ino <= le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count));
 }
+
+/*
+ * Inode dynamic state flags
+ */
+enum {
+	EXT3_STATE_JDATA,		/* journaled data exists */
+	EXT3_STATE_NEW,			/* inode is newly created */
+	EXT3_STATE_XATTR,		/* has in-inode xattrs */
+	EXT3_STATE_FLUSH_ON_CLOSE,	/* flush dirty pages on close */
+};
+
+static inline int ext3_test_inode_state(struct inode *inode, int bit)
+{
+	return test_bit(bit, &EXT3_I(inode)->i_state);
+}
+
+static inline void ext3_set_inode_state(struct inode *inode, int bit)
+{
+	set_bit(bit, &EXT3_I(inode)->i_state);
+}
+
+static inline void ext3_clear_inode_state(struct inode *inode, int bit)
+{
+	clear_bit(bit, &EXT3_I(inode)->i_state);
+}
 #else
 /* Assume that user mode programs are passing in an ext3fs superblock, not
  * a kernel struct super_block.  This will allow us to call the feature-test
@@ -877,7 +894,7 @@
 	int create);
 
 extern struct inode *ext3_iget(struct super_block *, unsigned long);
-extern int  ext3_write_inode (struct inode *, int);
+extern int  ext3_write_inode (struct inode *, struct writeback_control *);
 extern int  ext3_setattr (struct dentry *, struct iattr *);
 extern void ext3_delete_inode (struct inode *);
 extern int  ext3_sync_inode (handle_t *, struct inode *);
diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h
index 93e7428..7679acd 100644
--- a/include/linux/ext3_fs_i.h
+++ b/include/linux/ext3_fs_i.h
@@ -87,7 +87,7 @@
 	 * near to their parent directory's inode.
 	 */
 	__u32	i_block_group;
-	__u32	i_state;		/* Dynamic state flags for ext3 */
+	unsigned long	i_state;	/* Dynamic state flags for ext3 */
 
 	/* block reservation info */
 	struct ext3_block_alloc_info *i_block_alloc_info;
diff --git a/include/linux/fault-inject.h b/include/linux/fault-inject.h
index 06ca9b2..7b64ad4 100644
--- a/include/linux/fault-inject.h
+++ b/include/linux/fault-inject.h
@@ -82,9 +82,10 @@
 #endif /* CONFIG_FAULT_INJECTION */
 
 #ifdef CONFIG_FAILSLAB
-extern bool should_failslab(size_t size, gfp_t gfpflags);
+extern bool should_failslab(size_t size, gfp_t gfpflags, unsigned long flags);
 #else
-static inline bool should_failslab(size_t size, gfp_t gfpflags)
+static inline bool should_failslab(size_t size, gfp_t gfpflags,
+				unsigned long flags)
 {
 	return false;
 }
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 369767b..c10163b 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -543,6 +543,8 @@
 #define FB_EVENT_GET_REQ                0x0D
 /*      Unbind from the console if possible */
 #define FB_EVENT_FB_UNBIND              0x0E
+/*      CONSOLE-SPECIFIC: remap all consoles to new fb - for vga switcheroo */
+#define FB_EVENT_REMAP_ALL_CONSOLE      0x0F
 
 struct fb_event {
 	struct fb_info *info;
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index 520ecf8..40b1101 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -248,13 +248,20 @@
 #define FW_CDEV_IOC_SEND_BROADCAST_REQUEST       _IOW('#', 0x12, struct fw_cdev_send_request)
 #define FW_CDEV_IOC_SEND_STREAM_PACKET           _IOW('#', 0x13, struct fw_cdev_send_stream_packet)
 
+/* available since kernel version 2.6.34 */
+#define FW_CDEV_IOC_GET_CYCLE_TIMER2   _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2)
+
 /*
  * FW_CDEV_VERSION History
  *  1  (2.6.22)  - initial version
  *  2  (2.6.30)  - changed &fw_cdev_event_iso_interrupt.header if
  *                 &fw_cdev_create_iso_context.header_size is 8 or more
+ *     (2.6.32)  - added time stamp to xmit &fw_cdev_event_iso_interrupt
+ *     (2.6.33)  - IR has always packet-per-buffer semantics now, not one of
+ *                 dual-buffer or packet-per-buffer depending on hardware
+ *  3  (2.6.34)  - made &fw_cdev_get_cycle_timer reliable
  */
-#define FW_CDEV_VERSION 2
+#define FW_CDEV_VERSION 3
 
 /**
  * struct fw_cdev_get_info - General purpose information ioctl
@@ -544,14 +551,18 @@
 /**
  * struct fw_cdev_get_cycle_timer - read cycle timer register
  * @local_time:   system time, in microseconds since the Epoch
- * @cycle_timer:  isochronous cycle timer, as per OHCI 1.1 clause 5.13
+ * @cycle_timer:  Cycle Time register contents
  *
  * The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer
- * and also the system clock.  This allows to express the receive time of an
- * isochronous packet as a system time with microsecond accuracy.
+ * and also the system clock (%CLOCK_REALTIME).  This allows to express the
+ * receive time of an isochronous packet as a system time.
  *
  * @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and
- * 12 bits cycleOffset, in host byte order.
+ * 12 bits cycleOffset, in host byte order.  Cf. the Cycle Time register
+ * per IEEE 1394 or Isochronous Cycle Timer register per OHCI-1394.
+ *
+ * In version 1 and 2 of the ABI, this ioctl returned unreliable (non-
+ * monotonic) @cycle_timer values on certain controllers.
  */
 struct fw_cdev_get_cycle_timer {
 	__u64 local_time;
@@ -559,6 +570,25 @@
 };
 
 /**
+ * struct fw_cdev_get_cycle_timer2 - read cycle timer register
+ * @tv_sec:       system time, seconds
+ * @tv_nsec:      system time, sub-seconds part in nanoseconds
+ * @clk_id:       input parameter, clock from which to get the system time
+ * @cycle_timer:  Cycle Time register contents
+ *
+ * The %FW_CDEV_IOC_GET_CYCLE_TIMER2 works like
+ * %FW_CDEV_IOC_GET_CYCLE_TIMER but lets you choose a clock like with POSIX'
+ * clock_gettime function.  Supported @clk_id values are POSIX' %CLOCK_REALTIME
+ * and %CLOCK_MONOTONIC and Linux' %CLOCK_MONOTONIC_RAW.
+ */
+struct fw_cdev_get_cycle_timer2 {
+	__s64 tv_sec;
+	__s32 tv_nsec;
+	__s32 clk_id;
+	__u32 cycle_timer;
+};
+
+/**
  * struct fw_cdev_allocate_iso_resource - (De)allocate a channel or bandwidth
  * @closure:	Passed back to userspace in correponding iso resource events
  * @channels:	Isochronous channels of which one is to be (de)allocated
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index a0e6715..4bd94bf 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -65,12 +65,13 @@
 #define CSR_DIRECTORY_ID	0x20
 
 struct fw_csr_iterator {
-	u32 *p;
-	u32 *end;
+	const u32 *p;
+	const u32 *end;
 };
 
-void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p);
+void fw_csr_iterator_init(struct fw_csr_iterator *ci, const u32 *p);
 int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value);
+int fw_csr_string(const u32 *directory, int key, char *buf, size_t size);
 
 extern struct bus_type fw_bus_type;
 
@@ -162,7 +163,7 @@
 	struct mutex client_list_mutex;
 	struct list_head client_list;
 
-	u32 *config_rom;
+	const u32 *config_rom;
 	size_t config_rom_length;
 	int config_rom_retries;
 	unsigned is_local:1;
@@ -204,7 +205,7 @@
  */
 struct fw_unit {
 	struct device device;
-	u32 *directory;
+	const u32 *directory;
 	struct fw_attribute_group attribute_group;
 };
 
diff --git a/include/linux/firmware-map.h b/include/linux/firmware-map.h
index 875451f..c6dcc1d 100644
--- a/include/linux/firmware-map.h
+++ b/include/linux/firmware-map.h
@@ -24,17 +24,17 @@
  */
 #ifdef CONFIG_FIRMWARE_MEMMAP
 
-int firmware_map_add(u64 start, u64 end, const char *type);
 int firmware_map_add_early(u64 start, u64 end, const char *type);
+int firmware_map_add_hotplug(u64 start, u64 end, const char *type);
 
 #else /* CONFIG_FIRMWARE_MEMMAP */
 
-static inline int firmware_map_add(u64 start, u64 end, const char *type)
+static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
 {
 	return 0;
 }
 
-static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
+static inline int firmware_map_add_hotplug(u64 start, u64 end, const char *type)
 {
 	return 0;
 }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ebb1cd5..10b8ded 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -60,24 +60,24 @@
  */
 
 /* file is open for reading */
-#define FMODE_READ		((__force fmode_t)1)
+#define FMODE_READ		((__force fmode_t)0x1)
 /* file is open for writing */
-#define FMODE_WRITE		((__force fmode_t)2)
+#define FMODE_WRITE		((__force fmode_t)0x2)
 /* file is seekable */
-#define FMODE_LSEEK		((__force fmode_t)4)
+#define FMODE_LSEEK		((__force fmode_t)0x4)
 /* file can be accessed using pread */
-#define FMODE_PREAD		((__force fmode_t)8)
+#define FMODE_PREAD		((__force fmode_t)0x8)
 /* file can be accessed using pwrite */
-#define FMODE_PWRITE		((__force fmode_t)16)
+#define FMODE_PWRITE		((__force fmode_t)0x10)
 /* File is opened for execution with sys_execve / sys_uselib */
-#define FMODE_EXEC		((__force fmode_t)32)
+#define FMODE_EXEC		((__force fmode_t)0x20)
 /* File is opened with O_NDELAY (only set for block devices) */
-#define FMODE_NDELAY		((__force fmode_t)64)
+#define FMODE_NDELAY		((__force fmode_t)0x40)
 /* File is opened with O_EXCL (only set for block devices) */
-#define FMODE_EXCL		((__force fmode_t)128)
+#define FMODE_EXCL		((__force fmode_t)0x80)
 /* File is opened using open(.., 3, ..) and is writeable only for ioctls
    (specialy hack for floppy.c) */
-#define FMODE_WRITE_IOCTL	((__force fmode_t)256)
+#define FMODE_WRITE_IOCTL	((__force fmode_t)0x100)
 
 /*
  * Don't update ctime and mtime.
@@ -85,7 +85,10 @@
  * Currently a special hack for the XFS open_by_handle ioctl, but we'll
  * hopefully graduate it to a proper O_CMTIME flag supported by open(2) soon.
  */
-#define FMODE_NOCMTIME		((__force fmode_t)2048)
+#define FMODE_NOCMTIME		((__force fmode_t)0x800)
+
+/* Expect random access pattern */
+#define FMODE_RANDOM		((__force fmode_t)0x1000)
 
 /*
  * The below are the various read and write types that we support. Some of
@@ -1305,6 +1308,8 @@
 #define MNT_FORCE	0x00000001	/* Attempt to forcibily umount */
 #define MNT_DETACH	0x00000002	/* Just detach from the tree */
 #define MNT_EXPIRE	0x00000004	/* Mark for expiry */
+#define UMOUNT_NOFOLLOW	0x00000008	/* Don't follow symlink on umount */
+#define UMOUNT_UNUSED	0x80000000	/* Flag guaranteed to be unused */
 
 extern struct list_head super_blocks;
 extern spinlock_t sb_lock;
@@ -1314,9 +1319,9 @@
 struct super_block {
 	struct list_head	s_list;		/* Keep this first */
 	dev_t			s_dev;		/* search index; _not_ kdev_t */
-	unsigned long		s_blocksize;
-	unsigned char		s_blocksize_bits;
 	unsigned char		s_dirt;
+	unsigned char		s_blocksize_bits;
+	unsigned long		s_blocksize;
 	loff_t			s_maxbytes;	/* Max file size */
 	struct file_system_type	*s_type;
 	const struct super_operations	*s_op;
@@ -1357,16 +1362,16 @@
 	void 			*s_fs_info;	/* Filesystem private info */
 	fmode_t			s_mode;
 
+	/* Granularity of c/m/atime in ns.
+	   Cannot be worse than a second */
+	u32		   s_time_gran;
+
 	/*
 	 * The next field is for VFS *only*. No filesystems have any business
 	 * even looking at it. You had been warned.
 	 */
 	struct mutex s_vfs_rename_mutex;	/* Kludge */
 
-	/* Granularity of c/m/atime in ns.
-	   Cannot be worse than a second */
-	u32		   s_time_gran;
-
 	/*
 	 * Filesystem subtype.  If non-empty the filesystem type field
 	 * in /proc/mounts will be "type.subtype"
@@ -1555,7 +1560,7 @@
 	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);
 	void (*drop_inode) (struct inode *);
 	void (*delete_inode) (struct inode *);
 	void (*put_super) (struct super_block *);
@@ -1794,7 +1799,8 @@
 extern long do_mount(char *, char *, char *, unsigned long, void *);
 extern struct vfsmount *collect_mounts(struct path *);
 extern void drop_collected_mounts(struct vfsmount *);
-
+extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *,
+			  struct vfsmount *);
 extern int vfs_statfs(struct dentry *, struct kstatfs *);
 
 extern int current_umask(void);
@@ -2058,12 +2064,6 @@
 unsigned long invalidate_mapping_pages(struct address_space *mapping,
 					pgoff_t start, pgoff_t end);
 
-static inline unsigned long __deprecated
-invalidate_inode_pages(struct address_space *mapping)
-{
-	return invalidate_mapping_pages(mapping, 0, ~0UL);
-}
-
 static inline void invalidate_remote_inode(struct inode *inode)
 {
 	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
@@ -2132,6 +2132,7 @@
  
 /* fs/dcache.c -- generic fs support functions */
 extern int is_subdir(struct dentry *, struct dentry *);
+extern int path_is_under(struct path *, struct path *);
 extern ino_t find_inode_number(struct dentry *, struct qstr *);
 
 #include <linux/err.h>
@@ -2340,8 +2341,6 @@
 extern int simple_sync_file(struct file *, struct dentry *, int);
 extern int simple_empty(struct dentry *);
 extern int simple_readpage(struct file *file, struct page *page);
-extern int simple_prepare_write(struct file *file, struct page *page,
-			unsigned offset, unsigned to);
 extern int simple_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned flags,
 			struct page **pagep, void **fsdata);
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 936f9aa..df8fd9a 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -65,7 +65,7 @@
  * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
  */
 static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
-				 const char *old_name, const char *new_name,
+				 const char *old_name,
 				 int isdir, struct inode *target, struct dentry *moved)
 {
 	struct inode *source = moved->d_inode;
@@ -73,6 +73,7 @@
 	u32 fs_cookie = fsnotify_get_cookie();
 	__u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM);
 	__u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO);
+	const char *new_name = moved->d_name.name;
 
 	if (old_dir == new_dir)
 		old_dir_mask |= FS_DN_RENAME;
@@ -103,7 +104,7 @@
 		inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
 		fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
 	}
-	audit_inode_child(new_name, moved, new_dir);
+	audit_inode_child(moved, new_dir);
 }
 
 /*
@@ -146,7 +147,7 @@
 {
 	inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name,
 				  dentry->d_inode);
-	audit_inode_child(dentry->d_name.name, dentry, inode);
+	audit_inode_child(dentry, inode);
 
 	fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 }
@@ -161,7 +162,7 @@
 	inotify_inode_queue_event(dir, IN_CREATE, 0, new_dentry->d_name.name,
 				  inode);
 	fsnotify_link_count(inode);
-	audit_inode_child(new_dentry->d_name.name, new_dentry, dir);
+	audit_inode_child(new_dentry, dir);
 
 	fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
 }
@@ -175,7 +176,7 @@
 	struct inode *d_inode = dentry->d_inode;
 
 	inotify_inode_queue_event(inode, mask, 0, dentry->d_name.name, d_inode);
-	audit_inode_child(dentry->d_name.name, dentry, inode);
+	audit_inode_child(dentry, inode);
 
 	fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 }
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 9717081..56b5051 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -101,7 +101,7 @@
 	unsigned long stamp;
 	int in_flight[2];
 #ifdef	CONFIG_SMP
-	struct disk_stats *dkstats;
+	struct disk_stats __percpu *dkstats;
 #else
 	struct disk_stats dkstats;
 #endif
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 557bdad..4c6d413 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -30,7 +30,8 @@
  * _might_ fail.  This depends upon the particular VM implementation.
  *
  * __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
- * cannot handle allocation failures.
+ * cannot handle allocation failures.  This modifier is deprecated and no new
+ * users should be added.
  *
  * __GFP_NORETRY: The VM implementation must not retry indefinitely.
  *
@@ -83,6 +84,7 @@
 #define GFP_HIGHUSER_MOVABLE	(__GFP_WAIT | __GFP_IO | __GFP_FS | \
 				 __GFP_HARDWALL | __GFP_HIGHMEM | \
 				 __GFP_MOVABLE)
+#define GFP_IOFS	(__GFP_IO | __GFP_FS)
 
 #ifdef CONFIG_NUMA
 #define GFP_THISNODE	(__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
@@ -325,7 +327,7 @@
 
 extern void __free_pages(struct page *page, unsigned int order);
 extern void free_pages(unsigned long addr, unsigned int order);
-extern void free_hot_page(struct page *page);
+extern void free_hot_cold_page(struct page *page, int cold);
 
 #define __free_page(page) __free_pages((page), 0)
 #define free_page(addr) free_pages((addr),0)
@@ -337,9 +339,7 @@
 
 extern gfp_t gfp_allowed_mask;
 
-static inline void set_gfp_allowed_mask(gfp_t mask)
-{
-	gfp_allowed_mask = mask;
-}
+extern void set_gfp_allowed_mask(gfp_t mask);
+extern gfp_t clear_gfp_allowed_mask(gfp_t mask);
 
 #endif /* __LINUX_GFP_H */
diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h
index 81f90a5..4f44629 100644
--- a/include/linux/gfs2_ondisk.h
+++ b/include/linux/gfs2_ondisk.h
@@ -180,33 +180,6 @@
 };
 
 /*
- * quota linked list: user quotas and group quotas form two separate 
- * singly linked lists. ll_next stores uids or gids of next quotas in the 
- * linked list.
-
-Given the uid/gid, how to calculate the quota file offsets for the corresponding
-gfs2_quota structures on disk:
-
-for user quotas, given uid,
-offset = uid * sizeof(struct gfs2_quota);
-
-for group quotas, given gid,
-offset = (gid * sizeof(struct gfs2_quota)) + sizeof(struct gfs2_quota);
-
-
-  uid:0   gid:0       uid:12   gid:12      uid:17   gid:17     uid:5142 gid:5142
-+-------+-------+    +-------+-------+    +-------+- - - -+    +- - - -+-------+
-| valid | valid | :: | valid | valid | :: | valid | inval | :: | inval | valid |
-+-------+-------+    +-------+-------+    +-------+- - - -+    +- - - -+-------+
-next:12   next:12    next:17 next:5142    next:NULL                    next:NULL
-    |       |            |       |            |<-- user quota list         |
-     \______|___________/ \______|___________/         group quota list -->|
-            |                    |                                         |
-             \__________________/ \_______________________________________/
-
-*/
-
-/*
  * quota structure
  */
 
@@ -214,8 +187,7 @@
 	__be64 qu_limit;
 	__be64 qu_warn;
 	__be64 qu_value;
-	__be32 qu_ll_next; /* location of next quota in list */
-	__u8 qu_reserved[60];
+	__u8 qu_reserved[64];
 };
 
 /*
diff --git a/include/linux/hil.h b/include/linux/hil.h
index 13352d7..523785a 100644
--- a/include/linux/hil.h
+++ b/include/linux/hil.h
@@ -168,14 +168,14 @@
 	HIL_CMD_PR6	= 0x45,	/* Prompt6 */
 	HIL_CMD_PR7	= 0x46,	/* Prompt7 */
 	HIL_CMD_PRM	= 0x47,	/* Prompt (General Purpose) */
-	HIL_CMD_AK1	= 0x48,	/* Acknowlege1 */  
-	HIL_CMD_AK2	= 0x49,	/* Acknowlege2 */
-	HIL_CMD_AK3	= 0x4a,	/* Acknowlege3 */
-	HIL_CMD_AK4	= 0x4b,	/* Acknowlege4 */
-	HIL_CMD_AK5	= 0x4c,	/* Acknowlege5 */
-	HIL_CMD_AK6	= 0x4d,	/* Acknowlege6 */
-	HIL_CMD_AK7	= 0x4e,	/* Acknowlege7 */
-	HIL_CMD_ACK	= 0x4f,	/* Acknowlege (General Purpose) */
+	HIL_CMD_AK1	= 0x48,	/* Acknowledge1 */  
+	HIL_CMD_AK2	= 0x49,	/* Acknowledge2 */
+	HIL_CMD_AK3	= 0x4a,	/* Acknowledge3 */
+	HIL_CMD_AK4	= 0x4b,	/* Acknowledge4 */
+	HIL_CMD_AK5	= 0x4c,	/* Acknowledge5 */
+	HIL_CMD_AK6	= 0x4d,	/* Acknowledge6 */
+	HIL_CMD_AK7	= 0x4e,	/* Acknowledge7 */
+	HIL_CMD_ACK	= 0x4f,	/* Acknowledge (General Purpose) */
 
 	/* 0x50 to 0x78 reserved for future use  */
 	/* 0x80 to 0xEF device-specific commands */
diff --git a/include/linux/htcpld.h b/include/linux/htcpld.h
new file mode 100644
index 0000000..ab3f6cb4
--- /dev/null
+++ b/include/linux/htcpld.h
@@ -0,0 +1,24 @@
+#ifndef __LINUX_HTCPLD_H
+#define __LINUX_HTCPLD_H
+
+struct htcpld_chip_platform_data {
+	unsigned int addr;
+	unsigned int reset;
+	unsigned int num_gpios;
+	unsigned int gpio_out_base;
+	unsigned int gpio_in_base;
+	unsigned int irq_base;
+	unsigned int num_irqs;
+};
+
+struct htcpld_core_platform_data {
+	unsigned int                      int_reset_gpio_hi;
+	unsigned int                      int_reset_gpio_lo;
+	unsigned int                      i2c_adapter_id;
+
+	struct htcpld_chip_platform_data  *chip;
+	unsigned int                      num_chip;
+};
+
+#endif /* __LINUX_HTCPLD_H */
+
diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h
index 5977b72..c70d27a 100644
--- a/include/linux/hw_breakpoint.h
+++ b/include/linux/hw_breakpoint.h
@@ -66,14 +66,14 @@
 				perf_overflow_handler_t	triggered,
 				int cpu);
 
-extern struct perf_event **
+extern struct perf_event * __percpu *
 register_wide_hw_breakpoint(struct perf_event_attr *attr,
 			    perf_overflow_handler_t triggered);
 
 extern int register_perf_hw_breakpoint(struct perf_event *bp);
 extern int __register_perf_hw_breakpoint(struct perf_event *bp);
 extern void unregister_hw_breakpoint(struct perf_event *bp);
-extern void unregister_wide_hw_breakpoint(struct perf_event **cpu_events);
+extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events);
 
 extern int dbg_reserve_bp_slot(struct perf_event *bp);
 extern int dbg_release_bp_slot(struct perf_event *bp);
@@ -100,7 +100,7 @@
 register_wide_hw_breakpoint_cpu(struct perf_event_attr *attr,
 				perf_overflow_handler_t	 triggered,
 				int cpu)		{ return NULL; }
-static inline struct perf_event **
+static inline struct perf_event * __percpu *
 register_wide_hw_breakpoint(struct perf_event_attr *attr,
 			    perf_overflow_handler_t triggered)	{ return NULL; }
 static inline int
@@ -109,7 +109,7 @@
 __register_perf_hw_breakpoint(struct perf_event *bp) 	{ return -ENOSYS; }
 static inline void unregister_hw_breakpoint(struct perf_event *bp)	{ }
 static inline void
-unregister_wide_hw_breakpoint(struct perf_event **cpu_events)		{ }
+unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events)	{ }
 static inline int
 reserve_bp_slot(struct perf_event *bp)			{return -ENOSYS; }
 static inline void release_bp_slot(struct perf_event *bp) 		{ }
diff --git a/include/linux/i2c-smbus.h b/include/linux/i2c-smbus.h
new file mode 100644
index 0000000..63f57a8
--- /dev/null
+++ b/include/linux/i2c-smbus.h
@@ -0,0 +1,50 @@
+/*
+ * i2c-smbus.h - SMBus extensions to the I2C protocol
+ *
+ * Copyright (C) 2010 Jean Delvare <khali@linux-fr.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.
+ */
+
+#ifndef _LINUX_I2C_SMBUS_H
+#define _LINUX_I2C_SMBUS_H
+
+#include <linux/i2c.h>
+
+
+/**
+ * i2c_smbus_alert_setup - platform data for the smbus_alert i2c client
+ * @alert_edge_triggered: whether the alert interrupt is edge (1) or level (0)
+ *		triggered
+ * @irq: IRQ number, if the smbus_alert driver should take care of interrupt
+ *		handling
+ *
+ * If irq is not specified, the smbus_alert driver doesn't take care of
+ * interrupt handling. In that case it is up to the I2C bus driver to either
+ * handle the interrupts or to poll for alerts.
+ *
+ * If irq is specified then it it crucial that alert_edge_triggered is
+ * properly set.
+ */
+struct i2c_smbus_alert_setup {
+	unsigned int		alert_edge_triggered:1;
+	int			irq;
+};
+
+struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
+					 struct i2c_smbus_alert_setup *setup);
+int i2c_handle_smbus_alert(struct i2c_client *ara);
+
+#endif /* _LINUX_I2C_SMBUS_H */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 02fc617..0a5da63 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -53,6 +53,7 @@
  * on a bus (or read from them). Apart from two basic transfer functions to
  * transmit one message at a time, a more complex version can be used to
  * transmit an arbitrary number of messages without interruption.
+ * @count must be be less than 64k since msg.len is u16.
  */
 extern int i2c_master_send(struct i2c_client *client, const char *buf,
 			   int count);
@@ -152,6 +153,13 @@
 	int (*suspend)(struct i2c_client *, pm_message_t mesg);
 	int (*resume)(struct i2c_client *);
 
+	/* Alert callback, for example for the SMBus alert protocol.
+	 * The format and meaning of the data value depends on the protocol.
+	 * For the SMBus alert protocol, there is a single bit of data passed
+	 * as the alert response's low bit ("event flag").
+	 */
+	void (*alert)(struct i2c_client *, unsigned int data);
+
 	/* a ioctl like command that can be used to perform specific functions
 	 * with the device.
 	 */
diff --git a/include/linux/i2c/pca953x.h b/include/linux/i2c/pca953x.h
index 81736d6..d5c5a60 100644
--- a/include/linux/i2c/pca953x.h
+++ b/include/linux/i2c/pca953x.h
@@ -1,3 +1,9 @@
+#ifndef _LINUX_PCA953X_H
+#define _LINUX_PCA953X_H
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
 /* platform data for the PCA9539 16-bit I/O expander driver */
 
 struct pca953x_platform_data {
@@ -7,6 +13,9 @@
 	/* initial polarity inversion setting */
 	uint16_t	invert;
 
+	/* interrupt base */
+	int		irq_base;
+
 	void		*context;	/* param to setup/teardown */
 
 	int		(*setup)(struct i2c_client *client,
@@ -17,3 +26,5 @@
 				void *context);
 	char		**names;
 };
+
+#endif /* _LINUX_PCA953X_H */
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 7897f30..fb6784e 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -80,6 +80,11 @@
 #define TWL_MODULE_PM_MASTER	TWL4030_MODULE_PM_MASTER
 #define TWL_MODULE_PM_RECEIVER	TWL4030_MODULE_PM_RECEIVER
 #define TWL_MODULE_RTC		TWL4030_MODULE_RTC
+#define TWL_MODULE_PWM		TWL4030_MODULE_PWM0
+
+#define TWL6030_MODULE_ID0	0x0D
+#define TWL6030_MODULE_ID1	0x0E
+#define TWL6030_MODULE_ID2	0x0F
 
 #define GPIO_INTR_OFFSET	0
 #define KEYPAD_INTR_OFFSET	1
@@ -239,6 +244,21 @@
 
 /*----------------------------------------------------------------------*/
 
+/*Interface Bit Register (INTBR) offsets
+ *(Use TWL_4030_MODULE_INTBR)
+ */
+
+#define REG_GPPUPDCTR1			0x0F
+
+/*I2C1 and I2C4(SR) SDA/SCL pull-up control bits */
+
+#define I2C_SCL_CTRL_PU			BIT(0)
+#define I2C_SDA_CTRL_PU			BIT(2)
+#define SR_I2C_SCL_CTRL_PU		BIT(4)
+#define SR_I2C_SDA_CTRL_PU		BIT(6)
+
+/*----------------------------------------------------------------------*/
+
 /*
  * Keypad register offsets (use TWL4030_MODULE_KEYPAD)
  * ... SIH/interrupt only
@@ -530,6 +550,7 @@
 };
 
 extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
+extern int twl4030_remove_script(u8 flags);
 
 struct twl4030_codec_audio_data {
 	unsigned int	audio_mclk;
@@ -605,12 +626,7 @@
 #define TWL4030_VAUX3_DEV_GRP		0x1F
 #define TWL4030_VAUX3_DEDICATED		0x22
 
-#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
-	defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
-	extern int twl4030charger_usb_en(int enable);
-#else
-	static inline int twl4030charger_usb_en(int enable) { return 0; }
-#endif
+static inline int twl4030charger_usb_en(int enable) { return 0; }
 
 /*----------------------------------------------------------------------*/
 
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 0ec6129..97e6ab4 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -515,6 +515,8 @@
         u8	init_speed;	/* transfer rate set at boot */
         u8	current_speed;	/* current transfer rate set */
 	u8	desired_speed;	/* desired transfer rate set */
+	u8	pio_mode;	/* for ->set_pio_mode _only_ */
+	u8	dma_mode;	/* for ->dma_pio_mode _only_ */
         u8	dn;		/* now wide spread use */
 	u8	acoustic;	/* acoustic management */
 	u8	media;		/* disk, cdrom, tape, floppy, ... */
@@ -622,8 +624,8 @@
  */
 struct ide_port_ops {
 	void	(*init_dev)(ide_drive_t *);
-	void	(*set_pio_mode)(ide_drive_t *, const u8);
-	void	(*set_dma_mode)(ide_drive_t *, const u8);
+	void	(*set_pio_mode)(struct hwif_s *, ide_drive_t *);
+	void	(*set_dma_mode)(struct hwif_s *, ide_drive_t *);
 	int	(*reset_poll)(ide_drive_t *);
 	void	(*pre_reset)(ide_drive_t *);
 	void	(*resetproc)(ide_drive_t *);
@@ -1494,7 +1496,6 @@
 #ifdef CONFIG_IDE_XFER_MODE
 int ide_scan_pio_blacklist(char *);
 const char *ide_xfer_verbose(u8);
-u8 ide_get_best_pio_mode(ide_drive_t *, u8, u8);
 int ide_pio_need_iordy(ide_drive_t *, const u8);
 int ide_set_pio_mode(ide_drive_t *, u8);
 int ide_set_dma_mode(ide_drive_t *, u8);
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index abec69b..b1ed1cd 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -32,14 +32,6 @@
 }
 
 extern struct nsproxy init_nsproxy;
-#define INIT_NSPROXY(nsproxy) {						\
-	.pid_ns		= &init_pid_ns,					\
-	.count		= ATOMIC_INIT(1),				\
-	.uts_ns		= &init_uts_ns,					\
-	.mnt_ns		= NULL,						\
-	INIT_NET_NS(net_ns)                                             \
-	INIT_IPC_NS(ipc_ns)						\
-}
 
 #define INIT_SIGHAND(sighand) {						\
 	.count		= ATOMIC_INIT(1), 				\
diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h
index 1195a80..a0bb301 100644
--- a/include/linux/iocontext.h
+++ b/include/linux/iocontext.h
@@ -42,7 +42,7 @@
 	unsigned short ioprio;
 	unsigned short ioprio_changed;
 
-#ifdef CONFIG_BLK_CGROUP
+#if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
 	unsigned short cgroup_changed;
 #endif
 
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index 07baa38..5195298 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -62,11 +62,6 @@
 extern atomic_t nr_ipc_ns;
 
 extern spinlock_t mq_lock;
-#if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
-#define INIT_IPC_NS(ns)		.ns		= &init_ipc_ns,
-#else
-#define INIT_IPC_NS(ns)
-#endif
 
 #ifdef CONFIG_SYSVIPC
 extern int register_ipcns_notifier(struct ipc_namespace *);
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
index f7c9c75..4b48318 100644
--- a/include/linux/ipmi_smi.h
+++ b/include/linux/ipmi_smi.h
@@ -39,7 +39,6 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <linux/ipmi_smi.h>
 
 /* This files describes the interface for IPMI system management interface
    drivers to bind into the IPMI message handler. */
diff --git a/include/linux/irq.h b/include/linux/irq.h
index d13492d..707ab12 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -400,7 +400,9 @@
 
 /* Dynamic irq helper functions */
 extern void dynamic_irq_init(unsigned int irq);
+void dynamic_irq_init_keep_chip_data(unsigned int irq);
 extern void dynamic_irq_cleanup(unsigned int irq);
+void dynamic_irq_cleanup_keep_chip_data(unsigned int irq);
 
 /* Set/get chip/data for an IRQ: */
 extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 331530c..f3aa59c 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -246,19 +246,8 @@
 
 #define J_ASSERT(assert)	BUG_ON(!(assert))
 
-#if defined(CONFIG_BUFFER_DEBUG)
-void buffer_assertion_failure(struct buffer_head *bh);
-#define J_ASSERT_BH(bh, expr)						\
-	do {								\
-		if (!(expr))						\
-			buffer_assertion_failure(bh);			\
-		J_ASSERT(expr);						\
-	} while (0)
-#define J_ASSERT_JH(jh, expr)	J_ASSERT_BH(jh2bh(jh), expr)
-#else
 #define J_ASSERT_BH(bh, expr)	J_ASSERT(expr)
 #define J_ASSERT_JH(jh, expr)	J_ASSERT(expr)
-#endif
 
 #if defined(JBD_PARANOID_IOFAIL)
 #define J_EXPECT(expr, why...)		J_ASSERT(expr)
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 638ce45..1ec8763 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -69,15 +69,8 @@
 #define jbd_debug(f, a...)	/**/
 #endif
 
-static inline void *jbd2_alloc(size_t size, gfp_t flags)
-{
-	return (void *)__get_free_pages(flags, get_order(size));
-}
-
-static inline void jbd2_free(void *ptr, size_t size)
-{
-	free_pages((unsigned long)ptr, get_order(size));
-};
+extern void *jbd2_alloc(size_t size, gfp_t flags);
+extern void jbd2_free(void *ptr, size_t size);
 
 #define JBD2_MIN_JOURNAL_BLOCKS 1024
 
@@ -284,19 +277,8 @@
 
 #define J_ASSERT(assert)	BUG_ON(!(assert))
 
-#if defined(CONFIG_BUFFER_DEBUG)
-void buffer_assertion_failure(struct buffer_head *bh);
-#define J_ASSERT_BH(bh, expr)						\
-	do {								\
-		if (!(expr))						\
-			buffer_assertion_failure(bh);			\
-		J_ASSERT(expr);						\
-	} while (0)
-#define J_ASSERT_JH(jh, expr)	J_ASSERT_BH(jh2bh(jh), expr)
-#else
 #define J_ASSERT_BH(bh, expr)	J_ASSERT(expr)
 #define J_ASSERT_JH(jh, expr)	J_ASSERT(expr)
-#endif
 
 #if defined(JBD2_PARANOID_IOFAIL)
 #define J_EXPECT(expr, why...)		J_ASSERT(expr)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 1221d23..7f07074 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -44,6 +44,16 @@
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
 
+/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+
 #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index c356b69..03e8e8d 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -199,7 +199,7 @@
  */
 extern struct resource crashk_res;
 typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
-extern note_buf_t *crash_notes;
+extern note_buf_t __percpu *crash_notes;
 extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
 extern size_t vmcoreinfo_size;
 extern size_t vmcoreinfo_max_size;
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 384ca8b..facb27f 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -27,6 +27,7 @@
 #define KMOD_PATH_LEN 256
 
 #ifdef CONFIG_MODULES
+extern char modprobe_path[]; /* for sysctl */
 /* modprobe exit status on success, -ve on error.  Return value
  * usually useless though. */
 extern int __request_module(bool wait, const char *name, ...) \
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 58ae8e00..3950d3c 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -106,7 +106,7 @@
 
 struct kobj_type {
 	void (*release)(struct kobject *kobj);
-	struct sysfs_ops *sysfs_ops;
+	const struct sysfs_ops *sysfs_ops;
 	struct attribute **default_attrs;
 };
 
@@ -118,9 +118,9 @@
 };
 
 struct kset_uevent_ops {
-	int (*filter)(struct kset *kset, struct kobject *kobj);
-	const char *(*name)(struct kset *kset, struct kobject *kobj);
-	int (*uevent)(struct kset *kset, struct kobject *kobj,
+	int (* const filter)(struct kset *kset, struct kobject *kobj);
+	const char *(* const name)(struct kset *kset, struct kobject *kobj);
+	int (* const uevent)(struct kset *kset, struct kobject *kobj,
 		      struct kobj_uevent_env *env);
 };
 
@@ -132,7 +132,7 @@
 			 const char *buf, size_t count);
 };
 
-extern struct sysfs_ops kobj_sysfs_ops;
+extern const struct sysfs_ops kobj_sysfs_ops;
 
 /**
  * struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
@@ -155,14 +155,14 @@
 	struct list_head list;
 	spinlock_t list_lock;
 	struct kobject kobj;
-	struct kset_uevent_ops *uevent_ops;
+	const struct kset_uevent_ops *uevent_ops;
 };
 
 extern void kset_init(struct kset *kset);
 extern int __must_check kset_register(struct kset *kset);
 extern void kset_unregister(struct kset *kset);
 extern struct kset * __must_check kset_create_and_add(const char *name,
-						struct kset_uevent_ops *u,
+						const struct kset_uevent_ops *u,
 						struct kobject *parent_kobj);
 
 static inline struct kset *to_kset(struct kobject *kobj)
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 1b672f7..e7d1b2e 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -122,6 +122,11 @@
 /* Kprobe status flags */
 #define KPROBE_FLAG_GONE	1 /* breakpoint has already gone */
 #define KPROBE_FLAG_DISABLED	2 /* probe is temporarily disabled */
+#define KPROBE_FLAG_OPTIMIZED	4 /*
+				   * probe is really optimized.
+				   * NOTE:
+				   * this flag is only for optimized_kprobe.
+				   */
 
 /* Has this kprobe gone ? */
 static inline int kprobe_gone(struct kprobe *p)
@@ -134,6 +139,12 @@
 {
 	return p->flags & (KPROBE_FLAG_DISABLED | KPROBE_FLAG_GONE);
 }
+
+/* Is this kprobe really running optimized path ? */
+static inline int kprobe_optimized(struct kprobe *p)
+{
+	return p->flags & KPROBE_FLAG_OPTIMIZED;
+}
 /*
  * Special probe type that uses setjmp-longjmp type tricks to resume
  * execution at a specified entry with a matching prototype corresponding
@@ -249,6 +260,39 @@
 extern void free_insn_slot(kprobe_opcode_t *slot, int dirty);
 extern void kprobes_inc_nmissed_count(struct kprobe *p);
 
+#ifdef CONFIG_OPTPROBES
+/*
+ * Internal structure for direct jump optimized probe
+ */
+struct optimized_kprobe {
+	struct kprobe kp;
+	struct list_head list;	/* list for optimizing queue */
+	struct arch_optimized_insn optinsn;
+};
+
+/* Architecture dependent functions for direct jump optimization */
+extern int arch_prepared_optinsn(struct arch_optimized_insn *optinsn);
+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_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);
+extern int arch_within_optimized_kprobe(struct optimized_kprobe *op,
+					unsigned long addr);
+
+extern void opt_pre_handler(struct kprobe *p, struct pt_regs *regs);
+
+#ifdef CONFIG_SYSCTL
+extern int sysctl_kprobes_optimization;
+extern int proc_kprobes_optimization_handler(struct ctl_table *table,
+					     int write, void __user *buffer,
+					     size_t *length, loff_t *ppos);
+#endif
+
+#endif /* CONFIG_OPTPROBES */
+
 /* Get the kprobe at this addr (if any) - called with preemption disabled */
 struct kprobe *get_kprobe(void *addr);
 void kretprobe_hash_lock(struct task_struct *tsk,
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index a24de0b..60df9c8 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -103,7 +103,7 @@
 
 /* for kvm_memory_region::flags */
 #define KVM_MEM_LOG_DIRTY_PAGES  1UL
-
+#define KVM_MEMSLOT_INVALID      (1UL << 1)
 
 /* for KVM_IRQ_LINE */
 struct kvm_irq_level {
@@ -497,6 +497,11 @@
 #endif
 #define KVM_CAP_S390_PSW 42
 #define KVM_CAP_PPC_SEGSTATE 43
+#define KVM_CAP_HYPERV 44
+#define KVM_CAP_HYPERV_VAPIC 45
+#define KVM_CAP_HYPERV_SPIN 46
+#define KVM_CAP_PCI_SEGMENT 47
+#define KVM_CAP_X86_ROBUST_SINGLESTEP 51
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -691,8 +696,9 @@
 	__u32 busnr;
 	__u32 devfn;
 	__u32 flags;
+	__u32 segnr;
 	union {
-		__u32 reserved[12];
+		__u32 reserved[11];
 	};
 };
 
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index bd5a616..a3fd0f9 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -38,6 +38,7 @@
 #define KVM_REQ_MMU_SYNC           7
 #define KVM_REQ_KVMCLOCK_UPDATE    8
 #define KVM_REQ_KICK               9
+#define KVM_REQ_DEACTIVATE_FPU    10
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID	0
 
@@ -57,20 +58,20 @@
 	struct kvm_io_device *devs[NR_IOBUS_DEVS];
 };
 
-void kvm_io_bus_init(struct kvm_io_bus *bus);
-void kvm_io_bus_destroy(struct kvm_io_bus *bus);
-int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, int len,
-		     const void *val);
-int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len,
+enum kvm_bus {
+	KVM_MMIO_BUS,
+	KVM_PIO_BUS,
+	KVM_NR_BUSES
+};
+
+int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+		     int len, const void *val);
+int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
 		    void *val);
-int __kvm_io_bus_register_dev(struct kvm_io_bus *bus,
-			       struct kvm_io_device *dev);
-int kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus,
+int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx,
 			    struct kvm_io_device *dev);
-void __kvm_io_bus_unregister_dev(struct kvm_io_bus *bus,
-				 struct kvm_io_device *dev);
-void kvm_io_bus_unregister_dev(struct kvm *kvm, struct kvm_io_bus *bus,
-			       struct kvm_io_device *dev);
+int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
+			      struct kvm_io_device *dev);
 
 struct kvm_vcpu {
 	struct kvm *kvm;
@@ -83,6 +84,8 @@
 	struct kvm_run *run;
 	unsigned long requests;
 	unsigned long guest_debug;
+	int srcu_idx;
+
 	int fpu_active;
 	int guest_fpu_loaded;
 	wait_queue_head_t wq;
@@ -150,14 +153,19 @@
 
 #endif
 
-struct kvm {
-	spinlock_t mmu_lock;
-	spinlock_t requests_lock;
-	struct rw_semaphore slots_lock;
-	struct mm_struct *mm; /* userspace tied to this vm */
+struct kvm_memslots {
 	int nmemslots;
 	struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS +
 					KVM_PRIVATE_MEM_SLOTS];
+};
+
+struct kvm {
+	spinlock_t mmu_lock;
+	raw_spinlock_t requests_lock;
+	struct mutex slots_lock;
+	struct mm_struct *mm; /* userspace tied to this vm */
+	struct kvm_memslots *memslots;
+	struct srcu_struct srcu;
 #ifdef CONFIG_KVM_APIC_ARCHITECTURE
 	u32 bsp_vcpu_id;
 	struct kvm_vcpu *bsp_vcpu;
@@ -166,8 +174,7 @@
 	atomic_t online_vcpus;
 	struct list_head vm_list;
 	struct mutex lock;
-	struct kvm_io_bus mmio_bus;
-	struct kvm_io_bus pio_bus;
+	struct kvm_io_bus *buses[KVM_NR_BUSES];
 #ifdef CONFIG_HAVE_KVM_EVENTFD
 	struct {
 		spinlock_t        lock;
@@ -249,13 +256,20 @@
 int __kvm_set_memory_region(struct kvm *kvm,
 			    struct kvm_userspace_memory_region *mem,
 			    int user_alloc);
-int kvm_arch_set_memory_region(struct kvm *kvm,
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+				struct kvm_memory_slot *memslot,
+				struct kvm_memory_slot old,
+				struct kvm_userspace_memory_region *mem,
+				int user_alloc);
+void kvm_arch_commit_memory_region(struct kvm *kvm,
 				struct kvm_userspace_memory_region *mem,
 				struct kvm_memory_slot old,
 				int user_alloc);
 void kvm_disable_largepages(void);
 void kvm_arch_flush_shadow(struct kvm *kvm);
 gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn);
+gfn_t unalias_gfn_instantiation(struct kvm *kvm, gfn_t gfn);
+
 struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn);
 unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn);
 void kvm_release_page_clean(struct page *page);
@@ -264,6 +278,9 @@
 void kvm_set_page_accessed(struct page *page);
 
 pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn);
+pfn_t gfn_to_pfn_memslot(struct kvm *kvm,
+			 struct kvm_memory_slot *slot, gfn_t gfn);
+int memslot_id(struct kvm *kvm, gfn_t gfn);
 void kvm_release_pfn_dirty(pfn_t);
 void kvm_release_pfn_clean(pfn_t pfn);
 void kvm_set_pfn_dirty(pfn_t pfn);
@@ -283,6 +300,7 @@
 int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len);
 struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
 int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn);
+unsigned long kvm_host_page_size(struct kvm *kvm, gfn_t gfn);
 void mark_page_dirty(struct kvm *kvm, gfn_t gfn);
 
 void kvm_vcpu_block(struct kvm_vcpu *vcpu);
@@ -383,6 +401,7 @@
 	struct work_struct interrupt_work;
 	struct list_head list;
 	int assigned_dev_id;
+	int host_segnr;
 	int host_busnr;
 	int host_devfn;
 	unsigned int entries_nr;
@@ -429,8 +448,7 @@
 #define KVM_IOMMU_CACHE_COHERENCY	0x1
 
 #ifdef CONFIG_IOMMU_API
-int kvm_iommu_map_pages(struct kvm *kvm, gfn_t base_gfn,
-			unsigned long npages);
+int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot);
 int kvm_iommu_map_guest(struct kvm *kvm);
 int kvm_iommu_unmap_guest(struct kvm *kvm);
 int kvm_assign_device(struct kvm *kvm,
@@ -480,11 +498,6 @@
 	current->flags &= ~PF_VCPU;
 }
 
-static inline int memslot_id(struct kvm *kvm, struct kvm_memory_slot *slot)
-{
-	return slot - kvm->memslots;
-}
-
 static inline gpa_t gfn_to_gpa(gfn_t gfn)
 {
 	return (gpa_t)gfn << PAGE_SHIFT;
@@ -532,6 +545,10 @@
 }
 #endif
 
+#ifndef KVM_ARCH_HAS_UNALIAS_INSTANTIATION
+#define unalias_gfn_instantiation unalias_gfn
+#endif
+
 #ifdef CONFIG_HAVE_KVM_IRQCHIP
 
 #define KVM_MAX_IRQ_ROUTES 1024
diff --git a/include/linux/list.h b/include/linux/list.h
index 5d9c655..8392884 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -498,7 +498,7 @@
 	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
 
 /**
- * list_for_each_entry_safe_continue
+ * list_for_each_entry_safe_continue - continue list iteration safe against removal
  * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
@@ -514,7 +514,7 @@
 	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
 
 /**
- * list_for_each_entry_safe_from
+ * list_for_each_entry_safe_from - iterate over list from current point safe against removal
  * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
@@ -529,7 +529,7 @@
 	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
 
 /**
- * list_for_each_entry_safe_reverse
+ * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
  * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 10206a8..a03977a9 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -12,6 +12,10 @@
 struct task_struct;
 struct lockdep_map;
 
+/* for sysctl */
+extern int prove_locking;
+extern int lock_stat;
+
 #ifdef CONFIG_LOCKDEP
 
 #include <linux/linkage.h>
diff --git a/include/linux/lru_cache.h b/include/linux/lru_cache.h
index 3a2b2d9..de48d16 100644
--- a/include/linux/lru_cache.h
+++ b/include/linux/lru_cache.h
@@ -64,7 +64,7 @@
   usually the condition is softened to regions that _may_ have been target of
   in-flight WRITE IO, e.g. by only lazily clearing the on-disk write-intent
   bitmap, trading frequency of meta data transactions against amount of
-  (possibly unneccessary) resync traffic.
+  (possibly unnecessary) resync traffic.
 
   If we set a hard limit on the area that may be "hot" at any given time, we
   limit the amount of resync traffic needed for crash recovery.
diff --git a/include/linux/magic.h b/include/linux/magic.h
index 76285e0..eb9800f 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -52,7 +52,6 @@
 #define CGROUP_SUPER_MAGIC	0x27e0eb
 
 #define FUTEXFS_SUPER_MAGIC	0xBAD1DEA
-#define INOTIFYFS_SUPER_MAGIC	0x2BAD1DEA
 
 #define STACK_END_MAGIC		0x57AC6E9D
 
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 1f9b119..44301c6 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -124,7 +124,6 @@
 	return false;
 }
 
-extern bool mem_cgroup_oom_called(struct task_struct *task);
 void mem_cgroup_update_file_mapped(struct page *page, int val);
 unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 						gfp_t gfp_mask, int nid,
@@ -258,11 +257,6 @@
 	return true;
 }
 
-static inline bool mem_cgroup_oom_called(struct task_struct *task)
-{
-	return false;
-}
-
 static inline int
 mem_cgroup_inactive_anon_is_low(struct mem_cgroup *memcg)
 {
diff --git a/include/linux/mfd/88pm8607.h b/include/linux/mfd/88pm8607.h
deleted file mode 100644
index f41b428..0000000
--- a/include/linux/mfd/88pm8607.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Marvell 88PM8607 Interface
- *
- * Copyright (C) 2009 Marvell International Ltd.
- * 	Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __LINUX_MFD_88PM8607_H
-#define __LINUX_MFD_88PM8607_H
-
-enum {
-	PM8607_ID_BUCK1 = 0,
-	PM8607_ID_BUCK2,
-	PM8607_ID_BUCK3,
-
-	PM8607_ID_LDO1,
-	PM8607_ID_LDO2,
-	PM8607_ID_LDO3,
-	PM8607_ID_LDO4,
-	PM8607_ID_LDO5,
-	PM8607_ID_LDO6,
-	PM8607_ID_LDO7,
-	PM8607_ID_LDO8,
-	PM8607_ID_LDO9,
-	PM8607_ID_LDO10,
-	PM8607_ID_LDO12,
-	PM8607_ID_LDO14,
-
-	PM8607_ID_RG_MAX,
-};
-
-#define CHIP_ID				(0x40)
-#define CHIP_ID_MASK			(0xF8)
-
-/* Interrupt Registers */
-#define PM8607_STATUS_1			(0x01)
-#define PM8607_STATUS_2			(0x02)
-#define PM8607_INT_STATUS1		(0x03)
-#define PM8607_INT_STATUS2		(0x04)
-#define PM8607_INT_STATUS3		(0x05)
-#define PM8607_INT_MASK_1		(0x06)
-#define PM8607_INT_MASK_2		(0x07)
-#define PM8607_INT_MASK_3		(0x08)
-
-/* Regulator Control Registers */
-#define PM8607_LDO1			(0x10)
-#define PM8607_LDO2			(0x11)
-#define PM8607_LDO3			(0x12)
-#define PM8607_LDO4			(0x13)
-#define PM8607_LDO5			(0x14)
-#define PM8607_LDO6			(0x15)
-#define PM8607_LDO7			(0x16)
-#define PM8607_LDO8			(0x17)
-#define PM8607_LDO9			(0x18)
-#define PM8607_LDO10			(0x19)
-#define PM8607_LDO12			(0x1A)
-#define PM8607_LDO14			(0x1B)
-#define PM8607_SLEEP_MODE1		(0x1C)
-#define PM8607_SLEEP_MODE2		(0x1D)
-#define PM8607_SLEEP_MODE3		(0x1E)
-#define PM8607_SLEEP_MODE4		(0x1F)
-#define PM8607_GO			(0x20)
-#define PM8607_SLEEP_BUCK1		(0x21)
-#define PM8607_SLEEP_BUCK2		(0x22)
-#define PM8607_SLEEP_BUCK3		(0x23)
-#define PM8607_BUCK1			(0x24)
-#define PM8607_BUCK2			(0x25)
-#define PM8607_BUCK3			(0x26)
-#define PM8607_BUCK_CONTROLS		(0x27)
-#define PM8607_SUPPLIES_EN11		(0x2B)
-#define PM8607_SUPPLIES_EN12		(0x2C)
-#define PM8607_GROUP1			(0x2D)
-#define PM8607_GROUP2			(0x2E)
-#define PM8607_GROUP3			(0x2F)
-#define PM8607_GROUP4			(0x30)
-#define PM8607_GROUP5			(0x31)
-#define PM8607_GROUP6			(0x32)
-#define PM8607_SUPPLIES_EN21		(0x33)
-#define PM8607_SUPPLIES_EN22		(0x34)
-
-/* RTC Control Registers */
-#define PM8607_RTC1			(0xA0)
-#define PM8607_RTC_COUNTER1		(0xA1)
-#define PM8607_RTC_COUNTER2		(0xA2)
-#define PM8607_RTC_COUNTER3		(0xA3)
-#define PM8607_RTC_COUNTER4		(0xA4)
-#define PM8607_RTC_EXPIRE1		(0xA5)
-#define PM8607_RTC_EXPIRE2		(0xA6)
-#define PM8607_RTC_EXPIRE3		(0xA7)
-#define PM8607_RTC_EXPIRE4		(0xA8)
-#define PM8607_RTC_TRIM1		(0xA9)
-#define PM8607_RTC_TRIM2		(0xAA)
-#define PM8607_RTC_TRIM3		(0xAB)
-#define PM8607_RTC_TRIM4		(0xAC)
-#define PM8607_RTC_MISC1		(0xAD)
-#define PM8607_RTC_MISC2		(0xAE)
-#define PM8607_RTC_MISC3		(0xAF)
-
-/* Misc Registers */
-#define PM8607_CHIP_ID			(0x00)
-#define PM8607_LDO1			(0x10)
-#define PM8607_DVC3			(0x26)
-#define PM8607_MISC1			(0x40)
-
-/* bit definitions for PM8607 events */
-#define PM8607_EVENT_ONKEY		(1 << 0)
-#define PM8607_EVENT_EXTON		(1 << 1)
-#define PM8607_EVENT_CHG		(1 << 2)
-#define PM8607_EVENT_BAT		(1 << 3)
-#define PM8607_EVENT_RTC		(1 << 4)
-#define PM8607_EVENT_CC			(1 << 5)
-#define PM8607_EVENT_VBAT		(1 << 8)
-#define PM8607_EVENT_VCHG		(1 << 9)
-#define PM8607_EVENT_VSYS		(1 << 10)
-#define PM8607_EVENT_TINT		(1 << 11)
-#define PM8607_EVENT_GPADC0		(1 << 12)
-#define PM8607_EVENT_GPADC1		(1 << 13)
-#define PM8607_EVENT_GPADC2		(1 << 14)
-#define PM8607_EVENT_GPADC3		(1 << 15)
-#define PM8607_EVENT_AUDIO_SHORT	(1 << 16)
-#define PM8607_EVENT_PEN		(1 << 17)
-#define PM8607_EVENT_HEADSET		(1 << 18)
-#define PM8607_EVENT_HOOK		(1 << 19)
-#define PM8607_EVENT_MICIN		(1 << 20)
-#define PM8607_EVENT_CHG_TIMEOUT	(1 << 21)
-#define PM8607_EVENT_CHG_DONE		(1 << 22)
-#define PM8607_EVENT_CHG_FAULT		(1 << 23)
-
-/* bit definitions of Status Query Interface */
-#define PM8607_STATUS_CC		(1 << 3)
-#define PM8607_STATUS_PEN		(1 << 4)
-#define PM8607_STATUS_HEADSET		(1 << 5)
-#define PM8607_STATUS_HOOK		(1 << 6)
-#define PM8607_STATUS_MICIN		(1 << 7)
-#define PM8607_STATUS_ONKEY		(1 << 8)
-#define PM8607_STATUS_EXTON		(1 << 9)
-#define PM8607_STATUS_CHG		(1 << 10)
-#define PM8607_STATUS_BAT		(1 << 11)
-#define PM8607_STATUS_VBUS		(1 << 12)
-#define PM8607_STATUS_OV		(1 << 13)
-
-/* bit definitions of BUCK3 */
-#define PM8607_BUCK3_DOUBLE		(1 << 6)
-
-/* bit definitions of Misc1 */
-#define PM8607_MISC1_PI2C		(1 << 0)
-
-/* Interrupt Number in 88PM8607 */
-enum {
-	PM8607_IRQ_ONKEY = 0,
-	PM8607_IRQ_EXTON,
-	PM8607_IRQ_CHG,
-	PM8607_IRQ_BAT,
-	PM8607_IRQ_RTC,
-	PM8607_IRQ_VBAT = 8,
-	PM8607_IRQ_VCHG,
-	PM8607_IRQ_VSYS,
-	PM8607_IRQ_TINT,
-	PM8607_IRQ_GPADC0,
-	PM8607_IRQ_GPADC1,
-	PM8607_IRQ_GPADC2,
-	PM8607_IRQ_GPADC3,
-	PM8607_IRQ_AUDIO_SHORT = 16,
-	PM8607_IRQ_PEN,
-	PM8607_IRQ_HEADSET,
-	PM8607_IRQ_HOOK,
-	PM8607_IRQ_MICIN,
-	PM8607_IRQ_CHG_FAIL,
-	PM8607_IRQ_CHG_DONE,
-	PM8607_IRQ_CHG_FAULT,
-};
-
-enum {
-	PM8607_CHIP_A0 = 0x40,
-	PM8607_CHIP_A1 = 0x41,
-	PM8607_CHIP_B0 = 0x48,
-};
-
-
-struct pm8607_chip {
-	struct device		*dev;
-	struct mutex		io_lock;
-	struct i2c_client	*client;
-
-	int (*read)(struct pm8607_chip *chip, int reg, int bytes, void *dest);
-	int (*write)(struct pm8607_chip *chip, int reg, int bytes, void *src);
-
-	int			buck3_double;	/* DVC ramp slope double */
-	unsigned char		chip_id;
-
-};
-
-#define PM8607_MAX_REGULATOR	15	/* 3 Bucks, 12 LDOs */
-
-enum {
-	GI2C_PORT = 0,
-	PI2C_PORT,
-};
-
-struct pm8607_platform_data {
-	int	i2c_port;	/* Controlled by GI2C or PI2C */
-	struct regulator_init_data *regulator[PM8607_MAX_REGULATOR];
-};
-
-extern int pm8607_reg_read(struct pm8607_chip *, int);
-extern int pm8607_reg_write(struct pm8607_chip *, int, unsigned char);
-extern int pm8607_bulk_read(struct pm8607_chip *, int, int,
-			    unsigned char *);
-extern int pm8607_bulk_write(struct pm8607_chip *, int, int,
-			     unsigned char *);
-extern int pm8607_set_bits(struct pm8607_chip *, int, unsigned char,
-			   unsigned char);
-#endif /* __LINUX_MFD_88PM8607_H */
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h
new file mode 100644
index 0000000..73f92c5f
--- /dev/null
+++ b/include/linux/mfd/88pm860x.h
@@ -0,0 +1,375 @@
+/*
+ * Marvell 88PM860x Interface
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * 	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_MFD_88PM860X_H
+#define __LINUX_MFD_88PM860X_H
+
+#include <linux/interrupt.h>
+
+#define MFD_NAME_SIZE		(40)
+
+enum {
+	CHIP_INVALID = 0,
+	CHIP_PM8606,
+	CHIP_PM8607,
+	CHIP_MAX,
+};
+
+enum {
+	PM8606_ID_INVALID,
+	PM8606_ID_BACKLIGHT,
+	PM8606_ID_LED,
+	PM8606_ID_VIBRATOR,
+	PM8606_ID_TOUCH,
+	PM8606_ID_SOUND,
+	PM8606_ID_CHARGER,
+	PM8606_ID_MAX,
+};
+
+enum {
+	PM8606_BACKLIGHT1 = 0,
+	PM8606_BACKLIGHT2,
+	PM8606_BACKLIGHT3,
+};
+
+enum {
+	PM8606_LED1_RED = 0,
+	PM8606_LED1_GREEN,
+	PM8606_LED1_BLUE,
+	PM8606_LED2_RED,
+	PM8606_LED2_GREEN,
+	PM8606_LED2_BLUE,
+	PM8607_LED_VIBRATOR,
+};
+
+
+/* 8606 Registers */
+#define PM8606_DCM_BOOST		(0x00)
+#define PM8606_PWM			(0x01)
+
+/* Backlight Registers */
+#define PM8606_WLED1A			(0x02)
+#define PM8606_WLED1B			(0x03)
+#define PM8606_WLED2A			(0x04)
+#define PM8606_WLED2B			(0x05)
+#define PM8606_WLED3A			(0x06)
+#define PM8606_WLED3B			(0x07)
+
+/* LED Registers */
+#define PM8606_RGB2A			(0x08)
+#define PM8606_RGB2B			(0x09)
+#define PM8606_RGB2C			(0x0A)
+#define PM8606_RGB2D			(0x0B)
+#define PM8606_RGB1A			(0x0C)
+#define PM8606_RGB1B			(0x0D)
+#define PM8606_RGB1C			(0x0E)
+#define PM8606_RGB1D			(0x0F)
+
+#define PM8606_PREREGULATORA		(0x10)
+#define PM8606_PREREGULATORB		(0x11)
+#define PM8606_VIBRATORA		(0x12)
+#define PM8606_VIBRATORB		(0x13)
+#define PM8606_VCHG			(0x14)
+#define PM8606_VSYS			(0x15)
+#define PM8606_MISC			(0x16)
+#define PM8606_CHIP_ID			(0x17)
+#define PM8606_STATUS			(0x18)
+#define PM8606_FLAGS			(0x19)
+#define PM8606_PROTECTA			(0x1A)
+#define PM8606_PROTECTB			(0x1B)
+#define PM8606_PROTECTC			(0x1C)
+
+/* Bit definitions of PM8606 registers */
+#define PM8606_DCM_500MA		(0x0)	/* current limit */
+#define PM8606_DCM_750MA		(0x1)
+#define PM8606_DCM_1000MA		(0x2)
+#define PM8606_DCM_1250MA		(0x3)
+#define PM8606_DCM_250MV		(0x0 << 2)
+#define PM8606_DCM_300MV		(0x1 << 2)
+#define PM8606_DCM_350MV		(0x2 << 2)
+#define PM8606_DCM_400MV		(0x3 << 2)
+
+#define PM8606_PWM_31200HZ		(0x0)
+#define PM8606_PWM_15600HZ		(0x1)
+#define PM8606_PWM_7800HZ		(0x2)
+#define PM8606_PWM_3900HZ		(0x3)
+#define PM8606_PWM_1950HZ		(0x4)
+#define PM8606_PWM_976HZ		(0x5)
+#define PM8606_PWM_488HZ		(0x6)
+#define PM8606_PWM_244HZ		(0x7)
+#define PM8606_PWM_FREQ_MASK		(0x7)
+
+#define PM8606_WLED_ON			(1 << 0)
+#define PM8606_WLED_CURRENT(x)		((x & 0x1F) << 1)
+
+#define PM8606_LED_CURRENT(x)		(((x >> 2) & 0x07) << 5)
+
+#define PM8606_VSYS_EN			(1 << 1)
+
+#define PM8606_MISC_OSC_EN		(1 << 4)
+
+enum {
+	PM8607_ID_BUCK1 = 0,
+	PM8607_ID_BUCK2,
+	PM8607_ID_BUCK3,
+
+	PM8607_ID_LDO1,
+	PM8607_ID_LDO2,
+	PM8607_ID_LDO3,
+	PM8607_ID_LDO4,
+	PM8607_ID_LDO5,
+	PM8607_ID_LDO6,
+	PM8607_ID_LDO7,
+	PM8607_ID_LDO8,
+	PM8607_ID_LDO9,
+	PM8607_ID_LDO10,
+	PM8607_ID_LDO12,
+	PM8607_ID_LDO14,
+
+	PM8607_ID_RG_MAX,
+};
+
+#define PM8607_VERSION			(0x40)	/* 8607 chip ID */
+#define PM8607_VERSION_MASK		(0xF0)	/* 8607 chip ID mask */
+
+/* Interrupt Registers */
+#define PM8607_STATUS_1			(0x01)
+#define PM8607_STATUS_2			(0x02)
+#define PM8607_INT_STATUS1		(0x03)
+#define PM8607_INT_STATUS2		(0x04)
+#define PM8607_INT_STATUS3		(0x05)
+#define PM8607_INT_MASK_1		(0x06)
+#define PM8607_INT_MASK_2		(0x07)
+#define PM8607_INT_MASK_3		(0x08)
+
+/* Regulator Control Registers */
+#define PM8607_LDO1			(0x10)
+#define PM8607_LDO2			(0x11)
+#define PM8607_LDO3			(0x12)
+#define PM8607_LDO4			(0x13)
+#define PM8607_LDO5			(0x14)
+#define PM8607_LDO6			(0x15)
+#define PM8607_LDO7			(0x16)
+#define PM8607_LDO8			(0x17)
+#define PM8607_LDO9			(0x18)
+#define PM8607_LDO10			(0x19)
+#define PM8607_LDO12			(0x1A)
+#define PM8607_LDO14			(0x1B)
+#define PM8607_SLEEP_MODE1		(0x1C)
+#define PM8607_SLEEP_MODE2		(0x1D)
+#define PM8607_SLEEP_MODE3		(0x1E)
+#define PM8607_SLEEP_MODE4		(0x1F)
+#define PM8607_GO			(0x20)
+#define PM8607_SLEEP_BUCK1		(0x21)
+#define PM8607_SLEEP_BUCK2		(0x22)
+#define PM8607_SLEEP_BUCK3		(0x23)
+#define PM8607_BUCK1			(0x24)
+#define PM8607_BUCK2			(0x25)
+#define PM8607_BUCK3			(0x26)
+#define PM8607_BUCK_CONTROLS		(0x27)
+#define PM8607_SUPPLIES_EN11		(0x2B)
+#define PM8607_SUPPLIES_EN12		(0x2C)
+#define PM8607_GROUP1			(0x2D)
+#define PM8607_GROUP2			(0x2E)
+#define PM8607_GROUP3			(0x2F)
+#define PM8607_GROUP4			(0x30)
+#define PM8607_GROUP5			(0x31)
+#define PM8607_GROUP6			(0x32)
+#define PM8607_SUPPLIES_EN21		(0x33)
+#define PM8607_SUPPLIES_EN22		(0x34)
+
+/* Vibrator Control Registers */
+#define PM8607_VIBRATOR_SET		(0x28)
+#define PM8607_VIBRATOR_PWM		(0x29)
+
+/* GPADC Registers */
+#define PM8607_GP_BIAS1			(0x4F)
+#define PM8607_MEAS_EN1			(0x50)
+#define PM8607_MEAS_EN2			(0x51)
+#define PM8607_MEAS_EN3			(0x52)
+#define PM8607_MEAS_OFF_TIME1		(0x53)
+#define PM8607_MEAS_OFF_TIME2		(0x54)
+#define PM8607_TSI_PREBIAS		(0x55)	/* prebias time */
+#define PM8607_PD_PREBIAS		(0x56)	/* prebias time */
+#define PM8607_GPADC_MISC1		(0x57)
+
+/* RTC Control Registers */
+#define PM8607_RTC1			(0xA0)
+#define PM8607_RTC_COUNTER1		(0xA1)
+#define PM8607_RTC_COUNTER2		(0xA2)
+#define PM8607_RTC_COUNTER3		(0xA3)
+#define PM8607_RTC_COUNTER4		(0xA4)
+#define PM8607_RTC_EXPIRE1		(0xA5)
+#define PM8607_RTC_EXPIRE2		(0xA6)
+#define PM8607_RTC_EXPIRE3		(0xA7)
+#define PM8607_RTC_EXPIRE4		(0xA8)
+#define PM8607_RTC_TRIM1		(0xA9)
+#define PM8607_RTC_TRIM2		(0xAA)
+#define PM8607_RTC_TRIM3		(0xAB)
+#define PM8607_RTC_TRIM4		(0xAC)
+#define PM8607_RTC_MISC1		(0xAD)
+#define PM8607_RTC_MISC2		(0xAE)
+#define PM8607_RTC_MISC3		(0xAF)
+
+/* Misc Registers */
+#define PM8607_CHIP_ID			(0x00)
+#define PM8607_B0_MISC1			(0x0C)
+#define PM8607_LDO1			(0x10)
+#define PM8607_DVC3			(0x26)
+#define PM8607_A1_MISC1			(0x40)
+
+/* bit definitions of Status Query Interface */
+#define PM8607_STATUS_CC		(1 << 3)
+#define PM8607_STATUS_PEN		(1 << 4)
+#define PM8607_STATUS_HEADSET		(1 << 5)
+#define PM8607_STATUS_HOOK		(1 << 6)
+#define PM8607_STATUS_MICIN		(1 << 7)
+#define PM8607_STATUS_ONKEY		(1 << 8)
+#define PM8607_STATUS_EXTON		(1 << 9)
+#define PM8607_STATUS_CHG		(1 << 10)
+#define PM8607_STATUS_BAT		(1 << 11)
+#define PM8607_STATUS_VBUS		(1 << 12)
+#define PM8607_STATUS_OV		(1 << 13)
+
+/* bit definitions of BUCK3 */
+#define PM8607_BUCK3_DOUBLE		(1 << 6)
+
+/* bit definitions of Misc1 */
+#define PM8607_A1_MISC1_PI2C		(1 << 0)
+#define PM8607_B0_MISC1_INV_INT		(1 << 0)
+#define PM8607_B0_MISC1_INT_CLEAR	(1 << 1)
+#define PM8607_B0_MISC1_INT_MASK	(1 << 2)
+#define PM8607_B0_MISC1_PI2C		(1 << 3)
+#define PM8607_B0_MISC1_RESET		(1 << 6)
+
+/* bits definitions of GPADC */
+#define PM8607_GPADC_EN			(1 << 0)
+#define PM8607_GPADC_PREBIAS_MASK	(3 << 1)
+#define PM8607_GPADC_SLOT_CYCLE_MASK	(3 << 3)	/* slow mode */
+#define PM8607_GPADC_OFF_SCALE_MASK	(3 << 5)	/* GP sleep mode */
+#define PM8607_GPADC_SW_CAL_MASK	(1 << 7)
+
+#define PM8607_PD_PREBIAS_MASK		(0x1F << 0)
+#define PM8607_PD_PRECHG_MASK		(7 << 5)
+
+/* Interrupt Number in 88PM8607 */
+enum {
+	PM8607_IRQ_ONKEY,
+	PM8607_IRQ_EXTON,
+	PM8607_IRQ_CHG,
+	PM8607_IRQ_BAT,
+	PM8607_IRQ_RTC,
+	PM8607_IRQ_CC,
+	PM8607_IRQ_VBAT,
+	PM8607_IRQ_VCHG,
+	PM8607_IRQ_VSYS,
+	PM8607_IRQ_TINT,
+	PM8607_IRQ_GPADC0,
+	PM8607_IRQ_GPADC1,
+	PM8607_IRQ_GPADC2,
+	PM8607_IRQ_GPADC3,
+	PM8607_IRQ_AUDIO_SHORT,
+	PM8607_IRQ_PEN,
+	PM8607_IRQ_HEADSET,
+	PM8607_IRQ_HOOK,
+	PM8607_IRQ_MICIN,
+	PM8607_IRQ_CHG_FAIL,
+	PM8607_IRQ_CHG_DONE,
+	PM8607_IRQ_CHG_FAULT,
+};
+
+enum {
+	PM8607_CHIP_A0 = 0x40,
+	PM8607_CHIP_A1 = 0x41,
+	PM8607_CHIP_B0 = 0x48,
+};
+
+struct pm860x_chip {
+	struct device		*dev;
+	struct mutex		io_lock;
+	struct mutex		irq_lock;
+	struct i2c_client	*client;
+	struct i2c_client	*companion;	/* companion chip client */
+
+	int			buck3_double;	/* DVC ramp slope double */
+	unsigned short		companion_addr;
+	int			id;
+	int			irq_mode;
+	int			irq_base;
+	int			core_irq;
+	unsigned char		chip_version;
+
+};
+
+#define PM8607_MAX_REGULATOR	15	/* 3 Bucks, 12 LDOs */
+
+enum {
+	GI2C_PORT = 0,
+	PI2C_PORT,
+};
+
+struct pm860x_backlight_pdata {
+	int		id;
+	int		pwm;
+	int		iset;
+	unsigned long	flags;
+};
+
+struct pm860x_led_pdata {
+	int		id;
+	int		iset;
+	unsigned long	flags;
+};
+
+struct pm860x_touch_pdata {
+	int		gpadc_prebias;
+	int		slot_cycle;
+	int		off_scale;
+	int		sw_cal;
+	int		tsi_prebias;	/* time, slot */
+	int		pen_prebias;	/* time, slot */
+	int		pen_prechg;	/* time, slot */
+	int		res_x;		/* resistor of Xplate */
+	unsigned long	flags;
+};
+
+struct pm860x_power_pdata {
+	unsigned	fast_charge;	/* charge current */
+};
+
+struct pm860x_platform_data {
+	struct pm860x_backlight_pdata	*backlight;
+	struct pm860x_led_pdata		*led;
+	struct pm860x_touch_pdata	*touch;
+	struct pm860x_power_pdata	*power;
+
+	unsigned short	companion_addr;	/* I2C address of companion chip */
+	int		i2c_port;	/* Controlled by GI2C or PI2C */
+	int		irq_mode;	/* Clear interrupt by read/write(0/1) */
+	int		irq_base;	/* IRQ base number of 88pm860x */
+	struct regulator_init_data *regulator[PM8607_MAX_REGULATOR];
+};
+
+extern char pm860x_backlight_name[][MFD_NAME_SIZE];
+extern char pm860x_led_name[][MFD_NAME_SIZE];
+
+extern int pm860x_reg_read(struct i2c_client *, int);
+extern int pm860x_reg_write(struct i2c_client *, int, unsigned char);
+extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *);
+extern int pm860x_bulk_write(struct i2c_client *, int, int, unsigned char *);
+extern int pm860x_set_bits(struct i2c_client *, int, unsigned char,
+			   unsigned char);
+
+extern int pm860x_device_init(struct pm860x_chip *chip,
+			      struct pm860x_platform_data *pdata);
+extern void pm860x_device_exit(struct pm860x_chip *chip);
+
+#endif /* __LINUX_MFD_88PM860X_H */
diff --git a/include/linux/mfd/ab3100.h b/include/linux/mfd/ab3100.h
index e9aa4c9..9a881c3 100644
--- a/include/linux/mfd/ab3100.h
+++ b/include/linux/mfd/ab3100.h
@@ -6,7 +6,6 @@
  */
 
 #include <linux/device.h>
-#include <linux/workqueue.h>
 #include <linux/regulator/machine.h>
 
 #ifndef MFD_AB3100_H
@@ -74,7 +73,6 @@
  * @testreg_client: secondary client for test registers
  * @chip_name: name of this chip variant
  * @chip_id: 8 bit chip ID for this chip variant
- * @work: an event handling worker
  * @event_subscribers: event subscribers are listed here
  * @startup_events: a copy of the first reading of the event registers
  * @startup_events_read: whether the first events have been read
@@ -90,7 +88,6 @@
 	struct i2c_client *testreg_client;
 	char chip_name[32];
 	u8 chip_id;
-	struct work_struct work;
 	struct blocking_notifier_head event_subscribers;
 	u32 startup_events;
 	bool startup_events_read;
diff --git a/include/linux/mfd/max8925.h b/include/linux/mfd/max8925.h
new file mode 100644
index 0000000..5259dfe
--- /dev/null
+++ b/include/linux/mfd/max8925.h
@@ -0,0 +1,253 @@
+/*
+ * Maxim8925 Interface
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ *	Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_MFD_MAX8925_H
+#define __LINUX_MFD_MAX8925_H
+
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+
+/* Unified sub device IDs for MAX8925 */
+enum {
+	MAX8925_ID_SD1,
+	MAX8925_ID_SD2,
+	MAX8925_ID_SD3,
+	MAX8925_ID_LDO1,
+	MAX8925_ID_LDO2,
+	MAX8925_ID_LDO3,
+	MAX8925_ID_LDO4,
+	MAX8925_ID_LDO5,
+	MAX8925_ID_LDO6,
+	MAX8925_ID_LDO7,
+	MAX8925_ID_LDO8,
+	MAX8925_ID_LDO9,
+	MAX8925_ID_LDO10,
+	MAX8925_ID_LDO11,
+	MAX8925_ID_LDO12,
+	MAX8925_ID_LDO13,
+	MAX8925_ID_LDO14,
+	MAX8925_ID_LDO15,
+	MAX8925_ID_LDO16,
+	MAX8925_ID_LDO17,
+	MAX8925_ID_LDO18,
+	MAX8925_ID_LDO19,
+	MAX8925_ID_LDO20,
+	MAX8925_ID_MAX,
+};
+
+enum {
+	/*
+	 * Charging current threshold trigger going from fast charge
+	 * to TOPOFF charge. From 5% to 20% of fasting charging current.
+	 */
+	MAX8925_TOPOFF_THR_5PER,
+	MAX8925_TOPOFF_THR_10PER,
+	MAX8925_TOPOFF_THR_15PER,
+	MAX8925_TOPOFF_THR_20PER,
+};
+
+enum {
+	/* Fast charging current */
+	MAX8925_FCHG_85MA,
+	MAX8925_FCHG_300MA,
+	MAX8925_FCHG_460MA,
+	MAX8925_FCHG_600MA,
+	MAX8925_FCHG_700MA,
+	MAX8925_FCHG_800MA,
+	MAX8925_FCHG_900MA,
+	MAX8925_FCHG_1000MA,
+};
+
+/* Charger registers */
+#define MAX8925_CHG_IRQ1		(0x7e)
+#define MAX8925_CHG_IRQ2		(0x7f)
+#define MAX8925_CHG_IRQ1_MASK		(0x80)
+#define MAX8925_CHG_IRQ2_MASK		(0x81)
+#define MAX8925_CHG_STATUS		(0x82)
+
+/* GPM registers */
+#define MAX8925_SYSENSEL		(0x00)
+#define MAX8925_ON_OFF_IRQ1		(0x01)
+#define MAX8925_ON_OFF_IRQ1_MASK	(0x02)
+#define MAX8925_ON_OFF_STATUS		(0x03)
+#define MAX8925_ON_OFF_IRQ2		(0x0d)
+#define MAX8925_ON_OFF_IRQ2_MASK	(0x0e)
+#define MAX8925_RESET_CNFG		(0x0f)
+
+/* Touch registers */
+#define MAX8925_TSC_IRQ			(0x00)
+#define MAX8925_TSC_IRQ_MASK		(0x01)
+#define MAX8925_TSC_CNFG1		(0x02)
+#define MAX8925_ADC_SCHED		(0x10)
+#define MAX8925_ADC_RES_END		(0x6f)
+
+#define MAX8925_NREF_OK			(1 << 4)
+
+/* RTC registers */
+#define MAX8925_ALARM0_CNTL		(0x18)
+#define MAX8925_ALARM1_CNTL		(0x19)
+#define MAX8925_RTC_IRQ			(0x1c)
+#define MAX8925_RTC_IRQ_MASK		(0x1d)
+#define MAX8925_MPL_CNTL		(0x1e)
+
+/* WLED registers */
+#define MAX8925_WLED_MODE_CNTL		(0x84)
+#define MAX8925_WLED_CNTL		(0x85)
+
+/* MAX8925 Registers */
+#define MAX8925_SDCTL1			(0x04)
+#define MAX8925_SDCTL2			(0x07)
+#define MAX8925_SDCTL3			(0x0A)
+#define MAX8925_SDV1			(0x06)
+#define MAX8925_SDV2			(0x09)
+#define MAX8925_SDV3			(0x0C)
+#define MAX8925_LDOCTL1			(0x18)
+#define MAX8925_LDOCTL2			(0x1C)
+#define MAX8925_LDOCTL3			(0x20)
+#define MAX8925_LDOCTL4			(0x24)
+#define MAX8925_LDOCTL5			(0x28)
+#define MAX8925_LDOCTL6			(0x2C)
+#define MAX8925_LDOCTL7			(0x30)
+#define MAX8925_LDOCTL8			(0x34)
+#define MAX8925_LDOCTL9			(0x38)
+#define MAX8925_LDOCTL10		(0x3C)
+#define MAX8925_LDOCTL11		(0x40)
+#define MAX8925_LDOCTL12		(0x44)
+#define MAX8925_LDOCTL13		(0x48)
+#define MAX8925_LDOCTL14		(0x4C)
+#define MAX8925_LDOCTL15		(0x50)
+#define MAX8925_LDOCTL16		(0x10)
+#define MAX8925_LDOCTL17		(0x14)
+#define MAX8925_LDOCTL18		(0x72)
+#define MAX8925_LDOCTL19		(0x5C)
+#define MAX8925_LDOCTL20		(0x9C)
+#define MAX8925_LDOVOUT1		(0x1A)
+#define MAX8925_LDOVOUT2		(0x1E)
+#define MAX8925_LDOVOUT3		(0x22)
+#define MAX8925_LDOVOUT4		(0x26)
+#define MAX8925_LDOVOUT5		(0x2A)
+#define MAX8925_LDOVOUT6		(0x2E)
+#define MAX8925_LDOVOUT7		(0x32)
+#define MAX8925_LDOVOUT8		(0x36)
+#define MAX8925_LDOVOUT9		(0x3A)
+#define MAX8925_LDOVOUT10		(0x3E)
+#define MAX8925_LDOVOUT11		(0x42)
+#define MAX8925_LDOVOUT12		(0x46)
+#define MAX8925_LDOVOUT13		(0x4A)
+#define MAX8925_LDOVOUT14		(0x4E)
+#define MAX8925_LDOVOUT15		(0x52)
+#define MAX8925_LDOVOUT16		(0x12)
+#define MAX8925_LDOVOUT17		(0x16)
+#define MAX8925_LDOVOUT18		(0x74)
+#define MAX8925_LDOVOUT19		(0x5E)
+#define MAX8925_LDOVOUT20		(0x9E)
+
+/* bit definitions */
+#define CHG_IRQ1_MASK			(0x07)
+#define CHG_IRQ2_MASK			(0xff)
+#define ON_OFF_IRQ1_MASK		(0xff)
+#define ON_OFF_IRQ2_MASK		(0x03)
+#define TSC_IRQ_MASK			(0x03)
+#define RTC_IRQ_MASK			(0x0c)
+
+#define MAX8925_MAX_REGULATOR		(23)
+
+#define MAX8925_NAME_SIZE		(32)
+
+/* IRQ definitions */
+enum {
+	MAX8925_IRQ_VCHG_DC_OVP,
+	MAX8925_IRQ_VCHG_DC_F,
+	MAX8925_IRQ_VCHG_DC_R,
+	MAX8925_IRQ_VCHG_USB_OVP,
+	MAX8925_IRQ_VCHG_USB_F,
+	MAX8925_IRQ_VCHG_USB_R,
+	MAX8925_IRQ_VCHG_THM_OK_R,
+	MAX8925_IRQ_VCHG_THM_OK_F,
+	MAX8925_IRQ_VCHG_SYSLOW_F,
+	MAX8925_IRQ_VCHG_SYSLOW_R,
+	MAX8925_IRQ_VCHG_RST,
+	MAX8925_IRQ_VCHG_DONE,
+	MAX8925_IRQ_VCHG_TOPOFF,
+	MAX8925_IRQ_VCHG_TMR_FAULT,
+	MAX8925_IRQ_GPM_RSTIN,
+	MAX8925_IRQ_GPM_MPL,
+	MAX8925_IRQ_GPM_SW_3SEC,
+	MAX8925_IRQ_GPM_EXTON_F,
+	MAX8925_IRQ_GPM_EXTON_R,
+	MAX8925_IRQ_GPM_SW_1SEC,
+	MAX8925_IRQ_GPM_SW_F,
+	MAX8925_IRQ_GPM_SW_R,
+	MAX8925_IRQ_GPM_SYSCKEN_F,
+	MAX8925_IRQ_GPM_SYSCKEN_R,
+	MAX8925_IRQ_RTC_ALARM1,
+	MAX8925_IRQ_RTC_ALARM0,
+	MAX8925_IRQ_TSC_STICK,
+	MAX8925_IRQ_TSC_NSTICK,
+	MAX8925_NR_IRQS,
+};
+
+struct max8925_chip {
+	struct device		*dev;
+	struct i2c_client	*i2c;
+	struct i2c_client	*adc;
+	struct i2c_client	*rtc;
+	struct mutex		io_lock;
+	struct mutex		irq_lock;
+
+	int			irq_base;
+	int			core_irq;
+	int			tsc_irq;
+};
+
+struct max8925_backlight_pdata {
+	int	lxw_scl;	/* 0/1 -- 0.8Ohm/0.4Ohm */
+	int	lxw_freq;	/* 700KHz ~ 1400KHz */
+	int	dual_string;	/* 0/1 -- single/dual string */
+};
+
+struct max8925_touch_pdata {
+	unsigned int		flags;
+};
+
+struct max8925_power_pdata {
+	int		(*set_charger)(int);
+	unsigned	batt_detect:1;
+	unsigned	topoff_threshold:2;
+	unsigned	fast_charge:3;	/* charge current */
+};
+
+/*
+ * irq_base: stores IRQ base number of MAX8925 in platform
+ * tsc_irq: stores IRQ number of MAX8925 TSC
+ */
+struct max8925_platform_data {
+	struct max8925_backlight_pdata	*backlight;
+	struct max8925_touch_pdata	*touch;
+	struct max8925_power_pdata	*power;
+	struct regulator_init_data	*regulator[MAX8925_MAX_REGULATOR];
+
+	int		irq_base;
+	int		tsc_irq;
+};
+
+extern int max8925_reg_read(struct i2c_client *, int);
+extern int max8925_reg_write(struct i2c_client *, int, unsigned char);
+extern int max8925_bulk_read(struct i2c_client *, int, int, unsigned char *);
+extern int max8925_bulk_write(struct i2c_client *, int, int, unsigned char *);
+extern int max8925_set_bits(struct i2c_client *, int, unsigned char,
+			unsigned char);
+
+extern int max8925_device_init(struct max8925_chip *,
+				struct max8925_platform_data *);
+extern void max8925_device_exit(struct max8925_chip *);
+#endif /* __LINUX_MFD_MAX8925_H */
+
diff --git a/include/linux/mfd/mc13783.h b/include/linux/mfd/mc13783.h
index 3568040..8895d9d 100644
--- a/include/linux/mfd/mc13783.h
+++ b/include/linux/mfd/mc13783.h
@@ -26,10 +26,30 @@
 int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq,
 		irq_handler_t handler, const char *name, void *dev);
 int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev);
-int mc13783_ackirq(struct mc13783 *mc13783, int irq);
 
-int mc13783_mask(struct mc13783 *mc13783, int irq);
-int mc13783_unmask(struct mc13783 *mc13783, int irq);
+int mc13783_irq_mask(struct mc13783 *mc13783, int irq);
+int mc13783_irq_unmask(struct mc13783 *mc13783, int irq);
+int mc13783_irq_status(struct mc13783 *mc13783, int irq,
+		int *enabled, int *pending);
+int mc13783_irq_ack(struct mc13783 *mc13783, int irq);
+
+static inline int mc13783_mask(struct mc13783 *mc13783, int irq) __deprecated;
+static inline int mc13783_mask(struct mc13783 *mc13783, int irq)
+{
+	return mc13783_irq_mask(mc13783, irq);
+}
+
+static inline int mc13783_unmask(struct mc13783 *mc13783, int irq) __deprecated;
+static inline int mc13783_unmask(struct mc13783 *mc13783, int irq)
+{
+	return mc13783_irq_unmask(mc13783, irq);
+}
+
+static inline int mc13783_ackirq(struct mc13783 *mc13783, int irq) __deprecated;
+static inline int mc13783_ackirq(struct mc13783 *mc13783, int irq)
+{
+	return mc13783_irq_ack(mc13783, irq);
+}
 
 #define MC13783_ADC0		43
 #define MC13783_ADC0_ADREFEN		(1 << 10)
@@ -108,6 +128,8 @@
 #define	MC13783_REGU_V2		28
 #define	MC13783_REGU_V3		29
 #define	MC13783_REGU_V4		30
+#define	MC13783_REGU_PWGT1SPI	31
+#define	MC13783_REGU_PWGT2SPI	32
 
 #define MC13783_IRQ_ADCDONE	0
 #define MC13783_IRQ_ADCBISDONE	1
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index 9cb1834..c3f7dff 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -59,7 +59,8 @@
  * data for the MMC controller
  */
 struct tmio_mmc_data {
-	const unsigned int		hclk;
+	unsigned int			hclk;
+	unsigned long			capabilities;
 	void (*set_pwr)(struct platform_device *host, int state);
 	void (*set_clk_div)(struct platform_device *host, int state);
 };
diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h
index aa9c378..4321f04 100644
--- a/include/linux/mfd/ucb1x00.h
+++ b/include/linux/mfd/ucb1x00.h
@@ -12,6 +12,7 @@
 
 #include <linux/mfd/mcp.h>
 #include <linux/gpio.h>
+#include <linux/semaphore.h>
 
 #define UCB_IO_DATA	0x00
 #define UCB_IO_DIR	0x01
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h
index 5184b79..5915f6e 100644
--- a/include/linux/mfd/wm831x/core.h
+++ b/include/linux/mfd/wm831x/core.h
@@ -15,6 +15,7 @@
 #ifndef __MFD_WM831X_CORE_H__
 #define __MFD_WM831X_CORE_H__
 
+#include <linux/completion.h>
 #include <linux/interrupt.h>
 
 /*
@@ -254,9 +255,14 @@
 	int irq_masks_cur[WM831X_NUM_IRQ_REGS];   /* Currently active value */
 	int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */
 
+	/* Chip revision based flags */
+	unsigned has_gpio_ena:1;  /* Has GPIO enable bit */
+	unsigned has_cs_sts:1;    /* Has current sink status bit */
+
 	int num_gpio;
 
 	struct mutex auxadc_lock;
+	struct completion auxadc_done;
 
 	/* The WM831x has a security key blocking access to certain
 	 * registers.  The mutex is taken by the accessors for locking
diff --git a/include/linux/mfd/wm831x/gpio.h b/include/linux/mfd/wm831x/gpio.h
index 2835614..9b163c5 100644
--- a/include/linux/mfd/wm831x/gpio.h
+++ b/include/linux/mfd/wm831x/gpio.h
@@ -41,6 +41,10 @@
 #define WM831X_GPN_OD_MASK                      0x0200  /* GPN_OD */
 #define WM831X_GPN_OD_SHIFT                          9  /* GPN_OD */
 #define WM831X_GPN_OD_WIDTH                          1  /* GPN_OD */
+#define WM831X_GPN_ENA                          0x0080  /* GPN_ENA */
+#define WM831X_GPN_ENA_MASK                     0x0080  /* GPN_ENA */
+#define WM831X_GPN_ENA_SHIFT                         7  /* GPN_ENA */
+#define WM831X_GPN_ENA_WIDTH                         1  /* GPN_ENA */
 #define WM831X_GPN_TRI                          0x0080  /* GPN_TRI */
 #define WM831X_GPN_TRI_MASK                     0x0080  /* GPN_TRI */
 #define WM831X_GPN_TRI_SHIFT                         7  /* GPN_TRI */
diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h
index 4386889..98fcc97 100644
--- a/include/linux/mfd/wm8350/core.h
+++ b/include/linux/mfd/wm8350/core.h
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/mutex.h>
 #include <linux/interrupt.h>
+#include <linux/completion.h>
 
 #include <linux/mfd/wm8350/audio.h>
 #include <linux/mfd/wm8350/gpio.h>
@@ -579,6 +580,8 @@
 
 #define WM8350_NUM_IRQ				63
 
+#define WM8350_NUM_IRQ_REGS 7
+
 struct wm8350_reg_access {
 	u16 readable;		/* Mask of readable bits */
 	u16 writable;		/* Mask of writable bits */
@@ -600,11 +603,6 @@
 
 struct wm8350;
 
-struct wm8350_irq {
-	irq_handler_t handler;
-	void *data;
-};
-
 struct wm8350_hwmon {
 	struct platform_device *pdev;
 	struct device *classdev;
@@ -624,11 +622,13 @@
 	u16 *reg_cache;
 
 	struct mutex auxadc_mutex;
+	struct completion auxadc_done;
 
 	/* Interrupt handling */
-	struct mutex irq_mutex; /* IRQ table mutex */
-	struct wm8350_irq irq[WM8350_NUM_IRQ];
+	struct mutex irq_lock;
 	int chip_irq;
+	int irq_base;
+	u16 irq_masks[WM8350_NUM_IRQ_REGS];
 
 	/* Client devices */
 	struct wm8350_codec codec;
@@ -647,11 +647,13 @@
  *        used by the platform to configure GPIO functions and similar.
  * @irq_high: Set if WM8350 IRQ is active high.
  * @irq_base: Base IRQ for genirq (not currently used).
+ * @gpio_base: Base for gpiolib.
  */
 struct wm8350_platform_data {
 	int (*init)(struct wm8350 *wm8350);
 	int irq_high;
 	int irq_base;
+	int gpio_base;
 };
 
 
@@ -677,12 +679,33 @@
 /*
  * WM8350 internal interrupts
  */
-int wm8350_register_irq(struct wm8350 *wm8350, int irq,
-			irq_handler_t handler, unsigned long flags,
-			const char *name, void *data);
-int wm8350_free_irq(struct wm8350 *wm8350, int irq);
-int wm8350_mask_irq(struct wm8350 *wm8350, int irq);
-int wm8350_unmask_irq(struct wm8350 *wm8350, int irq);
+static inline int wm8350_register_irq(struct wm8350 *wm8350, int irq,
+				      irq_handler_t handler,
+				      unsigned long flags,
+				      const char *name, void *data)
+{
+	if (!wm8350->irq_base)
+		return -ENODEV;
+
+	return request_threaded_irq(irq + wm8350->irq_base, NULL,
+				    handler, flags, name, data);
+}
+
+static inline void wm8350_free_irq(struct wm8350 *wm8350, int irq, void *data)
+{
+	free_irq(irq + wm8350->irq_base, data);
+}
+
+static inline void wm8350_mask_irq(struct wm8350 *wm8350, int irq)
+{
+	disable_irq(irq + wm8350->irq_base);
+}
+
+static inline void wm8350_unmask_irq(struct wm8350 *wm8350, int irq)
+{
+	enable_irq(irq + wm8350->irq_base);
+}
+
 int wm8350_irq_init(struct wm8350 *wm8350, int irq,
 		    struct wm8350_platform_data *pdata);
 int wm8350_irq_exit(struct wm8350 *wm8350);
diff --git a/include/linux/mfd/wm8350/gpio.h b/include/linux/mfd/wm8350/gpio.h
index 71af3d6..d657bcd 100644
--- a/include/linux/mfd/wm8350/gpio.h
+++ b/include/linux/mfd/wm8350/gpio.h
@@ -29,6 +29,7 @@
 #define WM8350_GPIO_FUNCTION_SELECT_2           0x8D
 #define WM8350_GPIO_FUNCTION_SELECT_3           0x8E
 #define WM8350_GPIO_FUNCTION_SELECT_4           0x8F
+#define WM8350_GPIO_LEVEL			0xE6
 
 /*
  * GPIO Functions
diff --git a/include/linux/mfd/wm8350/rtc.h b/include/linux/mfd/wm8350/rtc.h
index 24add2b..ebd72ff 100644
--- a/include/linux/mfd/wm8350/rtc.h
+++ b/include/linux/mfd/wm8350/rtc.h
@@ -263,6 +263,7 @@
 	struct platform_device *pdev;
 	struct rtc_device *rtc;
 	int alarm_enabled;      /* used over suspend/resume */
+	int update_enabled;
 };
 
 #endif
diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h
new file mode 100644
index 0000000..b06ff28
--- /dev/null
+++ b/include/linux/mfd/wm8994/core.h
@@ -0,0 +1,54 @@
+/*
+ * include/linux/mfd/wm8994/core.h -- Core interface for WM8994
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __MFD_WM8994_CORE_H__
+#define __MFD_WM8994_CORE_H__
+
+struct regulator_dev;
+struct regulator_bulk_data;
+
+#define WM8994_NUM_GPIO_REGS 11
+#define WM8994_NUM_LDO_REGS 2
+
+struct wm8994 {
+	struct mutex io_lock;
+
+	struct device *dev;
+	int (*read_dev)(struct wm8994 *wm8994, unsigned short reg,
+			int bytes, void *dest);
+	int (*write_dev)(struct wm8994 *wm8994, unsigned short reg,
+			 int bytes, void *src);
+
+	void *control_data;
+
+	int gpio_base;
+
+	/* Used over suspend/resume */
+	u16 ldo_regs[WM8994_NUM_LDO_REGS];
+	u16 gpio_regs[WM8994_NUM_GPIO_REGS];
+
+	struct regulator_dev *dbvdd;
+	struct regulator_bulk_data *supplies;
+};
+
+/* Device I/O API */
+int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg);
+int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
+		 unsigned short val);
+int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
+		    unsigned short mask, unsigned short val);
+int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
+		     int count, u16 *buf);
+
+#endif
diff --git a/include/linux/mfd/wm8994/gpio.h b/include/linux/mfd/wm8994/gpio.h
new file mode 100644
index 0000000..b4d4c22
--- /dev/null
+++ b/include/linux/mfd/wm8994/gpio.h
@@ -0,0 +1,72 @@
+/*
+ * include/linux/mfd/wm8994/gpio.h - GPIO configuration for WM8994
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __MFD_WM8994_GPIO_H__
+#define __MFD_WM8994_GPIO_H__
+
+#define WM8994_GPIO_MAX 11
+
+#define WM8994_GP_FN_PIN_SPECIFIC    0
+#define WM8994_GP_FN_GPIO            1
+#define WM8994_GP_FN_SDOUT           2
+#define WM8994_GP_FN_IRQ             3
+#define WM8994_GP_FN_TEMPERATURE     4
+#define WM8994_GP_FN_MICBIAS1_DET    5
+#define WM8994_GP_FN_MICBIAS1_SHORT  6
+#define WM8994_GP_FN_MICBIAS2_DET    7
+#define WM8994_GP_FN_MICBIAS2_SHORT  8
+#define WM8994_GP_FN_FLL1_LOCK       9
+#define WM8994_GP_FN_FLL2_LOCK      10
+#define WM8994_GP_FN_SRC1_LOCK      11
+#define WM8994_GP_FN_SRC2_LOCK      12
+#define WM8994_GP_FN_DRC1_ACT       13
+#define WM8994_GP_FN_DRC2_ACT       14
+#define WM8994_GP_FN_DRC3_ACT       15
+#define WM8994_GP_FN_WSEQ_STATUS    16
+#define WM8994_GP_FN_FIFO_ERROR     17
+#define WM8994_GP_FN_OPCLK          18
+
+#define WM8994_GPN_DIR                          0x8000  /* GPN_DIR */
+#define WM8994_GPN_DIR_MASK                     0x8000  /* GPN_DIR */
+#define WM8994_GPN_DIR_SHIFT                        15  /* GPN_DIR */
+#define WM8994_GPN_DIR_WIDTH                         1  /* GPN_DIR */
+#define WM8994_GPN_PU                           0x4000  /* GPN_PU */
+#define WM8994_GPN_PU_MASK                      0x4000  /* GPN_PU */
+#define WM8994_GPN_PU_SHIFT                         14  /* GPN_PU */
+#define WM8994_GPN_PU_WIDTH                          1  /* GPN_PU */
+#define WM8994_GPN_PD                           0x2000  /* GPN_PD */
+#define WM8994_GPN_PD_MASK                      0x2000  /* GPN_PD */
+#define WM8994_GPN_PD_SHIFT                         13  /* GPN_PD */
+#define WM8994_GPN_PD_WIDTH                          1  /* GPN_PD */
+#define WM8994_GPN_POL                          0x0400  /* GPN_POL */
+#define WM8994_GPN_POL_MASK                     0x0400  /* GPN_POL */
+#define WM8994_GPN_POL_SHIFT                        10  /* GPN_POL */
+#define WM8994_GPN_POL_WIDTH                         1  /* GPN_POL */
+#define WM8994_GPN_OP_CFG                       0x0200  /* GPN_OP_CFG */
+#define WM8994_GPN_OP_CFG_MASK                  0x0200  /* GPN_OP_CFG */
+#define WM8994_GPN_OP_CFG_SHIFT                      9  /* GPN_OP_CFG */
+#define WM8994_GPN_OP_CFG_WIDTH                      1  /* GPN_OP_CFG */
+#define WM8994_GPN_DB                           0x0100  /* GPN_DB */
+#define WM8994_GPN_DB_MASK                      0x0100  /* GPN_DB */
+#define WM8994_GPN_DB_SHIFT                          8  /* GPN_DB */
+#define WM8994_GPN_DB_WIDTH                          1  /* GPN_DB */
+#define WM8994_GPN_LVL                          0x0040  /* GPN_LVL */
+#define WM8994_GPN_LVL_MASK                     0x0040  /* GPN_LVL */
+#define WM8994_GPN_LVL_SHIFT                         6  /* GPN_LVL */
+#define WM8994_GPN_LVL_WIDTH                         1  /* GPN_LVL */
+#define WM8994_GPN_FN_MASK                      0x001F  /* GPN_FN - [4:0] */
+#define WM8994_GPN_FN_SHIFT                          0  /* GPN_FN - [4:0] */
+#define WM8994_GPN_FN_WIDTH                          5  /* GPN_FN - [4:0] */
+
+#endif
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
new file mode 100644
index 0000000..70d6a86
--- /dev/null
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -0,0 +1,97 @@
+/*
+ * include/linux/mfd/wm8994/pdata.h -- Platform data for WM8994
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __MFD_WM8994_PDATA_H__
+#define __MFD_WM8994_PDATA_H__
+
+#define WM8994_NUM_LDO   2
+#define WM8994_NUM_GPIO 11
+
+struct wm8994_ldo_pdata {
+	/** GPIOs to enable regulator, 0 or less if not available */
+	int enable;
+
+	const char *supply;
+	struct regulator_init_data *init_data;
+};
+
+#define WM8994_CONFIGURE_GPIO 0x8000
+
+#define WM8994_DRC_REGS 5
+#define WM8994_EQ_REGS  19
+
+/**
+ * DRC configurations are specified with a label and a set of register
+ * values to write (the enable bits will be ignored).  At runtime an
+ * enumerated control will be presented for each DRC block allowing
+ * the user to choose the configration to use.
+ *
+ * Configurations may be generated by hand or by using the DRC control
+ * panel provided by the WISCE - see  http://www.wolfsonmicro.com/wisce/
+ * for details.
+ */
+struct wm8994_drc_cfg {
+        const char *name;
+        u16 regs[WM8994_DRC_REGS];
+};
+
+/**
+ * ReTune Mobile configurations are specified with a label, sample
+ * rate and set of values to write (the enable bits will be ignored).
+ *
+ * Configurations are expected to be generated using the ReTune Mobile
+ * control panel in WISCE - see http://www.wolfsonmicro.com/wisce/
+ */
+struct wm8994_retune_mobile_cfg {
+        const char *name;
+        unsigned int rate;
+        u16 regs[WM8994_EQ_REGS];
+};
+
+struct wm8994_pdata {
+	int gpio_base;
+
+	/**
+	 * Default values for GPIOs if non-zero, WM8994_CONFIGURE_GPIO
+	 * can be used for all zero values.
+	 */
+	int gpio_defaults[WM8994_NUM_GPIO];
+
+	struct wm8994_ldo_pdata ldo[WM8994_NUM_LDO];
+
+
+        int num_drc_cfgs;
+        struct wm8994_drc_cfg *drc_cfgs;
+
+        int num_retune_mobile_cfgs;
+        struct wm8994_retune_mobile_cfg *retune_mobile_cfgs;
+
+        /* LINEOUT can be differential or single ended */
+        unsigned int lineout1_diff:1;
+        unsigned int lineout2_diff:1;
+
+        /* Common mode feedback */
+        unsigned int lineout1fb:1;
+        unsigned int lineout2fb:1;
+
+        /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */
+        unsigned int micbias1_lvl:1;
+        unsigned int micbias2_lvl:1;
+
+        /* Jack detect threashold levels, see datasheet for values */
+        unsigned int jd_scthr:2;
+        unsigned int jd_thr:2;
+};
+
+#endif
diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h
new file mode 100644
index 0000000..967f62f
--- /dev/null
+++ b/include/linux/mfd/wm8994/registers.h
@@ -0,0 +1,4292 @@
+/*
+ * include/linux/mfd/wm8994/registers.h -- Register definitions for WM8994
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __MFD_WM8994_REGISTERS_H__
+#define __MFD_WM8994_REGISTERS_H__
+
+/*
+ * Register values.
+ */
+#define WM8994_SOFTWARE_RESET                   0x00
+#define WM8994_POWER_MANAGEMENT_1               0x01
+#define WM8994_POWER_MANAGEMENT_2               0x02
+#define WM8994_POWER_MANAGEMENT_3               0x03
+#define WM8994_POWER_MANAGEMENT_4               0x04
+#define WM8994_POWER_MANAGEMENT_5               0x05
+#define WM8994_POWER_MANAGEMENT_6               0x06
+#define WM8994_INPUT_MIXER_1                    0x15
+#define WM8994_LEFT_LINE_INPUT_1_2_VOLUME       0x18
+#define WM8994_LEFT_LINE_INPUT_3_4_VOLUME       0x19
+#define WM8994_RIGHT_LINE_INPUT_1_2_VOLUME      0x1A
+#define WM8994_RIGHT_LINE_INPUT_3_4_VOLUME      0x1B
+#define WM8994_LEFT_OUTPUT_VOLUME               0x1C
+#define WM8994_RIGHT_OUTPUT_VOLUME              0x1D
+#define WM8994_LINE_OUTPUTS_VOLUME              0x1E
+#define WM8994_HPOUT2_VOLUME                    0x1F
+#define WM8994_LEFT_OPGA_VOLUME                 0x20
+#define WM8994_RIGHT_OPGA_VOLUME                0x21
+#define WM8994_SPKMIXL_ATTENUATION              0x22
+#define WM8994_SPKMIXR_ATTENUATION              0x23
+#define WM8994_SPKOUT_MIXERS                    0x24
+#define WM8994_CLASSD                           0x25
+#define WM8994_SPEAKER_VOLUME_LEFT              0x26
+#define WM8994_SPEAKER_VOLUME_RIGHT             0x27
+#define WM8994_INPUT_MIXER_2                    0x28
+#define WM8994_INPUT_MIXER_3                    0x29
+#define WM8994_INPUT_MIXER_4                    0x2A
+#define WM8994_INPUT_MIXER_5                    0x2B
+#define WM8994_INPUT_MIXER_6                    0x2C
+#define WM8994_OUTPUT_MIXER_1                   0x2D
+#define WM8994_OUTPUT_MIXER_2                   0x2E
+#define WM8994_OUTPUT_MIXER_3                   0x2F
+#define WM8994_OUTPUT_MIXER_4                   0x30
+#define WM8994_OUTPUT_MIXER_5                   0x31
+#define WM8994_OUTPUT_MIXER_6                   0x32
+#define WM8994_HPOUT2_MIXER                     0x33
+#define WM8994_LINE_MIXER_1                     0x34
+#define WM8994_LINE_MIXER_2                     0x35
+#define WM8994_SPEAKER_MIXER                    0x36
+#define WM8994_ADDITIONAL_CONTROL               0x37
+#define WM8994_ANTIPOP_1                        0x38
+#define WM8994_ANTIPOP_2                        0x39
+#define WM8994_MICBIAS                          0x3A
+#define WM8994_LDO_1                            0x3B
+#define WM8994_LDO_2                            0x3C
+#define WM8994_CHARGE_PUMP_1                    0x4C
+#define WM8994_CLASS_W_1                        0x51
+#define WM8994_DC_SERVO_1                       0x54
+#define WM8994_DC_SERVO_2                       0x55
+#define WM8994_DC_SERVO_4                       0x57
+#define WM8994_DC_SERVO_READBACK                0x58
+#define WM8994_ANALOGUE_HP_1                    0x60
+#define WM8994_CHIP_REVISION                    0x100
+#define WM8994_CONTROL_INTERFACE                0x101
+#define WM8994_WRITE_SEQUENCER_CTRL_1           0x110
+#define WM8994_WRITE_SEQUENCER_CTRL_2           0x111
+#define WM8994_AIF1_CLOCKING_1                  0x200
+#define WM8994_AIF1_CLOCKING_2                  0x201
+#define WM8994_AIF2_CLOCKING_1                  0x204
+#define WM8994_AIF2_CLOCKING_2                  0x205
+#define WM8994_CLOCKING_1                       0x208
+#define WM8994_CLOCKING_2                       0x209
+#define WM8994_AIF1_RATE                        0x210
+#define WM8994_AIF2_RATE                        0x211
+#define WM8994_RATE_STATUS                      0x212
+#define WM8994_FLL1_CONTROL_1                   0x220
+#define WM8994_FLL1_CONTROL_2                   0x221
+#define WM8994_FLL1_CONTROL_3                   0x222
+#define WM8994_FLL1_CONTROL_4                   0x223
+#define WM8994_FLL1_CONTROL_5                   0x224
+#define WM8994_FLL2_CONTROL_1                   0x240
+#define WM8994_FLL2_CONTROL_2                   0x241
+#define WM8994_FLL2_CONTROL_3                   0x242
+#define WM8994_FLL2_CONTROL_4                   0x243
+#define WM8994_FLL2_CONTROL_5                   0x244
+#define WM8994_AIF1_CONTROL_1                   0x300
+#define WM8994_AIF1_CONTROL_2                   0x301
+#define WM8994_AIF1_MASTER_SLAVE                0x302
+#define WM8994_AIF1_BCLK                        0x303
+#define WM8994_AIF1ADC_LRCLK                    0x304
+#define WM8994_AIF1DAC_LRCLK                    0x305
+#define WM8994_AIF1DAC_DATA                     0x306
+#define WM8994_AIF1ADC_DATA                     0x307
+#define WM8994_AIF2_CONTROL_1                   0x310
+#define WM8994_AIF2_CONTROL_2                   0x311
+#define WM8994_AIF2_MASTER_SLAVE                0x312
+#define WM8994_AIF2_BCLK                        0x313
+#define WM8994_AIF2ADC_LRCLK                    0x314
+#define WM8994_AIF2DAC_LRCLK                    0x315
+#define WM8994_AIF2DAC_DATA                     0x316
+#define WM8994_AIF2ADC_DATA                     0x317
+#define WM8994_AIF1_ADC1_LEFT_VOLUME            0x400
+#define WM8994_AIF1_ADC1_RIGHT_VOLUME           0x401
+#define WM8994_AIF1_DAC1_LEFT_VOLUME            0x402
+#define WM8994_AIF1_DAC1_RIGHT_VOLUME           0x403
+#define WM8994_AIF1_ADC2_LEFT_VOLUME            0x404
+#define WM8994_AIF1_ADC2_RIGHT_VOLUME           0x405
+#define WM8994_AIF1_DAC2_LEFT_VOLUME            0x406
+#define WM8994_AIF1_DAC2_RIGHT_VOLUME           0x407
+#define WM8994_AIF1_ADC1_FILTERS                0x410
+#define WM8994_AIF1_ADC2_FILTERS                0x411
+#define WM8994_AIF1_DAC1_FILTERS_1              0x420
+#define WM8994_AIF1_DAC1_FILTERS_2              0x421
+#define WM8994_AIF1_DAC2_FILTERS_1              0x422
+#define WM8994_AIF1_DAC2_FILTERS_2              0x423
+#define WM8994_AIF1_DRC1_1                      0x440
+#define WM8994_AIF1_DRC1_2                      0x441
+#define WM8994_AIF1_DRC1_3                      0x442
+#define WM8994_AIF1_DRC1_4                      0x443
+#define WM8994_AIF1_DRC1_5                      0x444
+#define WM8994_AIF1_DRC2_1                      0x450
+#define WM8994_AIF1_DRC2_2                      0x451
+#define WM8994_AIF1_DRC2_3                      0x452
+#define WM8994_AIF1_DRC2_4                      0x453
+#define WM8994_AIF1_DRC2_5                      0x454
+#define WM8994_AIF1_DAC1_EQ_GAINS_1             0x480
+#define WM8994_AIF1_DAC1_EQ_GAINS_2             0x481
+#define WM8994_AIF1_DAC1_EQ_BAND_1_A            0x482
+#define WM8994_AIF1_DAC1_EQ_BAND_1_B            0x483
+#define WM8994_AIF1_DAC1_EQ_BAND_1_PG           0x484
+#define WM8994_AIF1_DAC1_EQ_BAND_2_A            0x485
+#define WM8994_AIF1_DAC1_EQ_BAND_2_B            0x486
+#define WM8994_AIF1_DAC1_EQ_BAND_2_C            0x487
+#define WM8994_AIF1_DAC1_EQ_BAND_2_PG           0x488
+#define WM8994_AIF1_DAC1_EQ_BAND_3_A            0x489
+#define WM8994_AIF1_DAC1_EQ_BAND_3_B            0x48A
+#define WM8994_AIF1_DAC1_EQ_BAND_3_C            0x48B
+#define WM8994_AIF1_DAC1_EQ_BAND_3_PG           0x48C
+#define WM8994_AIF1_DAC1_EQ_BAND_4_A            0x48D
+#define WM8994_AIF1_DAC1_EQ_BAND_4_B            0x48E
+#define WM8994_AIF1_DAC1_EQ_BAND_4_C            0x48F
+#define WM8994_AIF1_DAC1_EQ_BAND_4_PG           0x490
+#define WM8994_AIF1_DAC1_EQ_BAND_5_A            0x491
+#define WM8994_AIF1_DAC1_EQ_BAND_5_B            0x492
+#define WM8994_AIF1_DAC1_EQ_BAND_5_PG           0x493
+#define WM8994_AIF1_DAC2_EQ_GAINS_1             0x4A0
+#define WM8994_AIF1_DAC2_EQ_GAINS_2             0x4A1
+#define WM8994_AIF1_DAC2_EQ_BAND_1_A            0x4A2
+#define WM8994_AIF1_DAC2_EQ_BAND_1_B            0x4A3
+#define WM8994_AIF1_DAC2_EQ_BAND_1_PG           0x4A4
+#define WM8994_AIF1_DAC2_EQ_BAND_2_A            0x4A5
+#define WM8994_AIF1_DAC2_EQ_BAND_2_B            0x4A6
+#define WM8994_AIF1_DAC2_EQ_BAND_2_C            0x4A7
+#define WM8994_AIF1_DAC2_EQ_BAND_2_PG           0x4A8
+#define WM8994_AIF1_DAC2_EQ_BAND_3_A            0x4A9
+#define WM8994_AIF1_DAC2_EQ_BAND_3_B            0x4AA
+#define WM8994_AIF1_DAC2_EQ_BAND_3_C            0x4AB
+#define WM8994_AIF1_DAC2_EQ_BAND_3_PG           0x4AC
+#define WM8994_AIF1_DAC2_EQ_BAND_4_A            0x4AD
+#define WM8994_AIF1_DAC2_EQ_BAND_4_B            0x4AE
+#define WM8994_AIF1_DAC2_EQ_BAND_4_C            0x4AF
+#define WM8994_AIF1_DAC2_EQ_BAND_4_PG           0x4B0
+#define WM8994_AIF1_DAC2_EQ_BAND_5_A            0x4B1
+#define WM8994_AIF1_DAC2_EQ_BAND_5_B            0x4B2
+#define WM8994_AIF1_DAC2_EQ_BAND_5_PG           0x4B3
+#define WM8994_AIF2_ADC_LEFT_VOLUME             0x500
+#define WM8994_AIF2_ADC_RIGHT_VOLUME            0x501
+#define WM8994_AIF2_DAC_LEFT_VOLUME             0x502
+#define WM8994_AIF2_DAC_RIGHT_VOLUME            0x503
+#define WM8994_AIF2_ADC_FILTERS                 0x510
+#define WM8994_AIF2_DAC_FILTERS_1               0x520
+#define WM8994_AIF2_DAC_FILTERS_2               0x521
+#define WM8994_AIF2_DRC_1                       0x540
+#define WM8994_AIF2_DRC_2                       0x541
+#define WM8994_AIF2_DRC_3                       0x542
+#define WM8994_AIF2_DRC_4                       0x543
+#define WM8994_AIF2_DRC_5                       0x544
+#define WM8994_AIF2_EQ_GAINS_1                  0x580
+#define WM8994_AIF2_EQ_GAINS_2                  0x581
+#define WM8994_AIF2_EQ_BAND_1_A                 0x582
+#define WM8994_AIF2_EQ_BAND_1_B                 0x583
+#define WM8994_AIF2_EQ_BAND_1_PG                0x584
+#define WM8994_AIF2_EQ_BAND_2_A                 0x585
+#define WM8994_AIF2_EQ_BAND_2_B                 0x586
+#define WM8994_AIF2_EQ_BAND_2_C                 0x587
+#define WM8994_AIF2_EQ_BAND_2_PG                0x588
+#define WM8994_AIF2_EQ_BAND_3_A                 0x589
+#define WM8994_AIF2_EQ_BAND_3_B                 0x58A
+#define WM8994_AIF2_EQ_BAND_3_C                 0x58B
+#define WM8994_AIF2_EQ_BAND_3_PG                0x58C
+#define WM8994_AIF2_EQ_BAND_4_A                 0x58D
+#define WM8994_AIF2_EQ_BAND_4_B                 0x58E
+#define WM8994_AIF2_EQ_BAND_4_C                 0x58F
+#define WM8994_AIF2_EQ_BAND_4_PG                0x590
+#define WM8994_AIF2_EQ_BAND_5_A                 0x591
+#define WM8994_AIF2_EQ_BAND_5_B                 0x592
+#define WM8994_AIF2_EQ_BAND_5_PG                0x593
+#define WM8994_DAC1_MIXER_VOLUMES               0x600
+#define WM8994_DAC1_LEFT_MIXER_ROUTING          0x601
+#define WM8994_DAC1_RIGHT_MIXER_ROUTING         0x602
+#define WM8994_DAC2_MIXER_VOLUMES               0x603
+#define WM8994_DAC2_LEFT_MIXER_ROUTING          0x604
+#define WM8994_DAC2_RIGHT_MIXER_ROUTING         0x605
+#define WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING     0x606
+#define WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING    0x607
+#define WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING     0x608
+#define WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING    0x609
+#define WM8994_DAC1_LEFT_VOLUME                 0x610
+#define WM8994_DAC1_RIGHT_VOLUME                0x611
+#define WM8994_DAC2_LEFT_VOLUME                 0x612
+#define WM8994_DAC2_RIGHT_VOLUME                0x613
+#define WM8994_DAC_SOFTMUTE                     0x614
+#define WM8994_OVERSAMPLING                     0x620
+#define WM8994_SIDETONE                         0x621
+#define WM8994_GPIO_1                           0x700
+#define WM8994_GPIO_2                           0x701
+#define WM8994_GPIO_3                           0x702
+#define WM8994_GPIO_4                           0x703
+#define WM8994_GPIO_5                           0x704
+#define WM8994_GPIO_6                           0x705
+#define WM8994_GPIO_7                           0x706
+#define WM8994_GPIO_8                           0x707
+#define WM8994_GPIO_9                           0x708
+#define WM8994_GPIO_10                          0x709
+#define WM8994_GPIO_11                          0x70A
+#define WM8994_PULL_CONTROL_1                   0x720
+#define WM8994_PULL_CONTROL_2                   0x721
+#define WM8994_INTERRUPT_STATUS_1               0x730
+#define WM8994_INTERRUPT_STATUS_2               0x731
+#define WM8994_INTERRUPT_RAW_STATUS_2           0x732
+#define WM8994_INTERRUPT_STATUS_1_MASK          0x738
+#define WM8994_INTERRUPT_STATUS_2_MASK          0x739
+#define WM8994_INTERRUPT_CONTROL                0x740
+#define WM8994_IRQ_DEBOUNCE                     0x748
+#define WM8994_WRITE_SEQUENCER_0                0x3000
+#define WM8994_WRITE_SEQUENCER_1                0x3001
+#define WM8994_WRITE_SEQUENCER_2                0x3002
+#define WM8994_WRITE_SEQUENCER_3                0x3003
+#define WM8994_WRITE_SEQUENCER_4                0x3004
+#define WM8994_WRITE_SEQUENCER_5                0x3005
+#define WM8994_WRITE_SEQUENCER_6                0x3006
+#define WM8994_WRITE_SEQUENCER_7                0x3007
+#define WM8994_WRITE_SEQUENCER_8                0x3008
+#define WM8994_WRITE_SEQUENCER_9                0x3009
+#define WM8994_WRITE_SEQUENCER_10               0x300A
+#define WM8994_WRITE_SEQUENCER_11               0x300B
+#define WM8994_WRITE_SEQUENCER_12               0x300C
+#define WM8994_WRITE_SEQUENCER_13               0x300D
+#define WM8994_WRITE_SEQUENCER_14               0x300E
+#define WM8994_WRITE_SEQUENCER_15               0x300F
+#define WM8994_WRITE_SEQUENCER_16               0x3010
+#define WM8994_WRITE_SEQUENCER_17               0x3011
+#define WM8994_WRITE_SEQUENCER_18               0x3012
+#define WM8994_WRITE_SEQUENCER_19               0x3013
+#define WM8994_WRITE_SEQUENCER_20               0x3014
+#define WM8994_WRITE_SEQUENCER_21               0x3015
+#define WM8994_WRITE_SEQUENCER_22               0x3016
+#define WM8994_WRITE_SEQUENCER_23               0x3017
+#define WM8994_WRITE_SEQUENCER_24               0x3018
+#define WM8994_WRITE_SEQUENCER_25               0x3019
+#define WM8994_WRITE_SEQUENCER_26               0x301A
+#define WM8994_WRITE_SEQUENCER_27               0x301B
+#define WM8994_WRITE_SEQUENCER_28               0x301C
+#define WM8994_WRITE_SEQUENCER_29               0x301D
+#define WM8994_WRITE_SEQUENCER_30               0x301E
+#define WM8994_WRITE_SEQUENCER_31               0x301F
+#define WM8994_WRITE_SEQUENCER_32               0x3020
+#define WM8994_WRITE_SEQUENCER_33               0x3021
+#define WM8994_WRITE_SEQUENCER_34               0x3022
+#define WM8994_WRITE_SEQUENCER_35               0x3023
+#define WM8994_WRITE_SEQUENCER_36               0x3024
+#define WM8994_WRITE_SEQUENCER_37               0x3025
+#define WM8994_WRITE_SEQUENCER_38               0x3026
+#define WM8994_WRITE_SEQUENCER_39               0x3027
+#define WM8994_WRITE_SEQUENCER_40               0x3028
+#define WM8994_WRITE_SEQUENCER_41               0x3029
+#define WM8994_WRITE_SEQUENCER_42               0x302A
+#define WM8994_WRITE_SEQUENCER_43               0x302B
+#define WM8994_WRITE_SEQUENCER_44               0x302C
+#define WM8994_WRITE_SEQUENCER_45               0x302D
+#define WM8994_WRITE_SEQUENCER_46               0x302E
+#define WM8994_WRITE_SEQUENCER_47               0x302F
+#define WM8994_WRITE_SEQUENCER_48               0x3030
+#define WM8994_WRITE_SEQUENCER_49               0x3031
+#define WM8994_WRITE_SEQUENCER_50               0x3032
+#define WM8994_WRITE_SEQUENCER_51               0x3033
+#define WM8994_WRITE_SEQUENCER_52               0x3034
+#define WM8994_WRITE_SEQUENCER_53               0x3035
+#define WM8994_WRITE_SEQUENCER_54               0x3036
+#define WM8994_WRITE_SEQUENCER_55               0x3037
+#define WM8994_WRITE_SEQUENCER_56               0x3038
+#define WM8994_WRITE_SEQUENCER_57               0x3039
+#define WM8994_WRITE_SEQUENCER_58               0x303A
+#define WM8994_WRITE_SEQUENCER_59               0x303B
+#define WM8994_WRITE_SEQUENCER_60               0x303C
+#define WM8994_WRITE_SEQUENCER_61               0x303D
+#define WM8994_WRITE_SEQUENCER_62               0x303E
+#define WM8994_WRITE_SEQUENCER_63               0x303F
+#define WM8994_WRITE_SEQUENCER_64               0x3040
+#define WM8994_WRITE_SEQUENCER_65               0x3041
+#define WM8994_WRITE_SEQUENCER_66               0x3042
+#define WM8994_WRITE_SEQUENCER_67               0x3043
+#define WM8994_WRITE_SEQUENCER_68               0x3044
+#define WM8994_WRITE_SEQUENCER_69               0x3045
+#define WM8994_WRITE_SEQUENCER_70               0x3046
+#define WM8994_WRITE_SEQUENCER_71               0x3047
+#define WM8994_WRITE_SEQUENCER_72               0x3048
+#define WM8994_WRITE_SEQUENCER_73               0x3049
+#define WM8994_WRITE_SEQUENCER_74               0x304A
+#define WM8994_WRITE_SEQUENCER_75               0x304B
+#define WM8994_WRITE_SEQUENCER_76               0x304C
+#define WM8994_WRITE_SEQUENCER_77               0x304D
+#define WM8994_WRITE_SEQUENCER_78               0x304E
+#define WM8994_WRITE_SEQUENCER_79               0x304F
+#define WM8994_WRITE_SEQUENCER_80               0x3050
+#define WM8994_WRITE_SEQUENCER_81               0x3051
+#define WM8994_WRITE_SEQUENCER_82               0x3052
+#define WM8994_WRITE_SEQUENCER_83               0x3053
+#define WM8994_WRITE_SEQUENCER_84               0x3054
+#define WM8994_WRITE_SEQUENCER_85               0x3055
+#define WM8994_WRITE_SEQUENCER_86               0x3056
+#define WM8994_WRITE_SEQUENCER_87               0x3057
+#define WM8994_WRITE_SEQUENCER_88               0x3058
+#define WM8994_WRITE_SEQUENCER_89               0x3059
+#define WM8994_WRITE_SEQUENCER_90               0x305A
+#define WM8994_WRITE_SEQUENCER_91               0x305B
+#define WM8994_WRITE_SEQUENCER_92               0x305C
+#define WM8994_WRITE_SEQUENCER_93               0x305D
+#define WM8994_WRITE_SEQUENCER_94               0x305E
+#define WM8994_WRITE_SEQUENCER_95               0x305F
+#define WM8994_WRITE_SEQUENCER_96               0x3060
+#define WM8994_WRITE_SEQUENCER_97               0x3061
+#define WM8994_WRITE_SEQUENCER_98               0x3062
+#define WM8994_WRITE_SEQUENCER_99               0x3063
+#define WM8994_WRITE_SEQUENCER_100              0x3064
+#define WM8994_WRITE_SEQUENCER_101              0x3065
+#define WM8994_WRITE_SEQUENCER_102              0x3066
+#define WM8994_WRITE_SEQUENCER_103              0x3067
+#define WM8994_WRITE_SEQUENCER_104              0x3068
+#define WM8994_WRITE_SEQUENCER_105              0x3069
+#define WM8994_WRITE_SEQUENCER_106              0x306A
+#define WM8994_WRITE_SEQUENCER_107              0x306B
+#define WM8994_WRITE_SEQUENCER_108              0x306C
+#define WM8994_WRITE_SEQUENCER_109              0x306D
+#define WM8994_WRITE_SEQUENCER_110              0x306E
+#define WM8994_WRITE_SEQUENCER_111              0x306F
+#define WM8994_WRITE_SEQUENCER_112              0x3070
+#define WM8994_WRITE_SEQUENCER_113              0x3071
+#define WM8994_WRITE_SEQUENCER_114              0x3072
+#define WM8994_WRITE_SEQUENCER_115              0x3073
+#define WM8994_WRITE_SEQUENCER_116              0x3074
+#define WM8994_WRITE_SEQUENCER_117              0x3075
+#define WM8994_WRITE_SEQUENCER_118              0x3076
+#define WM8994_WRITE_SEQUENCER_119              0x3077
+#define WM8994_WRITE_SEQUENCER_120              0x3078
+#define WM8994_WRITE_SEQUENCER_121              0x3079
+#define WM8994_WRITE_SEQUENCER_122              0x307A
+#define WM8994_WRITE_SEQUENCER_123              0x307B
+#define WM8994_WRITE_SEQUENCER_124              0x307C
+#define WM8994_WRITE_SEQUENCER_125              0x307D
+#define WM8994_WRITE_SEQUENCER_126              0x307E
+#define WM8994_WRITE_SEQUENCER_127              0x307F
+#define WM8994_WRITE_SEQUENCER_128              0x3080
+#define WM8994_WRITE_SEQUENCER_129              0x3081
+#define WM8994_WRITE_SEQUENCER_130              0x3082
+#define WM8994_WRITE_SEQUENCER_131              0x3083
+#define WM8994_WRITE_SEQUENCER_132              0x3084
+#define WM8994_WRITE_SEQUENCER_133              0x3085
+#define WM8994_WRITE_SEQUENCER_134              0x3086
+#define WM8994_WRITE_SEQUENCER_135              0x3087
+#define WM8994_WRITE_SEQUENCER_136              0x3088
+#define WM8994_WRITE_SEQUENCER_137              0x3089
+#define WM8994_WRITE_SEQUENCER_138              0x308A
+#define WM8994_WRITE_SEQUENCER_139              0x308B
+#define WM8994_WRITE_SEQUENCER_140              0x308C
+#define WM8994_WRITE_SEQUENCER_141              0x308D
+#define WM8994_WRITE_SEQUENCER_142              0x308E
+#define WM8994_WRITE_SEQUENCER_143              0x308F
+#define WM8994_WRITE_SEQUENCER_144              0x3090
+#define WM8994_WRITE_SEQUENCER_145              0x3091
+#define WM8994_WRITE_SEQUENCER_146              0x3092
+#define WM8994_WRITE_SEQUENCER_147              0x3093
+#define WM8994_WRITE_SEQUENCER_148              0x3094
+#define WM8994_WRITE_SEQUENCER_149              0x3095
+#define WM8994_WRITE_SEQUENCER_150              0x3096
+#define WM8994_WRITE_SEQUENCER_151              0x3097
+#define WM8994_WRITE_SEQUENCER_152              0x3098
+#define WM8994_WRITE_SEQUENCER_153              0x3099
+#define WM8994_WRITE_SEQUENCER_154              0x309A
+#define WM8994_WRITE_SEQUENCER_155              0x309B
+#define WM8994_WRITE_SEQUENCER_156              0x309C
+#define WM8994_WRITE_SEQUENCER_157              0x309D
+#define WM8994_WRITE_SEQUENCER_158              0x309E
+#define WM8994_WRITE_SEQUENCER_159              0x309F
+#define WM8994_WRITE_SEQUENCER_160              0x30A0
+#define WM8994_WRITE_SEQUENCER_161              0x30A1
+#define WM8994_WRITE_SEQUENCER_162              0x30A2
+#define WM8994_WRITE_SEQUENCER_163              0x30A3
+#define WM8994_WRITE_SEQUENCER_164              0x30A4
+#define WM8994_WRITE_SEQUENCER_165              0x30A5
+#define WM8994_WRITE_SEQUENCER_166              0x30A6
+#define WM8994_WRITE_SEQUENCER_167              0x30A7
+#define WM8994_WRITE_SEQUENCER_168              0x30A8
+#define WM8994_WRITE_SEQUENCER_169              0x30A9
+#define WM8994_WRITE_SEQUENCER_170              0x30AA
+#define WM8994_WRITE_SEQUENCER_171              0x30AB
+#define WM8994_WRITE_SEQUENCER_172              0x30AC
+#define WM8994_WRITE_SEQUENCER_173              0x30AD
+#define WM8994_WRITE_SEQUENCER_174              0x30AE
+#define WM8994_WRITE_SEQUENCER_175              0x30AF
+#define WM8994_WRITE_SEQUENCER_176              0x30B0
+#define WM8994_WRITE_SEQUENCER_177              0x30B1
+#define WM8994_WRITE_SEQUENCER_178              0x30B2
+#define WM8994_WRITE_SEQUENCER_179              0x30B3
+#define WM8994_WRITE_SEQUENCER_180              0x30B4
+#define WM8994_WRITE_SEQUENCER_181              0x30B5
+#define WM8994_WRITE_SEQUENCER_182              0x30B6
+#define WM8994_WRITE_SEQUENCER_183              0x30B7
+#define WM8994_WRITE_SEQUENCER_184              0x30B8
+#define WM8994_WRITE_SEQUENCER_185              0x30B9
+#define WM8994_WRITE_SEQUENCER_186              0x30BA
+#define WM8994_WRITE_SEQUENCER_187              0x30BB
+#define WM8994_WRITE_SEQUENCER_188              0x30BC
+#define WM8994_WRITE_SEQUENCER_189              0x30BD
+#define WM8994_WRITE_SEQUENCER_190              0x30BE
+#define WM8994_WRITE_SEQUENCER_191              0x30BF
+#define WM8994_WRITE_SEQUENCER_192              0x30C0
+#define WM8994_WRITE_SEQUENCER_193              0x30C1
+#define WM8994_WRITE_SEQUENCER_194              0x30C2
+#define WM8994_WRITE_SEQUENCER_195              0x30C3
+#define WM8994_WRITE_SEQUENCER_196              0x30C4
+#define WM8994_WRITE_SEQUENCER_197              0x30C5
+#define WM8994_WRITE_SEQUENCER_198              0x30C6
+#define WM8994_WRITE_SEQUENCER_199              0x30C7
+#define WM8994_WRITE_SEQUENCER_200              0x30C8
+#define WM8994_WRITE_SEQUENCER_201              0x30C9
+#define WM8994_WRITE_SEQUENCER_202              0x30CA
+#define WM8994_WRITE_SEQUENCER_203              0x30CB
+#define WM8994_WRITE_SEQUENCER_204              0x30CC
+#define WM8994_WRITE_SEQUENCER_205              0x30CD
+#define WM8994_WRITE_SEQUENCER_206              0x30CE
+#define WM8994_WRITE_SEQUENCER_207              0x30CF
+#define WM8994_WRITE_SEQUENCER_208              0x30D0
+#define WM8994_WRITE_SEQUENCER_209              0x30D1
+#define WM8994_WRITE_SEQUENCER_210              0x30D2
+#define WM8994_WRITE_SEQUENCER_211              0x30D3
+#define WM8994_WRITE_SEQUENCER_212              0x30D4
+#define WM8994_WRITE_SEQUENCER_213              0x30D5
+#define WM8994_WRITE_SEQUENCER_214              0x30D6
+#define WM8994_WRITE_SEQUENCER_215              0x30D7
+#define WM8994_WRITE_SEQUENCER_216              0x30D8
+#define WM8994_WRITE_SEQUENCER_217              0x30D9
+#define WM8994_WRITE_SEQUENCER_218              0x30DA
+#define WM8994_WRITE_SEQUENCER_219              0x30DB
+#define WM8994_WRITE_SEQUENCER_220              0x30DC
+#define WM8994_WRITE_SEQUENCER_221              0x30DD
+#define WM8994_WRITE_SEQUENCER_222              0x30DE
+#define WM8994_WRITE_SEQUENCER_223              0x30DF
+#define WM8994_WRITE_SEQUENCER_224              0x30E0
+#define WM8994_WRITE_SEQUENCER_225              0x30E1
+#define WM8994_WRITE_SEQUENCER_226              0x30E2
+#define WM8994_WRITE_SEQUENCER_227              0x30E3
+#define WM8994_WRITE_SEQUENCER_228              0x30E4
+#define WM8994_WRITE_SEQUENCER_229              0x30E5
+#define WM8994_WRITE_SEQUENCER_230              0x30E6
+#define WM8994_WRITE_SEQUENCER_231              0x30E7
+#define WM8994_WRITE_SEQUENCER_232              0x30E8
+#define WM8994_WRITE_SEQUENCER_233              0x30E9
+#define WM8994_WRITE_SEQUENCER_234              0x30EA
+#define WM8994_WRITE_SEQUENCER_235              0x30EB
+#define WM8994_WRITE_SEQUENCER_236              0x30EC
+#define WM8994_WRITE_SEQUENCER_237              0x30ED
+#define WM8994_WRITE_SEQUENCER_238              0x30EE
+#define WM8994_WRITE_SEQUENCER_239              0x30EF
+#define WM8994_WRITE_SEQUENCER_240              0x30F0
+#define WM8994_WRITE_SEQUENCER_241              0x30F1
+#define WM8994_WRITE_SEQUENCER_242              0x30F2
+#define WM8994_WRITE_SEQUENCER_243              0x30F3
+#define WM8994_WRITE_SEQUENCER_244              0x30F4
+#define WM8994_WRITE_SEQUENCER_245              0x30F5
+#define WM8994_WRITE_SEQUENCER_246              0x30F6
+#define WM8994_WRITE_SEQUENCER_247              0x30F7
+#define WM8994_WRITE_SEQUENCER_248              0x30F8
+#define WM8994_WRITE_SEQUENCER_249              0x30F9
+#define WM8994_WRITE_SEQUENCER_250              0x30FA
+#define WM8994_WRITE_SEQUENCER_251              0x30FB
+#define WM8994_WRITE_SEQUENCER_252              0x30FC
+#define WM8994_WRITE_SEQUENCER_253              0x30FD
+#define WM8994_WRITE_SEQUENCER_254              0x30FE
+#define WM8994_WRITE_SEQUENCER_255              0x30FF
+#define WM8994_WRITE_SEQUENCER_256              0x3100
+#define WM8994_WRITE_SEQUENCER_257              0x3101
+#define WM8994_WRITE_SEQUENCER_258              0x3102
+#define WM8994_WRITE_SEQUENCER_259              0x3103
+#define WM8994_WRITE_SEQUENCER_260              0x3104
+#define WM8994_WRITE_SEQUENCER_261              0x3105
+#define WM8994_WRITE_SEQUENCER_262              0x3106
+#define WM8994_WRITE_SEQUENCER_263              0x3107
+#define WM8994_WRITE_SEQUENCER_264              0x3108
+#define WM8994_WRITE_SEQUENCER_265              0x3109
+#define WM8994_WRITE_SEQUENCER_266              0x310A
+#define WM8994_WRITE_SEQUENCER_267              0x310B
+#define WM8994_WRITE_SEQUENCER_268              0x310C
+#define WM8994_WRITE_SEQUENCER_269              0x310D
+#define WM8994_WRITE_SEQUENCER_270              0x310E
+#define WM8994_WRITE_SEQUENCER_271              0x310F
+#define WM8994_WRITE_SEQUENCER_272              0x3110
+#define WM8994_WRITE_SEQUENCER_273              0x3111
+#define WM8994_WRITE_SEQUENCER_274              0x3112
+#define WM8994_WRITE_SEQUENCER_275              0x3113
+#define WM8994_WRITE_SEQUENCER_276              0x3114
+#define WM8994_WRITE_SEQUENCER_277              0x3115
+#define WM8994_WRITE_SEQUENCER_278              0x3116
+#define WM8994_WRITE_SEQUENCER_279              0x3117
+#define WM8994_WRITE_SEQUENCER_280              0x3118
+#define WM8994_WRITE_SEQUENCER_281              0x3119
+#define WM8994_WRITE_SEQUENCER_282              0x311A
+#define WM8994_WRITE_SEQUENCER_283              0x311B
+#define WM8994_WRITE_SEQUENCER_284              0x311C
+#define WM8994_WRITE_SEQUENCER_285              0x311D
+#define WM8994_WRITE_SEQUENCER_286              0x311E
+#define WM8994_WRITE_SEQUENCER_287              0x311F
+#define WM8994_WRITE_SEQUENCER_288              0x3120
+#define WM8994_WRITE_SEQUENCER_289              0x3121
+#define WM8994_WRITE_SEQUENCER_290              0x3122
+#define WM8994_WRITE_SEQUENCER_291              0x3123
+#define WM8994_WRITE_SEQUENCER_292              0x3124
+#define WM8994_WRITE_SEQUENCER_293              0x3125
+#define WM8994_WRITE_SEQUENCER_294              0x3126
+#define WM8994_WRITE_SEQUENCER_295              0x3127
+#define WM8994_WRITE_SEQUENCER_296              0x3128
+#define WM8994_WRITE_SEQUENCER_297              0x3129
+#define WM8994_WRITE_SEQUENCER_298              0x312A
+#define WM8994_WRITE_SEQUENCER_299              0x312B
+#define WM8994_WRITE_SEQUENCER_300              0x312C
+#define WM8994_WRITE_SEQUENCER_301              0x312D
+#define WM8994_WRITE_SEQUENCER_302              0x312E
+#define WM8994_WRITE_SEQUENCER_303              0x312F
+#define WM8994_WRITE_SEQUENCER_304              0x3130
+#define WM8994_WRITE_SEQUENCER_305              0x3131
+#define WM8994_WRITE_SEQUENCER_306              0x3132
+#define WM8994_WRITE_SEQUENCER_307              0x3133
+#define WM8994_WRITE_SEQUENCER_308              0x3134
+#define WM8994_WRITE_SEQUENCER_309              0x3135
+#define WM8994_WRITE_SEQUENCER_310              0x3136
+#define WM8994_WRITE_SEQUENCER_311              0x3137
+#define WM8994_WRITE_SEQUENCER_312              0x3138
+#define WM8994_WRITE_SEQUENCER_313              0x3139
+#define WM8994_WRITE_SEQUENCER_314              0x313A
+#define WM8994_WRITE_SEQUENCER_315              0x313B
+#define WM8994_WRITE_SEQUENCER_316              0x313C
+#define WM8994_WRITE_SEQUENCER_317              0x313D
+#define WM8994_WRITE_SEQUENCER_318              0x313E
+#define WM8994_WRITE_SEQUENCER_319              0x313F
+#define WM8994_WRITE_SEQUENCER_320              0x3140
+#define WM8994_WRITE_SEQUENCER_321              0x3141
+#define WM8994_WRITE_SEQUENCER_322              0x3142
+#define WM8994_WRITE_SEQUENCER_323              0x3143
+#define WM8994_WRITE_SEQUENCER_324              0x3144
+#define WM8994_WRITE_SEQUENCER_325              0x3145
+#define WM8994_WRITE_SEQUENCER_326              0x3146
+#define WM8994_WRITE_SEQUENCER_327              0x3147
+#define WM8994_WRITE_SEQUENCER_328              0x3148
+#define WM8994_WRITE_SEQUENCER_329              0x3149
+#define WM8994_WRITE_SEQUENCER_330              0x314A
+#define WM8994_WRITE_SEQUENCER_331              0x314B
+#define WM8994_WRITE_SEQUENCER_332              0x314C
+#define WM8994_WRITE_SEQUENCER_333              0x314D
+#define WM8994_WRITE_SEQUENCER_334              0x314E
+#define WM8994_WRITE_SEQUENCER_335              0x314F
+#define WM8994_WRITE_SEQUENCER_336              0x3150
+#define WM8994_WRITE_SEQUENCER_337              0x3151
+#define WM8994_WRITE_SEQUENCER_338              0x3152
+#define WM8994_WRITE_SEQUENCER_339              0x3153
+#define WM8994_WRITE_SEQUENCER_340              0x3154
+#define WM8994_WRITE_SEQUENCER_341              0x3155
+#define WM8994_WRITE_SEQUENCER_342              0x3156
+#define WM8994_WRITE_SEQUENCER_343              0x3157
+#define WM8994_WRITE_SEQUENCER_344              0x3158
+#define WM8994_WRITE_SEQUENCER_345              0x3159
+#define WM8994_WRITE_SEQUENCER_346              0x315A
+#define WM8994_WRITE_SEQUENCER_347              0x315B
+#define WM8994_WRITE_SEQUENCER_348              0x315C
+#define WM8994_WRITE_SEQUENCER_349              0x315D
+#define WM8994_WRITE_SEQUENCER_350              0x315E
+#define WM8994_WRITE_SEQUENCER_351              0x315F
+#define WM8994_WRITE_SEQUENCER_352              0x3160
+#define WM8994_WRITE_SEQUENCER_353              0x3161
+#define WM8994_WRITE_SEQUENCER_354              0x3162
+#define WM8994_WRITE_SEQUENCER_355              0x3163
+#define WM8994_WRITE_SEQUENCER_356              0x3164
+#define WM8994_WRITE_SEQUENCER_357              0x3165
+#define WM8994_WRITE_SEQUENCER_358              0x3166
+#define WM8994_WRITE_SEQUENCER_359              0x3167
+#define WM8994_WRITE_SEQUENCER_360              0x3168
+#define WM8994_WRITE_SEQUENCER_361              0x3169
+#define WM8994_WRITE_SEQUENCER_362              0x316A
+#define WM8994_WRITE_SEQUENCER_363              0x316B
+#define WM8994_WRITE_SEQUENCER_364              0x316C
+#define WM8994_WRITE_SEQUENCER_365              0x316D
+#define WM8994_WRITE_SEQUENCER_366              0x316E
+#define WM8994_WRITE_SEQUENCER_367              0x316F
+#define WM8994_WRITE_SEQUENCER_368              0x3170
+#define WM8994_WRITE_SEQUENCER_369              0x3171
+#define WM8994_WRITE_SEQUENCER_370              0x3172
+#define WM8994_WRITE_SEQUENCER_371              0x3173
+#define WM8994_WRITE_SEQUENCER_372              0x3174
+#define WM8994_WRITE_SEQUENCER_373              0x3175
+#define WM8994_WRITE_SEQUENCER_374              0x3176
+#define WM8994_WRITE_SEQUENCER_375              0x3177
+#define WM8994_WRITE_SEQUENCER_376              0x3178
+#define WM8994_WRITE_SEQUENCER_377              0x3179
+#define WM8994_WRITE_SEQUENCER_378              0x317A
+#define WM8994_WRITE_SEQUENCER_379              0x317B
+#define WM8994_WRITE_SEQUENCER_380              0x317C
+#define WM8994_WRITE_SEQUENCER_381              0x317D
+#define WM8994_WRITE_SEQUENCER_382              0x317E
+#define WM8994_WRITE_SEQUENCER_383              0x317F
+#define WM8994_WRITE_SEQUENCER_384              0x3180
+#define WM8994_WRITE_SEQUENCER_385              0x3181
+#define WM8994_WRITE_SEQUENCER_386              0x3182
+#define WM8994_WRITE_SEQUENCER_387              0x3183
+#define WM8994_WRITE_SEQUENCER_388              0x3184
+#define WM8994_WRITE_SEQUENCER_389              0x3185
+#define WM8994_WRITE_SEQUENCER_390              0x3186
+#define WM8994_WRITE_SEQUENCER_391              0x3187
+#define WM8994_WRITE_SEQUENCER_392              0x3188
+#define WM8994_WRITE_SEQUENCER_393              0x3189
+#define WM8994_WRITE_SEQUENCER_394              0x318A
+#define WM8994_WRITE_SEQUENCER_395              0x318B
+#define WM8994_WRITE_SEQUENCER_396              0x318C
+#define WM8994_WRITE_SEQUENCER_397              0x318D
+#define WM8994_WRITE_SEQUENCER_398              0x318E
+#define WM8994_WRITE_SEQUENCER_399              0x318F
+#define WM8994_WRITE_SEQUENCER_400              0x3190
+#define WM8994_WRITE_SEQUENCER_401              0x3191
+#define WM8994_WRITE_SEQUENCER_402              0x3192
+#define WM8994_WRITE_SEQUENCER_403              0x3193
+#define WM8994_WRITE_SEQUENCER_404              0x3194
+#define WM8994_WRITE_SEQUENCER_405              0x3195
+#define WM8994_WRITE_SEQUENCER_406              0x3196
+#define WM8994_WRITE_SEQUENCER_407              0x3197
+#define WM8994_WRITE_SEQUENCER_408              0x3198
+#define WM8994_WRITE_SEQUENCER_409              0x3199
+#define WM8994_WRITE_SEQUENCER_410              0x319A
+#define WM8994_WRITE_SEQUENCER_411              0x319B
+#define WM8994_WRITE_SEQUENCER_412              0x319C
+#define WM8994_WRITE_SEQUENCER_413              0x319D
+#define WM8994_WRITE_SEQUENCER_414              0x319E
+#define WM8994_WRITE_SEQUENCER_415              0x319F
+#define WM8994_WRITE_SEQUENCER_416              0x31A0
+#define WM8994_WRITE_SEQUENCER_417              0x31A1
+#define WM8994_WRITE_SEQUENCER_418              0x31A2
+#define WM8994_WRITE_SEQUENCER_419              0x31A3
+#define WM8994_WRITE_SEQUENCER_420              0x31A4
+#define WM8994_WRITE_SEQUENCER_421              0x31A5
+#define WM8994_WRITE_SEQUENCER_422              0x31A6
+#define WM8994_WRITE_SEQUENCER_423              0x31A7
+#define WM8994_WRITE_SEQUENCER_424              0x31A8
+#define WM8994_WRITE_SEQUENCER_425              0x31A9
+#define WM8994_WRITE_SEQUENCER_426              0x31AA
+#define WM8994_WRITE_SEQUENCER_427              0x31AB
+#define WM8994_WRITE_SEQUENCER_428              0x31AC
+#define WM8994_WRITE_SEQUENCER_429              0x31AD
+#define WM8994_WRITE_SEQUENCER_430              0x31AE
+#define WM8994_WRITE_SEQUENCER_431              0x31AF
+#define WM8994_WRITE_SEQUENCER_432              0x31B0
+#define WM8994_WRITE_SEQUENCER_433              0x31B1
+#define WM8994_WRITE_SEQUENCER_434              0x31B2
+#define WM8994_WRITE_SEQUENCER_435              0x31B3
+#define WM8994_WRITE_SEQUENCER_436              0x31B4
+#define WM8994_WRITE_SEQUENCER_437              0x31B5
+#define WM8994_WRITE_SEQUENCER_438              0x31B6
+#define WM8994_WRITE_SEQUENCER_439              0x31B7
+#define WM8994_WRITE_SEQUENCER_440              0x31B8
+#define WM8994_WRITE_SEQUENCER_441              0x31B9
+#define WM8994_WRITE_SEQUENCER_442              0x31BA
+#define WM8994_WRITE_SEQUENCER_443              0x31BB
+#define WM8994_WRITE_SEQUENCER_444              0x31BC
+#define WM8994_WRITE_SEQUENCER_445              0x31BD
+#define WM8994_WRITE_SEQUENCER_446              0x31BE
+#define WM8994_WRITE_SEQUENCER_447              0x31BF
+#define WM8994_WRITE_SEQUENCER_448              0x31C0
+#define WM8994_WRITE_SEQUENCER_449              0x31C1
+#define WM8994_WRITE_SEQUENCER_450              0x31C2
+#define WM8994_WRITE_SEQUENCER_451              0x31C3
+#define WM8994_WRITE_SEQUENCER_452              0x31C4
+#define WM8994_WRITE_SEQUENCER_453              0x31C5
+#define WM8994_WRITE_SEQUENCER_454              0x31C6
+#define WM8994_WRITE_SEQUENCER_455              0x31C7
+#define WM8994_WRITE_SEQUENCER_456              0x31C8
+#define WM8994_WRITE_SEQUENCER_457              0x31C9
+#define WM8994_WRITE_SEQUENCER_458              0x31CA
+#define WM8994_WRITE_SEQUENCER_459              0x31CB
+#define WM8994_WRITE_SEQUENCER_460              0x31CC
+#define WM8994_WRITE_SEQUENCER_461              0x31CD
+#define WM8994_WRITE_SEQUENCER_462              0x31CE
+#define WM8994_WRITE_SEQUENCER_463              0x31CF
+#define WM8994_WRITE_SEQUENCER_464              0x31D0
+#define WM8994_WRITE_SEQUENCER_465              0x31D1
+#define WM8994_WRITE_SEQUENCER_466              0x31D2
+#define WM8994_WRITE_SEQUENCER_467              0x31D3
+#define WM8994_WRITE_SEQUENCER_468              0x31D4
+#define WM8994_WRITE_SEQUENCER_469              0x31D5
+#define WM8994_WRITE_SEQUENCER_470              0x31D6
+#define WM8994_WRITE_SEQUENCER_471              0x31D7
+#define WM8994_WRITE_SEQUENCER_472              0x31D8
+#define WM8994_WRITE_SEQUENCER_473              0x31D9
+#define WM8994_WRITE_SEQUENCER_474              0x31DA
+#define WM8994_WRITE_SEQUENCER_475              0x31DB
+#define WM8994_WRITE_SEQUENCER_476              0x31DC
+#define WM8994_WRITE_SEQUENCER_477              0x31DD
+#define WM8994_WRITE_SEQUENCER_478              0x31DE
+#define WM8994_WRITE_SEQUENCER_479              0x31DF
+#define WM8994_WRITE_SEQUENCER_480              0x31E0
+#define WM8994_WRITE_SEQUENCER_481              0x31E1
+#define WM8994_WRITE_SEQUENCER_482              0x31E2
+#define WM8994_WRITE_SEQUENCER_483              0x31E3
+#define WM8994_WRITE_SEQUENCER_484              0x31E4
+#define WM8994_WRITE_SEQUENCER_485              0x31E5
+#define WM8994_WRITE_SEQUENCER_486              0x31E6
+#define WM8994_WRITE_SEQUENCER_487              0x31E7
+#define WM8994_WRITE_SEQUENCER_488              0x31E8
+#define WM8994_WRITE_SEQUENCER_489              0x31E9
+#define WM8994_WRITE_SEQUENCER_490              0x31EA
+#define WM8994_WRITE_SEQUENCER_491              0x31EB
+#define WM8994_WRITE_SEQUENCER_492              0x31EC
+#define WM8994_WRITE_SEQUENCER_493              0x31ED
+#define WM8994_WRITE_SEQUENCER_494              0x31EE
+#define WM8994_WRITE_SEQUENCER_495              0x31EF
+#define WM8994_WRITE_SEQUENCER_496              0x31F0
+#define WM8994_WRITE_SEQUENCER_497              0x31F1
+#define WM8994_WRITE_SEQUENCER_498              0x31F2
+#define WM8994_WRITE_SEQUENCER_499              0x31F3
+#define WM8994_WRITE_SEQUENCER_500              0x31F4
+#define WM8994_WRITE_SEQUENCER_501              0x31F5
+#define WM8994_WRITE_SEQUENCER_502              0x31F6
+#define WM8994_WRITE_SEQUENCER_503              0x31F7
+#define WM8994_WRITE_SEQUENCER_504              0x31F8
+#define WM8994_WRITE_SEQUENCER_505              0x31F9
+#define WM8994_WRITE_SEQUENCER_506              0x31FA
+#define WM8994_WRITE_SEQUENCER_507              0x31FB
+#define WM8994_WRITE_SEQUENCER_508              0x31FC
+#define WM8994_WRITE_SEQUENCER_509              0x31FD
+#define WM8994_WRITE_SEQUENCER_510              0x31FE
+#define WM8994_WRITE_SEQUENCER_511              0x31FF
+
+#define WM8994_REGISTER_COUNT                   736
+#define WM8994_MAX_REGISTER                     0x31FF
+#define WM8994_MAX_CACHED_REGISTER              0x749
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Software Reset
+ */
+#define WM8994_SW_RESET_MASK                    0xFFFF  /* SW_RESET - [15:0] */
+#define WM8994_SW_RESET_SHIFT                        0  /* SW_RESET - [15:0] */
+#define WM8994_SW_RESET_WIDTH                       16  /* SW_RESET - [15:0] */
+
+/*
+ * R1 (0x01) - Power Management (1)
+ */
+#define WM8994_SPKOUTR_ENA                      0x2000  /* SPKOUTR_ENA */
+#define WM8994_SPKOUTR_ENA_MASK                 0x2000  /* SPKOUTR_ENA */
+#define WM8994_SPKOUTR_ENA_SHIFT                    13  /* SPKOUTR_ENA */
+#define WM8994_SPKOUTR_ENA_WIDTH                     1  /* SPKOUTR_ENA */
+#define WM8994_SPKOUTL_ENA                      0x1000  /* SPKOUTL_ENA */
+#define WM8994_SPKOUTL_ENA_MASK                 0x1000  /* SPKOUTL_ENA */
+#define WM8994_SPKOUTL_ENA_SHIFT                    12  /* SPKOUTL_ENA */
+#define WM8994_SPKOUTL_ENA_WIDTH                     1  /* SPKOUTL_ENA */
+#define WM8994_HPOUT2_ENA                       0x0800  /* HPOUT2_ENA */
+#define WM8994_HPOUT2_ENA_MASK                  0x0800  /* HPOUT2_ENA */
+#define WM8994_HPOUT2_ENA_SHIFT                     11  /* HPOUT2_ENA */
+#define WM8994_HPOUT2_ENA_WIDTH                      1  /* HPOUT2_ENA */
+#define WM8994_HPOUT1L_ENA                      0x0200  /* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA_MASK                 0x0200  /* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA_SHIFT                     9  /* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA_WIDTH                     1  /* HPOUT1L_ENA */
+#define WM8994_HPOUT1R_ENA                      0x0100  /* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA_MASK                 0x0100  /* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA_SHIFT                     8  /* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA_WIDTH                     1  /* HPOUT1R_ENA */
+#define WM8994_MICB2_ENA                        0x0020  /* MICB2_ENA */
+#define WM8994_MICB2_ENA_MASK                   0x0020  /* MICB2_ENA */
+#define WM8994_MICB2_ENA_SHIFT                       5  /* MICB2_ENA */
+#define WM8994_MICB2_ENA_WIDTH                       1  /* MICB2_ENA */
+#define WM8994_MICB1_ENA                        0x0010  /* MICB1_ENA */
+#define WM8994_MICB1_ENA_MASK                   0x0010  /* MICB1_ENA */
+#define WM8994_MICB1_ENA_SHIFT                       4  /* MICB1_ENA */
+#define WM8994_MICB1_ENA_WIDTH                       1  /* MICB1_ENA */
+#define WM8994_VMID_SEL_MASK                    0x0006  /* VMID_SEL - [2:1] */
+#define WM8994_VMID_SEL_SHIFT                        1  /* VMID_SEL - [2:1] */
+#define WM8994_VMID_SEL_WIDTH                        2  /* VMID_SEL - [2:1] */
+#define WM8994_BIAS_ENA                         0x0001  /* BIAS_ENA */
+#define WM8994_BIAS_ENA_MASK                    0x0001  /* BIAS_ENA */
+#define WM8994_BIAS_ENA_SHIFT                        0  /* BIAS_ENA */
+#define WM8994_BIAS_ENA_WIDTH                        1  /* BIAS_ENA */
+
+/*
+ * R2 (0x02) - Power Management (2)
+ */
+#define WM8994_TSHUT_ENA                        0x4000  /* TSHUT_ENA */
+#define WM8994_TSHUT_ENA_MASK                   0x4000  /* TSHUT_ENA */
+#define WM8994_TSHUT_ENA_SHIFT                      14  /* TSHUT_ENA */
+#define WM8994_TSHUT_ENA_WIDTH                       1  /* TSHUT_ENA */
+#define WM8994_TSHUT_OPDIS                      0x2000  /* TSHUT_OPDIS */
+#define WM8994_TSHUT_OPDIS_MASK                 0x2000  /* TSHUT_OPDIS */
+#define WM8994_TSHUT_OPDIS_SHIFT                    13  /* TSHUT_OPDIS */
+#define WM8994_TSHUT_OPDIS_WIDTH                     1  /* TSHUT_OPDIS */
+#define WM8994_OPCLK_ENA                        0x0800  /* OPCLK_ENA */
+#define WM8994_OPCLK_ENA_MASK                   0x0800  /* OPCLK_ENA */
+#define WM8994_OPCLK_ENA_SHIFT                      11  /* OPCLK_ENA */
+#define WM8994_OPCLK_ENA_WIDTH                       1  /* OPCLK_ENA */
+#define WM8994_MIXINL_ENA                       0x0200  /* MIXINL_ENA */
+#define WM8994_MIXINL_ENA_MASK                  0x0200  /* MIXINL_ENA */
+#define WM8994_MIXINL_ENA_SHIFT                      9  /* MIXINL_ENA */
+#define WM8994_MIXINL_ENA_WIDTH                      1  /* MIXINL_ENA */
+#define WM8994_MIXINR_ENA                       0x0100  /* MIXINR_ENA */
+#define WM8994_MIXINR_ENA_MASK                  0x0100  /* MIXINR_ENA */
+#define WM8994_MIXINR_ENA_SHIFT                      8  /* MIXINR_ENA */
+#define WM8994_MIXINR_ENA_WIDTH                      1  /* MIXINR_ENA */
+#define WM8994_IN2L_ENA                         0x0080  /* IN2L_ENA */
+#define WM8994_IN2L_ENA_MASK                    0x0080  /* IN2L_ENA */
+#define WM8994_IN2L_ENA_SHIFT                        7  /* IN2L_ENA */
+#define WM8994_IN2L_ENA_WIDTH                        1  /* IN2L_ENA */
+#define WM8994_IN1L_ENA                         0x0040  /* IN1L_ENA */
+#define WM8994_IN1L_ENA_MASK                    0x0040  /* IN1L_ENA */
+#define WM8994_IN1L_ENA_SHIFT                        6  /* IN1L_ENA */
+#define WM8994_IN1L_ENA_WIDTH                        1  /* IN1L_ENA */
+#define WM8994_IN2R_ENA                         0x0020  /* IN2R_ENA */
+#define WM8994_IN2R_ENA_MASK                    0x0020  /* IN2R_ENA */
+#define WM8994_IN2R_ENA_SHIFT                        5  /* IN2R_ENA */
+#define WM8994_IN2R_ENA_WIDTH                        1  /* IN2R_ENA */
+#define WM8994_IN1R_ENA                         0x0010  /* IN1R_ENA */
+#define WM8994_IN1R_ENA_MASK                    0x0010  /* IN1R_ENA */
+#define WM8994_IN1R_ENA_SHIFT                        4  /* IN1R_ENA */
+#define WM8994_IN1R_ENA_WIDTH                        1  /* IN1R_ENA */
+
+/*
+ * R3 (0x03) - Power Management (3)
+ */
+#define WM8994_LINEOUT1N_ENA                    0x2000  /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1N_ENA_MASK               0x2000  /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1N_ENA_SHIFT                  13  /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1N_ENA_WIDTH                   1  /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1P_ENA                    0x1000  /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT1P_ENA_MASK               0x1000  /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT1P_ENA_SHIFT                  12  /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT1P_ENA_WIDTH                   1  /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT2N_ENA                    0x0800  /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2N_ENA_MASK               0x0800  /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2N_ENA_SHIFT                  11  /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2N_ENA_WIDTH                   1  /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2P_ENA                    0x0400  /* LINEOUT2P_ENA */
+#define WM8994_LINEOUT2P_ENA_MASK               0x0400  /* LINEOUT2P_ENA */
+#define WM8994_LINEOUT2P_ENA_SHIFT                  10  /* LINEOUT2P_ENA */
+#define WM8994_LINEOUT2P_ENA_WIDTH                   1  /* LINEOUT2P_ENA */
+#define WM8994_SPKRVOL_ENA                      0x0200  /* SPKRVOL_ENA */
+#define WM8994_SPKRVOL_ENA_MASK                 0x0200  /* SPKRVOL_ENA */
+#define WM8994_SPKRVOL_ENA_SHIFT                     9  /* SPKRVOL_ENA */
+#define WM8994_SPKRVOL_ENA_WIDTH                     1  /* SPKRVOL_ENA */
+#define WM8994_SPKLVOL_ENA                      0x0100  /* SPKLVOL_ENA */
+#define WM8994_SPKLVOL_ENA_MASK                 0x0100  /* SPKLVOL_ENA */
+#define WM8994_SPKLVOL_ENA_SHIFT                     8  /* SPKLVOL_ENA */
+#define WM8994_SPKLVOL_ENA_WIDTH                     1  /* SPKLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA                   0x0080  /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA_MASK              0x0080  /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA_SHIFT                  7  /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA_WIDTH                  1  /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA                   0x0040  /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA_MASK              0x0040  /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA_SHIFT                  6  /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA_WIDTH                  1  /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTL_ENA                      0x0020  /* MIXOUTL_ENA */
+#define WM8994_MIXOUTL_ENA_MASK                 0x0020  /* MIXOUTL_ENA */
+#define WM8994_MIXOUTL_ENA_SHIFT                     5  /* MIXOUTL_ENA */
+#define WM8994_MIXOUTL_ENA_WIDTH                     1  /* MIXOUTL_ENA */
+#define WM8994_MIXOUTR_ENA                      0x0010  /* MIXOUTR_ENA */
+#define WM8994_MIXOUTR_ENA_MASK                 0x0010  /* MIXOUTR_ENA */
+#define WM8994_MIXOUTR_ENA_SHIFT                     4  /* MIXOUTR_ENA */
+#define WM8994_MIXOUTR_ENA_WIDTH                     1  /* MIXOUTR_ENA */
+
+/*
+ * R4 (0x04) - Power Management (4)
+ */
+#define WM8994_AIF2ADCL_ENA                     0x2000  /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCL_ENA_MASK                0x2000  /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCL_ENA_SHIFT                   13  /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCL_ENA_WIDTH                    1  /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCR_ENA                     0x1000  /* AIF2ADCR_ENA */
+#define WM8994_AIF2ADCR_ENA_MASK                0x1000  /* AIF2ADCR_ENA */
+#define WM8994_AIF2ADCR_ENA_SHIFT                   12  /* AIF2ADCR_ENA */
+#define WM8994_AIF2ADCR_ENA_WIDTH                    1  /* AIF2ADCR_ENA */
+#define WM8994_AIF1ADC2L_ENA                    0x0800  /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2L_ENA_MASK               0x0800  /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2L_ENA_SHIFT                  11  /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2L_ENA_WIDTH                   1  /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2R_ENA                    0x0400  /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC2R_ENA_MASK               0x0400  /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC2R_ENA_SHIFT                  10  /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC2R_ENA_WIDTH                   1  /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC1L_ENA                    0x0200  /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1L_ENA_MASK               0x0200  /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1L_ENA_SHIFT                   9  /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1L_ENA_WIDTH                   1  /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1R_ENA                    0x0100  /* AIF1ADC1R_ENA */
+#define WM8994_AIF1ADC1R_ENA_MASK               0x0100  /* AIF1ADC1R_ENA */
+#define WM8994_AIF1ADC1R_ENA_SHIFT                   8  /* AIF1ADC1R_ENA */
+#define WM8994_AIF1ADC1R_ENA_WIDTH                   1  /* AIF1ADC1R_ENA */
+#define WM8994_DMIC2L_ENA                       0x0020  /* DMIC2L_ENA */
+#define WM8994_DMIC2L_ENA_MASK                  0x0020  /* DMIC2L_ENA */
+#define WM8994_DMIC2L_ENA_SHIFT                      5  /* DMIC2L_ENA */
+#define WM8994_DMIC2L_ENA_WIDTH                      1  /* DMIC2L_ENA */
+#define WM8994_DMIC2R_ENA                       0x0010  /* DMIC2R_ENA */
+#define WM8994_DMIC2R_ENA_MASK                  0x0010  /* DMIC2R_ENA */
+#define WM8994_DMIC2R_ENA_SHIFT                      4  /* DMIC2R_ENA */
+#define WM8994_DMIC2R_ENA_WIDTH                      1  /* DMIC2R_ENA */
+#define WM8994_DMIC1L_ENA                       0x0008  /* DMIC1L_ENA */
+#define WM8994_DMIC1L_ENA_MASK                  0x0008  /* DMIC1L_ENA */
+#define WM8994_DMIC1L_ENA_SHIFT                      3  /* DMIC1L_ENA */
+#define WM8994_DMIC1L_ENA_WIDTH                      1  /* DMIC1L_ENA */
+#define WM8994_DMIC1R_ENA                       0x0004  /* DMIC1R_ENA */
+#define WM8994_DMIC1R_ENA_MASK                  0x0004  /* DMIC1R_ENA */
+#define WM8994_DMIC1R_ENA_SHIFT                      2  /* DMIC1R_ENA */
+#define WM8994_DMIC1R_ENA_WIDTH                      1  /* DMIC1R_ENA */
+#define WM8994_ADCL_ENA                         0x0002  /* ADCL_ENA */
+#define WM8994_ADCL_ENA_MASK                    0x0002  /* ADCL_ENA */
+#define WM8994_ADCL_ENA_SHIFT                        1  /* ADCL_ENA */
+#define WM8994_ADCL_ENA_WIDTH                        1  /* ADCL_ENA */
+#define WM8994_ADCR_ENA                         0x0001  /* ADCR_ENA */
+#define WM8994_ADCR_ENA_MASK                    0x0001  /* ADCR_ENA */
+#define WM8994_ADCR_ENA_SHIFT                        0  /* ADCR_ENA */
+#define WM8994_ADCR_ENA_WIDTH                        1  /* ADCR_ENA */
+
+/*
+ * R5 (0x05) - Power Management (5)
+ */
+#define WM8994_AIF2DACL_ENA                     0x2000  /* AIF2DACL_ENA */
+#define WM8994_AIF2DACL_ENA_MASK                0x2000  /* AIF2DACL_ENA */
+#define WM8994_AIF2DACL_ENA_SHIFT                   13  /* AIF2DACL_ENA */
+#define WM8994_AIF2DACL_ENA_WIDTH                    1  /* AIF2DACL_ENA */
+#define WM8994_AIF2DACR_ENA                     0x1000  /* AIF2DACR_ENA */
+#define WM8994_AIF2DACR_ENA_MASK                0x1000  /* AIF2DACR_ENA */
+#define WM8994_AIF2DACR_ENA_SHIFT                   12  /* AIF2DACR_ENA */
+#define WM8994_AIF2DACR_ENA_WIDTH                    1  /* AIF2DACR_ENA */
+#define WM8994_AIF1DAC2L_ENA                    0x0800  /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2L_ENA_MASK               0x0800  /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2L_ENA_SHIFT                  11  /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2L_ENA_WIDTH                   1  /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2R_ENA                    0x0400  /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC2R_ENA_MASK               0x0400  /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC2R_ENA_SHIFT                  10  /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC2R_ENA_WIDTH                   1  /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC1L_ENA                    0x0200  /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1L_ENA_MASK               0x0200  /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1L_ENA_SHIFT                   9  /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1L_ENA_WIDTH                   1  /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1R_ENA                    0x0100  /* AIF1DAC1R_ENA */
+#define WM8994_AIF1DAC1R_ENA_MASK               0x0100  /* AIF1DAC1R_ENA */
+#define WM8994_AIF1DAC1R_ENA_SHIFT                   8  /* AIF1DAC1R_ENA */
+#define WM8994_AIF1DAC1R_ENA_WIDTH                   1  /* AIF1DAC1R_ENA */
+#define WM8994_DAC2L_ENA                        0x0008  /* DAC2L_ENA */
+#define WM8994_DAC2L_ENA_MASK                   0x0008  /* DAC2L_ENA */
+#define WM8994_DAC2L_ENA_SHIFT                       3  /* DAC2L_ENA */
+#define WM8994_DAC2L_ENA_WIDTH                       1  /* DAC2L_ENA */
+#define WM8994_DAC2R_ENA                        0x0004  /* DAC2R_ENA */
+#define WM8994_DAC2R_ENA_MASK                   0x0004  /* DAC2R_ENA */
+#define WM8994_DAC2R_ENA_SHIFT                       2  /* DAC2R_ENA */
+#define WM8994_DAC2R_ENA_WIDTH                       1  /* DAC2R_ENA */
+#define WM8994_DAC1L_ENA                        0x0002  /* DAC1L_ENA */
+#define WM8994_DAC1L_ENA_MASK                   0x0002  /* DAC1L_ENA */
+#define WM8994_DAC1L_ENA_SHIFT                       1  /* DAC1L_ENA */
+#define WM8994_DAC1L_ENA_WIDTH                       1  /* DAC1L_ENA */
+#define WM8994_DAC1R_ENA                        0x0001  /* DAC1R_ENA */
+#define WM8994_DAC1R_ENA_MASK                   0x0001  /* DAC1R_ENA */
+#define WM8994_DAC1R_ENA_SHIFT                       0  /* DAC1R_ENA */
+#define WM8994_DAC1R_ENA_WIDTH                       1  /* DAC1R_ENA */
+
+/*
+ * R6 (0x06) - Power Management (6)
+ */
+#define WM8994_AIF3_TRI                         0x0020  /* AIF3_TRI */
+#define WM8994_AIF3_TRI_MASK                    0x0020  /* AIF3_TRI */
+#define WM8994_AIF3_TRI_SHIFT                        5  /* AIF3_TRI */
+#define WM8994_AIF3_TRI_WIDTH                        1  /* AIF3_TRI */
+#define WM8994_AIF3_ADCDAT_SRC_MASK             0x0018  /* AIF3_ADCDAT_SRC - [4:3] */
+#define WM8994_AIF3_ADCDAT_SRC_SHIFT                 3  /* AIF3_ADCDAT_SRC - [4:3] */
+#define WM8994_AIF3_ADCDAT_SRC_WIDTH                 2  /* AIF3_ADCDAT_SRC - [4:3] */
+#define WM8994_AIF2_ADCDAT_SRC                  0x0004  /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_ADCDAT_SRC_MASK             0x0004  /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_ADCDAT_SRC_SHIFT                 2  /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_ADCDAT_SRC_WIDTH                 1  /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC                  0x0002  /* AIF2_DACDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC_MASK             0x0002  /* AIF2_DACDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC_SHIFT                 1  /* AIF2_DACDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC_WIDTH                 1  /* AIF2_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC                  0x0001  /* AIF1_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC_MASK             0x0001  /* AIF1_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC_SHIFT                 0  /* AIF1_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC_WIDTH                 1  /* AIF1_DACDAT_SRC */
+
+/*
+ * R21 (0x15) - Input Mixer (1)
+ */
+#define WM8994_IN1RP_MIXINR_BOOST               0x0100  /* IN1RP_MIXINR_BOOST */
+#define WM8994_IN1RP_MIXINR_BOOST_MASK          0x0100  /* IN1RP_MIXINR_BOOST */
+#define WM8994_IN1RP_MIXINR_BOOST_SHIFT              8  /* IN1RP_MIXINR_BOOST */
+#define WM8994_IN1RP_MIXINR_BOOST_WIDTH              1  /* IN1RP_MIXINR_BOOST */
+#define WM8994_IN1LP_MIXINL_BOOST               0x0080  /* IN1LP_MIXINL_BOOST */
+#define WM8994_IN1LP_MIXINL_BOOST_MASK          0x0080  /* IN1LP_MIXINL_BOOST */
+#define WM8994_IN1LP_MIXINL_BOOST_SHIFT              7  /* IN1LP_MIXINL_BOOST */
+#define WM8994_IN1LP_MIXINL_BOOST_WIDTH              1  /* IN1LP_MIXINL_BOOST */
+#define WM8994_INPUTS_CLAMP                     0x0040  /* INPUTS_CLAMP */
+#define WM8994_INPUTS_CLAMP_MASK                0x0040  /* INPUTS_CLAMP */
+#define WM8994_INPUTS_CLAMP_SHIFT                    6  /* INPUTS_CLAMP */
+#define WM8994_INPUTS_CLAMP_WIDTH                    1  /* INPUTS_CLAMP */
+
+/*
+ * R24 (0x18) - Left Line Input 1&2 Volume
+ */
+#define WM8994_IN1_VU                           0x0100  /* IN1_VU */
+#define WM8994_IN1_VU_MASK                      0x0100  /* IN1_VU */
+#define WM8994_IN1_VU_SHIFT                          8  /* IN1_VU */
+#define WM8994_IN1_VU_WIDTH                          1  /* IN1_VU */
+#define WM8994_IN1L_MUTE                        0x0080  /* IN1L_MUTE */
+#define WM8994_IN1L_MUTE_MASK                   0x0080  /* IN1L_MUTE */
+#define WM8994_IN1L_MUTE_SHIFT                       7  /* IN1L_MUTE */
+#define WM8994_IN1L_MUTE_WIDTH                       1  /* IN1L_MUTE */
+#define WM8994_IN1L_ZC                          0x0040  /* IN1L_ZC */
+#define WM8994_IN1L_ZC_MASK                     0x0040  /* IN1L_ZC */
+#define WM8994_IN1L_ZC_SHIFT                         6  /* IN1L_ZC */
+#define WM8994_IN1L_ZC_WIDTH                         1  /* IN1L_ZC */
+#define WM8994_IN1L_VOL_MASK                    0x001F  /* IN1L_VOL - [4:0] */
+#define WM8994_IN1L_VOL_SHIFT                        0  /* IN1L_VOL - [4:0] */
+#define WM8994_IN1L_VOL_WIDTH                        5  /* IN1L_VOL - [4:0] */
+
+/*
+ * R25 (0x19) - Left Line Input 3&4 Volume
+ */
+#define WM8994_IN2_VU                           0x0100  /* IN2_VU */
+#define WM8994_IN2_VU_MASK                      0x0100  /* IN2_VU */
+#define WM8994_IN2_VU_SHIFT                          8  /* IN2_VU */
+#define WM8994_IN2_VU_WIDTH                          1  /* IN2_VU */
+#define WM8994_IN2L_MUTE                        0x0080  /* IN2L_MUTE */
+#define WM8994_IN2L_MUTE_MASK                   0x0080  /* IN2L_MUTE */
+#define WM8994_IN2L_MUTE_SHIFT                       7  /* IN2L_MUTE */
+#define WM8994_IN2L_MUTE_WIDTH                       1  /* IN2L_MUTE */
+#define WM8994_IN2L_ZC                          0x0040  /* IN2L_ZC */
+#define WM8994_IN2L_ZC_MASK                     0x0040  /* IN2L_ZC */
+#define WM8994_IN2L_ZC_SHIFT                         6  /* IN2L_ZC */
+#define WM8994_IN2L_ZC_WIDTH                         1  /* IN2L_ZC */
+#define WM8994_IN2L_VOL_MASK                    0x001F  /* IN2L_VOL - [4:0] */
+#define WM8994_IN2L_VOL_SHIFT                        0  /* IN2L_VOL - [4:0] */
+#define WM8994_IN2L_VOL_WIDTH                        5  /* IN2L_VOL - [4:0] */
+
+/*
+ * R26 (0x1A) - Right Line Input 1&2 Volume
+ */
+#define WM8994_IN1_VU                           0x0100  /* IN1_VU */
+#define WM8994_IN1_VU_MASK                      0x0100  /* IN1_VU */
+#define WM8994_IN1_VU_SHIFT                          8  /* IN1_VU */
+#define WM8994_IN1_VU_WIDTH                          1  /* IN1_VU */
+#define WM8994_IN1R_MUTE                        0x0080  /* IN1R_MUTE */
+#define WM8994_IN1R_MUTE_MASK                   0x0080  /* IN1R_MUTE */
+#define WM8994_IN1R_MUTE_SHIFT                       7  /* IN1R_MUTE */
+#define WM8994_IN1R_MUTE_WIDTH                       1  /* IN1R_MUTE */
+#define WM8994_IN1R_ZC                          0x0040  /* IN1R_ZC */
+#define WM8994_IN1R_ZC_MASK                     0x0040  /* IN1R_ZC */
+#define WM8994_IN1R_ZC_SHIFT                         6  /* IN1R_ZC */
+#define WM8994_IN1R_ZC_WIDTH                         1  /* IN1R_ZC */
+#define WM8994_IN1R_VOL_MASK                    0x001F  /* IN1R_VOL - [4:0] */
+#define WM8994_IN1R_VOL_SHIFT                        0  /* IN1R_VOL - [4:0] */
+#define WM8994_IN1R_VOL_WIDTH                        5  /* IN1R_VOL - [4:0] */
+
+/*
+ * R27 (0x1B) - Right Line Input 3&4 Volume
+ */
+#define WM8994_IN2_VU                           0x0100  /* IN2_VU */
+#define WM8994_IN2_VU_MASK                      0x0100  /* IN2_VU */
+#define WM8994_IN2_VU_SHIFT                          8  /* IN2_VU */
+#define WM8994_IN2_VU_WIDTH                          1  /* IN2_VU */
+#define WM8994_IN2R_MUTE                        0x0080  /* IN2R_MUTE */
+#define WM8994_IN2R_MUTE_MASK                   0x0080  /* IN2R_MUTE */
+#define WM8994_IN2R_MUTE_SHIFT                       7  /* IN2R_MUTE */
+#define WM8994_IN2R_MUTE_WIDTH                       1  /* IN2R_MUTE */
+#define WM8994_IN2R_ZC                          0x0040  /* IN2R_ZC */
+#define WM8994_IN2R_ZC_MASK                     0x0040  /* IN2R_ZC */
+#define WM8994_IN2R_ZC_SHIFT                         6  /* IN2R_ZC */
+#define WM8994_IN2R_ZC_WIDTH                         1  /* IN2R_ZC */
+#define WM8994_IN2R_VOL_MASK                    0x001F  /* IN2R_VOL - [4:0] */
+#define WM8994_IN2R_VOL_SHIFT                        0  /* IN2R_VOL - [4:0] */
+#define WM8994_IN2R_VOL_WIDTH                        5  /* IN2R_VOL - [4:0] */
+
+/*
+ * R28 (0x1C) - Left Output Volume
+ */
+#define WM8994_HPOUT1_VU                        0x0100  /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_MASK                   0x0100  /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_SHIFT                       8  /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_WIDTH                       1  /* HPOUT1_VU */
+#define WM8994_HPOUT1L_ZC                       0x0080  /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_ZC_MASK                  0x0080  /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_ZC_SHIFT                      7  /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_ZC_WIDTH                      1  /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_MUTE_N                   0x0040  /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_MUTE_N_MASK              0x0040  /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_MUTE_N_SHIFT                  6  /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_MUTE_N_WIDTH                  1  /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_VOL_MASK                 0x003F  /* HPOUT1L_VOL - [5:0] */
+#define WM8994_HPOUT1L_VOL_SHIFT                     0  /* HPOUT1L_VOL - [5:0] */
+#define WM8994_HPOUT1L_VOL_WIDTH                     6  /* HPOUT1L_VOL - [5:0] */
+
+/*
+ * R29 (0x1D) - Right Output Volume
+ */
+#define WM8994_HPOUT1_VU                        0x0100  /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_MASK                   0x0100  /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_SHIFT                       8  /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_WIDTH                       1  /* HPOUT1_VU */
+#define WM8994_HPOUT1R_ZC                       0x0080  /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_ZC_MASK                  0x0080  /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_ZC_SHIFT                      7  /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_ZC_WIDTH                      1  /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_MUTE_N                   0x0040  /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_MUTE_N_MASK              0x0040  /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_MUTE_N_SHIFT                  6  /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_MUTE_N_WIDTH                  1  /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_VOL_MASK                 0x003F  /* HPOUT1R_VOL - [5:0] */
+#define WM8994_HPOUT1R_VOL_SHIFT                     0  /* HPOUT1R_VOL - [5:0] */
+#define WM8994_HPOUT1R_VOL_WIDTH                     6  /* HPOUT1R_VOL - [5:0] */
+
+/*
+ * R30 (0x1E) - Line Outputs Volume
+ */
+#define WM8994_LINEOUT1N_MUTE                   0x0040  /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1N_MUTE_MASK              0x0040  /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1N_MUTE_SHIFT                  6  /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1N_MUTE_WIDTH                  1  /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1P_MUTE                   0x0020  /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1P_MUTE_MASK              0x0020  /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1P_MUTE_SHIFT                  5  /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1P_MUTE_WIDTH                  1  /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1_VOL                     0x0010  /* LINEOUT1_VOL */
+#define WM8994_LINEOUT1_VOL_MASK                0x0010  /* LINEOUT1_VOL */
+#define WM8994_LINEOUT1_VOL_SHIFT                    4  /* LINEOUT1_VOL */
+#define WM8994_LINEOUT1_VOL_WIDTH                    1  /* LINEOUT1_VOL */
+#define WM8994_LINEOUT2N_MUTE                   0x0004  /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2N_MUTE_MASK              0x0004  /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2N_MUTE_SHIFT                  2  /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2N_MUTE_WIDTH                  1  /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2P_MUTE                   0x0002  /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2P_MUTE_MASK              0x0002  /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2P_MUTE_SHIFT                  1  /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2P_MUTE_WIDTH                  1  /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2_VOL                     0x0001  /* LINEOUT2_VOL */
+#define WM8994_LINEOUT2_VOL_MASK                0x0001  /* LINEOUT2_VOL */
+#define WM8994_LINEOUT2_VOL_SHIFT                    0  /* LINEOUT2_VOL */
+#define WM8994_LINEOUT2_VOL_WIDTH                    1  /* LINEOUT2_VOL */
+
+/*
+ * R31 (0x1F) - HPOUT2 Volume
+ */
+#define WM8994_HPOUT2_MUTE                      0x0020  /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_MUTE_MASK                 0x0020  /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_MUTE_SHIFT                     5  /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_MUTE_WIDTH                     1  /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_VOL                       0x0010  /* HPOUT2_VOL */
+#define WM8994_HPOUT2_VOL_MASK                  0x0010  /* HPOUT2_VOL */
+#define WM8994_HPOUT2_VOL_SHIFT                      4  /* HPOUT2_VOL */
+#define WM8994_HPOUT2_VOL_WIDTH                      1  /* HPOUT2_VOL */
+
+/*
+ * R32 (0x20) - Left OPGA Volume
+ */
+#define WM8994_MIXOUT_VU                        0x0100  /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_MASK                   0x0100  /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_SHIFT                       8  /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_WIDTH                       1  /* MIXOUT_VU */
+#define WM8994_MIXOUTL_ZC                       0x0080  /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_ZC_MASK                  0x0080  /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_ZC_SHIFT                      7  /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_ZC_WIDTH                      1  /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_MUTE_N                   0x0040  /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_MUTE_N_MASK              0x0040  /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_MUTE_N_SHIFT                  6  /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_MUTE_N_WIDTH                  1  /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_VOL_MASK                 0x003F  /* MIXOUTL_VOL - [5:0] */
+#define WM8994_MIXOUTL_VOL_SHIFT                     0  /* MIXOUTL_VOL - [5:0] */
+#define WM8994_MIXOUTL_VOL_WIDTH                     6  /* MIXOUTL_VOL - [5:0] */
+
+/*
+ * R33 (0x21) - Right OPGA Volume
+ */
+#define WM8994_MIXOUT_VU                        0x0100  /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_MASK                   0x0100  /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_SHIFT                       8  /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_WIDTH                       1  /* MIXOUT_VU */
+#define WM8994_MIXOUTR_ZC                       0x0080  /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_ZC_MASK                  0x0080  /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_ZC_SHIFT                      7  /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_ZC_WIDTH                      1  /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_MUTE_N                   0x0040  /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_MUTE_N_MASK              0x0040  /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_MUTE_N_SHIFT                  6  /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_MUTE_N_WIDTH                  1  /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_VOL_MASK                 0x003F  /* MIXOUTR_VOL - [5:0] */
+#define WM8994_MIXOUTR_VOL_SHIFT                     0  /* MIXOUTR_VOL - [5:0] */
+#define WM8994_MIXOUTR_VOL_WIDTH                     6  /* MIXOUTR_VOL - [5:0] */
+
+/*
+ * R34 (0x22) - SPKMIXL Attenuation
+ */
+#define WM8994_DAC2L_SPKMIXL_VOL                0x0040  /* DAC2L_SPKMIXL_VOL */
+#define WM8994_DAC2L_SPKMIXL_VOL_MASK           0x0040  /* DAC2L_SPKMIXL_VOL */
+#define WM8994_DAC2L_SPKMIXL_VOL_SHIFT               6  /* DAC2L_SPKMIXL_VOL */
+#define WM8994_DAC2L_SPKMIXL_VOL_WIDTH               1  /* DAC2L_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL               0x0020  /* MIXINL_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL_MASK          0x0020  /* MIXINL_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL_SHIFT              5  /* MIXINL_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL_WIDTH              1  /* MIXINL_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL                0x0010  /* IN1LP_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL_MASK           0x0010  /* IN1LP_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL_SHIFT               4  /* IN1LP_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL_WIDTH               1  /* IN1LP_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL              0x0008  /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL_MASK         0x0008  /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL_SHIFT             3  /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL_WIDTH             1  /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL                0x0004  /* DAC1L_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL_MASK           0x0004  /* DAC1L_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL_SHIFT               2  /* DAC1L_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL_WIDTH               1  /* DAC1L_SPKMIXL_VOL */
+#define WM8994_SPKMIXL_VOL_MASK                 0x0003  /* SPKMIXL_VOL - [1:0] */
+#define WM8994_SPKMIXL_VOL_SHIFT                     0  /* SPKMIXL_VOL - [1:0] */
+#define WM8994_SPKMIXL_VOL_WIDTH                     2  /* SPKMIXL_VOL - [1:0] */
+
+/*
+ * R35 (0x23) - SPKMIXR Attenuation
+ */
+#define WM8994_SPKOUT_CLASSAB                   0x0100  /* SPKOUT_CLASSAB */
+#define WM8994_SPKOUT_CLASSAB_MASK              0x0100  /* SPKOUT_CLASSAB */
+#define WM8994_SPKOUT_CLASSAB_SHIFT                  8  /* SPKOUT_CLASSAB */
+#define WM8994_SPKOUT_CLASSAB_WIDTH                  1  /* SPKOUT_CLASSAB */
+#define WM8994_DAC2R_SPKMIXR_VOL                0x0040  /* DAC2R_SPKMIXR_VOL */
+#define WM8994_DAC2R_SPKMIXR_VOL_MASK           0x0040  /* DAC2R_SPKMIXR_VOL */
+#define WM8994_DAC2R_SPKMIXR_VOL_SHIFT               6  /* DAC2R_SPKMIXR_VOL */
+#define WM8994_DAC2R_SPKMIXR_VOL_WIDTH               1  /* DAC2R_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL               0x0020  /* MIXINR_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL_MASK          0x0020  /* MIXINR_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL_SHIFT              5  /* MIXINR_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL_WIDTH              1  /* MIXINR_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL                0x0010  /* IN1RP_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL_MASK           0x0010  /* IN1RP_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL_SHIFT               4  /* IN1RP_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL_WIDTH               1  /* IN1RP_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL              0x0008  /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL_MASK         0x0008  /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL_SHIFT             3  /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL_WIDTH             1  /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL                0x0004  /* DAC1R_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL_MASK           0x0004  /* DAC1R_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL_SHIFT               2  /* DAC1R_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL_WIDTH               1  /* DAC1R_SPKMIXR_VOL */
+#define WM8994_SPKMIXR_VOL_MASK                 0x0003  /* SPKMIXR_VOL - [1:0] */
+#define WM8994_SPKMIXR_VOL_SHIFT                     0  /* SPKMIXR_VOL - [1:0] */
+#define WM8994_SPKMIXR_VOL_WIDTH                     2  /* SPKMIXR_VOL - [1:0] */
+
+/*
+ * R36 (0x24) - SPKOUT Mixers
+ */
+#define WM8994_IN2LRP_TO_SPKOUTL                0x0020  /* IN2LRP_TO_SPKOUTL */
+#define WM8994_IN2LRP_TO_SPKOUTL_MASK           0x0020  /* IN2LRP_TO_SPKOUTL */
+#define WM8994_IN2LRP_TO_SPKOUTL_SHIFT               5  /* IN2LRP_TO_SPKOUTL */
+#define WM8994_IN2LRP_TO_SPKOUTL_WIDTH               1  /* IN2LRP_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL               0x0010  /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL_MASK          0x0010  /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL_SHIFT              4  /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL_WIDTH              1  /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL               0x0008  /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL_MASK          0x0008  /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL_SHIFT              3  /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL_WIDTH              1  /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_IN2LRP_TO_SPKOUTR                0x0004  /* IN2LRP_TO_SPKOUTR */
+#define WM8994_IN2LRP_TO_SPKOUTR_MASK           0x0004  /* IN2LRP_TO_SPKOUTR */
+#define WM8994_IN2LRP_TO_SPKOUTR_SHIFT               2  /* IN2LRP_TO_SPKOUTR */
+#define WM8994_IN2LRP_TO_SPKOUTR_WIDTH               1  /* IN2LRP_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR               0x0002  /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR_MASK          0x0002  /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR_SHIFT              1  /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR_WIDTH              1  /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR               0x0001  /* SPKMIXR_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR_MASK          0x0001  /* SPKMIXR_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR_SHIFT              0  /* SPKMIXR_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR_WIDTH              1  /* SPKMIXR_TO_SPKOUTR */
+
+/*
+ * R37 (0x25) - ClassD
+ */
+#define WM8994_SPKOUTL_BOOST_MASK               0x0038  /* SPKOUTL_BOOST - [5:3] */
+#define WM8994_SPKOUTL_BOOST_SHIFT                   3  /* SPKOUTL_BOOST - [5:3] */
+#define WM8994_SPKOUTL_BOOST_WIDTH                   3  /* SPKOUTL_BOOST - [5:3] */
+#define WM8994_SPKOUTR_BOOST_MASK               0x0007  /* SPKOUTR_BOOST - [2:0] */
+#define WM8994_SPKOUTR_BOOST_SHIFT                   0  /* SPKOUTR_BOOST - [2:0] */
+#define WM8994_SPKOUTR_BOOST_WIDTH                   3  /* SPKOUTR_BOOST - [2:0] */
+
+/*
+ * R38 (0x26) - Speaker Volume Left
+ */
+#define WM8994_SPKOUT_VU                        0x0100  /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_MASK                   0x0100  /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_SHIFT                       8  /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_WIDTH                       1  /* SPKOUT_VU */
+#define WM8994_SPKOUTL_ZC                       0x0080  /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_ZC_MASK                  0x0080  /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_ZC_SHIFT                      7  /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_ZC_WIDTH                      1  /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_MUTE_N                   0x0040  /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_MUTE_N_MASK              0x0040  /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_MUTE_N_SHIFT                  6  /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_MUTE_N_WIDTH                  1  /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_VOL_MASK                 0x003F  /* SPKOUTL_VOL - [5:0] */
+#define WM8994_SPKOUTL_VOL_SHIFT                     0  /* SPKOUTL_VOL - [5:0] */
+#define WM8994_SPKOUTL_VOL_WIDTH                     6  /* SPKOUTL_VOL - [5:0] */
+
+/*
+ * R39 (0x27) - Speaker Volume Right
+ */
+#define WM8994_SPKOUT_VU                        0x0100  /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_MASK                   0x0100  /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_SHIFT                       8  /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_WIDTH                       1  /* SPKOUT_VU */
+#define WM8994_SPKOUTR_ZC                       0x0080  /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_ZC_MASK                  0x0080  /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_ZC_SHIFT                      7  /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_ZC_WIDTH                      1  /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_MUTE_N                   0x0040  /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_MUTE_N_MASK              0x0040  /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_MUTE_N_SHIFT                  6  /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_MUTE_N_WIDTH                  1  /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_VOL_MASK                 0x003F  /* SPKOUTR_VOL - [5:0] */
+#define WM8994_SPKOUTR_VOL_SHIFT                     0  /* SPKOUTR_VOL - [5:0] */
+#define WM8994_SPKOUTR_VOL_WIDTH                     6  /* SPKOUTR_VOL - [5:0] */
+
+/*
+ * R40 (0x28) - Input Mixer (2)
+ */
+#define WM8994_IN2LP_TO_IN2L                    0x0080  /* IN2LP_TO_IN2L */
+#define WM8994_IN2LP_TO_IN2L_MASK               0x0080  /* IN2LP_TO_IN2L */
+#define WM8994_IN2LP_TO_IN2L_SHIFT                   7  /* IN2LP_TO_IN2L */
+#define WM8994_IN2LP_TO_IN2L_WIDTH                   1  /* IN2LP_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L                    0x0040  /* IN2LN_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L_MASK               0x0040  /* IN2LN_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L_SHIFT                   6  /* IN2LN_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L_WIDTH                   1  /* IN2LN_TO_IN2L */
+#define WM8994_IN1LP_TO_IN1L                    0x0020  /* IN1LP_TO_IN1L */
+#define WM8994_IN1LP_TO_IN1L_MASK               0x0020  /* IN1LP_TO_IN1L */
+#define WM8994_IN1LP_TO_IN1L_SHIFT                   5  /* IN1LP_TO_IN1L */
+#define WM8994_IN1LP_TO_IN1L_WIDTH                   1  /* IN1LP_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L                    0x0010  /* IN1LN_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L_MASK               0x0010  /* IN1LN_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L_SHIFT                   4  /* IN1LN_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L_WIDTH                   1  /* IN1LN_TO_IN1L */
+#define WM8994_IN2RP_TO_IN2R                    0x0008  /* IN2RP_TO_IN2R */
+#define WM8994_IN2RP_TO_IN2R_MASK               0x0008  /* IN2RP_TO_IN2R */
+#define WM8994_IN2RP_TO_IN2R_SHIFT                   3  /* IN2RP_TO_IN2R */
+#define WM8994_IN2RP_TO_IN2R_WIDTH                   1  /* IN2RP_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R                    0x0004  /* IN2RN_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R_MASK               0x0004  /* IN2RN_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R_SHIFT                   2  /* IN2RN_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R_WIDTH                   1  /* IN2RN_TO_IN2R */
+#define WM8994_IN1RP_TO_IN1R                    0x0002  /* IN1RP_TO_IN1R */
+#define WM8994_IN1RP_TO_IN1R_MASK               0x0002  /* IN1RP_TO_IN1R */
+#define WM8994_IN1RP_TO_IN1R_SHIFT                   1  /* IN1RP_TO_IN1R */
+#define WM8994_IN1RP_TO_IN1R_WIDTH                   1  /* IN1RP_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R                    0x0001  /* IN1RN_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R_MASK               0x0001  /* IN1RN_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R_SHIFT                   0  /* IN1RN_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R_WIDTH                   1  /* IN1RN_TO_IN1R */
+
+/*
+ * R41 (0x29) - Input Mixer (3)
+ */
+#define WM8994_IN2L_TO_MIXINL                   0x0100  /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_TO_MIXINL_MASK              0x0100  /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_TO_MIXINL_SHIFT                  8  /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_TO_MIXINL_WIDTH                  1  /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_MIXINL_VOL                  0x0080  /* IN2L_MIXINL_VOL */
+#define WM8994_IN2L_MIXINL_VOL_MASK             0x0080  /* IN2L_MIXINL_VOL */
+#define WM8994_IN2L_MIXINL_VOL_SHIFT                 7  /* IN2L_MIXINL_VOL */
+#define WM8994_IN2L_MIXINL_VOL_WIDTH                 1  /* IN2L_MIXINL_VOL */
+#define WM8994_IN1L_TO_MIXINL                   0x0020  /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_TO_MIXINL_MASK              0x0020  /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_TO_MIXINL_SHIFT                  5  /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_TO_MIXINL_WIDTH                  1  /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_MIXINL_VOL                  0x0010  /* IN1L_MIXINL_VOL */
+#define WM8994_IN1L_MIXINL_VOL_MASK             0x0010  /* IN1L_MIXINL_VOL */
+#define WM8994_IN1L_MIXINL_VOL_SHIFT                 4  /* IN1L_MIXINL_VOL */
+#define WM8994_IN1L_MIXINL_VOL_WIDTH                 1  /* IN1L_MIXINL_VOL */
+#define WM8994_MIXOUTL_MIXINL_VOL_MASK          0x0007  /* MIXOUTL_MIXINL_VOL - [2:0] */
+#define WM8994_MIXOUTL_MIXINL_VOL_SHIFT              0  /* MIXOUTL_MIXINL_VOL - [2:0] */
+#define WM8994_MIXOUTL_MIXINL_VOL_WIDTH              3  /* MIXOUTL_MIXINL_VOL - [2:0] */
+
+/*
+ * R42 (0x2A) - Input Mixer (4)
+ */
+#define WM8994_IN2R_TO_MIXINR                   0x0100  /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_TO_MIXINR_MASK              0x0100  /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_TO_MIXINR_SHIFT                  8  /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_TO_MIXINR_WIDTH                  1  /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_MIXINR_VOL                  0x0080  /* IN2R_MIXINR_VOL */
+#define WM8994_IN2R_MIXINR_VOL_MASK             0x0080  /* IN2R_MIXINR_VOL */
+#define WM8994_IN2R_MIXINR_VOL_SHIFT                 7  /* IN2R_MIXINR_VOL */
+#define WM8994_IN2R_MIXINR_VOL_WIDTH                 1  /* IN2R_MIXINR_VOL */
+#define WM8994_IN1R_TO_MIXINR                   0x0020  /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_TO_MIXINR_MASK              0x0020  /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_TO_MIXINR_SHIFT                  5  /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_TO_MIXINR_WIDTH                  1  /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_MIXINR_VOL                  0x0010  /* IN1R_MIXINR_VOL */
+#define WM8994_IN1R_MIXINR_VOL_MASK             0x0010  /* IN1R_MIXINR_VOL */
+#define WM8994_IN1R_MIXINR_VOL_SHIFT                 4  /* IN1R_MIXINR_VOL */
+#define WM8994_IN1R_MIXINR_VOL_WIDTH                 1  /* IN1R_MIXINR_VOL */
+#define WM8994_MIXOUTR_MIXINR_VOL_MASK          0x0007  /* MIXOUTR_MIXINR_VOL - [2:0] */
+#define WM8994_MIXOUTR_MIXINR_VOL_SHIFT              0  /* MIXOUTR_MIXINR_VOL - [2:0] */
+#define WM8994_MIXOUTR_MIXINR_VOL_WIDTH              3  /* MIXOUTR_MIXINR_VOL - [2:0] */
+
+/*
+ * R43 (0x2B) - Input Mixer (5)
+ */
+#define WM8994_IN1LP_MIXINL_VOL_MASK            0x01C0  /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8994_IN1LP_MIXINL_VOL_SHIFT                6  /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8994_IN1LP_MIXINL_VOL_WIDTH                3  /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8994_IN2LRP_MIXINL_VOL_MASK           0x0007  /* IN2LRP_MIXINL_VOL - [2:0] */
+#define WM8994_IN2LRP_MIXINL_VOL_SHIFT               0  /* IN2LRP_MIXINL_VOL - [2:0] */
+#define WM8994_IN2LRP_MIXINL_VOL_WIDTH               3  /* IN2LRP_MIXINL_VOL - [2:0] */
+
+/*
+ * R44 (0x2C) - Input Mixer (6)
+ */
+#define WM8994_IN1RP_MIXINR_VOL_MASK            0x01C0  /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8994_IN1RP_MIXINR_VOL_SHIFT                6  /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8994_IN1RP_MIXINR_VOL_WIDTH                3  /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8994_IN2LRP_MIXINR_VOL_MASK           0x0007  /* IN2LRP_MIXINR_VOL - [2:0] */
+#define WM8994_IN2LRP_MIXINR_VOL_SHIFT               0  /* IN2LRP_MIXINR_VOL - [2:0] */
+#define WM8994_IN2LRP_MIXINR_VOL_WIDTH               3  /* IN2LRP_MIXINR_VOL - [2:0] */
+
+/*
+ * R45 (0x2D) - Output Mixer (1)
+ */
+#define WM8994_DAC1L_TO_HPOUT1L                 0x0100  /* DAC1L_TO_HPOUT1L */
+#define WM8994_DAC1L_TO_HPOUT1L_MASK            0x0100  /* DAC1L_TO_HPOUT1L */
+#define WM8994_DAC1L_TO_HPOUT1L_SHIFT                8  /* DAC1L_TO_HPOUT1L */
+#define WM8994_DAC1L_TO_HPOUT1L_WIDTH                1  /* DAC1L_TO_HPOUT1L */
+#define WM8994_MIXINR_TO_MIXOUTL                0x0080  /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINR_TO_MIXOUTL_MASK           0x0080  /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINR_TO_MIXOUTL_SHIFT               7  /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINR_TO_MIXOUTL_WIDTH               1  /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL                0x0040  /* MIXINL_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL_MASK           0x0040  /* MIXINL_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL_SHIFT               6  /* MIXINL_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL_WIDTH               1  /* MIXINL_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL                 0x0020  /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL_MASK            0x0020  /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL_SHIFT                5  /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL_WIDTH                1  /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL                 0x0010  /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL_MASK            0x0010  /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL_SHIFT                4  /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL_WIDTH                1  /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL                  0x0008  /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL_MASK             0x0008  /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL_SHIFT                 3  /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL_WIDTH                 1  /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL                  0x0004  /* IN1L_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL_MASK             0x0004  /* IN1L_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL_SHIFT                 2  /* IN1L_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL_WIDTH                 1  /* IN1L_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL                 0x0002  /* IN2LP_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL_MASK            0x0002  /* IN2LP_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL_SHIFT                1  /* IN2LP_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL_WIDTH                1  /* IN2LP_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL                 0x0001  /* DAC1L_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL_MASK            0x0001  /* DAC1L_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL_SHIFT                0  /* DAC1L_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL_WIDTH                1  /* DAC1L_TO_MIXOUTL */
+
+/*
+ * R46 (0x2E) - Output Mixer (2)
+ */
+#define WM8994_DAC1R_TO_HPOUT1R                 0x0100  /* DAC1R_TO_HPOUT1R */
+#define WM8994_DAC1R_TO_HPOUT1R_MASK            0x0100  /* DAC1R_TO_HPOUT1R */
+#define WM8994_DAC1R_TO_HPOUT1R_SHIFT                8  /* DAC1R_TO_HPOUT1R */
+#define WM8994_DAC1R_TO_HPOUT1R_WIDTH                1  /* DAC1R_TO_HPOUT1R */
+#define WM8994_MIXINL_TO_MIXOUTR                0x0080  /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINL_TO_MIXOUTR_MASK           0x0080  /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINL_TO_MIXOUTR_SHIFT               7  /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINL_TO_MIXOUTR_WIDTH               1  /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR                0x0040  /* MIXINR_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR_MASK           0x0040  /* MIXINR_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR_SHIFT               6  /* MIXINR_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR_WIDTH               1  /* MIXINR_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR                 0x0020  /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR_MASK            0x0020  /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR_SHIFT                5  /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR_WIDTH                1  /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR                 0x0010  /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR_MASK            0x0010  /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR_SHIFT                4  /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR_WIDTH                1  /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR                  0x0008  /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR_MASK             0x0008  /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR_SHIFT                 3  /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR_WIDTH                 1  /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR                  0x0004  /* IN1R_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR_MASK             0x0004  /* IN1R_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR_SHIFT                 2  /* IN1R_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR_WIDTH                 1  /* IN1R_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR                 0x0002  /* IN2RP_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR_MASK            0x0002  /* IN2RP_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR_SHIFT                1  /* IN2RP_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR_WIDTH                1  /* IN2RP_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR                 0x0001  /* DAC1R_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR_MASK            0x0001  /* DAC1R_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR_SHIFT                0  /* DAC1R_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR_WIDTH                1  /* DAC1R_TO_MIXOUTR */
+
+/*
+ * R47 (0x2F) - Output Mixer (3)
+ */
+#define WM8994_IN2LP_MIXOUTL_VOL_MASK           0x0E00  /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2LP_MIXOUTL_VOL_SHIFT               9  /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2LP_MIXOUTL_VOL_WIDTH               3  /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2LN_MIXOUTL_VOL_MASK           0x01C0  /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTL_VOL_SHIFT               6  /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTL_VOL_WIDTH               3  /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN1R_MIXOUTL_VOL_MASK            0x0038  /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8994_IN1R_MIXOUTL_VOL_SHIFT                3  /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8994_IN1R_MIXOUTL_VOL_WIDTH                3  /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8994_IN1L_MIXOUTL_VOL_MASK            0x0007  /* IN1L_MIXOUTL_VOL - [2:0] */
+#define WM8994_IN1L_MIXOUTL_VOL_SHIFT                0  /* IN1L_MIXOUTL_VOL - [2:0] */
+#define WM8994_IN1L_MIXOUTL_VOL_WIDTH                3  /* IN1L_MIXOUTL_VOL - [2:0] */
+
+/*
+ * R48 (0x30) - Output Mixer (4)
+ */
+#define WM8994_IN2RP_MIXOUTR_VOL_MASK           0x0E00  /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2RP_MIXOUTR_VOL_SHIFT               9  /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2RP_MIXOUTR_VOL_WIDTH               3  /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2RN_MIXOUTR_VOL_MASK           0x01C0  /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTR_VOL_SHIFT               6  /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTR_VOL_WIDTH               3  /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN1L_MIXOUTR_VOL_MASK            0x0038  /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8994_IN1L_MIXOUTR_VOL_SHIFT                3  /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8994_IN1L_MIXOUTR_VOL_WIDTH                3  /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8994_IN1R_MIXOUTR_VOL_MASK            0x0007  /* IN1R_MIXOUTR_VOL - [2:0] */
+#define WM8994_IN1R_MIXOUTR_VOL_SHIFT                0  /* IN1R_MIXOUTR_VOL - [2:0] */
+#define WM8994_IN1R_MIXOUTR_VOL_WIDTH                3  /* IN1R_MIXOUTR_VOL - [2:0] */
+
+/*
+ * R49 (0x31) - Output Mixer (5)
+ */
+#define WM8994_DAC1L_MIXOUTL_VOL_MASK           0x0E00  /* DAC1L_MIXOUTL_VOL - [11:9] */
+#define WM8994_DAC1L_MIXOUTL_VOL_SHIFT               9  /* DAC1L_MIXOUTL_VOL - [11:9] */
+#define WM8994_DAC1L_MIXOUTL_VOL_WIDTH               3  /* DAC1L_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2RN_MIXOUTL_VOL_MASK           0x01C0  /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTL_VOL_SHIFT               6  /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTL_VOL_WIDTH               3  /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8994_MIXINR_MIXOUTL_VOL_MASK          0x0038  /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8994_MIXINR_MIXOUTL_VOL_SHIFT              3  /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8994_MIXINR_MIXOUTL_VOL_WIDTH              3  /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8994_MIXINL_MIXOUTL_VOL_MASK          0x0007  /* MIXINL_MIXOUTL_VOL - [2:0] */
+#define WM8994_MIXINL_MIXOUTL_VOL_SHIFT              0  /* MIXINL_MIXOUTL_VOL - [2:0] */
+#define WM8994_MIXINL_MIXOUTL_VOL_WIDTH              3  /* MIXINL_MIXOUTL_VOL - [2:0] */
+
+/*
+ * R50 (0x32) - Output Mixer (6)
+ */
+#define WM8994_DAC1R_MIXOUTR_VOL_MASK           0x0E00  /* DAC1R_MIXOUTR_VOL - [11:9] */
+#define WM8994_DAC1R_MIXOUTR_VOL_SHIFT               9  /* DAC1R_MIXOUTR_VOL - [11:9] */
+#define WM8994_DAC1R_MIXOUTR_VOL_WIDTH               3  /* DAC1R_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2LN_MIXOUTR_VOL_MASK           0x01C0  /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTR_VOL_SHIFT               6  /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTR_VOL_WIDTH               3  /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8994_MIXINL_MIXOUTR_VOL_MASK          0x0038  /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8994_MIXINL_MIXOUTR_VOL_SHIFT              3  /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8994_MIXINL_MIXOUTR_VOL_WIDTH              3  /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8994_MIXINR_MIXOUTR_VOL_MASK          0x0007  /* MIXINR_MIXOUTR_VOL - [2:0] */
+#define WM8994_MIXINR_MIXOUTR_VOL_SHIFT              0  /* MIXINR_MIXOUTR_VOL - [2:0] */
+#define WM8994_MIXINR_MIXOUTR_VOL_WIDTH              3  /* MIXINR_MIXOUTR_VOL - [2:0] */
+
+/*
+ * R51 (0x33) - HPOUT2 Mixer
+ */
+#define WM8994_IN2LRP_TO_HPOUT2                 0x0020  /* IN2LRP_TO_HPOUT2 */
+#define WM8994_IN2LRP_TO_HPOUT2_MASK            0x0020  /* IN2LRP_TO_HPOUT2 */
+#define WM8994_IN2LRP_TO_HPOUT2_SHIFT                5  /* IN2LRP_TO_HPOUT2 */
+#define WM8994_IN2LRP_TO_HPOUT2_WIDTH                1  /* IN2LRP_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2             0x0010  /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2_MASK        0x0010  /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2_SHIFT            4  /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2_WIDTH            1  /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2             0x0008  /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2_MASK        0x0008  /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2_SHIFT            3  /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2_WIDTH            1  /* MIXOUTRVOL_TO_HPOUT2 */
+
+/*
+ * R52 (0x34) - Line Mixer (1)
+ */
+#define WM8994_MIXOUTL_TO_LINEOUT1N             0x0040  /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTL_TO_LINEOUT1N_MASK        0x0040  /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTL_TO_LINEOUT1N_SHIFT            6  /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTL_TO_LINEOUT1N_WIDTH            1  /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N             0x0020  /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N_MASK        0x0020  /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N_SHIFT            5  /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N_WIDTH            1  /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_LINEOUT1_MODE                    0x0010  /* LINEOUT1_MODE */
+#define WM8994_LINEOUT1_MODE_MASK               0x0010  /* LINEOUT1_MODE */
+#define WM8994_LINEOUT1_MODE_SHIFT                   4  /* LINEOUT1_MODE */
+#define WM8994_LINEOUT1_MODE_WIDTH                   1  /* LINEOUT1_MODE */
+#define WM8994_IN1R_TO_LINEOUT1P                0x0004  /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1R_TO_LINEOUT1P_MASK           0x0004  /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1R_TO_LINEOUT1P_SHIFT               2  /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1R_TO_LINEOUT1P_WIDTH               1  /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P                0x0002  /* IN1L_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P_MASK           0x0002  /* IN1L_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P_SHIFT               1  /* IN1L_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P_WIDTH               1  /* IN1L_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P             0x0001  /* MIXOUTL_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P_MASK        0x0001  /* MIXOUTL_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P_SHIFT            0  /* MIXOUTL_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P_WIDTH            1  /* MIXOUTL_TO_LINEOUT1P */
+
+/*
+ * R53 (0x35) - Line Mixer (2)
+ */
+#define WM8994_MIXOUTR_TO_LINEOUT2N             0x0040  /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTR_TO_LINEOUT2N_MASK        0x0040  /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTR_TO_LINEOUT2N_SHIFT            6  /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTR_TO_LINEOUT2N_WIDTH            1  /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N             0x0020  /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N_MASK        0x0020  /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N_SHIFT            5  /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N_WIDTH            1  /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_LINEOUT2_MODE                    0x0010  /* LINEOUT2_MODE */
+#define WM8994_LINEOUT2_MODE_MASK               0x0010  /* LINEOUT2_MODE */
+#define WM8994_LINEOUT2_MODE_SHIFT                   4  /* LINEOUT2_MODE */
+#define WM8994_LINEOUT2_MODE_WIDTH                   1  /* LINEOUT2_MODE */
+#define WM8994_IN1L_TO_LINEOUT2P                0x0004  /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1L_TO_LINEOUT2P_MASK           0x0004  /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1L_TO_LINEOUT2P_SHIFT               2  /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1L_TO_LINEOUT2P_WIDTH               1  /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P                0x0002  /* IN1R_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P_MASK           0x0002  /* IN1R_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P_SHIFT               1  /* IN1R_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P_WIDTH               1  /* IN1R_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P             0x0001  /* MIXOUTR_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P_MASK        0x0001  /* MIXOUTR_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P_SHIFT            0  /* MIXOUTR_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P_WIDTH            1  /* MIXOUTR_TO_LINEOUT2P */
+
+/*
+ * R54 (0x36) - Speaker Mixer
+ */
+#define WM8994_DAC2L_TO_SPKMIXL                 0x0200  /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2L_TO_SPKMIXL_MASK            0x0200  /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2L_TO_SPKMIXL_SHIFT                9  /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2L_TO_SPKMIXL_WIDTH                1  /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2R_TO_SPKMIXR                 0x0100  /* DAC2R_TO_SPKMIXR */
+#define WM8994_DAC2R_TO_SPKMIXR_MASK            0x0100  /* DAC2R_TO_SPKMIXR */
+#define WM8994_DAC2R_TO_SPKMIXR_SHIFT                8  /* DAC2R_TO_SPKMIXR */
+#define WM8994_DAC2R_TO_SPKMIXR_WIDTH                1  /* DAC2R_TO_SPKMIXR */
+#define WM8994_MIXINL_TO_SPKMIXL                0x0080  /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINL_TO_SPKMIXL_MASK           0x0080  /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINL_TO_SPKMIXL_SHIFT               7  /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINL_TO_SPKMIXL_WIDTH               1  /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINR_TO_SPKMIXR                0x0040  /* MIXINR_TO_SPKMIXR */
+#define WM8994_MIXINR_TO_SPKMIXR_MASK           0x0040  /* MIXINR_TO_SPKMIXR */
+#define WM8994_MIXINR_TO_SPKMIXR_SHIFT               6  /* MIXINR_TO_SPKMIXR */
+#define WM8994_MIXINR_TO_SPKMIXR_WIDTH               1  /* MIXINR_TO_SPKMIXR */
+#define WM8994_IN1LP_TO_SPKMIXL                 0x0020  /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1LP_TO_SPKMIXL_MASK            0x0020  /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1LP_TO_SPKMIXL_SHIFT                5  /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1LP_TO_SPKMIXL_WIDTH                1  /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1RP_TO_SPKMIXR                 0x0010  /* IN1RP_TO_SPKMIXR */
+#define WM8994_IN1RP_TO_SPKMIXR_MASK            0x0010  /* IN1RP_TO_SPKMIXR */
+#define WM8994_IN1RP_TO_SPKMIXR_SHIFT                4  /* IN1RP_TO_SPKMIXR */
+#define WM8994_IN1RP_TO_SPKMIXR_WIDTH                1  /* IN1RP_TO_SPKMIXR */
+#define WM8994_MIXOUTL_TO_SPKMIXL               0x0008  /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTL_TO_SPKMIXL_MASK          0x0008  /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTL_TO_SPKMIXL_SHIFT              3  /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTL_TO_SPKMIXL_WIDTH              1  /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTR_TO_SPKMIXR               0x0004  /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_MIXOUTR_TO_SPKMIXR_MASK          0x0004  /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_MIXOUTR_TO_SPKMIXR_SHIFT              2  /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_MIXOUTR_TO_SPKMIXR_WIDTH              1  /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_DAC1L_TO_SPKMIXL                 0x0002  /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1L_TO_SPKMIXL_MASK            0x0002  /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1L_TO_SPKMIXL_SHIFT                1  /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1L_TO_SPKMIXL_WIDTH                1  /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1R_TO_SPKMIXR                 0x0001  /* DAC1R_TO_SPKMIXR */
+#define WM8994_DAC1R_TO_SPKMIXR_MASK            0x0001  /* DAC1R_TO_SPKMIXR */
+#define WM8994_DAC1R_TO_SPKMIXR_SHIFT                0  /* DAC1R_TO_SPKMIXR */
+#define WM8994_DAC1R_TO_SPKMIXR_WIDTH                1  /* DAC1R_TO_SPKMIXR */
+
+/*
+ * R55 (0x37) - Additional Control
+ */
+#define WM8994_LINEOUT1_FB                      0x0080  /* LINEOUT1_FB */
+#define WM8994_LINEOUT1_FB_MASK                 0x0080  /* LINEOUT1_FB */
+#define WM8994_LINEOUT1_FB_SHIFT                     7  /* LINEOUT1_FB */
+#define WM8994_LINEOUT1_FB_WIDTH                     1  /* LINEOUT1_FB */
+#define WM8994_LINEOUT2_FB                      0x0040  /* LINEOUT2_FB */
+#define WM8994_LINEOUT2_FB_MASK                 0x0040  /* LINEOUT2_FB */
+#define WM8994_LINEOUT2_FB_SHIFT                     6  /* LINEOUT2_FB */
+#define WM8994_LINEOUT2_FB_WIDTH                     1  /* LINEOUT2_FB */
+#define WM8994_VROI                             0x0001  /* VROI */
+#define WM8994_VROI_MASK                        0x0001  /* VROI */
+#define WM8994_VROI_SHIFT                            0  /* VROI */
+#define WM8994_VROI_WIDTH                            1  /* VROI */
+
+/*
+ * R56 (0x38) - AntiPOP (1)
+ */
+#define WM8994_LINEOUT_VMID_BUF_ENA             0x0080  /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_LINEOUT_VMID_BUF_ENA_MASK        0x0080  /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_LINEOUT_VMID_BUF_ENA_SHIFT            7  /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_LINEOUT_VMID_BUF_ENA_WIDTH            1  /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_HPOUT2_IN_ENA                    0x0040  /* HPOUT2_IN_ENA */
+#define WM8994_HPOUT2_IN_ENA_MASK               0x0040  /* HPOUT2_IN_ENA */
+#define WM8994_HPOUT2_IN_ENA_SHIFT                   6  /* HPOUT2_IN_ENA */
+#define WM8994_HPOUT2_IN_ENA_WIDTH                   1  /* HPOUT2_IN_ENA */
+#define WM8994_LINEOUT1_DISCH                   0x0020  /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT1_DISCH_MASK              0x0020  /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT1_DISCH_SHIFT                  5  /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT1_DISCH_WIDTH                  1  /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT2_DISCH                   0x0010  /* LINEOUT2_DISCH */
+#define WM8994_LINEOUT2_DISCH_MASK              0x0010  /* LINEOUT2_DISCH */
+#define WM8994_LINEOUT2_DISCH_SHIFT                  4  /* LINEOUT2_DISCH */
+#define WM8994_LINEOUT2_DISCH_WIDTH                  1  /* LINEOUT2_DISCH */
+
+/*
+ * R57 (0x39) - AntiPOP (2)
+ */
+#define WM8994_MICB2_DISCH                      0x0100  /* MICB2_DISCH */
+#define WM8994_MICB2_DISCH_MASK                 0x0100  /* MICB2_DISCH */
+#define WM8994_MICB2_DISCH_SHIFT                     8  /* MICB2_DISCH */
+#define WM8994_MICB2_DISCH_WIDTH                     1  /* MICB2_DISCH */
+#define WM8994_MICB1_DISCH                      0x0080  /* MICB1_DISCH */
+#define WM8994_MICB1_DISCH_MASK                 0x0080  /* MICB1_DISCH */
+#define WM8994_MICB1_DISCH_SHIFT                     7  /* MICB1_DISCH */
+#define WM8994_MICB1_DISCH_WIDTH                     1  /* MICB1_DISCH */
+#define WM8994_VMID_RAMP_MASK                   0x0060  /* VMID_RAMP - [6:5] */
+#define WM8994_VMID_RAMP_SHIFT                       5  /* VMID_RAMP - [6:5] */
+#define WM8994_VMID_RAMP_WIDTH                       2  /* VMID_RAMP - [6:5] */
+#define WM8994_VMID_BUF_ENA                     0x0008  /* VMID_BUF_ENA */
+#define WM8994_VMID_BUF_ENA_MASK                0x0008  /* VMID_BUF_ENA */
+#define WM8994_VMID_BUF_ENA_SHIFT                    3  /* VMID_BUF_ENA */
+#define WM8994_VMID_BUF_ENA_WIDTH                    1  /* VMID_BUF_ENA */
+#define WM8994_STARTUP_BIAS_ENA                 0x0004  /* STARTUP_BIAS_ENA */
+#define WM8994_STARTUP_BIAS_ENA_MASK            0x0004  /* STARTUP_BIAS_ENA */
+#define WM8994_STARTUP_BIAS_ENA_SHIFT                2  /* STARTUP_BIAS_ENA */
+#define WM8994_STARTUP_BIAS_ENA_WIDTH                1  /* STARTUP_BIAS_ENA */
+#define WM8994_BIAS_SRC                         0x0002  /* BIAS_SRC */
+#define WM8994_BIAS_SRC_MASK                    0x0002  /* BIAS_SRC */
+#define WM8994_BIAS_SRC_SHIFT                        1  /* BIAS_SRC */
+#define WM8994_BIAS_SRC_WIDTH                        1  /* BIAS_SRC */
+#define WM8994_VMID_DISCH                       0x0001  /* VMID_DISCH */
+#define WM8994_VMID_DISCH_MASK                  0x0001  /* VMID_DISCH */
+#define WM8994_VMID_DISCH_SHIFT                      0  /* VMID_DISCH */
+#define WM8994_VMID_DISCH_WIDTH                      1  /* VMID_DISCH */
+
+/*
+ * R58 (0x3A) - MICBIAS
+ */
+#define WM8994_MICD_SCTHR_MASK                  0x00C0  /* MICD_SCTHR - [7:6] */
+#define WM8994_MICD_SCTHR_SHIFT                      6  /* MICD_SCTHR - [7:6] */
+#define WM8994_MICD_SCTHR_WIDTH                      2  /* MICD_SCTHR - [7:6] */
+#define WM8994_MICD_THR_MASK                    0x0038  /* MICD_THR - [5:3] */
+#define WM8994_MICD_THR_SHIFT                        3  /* MICD_THR - [5:3] */
+#define WM8994_MICD_THR_WIDTH                        3  /* MICD_THR - [5:3] */
+#define WM8994_MICD_ENA                         0x0004  /* MICD_ENA */
+#define WM8994_MICD_ENA_MASK                    0x0004  /* MICD_ENA */
+#define WM8994_MICD_ENA_SHIFT                        2  /* MICD_ENA */
+#define WM8994_MICD_ENA_WIDTH                        1  /* MICD_ENA */
+#define WM8994_MICB2_LVL                        0x0002  /* MICB2_LVL */
+#define WM8994_MICB2_LVL_MASK                   0x0002  /* MICB2_LVL */
+#define WM8994_MICB2_LVL_SHIFT                       1  /* MICB2_LVL */
+#define WM8994_MICB2_LVL_WIDTH                       1  /* MICB2_LVL */
+#define WM8994_MICB1_LVL                        0x0001  /* MICB1_LVL */
+#define WM8994_MICB1_LVL_MASK                   0x0001  /* MICB1_LVL */
+#define WM8994_MICB1_LVL_SHIFT                       0  /* MICB1_LVL */
+#define WM8994_MICB1_LVL_WIDTH                       1  /* MICB1_LVL */
+
+/*
+ * R59 (0x3B) - LDO 1
+ */
+#define WM8994_LDO1_VSEL_MASK                   0x000E  /* LDO1_VSEL - [3:1] */
+#define WM8994_LDO1_VSEL_SHIFT                       1  /* LDO1_VSEL - [3:1] */
+#define WM8994_LDO1_VSEL_WIDTH                       3  /* LDO1_VSEL - [3:1] */
+#define WM8994_LDO1_DISCH                       0x0001  /* LDO1_DISCH */
+#define WM8994_LDO1_DISCH_MASK                  0x0001  /* LDO1_DISCH */
+#define WM8994_LDO1_DISCH_SHIFT                      0  /* LDO1_DISCH */
+#define WM8994_LDO1_DISCH_WIDTH                      1  /* LDO1_DISCH */
+
+/*
+ * R60 (0x3C) - LDO 2
+ */
+#define WM8994_LDO2_VSEL_MASK                   0x0006  /* LDO2_VSEL - [2:1] */
+#define WM8994_LDO2_VSEL_SHIFT                       1  /* LDO2_VSEL - [2:1] */
+#define WM8994_LDO2_VSEL_WIDTH                       2  /* LDO2_VSEL - [2:1] */
+#define WM8994_LDO2_DISCH                       0x0001  /* LDO2_DISCH */
+#define WM8994_LDO2_DISCH_MASK                  0x0001  /* LDO2_DISCH */
+#define WM8994_LDO2_DISCH_SHIFT                      0  /* LDO2_DISCH */
+#define WM8994_LDO2_DISCH_WIDTH                      1  /* LDO2_DISCH */
+
+/*
+ * R76 (0x4C) - Charge Pump (1)
+ */
+#define WM8994_CP_ENA                           0x8000  /* CP_ENA */
+#define WM8994_CP_ENA_MASK                      0x8000  /* CP_ENA */
+#define WM8994_CP_ENA_SHIFT                         15  /* CP_ENA */
+#define WM8994_CP_ENA_WIDTH                          1  /* CP_ENA */
+
+/*
+ * R81 (0x51) - Class W (1)
+ */
+#define WM8994_CP_DYN_SRC_SEL_MASK              0x0300  /* CP_DYN_SRC_SEL - [9:8] */
+#define WM8994_CP_DYN_SRC_SEL_SHIFT                  8  /* CP_DYN_SRC_SEL - [9:8] */
+#define WM8994_CP_DYN_SRC_SEL_WIDTH                  2  /* CP_DYN_SRC_SEL - [9:8] */
+#define WM8994_CP_DYN_PWR                       0x0001  /* CP_DYN_PWR */
+#define WM8994_CP_DYN_PWR_MASK                  0x0001  /* CP_DYN_PWR */
+#define WM8994_CP_DYN_PWR_SHIFT                      0  /* CP_DYN_PWR */
+#define WM8994_CP_DYN_PWR_WIDTH                      1  /* CP_DYN_PWR */
+
+/*
+ * R84 (0x54) - DC Servo (1)
+ */
+#define WM8994_DCS_TRIG_SINGLE_1                0x2000  /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_1_MASK           0x2000  /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_1_SHIFT              13  /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_1_WIDTH               1  /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_0                0x1000  /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SINGLE_0_MASK           0x1000  /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SINGLE_0_SHIFT              12  /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SINGLE_0_WIDTH               1  /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SERIES_1                0x0200  /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_1_MASK           0x0200  /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_1_SHIFT               9  /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_1_WIDTH               1  /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_0                0x0100  /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_SERIES_0_MASK           0x0100  /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_SERIES_0_SHIFT               8  /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_SERIES_0_WIDTH               1  /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_STARTUP_1               0x0020  /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_1_MASK          0x0020  /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_1_SHIFT              5  /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_1_WIDTH              1  /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_0               0x0010  /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_STARTUP_0_MASK          0x0010  /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_STARTUP_0_SHIFT              4  /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_STARTUP_0_WIDTH              1  /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_DAC_WR_1                0x0008  /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_1_MASK           0x0008  /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_1_SHIFT               3  /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_1_WIDTH               1  /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_0                0x0004  /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_TRIG_DAC_WR_0_MASK           0x0004  /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_TRIG_DAC_WR_0_SHIFT               2  /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_TRIG_DAC_WR_0_WIDTH               1  /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_ENA_CHAN_1                   0x0002  /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_1_MASK              0x0002  /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_1_SHIFT                  1  /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_1_WIDTH                  1  /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_0                   0x0001  /* DCS_ENA_CHAN_0 */
+#define WM8994_DCS_ENA_CHAN_0_MASK              0x0001  /* DCS_ENA_CHAN_0 */
+#define WM8994_DCS_ENA_CHAN_0_SHIFT                  0  /* DCS_ENA_CHAN_0 */
+#define WM8994_DCS_ENA_CHAN_0_WIDTH                  1  /* DCS_ENA_CHAN_0 */
+
+/*
+ * R85 (0x55) - DC Servo (2)
+ */
+#define WM8994_DCS_SERIES_NO_01_MASK            0x0FE0  /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8994_DCS_SERIES_NO_01_SHIFT                5  /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8994_DCS_SERIES_NO_01_WIDTH                7  /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8994_DCS_TIMER_PERIOD_01_MASK         0x000F  /* DCS_TIMER_PERIOD_01 - [3:0] */
+#define WM8994_DCS_TIMER_PERIOD_01_SHIFT             0  /* DCS_TIMER_PERIOD_01 - [3:0] */
+#define WM8994_DCS_TIMER_PERIOD_01_WIDTH             4  /* DCS_TIMER_PERIOD_01 - [3:0] */
+
+/*
+ * R87 (0x57) - DC Servo (4)
+ */
+#define WM8994_DCS_DAC_WR_VAL_1_MASK            0xFF00  /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8994_DCS_DAC_WR_VAL_1_SHIFT                8  /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8994_DCS_DAC_WR_VAL_1_WIDTH                8  /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8994_DCS_DAC_WR_VAL_0_MASK            0x00FF  /* DCS_DAC_WR_VAL_0 - [7:0] */
+#define WM8994_DCS_DAC_WR_VAL_0_SHIFT                0  /* DCS_DAC_WR_VAL_0 - [7:0] */
+#define WM8994_DCS_DAC_WR_VAL_0_WIDTH                8  /* DCS_DAC_WR_VAL_0 - [7:0] */
+
+/*
+ * R88 (0x58) - DC Servo Readback
+ */
+#define WM8994_DCS_CAL_COMPLETE_MASK            0x0300  /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8994_DCS_CAL_COMPLETE_SHIFT                8  /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8994_DCS_CAL_COMPLETE_WIDTH                2  /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8994_DCS_DAC_WR_COMPLETE_MASK         0x0030  /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8994_DCS_DAC_WR_COMPLETE_SHIFT             4  /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8994_DCS_DAC_WR_COMPLETE_WIDTH             2  /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8994_DCS_STARTUP_COMPLETE_MASK        0x0003  /* DCS_STARTUP_COMPLETE - [1:0] */
+#define WM8994_DCS_STARTUP_COMPLETE_SHIFT            0  /* DCS_STARTUP_COMPLETE - [1:0] */
+#define WM8994_DCS_STARTUP_COMPLETE_WIDTH            2  /* DCS_STARTUP_COMPLETE - [1:0] */
+
+/*
+ * R96 (0x60) - Analogue HP (1)
+ */
+#define WM8994_HPOUT1L_RMV_SHORT                0x0080  /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_RMV_SHORT_MASK           0x0080  /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_RMV_SHORT_SHIFT               7  /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_RMV_SHORT_WIDTH               1  /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_OUTP                     0x0040  /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_OUTP_MASK                0x0040  /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_OUTP_SHIFT                    6  /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_OUTP_WIDTH                    1  /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_DLY                      0x0020  /* HPOUT1L_DLY */
+#define WM8994_HPOUT1L_DLY_MASK                 0x0020  /* HPOUT1L_DLY */
+#define WM8994_HPOUT1L_DLY_SHIFT                     5  /* HPOUT1L_DLY */
+#define WM8994_HPOUT1L_DLY_WIDTH                     1  /* HPOUT1L_DLY */
+#define WM8994_HPOUT1R_RMV_SHORT                0x0008  /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_RMV_SHORT_MASK           0x0008  /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_RMV_SHORT_SHIFT               3  /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_RMV_SHORT_WIDTH               1  /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_OUTP                     0x0004  /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_OUTP_MASK                0x0004  /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_OUTP_SHIFT                    2  /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_OUTP_WIDTH                    1  /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_DLY                      0x0002  /* HPOUT1R_DLY */
+#define WM8994_HPOUT1R_DLY_MASK                 0x0002  /* HPOUT1R_DLY */
+#define WM8994_HPOUT1R_DLY_SHIFT                     1  /* HPOUT1R_DLY */
+#define WM8994_HPOUT1R_DLY_WIDTH                     1  /* HPOUT1R_DLY */
+
+/*
+ * R256 (0x100) - Chip Revision
+ */
+#define WM8994_CHIP_REV_MASK                    0x000F  /* CHIP_REV - [3:0] */
+#define WM8994_CHIP_REV_SHIFT                        0  /* CHIP_REV - [3:0] */
+#define WM8994_CHIP_REV_WIDTH                        4  /* CHIP_REV - [3:0] */
+
+/*
+ * R257 (0x101) - Control Interface
+ */
+#define WM8994_SPI_CONTRD                       0x0040  /* SPI_CONTRD */
+#define WM8994_SPI_CONTRD_MASK                  0x0040  /* SPI_CONTRD */
+#define WM8994_SPI_CONTRD_SHIFT                      6  /* SPI_CONTRD */
+#define WM8994_SPI_CONTRD_WIDTH                      1  /* SPI_CONTRD */
+#define WM8994_SPI_4WIRE                        0x0020  /* SPI_4WIRE */
+#define WM8994_SPI_4WIRE_MASK                   0x0020  /* SPI_4WIRE */
+#define WM8994_SPI_4WIRE_SHIFT                       5  /* SPI_4WIRE */
+#define WM8994_SPI_4WIRE_WIDTH                       1  /* SPI_4WIRE */
+#define WM8994_SPI_CFG                          0x0010  /* SPI_CFG */
+#define WM8994_SPI_CFG_MASK                     0x0010  /* SPI_CFG */
+#define WM8994_SPI_CFG_SHIFT                         4  /* SPI_CFG */
+#define WM8994_SPI_CFG_WIDTH                         1  /* SPI_CFG */
+#define WM8994_AUTO_INC                         0x0004  /* AUTO_INC */
+#define WM8994_AUTO_INC_MASK                    0x0004  /* AUTO_INC */
+#define WM8994_AUTO_INC_SHIFT                        2  /* AUTO_INC */
+#define WM8994_AUTO_INC_WIDTH                        1  /* AUTO_INC */
+
+/*
+ * R272 (0x110) - Write Sequencer Ctrl (1)
+ */
+#define WM8994_WSEQ_ENA                         0x8000  /* WSEQ_ENA */
+#define WM8994_WSEQ_ENA_MASK                    0x8000  /* WSEQ_ENA */
+#define WM8994_WSEQ_ENA_SHIFT                       15  /* WSEQ_ENA */
+#define WM8994_WSEQ_ENA_WIDTH                        1  /* WSEQ_ENA */
+#define WM8994_WSEQ_ABORT                       0x0200  /* WSEQ_ABORT */
+#define WM8994_WSEQ_ABORT_MASK                  0x0200  /* WSEQ_ABORT */
+#define WM8994_WSEQ_ABORT_SHIFT                      9  /* WSEQ_ABORT */
+#define WM8994_WSEQ_ABORT_WIDTH                      1  /* WSEQ_ABORT */
+#define WM8994_WSEQ_START                       0x0100  /* WSEQ_START */
+#define WM8994_WSEQ_START_MASK                  0x0100  /* WSEQ_START */
+#define WM8994_WSEQ_START_SHIFT                      8  /* WSEQ_START */
+#define WM8994_WSEQ_START_WIDTH                      1  /* WSEQ_START */
+#define WM8994_WSEQ_START_INDEX_MASK            0x007F  /* WSEQ_START_INDEX - [6:0] */
+#define WM8994_WSEQ_START_INDEX_SHIFT                0  /* WSEQ_START_INDEX - [6:0] */
+#define WM8994_WSEQ_START_INDEX_WIDTH                7  /* WSEQ_START_INDEX - [6:0] */
+
+/*
+ * R273 (0x111) - Write Sequencer Ctrl (2)
+ */
+#define WM8994_WSEQ_BUSY                        0x0100  /* WSEQ_BUSY */
+#define WM8994_WSEQ_BUSY_MASK                   0x0100  /* WSEQ_BUSY */
+#define WM8994_WSEQ_BUSY_SHIFT                       8  /* WSEQ_BUSY */
+#define WM8994_WSEQ_BUSY_WIDTH                       1  /* WSEQ_BUSY */
+#define WM8994_WSEQ_CURRENT_INDEX_MASK          0x007F  /* WSEQ_CURRENT_INDEX - [6:0] */
+#define WM8994_WSEQ_CURRENT_INDEX_SHIFT              0  /* WSEQ_CURRENT_INDEX - [6:0] */
+#define WM8994_WSEQ_CURRENT_INDEX_WIDTH              7  /* WSEQ_CURRENT_INDEX - [6:0] */
+
+/*
+ * R512 (0x200) - AIF1 Clocking (1)
+ */
+#define WM8994_AIF1CLK_SRC_MASK                 0x0018  /* AIF1CLK_SRC - [4:3] */
+#define WM8994_AIF1CLK_SRC_SHIFT                     3  /* AIF1CLK_SRC - [4:3] */
+#define WM8994_AIF1CLK_SRC_WIDTH                     2  /* AIF1CLK_SRC - [4:3] */
+#define WM8994_AIF1CLK_INV                      0x0004  /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_INV_MASK                 0x0004  /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_INV_SHIFT                     2  /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_INV_WIDTH                     1  /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_DIV                      0x0002  /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_DIV_MASK                 0x0002  /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_DIV_SHIFT                     1  /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_DIV_WIDTH                     1  /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_ENA                      0x0001  /* AIF1CLK_ENA */
+#define WM8994_AIF1CLK_ENA_MASK                 0x0001  /* AIF1CLK_ENA */
+#define WM8994_AIF1CLK_ENA_SHIFT                     0  /* AIF1CLK_ENA */
+#define WM8994_AIF1CLK_ENA_WIDTH                     1  /* AIF1CLK_ENA */
+
+/*
+ * R513 (0x201) - AIF1 Clocking (2)
+ */
+#define WM8994_AIF1DAC_DIV_MASK                 0x0038  /* AIF1DAC_DIV - [5:3] */
+#define WM8994_AIF1DAC_DIV_SHIFT                     3  /* AIF1DAC_DIV - [5:3] */
+#define WM8994_AIF1DAC_DIV_WIDTH                     3  /* AIF1DAC_DIV - [5:3] */
+#define WM8994_AIF1ADC_DIV_MASK                 0x0007  /* AIF1ADC_DIV - [2:0] */
+#define WM8994_AIF1ADC_DIV_SHIFT                     0  /* AIF1ADC_DIV - [2:0] */
+#define WM8994_AIF1ADC_DIV_WIDTH                     3  /* AIF1ADC_DIV - [2:0] */
+
+/*
+ * R516 (0x204) - AIF2 Clocking (1)
+ */
+#define WM8994_AIF2CLK_SRC_MASK                 0x0018  /* AIF2CLK_SRC - [4:3] */
+#define WM8994_AIF2CLK_SRC_SHIFT                     3  /* AIF2CLK_SRC - [4:3] */
+#define WM8994_AIF2CLK_SRC_WIDTH                     2  /* AIF2CLK_SRC - [4:3] */
+#define WM8994_AIF2CLK_INV                      0x0004  /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_INV_MASK                 0x0004  /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_INV_SHIFT                     2  /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_INV_WIDTH                     1  /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_DIV                      0x0002  /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_DIV_MASK                 0x0002  /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_DIV_SHIFT                     1  /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_DIV_WIDTH                     1  /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_ENA                      0x0001  /* AIF2CLK_ENA */
+#define WM8994_AIF2CLK_ENA_MASK                 0x0001  /* AIF2CLK_ENA */
+#define WM8994_AIF2CLK_ENA_SHIFT                     0  /* AIF2CLK_ENA */
+#define WM8994_AIF2CLK_ENA_WIDTH                     1  /* AIF2CLK_ENA */
+
+/*
+ * R517 (0x205) - AIF2 Clocking (2)
+ */
+#define WM8994_AIF2DAC_DIV_MASK                 0x0038  /* AIF2DAC_DIV - [5:3] */
+#define WM8994_AIF2DAC_DIV_SHIFT                     3  /* AIF2DAC_DIV - [5:3] */
+#define WM8994_AIF2DAC_DIV_WIDTH                     3  /* AIF2DAC_DIV - [5:3] */
+#define WM8994_AIF2ADC_DIV_MASK                 0x0007  /* AIF2ADC_DIV - [2:0] */
+#define WM8994_AIF2ADC_DIV_SHIFT                     0  /* AIF2ADC_DIV - [2:0] */
+#define WM8994_AIF2ADC_DIV_WIDTH                     3  /* AIF2ADC_DIV - [2:0] */
+
+/*
+ * R520 (0x208) - Clocking (1)
+ */
+#define WM8994_TOCLK_ENA                        0x0010  /* TOCLK_ENA */
+#define WM8994_TOCLK_ENA_MASK                   0x0010  /* TOCLK_ENA */
+#define WM8994_TOCLK_ENA_SHIFT                       4  /* TOCLK_ENA */
+#define WM8994_TOCLK_ENA_WIDTH                       1  /* TOCLK_ENA */
+#define WM8994_AIF1DSPCLK_ENA                   0x0008  /* AIF1DSPCLK_ENA */
+#define WM8994_AIF1DSPCLK_ENA_MASK              0x0008  /* AIF1DSPCLK_ENA */
+#define WM8994_AIF1DSPCLK_ENA_SHIFT                  3  /* AIF1DSPCLK_ENA */
+#define WM8994_AIF1DSPCLK_ENA_WIDTH                  1  /* AIF1DSPCLK_ENA */
+#define WM8994_AIF2DSPCLK_ENA                   0x0004  /* AIF2DSPCLK_ENA */
+#define WM8994_AIF2DSPCLK_ENA_MASK              0x0004  /* AIF2DSPCLK_ENA */
+#define WM8994_AIF2DSPCLK_ENA_SHIFT                  2  /* AIF2DSPCLK_ENA */
+#define WM8994_AIF2DSPCLK_ENA_WIDTH                  1  /* AIF2DSPCLK_ENA */
+#define WM8994_SYSDSPCLK_ENA                    0x0002  /* SYSDSPCLK_ENA */
+#define WM8994_SYSDSPCLK_ENA_MASK               0x0002  /* SYSDSPCLK_ENA */
+#define WM8994_SYSDSPCLK_ENA_SHIFT                   1  /* SYSDSPCLK_ENA */
+#define WM8994_SYSDSPCLK_ENA_WIDTH                   1  /* SYSDSPCLK_ENA */
+#define WM8994_SYSCLK_SRC                       0x0001  /* SYSCLK_SRC */
+#define WM8994_SYSCLK_SRC_MASK                  0x0001  /* SYSCLK_SRC */
+#define WM8994_SYSCLK_SRC_SHIFT                      0  /* SYSCLK_SRC */
+#define WM8994_SYSCLK_SRC_WIDTH                      1  /* SYSCLK_SRC */
+
+/*
+ * R521 (0x209) - Clocking (2)
+ */
+#define WM8994_TOCLK_DIV_MASK                   0x0700  /* TOCLK_DIV - [10:8] */
+#define WM8994_TOCLK_DIV_SHIFT                       8  /* TOCLK_DIV - [10:8] */
+#define WM8994_TOCLK_DIV_WIDTH                       3  /* TOCLK_DIV - [10:8] */
+#define WM8994_DBCLK_DIV_MASK                   0x0070  /* DBCLK_DIV - [6:4] */
+#define WM8994_DBCLK_DIV_SHIFT                       4  /* DBCLK_DIV - [6:4] */
+#define WM8994_DBCLK_DIV_WIDTH                       3  /* DBCLK_DIV - [6:4] */
+#define WM8994_OPCLK_DIV_MASK                   0x0007  /* OPCLK_DIV - [2:0] */
+#define WM8994_OPCLK_DIV_SHIFT                       0  /* OPCLK_DIV - [2:0] */
+#define WM8994_OPCLK_DIV_WIDTH                       3  /* OPCLK_DIV - [2:0] */
+
+/*
+ * R528 (0x210) - AIF1 Rate
+ */
+#define WM8994_AIF1_SR_MASK                     0x00F0  /* AIF1_SR - [7:4] */
+#define WM8994_AIF1_SR_SHIFT                         4  /* AIF1_SR - [7:4] */
+#define WM8994_AIF1_SR_WIDTH                         4  /* AIF1_SR - [7:4] */
+#define WM8994_AIF1CLK_RATE_MASK                0x000F  /* AIF1CLK_RATE - [3:0] */
+#define WM8994_AIF1CLK_RATE_SHIFT                    0  /* AIF1CLK_RATE - [3:0] */
+#define WM8994_AIF1CLK_RATE_WIDTH                    4  /* AIF1CLK_RATE - [3:0] */
+
+/*
+ * R529 (0x211) - AIF2 Rate
+ */
+#define WM8994_AIF2_SR_MASK                     0x00F0  /* AIF2_SR - [7:4] */
+#define WM8994_AIF2_SR_SHIFT                         4  /* AIF2_SR - [7:4] */
+#define WM8994_AIF2_SR_WIDTH                         4  /* AIF2_SR - [7:4] */
+#define WM8994_AIF2CLK_RATE_MASK                0x000F  /* AIF2CLK_RATE - [3:0] */
+#define WM8994_AIF2CLK_RATE_SHIFT                    0  /* AIF2CLK_RATE - [3:0] */
+#define WM8994_AIF2CLK_RATE_WIDTH                    4  /* AIF2CLK_RATE - [3:0] */
+
+/*
+ * R530 (0x212) - Rate Status
+ */
+#define WM8994_SR_ERROR_MASK                    0x000F  /* SR_ERROR - [3:0] */
+#define WM8994_SR_ERROR_SHIFT                        0  /* SR_ERROR - [3:0] */
+#define WM8994_SR_ERROR_WIDTH                        4  /* SR_ERROR - [3:0] */
+
+/*
+ * R544 (0x220) - FLL1 Control (1)
+ */
+#define WM8994_FLL1_FRAC                        0x0004  /* FLL1_FRAC */
+#define WM8994_FLL1_FRAC_MASK                   0x0004  /* FLL1_FRAC */
+#define WM8994_FLL1_FRAC_SHIFT                       2  /* FLL1_FRAC */
+#define WM8994_FLL1_FRAC_WIDTH                       1  /* FLL1_FRAC */
+#define WM8994_FLL1_OSC_ENA                     0x0002  /* FLL1_OSC_ENA */
+#define WM8994_FLL1_OSC_ENA_MASK                0x0002  /* FLL1_OSC_ENA */
+#define WM8994_FLL1_OSC_ENA_SHIFT                    1  /* FLL1_OSC_ENA */
+#define WM8994_FLL1_OSC_ENA_WIDTH                    1  /* FLL1_OSC_ENA */
+#define WM8994_FLL1_ENA                         0x0001  /* FLL1_ENA */
+#define WM8994_FLL1_ENA_MASK                    0x0001  /* FLL1_ENA */
+#define WM8994_FLL1_ENA_SHIFT                        0  /* FLL1_ENA */
+#define WM8994_FLL1_ENA_WIDTH                        1  /* FLL1_ENA */
+
+/*
+ * R545 (0x221) - FLL1 Control (2)
+ */
+#define WM8994_FLL1_OUTDIV_MASK                 0x3F00  /* FLL1_OUTDIV - [13:8] */
+#define WM8994_FLL1_OUTDIV_SHIFT                     8  /* FLL1_OUTDIV - [13:8] */
+#define WM8994_FLL1_OUTDIV_WIDTH                     6  /* FLL1_OUTDIV - [13:8] */
+#define WM8994_FLL1_CTRL_RATE_MASK              0x0070  /* FLL1_CTRL_RATE - [6:4] */
+#define WM8994_FLL1_CTRL_RATE_SHIFT                  4  /* FLL1_CTRL_RATE - [6:4] */
+#define WM8994_FLL1_CTRL_RATE_WIDTH                  3  /* FLL1_CTRL_RATE - [6:4] */
+#define WM8994_FLL1_FRATIO_MASK                 0x0007  /* FLL1_FRATIO - [2:0] */
+#define WM8994_FLL1_FRATIO_SHIFT                     0  /* FLL1_FRATIO - [2:0] */
+#define WM8994_FLL1_FRATIO_WIDTH                     3  /* FLL1_FRATIO - [2:0] */
+
+/*
+ * R546 (0x222) - FLL1 Control (3)
+ */
+#define WM8994_FLL1_K_MASK                      0xFFFF  /* FLL1_K - [15:0] */
+#define WM8994_FLL1_K_SHIFT                          0  /* FLL1_K - [15:0] */
+#define WM8994_FLL1_K_WIDTH                         16  /* FLL1_K - [15:0] */
+
+/*
+ * R547 (0x223) - FLL1 Control (4)
+ */
+#define WM8994_FLL1_N_MASK                      0x7FE0  /* FLL1_N - [14:5] */
+#define WM8994_FLL1_N_SHIFT                          5  /* FLL1_N - [14:5] */
+#define WM8994_FLL1_N_WIDTH                         10  /* FLL1_N - [14:5] */
+#define WM8994_FLL1_LOOP_GAIN_MASK              0x000F  /* FLL1_LOOP_GAIN - [3:0] */
+#define WM8994_FLL1_LOOP_GAIN_SHIFT                  0  /* FLL1_LOOP_GAIN - [3:0] */
+#define WM8994_FLL1_LOOP_GAIN_WIDTH                  4  /* FLL1_LOOP_GAIN - [3:0] */
+
+/*
+ * R548 (0x224) - FLL1 Control (5)
+ */
+#define WM8994_FLL1_FRC_NCO_VAL_MASK            0x1F80  /* FLL1_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL1_FRC_NCO_VAL_SHIFT                7  /* FLL1_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL1_FRC_NCO_VAL_WIDTH                6  /* FLL1_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL1_FRC_NCO                     0x0040  /* FLL1_FRC_NCO */
+#define WM8994_FLL1_FRC_NCO_MASK                0x0040  /* FLL1_FRC_NCO */
+#define WM8994_FLL1_FRC_NCO_SHIFT                    6  /* FLL1_FRC_NCO */
+#define WM8994_FLL1_FRC_NCO_WIDTH                    1  /* FLL1_FRC_NCO */
+#define WM8994_FLL1_REFCLK_DIV_MASK             0x0018  /* FLL1_REFCLK_DIV - [4:3] */
+#define WM8994_FLL1_REFCLK_DIV_SHIFT                 3  /* FLL1_REFCLK_DIV - [4:3] */
+#define WM8994_FLL1_REFCLK_DIV_WIDTH                 2  /* FLL1_REFCLK_DIV - [4:3] */
+#define WM8994_FLL1_REFCLK_SRC_MASK             0x0003  /* FLL1_REFCLK_SRC - [1:0] */
+#define WM8994_FLL1_REFCLK_SRC_SHIFT                 0  /* FLL1_REFCLK_SRC - [1:0] */
+#define WM8994_FLL1_REFCLK_SRC_WIDTH                 2  /* FLL1_REFCLK_SRC - [1:0] */
+
+/*
+ * R576 (0x240) - FLL2 Control (1)
+ */
+#define WM8994_FLL2_FRAC                        0x0004  /* FLL2_FRAC */
+#define WM8994_FLL2_FRAC_MASK                   0x0004  /* FLL2_FRAC */
+#define WM8994_FLL2_FRAC_SHIFT                       2  /* FLL2_FRAC */
+#define WM8994_FLL2_FRAC_WIDTH                       1  /* FLL2_FRAC */
+#define WM8994_FLL2_OSC_ENA                     0x0002  /* FLL2_OSC_ENA */
+#define WM8994_FLL2_OSC_ENA_MASK                0x0002  /* FLL2_OSC_ENA */
+#define WM8994_FLL2_OSC_ENA_SHIFT                    1  /* FLL2_OSC_ENA */
+#define WM8994_FLL2_OSC_ENA_WIDTH                    1  /* FLL2_OSC_ENA */
+#define WM8994_FLL2_ENA                         0x0001  /* FLL2_ENA */
+#define WM8994_FLL2_ENA_MASK                    0x0001  /* FLL2_ENA */
+#define WM8994_FLL2_ENA_SHIFT                        0  /* FLL2_ENA */
+#define WM8994_FLL2_ENA_WIDTH                        1  /* FLL2_ENA */
+
+/*
+ * R577 (0x241) - FLL2 Control (2)
+ */
+#define WM8994_FLL2_OUTDIV_MASK                 0x3F00  /* FLL2_OUTDIV - [13:8] */
+#define WM8994_FLL2_OUTDIV_SHIFT                     8  /* FLL2_OUTDIV - [13:8] */
+#define WM8994_FLL2_OUTDIV_WIDTH                     6  /* FLL2_OUTDIV - [13:8] */
+#define WM8994_FLL2_CTRL_RATE_MASK              0x0070  /* FLL2_CTRL_RATE - [6:4] */
+#define WM8994_FLL2_CTRL_RATE_SHIFT                  4  /* FLL2_CTRL_RATE - [6:4] */
+#define WM8994_FLL2_CTRL_RATE_WIDTH                  3  /* FLL2_CTRL_RATE - [6:4] */
+#define WM8994_FLL2_FRATIO_MASK                 0x0007  /* FLL2_FRATIO - [2:0] */
+#define WM8994_FLL2_FRATIO_SHIFT                     0  /* FLL2_FRATIO - [2:0] */
+#define WM8994_FLL2_FRATIO_WIDTH                     3  /* FLL2_FRATIO - [2:0] */
+
+/*
+ * R578 (0x242) - FLL2 Control (3)
+ */
+#define WM8994_FLL2_K_MASK                      0xFFFF  /* FLL2_K - [15:0] */
+#define WM8994_FLL2_K_SHIFT                          0  /* FLL2_K - [15:0] */
+#define WM8994_FLL2_K_WIDTH                         16  /* FLL2_K - [15:0] */
+
+/*
+ * R579 (0x243) - FLL2 Control (4)
+ */
+#define WM8994_FLL2_N_MASK                      0x7FE0  /* FLL2_N - [14:5] */
+#define WM8994_FLL2_N_SHIFT                          5  /* FLL2_N - [14:5] */
+#define WM8994_FLL2_N_WIDTH                         10  /* FLL2_N - [14:5] */
+#define WM8994_FLL2_LOOP_GAIN_MASK              0x000F  /* FLL2_LOOP_GAIN - [3:0] */
+#define WM8994_FLL2_LOOP_GAIN_SHIFT                  0  /* FLL2_LOOP_GAIN - [3:0] */
+#define WM8994_FLL2_LOOP_GAIN_WIDTH                  4  /* FLL2_LOOP_GAIN - [3:0] */
+
+/*
+ * R580 (0x244) - FLL2 Control (5)
+ */
+#define WM8994_FLL2_FRC_NCO_VAL_MASK            0x1F80  /* FLL2_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL2_FRC_NCO_VAL_SHIFT                7  /* FLL2_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL2_FRC_NCO_VAL_WIDTH                6  /* FLL2_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL2_FRC_NCO                     0x0040  /* FLL2_FRC_NCO */
+#define WM8994_FLL2_FRC_NCO_MASK                0x0040  /* FLL2_FRC_NCO */
+#define WM8994_FLL2_FRC_NCO_SHIFT                    6  /* FLL2_FRC_NCO */
+#define WM8994_FLL2_FRC_NCO_WIDTH                    1  /* FLL2_FRC_NCO */
+#define WM8994_FLL2_REFCLK_DIV_MASK             0x0018  /* FLL2_REFCLK_DIV - [4:3] */
+#define WM8994_FLL2_REFCLK_DIV_SHIFT                 3  /* FLL2_REFCLK_DIV - [4:3] */
+#define WM8994_FLL2_REFCLK_DIV_WIDTH                 2  /* FLL2_REFCLK_DIV - [4:3] */
+#define WM8994_FLL2_REFCLK_SRC_MASK             0x0003  /* FLL2_REFCLK_SRC - [1:0] */
+#define WM8994_FLL2_REFCLK_SRC_SHIFT                 0  /* FLL2_REFCLK_SRC - [1:0] */
+#define WM8994_FLL2_REFCLK_SRC_WIDTH                 2  /* FLL2_REFCLK_SRC - [1:0] */
+
+/*
+ * R768 (0x300) - AIF1 Control (1)
+ */
+#define WM8994_AIF1ADCL_SRC                     0x8000  /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCL_SRC_MASK                0x8000  /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCL_SRC_SHIFT                   15  /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCL_SRC_WIDTH                    1  /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCR_SRC                     0x4000  /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADCR_SRC_MASK                0x4000  /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADCR_SRC_SHIFT                   14  /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADCR_SRC_WIDTH                    1  /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADC_TDM                      0x2000  /* AIF1ADC_TDM */
+#define WM8994_AIF1ADC_TDM_MASK                 0x2000  /* AIF1ADC_TDM */
+#define WM8994_AIF1ADC_TDM_SHIFT                    13  /* AIF1ADC_TDM */
+#define WM8994_AIF1ADC_TDM_WIDTH                     1  /* AIF1ADC_TDM */
+#define WM8994_AIF1_BCLK_INV                    0x0100  /* AIF1_BCLK_INV */
+#define WM8994_AIF1_BCLK_INV_MASK               0x0100  /* AIF1_BCLK_INV */
+#define WM8994_AIF1_BCLK_INV_SHIFT                   8  /* AIF1_BCLK_INV */
+#define WM8994_AIF1_BCLK_INV_WIDTH                   1  /* AIF1_BCLK_INV */
+#define WM8994_AIF1_LRCLK_INV                   0x0080  /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_LRCLK_INV_MASK              0x0080  /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_LRCLK_INV_SHIFT                  7  /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_LRCLK_INV_WIDTH                  1  /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_WL_MASK                     0x0060  /* AIF1_WL - [6:5] */
+#define WM8994_AIF1_WL_SHIFT                         5  /* AIF1_WL - [6:5] */
+#define WM8994_AIF1_WL_WIDTH                         2  /* AIF1_WL - [6:5] */
+#define WM8994_AIF1_FMT_MASK                    0x0018  /* AIF1_FMT - [4:3] */
+#define WM8994_AIF1_FMT_SHIFT                        3  /* AIF1_FMT - [4:3] */
+#define WM8994_AIF1_FMT_WIDTH                        2  /* AIF1_FMT - [4:3] */
+
+/*
+ * R769 (0x301) - AIF1 Control (2)
+ */
+#define WM8994_AIF1DACL_SRC                     0x8000  /* AIF1DACL_SRC */
+#define WM8994_AIF1DACL_SRC_MASK                0x8000  /* AIF1DACL_SRC */
+#define WM8994_AIF1DACL_SRC_SHIFT                   15  /* AIF1DACL_SRC */
+#define WM8994_AIF1DACL_SRC_WIDTH                    1  /* AIF1DACL_SRC */
+#define WM8994_AIF1DACR_SRC                     0x4000  /* AIF1DACR_SRC */
+#define WM8994_AIF1DACR_SRC_MASK                0x4000  /* AIF1DACR_SRC */
+#define WM8994_AIF1DACR_SRC_SHIFT                   14  /* AIF1DACR_SRC */
+#define WM8994_AIF1DACR_SRC_WIDTH                    1  /* AIF1DACR_SRC */
+#define WM8994_AIF1DAC_BOOST_MASK               0x0C00  /* AIF1DAC_BOOST - [11:10] */
+#define WM8994_AIF1DAC_BOOST_SHIFT                  10  /* AIF1DAC_BOOST - [11:10] */
+#define WM8994_AIF1DAC_BOOST_WIDTH                   2  /* AIF1DAC_BOOST - [11:10] */
+#define WM8994_AIF1_MONO                        0x0100  /* AIF1_MONO */
+#define WM8994_AIF1_MONO_MASK                   0x0100  /* AIF1_MONO */
+#define WM8994_AIF1_MONO_SHIFT                       8  /* AIF1_MONO */
+#define WM8994_AIF1_MONO_WIDTH                       1  /* AIF1_MONO */
+#define WM8994_AIF1DAC_COMP                     0x0010  /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMP_MASK                0x0010  /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMP_SHIFT                    4  /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMP_WIDTH                    1  /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMPMODE                 0x0008  /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1DAC_COMPMODE_MASK            0x0008  /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1DAC_COMPMODE_SHIFT                3  /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1DAC_COMPMODE_WIDTH                1  /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1ADC_COMP                     0x0004  /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMP_MASK                0x0004  /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMP_SHIFT                    2  /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMP_WIDTH                    1  /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMPMODE                 0x0002  /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1ADC_COMPMODE_MASK            0x0002  /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1ADC_COMPMODE_SHIFT                1  /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1ADC_COMPMODE_WIDTH                1  /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1_LOOPBACK                    0x0001  /* AIF1_LOOPBACK */
+#define WM8994_AIF1_LOOPBACK_MASK               0x0001  /* AIF1_LOOPBACK */
+#define WM8994_AIF1_LOOPBACK_SHIFT                   0  /* AIF1_LOOPBACK */
+#define WM8994_AIF1_LOOPBACK_WIDTH                   1  /* AIF1_LOOPBACK */
+
+/*
+ * R770 (0x302) - AIF1 Master/Slave
+ */
+#define WM8994_AIF1_TRI                         0x8000  /* AIF1_TRI */
+#define WM8994_AIF1_TRI_MASK                    0x8000  /* AIF1_TRI */
+#define WM8994_AIF1_TRI_SHIFT                       15  /* AIF1_TRI */
+#define WM8994_AIF1_TRI_WIDTH                        1  /* AIF1_TRI */
+#define WM8994_AIF1_MSTR                        0x4000  /* AIF1_MSTR */
+#define WM8994_AIF1_MSTR_MASK                   0x4000  /* AIF1_MSTR */
+#define WM8994_AIF1_MSTR_SHIFT                      14  /* AIF1_MSTR */
+#define WM8994_AIF1_MSTR_WIDTH                       1  /* AIF1_MSTR */
+#define WM8994_AIF1_CLK_FRC                     0x2000  /* AIF1_CLK_FRC */
+#define WM8994_AIF1_CLK_FRC_MASK                0x2000  /* AIF1_CLK_FRC */
+#define WM8994_AIF1_CLK_FRC_SHIFT                   13  /* AIF1_CLK_FRC */
+#define WM8994_AIF1_CLK_FRC_WIDTH                    1  /* AIF1_CLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC                   0x1000  /* AIF1_LRCLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC_MASK              0x1000  /* AIF1_LRCLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC_SHIFT                 12  /* AIF1_LRCLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC_WIDTH                  1  /* AIF1_LRCLK_FRC */
+
+/*
+ * R771 (0x303) - AIF1 BCLK
+ */
+#define WM8994_AIF1_BCLK_DIV_MASK               0x01F0  /* AIF1_BCLK_DIV - [8:4] */
+#define WM8994_AIF1_BCLK_DIV_SHIFT                   4  /* AIF1_BCLK_DIV - [8:4] */
+#define WM8994_AIF1_BCLK_DIV_WIDTH                   5  /* AIF1_BCLK_DIV - [8:4] */
+
+/*
+ * R772 (0x304) - AIF1ADC LRCLK
+ */
+#define WM8994_AIF1ADC_LRCLK_DIR                0x0800  /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_LRCLK_DIR_MASK           0x0800  /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_LRCLK_DIR_SHIFT              11  /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_LRCLK_DIR_WIDTH               1  /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_RATE_MASK                0x07FF  /* AIF1ADC_RATE - [10:0] */
+#define WM8994_AIF1ADC_RATE_SHIFT                    0  /* AIF1ADC_RATE - [10:0] */
+#define WM8994_AIF1ADC_RATE_WIDTH                   11  /* AIF1ADC_RATE - [10:0] */
+
+/*
+ * R773 (0x305) - AIF1DAC LRCLK
+ */
+#define WM8994_AIF1DAC_LRCLK_DIR                0x0800  /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_LRCLK_DIR_MASK           0x0800  /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_LRCLK_DIR_SHIFT              11  /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_LRCLK_DIR_WIDTH               1  /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_RATE_MASK                0x07FF  /* AIF1DAC_RATE - [10:0] */
+#define WM8994_AIF1DAC_RATE_SHIFT                    0  /* AIF1DAC_RATE - [10:0] */
+#define WM8994_AIF1DAC_RATE_WIDTH                   11  /* AIF1DAC_RATE - [10:0] */
+
+/*
+ * R774 (0x306) - AIF1DAC Data
+ */
+#define WM8994_AIF1DACL_DAT_INV                 0x0002  /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACL_DAT_INV_MASK            0x0002  /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACL_DAT_INV_SHIFT                1  /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACL_DAT_INV_WIDTH                1  /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV                 0x0001  /* AIF1DACR_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV_MASK            0x0001  /* AIF1DACR_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV_SHIFT                0  /* AIF1DACR_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV_WIDTH                1  /* AIF1DACR_DAT_INV */
+
+/*
+ * R775 (0x307) - AIF1ADC Data
+ */
+#define WM8994_AIF1ADCL_DAT_INV                 0x0002  /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCL_DAT_INV_MASK            0x0002  /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCL_DAT_INV_SHIFT                1  /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCL_DAT_INV_WIDTH                1  /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV                 0x0001  /* AIF1ADCR_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV_MASK            0x0001  /* AIF1ADCR_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV_SHIFT                0  /* AIF1ADCR_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV_WIDTH                1  /* AIF1ADCR_DAT_INV */
+
+/*
+ * R784 (0x310) - AIF2 Control (1)
+ */
+#define WM8994_AIF2ADCL_SRC                     0x8000  /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCL_SRC_MASK                0x8000  /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCL_SRC_SHIFT                   15  /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCL_SRC_WIDTH                    1  /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCR_SRC                     0x4000  /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADCR_SRC_MASK                0x4000  /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADCR_SRC_SHIFT                   14  /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADCR_SRC_WIDTH                    1  /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADC_TDM                      0x2000  /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_MASK                 0x2000  /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_SHIFT                    13  /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_WIDTH                     1  /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_CHAN                 0x1000  /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2ADC_TDM_CHAN_MASK            0x1000  /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2ADC_TDM_CHAN_SHIFT               12  /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2ADC_TDM_CHAN_WIDTH                1  /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2_BCLK_INV                    0x0100  /* AIF2_BCLK_INV */
+#define WM8994_AIF2_BCLK_INV_MASK               0x0100  /* AIF2_BCLK_INV */
+#define WM8994_AIF2_BCLK_INV_SHIFT                   8  /* AIF2_BCLK_INV */
+#define WM8994_AIF2_BCLK_INV_WIDTH                   1  /* AIF2_BCLK_INV */
+#define WM8994_AIF2_LRCLK_INV                   0x0080  /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_LRCLK_INV_MASK              0x0080  /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_LRCLK_INV_SHIFT                  7  /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_LRCLK_INV_WIDTH                  1  /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_WL_MASK                     0x0060  /* AIF2_WL - [6:5] */
+#define WM8994_AIF2_WL_SHIFT                         5  /* AIF2_WL - [6:5] */
+#define WM8994_AIF2_WL_WIDTH                         2  /* AIF2_WL - [6:5] */
+#define WM8994_AIF2_FMT_MASK                    0x0018  /* AIF2_FMT - [4:3] */
+#define WM8994_AIF2_FMT_SHIFT                        3  /* AIF2_FMT - [4:3] */
+#define WM8994_AIF2_FMT_WIDTH                        2  /* AIF2_FMT - [4:3] */
+
+/*
+ * R785 (0x311) - AIF2 Control (2)
+ */
+#define WM8994_AIF2DACL_SRC                     0x8000  /* AIF2DACL_SRC */
+#define WM8994_AIF2DACL_SRC_MASK                0x8000  /* AIF2DACL_SRC */
+#define WM8994_AIF2DACL_SRC_SHIFT                   15  /* AIF2DACL_SRC */
+#define WM8994_AIF2DACL_SRC_WIDTH                    1  /* AIF2DACL_SRC */
+#define WM8994_AIF2DACR_SRC                     0x4000  /* AIF2DACR_SRC */
+#define WM8994_AIF2DACR_SRC_MASK                0x4000  /* AIF2DACR_SRC */
+#define WM8994_AIF2DACR_SRC_SHIFT                   14  /* AIF2DACR_SRC */
+#define WM8994_AIF2DACR_SRC_WIDTH                    1  /* AIF2DACR_SRC */
+#define WM8994_AIF2DAC_TDM                      0x2000  /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_MASK                 0x2000  /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_SHIFT                    13  /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_WIDTH                     1  /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_CHAN                 0x1000  /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_TDM_CHAN_MASK            0x1000  /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_TDM_CHAN_SHIFT               12  /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_TDM_CHAN_WIDTH                1  /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_BOOST_MASK               0x0C00  /* AIF2DAC_BOOST - [11:10] */
+#define WM8994_AIF2DAC_BOOST_SHIFT                  10  /* AIF2DAC_BOOST - [11:10] */
+#define WM8994_AIF2DAC_BOOST_WIDTH                   2  /* AIF2DAC_BOOST - [11:10] */
+#define WM8994_AIF2_MONO                        0x0100  /* AIF2_MONO */
+#define WM8994_AIF2_MONO_MASK                   0x0100  /* AIF2_MONO */
+#define WM8994_AIF2_MONO_SHIFT                       8  /* AIF2_MONO */
+#define WM8994_AIF2_MONO_WIDTH                       1  /* AIF2_MONO */
+#define WM8994_AIF2DAC_COMP                     0x0010  /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMP_MASK                0x0010  /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMP_SHIFT                    4  /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMP_WIDTH                    1  /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMPMODE                 0x0008  /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2DAC_COMPMODE_MASK            0x0008  /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2DAC_COMPMODE_SHIFT                3  /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2DAC_COMPMODE_WIDTH                1  /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2ADC_COMP                     0x0004  /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMP_MASK                0x0004  /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMP_SHIFT                    2  /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMP_WIDTH                    1  /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMPMODE                 0x0002  /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2ADC_COMPMODE_MASK            0x0002  /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2ADC_COMPMODE_SHIFT                1  /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2ADC_COMPMODE_WIDTH                1  /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2_LOOPBACK                    0x0001  /* AIF2_LOOPBACK */
+#define WM8994_AIF2_LOOPBACK_MASK               0x0001  /* AIF2_LOOPBACK */
+#define WM8994_AIF2_LOOPBACK_SHIFT                   0  /* AIF2_LOOPBACK */
+#define WM8994_AIF2_LOOPBACK_WIDTH                   1  /* AIF2_LOOPBACK */
+
+/*
+ * R786 (0x312) - AIF2 Master/Slave
+ */
+#define WM8994_AIF2_TRI                         0x8000  /* AIF2_TRI */
+#define WM8994_AIF2_TRI_MASK                    0x8000  /* AIF2_TRI */
+#define WM8994_AIF2_TRI_SHIFT                       15  /* AIF2_TRI */
+#define WM8994_AIF2_TRI_WIDTH                        1  /* AIF2_TRI */
+#define WM8994_AIF2_MSTR                        0x4000  /* AIF2_MSTR */
+#define WM8994_AIF2_MSTR_MASK                   0x4000  /* AIF2_MSTR */
+#define WM8994_AIF2_MSTR_SHIFT                      14  /* AIF2_MSTR */
+#define WM8994_AIF2_MSTR_WIDTH                       1  /* AIF2_MSTR */
+#define WM8994_AIF2_CLK_FRC                     0x2000  /* AIF2_CLK_FRC */
+#define WM8994_AIF2_CLK_FRC_MASK                0x2000  /* AIF2_CLK_FRC */
+#define WM8994_AIF2_CLK_FRC_SHIFT                   13  /* AIF2_CLK_FRC */
+#define WM8994_AIF2_CLK_FRC_WIDTH                    1  /* AIF2_CLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC                   0x1000  /* AIF2_LRCLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC_MASK              0x1000  /* AIF2_LRCLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC_SHIFT                 12  /* AIF2_LRCLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC_WIDTH                  1  /* AIF2_LRCLK_FRC */
+
+/*
+ * R787 (0x313) - AIF2 BCLK
+ */
+#define WM8994_AIF2_BCLK_DIV_MASK               0x01F0  /* AIF2_BCLK_DIV - [8:4] */
+#define WM8994_AIF2_BCLK_DIV_SHIFT                   4  /* AIF2_BCLK_DIV - [8:4] */
+#define WM8994_AIF2_BCLK_DIV_WIDTH                   5  /* AIF2_BCLK_DIV - [8:4] */
+
+/*
+ * R788 (0x314) - AIF2ADC LRCLK
+ */
+#define WM8994_AIF2ADC_LRCLK_DIR                0x0800  /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_LRCLK_DIR_MASK           0x0800  /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_LRCLK_DIR_SHIFT              11  /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_LRCLK_DIR_WIDTH               1  /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_RATE_MASK                0x07FF  /* AIF2ADC_RATE - [10:0] */
+#define WM8994_AIF2ADC_RATE_SHIFT                    0  /* AIF2ADC_RATE - [10:0] */
+#define WM8994_AIF2ADC_RATE_WIDTH                   11  /* AIF2ADC_RATE - [10:0] */
+
+/*
+ * R789 (0x315) - AIF2DAC LRCLK
+ */
+#define WM8994_AIF2DAC_LRCLK_DIR                0x0800  /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_LRCLK_DIR_MASK           0x0800  /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_LRCLK_DIR_SHIFT              11  /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_LRCLK_DIR_WIDTH               1  /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_RATE_MASK                0x07FF  /* AIF2DAC_RATE - [10:0] */
+#define WM8994_AIF2DAC_RATE_SHIFT                    0  /* AIF2DAC_RATE - [10:0] */
+#define WM8994_AIF2DAC_RATE_WIDTH                   11  /* AIF2DAC_RATE - [10:0] */
+
+/*
+ * R790 (0x316) - AIF2DAC Data
+ */
+#define WM8994_AIF2DACL_DAT_INV                 0x0002  /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACL_DAT_INV_MASK            0x0002  /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACL_DAT_INV_SHIFT                1  /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACL_DAT_INV_WIDTH                1  /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV                 0x0001  /* AIF2DACR_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV_MASK            0x0001  /* AIF2DACR_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV_SHIFT                0  /* AIF2DACR_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV_WIDTH                1  /* AIF2DACR_DAT_INV */
+
+/*
+ * R791 (0x317) - AIF2ADC Data
+ */
+#define WM8994_AIF2ADCL_DAT_INV                 0x0002  /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCL_DAT_INV_MASK            0x0002  /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCL_DAT_INV_SHIFT                1  /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCL_DAT_INV_WIDTH                1  /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV                 0x0001  /* AIF2ADCR_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV_MASK            0x0001  /* AIF2ADCR_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV_SHIFT                0  /* AIF2ADCR_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV_WIDTH                1  /* AIF2ADCR_DAT_INV */
+
+/*
+ * R1024 (0x400) - AIF1 ADC1 Left Volume
+ */
+#define WM8994_AIF1ADC1_VU                      0x0100  /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_MASK                 0x0100  /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_SHIFT                     8  /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_WIDTH                     1  /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1L_VOL_MASK               0x00FF  /* AIF1ADC1L_VOL - [7:0] */
+#define WM8994_AIF1ADC1L_VOL_SHIFT                   0  /* AIF1ADC1L_VOL - [7:0] */
+#define WM8994_AIF1ADC1L_VOL_WIDTH                   8  /* AIF1ADC1L_VOL - [7:0] */
+
+/*
+ * R1025 (0x401) - AIF1 ADC1 Right Volume
+ */
+#define WM8994_AIF1ADC1_VU                      0x0100  /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_MASK                 0x0100  /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_SHIFT                     8  /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_WIDTH                     1  /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1R_VOL_MASK               0x00FF  /* AIF1ADC1R_VOL - [7:0] */
+#define WM8994_AIF1ADC1R_VOL_SHIFT                   0  /* AIF1ADC1R_VOL - [7:0] */
+#define WM8994_AIF1ADC1R_VOL_WIDTH                   8  /* AIF1ADC1R_VOL - [7:0] */
+
+/*
+ * R1026 (0x402) - AIF1 DAC1 Left Volume
+ */
+#define WM8994_AIF1DAC1_VU                      0x0100  /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_MASK                 0x0100  /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_SHIFT                     8  /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_WIDTH                     1  /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1L_VOL_MASK               0x00FF  /* AIF1DAC1L_VOL - [7:0] */
+#define WM8994_AIF1DAC1L_VOL_SHIFT                   0  /* AIF1DAC1L_VOL - [7:0] */
+#define WM8994_AIF1DAC1L_VOL_WIDTH                   8  /* AIF1DAC1L_VOL - [7:0] */
+
+/*
+ * R1027 (0x403) - AIF1 DAC1 Right Volume
+ */
+#define WM8994_AIF1DAC1_VU                      0x0100  /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_MASK                 0x0100  /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_SHIFT                     8  /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_WIDTH                     1  /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1R_VOL_MASK               0x00FF  /* AIF1DAC1R_VOL - [7:0] */
+#define WM8994_AIF1DAC1R_VOL_SHIFT                   0  /* AIF1DAC1R_VOL - [7:0] */
+#define WM8994_AIF1DAC1R_VOL_WIDTH                   8  /* AIF1DAC1R_VOL - [7:0] */
+
+/*
+ * R1028 (0x404) - AIF1 ADC2 Left Volume
+ */
+#define WM8994_AIF1ADC2_VU                      0x0100  /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_MASK                 0x0100  /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_SHIFT                     8  /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_WIDTH                     1  /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2L_VOL_MASK               0x00FF  /* AIF1ADC2L_VOL - [7:0] */
+#define WM8994_AIF1ADC2L_VOL_SHIFT                   0  /* AIF1ADC2L_VOL - [7:0] */
+#define WM8994_AIF1ADC2L_VOL_WIDTH                   8  /* AIF1ADC2L_VOL - [7:0] */
+
+/*
+ * R1029 (0x405) - AIF1 ADC2 Right Volume
+ */
+#define WM8994_AIF1ADC2_VU                      0x0100  /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_MASK                 0x0100  /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_SHIFT                     8  /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_WIDTH                     1  /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2R_VOL_MASK               0x00FF  /* AIF1ADC2R_VOL - [7:0] */
+#define WM8994_AIF1ADC2R_VOL_SHIFT                   0  /* AIF1ADC2R_VOL - [7:0] */
+#define WM8994_AIF1ADC2R_VOL_WIDTH                   8  /* AIF1ADC2R_VOL - [7:0] */
+
+/*
+ * R1030 (0x406) - AIF1 DAC2 Left Volume
+ */
+#define WM8994_AIF1DAC2_VU                      0x0100  /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_MASK                 0x0100  /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_SHIFT                     8  /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_WIDTH                     1  /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2L_VOL_MASK               0x00FF  /* AIF1DAC2L_VOL - [7:0] */
+#define WM8994_AIF1DAC2L_VOL_SHIFT                   0  /* AIF1DAC2L_VOL - [7:0] */
+#define WM8994_AIF1DAC2L_VOL_WIDTH                   8  /* AIF1DAC2L_VOL - [7:0] */
+
+/*
+ * R1031 (0x407) - AIF1 DAC2 Right Volume
+ */
+#define WM8994_AIF1DAC2_VU                      0x0100  /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_MASK                 0x0100  /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_SHIFT                     8  /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_WIDTH                     1  /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2R_VOL_MASK               0x00FF  /* AIF1DAC2R_VOL - [7:0] */
+#define WM8994_AIF1DAC2R_VOL_SHIFT                   0  /* AIF1DAC2R_VOL - [7:0] */
+#define WM8994_AIF1DAC2R_VOL_WIDTH                   8  /* AIF1DAC2R_VOL - [7:0] */
+
+/*
+ * R1040 (0x410) - AIF1 ADC1 Filters
+ */
+#define WM8994_AIF1ADC_4FS                      0x8000  /* AIF1ADC_4FS */
+#define WM8994_AIF1ADC_4FS_MASK                 0x8000  /* AIF1ADC_4FS */
+#define WM8994_AIF1ADC_4FS_SHIFT                    15  /* AIF1ADC_4FS */
+#define WM8994_AIF1ADC_4FS_WIDTH                     1  /* AIF1ADC_4FS */
+#define WM8994_AIF1ADC1_HPF_CUT_MASK            0x6000  /* AIF1ADC1_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC1_HPF_CUT_SHIFT               13  /* AIF1ADC1_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC1_HPF_CUT_WIDTH                2  /* AIF1ADC1_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC1L_HPF                    0x1000  /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1L_HPF_MASK               0x1000  /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1L_HPF_SHIFT                  12  /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1L_HPF_WIDTH                   1  /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1R_HPF                    0x0800  /* AIF1ADC1R_HPF */
+#define WM8994_AIF1ADC1R_HPF_MASK               0x0800  /* AIF1ADC1R_HPF */
+#define WM8994_AIF1ADC1R_HPF_SHIFT                  11  /* AIF1ADC1R_HPF */
+#define WM8994_AIF1ADC1R_HPF_WIDTH                   1  /* AIF1ADC1R_HPF */
+
+/*
+ * R1041 (0x411) - AIF1 ADC2 Filters
+ */
+#define WM8994_AIF1ADC2_HPF_CUT_MASK            0x6000  /* AIF1ADC2_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC2_HPF_CUT_SHIFT               13  /* AIF1ADC2_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC2_HPF_CUT_WIDTH                2  /* AIF1ADC2_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC2L_HPF                    0x1000  /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2L_HPF_MASK               0x1000  /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2L_HPF_SHIFT                  12  /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2L_HPF_WIDTH                   1  /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2R_HPF                    0x0800  /* AIF1ADC2R_HPF */
+#define WM8994_AIF1ADC2R_HPF_MASK               0x0800  /* AIF1ADC2R_HPF */
+#define WM8994_AIF1ADC2R_HPF_SHIFT                  11  /* AIF1ADC2R_HPF */
+#define WM8994_AIF1ADC2R_HPF_WIDTH                   1  /* AIF1ADC2R_HPF */
+
+/*
+ * R1056 (0x420) - AIF1 DAC1 Filters (1)
+ */
+#define WM8994_AIF1DAC1_MUTE                    0x0200  /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MUTE_MASK               0x0200  /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MUTE_SHIFT                   9  /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MUTE_WIDTH                   1  /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MONO                    0x0080  /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MONO_MASK               0x0080  /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MONO_SHIFT                   7  /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MONO_WIDTH                   1  /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MUTERATE                0x0020  /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_MUTERATE_MASK           0x0020  /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_MUTERATE_SHIFT               5  /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_MUTERATE_WIDTH               1  /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP             0x0010  /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP_MASK        0x0010  /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP_SHIFT            4  /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP_WIDTH            1  /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_DEEMP_MASK              0x0006  /* AIF1DAC1_DEEMP - [2:1] */
+#define WM8994_AIF1DAC1_DEEMP_SHIFT                  1  /* AIF1DAC1_DEEMP - [2:1] */
+#define WM8994_AIF1DAC1_DEEMP_WIDTH                  2  /* AIF1DAC1_DEEMP - [2:1] */
+
+/*
+ * R1057 (0x421) - AIF1 DAC1 Filters (2)
+ */
+#define WM8994_AIF1DAC1_3D_GAIN_MASK            0x3E00  /* AIF1DAC1_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC1_3D_GAIN_SHIFT                9  /* AIF1DAC1_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC1_3D_GAIN_WIDTH                5  /* AIF1DAC1_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC1_3D_ENA                  0x0100  /* AIF1DAC1_3D_ENA */
+#define WM8994_AIF1DAC1_3D_ENA_MASK             0x0100  /* AIF1DAC1_3D_ENA */
+#define WM8994_AIF1DAC1_3D_ENA_SHIFT                 8  /* AIF1DAC1_3D_ENA */
+#define WM8994_AIF1DAC1_3D_ENA_WIDTH                 1  /* AIF1DAC1_3D_ENA */
+
+/*
+ * R1058 (0x422) - AIF1 DAC2 Filters (1)
+ */
+#define WM8994_AIF1DAC2_MUTE                    0x0200  /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MUTE_MASK               0x0200  /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MUTE_SHIFT                   9  /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MUTE_WIDTH                   1  /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MONO                    0x0080  /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MONO_MASK               0x0080  /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MONO_SHIFT                   7  /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MONO_WIDTH                   1  /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MUTERATE                0x0020  /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_MUTERATE_MASK           0x0020  /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_MUTERATE_SHIFT               5  /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_MUTERATE_WIDTH               1  /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP             0x0010  /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP_MASK        0x0010  /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP_SHIFT            4  /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP_WIDTH            1  /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_DEEMP_MASK              0x0006  /* AIF1DAC2_DEEMP - [2:1] */
+#define WM8994_AIF1DAC2_DEEMP_SHIFT                  1  /* AIF1DAC2_DEEMP - [2:1] */
+#define WM8994_AIF1DAC2_DEEMP_WIDTH                  2  /* AIF1DAC2_DEEMP - [2:1] */
+
+/*
+ * R1059 (0x423) - AIF1 DAC2 Filters (2)
+ */
+#define WM8994_AIF1DAC2_3D_GAIN_MASK            0x3E00  /* AIF1DAC2_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC2_3D_GAIN_SHIFT                9  /* AIF1DAC2_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC2_3D_GAIN_WIDTH                5  /* AIF1DAC2_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC2_3D_ENA                  0x0100  /* AIF1DAC2_3D_ENA */
+#define WM8994_AIF1DAC2_3D_ENA_MASK             0x0100  /* AIF1DAC2_3D_ENA */
+#define WM8994_AIF1DAC2_3D_ENA_SHIFT                 8  /* AIF1DAC2_3D_ENA */
+#define WM8994_AIF1DAC2_3D_ENA_WIDTH                 1  /* AIF1DAC2_3D_ENA */
+
+/*
+ * R1088 (0x440) - AIF1 DRC1 (1)
+ */
+#define WM8994_AIF1DRC1_SIG_DET_RMS_MASK        0xF800  /* AIF1DRC1_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC1_SIG_DET_RMS_SHIFT           11  /* AIF1DRC1_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC1_SIG_DET_RMS_WIDTH            5  /* AIF1DRC1_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC1_SIG_DET_PK_MASK         0x0600  /* AIF1DRC1_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC1_SIG_DET_PK_SHIFT             9  /* AIF1DRC1_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC1_SIG_DET_PK_WIDTH             2  /* AIF1DRC1_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC1_NG_ENA                  0x0100  /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_NG_ENA_MASK             0x0100  /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_NG_ENA_SHIFT                 8  /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_NG_ENA_WIDTH                 1  /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_SIG_DET_MODE            0x0080  /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET_MODE_MASK       0x0080  /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET_MODE_SHIFT           7  /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET_MODE_WIDTH           1  /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET                 0x0040  /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_SIG_DET_MASK            0x0040  /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_SIG_DET_SHIFT                6  /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_SIG_DET_WIDTH                1  /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA            0x0020  /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA_MASK       0x0020  /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA_SHIFT           5  /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA_WIDTH           1  /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_QR                      0x0010  /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_QR_MASK                 0x0010  /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_QR_SHIFT                     4  /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_QR_WIDTH                     1  /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_ANTICLIP                0x0008  /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DRC1_ANTICLIP_MASK           0x0008  /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DRC1_ANTICLIP_SHIFT               3  /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DRC1_ANTICLIP_WIDTH               1  /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DAC1_DRC_ENA                 0x0004  /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1DAC1_DRC_ENA_MASK            0x0004  /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1DAC1_DRC_ENA_SHIFT                2  /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1DAC1_DRC_ENA_WIDTH                1  /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA                0x0002  /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA_MASK           0x0002  /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA_SHIFT               1  /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA_WIDTH               1  /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA                0x0001  /* AIF1ADC1R_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA_MASK           0x0001  /* AIF1ADC1R_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA_SHIFT               0  /* AIF1ADC1R_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA_WIDTH               1  /* AIF1ADC1R_DRC_ENA */
+
+/*
+ * R1089 (0x441) - AIF1 DRC1 (2)
+ */
+#define WM8994_AIF1DRC1_ATK_MASK                0x1E00  /* AIF1DRC1_ATK - [12:9] */
+#define WM8994_AIF1DRC1_ATK_SHIFT                    9  /* AIF1DRC1_ATK - [12:9] */
+#define WM8994_AIF1DRC1_ATK_WIDTH                    4  /* AIF1DRC1_ATK - [12:9] */
+#define WM8994_AIF1DRC1_DCY_MASK                0x01E0  /* AIF1DRC1_DCY - [8:5] */
+#define WM8994_AIF1DRC1_DCY_SHIFT                    5  /* AIF1DRC1_DCY - [8:5] */
+#define WM8994_AIF1DRC1_DCY_WIDTH                    4  /* AIF1DRC1_DCY - [8:5] */
+#define WM8994_AIF1DRC1_MINGAIN_MASK            0x001C  /* AIF1DRC1_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC1_MINGAIN_SHIFT                2  /* AIF1DRC1_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC1_MINGAIN_WIDTH                3  /* AIF1DRC1_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC1_MAXGAIN_MASK            0x0003  /* AIF1DRC1_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC1_MAXGAIN_SHIFT                0  /* AIF1DRC1_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC1_MAXGAIN_WIDTH                2  /* AIF1DRC1_MAXGAIN - [1:0] */
+
+/*
+ * R1090 (0x442) - AIF1 DRC1 (3)
+ */
+#define WM8994_AIF1DRC1_NG_MINGAIN_MASK         0xF000  /* AIF1DRC1_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC1_NG_MINGAIN_SHIFT            12  /* AIF1DRC1_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC1_NG_MINGAIN_WIDTH             4  /* AIF1DRC1_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC1_NG_EXP_MASK             0x0C00  /* AIF1DRC1_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC1_NG_EXP_SHIFT                10  /* AIF1DRC1_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC1_NG_EXP_WIDTH                 2  /* AIF1DRC1_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC1_QR_THR_MASK             0x0300  /* AIF1DRC1_QR_THR - [9:8] */
+#define WM8994_AIF1DRC1_QR_THR_SHIFT                 8  /* AIF1DRC1_QR_THR - [9:8] */
+#define WM8994_AIF1DRC1_QR_THR_WIDTH                 2  /* AIF1DRC1_QR_THR - [9:8] */
+#define WM8994_AIF1DRC1_QR_DCY_MASK             0x00C0  /* AIF1DRC1_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC1_QR_DCY_SHIFT                 6  /* AIF1DRC1_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC1_QR_DCY_WIDTH                 2  /* AIF1DRC1_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC1_HI_COMP_MASK            0x0038  /* AIF1DRC1_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC1_HI_COMP_SHIFT                3  /* AIF1DRC1_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC1_HI_COMP_WIDTH                3  /* AIF1DRC1_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC1_LO_COMP_MASK            0x0007  /* AIF1DRC1_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC1_LO_COMP_SHIFT                0  /* AIF1DRC1_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC1_LO_COMP_WIDTH                3  /* AIF1DRC1_LO_COMP - [2:0] */
+
+/*
+ * R1091 (0x443) - AIF1 DRC1 (4)
+ */
+#define WM8994_AIF1DRC1_KNEE_IP_MASK            0x07E0  /* AIF1DRC1_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC1_KNEE_IP_SHIFT                5  /* AIF1DRC1_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC1_KNEE_IP_WIDTH                6  /* AIF1DRC1_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC1_KNEE_OP_MASK            0x001F  /* AIF1DRC1_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE_OP_SHIFT                0  /* AIF1DRC1_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE_OP_WIDTH                5  /* AIF1DRC1_KNEE_OP - [4:0] */
+
+/*
+ * R1092 (0x444) - AIF1 DRC1 (5)
+ */
+#define WM8994_AIF1DRC1_KNEE2_IP_MASK           0x03E0  /* AIF1DRC1_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC1_KNEE2_IP_SHIFT               5  /* AIF1DRC1_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC1_KNEE2_IP_WIDTH               5  /* AIF1DRC1_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC1_KNEE2_OP_MASK           0x001F  /* AIF1DRC1_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE2_OP_SHIFT               0  /* AIF1DRC1_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE2_OP_WIDTH               5  /* AIF1DRC1_KNEE2_OP - [4:0] */
+
+/*
+ * R1104 (0x450) - AIF1 DRC2 (1)
+ */
+#define WM8994_AIF1DRC2_SIG_DET_RMS_MASK        0xF800  /* AIF1DRC2_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC2_SIG_DET_RMS_SHIFT           11  /* AIF1DRC2_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC2_SIG_DET_RMS_WIDTH            5  /* AIF1DRC2_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC2_SIG_DET_PK_MASK         0x0600  /* AIF1DRC2_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC2_SIG_DET_PK_SHIFT             9  /* AIF1DRC2_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC2_SIG_DET_PK_WIDTH             2  /* AIF1DRC2_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC2_NG_ENA                  0x0100  /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_NG_ENA_MASK             0x0100  /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_NG_ENA_SHIFT                 8  /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_NG_ENA_WIDTH                 1  /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_SIG_DET_MODE            0x0080  /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET_MODE_MASK       0x0080  /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET_MODE_SHIFT           7  /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET_MODE_WIDTH           1  /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET                 0x0040  /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_SIG_DET_MASK            0x0040  /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_SIG_DET_SHIFT                6  /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_SIG_DET_WIDTH                1  /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA            0x0020  /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA_MASK       0x0020  /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA_SHIFT           5  /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA_WIDTH           1  /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_QR                      0x0010  /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_QR_MASK                 0x0010  /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_QR_SHIFT                     4  /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_QR_WIDTH                     1  /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_ANTICLIP                0x0008  /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DRC2_ANTICLIP_MASK           0x0008  /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DRC2_ANTICLIP_SHIFT               3  /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DRC2_ANTICLIP_WIDTH               1  /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DAC2_DRC_ENA                 0x0004  /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1DAC2_DRC_ENA_MASK            0x0004  /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1DAC2_DRC_ENA_SHIFT                2  /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1DAC2_DRC_ENA_WIDTH                1  /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA                0x0002  /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA_MASK           0x0002  /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA_SHIFT               1  /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA_WIDTH               1  /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA                0x0001  /* AIF1ADC2R_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA_MASK           0x0001  /* AIF1ADC2R_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA_SHIFT               0  /* AIF1ADC2R_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA_WIDTH               1  /* AIF1ADC2R_DRC_ENA */
+
+/*
+ * R1105 (0x451) - AIF1 DRC2 (2)
+ */
+#define WM8994_AIF1DRC2_ATK_MASK                0x1E00  /* AIF1DRC2_ATK - [12:9] */
+#define WM8994_AIF1DRC2_ATK_SHIFT                    9  /* AIF1DRC2_ATK - [12:9] */
+#define WM8994_AIF1DRC2_ATK_WIDTH                    4  /* AIF1DRC2_ATK - [12:9] */
+#define WM8994_AIF1DRC2_DCY_MASK                0x01E0  /* AIF1DRC2_DCY - [8:5] */
+#define WM8994_AIF1DRC2_DCY_SHIFT                    5  /* AIF1DRC2_DCY - [8:5] */
+#define WM8994_AIF1DRC2_DCY_WIDTH                    4  /* AIF1DRC2_DCY - [8:5] */
+#define WM8994_AIF1DRC2_MINGAIN_MASK            0x001C  /* AIF1DRC2_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC2_MINGAIN_SHIFT                2  /* AIF1DRC2_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC2_MINGAIN_WIDTH                3  /* AIF1DRC2_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC2_MAXGAIN_MASK            0x0003  /* AIF1DRC2_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC2_MAXGAIN_SHIFT                0  /* AIF1DRC2_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC2_MAXGAIN_WIDTH                2  /* AIF1DRC2_MAXGAIN - [1:0] */
+
+/*
+ * R1106 (0x452) - AIF1 DRC2 (3)
+ */
+#define WM8994_AIF1DRC2_NG_MINGAIN_MASK         0xF000  /* AIF1DRC2_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC2_NG_MINGAIN_SHIFT            12  /* AIF1DRC2_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC2_NG_MINGAIN_WIDTH             4  /* AIF1DRC2_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC2_NG_EXP_MASK             0x0C00  /* AIF1DRC2_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC2_NG_EXP_SHIFT                10  /* AIF1DRC2_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC2_NG_EXP_WIDTH                 2  /* AIF1DRC2_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC2_QR_THR_MASK             0x0300  /* AIF1DRC2_QR_THR - [9:8] */
+#define WM8994_AIF1DRC2_QR_THR_SHIFT                 8  /* AIF1DRC2_QR_THR - [9:8] */
+#define WM8994_AIF1DRC2_QR_THR_WIDTH                 2  /* AIF1DRC2_QR_THR - [9:8] */
+#define WM8994_AIF1DRC2_QR_DCY_MASK             0x00C0  /* AIF1DRC2_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC2_QR_DCY_SHIFT                 6  /* AIF1DRC2_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC2_QR_DCY_WIDTH                 2  /* AIF1DRC2_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC2_HI_COMP_MASK            0x0038  /* AIF1DRC2_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC2_HI_COMP_SHIFT                3  /* AIF1DRC2_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC2_HI_COMP_WIDTH                3  /* AIF1DRC2_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC2_LO_COMP_MASK            0x0007  /* AIF1DRC2_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC2_LO_COMP_SHIFT                0  /* AIF1DRC2_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC2_LO_COMP_WIDTH                3  /* AIF1DRC2_LO_COMP - [2:0] */
+
+/*
+ * R1107 (0x453) - AIF1 DRC2 (4)
+ */
+#define WM8994_AIF1DRC2_KNEE_IP_MASK            0x07E0  /* AIF1DRC2_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC2_KNEE_IP_SHIFT                5  /* AIF1DRC2_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC2_KNEE_IP_WIDTH                6  /* AIF1DRC2_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC2_KNEE_OP_MASK            0x001F  /* AIF1DRC2_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE_OP_SHIFT                0  /* AIF1DRC2_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE_OP_WIDTH                5  /* AIF1DRC2_KNEE_OP - [4:0] */
+
+/*
+ * R1108 (0x454) - AIF1 DRC2 (5)
+ */
+#define WM8994_AIF1DRC2_KNEE2_IP_MASK           0x03E0  /* AIF1DRC2_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC2_KNEE2_IP_SHIFT               5  /* AIF1DRC2_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC2_KNEE2_IP_WIDTH               5  /* AIF1DRC2_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC2_KNEE2_OP_MASK           0x001F  /* AIF1DRC2_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE2_OP_SHIFT               0  /* AIF1DRC2_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE2_OP_WIDTH               5  /* AIF1DRC2_KNEE2_OP - [4:0] */
+
+/*
+ * R1152 (0x480) - AIF1 DAC1 EQ Gains (1)
+ */
+#define WM8994_AIF1DAC1_EQ_B1_GAIN_MASK         0xF800  /* AIF1DAC1_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B1_GAIN_SHIFT            11  /* AIF1DAC1_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B1_GAIN_WIDTH             5  /* AIF1DAC1_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B2_GAIN_MASK         0x07C0  /* AIF1DAC1_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B2_GAIN_SHIFT             6  /* AIF1DAC1_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B2_GAIN_WIDTH             5  /* AIF1DAC1_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B3_GAIN_MASK         0x003E  /* AIF1DAC1_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC1_EQ_B3_GAIN_SHIFT             1  /* AIF1DAC1_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC1_EQ_B3_GAIN_WIDTH             5  /* AIF1DAC1_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC1_EQ_ENA                  0x0001  /* AIF1DAC1_EQ_ENA */
+#define WM8994_AIF1DAC1_EQ_ENA_MASK             0x0001  /* AIF1DAC1_EQ_ENA */
+#define WM8994_AIF1DAC1_EQ_ENA_SHIFT                 0  /* AIF1DAC1_EQ_ENA */
+#define WM8994_AIF1DAC1_EQ_ENA_WIDTH                 1  /* AIF1DAC1_EQ_ENA */
+
+/*
+ * R1153 (0x481) - AIF1 DAC1 EQ Gains (2)
+ */
+#define WM8994_AIF1DAC1_EQ_B4_GAIN_MASK         0xF800  /* AIF1DAC1_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B4_GAIN_SHIFT            11  /* AIF1DAC1_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B4_GAIN_WIDTH             5  /* AIF1DAC1_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B5_GAIN_MASK         0x07C0  /* AIF1DAC1_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B5_GAIN_SHIFT             6  /* AIF1DAC1_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B5_GAIN_WIDTH             5  /* AIF1DAC1_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1154 (0x482) - AIF1 DAC1 EQ Band 1 A
+ */
+#define WM8994_AIF1DAC1_EQ_B1_A_MASK            0xFFFF  /* AIF1DAC1_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_A_SHIFT                0  /* AIF1DAC1_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_A_WIDTH               16  /* AIF1DAC1_EQ_B1_A - [15:0] */
+
+/*
+ * R1155 (0x483) - AIF1 DAC1 EQ Band 1 B
+ */
+#define WM8994_AIF1DAC1_EQ_B1_B_MASK            0xFFFF  /* AIF1DAC1_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_B_SHIFT                0  /* AIF1DAC1_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_B_WIDTH               16  /* AIF1DAC1_EQ_B1_B - [15:0] */
+
+/*
+ * R1156 (0x484) - AIF1 DAC1 EQ Band 1 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B1_PG_MASK           0xFFFF  /* AIF1DAC1_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_PG_SHIFT               0  /* AIF1DAC1_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_PG_WIDTH              16  /* AIF1DAC1_EQ_B1_PG - [15:0] */
+
+/*
+ * R1157 (0x485) - AIF1 DAC1 EQ Band 2 A
+ */
+#define WM8994_AIF1DAC1_EQ_B2_A_MASK            0xFFFF  /* AIF1DAC1_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_A_SHIFT                0  /* AIF1DAC1_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_A_WIDTH               16  /* AIF1DAC1_EQ_B2_A - [15:0] */
+
+/*
+ * R1158 (0x486) - AIF1 DAC1 EQ Band 2 B
+ */
+#define WM8994_AIF1DAC1_EQ_B2_B_MASK            0xFFFF  /* AIF1DAC1_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_B_SHIFT                0  /* AIF1DAC1_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_B_WIDTH               16  /* AIF1DAC1_EQ_B2_B - [15:0] */
+
+/*
+ * R1159 (0x487) - AIF1 DAC1 EQ Band 2 C
+ */
+#define WM8994_AIF1DAC1_EQ_B2_C_MASK            0xFFFF  /* AIF1DAC1_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_C_SHIFT                0  /* AIF1DAC1_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_C_WIDTH               16  /* AIF1DAC1_EQ_B2_C - [15:0] */
+
+/*
+ * R1160 (0x488) - AIF1 DAC1 EQ Band 2 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B2_PG_MASK           0xFFFF  /* AIF1DAC1_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_PG_SHIFT               0  /* AIF1DAC1_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_PG_WIDTH              16  /* AIF1DAC1_EQ_B2_PG - [15:0] */
+
+/*
+ * R1161 (0x489) - AIF1 DAC1 EQ Band 3 A
+ */
+#define WM8994_AIF1DAC1_EQ_B3_A_MASK            0xFFFF  /* AIF1DAC1_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_A_SHIFT                0  /* AIF1DAC1_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_A_WIDTH               16  /* AIF1DAC1_EQ_B3_A - [15:0] */
+
+/*
+ * R1162 (0x48A) - AIF1 DAC1 EQ Band 3 B
+ */
+#define WM8994_AIF1DAC1_EQ_B3_B_MASK            0xFFFF  /* AIF1DAC1_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_B_SHIFT                0  /* AIF1DAC1_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_B_WIDTH               16  /* AIF1DAC1_EQ_B3_B - [15:0] */
+
+/*
+ * R1163 (0x48B) - AIF1 DAC1 EQ Band 3 C
+ */
+#define WM8994_AIF1DAC1_EQ_B3_C_MASK            0xFFFF  /* AIF1DAC1_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_C_SHIFT                0  /* AIF1DAC1_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_C_WIDTH               16  /* AIF1DAC1_EQ_B3_C - [15:0] */
+
+/*
+ * R1164 (0x48C) - AIF1 DAC1 EQ Band 3 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B3_PG_MASK           0xFFFF  /* AIF1DAC1_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_PG_SHIFT               0  /* AIF1DAC1_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_PG_WIDTH              16  /* AIF1DAC1_EQ_B3_PG - [15:0] */
+
+/*
+ * R1165 (0x48D) - AIF1 DAC1 EQ Band 4 A
+ */
+#define WM8994_AIF1DAC1_EQ_B4_A_MASK            0xFFFF  /* AIF1DAC1_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_A_SHIFT                0  /* AIF1DAC1_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_A_WIDTH               16  /* AIF1DAC1_EQ_B4_A - [15:0] */
+
+/*
+ * R1166 (0x48E) - AIF1 DAC1 EQ Band 4 B
+ */
+#define WM8994_AIF1DAC1_EQ_B4_B_MASK            0xFFFF  /* AIF1DAC1_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_B_SHIFT                0  /* AIF1DAC1_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_B_WIDTH               16  /* AIF1DAC1_EQ_B4_B - [15:0] */
+
+/*
+ * R1167 (0x48F) - AIF1 DAC1 EQ Band 4 C
+ */
+#define WM8994_AIF1DAC1_EQ_B4_C_MASK            0xFFFF  /* AIF1DAC1_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_C_SHIFT                0  /* AIF1DAC1_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_C_WIDTH               16  /* AIF1DAC1_EQ_B4_C - [15:0] */
+
+/*
+ * R1168 (0x490) - AIF1 DAC1 EQ Band 4 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B4_PG_MASK           0xFFFF  /* AIF1DAC1_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_PG_SHIFT               0  /* AIF1DAC1_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_PG_WIDTH              16  /* AIF1DAC1_EQ_B4_PG - [15:0] */
+
+/*
+ * R1169 (0x491) - AIF1 DAC1 EQ Band 5 A
+ */
+#define WM8994_AIF1DAC1_EQ_B5_A_MASK            0xFFFF  /* AIF1DAC1_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_A_SHIFT                0  /* AIF1DAC1_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_A_WIDTH               16  /* AIF1DAC1_EQ_B5_A - [15:0] */
+
+/*
+ * R1170 (0x492) - AIF1 DAC1 EQ Band 5 B
+ */
+#define WM8994_AIF1DAC1_EQ_B5_B_MASK            0xFFFF  /* AIF1DAC1_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_B_SHIFT                0  /* AIF1DAC1_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_B_WIDTH               16  /* AIF1DAC1_EQ_B5_B - [15:0] */
+
+/*
+ * R1171 (0x493) - AIF1 DAC1 EQ Band 5 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B5_PG_MASK           0xFFFF  /* AIF1DAC1_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_PG_SHIFT               0  /* AIF1DAC1_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_PG_WIDTH              16  /* AIF1DAC1_EQ_B5_PG - [15:0] */
+
+/*
+ * R1184 (0x4A0) - AIF1 DAC2 EQ Gains (1)
+ */
+#define WM8994_AIF1DAC2_EQ_B1_GAIN_MASK         0xF800  /* AIF1DAC2_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B1_GAIN_SHIFT            11  /* AIF1DAC2_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B1_GAIN_WIDTH             5  /* AIF1DAC2_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B2_GAIN_MASK         0x07C0  /* AIF1DAC2_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B2_GAIN_SHIFT             6  /* AIF1DAC2_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B2_GAIN_WIDTH             5  /* AIF1DAC2_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B3_GAIN_MASK         0x003E  /* AIF1DAC2_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC2_EQ_B3_GAIN_SHIFT             1  /* AIF1DAC2_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC2_EQ_B3_GAIN_WIDTH             5  /* AIF1DAC2_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC2_EQ_ENA                  0x0001  /* AIF1DAC2_EQ_ENA */
+#define WM8994_AIF1DAC2_EQ_ENA_MASK             0x0001  /* AIF1DAC2_EQ_ENA */
+#define WM8994_AIF1DAC2_EQ_ENA_SHIFT                 0  /* AIF1DAC2_EQ_ENA */
+#define WM8994_AIF1DAC2_EQ_ENA_WIDTH                 1  /* AIF1DAC2_EQ_ENA */
+
+/*
+ * R1185 (0x4A1) - AIF1 DAC2 EQ Gains (2)
+ */
+#define WM8994_AIF1DAC2_EQ_B4_GAIN_MASK         0xF800  /* AIF1DAC2_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B4_GAIN_SHIFT            11  /* AIF1DAC2_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B4_GAIN_WIDTH             5  /* AIF1DAC2_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B5_GAIN_MASK         0x07C0  /* AIF1DAC2_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B5_GAIN_SHIFT             6  /* AIF1DAC2_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B5_GAIN_WIDTH             5  /* AIF1DAC2_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1186 (0x4A2) - AIF1 DAC2 EQ Band 1 A
+ */
+#define WM8994_AIF1DAC2_EQ_B1_A_MASK            0xFFFF  /* AIF1DAC2_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_A_SHIFT                0  /* AIF1DAC2_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_A_WIDTH               16  /* AIF1DAC2_EQ_B1_A - [15:0] */
+
+/*
+ * R1187 (0x4A3) - AIF1 DAC2 EQ Band 1 B
+ */
+#define WM8994_AIF1DAC2_EQ_B1_B_MASK            0xFFFF  /* AIF1DAC2_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_B_SHIFT                0  /* AIF1DAC2_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_B_WIDTH               16  /* AIF1DAC2_EQ_B1_B - [15:0] */
+
+/*
+ * R1188 (0x4A4) - AIF1 DAC2 EQ Band 1 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B1_PG_MASK           0xFFFF  /* AIF1DAC2_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_PG_SHIFT               0  /* AIF1DAC2_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_PG_WIDTH              16  /* AIF1DAC2_EQ_B1_PG - [15:0] */
+
+/*
+ * R1189 (0x4A5) - AIF1 DAC2 EQ Band 2 A
+ */
+#define WM8994_AIF1DAC2_EQ_B2_A_MASK            0xFFFF  /* AIF1DAC2_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_A_SHIFT                0  /* AIF1DAC2_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_A_WIDTH               16  /* AIF1DAC2_EQ_B2_A - [15:0] */
+
+/*
+ * R1190 (0x4A6) - AIF1 DAC2 EQ Band 2 B
+ */
+#define WM8994_AIF1DAC2_EQ_B2_B_MASK            0xFFFF  /* AIF1DAC2_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_B_SHIFT                0  /* AIF1DAC2_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_B_WIDTH               16  /* AIF1DAC2_EQ_B2_B - [15:0] */
+
+/*
+ * R1191 (0x4A7) - AIF1 DAC2 EQ Band 2 C
+ */
+#define WM8994_AIF1DAC2_EQ_B2_C_MASK            0xFFFF  /* AIF1DAC2_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_C_SHIFT                0  /* AIF1DAC2_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_C_WIDTH               16  /* AIF1DAC2_EQ_B2_C - [15:0] */
+
+/*
+ * R1192 (0x4A8) - AIF1 DAC2 EQ Band 2 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B2_PG_MASK           0xFFFF  /* AIF1DAC2_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_PG_SHIFT               0  /* AIF1DAC2_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_PG_WIDTH              16  /* AIF1DAC2_EQ_B2_PG - [15:0] */
+
+/*
+ * R1193 (0x4A9) - AIF1 DAC2 EQ Band 3 A
+ */
+#define WM8994_AIF1DAC2_EQ_B3_A_MASK            0xFFFF  /* AIF1DAC2_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_A_SHIFT                0  /* AIF1DAC2_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_A_WIDTH               16  /* AIF1DAC2_EQ_B3_A - [15:0] */
+
+/*
+ * R1194 (0x4AA) - AIF1 DAC2 EQ Band 3 B
+ */
+#define WM8994_AIF1DAC2_EQ_B3_B_MASK            0xFFFF  /* AIF1DAC2_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_B_SHIFT                0  /* AIF1DAC2_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_B_WIDTH               16  /* AIF1DAC2_EQ_B3_B - [15:0] */
+
+/*
+ * R1195 (0x4AB) - AIF1 DAC2 EQ Band 3 C
+ */
+#define WM8994_AIF1DAC2_EQ_B3_C_MASK            0xFFFF  /* AIF1DAC2_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_C_SHIFT                0  /* AIF1DAC2_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_C_WIDTH               16  /* AIF1DAC2_EQ_B3_C - [15:0] */
+
+/*
+ * R1196 (0x4AC) - AIF1 DAC2 EQ Band 3 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B3_PG_MASK           0xFFFF  /* AIF1DAC2_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_PG_SHIFT               0  /* AIF1DAC2_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_PG_WIDTH              16  /* AIF1DAC2_EQ_B3_PG - [15:0] */
+
+/*
+ * R1197 (0x4AD) - AIF1 DAC2 EQ Band 4 A
+ */
+#define WM8994_AIF1DAC2_EQ_B4_A_MASK            0xFFFF  /* AIF1DAC2_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_A_SHIFT                0  /* AIF1DAC2_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_A_WIDTH               16  /* AIF1DAC2_EQ_B4_A - [15:0] */
+
+/*
+ * R1198 (0x4AE) - AIF1 DAC2 EQ Band 4 B
+ */
+#define WM8994_AIF1DAC2_EQ_B4_B_MASK            0xFFFF  /* AIF1DAC2_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_B_SHIFT                0  /* AIF1DAC2_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_B_WIDTH               16  /* AIF1DAC2_EQ_B4_B - [15:0] */
+
+/*
+ * R1199 (0x4AF) - AIF1 DAC2 EQ Band 4 C
+ */
+#define WM8994_AIF1DAC2_EQ_B4_C_MASK            0xFFFF  /* AIF1DAC2_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_C_SHIFT                0  /* AIF1DAC2_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_C_WIDTH               16  /* AIF1DAC2_EQ_B4_C - [15:0] */
+
+/*
+ * R1200 (0x4B0) - AIF1 DAC2 EQ Band 4 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B4_PG_MASK           0xFFFF  /* AIF1DAC2_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_PG_SHIFT               0  /* AIF1DAC2_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_PG_WIDTH              16  /* AIF1DAC2_EQ_B4_PG - [15:0] */
+
+/*
+ * R1201 (0x4B1) - AIF1 DAC2 EQ Band 5 A
+ */
+#define WM8994_AIF1DAC2_EQ_B5_A_MASK            0xFFFF  /* AIF1DAC2_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_A_SHIFT                0  /* AIF1DAC2_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_A_WIDTH               16  /* AIF1DAC2_EQ_B5_A - [15:0] */
+
+/*
+ * R1202 (0x4B2) - AIF1 DAC2 EQ Band 5 B
+ */
+#define WM8994_AIF1DAC2_EQ_B5_B_MASK            0xFFFF  /* AIF1DAC2_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_B_SHIFT                0  /* AIF1DAC2_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_B_WIDTH               16  /* AIF1DAC2_EQ_B5_B - [15:0] */
+
+/*
+ * R1203 (0x4B3) - AIF1 DAC2 EQ Band 5 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B5_PG_MASK           0xFFFF  /* AIF1DAC2_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_PG_SHIFT               0  /* AIF1DAC2_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_PG_WIDTH              16  /* AIF1DAC2_EQ_B5_PG - [15:0] */
+
+/*
+ * R1280 (0x500) - AIF2 ADC Left Volume
+ */
+#define WM8994_AIF2ADC_VU                       0x0100  /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_MASK                  0x0100  /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_SHIFT                      8  /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_WIDTH                      1  /* AIF2ADC_VU */
+#define WM8994_AIF2ADCL_VOL_MASK                0x00FF  /* AIF2ADCL_VOL - [7:0] */
+#define WM8994_AIF2ADCL_VOL_SHIFT                    0  /* AIF2ADCL_VOL - [7:0] */
+#define WM8994_AIF2ADCL_VOL_WIDTH                    8  /* AIF2ADCL_VOL - [7:0] */
+
+/*
+ * R1281 (0x501) - AIF2 ADC Right Volume
+ */
+#define WM8994_AIF2ADC_VU                       0x0100  /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_MASK                  0x0100  /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_SHIFT                      8  /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_WIDTH                      1  /* AIF2ADC_VU */
+#define WM8994_AIF2ADCR_VOL_MASK                0x00FF  /* AIF2ADCR_VOL - [7:0] */
+#define WM8994_AIF2ADCR_VOL_SHIFT                    0  /* AIF2ADCR_VOL - [7:0] */
+#define WM8994_AIF2ADCR_VOL_WIDTH                    8  /* AIF2ADCR_VOL - [7:0] */
+
+/*
+ * R1282 (0x502) - AIF2 DAC Left Volume
+ */
+#define WM8994_AIF2DAC_VU                       0x0100  /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_MASK                  0x0100  /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_SHIFT                      8  /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_WIDTH                      1  /* AIF2DAC_VU */
+#define WM8994_AIF2DACL_VOL_MASK                0x00FF  /* AIF2DACL_VOL - [7:0] */
+#define WM8994_AIF2DACL_VOL_SHIFT                    0  /* AIF2DACL_VOL - [7:0] */
+#define WM8994_AIF2DACL_VOL_WIDTH                    8  /* AIF2DACL_VOL - [7:0] */
+
+/*
+ * R1283 (0x503) - AIF2 DAC Right Volume
+ */
+#define WM8994_AIF2DAC_VU                       0x0100  /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_MASK                  0x0100  /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_SHIFT                      8  /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_WIDTH                      1  /* AIF2DAC_VU */
+#define WM8994_AIF2DACR_VOL_MASK                0x00FF  /* AIF2DACR_VOL - [7:0] */
+#define WM8994_AIF2DACR_VOL_SHIFT                    0  /* AIF2DACR_VOL - [7:0] */
+#define WM8994_AIF2DACR_VOL_WIDTH                    8  /* AIF2DACR_VOL - [7:0] */
+
+/*
+ * R1296 (0x510) - AIF2 ADC Filters
+ */
+#define WM8994_AIF2ADC_4FS                      0x8000  /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_4FS_MASK                 0x8000  /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_4FS_SHIFT                    15  /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_4FS_WIDTH                     1  /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_HPF_CUT_MASK             0x6000  /* AIF2ADC_HPF_CUT - [14:13] */
+#define WM8994_AIF2ADC_HPF_CUT_SHIFT                13  /* AIF2ADC_HPF_CUT - [14:13] */
+#define WM8994_AIF2ADC_HPF_CUT_WIDTH                 2  /* AIF2ADC_HPF_CUT - [14:13] */
+#define WM8994_AIF2ADCL_HPF                     0x1000  /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCL_HPF_MASK                0x1000  /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCL_HPF_SHIFT                   12  /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCL_HPF_WIDTH                    1  /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCR_HPF                     0x0800  /* AIF2ADCR_HPF */
+#define WM8994_AIF2ADCR_HPF_MASK                0x0800  /* AIF2ADCR_HPF */
+#define WM8994_AIF2ADCR_HPF_SHIFT                   11  /* AIF2ADCR_HPF */
+#define WM8994_AIF2ADCR_HPF_WIDTH                    1  /* AIF2ADCR_HPF */
+
+/*
+ * R1312 (0x520) - AIF2 DAC Filters (1)
+ */
+#define WM8994_AIF2DAC_MUTE                     0x0200  /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MUTE_MASK                0x0200  /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MUTE_SHIFT                    9  /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MUTE_WIDTH                    1  /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MONO                     0x0080  /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MONO_MASK                0x0080  /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MONO_SHIFT                    7  /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MONO_WIDTH                    1  /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MUTERATE                 0x0020  /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_MUTERATE_MASK            0x0020  /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_MUTERATE_SHIFT                5  /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_MUTERATE_WIDTH                1  /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_UNMUTE_RAMP              0x0010  /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_UNMUTE_RAMP_MASK         0x0010  /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_UNMUTE_RAMP_SHIFT             4  /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_UNMUTE_RAMP_WIDTH             1  /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_DEEMP_MASK               0x0006  /* AIF2DAC_DEEMP - [2:1] */
+#define WM8994_AIF2DAC_DEEMP_SHIFT                   1  /* AIF2DAC_DEEMP - [2:1] */
+#define WM8994_AIF2DAC_DEEMP_WIDTH                   2  /* AIF2DAC_DEEMP - [2:1] */
+
+/*
+ * R1313 (0x521) - AIF2 DAC Filters (2)
+ */
+#define WM8994_AIF2DAC_3D_GAIN_MASK             0x3E00  /* AIF2DAC_3D_GAIN - [13:9] */
+#define WM8994_AIF2DAC_3D_GAIN_SHIFT                 9  /* AIF2DAC_3D_GAIN - [13:9] */
+#define WM8994_AIF2DAC_3D_GAIN_WIDTH                 5  /* AIF2DAC_3D_GAIN - [13:9] */
+#define WM8994_AIF2DAC_3D_ENA                   0x0100  /* AIF2DAC_3D_ENA */
+#define WM8994_AIF2DAC_3D_ENA_MASK              0x0100  /* AIF2DAC_3D_ENA */
+#define WM8994_AIF2DAC_3D_ENA_SHIFT                  8  /* AIF2DAC_3D_ENA */
+#define WM8994_AIF2DAC_3D_ENA_WIDTH                  1  /* AIF2DAC_3D_ENA */
+
+/*
+ * R1344 (0x540) - AIF2 DRC (1)
+ */
+#define WM8994_AIF2DRC_SIG_DET_RMS_MASK         0xF800  /* AIF2DRC_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF2DRC_SIG_DET_RMS_SHIFT            11  /* AIF2DRC_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF2DRC_SIG_DET_RMS_WIDTH             5  /* AIF2DRC_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF2DRC_SIG_DET_PK_MASK          0x0600  /* AIF2DRC_SIG_DET_PK - [10:9] */
+#define WM8994_AIF2DRC_SIG_DET_PK_SHIFT              9  /* AIF2DRC_SIG_DET_PK - [10:9] */
+#define WM8994_AIF2DRC_SIG_DET_PK_WIDTH              2  /* AIF2DRC_SIG_DET_PK - [10:9] */
+#define WM8994_AIF2DRC_NG_ENA                   0x0100  /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_NG_ENA_MASK              0x0100  /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_NG_ENA_SHIFT                  8  /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_NG_ENA_WIDTH                  1  /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_SIG_DET_MODE             0x0080  /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET_MODE_MASK        0x0080  /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET_MODE_SHIFT            7  /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET_MODE_WIDTH            1  /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET                  0x0040  /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_SIG_DET_MASK             0x0040  /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_SIG_DET_SHIFT                 6  /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_SIG_DET_WIDTH                 1  /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA             0x0020  /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA_MASK        0x0020  /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA_SHIFT            5  /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA_WIDTH            1  /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_QR                       0x0010  /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_QR_MASK                  0x0010  /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_QR_SHIFT                      4  /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_QR_WIDTH                      1  /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_ANTICLIP                 0x0008  /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DRC_ANTICLIP_MASK            0x0008  /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DRC_ANTICLIP_SHIFT                3  /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DRC_ANTICLIP_WIDTH                1  /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DAC_DRC_ENA                  0x0004  /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2DAC_DRC_ENA_MASK             0x0004  /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2DAC_DRC_ENA_SHIFT                 2  /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2DAC_DRC_ENA_WIDTH                 1  /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA                 0x0002  /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA_MASK            0x0002  /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA_SHIFT                1  /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA_WIDTH                1  /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA                 0x0001  /* AIF2ADCR_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA_MASK            0x0001  /* AIF2ADCR_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA_SHIFT                0  /* AIF2ADCR_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA_WIDTH                1  /* AIF2ADCR_DRC_ENA */
+
+/*
+ * R1345 (0x541) - AIF2 DRC (2)
+ */
+#define WM8994_AIF2DRC_ATK_MASK                 0x1E00  /* AIF2DRC_ATK - [12:9] */
+#define WM8994_AIF2DRC_ATK_SHIFT                     9  /* AIF2DRC_ATK - [12:9] */
+#define WM8994_AIF2DRC_ATK_WIDTH                     4  /* AIF2DRC_ATK - [12:9] */
+#define WM8994_AIF2DRC_DCY_MASK                 0x01E0  /* AIF2DRC_DCY - [8:5] */
+#define WM8994_AIF2DRC_DCY_SHIFT                     5  /* AIF2DRC_DCY - [8:5] */
+#define WM8994_AIF2DRC_DCY_WIDTH                     4  /* AIF2DRC_DCY - [8:5] */
+#define WM8994_AIF2DRC_MINGAIN_MASK             0x001C  /* AIF2DRC_MINGAIN - [4:2] */
+#define WM8994_AIF2DRC_MINGAIN_SHIFT                 2  /* AIF2DRC_MINGAIN - [4:2] */
+#define WM8994_AIF2DRC_MINGAIN_WIDTH                 3  /* AIF2DRC_MINGAIN - [4:2] */
+#define WM8994_AIF2DRC_MAXGAIN_MASK             0x0003  /* AIF2DRC_MAXGAIN - [1:0] */
+#define WM8994_AIF2DRC_MAXGAIN_SHIFT                 0  /* AIF2DRC_MAXGAIN - [1:0] */
+#define WM8994_AIF2DRC_MAXGAIN_WIDTH                 2  /* AIF2DRC_MAXGAIN - [1:0] */
+
+/*
+ * R1346 (0x542) - AIF2 DRC (3)
+ */
+#define WM8994_AIF2DRC_NG_MINGAIN_MASK          0xF000  /* AIF2DRC_NG_MINGAIN - [15:12] */
+#define WM8994_AIF2DRC_NG_MINGAIN_SHIFT             12  /* AIF2DRC_NG_MINGAIN - [15:12] */
+#define WM8994_AIF2DRC_NG_MINGAIN_WIDTH              4  /* AIF2DRC_NG_MINGAIN - [15:12] */
+#define WM8994_AIF2DRC_NG_EXP_MASK              0x0C00  /* AIF2DRC_NG_EXP - [11:10] */
+#define WM8994_AIF2DRC_NG_EXP_SHIFT                 10  /* AIF2DRC_NG_EXP - [11:10] */
+#define WM8994_AIF2DRC_NG_EXP_WIDTH                  2  /* AIF2DRC_NG_EXP - [11:10] */
+#define WM8994_AIF2DRC_QR_THR_MASK              0x0300  /* AIF2DRC_QR_THR - [9:8] */
+#define WM8994_AIF2DRC_QR_THR_SHIFT                  8  /* AIF2DRC_QR_THR - [9:8] */
+#define WM8994_AIF2DRC_QR_THR_WIDTH                  2  /* AIF2DRC_QR_THR - [9:8] */
+#define WM8994_AIF2DRC_QR_DCY_MASK              0x00C0  /* AIF2DRC_QR_DCY - [7:6] */
+#define WM8994_AIF2DRC_QR_DCY_SHIFT                  6  /* AIF2DRC_QR_DCY - [7:6] */
+#define WM8994_AIF2DRC_QR_DCY_WIDTH                  2  /* AIF2DRC_QR_DCY - [7:6] */
+#define WM8994_AIF2DRC_HI_COMP_MASK             0x0038  /* AIF2DRC_HI_COMP - [5:3] */
+#define WM8994_AIF2DRC_HI_COMP_SHIFT                 3  /* AIF2DRC_HI_COMP - [5:3] */
+#define WM8994_AIF2DRC_HI_COMP_WIDTH                 3  /* AIF2DRC_HI_COMP - [5:3] */
+#define WM8994_AIF2DRC_LO_COMP_MASK             0x0007  /* AIF2DRC_LO_COMP - [2:0] */
+#define WM8994_AIF2DRC_LO_COMP_SHIFT                 0  /* AIF2DRC_LO_COMP - [2:0] */
+#define WM8994_AIF2DRC_LO_COMP_WIDTH                 3  /* AIF2DRC_LO_COMP - [2:0] */
+
+/*
+ * R1347 (0x543) - AIF2 DRC (4)
+ */
+#define WM8994_AIF2DRC_KNEE_IP_MASK             0x07E0  /* AIF2DRC_KNEE_IP - [10:5] */
+#define WM8994_AIF2DRC_KNEE_IP_SHIFT                 5  /* AIF2DRC_KNEE_IP - [10:5] */
+#define WM8994_AIF2DRC_KNEE_IP_WIDTH                 6  /* AIF2DRC_KNEE_IP - [10:5] */
+#define WM8994_AIF2DRC_KNEE_OP_MASK             0x001F  /* AIF2DRC_KNEE_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE_OP_SHIFT                 0  /* AIF2DRC_KNEE_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE_OP_WIDTH                 5  /* AIF2DRC_KNEE_OP - [4:0] */
+
+/*
+ * R1348 (0x544) - AIF2 DRC (5)
+ */
+#define WM8994_AIF2DRC_KNEE2_IP_MASK            0x03E0  /* AIF2DRC_KNEE2_IP - [9:5] */
+#define WM8994_AIF2DRC_KNEE2_IP_SHIFT                5  /* AIF2DRC_KNEE2_IP - [9:5] */
+#define WM8994_AIF2DRC_KNEE2_IP_WIDTH                5  /* AIF2DRC_KNEE2_IP - [9:5] */
+#define WM8994_AIF2DRC_KNEE2_OP_MASK            0x001F  /* AIF2DRC_KNEE2_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE2_OP_SHIFT                0  /* AIF2DRC_KNEE2_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE2_OP_WIDTH                5  /* AIF2DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R1408 (0x580) - AIF2 EQ Gains (1)
+ */
+#define WM8994_AIF2DAC_EQ_B1_GAIN_MASK          0xF800  /* AIF2DAC_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B1_GAIN_SHIFT             11  /* AIF2DAC_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B1_GAIN_WIDTH              5  /* AIF2DAC_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B2_GAIN_MASK          0x07C0  /* AIF2DAC_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B2_GAIN_SHIFT              6  /* AIF2DAC_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B2_GAIN_WIDTH              5  /* AIF2DAC_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B3_GAIN_MASK          0x003E  /* AIF2DAC_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF2DAC_EQ_B3_GAIN_SHIFT              1  /* AIF2DAC_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF2DAC_EQ_B3_GAIN_WIDTH              5  /* AIF2DAC_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF2DAC_EQ_ENA                   0x0001  /* AIF2DAC_EQ_ENA */
+#define WM8994_AIF2DAC_EQ_ENA_MASK              0x0001  /* AIF2DAC_EQ_ENA */
+#define WM8994_AIF2DAC_EQ_ENA_SHIFT                  0  /* AIF2DAC_EQ_ENA */
+#define WM8994_AIF2DAC_EQ_ENA_WIDTH                  1  /* AIF2DAC_EQ_ENA */
+
+/*
+ * R1409 (0x581) - AIF2 EQ Gains (2)
+ */
+#define WM8994_AIF2DAC_EQ_B4_GAIN_MASK          0xF800  /* AIF2DAC_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B4_GAIN_SHIFT             11  /* AIF2DAC_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B4_GAIN_WIDTH              5  /* AIF2DAC_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B5_GAIN_MASK          0x07C0  /* AIF2DAC_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B5_GAIN_SHIFT              6  /* AIF2DAC_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B5_GAIN_WIDTH              5  /* AIF2DAC_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1410 (0x582) - AIF2 EQ Band 1 A
+ */
+#define WM8994_AIF2DAC_EQ_B1_A_MASK             0xFFFF  /* AIF2DAC_EQ_B1_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_A_SHIFT                 0  /* AIF2DAC_EQ_B1_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_A_WIDTH                16  /* AIF2DAC_EQ_B1_A - [15:0] */
+
+/*
+ * R1411 (0x583) - AIF2 EQ Band 1 B
+ */
+#define WM8994_AIF2DAC_EQ_B1_B_MASK             0xFFFF  /* AIF2DAC_EQ_B1_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_B_SHIFT                 0  /* AIF2DAC_EQ_B1_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_B_WIDTH                16  /* AIF2DAC_EQ_B1_B - [15:0] */
+
+/*
+ * R1412 (0x584) - AIF2 EQ Band 1 PG
+ */
+#define WM8994_AIF2DAC_EQ_B1_PG_MASK            0xFFFF  /* AIF2DAC_EQ_B1_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_PG_SHIFT                0  /* AIF2DAC_EQ_B1_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_PG_WIDTH               16  /* AIF2DAC_EQ_B1_PG - [15:0] */
+
+/*
+ * R1413 (0x585) - AIF2 EQ Band 2 A
+ */
+#define WM8994_AIF2DAC_EQ_B2_A_MASK             0xFFFF  /* AIF2DAC_EQ_B2_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_A_SHIFT                 0  /* AIF2DAC_EQ_B2_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_A_WIDTH                16  /* AIF2DAC_EQ_B2_A - [15:0] */
+
+/*
+ * R1414 (0x586) - AIF2 EQ Band 2 B
+ */
+#define WM8994_AIF2DAC_EQ_B2_B_MASK             0xFFFF  /* AIF2DAC_EQ_B2_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_B_SHIFT                 0  /* AIF2DAC_EQ_B2_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_B_WIDTH                16  /* AIF2DAC_EQ_B2_B - [15:0] */
+
+/*
+ * R1415 (0x587) - AIF2 EQ Band 2 C
+ */
+#define WM8994_AIF2DAC_EQ_B2_C_MASK             0xFFFF  /* AIF2DAC_EQ_B2_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_C_SHIFT                 0  /* AIF2DAC_EQ_B2_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_C_WIDTH                16  /* AIF2DAC_EQ_B2_C - [15:0] */
+
+/*
+ * R1416 (0x588) - AIF2 EQ Band 2 PG
+ */
+#define WM8994_AIF2DAC_EQ_B2_PG_MASK            0xFFFF  /* AIF2DAC_EQ_B2_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_PG_SHIFT                0  /* AIF2DAC_EQ_B2_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_PG_WIDTH               16  /* AIF2DAC_EQ_B2_PG - [15:0] */
+
+/*
+ * R1417 (0x589) - AIF2 EQ Band 3 A
+ */
+#define WM8994_AIF2DAC_EQ_B3_A_MASK             0xFFFF  /* AIF2DAC_EQ_B3_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_A_SHIFT                 0  /* AIF2DAC_EQ_B3_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_A_WIDTH                16  /* AIF2DAC_EQ_B3_A - [15:0] */
+
+/*
+ * R1418 (0x58A) - AIF2 EQ Band 3 B
+ */
+#define WM8994_AIF2DAC_EQ_B3_B_MASK             0xFFFF  /* AIF2DAC_EQ_B3_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_B_SHIFT                 0  /* AIF2DAC_EQ_B3_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_B_WIDTH                16  /* AIF2DAC_EQ_B3_B - [15:0] */
+
+/*
+ * R1419 (0x58B) - AIF2 EQ Band 3 C
+ */
+#define WM8994_AIF2DAC_EQ_B3_C_MASK             0xFFFF  /* AIF2DAC_EQ_B3_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_C_SHIFT                 0  /* AIF2DAC_EQ_B3_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_C_WIDTH                16  /* AIF2DAC_EQ_B3_C - [15:0] */
+
+/*
+ * R1420 (0x58C) - AIF2 EQ Band 3 PG
+ */
+#define WM8994_AIF2DAC_EQ_B3_PG_MASK            0xFFFF  /* AIF2DAC_EQ_B3_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_PG_SHIFT                0  /* AIF2DAC_EQ_B3_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_PG_WIDTH               16  /* AIF2DAC_EQ_B3_PG - [15:0] */
+
+/*
+ * R1421 (0x58D) - AIF2 EQ Band 4 A
+ */
+#define WM8994_AIF2DAC_EQ_B4_A_MASK             0xFFFF  /* AIF2DAC_EQ_B4_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_A_SHIFT                 0  /* AIF2DAC_EQ_B4_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_A_WIDTH                16  /* AIF2DAC_EQ_B4_A - [15:0] */
+
+/*
+ * R1422 (0x58E) - AIF2 EQ Band 4 B
+ */
+#define WM8994_AIF2DAC_EQ_B4_B_MASK             0xFFFF  /* AIF2DAC_EQ_B4_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_B_SHIFT                 0  /* AIF2DAC_EQ_B4_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_B_WIDTH                16  /* AIF2DAC_EQ_B4_B - [15:0] */
+
+/*
+ * R1423 (0x58F) - AIF2 EQ Band 4 C
+ */
+#define WM8994_AIF2DAC_EQ_B4_C_MASK             0xFFFF  /* AIF2DAC_EQ_B4_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_C_SHIFT                 0  /* AIF2DAC_EQ_B4_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_C_WIDTH                16  /* AIF2DAC_EQ_B4_C - [15:0] */
+
+/*
+ * R1424 (0x590) - AIF2 EQ Band 4 PG
+ */
+#define WM8994_AIF2DAC_EQ_B4_PG_MASK            0xFFFF  /* AIF2DAC_EQ_B4_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_PG_SHIFT                0  /* AIF2DAC_EQ_B4_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_PG_WIDTH               16  /* AIF2DAC_EQ_B4_PG - [15:0] */
+
+/*
+ * R1425 (0x591) - AIF2 EQ Band 5 A
+ */
+#define WM8994_AIF2DAC_EQ_B5_A_MASK             0xFFFF  /* AIF2DAC_EQ_B5_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_A_SHIFT                 0  /* AIF2DAC_EQ_B5_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_A_WIDTH                16  /* AIF2DAC_EQ_B5_A - [15:0] */
+
+/*
+ * R1426 (0x592) - AIF2 EQ Band 5 B
+ */
+#define WM8994_AIF2DAC_EQ_B5_B_MASK             0xFFFF  /* AIF2DAC_EQ_B5_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_B_SHIFT                 0  /* AIF2DAC_EQ_B5_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_B_WIDTH                16  /* AIF2DAC_EQ_B5_B - [15:0] */
+
+/*
+ * R1427 (0x593) - AIF2 EQ Band 5 PG
+ */
+#define WM8994_AIF2DAC_EQ_B5_PG_MASK            0xFFFF  /* AIF2DAC_EQ_B5_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_PG_SHIFT                0  /* AIF2DAC_EQ_B5_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_PG_WIDTH               16  /* AIF2DAC_EQ_B5_PG - [15:0] */
+
+/*
+ * R1536 (0x600) - DAC1 Mixer Volumes
+ */
+#define WM8994_ADCR_DAC1_VOL_MASK               0x01E0  /* ADCR_DAC1_VOL - [8:5] */
+#define WM8994_ADCR_DAC1_VOL_SHIFT                   5  /* ADCR_DAC1_VOL - [8:5] */
+#define WM8994_ADCR_DAC1_VOL_WIDTH                   4  /* ADCR_DAC1_VOL - [8:5] */
+#define WM8994_ADCL_DAC1_VOL_MASK               0x000F  /* ADCL_DAC1_VOL - [3:0] */
+#define WM8994_ADCL_DAC1_VOL_SHIFT                   0  /* ADCL_DAC1_VOL - [3:0] */
+#define WM8994_ADCL_DAC1_VOL_WIDTH                   4  /* ADCL_DAC1_VOL - [3:0] */
+
+/*
+ * R1537 (0x601) - DAC1 Left Mixer Routing
+ */
+#define WM8994_ADCR_TO_DAC1L                    0x0020  /* ADCR_TO_DAC1L */
+#define WM8994_ADCR_TO_DAC1L_MASK               0x0020  /* ADCR_TO_DAC1L */
+#define WM8994_ADCR_TO_DAC1L_SHIFT                   5  /* ADCR_TO_DAC1L */
+#define WM8994_ADCR_TO_DAC1L_WIDTH                   1  /* ADCR_TO_DAC1L */
+#define WM8994_ADCL_TO_DAC1L                    0x0010  /* ADCL_TO_DAC1L */
+#define WM8994_ADCL_TO_DAC1L_MASK               0x0010  /* ADCL_TO_DAC1L */
+#define WM8994_ADCL_TO_DAC1L_SHIFT                   4  /* ADCL_TO_DAC1L */
+#define WM8994_ADCL_TO_DAC1L_WIDTH                   1  /* ADCL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L                0x0004  /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L_MASK           0x0004  /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L_SHIFT               2  /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L_WIDTH               1  /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L               0x0002  /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L_MASK          0x0002  /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L_SHIFT              1  /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L_WIDTH              1  /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L               0x0001  /* AIF1DAC1L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L_MASK          0x0001  /* AIF1DAC1L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L_SHIFT              0  /* AIF1DAC1L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L_WIDTH              1  /* AIF1DAC1L_TO_DAC1L */
+
+/*
+ * R1538 (0x602) - DAC1 Right Mixer Routing
+ */
+#define WM8994_ADCR_TO_DAC1R                    0x0020  /* ADCR_TO_DAC1R */
+#define WM8994_ADCR_TO_DAC1R_MASK               0x0020  /* ADCR_TO_DAC1R */
+#define WM8994_ADCR_TO_DAC1R_SHIFT                   5  /* ADCR_TO_DAC1R */
+#define WM8994_ADCR_TO_DAC1R_WIDTH                   1  /* ADCR_TO_DAC1R */
+#define WM8994_ADCL_TO_DAC1R                    0x0010  /* ADCL_TO_DAC1R */
+#define WM8994_ADCL_TO_DAC1R_MASK               0x0010  /* ADCL_TO_DAC1R */
+#define WM8994_ADCL_TO_DAC1R_SHIFT                   4  /* ADCL_TO_DAC1R */
+#define WM8994_ADCL_TO_DAC1R_WIDTH                   1  /* ADCL_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R                0x0004  /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R_MASK           0x0004  /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R_SHIFT               2  /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R_WIDTH               1  /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R               0x0002  /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R_MASK          0x0002  /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R_SHIFT              1  /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R_WIDTH              1  /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R               0x0001  /* AIF1DAC1R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R_MASK          0x0001  /* AIF1DAC1R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R_SHIFT              0  /* AIF1DAC1R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R_WIDTH              1  /* AIF1DAC1R_TO_DAC1R */
+
+/*
+ * R1539 (0x603) - DAC2 Mixer Volumes
+ */
+#define WM8994_ADCR_DAC2_VOL_MASK               0x01E0  /* ADCR_DAC2_VOL - [8:5] */
+#define WM8994_ADCR_DAC2_VOL_SHIFT                   5  /* ADCR_DAC2_VOL - [8:5] */
+#define WM8994_ADCR_DAC2_VOL_WIDTH                   4  /* ADCR_DAC2_VOL - [8:5] */
+#define WM8994_ADCL_DAC2_VOL_MASK               0x000F  /* ADCL_DAC2_VOL - [3:0] */
+#define WM8994_ADCL_DAC2_VOL_SHIFT                   0  /* ADCL_DAC2_VOL - [3:0] */
+#define WM8994_ADCL_DAC2_VOL_WIDTH                   4  /* ADCL_DAC2_VOL - [3:0] */
+
+/*
+ * R1540 (0x604) - DAC2 Left Mixer Routing
+ */
+#define WM8994_ADCR_TO_DAC2L                    0x0020  /* ADCR_TO_DAC2L */
+#define WM8994_ADCR_TO_DAC2L_MASK               0x0020  /* ADCR_TO_DAC2L */
+#define WM8994_ADCR_TO_DAC2L_SHIFT                   5  /* ADCR_TO_DAC2L */
+#define WM8994_ADCR_TO_DAC2L_WIDTH                   1  /* ADCR_TO_DAC2L */
+#define WM8994_ADCL_TO_DAC2L                    0x0010  /* ADCL_TO_DAC2L */
+#define WM8994_ADCL_TO_DAC2L_MASK               0x0010  /* ADCL_TO_DAC2L */
+#define WM8994_ADCL_TO_DAC2L_SHIFT                   4  /* ADCL_TO_DAC2L */
+#define WM8994_ADCL_TO_DAC2L_WIDTH                   1  /* ADCL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L                0x0004  /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L_MASK           0x0004  /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L_SHIFT               2  /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L_WIDTH               1  /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L               0x0002  /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L_MASK          0x0002  /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L_SHIFT              1  /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L_WIDTH              1  /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L               0x0001  /* AIF1DAC1L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L_MASK          0x0001  /* AIF1DAC1L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L_SHIFT              0  /* AIF1DAC1L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L_WIDTH              1  /* AIF1DAC1L_TO_DAC2L */
+
+/*
+ * R1541 (0x605) - DAC2 Right Mixer Routing
+ */
+#define WM8994_ADCR_TO_DAC2R                    0x0020  /* ADCR_TO_DAC2R */
+#define WM8994_ADCR_TO_DAC2R_MASK               0x0020  /* ADCR_TO_DAC2R */
+#define WM8994_ADCR_TO_DAC2R_SHIFT                   5  /* ADCR_TO_DAC2R */
+#define WM8994_ADCR_TO_DAC2R_WIDTH                   1  /* ADCR_TO_DAC2R */
+#define WM8994_ADCL_TO_DAC2R                    0x0010  /* ADCL_TO_DAC2R */
+#define WM8994_ADCL_TO_DAC2R_MASK               0x0010  /* ADCL_TO_DAC2R */
+#define WM8994_ADCL_TO_DAC2R_SHIFT                   4  /* ADCL_TO_DAC2R */
+#define WM8994_ADCL_TO_DAC2R_WIDTH                   1  /* ADCL_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R                0x0004  /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R_MASK           0x0004  /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R_SHIFT               2  /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R_WIDTH               1  /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R               0x0002  /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R_MASK          0x0002  /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R_SHIFT              1  /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R_WIDTH              1  /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R               0x0001  /* AIF1DAC1R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R_MASK          0x0001  /* AIF1DAC1R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R_SHIFT              0  /* AIF1DAC1R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R_WIDTH              1  /* AIF1DAC1R_TO_DAC2R */
+
+/*
+ * R1542 (0x606) - AIF1 ADC1 Left Mixer Routing
+ */
+#define WM8994_ADC1L_TO_AIF1ADC1L               0x0002  /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_ADC1L_TO_AIF1ADC1L_MASK          0x0002  /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_ADC1L_TO_AIF1ADC1L_SHIFT              1  /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_ADC1L_TO_AIF1ADC1L_WIDTH              1  /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L            0x0001  /* AIF2DACL_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L_MASK       0x0001  /* AIF2DACL_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L_SHIFT           0  /* AIF2DACL_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L_WIDTH           1  /* AIF2DACL_TO_AIF1ADC1L */
+
+/*
+ * R1543 (0x607) - AIF1 ADC1 Right Mixer Routing
+ */
+#define WM8994_ADC1R_TO_AIF1ADC1R               0x0002  /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_ADC1R_TO_AIF1ADC1R_MASK          0x0002  /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_ADC1R_TO_AIF1ADC1R_SHIFT              1  /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_ADC1R_TO_AIF1ADC1R_WIDTH              1  /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R            0x0001  /* AIF2DACR_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R_MASK       0x0001  /* AIF2DACR_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R_SHIFT           0  /* AIF2DACR_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R_WIDTH           1  /* AIF2DACR_TO_AIF1ADC1R */
+
+/*
+ * R1544 (0x608) - AIF1 ADC2 Left Mixer Routing
+ */
+#define WM8994_ADC2L_TO_AIF1ADC2L               0x0002  /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_ADC2L_TO_AIF1ADC2L_MASK          0x0002  /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_ADC2L_TO_AIF1ADC2L_SHIFT              1  /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_ADC2L_TO_AIF1ADC2L_WIDTH              1  /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L            0x0001  /* AIF2DACL_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L_MASK       0x0001  /* AIF2DACL_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L_SHIFT           0  /* AIF2DACL_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L_WIDTH           1  /* AIF2DACL_TO_AIF1ADC2L */
+
+/*
+ * R1545 (0x609) - AIF1 ADC2 Right mixer Routing
+ */
+#define WM8994_ADC2R_TO_AIF1ADC2R               0x0002  /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_ADC2R_TO_AIF1ADC2R_MASK          0x0002  /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_ADC2R_TO_AIF1ADC2R_SHIFT              1  /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_ADC2R_TO_AIF1ADC2R_WIDTH              1  /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R            0x0001  /* AIF2DACR_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R_MASK       0x0001  /* AIF2DACR_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R_SHIFT           0  /* AIF2DACR_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R_WIDTH           1  /* AIF2DACR_TO_AIF1ADC2R */
+
+/*
+ * R1552 (0x610) - DAC1 Left Volume
+ */
+#define WM8994_DAC1L_MUTE                       0x0200  /* DAC1L_MUTE */
+#define WM8994_DAC1L_MUTE_MASK                  0x0200  /* DAC1L_MUTE */
+#define WM8994_DAC1L_MUTE_SHIFT                      9  /* DAC1L_MUTE */
+#define WM8994_DAC1L_MUTE_WIDTH                      1  /* DAC1L_MUTE */
+#define WM8994_DAC1_VU                          0x0100  /* DAC1_VU */
+#define WM8994_DAC1_VU_MASK                     0x0100  /* DAC1_VU */
+#define WM8994_DAC1_VU_SHIFT                         8  /* DAC1_VU */
+#define WM8994_DAC1_VU_WIDTH                         1  /* DAC1_VU */
+#define WM8994_DAC1L_VOL_MASK                   0x00FF  /* DAC1L_VOL - [7:0] */
+#define WM8994_DAC1L_VOL_SHIFT                       0  /* DAC1L_VOL - [7:0] */
+#define WM8994_DAC1L_VOL_WIDTH                       8  /* DAC1L_VOL - [7:0] */
+
+/*
+ * R1553 (0x611) - DAC1 Right Volume
+ */
+#define WM8994_DAC1R_MUTE                       0x0200  /* DAC1R_MUTE */
+#define WM8994_DAC1R_MUTE_MASK                  0x0200  /* DAC1R_MUTE */
+#define WM8994_DAC1R_MUTE_SHIFT                      9  /* DAC1R_MUTE */
+#define WM8994_DAC1R_MUTE_WIDTH                      1  /* DAC1R_MUTE */
+#define WM8994_DAC1_VU                          0x0100  /* DAC1_VU */
+#define WM8994_DAC1_VU_MASK                     0x0100  /* DAC1_VU */
+#define WM8994_DAC1_VU_SHIFT                         8  /* DAC1_VU */
+#define WM8994_DAC1_VU_WIDTH                         1  /* DAC1_VU */
+#define WM8994_DAC1R_VOL_MASK                   0x00FF  /* DAC1R_VOL - [7:0] */
+#define WM8994_DAC1R_VOL_SHIFT                       0  /* DAC1R_VOL - [7:0] */
+#define WM8994_DAC1R_VOL_WIDTH                       8  /* DAC1R_VOL - [7:0] */
+
+/*
+ * R1554 (0x612) - DAC2 Left Volume
+ */
+#define WM8994_DAC2L_MUTE                       0x0200  /* DAC2L_MUTE */
+#define WM8994_DAC2L_MUTE_MASK                  0x0200  /* DAC2L_MUTE */
+#define WM8994_DAC2L_MUTE_SHIFT                      9  /* DAC2L_MUTE */
+#define WM8994_DAC2L_MUTE_WIDTH                      1  /* DAC2L_MUTE */
+#define WM8994_DAC2_VU                          0x0100  /* DAC2_VU */
+#define WM8994_DAC2_VU_MASK                     0x0100  /* DAC2_VU */
+#define WM8994_DAC2_VU_SHIFT                         8  /* DAC2_VU */
+#define WM8994_DAC2_VU_WIDTH                         1  /* DAC2_VU */
+#define WM8994_DAC2L_VOL_MASK                   0x00FF  /* DAC2L_VOL - [7:0] */
+#define WM8994_DAC2L_VOL_SHIFT                       0  /* DAC2L_VOL - [7:0] */
+#define WM8994_DAC2L_VOL_WIDTH                       8  /* DAC2L_VOL - [7:0] */
+
+/*
+ * R1555 (0x613) - DAC2 Right Volume
+ */
+#define WM8994_DAC2R_MUTE                       0x0200  /* DAC2R_MUTE */
+#define WM8994_DAC2R_MUTE_MASK                  0x0200  /* DAC2R_MUTE */
+#define WM8994_DAC2R_MUTE_SHIFT                      9  /* DAC2R_MUTE */
+#define WM8994_DAC2R_MUTE_WIDTH                      1  /* DAC2R_MUTE */
+#define WM8994_DAC2_VU                          0x0100  /* DAC2_VU */
+#define WM8994_DAC2_VU_MASK                     0x0100  /* DAC2_VU */
+#define WM8994_DAC2_VU_SHIFT                         8  /* DAC2_VU */
+#define WM8994_DAC2_VU_WIDTH                         1  /* DAC2_VU */
+#define WM8994_DAC2R_VOL_MASK                   0x00FF  /* DAC2R_VOL - [7:0] */
+#define WM8994_DAC2R_VOL_SHIFT                       0  /* DAC2R_VOL - [7:0] */
+#define WM8994_DAC2R_VOL_WIDTH                       8  /* DAC2R_VOL - [7:0] */
+
+/*
+ * R1556 (0x614) - DAC Softmute
+ */
+#define WM8994_DAC_SOFTMUTEMODE                 0x0002  /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_SOFTMUTEMODE_MASK            0x0002  /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_SOFTMUTEMODE_SHIFT                1  /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_SOFTMUTEMODE_WIDTH                1  /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_MUTERATE                     0x0001  /* DAC_MUTERATE */
+#define WM8994_DAC_MUTERATE_MASK                0x0001  /* DAC_MUTERATE */
+#define WM8994_DAC_MUTERATE_SHIFT                    0  /* DAC_MUTERATE */
+#define WM8994_DAC_MUTERATE_WIDTH                    1  /* DAC_MUTERATE */
+
+/*
+ * R1568 (0x620) - Oversampling
+ */
+#define WM8994_ADC_OSR128                       0x0002  /* ADC_OSR128 */
+#define WM8994_ADC_OSR128_MASK                  0x0002  /* ADC_OSR128 */
+#define WM8994_ADC_OSR128_SHIFT                      1  /* ADC_OSR128 */
+#define WM8994_ADC_OSR128_WIDTH                      1  /* ADC_OSR128 */
+#define WM8994_DAC_OSR128                       0x0001  /* DAC_OSR128 */
+#define WM8994_DAC_OSR128_MASK                  0x0001  /* DAC_OSR128 */
+#define WM8994_DAC_OSR128_SHIFT                      0  /* DAC_OSR128 */
+#define WM8994_DAC_OSR128_WIDTH                      1  /* DAC_OSR128 */
+
+/*
+ * R1569 (0x621) - Sidetone
+ */
+#define WM8994_ST_HPF_CUT_MASK                  0x0380  /* ST_HPF_CUT - [9:7] */
+#define WM8994_ST_HPF_CUT_SHIFT                      7  /* ST_HPF_CUT - [9:7] */
+#define WM8994_ST_HPF_CUT_WIDTH                      3  /* ST_HPF_CUT - [9:7] */
+#define WM8994_ST_HPF                           0x0040  /* ST_HPF */
+#define WM8994_ST_HPF_MASK                      0x0040  /* ST_HPF */
+#define WM8994_ST_HPF_SHIFT                          6  /* ST_HPF */
+#define WM8994_ST_HPF_WIDTH                          1  /* ST_HPF */
+#define WM8994_STR_SEL                          0x0002  /* STR_SEL */
+#define WM8994_STR_SEL_MASK                     0x0002  /* STR_SEL */
+#define WM8994_STR_SEL_SHIFT                         1  /* STR_SEL */
+#define WM8994_STR_SEL_WIDTH                         1  /* STR_SEL */
+#define WM8994_STL_SEL                          0x0001  /* STL_SEL */
+#define WM8994_STL_SEL_MASK                     0x0001  /* STL_SEL */
+#define WM8994_STL_SEL_SHIFT                         0  /* STL_SEL */
+#define WM8994_STL_SEL_WIDTH                         1  /* STL_SEL */
+
+/*
+ * R1824 (0x720) - Pull Control (1)
+ */
+#define WM8994_DMICDAT2_PU                      0x0800  /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PU_MASK                 0x0800  /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PU_SHIFT                    11  /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PU_WIDTH                     1  /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PD                      0x0400  /* DMICDAT2_PD */
+#define WM8994_DMICDAT2_PD_MASK                 0x0400  /* DMICDAT2_PD */
+#define WM8994_DMICDAT2_PD_SHIFT                    10  /* DMICDAT2_PD */
+#define WM8994_DMICDAT2_PD_WIDTH                     1  /* DMICDAT2_PD */
+#define WM8994_DMICDAT1_PU                      0x0200  /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PU_MASK                 0x0200  /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PU_SHIFT                     9  /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PU_WIDTH                     1  /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PD                      0x0100  /* DMICDAT1_PD */
+#define WM8994_DMICDAT1_PD_MASK                 0x0100  /* DMICDAT1_PD */
+#define WM8994_DMICDAT1_PD_SHIFT                     8  /* DMICDAT1_PD */
+#define WM8994_DMICDAT1_PD_WIDTH                     1  /* DMICDAT1_PD */
+#define WM8994_MCLK1_PU                         0x0080  /* MCLK1_PU */
+#define WM8994_MCLK1_PU_MASK                    0x0080  /* MCLK1_PU */
+#define WM8994_MCLK1_PU_SHIFT                        7  /* MCLK1_PU */
+#define WM8994_MCLK1_PU_WIDTH                        1  /* MCLK1_PU */
+#define WM8994_MCLK1_PD                         0x0040  /* MCLK1_PD */
+#define WM8994_MCLK1_PD_MASK                    0x0040  /* MCLK1_PD */
+#define WM8994_MCLK1_PD_SHIFT                        6  /* MCLK1_PD */
+#define WM8994_MCLK1_PD_WIDTH                        1  /* MCLK1_PD */
+#define WM8994_DACDAT1_PU                       0x0020  /* DACDAT1_PU */
+#define WM8994_DACDAT1_PU_MASK                  0x0020  /* DACDAT1_PU */
+#define WM8994_DACDAT1_PU_SHIFT                      5  /* DACDAT1_PU */
+#define WM8994_DACDAT1_PU_WIDTH                      1  /* DACDAT1_PU */
+#define WM8994_DACDAT1_PD                       0x0010  /* DACDAT1_PD */
+#define WM8994_DACDAT1_PD_MASK                  0x0010  /* DACDAT1_PD */
+#define WM8994_DACDAT1_PD_SHIFT                      4  /* DACDAT1_PD */
+#define WM8994_DACDAT1_PD_WIDTH                      1  /* DACDAT1_PD */
+#define WM8994_DACLRCLK1_PU                     0x0008  /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PU_MASK                0x0008  /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PU_SHIFT                    3  /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PU_WIDTH                    1  /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PD                     0x0004  /* DACLRCLK1_PD */
+#define WM8994_DACLRCLK1_PD_MASK                0x0004  /* DACLRCLK1_PD */
+#define WM8994_DACLRCLK1_PD_SHIFT                    2  /* DACLRCLK1_PD */
+#define WM8994_DACLRCLK1_PD_WIDTH                    1  /* DACLRCLK1_PD */
+#define WM8994_BCLK1_PU                         0x0002  /* BCLK1_PU */
+#define WM8994_BCLK1_PU_MASK                    0x0002  /* BCLK1_PU */
+#define WM8994_BCLK1_PU_SHIFT                        1  /* BCLK1_PU */
+#define WM8994_BCLK1_PU_WIDTH                        1  /* BCLK1_PU */
+#define WM8994_BCLK1_PD                         0x0001  /* BCLK1_PD */
+#define WM8994_BCLK1_PD_MASK                    0x0001  /* BCLK1_PD */
+#define WM8994_BCLK1_PD_SHIFT                        0  /* BCLK1_PD */
+#define WM8994_BCLK1_PD_WIDTH                        1  /* BCLK1_PD */
+
+/*
+ * R1825 (0x721) - Pull Control (2)
+ */
+#define WM8994_CSNADDR_PD                       0x0100  /* CSNADDR_PD */
+#define WM8994_CSNADDR_PD_MASK                  0x0100  /* CSNADDR_PD */
+#define WM8994_CSNADDR_PD_SHIFT                      8  /* CSNADDR_PD */
+#define WM8994_CSNADDR_PD_WIDTH                      1  /* CSNADDR_PD */
+#define WM8994_LDO2ENA_PD                       0x0040  /* LDO2ENA_PD */
+#define WM8994_LDO2ENA_PD_MASK                  0x0040  /* LDO2ENA_PD */
+#define WM8994_LDO2ENA_PD_SHIFT                      6  /* LDO2ENA_PD */
+#define WM8994_LDO2ENA_PD_WIDTH                      1  /* LDO2ENA_PD */
+#define WM8994_LDO1ENA_PD                       0x0010  /* LDO1ENA_PD */
+#define WM8994_LDO1ENA_PD_MASK                  0x0010  /* LDO1ENA_PD */
+#define WM8994_LDO1ENA_PD_SHIFT                      4  /* LDO1ENA_PD */
+#define WM8994_LDO1ENA_PD_WIDTH                      1  /* LDO1ENA_PD */
+#define WM8994_CIFMODE_PD                       0x0004  /* CIFMODE_PD */
+#define WM8994_CIFMODE_PD_MASK                  0x0004  /* CIFMODE_PD */
+#define WM8994_CIFMODE_PD_SHIFT                      2  /* CIFMODE_PD */
+#define WM8994_CIFMODE_PD_WIDTH                      1  /* CIFMODE_PD */
+#define WM8994_SPKMODE_PU                       0x0002  /* SPKMODE_PU */
+#define WM8994_SPKMODE_PU_MASK                  0x0002  /* SPKMODE_PU */
+#define WM8994_SPKMODE_PU_SHIFT                      1  /* SPKMODE_PU */
+#define WM8994_SPKMODE_PU_WIDTH                      1  /* SPKMODE_PU */
+
+/*
+ * R1840 (0x730) - Interrupt Status 1
+ */
+#define WM8994_GP11_EINT                        0x0400  /* GP11_EINT */
+#define WM8994_GP11_EINT_MASK                   0x0400  /* GP11_EINT */
+#define WM8994_GP11_EINT_SHIFT                      10  /* GP11_EINT */
+#define WM8994_GP11_EINT_WIDTH                       1  /* GP11_EINT */
+#define WM8994_GP10_EINT                        0x0200  /* GP10_EINT */
+#define WM8994_GP10_EINT_MASK                   0x0200  /* GP10_EINT */
+#define WM8994_GP10_EINT_SHIFT                       9  /* GP10_EINT */
+#define WM8994_GP10_EINT_WIDTH                       1  /* GP10_EINT */
+#define WM8994_GP9_EINT                         0x0100  /* GP9_EINT */
+#define WM8994_GP9_EINT_MASK                    0x0100  /* GP9_EINT */
+#define WM8994_GP9_EINT_SHIFT                        8  /* GP9_EINT */
+#define WM8994_GP9_EINT_WIDTH                        1  /* GP9_EINT */
+#define WM8994_GP8_EINT                         0x0080  /* GP8_EINT */
+#define WM8994_GP8_EINT_MASK                    0x0080  /* GP8_EINT */
+#define WM8994_GP8_EINT_SHIFT                        7  /* GP8_EINT */
+#define WM8994_GP8_EINT_WIDTH                        1  /* GP8_EINT */
+#define WM8994_GP7_EINT                         0x0040  /* GP7_EINT */
+#define WM8994_GP7_EINT_MASK                    0x0040  /* GP7_EINT */
+#define WM8994_GP7_EINT_SHIFT                        6  /* GP7_EINT */
+#define WM8994_GP7_EINT_WIDTH                        1  /* GP7_EINT */
+#define WM8994_GP6_EINT                         0x0020  /* GP6_EINT */
+#define WM8994_GP6_EINT_MASK                    0x0020  /* GP6_EINT */
+#define WM8994_GP6_EINT_SHIFT                        5  /* GP6_EINT */
+#define WM8994_GP6_EINT_WIDTH                        1  /* GP6_EINT */
+#define WM8994_GP5_EINT                         0x0010  /* GP5_EINT */
+#define WM8994_GP5_EINT_MASK                    0x0010  /* GP5_EINT */
+#define WM8994_GP5_EINT_SHIFT                        4  /* GP5_EINT */
+#define WM8994_GP5_EINT_WIDTH                        1  /* GP5_EINT */
+#define WM8994_GP4_EINT                         0x0008  /* GP4_EINT */
+#define WM8994_GP4_EINT_MASK                    0x0008  /* GP4_EINT */
+#define WM8994_GP4_EINT_SHIFT                        3  /* GP4_EINT */
+#define WM8994_GP4_EINT_WIDTH                        1  /* GP4_EINT */
+#define WM8994_GP3_EINT                         0x0004  /* GP3_EINT */
+#define WM8994_GP3_EINT_MASK                    0x0004  /* GP3_EINT */
+#define WM8994_GP3_EINT_SHIFT                        2  /* GP3_EINT */
+#define WM8994_GP3_EINT_WIDTH                        1  /* GP3_EINT */
+#define WM8994_GP2_EINT                         0x0002  /* GP2_EINT */
+#define WM8994_GP2_EINT_MASK                    0x0002  /* GP2_EINT */
+#define WM8994_GP2_EINT_SHIFT                        1  /* GP2_EINT */
+#define WM8994_GP2_EINT_WIDTH                        1  /* GP2_EINT */
+#define WM8994_GP1_EINT                         0x0001  /* GP1_EINT */
+#define WM8994_GP1_EINT_MASK                    0x0001  /* GP1_EINT */
+#define WM8994_GP1_EINT_SHIFT                        0  /* GP1_EINT */
+#define WM8994_GP1_EINT_WIDTH                        1  /* GP1_EINT */
+
+/*
+ * R1841 (0x731) - Interrupt Status 2
+ */
+#define WM8994_TEMP_WARN_EINT                   0x8000  /* TEMP_WARN_EINT */
+#define WM8994_TEMP_WARN_EINT_MASK              0x8000  /* TEMP_WARN_EINT */
+#define WM8994_TEMP_WARN_EINT_SHIFT                 15  /* TEMP_WARN_EINT */
+#define WM8994_TEMP_WARN_EINT_WIDTH                  1  /* TEMP_WARN_EINT */
+#define WM8994_DCS_DONE_EINT                    0x4000  /* DCS_DONE_EINT */
+#define WM8994_DCS_DONE_EINT_MASK               0x4000  /* DCS_DONE_EINT */
+#define WM8994_DCS_DONE_EINT_SHIFT                  14  /* DCS_DONE_EINT */
+#define WM8994_DCS_DONE_EINT_WIDTH                   1  /* DCS_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT                   0x2000  /* WSEQ_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT_MASK              0x2000  /* WSEQ_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT_SHIFT                 13  /* WSEQ_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT_WIDTH                  1  /* WSEQ_DONE_EINT */
+#define WM8994_FIFOS_ERR_EINT                   0x1000  /* FIFOS_ERR_EINT */
+#define WM8994_FIFOS_ERR_EINT_MASK              0x1000  /* FIFOS_ERR_EINT */
+#define WM8994_FIFOS_ERR_EINT_SHIFT                 12  /* FIFOS_ERR_EINT */
+#define WM8994_FIFOS_ERR_EINT_WIDTH                  1  /* FIFOS_ERR_EINT */
+#define WM8994_AIF2DRC_SIG_DET_EINT             0x0800  /* AIF2DRC_SIG_DET_EINT */
+#define WM8994_AIF2DRC_SIG_DET_EINT_MASK        0x0800  /* AIF2DRC_SIG_DET_EINT */
+#define WM8994_AIF2DRC_SIG_DET_EINT_SHIFT           11  /* AIF2DRC_SIG_DET_EINT */
+#define WM8994_AIF2DRC_SIG_DET_EINT_WIDTH            1  /* AIF2DRC_SIG_DET_EINT */
+#define WM8994_AIF1DRC2_SIG_DET_EINT            0x0400  /* AIF1DRC2_SIG_DET_EINT */
+#define WM8994_AIF1DRC2_SIG_DET_EINT_MASK       0x0400  /* AIF1DRC2_SIG_DET_EINT */
+#define WM8994_AIF1DRC2_SIG_DET_EINT_SHIFT          10  /* AIF1DRC2_SIG_DET_EINT */
+#define WM8994_AIF1DRC2_SIG_DET_EINT_WIDTH           1  /* AIF1DRC2_SIG_DET_EINT */
+#define WM8994_AIF1DRC1_SIG_DET_EINT            0x0200  /* AIF1DRC1_SIG_DET_EINT */
+#define WM8994_AIF1DRC1_SIG_DET_EINT_MASK       0x0200  /* AIF1DRC1_SIG_DET_EINT */
+#define WM8994_AIF1DRC1_SIG_DET_EINT_SHIFT           9  /* AIF1DRC1_SIG_DET_EINT */
+#define WM8994_AIF1DRC1_SIG_DET_EINT_WIDTH           1  /* AIF1DRC1_SIG_DET_EINT */
+#define WM8994_SRC2_LOCK_EINT                   0x0100  /* SRC2_LOCK_EINT */
+#define WM8994_SRC2_LOCK_EINT_MASK              0x0100  /* SRC2_LOCK_EINT */
+#define WM8994_SRC2_LOCK_EINT_SHIFT                  8  /* SRC2_LOCK_EINT */
+#define WM8994_SRC2_LOCK_EINT_WIDTH                  1  /* SRC2_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT                   0x0080  /* SRC1_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT_MASK              0x0080  /* SRC1_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT_SHIFT                  7  /* SRC1_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT_WIDTH                  1  /* SRC1_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT                   0x0040  /* FLL2_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT_MASK              0x0040  /* FLL2_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT_SHIFT                  6  /* FLL2_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT_WIDTH                  1  /* FLL2_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT                   0x0020  /* FLL1_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT_MASK              0x0020  /* FLL1_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT_SHIFT                  5  /* FLL1_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT_WIDTH                  1  /* FLL1_LOCK_EINT */
+#define WM8994_MIC2_SHRT_EINT                   0x0010  /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_SHRT_EINT_MASK              0x0010  /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_SHRT_EINT_SHIFT                  4  /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_SHRT_EINT_WIDTH                  1  /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_DET_EINT                    0x0008  /* MIC2_DET_EINT */
+#define WM8994_MIC2_DET_EINT_MASK               0x0008  /* MIC2_DET_EINT */
+#define WM8994_MIC2_DET_EINT_SHIFT                   3  /* MIC2_DET_EINT */
+#define WM8994_MIC2_DET_EINT_WIDTH                   1  /* MIC2_DET_EINT */
+#define WM8994_MIC1_SHRT_EINT                   0x0004  /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_SHRT_EINT_MASK              0x0004  /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_SHRT_EINT_SHIFT                  2  /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_SHRT_EINT_WIDTH                  1  /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_DET_EINT                    0x0002  /* MIC1_DET_EINT */
+#define WM8994_MIC1_DET_EINT_MASK               0x0002  /* MIC1_DET_EINT */
+#define WM8994_MIC1_DET_EINT_SHIFT                   1  /* MIC1_DET_EINT */
+#define WM8994_MIC1_DET_EINT_WIDTH                   1  /* MIC1_DET_EINT */
+#define WM8994_TEMP_SHUT_EINT                   0x0001  /* TEMP_SHUT_EINT */
+#define WM8994_TEMP_SHUT_EINT_MASK              0x0001  /* TEMP_SHUT_EINT */
+#define WM8994_TEMP_SHUT_EINT_SHIFT                  0  /* TEMP_SHUT_EINT */
+#define WM8994_TEMP_SHUT_EINT_WIDTH                  1  /* TEMP_SHUT_EINT */
+
+/*
+ * R1842 (0x732) - Interrupt Raw Status 2
+ */
+#define WM8994_TEMP_WARN_STS                    0x8000  /* TEMP_WARN_STS */
+#define WM8994_TEMP_WARN_STS_MASK               0x8000  /* TEMP_WARN_STS */
+#define WM8994_TEMP_WARN_STS_SHIFT                  15  /* TEMP_WARN_STS */
+#define WM8994_TEMP_WARN_STS_WIDTH                   1  /* TEMP_WARN_STS */
+#define WM8994_DCS_DONE_STS                     0x4000  /* DCS_DONE_STS */
+#define WM8994_DCS_DONE_STS_MASK                0x4000  /* DCS_DONE_STS */
+#define WM8994_DCS_DONE_STS_SHIFT                   14  /* DCS_DONE_STS */
+#define WM8994_DCS_DONE_STS_WIDTH                    1  /* DCS_DONE_STS */
+#define WM8994_WSEQ_DONE_STS                    0x2000  /* WSEQ_DONE_STS */
+#define WM8994_WSEQ_DONE_STS_MASK               0x2000  /* WSEQ_DONE_STS */
+#define WM8994_WSEQ_DONE_STS_SHIFT                  13  /* WSEQ_DONE_STS */
+#define WM8994_WSEQ_DONE_STS_WIDTH                   1  /* WSEQ_DONE_STS */
+#define WM8994_FIFOS_ERR_STS                    0x1000  /* FIFOS_ERR_STS */
+#define WM8994_FIFOS_ERR_STS_MASK               0x1000  /* FIFOS_ERR_STS */
+#define WM8994_FIFOS_ERR_STS_SHIFT                  12  /* FIFOS_ERR_STS */
+#define WM8994_FIFOS_ERR_STS_WIDTH                   1  /* FIFOS_ERR_STS */
+#define WM8994_AIF2DRC_SIG_DET_STS              0x0800  /* AIF2DRC_SIG_DET_STS */
+#define WM8994_AIF2DRC_SIG_DET_STS_MASK         0x0800  /* AIF2DRC_SIG_DET_STS */
+#define WM8994_AIF2DRC_SIG_DET_STS_SHIFT            11  /* AIF2DRC_SIG_DET_STS */
+#define WM8994_AIF2DRC_SIG_DET_STS_WIDTH             1  /* AIF2DRC_SIG_DET_STS */
+#define WM8994_AIF1DRC2_SIG_DET_STS             0x0400  /* AIF1DRC2_SIG_DET_STS */
+#define WM8994_AIF1DRC2_SIG_DET_STS_MASK        0x0400  /* AIF1DRC2_SIG_DET_STS */
+#define WM8994_AIF1DRC2_SIG_DET_STS_SHIFT           10  /* AIF1DRC2_SIG_DET_STS */
+#define WM8994_AIF1DRC2_SIG_DET_STS_WIDTH            1  /* AIF1DRC2_SIG_DET_STS */
+#define WM8994_AIF1DRC1_SIG_DET_STS             0x0200  /* AIF1DRC1_SIG_DET_STS */
+#define WM8994_AIF1DRC1_SIG_DET_STS_MASK        0x0200  /* AIF1DRC1_SIG_DET_STS */
+#define WM8994_AIF1DRC1_SIG_DET_STS_SHIFT            9  /* AIF1DRC1_SIG_DET_STS */
+#define WM8994_AIF1DRC1_SIG_DET_STS_WIDTH            1  /* AIF1DRC1_SIG_DET_STS */
+#define WM8994_SRC2_LOCK_STS                    0x0100  /* SRC2_LOCK_STS */
+#define WM8994_SRC2_LOCK_STS_MASK               0x0100  /* SRC2_LOCK_STS */
+#define WM8994_SRC2_LOCK_STS_SHIFT                   8  /* SRC2_LOCK_STS */
+#define WM8994_SRC2_LOCK_STS_WIDTH                   1  /* SRC2_LOCK_STS */
+#define WM8994_SRC1_LOCK_STS                    0x0080  /* SRC1_LOCK_STS */
+#define WM8994_SRC1_LOCK_STS_MASK               0x0080  /* SRC1_LOCK_STS */
+#define WM8994_SRC1_LOCK_STS_SHIFT                   7  /* SRC1_LOCK_STS */
+#define WM8994_SRC1_LOCK_STS_WIDTH                   1  /* SRC1_LOCK_STS */
+#define WM8994_FLL2_LOCK_STS                    0x0040  /* FLL2_LOCK_STS */
+#define WM8994_FLL2_LOCK_STS_MASK               0x0040  /* FLL2_LOCK_STS */
+#define WM8994_FLL2_LOCK_STS_SHIFT                   6  /* FLL2_LOCK_STS */
+#define WM8994_FLL2_LOCK_STS_WIDTH                   1  /* FLL2_LOCK_STS */
+#define WM8994_FLL1_LOCK_STS                    0x0020  /* FLL1_LOCK_STS */
+#define WM8994_FLL1_LOCK_STS_MASK               0x0020  /* FLL1_LOCK_STS */
+#define WM8994_FLL1_LOCK_STS_SHIFT                   5  /* FLL1_LOCK_STS */
+#define WM8994_FLL1_LOCK_STS_WIDTH                   1  /* FLL1_LOCK_STS */
+#define WM8994_MIC2_SHRT_STS                    0x0010  /* MIC2_SHRT_STS */
+#define WM8994_MIC2_SHRT_STS_MASK               0x0010  /* MIC2_SHRT_STS */
+#define WM8994_MIC2_SHRT_STS_SHIFT                   4  /* MIC2_SHRT_STS */
+#define WM8994_MIC2_SHRT_STS_WIDTH                   1  /* MIC2_SHRT_STS */
+#define WM8994_MIC2_DET_STS                     0x0008  /* MIC2_DET_STS */
+#define WM8994_MIC2_DET_STS_MASK                0x0008  /* MIC2_DET_STS */
+#define WM8994_MIC2_DET_STS_SHIFT                    3  /* MIC2_DET_STS */
+#define WM8994_MIC2_DET_STS_WIDTH                    1  /* MIC2_DET_STS */
+#define WM8994_MIC1_SHRT_STS                    0x0004  /* MIC1_SHRT_STS */
+#define WM8994_MIC1_SHRT_STS_MASK               0x0004  /* MIC1_SHRT_STS */
+#define WM8994_MIC1_SHRT_STS_SHIFT                   2  /* MIC1_SHRT_STS */
+#define WM8994_MIC1_SHRT_STS_WIDTH                   1  /* MIC1_SHRT_STS */
+#define WM8994_MIC1_DET_STS                     0x0002  /* MIC1_DET_STS */
+#define WM8994_MIC1_DET_STS_MASK                0x0002  /* MIC1_DET_STS */
+#define WM8994_MIC1_DET_STS_SHIFT                    1  /* MIC1_DET_STS */
+#define WM8994_MIC1_DET_STS_WIDTH                    1  /* MIC1_DET_STS */
+#define WM8994_TEMP_SHUT_STS                    0x0001  /* TEMP_SHUT_STS */
+#define WM8994_TEMP_SHUT_STS_MASK               0x0001  /* TEMP_SHUT_STS */
+#define WM8994_TEMP_SHUT_STS_SHIFT                   0  /* TEMP_SHUT_STS */
+#define WM8994_TEMP_SHUT_STS_WIDTH                   1  /* TEMP_SHUT_STS */
+
+/*
+ * R1848 (0x738) - Interrupt Status 1 Mask
+ */
+#define WM8994_IM_GP11_EINT                     0x0400  /* IM_GP11_EINT */
+#define WM8994_IM_GP11_EINT_MASK                0x0400  /* IM_GP11_EINT */
+#define WM8994_IM_GP11_EINT_SHIFT                   10  /* IM_GP11_EINT */
+#define WM8994_IM_GP11_EINT_WIDTH                    1  /* IM_GP11_EINT */
+#define WM8994_IM_GP10_EINT                     0x0200  /* IM_GP10_EINT */
+#define WM8994_IM_GP10_EINT_MASK                0x0200  /* IM_GP10_EINT */
+#define WM8994_IM_GP10_EINT_SHIFT                    9  /* IM_GP10_EINT */
+#define WM8994_IM_GP10_EINT_WIDTH                    1  /* IM_GP10_EINT */
+#define WM8994_IM_GP9_EINT                      0x0100  /* IM_GP9_EINT */
+#define WM8994_IM_GP9_EINT_MASK                 0x0100  /* IM_GP9_EINT */
+#define WM8994_IM_GP9_EINT_SHIFT                     8  /* IM_GP9_EINT */
+#define WM8994_IM_GP9_EINT_WIDTH                     1  /* IM_GP9_EINT */
+#define WM8994_IM_GP8_EINT                      0x0080  /* IM_GP8_EINT */
+#define WM8994_IM_GP8_EINT_MASK                 0x0080  /* IM_GP8_EINT */
+#define WM8994_IM_GP8_EINT_SHIFT                     7  /* IM_GP8_EINT */
+#define WM8994_IM_GP8_EINT_WIDTH                     1  /* IM_GP8_EINT */
+#define WM8994_IM_GP7_EINT                      0x0040  /* IM_GP7_EINT */
+#define WM8994_IM_GP7_EINT_MASK                 0x0040  /* IM_GP7_EINT */
+#define WM8994_IM_GP7_EINT_SHIFT                     6  /* IM_GP7_EINT */
+#define WM8994_IM_GP7_EINT_WIDTH                     1  /* IM_GP7_EINT */
+#define WM8994_IM_GP6_EINT                      0x0020  /* IM_GP6_EINT */
+#define WM8994_IM_GP6_EINT_MASK                 0x0020  /* IM_GP6_EINT */
+#define WM8994_IM_GP6_EINT_SHIFT                     5  /* IM_GP6_EINT */
+#define WM8994_IM_GP6_EINT_WIDTH                     1  /* IM_GP6_EINT */
+#define WM8994_IM_GP5_EINT                      0x0010  /* IM_GP5_EINT */
+#define WM8994_IM_GP5_EINT_MASK                 0x0010  /* IM_GP5_EINT */
+#define WM8994_IM_GP5_EINT_SHIFT                     4  /* IM_GP5_EINT */
+#define WM8994_IM_GP5_EINT_WIDTH                     1  /* IM_GP5_EINT */
+#define WM8994_IM_GP4_EINT                      0x0008  /* IM_GP4_EINT */
+#define WM8994_IM_GP4_EINT_MASK                 0x0008  /* IM_GP4_EINT */
+#define WM8994_IM_GP4_EINT_SHIFT                     3  /* IM_GP4_EINT */
+#define WM8994_IM_GP4_EINT_WIDTH                     1  /* IM_GP4_EINT */
+#define WM8994_IM_GP3_EINT                      0x0004  /* IM_GP3_EINT */
+#define WM8994_IM_GP3_EINT_MASK                 0x0004  /* IM_GP3_EINT */
+#define WM8994_IM_GP3_EINT_SHIFT                     2  /* IM_GP3_EINT */
+#define WM8994_IM_GP3_EINT_WIDTH                     1  /* IM_GP3_EINT */
+#define WM8994_IM_GP2_EINT                      0x0002  /* IM_GP2_EINT */
+#define WM8994_IM_GP2_EINT_MASK                 0x0002  /* IM_GP2_EINT */
+#define WM8994_IM_GP2_EINT_SHIFT                     1  /* IM_GP2_EINT */
+#define WM8994_IM_GP2_EINT_WIDTH                     1  /* IM_GP2_EINT */
+#define WM8994_IM_GP1_EINT                      0x0001  /* IM_GP1_EINT */
+#define WM8994_IM_GP1_EINT_MASK                 0x0001  /* IM_GP1_EINT */
+#define WM8994_IM_GP1_EINT_SHIFT                     0  /* IM_GP1_EINT */
+#define WM8994_IM_GP1_EINT_WIDTH                     1  /* IM_GP1_EINT */
+
+/*
+ * R1849 (0x739) - Interrupt Status 2 Mask
+ */
+#define WM8994_IM_TEMP_WARN_EINT                0x8000  /* IM_TEMP_WARN_EINT */
+#define WM8994_IM_TEMP_WARN_EINT_MASK           0x8000  /* IM_TEMP_WARN_EINT */
+#define WM8994_IM_TEMP_WARN_EINT_SHIFT              15  /* IM_TEMP_WARN_EINT */
+#define WM8994_IM_TEMP_WARN_EINT_WIDTH               1  /* IM_TEMP_WARN_EINT */
+#define WM8994_IM_DCS_DONE_EINT                 0x4000  /* IM_DCS_DONE_EINT */
+#define WM8994_IM_DCS_DONE_EINT_MASK            0x4000  /* IM_DCS_DONE_EINT */
+#define WM8994_IM_DCS_DONE_EINT_SHIFT               14  /* IM_DCS_DONE_EINT */
+#define WM8994_IM_DCS_DONE_EINT_WIDTH                1  /* IM_DCS_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT                0x2000  /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT_MASK           0x2000  /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT_SHIFT              13  /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT_WIDTH               1  /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT                0x1000  /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT_MASK           0x1000  /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT_SHIFT              12  /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT_WIDTH               1  /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_AIF2DRC_SIG_DET_EINT          0x0800  /* IM_AIF2DRC_SIG_DET_EINT */
+#define WM8994_IM_AIF2DRC_SIG_DET_EINT_MASK     0x0800  /* IM_AIF2DRC_SIG_DET_EINT */
+#define WM8994_IM_AIF2DRC_SIG_DET_EINT_SHIFT        11  /* IM_AIF2DRC_SIG_DET_EINT */
+#define WM8994_IM_AIF2DRC_SIG_DET_EINT_WIDTH         1  /* IM_AIF2DRC_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC2_SIG_DET_EINT         0x0400  /* IM_AIF1DRC2_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC2_SIG_DET_EINT_MASK    0x0400  /* IM_AIF1DRC2_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC2_SIG_DET_EINT_SHIFT       10  /* IM_AIF1DRC2_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC2_SIG_DET_EINT_WIDTH        1  /* IM_AIF1DRC2_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC1_SIG_DET_EINT         0x0200  /* IM_AIF1DRC1_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC1_SIG_DET_EINT_MASK    0x0200  /* IM_AIF1DRC1_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC1_SIG_DET_EINT_SHIFT        9  /* IM_AIF1DRC1_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC1_SIG_DET_EINT_WIDTH        1  /* IM_AIF1DRC1_SIG_DET_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT                0x0100  /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT_MASK           0x0100  /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT_SHIFT               8  /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT_WIDTH               1  /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT                0x0080  /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT_MASK           0x0080  /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT_SHIFT               7  /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT_WIDTH               1  /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT                0x0040  /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT_MASK           0x0040  /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT_SHIFT               6  /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT_WIDTH               1  /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT                0x0020  /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT_MASK           0x0020  /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT_SHIFT               5  /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT_WIDTH               1  /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT                0x0010  /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT_MASK           0x0010  /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT_SHIFT               4  /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT_WIDTH               1  /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_DET_EINT                 0x0008  /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC2_DET_EINT_MASK            0x0008  /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC2_DET_EINT_SHIFT                3  /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC2_DET_EINT_WIDTH                1  /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT                0x0004  /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT_MASK           0x0004  /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT_SHIFT               2  /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT_WIDTH               1  /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_DET_EINT                 0x0002  /* IM_MIC1_DET_EINT */
+#define WM8994_IM_MIC1_DET_EINT_MASK            0x0002  /* IM_MIC1_DET_EINT */
+#define WM8994_IM_MIC1_DET_EINT_SHIFT                1  /* IM_MIC1_DET_EINT */
+#define WM8994_IM_MIC1_DET_EINT_WIDTH                1  /* IM_MIC1_DET_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT                0x0001  /* IM_TEMP_SHUT_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT_MASK           0x0001  /* IM_TEMP_SHUT_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT_SHIFT               0  /* IM_TEMP_SHUT_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT_WIDTH               1  /* IM_TEMP_SHUT_EINT */
+
+/*
+ * R1856 (0x740) - Interrupt Control
+ */
+#define WM8994_IM_IRQ                           0x0001  /* IM_IRQ */
+#define WM8994_IM_IRQ_MASK                      0x0001  /* IM_IRQ */
+#define WM8994_IM_IRQ_SHIFT                          0  /* IM_IRQ */
+#define WM8994_IM_IRQ_WIDTH                          1  /* IM_IRQ */
+
+/*
+ * R1864 (0x748) - IRQ Debounce
+ */
+#define WM8994_TEMP_WARN_DB                     0x0020  /* TEMP_WARN_DB */
+#define WM8994_TEMP_WARN_DB_MASK                0x0020  /* TEMP_WARN_DB */
+#define WM8994_TEMP_WARN_DB_SHIFT                    5  /* TEMP_WARN_DB */
+#define WM8994_TEMP_WARN_DB_WIDTH                    1  /* TEMP_WARN_DB */
+#define WM8994_MIC2_SHRT_DB                     0x0010  /* MIC2_SHRT_DB */
+#define WM8994_MIC2_SHRT_DB_MASK                0x0010  /* MIC2_SHRT_DB */
+#define WM8994_MIC2_SHRT_DB_SHIFT                    4  /* MIC2_SHRT_DB */
+#define WM8994_MIC2_SHRT_DB_WIDTH                    1  /* MIC2_SHRT_DB */
+#define WM8994_MIC2_DET_DB                      0x0008  /* MIC2_DET_DB */
+#define WM8994_MIC2_DET_DB_MASK                 0x0008  /* MIC2_DET_DB */
+#define WM8994_MIC2_DET_DB_SHIFT                     3  /* MIC2_DET_DB */
+#define WM8994_MIC2_DET_DB_WIDTH                     1  /* MIC2_DET_DB */
+#define WM8994_MIC1_SHRT_DB                     0x0004  /* MIC1_SHRT_DB */
+#define WM8994_MIC1_SHRT_DB_MASK                0x0004  /* MIC1_SHRT_DB */
+#define WM8994_MIC1_SHRT_DB_SHIFT                    2  /* MIC1_SHRT_DB */
+#define WM8994_MIC1_SHRT_DB_WIDTH                    1  /* MIC1_SHRT_DB */
+#define WM8994_MIC1_DET_DB                      0x0002  /* MIC1_DET_DB */
+#define WM8994_MIC1_DET_DB_MASK                 0x0002  /* MIC1_DET_DB */
+#define WM8994_MIC1_DET_DB_SHIFT                     1  /* MIC1_DET_DB */
+#define WM8994_MIC1_DET_DB_WIDTH                     1  /* MIC1_DET_DB */
+#define WM8994_TEMP_SHUT_DB                     0x0001  /* TEMP_SHUT_DB */
+#define WM8994_TEMP_SHUT_DB_MASK                0x0001  /* TEMP_SHUT_DB */
+#define WM8994_TEMP_SHUT_DB_SHIFT                    0  /* TEMP_SHUT_DB */
+#define WM8994_TEMP_SHUT_DB_WIDTH                    1  /* TEMP_SHUT_DB */
+
+#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 8b2fa85..e70f21b 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -12,6 +12,7 @@
 #include <linux/prio_tree.h>
 #include <linux/debug_locks.h>
 #include <linux/mm_types.h>
+#include <linux/range.h>
 
 struct mempolicy;
 struct anon_vma;
@@ -869,6 +870,114 @@
  */
 int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
 			  struct page **pages);
+/*
+ * per-process(per-mm_struct) statistics.
+ */
+#if defined(SPLIT_RSS_COUNTING)
+/*
+ * The mm counters are not protected by its page_table_lock,
+ * so must be incremented atomically.
+ */
+static inline void set_mm_counter(struct mm_struct *mm, int member, long value)
+{
+	atomic_long_set(&mm->rss_stat.count[member], value);
+}
+
+unsigned long get_mm_counter(struct mm_struct *mm, int member);
+
+static inline void add_mm_counter(struct mm_struct *mm, int member, long value)
+{
+	atomic_long_add(value, &mm->rss_stat.count[member]);
+}
+
+static inline void inc_mm_counter(struct mm_struct *mm, int member)
+{
+	atomic_long_inc(&mm->rss_stat.count[member]);
+}
+
+static inline void dec_mm_counter(struct mm_struct *mm, int member)
+{
+	atomic_long_dec(&mm->rss_stat.count[member]);
+}
+
+#else  /* !USE_SPLIT_PTLOCKS */
+/*
+ * The mm counters are protected by its page_table_lock,
+ * so can be incremented directly.
+ */
+static inline void set_mm_counter(struct mm_struct *mm, int member, long value)
+{
+	mm->rss_stat.count[member] = value;
+}
+
+static inline unsigned long get_mm_counter(struct mm_struct *mm, int member)
+{
+	return mm->rss_stat.count[member];
+}
+
+static inline void add_mm_counter(struct mm_struct *mm, int member, long value)
+{
+	mm->rss_stat.count[member] += value;
+}
+
+static inline void inc_mm_counter(struct mm_struct *mm, int member)
+{
+	mm->rss_stat.count[member]++;
+}
+
+static inline void dec_mm_counter(struct mm_struct *mm, int member)
+{
+	mm->rss_stat.count[member]--;
+}
+
+#endif /* !USE_SPLIT_PTLOCKS */
+
+static inline unsigned long get_mm_rss(struct mm_struct *mm)
+{
+	return get_mm_counter(mm, MM_FILEPAGES) +
+		get_mm_counter(mm, MM_ANONPAGES);
+}
+
+static inline unsigned long get_mm_hiwater_rss(struct mm_struct *mm)
+{
+	return max(mm->hiwater_rss, get_mm_rss(mm));
+}
+
+static inline unsigned long get_mm_hiwater_vm(struct mm_struct *mm)
+{
+	return max(mm->hiwater_vm, mm->total_vm);
+}
+
+static inline void update_hiwater_rss(struct mm_struct *mm)
+{
+	unsigned long _rss = get_mm_rss(mm);
+
+	if ((mm)->hiwater_rss < _rss)
+		(mm)->hiwater_rss = _rss;
+}
+
+static inline void update_hiwater_vm(struct mm_struct *mm)
+{
+	if (mm->hiwater_vm < mm->total_vm)
+		mm->hiwater_vm = mm->total_vm;
+}
+
+static inline void setmax_mm_hiwater_rss(unsigned long *maxrss,
+					 struct mm_struct *mm)
+{
+	unsigned long hiwater_rss = get_mm_hiwater_rss(mm);
+
+	if (*maxrss < hiwater_rss)
+		*maxrss = hiwater_rss;
+}
+
+#if defined(SPLIT_RSS_COUNTING)
+void sync_mm_rss(struct task_struct *task, struct mm_struct *mm);
+#else
+static inline void sync_mm_rss(struct task_struct *task, struct mm_struct *mm)
+{
+}
+#endif
 
 /*
  * A callback you can register to apply pressure to ageable caches.
@@ -1049,6 +1158,10 @@
 extern unsigned long find_min_pfn_with_active_regions(void);
 extern void free_bootmem_with_active_regions(int nid,
 						unsigned long max_low_pfn);
+int add_from_early_node_map(struct range *range, int az,
+				   int nr_range, int nid);
+void *__alloc_memory_core_early(int nodeid, u64 size, u64 align,
+				 u64 goal, u64 limit);
 typedef int (*work_fn_t)(unsigned long, unsigned long, void *);
 extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data);
 extern void sparse_memory_present_with_active_regions(int nid);
@@ -1081,11 +1194,7 @@
 extern void si_meminfo_node(struct sysinfo *val, int nid);
 extern int after_bootmem;
 
-#ifdef CONFIG_NUMA
 extern void setup_per_cpu_pageset(void);
-#else
-static inline void setup_per_cpu_pageset(void) {}
-#endif
 
 extern void zone_pcp_update(struct zone *zone);
 
@@ -1113,7 +1222,7 @@
 
 /* mmap.c */
 extern int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin);
-extern void vma_adjust(struct vm_area_struct *vma, unsigned long start,
+extern int vma_adjust(struct vm_area_struct *vma, unsigned long start,
 	unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert);
 extern struct vm_area_struct *vma_merge(struct mm_struct *,
 	struct vm_area_struct *prev, unsigned long addr, unsigned long end,
@@ -1321,12 +1430,19 @@
 const char * arch_vma_name(struct vm_area_struct *vma);
 void print_vma_addr(char *prefix, unsigned long rip);
 
+void sparse_mem_maps_populate_node(struct page **map_map,
+				   unsigned long pnum_begin,
+				   unsigned long pnum_end,
+				   unsigned long map_count,
+				   int nodeid);
+
 struct page *sparse_mem_map_populate(unsigned long pnum, int nid);
 pgd_t *vmemmap_pgd_populate(unsigned long addr, int node);
 pud_t *vmemmap_pud_populate(pgd_t *pgd, unsigned long addr, int node);
 pmd_t *vmemmap_pmd_populate(pud_t *pud, unsigned long addr, int node);
 pte_t *vmemmap_pte_populate(pmd_t *pmd, unsigned long addr, int node);
 void *vmemmap_alloc_block(unsigned long size, int node);
+void *vmemmap_alloc_block_buf(unsigned long size, int node);
 void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
 int vmemmap_populate_basepages(struct page *start_page,
 						unsigned long pages, int node);
@@ -1349,5 +1465,7 @@
 extern atomic_long_t mce_bad_pages;
 extern int soft_offline_page(struct page *page, int flags);
 
+extern void dump_page(struct page *page);
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 36f9627..b8bb9a6 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -24,12 +24,6 @@
 
 #define USE_SPLIT_PTLOCKS	(NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS)
 
-#if USE_SPLIT_PTLOCKS
-typedef atomic_long_t mm_counter_t;
-#else  /* !USE_SPLIT_PTLOCKS */
-typedef unsigned long mm_counter_t;
-#endif /* !USE_SPLIT_PTLOCKS */
-
 /*
  * Each physical page in the system has a struct page associated with
  * it to keep track of whatever it is we are using the page for at the
@@ -169,7 +163,8 @@
 	 * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack
 	 * or brk vma (with NULL file) can only be in an anon_vma list.
 	 */
-	struct list_head anon_vma_node;	/* Serialized by anon_vma->lock */
+	struct list_head anon_vma_chain; /* Serialized by mmap_sem &
+					  * page_table_lock */
 	struct anon_vma *anon_vma;	/* Serialized by page_table_lock */
 
 	/* Function pointers to deal with this struct. */
@@ -201,6 +196,29 @@
 	struct completion startup;
 };
 
+enum {
+	MM_FILEPAGES,
+	MM_ANONPAGES,
+	MM_SWAPENTS,
+	NR_MM_COUNTERS
+};
+
+#if USE_SPLIT_PTLOCKS && defined(CONFIG_MMU)
+#define SPLIT_RSS_COUNTING
+struct mm_rss_stat {
+	atomic_long_t count[NR_MM_COUNTERS];
+};
+/* per-thread cached information, */
+struct task_rss_stat {
+	int events;	/* for synchronization threshold */
+	int count[NR_MM_COUNTERS];
+};
+#else  /* !USE_SPLIT_PTLOCKS */
+struct mm_rss_stat {
+	unsigned long count[NR_MM_COUNTERS];
+};
+#endif /* !USE_SPLIT_PTLOCKS */
+
 struct mm_struct {
 	struct vm_area_struct * mmap;		/* list of VMAs */
 	struct rb_root mm_rb;
@@ -227,11 +245,6 @@
 						 * by mmlist_lock
 						 */
 
-	/* Special counters, in some configurations protected by the
-	 * page_table_lock, in other configurations by being atomic.
-	 */
-	mm_counter_t _file_rss;
-	mm_counter_t _anon_rss;
 
 	unsigned long hiwater_rss;	/* High-watermark of RSS usage */
 	unsigned long hiwater_vm;	/* High-water virtual memory usage */
@@ -244,6 +257,12 @@
 
 	unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
 
+	/*
+	 * Special counters, in some configurations protected by the
+	 * page_table_lock, in other configurations by being atomic.
+	 */
+	struct mm_rss_stat rss_stat;
+
 	struct linux_binfmt *binfmt;
 
 	cpumask_t cpu_vm_mask;
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 2ee22e8..d02d2c6 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -99,6 +99,8 @@
 #define MMC_STATE_BLOCKADDR	(1<<3)		/* card uses block-addressing */
 	unsigned int		quirks; 	/* card quirks */
 #define MMC_QUIRK_LENIENT_FN0	(1<<0)		/* allow SDIO FN0 writes outside of the VS CCCR range */
+#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1)	/* use func->cur_blksize */
+						/* for byte mode */
 
 	u32			raw_cid[4];	/* raw card CID */
 	u32			raw_csd[4];	/* raw card CSD */
@@ -139,6 +141,11 @@
 	return c->quirks & MMC_QUIRK_LENIENT_FN0;
 }
 
+static inline int mmc_blksz_for_byte_mode(const struct mmc_card *c)
+{
+	return c->quirks & MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+}
+
 #define mmc_card_name(c)	((c)->cid.prod_name)
 #define mmc_card_id(c)		(dev_name(&(c)->dev))
 
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index eaf3636..43eaf5c 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 
 #include <linux/mmc/core.h>
+#include <linux/mmc/pm.h>
 
 struct mmc_ios {
 	unsigned int	clock;			/* clock rate */
@@ -152,6 +153,8 @@
 #define MMC_CAP_NONREMOVABLE	(1 << 8)	/* Nonremovable e.g. eMMC */
 #define MMC_CAP_WAIT_WHILE_BUSY	(1 << 9)	/* Waits while card is busy */
 
+	mmc_pm_flag_t		pm_caps;	/* supported pm features */
+
 	/* host specific block data */
 	unsigned int		max_seg_size;	/* see blk_queue_max_segment_size */
 	unsigned short		max_hw_segs;	/* see blk_queue_max_hw_segments */
@@ -197,6 +200,8 @@
 	struct task_struct	*sdio_irq_thread;
 	atomic_t		sdio_irq_thread_abort;
 
+	mmc_pm_flag_t		pm_flags;	/* requested pm features */
+
 #ifdef CONFIG_LEDS_TRIGGERS
 	struct led_trigger	*led;		/* activity led */
 #endif
diff --git a/include/linux/mmc/pm.h b/include/linux/mmc/pm.h
new file mode 100644
index 0000000..d37aac4
--- /dev/null
+++ b/include/linux/mmc/pm.h
@@ -0,0 +1,30 @@
+/*
+ * linux/include/linux/mmc/pm.h
+ *
+ * Author:	Nicolas Pitre
+ * Copyright:	(C) 2009 Marvell Technology Group 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.
+ */
+
+#ifndef LINUX_MMC_PM_H
+#define LINUX_MMC_PM_H
+
+/*
+ * These flags are used to describe power management features that
+ * some cards (typically SDIO cards) might wish to benefit from when
+ * the host system is being suspended.  There are several layers of
+ * abstractions involved, from the host controller driver, to the MMC core
+ * code, to the SDIO core code, to finally get to the actual SDIO function
+ * driver.  This file is therefore used for common definitions shared across
+ * all those layers.
+ */
+
+typedef unsigned int mmc_pm_flag_t;
+
+#define MMC_PM_KEEP_POWER	(1 << 0)	/* preserve card power during suspend */
+#define MMC_PM_WAKE_SDIO_IRQ	(1 << 1)	/* wake up host system on SDIO IRQ assertion */
+
+#endif
diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h
index 47ba464..0ebaef5 100644
--- a/include/linux/mmc/sdio.h
+++ b/include/linux/mmc/sdio.h
@@ -95,6 +95,8 @@
 #define  SDIO_BUS_WIDTH_1BIT	0x00
 #define  SDIO_BUS_WIDTH_4BIT	0x02
 
+#define  SDIO_BUS_ASYNC_INT	0x20
+
 #define  SDIO_BUS_CD_DISABLE     0x80	/* disable pull-up on DAT3 (pin 1) */
 
 #define SDIO_CCCR_CAPS		0x08
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
index ac3ab68..c6c0cce 100644
--- a/include/linux/mmc/sdio_func.h
+++ b/include/linux/mmc/sdio_func.h
@@ -15,6 +15,8 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 
+#include <linux/mmc/pm.h>
+
 struct mmc_card;
 struct sdio_func;
 
@@ -153,5 +155,8 @@
 extern void sdio_f0_writeb(struct sdio_func *func, unsigned char b,
 	unsigned int addr, int *err_ret);
 
+extern mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func);
+extern int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags);
+
 #endif
 
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 30fe668..cf9e458 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -184,13 +184,7 @@
 	s8 stat_threshold;
 	s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS];
 #endif
-} ____cacheline_aligned_in_smp;
-
-#ifdef CONFIG_NUMA
-#define zone_pcp(__z, __cpu) ((__z)->pageset[(__cpu)])
-#else
-#define zone_pcp(__z, __cpu) (&(__z)->pageset[(__cpu)])
-#endif
+};
 
 #endif /* !__GENERATING_BOUNDS.H */
 
@@ -306,14 +300,13 @@
 	 */
 	unsigned long		min_unmapped_pages;
 	unsigned long		min_slab_pages;
-	struct per_cpu_pageset	*pageset[NR_CPUS];
-#else
-	struct per_cpu_pageset	pageset[NR_CPUS];
 #endif
+	struct per_cpu_pageset __percpu *pageset;
 	/*
 	 * free areas of different sizes
 	 */
 	spinlock_t		lock;
+	int                     all_unreclaimable; /* All pages pinned */
 #ifdef CONFIG_MEMORY_HOTPLUG
 	/* see spanned/present_pages for more description */
 	seqlock_t		span_seqlock;
@@ -349,7 +342,7 @@
 	 * prev_priority holds the scanning priority for this zone.  It is
 	 * defined as the scanning priority at which we achieved our reclaim
 	 * target at the previous try_to_free_pages() or balance_pgdat()
-	 * invokation.
+	 * invocation.
 	 *
 	 * We use prev_priority as a measure of how much stress page reclaim is
 	 * under - it drives the swappiness decision: whether to unmap mapped
@@ -425,7 +418,6 @@
 } ____cacheline_internodealigned_in_smp;
 
 typedef enum {
-	ZONE_ALL_UNRECLAIMABLE,		/* all pages pinned */
 	ZONE_RECLAIM_LOCKED,		/* prevents concurrent reclaim */
 	ZONE_OOM_LOCKED,		/* zone is in OOM killer zonelist */
 } zone_flags_t;
@@ -445,11 +437,6 @@
 	clear_bit(flag, &zone->flags);
 }
 
-static inline int zone_is_all_unreclaimable(const struct zone *zone)
-{
-	return test_bit(ZONE_ALL_UNRECLAIMABLE, &zone->flags);
-}
-
 static inline int zone_is_reclaim_locked(const struct zone *zone)
 {
 	return test_bit(ZONE_RECLAIM_LOCKED, &zone->flags);
@@ -620,7 +607,9 @@
 	struct page_cgroup *node_page_cgroup;
 #endif
 #endif
+#ifndef CONFIG_NO_BOOTMEM
 	struct bootmem_data *bdata;
+#endif
 #ifdef CONFIG_MEMORY_HOTPLUG
 	/*
 	 * Must be held any time you expect node_start_pfn, node_present_pages
diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
index d74785c..0b89efc 100644
--- a/include/linux/mnt_namespace.h
+++ b/include/linux/mnt_namespace.h
@@ -35,6 +35,7 @@
 extern const struct seq_operations mounts_op;
 extern const struct seq_operations mountinfo_op;
 extern const struct seq_operations mountstats_op;
+extern int mnt_had_events(struct proc_mounts *);
 
 #endif
 #endif
diff --git a/include/linux/module.h b/include/linux/module.h
index 6cb1a3c..5e869ff 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -17,7 +17,7 @@
 #include <linux/moduleparam.h>
 #include <linux/tracepoint.h>
 
-#include <asm/local.h>
+#include <linux/percpu.h>
 #include <asm/module.h>
 
 #include <trace/events/module.h>
@@ -175,6 +175,7 @@
 
 #ifdef CONFIG_MODULES
 
+extern int modules_disabled; /* for sysctl */
 /* Get/put a kernel symbol (calls must be symmetric) */
 void *__symbol_get(const char *symbol);
 void *__symbol_get_gpl(const char *symbol);
@@ -363,11 +364,9 @@
 	/* Destruction function. */
 	void (*exit)(void);
 
-#ifdef CONFIG_SMP
-	char *refptr;
-#else
-	local_t ref;
-#endif
+	struct module_ref {
+		int count;
+	} __percpu *refptr;
 #endif
 
 #ifdef CONFIG_CONSTRUCTORS
@@ -454,25 +453,16 @@
 #define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x)
 void symbol_put_addr(void *addr);
 
-static inline local_t *__module_ref_addr(struct module *mod, int cpu)
-{
-#ifdef CONFIG_SMP
-	return (local_t *) (mod->refptr + per_cpu_offset(cpu));
-#else
-	return &mod->ref;
-#endif
-}
-
 /* Sometimes we know we already have a refcount, and it's easier not
    to handle the error case (which only happens with rmmod --wait). */
 static inline void __module_get(struct module *module)
 {
 	if (module) {
-		unsigned int cpu = get_cpu();
-		local_inc(__module_ref_addr(module, cpu));
+		preempt_disable();
+		__this_cpu_inc(module->refptr->count);
 		trace_module_get(module, _THIS_IP_,
-				 local_read(__module_ref_addr(module, cpu)));
-		put_cpu();
+				 __this_cpu_read(module->refptr->count));
+		preempt_enable();
 	}
 }
 
@@ -481,15 +471,17 @@
 	int ret = 1;
 
 	if (module) {
-		unsigned int cpu = get_cpu();
+		preempt_disable();
+
 		if (likely(module_is_live(module))) {
-			local_inc(__module_ref_addr(module, cpu));
+			__this_cpu_inc(module->refptr->count);
 			trace_module_get(module, _THIS_IP_,
-				local_read(__module_ref_addr(module, cpu)));
+				__this_cpu_read(module->refptr->count));
 		}
 		else
 			ret = 0;
-		put_cpu();
+
+		preempt_enable();
 	}
 	return ret;
 }
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 5d52753..4bd0547 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -34,7 +34,18 @@
 
 #define MNT_SHARED	0x1000	/* if the vfsmount is a shared mount */
 #define MNT_UNBINDABLE	0x2000	/* if the vfsmount is a unbindable mount */
-#define MNT_PNODE_MASK	0x3000	/* propagation flag mask */
+/*
+ * MNT_SHARED_MASK is the set of flags that should be cleared when a
+ * mount becomes shared.  Currently, this is only the flag that says a
+ * mount cannot be bind mounted, since this is how we create a mount
+ * that shares events with another mount.  If you add a new MNT_*
+ * flag, consider how it interacts with shared mounts.
+ */
+#define MNT_SHARED_MASK	(MNT_UNBINDABLE)
+#define MNT_PROPAGATION_MASK	(MNT_SHARED | MNT_UNBINDABLE)
+
+
+#define MNT_INTERNAL	0x4000
 
 struct vfsmount {
 	struct list_head mnt_hash;
@@ -66,7 +77,7 @@
 	int mnt_pinned;
 	int mnt_ghosts;
 #ifdef CONFIG_SMP
-	int *mnt_writers;
+	int __percpu *mnt_writers;
 #else
 	int mnt_writers;
 #endif
@@ -123,7 +134,6 @@
 
 extern void mark_mounts_for_expiry(struct list_head *mounts);
 
-extern spinlock_t vfsmount_lock;
 extern dev_t name_to_dev_t(char *name);
 
 #endif /* _LINUX_MOUNT_H */
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index ce38f1c..34066e6 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -15,6 +15,7 @@
 #define MSDOS_DPB_BITS	4		/* log2(MSDOS_DPB) */
 #define MSDOS_DPS	(SECTOR_SIZE / sizeof(struct msdos_dir_entry))
 #define MSDOS_DPS_BITS	4		/* log2(MSDOS_DPS) */
+#define MSDOS_LONGNAME	256		/* maximum name length */
 #define CF_LE_W(v)	le16_to_cpu(v)
 #define CF_LE_L(v)	le32_to_cpu(v)
 #define CT_LE_W(v)	cpu_to_le16(v)
@@ -47,8 +48,8 @@
 #define DELETED_FLAG	0xe5	/* marks file as deleted when in name[0] */
 #define IS_FREE(n)	(!*(n) || *(n) == DELETED_FLAG)
 
+#define FAT_LFN_LEN	255	/* maximum long name length */
 #define MSDOS_NAME	11	/* maximum name length */
-#define MSDOS_LONGNAME	256	/* maximum name length */
 #define MSDOS_SLOTS	21	/* max # of slots for short and long names */
 #define MSDOS_DOT	".          "	/* ".", padded to MSDOS_NAME chars */
 #define MSDOS_DOTDOT	"..         "	/* "..", padded to MSDOS_NAME chars */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index d09db1b..1a0b85a 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -33,9 +33,6 @@
 #define FLUSH_STABLE		4	/* commit to stable storage */
 #define FLUSH_LOWPRI		8	/* low priority background flush */
 #define FLUSH_HIGHPRI		16	/* high priority memory reclaim flush */
-#define FLUSH_NOCOMMIT		32	/* Don't send the NFSv3/v4 COMMIT */
-#define FLUSH_INVALIDATE	64	/* Invalidate the page cache */
-#define FLUSH_NOWRITEPAGE	128	/* Don't call writepage() */
 
 #ifdef __KERNEL__
 
@@ -166,6 +163,7 @@
 	struct radix_tree_root	nfs_page_tree;
 
 	unsigned long		npages;
+	unsigned long		ncommit;
 
 	/* Open contexts for shared mmap writes */
 	struct list_head	open_files;
@@ -349,7 +347,6 @@
 extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
 extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
-extern int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping);
 extern int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
@@ -477,21 +474,12 @@
  * Try to write back everything synchronously (but check the
  * return value!)
  */
-extern long nfs_sync_mapping_wait(struct address_space *, struct writeback_control *, int);
 extern int nfs_wb_all(struct inode *inode);
-extern int nfs_wb_nocommit(struct inode *inode);
 extern int nfs_wb_page(struct inode *inode, struct page* page);
 extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-extern int  nfs_commit_inode(struct inode *, int);
 extern struct nfs_write_data *nfs_commitdata_alloc(void);
 extern void nfs_commit_free(struct nfs_write_data *wdata);
-#else
-static inline int
-nfs_commit_inode(struct inode *inode, int how)
-{
-	return 0;
-}
 #endif
 
 static inline int
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 34fc6be..717a5e5 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -105,7 +105,7 @@
 	struct rpc_clnt *	client;		/* RPC client handle */
 	struct rpc_clnt *	client_acl;	/* ACL RPC client handle */
 	struct nlm_host		*nlm_host;	/* NLM client handle */
-	struct nfs_iostats *	io_stats;	/* I/O statistics */
+	struct nfs_iostats __percpu *io_stats;	/* I/O statistics */
 	struct backing_dev_info	backing_dev_info;
 	atomic_long_t		writeback;	/* number of writeback pages */
 	int			flags;		/* various flags */
@@ -193,6 +193,8 @@
 	int		max_slots;		/* # slots in table */
 	int		highest_used_slotid;	/* sent to server on each SEQ.
 						 * op for dynamic resizing */
+	int		target_max_slots;	/* Set by CB_RECALL_SLOT as
+						 * the new max_slots */
 };
 
 static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp)
diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h
index 3fe02cf..640702e 100644
--- a/include/linux/nilfs2_fs.h
+++ b/include/linux/nilfs2_fs.h
@@ -153,6 +153,7 @@
 						   semantics also for data */
 #define NILFS_MOUNT_NORECOVERY		0x4000  /* Disable write access during
 						   mount-time recovery */
+#define NILFS_MOUNT_DISCARD		0x8000  /* Issue DISCARD requests */
 
 
 /**
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 454997c..dba35e4 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -69,8 +69,6 @@
  * int node_online(node)		Is some node online?
  * int node_possible(node)		Is some node possible?
  *
- * int any_online_node(mask)		First online node in mask
- *
  * node_set_online(node)		set bit 'node' in node_online_map
  * node_set_offline(node)		clear bit 'node' in node_online_map
  *
@@ -467,15 +465,6 @@
 #define node_online_map 	node_states[N_ONLINE]
 #define node_possible_map 	node_states[N_POSSIBLE]
 
-#define any_online_node(mask)			\
-({						\
-	int node;				\
-	for_each_node_mask(node, (mask))	\
-		if (node_online(node))		\
-			break;			\
-	node;					\
-})
-
 #define num_online_nodes()	num_node_state(N_ONLINE)
 #define num_possible_nodes()	num_node_state(N_POSSIBLE)
 #define node_online(node)	node_state((node), N_ONLINE)
@@ -494,7 +483,7 @@
 			type *name = kmalloc(sizeof(*name), gfp_flags)
 #define NODEMASK_FREE(m)			kfree(m)
 #else
-#define NODEMASK_ALLOC(type, name, gfp_flags)	type _name, *name = &_name
+#define NODEMASK_ALLOC(type, name, gfp_flags)	type _##name, *name = &_##name
 #define NODEMASK_FREE(m)			do {} while (0)
 #endif
 
diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h
index b0e4eb1..30b0813 100644
--- a/include/linux/page_cgroup.h
+++ b/include/linux/page_cgroup.h
@@ -118,6 +118,8 @@
 #include <linux/swap.h>
 
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
+extern unsigned short swap_cgroup_cmpxchg(swp_entry_t ent,
+					unsigned short old, unsigned short new);
 extern unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id);
 extern unsigned short lookup_swap_cgroup(swp_entry_t ent);
 extern int swap_cgroup_swapon(int type, unsigned long max_pages);
diff --git a/include/linux/pci-dma.h b/include/linux/pci-dma.h
new file mode 100644
index 0000000..549a041
--- /dev/null
+++ b/include/linux/pci-dma.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_PCI_DMA_H
+#define _LINUX_PCI_DMA_H
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) DEFINE_DMA_UNMAP_ADDR(ADDR_NAME);
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)   DEFINE_DMA_UNMAP_LEN(LEN_NAME);
+#define pci_unmap_addr             dma_unmap_addr
+#define pci_unmap_addr_set         dma_unmap_addr_set
+#define pci_unmap_len              dma_unmap_len
+#define pci_unmap_len_set          dma_unmap_len_set
+
+#endif
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ec95ebe..a788fa1 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -678,6 +678,8 @@
 int pci_find_capability(struct pci_dev *dev, int cap);
 int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
 int pci_find_ext_capability(struct pci_dev *dev, int cap);
+int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
+				int cap);
 int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
 int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
 struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
@@ -767,8 +769,6 @@
 void pci_clear_mwi(struct pci_dev *dev);
 void pci_intx(struct pci_dev *dev, int enable);
 void pci_msi_off(struct pci_dev *dev);
-int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
-int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
 int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
 int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
 int pcix_get_max_mmrbc(struct pci_dev *dev);
@@ -902,6 +902,7 @@
 		      unsigned int command_bits, bool change_bridge);
 /* kmem_cache style wrapper around pci_alloc_consistent() */
 
+#include <linux/pci-dma.h>
 #include <linux/dmapool.h>
 
 #define	pci_pool dma_pool
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 0be8243..9f688d2 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -770,7 +770,6 @@
 #define PCI_VENDOR_ID_TI		0x104c
 #define PCI_DEVICE_ID_TI_TVP4020	0x3d07
 #define PCI_DEVICE_ID_TI_4450		0x8011
-#define PCI_DEVICE_ID_TI_TSB43AB22	0x8023
 #define PCI_DEVICE_ID_TI_XX21_XX11	0x8031
 #define PCI_DEVICE_ID_TI_XX21_XX11_FM	0x8033
 #define PCI_DEVICE_ID_TI_XX21_XX11_SD	0x8034
@@ -2333,6 +2332,8 @@
 #define PCI_VENDOR_ID_KORENIX		0x1982
 #define PCI_DEVICE_ID_KORENIX_JETCARDF0	0x1600
 #define PCI_DEVICE_ID_KORENIX_JETCARDF1	0x16ff
+#define PCI_DEVICE_ID_KORENIX_JETCARDF2	0x1700
+#define PCI_DEVICE_ID_KORENIX_JETCARDF3	0x17ff
 
 #define PCI_VENDOR_ID_QMI		0x1a32
 
@@ -2697,6 +2698,7 @@
 #define PCI_DEVICE_ID_NETMOS_9835	0x9835
 #define PCI_DEVICE_ID_NETMOS_9845	0x9845
 #define PCI_DEVICE_ID_NETMOS_9855	0x9855
+#define PCI_DEVICE_ID_NETMOS_9865	0x9865
 #define PCI_DEVICE_ID_NETMOS_9901	0x9901
 
 #define PCI_VENDOR_ID_3COM_2		0xa727
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index 9f2ad0a..c8f3029 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -507,6 +507,7 @@
 #define PCI_EXT_CAP_ID_VC	2
 #define PCI_EXT_CAP_ID_DSN	3
 #define PCI_EXT_CAP_ID_PWR	4
+#define PCI_EXT_CAP_ID_VNDR	11
 #define PCI_EXT_CAP_ID_ACS	13
 #define PCI_EXT_CAP_ID_ARI	14
 #define PCI_EXT_CAP_ID_ATS	15
diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
index 5a5d6ce..68567c0 100644
--- a/include/linux/percpu-defs.h
+++ b/include/linux/percpu-defs.h
@@ -2,12 +2,6 @@
 #define _LINUX_PERCPU_DEFS_H
 
 /*
- * Determine the real variable name from the name visible in the
- * kernel sources.
- */
-#define per_cpu_var(var) per_cpu__##var
-
-/*
  * Base implementations of per-CPU variable declarations and definitions, where
  * the section in which the variable is to be placed is provided by the
  * 'sec' argument.  This may be used to affect the parameters governing the
@@ -18,13 +12,23 @@
  * that section.
  */
 #define __PCPU_ATTRS(sec)						\
-	__attribute__((section(PER_CPU_BASE_SECTION sec)))		\
+	__percpu __attribute__((section(PER_CPU_BASE_SECTION sec)))	\
 	PER_CPU_ATTRIBUTES
 
 #define __PCPU_DUMMY_ATTRS						\
 	__attribute__((section(".discard"), unused))
 
 /*
+ * Macro which verifies @ptr is a percpu pointer without evaluating
+ * @ptr.  This is to be used in percpu accessors to verify that the
+ * input parameter is a percpu pointer.
+ */
+#define __verify_pcpu_ptr(ptr)	do {					\
+	const void __percpu *__vpp_verify = (typeof(ptr))NULL;		\
+	(void)__vpp_verify;						\
+} while (0)
+
+/*
  * s390 and alpha modules require percpu variables to be defined as
  * weak to force the compiler to generate GOT based external
  * references for them.  This is necessary because percpu sections
@@ -56,24 +60,24 @@
  */
 #define DECLARE_PER_CPU_SECTION(type, name, sec)			\
 	extern __PCPU_DUMMY_ATTRS char __pcpu_scope_##name;		\
-	extern __PCPU_ATTRS(sec) __typeof__(type) per_cpu__##name
+	extern __PCPU_ATTRS(sec) __typeof__(type) name
 
 #define DEFINE_PER_CPU_SECTION(type, name, sec)				\
 	__PCPU_DUMMY_ATTRS char __pcpu_scope_##name;			\
 	extern __PCPU_DUMMY_ATTRS char __pcpu_unique_##name;		\
 	__PCPU_DUMMY_ATTRS char __pcpu_unique_##name;			\
 	__PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES __weak			\
-	__typeof__(type) per_cpu__##name
+	__typeof__(type) name
 #else
 /*
  * Normal declaration and definition macros.
  */
 #define DECLARE_PER_CPU_SECTION(type, name, sec)			\
-	extern __PCPU_ATTRS(sec) __typeof__(type) per_cpu__##name
+	extern __PCPU_ATTRS(sec) __typeof__(type) name
 
 #define DEFINE_PER_CPU_SECTION(type, name, sec)				\
 	__PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES			\
-	__typeof__(type) per_cpu__##name
+	__typeof__(type) name
 #endif
 
 /*
@@ -135,10 +139,16 @@
 	__aligned(PAGE_SIZE)
 
 /*
- * Intermodule exports for per-CPU variables.
+ * Intermodule exports for per-CPU variables.  sparse forgets about
+ * address space across EXPORT_SYMBOL(), change EXPORT_SYMBOL() to
+ * noop if __CHECKER__.
  */
-#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
-#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
-
+#ifndef __CHECKER__
+#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var)
+#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var)
+#else
+#define EXPORT_PER_CPU_SYMBOL(var)
+#define EXPORT_PER_CPU_SYMBOL_GPL(var)
+#endif
 
 #endif /* _LINUX_PERCPU_DEFS_H */
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index cf5efbc..a93e5bf 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -27,10 +27,17 @@
  * we force a syntax error here if it isn't.
  */
 #define get_cpu_var(var) (*({				\
-	extern int simple_identifier_##var(void);	\
 	preempt_disable();				\
 	&__get_cpu_var(var); }))
-#define put_cpu_var(var) preempt_enable()
+
+/*
+ * The weird & is necessary because sparse considers (void)(var) to be
+ * a direct dereference of percpu variable (var).
+ */
+#define put_cpu_var(var) do {				\
+	(void)&(var);					\
+	preempt_enable();				\
+} while (0)
 
 #ifdef CONFIG_SMP
 
@@ -127,9 +134,9 @@
  */
 #define per_cpu_ptr(ptr, cpu)	SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu)))
 
-extern void *__alloc_reserved_percpu(size_t size, size_t align);
-extern void *__alloc_percpu(size_t size, size_t align);
-extern void free_percpu(void *__pdata);
+extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align);
+extern void __percpu *__alloc_percpu(size_t size, size_t align);
+extern void free_percpu(void __percpu *__pdata);
 extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
 
 #ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
@@ -140,7 +147,7 @@
 
 #define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); })
 
-static inline void *__alloc_percpu(size_t size, size_t align)
+static inline void __percpu *__alloc_percpu(size_t size, size_t align)
 {
 	/*
 	 * Can't easily make larger alignment work with kmalloc.  WARN
@@ -151,7 +158,7 @@
 	return kzalloc(size, GFP_KERNEL);
 }
 
-static inline void free_percpu(void *p)
+static inline void free_percpu(void __percpu *p)
 {
 	kfree(p);
 }
@@ -171,7 +178,7 @@
 #endif /* CONFIG_SMP */
 
 #define alloc_percpu(type)	\
-	(typeof(type) *)__alloc_percpu(sizeof(type), __alignof__(type))
+	(typeof(type) __percpu *)__alloc_percpu(sizeof(type), __alignof__(type))
 
 /*
  * Optional methods for optimized non-lvalue per-cpu variable access.
@@ -188,17 +195,19 @@
 #ifndef percpu_read
 # define percpu_read(var)						\
   ({									\
-	typeof(per_cpu_var(var)) __tmp_var__;				\
-	__tmp_var__ = get_cpu_var(var);					\
-	put_cpu_var(var);						\
-	__tmp_var__;							\
+	typeof(var) *pr_ptr__ = &(var);					\
+	typeof(var) pr_ret__;						\
+	pr_ret__ = get_cpu_var(*pr_ptr__);				\
+	put_cpu_var(*pr_ptr__);						\
+	pr_ret__;							\
   })
 #endif
 
 #define __percpu_generic_to_op(var, val, op)				\
 do {									\
-	get_cpu_var(var) op val;					\
-	put_cpu_var(var);						\
+	typeof(var) *pgto_ptr__ = &(var);				\
+	get_cpu_var(*pgto_ptr__) op val;				\
+	put_cpu_var(*pgto_ptr__);					\
 } while (0)
 
 #ifndef percpu_write
@@ -234,6 +243,7 @@
 
 #define __pcpu_size_call_return(stem, variable)				\
 ({	typeof(variable) pscr_ret__;					\
+	__verify_pcpu_ptr(&(variable));					\
 	switch(sizeof(variable)) {					\
 	case 1: pscr_ret__ = stem##1(variable);break;			\
 	case 2: pscr_ret__ = stem##2(variable);break;			\
@@ -247,6 +257,7 @@
 
 #define __pcpu_size_call(stem, variable, ...)				\
 do {									\
+	__verify_pcpu_ptr(&(variable));					\
 	switch(sizeof(variable)) {					\
 		case 1: stem##1(variable, __VA_ARGS__);break;		\
 		case 2: stem##2(variable, __VA_ARGS__);break;		\
@@ -259,8 +270,7 @@
 
 /*
  * Optimized manipulation for memory allocated through the per cpu
- * allocator or for addresses of per cpu variables (can be determined
- * using per_cpu_var(xx).
+ * allocator or for addresses of per cpu variables.
  *
  * These operation guarantee exclusivity of access for other operations
  * on the *same* processor. The assumption is that per cpu data is only
@@ -311,7 +321,7 @@
 #define _this_cpu_generic_to_op(pcp, val, op)				\
 do {									\
 	preempt_disable();						\
-	*__this_cpu_ptr(&pcp) op val;					\
+	*__this_cpu_ptr(&(pcp)) op val;					\
 	preempt_enable();						\
 } while (0)
 
diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
index 794662b..c88d67b 100644
--- a/include/linux/percpu_counter.h
+++ b/include/linux/percpu_counter.h
@@ -21,7 +21,7 @@
 #ifdef CONFIG_HOTPLUG_CPU
 	struct list_head list;	/* All percpu_counters are on a list */
 #endif
-	s32 *counters;
+	s32 __percpu *counters;
 };
 
 extern int percpu_counter_batch;
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 7b18b4f..6f8cd7d 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -487,9 +487,8 @@
 			struct hrtimer	hrtimer;
 		};
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
-		union { /* breakpoint */
-			struct arch_hw_breakpoint	info;
-		};
+		/* breakpoint */
+		struct arch_hw_breakpoint	info;
 #endif
 	};
 	atomic64_t			prev_count;
@@ -802,6 +801,13 @@
 	struct perf_raw_record		*raw;
 };
 
+static inline
+void perf_sample_data_init(struct perf_sample_data *data, u64 addr)
+{
+	data->addr = addr;
+	data->raw  = NULL;
+}
+
 extern void perf_output_sample(struct perf_output_handle *handle,
 			       struct perf_event_header *header,
 			       struct perf_sample_data *data,
@@ -858,6 +864,21 @@
 extern int sysctl_perf_event_mlock;
 extern int sysctl_perf_event_sample_rate;
 
+static inline bool perf_paranoid_tracepoint_raw(void)
+{
+	return sysctl_perf_event_paranoid > -1;
+}
+
+static inline bool perf_paranoid_cpu(void)
+{
+	return sysctl_perf_event_paranoid > 0;
+}
+
+static inline bool perf_paranoid_kernel(void)
+{
+	return sysctl_perf_event_paranoid > 1;
+}
+
 extern void perf_event_init(void);
 extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record, int entry_size);
 extern void perf_bp_event(struct perf_event *event, void *data);
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 71ff887..212da17 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -21,7 +21,7 @@
 	u32		num_resources;
 	struct resource	* resource;
 
-	struct platform_device_id	*id_entry;
+	const struct platform_device_id	*id_entry;
 
 	/* arch specific additions */
 	struct pdev_archdata	archdata;
@@ -62,7 +62,7 @@
 	int (*suspend)(struct platform_device *, pm_message_t state);
 	int (*resume)(struct platform_device *);
 	struct device_driver driver;
-	struct platform_device_id *id_table;
+	const struct platform_device_id *id_table;
 };
 
 extern int platform_driver_register(struct platform_driver *);
@@ -77,6 +77,11 @@
 #define platform_get_drvdata(_dev)	dev_get_drvdata(&(_dev)->dev)
 #define platform_set_drvdata(_dev,data)	dev_set_drvdata(&(_dev)->dev, (data))
 
+extern struct platform_device *platform_create_bundle(struct platform_driver *driver,
+					int (*probe)(struct platform_device *),
+					struct resource *res, unsigned int n_res,
+					const void *data, size_t size);
+
 /* early platform driver interface */
 struct early_platform_driver {
 	const char *class_str;
diff --git a/include/linux/pm.h b/include/linux/pm.h
index e80df06..8e258c7 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -215,20 +215,59 @@
 	int (*runtime_idle)(struct device *dev);
 };
 
+#ifdef CONFIG_PM_SLEEP
+#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
+	.suspend = suspend_fn, \
+	.resume = resume_fn, \
+	.freeze = suspend_fn, \
+	.thaw = resume_fn, \
+	.poweroff = suspend_fn, \
+	.restore = resume_fn,
+#else
+#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \
+	.runtime_suspend = suspend_fn, \
+	.runtime_resume = resume_fn, \
+	.runtime_idle = idle_fn,
+#else
+#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn)
+#endif
+
 /*
  * Use this if you want to use the same suspend and resume callbacks for suspend
  * to RAM and hibernation.
  */
 #define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \
 const struct dev_pm_ops name = { \
-	.suspend = suspend_fn, \
-	.resume = resume_fn, \
-	.freeze = suspend_fn, \
-	.thaw = resume_fn, \
-	.poweroff = suspend_fn, \
-	.restore = resume_fn, \
+	SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
 }
 
+/*
+ * Use this for defining a set of PM operations to be used in all situations
+ * (sustem suspend, hibernation or runtime PM).
+ */
+#define UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \
+const struct dev_pm_ops name = { \
+	SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
+	SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \
+}
+
+/*
+ * Use this for subsystems (bus types, device types, device classes) that don't
+ * need any special suspend/resume handling in addition to invoking the PM
+ * callbacks provided by device drivers supporting both the system sleep PM and
+ * runtime PM, make the pm member point to generic_subsys_pm_ops.
+ */
+#ifdef CONFIG_PM_OPS
+extern struct dev_pm_ops generic_subsys_pm_ops;
+#define GENERIC_SUBSYS_PM_OPS	(&generic_subsys_pm_ops)
+#else
+#define GENERIC_SUBSYS_PM_OPS	NULL
+#endif
+
 /**
  * PM_EVENT_ messages
  *
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index 7d773aa..b776db7 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -62,6 +62,11 @@
 	dev->power.run_wake = enable;
 }
 
+static inline bool pm_runtime_suspended(struct device *dev)
+{
+	return dev->power.runtime_status == RPM_SUSPENDED;
+}
+
 #else /* !CONFIG_PM_RUNTIME */
 
 static inline int pm_runtime_idle(struct device *dev) { return -ENOSYS; }
@@ -89,6 +94,7 @@
 static inline void pm_runtime_put_noidle(struct device *dev) {}
 static inline bool device_run_wake(struct device *dev) { return false; }
 static inline void device_set_run_wake(struct device *dev, bool enable) {}
+static inline bool pm_runtime_suspended(struct device *dev) { return false; }
 
 #endif /* !CONFIG_PM_RUNTIME */
 
diff --git a/include/linux/poll.h b/include/linux/poll.h
index 6673743..600cc1f 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -10,8 +10,10 @@
 #include <linux/wait.h>
 #include <linux/string.h>
 #include <linux/fs.h>
+#include <linux/sysctl.h>
 #include <asm/uaccess.h>
 
+extern struct ctl_table epoll_table[]; /* for sysctl */
 /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating
    additional memory. */
 #define MAX_STACK_ALLOC 832
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index c5eab89..e1fb607 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -264,6 +264,9 @@
 static inline void user_disable_single_step(struct task_struct *task)
 {
 }
+#else
+extern void user_enable_single_step(struct task_struct *);
+extern void user_disable_single_step(struct task_struct *);
 #endif	/* arch_has_single_step */
 
 #ifndef arch_has_block_step
@@ -291,6 +294,8 @@
 {
 	BUG();			/* This can never be called.  */
 }
+#else
+extern void user_enable_block_step(struct task_struct *);
 #endif	/* arch_has_block_step */
 
 #ifdef ARCH_HAS_USER_SINGLE_STEP_INFO
diff --git a/include/linux/quota.h b/include/linux/quota.h
index a6861f1..b462916 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -279,9 +279,6 @@
 	struct mem_dqblk dq_dqb;	/* Diskquota usage */
 };
 
-#define QUOTA_OK          0
-#define NO_QUOTA          1
-
 /* Operations which must be implemented by each quota format */
 struct quota_format_ops {
 	int (*check_quota_file)(struct super_block *sb, int type);	/* Detect whether file is in our format */
@@ -295,13 +292,6 @@
 
 /* Operations working with dquots */
 struct dquot_operations {
-	int (*initialize) (struct inode *, int);
-	int (*drop) (struct inode *);
-	int (*alloc_space) (struct inode *, qsize_t, int);
-	int (*alloc_inode) (const struct inode *, qsize_t);
-	int (*free_space) (struct inode *, qsize_t);
-	int (*free_inode) (const struct inode *, qsize_t);
-	int (*transfer) (struct inode *, struct iattr *);
 	int (*write_dquot) (struct dquot *);		/* Ordinary dquot write */
 	struct dquot *(*alloc_dquot)(struct super_block *, int);	/* Allocate memory for new dquot */
 	void (*destroy_dquot)(struct dquot *);		/* Free memory for dquot */
@@ -309,12 +299,6 @@
 	int (*release_dquot) (struct dquot *);		/* Quota is going to be deleted from disk */
 	int (*mark_dirty) (struct dquot *);		/* Dquot is marked dirty */
 	int (*write_info) (struct super_block *, int);	/* Write of quota "superblock" */
-	/* reserve quota for delayed block allocation */
-	int (*reserve_space) (struct inode *, qsize_t, int);
-	/* claim reserved quota for delayed alloc */
-	int (*claim_space) (struct inode *, qsize_t);
-	/* release rsved quota for delayed alloc */
-	void (*release_rsv) (struct inode *, qsize_t);
 	/* get reserved quota for delayed alloc, value returned is managed by
 	 * quota code only */
 	qsize_t *(*get_reserved_space) (struct inode *);
@@ -324,7 +308,7 @@
 struct quotactl_ops {
 	int (*quota_on)(struct super_block *, int, int, char *, int);
 	int (*quota_off)(struct super_block *, int, int);
-	int (*quota_sync)(struct super_block *, int);
+	int (*quota_sync)(struct super_block *, int, int);
 	int (*get_info)(struct super_block *, int, struct if_dqinfo *);
 	int (*set_info)(struct super_block *, int, struct if_dqinfo *);
 	int (*get_dqblk)(struct super_block *, int, qid_t, struct if_dqblk *);
@@ -357,26 +341,25 @@
 #define DQUOT_STATE_FLAGS	(DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED | \
 				 DQUOT_SUSPENDED)
 /* Other quota flags */
-#define DQUOT_QUOTA_SYS_FILE	(1 << 6)	/* Quota file is a special
+#define DQUOT_STATE_LAST	(_DQUOT_STATE_FLAGS * MAXQUOTAS)
+#define DQUOT_QUOTA_SYS_FILE	(1 << DQUOT_STATE_LAST)
+						/* Quota file is a special
 						 * system file and user cannot
 						 * touch it. Filesystem is
 						 * responsible for setting
 						 * S_NOQUOTA, S_NOATIME flags
 						 */
-#define DQUOT_NEGATIVE_USAGE	(1 << 7)	/* Allow negative quota usage */
+#define DQUOT_NEGATIVE_USAGE	(1 << (DQUOT_STATE_LAST + 1))
+					       /* Allow negative quota usage */
 
 static inline unsigned int dquot_state_flag(unsigned int flags, int type)
 {
-	if (type == USRQUOTA)
-		return flags;
-	return flags << _DQUOT_STATE_FLAGS;
+	return flags << _DQUOT_STATE_FLAGS * type;
 }
 
 static inline unsigned int dquot_generic_flag(unsigned int flags, int type)
 {
-	if (type == USRQUOTA)
-		return flags;
-	return flags >> _DQUOT_STATE_FLAGS;
+	return (flags >> _DQUOT_STATE_FLAGS * type) & DQUOT_STATE_FLAGS;
 }
 
 #ifdef CONFIG_QUOTA_NETLINK_INTERFACE
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 3ebb2315..e6fa7ac 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -19,15 +19,12 @@
 /*
  * declaration of quota_function calls in kernel.
  */
-void sync_quota_sb(struct super_block *sb, int type);
-static inline void writeout_quota_sb(struct super_block *sb, int type)
-{
-	if (sb->s_qcop->quota_sync)
-		sb->s_qcop->quota_sync(sb, type);
-}
+void inode_add_rsv_space(struct inode *inode, qsize_t number);
+void inode_claim_rsv_space(struct inode *inode, qsize_t number);
+void inode_sub_rsv_space(struct inode *inode, qsize_t number);
 
-int dquot_initialize(struct inode *inode, int type);
-int dquot_drop(struct inode *inode);
+void dquot_initialize(struct inode *inode);
+void dquot_drop(struct inode *inode);
 struct dquot *dqget(struct super_block *sb, unsigned int id, int type);
 void dqput(struct dquot *dquot);
 int dquot_scan_active(struct super_block *sb,
@@ -36,24 +33,23 @@
 struct dquot *dquot_alloc(struct super_block *sb, int type);
 void dquot_destroy(struct dquot *dquot);
 
-int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
-int dquot_alloc_inode(const struct inode *inode, qsize_t number);
+int __dquot_alloc_space(struct inode *inode, qsize_t number,
+		int warn, int reserve);
+void __dquot_free_space(struct inode *inode, qsize_t number, int reserve);
 
-int dquot_reserve_space(struct inode *inode, qsize_t number, int prealloc);
-int dquot_claim_space(struct inode *inode, qsize_t number);
-void dquot_release_reserved_space(struct inode *inode, qsize_t number);
-qsize_t dquot_get_reserved_space(struct inode *inode);
+int dquot_alloc_inode(const struct inode *inode);
 
-int dquot_free_space(struct inode *inode, qsize_t number);
-int dquot_free_inode(const struct inode *inode, qsize_t number);
+int dquot_claim_space_nodirty(struct inode *inode, qsize_t number);
+void dquot_free_inode(const struct inode *inode);
 
-int dquot_transfer(struct inode *inode, struct iattr *iattr);
 int dquot_commit(struct dquot *dquot);
 int dquot_acquire(struct dquot *dquot);
 int dquot_release(struct dquot *dquot);
 int dquot_commit_info(struct super_block *sb, int type);
 int dquot_mark_dquot_dirty(struct dquot *dquot);
 
+int dquot_file_open(struct inode *inode, struct file *file);
+
 int vfs_quota_on(struct super_block *sb, int type, int format_id,
  	char *path, int remount);
 int vfs_quota_enable(struct inode *inode, int type, int format_id,
@@ -64,14 +60,13 @@
  	int format_id, int type);
 int vfs_quota_off(struct super_block *sb, int type, int remount);
 int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags);
-int vfs_quota_sync(struct super_block *sb, int type);
+int vfs_quota_sync(struct super_block *sb, int type, int wait);
 int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
 int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
 int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
 int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di);
 
-void vfs_dq_drop(struct inode *inode);
-int vfs_dq_transfer(struct inode *inode, struct iattr *iattr);
+int dquot_transfer(struct inode *inode, struct iattr *iattr);
 int vfs_dq_quota_on_remount(struct super_block *sb);
 
 static inline struct mem_dqinfo *sb_dqinfo(struct super_block *sb, int type)
@@ -83,53 +78,56 @@
  * Functions for checking status of quota
  */
 
-static inline int sb_has_quota_usage_enabled(struct super_block *sb, int type)
+static inline bool sb_has_quota_usage_enabled(struct super_block *sb, int type)
 {
 	return sb_dqopt(sb)->flags &
 				dquot_state_flag(DQUOT_USAGE_ENABLED, type);
 }
 
-static inline int sb_has_quota_limits_enabled(struct super_block *sb, int type)
+static inline bool sb_has_quota_limits_enabled(struct super_block *sb, int type)
 {
 	return sb_dqopt(sb)->flags &
 				dquot_state_flag(DQUOT_LIMITS_ENABLED, type);
 }
 
-static inline int sb_has_quota_suspended(struct super_block *sb, int type)
+static inline bool sb_has_quota_suspended(struct super_block *sb, int type)
 {
 	return sb_dqopt(sb)->flags &
 				dquot_state_flag(DQUOT_SUSPENDED, type);
 }
 
-static inline int sb_any_quota_suspended(struct super_block *sb)
+static inline unsigned sb_any_quota_suspended(struct super_block *sb)
 {
-	return sb_has_quota_suspended(sb, USRQUOTA) ||
-		sb_has_quota_suspended(sb, GRPQUOTA);
+	unsigned type, tmsk = 0;
+	for (type = 0; type < MAXQUOTAS; type++)
+		tmsk |= sb_has_quota_suspended(sb, type) << type;
+	return tmsk;
 }
 
 /* Does kernel know about any quota information for given sb + type? */
-static inline int sb_has_quota_loaded(struct super_block *sb, int type)
+static inline bool sb_has_quota_loaded(struct super_block *sb, int type)
 {
 	/* Currently if anything is on, then quota usage is on as well */
 	return sb_has_quota_usage_enabled(sb, type);
 }
 
-static inline int sb_any_quota_loaded(struct super_block *sb)
+static inline unsigned sb_any_quota_loaded(struct super_block *sb)
 {
-	return sb_has_quota_loaded(sb, USRQUOTA) ||
-		sb_has_quota_loaded(sb, GRPQUOTA);
+	unsigned type, tmsk = 0;
+	for (type = 0; type < MAXQUOTAS; type++)
+		tmsk |= sb_has_quota_loaded(sb, type) << type;
+	return	tmsk;
 }
 
-static inline int sb_has_quota_active(struct super_block *sb, int type)
+static inline bool sb_has_quota_active(struct super_block *sb, int type)
 {
 	return sb_has_quota_loaded(sb, type) &&
 	       !sb_has_quota_suspended(sb, type);
 }
 
-static inline int sb_any_quota_active(struct super_block *sb)
+static inline unsigned sb_any_quota_active(struct super_block *sb)
 {
-	return sb_has_quota_active(sb, USRQUOTA) ||
-	       sb_has_quota_active(sb, GRPQUOTA);
+	return sb_any_quota_loaded(sb) & ~sb_any_quota_suspended(sb);
 }
 
 /*
@@ -141,122 +139,6 @@
 #define sb_dquot_ops (&dquot_operations)
 #define sb_quotactl_ops (&vfs_quotactl_ops)
 
-/* It is better to call this function outside of any transaction as it might
- * need a lot of space in journal for dquot structure allocation. */
-static inline void vfs_dq_init(struct inode *inode)
-{
-	BUG_ON(!inode->i_sb);
-	if (sb_any_quota_active(inode->i_sb) && !IS_NOQUOTA(inode))
-		inode->i_sb->dq_op->initialize(inode, -1);
-}
-
-/* The following allocation/freeing/transfer functions *must* be called inside
- * a transaction (deadlocks possible otherwise) */
-static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr)
-{
-	if (sb_any_quota_active(inode->i_sb)) {
-		/* Used space is updated in alloc_space() */
-		if (inode->i_sb->dq_op->alloc_space(inode, nr, 1) == NO_QUOTA)
-			return 1;
-	}
-	else
-		inode_add_bytes(inode, nr);
-	return 0;
-}
-
-static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr)
-{
-	int ret;
-        if (!(ret =  vfs_dq_prealloc_space_nodirty(inode, nr)))
-		mark_inode_dirty(inode);
-	return ret;
-}
-
-static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr)
-{
-	if (sb_any_quota_active(inode->i_sb)) {
-		/* Used space is updated in alloc_space() */
-		if (inode->i_sb->dq_op->alloc_space(inode, nr, 0) == NO_QUOTA)
-			return 1;
-	}
-	else
-		inode_add_bytes(inode, nr);
-	return 0;
-}
-
-static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
-{
-	int ret;
-	if (!(ret = vfs_dq_alloc_space_nodirty(inode, nr)))
-		mark_inode_dirty(inode);
-	return ret;
-}
-
-static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr)
-{
-	if (sb_any_quota_active(inode->i_sb)) {
-		/* Used space is updated in alloc_space() */
-		if (inode->i_sb->dq_op->reserve_space(inode, nr, 0) == NO_QUOTA)
-			return 1;
-	}
-	return 0;
-}
-
-static inline int vfs_dq_alloc_inode(struct inode *inode)
-{
-	if (sb_any_quota_active(inode->i_sb)) {
-		vfs_dq_init(inode);
-		if (inode->i_sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA)
-			return 1;
-	}
-	return 0;
-}
-
-/*
- * Convert in-memory reserved quotas to real consumed quotas
- */
-static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr)
-{
-	if (sb_any_quota_active(inode->i_sb)) {
-		if (inode->i_sb->dq_op->claim_space(inode, nr) == NO_QUOTA)
-			return 1;
-	} else
-		inode_add_bytes(inode, nr);
-
-	mark_inode_dirty(inode);
-	return 0;
-}
-
-/*
- * Release reserved (in-memory) quotas
- */
-static inline
-void vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr)
-{
-	if (sb_any_quota_active(inode->i_sb))
-		inode->i_sb->dq_op->release_rsv(inode, nr);
-}
-
-static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
-{
-	if (sb_any_quota_active(inode->i_sb))
-		inode->i_sb->dq_op->free_space(inode, nr);
-	else
-		inode_sub_bytes(inode, nr);
-}
-
-static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
-{
-	vfs_dq_free_space_nodirty(inode, nr);
-	mark_inode_dirty(inode);
-}
-
-static inline void vfs_dq_free_inode(struct inode *inode)
-{
-	if (sb_any_quota_active(inode->i_sb))
-		inode->i_sb->dq_op->free_inode(inode, 1);
-}
-
 /* Cannot be called inside a transaction */
 static inline int vfs_dq_off(struct super_block *sb, int remount)
 {
@@ -316,28 +198,20 @@
 #define sb_dquot_ops				(NULL)
 #define sb_quotactl_ops				(NULL)
 
-static inline void vfs_dq_init(struct inode *inode)
+static inline void dquot_initialize(struct inode *inode)
 {
 }
 
-static inline void vfs_dq_drop(struct inode *inode)
+static inline void dquot_drop(struct inode *inode)
 {
 }
 
-static inline int vfs_dq_alloc_inode(struct inode *inode)
+static inline int dquot_alloc_inode(const struct inode *inode)
 {
 	return 0;
 }
 
-static inline void vfs_dq_free_inode(struct inode *inode)
-{
-}
-
-static inline void sync_quota_sb(struct super_block *sb, int type)
-{
-}
-
-static inline void writeout_quota_sb(struct super_block *sb, int type)
+static inline void dquot_free_inode(const struct inode *inode)
 {
 }
 
@@ -351,110 +225,116 @@
 	return 0;
 }
 
-static inline int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
+static inline int dquot_transfer(struct inode *inode, struct iattr *iattr)
 {
 	return 0;
 }
 
-static inline int vfs_dq_prealloc_space_nodirty(struct inode *inode, qsize_t nr)
+static inline int __dquot_alloc_space(struct inode *inode, qsize_t number,
+		int warn, int reserve)
 {
-	inode_add_bytes(inode, nr);
+	if (!reserve)
+		inode_add_bytes(inode, number);
 	return 0;
 }
 
-static inline int vfs_dq_prealloc_space(struct inode *inode, qsize_t nr)
+static inline void __dquot_free_space(struct inode *inode, qsize_t number,
+		int reserve)
 {
-	vfs_dq_prealloc_space_nodirty(inode, nr);
-	mark_inode_dirty(inode);
+	if (!reserve)
+		inode_sub_bytes(inode, number);
+}
+
+static inline int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
+{
+	inode_add_bytes(inode, number);
 	return 0;
 }
 
-static inline int vfs_dq_alloc_space_nodirty(struct inode *inode, qsize_t nr)
-{
-	inode_add_bytes(inode, nr);
-	return 0;
-}
-
-static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
-{
-	vfs_dq_alloc_space_nodirty(inode, nr);
-	mark_inode_dirty(inode);
-	return 0;
-}
-
-static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr)
-{
-	return 0;
-}
-
-static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr)
-{
-	return vfs_dq_alloc_space(inode, nr);
-}
-
-static inline
-int vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr)
-{
-	return 0;
-}
-
-static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
-{
-	inode_sub_bytes(inode, nr);
-}
-
-static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
-{
-	vfs_dq_free_space_nodirty(inode, nr);
-	mark_inode_dirty(inode);
-}	
+#define dquot_file_open		generic_file_open
 
 #endif /* CONFIG_QUOTA */
 
-static inline int vfs_dq_prealloc_block_nodirty(struct inode *inode, qsize_t nr)
+static inline int dquot_alloc_space_nodirty(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_prealloc_space_nodirty(inode, nr << inode->i_blkbits);
+	return __dquot_alloc_space(inode, nr, 1, 0);
 }
 
-static inline int vfs_dq_prealloc_block(struct inode *inode, qsize_t nr)
+static inline int dquot_alloc_space(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_prealloc_space(inode, nr << inode->i_blkbits);
+	int ret;
+
+	ret = dquot_alloc_space_nodirty(inode, nr);
+	if (!ret)
+		mark_inode_dirty(inode);
+	return ret;
 }
 
-static inline int vfs_dq_alloc_block_nodirty(struct inode *inode, qsize_t nr)
+static inline int dquot_alloc_block_nodirty(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_alloc_space_nodirty(inode, nr << inode->i_blkbits);
+	return dquot_alloc_space_nodirty(inode, nr << inode->i_blkbits);
 }
 
-static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr)
+static inline int dquot_alloc_block(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_alloc_space(inode, nr << inode->i_blkbits);
+	return dquot_alloc_space(inode, nr << inode->i_blkbits);
 }
 
-static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr)
+static inline int dquot_prealloc_block_nodirty(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_reserve_space(inode, nr << inode->i_blkbits);
+	return __dquot_alloc_space(inode, nr << inode->i_blkbits, 0, 0);
 }
 
-static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr)
+static inline int dquot_prealloc_block(struct inode *inode, qsize_t nr)
 {
-	return vfs_dq_claim_space(inode, nr << inode->i_blkbits);
+	int ret;
+
+	ret = dquot_prealloc_block_nodirty(inode, nr);
+	if (!ret)
+		mark_inode_dirty(inode);
+	return ret;
 }
 
-static inline
-void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr)
+static inline int dquot_reserve_block(struct inode *inode, qsize_t nr)
 {
-	vfs_dq_release_reservation_space(inode, nr << inode->i_blkbits);
+	return __dquot_alloc_space(inode, nr << inode->i_blkbits, 1, 1);
 }
 
-static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
+static inline int dquot_claim_block(struct inode *inode, qsize_t nr)
 {
-	vfs_dq_free_space_nodirty(inode, nr << inode->i_blkbits);
+	int ret;
+
+	ret = dquot_claim_space_nodirty(inode, nr << inode->i_blkbits);
+	if (!ret)
+		mark_inode_dirty(inode);
+	return ret;
 }
 
-static inline void vfs_dq_free_block(struct inode *inode, qsize_t nr)
+static inline void dquot_free_space_nodirty(struct inode *inode, qsize_t nr)
 {
-	vfs_dq_free_space(inode, nr << inode->i_blkbits);
+	__dquot_free_space(inode, nr, 0);
+}
+
+static inline void dquot_free_space(struct inode *inode, qsize_t nr)
+{
+	dquot_free_space_nodirty(inode, nr);
+	mark_inode_dirty(inode);
+}
+
+static inline void dquot_free_block_nodirty(struct inode *inode, qsize_t nr)
+{
+	dquot_free_space_nodirty(inode, nr << inode->i_blkbits);
+}
+
+static inline void dquot_free_block(struct inode *inode, qsize_t nr)
+{
+	dquot_free_space(inode, nr << inode->i_blkbits);
+}
+
+static inline void dquot_release_reservation_block(struct inode *inode,
+		qsize_t nr)
+{
+	__dquot_free_space(inode, nr << inode->i_blkbits, 1);
 }
 
 #endif /* _LINUX_QUOTAOPS_ */
diff --git a/include/linux/range.h b/include/linux/range.h
new file mode 100644
index 0000000..bd184a5
--- /dev/null
+++ b/include/linux/range.h
@@ -0,0 +1,30 @@
+#ifndef _LINUX_RANGE_H
+#define _LINUX_RANGE_H
+
+struct range {
+	u64   start;
+	u64   end;
+};
+
+int add_range(struct range *range, int az, int nr_range,
+		u64 start, u64 end);
+
+
+int add_range_with_merge(struct range *range, int az, int nr_range,
+				u64 start, u64 end);
+
+void subtract_range(struct range *range, int az, u64 start, u64 end);
+
+int clean_sort_range(struct range *range, int az);
+
+void sort_range(struct range *range, int nr_range);
+
+#define MAX_RESOURCE ((resource_size_t)~0)
+static inline resource_size_t cap_resource(u64 val)
+{
+	if (val > MAX_RESOURCE)
+		return MAX_RESOURCE;
+
+	return val;
+}
+#endif
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h
index 9c29541..5210a5c 100644
--- a/include/linux/rbtree.h
+++ b/include/linux/rbtree.h
@@ -25,10 +25,10 @@
 
   Some example of insert and search follows here. The search is a plain
   normal search over an ordered tree. The insert instead must be implemented
-  int two steps: as first thing the code must insert the element in
-  order as a red leaf in the tree, then the support library function
-  rb_insert_color() must be called. Such function will do the
-  not trivial work to rebalance the rbtree if necessary.
+  in two steps: First, the code must insert the element in order as a red leaf
+  in the tree, and then the support library function rb_insert_color() must
+  be called. Such function will do the not trivial work to rebalance the
+  rbtree, if necessary.
 
 -----------------------------------------------------------------------
 static inline struct page * rb_search_page_cache(struct inode * inode,
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index c843736..3024050 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -41,6 +41,10 @@
 #include <linux/lockdep.h>
 #include <linux/completion.h>
 
+#ifdef CONFIG_RCU_TORTURE_TEST
+extern int rcutorture_runnable; /* for sysctl */
+#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
+
 /**
  * struct rcu_head - callback structure for use with RCU
  * @next: next update requests in a list
@@ -97,6 +101,11 @@
 # define rcu_read_release_sched() \
 		lock_release(&rcu_sched_lock_map, 1, _THIS_IP_)
 
+static inline int debug_lockdep_rcu_enabled(void)
+{
+	return likely(rcu_scheduler_active && debug_locks);
+}
+
 /**
  * rcu_read_lock_held - might we be in RCU read-side critical section?
  *
@@ -104,12 +113,14 @@
  * an RCU read-side critical section.  In absence of CONFIG_PROVE_LOCKING,
  * this assumes we are in an RCU read-side critical section unless it can
  * prove otherwise.
+ *
+ * Check rcu_scheduler_active to prevent false positives during boot.
  */
 static inline int rcu_read_lock_held(void)
 {
-	if (debug_locks)
-		return lock_is_held(&rcu_lock_map);
-	return 1;
+	if (!debug_lockdep_rcu_enabled())
+		return 1;
+	return lock_is_held(&rcu_lock_map);
 }
 
 /**
@@ -119,12 +130,14 @@
  * an RCU-bh read-side critical section.  In absence of CONFIG_PROVE_LOCKING,
  * this assumes we are in an RCU-bh read-side critical section unless it can
  * prove otherwise.
+ *
+ * Check rcu_scheduler_active to prevent false positives during boot.
  */
 static inline int rcu_read_lock_bh_held(void)
 {
-	if (debug_locks)
-		return lock_is_held(&rcu_bh_lock_map);
-	return 1;
+	if (!debug_lockdep_rcu_enabled())
+		return 1;
+	return lock_is_held(&rcu_bh_lock_map);
 }
 
 /**
@@ -135,15 +148,26 @@
  * this assumes we are in an RCU-sched read-side critical section unless it
  * can prove otherwise.  Note that disabling of preemption (including
  * disabling irqs) counts as an RCU-sched read-side critical section.
+ *
+ * Check rcu_scheduler_active to prevent false positives during boot.
  */
+#ifdef CONFIG_PREEMPT
 static inline int rcu_read_lock_sched_held(void)
 {
 	int lockdep_opinion = 0;
 
+	if (!debug_lockdep_rcu_enabled())
+		return 1;
 	if (debug_locks)
 		lockdep_opinion = lock_is_held(&rcu_sched_lock_map);
-	return lockdep_opinion || preempt_count() != 0 || !rcu_scheduler_active;
+	return lockdep_opinion || preempt_count() != 0;
 }
+#else /* #ifdef CONFIG_PREEMPT */
+static inline int rcu_read_lock_sched_held(void)
+{
+	return 1;
+}
+#endif /* #else #ifdef CONFIG_PREEMPT */
 
 #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
@@ -164,10 +188,17 @@
 	return 1;
 }
 
+#ifdef CONFIG_PREEMPT
 static inline int rcu_read_lock_sched_held(void)
 {
-	return preempt_count() != 0 || !rcu_scheduler_active;
+	return !rcu_scheduler_active || preempt_count() != 0;
 }
+#else /* #ifdef CONFIG_PREEMPT */
+static inline int rcu_read_lock_sched_held(void)
+{
+	return 1;
+}
+#endif /* #else #ifdef CONFIG_PREEMPT */
 
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
@@ -184,7 +215,7 @@
  */
 #define rcu_dereference_check(p, c) \
 	({ \
-		if (debug_locks && !(c)) \
+		if (debug_lockdep_rcu_enabled() && !(c)) \
 			lockdep_rcu_dereference(__FILE__, __LINE__); \
 		rcu_dereference_raw(p); \
 	})
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 988e55f..3005d5a 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -64,6 +64,7 @@
 extern void kernel_halt(void);
 extern void kernel_power_off(void);
 
+extern int C_A_D; /* for sysctl */
 void ctrl_alt_del(void);
 
 #define POWEROFF_CMD_PATH_LEN	256
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 030d922..28c9fd0 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -89,8 +89,9 @@
  * REGULATION_OUT Regulator output is out of regulation.
  * FAIL           Regulator output has failed.
  * OVER_TEMP      Regulator over temp.
- * FORCE_DISABLE  Regulator shut down by software.
+ * FORCE_DISABLE  Regulator forcibly shut down by software.
  * VOLTAGE_CHANGE Regulator voltage changed.
+ * DISABLE        Regulator was disabled.
  *
  * NOTE: These events can be OR'ed together when passed into handler.
  */
@@ -102,6 +103,7 @@
 #define REGULATOR_EVENT_OVER_TEMP		0x10
 #define REGULATOR_EVENT_FORCE_DISABLE		0x20
 #define REGULATOR_EVENT_VOLTAGE_CHANGE		0x40
+#define REGULATOR_EVENT_DISABLE 		0x80
 
 struct regulator;
 
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 31f2055..592cd7c 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -58,6 +58,9 @@
  * @get_optimum_mode: Get the most efficient operating mode for the regulator
  *                    when running with the specified parameters.
  *
+ * @enable_time: Time taken for the regulator voltage output voltage to
+ *               stabalise after being enabled, in microseconds.
+ *
  * @set_suspend_voltage: Set the voltage for the regulator when the system
  *                       is suspended.
  * @set_suspend_enable: Mark the regulator as enabled when the system is
@@ -93,6 +96,9 @@
 	int (*set_mode) (struct regulator_dev *, unsigned int mode);
 	unsigned int (*get_mode) (struct regulator_dev *);
 
+	/* Time taken to enable the regulator */
+	int (*enable_time) (struct regulator_dev *);
+
 	/* report regulator status ... most other accessors report
 	 * control inputs, this reports results of combining inputs
 	 * from Linux (and other sources) with the actual load.
diff --git a/include/linux/regulator/fixed.h b/include/linux/regulator/fixed.h
index e94a4a1..ffd7d50 100644
--- a/include/linux/regulator/fixed.h
+++ b/include/linux/regulator/fixed.h
@@ -25,6 +25,7 @@
  * @microvolts:		Output voltage of regulator
  * @gpio:		GPIO to use for enable control
  * 			set to -EINVAL if not used
+ * @startup_delay:	Start-up time in microseconds
  * @enable_high:	Polarity of enable GPIO
  *			1 = Active high, 0 = Active low
  * @enabled_at_boot:	Whether regulator has been enabled at
@@ -41,6 +42,7 @@
 	const char *supply_name;
 	int microvolts;
 	int gpio;
+	unsigned startup_delay;
 	unsigned enable_high:1;
 	unsigned enabled_at_boot:1;
 	struct regulator_init_data *init_data;
diff --git a/include/linux/regulator/max8649.h b/include/linux/regulator/max8649.h
new file mode 100644
index 0000000..417d14e
--- /dev/null
+++ b/include/linux/regulator/max8649.h
@@ -0,0 +1,44 @@
+/*
+ * Interface of Maxim max8649
+ *
+ * Copyright (C) 2009-2010 Marvell International Ltd.
+ *      Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_REGULATOR_MAX8649_H
+#define	__LINUX_REGULATOR_MAX8649_H
+
+#include <linux/regulator/machine.h>
+
+enum {
+	MAX8649_EXTCLK_26MHZ = 0,
+	MAX8649_EXTCLK_13MHZ,
+	MAX8649_EXTCLK_19MHZ,	/* 19.2MHz */
+};
+
+enum {
+	MAX8649_RAMP_32MV = 0,
+	MAX8649_RAMP_16MV,
+	MAX8649_RAMP_8MV,
+	MAX8649_RAMP_4MV,
+	MAX8649_RAMP_2MV,
+	MAX8649_RAMP_1MV,
+	MAX8649_RAMP_0_5MV,
+	MAX8649_RAMP_0_25MV,
+};
+
+struct max8649_platform_data {
+	struct regulator_init_data *regulator;
+
+	unsigned	mode:2;		/* bit[1:0] = VID1,VID0 */
+	unsigned	extclk_freq:2;
+	unsigned	extclk:1;
+	unsigned	ramp_timing:3;
+	unsigned	ramp_down:1;
+};
+
+#endif	/* __LINUX_REGULATOR_MAX8649_H */
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 1ba3cf6..3b603f4 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -2034,7 +2034,7 @@
 int reiserfs_find_actor(struct inode *inode, void *p);
 int reiserfs_init_locked_inode(struct inode *inode, void *p);
 void reiserfs_delete_inode(struct inode *inode);
-int reiserfs_write_inode(struct inode *inode, int);
+int reiserfs_write_inode(struct inode *inode, struct writeback_control *wbc);
 int reiserfs_get_block(struct inode *inode, sector_t block,
 		       struct buffer_head *bh_result, int create);
 struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index b019ae6..d25bd22 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -37,7 +37,27 @@
 	 * is serialized by a system wide lock only visible to
 	 * mm_take_all_locks() (mm_all_locks_mutex).
 	 */
-	struct list_head head;	/* List of private "related" vmas */
+	struct list_head head;	/* Chain of private "related" vmas */
+};
+
+/*
+ * The copy-on-write semantics of fork mean that an anon_vma
+ * can become associated with multiple processes. Furthermore,
+ * each child process will have its own anon_vma, where new
+ * pages for that process are instantiated.
+ *
+ * This structure allows us to find the anon_vmas associated
+ * with a VMA, or the VMAs associated with an anon_vma.
+ * The "same_vma" list contains the anon_vma_chains linking
+ * all the anon_vmas associated with this VMA.
+ * The "same_anon_vma" list contains the anon_vma_chains
+ * which link all the VMAs associated with this anon_vma.
+ */
+struct anon_vma_chain {
+	struct vm_area_struct *vma;
+	struct anon_vma *anon_vma;
+	struct list_head same_vma;   /* locked by mmap_sem & page_table_lock */
+	struct list_head same_anon_vma;	/* locked by anon_vma->lock */
 };
 
 #ifdef CONFIG_MMU
@@ -89,15 +109,23 @@
  */
 void anon_vma_init(void);	/* create anon_vma_cachep */
 int  anon_vma_prepare(struct vm_area_struct *);
-void __anon_vma_merge(struct vm_area_struct *, struct vm_area_struct *);
-void anon_vma_unlink(struct vm_area_struct *);
-void anon_vma_link(struct vm_area_struct *);
+void unlink_anon_vmas(struct vm_area_struct *);
+int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
+int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
 void __anon_vma_link(struct vm_area_struct *);
 void anon_vma_free(struct anon_vma *);
 
+static inline void anon_vma_merge(struct vm_area_struct *vma,
+				  struct vm_area_struct *next)
+{
+	VM_BUG_ON(vma->anon_vma != next->anon_vma);
+	unlink_anon_vmas(next);
+}
+
 /*
  * rmap interfaces called when adding or removing pte of page
  */
+void page_move_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
 void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
 void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
 void page_add_file_rmap(struct page *);
@@ -181,7 +209,7 @@
 				  unsigned long *vm_flags)
 {
 	*vm_flags = 0;
-	return TestClearPageReferenced(page);
+	return 0;
 }
 
 #define try_to_unmap(page, refs) SWAP_FAIL
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 60f88a7..14dbc83 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -238,6 +238,12 @@
 	return (!(year % 4) && (year % 100)) || !(year % 400);
 }
 
+#ifdef CONFIG_RTC_HCTOSYS
+extern int rtc_hctosys_ret;
+#else
+#define rtc_hctosys_ret -ENODEV
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_RTC_H_ */
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h
index 281d8fd..8d522ff 100644
--- a/include/linux/rtmutex.h
+++ b/include/linux/rtmutex.h
@@ -16,6 +16,8 @@
 #include <linux/plist.h>
 #include <linux/spinlock_types.h>
 
+extern int max_lock_depth; /* for sysctl */
+
 /**
  * The rt_mutex structure
  *
diff --git a/include/linux/rwlock.h b/include/linux/rwlock.h
index 71e0b00..bc2994e 100644
--- a/include/linux/rwlock.h
+++ b/include/linux/rwlock.h
@@ -29,25 +29,25 @@
 #endif
 
 #ifdef CONFIG_DEBUG_SPINLOCK
- extern void do_raw_read_lock(rwlock_t *lock);
+ extern void do_raw_read_lock(rwlock_t *lock) __acquires(lock);
 #define do_raw_read_lock_flags(lock, flags) do_raw_read_lock(lock)
  extern int do_raw_read_trylock(rwlock_t *lock);
- extern void do_raw_read_unlock(rwlock_t *lock);
- extern void do_raw_write_lock(rwlock_t *lock);
+ extern void do_raw_read_unlock(rwlock_t *lock) __releases(lock);
+ extern void do_raw_write_lock(rwlock_t *lock) __acquires(lock);
 #define do_raw_write_lock_flags(lock, flags) do_raw_write_lock(lock)
  extern int do_raw_write_trylock(rwlock_t *lock);
- extern void do_raw_write_unlock(rwlock_t *lock);
+ extern void do_raw_write_unlock(rwlock_t *lock) __releases(lock);
 #else
-# define do_raw_read_lock(rwlock)	arch_read_lock(&(rwlock)->raw_lock)
+# define do_raw_read_lock(rwlock)	do {__acquire(lock); arch_read_lock(&(rwlock)->raw_lock); } while (0)
 # define do_raw_read_lock_flags(lock, flags) \
-		arch_read_lock_flags(&(lock)->raw_lock, *(flags))
+		do {__acquire(lock); arch_read_lock_flags(&(lock)->raw_lock, *(flags)); } while (0)
 # define do_raw_read_trylock(rwlock)	arch_read_trylock(&(rwlock)->raw_lock)
-# define do_raw_read_unlock(rwlock)	arch_read_unlock(&(rwlock)->raw_lock)
-# define do_raw_write_lock(rwlock)	arch_write_lock(&(rwlock)->raw_lock)
+# define do_raw_read_unlock(rwlock)	do {arch_read_unlock(&(rwlock)->raw_lock); __release(lock); } while (0)
+# define do_raw_write_lock(rwlock)	do {__acquire(lock); arch_write_lock(&(rwlock)->raw_lock); } while (0)
 # define do_raw_write_lock_flags(lock, flags) \
-		arch_write_lock_flags(&(lock)->raw_lock, *(flags))
+		do {__acquire(lock); arch_write_lock_flags(&(lock)->raw_lock, *(flags)); } while (0)
 # define do_raw_write_trylock(rwlock)	arch_write_trylock(&(rwlock)->raw_lock)
-# define do_raw_write_unlock(rwlock)	arch_write_unlock(&(rwlock)->raw_lock)
+# define do_raw_write_unlock(rwlock)	do {arch_write_unlock(&(rwlock)->raw_lock); __release(lock); } while (0)
 #endif
 
 #define read_can_lock(rwlock)		arch_read_can_lock(&(rwlock)->raw_lock)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4b1753f..dad7f66 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -258,6 +258,10 @@
 
 struct task_struct;
 
+#ifdef CONFIG_PROVE_RCU
+extern int lockdep_tasklist_lock_is_held(void);
+#endif /* #ifdef CONFIG_PROVE_RCU */
+
 extern void sched_init(void);
 extern void sched_init_smp(void);
 extern asmlinkage void schedule_tail(struct task_struct *prev);
@@ -396,60 +400,6 @@
 static inline void arch_pick_mmap_layout(struct mm_struct *mm) {}
 #endif
 
-#if USE_SPLIT_PTLOCKS
-/*
- * The mm counters are not protected by its page_table_lock,
- * so must be incremented atomically.
- */
-#define set_mm_counter(mm, member, value) atomic_long_set(&(mm)->_##member, value)
-#define get_mm_counter(mm, member) ((unsigned long)atomic_long_read(&(mm)->_##member))
-#define add_mm_counter(mm, member, value) atomic_long_add(value, &(mm)->_##member)
-#define inc_mm_counter(mm, member) atomic_long_inc(&(mm)->_##member)
-#define dec_mm_counter(mm, member) atomic_long_dec(&(mm)->_##member)
-
-#else  /* !USE_SPLIT_PTLOCKS */
-/*
- * The mm counters are protected by its page_table_lock,
- * so can be incremented directly.
- */
-#define set_mm_counter(mm, member, value) (mm)->_##member = (value)
-#define get_mm_counter(mm, member) ((mm)->_##member)
-#define add_mm_counter(mm, member, value) (mm)->_##member += (value)
-#define inc_mm_counter(mm, member) (mm)->_##member++
-#define dec_mm_counter(mm, member) (mm)->_##member--
-
-#endif /* !USE_SPLIT_PTLOCKS */
-
-#define get_mm_rss(mm)					\
-	(get_mm_counter(mm, file_rss) + get_mm_counter(mm, anon_rss))
-#define update_hiwater_rss(mm)	do {			\
-	unsigned long _rss = get_mm_rss(mm);		\
-	if ((mm)->hiwater_rss < _rss)			\
-		(mm)->hiwater_rss = _rss;		\
-} while (0)
-#define update_hiwater_vm(mm)	do {			\
-	if ((mm)->hiwater_vm < (mm)->total_vm)		\
-		(mm)->hiwater_vm = (mm)->total_vm;	\
-} while (0)
-
-static inline unsigned long get_mm_hiwater_rss(struct mm_struct *mm)
-{
-	return max(mm->hiwater_rss, get_mm_rss(mm));
-}
-
-static inline void setmax_mm_hiwater_rss(unsigned long *maxrss,
-					 struct mm_struct *mm)
-{
-	unsigned long hiwater_rss = get_mm_hiwater_rss(mm);
-
-	if (*maxrss < hiwater_rss)
-		*maxrss = hiwater_rss;
-}
-
-static inline unsigned long get_mm_hiwater_vm(struct mm_struct *mm)
-{
-	return max(mm->hiwater_vm, mm->total_vm);
-}
 
 extern void set_dumpable(struct mm_struct *mm, int value);
 extern int get_dumpable(struct mm_struct *mm);
@@ -1274,7 +1224,9 @@
 	struct plist_node pushable_tasks;
 
 	struct mm_struct *mm, *active_mm;
-
+#if defined(SPLIT_RSS_COUNTING)
+	struct task_rss_stat	rss_stat;
+#endif
 /* task state */
 	int exit_state;
 	int exit_code, exit_signal;
@@ -1525,7 +1477,7 @@
 
 	struct list_head	*scm_work_list;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-	/* Index of current stored adress in ret_stack */
+	/* Index of current stored address in ret_stack */
 	int curr_ret_stack;
 	/* Stack of return addresses for return function tracing */
 	struct ftrace_ret_stack	*ret_stack;
@@ -2443,9 +2395,7 @@
 
 static inline void thread_group_cputime_init(struct signal_struct *sig)
 {
-	sig->cputimer.cputime = INIT_CPUTIME;
 	spin_lock_init(&sig->cputimer.lock);
-	sig->cputimer.running = 0;
 }
 
 static inline void thread_group_cputime_free(struct signal_struct *sig)
diff --git a/include/linux/security.h b/include/linux/security.h
index 2c627d3..233d20b 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -76,7 +76,7 @@
 extern int cap_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp);
 extern int cap_task_setioprio(struct task_struct *p, int ioprio);
 extern int cap_task_setnice(struct task_struct *p, int nice);
-extern int cap_syslog(int type);
+extern int cap_syslog(int type, bool from_file);
 extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);
 
 struct msghdr;
@@ -95,6 +95,8 @@
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
 
+void reset_security_ops(void);
+
 #ifdef CONFIG_MMU
 extern unsigned long mmap_min_addr;
 extern unsigned long dac_mmap_min_addr;
@@ -985,6 +987,7 @@
  *	Check permissions on incoming network packets.  This hook is distinct
  *	from Netfilter's IP input hooks since it is the first time that the
  *	incoming sk_buff @skb has been associated with a particular socket, @sk.
+ *	Must not sleep inside this hook because some callers hold spinlocks.
  *	@sk contains the sock (not socket) associated with the incoming sk_buff.
  *	@skb contains the incoming network data.
  * @socket_getpeersec_stream:
@@ -1348,6 +1351,7 @@
  *	logging to the console.
  *	See the syslog(2) manual page for an explanation of the @type values.
  *	@type contains the type of action.
+ *	@from_file indicates the context of action (if it came from /proc).
  *	Return 0 if permission is granted.
  * @settime:
  *	Check permission to change the system time.
@@ -1462,7 +1466,7 @@
 	int (*sysctl) (struct ctl_table *table, int op);
 	int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
 	int (*quota_on) (struct dentry *dentry);
-	int (*syslog) (int type);
+	int (*syslog) (int type, bool from_file);
 	int (*settime) (struct timespec *ts, struct timezone *tz);
 	int (*vm_enough_memory) (struct mm_struct *mm, long pages);
 
@@ -1761,7 +1765,7 @@
 int security_sysctl(struct ctl_table *table, int op);
 int security_quotactl(int cmds, int type, int id, struct super_block *sb);
 int security_quota_on(struct dentry *dentry);
-int security_syslog(int type);
+int security_syslog(int type, bool from_file);
 int security_settime(struct timespec *ts, struct timezone *tz);
 int security_vm_enough_memory(long pages);
 int security_vm_enough_memory_mm(struct mm_struct *mm, long pages);
@@ -2007,9 +2011,9 @@
 	return 0;
 }
 
-static inline int security_syslog(int type)
+static inline int security_syslog(int type, bool from_file)
 {
-	return cap_syslog(type);
+	return cap_syslog(type, from_file);
 }
 
 static inline int security_settime(struct timespec *ts, struct timezone *tz)
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 8c3dd36..78dd1e7 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -491,9 +491,13 @@
 {
 	struct uart_state *state = uport->state;
 	struct tty_port *port = &state->port;
+	struct tty_ldisc *ld = tty_ldisc_ref(port->tty);
+	struct timespec ts;
+
+	if (ld && ld->ops->dcd_change)
+		getnstimeofday(&ts);
 
 	uport->icount.dcd++;
-
 #ifdef CONFIG_HARD_PPS
 	if ((uport->flags & UPF_HARDPPS_CD) && status)
 		hardpps();
@@ -505,6 +509,11 @@
 		else if (port->tty)
 			tty_hangup(port->tty);
 	}
+
+	if (ld && ld->ops->dcd_change)
+		ld->ops->dcd_change(port->tty, status, &ts);
+	if (ld)
+		tty_ldisc_deref(ld);
 }
 
 /**
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index 1c297dd..1b177d29 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -2,6 +2,7 @@
 #define __LINUX_SERIAL_SCI_H
 
 #include <linux/serial_core.h>
+#include <asm/dmaengine.h>
 
 /*
  * Generic header for SuperH SCI(F) (used by sh/sh64/h8300 and related parts)
@@ -16,6 +17,8 @@
 	SCIx_NR_IRQS,
 };
 
+struct device;
+
 /*
  * Platform device specific platform_data struct
  */
@@ -26,6 +29,9 @@
 	unsigned int	type;			/* SCI / SCIF / IRDA */
 	upf_t		flags;			/* UPF_* flags */
 	char		*clk;			/* clock string */
+	struct device	*dma_dev;
+	enum sh_dmae_slave_chan_id dma_slave_tx;
+	enum sh_dmae_slave_chan_id dma_slave_rx;
 };
 
 #endif /* __LINUX_SERIAL_SCI_H */
diff --git a/include/linux/signal.h b/include/linux/signal.h
index ab9272c..fcd2b14 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -7,6 +7,8 @@
 #ifdef __KERNEL__
 #include <linux/list.h>
 
+/* for sysctl */
+extern int print_fatal_signals;
 /*
  * Real Time signals may be queued.
  */
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 2da8372..4884462 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -70,6 +70,11 @@
 #else
 # define SLAB_NOTRACK		0x00000000UL
 #endif
+#ifdef CONFIG_FAILSLAB
+# define SLAB_FAILSLAB		0x02000000UL	/* Fault injection mark */
+#else
+# define SLAB_FAILSLAB		0x00000000UL
+#endif
 
 /* The following flags affect the page allocator grouping pages by mobility */
 #define SLAB_RECLAIM_ACCOUNT	0x00020000UL		/* Objects are reclaimable */
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 1e14beb..0249d41 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -38,8 +38,6 @@
 	void **freelist;	/* Pointer to first free per cpu object */
 	struct page *page;	/* The slab from which we are allocating */
 	int node;		/* The node of the page (or -1 for debug) */
-	unsigned int offset;	/* Freepointer offset (in word units) */
-	unsigned int objsize;	/* Size of an object (from kmem_cache) */
 #ifdef CONFIG_SLUB_STATS
 	unsigned stat[NR_SLUB_STAT_ITEMS];
 #endif
@@ -69,6 +67,7 @@
  * Slab cache management.
  */
 struct kmem_cache {
+	struct kmem_cache_cpu *cpu_slab;
 	/* Used for retriving partial slabs etc */
 	unsigned long flags;
 	int size;		/* The size of an object including meta data */
@@ -104,11 +103,6 @@
 	int remote_node_defrag_ratio;
 	struct kmem_cache_node *node[MAX_NUMNODES];
 #endif
-#ifdef CONFIG_SMP
-	struct kmem_cache_cpu *cpu_slab[NR_CPUS];
-#else
-	struct kmem_cache_cpu cpu_slab;
-#endif
 };
 
 /*
@@ -135,11 +129,21 @@
 
 #define SLUB_PAGE_SHIFT (PAGE_SHIFT + 2)
 
+#ifdef CONFIG_ZONE_DMA
+#define SLUB_DMA __GFP_DMA
+/* Reserve extra caches for potential DMA use */
+#define KMALLOC_CACHES (2 * SLUB_PAGE_SHIFT - 6)
+#else
+/* Disable DMA functionality */
+#define SLUB_DMA (__force gfp_t)0
+#define KMALLOC_CACHES SLUB_PAGE_SHIFT
+#endif
+
 /*
  * We keep the general caches in an array of slab caches that are used for
  * 2^x bytes of allocations.
  */
-extern struct kmem_cache kmalloc_caches[SLUB_PAGE_SHIFT];
+extern struct kmem_cache kmalloc_caches[KMALLOC_CACHES];
 
 /*
  * Sorry that the following has to be that ugly but some versions of GCC
@@ -207,13 +211,6 @@
 	return &kmalloc_caches[index];
 }
 
-#ifdef CONFIG_ZONE_DMA
-#define SLUB_DMA __GFP_DMA
-#else
-/* Disable DMA functionality */
-#define SLUB_DMA (__force gfp_t)0
-#endif
-
 void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
 void *__kmalloc(size_t size, gfp_t flags);
 
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 7a0570e..cfa2d20 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -154,7 +154,7 @@
 /*
  * smp_processor_id(): get the current CPU ID.
  *
- * if DEBUG_PREEMPT is enabled the we check whether it is
+ * if DEBUG_PREEMPT is enabled then we check whether it is
  * used in a preemption-safe way. (smp_processor_id() is safe
  * if it's used in a preemption-off critical section, or in
  * a thread that is bound to the current CPU.)
diff --git a/include/linux/spi/max7301.h b/include/linux/spi/max7301.h
index 6dfd83f..34af0a3 100644
--- a/include/linux/spi/max7301.h
+++ b/include/linux/spi/max7301.h
@@ -1,9 +1,27 @@
 #ifndef LINUX_SPI_MAX7301_H
 #define LINUX_SPI_MAX7301_H
 
+#include <linux/gpio.h>
+
+/*
+ * Some registers must be read back to modify.
+ * To save time we cache them here in memory
+ */
+struct max7301 {
+	struct mutex	lock;
+	u8		port_config[8];	/* field 0 is unused */
+	u32		out_level;	/* cached output levels */
+	struct gpio_chip chip;
+	struct device *dev;
+	int (*write)(struct device *dev, unsigned int reg, unsigned int val);
+	int (*read)(struct device *dev, unsigned int reg);
+};
+
 struct max7301_platform_data {
 	/* number assigned to the first GPIO */
 	unsigned	base;
 };
 
+extern int __max730x_remove(struct device *dev);
+extern int __max730x_probe(struct max7301 *ts);
 #endif
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 8608821..89fac6a 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -128,19 +128,21 @@
 #define raw_spin_unlock_wait(lock)	arch_spin_unlock_wait(&(lock)->raw_lock)
 
 #ifdef CONFIG_DEBUG_SPINLOCK
- extern void do_raw_spin_lock(raw_spinlock_t *lock);
+ extern void do_raw_spin_lock(raw_spinlock_t *lock) __acquires(lock);
 #define do_raw_spin_lock_flags(lock, flags) do_raw_spin_lock(lock)
  extern int do_raw_spin_trylock(raw_spinlock_t *lock);
- extern void do_raw_spin_unlock(raw_spinlock_t *lock);
+ extern void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock);
 #else
-static inline void do_raw_spin_lock(raw_spinlock_t *lock)
+static inline void do_raw_spin_lock(raw_spinlock_t *lock) __acquires(lock)
 {
+	__acquire(lock);
 	arch_spin_lock(&lock->raw_lock);
 }
 
 static inline void
-do_raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long *flags)
+do_raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long *flags) __acquires(lock)
 {
+	__acquire(lock);
 	arch_spin_lock_flags(&lock->raw_lock, *flags);
 }
 
@@ -149,9 +151,10 @@
 	return arch_spin_trylock(&(lock)->raw_lock);
 }
 
-static inline void do_raw_spin_unlock(raw_spinlock_t *lock)
+static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
 {
 	arch_spin_unlock(&lock->raw_lock);
+	__release(lock);
 }
 #endif
 
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 3084f80..4d5ecb2 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -33,7 +33,7 @@
 
 struct srcu_struct {
 	int completed;
-	struct srcu_struct_array *per_cpu_ref;
+	struct srcu_struct_array __percpu *per_cpu_ref;
 	struct mutex mutex;
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 	struct lockdep_map dep_map;
diff --git a/include/linux/sunrpc/bc_xprt.h b/include/linux/sunrpc/bc_xprt.h
index 6508f0d..d7152b4 100644
--- a/include/linux/sunrpc/bc_xprt.h
+++ b/include/linux/sunrpc/bc_xprt.h
@@ -38,12 +38,27 @@
 void xprt_destroy_backchannel(struct rpc_xprt *, int max_reqs);
 void bc_release_request(struct rpc_task *);
 int bc_send(struct rpc_rqst *req);
+
+/*
+ * Determine if a shared backchannel is in use
+ */
+static inline int svc_is_backchannel(const struct svc_rqst *rqstp)
+{
+	if (rqstp->rq_server->bc_xprt)
+		return 1;
+	return 0;
+}
 #else /* CONFIG_NFS_V4_1 */
 static inline int xprt_setup_backchannel(struct rpc_xprt *xprt,
 					 unsigned int min_reqs)
 {
 	return 0;
 }
+
+static inline int svc_is_backchannel(const struct svc_rqst *rqstp)
+{
+	return 0;
+}
 #endif /* CONFIG_NFS_V4_1 */
 #endif /* _LINUX_SUNRPC_BC_XPRT_H */
 
diff --git a/include/linux/swap.h b/include/linux/swap.h
index a2602a8..1f59d93 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -355,6 +355,7 @@
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 extern void
 mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout);
+extern int mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep);
 #else
 static inline void
 mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
@@ -485,6 +486,14 @@
 {
 }
 
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+static inline int
+mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep)
+{
+	return 0;
+}
+#endif
+
 #endif /* CONFIG_SWAP */
 #endif /* __KERNEL__*/
 #endif /* _LINUX_SWAP_H */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 8126f23..44f2ad0 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -23,6 +23,7 @@
 struct linux_dirent;
 struct linux_dirent64;
 struct list_head;
+struct mmap_arg_struct;
 struct msgbuf;
 struct msghdr;
 struct mmsghdr;
@@ -30,10 +31,13 @@
 struct new_utsname;
 struct nfsctl_arg;
 struct __old_kernel_stat;
+struct oldold_utsname;
+struct old_utsname;
 struct pollfd;
 struct rlimit;
 struct rusage;
 struct sched_param;
+struct sel_arg_struct;
 struct semaphore;
 struct sembuf;
 struct shmid_ds;
@@ -638,6 +642,7 @@
 				long timeout);
 asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
 			fd_set __user *exp, struct timeval __user *tvp);
+asmlinkage long sys_old_select(struct sel_arg_struct __user *arg);
 asmlinkage long sys_epoll_create(int size);
 asmlinkage long sys_epoll_create1(int flags);
 asmlinkage long sys_epoll_ctl(int epfd, int op, int fd,
@@ -652,6 +657,8 @@
 asmlinkage long sys_sethostname(char __user *name, int len);
 asmlinkage long sys_setdomainname(char __user *name, int len);
 asmlinkage long sys_newuname(struct new_utsname __user *name);
+asmlinkage long sys_uname(struct old_utsname __user *);
+asmlinkage long sys_olduname(struct oldold_utsname __user *);
 
 asmlinkage long sys_getrlimit(unsigned int resource,
 				struct rlimit __user *rlim);
@@ -681,6 +688,8 @@
 asmlinkage long sys_shmget(key_t key, size_t size, int flag);
 asmlinkage long sys_shmdt(char __user *shmaddr);
 asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
+asmlinkage long sys_ipc(unsigned int call, int first, int second,
+		unsigned long third, void __user *ptr, long fifth);
 
 asmlinkage long sys_mq_open(const char __user *name, int oflag, mode_t mode, struct mq_attr __user *attr);
 asmlinkage long sys_mq_unlink(const char __user *name);
@@ -836,4 +845,6 @@
 asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
 			unsigned long prot, unsigned long flags,
 			unsigned long fd, unsigned long pgoff);
+asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);
+
 #endif
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index f395bb3..1154c29 100644
--- a/include/linux/sysdev.h
+++ b/include/linux/sysdev.h
@@ -27,10 +27,12 @@
 
 
 struct sys_device;
+struct sysdev_class_attribute;
 
 struct sysdev_class {
 	const char *name;
 	struct list_head	drivers;
+	struct sysdev_class_attribute **attrs;
 
 	/* Default operations for these types of devices */
 	int	(*shutdown)(struct sys_device *);
@@ -41,8 +43,10 @@
 
 struct sysdev_class_attribute {
 	struct attribute attr;
-	ssize_t (*show)(struct sysdev_class *, char *);
-	ssize_t (*store)(struct sysdev_class *, const char *, size_t);
+	ssize_t (*show)(struct sysdev_class *, struct sysdev_class_attribute *,
+			char *);
+	ssize_t (*store)(struct sysdev_class *, struct sysdev_class_attribute *,
+			 const char *, size_t);
 };
 
 #define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) 		\
@@ -119,6 +123,19 @@
 extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
 extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
 
+/* Create/remove NULL terminated attribute list */
+static inline int
+sysdev_create_files(struct sys_device *d, struct sysdev_attribute **a)
+{
+	return sysfs_create_files(&d->kobj, (const struct attribute **)a);
+}
+
+static inline void
+sysdev_remove_files(struct sys_device *d, struct sysdev_attribute **a)
+{
+	return sysfs_remove_files(&d->kobj, (const struct attribute **)a);
+}
+
 struct sysdev_ext_attribute {
 	struct sysdev_attribute attr;
 	void *var;
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index cfa8308..f0496b3 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -15,6 +15,7 @@
 #include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/list.h>
+#include <linux/lockdep.h>
 #include <asm/atomic.h>
 
 struct kobject;
@@ -29,8 +30,33 @@
 	const char		*name;
 	struct module		*owner;
 	mode_t			mode;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	struct lock_class_key	*key;
+	struct lock_class_key	skey;
+#endif
 };
 
+/**
+ *	sysfs_attr_init - initialize a dynamically allocated sysfs attribute
+ *	@attr: struct attribute to initialize
+ *
+ *	Initialize a dynamically allocated struct attribute so we can
+ *	make lockdep happy.  This is a new requirement for attributes
+ *	and initially this is only needed when lockdep is enabled.
+ *	Lockdep gives a nice error when your attribute is added to
+ *	sysfs if you don't have this.
+ */
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#define sysfs_attr_init(attr)				\
+do {							\
+	static struct lock_class_key __key;		\
+							\
+	(attr)->key = &__key;				\
+} while(0)
+#else
+#define sysfs_attr_init(attr) do {} while(0)
+#endif
+
 struct attribute_group {
 	const char		*name;
 	mode_t			(*is_visible)(struct kobject *,
@@ -74,6 +100,18 @@
 		    struct vm_area_struct *vma);
 };
 
+/**
+ *	sysfs_bin_attr_init - initialize a dynamically allocated bin_attribute
+ *	@attr: struct bin_attribute to initialize
+ *
+ *	Initialize a dynamically allocated struct bin_attribute so we
+ *	can make lockdep happy.  This is a new requirement for
+ *	attributes and initially this is only needed when lockdep is
+ *	enabled.  Lockdep gives a nice error when your attribute is
+ *	added to sysfs if you don't have this.
+ */
+#define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
+
 struct sysfs_ops {
 	ssize_t	(*show)(struct kobject *, struct attribute *,char *);
 	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
@@ -94,9 +132,12 @@
 
 int __must_check sysfs_create_file(struct kobject *kobj,
 				   const struct attribute *attr);
+int __must_check sysfs_create_files(struct kobject *kobj,
+				   const struct attribute **attr);
 int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr,
 				  mode_t mode);
 void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
+void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr);
 
 int __must_check sysfs_create_bin_file(struct kobject *kobj,
 				       const struct bin_attribute *attr);
@@ -110,6 +151,9 @@
 					  const char *name);
 void sysfs_remove_link(struct kobject *kobj, const char *name);
 
+int sysfs_rename_link(struct kobject *kobj, struct kobject *target,
+			const char *old_name, const char *new_name);
+
 int __must_check sysfs_create_group(struct kobject *kobj,
 				    const struct attribute_group *grp);
 int sysfs_update_group(struct kobject *kobj,
@@ -164,6 +208,12 @@
 	return 0;
 }
 
+static inline int sysfs_create_files(struct kobject *kobj,
+				    const struct attribute **attr)
+{
+	return 0;
+}
+
 static inline int sysfs_chmod_file(struct kobject *kobj,
 				   struct attribute *attr, mode_t mode)
 {
@@ -175,6 +225,11 @@
 {
 }
 
+static inline void sysfs_remove_files(struct kobject *kobj,
+				     const struct attribute **attr)
+{
+}
+
 static inline int sysfs_create_bin_file(struct kobject *kobj,
 					const struct bin_attribute *attr)
 {
@@ -203,6 +258,12 @@
 {
 }
 
+static inline int sysfs_rename_link(struct kobject *k, struct kobject *t,
+				    const char *old_name, const char *new_name)
+{
+	return 0;
+}
+
 static inline int sysfs_create_group(struct kobject *kobj,
 				     const struct attribute_group *grp)
 {
diff --git a/include/linux/syslog.h b/include/linux/syslog.h
new file mode 100644
index 0000000..3891139
--- /dev/null
+++ b/include/linux/syslog.h
@@ -0,0 +1,52 @@
+/*  Syslog internals
+ *
+ *  Copyright 2010 Canonical, Ltd.
+ *  Author: Kees Cook <kees.cook@canonical.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LINUX_SYSLOG_H
+#define _LINUX_SYSLOG_H
+
+/* Close the log.  Currently a NOP. */
+#define SYSLOG_ACTION_CLOSE          0
+/* Open the log. Currently a NOP. */
+#define SYSLOG_ACTION_OPEN           1
+/* Read from the log. */
+#define SYSLOG_ACTION_READ           2
+/* Read all messages remaining in the ring buffer. */
+#define SYSLOG_ACTION_READ_ALL       3
+/* Read and clear all messages remaining in the ring buffer */
+#define SYSLOG_ACTION_READ_CLEAR     4
+/* Clear ring buffer. */
+#define SYSLOG_ACTION_CLEAR          5
+/* Disable printk's to console */
+#define SYSLOG_ACTION_CONSOLE_OFF    6
+/* Enable printk's to console */
+#define SYSLOG_ACTION_CONSOLE_ON     7
+/* Set level of messages printed to console */
+#define SYSLOG_ACTION_CONSOLE_LEVEL  8
+/* Return number of unread characters in the log buffer */
+#define SYSLOG_ACTION_SIZE_UNREAD    9
+/* Return size of the log buffer */
+#define SYSLOG_ACTION_SIZE_BUFFER   10
+
+#define SYSLOG_FROM_CALL 0
+#define SYSLOG_FROM_FILE 1
+
+int do_syslog(int type, char __user *buf, int count, bool from_file);
+
+#endif /* _LINUX_SYSLOG_H */
diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h
index 3398f45..b6523c1 100644
--- a/include/linux/taskstats_kern.h
+++ b/include/linux/taskstats_kern.h
@@ -14,11 +14,6 @@
 extern struct kmem_cache *taskstats_cache;
 extern struct mutex taskstats_exit_mutex;
 
-static inline void taskstats_tgid_init(struct signal_struct *sig)
-{
-	sig->stats = NULL;
-}
-
 static inline void taskstats_tgid_free(struct signal_struct *sig)
 {
 	if (sig->stats)
@@ -30,8 +25,6 @@
 #else
 static inline void taskstats_exit(struct task_struct *tsk, int group_dead)
 {}
-static inline void taskstats_tgid_init(struct signal_struct *sig)
-{}
 static inline void taskstats_tgid_free(struct signal_struct *sig)
 {}
 static inline void taskstats_init_early(void)
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 6abfcf5..568369a 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -68,6 +68,16 @@
 	unsigned long data[0];
 };
 
+/*
+ * We default to dicing tty buffer allocations to this many characters
+ * in order to avoid multiple page allocations. We assume tty_buffer itself
+ * is under 256 bytes. See tty_buffer_find for the allocation logic this
+ * must match
+ */
+
+#define TTY_BUFFER_PAGE		((PAGE_SIZE  - 256) / 2)
+
+
 struct tty_bufhead {
 	struct delayed_work work;
 	spinlock_t lock;
@@ -504,6 +514,7 @@
 
 /* n_tty.c */
 extern struct tty_ldisc_ops tty_ldisc_N_TTY;
+extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
 
 /* tty_audit.c */
 #ifdef CONFIG_AUDIT
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index eb677cf..9239d03 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -2,8 +2,8 @@
 #define _LINUX_TTY_FLIP_H
 
 extern int tty_buffer_request_room(struct tty_struct *tty, size_t size);
-extern int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size);
 extern int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size);
+extern int tty_insert_flip_string_fixed_flag(struct tty_struct *tty, const unsigned char *chars, char flag, size_t size);
 extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size);
 extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size);
 void tty_schedule_flip(struct tty_struct *tty);
@@ -20,4 +20,9 @@
 	return tty_insert_flip_string_flags(tty, &ch, &flag, 1);
 }
 
+static inline int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size)
+{
+	return tty_insert_flip_string_fixed_flag(tty, chars, TTY_NORMAL, size);
+}
+
 #endif /* _LINUX_TTY_FLIP_H */
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index 0c4ee9b..526d66f 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -99,6 +99,12 @@
  *	cease I/O to the tty driver. Can sleep. The driver should
  *	seek to perform this action quickly but should wait until
  *	any pending driver I/O is completed.
+ *
+ * void (*dcd_change)(struct tty_struct *tty, unsigned int status,
+ * 			struct timespec *ts)
+ *
+ *	Tells the discipline that the DCD pin has changed its status and
+ *	the relative timestamp. Pointer ts can be NULL.
  */
 
 #include <linux/fs.h>
@@ -136,6 +142,8 @@
 	void	(*receive_buf)(struct tty_struct *, const unsigned char *cp,
 			       char *fp, int count);
 	void	(*write_wakeup)(struct tty_struct *);
+	void	(*dcd_change)(struct tty_struct *, unsigned int,
+				struct timespec *);
 
 	struct  module *owner;
 	
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 332eaea..8c9f053 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -122,7 +122,6 @@
  *	number from the USB core by calling usb_register_dev().
  * @condition: binding state of the interface: not bound, binding
  *	(in probe()), bound to a driver, or unbinding (in disconnect())
- * @is_active: flag set when the interface is bound and not suspended.
  * @sysfs_files_created: sysfs attributes exist
  * @ep_devs_created: endpoint child pseudo-devices exist
  * @unregistering: flag set when the interface is being unregistered
@@ -135,8 +134,7 @@
  * @dev: driver model's view of this device
  * @usb_dev: if an interface is bound to the USB major, this will point
  *	to the sysfs representation for that device.
- * @pm_usage_cnt: PM usage counter for this interface; autosuspend is not
- *	allowed unless the counter is 0.
+ * @pm_usage_cnt: PM usage counter for this interface
  * @reset_ws: Used for scheduling resets from atomic context.
  * @reset_running: set to 1 if the interface is currently running a
  *      queued reset so that usb_cancel_queued_reset() doesn't try to
@@ -184,7 +182,6 @@
 	int minor;			/* minor number this interface is
 					 * bound to */
 	enum usb_interface_condition condition;		/* state of binding */
-	unsigned is_active:1;		/* the interface is not suspended */
 	unsigned sysfs_files_created:1;	/* the sysfs attributes exist */
 	unsigned ep_devs_created:1;	/* endpoint "devices" exist */
 	unsigned unregistering:1;	/* unregistration is in progress */
@@ -401,7 +398,6 @@
  * @portnum: parent port number (origin 1)
  * @level: number of USB hub ancestors
  * @can_submit: URBs may be submitted
- * @discon_suspended: disconnected while suspended
  * @persist_enabled:  USB_PERSIST enabled for this device
  * @have_langid: whether string_langid is valid
  * @authorized: policy has said we can use it;
@@ -421,20 +417,15 @@
  * @usbfs_dentry: usbfs dentry entry for the device
  * @maxchild: number of ports if hub
  * @children: child devices - USB devices that are attached to this hub
- * @pm_usage_cnt: usage counter for autosuspend
  * @quirks: quirks of the whole device
  * @urbnum: number of URBs submitted for the whole device
  * @active_duration: total time device is not suspended
- * @autosuspend: for delayed autosuspends
- * @autoresume: for autoresumes requested while in_interrupt
- * @pm_mutex: protects PM operations
  * @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
  * @autosuspend_disabled: autosuspend disabled by the user
- * @skip_sys_resume: skip the next system resume
  * @wusb_dev: if this is a Wireless USB device, link to the WUSB
  *	specific data for the device.
  * @slot_id: Slot ID assigned by xHCI
@@ -475,7 +466,6 @@
 	u8 level;
 
 	unsigned can_submit:1;
-	unsigned discon_suspended:1;
 	unsigned persist_enabled:1;
 	unsigned have_langid:1;
 	unsigned authorized:1;
@@ -499,17 +489,12 @@
 	int maxchild;
 	struct usb_device *children[USB_MAXCHILDREN];
 
-	int pm_usage_cnt;
 	u32 quirks;
 	atomic_t urbnum;
 
 	unsigned long active_duration;
 
 #ifdef CONFIG_PM
-	struct delayed_work autosuspend;
-	struct work_struct autoresume;
-	struct mutex pm_mutex;
-
 	unsigned long last_busy;
 	int autosuspend_delay;
 	unsigned long connect_time;
@@ -517,7 +502,6 @@
 	unsigned do_remote_wakeup:1;
 	unsigned reset_resume:1;
 	unsigned autosuspend_disabled:1;
-	unsigned skip_sys_resume:1;
 #endif
 	struct wusb_dev *wusb_dev;
 	int slot_id;
@@ -528,9 +512,9 @@
 extern void usb_put_dev(struct usb_device *dev);
 
 /* USB device locking */
-#define usb_lock_device(udev)		down(&(udev)->dev.sem)
-#define usb_unlock_device(udev)		up(&(udev)->dev.sem)
-#define usb_trylock_device(udev)	down_trylock(&(udev)->dev.sem)
+#define usb_lock_device(udev)		device_lock(&(udev)->dev)
+#define usb_unlock_device(udev)		device_unlock(&(udev)->dev)
+#define usb_trylock_device(udev)	device_trylock(&(udev)->dev)
 extern int usb_lock_device_for_reset(struct usb_device *udev,
 				     const struct usb_interface *iface);
 
@@ -542,21 +526,15 @@
 
 /* USB autosuspend and autoresume */
 #ifdef CONFIG_USB_SUSPEND
+extern int usb_enable_autosuspend(struct usb_device *udev);
+extern int usb_disable_autosuspend(struct usb_device *udev);
+
 extern int usb_autopm_get_interface(struct usb_interface *intf);
 extern void usb_autopm_put_interface(struct usb_interface *intf);
 extern int usb_autopm_get_interface_async(struct usb_interface *intf);
 extern void usb_autopm_put_interface_async(struct usb_interface *intf);
-
-static inline void usb_autopm_get_interface_no_resume(
-		struct usb_interface *intf)
-{
-	atomic_inc(&intf->pm_usage_cnt);
-}
-static inline void usb_autopm_put_interface_no_suspend(
-		struct usb_interface *intf)
-{
-	atomic_dec(&intf->pm_usage_cnt);
-}
+extern void usb_autopm_get_interface_no_resume(struct usb_interface *intf);
+extern void usb_autopm_put_interface_no_suspend(struct usb_interface *intf);
 
 static inline void usb_mark_last_busy(struct usb_device *udev)
 {
@@ -565,6 +543,11 @@
 
 #else
 
+static inline int usb_enable_autosuspend(struct usb_device *udev)
+{ return 0; }
+static inline int usb_disable_autosuspend(struct usb_device *udev)
+{ return 0; }
+
 static inline int usb_autopm_get_interface(struct usb_interface *intf)
 { return 0; }
 static inline int usb_autopm_get_interface_async(struct usb_interface *intf)
@@ -1583,14 +1566,18 @@
 extern void usb_unregister_notify(struct notifier_block *nb);
 
 #ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
-	__FILE__ , ## arg)
+#define dbg(format, arg...)						\
+	printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg)
 #else
-#define dbg(format, arg...) do {} while (0)
+#define dbg(format, arg...)						\
+do {									\
+	if (0)								\
+		printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \
+} while (0)
 #endif
 
-#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \
-	format "\n" , ## arg)
+#define err(format, arg...)					\
+	printk(KERN_ERR KBUILD_MODNAME ": " format "\n", ##arg)
 
 /* debugfs stuff */
 extern struct dentry *usb_debug_root;
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
index 54c4463..29fd73b 100644
--- a/include/linux/usb/Kbuild
+++ b/include/linux/usb/Kbuild
@@ -5,4 +5,3 @@
 header-y += midi.h
 header-y += g_printer.h
 header-y += tmc.h
-header-y += vstusb.h
diff --git a/include/linux/usb/atmel_usba_udc.h b/include/linux/usb/atmel_usba_udc.h
index 6311fa2..baf41c8 100644
--- a/include/linux/usb/atmel_usba_udc.h
+++ b/include/linux/usb/atmel_usba_udc.h
@@ -15,6 +15,7 @@
 
 struct usba_platform_data {
 	int			vbus_pin;
+	int		 	vbus_pin_inverted;
 	int			num_ep;
 	struct usba_ep_data	ep[0];
 };
diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
index 6bb2936..4d3e450 100644
--- a/include/linux/usb/audio.h
+++ b/include/linux/usb/audio.h
@@ -269,8 +269,8 @@
 	__u8 bLength;
 	__u8 bDescriptorType;
 	__u8 bDescriptorSubtype;
-	__u8 bSubslotSize;
 	__u8 bFormatType;
+	__u8 bSubslotSize;
 	__u8 bBitResolution;
 	__u8 bHeaderLength;
 	__u8 bControlSize;
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index 94012e6..e58369f 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -775,7 +775,7 @@
 	USB_SPEED_UNKNOWN = 0,			/* enumerating */
 	USB_SPEED_LOW, USB_SPEED_FULL,		/* usb 1.1 */
 	USB_SPEED_HIGH,				/* usb 2.0 */
-	USB_SPEED_VARIABLE,			/* wireless (usb 2.5) */
+	USB_SPEED_WIRELESS,			/* wireless (usb 2.5) */
 	USB_SPEED_SUPER,			/* usb 3.0 */
 };
 
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index 5dc2f22..7acef02 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -30,26 +30,26 @@
 struct musb_hdrc_config {
 	/* MUSB configuration-specific details */
 	unsigned	multipoint:1;	/* multipoint device */
-	unsigned	dyn_fifo:1;	/* supports dynamic fifo sizing */
-	unsigned	soft_con:1;	/* soft connect required */
-	unsigned	utm_16:1;	/* utm data witdh is 16 bits */
+	unsigned	dyn_fifo:1 __deprecated; /* supports dynamic fifo sizing */
+	unsigned	soft_con:1 __deprecated; /* soft connect required */
+	unsigned	utm_16:1 __deprecated; /* utm data witdh is 16 bits */
 	unsigned	big_endian:1;	/* true if CPU uses big-endian */
 	unsigned	mult_bulk_tx:1;	/* Tx ep required for multbulk pkts */
 	unsigned	mult_bulk_rx:1;	/* Rx ep required for multbulk pkts */
 	unsigned	high_iso_tx:1;	/* Tx ep required for HB iso */
 	unsigned	high_iso_rx:1;	/* Rx ep required for HD iso */
-	unsigned	dma:1;		/* supports DMA */
-	unsigned	vendor_req:1;	/* vendor registers required */
+	unsigned	dma:1 __deprecated; /* supports DMA */
+	unsigned	vendor_req:1 __deprecated; /* vendor registers required */
 
 	u8		num_eps;	/* number of endpoints _with_ ep0 */
-	u8		dma_channels;	/* number of dma channels */
+	u8		dma_channels __deprecated; /* number of dma channels */
 	u8		dyn_fifo_size;	/* dynamic size in bytes */
-	u8		vendor_ctrl;	/* vendor control reg width */
-	u8		vendor_stat;	/* vendor status reg witdh */
-	u8		dma_req_chan;	/* bitmask for required dma channels */
+	u8		vendor_ctrl __deprecated; /* vendor control reg width */
+	u8		vendor_stat __deprecated; /* vendor status reg witdh */
+	u8		dma_req_chan __deprecated; /* bitmask for required dma channels */
 	u8		ram_bits;	/* ram address size */
 
-	struct musb_hdrc_eps_bits *eps_bits;
+	struct musb_hdrc_eps_bits *eps_bits __deprecated;
 #ifdef CONFIG_BLACKFIN
         /* A GPIO controlling VRSEL in Blackfin */
         unsigned int    gpio_vrsel;
@@ -76,6 +76,9 @@
 	/* (HOST or OTG) msec/2 after VBUS on till power good */
 	u8		potpgt;
 
+	/* (HOST or OTG) program PHY for external Vbus */
+	unsigned	extvbus:1;
+
 	/* Power the device on or off */
 	int		(*set_power)(int state);
 
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index fef0972..f8302d0 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -9,6 +9,8 @@
 #ifndef __LINUX_USB_OTG_H
 #define __LINUX_USB_OTG_H
 
+#include <linux/notifier.h>
+
 /* OTG defines lots of enumeration states before device reset */
 enum usb_otg_state {
 	OTG_STATE_UNDEFINED = 0,
@@ -33,6 +35,14 @@
 	OTG_STATE_A_VBUS_ERR,
 };
 
+enum usb_xceiv_events {
+	USB_EVENT_NONE,         /* no events or cable disconnected */
+	USB_EVENT_VBUS,         /* vbus valid event */
+	USB_EVENT_ID,           /* id was grounded */
+	USB_EVENT_CHARGER,      /* usb dedicated charger */
+	USB_EVENT_ENUMERATED,   /* gadget driver enumerated */
+};
+
 #define USB_OTG_PULLUP_ID		(1 << 0)
 #define USB_OTG_PULLDOWN_DP		(1 << 1)
 #define USB_OTG_PULLDOWN_DM		(1 << 2)
@@ -70,6 +80,9 @@
 	struct otg_io_access_ops	*io_ops;
 	void __iomem			*io_priv;
 
+	/* for notification of usb_xceiv_events */
+	struct blocking_notifier_head	notifier;
+
 	/* to pass extra port status to the root hub */
 	u16			port_status;
 	u16			port_change;
@@ -213,6 +226,18 @@
 	return otg->start_srp(otg);
 }
 
+/* notifiers */
+static inline int
+otg_register_notifier(struct otg_transceiver *otg, struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&otg->notifier, nb);
+}
+
+static inline void
+otg_unregister_notifier(struct otg_transceiver *otg, struct notifier_block *nb)
+{
+	blocking_notifier_chain_unregister(&otg->notifier, nb);
+}
 
 /* for OTG controller drivers (and maybe other stuff) */
 extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index 2526f3b..0a555dd 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -19,4 +19,7 @@
 /* device can't handle its Configuration or Interface strings */
 #define USB_QUIRK_CONFIG_INTF_STRINGS	0x00000008
 
+/*device will morph if reset, don't use reset for handling errors */
+#define USB_QUIRK_RESET_MORPHS		0x00000010
+
 #endif /* __LINUX_USB_QUIRKS_H */
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 1819396..0a458b8 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -351,14 +351,11 @@
 
 /* Use our own dbg macro */
 #undef dbg
-#define dbg(format, arg...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , \
-				## arg); \
-	} while (0)
-
-
+#define dbg(format, arg...)						\
+do {									\
+	if (debug)							\
+		printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg);	\
+} while (0)
 
 #endif /* __LINUX_USB_SERIAL_H */
 
diff --git a/include/linux/usb/vstusb.h b/include/linux/usb/vstusb.h
deleted file mode 100644
index 1cfac67..0000000
--- a/include/linux/usb/vstusb.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*****************************************************************************
- *  File: drivers/usb/misc/vstusb.h
- *
- *  Purpose: Support for the bulk USB Vernier Spectrophotometers
- *
- *  Author:     EQware Engineering, Inc.
- *              Oregon City, OR, USA 97045
- *
- *  Copyright:  2007, 2008
- *              Vernier Software & Technology
- *              Beaverton, OR, USA 97005
- *
- *  Web:        www.vernier.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.
- *
- *****************************************************************************/
-/*****************************************************************************
- *
- *  The vstusb module is a standard usb 'client' driver running on top of the
- *  standard usb host controller stack.
- *
- *  In general, vstusb supports standard bulk usb pipes.  It supports multiple
- *  devices and multiple pipes per device.
- *
- *  The vstusb driver supports two interfaces:
- *  1 - ioctl SEND_PIPE/RECV_PIPE - a general bulk write/read msg
- *  	interface to any pipe with timeout support;
- *  2 - standard read/write with ioctl config - offers standard read/write
- *  	interface with ioctl configured pipes and timeouts.
- *
- *  Both interfaces can be signal from other process and will abort its i/o
- *  operation.
- *
- *  A timeout of 0 means NO timeout.  The user can still terminate the read via
- *  signal.
- *
- *  If using multiple threads with this driver, the user should ensure that
- *  any reads, writes, or ioctls are complete before closing the device.
- *  Changing read/write timeouts or pipes takes effect on next read/write.
- *
- *****************************************************************************/
-
-struct vstusb_args {
-	union {
-		/* this struct is used for IOCTL_VSTUSB_SEND_PIPE,	*
-		 * IOCTL_VSTUSB_RECV_PIPE, and read()/write() fops	*/
-		struct {
-			void __user	*buffer;
-			size_t          count;
-			unsigned int    timeout_ms;
-			int             pipe;
-		};
-
-		/* this one is used for IOCTL_VSTUSB_CONFIG_RW  	*/
-		struct {
-			int rd_pipe;
-			int rd_timeout_ms;
-			int wr_pipe;
-			int wr_timeout_ms;
-		};
-	};
-};
-
-#define VST_IOC_MAGIC 'L'
-#define VST_IOC_FIRST 0x20
-#define IOCTL_VSTUSB_SEND_PIPE	_IO(VST_IOC_MAGIC, VST_IOC_FIRST)
-#define IOCTL_VSTUSB_RECV_PIPE	_IO(VST_IOC_MAGIC, VST_IOC_FIRST + 1)
-#define IOCTL_VSTUSB_CONFIG_RW	_IO(VST_IOC_MAGIC, VST_IOC_FIRST + 2)
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
new file mode 100644
index 0000000..ae9ab13
--- /dev/null
+++ b/include/linux/vga_switcheroo.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010 Red Hat Inc.
+ * Author : Dave Airlie <airlied@redhat.com>
+ *
+ * Licensed under GPLv2
+ *
+ * vga_switcheroo.h - Support for laptop with dual GPU using one set of outputs
+ */
+
+#include <linux/fb.h>
+
+enum vga_switcheroo_state {
+	VGA_SWITCHEROO_OFF,
+	VGA_SWITCHEROO_ON,
+};
+
+enum vga_switcheroo_client_id {
+	VGA_SWITCHEROO_IGD,
+	VGA_SWITCHEROO_DIS,
+	VGA_SWITCHEROO_MAX_CLIENTS,
+};
+
+struct vga_switcheroo_handler {
+	int (*switchto)(enum vga_switcheroo_client_id id);
+	int (*power_state)(enum vga_switcheroo_client_id id,
+			   enum vga_switcheroo_state state);
+	int (*init)(void);
+	int (*get_client_id)(struct pci_dev *pdev);
+};
+
+
+#if defined(CONFIG_VGA_SWITCHEROO)
+void vga_switcheroo_unregister_client(struct pci_dev *dev);
+int vga_switcheroo_register_client(struct pci_dev *dev,
+				   void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state),
+				   bool (*can_switch)(struct pci_dev *dev));
+
+void vga_switcheroo_client_fb_set(struct pci_dev *dev,
+				  struct fb_info *info);
+
+int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler);
+void vga_switcheroo_unregister_handler(void);
+
+int vga_switcheroo_process_delayed_switch(void);
+
+#else
+
+static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
+static inline int vga_switcheroo_register_client(struct pci_dev *dev,
+					  void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state),
+					  bool (*can_switch)(struct pci_dev *dev)) { return 0; }
+static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {}
+static inline int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) { return 0; }
+static inline void vga_switcheroo_unregister_handler(void) {}
+static inline int vga_switcheroo_process_delayed_switch(void) { return 0; }
+
+#endif
diff --git a/include/linux/virtio_9p.h b/include/linux/virtio_9p.h
index 095e10d..3322750 100644
--- a/include/linux/virtio_9p.h
+++ b/include/linux/virtio_9p.h
@@ -5,7 +5,4 @@
 #include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 
-/* Maximum number of virtio channels per partition (1 for now) */
-#define MAX_9P_CHAN	1
-
 #endif /* _LINUX_VIRTIO_9P_H */
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index ee03bba..117f0dd 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -78,22 +78,22 @@
 
 static inline void __count_vm_event(enum vm_event_item item)
 {
-	__this_cpu_inc(per_cpu_var(vm_event_states).event[item]);
+	__this_cpu_inc(vm_event_states.event[item]);
 }
 
 static inline void count_vm_event(enum vm_event_item item)
 {
-	this_cpu_inc(per_cpu_var(vm_event_states).event[item]);
+	this_cpu_inc(vm_event_states.event[item]);
 }
 
 static inline void __count_vm_events(enum vm_event_item item, long delta)
 {
-	__this_cpu_add(per_cpu_var(vm_event_states).event[item], delta);
+	__this_cpu_add(vm_event_states.event[item], delta);
 }
 
 static inline void count_vm_events(enum vm_event_item item, long delta)
 {
-	this_cpu_add(per_cpu_var(vm_event_states).event[item], delta);
+	this_cpu_add(vm_event_states.event[item], delta);
 }
 
 extern void all_vm_events(unsigned long *);
diff --git a/include/linux/vt.h b/include/linux/vt.h
index d5dd0bc..778b7b2 100644
--- a/include/linux/vt.h
+++ b/include/linux/vt.h
@@ -27,7 +27,7 @@
 #define VT_SETMODE	0x5602	/* set mode of active vt */
 #define		VT_AUTO		0x00	/* auto vt switching */
 #define		VT_PROCESS	0x01	/* process controls switching */
-#define		VT_ACKACQ	0x02	/* acknowledge switch */
+#define		VT_PROCESS_AUTO 0x02	/* process is notified of switching */
 
 struct vt_stat {
 	unsigned short v_active;	/* active vt */
@@ -38,6 +38,7 @@
 #define VT_SENDSIG	0x5604	/* signal to send to bitmask of vts */
 
 #define VT_RELDISP	0x5605	/* release display */
+#define		VT_ACKACQ	0x02	/* acknowledge switch */
 
 #define VT_ACTIVATE	0x5606	/* make vt active */
 #define VT_WAITACTIVE	0x5607	/* wait for vt active */
diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h
index f456534..fd88226 100644
--- a/include/math-emu/op-common.h
+++ b/include/math-emu/op-common.h
@@ -29,7 +29,7 @@
   _FP_FRAC_DECL_##wc(X)
 
 /*
- * Finish truely unpacking a native fp value by classifying the kind
+ * Finish truly unpacking a native fp value by classifying the kind
  * of fp value and normalizing both the exponent and the fraction.
  */
 
diff --git a/include/media/davinci/vpfe_capture.h b/include/media/davinci/vpfe_capture.h
index d863e5e..4314a5f 100644
--- a/include/media/davinci/vpfe_capture.h
+++ b/include/media/davinci/vpfe_capture.h
@@ -165,7 +165,7 @@
 	u8 started;
 	/*
 	 * offset where second field starts from the starting of the
-	 * buffer for field seperated YCbCr formats
+	 * buffer for field separated YCbCr formats
 	 */
 	u32 field_off;
 };
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index fb00b32..52e1fff 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -29,6 +29,19 @@
 /* Number of requests per row */
 #define P9_ROW_MAXTAG 255
 
+/** enum p9_proto_versions - 9P protocol versions
+ * @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u
+ * @p9_proto_2000u: 9P2000.u extension
+ * @p9_proto_2010L: 9P2010.L extension
+ */
+
+enum p9_proto_versions{
+	p9_proto_legacy = 0,
+	p9_proto_2000u = 1,
+	p9_proto_2010L = 2,
+};
+
+
 /**
  * enum p9_trans_status - different states of underlying transports
  * @Connected: transport is connected and healthy
@@ -111,6 +124,7 @@
  * @lock: protect @fidlist
  * @msize: maximum data size negotiated by protocol
  * @dotu: extension flags negotiated by protocol
+ * @proto_version: 9P protocol version to use
  * @trans_mod: module API instantiated with this client
  * @trans: tranport instance state and API
  * @conn: connection state information used by trans_fd
@@ -137,7 +151,7 @@
 struct p9_client {
 	spinlock_t lock; /* protect client structure */
 	int msize;
-	unsigned char dotu;
+	unsigned char proto_version;
 	struct p9_trans_module *trans_mod;
 	enum p9_trans_status status;
 	void *trans;
@@ -209,5 +223,7 @@
 int p9stat_read(char *, int, struct p9_wstat *, int);
 void p9stat_free(struct p9_wstat *);
 
+int p9_is_proto_dotu(struct p9_client *clnt);
+int p9_is_proto_dotl(struct p9_client *clnt);
 
 #endif /* NET_9P_CLIENT_H */
diff --git a/include/net/irda/irttp.h b/include/net/irda/irttp.h
index 0788c23..11aee7a 100644
--- a/include/net/irda/irttp.h
+++ b/include/net/irda/irttp.h
@@ -97,7 +97,7 @@
 #define TTP_MAX_SDU_SIZE 0x01
 
 /*
- *  This structure contains all data assosiated with one instance of a TTP 
+ *  This structure contains all data associated with one instance of a TTP 
  *  connection.
  */
 struct tsap_cb {
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 82b7be4..bd10a79 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -100,14 +100,9 @@
 extern struct net init_net;
 
 #ifdef CONFIG_NET
-#define INIT_NET_NS(net_ns) .net_ns = &init_net,
-
 extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
 
 #else /* CONFIG_NET */
-
-#define INIT_NET_NS(net_ns)
-
 static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
 {
 	/* There is nothing to copy so this is a noop */
diff --git a/include/rdma/ib_pack.h b/include/rdma/ib_pack.h
index d7fc45c..cbb50f4 100644
--- a/include/rdma/ib_pack.h
+++ b/include/rdma/ib_pack.h
@@ -232,6 +232,7 @@
 
 void ib_ud_header_init(int     		   payload_bytes,
 		       int    		   grh_present,
+		       int		   immediate_present,
 		       struct ib_ud_header *header);
 
 int ib_ud_header_pack(struct ib_ud_header *header,
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 09509ed..a585e0f 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -984,9 +984,9 @@
 	struct list_head              event_handler_list;
 	spinlock_t                    event_handler_lock;
 
+	spinlock_t                    client_data_lock;
 	struct list_head              core_list;
 	struct list_head              client_data_list;
-	spinlock_t                    client_data_lock;
 
 	struct ib_cache               cache;
 	int                          *pkey_tbl_len;
@@ -1144,8 +1144,8 @@
 		IB_DEV_UNREGISTERED
 	}                            reg_state;
 
-	u64			     uverbs_cmd_mask;
 	int			     uverbs_abi_ver;
+	u64			     uverbs_cmd_mask;
 
 	char			     node_desc[64];
 	__be64			     node_guid;
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index c6b2962..4fae903 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -67,7 +67,6 @@
 	RDMA_PS_IPOIB = 0x0002,
 	RDMA_PS_TCP   = 0x0106,
 	RDMA_PS_UDP   = 0x0111,
-	RDMA_PS_SCTP  = 0x0183
 };
 
 struct rdma_addr {
diff --git a/include/scsi/sg.h b/include/scsi/sg.h
index 934ae38..a9f3c6f 100644
--- a/include/scsi/sg.h
+++ b/include/scsi/sg.h
@@ -70,6 +70,9 @@
  (for the lk 2.2 series).
 */
 
+#ifdef __KERNEL__
+extern int sg_big_buff; /* for sysctl */
+#endif
 
 /* New interface introduced in the 3.x SG drivers follows */
 
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 1f57bb9..0985955 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -544,7 +544,7 @@
  *  Timer section - /dev/snd/timer
  */
 
-#define SNDRV_TIMER_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 5)
+#define SNDRV_TIMER_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 6)
 
 enum {
 	SNDRV_TIMER_CLASS_NONE = -1,
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index d0b6cd3..2aa6aa3 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -874,6 +874,107 @@
 		  __entry->mode, __entry->is_metadata, __entry->block)
 );
 
+TRACE_EVENT(ext4_da_update_reserve_space,
+	TP_PROTO(struct inode *inode, int used_blocks),
+
+	TP_ARGS(inode, used_blocks),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	umode_t, mode			)
+		__field(	__u64,	i_blocks		)
+		__field(	int,	used_blocks		)
+		__field(	int,	reserved_data_blocks	)
+		__field(	int,	reserved_meta_blocks	)
+		__field(	int,	allocated_meta_blocks	)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->mode	= inode->i_mode;
+		__entry->i_blocks = inode->i_blocks;
+		__entry->used_blocks = used_blocks;
+		__entry->reserved_data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
+		__entry->reserved_meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
+		__entry->allocated_meta_blocks = EXT4_I(inode)->i_allocated_meta_blocks;
+	),
+
+	TP_printk("dev %s ino %lu mode 0%o i_blocks %llu used_blocks %d reserved_data_blocks %d reserved_meta_blocks %d allocated_meta_blocks %d",
+		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+		  __entry->mode,  (unsigned long long) __entry->i_blocks,
+		  __entry->used_blocks, __entry->reserved_data_blocks,
+		  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
+);
+
+TRACE_EVENT(ext4_da_reserve_space,
+	TP_PROTO(struct inode *inode, int md_needed),
+
+	TP_ARGS(inode, md_needed),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	umode_t, mode			)
+		__field(	__u64,	i_blocks		)
+		__field(	int,	md_needed		)
+		__field(	int,	reserved_data_blocks	)
+		__field(	int,	reserved_meta_blocks	)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->mode	= inode->i_mode;
+		__entry->i_blocks = inode->i_blocks;
+		__entry->md_needed = md_needed;
+		__entry->reserved_data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
+		__entry->reserved_meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
+	),
+
+	TP_printk("dev %s ino %lu mode 0%o i_blocks %llu md_needed %d reserved_data_blocks %d reserved_meta_blocks %d",
+		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+		  __entry->mode, (unsigned long long) __entry->i_blocks,
+		  __entry->md_needed, __entry->reserved_data_blocks,
+		  __entry->reserved_meta_blocks)
+);
+
+TRACE_EVENT(ext4_da_release_space,
+	TP_PROTO(struct inode *inode, int freed_blocks),
+
+	TP_ARGS(inode, freed_blocks),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	ino_t,	ino			)
+		__field(	umode_t, mode			)
+		__field(	__u64,	i_blocks		)
+		__field(	int,	freed_blocks		)
+		__field(	int,	reserved_data_blocks	)
+		__field(	int,	reserved_meta_blocks	)
+		__field(	int,	allocated_meta_blocks	)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= inode->i_sb->s_dev;
+		__entry->ino	= inode->i_ino;
+		__entry->mode	= inode->i_mode;
+		__entry->i_blocks = inode->i_blocks;
+		__entry->freed_blocks = freed_blocks;
+		__entry->reserved_data_blocks = EXT4_I(inode)->i_reserved_data_blocks;
+		__entry->reserved_meta_blocks = EXT4_I(inode)->i_reserved_meta_blocks;
+		__entry->allocated_meta_blocks = EXT4_I(inode)->i_allocated_meta_blocks;
+	),
+
+	TP_printk("dev %s ino %lu mode 0%o i_blocks %llu freed_blocks %d reserved_data_blocks %d reserved_meta_blocks %d allocated_meta_blocks %d",
+		  jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+		  __entry->mode, (unsigned long long) __entry->i_blocks,
+		  __entry->freed_blocks, __entry->reserved_data_blocks,
+		  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
+);
+
+
 #endif /* _TRACE_EXT4_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h
index 96b370a..bf16545 100644
--- a/include/trace/events/jbd2.h
+++ b/include/trace/events/jbd2.h
@@ -199,6 +199,34 @@
 		  __entry->forced_to_close, __entry->written, __entry->dropped)
 );
 
+TRACE_EVENT(jbd2_cleanup_journal_tail,
+
+	TP_PROTO(journal_t *journal, tid_t first_tid,
+		 unsigned long block_nr, unsigned long freed),
+
+	TP_ARGS(journal, first_tid, block_nr, freed),
+
+	TP_STRUCT__entry(
+		__field(	dev_t,	dev			)
+		__field(	tid_t,	tail_sequence		)
+		__field(	tid_t,	first_tid		)
+		__field(unsigned long,	block_nr		)
+		__field(unsigned long,	freed			)
+	),
+
+	TP_fast_assign(
+		__entry->dev		= journal->j_fs_dev->bd_dev;
+		__entry->tail_sequence	= journal->j_tail_sequence;
+		__entry->first_tid	= first_tid;
+		__entry->block_nr	= block_nr;
+		__entry->freed		= freed;
+	),
+
+	TP_printk("dev %s from %u to %u offset %lu freed %lu",
+		  jbd2_dev_to_name(__entry->dev), __entry->tail_sequence,
+		  __entry->first_tid, __entry->block_nr, __entry->freed)
+);
+
 #endif /* _TRACE_JBD2_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h
index dbe1084..b17d49d 100644
--- a/include/trace/events/kvm.h
+++ b/include/trace/events/kvm.h
@@ -145,6 +145,47 @@
 		  __entry->len, __entry->gpa, __entry->val)
 );
 
+#define kvm_fpu_load_symbol	\
+	{0, "unload"},		\
+	{1, "load"}
+
+TRACE_EVENT(kvm_fpu,
+	TP_PROTO(int load),
+	TP_ARGS(load),
+
+	TP_STRUCT__entry(
+		__field(	u32,	        load		)
+	),
+
+	TP_fast_assign(
+		__entry->load		= load;
+	),
+
+	TP_printk("%s", __print_symbolic(__entry->load, kvm_fpu_load_symbol))
+);
+
+TRACE_EVENT(kvm_age_page,
+	TP_PROTO(ulong hva, struct kvm_memory_slot *slot, int ref),
+	TP_ARGS(hva, slot, ref),
+
+	TP_STRUCT__entry(
+		__field(	u64,	hva		)
+		__field(	u64,	gfn		)
+		__field(	u8,	referenced	)
+	),
+
+	TP_fast_assign(
+		__entry->hva		= hva;
+		__entry->gfn		=
+		  slot->base_gfn + ((hva - slot->userspace_addr) >> PAGE_SHIFT);
+		__entry->referenced	= ref;
+	),
+
+	TP_printk("hva %llx gfn %llx %s",
+		  __entry->hva, __entry->gfn,
+		  __entry->referenced ? "YOUNG" : "OLD")
+);
+
 #endif /* _TRACE_KVM_MAIN_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 0804cd5..601ad77 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -699,9 +699,9 @@
  *	__cpu = smp_processor_id();
  *
  *	if (in_nmi())
- *		trace_buf = rcu_dereference(perf_trace_buf_nmi);
+ *		trace_buf = rcu_dereference_sched(perf_trace_buf_nmi);
  *	else
- *		trace_buf = rcu_dereference(perf_trace_buf);
+ *		trace_buf = rcu_dereference_sched(perf_trace_buf);
  *
  *	if (!trace_buf)
  *		goto end;
diff --git a/include/video/broadsheetfb.h b/include/video/broadsheetfb.h
index a758534..548d28f 100644
--- a/include/video/broadsheetfb.h
+++ b/include/video/broadsheetfb.h
@@ -29,11 +29,19 @@
 #define BS_CMD_UPD_FULL		0x33
 #define BS_CMD_UPD_GDRV_CLR	0x37
 
+/* Broadsheet register interface defines */
+#define BS_REG_REV		0x00
+#define BS_REG_PRC		0x02
+
 /* Broadsheet pin interface specific defines */
 #define BS_CS	0x01
 #define BS_DC 	0x02
 #define BS_WR 	0x03
 
+/* Broadsheet IO interface specific defines */
+#define BS_MMIO_CMD	0x01
+#define BS_MMIO_DATA	0x02
+
 /* struct used by broadsheet. board specific stuff comes from *board */
 struct broadsheetfb_par {
 	struct fb_info *info;
@@ -41,6 +49,8 @@
 	void (*write_reg)(struct broadsheetfb_par *, u16 reg, u16 val);
 	u16 (*read_reg)(struct broadsheetfb_par *, u16 reg);
 	wait_queue_head_t waitq;
+	int panel_index;
+	struct mutex io_lock;
 };
 
 /* board specific routines */
@@ -48,12 +58,17 @@
 	struct module *owner;
 	int (*init)(struct broadsheetfb_par *);
 	int (*wait_for_rdy)(struct broadsheetfb_par *);
-	void (*set_ctl)(struct broadsheetfb_par *, unsigned char, u8);
-	void (*set_hdb)(struct broadsheetfb_par *, u16);
-	u16 (*get_hdb)(struct broadsheetfb_par *);
 	void (*cleanup)(struct broadsheetfb_par *);
 	int (*get_panel_type)(void);
 	int (*setup_irq)(struct fb_info *);
-};
 
+	/* Functions for boards that use GPIO */
+	void (*set_ctl)(struct broadsheetfb_par *, unsigned char, u8);
+	void (*set_hdb)(struct broadsheetfb_par *, u16);
+	u16 (*get_hdb)(struct broadsheetfb_par *);
+
+	/* Functions for boards that have specialized MMIO */
+	void (*mmio_write)(struct broadsheetfb_par *, int type, u16);
+	u16 (*mmio_read)(struct broadsheetfb_par *);
+};
 #endif
diff --git a/init/Kconfig b/init/Kconfig
index 089a230..eb77e8c 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -463,6 +463,7 @@
 
 menuconfig CGROUPS
 	boolean "Control Group support"
+	depends on EVENTFD
 	help
 	  This option adds support for grouping sets of processes together, for
 	  use with process control subsystems such as Cpusets, CFS, memory
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index 614241b..2b10853 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -30,11 +30,7 @@
 	extern char * envp_init[];
 
 	sys_close(old_fd);sys_close(root_fd);
-	sys_close(0);sys_close(1);sys_close(2);
 	sys_setsid();
-	(void) sys_open("/dev/console",O_RDWR,0);
-	(void) sys_dup(0);
-	(void) sys_dup(0);
 	return kernel_execve(shell, argv, envp_init);
 }
 
diff --git a/init/initramfs.c b/init/initramfs.c
index b37d34b..37d3859 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -525,7 +525,7 @@
 	int fd;
 	void *buf;
 	struct linux_dirent64 *dirp;
-	int count;
+	int num;
 
 	fd = sys_open("/", O_RDONLY, 0);
 	WARN_ON(fd < 0);
@@ -539,9 +539,9 @@
 	}
 
 	dirp = buf;
-	count = sys_getdents64(fd, dirp, BUF_SIZE);
-	while (count > 0) {
-		while (count > 0) {
+	num = sys_getdents64(fd, dirp, BUF_SIZE);
+	while (num > 0) {
+		while (num > 0) {
 			struct stat st;
 			int ret;
 
@@ -554,12 +554,12 @@
 					sys_unlink(dirp->d_name);
 			}
 
-			count -= dirp->d_reclen;
+			num -= dirp->d_reclen;
 			dirp = (void *)dirp + dirp->d_reclen;
 		}
 		dirp = buf;
 		memset(buf, 0, BUF_SIZE);
-		count = sys_getdents64(fd, dirp, BUF_SIZE);
+		num = sys_getdents64(fd, dirp, BUF_SIZE);
 	}
 
 	sys_close(fd);
diff --git a/init/main.c b/init/main.c
index c75dcd6..a1ab78c 100644
--- a/init/main.c
+++ b/init/main.c
@@ -149,6 +149,20 @@
 
 early_param("nosmp", nosmp);
 
+/* this is hard limit */
+static int __init nrcpus(char *str)
+{
+	int nr_cpus;
+
+	get_option(&str, &nr_cpus);
+	if (nr_cpus > 0 && nr_cpus < nr_cpu_ids)
+		nr_cpu_ids = nr_cpus;
+
+	return 0;
+}
+
+early_param("nr_cpus", nrcpus);
+
 static int __init maxcpus(char *str)
 {
 	get_option(&str, &setup_max_cpus);
@@ -160,7 +174,7 @@
 
 early_param("maxcpus", maxcpus);
 #else
-const unsigned int setup_max_cpus = NR_CPUS;
+static const unsigned int setup_max_cpus = NR_CPUS;
 #endif
 
 /*
@@ -586,6 +600,7 @@
 		local_irq_disable();
 	}
 	rcu_init();
+	radix_tree_init();
 	/* init some links before init_ISA_irqs() */
 	early_irq_init();
 	init_IRQ();
@@ -603,7 +618,7 @@
 	local_irq_enable();
 
 	/* Interrupts are enabled now so all GFP allocations are safe. */
-	set_gfp_allowed_mask(__GFP_BITS_MASK);
+	gfp_allowed_mask = __GFP_BITS_MASK;
 
 	kmem_cache_init_late();
 
@@ -659,7 +674,6 @@
 	proc_caches_init();
 	buffer_init();
 	key_init();
-	radix_tree_init();
 	security_init();
 	vfs_caches_init(totalram_pages);
 	signals_init();
@@ -808,11 +822,6 @@
 	system_state = SYSTEM_RUNNING;
 	numa_default_policy();
 
-	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
-		printk(KERN_WARNING "Warning: unable to open an initial console.\n");
-
-	(void) sys_dup(0);
-	(void) sys_dup(0);
 
 	current->signal->flags |= SIGNAL_UNKILLABLE;
 
@@ -838,7 +847,8 @@
 	run_init_process("/bin/init");
 	run_init_process("/bin/sh");
 
-	panic("No init found.  Try passing init= option to kernel.");
+	panic("No init found.  Try passing init= option to kernel. "
+	      "See Linux Documentation/init.txt for guidance.");
 }
 
 static int __init kernel_init(void * unused)
@@ -875,6 +885,12 @@
 
 	do_basic_setup();
 
+	/* Open the /dev/console on the rootfs, this should never fail */
+	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
+		printk(KERN_WARNING "Warning: unable to open an initial console.\n");
+
+	(void) sys_dup(0);
+	(void) sys_dup(0);
 	/*
 	 * check if there is an early userspace init.  If yes, let it do all
 	 * the work
diff --git a/ipc/Makefile b/ipc/Makefile
index 4e1955e..9075e17 100644
--- a/ipc/Makefile
+++ b/ipc/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o
-obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o
+obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o syscall.o
 obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o
 obj_mq-$(CONFIG_COMPAT) += compat_mq.o
 obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index c79bd57..e4e3f04 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -134,7 +134,6 @@
 			init_waitqueue_head(&info->wait_q);
 			INIT_LIST_HEAD(&info->e_wait_q[0].list);
 			INIT_LIST_HEAD(&info->e_wait_q[1].list);
-			info->messages = NULL;
 			info->notify_owner = NULL;
 			info->qsize = 0;
 			info->user = NULL;	/* set when all is ok */
@@ -146,26 +145,24 @@
 				info->attr.mq_msgsize = attr->mq_msgsize;
 			}
 			mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
+			info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
+			if (!info->messages)
+				goto out_inode;
+
 			mq_bytes = (mq_msg_tblsz +
 				(info->attr.mq_maxmsg * info->attr.mq_msgsize));
 
 			spin_lock(&mq_lock);
 			if (u->mq_bytes + mq_bytes < u->mq_bytes ||
 		 	    u->mq_bytes + mq_bytes >
-			    p->signal->rlim[RLIMIT_MSGQUEUE].rlim_cur) {
+			    task_rlimit(p, RLIMIT_MSGQUEUE)) {
 				spin_unlock(&mq_lock);
+				kfree(info->messages);
 				goto out_inode;
 			}
 			u->mq_bytes += mq_bytes;
 			spin_unlock(&mq_lock);
 
-			info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
-			if (!info->messages) {
-				spin_lock(&mq_lock);
-				u->mq_bytes -= mq_bytes;
-				spin_unlock(&mq_lock);
-				goto out_inode;
-			}
 			/* all is ok */
 			info->user = get_uid(u);
 		} else if (S_ISDIR(mode)) {
@@ -187,7 +184,7 @@
 {
 	struct inode *inode;
 	struct ipc_namespace *ns = data;
-	int error = 0;
+	int error;
 
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -205,7 +202,9 @@
 	if (!sb->s_root) {
 		iput(inode);
 		error = -ENOMEM;
+		goto out;
 	}
+	error = 0;
 
 out:
 	return error;
@@ -264,8 +263,9 @@
 
 	clear_inode(inode);
 
-	mq_bytes = (info->attr.mq_maxmsg * sizeof(struct msg_msg *) +
-		   (info->attr.mq_maxmsg * info->attr.mq_msgsize));
+	/* Total amount of bytes accounted for the mqueue */
+	mq_bytes = info->attr.mq_maxmsg * (sizeof(struct msg_msg *)
+	    + info->attr.mq_msgsize);
 	user = info->user;
 	if (user) {
 		spin_lock(&mq_lock);
@@ -604,8 +604,8 @@
 	/* check for overflow */
 	if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg)
 		return 0;
-	if ((unsigned long)(attr->mq_maxmsg * attr->mq_msgsize) +
-	    (attr->mq_maxmsg * sizeof (struct msg_msg *)) <
+	if ((unsigned long)(attr->mq_maxmsg * (attr->mq_msgsize
+	    + sizeof (struct msg_msg *))) <
 	    (unsigned long)(attr->mq_maxmsg * attr->mq_msgsize))
 		return 0;
 	return 1;
@@ -623,9 +623,10 @@
 	int ret;
 
 	if (attr) {
-		ret = -EINVAL;
-		if (!mq_attr_ok(ipc_ns, attr))
+		if (!mq_attr_ok(ipc_ns, attr)) {
+			ret = -EINVAL;
 			goto out;
+		}
 		/* store for use during create */
 		dentry->d_fsdata = attr;
 	}
@@ -659,24 +660,28 @@
 static struct file *do_open(struct ipc_namespace *ipc_ns,
 				struct dentry *dentry, int oflag)
 {
+	int ret;
 	const struct cred *cred = current_cred();
 
 	static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
 						  MAY_READ | MAY_WRITE };
 
 	if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
-		dput(dentry);
-		mntput(ipc_ns->mq_mnt);
-		return ERR_PTR(-EINVAL);
+		ret = -EINVAL;
+		goto err;
 	}
 
 	if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) {
-		dput(dentry);
-		mntput(ipc_ns->mq_mnt);
-		return ERR_PTR(-EACCES);
+		ret = -EACCES;
+		goto err;
 	}
 
 	return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
+
+err:
+	dput(dentry);
+	mntput(ipc_ns->mq_mnt);
+	return ERR_PTR(ret);
 }
 
 SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
@@ -705,16 +710,17 @@
 	dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name));
 	if (IS_ERR(dentry)) {
 		error = PTR_ERR(dentry);
-		goto out_err;
+		goto out_putfd;
 	}
 	mntget(ipc_ns->mq_mnt);
 
 	if (oflag & O_CREAT) {
 		if (dentry->d_inode) {	/* entry already exists */
 			audit_inode(name, dentry);
-			error = -EEXIST;
-			if (oflag & O_EXCL)
+			if (oflag & O_EXCL) {
+				error = -EEXIST;
 				goto out;
+			}
 			filp = do_open(ipc_ns, dentry, oflag);
 		} else {
 			filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root,
@@ -722,9 +728,10 @@
 						u_attr ? &attr : NULL);
 		}
 	} else {
-		error = -ENOENT;
-		if (!dentry->d_inode)
+		if (!dentry->d_inode) {
+			error = -ENOENT;
 			goto out;
+		}
 		audit_inode(name, dentry);
 		filp = do_open(ipc_ns, dentry, oflag);
 	}
@@ -742,7 +749,6 @@
 	mntput(ipc_ns->mq_mnt);
 out_putfd:
 	put_unused_fd(fd);
-out_err:
 	fd = error;
 out_upsem:
 	mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
@@ -872,19 +878,24 @@
 	audit_mq_sendrecv(mqdes, msg_len, msg_prio, p);
 	timeout = prepare_timeout(p);
 
-	ret = -EBADF;
 	filp = fget(mqdes);
-	if (unlikely(!filp))
+	if (unlikely(!filp)) {
+		ret = -EBADF;
 		goto out;
+	}
 
 	inode = filp->f_path.dentry->d_inode;
-	if (unlikely(filp->f_op != &mqueue_file_operations))
+	if (unlikely(filp->f_op != &mqueue_file_operations)) {
+		ret = -EBADF;
 		goto out_fput;
+	}
 	info = MQUEUE_I(inode);
 	audit_inode(NULL, filp->f_path.dentry);
 
-	if (unlikely(!(filp->f_mode & FMODE_WRITE)))
+	if (unlikely(!(filp->f_mode & FMODE_WRITE))) {
+		ret = -EBADF;
 		goto out_fput;
+	}
 
 	if (unlikely(msg_len > info->attr.mq_msgsize)) {
 		ret = -EMSGSIZE;
@@ -961,19 +972,24 @@
 	audit_mq_sendrecv(mqdes, msg_len, 0, p);
 	timeout = prepare_timeout(p);
 
-	ret = -EBADF;
 	filp = fget(mqdes);
-	if (unlikely(!filp))
+	if (unlikely(!filp)) {
+		ret = -EBADF;
 		goto out;
+	}
 
 	inode = filp->f_path.dentry->d_inode;
-	if (unlikely(filp->f_op != &mqueue_file_operations))
+	if (unlikely(filp->f_op != &mqueue_file_operations)) {
+		ret = -EBADF;
 		goto out_fput;
+	}
 	info = MQUEUE_I(inode);
 	audit_inode(NULL, filp->f_path.dentry);
 
-	if (unlikely(!(filp->f_mode & FMODE_READ)))
+	if (unlikely(!(filp->f_mode & FMODE_READ))) {
+		ret = -EBADF;
 		goto out_fput;
+	}
 
 	/* checks if buffer is big enough */
 	if (unlikely(msg_len < info->attr.mq_msgsize)) {
@@ -1063,13 +1079,14 @@
 
 			/* create the notify skb */
 			nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
-			ret = -ENOMEM;
-			if (!nc)
+			if (!nc) {
+				ret = -ENOMEM;
 				goto out;
-			ret = -EFAULT;
+			}
 			if (copy_from_user(nc->data,
 					notification.sigev_value.sival_ptr,
 					NOTIFY_COOKIE_LEN)) {
+				ret = -EFAULT;
 				goto out;
 			}
 
@@ -1078,9 +1095,10 @@
 			/* and attach it to the socket */
 retry:
 			filp = fget(notification.sigev_signo);
-			ret = -EBADF;
-			if (!filp)
+			if (!filp) {
+				ret = -EBADF;
 				goto out;
+			}
 			sock = netlink_getsockbyfilp(filp);
 			fput(filp);
 			if (IS_ERR(sock)) {
@@ -1092,7 +1110,7 @@
 			timeo = MAX_SCHEDULE_TIMEOUT;
 			ret = netlink_attachskb(sock, nc, &timeo, NULL);
 			if (ret == 1)
-		       		goto retry;
+				goto retry;
 			if (ret) {
 				sock = NULL;
 				nc = NULL;
@@ -1101,14 +1119,17 @@
 		}
 	}
 
-	ret = -EBADF;
 	filp = fget(mqdes);
-	if (!filp)
+	if (!filp) {
+		ret = -EBADF;
 		goto out;
+	}
 
 	inode = filp->f_path.dentry->d_inode;
-	if (unlikely(filp->f_op != &mqueue_file_operations))
+	if (unlikely(filp->f_op != &mqueue_file_operations)) {
+		ret = -EBADF;
 		goto out_fput;
+	}
 	info = MQUEUE_I(inode);
 
 	ret = 0;
@@ -1171,14 +1192,17 @@
 			return -EINVAL;
 	}
 
-	ret = -EBADF;
 	filp = fget(mqdes);
-	if (!filp)
+	if (!filp) {
+		ret = -EBADF;
 		goto out;
+	}
 
 	inode = filp->f_path.dentry->d_inode;
-	if (unlikely(filp->f_op != &mqueue_file_operations))
+	if (unlikely(filp->f_op != &mqueue_file_operations)) {
+		ret = -EBADF;
 		goto out_fput;
+	}
 	info = MQUEUE_I(inode);
 
 	spin_lock(&info->lock);
@@ -1272,7 +1296,7 @@
 	if (mqueue_inode_cachep == NULL)
 		return -ENOMEM;
 
-	/* ignore failues - they are not fatal */
+	/* ignore failures - they are not fatal */
 	mq_sysctl_table = mq_register_sysctl_table();
 
 	error = register_filesystem(&mqueue_fs_type);
diff --git a/ipc/shm.c b/ipc/shm.c
index 23256b8..1a314c8 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -764,8 +764,7 @@
 			if (euid != shp->shm_perm.uid &&
 			    euid != shp->shm_perm.cuid)
 				goto out_unlock;
-			if (cmd == SHM_LOCK &&
-			    !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
+			if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK))
 				goto out_unlock;
 		}
 
diff --git a/ipc/syscall.c b/ipc/syscall.c
new file mode 100644
index 0000000..355a3da
--- /dev/null
+++ b/ipc/syscall.c
@@ -0,0 +1,99 @@
+/*
+ * sys_ipc() is the old de-multiplexer for the SysV IPC calls.
+ *
+ * This is really horribly ugly, and new architectures should just wire up
+ * the individual syscalls instead.
+ */
+#include <linux/unistd.h>
+
+#ifdef __ARCH_WANT_SYS_IPC
+#include <linux/errno.h>
+#include <linux/ipc.h>
+#include <linux/shm.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+
+SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second,
+		unsigned long, third, void __user *, ptr, long, fifth)
+{
+	int version, ret;
+
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	switch (call) {
+	case SEMOP:
+		return sys_semtimedop(first, (struct sembuf __user *)ptr,
+				      second, NULL);
+	case SEMTIMEDOP:
+		return sys_semtimedop(first, (struct sembuf __user *)ptr,
+				      second,
+				      (const struct timespec __user *)fifth);
+
+	case SEMGET:
+		return sys_semget(first, second, third);
+	case SEMCTL: {
+		union semun fourth;
+		if (!ptr)
+			return -EINVAL;
+		if (get_user(fourth.__pad, (void __user * __user *) ptr))
+			return -EFAULT;
+		return sys_semctl(first, second, third, fourth);
+	}
+
+	case MSGSND:
+		return sys_msgsnd(first, (struct msgbuf __user *) ptr,
+				  second, third);
+	case MSGRCV:
+		switch (version) {
+		case 0: {
+			struct ipc_kludge tmp;
+			if (!ptr)
+				return -EINVAL;
+
+			if (copy_from_user(&tmp,
+					   (struct ipc_kludge __user *) ptr,
+					   sizeof(tmp)))
+				return -EFAULT;
+			return sys_msgrcv(first, tmp.msgp, second,
+					   tmp.msgtyp, third);
+		}
+		default:
+			return sys_msgrcv(first,
+					   (struct msgbuf __user *) ptr,
+					   second, fifth, third);
+		}
+	case MSGGET:
+		return sys_msgget((key_t) first, second);
+	case MSGCTL:
+		return sys_msgctl(first, second, (struct msqid_ds __user *)ptr);
+
+	case SHMAT:
+		switch (version) {
+		default: {
+			unsigned long raddr;
+			ret = do_shmat(first, (char __user *)ptr,
+				       second, &raddr);
+			if (ret)
+				return ret;
+			return put_user(raddr, (unsigned long __user *) third);
+		}
+		case 1:
+			/*
+			 * This was the entry point for kernel-originating calls
+			 * from iBCS2 in 2.2 days.
+			 */
+			return -EINVAL;
+		}
+	case SHMDT:
+		return sys_shmdt((char __user *)ptr);
+	case SHMGET:
+		return sys_shmget(first, second, third);
+	case SHMCTL:
+		return sys_shmctl(first, second,
+				   (struct shmid_ds __user *) ptr);
+	default:
+		return -ENOSYS;
+	}
+}
+#endif
diff --git a/kernel/Makefile b/kernel/Makefile
index 6aebdeb..a987aa1 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -10,7 +10,8 @@
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
 	    hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
 	    notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \
-	    async.o
+	    async.o range.o
+obj-$(CONFIG_HAVE_EARLY_RES) += early_res.o
 obj-y += groups.o
 
 ifdef CONFIG_FUNCTION_TRACER
@@ -90,6 +91,9 @@
 obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
 obj-$(CONFIG_TRACEPOINTS) += tracepoint.o
 obj-$(CONFIG_LATENCYTOP) += latencytop.o
+obj-$(CONFIG_BINFMT_ELF) += elfcore.o
+obj-$(CONFIG_COMPAT_BINFMT_ELF) += elfcore.o
+obj-$(CONFIG_BINFMT_ELF_FDPIC) += elfcore.o
 obj-$(CONFIG_FUNCTION_TRACER) += trace/
 obj-$(CONFIG_TRACING) += trace/
 obj-$(CONFIG_X86_DS) += trace/
diff --git a/kernel/acct.c b/kernel/acct.c
index a6605ca..24f8c81 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -588,16 +588,6 @@
 }
 
 /**
- * acct_init_pacct - initialize a new pacct_struct
- * @pacct: per-process accounting info struct to initialize
- */
-void acct_init_pacct(struct pacct_struct *pacct)
-{
-	memset(pacct, 0, sizeof(struct pacct_struct));
-	pacct->ac_utime = pacct->ac_stime = cputime_zero;
-}
-
-/**
  * acct_collect - collect accounting information into pacct_struct
  * @exitcode: task exit code
  * @group_dead: not 0, if this thread is the last one in the process.
diff --git a/kernel/audit.c b/kernel/audit.c
index 5feed23..78f7f86 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -398,7 +398,7 @@
 	skb_get(skb);
 	err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0);
 	if (err < 0) {
-		BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
+		BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */
 		printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
 		audit_log_lost("auditd dissapeared\n");
 		audit_pid = 0;
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 4b05bd9..028e856 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -548,6 +548,11 @@
 	return 0;
 }
 
+static int compare_root(struct vfsmount *mnt, void *arg)
+{
+	return mnt->mnt_root->d_inode == arg;
+}
+
 void audit_trim_trees(void)
 {
 	struct list_head cursor;
@@ -559,7 +564,6 @@
 		struct path path;
 		struct vfsmount *root_mnt;
 		struct node *node;
-		struct list_head list;
 		int err;
 
 		tree = container_of(cursor.next, struct audit_tree, list);
@@ -577,24 +581,16 @@
 		if (!root_mnt)
 			goto skip_it;
 
-		list_add_tail(&list, &root_mnt->mnt_list);
 		spin_lock(&hash_lock);
 		list_for_each_entry(node, &tree->chunks, list) {
-			struct audit_chunk *chunk = find_chunk(node);
-			struct inode *inode = chunk->watch.inode;
-			struct vfsmount *mnt;
+			struct inode *inode = find_chunk(node)->watch.inode;
 			node->index |= 1U<<31;
-			list_for_each_entry(mnt, &list, mnt_list) {
-				if (mnt->mnt_root->d_inode == inode) {
-					node->index &= ~(1U<<31);
-					break;
-				}
-			}
+			if (iterate_mounts(compare_root, inode, root_mnt))
+				node->index &= ~(1U<<31);
 		}
 		spin_unlock(&hash_lock);
 		trim_marked(tree);
 		put_tree(tree);
-		list_del_init(&list);
 		drop_collected_mounts(root_mnt);
 skip_it:
 		mutex_lock(&audit_filter_mutex);
@@ -603,22 +599,6 @@
 	mutex_unlock(&audit_filter_mutex);
 }
 
-static int is_under(struct vfsmount *mnt, struct dentry *dentry,
-		    struct path *path)
-{
-	if (mnt != path->mnt) {
-		for (;;) {
-			if (mnt->mnt_parent == mnt)
-				return 0;
-			if (mnt->mnt_parent == path->mnt)
-					break;
-			mnt = mnt->mnt_parent;
-		}
-		dentry = mnt->mnt_mountpoint;
-	}
-	return is_subdir(dentry, path->dentry);
-}
-
 int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
 {
 
@@ -638,13 +618,17 @@
 	put_tree(tree);
 }
 
+static int tag_mount(struct vfsmount *mnt, void *arg)
+{
+	return tag_chunk(mnt->mnt_root->d_inode, arg);
+}
+
 /* called with audit_filter_mutex */
 int audit_add_tree_rule(struct audit_krule *rule)
 {
 	struct audit_tree *seed = rule->tree, *tree;
 	struct path path;
-	struct vfsmount *mnt, *p;
-	struct list_head list;
+	struct vfsmount *mnt;
 	int err;
 
 	list_for_each_entry(tree, &tree_list, list) {
@@ -670,16 +654,9 @@
 		err = -ENOMEM;
 		goto Err;
 	}
-	list_add_tail(&list, &mnt->mnt_list);
 
 	get_tree(tree);
-	list_for_each_entry(p, &list, mnt_list) {
-		err = tag_chunk(p->mnt_root->d_inode, tree);
-		if (err)
-			break;
-	}
-
-	list_del(&list);
+	err = iterate_mounts(tag_mount, tree, mnt);
 	drop_collected_mounts(mnt);
 
 	if (!err) {
@@ -714,31 +691,23 @@
 {
 	struct list_head cursor, barrier;
 	int failed = 0;
-	struct path path;
+	struct path path1, path2;
 	struct vfsmount *tagged;
-	struct list_head list;
-	struct vfsmount *mnt;
-	struct dentry *dentry;
 	int err;
 
-	err = kern_path(new, 0, &path);
+	err = kern_path(new, 0, &path2);
 	if (err)
 		return err;
-	tagged = collect_mounts(&path);
-	path_put(&path);
+	tagged = collect_mounts(&path2);
+	path_put(&path2);
 	if (!tagged)
 		return -ENOMEM;
 
-	err = kern_path(old, 0, &path);
+	err = kern_path(old, 0, &path1);
 	if (err) {
 		drop_collected_mounts(tagged);
 		return err;
 	}
-	mnt = mntget(path.mnt);
-	dentry = dget(path.dentry);
-	path_put(&path);
-
-	list_add_tail(&list, &tagged->mnt_list);
 
 	mutex_lock(&audit_filter_mutex);
 	list_add(&barrier, &tree_list);
@@ -746,7 +715,7 @@
 
 	while (cursor.next != &tree_list) {
 		struct audit_tree *tree;
-		struct vfsmount *p;
+		int good_one = 0;
 
 		tree = container_of(cursor.next, struct audit_tree, list);
 		get_tree(tree);
@@ -754,30 +723,19 @@
 		list_add(&cursor, &tree->list);
 		mutex_unlock(&audit_filter_mutex);
 
-		err = kern_path(tree->pathname, 0, &path);
-		if (err) {
+		err = kern_path(tree->pathname, 0, &path2);
+		if (!err) {
+			good_one = path_is_under(&path1, &path2);
+			path_put(&path2);
+		}
+
+		if (!good_one) {
 			put_tree(tree);
 			mutex_lock(&audit_filter_mutex);
 			continue;
 		}
 
-		spin_lock(&vfsmount_lock);
-		if (!is_under(mnt, dentry, &path)) {
-			spin_unlock(&vfsmount_lock);
-			path_put(&path);
-			put_tree(tree);
-			mutex_lock(&audit_filter_mutex);
-			continue;
-		}
-		spin_unlock(&vfsmount_lock);
-		path_put(&path);
-
-		list_for_each_entry(p, &list, mnt_list) {
-			failed = tag_chunk(p->mnt_root->d_inode, tree);
-			if (failed)
-				break;
-		}
-
+		failed = iterate_mounts(tag_mount, tree, tagged);
 		if (failed) {
 			put_tree(tree);
 			mutex_lock(&audit_filter_mutex);
@@ -818,10 +776,8 @@
 	}
 	list_del(&barrier);
 	list_del(&cursor);
-	list_del(&list);
 	mutex_unlock(&audit_filter_mutex);
-	dput(dentry);
-	mntput(mnt);
+	path_put(&path1);
 	drop_collected_mounts(tagged);
 	return failed;
 }
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index fc0f928..f3a461c 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1988,7 +1988,6 @@
 
 /**
  * audit_inode_child - collect inode info for created/removed objects
- * @dname: inode's dentry name
  * @dentry: dentry being audited
  * @parent: inode of dentry parent
  *
@@ -2000,13 +1999,14 @@
  * must be hooked prior, in order to capture the target inode during
  * unsuccessful attempts.
  */
-void __audit_inode_child(const char *dname, const struct dentry *dentry,
+void __audit_inode_child(const struct dentry *dentry,
 			 const struct inode *parent)
 {
 	int idx;
 	struct audit_context *context = current->audit_context;
 	const char *found_parent = NULL, *found_child = NULL;
 	const struct inode *inode = dentry->d_inode;
+	const char *dname = dentry->d_name.name;
 	int dirlen = 0;
 
 	if (!context->in_syscall)
@@ -2014,9 +2014,6 @@
 
 	if (inode)
 		handle_one(inode);
-	/* determine matching parent */
-	if (!dname)
-		goto add_names;
 
 	/* parent is more likely, look for it first */
 	for (idx = 0; idx < context->name_count; idx++) {
diff --git a/kernel/capability.c b/kernel/capability.c
index 7f876e6..9e4697e 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -135,7 +135,7 @@
 	if (pid && (pid != task_pid_vnr(current))) {
 		struct task_struct *target;
 
-		read_lock(&tasklist_lock);
+		rcu_read_lock();
 
 		target = find_task_by_vpid(pid);
 		if (!target)
@@ -143,7 +143,7 @@
 		else
 			ret = security_capget(target, pEp, pIp, pPp);
 
-		read_unlock(&tasklist_lock);
+		rcu_read_unlock();
 	} else
 		ret = security_capget(current, pEp, pIp, pPp);
 
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 4fd90e1..ef909a3 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4,6 +4,10 @@
  *  Based originally on the cpuset system, extracted by Paul Menage
  *  Copyright (C) 2006 Google, Inc
  *
+ *  Notifications support
+ *  Copyright (C) 2009 Nokia Corporation
+ *  Author: Kirill A. Shutemov
+ *
  *  Copyright notices from the original cpuset code:
  *  --------------------------------------------------
  *  Copyright (C) 2003 BULL SA.
@@ -44,6 +48,7 @@
 #include <linux/string.h>
 #include <linux/sort.h>
 #include <linux/kmod.h>
+#include <linux/module.h>
 #include <linux/delayacct.h>
 #include <linux/cgroupstats.h>
 #include <linux/hash.h>
@@ -52,15 +57,21 @@
 #include <linux/pid_namespace.h>
 #include <linux/idr.h>
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
+#include <linux/eventfd.h>
+#include <linux/poll.h>
 
 #include <asm/atomic.h>
 
 static DEFINE_MUTEX(cgroup_mutex);
 
-/* Generate an array of cgroup subsystem pointers */
+/*
+ * Generate an array of cgroup subsystem pointers. At boot time, this is
+ * populated up to CGROUP_BUILTIN_SUBSYS_COUNT, and modular subsystems are
+ * registered after that. The mutable section of this array is protected by
+ * cgroup_mutex.
+ */
 #define SUBSYS(_x) &_x ## _subsys,
-
-static struct cgroup_subsys *subsys[] = {
+static struct cgroup_subsys *subsys[CGROUP_SUBSYS_COUNT] = {
 #include <linux/cgroup_subsys.h>
 };
 
@@ -147,6 +158,35 @@
 	unsigned short stack[0]; /* Array of Length (depth+1) */
 };
 
+/*
+ * cgroup_event represents events which userspace want to recieve.
+ */
+struct cgroup_event {
+	/*
+	 * Cgroup which the event belongs to.
+	 */
+	struct cgroup *cgrp;
+	/*
+	 * Control file which the event associated.
+	 */
+	struct cftype *cft;
+	/*
+	 * eventfd to signal userspace about the event.
+	 */
+	struct eventfd_ctx *eventfd;
+	/*
+	 * Each of these stored in a list by the cgroup.
+	 */
+	struct list_head list;
+	/*
+	 * All fields below needed to unregister event when
+	 * userspace closes eventfd.
+	 */
+	poll_table pt;
+	wait_queue_head_t *wqh;
+	wait_queue_t wait;
+	struct work_struct remove;
+};
 
 /* The list of hierarchy roots */
 
@@ -250,7 +290,8 @@
 static struct css_set init_css_set;
 static struct cg_cgroup_link init_css_set_link;
 
-static int cgroup_subsys_init_idr(struct cgroup_subsys *ss);
+static int cgroup_init_idr(struct cgroup_subsys *ss,
+			   struct cgroup_subsys_state *css);
 
 /* css_set_lock protects the list of css_set objects, and the
  * chain of tasks off each css_set.  Nests outside task->alloc_lock
@@ -448,8 +489,11 @@
 	struct hlist_node *node;
 	struct css_set *cg;
 
-	/* Built the set of subsystem state objects that we want to
-	 * see in the new css_set */
+	/*
+	 * Build the set of subsystem state objects that we want to see in the
+	 * new css_set. while subsystems can change globally, the entries here
+	 * won't change, so no need for locking.
+	 */
 	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
 		if (root->subsys_bits & (1UL << i)) {
 			/* Subsystem is in this hierarchy. So we want
@@ -696,6 +740,7 @@
 {
 	mutex_lock(&cgroup_mutex);
 }
+EXPORT_SYMBOL_GPL(cgroup_lock);
 
 /**
  * cgroup_unlock - release lock on cgroup changes
@@ -706,6 +751,7 @@
 {
 	mutex_unlock(&cgroup_mutex);
 }
+EXPORT_SYMBOL_GPL(cgroup_unlock);
 
 /*
  * A couple of forward declarations required, due to cyclic reference loop:
@@ -757,6 +803,7 @@
 			if (ret)
 				break;
 		}
+
 	return ret;
 }
 
@@ -884,7 +931,11 @@
 	css_put(css);
 }
 
-
+/*
+ * Call with cgroup_mutex held. Drops reference counts on modules, including
+ * any duplicate ones that parse_cgroupfs_options took. If this function
+ * returns an error, no reference counts are touched.
+ */
 static int rebind_subsystems(struct cgroupfs_root *root,
 			      unsigned long final_bits)
 {
@@ -892,6 +943,8 @@
 	struct cgroup *cgrp = &root->top_cgroup;
 	int i;
 
+	BUG_ON(!mutex_is_locked(&cgroup_mutex));
+
 	removed_bits = root->actual_subsys_bits & ~final_bits;
 	added_bits = final_bits & ~root->actual_subsys_bits;
 	/* Check that any added subsystems are currently free */
@@ -900,6 +953,12 @@
 		struct cgroup_subsys *ss = subsys[i];
 		if (!(bit & added_bits))
 			continue;
+		/*
+		 * Nobody should tell us to do a subsys that doesn't exist:
+		 * parse_cgroupfs_options should catch that case and refcounts
+		 * ensure that subsystems won't disappear once selected.
+		 */
+		BUG_ON(ss == NULL);
 		if (ss->root != &rootnode) {
 			/* Subsystem isn't free */
 			return -EBUSY;
@@ -919,6 +978,7 @@
 		unsigned long bit = 1UL << i;
 		if (bit & added_bits) {
 			/* We're binding this subsystem to this hierarchy */
+			BUG_ON(ss == NULL);
 			BUG_ON(cgrp->subsys[i]);
 			BUG_ON(!dummytop->subsys[i]);
 			BUG_ON(dummytop->subsys[i]->cgroup != dummytop);
@@ -930,8 +990,10 @@
 			if (ss->bind)
 				ss->bind(ss, cgrp);
 			mutex_unlock(&ss->hierarchy_mutex);
+			/* refcount was already taken, and we're keeping it */
 		} else if (bit & removed_bits) {
 			/* We're removing this subsystem */
+			BUG_ON(ss == NULL);
 			BUG_ON(cgrp->subsys[i] != dummytop->subsys[i]);
 			BUG_ON(cgrp->subsys[i]->cgroup != cgrp);
 			mutex_lock(&ss->hierarchy_mutex);
@@ -942,9 +1004,20 @@
 			subsys[i]->root = &rootnode;
 			list_move(&ss->sibling, &rootnode.subsys_list);
 			mutex_unlock(&ss->hierarchy_mutex);
+			/* subsystem is now free - drop reference on module */
+			module_put(ss->module);
 		} else if (bit & final_bits) {
 			/* Subsystem state should already exist */
+			BUG_ON(ss == NULL);
 			BUG_ON(!cgrp->subsys[i]);
+			/*
+			 * a refcount was taken, but we already had one, so
+			 * drop the extra reference.
+			 */
+			module_put(ss->module);
+#ifdef CONFIG_MODULE_UNLOAD
+			BUG_ON(ss->module && !module_refcount(ss->module));
+#endif
 		} else {
 			/* Subsystem state shouldn't exist */
 			BUG_ON(cgrp->subsys[i]);
@@ -986,13 +1059,20 @@
 
 };
 
-/* Convert a hierarchy specifier into a bitmask of subsystems and
- * flags. */
-static int parse_cgroupfs_options(char *data,
-				     struct cgroup_sb_opts *opts)
+/*
+ * Convert a hierarchy specifier into a bitmask of subsystems and flags. Call
+ * with cgroup_mutex held to protect the subsys[] array. This function takes
+ * refcounts on subsystems to be used, unless it returns error, in which case
+ * no refcounts are taken.
+ */
+static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
 {
 	char *token, *o = data ?: "all";
 	unsigned long mask = (unsigned long)-1;
+	int i;
+	bool module_pin_failed = false;
+
+	BUG_ON(!mutex_is_locked(&cgroup_mutex));
 
 #ifdef CONFIG_CPUSETS
 	mask = ~(1UL << cpuset_subsys_id);
@@ -1005,10 +1085,11 @@
 			return -EINVAL;
 		if (!strcmp(token, "all")) {
 			/* Add all non-disabled subsystems */
-			int i;
 			opts->subsys_bits = 0;
 			for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
 				struct cgroup_subsys *ss = subsys[i];
+				if (ss == NULL)
+					continue;
 				if (!ss->disabled)
 					opts->subsys_bits |= 1ul << i;
 			}
@@ -1026,7 +1107,6 @@
 			if (!opts->release_agent)
 				return -ENOMEM;
 		} else if (!strncmp(token, "name=", 5)) {
-			int i;
 			const char *name = token + 5;
 			/* Can't specify an empty name */
 			if (!strlen(name))
@@ -1050,9 +1130,10 @@
 				return -ENOMEM;
 		} else {
 			struct cgroup_subsys *ss;
-			int i;
 			for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
 				ss = subsys[i];
+				if (ss == NULL)
+					continue;
 				if (!strcmp(token, ss->name)) {
 					if (!ss->disabled)
 						set_bit(i, &opts->subsys_bits);
@@ -1087,9 +1168,54 @@
 	if (!opts->subsys_bits && !opts->name)
 		return -EINVAL;
 
+	/*
+	 * Grab references on all the modules we'll need, so the subsystems
+	 * don't dance around before rebind_subsystems attaches them. This may
+	 * take duplicate reference counts on a subsystem that's already used,
+	 * but rebind_subsystems handles this case.
+	 */
+	for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) {
+		unsigned long bit = 1UL << i;
+
+		if (!(bit & opts->subsys_bits))
+			continue;
+		if (!try_module_get(subsys[i]->module)) {
+			module_pin_failed = true;
+			break;
+		}
+	}
+	if (module_pin_failed) {
+		/*
+		 * oops, one of the modules was going away. this means that we
+		 * raced with a module_delete call, and to the user this is
+		 * essentially a "subsystem doesn't exist" case.
+		 */
+		for (i--; i >= CGROUP_BUILTIN_SUBSYS_COUNT; i--) {
+			/* drop refcounts only on the ones we took */
+			unsigned long bit = 1UL << i;
+
+			if (!(bit & opts->subsys_bits))
+				continue;
+			module_put(subsys[i]->module);
+		}
+		return -ENOENT;
+	}
+
 	return 0;
 }
 
+static void drop_parsed_module_refcounts(unsigned long subsys_bits)
+{
+	int i;
+	for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) {
+		unsigned long bit = 1UL << i;
+
+		if (!(bit & subsys_bits))
+			continue;
+		module_put(subsys[i]->module);
+	}
+}
+
 static int cgroup_remount(struct super_block *sb, int *flags, char *data)
 {
 	int ret = 0;
@@ -1106,21 +1232,19 @@
 	if (ret)
 		goto out_unlock;
 
-	/* Don't allow flags to change at remount */
-	if (opts.flags != root->flags) {
+	/* Don't allow flags or name to change at remount */
+	if (opts.flags != root->flags ||
+	    (opts.name && strcmp(opts.name, root->name))) {
 		ret = -EINVAL;
-		goto out_unlock;
-	}
-
-	/* Don't allow name to change at remount */
-	if (opts.name && strcmp(opts.name, root->name)) {
-		ret = -EINVAL;
+		drop_parsed_module_refcounts(opts.subsys_bits);
 		goto out_unlock;
 	}
 
 	ret = rebind_subsystems(root, opts.subsys_bits);
-	if (ret)
+	if (ret) {
+		drop_parsed_module_refcounts(opts.subsys_bits);
 		goto out_unlock;
+	}
 
 	/* (re)populate subsystem files */
 	cgroup_populate_dir(cgrp);
@@ -1151,6 +1275,8 @@
 	INIT_LIST_HEAD(&cgrp->release_list);
 	INIT_LIST_HEAD(&cgrp->pidlists);
 	mutex_init(&cgrp->pidlist_mutex);
+	INIT_LIST_HEAD(&cgrp->event_list);
+	spin_lock_init(&cgrp->event_list_lock);
 }
 
 static void init_cgroup_root(struct cgroupfs_root *root)
@@ -1306,7 +1432,9 @@
 	struct cgroupfs_root *new_root;
 
 	/* First find the desired set of subsystems */
+	mutex_lock(&cgroup_mutex);
 	ret = parse_cgroupfs_options(data, &opts);
+	mutex_unlock(&cgroup_mutex);
 	if (ret)
 		goto out_err;
 
@@ -1317,7 +1445,7 @@
 	new_root = cgroup_root_from_opts(&opts);
 	if (IS_ERR(new_root)) {
 		ret = PTR_ERR(new_root);
-		goto out_err;
+		goto drop_modules;
 	}
 	opts.new_root = new_root;
 
@@ -1326,7 +1454,7 @@
 	if (IS_ERR(sb)) {
 		ret = PTR_ERR(sb);
 		cgroup_drop_root(opts.new_root);
-		goto out_err;
+		goto drop_modules;
 	}
 
 	root = sb->s_fs_info;
@@ -1382,6 +1510,11 @@
 			free_cg_links(&tmp_cg_links);
 			goto drop_new_super;
 		}
+		/*
+		 * There must be no failure case after here, since rebinding
+		 * takes care of subsystems' refcounts, which are explicitly
+		 * dropped in the failure exit path.
+		 */
 
 		/* EBUSY should be the only error here */
 		BUG_ON(ret);
@@ -1420,6 +1553,8 @@
 		 * any) is not needed
 		 */
 		cgroup_drop_root(opts.new_root);
+		/* no subsys rebinding, so refcounts don't change */
+		drop_parsed_module_refcounts(opts.subsys_bits);
 	}
 
 	simple_set_mnt(mnt, sb);
@@ -1429,6 +1564,8 @@
 
  drop_new_super:
 	deactivate_locked_super(sb);
+ drop_modules:
+	drop_parsed_module_refcounts(opts.subsys_bits);
  out_err:
 	kfree(opts.release_agent);
 	kfree(opts.name);
@@ -1542,6 +1679,7 @@
 	memmove(buf, start, buf + buflen - start);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(cgroup_path);
 
 /**
  * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp'
@@ -1554,7 +1692,7 @@
 int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
 {
 	int retval = 0;
-	struct cgroup_subsys *ss;
+	struct cgroup_subsys *ss, *failed_ss = NULL;
 	struct cgroup *oldcgrp;
 	struct css_set *cg;
 	struct css_set *newcg;
@@ -1568,8 +1706,16 @@
 	for_each_subsys(root, ss) {
 		if (ss->can_attach) {
 			retval = ss->can_attach(ss, cgrp, tsk, false);
-			if (retval)
-				return retval;
+			if (retval) {
+				/*
+				 * Remember on which subsystem the can_attach()
+				 * failed, so that we only call cancel_attach()
+				 * against the subsystems whose can_attach()
+				 * succeeded. (See below)
+				 */
+				failed_ss = ss;
+				goto out;
+			}
 		}
 	}
 
@@ -1583,14 +1729,17 @@
 	 */
 	newcg = find_css_set(cg, cgrp);
 	put_css_set(cg);
-	if (!newcg)
-		return -ENOMEM;
+	if (!newcg) {
+		retval = -ENOMEM;
+		goto out;
+	}
 
 	task_lock(tsk);
 	if (tsk->flags & PF_EXITING) {
 		task_unlock(tsk);
 		put_css_set(newcg);
-		return -ESRCH;
+		retval = -ESRCH;
+		goto out;
 	}
 	rcu_assign_pointer(tsk->cgroups, newcg);
 	task_unlock(tsk);
@@ -1616,7 +1765,22 @@
 	 * is no longer empty.
 	 */
 	cgroup_wakeup_rmdir_waiter(cgrp);
-	return 0;
+out:
+	if (retval) {
+		for_each_subsys(root, ss) {
+			if (ss == failed_ss)
+				/*
+				 * This subsystem was the one that failed the
+				 * can_attach() check earlier, so we don't need
+				 * to call cancel_attach() against it or any
+				 * remaining subsystems.
+				 */
+				break;
+			if (ss->cancel_attach)
+				ss->cancel_attach(ss, cgrp, tsk, false);
+		}
+	}
+	return retval;
 }
 
 /*
@@ -1682,6 +1846,7 @@
 	}
 	return true;
 }
+EXPORT_SYMBOL_GPL(cgroup_lock_live_group);
 
 static int cgroup_release_agent_write(struct cgroup *cgrp, struct cftype *cft,
 				      const char *buffer)
@@ -1950,6 +2115,16 @@
 	.rename = cgroup_rename,
 };
 
+/*
+ * Check if a file is a control file
+ */
+static inline struct cftype *__file_cft(struct file *file)
+{
+	if (file->f_dentry->d_inode->i_fop != &cgroup_file_operations)
+		return ERR_PTR(-EINVAL);
+	return __d_cft(file->f_dentry);
+}
+
 static int cgroup_create_file(struct dentry *dentry, mode_t mode,
 				struct super_block *sb)
 {
@@ -2069,6 +2244,7 @@
 		error = PTR_ERR(dentry);
 	return error;
 }
+EXPORT_SYMBOL_GPL(cgroup_add_file);
 
 int cgroup_add_files(struct cgroup *cgrp,
 			struct cgroup_subsys *subsys,
@@ -2083,6 +2259,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(cgroup_add_files);
 
 /**
  * cgroup_task_count - count the number of tasks in a cgroup.
@@ -2468,7 +2645,8 @@
 {
 	struct cgroup_pidlist *l;
 	/* don't need task_nsproxy() if we're looking at ourself */
-	struct pid_namespace *ns = get_pid_ns(current->nsproxy->pid_ns);
+	struct pid_namespace *ns = current->nsproxy->pid_ns;
+
 	/*
 	 * We can't drop the pidlist_mutex before taking the l->mutex in case
 	 * the last ref-holder is trying to remove l from the list at the same
@@ -2478,8 +2656,6 @@
 	mutex_lock(&cgrp->pidlist_mutex);
 	list_for_each_entry(l, &cgrp->pidlists, links) {
 		if (l->key.type == type && l->key.ns == ns) {
-			/* found a matching list - drop the extra refcount */
-			put_pid_ns(ns);
 			/* make sure l doesn't vanish out from under us */
 			down_write(&l->mutex);
 			mutex_unlock(&cgrp->pidlist_mutex);
@@ -2490,13 +2666,12 @@
 	l = kmalloc(sizeof(struct cgroup_pidlist), GFP_KERNEL);
 	if (!l) {
 		mutex_unlock(&cgrp->pidlist_mutex);
-		put_pid_ns(ns);
 		return l;
 	}
 	init_rwsem(&l->mutex);
 	down_write(&l->mutex);
 	l->key.type = type;
-	l->key.ns = ns;
+	l->key.ns = get_pid_ns(ns);
 	l->use_count = 0; /* don't increment here */
 	l->list = NULL;
 	l->owner = cgrp;
@@ -2804,6 +2979,174 @@
 }
 
 /*
+ * Unregister event and free resources.
+ *
+ * Gets called from workqueue.
+ */
+static void cgroup_event_remove(struct work_struct *work)
+{
+	struct cgroup_event *event = container_of(work, struct cgroup_event,
+			remove);
+	struct cgroup *cgrp = event->cgrp;
+
+	/* TODO: check return code */
+	event->cft->unregister_event(cgrp, event->cft, event->eventfd);
+
+	eventfd_ctx_put(event->eventfd);
+	kfree(event);
+	dput(cgrp->dentry);
+}
+
+/*
+ * Gets called on POLLHUP on eventfd when user closes it.
+ *
+ * Called with wqh->lock held and interrupts disabled.
+ */
+static int cgroup_event_wake(wait_queue_t *wait, unsigned mode,
+		int sync, void *key)
+{
+	struct cgroup_event *event = container_of(wait,
+			struct cgroup_event, wait);
+	struct cgroup *cgrp = event->cgrp;
+	unsigned long flags = (unsigned long)key;
+
+	if (flags & POLLHUP) {
+		remove_wait_queue_locked(event->wqh, &event->wait);
+		spin_lock(&cgrp->event_list_lock);
+		list_del(&event->list);
+		spin_unlock(&cgrp->event_list_lock);
+		/*
+		 * We are in atomic context, but cgroup_event_remove() may
+		 * sleep, so we have to call it in workqueue.
+		 */
+		schedule_work(&event->remove);
+	}
+
+	return 0;
+}
+
+static void cgroup_event_ptable_queue_proc(struct file *file,
+		wait_queue_head_t *wqh, poll_table *pt)
+{
+	struct cgroup_event *event = container_of(pt,
+			struct cgroup_event, pt);
+
+	event->wqh = wqh;
+	add_wait_queue(wqh, &event->wait);
+}
+
+/*
+ * Parse input and register new cgroup event handler.
+ *
+ * Input must be in format '<event_fd> <control_fd> <args>'.
+ * Interpretation of args is defined by control file implementation.
+ */
+static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
+				      const char *buffer)
+{
+	struct cgroup_event *event = NULL;
+	unsigned int efd, cfd;
+	struct file *efile = NULL;
+	struct file *cfile = NULL;
+	char *endp;
+	int ret;
+
+	efd = simple_strtoul(buffer, &endp, 10);
+	if (*endp != ' ')
+		return -EINVAL;
+	buffer = endp + 1;
+
+	cfd = simple_strtoul(buffer, &endp, 10);
+	if ((*endp != ' ') && (*endp != '\0'))
+		return -EINVAL;
+	buffer = endp + 1;
+
+	event = kzalloc(sizeof(*event), GFP_KERNEL);
+	if (!event)
+		return -ENOMEM;
+	event->cgrp = cgrp;
+	INIT_LIST_HEAD(&event->list);
+	init_poll_funcptr(&event->pt, cgroup_event_ptable_queue_proc);
+	init_waitqueue_func_entry(&event->wait, cgroup_event_wake);
+	INIT_WORK(&event->remove, cgroup_event_remove);
+
+	efile = eventfd_fget(efd);
+	if (IS_ERR(efile)) {
+		ret = PTR_ERR(efile);
+		goto fail;
+	}
+
+	event->eventfd = eventfd_ctx_fileget(efile);
+	if (IS_ERR(event->eventfd)) {
+		ret = PTR_ERR(event->eventfd);
+		goto fail;
+	}
+
+	cfile = fget(cfd);
+	if (!cfile) {
+		ret = -EBADF;
+		goto fail;
+	}
+
+	/* the process need read permission on control file */
+	ret = file_permission(cfile, MAY_READ);
+	if (ret < 0)
+		goto fail;
+
+	event->cft = __file_cft(cfile);
+	if (IS_ERR(event->cft)) {
+		ret = PTR_ERR(event->cft);
+		goto fail;
+	}
+
+	if (!event->cft->register_event || !event->cft->unregister_event) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	ret = event->cft->register_event(cgrp, event->cft,
+			event->eventfd, buffer);
+	if (ret)
+		goto fail;
+
+	if (efile->f_op->poll(efile, &event->pt) & POLLHUP) {
+		event->cft->unregister_event(cgrp, event->cft, event->eventfd);
+		ret = 0;
+		goto fail;
+	}
+
+	/*
+	 * Events should be removed after rmdir of cgroup directory, but before
+	 * destroying subsystem state objects. Let's take reference to cgroup
+	 * directory dentry to do that.
+	 */
+	dget(cgrp->dentry);
+
+	spin_lock(&cgrp->event_list_lock);
+	list_add(&event->list, &cgrp->event_list);
+	spin_unlock(&cgrp->event_list_lock);
+
+	fput(cfile);
+	fput(efile);
+
+	return 0;
+
+fail:
+	if (cfile)
+		fput(cfile);
+
+	if (event && event->eventfd && !IS_ERR(event->eventfd))
+		eventfd_ctx_put(event->eventfd);
+
+	if (!IS_ERR_OR_NULL(efile))
+		fput(efile);
+
+	kfree(event);
+
+	return ret;
+}
+
+/*
  * for the common functions, 'private' gives the type of file
  */
 /* for hysterical raisins, we can't put this on the older files */
@@ -2828,6 +3171,11 @@
 		.read_u64 = cgroup_read_notify_on_release,
 		.write_u64 = cgroup_write_notify_on_release,
 	},
+	{
+		.name = CGROUP_FILE_GENERIC_PREFIX "event_control",
+		.write_string = cgroup_write_event_control,
+		.mode = S_IWUGO,
+	},
 };
 
 static struct cftype cft_release_agent = {
@@ -2892,8 +3240,14 @@
 	/* We need to take each hierarchy_mutex in a consistent order */
 	int i;
 
+	/*
+	 * No worry about a race with rebind_subsystems that might mess up the
+	 * locking order, since both parties are under cgroup_mutex.
+	 */
 	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
 		struct cgroup_subsys *ss = subsys[i];
+		if (ss == NULL)
+			continue;
 		if (ss->root == root)
 			mutex_lock(&ss->hierarchy_mutex);
 	}
@@ -2905,6 +3259,8 @@
 
 	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
 		struct cgroup_subsys *ss = subsys[i];
+		if (ss == NULL)
+			continue;
 		if (ss->root == root)
 			mutex_unlock(&ss->hierarchy_mutex);
 	}
@@ -3028,11 +3384,16 @@
 	 * synchronization other than RCU, and the subsystem linked
 	 * list isn't RCU-safe */
 	int i;
+	/*
+	 * We won't need to lock the subsys array, because the subsystems
+	 * we're concerned about aren't going anywhere since our cgroup root
+	 * has a reference on them.
+	 */
 	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
 		struct cgroup_subsys *ss = subsys[i];
 		struct cgroup_subsys_state *css;
-		/* Skip subsystems not in this hierarchy */
-		if (ss->root != cgrp->root)
+		/* Skip subsystems not present or not in this hierarchy */
+		if (ss == NULL || ss->root != cgrp->root)
 			continue;
 		css = cgrp->subsys[ss->subsys_id];
 		/* When called from check_for_release() it's possible
@@ -3106,6 +3467,7 @@
 	struct dentry *d;
 	struct cgroup *parent;
 	DEFINE_WAIT(wait);
+	struct cgroup_event *event, *tmp;
 	int ret;
 
 	/* the vfs holds both inode->i_mutex already */
@@ -3189,6 +3551,20 @@
 	set_bit(CGRP_RELEASABLE, &parent->flags);
 	check_for_release(parent);
 
+	/*
+	 * Unregister events and notify userspace.
+	 * Notify userspace about cgroup removing only after rmdir of cgroup
+	 * directory to avoid race between userspace and kernelspace
+	 */
+	spin_lock(&cgrp->event_list_lock);
+	list_for_each_entry_safe(event, tmp, &cgrp->event_list, list) {
+		list_del(&event->list);
+		remove_wait_queue(event->wqh, &event->wait);
+		eventfd_signal(event->eventfd, 1);
+		schedule_work(&event->remove);
+	}
+	spin_unlock(&cgrp->event_list_lock);
+
 	mutex_unlock(&cgroup_mutex);
 	return 0;
 }
@@ -3223,9 +3599,198 @@
 	mutex_init(&ss->hierarchy_mutex);
 	lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key);
 	ss->active = 1;
+
+	/* this function shouldn't be used with modular subsystems, since they
+	 * need to register a subsys_id, among other things */
+	BUG_ON(ss->module);
 }
 
 /**
+ * cgroup_load_subsys: load and register a modular subsystem at runtime
+ * @ss: the subsystem to load
+ *
+ * This function should be called in a modular subsystem's initcall. If the
+ * subsytem is built as a module, it will be assigned a new subsys_id and set
+ * up for use. If the subsystem is built-in anyway, work is delegated to the
+ * simpler cgroup_init_subsys.
+ */
+int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
+{
+	int i;
+	struct cgroup_subsys_state *css;
+
+	/* check name and function validity */
+	if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN ||
+	    ss->create == NULL || ss->destroy == NULL)
+		return -EINVAL;
+
+	/*
+	 * we don't support callbacks in modular subsystems. this check is
+	 * before the ss->module check for consistency; a subsystem that could
+	 * be a module should still have no callbacks even if the user isn't
+	 * compiling it as one.
+	 */
+	if (ss->fork || ss->exit)
+		return -EINVAL;
+
+	/*
+	 * an optionally modular subsystem is built-in: we want to do nothing,
+	 * since cgroup_init_subsys will have already taken care of it.
+	 */
+	if (ss->module == NULL) {
+		/* a few sanity checks */
+		BUG_ON(ss->subsys_id >= CGROUP_BUILTIN_SUBSYS_COUNT);
+		BUG_ON(subsys[ss->subsys_id] != ss);
+		return 0;
+	}
+
+	/*
+	 * need to register a subsys id before anything else - for example,
+	 * init_cgroup_css needs it.
+	 */
+	mutex_lock(&cgroup_mutex);
+	/* find the first empty slot in the array */
+	for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) {
+		if (subsys[i] == NULL)
+			break;
+	}
+	if (i == CGROUP_SUBSYS_COUNT) {
+		/* maximum number of subsystems already registered! */
+		mutex_unlock(&cgroup_mutex);
+		return -EBUSY;
+	}
+	/* assign ourselves the subsys_id */
+	ss->subsys_id = i;
+	subsys[i] = ss;
+
+	/*
+	 * no ss->create seems to need anything important in the ss struct, so
+	 * this can happen first (i.e. before the rootnode attachment).
+	 */
+	css = ss->create(ss, dummytop);
+	if (IS_ERR(css)) {
+		/* failure case - need to deassign the subsys[] slot. */
+		subsys[i] = NULL;
+		mutex_unlock(&cgroup_mutex);
+		return PTR_ERR(css);
+	}
+
+	list_add(&ss->sibling, &rootnode.subsys_list);
+	ss->root = &rootnode;
+
+	/* our new subsystem will be attached to the dummy hierarchy. */
+	init_cgroup_css(css, ss, dummytop);
+	/* init_idr must be after init_cgroup_css because it sets css->id. */
+	if (ss->use_id) {
+		int ret = cgroup_init_idr(ss, css);
+		if (ret) {
+			dummytop->subsys[ss->subsys_id] = NULL;
+			ss->destroy(ss, dummytop);
+			subsys[i] = NULL;
+			mutex_unlock(&cgroup_mutex);
+			return ret;
+		}
+	}
+
+	/*
+	 * Now we need to entangle the css into the existing css_sets. unlike
+	 * in cgroup_init_subsys, there are now multiple css_sets, so each one
+	 * will need a new pointer to it; done by iterating the css_set_table.
+	 * furthermore, modifying the existing css_sets will corrupt the hash
+	 * table state, so each changed css_set will need its hash recomputed.
+	 * this is all done under the css_set_lock.
+	 */
+	write_lock(&css_set_lock);
+	for (i = 0; i < CSS_SET_TABLE_SIZE; i++) {
+		struct css_set *cg;
+		struct hlist_node *node, *tmp;
+		struct hlist_head *bucket = &css_set_table[i], *new_bucket;
+
+		hlist_for_each_entry_safe(cg, node, tmp, bucket, hlist) {
+			/* skip entries that we already rehashed */
+			if (cg->subsys[ss->subsys_id])
+				continue;
+			/* remove existing entry */
+			hlist_del(&cg->hlist);
+			/* set new value */
+			cg->subsys[ss->subsys_id] = css;
+			/* recompute hash and restore entry */
+			new_bucket = css_set_hash(cg->subsys);
+			hlist_add_head(&cg->hlist, new_bucket);
+		}
+	}
+	write_unlock(&css_set_lock);
+
+	mutex_init(&ss->hierarchy_mutex);
+	lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key);
+	ss->active = 1;
+
+	/* success! */
+	mutex_unlock(&cgroup_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cgroup_load_subsys);
+
+/**
+ * cgroup_unload_subsys: unload a modular subsystem
+ * @ss: the subsystem to unload
+ *
+ * This function should be called in a modular subsystem's exitcall. When this
+ * function is invoked, the refcount on the subsystem's module will be 0, so
+ * the subsystem will not be attached to any hierarchy.
+ */
+void cgroup_unload_subsys(struct cgroup_subsys *ss)
+{
+	struct cg_cgroup_link *link;
+	struct hlist_head *hhead;
+
+	BUG_ON(ss->module == NULL);
+
+	/*
+	 * we shouldn't be called if the subsystem is in use, and the use of
+	 * try_module_get in parse_cgroupfs_options should ensure that it
+	 * doesn't start being used while we're killing it off.
+	 */
+	BUG_ON(ss->root != &rootnode);
+
+	mutex_lock(&cgroup_mutex);
+	/* deassign the subsys_id */
+	BUG_ON(ss->subsys_id < CGROUP_BUILTIN_SUBSYS_COUNT);
+	subsys[ss->subsys_id] = NULL;
+
+	/* remove subsystem from rootnode's list of subsystems */
+	list_del(&ss->sibling);
+
+	/*
+	 * disentangle the css from all css_sets attached to the dummytop. as
+	 * in loading, we need to pay our respects to the hashtable gods.
+	 */
+	write_lock(&css_set_lock);
+	list_for_each_entry(link, &dummytop->css_sets, cgrp_link_list) {
+		struct css_set *cg = link->cg;
+
+		hlist_del(&cg->hlist);
+		BUG_ON(!cg->subsys[ss->subsys_id]);
+		cg->subsys[ss->subsys_id] = NULL;
+		hhead = css_set_hash(cg->subsys);
+		hlist_add_head(&cg->hlist, hhead);
+	}
+	write_unlock(&css_set_lock);
+
+	/*
+	 * remove subsystem's css from the dummytop and free it - need to free
+	 * before marking as null because ss->destroy needs the cgrp->subsys
+	 * pointer to find their state. note that this also takes care of
+	 * freeing the css_id.
+	 */
+	ss->destroy(ss, dummytop);
+	dummytop->subsys[ss->subsys_id] = NULL;
+
+	mutex_unlock(&cgroup_mutex);
+}
+EXPORT_SYMBOL_GPL(cgroup_unload_subsys);
+
+/**
  * cgroup_init_early - cgroup initialization at system boot
  *
  * Initialize cgroups at system boot, and initialize any
@@ -3253,7 +3818,8 @@
 	for (i = 0; i < CSS_SET_TABLE_SIZE; i++)
 		INIT_HLIST_HEAD(&css_set_table[i]);
 
-	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+	/* at bootup time, we don't worry about modular subsystems */
+	for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
 		struct cgroup_subsys *ss = subsys[i];
 
 		BUG_ON(!ss->name);
@@ -3288,12 +3854,13 @@
 	if (err)
 		return err;
 
-	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+	/* at bootup time, we don't worry about modular subsystems */
+	for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
 		struct cgroup_subsys *ss = subsys[i];
 		if (!ss->early_init)
 			cgroup_init_subsys(ss);
 		if (ss->use_id)
-			cgroup_subsys_init_idr(ss);
+			cgroup_init_idr(ss, init_css_set.subsys[ss->subsys_id]);
 	}
 
 	/* Add init_css_set to the hash table */
@@ -3397,9 +3964,16 @@
 	int i;
 
 	seq_puts(m, "#subsys_name\thierarchy\tnum_cgroups\tenabled\n");
+	/*
+	 * ideally we don't want subsystems moving around while we do this.
+	 * cgroup_mutex is also necessary to guarantee an atomic snapshot of
+	 * subsys/hierarchy state.
+	 */
 	mutex_lock(&cgroup_mutex);
 	for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
 		struct cgroup_subsys *ss = subsys[i];
+		if (ss == NULL)
+			continue;
 		seq_printf(m, "%s\t%d\t%d\t%d\n",
 			   ss->name, ss->root->hierarchy_id,
 			   ss->root->number_of_cgroups, !ss->disabled);
@@ -3457,7 +4031,12 @@
 {
 	if (need_forkexit_callback) {
 		int i;
-		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+		/*
+		 * forkexit callbacks are only supported for builtin
+		 * subsystems, and the builtin section of the subsys array is
+		 * immutable, so we don't need to lock the subsys array here.
+		 */
+		for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
 			struct cgroup_subsys *ss = subsys[i];
 			if (ss->fork)
 				ss->fork(ss, child);
@@ -3526,7 +4105,11 @@
 	struct css_set *cg;
 
 	if (run_callbacks && need_forkexit_callback) {
-		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+		/*
+		 * modular subsystems can't use callbacks, so no need to lock
+		 * the subsys array
+		 */
+		for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
 			struct cgroup_subsys *ss = subsys[i];
 			if (ss->exit)
 				ss->exit(ss, tsk);
@@ -3720,12 +4303,13 @@
 	}
 }
 
-void __css_put(struct cgroup_subsys_state *css)
+/* Caller must verify that the css is not for root cgroup */
+void __css_put(struct cgroup_subsys_state *css, int count)
 {
 	struct cgroup *cgrp = css->cgroup;
 	int val;
 	rcu_read_lock();
-	val = atomic_dec_return(&css->refcnt);
+	val = atomic_sub_return(count, &css->refcnt);
 	if (val == 1) {
 		if (notify_on_release(cgrp)) {
 			set_bit(CGRP_RELEASABLE, &cgrp->flags);
@@ -3736,6 +4320,7 @@
 	rcu_read_unlock();
 	WARN_ON_ONCE(val < 1);
 }
+EXPORT_SYMBOL_GPL(__css_put);
 
 /*
  * Notify userspace when a cgroup is released, by running the
@@ -3817,8 +4402,11 @@
 	while ((token = strsep(&str, ",")) != NULL) {
 		if (!*token)
 			continue;
-
-		for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+		/*
+		 * cgroup_disable, being at boot time, can't know about module
+		 * subsystems, so we don't worry about them.
+		 */
+		for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
 			struct cgroup_subsys *ss = subsys[i];
 
 			if (!strcmp(token, ss->name)) {
@@ -3848,6 +4436,7 @@
 		return cssid->id;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(css_id);
 
 unsigned short css_depth(struct cgroup_subsys_state *css)
 {
@@ -3857,6 +4446,7 @@
 		return cssid->depth;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(css_depth);
 
 bool css_is_ancestor(struct cgroup_subsys_state *child,
 		    const struct cgroup_subsys_state *root)
@@ -3893,6 +4483,7 @@
 	spin_unlock(&ss->id_lock);
 	call_rcu(&id->rcu_head, __free_css_id_cb);
 }
+EXPORT_SYMBOL_GPL(free_css_id);
 
 /*
  * This is called by init or create(). Then, calls to this function are
@@ -3942,15 +4533,14 @@
 
 }
 
-static int __init cgroup_subsys_init_idr(struct cgroup_subsys *ss)
+static int __init_or_module cgroup_init_idr(struct cgroup_subsys *ss,
+					    struct cgroup_subsys_state *rootcss)
 {
 	struct css_id *newid;
-	struct cgroup_subsys_state *rootcss;
 
 	spin_lock_init(&ss->id_lock);
 	idr_init(&ss->idr);
 
-	rootcss = init_css_set.subsys[ss->subsys_id];
 	newid = get_new_cssid(ss, 0);
 	if (IS_ERR(newid))
 		return PTR_ERR(newid);
@@ -4010,6 +4600,7 @@
 
 	return rcu_dereference(cssid->css);
 }
+EXPORT_SYMBOL_GPL(css_lookup);
 
 /**
  * css_get_next - lookup next cgroup under specified hierarchy.
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 677f253..f8cced2 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -338,7 +338,7 @@
 	if (!cpu_possible(cpu)) {
 		printk(KERN_ERR "can't online cpu %d because it is not "
 			"configured as may-hotadd at boot time\n", cpu);
-#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
+#if defined(CONFIG_IA64)
 		printk(KERN_ERR "please check additional_cpus= boot "
 				"parameter\n");
 #endif
diff --git a/kernel/early_res.c b/kernel/early_res.c
new file mode 100644
index 0000000..3cb2c66
--- /dev/null
+++ b/kernel/early_res.c
@@ -0,0 +1,578 @@
+/*
+ * early_res, could be used to replace bootmem
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/early_res.h>
+
+/*
+ * Early reserved memory areas.
+ */
+/*
+ * need to make sure this one is bigger enough before
+ * find_fw_memmap_area could be used
+ */
+#define MAX_EARLY_RES_X 32
+
+struct early_res {
+	u64 start, end;
+	char name[15];
+	char overlap_ok;
+};
+static struct early_res early_res_x[MAX_EARLY_RES_X] __initdata;
+
+static int max_early_res __initdata = MAX_EARLY_RES_X;
+static struct early_res *early_res __initdata = &early_res_x[0];
+static int early_res_count __initdata;
+
+static int __init find_overlapped_early(u64 start, u64 end)
+{
+	int i;
+	struct early_res *r;
+
+	for (i = 0; i < max_early_res && early_res[i].end; i++) {
+		r = &early_res[i];
+		if (end > r->start && start < r->end)
+			break;
+	}
+
+	return i;
+}
+
+/*
+ * Drop the i-th range from the early reservation map,
+ * by copying any higher ranges down one over it, and
+ * clearing what had been the last slot.
+ */
+static void __init drop_range(int i)
+{
+	int j;
+
+	for (j = i + 1; j < max_early_res && early_res[j].end; j++)
+		;
+
+	memmove(&early_res[i], &early_res[i + 1],
+	       (j - 1 - i) * sizeof(struct early_res));
+
+	early_res[j - 1].end = 0;
+	early_res_count--;
+}
+
+static void __init drop_range_partial(int i, u64 start, u64 end)
+{
+	u64 common_start, common_end;
+	u64 old_start, old_end;
+
+	old_start = early_res[i].start;
+	old_end = early_res[i].end;
+	common_start = max(old_start, start);
+	common_end = min(old_end, end);
+
+	/* no overlap ? */
+	if (common_start >= common_end)
+		return;
+
+	if (old_start < common_start) {
+		/* make head segment */
+		early_res[i].end = common_start;
+		if (old_end > common_end) {
+			char name[15];
+
+			/*
+			 * Save a local copy of the name, since the
+			 * early_res array could get resized inside
+			 * reserve_early_without_check() ->
+			 * __check_and_double_early_res(), which would
+			 * make the current name pointer invalid.
+			 */
+			strncpy(name, early_res[i].name,
+					 sizeof(early_res[i].name) - 1);
+			/* add another for left over on tail */
+			reserve_early_without_check(common_end, old_end, name);
+		}
+		return;
+	} else {
+		if (old_end > common_end) {
+			/* reuse the entry for tail left */
+			early_res[i].start = common_end;
+			return;
+		}
+		/* all covered */
+		drop_range(i);
+	}
+}
+
+/*
+ * Split any existing ranges that:
+ *  1) are marked 'overlap_ok', and
+ *  2) overlap with the stated range [start, end)
+ * into whatever portion (if any) of the existing range is entirely
+ * below or entirely above the stated range.  Drop the portion
+ * of the existing range that overlaps with the stated range,
+ * which will allow the caller of this routine to then add that
+ * stated range without conflicting with any existing range.
+ */
+static void __init drop_overlaps_that_are_ok(u64 start, u64 end)
+{
+	int i;
+	struct early_res *r;
+	u64 lower_start, lower_end;
+	u64 upper_start, upper_end;
+	char name[15];
+
+	for (i = 0; i < max_early_res && early_res[i].end; i++) {
+		r = &early_res[i];
+
+		/* Continue past non-overlapping ranges */
+		if (end <= r->start || start >= r->end)
+			continue;
+
+		/*
+		 * Leave non-ok overlaps as is; let caller
+		 * panic "Overlapping early reservations"
+		 * when it hits this overlap.
+		 */
+		if (!r->overlap_ok)
+			return;
+
+		/*
+		 * We have an ok overlap.  We will drop it from the early
+		 * reservation map, and add back in any non-overlapping
+		 * portions (lower or upper) as separate, overlap_ok,
+		 * non-overlapping ranges.
+		 */
+
+		/* 1. Note any non-overlapping (lower or upper) ranges. */
+		strncpy(name, r->name, sizeof(name) - 1);
+
+		lower_start = lower_end = 0;
+		upper_start = upper_end = 0;
+		if (r->start < start) {
+			lower_start = r->start;
+			lower_end = start;
+		}
+		if (r->end > end) {
+			upper_start = end;
+			upper_end = r->end;
+		}
+
+		/* 2. Drop the original ok overlapping range */
+		drop_range(i);
+
+		i--;		/* resume for-loop on copied down entry */
+
+		/* 3. Add back in any non-overlapping ranges. */
+		if (lower_end)
+			reserve_early_overlap_ok(lower_start, lower_end, name);
+		if (upper_end)
+			reserve_early_overlap_ok(upper_start, upper_end, name);
+	}
+}
+
+static void __init __reserve_early(u64 start, u64 end, char *name,
+						int overlap_ok)
+{
+	int i;
+	struct early_res *r;
+
+	i = find_overlapped_early(start, end);
+	if (i >= max_early_res)
+		panic("Too many early reservations");
+	r = &early_res[i];
+	if (r->end)
+		panic("Overlapping early reservations "
+		      "%llx-%llx %s to %llx-%llx %s\n",
+		      start, end - 1, name ? name : "", r->start,
+		      r->end - 1, r->name);
+	r->start = start;
+	r->end = end;
+	r->overlap_ok = overlap_ok;
+	if (name)
+		strncpy(r->name, name, sizeof(r->name) - 1);
+	early_res_count++;
+}
+
+/*
+ * A few early reservtations come here.
+ *
+ * The 'overlap_ok' in the name of this routine does -not- mean it
+ * is ok for these reservations to overlap an earlier reservation.
+ * Rather it means that it is ok for subsequent reservations to
+ * overlap this one.
+ *
+ * Use this entry point to reserve early ranges when you are doing
+ * so out of "Paranoia", reserving perhaps more memory than you need,
+ * just in case, and don't mind a subsequent overlapping reservation
+ * that is known to be needed.
+ *
+ * The drop_overlaps_that_are_ok() call here isn't really needed.
+ * It would be needed if we had two colliding 'overlap_ok'
+ * reservations, so that the second such would not panic on the
+ * overlap with the first.  We don't have any such as of this
+ * writing, but might as well tolerate such if it happens in
+ * the future.
+ */
+void __init reserve_early_overlap_ok(u64 start, u64 end, char *name)
+{
+	drop_overlaps_that_are_ok(start, end);
+	__reserve_early(start, end, name, 1);
+}
+
+static void __init __check_and_double_early_res(u64 ex_start, u64 ex_end)
+{
+	u64 start, end, size, mem;
+	struct early_res *new;
+
+	/* do we have enough slots left ? */
+	if ((max_early_res - early_res_count) > max(max_early_res/8, 2))
+		return;
+
+	/* double it */
+	mem = -1ULL;
+	size = sizeof(struct early_res) * max_early_res * 2;
+	if (early_res == early_res_x)
+		start = 0;
+	else
+		start = early_res[0].end;
+	end = ex_start;
+	if (start + size < end)
+		mem = find_fw_memmap_area(start, end, size,
+					 sizeof(struct early_res));
+	if (mem == -1ULL) {
+		start = ex_end;
+		end = get_max_mapped();
+		if (start + size < end)
+			mem = find_fw_memmap_area(start, end, size,
+						 sizeof(struct early_res));
+	}
+	if (mem == -1ULL)
+		panic("can not find more space for early_res array");
+
+	new = __va(mem);
+	/* save the first one for own */
+	new[0].start = mem;
+	new[0].end = mem + size;
+	new[0].overlap_ok = 0;
+	/* copy old to new */
+	if (early_res == early_res_x) {
+		memcpy(&new[1], &early_res[0],
+			 sizeof(struct early_res) * max_early_res);
+		memset(&new[max_early_res+1], 0,
+			 sizeof(struct early_res) * (max_early_res - 1));
+		early_res_count++;
+	} else {
+		memcpy(&new[1], &early_res[1],
+			 sizeof(struct early_res) * (max_early_res - 1));
+		memset(&new[max_early_res], 0,
+			 sizeof(struct early_res) * max_early_res);
+	}
+	memset(&early_res[0], 0, sizeof(struct early_res) * max_early_res);
+	early_res = new;
+	max_early_res *= 2;
+	printk(KERN_DEBUG "early_res array is doubled to %d at [%llx - %llx]\n",
+		max_early_res, mem, mem + size - 1);
+}
+
+/*
+ * Most early reservations come here.
+ *
+ * We first have drop_overlaps_that_are_ok() drop any pre-existing
+ * 'overlap_ok' ranges, so that we can then reserve this memory
+ * range without risk of panic'ing on an overlapping overlap_ok
+ * early reservation.
+ */
+void __init reserve_early(u64 start, u64 end, char *name)
+{
+	if (start >= end)
+		return;
+
+	__check_and_double_early_res(start, end);
+
+	drop_overlaps_that_are_ok(start, end);
+	__reserve_early(start, end, name, 0);
+}
+
+void __init reserve_early_without_check(u64 start, u64 end, char *name)
+{
+	struct early_res *r;
+
+	if (start >= end)
+		return;
+
+	__check_and_double_early_res(start, end);
+
+	r = &early_res[early_res_count];
+
+	r->start = start;
+	r->end = end;
+	r->overlap_ok = 0;
+	if (name)
+		strncpy(r->name, name, sizeof(r->name) - 1);
+	early_res_count++;
+}
+
+void __init free_early(u64 start, u64 end)
+{
+	struct early_res *r;
+	int i;
+
+	i = find_overlapped_early(start, end);
+	r = &early_res[i];
+	if (i >= max_early_res || r->end != end || r->start != start)
+		panic("free_early on not reserved area: %llx-%llx!",
+			 start, end - 1);
+
+	drop_range(i);
+}
+
+void __init free_early_partial(u64 start, u64 end)
+{
+	struct early_res *r;
+	int i;
+
+try_next:
+	i = find_overlapped_early(start, end);
+	if (i >= max_early_res)
+		return;
+
+	r = &early_res[i];
+	/* hole ? */
+	if (r->end >= end && r->start <= start) {
+		drop_range_partial(i, start, end);
+		return;
+	}
+
+	drop_range_partial(i, start, end);
+	goto try_next;
+}
+
+#ifdef CONFIG_NO_BOOTMEM
+static void __init subtract_early_res(struct range *range, int az)
+{
+	int i, count;
+	u64 final_start, final_end;
+	int idx = 0;
+
+	count  = 0;
+	for (i = 0; i < max_early_res && early_res[i].end; i++)
+		count++;
+
+	/* need to skip first one ?*/
+	if (early_res != early_res_x)
+		idx = 1;
+
+#define DEBUG_PRINT_EARLY_RES 1
+
+#if DEBUG_PRINT_EARLY_RES
+	printk(KERN_INFO "Subtract (%d early reservations)\n", count);
+#endif
+	for (i = idx; i < count; i++) {
+		struct early_res *r = &early_res[i];
+#if DEBUG_PRINT_EARLY_RES
+		printk(KERN_INFO "  #%d [%010llx - %010llx] %15s\n", i,
+			r->start, r->end, r->name);
+#endif
+		final_start = PFN_DOWN(r->start);
+		final_end = PFN_UP(r->end);
+		if (final_start >= final_end)
+			continue;
+		subtract_range(range, az, final_start, final_end);
+	}
+
+}
+
+int __init get_free_all_memory_range(struct range **rangep, int nodeid)
+{
+	int i, count;
+	u64 start = 0, end;
+	u64 size;
+	u64 mem;
+	struct range *range;
+	int nr_range;
+
+	count  = 0;
+	for (i = 0; i < max_early_res && early_res[i].end; i++)
+		count++;
+
+	count *= 2;
+
+	size = sizeof(struct range) * count;
+	end = get_max_mapped();
+#ifdef MAX_DMA32_PFN
+	if (end > (MAX_DMA32_PFN << PAGE_SHIFT))
+		start = MAX_DMA32_PFN << PAGE_SHIFT;
+#endif
+	mem = find_fw_memmap_area(start, end, size, sizeof(struct range));
+	if (mem == -1ULL)
+		panic("can not find more space for range free");
+
+	range = __va(mem);
+	/* use early_node_map[] and early_res to get range array at first */
+	memset(range, 0, size);
+	nr_range = 0;
+
+	/* need to go over early_node_map to find out good range for node */
+	nr_range = add_from_early_node_map(range, count, nr_range, nodeid);
+#ifdef CONFIG_X86_32
+	subtract_range(range, count, max_low_pfn, -1ULL);
+#endif
+	subtract_early_res(range, count);
+	nr_range = clean_sort_range(range, count);
+
+	/* need to clear it ? */
+	if (nodeid == MAX_NUMNODES) {
+		memset(&early_res[0], 0,
+			 sizeof(struct early_res) * max_early_res);
+		early_res = NULL;
+		max_early_res = 0;
+	}
+
+	*rangep = range;
+	return nr_range;
+}
+#else
+void __init early_res_to_bootmem(u64 start, u64 end)
+{
+	int i, count;
+	u64 final_start, final_end;
+	int idx = 0;
+
+	count  = 0;
+	for (i = 0; i < max_early_res && early_res[i].end; i++)
+		count++;
+
+	/* need to skip first one ?*/
+	if (early_res != early_res_x)
+		idx = 1;
+
+	printk(KERN_INFO "(%d/%d early reservations) ==> bootmem [%010llx - %010llx]\n",
+			 count - idx, max_early_res, start, end);
+	for (i = idx; i < count; i++) {
+		struct early_res *r = &early_res[i];
+		printk(KERN_INFO "  #%d [%010llx - %010llx] %16s", i,
+			r->start, r->end, r->name);
+		final_start = max(start, r->start);
+		final_end = min(end, r->end);
+		if (final_start >= final_end) {
+			printk(KERN_CONT "\n");
+			continue;
+		}
+		printk(KERN_CONT " ==> [%010llx - %010llx]\n",
+			final_start, final_end);
+		reserve_bootmem_generic(final_start, final_end - final_start,
+				BOOTMEM_DEFAULT);
+	}
+	/* clear them */
+	memset(&early_res[0], 0, sizeof(struct early_res) * max_early_res);
+	early_res = NULL;
+	max_early_res = 0;
+	early_res_count = 0;
+}
+#endif
+
+/* Check for already reserved areas */
+static inline int __init bad_addr(u64 *addrp, u64 size, u64 align)
+{
+	int i;
+	u64 addr = *addrp;
+	int changed = 0;
+	struct early_res *r;
+again:
+	i = find_overlapped_early(addr, addr + size);
+	r = &early_res[i];
+	if (i < max_early_res && r->end) {
+		*addrp = addr = round_up(r->end, align);
+		changed = 1;
+		goto again;
+	}
+	return changed;
+}
+
+/* Check for already reserved areas */
+static inline int __init bad_addr_size(u64 *addrp, u64 *sizep, u64 align)
+{
+	int i;
+	u64 addr = *addrp, last;
+	u64 size = *sizep;
+	int changed = 0;
+again:
+	last = addr + size;
+	for (i = 0; i < max_early_res && early_res[i].end; i++) {
+		struct early_res *r = &early_res[i];
+		if (last > r->start && addr < r->start) {
+			size = r->start - addr;
+			changed = 1;
+			goto again;
+		}
+		if (last > r->end && addr < r->end) {
+			addr = round_up(r->end, align);
+			size = last - addr;
+			changed = 1;
+			goto again;
+		}
+		if (last <= r->end && addr >= r->start) {
+			(*sizep)++;
+			return 0;
+		}
+	}
+	if (changed) {
+		*addrp = addr;
+		*sizep = size;
+	}
+	return changed;
+}
+
+/*
+ * Find a free area with specified alignment in a specific range.
+ * only with the area.between start to end is active range from early_node_map
+ * so they are good as RAM
+ */
+u64 __init find_early_area(u64 ei_start, u64 ei_last, u64 start, u64 end,
+			 u64 size, u64 align)
+{
+	u64 addr, last;
+
+	addr = round_up(ei_start, align);
+	if (addr < start)
+		addr = round_up(start, align);
+	if (addr >= ei_last)
+		goto out;
+	while (bad_addr(&addr, size, align) && addr+size <= ei_last)
+		;
+	last = addr + size;
+	if (last > ei_last)
+		goto out;
+	if (last > end)
+		goto out;
+
+	return addr;
+
+out:
+	return -1ULL;
+}
+
+u64 __init find_early_area_size(u64 ei_start, u64 ei_last, u64 start,
+			 u64 *sizep, u64 align)
+{
+	u64 addr, last;
+
+	addr = round_up(ei_start, align);
+	if (addr < start)
+		addr = round_up(start, align);
+	if (addr >= ei_last)
+		goto out;
+	*sizep = ei_last - addr;
+	while (bad_addr_size(&addr, sizep, align) && addr + *sizep <= ei_last)
+		;
+	last = addr + *sizep;
+	if (last > ei_last)
+		goto out;
+
+	return addr;
+
+out:
+	return -1ULL;
+}
diff --git a/kernel/elfcore.c b/kernel/elfcore.c
new file mode 100644
index 0000000..ff915ef
--- /dev/null
+++ b/kernel/elfcore.c
@@ -0,0 +1,28 @@
+#include <linux/elf.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/elf.h>
+
+
+Elf_Half __weak elf_core_extra_phdrs(void)
+{
+	return 0;
+}
+
+int __weak elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
+				      unsigned long limit)
+{
+	return 1;
+}
+
+int __weak elf_core_write_extra_data(struct file *file, size_t *size,
+				     unsigned long limit)
+{
+	return 1;
+}
+
+size_t __weak elf_core_extra_data_size(void)
+{
+	return 0;
+}
diff --git a/kernel/exit.c b/kernel/exit.c
index 45ed043..cce59cb 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -87,7 +87,7 @@
 
 	sighand = rcu_dereference_check(tsk->sighand,
 					rcu_read_lock_held() ||
-					lockdep_is_held(&tasklist_lock));
+					lockdep_tasklist_lock_is_held());
 	spin_lock(&sighand->siglock);
 
 	posix_cpu_timers_exit(tsk);
@@ -952,7 +952,8 @@
 				preempt_count());
 
 	acct_update_integrals(tsk);
-
+	/* sync mm's RSS info before statistics gathering */
+	sync_mm_rss(tsk, tsk->mm);
 	group_dead = atomic_dec_and_test(&tsk->signal->live);
 	if (group_dead) {
 		hrtimer_cancel(&tsk->signal->real_timer);
@@ -1188,7 +1189,7 @@
 
 	if (unlikely(wo->wo_flags & WNOWAIT)) {
 		int exit_code = p->exit_code;
-		int why, status;
+		int why;
 
 		get_task_struct(p);
 		read_unlock(&tasklist_lock);
diff --git a/kernel/fork.c b/kernel/fork.c
index 17bbf09..4799c5f 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -86,7 +86,14 @@
 DEFINE_PER_CPU(unsigned long, process_counts) = 0;
 
 __cacheline_aligned DEFINE_RWLOCK(tasklist_lock);  /* outer */
-EXPORT_SYMBOL_GPL(tasklist_lock);
+
+#ifdef CONFIG_PROVE_RCU
+int lockdep_tasklist_lock_is_held(void)
+{
+	return lockdep_is_held(&tasklist_lock);
+}
+EXPORT_SYMBOL_GPL(lockdep_tasklist_lock_is_held);
+#endif /* #ifdef CONFIG_PROVE_RCU */
 
 int nr_processes(void)
 {
@@ -329,15 +336,17 @@
 		if (!tmp)
 			goto fail_nomem;
 		*tmp = *mpnt;
+		INIT_LIST_HEAD(&tmp->anon_vma_chain);
 		pol = mpol_dup(vma_policy(mpnt));
 		retval = PTR_ERR(pol);
 		if (IS_ERR(pol))
 			goto fail_nomem_policy;
 		vma_set_policy(tmp, pol);
+		if (anon_vma_fork(tmp, mpnt))
+			goto fail_nomem_anon_vma_fork;
 		tmp->vm_flags &= ~VM_LOCKED;
 		tmp->vm_mm = mm;
 		tmp->vm_next = NULL;
-		anon_vma_link(tmp);
 		file = tmp->vm_file;
 		if (file) {
 			struct inode *inode = file->f_path.dentry->d_inode;
@@ -392,6 +401,8 @@
 	flush_tlb_mm(oldmm);
 	up_write(&oldmm->mmap_sem);
 	return retval;
+fail_nomem_anon_vma_fork:
+	mpol_put(pol);
 fail_nomem_policy:
 	kmem_cache_free(vm_area_cachep, tmp);
 fail_nomem:
@@ -455,8 +466,7 @@
 		(current->mm->flags & MMF_INIT_MASK) : default_dump_filter;
 	mm->core_state = NULL;
 	mm->nr_ptes = 0;
-	set_mm_counter(mm, file_rss, 0);
-	set_mm_counter(mm, anon_rss, 0);
+	memset(&mm->rss_stat, 0, sizeof(mm->rss_stat));
 	spin_lock_init(&mm->page_table_lock);
 	mm->free_area_cache = TASK_UNMAPPED_BASE;
 	mm->cached_hole_size = ~0UL;
@@ -825,23 +835,14 @@
  */
 static void posix_cpu_timers_init_group(struct signal_struct *sig)
 {
+	unsigned long cpu_limit;
+
 	/* Thread group counters. */
 	thread_group_cputime_init(sig);
 
-	/* Expiration times and increments. */
-	sig->it[CPUCLOCK_PROF].expires = cputime_zero;
-	sig->it[CPUCLOCK_PROF].incr = cputime_zero;
-	sig->it[CPUCLOCK_VIRT].expires = cputime_zero;
-	sig->it[CPUCLOCK_VIRT].incr = cputime_zero;
-
-	/* Cached expiration times. */
-	sig->cputime_expires.prof_exp = cputime_zero;
-	sig->cputime_expires.virt_exp = cputime_zero;
-	sig->cputime_expires.sched_exp = 0;
-
-	if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
-		sig->cputime_expires.prof_exp =
-			secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
+	cpu_limit = ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
+	if (cpu_limit != RLIM_INFINITY) {
+		sig->cputime_expires.prof_exp = secs_to_cputime(cpu_limit);
 		sig->cputimer.running = 1;
 	}
 
@@ -858,7 +859,7 @@
 	if (clone_flags & CLONE_THREAD)
 		return 0;
 
-	sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL);
+	sig = kmem_cache_zalloc(signal_cachep, GFP_KERNEL);
 	tsk->signal = sig;
 	if (!sig)
 		return -ENOMEM;
@@ -866,46 +867,21 @@
 	atomic_set(&sig->count, 1);
 	atomic_set(&sig->live, 1);
 	init_waitqueue_head(&sig->wait_chldexit);
-	sig->flags = 0;
 	if (clone_flags & CLONE_NEWPID)
 		sig->flags |= SIGNAL_UNKILLABLE;
-	sig->group_exit_code = 0;
-	sig->group_exit_task = NULL;
-	sig->group_stop_count = 0;
 	sig->curr_target = tsk;
 	init_sigpending(&sig->shared_pending);
 	INIT_LIST_HEAD(&sig->posix_timers);
 
 	hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-	sig->it_real_incr.tv64 = 0;
 	sig->real_timer.function = it_real_fn;
 
-	sig->leader = 0;	/* session leadership doesn't inherit */
-	sig->tty_old_pgrp = NULL;
-	sig->tty = NULL;
-
-	sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
-	sig->gtime = cputime_zero;
-	sig->cgtime = cputime_zero;
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
-	sig->prev_utime = sig->prev_stime = cputime_zero;
-#endif
-	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
-	sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
-	sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
-	sig->maxrss = sig->cmaxrss = 0;
-	task_io_accounting_init(&sig->ioac);
-	sig->sum_sched_runtime = 0;
-	taskstats_tgid_init(sig);
-
 	task_lock(current->group_leader);
 	memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim);
 	task_unlock(current->group_leader);
 
 	posix_cpu_timers_init_group(sig);
 
-	acct_init_pacct(&sig->pacct);
-
 	tty_audit_fork(sig);
 
 	sig->oom_adj = current->signal->oom_adj;
@@ -1034,7 +1010,7 @@
 #endif
 	retval = -EAGAIN;
 	if (atomic_read(&p->real_cred->user->processes) >=
-			p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
+			task_rlimit(p, RLIMIT_NPROC)) {
 		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
 		    p->real_cred->user != INIT_USER)
 			goto bad_fork_free;
diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c
index 967e6614..03808ed 100644
--- a/kernel/hw_breakpoint.c
+++ b/kernel/hw_breakpoint.c
@@ -413,17 +413,17 @@
  *
  * @return a set of per_cpu pointers to perf events
  */
-struct perf_event **
+struct perf_event * __percpu *
 register_wide_hw_breakpoint(struct perf_event_attr *attr,
 			    perf_overflow_handler_t triggered)
 {
-	struct perf_event **cpu_events, **pevent, *bp;
+	struct perf_event * __percpu *cpu_events, **pevent, *bp;
 	long err;
 	int cpu;
 
 	cpu_events = alloc_percpu(typeof(*cpu_events));
 	if (!cpu_events)
-		return ERR_PTR(-ENOMEM);
+		return (void __percpu __force *)ERR_PTR(-ENOMEM);
 
 	get_online_cpus();
 	for_each_online_cpu(cpu) {
@@ -451,7 +451,7 @@
 	put_online_cpus();
 
 	free_percpu(cpu_events);
-	return ERR_PTR(err);
+	return (void __percpu __force *)ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint);
 
@@ -459,7 +459,7 @@
  * unregister_wide_hw_breakpoint - unregister a wide breakpoint in the kernel
  * @cpu_events: the per cpu set of events to unregister
  */
-void unregister_wide_hw_breakpoint(struct perf_event **cpu_events)
+void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events)
 {
 	int cpu;
 	struct perf_event **pevent;
@@ -489,5 +489,4 @@
 	.enable		= arch_install_hw_breakpoint,
 	.disable	= arch_uninstall_hw_breakpoint,
 	.read		= hw_breakpoint_pmu_read,
-	.unthrottle	= hw_breakpoint_pmu_unthrottle
 };
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index ecc3fa2..42ec11b 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -18,11 +18,7 @@
 
 #include "internals.h"
 
-/**
- *	dynamic_irq_init - initialize a dynamically allocated irq
- *	@irq:	irq number to initialize
- */
-void dynamic_irq_init(unsigned int irq)
+static void dynamic_irq_init_x(unsigned int irq, bool keep_chip_data)
 {
 	struct irq_desc *desc;
 	unsigned long flags;
@@ -41,7 +37,8 @@
 	desc->depth = 1;
 	desc->msi_desc = NULL;
 	desc->handler_data = NULL;
-	desc->chip_data = NULL;
+	if (!keep_chip_data)
+		desc->chip_data = NULL;
 	desc->action = NULL;
 	desc->irq_count = 0;
 	desc->irqs_unhandled = 0;
@@ -55,10 +52,26 @@
 }
 
 /**
- *	dynamic_irq_cleanup - cleanup a dynamically allocated irq
+ *	dynamic_irq_init - initialize a dynamically allocated irq
  *	@irq:	irq number to initialize
  */
-void dynamic_irq_cleanup(unsigned int irq)
+void dynamic_irq_init(unsigned int irq)
+{
+	dynamic_irq_init_x(irq, false);
+}
+
+/**
+ *	dynamic_irq_init_keep_chip_data - initialize a dynamically allocated irq
+ *	@irq:	irq number to initialize
+ *
+ *	does not set irq_to_desc(irq)->chip_data to NULL
+ */
+void dynamic_irq_init_keep_chip_data(unsigned int irq)
+{
+	dynamic_irq_init_x(irq, true);
+}
+
+static void dynamic_irq_cleanup_x(unsigned int irq, bool keep_chip_data)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
@@ -77,7 +90,8 @@
 	}
 	desc->msi_desc = NULL;
 	desc->handler_data = NULL;
-	desc->chip_data = NULL;
+	if (!keep_chip_data)
+		desc->chip_data = NULL;
 	desc->handle_irq = handle_bad_irq;
 	desc->chip = &no_irq_chip;
 	desc->name = NULL;
@@ -85,6 +99,26 @@
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+/**
+ *	dynamic_irq_cleanup - cleanup a dynamically allocated irq
+ *	@irq:	irq number to initialize
+ */
+void dynamic_irq_cleanup(unsigned int irq)
+{
+	dynamic_irq_cleanup_x(irq, false);
+}
+
+/**
+ *	dynamic_irq_cleanup_keep_chip_data - cleanup a dynamically allocated irq
+ *	@irq:	irq number to initialize
+ *
+ *	does not set irq_to_desc(irq)->chip_data to NULL
+ */
+void dynamic_irq_cleanup_keep_chip_data(unsigned int irq)
+{
+	dynamic_irq_cleanup_x(irq, true);
+}
+
 
 /**
  *	set_irq_chip - set the irq chip for an irq
@@ -520,7 +554,7 @@
  *	signal. The occurence is latched into the irq controller hardware
  *	and must be acked in order to be reenabled. After the ack another
  *	interrupt can happen on the same source even before the first one
- *	is handled by the assosiacted event handler. If this happens it
+ *	is handled by the associated event handler. If this happens it
  *	might be necessary to disable (mask) the interrupt depending on the
  *	controller hardware. This requires to reenable the interrupt inside
  *	of the loop which handles the interrupts which have arrived while
diff --git a/kernel/irq/devres.c b/kernel/irq/devres.c
index d06df9c..1ef4ffc 100644
--- a/kernel/irq/devres.c
+++ b/kernel/irq/devres.c
@@ -42,7 +42,7 @@
  *	automatically freed on driver detach.
  *
  *	If an IRQ allocated with this function needs to be freed
- *	separately, dev_free_irq() must be used.
+ *	separately, devm_free_irq() must be used.
  */
 int devm_request_threaded_irq(struct device *dev, unsigned int irq,
 			      irq_handler_t handler, irq_handler_t thread_fn,
@@ -81,7 +81,7 @@
  *	Except for the extra @dev argument, this function takes the
  *	same arguments and performs the same function as free_irq().
  *	This function instead of free_irq() should be used to manually
- *	free IRQs allocated with dev_request_irq().
+ *	free IRQs allocated with devm_request_irq().
  */
 void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id)
 {
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 814940e..76d5a67 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -19,7 +19,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/rculist.h>
 #include <linux/hash.h>
-#include <linux/bootmem.h>
+#include <linux/radix-tree.h>
 #include <trace/events/irq.h>
 
 #include "internals.h"
@@ -87,12 +87,8 @@
 {
 	void *ptr;
 
-	if (slab_is_available())
-		ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs),
-				   GFP_ATOMIC, node);
-	else
-		ptr = alloc_bootmem_node(NODE_DATA(node),
-				nr * sizeof(*desc->kstat_irqs));
+	ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs),
+			   GFP_ATOMIC, node);
 
 	/*
 	 * don't overwite if can not get new one
@@ -132,7 +128,26 @@
  */
 DEFINE_RAW_SPINLOCK(sparse_irq_lock);
 
-struct irq_desc **irq_desc_ptrs __read_mostly;
+static RADIX_TREE(irq_desc_tree, GFP_ATOMIC);
+
+static void set_irq_desc(unsigned int irq, struct irq_desc *desc)
+{
+	radix_tree_insert(&irq_desc_tree, irq, desc);
+}
+
+struct irq_desc *irq_to_desc(unsigned int irq)
+{
+	return radix_tree_lookup(&irq_desc_tree, irq);
+}
+
+void replace_irq_desc(unsigned int irq, struct irq_desc *desc)
+{
+	void **ptr;
+
+	ptr = radix_tree_lookup_slot(&irq_desc_tree, irq);
+	if (ptr)
+		radix_tree_replace_slot(ptr, desc);
+}
 
 static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = {
 	[0 ... NR_IRQS_LEGACY-1] = {
@@ -164,9 +179,6 @@
 	legacy_count = ARRAY_SIZE(irq_desc_legacy);
 	node = first_online_node;
 
-	/* allocate irq_desc_ptrs array based on nr_irqs */
-	irq_desc_ptrs = kcalloc(nr_irqs, sizeof(void *), GFP_NOWAIT);
-
 	/* allocate based on nr_cpu_ids */
 	kstat_irqs_legacy = kzalloc_node(NR_IRQS_LEGACY * nr_cpu_ids *
 					  sizeof(int), GFP_NOWAIT, node);
@@ -180,23 +192,12 @@
 		lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
 		alloc_desc_masks(&desc[i], node, true);
 		init_desc_masks(&desc[i]);
-		irq_desc_ptrs[i] = desc + i;
+		set_irq_desc(i, &desc[i]);
 	}
 
-	for (i = legacy_count; i < nr_irqs; i++)
-		irq_desc_ptrs[i] = NULL;
-
 	return arch_early_irq_init();
 }
 
-struct irq_desc *irq_to_desc(unsigned int irq)
-{
-	if (irq_desc_ptrs && irq < nr_irqs)
-		return irq_desc_ptrs[irq];
-
-	return NULL;
-}
-
 struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
 {
 	struct irq_desc *desc;
@@ -208,21 +209,18 @@
 		return NULL;
 	}
 
-	desc = irq_desc_ptrs[irq];
+	desc = irq_to_desc(irq);
 	if (desc)
 		return desc;
 
 	raw_spin_lock_irqsave(&sparse_irq_lock, flags);
 
 	/* We have to check it to avoid races with another CPU */
-	desc = irq_desc_ptrs[irq];
+	desc = irq_to_desc(irq);
 	if (desc)
 		goto out_unlock;
 
-	if (slab_is_available())
-		desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
-	else
-		desc = alloc_bootmem_node(NODE_DATA(node), sizeof(*desc));
+	desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
 
 	printk(KERN_DEBUG "  alloc irq_desc for %d on node %d\n", irq, node);
 	if (!desc) {
@@ -231,7 +229,7 @@
 	}
 	init_one_irq_desc(irq, desc, node);
 
-	irq_desc_ptrs[irq] = desc;
+	set_irq_desc(irq, desc);
 
 out_unlock:
 	raw_spin_unlock_irqrestore(&sparse_irq_lock, flags);
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index b2821f0..c63f3bc 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -21,11 +21,7 @@
 extern raw_spinlock_t sparse_irq_lock;
 
 #ifdef CONFIG_SPARSE_IRQ
-/* irq_desc_ptrs allocated at boot time */
-extern struct irq_desc **irq_desc_ptrs;
-#else
-/* irq_desc_ptrs is a fixed size array */
-extern struct irq_desc *irq_desc_ptrs[NR_IRQS];
+void replace_irq_desc(unsigned int irq, struct irq_desc *desc);
 #endif
 
 #ifdef CONFIG_PROC_FS
diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c
index 26bac9d..963559d 100644
--- a/kernel/irq/numa_migrate.c
+++ b/kernel/irq/numa_migrate.c
@@ -70,7 +70,7 @@
 	raw_spin_lock_irqsave(&sparse_irq_lock, flags);
 
 	/* We have to check it to avoid races with another CPU */
-	desc = irq_desc_ptrs[irq];
+	desc = irq_to_desc(irq);
 
 	if (desc && old_desc != desc)
 		goto out_unlock;
@@ -90,7 +90,7 @@
 		goto out_unlock;
 	}
 
-	irq_desc_ptrs[irq] = desc;
+	replace_irq_desc(irq, desc);
 	raw_spin_unlock_irqrestore(&sparse_irq_lock, flags);
 
 	/* free the old one */
diff --git a/kernel/kexec.c b/kernel/kexec.c
index ef077fb..87ebe8a 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -41,7 +41,7 @@
 #include <asm/sections.h>
 
 /* Per cpu memory for storing cpu states in case of system crash. */
-note_buf_t* crash_notes;
+note_buf_t __percpu *crash_notes;
 
 /* vmcoreinfo stuff */
 static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index ccec774..fa034d2 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -42,9 +42,11 @@
 #include <linux/freezer.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
+#include <linux/sysctl.h>
 #include <linux/kdebug.h>
 #include <linux/memory.h>
 #include <linux/ftrace.h>
+#include <linux/cpu.h>
 
 #include <asm-generic/sections.h>
 #include <asm/cacheflush.h>
@@ -105,57 +107,74 @@
  * stepping on the instruction on a vmalloced/kmalloced/data page
  * is a recipe for disaster
  */
-#define INSNS_PER_PAGE	(PAGE_SIZE/(MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
-
 struct kprobe_insn_page {
 	struct list_head list;
 	kprobe_opcode_t *insns;		/* Page of instruction slots */
-	char slot_used[INSNS_PER_PAGE];
 	int nused;
 	int ngarbage;
+	char slot_used[];
 };
 
+#define KPROBE_INSN_PAGE_SIZE(slots)			\
+	(offsetof(struct kprobe_insn_page, slot_used) +	\
+	 (sizeof(char) * (slots)))
+
+struct kprobe_insn_cache {
+	struct list_head pages;	/* list of kprobe_insn_page */
+	size_t insn_size;	/* size of instruction slot */
+	int nr_garbage;
+};
+
+static int slots_per_page(struct kprobe_insn_cache *c)
+{
+	return PAGE_SIZE/(c->insn_size * sizeof(kprobe_opcode_t));
+}
+
 enum kprobe_slot_state {
 	SLOT_CLEAN = 0,
 	SLOT_DIRTY = 1,
 	SLOT_USED = 2,
 };
 
-static DEFINE_MUTEX(kprobe_insn_mutex);	/* Protects kprobe_insn_pages */
-static LIST_HEAD(kprobe_insn_pages);
-static int kprobe_garbage_slots;
-static int collect_garbage_slots(void);
+static DEFINE_MUTEX(kprobe_insn_mutex);	/* Protects kprobe_insn_slots */
+static struct kprobe_insn_cache kprobe_insn_slots = {
+	.pages = LIST_HEAD_INIT(kprobe_insn_slots.pages),
+	.insn_size = MAX_INSN_SIZE,
+	.nr_garbage = 0,
+};
+static int __kprobes collect_garbage_slots(struct kprobe_insn_cache *c);
 
 /**
  * __get_insn_slot() - Find a slot on an executable page for an instruction.
  * We allocate an executable page if there's no room on existing ones.
  */
-static kprobe_opcode_t __kprobes *__get_insn_slot(void)
+static kprobe_opcode_t __kprobes *__get_insn_slot(struct kprobe_insn_cache *c)
 {
 	struct kprobe_insn_page *kip;
 
  retry:
-	list_for_each_entry(kip, &kprobe_insn_pages, list) {
-		if (kip->nused < INSNS_PER_PAGE) {
+	list_for_each_entry(kip, &c->pages, list) {
+		if (kip->nused < slots_per_page(c)) {
 			int i;
-			for (i = 0; i < INSNS_PER_PAGE; i++) {
+			for (i = 0; i < slots_per_page(c); i++) {
 				if (kip->slot_used[i] == SLOT_CLEAN) {
 					kip->slot_used[i] = SLOT_USED;
 					kip->nused++;
-					return kip->insns + (i * MAX_INSN_SIZE);
+					return kip->insns + (i * c->insn_size);
 				}
 			}
-			/* Surprise!  No unused slots.  Fix kip->nused. */
-			kip->nused = INSNS_PER_PAGE;
+			/* kip->nused is broken. Fix it. */
+			kip->nused = slots_per_page(c);
+			WARN_ON(1);
 		}
 	}
 
 	/* If there are any garbage slots, collect it and try again. */
-	if (kprobe_garbage_slots && collect_garbage_slots() == 0) {
+	if (c->nr_garbage && collect_garbage_slots(c) == 0)
 		goto retry;
-	}
-	/* All out of space.  Need to allocate a new page. Use slot 0. */
-	kip = kmalloc(sizeof(struct kprobe_insn_page), GFP_KERNEL);
+
+	/* All out of space.  Need to allocate a new page. */
+	kip = kmalloc(KPROBE_INSN_PAGE_SIZE(slots_per_page(c)), GFP_KERNEL);
 	if (!kip)
 		return NULL;
 
@@ -170,20 +189,23 @@
 		return NULL;
 	}
 	INIT_LIST_HEAD(&kip->list);
-	list_add(&kip->list, &kprobe_insn_pages);
-	memset(kip->slot_used, SLOT_CLEAN, INSNS_PER_PAGE);
+	memset(kip->slot_used, SLOT_CLEAN, slots_per_page(c));
 	kip->slot_used[0] = SLOT_USED;
 	kip->nused = 1;
 	kip->ngarbage = 0;
+	list_add(&kip->list, &c->pages);
 	return kip->insns;
 }
 
+
 kprobe_opcode_t __kprobes *get_insn_slot(void)
 {
-	kprobe_opcode_t *ret;
+	kprobe_opcode_t *ret = NULL;
+
 	mutex_lock(&kprobe_insn_mutex);
-	ret = __get_insn_slot();
+	ret = __get_insn_slot(&kprobe_insn_slots);
 	mutex_unlock(&kprobe_insn_mutex);
+
 	return ret;
 }
 
@@ -199,7 +221,7 @@
 		 * so as not to have to set it up again the
 		 * next time somebody inserts a probe.
 		 */
-		if (!list_is_singular(&kprobe_insn_pages)) {
+		if (!list_is_singular(&kip->list)) {
 			list_del(&kip->list);
 			module_free(NULL, kip->insns);
 			kfree(kip);
@@ -209,51 +231,84 @@
 	return 0;
 }
 
-static int __kprobes collect_garbage_slots(void)
+static int __kprobes collect_garbage_slots(struct kprobe_insn_cache *c)
 {
 	struct kprobe_insn_page *kip, *next;
 
 	/* Ensure no-one is interrupted on the garbages */
 	synchronize_sched();
 
-	list_for_each_entry_safe(kip, next, &kprobe_insn_pages, list) {
+	list_for_each_entry_safe(kip, next, &c->pages, list) {
 		int i;
 		if (kip->ngarbage == 0)
 			continue;
 		kip->ngarbage = 0;	/* we will collect all garbages */
-		for (i = 0; i < INSNS_PER_PAGE; i++) {
+		for (i = 0; i < slots_per_page(c); i++) {
 			if (kip->slot_used[i] == SLOT_DIRTY &&
 			    collect_one_slot(kip, i))
 				break;
 		}
 	}
-	kprobe_garbage_slots = 0;
+	c->nr_garbage = 0;
 	return 0;
 }
 
+static void __kprobes __free_insn_slot(struct kprobe_insn_cache *c,
+				       kprobe_opcode_t *slot, int dirty)
+{
+	struct kprobe_insn_page *kip;
+
+	list_for_each_entry(kip, &c->pages, list) {
+		long idx = ((long)slot - (long)kip->insns) / c->insn_size;
+		if (idx >= 0 && idx < slots_per_page(c)) {
+			WARN_ON(kip->slot_used[idx] != SLOT_USED);
+			if (dirty) {
+				kip->slot_used[idx] = SLOT_DIRTY;
+				kip->ngarbage++;
+				if (++c->nr_garbage > slots_per_page(c))
+					collect_garbage_slots(c);
+			} else
+				collect_one_slot(kip, idx);
+			return;
+		}
+	}
+	/* Could not free this slot. */
+	WARN_ON(1);
+}
+
 void __kprobes free_insn_slot(kprobe_opcode_t * slot, int dirty)
 {
-	struct kprobe_insn_page *kip;
-
 	mutex_lock(&kprobe_insn_mutex);
-	list_for_each_entry(kip, &kprobe_insn_pages, list) {
-		if (kip->insns <= slot &&
-		    slot < kip->insns + (INSNS_PER_PAGE * MAX_INSN_SIZE)) {
-			int i = (slot - kip->insns) / MAX_INSN_SIZE;
-			if (dirty) {
-				kip->slot_used[i] = SLOT_DIRTY;
-				kip->ngarbage++;
-			} else
-				collect_one_slot(kip, i);
-			break;
-		}
-	}
-
-	if (dirty && ++kprobe_garbage_slots > INSNS_PER_PAGE)
-		collect_garbage_slots();
-
+	__free_insn_slot(&kprobe_insn_slots, slot, dirty);
 	mutex_unlock(&kprobe_insn_mutex);
 }
+#ifdef CONFIG_OPTPROBES
+/* For optimized_kprobe buffer */
+static DEFINE_MUTEX(kprobe_optinsn_mutex); /* Protects kprobe_optinsn_slots */
+static struct kprobe_insn_cache kprobe_optinsn_slots = {
+	.pages = LIST_HEAD_INIT(kprobe_optinsn_slots.pages),
+	/* .insn_size is initialized later */
+	.nr_garbage = 0,
+};
+/* Get a slot for optimized_kprobe buffer */
+kprobe_opcode_t __kprobes *get_optinsn_slot(void)
+{
+	kprobe_opcode_t *ret = NULL;
+
+	mutex_lock(&kprobe_optinsn_mutex);
+	ret = __get_insn_slot(&kprobe_optinsn_slots);
+	mutex_unlock(&kprobe_optinsn_mutex);
+
+	return ret;
+}
+
+void __kprobes free_optinsn_slot(kprobe_opcode_t * slot, int dirty)
+{
+	mutex_lock(&kprobe_optinsn_mutex);
+	__free_insn_slot(&kprobe_optinsn_slots, slot, dirty);
+	mutex_unlock(&kprobe_optinsn_mutex);
+}
+#endif
 #endif
 
 /* We have preemption disabled.. so it is safe to use __ versions */
@@ -284,23 +339,401 @@
 		if (p->addr == addr)
 			return p;
 	}
+
 	return NULL;
 }
 
+static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs);
+
+/* Return true if the kprobe is an aggregator */
+static inline int kprobe_aggrprobe(struct kprobe *p)
+{
+	return p->pre_handler == aggr_pre_handler;
+}
+
+/*
+ * Keep all fields in the kprobe consistent
+ */
+static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
+{
+	memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
+	memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
+}
+
+#ifdef CONFIG_OPTPROBES
+/* NOTE: change this value only with kprobe_mutex held */
+static bool kprobes_allow_optimization;
+
+/*
+ * Call all pre_handler on the list, but ignores its return value.
+ * This must be called from arch-dep optimized caller.
+ */
+void __kprobes opt_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct kprobe *kp;
+
+	list_for_each_entry_rcu(kp, &p->list, list) {
+		if (kp->pre_handler && likely(!kprobe_disabled(kp))) {
+			set_kprobe_instance(kp);
+			kp->pre_handler(kp, regs);
+		}
+		reset_kprobe_instance();
+	}
+}
+
+/* Return true(!0) if the kprobe is ready for optimization. */
+static inline int kprobe_optready(struct kprobe *p)
+{
+	struct optimized_kprobe *op;
+
+	if (kprobe_aggrprobe(p)) {
+		op = container_of(p, struct optimized_kprobe, kp);
+		return arch_prepared_optinsn(&op->optinsn);
+	}
+
+	return 0;
+}
+
+/*
+ * Return an optimized kprobe whose optimizing code replaces
+ * instructions including addr (exclude breakpoint).
+ */
+struct kprobe *__kprobes get_optimized_kprobe(unsigned long addr)
+{
+	int i;
+	struct kprobe *p = NULL;
+	struct optimized_kprobe *op;
+
+	/* Don't check i == 0, since that is a breakpoint case. */
+	for (i = 1; !p && i < MAX_OPTIMIZED_LENGTH; i++)
+		p = get_kprobe((void *)(addr - i));
+
+	if (p && kprobe_optready(p)) {
+		op = container_of(p, struct optimized_kprobe, kp);
+		if (arch_within_optimized_kprobe(op, addr))
+			return p;
+	}
+
+	return NULL;
+}
+
+/* Optimization staging list, protected by kprobe_mutex */
+static LIST_HEAD(optimizing_list);
+
+static void kprobe_optimizer(struct work_struct *work);
+static DECLARE_DELAYED_WORK(optimizing_work, kprobe_optimizer);
+#define OPTIMIZE_DELAY 5
+
+/* Kprobe jump optimizer */
+static __kprobes void kprobe_optimizer(struct work_struct *work)
+{
+	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();
+
+	/*
+	 * The optimization/unoptimization refers online_cpus via
+	 * stop_machine() and cpu-hotplug modifies online_cpus.
+	 * And same time, text_mutex will be held in cpu-hotplug and here.
+	 * This combination can cause a deadlock (cpu-hotplug try to lock
+	 * text_mutex but stop_machine can not be done because online_cpus
+	 * has been changed)
+	 * To avoid this deadlock, we need to call get_online_cpus()
+	 * for preventing cpu-hotplug outside of text_mutex locking.
+	 */
+	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);
+	}
+	mutex_unlock(&text_mutex);
+	put_online_cpus();
+end:
+	mutex_unlock(&kprobe_mutex);
+	mutex_unlock(&module_mutex);
+}
+
+/* Optimize kprobe if p is ready to be optimized */
+static __kprobes void optimize_kprobe(struct kprobe *p)
+{
+	struct optimized_kprobe *op;
+
+	/* Check if the kprobe is disabled or not ready for optimization. */
+	if (!kprobe_optready(p) || !kprobes_allow_optimization ||
+	    (kprobe_disabled(p) || kprobes_all_disarmed))
+		return;
+
+	/* Both of break_handler and post_handler are not supported. */
+	if (p->break_handler || p->post_handler)
+		return;
+
+	op = container_of(p, struct optimized_kprobe, kp);
+
+	/* Check there is no other kprobes at the optimized instructions */
+	if (arch_check_optimized_kprobe(op) < 0)
+		return;
+
+	/* 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);
+}
+
+/* Unoptimize a kprobe if p is optimized */
+static __kprobes void unoptimize_kprobe(struct kprobe *p)
+{
+	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 */
+			list_del_init(&op->list);
+		else
+			/* Replace jump with break */
+			arch_unoptimize_kprobe(op);
+		op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
+	}
+}
+
+/* Remove optimized instructions */
+static void __kprobes kill_optimized_kprobe(struct kprobe *p)
+{
+	struct optimized_kprobe *op;
+
+	op = container_of(p, struct optimized_kprobe, kp);
+	if (!list_empty(&op->list)) {
+		/* Dequeue from the optimization queue */
+		list_del_init(&op->list);
+		op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
+	}
+	/* Don't unoptimize, because the target code will be freed. */
+	arch_remove_optimized_kprobe(op);
+}
+
+/* Try to prepare optimized instructions */
+static __kprobes void prepare_optimized_kprobe(struct kprobe *p)
+{
+	struct optimized_kprobe *op;
+
+	op = container_of(p, struct optimized_kprobe, kp);
+	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)
+{
+	struct optimized_kprobe *op;
+
+	op = kzalloc(sizeof(struct optimized_kprobe), GFP_KERNEL);
+	if (!op)
+		return NULL;
+
+	INIT_LIST_HEAD(&op->list);
+	op->kp.addr = p->addr;
+	arch_prepare_optimized_kprobe(op);
+
+	return &op->kp;
+}
+
+static void __kprobes init_aggr_kprobe(struct kprobe *ap, struct kprobe *p);
+
+/*
+ * Prepare an optimized_kprobe and optimize it
+ * NOTE: p must be a normal registered kprobe
+ */
+static __kprobes void try_to_optimize_kprobe(struct kprobe *p)
+{
+	struct kprobe *ap;
+	struct optimized_kprobe *op;
+
+	ap = alloc_aggr_kprobe(p);
+	if (!ap)
+		return;
+
+	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);
+		return;
+	}
+
+	init_aggr_kprobe(ap, p);
+	optimize_kprobe(ap);
+}
+
+#ifdef CONFIG_SYSCTL
+static void __kprobes optimize_all_kprobes(void)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct kprobe *p;
+	unsigned int i;
+
+	/* If optimization is already allowed, just return */
+	if (kprobes_allow_optimization)
+		return;
+
+	kprobes_allow_optimization = true;
+	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))
+				optimize_kprobe(p);
+	}
+	mutex_unlock(&text_mutex);
+	printk(KERN_INFO "Kprobes globally optimized\n");
+}
+
+static void __kprobes unoptimize_all_kprobes(void)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct kprobe *p;
+	unsigned int i;
+
+	/* If optimization is already prohibited, just return */
+	if (!kprobes_allow_optimization)
+		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);
+		}
+	}
+
+	mutex_unlock(&text_mutex);
+	put_online_cpus();
+	/* Allow all currently running kprobes to complete */
+	synchronize_sched();
+}
+
+int sysctl_kprobes_optimization;
+int proc_kprobes_optimization_handler(struct ctl_table *table, int write,
+				      void __user *buffer, size_t *length,
+				      loff_t *ppos)
+{
+	int ret;
+
+	mutex_lock(&kprobe_mutex);
+	sysctl_kprobes_optimization = kprobes_allow_optimization ? 1 : 0;
+	ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
+
+	if (sysctl_kprobes_optimization)
+		optimize_all_kprobes();
+	else
+		unoptimize_all_kprobes();
+	mutex_unlock(&kprobe_mutex);
+
+	return ret;
+}
+#endif /* CONFIG_SYSCTL */
+
+static void __kprobes __arm_kprobe(struct kprobe *p)
+{
+	struct kprobe *old_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 */
+
+	arch_arm_kprobe(p);
+	optimize_kprobe(p);	/* Try to optimize (add kprobe to a list) */
+}
+
+static void __kprobes __disarm_kprobe(struct kprobe *p)
+{
+	struct kprobe *old_p;
+
+	unoptimize_kprobe(p);	/* Try to unoptimize */
+	arch_disarm_kprobe(p);
+
+	/* If another kprobe was blocked, optimize it. */
+	old_p = get_optimized_kprobe((unsigned long)p->addr);
+	if (unlikely(old_p))
+		optimize_kprobe(old_p);
+}
+
+#else /* !CONFIG_OPTPROBES */
+
+#define optimize_kprobe(p)			do {} while (0)
+#define unoptimize_kprobe(p)			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)
+
+static __kprobes void free_aggr_kprobe(struct kprobe *p)
+{
+	kfree(p);
+}
+
+static __kprobes struct kprobe *alloc_aggr_kprobe(struct kprobe *p)
+{
+	return kzalloc(sizeof(struct kprobe), GFP_KERNEL);
+}
+#endif /* CONFIG_OPTPROBES */
+
 /* Arm a kprobe with text_mutex */
 static void __kprobes arm_kprobe(struct kprobe *kp)
 {
+	/*
+	 * Here, since __arm_kprobe() doesn't use stop_machine(),
+	 * this doesn't cause deadlock on text_mutex. So, we don't
+	 * need get_online_cpus().
+	 */
 	mutex_lock(&text_mutex);
-	arch_arm_kprobe(kp);
+	__arm_kprobe(kp);
 	mutex_unlock(&text_mutex);
 }
 
 /* Disarm a kprobe with text_mutex */
 static void __kprobes disarm_kprobe(struct kprobe *kp)
 {
+	get_online_cpus();	/* For avoiding text_mutex deadlock */
 	mutex_lock(&text_mutex);
-	arch_disarm_kprobe(kp);
+	__disarm_kprobe(kp);
 	mutex_unlock(&text_mutex);
+	put_online_cpus();
 }
 
 /*
@@ -369,7 +802,7 @@
 void __kprobes kprobes_inc_nmissed_count(struct kprobe *p)
 {
 	struct kprobe *kp;
-	if (p->pre_handler != aggr_pre_handler) {
+	if (!kprobe_aggrprobe(p)) {
 		p->nmissed++;
 	} else {
 		list_for_each_entry_rcu(kp, &p->list, list)
@@ -493,21 +926,16 @@
 }
 
 /*
- * Keep all fields in the kprobe consistent
- */
-static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
-{
-	memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
-	memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
-}
-
-/*
 * Add the new probe to ap->list. Fail if this is the
 * second jprobe at the address - two jprobes can't coexist
 */
 static int __kprobes add_new_kprobe(struct kprobe *ap, struct kprobe *p)
 {
 	BUG_ON(kprobe_gone(ap) || kprobe_gone(p));
+
+	if (p->break_handler || p->post_handler)
+		unoptimize_kprobe(ap);	/* Fall back to normal kprobe */
+
 	if (p->break_handler) {
 		if (ap->break_handler)
 			return -EEXIST;
@@ -522,7 +950,7 @@
 		ap->flags &= ~KPROBE_FLAG_DISABLED;
 		if (!kprobes_all_disarmed)
 			/* Arm the breakpoint again. */
-			arm_kprobe(ap);
+			__arm_kprobe(ap);
 	}
 	return 0;
 }
@@ -531,12 +959,13 @@
  * Fill in the required fields of the "manager kprobe". Replace the
  * earlier kprobe in the hlist with the manager kprobe
  */
-static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
+static void __kprobes init_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
 {
+	/* Copy p's insn slot to ap */
 	copy_kprobe(p, ap);
 	flush_insn_slot(ap);
 	ap->addr = p->addr;
-	ap->flags = p->flags;
+	ap->flags = p->flags & ~KPROBE_FLAG_OPTIMIZED;
 	ap->pre_handler = aggr_pre_handler;
 	ap->fault_handler = aggr_fault_handler;
 	/* We don't care the kprobe which has gone. */
@@ -546,8 +975,9 @@
 		ap->break_handler = aggr_break_handler;
 
 	INIT_LIST_HEAD(&ap->list);
-	list_add_rcu(&p->list, &ap->list);
+	INIT_HLIST_NODE(&ap->hlist);
 
+	list_add_rcu(&p->list, &ap->list);
 	hlist_replace_rcu(&p->hlist, &ap->hlist);
 }
 
@@ -561,12 +991,12 @@
 	int ret = 0;
 	struct kprobe *ap = old_p;
 
-	if (old_p->pre_handler != aggr_pre_handler) {
-		/* If old_p is not an aggr_probe, create new aggr_kprobe. */
-		ap = kzalloc(sizeof(struct kprobe), GFP_KERNEL);
+	if (!kprobe_aggrprobe(old_p)) {
+		/* If old_p is not an aggr_kprobe, create new aggr_kprobe. */
+		ap = alloc_aggr_kprobe(old_p);
 		if (!ap)
 			return -ENOMEM;
-		add_aggr_kprobe(ap, old_p);
+		init_aggr_kprobe(ap, old_p);
 	}
 
 	if (kprobe_gone(ap)) {
@@ -585,6 +1015,9 @@
 			 */
 			return ret;
 
+		/* Prepare optimized instructions if possible. */
+		prepare_optimized_kprobe(ap);
+
 		/*
 		 * Clear gone flag to prevent allocating new slot again, and
 		 * set disabled flag because it is not armed yet.
@@ -593,6 +1026,7 @@
 			    | KPROBE_FLAG_DISABLED;
 	}
 
+	/* Copy ap's insn slot to p */
 	copy_kprobe(ap, p);
 	return add_new_kprobe(ap, p);
 }
@@ -743,27 +1177,34 @@
 	p->nmissed = 0;
 	INIT_LIST_HEAD(&p->list);
 	mutex_lock(&kprobe_mutex);
+
+	get_online_cpus();	/* For avoiding text_mutex deadlock. */
+	mutex_lock(&text_mutex);
+
 	old_p = get_kprobe(p->addr);
 	if (old_p) {
+		/* Since this may unoptimize old_p, locking text_mutex. */
 		ret = register_aggr_kprobe(old_p, p);
 		goto out;
 	}
 
-	mutex_lock(&text_mutex);
 	ret = arch_prepare_kprobe(p);
 	if (ret)
-		goto out_unlock_text;
+		goto out;
 
 	INIT_HLIST_NODE(&p->hlist);
 	hlist_add_head_rcu(&p->hlist,
 		       &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
 
 	if (!kprobes_all_disarmed && !kprobe_disabled(p))
-		arch_arm_kprobe(p);
+		__arm_kprobe(p);
 
-out_unlock_text:
-	mutex_unlock(&text_mutex);
+	/* Try to optimize kprobe */
+	try_to_optimize_kprobe(p);
+
 out:
+	mutex_unlock(&text_mutex);
+	put_online_cpus();
 	mutex_unlock(&kprobe_mutex);
 
 	if (probed_mod)
@@ -785,7 +1226,7 @@
 		return -EINVAL;
 
 	if (old_p == p ||
-	    (old_p->pre_handler == aggr_pre_handler &&
+	    (kprobe_aggrprobe(old_p) &&
 	     list_is_singular(&old_p->list))) {
 		/*
 		 * Only probe on the hash list. Disarm only if kprobes are
@@ -793,7 +1234,7 @@
 		 * already have been removed. We save on flushing icache.
 		 */
 		if (!kprobes_all_disarmed && !kprobe_disabled(old_p))
-			disarm_kprobe(p);
+			disarm_kprobe(old_p);
 		hlist_del_rcu(&old_p->hlist);
 	} else {
 		if (p->break_handler && !kprobe_gone(p))
@@ -809,8 +1250,13 @@
 		list_del_rcu(&p->list);
 		if (!kprobe_disabled(old_p)) {
 			try_to_disable_aggr_kprobe(old_p);
-			if (!kprobes_all_disarmed && kprobe_disabled(old_p))
-				disarm_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);
+			}
 		}
 	}
 	return 0;
@@ -827,7 +1273,7 @@
 		old_p = list_entry(p->list.next, struct kprobe, list);
 		list_del(&p->list);
 		arch_remove_kprobe(old_p);
-		kfree(old_p);
+		free_aggr_kprobe(old_p);
 	}
 }
 
@@ -1123,7 +1569,7 @@
 	struct kprobe *kp;
 
 	p->flags |= KPROBE_FLAG_GONE;
-	if (p->pre_handler == aggr_pre_handler) {
+	if (kprobe_aggrprobe(p)) {
 		/*
 		 * If this is an aggr_kprobe, we have to list all the
 		 * chained probes and mark them GONE.
@@ -1132,6 +1578,7 @@
 			kp->flags |= KPROBE_FLAG_GONE;
 		p->post_handler = NULL;
 		p->break_handler = NULL;
+		kill_optimized_kprobe(p);
 	}
 	/*
 	 * Here, we can remove insn_slot safely, because no thread calls
@@ -1241,6 +1688,15 @@
 		}
 	}
 
+#if defined(CONFIG_OPTPROBES)
+#if defined(__ARCH_WANT_KPROBES_INSN_SLOT)
+	/* Init kprobe_optinsn_slots */
+	kprobe_optinsn_slots.insn_size = MAX_OPTINSN_SIZE;
+#endif
+	/* By default, kprobes can be optimized */
+	kprobes_allow_optimization = true;
+#endif
+
 	/* By default, kprobes are armed */
 	kprobes_all_disarmed = false;
 
@@ -1259,7 +1715,7 @@
 
 #ifdef CONFIG_DEBUG_FS
 static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p,
-		const char *sym, int offset,char *modname)
+		const char *sym, int offset, char *modname, struct kprobe *pp)
 {
 	char *kprobe_type;
 
@@ -1269,19 +1725,21 @@
 		kprobe_type = "j";
 	else
 		kprobe_type = "k";
+
 	if (sym)
-		seq_printf(pi, "%p  %s  %s+0x%x  %s %s%s\n",
+		seq_printf(pi, "%p  %s  %s+0x%x  %s ",
 			p->addr, kprobe_type, sym, offset,
-			(modname ? modname : " "),
-			(kprobe_gone(p) ? "[GONE]" : ""),
-			((kprobe_disabled(p) && !kprobe_gone(p)) ?
-			 "[DISABLED]" : ""));
+			(modname ? modname : " "));
 	else
-		seq_printf(pi, "%p  %s  %p %s%s\n",
-			p->addr, kprobe_type, p->addr,
-			(kprobe_gone(p) ? "[GONE]" : ""),
-			((kprobe_disabled(p) && !kprobe_gone(p)) ?
-			 "[DISABLED]" : ""));
+		seq_printf(pi, "%p  %s  %p ",
+			p->addr, kprobe_type, p->addr);
+
+	if (!pp)
+		pp = p;
+	seq_printf(pi, "%s%s%s\n",
+		(kprobe_gone(p) ? "[GONE]" : ""),
+		((kprobe_disabled(p) && !kprobe_gone(p)) ?  "[DISABLED]" : ""),
+		(kprobe_optimized(pp) ? "[OPTIMIZED]" : ""));
 }
 
 static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos)
@@ -1317,11 +1775,11 @@
 	hlist_for_each_entry_rcu(p, node, head, hlist) {
 		sym = kallsyms_lookup((unsigned long)p->addr, NULL,
 					&offset, &modname, namebuf);
-		if (p->pre_handler == aggr_pre_handler) {
+		if (kprobe_aggrprobe(p)) {
 			list_for_each_entry_rcu(kp, &p->list, list)
-				report_probe(pi, kp, sym, offset, modname);
+				report_probe(pi, kp, sym, offset, modname, p);
 		} else
-			report_probe(pi, p, sym, offset, modname);
+			report_probe(pi, p, sym, offset, modname, NULL);
 	}
 	preempt_enable();
 	return 0;
@@ -1399,12 +1857,13 @@
 		goto out;
 	}
 
-	if (!kprobes_all_disarmed && kprobe_disabled(p))
-		arm_kprobe(p);
-
-	p->flags &= ~KPROBE_FLAG_DISABLED;
 	if (p != kp)
 		kp->flags &= ~KPROBE_FLAG_DISABLED;
+
+	if (!kprobes_all_disarmed && kprobe_disabled(p)) {
+		p->flags &= ~KPROBE_FLAG_DISABLED;
+		arm_kprobe(p);
+	}
 out:
 	mutex_unlock(&kprobe_mutex);
 	return ret;
@@ -1424,12 +1883,13 @@
 	if (!kprobes_all_disarmed)
 		goto already_enabled;
 
+	/* Arming kprobes doesn't optimize kprobe itself */
 	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))
-				arch_arm_kprobe(p);
+				__arm_kprobe(p);
 	}
 	mutex_unlock(&text_mutex);
 
@@ -1456,16 +1916,23 @@
 
 	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))
-				arch_disarm_kprobe(p);
+				__disarm_kprobe(p);
 		}
 	}
 
 	mutex_unlock(&text_mutex);
+	put_online_cpus();
 	mutex_unlock(&kprobe_mutex);
 	/* Allow all currently running kprobes to complete */
 	synchronize_sched();
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 6b1ccc3..21fe3c4 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -33,7 +33,7 @@
 }
 KERNEL_ATTR_RO(uevent_seqnum);
 
-/* uevent helper program, used during early boo */
+/* uevent helper program, used during early boot */
 static ssize_t uevent_helper_show(struct kobject *kobj,
 				  struct kobj_attribute *attr, char *buf)
 {
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 0c30d04..681bc2e 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -3822,6 +3822,7 @@
 	printk("%s:%d invoked rcu_dereference_check() without protection!\n",
 			file, line);
 	printk("\nother info that might help us debug this:\n\n");
+	printk("\nrcu_scheduler_active = %d, debug_locks = %d\n", rcu_scheduler_active, debug_locks);
 	lockdep_print_held_locks(curr);
 	printk("\nstack backtrace:\n");
 	dump_stack();
diff --git a/kernel/module.c b/kernel/module.c
index f82386b..c968d36 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -474,9 +474,10 @@
 
 	INIT_LIST_HEAD(&mod->modules_which_use_me);
 	for_each_possible_cpu(cpu)
-		local_set(__module_ref_addr(mod, cpu), 0);
+		per_cpu_ptr(mod->refptr, cpu)->count = 0;
+
 	/* Hold reference count during initialization. */
-	local_set(__module_ref_addr(mod, raw_smp_processor_id()), 1);
+	__this_cpu_write(mod->refptr->count, 1);
 	/* Backwards compatibility macros put refcount during init. */
 	mod->waiter = current;
 }
@@ -619,7 +620,7 @@
 	int cpu;
 
 	for_each_possible_cpu(cpu)
-		total += local_read(__module_ref_addr(mod, cpu));
+		total += per_cpu_ptr(mod->refptr, cpu)->count;
 	return total;
 }
 EXPORT_SYMBOL(module_refcount);
@@ -796,14 +797,15 @@
 void module_put(struct module *module)
 {
 	if (module) {
-		unsigned int cpu = get_cpu();
-		local_dec(__module_ref_addr(module, cpu));
+		preempt_disable();
+		__this_cpu_dec(module->refptr->count);
+
 		trace_module_put(module, _RET_IP_,
-				 local_read(__module_ref_addr(module, cpu)));
+				 __this_cpu_read(module->refptr->count));
 		/* Maybe they're waiting for us to drop reference? */
 		if (unlikely(!module_is_live(module)))
 			wake_up_process(module->waiter);
-		put_cpu();
+		preempt_enable();
 	}
 }
 EXPORT_SYMBOL(module_put);
@@ -1083,6 +1085,7 @@
 		if (sattr->name == NULL)
 			goto out;
 		sect_attrs->nsections++;
+		sysfs_attr_init(&sattr->mattr.attr);
 		sattr->mattr.show = module_sect_show;
 		sattr->mattr.store = NULL;
 		sattr->mattr.attr.name = sattr->name;
@@ -1178,6 +1181,7 @@
 		if (sect_empty(&sechdrs[i]))
 			continue;
 		if (sechdrs[i].sh_type == SHT_NOTE) {
+			sysfs_bin_attr_init(nattr);
 			nattr->attr.name = mod->sect_attrs->attrs[loaded].name;
 			nattr->attr.mode = S_IRUGO;
 			nattr->size = sechdrs[i].sh_size;
@@ -1250,6 +1254,7 @@
 		if (!attr->test ||
 		    (attr->test && attr->test(mod))) {
 			memcpy(temp_attr, attr, sizeof(*temp_attr));
+			sysfs_attr_init(&temp_attr->attr);
 			error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);
 			++temp_attr;
 		}
@@ -1397,9 +1402,9 @@
 	kfree(mod->args);
 	if (mod->percpu)
 		percpu_modfree(mod->percpu);
-#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
+#if defined(CONFIG_MODULE_UNLOAD)
 	if (mod->refptr)
-		percpu_modfree(mod->refptr);
+		free_percpu(mod->refptr);
 #endif
 	/* Free lock-classes: */
 	lockdep_free_key_range(mod->module_core, mod->core_size);
@@ -2162,9 +2167,8 @@
 	mod = (void *)sechdrs[modindex].sh_addr;
 	kmemleak_load_module(mod, hdr, sechdrs, secstrings);
 
-#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
-	mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t),
-				      mod->name);
+#if defined(CONFIG_MODULE_UNLOAD)
+	mod->refptr = alloc_percpu(struct module_ref);
 	if (!mod->refptr) {
 		err = -ENOMEM;
 		goto free_init;
@@ -2396,8 +2400,8 @@
 	kobject_put(&mod->mkobj.kobj);
  free_unload:
 	module_unload_free(mod);
-#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
-	percpu_modfree(mod->refptr);
+#if defined(CONFIG_MODULE_UNLOAD)
+	free_percpu(mod->refptr);
  free_init:
 #endif
 	module_free(mod, mod->module_init);
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 09b4ff9..2ab6723 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -24,7 +24,18 @@
 
 static struct kmem_cache *nsproxy_cachep;
 
-struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
+struct nsproxy init_nsproxy = {
+	.count	= ATOMIC_INIT(1),
+	.uts_ns	= &init_uts_ns,
+#if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
+	.ipc_ns	= &init_ipc_ns,
+#endif
+	.mnt_ns	= NULL,
+	.pid_ns	= &init_pid_ns,
+#ifdef CONFIG_NET
+	.net_ns	= &init_net,
+#endif
+};
 
 static inline struct nsproxy *create_nsproxy(void)
 {
diff --git a/kernel/padata.c b/kernel/padata.c
index 6f9bcb8..93caf65 100644
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -642,6 +642,9 @@
 	if (!pd)
 		goto err_free_inst;
 
+	if (!alloc_cpumask_var(&pinst->cpumask, GFP_KERNEL))
+		goto err_free_pd;
+
 	rcu_assign_pointer(pinst->pd, pd);
 
 	pinst->wq = wq;
@@ -654,12 +657,14 @@
 	pinst->cpu_notifier.priority = 0;
 	err = register_hotcpu_notifier(&pinst->cpu_notifier);
 	if (err)
-		goto err_free_pd;
+		goto err_free_cpumask;
 
 	mutex_init(&pinst->lock);
 
 	return pinst;
 
+err_free_cpumask:
+	free_cpumask_var(pinst->cpumask);
 err_free_pd:
 	padata_free_pd(pd);
 err_free_inst:
@@ -685,6 +690,7 @@
 
 	unregister_hotcpu_notifier(&pinst->cpu_notifier);
 	padata_free_pd(pinst->pd);
+	free_cpumask_var(pinst->cpumask);
 	kfree(pinst);
 }
 EXPORT_SYMBOL(padata_free);
diff --git a/kernel/panic.c b/kernel/panic.c
index c787333..13d966b 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -36,15 +36,36 @@
 
 EXPORT_SYMBOL(panic_notifier_list);
 
-static long no_blink(long time)
-{
-	return 0;
-}
-
 /* Returns how long it waited in ms */
 long (*panic_blink)(long time);
 EXPORT_SYMBOL(panic_blink);
 
+static void panic_blink_one_second(void)
+{
+	static long i = 0, end;
+
+	if (panic_blink) {
+		end = i + MSEC_PER_SEC;
+
+		while (i < end) {
+			i += panic_blink(i);
+			mdelay(1);
+			i++;
+		}
+	} else {
+		/*
+		 * When running under a hypervisor a small mdelay may get
+		 * rounded up to the hypervisor timeslice. For example, with
+		 * a 1ms in 10ms hypervisor timeslice we might inflate a
+		 * mdelay(1) loop by 10x.
+		 *
+		 * If we have nothing to blink, spin on 1 second calls to
+		 * mdelay to avoid this.
+		 */
+		mdelay(MSEC_PER_SEC);
+	}
+}
+
 /**
  *	panic - halt the system
  *	@fmt: The text string to print
@@ -95,9 +116,6 @@
 
 	bust_spinlocks(0);
 
-	if (!panic_blink)
-		panic_blink = no_blink;
-
 	if (panic_timeout > 0) {
 		/*
 		 * Delay timeout seconds before rebooting the machine.
@@ -105,11 +123,9 @@
 		 */
 		printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout);
 
-		for (i = 0; i < panic_timeout*1000; ) {
+		for (i = 0; i < panic_timeout; i++) {
 			touch_nmi_watchdog();
-			i += panic_blink(i);
-			mdelay(1);
-			i++;
+			panic_blink_one_second();
 		}
 		/*
 		 * This will not be a clean reboot, with everything
@@ -135,11 +151,9 @@
 	}
 #endif
 	local_irq_enable();
-	for (i = 0; ; ) {
+	while (1) {
 		touch_softlockup_watchdog();
-		i += panic_blink(i);
-		mdelay(1);
-		i++;
+		panic_blink_one_second();
 	}
 }
 
diff --git a/kernel/params.c b/kernel/params.c
index cf1b691..0b30ecd 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -24,7 +24,6 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/ctype.h>
-#include <linux/string.h>
 
 #if 0
 #define DEBUGP printk
@@ -402,8 +401,8 @@
 }
 
 /* sysfs output in /sys/modules/XYZ/parameters/ */
-#define to_module_attr(n) container_of(n, struct module_attribute, attr);
-#define to_module_kobject(n) container_of(n, struct module_kobject, kobj);
+#define to_module_attr(n) container_of(n, struct module_attribute, attr)
+#define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
 
 extern struct kernel_param __start___param[], __stop___param[];
 
@@ -421,7 +420,7 @@
 };
 
 #ifdef CONFIG_SYSFS
-#define to_param_attr(n) container_of(n, struct param_attribute, mattr);
+#define to_param_attr(n) container_of(n, struct param_attribute, mattr)
 
 static ssize_t param_attr_show(struct module_attribute *mattr,
 			       struct module *mod, char *buf)
@@ -517,6 +516,7 @@
 	new->grp.attrs = attrs;
 
 	/* Tack new one on the end. */
+	sysfs_attr_init(&new->attrs[num].mattr.attr);
 	new->attrs[num].param = kp;
 	new->attrs[num].mattr.show = param_attr_show;
 	new->attrs[num].mattr.store = param_attr_store;
@@ -723,7 +723,7 @@
 	return ret;
 }
 
-static struct sysfs_ops module_sysfs_ops = {
+static const struct sysfs_ops module_sysfs_ops = {
 	.show = module_attr_show,
 	.store = module_attr_store,
 };
@@ -737,7 +737,7 @@
 	return 0;
 }
 
-static struct kset_uevent_ops module_uevent_ops = {
+static const struct kset_uevent_ops module_uevent_ops = {
 	.filter = uevent_filter,
 };
 
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index a661e79..4393b9e 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -56,21 +56,6 @@
  */
 int sysctl_perf_event_paranoid __read_mostly = 1;
 
-static inline bool perf_paranoid_tracepoint_raw(void)
-{
-	return sysctl_perf_event_paranoid > -1;
-}
-
-static inline bool perf_paranoid_cpu(void)
-{
-	return sysctl_perf_event_paranoid > 0;
-}
-
-static inline bool perf_paranoid_kernel(void)
-{
-	return sysctl_perf_event_paranoid > 1;
-}
-
 int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */
 
 /*
@@ -2610,7 +2595,7 @@
 	if (user_locked > user_lock_limit)
 		extra = user_locked - user_lock_limit;
 
-	lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+	lock_limit = rlimit(RLIMIT_MEMLOCK);
 	lock_limit >>= PAGE_SHIFT;
 	locked = vma->vm_mm->locked_vm + extra;
 
@@ -4123,8 +4108,7 @@
 	if (rctx < 0)
 		return;
 
-	data.addr = addr;
-	data.raw  = NULL;
+	perf_sample_data_init(&data, addr);
 
 	do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs);
 
@@ -4169,11 +4153,10 @@
 	struct perf_event *event;
 	u64 period;
 
-	event	= container_of(hrtimer, struct perf_event, hw.hrtimer);
+	event = container_of(hrtimer, struct perf_event, hw.hrtimer);
 	event->pmu->read(event);
 
-	data.addr = 0;
-	data.raw = NULL;
+	perf_sample_data_init(&data, 0);
 	data.period = event->hw.last_period;
 	regs = get_irq_regs();
 	/*
@@ -4337,17 +4320,15 @@
 void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
 			  int entry_size)
 {
+	struct pt_regs *regs = get_irq_regs();
+	struct perf_sample_data data;
 	struct perf_raw_record raw = {
 		.size = entry_size,
 		.data = record,
 	};
 
-	struct perf_sample_data data = {
-		.addr = addr,
-		.raw = &raw,
-	};
-
-	struct pt_regs *regs = get_irq_regs();
+	perf_sample_data_init(&data, addr);
+	data.raw = &raw;
 
 	if (!regs)
 		regs = task_pt_regs(current);
@@ -4463,8 +4444,7 @@
 	struct perf_sample_data sample;
 	struct pt_regs *regs = data;
 
-	sample.raw = NULL;
-	sample.addr = bp->attr.bp_addr;
+	perf_sample_data_init(&sample, bp->attr.bp_addr);
 
 	if (!perf_exclude_event(bp, regs))
 		perf_swevent_add(bp, 1, 1, &sample, regs);
@@ -5481,13 +5461,16 @@
 	register_cpu_notifier(&perf_cpu_nb);
 }
 
-static ssize_t perf_show_reserve_percpu(struct sysdev_class *class, char *buf)
+static ssize_t perf_show_reserve_percpu(struct sysdev_class *class,
+					struct sysdev_class_attribute *attr,
+					char *buf)
 {
 	return sprintf(buf, "%d\n", perf_reserved_percpu);
 }
 
 static ssize_t
 perf_set_reserve_percpu(struct sysdev_class *class,
+			struct sysdev_class_attribute *attr,
 			const char *buf,
 			size_t count)
 {
@@ -5516,13 +5499,17 @@
 	return count;
 }
 
-static ssize_t perf_show_overcommit(struct sysdev_class *class, char *buf)
+static ssize_t perf_show_overcommit(struct sysdev_class *class,
+				    struct sysdev_class_attribute *attr,
+				    char *buf)
 {
 	return sprintf(buf, "%d\n", perf_overcommit);
 }
 
 static ssize_t
-perf_set_overcommit(struct sysdev_class *class, const char *buf, size_t count)
+perf_set_overcommit(struct sysdev_class *class,
+		    struct sysdev_class_attribute *attr,
+		    const char *buf, size_t count)
 {
 	unsigned long val;
 	int err;
diff --git a/kernel/pid.c b/kernel/pid.c
index b08e697..aebb30d 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -367,7 +367,9 @@
 	struct task_struct *result = NULL;
 	if (pid) {
 		struct hlist_node *first;
-		first = rcu_dereference_check(pid->tasks[type].first, rcu_read_lock_held() || lockdep_is_held(&tasklist_lock));
+		first = rcu_dereference_check(pid->tasks[type].first,
+					      rcu_read_lock_held() ||
+					      lockdep_tasklist_lock_is_held());
 		if (first)
 			result = hlist_entry(first, struct task_struct, pids[(type)].node);
 	}
@@ -376,7 +378,7 @@
 EXPORT_SYMBOL(pid_task);
 
 /*
- * Must be called under rcu_read_lock() or with tasklist_lock read-held.
+ * Must be called under rcu_read_lock().
  */
 struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns)
 {
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 86b3796..79aac93 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -161,13 +161,12 @@
 		rcu_read_lock();
 
 		/*
-		 * Use force_sig() since it clears SIGNAL_UNKILLABLE ensuring
-		 * any nested-container's init processes don't ignore the
-		 * signal
+		 * Any nested-container's init processes won't ignore the
+		 * SEND_SIG_NOINFO signal, see send_signal()->si_fromuser().
 		 */
 		task = pid_task(find_vpid(nr), PIDTYPE_PID);
 		if (task)
-			force_sig(SIGKILL, task);
+			send_sig_info(SIGKILL, SEND_SIG_NOINFO, task);
 
 		rcu_read_unlock();
 
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 438ff45..1a22dfd 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -982,6 +982,7 @@
 	int maxfire;
 	struct list_head *timers = tsk->cpu_timers;
 	struct signal_struct *const sig = tsk->signal;
+	unsigned long soft;
 
 	maxfire = 20;
 	tsk->cputime_expires.prof_exp = cputime_zero;
@@ -1030,9 +1031,10 @@
 	/*
 	 * Check for the special case thread timers.
 	 */
-	if (sig->rlim[RLIMIT_RTTIME].rlim_cur != RLIM_INFINITY) {
-		unsigned long hard = sig->rlim[RLIMIT_RTTIME].rlim_max;
-		unsigned long *soft = &sig->rlim[RLIMIT_RTTIME].rlim_cur;
+	soft = ACCESS_ONCE(sig->rlim[RLIMIT_RTTIME].rlim_cur);
+	if (soft != RLIM_INFINITY) {
+		unsigned long hard =
+			ACCESS_ONCE(sig->rlim[RLIMIT_RTTIME].rlim_max);
 
 		if (hard != RLIM_INFINITY &&
 		    tsk->rt.timeout > DIV_ROUND_UP(hard, USEC_PER_SEC/HZ)) {
@@ -1043,14 +1045,13 @@
 			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
 			return;
 		}
-		if (tsk->rt.timeout > DIV_ROUND_UP(*soft, USEC_PER_SEC/HZ)) {
+		if (tsk->rt.timeout > DIV_ROUND_UP(soft, USEC_PER_SEC/HZ)) {
 			/*
 			 * At the soft limit, send a SIGXCPU every second.
 			 */
-			if (sig->rlim[RLIMIT_RTTIME].rlim_cur
-			    < sig->rlim[RLIMIT_RTTIME].rlim_max) {
-				sig->rlim[RLIMIT_RTTIME].rlim_cur +=
-								USEC_PER_SEC;
+			if (soft < hard) {
+				soft += USEC_PER_SEC;
+				sig->rlim[RLIMIT_RTTIME].rlim_cur = soft;
 			}
 			printk(KERN_INFO
 				"RT Watchdog Timeout: %s[%d]\n",
@@ -1121,6 +1122,7 @@
 	unsigned long long sum_sched_runtime, sched_expires;
 	struct list_head *timers = sig->cpu_timers;
 	struct task_cputime cputime;
+	unsigned long soft;
 
 	/*
 	 * Don't sample the current process CPU clocks if there are no timers.
@@ -1193,11 +1195,13 @@
 			 SIGPROF);
 	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_expires, utime,
 			 SIGVTALRM);
-
-	if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
+	soft = ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
+	if (soft != RLIM_INFINITY) {
 		unsigned long psecs = cputime_to_secs(ptime);
+		unsigned long hard =
+			ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_max);
 		cputime_t x;
-		if (psecs >= sig->rlim[RLIMIT_CPU].rlim_max) {
+		if (psecs >= hard) {
 			/*
 			 * At the hard limit, we just die.
 			 * No need to calculate anything else now.
@@ -1205,17 +1209,17 @@
 			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
 			return;
 		}
-		if (psecs >= sig->rlim[RLIMIT_CPU].rlim_cur) {
+		if (psecs >= soft) {
 			/*
 			 * At the soft limit, send a SIGXCPU every second.
 			 */
 			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
-			if (sig->rlim[RLIMIT_CPU].rlim_cur
-			    < sig->rlim[RLIMIT_CPU].rlim_max) {
-				sig->rlim[RLIMIT_CPU].rlim_cur++;
+			if (soft < hard) {
+				soft++;
+				sig->rlim[RLIMIT_CPU].rlim_cur = soft;
 			}
 		}
-		x = secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
+		x = secs_to_cputime(soft);
 		if (cputime_eq(prof_expires, cputime_zero) ||
 		    cputime_lt(x, prof_expires)) {
 			prof_expires = x;
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index bbfe472..da5288e 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -323,6 +323,7 @@
 int hibernation_snapshot(int platform_mode)
 {
 	int error;
+	gfp_t saved_mask;
 
 	error = platform_begin(platform_mode);
 	if (error)
@@ -334,6 +335,7 @@
 		goto Close;
 
 	suspend_console();
+	saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
 	error = dpm_suspend_start(PMSG_FREEZE);
 	if (error)
 		goto Recover_platform;
@@ -351,6 +353,7 @@
 
 	dpm_resume_end(in_suspend ?
 		(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
+	set_gfp_allowed_mask(saved_mask);
 	resume_console();
  Close:
 	platform_end(platform_mode);
@@ -445,14 +448,17 @@
 int hibernation_restore(int platform_mode)
 {
 	int error;
+	gfp_t saved_mask;
 
 	pm_prepare_console();
 	suspend_console();
+	saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
 	error = dpm_suspend_start(PMSG_QUIESCE);
 	if (!error) {
 		error = resume_target_kernel(platform_mode);
 		dpm_resume_end(PMSG_RECOVER);
 	}
+	set_gfp_allowed_mask(saved_mask);
 	resume_console();
 	pm_restore_console();
 	return error;
@@ -466,6 +472,7 @@
 int hibernation_platform_enter(void)
 {
 	int error;
+	gfp_t saved_mask;
 
 	if (!hibernation_ops)
 		return -ENOSYS;
@@ -481,6 +488,7 @@
 
 	entering_platform_hibernation = true;
 	suspend_console();
+	saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
 	error = dpm_suspend_start(PMSG_HIBERNATE);
 	if (error) {
 		if (hibernation_ops->recover)
@@ -518,6 +526,7 @@
  Resume_devices:
 	entering_platform_hibernation = false;
 	dpm_resume_end(PMSG_RESTORE);
+	set_gfp_allowed_mask(saved_mask);
 	resume_console();
 
  Close:
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 6f10dfc..44cce10 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -189,6 +189,7 @@
 int suspend_devices_and_enter(suspend_state_t state)
 {
 	int error;
+	gfp_t saved_mask;
 
 	if (!suspend_ops)
 		return -ENOSYS;
@@ -199,6 +200,7 @@
 			goto Close;
 	}
 	suspend_console();
+	saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
 	suspend_test_start();
 	error = dpm_suspend_start(PMSG_SUSPEND);
 	if (error) {
@@ -215,6 +217,7 @@
 	suspend_test_start();
 	dpm_resume_end(PMSG_RESUME);
 	suspend_test_finish("resume devices");
+	set_gfp_allowed_mask(saved_mask);
 	resume_console();
  Close:
 	if (suspend_ops->end)
diff --git a/kernel/printk.c b/kernel/printk.c
index 1751c456..75077ad 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -35,6 +35,7 @@
 #include <linux/kexec.h>
 #include <linux/ratelimit.h>
 #include <linux/kmsg_dump.h>
+#include <linux/syslog.h>
 
 #include <asm/uaccess.h>
 
@@ -69,8 +70,6 @@
 	DEFAULT_CONSOLE_LOGLEVEL,	/* default_console_loglevel */
 };
 
-static int saved_console_loglevel = -1;
-
 /*
  * Low level drivers may need that to know if they can schedule in
  * their unblank() callback or not. So let's export it.
@@ -145,6 +144,7 @@
 static char *log_buf = __log_buf;
 static int log_buf_len = __LOG_BUF_LEN;
 static unsigned logged_chars; /* Number of chars produced since last read+clear operation */
+static int saved_console_loglevel = -1;
 
 #ifdef CONFIG_KEXEC
 /*
@@ -258,38 +258,23 @@
 }
 #endif
 
-/*
- * Commands to do_syslog:
- *
- * 	0 -- Close the log.  Currently a NOP.
- * 	1 -- Open the log. Currently a NOP.
- * 	2 -- Read from the log.
- * 	3 -- Read all messages remaining in the ring buffer.
- * 	4 -- Read and clear all messages remaining in the ring buffer
- * 	5 -- Clear ring buffer.
- * 	6 -- Disable printk's to console
- * 	7 -- Enable printk's to console
- *	8 -- Set level of messages printed to console
- *	9 -- Return number of unread characters in the log buffer
- *     10 -- Return size of the log buffer
- */
-int do_syslog(int type, char __user *buf, int len)
+int do_syslog(int type, char __user *buf, int len, bool from_file)
 {
 	unsigned i, j, limit, count;
 	int do_clear = 0;
 	char c;
 	int error = 0;
 
-	error = security_syslog(type);
+	error = security_syslog(type, from_file);
 	if (error)
 		return error;
 
 	switch (type) {
-	case 0:		/* Close log */
+	case SYSLOG_ACTION_CLOSE:	/* Close log */
 		break;
-	case 1:		/* Open log */
+	case SYSLOG_ACTION_OPEN:	/* Open log */
 		break;
-	case 2:		/* Read from log */
+	case SYSLOG_ACTION_READ:	/* Read from log */
 		error = -EINVAL;
 		if (!buf || len < 0)
 			goto out;
@@ -320,10 +305,12 @@
 		if (!error)
 			error = i;
 		break;
-	case 4:		/* Read/clear last kernel messages */
+	/* Read/clear last kernel messages */
+	case SYSLOG_ACTION_READ_CLEAR:
 		do_clear = 1;
 		/* FALL THRU */
-	case 3:		/* Read last kernel messages */
+	/* Read last kernel messages */
+	case SYSLOG_ACTION_READ_ALL:
 		error = -EINVAL;
 		if (!buf || len < 0)
 			goto out;
@@ -376,21 +363,25 @@
 			}
 		}
 		break;
-	case 5:		/* Clear ring buffer */
+	/* Clear ring buffer */
+	case SYSLOG_ACTION_CLEAR:
 		logged_chars = 0;
 		break;
-	case 6:		/* Disable logging to console */
+	/* Disable logging to console */
+	case SYSLOG_ACTION_CONSOLE_OFF:
 		if (saved_console_loglevel == -1)
 			saved_console_loglevel = console_loglevel;
 		console_loglevel = minimum_console_loglevel;
 		break;
-	case 7:		/* Enable logging to console */
+	/* Enable logging to console */
+	case SYSLOG_ACTION_CONSOLE_ON:
 		if (saved_console_loglevel != -1) {
 			console_loglevel = saved_console_loglevel;
 			saved_console_loglevel = -1;
 		}
 		break;
-	case 8:		/* Set level of messages printed to console */
+	/* Set level of messages printed to console */
+	case SYSLOG_ACTION_CONSOLE_LEVEL:
 		error = -EINVAL;
 		if (len < 1 || len > 8)
 			goto out;
@@ -401,10 +392,12 @@
 		saved_console_loglevel = -1;
 		error = 0;
 		break;
-	case 9:		/* Number of chars in the log buffer */
+	/* Number of chars in the log buffer */
+	case SYSLOG_ACTION_SIZE_UNREAD:
 		error = log_end - log_start;
 		break;
-	case 10:	/* Size of the log buffer */
+	/* Size of the log buffer */
+	case SYSLOG_ACTION_SIZE_BUFFER:
 		error = log_buf_len;
 		break;
 	default:
@@ -417,7 +410,7 @@
 
 SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
 {
-	return do_syslog(type, buf, len);
+	return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
 }
 
 /*
diff --git a/kernel/range.c b/kernel/range.c
new file mode 100644
index 0000000..74e2e61
--- /dev/null
+++ b/kernel/range.c
@@ -0,0 +1,163 @@
+/*
+ * Range add and subtract
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sort.h>
+
+#include <linux/range.h>
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+int add_range(struct range *range, int az, int nr_range, u64 start, u64 end)
+{
+	if (start >= end)
+		return nr_range;
+
+	/* Out of slots: */
+	if (nr_range >= az)
+		return nr_range;
+
+	range[nr_range].start = start;
+	range[nr_range].end = end;
+
+	nr_range++;
+
+	return nr_range;
+}
+
+int add_range_with_merge(struct range *range, int az, int nr_range,
+		     u64 start, u64 end)
+{
+	int i;
+
+	if (start >= end)
+		return nr_range;
+
+	/* Try to merge it with old one: */
+	for (i = 0; i < nr_range; i++) {
+		u64 final_start, final_end;
+		u64 common_start, common_end;
+
+		if (!range[i].end)
+			continue;
+
+		common_start = max(range[i].start, start);
+		common_end = min(range[i].end, end);
+		if (common_start > common_end)
+			continue;
+
+		final_start = min(range[i].start, start);
+		final_end = max(range[i].end, end);
+
+		range[i].start = final_start;
+		range[i].end =  final_end;
+		return nr_range;
+	}
+
+	/* Need to add it: */
+	return add_range(range, az, nr_range, start, end);
+}
+
+void subtract_range(struct range *range, int az, u64 start, u64 end)
+{
+	int i, j;
+
+	if (start >= end)
+		return;
+
+	for (j = 0; j < az; j++) {
+		if (!range[j].end)
+			continue;
+
+		if (start <= range[j].start && end >= range[j].end) {
+			range[j].start = 0;
+			range[j].end = 0;
+			continue;
+		}
+
+		if (start <= range[j].start && end < range[j].end &&
+		    range[j].start < end) {
+			range[j].start = end;
+			continue;
+		}
+
+
+		if (start > range[j].start && end >= range[j].end &&
+		    range[j].end > start) {
+			range[j].end = start;
+			continue;
+		}
+
+		if (start > range[j].start && end < range[j].end) {
+			/* Find the new spare: */
+			for (i = 0; i < az; i++) {
+				if (range[i].end == 0)
+					break;
+			}
+			if (i < az) {
+				range[i].end = range[j].end;
+				range[i].start = end;
+			} else {
+				printk(KERN_ERR "run of slot in ranges\n");
+			}
+			range[j].end = start;
+			continue;
+		}
+	}
+}
+
+static int cmp_range(const void *x1, const void *x2)
+{
+	const struct range *r1 = x1;
+	const struct range *r2 = x2;
+	s64 start1, start2;
+
+	start1 = r1->start;
+	start2 = r2->start;
+
+	return start1 - start2;
+}
+
+int clean_sort_range(struct range *range, int az)
+{
+	int i, j, k = az - 1, nr_range = 0;
+
+	for (i = 0; i < k; i++) {
+		if (range[i].end)
+			continue;
+		for (j = k; j > i; j--) {
+			if (range[j].end) {
+				k = j;
+				break;
+			}
+		}
+		if (j == i)
+			break;
+		range[i].start = range[k].start;
+		range[i].end   = range[k].end;
+		range[k].start = 0;
+		range[k].end   = 0;
+		k--;
+	}
+	/* count it */
+	for (i = 0; i < az; i++) {
+		if (!range[i].end) {
+			nr_range = i;
+			break;
+		}
+	}
+
+	/* sort them */
+	sort(range, nr_range, sizeof(struct range), cmp_range, NULL);
+
+	return nr_range;
+}
+
+void sort_range(struct range *range, int nr_range)
+{
+	/* sort them */
+	sort(range, nr_range, sizeof(struct range), cmp_range, NULL);
+}
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 258cdf0..58df55b 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -818,13 +818,13 @@
 		/* Should not happen, but... */
 		pipe_count = RCU_TORTURE_PIPE_LEN;
 	}
-	__this_cpu_inc(per_cpu_var(rcu_torture_count)[pipe_count]);
+	__this_cpu_inc(rcu_torture_count[pipe_count]);
 	completed = cur_ops->completed() - completed;
 	if (completed > RCU_TORTURE_PIPE_LEN) {
 		/* Should not happen, but... */
 		completed = RCU_TORTURE_PIPE_LEN;
 	}
-	__this_cpu_inc(per_cpu_var(rcu_torture_batch)[completed]);
+	__this_cpu_inc(rcu_torture_batch[completed]);
 	preempt_enable();
 	cur_ops->readunlock(idx);
 }
@@ -877,13 +877,13 @@
 			/* Should not happen, but... */
 			pipe_count = RCU_TORTURE_PIPE_LEN;
 		}
-		__this_cpu_inc(per_cpu_var(rcu_torture_count)[pipe_count]);
+		__this_cpu_inc(rcu_torture_count[pipe_count]);
 		completed = cur_ops->completed() - completed;
 		if (completed > RCU_TORTURE_PIPE_LEN) {
 			/* Should not happen, but... */
 			completed = RCU_TORTURE_PIPE_LEN;
 		}
-		__this_cpu_inc(per_cpu_var(rcu_torture_batch)[completed]);
+		__this_cpu_inc(rcu_torture_batch[completed]);
 		preempt_enable();
 		cur_ops->readunlock(idx);
 		schedule();
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 1439eb5..4a525a3 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -246,12 +246,21 @@
 
 #define RCU_JIFFIES_TILL_FORCE_QS	 3	/* for rsp->jiffies_force_qs */
 #ifdef CONFIG_RCU_CPU_STALL_DETECTOR
-#define RCU_SECONDS_TILL_STALL_CHECK   (10 * HZ)  /* for rsp->jiffies_stall */
-#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ)  /* for rsp->jiffies_stall */
-#define RCU_STALL_RAT_DELAY		2	  /* Allow other CPUs time */
-						  /*  to take at least one */
-						  /*  scheduling clock irq */
-						  /*  before ratting on them. */
+
+#ifdef CONFIG_PROVE_RCU
+#define RCU_STALL_DELAY_DELTA	       (5 * HZ)
+#else
+#define RCU_STALL_DELAY_DELTA	       0
+#endif
+
+#define RCU_SECONDS_TILL_STALL_CHECK   (10 * HZ + RCU_STALL_DELAY_DELTA)
+						/* for rsp->jiffies_stall */
+#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ + RCU_STALL_DELAY_DELTA)
+						/* for rsp->jiffies_stall */
+#define RCU_STALL_RAT_DELAY		2	/* Allow other CPUs time */
+						/*  to take at least one */
+						/*  scheduling clock irq */
+						/*  before ratting on them. */
 
 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 464ad2c..79b53bd 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -1010,6 +1010,10 @@
 	int c = 0;
 	int thatcpu;
 
+	/* Check for being in the holdoff period. */
+	if (per_cpu(rcu_dyntick_holdoff, cpu) == jiffies)
+		return rcu_needs_cpu_quick_check(cpu);
+
 	/* Don't bother unless we are the last non-dyntick-idle CPU. */
 	for_each_cpu_not(thatcpu, nohz_cpu_mask)
 		if (thatcpu != cpu) {
@@ -1041,10 +1045,8 @@
 	}
 
 	/* If RCU callbacks are still pending, RCU still needs this CPU. */
-	if (c) {
+	if (c)
 		raise_softirq(RCU_SOFTIRQ);
-		per_cpu(rcu_dyntick_holdoff, cpu) = jiffies;
-	}
 	return c;
 }
 
diff --git a/kernel/relay.c b/kernel/relay.c
index c705a41..3d97f28 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -1215,14 +1215,14 @@
 /*
  *	subbuf_splice_actor - splice up to one subbuf's worth of data
  */
-static int subbuf_splice_actor(struct file *in,
+static ssize_t subbuf_splice_actor(struct file *in,
 			       loff_t *ppos,
 			       struct pipe_inode_info *pipe,
 			       size_t len,
 			       unsigned int flags,
 			       int *nonpad_ret)
 {
-	unsigned int pidx, poff, total_len, subbuf_pages, nr_pages, ret;
+	unsigned int pidx, poff, total_len, subbuf_pages, nr_pages;
 	struct rchan_buf *rbuf = in->private_data;
 	unsigned int subbuf_size = rbuf->chan->subbuf_size;
 	uint64_t pos = (uint64_t) *ppos;
@@ -1241,6 +1241,7 @@
 		.ops = &relay_pipe_buf_ops,
 		.spd_release = relay_page_release,
 	};
+	ssize_t ret;
 
 	if (rbuf->subbufs_produced == rbuf->subbufs_consumed)
 		return 0;
diff --git a/kernel/resource.c b/kernel/resource.c
index 4e9d87f..2d5be5d 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -304,7 +304,7 @@
 		void *arg, int (*func)(unsigned long, unsigned long, void *))
 {
 	struct resource res;
-	unsigned long pfn, len;
+	unsigned long pfn, end_pfn;
 	u64 orig_end;
 	int ret = -1;
 
@@ -314,9 +314,10 @@
 	orig_end = res.end;
 	while ((res.start < res.end) &&
 		(find_next_system_ram(&res, "System RAM") >= 0)) {
-		pfn = (unsigned long)(res.start >> PAGE_SHIFT);
-		len = (unsigned long)((res.end + 1 - res.start) >> PAGE_SHIFT);
-		ret = (*func)(pfn, len, arg);
+		pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		end_pfn = (res.end + 1) >> PAGE_SHIFT;
+		if (end_pfn > pfn)
+			ret = (*func)(pfn, end_pfn - pfn, arg);
 		if (ret)
 			break;
 		res.start = res.end + 1;
diff --git a/kernel/sched.c b/kernel/sched.c
index 6a212c9..9ab3cd7 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1521,7 +1521,7 @@
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 
-static __read_mostly unsigned long *update_shares_data;
+static __read_mostly unsigned long __percpu *update_shares_data;
 
 static void __set_se_shares(struct sched_entity *se, unsigned long shares);
 
@@ -2359,7 +2359,7 @@
 {
 	int cpu, orig_cpu, this_cpu, success = 0;
 	unsigned long flags;
-	struct rq *rq, *orig_rq;
+	struct rq *rq;
 
 	if (!sched_feat(SYNC_WAKEUPS))
 		wake_flags &= ~WF_SYNC;
@@ -2367,7 +2367,7 @@
 	this_cpu = get_cpu();
 
 	smp_wmb();
-	rq = orig_rq = task_rq_lock(p, &flags);
+	rq = task_rq_lock(p, &flags);
 	update_rq_clock(rq);
 	if (!(p->state & state))
 		goto out;
@@ -4353,7 +4353,7 @@
 	/* convert nice value [19,-20] to rlimit style value [1,40] */
 	int nice_rlim = 20 - nice;
 
-	return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur ||
+	return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) ||
 		capable(CAP_SYS_NICE));
 }
 
@@ -4530,7 +4530,7 @@
 
 			if (!lock_task_sighand(p, &flags))
 				return -ESRCH;
-			rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur;
+			rlim_rtprio = task_rlimit(p, RLIMIT_RTPRIO);
 			unlock_task_sighand(p, &flags);
 
 			/* can't set/change the rt policy */
@@ -7406,11 +7406,13 @@
 
 #ifdef CONFIG_SCHED_MC
 static ssize_t sched_mc_power_savings_show(struct sysdev_class *class,
+					   struct sysdev_class_attribute *attr,
 					   char *page)
 {
 	return sprintf(page, "%u\n", sched_mc_power_savings);
 }
 static ssize_t sched_mc_power_savings_store(struct sysdev_class *class,
+					    struct sysdev_class_attribute *attr,
 					    const char *buf, size_t count)
 {
 	return sched_power_savings_store(buf, count, 0);
@@ -7422,11 +7424,13 @@
 
 #ifdef CONFIG_SCHED_SMT
 static ssize_t sched_smt_power_savings_show(struct sysdev_class *dev,
+					    struct sysdev_class_attribute *attr,
 					    char *page)
 {
 	return sprintf(page, "%u\n", sched_smt_power_savings);
 }
 static ssize_t sched_smt_power_savings_store(struct sysdev_class *dev,
+					     struct sysdev_class_attribute *attr,
 					     const char *buf, size_t count)
 {
 	return sched_power_savings_store(buf, count, 1);
@@ -8813,7 +8817,7 @@
 struct cpuacct {
 	struct cgroup_subsys_state css;
 	/* cpuusage holds pointer to a u64-type object on every cpu */
-	u64 *cpuusage;
+	u64 __percpu *cpuusage;
 	struct percpu_counter cpustat[CPUACCT_STAT_NSTATS];
 	struct cpuacct *parent;
 };
diff --git a/kernel/sched_cpupri.c b/kernel/sched_cpupri.c
index eeb3506..fccf9fb 100644
--- a/kernel/sched_cpupri.c
+++ b/kernel/sched_cpupri.c
@@ -47,7 +47,7 @@
 }
 
 #define for_each_cpupri_active(array, idx)                    \
-	for_each_bit(idx, array, CPUPRI_NR_PRIORITIES)
+	for_each_set_bit(idx, array, CPUPRI_NR_PRIORITIES)
 
 /**
  * cpupri_find - find the best (lowest-pri) CPU in the system
@@ -56,7 +56,7 @@
  * @lowest_mask: A mask to fill in with selected CPUs (or NULL)
  *
  * Note: This function returns the recommended CPUs as calculated during the
- * current invokation.  By the time the call returns, the CPUs may have in
+ * current invocation.  By the time the call returns, the CPUs may have in
  * fact changed priorities any number of times.  While not ideal, it is not
  * an issue of correctness since the normal rebalancer logic will correct
  * any discrepancies created by racing against the uncertainty of the current
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 3e1fd96..5a5ea2c 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -3476,7 +3476,7 @@
 
 static inline int on_null_domain(int cpu)
 {
-	return !rcu_dereference(cpu_rq(cpu)->sd);
+	return !rcu_dereference_sched(cpu_rq(cpu)->sd);
 }
 
 /*
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index bf3e38f..b5b920a 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -1146,7 +1146,12 @@
 		if (next && next->prio < idx)
 			continue;
 		list_for_each_entry(rt_se, array->queue + idx, run_list) {
-			struct task_struct *p = rt_task_of(rt_se);
+			struct task_struct *p;
+
+			if (!rt_entity_is_task(rt_se))
+				continue;
+
+			p = rt_task_of(rt_se);
 			if (pick_rt_task(rq, p, cpu)) {
 				next = p;
 				break;
@@ -1662,8 +1667,9 @@
 	if (!p->signal)
 		return;
 
-	soft = p->signal->rlim[RLIMIT_RTTIME].rlim_cur;
-	hard = p->signal->rlim[RLIMIT_RTTIME].rlim_max;
+	/* max may change after cur was read, this will be fixed next tick */
+	soft = task_rlimit(p, RLIMIT_RTTIME);
+	hard = task_rlimit_max(p, RLIMIT_RTTIME);
 
 	if (soft != RLIM_INFINITY) {
 		unsigned long next;
diff --git a/kernel/signal.c b/kernel/signal.c
index 934ae5e..dbd7fe0 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -159,6 +159,10 @@
 
 /* Given the mask, find the first available signal that should be serviced. */
 
+#define SYNCHRONOUS_MASK \
+	(sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \
+	 sigmask(SIGTRAP) | sigmask(SIGFPE))
+
 int next_signal(struct sigpending *pending, sigset_t *mask)
 {
 	unsigned long i, *s, *m, x;
@@ -166,26 +170,39 @@
 
 	s = pending->signal.sig;
 	m = mask->sig;
+
+	/*
+	 * Handle the first word specially: it contains the
+	 * synchronous signals that need to be dequeued first.
+	 */
+	x = *s &~ *m;
+	if (x) {
+		if (x & SYNCHRONOUS_MASK)
+			x &= SYNCHRONOUS_MASK;
+		sig = ffz(~x) + 1;
+		return sig;
+	}
+
 	switch (_NSIG_WORDS) {
 	default:
-		for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m)
-			if ((x = *s &~ *m) != 0) {
-				sig = ffz(~x) + i*_NSIG_BPW + 1;
-				break;
-			}
-		break;
-
-	case 2: if ((x = s[0] &~ m[0]) != 0)
-			sig = 1;
-		else if ((x = s[1] &~ m[1]) != 0)
-			sig = _NSIG_BPW + 1;
-		else
+		for (i = 1; i < _NSIG_WORDS; ++i) {
+			x = *++s &~ *++m;
+			if (!x)
+				continue;
+			sig = ffz(~x) + i*_NSIG_BPW + 1;
 			break;
-		sig += ffz(~x);
+		}
 		break;
 
-	case 1: if ((x = *s &~ *m) != 0)
-			sig = ffz(~x) + 1;
+	case 2:
+		x = s[1] &~ m[1];
+		if (!x)
+			break;
+		sig = ffz(~x) + _NSIG_BPW + 1;
+		break;
+
+	case 1:
+		/* Nothing to do */
 		break;
 	}
 
@@ -228,7 +245,7 @@
 
 	if (override_rlimit ||
 	    atomic_read(&user->sigpending) <=
-			t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) {
+			task_rlimit(t, RLIMIT_SIGPENDING)) {
 		q = kmem_cache_alloc(sigqueue_cachep, flags);
 	} else {
 		print_dropped_signal(sig);
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 912823e..9bb9fb1 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -45,7 +45,7 @@
 static struct workqueue_struct *stop_machine_wq;
 static struct stop_machine_data active, idle;
 static const struct cpumask *active_cpus;
-static void *stop_machine_work;
+static void __percpu *stop_machine_work;
 
 static void set_state(enum stopmachine_state newstate)
 {
diff --git a/kernel/sys.c b/kernel/sys.c
index 877fe4f..8298878f 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -33,6 +33,7 @@
 #include <linux/task_io_accounting_ops.h>
 #include <linux/seccomp.h>
 #include <linux/cpu.h>
+#include <linux/personality.h>
 #include <linux/ptrace.h>
 #include <linux/fs_struct.h>
 
@@ -571,8 +572,7 @@
 	if (!new_user)
 		return -EAGAIN;
 
-	if (atomic_read(&new_user->processes) >=
-				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
+	if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
 			new_user != INIT_USER) {
 		free_uid(new_user);
 		return -EAGAIN;
@@ -1115,6 +1115,15 @@
 
 DECLARE_RWSEM(uts_sem);
 
+#ifdef COMPAT_UTS_MACHINE
+#define override_architecture(name) \
+	(current->personality == PER_LINUX32 && \
+	 copy_to_user(name->machine, COMPAT_UTS_MACHINE, \
+		      sizeof(COMPAT_UTS_MACHINE)))
+#else
+#define override_architecture(name)	0
+#endif
+
 SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
 {
 	int errno = 0;
@@ -1123,9 +1132,66 @@
 	if (copy_to_user(name, utsname(), sizeof *name))
 		errno = -EFAULT;
 	up_read(&uts_sem);
+
+	if (!errno && override_architecture(name))
+		errno = -EFAULT;
 	return errno;
 }
 
+#ifdef __ARCH_WANT_SYS_OLD_UNAME
+/*
+ * Old cruft
+ */
+SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
+{
+	int error = 0;
+
+	if (!name)
+		return -EFAULT;
+
+	down_read(&uts_sem);
+	if (copy_to_user(name, utsname(), sizeof(*name)))
+		error = -EFAULT;
+	up_read(&uts_sem);
+
+	if (!error && override_architecture(name))
+		error = -EFAULT;
+	return error;
+}
+
+SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
+{
+	int error;
+
+	if (!name)
+		return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
+		return -EFAULT;
+
+	down_read(&uts_sem);
+	error = __copy_to_user(&name->sysname, &utsname()->sysname,
+			       __OLD_UTS_LEN);
+	error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
+	error |= __copy_to_user(&name->nodename, &utsname()->nodename,
+				__OLD_UTS_LEN);
+	error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
+	error |= __copy_to_user(&name->release, &utsname()->release,
+				__OLD_UTS_LEN);
+	error |= __put_user(0, name->release + __OLD_UTS_LEN);
+	error |= __copy_to_user(&name->version, &utsname()->version,
+				__OLD_UTS_LEN);
+	error |= __put_user(0, name->version + __OLD_UTS_LEN);
+	error |= __copy_to_user(&name->machine, &utsname()->machine,
+				__OLD_UTS_LEN);
+	error |= __put_user(0, name->machine + __OLD_UTS_LEN);
+	up_read(&uts_sem);
+
+	if (!error && override_architecture(name))
+		error = -EFAULT;
+	return error ? -EFAULT : 0;
+}
+#endif
+
 SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
 {
 	int errno;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 695384f..70f2ea7 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -126,6 +126,7 @@
 cond_syscall(sys_setuid16);
 cond_syscall(sys_vm86old);
 cond_syscall(sys_vm86);
+cond_syscall(sys_ipc);
 cond_syscall(compat_sys_ipc);
 cond_syscall(compat_sys_sysctl);
 cond_syscall(sys_flock);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 33e7a38..8686b0f 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -23,6 +23,7 @@
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
+#include <linux/signal.h>
 #include <linux/proc_fs.h>
 #include <linux/security.h>
 #include <linux/ctype.h>
@@ -50,6 +51,7 @@
 #include <linux/ftrace.h>
 #include <linux/slow-work.h>
 #include <linux/perf_event.h>
+#include <linux/kprobes.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>
@@ -59,13 +61,23 @@
 #include <asm/stacktrace.h>
 #include <asm/io.h>
 #endif
+#ifdef CONFIG_BSD_PROCESS_ACCT
+#include <linux/acct.h>
+#endif
+#ifdef CONFIG_RT_MUTEXES
+#include <linux/rtmutex.h>
+#endif
+#if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_LOCK_STAT)
+#include <linux/lockdep.h>
+#endif
+#ifdef CONFIG_CHR_DEV_SG
+#include <scsi/sg.h>
+#endif
 
 
 #if defined(CONFIG_SYSCTL)
 
 /* External variables not in a header file. */
-extern int C_A_D;
-extern int print_fatal_signals;
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern int sysctl_panic_on_oom;
@@ -87,9 +99,6 @@
 #ifndef CONFIG_MMU
 extern int sysctl_nr_trim_pages;
 #endif
-#ifdef CONFIG_RCU_TORTURE_TEST
-extern int rcutorture_runnable;
-#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
 #ifdef CONFIG_BLOCK
 extern int blk_iopoll_enabled;
 #endif
@@ -119,14 +128,6 @@
 
 static int ngroups_max = NGROUPS_MAX;
 
-#ifdef CONFIG_MODULES
-extern char modprobe_path[];
-extern int modules_disabled;
-#endif
-#ifdef CONFIG_CHR_DEV_SG
-extern int sg_big_buff;
-#endif
-
 #ifdef CONFIG_SPARC
 #include <asm/system.h>
 #endif
@@ -148,10 +149,6 @@
 extern int spin_retry;
 #endif
 
-#ifdef CONFIG_BSD_PROCESS_ACCT
-extern int acct_parm[];
-#endif
-
 #ifdef CONFIG_IA64
 extern int no_unaligned_warning;
 extern int unaligned_dump_stack;
@@ -159,10 +156,6 @@
 
 extern struct ratelimit_state printk_ratelimit_state;
 
-#ifdef CONFIG_RT_MUTEXES
-extern int max_lock_depth;
-#endif
-
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(struct ctl_table *table, int write,
 		  void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -201,9 +194,6 @@
 int sysctl_legacy_va_layout;
 #endif
 
-extern int prove_locking;
-extern int lock_stat;
-
 /* The default sysctl tables: */
 
 static struct ctl_table root_table[] = {
@@ -1450,6 +1440,17 @@
 		.proc_handler	= proc_dointvec
 	},
 #endif
+#if defined(CONFIG_OPTPROBES)
+	{
+		.procname	= "kprobes-optimization",
+		.data		= &sysctl_kprobes_optimization,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_kprobes_optimization_handler,
+		.extra1		= &zero,
+		.extra2		= &one,
+	},
+#endif
 	{ }
 };
 
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index 8f5d16e..8cd50d8 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -1331,7 +1331,7 @@
 	ssize_t result;
 	char *pathname;
 	int flags;
-	int acc_mode, fmode;
+	int acc_mode;
 
 	pathname = sysctl_getname(name, nlen, &table);
 	result = PTR_ERR(pathname);
@@ -1342,15 +1342,12 @@
 	if (oldval && oldlen && newval && newlen) {
 		flags = O_RDWR;
 		acc_mode = MAY_READ | MAY_WRITE;
-		fmode = FMODE_READ | FMODE_WRITE;
 	} else if (newval && newlen) {
 		flags = O_WRONLY;
 		acc_mode = MAY_WRITE;
-		fmode = FMODE_WRITE;
 	} else if (oldval && oldlen) {
 		flags = O_RDONLY;
 		acc_mode = MAY_READ;
-		fmode = FMODE_READ;
 	} else {
 		result = 0;
 		goto out_putname;
@@ -1361,7 +1358,7 @@
 	if (result)
 		goto out_putname;
 
-	result = may_open(&nd.path, acc_mode, fmode);
+	result = may_open(&nd.path, acc_mode, flags);
 	if (result)
 		goto out_putpath;
 
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 1f663d2..1f5dde6 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -592,6 +592,10 @@
  */
 static int __init clocksource_done_booting(void)
 {
+	mutex_lock(&clocksource_mutex);
+	curr_clocksource = clocksource_default_clock();
+	mutex_unlock(&clocksource_mutex);
+
 	finished_booting = 1;
 
 	/*
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 8378357..d9062f5 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -27,6 +27,7 @@
 #include <linux/ctype.h>
 #include <linux/list.h>
 #include <linux/hash.h>
+#include <linux/rcupdate.h>
 
 #include <trace/events/sched.h>
 
@@ -84,22 +85,22 @@
 ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
 ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
 
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-static int ftrace_set_func(unsigned long *array, int *idx, char *buffer);
-#endif
-
+/*
+ * Traverse the ftrace_list, invoking all entries.  The reason that we
+ * can use rcu_dereference_raw() is that elements removed from this list
+ * are simply leaked, so there is no need to interact with a grace-period
+ * mechanism.  The rcu_dereference_raw() calls are needed to handle
+ * concurrent insertions into the ftrace_list.
+ *
+ * Silly Alpha and silly pointer-speculation compiler optimizations!
+ */
 static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
 {
-	struct ftrace_ops *op = ftrace_list;
-
-	/* in case someone actually ports this to alpha! */
-	read_barrier_depends();
+	struct ftrace_ops *op = rcu_dereference_raw(ftrace_list); /*see above*/
 
 	while (op != &ftrace_list_end) {
-		/* silly alpha */
-		read_barrier_depends();
 		op->func(ip, parent_ip);
-		op = op->next;
+		op = rcu_dereference_raw(op->next); /*see above*/
 	};
 }
 
@@ -154,8 +155,7 @@
 	 * the ops->next pointer is valid before another CPU sees
 	 * the ops pointer included into the ftrace_list.
 	 */
-	smp_wmb();
-	ftrace_list = ops;
+	rcu_assign_pointer(ftrace_list, ops);
 
 	if (ftrace_enabled) {
 		ftrace_func_t func;
@@ -2276,6 +2276,8 @@
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
+static int ftrace_set_func(unsigned long *array, int *idx, char *buffer);
+
 static int __init set_graph_function(char *str)
 {
 	strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
@@ -3351,6 +3353,7 @@
 {
 	/* Make sure we do not use the parent ret_stack */
 	t->ret_stack = NULL;
+	t->curr_ret_stack = -1;
 
 	if (ftrace_graph_active) {
 		struct ftrace_ret_stack *ret_stack;
@@ -3360,7 +3363,6 @@
 				GFP_KERNEL);
 		if (!ret_stack)
 			return;
-		t->curr_ret_stack = -1;
 		atomic_set(&t->tracing_graph_pause, 0);
 		atomic_set(&t->trace_overrun, 0);
 		t->ftrace_timestamp = 0;
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 8c1b2d2..05a9f83 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -20,6 +20,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 
+#include <asm/local.h>
 #include "trace.h"
 
 /*
@@ -2232,12 +2233,12 @@
 	if (ring_buffer_flags != RB_BUFFERS_ON)
 		return NULL;
 
-	if (atomic_read(&buffer->record_disabled))
-		return NULL;
-
 	/* If we are tracing schedule, we don't want to recurse */
 	resched = ftrace_preempt_disable();
 
+	if (atomic_read(&buffer->record_disabled))
+		goto out_nocheck;
+
 	if (trace_recursive_lock())
 		goto out_nocheck;
 
@@ -2469,11 +2470,11 @@
 	if (ring_buffer_flags != RB_BUFFERS_ON)
 		return -EBUSY;
 
-	if (atomic_read(&buffer->record_disabled))
-		return -EBUSY;
-
 	resched = ftrace_preempt_disable();
 
+	if (atomic_read(&buffer->record_disabled))
+		goto out;
+
 	cpu = raw_smp_processor_id();
 
 	if (!cpumask_test_cpu(cpu, buffer->cpumask))
@@ -2541,7 +2542,7 @@
  * @buffer: The ring buffer to enable writes
  *
  * Note, multiple disables will need the same number of enables
- * to truely enable the writing (much like preempt_disable).
+ * to truly enable the writing (much like preempt_disable).
  */
 void ring_buffer_record_enable(struct ring_buffer *buffer)
 {
@@ -2577,7 +2578,7 @@
  * @cpu: The CPU to enable.
  *
  * Note, multiple disables will need the same number of enables
- * to truely enable the writing (much like preempt_disable).
+ * to truly enable the writing (much like preempt_disable).
  */
 void ring_buffer_record_enable_cpu(struct ring_buffer *buffer, int cpu)
 {
diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c
index b2477ca..df74c79 100644
--- a/kernel/trace/ring_buffer_benchmark.c
+++ b/kernel/trace/ring_buffer_benchmark.c
@@ -8,6 +8,7 @@
 #include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/time.h>
+#include <asm/local.h>
 
 struct rb_page {
 	u64		ts;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 032c57c..3ec2ee6 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -92,12 +92,12 @@
 static inline void ftrace_disable_cpu(void)
 {
 	preempt_disable();
-	__this_cpu_inc(per_cpu_var(ftrace_cpu_disabled));
+	__this_cpu_inc(ftrace_cpu_disabled);
 }
 
 static inline void ftrace_enable_cpu(void)
 {
-	__this_cpu_dec(per_cpu_var(ftrace_cpu_disabled));
+	__this_cpu_dec(ftrace_cpu_disabled);
 	preempt_enable();
 }
 
@@ -374,6 +374,21 @@
 }
 __setup("trace_buf_size=", set_buf_size);
 
+static int __init set_tracing_thresh(char *str)
+{
+	unsigned long threshhold;
+	int ret;
+
+	if (!str)
+		return 0;
+	ret = strict_strtoul(str, 0, &threshhold);
+	if (ret < 0)
+		return 0;
+	tracing_thresh = threshhold * 1000;
+	return 1;
+}
+__setup("tracing_thresh=", set_tracing_thresh);
+
 unsigned long nsecs_to_usecs(unsigned long nsecs)
 {
 	return nsecs / 1000;
@@ -579,9 +594,10 @@
 static arch_spinlock_t ftrace_max_lock =
 	(arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
 
+unsigned long __read_mostly	tracing_thresh;
+
 #ifdef CONFIG_TRACER_MAX_TRACE
 unsigned long __read_mostly	tracing_max_latency;
-unsigned long __read_mostly	tracing_thresh;
 
 /*
  * Copy the new maximum trace into the separate maximum-trace
@@ -592,7 +608,7 @@
 __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
 {
 	struct trace_array_cpu *data = tr->data[cpu];
-	struct trace_array_cpu *max_data = tr->data[cpu];
+	struct trace_array_cpu *max_data;
 
 	max_tr.cpu = cpu;
 	max_tr.time_start = data->preempt_timestamp;
@@ -602,7 +618,7 @@
 	max_data->critical_start = data->critical_start;
 	max_data->critical_end = data->critical_end;
 
-	memcpy(data->comm, tsk->comm, TASK_COMM_LEN);
+	memcpy(max_data->comm, tsk->comm, TASK_COMM_LEN);
 	max_data->pid = tsk->pid;
 	max_data->uid = task_uid(tsk);
 	max_data->nice = tsk->static_prio - 20 - MAX_RT_PRIO;
@@ -824,10 +840,10 @@
 	mutex_unlock(&trace_types_lock);
 }
 
-static void __tracing_reset(struct trace_array *tr, int cpu)
+static void __tracing_reset(struct ring_buffer *buffer, int cpu)
 {
 	ftrace_disable_cpu();
-	ring_buffer_reset_cpu(tr->buffer, cpu);
+	ring_buffer_reset_cpu(buffer, cpu);
 	ftrace_enable_cpu();
 }
 
@@ -839,7 +855,7 @@
 
 	/* Make sure all commits have finished */
 	synchronize_sched();
-	__tracing_reset(tr, cpu);
+	__tracing_reset(buffer, cpu);
 
 	ring_buffer_record_enable(buffer);
 }
@@ -857,7 +873,7 @@
 	tr->time_start = ftrace_now(tr->cpu);
 
 	for_each_online_cpu(cpu)
-		__tracing_reset(tr, cpu);
+		__tracing_reset(buffer, cpu);
 
 	ring_buffer_record_enable(buffer);
 }
@@ -934,6 +950,8 @@
 		goto out;
 	}
 
+	/* Prevent the buffers from switching */
+	arch_spin_lock(&ftrace_max_lock);
 
 	buffer = global_trace.buffer;
 	if (buffer)
@@ -943,6 +961,8 @@
 	if (buffer)
 		ring_buffer_record_enable(buffer);
 
+	arch_spin_unlock(&ftrace_max_lock);
+
 	ftrace_start();
  out:
 	spin_unlock_irqrestore(&tracing_start_lock, flags);
@@ -964,6 +984,9 @@
 	if (trace_stop_count++)
 		goto out;
 
+	/* Prevent the buffers from switching */
+	arch_spin_lock(&ftrace_max_lock);
+
 	buffer = global_trace.buffer;
 	if (buffer)
 		ring_buffer_record_disable(buffer);
@@ -972,6 +995,8 @@
 	if (buffer)
 		ring_buffer_record_disable(buffer);
 
+	arch_spin_unlock(&ftrace_max_lock);
+
  out:
 	spin_unlock_irqrestore(&tracing_start_lock, flags);
 }
@@ -1166,7 +1191,7 @@
 	struct ftrace_entry *entry;
 
 	/* If we are reading the ring buffer, don't trace */
-	if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled))))
+	if (unlikely(__this_cpu_read(ftrace_cpu_disabled)))
 		return;
 
 	event = trace_buffer_lock_reserve(buffer, TRACE_FN, sizeof(*entry),
@@ -1259,6 +1284,13 @@
 	if (!(trace_flags & TRACE_ITER_USERSTACKTRACE))
 		return;
 
+	/*
+	 * NMIs can not handle page faults, even with fix ups.
+	 * The save user stack can (and often does) fault.
+	 */
+	if (unlikely(in_nmi()))
+		return;
+
 	event = trace_buffer_lock_reserve(buffer, TRACE_USER_STACK,
 					  sizeof(*entry), flags, pc);
 	if (!event)
@@ -1703,6 +1735,7 @@
 
 		ftrace_enable_cpu();
 
+		iter->leftover = 0;
 		for (p = iter; p && l < *pos; p = s_next(m, p, &l))
 			;
 
@@ -4248,10 +4281,10 @@
 #ifdef CONFIG_TRACER_MAX_TRACE
 	trace_create_file("tracing_max_latency", 0644, d_tracer,
 			&tracing_max_latency, &tracing_max_lat_fops);
+#endif
 
 	trace_create_file("tracing_thresh", 0644, d_tracer,
 			&tracing_thresh, &tracing_max_lat_fops);
-#endif
 
 	trace_create_file("README", 0444, d_tracer,
 			NULL, &tracing_readme_fops);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index fd05bca..2825ef2 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -396,9 +396,10 @@
 
 extern unsigned long nsecs_to_usecs(unsigned long nsecs);
 
+extern unsigned long tracing_thresh;
+
 #ifdef CONFIG_TRACER_MAX_TRACE
 extern unsigned long tracing_max_latency;
-extern unsigned long tracing_thresh;
 
 void update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu);
 void update_max_tr_single(struct trace_array *tr,
@@ -550,7 +551,7 @@
  * struct trace_parser - servers for reading the user input separated by spaces
  * @cont: set if the input is not complete - no final space char was found
  * @buffer: holds the parsed user input
- * @idx: user input lenght
+ * @idx: user input length
  * @size: buffer size
  */
 struct trace_parser {
diff --git a/kernel/trace/trace_clock.c b/kernel/trace/trace_clock.c
index 84a3a7b..6fbfb8f 100644
--- a/kernel/trace/trace_clock.c
+++ b/kernel/trace/trace_clock.c
@@ -13,6 +13,7 @@
  * Tracer plugins will chose a default from these clocks.
  */
 #include <linux/spinlock.h>
+#include <linux/irqflags.h>
 #include <linux/hardirq.h>
 #include <linux/module.h>
 #include <linux/percpu.h>
diff --git a/kernel/trace/trace_event_profile.c b/kernel/trace/trace_event_profile.c
index f0d6930..c1cc3ab 100644
--- a/kernel/trace/trace_event_profile.c
+++ b/kernel/trace/trace_event_profile.c
@@ -138,9 +138,9 @@
 	cpu = smp_processor_id();
 
 	if (in_nmi())
-		trace_buf = rcu_dereference(perf_trace_buf_nmi);
+		trace_buf = rcu_dereference_sched(perf_trace_buf_nmi);
 	else
-		trace_buf = rcu_dereference(perf_trace_buf);
+		trace_buf = rcu_dereference_sched(perf_trace_buf);
 
 	if (!trace_buf)
 		goto err;
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index e998a82..e6989d9 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -188,7 +188,7 @@
 	struct ring_buffer *buffer = tr->buffer;
 	struct ftrace_graph_ent_entry *entry;
 
-	if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled))))
+	if (unlikely(__this_cpu_read(ftrace_cpu_disabled)))
 		return 0;
 
 	event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_ENT,
@@ -237,6 +237,14 @@
 	return ret;
 }
 
+int trace_graph_thresh_entry(struct ftrace_graph_ent *trace)
+{
+	if (tracing_thresh)
+		return 1;
+	else
+		return trace_graph_entry(trace);
+}
+
 static void __trace_graph_return(struct trace_array *tr,
 				struct ftrace_graph_ret *trace,
 				unsigned long flags,
@@ -247,7 +255,7 @@
 	struct ring_buffer *buffer = tr->buffer;
 	struct ftrace_graph_ret_entry *entry;
 
-	if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled))))
+	if (unlikely(__this_cpu_read(ftrace_cpu_disabled)))
 		return;
 
 	event = trace_buffer_lock_reserve(buffer, TRACE_GRAPH_RET,
@@ -290,13 +298,26 @@
 	smp_mb();
 }
 
+void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
+{
+	if (tracing_thresh &&
+	    (trace->rettime - trace->calltime < tracing_thresh))
+		return;
+	else
+		trace_graph_return(trace);
+}
+
 static int graph_trace_init(struct trace_array *tr)
 {
 	int ret;
 
 	set_graph_array(tr);
-	ret = register_ftrace_graph(&trace_graph_return,
-				    &trace_graph_entry);
+	if (tracing_thresh)
+		ret = register_ftrace_graph(&trace_graph_thresh_return,
+					    &trace_graph_thresh_entry);
+	else
+		ret = register_ftrace_graph(&trace_graph_return,
+					    &trace_graph_entry);
 	if (ret)
 		return ret;
 	tracing_start_cmdline_record();
@@ -920,7 +941,7 @@
 		if (!ret)
 			return TRACE_TYPE_PARTIAL_LINE;
 	} else {
-		ret = trace_seq_printf(s, "} (%ps)\n", (void *)trace->func);
+		ret = trace_seq_printf(s, "} /* %ps */\n", (void *)trace->func);
 		if (!ret)
 			return TRACE_TYPE_PARTIAL_LINE;
 	}
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index 00d59d0..0a67e041 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -21,6 +21,7 @@
 #include <linux/tsacct_kern.h>
 #include <linux/acct.h>
 #include <linux/jiffies.h>
+#include <linux/mm.h>
 
 /*
  * fill in basic accounting fields
diff --git a/lib/Kconfig b/lib/Kconfig
index 97b136f..170d8ca 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -160,6 +160,9 @@
 config TEXTSEARCH_FSM
 	tristate
 
+config BTREE
+	boolean
+
 config HAS_IOMEM
 	boolean
 	depends on !NO_IOMEM
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 5e3407d..8e5ec5e 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -532,6 +532,14 @@
 
 	 For more details, see Documentation/lockstat.txt
 
+	 This also enables lock events required by "perf lock",
+	 subcommand of perf.
+	 If you want to use "perf lock", you also need to turn on
+	 CONFIG_EVENT_TRACING.
+
+	 CONFIG_LOCK_STAT defines "contended" and "acquired" lock events.
+	 (CONFIG_LOCKDEP defines "acquire" and "release" events.)
+
 config DEBUG_LOCKDEP
 	bool "Lock dependency engine debugging"
 	depends on DEBUG_KERNEL && LOCKDEP
@@ -864,8 +872,7 @@
 
 config LKDTM
 	tristate "Linux Kernel Dump Test Tool Module"
-	depends on DEBUG_KERNEL
-	depends on KPROBES
+	depends on DEBUG_FS
 	depends on BLOCK
 	default n
 	help
@@ -876,7 +883,7 @@
 	called lkdtm.
 
 	Documentation on how to use the module can be found in
-	drivers/misc/lkdtm.c
+	Documentation/fault-injection/provoke-crashes.txt
 
 config FAULT_INJECTION
 	bool "Fault-injection framework"
diff --git a/lib/Makefile b/lib/Makefile
index 3b0b4a6..2e152ae 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -41,6 +41,7 @@
 obj-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
+obj-$(CONFIG_BTREE) += btree.o
 obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
 obj-$(CONFIG_DEBUG_LIST) += list_debug.o
 obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 11bf497..ffb78c9 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -487,7 +487,7 @@
 EXPORT_SYMBOL(__bitmap_parse);
 
 /**
- * bitmap_parse_user()
+ * bitmap_parse_user - convert an ASCII hex string in a user buffer into a bitmap
  *
  * @ubuf: pointer to user buffer containing string.
  * @ulen: buffer size in bytes.  If string is smaller than this
@@ -619,7 +619,7 @@
 EXPORT_SYMBOL(bitmap_parselist);
 
 /**
- * bitmap_pos_to_ord(buf, pos, bits)
+ * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap
  *	@buf: pointer to a bitmap
  *	@pos: a bit position in @buf (0 <= @pos < @bits)
  *	@bits: number of valid bit positions in @buf
@@ -655,7 +655,7 @@
 }
 
 /**
- * bitmap_ord_to_pos(buf, ord, bits)
+ * bitmap_ord_to_pos - find position of n-th set bit in bitmap
  *	@buf: pointer to bitmap
  *	@ord: ordinal bit position (n-th set bit, n >= 0)
  *	@bits: number of valid bit positions in @buf
@@ -733,10 +733,9 @@
 	bitmap_zero(dst, bits);
 
 	w = bitmap_weight(new, bits);
-	for (oldbit = find_first_bit(src, bits);
-	     oldbit < bits;
-	     oldbit = find_next_bit(src, bits, oldbit + 1)) {
+	for_each_set_bit(oldbit, src, bits) {
 	     	int n = bitmap_pos_to_ord(old, oldbit, bits);
+
 		if (n < 0 || w == 0)
 			set_bit(oldbit, dst);	/* identity map */
 		else
@@ -903,9 +902,7 @@
 	 */
 
 	m = 0;
-	for (n = find_first_bit(relmap, bits);
-	     n < bits;
-	     n = find_next_bit(relmap, bits, n + 1)) {
+	for_each_set_bit(n, relmap, bits) {
 		/* m == bitmap_pos_to_ord(relmap, n, bits) */
 		if (test_bit(m, orig))
 			set_bit(n, dst);
@@ -934,9 +931,7 @@
 		return;
 	bitmap_zero(dst, bits);
 
-	for (oldbit = find_first_bit(orig, bits);
-	     oldbit < bits;
-	     oldbit = find_next_bit(orig, bits, oldbit + 1))
+	for_each_set_bit(oldbit, orig, bits)
 		set_bit(oldbit % sz, dst);
 }
 EXPORT_SYMBOL(bitmap_fold);
diff --git a/lib/btree.c b/lib/btree.c
new file mode 100644
index 0000000..41859a8
--- /dev/null
+++ b/lib/btree.c
@@ -0,0 +1,797 @@
+/*
+ * lib/btree.c	- Simple In-memory B+Tree
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2007-2008 Joern Engel <joern@logfs.org>
+ * Bits and pieces stolen from Peter Zijlstra's code, which is
+ * Copyright 2007, Red Hat Inc. Peter Zijlstra <pzijlstr@redhat.com>
+ * GPLv2
+ *
+ * see http://programming.kicks-ass.net/kernel-patches/vma_lookup/btree.patch
+ *
+ * A relatively simple B+Tree implementation.  I have written it as a learning
+ * excercise to understand how B+Trees work.  Turned out to be useful as well.
+ *
+ * B+Trees can be used similar to Linux radix trees (which don't have anything
+ * in common with textbook radix trees, beware).  Prerequisite for them working
+ * well is that access to a random tree node is much faster than a large number
+ * of operations within each node.
+ *
+ * Disks have fulfilled the prerequisite for a long time.  More recently DRAM
+ * has gained similar properties, as memory access times, when measured in cpu
+ * cycles, have increased.  Cacheline sizes have increased as well, which also
+ * helps B+Trees.
+ *
+ * Compared to radix trees, B+Trees are more efficient when dealing with a
+ * sparsely populated address space.  Between 25% and 50% of the memory is
+ * occupied with valid pointers.  When densely populated, radix trees contain
+ * ~98% pointers - hard to beat.  Very sparse radix trees contain only ~2%
+ * pointers.
+ *
+ * This particular implementation stores pointers identified by a long value.
+ * Storing NULL pointers is illegal, lookup will return NULL when no entry
+ * was found.
+ *
+ * A tricks was used that is not commonly found in textbooks.  The lowest
+ * values are to the right, not to the left.  All used slots within a node
+ * are on the left, all unused slots contain NUL values.  Most operations
+ * simply loop once over all slots and terminate on the first NUL.
+ */
+
+#include <linux/btree.h>
+#include <linux/cache.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define NODESIZE MAX(L1_CACHE_BYTES, 128)
+
+struct btree_geo {
+	int keylen;
+	int no_pairs;
+	int no_longs;
+};
+
+struct btree_geo btree_geo32 = {
+	.keylen = 1,
+	.no_pairs = NODESIZE / sizeof(long) / 2,
+	.no_longs = NODESIZE / sizeof(long) / 2,
+};
+EXPORT_SYMBOL_GPL(btree_geo32);
+
+#define LONG_PER_U64 (64 / BITS_PER_LONG)
+struct btree_geo btree_geo64 = {
+	.keylen = LONG_PER_U64,
+	.no_pairs = NODESIZE / sizeof(long) / (1 + LONG_PER_U64),
+	.no_longs = LONG_PER_U64 * (NODESIZE / sizeof(long) / (1 + LONG_PER_U64)),
+};
+EXPORT_SYMBOL_GPL(btree_geo64);
+
+struct btree_geo btree_geo128 = {
+	.keylen = 2 * LONG_PER_U64,
+	.no_pairs = NODESIZE / sizeof(long) / (1 + 2 * LONG_PER_U64),
+	.no_longs = 2 * LONG_PER_U64 * (NODESIZE / sizeof(long) / (1 + 2 * LONG_PER_U64)),
+};
+EXPORT_SYMBOL_GPL(btree_geo128);
+
+static struct kmem_cache *btree_cachep;
+
+void *btree_alloc(gfp_t gfp_mask, void *pool_data)
+{
+	return kmem_cache_alloc(btree_cachep, gfp_mask);
+}
+EXPORT_SYMBOL_GPL(btree_alloc);
+
+void btree_free(void *element, void *pool_data)
+{
+	kmem_cache_free(btree_cachep, element);
+}
+EXPORT_SYMBOL_GPL(btree_free);
+
+static unsigned long *btree_node_alloc(struct btree_head *head, gfp_t gfp)
+{
+	unsigned long *node;
+
+	node = mempool_alloc(head->mempool, gfp);
+	memset(node, 0, NODESIZE);
+	return node;
+}
+
+static int longcmp(const unsigned long *l1, const unsigned long *l2, size_t n)
+{
+	size_t i;
+
+	for (i = 0; i < n; i++) {
+		if (l1[i] < l2[i])
+			return -1;
+		if (l1[i] > l2[i])
+			return 1;
+	}
+	return 0;
+}
+
+static unsigned long *longcpy(unsigned long *dest, const unsigned long *src,
+		size_t n)
+{
+	size_t i;
+
+	for (i = 0; i < n; i++)
+		dest[i] = src[i];
+	return dest;
+}
+
+static unsigned long *longset(unsigned long *s, unsigned long c, size_t n)
+{
+	size_t i;
+
+	for (i = 0; i < n; i++)
+		s[i] = c;
+	return s;
+}
+
+static void dec_key(struct btree_geo *geo, unsigned long *key)
+{
+	unsigned long val;
+	int i;
+
+	for (i = geo->keylen - 1; i >= 0; i--) {
+		val = key[i];
+		key[i] = val - 1;
+		if (val)
+			break;
+	}
+}
+
+static unsigned long *bkey(struct btree_geo *geo, unsigned long *node, int n)
+{
+	return &node[n * geo->keylen];
+}
+
+static void *bval(struct btree_geo *geo, unsigned long *node, int n)
+{
+	return (void *)node[geo->no_longs + n];
+}
+
+static void setkey(struct btree_geo *geo, unsigned long *node, int n,
+		   unsigned long *key)
+{
+	longcpy(bkey(geo, node, n), key, geo->keylen);
+}
+
+static void setval(struct btree_geo *geo, unsigned long *node, int n,
+		   void *val)
+{
+	node[geo->no_longs + n] = (unsigned long) val;
+}
+
+static void clearpair(struct btree_geo *geo, unsigned long *node, int n)
+{
+	longset(bkey(geo, node, n), 0, geo->keylen);
+	node[geo->no_longs + n] = 0;
+}
+
+static inline void __btree_init(struct btree_head *head)
+{
+	head->node = NULL;
+	head->height = 0;
+}
+
+void btree_init_mempool(struct btree_head *head, mempool_t *mempool)
+{
+	__btree_init(head);
+	head->mempool = mempool;
+}
+EXPORT_SYMBOL_GPL(btree_init_mempool);
+
+int btree_init(struct btree_head *head)
+{
+	__btree_init(head);
+	head->mempool = mempool_create(0, btree_alloc, btree_free, NULL);
+	if (!head->mempool)
+		return -ENOMEM;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btree_init);
+
+void btree_destroy(struct btree_head *head)
+{
+	mempool_destroy(head->mempool);
+	head->mempool = NULL;
+}
+EXPORT_SYMBOL_GPL(btree_destroy);
+
+void *btree_last(struct btree_head *head, struct btree_geo *geo,
+		 unsigned long *key)
+{
+	int height = head->height;
+	unsigned long *node = head->node;
+
+	if (height == 0)
+		return NULL;
+
+	for ( ; height > 1; height--)
+		node = bval(geo, node, 0);
+
+	longcpy(key, bkey(geo, node, 0), geo->keylen);
+	return bval(geo, node, 0);
+}
+EXPORT_SYMBOL_GPL(btree_last);
+
+static int keycmp(struct btree_geo *geo, unsigned long *node, int pos,
+		  unsigned long *key)
+{
+	return longcmp(bkey(geo, node, pos), key, geo->keylen);
+}
+
+static int keyzero(struct btree_geo *geo, unsigned long *key)
+{
+	int i;
+
+	for (i = 0; i < geo->keylen; i++)
+		if (key[i])
+			return 0;
+
+	return 1;
+}
+
+void *btree_lookup(struct btree_head *head, struct btree_geo *geo,
+		unsigned long *key)
+{
+	int i, height = head->height;
+	unsigned long *node = head->node;
+
+	if (height == 0)
+		return NULL;
+
+	for ( ; height > 1; height--) {
+		for (i = 0; i < geo->no_pairs; i++)
+			if (keycmp(geo, node, i, key) <= 0)
+				break;
+		if (i == geo->no_pairs)
+			return NULL;
+		node = bval(geo, node, i);
+		if (!node)
+			return NULL;
+	}
+
+	if (!node)
+		return NULL;
+
+	for (i = 0; i < geo->no_pairs; i++)
+		if (keycmp(geo, node, i, key) == 0)
+			return bval(geo, node, i);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(btree_lookup);
+
+int btree_update(struct btree_head *head, struct btree_geo *geo,
+		 unsigned long *key, void *val)
+{
+	int i, height = head->height;
+	unsigned long *node = head->node;
+
+	if (height == 0)
+		return -ENOENT;
+
+	for ( ; height > 1; height--) {
+		for (i = 0; i < geo->no_pairs; i++)
+			if (keycmp(geo, node, i, key) <= 0)
+				break;
+		if (i == geo->no_pairs)
+			return -ENOENT;
+		node = bval(geo, node, i);
+		if (!node)
+			return -ENOENT;
+	}
+
+	if (!node)
+		return -ENOENT;
+
+	for (i = 0; i < geo->no_pairs; i++)
+		if (keycmp(geo, node, i, key) == 0) {
+			setval(geo, node, i, val);
+			return 0;
+		}
+	return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(btree_update);
+
+/*
+ * Usually this function is quite similar to normal lookup.  But the key of
+ * a parent node may be smaller than the smallest key of all its siblings.
+ * In such a case we cannot just return NULL, as we have only proven that no
+ * key smaller than __key, but larger than this parent key exists.
+ * So we set __key to the parent key and retry.  We have to use the smallest
+ * such parent key, which is the last parent key we encountered.
+ */
+void *btree_get_prev(struct btree_head *head, struct btree_geo *geo,
+		     unsigned long *__key)
+{
+	int i, height;
+	unsigned long *node, *oldnode;
+	unsigned long *retry_key = NULL, key[geo->keylen];
+
+	if (keyzero(geo, __key))
+		return NULL;
+
+	if (head->height == 0)
+		return NULL;
+retry:
+	longcpy(key, __key, geo->keylen);
+	dec_key(geo, key);
+
+	node = head->node;
+	for (height = head->height ; height > 1; height--) {
+		for (i = 0; i < geo->no_pairs; i++)
+			if (keycmp(geo, node, i, key) <= 0)
+				break;
+		if (i == geo->no_pairs)
+			goto miss;
+		oldnode = node;
+		node = bval(geo, node, i);
+		if (!node)
+			goto miss;
+		retry_key = bkey(geo, oldnode, i);
+	}
+
+	if (!node)
+		goto miss;
+
+	for (i = 0; i < geo->no_pairs; i++) {
+		if (keycmp(geo, node, i, key) <= 0) {
+			if (bval(geo, node, i)) {
+				longcpy(__key, bkey(geo, node, i), geo->keylen);
+				return bval(geo, node, i);
+			} else
+				goto miss;
+		}
+	}
+miss:
+	if (retry_key) {
+		__key = retry_key;
+		retry_key = NULL;
+		goto retry;
+	}
+	return NULL;
+}
+
+static int getpos(struct btree_geo *geo, unsigned long *node,
+		unsigned long *key)
+{
+	int i;
+
+	for (i = 0; i < geo->no_pairs; i++) {
+		if (keycmp(geo, node, i, key) <= 0)
+			break;
+	}
+	return i;
+}
+
+static int getfill(struct btree_geo *geo, unsigned long *node, int start)
+{
+	int i;
+
+	for (i = start; i < geo->no_pairs; i++)
+		if (!bval(geo, node, i))
+			break;
+	return i;
+}
+
+/*
+ * locate the correct leaf node in the btree
+ */
+static unsigned long *find_level(struct btree_head *head, struct btree_geo *geo,
+		unsigned long *key, int level)
+{
+	unsigned long *node = head->node;
+	int i, height;
+
+	for (height = head->height; height > level; height--) {
+		for (i = 0; i < geo->no_pairs; i++)
+			if (keycmp(geo, node, i, key) <= 0)
+				break;
+
+		if ((i == geo->no_pairs) || !bval(geo, node, i)) {
+			/* right-most key is too large, update it */
+			/* FIXME: If the right-most key on higher levels is
+			 * always zero, this wouldn't be necessary. */
+			i--;
+			setkey(geo, node, i, key);
+		}
+		BUG_ON(i < 0);
+		node = bval(geo, node, i);
+	}
+	BUG_ON(!node);
+	return node;
+}
+
+static int btree_grow(struct btree_head *head, struct btree_geo *geo,
+		      gfp_t gfp)
+{
+	unsigned long *node;
+	int fill;
+
+	node = btree_node_alloc(head, gfp);
+	if (!node)
+		return -ENOMEM;
+	if (head->node) {
+		fill = getfill(geo, head->node, 0);
+		setkey(geo, node, 0, bkey(geo, head->node, fill - 1));
+		setval(geo, node, 0, head->node);
+	}
+	head->node = node;
+	head->height++;
+	return 0;
+}
+
+static void btree_shrink(struct btree_head *head, struct btree_geo *geo)
+{
+	unsigned long *node;
+	int fill;
+
+	if (head->height <= 1)
+		return;
+
+	node = head->node;
+	fill = getfill(geo, node, 0);
+	BUG_ON(fill > 1);
+	head->node = bval(geo, node, 0);
+	head->height--;
+	mempool_free(node, head->mempool);
+}
+
+static int btree_insert_level(struct btree_head *head, struct btree_geo *geo,
+			      unsigned long *key, void *val, int level,
+			      gfp_t gfp)
+{
+	unsigned long *node;
+	int i, pos, fill, err;
+
+	BUG_ON(!val);
+	if (head->height < level) {
+		err = btree_grow(head, geo, gfp);
+		if (err)
+			return err;
+	}
+
+retry:
+	node = find_level(head, geo, key, level);
+	pos = getpos(geo, node, key);
+	fill = getfill(geo, node, pos);
+	/* two identical keys are not allowed */
+	BUG_ON(pos < fill && keycmp(geo, node, pos, key) == 0);
+
+	if (fill == geo->no_pairs) {
+		/* need to split node */
+		unsigned long *new;
+
+		new = btree_node_alloc(head, gfp);
+		if (!new)
+			return -ENOMEM;
+		err = btree_insert_level(head, geo,
+				bkey(geo, node, fill / 2 - 1),
+				new, level + 1, gfp);
+		if (err) {
+			mempool_free(new, head->mempool);
+			return err;
+		}
+		for (i = 0; i < fill / 2; i++) {
+			setkey(geo, new, i, bkey(geo, node, i));
+			setval(geo, new, i, bval(geo, node, i));
+			setkey(geo, node, i, bkey(geo, node, i + fill / 2));
+			setval(geo, node, i, bval(geo, node, i + fill / 2));
+			clearpair(geo, node, i + fill / 2);
+		}
+		if (fill & 1) {
+			setkey(geo, node, i, bkey(geo, node, fill - 1));
+			setval(geo, node, i, bval(geo, node, fill - 1));
+			clearpair(geo, node, fill - 1);
+		}
+		goto retry;
+	}
+	BUG_ON(fill >= geo->no_pairs);
+
+	/* shift and insert */
+	for (i = fill; i > pos; i--) {
+		setkey(geo, node, i, bkey(geo, node, i - 1));
+		setval(geo, node, i, bval(geo, node, i - 1));
+	}
+	setkey(geo, node, pos, key);
+	setval(geo, node, pos, val);
+
+	return 0;
+}
+
+int btree_insert(struct btree_head *head, struct btree_geo *geo,
+		unsigned long *key, void *val, gfp_t gfp)
+{
+	return btree_insert_level(head, geo, key, val, 1, gfp);
+}
+EXPORT_SYMBOL_GPL(btree_insert);
+
+static void *btree_remove_level(struct btree_head *head, struct btree_geo *geo,
+		unsigned long *key, int level);
+static void merge(struct btree_head *head, struct btree_geo *geo, int level,
+		unsigned long *left, int lfill,
+		unsigned long *right, int rfill,
+		unsigned long *parent, int lpos)
+{
+	int i;
+
+	for (i = 0; i < rfill; i++) {
+		/* Move all keys to the left */
+		setkey(geo, left, lfill + i, bkey(geo, right, i));
+		setval(geo, left, lfill + i, bval(geo, right, i));
+	}
+	/* Exchange left and right child in parent */
+	setval(geo, parent, lpos, right);
+	setval(geo, parent, lpos + 1, left);
+	/* Remove left (formerly right) child from parent */
+	btree_remove_level(head, geo, bkey(geo, parent, lpos), level + 1);
+	mempool_free(right, head->mempool);
+}
+
+static void rebalance(struct btree_head *head, struct btree_geo *geo,
+		unsigned long *key, int level, unsigned long *child, int fill)
+{
+	unsigned long *parent, *left = NULL, *right = NULL;
+	int i, no_left, no_right;
+
+	if (fill == 0) {
+		/* Because we don't steal entries from a neigbour, this case
+		 * can happen.  Parent node contains a single child, this
+		 * node, so merging with a sibling never happens.
+		 */
+		btree_remove_level(head, geo, key, level + 1);
+		mempool_free(child, head->mempool);
+		return;
+	}
+
+	parent = find_level(head, geo, key, level + 1);
+	i = getpos(geo, parent, key);
+	BUG_ON(bval(geo, parent, i) != child);
+
+	if (i > 0) {
+		left = bval(geo, parent, i - 1);
+		no_left = getfill(geo, left, 0);
+		if (fill + no_left <= geo->no_pairs) {
+			merge(head, geo, level,
+					left, no_left,
+					child, fill,
+					parent, i - 1);
+			return;
+		}
+	}
+	if (i + 1 < getfill(geo, parent, i)) {
+		right = bval(geo, parent, i + 1);
+		no_right = getfill(geo, right, 0);
+		if (fill + no_right <= geo->no_pairs) {
+			merge(head, geo, level,
+					child, fill,
+					right, no_right,
+					parent, i);
+			return;
+		}
+	}
+	/*
+	 * We could also try to steal one entry from the left or right
+	 * neighbor.  By not doing so we changed the invariant from
+	 * "all nodes are at least half full" to "no two neighboring
+	 * nodes can be merged".  Which means that the average fill of
+	 * all nodes is still half or better.
+	 */
+}
+
+static void *btree_remove_level(struct btree_head *head, struct btree_geo *geo,
+		unsigned long *key, int level)
+{
+	unsigned long *node;
+	int i, pos, fill;
+	void *ret;
+
+	if (level > head->height) {
+		/* we recursed all the way up */
+		head->height = 0;
+		head->node = NULL;
+		return NULL;
+	}
+
+	node = find_level(head, geo, key, level);
+	pos = getpos(geo, node, key);
+	fill = getfill(geo, node, pos);
+	if ((level == 1) && (keycmp(geo, node, pos, key) != 0))
+		return NULL;
+	ret = bval(geo, node, pos);
+
+	/* remove and shift */
+	for (i = pos; i < fill - 1; i++) {
+		setkey(geo, node, i, bkey(geo, node, i + 1));
+		setval(geo, node, i, bval(geo, node, i + 1));
+	}
+	clearpair(geo, node, fill - 1);
+
+	if (fill - 1 < geo->no_pairs / 2) {
+		if (level < head->height)
+			rebalance(head, geo, key, level, node, fill - 1);
+		else if (fill - 1 == 1)
+			btree_shrink(head, geo);
+	}
+
+	return ret;
+}
+
+void *btree_remove(struct btree_head *head, struct btree_geo *geo,
+		unsigned long *key)
+{
+	if (head->height == 0)
+		return NULL;
+
+	return btree_remove_level(head, geo, key, 1);
+}
+EXPORT_SYMBOL_GPL(btree_remove);
+
+int btree_merge(struct btree_head *target, struct btree_head *victim,
+		struct btree_geo *geo, gfp_t gfp)
+{
+	unsigned long key[geo->keylen];
+	unsigned long dup[geo->keylen];
+	void *val;
+	int err;
+
+	BUG_ON(target == victim);
+
+	if (!(target->node)) {
+		/* target is empty, just copy fields over */
+		target->node = victim->node;
+		target->height = victim->height;
+		__btree_init(victim);
+		return 0;
+	}
+
+	/* TODO: This needs some optimizations.  Currently we do three tree
+	 * walks to remove a single object from the victim.
+	 */
+	for (;;) {
+		if (!btree_last(victim, geo, key))
+			break;
+		val = btree_lookup(victim, geo, key);
+		err = btree_insert(target, geo, key, val, gfp);
+		if (err)
+			return err;
+		/* We must make a copy of the key, as the original will get
+		 * mangled inside btree_remove. */
+		longcpy(dup, key, geo->keylen);
+		btree_remove(victim, geo, dup);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(btree_merge);
+
+static size_t __btree_for_each(struct btree_head *head, struct btree_geo *geo,
+			       unsigned long *node, unsigned long opaque,
+			       void (*func)(void *elem, unsigned long opaque,
+					    unsigned long *key, size_t index,
+					    void *func2),
+			       void *func2, int reap, int height, size_t count)
+{
+	int i;
+	unsigned long *child;
+
+	for (i = 0; i < geo->no_pairs; i++) {
+		child = bval(geo, node, i);
+		if (!child)
+			break;
+		if (height > 1)
+			count = __btree_for_each(head, geo, child, opaque,
+					func, func2, reap, height - 1, count);
+		else
+			func(child, opaque, bkey(geo, node, i), count++,
+					func2);
+	}
+	if (reap)
+		mempool_free(node, head->mempool);
+	return count;
+}
+
+static void empty(void *elem, unsigned long opaque, unsigned long *key,
+		  size_t index, void *func2)
+{
+}
+
+void visitorl(void *elem, unsigned long opaque, unsigned long *key,
+	      size_t index, void *__func)
+{
+	visitorl_t func = __func;
+
+	func(elem, opaque, *key, index);
+}
+EXPORT_SYMBOL_GPL(visitorl);
+
+void visitor32(void *elem, unsigned long opaque, unsigned long *__key,
+	       size_t index, void *__func)
+{
+	visitor32_t func = __func;
+	u32 *key = (void *)__key;
+
+	func(elem, opaque, *key, index);
+}
+EXPORT_SYMBOL_GPL(visitor32);
+
+void visitor64(void *elem, unsigned long opaque, unsigned long *__key,
+	       size_t index, void *__func)
+{
+	visitor64_t func = __func;
+	u64 *key = (void *)__key;
+
+	func(elem, opaque, *key, index);
+}
+EXPORT_SYMBOL_GPL(visitor64);
+
+void visitor128(void *elem, unsigned long opaque, unsigned long *__key,
+		size_t index, void *__func)
+{
+	visitor128_t func = __func;
+	u64 *key = (void *)__key;
+
+	func(elem, opaque, key[0], key[1], index);
+}
+EXPORT_SYMBOL_GPL(visitor128);
+
+size_t btree_visitor(struct btree_head *head, struct btree_geo *geo,
+		     unsigned long opaque,
+		     void (*func)(void *elem, unsigned long opaque,
+		     		  unsigned long *key,
+		     		  size_t index, void *func2),
+		     void *func2)
+{
+	size_t count = 0;
+
+	if (!func2)
+		func = empty;
+	if (head->node)
+		count = __btree_for_each(head, geo, head->node, opaque, func,
+				func2, 0, head->height, 0);
+	return count;
+}
+EXPORT_SYMBOL_GPL(btree_visitor);
+
+size_t btree_grim_visitor(struct btree_head *head, struct btree_geo *geo,
+			  unsigned long opaque,
+			  void (*func)(void *elem, unsigned long opaque,
+				       unsigned long *key,
+				       size_t index, void *func2),
+			  void *func2)
+{
+	size_t count = 0;
+
+	if (!func2)
+		func = empty;
+	if (head->node)
+		count = __btree_for_each(head, geo, head->node, opaque, func,
+				func2, 1, head->height, 0);
+	__btree_init(head);
+	return count;
+}
+EXPORT_SYMBOL_GPL(btree_grim_visitor);
+
+static int __init btree_module_init(void)
+{
+	btree_cachep = kmem_cache_create("btree_node", NODESIZE, 0,
+			SLAB_HWCACHE_ALIGN, NULL);
+	return 0;
+}
+
+static void __exit btree_module_exit(void)
+{
+	kmem_cache_destroy(btree_cachep);
+}
+
+/* If core code starts using btree, initialization should happen even earlier */
+module_init(btree_module_init);
+module_exit(btree_module_exit);
+
+MODULE_AUTHOR("Joern Engel <joern@logfs.org>");
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
diff --git a/lib/crc32.c b/lib/crc32.c
index 02e3b31..0f45fbf 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -30,11 +30,15 @@
 #include <asm/atomic.h>
 #include "crc32defs.h"
 #if CRC_LE_BITS == 8
-#define tole(x) __constant_cpu_to_le32(x)
-#define tobe(x) __constant_cpu_to_be32(x)
+# define tole(x) __constant_cpu_to_le32(x)
 #else
-#define tole(x) (x)
-#define tobe(x) (x)
+# define tole(x) (x)
+#endif
+
+#if CRC_BE_BITS == 8
+# define tobe(x) __constant_cpu_to_be32(x)
+#else
+# define tobe(x) (x)
 #endif
 #include "crc32table.h"
 
@@ -52,20 +56,19 @@
 # else
 #  define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
 # endif
-	const u32 *b = (const u32 *)buf;
+	const u32 *b;
 	size_t    rem_len;
 
 	/* Align it */
-	if (unlikely((long)b & 3 && len)) {
-		u8 *p = (u8 *)b;
+	if (unlikely((long)buf & 3 && len)) {
 		do {
-			DO_CRC(*p++);
-		} while ((--len) && ((long)p)&3);
-		b = (u32 *)p;
+			DO_CRC(*buf++);
+		} while ((--len) && ((long)buf)&3);
 	}
 	rem_len = len & 3;
 	/* load data 32 bits wide, xor data 32 bits wide. */
 	len = len >> 2;
+	b = (const u32 *)buf;
 	for (--b; len; --len) {
 		crc ^= *++b; /* use pre increment for speed */
 		DO_CRC(0);
@@ -82,6 +85,7 @@
 		} while (--len);
 	}
 	return crc;
+#undef DO_CRC
 }
 #endif
 /**
@@ -119,9 +123,6 @@
 	crc = __cpu_to_le32(crc);
 	crc = crc32_body(crc, p, len, tab);
 	return __le32_to_cpu(crc);
-#undef ENDIAN_SHIFT
-#undef DO_CRC
-
 # elif CRC_LE_BITS == 4
 	while (len--) {
 		crc ^= *p++;
@@ -179,9 +180,6 @@
 	crc = __cpu_to_be32(crc);
 	crc = crc32_body(crc, p, len, tab);
 	return __be32_to_cpu(crc);
-#undef ENDIAN_SHIFT
-#undef DO_CRC
-
 # elif CRC_BE_BITS == 4
 	while (len--) {
 		crc ^= *p++ << 24;
diff --git a/lib/kobject.c b/lib/kobject.c
index b512b74..8115eb1 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -700,7 +700,7 @@
 	return ret;
 }
 
-struct sysfs_ops kobj_sysfs_ops = {
+const struct sysfs_ops kobj_sysfs_ops = {
 	.show	= kobj_attr_show,
 	.store	= kobj_attr_store,
 };
@@ -789,7 +789,7 @@
  * If the kset was not able to be created, NULL will be returned.
  */
 static struct kset *kset_create(const char *name,
-				struct kset_uevent_ops *uevent_ops,
+				const struct kset_uevent_ops *uevent_ops,
 				struct kobject *parent_kobj)
 {
 	struct kset *kset;
@@ -832,7 +832,7 @@
  * If the kset was not able to be created, NULL will be returned.
  */
 struct kset *kset_create_and_add(const char *name,
-				 struct kset_uevent_ops *uevent_ops,
+				 const struct kset_uevent_ops *uevent_ops,
 				 struct kobject *parent_kobj)
 {
 	struct kset *kset;
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 920a3ca..c9d3a3e 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -95,7 +95,7 @@
 	const char *subsystem;
 	struct kobject *top_kobj;
 	struct kset *kset;
-	struct kset_uevent_ops *uevent_ops;
+	const struct kset_uevent_ops *uevent_ops;
 	u64 seq;
 	int i = 0;
 	int retval = 0;
diff --git a/lib/list_sort.c b/lib/list_sort.c
index 19d11e0..4b5cb79 100644
--- a/lib/list_sort.c
+++ b/lib/list_sort.c
@@ -4,99 +4,214 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 
+#define MAX_LIST_LENGTH_BITS 20
+
+/*
+ * Returns a list organized in an intermediate format suited
+ * to chaining of merge() calls: null-terminated, no reserved or
+ * sentinel head node, "prev" links not maintained.
+ */
+static struct list_head *merge(void *priv,
+				int (*cmp)(void *priv, struct list_head *a,
+					struct list_head *b),
+				struct list_head *a, struct list_head *b)
+{
+	struct list_head head, *tail = &head;
+
+	while (a && b) {
+		/* if equal, take 'a' -- important for sort stability */
+		if ((*cmp)(priv, a, b) <= 0) {
+			tail->next = a;
+			a = a->next;
+		} else {
+			tail->next = b;
+			b = b->next;
+		}
+		tail = tail->next;
+	}
+	tail->next = a?:b;
+	return head.next;
+}
+
+/*
+ * Combine final list merge with restoration of standard doubly-linked
+ * list structure.  This approach duplicates code from merge(), but
+ * runs faster than the tidier alternatives of either a separate final
+ * prev-link restoration pass, or maintaining the prev links
+ * throughout.
+ */
+static void merge_and_restore_back_links(void *priv,
+				int (*cmp)(void *priv, struct list_head *a,
+					struct list_head *b),
+				struct list_head *head,
+				struct list_head *a, struct list_head *b)
+{
+	struct list_head *tail = head;
+
+	while (a && b) {
+		/* if equal, take 'a' -- important for sort stability */
+		if ((*cmp)(priv, a, b) <= 0) {
+			tail->next = a;
+			a->prev = tail;
+			a = a->next;
+		} else {
+			tail->next = b;
+			b->prev = tail;
+			b = b->next;
+		}
+		tail = tail->next;
+	}
+	tail->next = a ? : b;
+
+	do {
+		/*
+		 * In worst cases this loop may run many iterations.
+		 * Continue callbacks to the client even though no
+		 * element comparison is needed, so the client's cmp()
+		 * routine can invoke cond_resched() periodically.
+		 */
+		(*cmp)(priv, tail, tail);
+
+		tail->next->prev = tail;
+		tail = tail->next;
+	} while (tail->next);
+
+	tail->next = head;
+	head->prev = tail;
+}
+
 /**
- * list_sort - sort a list.
- * @priv: private data, passed to @cmp
+ * list_sort - sort a list
+ * @priv: private data, opaque to list_sort(), passed to @cmp
  * @head: the list to sort
  * @cmp: the elements comparison function
  *
- * This function has been implemented by Mark J Roberts <mjr@znex.org>. It
- * implements "merge sort" which has O(nlog(n)) complexity. The list is sorted
- * in ascending order.
+ * This function implements "merge sort", which has O(nlog(n))
+ * complexity.
  *
- * The comparison function @cmp is supposed to return a negative value if @a is
- * less than @b, and a positive value if @a is greater than @b. If @a and @b
- * are equivalent, then it does not matter what this function returns.
+ * The comparison function @cmp must return a negative value if @a
+ * should sort before @b, and a positive value if @a should sort after
+ * @b. If @a and @b are equivalent, and their original relative
+ * ordering is to be preserved, @cmp must return 0.
  */
 void list_sort(void *priv, struct list_head *head,
-	       int (*cmp)(void *priv, struct list_head *a,
-			  struct list_head *b))
+		int (*cmp)(void *priv, struct list_head *a,
+			struct list_head *b))
 {
-	struct list_head *p, *q, *e, *list, *tail, *oldhead;
-	int insize, nmerges, psize, qsize, i;
+	struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
+						-- last slot is a sentinel */
+	int lev;  /* index into part[] */
+	int max_lev = 0;
+	struct list_head *list;
 
 	if (list_empty(head))
 		return;
 
+	memset(part, 0, sizeof(part));
+
+	head->prev->next = NULL;
 	list = head->next;
-	list_del(head);
-	insize = 1;
-	for (;;) {
-		p = oldhead = list;
-		list = tail = NULL;
-		nmerges = 0;
 
-		while (p) {
-			nmerges++;
-			q = p;
-			psize = 0;
-			for (i = 0; i < insize; i++) {
-				psize++;
-				q = q->next == oldhead ? NULL : q->next;
-				if (!q)
-					break;
-			}
+	while (list) {
+		struct list_head *cur = list;
+		list = list->next;
+		cur->next = NULL;
 
-			qsize = insize;
-			while (psize > 0 || (qsize > 0 && q)) {
-				if (!psize) {
-					e = q;
-					q = q->next;
-					qsize--;
-					if (q == oldhead)
-						q = NULL;
-				} else if (!qsize || !q) {
-					e = p;
-					p = p->next;
-					psize--;
-					if (p == oldhead)
-						p = NULL;
-				} else if (cmp(priv, p, q) <= 0) {
-					e = p;
-					p = p->next;
-					psize--;
-					if (p == oldhead)
-						p = NULL;
-				} else {
-					e = q;
-					q = q->next;
-					qsize--;
-					if (q == oldhead)
-						q = NULL;
-				}
-				if (tail)
-					tail->next = e;
-				else
-					list = e;
-				e->prev = tail;
-				tail = e;
-			}
-			p = q;
+		for (lev = 0; part[lev]; lev++) {
+			cur = merge(priv, cmp, part[lev], cur);
+			part[lev] = NULL;
 		}
-
-		tail->next = list;
-		list->prev = tail;
-
-		if (nmerges <= 1)
-			break;
-
-		insize *= 2;
+		if (lev > max_lev) {
+			if (unlikely(lev >= ARRAY_SIZE(part)-1)) {
+				printk_once(KERN_DEBUG "list passed to"
+					" list_sort() too long for"
+					" efficiency\n");
+				lev--;
+			}
+			max_lev = lev;
+		}
+		part[lev] = cur;
 	}
 
-	head->next = list;
-	head->prev = list->prev;
-	list->prev->next = head;
-	list->prev = head;
+	for (lev = 0; lev < max_lev; lev++)
+		if (part[lev])
+			list = merge(priv, cmp, part[lev], list);
+
+	merge_and_restore_back_links(priv, cmp, head, part[max_lev], list);
+}
+EXPORT_SYMBOL(list_sort);
+
+#ifdef DEBUG_LIST_SORT
+struct debug_el {
+	struct list_head l_h;
+	int value;
+	unsigned serial;
+};
+
+static int cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+	return container_of(a, struct debug_el, l_h)->value
+	     - container_of(b, struct debug_el, l_h)->value;
 }
 
-EXPORT_SYMBOL(list_sort);
+/*
+ * The pattern of set bits in the list length determines which cases
+ * are hit in list_sort().
+ */
+#define LIST_SORT_TEST_LENGTH (512+128+2) /* not including head */
+
+static int __init list_sort_test(void)
+{
+	int i, r = 1, count;
+	struct list_head *head = kmalloc(sizeof(*head), GFP_KERNEL);
+	struct list_head *cur;
+
+	printk(KERN_WARNING "testing list_sort()\n");
+
+	cur = head;
+	for (i = 0; i < LIST_SORT_TEST_LENGTH; i++) {
+		struct debug_el *el = kmalloc(sizeof(*el), GFP_KERNEL);
+		BUG_ON(!el);
+		 /* force some equivalencies */
+		el->value = (r = (r * 725861) % 6599) % (LIST_SORT_TEST_LENGTH/3);
+		el->serial = i;
+
+		el->l_h.prev = cur;
+		cur->next = &el->l_h;
+		cur = cur->next;
+	}
+	head->prev = cur;
+
+	list_sort(NULL, head, cmp);
+
+	count = 1;
+	for (cur = head->next; cur->next != head; cur = cur->next) {
+		struct debug_el *el = container_of(cur, struct debug_el, l_h);
+		int cmp_result = cmp(NULL, cur, cur->next);
+		if (cur->next->prev != cur) {
+			printk(KERN_EMERG "list_sort() returned "
+						"a corrupted list!\n");
+			return 1;
+		} else if (cmp_result > 0) {
+			printk(KERN_EMERG "list_sort() failed to sort!\n");
+			return 1;
+		} else if (cmp_result == 0 &&
+				el->serial >= container_of(cur->next,
+					struct debug_el, l_h)->serial) {
+			printk(KERN_EMERG "list_sort() failed to preserve order"
+						 " of equivalent elements!\n");
+			return 1;
+		}
+		kfree(cur->prev);
+		count++;
+	}
+	kfree(cur);
+	if (count != LIST_SORT_TEST_LENGTH) {
+		printk(KERN_EMERG "list_sort() returned list of"
+						"different length!\n");
+		return 1;
+	}
+	return 0;
+}
+module_init(list_sort_test);
+#endif
diff --git a/lib/show_mem.c b/lib/show_mem.c
index 238e72a..fdc77c8 100644
--- a/lib/show_mem.c
+++ b/lib/show_mem.c
@@ -15,7 +15,7 @@
 	unsigned long total = 0, reserved = 0, shared = 0,
 		nonshared = 0, highmem = 0;
 
-	printk(KERN_INFO "Mem-Info:\n");
+	printk("Mem-Info:\n");
 	show_free_areas();
 
 	for_each_online_pgdat(pgdat) {
@@ -49,15 +49,15 @@
 		pgdat_resize_unlock(pgdat, &flags);
 	}
 
-	printk(KERN_INFO "%lu pages RAM\n", total);
+	printk("%lu pages RAM\n", total);
 #ifdef CONFIG_HIGHMEM
-	printk(KERN_INFO "%lu pages HighMem\n", highmem);
+	printk("%lu pages HighMem\n", highmem);
 #endif
-	printk(KERN_INFO "%lu pages reserved\n", reserved);
-	printk(KERN_INFO "%lu pages shared\n", shared);
-	printk(KERN_INFO "%lu pages non-shared\n", nonshared);
+	printk("%lu pages reserved\n", reserved);
+	printk("%lu pages shared\n", shared);
+	printk("%lu pages non-shared\n", nonshared);
 #ifdef CONFIG_QUICKLIST
-	printk(KERN_INFO "%lu pages in pagetable cache\n",
+	printk("%lu pages in pagetable cache\n",
 		quicklist_total_size());
 #endif
 }
diff --git a/lib/string.c b/lib/string.c
index a1cdcfcc..f71bead 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -36,25 +36,21 @@
 	/* Yes, Virginia, it had better be unsigned */
 	unsigned char c1, c2;
 
-	c1 = c2 = 0;
-	if (len) {
-		do {
-			c1 = *s1;
-			c2 = *s2;
-			s1++;
-			s2++;
-			if (!c1)
-				break;
-			if (!c2)
-				break;
-			if (c1 == c2)
-				continue;
-			c1 = tolower(c1);
-			c2 = tolower(c2);
-			if (c1 != c2)
-				break;
-		} while (--len);
-	}
+	if (!len)
+		return 0;
+
+	do {
+		c1 = *s1++;
+		c2 = *s2++;
+		if (!c1 || !c2)
+			break;
+		if (c1 == c2)
+			continue;
+		c1 = tolower(c1);
+		c2 = tolower(c2);
+		if (c1 != c2)
+			break;
+	} while (--len);
 	return (int)c1 - (int)c2;
 }
 EXPORT_SYMBOL(strnicmp);
@@ -693,13 +689,13 @@
  */
 char *strnstr(const char *s1, const char *s2, size_t len)
 {
-	size_t l1 = len, l2;
+	size_t l2;
 
 	l2 = strlen(s2);
 	if (!l2)
 		return (char *)s1;
-	while (l1 >= l2) {
-		l1--;
+	while (len >= l2) {
+		len--;
 		if (!memcmp(s1, s2, l2))
 			return (char *)s1;
 		s1++;
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index af4aaa6..0d461c7 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -381,8 +381,8 @@
 #define PLUS	4		/* show plus */
 #define SPACE	8		/* space if plus */
 #define LEFT	16		/* left justified */
-#define SMALL	32		/* Must be 32 == 0x20 */
-#define SPECIAL	64		/* 0x */
+#define SMALL	32		/* use lowercase in hex (must be 32 == 0x20) */
+#define SPECIAL	64		/* prefix hex with "0x", octal with "0" */
 
 enum format_type {
 	FORMAT_TYPE_NONE, /* Just a string part */
@@ -408,12 +408,12 @@
 };
 
 struct printf_spec {
-	enum format_type	type;
-	int			flags;		/* flags to number() */
-	int			field_width;	/* width of output field */
-	int			base;
-	int			precision;	/* # of digits/chars */
-	int			qualifier;
+	u16	type;
+	s16	field_width;	/* width of output field */
+	u8	flags;		/* flags to number() */
+	u8	base;
+	s8	precision;	/* # of digits/chars */
+	u8	qualifier;
 };
 
 static char *number(char *buf, char *end, unsigned long long num,
@@ -597,22 +597,29 @@
 #ifndef MEM_RSRC_PRINTK_SIZE
 #define MEM_RSRC_PRINTK_SIZE	10
 #endif
-	struct printf_spec hex_spec = {
+	static const struct printf_spec io_spec = {
 		.base = 16,
+		.field_width = IO_RSRC_PRINTK_SIZE,
 		.precision = -1,
 		.flags = SPECIAL | SMALL | ZEROPAD,
 	};
-	struct printf_spec dec_spec = {
+	static const struct printf_spec mem_spec = {
+		.base = 16,
+		.field_width = MEM_RSRC_PRINTK_SIZE,
+		.precision = -1,
+		.flags = SPECIAL | SMALL | ZEROPAD,
+	};
+	static const struct printf_spec dec_spec = {
 		.base = 10,
 		.precision = -1,
 		.flags = 0,
 	};
-	struct printf_spec str_spec = {
+	static const struct printf_spec str_spec = {
 		.field_width = -1,
 		.precision = 10,
 		.flags = LEFT,
 	};
-	struct printf_spec flag_spec = {
+	static const struct printf_spec flag_spec = {
 		.base = 16,
 		.precision = -1,
 		.flags = SPECIAL | SMALL,
@@ -628,35 +635,31 @@
 		     2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
 
 	char *p = sym, *pend = sym + sizeof(sym);
-	int size = -1, addr = 0;
 	int decode = (fmt[0] == 'R') ? 1 : 0;
-
-	if (res->flags & IORESOURCE_IO) {
-		size = IO_RSRC_PRINTK_SIZE;
-		addr = 1;
-	} else if (res->flags & IORESOURCE_MEM) {
-		size = MEM_RSRC_PRINTK_SIZE;
-		addr = 1;
-	}
+	const struct printf_spec *specp;
 
 	*p++ = '[';
-	if (res->flags & IORESOURCE_IO)
+	if (res->flags & IORESOURCE_IO) {
 		p = string(p, pend, "io  ", str_spec);
-	else if (res->flags & IORESOURCE_MEM)
+		specp = &io_spec;
+	} else if (res->flags & IORESOURCE_MEM) {
 		p = string(p, pend, "mem ", str_spec);
-	else if (res->flags & IORESOURCE_IRQ)
+		specp = &mem_spec;
+	} else if (res->flags & IORESOURCE_IRQ) {
 		p = string(p, pend, "irq ", str_spec);
-	else if (res->flags & IORESOURCE_DMA)
+		specp = &dec_spec;
+	} else if (res->flags & IORESOURCE_DMA) {
 		p = string(p, pend, "dma ", str_spec);
-	else {
+		specp = &dec_spec;
+	} else {
 		p = string(p, pend, "??? ", str_spec);
+		specp = &mem_spec;
 		decode = 0;
 	}
-	hex_spec.field_width = size;
-	p = number(p, pend, res->start, addr ? hex_spec : dec_spec);
+	p = number(p, pend, res->start, *specp);
 	if (res->start != res->end) {
 		*p++ = '-';
-		p = number(p, pend, res->end, addr ? hex_spec : dec_spec);
+		p = number(p, pend, res->end, *specp);
 	}
 	if (decode) {
 		if (res->flags & IORESOURCE_MEM_64)
@@ -1333,7 +1336,7 @@
 			break;
 
 		case FORMAT_TYPE_NRCHARS: {
-			int qualifier = spec.qualifier;
+			u8 qualifier = spec.qualifier;
 
 			if (qualifier == 'l') {
 				long *ip = va_arg(args, long *);
@@ -1619,7 +1622,7 @@
 
 		case FORMAT_TYPE_NRCHARS: {
 			/* skip %n 's argument */
-			int qualifier = spec.qualifier;
+			u8 qualifier = spec.qualifier;
 			void *skip_arg;
 			if (qualifier == 'l')
 				skip_arg = va_arg(args, long *);
@@ -1885,7 +1888,9 @@
 	char *next;
 	char digit;
 	int num = 0;
-	int qualifier, base, field_width;
+	u8 qualifier;
+	u8 base;
+	s16 field_width;
 	bool is_sign;
 
 	while (*fmt && *str) {
@@ -1963,7 +1968,7 @@
 		{
 			char *s = (char *)va_arg(args, char *);
 			if (field_width == -1)
-				field_width = INT_MAX;
+				field_width = SHORT_MAX;
 			/* first, skip leading white space in buffer */
 			str = skip_spaces(str);
 
diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c
index 215447c..2c13ecc 100644
--- a/lib/zlib_inflate/inffast.c
+++ b/lib/zlib_inflate/inffast.c
@@ -8,21 +8,6 @@
 #include "inflate.h"
 #include "inffast.h"
 
-/* Only do the unaligned "Faster" variant when
- * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is set
- *
- * On powerpc, it won't be as we don't include autoconf.h
- * automatically for the boot wrapper, which is intended as
- * we run in an environment where we may not be able to deal
- * with (even rare) alignment faults. In addition, we do not
- * define __KERNEL__ for arch/powerpc/boot unlike x86
- */
-
-#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
-#endif
-
 #ifndef ASMINF
 
 /* Allow machine dependent optimization for post-increment or pre-increment.
@@ -36,14 +21,31 @@
    - Pentium III (Anderson)
    - M68060 (Nikl)
  */
+union uu {
+	unsigned short us;
+	unsigned char b[2];
+};
+
+/* Endian independed version */
+static inline unsigned short
+get_unaligned16(const unsigned short *p)
+{
+	union uu  mm;
+	unsigned char *b = (unsigned char *)p;
+
+	mm.b[0] = b[0];
+	mm.b[1] = b[1];
+	return mm.us;
+}
+
 #ifdef POSTINC
 #  define OFF 0
 #  define PUP(a) *(a)++
-#  define UP_UNALIGNED(a) get_unaligned((a)++)
+#  define UP_UNALIGNED(a) get_unaligned16((a)++)
 #else
 #  define OFF 1
 #  define PUP(a) *++(a)
-#  define UP_UNALIGNED(a) get_unaligned(++(a))
+#  define UP_UNALIGNED(a) get_unaligned16(++(a))
 #endif
 
 /*
@@ -256,7 +258,6 @@
                     }
                 }
                 else {
-#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 		    unsigned short *sout;
 		    unsigned long loops;
 
@@ -274,22 +275,25 @@
 			sfrom = (unsigned short *)(from - OFF);
 			loops = len >> 1;
 			do
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+			    PUP(sout) = PUP(sfrom);
+#else
 			    PUP(sout) = UP_UNALIGNED(sfrom);
+#endif
 			while (--loops);
 			out = (unsigned char *)sout + OFF;
 			from = (unsigned char *)sfrom + OFF;
 		    } else { /* dist == 1 or dist == 2 */
 			unsigned short pat16;
 
-			pat16 = *(sout-2+2*OFF);
-			if (dist == 1)
-#if defined(__BIG_ENDIAN)
-			    pat16 = (pat16 & 0xff) | ((pat16 & 0xff) << 8);
-#elif defined(__LITTLE_ENDIAN)
-			    pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00) >> 8);
-#else
-#error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined
-#endif
+			pat16 = *(sout-1+OFF);
+			if (dist == 1) {
+				union uu mm;
+				/* copy one char pattern to both bytes */
+				mm.us = pat16;
+				mm.b[0] = mm.b[1];
+				pat16 = mm.us;
+			}
 			loops = len >> 1;
 			do
 			    PUP(sout) = pat16;
@@ -298,20 +302,6 @@
 		    }
 		    if (len & 1)
 			PUP(out) = PUP(from);
-#else /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
-                    from = out - dist;          /* copy direct from output */
-                    do {                        /* minimum length is three */
-			 PUP(out) = PUP(from);
-			 PUP(out) = PUP(from);
-			 PUP(out) = PUP(from);
-			 len -= 3;
-                    } while (len > 2);
-                    if (len) {
-			 PUP(out) = PUP(from);
-			 if (len > 1)
-			     PUP(out) = PUP(from);
-                    }
-#endif /* !CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */
                 }
             }
             else if ((op & 64) == 0) {          /* 2nd level distance code */
diff --git a/mm/Kconfig b/mm/Kconfig
index d34c2b9..9c61158 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -115,6 +115,10 @@
 config SPARSEMEM_VMEMMAP_ENABLE
 	bool
 
+config SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
+	def_bool y
+	depends on SPARSEMEM && X86_64
+
 config SPARSEMEM_VMEMMAP
 	bool "Sparse Memory virtual memmap"
 	depends on SPARSEMEM && SPARSEMEM_VMEMMAP_ENABLE
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 7d14868..d7c791e 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -13,6 +13,7 @@
 #include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/kmemleak.h>
+#include <linux/range.h>
 
 #include <asm/bug.h>
 #include <asm/io.h>
@@ -32,6 +33,7 @@
 unsigned long saved_max_pfn;
 #endif
 
+#ifndef CONFIG_NO_BOOTMEM
 bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata;
 
 static struct list_head bdata_list __initdata = LIST_HEAD_INIT(bdata_list);
@@ -142,7 +144,7 @@
 	min_low_pfn = start;
 	return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages);
 }
-
+#endif
 /*
  * free_bootmem_late - free bootmem pages directly to page allocator
  * @addr: starting address of the range
@@ -167,6 +169,60 @@
 	}
 }
 
+#ifdef CONFIG_NO_BOOTMEM
+static void __init __free_pages_memory(unsigned long start, unsigned long end)
+{
+	int i;
+	unsigned long start_aligned, end_aligned;
+	int order = ilog2(BITS_PER_LONG);
+
+	start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1);
+	end_aligned = end & ~(BITS_PER_LONG - 1);
+
+	if (end_aligned <= start_aligned) {
+#if 1
+		printk(KERN_DEBUG " %lx - %lx\n", start, end);
+#endif
+		for (i = start; i < end; i++)
+			__free_pages_bootmem(pfn_to_page(i), 0);
+
+		return;
+	}
+
+#if 1
+	printk(KERN_DEBUG " %lx %lx - %lx %lx\n",
+		 start, start_aligned, end_aligned, end);
+#endif
+	for (i = start; i < start_aligned; i++)
+		__free_pages_bootmem(pfn_to_page(i), 0);
+
+	for (i = start_aligned; i < end_aligned; i += BITS_PER_LONG)
+		__free_pages_bootmem(pfn_to_page(i), order);
+
+	for (i = end_aligned; i < end; i++)
+		__free_pages_bootmem(pfn_to_page(i), 0);
+}
+
+unsigned long __init free_all_memory_core_early(int nodeid)
+{
+	int i;
+	u64 start, end;
+	unsigned long count = 0;
+	struct range *range = NULL;
+	int nr_range;
+
+	nr_range = get_free_all_memory_range(&range, nodeid);
+
+	for (i = 0; i < nr_range; i++) {
+		start = range[i].start;
+		end = range[i].end;
+		count += end - start;
+		__free_pages_memory(start, end);
+	}
+
+	return count;
+}
+#else
 static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 {
 	int aligned;
@@ -227,6 +283,7 @@
 
 	return count;
 }
+#endif
 
 /**
  * free_all_bootmem_node - release a node's free pages to the buddy allocator
@@ -237,7 +294,12 @@
 unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
 {
 	register_page_bootmem_info_node(pgdat);
+#ifdef CONFIG_NO_BOOTMEM
+	/* free_all_memory_core_early(MAX_NUMNODES) will be called later */
+	return 0;
+#else
 	return free_all_bootmem_core(pgdat->bdata);
+#endif
 }
 
 /**
@@ -247,9 +309,14 @@
  */
 unsigned long __init free_all_bootmem(void)
 {
+#ifdef CONFIG_NO_BOOTMEM
+	return free_all_memory_core_early(NODE_DATA(0)->node_id);
+#else
 	return free_all_bootmem_core(NODE_DATA(0)->bdata);
+#endif
 }
 
+#ifndef CONFIG_NO_BOOTMEM
 static void __init __free(bootmem_data_t *bdata,
 			unsigned long sidx, unsigned long eidx)
 {
@@ -344,6 +411,7 @@
 	}
 	BUG();
 }
+#endif
 
 /**
  * free_bootmem_node - mark a page range as usable
@@ -358,6 +426,12 @@
 void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 			      unsigned long size)
 {
+#ifdef CONFIG_NO_BOOTMEM
+	free_early(physaddr, physaddr + size);
+#if 0
+	printk(KERN_DEBUG "free %lx %lx\n", physaddr, size);
+#endif
+#else
 	unsigned long start, end;
 
 	kmemleak_free_part(__va(physaddr), size);
@@ -366,6 +440,7 @@
 	end = PFN_DOWN(physaddr + size);
 
 	mark_bootmem_node(pgdat->bdata, start, end, 0, 0);
+#endif
 }
 
 /**
@@ -379,6 +454,12 @@
  */
 void __init free_bootmem(unsigned long addr, unsigned long size)
 {
+#ifdef CONFIG_NO_BOOTMEM
+	free_early(addr, addr + size);
+#if 0
+	printk(KERN_DEBUG "free %lx %lx\n", addr, size);
+#endif
+#else
 	unsigned long start, end;
 
 	kmemleak_free_part(__va(addr), size);
@@ -387,6 +468,7 @@
 	end = PFN_DOWN(addr + size);
 
 	mark_bootmem(start, end, 0, 0);
+#endif
 }
 
 /**
@@ -403,12 +485,17 @@
 int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 				 unsigned long size, int flags)
 {
+#ifdef CONFIG_NO_BOOTMEM
+	panic("no bootmem");
+	return 0;
+#else
 	unsigned long start, end;
 
 	start = PFN_DOWN(physaddr);
 	end = PFN_UP(physaddr + size);
 
 	return mark_bootmem_node(pgdat->bdata, start, end, 1, flags);
+#endif
 }
 
 /**
@@ -424,14 +511,20 @@
 int __init reserve_bootmem(unsigned long addr, unsigned long size,
 			    int flags)
 {
+#ifdef CONFIG_NO_BOOTMEM
+	panic("no bootmem");
+	return 0;
+#else
 	unsigned long start, end;
 
 	start = PFN_DOWN(addr);
 	end = PFN_UP(addr + size);
 
 	return mark_bootmem(start, end, 1, flags);
+#endif
 }
 
+#ifndef CONFIG_NO_BOOTMEM
 static unsigned long __init align_idx(struct bootmem_data *bdata,
 				      unsigned long idx, unsigned long step)
 {
@@ -582,12 +675,33 @@
 #endif
 	return NULL;
 }
+#endif
 
 static void * __init ___alloc_bootmem_nopanic(unsigned long size,
 					unsigned long align,
 					unsigned long goal,
 					unsigned long limit)
 {
+#ifdef CONFIG_NO_BOOTMEM
+	void *ptr;
+
+	if (WARN_ON_ONCE(slab_is_available()))
+		return kzalloc(size, GFP_NOWAIT);
+
+restart:
+
+	ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, goal, limit);
+
+	if (ptr)
+		return ptr;
+
+	if (goal != 0) {
+		goal = 0;
+		goto restart;
+	}
+
+	return NULL;
+#else
 	bootmem_data_t *bdata;
 	void *region;
 
@@ -613,6 +727,7 @@
 	}
 
 	return NULL;
+#endif
 }
 
 /**
@@ -631,7 +746,13 @@
 void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
 					unsigned long goal)
 {
-	return ___alloc_bootmem_nopanic(size, align, goal, 0);
+	unsigned long limit = 0;
+
+#ifdef CONFIG_NO_BOOTMEM
+	limit = -1UL;
+#endif
+
+	return ___alloc_bootmem_nopanic(size, align, goal, limit);
 }
 
 static void * __init ___alloc_bootmem(unsigned long size, unsigned long align,
@@ -665,9 +786,16 @@
 void * __init __alloc_bootmem(unsigned long size, unsigned long align,
 			      unsigned long goal)
 {
-	return ___alloc_bootmem(size, align, goal, 0);
+	unsigned long limit = 0;
+
+#ifdef CONFIG_NO_BOOTMEM
+	limit = -1UL;
+#endif
+
+	return ___alloc_bootmem(size, align, goal, limit);
 }
 
+#ifndef CONFIG_NO_BOOTMEM
 static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata,
 				unsigned long size, unsigned long align,
 				unsigned long goal, unsigned long limit)
@@ -684,6 +812,7 @@
 
 	return ___alloc_bootmem(size, align, goal, limit);
 }
+#endif
 
 /**
  * __alloc_bootmem_node - allocate boot memory from a specific node
@@ -706,7 +835,46 @@
 	if (WARN_ON_ONCE(slab_is_available()))
 		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
 
+#ifdef CONFIG_NO_BOOTMEM
+	return __alloc_memory_core_early(pgdat->node_id, size, align,
+					 goal, -1ULL);
+#else
 	return ___alloc_bootmem_node(pgdat->bdata, size, align, goal, 0);
+#endif
+}
+
+void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
+				   unsigned long align, unsigned long goal)
+{
+#ifdef MAX_DMA32_PFN
+	unsigned long end_pfn;
+
+	if (WARN_ON_ONCE(slab_is_available()))
+		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
+
+	/* update goal according ...MAX_DMA32_PFN */
+	end_pfn = pgdat->node_start_pfn + pgdat->node_spanned_pages;
+
+	if (end_pfn > MAX_DMA32_PFN + (128 >> (20 - PAGE_SHIFT)) &&
+	    (goal >> PAGE_SHIFT) < MAX_DMA32_PFN) {
+		void *ptr;
+		unsigned long new_goal;
+
+		new_goal = MAX_DMA32_PFN << PAGE_SHIFT;
+#ifdef CONFIG_NO_BOOTMEM
+		ptr =  __alloc_memory_core_early(pgdat->node_id, size, align,
+						 new_goal, -1ULL);
+#else
+		ptr = alloc_bootmem_core(pgdat->bdata, size, align,
+						 new_goal, 0);
+#endif
+		if (ptr)
+			return ptr;
+	}
+#endif
+
+	return __alloc_bootmem_node(pgdat, size, align, goal);
+
 }
 
 #ifdef CONFIG_SPARSEMEM
@@ -720,6 +888,16 @@
 void * __init alloc_bootmem_section(unsigned long size,
 				    unsigned long section_nr)
 {
+#ifdef CONFIG_NO_BOOTMEM
+	unsigned long pfn, goal, limit;
+
+	pfn = section_nr_to_pfn(section_nr);
+	goal = pfn << PAGE_SHIFT;
+	limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
+
+	return __alloc_memory_core_early(early_pfn_to_nid(pfn), size,
+					 SMP_CACHE_BYTES, goal, limit);
+#else
 	bootmem_data_t *bdata;
 	unsigned long pfn, goal, limit;
 
@@ -729,6 +907,7 @@
 	bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];
 
 	return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit);
+#endif
 }
 #endif
 
@@ -740,11 +919,16 @@
 	if (WARN_ON_ONCE(slab_is_available()))
 		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
 
+#ifdef CONFIG_NO_BOOTMEM
+	ptr =  __alloc_memory_core_early(pgdat->node_id, size, align,
+						 goal, -1ULL);
+#else
 	ptr = alloc_arch_preferred_bootmem(pgdat->bdata, size, align, goal, 0);
 	if (ptr)
 		return ptr;
 
 	ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0);
+#endif
 	if (ptr)
 		return ptr;
 
@@ -795,6 +979,11 @@
 	if (WARN_ON_ONCE(slab_is_available()))
 		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
 
+#ifdef CONFIG_NO_BOOTMEM
+	return __alloc_memory_core_early(pgdat->node_id, size, align,
+				goal, ARCH_LOW_ADDRESS_LIMIT);
+#else
 	return ___alloc_bootmem_node(pgdat->bdata, size, align,
 				goal, ARCH_LOW_ADDRESS_LIMIT);
+#endif
 }
diff --git a/mm/fadvise.c b/mm/fadvise.c
index e433592..8d723c9 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -77,12 +77,20 @@
 	switch (advice) {
 	case POSIX_FADV_NORMAL:
 		file->f_ra.ra_pages = bdi->ra_pages;
+		spin_lock(&file->f_lock);
+		file->f_mode &= ~FMODE_RANDOM;
+		spin_unlock(&file->f_lock);
 		break;
 	case POSIX_FADV_RANDOM:
-		file->f_ra.ra_pages = 0;
+		spin_lock(&file->f_lock);
+		file->f_mode |= FMODE_RANDOM;
+		spin_unlock(&file->f_lock);
 		break;
 	case POSIX_FADV_SEQUENTIAL:
 		file->f_ra.ra_pages = bdi->ra_pages * 2;
+		spin_lock(&file->f_lock);
+		file->f_mode &= ~FMODE_RANDOM;
+		spin_unlock(&file->f_lock);
 		break;
 	case POSIX_FADV_WILLNEED:
 		if (!mapping->a_ops->readpage) {
diff --git a/mm/failslab.c b/mm/failslab.c
index 9339de5..bb41f98 100644
--- a/mm/failslab.c
+++ b/mm/failslab.c
@@ -1,18 +1,22 @@
 #include <linux/fault-inject.h>
 #include <linux/gfp.h>
+#include <linux/slab.h>
 
 static struct {
 	struct fault_attr attr;
 	u32 ignore_gfp_wait;
+	int cache_filter;
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
 	struct dentry *ignore_gfp_wait_file;
+	struct dentry *cache_filter_file;
 #endif
 } failslab = {
 	.attr = FAULT_ATTR_INITIALIZER,
 	.ignore_gfp_wait = 1,
+	.cache_filter = 0,
 };
 
-bool should_failslab(size_t size, gfp_t gfpflags)
+bool should_failslab(size_t size, gfp_t gfpflags, unsigned long cache_flags)
 {
 	if (gfpflags & __GFP_NOFAIL)
 		return false;
@@ -20,6 +24,9 @@
         if (failslab.ignore_gfp_wait && (gfpflags & __GFP_WAIT))
 		return false;
 
+	if (failslab.cache_filter && !(cache_flags & SLAB_FAILSLAB))
+		return false;
+
 	return should_fail(&failslab.attr, size);
 }
 
@@ -30,7 +37,6 @@
 __setup("failslab=", setup_failslab);
 
 #ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
-
 static int __init failslab_debugfs_init(void)
 {
 	mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
@@ -46,8 +52,14 @@
 		debugfs_create_bool("ignore-gfp-wait", mode, dir,
 				      &failslab.ignore_gfp_wait);
 
-	if (!failslab.ignore_gfp_wait_file) {
+	failslab.cache_filter_file =
+		debugfs_create_bool("cache-filter", mode, dir,
+				      &failslab.cache_filter);
+
+	if (!failslab.ignore_gfp_wait_file ||
+	    !failslab.cache_filter_file) {
 		err = -ENOMEM;
+		debugfs_remove(failslab.cache_filter_file);
 		debugfs_remove(failslab.ignore_gfp_wait_file);
 		cleanup_fault_attr_dentries(&failslab.attr);
 	}
diff --git a/mm/filemap.c b/mm/filemap.c
index 698ea80..045b31c 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1117,7 +1117,7 @@
 			if (!PageUptodate(page)) {
 				if (page->mapping == NULL) {
 					/*
-					 * invalidate_inode_pages got it
+					 * invalidate_mapping_pages got it
 					 */
 					unlock_page(page);
 					page_cache_release(page);
@@ -1986,7 +1986,7 @@
 inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk)
 {
 	struct inode *inode = file->f_mapping->host;
-	unsigned long limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+	unsigned long limit = rlimit(RLIMIT_FSIZE);
 
         if (unlikely(*pos < 0))
                 return -EINVAL;
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index 1888b2d..78b94f0 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -194,7 +194,7 @@
 			flush_cache_page(vma, address, pte_pfn(*pte));
 			pteval = ptep_clear_flush_notify(vma, address, pte);
 			page_remove_rmap(page);
-			dec_mm_counter(mm, file_rss);
+			dec_mm_counter(mm, MM_FILEPAGES);
 			BUG_ON(pte_dirty(pteval));
 			pte_unmap_unlock(pte, ptl);
 			page_cache_release(page);
diff --git a/mm/fremap.c b/mm/fremap.c
index b6ec85a..46f5dac 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -40,7 +40,7 @@
 			page_remove_rmap(page);
 			page_cache_release(page);
 			update_hiwater_rss(mm);
-			dec_mm_counter(mm, file_rss);
+			dec_mm_counter(mm, MM_FILEPAGES);
 		}
 	} else {
 		if (!pte_file(pte))
diff --git a/mm/highmem.c b/mm/highmem.c
index 9c1e627..bed8a8b 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -220,7 +220,7 @@
  * @page: &struct page to pin
  *
  * Returns the page's current virtual memory address, or NULL if no mapping
- * exists.  When and only when a non null address is returned then a
+ * exists.  If and only if a non null address is returned then a
  * matching call to kunmap_high() is necessary.
  *
  * This can be called from any context.
diff --git a/mm/ksm.c b/mm/ksm.c
index 56a0da1..a93f1b7 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1563,10 +1563,12 @@
 again:
 	hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) {
 		struct anon_vma *anon_vma = rmap_item->anon_vma;
+		struct anon_vma_chain *vmac;
 		struct vm_area_struct *vma;
 
 		spin_lock(&anon_vma->lock);
-		list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+		list_for_each_entry(vmac, &anon_vma->head, same_anon_vma) {
+			vma = vmac->vma;
 			if (rmap_item->address < vma->vm_start ||
 			    rmap_item->address >= vma->vm_end)
 				continue;
@@ -1614,10 +1616,12 @@
 again:
 	hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) {
 		struct anon_vma *anon_vma = rmap_item->anon_vma;
+		struct anon_vma_chain *vmac;
 		struct vm_area_struct *vma;
 
 		spin_lock(&anon_vma->lock);
-		list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+		list_for_each_entry(vmac, &anon_vma->head, same_anon_vma) {
+			vma = vmac->vma;
 			if (rmap_item->address < vma->vm_start ||
 			    rmap_item->address >= vma->vm_end)
 				continue;
@@ -1664,10 +1668,12 @@
 again:
 	hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) {
 		struct anon_vma *anon_vma = rmap_item->anon_vma;
+		struct anon_vma_chain *vmac;
 		struct vm_area_struct *vma;
 
 		spin_lock(&anon_vma->lock);
-		list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+		list_for_each_entry(vmac, &anon_vma->head, same_anon_vma) {
+			vma = vmac->vma;
 			if (rmap_item->address < vma->vm_start ||
 			    rmap_item->address >= vma->vm_end)
 				continue;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 954032b..7973b52 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -6,6 +6,10 @@
  * Copyright 2007 OpenVZ SWsoft Inc
  * Author: Pavel Emelianov <xemul@openvz.org>
  *
+ * Memory thresholds
+ * Copyright (C) 2009 Nokia Corporation
+ * Author: Kirill A. Shutemov
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -21,6 +25,7 @@
 #include <linux/memcontrol.h>
 #include <linux/cgroup.h>
 #include <linux/mm.h>
+#include <linux/hugetlb.h>
 #include <linux/pagemap.h>
 #include <linux/smp.h>
 #include <linux/page-flags.h>
@@ -32,7 +37,10 @@
 #include <linux/rbtree.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
+#include <linux/swapops.h>
 #include <linux/spinlock.h>
+#include <linux/eventfd.h>
+#include <linux/sort.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/vmalloc.h>
@@ -55,7 +63,15 @@
 #define do_swap_account		(0)
 #endif
 
-#define SOFTLIMIT_EVENTS_THRESH (1000)
+/*
+ * Per memcg event counter is incremented at every pagein/pageout. This counter
+ * is used for trigger some periodic events. This is straightforward and better
+ * than using jiffies etc. to handle periodic memcg event.
+ *
+ * These values will be used as !((event) & ((1 <<(thresh)) - 1))
+ */
+#define THRESHOLDS_EVENTS_THRESH (7) /* once in 128 */
+#define SOFTLIMIT_EVENTS_THRESH (10) /* once in 1024 */
 
 /*
  * Statistics for memory cgroup.
@@ -69,62 +85,16 @@
 	MEM_CGROUP_STAT_FILE_MAPPED,  /* # of pages charged as file rss */
 	MEM_CGROUP_STAT_PGPGIN_COUNT,	/* # of pages paged in */
 	MEM_CGROUP_STAT_PGPGOUT_COUNT,	/* # of pages paged out */
-	MEM_CGROUP_STAT_EVENTS,	/* sum of pagein + pageout for internal use */
 	MEM_CGROUP_STAT_SWAPOUT, /* # of pages, swapped out */
+	MEM_CGROUP_EVENTS,	/* incremented at every  pagein/pageout */
 
 	MEM_CGROUP_STAT_NSTATS,
 };
 
 struct mem_cgroup_stat_cpu {
 	s64 count[MEM_CGROUP_STAT_NSTATS];
-} ____cacheline_aligned_in_smp;
-
-struct mem_cgroup_stat {
-	struct mem_cgroup_stat_cpu cpustat[0];
 };
 
-static inline void
-__mem_cgroup_stat_reset_safe(struct mem_cgroup_stat_cpu *stat,
-				enum mem_cgroup_stat_index idx)
-{
-	stat->count[idx] = 0;
-}
-
-static inline s64
-__mem_cgroup_stat_read_local(struct mem_cgroup_stat_cpu *stat,
-				enum mem_cgroup_stat_index idx)
-{
-	return stat->count[idx];
-}
-
-/*
- * For accounting under irq disable, no need for increment preempt count.
- */
-static inline void __mem_cgroup_stat_add_safe(struct mem_cgroup_stat_cpu *stat,
-		enum mem_cgroup_stat_index idx, int val)
-{
-	stat->count[idx] += val;
-}
-
-static s64 mem_cgroup_read_stat(struct mem_cgroup_stat *stat,
-		enum mem_cgroup_stat_index idx)
-{
-	int cpu;
-	s64 ret = 0;
-	for_each_possible_cpu(cpu)
-		ret += stat->cpustat[cpu].count[idx];
-	return ret;
-}
-
-static s64 mem_cgroup_local_usage(struct mem_cgroup_stat *stat)
-{
-	s64 ret;
-
-	ret = mem_cgroup_read_stat(stat, MEM_CGROUP_STAT_CACHE);
-	ret += mem_cgroup_read_stat(stat, MEM_CGROUP_STAT_RSS);
-	return ret;
-}
-
 /*
  * per-zone information in memory controller.
  */
@@ -174,6 +144,22 @@
 
 static struct mem_cgroup_tree soft_limit_tree __read_mostly;
 
+struct mem_cgroup_threshold {
+	struct eventfd_ctx *eventfd;
+	u64 threshold;
+};
+
+struct mem_cgroup_threshold_ary {
+	/* An array index points to threshold just below usage. */
+	atomic_t current_threshold;
+	/* Size of entries[] */
+	unsigned int size;
+	/* Array of thresholds */
+	struct mem_cgroup_threshold entries[0];
+};
+
+static void mem_cgroup_threshold(struct mem_cgroup *mem);
+
 /*
  * The memory controller data structure. The memory controller controls both
  * page cache and RSS per cgroup. We would eventually like to provide
@@ -217,7 +203,7 @@
 	 * Should the accounting and control be hierarchical, per subtree?
 	 */
 	bool use_hierarchy;
-	unsigned long	last_oom_jiffies;
+	atomic_t	oom_lock;
 	atomic_t	refcnt;
 
 	unsigned int	swappiness;
@@ -225,10 +211,48 @@
 	/* set when res.limit == memsw.limit */
 	bool		memsw_is_minimum;
 
+	/* protect arrays of thresholds */
+	struct mutex thresholds_lock;
+
+	/* thresholds for memory usage. RCU-protected */
+	struct mem_cgroup_threshold_ary *thresholds;
+
+	/* thresholds for mem+swap usage. RCU-protected */
+	struct mem_cgroup_threshold_ary *memsw_thresholds;
+
 	/*
-	 * statistics. This must be placed at the end of memcg.
+	 * Should we move charges of a task when a task is moved into this
+	 * mem_cgroup ? And what type of charges should we move ?
 	 */
-	struct mem_cgroup_stat stat;
+	unsigned long 	move_charge_at_immigrate;
+
+	/*
+	 * percpu counter.
+	 */
+	struct mem_cgroup_stat_cpu *stat;
+};
+
+/* Stuffs for move charges at task migration. */
+/*
+ * Types of charges to be moved. "move_charge_at_immitgrate" is treated as a
+ * left-shifted bitmap of these types.
+ */
+enum move_type {
+	MOVE_CHARGE_TYPE_ANON,	/* private anonymous page and swap of it */
+	NR_MOVE_TYPE,
+};
+
+/* "mc" and its members are protected by cgroup_mutex */
+static struct move_charge_struct {
+	struct mem_cgroup *from;
+	struct mem_cgroup *to;
+	unsigned long precharge;
+	unsigned long moved_charge;
+	unsigned long moved_swap;
+	struct task_struct *moving_task;	/* a task moving charges */
+	wait_queue_head_t waitq;		/* a waitq for other context */
+} mc = {
+	.waitq = __WAIT_QUEUE_HEAD_INITIALIZER(mc.waitq),
 };
 
 /*
@@ -371,23 +395,6 @@
 	spin_unlock(&mctz->lock);
 }
 
-static bool mem_cgroup_soft_limit_check(struct mem_cgroup *mem)
-{
-	bool ret = false;
-	int cpu;
-	s64 val;
-	struct mem_cgroup_stat_cpu *cpustat;
-
-	cpu = get_cpu();
-	cpustat = &mem->stat.cpustat[cpu];
-	val = __mem_cgroup_stat_read_local(cpustat, MEM_CGROUP_STAT_EVENTS);
-	if (unlikely(val > SOFTLIMIT_EVENTS_THRESH)) {
-		__mem_cgroup_stat_reset_safe(cpustat, MEM_CGROUP_STAT_EVENTS);
-		ret = true;
-	}
-	put_cpu();
-	return ret;
-}
 
 static void mem_cgroup_update_tree(struct mem_cgroup *mem, struct page *page)
 {
@@ -481,17 +488,31 @@
 	return mz;
 }
 
+static s64 mem_cgroup_read_stat(struct mem_cgroup *mem,
+		enum mem_cgroup_stat_index idx)
+{
+	int cpu;
+	s64 val = 0;
+
+	for_each_possible_cpu(cpu)
+		val += per_cpu(mem->stat->count[idx], cpu);
+	return val;
+}
+
+static s64 mem_cgroup_local_usage(struct mem_cgroup *mem)
+{
+	s64 ret;
+
+	ret = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_RSS);
+	ret += mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_CACHE);
+	return ret;
+}
+
 static void mem_cgroup_swap_statistics(struct mem_cgroup *mem,
 					 bool charge)
 {
 	int val = (charge) ? 1 : -1;
-	struct mem_cgroup_stat *stat = &mem->stat;
-	struct mem_cgroup_stat_cpu *cpustat;
-	int cpu = get_cpu();
-
-	cpustat = &stat->cpustat[cpu];
-	__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_SWAPOUT, val);
-	put_cpu();
+	this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_SWAPOUT], val);
 }
 
 static void mem_cgroup_charge_statistics(struct mem_cgroup *mem,
@@ -499,24 +520,21 @@
 					 bool charge)
 {
 	int val = (charge) ? 1 : -1;
-	struct mem_cgroup_stat *stat = &mem->stat;
-	struct mem_cgroup_stat_cpu *cpustat;
-	int cpu = get_cpu();
 
-	cpustat = &stat->cpustat[cpu];
+	preempt_disable();
+
 	if (PageCgroupCache(pc))
-		__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_CACHE, val);
+		__this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_CACHE], val);
 	else
-		__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_RSS, val);
+		__this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_RSS], val);
 
 	if (charge)
-		__mem_cgroup_stat_add_safe(cpustat,
-				MEM_CGROUP_STAT_PGPGIN_COUNT, 1);
+		__this_cpu_inc(mem->stat->count[MEM_CGROUP_STAT_PGPGIN_COUNT]);
 	else
-		__mem_cgroup_stat_add_safe(cpustat,
-				MEM_CGROUP_STAT_PGPGOUT_COUNT, 1);
-	__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_EVENTS, 1);
-	put_cpu();
+		__this_cpu_inc(mem->stat->count[MEM_CGROUP_STAT_PGPGOUT_COUNT]);
+	__this_cpu_inc(mem->stat->count[MEM_CGROUP_EVENTS]);
+
+	preempt_enable();
 }
 
 static unsigned long mem_cgroup_get_local_zonestat(struct mem_cgroup *mem,
@@ -534,6 +552,29 @@
 	return total;
 }
 
+static bool __memcg_event_check(struct mem_cgroup *mem, int event_mask_shift)
+{
+	s64 val;
+
+	val = this_cpu_read(mem->stat->count[MEM_CGROUP_EVENTS]);
+
+	return !(val & ((1 << event_mask_shift) - 1));
+}
+
+/*
+ * Check events in order.
+ *
+ */
+static void memcg_check_events(struct mem_cgroup *mem, struct page *page)
+{
+	/* threshold event is triggered in finer grain than soft limit */
+	if (unlikely(__memcg_event_check(mem, THRESHOLDS_EVENTS_THRESH))) {
+		mem_cgroup_threshold(mem);
+		if (unlikely(__memcg_event_check(mem, SOFTLIMIT_EVENTS_THRESH)))
+			mem_cgroup_update_tree(mem, page);
+	}
+}
+
 static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)
 {
 	return container_of(cgroup_subsys_state(cont,
@@ -1000,7 +1041,7 @@
 }
 
 /**
- * mem_cgroup_print_mem_info: Called from OOM with tasklist_lock held in read mode.
+ * mem_cgroup_print_oom_info: Called from OOM with tasklist_lock held in read mode.
  * @memcg: The memory cgroup that went over limit
  * @p: Task that is going to be killed
  *
@@ -1174,7 +1215,7 @@
 				}
 			}
 		}
-		if (!mem_cgroup_local_usage(&victim->stat)) {
+		if (!mem_cgroup_local_usage(victim)) {
 			/* this cgroup's local usage == 0 */
 			css_put(&victim->css);
 			continue;
@@ -1205,32 +1246,102 @@
 	return total;
 }
 
-bool mem_cgroup_oom_called(struct task_struct *task)
+static int mem_cgroup_oom_lock_cb(struct mem_cgroup *mem, void *data)
 {
-	bool ret = false;
-	struct mem_cgroup *mem;
-	struct mm_struct *mm;
+	int *val = (int *)data;
+	int x;
+	/*
+	 * Logically, we can stop scanning immediately when we find
+	 * a memcg is already locked. But condidering unlock ops and
+	 * creation/removal of memcg, scan-all is simple operation.
+	 */
+	x = atomic_inc_return(&mem->oom_lock);
+	*val = max(x, *val);
+	return 0;
+}
+/*
+ * Check OOM-Killer is already running under our hierarchy.
+ * If someone is running, return false.
+ */
+static bool mem_cgroup_oom_lock(struct mem_cgroup *mem)
+{
+	int lock_count = 0;
 
-	rcu_read_lock();
-	mm = task->mm;
-	if (!mm)
-		mm = &init_mm;
-	mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
-	if (mem && time_before(jiffies, mem->last_oom_jiffies + HZ/10))
-		ret = true;
-	rcu_read_unlock();
-	return ret;
+	mem_cgroup_walk_tree(mem, &lock_count, mem_cgroup_oom_lock_cb);
+
+	if (lock_count == 1)
+		return true;
+	return false;
 }
 
-static int record_last_oom_cb(struct mem_cgroup *mem, void *data)
+static int mem_cgroup_oom_unlock_cb(struct mem_cgroup *mem, void *data)
 {
-	mem->last_oom_jiffies = jiffies;
+	/*
+	 * When a new child is created while the hierarchy is under oom,
+	 * mem_cgroup_oom_lock() may not be called. We have to use
+	 * atomic_add_unless() here.
+	 */
+	atomic_add_unless(&mem->oom_lock, -1, 0);
 	return 0;
 }
 
-static void record_last_oom(struct mem_cgroup *mem)
+static void mem_cgroup_oom_unlock(struct mem_cgroup *mem)
 {
-	mem_cgroup_walk_tree(mem, NULL, record_last_oom_cb);
+	mem_cgroup_walk_tree(mem, NULL,	mem_cgroup_oom_unlock_cb);
+}
+
+static DEFINE_MUTEX(memcg_oom_mutex);
+static DECLARE_WAIT_QUEUE_HEAD(memcg_oom_waitq);
+
+/*
+ * try to call OOM killer. returns false if we should exit memory-reclaim loop.
+ */
+bool mem_cgroup_handle_oom(struct mem_cgroup *mem, gfp_t mask)
+{
+	DEFINE_WAIT(wait);
+	bool locked;
+
+	/* At first, try to OOM lock hierarchy under mem.*/
+	mutex_lock(&memcg_oom_mutex);
+	locked = mem_cgroup_oom_lock(mem);
+	/*
+	 * Even if signal_pending(), we can't quit charge() loop without
+	 * accounting. So, UNINTERRUPTIBLE is appropriate. But SIGKILL
+	 * under OOM is always welcomed, use TASK_KILLABLE here.
+	 */
+	if (!locked)
+		prepare_to_wait(&memcg_oom_waitq, &wait, TASK_KILLABLE);
+	mutex_unlock(&memcg_oom_mutex);
+
+	if (locked)
+		mem_cgroup_out_of_memory(mem, mask);
+	else {
+		schedule();
+		finish_wait(&memcg_oom_waitq, &wait);
+	}
+	mutex_lock(&memcg_oom_mutex);
+	mem_cgroup_oom_unlock(mem);
+	/*
+	 * Here, we use global waitq .....more fine grained waitq ?
+	 * Assume following hierarchy.
+	 * A/
+	 *   01
+	 *   02
+	 * assume OOM happens both in A and 01 at the same time. Tthey are
+	 * mutually exclusive by lock. (kill in 01 helps A.)
+	 * When we use per memcg waitq, we have to wake up waiters on A and 02
+	 * in addtion to waiters on 01. We use global waitq for avoiding mess.
+	 * It will not be a big problem.
+	 * (And a task may be moved to other groups while it's waiting for OOM.)
+	 */
+	wake_up_all(&memcg_oom_waitq);
+	mutex_unlock(&memcg_oom_mutex);
+
+	if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current))
+		return false;
+	/* Give chance to dying process */
+	schedule_timeout(1);
+	return true;
 }
 
 /*
@@ -1240,9 +1351,6 @@
 void mem_cgroup_update_file_mapped(struct page *page, int val)
 {
 	struct mem_cgroup *mem;
-	struct mem_cgroup_stat *stat;
-	struct mem_cgroup_stat_cpu *cpustat;
-	int cpu;
 	struct page_cgroup *pc;
 
 	pc = lookup_page_cgroup(page);
@@ -1258,13 +1366,10 @@
 		goto done;
 
 	/*
-	 * Preemption is already disabled, we don't need get_cpu()
+	 * Preemption is already disabled. We can use __this_cpu_xxx
 	 */
-	cpu = smp_processor_id();
-	stat = &mem->stat;
-	cpustat = &stat->cpustat[cpu];
+	__this_cpu_add(mem->stat->count[MEM_CGROUP_STAT_FILE_MAPPED], val);
 
-	__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_FILE_MAPPED, val);
 done:
 	unlock_page_cgroup(pc);
 }
@@ -1401,19 +1506,21 @@
  * oom-killer can be invoked.
  */
 static int __mem_cgroup_try_charge(struct mm_struct *mm,
-			gfp_t gfp_mask, struct mem_cgroup **memcg,
-			bool oom, struct page *page)
+			gfp_t gfp_mask, struct mem_cgroup **memcg, bool oom)
 {
 	struct mem_cgroup *mem, *mem_over_limit;
 	int nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
 	struct res_counter *fail_res;
 	int csize = CHARGE_SIZE;
 
-	if (unlikely(test_thread_flag(TIF_MEMDIE))) {
-		/* Don't account this! */
-		*memcg = NULL;
-		return 0;
-	}
+	/*
+	 * Unlike gloval-vm's OOM-kill, we're not in memory shortage
+	 * in system level. So, allow to go ahead dying process in addition to
+	 * MEMDIE process.
+	 */
+	if (unlikely(test_thread_flag(TIF_MEMDIE)
+		     || fatal_signal_pending(current)))
+		goto bypass;
 
 	/*
 	 * We always charge the cgroup the mm_struct belongs to.
@@ -1440,7 +1547,7 @@
 		unsigned long flags = 0;
 
 		if (consume_stock(mem))
-			goto charged;
+			goto done;
 
 		ret = res_counter_charge(&mem->res, csize, &fail_res);
 		if (likely(!ret)) {
@@ -1483,28 +1590,70 @@
 		if (mem_cgroup_check_under_limit(mem_over_limit))
 			continue;
 
-		if (!nr_retries--) {
-			if (oom) {
-				mem_cgroup_out_of_memory(mem_over_limit, gfp_mask);
-				record_last_oom(mem_over_limit);
+		/* try to avoid oom while someone is moving charge */
+		if (mc.moving_task && current != mc.moving_task) {
+			struct mem_cgroup *from, *to;
+			bool do_continue = false;
+			/*
+			 * There is a small race that "from" or "to" can be
+			 * freed by rmdir, so we use css_tryget().
+			 */
+			rcu_read_lock();
+			from = mc.from;
+			to = mc.to;
+			if (from && css_tryget(&from->css)) {
+				if (mem_over_limit->use_hierarchy)
+					do_continue = css_is_ancestor(
+							&from->css,
+							&mem_over_limit->css);
+				else
+					do_continue = (from == mem_over_limit);
+				css_put(&from->css);
 			}
-			goto nomem;
+			if (!do_continue && to && css_tryget(&to->css)) {
+				if (mem_over_limit->use_hierarchy)
+					do_continue = css_is_ancestor(
+							&to->css,
+							&mem_over_limit->css);
+				else
+					do_continue = (to == mem_over_limit);
+				css_put(&to->css);
+			}
+			rcu_read_unlock();
+			if (do_continue) {
+				DEFINE_WAIT(wait);
+				prepare_to_wait(&mc.waitq, &wait,
+							TASK_INTERRUPTIBLE);
+				/* moving charge context might have finished. */
+				if (mc.moving_task)
+					schedule();
+				finish_wait(&mc.waitq, &wait);
+				continue;
+			}
+		}
+
+		if (!nr_retries--) {
+			if (!oom)
+				goto nomem;
+			if (mem_cgroup_handle_oom(mem_over_limit, gfp_mask)) {
+				nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
+				continue;
+			}
+			/* When we reach here, current task is dying .*/
+			css_put(&mem->css);
+			goto bypass;
 		}
 	}
 	if (csize > PAGE_SIZE)
 		refill_stock(mem, csize - PAGE_SIZE);
-charged:
-	/*
-	 * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree.
-	 * if they exceeds softlimit.
-	 */
-	if (mem_cgroup_soft_limit_check(mem))
-		mem_cgroup_update_tree(mem, page);
 done:
 	return 0;
 nomem:
 	css_put(&mem->css);
 	return -ENOMEM;
+bypass:
+	*memcg = NULL;
+	return 0;
 }
 
 /*
@@ -1512,14 +1661,23 @@
  * This function is for that and do uncharge, put css's refcnt.
  * gotten by try_charge().
  */
-static void mem_cgroup_cancel_charge(struct mem_cgroup *mem)
+static void __mem_cgroup_cancel_charge(struct mem_cgroup *mem,
+							unsigned long count)
 {
 	if (!mem_cgroup_is_root(mem)) {
-		res_counter_uncharge(&mem->res, PAGE_SIZE);
+		res_counter_uncharge(&mem->res, PAGE_SIZE * count);
 		if (do_swap_account)
-			res_counter_uncharge(&mem->memsw, PAGE_SIZE);
+			res_counter_uncharge(&mem->memsw, PAGE_SIZE * count);
+		VM_BUG_ON(test_bit(CSS_ROOT, &mem->css.flags));
+		WARN_ON_ONCE(count > INT_MAX);
+		__css_put(&mem->css, (int)count);
 	}
-	css_put(&mem->css);
+	/* we don't need css_put for root */
+}
+
+static void mem_cgroup_cancel_charge(struct mem_cgroup *mem)
+{
+	__mem_cgroup_cancel_charge(mem, 1);
 }
 
 /*
@@ -1615,6 +1773,12 @@
 	mem_cgroup_charge_statistics(mem, pc, true);
 
 	unlock_page_cgroup(pc);
+	/*
+	 * "charge_statistics" updated event counter. Then, check it.
+	 * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree.
+	 * if they exceeds softlimit.
+	 */
+	memcg_check_events(mem, pc->page);
 }
 
 /**
@@ -1622,22 +1786,22 @@
  * @pc:	page_cgroup of the page.
  * @from: mem_cgroup which the page is moved from.
  * @to:	mem_cgroup which the page is moved to. @from != @to.
+ * @uncharge: whether we should call uncharge and css_put against @from.
  *
  * The caller must confirm following.
  * - page is not on LRU (isolate_page() is useful.)
  * - the pc is locked, used, and ->mem_cgroup points to @from.
  *
- * This function does "uncharge" from old cgroup but doesn't do "charge" to
- * new cgroup. It should be done by a caller.
+ * This function doesn't do "charge" nor css_get to new cgroup. It should be
+ * done by a caller(__mem_cgroup_try_charge would be usefull). If @uncharge is
+ * true, this function does "uncharge" from old cgroup, but it doesn't if
+ * @uncharge is false, so a caller should do "uncharge".
  */
 
 static void __mem_cgroup_move_account(struct page_cgroup *pc,
-	struct mem_cgroup *from, struct mem_cgroup *to)
+	struct mem_cgroup *from, struct mem_cgroup *to, bool uncharge)
 {
 	struct page *page;
-	int cpu;
-	struct mem_cgroup_stat *stat;
-	struct mem_cgroup_stat_cpu *cpustat;
 
 	VM_BUG_ON(from == to);
 	VM_BUG_ON(PageLRU(pc->page));
@@ -1645,38 +1809,28 @@
 	VM_BUG_ON(!PageCgroupUsed(pc));
 	VM_BUG_ON(pc->mem_cgroup != from);
 
-	if (!mem_cgroup_is_root(from))
-		res_counter_uncharge(&from->res, PAGE_SIZE);
-	mem_cgroup_charge_statistics(from, pc, false);
-
 	page = pc->page;
 	if (page_mapped(page) && !PageAnon(page)) {
-		cpu = smp_processor_id();
-		/* Update mapped_file data for mem_cgroup "from" */
-		stat = &from->stat;
-		cpustat = &stat->cpustat[cpu];
-		__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_FILE_MAPPED,
-						-1);
-
-		/* Update mapped_file data for mem_cgroup "to" */
-		stat = &to->stat;
-		cpustat = &stat->cpustat[cpu];
-		__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_FILE_MAPPED,
-						1);
+		/* Update mapped_file data for mem_cgroup */
+		preempt_disable();
+		__this_cpu_dec(from->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]);
+		__this_cpu_inc(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]);
+		preempt_enable();
 	}
+	mem_cgroup_charge_statistics(from, pc, false);
+	if (uncharge)
+		/* This is not "cancel", but cancel_charge does all we need. */
+		mem_cgroup_cancel_charge(from);
 
-	if (do_swap_account && !mem_cgroup_is_root(from))
-		res_counter_uncharge(&from->memsw, PAGE_SIZE);
-	css_put(&from->css);
-
-	css_get(&to->css);
+	/* caller should have done css_get */
 	pc->mem_cgroup = to;
 	mem_cgroup_charge_statistics(to, pc, true);
 	/*
 	 * We charges against "to" which may not have any tasks. Then, "to"
 	 * can be under rmdir(). But in current implementation, caller of
-	 * this function is just force_empty() and it's garanteed that
-	 * "to" is never removed. So, we don't check rmdir status here.
+	 * this function is just force_empty() and move charge, so it's
+	 * garanteed that "to" is never removed. So, we don't check rmdir
+	 * status here.
 	 */
 }
 
@@ -1685,15 +1839,20 @@
  * __mem_cgroup_move_account()
  */
 static int mem_cgroup_move_account(struct page_cgroup *pc,
-				struct mem_cgroup *from, struct mem_cgroup *to)
+		struct mem_cgroup *from, struct mem_cgroup *to, bool uncharge)
 {
 	int ret = -EINVAL;
 	lock_page_cgroup(pc);
 	if (PageCgroupUsed(pc) && pc->mem_cgroup == from) {
-		__mem_cgroup_move_account(pc, from, to);
+		__mem_cgroup_move_account(pc, from, to, uncharge);
 		ret = 0;
 	}
 	unlock_page_cgroup(pc);
+	/*
+	 * check events
+	 */
+	memcg_check_events(to, pc->page);
+	memcg_check_events(from, pc->page);
 	return ret;
 }
 
@@ -1722,15 +1881,13 @@
 		goto put;
 
 	parent = mem_cgroup_from_cont(pcg);
-	ret = __mem_cgroup_try_charge(NULL, gfp_mask, &parent, false, page);
+	ret = __mem_cgroup_try_charge(NULL, gfp_mask, &parent, false);
 	if (ret || !parent)
 		goto put_back;
 
-	ret = mem_cgroup_move_account(pc, child, parent);
-	if (!ret)
-		css_put(&parent->css);	/* drop extra refcnt by try_charge() */
-	else
-		mem_cgroup_cancel_charge(parent);	/* does css_put */
+	ret = mem_cgroup_move_account(pc, child, parent, true);
+	if (ret)
+		mem_cgroup_cancel_charge(parent);
 put_back:
 	putback_lru_page(page);
 put:
@@ -1760,7 +1917,7 @@
 	prefetchw(pc);
 
 	mem = memcg;
-	ret = __mem_cgroup_try_charge(mm, gfp_mask, &mem, true, page);
+	ret = __mem_cgroup_try_charge(mm, gfp_mask, &mem, true);
 	if (ret || !mem)
 		return ret;
 
@@ -1880,14 +2037,14 @@
 	if (!mem)
 		goto charge_cur_mm;
 	*ptr = mem;
-	ret = __mem_cgroup_try_charge(NULL, mask, ptr, true, page);
+	ret = __mem_cgroup_try_charge(NULL, mask, ptr, true);
 	/* drop extra refcnt from tryget */
 	css_put(&mem->css);
 	return ret;
 charge_cur_mm:
 	if (unlikely(!mm))
 		mm = &init_mm;
-	return __mem_cgroup_try_charge(mm, mask, ptr, true, page);
+	return __mem_cgroup_try_charge(mm, mask, ptr, true);
 }
 
 static void
@@ -2064,8 +2221,7 @@
 	mz = page_cgroup_zoneinfo(pc);
 	unlock_page_cgroup(pc);
 
-	if (mem_cgroup_soft_limit_check(mem))
-		mem_cgroup_update_tree(mem, page);
+	memcg_check_events(mem, page);
 	/* at swapout, this memcg will be accessed to record to swap */
 	if (ctype != MEM_CGROUP_CHARGE_TYPE_SWAPOUT)
 		css_put(&mem->css);
@@ -2192,6 +2348,64 @@
 	}
 	rcu_read_unlock();
 }
+
+/**
+ * mem_cgroup_move_swap_account - move swap charge and swap_cgroup's record.
+ * @entry: swap entry to be moved
+ * @from:  mem_cgroup which the entry is moved from
+ * @to:  mem_cgroup which the entry is moved to
+ * @need_fixup: whether we should fixup res_counters and refcounts.
+ *
+ * It succeeds only when the swap_cgroup's record for this entry is the same
+ * as the mem_cgroup's id of @from.
+ *
+ * Returns 0 on success, -EINVAL on failure.
+ *
+ * The caller must have charged to @to, IOW, called res_counter_charge() about
+ * both res and memsw, and called css_get().
+ */
+static int mem_cgroup_move_swap_account(swp_entry_t entry,
+		struct mem_cgroup *from, struct mem_cgroup *to, bool need_fixup)
+{
+	unsigned short old_id, new_id;
+
+	old_id = css_id(&from->css);
+	new_id = css_id(&to->css);
+
+	if (swap_cgroup_cmpxchg(entry, old_id, new_id) == old_id) {
+		mem_cgroup_swap_statistics(from, false);
+		mem_cgroup_swap_statistics(to, true);
+		/*
+		 * This function is only called from task migration context now.
+		 * It postpones res_counter and refcount handling till the end
+		 * of task migration(mem_cgroup_clear_mc()) for performance
+		 * improvement. But we cannot postpone mem_cgroup_get(to)
+		 * because if the process that has been moved to @to does
+		 * swap-in, the refcount of @to might be decreased to 0.
+		 */
+		mem_cgroup_get(to);
+		if (need_fixup) {
+			if (!mem_cgroup_is_root(from))
+				res_counter_uncharge(&from->memsw, PAGE_SIZE);
+			mem_cgroup_put(from);
+			/*
+			 * we charged both to->res and to->memsw, so we should
+			 * uncharge to->res.
+			 */
+			if (!mem_cgroup_is_root(to))
+				res_counter_uncharge(&to->res, PAGE_SIZE);
+			css_put(&to->css);
+		}
+		return 0;
+	}
+	return -EINVAL;
+}
+#else
+static inline int mem_cgroup_move_swap_account(swp_entry_t entry,
+		struct mem_cgroup *from, struct mem_cgroup *to, bool need_fixup)
+{
+	return -EINVAL;
+}
 #endif
 
 /*
@@ -2216,8 +2430,7 @@
 	unlock_page_cgroup(pc);
 
 	if (mem) {
-		ret = __mem_cgroup_try_charge(NULL, GFP_KERNEL, &mem, false,
-						page);
+		ret = __mem_cgroup_try_charge(NULL, GFP_KERNEL, &mem, false);
 		css_put(&mem->css);
 	}
 	*ptr = mem;
@@ -2545,7 +2758,7 @@
 		pc = list_entry(list->prev, struct page_cgroup, lru);
 		if (busy == pc) {
 			list_move(&pc->lru, list);
-			busy = 0;
+			busy = NULL;
 			spin_unlock_irqrestore(&zone->lru_lock, flags);
 			continue;
 		}
@@ -2704,7 +2917,7 @@
 mem_cgroup_get_idx_stat(struct mem_cgroup *mem, void *data)
 {
 	struct mem_cgroup_idx_data *d = data;
-	d->val += mem_cgroup_read_stat(&mem->stat, d->idx);
+	d->val += mem_cgroup_read_stat(mem, d->idx);
 	return 0;
 }
 
@@ -2719,40 +2932,50 @@
 	*val = d.val;
 }
 
+static inline u64 mem_cgroup_usage(struct mem_cgroup *mem, bool swap)
+{
+	u64 idx_val, val;
+
+	if (!mem_cgroup_is_root(mem)) {
+		if (!swap)
+			return res_counter_read_u64(&mem->res, RES_USAGE);
+		else
+			return res_counter_read_u64(&mem->memsw, RES_USAGE);
+	}
+
+	mem_cgroup_get_recursive_idx_stat(mem, MEM_CGROUP_STAT_CACHE, &idx_val);
+	val = idx_val;
+	mem_cgroup_get_recursive_idx_stat(mem, MEM_CGROUP_STAT_RSS, &idx_val);
+	val += idx_val;
+
+	if (swap) {
+		mem_cgroup_get_recursive_idx_stat(mem,
+				MEM_CGROUP_STAT_SWAPOUT, &idx_val);
+		val += idx_val;
+	}
+
+	return val << PAGE_SHIFT;
+}
+
 static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
 {
 	struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
-	u64 idx_val, val;
+	u64 val;
 	int type, name;
 
 	type = MEMFILE_TYPE(cft->private);
 	name = MEMFILE_ATTR(cft->private);
 	switch (type) {
 	case _MEM:
-		if (name == RES_USAGE && mem_cgroup_is_root(mem)) {
-			mem_cgroup_get_recursive_idx_stat(mem,
-				MEM_CGROUP_STAT_CACHE, &idx_val);
-			val = idx_val;
-			mem_cgroup_get_recursive_idx_stat(mem,
-				MEM_CGROUP_STAT_RSS, &idx_val);
-			val += idx_val;
-			val <<= PAGE_SHIFT;
-		} else
+		if (name == RES_USAGE)
+			val = mem_cgroup_usage(mem, false);
+		else
 			val = res_counter_read_u64(&mem->res, name);
 		break;
 	case _MEMSWAP:
-		if (name == RES_USAGE && mem_cgroup_is_root(mem)) {
-			mem_cgroup_get_recursive_idx_stat(mem,
-				MEM_CGROUP_STAT_CACHE, &idx_val);
-			val = idx_val;
-			mem_cgroup_get_recursive_idx_stat(mem,
-				MEM_CGROUP_STAT_RSS, &idx_val);
-			val += idx_val;
-			mem_cgroup_get_recursive_idx_stat(mem,
-				MEM_CGROUP_STAT_SWAPOUT, &idx_val);
-			val += idx_val;
-			val <<= PAGE_SHIFT;
-		} else
+		if (name == RES_USAGE)
+			val = mem_cgroup_usage(mem, true);
+		else
 			val = res_counter_read_u64(&mem->memsw, name);
 		break;
 	default:
@@ -2865,6 +3088,39 @@
 	return 0;
 }
 
+static u64 mem_cgroup_move_charge_read(struct cgroup *cgrp,
+					struct cftype *cft)
+{
+	return mem_cgroup_from_cont(cgrp)->move_charge_at_immigrate;
+}
+
+#ifdef CONFIG_MMU
+static int mem_cgroup_move_charge_write(struct cgroup *cgrp,
+					struct cftype *cft, u64 val)
+{
+	struct mem_cgroup *mem = mem_cgroup_from_cont(cgrp);
+
+	if (val >= (1 << NR_MOVE_TYPE))
+		return -EINVAL;
+	/*
+	 * We check this value several times in both in can_attach() and
+	 * attach(), so we need cgroup lock to prevent this value from being
+	 * inconsistent.
+	 */
+	cgroup_lock();
+	mem->move_charge_at_immigrate = val;
+	cgroup_unlock();
+
+	return 0;
+}
+#else
+static int mem_cgroup_move_charge_write(struct cgroup *cgrp,
+					struct cftype *cft, u64 val)
+{
+	return -ENOSYS;
+}
+#endif
+
 
 /* For read statistics */
 enum {
@@ -2910,18 +3166,18 @@
 	s64 val;
 
 	/* per cpu stat */
-	val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_CACHE);
+	val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_CACHE);
 	s->stat[MCS_CACHE] += val * PAGE_SIZE;
-	val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_RSS);
+	val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_RSS);
 	s->stat[MCS_RSS] += val * PAGE_SIZE;
-	val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_FILE_MAPPED);
+	val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_FILE_MAPPED);
 	s->stat[MCS_FILE_MAPPED] += val * PAGE_SIZE;
-	val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGIN_COUNT);
+	val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_PGPGIN_COUNT);
 	s->stat[MCS_PGPGIN] += val;
-	val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGOUT_COUNT);
+	val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_PGPGOUT_COUNT);
 	s->stat[MCS_PGPGOUT] += val;
 	if (do_swap_account) {
-		val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_SWAPOUT);
+		val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_SWAPOUT);
 		s->stat[MCS_SWAP] += val * PAGE_SIZE;
 	}
 
@@ -3049,12 +3305,249 @@
 	return 0;
 }
 
+static void __mem_cgroup_threshold(struct mem_cgroup *memcg, bool swap)
+{
+	struct mem_cgroup_threshold_ary *t;
+	u64 usage;
+	int i;
+
+	rcu_read_lock();
+	if (!swap)
+		t = rcu_dereference(memcg->thresholds);
+	else
+		t = rcu_dereference(memcg->memsw_thresholds);
+
+	if (!t)
+		goto unlock;
+
+	usage = mem_cgroup_usage(memcg, swap);
+
+	/*
+	 * current_threshold points to threshold just below usage.
+	 * If it's not true, a threshold was crossed after last
+	 * call of __mem_cgroup_threshold().
+	 */
+	i = atomic_read(&t->current_threshold);
+
+	/*
+	 * Iterate backward over array of thresholds starting from
+	 * current_threshold and check if a threshold is crossed.
+	 * If none of thresholds below usage is crossed, we read
+	 * only one element of the array here.
+	 */
+	for (; i >= 0 && unlikely(t->entries[i].threshold > usage); i--)
+		eventfd_signal(t->entries[i].eventfd, 1);
+
+	/* i = current_threshold + 1 */
+	i++;
+
+	/*
+	 * Iterate forward over array of thresholds starting from
+	 * current_threshold+1 and check if a threshold is crossed.
+	 * If none of thresholds above usage is crossed, we read
+	 * only one element of the array here.
+	 */
+	for (; i < t->size && unlikely(t->entries[i].threshold <= usage); i++)
+		eventfd_signal(t->entries[i].eventfd, 1);
+
+	/* Update current_threshold */
+	atomic_set(&t->current_threshold, i - 1);
+unlock:
+	rcu_read_unlock();
+}
+
+static void mem_cgroup_threshold(struct mem_cgroup *memcg)
+{
+	__mem_cgroup_threshold(memcg, false);
+	if (do_swap_account)
+		__mem_cgroup_threshold(memcg, true);
+}
+
+static int compare_thresholds(const void *a, const void *b)
+{
+	const struct mem_cgroup_threshold *_a = a;
+	const struct mem_cgroup_threshold *_b = b;
+
+	return _a->threshold - _b->threshold;
+}
+
+static int mem_cgroup_register_event(struct cgroup *cgrp, struct cftype *cft,
+		struct eventfd_ctx *eventfd, const char *args)
+{
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
+	struct mem_cgroup_threshold_ary *thresholds, *thresholds_new;
+	int type = MEMFILE_TYPE(cft->private);
+	u64 threshold, usage;
+	int size;
+	int i, ret;
+
+	ret = res_counter_memparse_write_strategy(args, &threshold);
+	if (ret)
+		return ret;
+
+	mutex_lock(&memcg->thresholds_lock);
+	if (type == _MEM)
+		thresholds = memcg->thresholds;
+	else if (type == _MEMSWAP)
+		thresholds = memcg->memsw_thresholds;
+	else
+		BUG();
+
+	usage = mem_cgroup_usage(memcg, type == _MEMSWAP);
+
+	/* Check if a threshold crossed before adding a new one */
+	if (thresholds)
+		__mem_cgroup_threshold(memcg, type == _MEMSWAP);
+
+	if (thresholds)
+		size = thresholds->size + 1;
+	else
+		size = 1;
+
+	/* Allocate memory for new array of thresholds */
+	thresholds_new = kmalloc(sizeof(*thresholds_new) +
+			size * sizeof(struct mem_cgroup_threshold),
+			GFP_KERNEL);
+	if (!thresholds_new) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+	thresholds_new->size = size;
+
+	/* Copy thresholds (if any) to new array */
+	if (thresholds)
+		memcpy(thresholds_new->entries, thresholds->entries,
+				thresholds->size *
+				sizeof(struct mem_cgroup_threshold));
+	/* Add new threshold */
+	thresholds_new->entries[size - 1].eventfd = eventfd;
+	thresholds_new->entries[size - 1].threshold = threshold;
+
+	/* Sort thresholds. Registering of new threshold isn't time-critical */
+	sort(thresholds_new->entries, size,
+			sizeof(struct mem_cgroup_threshold),
+			compare_thresholds, NULL);
+
+	/* Find current threshold */
+	atomic_set(&thresholds_new->current_threshold, -1);
+	for (i = 0; i < size; i++) {
+		if (thresholds_new->entries[i].threshold < usage) {
+			/*
+			 * thresholds_new->current_threshold will not be used
+			 * until rcu_assign_pointer(), so it's safe to increment
+			 * it here.
+			 */
+			atomic_inc(&thresholds_new->current_threshold);
+		}
+	}
+
+	if (type == _MEM)
+		rcu_assign_pointer(memcg->thresholds, thresholds_new);
+	else
+		rcu_assign_pointer(memcg->memsw_thresholds, thresholds_new);
+
+	/* To be sure that nobody uses thresholds before freeing it */
+	synchronize_rcu();
+
+	kfree(thresholds);
+unlock:
+	mutex_unlock(&memcg->thresholds_lock);
+
+	return ret;
+}
+
+static int mem_cgroup_unregister_event(struct cgroup *cgrp, struct cftype *cft,
+		struct eventfd_ctx *eventfd)
+{
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
+	struct mem_cgroup_threshold_ary *thresholds, *thresholds_new;
+	int type = MEMFILE_TYPE(cft->private);
+	u64 usage;
+	int size = 0;
+	int i, j, ret;
+
+	mutex_lock(&memcg->thresholds_lock);
+	if (type == _MEM)
+		thresholds = memcg->thresholds;
+	else if (type == _MEMSWAP)
+		thresholds = memcg->memsw_thresholds;
+	else
+		BUG();
+
+	/*
+	 * Something went wrong if we trying to unregister a threshold
+	 * if we don't have thresholds
+	 */
+	BUG_ON(!thresholds);
+
+	usage = mem_cgroup_usage(memcg, type == _MEMSWAP);
+
+	/* Check if a threshold crossed before removing */
+	__mem_cgroup_threshold(memcg, type == _MEMSWAP);
+
+	/* Calculate new number of threshold */
+	for (i = 0; i < thresholds->size; i++) {
+		if (thresholds->entries[i].eventfd != eventfd)
+			size++;
+	}
+
+	/* Set thresholds array to NULL if we don't have thresholds */
+	if (!size) {
+		thresholds_new = NULL;
+		goto assign;
+	}
+
+	/* Allocate memory for new array of thresholds */
+	thresholds_new = kmalloc(sizeof(*thresholds_new) +
+			size * sizeof(struct mem_cgroup_threshold),
+			GFP_KERNEL);
+	if (!thresholds_new) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+	thresholds_new->size = size;
+
+	/* Copy thresholds and find current threshold */
+	atomic_set(&thresholds_new->current_threshold, -1);
+	for (i = 0, j = 0; i < thresholds->size; i++) {
+		if (thresholds->entries[i].eventfd == eventfd)
+			continue;
+
+		thresholds_new->entries[j] = thresholds->entries[i];
+		if (thresholds_new->entries[j].threshold < usage) {
+			/*
+			 * thresholds_new->current_threshold will not be used
+			 * until rcu_assign_pointer(), so it's safe to increment
+			 * it here.
+			 */
+			atomic_inc(&thresholds_new->current_threshold);
+		}
+		j++;
+	}
+
+assign:
+	if (type == _MEM)
+		rcu_assign_pointer(memcg->thresholds, thresholds_new);
+	else
+		rcu_assign_pointer(memcg->memsw_thresholds, thresholds_new);
+
+	/* To be sure that nobody uses thresholds before freeing it */
+	synchronize_rcu();
+
+	kfree(thresholds);
+unlock:
+	mutex_unlock(&memcg->thresholds_lock);
+
+	return ret;
+}
 
 static struct cftype mem_cgroup_files[] = {
 	{
 		.name = "usage_in_bytes",
 		.private = MEMFILE_PRIVATE(_MEM, RES_USAGE),
 		.read_u64 = mem_cgroup_read,
+		.register_event = mem_cgroup_register_event,
+		.unregister_event = mem_cgroup_unregister_event,
 	},
 	{
 		.name = "max_usage_in_bytes",
@@ -3098,6 +3591,11 @@
 		.read_u64 = mem_cgroup_swappiness_read,
 		.write_u64 = mem_cgroup_swappiness_write,
 	},
+	{
+		.name = "move_charge_at_immigrate",
+		.read_u64 = mem_cgroup_move_charge_read,
+		.write_u64 = mem_cgroup_move_charge_write,
+	},
 };
 
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
@@ -3106,6 +3604,8 @@
 		.name = "memsw.usage_in_bytes",
 		.private = MEMFILE_PRIVATE(_MEMSWAP, RES_USAGE),
 		.read_u64 = mem_cgroup_read,
+		.register_event = mem_cgroup_register_event,
+		.unregister_event = mem_cgroup_unregister_event,
 	},
 	{
 		.name = "memsw.max_usage_in_bytes",
@@ -3180,17 +3680,12 @@
 	kfree(mem->info.nodeinfo[node]);
 }
 
-static int mem_cgroup_size(void)
-{
-	int cpustat_size = nr_cpu_ids * sizeof(struct mem_cgroup_stat_cpu);
-	return sizeof(struct mem_cgroup) + cpustat_size;
-}
-
 static struct mem_cgroup *mem_cgroup_alloc(void)
 {
 	struct mem_cgroup *mem;
-	int size = mem_cgroup_size();
+	int size = sizeof(struct mem_cgroup);
 
+	/* Can be very big if MAX_NUMNODES is very big */
 	if (size < PAGE_SIZE)
 		mem = kmalloc(size, GFP_KERNEL);
 	else
@@ -3198,6 +3693,14 @@
 
 	if (mem)
 		memset(mem, 0, size);
+	mem->stat = alloc_percpu(struct mem_cgroup_stat_cpu);
+	if (!mem->stat) {
+		if (size < PAGE_SIZE)
+			kfree(mem);
+		else
+			vfree(mem);
+		mem = NULL;
+	}
 	return mem;
 }
 
@@ -3222,7 +3725,8 @@
 	for_each_node_state(node, N_POSSIBLE)
 		free_mem_cgroup_per_zone_info(mem, node);
 
-	if (mem_cgroup_size() < PAGE_SIZE)
+	free_percpu(mem->stat);
+	if (sizeof(struct mem_cgroup) < PAGE_SIZE)
 		kfree(mem);
 	else
 		vfree(mem);
@@ -3233,9 +3737,9 @@
 	atomic_inc(&mem->refcnt);
 }
 
-static void mem_cgroup_put(struct mem_cgroup *mem)
+static void __mem_cgroup_put(struct mem_cgroup *mem, int count)
 {
-	if (atomic_dec_and_test(&mem->refcnt)) {
+	if (atomic_sub_and_test(count, &mem->refcnt)) {
 		struct mem_cgroup *parent = parent_mem_cgroup(mem);
 		__mem_cgroup_free(mem);
 		if (parent)
@@ -3243,6 +3747,11 @@
 	}
 }
 
+static void mem_cgroup_put(struct mem_cgroup *mem)
+{
+	__mem_cgroup_put(mem, 1);
+}
+
 /*
  * Returns the parent mem_cgroup in memcgroup hierarchy with hierarchy enabled.
  */
@@ -3319,7 +3828,6 @@
 			INIT_WORK(&stock->work, drain_local_stock);
 		}
 		hotcpu_notifier(memcg_stock_cpu_callback, 0);
-
 	} else {
 		parent = mem_cgroup_from_cont(cont->parent);
 		mem->use_hierarchy = parent->use_hierarchy;
@@ -3345,6 +3853,8 @@
 	if (parent)
 		mem->swappiness = get_swappiness(parent);
 	atomic_set(&mem->refcnt, 1);
+	mem->move_charge_at_immigrate = 0;
+	mutex_init(&mem->thresholds_lock);
 	return &mem->css;
 free_out:
 	__mem_cgroup_free(mem);
@@ -3381,16 +3891,444 @@
 	return ret;
 }
 
+#ifdef CONFIG_MMU
+/* Handlers for move charge at task migration. */
+#define PRECHARGE_COUNT_AT_ONCE	256
+static int mem_cgroup_do_precharge(unsigned long count)
+{
+	int ret = 0;
+	int batch_count = PRECHARGE_COUNT_AT_ONCE;
+	struct mem_cgroup *mem = mc.to;
+
+	if (mem_cgroup_is_root(mem)) {
+		mc.precharge += count;
+		/* we don't need css_get for root */
+		return ret;
+	}
+	/* try to charge at once */
+	if (count > 1) {
+		struct res_counter *dummy;
+		/*
+		 * "mem" cannot be under rmdir() because we've already checked
+		 * by cgroup_lock_live_cgroup() that it is not removed and we
+		 * are still under the same cgroup_mutex. So we can postpone
+		 * css_get().
+		 */
+		if (res_counter_charge(&mem->res, PAGE_SIZE * count, &dummy))
+			goto one_by_one;
+		if (do_swap_account && res_counter_charge(&mem->memsw,
+						PAGE_SIZE * count, &dummy)) {
+			res_counter_uncharge(&mem->res, PAGE_SIZE * count);
+			goto one_by_one;
+		}
+		mc.precharge += count;
+		VM_BUG_ON(test_bit(CSS_ROOT, &mem->css.flags));
+		WARN_ON_ONCE(count > INT_MAX);
+		__css_get(&mem->css, (int)count);
+		return ret;
+	}
+one_by_one:
+	/* fall back to one by one charge */
+	while (count--) {
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
+		if (!batch_count--) {
+			batch_count = PRECHARGE_COUNT_AT_ONCE;
+			cond_resched();
+		}
+		ret = __mem_cgroup_try_charge(NULL, GFP_KERNEL, &mem, false);
+		if (ret || !mem)
+			/* mem_cgroup_clear_mc() will do uncharge later */
+			return -ENOMEM;
+		mc.precharge++;
+	}
+	return ret;
+}
+#else	/* !CONFIG_MMU */
+static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
+				struct cgroup *cgroup,
+				struct task_struct *p,
+				bool threadgroup)
+{
+	return 0;
+}
+static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss,
+				struct cgroup *cgroup,
+				struct task_struct *p,
+				bool threadgroup)
+{
+}
 static void mem_cgroup_move_task(struct cgroup_subsys *ss,
 				struct cgroup *cont,
 				struct cgroup *old_cont,
 				struct task_struct *p,
 				bool threadgroup)
 {
+}
+#endif
+
+/**
+ * is_target_pte_for_mc - check a pte whether it is valid for move charge
+ * @vma: the vma the pte to be checked belongs
+ * @addr: the address corresponding to the pte to be checked
+ * @ptent: the pte to be checked
+ * @target: the pointer the target page or swap ent will be stored(can be NULL)
+ *
+ * Returns
+ *   0(MC_TARGET_NONE): if the pte is not a target for move charge.
+ *   1(MC_TARGET_PAGE): if the page corresponding to this pte is a target for
+ *     move charge. if @target is not NULL, the page is stored in target->page
+ *     with extra refcnt got(Callers should handle it).
+ *   2(MC_TARGET_SWAP): if the swap entry corresponding to this pte is a
+ *     target for charge migration. if @target is not NULL, the entry is stored
+ *     in target->ent.
+ *
+ * Called with pte lock held.
+ */
+union mc_target {
+	struct page	*page;
+	swp_entry_t	ent;
+};
+
+enum mc_target_type {
+	MC_TARGET_NONE,	/* not used */
+	MC_TARGET_PAGE,
+	MC_TARGET_SWAP,
+};
+
+static int is_target_pte_for_mc(struct vm_area_struct *vma,
+		unsigned long addr, pte_t ptent, union mc_target *target)
+{
+	struct page *page = NULL;
+	struct page_cgroup *pc;
+	int ret = 0;
+	swp_entry_t ent = { .val = 0 };
+	int usage_count = 0;
+	bool move_anon = test_bit(MOVE_CHARGE_TYPE_ANON,
+					&mc.to->move_charge_at_immigrate);
+
+	if (!pte_present(ptent)) {
+		/* TODO: handle swap of shmes/tmpfs */
+		if (pte_none(ptent) || pte_file(ptent))
+			return 0;
+		else if (is_swap_pte(ptent)) {
+			ent = pte_to_swp_entry(ptent);
+			if (!move_anon || non_swap_entry(ent))
+				return 0;
+			usage_count = mem_cgroup_count_swap_user(ent, &page);
+		}
+	} else {
+		page = vm_normal_page(vma, addr, ptent);
+		if (!page || !page_mapped(page))
+			return 0;
+		/*
+		 * TODO: We don't move charges of file(including shmem/tmpfs)
+		 * pages for now.
+		 */
+		if (!move_anon || !PageAnon(page))
+			return 0;
+		if (!get_page_unless_zero(page))
+			return 0;
+		usage_count = page_mapcount(page);
+	}
+	if (usage_count > 1) {
+		/*
+		 * TODO: We don't move charges of shared(used by multiple
+		 * processes) pages for now.
+		 */
+		if (page)
+			put_page(page);
+		return 0;
+	}
+	if (page) {
+		pc = lookup_page_cgroup(page);
+		/*
+		 * Do only loose check w/o page_cgroup lock.
+		 * mem_cgroup_move_account() checks the pc is valid or not under
+		 * the lock.
+		 */
+		if (PageCgroupUsed(pc) && pc->mem_cgroup == mc.from) {
+			ret = MC_TARGET_PAGE;
+			if (target)
+				target->page = page;
+		}
+		if (!ret || !target)
+			put_page(page);
+	}
+	/* throught */
+	if (ent.val && do_swap_account && !ret &&
+			css_id(&mc.from->css) == lookup_swap_cgroup(ent)) {
+		ret = MC_TARGET_SWAP;
+		if (target)
+			target->ent = ent;
+	}
+	return ret;
+}
+
+static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd,
+					unsigned long addr, unsigned long end,
+					struct mm_walk *walk)
+{
+	struct vm_area_struct *vma = walk->private;
+	pte_t *pte;
+	spinlock_t *ptl;
+
+	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+	for (; addr != end; pte++, addr += PAGE_SIZE)
+		if (is_target_pte_for_mc(vma, addr, *pte, NULL))
+			mc.precharge++;	/* increment precharge temporarily */
+	pte_unmap_unlock(pte - 1, ptl);
+	cond_resched();
+
+	return 0;
+}
+
+static unsigned long mem_cgroup_count_precharge(struct mm_struct *mm)
+{
+	unsigned long precharge;
+	struct vm_area_struct *vma;
+
+	down_read(&mm->mmap_sem);
+	for (vma = mm->mmap; vma; vma = vma->vm_next) {
+		struct mm_walk mem_cgroup_count_precharge_walk = {
+			.pmd_entry = mem_cgroup_count_precharge_pte_range,
+			.mm = mm,
+			.private = vma,
+		};
+		if (is_vm_hugetlb_page(vma))
+			continue;
+		/* TODO: We don't move charges of shmem/tmpfs pages for now. */
+		if (vma->vm_flags & VM_SHARED)
+			continue;
+		walk_page_range(vma->vm_start, vma->vm_end,
+					&mem_cgroup_count_precharge_walk);
+	}
+	up_read(&mm->mmap_sem);
+
+	precharge = mc.precharge;
+	mc.precharge = 0;
+
+	return precharge;
+}
+
+static int mem_cgroup_precharge_mc(struct mm_struct *mm)
+{
+	return mem_cgroup_do_precharge(mem_cgroup_count_precharge(mm));
+}
+
+static void mem_cgroup_clear_mc(void)
+{
+	/* we must uncharge all the leftover precharges from mc.to */
+	if (mc.precharge) {
+		__mem_cgroup_cancel_charge(mc.to, mc.precharge);
+		mc.precharge = 0;
+	}
 	/*
-	 * FIXME: It's better to move charges of this process from old
-	 * memcg to new memcg. But it's just on TODO-List now.
+	 * we didn't uncharge from mc.from at mem_cgroup_move_account(), so
+	 * we must uncharge here.
 	 */
+	if (mc.moved_charge) {
+		__mem_cgroup_cancel_charge(mc.from, mc.moved_charge);
+		mc.moved_charge = 0;
+	}
+	/* we must fixup refcnts and charges */
+	if (mc.moved_swap) {
+		WARN_ON_ONCE(mc.moved_swap > INT_MAX);
+		/* uncharge swap account from the old cgroup */
+		if (!mem_cgroup_is_root(mc.from))
+			res_counter_uncharge(&mc.from->memsw,
+						PAGE_SIZE * mc.moved_swap);
+		__mem_cgroup_put(mc.from, mc.moved_swap);
+
+		if (!mem_cgroup_is_root(mc.to)) {
+			/*
+			 * we charged both to->res and to->memsw, so we should
+			 * uncharge to->res.
+			 */
+			res_counter_uncharge(&mc.to->res,
+						PAGE_SIZE * mc.moved_swap);
+			VM_BUG_ON(test_bit(CSS_ROOT, &mc.to->css.flags));
+			__css_put(&mc.to->css, mc.moved_swap);
+		}
+		/* we've already done mem_cgroup_get(mc.to) */
+
+		mc.moved_swap = 0;
+	}
+	mc.from = NULL;
+	mc.to = NULL;
+	mc.moving_task = NULL;
+	wake_up_all(&mc.waitq);
+}
+
+static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
+				struct cgroup *cgroup,
+				struct task_struct *p,
+				bool threadgroup)
+{
+	int ret = 0;
+	struct mem_cgroup *mem = mem_cgroup_from_cont(cgroup);
+
+	if (mem->move_charge_at_immigrate) {
+		struct mm_struct *mm;
+		struct mem_cgroup *from = mem_cgroup_from_task(p);
+
+		VM_BUG_ON(from == mem);
+
+		mm = get_task_mm(p);
+		if (!mm)
+			return 0;
+		/* We move charges only when we move a owner of the mm */
+		if (mm->owner == p) {
+			VM_BUG_ON(mc.from);
+			VM_BUG_ON(mc.to);
+			VM_BUG_ON(mc.precharge);
+			VM_BUG_ON(mc.moved_charge);
+			VM_BUG_ON(mc.moved_swap);
+			VM_BUG_ON(mc.moving_task);
+			mc.from = from;
+			mc.to = mem;
+			mc.precharge = 0;
+			mc.moved_charge = 0;
+			mc.moved_swap = 0;
+			mc.moving_task = current;
+
+			ret = mem_cgroup_precharge_mc(mm);
+			if (ret)
+				mem_cgroup_clear_mc();
+		}
+		mmput(mm);
+	}
+	return ret;
+}
+
+static void mem_cgroup_cancel_attach(struct cgroup_subsys *ss,
+				struct cgroup *cgroup,
+				struct task_struct *p,
+				bool threadgroup)
+{
+	mem_cgroup_clear_mc();
+}
+
+static int mem_cgroup_move_charge_pte_range(pmd_t *pmd,
+				unsigned long addr, unsigned long end,
+				struct mm_walk *walk)
+{
+	int ret = 0;
+	struct vm_area_struct *vma = walk->private;
+	pte_t *pte;
+	spinlock_t *ptl;
+
+retry:
+	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+	for (; addr != end; addr += PAGE_SIZE) {
+		pte_t ptent = *(pte++);
+		union mc_target target;
+		int type;
+		struct page *page;
+		struct page_cgroup *pc;
+		swp_entry_t ent;
+
+		if (!mc.precharge)
+			break;
+
+		type = is_target_pte_for_mc(vma, addr, ptent, &target);
+		switch (type) {
+		case MC_TARGET_PAGE:
+			page = target.page;
+			if (isolate_lru_page(page))
+				goto put;
+			pc = lookup_page_cgroup(page);
+			if (!mem_cgroup_move_account(pc,
+						mc.from, mc.to, false)) {
+				mc.precharge--;
+				/* we uncharge from mc.from later. */
+				mc.moved_charge++;
+			}
+			putback_lru_page(page);
+put:			/* is_target_pte_for_mc() gets the page */
+			put_page(page);
+			break;
+		case MC_TARGET_SWAP:
+			ent = target.ent;
+			if (!mem_cgroup_move_swap_account(ent,
+						mc.from, mc.to, false)) {
+				mc.precharge--;
+				/* we fixup refcnts and charges later. */
+				mc.moved_swap++;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	pte_unmap_unlock(pte - 1, ptl);
+	cond_resched();
+
+	if (addr != end) {
+		/*
+		 * We have consumed all precharges we got in can_attach().
+		 * We try charge one by one, but don't do any additional
+		 * charges to mc.to if we have failed in charge once in attach()
+		 * phase.
+		 */
+		ret = mem_cgroup_do_precharge(1);
+		if (!ret)
+			goto retry;
+	}
+
+	return ret;
+}
+
+static void mem_cgroup_move_charge(struct mm_struct *mm)
+{
+	struct vm_area_struct *vma;
+
+	lru_add_drain_all();
+	down_read(&mm->mmap_sem);
+	for (vma = mm->mmap; vma; vma = vma->vm_next) {
+		int ret;
+		struct mm_walk mem_cgroup_move_charge_walk = {
+			.pmd_entry = mem_cgroup_move_charge_pte_range,
+			.mm = mm,
+			.private = vma,
+		};
+		if (is_vm_hugetlb_page(vma))
+			continue;
+		/* TODO: We don't move charges of shmem/tmpfs pages for now. */
+		if (vma->vm_flags & VM_SHARED)
+			continue;
+		ret = walk_page_range(vma->vm_start, vma->vm_end,
+						&mem_cgroup_move_charge_walk);
+		if (ret)
+			/*
+			 * means we have consumed all precharges and failed in
+			 * doing additional charge. Just abandon here.
+			 */
+			break;
+	}
+	up_read(&mm->mmap_sem);
+}
+
+static void mem_cgroup_move_task(struct cgroup_subsys *ss,
+				struct cgroup *cont,
+				struct cgroup *old_cont,
+				struct task_struct *p,
+				bool threadgroup)
+{
+	struct mm_struct *mm;
+
+	if (!mc.to)
+		/* no need to move charge */
+		return;
+
+	mm = get_task_mm(p);
+	if (mm) {
+		mem_cgroup_move_charge(mm);
+		mmput(mm);
+	}
+	mem_cgroup_clear_mc();
 }
 
 struct cgroup_subsys mem_cgroup_subsys = {
@@ -3400,6 +4338,8 @@
 	.pre_destroy = mem_cgroup_pre_destroy,
 	.destroy = mem_cgroup_destroy,
 	.populate = mem_cgroup_populate,
+	.can_attach = mem_cgroup_can_attach,
+	.cancel_attach = mem_cgroup_cancel_attach,
 	.attach = mem_cgroup_move_task,
 	.early_init = 0,
 	.use_id = 1,
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 17299fd..d1f3351 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -383,9 +383,12 @@
 	if (av == NULL)	/* Not actually mapped anymore */
 		goto out;
 	for_each_process (tsk) {
+		struct anon_vma_chain *vmac;
+
 		if (!task_early_kill(tsk))
 			continue;
-		list_for_each_entry (vma, &av->head, anon_vma_node) {
+		list_for_each_entry(vmac, &av->head, same_anon_vma) {
+			vma = vmac->vma;
 			if (!page_mapped_in_vma(page, vma))
 				continue;
 			if (vma->vm_mm == tsk->mm)
diff --git a/mm/memory.c b/mm/memory.c
index 72fb5f3..5b7f200 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -121,6 +121,77 @@
 }
 core_initcall(init_zero_pfn);
 
+
+#if defined(SPLIT_RSS_COUNTING)
+
+void __sync_task_rss_stat(struct task_struct *task, struct mm_struct *mm)
+{
+	int i;
+
+	for (i = 0; i < NR_MM_COUNTERS; i++) {
+		if (task->rss_stat.count[i]) {
+			add_mm_counter(mm, i, task->rss_stat.count[i]);
+			task->rss_stat.count[i] = 0;
+		}
+	}
+	task->rss_stat.events = 0;
+}
+
+static void add_mm_counter_fast(struct mm_struct *mm, int member, int val)
+{
+	struct task_struct *task = current;
+
+	if (likely(task->mm == mm))
+		task->rss_stat.count[member] += val;
+	else
+		add_mm_counter(mm, member, val);
+}
+#define inc_mm_counter_fast(mm, member) add_mm_counter_fast(mm, member, 1)
+#define dec_mm_counter_fast(mm, member) add_mm_counter_fast(mm, member, -1)
+
+/* sync counter once per 64 page faults */
+#define TASK_RSS_EVENTS_THRESH	(64)
+static void check_sync_rss_stat(struct task_struct *task)
+{
+	if (unlikely(task != current))
+		return;
+	if (unlikely(task->rss_stat.events++ > TASK_RSS_EVENTS_THRESH))
+		__sync_task_rss_stat(task, task->mm);
+}
+
+unsigned long get_mm_counter(struct mm_struct *mm, int member)
+{
+	long val = 0;
+
+	/*
+	 * Don't use task->mm here...for avoiding to use task_get_mm()..
+	 * The caller must guarantee task->mm is not invalid.
+	 */
+	val = atomic_long_read(&mm->rss_stat.count[member]);
+	/*
+	 * counter is updated in asynchronous manner and may go to minus.
+	 * But it's never be expected number for users.
+	 */
+	if (val < 0)
+		return 0;
+	return (unsigned long)val;
+}
+
+void sync_mm_rss(struct task_struct *task, struct mm_struct *mm)
+{
+	__sync_task_rss_stat(task, mm);
+}
+#else
+
+#define inc_mm_counter_fast(mm, member) inc_mm_counter(mm, member)
+#define dec_mm_counter_fast(mm, member) dec_mm_counter(mm, member)
+
+static void check_sync_rss_stat(struct task_struct *task)
+{
+}
+
+#endif
+
 /*
  * If a p?d_bad entry is found while walking page tables, report
  * the error, before resetting entry to p?d_none.  Usually (but
@@ -300,7 +371,7 @@
 		 * Hide vma from rmap and truncate_pagecache before freeing
 		 * pgtables
 		 */
-		anon_vma_unlink(vma);
+		unlink_anon_vmas(vma);
 		unlink_file_vma(vma);
 
 		if (is_vm_hugetlb_page(vma)) {
@@ -314,7 +385,7 @@
 			       && !is_vm_hugetlb_page(next)) {
 				vma = next;
 				next = vma->vm_next;
-				anon_vma_unlink(vma);
+				unlink_anon_vmas(vma);
 				unlink_file_vma(vma);
 			}
 			free_pgd_range(tlb, addr, vma->vm_end,
@@ -376,12 +447,20 @@
 	return 0;
 }
 
-static inline void add_mm_rss(struct mm_struct *mm, int file_rss, int anon_rss)
+static inline void init_rss_vec(int *rss)
 {
-	if (file_rss)
-		add_mm_counter(mm, file_rss, file_rss);
-	if (anon_rss)
-		add_mm_counter(mm, anon_rss, anon_rss);
+	memset(rss, 0, sizeof(int) * NR_MM_COUNTERS);
+}
+
+static inline void add_mm_rss_vec(struct mm_struct *mm, int *rss)
+{
+	int i;
+
+	if (current->mm == mm)
+		sync_mm_rss(current, mm);
+	for (i = 0; i < NR_MM_COUNTERS; i++)
+		if (rss[i])
+			add_mm_counter(mm, i, rss[i]);
 }
 
 /*
@@ -430,12 +509,8 @@
 		"BUG: Bad page map in process %s  pte:%08llx pmd:%08llx\n",
 		current->comm,
 		(long long)pte_val(pte), (long long)pmd_val(*pmd));
-	if (page) {
-		printk(KERN_ALERT
-		"page:%p flags:%p count:%d mapcount:%d mapping:%p index:%lx\n",
-		page, (void *)page->flags, page_count(page),
-		page_mapcount(page), page->mapping, page->index);
-	}
+	if (page)
+		dump_page(page);
 	printk(KERN_ALERT
 		"addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n",
 		(void *)addr, vma->vm_flags, vma->anon_vma, mapping, index);
@@ -597,7 +672,9 @@
 						 &src_mm->mmlist);
 				spin_unlock(&mmlist_lock);
 			}
-			if (is_write_migration_entry(entry) &&
+			if (likely(!non_swap_entry(entry)))
+				rss[MM_SWAPENTS]++;
+			else if (is_write_migration_entry(entry) &&
 					is_cow_mapping(vm_flags)) {
 				/*
 				 * COW mappings require pages in both parent
@@ -632,7 +709,10 @@
 	if (page) {
 		get_page(page);
 		page_dup_rmap(page);
-		rss[PageAnon(page)]++;
+		if (PageAnon(page))
+			rss[MM_ANONPAGES]++;
+		else
+			rss[MM_FILEPAGES]++;
 	}
 
 out_set_pte:
@@ -648,11 +728,12 @@
 	pte_t *src_pte, *dst_pte;
 	spinlock_t *src_ptl, *dst_ptl;
 	int progress = 0;
-	int rss[2];
+	int rss[NR_MM_COUNTERS];
 	swp_entry_t entry = (swp_entry_t){0};
 
 again:
-	rss[1] = rss[0] = 0;
+	init_rss_vec(rss);
+
 	dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl);
 	if (!dst_pte)
 		return -ENOMEM;
@@ -688,7 +769,7 @@
 	arch_leave_lazy_mmu_mode();
 	spin_unlock(src_ptl);
 	pte_unmap_nested(orig_src_pte);
-	add_mm_rss(dst_mm, rss[0], rss[1]);
+	add_mm_rss_vec(dst_mm, rss);
 	pte_unmap_unlock(orig_dst_pte, dst_ptl);
 	cond_resched();
 
@@ -816,8 +897,9 @@
 	struct mm_struct *mm = tlb->mm;
 	pte_t *pte;
 	spinlock_t *ptl;
-	int file_rss = 0;
-	int anon_rss = 0;
+	int rss[NR_MM_COUNTERS];
+
+	init_rss_vec(rss);
 
 	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
 	arch_enter_lazy_mmu_mode();
@@ -863,14 +945,14 @@
 				set_pte_at(mm, addr, pte,
 					   pgoff_to_pte(page->index));
 			if (PageAnon(page))
-				anon_rss--;
+				rss[MM_ANONPAGES]--;
 			else {
 				if (pte_dirty(ptent))
 					set_page_dirty(page);
 				if (pte_young(ptent) &&
 				    likely(!VM_SequentialReadHint(vma)))
 					mark_page_accessed(page);
-				file_rss--;
+				rss[MM_FILEPAGES]--;
 			}
 			page_remove_rmap(page);
 			if (unlikely(page_mapcount(page) < 0))
@@ -887,13 +969,18 @@
 		if (pte_file(ptent)) {
 			if (unlikely(!(vma->vm_flags & VM_NONLINEAR)))
 				print_bad_pte(vma, addr, ptent, NULL);
-		} else if
-		  (unlikely(!free_swap_and_cache(pte_to_swp_entry(ptent))))
-			print_bad_pte(vma, addr, ptent, NULL);
+		} else {
+			swp_entry_t entry = pte_to_swp_entry(ptent);
+
+			if (!non_swap_entry(entry))
+				rss[MM_SWAPENTS]--;
+			if (unlikely(!free_swap_and_cache(entry)))
+				print_bad_pte(vma, addr, ptent, NULL);
+		}
 		pte_clear_not_present_full(mm, addr, pte, tlb->fullmm);
 	} while (pte++, addr += PAGE_SIZE, (addr != end && *zap_work > 0));
 
-	add_mm_rss(mm, file_rss, anon_rss);
+	add_mm_rss_vec(mm, rss);
 	arch_leave_lazy_mmu_mode();
 	pte_unmap_unlock(pte - 1, ptl);
 
@@ -1527,7 +1614,7 @@
 
 	/* Ok, finally just insert the thing.. */
 	get_page(page);
-	inc_mm_counter(mm, file_rss);
+	inc_mm_counter_fast(mm, MM_FILEPAGES);
 	page_add_file_rmap(page);
 	set_pte_at(mm, addr, pte, mk_pte(page, prot));
 
@@ -2044,6 +2131,13 @@
 			page_cache_release(old_page);
 		}
 		reuse = reuse_swap_page(old_page);
+		if (reuse)
+			/*
+			 * The page is all ours.  Move it to our anon_vma so
+			 * the rmap code will not search our parent or siblings.
+			 * Protected against the rmap code by the page lock.
+			 */
+			page_move_anon_rmap(old_page, vma, address);
 		unlock_page(old_page);
 	} else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
 					(VM_WRITE|VM_SHARED))) {
@@ -2163,11 +2257,11 @@
 	if (likely(pte_same(*page_table, orig_pte))) {
 		if (old_page) {
 			if (!PageAnon(old_page)) {
-				dec_mm_counter(mm, file_rss);
-				inc_mm_counter(mm, anon_rss);
+				dec_mm_counter_fast(mm, MM_FILEPAGES);
+				inc_mm_counter_fast(mm, MM_ANONPAGES);
 			}
 		} else
-			inc_mm_counter(mm, anon_rss);
+			inc_mm_counter_fast(mm, MM_ANONPAGES);
 		flush_cache_page(vma, address, pte_pfn(orig_pte));
 		entry = mk_pte(new_page, vma->vm_page_prot);
 		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
@@ -2604,7 +2698,8 @@
 	 * discarded at swap_free().
 	 */
 
-	inc_mm_counter(mm, anon_rss);
+	inc_mm_counter_fast(mm, MM_ANONPAGES);
+	dec_mm_counter_fast(mm, MM_SWAPENTS);
 	pte = mk_pte(page, vma->vm_page_prot);
 	if ((flags & FAULT_FLAG_WRITE) && reuse_swap_page(page)) {
 		pte = maybe_mkwrite(pte_mkdirty(pte), vma);
@@ -2688,7 +2783,7 @@
 	if (!pte_none(*page_table))
 		goto release;
 
-	inc_mm_counter(mm, anon_rss);
+	inc_mm_counter_fast(mm, MM_ANONPAGES);
 	page_add_new_anon_rmap(page, vma, address);
 setpte:
 	set_pte_at(mm, address, page_table, entry);
@@ -2842,10 +2937,10 @@
 		if (flags & FAULT_FLAG_WRITE)
 			entry = maybe_mkwrite(pte_mkdirty(entry), vma);
 		if (anon) {
-			inc_mm_counter(mm, anon_rss);
+			inc_mm_counter_fast(mm, MM_ANONPAGES);
 			page_add_new_anon_rmap(page, vma, address);
 		} else {
-			inc_mm_counter(mm, file_rss);
+			inc_mm_counter_fast(mm, MM_FILEPAGES);
 			page_add_file_rmap(page);
 			if (flags & FAULT_FLAG_WRITE) {
 				dirty_page = page;
@@ -3023,6 +3118,9 @@
 
 	count_vm_event(PGFAULT);
 
+	/* do counter updates before entering really critical section. */
+	check_sync_rss_stat(current);
+
 	if (unlikely(is_vm_hugetlb_page(vma)))
 		return hugetlb_fault(mm, vma, address, flags);
 
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 030ce8a..be211a5 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -28,6 +28,7 @@
 #include <linux/pfn.h>
 #include <linux/suspend.h>
 #include <linux/mm_inline.h>
+#include <linux/firmware-map.h>
 
 #include <asm/tlbflush.h>
 
@@ -523,6 +524,9 @@
 		BUG_ON(ret);
 	}
 
+	/* create new memmap entry */
+	firmware_map_add_hotplug(start, start + size, "System RAM");
+
 	goto out;
 
 error:
@@ -684,9 +688,9 @@
 			if (page_count(page))
 				not_managed++;
 #ifdef CONFIG_DEBUG_VM
-			printk(KERN_INFO "removing from LRU failed"
-					 " %lx/%d/%lx\n",
-				pfn, page_count(page), page->flags);
+			printk(KERN_ALERT "removing pfn %lx from LRU failed\n",
+			       pfn);
+			dump_page(page);
 #endif
 		}
 	}
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 290fb5b..643f66e 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -563,24 +563,50 @@
 }
 
 /* Step 2: apply policy to a range and do splits. */
-static int mbind_range(struct vm_area_struct *vma, unsigned long start,
-		       unsigned long end, struct mempolicy *new)
+static int mbind_range(struct mm_struct *mm, unsigned long start,
+		       unsigned long end, struct mempolicy *new_pol)
 {
 	struct vm_area_struct *next;
-	int err;
+	struct vm_area_struct *prev;
+	struct vm_area_struct *vma;
+	int err = 0;
+	pgoff_t pgoff;
+	unsigned long vmstart;
+	unsigned long vmend;
 
-	err = 0;
-	for (; vma && vma->vm_start < end; vma = next) {
+	vma = find_vma_prev(mm, start, &prev);
+	if (!vma || vma->vm_start > start)
+		return -EFAULT;
+
+	for (; vma && vma->vm_start < end; prev = vma, vma = next) {
 		next = vma->vm_next;
-		if (vma->vm_start < start)
-			err = split_vma(vma->vm_mm, vma, start, 1);
-		if (!err && vma->vm_end > end)
-			err = split_vma(vma->vm_mm, vma, end, 0);
-		if (!err)
-			err = policy_vma(vma, new);
+		vmstart = max(start, vma->vm_start);
+		vmend   = min(end, vma->vm_end);
+
+		pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+		prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags,
+				  vma->anon_vma, vma->vm_file, pgoff, new_pol);
+		if (prev) {
+			vma = prev;
+			next = vma->vm_next;
+			continue;
+		}
+		if (vma->vm_start != vmstart) {
+			err = split_vma(vma->vm_mm, vma, vmstart, 1);
+			if (err)
+				goto out;
+		}
+		if (vma->vm_end != vmend) {
+			err = split_vma(vma->vm_mm, vma, vmend, 0);
+			if (err)
+				goto out;
+		}
+		err = policy_vma(vma, new_pol);
 		if (err)
-			break;
+			goto out;
 	}
+
+ out:
 	return err;
 }
 
@@ -862,36 +888,36 @@
 	if (err)
 		goto out;
 
-/*
- * Find a 'source' bit set in 'tmp' whose corresponding 'dest'
- * bit in 'to' is not also set in 'tmp'.  Clear the found 'source'
- * bit in 'tmp', and return that <source, dest> pair for migration.
- * The pair of nodemasks 'to' and 'from' define the map.
- *
- * If no pair of bits is found that way, fallback to picking some
- * pair of 'source' and 'dest' bits that are not the same.  If the
- * 'source' and 'dest' bits are the same, this represents a node
- * that will be migrating to itself, so no pages need move.
- *
- * If no bits are left in 'tmp', or if all remaining bits left
- * in 'tmp' correspond to the same bit in 'to', return false
- * (nothing left to migrate).
- *
- * This lets us pick a pair of nodes to migrate between, such that
- * if possible the dest node is not already occupied by some other
- * source node, minimizing the risk of overloading the memory on a
- * node that would happen if we migrated incoming memory to a node
- * before migrating outgoing memory source that same node.
- *
- * A single scan of tmp is sufficient.  As we go, we remember the
- * most recent <s, d> pair that moved (s != d).  If we find a pair
- * that not only moved, but what's better, moved to an empty slot
- * (d is not set in tmp), then we break out then, with that pair.
- * Otherwise when we finish scannng from_tmp, we at least have the
- * most recent <s, d> pair that moved.  If we get all the way through
- * the scan of tmp without finding any node that moved, much less
- * moved to an empty node, then there is nothing left worth migrating.
- */
+	/*
+	 * Find a 'source' bit set in 'tmp' whose corresponding 'dest'
+	 * bit in 'to' is not also set in 'tmp'.  Clear the found 'source'
+	 * bit in 'tmp', and return that <source, dest> pair for migration.
+	 * The pair of nodemasks 'to' and 'from' define the map.
+	 *
+	 * If no pair of bits is found that way, fallback to picking some
+	 * pair of 'source' and 'dest' bits that are not the same.  If the
+	 * 'source' and 'dest' bits are the same, this represents a node
+	 * that will be migrating to itself, so no pages need move.
+	 *
+	 * If no bits are left in 'tmp', or if all remaining bits left
+	 * in 'tmp' correspond to the same bit in 'to', return false
+	 * (nothing left to migrate).
+	 *
+	 * This lets us pick a pair of nodes to migrate between, such that
+	 * if possible the dest node is not already occupied by some other
+	 * source node, minimizing the risk of overloading the memory on a
+	 * node that would happen if we migrated incoming memory to a node
+	 * before migrating outgoing memory source that same node.
+	 *
+	 * A single scan of tmp is sufficient.  As we go, we remember the
+	 * most recent <s, d> pair that moved (s != d).  If we find a pair
+	 * that not only moved, but what's better, moved to an empty slot
+	 * (d is not set in tmp), then we break out then, with that pair.
+	 * Otherwise when we finish scannng from_tmp, we at least have the
+	 * most recent <s, d> pair that moved.  If we get all the way through
+	 * the scan of tmp without finding any node that moved, much less
+	 * moved to an empty node, then there is nothing left worth migrating.
+	 */
 
 	tmp = *from_nodes;
 	while (!nodes_empty(tmp)) {
@@ -1047,7 +1073,7 @@
 	if (!IS_ERR(vma)) {
 		int nr_failed = 0;
 
-		err = mbind_range(vma, start, end, new);
+		err = mbind_range(mm, start, end, new);
 
 		if (!list_empty(&pagelist))
 			nr_failed = migrate_pages(&pagelist, new_vma_page,
@@ -1730,10 +1756,12 @@
 
 	if (!new)
 		return ERR_PTR(-ENOMEM);
+	rcu_read_lock();
 	if (current_cpuset_is_being_rebound()) {
 		nodemask_t mems = cpuset_mems_allowed(current);
 		mpol_rebind_policy(old, &mems);
 	}
+	rcu_read_unlock();
 	*new = *old;
 	atomic_set(&new->refcnt, 1);
 	return new;
diff --git a/mm/migrate.c b/mm/migrate.c
index edb6101..88000b8 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -275,8 +275,6 @@
  */
 static void migrate_page_copy(struct page *newpage, struct page *page)
 {
-	int anon;
-
 	copy_highpage(newpage, page);
 
 	if (PageError(page))
@@ -313,8 +311,6 @@
 	ClearPageSwapCache(page);
 	ClearPagePrivate(page);
 	set_page_private(page, 0);
-	/* page->mapping contains a flag for PageAnon() */
-	anon = PageAnon(page);
 	page->mapping = NULL;
 
 	/*
diff --git a/mm/mlock.c b/mm/mlock.c
index 2b8335a..8f4e2df 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -25,7 +25,7 @@
 {
 	if (capable(CAP_IPC_LOCK))
 		return 1;
-	if (current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur != 0)
+	if (rlimit(RLIMIT_MEMLOCK) != 0)
 		return 1;
 	return 0;
 }
@@ -487,7 +487,7 @@
 	locked = len >> PAGE_SHIFT;
 	locked += current->mm->locked_vm;
 
-	lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+	lock_limit = rlimit(RLIMIT_MEMLOCK);
 	lock_limit >>= PAGE_SHIFT;
 
 	/* check against resource limits */
@@ -550,7 +550,7 @@
 
 	down_write(&current->mm->mmap_sem);
 
-	lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+	lock_limit = rlimit(RLIMIT_MEMLOCK);
 	lock_limit >>= PAGE_SHIFT;
 
 	ret = -ENOMEM;
@@ -584,7 +584,7 @@
 	int allowed = 0;
 
 	locked = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+	lock_limit = rlimit(RLIMIT_MEMLOCK);
 	if (lock_limit == RLIM_INFINITY)
 		allowed = 1;
 	lock_limit >>= PAGE_SHIFT;
@@ -618,12 +618,12 @@
 
 	down_write(&mm->mmap_sem);
 
-	lim = rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
+	lim = ACCESS_ONCE(rlim[RLIMIT_AS].rlim_cur) >> PAGE_SHIFT;
 	vm   = mm->total_vm + pgsz;
 	if (lim < vm)
 		goto out;
 
-	lim = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
+	lim = ACCESS_ONCE(rlim[RLIMIT_MEMLOCK].rlim_cur) >> PAGE_SHIFT;
 	vm   = mm->locked_vm + pgsz;
 	if (lim < vm)
 		goto out;
diff --git a/mm/mmap.c b/mm/mmap.c
index ee22989..75557c6 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -265,7 +265,7 @@
 	 * segment grow beyond its set limit the in case where the limit is
 	 * not page aligned -Ram Gupta
 	 */
-	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+	rlim = rlimit(RLIMIT_DATA);
 	if (rlim < RLIM_INFINITY && (brk - mm->start_brk) +
 			(mm->end_data - mm->start_data) > rlim)
 		goto out;
@@ -437,7 +437,6 @@
 {
 	__vma_link_list(mm, vma, prev, rb_parent);
 	__vma_link_rb(mm, vma, rb_link, rb_parent);
-	__anon_vma_link(vma);
 }
 
 static void vma_link(struct mm_struct *mm, struct vm_area_struct *vma,
@@ -499,7 +498,7 @@
  * are necessary.  The "insert" vma (if any) is to be inserted
  * before we drop the necessary locks.
  */
-void vma_adjust(struct vm_area_struct *vma, unsigned long start,
+int vma_adjust(struct vm_area_struct *vma, unsigned long start,
 	unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert)
 {
 	struct mm_struct *mm = vma->vm_mm;
@@ -542,6 +541,26 @@
 		}
 	}
 
+	/*
+	 * When changing only vma->vm_end, we don't really need anon_vma lock.
+	 */
+	if (vma->anon_vma && (insert || importer || start != vma->vm_start))
+		anon_vma = vma->anon_vma;
+	if (anon_vma) {
+		/*
+		 * Easily overlooked: when mprotect shifts the boundary,
+		 * make sure the expanding vma has anon_vma set if the
+		 * shrinking vma had, to cover any anon pages imported.
+		 */
+		if (importer && !importer->anon_vma) {
+			/* Block reverse map lookups until things are set up. */
+			if (anon_vma_clone(importer, vma)) {
+				return -ENOMEM;
+			}
+			importer->anon_vma = anon_vma;
+		}
+	}
+
 	if (file) {
 		mapping = file->f_mapping;
 		if (!(vma->vm_flags & VM_NONLINEAR))
@@ -567,25 +586,6 @@
 		}
 	}
 
-	/*
-	 * When changing only vma->vm_end, we don't really need
-	 * anon_vma lock.
-	 */
-	if (vma->anon_vma && (insert || importer || start != vma->vm_start))
-		anon_vma = vma->anon_vma;
-	if (anon_vma) {
-		spin_lock(&anon_vma->lock);
-		/*
-		 * Easily overlooked: when mprotect shifts the boundary,
-		 * make sure the expanding vma has anon_vma set if the
-		 * shrinking vma had, to cover any anon pages imported.
-		 */
-		if (importer && !importer->anon_vma) {
-			importer->anon_vma = anon_vma;
-			__anon_vma_link(importer);
-		}
-	}
-
 	if (root) {
 		flush_dcache_mmap_lock(mapping);
 		vma_prio_tree_remove(vma, root);
@@ -616,8 +616,6 @@
 		__vma_unlink(mm, next, vma);
 		if (file)
 			__remove_shared_vm_struct(next, file, mapping);
-		if (next->anon_vma)
-			__anon_vma_merge(vma, next);
 	} else if (insert) {
 		/*
 		 * split_vma has split insert from vma, and needs
@@ -627,8 +625,6 @@
 		__insert_vm_struct(mm, insert);
 	}
 
-	if (anon_vma)
-		spin_unlock(&anon_vma->lock);
 	if (mapping)
 		spin_unlock(&mapping->i_mmap_lock);
 
@@ -638,6 +634,8 @@
 			if (next->vm_flags & VM_EXECUTABLE)
 				removed_exe_file_vma(mm);
 		}
+		if (next->anon_vma)
+			anon_vma_merge(vma, next);
 		mm->map_count--;
 		mpol_put(vma_policy(next));
 		kmem_cache_free(vm_area_cachep, next);
@@ -653,6 +651,8 @@
 	}
 
 	validate_mm(mm);
+
+	return 0;
 }
 
 /*
@@ -759,6 +759,7 @@
 {
 	pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
 	struct vm_area_struct *area, *next;
+	int err;
 
 	/*
 	 * We later require that vma->vm_flags == vm_flags,
@@ -792,11 +793,13 @@
 				is_mergeable_anon_vma(prev->anon_vma,
 						      next->anon_vma)) {
 							/* cases 1, 6 */
-			vma_adjust(prev, prev->vm_start,
+			err = vma_adjust(prev, prev->vm_start,
 				next->vm_end, prev->vm_pgoff, NULL);
 		} else					/* cases 2, 5, 7 */
-			vma_adjust(prev, prev->vm_start,
+			err = vma_adjust(prev, prev->vm_start,
 				end, prev->vm_pgoff, NULL);
+		if (err)
+			return NULL;
 		return prev;
 	}
 
@@ -808,11 +811,13 @@
 			can_vma_merge_before(next, vm_flags,
 					anon_vma, file, pgoff+pglen)) {
 		if (prev && addr < prev->vm_end)	/* case 4 */
-			vma_adjust(prev, prev->vm_start,
+			err = vma_adjust(prev, prev->vm_start,
 				addr, prev->vm_pgoff, NULL);
 		else					/* cases 3, 8 */
-			vma_adjust(area, addr, next->vm_end,
+			err = vma_adjust(area, addr, next->vm_end,
 				next->vm_pgoff - pglen, NULL);
+		if (err)
+			return NULL;
 		return area;
 	}
 
@@ -967,7 +972,7 @@
 		unsigned long locked, lock_limit;
 		locked = len >> PAGE_SHIFT;
 		locked += mm->locked_vm;
-		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+		lock_limit = rlimit(RLIMIT_MEMLOCK);
 		lock_limit >>= PAGE_SHIFT;
 		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			return -EAGAIN;
@@ -1083,6 +1088,30 @@
 	return retval;
 }
 
+#ifdef __ARCH_WANT_SYS_OLD_MMAP
+struct mmap_arg_struct {
+	unsigned long addr;
+	unsigned long len;
+	unsigned long prot;
+	unsigned long flags;
+	unsigned long fd;
+	unsigned long offset;
+};
+
+SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg)
+{
+	struct mmap_arg_struct a;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EFAULT;
+	if (a.offset & ~PAGE_MASK)
+		return -EINVAL;
+
+	return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+			      a.offset >> PAGE_SHIFT);
+}
+#endif /* __ARCH_WANT_SYS_OLD_MMAP */
+
 /*
  * Some shared mappigns will want the pages marked read-only
  * to track write events. If so, we'll downgrade vm_page_prot
@@ -1205,6 +1234,7 @@
 	vma->vm_flags = vm_flags;
 	vma->vm_page_prot = vm_get_page_prot(vm_flags);
 	vma->vm_pgoff = pgoff;
+	INIT_LIST_HEAD(&vma->anon_vma_chain);
 
 	if (file) {
 		error = -EINVAL;
@@ -1265,13 +1295,8 @@
 	mm->total_vm += len >> PAGE_SHIFT;
 	vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
 	if (vm_flags & VM_LOCKED) {
-		/*
-		 * makes pages present; downgrades, drops, reacquires mmap_sem
-		 */
-		long nr_pages = mlock_vma_pages_range(vma, addr, addr + len);
-		if (nr_pages < 0)
-			return nr_pages;	/* vma gone! */
-		mm->locked_vm += (len >> PAGE_SHIFT) - nr_pages;
+		if (!mlock_vma_pages_range(vma, addr, addr + len))
+			mm->locked_vm += (len >> PAGE_SHIFT);
 	} else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
 		make_pages_present(addr, addr + len);
 	return addr;
@@ -1599,7 +1624,7 @@
 		return -ENOMEM;
 
 	/* Stack limit test */
-	if (size > rlim[RLIMIT_STACK].rlim_cur)
+	if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur))
 		return -ENOMEM;
 
 	/* mlock limit tests */
@@ -1607,7 +1632,8 @@
 		unsigned long locked;
 		unsigned long limit;
 		locked = mm->locked_vm + grow;
-		limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
+		limit = ACCESS_ONCE(rlim[RLIMIT_MEMLOCK].rlim_cur);
+		limit >>= PAGE_SHIFT;
 		if (locked > limit && !capable(CAP_IPC_LOCK))
 			return -ENOMEM;
 	}
@@ -1754,8 +1780,7 @@
 	if (!prev || expand_stack(prev, addr))
 		return NULL;
 	if (prev->vm_flags & VM_LOCKED) {
-		if (mlock_vma_pages_range(prev, addr, prev->vm_end) < 0)
-			return NULL;	/* vma gone! */
+		mlock_vma_pages_range(prev, addr, prev->vm_end);
 	}
 	return prev;
 }
@@ -1783,8 +1808,7 @@
 	if (expand_stack(vma, addr))
 		return NULL;
 	if (vma->vm_flags & VM_LOCKED) {
-		if (mlock_vma_pages_range(vma, addr, start) < 0)
-			return NULL;	/* vma gone! */
+		mlock_vma_pages_range(vma, addr, start);
 	}
 	return vma;
 }
@@ -1871,6 +1895,7 @@
 {
 	struct mempolicy *pol;
 	struct vm_area_struct *new;
+	int err = -ENOMEM;
 
 	if (is_vm_hugetlb_page(vma) && (addr &
 					~(huge_page_mask(hstate_vma(vma)))))
@@ -1878,11 +1903,13 @@
 
 	new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
 	if (!new)
-		return -ENOMEM;
+		goto out_err;
 
 	/* most fields are the same, copy all, and then fixup */
 	*new = *vma;
 
+	INIT_LIST_HEAD(&new->anon_vma_chain);
+
 	if (new_below)
 		new->vm_end = addr;
 	else {
@@ -1892,11 +1919,14 @@
 
 	pol = mpol_dup(vma_policy(vma));
 	if (IS_ERR(pol)) {
-		kmem_cache_free(vm_area_cachep, new);
-		return PTR_ERR(pol);
+		err = PTR_ERR(pol);
+		goto out_free_vma;
 	}
 	vma_set_policy(new, pol);
 
+	if (anon_vma_clone(new, vma))
+		goto out_free_mpol;
+
 	if (new->vm_file) {
 		get_file(new->vm_file);
 		if (vma->vm_flags & VM_EXECUTABLE)
@@ -1907,12 +1937,28 @@
 		new->vm_ops->open(new);
 
 	if (new_below)
-		vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff +
+		err = vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff +
 			((addr - new->vm_start) >> PAGE_SHIFT), new);
 	else
-		vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
+		err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
 
-	return 0;
+	/* Success. */
+	if (!err)
+		return 0;
+
+	/* Clean everything up if vma_adjust failed. */
+	new->vm_ops->close(new);
+	if (new->vm_file) {
+		if (vma->vm_flags & VM_EXECUTABLE)
+			removed_exe_file_vma(mm);
+		fput(new->vm_file);
+	}
+ out_free_mpol:
+	mpol_put(pol);
+ out_free_vma:
+	kmem_cache_free(vm_area_cachep, new);
+ out_err:
+	return err;
 }
 
 /*
@@ -2074,7 +2120,7 @@
 		unsigned long locked, lock_limit;
 		locked = len >> PAGE_SHIFT;
 		locked += mm->locked_vm;
-		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+		lock_limit = rlimit(RLIMIT_MEMLOCK);
 		lock_limit >>= PAGE_SHIFT;
 		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			return -EAGAIN;
@@ -2122,6 +2168,7 @@
 		return -ENOMEM;
 	}
 
+	INIT_LIST_HEAD(&vma->anon_vma_chain);
 	vma->vm_mm = mm;
 	vma->vm_start = addr;
 	vma->vm_end = addr + len;
@@ -2258,10 +2305,11 @@
 		if (new_vma) {
 			*new_vma = *vma;
 			pol = mpol_dup(vma_policy(vma));
-			if (IS_ERR(pol)) {
-				kmem_cache_free(vm_area_cachep, new_vma);
-				return NULL;
-			}
+			if (IS_ERR(pol))
+				goto out_free_vma;
+			INIT_LIST_HEAD(&new_vma->anon_vma_chain);
+			if (anon_vma_clone(new_vma, vma))
+				goto out_free_mempol;
 			vma_set_policy(new_vma, pol);
 			new_vma->vm_start = addr;
 			new_vma->vm_end = addr + len;
@@ -2277,6 +2325,12 @@
 		}
 	}
 	return new_vma;
+
+ out_free_mempol:
+	mpol_put(pol);
+ out_free_vma:
+	kmem_cache_free(vm_area_cachep, new_vma);
+	return NULL;
 }
 
 /*
@@ -2288,7 +2342,7 @@
 	unsigned long cur = mm->total_vm;	/* pages */
 	unsigned long lim;
 
-	lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
+	lim = rlimit(RLIMIT_AS) >> PAGE_SHIFT;
 
 	if (cur + npages > lim)
 		return 0;
@@ -2354,6 +2408,7 @@
 	if (unlikely(vma == NULL))
 		return -ENOMEM;
 
+	INIT_LIST_HEAD(&vma->anon_vma_chain);
 	vma->vm_mm = mm;
 	vma->vm_start = addr;
 	vma->vm_end = addr + len;
@@ -2454,6 +2509,7 @@
 int mm_take_all_locks(struct mm_struct *mm)
 {
 	struct vm_area_struct *vma;
+	struct anon_vma_chain *avc;
 	int ret = -EINTR;
 
 	BUG_ON(down_read_trylock(&mm->mmap_sem));
@@ -2471,7 +2527,8 @@
 		if (signal_pending(current))
 			goto out_unlock;
 		if (vma->anon_vma)
-			vm_lock_anon_vma(mm, vma->anon_vma);
+			list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
+				vm_lock_anon_vma(mm, avc->anon_vma);
 	}
 
 	ret = 0;
@@ -2526,13 +2583,15 @@
 void mm_drop_all_locks(struct mm_struct *mm)
 {
 	struct vm_area_struct *vma;
+	struct anon_vma_chain *avc;
 
 	BUG_ON(down_read_trylock(&mm->mmap_sem));
 	BUG_ON(!mutex_is_locked(&mm_all_locks_mutex));
 
 	for (vma = mm->mmap; vma; vma = vma->vm_next) {
 		if (vma->anon_vma)
-			vm_unlock_anon_vma(vma->anon_vma);
+			list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
+				vm_unlock_anon_vma(avc->anon_vma);
 		if (vma->vm_file && vma->vm_file->f_mapping)
 			vm_unlock_mapping(vma->vm_file->f_mapping);
 	}
diff --git a/mm/mremap.c b/mm/mremap.c
index 8451908..e9c75ef 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -285,7 +285,7 @@
 	if (vma->vm_flags & VM_LOCKED) {
 		unsigned long locked, lock_limit;
 		locked = mm->locked_vm << PAGE_SHIFT;
-		lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+		lock_limit = rlimit(RLIMIT_MEMLOCK);
 		locked += new_len - old_len;
 		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			goto Eagain;
@@ -460,8 +460,11 @@
 		if (vma_expandable(vma, new_len - old_len)) {
 			int pages = (new_len - old_len) >> PAGE_SHIFT;
 
-			vma_adjust(vma, vma->vm_start,
-				addr + new_len, vma->vm_pgoff, NULL);
+			if (vma_adjust(vma, vma->vm_start, addr + new_len,
+				       vma->vm_pgoff, NULL)) {
+				ret = -ENOMEM;
+				goto out;
+			}
 
 			mm->total_vm += pages;
 			vm_stat_account(mm, vma->vm_flags, vma->vm_file, pages);
diff --git a/mm/nommu.c b/mm/nommu.c
index 48a2ecf..605ace8 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -146,7 +146,7 @@
 			(VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
 
 	for (i = 0; i < nr_pages; i++) {
-		vma = find_vma(mm, start);
+		vma = find_extend_vma(mm, start);
 		if (!vma)
 			goto finish_or_fault;
 
@@ -764,7 +764,7 @@
  */
 struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
 {
-	return find_vma(mm, addr);
+	return find_vma(mm, addr & PAGE_MASK);
 }
 
 /*
@@ -1209,7 +1209,7 @@
 	region->vm_flags = vm_flags;
 	region->vm_pgoff = pgoff;
 
-	INIT_LIST_HEAD(&vma->anon_vma_node);
+	INIT_LIST_HEAD(&vma->anon_vma_chain);
 	vma->vm_flags = vm_flags;
 	vma->vm_pgoff = pgoff;
 
@@ -1428,6 +1428,30 @@
 	return retval;
 }
 
+#ifdef __ARCH_WANT_SYS_OLD_MMAP
+struct mmap_arg_struct {
+	unsigned long addr;
+	unsigned long len;
+	unsigned long prot;
+	unsigned long flags;
+	unsigned long fd;
+	unsigned long offset;
+};
+
+SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg)
+{
+	struct mmap_arg_struct a;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EFAULT;
+	if (a.offset & ~PAGE_MASK)
+		return -EINVAL;
+
+	return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,
+			      a.offset >> PAGE_SHIFT);
+}
+#endif /* __ARCH_WANT_SYS_OLD_MMAP */
+
 /*
  * split a vma into two pieces at address 'addr', a new vma is allocated either
  * for the first part or the tail.
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 2370504..9b223af 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -401,8 +401,8 @@
 		       "vsz:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
 		       task_pid_nr(p), p->comm,
 		       K(p->mm->total_vm),
-		       K(get_mm_counter(p->mm, anon_rss)),
-		       K(get_mm_counter(p->mm, file_rss)));
+		       K(get_mm_counter(p->mm, MM_ANONPAGES)),
+		       K(get_mm_counter(p->mm, MM_FILEPAGES)));
 	task_unlock(p);
 
 	/*
@@ -473,6 +473,8 @@
 	unsigned long points = 0;
 	struct task_struct *p;
 
+	if (sysctl_panic_on_oom == 2)
+		panic("out of memory(memcg). panic_on_oom is selected.\n");
 	read_lock(&tasklist_lock);
 retry:
 	p = select_bad_process(&points, mem);
@@ -601,13 +603,6 @@
 		/* Got some memory back in the last second. */
 		return;
 
-	/*
-	 * If this is from memcg, oom-killer is already invoked.
-	 * and not worth to go system-wide-oom.
-	 */
-	if (mem_cgroup_oom_called(current))
-		goto rest_and_return;
-
 	if (sysctl_panic_on_oom)
 		panic("out of memory from page fault. panic_on_oom is selected.\n");
 
@@ -619,7 +614,6 @@
 	 * Give "p" a good chance of killing itself before we
 	 * retry to allocate memory.
 	 */
-rest_and_return:
 	if (!test_thread_flag(TIF_MEMDIE))
 		schedule_timeout_uninterruptible(1);
 }
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 8deb9d0..d03c946 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -50,6 +50,7 @@
 #include <linux/kmemleak.h>
 #include <linux/memory.h>
 #include <trace/events/kmem.h>
+#include <linux/ftrace_event.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -76,6 +77,31 @@
 int percpu_pagelist_fraction;
 gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK;
 
+#ifdef CONFIG_PM_SLEEP
+/*
+ * The following functions are used by the suspend/hibernate code to temporarily
+ * change gfp_allowed_mask in order to avoid using I/O during memory allocations
+ * while devices are suspended.  To avoid races with the suspend/hibernate code,
+ * they should always be called with pm_mutex held (gfp_allowed_mask also should
+ * only be modified with pm_mutex held, unless the suspend/hibernate code is
+ * guaranteed not to run in parallel with that modification).
+ */
+void set_gfp_allowed_mask(gfp_t mask)
+{
+	WARN_ON(!mutex_is_locked(&pm_mutex));
+	gfp_allowed_mask = mask;
+}
+
+gfp_t clear_gfp_allowed_mask(gfp_t mask)
+{
+	gfp_t ret = gfp_allowed_mask;
+
+	WARN_ON(!mutex_is_locked(&pm_mutex));
+	gfp_allowed_mask &= ~mask;
+	return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
 #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
 int pageblock_order __read_mostly;
 #endif
@@ -263,10 +289,7 @@
 
 	printk(KERN_ALERT "BUG: Bad page state in process %s  pfn:%05lx\n",
 		current->comm, page_to_pfn(page));
-	printk(KERN_ALERT
-		"page:%p flags:%p count:%d mapcount:%d mapping:%p index:%lx\n",
-		page, (void *)page->flags, page_count(page),
-		page_mapcount(page), page->mapping, page->index);
+	dump_page(page);
 
 	dump_stack();
 out:
@@ -530,7 +553,7 @@
 	int batch_free = 0;
 
 	spin_lock(&zone->lock);
-	zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE);
+	zone->all_unreclaimable = 0;
 	zone->pages_scanned = 0;
 
 	__mod_zone_page_state(zone, NR_FREE_PAGES, count);
@@ -568,7 +591,7 @@
 				int migratetype)
 {
 	spin_lock(&zone->lock);
-	zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE);
+	zone->all_unreclaimable = 0;
 	zone->pages_scanned = 0;
 
 	__mod_zone_page_state(zone, NR_FREE_PAGES, 1 << order);
@@ -583,6 +606,7 @@
 	int bad = 0;
 	int wasMlocked = __TestClearPageMlocked(page);
 
+	trace_mm_page_free_direct(page, order);
 	kmemcheck_free_shadow(page, order);
 
 	for (i = 0 ; i < (1 << order) ; ++i)
@@ -1009,10 +1033,10 @@
 		struct per_cpu_pageset *pset;
 		struct per_cpu_pages *pcp;
 
-		pset = zone_pcp(zone, cpu);
+		local_irq_save(flags);
+		pset = per_cpu_ptr(zone->pageset, cpu);
 
 		pcp = &pset->pcp;
-		local_irq_save(flags);
 		free_pcppages_bulk(zone, pcp->count, pcp);
 		pcp->count = 0;
 		local_irq_restore(flags);
@@ -1073,8 +1097,9 @@
 
 /*
  * Free a 0-order page
+ * cold == 1 ? free a cold page : free a hot page
  */
-static void free_hot_cold_page(struct page *page, int cold)
+void free_hot_cold_page(struct page *page, int cold)
 {
 	struct zone *zone = page_zone(page);
 	struct per_cpu_pages *pcp;
@@ -1082,6 +1107,7 @@
 	int migratetype;
 	int wasMlocked = __TestClearPageMlocked(page);
 
+	trace_mm_page_free_direct(page, 0);
 	kmemcheck_free_shadow(page, 0);
 
 	if (PageAnon(page))
@@ -1096,7 +1122,6 @@
 	arch_free_page(page, 0);
 	kernel_map_pages(page, 1, 0);
 
-	pcp = &zone_pcp(zone, get_cpu())->pcp;
 	migratetype = get_pageblock_migratetype(page);
 	set_page_private(page, migratetype);
 	local_irq_save(flags);
@@ -1119,6 +1144,7 @@
 		migratetype = MIGRATE_MOVABLE;
 	}
 
+	pcp = &this_cpu_ptr(zone->pageset)->pcp;
 	if (cold)
 		list_add_tail(&page->lru, &pcp->lists[migratetype]);
 	else
@@ -1131,15 +1157,8 @@
 
 out:
 	local_irq_restore(flags);
-	put_cpu();
 }
 
-void free_hot_page(struct page *page)
-{
-	trace_mm_page_free_direct(page, 0);
-	free_hot_cold_page(page, 0);
-}
-	
 /*
  * split_page takes a non-compound higher-order page, and splits it into
  * n (1<<order) sub-pages: page[0..n]
@@ -1181,17 +1200,15 @@
 	unsigned long flags;
 	struct page *page;
 	int cold = !!(gfp_flags & __GFP_COLD);
-	int cpu;
 
 again:
-	cpu  = get_cpu();
 	if (likely(order == 0)) {
 		struct per_cpu_pages *pcp;
 		struct list_head *list;
 
-		pcp = &zone_pcp(zone, cpu)->pcp;
-		list = &pcp->lists[migratetype];
 		local_irq_save(flags);
+		pcp = &this_cpu_ptr(zone->pageset)->pcp;
+		list = &pcp->lists[migratetype];
 		if (list_empty(list)) {
 			pcp->count += rmqueue_bulk(zone, 0,
 					pcp->batch, list,
@@ -1232,7 +1249,6 @@
 	__count_zone_vm_events(PGALLOC, zone, 1 << order);
 	zone_statistics(preferred_zone, zone);
 	local_irq_restore(flags);
-	put_cpu();
 
 	VM_BUG_ON(bad_range(zone, page));
 	if (prep_new_page(page, order, gfp_flags))
@@ -1241,7 +1257,6 @@
 
 failed:
 	local_irq_restore(flags);
-	put_cpu();
 	return NULL;
 }
 
@@ -2013,9 +2028,8 @@
 void __free_pages(struct page *page, unsigned int order)
 {
 	if (put_page_testzero(page)) {
-		trace_mm_page_free_direct(page, order);
 		if (order == 0)
-			free_hot_page(page);
+			free_hot_cold_page(page, 0);
 		else
 			__free_pages_ok(page, order);
 	}
@@ -2180,7 +2194,7 @@
 		for_each_online_cpu(cpu) {
 			struct per_cpu_pageset *pageset;
 
-			pageset = zone_pcp(zone, cpu);
+			pageset = per_cpu_ptr(zone->pageset, cpu);
 
 			printk("CPU %4d: hi:%5d, btch:%4d usd:%4d\n",
 			       cpu, pageset->pcp.high,
@@ -2271,7 +2285,7 @@
 			K(zone_page_state(zone, NR_BOUNCE)),
 			K(zone_page_state(zone, NR_WRITEBACK_TEMP)),
 			zone->pages_scanned,
-			(zone_is_all_unreclaimable(zone) ? "yes" : "no")
+			(zone->all_unreclaimable ? "yes" : "no")
 			);
 		printk("lowmem_reserve[]:");
 		for (i = 0; i < MAX_NR_ZONES; i++)
@@ -2745,10 +2759,29 @@
 
 #endif	/* CONFIG_NUMA */
 
+/*
+ * Boot pageset table. One per cpu which is going to be used for all
+ * zones and all nodes. The parameters will be set in such a way
+ * that an item put on a list will immediately be handed over to
+ * the buddy list. This is safe since pageset manipulation is done
+ * with interrupts disabled.
+ *
+ * The boot_pagesets must be kept even after bootup is complete for
+ * unused processors and/or zones. They do play a role for bootstrapping
+ * hotplugged processors.
+ *
+ * zoneinfo_show() and maybe other functions do
+ * not check if the processor is online before following the pageset pointer.
+ * Other parts of the kernel may not check if the zone is available.
+ */
+static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch);
+static DEFINE_PER_CPU(struct per_cpu_pageset, boot_pageset);
+
 /* return values int ....just for stop_machine() */
 static int __build_all_zonelists(void *dummy)
 {
 	int nid;
+	int cpu;
 
 #ifdef CONFIG_NUMA
 	memset(node_load, 0, sizeof(node_load));
@@ -2759,6 +2792,23 @@
 		build_zonelists(pgdat);
 		build_zonelist_cache(pgdat);
 	}
+
+	/*
+	 * Initialize the boot_pagesets that are going to be used
+	 * for bootstrapping processors. The real pagesets for
+	 * each zone will be allocated later when the per cpu
+	 * allocator is available.
+	 *
+	 * boot_pagesets are used also for bootstrapping offline
+	 * cpus if the system is already booted because the pagesets
+	 * are needed to initialize allocators on a specific cpu too.
+	 * F.e. the percpu allocator needs the page allocator which
+	 * needs the percpu allocator in order to allocate its pagesets
+	 * (a chicken-egg dilemma).
+	 */
+	for_each_possible_cpu(cpu)
+		setup_pageset(&per_cpu(boot_pageset, cpu), 0);
+
 	return 0;
 }
 
@@ -3096,121 +3146,33 @@
 		pcp->batch = PAGE_SHIFT * 8;
 }
 
-
-#ifdef CONFIG_NUMA
 /*
- * Boot pageset table. One per cpu which is going to be used for all
- * zones and all nodes. The parameters will be set in such a way
- * that an item put on a list will immediately be handed over to
- * the buddy list. This is safe since pageset manipulation is done
- * with interrupts disabled.
- *
- * Some NUMA counter updates may also be caught by the boot pagesets.
- *
- * The boot_pagesets must be kept even after bootup is complete for
- * unused processors and/or zones. They do play a role for bootstrapping
- * hotplugged processors.
- *
- * zoneinfo_show() and maybe other functions do
- * not check if the processor is online before following the pageset pointer.
- * Other parts of the kernel may not check if the zone is available.
+ * Allocate per cpu pagesets and initialize them.
+ * Before this call only boot pagesets were available.
+ * Boot pagesets will no longer be used by this processorr
+ * after setup_per_cpu_pageset().
  */
-static struct per_cpu_pageset boot_pageset[NR_CPUS];
-
-/*
- * Dynamically allocate memory for the
- * per cpu pageset array in struct zone.
- */
-static int __cpuinit process_zones(int cpu)
-{
-	struct zone *zone, *dzone;
-	int node = cpu_to_node(cpu);
-
-	node_set_state(node, N_CPU);	/* this node has a cpu */
-
-	for_each_populated_zone(zone) {
-		zone_pcp(zone, cpu) = kmalloc_node(sizeof(struct per_cpu_pageset),
-					 GFP_KERNEL, node);
-		if (!zone_pcp(zone, cpu))
-			goto bad;
-
-		setup_pageset(zone_pcp(zone, cpu), zone_batchsize(zone));
-
-		if (percpu_pagelist_fraction)
-			setup_pagelist_highmark(zone_pcp(zone, cpu),
-			    (zone->present_pages / percpu_pagelist_fraction));
-	}
-
-	return 0;
-bad:
-	for_each_zone(dzone) {
-		if (!populated_zone(dzone))
-			continue;
-		if (dzone == zone)
-			break;
-		kfree(zone_pcp(dzone, cpu));
-		zone_pcp(dzone, cpu) = &boot_pageset[cpu];
-	}
-	return -ENOMEM;
-}
-
-static inline void free_zone_pagesets(int cpu)
-{
-	struct zone *zone;
-
-	for_each_zone(zone) {
-		struct per_cpu_pageset *pset = zone_pcp(zone, cpu);
-
-		/* Free per_cpu_pageset if it is slab allocated */
-		if (pset != &boot_pageset[cpu])
-			kfree(pset);
-		zone_pcp(zone, cpu) = &boot_pageset[cpu];
-	}
-}
-
-static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb,
-		unsigned long action,
-		void *hcpu)
-{
-	int cpu = (long)hcpu;
-	int ret = NOTIFY_OK;
-
-	switch (action) {
-	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
-		if (process_zones(cpu))
-			ret = NOTIFY_BAD;
-		break;
-	case CPU_UP_CANCELED:
-	case CPU_UP_CANCELED_FROZEN:
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		free_zone_pagesets(cpu);
-		break;
-	default:
-		break;
-	}
-	return ret;
-}
-
-static struct notifier_block __cpuinitdata pageset_notifier =
-	{ &pageset_cpuup_callback, NULL, 0 };
-
 void __init setup_per_cpu_pageset(void)
 {
-	int err;
+	struct zone *zone;
+	int cpu;
 
-	/* Initialize per_cpu_pageset for cpu 0.
-	 * A cpuup callback will do this for every cpu
-	 * as it comes online
-	 */
-	err = process_zones(smp_processor_id());
-	BUG_ON(err);
-	register_cpu_notifier(&pageset_notifier);
+	for_each_populated_zone(zone) {
+		zone->pageset = alloc_percpu(struct per_cpu_pageset);
+
+		for_each_possible_cpu(cpu) {
+			struct per_cpu_pageset *pcp = per_cpu_ptr(zone->pageset, cpu);
+
+			setup_pageset(pcp, zone_batchsize(zone));
+
+			if (percpu_pagelist_fraction)
+				setup_pagelist_highmark(pcp,
+					(zone->present_pages /
+						percpu_pagelist_fraction));
+		}
+	}
 }
 
-#endif
-
 static noinline __init_refok
 int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
 {
@@ -3260,11 +3222,11 @@
 	int cpu;
 	unsigned long batch = zone_batchsize(zone), flags;
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+	for_each_possible_cpu(cpu) {
 		struct per_cpu_pageset *pset;
 		struct per_cpu_pages *pcp;
 
-		pset = zone_pcp(zone, cpu);
+		pset = per_cpu_ptr(zone->pageset, cpu);
 		pcp = &pset->pcp;
 
 		local_irq_save(flags);
@@ -3282,21 +3244,17 @@
 
 static __meminit void zone_pcp_init(struct zone *zone)
 {
-	int cpu;
-	unsigned long batch = zone_batchsize(zone);
+	/*
+	 * per cpu subsystem is not up at this point. The following code
+	 * relies on the ability of the linker to provide the
+	 * offset of a (static) per cpu variable into the per cpu area.
+	 */
+	zone->pageset = &boot_pageset;
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
-#ifdef CONFIG_NUMA
-		/* Early boot. Slab allocator not functional yet */
-		zone_pcp(zone, cpu) = &boot_pageset[cpu];
-		setup_pageset(&boot_pageset[cpu],0);
-#else
-		setup_pageset(zone_pcp(zone,cpu), batch);
-#endif
-	}
 	if (zone->present_pages)
-		printk(KERN_DEBUG "  %s zone: %lu pages, LIFO batch:%lu\n",
-			zone->name, zone->present_pages, batch);
+		printk(KERN_DEBUG "  %s zone: %lu pages, LIFO batch:%u\n",
+			zone->name, zone->present_pages,
+					 zone_batchsize(zone));
 }
 
 __meminit int init_currently_empty_zone(struct zone *zone,
@@ -3435,6 +3393,61 @@
 	}
 }
 
+int __init add_from_early_node_map(struct range *range, int az,
+				   int nr_range, int nid)
+{
+	int i;
+	u64 start, end;
+
+	/* need to go over early_node_map to find out good range for node */
+	for_each_active_range_index_in_nid(i, nid) {
+		start = early_node_map[i].start_pfn;
+		end = early_node_map[i].end_pfn;
+		nr_range = add_range(range, az, nr_range, start, end);
+	}
+	return nr_range;
+}
+
+#ifdef CONFIG_NO_BOOTMEM
+void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
+					u64 goal, u64 limit)
+{
+	int i;
+	void *ptr;
+
+	/* need to go over early_node_map to find out good range for node */
+	for_each_active_range_index_in_nid(i, nid) {
+		u64 addr;
+		u64 ei_start, ei_last;
+
+		ei_last = early_node_map[i].end_pfn;
+		ei_last <<= PAGE_SHIFT;
+		ei_start = early_node_map[i].start_pfn;
+		ei_start <<= PAGE_SHIFT;
+		addr = find_early_area(ei_start, ei_last,
+					 goal, limit, size, align);
+
+		if (addr == -1ULL)
+			continue;
+
+#if 0
+		printk(KERN_DEBUG "alloc (nid=%d %llx - %llx) (%llx - %llx) %llx %llx => %llx\n",
+				nid,
+				ei_start, ei_last, goal, limit, size,
+				align, addr);
+#endif
+
+		ptr = phys_to_virt(addr);
+		memset(ptr, 0, size);
+		reserve_early_without_check(addr, addr + size, "BOOTMEM");
+		return ptr;
+	}
+
+	return NULL;
+}
+#endif
+
+
 void __init work_with_active_regions(int nid, work_fn_t work_fn, void *data)
 {
 	int i;
@@ -4377,8 +4390,12 @@
 	for (i = 0; i < MAX_NR_ZONES; i++) {
 		if (i == ZONE_MOVABLE)
 			continue;
-		printk("  %-8s %0#10lx -> %0#10lx\n",
-				zone_names[i],
+		printk("  %-8s ", zone_names[i]);
+		if (arch_zone_lowest_possible_pfn[i] ==
+				arch_zone_highest_possible_pfn[i])
+			printk("empty\n");
+		else
+			printk("%0#10lx -> %0#10lx\n",
 				arch_zone_lowest_possible_pfn[i],
 				arch_zone_highest_possible_pfn[i]);
 	}
@@ -4467,7 +4484,11 @@
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-struct pglist_data __refdata contig_page_data = { .bdata = &bootmem_node_data[0] };
+struct pglist_data __refdata contig_page_data = {
+#ifndef CONFIG_NO_BOOTMEM
+ .bdata = &bootmem_node_data[0]
+#endif
+ };
 EXPORT_SYMBOL(contig_page_data);
 #endif
 
@@ -4810,10 +4831,11 @@
 	if (!write || (ret == -EINVAL))
 		return ret;
 	for_each_populated_zone(zone) {
-		for_each_online_cpu(cpu) {
+		for_each_possible_cpu(cpu) {
 			unsigned long  high;
 			high = zone->present_pages / percpu_pagelist_fraction;
-			setup_pagelist_highmark(zone_pcp(zone, cpu), high);
+			setup_pagelist_highmark(
+				per_cpu_ptr(zone->pageset, cpu), high);
 		}
 	}
 	return 0;
@@ -5159,3 +5181,80 @@
 	return order < MAX_ORDER;
 }
 #endif
+
+static struct trace_print_flags pageflag_names[] = {
+	{1UL << PG_locked,		"locked"	},
+	{1UL << PG_error,		"error"		},
+	{1UL << PG_referenced,		"referenced"	},
+	{1UL << PG_uptodate,		"uptodate"	},
+	{1UL << PG_dirty,		"dirty"		},
+	{1UL << PG_lru,			"lru"		},
+	{1UL << PG_active,		"active"	},
+	{1UL << PG_slab,		"slab"		},
+	{1UL << PG_owner_priv_1,	"owner_priv_1"	},
+	{1UL << PG_arch_1,		"arch_1"	},
+	{1UL << PG_reserved,		"reserved"	},
+	{1UL << PG_private,		"private"	},
+	{1UL << PG_private_2,		"private_2"	},
+	{1UL << PG_writeback,		"writeback"	},
+#ifdef CONFIG_PAGEFLAGS_EXTENDED
+	{1UL << PG_head,		"head"		},
+	{1UL << PG_tail,		"tail"		},
+#else
+	{1UL << PG_compound,		"compound"	},
+#endif
+	{1UL << PG_swapcache,		"swapcache"	},
+	{1UL << PG_mappedtodisk,	"mappedtodisk"	},
+	{1UL << PG_reclaim,		"reclaim"	},
+	{1UL << PG_buddy,		"buddy"		},
+	{1UL << PG_swapbacked,		"swapbacked"	},
+	{1UL << PG_unevictable,		"unevictable"	},
+#ifdef CONFIG_MMU
+	{1UL << PG_mlocked,		"mlocked"	},
+#endif
+#ifdef CONFIG_ARCH_USES_PG_UNCACHED
+	{1UL << PG_uncached,		"uncached"	},
+#endif
+#ifdef CONFIG_MEMORY_FAILURE
+	{1UL << PG_hwpoison,		"hwpoison"	},
+#endif
+	{-1UL,				NULL		},
+};
+
+static void dump_page_flags(unsigned long flags)
+{
+	const char *delim = "";
+	unsigned long mask;
+	int i;
+
+	printk(KERN_ALERT "page flags: %#lx(", flags);
+
+	/* remove zone id */
+	flags &= (1UL << NR_PAGEFLAGS) - 1;
+
+	for (i = 0; pageflag_names[i].name && flags; i++) {
+
+		mask = pageflag_names[i].mask;
+		if ((flags & mask) != mask)
+			continue;
+
+		flags &= ~mask;
+		printk("%s%s", delim, pageflag_names[i].name);
+		delim = "|";
+	}
+
+	/* check for left over flags */
+	if (flags)
+		printk("%s%#lx", delim, flags);
+
+	printk(")\n");
+}
+
+void dump_page(struct page *page)
+{
+	printk(KERN_ALERT
+	       "page:%p count:%d mapcount:%d mapping:%p index:%#lx\n",
+		page, page_count(page), page_mapcount(page),
+		page->mapping, page->index);
+	dump_page_flags(page->flags);
+}
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c
index 3d535d5..3dd8853 100644
--- a/mm/page_cgroup.c
+++ b/mm/page_cgroup.c
@@ -335,6 +335,37 @@
 }
 
 /**
+ * swap_cgroup_cmpxchg - cmpxchg mem_cgroup's id for this swp_entry.
+ * @end: swap entry to be cmpxchged
+ * @old: old id
+ * @new: new id
+ *
+ * Returns old id at success, 0 at failure.
+ * (There is no mem_cgroup useing 0 as its id)
+ */
+unsigned short swap_cgroup_cmpxchg(swp_entry_t ent,
+					unsigned short old, unsigned short new)
+{
+	int type = swp_type(ent);
+	unsigned long offset = swp_offset(ent);
+	unsigned long idx = offset / SC_PER_PAGE;
+	unsigned long pos = offset & SC_POS_MASK;
+	struct swap_cgroup_ctrl *ctrl;
+	struct page *mappage;
+	struct swap_cgroup *sc;
+
+	ctrl = &swap_cgroup_ctrl[type];
+
+	mappage = ctrl->map[idx];
+	sc = page_address(mappage);
+	sc += pos;
+	if (cmpxchg(&sc->id, old, new) == old)
+		return old;
+	else
+		return 0;
+}
+
+/**
  * swap_cgroup_record - record mem_cgroup for this swp_entry.
  * @ent: swap entry to be recorded into
  * @mem: mem_cgroup to be recorded
@@ -358,8 +389,7 @@
 	mappage = ctrl->map[idx];
 	sc = page_address(mappage);
 	sc += pos;
-	old = sc->id;
-	sc->id = id;
+	old = xchg(&sc->id, id);
 
 	return old;
 }
diff --git a/mm/percpu.c b/mm/percpu.c
index 083e7c9..768419d 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -80,13 +80,15 @@
 /* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */
 #ifndef __addr_to_pcpu_ptr
 #define __addr_to_pcpu_ptr(addr)					\
-	(void *)((unsigned long)(addr) - (unsigned long)pcpu_base_addr	\
-		 + (unsigned long)__per_cpu_start)
+	(void __percpu *)((unsigned long)(addr) -			\
+			  (unsigned long)pcpu_base_addr	+		\
+			  (unsigned long)__per_cpu_start)
 #endif
 #ifndef __pcpu_ptr_to_addr
 #define __pcpu_ptr_to_addr(ptr)						\
-	(void *)((unsigned long)(ptr) + (unsigned long)pcpu_base_addr	\
-		 - (unsigned long)__per_cpu_start)
+	(void __force *)((unsigned long)(ptr) +				\
+			 (unsigned long)pcpu_base_addr -		\
+			 (unsigned long)__per_cpu_start)
 #endif
 
 struct pcpu_chunk {
@@ -913,11 +915,10 @@
 	int rs, re;
 
 	/* quick path, check whether it's empty already */
-	pcpu_for_each_unpop_region(chunk, rs, re, page_start, page_end) {
-		if (rs == page_start && re == page_end)
-			return;
-		break;
-	}
+	rs = page_start;
+	pcpu_next_unpop(chunk, &rs, &re, page_end);
+	if (rs == page_start && re == page_end)
+		return;
 
 	/* immutable chunks can't be depopulated */
 	WARN_ON(chunk->immutable);
@@ -968,11 +969,10 @@
 	int rs, re, rc;
 
 	/* quick path, check whether all pages are already there */
-	pcpu_for_each_pop_region(chunk, rs, re, page_start, page_end) {
-		if (rs == page_start && re == page_end)
-			goto clear;
-		break;
-	}
+	rs = page_start;
+	pcpu_next_pop(chunk, &rs, &re, page_end);
+	if (rs == page_start && re == page_end)
+		goto clear;
 
 	/* need to allocate and map pages, this chunk can't be immutable */
 	WARN_ON(chunk->immutable);
@@ -1067,7 +1067,7 @@
  * RETURNS:
  * Percpu pointer to the allocated area on success, NULL on failure.
  */
-static void *pcpu_alloc(size_t size, size_t align, bool reserved)
+static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved)
 {
 	static int warn_limit = 10;
 	struct pcpu_chunk *chunk;
@@ -1196,7 +1196,7 @@
  * RETURNS:
  * Percpu pointer to the allocated area on success, NULL on failure.
  */
-void *__alloc_percpu(size_t size, size_t align)
+void __percpu *__alloc_percpu(size_t size, size_t align)
 {
 	return pcpu_alloc(size, align, false);
 }
@@ -1217,7 +1217,7 @@
  * RETURNS:
  * Percpu pointer to the allocated area on success, NULL on failure.
  */
-void *__alloc_reserved_percpu(size_t size, size_t align)
+void __percpu *__alloc_reserved_percpu(size_t size, size_t align)
 {
 	return pcpu_alloc(size, align, true);
 }
@@ -1269,7 +1269,7 @@
  * CONTEXT:
  * Can be called from atomic context.
  */
-void free_percpu(void *ptr)
+void free_percpu(void __percpu *ptr)
 {
 	void *addr;
 	struct pcpu_chunk *chunk;
diff --git a/mm/readahead.c b/mm/readahead.c
index 033bc13..337b20e 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -501,6 +501,12 @@
 	if (!ra->ra_pages)
 		return;
 
+	/* be dumb */
+	if (filp->f_mode & FMODE_RANDOM) {
+		force_page_cache_readahead(mapping, filp, offset, req_size);
+		return;
+	}
+
 	/* do read-ahead */
 	ondemand_readahead(mapping, ra, filp, false, offset, req_size);
 }
diff --git a/mm/rmap.c b/mm/rmap.c
index 278cd27..fcd593c9 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -62,6 +62,7 @@
 #include "internal.h"
 
 static struct kmem_cache *anon_vma_cachep;
+static struct kmem_cache *anon_vma_chain_cachep;
 
 static inline struct anon_vma *anon_vma_alloc(void)
 {
@@ -73,6 +74,16 @@
 	kmem_cache_free(anon_vma_cachep, anon_vma);
 }
 
+static inline struct anon_vma_chain *anon_vma_chain_alloc(void)
+{
+	return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL);
+}
+
+void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain)
+{
+	kmem_cache_free(anon_vma_chain_cachep, anon_vma_chain);
+}
+
 /**
  * anon_vma_prepare - attach an anon_vma to a memory region
  * @vma: the memory region in question
@@ -103,18 +114,23 @@
 int anon_vma_prepare(struct vm_area_struct *vma)
 {
 	struct anon_vma *anon_vma = vma->anon_vma;
+	struct anon_vma_chain *avc;
 
 	might_sleep();
 	if (unlikely(!anon_vma)) {
 		struct mm_struct *mm = vma->vm_mm;
 		struct anon_vma *allocated;
 
+		avc = anon_vma_chain_alloc();
+		if (!avc)
+			goto out_enomem;
+
 		anon_vma = find_mergeable_anon_vma(vma);
 		allocated = NULL;
 		if (!anon_vma) {
 			anon_vma = anon_vma_alloc();
 			if (unlikely(!anon_vma))
-				return -ENOMEM;
+				goto out_enomem_free_avc;
 			allocated = anon_vma;
 		}
 		spin_lock(&anon_vma->lock);
@@ -123,53 +139,113 @@
 		spin_lock(&mm->page_table_lock);
 		if (likely(!vma->anon_vma)) {
 			vma->anon_vma = anon_vma;
-			list_add_tail(&vma->anon_vma_node, &anon_vma->head);
+			avc->anon_vma = anon_vma;
+			avc->vma = vma;
+			list_add(&avc->same_vma, &vma->anon_vma_chain);
+			list_add(&avc->same_anon_vma, &anon_vma->head);
 			allocated = NULL;
 		}
 		spin_unlock(&mm->page_table_lock);
 
 		spin_unlock(&anon_vma->lock);
-		if (unlikely(allocated))
+		if (unlikely(allocated)) {
 			anon_vma_free(allocated);
+			anon_vma_chain_free(avc);
+		}
 	}
 	return 0;
+
+ out_enomem_free_avc:
+	anon_vma_chain_free(avc);
+ out_enomem:
+	return -ENOMEM;
 }
 
-void __anon_vma_merge(struct vm_area_struct *vma, struct vm_area_struct *next)
+static void anon_vma_chain_link(struct vm_area_struct *vma,
+				struct anon_vma_chain *avc,
+				struct anon_vma *anon_vma)
 {
-	BUG_ON(vma->anon_vma != next->anon_vma);
-	list_del(&next->anon_vma_node);
+	avc->vma = vma;
+	avc->anon_vma = anon_vma;
+	list_add(&avc->same_vma, &vma->anon_vma_chain);
+
+	spin_lock(&anon_vma->lock);
+	list_add_tail(&avc->same_anon_vma, &anon_vma->head);
+	spin_unlock(&anon_vma->lock);
 }
 
-void __anon_vma_link(struct vm_area_struct *vma)
+/*
+ * Attach the anon_vmas from src to dst.
+ * Returns 0 on success, -ENOMEM on failure.
+ */
+int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
 {
-	struct anon_vma *anon_vma = vma->anon_vma;
+	struct anon_vma_chain *avc, *pavc;
 
-	if (anon_vma)
-		list_add_tail(&vma->anon_vma_node, &anon_vma->head);
-}
-
-void anon_vma_link(struct vm_area_struct *vma)
-{
-	struct anon_vma *anon_vma = vma->anon_vma;
-
-	if (anon_vma) {
-		spin_lock(&anon_vma->lock);
-		list_add_tail(&vma->anon_vma_node, &anon_vma->head);
-		spin_unlock(&anon_vma->lock);
+	list_for_each_entry(pavc, &src->anon_vma_chain, same_vma) {
+		avc = anon_vma_chain_alloc();
+		if (!avc)
+			goto enomem_failure;
+		anon_vma_chain_link(dst, avc, pavc->anon_vma);
 	}
+	return 0;
+
+ enomem_failure:
+	unlink_anon_vmas(dst);
+	return -ENOMEM;
 }
 
-void anon_vma_unlink(struct vm_area_struct *vma)
+/*
+ * Attach vma to its own anon_vma, as well as to the anon_vmas that
+ * the corresponding VMA in the parent process is attached to.
+ * Returns 0 on success, non-zero on failure.
+ */
+int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
 {
-	struct anon_vma *anon_vma = vma->anon_vma;
+	struct anon_vma_chain *avc;
+	struct anon_vma *anon_vma;
+
+	/* Don't bother if the parent process has no anon_vma here. */
+	if (!pvma->anon_vma)
+		return 0;
+
+	/*
+	 * First, attach the new VMA to the parent VMA's anon_vmas,
+	 * so rmap can find non-COWed pages in child processes.
+	 */
+	if (anon_vma_clone(vma, pvma))
+		return -ENOMEM;
+
+	/* Then add our own anon_vma. */
+	anon_vma = anon_vma_alloc();
+	if (!anon_vma)
+		goto out_error;
+	avc = anon_vma_chain_alloc();
+	if (!avc)
+		goto out_error_free_anon_vma;
+	anon_vma_chain_link(vma, avc, anon_vma);
+	/* Mark this anon_vma as the one where our new (COWed) pages go. */
+	vma->anon_vma = anon_vma;
+
+	return 0;
+
+ out_error_free_anon_vma:
+	anon_vma_free(anon_vma);
+ out_error:
+	return -ENOMEM;
+}
+
+static void anon_vma_unlink(struct anon_vma_chain *anon_vma_chain)
+{
+	struct anon_vma *anon_vma = anon_vma_chain->anon_vma;
 	int empty;
 
+	/* If anon_vma_fork fails, we can get an empty anon_vma_chain. */
 	if (!anon_vma)
 		return;
 
 	spin_lock(&anon_vma->lock);
-	list_del(&vma->anon_vma_node);
+	list_del(&anon_vma_chain->same_anon_vma);
 
 	/* We must garbage collect the anon_vma if it's empty */
 	empty = list_empty(&anon_vma->head) && !ksm_refcount(anon_vma);
@@ -179,6 +255,18 @@
 		anon_vma_free(anon_vma);
 }
 
+void unlink_anon_vmas(struct vm_area_struct *vma)
+{
+	struct anon_vma_chain *avc, *next;
+
+	/* Unlink each anon_vma chained to the VMA. */
+	list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
+		anon_vma_unlink(avc);
+		list_del(&avc->same_vma);
+		anon_vma_chain_free(avc);
+	}
+}
+
 static void anon_vma_ctor(void *data)
 {
 	struct anon_vma *anon_vma = data;
@@ -192,6 +280,7 @@
 {
 	anon_vma_cachep = kmem_cache_create("anon_vma", sizeof(struct anon_vma),
 			0, SLAB_DESTROY_BY_RCU|SLAB_PANIC, anon_vma_ctor);
+	anon_vma_chain_cachep = KMEM_CACHE(anon_vma_chain, SLAB_PANIC);
 }
 
 /*
@@ -396,7 +485,7 @@
 {
 	unsigned int mapcount;
 	struct anon_vma *anon_vma;
-	struct vm_area_struct *vma;
+	struct anon_vma_chain *avc;
 	int referenced = 0;
 
 	anon_vma = page_lock_anon_vma(page);
@@ -404,7 +493,8 @@
 		return referenced;
 
 	mapcount = page_mapcount(page);
-	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+	list_for_each_entry(avc, &anon_vma->head, same_anon_vma) {
+		struct vm_area_struct *vma = avc->vma;
 		unsigned long address = vma_address(page, vma);
 		if (address == -EFAULT)
 			continue;
@@ -511,9 +601,6 @@
 	int referenced = 0;
 	int we_locked = 0;
 
-	if (TestClearPageReferenced(page))
-		referenced++;
-
 	*vm_flags = 0;
 	if (page_mapped(page) && page_rmapping(page)) {
 		if (!is_locked && (!PageAnon(page) || PageKsm(page))) {
@@ -614,6 +701,30 @@
 EXPORT_SYMBOL_GPL(page_mkclean);
 
 /**
+ * page_move_anon_rmap - move a page to our anon_vma
+ * @page:	the page to move to our anon_vma
+ * @vma:	the vma the page belongs to
+ * @address:	the user virtual address mapped
+ *
+ * When a page belongs exclusively to one process after a COW event,
+ * that page can be moved into the anon_vma that belongs to just that
+ * process, so the rmap code will not search the parent or sibling
+ * processes.
+ */
+void page_move_anon_rmap(struct page *page,
+	struct vm_area_struct *vma, unsigned long address)
+{
+	struct anon_vma *anon_vma = vma->anon_vma;
+
+	VM_BUG_ON(!PageLocked(page));
+	VM_BUG_ON(!anon_vma);
+	VM_BUG_ON(page->index != linear_page_index(vma, address));
+
+	anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
+	page->mapping = (struct address_space *) anon_vma;
+}
+
+/**
  * __page_set_anon_rmap - setup new anonymous rmap
  * @page:	the page to add the mapping to
  * @vma:	the vm area in which the mapping is added
@@ -652,9 +763,6 @@
 	 * are initially only visible via the pagetables, and the pte is locked
 	 * over the call to page_add_new_anon_rmap.
 	 */
-	struct anon_vma *anon_vma = vma->anon_vma;
-	anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
-	BUG_ON(page->mapping != (struct address_space *)anon_vma);
 	BUG_ON(page->index != linear_page_index(vma, address));
 #endif
 }
@@ -815,9 +923,9 @@
 
 	if (PageHWPoison(page) && !(flags & TTU_IGNORE_HWPOISON)) {
 		if (PageAnon(page))
-			dec_mm_counter(mm, anon_rss);
+			dec_mm_counter(mm, MM_ANONPAGES);
 		else
-			dec_mm_counter(mm, file_rss);
+			dec_mm_counter(mm, MM_FILEPAGES);
 		set_pte_at(mm, address, pte,
 				swp_entry_to_pte(make_hwpoison_entry(page)));
 	} else if (PageAnon(page)) {
@@ -839,7 +947,8 @@
 					list_add(&mm->mmlist, &init_mm.mmlist);
 				spin_unlock(&mmlist_lock);
 			}
-			dec_mm_counter(mm, anon_rss);
+			dec_mm_counter(mm, MM_ANONPAGES);
+			inc_mm_counter(mm, MM_SWAPENTS);
 		} else if (PAGE_MIGRATION) {
 			/*
 			 * Store the pfn of the page in a special migration
@@ -857,7 +966,7 @@
 		entry = make_migration_entry(page, pte_write(pteval));
 		set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
 	} else
-		dec_mm_counter(mm, file_rss);
+		dec_mm_counter(mm, MM_FILEPAGES);
 
 	page_remove_rmap(page);
 	page_cache_release(page);
@@ -996,7 +1105,7 @@
 
 		page_remove_rmap(page);
 		page_cache_release(page);
-		dec_mm_counter(mm, file_rss);
+		dec_mm_counter(mm, MM_FILEPAGES);
 		(*mapcount)--;
 	}
 	pte_unmap_unlock(pte - 1, ptl);
@@ -1024,14 +1133,15 @@
 static int try_to_unmap_anon(struct page *page, enum ttu_flags flags)
 {
 	struct anon_vma *anon_vma;
-	struct vm_area_struct *vma;
+	struct anon_vma_chain *avc;
 	int ret = SWAP_AGAIN;
 
 	anon_vma = page_lock_anon_vma(page);
 	if (!anon_vma)
 		return ret;
 
-	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+	list_for_each_entry(avc, &anon_vma->head, same_anon_vma) {
+		struct vm_area_struct *vma = avc->vma;
 		unsigned long address = vma_address(page, vma);
 		if (address == -EFAULT)
 			continue;
@@ -1222,7 +1332,7 @@
 		struct vm_area_struct *, unsigned long, void *), void *arg)
 {
 	struct anon_vma *anon_vma;
-	struct vm_area_struct *vma;
+	struct anon_vma_chain *avc;
 	int ret = SWAP_AGAIN;
 
 	/*
@@ -1237,7 +1347,8 @@
 	if (!anon_vma)
 		return ret;
 	spin_lock(&anon_vma->lock);
-	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+	list_for_each_entry(avc, &anon_vma->head, same_anon_vma) {
+		struct vm_area_struct *vma = avc->vma;
 		unsigned long address = vma_address(page, vma);
 		if (address == -EFAULT)
 			continue;
diff --git a/mm/slab.c b/mm/slab.c
index 7451bda..a9f325b 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -935,7 +935,6 @@
 
 	from->avail -= nr;
 	to->avail += nr;
-	to->touched = 1;
 	return nr;
 }
 
@@ -983,13 +982,11 @@
 
 	if (limit > 1)
 		limit = 12;
-	ac_ptr = kmalloc_node(memsize, gfp, node);
+	ac_ptr = kzalloc_node(memsize, gfp, node);
 	if (ac_ptr) {
 		for_each_node(i) {
-			if (i == node || !node_online(i)) {
-				ac_ptr[i] = NULL;
+			if (i == node || !node_online(i))
 				continue;
-			}
 			ac_ptr[i] = alloc_arraycache(node, limit, 0xbaadf00d, gfp);
 			if (!ac_ptr[i]) {
 				for (i--; i >= 0; i--)
@@ -2963,8 +2960,10 @@
 	spin_lock(&l3->list_lock);
 
 	/* See if we can refill from the shared array */
-	if (l3->shared && transfer_objects(ac, l3->shared, batchcount))
+	if (l3->shared && transfer_objects(ac, l3->shared, batchcount)) {
+		l3->shared->touched = 1;
 		goto alloc_done;
+	}
 
 	while (batchcount > 0) {
 		struct list_head *entry;
@@ -3101,7 +3100,7 @@
 	if (cachep == &cache_cache)
 		return false;
 
-	return should_failslab(obj_size(cachep), flags);
+	return should_failslab(obj_size(cachep), flags, cachep->flags);
 }
 
 static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
diff --git a/mm/slub.c b/mm/slub.c
index 8d71aaf..b364844 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -151,7 +151,8 @@
  * Set of flags that will prevent slab merging
  */
 #define SLUB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
-		SLAB_TRACE | SLAB_DESTROY_BY_RCU | SLAB_NOLEAKTRACE)
+		SLAB_TRACE | SLAB_DESTROY_BY_RCU | SLAB_NOLEAKTRACE | \
+		SLAB_FAILSLAB)
 
 #define SLUB_MERGE_SAME (SLAB_DEBUG_FREE | SLAB_RECLAIM_ACCOUNT | \
 		SLAB_CACHE_DMA | SLAB_NOTRACK)
@@ -217,10 +218,10 @@
 
 #endif
 
-static inline void stat(struct kmem_cache_cpu *c, enum stat_item si)
+static inline void stat(struct kmem_cache *s, enum stat_item si)
 {
 #ifdef CONFIG_SLUB_STATS
-	c->stat[si]++;
+	__this_cpu_inc(s->cpu_slab->stat[si]);
 #endif
 }
 
@@ -242,15 +243,6 @@
 #endif
 }
 
-static inline struct kmem_cache_cpu *get_cpu_slab(struct kmem_cache *s, int cpu)
-{
-#ifdef CONFIG_SMP
-	return s->cpu_slab[cpu];
-#else
-	return &s->cpu_slab;
-#endif
-}
-
 /* Verify that a pointer has an address that is valid within a slab page */
 static inline int check_valid_pointer(struct kmem_cache *s,
 				struct page *page, const void *object)
@@ -269,13 +261,6 @@
 	return 1;
 }
 
-/*
- * Slow version of get and set free pointer.
- *
- * This version requires touching the cache lines of kmem_cache which
- * we avoid to do in the fast alloc free paths. There we obtain the offset
- * from the page struct.
- */
 static inline void *get_freepointer(struct kmem_cache *s, void *object)
 {
 	return *(void **)(object + s->offset);
@@ -1020,6 +1005,9 @@
 		case 't':
 			slub_debug |= SLAB_TRACE;
 			break;
+		case 'a':
+			slub_debug |= SLAB_FAILSLAB;
+			break;
 		default:
 			printk(KERN_ERR "slub_debug option '%c' "
 				"unknown. skipped\n", *str);
@@ -1124,7 +1112,7 @@
 		if (!page)
 			return NULL;
 
-		stat(get_cpu_slab(s, raw_smp_processor_id()), ORDER_FALLBACK);
+		stat(s, ORDER_FALLBACK);
 	}
 
 	if (kmemcheck_enabled
@@ -1422,23 +1410,22 @@
 static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
 {
 	struct kmem_cache_node *n = get_node(s, page_to_nid(page));
-	struct kmem_cache_cpu *c = get_cpu_slab(s, smp_processor_id());
 
 	__ClearPageSlubFrozen(page);
 	if (page->inuse) {
 
 		if (page->freelist) {
 			add_partial(n, page, tail);
-			stat(c, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD);
+			stat(s, tail ? DEACTIVATE_TO_TAIL : DEACTIVATE_TO_HEAD);
 		} else {
-			stat(c, DEACTIVATE_FULL);
+			stat(s, DEACTIVATE_FULL);
 			if (SLABDEBUG && PageSlubDebug(page) &&
 						(s->flags & SLAB_STORE_USER))
 				add_full(n, page);
 		}
 		slab_unlock(page);
 	} else {
-		stat(c, DEACTIVATE_EMPTY);
+		stat(s, DEACTIVATE_EMPTY);
 		if (n->nr_partial < s->min_partial) {
 			/*
 			 * Adding an empty slab to the partial slabs in order
@@ -1454,7 +1441,7 @@
 			slab_unlock(page);
 		} else {
 			slab_unlock(page);
-			stat(get_cpu_slab(s, raw_smp_processor_id()), FREE_SLAB);
+			stat(s, FREE_SLAB);
 			discard_slab(s, page);
 		}
 	}
@@ -1469,7 +1456,7 @@
 	int tail = 1;
 
 	if (page->freelist)
-		stat(c, DEACTIVATE_REMOTE_FREES);
+		stat(s, DEACTIVATE_REMOTE_FREES);
 	/*
 	 * Merge cpu freelist into slab freelist. Typically we get here
 	 * because both freelists are empty. So this is unlikely
@@ -1482,10 +1469,10 @@
 
 		/* Retrieve object from cpu_freelist */
 		object = c->freelist;
-		c->freelist = c->freelist[c->offset];
+		c->freelist = get_freepointer(s, c->freelist);
 
 		/* And put onto the regular freelist */
-		object[c->offset] = page->freelist;
+		set_freepointer(s, object, page->freelist);
 		page->freelist = object;
 		page->inuse--;
 	}
@@ -1495,7 +1482,7 @@
 
 static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
 {
-	stat(c, CPUSLAB_FLUSH);
+	stat(s, CPUSLAB_FLUSH);
 	slab_lock(c->page);
 	deactivate_slab(s, c);
 }
@@ -1507,7 +1494,7 @@
  */
 static inline void __flush_cpu_slab(struct kmem_cache *s, int cpu)
 {
-	struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+	struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu);
 
 	if (likely(c && c->page))
 		flush_slab(s, c);
@@ -1635,7 +1622,7 @@
 	if (unlikely(!node_match(c, node)))
 		goto another_slab;
 
-	stat(c, ALLOC_REFILL);
+	stat(s, ALLOC_REFILL);
 
 load_freelist:
 	object = c->page->freelist;
@@ -1644,13 +1631,13 @@
 	if (unlikely(SLABDEBUG && PageSlubDebug(c->page)))
 		goto debug;
 
-	c->freelist = object[c->offset];
+	c->freelist = get_freepointer(s, object);
 	c->page->inuse = c->page->objects;
 	c->page->freelist = NULL;
 	c->node = page_to_nid(c->page);
 unlock_out:
 	slab_unlock(c->page);
-	stat(c, ALLOC_SLOWPATH);
+	stat(s, ALLOC_SLOWPATH);
 	return object;
 
 another_slab:
@@ -1660,7 +1647,7 @@
 	new = get_partial(s, gfpflags, node);
 	if (new) {
 		c->page = new;
-		stat(c, ALLOC_FROM_PARTIAL);
+		stat(s, ALLOC_FROM_PARTIAL);
 		goto load_freelist;
 	}
 
@@ -1673,8 +1660,8 @@
 		local_irq_disable();
 
 	if (new) {
-		c = get_cpu_slab(s, smp_processor_id());
-		stat(c, ALLOC_SLAB);
+		c = __this_cpu_ptr(s->cpu_slab);
+		stat(s, ALLOC_SLAB);
 		if (c->page)
 			flush_slab(s, c);
 		slab_lock(new);
@@ -1690,7 +1677,7 @@
 		goto another_slab;
 
 	c->page->inuse++;
-	c->page->freelist = object[c->offset];
+	c->page->freelist = get_freepointer(s, object);
 	c->node = -1;
 	goto unlock_out;
 }
@@ -1711,35 +1698,33 @@
 	void **object;
 	struct kmem_cache_cpu *c;
 	unsigned long flags;
-	unsigned int objsize;
 
 	gfpflags &= gfp_allowed_mask;
 
 	lockdep_trace_alloc(gfpflags);
 	might_sleep_if(gfpflags & __GFP_WAIT);
 
-	if (should_failslab(s->objsize, gfpflags))
+	if (should_failslab(s->objsize, gfpflags, s->flags))
 		return NULL;
 
 	local_irq_save(flags);
-	c = get_cpu_slab(s, smp_processor_id());
-	objsize = c->objsize;
-	if (unlikely(!c->freelist || !node_match(c, node)))
+	c = __this_cpu_ptr(s->cpu_slab);
+	object = c->freelist;
+	if (unlikely(!object || !node_match(c, node)))
 
 		object = __slab_alloc(s, gfpflags, node, addr, c);
 
 	else {
-		object = c->freelist;
-		c->freelist = object[c->offset];
-		stat(c, ALLOC_FASTPATH);
+		c->freelist = get_freepointer(s, object);
+		stat(s, ALLOC_FASTPATH);
 	}
 	local_irq_restore(flags);
 
 	if (unlikely(gfpflags & __GFP_ZERO) && object)
-		memset(object, 0, objsize);
+		memset(object, 0, s->objsize);
 
-	kmemcheck_slab_alloc(s, gfpflags, object, c->objsize);
-	kmemleak_alloc_recursive(object, objsize, 1, s->flags, gfpflags);
+	kmemcheck_slab_alloc(s, gfpflags, object, s->objsize);
+	kmemleak_alloc_recursive(object, s->objsize, 1, s->flags, gfpflags);
 
 	return object;
 }
@@ -1794,26 +1779,25 @@
  * handling required then we can return immediately.
  */
 static void __slab_free(struct kmem_cache *s, struct page *page,
-			void *x, unsigned long addr, unsigned int offset)
+			void *x, unsigned long addr)
 {
 	void *prior;
 	void **object = (void *)x;
-	struct kmem_cache_cpu *c;
 
-	c = get_cpu_slab(s, raw_smp_processor_id());
-	stat(c, FREE_SLOWPATH);
+	stat(s, FREE_SLOWPATH);
 	slab_lock(page);
 
 	if (unlikely(SLABDEBUG && PageSlubDebug(page)))
 		goto debug;
 
 checks_ok:
-	prior = object[offset] = page->freelist;
+	prior = page->freelist;
+	set_freepointer(s, object, prior);
 	page->freelist = object;
 	page->inuse--;
 
 	if (unlikely(PageSlubFrozen(page))) {
-		stat(c, FREE_FROZEN);
+		stat(s, FREE_FROZEN);
 		goto out_unlock;
 	}
 
@@ -1826,7 +1810,7 @@
 	 */
 	if (unlikely(!prior)) {
 		add_partial(get_node(s, page_to_nid(page)), page, 1);
-		stat(c, FREE_ADD_PARTIAL);
+		stat(s, FREE_ADD_PARTIAL);
 	}
 
 out_unlock:
@@ -1839,10 +1823,10 @@
 		 * Slab still on the partial list.
 		 */
 		remove_partial(s, page);
-		stat(c, FREE_REMOVE_PARTIAL);
+		stat(s, FREE_REMOVE_PARTIAL);
 	}
 	slab_unlock(page);
-	stat(c, FREE_SLAB);
+	stat(s, FREE_SLAB);
 	discard_slab(s, page);
 	return;
 
@@ -1872,17 +1856,17 @@
 
 	kmemleak_free_recursive(x, s->flags);
 	local_irq_save(flags);
-	c = get_cpu_slab(s, smp_processor_id());
-	kmemcheck_slab_free(s, object, c->objsize);
-	debug_check_no_locks_freed(object, c->objsize);
+	c = __this_cpu_ptr(s->cpu_slab);
+	kmemcheck_slab_free(s, object, s->objsize);
+	debug_check_no_locks_freed(object, s->objsize);
 	if (!(s->flags & SLAB_DEBUG_OBJECTS))
-		debug_check_no_obj_freed(object, c->objsize);
+		debug_check_no_obj_freed(object, s->objsize);
 	if (likely(page == c->page && c->node >= 0)) {
-		object[c->offset] = c->freelist;
+		set_freepointer(s, object, c->freelist);
 		c->freelist = object;
-		stat(c, FREE_FASTPATH);
+		stat(s, FREE_FASTPATH);
 	} else
-		__slab_free(s, page, x, addr, c->offset);
+		__slab_free(s, page, x, addr);
 
 	local_irq_restore(flags);
 }
@@ -2069,19 +2053,6 @@
 	return ALIGN(align, sizeof(void *));
 }
 
-static void init_kmem_cache_cpu(struct kmem_cache *s,
-			struct kmem_cache_cpu *c)
-{
-	c->page = NULL;
-	c->freelist = NULL;
-	c->node = 0;
-	c->offset = s->offset / sizeof(void *);
-	c->objsize = s->objsize;
-#ifdef CONFIG_SLUB_STATS
-	memset(c->stat, 0, NR_SLUB_STAT_ITEMS * sizeof(unsigned));
-#endif
-}
-
 static void
 init_kmem_cache_node(struct kmem_cache_node *n, struct kmem_cache *s)
 {
@@ -2095,130 +2066,24 @@
 #endif
 }
 
-#ifdef CONFIG_SMP
-/*
- * Per cpu array for per cpu structures.
- *
- * The per cpu array places all kmem_cache_cpu structures from one processor
- * close together meaning that it becomes possible that multiple per cpu
- * structures are contained in one cacheline. This may be particularly
- * beneficial for the kmalloc caches.
- *
- * A desktop system typically has around 60-80 slabs. With 100 here we are
- * likely able to get per cpu structures for all caches from the array defined
- * here. We must be able to cover all kmalloc caches during bootstrap.
- *
- * If the per cpu array is exhausted then fall back to kmalloc
- * of individual cachelines. No sharing is possible then.
- */
-#define NR_KMEM_CACHE_CPU 100
-
-static DEFINE_PER_CPU(struct kmem_cache_cpu [NR_KMEM_CACHE_CPU],
-		      kmem_cache_cpu);
-
-static DEFINE_PER_CPU(struct kmem_cache_cpu *, kmem_cache_cpu_free);
-static DECLARE_BITMAP(kmem_cach_cpu_free_init_once, CONFIG_NR_CPUS);
-
-static struct kmem_cache_cpu *alloc_kmem_cache_cpu(struct kmem_cache *s,
-							int cpu, gfp_t flags)
-{
-	struct kmem_cache_cpu *c = per_cpu(kmem_cache_cpu_free, cpu);
-
-	if (c)
-		per_cpu(kmem_cache_cpu_free, cpu) =
-				(void *)c->freelist;
-	else {
-		/* Table overflow: So allocate ourselves */
-		c = kmalloc_node(
-			ALIGN(sizeof(struct kmem_cache_cpu), cache_line_size()),
-			flags, cpu_to_node(cpu));
-		if (!c)
-			return NULL;
-	}
-
-	init_kmem_cache_cpu(s, c);
-	return c;
-}
-
-static void free_kmem_cache_cpu(struct kmem_cache_cpu *c, int cpu)
-{
-	if (c < per_cpu(kmem_cache_cpu, cpu) ||
-			c >= per_cpu(kmem_cache_cpu, cpu) + NR_KMEM_CACHE_CPU) {
-		kfree(c);
-		return;
-	}
-	c->freelist = (void *)per_cpu(kmem_cache_cpu_free, cpu);
-	per_cpu(kmem_cache_cpu_free, cpu) = c;
-}
-
-static void free_kmem_cache_cpus(struct kmem_cache *s)
-{
-	int cpu;
-
-	for_each_online_cpu(cpu) {
-		struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
-
-		if (c) {
-			s->cpu_slab[cpu] = NULL;
-			free_kmem_cache_cpu(c, cpu);
-		}
-	}
-}
-
-static int alloc_kmem_cache_cpus(struct kmem_cache *s, gfp_t flags)
-{
-	int cpu;
-
-	for_each_online_cpu(cpu) {
-		struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
-
-		if (c)
-			continue;
-
-		c = alloc_kmem_cache_cpu(s, cpu, flags);
-		if (!c) {
-			free_kmem_cache_cpus(s);
-			return 0;
-		}
-		s->cpu_slab[cpu] = c;
-	}
-	return 1;
-}
-
-/*
- * Initialize the per cpu array.
- */
-static void init_alloc_cpu_cpu(int cpu)
-{
-	int i;
-
-	if (cpumask_test_cpu(cpu, to_cpumask(kmem_cach_cpu_free_init_once)))
-		return;
-
-	for (i = NR_KMEM_CACHE_CPU - 1; i >= 0; i--)
-		free_kmem_cache_cpu(&per_cpu(kmem_cache_cpu, cpu)[i], cpu);
-
-	cpumask_set_cpu(cpu, to_cpumask(kmem_cach_cpu_free_init_once));
-}
-
-static void __init init_alloc_cpu(void)
-{
-	int cpu;
-
-	for_each_online_cpu(cpu)
-		init_alloc_cpu_cpu(cpu);
-  }
-
-#else
-static inline void free_kmem_cache_cpus(struct kmem_cache *s) {}
-static inline void init_alloc_cpu(void) {}
+static DEFINE_PER_CPU(struct kmem_cache_cpu, kmalloc_percpu[KMALLOC_CACHES]);
 
 static inline int alloc_kmem_cache_cpus(struct kmem_cache *s, gfp_t flags)
 {
-	init_kmem_cache_cpu(s, &s->cpu_slab);
+	if (s < kmalloc_caches + KMALLOC_CACHES && s >= kmalloc_caches)
+		/*
+		 * Boot time creation of the kmalloc array. Use static per cpu data
+		 * since the per cpu allocator is not available yet.
+		 */
+		s->cpu_slab = kmalloc_percpu + (s - kmalloc_caches);
+	else
+		s->cpu_slab =  alloc_percpu(struct kmem_cache_cpu);
+
+	if (!s->cpu_slab)
+		return 0;
+
 	return 1;
 }
-#endif
 
 #ifdef CONFIG_NUMA
 /*
@@ -2287,7 +2152,8 @@
 	int node;
 	int local_node;
 
-	if (slab_state >= UP)
+	if (slab_state >= UP && (s < kmalloc_caches ||
+			s > kmalloc_caches + KMALLOC_CACHES))
 		local_node = page_to_nid(virt_to_page(s));
 	else
 		local_node = 0;
@@ -2502,6 +2368,7 @@
 
 	if (alloc_kmem_cache_cpus(s, gfpflags & ~SLUB_DMA))
 		return 1;
+
 	free_kmem_cache_nodes(s);
 error:
 	if (flags & SLAB_PANIC)
@@ -2609,9 +2476,8 @@
 	int node;
 
 	flush_all(s);
-
+	free_percpu(s->cpu_slab);
 	/* Attempt to free all objects */
-	free_kmem_cache_cpus(s);
 	for_each_node_state(node, N_NORMAL_MEMORY) {
 		struct kmem_cache_node *n = get_node(s, node);
 
@@ -2651,7 +2517,7 @@
  *		Kmalloc subsystem
  *******************************************************************/
 
-struct kmem_cache kmalloc_caches[SLUB_PAGE_SHIFT] __cacheline_aligned;
+struct kmem_cache kmalloc_caches[KMALLOC_CACHES] __cacheline_aligned;
 EXPORT_SYMBOL(kmalloc_caches);
 
 static int __init setup_slub_min_order(char *str)
@@ -2741,6 +2607,7 @@
 	char *text;
 	size_t realsize;
 	unsigned long slabflags;
+	int i;
 
 	s = kmalloc_caches_dma[index];
 	if (s)
@@ -2760,7 +2627,14 @@
 	realsize = kmalloc_caches[index].objsize;
 	text = kasprintf(flags & ~SLUB_DMA, "kmalloc_dma-%d",
 			 (unsigned int)realsize);
-	s = kmalloc(kmem_size, flags & ~SLUB_DMA);
+
+	s = NULL;
+	for (i = 0; i < KMALLOC_CACHES; i++)
+		if (!kmalloc_caches[i].size)
+			break;
+
+	BUG_ON(i >= KMALLOC_CACHES);
+	s = kmalloc_caches + i;
 
 	/*
 	 * Must defer sysfs creation to a workqueue because we don't know
@@ -2772,9 +2646,9 @@
 	if (slab_state >= SYSFS)
 		slabflags |= __SYSFS_ADD_DEFERRED;
 
-	if (!s || !text || !kmem_cache_open(s, flags, text,
+	if (!text || !kmem_cache_open(s, flags, text,
 			realsize, ARCH_KMALLOC_MINALIGN, slabflags, NULL)) {
-		kfree(s);
+		s->size = 0;
 		kfree(text);
 		goto unlock_out;
 	}
@@ -3086,7 +2960,7 @@
 			/*
 			 * if n->nr_slabs > 0, slabs still exist on the node
 			 * that is going down. We were unable to free them,
-			 * and offline_pages() function shoudn't call this
+			 * and offline_pages() function shouldn't call this
 			 * callback. So, we must fail.
 			 */
 			BUG_ON(slabs_node(s, offline_node));
@@ -3176,8 +3050,6 @@
 	int i;
 	int caches = 0;
 
-	init_alloc_cpu();
-
 #ifdef CONFIG_NUMA
 	/*
 	 * Must first have the slab cache available for the allocations of the
@@ -3261,8 +3133,10 @@
 
 #ifdef CONFIG_SMP
 	register_cpu_notifier(&slab_notifier);
-	kmem_size = offsetof(struct kmem_cache, cpu_slab) +
-				nr_cpu_ids * sizeof(struct kmem_cache_cpu *);
+#endif
+#ifdef CONFIG_NUMA
+	kmem_size = offsetof(struct kmem_cache, node) +
+				nr_node_ids * sizeof(struct kmem_cache_node *);
 #else
 	kmem_size = sizeof(struct kmem_cache);
 #endif
@@ -3351,22 +3225,12 @@
 	down_write(&slub_lock);
 	s = find_mergeable(size, align, flags, name, ctor);
 	if (s) {
-		int cpu;
-
 		s->refcount++;
 		/*
 		 * Adjust the object sizes so that we clear
 		 * the complete object on kzalloc.
 		 */
 		s->objsize = max(s->objsize, (int)size);
-
-		/*
-		 * And then we need to update the object size in the
-		 * per cpu structures
-		 */
-		for_each_online_cpu(cpu)
-			get_cpu_slab(s, cpu)->objsize = s->objsize;
-
 		s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *)));
 		up_write(&slub_lock);
 
@@ -3420,29 +3284,15 @@
 	unsigned long flags;
 
 	switch (action) {
-	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
-		init_alloc_cpu_cpu(cpu);
-		down_read(&slub_lock);
-		list_for_each_entry(s, &slab_caches, list)
-			s->cpu_slab[cpu] = alloc_kmem_cache_cpu(s, cpu,
-							GFP_KERNEL);
-		up_read(&slub_lock);
-		break;
-
 	case CPU_UP_CANCELED:
 	case CPU_UP_CANCELED_FROZEN:
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
 		down_read(&slub_lock);
 		list_for_each_entry(s, &slab_caches, list) {
-			struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
-
 			local_irq_save(flags);
 			__flush_cpu_slab(s, cpu);
 			local_irq_restore(flags);
-			free_kmem_cache_cpu(c, cpu);
-			s->cpu_slab[cpu] = NULL;
 		}
 		up_read(&slub_lock);
 		break;
@@ -3928,7 +3778,7 @@
 		int cpu;
 
 		for_each_possible_cpu(cpu) {
-			struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+			struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu);
 
 			if (!c || c->node < 0)
 				continue;
@@ -4171,6 +4021,23 @@
 }
 SLAB_ATTR(trace);
 
+#ifdef CONFIG_FAILSLAB
+static ssize_t failslab_show(struct kmem_cache *s, char *buf)
+{
+	return sprintf(buf, "%d\n", !!(s->flags & SLAB_FAILSLAB));
+}
+
+static ssize_t failslab_store(struct kmem_cache *s, const char *buf,
+							size_t length)
+{
+	s->flags &= ~SLAB_FAILSLAB;
+	if (buf[0] == '1')
+		s->flags |= SLAB_FAILSLAB;
+	return length;
+}
+SLAB_ATTR(failslab);
+#endif
+
 static ssize_t reclaim_account_show(struct kmem_cache *s, char *buf)
 {
 	return sprintf(buf, "%d\n", !!(s->flags & SLAB_RECLAIM_ACCOUNT));
@@ -4353,7 +4220,7 @@
 		return -ENOMEM;
 
 	for_each_online_cpu(cpu) {
-		unsigned x = get_cpu_slab(s, cpu)->stat[si];
+		unsigned x = per_cpu_ptr(s->cpu_slab, cpu)->stat[si];
 
 		data[cpu] = x;
 		sum += x;
@@ -4376,7 +4243,7 @@
 	int cpu;
 
 	for_each_online_cpu(cpu)
-		get_cpu_slab(s, cpu)->stat[si] = 0;
+		per_cpu_ptr(s->cpu_slab, cpu)->stat[si] = 0;
 }
 
 #define STAT_ATTR(si, text) 					\
@@ -4467,6 +4334,10 @@
 	&deactivate_remote_frees_attr.attr,
 	&order_fallback_attr.attr,
 #endif
+#ifdef CONFIG_FAILSLAB
+	&failslab_attr.attr,
+#endif
+
 	NULL
 };
 
@@ -4519,7 +4390,7 @@
 	kfree(s);
 }
 
-static struct sysfs_ops slab_sysfs_ops = {
+static const struct sysfs_ops slab_sysfs_ops = {
 	.show = slab_attr_show,
 	.store = slab_attr_store,
 };
@@ -4538,7 +4409,7 @@
 	return 0;
 }
 
-static struct kset_uevent_ops slab_uevent_ops = {
+static const struct kset_uevent_ops slab_uevent_ops = {
 	.filter = uevent_filter,
 };
 
diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index d9714bd..392b9bb 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -40,9 +40,11 @@
 				unsigned long align,
 				unsigned long goal)
 {
-	return __alloc_bootmem_node(NODE_DATA(node), size, align, goal);
+	return __alloc_bootmem_node_high(NODE_DATA(node), size, align, goal);
 }
 
+static void *vmemmap_buf;
+static void *vmemmap_buf_end;
 
 void * __meminit vmemmap_alloc_block(unsigned long size, int node)
 {
@@ -64,6 +66,24 @@
 				__pa(MAX_DMA_ADDRESS));
 }
 
+/* need to make sure size is all the same during early stage */
+void * __meminit vmemmap_alloc_block_buf(unsigned long size, int node)
+{
+	void *ptr;
+
+	if (!vmemmap_buf)
+		return vmemmap_alloc_block(size, node);
+
+	/* take the from buf */
+	ptr = (void *)ALIGN((unsigned long)vmemmap_buf, size);
+	if (ptr + size > vmemmap_buf_end)
+		return vmemmap_alloc_block(size, node);
+
+	vmemmap_buf = ptr + size;
+
+	return ptr;
+}
+
 void __meminit vmemmap_verify(pte_t *pte, int node,
 				unsigned long start, unsigned long end)
 {
@@ -80,7 +100,7 @@
 	pte_t *pte = pte_offset_kernel(pmd, addr);
 	if (pte_none(*pte)) {
 		pte_t entry;
-		void *p = vmemmap_alloc_block(PAGE_SIZE, node);
+		void *p = vmemmap_alloc_block_buf(PAGE_SIZE, node);
 		if (!p)
 			return NULL;
 		entry = pfn_pte(__pa(p) >> PAGE_SHIFT, PAGE_KERNEL);
@@ -163,3 +183,55 @@
 
 	return map;
 }
+
+void __init sparse_mem_maps_populate_node(struct page **map_map,
+					  unsigned long pnum_begin,
+					  unsigned long pnum_end,
+					  unsigned long map_count, int nodeid)
+{
+	unsigned long pnum;
+	unsigned long size = sizeof(struct page) * PAGES_PER_SECTION;
+	void *vmemmap_buf_start;
+
+	size = ALIGN(size, PMD_SIZE);
+	vmemmap_buf_start = __earlyonly_bootmem_alloc(nodeid, size * map_count,
+			 PMD_SIZE, __pa(MAX_DMA_ADDRESS));
+
+	if (vmemmap_buf_start) {
+		vmemmap_buf = vmemmap_buf_start;
+		vmemmap_buf_end = vmemmap_buf_start + size * map_count;
+	}
+
+	for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+		struct mem_section *ms;
+
+		if (!present_section_nr(pnum))
+			continue;
+
+		map_map[pnum] = sparse_mem_map_populate(pnum, nodeid);
+		if (map_map[pnum])
+			continue;
+		ms = __nr_to_section(pnum);
+		printk(KERN_ERR "%s: sparsemem memory map backing failed "
+			"some memory will not be available.\n", __func__);
+		ms->section_mem_map = 0;
+	}
+
+	if (vmemmap_buf_start) {
+		/* need to free left buf */
+#ifdef CONFIG_NO_BOOTMEM
+		free_early(__pa(vmemmap_buf_start), __pa(vmemmap_buf_end));
+		if (vmemmap_buf_start < vmemmap_buf) {
+			char name[15];
+
+			snprintf(name, sizeof(name), "MEMMAP %d", nodeid);
+			reserve_early_without_check(__pa(vmemmap_buf_start),
+						    __pa(vmemmap_buf), name);
+		}
+#else
+		free_bootmem(__pa(vmemmap_buf), vmemmap_buf_end - vmemmap_buf);
+#endif
+		vmemmap_buf = NULL;
+		vmemmap_buf_end = NULL;
+	}
+}
diff --git a/mm/sparse.c b/mm/sparse.c
index 6ce4aab..22896d5 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -271,7 +271,8 @@
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
 static unsigned long * __init
-sparse_early_usemap_alloc_pgdat_section(struct pglist_data *pgdat)
+sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,
+					 unsigned long count)
 {
 	unsigned long section_nr;
 
@@ -286,7 +287,7 @@
 	 * this problem.
 	 */
 	section_nr = pfn_to_section_nr(__pa(pgdat) >> PAGE_SHIFT);
-	return alloc_bootmem_section(usemap_size(), section_nr);
+	return alloc_bootmem_section(usemap_size() * count, section_nr);
 }
 
 static void __init check_usemap_section_nr(int nid, unsigned long *usemap)
@@ -329,7 +330,8 @@
 }
 #else
 static unsigned long * __init
-sparse_early_usemap_alloc_pgdat_section(struct pglist_data *pgdat)
+sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,
+					 unsigned long count)
 {
 	return NULL;
 }
@@ -339,27 +341,40 @@
 }
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
-static unsigned long *__init sparse_early_usemap_alloc(unsigned long pnum)
+static void __init sparse_early_usemaps_alloc_node(unsigned long**usemap_map,
+				 unsigned long pnum_begin,
+				 unsigned long pnum_end,
+				 unsigned long usemap_count, int nodeid)
 {
-	unsigned long *usemap;
-	struct mem_section *ms = __nr_to_section(pnum);
-	int nid = sparse_early_nid(ms);
+	void *usemap;
+	unsigned long pnum;
+	int size = usemap_size();
 
-	usemap = sparse_early_usemap_alloc_pgdat_section(NODE_DATA(nid));
-	if (usemap)
-		return usemap;
-
-	usemap = alloc_bootmem_node(NODE_DATA(nid), usemap_size());
+	usemap = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nodeid),
+								 usemap_count);
 	if (usemap) {
-		check_usemap_section_nr(nid, usemap);
-		return usemap;
+		for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+			if (!present_section_nr(pnum))
+				continue;
+			usemap_map[pnum] = usemap;
+			usemap += size;
+		}
+		return;
 	}
 
-	/* Stupid: suppress gcc warning for SPARSEMEM && !NUMA */
-	nid = 0;
+	usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count);
+	if (usemap) {
+		for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+			if (!present_section_nr(pnum))
+				continue;
+			usemap_map[pnum] = usemap;
+			usemap += size;
+			check_usemap_section_nr(nodeid, usemap_map[pnum]);
+		}
+		return;
+	}
 
 	printk(KERN_WARNING "%s: allocation failed\n", __func__);
-	return NULL;
 }
 
 #ifndef CONFIG_SPARSEMEM_VMEMMAP
@@ -375,8 +390,65 @@
 		       PAGE_ALIGN(sizeof(struct page) * PAGES_PER_SECTION));
 	return map;
 }
+void __init sparse_mem_maps_populate_node(struct page **map_map,
+					  unsigned long pnum_begin,
+					  unsigned long pnum_end,
+					  unsigned long map_count, int nodeid)
+{
+	void *map;
+	unsigned long pnum;
+	unsigned long size = sizeof(struct page) * PAGES_PER_SECTION;
+
+	map = alloc_remap(nodeid, size * map_count);
+	if (map) {
+		for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+			if (!present_section_nr(pnum))
+				continue;
+			map_map[pnum] = map;
+			map += size;
+		}
+		return;
+	}
+
+	size = PAGE_ALIGN(size);
+	map = alloc_bootmem_pages_node(NODE_DATA(nodeid), size * map_count);
+	if (map) {
+		for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+			if (!present_section_nr(pnum))
+				continue;
+			map_map[pnum] = map;
+			map += size;
+		}
+		return;
+	}
+
+	/* fallback */
+	for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+		struct mem_section *ms;
+
+		if (!present_section_nr(pnum))
+			continue;
+		map_map[pnum] = sparse_mem_map_populate(pnum, nodeid);
+		if (map_map[pnum])
+			continue;
+		ms = __nr_to_section(pnum);
+		printk(KERN_ERR "%s: sparsemem memory map backing failed "
+			"some memory will not be available.\n", __func__);
+		ms->section_mem_map = 0;
+	}
+}
 #endif /* !CONFIG_SPARSEMEM_VMEMMAP */
 
+#ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
+static void __init sparse_early_mem_maps_alloc_node(struct page **map_map,
+				 unsigned long pnum_begin,
+				 unsigned long pnum_end,
+				 unsigned long map_count, int nodeid)
+{
+	sparse_mem_maps_populate_node(map_map, pnum_begin, pnum_end,
+					 map_count, nodeid);
+}
+#else
 static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
 {
 	struct page *map;
@@ -392,10 +464,12 @@
 	ms->section_mem_map = 0;
 	return NULL;
 }
+#endif
 
 void __attribute__((weak)) __meminit vmemmap_populate_print_last(void)
 {
 }
+
 /*
  * Allocate the accumulated non-linear sections, allocate a mem_map
  * for each and record the physical to section mapping.
@@ -407,6 +481,14 @@
 	unsigned long *usemap;
 	unsigned long **usemap_map;
 	int size;
+	int nodeid_begin = 0;
+	unsigned long pnum_begin = 0;
+	unsigned long usemap_count;
+#ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
+	unsigned long map_count;
+	int size2;
+	struct page **map_map;
+#endif
 
 	/*
 	 * map is using big page (aka 2M in x86 64 bit)
@@ -425,10 +507,81 @@
 		panic("can not allocate usemap_map\n");
 
 	for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
+		struct mem_section *ms;
+
 		if (!present_section_nr(pnum))
 			continue;
-		usemap_map[pnum] = sparse_early_usemap_alloc(pnum);
+		ms = __nr_to_section(pnum);
+		nodeid_begin = sparse_early_nid(ms);
+		pnum_begin = pnum;
+		break;
 	}
+	usemap_count = 1;
+	for (pnum = pnum_begin + 1; pnum < NR_MEM_SECTIONS; pnum++) {
+		struct mem_section *ms;
+		int nodeid;
+
+		if (!present_section_nr(pnum))
+			continue;
+		ms = __nr_to_section(pnum);
+		nodeid = sparse_early_nid(ms);
+		if (nodeid == nodeid_begin) {
+			usemap_count++;
+			continue;
+		}
+		/* ok, we need to take cake of from pnum_begin to pnum - 1*/
+		sparse_early_usemaps_alloc_node(usemap_map, pnum_begin, pnum,
+						 usemap_count, nodeid_begin);
+		/* new start, update count etc*/
+		nodeid_begin = nodeid;
+		pnum_begin = pnum;
+		usemap_count = 1;
+	}
+	/* ok, last chunk */
+	sparse_early_usemaps_alloc_node(usemap_map, pnum_begin, NR_MEM_SECTIONS,
+					 usemap_count, nodeid_begin);
+
+#ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
+	size2 = sizeof(struct page *) * NR_MEM_SECTIONS;
+	map_map = alloc_bootmem(size2);
+	if (!map_map)
+		panic("can not allocate map_map\n");
+
+	for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
+		struct mem_section *ms;
+
+		if (!present_section_nr(pnum))
+			continue;
+		ms = __nr_to_section(pnum);
+		nodeid_begin = sparse_early_nid(ms);
+		pnum_begin = pnum;
+		break;
+	}
+	map_count = 1;
+	for (pnum = pnum_begin + 1; pnum < NR_MEM_SECTIONS; pnum++) {
+		struct mem_section *ms;
+		int nodeid;
+
+		if (!present_section_nr(pnum))
+			continue;
+		ms = __nr_to_section(pnum);
+		nodeid = sparse_early_nid(ms);
+		if (nodeid == nodeid_begin) {
+			map_count++;
+			continue;
+		}
+		/* ok, we need to take cake of from pnum_begin to pnum - 1*/
+		sparse_early_mem_maps_alloc_node(map_map, pnum_begin, pnum,
+						 map_count, nodeid_begin);
+		/* new start, update count etc*/
+		nodeid_begin = nodeid;
+		pnum_begin = pnum;
+		map_count = 1;
+	}
+	/* ok, last chunk */
+	sparse_early_mem_maps_alloc_node(map_map, pnum_begin, NR_MEM_SECTIONS,
+					 map_count, nodeid_begin);
+#endif
 
 	for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
 		if (!present_section_nr(pnum))
@@ -438,7 +591,11 @@
 		if (!usemap)
 			continue;
 
+#ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
+		map = map_map[pnum];
+#else
 		map = sparse_early_mem_map_alloc(pnum);
+#endif
 		if (!map)
 			continue;
 
@@ -448,6 +605,9 @@
 
 	vmemmap_populate_print_last();
 
+#ifdef CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER
+	free_bootmem(__pa(map_map), size2);
+#endif
 	free_bootmem(__pa(usemap_map), size);
 }
 
diff --git a/mm/swap.c b/mm/swap.c
index 308e57d..9036b89 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -55,7 +55,7 @@
 		del_page_from_lru(zone, page);
 		spin_unlock_irqrestore(&zone->lru_lock, flags);
 	}
-	free_hot_page(page);
+	free_hot_cold_page(page, 0);
 }
 
 static void put_compound_page(struct page *page)
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 6c0585b..6cd0a8f 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -723,6 +723,37 @@
 	return p != NULL;
 }
 
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+/**
+ * mem_cgroup_count_swap_user - count the user of a swap entry
+ * @ent: the swap entry to be checked
+ * @pagep: the pointer for the swap cache page of the entry to be stored
+ *
+ * Returns the number of the user of the swap entry. The number is valid only
+ * for swaps of anonymous pages.
+ * If the entry is found on swap cache, the page is stored to pagep with
+ * refcount of it being incremented.
+ */
+int mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep)
+{
+	struct page *page;
+	struct swap_info_struct *p;
+	int count = 0;
+
+	page = find_get_page(&swapper_space, ent.val);
+	if (page)
+		count += page_mapcount(page);
+	p = swap_info_get(ent);
+	if (p) {
+		count += swap_count(p->swap_map[swp_offset(ent)]);
+		spin_unlock(&swap_lock);
+	}
+
+	*pagep = page;
+	return count;
+}
+#endif
+
 #ifdef CONFIG_HIBERNATION
 /*
  * Find the swap type that corresponds to given device (if any).
@@ -840,7 +871,8 @@
 		goto out;
 	}
 
-	inc_mm_counter(vma->vm_mm, anon_rss);
+	dec_mm_counter(vma->vm_mm, MM_SWAPENTS);
+	inc_mm_counter(vma->vm_mm, MM_ANONPAGES);
 	get_page(page);
 	set_pte_at(vma->vm_mm, addr, pte,
 		   pte_mkold(mk_pte(page, vma->vm_page_prot)));
@@ -1759,11 +1791,11 @@
 	unsigned int type;
 	int i, prev;
 	int error;
-	union swap_header *swap_header = NULL;
-	unsigned int nr_good_pages = 0;
+	union swap_header *swap_header;
+	unsigned int nr_good_pages;
 	int nr_extents = 0;
 	sector_t span;
-	unsigned long maxpages = 1;
+	unsigned long maxpages;
 	unsigned long swapfilepages;
 	unsigned char *swap_map = NULL;
 	struct page *page = NULL;
@@ -1922,9 +1954,13 @@
 	 * swap pte.
 	 */
 	maxpages = swp_offset(pte_to_swp_entry(
-			swp_entry_to_pte(swp_entry(0, ~0UL)))) - 1;
-	if (maxpages > swap_header->info.last_page)
-		maxpages = swap_header->info.last_page;
+			swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1;
+	if (maxpages > swap_header->info.last_page) {
+		maxpages = swap_header->info.last_page + 1;
+		/* p->max is an unsigned int: don't overflow it */
+		if ((unsigned int)maxpages == 0)
+			maxpages = UINT_MAX;
+	}
 	p->highest_bit = maxpages - 1;
 
 	error = -EINVAL;
@@ -1948,23 +1984,24 @@
 	}
 
 	memset(swap_map, 0, maxpages);
+	nr_good_pages = maxpages - 1;	/* omit header page */
+
 	for (i = 0; i < swap_header->info.nr_badpages; i++) {
-		int page_nr = swap_header->info.badpages[i];
-		if (page_nr <= 0 || page_nr >= swap_header->info.last_page) {
+		unsigned int page_nr = swap_header->info.badpages[i];
+		if (page_nr == 0 || page_nr > swap_header->info.last_page) {
 			error = -EINVAL;
 			goto bad_swap;
 		}
-		swap_map[page_nr] = SWAP_MAP_BAD;
+		if (page_nr < maxpages) {
+			swap_map[page_nr] = SWAP_MAP_BAD;
+			nr_good_pages--;
+		}
 	}
 
 	error = swap_cgroup_swapon(type, maxpages);
 	if (error)
 		goto bad_swap;
 
-	nr_good_pages = swap_header->info.last_page -
-			swap_header->info.nr_badpages -
-			1 /* header page */;
-
 	if (nr_good_pages) {
 		swap_map[0] = SWAP_MAP_BAD;
 		p->max = maxpages;
@@ -2155,7 +2192,11 @@
 }
 
 /*
- * increase reference count of swap entry by 1.
+ * Increase reference count of swap entry by 1.
+ * Returns 0 for success, or -ENOMEM if a swap_count_continuation is required
+ * but could not be atomically allocated.  Returns 0, just as if it succeeded,
+ * if __swap_duplicate() fails for another reason (-EINVAL or -ENOENT), which
+ * might occur if a page table entry has got corrupted.
  */
 int swap_duplicate(swp_entry_t entry)
 {
diff --git a/mm/vmscan.c b/mm/vmscan.c
index c26986c..79c8098 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -262,27 +262,6 @@
 	return ret;
 }
 
-/* Called without lock on whether page is mapped, so answer is unstable */
-static inline int page_mapping_inuse(struct page *page)
-{
-	struct address_space *mapping;
-
-	/* Page is in somebody's page tables. */
-	if (page_mapped(page))
-		return 1;
-
-	/* Be more reluctant to reclaim swapcache than pagecache */
-	if (PageSwapCache(page))
-		return 1;
-
-	mapping = page_mapping(page);
-	if (!mapping)
-		return 0;
-
-	/* File is mmap'd by somebody? */
-	return mapping_mapped(mapping);
-}
-
 static inline int is_page_cache_freeable(struct page *page)
 {
 	/*
@@ -579,6 +558,65 @@
 	put_page(page);		/* drop ref from isolate */
 }
 
+enum page_references {
+	PAGEREF_RECLAIM,
+	PAGEREF_RECLAIM_CLEAN,
+	PAGEREF_KEEP,
+	PAGEREF_ACTIVATE,
+};
+
+static enum page_references page_check_references(struct page *page,
+						  struct scan_control *sc)
+{
+	int referenced_ptes, referenced_page;
+	unsigned long vm_flags;
+
+	referenced_ptes = page_referenced(page, 1, sc->mem_cgroup, &vm_flags);
+	referenced_page = TestClearPageReferenced(page);
+
+	/* Lumpy reclaim - ignore references */
+	if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
+		return PAGEREF_RECLAIM;
+
+	/*
+	 * Mlock lost the isolation race with us.  Let try_to_unmap()
+	 * move the page to the unevictable list.
+	 */
+	if (vm_flags & VM_LOCKED)
+		return PAGEREF_RECLAIM;
+
+	if (referenced_ptes) {
+		if (PageAnon(page))
+			return PAGEREF_ACTIVATE;
+		/*
+		 * All mapped pages start out with page table
+		 * references from the instantiating fault, so we need
+		 * to look twice if a mapped file page is used more
+		 * than once.
+		 *
+		 * Mark it and spare it for another trip around the
+		 * inactive list.  Another page table reference will
+		 * lead to its activation.
+		 *
+		 * Note: the mark is set for activated pages as well
+		 * so that recently deactivated but used pages are
+		 * quickly recovered.
+		 */
+		SetPageReferenced(page);
+
+		if (referenced_page)
+			return PAGEREF_ACTIVATE;
+
+		return PAGEREF_KEEP;
+	}
+
+	/* Reclaim if clean, defer dirty pages to writeback */
+	if (referenced_page)
+		return PAGEREF_RECLAIM_CLEAN;
+
+	return PAGEREF_RECLAIM;
+}
+
 /*
  * shrink_page_list() returns the number of reclaimed pages
  */
@@ -590,16 +628,15 @@
 	struct pagevec freed_pvec;
 	int pgactivate = 0;
 	unsigned long nr_reclaimed = 0;
-	unsigned long vm_flags;
 
 	cond_resched();
 
 	pagevec_init(&freed_pvec, 1);
 	while (!list_empty(page_list)) {
+		enum page_references references;
 		struct address_space *mapping;
 		struct page *page;
 		int may_enter_fs;
-		int referenced;
 
 		cond_resched();
 
@@ -641,17 +678,16 @@
 				goto keep_locked;
 		}
 
-		referenced = page_referenced(page, 1,
-						sc->mem_cgroup, &vm_flags);
-		/*
-		 * In active use or really unfreeable?  Activate it.
-		 * If page which have PG_mlocked lost isoltation race,
-		 * try_to_unmap moves it to unevictable list
-		 */
-		if (sc->order <= PAGE_ALLOC_COSTLY_ORDER &&
-					referenced && page_mapping_inuse(page)
-					&& !(vm_flags & VM_LOCKED))
+		references = page_check_references(page, sc);
+		switch (references) {
+		case PAGEREF_ACTIVATE:
 			goto activate_locked;
+		case PAGEREF_KEEP:
+			goto keep_locked;
+		case PAGEREF_RECLAIM:
+		case PAGEREF_RECLAIM_CLEAN:
+			; /* try to reclaim the page below */
+		}
 
 		/*
 		 * Anonymous process memory has backing store?
@@ -685,7 +721,7 @@
 		}
 
 		if (PageDirty(page)) {
-			if (sc->order <= PAGE_ALLOC_COSTLY_ORDER && referenced)
+			if (references == PAGEREF_RECLAIM_CLEAN)
 				goto keep_locked;
 			if (!may_enter_fs)
 				goto keep_locked;
@@ -1350,9 +1386,7 @@
 			continue;
 		}
 
-		/* page_referenced clears PageReferenced */
-		if (page_mapping_inuse(page) &&
-		    page_referenced(page, 0, sc->mem_cgroup, &vm_flags)) {
+		if (page_referenced(page, 0, sc->mem_cgroup, &vm_flags)) {
 			nr_rotated++;
 			/*
 			 * Identify referenced, file-backed active pages and
@@ -1501,6 +1535,13 @@
 	unsigned long ap, fp;
 	struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc);
 
+	/* If we have no swap space, do not bother scanning anon pages. */
+	if (!sc->may_swap || (nr_swap_pages <= 0)) {
+		percent[0] = 0;
+		percent[1] = 100;
+		return;
+	}
+
 	anon  = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) +
 		zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON);
 	file  = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_FILE) +
@@ -1598,22 +1639,20 @@
 	unsigned long nr_reclaimed = sc->nr_reclaimed;
 	unsigned long nr_to_reclaim = sc->nr_to_reclaim;
 	struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc);
-	int noswap = 0;
 
-	/* If we have no swap space, do not bother scanning anon pages. */
-	if (!sc->may_swap || (nr_swap_pages <= 0)) {
-		noswap = 1;
-		percent[0] = 0;
-		percent[1] = 100;
-	} else
-		get_scan_ratio(zone, sc, percent);
+	get_scan_ratio(zone, sc, percent);
 
 	for_each_evictable_lru(l) {
 		int file = is_file_lru(l);
 		unsigned long scan;
 
+		if (percent[file] == 0) {
+			nr[l] = 0;
+			continue;
+		}
+
 		scan = zone_nr_lru_pages(zone, sc, l);
-		if (priority || noswap) {
+		if (priority) {
 			scan >>= priority;
 			scan = (scan * percent[file]) / 100;
 		}
@@ -1694,8 +1733,7 @@
 				continue;
 			note_zone_scanning_priority(zone, priority);
 
-			if (zone_is_all_unreclaimable(zone) &&
-						priority != DEF_PRIORITY)
+			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
 				continue;	/* Let kswapd poll it */
 			sc->all_unreclaimable = 0;
 		} else {
@@ -1922,7 +1960,7 @@
 		if (!populated_zone(zone))
 			continue;
 
-		if (zone_is_all_unreclaimable(zone))
+		if (zone->all_unreclaimable)
 			continue;
 
 		if (!zone_watermark_ok(zone, order, high_wmark_pages(zone),
@@ -2012,8 +2050,7 @@
 			if (!populated_zone(zone))
 				continue;
 
-			if (zone_is_all_unreclaimable(zone) &&
-			    priority != DEF_PRIORITY)
+			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
 				continue;
 
 			/*
@@ -2056,13 +2093,9 @@
 			if (!populated_zone(zone))
 				continue;
 
-			if (zone_is_all_unreclaimable(zone) &&
-					priority != DEF_PRIORITY)
+			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
 				continue;
 
-			if (!zone_watermark_ok(zone, order,
-					high_wmark_pages(zone), end_zone, 0))
-				all_zones_ok = 0;
 			temp_priority[i] = priority;
 			sc.nr_scanned = 0;
 			note_zone_scanning_priority(zone, priority);
@@ -2087,12 +2120,11 @@
 						lru_pages);
 			sc.nr_reclaimed += reclaim_state->reclaimed_slab;
 			total_scanned += sc.nr_scanned;
-			if (zone_is_all_unreclaimable(zone))
+			if (zone->all_unreclaimable)
 				continue;
-			if (nr_slab == 0 && zone->pages_scanned >=
-					(zone_reclaimable_pages(zone) * 6))
-					zone_set_flag(zone,
-						      ZONE_ALL_UNRECLAIMABLE);
+			if (nr_slab == 0 &&
+			    zone->pages_scanned >= (zone_reclaimable_pages(zone) * 6))
+				zone->all_unreclaimable = 1;
 			/*
 			 * If we've done a decent amount of scanning and
 			 * the reclaim ratio is low, start doing writepage
@@ -2102,13 +2134,18 @@
 			    total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2)
 				sc.may_writepage = 1;
 
-			/*
-			 * We are still under min water mark. it mean we have
-			 * GFP_ATOMIC allocation failure risk. Hurry up!
-			 */
-			if (!zone_watermark_ok(zone, order, min_wmark_pages(zone),
-					      end_zone, 0))
-				has_under_min_watermark_zone = 1;
+			if (!zone_watermark_ok(zone, order,
+					high_wmark_pages(zone), end_zone, 0)) {
+				all_zones_ok = 0;
+				/*
+				 * We are still under min water mark.  This
+				 * means that we have a GFP_ATOMIC allocation
+				 * failure risk. Hurry up!
+				 */
+				if (!zone_watermark_ok(zone, order,
+					    min_wmark_pages(zone), end_zone, 0))
+					has_under_min_watermark_zone = 1;
+			}
 
 		}
 		if (all_zones_ok)
@@ -2550,6 +2587,7 @@
 	 * and RECLAIM_SWAP.
 	 */
 	p->flags |= PF_MEMALLOC | PF_SWAPWRITE;
+	lockdep_set_current_reclaim_state(gfp_mask);
 	reclaim_state.reclaimed_slab = 0;
 	p->reclaim_state = &reclaim_state;
 
@@ -2593,6 +2631,7 @@
 
 	p->reclaim_state = NULL;
 	current->flags &= ~(PF_MEMALLOC | PF_SWAPWRITE);
+	lockdep_clear_current_reclaim_state();
 	return sc.nr_reclaimed >= nr_pages;
 }
 
@@ -2615,7 +2654,7 @@
 	    zone_page_state(zone, NR_SLAB_RECLAIMABLE) <= zone->min_slab_pages)
 		return ZONE_RECLAIM_FULL;
 
-	if (zone_is_all_unreclaimable(zone))
+	if (zone->all_unreclaimable)
 		return ZONE_RECLAIM_FULL;
 
 	/*
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 6051fba..7f760cb 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -139,7 +139,8 @@
 		threshold = calculate_threshold(zone);
 
 		for_each_online_cpu(cpu)
-			zone_pcp(zone, cpu)->stat_threshold = threshold;
+			per_cpu_ptr(zone->pageset, cpu)->stat_threshold
+							= threshold;
 	}
 }
 
@@ -149,7 +150,8 @@
 void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
 				int delta)
 {
-	struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+	struct per_cpu_pageset *pcp = this_cpu_ptr(zone->pageset);
+
 	s8 *p = pcp->vm_stat_diff + item;
 	long x;
 
@@ -202,7 +204,7 @@
  */
 void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
 {
-	struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+	struct per_cpu_pageset *pcp = this_cpu_ptr(zone->pageset);
 	s8 *p = pcp->vm_stat_diff + item;
 
 	(*p)++;
@@ -223,7 +225,7 @@
 
 void __dec_zone_state(struct zone *zone, enum zone_stat_item item)
 {
-	struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+	struct per_cpu_pageset *pcp = this_cpu_ptr(zone->pageset);
 	s8 *p = pcp->vm_stat_diff + item;
 
 	(*p)--;
@@ -300,7 +302,7 @@
 	for_each_populated_zone(zone) {
 		struct per_cpu_pageset *p;
 
-		p = zone_pcp(zone, cpu);
+		p = per_cpu_ptr(zone->pageset, cpu);
 
 		for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
 			if (p->vm_stat_diff[i]) {
@@ -741,7 +743,7 @@
 	for_each_online_cpu(i) {
 		struct per_cpu_pageset *pageset;
 
-		pageset = zone_pcp(zone, i);
+		pageset = per_cpu_ptr(zone->pageset, i);
 		seq_printf(m,
 			   "\n    cpu: %i"
 			   "\n              count: %i"
@@ -761,7 +763,7 @@
 		   "\n  prev_priority:     %i"
 		   "\n  start_pfn:         %lu"
 		   "\n  inactive_ratio:    %u",
-			   zone_is_all_unreclaimable(zone),
+		   zone->all_unreclaimable,
 		   zone->prev_priority,
 		   zone->zone_start_pfn,
 		   zone->inactive_ratio);
@@ -906,6 +908,7 @@
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
 		start_cpu_timer(cpu);
+		node_set_state(cpu_to_node(cpu), N_CPU);
 		break;
 	case CPU_DOWN_PREPARE:
 	case CPU_DOWN_PREPARE_FROZEN:
diff --git a/net/9p/client.c b/net/9p/client.c
index 09d4f1e2..bde9f3d 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -46,6 +46,7 @@
 	Opt_msize,
 	Opt_trans,
 	Opt_legacy,
+	Opt_version,
 	Opt_err,
 };
 
@@ -53,9 +54,42 @@
 	{Opt_msize, "msize=%u"},
 	{Opt_legacy, "noextend"},
 	{Opt_trans, "trans=%s"},
+	{Opt_version, "version=%s"},
 	{Opt_err, NULL},
 };
 
+inline int p9_is_proto_dotl(struct p9_client *clnt)
+{
+	return (clnt->proto_version == p9_proto_2010L);
+}
+EXPORT_SYMBOL(p9_is_proto_dotl);
+
+inline int p9_is_proto_dotu(struct p9_client *clnt)
+{
+	return (clnt->proto_version == p9_proto_2000u);
+}
+EXPORT_SYMBOL(p9_is_proto_dotu);
+
+/* Interpret mount option for protocol version */
+static unsigned char get_protocol_version(const substring_t *name)
+{
+	unsigned char version = -EINVAL;
+	if (!strncmp("9p2000", name->from, name->to-name->from)) {
+		version = p9_proto_legacy;
+		P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");
+	} else if (!strncmp("9p2000.u", name->from, name->to-name->from)) {
+		version = p9_proto_2000u;
+		P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
+	} else if (!strncmp("9p2010.L", name->from, name->to-name->from)) {
+		version = p9_proto_2010L;
+		P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2010.L\n");
+	} else {
+		P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",
+							name->from);
+	}
+	return version;
+}
+
 static struct p9_req_t *
 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
 
@@ -75,7 +109,7 @@
 	int option;
 	int ret = 0;
 
-	clnt->dotu = 1;
+	clnt->proto_version = p9_proto_2000u;
 	clnt->msize = 8192;
 
 	if (!opts)
@@ -118,7 +152,13 @@
 			}
 			break;
 		case Opt_legacy:
-			clnt->dotu = 0;
+			clnt->proto_version = p9_proto_legacy;
+			break;
+		case Opt_version:
+			ret = get_protocol_version(&args[0]);
+			if (ret == -EINVAL)
+				goto free_and_return;
+			clnt->proto_version = ret;
 			break;
 		default:
 			continue;
@@ -410,14 +450,15 @@
 		int ecode;
 		char *ename;
 
-		err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode);
+		err = p9pdu_readf(req->rc, c->proto_version, "s?d",
+							&ename, &ecode);
 		if (err) {
 			P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
 									err);
 			return err;
 		}
 
-		if (c->dotu)
+		if (p9_is_proto_dotu(c))
 			err = -ecode;
 
 		if (!err || !IS_ERR_VALUE(err))
@@ -515,7 +556,7 @@
 	/* marshall the data */
 	p9pdu_prepare(req->tc, tag, type);
 	va_start(ap, fmt);
-	err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap);
+	err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap);
 	va_end(ap);
 	p9pdu_finalize(req->tc);
 
@@ -627,14 +668,31 @@
 	char *version;
 	int msize;
 
-	P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n",
-							c->msize, c->dotu);
-	req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize,
-				c->dotu ? "9P2000.u" : "9P2000");
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n",
+						c->msize, c->proto_version);
+
+	switch (c->proto_version) {
+	case p9_proto_2010L:
+		req = p9_client_rpc(c, P9_TVERSION, "ds",
+					c->msize, "9P2010.L");
+		break;
+	case p9_proto_2000u:
+		req = p9_client_rpc(c, P9_TVERSION, "ds",
+					c->msize, "9P2000.u");
+		break;
+	case p9_proto_legacy:
+		req = p9_client_rpc(c, P9_TVERSION, "ds",
+					c->msize, "9P2000");
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
-	err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version);
+	err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version);
 	if (err) {
 		P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
 		p9pdu_dump(1, req->rc);
@@ -642,10 +700,12 @@
 	}
 
 	P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
-	if (!memcmp(version, "9P2000.u", 8))
-		c->dotu = 1;
-	else if (!memcmp(version, "9P2000", 6))
-		c->dotu = 0;
+	if (!strncmp(version, "9P2010.L", 8))
+		c->proto_version = p9_proto_2010L;
+	else if (!strncmp(version, "9P2000.u", 8))
+		c->proto_version = p9_proto_2000u;
+	else if (!strncmp(version, "9P2000", 6))
+		c->proto_version = p9_proto_legacy;
 	else {
 		err = -EREMOTEIO;
 		goto error;
@@ -700,8 +760,8 @@
 		goto put_trans;
 	}
 
-	P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n",
-		clnt, clnt->trans_mod, clnt->msize, clnt->dotu);
+	P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
+		clnt, clnt->trans_mod, clnt->msize, clnt->proto_version);
 
 	err = clnt->trans_mod->create(clnt, dev_name, options);
 	if (err)
@@ -784,7 +844,7 @@
 		goto error;
 	}
 
-	err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
+	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
 	if (err) {
 		p9pdu_dump(1, req->rc);
 		p9_free_req(clnt, req);
@@ -833,7 +893,7 @@
 		goto error;
 	}
 
-	err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
+	err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
 	if (err) {
 		p9pdu_dump(1, req->rc);
 		p9_free_req(clnt, req);
@@ -891,7 +951,7 @@
 		goto error;
 	}
 
-	err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids);
+	err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids);
 	if (err) {
 		p9pdu_dump(1, req->rc);
 		p9_free_req(clnt, req);
@@ -952,7 +1012,7 @@
 		goto error;
 	}
 
-	err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
+	err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
 	if (err) {
 		p9pdu_dump(1, req->rc);
 		goto free_and_error;
@@ -997,7 +1057,7 @@
 		goto error;
 	}
 
-	err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
+	err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
 	if (err) {
 		p9pdu_dump(1, req->rc);
 		goto free_and_error;
@@ -1098,7 +1158,7 @@
 		goto error;
 	}
 
-	err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr);
+	err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
 	if (err) {
 		p9pdu_dump(1, req->rc);
 		goto free_and_error;
@@ -1159,7 +1219,7 @@
 		goto error;
 	}
 
-	err = p9pdu_readf(req->rc, clnt->dotu, "d", &count);
+	err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
 	if (err) {
 		p9pdu_dump(1, req->rc);
 		goto free_and_error;
@@ -1199,7 +1259,7 @@
 		goto error;
 	}
 
-	err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret);
+	err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret);
 	if (err) {
 		p9pdu_dump(1, req->rc);
 		p9_free_req(clnt, req);
@@ -1226,7 +1286,7 @@
 }
 EXPORT_SYMBOL(p9_client_stat);
 
-static int p9_client_statsize(struct p9_wstat *wst, int optional)
+static int p9_client_statsize(struct p9_wstat *wst, int proto_version)
 {
 	int ret;
 
@@ -1245,7 +1305,7 @@
 	if (wst->muid)
 		ret += strlen(wst->muid);
 
-	if (optional) {
+	if (proto_version == p9_proto_2000u) {
 		ret += 2+4+4+4;	/* extension[s] n_uid[4] n_gid[4] n_muid[4] */
 		if (wst->extension)
 			ret += strlen(wst->extension);
@@ -1262,7 +1322,7 @@
 
 	err = 0;
 	clnt = fid->clnt;
-	wst->size = p9_client_statsize(wst, clnt->dotu);
+	wst->size = p9_client_statsize(wst, clnt->proto_version);
 	P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
 	P9_DPRINTK(P9_DEBUG_9P,
 		"     sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index fc70147..94f5a8f 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -52,7 +52,7 @@
 #endif
 
 static int
-p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...);
+p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...);
 
 #ifdef CONFIG_NET_9P_DEBUG
 void
@@ -144,7 +144,8 @@
 */
 
 static int
-p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
+p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
+	va_list ap)
 {
 	const char *ptr;
 	int errcode = 0;
@@ -194,7 +195,8 @@
 				int16_t len;
 				int size;
 
-				errcode = p9pdu_readf(pdu, optional, "w", &len);
+				errcode = p9pdu_readf(pdu, proto_version,
+								"w", &len);
 				if (errcode)
 					break;
 
@@ -217,7 +219,7 @@
 				struct p9_qid *qid =
 				    va_arg(ap, struct p9_qid *);
 
-				errcode = p9pdu_readf(pdu, optional, "bdq",
+				errcode = p9pdu_readf(pdu, proto_version, "bdq",
 						      &qid->type, &qid->version,
 						      &qid->path);
 			}
@@ -230,7 +232,7 @@
 				stbuf->n_uid = stbuf->n_gid = stbuf->n_muid =
 									-1;
 				errcode =
-				    p9pdu_readf(pdu, optional,
+				    p9pdu_readf(pdu, proto_version,
 						"wwdQdddqssss?sddd",
 						&stbuf->size, &stbuf->type,
 						&stbuf->dev, &stbuf->qid,
@@ -250,7 +252,7 @@
 				void **data = va_arg(ap, void **);
 
 				errcode =
-				    p9pdu_readf(pdu, optional, "d", count);
+				    p9pdu_readf(pdu, proto_version, "d", count);
 				if (!errcode) {
 					*count =
 					    MIN(*count,
@@ -263,8 +265,8 @@
 				int16_t *nwname = va_arg(ap, int16_t *);
 				char ***wnames = va_arg(ap, char ***);
 
-				errcode =
-				    p9pdu_readf(pdu, optional, "w", nwname);
+				errcode = p9pdu_readf(pdu, proto_version,
+								"w", nwname);
 				if (!errcode) {
 					*wnames =
 					    kmalloc(sizeof(char *) * *nwname,
@@ -278,7 +280,8 @@
 
 					for (i = 0; i < *nwname; i++) {
 						errcode =
-						    p9pdu_readf(pdu, optional,
+						    p9pdu_readf(pdu,
+								proto_version,
 								"s",
 								&(*wnames)[i]);
 						if (errcode)
@@ -306,7 +309,7 @@
 				*wqids = NULL;
 
 				errcode =
-				    p9pdu_readf(pdu, optional, "w", nwqid);
+				    p9pdu_readf(pdu, proto_version, "w", nwqid);
 				if (!errcode) {
 					*wqids =
 					    kmalloc(*nwqid *
@@ -321,7 +324,8 @@
 
 					for (i = 0; i < *nwqid; i++) {
 						errcode =
-						    p9pdu_readf(pdu, optional,
+						    p9pdu_readf(pdu,
+								proto_version,
 								"Q",
 								&(*wqids)[i]);
 						if (errcode)
@@ -336,7 +340,7 @@
 			}
 			break;
 		case '?':
-			if (!optional)
+			if (proto_version != p9_proto_2000u)
 				return 0;
 			break;
 		default:
@@ -352,7 +356,8 @@
 }
 
 int
-p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap)
+p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
+	va_list ap)
 {
 	const char *ptr;
 	int errcode = 0;
@@ -389,7 +394,8 @@
 				if (sptr)
 					len = MIN(strlen(sptr), USHORT_MAX);
 
-				errcode = p9pdu_writef(pdu, optional, "w", len);
+				errcode = p9pdu_writef(pdu, proto_version,
+								"w", len);
 				if (!errcode && pdu_write(pdu, sptr, len))
 					errcode = -EFAULT;
 			}
@@ -398,7 +404,7 @@
 				const struct p9_qid *qid =
 				    va_arg(ap, const struct p9_qid *);
 				errcode =
-				    p9pdu_writef(pdu, optional, "bdq",
+				    p9pdu_writef(pdu, proto_version, "bdq",
 						 qid->type, qid->version,
 						 qid->path);
 			} break;
@@ -406,7 +412,7 @@
 				const struct p9_wstat *stbuf =
 				    va_arg(ap, const struct p9_wstat *);
 				errcode =
-				    p9pdu_writef(pdu, optional,
+				    p9pdu_writef(pdu, proto_version,
 						 "wwdQdddqssss?sddd",
 						 stbuf->size, stbuf->type,
 						 stbuf->dev, &stbuf->qid,
@@ -421,8 +427,8 @@
 				int32_t count = va_arg(ap, int32_t);
 				const void *data = va_arg(ap, const void *);
 
-				errcode =
-				    p9pdu_writef(pdu, optional, "d", count);
+				errcode = p9pdu_writef(pdu, proto_version, "d",
+									count);
 				if (!errcode && pdu_write(pdu, data, count))
 					errcode = -EFAULT;
 			}
@@ -431,8 +437,8 @@
 				int32_t count = va_arg(ap, int32_t);
 				const char __user *udata =
 						va_arg(ap, const void __user *);
-				errcode =
-				    p9pdu_writef(pdu, optional, "d", count);
+				errcode = p9pdu_writef(pdu, proto_version, "d",
+									count);
 				if (!errcode && pdu_write_u(pdu, udata, count))
 					errcode = -EFAULT;
 			}
@@ -441,14 +447,15 @@
 				int16_t nwname = va_arg(ap, int);
 				const char **wnames = va_arg(ap, const char **);
 
-				errcode =
-				    p9pdu_writef(pdu, optional, "w", nwname);
+				errcode = p9pdu_writef(pdu, proto_version, "w",
+									nwname);
 				if (!errcode) {
 					int i;
 
 					for (i = 0; i < nwname; i++) {
 						errcode =
-						    p9pdu_writef(pdu, optional,
+						    p9pdu_writef(pdu,
+								proto_version,
 								 "s",
 								 wnames[i]);
 						if (errcode)
@@ -462,14 +469,15 @@
 				struct p9_qid *wqids =
 				    va_arg(ap, struct p9_qid *);
 
-				errcode =
-				    p9pdu_writef(pdu, optional, "w", nwqid);
+				errcode = p9pdu_writef(pdu, proto_version, "w",
+									nwqid);
 				if (!errcode) {
 					int i;
 
 					for (i = 0; i < nwqid; i++) {
 						errcode =
-						    p9pdu_writef(pdu, optional,
+						    p9pdu_writef(pdu,
+								proto_version,
 								 "Q",
 								 &wqids[i]);
 						if (errcode)
@@ -479,7 +487,7 @@
 			}
 			break;
 		case '?':
-			if (!optional)
+			if (proto_version != p9_proto_2000u)
 				return 0;
 			break;
 		default:
@@ -494,32 +502,32 @@
 	return errcode;
 }
 
-int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...)
+int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
 {
 	va_list ap;
 	int ret;
 
 	va_start(ap, fmt);
-	ret = p9pdu_vreadf(pdu, optional, fmt, ap);
+	ret = p9pdu_vreadf(pdu, proto_version, fmt, ap);
 	va_end(ap);
 
 	return ret;
 }
 
 static int
-p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...)
+p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
 {
 	va_list ap;
 	int ret;
 
 	va_start(ap, fmt);
-	ret = p9pdu_vwritef(pdu, optional, fmt, ap);
+	ret = p9pdu_vwritef(pdu, proto_version, fmt, ap);
 	va_end(ap);
 
 	return ret;
 }
 
-int p9stat_read(char *buf, int len, struct p9_wstat *st, int dotu)
+int p9stat_read(char *buf, int len, struct p9_wstat *st, int proto_version)
 {
 	struct p9_fcall fake_pdu;
 	int ret;
@@ -529,7 +537,7 @@
 	fake_pdu.sdata = buf;
 	fake_pdu.offset = 0;
 
-	ret = p9pdu_readf(&fake_pdu, dotu, "S", st);
+	ret = p9pdu_readf(&fake_pdu, proto_version, "S", st);
 	if (ret) {
 		P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret);
 		p9pdu_dump(1, &fake_pdu);
diff --git a/net/9p/protocol.h b/net/9p/protocol.h
index ccde462..2431c0f 100644
--- a/net/9p/protocol.h
+++ b/net/9p/protocol.h
@@ -25,9 +25,9 @@
  *
  */
 
-int
-p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap);
-int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...);
+int p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
+								va_list ap);
+int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...);
 int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type);
 int p9pdu_finalize(struct p9_fcall *pdu);
 void p9pdu_dump(int, struct p9_fcall *);
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index cb50f4a..0aaed48 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -49,8 +49,6 @@
 
 /* a single mutex to manage channel initialization and attachment */
 static DEFINE_MUTEX(virtio_9p_lock);
-/* global which tracks highest initialized channel */
-static int chan_index;
 
 /**
  * struct virtio_chan - per-instance transport information
@@ -68,8 +66,7 @@
  *
  */
 
-static struct virtio_chan {
-	bool initialized;
+struct virtio_chan {
 	bool inuse;
 
 	spinlock_t lock;
@@ -80,7 +77,11 @@
 
 	/* Scatterlist: can be too big for stack. */
 	struct scatterlist sg[VIRTQUEUE_NUM];
-} channels[MAX_9P_CHAN];
+
+	struct list_head chan_list;
+};
+
+static struct list_head virtio_chan_list;
 
 /* How many bytes left in this page. */
 static unsigned int rest_of_page(void *data)
@@ -217,9 +218,7 @@
  * p9_virtio_probe - probe for existence of 9P virtio channels
  * @vdev: virtio device to probe
  *
- * This probes for existing virtio channels.  At present only
- * a single channel is in use, so in the future more work may need
- * to be done here.
+ * This probes for existing virtio channels.
  *
  */
 
@@ -227,16 +226,10 @@
 {
 	int err;
 	struct virtio_chan *chan;
-	int index;
 
-	mutex_lock(&virtio_9p_lock);
-	index = chan_index++;
-	chan = &channels[index];
-	mutex_unlock(&virtio_9p_lock);
-
-	if (chan_index > MAX_9P_CHAN) {
-		printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n");
-		BUG();
+	chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL);
+	if (!chan) {
+		printk(KERN_ERR "9p: Failed to allocate virtio 9P channel\n");
 		err = -ENOMEM;
 		goto fail;
 	}
@@ -255,15 +248,15 @@
 	sg_init_table(chan->sg, VIRTQUEUE_NUM);
 
 	chan->inuse = false;
-	chan->initialized = true;
+	mutex_lock(&virtio_9p_lock);
+	list_add_tail(&chan->chan_list, &virtio_chan_list);
+	mutex_unlock(&virtio_9p_lock);
 	return 0;
 
 out_free_vq:
 	vdev->config->del_vqs(vdev);
+	kfree(chan);
 fail:
-	mutex_lock(&virtio_9p_lock);
-	chan_index--;
-	mutex_unlock(&virtio_9p_lock);
 	return err;
 }
 
@@ -280,35 +273,31 @@
  * We use a simple reference count mechanism to ensure that only a single
  * mount has a channel open at a time.
  *
- * Bugs: doesn't allow identification of a specific channel
- * to allocate, channels are allocated sequentially. This was
- * a pragmatic decision to get things rolling, but ideally some
- * way of identifying the channel to attach to would be nice
- * if we are going to support multiple channels.
- *
  */
 
 static int
 p9_virtio_create(struct p9_client *client, const char *devname, char *args)
 {
-	struct virtio_chan *chan = channels;
-	int index = 0;
+	struct virtio_chan *chan;
+	int ret = -ENOENT;
+	int found = 0;
 
 	mutex_lock(&virtio_9p_lock);
-	while (index < MAX_9P_CHAN) {
-		if (chan->initialized && !chan->inuse) {
-			chan->inuse = true;
-			break;
-		} else {
-			index++;
-			chan = &channels[index];
+	list_for_each_entry(chan, &virtio_chan_list, chan_list) {
+		if (!strcmp(devname, dev_name(&chan->vdev->dev))) {
+			if (!chan->inuse) {
+				chan->inuse = true;
+				found = 1;
+				break;
+			}
+			ret = -EBUSY;
 		}
 	}
 	mutex_unlock(&virtio_9p_lock);
 
-	if (index >= MAX_9P_CHAN) {
+	if (!found) {
 		printk(KERN_ERR "9p: no channels available\n");
-		return -ENODEV;
+		return ret;
 	}
 
 	client->trans = (void *)chan;
@@ -329,11 +318,13 @@
 	struct virtio_chan *chan = vdev->priv;
 
 	BUG_ON(chan->inuse);
+	vdev->config->del_vqs(vdev);
 
-	if (chan->initialized) {
-		vdev->config->del_vqs(vdev);
-		chan->initialized = false;
-	}
+	mutex_lock(&virtio_9p_lock);
+	list_del(&chan->chan_list);
+	mutex_unlock(&virtio_9p_lock);
+	kfree(chan);
+
 }
 
 static struct virtio_device_id id_table[] = {
@@ -364,10 +355,7 @@
 /* The standard init function */
 static int __init p9_virtio_init(void)
 {
-	int count;
-
-	for (count = 0; count < MAX_9P_CHAN; count++)
-		channels[count].initialized = false;
+	INIT_LIST_HEAD(&virtio_chan_list);
 
 	v9fs_register_trans(&p9_virtio_trans);
 	return register_virtio_driver(&p9_virtio_drv);
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 400efa2..4db7ae2 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3937,7 +3937,9 @@
 	return 0;
 }
 
-static ssize_t l2cap_sysfs_show(struct class *dev, char *buf)
+static ssize_t l2cap_sysfs_show(struct class *dev,
+				struct class_attribute *attr,
+				char *buf)
 {
 	struct sock *sk;
 	struct hlist_node *node;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 89f4a59..db8a68e 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2098,7 +2098,9 @@
 	.security_cfm	= rfcomm_security_cfm
 };
 
-static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, char *buf)
+static ssize_t rfcomm_dlc_sysfs_show(struct class *dev,
+				     struct class_attribute *attr,
+				     char *buf)
 {
 	struct rfcomm_session *s;
 	struct list_head *pp, *p;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 4b5968d..ca87d6a 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -1061,7 +1061,9 @@
 	return result;
 }
 
-static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf)
+static ssize_t rfcomm_sock_sysfs_show(struct class *dev,
+				      struct class_attribute *attr,
+				      char *buf)
 {
 	struct sock *sk;
 	struct hlist_node *node;
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index dd8f6ec..f93b939 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -953,7 +953,9 @@
 	return 0;
 }
 
-static ssize_t sco_sysfs_show(struct class *dev, char *buf)
+static ssize_t sco_sysfs_show(struct class *dev,
+				struct class_attribute *attr,
+				char *buf)
 {
 	struct sock *sk;
 	struct hlist_node *node;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 1cf2cef..fef0384 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -423,7 +423,7 @@
 
 #ifdef CONFIG_SYSFS
 /* br_sysfs_if.c */
-extern struct sysfs_ops brport_sysfs_ops;
+extern const struct sysfs_ops brport_sysfs_ops;
 extern int br_sysfs_addif(struct net_bridge_port *p);
 
 /* br_sysfs_br.c */
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 696596c..0b99164 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -238,7 +238,7 @@
 	return ret;
 }
 
-struct sysfs_ops brport_sysfs_ops = {
+const struct sysfs_ops brport_sysfs_ops = {
 	.show = brport_show,
 	.store = brport_store,
 };
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index a17629b..b2e6bbc 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -134,7 +134,7 @@
 }
 
 /* This function calculates a "timeout" which is equivalent to the timeout of a
- * TCP connection after "boundary" unsucessful, exponentially backed-off
+ * TCP connection after "boundary" unsuccessful, exponentially backed-off
  * retransmissions with an initial RTO of TCP_RTO_MIN.
  */
 static bool retransmits_timed_out(struct sock *sk,
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index bc4e20e..1a29c4a 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -744,7 +744,7 @@
 		break;
 	default:
 		/* should not get here, PLINK_BLOCKED is dealt with at the
-		 * beggining of the function
+		 * beginning of the function
 		 */
 		spin_unlock_bh(&sta->lock);
 		break;
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 8dd75d9..c6cd1b8 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -284,7 +284,7 @@
  * tabs, spaces and continuation lines, which are treated as a single whitespace
  * character.
  *
- * Some headers may appear multiple times. A comma seperated list of values is
+ * Some headers may appear multiple times. A comma separated list of values is
  * equivalent to multiple headers.
  */
 static const struct sip_header ct_sip_hdrs[] = {
@@ -421,7 +421,7 @@
 }
 EXPORT_SYMBOL_GPL(ct_sip_get_header);
 
-/* Get next header field in a list of comma seperated values */
+/* Get next header field in a list of comma separated values */
 static int ct_sip_next_header(const struct nf_conn *ct, const char *dptr,
 			      unsigned int dataoff, unsigned int datalen,
 			      enum sip_header_types type,
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index d952806..9e9c489 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -1,6 +1,6 @@
 /*
  *	xt_hashlimit - Netfilter module to limit the number of packets per time
- *	seperately for each hashbucket (sourceip/sourceport/dstip/dstport)
+ *	separately for each hashbucket (sourceip/sourceport/dstip/dstport)
  *
  *	(C) 2003-2004 by Harald Welte <laforge@netfilter.org>
  *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 4e4ca65..500886b 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -475,7 +475,7 @@
 	 * used to provide an upper bound to this doubling operation.
 	 *
 	 * Special Case:  the first HB doesn't trigger exponential backoff.
-	 * The first unacknowleged HB triggers it.  We do this with a flag
+	 * The first unacknowledged HB triggers it.  We do this with a flag
 	 * that indicates that we have an outstanding HB.
 	 */
 	if (!is_hb || transport->hb_sent) {
diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c
index 6dcdd25..f845d9d 100644
--- a/net/sunrpc/addr.c
+++ b/net/sunrpc/addr.c
@@ -71,8 +71,9 @@
 	if (unlikely(len == 0))
 		return len;
 
-	if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) &&
-	    !(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_SITELOCAL))
+	if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
+		return len;
+	if (sin6->sin6_scope_id == 0)
 		return len;
 
 	rc = snprintf(scopebuf, sizeof(scopebuf), "%c%u",
@@ -165,8 +166,7 @@
 	if (*delim != IPV6_SCOPE_DELIMITER)
 		return 0;
 
-	if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) &&
-	    !(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_SITELOCAL))
+	if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
 		return 0;
 
 	len = (buf + buflen) - delim - 1;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index f7a7f83..0cfccc2a 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -206,8 +206,14 @@
 	ctx->gc_win = window_size;
 	/* gssd signals an error by passing ctx->gc_win = 0: */
 	if (ctx->gc_win == 0) {
-		/* in which case, p points to  an error code which we ignore */
-		p = ERR_PTR(-EACCES);
+		/*
+		 * in which case, p points to an error code. Anything other
+		 * than -EKEYEXPIRED gets converted to -EACCES.
+		 */
+		p = simple_get_bytes(p, end, &ret, sizeof(ret));
+		if (!IS_ERR(p))
+			p = (ret == -EKEYEXPIRED) ? ERR_PTR(-EKEYEXPIRED) :
+						    ERR_PTR(-EACCES);
 		goto err;
 	}
 	/* copy the opaque wire context */
@@ -646,6 +652,7 @@
 		err = PTR_ERR(p);
 		switch (err) {
 		case -EACCES:
+		case -EKEYEXPIRED:
 			gss_msg->msg.errno = err;
 			err = mlen;
 			break;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 9ea4538..8d63f8f 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -999,19 +999,14 @@
 	inode = rpc_get_inode(sb, S_IFDIR | 0755);
 	if (!inode)
 		return -ENOMEM;
-	root = d_alloc_root(inode);
+	sb->s_root = root = d_alloc_root(inode);
 	if (!root) {
 		iput(inode);
 		return -ENOMEM;
 	}
 	if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
-		goto out;
-	sb->s_root = root;
+		return -ENOMEM;
 	return 0;
-out:
-	d_genocide(root);
-	dput(root);
-	return -ENOMEM;
 }
 
 static int
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 538ca43..8420a42 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -133,7 +133,7 @@
 		return SVC_POOL_PERNODE;
 	}
 
-	node = any_online_node(node_online_map);
+	node = first_online_node;
 	if (nr_cpus_node(node) > 2) {
 		/*
 		 * Non-trivial SMP, or CONFIG_NUMA on
@@ -506,6 +506,10 @@
 {
 	unsigned int pages, arghi;
 
+	/* bc_xprt uses fore channel allocated buffers */
+	if (svc_is_backchannel(rqstp))
+		return 1;
+
 	pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply.
 				       * We assume one is at most one page
 				       */
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 7d1f9e9..8f0f1fb 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -173,11 +173,13 @@
 		.sin_addr.s_addr	= htonl(INADDR_ANY),
 		.sin_port		= htons(port),
 	};
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	struct sockaddr_in6 sin6 = {
 		.sin6_family		= AF_INET6,
 		.sin6_addr		= IN6ADDR_ANY_INIT,
 		.sin6_port		= htons(port),
 	};
+#endif	/* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
 	struct sockaddr *sap;
 	size_t len;
 
@@ -186,10 +188,12 @@
 		sap = (struct sockaddr *)&sin;
 		len = sizeof(sin);
 		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case PF_INET6:
 		sap = (struct sockaddr *)&sin6;
 		len = sizeof(sin6);
 		break;
+#endif	/* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
 	default:
 		return ERR_PTR(-EAFNOSUPPORT);
 	}
@@ -231,7 +235,10 @@
  err:
 	spin_unlock(&svc_xprt_class_lock);
 	dprintk("svc: transport %s not found\n", xprt_name);
-	return -ENOENT;
+
+	/* This errno is exposed to user space.  Provide a reasonable
+	 * perror msg for a bad transport. */
+	return -EPROTONOSUPPORT;
 }
 EXPORT_SYMBOL_GPL(svc_create_xprt);
 
@@ -699,8 +706,10 @@
 	spin_unlock_bh(&pool->sp_lock);
 
 	len = 0;
-	if (test_bit(XPT_LISTENER, &xprt->xpt_flags) &&
-	    !test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
+	if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
+		dprintk("svc_recv: found XPT_CLOSE\n");
+		svc_delete_xprt(xprt);
+	} else if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
 		struct svc_xprt *newxpt;
 		newxpt = xprt->xpt_ops->xpo_accept(xprt);
 		if (newxpt) {
@@ -726,7 +735,7 @@
 			svc_xprt_received(newxpt);
 		}
 		svc_xprt_received(xprt);
-	} else if (!test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
+	} else {
 		dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",
 			rqstp, pool->sp_id, xprt,
 			atomic_read(&xprt->xpt_ref.refcount));
@@ -739,11 +748,6 @@
 		dprintk("svc: got len=%d\n", len);
 	}
 
-	if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
-		dprintk("svc_recv: found XPT_CLOSE\n");
-		svc_delete_xprt(xprt);
-	}
-
 	/* No data, incomplete (TCP) read, or accept() */
 	if (len == 0 || len == -EAGAIN) {
 		rqstp->rq_res.len = 0;
@@ -889,11 +893,8 @@
 	if (test_bit(XPT_TEMP, &xprt->xpt_flags))
 		serv->sv_tmpcnt--;
 
-	for (dr = svc_deferred_dequeue(xprt); dr;
-	     dr = svc_deferred_dequeue(xprt)) {
-		svc_xprt_put(xprt);
+	while ((dr = svc_deferred_dequeue(xprt)) != NULL)
 		kfree(dr);
-	}
 
 	svc_xprt_put(xprt);
 	spin_unlock_bh(&serv->sv_lock);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index d8c0411..afdcb04 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #define RPCDBG_FACILITY	RPCDBG_AUTH
 
+#include <linux/sunrpc/clnt.h>
 
 /*
  * AUTHUNIX and AUTHNULL credentials are both handled here.
@@ -187,10 +188,13 @@
 	 * for scratch: */
 	char *buf = mesg;
 	int len;
-	int b1, b2, b3, b4, b5, b6, b7, b8;
-	char c;
 	char class[8];
-	struct in6_addr addr;
+	union {
+		struct sockaddr		sa;
+		struct sockaddr_in	s4;
+		struct sockaddr_in6	s6;
+	} address;
+	struct sockaddr_in6 sin6;
 	int err;
 
 	struct ip_map *ipmp;
@@ -209,24 +213,24 @@
 	len = qword_get(&mesg, buf, mlen);
 	if (len <= 0) return -EINVAL;
 
-	if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) == 4) {
-		addr.s6_addr32[0] = 0;
-		addr.s6_addr32[1] = 0;
-		addr.s6_addr32[2] = htonl(0xffff);
-		addr.s6_addr32[3] =
-			htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
-       } else if (sscanf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x%c",
-			&b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
-		addr.s6_addr16[0] = htons(b1);
-		addr.s6_addr16[1] = htons(b2);
-		addr.s6_addr16[2] = htons(b3);
-		addr.s6_addr16[3] = htons(b4);
-		addr.s6_addr16[4] = htons(b5);
-		addr.s6_addr16[5] = htons(b6);
-		addr.s6_addr16[6] = htons(b7);
-		addr.s6_addr16[7] = htons(b8);
-       } else
+	if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0)
 		return -EINVAL;
+	switch (address.sa.sa_family) {
+	case AF_INET:
+		/* Form a mapped IPv4 address in sin6 */
+		memset(&sin6, 0, sizeof(sin6));
+		sin6.sin6_family = AF_INET6;
+		sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
+		sin6.sin6_addr.s6_addr32[3] = address.s4.sin_addr.s_addr;
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		memcpy(&sin6, &address.s6, sizeof(sin6));
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
 
 	expiry = get_expiry(&mesg);
 	if (expiry ==0)
@@ -243,7 +247,8 @@
 	} else
 		dom = NULL;
 
-	ipmp = ip_map_lookup(class, &addr);
+	/* IPv6 scope IDs are ignored for now */
+	ipmp = ip_map_lookup(class, &sin6.sin6_addr);
 	if (ipmp) {
 		err = ip_map_update(ipmp,
 			     container_of(dom, struct unix_domain, h),
@@ -619,7 +624,7 @@
 	else
 		glen = 0;
 
-	seq_printf(m, "%d %d:", ug->uid, glen);
+	seq_printf(m, "%u %d:", ug->uid, glen);
 	for (i = 0; i < glen; i++)
 		seq_printf(m, " %d", GROUP_AT(ug->gi, i));
 	seq_printf(m, "\n");
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 870929e..a29f259 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -968,6 +968,7 @@
 	return len;
  err_delete:
 	set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
+	svc_xprt_received(&svsk->sk_xprt);
  err_again:
 	return -EAGAIN;
 }
@@ -1357,7 +1358,7 @@
 
 	if (!so)
 		return err;
-	if (so->sk->sk_family != AF_INET)
+	if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6))
 		err =  -EAFNOSUPPORT;
 	else if (so->sk->sk_protocol != IPPROTO_TCP &&
 	    so->sk->sk_protocol != IPPROTO_UDP)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 4f55ab7..75ab08e 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1911,6 +1911,11 @@
 	case -EALREADY:
 		xprt_clear_connecting(xprt);
 		return;
+	case -EINVAL:
+		/* Happens, for instance, if the user specified a link
+		 * local IPv6 address without a scope-id.
+		 */
+		goto out;
 	}
 out_eagain:
 	status = -EAGAIN;
@@ -2099,7 +2104,7 @@
  * we allocate pages instead doing a kmalloc like rpc_malloc is because we want
  * to use the server side send routines.
  */
-void *bc_malloc(struct rpc_task *task, size_t size)
+static void *bc_malloc(struct rpc_task *task, size_t size)
 {
 	struct page *page;
 	struct rpc_buffer *buf;
@@ -2119,7 +2124,7 @@
 /*
  * Free the space allocated in the bc_alloc routine
  */
-void bc_free(void *buffer)
+static void bc_free(void *buffer)
 {
 	struct rpc_buffer *buf;
 
diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c
index c69cbe9..bd0f337 100644
--- a/samples/hw_breakpoint/data_breakpoint.c
+++ b/samples/hw_breakpoint/data_breakpoint.c
@@ -34,7 +34,7 @@
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
 
-struct perf_event **sample_hbp;
+struct perf_event * __percpu *sample_hbp;
 
 static char ksym_name[KSYM_NAME_LEN] = "pid_max";
 module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
@@ -61,8 +61,8 @@
 	attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;
 
 	sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler);
-	if (IS_ERR(sample_hbp)) {
-		ret = PTR_ERR(sample_hbp);
+	if (IS_ERR((void __force *)sample_hbp)) {
+		ret = PTR_ERR((void __force *)sample_hbp);
 		goto fail;
 	}
 
diff --git a/samples/kobject/kobject-example.c b/samples/kobject/kobject-example.c
index 8d9b55a..86ea0c3 100644
--- a/samples/kobject/kobject-example.c
+++ b/samples/kobject/kobject-example.c
@@ -44,7 +44,7 @@
 	__ATTR(foo, 0666, foo_show, foo_store);
 
 /*
- * More complex function where we determine which varible is being accessed by
+ * More complex function where we determine which variable is being accessed by
  * looking at the attribute for the "baz" and "bar" files.
  */
 static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr,
@@ -79,7 +79,7 @@
 
 
 /*
- * Create a group of attributes so that we can create and destory them all
+ * Create a group of attributes so that we can create and destroy them all
  * at once.
  */
 static struct attribute *attrs[] = {
diff --git a/samples/kobject/kset-example.c b/samples/kobject/kset-example.c
index 45b7d56..3b126d1 100644
--- a/samples/kobject/kset-example.c
+++ b/samples/kobject/kset-example.c
@@ -87,7 +87,7 @@
 }
 
 /* Our custom sysfs_ops that we will associate with our ktype later on */
-static struct sysfs_ops foo_sysfs_ops = {
+static const struct sysfs_ops foo_sysfs_ops = {
 	.show = foo_attr_show,
 	.store = foo_attr_store,
 };
@@ -127,7 +127,7 @@
 	__ATTR(foo, 0666, foo_show, foo_store);
 
 /*
- * More complex function where we determine which varible is being accessed by
+ * More complex function where we determine which variable is being accessed by
  * looking at the attribute for the "baz" and "bar" files.
  */
 static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
@@ -161,7 +161,7 @@
 	__ATTR(bar, 0666, b_show, b_store);
 
 /*
- * Create a group of attributes so that we can create and destory them all
+ * Create a group of attributes so that we can create and destroy them all
  * at once.
  */
 static struct attribute *foo_default_attrs[] = {
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 3257d3d..a4d7434 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -145,11 +145,14 @@
 			__kprobes|
 			__ref
 		}x;
+
+# Notes to $Attribute:
+# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
 our $Attribute	= qr{
 			const|
 			__read_mostly|
 			__kprobes|
-			__(?:mem|cpu|dev|)(?:initdata|init)|
+			__(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
 			____cacheline_aligned|
 			____cacheline_aligned_in_smp|
 			____cacheline_internodealigned_in_smp|
@@ -189,6 +192,14 @@
 	atomic_t
 )};
 
+our $logFunctions = qr{(?x:
+	printk|
+	pr_(debug|dbg|vdbg|devel|info|warning|err|notice|alert|crit|emerg|cont)|
+	dev_(printk|dbg|vdbg|info|warn|err|notice|alert|crit|emerg|WARN)|
+	WARN|
+	panic
+)};
+
 our @typeList = (
 	qr{void},
 	qr{(?:unsigned\s+)?char},
@@ -1377,12 +1388,17 @@
 #80 column limit
 		if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
 		    $rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
-		    $line !~ /^\+\s*printk\s*\(\s*(?:KERN_\S+\s*)?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ &&
+		    $line !~ /^\+\s*$logFunctions\s*\(\s*(?:KERN_\S+\s*)?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ &&
 		    $length > 80)
 		{
 			WARN("line over 80 characters\n" . $herecurr);
 		}
 
+# check for spaces before a quoted newline
+		if ($rawline =~ /^.*\".*\s\\n/) {
+			WARN("unnecessary whitespace before a quoted newline\n" . $herecurr);
+		}
+
 # check for adding lines without a newline.
 		if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
 			WARN("adding a line without newline at end of file\n" . $herecurr);
@@ -1411,6 +1427,12 @@
 			ERROR("code indent should use tabs where possible\n" . $herevet);
 		}
 
+# check for space before tabs.
+		if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
+			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+			WARN("please, no space before tabs\n" . $herevet);
+		}
+
 # check we are in a valid C source file if not then ignore this hunk
 		next if ($realfile !~ /\.(h|c)$/);
 
@@ -2182,8 +2204,10 @@
 				# Find out how long the conditional actually is.
 				my @newlines = ($c =~ /\n/gs);
 				my $cond_lines = 1 + $#newlines;
+				my $stat_real = '';
 
-				my $stat_real = raw_line($linenr, $cond_lines);
+				$stat_real = raw_line($linenr, $cond_lines)
+							. "\n" if ($cond_lines);
 				if (defined($stat_real) && $cond_lines > 1) {
 					$stat_real = "[...]\n$stat_real";
 				}
@@ -2348,6 +2372,8 @@
 				DECLARE_PER_CPU|
 				DEFINE_PER_CPU|
 				__typeof__\(|
+				union|
+				struct|
 				\.$Ident\s*=\s*|
 				^\"|\"$
 			}x;
@@ -2572,6 +2598,11 @@
 			WARN("plain inline is preferred over $1\n" . $herecurr);
 		}
 
+# check for sizeof(&)
+		if ($line =~ /\bsizeof\s*\(\s*\&/) {
+			WARN("sizeof(& should be avoided\n" . $herecurr);
+		}
+
 # check for new externs in .c files.
 		if ($realfile =~ /\.c$/ && defined $stat &&
 		    $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
@@ -2634,9 +2665,46 @@
 		if ($line =~ /^.\s*__initcall\s*\(/) {
 			WARN("please use device_initcall() instead of __initcall()\n" . $herecurr);
 		}
-# check for struct file_operations, ensure they are const.
+# check for various ops structs, ensure they are const.
+		my $struct_ops = qr{acpi_dock_ops|
+				address_space_operations|
+				backlight_ops|
+				block_device_operations|
+				dentry_operations|
+				dev_pm_ops|
+				dma_map_ops|
+				extent_io_ops|
+				file_lock_operations|
+				file_operations|
+				hv_ops|
+				ide_dma_ops|
+				intel_dvo_dev_ops|
+				item_operations|
+				iwl_ops|
+				kgdb_arch|
+				kgdb_io|
+				kset_uevent_ops|
+				lock_manager_operations|
+				microcode_ops|
+				mtrr_ops|
+				neigh_ops|
+				nlmsvc_binding|
+				pci_raw_ops|
+				pipe_buf_operations|
+				platform_hibernation_ops|
+				platform_suspend_ops|
+				proto_ops|
+				rpc_pipe_ops|
+				seq_operations|
+				snd_ac97_build_ops|
+				soc_pcmcia_socket_ops|
+				stacktrace_ops|
+				sysfs_ops|
+				tty_operations|
+				usb_mon_operations|
+				wd_ops}x;
 		if ($line !~ /\bconst\b/ &&
-		    $line =~ /\bstruct\s+(file_operations|seq_operations)\b/) {
+		    $line =~ /\bstruct\s+($struct_ops)\b/) {
 			WARN("struct $1 should normally be const\n" .
 				$herecurr);
 		}
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 2f3230d..f76f3d1 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -41,6 +41,8 @@
 my $subsystem = 0;
 my $status = 0;
 my $keywords = 1;
+my $sections = 0;
+my $file_emails = 0;
 my $from_filename = 0;
 my $pattern_depth = 0;
 my $version = 0;
@@ -120,9 +122,11 @@
 		'web!' => \$web,
 		'pattern-depth=i' => \$pattern_depth,
 		'k|keywords!' => \$keywords,
+		'sections!' => \$sections,
+		'fe|file-emails!' => \$file_emails,
 		'f|file' => \$from_filename,
 		'v|version' => \$version,
-		'h|help' => \$help,
+		'h|help|usage' => \$help,
 		)) {
     die "$P: invalid argument - use --help if necessary\n";
 }
@@ -137,9 +141,9 @@
     exit 0;
 }
 
-if ($#ARGV < 0) {
-    usage();
-    die "$P: argument missing: patchfile or -f file please\n";
+if (-t STDIN && !@ARGV) {
+    # We're talking to a terminal, but have no command line arguments.
+    die "$P: missing patchfile or -f file - use --help if necessary\n";
 }
 
 if ($output_separator ne ", ") {
@@ -150,16 +154,24 @@
     $output_roles = 1;
 }
 
-my $selections = $email + $scm + $status + $subsystem + $web;
-if ($selections == 0) {
-    usage();
-    die "$P:  Missing required option: email, scm, status, subsystem or web\n";
+if ($sections) {
+    $email = 0;
+    $email_list = 0;
+    $scm = 0;
+    $status = 0;
+    $subsystem = 0;
+    $web = 0;
+    $keywords = 0;
+} else {
+    my $selections = $email + $scm + $status + $subsystem + $web;
+    if ($selections == 0) {
+	die "$P:  Missing required option: email, scm, status, subsystem or web\n";
+    }
 }
 
 if ($email &&
     ($email_maintainer + $email_list + $email_subscriber_list +
      $email_git + $email_git_penguin_chiefs + $email_git_blame) == 0) {
-    usage();
     die "$P: Please select at least 1 email option\n";
 }
 
@@ -173,8 +185,9 @@
 my @typevalue = ();
 my %keyword_hash;
 
-open(MAINT, "<${lk_path}MAINTAINERS") || die "$P: Can't open MAINTAINERS\n";
-while (<MAINT>) {
+open (my $maint, '<', "${lk_path}MAINTAINERS")
+    or die "$P: Can't open MAINTAINERS: $!\n";
+while (<$maint>) {
     my $line = $_;
 
     if ($line =~ m/^(\C):\s*(.*)/) {
@@ -199,13 +212,14 @@
 	push(@typevalue, $line);
     }
 }
-close(MAINT);
+close($maint);
 
 my %mailmap;
 
 if ($email_remove_duplicates) {
-    open(MAILMAP, "<${lk_path}.mailmap") || warn "$P: Can't open .mailmap\n";
-    while (<MAILMAP>) {
+    open(my $mailmap, '<', "${lk_path}.mailmap")
+	or warn "$P: Can't open .mailmap: $!\n";
+    while (<$mailmap>) {
 	my $line = $_;
 
 	next if ($line =~ m/^\s*#/);
@@ -224,7 +238,7 @@
 	    $mailmap{$name} = \@arr;
 	}
     }
-    close(MAILMAP);
+    close($mailmap);
 }
 
 ## use the filenames on the command line or find the filenames in the patchfiles
@@ -232,31 +246,47 @@
 my @files = ();
 my @range = ();
 my @keyword_tvi = ();
+my @file_emails = ();
+
+if (!@ARGV) {
+    push(@ARGV, "&STDIN");
+}
 
 foreach my $file (@ARGV) {
-    ##if $file is a directory and it lacks a trailing slash, add one
-    if ((-d $file)) {
-	$file =~ s@([^/])$@$1/@;
-    } elsif (!(-f $file)) {
-	die "$P: file '${file}' not found\n";
+    if ($file ne "&STDIN") {
+	##if $file is a directory and it lacks a trailing slash, add one
+	if ((-d $file)) {
+	    $file =~ s@([^/])$@$1/@;
+	} elsif (!(-f $file)) {
+	    die "$P: file '${file}' not found\n";
+	}
     }
     if ($from_filename) {
 	push(@files, $file);
-	if (-f $file && $keywords) {
-	    open(FILE, "<$file") or die "$P: Can't open ${file}\n";
-	    my $text = do { local($/) ; <FILE> };
-	    foreach my $line (keys %keyword_hash) {
-		if ($text =~ m/$keyword_hash{$line}/x) {
-		    push(@keyword_tvi, $line);
+	if (-f $file && ($keywords || $file_emails)) {
+	    open(my $f, '<', $file)
+		or die "$P: Can't open $file: $!\n";
+	    my $text = do { local($/) ; <$f> };
+	    close($f);
+	    if ($keywords) {
+		foreach my $line (keys %keyword_hash) {
+		    if ($text =~ m/$keyword_hash{$line}/x) {
+			push(@keyword_tvi, $line);
+		    }
 		}
 	    }
-	    close(FILE);
+	    if ($file_emails) {
+		my @poss_addr = $text =~ m$[A-Za-zÀ-ÿ\"\' \,\.\+-]*\s*[\,]*\s*[\(\<\{]{0,1}[A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+\.[A-Za-z0-9]+[\)\>\}]{0,1}$g;
+		push(@file_emails, clean_file_emails(@poss_addr));
+	    }
 	}
     } else {
 	my $file_cnt = @files;
 	my $lastfile;
-	open(PATCH, "<$file") or die "$P: Can't open ${file}\n";
-	while (<PATCH>) {
+
+	open(my $patch, '<', $file)
+	    or die "$P: Can't open $file: $!\n";
+	while (<$patch>) {
 	    my $patch_line = $_;
 	    if (m/^\+\+\+\s+(\S+)/) {
 		my $filename = $1;
@@ -276,7 +306,8 @@
 		}
 	    }
 	}
-	close(PATCH);
+	close($patch);
+
 	if ($file_cnt == @files) {
 	    warn "$P: file '${file}' doesn't appear to be a patch.  "
 		. "Add -f to options?\n";
@@ -285,6 +316,8 @@
     }
 }
 
+@file_emails = uniq(@file_emails);
+
 my @email_to = ();
 my @list_to = ();
 my @scm = ();
@@ -314,6 +347,7 @@
 		if ($type eq 'X') {
 		    if (file_match_pattern($file, $value)) {
 			$exclude = 1;
+			last;
 		    }
 		}
 	    }
@@ -340,12 +374,28 @@
 	    }
 	}
 
-	$tvi += ($end - $start);
-
+	$tvi = $end + 1;
     }
 
     foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
 	add_categories($line);
+	    if ($sections) {
+		my $i;
+		my $start = find_starting_index($line);
+		my $end = find_ending_index($line);
+		for ($i = $start; $i < $end; $i++) {
+		    my $line = $typevalue[$i];
+		    if ($line =~ /^[FX]:/) {		##Restore file patterns
+			$line =~ s/([^\\])\.([^\*])/$1\?$2/g;
+			$line =~ s/([^\\])\.$/$1\?/g;	##Convert . back to ?
+			$line =~ s/\\\./\./g;       	##Convert \. to .
+			$line =~ s/\.\*/\*/g;       	##Convert .* to *
+		    }
+		    $line =~ s/^([A-Z]):/$1:\t/g;
+		    print("$line\n");
+		}
+		print("\n");
+	    }
     }
 
     if ($email && $email_git) {
@@ -377,6 +427,14 @@
 	    }
 	}
     }
+
+    foreach my $email (@file_emails) {
+	my ($name, $address) = parse_email($email);
+
+	my $tmp_email = format_email($name, $address, $email_usename);
+	push_email_address($tmp_email, '');
+	add_role($tmp_email, 'in file');
+    }
 }
 
 if ($email || $email_list) {
@@ -453,6 +511,7 @@
     --remove-duplicates => minimize duplicate email names/addresses
     --roles => show roles (status:subsystem, git-signer, list, etc...)
     --rolestats => show roles and statistics (commits/total_commits, %)
+    --file-emails => add email addresses found in -f file (default: 0 (off))
   --scm => print SCM tree(s) if any
   --status => print status if any
   --subsystem => print subsystem name if any
@@ -466,6 +525,7 @@
 Other options:
   --pattern-depth => Number of pattern directory traversals (default: 0 (all))
   --keywords => scan patch for keywords (default: 1 (on))
+  --sections => print the entire subsystem sections with pattern matches
   --version => show version
   --help => show this help information
 
@@ -545,7 +605,7 @@
     $name =~ s/^\"|\"$//g;
     $address =~ s/^\s+|\s+$//g;
 
-    if ($name =~ /[^a-z0-9 \.\-]/i) {    ##has "must quote" chars
+    if ($name =~ /[^\w \-]/i) {  	 ##has "must quote" chars
 	$name =~ s/(?<!\\)"/\\"/g;       ##escape quotes
 	$name = "\"$name\"";
     }
@@ -562,7 +622,7 @@
     $name =~ s/^\"|\"$//g;
     $address =~ s/^\s+|\s+$//g;
 
-    if ($name =~ /[^a-z0-9 \.\-]/i) {    ##has "must quote" chars
+    if ($name =~ /[^\w \-]/i) {          ##has "must quote" chars
 	$name =~ s/(?<!\\)"/\\"/g;       ##escape quotes
 	$name = "\"$name\"";
     }
@@ -811,7 +871,9 @@
     foreach my $entry (@email_to) {
 	if ($email_remove_duplicates) {
 	    my ($entry_name, $entry_address) = parse_email($entry->[0]);
-	    if ($name eq $entry_name || $address eq $entry_address) {
+	    if (($name eq $entry_name || $address eq $entry_address)
+		&& ($role eq "" || !($entry->[1] =~ m/$role/))
+	    ) {
 		if ($entry->[1] eq "") {
 		    $entry->[1] = "$role";
 		} else {
@@ -819,7 +881,9 @@
 		}
 	    }
 	} else {
-	    if ($email eq $entry->[0]) {
+	    if ($email eq $entry->[0]
+		&& ($role eq "" || !($entry->[1] =~ m/$role/))
+	    ) {
 		if ($entry->[1] eq "") {
 		    $entry->[1] = "$role";
 		} else {
@@ -1099,6 +1163,51 @@
     return @parms;
 }
 
+sub clean_file_emails {
+    my (@file_emails) = @_;
+    my @fmt_emails = ();
+
+    foreach my $email (@file_emails) {
+	$email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
+	my ($name, $address) = parse_email($email);
+	if ($name eq '"[,\.]"') {
+	    $name = "";
+	}
+
+	my @nw = split(/[^A-Za-zÀ-ÿ\'\,\.\+-]/, $name);
+	if (@nw > 2) {
+	    my $first = $nw[@nw - 3];
+	    my $middle = $nw[@nw - 2];
+	    my $last = $nw[@nw - 1];
+
+	    if (((length($first) == 1 && $first =~ m/[A-Za-z]/) ||
+		 (length($first) == 2 && substr($first, -1) eq ".")) ||
+		(length($middle) == 1 ||
+		 (length($middle) == 2 && substr($middle, -1) eq "."))) {
+		$name = "$first $middle $last";
+	    } else {
+		$name = "$middle $last";
+	    }
+	}
+
+	if (substr($name, -1) =~ /[,\.]/) {
+	    $name = substr($name, 0, length($name) - 1);
+	} elsif (substr($name, -2) =~ /[,\.]"/) {
+	    $name = substr($name, 0, length($name) - 2) . '"';
+	}
+
+	if (substr($name, 0, 1) =~ /[,\.]/) {
+	    $name = substr($name, 1, length($name) - 1);
+	} elsif (substr($name, 0, 2) =~ /"[,\.]/) {
+	    $name = '"' . substr($name, 2, length($name) - 2);
+	}
+
+	my $fmt_email = format_email($name, $address, $email_usename);
+	push(@fmt_emails, $fmt_email);
+    }
+    return @fmt_emails;
+}
+
 sub merge_email {
     my @lines;
     my %saw;
@@ -1183,7 +1292,7 @@
 
 #   valid: returns true if the parameter is an RFC822 valid address
 #
-sub rfc822_valid ($) {
+sub rfc822_valid {
     my $s = rfc822_strip_comments(shift);
 
     if (!$rfc822re) {
@@ -1203,7 +1312,7 @@
 #              from success with no addresses found, because an empty string is
 #              a valid list.
 
-sub rfc822_validlist ($) {
+sub rfc822_validlist {
     my $s = rfc822_strip_comments(shift);
 
     if (!$rfc822re) {
diff --git a/scripts/gfp-translate b/scripts/gfp-translate
index 073cb6d..d81b968 100644
--- a/scripts/gfp-translate
+++ b/scripts/gfp-translate
@@ -19,7 +19,7 @@
 	exit 0
 }
 
-# Parse command-line arguements
+# Parse command-line arguments
 while [ $# -gt 0 ]; do
 	case $1 in
 		--source)
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 208ad3b..c7865c3 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -2103,7 +2103,7 @@
 		$section = $newsection;
 	    } elsif (/$doc_end/) {
 
-		if ($contents ne "") {
+		if (($contents ne "") && ($contents ne "\n")) {
 		    dump_section($file, $section, xml_escape($contents));
 		    $section = $section_default;
 		    $contents = "";
diff --git a/security/capability.c b/security/capability.c
index 5c700e1..4875142 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -906,10 +906,6 @@
 }
 #endif /* CONFIG_AUDIT */
 
-struct security_operations default_security_ops = {
-	.name	= "default",
-};
-
 #define set_to_cap_if_null(ops, function)				\
 	do {								\
 		if (!ops->function) {					\
diff --git a/security/commoncap.c b/security/commoncap.c
index f800fdb..6166973 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -27,6 +27,7 @@
 #include <linux/sched.h>
 #include <linux/prctl.h>
 #include <linux/securebits.h>
+#include <linux/syslog.h>
 
 /*
  * If a non-root user executes a setuid-root binary in
@@ -888,13 +889,17 @@
 /**
  * cap_syslog - Determine whether syslog function is permitted
  * @type: Function requested
+ * @from_file: Whether this request came from an open file (i.e. /proc)
  *
  * Determine whether the current process is permitted to use a particular
  * syslog function, returning 0 if permission is granted, -ve if not.
  */
-int cap_syslog(int type)
+int cap_syslog(int type, bool from_file)
 {
-	if ((type != 3 && type != 10) && !capable(CAP_SYS_ADMIN))
+	if (type != SYSLOG_ACTION_OPEN && from_file)
+		return 0;
+	if ((type != SYSLOG_ACTION_READ_ALL &&
+	     type != SYSLOG_ACTION_SIZE_BUFFER) && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	return 0;
 }
diff --git a/security/security.c b/security/security.c
index 122b748..687c6fd 100644
--- a/security/security.c
+++ b/security/security.c
@@ -23,10 +23,12 @@
 	CONFIG_DEFAULT_SECURITY;
 
 /* things that live in capability.c */
-extern struct security_operations default_security_ops;
 extern void security_fixup_ops(struct security_operations *ops);
 
-struct security_operations *security_ops;	/* Initialized to NULL */
+static struct security_operations *security_ops;
+static struct security_operations default_security_ops = {
+	.name	= "default",
+};
 
 static inline int verify(struct security_operations *ops)
 {
@@ -63,6 +65,11 @@
 	return 0;
 }
 
+void reset_security_ops(void)
+{
+	security_ops = &default_security_ops;
+}
+
 /* Save user chosen LSM */
 static int __init choose_lsm(char *str)
 {
@@ -203,9 +210,9 @@
 	return security_ops->quota_on(dentry);
 }
 
-int security_syslog(int type)
+int security_syslog(int type, bool from_file)
 {
-	return security_ops->syslog(type);
+	return security_ops->syslog(type, from_file);
 }
 
 int security_settime(struct timespec *ts, struct timezone *tz)
@@ -389,42 +396,42 @@
 EXPORT_SYMBOL(security_inode_init_security);
 
 #ifdef CONFIG_SECURITY_PATH
-int security_path_mknod(struct path *path, struct dentry *dentry, int mode,
+int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
 			unsigned int dev)
 {
-	if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+	if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
 		return 0;
-	return security_ops->path_mknod(path, dentry, mode, dev);
+	return security_ops->path_mknod(dir, dentry, mode, dev);
 }
 EXPORT_SYMBOL(security_path_mknod);
 
-int security_path_mkdir(struct path *path, struct dentry *dentry, int mode)
+int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
 {
-	if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+	if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
 		return 0;
-	return security_ops->path_mkdir(path, dentry, mode);
+	return security_ops->path_mkdir(dir, dentry, mode);
 }
 
-int security_path_rmdir(struct path *path, struct dentry *dentry)
+int security_path_rmdir(struct path *dir, struct dentry *dentry)
 {
-	if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+	if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
 		return 0;
-	return security_ops->path_rmdir(path, dentry);
+	return security_ops->path_rmdir(dir, dentry);
 }
 
-int security_path_unlink(struct path *path, struct dentry *dentry)
+int security_path_unlink(struct path *dir, struct dentry *dentry)
 {
-	if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+	if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
 		return 0;
-	return security_ops->path_unlink(path, dentry);
+	return security_ops->path_unlink(dir, dentry);
 }
 
-int security_path_symlink(struct path *path, struct dentry *dentry,
+int security_path_symlink(struct path *dir, struct dentry *dentry,
 			  const char *old_name)
 {
-	if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+	if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
 		return 0;
-	return security_ops->path_symlink(path, dentry, old_name);
+	return security_ops->path_symlink(dir, dentry, old_name);
 }
 
 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
@@ -630,14 +637,14 @@
 int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
 {
 	if (unlikely(IS_PRIVATE(inode)))
-		return 0;
+		return -EOPNOTSUPP;
 	return security_ops->inode_getsecurity(inode, name, buffer, alloc);
 }
 
 int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
 {
 	if (unlikely(IS_PRIVATE(inode)))
-		return 0;
+		return -EOPNOTSUPP;
 	return security_ops->inode_setsecurity(inode, name, value, size, flags);
 }
 
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index f2dde26..989fef8 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -337,7 +337,7 @@
  * Look up an AVC entry that is valid for the
  * (@ssid, @tsid), interpreting the permissions
  * based on @tclass.  If a valid AVC entry exists,
- * then this function return the avc_node.
+ * then this function returns the avc_node.
  * Otherwise, this function returns NULL.
  */
 static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass)
@@ -489,17 +489,14 @@
 	struct common_audit_data stack_data;
 	u32 denied, audited;
 	denied = requested & ~avd->allowed;
-	if (denied) {
-		audited = denied;
-		if (!(audited & avd->auditdeny))
-			return;
-	} else if (result) {
+	if (denied)
+		audited = denied & avd->auditdeny;
+	else if (result)
 		audited = denied = requested;
-	} else {
-		audited = requested;
-		if (!(audited & avd->auditallow))
-			return;
-	}
+	else
+		audited = requested & avd->auditallow;
+	if (!audited)
+		return;
 	if (!a) {
 		a = &stack_data;
 		memset(a, 0, sizeof(*a));
@@ -526,7 +523,7 @@
  * @perms: permissions
  *
  * Register a callback function for events in the set @events
- * related to the SID pair (@ssid, @tsid) and
+ * related to the SID pair (@ssid, @tsid) 
  * and the permissions @perms, interpreting
  * @perms based on @tclass.  Returns %0 on success or
  * -%ENOMEM if insufficient memory exists to add the callback.
@@ -571,7 +568,7 @@
  *
  * if a valid AVC entry doesn't exist,this function returns -ENOENT.
  * if kmalloc() called internal returns NULL, this function returns -ENOMEM.
- * otherwise, this function update the AVC entry. The original AVC-entry object
+ * otherwise, this function updates the AVC entry. The original AVC-entry object
  * will release later by RCU.
  */
 static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass,
@@ -746,9 +743,7 @@
 		else
 			avd = &avd_entry;
 
-		rc = security_compute_av(ssid, tsid, tclass, requested, avd);
-		if (rc)
-			goto out;
+		security_compute_av(ssid, tsid, tclass, avd);
 		rcu_read_lock();
 		node = avc_insert(ssid, tsid, tclass, avd);
 	} else {
@@ -770,7 +765,6 @@
 	}
 
 	rcu_read_unlock();
-out:
 	return rc;
 }
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9a2ee84..5feecb4 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -76,6 +76,7 @@
 #include <linux/selinux.h>
 #include <linux/mutex.h>
 #include <linux/posix-timers.h>
+#include <linux/syslog.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -125,13 +126,6 @@
 int selinux_enabled = 1;
 #endif
 
-
-/*
- * Minimal support for a secondary security module,
- * just to allow the use of the capability module.
- */
-static struct security_operations *secondary_ops;
-
 /* Lists of inode and superblock security structures initialized
    before the policy was loaded. */
 static LIST_HEAD(superblock_security_head);
@@ -2049,29 +2043,30 @@
 	return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON);
 }
 
-static int selinux_syslog(int type)
+static int selinux_syslog(int type, bool from_file)
 {
 	int rc;
 
-	rc = cap_syslog(type);
+	rc = cap_syslog(type, from_file);
 	if (rc)
 		return rc;
 
 	switch (type) {
-	case 3:		/* Read last kernel messages */
-	case 10:	/* Return size of the log buffer */
+	case SYSLOG_ACTION_READ_ALL:	/* Read last kernel messages */
+	case SYSLOG_ACTION_SIZE_BUFFER:	/* Return size of the log buffer */
 		rc = task_has_system(current, SYSTEM__SYSLOG_READ);
 		break;
-	case 6:		/* Disable logging to console */
-	case 7:		/* Enable logging to console */
-	case 8:		/* Set level of messages printed to console */
+	case SYSLOG_ACTION_CONSOLE_OFF:	/* Disable logging to console */
+	case SYSLOG_ACTION_CONSOLE_ON:	/* Enable logging to console */
+	/* Set level of messages printed to console */
+	case SYSLOG_ACTION_CONSOLE_LEVEL:
 		rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
 		break;
-	case 0:		/* Close log */
-	case 1:		/* Open log */
-	case 2:		/* Read from log */
-	case 4:		/* Read/clear last kernel messages */
-	case 5:		/* Clear ring buffer */
+	case SYSLOG_ACTION_CLOSE:	/* Close log */
+	case SYSLOG_ACTION_OPEN:	/* Open log */
+	case SYSLOG_ACTION_READ:	/* Read from log */
+	case SYSLOG_ACTION_READ_CLEAR:	/* Read/clear last kernel messages */
+	case SYSLOG_ACTION_CLEAR:	/* Clear ring buffer */
 	default:
 		rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
 		break;
@@ -3334,7 +3329,7 @@
 
 	if (ret == 0)
 		tsec->create_sid = isec->sid;
-	return 0;
+	return ret;
 }
 
 static int selinux_kernel_module_request(char *kmod_name)
@@ -5672,9 +5667,6 @@
 					    0, SLAB_PANIC, NULL);
 	avc_init();
 
-	secondary_ops = security_ops;
-	if (!secondary_ops)
-		panic("SELinux: No initial security operations\n");
 	if (register_security(&selinux_ops))
 		panic("SELinux: Unable to register with kernel.\n");
 
@@ -5835,8 +5827,7 @@
 	selinux_disabled = 1;
 	selinux_enabled = 0;
 
-	/* Reset security_ops to the secondary module, dummy or capability. */
-	security_ops = secondary_ops;
+	reset_security_ops();
 
 	/* Try to destroy the avc node cache */
 	avc_disable();
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 2553266..1f7c249 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -57,7 +57,6 @@
 struct netlbl_lsm_secattr;
 
 extern int selinux_enabled;
-extern int selinux_mls_enabled;
 
 /* Policy capabilities */
 enum {
@@ -80,6 +79,8 @@
 /* limitation of boundary depth  */
 #define POLICYDB_BOUNDS_MAXDEPTH	4
 
+int security_mls_enabled(void);
+
 int security_load_policy(void *data, size_t len);
 
 int security_policycap_supported(unsigned int req_cap);
@@ -96,13 +97,11 @@
 /* definitions of av_decision.flags */
 #define AVD_FLAGS_PERMISSIVE	0x0001
 
-int security_compute_av(u32 ssid, u32 tsid,
-			u16 tclass, u32 requested,
-			struct av_decision *avd);
+void security_compute_av(u32 ssid, u32 tsid,
+			 u16 tclass, struct av_decision *avd);
 
-int security_compute_av_user(u32 ssid, u32 tsid,
-			     u16 tclass, u32 requested,
-			     struct av_decision *avd);
+void security_compute_av_user(u32 ssid, u32 tsid,
+			     u16 tclass, struct av_decision *avd);
 
 int security_transition_sid(u32 ssid, u32 tsid,
 			    u16 tclass, u32 *out_sid);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index fab36fd..cd191bb 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -282,7 +282,8 @@
 	char tmpbuf[TMPBUFLEN];
 	ssize_t length;
 
-	length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled);
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%d",
+			   security_mls_enabled());
 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
@@ -494,7 +495,6 @@
 	char *scon, *tcon;
 	u32 ssid, tsid;
 	u16 tclass;
-	u32 req;
 	struct av_decision avd;
 	ssize_t length;
 
@@ -512,7 +512,7 @@
 		goto out;
 
 	length = -EINVAL;
-	if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4)
+	if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
 		goto out2;
 
 	length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
@@ -522,9 +522,7 @@
 	if (length < 0)
 		goto out2;
 
-	length = security_compute_av_user(ssid, tsid, tclass, req, &avd);
-	if (length < 0)
-		goto out2;
+	security_compute_av_user(ssid, tsid, tclass, &avd);
 
 	length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
 			  "%x %x %x %x %u %x",
@@ -979,6 +977,8 @@
 	u32 sid;
 
 	/* remove any existing files */
+	for (i = 0; i < bool_num; i++)
+		kfree(bool_pending_names[i]);
 	kfree(bool_pending_names);
 	kfree(bool_pending_values);
 	bool_pending_names = NULL;
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
index d9dd7a2..45e8fb0 100644
--- a/security/selinux/ss/context.h
+++ b/security/selinux/ss/context.h
@@ -41,9 +41,6 @@
 {
 	int rc;
 
-	if (!selinux_mls_enabled)
-		return 0;
-
 	dst->range.level[0].sens = src->range.level[0].sens;
 	rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
 	if (rc)
@@ -64,9 +61,6 @@
 {
 	int rc;
 
-	if (!selinux_mls_enabled)
-		return 0;
-
 	dst->range.level[0].sens = src->range.level[0].sens;
 	rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
 	if (rc)
@@ -82,9 +76,6 @@
 
 static inline int mls_context_cmp(struct context *c1, struct context *c2)
 {
-	if (!selinux_mls_enabled)
-		return 1;
-
 	return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
 		ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
 		(c1->range.level[1].sens == c2->range.level[1].sens) &&
@@ -93,9 +84,6 @@
 
 static inline void mls_context_destroy(struct context *c)
 {
-	if (!selinux_mls_enabled)
-		return;
-
 	ebitmap_destroy(&c->range.level[0].cat);
 	ebitmap_destroy(&c->range.level[1].cat);
 	mls_context_init(c);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 3f2b270..372b773 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -39,7 +39,7 @@
 	struct ebitmap *e;
 	struct ebitmap_node *node;
 
-	if (!selinux_mls_enabled)
+	if (!policydb.mls_enabled)
 		return 0;
 
 	len = 1; /* for the beginning ":" */
@@ -93,7 +93,7 @@
 	struct ebitmap *e;
 	struct ebitmap_node *node;
 
-	if (!selinux_mls_enabled)
+	if (!policydb.mls_enabled)
 		return;
 
 	scontextp = *scontext;
@@ -200,7 +200,7 @@
 {
 	struct user_datum *usrdatum;
 
-	if (!selinux_mls_enabled)
+	if (!p->mls_enabled)
 		return 1;
 
 	if (!mls_range_isvalid(p, &c->range))
@@ -253,7 +253,7 @@
 	struct cat_datum *catdatum, *rngdatum;
 	int l, rc = -EINVAL;
 
-	if (!selinux_mls_enabled) {
+	if (!pol->mls_enabled) {
 		if (def_sid != SECSID_NULL && oldc)
 			*scontext += strlen(*scontext)+1;
 		return 0;
@@ -387,7 +387,7 @@
 	char *tmpstr, *freestr;
 	int rc;
 
-	if (!selinux_mls_enabled)
+	if (!policydb.mls_enabled)
 		return -EINVAL;
 
 	/* we need freestr because mls_context_to_sid will change
@@ -407,7 +407,7 @@
 /*
  * Copies the MLS range `range' into `context'.
  */
-static inline int mls_range_set(struct context *context,
+int mls_range_set(struct context *context,
 				struct mls_range *range)
 {
 	int l, rc = 0;
@@ -427,7 +427,7 @@
 int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
 			 struct context *usercon)
 {
-	if (selinux_mls_enabled) {
+	if (policydb.mls_enabled) {
 		struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
 		struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
 		struct mls_level *user_low = &(user->range.level[0]);
@@ -477,7 +477,7 @@
 	struct ebitmap_node *node;
 	int l, i;
 
-	if (!selinux_mls_enabled)
+	if (!policydb.mls_enabled)
 		return 0;
 
 	for (l = 0; l < 2; l++) {
@@ -513,23 +513,21 @@
 		    u32 specified,
 		    struct context *newcontext)
 {
-	struct range_trans *rtr;
+	struct range_trans rtr;
+	struct mls_range *r;
 
-	if (!selinux_mls_enabled)
+	if (!policydb.mls_enabled)
 		return 0;
 
 	switch (specified) {
 	case AVTAB_TRANSITION:
 		/* Look for a range transition rule. */
-		for (rtr = policydb.range_tr; rtr; rtr = rtr->next) {
-			if (rtr->source_type == scontext->type &&
-			    rtr->target_type == tcontext->type &&
-			    rtr->target_class == tclass) {
-				/* Set the range from the rule */
-				return mls_range_set(newcontext,
-						     &rtr->target_range);
-			}
-		}
+		rtr.source_type = scontext->type;
+		rtr.target_type = tcontext->type;
+		rtr.target_class = tclass;
+		r = hashtab_search(policydb.range_tr, &rtr);
+		if (r)
+			return mls_range_set(newcontext, r);
 		/* Fallthrough */
 	case AVTAB_CHANGE:
 		if (tclass == policydb.process_class)
@@ -541,8 +539,8 @@
 	case AVTAB_MEMBER:
 		/* Use the process effective MLS attributes. */
 		return mls_context_cpy_low(newcontext, scontext);
-	default:
-		return -EINVAL;
+
+	/* fall through */
 	}
 	return -EINVAL;
 }
@@ -561,7 +559,7 @@
 void mls_export_netlbl_lvl(struct context *context,
 			   struct netlbl_lsm_secattr *secattr)
 {
-	if (!selinux_mls_enabled)
+	if (!policydb.mls_enabled)
 		return;
 
 	secattr->attr.mls.lvl = context->range.level[0].sens - 1;
@@ -581,7 +579,7 @@
 void mls_import_netlbl_lvl(struct context *context,
 			   struct netlbl_lsm_secattr *secattr)
 {
-	if (!selinux_mls_enabled)
+	if (!policydb.mls_enabled)
 		return;
 
 	context->range.level[0].sens = secattr->attr.mls.lvl + 1;
@@ -603,7 +601,7 @@
 {
 	int rc;
 
-	if (!selinux_mls_enabled)
+	if (!policydb.mls_enabled)
 		return 0;
 
 	rc = ebitmap_netlbl_export(&context->range.level[0].cat,
@@ -631,7 +629,7 @@
 {
 	int rc;
 
-	if (!selinux_mls_enabled)
+	if (!policydb.mls_enabled)
 		return 0;
 
 	rc = ebitmap_netlbl_import(&context->range.level[0].cat,
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 1276715..cd91526 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -39,6 +39,8 @@
 
 int mls_from_string(char *str, struct context *context, gfp_t gfp_mask);
 
+int mls_range_set(struct context *context, struct mls_range *range);
+
 int mls_convert_context(struct policydb *oldp,
 			struct policydb *newp,
 			struct context *context);
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h
index b6e943a..03bed52 100644
--- a/security/selinux/ss/mls_types.h
+++ b/security/selinux/ss/mls_types.h
@@ -15,6 +15,7 @@
 #define _SS_MLS_TYPES_H_
 
 #include "security.h"
+#include "ebitmap.h"
 
 struct mls_level {
 	u32 sens;		/* sensitivity */
@@ -27,18 +28,12 @@
 
 static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
 {
-	if (!selinux_mls_enabled)
-		return 1;
-
 	return ((l1->sens == l2->sens) &&
 		ebitmap_cmp(&l1->cat, &l2->cat));
 }
 
 static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
 {
-	if (!selinux_mls_enabled)
-		return 1;
-
 	return ((l1->sens >= l2->sens) &&
 		ebitmap_contains(&l1->cat, &l2->cat));
 }
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index f036672..23c6e53 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -52,8 +52,6 @@
 };
 #endif
 
-int selinux_mls_enabled;
-
 static unsigned int symtab_sizes[SYM_NUM] = {
 	2,
 	32,
@@ -177,6 +175,21 @@
 	goto out;
 }
 
+static u32 rangetr_hash(struct hashtab *h, const void *k)
+{
+	const struct range_trans *key = k;
+	return (key->source_type + (key->target_type << 3) +
+		(key->target_class << 5)) & (h->size - 1);
+}
+
+static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
+{
+	const struct range_trans *key1 = k1, *key2 = k2;
+	return (key1->source_type != key2->source_type ||
+		key1->target_type != key2->target_type ||
+		key1->target_class != key2->target_class);
+}
+
 /*
  * Initialize a policy database structure.
  */
@@ -204,6 +217,10 @@
 	if (rc)
 		goto out_free_symtab;
 
+	p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256);
+	if (!p->range_tr)
+		goto out_free_symtab;
+
 	ebitmap_init(&p->policycaps);
 	ebitmap_init(&p->permissive_map);
 
@@ -408,6 +425,20 @@
 		       info.slots_used, h->size, info.max_chain_len);
 	}
 }
+
+static void rangetr_hash_eval(struct hashtab *h)
+{
+	struct hashtab_info info;
+
+	hashtab_stat(h, &info);
+	printk(KERN_DEBUG "SELinux: rangetr:  %d entries and %d/%d buckets used, "
+	       "longest chain length %d\n", h->nel,
+	       info.slots_used, h->size, info.max_chain_len);
+}
+#else
+static inline void rangetr_hash_eval(struct hashtab *h)
+{
+}
 #endif
 
 /*
@@ -422,7 +453,7 @@
 
 	printk(KERN_DEBUG "SELinux:  %d users, %d roles, %d types, %d bools",
 	       p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
-	if (selinux_mls_enabled)
+	if (p->mls_enabled)
 		printk(", %d sens, %d cats", p->p_levels.nprim,
 		       p->p_cats.nprim);
 	printk("\n");
@@ -612,6 +643,17 @@
 	cat_destroy,
 };
 
+static int range_tr_destroy(void *key, void *datum, void *p)
+{
+	struct mls_range *rt = datum;
+	kfree(key);
+	ebitmap_destroy(&rt->level[0].cat);
+	ebitmap_destroy(&rt->level[1].cat);
+	kfree(datum);
+	cond_resched();
+	return 0;
+}
+
 static void ocontext_destroy(struct ocontext *c, int i)
 {
 	context_destroy(&c->context[0]);
@@ -632,7 +674,6 @@
 	int i;
 	struct role_allow *ra, *lra = NULL;
 	struct role_trans *tr, *ltr = NULL;
-	struct range_trans *rt, *lrt = NULL;
 
 	for (i = 0; i < SYM_NUM; i++) {
 		cond_resched();
@@ -693,20 +734,8 @@
 	}
 	kfree(lra);
 
-	for (rt = p->range_tr; rt; rt = rt->next) {
-		cond_resched();
-		if (lrt) {
-			ebitmap_destroy(&lrt->target_range.level[0].cat);
-			ebitmap_destroy(&lrt->target_range.level[1].cat);
-			kfree(lrt);
-		}
-		lrt = rt;
-	}
-	if (lrt) {
-		ebitmap_destroy(&lrt->target_range.level[0].cat);
-		ebitmap_destroy(&lrt->target_range.level[1].cat);
-		kfree(lrt);
-	}
+	hashtab_map(p->range_tr, range_tr_destroy, NULL);
+	hashtab_destroy(p->range_tr);
 
 	if (p->type_attr_map) {
 		for (i = 0; i < p->p_types.nprim; i++)
@@ -1686,12 +1715,11 @@
 	int i, j, rc;
 	__le32 buf[4];
 	u32 nodebuf[8];
-	u32 len, len2, config, nprim, nel, nel2;
+	u32 len, len2, nprim, nel, nel2;
 	char *policydb_str;
 	struct policydb_compat_info *info;
-	struct range_trans *rt, *lrt;
-
-	config = 0;
+	struct range_trans *rt;
+	struct mls_range *r;
 
 	rc = policydb_init(p);
 	if (rc)
@@ -1740,7 +1768,7 @@
 	kfree(policydb_str);
 	policydb_str = NULL;
 
-	/* Read the version, config, and table sizes. */
+	/* Read the version and table sizes. */
 	rc = next_entry(buf, fp, sizeof(u32)*4);
 	if (rc < 0)
 		goto bad;
@@ -1755,13 +1783,7 @@
 	}
 
 	if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
-		if (ss_initialized && !selinux_mls_enabled) {
-			printk(KERN_ERR "SELinux: Cannot switch between non-MLS"
-				" and MLS policies\n");
-			goto bad;
-		}
-		selinux_mls_enabled = 1;
-		config |= POLICYDB_CONFIG_MLS;
+		p->mls_enabled = 1;
 
 		if (p->policyvers < POLICYDB_VERSION_MLS) {
 			printk(KERN_ERR "SELinux: security policydb version %d "
@@ -1769,12 +1791,6 @@
 				p->policyvers);
 			goto bad;
 		}
-	} else {
-		if (ss_initialized && selinux_mls_enabled) {
-			printk(KERN_ERR "SELinux: Cannot switch between MLS and"
-				" non-MLS policies\n");
-			goto bad;
-		}
 	}
 	p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
 	p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
@@ -2122,44 +2138,61 @@
 		if (rc < 0)
 			goto bad;
 		nel = le32_to_cpu(buf[0]);
-		lrt = NULL;
 		for (i = 0; i < nel; i++) {
 			rt = kzalloc(sizeof(*rt), GFP_KERNEL);
 			if (!rt) {
 				rc = -ENOMEM;
 				goto bad;
 			}
-			if (lrt)
-				lrt->next = rt;
-			else
-				p->range_tr = rt;
 			rc = next_entry(buf, fp, (sizeof(u32) * 2));
-			if (rc < 0)
+			if (rc < 0) {
+				kfree(rt);
 				goto bad;
+			}
 			rt->source_type = le32_to_cpu(buf[0]);
 			rt->target_type = le32_to_cpu(buf[1]);
 			if (new_rangetr) {
 				rc = next_entry(buf, fp, sizeof(u32));
-				if (rc < 0)
+				if (rc < 0) {
+					kfree(rt);
 					goto bad;
+				}
 				rt->target_class = le32_to_cpu(buf[0]);
 			} else
 				rt->target_class = p->process_class;
 			if (!policydb_type_isvalid(p, rt->source_type) ||
 			    !policydb_type_isvalid(p, rt->target_type) ||
 			    !policydb_class_isvalid(p, rt->target_class)) {
+				kfree(rt);
 				rc = -EINVAL;
 				goto bad;
 			}
-			rc = mls_read_range_helper(&rt->target_range, fp);
-			if (rc)
-				goto bad;
-			if (!mls_range_isvalid(p, &rt->target_range)) {
-				printk(KERN_WARNING "SELinux:  rangetrans:  invalid range\n");
+			r = kzalloc(sizeof(*r), GFP_KERNEL);
+			if (!r) {
+				kfree(rt);
+				rc = -ENOMEM;
 				goto bad;
 			}
-			lrt = rt;
+			rc = mls_read_range_helper(r, fp);
+			if (rc) {
+				kfree(rt);
+				kfree(r);
+				goto bad;
+			}
+			if (!mls_range_isvalid(p, r)) {
+				printk(KERN_WARNING "SELinux:  rangetrans:  invalid range\n");
+				kfree(rt);
+				kfree(r);
+				goto bad;
+			}
+			rc = hashtab_insert(p->range_tr, rt, r);
+			if (rc) {
+				kfree(rt);
+				kfree(r);
+				goto bad;
+			}
 		}
+		rangetr_hash_eval(p->range_tr);
 	}
 
 	p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL);
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index cdcc570..26d9adf 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -27,6 +27,8 @@
 #include "symtab.h"
 #include "avtab.h"
 #include "sidtab.h"
+#include "ebitmap.h"
+#include "mls_types.h"
 #include "context.h"
 #include "constraint.h"
 
@@ -113,8 +115,6 @@
 	u32 source_type;
 	u32 target_type;
 	u32 target_class;
-	struct mls_range target_range;
-	struct range_trans *next;
 };
 
 /* Boolean data type */
@@ -187,6 +187,8 @@
 
 /* The policy database */
 struct policydb {
+	int mls_enabled;
+
 	/* symbol tables */
 	struct symtab symtab[SYM_NUM];
 #define p_commons symtab[SYM_COMMONS]
@@ -240,8 +242,8 @@
 	   fixed labeling behavior. */
 	struct genfs *genfs;
 
-	/* range transitions */
-	struct range_trans *range_tr;
+	/* range transitions table (range_trans_key -> mls_range) */
+	struct hashtab *range_tr;
 
 	/* type -> attribute reverse mapping */
 	struct ebitmap *type_attr_map;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b3efae2..cf27b3e 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -26,6 +26,10 @@
  *
  *  Added support for bounds domain and audit messaged on masked permissions
  *
+ * Updated: Guido Trentalancia <guido@trentalancia.com>
+ *
+ *  Added support for runtime switching of the policy type
+ *
  * Copyright (C) 2008, 2009 NEC Corporation
  * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
  * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
@@ -87,11 +91,10 @@
 static int context_struct_to_string(struct context *context, char **scontext,
 				    u32 *scontext_len);
 
-static int context_struct_compute_av(struct context *scontext,
-				     struct context *tcontext,
-				     u16 tclass,
-				     u32 requested,
-				     struct av_decision *avd);
+static void context_struct_compute_av(struct context *scontext,
+				      struct context *tcontext,
+				      u16 tclass,
+				      struct av_decision *avd);
 
 struct selinux_mapping {
 	u16 value; /* policy value */
@@ -196,23 +199,6 @@
 	return tclass;
 }
 
-static u32 unmap_perm(u16 tclass, u32 tperm)
-{
-	if (tclass < current_mapping_size) {
-		unsigned i;
-		u32 kperm = 0;
-
-		for (i = 0; i < current_mapping[tclass].num_perms; i++)
-			if (tperm & (1<<i)) {
-				kperm |= current_mapping[tclass].perms[i];
-				tperm &= ~(1<<i);
-			}
-		return kperm;
-	}
-
-	return tperm;
-}
-
 static void map_decision(u16 tclass, struct av_decision *avd,
 			 int allow_unknown)
 {
@@ -250,6 +236,10 @@
 	}
 }
 
+int security_mls_enabled(void)
+{
+	return policydb.mls_enabled;
+}
 
 /*
  * Return the boolean value of a constraint expression
@@ -465,7 +455,8 @@
 	char *scontext_name = NULL;
 	char *tcontext_name = NULL;
 	char *permission_names[32];
-	int index, length;
+	int index;
+	u32 length;
 	bool need_comma = false;
 
 	if (!permissions)
@@ -532,7 +523,6 @@
 static void type_attribute_bounds_av(struct context *scontext,
 				     struct context *tcontext,
 				     u16 tclass,
-				     u32 requested,
 				     struct av_decision *avd)
 {
 	struct context lo_scontext;
@@ -553,7 +543,6 @@
 		context_struct_compute_av(&lo_scontext,
 					  tcontext,
 					  tclass,
-					  requested,
 					  &lo_avd);
 		if ((lo_avd.allowed & avd->allowed) == avd->allowed)
 			return;		/* no masked permission */
@@ -569,7 +558,6 @@
 		context_struct_compute_av(scontext,
 					  &lo_tcontext,
 					  tclass,
-					  requested,
 					  &lo_avd);
 		if ((lo_avd.allowed & avd->allowed) == avd->allowed)
 			return;		/* no masked permission */
@@ -586,7 +574,6 @@
 		context_struct_compute_av(&lo_scontext,
 					  &lo_tcontext,
 					  tclass,
-					  requested,
 					  &lo_avd);
 		if ((lo_avd.allowed & avd->allowed) == avd->allowed)
 			return;		/* no masked permission */
@@ -607,11 +594,10 @@
  * Compute access vectors based on a context structure pair for
  * the permissions in a particular class.
  */
-static int context_struct_compute_av(struct context *scontext,
-				     struct context *tcontext,
-				     u16 tclass,
-				     u32 requested,
-				     struct av_decision *avd)
+static void context_struct_compute_av(struct context *scontext,
+				      struct context *tcontext,
+				      u16 tclass,
+				      struct av_decision *avd)
 {
 	struct constraint_node *constraint;
 	struct role_allow *ra;
@@ -622,19 +608,14 @@
 	struct ebitmap_node *snode, *tnode;
 	unsigned int i, j;
 
-	/*
-	 * Initialize the access vectors to the default values.
-	 */
 	avd->allowed = 0;
 	avd->auditallow = 0;
 	avd->auditdeny = 0xffffffff;
-	avd->seqno = latest_granting;
-	avd->flags = 0;
 
 	if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) {
 		if (printk_ratelimit())
 			printk(KERN_WARNING "SELinux:  Invalid class %hu\n", tclass);
-		return -EINVAL;
+		return;
 	}
 
 	tclass_datum = policydb.class_val_to_struct[tclass - 1];
@@ -705,9 +686,7 @@
 	 * permission and notice it to userspace via audit.
 	 */
 	type_attribute_bounds_av(scontext, tcontext,
-				 tclass, requested, avd);
-
-	return 0;
+				 tclass, avd);
 }
 
 static int security_validtrans_handle_fail(struct context *ocontext,
@@ -864,7 +843,7 @@
 	if (rc) {
 		char *old_name = NULL;
 		char *new_name = NULL;
-		int length;
+		u32 length;
 
 		if (!context_struct_to_string(old_context,
 					      &old_name, &length) &&
@@ -886,110 +865,116 @@
 	return rc;
 }
 
-
-static int security_compute_av_core(u32 ssid,
-				    u32 tsid,
-				    u16 tclass,
-				    u32 requested,
-				    struct av_decision *avd)
+static void avd_init(struct av_decision *avd)
 {
-	struct context *scontext = NULL, *tcontext = NULL;
-	int rc = 0;
-
-	scontext = sidtab_search(&sidtab, ssid);
-	if (!scontext) {
-		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
-		       __func__, ssid);
-		return -EINVAL;
-	}
-	tcontext = sidtab_search(&sidtab, tsid);
-	if (!tcontext) {
-		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
-		       __func__, tsid);
-		return -EINVAL;
-	}
-
-	rc = context_struct_compute_av(scontext, tcontext, tclass,
-				       requested, avd);
-
-	/* permissive domain? */
-	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
-		avd->flags |= AVD_FLAGS_PERMISSIVE;
-
-	return rc;
+	avd->allowed = 0;
+	avd->auditallow = 0;
+	avd->auditdeny = 0xffffffff;
+	avd->seqno = latest_granting;
+	avd->flags = 0;
 }
 
+
 /**
  * security_compute_av - Compute access vector decisions.
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
- * @requested: requested permissions
  * @avd: access vector decisions
  *
  * Compute a set of access vector decisions based on the
  * SID pair (@ssid, @tsid) for the permissions in @tclass.
- * Return -%EINVAL if any of the parameters are invalid or %0
- * if the access vector decisions were computed successfully.
  */
-int security_compute_av(u32 ssid,
-			u32 tsid,
-			u16 orig_tclass,
-			u32 orig_requested,
-			struct av_decision *avd)
+void security_compute_av(u32 ssid,
+			 u32 tsid,
+			 u16 orig_tclass,
+			 struct av_decision *avd)
 {
 	u16 tclass;
-	u32 requested;
-	int rc;
+	struct context *scontext = NULL, *tcontext = NULL;
 
 	read_lock(&policy_rwlock);
-
+	avd_init(avd);
 	if (!ss_initialized)
 		goto allow;
 
-	requested = unmap_perm(orig_tclass, orig_requested);
+	scontext = sidtab_search(&sidtab, ssid);
+	if (!scontext) {
+		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
+		       __func__, ssid);
+		goto out;
+	}
+
+	/* permissive domain? */
+	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+		avd->flags |= AVD_FLAGS_PERMISSIVE;
+
+	tcontext = sidtab_search(&sidtab, tsid);
+	if (!tcontext) {
+		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
+		       __func__, tsid);
+		goto out;
+	}
+
 	tclass = unmap_class(orig_tclass);
 	if (unlikely(orig_tclass && !tclass)) {
 		if (policydb.allow_unknown)
 			goto allow;
-		rc = -EINVAL;
 		goto out;
 	}
-	rc = security_compute_av_core(ssid, tsid, tclass, requested, avd);
+	context_struct_compute_av(scontext, tcontext, tclass, avd);
 	map_decision(orig_tclass, avd, policydb.allow_unknown);
 out:
 	read_unlock(&policy_rwlock);
-	return rc;
+	return;
 allow:
 	avd->allowed = 0xffffffff;
-	avd->auditallow = 0;
-	avd->auditdeny = 0xffffffff;
-	avd->seqno = latest_granting;
-	avd->flags = 0;
-	rc = 0;
 	goto out;
 }
 
-int security_compute_av_user(u32 ssid,
-			     u32 tsid,
-			     u16 tclass,
-			     u32 requested,
-			     struct av_decision *avd)
+void security_compute_av_user(u32 ssid,
+			      u32 tsid,
+			      u16 tclass,
+			      struct av_decision *avd)
 {
-	int rc;
-
-	if (!ss_initialized) {
-		avd->allowed = 0xffffffff;
-		avd->auditallow = 0;
-		avd->auditdeny = 0xffffffff;
-		avd->seqno = latest_granting;
-		return 0;
-	}
+	struct context *scontext = NULL, *tcontext = NULL;
 
 	read_lock(&policy_rwlock);
-	rc = security_compute_av_core(ssid, tsid, tclass, requested, avd);
+	avd_init(avd);
+	if (!ss_initialized)
+		goto allow;
+
+	scontext = sidtab_search(&sidtab, ssid);
+	if (!scontext) {
+		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
+		       __func__, ssid);
+		goto out;
+	}
+
+	/* permissive domain? */
+	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+		avd->flags |= AVD_FLAGS_PERMISSIVE;
+
+	tcontext = sidtab_search(&sidtab, tsid);
+	if (!tcontext) {
+		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
+		       __func__, tsid);
+		goto out;
+	}
+
+	if (unlikely(!tclass)) {
+		if (policydb.allow_unknown)
+			goto allow;
+		goto out;
+	}
+
+	context_struct_compute_av(scontext, tcontext, tclass, avd);
+ out:
 	read_unlock(&policy_rwlock);
-	return rc;
+	return;
+allow:
+	avd->allowed = 0xffffffff;
+	goto out;
 }
 
 /*
@@ -1565,7 +1550,10 @@
 {
 	struct sidtab *s = arg;
 
-	return sidtab_insert(s, sid, context);
+	if (sid > SECINITSID_NUM)
+		return sidtab_insert(s, sid, context);
+	else
+		return 0;
 }
 
 static inline int convert_context_handle_invalid_context(struct context *context)
@@ -1606,12 +1594,17 @@
 {
 	struct convert_context_args *args;
 	struct context oldc;
+	struct ocontext *oc;
+	struct mls_range *range;
 	struct role_datum *role;
 	struct type_datum *typdatum;
 	struct user_datum *usrdatum;
 	char *s;
 	u32 len;
-	int rc;
+	int rc = 0;
+
+	if (key <= SECINITSID_NUM)
+		goto out;
 
 	args = p;
 
@@ -1673,9 +1666,39 @@
 		goto bad;
 	c->type = typdatum->value;
 
-	rc = mls_convert_context(args->oldp, args->newp, c);
-	if (rc)
-		goto bad;
+	/* Convert the MLS fields if dealing with MLS policies */
+	if (args->oldp->mls_enabled && args->newp->mls_enabled) {
+		rc = mls_convert_context(args->oldp, args->newp, c);
+		if (rc)
+			goto bad;
+	} else if (args->oldp->mls_enabled && !args->newp->mls_enabled) {
+		/*
+		 * Switching between MLS and non-MLS policy:
+		 * free any storage used by the MLS fields in the
+		 * context for all existing entries in the sidtab.
+		 */
+		mls_context_destroy(c);
+	} else if (!args->oldp->mls_enabled && args->newp->mls_enabled) {
+		/*
+		 * Switching between non-MLS and MLS policy:
+		 * ensure that the MLS fields of the context for all
+		 * existing entries in the sidtab are filled in with a
+		 * suitable default value, likely taken from one of the
+		 * initial SIDs.
+		 */
+		oc = args->newp->ocontexts[OCON_ISID];
+		while (oc && oc->sid[0] != SECINITSID_UNLABELED)
+			oc = oc->next;
+		if (!oc) {
+			printk(KERN_ERR "SELinux:  unable to look up"
+				" the initial SIDs list\n");
+			goto bad;
+		}
+		range = &oc->context[0].range;
+		rc = mls_range_set(c, range);
+		if (rc)
+			goto bad;
+	}
 
 	/* Check the validity of the new context. */
 	if (!policydb_context_isvalid(args->newp, c)) {
@@ -1771,9 +1794,17 @@
 	if (policydb_read(&newpolicydb, fp))
 		return -EINVAL;
 
-	if (sidtab_init(&newsidtab)) {
+	/* If switching between different policy types, log MLS status */
+	if (policydb.mls_enabled && !newpolicydb.mls_enabled)
+		printk(KERN_INFO "SELinux: Disabling MLS support...\n");
+	else if (!policydb.mls_enabled && newpolicydb.mls_enabled)
+		printk(KERN_INFO "SELinux: Enabling MLS support...\n");
+
+	rc = policydb_load_isids(&newpolicydb, &newsidtab);
+	if (rc) {
+		printk(KERN_ERR "SELinux:  unable to load the initial SIDs\n");
 		policydb_destroy(&newpolicydb);
-		return -ENOMEM;
+		return rc;
 	}
 
 	if (selinux_set_mapping(&newpolicydb, secclass_map,
@@ -1800,8 +1831,12 @@
 	args.oldp = &policydb;
 	args.newp = &newpolicydb;
 	rc = sidtab_map(&newsidtab, convert_context, &args);
-	if (rc)
+	if (rc) {
+		printk(KERN_ERR "SELinux:  unable to convert the internal"
+			" representation of contexts in the new SID"
+			" table\n");
 		goto err;
+	}
 
 	/* Save the old policydb and SID table to free later. */
 	memcpy(&oldpolicydb, &policydb, sizeof policydb);
@@ -2397,7 +2432,7 @@
 	u32 len;
 	int rc = 0;
 
-	if (!ss_initialized || !selinux_mls_enabled) {
+	if (!ss_initialized || !policydb.mls_enabled) {
 		*new_sid = sid;
 		goto out;
 	}
@@ -2498,7 +2533,7 @@
 	/* we don't need to check ss_initialized here since the only way both
 	 * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
 	 * security server was initialized and ss_initialized was true */
-	if (!selinux_mls_enabled) {
+	if (!policydb.mls_enabled) {
 		*peer_sid = SECSID_NULL;
 		return 0;
 	}
@@ -2555,7 +2590,7 @@
 	read_lock(&policy_rwlock);
 
 	*nclasses = policydb.p_classes.nprim;
-	*classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC);
+	*classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);
 	if (!*classes)
 		goto out;
 
@@ -2602,7 +2637,7 @@
 	}
 
 	*nperms = match->permissions.nprim;
-	*perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC);
+	*perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC);
 	if (!*perms)
 		goto out;
 
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 529c9ca..5225e66 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -157,12 +157,12 @@
  *
  * Returns 0 on success, error code otherwise.
  */
-static int smack_syslog(int type)
+static int smack_syslog(int type, bool from_file)
 {
 	int rc;
 	char *sp = current_security();
 
-	rc = cap_syslog(type);
+	rc = cap_syslog(type, from_file);
 	if (rc != 0)
 		return rc;
 
@@ -387,7 +387,7 @@
 	struct smk_audit_info ad;
 
 	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
-	smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_mountpoint);
+	smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_root);
 	smk_ad_setfield_u_fs_path_mnt(&ad, mnt);
 
 	sbp = mnt->mnt_sb->s_security;
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
index 10ccd68..60a9e20 100644
--- a/security/tomoyo/Makefile
+++ b/security/tomoyo/Makefile
@@ -1 +1 @@
-obj-y = common.o realpath.o tomoyo.o domain.o file.o
+obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index e0d0354..ff51f10 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -12,9 +12,10 @@
 #include <linux/uaccess.h>
 #include <linux/security.h>
 #include <linux/hardirq.h>
-#include "realpath.h"
 #include "common.h"
-#include "tomoyo.h"
+
+/* Lock for protecting policy. */
+DEFINE_MUTEX(tomoyo_policy_lock);
 
 /* Has loading policy done? */
 bool tomoyo_policy_loaded;
@@ -178,14 +179,12 @@
  *                1 = must / -1 = must not / 0 = don't care
  * @end_type:     Should the pathname end with '/'?
  *                1 = must / -1 = must not / 0 = don't care
- * @function:     The name of function calling me.
  *
  * Check whether the given filename follows the naming rules.
  * Returns true if @filename follows the naming rules, false otherwise.
  */
 bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
-			    const s8 pattern_type, const s8 end_type,
-			    const char *function)
+			    const s8 pattern_type, const s8 end_type)
 {
 	const char *const start = filename;
 	bool in_repetition = false;
@@ -193,7 +192,6 @@
 	unsigned char c;
 	unsigned char d;
 	unsigned char e;
-	const char *original_filename = filename;
 
 	if (!filename)
 		goto out;
@@ -282,25 +280,20 @@
 		goto out;
 	return true;
  out:
-	printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
-	       original_filename);
 	return false;
 }
 
 /**
  * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
  * @domainname:   The domainname to check.
- * @function:     The name of function calling me.
  *
  * Returns true if @domainname follows the naming rules, false otherwise.
  */
-bool tomoyo_is_correct_domain(const unsigned char *domainname,
-			      const char *function)
+bool tomoyo_is_correct_domain(const unsigned char *domainname)
 {
 	unsigned char c;
 	unsigned char d;
 	unsigned char e;
-	const char *org_domainname = domainname;
 
 	if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
 				   TOMOYO_ROOT_NAME_LEN))
@@ -343,8 +336,6 @@
 	} while (*domainname);
 	return true;
  out:
-	printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function,
-	       org_domainname);
 	return false;
 }
 
@@ -365,10 +356,9 @@
  *
  * @domainname: The domainname to find.
  *
- * Caller must call down_read(&tomoyo_domain_list_lock); or
- * down_write(&tomoyo_domain_list_lock); .
- *
  * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
 {
@@ -377,7 +367,7 @@
 
 	name.name = domainname;
 	tomoyo_fill_path_info(&name);
-	list_for_each_entry(domain, &tomoyo_domain_list, list) {
+	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
 		if (!domain->is_deleted &&
 		    !tomoyo_pathcmp(&name, domain->domainname))
 			return domain;
@@ -748,7 +738,7 @@
  *
  * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
  *
- * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
+ * This function uses kzalloc(), so the caller must call kfree()
  * if this function didn't return NULL.
  */
 static const char *tomoyo_get_exe(void)
@@ -829,6 +819,8 @@
  * @domain: Pointer to "struct tomoyo_domain_info".
  *
  * Returns true if the domain is not exceeded quota, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
 {
@@ -837,61 +829,29 @@
 
 	if (!domain)
 		return true;
-	down_read(&tomoyo_domain_acl_info_list_lock);
-	list_for_each_entry(ptr, &domain->acl_info_list, list) {
-		if (ptr->type & TOMOYO_ACL_DELETED)
-			continue;
-		switch (tomoyo_acl_type2(ptr)) {
-			struct tomoyo_single_path_acl_record *acl1;
-			struct tomoyo_double_path_acl_record *acl2;
-			u16 perm;
-		case TOMOYO_TYPE_SINGLE_PATH_ACL:
-			acl1 = container_of(ptr,
-				    struct tomoyo_single_path_acl_record,
-					    head);
-			perm = acl1->perm;
-			if (perm & (1 << TOMOYO_TYPE_EXECUTE_ACL))
-				count++;
-			if (perm &
-			    ((1 << TOMOYO_TYPE_READ_ACL) |
-			     (1 << TOMOYO_TYPE_WRITE_ACL)))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_CREATE_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_UNLINK_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_MKDIR_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_RMDIR_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_MKFIFO_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_MKSOCK_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_MKBLOCK_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_MKCHAR_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_TRUNCATE_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_SYMLINK_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_REWRITE_ACL))
-				count++;
+	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
+		switch (ptr->type) {
+			struct tomoyo_path_acl *acl;
+			u32 perm;
+			u8 i;
+		case TOMOYO_TYPE_PATH_ACL:
+			acl = container_of(ptr, struct tomoyo_path_acl, head);
+			perm = acl->perm | (((u32) acl->perm_high) << 16);
+			for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++)
+				if (perm & (1 << i))
+					count++;
+			if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
+				count -= 2;
 			break;
-		case TOMOYO_TYPE_DOUBLE_PATH_ACL:
-			acl2 = container_of(ptr,
-				    struct tomoyo_double_path_acl_record,
-					    head);
-			perm = acl2->perm;
-			if (perm & (1 << TOMOYO_TYPE_LINK_ACL))
-				count++;
-			if (perm & (1 << TOMOYO_TYPE_RENAME_ACL))
-				count++;
+		case TOMOYO_TYPE_PATH2_ACL:
+			perm = container_of(ptr, struct tomoyo_path2_acl, head)
+				->perm;
+			for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++)
+				if (perm & (1 << i))
+					count++;
 			break;
 		}
 	}
-	up_read(&tomoyo_domain_acl_info_list_lock);
 	if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
 		return true;
 	if (!domain->quota_warned) {
@@ -923,9 +883,11 @@
 	ptr = tomoyo_profile_ptr[profile];
 	if (ptr)
 		goto ok;
-	ptr = tomoyo_alloc_element(sizeof(*ptr));
-	if (!ptr)
+	ptr = kmalloc(sizeof(*ptr), GFP_KERNEL);
+	if (!tomoyo_memory_ok(ptr)) {
+		kfree(ptr);
 		goto ok;
+	}
 	for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
 		ptr->value[i] = tomoyo_control_array[i].current_value;
 	mb(); /* Avoid out-of-order execution. */
@@ -966,7 +928,9 @@
 		return -EINVAL;
 	*cp = '\0';
 	if (!strcmp(data, "COMMENT")) {
-		profile->comment = tomoyo_save_name(cp + 1);
+		const struct tomoyo_path_info *old_comment = profile->comment;
+		profile->comment = tomoyo_get_name(cp + 1);
+		tomoyo_put_name(old_comment);
 		return 0;
 	}
 	for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) {
@@ -1061,27 +1025,6 @@
 }
 
 /*
- * tomoyo_policy_manager_entry is a structure which is used for holding list of
- * domainnames or programs which are permitted to modify configuration via
- * /sys/kernel/security/tomoyo/ interface.
- * It has following fields.
- *
- *  (1) "list" which is linked to tomoyo_policy_manager_list .
- *  (2) "manager" is a domainname or a program's pathname.
- *  (3) "is_domain" is a bool which is true if "manager" is a domainname, false
- *      otherwise.
- *  (4) "is_deleted" is a bool which is true if marked as deleted, false
- *      otherwise.
- */
-struct tomoyo_policy_manager_entry {
-	struct list_head list;
-	/* A path to program or a domainname. */
-	const struct tomoyo_path_info *manager;
-	bool is_domain;  /* True if manager is a domainname. */
-	bool is_deleted; /* True if this entry is deleted. */
-};
-
-/*
  * tomoyo_policy_manager_list is used for holding list of domainnames or
  * programs which are permitted to modify configuration via
  * /sys/kernel/security/tomoyo/ interface.
@@ -1111,8 +1054,7 @@
  *
  * # cat /sys/kernel/security/tomoyo/manager
  */
-static LIST_HEAD(tomoyo_policy_manager_list);
-static DECLARE_RWSEM(tomoyo_policy_manager_list_lock);
+LIST_HEAD(tomoyo_policy_manager_list);
 
 /**
  * tomoyo_update_manager_entry - Add a manager entry.
@@ -1121,48 +1063,50 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_update_manager_entry(const char *manager,
 				       const bool is_delete)
 {
-	struct tomoyo_policy_manager_entry *new_entry;
+	struct tomoyo_policy_manager_entry *entry = NULL;
 	struct tomoyo_policy_manager_entry *ptr;
 	const struct tomoyo_path_info *saved_manager;
-	int error = -ENOMEM;
+	int error = is_delete ? -ENOENT : -ENOMEM;
 	bool is_domain = false;
 
 	if (tomoyo_is_domain_def(manager)) {
-		if (!tomoyo_is_correct_domain(manager, __func__))
+		if (!tomoyo_is_correct_domain(manager))
 			return -EINVAL;
 		is_domain = true;
 	} else {
-		if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__))
+		if (!tomoyo_is_correct_path(manager, 1, -1, -1))
 			return -EINVAL;
 	}
-	saved_manager = tomoyo_save_name(manager);
+	saved_manager = tomoyo_get_name(manager);
 	if (!saved_manager)
 		return -ENOMEM;
-	down_write(&tomoyo_policy_manager_list_lock);
-	list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
+	if (!is_delete)
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	mutex_lock(&tomoyo_policy_lock);
+	list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
 		if (ptr->manager != saved_manager)
 			continue;
 		ptr->is_deleted = is_delete;
 		error = 0;
-		goto out;
+		break;
 	}
-	if (is_delete) {
-		error = -ENOENT;
-		goto out;
+	if (!is_delete && error && tomoyo_memory_ok(entry)) {
+		entry->manager = saved_manager;
+		saved_manager = NULL;
+		entry->is_domain = is_domain;
+		list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list);
+		entry = NULL;
+		error = 0;
 	}
-	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
-	if (!new_entry)
-		goto out;
-	new_entry->manager = saved_manager;
-	new_entry->is_domain = is_domain;
-	list_add_tail(&new_entry->list, &tomoyo_policy_manager_list);
-	error = 0;
- out:
-	up_write(&tomoyo_policy_manager_list_lock);
+	mutex_unlock(&tomoyo_policy_lock);
+	tomoyo_put_name(saved_manager);
+	kfree(entry);
 	return error;
 }
 
@@ -1172,6 +1116,8 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
 {
@@ -1191,6 +1137,8 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns 0.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
 {
@@ -1199,7 +1147,6 @@
 
 	if (head->read_eof)
 		return 0;
-	down_read(&tomoyo_policy_manager_list_lock);
 	list_for_each_cookie(pos, head->read_var2,
 			     &tomoyo_policy_manager_list) {
 		struct tomoyo_policy_manager_entry *ptr;
@@ -1211,7 +1158,6 @@
 		if (!done)
 			break;
 	}
-	up_read(&tomoyo_policy_manager_list_lock);
 	head->read_eof = done;
 	return 0;
 }
@@ -1221,6 +1167,8 @@
  *
  * Returns true if the current process is permitted to modify policy
  * via /sys/kernel/security/tomoyo/ interface.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static bool tomoyo_is_policy_manager(void)
 {
@@ -1234,29 +1182,25 @@
 		return true;
 	if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
 		return false;
-	down_read(&tomoyo_policy_manager_list_lock);
-	list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
+	list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
 		if (!ptr->is_deleted && ptr->is_domain
 		    && !tomoyo_pathcmp(domainname, ptr->manager)) {
 			found = true;
 			break;
 		}
 	}
-	up_read(&tomoyo_policy_manager_list_lock);
 	if (found)
 		return true;
 	exe = tomoyo_get_exe();
 	if (!exe)
 		return false;
-	down_read(&tomoyo_policy_manager_list_lock);
-	list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
+	list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
 		if (!ptr->is_deleted && !ptr->is_domain
 		    && !strcmp(exe, ptr->manager->name)) {
 			found = true;
 			break;
 		}
 	}
-	up_read(&tomoyo_policy_manager_list_lock);
 	if (!found) { /* Reduce error messages. */
 		static pid_t last_pid;
 		const pid_t pid = current->pid;
@@ -1266,7 +1210,7 @@
 			last_pid = pid;
 		}
 	}
-	tomoyo_free(exe);
+	kfree(exe);
 	return found;
 }
 
@@ -1277,6 +1221,8 @@
  * @data: String to parse.
  *
  * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
 				 const char *data)
@@ -1286,17 +1232,16 @@
 
 	if (sscanf(data, "pid=%u", &pid) == 1) {
 		struct task_struct *p;
+		rcu_read_lock();
 		read_lock(&tasklist_lock);
 		p = find_task_by_vpid(pid);
 		if (p)
 			domain = tomoyo_real_domain(p);
 		read_unlock(&tasklist_lock);
+		rcu_read_unlock();
 	} else if (!strncmp(data, "domain=", 7)) {
-		if (tomoyo_is_domain_def(data + 7)) {
-			down_read(&tomoyo_domain_list_lock);
+		if (tomoyo_is_domain_def(data + 7))
 			domain = tomoyo_find_domain(data + 7);
-			up_read(&tomoyo_domain_list_lock);
-		}
 	} else
 		return false;
 	head->write_var1 = domain;
@@ -1310,13 +1255,11 @@
 	if (domain) {
 		struct tomoyo_domain_info *d;
 		head->read_var1 = NULL;
-		down_read(&tomoyo_domain_list_lock);
-		list_for_each_entry(d, &tomoyo_domain_list, list) {
+		list_for_each_entry_rcu(d, &tomoyo_domain_list, list) {
 			if (d == domain)
 				break;
 			head->read_var1 = &d->list;
 		}
-		up_read(&tomoyo_domain_list_lock);
 		head->read_var2 = NULL;
 		head->read_bit = 0;
 		head->read_step = 0;
@@ -1332,6 +1275,8 @@
  * @domainname: The name of domain.
  *
  * Returns 0.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_delete_domain(char *domainname)
 {
@@ -1340,9 +1285,9 @@
 
 	name.name = domainname;
 	tomoyo_fill_path_info(&name);
-	down_write(&tomoyo_domain_list_lock);
+	mutex_lock(&tomoyo_policy_lock);
 	/* Is there an active domain? */
-	list_for_each_entry(domain, &tomoyo_domain_list, list) {
+	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
 		/* Never delete tomoyo_kernel_domain */
 		if (domain == &tomoyo_kernel_domain)
 			continue;
@@ -1352,7 +1297,7 @@
 		domain->is_deleted = true;
 		break;
 	}
-	up_write(&tomoyo_domain_list_lock);
+	mutex_unlock(&tomoyo_policy_lock);
 	return 0;
 }
 
@@ -1362,6 +1307,8 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
 {
@@ -1384,11 +1331,9 @@
 		domain = NULL;
 		if (is_delete)
 			tomoyo_delete_domain(data);
-		else if (is_select) {
-			down_read(&tomoyo_domain_list_lock);
+		else if (is_select)
 			domain = tomoyo_find_domain(data);
-			up_read(&tomoyo_domain_list_lock);
-		} else
+		else
 			domain = tomoyo_find_or_assign_new_domain(data, 0);
 		head->write_var1 = domain;
 		return 0;
@@ -1403,43 +1348,39 @@
 		return 0;
 	}
 	if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
-		tomoyo_set_domain_flag(domain, is_delete,
-			       TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);
+		domain->ignore_global_allow_read = !is_delete;
 		return 0;
 	}
 	return tomoyo_write_file_policy(data, domain, is_delete);
 }
 
 /**
- * tomoyo_print_single_path_acl - Print a single path ACL entry.
+ * tomoyo_print_path_acl - Print a single path ACL entry.
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
- * @ptr:  Pointer to "struct tomoyo_single_path_acl_record".
+ * @ptr:  Pointer to "struct tomoyo_path_acl".
  *
  * Returns true on success, false otherwise.
  */
-static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head,
-					 struct tomoyo_single_path_acl_record *
-					 ptr)
+static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head,
+				  struct tomoyo_path_acl *ptr)
 {
 	int pos;
 	u8 bit;
 	const char *atmark = "";
 	const char *filename;
-	const u16 perm = ptr->perm;
+	const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16);
 
 	filename = ptr->filename->name;
-	for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION;
-	     bit++) {
+	for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
 		const char *msg;
 		if (!(perm & (1 << bit)))
 			continue;
 		/* Print "read/write" instead of "read" and "write". */
-		if ((bit == TOMOYO_TYPE_READ_ACL ||
-		     bit == TOMOYO_TYPE_WRITE_ACL)
-		    && (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
+		if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE)
+		    && (perm & (1 << TOMOYO_TYPE_READ_WRITE)))
 			continue;
-		msg = tomoyo_sp2keyword(bit);
+		msg = tomoyo_path2keyword(bit);
 		pos = head->read_avail;
 		if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg,
 				      atmark, filename))
@@ -1454,16 +1395,15 @@
 }
 
 /**
- * tomoyo_print_double_path_acl - Print a double path ACL entry.
+ * tomoyo_print_path2_acl - Print a double path ACL entry.
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
- * @ptr:  Pointer to "struct tomoyo_double_path_acl_record".
+ * @ptr:  Pointer to "struct tomoyo_path2_acl".
  *
  * Returns true on success, false otherwise.
  */
-static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
-					 struct tomoyo_double_path_acl_record *
-					 ptr)
+static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head,
+				   struct tomoyo_path2_acl *ptr)
 {
 	int pos;
 	const char *atmark1 = "";
@@ -1475,12 +1415,11 @@
 
 	filename1 = ptr->filename1->name;
 	filename2 = ptr->filename2->name;
-	for (bit = head->read_bit; bit < TOMOYO_MAX_DOUBLE_PATH_OPERATION;
-	     bit++) {
+	for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) {
 		const char *msg;
 		if (!(perm & (1 << bit)))
 			continue;
-		msg = tomoyo_dp2keyword(bit);
+		msg = tomoyo_path22keyword(bit);
 		pos = head->read_avail;
 		if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg,
 				      atmark1, filename1, atmark2, filename2))
@@ -1505,23 +1444,17 @@
 static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
 			       struct tomoyo_acl_info *ptr)
 {
-	const u8 acl_type = tomoyo_acl_type2(ptr);
+	const u8 acl_type = ptr->type;
 
-	if (acl_type & TOMOYO_ACL_DELETED)
-		return true;
-	if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) {
-		struct tomoyo_single_path_acl_record *acl
-			= container_of(ptr,
-				       struct tomoyo_single_path_acl_record,
-				       head);
-		return tomoyo_print_single_path_acl(head, acl);
+	if (acl_type == TOMOYO_TYPE_PATH_ACL) {
+		struct tomoyo_path_acl *acl
+			= container_of(ptr, struct tomoyo_path_acl, head);
+		return tomoyo_print_path_acl(head, acl);
 	}
-	if (acl_type == TOMOYO_TYPE_DOUBLE_PATH_ACL) {
-		struct tomoyo_double_path_acl_record *acl
-			= container_of(ptr,
-				       struct tomoyo_double_path_acl_record,
-				       head);
-		return tomoyo_print_double_path_acl(head, acl);
+	if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
+		struct tomoyo_path2_acl *acl
+			= container_of(ptr, struct tomoyo_path2_acl, head);
+		return tomoyo_print_path2_acl(head, acl);
 	}
 	BUG(); /* This must not happen. */
 	return false;
@@ -1533,6 +1466,8 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns 0.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
 {
@@ -1544,7 +1479,6 @@
 		return 0;
 	if (head->read_step == 0)
 		head->read_step = 1;
-	down_read(&tomoyo_domain_list_lock);
 	list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) {
 		struct tomoyo_domain_info *domain;
 		const char *quota_exceeded = "";
@@ -1558,10 +1492,9 @@
 		/* Print domainname and flags. */
 		if (domain->quota_warned)
 			quota_exceeded = "quota_exceeded\n";
-		if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED)
+		if (domain->transition_failed)
 			transition_failed = "transition_failed\n";
-		if (domain->flags &
-		    TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)
+		if (domain->ignore_global_allow_read)
 			ignore_global_allow_read
 				= TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
 		done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE
@@ -1577,7 +1510,6 @@
 		if (head->read_step == 3)
 			goto tail_mark;
 		/* Print ACL entries in the domain. */
-		down_read(&tomoyo_domain_acl_info_list_lock);
 		list_for_each_cookie(apos, head->read_var2,
 				     &domain->acl_info_list) {
 			struct tomoyo_acl_info *ptr
@@ -1587,7 +1519,6 @@
 			if (!done)
 				break;
 		}
-		up_read(&tomoyo_domain_acl_info_list_lock);
 		if (!done)
 			break;
 		head->read_step = 3;
@@ -1599,7 +1530,6 @@
 		if (head->read_single_domain)
 			break;
 	}
-	up_read(&tomoyo_domain_list_lock);
 	head->read_eof = done;
 	return 0;
 }
@@ -1615,6 +1545,8 @@
  *
  *     ( echo "select " $domainname; echo "use_profile " $profile ) |
  *     /usr/lib/ccs/loadpolicy -d
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
 {
@@ -1626,9 +1558,7 @@
 	if (!cp)
 		return -EINVAL;
 	*cp = '\0';
-	down_read(&tomoyo_domain_list_lock);
 	domain = tomoyo_find_domain(cp + 1);
-	up_read(&tomoyo_domain_list_lock);
 	if (strict_strtoul(data, 10, &profile))
 		return -EINVAL;
 	if (domain && profile < TOMOYO_MAX_PROFILES
@@ -1650,6 +1580,8 @@
  *     awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
  *     domainname = $0; } else if ( $1 == "use_profile" ) {
  *     print $2 " " domainname; domainname = ""; } } ; '
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
 {
@@ -1658,7 +1590,6 @@
 
 	if (head->read_eof)
 		return 0;
-	down_read(&tomoyo_domain_list_lock);
 	list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) {
 		struct tomoyo_domain_info *domain;
 		domain = list_entry(pos, struct tomoyo_domain_info, list);
@@ -1669,7 +1600,6 @@
 		if (!done)
 			break;
 	}
-	up_read(&tomoyo_domain_list_lock);
 	head->read_eof = done;
 	return 0;
 }
@@ -1707,11 +1637,13 @@
 		const int pid = head->read_step;
 		struct task_struct *p;
 		struct tomoyo_domain_info *domain = NULL;
+		rcu_read_lock();
 		read_lock(&tasklist_lock);
 		p = find_task_by_vpid(pid);
 		if (p)
 			domain = tomoyo_real_domain(p);
 		read_unlock(&tasklist_lock);
+		rcu_read_unlock();
 		if (domain)
 			tomoyo_io_printf(head, "%d %u %s", pid, domain->profile,
 					 domain->domainname->name);
@@ -1726,6 +1658,8 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
 {
@@ -1760,6 +1694,8 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns 0 on success, -EINVAL otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
 {
@@ -1889,15 +1825,13 @@
 	tomoyo_policy_loaded = true;
 	{ /* Check all profiles currently assigned to domains are defined. */
 		struct tomoyo_domain_info *domain;
-		down_read(&tomoyo_domain_list_lock);
-		list_for_each_entry(domain, &tomoyo_domain_list, list) {
+		list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
 			const u8 profile = domain->profile;
 			if (tomoyo_profile_ptr[profile])
 				continue;
 			panic("Profile %u (used by '%s') not defined.\n",
 			      profile, domain->domainname->name);
 		}
-		up_read(&tomoyo_domain_list_lock);
 	}
 }
 
@@ -1945,10 +1879,12 @@
  * @file: Pointer to "struct file".
  *
  * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
+ *
+ * Caller acquires tomoyo_read_lock().
  */
 static int tomoyo_open_control(const u8 type, struct file *file)
 {
-	struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head));
+	struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL);
 
 	if (!head)
 		return -ENOMEM;
@@ -2009,9 +1945,9 @@
 	} else {
 		if (!head->readbuf_size)
 			head->readbuf_size = 4096 * 2;
-		head->read_buf = tomoyo_alloc(head->readbuf_size);
+		head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
 		if (!head->read_buf) {
-			tomoyo_free(head);
+			kfree(head);
 			return -ENOMEM;
 		}
 	}
@@ -2023,13 +1959,14 @@
 		head->write = NULL;
 	} else if (head->write) {
 		head->writebuf_size = 4096 * 2;
-		head->write_buf = tomoyo_alloc(head->writebuf_size);
+		head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
 		if (!head->write_buf) {
-			tomoyo_free(head->read_buf);
-			tomoyo_free(head);
+			kfree(head->read_buf);
+			kfree(head);
 			return -ENOMEM;
 		}
 	}
+	head->reader_idx = tomoyo_read_lock();
 	file->private_data = head;
 	/*
 	 * Call the handler now if the file is
@@ -2051,6 +1988,8 @@
  * @buffer_len: Size of @buffer.
  *
  * Returns bytes read on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_read_control(struct file *file, char __user *buffer,
 			       const int buffer_len)
@@ -2094,6 +2033,8 @@
  * @buffer_len: Size of @buffer.
  *
  * Returns @buffer_len on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_write_control(struct file *file, const char __user *buffer,
 				const int buffer_len)
@@ -2144,52 +2085,29 @@
  * @file: Pointer to "struct file".
  *
  * Releases memory and returns 0.
+ *
+ * Caller looses tomoyo_read_lock().
  */
 static int tomoyo_close_control(struct file *file)
 {
 	struct tomoyo_io_buffer *head = file->private_data;
+	const bool is_write = !!head->write_buf;
 
+	tomoyo_read_unlock(head->reader_idx);
 	/* Release memory used for policy I/O. */
-	tomoyo_free(head->read_buf);
+	kfree(head->read_buf);
 	head->read_buf = NULL;
-	tomoyo_free(head->write_buf);
+	kfree(head->write_buf);
 	head->write_buf = NULL;
-	tomoyo_free(head);
+	kfree(head);
 	head = NULL;
 	file->private_data = NULL;
+	if (is_write)
+		tomoyo_run_gc();
 	return 0;
 }
 
 /**
- * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry.
- *
- * @acl_type:  Type of ACL entry.
- *
- * Returns pointer to the ACL entry on success, NULL otherwise.
- */
-void *tomoyo_alloc_acl_element(const u8 acl_type)
-{
-	int len;
-	struct tomoyo_acl_info *ptr;
-
-	switch (acl_type) {
-	case TOMOYO_TYPE_SINGLE_PATH_ACL:
-		len = sizeof(struct tomoyo_single_path_acl_record);
-		break;
-	case TOMOYO_TYPE_DOUBLE_PATH_ACL:
-		len = sizeof(struct tomoyo_double_path_acl_record);
-		break;
-	default:
-		return NULL;
-	}
-	ptr = tomoyo_alloc_element(len);
-	if (!ptr)
-		return NULL;
-	ptr->type = acl_type;
-	return ptr;
-}
-
-/**
  * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
  *
  * @inode: Pointer to "struct inode".
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 92169d2..67bd22d 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -1,12 +1,9 @@
 /*
  * security/tomoyo/common.h
  *
- * Common functions for TOMOYO.
+ * Header file for TOMOYO.
  *
- * Copyright (C) 2005-2009  NTT DATA CORPORATION
- *
- * Version: 2.2.0   2009/04/01
- *
+ * Copyright (C) 2005-2010  NTT DATA CORPORATION
  */
 
 #ifndef _SECURITY_TOMOYO_COMMON_H
@@ -22,9 +19,119 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/list.h>
+#include <linux/cred.h>
+struct linux_binprm;
 
-struct dentry;
-struct vfsmount;
+/********** Constants definitions. **********/
+
+/*
+ * TOMOYO uses this hash only when appending a string into the string
+ * table. Frequency of appending strings is very low. So we don't need
+ * large (e.g. 64k) hash size. 256 will be sufficient.
+ */
+#define TOMOYO_HASH_BITS  8
+#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)
+
+/*
+ * This is the max length of a token.
+ *
+ * A token consists of only ASCII printable characters.
+ * Non printable characters in a token is represented in \ooo style
+ * octal string. Thus, \ itself is represented as \\.
+ */
+#define TOMOYO_MAX_PATHNAME_LEN 4000
+
+/* Profile number is an integer between 0 and 255. */
+#define TOMOYO_MAX_PROFILES 256
+
+/* Keywords for ACLs. */
+#define TOMOYO_KEYWORD_ALIAS                     "alias "
+#define TOMOYO_KEYWORD_ALLOW_READ                "allow_read "
+#define TOMOYO_KEYWORD_DELETE                    "delete "
+#define TOMOYO_KEYWORD_DENY_REWRITE              "deny_rewrite "
+#define TOMOYO_KEYWORD_FILE_PATTERN              "file_pattern "
+#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN         "initialize_domain "
+#define TOMOYO_KEYWORD_KEEP_DOMAIN               "keep_domain "
+#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN      "no_initialize_domain "
+#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN            "no_keep_domain "
+#define TOMOYO_KEYWORD_SELECT                    "select "
+#define TOMOYO_KEYWORD_USE_PROFILE               "use_profile "
+#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ  "ignore_global_allow_read"
+/* A domain definition starts with <kernel>. */
+#define TOMOYO_ROOT_NAME                         "<kernel>"
+#define TOMOYO_ROOT_NAME_LEN                     (sizeof(TOMOYO_ROOT_NAME) - 1)
+
+/* Index numbers for Access Controls. */
+enum tomoyo_mac_index {
+	TOMOYO_MAC_FOR_FILE,  /* domain_policy.conf */
+	TOMOYO_MAX_ACCEPT_ENTRY,
+	TOMOYO_VERBOSE,
+	TOMOYO_MAX_CONTROL_INDEX
+};
+
+/* Index numbers for Access Controls. */
+enum tomoyo_acl_entry_type_index {
+	TOMOYO_TYPE_PATH_ACL,
+	TOMOYO_TYPE_PATH2_ACL,
+};
+
+/* Index numbers for File Controls. */
+
+/*
+ * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set
+ * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and
+ * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set.
+ * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or
+ * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are
+ * automatically cleared if TYPE_READ_WRITE_ACL is cleared.
+ */
+
+enum tomoyo_path_acl_index {
+	TOMOYO_TYPE_READ_WRITE,
+	TOMOYO_TYPE_EXECUTE,
+	TOMOYO_TYPE_READ,
+	TOMOYO_TYPE_WRITE,
+	TOMOYO_TYPE_CREATE,
+	TOMOYO_TYPE_UNLINK,
+	TOMOYO_TYPE_MKDIR,
+	TOMOYO_TYPE_RMDIR,
+	TOMOYO_TYPE_MKFIFO,
+	TOMOYO_TYPE_MKSOCK,
+	TOMOYO_TYPE_MKBLOCK,
+	TOMOYO_TYPE_MKCHAR,
+	TOMOYO_TYPE_TRUNCATE,
+	TOMOYO_TYPE_SYMLINK,
+	TOMOYO_TYPE_REWRITE,
+	TOMOYO_TYPE_IOCTL,
+	TOMOYO_TYPE_CHMOD,
+	TOMOYO_TYPE_CHOWN,
+	TOMOYO_TYPE_CHGRP,
+	TOMOYO_TYPE_CHROOT,
+	TOMOYO_TYPE_MOUNT,
+	TOMOYO_TYPE_UMOUNT,
+	TOMOYO_MAX_PATH_OPERATION
+};
+
+enum tomoyo_path2_acl_index {
+	TOMOYO_TYPE_LINK,
+	TOMOYO_TYPE_RENAME,
+	TOMOYO_TYPE_PIVOT_ROOT,
+	TOMOYO_MAX_PATH2_OPERATION
+};
+
+enum tomoyo_securityfs_interface_index {
+	TOMOYO_DOMAINPOLICY,
+	TOMOYO_EXCEPTIONPOLICY,
+	TOMOYO_DOMAIN_STATUS,
+	TOMOYO_PROCESS_STATUS,
+	TOMOYO_MEMINFO,
+	TOMOYO_SELFDOMAIN,
+	TOMOYO_VERSION,
+	TOMOYO_PROFILE,
+	TOMOYO_MANAGER
+};
+
+/********** Structure definitions. **********/
 
 /*
  * tomoyo_page_buffer is a structure which is used for holding a pathname
@@ -66,13 +173,14 @@
 };
 
 /*
- * This is the max length of a token.
- *
- * A token consists of only ASCII printable characters.
- * Non printable characters in a token is represented in \ooo style
- * octal string. Thus, \ itself is represented as \\.
+ * tomoyo_name_entry is a structure which is used for linking
+ * "struct tomoyo_path_info" into tomoyo_name_list .
  */
-#define TOMOYO_MAX_PATHNAME_LEN 4000
+struct tomoyo_name_entry {
+	struct list_head list;
+	atomic_t users;
+	struct tomoyo_path_info entry;
+};
 
 /*
  * tomoyo_path_info_with_data is a structure which is used for holding a
@@ -89,7 +197,7 @@
  * "struct tomoyo_path_info_with_data".
  */
 struct tomoyo_path_info_with_data {
-	/* Keep "head" first, for this pointer is passed to tomoyo_free(). */
+	/* Keep "head" first, for this pointer is passed to kfree(). */
 	struct tomoyo_path_info head;
 	char barrier1[16]; /* Safeguard for overrun. */
 	char body[TOMOYO_MAX_PATHNAME_LEN];
@@ -101,30 +209,19 @@
  *
  *  (1) "list" which is linked to the ->acl_info_list of
  *      "struct tomoyo_domain_info"
- *  (2) "type" which tells
- *      (a) type & 0x7F : type of the entry (either
- *          "struct tomoyo_single_path_acl_record" or
- *          "struct tomoyo_double_path_acl_record")
- *      (b) type & 0x80 : whether the entry is marked as "deleted".
+ *  (2) "type" which tells type of the entry (either
+ *      "struct tomoyo_path_acl" or "struct tomoyo_path2_acl").
  *
  * Packing "struct tomoyo_acl_info" allows
- * "struct tomoyo_single_path_acl_record" to embed "u16" and
- * "struct tomoyo_double_path_acl_record" to embed "u8"
+ * "struct tomoyo_path_acl" to embed "u8" + "u16" and
+ * "struct tomoyo_path2_acl" to embed "u8"
  * without enlarging their structure size.
  */
 struct tomoyo_acl_info {
 	struct list_head list;
-	/*
-	 * Type of this ACL entry.
-	 *
-	 * MSB is is_deleted flag.
-	 */
 	u8 type;
 } __packed;
 
-/* This ACL entry is deleted.           */
-#define TOMOYO_ACL_DELETED        0x80
-
 /*
  * tomoyo_domain_info is a structure which is used for holding permissions
  * (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
@@ -138,7 +235,17 @@
  *      "deleted", false otherwise.
  *  (6) "quota_warned" is a bool which is used for suppressing warning message
  *      when learning mode learned too much entries.
- *  (7) "flags" which remembers this domain's attributes.
+ *  (7) "ignore_global_allow_read" is a bool which is true if this domain
+ *      should ignore "allow_read" directive in exception policy.
+ *  (8) "transition_failed" is a bool which is set to true when this domain was
+ *      unable to create a new domain at tomoyo_find_next_domain() because the
+ *      name of the domain to be created was too long or it could not allocate
+ *      memory. If set to true, more than one process continued execve()
+ *      without domain transition.
+ *  (9) "users" is an atomic_t that holds how many "struct cred"->security
+ *      are referring this "struct tomoyo_domain_info". If is_deleted == true
+ *      and users == 0, this struct will be kfree()d upon next garbage
+ *      collection.
  *
  * A domain's lifecycle is an analogy of files on / directory.
  * Multiple domains with the same domainname cannot be created (as with
@@ -155,25 +262,13 @@
 	u8 profile;        /* Profile number to use. */
 	bool is_deleted;   /* Delete flag.           */
 	bool quota_warned; /* Quota warnning flag.   */
-	/* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */
-	u8 flags;
+	bool ignore_global_allow_read; /* Ignore "allow_read" flag. */
+	bool transition_failed; /* Domain transition failed flag. */
+	atomic_t users; /* Number of referring credentials. */
 };
 
-/* Profile number is an integer between 0 and 255. */
-#define TOMOYO_MAX_PROFILES 256
-
-/* Ignore "allow_read" directive in exception policy. */
-#define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1
 /*
- * This domain was unable to create a new domain at tomoyo_find_next_domain()
- * because the name of the domain to be created was too long or
- * it could not allocate memory.
- * More than one process continued execve() without domain transition.
- */
-#define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED        2
-
-/*
- * tomoyo_single_path_acl_record is a structure which is used for holding an
+ * tomoyo_path_acl is a structure which is used for holding an
  * entry with one pathname operation (e.g. open(), mkdir()).
  * It has following fields.
  *
@@ -184,18 +279,21 @@
  * Directives held by this structure are "allow_read/write", "allow_execute",
  * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir",
  * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock",
- * "allow_mkchar", "allow_truncate", "allow_symlink" and "allow_rewrite".
+ * "allow_mkchar", "allow_truncate", "allow_symlink", "allow_rewrite",
+ * "allow_chmod", "allow_chown", "allow_chgrp", "allow_chroot", "allow_mount"
+ * and "allow_unmount".
  */
-struct tomoyo_single_path_acl_record {
-	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_SINGLE_PATH_ACL */
+struct tomoyo_path_acl {
+	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */
+	u8 perm_high;
 	u16 perm;
 	/* Pointer to single pathname. */
 	const struct tomoyo_path_info *filename;
 };
 
 /*
- * tomoyo_double_path_acl_record is a structure which is used for holding an
- * entry with two pathnames operation (i.e. link() and rename()).
+ * tomoyo_path2_acl is a structure which is used for holding an
+ * entry with two pathnames operation (i.e. link(), rename() and pivot_root()).
  * It has following fields.
  *
  *  (1) "head" which is a "struct tomoyo_acl_info".
@@ -203,10 +301,11 @@
  *  (3) "filename1" is the source/old pathname.
  *  (4) "filename2" is the destination/new pathname.
  *
- * Directives held by this structure are "allow_rename" and "allow_link".
+ * Directives held by this structure are "allow_rename", "allow_link" and
+ * "allow_pivot_root".
  */
-struct tomoyo_double_path_acl_record {
-	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_DOUBLE_PATH_ACL */
+struct tomoyo_path2_acl {
+	struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */
 	u8 perm;
 	/* Pointer to single pathname. */
 	const struct tomoyo_path_info *filename1;
@@ -214,29 +313,6 @@
 	const struct tomoyo_path_info *filename2;
 };
 
-/* Keywords for ACLs. */
-#define TOMOYO_KEYWORD_ALIAS                     "alias "
-#define TOMOYO_KEYWORD_ALLOW_READ                "allow_read "
-#define TOMOYO_KEYWORD_DELETE                    "delete "
-#define TOMOYO_KEYWORD_DENY_REWRITE              "deny_rewrite "
-#define TOMOYO_KEYWORD_FILE_PATTERN              "file_pattern "
-#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN         "initialize_domain "
-#define TOMOYO_KEYWORD_KEEP_DOMAIN               "keep_domain "
-#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN      "no_initialize_domain "
-#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN            "no_keep_domain "
-#define TOMOYO_KEYWORD_SELECT                    "select "
-#define TOMOYO_KEYWORD_USE_PROFILE               "use_profile "
-#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ  "ignore_global_allow_read"
-/* A domain definition starts with <kernel>. */
-#define TOMOYO_ROOT_NAME                         "<kernel>"
-#define TOMOYO_ROOT_NAME_LEN                     (sizeof(TOMOYO_ROOT_NAME) - 1)
-
-/* Index numbers for Access Controls. */
-#define TOMOYO_MAC_FOR_FILE                  0  /* domain_policy.conf */
-#define TOMOYO_MAX_ACCEPT_ENTRY              1
-#define TOMOYO_VERBOSE                       2
-#define TOMOYO_MAX_CONTROL_INDEX             3
-
 /*
  * tomoyo_io_buffer is a structure which is used for reading and modifying
  * configuration via /sys/kernel/security/tomoyo/ interface.
@@ -265,6 +341,8 @@
 	int (*write) (struct tomoyo_io_buffer *);
 	/* Exclusive lock for this structure.   */
 	struct mutex io_sem;
+	/* Index returned by tomoyo_read_lock(). */
+	int reader_idx;
 	/* The position currently reading from. */
 	struct list_head *read_var1;
 	/* Extra variables for reading.         */
@@ -293,18 +371,159 @@
 	int writebuf_size;
 };
 
+/*
+ * tomoyo_globally_readable_file_entry is a structure which is used for holding
+ * "allow_read" entries.
+ * It has following fields.
+ *
+ *  (1) "list" which is linked to tomoyo_globally_readable_list .
+ *  (2) "filename" is a pathname which is allowed to open(O_RDONLY).
+ *  (3) "is_deleted" is a bool which is true if marked as deleted, false
+ *      otherwise.
+ */
+struct tomoyo_globally_readable_file_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *filename;
+	bool is_deleted;
+};
+
+/*
+ * tomoyo_pattern_entry is a structure which is used for holding
+ * "tomoyo_pattern_list" entries.
+ * It has following fields.
+ *
+ *  (1) "list" which is linked to tomoyo_pattern_list .
+ *  (2) "pattern" is a pathname pattern which is used for converting pathnames
+ *      to pathname patterns during learning mode.
+ *  (3) "is_deleted" is a bool which is true if marked as deleted, false
+ *      otherwise.
+ */
+struct tomoyo_pattern_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *pattern;
+	bool is_deleted;
+};
+
+/*
+ * tomoyo_no_rewrite_entry is a structure which is used for holding
+ * "deny_rewrite" entries.
+ * It has following fields.
+ *
+ *  (1) "list" which is linked to tomoyo_no_rewrite_list .
+ *  (2) "pattern" is a pathname which is by default not permitted to modify
+ *      already existing content.
+ *  (3) "is_deleted" is a bool which is true if marked as deleted, false
+ *      otherwise.
+ */
+struct tomoyo_no_rewrite_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *pattern;
+	bool is_deleted;
+};
+
+/*
+ * tomoyo_domain_initializer_entry is a structure which is used for holding
+ * "initialize_domain" and "no_initialize_domain" entries.
+ * It has following fields.
+ *
+ *  (1) "list" which is linked to tomoyo_domain_initializer_list .
+ *  (2) "domainname" which is "a domainname" or "the last component of a
+ *      domainname". This field is NULL if "from" clause is not specified.
+ *  (3) "program" which is a program's pathname.
+ *  (4) "is_deleted" is a bool which is true if marked as deleted, false
+ *      otherwise.
+ *  (5) "is_not" is a bool which is true if "no_initialize_domain", false
+ *      otherwise.
+ *  (6) "is_last_name" is a bool which is true if "domainname" is "the last
+ *      component of a domainname", false otherwise.
+ */
+struct tomoyo_domain_initializer_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *domainname;    /* This may be NULL */
+	const struct tomoyo_path_info *program;
+	bool is_deleted;
+	bool is_not;       /* True if this entry is "no_initialize_domain".  */
+	/* True if the domainname is tomoyo_get_last_name(). */
+	bool is_last_name;
+};
+
+/*
+ * tomoyo_domain_keeper_entry is a structure which is used for holding
+ * "keep_domain" and "no_keep_domain" entries.
+ * It has following fields.
+ *
+ *  (1) "list" which is linked to tomoyo_domain_keeper_list .
+ *  (2) "domainname" which is "a domainname" or "the last component of a
+ *      domainname".
+ *  (3) "program" which is a program's pathname.
+ *      This field is NULL if "from" clause is not specified.
+ *  (4) "is_deleted" is a bool which is true if marked as deleted, false
+ *      otherwise.
+ *  (5) "is_not" is a bool which is true if "no_initialize_domain", false
+ *      otherwise.
+ *  (6) "is_last_name" is a bool which is true if "domainname" is "the last
+ *      component of a domainname", false otherwise.
+ */
+struct tomoyo_domain_keeper_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *domainname;
+	const struct tomoyo_path_info *program;       /* This may be NULL */
+	bool is_deleted;
+	bool is_not;       /* True if this entry is "no_keep_domain".        */
+	/* True if the domainname is tomoyo_get_last_name(). */
+	bool is_last_name;
+};
+
+/*
+ * tomoyo_alias_entry is a structure which is used for holding "alias" entries.
+ * It has following fields.
+ *
+ *  (1) "list" which is linked to tomoyo_alias_list .
+ *  (2) "original_name" which is a dereferenced pathname.
+ *  (3) "aliased_name" which is a symlink's pathname.
+ *  (4) "is_deleted" is a bool which is true if marked as deleted, false
+ *      otherwise.
+ */
+struct tomoyo_alias_entry {
+	struct list_head list;
+	const struct tomoyo_path_info *original_name;
+	const struct tomoyo_path_info *aliased_name;
+	bool is_deleted;
+};
+
+/*
+ * tomoyo_policy_manager_entry is a structure which is used for holding list of
+ * domainnames or programs which are permitted to modify configuration via
+ * /sys/kernel/security/tomoyo/ interface.
+ * It has following fields.
+ *
+ *  (1) "list" which is linked to tomoyo_policy_manager_list .
+ *  (2) "manager" is a domainname or a program's pathname.
+ *  (3) "is_domain" is a bool which is true if "manager" is a domainname, false
+ *      otherwise.
+ *  (4) "is_deleted" is a bool which is true if marked as deleted, false
+ *      otherwise.
+ */
+struct tomoyo_policy_manager_entry {
+	struct list_head list;
+	/* A path to program or a domainname. */
+	const struct tomoyo_path_info *manager;
+	bool is_domain;  /* True if manager is a domainname. */
+	bool is_deleted; /* True if this entry is deleted. */
+};
+
+/********** Function prototypes. **********/
+
 /* Check whether the domain has too many ACL entries to hold. */
 bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain);
 /* Transactional sprintf() for policy dump. */
 bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
 	__attribute__ ((format(printf, 2, 3)));
 /* Check whether the domainname is correct. */
-bool tomoyo_is_correct_domain(const unsigned char *domainname,
-			      const char *function);
+bool tomoyo_is_correct_domain(const unsigned char *domainname);
 /* Check whether the token is correct. */
 bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
-			    const s8 pattern_type, const s8 end_type,
-			    const char *function);
+			    const s8 pattern_type, const s8 end_type);
 /* Check whether the token can be a domainname. */
 bool tomoyo_is_domain_def(const unsigned char *buffer);
 /* Check whether the given filename matches the given pattern. */
@@ -328,13 +547,13 @@
 /* Write domain policy violation warning message to console? */
 bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain);
 /* Convert double path operation to operation name. */
-const char *tomoyo_dp2keyword(const u8 operation);
+const char *tomoyo_path22keyword(const u8 operation);
 /* Get the last component of the given domainname. */
 const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain);
 /* Get warning message. */
 const char *tomoyo_get_msg(const bool is_enforce);
 /* Convert single path operation to operation name. */
-const char *tomoyo_sp2keyword(const u8 operation);
+const char *tomoyo_path2keyword(const u8 operation);
 /* Create "alias" entry in exception policy. */
 int tomoyo_write_alias_policy(char *data, const bool is_delete);
 /*
@@ -370,15 +589,101 @@
 /* Check mode for specified functionality. */
 unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
 				const u8 index);
-/* Allocate memory for structures. */
-void *tomoyo_alloc_acl_element(const u8 acl_type);
 /* Fill in "struct tomoyo_path_info" members. */
 void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
 /* Run policy loader when /sbin/init starts. */
 void tomoyo_load_policy(const char *filename);
-/* Change "struct tomoyo_domain_info"->flags. */
-void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
-			    const bool is_delete, const u8 flags);
+
+/* Convert binary string to ascii string. */
+int tomoyo_encode(char *buffer, int buflen, const char *str);
+
+/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
+int tomoyo_realpath_from_path2(struct path *path, char *newname,
+			       int newname_len);
+
+/*
+ * Returns realpath(3) of the given pathname but ignores chroot'ed root.
+ * These functions use kzalloc(), so the caller must call kfree()
+ * if these functions didn't return NULL.
+ */
+char *tomoyo_realpath(const char *pathname);
+/*
+ * Same with tomoyo_realpath() except that it doesn't follow the final symlink.
+ */
+char *tomoyo_realpath_nofollow(const char *pathname);
+/* Same with tomoyo_realpath() except that the pathname is already solved. */
+char *tomoyo_realpath_from_path(struct path *path);
+
+/* Check memory quota. */
+bool tomoyo_memory_ok(void *ptr);
+
+/*
+ * Keep the given name on the RAM.
+ * The RAM is shared, so NEVER try to modify or kfree() the returned name.
+ */
+const struct tomoyo_path_info *tomoyo_get_name(const char *name);
+
+/* Check for memory usage. */
+int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head);
+
+/* Set memory quota. */
+int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
+
+/* Initialize realpath related code. */
+void __init tomoyo_realpath_init(void);
+int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
+			   const struct tomoyo_path_info *filename);
+int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
+				 struct path *path, const int flag);
+int tomoyo_path_perm(const u8 operation, struct path *path);
+int tomoyo_path2_perm(const u8 operation, struct path *path1,
+		      struct path *path2);
+int tomoyo_check_rewrite_permission(struct file *filp);
+int tomoyo_find_next_domain(struct linux_binprm *bprm);
+
+/* Run garbage collector. */
+void tomoyo_run_gc(void);
+
+void tomoyo_memory_free(void *ptr);
+
+/********** External variable definitions. **********/
+
+/* Lock for GC. */
+extern struct srcu_struct tomoyo_ss;
+
+/* The list for "struct tomoyo_domain_info". */
+extern struct list_head tomoyo_domain_list;
+
+extern struct list_head tomoyo_domain_initializer_list;
+extern struct list_head tomoyo_domain_keeper_list;
+extern struct list_head tomoyo_alias_list;
+extern struct list_head tomoyo_globally_readable_list;
+extern struct list_head tomoyo_pattern_list;
+extern struct list_head tomoyo_no_rewrite_list;
+extern struct list_head tomoyo_policy_manager_list;
+extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
+extern struct mutex tomoyo_name_list_lock;
+
+/* Lock for protecting policy. */
+extern struct mutex tomoyo_policy_lock;
+
+/* Has /sbin/init started? */
+extern bool tomoyo_policy_loaded;
+
+/* The kernel's domain. */
+extern struct tomoyo_domain_info tomoyo_kernel_domain;
+
+/********** Inlined functions. **********/
+
+static inline int tomoyo_read_lock(void)
+{
+	return srcu_read_lock(&tomoyo_ss);
+}
+
+static inline void tomoyo_read_unlock(int idx)
+{
+	srcu_read_unlock(&tomoyo_ss, idx);
+}
 
 /* strcmp() for "struct tomoyo_path_info" structure. */
 static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
@@ -387,18 +692,6 @@
 	return a->hash != b->hash || strcmp(a->name, b->name);
 }
 
-/* Get type of an ACL entry. */
-static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr)
-{
-	return ptr->type & ~TOMOYO_ACL_DELETED;
-}
-
-/* Get type of an ACL entry. */
-static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr)
-{
-	return ptr->type;
-}
-
 /**
  * tomoyo_is_valid - Check whether the character is a valid char.
  *
@@ -423,18 +716,25 @@
 	return c && (c <= ' ' || c >= 127);
 }
 
-/* The list for "struct tomoyo_domain_info". */
-extern struct list_head tomoyo_domain_list;
-extern struct rw_semaphore tomoyo_domain_list_lock;
+static inline void tomoyo_put_name(const struct tomoyo_path_info *name)
+{
+	if (name) {
+		struct tomoyo_name_entry *ptr =
+			container_of(name, struct tomoyo_name_entry, entry);
+		atomic_dec(&ptr->users);
+	}
+}
 
-/* Lock for domain->acl_info_list. */
-extern struct rw_semaphore tomoyo_domain_acl_info_list_lock;
+static inline struct tomoyo_domain_info *tomoyo_domain(void)
+{
+	return current_cred()->security;
+}
 
-/* Has /sbin/init started? */
-extern bool tomoyo_policy_loaded;
-
-/* The kernel's domain. */
-extern struct tomoyo_domain_info tomoyo_kernel_domain;
+static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
+							    *task)
+{
+	return task_cred_xxx(task, security);
+}
 
 /**
  * list_for_each_cookie - iterate over a list with cookie.
@@ -442,16 +742,16 @@
  * @cookie:     the &struct list_head to use as a cookie.
  * @head:       the head for your list.
  *
- * Same with list_for_each() except that this primitive uses @cookie
+ * Same with list_for_each_rcu() except that this primitive uses @cookie
  * so that we can continue iteration.
  * @cookie must be NULL when iteration starts, and @cookie will become
  * NULL when iteration finishes.
  */
-#define list_for_each_cookie(pos, cookie, head)                       \
-	for (({ if (!cookie)                                          \
-				     cookie = head; }),               \
-	     pos = (cookie)->next;                                    \
-	     prefetch(pos->next), pos != (head) || ((cookie) = NULL); \
-	     (cookie) = pos, pos = pos->next)
+#define list_for_each_cookie(pos, cookie, head)				\
+	for (({ if (!cookie)						\
+				     cookie = head; }),			\
+		     pos = rcu_dereference((cookie)->next);		\
+	     prefetch(pos->next), pos != (head) || ((cookie) = NULL);	\
+	     (cookie) = pos, pos = rcu_dereference(pos->next))
 
 #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index fcf52ac..66caaa1 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -10,8 +10,6 @@
  */
 
 #include "common.h"
-#include "tomoyo.h"
-#include "realpath.h"
 #include <linux/binfmts.h>
 
 /* Variables definitions.*/
@@ -58,99 +56,6 @@
  * exceptions.
  */
 LIST_HEAD(tomoyo_domain_list);
-DECLARE_RWSEM(tomoyo_domain_list_lock);
-
-/*
- * tomoyo_domain_initializer_entry is a structure which is used for holding
- * "initialize_domain" and "no_initialize_domain" entries.
- * It has following fields.
- *
- *  (1) "list" which is linked to tomoyo_domain_initializer_list .
- *  (2) "domainname" which is "a domainname" or "the last component of a
- *      domainname". This field is NULL if "from" clause is not specified.
- *  (3) "program" which is a program's pathname.
- *  (4) "is_deleted" is a bool which is true if marked as deleted, false
- *      otherwise.
- *  (5) "is_not" is a bool which is true if "no_initialize_domain", false
- *      otherwise.
- *  (6) "is_last_name" is a bool which is true if "domainname" is "the last
- *      component of a domainname", false otherwise.
- */
-struct tomoyo_domain_initializer_entry {
-	struct list_head list;
-	const struct tomoyo_path_info *domainname;    /* This may be NULL */
-	const struct tomoyo_path_info *program;
-	bool is_deleted;
-	bool is_not;       /* True if this entry is "no_initialize_domain".  */
-	/* True if the domainname is tomoyo_get_last_name(). */
-	bool is_last_name;
-};
-
-/*
- * tomoyo_domain_keeper_entry is a structure which is used for holding
- * "keep_domain" and "no_keep_domain" entries.
- * It has following fields.
- *
- *  (1) "list" which is linked to tomoyo_domain_keeper_list .
- *  (2) "domainname" which is "a domainname" or "the last component of a
- *      domainname".
- *  (3) "program" which is a program's pathname.
- *      This field is NULL if "from" clause is not specified.
- *  (4) "is_deleted" is a bool which is true if marked as deleted, false
- *      otherwise.
- *  (5) "is_not" is a bool which is true if "no_initialize_domain", false
- *      otherwise.
- *  (6) "is_last_name" is a bool which is true if "domainname" is "the last
- *      component of a domainname", false otherwise.
- */
-struct tomoyo_domain_keeper_entry {
-	struct list_head list;
-	const struct tomoyo_path_info *domainname;
-	const struct tomoyo_path_info *program;       /* This may be NULL */
-	bool is_deleted;
-	bool is_not;       /* True if this entry is "no_keep_domain".        */
-	/* True if the domainname is tomoyo_get_last_name(). */
-	bool is_last_name;
-};
-
-/*
- * tomoyo_alias_entry is a structure which is used for holding "alias" entries.
- * It has following fields.
- *
- *  (1) "list" which is linked to tomoyo_alias_list .
- *  (2) "original_name" which is a dereferenced pathname.
- *  (3) "aliased_name" which is a symlink's pathname.
- *  (4) "is_deleted" is a bool which is true if marked as deleted, false
- *      otherwise.
- */
-struct tomoyo_alias_entry {
-	struct list_head list;
-	const struct tomoyo_path_info *original_name;
-	const struct tomoyo_path_info *aliased_name;
-	bool is_deleted;
-};
-
-/**
- * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
- *
- * @domain:    Pointer to "struct tomoyo_domain_info".
- * @is_delete: True if it is a delete request.
- * @flags:     Flags to set or clear.
- *
- * Returns nothing.
- */
-void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
-			    const bool is_delete, const u8 flags)
-{
-	/* We need to serialize because this is bitfield operation. */
-	static DEFINE_SPINLOCK(lock);
-	spin_lock(&lock);
-	if (!is_delete)
-		domain->flags |= flags;
-	else
-		domain->flags &= ~flags;
-	spin_unlock(&lock);
-}
 
 /**
  * tomoyo_get_last_name - Get last component of a domainname.
@@ -205,8 +110,7 @@
  * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
  * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
  */
-static LIST_HEAD(tomoyo_domain_initializer_list);
-static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
+LIST_HEAD(tomoyo_domain_initializer_list);
 
 /**
  * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
@@ -217,59 +121,65 @@
  * @is_delete:  True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_update_domain_initializer_entry(const char *domainname,
 						  const char *program,
 						  const bool is_not,
 						  const bool is_delete)
 {
-	struct tomoyo_domain_initializer_entry *new_entry;
+	struct tomoyo_domain_initializer_entry *entry = NULL;
 	struct tomoyo_domain_initializer_entry *ptr;
-	const struct tomoyo_path_info *saved_program;
+	const struct tomoyo_path_info *saved_program = NULL;
 	const struct tomoyo_path_info *saved_domainname = NULL;
-	int error = -ENOMEM;
+	int error = is_delete ? -ENOENT : -ENOMEM;
 	bool is_last_name = false;
 
-	if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
+	if (!tomoyo_is_correct_path(program, 1, -1, -1))
 		return -EINVAL; /* No patterns allowed. */
 	if (domainname) {
 		if (!tomoyo_is_domain_def(domainname) &&
-		    tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
+		    tomoyo_is_correct_path(domainname, 1, -1, -1))
 			is_last_name = true;
-		else if (!tomoyo_is_correct_domain(domainname, __func__))
+		else if (!tomoyo_is_correct_domain(domainname))
 			return -EINVAL;
-		saved_domainname = tomoyo_save_name(domainname);
+		saved_domainname = tomoyo_get_name(domainname);
 		if (!saved_domainname)
-			return -ENOMEM;
+			goto out;
 	}
-	saved_program = tomoyo_save_name(program);
+	saved_program = tomoyo_get_name(program);
 	if (!saved_program)
-		return -ENOMEM;
-	down_write(&tomoyo_domain_initializer_list_lock);
-	list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
+		goto out;
+	if (!is_delete)
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	mutex_lock(&tomoyo_policy_lock);
+	list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
 		if (ptr->is_not != is_not ||
 		    ptr->domainname != saved_domainname ||
 		    ptr->program != saved_program)
 			continue;
 		ptr->is_deleted = is_delete;
 		error = 0;
-		goto out;
+		break;
 	}
-	if (is_delete) {
-		error = -ENOENT;
-		goto out;
+	if (!is_delete && error && tomoyo_memory_ok(entry)) {
+		entry->domainname = saved_domainname;
+		saved_domainname = NULL;
+		entry->program = saved_program;
+		saved_program = NULL;
+		entry->is_not = is_not;
+		entry->is_last_name = is_last_name;
+		list_add_tail_rcu(&entry->list,
+				  &tomoyo_domain_initializer_list);
+		entry = NULL;
+		error = 0;
 	}
-	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
-	if (!new_entry)
-		goto out;
-	new_entry->domainname = saved_domainname;
-	new_entry->program = saved_program;
-	new_entry->is_not = is_not;
-	new_entry->is_last_name = is_last_name;
-	list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list);
-	error = 0;
+	mutex_unlock(&tomoyo_policy_lock);
  out:
-	up_write(&tomoyo_domain_initializer_list_lock);
+	tomoyo_put_name(saved_domainname);
+	tomoyo_put_name(saved_program);
+	kfree(entry);
 	return error;
 }
 
@@ -279,13 +189,14 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
 {
 	struct list_head *pos;
 	bool done = true;
 
-	down_read(&tomoyo_domain_initializer_list_lock);
 	list_for_each_cookie(pos, head->read_var2,
 			     &tomoyo_domain_initializer_list) {
 		const char *no;
@@ -308,7 +219,6 @@
 		if (!done)
 			break;
 	}
-	up_read(&tomoyo_domain_initializer_list_lock);
 	return done;
 }
 
@@ -320,6 +230,8 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
 					   const bool is_delete)
@@ -345,6 +257,8 @@
  *
  * Returns true if executing @program reinitializes domain transition,
  * false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
 					 domainname,
@@ -355,8 +269,7 @@
 	struct tomoyo_domain_initializer_entry *ptr;
 	bool flag = false;
 
-	down_read(&tomoyo_domain_initializer_list_lock);
-	list_for_each_entry(ptr,  &tomoyo_domain_initializer_list, list) {
+	list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
 		if (ptr->is_deleted)
 			continue;
 		if (ptr->domainname) {
@@ -376,7 +289,6 @@
 		}
 		flag = true;
 	}
-	up_read(&tomoyo_domain_initializer_list_lock);
 	return flag;
 }
 
@@ -418,8 +330,7 @@
  * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
  * explicitly specified by "initialize_domain".
  */
-static LIST_HEAD(tomoyo_domain_keeper_list);
-static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
+LIST_HEAD(tomoyo_domain_keeper_list);
 
 /**
  * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
@@ -430,59 +341,64 @@
  * @is_delete:  True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_update_domain_keeper_entry(const char *domainname,
 					     const char *program,
 					     const bool is_not,
 					     const bool is_delete)
 {
-	struct tomoyo_domain_keeper_entry *new_entry;
+	struct tomoyo_domain_keeper_entry *entry = NULL;
 	struct tomoyo_domain_keeper_entry *ptr;
-	const struct tomoyo_path_info *saved_domainname;
+	const struct tomoyo_path_info *saved_domainname = NULL;
 	const struct tomoyo_path_info *saved_program = NULL;
-	int error = -ENOMEM;
+	int error = is_delete ? -ENOENT : -ENOMEM;
 	bool is_last_name = false;
 
 	if (!tomoyo_is_domain_def(domainname) &&
-	    tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
+	    tomoyo_is_correct_path(domainname, 1, -1, -1))
 		is_last_name = true;
-	else if (!tomoyo_is_correct_domain(domainname, __func__))
+	else if (!tomoyo_is_correct_domain(domainname))
 		return -EINVAL;
 	if (program) {
-		if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
+		if (!tomoyo_is_correct_path(program, 1, -1, -1))
 			return -EINVAL;
-		saved_program = tomoyo_save_name(program);
+		saved_program = tomoyo_get_name(program);
 		if (!saved_program)
-			return -ENOMEM;
+			goto out;
 	}
-	saved_domainname = tomoyo_save_name(domainname);
+	saved_domainname = tomoyo_get_name(domainname);
 	if (!saved_domainname)
-		return -ENOMEM;
-	down_write(&tomoyo_domain_keeper_list_lock);
-	list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
+		goto out;
+	if (!is_delete)
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	mutex_lock(&tomoyo_policy_lock);
+	list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
 		if (ptr->is_not != is_not ||
 		    ptr->domainname != saved_domainname ||
 		    ptr->program != saved_program)
 			continue;
 		ptr->is_deleted = is_delete;
 		error = 0;
-		goto out;
+		break;
 	}
-	if (is_delete) {
-		error = -ENOENT;
-		goto out;
+	if (!is_delete && error && tomoyo_memory_ok(entry)) {
+		entry->domainname = saved_domainname;
+		saved_domainname = NULL;
+		entry->program = saved_program;
+		saved_program = NULL;
+		entry->is_not = is_not;
+		entry->is_last_name = is_last_name;
+		list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list);
+		entry = NULL;
+		error = 0;
 	}
-	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
-	if (!new_entry)
-		goto out;
-	new_entry->domainname = saved_domainname;
-	new_entry->program = saved_program;
-	new_entry->is_not = is_not;
-	new_entry->is_last_name = is_last_name;
-	list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list);
-	error = 0;
+	mutex_unlock(&tomoyo_policy_lock);
  out:
-	up_write(&tomoyo_domain_keeper_list_lock);
+	tomoyo_put_name(saved_domainname);
+	tomoyo_put_name(saved_program);
+	kfree(entry);
 	return error;
 }
 
@@ -493,6 +409,7 @@
  * @is_not:    True if it is "no_keep_domain" entry.
  * @is_delete: True if it is a delete request.
  *
+ * Caller holds tomoyo_read_lock().
  */
 int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
 				      const bool is_delete)
@@ -513,13 +430,14 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
 {
 	struct list_head *pos;
 	bool done = true;
 
-	down_read(&tomoyo_domain_keeper_list_lock);
 	list_for_each_cookie(pos, head->read_var2,
 			     &tomoyo_domain_keeper_list) {
 		struct tomoyo_domain_keeper_entry *ptr;
@@ -542,7 +460,6 @@
 		if (!done)
 			break;
 	}
-	up_read(&tomoyo_domain_keeper_list_lock);
 	return done;
 }
 
@@ -555,6 +472,8 @@
  *
  * Returns true if executing @program supresses domain transition,
  * false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
 				    const struct tomoyo_path_info *program,
@@ -563,8 +482,7 @@
 	struct tomoyo_domain_keeper_entry *ptr;
 	bool flag = false;
 
-	down_read(&tomoyo_domain_keeper_list_lock);
-	list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
+	list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
 		if (ptr->is_deleted)
 			continue;
 		if (!ptr->is_last_name) {
@@ -582,7 +500,6 @@
 		}
 		flag = true;
 	}
-	up_read(&tomoyo_domain_keeper_list_lock);
 	return flag;
 }
 
@@ -616,8 +533,7 @@
  * /bin/busybox and domainname which the current process will belong to after
  * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
  */
-static LIST_HEAD(tomoyo_alias_list);
-static DECLARE_RWSEM(tomoyo_alias_list_lock);
+LIST_HEAD(tomoyo_alias_list);
 
 /**
  * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
@@ -627,46 +543,51 @@
  * @is_delete:     True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_update_alias_entry(const char *original_name,
 				     const char *aliased_name,
 				     const bool is_delete)
 {
-	struct tomoyo_alias_entry *new_entry;
+	struct tomoyo_alias_entry *entry = NULL;
 	struct tomoyo_alias_entry *ptr;
 	const struct tomoyo_path_info *saved_original_name;
 	const struct tomoyo_path_info *saved_aliased_name;
-	int error = -ENOMEM;
+	int error = is_delete ? -ENOENT : -ENOMEM;
 
-	if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) ||
-	    !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__))
+	if (!tomoyo_is_correct_path(original_name, 1, -1, -1) ||
+	    !tomoyo_is_correct_path(aliased_name, 1, -1, -1))
 		return -EINVAL; /* No patterns allowed. */
-	saved_original_name = tomoyo_save_name(original_name);
-	saved_aliased_name = tomoyo_save_name(aliased_name);
+	saved_original_name = tomoyo_get_name(original_name);
+	saved_aliased_name = tomoyo_get_name(aliased_name);
 	if (!saved_original_name || !saved_aliased_name)
-		return -ENOMEM;
-	down_write(&tomoyo_alias_list_lock);
-	list_for_each_entry(ptr, &tomoyo_alias_list, list) {
+		goto out;
+	if (!is_delete)
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	mutex_lock(&tomoyo_policy_lock);
+	list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
 		if (ptr->original_name != saved_original_name ||
 		    ptr->aliased_name != saved_aliased_name)
 			continue;
 		ptr->is_deleted = is_delete;
 		error = 0;
-		goto out;
+		break;
 	}
-	if (is_delete) {
-		error = -ENOENT;
-		goto out;
+	if (!is_delete && error && tomoyo_memory_ok(entry)) {
+		entry->original_name = saved_original_name;
+		saved_original_name = NULL;
+		entry->aliased_name = saved_aliased_name;
+		saved_aliased_name = NULL;
+		list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
+		entry = NULL;
+		error = 0;
 	}
-	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
-	if (!new_entry)
-		goto out;
-	new_entry->original_name = saved_original_name;
-	new_entry->aliased_name = saved_aliased_name;
-	list_add_tail(&new_entry->list, &tomoyo_alias_list);
-	error = 0;
+	mutex_unlock(&tomoyo_policy_lock);
  out:
-	up_write(&tomoyo_alias_list_lock);
+	tomoyo_put_name(saved_original_name);
+	tomoyo_put_name(saved_aliased_name);
+	kfree(entry);
 	return error;
 }
 
@@ -676,13 +597,14 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
 {
 	struct list_head *pos;
 	bool done = true;
 
-	down_read(&tomoyo_alias_list_lock);
 	list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
 		struct tomoyo_alias_entry *ptr;
 
@@ -695,7 +617,6 @@
 		if (!done)
 			break;
 	}
-	up_read(&tomoyo_alias_list_lock);
 	return done;
 }
 
@@ -706,6 +627,8 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 int tomoyo_write_alias_policy(char *data, const bool is_delete)
 {
@@ -724,63 +647,46 @@
  * @profile:    Profile number to assign if the domain was newly created.
  *
  * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
 							    domainname,
 							    const u8 profile)
 {
-	struct tomoyo_domain_info *domain = NULL;
+	struct tomoyo_domain_info *entry;
+	struct tomoyo_domain_info *domain;
 	const struct tomoyo_path_info *saved_domainname;
+	bool found = false;
 
-	down_write(&tomoyo_domain_list_lock);
-	domain = tomoyo_find_domain(domainname);
-	if (domain)
-		goto out;
-	if (!tomoyo_is_correct_domain(domainname, __func__))
-		goto out;
-	saved_domainname = tomoyo_save_name(domainname);
+	if (!tomoyo_is_correct_domain(domainname))
+		return NULL;
+	saved_domainname = tomoyo_get_name(domainname);
 	if (!saved_domainname)
-		goto out;
-	/* Can I reuse memory of deleted domain? */
-	list_for_each_entry(domain, &tomoyo_domain_list, list) {
-		struct task_struct *p;
-		struct tomoyo_acl_info *ptr;
-		bool flag;
-		if (!domain->is_deleted ||
-		    domain->domainname != saved_domainname)
+		return NULL;
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	mutex_lock(&tomoyo_policy_lock);
+	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
+		if (domain->is_deleted ||
+		    tomoyo_pathcmp(saved_domainname, domain->domainname))
 			continue;
-		flag = false;
-		read_lock(&tasklist_lock);
-		for_each_process(p) {
-			if (tomoyo_real_domain(p) != domain)
-				continue;
-			flag = true;
-			break;
-		}
-		read_unlock(&tasklist_lock);
-		if (flag)
-			continue;
-		list_for_each_entry(ptr, &domain->acl_info_list, list) {
-			ptr->type |= TOMOYO_ACL_DELETED;
-		}
-		tomoyo_set_domain_flag(domain, true, domain->flags);
-		domain->profile = profile;
-		domain->quota_warned = false;
-		mb(); /* Avoid out-of-order execution. */
-		domain->is_deleted = false;
-		goto out;
+		found = true;
+		break;
 	}
-	/* No memory reusable. Create using new memory. */
-	domain = tomoyo_alloc_element(sizeof(*domain));
-	if (domain) {
-		INIT_LIST_HEAD(&domain->acl_info_list);
-		domain->domainname = saved_domainname;
-		domain->profile = profile;
-		list_add_tail(&domain->list, &tomoyo_domain_list);
+	if (!found && tomoyo_memory_ok(entry)) {
+		INIT_LIST_HEAD(&entry->acl_info_list);
+		entry->domainname = saved_domainname;
+		saved_domainname = NULL;
+		entry->profile = profile;
+		list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
+		domain = entry;
+		entry = NULL;
+		found = true;
 	}
- out:
-	up_write(&tomoyo_domain_list_lock);
-	return domain;
+	mutex_unlock(&tomoyo_policy_lock);
+	tomoyo_put_name(saved_domainname);
+	kfree(entry);
+	return found ? domain : NULL;
 }
 
 /**
@@ -789,6 +695,8 @@
  * @bprm: Pointer to "struct linux_binprm".
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 int tomoyo_find_next_domain(struct linux_binprm *bprm)
 {
@@ -796,7 +704,7 @@
 	 * This function assumes that the size of buffer returned by
 	 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
 	 */
-	struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp));
+	struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
 	struct tomoyo_domain_info *old_domain = tomoyo_domain();
 	struct tomoyo_domain_info *domain = NULL;
 	const char *old_domain_name = old_domain->domainname->name;
@@ -849,8 +757,7 @@
 	if (tomoyo_pathcmp(&r, &s)) {
 		struct tomoyo_alias_entry *ptr;
 		/* Is this program allowed to be called via symbolic links? */
-		down_read(&tomoyo_alias_list_lock);
-		list_for_each_entry(ptr, &tomoyo_alias_list, list) {
+		list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
 			if (ptr->is_deleted ||
 			    tomoyo_pathcmp(&r, ptr->original_name) ||
 			    tomoyo_pathcmp(&s, ptr->aliased_name))
@@ -861,7 +768,6 @@
 			tomoyo_fill_path_info(&r);
 			break;
 		}
-		up_read(&tomoyo_alias_list_lock);
 	}
 
 	/* Check execute permission. */
@@ -892,9 +798,7 @@
 	}
 	if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
 		goto done;
-	down_read(&tomoyo_domain_list_lock);
 	domain = tomoyo_find_domain(new_domain_name);
-	up_read(&tomoyo_domain_list_lock);
 	if (domain)
 		goto done;
 	if (is_enforce)
@@ -909,14 +813,15 @@
 	if (is_enforce)
 		retval = -EPERM;
 	else
-		tomoyo_set_domain_flag(old_domain, false,
-				       TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
+		old_domain->transition_failed = true;
  out:
 	if (!domain)
 		domain = old_domain;
+	/* Update reference count on "struct tomoyo_domain_info". */
+	atomic_inc(&domain->users);
 	bprm->cred->security = domain;
-	tomoyo_free(real_program_name);
-	tomoyo_free(symlink_program_name);
-	tomoyo_free(tmp);
+	kfree(real_program_name);
+	kfree(symlink_program_name);
+	kfree(tmp);
 	return retval;
 }
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 9a6c588..1b24304 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -10,108 +10,64 @@
  */
 
 #include "common.h"
-#include "tomoyo.h"
-#include "realpath.h"
-
-/*
- * tomoyo_globally_readable_file_entry is a structure which is used for holding
- * "allow_read" entries.
- * It has following fields.
- *
- *  (1) "list" which is linked to tomoyo_globally_readable_list .
- *  (2) "filename" is a pathname which is allowed to open(O_RDONLY).
- *  (3) "is_deleted" is a bool which is true if marked as deleted, false
- *      otherwise.
- */
-struct tomoyo_globally_readable_file_entry {
-	struct list_head list;
-	const struct tomoyo_path_info *filename;
-	bool is_deleted;
-};
-
-/*
- * tomoyo_pattern_entry is a structure which is used for holding
- * "tomoyo_pattern_list" entries.
- * It has following fields.
- *
- *  (1) "list" which is linked to tomoyo_pattern_list .
- *  (2) "pattern" is a pathname pattern which is used for converting pathnames
- *      to pathname patterns during learning mode.
- *  (3) "is_deleted" is a bool which is true if marked as deleted, false
- *      otherwise.
- */
-struct tomoyo_pattern_entry {
-	struct list_head list;
-	const struct tomoyo_path_info *pattern;
-	bool is_deleted;
-};
-
-/*
- * tomoyo_no_rewrite_entry is a structure which is used for holding
- * "deny_rewrite" entries.
- * It has following fields.
- *
- *  (1) "list" which is linked to tomoyo_no_rewrite_list .
- *  (2) "pattern" is a pathname which is by default not permitted to modify
- *      already existing content.
- *  (3) "is_deleted" is a bool which is true if marked as deleted, false
- *      otherwise.
- */
-struct tomoyo_no_rewrite_entry {
-	struct list_head list;
-	const struct tomoyo_path_info *pattern;
-	bool is_deleted;
-};
 
 /* Keyword array for single path operations. */
-static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
-	[TOMOYO_TYPE_READ_WRITE_ACL] = "read/write",
-	[TOMOYO_TYPE_EXECUTE_ACL]    = "execute",
-	[TOMOYO_TYPE_READ_ACL]       = "read",
-	[TOMOYO_TYPE_WRITE_ACL]      = "write",
-	[TOMOYO_TYPE_CREATE_ACL]     = "create",
-	[TOMOYO_TYPE_UNLINK_ACL]     = "unlink",
-	[TOMOYO_TYPE_MKDIR_ACL]      = "mkdir",
-	[TOMOYO_TYPE_RMDIR_ACL]      = "rmdir",
-	[TOMOYO_TYPE_MKFIFO_ACL]     = "mkfifo",
-	[TOMOYO_TYPE_MKSOCK_ACL]     = "mksock",
-	[TOMOYO_TYPE_MKBLOCK_ACL]    = "mkblock",
-	[TOMOYO_TYPE_MKCHAR_ACL]     = "mkchar",
-	[TOMOYO_TYPE_TRUNCATE_ACL]   = "truncate",
-	[TOMOYO_TYPE_SYMLINK_ACL]    = "symlink",
-	[TOMOYO_TYPE_REWRITE_ACL]    = "rewrite",
+static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = {
+	[TOMOYO_TYPE_READ_WRITE] = "read/write",
+	[TOMOYO_TYPE_EXECUTE]    = "execute",
+	[TOMOYO_TYPE_READ]       = "read",
+	[TOMOYO_TYPE_WRITE]      = "write",
+	[TOMOYO_TYPE_CREATE]     = "create",
+	[TOMOYO_TYPE_UNLINK]     = "unlink",
+	[TOMOYO_TYPE_MKDIR]      = "mkdir",
+	[TOMOYO_TYPE_RMDIR]      = "rmdir",
+	[TOMOYO_TYPE_MKFIFO]     = "mkfifo",
+	[TOMOYO_TYPE_MKSOCK]     = "mksock",
+	[TOMOYO_TYPE_MKBLOCK]    = "mkblock",
+	[TOMOYO_TYPE_MKCHAR]     = "mkchar",
+	[TOMOYO_TYPE_TRUNCATE]   = "truncate",
+	[TOMOYO_TYPE_SYMLINK]    = "symlink",
+	[TOMOYO_TYPE_REWRITE]    = "rewrite",
+	[TOMOYO_TYPE_IOCTL]      = "ioctl",
+	[TOMOYO_TYPE_CHMOD]      = "chmod",
+	[TOMOYO_TYPE_CHOWN]      = "chown",
+	[TOMOYO_TYPE_CHGRP]      = "chgrp",
+	[TOMOYO_TYPE_CHROOT]     = "chroot",
+	[TOMOYO_TYPE_MOUNT]      = "mount",
+	[TOMOYO_TYPE_UMOUNT]     = "unmount",
 };
 
 /* Keyword array for double path operations. */
-static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
-	[TOMOYO_TYPE_LINK_ACL]    = "link",
-	[TOMOYO_TYPE_RENAME_ACL]  = "rename",
+static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = {
+	[TOMOYO_TYPE_LINK]    = "link",
+	[TOMOYO_TYPE_RENAME]  = "rename",
+	[TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root",
 };
 
 /**
- * tomoyo_sp2keyword - Get the name of single path operation.
+ * tomoyo_path2keyword - Get the name of single path operation.
  *
  * @operation: Type of operation.
  *
  * Returns the name of single path operation.
  */
-const char *tomoyo_sp2keyword(const u8 operation)
+const char *tomoyo_path2keyword(const u8 operation)
 {
-	return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION)
-		? tomoyo_sp_keyword[operation] : NULL;
+	return (operation < TOMOYO_MAX_PATH_OPERATION)
+		? tomoyo_path_keyword[operation] : NULL;
 }
 
 /**
- * tomoyo_dp2keyword - Get the name of double path operation.
+ * tomoyo_path22keyword - Get the name of double path operation.
  *
  * @operation: Type of operation.
  *
  * Returns the name of double path operation.
  */
-const char *tomoyo_dp2keyword(const u8 operation)
+const char *tomoyo_path22keyword(const u8 operation)
 {
-	return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION)
-		? tomoyo_dp_keyword[operation] : NULL;
+	return (operation < TOMOYO_MAX_PATH2_OPERATION)
+		? tomoyo_path2_keyword[operation] : NULL;
 }
 
 /**
@@ -142,7 +98,8 @@
 static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
 {
 	int error;
-	struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf));
+	struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf),
+							 GFP_KERNEL);
 
 	if (!buf)
 		return NULL;
@@ -154,20 +111,17 @@
 		tomoyo_fill_path_info(&buf->head);
 		return &buf->head;
 	}
-	tomoyo_free(buf);
+	kfree(buf);
 	return NULL;
 }
 
-/* Lock for domain->acl_info_list. */
-DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
-
-static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
-					 const char *filename2,
-					 struct tomoyo_domain_info *
-					 const domain, const bool is_delete);
-static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
-					 struct tomoyo_domain_info *
-					 const domain, const bool is_delete);
+static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
+				   const char *filename2,
+				   struct tomoyo_domain_info *const domain,
+				   const bool is_delete);
+static int tomoyo_update_path_acl(const u8 type, const char *filename,
+				  struct tomoyo_domain_info *const domain,
+				  const bool is_delete);
 
 /*
  * tomoyo_globally_readable_list is used for holding list of pathnames which
@@ -194,8 +148,7 @@
  * given "allow_read /lib/libc-2.5.so" to the domain which current process
  * belongs to.
  */
-static LIST_HEAD(tomoyo_globally_readable_list);
-static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
+LIST_HEAD(tomoyo_globally_readable_list);
 
 /**
  * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
@@ -204,40 +157,42 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_update_globally_readable_entry(const char *filename,
 						 const bool is_delete)
 {
-	struct tomoyo_globally_readable_file_entry *new_entry;
+	struct tomoyo_globally_readable_file_entry *entry = NULL;
 	struct tomoyo_globally_readable_file_entry *ptr;
 	const struct tomoyo_path_info *saved_filename;
-	int error = -ENOMEM;
+	int error = is_delete ? -ENOENT : -ENOMEM;
 
-	if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
+	if (!tomoyo_is_correct_path(filename, 1, 0, -1))
 		return -EINVAL;
-	saved_filename = tomoyo_save_name(filename);
+	saved_filename = tomoyo_get_name(filename);
 	if (!saved_filename)
 		return -ENOMEM;
-	down_write(&tomoyo_globally_readable_list_lock);
-	list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
+	if (!is_delete)
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	mutex_lock(&tomoyo_policy_lock);
+	list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
 		if (ptr->filename != saved_filename)
 			continue;
 		ptr->is_deleted = is_delete;
 		error = 0;
-		goto out;
+		break;
 	}
-	if (is_delete) {
-		error = -ENOENT;
-		goto out;
+	if (!is_delete && error && tomoyo_memory_ok(entry)) {
+		entry->filename = saved_filename;
+		saved_filename = NULL;
+		list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list);
+		entry = NULL;
+		error = 0;
 	}
-	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
-	if (!new_entry)
-		goto out;
-	new_entry->filename = saved_filename;
-	list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
-	error = 0;
- out:
-	up_write(&tomoyo_globally_readable_list_lock);
+	mutex_unlock(&tomoyo_policy_lock);
+	tomoyo_put_name(saved_filename);
+	kfree(entry);
 	return error;
 }
 
@@ -247,21 +202,22 @@
  * @filename: The filename to check.
  *
  * Returns true if any domain can open @filename for reading, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
 					     filename)
 {
 	struct tomoyo_globally_readable_file_entry *ptr;
 	bool found = false;
-	down_read(&tomoyo_globally_readable_list_lock);
-	list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
+
+	list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
 		if (!ptr->is_deleted &&
 		    tomoyo_path_matches_pattern(filename, ptr->filename)) {
 			found = true;
 			break;
 		}
 	}
-	up_read(&tomoyo_globally_readable_list_lock);
 	return found;
 }
 
@@ -272,6 +228,8 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
 {
@@ -284,13 +242,14 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
 {
 	struct list_head *pos;
 	bool done = true;
 
-	down_read(&tomoyo_globally_readable_list_lock);
 	list_for_each_cookie(pos, head->read_var2,
 			     &tomoyo_globally_readable_list) {
 		struct tomoyo_globally_readable_file_entry *ptr;
@@ -304,7 +263,6 @@
 		if (!done)
 			break;
 	}
-	up_read(&tomoyo_globally_readable_list_lock);
 	return done;
 }
 
@@ -337,8 +295,7 @@
  * which pretends as if /proc/self/ is not a symlink; so that we can forbid
  * current process from accessing other process's information.
  */
-static LIST_HEAD(tomoyo_pattern_list);
-static DECLARE_RWSEM(tomoyo_pattern_list_lock);
+LIST_HEAD(tomoyo_pattern_list);
 
 /**
  * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
@@ -347,40 +304,43 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_update_file_pattern_entry(const char *pattern,
 					    const bool is_delete)
 {
-	struct tomoyo_pattern_entry *new_entry;
+	struct tomoyo_pattern_entry *entry = NULL;
 	struct tomoyo_pattern_entry *ptr;
 	const struct tomoyo_path_info *saved_pattern;
-	int error = -ENOMEM;
+	int error = is_delete ? -ENOENT : -ENOMEM;
 
-	if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
-		return -EINVAL;
-	saved_pattern = tomoyo_save_name(pattern);
+	saved_pattern = tomoyo_get_name(pattern);
 	if (!saved_pattern)
-		return -ENOMEM;
-	down_write(&tomoyo_pattern_list_lock);
-	list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
+		return error;
+	if (!saved_pattern->is_patterned)
+		goto out;
+	if (!is_delete)
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	mutex_lock(&tomoyo_policy_lock);
+	list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
 		if (saved_pattern != ptr->pattern)
 			continue;
 		ptr->is_deleted = is_delete;
 		error = 0;
-		goto out;
+		break;
 	}
-	if (is_delete) {
-		error = -ENOENT;
-		goto out;
+	if (!is_delete && error && tomoyo_memory_ok(entry)) {
+		entry->pattern = saved_pattern;
+		saved_pattern = NULL;
+		list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
+		entry = NULL;
+		error = 0;
 	}
-	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
-	if (!new_entry)
-		goto out;
-	new_entry->pattern = saved_pattern;
-	list_add_tail(&new_entry->list, &tomoyo_pattern_list);
-	error = 0;
+	mutex_unlock(&tomoyo_policy_lock);
  out:
-	up_write(&tomoyo_pattern_list_lock);
+	kfree(entry);
+	tomoyo_put_name(saved_pattern);
 	return error;
 }
 
@@ -390,6 +350,8 @@
  * @filename: The filename to find patterned pathname.
  *
  * Returns pointer to pathname pattern if matched, @filename otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static const struct tomoyo_path_info *
 tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
@@ -397,8 +359,7 @@
 	struct tomoyo_pattern_entry *ptr;
 	const struct tomoyo_path_info *pattern = NULL;
 
-	down_read(&tomoyo_pattern_list_lock);
-	list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
+	list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
 		if (ptr->is_deleted)
 			continue;
 		if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
@@ -411,7 +372,6 @@
 			break;
 		}
 	}
-	up_read(&tomoyo_pattern_list_lock);
 	if (pattern)
 		filename = pattern;
 	return filename;
@@ -424,6 +384,8 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 int tomoyo_write_pattern_policy(char *data, const bool is_delete)
 {
@@ -436,13 +398,14 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
 {
 	struct list_head *pos;
 	bool done = true;
 
-	down_read(&tomoyo_pattern_list_lock);
 	list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
 		struct tomoyo_pattern_entry *ptr;
 		ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
@@ -453,7 +416,6 @@
 		if (!done)
 			break;
 	}
-	up_read(&tomoyo_pattern_list_lock);
 	return done;
 }
 
@@ -486,8 +448,7 @@
  * " (deleted)" suffix if the file is already unlink()ed; so that we don't
  * need to worry whether the file is already unlink()ed or not.
  */
-static LIST_HEAD(tomoyo_no_rewrite_list);
-static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
+LIST_HEAD(tomoyo_no_rewrite_list);
 
 /**
  * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
@@ -496,39 +457,42 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_update_no_rewrite_entry(const char *pattern,
 					  const bool is_delete)
 {
-	struct tomoyo_no_rewrite_entry *new_entry, *ptr;
+	struct tomoyo_no_rewrite_entry *entry = NULL;
+	struct tomoyo_no_rewrite_entry *ptr;
 	const struct tomoyo_path_info *saved_pattern;
-	int error = -ENOMEM;
+	int error = is_delete ? -ENOENT : -ENOMEM;
 
-	if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
+	if (!tomoyo_is_correct_path(pattern, 0, 0, 0))
 		return -EINVAL;
-	saved_pattern = tomoyo_save_name(pattern);
+	saved_pattern = tomoyo_get_name(pattern);
 	if (!saved_pattern)
-		return -ENOMEM;
-	down_write(&tomoyo_no_rewrite_list_lock);
-	list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
+		return error;
+	if (!is_delete)
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	mutex_lock(&tomoyo_policy_lock);
+	list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
 		if (ptr->pattern != saved_pattern)
 			continue;
 		ptr->is_deleted = is_delete;
 		error = 0;
-		goto out;
+		break;
 	}
-	if (is_delete) {
-		error = -ENOENT;
-		goto out;
+	if (!is_delete && error && tomoyo_memory_ok(entry)) {
+		entry->pattern = saved_pattern;
+		saved_pattern = NULL;
+		list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list);
+		entry = NULL;
+		error = 0;
 	}
-	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
-	if (!new_entry)
-		goto out;
-	new_entry->pattern = saved_pattern;
-	list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
-	error = 0;
- out:
-	up_write(&tomoyo_no_rewrite_list_lock);
+	mutex_unlock(&tomoyo_policy_lock);
+	tomoyo_put_name(saved_pattern);
+	kfree(entry);
 	return error;
 }
 
@@ -539,14 +503,15 @@
  *
  * Returns true if @filename is specified by "deny_rewrite" directive,
  * false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
 {
 	struct tomoyo_no_rewrite_entry *ptr;
 	bool found = false;
 
-	down_read(&tomoyo_no_rewrite_list_lock);
-	list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
+	list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
 		if (ptr->is_deleted)
 			continue;
 		if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
@@ -554,7 +519,6 @@
 		found = true;
 		break;
 	}
-	up_read(&tomoyo_no_rewrite_list_lock);
 	return found;
 }
 
@@ -565,6 +529,8 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
 {
@@ -577,13 +543,14 @@
  * @head: Pointer to "struct tomoyo_io_buffer".
  *
  * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
 {
 	struct list_head *pos;
 	bool done = true;
 
-	down_read(&tomoyo_no_rewrite_list_lock);
 	list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
 		struct tomoyo_no_rewrite_entry *ptr;
 		ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
@@ -594,7 +561,6 @@
 		if (!done)
 			break;
 	}
-	up_read(&tomoyo_no_rewrite_list_lock);
 	return done;
 }
 
@@ -612,6 +578,8 @@
  * Current policy syntax uses "allow_read/write" instead of "6",
  * "allow_read" instead of "4", "allow_write" instead of "2",
  * "allow_execute" instead of "1".
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_update_file_acl(const char *filename, u8 perm,
 				  struct tomoyo_domain_info * const domain,
@@ -629,19 +597,19 @@
 		 */
 		return 0;
 	if (perm & 4)
-		tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename,
-					      domain, is_delete);
+		tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain,
+				       is_delete);
 	if (perm & 2)
-		tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename,
-					      domain, is_delete);
+		tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain,
+				       is_delete);
 	if (perm & 1)
-		tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL,
-					      filename, domain, is_delete);
+		tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain,
+				       is_delete);
 	return 0;
 }
 
 /**
- * tomoyo_check_single_path_acl2 - Check permission for single path operation.
+ * tomoyo_path_acl2 - Check permission for single path operation.
  *
  * @domain:          Pointer to "struct tomoyo_domain_info".
  * @filename:        Filename to check.
@@ -649,26 +617,28 @@
  * @may_use_pattern: True if patterned ACL is permitted.
  *
  * Returns 0 on success, -EPERM otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
-					 domain,
-					 const struct tomoyo_path_info *
-					 filename,
-					 const u16 perm,
-					 const bool may_use_pattern)
+static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain,
+			    const struct tomoyo_path_info *filename,
+			    const u32 perm, const bool may_use_pattern)
 {
 	struct tomoyo_acl_info *ptr;
 	int error = -EPERM;
 
-	down_read(&tomoyo_domain_acl_info_list_lock);
-	list_for_each_entry(ptr, &domain->acl_info_list, list) {
-		struct tomoyo_single_path_acl_record *acl;
-		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
+	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
+		struct tomoyo_path_acl *acl;
+		if (ptr->type != TOMOYO_TYPE_PATH_ACL)
 			continue;
-		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
-				   head);
-		if (!(acl->perm & perm))
-			continue;
+		acl = container_of(ptr, struct tomoyo_path_acl, head);
+		if (perm <= 0xFFFF) {
+			if (!(acl->perm & perm))
+				continue;
+		} else {
+			if (!(acl->perm_high & (perm >> 16)))
+				continue;
+		}
 		if (may_use_pattern || !acl->filename->is_patterned) {
 			if (!tomoyo_path_matches_pattern(filename,
 							 acl->filename))
@@ -679,7 +649,6 @@
 		error = 0;
 		break;
 	}
-	up_read(&tomoyo_domain_acl_info_list_lock);
 	return error;
 }
 
@@ -691,27 +660,28 @@
  * @operation: Mode ("read" or "write" or "read/write" or "execute").
  *
  * Returns 0 on success, -EPERM otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
 				 const struct tomoyo_path_info *filename,
 				 const u8 operation)
 {
-	u16 perm = 0;
+	u32 perm = 0;
 
 	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
 		return 0;
 	if (operation == 6)
-		perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL;
+		perm = 1 << TOMOYO_TYPE_READ_WRITE;
 	else if (operation == 4)
-		perm = 1 << TOMOYO_TYPE_READ_ACL;
+		perm = 1 << TOMOYO_TYPE_READ;
 	else if (operation == 2)
-		perm = 1 << TOMOYO_TYPE_WRITE_ACL;
+		perm = 1 << TOMOYO_TYPE_WRITE;
 	else if (operation == 1)
-		perm = 1 << TOMOYO_TYPE_EXECUTE_ACL;
+		perm = 1 << TOMOYO_TYPE_EXECUTE;
 	else
 		BUG();
-	return tomoyo_check_single_path_acl2(domain, filename, perm,
-					     operation != 1);
+	return tomoyo_path_acl2(domain, filename, perm, operation != 1);
 }
 
 /**
@@ -724,6 +694,8 @@
  * @mode:      Access control mode.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
 				   const struct tomoyo_path_info *filename,
@@ -737,18 +709,17 @@
 	if (!filename)
 		return 0;
 	error = tomoyo_check_file_acl(domain, filename, perm);
-	if (error && perm == 4 &&
-	    (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
+	if (error && perm == 4 && !domain->ignore_global_allow_read
 	    && tomoyo_is_globally_readable_file(filename))
 		error = 0;
 	if (perm == 6)
-		msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL);
+		msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE);
 	else if (perm == 4)
-		msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL);
+		msg = tomoyo_path2keyword(TOMOYO_TYPE_READ);
 	else if (perm == 2)
-		msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL);
+		msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE);
 	else if (perm == 1)
-		msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL);
+		msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE);
 	else
 		BUG();
 	if (!error)
@@ -777,6 +748,8 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
 			     const bool is_delete)
@@ -795,28 +768,28 @@
 	if (strncmp(data, "allow_", 6))
 		goto out;
 	data += 6;
-	for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) {
-		if (strcmp(data, tomoyo_sp_keyword[type]))
+	for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
+		if (strcmp(data, tomoyo_path_keyword[type]))
 			continue;
-		return tomoyo_update_single_path_acl(type, filename,
-						     domain, is_delete);
+		return tomoyo_update_path_acl(type, filename, domain,
+					      is_delete);
 	}
 	filename2 = strchr(filename, ' ');
 	if (!filename2)
 		goto out;
 	*filename2++ = '\0';
-	for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) {
-		if (strcmp(data, tomoyo_dp_keyword[type]))
+	for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) {
+		if (strcmp(data, tomoyo_path2_keyword[type]))
 			continue;
-		return tomoyo_update_double_path_acl(type, filename, filename2,
-						     domain, is_delete);
+		return tomoyo_update_path2_acl(type, filename, filename2,
+					       domain, is_delete);
 	}
  out:
 	return -EINVAL;
 }
 
 /**
- * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list.
+ * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
  *
  * @type:      Type of operation.
  * @filename:  Filename.
@@ -824,85 +797,82 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
-					 struct tomoyo_domain_info *
-					 const domain, const bool is_delete)
+static int tomoyo_update_path_acl(const u8 type, const char *filename,
+				  struct tomoyo_domain_info *const domain,
+				  const bool is_delete)
 {
-	static const u16 rw_mask =
-		(1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
+	static const u32 rw_mask =
+		(1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE);
 	const struct tomoyo_path_info *saved_filename;
 	struct tomoyo_acl_info *ptr;
-	struct tomoyo_single_path_acl_record *acl;
-	int error = -ENOMEM;
-	const u16 perm = 1 << type;
+	struct tomoyo_path_acl *entry = NULL;
+	int error = is_delete ? -ENOENT : -ENOMEM;
+	const u32 perm = 1 << type;
 
 	if (!domain)
 		return -EINVAL;
-	if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
+	if (!tomoyo_is_correct_path(filename, 0, 0, 0))
 		return -EINVAL;
-	saved_filename = tomoyo_save_name(filename);
+	saved_filename = tomoyo_get_name(filename);
 	if (!saved_filename)
 		return -ENOMEM;
-	down_write(&tomoyo_domain_acl_info_list_lock);
-	if (is_delete)
-		goto delete;
-	list_for_each_entry(ptr, &domain->acl_info_list, list) {
-		if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
+	if (!is_delete)
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	mutex_lock(&tomoyo_policy_lock);
+	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
+		struct tomoyo_path_acl *acl =
+			container_of(ptr, struct tomoyo_path_acl, head);
+		if (ptr->type != TOMOYO_TYPE_PATH_ACL)
 			continue;
-		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
-				   head);
 		if (acl->filename != saved_filename)
 			continue;
-		/* Special case. Clear all bits if marked as deleted. */
-		if (ptr->type & TOMOYO_ACL_DELETED)
-			acl->perm = 0;
-		acl->perm |= perm;
-		if ((acl->perm & rw_mask) == rw_mask)
-			acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
-		else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
-			acl->perm |= rw_mask;
-		ptr->type &= ~TOMOYO_ACL_DELETED;
-		error = 0;
-		goto out;
-	}
-	/* Not found. Append it to the tail. */
-	acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
-	if (!acl)
-		goto out;
-	acl->perm = perm;
-	if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
-		acl->perm |= rw_mask;
-	acl->filename = saved_filename;
-	list_add_tail(&acl->head.list, &domain->acl_info_list);
-	error = 0;
-	goto out;
- delete:
-	error = -ENOENT;
-	list_for_each_entry(ptr, &domain->acl_info_list, list) {
-		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
-			continue;
-		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
-				   head);
-		if (acl->filename != saved_filename)
-			continue;
-		acl->perm &= ~perm;
-		if ((acl->perm & rw_mask) != rw_mask)
-			acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
-		else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
-			acl->perm &= ~rw_mask;
-		if (!acl->perm)
-			ptr->type |= TOMOYO_ACL_DELETED;
+		if (is_delete) {
+			if (perm <= 0xFFFF)
+				acl->perm &= ~perm;
+			else
+				acl->perm_high &= ~(perm >> 16);
+			if ((acl->perm & rw_mask) != rw_mask)
+				acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
+			else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)))
+				acl->perm &= ~rw_mask;
+		} else {
+			if (perm <= 0xFFFF)
+				acl->perm |= perm;
+			else
+				acl->perm_high |= (perm >> 16);
+			if ((acl->perm & rw_mask) == rw_mask)
+				acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
+			else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))
+				acl->perm |= rw_mask;
+		}
 		error = 0;
 		break;
 	}
- out:
-	up_write(&tomoyo_domain_acl_info_list_lock);
+	if (!is_delete && error && tomoyo_memory_ok(entry)) {
+		entry->head.type = TOMOYO_TYPE_PATH_ACL;
+		if (perm <= 0xFFFF)
+			entry->perm = perm;
+		else
+			entry->perm_high = (perm >> 16);
+		if (perm == (1 << TOMOYO_TYPE_READ_WRITE))
+			entry->perm |= rw_mask;
+		entry->filename = saved_filename;
+		saved_filename = NULL;
+		list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
+		entry = NULL;
+		error = 0;
+	}
+	mutex_unlock(&tomoyo_policy_lock);
+	kfree(entry);
+	tomoyo_put_name(saved_filename);
 	return error;
 }
 
 /**
- * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list.
+ * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
  *
  * @type:      Type of operation.
  * @filename1: First filename.
@@ -911,98 +881,88 @@
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
-					 const char *filename2,
-					 struct tomoyo_domain_info *
-					 const domain, const bool is_delete)
+static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
+				   const char *filename2,
+				   struct tomoyo_domain_info *const domain,
+				   const bool is_delete)
 {
 	const struct tomoyo_path_info *saved_filename1;
 	const struct tomoyo_path_info *saved_filename2;
 	struct tomoyo_acl_info *ptr;
-	struct tomoyo_double_path_acl_record *acl;
-	int error = -ENOMEM;
+	struct tomoyo_path2_acl *entry = NULL;
+	int error = is_delete ? -ENOENT : -ENOMEM;
 	const u8 perm = 1 << type;
 
 	if (!domain)
 		return -EINVAL;
-	if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
-	    !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
+	if (!tomoyo_is_correct_path(filename1, 0, 0, 0) ||
+	    !tomoyo_is_correct_path(filename2, 0, 0, 0))
 		return -EINVAL;
-	saved_filename1 = tomoyo_save_name(filename1);
-	saved_filename2 = tomoyo_save_name(filename2);
+	saved_filename1 = tomoyo_get_name(filename1);
+	saved_filename2 = tomoyo_get_name(filename2);
 	if (!saved_filename1 || !saved_filename2)
-		return -ENOMEM;
-	down_write(&tomoyo_domain_acl_info_list_lock);
-	if (is_delete)
-		goto delete;
-	list_for_each_entry(ptr, &domain->acl_info_list, list) {
-		if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
+		goto out;
+	if (!is_delete)
+		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	mutex_lock(&tomoyo_policy_lock);
+	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
+		struct tomoyo_path2_acl *acl =
+			container_of(ptr, struct tomoyo_path2_acl, head);
+		if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
 			continue;
-		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
-				   head);
 		if (acl->filename1 != saved_filename1 ||
 		    acl->filename2 != saved_filename2)
 			continue;
-		/* Special case. Clear all bits if marked as deleted. */
-		if (ptr->type & TOMOYO_ACL_DELETED)
-			acl->perm = 0;
-		acl->perm |= perm;
-		ptr->type &= ~TOMOYO_ACL_DELETED;
-		error = 0;
-		goto out;
-	}
-	/* Not found. Append it to the tail. */
-	acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
-	if (!acl)
-		goto out;
-	acl->perm = perm;
-	acl->filename1 = saved_filename1;
-	acl->filename2 = saved_filename2;
-	list_add_tail(&acl->head.list, &domain->acl_info_list);
-	error = 0;
-	goto out;
- delete:
-	error = -ENOENT;
-	list_for_each_entry(ptr, &domain->acl_info_list, list) {
-		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
-			continue;
-		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
-				   head);
-		if (acl->filename1 != saved_filename1 ||
-		    acl->filename2 != saved_filename2)
-			continue;
-		acl->perm &= ~perm;
-		if (!acl->perm)
-			ptr->type |= TOMOYO_ACL_DELETED;
+		if (is_delete)
+			acl->perm &= ~perm;
+		else
+			acl->perm |= perm;
 		error = 0;
 		break;
 	}
+	if (!is_delete && error && tomoyo_memory_ok(entry)) {
+		entry->head.type = TOMOYO_TYPE_PATH2_ACL;
+		entry->perm = perm;
+		entry->filename1 = saved_filename1;
+		saved_filename1 = NULL;
+		entry->filename2 = saved_filename2;
+		saved_filename2 = NULL;
+		list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
+		entry = NULL;
+		error = 0;
+	}
+	mutex_unlock(&tomoyo_policy_lock);
  out:
-	up_write(&tomoyo_domain_acl_info_list_lock);
+	tomoyo_put_name(saved_filename1);
+	tomoyo_put_name(saved_filename2);
+	kfree(entry);
 	return error;
 }
 
 /**
- * tomoyo_check_single_path_acl - Check permission for single path operation.
+ * tomoyo_path_acl - Check permission for single path operation.
  *
  * @domain:   Pointer to "struct tomoyo_domain_info".
  * @type:     Type of operation.
  * @filename: Filename to check.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
-					const u8 type,
-					const struct tomoyo_path_info *filename)
+static int tomoyo_path_acl(struct tomoyo_domain_info *domain, const u8 type,
+			   const struct tomoyo_path_info *filename)
 {
 	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
 		return 0;
-	return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1);
+	return tomoyo_path_acl2(domain, filename, 1 << type, 1);
 }
 
 /**
- * tomoyo_check_double_path_acl - Check permission for double path operation.
+ * tomoyo_path2_acl - Check permission for double path operation.
  *
  * @domain:    Pointer to "struct tomoyo_domain_info".
  * @type:      Type of operation.
@@ -1010,13 +970,13 @@
  * @filename2: Second filename to check.
  *
  * Returns 0 on success, -EPERM otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
-					const u8 type,
-					const struct tomoyo_path_info *
-					filename1,
-					const struct tomoyo_path_info *
-					filename2)
+static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain,
+			    const u8 type,
+			    const struct tomoyo_path_info *filename1,
+			    const struct tomoyo_path_info *filename2)
 {
 	struct tomoyo_acl_info *ptr;
 	const u8 perm = 1 << type;
@@ -1024,13 +984,11 @@
 
 	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
 		return 0;
-	down_read(&tomoyo_domain_acl_info_list_lock);
-	list_for_each_entry(ptr, &domain->acl_info_list, list) {
-		struct tomoyo_double_path_acl_record *acl;
-		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
+	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
+		struct tomoyo_path2_acl *acl;
+		if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
 			continue;
-		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
-				   head);
+		acl = container_of(ptr, struct tomoyo_path2_acl, head);
 		if (!(acl->perm & perm))
 			continue;
 		if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
@@ -1040,12 +998,11 @@
 		error = 0;
 		break;
 	}
-	up_read(&tomoyo_domain_acl_info_list_lock);
 	return error;
 }
 
 /**
- * tomoyo_check_single_path_permission2 - Check permission for single path operation.
+ * tomoyo_path_permission2 - Check permission for single path operation.
  *
  * @domain:    Pointer to "struct tomoyo_domain_info".
  * @operation: Type of operation.
@@ -1053,11 +1010,13 @@
  * @mode:      Access control mode.
  *
  * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
-						const domain, u8 operation,
-						const struct tomoyo_path_info *
-						filename, const u8 mode)
+static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain,
+				   u8 operation,
+				   const struct tomoyo_path_info *filename,
+				   const u8 mode)
 {
 	const char *msg;
 	int error;
@@ -1066,8 +1025,8 @@
 	if (!mode)
 		return 0;
  next:
-	error = tomoyo_check_single_path_acl(domain, operation, filename);
-	msg = tomoyo_sp2keyword(operation);
+	error = tomoyo_path_acl(domain, operation, filename);
+	msg = tomoyo_path2keyword(operation);
 	if (!error)
 		goto ok;
 	if (tomoyo_verbose_mode(domain))
@@ -1076,7 +1035,7 @@
 		       tomoyo_get_last_name(domain));
 	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
 		const char *name = tomoyo_get_file_pattern(filename)->name;
-		tomoyo_update_single_path_acl(operation, name, domain, false);
+		tomoyo_update_path_acl(operation, name, domain, false);
 	}
 	if (!is_enforce)
 		error = 0;
@@ -1086,9 +1045,9 @@
 	 * we need to check "allow_rewrite" permission if the filename is
 	 * specified by "deny_rewrite" keyword.
 	 */
-	if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL &&
+	if (!error && operation == TOMOYO_TYPE_TRUNCATE &&
 	    tomoyo_is_no_rewrite_file(filename)) {
-		operation = TOMOYO_TYPE_REWRITE_ACL;
+		operation = TOMOYO_TYPE_REWRITE;
 		goto next;
 	}
 	return error;
@@ -1101,6 +1060,8 @@
  * @filename: Check permission for "execute".
  *
  * Returns 0 on success, negativevalue otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
  */
 int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
 			   const struct tomoyo_path_info *filename)
@@ -1129,6 +1090,7 @@
 	struct tomoyo_path_info *buf;
 	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
 	const bool is_enforce = (mode == 3);
+	int idx;
 
 	if (!mode || !path->mnt)
 		return 0;
@@ -1140,6 +1102,7 @@
 		 * don't call me.
 		 */
 		return 0;
+	idx = tomoyo_read_lock();
 	buf = tomoyo_get_path(path);
 	if (!buf)
 		goto out;
@@ -1152,49 +1115,50 @@
 	if ((acc_mode & MAY_WRITE) &&
 	    ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
 	    (tomoyo_is_no_rewrite_file(buf))) {
-		error = tomoyo_check_single_path_permission2(domain,
-						     TOMOYO_TYPE_REWRITE_ACL,
-							     buf, mode);
+		error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE,
+						buf, mode);
 	}
 	if (!error)
 		error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
 						mode);
 	if (!error && (flag & O_TRUNC))
-		error = tomoyo_check_single_path_permission2(domain,
-						     TOMOYO_TYPE_TRUNCATE_ACL,
-							     buf, mode);
+		error = tomoyo_path_permission2(domain, TOMOYO_TYPE_TRUNCATE,
+						buf, mode);
  out:
-	tomoyo_free(buf);
+	kfree(buf);
+	tomoyo_read_unlock(idx);
 	if (!is_enforce)
 		error = 0;
 	return error;
 }
 
 /**
- * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink".
+ * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount".
  *
- * @domain:    Pointer to "struct tomoyo_domain_info".
  * @operation: Type of operation.
  * @path:      Pointer to "struct path".
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
-			    const u8 operation, struct path *path)
+int tomoyo_path_perm(const u8 operation, struct path *path)
 {
 	int error = -ENOMEM;
 	struct tomoyo_path_info *buf;
+	struct tomoyo_domain_info *domain = tomoyo_domain();
 	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
 	const bool is_enforce = (mode == 3);
+	int idx;
 
 	if (!mode || !path->mnt)
 		return 0;
+	idx = tomoyo_read_lock();
 	buf = tomoyo_get_path(path);
 	if (!buf)
 		goto out;
 	switch (operation) {
-	case TOMOYO_TYPE_MKDIR_ACL:
-	case TOMOYO_TYPE_RMDIR_ACL:
+	case TOMOYO_TYPE_MKDIR:
+	case TOMOYO_TYPE_RMDIR:
+	case TOMOYO_TYPE_CHROOT:
 		if (!buf->is_dir) {
 			/*
 			 * tomoyo_get_path() reserves space for appending "/."
@@ -1203,10 +1167,10 @@
 			tomoyo_fill_path_info(buf);
 		}
 	}
-	error = tomoyo_check_single_path_permission2(domain, operation, buf,
-						     mode);
+	error = tomoyo_path_permission2(domain, operation, buf, mode);
  out:
-	tomoyo_free(buf);
+	kfree(buf);
+	tomoyo_read_unlock(idx);
 	if (!is_enforce)
 		error = 0;
 	return error;
@@ -1215,21 +1179,23 @@
 /**
  * tomoyo_check_rewrite_permission - Check permission for "rewrite".
  *
- * @domain: Pointer to "struct tomoyo_domain_info".
  * @filp: Pointer to "struct file".
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
-				    struct file *filp)
+int tomoyo_check_rewrite_permission(struct file *filp)
 {
 	int error = -ENOMEM;
+	struct tomoyo_domain_info *domain = tomoyo_domain();
 	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
 	const bool is_enforce = (mode == 3);
 	struct tomoyo_path_info *buf;
+	int idx;
 
 	if (!mode || !filp->f_path.mnt)
 		return 0;
+
+	idx = tomoyo_read_lock();
 	buf = tomoyo_get_path(&filp->f_path);
 	if (!buf)
 		goto out;
@@ -1237,38 +1203,38 @@
 		error = 0;
 		goto out;
 	}
-	error = tomoyo_check_single_path_permission2(domain,
-						     TOMOYO_TYPE_REWRITE_ACL,
-						     buf, mode);
+	error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, buf, mode);
  out:
-	tomoyo_free(buf);
+	kfree(buf);
+	tomoyo_read_unlock(idx);
 	if (!is_enforce)
 		error = 0;
 	return error;
 }
 
 /**
- * tomoyo_check_2path_perm - Check permission for "rename" and "link".
+ * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
  *
- * @domain:    Pointer to "struct tomoyo_domain_info".
  * @operation: Type of operation.
  * @path1:      Pointer to "struct path".
  * @path2:      Pointer to "struct path".
  *
  * Returns 0 on success, negative value otherwise.
  */
-int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
-			    const u8 operation, struct path *path1,
-			    struct path *path2)
+int tomoyo_path2_perm(const u8 operation, struct path *path1,
+		      struct path *path2)
 {
 	int error = -ENOMEM;
 	struct tomoyo_path_info *buf1, *buf2;
+	struct tomoyo_domain_info *domain = tomoyo_domain();
 	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
 	const bool is_enforce = (mode == 3);
 	const char *msg;
+	int idx;
 
 	if (!mode || !path1->mnt || !path2->mnt)
 		return 0;
+	idx = tomoyo_read_lock();
 	buf1 = tomoyo_get_path(path1);
 	buf2 = tomoyo_get_path(path2);
 	if (!buf1 || !buf2)
@@ -1289,8 +1255,8 @@
 			}
 		}
 	}
-	error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2);
-	msg = tomoyo_dp2keyword(operation);
+	error = tomoyo_path2_acl(domain, operation, buf1, buf2);
+	msg = tomoyo_path22keyword(operation);
 	if (!error)
 		goto out;
 	if (tomoyo_verbose_mode(domain))
@@ -1301,12 +1267,13 @@
 	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
 		const char *name1 = tomoyo_get_file_pattern(buf1)->name;
 		const char *name2 = tomoyo_get_file_pattern(buf2)->name;
-		tomoyo_update_double_path_acl(operation, name1, name2, domain,
-					      false);
+		tomoyo_update_path2_acl(operation, name1, name2, domain,
+					false);
 	}
  out:
-	tomoyo_free(buf1);
-	tomoyo_free(buf2);
+	kfree(buf1);
+	kfree(buf2);
+	tomoyo_read_unlock(idx);
 	if (!is_enforce)
 		error = 0;
 	return error;
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
new file mode 100644
index 0000000..9645525
--- /dev/null
+++ b/security/tomoyo/gc.c
@@ -0,0 +1,370 @@
+/*
+ * security/tomoyo/gc.c
+ *
+ * Implementation of the Domain-Based Mandatory Access Control.
+ *
+ * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ *
+ */
+
+#include "common.h"
+#include <linux/kthread.h>
+
+enum tomoyo_gc_id {
+	TOMOYO_ID_DOMAIN_INITIALIZER,
+	TOMOYO_ID_DOMAIN_KEEPER,
+	TOMOYO_ID_ALIAS,
+	TOMOYO_ID_GLOBALLY_READABLE,
+	TOMOYO_ID_PATTERN,
+	TOMOYO_ID_NO_REWRITE,
+	TOMOYO_ID_MANAGER,
+	TOMOYO_ID_NAME,
+	TOMOYO_ID_ACL,
+	TOMOYO_ID_DOMAIN
+};
+
+struct tomoyo_gc_entry {
+	struct list_head list;
+	int type;
+	void *element;
+};
+static LIST_HEAD(tomoyo_gc_queue);
+static DEFINE_MUTEX(tomoyo_gc_mutex);
+
+/* Caller holds tomoyo_policy_lock mutex. */
+static bool tomoyo_add_to_gc(const int type, void *element)
+{
+	struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+	if (!entry)
+		return false;
+	entry->type = type;
+	entry->element = element;
+	list_add(&entry->list, &tomoyo_gc_queue);
+	return true;
+}
+
+static void tomoyo_del_allow_read
+(struct tomoyo_globally_readable_file_entry *ptr)
+{
+	tomoyo_put_name(ptr->filename);
+}
+
+static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr)
+{
+	tomoyo_put_name(ptr->pattern);
+}
+
+static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr)
+{
+	tomoyo_put_name(ptr->pattern);
+}
+
+static void tomoyo_del_domain_initializer
+(struct tomoyo_domain_initializer_entry *ptr)
+{
+	tomoyo_put_name(ptr->domainname);
+	tomoyo_put_name(ptr->program);
+}
+
+static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr)
+{
+	tomoyo_put_name(ptr->domainname);
+	tomoyo_put_name(ptr->program);
+}
+
+static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr)
+{
+	tomoyo_put_name(ptr->original_name);
+	tomoyo_put_name(ptr->aliased_name);
+}
+
+static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr)
+{
+	tomoyo_put_name(ptr->manager);
+}
+
+static void tomoyo_del_acl(struct tomoyo_acl_info *acl)
+{
+	switch (acl->type) {
+	case TOMOYO_TYPE_PATH_ACL:
+		{
+			struct tomoyo_path_acl *entry
+				= container_of(acl, typeof(*entry), head);
+			tomoyo_put_name(entry->filename);
+		}
+		break;
+	case TOMOYO_TYPE_PATH2_ACL:
+		{
+			struct tomoyo_path2_acl *entry
+				= container_of(acl, typeof(*entry), head);
+			tomoyo_put_name(entry->filename1);
+			tomoyo_put_name(entry->filename2);
+		}
+		break;
+	default:
+		printk(KERN_WARNING "Unknown type\n");
+		break;
+	}
+}
+
+static bool tomoyo_del_domain(struct tomoyo_domain_info *domain)
+{
+	struct tomoyo_acl_info *acl;
+	struct tomoyo_acl_info *tmp;
+	/*
+	 * Since we don't protect whole execve() operation using SRCU,
+	 * we need to recheck domain->users at this point.
+	 *
+	 * (1) Reader starts SRCU section upon execve().
+	 * (2) Reader traverses tomoyo_domain_list and finds this domain.
+	 * (3) Writer marks this domain as deleted.
+	 * (4) Garbage collector removes this domain from tomoyo_domain_list
+	 *     because this domain is marked as deleted and used by nobody.
+	 * (5) Reader saves reference to this domain into
+	 *     "struct linux_binprm"->cred->security .
+	 * (6) Reader finishes SRCU section, although execve() operation has
+	 *     not finished yet.
+	 * (7) Garbage collector waits for SRCU synchronization.
+	 * (8) Garbage collector kfree() this domain because this domain is
+	 *     used by nobody.
+	 * (9) Reader finishes execve() operation and restores this domain from
+	 *     "struct linux_binprm"->cred->security.
+	 *
+	 * By updating domain->users at (5), we can solve this race problem
+	 * by rechecking domain->users at (8).
+	 */
+	if (atomic_read(&domain->users))
+		return false;
+	list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
+		tomoyo_del_acl(acl);
+		tomoyo_memory_free(acl);
+	}
+	tomoyo_put_name(domain->domainname);
+	return true;
+}
+
+
+static void tomoyo_del_name(const struct tomoyo_name_entry *ptr)
+{
+}
+
+static void tomoyo_collect_entry(void)
+{
+	mutex_lock(&tomoyo_policy_lock);
+	{
+		struct tomoyo_globally_readable_file_entry *ptr;
+		list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list,
+					list) {
+			if (!ptr->is_deleted)
+				continue;
+			if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr))
+				list_del_rcu(&ptr->list);
+			else
+				break;
+		}
+	}
+	{
+		struct tomoyo_pattern_entry *ptr;
+		list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
+			if (!ptr->is_deleted)
+				continue;
+			if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr))
+				list_del_rcu(&ptr->list);
+			else
+				break;
+		}
+	}
+	{
+		struct tomoyo_no_rewrite_entry *ptr;
+		list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
+			if (!ptr->is_deleted)
+				continue;
+			if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr))
+				list_del_rcu(&ptr->list);
+			else
+				break;
+		}
+	}
+	{
+		struct tomoyo_domain_initializer_entry *ptr;
+		list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list,
+					list) {
+			if (!ptr->is_deleted)
+				continue;
+			if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr))
+				list_del_rcu(&ptr->list);
+			else
+				break;
+		}
+	}
+	{
+		struct tomoyo_domain_keeper_entry *ptr;
+		list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
+			if (!ptr->is_deleted)
+				continue;
+			if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr))
+				list_del_rcu(&ptr->list);
+			else
+				break;
+		}
+	}
+	{
+		struct tomoyo_alias_entry *ptr;
+		list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
+			if (!ptr->is_deleted)
+				continue;
+			if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr))
+				list_del_rcu(&ptr->list);
+			else
+				break;
+		}
+	}
+	{
+		struct tomoyo_policy_manager_entry *ptr;
+		list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list,
+					list) {
+			if (!ptr->is_deleted)
+				continue;
+			if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr))
+				list_del_rcu(&ptr->list);
+			else
+				break;
+		}
+	}
+	{
+		struct tomoyo_domain_info *domain;
+		list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
+			struct tomoyo_acl_info *acl;
+			list_for_each_entry_rcu(acl, &domain->acl_info_list,
+						list) {
+				switch (acl->type) {
+				case TOMOYO_TYPE_PATH_ACL:
+					if (container_of(acl,
+					 struct tomoyo_path_acl,
+							 head)->perm ||
+					    container_of(acl,
+					 struct tomoyo_path_acl,
+							 head)->perm_high)
+						continue;
+					break;
+				case TOMOYO_TYPE_PATH2_ACL:
+					if (container_of(acl,
+					 struct tomoyo_path2_acl,
+							 head)->perm)
+						continue;
+					break;
+				default:
+					continue;
+				}
+				if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl))
+					list_del_rcu(&acl->list);
+				else
+					break;
+			}
+			if (!domain->is_deleted || atomic_read(&domain->users))
+				continue;
+			/*
+			 * Nobody is referring this domain. But somebody may
+			 * refer this domain after successful execve().
+			 * We recheck domain->users after SRCU synchronization.
+			 */
+			if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain))
+				list_del_rcu(&domain->list);
+			else
+				break;
+		}
+	}
+	mutex_unlock(&tomoyo_policy_lock);
+	mutex_lock(&tomoyo_name_list_lock);
+	{
+		int i;
+		for (i = 0; i < TOMOYO_MAX_HASH; i++) {
+			struct tomoyo_name_entry *ptr;
+			list_for_each_entry_rcu(ptr, &tomoyo_name_list[i],
+						list) {
+				if (atomic_read(&ptr->users))
+					continue;
+				if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr))
+					list_del_rcu(&ptr->list);
+				else {
+					i = TOMOYO_MAX_HASH;
+					break;
+				}
+			}
+		}
+	}
+	mutex_unlock(&tomoyo_name_list_lock);
+}
+
+static void tomoyo_kfree_entry(void)
+{
+	struct tomoyo_gc_entry *p;
+	struct tomoyo_gc_entry *tmp;
+
+	list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
+		switch (p->type) {
+		case TOMOYO_ID_DOMAIN_INITIALIZER:
+			tomoyo_del_domain_initializer(p->element);
+			break;
+		case TOMOYO_ID_DOMAIN_KEEPER:
+			tomoyo_del_domain_keeper(p->element);
+			break;
+		case TOMOYO_ID_ALIAS:
+			tomoyo_del_alias(p->element);
+			break;
+		case TOMOYO_ID_GLOBALLY_READABLE:
+			tomoyo_del_allow_read(p->element);
+			break;
+		case TOMOYO_ID_PATTERN:
+			tomoyo_del_file_pattern(p->element);
+			break;
+		case TOMOYO_ID_NO_REWRITE:
+			tomoyo_del_no_rewrite(p->element);
+			break;
+		case TOMOYO_ID_MANAGER:
+			tomoyo_del_manager(p->element);
+			break;
+		case TOMOYO_ID_NAME:
+			tomoyo_del_name(p->element);
+			break;
+		case TOMOYO_ID_ACL:
+			tomoyo_del_acl(p->element);
+			break;
+		case TOMOYO_ID_DOMAIN:
+			if (!tomoyo_del_domain(p->element))
+				continue;
+			break;
+		default:
+			printk(KERN_WARNING "Unknown type\n");
+			break;
+		}
+		tomoyo_memory_free(p->element);
+		list_del(&p->list);
+		kfree(p);
+	}
+}
+
+static int tomoyo_gc_thread(void *unused)
+{
+	daemonize("GC for TOMOYO");
+	if (mutex_trylock(&tomoyo_gc_mutex)) {
+		int i;
+		for (i = 0; i < 10; i++) {
+			tomoyo_collect_entry();
+			if (list_empty(&tomoyo_gc_queue))
+				break;
+			synchronize_srcu(&tomoyo_ss);
+			tomoyo_kfree_entry();
+		}
+		mutex_unlock(&tomoyo_gc_mutex);
+	}
+	do_exit(0);
+}
+
+void tomoyo_run_gc(void)
+{
+	struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL,
+						  "GC for TOMOYO");
+	if (!IS_ERR(task))
+		wake_up_process(task);
+}
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index 18369d49..cf7d61f 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -14,9 +14,8 @@
 #include <linux/mnt_namespace.h>
 #include <linux/fs_struct.h>
 #include <linux/hash.h>
-
+#include <linux/magic.h>
 #include "common.h"
-#include "realpath.h"
 
 /**
  * tomoyo_encode: Convert binary string to ascii string.
@@ -89,30 +88,15 @@
 		sp = dentry->d_op->d_dname(dentry, newname + offset,
 					   newname_len - offset);
 	} else {
-		/* Taken from d_namespace_path(). */
-		struct path root;
-		struct path ns_root = { };
-		struct path tmp;
+		struct path ns_root = {.mnt = NULL, .dentry = NULL};
 
-		read_lock(&current->fs->lock);
-		root = current->fs->root;
-		path_get(&root);
-		read_unlock(&current->fs->lock);
-		spin_lock(&vfsmount_lock);
-		if (root.mnt && root.mnt->mnt_ns)
-			ns_root.mnt = mntget(root.mnt->mnt_ns->root);
-		if (ns_root.mnt)
-			ns_root.dentry = dget(ns_root.mnt->mnt_root);
-		spin_unlock(&vfsmount_lock);
 		spin_lock(&dcache_lock);
-		tmp = ns_root;
-		sp = __d_path(path, &tmp, newname, newname_len);
+		/* go to whatever namespace root we are under */
+		sp = __d_path(path, &ns_root, newname, newname_len);
 		spin_unlock(&dcache_lock);
-		path_put(&root);
-		path_put(&ns_root);
 		/* Prepend "/proc" prefix if using internal proc vfs mount. */
-		if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
-		    (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) {
+		if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
+		    (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
 			sp -= 5;
 			if (sp >= newname)
 				memcpy(sp, "/proc", 5);
@@ -149,12 +133,12 @@
  *
  * Returns the realpath of the given @path on success, NULL otherwise.
  *
- * These functions use tomoyo_alloc(), so the caller must call tomoyo_free()
+ * These functions use kzalloc(), so the caller must call kfree()
  * if these functions didn't return NULL.
  */
 char *tomoyo_realpath_from_path(struct path *path)
 {
-	char *buf = tomoyo_alloc(sizeof(struct tomoyo_page_buffer));
+	char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_KERNEL);
 
 	BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
 		     <= TOMOYO_MAX_PATHNAME_LEN - 1);
@@ -163,7 +147,7 @@
 	if (tomoyo_realpath_from_path2(path, buf,
 				       TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
 		return buf;
-	tomoyo_free(buf);
+	kfree(buf);
 	return NULL;
 }
 
@@ -206,98 +190,47 @@
 }
 
 /* Memory allocated for non-string data. */
-static unsigned int tomoyo_allocated_memory_for_elements;
-/* Quota for holding non-string data. */
-static unsigned int tomoyo_quota_for_elements;
+static atomic_t tomoyo_policy_memory_size;
+/* Quota for holding policy. */
+static unsigned int tomoyo_quota_for_policy;
 
 /**
- * tomoyo_alloc_element - Allocate permanent memory for structures.
+ * tomoyo_memory_ok - Check memory quota.
  *
- * @size: Size in bytes.
+ * @ptr: Pointer to allocated memory.
  *
- * Returns pointer to allocated memory on success, NULL otherwise.
+ * Returns true on success, false otherwise.
  *
- * Memory has to be zeroed.
- * The RAM is chunked, so NEVER try to kfree() the returned pointer.
+ * Caller holds tomoyo_policy_lock.
+ * Memory pointed by @ptr will be zeroed on success.
  */
-void *tomoyo_alloc_element(const unsigned int size)
+bool tomoyo_memory_ok(void *ptr)
 {
-	static char *buf;
-	static DEFINE_MUTEX(lock);
-	static unsigned int buf_used_len = PATH_MAX;
-	char *ptr = NULL;
-	/*Assumes sizeof(void *) >= sizeof(long) is true. */
-	const unsigned int word_aligned_size
-		= roundup(size, max(sizeof(void *), sizeof(long)));
-	if (word_aligned_size > PATH_MAX)
-		return NULL;
-	mutex_lock(&lock);
-	if (buf_used_len + word_aligned_size > PATH_MAX) {
-		if (!tomoyo_quota_for_elements ||
-		    tomoyo_allocated_memory_for_elements
-		    + PATH_MAX <= tomoyo_quota_for_elements)
-			ptr = kzalloc(PATH_MAX, GFP_KERNEL);
-		if (!ptr) {
-			printk(KERN_WARNING "ERROR: Out of memory "
-			       "for tomoyo_alloc_element().\n");
-			if (!tomoyo_policy_loaded)
-				panic("MAC Initialization failed.\n");
-		} else {
-			buf = ptr;
-			tomoyo_allocated_memory_for_elements += PATH_MAX;
-			buf_used_len = word_aligned_size;
-			ptr = buf;
-		}
-	} else if (word_aligned_size) {
-		int i;
-		ptr = buf + buf_used_len;
-		buf_used_len += word_aligned_size;
-		for (i = 0; i < word_aligned_size; i++) {
-			if (!ptr[i])
-				continue;
-			printk(KERN_ERR "WARNING: Reserved memory was tainted! "
-			       "The system might go wrong.\n");
-			ptr[i] = '\0';
-		}
+	int allocated_len = ptr ? ksize(ptr) : 0;
+	atomic_add(allocated_len, &tomoyo_policy_memory_size);
+	if (ptr && (!tomoyo_quota_for_policy ||
+		    atomic_read(&tomoyo_policy_memory_size)
+		    <= tomoyo_quota_for_policy)) {
+		memset(ptr, 0, allocated_len);
+		return true;
 	}
-	mutex_unlock(&lock);
-	return ptr;
+	printk(KERN_WARNING "ERROR: Out of memory "
+	       "for tomoyo_alloc_element().\n");
+	if (!tomoyo_policy_loaded)
+		panic("MAC Initialization failed.\n");
+	return false;
 }
 
-/* Memory allocated for string data in bytes. */
-static unsigned int tomoyo_allocated_memory_for_savename;
-/* Quota for holding string data in bytes. */
-static unsigned int tomoyo_quota_for_savename;
-
-/*
- * TOMOYO uses this hash only when appending a string into the string
- * table. Frequency of appending strings is very low. So we don't need
- * large (e.g. 64k) hash size. 256 will be sufficient.
- */
-#define TOMOYO_HASH_BITS  8
-#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)
-
-/*
- * tomoyo_name_entry is a structure which is used for linking
- * "struct tomoyo_path_info" into tomoyo_name_list .
+/**
+ * tomoyo_memory_free - Free memory for elements.
  *
- * Since tomoyo_name_list manages a list of strings which are shared by
- * multiple processes (whereas "struct tomoyo_path_info" inside
- * "struct tomoyo_path_info_with_data" is not shared), a reference counter will
- * be added to "struct tomoyo_name_entry" rather than "struct tomoyo_path_info"
- * when TOMOYO starts supporting garbage collector.
+ * @ptr:  Pointer to allocated memory.
  */
-struct tomoyo_name_entry {
-	struct list_head list;
-	struct tomoyo_path_info entry;
-};
-
-/* Structure for available memory region. */
-struct tomoyo_free_memory_block_list {
-	struct list_head list;
-	char *ptr;             /* Pointer to a free area. */
-	int len;               /* Length of the area.     */
-};
+void tomoyo_memory_free(void *ptr)
+{
+	atomic_sub(ksize(ptr), &tomoyo_policy_memory_size);
+	kfree(ptr);
+}
 
 /*
  * tomoyo_name_list is used for holding string data used by TOMOYO.
@@ -305,87 +238,58 @@
  * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
  * "const struct tomoyo_path_info *".
  */
-static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
+struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
+/* Lock for protecting tomoyo_name_list . */
+DEFINE_MUTEX(tomoyo_name_list_lock);
 
 /**
- * tomoyo_save_name - Allocate permanent memory for string data.
+ * tomoyo_get_name - Allocate permanent memory for string data.
  *
  * @name: The string to store into the permernent memory.
  *
  * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
- *
- * The RAM is shared, so NEVER try to modify or kfree() the returned name.
  */
-const struct tomoyo_path_info *tomoyo_save_name(const char *name)
+const struct tomoyo_path_info *tomoyo_get_name(const char *name)
 {
-	static LIST_HEAD(fmb_list);
-	static DEFINE_MUTEX(lock);
 	struct tomoyo_name_entry *ptr;
 	unsigned int hash;
-	/* fmb contains available size in bytes.
-	   fmb is removed from the fmb_list when fmb->len becomes 0. */
-	struct tomoyo_free_memory_block_list *fmb;
 	int len;
-	char *cp;
+	int allocated_len;
 	struct list_head *head;
 
 	if (!name)
 		return NULL;
 	len = strlen(name) + 1;
-	if (len > TOMOYO_MAX_PATHNAME_LEN) {
-		printk(KERN_WARNING "ERROR: Name too long "
-		       "for tomoyo_save_name().\n");
-		return NULL;
-	}
 	hash = full_name_hash((const unsigned char *) name, len - 1);
 	head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
-
-	mutex_lock(&lock);
+	mutex_lock(&tomoyo_name_list_lock);
 	list_for_each_entry(ptr, head, list) {
-		if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
-			goto out;
+		if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
+			continue;
+		atomic_inc(&ptr->users);
+		goto out;
 	}
-	list_for_each_entry(fmb, &fmb_list, list) {
-		if (len <= fmb->len)
-			goto ready;
-	}
-	if (!tomoyo_quota_for_savename ||
-	    tomoyo_allocated_memory_for_savename + PATH_MAX
-	    <= tomoyo_quota_for_savename)
-		cp = kzalloc(PATH_MAX, GFP_KERNEL);
-	else
-		cp = NULL;
-	fmb = kzalloc(sizeof(*fmb), GFP_KERNEL);
-	if (!cp || !fmb) {
-		kfree(cp);
-		kfree(fmb);
+	ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL);
+	allocated_len = ptr ? ksize(ptr) : 0;
+	if (!ptr || (tomoyo_quota_for_policy &&
+		     atomic_read(&tomoyo_policy_memory_size) + allocated_len
+		     > tomoyo_quota_for_policy)) {
+		kfree(ptr);
 		printk(KERN_WARNING "ERROR: Out of memory "
-		       "for tomoyo_save_name().\n");
+		       "for tomoyo_get_name().\n");
 		if (!tomoyo_policy_loaded)
 			panic("MAC Initialization failed.\n");
 		ptr = NULL;
 		goto out;
 	}
-	tomoyo_allocated_memory_for_savename += PATH_MAX;
-	list_add(&fmb->list, &fmb_list);
-	fmb->ptr = cp;
-	fmb->len = PATH_MAX;
- ready:
-	ptr = tomoyo_alloc_element(sizeof(*ptr));
-	if (!ptr)
-		goto out;
-	ptr->entry.name = fmb->ptr;
-	memmove(fmb->ptr, name, len);
+	atomic_add(allocated_len, &tomoyo_policy_memory_size);
+	ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
+	memmove((char *) ptr->entry.name, name, len);
+	atomic_set(&ptr->users, 1);
 	tomoyo_fill_path_info(&ptr->entry);
-	fmb->ptr += len;
-	fmb->len -= len;
 	list_add_tail(&ptr->list, head);
-	if (fmb->len == 0) {
-		list_del(&fmb->list);
-		kfree(fmb);
-	}
  out:
-	mutex_unlock(&lock);
+	mutex_unlock(&tomoyo_name_list_lock);
 	return ptr ? &ptr->entry : NULL;
 }
 
@@ -400,45 +304,14 @@
 	for (i = 0; i < TOMOYO_MAX_HASH; i++)
 		INIT_LIST_HEAD(&tomoyo_name_list[i]);
 	INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
-	tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME);
-	list_add_tail(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
-	down_read(&tomoyo_domain_list_lock);
+	tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME);
+	/*
+	 * tomoyo_read_lock() is not needed because this function is
+	 * called before the first "delete" request.
+	 */
+	list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
 	if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
 		panic("Can't register tomoyo_kernel_domain");
-	up_read(&tomoyo_domain_list_lock);
-}
-
-/* Memory allocated for temporary purpose. */
-static atomic_t tomoyo_dynamic_memory_size;
-
-/**
- * tomoyo_alloc - Allocate memory for temporary purpose.
- *
- * @size: Size in bytes.
- *
- * Returns pointer to allocated memory on success, NULL otherwise.
- */
-void *tomoyo_alloc(const size_t size)
-{
-	void *p = kzalloc(size, GFP_KERNEL);
-	if (p)
-		atomic_add(ksize(p), &tomoyo_dynamic_memory_size);
-	return p;
-}
-
-/**
- * tomoyo_free - Release memory allocated by tomoyo_alloc().
- *
- * @p: Pointer returned by tomoyo_alloc(). May be NULL.
- *
- * Returns nothing.
- */
-void tomoyo_free(const void *p)
-{
-	if (p) {
-		atomic_sub(ksize(p), &tomoyo_dynamic_memory_size);
-		kfree(p);
-	}
 }
 
 /**
@@ -451,32 +324,19 @@
 int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
 {
 	if (!head->read_eof) {
-		const unsigned int shared
-			= tomoyo_allocated_memory_for_savename;
-		const unsigned int private
-			= tomoyo_allocated_memory_for_elements;
-		const unsigned int dynamic
-			= atomic_read(&tomoyo_dynamic_memory_size);
+		const unsigned int policy
+			= atomic_read(&tomoyo_policy_memory_size);
 		char buffer[64];
 
 		memset(buffer, 0, sizeof(buffer));
-		if (tomoyo_quota_for_savename)
+		if (tomoyo_quota_for_policy)
 			snprintf(buffer, sizeof(buffer) - 1,
 				 "   (Quota: %10u)",
-				 tomoyo_quota_for_savename);
+				 tomoyo_quota_for_policy);
 		else
 			buffer[0] = '\0';
-		tomoyo_io_printf(head, "Shared:  %10u%s\n", shared, buffer);
-		if (tomoyo_quota_for_elements)
-			snprintf(buffer, sizeof(buffer) - 1,
-				 "   (Quota: %10u)",
-				 tomoyo_quota_for_elements);
-		else
-			buffer[0] = '\0';
-		tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer);
-		tomoyo_io_printf(head, "Dynamic: %10u\n", dynamic);
-		tomoyo_io_printf(head, "Total:   %10u\n",
-				 shared + private + dynamic);
+		tomoyo_io_printf(head, "Policy:  %10u%s\n", policy, buffer);
+		tomoyo_io_printf(head, "Total:   %10u\n", policy);
 		head->read_eof = true;
 	}
 	return 0;
@@ -494,9 +354,7 @@
 	char *data = head->write_buf;
 	unsigned int size;
 
-	if (sscanf(data, "Shared: %u", &size) == 1)
-		tomoyo_quota_for_savename = size;
-	else if (sscanf(data, "Private: %u", &size) == 1)
-		tomoyo_quota_for_elements = size;
+	if (sscanf(data, "Policy: %u", &size) == 1)
+		tomoyo_quota_for_policy = size;
 	return 0;
 }
diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h
deleted file mode 100644
index 78217a3..0000000
--- a/security/tomoyo/realpath.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * security/tomoyo/realpath.h
- *
- * Get the canonicalized absolute pathnames. The basis for TOMOYO.
- *
- * Copyright (C) 2005-2009  NTT DATA CORPORATION
- *
- * Version: 2.2.0   2009/04/01
- *
- */
-
-#ifndef _SECURITY_TOMOYO_REALPATH_H
-#define _SECURITY_TOMOYO_REALPATH_H
-
-struct path;
-struct tomoyo_path_info;
-struct tomoyo_io_buffer;
-
-/* Convert binary string to ascii string. */
-int tomoyo_encode(char *buffer, int buflen, const char *str);
-
-/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
-int tomoyo_realpath_from_path2(struct path *path, char *newname,
-			       int newname_len);
-
-/*
- * Returns realpath(3) of the given pathname but ignores chroot'ed root.
- * These functions use tomoyo_alloc(), so the caller must call tomoyo_free()
- * if these functions didn't return NULL.
- */
-char *tomoyo_realpath(const char *pathname);
-/*
- * Same with tomoyo_realpath() except that it doesn't follow the final symlink.
- */
-char *tomoyo_realpath_nofollow(const char *pathname);
-/* Same with tomoyo_realpath() except that the pathname is already solved. */
-char *tomoyo_realpath_from_path(struct path *path);
-
-/*
- * Allocate memory for ACL entry.
- * The RAM is chunked, so NEVER try to kfree() the returned pointer.
- */
-void *tomoyo_alloc_element(const unsigned int size);
-
-/*
- * Keep the given name on the RAM.
- * The RAM is shared, so NEVER try to modify or kfree() the returned name.
- */
-const struct tomoyo_path_info *tomoyo_save_name(const char *name);
-
-/* Allocate memory for temporary use (e.g. permission checks). */
-void *tomoyo_alloc(const size_t size);
-
-/* Free memory allocated by tomoyo_alloc(). */
-void tomoyo_free(const void *p);
-
-/* Check for memory usage. */
-int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head);
-
-/* Set memory quota. */
-int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
-
-/* Initialize realpath related code. */
-void __init tomoyo_realpath_init(void);
-
-#endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 2aceebf..dedd97d 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -11,8 +11,6 @@
 
 #include <linux/security.h>
 #include "common.h"
-#include "tomoyo.h"
-#include "realpath.h"
 
 static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp)
 {
@@ -23,21 +21,23 @@
 static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
 			       gfp_t gfp)
 {
-	/*
-	 * Since "struct tomoyo_domain_info *" is a sharable pointer,
-	 * we don't need to duplicate.
-	 */
-	new->security = old->security;
+	struct tomoyo_domain_info *domain = old->security;
+	new->security = domain;
+	if (domain)
+		atomic_inc(&domain->users);
 	return 0;
 }
 
 static void tomoyo_cred_transfer(struct cred *new, const struct cred *old)
 {
-	/*
-	 * Since "struct tomoyo_domain_info *" is a sharable pointer,
-	 * we don't need to duplicate.
-	 */
-	new->security = old->security;
+	tomoyo_cred_prepare(new, old, 0);
+}
+
+static void tomoyo_cred_free(struct cred *cred)
+{
+	struct tomoyo_domain_info *domain = cred->security;
+	if (domain)
+		atomic_dec(&domain->users);
 }
 
 static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
@@ -61,6 +61,14 @@
 	if (!tomoyo_policy_loaded)
 		tomoyo_load_policy(bprm->filename);
 	/*
+	 * Release reference to "struct tomoyo_domain_info" stored inside
+	 * "bprm->cred->security". New reference to "struct tomoyo_domain_info"
+	 * stored inside "bprm->cred->security" will be acquired later inside
+	 * tomoyo_find_next_domain().
+	 */
+	atomic_dec(&((struct tomoyo_domain_info *)
+		     bprm->cred->security)->users);
+	/*
 	 * Tell tomoyo_bprm_check_security() is called for the first time of an
 	 * execve operation.
 	 */
@@ -76,8 +84,12 @@
 	 * Execute permission is checked against pathname passed to do_execve()
 	 * using current domain.
 	 */
-	if (!domain)
-		return tomoyo_find_next_domain(bprm);
+	if (!domain) {
+		const int idx = tomoyo_read_lock();
+		const int err = tomoyo_find_next_domain(bprm);
+		tomoyo_read_unlock(idx);
+		return err;
+	}
 	/*
 	 * Read permission is checked against interpreters using next domain.
 	 */
@@ -87,67 +99,56 @@
 static int tomoyo_path_truncate(struct path *path, loff_t length,
 				unsigned int time_attrs)
 {
-	return tomoyo_check_1path_perm(tomoyo_domain(),
-				       TOMOYO_TYPE_TRUNCATE_ACL,
-				       path);
+	return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path);
 }
 
 static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
 {
 	struct path path = { parent->mnt, dentry };
-	return tomoyo_check_1path_perm(tomoyo_domain(),
-				       TOMOYO_TYPE_UNLINK_ACL,
-				       &path);
+	return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path);
 }
 
 static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
 			     int mode)
 {
 	struct path path = { parent->mnt, dentry };
-	return tomoyo_check_1path_perm(tomoyo_domain(),
-				       TOMOYO_TYPE_MKDIR_ACL,
-				       &path);
+	return tomoyo_path_perm(TOMOYO_TYPE_MKDIR, &path);
 }
 
 static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
 {
 	struct path path = { parent->mnt, dentry };
-	return tomoyo_check_1path_perm(tomoyo_domain(),
-				       TOMOYO_TYPE_RMDIR_ACL,
-				       &path);
+	return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path);
 }
 
 static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
 			       const char *old_name)
 {
 	struct path path = { parent->mnt, dentry };
-	return tomoyo_check_1path_perm(tomoyo_domain(),
-				       TOMOYO_TYPE_SYMLINK_ACL,
-				       &path);
+	return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path);
 }
 
 static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
 			     int mode, unsigned int dev)
 {
 	struct path path = { parent->mnt, dentry };
-	int type = TOMOYO_TYPE_CREATE_ACL;
+	int type = TOMOYO_TYPE_CREATE;
 
 	switch (mode & S_IFMT) {
 	case S_IFCHR:
-		type = TOMOYO_TYPE_MKCHAR_ACL;
+		type = TOMOYO_TYPE_MKCHAR;
 		break;
 	case S_IFBLK:
-		type = TOMOYO_TYPE_MKBLOCK_ACL;
+		type = TOMOYO_TYPE_MKBLOCK;
 		break;
 	case S_IFIFO:
-		type = TOMOYO_TYPE_MKFIFO_ACL;
+		type = TOMOYO_TYPE_MKFIFO;
 		break;
 	case S_IFSOCK:
-		type = TOMOYO_TYPE_MKSOCK_ACL;
+		type = TOMOYO_TYPE_MKSOCK;
 		break;
 	}
-	return tomoyo_check_1path_perm(tomoyo_domain(),
-				       type, &path);
+	return tomoyo_path_perm(type, &path);
 }
 
 static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,
@@ -155,9 +156,7 @@
 {
 	struct path path1 = { new_dir->mnt, old_dentry };
 	struct path path2 = { new_dir->mnt, new_dentry };
-	return tomoyo_check_2path_perm(tomoyo_domain(),
-				       TOMOYO_TYPE_LINK_ACL,
-				       &path1, &path2);
+	return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2);
 }
 
 static int tomoyo_path_rename(struct path *old_parent,
@@ -167,16 +166,14 @@
 {
 	struct path path1 = { old_parent->mnt, old_dentry };
 	struct path path2 = { new_parent->mnt, new_dentry };
-	return tomoyo_check_2path_perm(tomoyo_domain(),
-				       TOMOYO_TYPE_RENAME_ACL,
-				       &path1, &path2);
+	return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2);
 }
 
 static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
 			     unsigned long arg)
 {
 	if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))
-		return tomoyo_check_rewrite_permission(tomoyo_domain(), file);
+		return tomoyo_check_rewrite_permission(file);
 	return 0;
 }
 
@@ -189,6 +186,51 @@
 	return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags);
 }
 
+static int tomoyo_file_ioctl(struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	return tomoyo_path_perm(TOMOYO_TYPE_IOCTL, &file->f_path);
+}
+
+static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+			     mode_t mode)
+{
+	struct path path = { mnt, dentry };
+	return tomoyo_path_perm(TOMOYO_TYPE_CHMOD, &path);
+}
+
+static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid)
+{
+	int error = 0;
+	if (uid != (uid_t) -1)
+		error = tomoyo_path_perm(TOMOYO_TYPE_CHOWN, path);
+	if (!error && gid != (gid_t) -1)
+		error = tomoyo_path_perm(TOMOYO_TYPE_CHGRP, path);
+	return error;
+}
+
+static int tomoyo_path_chroot(struct path *path)
+{
+	return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path);
+}
+
+static int tomoyo_sb_mount(char *dev_name, struct path *path,
+			   char *type, unsigned long flags, void *data)
+{
+	return tomoyo_path_perm(TOMOYO_TYPE_MOUNT, path);
+}
+
+static int tomoyo_sb_umount(struct vfsmount *mnt, int flags)
+{
+	struct path path = { mnt, mnt->mnt_root };
+	return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path);
+}
+
+static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path)
+{
+	return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path);
+}
+
 /*
  * tomoyo_security_ops is a "struct security_operations" which is used for
  * registering TOMOYO.
@@ -198,6 +240,7 @@
 	.cred_alloc_blank    = tomoyo_cred_alloc_blank,
 	.cred_prepare        = tomoyo_cred_prepare,
 	.cred_transfer	     = tomoyo_cred_transfer,
+	.cred_free           = tomoyo_cred_free,
 	.bprm_set_creds      = tomoyo_bprm_set_creds,
 	.bprm_check_security = tomoyo_bprm_check_security,
 	.file_fcntl          = tomoyo_file_fcntl,
@@ -210,8 +253,18 @@
 	.path_mknod          = tomoyo_path_mknod,
 	.path_link           = tomoyo_path_link,
 	.path_rename         = tomoyo_path_rename,
+	.file_ioctl          = tomoyo_file_ioctl,
+	.path_chmod          = tomoyo_path_chmod,
+	.path_chown          = tomoyo_path_chown,
+	.path_chroot         = tomoyo_path_chroot,
+	.sb_mount            = tomoyo_sb_mount,
+	.sb_umount           = tomoyo_sb_umount,
+	.sb_pivotroot        = tomoyo_sb_pivotroot,
 };
 
+/* Lock for GC. */
+struct srcu_struct tomoyo_ss;
+
 static int __init tomoyo_init(void)
 {
 	struct cred *cred = (struct cred *) current_cred();
@@ -219,7 +272,8 @@
 	if (!security_module_enable(&tomoyo_security_ops))
 		return 0;
 	/* register ourselves with the security framework */
-	if (register_security(&tomoyo_security_ops))
+	if (register_security(&tomoyo_security_ops) ||
+	    init_srcu_struct(&tomoyo_ss))
 		panic("Failure registering TOMOYO Linux");
 	printk(KERN_INFO "TOMOYO Linux initialized\n");
 	cred->security = &tomoyo_kernel_domain;
diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h
deleted file mode 100644
index ed75832..0000000
--- a/security/tomoyo/tomoyo.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * security/tomoyo/tomoyo.h
- *
- * Implementation of the Domain-Based Mandatory Access Control.
- *
- * Copyright (C) 2005-2009  NTT DATA CORPORATION
- *
- * Version: 2.2.0   2009/04/01
- *
- */
-
-#ifndef _SECURITY_TOMOYO_TOMOYO_H
-#define _SECURITY_TOMOYO_TOMOYO_H
-
-struct tomoyo_path_info;
-struct path;
-struct inode;
-struct linux_binprm;
-struct pt_regs;
-
-int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
-			   const struct tomoyo_path_info *filename);
-int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
-				 struct path *path, const int flag);
-int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
-			    const u8 operation, struct path *path);
-int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain,
-			    const u8 operation, struct path *path1,
-			    struct path *path2);
-int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
-				    struct file *filp);
-int tomoyo_find_next_domain(struct linux_binprm *bprm);
-
-/* Index numbers for Access Controls. */
-
-#define TOMOYO_TYPE_SINGLE_PATH_ACL                 0
-#define TOMOYO_TYPE_DOUBLE_PATH_ACL                 1
-
-/* Index numbers for File Controls. */
-
-/*
- * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set
- * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and
- * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set.
- * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or
- * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are
- * automatically cleared if TYPE_READ_WRITE_ACL is cleared.
- */
-
-#define TOMOYO_TYPE_READ_WRITE_ACL    0
-#define TOMOYO_TYPE_EXECUTE_ACL       1
-#define TOMOYO_TYPE_READ_ACL          2
-#define TOMOYO_TYPE_WRITE_ACL         3
-#define TOMOYO_TYPE_CREATE_ACL        4
-#define TOMOYO_TYPE_UNLINK_ACL        5
-#define TOMOYO_TYPE_MKDIR_ACL         6
-#define TOMOYO_TYPE_RMDIR_ACL         7
-#define TOMOYO_TYPE_MKFIFO_ACL        8
-#define TOMOYO_TYPE_MKSOCK_ACL        9
-#define TOMOYO_TYPE_MKBLOCK_ACL      10
-#define TOMOYO_TYPE_MKCHAR_ACL       11
-#define TOMOYO_TYPE_TRUNCATE_ACL     12
-#define TOMOYO_TYPE_SYMLINK_ACL      13
-#define TOMOYO_TYPE_REWRITE_ACL      14
-#define TOMOYO_MAX_SINGLE_PATH_OPERATION 15
-
-#define TOMOYO_TYPE_LINK_ACL         0
-#define TOMOYO_TYPE_RENAME_ACL       1
-#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 2
-
-#define TOMOYO_DOMAINPOLICY          0
-#define TOMOYO_EXCEPTIONPOLICY       1
-#define TOMOYO_DOMAIN_STATUS         2
-#define TOMOYO_PROCESS_STATUS        3
-#define TOMOYO_MEMINFO               4
-#define TOMOYO_SELFDOMAIN            5
-#define TOMOYO_VERSION               6
-#define TOMOYO_PROFILE               7
-#define TOMOYO_MANAGER               8
-
-extern struct tomoyo_domain_info tomoyo_kernel_domain;
-
-static inline struct tomoyo_domain_info *tomoyo_domain(void)
-{
-	return current_cred()->security;
-}
-
-static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
-							    *task)
-{
-	return task_cred_xxx(task, security);
-}
-
-#endif /* !defined(_SECURITY_TOMOYO_TOMOYO_H) */
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 6fdca97..88eec38 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -22,7 +22,6 @@
 
 #include <asm/irq.h>
 #include <mach/regs-ac97.h>
-#include <mach/pxa2xx-gpio.h>
 #include <mach/audio.h>
 
 static DEFINE_MUTEX(car_mutex);
@@ -32,6 +31,8 @@
 static struct clk *ac97conf_clk;
 static int reset_gpio;
 
+extern void pxa27x_assert_ac97reset(int reset_gpio, int on);
+
 /*
  * Beware PXA27x bugs:
  *
@@ -42,45 +43,6 @@
  * 1 jiffy timeout if interrupt never comes).
  */
 
-enum {
-	RESETGPIO_FORCE_HIGH,
-	RESETGPIO_FORCE_LOW,
-	RESETGPIO_NORMAL_ALTFUNC
-};
-
-/**
- * set_resetgpio_mode - computes and sets the AC97_RESET gpio mode on PXA
- * @mode: chosen action
- *
- * As the PXA27x CPUs suffer from a AC97 bug, a manual control of the reset line
- * must be done to insure proper work of AC97 reset line.  This function
- * computes the correct gpio_mode for further use by reset functions, and
- * applied the change through pxa_gpio_mode.
- */
-static void set_resetgpio_mode(int resetgpio_action)
-{
-	int mode = 0;
-
-	if (reset_gpio)
-		switch (resetgpio_action) {
-		case RESETGPIO_NORMAL_ALTFUNC:
-			if (reset_gpio == 113)
-				mode = 113 | GPIO_ALT_FN_2_OUT;
-			if (reset_gpio == 95)
-				mode = 95 | GPIO_ALT_FN_1_OUT;
-			break;
-		case RESETGPIO_FORCE_LOW:
-			mode = reset_gpio | GPIO_OUT | GPIO_DFLT_LOW;
-			break;
-		case RESETGPIO_FORCE_HIGH:
-			mode = reset_gpio | GPIO_OUT | GPIO_DFLT_HIGH;
-			break;
-		};
-
-	if (mode)
-		pxa_gpio_mode(mode);
-}
-
 unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
 	unsigned short val = -1;
@@ -174,12 +136,11 @@
 {
 	gsr_bits = 0;
 
-	/* warm reset broken on Bulverde,
-	   so manually keep AC97 reset high */
-	set_resetgpio_mode(RESETGPIO_FORCE_HIGH);
+	/* warm reset broken on Bulverde, so manually keep AC97 reset high */
+	pxa27x_assert_ac97reset(reset_gpio, 1);
 	udelay(10);
 	GCR |= GCR_WARM_RST;
-	set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
+	pxa27x_assert_ac97reset(reset_gpio, 0);
 	udelay(500);
 }
 
@@ -345,16 +306,6 @@
 
 int pxa2xx_ac97_hw_resume(void)
 {
-	if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
-		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
-		pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
-		pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
-		pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
-	}
-	if (cpu_is_pxa27x()) {
-		/* Use GPIO 113 or 95 as AC97 Reset on Bulverde */
-		set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
-	}
 	clk_enable(ac97_clk);
 	return 0;
 }
@@ -386,16 +337,9 @@
 			reset_gpio = 113;
 	}
 
-	if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
-		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
-		pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
-		pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
-		pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
-	}
-
 	if (cpu_is_pxa27x()) {
 		/* Use GPIO 113 as AC97 Reset on Bulverde */
-		set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
+		pxa27x_assert_ac97reset(reset_gpio, 0);
 		ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
 		if (IS_ERR(ac97conf_clk)) {
 			ret = PTR_ERR(ac97conf_clk);
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 8f8b17a..7394365 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -393,7 +393,7 @@
 	    event == SNDRV_TIMER_EVENT_CONTINUE)
 		resolution = snd_timer_resolution(ti);
 	if (ti->ccallback)
-		ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution);
+		ti->ccallback(ti, event, &tstamp, resolution);
 	if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)
 		return;
 	timer = ti->timer;
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index b865e45..5913717 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -1558,7 +1558,7 @@
 
 	err = pnp_activate_dev(devmc);
 	if (err < 0) {
-		snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n",
+		snd_printk(KERN_ERR "MC pnp configure failure: %d\n",
 				    err);
 		return err;
 	}
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index a4af53b..4d2d040 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -144,12 +144,8 @@
 
 	spinlock_t lock;
 
+	long wss_base;
 	int irq;
-
-#ifdef CONFIG_PNP
-	struct pnp_dev *dev;
-	struct pnp_dev *devmpu;
-#endif	/* CONFIG_PNP */
 };
 
 static int snd_opti9xx_pnp_is_probed;
@@ -159,12 +155,17 @@
 static struct pnp_card_device_id snd_opti9xx_pnpids[] = {
 #ifndef OPTi93X
 	/* OPTi 82C924 */
-	{ .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 },
+	{ .id = "OPT0924",
+	  .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } },
+	  .driver_data = 0x0924 },
 	/* OPTi 82C925 */
-	{ .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 },
+	{ .id = "OPT0925",
+	  .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } },
+	  .driver_data = 0x0925 },
 #else
 	/* OPTi 82C931/3 */
-	{ .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 },
+	{ .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } },
+	  .driver_data = 0x0931 },
 #endif	/* OPTi93X */
 	{ .id = "" }
 };
@@ -207,24 +208,35 @@
 	chip->hardware = hardware;
 	strcpy(chip->name, snd_opti9xx_names[hardware]);
 
-	chip->mc_base_size = opti9xx_mc_size[hardware];  
-
 	spin_lock_init(&chip->lock);
 
 	chip->irq = -1;
 
+#ifndef OPTi93X
+#ifdef CONFIG_PNP
+	if (isapnp && chip->mc_base)
+		/* PnP resource gives the least 10 bits */
+		chip->mc_base |= 0xc00;
+	else
+#endif	/* CONFIG_PNP */
+	{
+		chip->mc_base = 0xf8c;
+		chip->mc_base_size = opti9xx_mc_size[hardware];
+	}
+#else
+		chip->mc_base_size = opti9xx_mc_size[hardware];
+#endif
+
 	switch (hardware) {
 #ifndef OPTi93X
 	case OPTi9XX_HW_82C928:
 	case OPTi9XX_HW_82C929:
-		chip->mc_base = 0xf8c;
 		chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3;
 		chip->pwd_reg = 3;
 		break;
 
 	case OPTi9XX_HW_82C924:
 	case OPTi9XX_HW_82C925:
-		chip->mc_base = 0xf8c;
 		chip->password = 0xe5;
 		chip->pwd_reg = 3;
 		break;
@@ -292,7 +304,7 @@
 	spin_unlock_irqrestore(&chip->lock, flags);
 	return retval;
 }
-	
+
 static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
 			      unsigned char value)
 {
@@ -341,7 +353,7 @@
 
 
 static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
-					   long wss_base,
+					   long port,
 					   int irq, int dma1, int dma2,
 					   long mpu_port, int mpu_irq)
 {
@@ -354,16 +366,23 @@
 	switch (chip->hardware) {
 #ifndef OPTi93X
 	case OPTi9XX_HW_82C924:
+		/* opti 929 mode (?), OPL3 clock output, audio enable */
 		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc);
+		/* enable wave audio */
 		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
 
 	case OPTi9XX_HW_82C925:
+		/* enable WSS mode */
 		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
+		/* OPL3 FM synthesis */
 		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
+		/* disable Sound Blaster IRQ and DMA */
 		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
 #ifdef CS4231
+		/* cs4231/4248 fix enabled */
 		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
 #else
+		/* cs4231/4248 fix disabled */
 		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
 #endif	/* CS4231 */
 		break;
@@ -411,21 +430,26 @@
 		return -EINVAL;
 	}
 
-	switch (wss_base) {
-	case 0x530:
+	/* PnP resource says it decodes only 10 bits of address */
+	switch (port & 0x3ff) {
+	case 0x130:
+		chip->wss_base = 0x530;
 		wss_base_bits = 0x00;
 		break;
-	case 0x604:
+	case 0x204:
+		chip->wss_base = 0x604;
 		wss_base_bits = 0x03;
 		break;
-	case 0xe80:
+	case 0x280:
+		chip->wss_base = 0xe80;
 		wss_base_bits = 0x01;
 		break;
-	case 0xf40:
+	case 0x340:
+		chip->wss_base = 0xf40;
 		wss_base_bits = 0x02;
 		break;
 	default:
-		snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base);
+		snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port);
 		goto __skip_base;
 	}
 	snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
@@ -487,7 +511,7 @@
 #endif	/* CS4231 || OPTi93X */
 
 #ifndef OPTi93X
-	 outb(irq_bits << 3 | dma_bits, wss_base);
+	 outb(irq_bits << 3 | dma_bits, chip->wss_base);
 #else /* OPTi93X */
 	snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
 #endif /* OPTi93X */
@@ -729,15 +753,15 @@
 {
 	struct pnp_dev *pdev;
 	int err;
+	struct pnp_dev *devmpu;
+#ifndef OPTi93X
+	struct pnp_dev *devmc;
+#endif
 
-	chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL);
-	if (chip->dev == NULL)
+	pdev = pnp_request_card_device(card, pid->devs[0].id, NULL);
+	if (pdev == NULL)
 		return -EBUSY;
 
-	chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
-
-	pdev = chip->dev;
-
 	err = pnp_activate_dev(pdev);
 	if (err < 0) {
 		snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);
@@ -750,9 +774,24 @@
 	chip->mc_indir_index = pnp_port_start(pdev, 3) + 2;
 	chip->mc_indir_size = pnp_port_len(pdev, 3) - 2;
 #else
-	if (pid->driver_data != 0x0924)
-		port = pnp_port_start(pdev, 1);
+	devmc = pnp_request_card_device(card, pid->devs[2].id, NULL);
+	if (devmc == NULL)
+		return -EBUSY;
+
+	err = pnp_activate_dev(devmc);
+	if (err < 0) {
+		snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err);
+		return err;
+	}
+
+	port = pnp_port_start(pdev, 1);
 	fm_port = pnp_port_start(pdev, 2) + 8;
+	/*
+	 * The MC(0) is never accessed and card does not
+	 * include it in the PnP resource range. OPTI93x include it.
+	 */
+	chip->mc_base = pnp_port_start(devmc, 0) - 1;
+	chip->mc_base_size = pnp_port_len(devmc, 0) + 1;
 #endif	/* OPTi93X */
 	irq = pnp_irq(pdev, 0);
 	dma1 = pnp_dma(pdev, 0);
@@ -760,16 +799,16 @@
 	dma2 = pnp_dma(pdev, 1);
 #endif	/* CS4231 || OPTi93X */
 
-	pdev = chip->devmpu;
-	if (pdev && mpu_port > 0) {
-		err = pnp_activate_dev(pdev);
+	devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
+
+	if (devmpu && mpu_port > 0) {
+		err = pnp_activate_dev(devmpu);
 		if (err < 0) {
-			snd_printk(KERN_ERR "AUDIO pnp configure failure\n");
+			snd_printk(KERN_ERR "MPU401 pnp configure failure\n");
 			mpu_port = -1;
-			chip->devmpu = NULL;
 		} else {
-			mpu_port = pnp_port_start(pdev, 0);
-			mpu_irq = pnp_irq(pdev, 0);
+			mpu_port = pnp_port_start(devmpu, 0);
+			mpu_irq = pnp_irq(devmpu, 0);
 		}
 	}
 	return pid->driver_data;
@@ -824,7 +863,7 @@
 	if (error)
 		return error;
 
-	error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2,
+	error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2,
 #ifdef OPTi93X
 			       WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
 #else
@@ -865,10 +904,11 @@
 	sprintf(card->shortname, "OPTi %s", card->driver);
 #if defined(CS4231) || defined(OPTi93X)
 	sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d",
-		card->shortname, pcm->name, port + 4, irq, dma1, xdma2);
+		card->shortname, pcm->name,
+		chip->wss_base + 4, irq, dma1, xdma2);
 #else
 	sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d",
-		card->shortname, pcm->name, port + 4, irq, dma1);
+		card->shortname, pcm->name, chip->wss_base + 4, irq, dma1);
 #endif	/* CS4231 || OPTi93X */
 
 	if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
@@ -1062,9 +1102,6 @@
 		snd_card_free(card);
 		return error;
 	}
-	if (hw <= OPTi9XX_HW_82C930)
-		chip->mc_base -= 0x80;
-
 	error = snd_opti9xx_read_check(chip);
 	if (error) {
 		snd_printk(KERN_ERR "OPTI chip not found\n");
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index 8d21a3f..8ccbcdd 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/delay.h>
 #include <asm/dma.h>
 #include <linux/isa.h>
 #include <sound/core.h>
diff --git a/sound/oss/coproc.h b/sound/oss/coproc.h
index 7306346..7bec21b 100644
--- a/sound/oss/coproc.h
+++ b/sound/oss/coproc.h
@@ -4,7 +4,7 @@
  */
 
 /*
- * Coprocessor access types 
+ * Coprocessor access types
  */
 #define COPR_CUSTOM		0x0001	/* Custom applications */
 #define COPR_MIDI		0x0002	/* MIDI (MPU-401) emulation */
diff --git a/sound/oss/v_midi.h b/sound/oss/v_midi.h
index 1b86cb4..08e2185 100644
--- a/sound/oss/v_midi.h
+++ b/sound/oss/v_midi.h
@@ -2,9 +2,9 @@
 	   int dev;
 
 	/* State variables */
- 	   int opened;
+	   int opened;
 	   spinlock_t lock;
-	
+
 	/* MIDI fields */
 	   int my_mididev;
 	   int pair_mididev;
@@ -12,4 +12,3 @@
 	   int intr_active;
 	   void (*midi_input_intr) (int dev, unsigned char data);
 	} vmidi_devc;
-
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 556cff9..567348b 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -157,7 +157,7 @@
 
 config SND_HDA_ELD
 	def_bool y
-	depends on SND_HDA_CODEC_INTELHDMI
+	depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
 
 config SND_HDA_CODEC_CIRRUS
 	bool "Build Cirrus Logic codec support"
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 315a1c4..24bc195 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -3,7 +3,7 @@
 snd-hda-codec-y := hda_codec.o
 snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
 snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
-# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
+snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
 snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
 snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
 
@@ -18,7 +18,7 @@
 snd-hda-codec-conexant-objs :=	patch_conexant.o
 snd-hda-codec-via-objs :=	patch_via.o
 snd-hda-codec-nvhdmi-objs :=	patch_nvhdmi.o
-snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o hda_eld.o
+snd-hda-codec-intelhdmi-objs :=	patch_intelhdmi.o
 
 # common driver
 obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 76d3c4c..5bd7cf4 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -978,8 +978,9 @@
  *
  * Returns 0 if successful, or a negative error code.
  */
-int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
-				    struct hda_codec **codecp)
+int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
+				unsigned int codec_addr,
+				struct hda_codec **codecp)
 {
 	struct hda_codec *codec;
 	char component[31];
@@ -1186,7 +1187,7 @@
  */
 
 /* FIXME: more better hash key? */
-#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
+#define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
 #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24))
 #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24))
 #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24))
@@ -1356,7 +1357,8 @@
 	if (!codec->no_trigger_sense) {
 		pincap = snd_hda_query_pin_caps(codec, nid);
 		if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
-			snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
+			snd_hda_codec_read(codec, nid, 0,
+					AC_VERB_SET_PIN_SENSE, 0);
 	}
 	return snd_hda_codec_read(codec, nid, 0,
 				  AC_VERB_GET_PIN_SENSE, 0);
@@ -1372,8 +1374,8 @@
  */
 int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
 {
-        u32 sense = snd_hda_pin_sense(codec, nid);
-        return !!(sense & AC_PINSENSE_PRESENCE);
+	u32 sense = snd_hda_pin_sense(codec, nid);
+	return !!(sense & AC_PINSENSE_PRESENCE);
 }
 EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
 
@@ -1952,7 +1954,7 @@
 	err = snd_hda_ctl_add(codec, 0, kctl);
 	if (err < 0)
 		return err;
-	
+
 	for (s = slaves; *s; s++) {
 		struct snd_kcontrol *sctl;
 		int i = 0;
@@ -2439,27 +2441,27 @@
 	{
 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
 		.info = snd_hda_spdif_mask_info,
 		.get = snd_hda_spdif_cmask_get,
 	},
 	{
 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
+		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK),
 		.info = snd_hda_spdif_mask_info,
 		.get = snd_hda_spdif_pmask_get,
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
 		.info = snd_hda_spdif_mask_info,
 		.get = snd_hda_spdif_default_get,
 		.put = snd_hda_spdif_default_put,
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
+		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
 		.info = snd_hda_spdif_out_switch_info,
 		.get = snd_hda_spdif_out_switch_get,
 		.put = snd_hda_spdif_out_switch_put,
@@ -2610,7 +2612,7 @@
 static struct snd_kcontrol_new dig_in_ctls[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
+		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
 		.info = snd_hda_spdif_in_switch_info,
 		.get = snd_hda_spdif_in_switch_get,
 		.put = snd_hda_spdif_in_switch_put,
@@ -2618,7 +2620,7 @@
 	{
 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
+		.name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
 		.info = snd_hda_spdif_mask_info,
 		.get = snd_hda_spdif_in_status_get,
 	},
@@ -2883,7 +2885,7 @@
 		int err = snd_hda_codec_build_controls(codec);
 		if (err < 0) {
 			printk(KERN_ERR "hda_codec: cannot build controls"
-			       "for #%d (error %d)\n", codec->addr, err); 
+			       "for #%d (error %d)\n", codec->addr, err);
 			err = snd_hda_codec_reset(codec);
 			if (err < 0) {
 				printk(KERN_ERR
@@ -2979,8 +2981,12 @@
 	val |= channels - 1;
 
 	switch (snd_pcm_format_width(format)) {
-	case 8:  val |= 0x00; break;
-	case 16: val |= 0x10; break;
+	case 8:
+		val |= 0x00;
+		break;
+	case 16:
+		val |= 0x10;
+		break;
 	case 20:
 	case 24:
 	case 32:
@@ -3298,7 +3304,8 @@
 		if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
 			return audio_idx[type][i];
 
-	snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
+	snd_printk(KERN_WARNING "Too many %s devices\n",
+		snd_hda_pcm_type_name[type]);
 	return -EAGAIN;
 }
 
@@ -3336,7 +3343,7 @@
 		err = codec->patch_ops.build_pcms(codec);
 		if (err < 0) {
 			printk(KERN_ERR "hda_codec: cannot build PCMs"
-			       "for #%d (error %d)\n", codec->addr, err); 
+			       "for #%d (error %d)\n", codec->addr, err);
 			err = snd_hda_codec_reset(codec);
 			if (err < 0) {
 				printk(KERN_ERR
@@ -3466,8 +3473,8 @@
 
 /**
  * snd_hda_check_board_codec_sid_config - compare the current codec
-				          subsystem ID with the
-					  config table
+					subsystem ID with the
+					config table
 
 	   This is important for Gateway notebooks with SB450 HDA Audio
 	   where the vendor ID of the PCI device is:
@@ -3607,7 +3614,7 @@
  *
  * Increment the power-up counter and power up the hardware really when
  * not turned on yet.
- */ 
+ */
 void snd_hda_power_up(struct hda_codec *codec)
 {
 	struct hda_bus *bus = codec->bus;
@@ -3636,7 +3643,7 @@
  *
  * Decrement the power-up counter and schedules the power-off work if
  * the counter rearches to zero.
- */ 
+ */
 void snd_hda_power_down(struct hda_codec *codec)
 {
 	--codec->power_count;
@@ -3662,7 +3669,7 @@
  *
  * This function is supposed to be set or called from the check_power_status
  * patch ops.
- */ 
+ */
 int snd_hda_check_amp_list_power(struct hda_codec *codec,
 				 struct hda_loopback_check *check,
 				 hda_nid_t nid)
@@ -3830,7 +3837,7 @@
 {
 	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
 	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
-		set_dig_out_convert(codec, nid, 
+		set_dig_out_convert(codec, nid,
 				    codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
 				    -1);
 	snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
@@ -4089,13 +4096,13 @@
 /*
  * Sort an associated group of pins according to their sequence numbers.
  */
-static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
+static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
 				  int num_pins)
 {
 	int i, j;
 	short seq;
 	hda_nid_t nid;
-	
+
 	for (i = 0; i < num_pins; i++) {
 		for (j = i + 1; j < num_pins; j++) {
 			if (sequences[i] > sequences[j]) {
@@ -4123,7 +4130,7 @@
  * is detected, one of speaker of HP pins is assigned as the primary
  * output, i.e. to line_out_pins[0].  So, line_outs is always positive
  * if any analog output exists.
- * 
+ *
  * The analog input pins are assigned to input_pins array.
  * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
  * respectively.
@@ -4186,9 +4193,9 @@
 		case AC_JACK_SPEAKER:
 			seq = get_defcfg_sequence(def_conf);
 			assoc = get_defcfg_association(def_conf);
-			if (! assoc)
+			if (!assoc)
 				continue;
-			if (! assoc_speaker)
+			if (!assoc_speaker)
 				assoc_speaker = assoc;
 			else if (assoc_speaker != assoc)
 				continue;
@@ -4286,7 +4293,7 @@
 			      cfg->speaker_outs);
 	sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
 			      cfg->hp_outs);
-	
+
 	/* if we have only one mic, make it AUTO_PIN_MIC */
 	if (!cfg->input_pins[AUTO_PIN_MIC] &&
 	    cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
@@ -4436,7 +4443,7 @@
 /**
  * snd_array_new - get a new element from the given array
  * @array: the array object
- * 
+ *
  * Get a new element from the given array.  If it exceeds the
  * pre-allocated array size, re-allocate the array.
  *
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 4228f2f..dcd2244 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -331,6 +331,7 @@
 	return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
 						 AC_DIPSIZE_ELD_BUF);
 }
+EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size);
 
 int snd_hdmi_get_eld(struct hdmi_eld *eld,
 		     struct hda_codec *codec, hda_nid_t nid)
@@ -366,6 +367,7 @@
 	kfree(buf);
 	return ret;
 }
+EXPORT_SYMBOL_HDA(snd_hdmi_get_eld);
 
 static void hdmi_show_short_audio_desc(struct cea_sad *a)
 {
@@ -404,6 +406,7 @@
 	}
 	buf[j] = '\0';	/* necessary when j == 0 */
 }
+EXPORT_SYMBOL_HDA(snd_print_channel_allocation);
 
 void snd_hdmi_show_eld(struct hdmi_eld *e)
 {
@@ -422,6 +425,7 @@
 	for (i = 0; i < e->sad_count; i++)
 		hdmi_show_short_audio_desc(e->sad + i);
 }
+EXPORT_SYMBOL_HDA(snd_hdmi_show_eld);
 
 #ifdef CONFIG_PROC_FS
 
@@ -580,6 +584,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new);
 
 void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
 {
@@ -588,5 +593,6 @@
 		eld->proc_entry = NULL;
 	}
 }
+EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free);
 
 #endif /* CONFIG_PROC_FS */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d5c93ad..da1ac90 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -267,7 +267,8 @@
 #define RIRB_INT_MASK		0x05
 
 /* STATESTS int mask: S3,SD2,SD1,SD0 */
-#define AZX_MAX_CODECS		4
+#define AZX_MAX_CODECS		8
+#define AZX_DEFAULT_CODECS	4
 #define STATESTS_INT_MASK	((1 << AZX_MAX_CODECS) - 1)
 
 /* SD_CTL bits */
@@ -1367,6 +1368,7 @@
 
 /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
 static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
+	[AZX_DRIVER_NVIDIA] = 8,
 	[AZX_DRIVER_TERA] = 1,
 };
 
@@ -1399,7 +1401,7 @@
 	codecs = 0;
 	max_slots = azx_max_codecs[chip->driver_type];
 	if (!max_slots)
-		max_slots = AZX_MAX_CODECS;
+		max_slots = AZX_DEFAULT_CODECS;
 
 	/* First try to probe all given codec slots */
 	for (c = 0; c < max_slots; c++) {
@@ -2263,10 +2265,12 @@
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
 	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(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
 	SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
+	SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
 	{}
 };
 
@@ -2354,6 +2358,8 @@
 static struct snd_pci_quirk msi_black_list[] __devinitdata = {
 	SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
 	SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
+	SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
+	SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */
 	{}
 };
 
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
new file mode 100644
index 0000000..2c2bafb
--- /dev/null
+++ b/sound/pci/hda/patch_hdmi.c
@@ -0,0 +1,849 @@
+/*
+ *
+ *  patch_hdmi.c - routines for HDMI/DisplayPort codecs
+ *
+ *  Copyright(c) 2008-2010 Intel Corporation. All rights reserved.
+ *
+ *  Authors:
+ *			Wu Fengguang <wfg@linux.intel.com>
+ *
+ *  Maintained by:
+ *			Wu Fengguang <wfg@linux.intel.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software Foundation,
+ *  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+
+struct hdmi_spec {
+	int num_cvts;
+	int num_pins;
+	hda_nid_t cvt[MAX_HDMI_CVTS+1];  /* audio sources */
+	hda_nid_t pin[MAX_HDMI_PINS+1];  /* audio sinks */
+
+	/*
+	 * source connection for each pin
+	 */
+	hda_nid_t pin_cvt[MAX_HDMI_PINS+1];
+
+	/*
+	 * HDMI sink attached to each pin
+	 */
+	struct hdmi_eld sink_eld[MAX_HDMI_PINS];
+
+	/*
+	 * export one pcm per pipe
+	 */
+	struct hda_pcm	pcm_rec[MAX_HDMI_CVTS];
+
+	/*
+	 * nvhdmi specific
+	 */
+	struct hda_multi_out multiout;
+	unsigned int codec_type;
+};
+
+
+struct hdmi_audio_infoframe {
+	u8 type; /* 0x84 */
+	u8 ver;  /* 0x01 */
+	u8 len;  /* 0x0a */
+
+	u8 checksum;	/* PB0 */
+	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
+	u8 SS01_SF24;
+	u8 CXT04;
+	u8 CA;
+	u8 LFEPBL01_LSV36_DM_INH7;
+	u8 reserved[5];	/* PB6 - PB10 */
+};
+
+/*
+ * CEA speaker placement:
+ *
+ *        FLH       FCH        FRH
+ *  FLW    FL  FLC   FC   FRC   FR   FRW
+ *
+ *                                  LFE
+ *                     TC
+ *
+ *          RL  RLC   RC   RRC   RR
+ *
+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+	FL  = (1 <<  0),	/* Front Left           */
+	FC  = (1 <<  1),	/* Front Center         */
+	FR  = (1 <<  2),	/* Front Right          */
+	FLC = (1 <<  3),	/* Front Left Center    */
+	FRC = (1 <<  4),	/* Front Right Center   */
+	RL  = (1 <<  5),	/* Rear Left            */
+	RC  = (1 <<  6),	/* Rear Center          */
+	RR  = (1 <<  7),	/* Rear Right           */
+	RLC = (1 <<  8),	/* Rear Left Center     */
+	RRC = (1 <<  9),	/* Rear Right Center    */
+	LFE = (1 << 10),	/* Low Frequency Effect */
+	FLW = (1 << 11),	/* Front Left Wide      */
+	FRW = (1 << 12),	/* Front Right Wide     */
+	FLH = (1 << 13),	/* Front Left High      */
+	FCH = (1 << 14),	/* Front Center High    */
+	FRH = (1 << 15),	/* Front Right High     */
+	TC  = (1 << 16),	/* Top Center           */
+};
+
+/*
+ * ELD SA bits in the CEA Speaker Allocation data block
+ */
+static int eld_speaker_allocation_bits[] = {
+	[0] = FL | FR,
+	[1] = LFE,
+	[2] = FC,
+	[3] = RL | RR,
+	[4] = RC,
+	[5] = FLC | FRC,
+	[6] = RLC | RRC,
+	/* the following are not defined in ELD yet */
+	[7] = FLW | FRW,
+	[8] = FLH | FRH,
+	[9] = TC,
+	[10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+	int ca_index;
+	int speakers[8];
+
+	/* derived values, just for convenience */
+	int channels;
+	int spk_mask;
+};
+
+/*
+ * ALSA sequence is:
+ *
+ *       surround40   surround41   surround50   surround51   surround71
+ * ch0   front left   =            =            =            =
+ * ch1   front right  =            =            =            =
+ * ch2   rear left    =            =            =            =
+ * ch3   rear right   =            =            =            =
+ * ch4                LFE          center       center       center
+ * ch5                                          LFE          LFE
+ * ch6                                                       side left
+ * ch7                                                       side right
+ *
+ * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
+ */
+static int hdmi_channel_mapping[0x32][8] = {
+	/* stereo */
+	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* 2.1 */
+	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* Dolby Surround */
+	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
+	/* surround40 */
+	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
+	/* 4ch */
+	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
+	/* surround41 */
+	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround50 */
+	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
+	/* surround51 */
+	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
+	/* 7.1 */
+	[0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_setup_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+/*			  channel:   7     6    5    4    3     2    1    0  */
+{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
+				 /* 2.1 */
+{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
+				 /* Dolby Surround */
+{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
+				 /* surround40 */
+{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
+				 /* surround41 */
+{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
+				 /* surround50 */
+{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+				 /* surround51 */
+{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* 6.1 */
+{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+				 /* surround71 */
+{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+
+{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
+{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
+{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
+{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
+{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
+{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
+{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
+};
+
+
+/*
+ * HDMI routines
+ */
+
+static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
+{
+	int i;
+
+	for (i = 0; nids[i]; i++)
+		if (nids[i] == nid)
+			return i;
+
+	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
+	return -EINVAL;
+}
+
+static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
+			      struct hdmi_eld *eld)
+{
+	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+		snd_hdmi_show_eld(eld);
+}
+
+#ifdef BE_PARANOID
+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int *packet_index, int *byte_index)
+{
+	int val;
+
+	val = snd_hda_codec_read(codec, pin_nid, 0,
+				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
+
+	*packet_index = val >> 5;
+	*byte_index = val & 0x1f;
+}
+#endif
+
+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+				int packet_index, int byte_index)
+{
+	int val;
+
+	val = (packet_index << 5) | (byte_index & 0x1f);
+
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
+				unsigned char val)
+{
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
+}
+
+static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	/* Unmute */
+	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
+		snd_hda_codec_write(codec, pin_nid, 0,
+				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	/* Enable pin out */
+	snd_hda_codec_write(codec, pin_nid, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+}
+
+static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
+{
+	return 1 + snd_hda_codec_read(codec, nid, 0,
+					AC_VERB_GET_CVT_CHAN_COUNT, 0);
+}
+
+static void hdmi_set_channel_count(struct hda_codec *codec,
+				   hda_nid_t nid, int chs)
+{
+	if (chs != hdmi_get_channel_count(codec, nid))
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
+}
+
+
+/*
+ * Channel mapping routines
+ */
+
+/*
+ * Compute derived values in channel_allocations[].
+ */
+static void init_channel_allocations(void)
+{
+	int i, j;
+	struct cea_channel_speaker_allocation *p;
+
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		p = channel_allocations + i;
+		p->channels = 0;
+		p->spk_mask = 0;
+		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+			if (p->speakers[j]) {
+				p->channels++;
+				p->spk_mask |= p->speakers[j];
+			}
+	}
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ *	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
+ *	      spk_mask => (channel_allocations[])         => ai->CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
+					 struct hdmi_audio_infoframe *ai)
+{
+	struct hdmi_spec *spec = codec->spec;
+	struct hdmi_eld *eld;
+	int i;
+	int spk_mask = 0;
+	int channels = 1 + (ai->CC02_CT47 & 0x7);
+	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+
+	/*
+	 * CA defaults to 0 for basic stereo audio
+	 */
+	if (channels <= 2)
+		return 0;
+
+	i = hda_node_index(spec->pin_cvt, nid);
+	if (i < 0)
+		return 0;
+	eld = &spec->sink_eld[i];
+
+	/*
+	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+	 * in console or for audio devices. Assume the highest speakers
+	 * configuration, to _not_ prohibit multi-channel audio playback.
+	 */
+	if (!eld->spk_alloc)
+		eld->spk_alloc = 0xffff;
+
+	/*
+	 * expand ELD's speaker allocation mask
+	 *
+	 * ELD tells the speaker mask in a compact(paired) form,
+	 * expand ELD's notions to match the ones used by Audio InfoFrame.
+	 */
+	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
+		if (eld->spk_alloc & (1 << i))
+			spk_mask |= eld_speaker_allocation_bits[i];
+	}
+
+	/* search for the first working match in the CA table */
+	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+		if (channels == channel_allocations[i].channels &&
+		    (spk_mask & channel_allocations[i].spk_mask) ==
+				channel_allocations[i].spk_mask) {
+			ai->CA = channel_allocations[i].ca_index;
+			break;
+		}
+	}
+
+	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+	snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+		    ai->CA, channels, buf);
+
+	return ai->CA;
+}
+
+static void hdmi_debug_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int slot;
+
+	for (i = 0; i < 8; i++) {
+		slot = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_CHAN_SLOT, i);
+		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
+						slot >> 4, slot & 0xf);
+	}
+#endif
+}
+
+
+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
+				       hda_nid_t pin_nid,
+				       struct hdmi_audio_infoframe *ai)
+{
+	int i;
+	int ca = ai->CA;
+	int err;
+
+	if (hdmi_channel_mapping[ca][1] == 0) {
+		for (i = 0; i < channel_allocations[ca].channels; i++)
+			hdmi_channel_mapping[ca][i] = i | (i << 4);
+		for (; i < 8; i++)
+			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+	}
+
+	for (i = 0; i < 8; i++) {
+		err = snd_hda_codec_write(codec, pin_nid, 0,
+					  AC_VERB_SET_HDMI_CHAN_SLOT,
+					  hdmi_channel_mapping[ca][i]);
+		if (err) {
+			snd_printdd(KERN_NOTICE
+				    "HDMI: channel mapping failed\n");
+			break;
+		}
+	}
+
+	hdmi_debug_channel_mapping(codec, pin_nid);
+}
+
+
+/*
+ * Audio InfoFrame routines
+ */
+
+/*
+ * Enable Audio InfoFrame Transmission
+ */
+static void hdmi_start_infoframe_trans(struct hda_codec *codec,
+				       hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_BEST);
+}
+
+/*
+ * Disable Audio InfoFrame Transmission
+ */
+static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
+				      hda_nid_t pin_nid)
+{
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+						AC_DIPXMIT_DISABLE);
+}
+
+static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+	int i;
+	int size;
+
+	size = snd_hdmi_get_eld_size(codec, pin_nid);
+	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
+
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
+	}
+#endif
+}
+
+static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef BE_PARANOID
+	int i, j;
+	int size;
+	int pi, bi;
+	for (i = 0; i < 8; i++) {
+		size = snd_hda_codec_read(codec, pin_nid, 0,
+						AC_VERB_GET_HDMI_DIP_SIZE, i);
+		if (size == 0)
+			continue;
+
+		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
+		for (j = 1; j < 1000; j++) {
+			hdmi_write_dip_byte(codec, pin_nid, 0x0);
+			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
+			if (pi != i)
+				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
+						bi, pi, i);
+			if (bi == 0) /* byte index wrapped around */
+				break;
+		}
+		snd_printd(KERN_INFO
+			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
+			i, size, j);
+	}
+#endif
+}
+
+static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	u8 sum = 0;
+	int i;
+
+	ai->checksum = 0;
+
+	for (i = 0; i < sizeof(*ai); i++)
+		sum += bytes[i];
+
+	ai->checksum = -sum;
+}
+
+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
+				      hda_nid_t pin_nid,
+				      struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	int i;
+
+	hdmi_debug_dip_size(codec, pin_nid);
+	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
+
+	hdmi_checksum_audio_infoframe(ai);
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++)
+		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
+}
+
+static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
+				    struct hdmi_audio_infoframe *ai)
+{
+	u8 *bytes = (u8 *)ai;
+	u8 val;
+	int i;
+
+	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
+							    != AC_DIPXMIT_BEST)
+		return false;
+
+	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+	for (i = 0; i < sizeof(*ai); i++) {
+		val = snd_hda_codec_read(codec, pin_nid, 0,
+					 AC_VERB_GET_HDMI_DIP_DATA, 0);
+		if (val != bytes[i])
+			return false;
+	}
+
+	return true;
+}
+
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
+					struct snd_pcm_substream *substream)
+{
+	struct hdmi_spec *spec = codec->spec;
+	hda_nid_t pin_nid;
+	int i;
+	struct hdmi_audio_infoframe ai = {
+		.type		= 0x84,
+		.ver		= 0x01,
+		.len		= 0x0a,
+		.CC02_CT47	= substream->runtime->channels - 1,
+	};
+
+	hdmi_setup_channel_allocation(codec, nid, &ai);
+
+	for (i = 0; i < spec->num_pins; i++) {
+		if (spec->pin_cvt[i] != nid)
+			continue;
+		if (!spec->sink_eld[i].monitor_present)
+			continue;
+
+		pin_nid = spec->pin[i];
+		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
+			snd_printdd("hdmi_setup_audio_infoframe: "
+				    "cvt=%d pin=%d channels=%d\n",
+				    nid, pin_nid,
+				    substream->runtime->channels);
+			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
+			hdmi_stop_infoframe_trans(codec, pin_nid);
+			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
+			hdmi_start_infoframe_trans(codec, pin_nid);
+		}
+	}
+}
+
+
+/*
+ * Unsolicited events
+ */
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	struct hdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int pind = !!(res & AC_UNSOL_RES_PD);
+	int eldv = !!(res & AC_UNSOL_RES_ELDV);
+	int index;
+
+	printk(KERN_INFO
+		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+		tag, pind, eldv);
+
+	index = hda_node_index(spec->pin, tag);
+	if (index < 0)
+		return;
+
+	spec->sink_eld[index].monitor_present = pind;
+	spec->sink_eld[index].eld_valid = eldv;
+
+	if (pind && eldv) {
+		hdmi_get_show_eld(codec, spec->pin[index],
+				  &spec->sink_eld[index]);
+		/* TODO: do real things about ELD */
+	}
+}
+
+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
+	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
+
+	printk(KERN_INFO
+		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+		tag,
+		subtag,
+		cp_state,
+		cp_ready);
+
+	/* TODO */
+	if (cp_state)
+		;
+	if (cp_ready)
+		;
+}
+
+
+static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	struct hdmi_spec *spec = codec->spec;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+
+	if (hda_node_index(spec->pin, tag) < 0) {
+		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
+		return;
+	}
+
+	if (subtag == 0)
+		hdmi_intrinsic_event(codec, res);
+	else
+		hdmi_non_intrinsic_event(codec, res);
+}
+
+/*
+ * Callbacks
+ */
+
+static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+			      u32 stream_tag, int format)
+{
+	int tag;
+	int fmt;
+
+	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
+	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
+
+	snd_printdd("hdmi_setup_stream: "
+		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
+		    nid,
+		    tag == stream_tag ? "" : "new-",
+		    stream_tag,
+		    fmt == format ? "" : "new-",
+		    format);
+
+	if (tag != stream_tag)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CHANNEL_STREAMID,
+				    stream_tag << 4);
+	if (fmt != format)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_STREAM_FORMAT, format);
+}
+
+/*
+ * HDA/HDMI auto parsing
+ */
+
+static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct hdmi_spec *spec = codec->spec;
+	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
+	int conn_len, curr;
+	int index;
+
+	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
+		snd_printk(KERN_WARNING
+			   "HDMI: pin %d wcaps %#x "
+			   "does not support connection list\n",
+			   pin_nid, get_wcaps(codec, pin_nid));
+		return -EINVAL;
+	}
+
+	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
+					   HDA_MAX_CONNECTIONS);
+	if (conn_len > 1)
+		curr = snd_hda_codec_read(codec, pin_nid, 0,
+					  AC_VERB_GET_CONNECT_SEL, 0);
+	else
+		curr = 0;
+
+	index = hda_node_index(spec->pin, pin_nid);
+	if (index < 0)
+		return -EINVAL;
+
+	spec->pin_cvt[index] = conn_list[curr];
+
+	return 0;
+}
+
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+			       struct hdmi_eld *eld)
+{
+	int present = snd_hda_pin_sense(codec, pin_nid);
+
+	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
+	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
+
+	if (present & AC_PINSENSE_ELDV)
+		hdmi_get_show_eld(codec, pin_nid, eld);
+}
+
+static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+	struct hdmi_spec *spec = codec->spec;
+
+	if (spec->num_pins >= MAX_HDMI_PINS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for pin %d\n", pin_nid);
+		return -EINVAL;
+	}
+
+	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
+
+	spec->pin[spec->num_pins] = pin_nid;
+	spec->num_pins++;
+
+	/*
+	 * It is assumed that converter nodes come first in the node list and
+	 * hence have been registered and usable now.
+	 */
+	return hdmi_read_pin_conn(codec, pin_nid);
+}
+
+static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct hdmi_spec *spec = codec->spec;
+
+	if (spec->num_cvts >= MAX_HDMI_CVTS) {
+		snd_printk(KERN_WARNING
+			   "HDMI: no space for converter %d\n", nid);
+		return -EINVAL;
+	}
+
+	spec->cvt[spec->num_cvts] = nid;
+	spec->num_cvts++;
+
+	return 0;
+}
+
+static int hdmi_parse_codec(struct hda_codec *codec)
+{
+	hda_nid_t nid;
+	int i, nodes;
+
+	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+	if (!nid || nodes < 0) {
+		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < nodes; i++, nid++) {
+		unsigned int caps;
+		unsigned int type;
+
+		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+		type = get_wcaps_type(caps);
+
+		if (!(caps & AC_WCAP_DIGITAL))
+			continue;
+
+		switch (type) {
+		case AC_WID_AUD_OUT:
+			if (hdmi_add_cvt(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		case AC_WID_PIN:
+			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
+				continue;
+			if (hdmi_add_pin(codec, nid) < 0)
+				return -EINVAL;
+			break;
+		}
+	}
+
+	/*
+	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
+	 * can be lost and presence sense verb will become inaccurate if the
+	 * HDA link is powered off at hot plug or hw initialization time.
+	 */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+	      AC_PWRST_EPSS))
+		codec->bus->power_keep_link_on = 1;
+#endif
+
+	return 0;
+}
+
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
index 918f403..88d0351 100644
--- a/sound/pci/hda/patch_intelhdmi.c
+++ b/sound/pci/hda/patch_intelhdmi.c
@@ -40,814 +40,19 @@
  *
  * The HDA correspondence of pipes/ports are converter/pin nodes.
  */
-#define INTEL_HDMI_CVTS	2
-#define INTEL_HDMI_PINS	3
+#define MAX_HDMI_CVTS	2
+#define MAX_HDMI_PINS	3
 
-static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = {
+#include "patch_hdmi.c"
+
+static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
 	"INTEL HDMI 0",
 	"INTEL HDMI 1",
 };
 
-struct intel_hdmi_spec {
-	int num_cvts;
-	int num_pins;
-	hda_nid_t cvt[INTEL_HDMI_CVTS+1];  /* audio sources */
-	hda_nid_t pin[INTEL_HDMI_PINS+1];  /* audio sinks */
-
-	/*
-	 * source connection for each pin
-	 */
-	hda_nid_t pin_cvt[INTEL_HDMI_PINS+1];
-
-	/*
-	 * HDMI sink attached to each pin
-	 */
-	struct hdmi_eld sink_eld[INTEL_HDMI_PINS];
-
-	/*
-	 * export one pcm per pipe
-	 */
-	struct hda_pcm	pcm_rec[INTEL_HDMI_CVTS];
-};
-
-struct hdmi_audio_infoframe {
-	u8 type; /* 0x84 */
-	u8 ver;  /* 0x01 */
-	u8 len;  /* 0x0a */
-
-	u8 checksum;	/* PB0 */
-	u8 CC02_CT47;	/* CC in bits 0:2, CT in 4:7 */
-	u8 SS01_SF24;
-	u8 CXT04;
-	u8 CA;
-	u8 LFEPBL01_LSV36_DM_INH7;
-	u8 reserved[5];	/* PB6 - PB10 */
-};
-
 /*
- * CEA speaker placement:
- *
- *        FLH       FCH        FRH
- *  FLW    FL  FLC   FC   FRC   FR   FRW
- *
- *                                  LFE
- *                     TC
- *
- *          RL  RLC   RC   RRC   RR
- *
- * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
- * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ * HDMI callbacks
  */
-enum cea_speaker_placement {
-	FL  = (1 <<  0),	/* Front Left           */
-	FC  = (1 <<  1),	/* Front Center         */
-	FR  = (1 <<  2),	/* Front Right          */
-	FLC = (1 <<  3),	/* Front Left Center    */
-	FRC = (1 <<  4),	/* Front Right Center   */
-	RL  = (1 <<  5),	/* Rear Left            */
-	RC  = (1 <<  6),	/* Rear Center          */
-	RR  = (1 <<  7),	/* Rear Right           */
-	RLC = (1 <<  8),	/* Rear Left Center     */
-	RRC = (1 <<  9),	/* Rear Right Center    */
-	LFE = (1 << 10),	/* Low Frequency Effect */
-	FLW = (1 << 11),	/* Front Left Wide      */
-	FRW = (1 << 12),	/* Front Right Wide     */
-	FLH = (1 << 13),	/* Front Left High      */
-	FCH = (1 << 14),	/* Front Center High    */
-	FRH = (1 << 15),	/* Front Right High     */
-	TC  = (1 << 16),	/* Top Center           */
-};
-
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static int eld_speaker_allocation_bits[] = {
-	[0] = FL | FR,
-	[1] = LFE,
-	[2] = FC,
-	[3] = RL | RR,
-	[4] = RC,
-	[5] = FLC | FRC,
-	[6] = RLC | RRC,
-	/* the following are not defined in ELD yet */
-	[7] = FLW | FRW,
-	[8] = FLH | FRH,
-	[9] = TC,
-	[10] = FCH,
-};
-
-struct cea_channel_speaker_allocation {
-	int ca_index;
-	int speakers[8];
-
-	/* derived values, just for convenience */
-	int channels;
-	int spk_mask;
-};
-
-/*
- * ALSA sequence is:
- *
- *       surround40   surround41   surround50   surround51   surround71
- * ch0   front left   =            =            =            =
- * ch1   front right  =            =            =            =
- * ch2   rear left    =            =            =            =
- * ch3   rear right   =            =            =            =
- * ch4                LFE          center       center       center
- * ch5                                          LFE          LFE
- * ch6                                                       side left
- * ch7                                                       side right
- *
- * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
- */
-static int hdmi_channel_mapping[0x32][8] = {
-	/* stereo */
-	[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* 2.1 */
-	[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* Dolby Surround */
-	[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
-	/* surround40 */
-	[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
-	/* 4ch */
-	[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
-	/* surround41 */
-	[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
-	/* surround50 */
-	[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
-	/* surround51 */
-	[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
-	/* 7.1 */
-	[0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
-};
-
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_setup_channel_allocation().
- */
-static struct cea_channel_speaker_allocation channel_allocations[] = {
-/* 			  channel:   7     6    5    4    3     2    1    0  */
-{ .ca_index = 0x00,  .speakers = {   0,    0,   0,   0,   0,    0,  FR,  FL } },
-				 /* 2.1 */
-{ .ca_index = 0x01,  .speakers = {   0,    0,   0,   0,   0,  LFE,  FR,  FL } },
-				 /* Dolby Surround */
-{ .ca_index = 0x02,  .speakers = {   0,    0,   0,   0,  FC,    0,  FR,  FL } },
-				 /* surround40 */
-{ .ca_index = 0x08,  .speakers = {   0,    0,  RR,  RL,   0,    0,  FR,  FL } },
-				 /* surround41 */
-{ .ca_index = 0x09,  .speakers = {   0,    0,  RR,  RL,   0,  LFE,  FR,  FL } },
-				 /* surround50 */
-{ .ca_index = 0x0a,  .speakers = {   0,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-				 /* surround51 */
-{ .ca_index = 0x0b,  .speakers = {   0,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				 /* 6.1 */
-{ .ca_index = 0x0f,  .speakers = {   0,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-				 /* surround71 */
-{ .ca_index = 0x13,  .speakers = { RRC,  RLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-
-{ .ca_index = 0x03,  .speakers = {   0,    0,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x04,  .speakers = {   0,    0,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x05,  .speakers = {   0,    0,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x06,  .speakers = {   0,    0,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x07,  .speakers = {   0,    0,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x0c,  .speakers = {   0,   RC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x0d,  .speakers = {   0,   RC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x0e,  .speakers = {   0,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x10,  .speakers = { RRC,  RLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x11,  .speakers = { RRC,  RLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x12,  .speakers = { RRC,  RLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x14,  .speakers = { FRC,  FLC,   0,   0,   0,    0,  FR,  FL } },
-{ .ca_index = 0x15,  .speakers = { FRC,  FLC,   0,   0,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x16,  .speakers = { FRC,  FLC,   0,   0,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x17,  .speakers = { FRC,  FLC,   0,   0,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x18,  .speakers = { FRC,  FLC,   0,  RC,   0,    0,  FR,  FL } },
-{ .ca_index = 0x19,  .speakers = { FRC,  FLC,   0,  RC,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1a,  .speakers = { FRC,  FLC,   0,  RC,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1b,  .speakers = { FRC,  FLC,   0,  RC,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x1c,  .speakers = { FRC,  FLC,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x1d,  .speakers = { FRC,  FLC,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x1e,  .speakers = { FRC,  FLC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x1f,  .speakers = { FRC,  FLC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x20,  .speakers = {   0,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x21,  .speakers = {   0,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x22,  .speakers = {  TC,    0,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x23,  .speakers = {  TC,    0,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x24,  .speakers = { FRH,  FLH,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x25,  .speakers = { FRH,  FLH,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x26,  .speakers = { FRW,  FLW,  RR,  RL,   0,    0,  FR,  FL } },
-{ .ca_index = 0x27,  .speakers = { FRW,  FLW,  RR,  RL,   0,  LFE,  FR,  FL } },
-{ .ca_index = 0x28,  .speakers = {  TC,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x29,  .speakers = {  TC,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2a,  .speakers = { FCH,   RC,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2b,  .speakers = { FCH,   RC,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2c,  .speakers = {  TC,  FCH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2d,  .speakers = {  TC,  FCH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x2e,  .speakers = { FRH,  FLH,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x2f,  .speakers = { FRH,  FLH,  RR,  RL,  FC,  LFE,  FR,  FL } },
-{ .ca_index = 0x30,  .speakers = { FRW,  FLW,  RR,  RL,  FC,    0,  FR,  FL } },
-{ .ca_index = 0x31,  .speakers = { FRW,  FLW,  RR,  RL,  FC,  LFE,  FR,  FL } },
-};
-
-/*
- * HDA/HDMI auto parsing
- */
-
-static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
-{
-	int i;
-
-	for (i = 0; nids[i]; i++)
-		if (nids[i] == nid)
-			return i;
-
-	snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
-	return -EINVAL;
-}
-
-static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
-	int conn_len, curr;
-	int index;
-
-	if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
-		snd_printk(KERN_WARNING
-			   "HDMI: pin %d wcaps %#x "
-			   "does not support connection list\n",
-			   pin_nid, get_wcaps(codec, pin_nid));
-		return -EINVAL;
-	}
-
-	conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
-					   HDA_MAX_CONNECTIONS);
-	if (conn_len > 1)
-		curr = snd_hda_codec_read(codec, pin_nid, 0,
-					  AC_VERB_GET_CONNECT_SEL, 0);
-	else
-		curr = 0;
-
-	index = hda_node_index(spec->pin, pin_nid);
-	if (index < 0)
-		return -EINVAL;
-
-	spec->pin_cvt[index] = conn_list[curr];
-
-	return 0;
-}
-
-static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
-			      struct hdmi_eld *eld)
-{
-	if (!snd_hdmi_get_eld(eld, codec, pin_nid))
-		snd_hdmi_show_eld(eld);
-}
-
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
-			       struct hdmi_eld *eld)
-{
-	int present = snd_hda_pin_sense(codec, pin_nid);
-
-	eld->monitor_present	= !!(present & AC_PINSENSE_PRESENCE);
-	eld->eld_valid		= !!(present & AC_PINSENSE_ELDV);
-
-	if (present & AC_PINSENSE_ELDV)
-		hdmi_get_show_eld(codec, pin_nid, eld);
-}
-
-static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-
-	if (spec->num_pins >= INTEL_HDMI_PINS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for pin %d \n", pin_nid);
-		return -EINVAL;
-	}
-
-	hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
-
-	spec->pin[spec->num_pins] = pin_nid;
-	spec->num_pins++;
-
-	/*
-	 * It is assumed that converter nodes come first in the node list and
-	 * hence have been registered and usable now.
-	 */
-	return intel_hdmi_read_pin_conn(codec, pin_nid);
-}
-
-static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-
-	if (spec->num_cvts >= INTEL_HDMI_CVTS) {
-		snd_printk(KERN_WARNING
-			   "HDMI: no space for converter %d \n", nid);
-		return -EINVAL;
-	}
-
-	spec->cvt[spec->num_cvts] = nid;
-	spec->num_cvts++;
-
-	return 0;
-}
-
-static int intel_hdmi_parse_codec(struct hda_codec *codec)
-{
-	hda_nid_t nid;
-	int i, nodes;
-
-	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
-	if (!nid || nodes < 0) {
-		snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < nodes; i++, nid++) {
-		unsigned int caps;
-		unsigned int type;
-
-		caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
-		type = get_wcaps_type(caps);
-
-		if (!(caps & AC_WCAP_DIGITAL))
-			continue;
-
-		switch (type) {
-		case AC_WID_AUD_OUT:
-			if (intel_hdmi_add_cvt(codec, nid) < 0)
-				return -EINVAL;
-			break;
-		case AC_WID_PIN:
-			caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
-			if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
-				continue;
-			if (intel_hdmi_add_pin(codec, nid) < 0)
-				return -EINVAL;
-			break;
-		}
-	}
-
-	/*
-	 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
-	 * can be lost and presence sense verb will become inaccurate if the
-	 * HDA link is powered off at hot plug or hw initialization time.
-	 */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
-	      AC_PWRST_EPSS))
-		codec->bus->power_keep_link_on = 1;
-#endif
-
-	return 0;
-}
-
-/*
- * HDMI routines
- */
-
-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-				int *packet_index, int *byte_index)
-{
-	int val;
-
-	val = snd_hda_codec_read(codec, pin_nid, 0,
-				 AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
-	*packet_index = val >> 5;
-	*byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
-				int packet_index, int byte_index)
-{
-	int val;
-
-	val = (packet_index << 5) | (byte_index & 0x1f);
-
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
-				unsigned char val)
-{
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-	/* Unmute */
-	if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
-		snd_hda_codec_write(codec, pin_nid, 0,
-				AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
-	/* Enable pin out */
-	snd_hda_codec_write(codec, pin_nid, 0,
-			    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-}
-
-/*
- * Enable Audio InfoFrame Transmission
- */
-static void hdmi_start_infoframe_trans(struct hda_codec *codec,
-				       hda_nid_t pin_nid)
-{
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-						AC_DIPXMIT_BEST);
-}
-
-/*
- * Disable Audio InfoFrame Transmission
- */
-static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
-				      hda_nid_t pin_nid)
-{
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
-						AC_DIPXMIT_DISABLE);
-}
-
-static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
-{
-	return 1 + snd_hda_codec_read(codec, nid, 0,
-					AC_VERB_GET_CVT_CHAN_COUNT, 0);
-}
-
-static void hdmi_set_channel_count(struct hda_codec *codec,
-				   hda_nid_t nid, int chs)
-{
-	if (chs != hdmi_get_channel_count(codec, nid))
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-}
-
-static void hdmi_debug_channel_mapping(struct hda_codec *codec,
-				       hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-	int i;
-	int slot;
-
-	for (i = 0; i < 8; i++) {
-		slot = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_CHAN_SLOT, i);
-		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
-						slot >> 4, slot & 0xf);
-	}
-#endif
-}
-
-
-/*
- * Audio InfoFrame routines
- */
-
-static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-	int i;
-	int size;
-
-	size = snd_hdmi_get_eld_size(codec, pin_nid);
-	printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-
-	for (i = 0; i < 8; i++) {
-		size = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_DIP_SIZE, i);
-		printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
-	}
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef BE_PARANOID
-	int i, j;
-	int size;
-	int pi, bi;
-	for (i = 0; i < 8; i++) {
-		size = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_DIP_SIZE, i);
-		if (size == 0)
-			continue;
-
-		hdmi_set_dip_index(codec, pin_nid, i, 0x0);
-		for (j = 1; j < 1000; j++) {
-			hdmi_write_dip_byte(codec, pin_nid, 0x0);
-			hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
-			if (pi != i)
-				snd_printd(KERN_INFO "dip index %d: %d != %d\n",
-						bi, pi, i);
-			if (bi == 0) /* byte index wrapped around */
-				break;
-		}
-		snd_printd(KERN_INFO
-			"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
-			i, size, j);
-	}
-#endif
-}
-
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	u8 sum = 0;
-	int i;
-
-	ai->checksum = 0;
-
-	for (i = 0; i < sizeof(*ai); i++)
-		sum += bytes[i];
-
-	ai->checksum = - sum;
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
-				      hda_nid_t pin_nid,
-				      struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	int i;
-
-	hdmi_debug_dip_size(codec, pin_nid);
-	hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
-
-	hdmi_checksum_audio_infoframe(ai);
-
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(*ai); i++)
-		hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
-}
-
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
-	int i, j;
-	struct cea_channel_speaker_allocation *p;
-
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		p = channel_allocations + i;
-		p->channels = 0;
-		p->spk_mask = 0;
-		for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
-			if (p->speakers[j]) {
-				p->channels++;
-				p->spk_mask |= p->speakers[j];
-			}
-	}
-}
-
-/*
- * The transformation takes two steps:
- *
- * 	eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- * 	      spk_mask => (channel_allocations[])         => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
-static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
-					 struct hdmi_audio_infoframe *ai)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	struct hdmi_eld *eld;
-	int i;
-	int spk_mask = 0;
-	int channels = 1 + (ai->CC02_CT47 & 0x7);
-	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-
-	/*
-	 * CA defaults to 0 for basic stereo audio
-	 */
-	if (channels <= 2)
-		return 0;
-
-	i = hda_node_index(spec->pin_cvt, nid);
-	if (i < 0)
-		return 0;
-	eld = &spec->sink_eld[i];
-
-	/*
-	 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
-	 * in console or for audio devices. Assume the highest speakers
-	 * configuration, to _not_ prohibit multi-channel audio playback.
-	 */
-	if (!eld->spk_alloc)
-		eld->spk_alloc = 0xffff;
-
-	/*
-	 * expand ELD's speaker allocation mask
-	 *
-	 * ELD tells the speaker mask in a compact(paired) form,
-	 * expand ELD's notions to match the ones used by Audio InfoFrame.
-	 */
-	for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
-		if (eld->spk_alloc & (1 << i))
-			spk_mask |= eld_speaker_allocation_bits[i];
-	}
-
-	/* search for the first working match in the CA table */
-	for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
-		if (channels == channel_allocations[i].channels &&
-		    (spk_mask & channel_allocations[i].spk_mask) ==
-				channel_allocations[i].spk_mask) {
-			ai->CA = channel_allocations[i].ca_index;
-			break;
-		}
-	}
-
-	snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
-	snd_printdd(KERN_INFO
-			"HDMI: select CA 0x%x for %d-channel allocation: %s\n",
-			ai->CA, channels, buf);
-
-	return ai->CA;
-}
-
-static void hdmi_setup_channel_mapping(struct hda_codec *codec,
-				       hda_nid_t pin_nid,
-				       struct hdmi_audio_infoframe *ai)
-{
-	int i;
-	int ca = ai->CA;
-	int err;
-
-	if (hdmi_channel_mapping[ca][1] == 0) {
-		for (i = 0; i < channel_allocations[ca].channels; i++)
-			hdmi_channel_mapping[ca][i] = i | (i << 4);
-		for (; i < 8; i++)
-			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
-	}
-
-	for (i = 0; i < 8; i++) {
-		err = snd_hda_codec_write(codec, pin_nid, 0,
-					  AC_VERB_SET_HDMI_CHAN_SLOT,
-					  hdmi_channel_mapping[ca][i]);
-		if (err) {
-			snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
-			break;
-		}
-	}
-
-	hdmi_debug_channel_mapping(codec, pin_nid);
-}
-
-static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
-				    struct hdmi_audio_infoframe *ai)
-{
-	u8 *bytes = (u8 *)ai;
-	u8 val;
-	int i;
-
-	if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
-							    != AC_DIPXMIT_BEST)
-		return false;
-
-	hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-	for (i = 0; i < sizeof(*ai); i++) {
-		val = snd_hda_codec_read(codec, pin_nid, 0,
-					 AC_VERB_GET_HDMI_DIP_DATA, 0);
-		if (val != bytes[i])
-			return false;
-	}
-
-	return true;
-}
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
-					struct snd_pcm_substream *substream)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	hda_nid_t pin_nid;
-	int i;
-	struct hdmi_audio_infoframe ai = {
-		.type		= 0x84,
-		.ver		= 0x01,
-		.len		= 0x0a,
-		.CC02_CT47	= substream->runtime->channels - 1,
-	};
-
-	hdmi_setup_channel_allocation(codec, nid, &ai);
-
-	for (i = 0; i < spec->num_pins; i++) {
-		if (spec->pin_cvt[i] != nid)
-			continue;
-		if (!spec->sink_eld[i].monitor_present)
-			continue;
-
-		pin_nid = spec->pin[i];
-		if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
-			hdmi_setup_channel_mapping(codec, pin_nid, &ai);
-			hdmi_stop_infoframe_trans(codec, pin_nid);
-			hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
-			hdmi_start_infoframe_trans(codec, pin_nid);
-		}
-	}
-}
-
-
-/*
- * Unsolicited events
- */
-
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int pind = !!(res & AC_UNSOL_RES_PD);
-	int eldv = !!(res & AC_UNSOL_RES_ELDV);
-	int index;
-
-	printk(KERN_INFO
-		"HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-		tag, pind, eldv);
-
-	index = hda_node_index(spec->pin, tag);
-	if (index < 0)
-		return;
-
-	spec->sink_eld[index].monitor_present = pind;
-	spec->sink_eld[index].eld_valid = eldv;
-
-	if (pind && eldv) {
-		hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]);
-		/* TODO: do real things about ELD */
-	}
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-	int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
-	int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
-	printk(KERN_INFO
-		"HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
-		tag,
-		subtag,
-		cp_state,
-		cp_ready);
-
-	/* TODO */
-	if (cp_state)
-		;
-	if (cp_ready)
-		;
-}
-
-
-static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	struct intel_hdmi_spec *spec = codec->spec;
-	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
-	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-
-	if (hda_node_index(spec->pin, tag) < 0) {
-		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
-		return;
-	}
-
-	if (subtag == 0)
-		hdmi_intrinsic_event(codec, res);
-	else
-		hdmi_non_intrinsic_event(codec, res);
-}
-
-/*
- * Callbacks
- */
-
-static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
-			      u32 stream_tag, int format)
-{
-	int tag;
-	int fmt;
-
-	tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
-	fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
-
-	snd_printdd("hdmi_setup_stream: "
-		    "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
-		    nid,
-		    tag == stream_tag ? "" : "new-",
-		    stream_tag,
-		    fmt == format ? "" : "new-",
-		    format);
-
-	if (tag != stream_tag)
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4);
-	if (fmt != format)
-		snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_STREAM_FORMAT, format);
-}
 
 static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 					   struct hda_codec *codec,
@@ -882,7 +87,7 @@
 
 static int intel_hdmi_build_pcms(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	struct hda_pcm *info = spec->pcm_rec;
 	int i;
 
@@ -908,7 +113,7 @@
 
 static int intel_hdmi_build_controls(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int err;
 	int i;
 
@@ -923,7 +128,7 @@
 
 static int intel_hdmi_init(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
 	for (i = 0; spec->pin[i]; i++) {
@@ -937,7 +142,7 @@
 
 static void intel_hdmi_free(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
 	for (i = 0; i < spec->num_pins; i++)
@@ -951,12 +156,12 @@
 	.free			= intel_hdmi_free,
 	.build_pcms		= intel_hdmi_build_pcms,
 	.build_controls 	= intel_hdmi_build_controls,
-	.unsol_event		= intel_hdmi_unsol_event,
+	.unsol_event		= hdmi_unsol_event,
 };
 
 static int patch_intel_hdmi(struct hda_codec *codec)
 {
-	struct intel_hdmi_spec *spec;
+	struct hdmi_spec *spec;
 	int i;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -964,7 +169,7 @@
 		return -ENOMEM;
 
 	codec->spec = spec;
-	if (intel_hdmi_parse_codec(codec) < 0) {
+	if (hdmi_parse_codec(codec) < 0) {
 		codec->spec = NULL;
 		kfree(spec);
 		return -EINVAL;
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 6afdab0..70669a2 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -29,13 +29,23 @@
 #include "hda_codec.h"
 #include "hda_local.h"
 
+#define MAX_HDMI_CVTS	1
+#define MAX_HDMI_PINS	1
+
+#include "patch_hdmi.c"
+
+static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = {
+	"NVIDIA HDMI",
+};
+
 /* define below to restrict the supported rates and formats */
 /* #define LIMITED_RATE_FMT_SUPPORT */
 
-struct nvhdmi_spec {
-	struct hda_multi_out multiout;
-
-	struct hda_pcm pcm_rec;
+enum HDACodec {
+	HDA_CODEC_NVIDIA_MCP7X,
+	HDA_CODEC_NVIDIA_MCP89,
+	HDA_CODEC_NVIDIA_GT21X,
+	HDA_CODEC_INVALID
 };
 
 #define Nv_VERB_SET_Channel_Allocation          0xF79
@@ -43,15 +53,18 @@
 #define Nv_VERB_SET_Audio_Protection_On         0xF98
 #define Nv_VERB_SET_Audio_Protection_Off        0xF99
 
-#define Nv_Master_Convert_nid   0x04
-#define Nv_Master_Pin_nid       0x05
+#define nvhdmi_master_con_nid_7x	0x04
+#define nvhdmi_master_pin_nid_7x	0x05
 
-static hda_nid_t nvhdmi_convert_nids[4] = {
+#define nvhdmi_master_con_nid_89	0x04
+#define nvhdmi_master_pin_nid_89	0x05
+
+static hda_nid_t nvhdmi_con_nids_7x[4] = {
 	/*front, rear, clfe, rear_surr */
 	0x6, 0x8, 0xa, 0xc,
 };
 
-static struct hda_verb nvhdmi_basic_init[] = {
+static struct hda_verb nvhdmi_basic_init_7x[] = {
 	/* set audio protect on */
 	{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
 	/* enable digital output on pin widget */
@@ -84,22 +97,60 @@
  */
 static int nvhdmi_build_controls(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int err;
+	int i;
 
-	err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
-	if (err < 0)
-		return err;
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; i < codec->num_pcms; i++) {
+			err = snd_hda_create_spdif_out_ctls(codec,
+							    spec->cvt[i]);
+			if (err < 0)
+				return err;
+		}
+	} else {
+		err = snd_hda_create_spdif_out_ctls(codec,
+						    spec->multiout.dig_out_nid);
+		if (err < 0)
+			return err;
+	}
 
 	return 0;
 }
 
 static int nvhdmi_init(struct hda_codec *codec)
 {
-	snd_hda_sequence_write(codec, nvhdmi_basic_init);
+	struct hdmi_spec *spec = codec->spec;
+	int i;
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; spec->pin[i]; i++) {
+			hdmi_enable_output(codec, spec->pin[i]);
+			snd_hda_codec_write(codec, spec->pin[i], 0,
+					    AC_VERB_SET_UNSOLICITED_ENABLE,
+					    AC_USRSP_EN | spec->pin[i]);
+		}
+	} else {
+		snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
+	}
 	return 0;
 }
 
+static void nvhdmi_free(struct hda_codec *codec)
+{
+	struct hdmi_spec *spec = codec->spec;
+	int i;
+
+	if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+	|| (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+		for (i = 0; i < spec->num_pins; i++)
+			snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
+	}
+
+	kfree(spec);
+}
+
 /*
  * Digital out
  */
@@ -107,25 +158,25 @@
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 }
 
-static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo,
+static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	int i;
 
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
 			0, AC_VERB_SET_CHANNEL_STREAMID, 0);
 	for (i = 0; i < 4; i++) {
 		/* set the stream id */
-		snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
 				AC_VERB_SET_CHANNEL_STREAMID, 0);
 		/* set the stream format */
-		snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
 				AC_VERB_SET_STREAM_FORMAT, 0);
 	}
 
@@ -136,10 +187,25 @@
 					struct hda_codec *codec,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
+static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					unsigned int stream_tag,
+					unsigned int format,
+					struct snd_pcm_substream *substream)
+{
+	hdmi_set_channel_count(codec, hinfo->nid,
+			       substream->runtime->channels);
+
+	hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
+
+	hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
+	return 0;
+}
+
 static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					unsigned int stream_tag,
@@ -181,29 +247,29 @@
 	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
 	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
 
 	/* set the stream id */
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
 			AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
 
 	/* set the stream format */
-	snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
 			AC_VERB_SET_STREAM_FORMAT, format);
 
 	/* turn on again (if needed) */
 	/* enable and set the channel status audio/data flag */
 	if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & 0xff);
 		snd_hda_codec_write(codec,
-				Nv_Master_Convert_nid,
+				nvhdmi_master_con_nid_7x,
 				0,
 				AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
 	}
@@ -220,19 +286,19 @@
 		if (codec->spdif_status_reset &&
 		(codec->spdif_ctls & AC_DIG1_ENABLE))
 			snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_DIGI_CONVERT_1,
 				codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
 		/* set the stream id */
 		snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_CHANNEL_STREAMID,
 				(stream_tag << 4) | channel_id);
 		/* set the stream format */
 		snd_hda_codec_write(codec,
-				nvhdmi_convert_nids[i],
+				nvhdmi_con_nids_7x[i],
 				0,
 				AC_VERB_SET_STREAM_FORMAT,
 				format);
@@ -241,12 +307,12 @@
 		if (codec->spdif_status_reset &&
 		(codec->spdif_ctls & AC_DIG1_ENABLE)) {
 			snd_hda_codec_write(codec,
-					nvhdmi_convert_nids[i],
+					nvhdmi_con_nids_7x[i],
 					0,
 					AC_VERB_SET_DIGI_CONVERT_1,
 					codec->spdif_ctls & 0xff);
 			snd_hda_codec_write(codec,
-					nvhdmi_convert_nids[i],
+					nvhdmi_con_nids_7x[i],
 					0,
 					AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
 		}
@@ -261,28 +327,47 @@
 	return 0;
 }
 
+static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
 static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
 					struct hda_codec *codec,
 					unsigned int stream_tag,
 					unsigned int format,
 					struct snd_pcm_substream *substream)
 {
-	struct nvhdmi_spec *spec = codec->spec;
+	struct hdmi_spec *spec = codec->spec;
 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
 					format, substream);
 }
 
-static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = {
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
+	.substreams = 1,
+	.channels_min = 2,
+	.rates = SUPPORTED_RATES,
+	.maxbps = SUPPORTED_MAXBPS,
+	.formats = SUPPORTED_FORMATS,
+	.ops = {
+		.prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
+		.cleanup = nvhdmi_playback_pcm_cleanup,
+	},
+};
+
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 8,
-	.nid = Nv_Master_Convert_nid,
+	.nid = nvhdmi_master_con_nid_7x,
 	.rates = SUPPORTED_RATES,
 	.maxbps = SUPPORTED_MAXBPS,
 	.formats = SUPPORTED_FORMATS,
 	.ops = {
 		.open = nvhdmi_dig_playback_pcm_open,
-		.close = nvhdmi_dig_playback_pcm_close_8ch,
+		.close = nvhdmi_dig_playback_pcm_close_8ch_7x,
 		.prepare = nvhdmi_dig_playback_pcm_prepare_8ch
 	},
 };
@@ -291,7 +376,7 @@
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
-	.nid = Nv_Master_Convert_nid,
+	.nid = nvhdmi_master_con_nid_7x,
 	.rates = SUPPORTED_RATES,
 	.maxbps = SUPPORTED_MAXBPS,
 	.formats = SUPPORTED_FORMATS,
@@ -302,10 +387,36 @@
 	},
 };
 
-static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
+static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
-	struct hda_pcm *info = &spec->pcm_rec;
+	struct hdmi_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+	int i;
+
+	codec->num_pcms = spec->num_cvts;
+	codec->pcm_info = info;
+
+	for (i = 0; i < codec->num_pcms; i++, info++) {
+		unsigned int chans;
+
+		chans = get_wcaps(codec, spec->cvt[i]);
+		chans = get_wcaps_channels(chans);
+
+		info->name = nvhdmi_pcm_names[i];
+		info->pcm_type = HDA_PCM_TYPE_HDMI;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK]
+					= nvhdmi_pcm_digital_playback_8ch_89;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
+	}
+
+	return 0;
+}
+
+static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
+{
+	struct hdmi_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
@@ -313,15 +424,15 @@
 	info->name = "NVIDIA HDMI";
 	info->pcm_type = HDA_PCM_TYPE_HDMI;
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK]
-					= nvhdmi_pcm_digital_playback_8ch;
+					= nvhdmi_pcm_digital_playback_8ch_7x;
 
 	return 0;
 }
 
 static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec = codec->spec;
-	struct hda_pcm *info = &spec->pcm_rec;
+	struct hdmi_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
 
 	codec->num_pcms = 1;
 	codec->pcm_info = info;
@@ -334,14 +445,17 @@
 	return 0;
 }
 
-static void nvhdmi_free(struct hda_codec *codec)
-{
-	kfree(codec->spec);
-}
-
-static struct hda_codec_ops nvhdmi_patch_ops_8ch = {
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = {
 	.build_controls = nvhdmi_build_controls,
-	.build_pcms = nvhdmi_build_pcms_8ch,
+	.build_pcms = nvhdmi_build_pcms_8ch_89,
+	.init = nvhdmi_init,
+	.free = nvhdmi_free,
+	.unsol_event = hdmi_unsol_event,
+};
+
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
+	.build_controls = nvhdmi_build_controls,
+	.build_pcms = nvhdmi_build_pcms_8ch_7x,
 	.init = nvhdmi_init,
 	.free = nvhdmi_free,
 };
@@ -353,9 +467,36 @@
 	.free = nvhdmi_free,
 };
 
-static int patch_nvhdmi_8ch(struct hda_codec *codec)
+static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec;
+	struct hdmi_spec *spec;
+	int i;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
+
+	if (hdmi_parse_codec(codec) < 0) {
+		codec->spec = NULL;
+		kfree(spec);
+		return -EINVAL;
+	}
+	codec->patch_ops = nvhdmi_patch_ops_8ch_89;
+
+	for (i = 0; i < spec->num_pins; i++)
+		snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
+
+	init_channel_allocations();
+
+	return 0;
+}
+
+static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
+{
+	struct hdmi_spec *spec;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -365,16 +506,17 @@
 
 	spec->multiout.num_dacs = 0;  /* no analog */
 	spec->multiout.max_channels = 8;
-	spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+	spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
 
-	codec->patch_ops = nvhdmi_patch_ops_8ch;
+	codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
 
 	return 0;
 }
 
 static int patch_nvhdmi_2ch(struct hda_codec *codec)
 {
-	struct nvhdmi_spec *spec;
+	struct hdmi_spec *spec;
 
 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -384,7 +526,8 @@
 
 	spec->multiout.num_dacs = 0;  /* no analog */
 	spec->multiout.max_channels = 2;
-	spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+	spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+	spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
 
 	codec->patch_ops = nvhdmi_patch_ops_2ch;
 
@@ -395,13 +538,24 @@
  * patch entries
  */
 static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
-	{ .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
-	{ .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
 	{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
 	{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
+	{ .id = 0x10de0002, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0003, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0005, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0006, .name = "MCP77/78 HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de0007, .name = "MCP79/7A HDMI",
+	  .patch = patch_nvhdmi_8ch_7x },
+	{ .id = 0x10de000c, .name = "MCP89 HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
+	{ .id = 0x10de000b, .name = "GT21x HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
+	{ .id = 0x10de000d, .name = "GT240 HDMI",
+	  .patch = patch_nvhdmi_8ch_89 },
 	{} /* terminator */
 };
 
@@ -412,9 +566,12 @@
 MODULE_ALIAS("snd-hda-codec-id:10de0007");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
+MODULE_ALIAS("snd-hda-codec-id:10de000c");
+MODULE_ALIAS("snd-hda-codec-id:10de000b");
+MODULE_ALIAS("snd-hda-codec-id:10de000d");
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
+MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
 
 static struct hda_codec_preset_list nvhdmi_list = {
 	.preset = snd_hda_preset_nvhdmi,
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e8cbe21..3a83719 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -411,6 +411,8 @@
 	unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id);
 	if (mux_idx >= spec->num_mux_defs)
 		mux_idx = 0;
+	if (!spec->input_mux[mux_idx].num_items && mux_idx > 0)
+		mux_idx = 0;
 	return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo);
 }
 
@@ -439,6 +441,8 @@
 
 	mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
 	imux = &spec->input_mux[mux_idx];
+	if (!imux->num_items && mux_idx > 0)
+		imux = &spec->input_mux[0];
 
 	type = get_wcaps_type(get_wcaps(codec, nid));
 	if (type == AC_WID_AUD_MIX) {
@@ -4915,7 +4919,7 @@
 static void fixup_single_adc(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	hda_nid_t pin;
+	hda_nid_t pin = 0;
 	int i;
 
 	/* search for the input pin; there must be only one */
@@ -10105,6 +10109,8 @@
 			continue;
 		mux_idx = c >= spec->num_mux_defs ? 0 : c;
 		imux = &spec->input_mux[mux_idx];
+		if (!imux->num_items && mux_idx > 0)
+			imux = &spec->input_mux[0];
 		for (idx = 0; idx < conns; idx++) {
 			/* if the current connection is the selected one,
 			 * unmute it as default - otherwise mute it
@@ -13201,7 +13207,7 @@
 
 	if (board_config < 0 || board_config >= ALC268_MODEL_LAST)
 		board_config = snd_hda_check_board_codec_sid_config(codec,
-			ALC882_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
+			ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
 
 	if (board_config < 0 || board_config >= ALC268_MODEL_LAST) {
 		printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
@@ -13561,6 +13567,8 @@
 static void alc269_quanta_fl1_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x19;
@@ -13656,6 +13664,8 @@
 static void alc269_laptop_dmic_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x12;
@@ -13666,6 +13676,8 @@
 static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x12;
@@ -13676,6 +13688,8 @@
 static void alc269_laptop_amic_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x19;
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c
index 7754db1..dbc4b89 100644
--- a/sound/pci/oxygen/xonar_wm87x6.c
+++ b/sound/pci/oxygen/xonar_wm87x6.c
@@ -68,7 +68,7 @@
 			 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
 			 (reg << 9) | value);
 	if (reg < ARRAY_SIZE(data->wm8776_regs)) {
-		if (reg >= WM8776_HPLVOL || reg <= WM8776_DACMASTER)
+		if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
 			value &= ~WM8776_UPDATE;
 		data->wm8776_regs[reg] = value;
 	}
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 960a227..ad44626 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1974,9 +1974,9 @@
 	}
 	snd_iprintf(buffer, "Paths:\n");
 	i = getpaths(cif, p);
-	while (i--) {
-		snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]);
-		i--;
+	while (i >= 2) {
+		i -= 2;
+		snd_iprintf(buffer, "%x->%x ", p[i], p[i + 1]);
 	}
 	snd_iprintf(buffer, "\n");
 }
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 3d72c1e..547b713 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -2479,7 +2479,7 @@
    on MADICARD 
   - playback mixer matrix: [channelout+64] [output] [value]
   - input(thru) mixer matrix: [channelin] [output] [value]
-  (better do 2 kontrols for seperation ?)
+  (better do 2 kontrols for separation ?)
 */
 
 #define HDSPM_MIXER(xname, xindex) \
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index b9ef7e4..b68d99f 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -90,12 +90,10 @@
 	if (reg >= codec->reg_cache_size)
 		return -EINVAL;
 
-	reg &= AK4104_REG_MASK;
-	reg |= AK4104_WRITE;
-
 	/* only write to the hardware if value has changed */
 	if (cache[reg] != value) {
-		u8 tmp[2] = { reg, value };
+		u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value };
+
 		if (spi_write(spi, tmp, sizeof(tmp))) {
 			dev_err(&spi->dev, "SPI write failed\n");
 			return -EIO;
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index a2763c2..9cd0a66 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -137,7 +137,7 @@
 {
 	int bit, reg;
 
-	for_each_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
+	for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
 		reg = 0x10 + bit;
 		pr_debug("uda1380: flush reg %x val %x:\n", reg,
 				uda1380_read_reg_cache(uda1380_codec, reg));
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 718ef91..df2c6d9 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1349,7 +1349,7 @@
 	int mask;
 	struct wm8350_jack_data *jack = NULL;
 
-	switch (irq) {
+	switch (irq - wm8350->irq_base) {
 	case WM8350_IRQ_CODEC_JCK_DET_L:
 		jack = &priv->hpl;
 		mask = WM8350_JACK_L_LVL;
@@ -1424,7 +1424,7 @@
 	wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena);
 
 	/* Sync status */
-	wm8350_hp_jack_handler(irq, priv);
+	wm8350_hp_jack_handler(irq + wm8350->irq_base, priv);
 
 	return 0;
 }
@@ -1521,8 +1521,8 @@
 			  WM8350_JDL_ENA | WM8350_JDR_ENA);
 	wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
 
-	wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
-	wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv);
 
 	priv->hpl.jack = NULL;
 	priv->hpr.jack = NULL;
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index a54dc77b..056b787 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -990,7 +990,7 @@
 		reg = snd_soc_read(codec, WM8990_CLOCKING_2);
 		snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
 
-		/* set up N , fractional mode and pre-divisor if neccessary */
+		/* set up N , fractional mode and pre-divisor if necessary */
 		snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
 			(pll_div.div2?WM8990_PRESCALE:0));
 		snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index e69397f..9e95e51 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -42,11 +42,14 @@
  * SSP audio private data
  */
 struct ssp_priv {
-	struct ssp_dev dev;
+	struct ssp_device *ssp;
 	unsigned int sysclk;
 	int dai_fmt;
 #ifdef CONFIG_PM
-	struct ssp_state state;
+	uint32_t	cr0;
+	uint32_t	cr1;
+	uint32_t	to;
+	uint32_t	psp;
 #endif
 };
 
@@ -61,6 +64,22 @@
 		 ssp_read_reg(ssp, SSACD));
 }
 
+static void ssp_enable(struct ssp_device *ssp)
+{
+	uint32_t sscr0;
+
+	sscr0 = __raw_readl(ssp->mmio_base + SSCR0) | SSCR0_SSE;
+	__raw_writel(sscr0, ssp->mmio_base + SSCR0);
+}
+
+static void ssp_disable(struct ssp_device *ssp)
+{
+	uint32_t sscr0;
+
+	sscr0 = __raw_readl(ssp->mmio_base + SSCR0) & ~SSCR0_SSE;
+	__raw_writel(sscr0, ssp->mmio_base + SSCR0);
+}
+
 struct pxa2xx_pcm_dma_data {
 	struct pxa2xx_pcm_dma_params params;
 	char name[20];
@@ -94,13 +113,12 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 	struct ssp_priv *priv = cpu_dai->private_data;
+	struct ssp_device *ssp = priv->ssp;
 	int ret = 0;
 
 	if (!cpu_dai->active) {
-		priv->dev.port = cpu_dai->id + 1;
-		priv->dev.irq = NO_IRQ;
-		clk_enable(priv->dev.ssp->clk);
-		ssp_disable(&priv->dev);
+		clk_enable(ssp->clk);
+		ssp_disable(ssp);
 	}
 
 	if (cpu_dai->dma_data) {
@@ -116,10 +134,11 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 	struct ssp_priv *priv = cpu_dai->private_data;
+	struct ssp_device *ssp = priv->ssp;
 
 	if (!cpu_dai->active) {
-		ssp_disable(&priv->dev);
-		clk_disable(priv->dev.ssp->clk);
+		ssp_disable(ssp);
+		clk_disable(ssp->clk);
 	}
 
 	if (cpu_dai->dma_data) {
@@ -133,27 +152,39 @@
 static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
 {
 	struct ssp_priv *priv = cpu_dai->private_data;
+	struct ssp_device *ssp = priv->ssp;
 
 	if (!cpu_dai->active)
-		clk_enable(priv->dev.ssp->clk);
+		clk_enable(ssp->clk);
 
-	ssp_save_state(&priv->dev, &priv->state);
-	clk_disable(priv->dev.ssp->clk);
+	priv->cr0 = __raw_readl(ssp->mmio_base + SSCR0);
+	priv->cr1 = __raw_readl(ssp->mmio_base + SSCR1);
+	priv->to  = __raw_readl(ssp->mmio_base + SSTO);
+	priv->psp = __raw_readl(ssp->mmio_base + SSPSP);
 
+	ssp_disable(ssp);
+	clk_disable(ssp->clk);
 	return 0;
 }
 
 static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
 {
 	struct ssp_priv *priv = cpu_dai->private_data;
+	struct ssp_device *ssp = priv->ssp;
+	uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE;
 
-	clk_enable(priv->dev.ssp->clk);
-	ssp_restore_state(&priv->dev, &priv->state);
+	clk_enable(ssp->clk);
+
+	__raw_writel(sssr, ssp->mmio_base + SSSR);
+	__raw_writel(priv->cr0 & ~SSCR0_SSE, ssp->mmio_base + SSCR0);
+	__raw_writel(priv->cr1, ssp->mmio_base + SSCR1);
+	__raw_writel(priv->to,  ssp->mmio_base + SSTO);
+	__raw_writel(priv->psp, ssp->mmio_base + SSPSP);
 
 	if (cpu_dai->active)
-		ssp_enable(&priv->dev);
+		ssp_enable(ssp);
 	else
-		clk_disable(priv->dev.ssp->clk);
+		clk_disable(ssp->clk);
 
 	return 0;
 }
@@ -203,7 +234,7 @@
 	int clk_id, unsigned int freq, int dir)
 {
 	struct ssp_priv *priv = cpu_dai->private_data;
-	struct ssp_device *ssp = priv->dev.ssp;
+	struct ssp_device *ssp = priv->ssp;
 	int val;
 
 	u32 sscr0 = ssp_read_reg(ssp, SSCR0) &
@@ -244,11 +275,11 @@
 	/* The SSP clock must be disabled when changing SSP clock mode
 	 * on PXA2xx.  On PXA3xx it must be enabled when doing so. */
 	if (!cpu_is_pxa3xx())
-		clk_disable(priv->dev.ssp->clk);
+		clk_disable(ssp->clk);
 	val = ssp_read_reg(ssp, SSCR0) | sscr0;
 	ssp_write_reg(ssp, SSCR0, val);
 	if (!cpu_is_pxa3xx())
-		clk_enable(priv->dev.ssp->clk);
+		clk_enable(ssp->clk);
 
 	return 0;
 }
@@ -260,7 +291,7 @@
 	int div_id, int div)
 {
 	struct ssp_priv *priv = cpu_dai->private_data;
-	struct ssp_device *ssp = priv->dev.ssp;
+	struct ssp_device *ssp = priv->ssp;
 	int val;
 
 	switch (div_id) {
@@ -311,7 +342,7 @@
 	int source, unsigned int freq_in, unsigned int freq_out)
 {
 	struct ssp_priv *priv = cpu_dai->private_data;
-	struct ssp_device *ssp = priv->dev.ssp;
+	struct ssp_device *ssp = priv->ssp;
 	u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70;
 
 #if defined(CONFIG_PXA3xx)
@@ -380,7 +411,7 @@
 	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
 {
 	struct ssp_priv *priv = cpu_dai->private_data;
-	struct ssp_device *ssp = priv->dev.ssp;
+	struct ssp_device *ssp = priv->ssp;
 	u32 sscr0;
 
 	sscr0 = ssp_read_reg(ssp, SSCR0);
@@ -415,7 +446,7 @@
 	int tristate)
 {
 	struct ssp_priv *priv = cpu_dai->private_data;
-	struct ssp_device *ssp = priv->dev.ssp;
+	struct ssp_device *ssp = priv->ssp;
 	u32 sscr1;
 
 	sscr1 = ssp_read_reg(ssp, SSCR1);
@@ -437,7 +468,7 @@
 		unsigned int fmt)
 {
 	struct ssp_priv *priv = cpu_dai->private_data;
-	struct ssp_device *ssp = priv->dev.ssp;
+	struct ssp_device *ssp = priv->ssp;
 	u32 sscr0;
 	u32 sscr1;
 	u32 sspsp;
@@ -532,7 +563,7 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 	struct ssp_priv *priv = cpu_dai->private_data;
-	struct ssp_device *ssp = priv->dev.ssp;
+	struct ssp_device *ssp = priv->ssp;
 	int chn = params_channels(params);
 	u32 sscr0;
 	u32 sspsp;
@@ -642,12 +673,12 @@
 	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 	int ret = 0;
 	struct ssp_priv *priv = cpu_dai->private_data;
-	struct ssp_device *ssp = priv->dev.ssp;
+	struct ssp_device *ssp = priv->ssp;
 	int val;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_RESUME:
-		ssp_enable(&priv->dev);
+		ssp_enable(ssp);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		val = ssp_read_reg(ssp, SSCR1);
@@ -666,7 +697,7 @@
 		else
 			val |= SSCR1_RSRE;
 		ssp_write_reg(ssp, SSCR1, val);
-		ssp_enable(&priv->dev);
+		ssp_enable(ssp);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		val = ssp_read_reg(ssp, SSCR1);
@@ -677,7 +708,7 @@
 		ssp_write_reg(ssp, SSCR1, val);
 		break;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-		ssp_disable(&priv->dev);
+		ssp_disable(ssp);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		val = ssp_read_reg(ssp, SSCR1);
@@ -707,8 +738,8 @@
 	if (!priv)
 		return -ENOMEM;
 
-	priv->dev.ssp = ssp_request(dai->id + 1, "SoC audio");
-	if (priv->dev.ssp == NULL) {
+	priv->ssp = ssp_request(dai->id + 1, "SoC audio");
+	if (priv->ssp == NULL) {
 		ret = -ENODEV;
 		goto err_priv;
 	}
@@ -727,7 +758,7 @@
 			      struct snd_soc_dai *dai)
 {
 	struct ssp_priv *priv = dai->private_data;
-	ssp_free(priv->dev.ssp);
+	ssp_free(priv->ssp);
 }
 
 #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index 93ed3aa..a72c251 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -22,8 +22,8 @@
 #include <sound/soc.h>
 
 #include <plat/regs-s3c2412-iis.h>
-#include <plat/gpio-bank-d.h>
-#include <plat/gpio-bank-e.h>
+#include <mach/gpio-bank-d.h>
+#include <mach/gpio-bank-e.h>
 #include <plat/gpio-cfg.h>
 
 #include <mach/map.h>
diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h
index 9cc04ab..c0bfab8 100644
--- a/sound/soc/sh/siu.h
+++ b/sound/soc/sh/siu.h
@@ -72,7 +72,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 
-#include <asm/dma-sh.h>
+#include <asm/dmaengine.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index c5efc30..ba7f8d0 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -32,7 +32,7 @@
 #include <sound/pcm_params.h>
 #include <sound/soc-dai.h>
 
-#include <asm/dma-sh.h>
+#include <asm/dmaengine.h>
 #include <asm/siu.h>
 
 #include "siu.h"
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index a03bac9..c8b0556 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -427,24 +427,24 @@
 	if (!runtime->hw.rates) {
 		printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
 			codec_dai->name, cpu_dai->name);
-		goto machine_err;
+		goto config_err;
 	}
 	if (!runtime->hw.formats) {
 		printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
 			codec_dai->name, cpu_dai->name);
-		goto machine_err;
+		goto config_err;
 	}
 	if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
 		printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
 			codec_dai->name, cpu_dai->name);
-		goto machine_err;
+		goto config_err;
 	}
 
 	/* Symmetry only applies if we've already got an active stream. */
 	if (cpu_dai->active || codec_dai->active) {
 		ret = soc_pcm_apply_symmetry(substream);
 		if (ret != 0)
-			goto machine_err;
+			goto config_err;
 	}
 
 	pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
@@ -464,10 +464,14 @@
 	mutex_unlock(&pcm_mutex);
 	return 0;
 
-machine_err:
+config_err:
 	if (machine->ops && machine->ops->shutdown)
 		machine->ops->shutdown(substream);
 
+machine_err:
+	if (codec_dai->ops->shutdown)
+		codec_dai->ops->shutdown(substream, codec_dai);
+
 codec_dai_err:
 	if (platform->pcm_ops->close)
 		platform->pcm_ops->close(substream);
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 8c29258..c570ae3 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -22,13 +22,13 @@
 	  will be called snd-usb-audio.
 
 config SND_USB_UA101
-	tristate "Edirol UA-101 driver (EXPERIMENTAL)"
+	tristate "Edirol UA-101/UA-1000 driver (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 	select SND_PCM
 	select SND_RAWMIDI
 	help
-	  Say Y here to include support for the Edirol UA-101 audio/MIDI
-	  interface.
+	  Say Y here to include support for the Edirol UA-101 and UA-1000
+	  audio/MIDI interfaces.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-ua101.
diff --git a/sound/usb/caiaq/midi.h b/sound/usb/caiaq/midi.h
index 9d16db0..380f984 100644
--- a/sound/usb/caiaq/midi.h
+++ b/sound/usb/caiaq/midi.h
@@ -3,6 +3,6 @@
 
 int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev);
 void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len);
-void snd_usb_caiaq_midi_output_done(struct urb* urb);
+void snd_usb_caiaq_midi_output_done(struct urb *urb);
 
 #endif /* CAIAQ_MIDI_H */
diff --git a/sound/usb/ua101.c b/sound/usb/ua101.c
index 4f4ccdf..3d458d3 100644
--- a/sound/usb/ua101.c
+++ b/sound/usb/ua101.c
@@ -1,5 +1,5 @@
 /*
- * Edirol UA-101 driver
+ * Edirol UA-101/UA-1000 driver
  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  *
  * This driver is free software: you can redistribute it and/or modify
@@ -25,13 +25,10 @@
 #include <sound/pcm_params.h>
 #include "usbaudio.h"
 
-MODULE_DESCRIPTION("Edirol UA-101 driver");
+MODULE_DESCRIPTION("Edirol UA-101/1000 driver");
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_LICENSE("GPL v2");
-MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101}}");
-
-/* I use my UA-1A for testing because I don't have a UA-101 ... */
-#define UA1A_HACK
+MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}");
 
 /*
  * Should not be lower than the minimum scheduling delay of the host
@@ -132,9 +129,6 @@
 			dma_addr_t dma;
 		} buffers[MAX_MEMORY_BUFFERS];
 	} capture, playback;
-
-	unsigned int fps[10];
-	unsigned int frame_counter;
 };
 
 static DEFINE_MUTEX(devices_mutex);
@@ -424,16 +418,6 @@
 	if (do_period_elapsed)
 		snd_pcm_period_elapsed(stream->substream);
 
-	/* for debugging: measure the sample rate relative to the USB clock */
-	ua->fps[ua->frame_counter++ / ua->packets_per_second] += frames;
-	if (ua->frame_counter >= ARRAY_SIZE(ua->fps) * ua->packets_per_second) {
-		printk(KERN_DEBUG "capture rate:");
-		for (frames = 0; frames < ARRAY_SIZE(ua->fps); ++frames)
-			printk(KERN_CONT " %u", ua->fps[frames]);
-		printk(KERN_CONT "\n");
-		memset(ua->fps, 0, sizeof(ua->fps));
-		ua->frame_counter = 0;
-	}
 	return;
 
 stream_stopped:
@@ -1200,13 +1184,30 @@
 		.type = QUIRK_MIDI_FIXED_ENDPOINT,
 		.data = &midi_ep
 	};
+	static const int intf_numbers[2][3] = {
+		{	/* UA-101 */
+			[INTF_PLAYBACK] = 0,
+			[INTF_CAPTURE] = 1,
+			[INTF_MIDI] = 2,
+		},
+		{	/* UA-1000 */
+			[INTF_CAPTURE] = 1,
+			[INTF_PLAYBACK] = 2,
+			[INTF_MIDI] = 3,
+		},
+	};
 	struct snd_card *card;
 	struct ua101 *ua;
 	unsigned int card_index, i;
+	int is_ua1000;
+	const char *name;
 	char usb_path[32];
 	int err;
 
-	if (interface->altsetting->desc.bInterfaceNumber != 0)
+	is_ua1000 = usb_id->idProduct == 0x0044;
+
+	if (interface->altsetting->desc.bInterfaceNumber !=
+	    intf_numbers[is_ua1000][0])
 		return -ENODEV;
 
 	mutex_lock(&devices_mutex);
@@ -1239,20 +1240,13 @@
 	init_waitqueue_head(&ua->rate_feedback_wait);
 	init_waitqueue_head(&ua->alsa_playback_wait);
 
-#ifdef UA1A_HACK
-	if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) {
-		ua->intf[2] = interface;
-		ua->intf[0] = usb_ifnum_to_if(ua->dev, 1);
-		ua->intf[1] = usb_ifnum_to_if(ua->dev, 2);
-		usb_driver_claim_interface(&ua101_driver, ua->intf[0], ua);
-		usb_driver_claim_interface(&ua101_driver, ua->intf[1], ua);
-	} else {
-#endif
 	ua->intf[0] = interface;
 	for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) {
-		ua->intf[i] = usb_ifnum_to_if(ua->dev, i);
+		ua->intf[i] = usb_ifnum_to_if(ua->dev,
+					      intf_numbers[is_ua1000][i]);
 		if (!ua->intf[i]) {
-			dev_err(&ua->dev->dev, "interface %u not found\n", i);
+			dev_err(&ua->dev->dev, "interface %u not found\n",
+				intf_numbers[is_ua1000][i]);
 			err = -ENXIO;
 			goto probe_error;
 		}
@@ -1264,39 +1258,19 @@
 			goto probe_error;
 		}
 	}
-#ifdef UA1A_HACK
-	}
-#endif
 
 	snd_card_set_dev(card, &interface->dev);
 
-#ifdef UA1A_HACK
-	if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) {
-		ua->format_bit = SNDRV_PCM_FMTBIT_S16_LE;
-		ua->rate = 44100;
-		ua->packets_per_second = 1000;
-		ua->capture.channels = 2;
-		ua->playback.channels = 2;
-		ua->capture.frame_bytes = 4;
-		ua->playback.frame_bytes = 4;
-		ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, 2);
-		ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, 1);
-		ua->capture.max_packet_bytes = 192;
-		ua->playback.max_packet_bytes = 192;
-	} else {
-#endif
 	err = detect_usb_format(ua);
 	if (err < 0)
 		goto probe_error;
-#ifdef UA1A_HACK
-	}
-#endif
 
+	name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101";
 	strcpy(card->driver, "UA-101");
-	strcpy(card->shortname, "UA-101");
+	strcpy(card->shortname, name);
 	usb_make_path(ua->dev, usb_path, sizeof(usb_path));
 	snprintf(ua->card->longname, sizeof(ua->card->longname),
-		 "EDIROL UA-101 (serial %s), %u Hz at %s, %s speed",
+		 "EDIROL %s (serial %s), %u Hz at %s, %s speed", name,
 		 ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path,
 		 ua->dev->speed == USB_SPEED_HIGH ? "high" : "full");
 
@@ -1314,24 +1288,18 @@
 	if (err < 0)
 		goto probe_error;
 
-	err = snd_pcm_new(card, "UA-101", 0, 1, 1, &ua->pcm);
+	err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm);
 	if (err < 0)
 		goto probe_error;
 	ua->pcm->private_data = ua;
-	strcpy(ua->pcm->name, "UA-101");
+	strcpy(ua->pcm->name, name);
 	snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops);
 	snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops);
 
-#ifdef UA1A_HACK
-	if (ua->dev->descriptor.idProduct != cpu_to_le16(0x0018)) {
-#endif
 	err = snd_usbmidi_create(card, ua->intf[INTF_MIDI],
 				 &ua->midi_list, &midi_quirk);
 	if (err < 0)
 		goto probe_error;
-#ifdef UA1A_HACK
-	}
-#endif
 
 	err = snd_card_register(card);
 	if (err < 0)
@@ -1386,11 +1354,9 @@
 }
 
 static struct usb_device_id ua101_ids[] = {
-#ifdef UA1A_HACK
-	{ USB_DEVICE(0x0582, 0x0018) },
-#endif
-	{ USB_DEVICE(0x0582, 0x007d) },
-	{ USB_DEVICE(0x0582, 0x008d) },
+	{ USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */
+	{ USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */
+	{ USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, ua101_ids);
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index c539f7f..11b0826 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2483,7 +2483,6 @@
 				   sample_width, sample_bytes);
 		}
 		/* check the format byte size */
-		printk(" XXXXX SAMPLE BYTES %d\n", sample_bytes);
 		switch (sample_bytes) {
 		case 1:
 			pcm_format = SNDRV_PCM_FORMAT_S8;
@@ -2581,6 +2580,9 @@
 			     chip->usb_id == USB_ID(0x0d8c, 0x0102)) &&
 			    fp->altsetting == 5 && fp->maxpacksize == 392)
 				rate = 96000;
+			/* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */
+			if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068))
+				rate = 8000;
 			fp->rate_table[fp->nr_rates] = rate;
 			if (!fp->rate_min || rate < fp->rate_min)
 				fp->rate_min = rate;
@@ -3386,58 +3388,6 @@
 	return 0;
 }
 
-/*
- * Create a stream for an Edirol UA-1000 interface.
- */
-static int create_ua1000_quirk(struct snd_usb_audio *chip,
-			       struct usb_interface *iface,
-			       const struct snd_usb_audio_quirk *quirk)
-{
-	static const struct audioformat ua1000_format = {
-		.format = SNDRV_PCM_FORMAT_S32_LE,
-		.fmt_type = UAC_FORMAT_TYPE_I,
-		.altsetting = 1,
-		.altset_idx = 1,
-		.attributes = 0,
-		.rates = SNDRV_PCM_RATE_CONTINUOUS,
-	};
-	struct usb_host_interface *alts;
-	struct usb_interface_descriptor *altsd;
-	struct audioformat *fp;
-	int stream, err;
-
-	if (iface->num_altsetting != 2)
-		return -ENXIO;
-	alts = &iface->altsetting[1];
-	altsd = get_iface_desc(alts);
-	if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE ||
-	    altsd->bNumEndpoints != 1)
-		return -ENXIO;
-
-	fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL);
-	if (!fp)
-		return -ENOMEM;
-
-	fp->channels = alts->extra[4];
-	fp->iface = altsd->bInterfaceNumber;
-	fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
-	fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
-	fp->datainterval = parse_datainterval(chip, alts);
-	fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
-	fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]);
-
-	stream = (fp->endpoint & USB_DIR_IN)
-		? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-	err = add_audio_endpoint(chip, stream, fp);
-	if (err < 0) {
-		kfree(fp);
-		return err;
-	}
-	/* FIXME: playback must be synchronized to capture */
-	usb_set_interface(chip->dev, fp->iface, 0);
-	return 0;
-}
-
 static int snd_usb_create_quirk(struct snd_usb_audio *chip,
 				struct usb_interface *iface,
 				const struct snd_usb_audio_quirk *quirk);
@@ -3686,7 +3636,6 @@
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
 		[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
 		[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
-		[QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
 		[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
 		[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk
 	};
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 6b016d4..42c299c 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -75,7 +75,6 @@
 	QUIRK_MIDI_US122L,
 	QUIRK_AUDIO_STANDARD_INTERFACE,
 	QUIRK_AUDIO_FIXED_ENDPOINT,
-	QUIRK_AUDIO_EDIROL_UA1000,
 	QUIRK_AUDIO_EDIROL_UAXX,
 	QUIRK_AUDIO_ALIGN_TRANSFER,
 
@@ -112,7 +111,7 @@
 
 /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */
 
-/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */
+/* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */
 
 /* for QUIRK_IGNORE_INTERFACE, data is NULL */
 
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index f06faf7..2b426c1 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -1016,36 +1016,6 @@
 	}
 },
 {
-	USB_DEVICE(0x0582, 0x0044),
-	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-		.vendor_name = "Roland",
-		.product_name = "UA-1000",
-		.ifnum = QUIRK_ANY_INTERFACE,
-		.type = QUIRK_COMPOSITE,
-		.data = (const struct snd_usb_audio_quirk[]) {
-			{
-				.ifnum = 1,
-				.type = QUIRK_AUDIO_EDIROL_UA1000
-			},
-			{
-				.ifnum = 2,
-				.type = QUIRK_AUDIO_EDIROL_UA1000
-			},
-			{
-				.ifnum = 3,
-				.type = QUIRK_MIDI_FIXED_ENDPOINT,
-				.data = & (const struct snd_usb_midi_endpoint_info) {
-					.out_cables = 0x0003,
-					.in_cables  = 0x0003
-				}
-			},
-			{
-				.ifnum = -1
-			}
-		}
-	}
-},
-{
 	/* has ID 0x0049 when not in "Advanced Driver" mode */
 	USB_DEVICE(0x0582, 0x0047),
 	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
new file mode 100644
index 0000000..b317102
--- /dev/null
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -0,0 +1,29 @@
+perf-lock(1)
+============
+
+NAME
+----
+perf-lock - Analyze lock events
+
+SYNOPSIS
+--------
+[verse]
+'perf lock' {record|report|trace}
+
+DESCRIPTION
+-----------
+You can analyze various lock behaviours
+and statistics with this 'perf lock' command.
+
+  'perf lock record <command>' records lock events
+  between start and end <command>. And this command
+  produces the file "perf.data" which contains tracing
+  results of lock events.
+
+  'perf lock trace' shows raw lock events.
+
+  'perf lock report' reports statistical data.
+
+SEE ALSO
+--------
+linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 2de3407..34202b1 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -41,7 +41,8 @@
 
 -d::
 --del=::
-	Delete a probe event.
+	Delete probe events. This accepts glob wildcards('*', '?') and character
+	classes(e.g. [a-z], [!A-Z]).
 
 -l::
 --list::
@@ -50,17 +51,29 @@
 -L::
 --line=::
 	Show source code lines which can be probed. This needs an argument
-	which specifies a range of the source code.
+	which specifies a range of the source code. (see LINE SYNTAX for detail)
+
+-f::
+--force::
+	Forcibly add events with existing name.
 
 PROBE SYNTAX
 ------------
 Probe points are defined by following syntax.
 
- "[EVENT=]FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]"
+    1) Define event based on function name
+     [EVENT=]FUNC[@SRC][:RLN|+OFFS|%return|;PTN] [ARG ...]
+
+    2) Define event based on source file with line number
+     [EVENT=]SRC:ALN [ARG ...]
+
+    3) Define event based on source file with lazy pattern
+     [EVENT=]SRC;PTN [ARG ...]
+
 
 'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'.
-'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, 'RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. In addition, 'SRC' specifies a source file which has that function.
-It is also possible to specify a probe point by the source line number by using 'SRC:ALN' syntax, where 'SRC' is the source file path and 'ALN' is the line number.
+'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition.  In addition, '@SRC' specifies a source file which has that function.
+It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern.
 'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc).
 
 LINE SYNTAX
@@ -76,6 +89,41 @@
 many lines to show by using 'NUM'.
 So, "source.c:100-120" shows lines between 100th to l20th in source.c file. And "func:10+20" shows 20 lines from 10th line of func function.
 
+LAZY MATCHING
+-------------
+ The lazy line matching is similar to glob matching but ignoring spaces in both of pattern and target. So this accepts wildcards('*', '?') and character classes(e.g. [a-z], [!A-Z]).
+
+e.g.
+ 'a=*' can matches 'a=b', 'a = b', 'a == b' and so on.
+
+This provides some sort of flexibility and robustness to probe point definitions against minor code changes. For example, actual 10th line of schedule() can be moved easily by modifying schedule(), but the same line matching 'rq=cpu_rq*' may still exist in the function.)
+
+
+EXAMPLES
+--------
+Display which lines in schedule() can be probed:
+
+ ./perf probe --line schedule
+
+Add a probe on schedule() function 12th line with recording cpu local variable:
+
+ ./perf probe schedule:12 cpu
+ or
+ ./perf probe --add='schedule:12 cpu'
+
+ this will add one or more probes which has the name start with "schedule".
+
+ Add probes on lines in schedule() function which calls update_rq_clock().
+
+ ./perf probe 'schedule;update_rq_clock*'
+ or
+ ./perf probe --add='schedule;update_rq_clock*'
+
+Delete all probes on schedule().
+
+ ./perf probe --del='schedule*'
+
+
 SEE ALSO
 --------
 linkperf:perf-trace[1], linkperf:perf-record[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 54a5b50..2d53738 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -500,12 +500,12 @@
 	msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
 endif
 
-ifneq ($(shell sh -c "(echo '\#ifndef _MIPS_SZLONG'; echo '\#define _MIPS_SZLONG 0'; echo '\#endif'; echo '\#include <dwarf.h>'; echo '\#include <libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/libdwarf -ldwarf -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
-	msg := $(warning No libdwarf.h found or old libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel >= 20081231);
-	BASIC_CFLAGS += -DNO_LIBDWARF
+ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
+	msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev);
+	BASIC_CFLAGS += -DNO_DWARF_SUPPORT
 else
-	BASIC_CFLAGS += -I/usr/include/libdwarf
-	EXTLIBS += -lelf -ldwarf
+	BASIC_CFLAGS += -I/usr/include/elfutils
+	EXTLIBS += -lelf -ldw
 	LIB_OBJS += util/probe-finder.o
 endif
 
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index fb9ab2a..e12c844 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -460,6 +460,150 @@
 		process_lock_release_event(data, event, cpu, timestamp, thread);
 }
 
+struct raw_event_queue {
+	u64			timestamp;
+	int			cpu;
+	void			*data;
+	struct thread		*thread;
+	struct list_head	list;
+};
+
+static LIST_HEAD(raw_event_head);
+
+#define FLUSH_PERIOD	(5 * NSEC_PER_SEC)
+
+static u64 flush_limit = ULLONG_MAX;
+static u64 last_flush = 0;
+struct raw_event_queue *last_inserted;
+
+static void flush_raw_event_queue(u64 limit)
+{
+	struct raw_event_queue *tmp, *iter;
+
+	list_for_each_entry_safe(iter, tmp, &raw_event_head, list) {
+		if (iter->timestamp > limit)
+			return;
+
+		if (iter == last_inserted)
+			last_inserted = NULL;
+
+		process_raw_event(iter->data, iter->cpu, iter->timestamp,
+				  iter->thread);
+
+		last_flush = iter->timestamp;
+		list_del(&iter->list);
+		free(iter->data);
+		free(iter);
+	}
+}
+
+static void __queue_raw_event_end(struct raw_event_queue *new)
+{
+	struct raw_event_queue *iter;
+
+	list_for_each_entry_reverse(iter, &raw_event_head, list) {
+		if (iter->timestamp < new->timestamp) {
+			list_add(&new->list, &iter->list);
+			return;
+		}
+	}
+
+	list_add(&new->list, &raw_event_head);
+}
+
+static void __queue_raw_event_before(struct raw_event_queue *new,
+				     struct raw_event_queue *iter)
+{
+	list_for_each_entry_continue_reverse(iter, &raw_event_head, list) {
+		if (iter->timestamp < new->timestamp) {
+			list_add(&new->list, &iter->list);
+			return;
+		}
+	}
+
+	list_add(&new->list, &raw_event_head);
+}
+
+static void __queue_raw_event_after(struct raw_event_queue *new,
+				     struct raw_event_queue *iter)
+{
+	list_for_each_entry_continue(iter, &raw_event_head, list) {
+		if (iter->timestamp > new->timestamp) {
+			list_add_tail(&new->list, &iter->list);
+			return;
+		}
+	}
+	list_add_tail(&new->list, &raw_event_head);
+}
+
+/* The queue is ordered by time */
+static void __queue_raw_event(struct raw_event_queue *new)
+{
+	if (!last_inserted) {
+		__queue_raw_event_end(new);
+		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.
+	 */
+	if (last_inserted->timestamp >= new->timestamp)
+		__queue_raw_event_before(new, last_inserted);
+	else
+		__queue_raw_event_after(new, last_inserted);
+}
+
+static void queue_raw_event(void *data, int raw_size, int cpu,
+			    u64 timestamp, struct thread *thread)
+{
+	struct raw_event_queue *new;
+
+	if (flush_limit == ULLONG_MAX)
+		flush_limit = timestamp + FLUSH_PERIOD;
+
+	if (timestamp < last_flush) {
+		printf("Warning: Timestamp below last timeslice flush\n");
+		return;
+	}
+
+	new = malloc(sizeof(*new));
+	if (!new)
+		die("Not enough memory\n");
+
+	new->timestamp = timestamp;
+	new->cpu = cpu;
+	new->thread = thread;
+
+	new->data = malloc(raw_size);
+	if (!new->data)
+		die("Not enough memory\n");
+
+	memcpy(new->data, data, raw_size);
+
+	__queue_raw_event(new);
+	last_inserted = new;
+
+	/*
+	 * We want to have a slice of events covering 2 * FLUSH_PERIOD
+	 * If FLUSH_PERIOD is big enough, it ensures every events that occured
+	 * in the first half of the timeslice have all been buffered and there
+	 * are none remaining (we need that because of the weakly ordered
+	 * event recording we have). Then once we reach the 2 * FLUSH_PERIOD
+	 * timeslice, we flush the first half to be gentle with the memory
+	 * (the second half can still get new events in the middle, so wait
+	 * another period to flush it)
+	 */
+	if (new->timestamp > flush_limit &&
+		new->timestamp - flush_limit > FLUSH_PERIOD) {
+		flush_limit += FLUSH_PERIOD;
+		flush_raw_event_queue(flush_limit);
+	}
+}
+
 static int process_sample_event(event_t *event, struct perf_session *session)
 {
 	struct thread *thread;
@@ -480,7 +624,7 @@
 	if (profile_cpu != -1 && profile_cpu != (int) data.cpu)
 		return 0;
 
-	process_raw_event(data.raw_data, data.cpu, data.time, thread);
+	queue_raw_event(data.raw_data, data.raw_size, data.cpu, data.time, thread);
 
 	return 0;
 }
@@ -576,6 +720,7 @@
 	setup_pager();
 	select_key();
 	read_events();
+	flush_raw_event_queue(ULLONG_MAX);
 	sort_result();
 	print_result();
 }
@@ -608,7 +753,6 @@
 	"record",
 	"-a",
 	"-R",
-	"-M",
 	"-f",
 	"-m", "1024",
 	"-c", "1",
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index ad47bd4..c30a335 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -128,7 +128,7 @@
 		    pp->function);
 }
 
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
 static int open_vmlinux(void)
 {
 	if (map__load(session.kmaps[MAP__FUNCTION], NULL) < 0) {
@@ -156,14 +156,16 @@
 	"perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
 	"perf probe [<options>] --del '[GROUP:]EVENT' ...",
 	"perf probe --list",
+#ifndef NO_DWARF_SUPPORT
 	"perf probe --line 'LINEDESC'",
+#endif
 	NULL
 };
 
 static const struct option options[] = {
 	OPT_BOOLEAN('v', "verbose", &verbose,
 		    "be more verbose (show parsed arguments, etc)"),
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
 	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 		   "file", "vmlinux pathname"),
 #endif
@@ -172,30 +174,32 @@
 	OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
 		opt_del_probe_event),
 	OPT_CALLBACK('a', "add", NULL,
-#ifdef NO_LIBDWARF
-		"[EVENT=]FUNC[+OFFS|%return] [ARG ...]",
+#ifdef NO_DWARF_SUPPORT
+		"[EVENT=]FUNC[+OFF|%return] [ARG ...]",
 #else
-		"[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]",
+		"[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
+		" [ARG ...]",
 #endif
 		"probe point definition, where\n"
 		"\t\tGROUP:\tGroup name (optional)\n"
 		"\t\tEVENT:\tEvent name\n"
 		"\t\tFUNC:\tFunction name\n"
-		"\t\tOFFS:\tOffset from function entry (in byte)\n"
+		"\t\tOFF:\tOffset from function entry (in byte)\n"
 		"\t\t%return:\tPut the probe at function return\n"
-#ifdef NO_LIBDWARF
+#ifdef NO_DWARF_SUPPORT
 		"\t\tARG:\tProbe argument (only \n"
 #else
 		"\t\tSRC:\tSource code path\n"
-		"\t\tRLN:\tRelative line number from function entry.\n"
-		"\t\tALN:\tAbsolute line number in file.\n"
+		"\t\tRL:\tRelative line number from function entry.\n"
+		"\t\tAL:\tAbsolute line number in file.\n"
+		"\t\tPT:\tLazy expression of line code.\n"
 		"\t\tARG:\tProbe argument (local variable name or\n"
 #endif
 		"\t\t\tkprobe-tracer argument format.)\n",
 		opt_add_probe_event),
 	OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events"
 		    " with existing name"),
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
 	OPT_CALLBACK('L', "line", NULL,
 		     "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]",
 		     "Show source code lines.", opt_show_lines),
@@ -223,7 +227,7 @@
 int cmd_probe(int argc, const char **argv, const char *prefix __used)
 {
 	int i, ret;
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
 	int fd;
 #endif
 	struct probe_point *pp;
@@ -259,7 +263,7 @@
 		return 0;
 	}
 
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
 	if (session.show_lines) {
 		if (session.nr_probe != 0 || session.dellist) {
 			pr_warning("  Error: Don't use --line with"
@@ -290,9 +294,9 @@
 	init_vmlinux();
 
 	if (session.need_dwarf)
-#ifdef NO_LIBDWARF
+#ifdef NO_DWARF_SUPPORT
 		die("Debuginfo-analysis is not supported");
-#else	/* !NO_LIBDWARF */
+#else	/* !NO_DWARF_SUPPORT */
 		pr_debug("Some probes require debuginfo.\n");
 
 	fd = open_vmlinux();
@@ -312,7 +316,7 @@
 			continue;
 
 		lseek(fd, SEEK_SET, 0);
-		ret = find_probepoint(fd, pp);
+		ret = find_probe_point(fd, pp);
 		if (ret > 0)
 			continue;
 		if (ret == 0) {	/* No error but failed to find probe point. */
@@ -333,7 +337,7 @@
 	close(fd);
 
 end_dwarf:
-#endif /* !NO_LIBDWARF */
+#endif /* !NO_DWARF_SUPPORT */
 
 	/* Synthesize probes without dwarf */
 	for (i = 0; i < session.nr_probe; i++) {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 5db687f..407041d 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -573,7 +573,8 @@
 
 	if (symbol__init() < 0)
 		return -1;
-	setup_pager();
+	if (!script_name)
+		setup_pager();
 
 	session = perf_session__new(input_name, O_RDONLY, 0);
 	if (session == NULL)
@@ -608,7 +609,6 @@
 			return -1;
 		}
 
-		perf_header__read(&session->header, input);
 		err = scripting_ops->generate_script("perf-trace");
 		goto out;
 	}
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 9afcff2..db6ee94 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -18,3 +18,4 @@
 perf-trace			mainporcelain common
 perf-probe			mainporcelain common
 perf-kmem			mainporcelain common
+perf-lock			mainporcelain common
diff --git a/tools/perf/perf-archive.sh b/tools/perf/perf-archive.sh
index 45fbe2f..910468e 100644
--- a/tools/perf/perf-archive.sh
+++ b/tools/perf/perf-archive.sh
@@ -9,8 +9,9 @@
 
 DEBUGDIR=~/.debug/
 BUILDIDS=$(mktemp /tmp/perf-archive-buildids.XXXXXX)
+NOBUILDID=0000000000000000000000000000000000000000
 
-perf buildid-list -i $PERF_DATA --with-hits > $BUILDIDS
+perf buildid-list -i $PERF_DATA --with-hits | grep -v "^$NOBUILDID " > $BUILDIDS
 if [ ! -s $BUILDIDS ] ; then
 	echo "perf archive: no build-ids found"
 	rm -f $BUILDIDS
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 57cb107..cd32c20 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -445,7 +445,7 @@
 
 	/*
 	 * We use PATH to find perf commands, but we prepend some higher
-	 * precidence paths: the "--exec-path" option, the PERF_EXEC_PATH
+	 * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH
 	 * environment, and the $(perfexecdir) from the Makefile at build
 	 * time.
 	 */
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 75f941b..6fb379b 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -65,9 +65,7 @@
  * Use the __kuser_memory_barrier helper in the CPU helper page. See
  * arch/arm/kernel/entry-armv.S in the kernel source for details.
  */
-#define rmb()		asm volatile("mov r0, #0xffff0fff; mov lr, pc;" \
-				     "sub pc, r0, #95" ::: "r0", "lr", "cc", \
-				     "memory")
+#define rmb()		((void(*)(void))0xffff0fa0)()
 #define cpu_relax()	asm volatile("":::"memory")
 #endif
 
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index e8daf5c..44408c2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -321,7 +321,7 @@
 			new_depth_mask &= ~(1 << (depth - 1));
 
 		/*
-		 * But we keep the older depth mask for the line seperator
+		 * But we keep the older depth mask for the line separator
 		 * to keep the level link until we reach the last child
 		 */
 		ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 8f05688..53181db 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -119,14 +119,14 @@
 	char c, nc = 0;
 	/*
 	 * <Syntax>
-	 * perf probe [EVENT=]SRC:LN
-	 * perf probe [EVENT=]FUNC[+OFFS|%return][@SRC]
+	 * perf probe [EVENT=]SRC[:LN|;PTN]
+	 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
 	 *
 	 * TODO:Group name support
 	 */
 
-	ptr = strchr(arg, '=');
-	if (ptr) {	/* Event name */
+	ptr = strpbrk(arg, ";=@+%");
+	if (ptr && *ptr == '=') {	/* Event name */
 		*ptr = '\0';
 		tmp = ptr + 1;
 		ptr = strchr(arg, ':');
@@ -139,7 +139,7 @@
 		arg = tmp;
 	}
 
-	ptr = strpbrk(arg, ":+@%");
+	ptr = strpbrk(arg, ";:+@%");
 	if (ptr) {
 		nc = *ptr;
 		*ptr++ = '\0';
@@ -156,7 +156,11 @@
 	while (ptr) {
 		arg = ptr;
 		c = nc;
-		ptr = strpbrk(arg, ":+@%");
+		if (c == ';') {	/* Lazy pattern must be the last part */
+			pp->lazy_line = strdup(arg);
+			break;
+		}
+		ptr = strpbrk(arg, ";:+@%");
 		if (ptr) {
 			nc = *ptr;
 			*ptr++ = '\0';
@@ -165,13 +169,13 @@
 		case ':':	/* Line number */
 			pp->line = strtoul(arg, &tmp, 0);
 			if (*tmp != '\0')
-				semantic_error("There is non-digit charactor"
-						" in line number.");
+				semantic_error("There is non-digit char"
+					       " in line number.");
 			break;
 		case '+':	/* Byte offset from a symbol */
 			pp->offset = strtoul(arg, &tmp, 0);
 			if (*tmp != '\0')
-				semantic_error("There is non-digit charactor"
+				semantic_error("There is non-digit character"
 						" in offset.");
 			break;
 		case '@':	/* File name */
@@ -179,9 +183,6 @@
 				semantic_error("SRC@SRC is not allowed.");
 			pp->file = strdup(arg);
 			DIE_IF(pp->file == NULL);
-			if (ptr)
-				semantic_error("@SRC must be the last "
-					       "option.");
 			break;
 		case '%':	/* Probe places */
 			if (strcmp(arg, "return") == 0) {
@@ -196,11 +197,18 @@
 	}
 
 	/* Exclusion check */
+	if (pp->lazy_line && pp->line)
+		semantic_error("Lazy pattern can't be used with line number.");
+
+	if (pp->lazy_line && pp->offset)
+		semantic_error("Lazy pattern can't be used with offset.");
+
 	if (pp->line && pp->offset)
 		semantic_error("Offset can't be used with line number.");
 
-	if (!pp->line && pp->file && !pp->function)
-		semantic_error("File always requires line number.");
+	if (!pp->line && !pp->lazy_line && pp->file && !pp->function)
+		semantic_error("File always requires line number or "
+			       "lazy pattern.");
 
 	if (pp->offset && !pp->function)
 		semantic_error("Offset requires an entry function.");
@@ -208,11 +216,13 @@
 	if (pp->retprobe && !pp->function)
 		semantic_error("Return probe requires an entry function.");
 
-	if ((pp->offset || pp->line) && pp->retprobe)
-		semantic_error("Offset/Line can't be used with return probe.");
+	if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe)
+		semantic_error("Offset/Line/Lazy pattern can't be used with "
+			       "return probe.");
 
-	pr_debug("symbol:%s file:%s line:%d offset:%d, return:%d\n",
-		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe);
+	pr_debug("symbol:%s file:%s line:%d offset:%d return:%d lazy:%s\n",
+		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
+		 pp->lazy_line);
 }
 
 /* Parse perf-probe event definition */
@@ -458,6 +468,8 @@
 		free(pp->function);
 	if (pp->file)
 		free(pp->file);
+	if (pp->lazy_line)
+		free(pp->lazy_line);
 	for (i = 0; i < pp->nr_args; i++)
 		free(pp->args[i]);
 	if (pp->args)
@@ -496,8 +508,8 @@
 	struct str_node *ent;
 
 	setup_pager();
-
 	memset(&pp, 0, sizeof(pp));
+
 	fd = open_kprobe_events(O_RDONLY, 0);
 	rawlist = get_trace_kprobe_event_rawlist(fd);
 	close(fd);
@@ -719,6 +731,7 @@
 }
 
 #define LINEBUF_SIZE 256
+#define NR_ADDITIONAL_LINES 2
 
 static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num)
 {
@@ -779,5 +792,11 @@
 			show_one_line(fp, (l++) - lr->offset, false, false);
 		show_one_line(fp, (l++) - lr->offset, false, true);
 	}
+
+	if (lr->end == INT_MAX)
+		lr->end = l + NR_ADDITIONAL_LINES;
+	while (l < lr->end && !feof(fp))
+		show_one_line(fp, (l++) - lr->offset, false, false);
+
 	fclose(fp);
 }
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 1b2124d..e77dc88 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -32,21 +32,13 @@
 #include <stdarg.h>
 #include <ctype.h>
 
+#include "string.h"
 #include "event.h"
 #include "debug.h"
 #include "util.h"
 #include "probe-finder.h"
 
 
-/* Dwarf_Die Linkage to parent Die */
-struct die_link {
-	struct die_link *parent;	/* Parent die */
-	Dwarf_Die die;			/* Current die */
-};
-
-static Dwarf_Debug __dw_debug;
-static Dwarf_Error __dw_error;
-
 /*
  * Generic dwarf analysis helpers
  */
@@ -113,281 +105,190 @@
 	return 0;
 }
 
-/* Find the fileno of the target file. */
-static Dwarf_Unsigned cu_find_fileno(Dwarf_Die cu_die, const char *fname)
+/* Line number list operations */
+
+/* Add a line to line number list */
+static void line_list__add_line(struct list_head *head, unsigned int line)
 {
-	Dwarf_Signed cnt, i;
-	Dwarf_Unsigned found = 0;
-	char **srcs;
+	struct line_node *ln;
+	struct list_head *p;
+
+	/* Reverse search, because new line will be the last one */
+	list_for_each_entry_reverse(ln, head, list) {
+		if (ln->line < line) {
+			p = &ln->list;
+			goto found;
+		} else if (ln->line == line)	/* Already exist */
+			return ;
+	}
+	/* List is empty, or the smallest entry */
+	p = head;
+found:
+	pr_debug("line list: add a line %u\n", line);
+	ln = zalloc(sizeof(struct line_node));
+	DIE_IF(ln == NULL);
+	ln->line = line;
+	INIT_LIST_HEAD(&ln->list);
+	list_add(&ln->list, p);
+}
+
+/* Check if the line in line number list */
+static int line_list__has_line(struct list_head *head, unsigned int line)
+{
+	struct line_node *ln;
+
+	/* Reverse search, because new line will be the last one */
+	list_for_each_entry(ln, head, list)
+		if (ln->line == line)
+			return 1;
+
+	return 0;
+}
+
+/* Init line number list */
+static void line_list__init(struct list_head *head)
+{
+	INIT_LIST_HEAD(head);
+}
+
+/* Free line number list */
+static void line_list__free(struct list_head *head)
+{
+	struct line_node *ln;
+	while (!list_empty(head)) {
+		ln = list_first_entry(head, struct line_node, list);
+		list_del(&ln->list);
+		free(ln);
+	}
+}
+
+/* Dwarf wrappers */
+
+/* Find the realpath of the target file. */
+static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
+{
+	Dwarf_Files *files;
+	size_t nfiles, i;
+	const char *src;
 	int ret;
 
 	if (!fname)
-		return 0;
+		return NULL;
 
-	ret = dwarf_srcfiles(cu_die, &srcs, &cnt, &__dw_error);
-	if (ret == DW_DLV_OK) {
-		for (i = 0; i < cnt && !found; i++) {
-			if (strtailcmp(srcs[i], fname) == 0)
-				found = i + 1;
-			dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
-		}
-		for (; i < cnt; i++)
-			dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
-		dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST);
+	ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
+	if (ret != 0)
+		return NULL;
+
+	for (i = 0; i < nfiles; i++) {
+		src = dwarf_filesrc(files, i, NULL, NULL);
+		if (strtailcmp(src, fname) == 0)
+			break;
 	}
-	if (found)
-		pr_debug("found fno: %d\n", (int)found);
-	return found;
+	return src;
 }
 
-static int cu_get_filename(Dwarf_Die cu_die, Dwarf_Unsigned fno, char **buf)
+struct __addr_die_search_param {
+	Dwarf_Addr	addr;
+	Dwarf_Die	*die_mem;
+};
+
+static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
 {
-	Dwarf_Signed cnt, i;
-	char **srcs;
-	int ret = 0;
+	struct __addr_die_search_param *ad = data;
 
-	if (!buf || !fno)
-		return -EINVAL;
+	if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
+	    dwarf_haspc(fn_die, ad->addr)) {
+		memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
+		return DWARF_CB_ABORT;
+	}
+	return DWARF_CB_OK;
+}
 
-	ret = dwarf_srcfiles(cu_die, &srcs, &cnt, &__dw_error);
-	if (ret == DW_DLV_OK) {
-		if ((Dwarf_Unsigned)cnt > fno - 1) {
-			*buf = strdup(srcs[fno - 1]);
-			ret = 0;
-			pr_debug("found filename: %s\n", *buf);
-		} else
-			ret = -ENOENT;
-		for (i = 0; i < cnt; i++)
-			dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
-		dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST);
-	} else
-		ret = -EINVAL;
-	return ret;
+/* Search a real subprogram including this line, */
+static Dwarf_Die *die_get_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
+					  Dwarf_Die *die_mem)
+{
+	struct __addr_die_search_param ad;
+	ad.addr = addr;
+	ad.die_mem = die_mem;
+	/* dwarf_getscopes can't find subprogram. */
+	if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
+		return NULL;
+	else
+		return die_mem;
+}
+
+/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
+static Dwarf_Die *die_get_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
+				     Dwarf_Die *die_mem)
+{
+	Dwarf_Die child_die;
+	int ret;
+
+	ret = dwarf_child(sp_die, die_mem);
+	if (ret != 0)
+		return NULL;
+
+	do {
+		if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
+		    dwarf_haspc(die_mem, addr))
+			return die_mem;
+
+		if (die_get_inlinefunc(die_mem, addr, &child_die)) {
+			memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
+			return die_mem;
+		}
+	} while (dwarf_siblingof(die_mem, die_mem) == 0);
+
+	return NULL;
 }
 
 /* Compare diename and tname */
-static int die_compare_name(Dwarf_Die dw_die, const char *tname)
+static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
 {
-	char *name;
-	int ret;
-	ret = dwarf_diename(dw_die, &name, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	if (ret == DW_DLV_OK) {
-		ret = strcmp(tname, name);
-		dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
-	} else
-		ret = -1;
-	return ret;
-}
-
-/* Check the address is in the subprogram(function). */
-static int die_within_subprogram(Dwarf_Die sp_die, Dwarf_Addr addr,
-				 Dwarf_Signed *offs)
-{
-	Dwarf_Addr lopc, hipc;
-	int ret;
-
-	/* TODO: check ranges */
-	ret = dwarf_lowpc(sp_die, &lopc, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	if (ret == DW_DLV_NO_ENTRY)
-		return 0;
-	ret = dwarf_highpc(sp_die, &hipc, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	if (lopc <= addr && addr < hipc) {
-		*offs = addr - lopc;
-		return 1;
-	} else
-		return 0;
-}
-
-/* Check the die is inlined function */
-static Dwarf_Bool die_inlined_subprogram(Dwarf_Die dw_die)
-{
-	/* TODO: check strictly */
-	Dwarf_Bool inl;
-	int ret;
-
-	ret = dwarf_hasattr(dw_die, DW_AT_inline, &inl, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	return inl;
-}
-
-/* Get the offset of abstruct_origin */
-static Dwarf_Off die_get_abstract_origin(Dwarf_Die dw_die)
-{
-	Dwarf_Attribute attr;
-	Dwarf_Off cu_offs;
-	int ret;
-
-	ret = dwarf_attr(dw_die, DW_AT_abstract_origin, &attr, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	ret = dwarf_formref(attr, &cu_offs, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
-	return cu_offs;
+	const char *name;
+	name = dwarf_diename(dw_die);
+	DIE_IF(name == NULL);
+	return strcmp(tname, name);
 }
 
 /* Get entry pc(or low pc, 1st entry of ranges)  of the die */
-static Dwarf_Addr die_get_entrypc(Dwarf_Die dw_die)
+static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
 {
-	Dwarf_Attribute attr;
-	Dwarf_Addr addr;
-	Dwarf_Off offs;
-	Dwarf_Ranges *ranges;
-	Dwarf_Signed cnt;
+	Dwarf_Addr epc;
 	int ret;
 
-	/* Try to get entry pc */
-	ret = dwarf_attr(dw_die, DW_AT_entry_pc, &attr, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	if (ret == DW_DLV_OK) {
-		ret = dwarf_formaddr(attr, &addr, &__dw_error);
-		DIE_IF(ret != DW_DLV_OK);
-		dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
-		return addr;
-	}
-
-	/* Try to get low pc */
-	ret = dwarf_lowpc(dw_die, &addr, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	if (ret == DW_DLV_OK)
-		return addr;
-
-	/* Try to get ranges */
-	ret = dwarf_attr(dw_die, DW_AT_ranges, &attr, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	ret = dwarf_formref(attr, &offs, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	ret = dwarf_get_ranges(__dw_debug, offs, &ranges, &cnt, NULL,
-				&__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	addr = ranges[0].dwr_addr1;
-	dwarf_ranges_dealloc(__dw_debug, ranges, cnt);
-	return addr;
+	ret = dwarf_entrypc(dw_die, &epc);
+	DIE_IF(ret == -1);
+	return epc;
 }
 
-/*
- * Search a Die from Die tree.
- * Note: cur_link->die should be deallocated in this function.
- */
-static int __search_die_tree(struct die_link *cur_link,
-			     int (*die_cb)(struct die_link *, void *),
-			     void *data)
+/* Get a variable die */
+static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name,
+				    Dwarf_Die *die_mem)
 {
-	Dwarf_Die new_die;
-	struct die_link new_link;
+	Dwarf_Die child_die;
+	int tag;
 	int ret;
 
-	if (!die_cb)
-		return 0;
+	ret = dwarf_child(sp_die, die_mem);
+	if (ret != 0)
+		return NULL;
 
-	/* Check current die */
-	while (!(ret = die_cb(cur_link, data))) {
-		/* Check child die */
-		ret = dwarf_child(cur_link->die, &new_die, &__dw_error);
-		DIE_IF(ret == DW_DLV_ERROR);
-		if (ret == DW_DLV_OK) {
-			new_link.parent = cur_link;
-			new_link.die = new_die;
-			ret = __search_die_tree(&new_link, die_cb, data);
-			if (ret)
-				break;
+	do {
+		tag = dwarf_tag(die_mem);
+		if ((tag == DW_TAG_formal_parameter ||
+		     tag == DW_TAG_variable) &&
+		    (die_compare_name(die_mem, name) == 0))
+			return die_mem;
+
+		if (die_find_variable(die_mem, name, &child_die)) {
+			memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
+			return die_mem;
 		}
+	} while (dwarf_siblingof(die_mem, die_mem) == 0);
 
-		/* Move to next sibling */
-		ret = dwarf_siblingof(__dw_debug, cur_link->die, &new_die,
-				      &__dw_error);
-		DIE_IF(ret == DW_DLV_ERROR);
-		dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
-		cur_link->die = new_die;
-		if (ret == DW_DLV_NO_ENTRY)
-			return 0;
-	}
-	dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
-	return ret;
-}
-
-/* Search a die in its children's die tree */
-static int search_die_from_children(Dwarf_Die parent_die,
-				    int (*die_cb)(struct die_link *, void *),
-				    void *data)
-{
-	struct die_link new_link;
-	int ret;
-
-	new_link.parent = NULL;
-	ret = dwarf_child(parent_die, &new_link.die, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	if (ret == DW_DLV_OK)
-		return __search_die_tree(&new_link, die_cb, data);
-	else
-		return 0;
-}
-
-/* Find a locdesc corresponding to the address */
-static int attr_get_locdesc(Dwarf_Attribute attr, Dwarf_Locdesc *desc,
-			    Dwarf_Addr addr)
-{
-	Dwarf_Signed lcnt;
-	Dwarf_Locdesc **llbuf;
-	int ret, i;
-
-	ret = dwarf_loclist_n(attr, &llbuf, &lcnt, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	ret = DW_DLV_NO_ENTRY;
-	for (i = 0; i < lcnt; ++i) {
-		if (llbuf[i]->ld_lopc <= addr &&
-		    llbuf[i]->ld_hipc > addr) {
-			memcpy(desc, llbuf[i], sizeof(Dwarf_Locdesc));
-			desc->ld_s =
-				malloc(sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
-			DIE_IF(desc->ld_s == NULL);
-			memcpy(desc->ld_s, llbuf[i]->ld_s,
-				sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
-			ret = DW_DLV_OK;
-			break;
-		}
-		dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
-		dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
-	}
-	/* Releasing loop */
-	for (; i < lcnt; ++i) {
-		dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
-		dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
-	}
-	dwarf_dealloc(__dw_debug, llbuf, DW_DLA_LIST);
-	return ret;
-}
-
-/* Get decl_file attribute value (file number) */
-static Dwarf_Unsigned die_get_decl_file(Dwarf_Die sp_die)
-{
-	Dwarf_Attribute attr;
-	Dwarf_Unsigned fno;
-	int ret;
-
-	ret = dwarf_attr(sp_die, DW_AT_decl_file, &attr, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	dwarf_formudata(attr, &fno, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
-	return fno;
-}
-
-/* Get decl_line attribute value (line number) */
-static Dwarf_Unsigned die_get_decl_line(Dwarf_Die sp_die)
-{
-	Dwarf_Attribute attr;
-	Dwarf_Unsigned lno;
-	int ret;
-
-	ret = dwarf_attr(sp_die, DW_AT_decl_line, &attr, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	dwarf_formudata(attr, &lno, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
-	return lno;
+	return NULL;
 }
 
 /*
@@ -395,47 +296,45 @@
  */
 
 /* Show a location */
-static void show_location(Dwarf_Loc *loc, struct probe_finder *pf)
+static void show_location(Dwarf_Op *op, struct probe_finder *pf)
 {
-	Dwarf_Small op;
-	Dwarf_Unsigned regn;
-	Dwarf_Signed offs;
+	unsigned int regn;
+	Dwarf_Word offs = 0;
 	int deref = 0, ret;
 	const char *regs;
 
-	op = loc->lr_atom;
-
+	/* TODO: support CFA */
 	/* If this is based on frame buffer, set the offset */
-	if (op == DW_OP_fbreg) {
+	if (op->atom == DW_OP_fbreg) {
+		if (pf->fb_ops == NULL)
+			die("The attribute of frame base is not supported.\n");
 		deref = 1;
-		offs = (Dwarf_Signed)loc->lr_number;
-		op = pf->fbloc.ld_s[0].lr_atom;
-		loc = &pf->fbloc.ld_s[0];
-	} else
-		offs = 0;
+		offs = op->number;
+		op = &pf->fb_ops[0];
+	}
 
-	if (op >= DW_OP_breg0 && op <= DW_OP_breg31) {
-		regn = op - DW_OP_breg0;
-		offs += (Dwarf_Signed)loc->lr_number;
+	if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
+		regn = op->atom - DW_OP_breg0;
+		offs += op->number;
 		deref = 1;
-	} else if (op >= DW_OP_reg0 && op <= DW_OP_reg31) {
-		regn = op - DW_OP_reg0;
-	} else if (op == DW_OP_bregx) {
-		regn = loc->lr_number;
-		offs += (Dwarf_Signed)loc->lr_number2;
+	} else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
+		regn = op->atom - DW_OP_reg0;
+	} else if (op->atom == DW_OP_bregx) {
+		regn = op->number;
+		offs += op->number2;
 		deref = 1;
-	} else if (op == DW_OP_regx) {
-		regn = loc->lr_number;
+	} else if (op->atom == DW_OP_regx) {
+		regn = op->number;
 	} else
-		die("Dwarf_OP %d is not supported.", op);
+		die("DW_OP %d is not supported.", op->atom);
 
 	regs = get_arch_regstr(regn);
 	if (!regs)
-		die("%lld exceeds max register number.", regn);
+		die("%u exceeds max register number.", regn);
 
 	if (deref)
-		ret = snprintf(pf->buf, pf->len,
-				 " %s=%+lld(%s)", pf->var, offs, regs);
+		ret = snprintf(pf->buf, pf->len, " %s=+%ju(%s)",
+			       pf->var, (uintmax_t)offs, regs);
 	else
 		ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs);
 	DIE_IF(ret < 0);
@@ -443,52 +342,37 @@
 }
 
 /* Show a variables in kprobe event format */
-static void show_variable(Dwarf_Die vr_die, struct probe_finder *pf)
+static void show_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
 {
 	Dwarf_Attribute attr;
-	Dwarf_Locdesc ld;
+	Dwarf_Op *expr;
+	size_t nexpr;
 	int ret;
 
-	ret = dwarf_attr(vr_die, DW_AT_location, &attr, &__dw_error);
-	if (ret != DW_DLV_OK)
+	if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
 		goto error;
-	ret = attr_get_locdesc(attr, &ld, (pf->addr - pf->cu_base));
-	if (ret != DW_DLV_OK)
+	/* TODO: handle more than 1 exprs */
+	ret = dwarf_getlocation_addr(&attr, (pf->addr - pf->cu_base),
+				     &expr, &nexpr, 1);
+	if (ret <= 0 || nexpr == 0)
 		goto error;
-	/* TODO? */
-	DIE_IF(ld.ld_cents != 1);
-	show_location(&ld.ld_s[0], pf);
-	free(ld.ld_s);
-	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
+
+	show_location(expr, pf);
+	/* *expr will be cached in libdw. Don't free it. */
 	return ;
 error:
+	/* TODO: Support const_value */
 	die("Failed to find the location of %s at this address.\n"
 	    " Perhaps, it has been optimized out.", pf->var);
 }
 
-static int variable_callback(struct die_link *dlink, void *data)
-{
-	struct probe_finder *pf = (struct probe_finder *)data;
-	Dwarf_Half tag;
-	int ret;
-
-	ret = dwarf_tag(dlink->die, &tag, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	if ((tag == DW_TAG_formal_parameter ||
-	     tag == DW_TAG_variable) &&
-	    (die_compare_name(dlink->die, pf->var) == 0)) {
-		show_variable(dlink->die, pf);
-		return 1;
-	}
-	/* TODO: Support struct members and arrays */
-	return 0;
-}
-
 /* Find a variable in a subprogram die */
-static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf)
+static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
 	int ret;
+	Dwarf_Die vr_die;
 
+	/* TODO: Support struct members and arrays */
 	if (!is_c_varname(pf->var)) {
 		/* Output raw parameters */
 		ret = snprintf(pf->buf, pf->len, " %s", pf->var);
@@ -499,58 +383,51 @@
 
 	pr_debug("Searching '%s' variable in context.\n", pf->var);
 	/* Search child die for local variables and parameters. */
-	ret = search_die_from_children(sp_die, variable_callback, pf);
-	if (!ret)
+	if (!die_find_variable(sp_die, pf->var, &vr_die))
 		die("Failed to find '%s' in this function.", pf->var);
-}
 
-/* Get a frame base on the address */
-static void get_current_frame_base(Dwarf_Die sp_die, struct probe_finder *pf)
-{
-	Dwarf_Attribute attr;
-	int ret;
-
-	ret = dwarf_attr(sp_die, DW_AT_frame_base, &attr, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
-	ret = attr_get_locdesc(attr, &pf->fbloc, (pf->addr - pf->cu_base));
-	DIE_IF(ret != DW_DLV_OK);
-	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
-}
-
-static void free_current_frame_base(struct probe_finder *pf)
-{
-	free(pf->fbloc.ld_s);
-	memset(&pf->fbloc, 0, sizeof(Dwarf_Locdesc));
+	show_variable(&vr_die, pf);
 }
 
 /* Show a probe point to output buffer */
-static void show_probepoint(Dwarf_Die sp_die, Dwarf_Signed offs,
-			    struct probe_finder *pf)
+static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
 	struct probe_point *pp = pf->pp;
-	char *name;
+	Dwarf_Addr eaddr;
+	Dwarf_Die die_mem;
+	const char *name;
 	char tmp[MAX_PROBE_BUFFER];
 	int ret, i, len;
+	Dwarf_Attribute fb_attr;
+	size_t nops;
+
+	/* If no real subprogram, find a real one */
+	if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
+		sp_die = die_get_real_subprogram(&pf->cu_die,
+						 pf->addr, &die_mem);
+		if (!sp_die)
+			die("Probe point is not found in subprograms.");
+	}
 
 	/* Output name of probe point */
-	ret = dwarf_diename(sp_die, &name, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	if (ret == DW_DLV_OK) {
-		ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name,
-				(unsigned int)offs);
+	name = dwarf_diename(sp_die);
+	if (name) {
+		dwarf_entrypc(sp_die, &eaddr);
+		ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%lu", name,
+				(unsigned long)(pf->addr - eaddr));
 		/* Copy the function name if possible */
 		if (!pp->function) {
 			pp->function = strdup(name);
-			pp->offset = offs;
+			pp->offset = (size_t)(pf->addr - eaddr);
 		}
-		dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
 	} else {
 		/* This function has no name. */
-		ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%llx", pf->addr);
+		ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%jx",
+			       (uintmax_t)pf->addr);
 		if (!pp->function) {
 			/* TODO: Use _stext */
 			pp->function = strdup("");
-			pp->offset = (int)pf->addr;
+			pp->offset = (size_t)pf->addr;
 		}
 	}
 	DIE_IF(ret < 0);
@@ -558,8 +435,15 @@
 	len = ret;
 	pr_debug("Probe point found: %s\n", tmp);
 
+	/* Get the frame base attribute/ops */
+	dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
+	ret = dwarf_getlocation_addr(&fb_attr, (pf->addr - pf->cu_base),
+				     &pf->fb_ops, &nops, 1);
+	if (ret <= 0 || nops == 0)
+		pf->fb_ops = NULL;
+
 	/* Find each argument */
-	get_current_frame_base(sp_die, pf);
+	/* TODO: use dwarf_cfi_addrframe */
 	for (i = 0; i < pp->nr_args; i++) {
 		pf->var = pp->args[i];
 		pf->buf = &tmp[len];
@@ -567,289 +451,327 @@
 		find_variable(sp_die, pf);
 		len += strlen(pf->buf);
 	}
-	free_current_frame_base(pf);
+
+	/* *pf->fb_ops will be cached in libdw. Don't free it. */
+	pf->fb_ops = NULL;
 
 	pp->probes[pp->found] = strdup(tmp);
 	pp->found++;
 }
 
-static int probeaddr_callback(struct die_link *dlink, void *data)
-{
-	struct probe_finder *pf = (struct probe_finder *)data;
-	Dwarf_Half tag;
-	Dwarf_Signed offs;
-	int ret;
-
-	ret = dwarf_tag(dlink->die, &tag, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	/* Check the address is in this subprogram */
-	if (tag == DW_TAG_subprogram &&
-	    die_within_subprogram(dlink->die, pf->addr, &offs)) {
-		show_probepoint(dlink->die, offs, pf);
-		return 1;
-	}
-	return 0;
-}
-
 /* Find probe point from its line number */
 static void find_probe_point_by_line(struct probe_finder *pf)
 {
-	Dwarf_Signed cnt, i, clm;
-	Dwarf_Line *lines;
-	Dwarf_Unsigned lineno = 0;
+	Dwarf_Lines *lines;
+	Dwarf_Line *line;
+	size_t nlines, i;
 	Dwarf_Addr addr;
-	Dwarf_Unsigned fno;
+	int lineno;
 	int ret;
 
-	ret = dwarf_srclines(pf->cu_die, &lines, &cnt, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
+	ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines);
+	DIE_IF(ret != 0);
 
-	for (i = 0; i < cnt; i++) {
-		ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error);
-		DIE_IF(ret != DW_DLV_OK);
-		if (fno != pf->fno)
-			continue;
-
-		ret = dwarf_lineno(lines[i], &lineno, &__dw_error);
-		DIE_IF(ret != DW_DLV_OK);
+	for (i = 0; i < nlines; i++) {
+		line = dwarf_onesrcline(lines, i);
+		dwarf_lineno(line, &lineno);
 		if (lineno != pf->lno)
 			continue;
 
-		ret = dwarf_lineoff(lines[i], &clm, &__dw_error);
-		DIE_IF(ret != DW_DLV_OK);
+		/* TODO: Get fileno from line, but how? */
+		if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
+			continue;
 
-		ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
-		DIE_IF(ret != DW_DLV_OK);
-		pr_debug("Probe line found: line[%d]:%u,%d addr:0x%llx\n",
-			 (int)i, (unsigned)lineno, (int)clm, addr);
+		ret = dwarf_lineaddr(line, &addr);
+		DIE_IF(ret != 0);
+		pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
+			 (int)i, lineno, (uintmax_t)addr);
 		pf->addr = addr;
-		/* Search a real subprogram including this line, */
-		ret = search_die_from_children(pf->cu_die,
-					       probeaddr_callback, pf);
-		if (ret == 0)
-			die("Probe point is not found in subprograms.");
+
+		show_probe_point(NULL, pf);
 		/* Continuing, because target line might be inlined. */
 	}
-	dwarf_srclines_dealloc(__dw_debug, lines, cnt);
 }
 
-/* Search function from function name */
-static int probefunc_callback(struct die_link *dlink, void *data)
+/* Find lines which match lazy pattern */
+static int find_lazy_match_lines(struct list_head *head,
+				 const char *fname, const char *pat)
+{
+	char *fbuf, *p1, *p2;
+	int fd, line, nlines = 0;
+	struct stat st;
+
+	fd = open(fname, O_RDONLY);
+	if (fd < 0)
+		die("failed to open %s", fname);
+	DIE_IF(fstat(fd, &st) < 0);
+	fbuf = malloc(st.st_size + 2);
+	DIE_IF(fbuf == NULL);
+	DIE_IF(read(fd, fbuf, st.st_size) < 0);
+	close(fd);
+	fbuf[st.st_size] = '\n';	/* Dummy line */
+	fbuf[st.st_size + 1] = '\0';
+	p1 = fbuf;
+	line = 1;
+	while ((p2 = strchr(p1, '\n')) != NULL) {
+		*p2 = '\0';
+		if (strlazymatch(p1, pat)) {
+			line_list__add_line(head, line);
+			nlines++;
+		}
+		line++;
+		p1 = p2 + 1;
+	}
+	free(fbuf);
+	return nlines;
+}
+
+/* Find probe points from lazy pattern  */
+static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
+{
+	Dwarf_Lines *lines;
+	Dwarf_Line *line;
+	size_t nlines, i;
+	Dwarf_Addr addr;
+	Dwarf_Die die_mem;
+	int lineno;
+	int ret;
+
+	if (list_empty(&pf->lcache)) {
+		/* Matching lazy line pattern */
+		ret = find_lazy_match_lines(&pf->lcache, pf->fname,
+					    pf->pp->lazy_line);
+		if (ret <= 0)
+			die("No matched lines found in %s.", pf->fname);
+	}
+
+	ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines);
+	DIE_IF(ret != 0);
+	for (i = 0; i < nlines; i++) {
+		line = dwarf_onesrcline(lines, i);
+
+		dwarf_lineno(line, &lineno);
+		if (!line_list__has_line(&pf->lcache, lineno))
+			continue;
+
+		/* TODO: Get fileno from line, but how? */
+		if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
+			continue;
+
+		ret = dwarf_lineaddr(line, &addr);
+		DIE_IF(ret != 0);
+		if (sp_die) {
+			/* Address filtering 1: does sp_die include addr? */
+			if (!dwarf_haspc(sp_die, addr))
+				continue;
+			/* Address filtering 2: No child include addr? */
+			if (die_get_inlinefunc(sp_die, addr, &die_mem))
+				continue;
+		}
+
+		pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
+			 (int)i, lineno, (unsigned long long)addr);
+		pf->addr = addr;
+
+		show_probe_point(sp_die, pf);
+		/* Continuing, because target line might be inlined. */
+	}
+	/* TODO: deallocate lines, but how? */
+}
+
+static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
 {
 	struct probe_finder *pf = (struct probe_finder *)data;
 	struct probe_point *pp = pf->pp;
-	struct die_link *lk;
-	Dwarf_Signed offs;
-	Dwarf_Half tag;
-	int ret;
 
-	ret = dwarf_tag(dlink->die, &tag, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	if (tag == DW_TAG_subprogram) {
-		if (die_compare_name(dlink->die, pp->function) == 0) {
-			if (pp->line) {	/* Function relative line */
-				pf->fno = die_get_decl_file(dlink->die);
-				pf->lno = die_get_decl_line(dlink->die)
-					 + pp->line;
-				find_probe_point_by_line(pf);
-				return 1;
-			}
-			if (die_inlined_subprogram(dlink->die)) {
-				/* Inlined function, save it. */
-				ret = dwarf_die_CU_offset(dlink->die,
-							  &pf->inl_offs,
-							  &__dw_error);
-				DIE_IF(ret != DW_DLV_OK);
-				pr_debug("inline definition offset %lld\n",
-					 pf->inl_offs);
-				return 0;	/* Continue to search */
-			}
-			/* Get probe address */
-			pf->addr = die_get_entrypc(dlink->die);
+	if (pp->lazy_line)
+		find_probe_point_lazy(in_die, pf);
+	else {
+		/* Get probe address */
+		pf->addr = die_get_entrypc(in_die);
+		pf->addr += pp->offset;
+		pr_debug("found inline addr: 0x%jx\n",
+			 (uintmax_t)pf->addr);
+
+		show_probe_point(in_die, pf);
+	}
+
+	return DWARF_CB_OK;
+}
+
+/* Search function from function name */
+static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
+{
+	struct probe_finder *pf = (struct probe_finder *)data;
+	struct probe_point *pp = pf->pp;
+
+	/* Check tag and diename */
+	if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
+	    die_compare_name(sp_die, pp->function) != 0)
+		return 0;
+
+	pf->fname = dwarf_decl_file(sp_die);
+	if (pp->line) { /* Function relative line */
+		dwarf_decl_line(sp_die, &pf->lno);
+		pf->lno += pp->line;
+		find_probe_point_by_line(pf);
+	} else if (!dwarf_func_inline(sp_die)) {
+		/* Real function */
+		if (pp->lazy_line)
+			find_probe_point_lazy(sp_die, pf);
+		else {
+			pf->addr = die_get_entrypc(sp_die);
 			pf->addr += pp->offset;
 			/* TODO: Check the address in this function */
-			show_probepoint(dlink->die, pp->offset, pf);
-			return 1; /* Exit; no same symbol in this CU. */
+			show_probe_point(sp_die, pf);
 		}
-	} else if (tag == DW_TAG_inlined_subroutine && pf->inl_offs) {
-		if (die_get_abstract_origin(dlink->die) == pf->inl_offs) {
-			/* Get probe address */
-			pf->addr = die_get_entrypc(dlink->die);
-			pf->addr += pp->offset;
-			pr_debug("found inline addr: 0x%llx\n", pf->addr);
-			/* Inlined function. Get a real subprogram */
-			for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
-				tag = 0;
-				dwarf_tag(lk->die, &tag, &__dw_error);
-				DIE_IF(ret == DW_DLV_ERROR);
-				if (tag == DW_TAG_subprogram &&
-				    !die_inlined_subprogram(lk->die))
-					goto found;
-			}
-			die("Failed to find real subprogram.");
-found:
-			/* Get offset from subprogram */
-			ret = die_within_subprogram(lk->die, pf->addr, &offs);
-			DIE_IF(!ret);
-			show_probepoint(lk->die, offs, pf);
-			/* Continue to search */
-		}
-	}
-	return 0;
+	} else
+		/* Inlined function: search instances */
+		dwarf_func_inline_instances(sp_die, probe_point_inline_cb, pf);
+
+	return 1; /* Exit; no same symbol in this CU. */
 }
 
 static void find_probe_point_by_func(struct probe_finder *pf)
 {
-	search_die_from_children(pf->cu_die, probefunc_callback, pf);
+	dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, pf, 0);
 }
 
 /* Find a probe point */
-int find_probepoint(int fd, struct probe_point *pp)
+int find_probe_point(int fd, struct probe_point *pp)
 {
-	Dwarf_Half addr_size = 0;
-	Dwarf_Unsigned next_cuh = 0;
-	int cu_number = 0, ret;
 	struct probe_finder pf = {.pp = pp};
+	int ret;
+	Dwarf_Off off, noff;
+	size_t cuhl;
+	Dwarf_Die *diep;
+	Dwarf *dbg;
 
-	ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
-	if (ret != DW_DLV_OK)
+	dbg = dwarf_begin(fd, DWARF_C_READ);
+	if (!dbg)
 		return -ENOENT;
 
 	pp->found = 0;
-	while (++cu_number) {
-		/* Search CU (Compilation Unit) */
-		ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL,
-			&addr_size, &next_cuh, &__dw_error);
-		DIE_IF(ret == DW_DLV_ERROR);
-		if (ret == DW_DLV_NO_ENTRY)
-			break;
-
+	off = 0;
+	line_list__init(&pf.lcache);
+	/* Loop on CUs (Compilation Unit) */
+	while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
 		/* Get the DIE(Debugging Information Entry) of this CU */
-		ret = dwarf_siblingof(__dw_debug, 0, &pf.cu_die, &__dw_error);
-		DIE_IF(ret != DW_DLV_OK);
+		diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die);
+		if (!diep)
+			continue;
 
 		/* Check if target file is included. */
 		if (pp->file)
-			pf.fno = cu_find_fileno(pf.cu_die, pp->file);
+			pf.fname = cu_find_realpath(&pf.cu_die, pp->file);
+		else
+			pf.fname = NULL;
 
-		if (!pp->file || pf.fno) {
+		if (!pp->file || pf.fname) {
 			/* Save CU base address (for frame_base) */
-			ret = dwarf_lowpc(pf.cu_die, &pf.cu_base, &__dw_error);
-			DIE_IF(ret == DW_DLV_ERROR);
-			if (ret == DW_DLV_NO_ENTRY)
+			ret = dwarf_lowpc(&pf.cu_die, &pf.cu_base);
+			if (ret != 0)
 				pf.cu_base = 0;
 			if (pp->function)
 				find_probe_point_by_func(&pf);
+			else if (pp->lazy_line)
+				find_probe_point_lazy(NULL, &pf);
 			else {
 				pf.lno = pp->line;
 				find_probe_point_by_line(&pf);
 			}
 		}
-		dwarf_dealloc(__dw_debug, pf.cu_die, DW_DLA_DIE);
+		off = noff;
 	}
-	ret = dwarf_finish(__dw_debug, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
+	line_list__free(&pf.lcache);
+	dwarf_end(dbg);
 
 	return pp->found;
 }
 
-
-static void line_range_add_line(struct line_range *lr, unsigned int line)
-{
-	struct line_node *ln;
-	struct list_head *p;
-
-	/* Reverse search, because new line will be the last one */
-	list_for_each_entry_reverse(ln, &lr->line_list, list) {
-		if (ln->line < line) {
-			p = &ln->list;
-			goto found;
-		} else if (ln->line == line)	/* Already exist */
-			return ;
-	}
-	/* List is empty, or the smallest entry */
-	p = &lr->line_list;
-found:
-	pr_debug("Debug: add a line %u\n", line);
-	ln = zalloc(sizeof(struct line_node));
-	DIE_IF(ln == NULL);
-	ln->line = line;
-	INIT_LIST_HEAD(&ln->list);
-	list_add(&ln->list, p);
-}
-
 /* Find line range from its line number */
-static void find_line_range_by_line(struct line_finder *lf)
+static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
 {
-	Dwarf_Signed cnt, i;
-	Dwarf_Line *lines;
-	Dwarf_Unsigned lineno = 0;
-	Dwarf_Unsigned fno;
+	Dwarf_Lines *lines;
+	Dwarf_Line *line;
+	size_t nlines, i;
 	Dwarf_Addr addr;
+	int lineno;
 	int ret;
+	const char *src;
+	Dwarf_Die die_mem;
 
-	ret = dwarf_srclines(lf->cu_die, &lines, &cnt, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
+	line_list__init(&lf->lr->line_list);
+	ret = dwarf_getsrclines(&lf->cu_die, &lines, &nlines);
+	DIE_IF(ret != 0);
 
-	for (i = 0; i < cnt; i++) {
-		ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error);
-		DIE_IF(ret != DW_DLV_OK);
-		if (fno != lf->fno)
-			continue;
-
-		ret = dwarf_lineno(lines[i], &lineno, &__dw_error);
-		DIE_IF(ret != DW_DLV_OK);
+	for (i = 0; i < nlines; i++) {
+		line = dwarf_onesrcline(lines, i);
+		ret = dwarf_lineno(line, &lineno);
+		DIE_IF(ret != 0);
 		if (lf->lno_s > lineno || lf->lno_e < lineno)
 			continue;
 
-		/* Filter line in the function address range */
-		if (lf->addr_s && lf->addr_e) {
-			ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
-			DIE_IF(ret != DW_DLV_OK);
-			if (lf->addr_s > addr || lf->addr_e <= addr)
+		if (sp_die) {
+			/* Address filtering 1: does sp_die include addr? */
+			ret = dwarf_lineaddr(line, &addr);
+			DIE_IF(ret != 0);
+			if (!dwarf_haspc(sp_die, addr))
+				continue;
+
+			/* Address filtering 2: No child include addr? */
+			if (die_get_inlinefunc(sp_die, addr, &die_mem))
 				continue;
 		}
-		line_range_add_line(lf->lr, (unsigned int)lineno);
+
+		/* TODO: Get fileno from line, but how? */
+		src = dwarf_linesrc(line, NULL, NULL);
+		if (strtailcmp(src, lf->fname) != 0)
+			continue;
+
+		/* Copy real path */
+		if (!lf->lr->path)
+			lf->lr->path = strdup(src);
+		line_list__add_line(&lf->lr->line_list, (unsigned int)lineno);
 	}
-	dwarf_srclines_dealloc(__dw_debug, lines, cnt);
+	/* Update status */
 	if (!list_empty(&lf->lr->line_list))
 		lf->found = 1;
+	else {
+		free(lf->lr->path);
+		lf->lr->path = NULL;
+	}
+}
+
+static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
+{
+	find_line_range_by_line(in_die, (struct line_finder *)data);
+	return DWARF_CB_ABORT;	/* No need to find other instances */
 }
 
 /* Search function from function name */
-static int linefunc_callback(struct die_link *dlink, void *data)
+static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
 {
 	struct line_finder *lf = (struct line_finder *)data;
 	struct line_range *lr = lf->lr;
-	Dwarf_Half tag;
-	int ret;
 
-	ret = dwarf_tag(dlink->die, &tag, &__dw_error);
-	DIE_IF(ret == DW_DLV_ERROR);
-	if (tag == DW_TAG_subprogram &&
-	    die_compare_name(dlink->die, lr->function) == 0) {
-		/* Get the address range of this function */
-		ret = dwarf_highpc(dlink->die, &lf->addr_e, &__dw_error);
-		if (ret == DW_DLV_OK)
-			ret = dwarf_lowpc(dlink->die, &lf->addr_s, &__dw_error);
-		DIE_IF(ret == DW_DLV_ERROR);
-		if (ret == DW_DLV_NO_ENTRY) {
-			lf->addr_s = 0;
-			lf->addr_e = 0;
-		}
-
-		lf->fno = die_get_decl_file(dlink->die);
-		lr->offset = die_get_decl_line(dlink->die);;
+	if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
+	    die_compare_name(sp_die, lr->function) == 0) {
+		lf->fname = dwarf_decl_file(sp_die);
+		dwarf_decl_line(sp_die, &lr->offset);
+		pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
 		lf->lno_s = lr->offset + lr->start;
 		if (!lr->end)
-			lf->lno_e = (Dwarf_Unsigned)-1;
+			lf->lno_e = INT_MAX;
 		else
 			lf->lno_e = lr->offset + lr->end;
 		lr->start = lf->lno_s;
 		lr->end = lf->lno_e;
-		find_line_range_by_line(lf);
-		/* If we find a target function, this should be end. */
-		lf->found = 1;
+		if (dwarf_func_inline(sp_die))
+			dwarf_func_inline_instances(sp_die,
+						    line_range_inline_cb, lf);
+		else
+			find_line_range_by_line(sp_die, lf);
 		return 1;
 	}
 	return 0;
@@ -857,55 +779,55 @@
 
 static void find_line_range_by_func(struct line_finder *lf)
 {
-	search_die_from_children(lf->cu_die, linefunc_callback, lf);
+	dwarf_getfuncs(&lf->cu_die, line_range_search_cb, lf, 0);
 }
 
 int find_line_range(int fd, struct line_range *lr)
 {
-	Dwarf_Half addr_size = 0;
-	Dwarf_Unsigned next_cuh = 0;
+	struct line_finder lf = {.lr = lr, .found = 0};
 	int ret;
-	struct line_finder lf = {.lr = lr};
+	Dwarf_Off off = 0, noff;
+	size_t cuhl;
+	Dwarf_Die *diep;
+	Dwarf *dbg;
 
-	ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
-	if (ret != DW_DLV_OK)
+	dbg = dwarf_begin(fd, DWARF_C_READ);
+	if (!dbg)
 		return -ENOENT;
 
+	/* Loop on CUs (Compilation Unit) */
 	while (!lf.found) {
-		/* Search CU (Compilation Unit) */
-		ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL,
-			&addr_size, &next_cuh, &__dw_error);
-		DIE_IF(ret == DW_DLV_ERROR);
-		if (ret == DW_DLV_NO_ENTRY)
+		ret = dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL);
+		if (ret != 0)
 			break;
 
 		/* Get the DIE(Debugging Information Entry) of this CU */
-		ret = dwarf_siblingof(__dw_debug, 0, &lf.cu_die, &__dw_error);
-		DIE_IF(ret != DW_DLV_OK);
+		diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die);
+		if (!diep)
+			continue;
 
 		/* Check if target file is included. */
 		if (lr->file)
-			lf.fno = cu_find_fileno(lf.cu_die, lr->file);
+			lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
+		else
+			lf.fname = 0;
 
-		if (!lr->file || lf.fno) {
+		if (!lr->file || lf.fname) {
 			if (lr->function)
 				find_line_range_by_func(&lf);
 			else {
 				lf.lno_s = lr->start;
 				if (!lr->end)
-					lf.lno_e = (Dwarf_Unsigned)-1;
+					lf.lno_e = INT_MAX;
 				else
 					lf.lno_e = lr->end;
-				find_line_range_by_line(&lf);
+				find_line_range_by_line(NULL, &lf);
 			}
-			/* Get the real file path */
-			if (lf.found)
-				cu_get_filename(lf.cu_die, lf.fno, &lr->path);
 		}
-		dwarf_dealloc(__dw_debug, lf.cu_die, DW_DLA_DIE);
+		off = noff;
 	}
-	ret = dwarf_finish(__dw_debug, &__dw_error);
-	DIE_IF(ret != DW_DLV_OK);
+	pr_debug("path: %lx\n", (unsigned long)lr->path);
+	dwarf_end(dbg);
 	return lf.found;
 }
 
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 972b386..d1a6517 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -1,6 +1,7 @@
 #ifndef _PROBE_FINDER_H
 #define _PROBE_FINDER_H
 
+#include <stdbool.h>
 #include "util.h"
 
 #define MAX_PATH_LEN		 256
@@ -20,6 +21,7 @@
 	/* Inputs */
 	char			*file;			/* File name */
 	int			line;			/* Line number */
+	char			*lazy_line;		/* Lazy line pattern */
 
 	char			*function;		/* Function name */
 	int			offset;			/* Offset bytes */
@@ -46,53 +48,46 @@
 	char			*function;		/* Function name */
 	unsigned int		start;			/* Start line number */
 	unsigned int		end;			/* End line number */
-	unsigned int		offset;			/* Start line offset */
+	int			offset;			/* Start line offset */
 	char			*path;			/* Real path name */
 	struct list_head	line_list;		/* Visible lines */
 };
 
-#ifndef NO_LIBDWARF
-extern int find_probepoint(int fd, struct probe_point *pp);
+#ifndef NO_DWARF_SUPPORT
+extern int find_probe_point(int fd, struct probe_point *pp);
 extern int find_line_range(int fd, struct line_range *lr);
 
-/* Workaround for undefined _MIPS_SZLONG bug in libdwarf.h: */
-#ifndef _MIPS_SZLONG
-# define _MIPS_SZLONG		0
-#endif
-
 #include <dwarf.h>
-#include <libdwarf.h>
+#include <libdw.h>
 
 struct probe_finder {
-	struct probe_point	*pp;			/* Target probe point */
+	struct probe_point	*pp;		/* Target probe point */
 
 	/* For function searching */
-	Dwarf_Addr		addr;			/* Address */
-	Dwarf_Unsigned		fno;			/* File number */
-	Dwarf_Unsigned		lno;			/* Line number */
-	Dwarf_Off		inl_offs;		/* Inline offset */
-	Dwarf_Die		cu_die;			/* Current CU */
+	Dwarf_Addr		addr;		/* Address */
+	const char		*fname;		/* File name */
+	int			lno;		/* Line number */
+	Dwarf_Die		cu_die;		/* Current CU */
 
 	/* For variable searching */
-	Dwarf_Addr		cu_base;		/* Current CU base address */
-	Dwarf_Locdesc		fbloc;			/* Location of Current Frame Base */
-	const char		*var;			/* Current variable name */
-	char			*buf;			/* Current output buffer */
-	int			len;			/* Length of output buffer */
+	Dwarf_Op		*fb_ops;	/* Frame base attribute */
+	Dwarf_Addr		cu_base;	/* Current CU base address */
+	const char		*var;		/* Current variable name */
+	char			*buf;		/* Current output buffer */
+	int			len;		/* Length of output buffer */
+	struct list_head	lcache;		/* Line cache for lazy match */
 };
 
 struct line_finder {
-	struct line_range	*lr;			/* Target line range */
+	struct line_range	*lr;		/* Target line range */
 
-	Dwarf_Unsigned		fno;			/* File number */
-	Dwarf_Unsigned		lno_s;			/* Start line number */
-	Dwarf_Unsigned		lno_e;			/* End line number */
-	Dwarf_Addr		addr_s;			/* Start address */
-	Dwarf_Addr		addr_e;			/* End address */
-	Dwarf_Die		cu_die;			/* Current CU */
+	const char		*fname;		/* File name */
+	int			lno_s;		/* Start line number */
+	int			lno_e;		/* End line number */
+	Dwarf_Die		cu_die;		/* Current CU */
 	int			found;
 };
 
-#endif /* NO_LIBDWARF */
+#endif /* NO_DWARF_SUPPORT */
 
 #endif /*_PROBE_FINDER_H */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index c397d4f..a175949 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -265,21 +265,21 @@
 	return false;
 }
 
-/**
- * strglobmatch - glob expression pattern matching
- * @str: the target string to match
- * @pat: the pattern string to match
- *
- * This returns true if the @str matches @pat. @pat can includes wildcards
- * ('*','?') and character classes ([CHARS], complementation and ranges are
- * also supported). Also, this supports escape character ('\') to use special
- * characters as normal character.
- *
- * Note: if @pat syntax is broken, this always returns false.
- */
-bool strglobmatch(const char *str, const char *pat)
+/* Glob/lazy pattern matching */
+static bool __match_glob(const char *str, const char *pat, bool ignore_space)
 {
 	while (*str && *pat && *pat != '*') {
+		if (ignore_space) {
+			/* Ignore spaces for lazy matching */
+			if (isspace(*str)) {
+				str++;
+				continue;
+			}
+			if (isspace(*pat)) {
+				pat++;
+				continue;
+			}
+		}
 		if (*pat == '?') {	/* Matches any single character */
 			str++;
 			pat++;
@@ -308,3 +308,32 @@
 	return !*str && !*pat;
 }
 
+/**
+ * strglobmatch - glob expression pattern matching
+ * @str: the target string to match
+ * @pat: the pattern string to match
+ *
+ * This returns true if the @str matches @pat. @pat can includes wildcards
+ * ('*','?') and character classes ([CHARS], complementation and ranges are
+ * also supported). Also, this supports escape character ('\') to use special
+ * characters as normal character.
+ *
+ * Note: if @pat syntax is broken, this always returns false.
+ */
+bool strglobmatch(const char *str, const char *pat)
+{
+	return __match_glob(str, pat, false);
+}
+
+/**
+ * strlazymatch - matching pattern strings lazily with glob pattern
+ * @str: the target string to match
+ * @pat: the pattern string to match
+ *
+ * This is similar to strglobmatch, except this ignores spaces in
+ * the target string.
+ */
+bool strlazymatch(const char *str, const char *pat)
+{
+	return __match_glob(str, pat, true);
+}
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index 02ede58..542e44d 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -10,6 +10,7 @@
 char **argv_split(const char *str, int *argcp);
 void argv_free(char **argv);
 bool strglobmatch(const char *str, const char *pat);
+bool strlazymatch(const char *str, const char *pat);
 
 #define _STR(x) #x
 #define STR(x) _STR(x)
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index daece36..7f1178f 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -12,3 +12,6 @@
 
 config KVM_APIC_ARCHITECTURE
        bool
+
+config KVM_MMIO
+       bool
diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c
index f73de63..057e2cc 100644
--- a/virt/kvm/assigned-dev.c
+++ b/virt/kvm/assigned-dev.c
@@ -504,12 +504,12 @@
 static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
 				      struct kvm_assigned_pci_dev *assigned_dev)
 {
-	int r = 0;
+	int r = 0, idx;
 	struct kvm_assigned_dev_kernel *match;
 	struct pci_dev *dev;
 
 	mutex_lock(&kvm->lock);
-	down_read(&kvm->slots_lock);
+	idx = srcu_read_lock(&kvm->srcu);
 
 	match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
 				      assigned_dev->assigned_dev_id);
@@ -526,7 +526,8 @@
 		r = -ENOMEM;
 		goto out;
 	}
-	dev = pci_get_bus_and_slot(assigned_dev->busnr,
+	dev = pci_get_domain_bus_and_slot(assigned_dev->segnr,
+				   assigned_dev->busnr,
 				   assigned_dev->devfn);
 	if (!dev) {
 		printk(KERN_INFO "%s: host device not found\n", __func__);
@@ -548,6 +549,7 @@
 	pci_reset_function(dev);
 
 	match->assigned_dev_id = assigned_dev->assigned_dev_id;
+	match->host_segnr = assigned_dev->segnr;
 	match->host_busnr = assigned_dev->busnr;
 	match->host_devfn = assigned_dev->devfn;
 	match->flags = assigned_dev->flags;
@@ -573,7 +575,7 @@
 	}
 
 out:
-	up_read(&kvm->slots_lock);
+	srcu_read_unlock(&kvm->srcu, idx);
 	mutex_unlock(&kvm->lock);
 	return r;
 out_list_del:
@@ -585,7 +587,7 @@
 	pci_dev_put(dev);
 out_free:
 	kfree(match);
-	up_read(&kvm->slots_lock);
+	srcu_read_unlock(&kvm->srcu, idx);
 	mutex_unlock(&kvm->lock);
 	return r;
 }
diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c
index 04d69cd..5169736 100644
--- a/virt/kvm/coalesced_mmio.c
+++ b/virt/kvm/coalesced_mmio.c
@@ -92,41 +92,64 @@
 int kvm_coalesced_mmio_init(struct kvm *kvm)
 {
 	struct kvm_coalesced_mmio_dev *dev;
+	struct page *page;
 	int ret;
 
+	ret = -ENOMEM;
+	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+	if (!page)
+		goto out_err;
+	kvm->coalesced_mmio_ring = page_address(page);
+
+	ret = -ENOMEM;
 	dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), GFP_KERNEL);
 	if (!dev)
-		return -ENOMEM;
+		goto out_free_page;
 	spin_lock_init(&dev->lock);
 	kvm_iodevice_init(&dev->dev, &coalesced_mmio_ops);
 	dev->kvm = kvm;
 	kvm->coalesced_mmio_dev = dev;
 
-	ret = kvm_io_bus_register_dev(kvm, &kvm->mmio_bus, &dev->dev);
+	mutex_lock(&kvm->slots_lock);
+	ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, &dev->dev);
+	mutex_unlock(&kvm->slots_lock);
 	if (ret < 0)
-		kfree(dev);
+		goto out_free_dev;
 
 	return ret;
+
+out_free_dev:
+	kfree(dev);
+out_free_page:
+	__free_page(page);
+out_err:
+	return ret;
 }
 
+void kvm_coalesced_mmio_free(struct kvm *kvm)
+{
+	if (kvm->coalesced_mmio_ring)
+		free_page((unsigned long)kvm->coalesced_mmio_ring);
+}
+
 int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
-				         struct kvm_coalesced_mmio_zone *zone)
+					 struct kvm_coalesced_mmio_zone *zone)
 {
 	struct kvm_coalesced_mmio_dev *dev = kvm->coalesced_mmio_dev;
 
 	if (dev == NULL)
 		return -EINVAL;
 
-	down_write(&kvm->slots_lock);
+	mutex_lock(&kvm->slots_lock);
 	if (dev->nb_zones >= KVM_COALESCED_MMIO_ZONE_MAX) {
-		up_write(&kvm->slots_lock);
+		mutex_unlock(&kvm->slots_lock);
 		return -ENOBUFS;
 	}
 
 	dev->zone[dev->nb_zones] = *zone;
 	dev->nb_zones++;
 
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 	return 0;
 }
 
@@ -140,10 +163,10 @@
 	if (dev == NULL)
 		return -EINVAL;
 
-	down_write(&kvm->slots_lock);
+	mutex_lock(&kvm->slots_lock);
 
 	i = dev->nb_zones;
-	while(i) {
+	while (i) {
 		z = &dev->zone[i - 1];
 
 		/* unregister all zones
@@ -158,7 +181,7 @@
 		i--;
 	}
 
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 
 	return 0;
 }
diff --git a/virt/kvm/coalesced_mmio.h b/virt/kvm/coalesced_mmio.h
index 4b49f27..8a5959e 100644
--- a/virt/kvm/coalesced_mmio.h
+++ b/virt/kvm/coalesced_mmio.h
@@ -1,3 +1,6 @@
+#ifndef __KVM_COALESCED_MMIO_H__
+#define __KVM_COALESCED_MMIO_H__
+
 /*
  * KVM coalesced MMIO
  *
@@ -7,6 +10,8 @@
  *
  */
 
+#ifdef CONFIG_KVM_MMIO
+
 #define KVM_COALESCED_MMIO_ZONE_MAX 100
 
 struct kvm_coalesced_mmio_dev {
@@ -18,7 +23,17 @@
 };
 
 int kvm_coalesced_mmio_init(struct kvm *kvm);
+void kvm_coalesced_mmio_free(struct kvm *kvm);
 int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
                                        struct kvm_coalesced_mmio_zone *zone);
 int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm,
                                          struct kvm_coalesced_mmio_zone *zone);
+
+#else
+
+static inline int kvm_coalesced_mmio_init(struct kvm *kvm) { return 0; }
+static inline void kvm_coalesced_mmio_free(struct kvm *kvm) { }
+
+#endif
+
+#endif
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index a9d3fc6..7016319 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -47,7 +47,6 @@
 	int                       gsi;
 	struct list_head          list;
 	poll_table                pt;
-	wait_queue_head_t        *wqh;
 	wait_queue_t              wait;
 	struct work_struct        inject;
 	struct work_struct        shutdown;
@@ -159,8 +158,6 @@
 			poll_table *pt)
 {
 	struct _irqfd *irqfd = container_of(pt, struct _irqfd, pt);
-
-	irqfd->wqh = wqh;
 	add_wait_queue(wqh, &irqfd->wait);
 }
 
@@ -463,7 +460,7 @@
 kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 {
 	int                       pio = args->flags & KVM_IOEVENTFD_FLAG_PIO;
-	struct kvm_io_bus        *bus = pio ? &kvm->pio_bus : &kvm->mmio_bus;
+	enum kvm_bus              bus_idx = pio ? KVM_PIO_BUS : KVM_MMIO_BUS;
 	struct _ioeventfd        *p;
 	struct eventfd_ctx       *eventfd;
 	int                       ret;
@@ -508,7 +505,7 @@
 	else
 		p->wildcard = true;
 
-	down_write(&kvm->slots_lock);
+	mutex_lock(&kvm->slots_lock);
 
 	/* Verify that there isnt a match already */
 	if (ioeventfd_check_collision(kvm, p)) {
@@ -518,18 +515,18 @@
 
 	kvm_iodevice_init(&p->dev, &ioeventfd_ops);
 
-	ret = __kvm_io_bus_register_dev(bus, &p->dev);
+	ret = kvm_io_bus_register_dev(kvm, bus_idx, &p->dev);
 	if (ret < 0)
 		goto unlock_fail;
 
 	list_add_tail(&p->list, &kvm->ioeventfds);
 
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 
 	return 0;
 
 unlock_fail:
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 
 fail:
 	kfree(p);
@@ -542,7 +539,7 @@
 kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 {
 	int                       pio = args->flags & KVM_IOEVENTFD_FLAG_PIO;
-	struct kvm_io_bus        *bus = pio ? &kvm->pio_bus : &kvm->mmio_bus;
+	enum kvm_bus              bus_idx = pio ? KVM_PIO_BUS : KVM_MMIO_BUS;
 	struct _ioeventfd        *p, *tmp;
 	struct eventfd_ctx       *eventfd;
 	int                       ret = -ENOENT;
@@ -551,7 +548,7 @@
 	if (IS_ERR(eventfd))
 		return PTR_ERR(eventfd);
 
-	down_write(&kvm->slots_lock);
+	mutex_lock(&kvm->slots_lock);
 
 	list_for_each_entry_safe(p, tmp, &kvm->ioeventfds, list) {
 		bool wildcard = !(args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH);
@@ -565,13 +562,13 @@
 		if (!p->wildcard && p->datamatch != args->datamatch)
 			continue;
 
-		__kvm_io_bus_unregister_dev(bus, &p->dev);
+		kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev);
 		ioeventfd_release(p);
 		ret = 0;
 		break;
 	}
 
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 
 	eventfd_ctx_put(eventfd);
 
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 38a2d20..3db15a8 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -100,6 +100,19 @@
 	return injected;
 }
 
+static void update_handled_vectors(struct kvm_ioapic *ioapic)
+{
+	DECLARE_BITMAP(handled_vectors, 256);
+	int i;
+
+	memset(handled_vectors, 0, sizeof(handled_vectors));
+	for (i = 0; i < IOAPIC_NUM_PINS; ++i)
+		__set_bit(ioapic->redirtbl[i].fields.vector, handled_vectors);
+	memcpy(ioapic->handled_vectors, handled_vectors,
+	       sizeof(handled_vectors));
+	smp_wmb();
+}
+
 static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
 {
 	unsigned index;
@@ -134,6 +147,7 @@
 			e->bits |= (u32) val;
 			e->fields.remote_irr = 0;
 		}
+		update_handled_vectors(ioapic);
 		mask_after = e->fields.mask;
 		if (mask_before != mask_after)
 			kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after);
@@ -241,6 +255,9 @@
 {
 	struct kvm_ioapic *ioapic = kvm->arch.vioapic;
 
+	smp_rmb();
+	if (!test_bit(vector, ioapic->handled_vectors))
+		return;
 	mutex_lock(&ioapic->lock);
 	__kvm_ioapic_update_eoi(ioapic, vector, trigger_mode);
 	mutex_unlock(&ioapic->lock);
@@ -352,6 +369,7 @@
 	ioapic->ioregsel = 0;
 	ioapic->irr = 0;
 	ioapic->id = 0;
+	update_handled_vectors(ioapic);
 }
 
 static const struct kvm_io_device_ops ioapic_mmio_ops = {
@@ -372,13 +390,28 @@
 	kvm_ioapic_reset(ioapic);
 	kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops);
 	ioapic->kvm = kvm;
-	ret = kvm_io_bus_register_dev(kvm, &kvm->mmio_bus, &ioapic->dev);
-	if (ret < 0)
+	mutex_lock(&kvm->slots_lock);
+	ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, &ioapic->dev);
+	mutex_unlock(&kvm->slots_lock);
+	if (ret < 0) {
+		kvm->arch.vioapic = NULL;
 		kfree(ioapic);
+	}
 
 	return ret;
 }
 
+void kvm_ioapic_destroy(struct kvm *kvm)
+{
+	struct kvm_ioapic *ioapic = kvm->arch.vioapic;
+
+	if (ioapic) {
+		kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &ioapic->dev);
+		kvm->arch.vioapic = NULL;
+		kfree(ioapic);
+	}
+}
+
 int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)
 {
 	struct kvm_ioapic *ioapic = ioapic_irqchip(kvm);
@@ -399,6 +432,7 @@
 
 	mutex_lock(&ioapic->lock);
 	memcpy(ioapic, state, sizeof(struct kvm_ioapic_state));
+	update_handled_vectors(ioapic);
 	mutex_unlock(&ioapic->lock);
 	return 0;
 }
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index 419c43b..8a751b7 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -46,6 +46,7 @@
 	struct kvm *kvm;
 	void (*ack_notifier)(void *opaque, int irq);
 	struct mutex lock;
+	DECLARE_BITMAP(handled_vectors, 256);
 };
 
 #ifdef DEBUG
@@ -71,6 +72,7 @@
 int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2);
 void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
 int kvm_ioapic_init(struct kvm *kvm);
+void kvm_ioapic_destroy(struct kvm *kvm);
 int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
 void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
 int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
index 1514758..80fd3ad 100644
--- a/virt/kvm/iommu.c
+++ b/virt/kvm/iommu.c
@@ -32,10 +32,10 @@
 static void kvm_iommu_put_pages(struct kvm *kvm,
 				gfn_t base_gfn, unsigned long npages);
 
-int kvm_iommu_map_pages(struct kvm *kvm,
-			gfn_t base_gfn, unsigned long npages)
+int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
 {
-	gfn_t gfn = base_gfn;
+	gfn_t gfn = slot->base_gfn;
+	unsigned long npages = slot->npages;
 	pfn_t pfn;
 	int i, r = 0;
 	struct iommu_domain *domain = kvm->arch.iommu_domain;
@@ -54,7 +54,7 @@
 		if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn)))
 			continue;
 
-		pfn = gfn_to_pfn(kvm, gfn);
+		pfn = gfn_to_pfn_memslot(kvm, slot, gfn);
 		r = iommu_map_range(domain,
 				    gfn_to_gpa(gfn),
 				    pfn_to_hpa(pfn),
@@ -69,17 +69,19 @@
 	return 0;
 
 unmap_pages:
-	kvm_iommu_put_pages(kvm, base_gfn, i);
+	kvm_iommu_put_pages(kvm, slot->base_gfn, i);
 	return r;
 }
 
 static int kvm_iommu_map_memslots(struct kvm *kvm)
 {
 	int i, r = 0;
+	struct kvm_memslots *slots;
 
-	for (i = 0; i < kvm->nmemslots; i++) {
-		r = kvm_iommu_map_pages(kvm, kvm->memslots[i].base_gfn,
-					kvm->memslots[i].npages);
+	slots = rcu_dereference(kvm->memslots);
+
+	for (i = 0; i < slots->nmemslots; i++) {
+		r = kvm_iommu_map_pages(kvm, &slots->memslots[i]);
 		if (r)
 			break;
 	}
@@ -104,7 +106,8 @@
 
 	r = iommu_attach_device(domain, &pdev->dev);
 	if (r) {
-		printk(KERN_ERR "assign device %x:%x.%x failed",
+		printk(KERN_ERR "assign device %x:%x:%x.%x failed",
+			pci_domain_nr(pdev->bus),
 			pdev->bus->number,
 			PCI_SLOT(pdev->devfn),
 			PCI_FUNC(pdev->devfn));
@@ -125,7 +128,8 @@
 			goto out_unmap;
 	}
 
-	printk(KERN_DEBUG "assign device: host bdf = %x:%x:%x\n",
+	printk(KERN_DEBUG "assign device %x:%x:%x.%x\n",
+		assigned_dev->host_segnr,
 		assigned_dev->host_busnr,
 		PCI_SLOT(assigned_dev->host_devfn),
 		PCI_FUNC(assigned_dev->host_devfn));
@@ -152,7 +156,8 @@
 
 	iommu_detach_device(domain, &pdev->dev);
 
-	printk(KERN_DEBUG "deassign device: host bdf = %x:%x:%x\n",
+	printk(KERN_DEBUG "deassign device %x:%x:%x.%x\n",
+		assigned_dev->host_segnr,
 		assigned_dev->host_busnr,
 		PCI_SLOT(assigned_dev->host_devfn),
 		PCI_FUNC(assigned_dev->host_devfn));
@@ -210,10 +215,13 @@
 static int kvm_iommu_unmap_memslots(struct kvm *kvm)
 {
 	int i;
+	struct kvm_memslots *slots;
 
-	for (i = 0; i < kvm->nmemslots; i++) {
-		kvm_iommu_put_pages(kvm, kvm->memslots[i].base_gfn,
-				    kvm->memslots[i].npages);
+	slots = rcu_dereference(kvm->memslots);
+
+	for (i = 0; i < slots->nmemslots; i++) {
+		kvm_iommu_put_pages(kvm, slots->memslots[i].base_gfn,
+				    slots->memslots[i].npages);
 	}
 
 	return 0;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index a944be3..548f925 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -44,6 +44,8 @@
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
 #include <linux/compat.h>
+#include <linux/srcu.h>
+#include <linux/hugetlb.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -51,9 +53,7 @@
 #include <asm/pgtable.h>
 #include <asm-generic/bitops/le.h>
 
-#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
 #include "coalesced_mmio.h"
-#endif
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/kvm.h>
@@ -86,6 +86,8 @@
 static int hardware_enable_all(void);
 static void hardware_disable_all(void);
 
+static void kvm_io_bus_destroy(struct kvm_io_bus *bus);
+
 static bool kvm_rebooting;
 
 static bool largepages_enabled = true;
@@ -136,7 +138,7 @@
 
 	zalloc_cpumask_var(&cpus, GFP_ATOMIC);
 
-	spin_lock(&kvm->requests_lock);
+	raw_spin_lock(&kvm->requests_lock);
 	me = smp_processor_id();
 	kvm_for_each_vcpu(i, vcpu, kvm) {
 		if (test_and_set_bit(req, &vcpu->requests))
@@ -151,7 +153,7 @@
 		smp_call_function_many(cpus, ack_flush, NULL, 1);
 	else
 		called = false;
-	spin_unlock(&kvm->requests_lock);
+	raw_spin_unlock(&kvm->requests_lock);
 	free_cpumask_var(cpus);
 	return called;
 }
@@ -215,7 +217,7 @@
 					     unsigned long address)
 {
 	struct kvm *kvm = mmu_notifier_to_kvm(mn);
-	int need_tlb_flush;
+	int need_tlb_flush, idx;
 
 	/*
 	 * When ->invalidate_page runs, the linux pte has been zapped
@@ -235,10 +237,12 @@
 	 * pte after kvm_unmap_hva returned, without noticing the page
 	 * is going to be freed.
 	 */
+	idx = srcu_read_lock(&kvm->srcu);
 	spin_lock(&kvm->mmu_lock);
 	kvm->mmu_notifier_seq++;
 	need_tlb_flush = kvm_unmap_hva(kvm, address);
 	spin_unlock(&kvm->mmu_lock);
+	srcu_read_unlock(&kvm->srcu, idx);
 
 	/* we've to flush the tlb before the pages can be freed */
 	if (need_tlb_flush)
@@ -252,11 +256,14 @@
 					pte_t pte)
 {
 	struct kvm *kvm = mmu_notifier_to_kvm(mn);
+	int idx;
 
+	idx = srcu_read_lock(&kvm->srcu);
 	spin_lock(&kvm->mmu_lock);
 	kvm->mmu_notifier_seq++;
 	kvm_set_spte_hva(kvm, address, pte);
 	spin_unlock(&kvm->mmu_lock);
+	srcu_read_unlock(&kvm->srcu, idx);
 }
 
 static void kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
@@ -265,8 +272,9 @@
 						    unsigned long end)
 {
 	struct kvm *kvm = mmu_notifier_to_kvm(mn);
-	int need_tlb_flush = 0;
+	int need_tlb_flush = 0, idx;
 
+	idx = srcu_read_lock(&kvm->srcu);
 	spin_lock(&kvm->mmu_lock);
 	/*
 	 * The count increase must become visible at unlock time as no
@@ -277,6 +285,7 @@
 	for (; start < end; start += PAGE_SIZE)
 		need_tlb_flush |= kvm_unmap_hva(kvm, start);
 	spin_unlock(&kvm->mmu_lock);
+	srcu_read_unlock(&kvm->srcu, idx);
 
 	/* we've to flush the tlb before the pages can be freed */
 	if (need_tlb_flush)
@@ -314,11 +323,13 @@
 					      unsigned long address)
 {
 	struct kvm *kvm = mmu_notifier_to_kvm(mn);
-	int young;
+	int young, idx;
 
+	idx = srcu_read_lock(&kvm->srcu);
 	spin_lock(&kvm->mmu_lock);
 	young = kvm_age_hva(kvm, address);
 	spin_unlock(&kvm->mmu_lock);
+	srcu_read_unlock(&kvm->srcu, idx);
 
 	if (young)
 		kvm_flush_remote_tlbs(kvm);
@@ -341,15 +352,26 @@
 	.change_pte		= kvm_mmu_notifier_change_pte,
 	.release		= kvm_mmu_notifier_release,
 };
+
+static int kvm_init_mmu_notifier(struct kvm *kvm)
+{
+	kvm->mmu_notifier.ops = &kvm_mmu_notifier_ops;
+	return mmu_notifier_register(&kvm->mmu_notifier, current->mm);
+}
+
+#else  /* !(CONFIG_MMU_NOTIFIER && KVM_ARCH_WANT_MMU_NOTIFIER) */
+
+static int kvm_init_mmu_notifier(struct kvm *kvm)
+{
+	return 0;
+}
+
 #endif /* CONFIG_MMU_NOTIFIER && KVM_ARCH_WANT_MMU_NOTIFIER */
 
 static struct kvm *kvm_create_vm(void)
 {
-	int r = 0;
+	int r = 0, i;
 	struct kvm *kvm = kvm_arch_create_vm();
-#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
-	struct page *page;
-#endif
 
 	if (IS_ERR(kvm))
 		goto out;
@@ -363,39 +385,35 @@
 	INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list);
 #endif
 
-#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
-	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
-	if (!page) {
-		r = -ENOMEM;
+	r = -ENOMEM;
+	kvm->memslots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
+	if (!kvm->memslots)
 		goto out_err;
-	}
-	kvm->coalesced_mmio_ring =
-			(struct kvm_coalesced_mmio_ring *)page_address(page);
-#endif
-
-#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
-	{
-		kvm->mmu_notifier.ops = &kvm_mmu_notifier_ops;
-		r = mmu_notifier_register(&kvm->mmu_notifier, current->mm);
-		if (r) {
-#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
-			put_page(page);
-#endif
+	if (init_srcu_struct(&kvm->srcu))
+		goto out_err;
+	for (i = 0; i < KVM_NR_BUSES; i++) {
+		kvm->buses[i] = kzalloc(sizeof(struct kvm_io_bus),
+					GFP_KERNEL);
+		if (!kvm->buses[i]) {
+			cleanup_srcu_struct(&kvm->srcu);
 			goto out_err;
 		}
 	}
-#endif
+
+	r = kvm_init_mmu_notifier(kvm);
+	if (r) {
+		cleanup_srcu_struct(&kvm->srcu);
+		goto out_err;
+	}
 
 	kvm->mm = current->mm;
 	atomic_inc(&kvm->mm->mm_count);
 	spin_lock_init(&kvm->mmu_lock);
-	spin_lock_init(&kvm->requests_lock);
-	kvm_io_bus_init(&kvm->pio_bus);
+	raw_spin_lock_init(&kvm->requests_lock);
 	kvm_eventfd_init(kvm);
 	mutex_init(&kvm->lock);
 	mutex_init(&kvm->irq_lock);
-	kvm_io_bus_init(&kvm->mmio_bus);
-	init_rwsem(&kvm->slots_lock);
+	mutex_init(&kvm->slots_lock);
 	atomic_set(&kvm->users_count, 1);
 	spin_lock(&kvm_lock);
 	list_add(&kvm->vm_list, &vm_list);
@@ -406,12 +424,12 @@
 out:
 	return kvm;
 
-#if defined(KVM_COALESCED_MMIO_PAGE_OFFSET) || \
-    (defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER))
 out_err:
 	hardware_disable_all();
-#endif
 out_err_nodisable:
+	for (i = 0; i < KVM_NR_BUSES; i++)
+		kfree(kvm->buses[i]);
+	kfree(kvm->memslots);
 	kfree(kvm);
 	return ERR_PTR(r);
 }
@@ -446,13 +464,17 @@
 void kvm_free_physmem(struct kvm *kvm)
 {
 	int i;
+	struct kvm_memslots *slots = kvm->memslots;
 
-	for (i = 0; i < kvm->nmemslots; ++i)
-		kvm_free_physmem_slot(&kvm->memslots[i], NULL);
+	for (i = 0; i < slots->nmemslots; ++i)
+		kvm_free_physmem_slot(&slots->memslots[i], NULL);
+
+	kfree(kvm->memslots);
 }
 
 static void kvm_destroy_vm(struct kvm *kvm)
 {
+	int i;
 	struct mm_struct *mm = kvm->mm;
 
 	kvm_arch_sync_events(kvm);
@@ -460,12 +482,9 @@
 	list_del(&kvm->vm_list);
 	spin_unlock(&kvm_lock);
 	kvm_free_irq_routing(kvm);
-	kvm_io_bus_destroy(&kvm->pio_bus);
-	kvm_io_bus_destroy(&kvm->mmio_bus);
-#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
-	if (kvm->coalesced_mmio_ring != NULL)
-		free_page((unsigned long)kvm->coalesced_mmio_ring);
-#endif
+	for (i = 0; i < KVM_NR_BUSES; i++)
+		kvm_io_bus_destroy(kvm->buses[i]);
+	kvm_coalesced_mmio_free(kvm);
 #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
 	mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm);
 #else
@@ -512,12 +531,13 @@
 			    struct kvm_userspace_memory_region *mem,
 			    int user_alloc)
 {
-	int r;
+	int r, flush_shadow = 0;
 	gfn_t base_gfn;
 	unsigned long npages;
 	unsigned long i;
 	struct kvm_memory_slot *memslot;
 	struct kvm_memory_slot old, new;
+	struct kvm_memslots *slots, *old_memslots;
 
 	r = -EINVAL;
 	/* General sanity checks */
@@ -532,7 +552,7 @@
 	if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr)
 		goto out;
 
-	memslot = &kvm->memslots[mem->slot];
+	memslot = &kvm->memslots->memslots[mem->slot];
 	base_gfn = mem->guest_phys_addr >> PAGE_SHIFT;
 	npages = mem->memory_size >> PAGE_SHIFT;
 
@@ -553,7 +573,7 @@
 	/* Check for overlaps */
 	r = -EEXIST;
 	for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
-		struct kvm_memory_slot *s = &kvm->memslots[i];
+		struct kvm_memory_slot *s = &kvm->memslots->memslots[i];
 
 		if (s == memslot || !s->npages)
 			continue;
@@ -579,15 +599,7 @@
 		memset(new.rmap, 0, npages * sizeof(*new.rmap));
 
 		new.user_alloc = user_alloc;
-		/*
-		 * hva_to_rmmap() serialzies with the mmu_lock and to be
-		 * safe it has to ignore memslots with !user_alloc &&
-		 * !userspace_addr.
-		 */
-		if (user_alloc)
-			new.userspace_addr = mem->userspace_addr;
-		else
-			new.userspace_addr = 0;
+		new.userspace_addr = mem->userspace_addr;
 	}
 	if (!npages)
 		goto skip_lpage;
@@ -642,8 +654,9 @@
 		if (!new.dirty_bitmap)
 			goto out_free;
 		memset(new.dirty_bitmap, 0, dirty_bytes);
+		/* destroy any largepage mappings for dirty tracking */
 		if (old.npages)
-			kvm_arch_flush_shadow(kvm);
+			flush_shadow = 1;
 	}
 #else  /* not defined CONFIG_S390 */
 	new.user_alloc = user_alloc;
@@ -651,36 +664,72 @@
 		new.userspace_addr = mem->userspace_addr;
 #endif /* not defined CONFIG_S390 */
 
-	if (!npages)
+	if (!npages) {
+		r = -ENOMEM;
+		slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
+		if (!slots)
+			goto out_free;
+		memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots));
+		if (mem->slot >= slots->nmemslots)
+			slots->nmemslots = mem->slot + 1;
+		slots->memslots[mem->slot].flags |= KVM_MEMSLOT_INVALID;
+
+		old_memslots = kvm->memslots;
+		rcu_assign_pointer(kvm->memslots, slots);
+		synchronize_srcu_expedited(&kvm->srcu);
+		/* From this point no new shadow pages pointing to a deleted
+		 * memslot will be created.
+		 *
+		 * validation of sp->gfn happens in:
+		 * 	- gfn_to_hva (kvm_read_guest, gfn_to_pfn)
+		 * 	- kvm_is_visible_gfn (mmu_check_roots)
+		 */
 		kvm_arch_flush_shadow(kvm);
-
-	spin_lock(&kvm->mmu_lock);
-	if (mem->slot >= kvm->nmemslots)
-		kvm->nmemslots = mem->slot + 1;
-
-	*memslot = new;
-	spin_unlock(&kvm->mmu_lock);
-
-	r = kvm_arch_set_memory_region(kvm, mem, old, user_alloc);
-	if (r) {
-		spin_lock(&kvm->mmu_lock);
-		*memslot = old;
-		spin_unlock(&kvm->mmu_lock);
-		goto out_free;
+		kfree(old_memslots);
 	}
 
-	kvm_free_physmem_slot(&old, npages ? &new : NULL);
-	/* Slot deletion case: we have to update the current slot */
-	spin_lock(&kvm->mmu_lock);
-	if (!npages)
-		*memslot = old;
-	spin_unlock(&kvm->mmu_lock);
+	r = kvm_arch_prepare_memory_region(kvm, &new, old, mem, user_alloc);
+	if (r)
+		goto out_free;
+
 #ifdef CONFIG_DMAR
 	/* map the pages in iommu page table */
-	r = kvm_iommu_map_pages(kvm, base_gfn, npages);
-	if (r)
-		goto out;
+	if (npages) {
+		r = kvm_iommu_map_pages(kvm, &new);
+		if (r)
+			goto out_free;
+	}
 #endif
+
+	r = -ENOMEM;
+	slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
+	if (!slots)
+		goto out_free;
+	memcpy(slots, kvm->memslots, sizeof(struct kvm_memslots));
+	if (mem->slot >= slots->nmemslots)
+		slots->nmemslots = mem->slot + 1;
+
+	/* actual memory is freed via old in kvm_free_physmem_slot below */
+	if (!npages) {
+		new.rmap = NULL;
+		new.dirty_bitmap = NULL;
+		for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i)
+			new.lpage_info[i] = NULL;
+	}
+
+	slots->memslots[mem->slot] = new;
+	old_memslots = kvm->memslots;
+	rcu_assign_pointer(kvm->memslots, slots);
+	synchronize_srcu_expedited(&kvm->srcu);
+
+	kvm_arch_commit_memory_region(kvm, mem, old, user_alloc);
+
+	kvm_free_physmem_slot(&old, &new);
+	kfree(old_memslots);
+
+	if (flush_shadow)
+		kvm_arch_flush_shadow(kvm);
+
 	return 0;
 
 out_free:
@@ -697,9 +746,9 @@
 {
 	int r;
 
-	down_write(&kvm->slots_lock);
+	mutex_lock(&kvm->slots_lock);
 	r = __kvm_set_memory_region(kvm, mem, user_alloc);
-	up_write(&kvm->slots_lock);
+	mutex_unlock(&kvm->slots_lock);
 	return r;
 }
 EXPORT_SYMBOL_GPL(kvm_set_memory_region);
@@ -726,7 +775,7 @@
 	if (log->slot >= KVM_MEMORY_SLOTS)
 		goto out;
 
-	memslot = &kvm->memslots[log->slot];
+	memslot = &kvm->memslots->memslots[log->slot];
 	r = -ENOENT;
 	if (!memslot->dirty_bitmap)
 		goto out;
@@ -780,9 +829,10 @@
 struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn)
 {
 	int i;
+	struct kvm_memslots *slots = rcu_dereference(kvm->memslots);
 
-	for (i = 0; i < kvm->nmemslots; ++i) {
-		struct kvm_memory_slot *memslot = &kvm->memslots[i];
+	for (i = 0; i < slots->nmemslots; ++i) {
+		struct kvm_memory_slot *memslot = &slots->memslots[i];
 
 		if (gfn >= memslot->base_gfn
 		    && gfn < memslot->base_gfn + memslot->npages)
@@ -801,10 +851,14 @@
 int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn)
 {
 	int i;
+	struct kvm_memslots *slots = rcu_dereference(kvm->memslots);
 
-	gfn = unalias_gfn(kvm, gfn);
+	gfn = unalias_gfn_instantiation(kvm, gfn);
 	for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
-		struct kvm_memory_slot *memslot = &kvm->memslots[i];
+		struct kvm_memory_slot *memslot = &slots->memslots[i];
+
+		if (memslot->flags & KVM_MEMSLOT_INVALID)
+			continue;
 
 		if (gfn >= memslot->base_gfn
 		    && gfn < memslot->base_gfn + memslot->npages)
@@ -814,33 +868,68 @@
 }
 EXPORT_SYMBOL_GPL(kvm_is_visible_gfn);
 
+unsigned long kvm_host_page_size(struct kvm *kvm, gfn_t gfn)
+{
+	struct vm_area_struct *vma;
+	unsigned long addr, size;
+
+	size = PAGE_SIZE;
+
+	addr = gfn_to_hva(kvm, gfn);
+	if (kvm_is_error_hva(addr))
+		return PAGE_SIZE;
+
+	down_read(&current->mm->mmap_sem);
+	vma = find_vma(current->mm, addr);
+	if (!vma)
+		goto out;
+
+	size = vma_kernel_pagesize(vma);
+
+out:
+	up_read(&current->mm->mmap_sem);
+
+	return size;
+}
+
+int memslot_id(struct kvm *kvm, gfn_t gfn)
+{
+	int i;
+	struct kvm_memslots *slots = rcu_dereference(kvm->memslots);
+	struct kvm_memory_slot *memslot = NULL;
+
+	gfn = unalias_gfn(kvm, gfn);
+	for (i = 0; i < slots->nmemslots; ++i) {
+		memslot = &slots->memslots[i];
+
+		if (gfn >= memslot->base_gfn
+		    && gfn < memslot->base_gfn + memslot->npages)
+			break;
+	}
+
+	return memslot - slots->memslots;
+}
+
 unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
 {
 	struct kvm_memory_slot *slot;
 
-	gfn = unalias_gfn(kvm, gfn);
+	gfn = unalias_gfn_instantiation(kvm, gfn);
 	slot = gfn_to_memslot_unaliased(kvm, gfn);
-	if (!slot)
+	if (!slot || slot->flags & KVM_MEMSLOT_INVALID)
 		return bad_hva();
 	return (slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE);
 }
 EXPORT_SYMBOL_GPL(gfn_to_hva);
 
-pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn)
+static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr)
 {
 	struct page *page[1];
-	unsigned long addr;
 	int npages;
 	pfn_t pfn;
 
 	might_sleep();
 
-	addr = gfn_to_hva(kvm, gfn);
-	if (kvm_is_error_hva(addr)) {
-		get_page(bad_page);
-		return page_to_pfn(bad_page);
-	}
-
 	npages = get_user_pages_fast(addr, 1, 1, page);
 
 	if (unlikely(npages != 1)) {
@@ -865,8 +954,32 @@
 	return pfn;
 }
 
+pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn)
+{
+	unsigned long addr;
+
+	addr = gfn_to_hva(kvm, gfn);
+	if (kvm_is_error_hva(addr)) {
+		get_page(bad_page);
+		return page_to_pfn(bad_page);
+	}
+
+	return hva_to_pfn(kvm, addr);
+}
 EXPORT_SYMBOL_GPL(gfn_to_pfn);
 
+static unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn)
+{
+	return (slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE);
+}
+
+pfn_t gfn_to_pfn_memslot(struct kvm *kvm,
+			 struct kvm_memory_slot *slot, gfn_t gfn)
+{
+	unsigned long addr = gfn_to_hva_memslot(slot, gfn);
+	return hva_to_pfn(kvm, addr);
+}
+
 struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
 {
 	pfn_t pfn;
@@ -1854,12 +1967,7 @@
 	.priority = 0,
 };
 
-void kvm_io_bus_init(struct kvm_io_bus *bus)
-{
-	memset(bus, 0, sizeof(*bus));
-}
-
-void kvm_io_bus_destroy(struct kvm_io_bus *bus)
+static void kvm_io_bus_destroy(struct kvm_io_bus *bus)
 {
 	int i;
 
@@ -1868,13 +1976,15 @@
 
 		kvm_iodevice_destructor(pos);
 	}
+	kfree(bus);
 }
 
 /* kvm_io_bus_write - called under kvm->slots_lock */
-int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr,
+int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 		     int len, const void *val)
 {
 	int i;
+	struct kvm_io_bus *bus = rcu_dereference(kvm->buses[bus_idx]);
 	for (i = 0; i < bus->dev_count; i++)
 		if (!kvm_iodevice_write(bus->devs[i], addr, len, val))
 			return 0;
@@ -1882,59 +1992,71 @@
 }
 
 /* kvm_io_bus_read - called under kvm->slots_lock */
-int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val)
+int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+		    int len, void *val)
 {
 	int i;
+	struct kvm_io_bus *bus = rcu_dereference(kvm->buses[bus_idx]);
+
 	for (i = 0; i < bus->dev_count; i++)
 		if (!kvm_iodevice_read(bus->devs[i], addr, len, val))
 			return 0;
 	return -EOPNOTSUPP;
 }
 
-int kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus,
-			     struct kvm_io_device *dev)
+/* Caller must hold slots_lock. */
+int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx,
+			    struct kvm_io_device *dev)
 {
-	int ret;
+	struct kvm_io_bus *new_bus, *bus;
 
-	down_write(&kvm->slots_lock);
-	ret = __kvm_io_bus_register_dev(bus, dev);
-	up_write(&kvm->slots_lock);
-
-	return ret;
-}
-
-/* An unlocked version. Caller must have write lock on slots_lock. */
-int __kvm_io_bus_register_dev(struct kvm_io_bus *bus,
-			      struct kvm_io_device *dev)
-{
+	bus = kvm->buses[bus_idx];
 	if (bus->dev_count > NR_IOBUS_DEVS-1)
 		return -ENOSPC;
 
-	bus->devs[bus->dev_count++] = dev;
+	new_bus = kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL);
+	if (!new_bus)
+		return -ENOMEM;
+	memcpy(new_bus, bus, sizeof(struct kvm_io_bus));
+	new_bus->devs[new_bus->dev_count++] = dev;
+	rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
+	synchronize_srcu_expedited(&kvm->srcu);
+	kfree(bus);
 
 	return 0;
 }
 
-void kvm_io_bus_unregister_dev(struct kvm *kvm,
-			       struct kvm_io_bus *bus,
-			       struct kvm_io_device *dev)
+/* Caller must hold slots_lock. */
+int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
+			      struct kvm_io_device *dev)
 {
-	down_write(&kvm->slots_lock);
-	__kvm_io_bus_unregister_dev(bus, dev);
-	up_write(&kvm->slots_lock);
-}
+	int i, r;
+	struct kvm_io_bus *new_bus, *bus;
 
-/* An unlocked version. Caller must have write lock on slots_lock. */
-void __kvm_io_bus_unregister_dev(struct kvm_io_bus *bus,
-				 struct kvm_io_device *dev)
-{
-	int i;
+	new_bus = kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL);
+	if (!new_bus)
+		return -ENOMEM;
 
-	for (i = 0; i < bus->dev_count; i++)
-		if (bus->devs[i] == dev) {
-			bus->devs[i] = bus->devs[--bus->dev_count];
+	bus = kvm->buses[bus_idx];
+	memcpy(new_bus, bus, sizeof(struct kvm_io_bus));
+
+	r = -ENOENT;
+	for (i = 0; i < new_bus->dev_count; i++)
+		if (new_bus->devs[i] == dev) {
+			r = 0;
+			new_bus->devs[i] = new_bus->devs[--new_bus->dev_count];
 			break;
 		}
+
+	if (r) {
+		kfree(new_bus);
+		return r;
+	}
+
+	rcu_assign_pointer(kvm->buses[bus_idx], new_bus);
+	synchronize_srcu_expedited(&kvm->srcu);
+	kfree(bus);
+	return r;
 }
 
 static struct notifier_block kvm_cpu_notifier = {